/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2017 Jon Evans * Copyright (C) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include #include #include #include #include #include #include #include "gerbview_inspection_tool.h" #include "gerbview_actions.h" #include #include #include #include #include #include #include #include #include #include #include #include GERBVIEW_INSPECTION_TOOL::GERBVIEW_INSPECTION_TOOL() : TOOL_INTERACTIVE( "gerbview.Inspection" ), m_frame( nullptr ) { } GERBVIEW_INSPECTION_TOOL::~GERBVIEW_INSPECTION_TOOL() { } bool GERBVIEW_INSPECTION_TOOL::Init() { return true; } void GERBVIEW_INSPECTION_TOOL::Reset( RESET_REASON aReason ) { m_frame = getEditFrame(); } int GERBVIEW_INSPECTION_TOOL::ShowDCodes( const TOOL_EVENT& aEvent ) { int ii, jj; wxString Line; wxArrayString list; int curr_layer = m_frame->GetActiveLayer(); double scale = 1.0; wxString units; switch( m_frame->GetUserUnits() ) { case EDA_UNITS::MILLIMETRES: scale = IU_PER_MM; units = wxT( "mm" ); break; case EDA_UNITS::INCHES: scale = IU_PER_MILS * 1000; units = wxT( "in" ); break; case EDA_UNITS::MILS: scale = IU_PER_MILS; units = wxT( "mil" ); break; default: wxASSERT_MSG( false, wxT( "Invalid units" ) ); } for( unsigned int layer = 0; layer < m_frame->ImagesMaxCount(); ++layer ) { GERBER_FILE_IMAGE* gerber = m_frame->GetGbrImage( layer ); if( !gerber ) continue; if( gerber->GetDcodesCount() == 0 ) continue; if( curr_layer == static_cast( layer ) ) Line.Printf( wxT( "*** Active layer (%2.2d) ***" ), layer + 1 ); else Line.Printf( wxT( "*** layer %2.2d ***" ), layer + 1 ); list.Add( Line ); for( ii = 0, jj = 1; ii < TOOLS_MAX_COUNT; ii++ ) { D_CODE* pt_D_code = gerber->GetDCODE( ii + FIRST_DCODE ); if( pt_D_code == nullptr ) continue; if( !pt_D_code->m_InUse && !pt_D_code->m_Defined ) continue; Line.Printf( wxT( "tool %2.2d: D%2.2d V %.4f %s H %.4f %s %s attribute '%s'" ), jj, pt_D_code->m_Num_Dcode, pt_D_code->m_Size.y / scale, units, pt_D_code->m_Size.x / scale, units, D_CODE::ShowApertureType( pt_D_code->m_Shape ), pt_D_code->m_AperFunction.IsEmpty()? wxT( "none" ) : pt_D_code->m_AperFunction ); if( !pt_D_code->m_Defined ) Line += wxT( " (not defined)" ); if( pt_D_code->m_InUse ) Line += wxT( " (in use)" ); list.Add( Line ); jj++; } } wxSingleChoiceDialog dlg( m_frame, wxEmptyString, _( "D Codes" ), list, (void**) nullptr, wxCHOICEDLG_STYLE & ~wxCANCEL ); dlg.ShowModal(); return 0; } int GERBVIEW_INSPECTION_TOOL::ShowSource( const TOOL_EVENT& aEvent ) { int layer = m_frame->GetActiveLayer(); GERBER_FILE_IMAGE* gerber_layer = m_frame->GetGbrImage( layer ); if( gerber_layer ) { wxString editorname = Pgm().GetTextEditor(); if( !editorname.IsEmpty() ) { wxFileName fn( gerber_layer->m_FileName ); // Call the editor only if the Gerber/drill source file is available. // This is not always the case, because it can be a temporary file // if it comes from a zip archive. if( !fn.FileExists() ) { wxString msg; msg.Printf( _( "Source file '%s' not found." ), fn.GetFullPath() ); wxMessageBox( msg ); } else { ExecuteFile( editorname, fn.GetFullPath() ); } } else { wxMessageBox( _( "No text editor selected in KiCad. Please choose one." ) ); } } else { wxString msg; msg.Printf( _( "No file loaded on the active layer %d." ), layer + 1 ); wxMessageBox( msg ); } return 0; } using KIGFX::PREVIEW::TWO_POINT_GEOMETRY_MANAGER; int GERBVIEW_INSPECTION_TOOL::MeasureTool( const TOOL_EVENT& aEvent ) { KIGFX::VIEW_CONTROLS& controls = *getViewControls(); bool originSet = false; TWO_POINT_GEOMETRY_MANAGER twoPtMgr; EDA_UNITS units = m_frame->GetUserUnits(); KIGFX::PREVIEW::RULER_ITEM ruler( twoPtMgr, units, false, false ); std::string tool = *aEvent.GetCommandStr(); m_frame->PushTool( tool ); auto setCursor = [&]() { m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::MEASURE ); }; auto cleanup = [&] () { getView()->SetVisible( &ruler, false ); controls.SetAutoPan( false ); controls.CaptureCursor( false ); originSet = false; }; Activate(); // Must be done after Activate() so that it gets set into the correct context controls.ShowCursor( true ); // Set initial cursor setCursor(); getView()->Add( &ruler ); getView()->SetVisible( &ruler, false ); while( TOOL_EVENT* evt = Wait() ) { setCursor(); const VECTOR2I cursorPos = controls.GetCursorPosition(); if( evt->IsCancelInteractive() ) { if( originSet ) { cleanup(); } else { m_frame->PopTool( tool ); break; } } else if( evt->IsActivate() ) { if( originSet ) cleanup(); if( evt->IsMoveTool() ) { // leave ourselves on the stack so we come back after the move break; } else { m_frame->PopTool( tool ); break; } } else if( !originSet && ( evt->IsDrag( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) ) { // click or drag starts twoPtMgr.SetOrigin( cursorPos ); twoPtMgr.SetEnd( cursorPos ); controls.CaptureCursor( true ); controls.SetAutoPan( true ); originSet = true; } else if( originSet && ( evt->IsClick( BUT_LEFT ) || evt->IsMouseUp( BUT_LEFT ) ) ) { // second click or mouse up after drag ends originSet = false; controls.SetAutoPan( false ); controls.CaptureCursor( false ); } else if( originSet && ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) ) { // move or drag when origin set updates rules twoPtMgr.SetAngleSnap( evt->Modifier( MD_SHIFT ) ); twoPtMgr.SetEnd( cursorPos ); getView()->SetVisible( &ruler, true ); getView()->Update( &ruler, KIGFX::GEOMETRY ); } else if( evt->IsAction( &ACTIONS::updateUnits ) ) { if( m_frame->GetUserUnits() != units ) { units = m_frame->GetUserUnits(); ruler.SwitchUnits( units ); getView()->Update( &ruler, KIGFX::GEOMETRY ); } evt->SetPassEvent(); } else if( evt->IsClick( BUT_RIGHT ) ) { m_menu.ShowContextMenu( m_frame->GetCurrentSelection() ); } else { evt->SetPassEvent(); } } getView()->SetVisible( &ruler, false ); getView()->Remove( &ruler ); m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW ); return 0; } void GERBVIEW_INSPECTION_TOOL::setTransitions() { Go( &GERBVIEW_INSPECTION_TOOL::ShowSource, GERBVIEW_ACTIONS::showSource.MakeEvent() ); Go( &GERBVIEW_INSPECTION_TOOL::ShowDCodes, GERBVIEW_ACTIONS::showDCodes.MakeEvent() ); Go( &GERBVIEW_INSPECTION_TOOL::MeasureTool, ACTIONS::measureTool.MakeEvent() ); }