void update() override { SELECTION_TOOL* selTool = getToolManager()->GetTool<SELECTION_TOOL>(); // enable zone actions that act on a single zone bool singleZoneActionsEnabled = ( SELECTION_CONDITIONS::Count( 1 ) && SELECTION_CONDITIONS::OnlyType( PCB_ZONE_AREA_T ) )( selTool->GetSelection() ); Enable( getMenuId( PCB_ACTIONS::zoneDuplicate ), singleZoneActionsEnabled ); Enable( getMenuId( PCB_ACTIONS::drawZoneCutout ), singleZoneActionsEnabled ); Enable( getMenuId( PCB_ACTIONS::drawSimilarZone ), singleZoneActionsEnabled ); // enable zone actions that ably to a specific set of zones (as opposed to all of them) bool nonGlobalActionsEnabled = ( SELECTION_CONDITIONS::MoreThan( 0 ) )( selTool->GetSelection() ); Enable( getMenuId( PCB_ACTIONS::zoneFill ), nonGlobalActionsEnabled ); Enable( getMenuId( PCB_ACTIONS::zoneUnfill ), nonGlobalActionsEnabled ); // lines like this make me really think about a better name for SELECTION_CONDITIONS class bool mergeEnabled = ( SELECTION_CONDITIONS::MoreThan( 1 ) && /*SELECTION_CONDITIONS::OnlyType( PCB_ZONE_AREA_T ) &&*/ PCB_SELECTION_CONDITIONS::SameNet( true ) && PCB_SELECTION_CONDITIONS::SameLayer() )( selTool->GetSelection() ); Enable( getMenuId( PCB_ACTIONS::zoneMerge ), mergeEnabled ); }
void update() { SELECTION_TOOL* selTool = getToolManager()->GetTool<SELECTION_TOOL>(); // lines like this make me really think about a better name for SELECTION_CONDITIONS class bool mergeEnabled = ( SELECTION_CONDITIONS::MoreThan( 1 ) && /*SELECTION_CONDITIONS::OnlyType( PCB_ZONE_AREA_T ) &&*/ SELECTION_CONDITIONS::SameNet( true ) && SELECTION_CONDITIONS::SameLayer() )( selTool->GetSelection() ); Enable( getMenuId( COMMON_ACTIONS::zoneMerge ), mergeEnabled ); }
int PCB_EDITOR_CONTROL::SelectionCrossProbe( const TOOL_EVENT& aEvent ) { SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); const SELECTION& selection = selTool->GetSelection(); if( selection.Size() == 1 ) m_frame->SendMessageToEESCHEMA( selection.Item<BOARD_ITEM>( 0 ) ); setTransitions(); return 0; }
int PCB_EDITOR_CONTROL::CrossProbePcbToSch( const TOOL_EVENT& aEvent ) { if( m_probingSchToPcb ) { m_probingSchToPcb = false; return 0; } SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); const SELECTION& selection = selTool->GetSelection(); if( selection.Size() == 1 ) m_frame->SendMessageToEESCHEMA( selection.Item<BOARD_ITEM>( 0 ) ); return 0; }
int EDIT_TOOL::CreateArray( const TOOL_EVENT& aEvent ) { // first, check if we have a selection, or try to get one SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); const SELECTION& selection = selTool->GetSelection(); // pick up items under the cursor if needed if( !hoverSelection() ) return 0; // we have a selection to work on now, so start the tool process PCB_BASE_FRAME* editFrame = getEditFrame<PCB_BASE_FRAME>(); GAL_ARRAY_CREATOR array_creator( *editFrame, m_editModules, selection ); array_creator.Invoke(); return 0; }
int PCB_EDITOR_CONTROL::UpdateSelectionRatsnest( const TOOL_EVENT& aEvent ) { SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); const SELECTION& selection = selTool->GetSelection(); RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest(); // Update "simple" ratsnest, computed for currently modified items ratsnest->ClearSimple(); for( auto item : selection ) { ratsnest->Update( static_cast<BOARD_ITEM*>( item ) ); ratsnest->AddSimple( static_cast<BOARD_ITEM*>( item ) ); } return 0; }
int PCB_EDITOR_CONTROL::ZoneUnfill( TOOL_EVENT& aEvent ) { SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); const SELECTION& selection = selTool->GetSelection(); for( int i = 0; i < selection.Size(); ++i ) { assert( selection.Item<BOARD_ITEM>( i )->Type() == PCB_ZONE_AREA_T ); ZONE_CONTAINER* zone = selection.Item<ZONE_CONTAINER>( i ); zone->SetIsFilled( false ); zone->ClearFilledPolysList(); zone->ViewUpdate(); } setTransitions(); return 0; }
static bool deleteItem( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition ) { SELECTION_TOOL* selectionTool = aToolMgr->GetTool<SELECTION_TOOL>(); assert( selectionTool ); aToolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); aToolMgr->RunAction( COMMON_ACTIONS::selectionCursor, true ); selectionTool->SanitizeSelection(); if( selectionTool->GetSelection().Empty() ) return true; if( IsOK( aToolMgr->GetEditFrame(), _( "Are you sure you want to delete item?" ) ) ) aToolMgr->RunAction( COMMON_ACTIONS::remove, true ); else aToolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); return true; }
int PCB_EDITOR_CONTROL::ZoneUnfill( const TOOL_EVENT& aEvent ) { SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); const SELECTION& selection = selTool->GetSelection(); RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest(); for( int i = 0; i < selection.Size(); ++i ) { assert( selection.Item<BOARD_ITEM>( i )->Type() == PCB_ZONE_AREA_T ); ZONE_CONTAINER* zone = selection.Item<ZONE_CONTAINER>( i ); zone->SetIsFilled( false ); zone->ClearFilledPolysList(); ratsnest->Update( zone ); zone->ViewUpdate(); } ratsnest->Recalculate(); return 0; }
int PCB_EDITOR_CONTROL::modifyLockSelected( MODIFY_MODE aMode ) { SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); const SELECTION& selection = selTool->GetSelection(); if( selection.Empty() ) m_toolMgr->RunAction( COMMON_ACTIONS::selectionCursor, true ); bool modified = false; for( int i = 0; i < selection.Size(); ++i ) { BOARD_ITEM* item = selection.Item<BOARD_ITEM>( i ); bool prevState = item->IsLocked(); switch( aMode ) { case ON: item->SetLocked( true ); break; case OFF: item->SetLocked( false ); break; case TOGGLE: item->SetLocked( !prevState ); break; } // Check if we really modified an item if( !modified && prevState != item->IsLocked() ) modified = true; } if( modified ) m_frame->OnModify(); return 0; }
int PCB_EDITOR_CONTROL::ToggleLockModule( const TOOL_EVENT& aEvent ) { SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); const SELECTION& selection = selTool->GetSelection(); bool clearSelection = selection.Empty(); if( clearSelection ) m_toolMgr->RunAction( COMMON_ACTIONS::selectionCursor, true ); for( int i = 0; i < selection.Size(); ++i ) { if( selection.Item<BOARD_ITEM>( i )->Type() == PCB_MODULE_T ) { MODULE* module = selection.Item<MODULE>( i ); module->SetLocked( !module->IsLocked() ); } } if( clearSelection ) m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); return 0; }
static bool deleteItem( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition ) { SELECTION_TOOL* selectionTool = aToolMgr->GetTool<SELECTION_TOOL>(); assert( selectionTool ); aToolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); aToolMgr->RunAction( COMMON_ACTIONS::selectionCursor, true ); selectionTool->SanitizeSelection(); const SELECTION& selection = selectionTool->GetSelection(); if( selection.Empty() ) return true; bool canBeRemoved = ( selection.Item<EDA_ITEM>( 0 )->Type() != PCB_MODULE_T ); if( canBeRemoved || IsOK( aToolMgr->GetEditFrame(), _( "Are you sure you want to delete item?" ) ) ) aToolMgr->RunAction( COMMON_ACTIONS::remove, true ); else aToolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); return true; }
int EDIT_TOOL::CreateArray( const TOOL_EVENT& aEvent ) { // first, check if we have a selection, or try to get one SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); const SELECTION& selection = selTool->GetSelection(); // Be sure that there is at least one item that we can modify if( !hoverSelection( selection ) ) return 0; bool originalItemsModified = false; // we have a selection to work on now, so start the tool process PCB_BASE_FRAME* editFrame = getEditFrame<PCB_BASE_FRAME>(); editFrame->OnModify(); if( m_editModules ) { // Module editors do their undo point upfront for the whole module editFrame->SaveCopyInUndoList( editFrame->GetBoard()->m_Modules, UR_MODEDIT ); } else { // We may also change the original item editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED ); } DIALOG_CREATE_ARRAY::ARRAY_OPTIONS* array_opts = NULL; VECTOR2I rp = selection.GetCenter(); const wxPoint rotPoint( rp.x, rp.y ); DIALOG_CREATE_ARRAY dialog( editFrame, rotPoint, &array_opts ); int ret = dialog.ShowModal(); if( ret == wxID_OK && array_opts != NULL ) { PICKED_ITEMS_LIST newItemList; for( int i = 0; i < selection.Size(); ++i ) { BOARD_ITEM* item = selection.Item<BOARD_ITEM>( i ); if( !item ) continue; wxString cachedString; if( item->Type() == PCB_MODULE_T ) { cachedString = static_cast<MODULE*>( item )->GetReferencePrefix(); } else if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item ) ) { // Copy the text (not just take a reference cachedString = text->GetText(); } // iterate across the array, laying out the item at the // correct position const unsigned nPoints = array_opts->GetArraySize(); for( unsigned ptN = 0; ptN < nPoints; ++ptN ) { BOARD_ITEM* newItem = NULL; if( ptN == 0 ) newItem = item; else { // if renumbering, no need to increment const bool increment = !array_opts->ShouldRenumberItems(); // Some items cannot be duplicated // i.e. the ref and value fields of a footprint or zones // therefore newItem can be null if( m_editModules ) newItem = editFrame->GetBoard()->m_Modules->DuplicateAndAddItem( item, increment ); else { #if 0 // @TODO: see if we allow zone duplication here // Duplicate zones is especially tricky (overlaping zones must be merged) // so zones are not duplicated if( item->Type() == PCB_ZONE_AREA_T ) newItem = NULL; else #endif newItem = editFrame->GetBoard()->DuplicateAndAddItem( item, increment ); } if( newItem ) { array_opts->TransformItem( ptN, newItem, rotPoint ); m_toolMgr->RunAction( COMMON_ACTIONS::unselectItem, true, newItem ); newItemList.PushItem( newItem ); if( newItem->Type() == PCB_MODULE_T) { static_cast<MODULE*>( newItem )->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, getView(), _1 ) ); } editFrame->GetGalCanvas()->GetView()->Add( newItem ); getModel<BOARD>()->GetRatsnest()->Update( newItem ); } } // set the number if needed: if( newItem && array_opts->ShouldRenumberItems() ) { switch( newItem->Type() ) { case PCB_PAD_T: { const wxString padName = array_opts->GetItemNumber( ptN ); static_cast<D_PAD*>( newItem )->SetPadName( padName ); originalItemsModified = true; break; } case PCB_MODULE_T: { const wxString moduleName = array_opts->GetItemNumber( ptN ); MODULE* module = static_cast<MODULE*>( newItem ); module->SetReference( cachedString + moduleName ); originalItemsModified = true; break; } case PCB_MODULE_TEXT_T: case PCB_TEXT_T: { EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( newItem ); if( text ) text->SetText( array_opts->InterpolateNumberIntoString( ptN, cachedString ) ); originalItemsModified = true; break; } default: // no renumbering of other items break; } } } } if( !m_editModules ) { if( originalItemsModified ) { // Update the appearance of the original items selection.group->ItemsViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); } // Add all items as a single undo point for PCB editors // TODO: Can this be merged into the previous undo point (where // we saved the original items) editFrame->SaveCopyInUndoList( newItemList, UR_NEW ); } } getModel<BOARD>()->GetRatsnest()->Recalculate(); return 0; }
int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent ) { bool increment = aEvent.IsAction( &COMMON_ACTIONS::duplicateIncrement ); // first, check if we have a selection, or try to get one SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); const SELECTION& selection = selTool->GetSelection(); // Be sure that there is at least one item that we can modify if( !hoverSelection( selection ) ) return 0; // we have a selection to work on now, so start the tool process PCB_BASE_FRAME* editFrame = getEditFrame<PCB_BASE_FRAME>(); editFrame->OnModify(); // prevent other tools making undo points while the duplicate is going on // so that if you cancel, you don't get a duplicate object hiding over // the original incUndoInhibit(); if( m_editModules ) editFrame->SaveCopyInUndoList( editFrame->GetBoard()->m_Modules, UR_MODEDIT ); std::vector<BOARD_ITEM*> old_items; for( int i = 0; i < selection.Size(); ++i ) { BOARD_ITEM* item = selection.Item<BOARD_ITEM>( i ); if( item ) old_items.push_back( item ); } for( unsigned i = 0; i < old_items.size(); ++i ) { BOARD_ITEM* item = old_items[i]; // Unselect the item, so we won't pick it up again // Do this first, so a single-item duplicate will correctly call // SetCurItem and show the item properties m_toolMgr->RunAction( COMMON_ACTIONS::unselectItem, true, item ); BOARD_ITEM* new_item = NULL; if( m_editModules ) new_item = editFrame->GetBoard()->m_Modules->DuplicateAndAddItem( item, increment ); else { #if 0 // @TODO: see if we allow zone duplication here // Duplicate zones is especially tricky (overlaping zones must be merged) // so zones are not duplicated if( item->Type() != PCB_ZONE_AREA_T ) #endif new_item = editFrame->GetBoard()->DuplicateAndAddItem( item, increment ); } if( new_item ) { if( new_item->Type() == PCB_MODULE_T ) { static_cast<MODULE*>( new_item )->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, getView(), _1 ) ); } editFrame->GetGalCanvas()->GetView()->Add( new_item ); // Select the new item, so we can pick it up m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, new_item ); } } // record the new items as added if( !m_editModules ) editFrame->SaveCopyInUndoList( selection.items, UR_NEW ); editFrame->DisplayToolMsg( wxString::Format( _( "Duplicated %d item(s)" ), (int) old_items.size() ) ); // pick up the selected item(s) and start moving // this works well for "dropping" copies around TOOL_EVENT evt = COMMON_ACTIONS::editActivate.MakeEvent(); Main( evt ); // and re-enable undos decUndoInhibit(); return 0; }
int PCBNEW_CONTROL::AppendBoard( const TOOL_EVENT& aEvent ) { int open_ctl; wxString fileName; PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame ); BOARD* board = getModel<BOARD>(); BOARD_COMMIT commit( editFrame ); if( !editFrame ) return 0; // Pick a file to append if( !AskLoadBoardFileName( editFrame, &open_ctl, &fileName, true ) ) return 0; IO_MGR::PCB_FILE_T pluginType = plugin_type( fileName, open_ctl ); PLUGIN::RELEASER pi( IO_MGR::PluginFind( pluginType ) ); // keep track of existing items, in order to know what are the new items // (for undo command for instance) // Tracks are inserted, not appended, so mark the existing tracks to know what are the new tracks for( TRACK* track = board->m_Track; track; track = track->Next() ) track->SetFlags( FLAG0 ); // Other items are appended to the item list, so keep trace to the last existing item is enough MODULE* module = board->m_Modules.GetLast(); BOARD_ITEM* drawing = board->m_Drawings.GetLast(); int zonescount = board->GetAreaCount(); // Keep also the count of copper layers, to adjust if necessary int initialCopperLayerCount = board->GetCopperLayerCount(); LSET initialEnabledLayers = board->GetEnabledLayers(); // Load the data try { PROPERTIES props; char xbuf[30]; char ybuf[30]; // EAGLE_PLUGIN can use this info to center the BOARD, but it does not yet. sprintf( xbuf, "%d", editFrame->GetPageSizeIU().x ); sprintf( ybuf, "%d", editFrame->GetPageSizeIU().y ); props["page_width"] = xbuf; props["page_height"] = ybuf; editFrame->GetDesignSettings().m_NetClasses.Clear(); pi->Load( fileName, board, &props ); } catch( const IO_ERROR& ioe ) { wxString msg = wxString::Format( _( "Error loading board.\n%s" ), GetChars( ioe.What() )); DisplayError( editFrame, msg ); return 0; } m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); // Process the new items for( TRACK* track = board->m_Track; track; track = track->Next() ) { if( track->GetFlags() & FLAG0 ) { track->ClearFlags( FLAG0 ); continue; } commit.Added( track ); m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, track ); } module = module ? module->Next() : board->m_Modules; for( ; module; module = module->Next() ) { commit.Added( module ); m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, module ); } drawing = drawing ? drawing->Next() : board->m_Drawings; for( ; drawing; drawing = drawing->Next() ) { commit.Added( drawing ); m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, drawing ); } for( ZONE_CONTAINER* zone = board->GetArea( zonescount ); zone; zone = board->GetArea( zonescount ) ) { ++zonescount; commit.Added( zone ); m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, zone ); } if( commit.Empty() ) return 0; commit.Push( _( "Append a board" ) ); // Synchronize layers // we should not ask PLUGINs to do these items: int copperLayerCount = board->GetCopperLayerCount(); if( copperLayerCount > initialCopperLayerCount ) board->SetCopperLayerCount( copperLayerCount ); // Enable all used layers, and make them visible: LSET enabledLayers = board->GetEnabledLayers(); enabledLayers |= initialEnabledLayers; board->SetEnabledLayers( enabledLayers ); board->SetVisibleLayers( enabledLayers ); editFrame->ReCreateLayerBox(); editFrame->ReFillLayerWidget(); static_cast<PCB_DRAW_PANEL_GAL*>( editFrame->GetGalCanvas() )->SyncLayersVisibility( board ); // Ratsnest board->BuildListOfNets(); board->SynchronizeNetsAndNetClasses(); board->GetRatsnest()->ProcessBoard(); // Start dragging the appended board SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SELECTION_TOOL>(); const SELECTION& selection = selectionTool->GetSelection(); VECTOR2D v( selection.Item<BOARD_ITEM>( 0 )->GetPosition() ); getViewControls()->WarpCursor( v, true, true ); m_toolMgr->InvokeTool( "pcbnew.InteractiveEdit" ); return 0; }
int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent ) { // Note: original items are no more modified. bool increment = aEvent.IsAction( &COMMON_ACTIONS::duplicateIncrement ); // first, check if we have a selection, or try to get one SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); const SELECTION& selection = selTool->GetSelection(); // Be sure that there is at least one item that we can modify if( !hoverSelection() ) return 0; // we have a selection to work on now, so start the tool process PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>(); std::vector<BOARD_ITEM*> old_items; for( int i = 0; i < selection.Size(); ++i ) { BOARD_ITEM* item = selection.Item<BOARD_ITEM>( i ); if( item ) old_items.push_back( item ); } for( unsigned i = 0; i < old_items.size(); ++i ) { BOARD_ITEM* item = old_items[i]; // Unselect the item, so we won't pick it up again // Do this first, so a single-item duplicate will correctly call // SetCurItem and show the item properties m_toolMgr->RunAction( COMMON_ACTIONS::unselectItem, true, item ); BOARD_ITEM* new_item = NULL; if( m_editModules ) new_item = editFrame->GetBoard()->m_Modules->Duplicate( item, increment ); else { #if 0 // @TODO: see if we allow zone duplication here // Duplicate zones is especially tricky (overlaping zones must be merged) // so zones are not duplicated if( item->Type() != PCB_ZONE_AREA_T ) #endif new_item = editFrame->GetBoard()->Duplicate( item ); } if( new_item ) { m_commit->Add( new_item ); // Select the new item, so we can pick it up m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, new_item ); } } // record the new items as added if( !selection.Empty() ) { editFrame->DisplayToolMsg( wxString::Format( _( "Duplicated %d item(s)" ), (int) old_items.size() ) ); // If items were duplicated, pick them up // this works well for "dropping" copies around and pushes the commit TOOL_EVENT evt = COMMON_ACTIONS::editActivate.MakeEvent(); Main( evt ); } return 0; };