From 3b7b0603b60b50716b6f9f75b14a9bba3c5d9915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20W=C5=82ostowski?= Date: Sat, 22 Apr 2017 17:46:31 +0200 Subject: [PATCH] pcbnew: via placement tool, initial version --- pcbnew/class_board.h | 2 +- pcbnew/class_track.cpp | 13 +-- pcbnew/pcbnew_id.h | 1 + pcbnew/tool_pcb.cpp | 5 +- pcbnew/tools/drawing_tool.cpp | 137 ++++++++++++++++++++++++++- pcbnew/tools/drawing_tool.h | 2 + pcbnew/tools/microwave_tool.cpp | 30 ++++-- pcbnew/tools/module_editor_tools.cpp | 87 +++-------------- pcbnew/tools/pcb_actions.cpp | 3 + pcbnew/tools/pcb_actions.h | 3 + pcbnew/tools/pcb_tool.cpp | 84 ++++++++++------ pcbnew/tools/pcb_tool.h | 34 +++++-- 12 files changed, 272 insertions(+), 129 deletions(-) diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h index dcd8bdf340..914313f43d 100644 --- a/pcbnew/class_board.h +++ b/pcbnew/class_board.h @@ -256,7 +256,7 @@ public: DLIST_ITERATOR_WRAPPER Tracks() { return DLIST_ITERATOR_WRAPPER(m_Track); } DLIST_ITERATOR_WRAPPER Modules() { return DLIST_ITERATOR_WRAPPER(m_Modules); } DLIST_ITERATOR_WRAPPER Drawings() { return DLIST_ITERATOR_WRAPPER(m_Drawings); } - + ZONE_CONTAINERS& Zones() { return m_ZoneDescriptorList; } // will be deprecated as soon as append board functionality is fixed diff --git a/pcbnew/class_track.cpp b/pcbnew/class_track.cpp index a31d4bf919..790af8cf30 100644 --- a/pcbnew/class_track.cpp +++ b/pcbnew/class_track.cpp @@ -990,24 +990,25 @@ void VIA::Draw( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode, const w void VIA::ViewGetLayers( int aLayers[], int& aCount ) const { aLayers[0] = LAYER_VIAS_HOLES; - aCount = 2; + aLayers[1] = GetNetnameLayer( m_Layer ); + aCount = 3; // Just show it on common via & via holes layers switch( GetViaType() ) { case VIA_THROUGH: - aLayers[1] = LAYER_VIA_THROUGH; + aLayers[2] = LAYER_VIA_THROUGH; break; case VIA_BLIND_BURIED: - aLayers[1] = LAYER_VIA_BBLIND; - aLayers[2] = m_Layer; - aLayers[3] = m_BottomLayer; + aLayers[2] = LAYER_VIA_BBLIND; + aLayers[3] = m_Layer; + aLayers[4] = m_BottomLayer; aCount += 2; break; case VIA_MICROVIA: - aLayers[1] = LAYER_VIA_MICROVIA; + aLayers[2] = LAYER_VIA_MICROVIA; break; default: diff --git a/pcbnew/pcbnew_id.h b/pcbnew/pcbnew_id.h index e092e9c8f2..bd0a5ec947 100644 --- a/pcbnew/pcbnew_id.h +++ b/pcbnew/pcbnew_id.h @@ -30,6 +30,7 @@ enum pcbnew_ids ID_PCB_MODULE_BUTT, ID_TRACK_BUTT, ID_PCB_ZONES_BUTT, + ID_PCB_DRAW_VIA_BUTT, ID_PCB_KEEPOUT_AREA_BUTT, ID_PCB_ADD_LINE_BUTT, ID_PCB_CIRCLE_BUTT, diff --git a/pcbnew/tool_pcb.cpp b/pcbnew/tool_pcb.cpp index 8e1ccf0352..6f7fa766c3 100644 --- a/pcbnew/tool_pcb.cpp +++ b/pcbnew/tool_pcb.cpp @@ -440,7 +440,10 @@ void PCB_EDIT_FRAME::ReCreateVToolbar() _( "Add footprints" ), wxITEM_CHECK ); m_drawToolBar->AddTool( ID_TRACK_BUTT, wxEmptyString, KiBitmap( add_tracks_xpm ), - _( "Add tracks and vias" ), wxITEM_CHECK ); + _( "Route tracks" ), wxITEM_CHECK ); + + m_drawToolBar->AddTool( ID_PCB_DRAW_VIA_BUTT, wxEmptyString, KiBitmap( add_via_xpm ), + _( "Add vias" ), wxITEM_CHECK ); m_drawToolBar->AddTool( ID_PCB_ZONES_BUTT, wxEmptyString, KiBitmap( add_zone_xpm ), _( "Add filled zones" ), wxITEM_CHECK ); diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp index 2813df0ebc..53adebf93e 100644 --- a/pcbnew/tools/drawing_tool.cpp +++ b/pcbnew/tools/drawing_tool.cpp @@ -88,7 +88,11 @@ TOOL_ACTION PCB_ACTIONS::drawZone( "pcbnew.InteractiveDrawing.zone", AS_GLOBAL, 0, _( "Add Filled Zone" ), _( "Add a filled zone" ), NULL, AF_ACTIVATE ); -TOOL_ACTION PCB_ACTIONS::drawZoneKeepout( "pcbnew.InteractiveDrawing.keepout", +TOOL_ACTION PCB_ACTIONS::drawVia( "pcbnew.InteractiveDrawing.via", + AS_GLOBAL, 0, + _( "Add Vias" ), _( "Add free-stanging vias" ), NULL, AF_ACTIVATE ); + +TOOL_ACTION PCB_ACTIONS::drawKeepout( "pcbnew.InteractiveDrawing.keepout", AS_GLOBAL, 0, _( "Add Keepout Area" ), _( "Add a keepout area" ), NULL, AF_ACTIVATE ); @@ -1392,6 +1396,136 @@ void DRAWING_TOOL::make45DegLine( DRAWSEGMENT* aSegment, DRAWSEGMENT* aHelper ) } } +int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent ) +{ + struct VIA_PLACER : public INTERACTIVE_PLACER_BASE + { + int findStitchedZoneNet( VIA *aVia ) + { + const auto pos = aVia->GetPosition(); + const auto lset = aVia->GetLayerSet(); + + for ( auto tv : m_board->Tracks() ) // fixme: move to BOARD class? + if( tv->HitTest(pos) && (tv->GetLayerSet() & + lset ).any() ) + return -1; + + for ( auto mod : m_board->Modules() ) + for ( auto pad : mod->PadsIter() ) + if( pad->HitTest(pos) && (pad->GetLayerSet() & + lset ).any() ) + return -1; + + std::set foundZones; + + for( auto zone : m_board->Zones() ) + { + if ( zone->HitTestFilledArea ( pos ) ) + { + foundZones.insert ( zone ); + } + } + + for( auto z : foundZones ) + { + if ( m_frame->GetActiveLayer() == z->GetLayer() ) + return z->GetNetCode(); + } + + + return -1; + } + + bool PlaceItem( BOARD_ITEM *aItem ) override + { + auto via = static_cast(aItem); + int newNet = findStitchedZoneNet(via); + + if(newNet > 0 ) + via->SetNetCode( newNet ); + + return false; + } + + + std::unique_ptr CreateItem() override + { + auto& ds = m_board->GetDesignSettings(); + VIA* via = new VIA ( m_board ); + + via->SetNetCode( 0 ); + via->SetViaType( ds.m_CurrentViaType ); + + // for microvias, the size and hole will be changed later. + via->SetWidth( ds.GetCurrentViaSize()); + via->SetDrill( ds.GetCurrentViaDrill() ); + + // Usual via is from copper to component. + // layer pair is B_Cu and F_Cu. + via->SetLayerPair( B_Cu, F_Cu ); + + LAYER_ID first_layer = m_frame->GetActiveLayer(); + LAYER_ID last_layer; + + // prepare switch to new active layer: + if( first_layer != m_frame->GetScreen()->m_Route_Layer_TOP ) + last_layer = m_frame->GetScreen()->m_Route_Layer_TOP; + else + last_layer = m_frame->GetScreen()->m_Route_Layer_BOTTOM; + + // Adjust the actual via layer pair + switch( via->GetViaType() ) + { + case VIA_BLIND_BURIED: + via->SetLayerPair( first_layer, last_layer ); + break; + + case VIA_MICROVIA: // from external to the near neighbor inner layer + { + LAYER_ID last_inner_layer = ToLAYER_ID( ( m_board->GetCopperLayerCount() - 2 ) ); + + if( first_layer == B_Cu ) + last_layer = last_inner_layer; + else if( first_layer == F_Cu ) + last_layer = In1_Cu; + else if( first_layer == last_inner_layer ) + last_layer = B_Cu; + else if( first_layer == In1_Cu ) + last_layer = F_Cu; + // else error: will be removed later + via->SetLayerPair( first_layer, last_layer ); + + // Update diameter and hole size, which where set previously + // for normal vias + NETINFO_ITEM* net = via->GetNet(); + if( net ) + { + via->SetWidth( net->GetMicroViaSize() ); + via->SetDrill( net->GetMicroViaDrillSize() ); + } + } + break; + + default: + break; + } + + + + return std::unique_ptr(via); + } + }; + + VIA_PLACER placer; + + frame()->SetToolID( ID_PCB_DRAW_VIA_BUTT, wxCURSOR_PENCIL, _( "Add vias" ) ); + + doInteractiveItemPlacement( &placer, _( "Place via" ), IPO_REPEAT | IPO_SINGLE_CLICK | IPO_ROTATE | IPO_FLIP | IPO_PROPERTIES ); + + frame()->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); + + return 0; +} void DRAWING_TOOL::SetTransitions() { @@ -1403,6 +1537,7 @@ void DRAWING_TOOL::SetTransitions() Go( &DRAWING_TOOL::DrawZoneKeepout, PCB_ACTIONS::drawZoneKeepout.MakeEvent() ); Go( &DRAWING_TOOL::DrawZoneCutout, PCB_ACTIONS::drawZoneCutout.MakeEvent() ); Go( &DRAWING_TOOL::DrawSimilarZone, PCB_ACTIONS::drawSimilarZone.MakeEvent() ); + Go( &DRAWING_TOOL::DrawVia, PCB_ACTIONS::drawVia.MakeEvent() ); Go( &DRAWING_TOOL::PlaceText, PCB_ACTIONS::placeText.MakeEvent() ); Go( &DRAWING_TOOL::PlaceDXF, PCB_ACTIONS::placeDXF.MakeEvent() ); Go( &DRAWING_TOOL::SetAnchor, PCB_ACTIONS::setAnchor.MakeEvent() ); diff --git a/pcbnew/tools/drawing_tool.h b/pcbnew/tools/drawing_tool.h index edf627239e..9268542681 100644 --- a/pcbnew/tools/drawing_tool.h +++ b/pcbnew/tools/drawing_tool.h @@ -135,6 +135,8 @@ public: */ int DrawZone( const TOOL_EVENT& aEvent ); + int DrawVia( const TOOL_EVENT& aEvent ); + /** * Function DrawZoneKeepout() * Starts interactively drawing a keepout area. After invoking the function an area settings diff --git a/pcbnew/tools/microwave_tool.cpp b/pcbnew/tools/microwave_tool.cpp index 6a0a0c6936..cf07507090 100644 --- a/pcbnew/tools/microwave_tool.cpp +++ b/pcbnew/tools/microwave_tool.cpp @@ -201,22 +201,32 @@ int MICROWAVE_TOOL::addMicrowaveFootprint( const TOOL_EVENT& aEvent ) frame.SetToolID( info.toolId, wxCURSOR_PENCIL, info.name ); - ITEM_CREATOR moduleCreator = [this, &info] ( const TOOL_EVENT& aAddingEvent ) + struct MICROWAVE_PLACER : public INTERACTIVE_PLACER_BASE { - auto module = info.creatorFunc(); + MICROWAVE_TOOL_INFO& m_info; - // Module has been added in the legacy backend, - // so we have to remove it before committing the change - // @todo LEGACY - if( module ) + MICROWAVE_PLACER( MICROWAVE_TOOL_INFO& aInfo ) : + m_info( aInfo ) {}; + + std::unique_ptr CreateItem() override { - board()->Remove( module.get() ); - } + auto module = m_info.creatorFunc(); - return module; + // Module has been added in the legacy backend, + // so we have to remove it before committing the change + // @todo LEGACY + if( module ) + { + m_board->Remove( module.get() ); + } + + return std::unique_ptr( module.release() ); + } }; - doInteractiveItemPlacement( moduleCreator, _( "Place microwave feature" ) ); + MICROWAVE_PLACER placer ( info ); + + doInteractiveItemPlacement( &placer, _( "Place microwave feature" ) ); frame.SetNoToolSelected(); diff --git a/pcbnew/tools/module_editor_tools.cpp b/pcbnew/tools/module_editor_tools.cpp index 4899a7187d..7100454475 100644 --- a/pcbnew/tools/module_editor_tools.cpp +++ b/pcbnew/tools/module_editor_tools.cpp @@ -95,85 +95,28 @@ void MODULE_EDITOR_TOOLS::Reset( RESET_REASON aReason ) } + int MODULE_EDITOR_TOOLS::PlacePad( const TOOL_EVENT& aEvent ) { + struct PAD_PLACER : public INTERACTIVE_PLACER_BASE + { + std::unique_ptr CreateItem() override + { + D_PAD* pad = new D_PAD ( m_board->m_Modules ); + m_frame->Import_Pad_Settings( pad, false ); // use the global settings for pad + // pad->IncrementPadName( true, true ); + return std::unique_ptr( pad ); + } + }; + + PAD_PLACER placer; + frame()->SetToolID( ID_MODEDIT_PAD_TOOL, wxCURSOR_PENCIL, _( "Add pads" ) ); assert( board()->m_Modules ); - D_PAD* pad = new D_PAD( board()->m_Modules ); - frame()->Import_Pad_Settings( pad, false ); // use the global settings for pad + doInteractiveItemPlacement( &placer, _( "Place pad" ), IPO_REPEAT | IPO_SINGLE_CLICK | IPO_ROTATE | IPO_FLIP | IPO_PROPERTIES ); - VECTOR2I cursorPos = getViewControls()->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( view() ); - preview.Add( pad ); - view()->Add( &preview ); - - m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true ); - getViewControls()->ShowCursor( true ); - getViewControls()->SetSnapping( true ); - - Activate(); - - // Main loop: keep receiving events - while( OPT_TOOL_EVENT evt = Wait() ) - { - cursorPos = getViewControls()->GetCursorPosition(); - - if( evt->IsMotion() ) - { - pad->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); - view()->Update( &preview ); - } - - else if( evt->Category() == TC_COMMAND ) - { - if( TOOL_EVT_UTILS::IsRotateToolEvt( *evt ) ) - { - const auto rotationAngle = TOOL_EVT_UTILS::GetEventRotationAngle( - *frame(), *evt ); - pad->Rotate( pad->GetPosition(), rotationAngle ); - view()->Update( &preview ); - } - else if( evt->IsAction( &PCB_ACTIONS::flip ) ) - { - pad->Flip( pad->GetPosition() ); - view()->Update( &preview ); - } - else if( evt->IsCancel() || evt->IsActivate() ) - { - preview.Clear(); - delete pad; - break; - } - } - - else if( evt->IsClick( BUT_LEFT ) ) - { - BOARD_COMMIT commit( frame() ); - commit.Add( pad ); - - board()->m_Status_Pcb = 0; // I have no clue why, but it is done in the legacy view - - // Take the next available pad number - pad->IncrementPadName( true, true ); - - // Handle the view aspect - preview.Remove( pad ); - commit.Push( _( "Add a pad" ) ); - - // Start placing next pad - pad = new D_PAD( board()->m_Modules ); - frame()->Import_Pad_Settings( pad, false ); - pad->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); - preview.Add( pad ); - } - } - - view()->Remove( &preview ); frame()->SetNoToolSelected(); return 0; diff --git a/pcbnew/tools/pcb_actions.cpp b/pcbnew/tools/pcb_actions.cpp index 6cd3d0437c..a3a3993517 100644 --- a/pcbnew/tools/pcb_actions.cpp +++ b/pcbnew/tools/pcb_actions.cpp @@ -58,6 +58,9 @@ boost::optional PCB_ACTIONS::TranslateLegacyId( int aId ) case ID_PCB_ZONES_BUTT: return PCB_ACTIONS::drawZone.MakeEvent(); + case ID_PCB_DRAW_VIA_BUTT: + return PCB_ACTIONS::drawVia.MakeEvent(); + case ID_PCB_KEEPOUT_AREA_BUTT: return PCB_ACTIONS::drawZoneKeepout.MakeEvent(); diff --git a/pcbnew/tools/pcb_actions.h b/pcbnew/tools/pcb_actions.h index fadc5d9c38..e92016e86f 100644 --- a/pcbnew/tools/pcb_actions.h +++ b/pcbnew/tools/pcb_actions.h @@ -139,6 +139,9 @@ public: /// Activation of the drawing tool (drawing a ZONE) static TOOL_ACTION drawZone; + /// Activation of the drawing tool (drawing a VIA) + static TOOL_ACTION drawVia; + /// Activation of the drawing tool (drawing a keepout area) static TOOL_ACTION drawZoneKeepout; diff --git a/pcbnew/tools/pcb_tool.cpp b/pcbnew/tools/pcb_tool.cpp index 9f921b4b7c..a7aa11cd33 100644 --- a/pcbnew/tools/pcb_tool.cpp +++ b/pcbnew/tools/pcb_tool.cpp @@ -35,36 +35,44 @@ #include "pcb_actions.h" #include "tool_event_utils.h" - -void PCB_TOOL::doInteractiveItemPlacement( ITEM_CREATOR aItemCreator, - const wxString& aCommitMessage ) +void PCB_TOOL::doInteractiveItemPlacement( INTERACTIVE_PLACER_BASE *aPlacer, + const wxString& aCommitMessage, + int aOptions ) { using namespace std::placeholders; - - KIGFX::VIEW& view = *getView(); - KIGFX::VIEW_CONTROLS& controls = *getViewControls(); - auto& frame = *getEditFrame(); - std::unique_ptr newItem; Activate(); - BOARD_COMMIT commit( &frame ); + BOARD_COMMIT commit( frame() ); GetManager()->RunAction( PCB_ACTIONS::selectionClear, true ); // do not capture or auto-pan until we start placing an item - controls.ShowCursor( true ); - controls.SetSnapping( true ); + controls()->ShowCursor( true ); + controls()->SetSnapping( true ); // Add a VIEW_GROUP that serves as a preview for the new item SELECTION preview; - view.Add( &preview ); + view()->Add( &preview ); + + aPlacer->m_board = board(); + aPlacer->m_frame = frame(); + + if ( aOptions & IPO_SINGLE_CLICK ) + { + VECTOR2I cursorPos = controls()->GetCursorPosition(); + + newItem = aPlacer->CreateItem(); + newItem->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); + + preview.Add( newItem.get() ); + } // Main loop: keep receiving events while( OPT_TOOL_EVENT evt = Wait() ) { - VECTOR2I cursorPos = controls.GetCursorPosition(); + VECTOR2I cursorPos = controls()->GetCursorPosition(); if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) ) { @@ -75,9 +83,12 @@ void PCB_TOOL::doInteractiveItemPlacement( ITEM_CREATOR aItemCreator, preview.Clear(); - controls.SetAutoPan( false ); - controls.CaptureCursor( false ); - controls.ShowCursor( true ); + if ( aOptions & IPO_SINGLE_CLICK ) + break; + + controls()->SetAutoPan( false ); + controls()->CaptureCursor( false ); + controls()->ShowCursor( true ); } else { @@ -93,14 +104,14 @@ void PCB_TOOL::doInteractiveItemPlacement( ITEM_CREATOR aItemCreator, if( !newItem ) { // create the item if possible - newItem = aItemCreator( *evt ); + newItem = aPlacer->CreateItem(); // no item created, so wait for another click if( !newItem ) continue; - controls.CaptureCursor( true ); - controls.SetAutoPan( true ); + controls()->CaptureCursor( true ); + controls()->SetAutoPan( true ); newItem->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); @@ -119,6 +130,8 @@ void PCB_TOOL::doInteractiveItemPlacement( ITEM_CREATOR aItemCreator, newItem->ClearFlags(); preview.Remove( newItem.get() ); + aPlacer->PlaceItem( newItem.get() ); + if( newItem->Type() == PCB_MODULE_T ) { auto module = dyn_cast( newItem.get() ); @@ -128,9 +141,22 @@ void PCB_TOOL::doInteractiveItemPlacement( ITEM_CREATOR aItemCreator, commit.Add( newItem.release() ); commit.Push( aCommitMessage ); - controls.CaptureCursor( false ); - controls.SetAutoPan( false ); - controls.ShowCursor( true ); + controls()->CaptureCursor( false ); + controls()->SetAutoPan( false ); + controls()->ShowCursor( true ); + if (! ( aOptions & IPO_REPEAT ) ) + break; + + if ( aOptions & IPO_SINGLE_CLICK ) + { + VECTOR2I cursorPos = controls()->GetCursorPosition(); + + newItem = aPlacer->CreateItem(); + newItem->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); + + preview.Add( newItem.get() ); + } + } } @@ -141,17 +167,17 @@ void PCB_TOOL::doInteractiveItemPlacement( ITEM_CREATOR aItemCreator, * it around, eg rotate and flip */ - if( TOOL_EVT_UTILS::IsRotateToolEvt( *evt ) ) + if( TOOL_EVT_UTILS::IsRotateToolEvt( *evt ) && ( aOptions & IPO_ROTATE ) ) { const auto rotationAngle = TOOL_EVT_UTILS::GetEventRotationAngle( - frame, *evt ); + *frame(), *evt ); newItem->Rotate( newItem->GetPosition(), rotationAngle ); - view.Update( &preview ); + view()->Update( &preview ); } - else if( evt->IsAction( &PCB_ACTIONS::flip ) ) + else if( evt->IsAction( &PCB_ACTIONS::flip ) && ( aOptions & IPO_FLIP ) ) { newItem->Flip( newItem->GetPosition() ); - view.Update( &preview ); + view()->Update( &preview ); } } @@ -161,9 +187,9 @@ void PCB_TOOL::doInteractiveItemPlacement( ITEM_CREATOR aItemCreator, newItem->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); // Show a preview of the item - view.Update( &preview ); + view()->Update( &preview ); } } - view.Remove( &preview ); + view()->Remove( &preview ); } diff --git a/pcbnew/tools/pcb_tool.h b/pcbnew/tools/pcb_tool.h index cac03fc42e..de6b62a3a3 100644 --- a/pcbnew/tools/pcb_tool.h +++ b/pcbnew/tools/pcb_tool.h @@ -42,6 +42,19 @@ * A tool operating on a BOARD object **/ +class PCB_TOOL; +class PCB_EDIT_FRAME; + +struct INTERACTIVE_PLACER_BASE +{ + virtual std::unique_ptr CreateItem() = 0; + virtual bool PlaceItem( BOARD_ITEM *aItem ) { return false; } + + PCB_EDIT_FRAME *m_frame; + BOARD *m_board; +}; + + class PCB_TOOL : public TOOL_INTERACTIVE { public: @@ -82,13 +95,14 @@ public: protected: - /** - * Callable that returns a new board item. - * - * The event that triggered it is provided, so you can check modifier - * keys, position, etc, if required - */ - using ITEM_CREATOR = std::function< std::unique_ptr< BOARD_ITEM >( const TOOL_EVENT& aEvt ) >; + enum INTERACTIVE_PLACEMENT_OPTIONS { + IPO_ROTATE = 1, + IPO_FLIP = 2, + IPO_PROPERTIES = 4, + IPO_SINGLE_CLICK = 8, + IPO_REPEAT = 16 + }; + /** * Helper function for performing a common interactive idiom: @@ -102,10 +116,12 @@ protected: * @param aItemCreator the callable that will attempt to create the item * @param aCommitMessage the message used on a successful commit */ - void doInteractiveItemPlacement( ITEM_CREATOR aItemCreator, - const wxString& aCommitMessage ); + void doInteractiveItemPlacement( INTERACTIVE_PLACER_BASE *aPlacer, + const wxString& aCommitMessage, + int aOptions = IPO_ROTATE | IPO_FLIP | IPO_REPEAT ); KIGFX::VIEW* view() const { return getView(); } + KIGFX::VIEW_CONTROLS* controls() const { return getViewControls(); } PCB_EDIT_FRAME* frame() const { return getEditFrame(); } BOARD* board() const { return getModel(); }