EDA_ITEM* SELECTION::GetTopLeftItem( bool onlyModules ) const { BOARD_ITEM* topLeftItem = nullptr; BOARD_ITEM* currentItem; wxPoint pnt; // find the leftmost (smallest x coord) and highest (smallest y with the smallest x) item in the selection for( auto item : m_items ) { currentItem = static_cast<BOARD_ITEM*>( item ); pnt = currentItem->GetPosition(); if( ( currentItem->Type() != PCB_MODULE_T ) && onlyModules ) { continue; } else { if( topLeftItem == nullptr ) { topLeftItem = currentItem; } else if( ( pnt.x < topLeftItem->GetPosition().x ) || ( ( topLeftItem->GetPosition().x == pnt.x ) && ( pnt.y < topLeftItem->GetPosition().y ) ) ) { topLeftItem = currentItem; } } } return static_cast<EDA_ITEM*>( topLeftItem ); }
void FOOTPRINT_EDIT_FRAME::moveExact() { MOVE_PARAMETERS params; params.allowOverride = false; params.editingFootprint = true; DIALOG_MOVE_EXACT dialog( this, params ); int ret = dialog.ShowModal(); if( ret == wxID_OK ) { SaveCopyInUndoList( GetBoard()->m_Modules, UR_CHANGED ); BOARD_ITEM* item = GetScreen()->GetCurItem(); wxPoint anchorPoint = item->GetPosition(); wxPoint origin; switch( params.origin ) { case RELATIVE_TO_USER_ORIGIN: origin = GetScreen()->m_O_Curseur; break; case RELATIVE_TO_GRID_ORIGIN: origin = GetGridOrigin(); break; case RELATIVE_TO_DRILL_PLACE_ORIGIN: origin = GetAuxOrigin(); break; case RELATIVE_TO_SHEET_ORIGIN: origin = wxPoint( 0, 0 ); break; case RELATIVE_TO_CURRENT_POSITION: // relative movement means that only the translation values should be used: // -> set origin and anchor to zero origin = wxPoint( 0, 0 ); anchorPoint = wxPoint( 0, 0 ); break; } wxPoint finalMoveVector = params.translation + origin - anchorPoint; item->Move( finalMoveVector ); item->Rotate( item->GetPosition(), params.rotation ); m_canvas->Refresh(); } m_canvas->MoveCursorToCrossHair(); }
void DIALOG_DRC_CONTROL::doSelectionMenu( const DRC_ITEM* aItem ) { // popup menu to go to either of the items listed in the DRC_ITEM. BOARD_ITEM* first = aItem->GetMainItem( m_brdEditor->GetBoard() ); BOARD_ITEM* second = nullptr; GENERAL_COLLECTOR items; items.Append( first ); if( aItem->HasSecondItem() ) { second = aItem->GetAuxiliaryItem( m_brdEditor->GetBoard() ); items.Append( second ); } WINDOW_THAWER thawer( m_brdEditor ); m_brdEditor->GetToolManager()->VetoContextMenuMouseWarp(); m_brdEditor->GetToolManager()->RunAction( PCB_ACTIONS::selectionMenu, true, &items ); // If we got an item, focus on it BOARD_ITEM* selection = m_brdEditor->GetCurItem(); if( selection && ( selection == first || selection == second ) ) m_brdEditor->GetToolManager()->GetView()->SetCenter( selection->GetPosition() ); m_brdEditor->GetCanvas()->Refresh(); }
int PCB_EDITOR_CONTROL::CrossProbeSchToPcb( const TOOL_EVENT& aEvent ) { BOARD_ITEM* item = aEvent.Parameter<BOARD_ITEM*>(); if( item ) { m_probingSchToPcb = true; getView()->SetCenter( VECTOR2D( item->GetPosition() ) ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); // If it is a pad and the net highlighting tool is enabled, highlight the net if( item->Type() == PCB_PAD_T && m_frame->GetToolId() == ID_PCB_HIGHLIGHT_BUTT ) { int net = static_cast<D_PAD*>( item )->GetNetCode(); m_toolMgr->RunAction( COMMON_ACTIONS::highlightNet, false, net ); } else // Otherwise simply select the corresponding item { m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, item ); } } return 0; }
int PCB_EDITOR_CONTROL::CrossProbeSchToPcb( const TOOL_EVENT& aEvent ) { BOARD_ITEM* item = aEvent.Parameter<BOARD_ITEM*>(); if( item ) { m_probingSchToPcb = true; getView()->SetCenter( VECTOR2D( item->GetPosition() ) ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, item ); } return 0; }
void FOOTPRINT_EDIT_FRAME::moveExact() { wxPoint translation; double rotation = 0; DIALOG_MOVE_EXACT dialog( this, translation, rotation ); int ret = dialog.ShowModal(); if( ret == wxID_OK ) { SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); BOARD_ITEM* item = GetScreen()->GetCurItem(); item->Move( translation ); item->Rotate( item->GetPosition(), rotation ); m_canvas->Refresh(); } m_canvas->MoveCursorToCrossHair(); }
int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) { KIGFX::VIEW_CONTROLS* controls = getViewControls(); PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>(); VECTOR2I originalCursorPos = controls->GetCursorPosition(); const SELECTION& selection = m_selectionTool->GetSelection(); // Shall the selection be cleared at the end? bool unselect = selection.Empty(); // Be sure that there is at least one item that we can modify. If nothing was selected before, // try looking for the stuff under mouse cursor (i.e. Kicad old-style hover selection) if( !hoverSelection( selection ) ) return 0; Activate(); m_dragging = false; // Are selected items being dragged? bool restore = false; // Should items' state be restored when finishing the tool? bool lockOverride = false; // By default, modified items need to update their geometry m_updateFlag = KIGFX::VIEW_ITEM::GEOMETRY; controls->ShowCursor( true ); // cumulative translation wxPoint totalMovement( 0, 0 ); GRID_HELPER grid( editFrame ); OPT_TOOL_EVENT evt = aEvent; // Main loop: keep receiving events do { if( evt->IsCancel() ) { restore = true; // Cancelling the tool means that items have to be restored break; // Finish } else if( evt->Action() == TA_UNDO_REDO ) { unselect = true; break; } else if( evt->IsAction( &COMMON_ACTIONS::editActivate ) || evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) { BOARD_ITEM* item = selection.Item<BOARD_ITEM>( 0 ); if( m_dragging && evt->Category() == TC_MOUSE ) { m_cursor = grid.BestSnapAnchor( evt->Position(), item ); controls->ForceCursorPosition( true, m_cursor ); wxPoint movement = wxPoint( m_cursor.x, m_cursor.y ) - item->GetPosition(); totalMovement += movement; // Drag items to the current cursor position for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) selection.Item<BOARD_ITEM>( i )->Move( movement + m_offset ); updateRatsnest( true ); } else if( !m_dragging ) // Prepare to start dragging { if( !invokeInlineRouter() ) { m_selectionTool->SanitizeSelection(); if( selection.Empty() ) break; // deal with locked items (override lock or abort the operation) SELECTION_LOCK_FLAGS lockFlags = m_selectionTool->CheckLock(); if( lockFlags == SELECTION_LOCKED ) break; else if( lockFlags == SELECTION_LOCK_OVERRIDE ) lockOverride = true; // Save items, so changes can be undone if( !isUndoInhibited() ) { editFrame->OnModify(); editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED ); } m_cursor = controls->GetCursorPosition(); if( selection.Size() == 1 ) { // Set the current cursor position to the first dragged item origin, so the // movement vector could be computed later m_cursor = grid.BestDragOrigin( originalCursorPos, item ); grid.SetAuxAxes( true, m_cursor ); } else { m_cursor = grid.Align( m_cursor ); } controls->ForceCursorPosition( true, m_cursor ); controls->WarpCursor( m_cursor, true ); VECTOR2I o = VECTOR2I( item->GetPosition() ); m_offset.x = o.x - m_cursor.x; m_offset.y = o.y - m_cursor.y; controls->SetAutoPan( true ); m_dragging = true; incUndoInhibit(); } } selection.group->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); m_toolMgr->RunAction( COMMON_ACTIONS::pointEditorUpdate, true ); } // Dispatch TOOL_ACTIONs else if( evt->Category() == TC_COMMAND ) { if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) { Rotate( aEvent ); } else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) { Flip( aEvent ); // Flip causes change of layers enableUpdateFlag( KIGFX::VIEW_ITEM::LAYERS ); } else if( evt->IsAction( &COMMON_ACTIONS::remove ) ) { Remove( aEvent ); break; // exit the loop, as there is no further processing for removed items } else if( evt->IsAction( &COMMON_ACTIONS::duplicate ) ) { // On duplicate, stop moving this item // The duplicate tool should then select the new item and start // a new move procedure break; } else if( evt->IsAction( &COMMON_ACTIONS::moveExact ) ) { // Can't do this, because the selection will then contain // stale pointers and it will all go horribly wrong... //editFrame->RestoreCopyFromUndoList( dummy ); // // So, instead, reset the position manually for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) { BOARD_ITEM* item = selection.Item<BOARD_ITEM>( i ); item->SetPosition( item->GetPosition() - totalMovement ); // And what about flipping and rotation? // for now, they won't be undone, but maybe that is how // it should be, so you can flip and move exact in the // same action? } // This causes a double event, so we will get the dialogue // correctly, somehow - why does Rotate not? //MoveExact( aEvent ); break; // exit the loop - we move exactly, so we have finished moving } } else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) { if( !lockOverride ) break; // Finish lockOverride = false; } } while( evt = Wait() ); if( m_dragging ) decUndoInhibit(); m_dragging = false; m_offset.x = 0; m_offset.y = 0; if( restore ) { // Modifications have to be rollbacked, so restore the previous state of items wxCommandEvent dummy; editFrame->RestoreCopyFromUndoList( dummy ); } else { // Changes are applied, so update the items selection.group->ItemsViewUpdate( m_updateFlag ); } if( unselect ) m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest(); ratsnest->ClearSimple(); ratsnest->Recalculate(); controls->ShowCursor( false ); controls->SetAutoPan( false ); return 0; }
void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRedoCommand, bool aRebuildRatsnet ) { BOARD_ITEM* item; bool not_found = false; bool reBuild_ratsnest = false; bool deep_reBuild_ratsnest = false; // true later if pointers must be rebuilt auto view = GetGalCanvas()->GetView(); auto connectivity = GetBoard()->GetConnectivity(); // Undo in the reverse order of list creation: (this can allow stacked changes // like the same item can be changes and deleted in the same complex command bool build_item_list = true; // if true the list of existing items must be rebuilt // Restore changes in reverse order for( int ii = aList->GetCount() - 1; ii >= 0 ; ii-- ) { item = (BOARD_ITEM*) aList->GetPickedItem( ii ); wxASSERT( item ); /* Test for existence of item on board. * It could be deleted, and no more on board: * - if a call to SaveCopyInUndoList was forgotten in Pcbnew * - in zones outlines, when a change in one zone merges this zone with an other * This test avoids a Pcbnew crash * Obviously, this test is not made for deleted items */ UNDO_REDO_T status = aList->GetPickedItemStatus( ii ); if( status != UR_DELETED && status != UR_DRILLORIGIN // origin markers never on board && status != UR_GRIDORIGIN ) // origin markers never on board { if( build_item_list ) // Build list of existing items, for integrity test TestForExistingItem( GetBoard(), NULL ); build_item_list = false; if( !TestForExistingItem( GetBoard(), item ) ) { // Checking if it ever happens wxASSERT_MSG( false, "Item in the undo buffer does not exist" ); // Remove this non existent item aList->RemovePicker( ii ); ii++; // the current item was removed, ii points now the next item // decrement it because it will be incremented later not_found = true; continue; } } item->ClearFlags(); // see if we must rebuild ratsnets and pointers lists switch( item->Type() ) { case PCB_MODULE_T: deep_reBuild_ratsnest = true; // Pointers on pads can be invalid // Fall through case PCB_ZONE_AREA_T: case PCB_TRACE_T: case PCB_VIA_T: reBuild_ratsnest = true; break; case PCB_NETINFO_T: reBuild_ratsnest = true; deep_reBuild_ratsnest = true; break; default: break; } // It is possible that we are going to replace the selected item, so clear it SetCurItem( NULL ); switch( aList->GetPickedItemStatus( ii ) ) { case UR_CHANGED: /* Exchange old and new data for each item */ { BOARD_ITEM* image = (BOARD_ITEM*) aList->GetPickedItemLink( ii ); // Remove all pads/drawings/texts, as they become invalid // for the VIEW after SwapData() called for modules view->Remove( item ); connectivity->Remove( item ); SwapItemData( item, image ); // Update all pads/drawings/texts, as they become invalid // for the VIEW after SwapData() called for modules if( item->Type() == PCB_MODULE_T ) { MODULE* newModule = static_cast<MODULE*>( item ); newModule->RunOnChildren( std::bind( &BOARD_ITEM::ClearFlags, _1, EDA_ITEM_ALL_FLAGS )); } view->Add( item ); connectivity->Add( item ); item->ClearFlags(); } break; case UR_NEW: /* new items are deleted */ aList->SetPickedItemStatus( UR_DELETED, ii ); GetModel()->Remove( item ); view->Remove( item ); break; case UR_DELETED: /* deleted items are put in List, as new items */ aList->SetPickedItemStatus( UR_NEW, ii ); GetModel()->Add( item ); view->Add( item ); build_item_list = true; break; case UR_MOVED: item->Move( aRedoCommand ? aList->m_TransformPoint : -aList->m_TransformPoint ); view->Update( item, KIGFX::GEOMETRY ); connectivity->Update( item ); break; case UR_ROTATED: item->Rotate( aList->m_TransformPoint, aRedoCommand ? m_rotationAngle : -m_rotationAngle ); view->Update( item, KIGFX::GEOMETRY ); connectivity->Update( item ); break; case UR_ROTATED_CLOCKWISE: item->Rotate( aList->m_TransformPoint, aRedoCommand ? -m_rotationAngle : m_rotationAngle ); view->Update( item, KIGFX::GEOMETRY ); connectivity->Update( item ); break; case UR_FLIPPED: item->Flip( aList->m_TransformPoint ); view->Update( item, KIGFX::LAYERS ); connectivity->Update( item ); break; case UR_DRILLORIGIN: case UR_GRIDORIGIN: { BOARD_ITEM* image = (BOARD_ITEM*) aList->GetPickedItemLink( ii ); VECTOR2D origin = image->GetPosition(); image->SetPosition( item->GetPosition() ); if( aList->GetPickedItemStatus( ii ) == UR_DRILLORIGIN ) PCB_EDITOR_CONTROL::DoSetDrillOrigin( view, this, item, origin ); else PCBNEW_CONTROL::DoSetGridOrigin( view, this, item, origin ); } break; default: { wxLogDebug( wxT( "PutDataInPreviousState() error (unknown code %X)" ), aList->GetPickedItemStatus( ii ) ); } break; } } if( not_found ) wxMessageBox( _( "Incomplete undo/redo operation: some items not found" ) ); // Rebuild pointers and connectivity that can be changed. // connectivity can be rebuilt only in the board editor frame if( IsType( FRAME_PCB ) && ( reBuild_ratsnest || deep_reBuild_ratsnest ) ) { Compile_Ratsnest( NULL, false ); } GetBoard()->SanitizeNetcodes(); }
int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent ) { if( m_editModules && !m_board->m_Modules ) return 0; DIALOG_DXF_IMPORT dlg( m_frame ); int dlgResult = dlg.ShowModal(); const std::list<BOARD_ITEM*>& list = dlg.GetImportedItems(); if( dlgResult != wxID_OK || list.empty() ) return 0; VECTOR2I cursorPos = m_controls->GetCursorPosition(); VECTOR2I delta = cursorPos - (*list.begin())->GetPosition(); // Add a VIEW_GROUP that serves as a preview for the new item KIGFX::VIEW_GROUP preview( m_view ); // Build the undo list & add items to the current view std::list<BOARD_ITEM*>::const_iterator it, itEnd; for( it = list.begin(), itEnd = list.end(); it != itEnd; ++it ) { KICAD_T type = (*it)->Type(); assert( type == PCB_LINE_T || type == PCB_TEXT_T ); if( type == PCB_LINE_T || type == PCB_TEXT_T ) preview.Add( *it ); } BOARD_ITEM* firstItem = static_cast<BOARD_ITEM*>( *preview.Begin() ); m_view->Add( &preview ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); 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() ) { delta = cursorPos - firstItem->GetPosition(); for( KIGFX::VIEW_GROUP::iter it = preview.Begin(), end = preview.End(); it != end; ++it ) static_cast<BOARD_ITEM*>( *it )->Move( wxPoint( delta.x, delta.y ) ); preview.ViewUpdate(); } else if( evt->Category() == TC_COMMAND ) { if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) { for( KIGFX::VIEW_GROUP::iter it = preview.Begin(), end = preview.End(); it != end; ++it ) static_cast<BOARD_ITEM*>( *it )->Rotate( wxPoint( cursorPos.x, cursorPos.y ), m_frame->GetRotationAngle() ); preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); } else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) { for( KIGFX::VIEW_GROUP::iter it = preview.Begin(), end = preview.End(); it != end; ++it ) static_cast<BOARD_ITEM*>( *it )->Flip( wxPoint( cursorPos.x, cursorPos.y ) ); preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); } else if( evt->IsCancel() || evt->IsActivate() ) { preview.FreeItems(); break; } } else if( evt->IsClick( BUT_LEFT ) ) { // Place the drawing if( m_editModules ) { assert( m_board->m_Modules ); m_frame->SaveCopyInUndoList( m_board->m_Modules, UR_MODEDIT ); m_board->m_Modules->SetLastEditTime(); for( KIGFX::VIEW_GROUP::iter it = preview.Begin(), end = preview.End(); it != end; ++it ) { BOARD_ITEM* item = static_cast<BOARD_ITEM*>( *it ); BOARD_ITEM* converted = NULL; // Modules use different types for the same things, // so we need to convert imported items to appropriate classes. switch( item->Type() ) { case PCB_TEXT_T: converted = new TEXTE_MODULE( m_board->m_Modules ); // Copy coordinates, layer, etc. *static_cast<TEXTE_PCB*>( converted ) = *static_cast<TEXTE_PCB*>( item ); static_cast<TEXTE_MODULE*>( converted )->SetLocalCoord(); break; case PCB_LINE_T: converted = new EDGE_MODULE( m_board->m_Modules ); // Copy coordinates, layer, etc. *static_cast<DRAWSEGMENT*>( converted ) = *static_cast<DRAWSEGMENT*>( item ); static_cast<EDGE_MODULE*>( converted )->SetLocalCoord(); break; default: assert( false ); break; } delete item; if( converted ) { m_board->m_Modules->Add( converted ); m_view->Add( converted ); } } } else // !m_editModules case { PICKED_ITEMS_LIST picklist; for( KIGFX::VIEW_GROUP::iter it = preview.Begin(), end = preview.End(); it != end; ++it ) { BOARD_ITEM* item = static_cast<BOARD_ITEM*>( *it ); m_board->Add( item ); ITEM_PICKER itemWrapper( item, UR_NEW ); picklist.PushItem( itemWrapper ); m_view->Add( item ); } m_frame->SaveCopyInUndoList( picklist, UR_NEW ); } m_frame->OnModify(); break; } } preview.Clear(); m_controls->ShowCursor( false ); m_controls->SetSnapping( false ); m_controls->SetAutoPan( false ); m_controls->CaptureCursor( false ); m_view->Remove( &preview ); return 0; }
int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent ) { if( !m_frame->GetModel() ) return 0; DIALOG_DXF_IMPORT dlg( m_frame ); int dlgResult = dlg.ShowModal(); const std::list<BOARD_ITEM*>& list = dlg.GetImportedItems(); if( dlgResult != wxID_OK || list.empty() ) return 0; VECTOR2I cursorPos = m_controls->GetCursorPosition(); VECTOR2I delta = cursorPos - list.front()->GetPosition(); // Add a VIEW_GROUP that serves as a preview for the new item SELECTION preview( m_view ); BOARD_COMMIT commit( m_frame ); // Build the undo list & add items to the current view for( auto item : list ) { assert( item->Type() == PCB_LINE_T || item->Type() == PCB_TEXT_T ); preview.Add( item ); } BOARD_ITEM* firstItem = preview.Front(); m_view->Add( &preview ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_controls->ShowCursor( true ); m_controls->SetSnapping( true ); SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::DXF ); Activate(); // Main loop: keep receiving events while( OPT_TOOL_EVENT evt = Wait() ) { cursorPos = m_controls->GetCursorPosition(); if( evt->IsMotion() ) { delta = cursorPos - firstItem->GetPosition(); for( auto item : preview ) item->Move( wxPoint( delta.x, delta.y ) ); m_view->Update( &preview ); } else if( evt->Category() == TC_COMMAND ) { // TODO it should be handled by EDIT_TOOL, so add items and select? if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) { for( auto item : preview ) item->Rotate( wxPoint( cursorPos.x, cursorPos.y ), m_frame->GetRotationAngle() ); m_view->Update( &preview ); } else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) { for( auto item : preview ) item->Flip( wxPoint( cursorPos.x, cursorPos.y ) ); m_view->Update( &preview ); } else if( evt->IsCancel() || evt->IsActivate() ) { preview.FreeItems(); break; } } else if ( evt->IsClick( BUT_RIGHT ) ) { showContextMenu(); } else if( evt->IsClick( BUT_LEFT ) ) { // Place the drawing BOARD_ITEM_CONTAINER* parent = m_frame->GetModel(); for( auto item : preview ) { if( m_editModules ) { // Modules use different types for the same things, // so we need to convert imported items to appropriate classes. BOARD_ITEM* converted = NULL; switch( item->Type() ) { case PCB_TEXT_T: { TEXTE_PCB* text = static_cast<TEXTE_PCB*>( item ); TEXTE_MODULE* textMod = new TEXTE_MODULE( (MODULE*) parent ); // Assignment operator also copies the item PCB_TEXT_T type, // so it cannot be added to a module which handles PCB_MODULE_TEXT_T textMod->SetPosition( text->GetPosition() ); textMod->SetText( text->GetText() ); textMod->SetSize( text->GetSize() ); textMod->SetThickness( text->GetThickness() ); textMod->SetOrientation( text->GetOrientation() ); textMod->SetTextPosition( text->GetTextPosition() ); textMod->SetSize( text->GetSize() ); textMod->SetMirrored( text->IsMirrored() ); textMod->SetAttributes( text->GetAttributes() ); textMod->SetItalic( text->IsItalic() ); textMod->SetBold( text->IsBold() ); textMod->SetHorizJustify( text->GetHorizJustify() ); textMod->SetVertJustify( text->GetVertJustify() ); textMod->SetMultilineAllowed( text->IsMultilineAllowed() ); converted = textMod; break; } case PCB_LINE_T: { DRAWSEGMENT* seg = static_cast<DRAWSEGMENT*>( item ); EDGE_MODULE* modSeg = new EDGE_MODULE( (MODULE*) parent ); // Assignment operator also copies the item PCB_LINE_T type, // so it cannot be added to a module which handles PCB_MODULE_EDGE_T modSeg->SetWidth( seg->GetWidth() ); modSeg->SetStart( seg->GetStart() ); modSeg->SetEnd( seg->GetEnd() ); modSeg->SetAngle( seg->GetAngle() ); modSeg->SetShape( seg->GetShape() ); modSeg->SetType( seg->GetType() ); modSeg->SetBezControl1( seg->GetBezControl1() ); modSeg->SetBezControl2( seg->GetBezControl2() ); modSeg->SetBezierPoints( seg->GetBezierPoints() ); modSeg->SetPolyPoints( seg->GetPolyPoints() ); converted = modSeg; break; } default: assert( false ); break; } if( converted ) converted->SetLayer( item->GetLayer() ); delete item; item = converted; } if( item ) commit.Add( item ); } commit.Push( _( "Place a DXF drawing" ) ); break; } } preview.Clear(); m_controls->ShowCursor( false ); m_controls->SetSnapping( false ); m_controls->SetAutoPan( false ); m_controls->CaptureCursor( false ); m_view->Remove( &preview ); return 0; }
int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent ) { BOARD_ITEM* text = NULL; const BOARD_DESIGN_SETTINGS& dsnSettings = m_frame->GetDesignSettings(); BOARD_COMMIT commit( m_frame ); // Add a VIEW_GROUP that serves as a preview for the new item SELECTION preview( m_view ); m_view->Add( &preview ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_controls->ShowCursor( true ); m_controls->SetSnapping( true ); // do not capture or auto-pan until we start placing some text SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::TEXT ); Activate(); m_frame->SetToolID( m_editModules ? ID_MODEDIT_TEXT_TOOL : ID_PCB_ADD_TEXT_BUTT, wxCURSOR_PENCIL, _( "Add text" ) ); // Main loop: keep receiving events while( OPT_TOOL_EVENT evt = Wait() ) { VECTOR2I cursorPos = m_controls->GetCursorPosition(); if( evt->IsCancel() || evt->IsActivate() ) { if( text ) { // Delete the old text and have another try delete text; text = NULL; preview.Clear(); m_controls->SetAutoPan( false ); m_controls->CaptureCursor( false ); m_controls->ShowCursor( true ); } else break; if( evt->IsActivate() ) // now finish unconditionally break; } else if( text && evt->Category() == TC_COMMAND ) { if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) { text->Rotate( text->GetPosition(), m_frame->GetRotationAngle() ); m_view->Update( &preview ); } // TODO rotate CCW else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) { text->Flip( text->GetPosition() ); m_view->Update( &preview ); } } else if ( evt->IsClick( BUT_RIGHT ) ) { showContextMenu(); } else if( evt->IsClick( BUT_LEFT ) ) { if( !text ) { // Init the new item attributes if( m_editModules ) { TEXTE_MODULE* textMod = new TEXTE_MODULE( (MODULE*) m_frame->GetModel() ); textMod->SetLayer( m_frame->GetActiveLayer() ); textMod->SetSize( dsnSettings.m_ModuleTextSize ); textMod->SetThickness( dsnSettings.m_ModuleTextWidth ); textMod->SetTextPosition( wxPoint( cursorPos.x, cursorPos.y ) ); DialogEditModuleText textDialog( m_frame, textMod, NULL ); bool placing; RunMainStack( [&]() { placing = textDialog.ShowModal() && ( textMod->GetText().Length() > 0 ); } ); if( placing ) text = textMod; else delete textMod; } else { TEXTE_PCB* textPcb = new TEXTE_PCB( m_frame->GetModel() ); // TODO we have to set IS_NEW, otherwise InstallTextPCB.. creates an undo entry :| LEGACY_CLEANUP textPcb->SetFlags( IS_NEW ); LAYER_ID layer = m_frame->GetActiveLayer(); textPcb->SetLayer( layer ); // Set the mirrored option for layers on the BACK side of the board if( IsBackLayer( layer ) ) textPcb->SetMirrored( true ); textPcb->SetSize( dsnSettings.m_PcbTextSize ); textPcb->SetThickness( dsnSettings.m_PcbTextWidth ); textPcb->SetTextPosition( wxPoint( cursorPos.x, cursorPos.y ) ); RunMainStack( [&]() { getEditFrame<PCB_EDIT_FRAME>()->InstallTextPCBOptionsFrame( textPcb, NULL ); } ); if( textPcb->GetText().IsEmpty() ) delete textPcb; else text = textPcb; } if( text == NULL ) continue; m_controls->CaptureCursor( true ); m_controls->SetAutoPan( true ); //m_controls->ShowCursor( false ); preview.Add( text ); } else { //assert( text->GetText().Length() > 0 ); //assert( text->GetSize().x > 0 && text->GetSize().y > 0 ); text->ClearFlags(); preview.Remove( text ); commit.Add( text ); commit.Push( _( "Place a text" ) ); m_controls->CaptureCursor( false ); m_controls->SetAutoPan( false ); m_controls->ShowCursor( true ); text = NULL; } } else if( text && evt->IsMotion() ) { text->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); // Show a preview of the item m_view->Update( &preview ); } } m_controls->ShowCursor( false ); m_controls->SetSnapping( false ); m_controls->SetAutoPan( false ); m_controls->CaptureCursor( false ); m_view->Remove( &preview ); m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); return 0; }