int EDIT_TOOL::Rotate( TOOL_EVENT& aEvent ) { const SELECTION& selection = m_selectionTool->GetSelection(); PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>(); // Shall the selection be cleared at the end? bool unselect = selection.Empty(); if( !makeSelection( selection ) || m_selectionTool->CheckLock() ) { setTransitions(); return 0; } wxPoint rotatePoint = getModificationPoint( selection ); if( !m_dragging ) // If it is being dragged, then it is already saved with UR_CHANGED flag { editFrame->OnModify(); editFrame->SaveCopyInUndoList( selection.items, UR_ROTATED, rotatePoint ); } for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) { BOARD_ITEM* item = selection.Item<BOARD_ITEM>( i ); item->Rotate( rotatePoint, editFrame->GetRotationAngle() ); if( !m_dragging ) item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); } updateRatsnest( m_dragging ); // Update dragging offset (distance between cursor and the first dragged item) m_offset = static_cast<BOARD_ITEM*>( selection.items.GetPickedItem( 0 ) )->GetPosition() - rotatePoint; if( m_dragging ) selection.group->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); else getModel<BOARD>()->GetRatsnest()->Recalculate(); if( unselect ) m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_toolMgr->RunAction( COMMON_ACTIONS::pointEditorUpdate, true ); setTransitions(); return 0; }
int EDIT_TOOL::editFootprintInFpEditor( const TOOL_EVENT& aEvent ) { const SELECTION& selection = m_selectionTool->GetSelection(); bool unselect = selection.Empty(); if( !hoverSelection( selection ) ) return 0; MODULE* mod = uniqueSelected<MODULE>(); if( !mod ) return 0; PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>(); editFrame-> SetCurItem( mod ); if( editFrame->GetCurItem()->GetTimeStamp() == 0 ) // Module Editor needs a non null timestamp { editFrame->GetCurItem()->SetTimeStamp( GetNewTimeStamp() ); editFrame->OnModify(); } FOOTPRINT_EDIT_FRAME* editor = (FOOTPRINT_EDIT_FRAME*) editFrame->Kiway().Player( FRAME_PCB_MODULE_EDITOR, true ); editor->Load_Module_From_BOARD( (MODULE*) editFrame->GetCurItem() ); editFrame->SetCurItem( NULL ); // the current module could be deleted by editor->Show( true ); editor->Raise(); // Iconize( false ); if( unselect ) m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); return 0; }
int EDIT_TOOL::Properties( const TOOL_EVENT& aEvent ) { const SELECTION& selection = m_selectionTool->GetSelection(); PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>(); // Shall the selection be cleared at the end? bool unselect = selection.Empty(); if( !hoverSelection( selection, false ) ) return 0; // Tracks & vias are treated in a special way: if( ( SELECTION_CONDITIONS::OnlyTypes( m_tracksViasType ) )( selection ) ) { DIALOG_TRACK_VIA_PROPERTIES dlg( editFrame, selection ); if( dlg.ShowModal() ) { RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest(); editFrame->OnModify(); editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED ); dlg.Apply(); selection.ForAll<KIGFX::VIEW_ITEM>( boost::bind( &KIGFX::VIEW_ITEM::ViewUpdate, _1, KIGFX::VIEW_ITEM::ALL ) ); selection.ForAll<BOARD_ITEM>( boost::bind( &RN_DATA::Update, ratsnest, _1 ) ); ratsnest->Recalculate(); } } else if( selection.Size() == 1 ) // Properties are displayed when there is only one item selected { // Display properties dialog BOARD_ITEM* item = selection.Item<BOARD_ITEM>( 0 ); // Store the head of the undo list to compare if anything has changed std::vector<PICKED_ITEMS_LIST*>& undoList = editFrame->GetScreen()->m_UndoList.m_CommandsList; // Some of properties dialogs alter pointers, so we should deselect them m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); STATUS_FLAGS flags = item->GetFlags(); item->ClearFlags(); // It is necessary to determine if anything has changed, so store the current undo save point PICKED_ITEMS_LIST* undoSavePoint = undoList.empty() ? NULL : undoList.back(); // Display properties dialog provided by the legacy canvas frame editFrame->OnEditItemRequest( NULL, item ); if( !undoList.empty() && undoList.back() != undoSavePoint ) // Undo buffer has changed { // Process changes stored after undoSavePoint processUndoBuffer( undoSavePoint ); // Update the modified item item->ViewUpdate(); RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest(); ratsnest->Recalculate(); // TODO OBSERVER! I miss you so much.. m_toolMgr->RunAction( COMMON_ACTIONS::pointEditorUpdate, true ); } item->SetFlags( flags ); } if( unselect ) m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); return 0; }
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; }
int EDIT_TOOL::Main( TOOL_EVENT& aEvent ) { 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( !makeSelection( selection ) ) { setTransitions(); return 0; } Activate(); m_dragging = false; // Are selected items being dragged? bool restore = false; // Should items' state be restored when finishing the tool? // By default, modified items need to update their geometry m_updateFlag = KIGFX::VIEW_ITEM::GEOMETRY; KIGFX::VIEW_CONTROLS* controls = getViewControls(); PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>(); controls->ShowCursor( true ); controls->SetSnapping( true ); controls->ForceCursorPosition( false ); // Main loop: keep receiving events while( OPT_TOOL_EVENT evt = Wait() ) { 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; } // 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->IsMotion() || evt->IsDrag( BUT_LEFT ) ) { m_cursor = controls->GetCursorPosition(); if( m_dragging ) { wxPoint movement = wxPoint( m_cursor.x, m_cursor.y ) - selection.Item<BOARD_ITEM>( 0 )->GetPosition(); // 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 // Prepare to start dragging { if( m_selectionTool->CheckLock() || selection.Empty() ) break; // Save items, so changes can be undone editFrame->OnModify(); editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED ); 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 = VECTOR2I( selection.Item<BOARD_ITEM>( 0 )->GetPosition() ); m_offset.x = 0; m_offset.y = 0; } else { VECTOR2D origin; if( evt->IsDrag( BUT_LEFT ) ) origin = getView()->GetGAL()->GetGridPoint( evt->DragOrigin() ); else origin = getViewControls()->GetCursorPosition(); // Update dragging offset (distance between cursor and the first dragged item) m_offset = static_cast<BOARD_ITEM*>( selection.items.GetPickedItem( 0 ) )->GetPosition() - wxPoint( origin.x, origin.y ); } controls->SetAutoPan( true ); m_dragging = true; } selection.group->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); m_toolMgr->RunAction( COMMON_ACTIONS::pointEditorUpdate, true ); } else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) break; // Finish } 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->SetSnapping( false ); controls->SetAutoPan( false ); setTransitions(); return 0; }
int POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent ) { const SELECTION& selection = m_selectionTool->GetSelection(); if( selection.Size() == 1 ) { Activate(); KIGFX::VIEW_CONTROLS* controls = getViewControls(); KIGFX::VIEW* view = getView(); PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>(); EDA_ITEM* item = selection.items.GetPickedItem( 0 ); m_editPoints = EDIT_POINTS_FACTORY::Make( item, getView()->GetGAL() ); if( !m_editPoints ) return 0; view->Add( m_editPoints.get() ); m_editedPoint = NULL; bool modified = false; // Main loop: keep receiving events while( OPT_TOOL_EVENT evt = Wait() ) { if( !m_editPoints || evt->Matches( m_selectionTool->ClearedEvent ) || evt->Matches( m_selectionTool->UnselectedEvent ) || evt->Matches( m_selectionTool->SelectedEvent ) ) { break; } if( evt->IsMotion() ) { EDIT_POINT* point = m_editPoints->FindPoint( evt->Position() ); if( m_editedPoint != point ) setEditedPoint( point ); } else if( evt->IsAction( &COMMON_ACTIONS::pointEditorAddCorner ) ) { addCorner( controls->GetCursorPosition() ); updatePoints(); } else if( evt->IsAction( &COMMON_ACTIONS::pointEditorRemoveCorner ) ) { if( m_editedPoint ) { removeCorner( m_editedPoint ); updatePoints(); } } else if( evt->IsDrag( BUT_LEFT ) && m_editedPoint ) { if( !modified ) { // Save items, so changes can be undone editFrame->OnModify(); editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED ); controls->ForceCursorPosition( false ); m_original = *m_editedPoint; // Save the original position controls->SetAutoPan( true ); modified = true; } bool enableAltConstraint = !!evt->Modifier( MD_CTRL ); if( enableAltConstraint != (bool) m_altConstraint ) // alternative constraint setAltConstraint( enableAltConstraint ); m_editedPoint->SetPosition( controls->GetCursorPosition() ); if( m_altConstraint ) m_altConstraint->Apply(); else m_editedPoint->ApplyConstraint(); updateItem(); updatePoints(); m_editPoints->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); } else if( evt->IsAction( &COMMON_ACTIONS::pointEditorUpdate ) ) { updatePoints(); } else if( evt->IsMouseUp( BUT_LEFT ) ) { controls->SetAutoPan( false ); setAltConstraint( false ); modified = false; m_toolMgr->PassEvent(); } else if( evt->IsCancel() ) { if( modified ) // Restore the last change { wxCommandEvent dummy; editFrame->RestoreCopyFromUndoList( dummy ); updatePoints(); modified = false; } // Let the selection tool receive the event too m_toolMgr->PassEvent(); break; } else { m_toolMgr->PassEvent(); } } if( m_editPoints ) { finishItem(); item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); view->Remove( m_editPoints.get() ); m_editPoints.reset(); } controls->ShowCursor( false ); controls->SetAutoPan( false ); controls->SetSnapping( false ); controls->ForceCursorPosition( false ); } return 0; }