From cdeb700f70fd4da40ede8130c2ef331086844df1 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 9 Jul 2014 14:01:06 +0200 Subject: [PATCH] Added pad placement tool for module editor (GAL). --- pcbnew/tools/common_actions.cpp | 7 +- pcbnew/tools/common_actions.h | 3 + pcbnew/tools/drawing_tool.cpp | 154 ++++++++++++++++++++++++++++++++ pcbnew/tools/drawing_tool.h | 12 +++ 4 files changed, 175 insertions(+), 1 deletion(-) diff --git a/pcbnew/tools/common_actions.cpp b/pcbnew/tools/common_actions.cpp index 57edb54dc6..45305cc83e 100644 --- a/pcbnew/tools/common_actions.cpp +++ b/pcbnew/tools/common_actions.cpp @@ -97,6 +97,9 @@ TOOL_ACTION COMMON_ACTIONS::placeModule( "pcbnew.InteractiveDrawing.placeModule" AS_GLOBAL, 'O', "Add modules", "Add modules", AF_ACTIVATE ); +TOOL_ACTION COMMON_ACTIONS::placePad( "pcbnew.InteractiveDrawing.placePad", + AS_GLOBAL, 0, + "Add pads", "Add pads", AF_ACTIVATE ); // View Controls TOOL_ACTION COMMON_ACTIONS::zoomIn( "pcbnew.Control.zoomIn", @@ -307,6 +310,9 @@ boost::optional COMMON_ACTIONS::TranslateLegacyId( int aId ) case ID_PCB_MIRE_BUTT: return COMMON_ACTIONS::placeTarget.MakeEvent(); + case ID_MODEDIT_PAD_TOOL: + return COMMON_ACTIONS::placePad.MakeEvent(); + case ID_PCB_PLACE_GRID_COORD_BUTT: case ID_MODEDIT_PLACE_GRID_COORD: return COMMON_ACTIONS::gridSetOrigin.MakeEvent(); @@ -329,7 +335,6 @@ boost::optional COMMON_ACTIONS::TranslateLegacyId( int aId ) case ID_TB_OPTIONS_SHOW_EXTRA_VERTICAL_TOOLBAR_MICROWAVE: case ID_MENU_PCB_SHOW_HIDE_MUWAVE_TOOLBAR: case ID_MICROWAVE_V_TOOLBAR: - case ID_MODEDIT_PAD_TOOL: case ID_MODEDIT_DELETE_TOOL: case ID_MODEDIT_ANCHOR_TOOL: return COMMON_ACTIONS::toBeDone.MakeEvent(); diff --git a/pcbnew/tools/common_actions.h b/pcbnew/tools/common_actions.h index 0cd45e56c2..9c812414df 100644 --- a/pcbnew/tools/common_actions.h +++ b/pcbnew/tools/common_actions.h @@ -90,6 +90,9 @@ public: /// Activation of the drawing tool (placing a MODULE) static TOOL_ACTION placeModule; + /// Activation of the drawing tool (placing a PAD) + static TOOL_ACTION placePad; + // Push and Shove Router Tool /// Activation of the Push and Shove router static TOOL_ACTION routerActivate; diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp index e46ce6db27..fff955bfca 100644 --- a/pcbnew/tools/drawing_tool.cpp +++ b/pcbnew/tools/drawing_tool.cpp @@ -23,6 +23,8 @@ */ #include +#include + #include "drawing_tool.h" #include "common_actions.h" @@ -594,6 +596,110 @@ int DRAWING_TOOL::PlaceModule( TOOL_EVENT& aEvent ) } +int DRAWING_TOOL::PlacePad( TOOL_EVENT& aEvent ) +{ + assert( m_editModules ); + + m_frame->SetToolID( ID_MODEDIT_PAD_TOOL, wxCURSOR_PENCIL, _( "Add pads" ) ); + + MODULE* module = m_board->m_Modules; + assert( module ); + + D_PAD* pad = new D_PAD( module ); + m_frame->Import_Pad_Settings( pad, false ); // use the global settings for pad + + VECTOR2I cursorPos = m_controls->GetCursorPosition(); + pad->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); + + // Add a VIEW_GROUP that serves as a preview for the new item + KIGFX::VIEW_GROUP preview( m_view ); + preview.Add( pad ); + m_view->Add( &preview ); + + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear ); + m_controls->ShowCursor( true ); + m_controls->SetSnapping( true ); + + Activate(); + + // Main loop: keep receiving events + while( OPT_TOOL_EVENT evt = Wait() ) + { + cursorPos = m_controls->GetCursorPosition(); + + if( evt->IsMotion() ) + { + pad->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); + preview.ViewUpdate(); + } + + else if( evt->Category() == TC_COMMAND ) + { + if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) + { + pad->Rotate( pad->GetPosition(), m_frame->GetRotationAngle() ); + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) + { + pad->Flip( pad->GetPosition() ); + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + else if( evt->IsCancel() || evt->IsActivate() ) + { + preview.Clear(); + delete pad; + break; + } + } + + else if( evt->IsClick( BUT_LEFT ) ) + { + m_frame->OnModify(); + m_frame->SaveCopyInUndoList( module, UR_MODEDIT ); + + m_board->m_Status_Pcb = 0; // I have no clue why, but it is done in the legacy view + module->SetLastEditTime(); + module->Pads().PushBack( pad ); + + pad->SetNetCode( NETINFO_LIST::UNCONNECTED ); + + // Set the relative pad position + // ( pad position for module orient, 0, and relative to the module position) + pad->SetLocalCoord(); + + /* NPTH pads take empty pad number (since they can't be connected), + * other pads get incremented from the last one edited */ + wxString padName; + + if( pad->GetAttribute() != PAD_HOLE_NOT_PLATED ) + padName = getNextPadName(); + + pad->SetPadName( padName ); + + // Handle the view aspect + preview.Remove( pad ); + m_view->Add( pad ); + + // Start placing next pad + pad = new D_PAD( module ); + m_frame->Import_Pad_Settings( pad, false ); + preview.Add( pad ); + } + } + + m_controls->ShowCursor( false ); + m_controls->SetSnapping( false ); + m_controls->SetAutoPan( false ); + m_view->Remove( &preview ); + + setTransitions(); + m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); + + return 0; +} + + bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT* aGraphic ) { // Only two shapes are currently supported @@ -1369,6 +1475,53 @@ void DRAWING_TOOL::make45DegLine( DRAWSEGMENT* aSegment, DRAWSEGMENT* aHelper ) } +bool isNotDigit( char aChar ) +{ + return ( aChar < '0' || aChar > '9' ); +} + + +wxString DRAWING_TOOL::getNextPadName() const +{ + std::set usedNumbers; + + // Find the first, not used pad number + for( MODULE* module = m_board->m_Modules; module; module = module->Next() ) + { + for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) + { + wxString padName = pad->GetPadName(); + int padNumber = 0; + int base = 1; + + // Trim and extract the trailing numeric part + while( padName.Len() && padName.Last() >= '0' && padName.Last() <= '9' ) + { + padNumber += ( padName.Last() - '0' ) * base; + padName.RemoveLast(); + base *= 10; + } + + usedNumbers.insert( padNumber ); + } + } + + int candidate = *usedNumbers.begin(); + + // Look for a gap in pad numbering + for( std::set::iterator it = usedNumbers.begin(), + itEnd = usedNumbers.end(); it != itEnd; ++it ) + { + if( *it - candidate > 1 ) + break; + + candidate = *it; + } + + return wxString::Format( wxT( "%i" ), ++candidate ); +} + + void DRAWING_TOOL::setTransitions() { Go( &DRAWING_TOOL::DrawLine, COMMON_ACTIONS::drawLine.MakeEvent() ); @@ -1380,4 +1533,5 @@ void DRAWING_TOOL::setTransitions() Go( &DRAWING_TOOL::PlaceText, COMMON_ACTIONS::placeText.MakeEvent() ); Go( &DRAWING_TOOL::PlaceTarget, COMMON_ACTIONS::placeTarget.MakeEvent() ); Go( &DRAWING_TOOL::PlaceModule, COMMON_ACTIONS::placeModule.MakeEvent() ); + Go( &DRAWING_TOOL::PlacePad, COMMON_ACTIONS::placePad.MakeEvent() ); } diff --git a/pcbnew/tools/drawing_tool.h b/pcbnew/tools/drawing_tool.h index 32c15a8401..29b87560ea 100644 --- a/pcbnew/tools/drawing_tool.h +++ b/pcbnew/tools/drawing_tool.h @@ -120,6 +120,12 @@ public: */ int PlaceModule( TOOL_EVENT& aEvent ); + /** + * Function PlacePad() + * Places a pad in the module editor. + */ + int PlacePad( TOOL_EVENT& aEvent ); + /** * Function EditModules() * Toggles edit module mode. When enabled, one may select parts of modules individually @@ -174,6 +180,12 @@ private: */ void make45DegLine( DRAWSEGMENT* aSegment, DRAWSEGMENT* aHelper ) const; + /** + * Function getNextPadName() + * Compute the 'next' pad number for autoincrement. + * */ + wxString getNextPadName() const; + ///> Sets up handlers for various events. void setTransitions();