diff --git a/eeschema/tools/ee_actions.cpp b/eeschema/tools/ee_actions.cpp index c1e3211517..7fcc150178 100644 --- a/eeschema/tools/ee_actions.cpp +++ b/eeschema/tools/ee_actions.cpp @@ -715,3 +715,7 @@ TOOL_ACTION EE_ACTIONS::moveActivate( "eeschema.InteractiveMove", TOOL_ACTION EE_ACTIONS::symbolMoveActivate( "eeschema.SymbolMoveTool", AS_GLOBAL, 0, "", _( "Symbol Move Activate" ), "", move_xpm, AF_ACTIVATE ); + +TOOL_ACTION EE_ACTIONS::alignToGrid( "eeschema.AlignToGrid", + AS_GLOBAL, 0, "", + _( "Align Elements to Grid" ), "", move_xpm, AF_ACTIVATE ); diff --git a/eeschema/tools/ee_actions.h b/eeschema/tools/ee_actions.h index 109d779e48..777e2ed562 100644 --- a/eeschema/tools/ee_actions.h +++ b/eeschema/tools/ee_actions.h @@ -108,6 +108,7 @@ public: static TOOL_ACTION finishDrawing; // Interactive Editing + static TOOL_ACTION alignToGrid; static TOOL_ACTION symbolMoveActivate; // Symbol editor move tool activate static TOOL_ACTION moveActivate; // Schematic editor move tool activate static TOOL_ACTION move; diff --git a/eeschema/tools/ee_grid_helper.cpp b/eeschema/tools/ee_grid_helper.cpp index c28149094d..2d8d83a54d 100644 --- a/eeschema/tools/ee_grid_helper.cpp +++ b/eeschema/tools/ee_grid_helper.cpp @@ -105,17 +105,25 @@ void EE_GRID_HELPER::SetAuxAxes( bool aEnable, const VECTOR2I& aOrigin ) } -VECTOR2I EE_GRID_HELPER::Align( const VECTOR2I& aPoint ) const +VECTOR2I EE_GRID_HELPER::AlignGrid( const VECTOR2I& aPoint ) const { - if( !m_toolMgr->GetView()->GetGAL()->GetGridSnapping() ) - return aPoint; - const VECTOR2D gridOffset( GetOrigin() ); const VECTOR2D grid( GetGrid() ); VECTOR2I nearest( KiROUND( ( aPoint.x - gridOffset.x ) / grid.x ) * grid.x + gridOffset.x, KiROUND( ( aPoint.y - gridOffset.y ) / grid.y ) * grid.y + gridOffset.y ); + return nearest; +} + + +VECTOR2I EE_GRID_HELPER::Align( const VECTOR2I& aPoint ) const +{ + if( !m_toolMgr->GetView()->GetGAL()->GetGridSnapping() ) + return aPoint; + + VECTOR2I nearest = AlignGrid( aPoint ); + if( !m_auxAxis ) return nearest; diff --git a/eeschema/tools/ee_grid_helper.h b/eeschema/tools/ee_grid_helper.h index 04472b6c7c..fb8fe92d40 100644 --- a/eeschema/tools/ee_grid_helper.h +++ b/eeschema/tools/ee_grid_helper.h @@ -56,6 +56,8 @@ public: VECTOR2I Align( const VECTOR2I& aPoint ) const; + VECTOR2I AlignGrid( const VECTOR2I& aPoint ) const; + VECTOR2I AlignToWire( const VECTOR2I& aPoint, const SEG& aSeg ); VECTOR2I BestDragOrigin( const VECTOR2I& aMousePos, std::vector& aItem ); diff --git a/eeschema/tools/sch_move_tool.cpp b/eeschema/tools/sch_move_tool.cpp index dc91921570..88b33b8a53 100644 --- a/eeschema/tools/sch_move_tool.cpp +++ b/eeschema/tools/sch_move_tool.cpp @@ -74,11 +74,33 @@ bool SCH_MOVE_TOOL::Init() selToolMenu.AddItem( EE_ACTIONS::move, moveCondition, 150 ); selToolMenu.AddItem( EE_ACTIONS::drag, moveCondition, 150 ); + selToolMenu.AddItem( EE_ACTIONS::alignToGrid, moveCondition, 150 ); return true; } +static const KICAD_T movableItems[] = +{ + SCH_MARKER_T, + SCH_JUNCTION_T, + SCH_NO_CONNECT_T, + SCH_BUS_BUS_ENTRY_T, + SCH_BUS_WIRE_ENTRY_T, + SCH_LINE_T, + SCH_BITMAP_T, + SCH_TEXT_T, + SCH_LABEL_T, + SCH_GLOBAL_LABEL_T, + SCH_HIER_LABEL_T, + SCH_FIELD_T, + SCH_COMPONENT_T, + SCH_SHEET_PIN_T, + SCH_SHEET_T, + EOT +}; + + /* TODO - Tom/Jeff - add preferences option "Move origin: always cursor / item origin" - add preferences option "Default drag action: drag items / move" @@ -88,26 +110,6 @@ bool SCH_MOVE_TOOL::Init() int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent ) { - const KICAD_T movableItems[] = - { - SCH_MARKER_T, - SCH_JUNCTION_T, - SCH_NO_CONNECT_T, - SCH_BUS_BUS_ENTRY_T, - SCH_BUS_WIRE_ENTRY_T, - SCH_LINE_T, - SCH_BITMAP_T, - SCH_TEXT_T, - SCH_LABEL_T, - SCH_GLOBAL_LABEL_T, - SCH_HIER_LABEL_T, - SCH_FIELD_T, - SCH_COMPONENT_T, - SCH_SHEET_PIN_T, - SCH_SHEET_T, - EOT - }; - EESCHEMA_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings(); KIGFX::VIEW_CONTROLS* controls = getViewControls(); EE_GRID_HELPER grid( m_toolMgr ); @@ -497,7 +499,7 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aOriginalItem, wxPoint aPoi for( SCH_ITEM *test : items.Overlapping( aOriginalItem->GetBoundingBox() ) ) { - if( test->IsSelected() || !test->CanConnect( aOriginalItem ) ) + if( test == aOriginalItem || test->IsSelected() || !test->CanConnect( aOriginalItem ) ) continue; KICAD_T testType = test->Type(); @@ -618,7 +620,7 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aOriginalItem, wxPoint aPoi else otherEnd = ends[0]; - getConnectedDragItems( (SCH_ITEM*) test, otherEnd, m_dragAdditions ); + getConnectedDragItems( test, otherEnd, aList ); } break; } @@ -705,9 +707,106 @@ void SCH_MOVE_TOOL::moveItem( EDA_ITEM* aItem, const VECTOR2I& aDelta ) } +int SCH_MOVE_TOOL::AlignElements( const TOOL_EVENT& aEvent ) +{ + EE_GRID_HELPER grid( m_toolMgr); + EE_SELECTION& selection = m_selectionTool->RequestSelection( movableItems ); + bool append_undo = false; + + for( EDA_ITEM* item : selection ) + { + if( item->Type() == SCH_LINE_T ) + { + SCH_LINE* line = static_cast( item ); + std::vector flags{ STARTPOINT, ENDPOINT }; + std::vector pts{ line->GetStartPoint(), line->GetEndPoint() }; + + for( int ii = 0; ii < 2; ++ii ) + { + EDA_ITEMS drag_items{ item }; + line->ClearFlags(); + line->SetFlags( flags[ii] ); + getConnectedDragItems( line, pts[ii], drag_items ); + std::set unique_items( drag_items.begin(), drag_items.end() ); + + VECTOR2I gridpt = grid.AlignGrid( pts[ii] ) - pts[ii]; + + if( gridpt != VECTOR2I( 0, 0 ) ) + { + for( auto dritem : unique_items ) + { + if( dritem->GetParent() && dritem->GetParent()->IsSelected() ) + continue; + + saveCopyInUndoList( dritem, UNDO_REDO::CHANGED, append_undo ); + append_undo = true; + + moveItem( dritem, gridpt ); + updateView( dritem ); + } + } + + } + } + else + { + std::vector connections; + EDA_ITEMS drag_items{ item }; + connections = static_cast( item )->GetConnectionPoints(); + + for( wxPoint point : connections ) + getConnectedDragItems( static_cast( item ), point, drag_items ); + + std::map shifts; + VECTOR2I most_common( 0, 0 ); + int max_count = 0; + + for( auto& conn : connections ) + { + VECTOR2I gridpt = grid.AlignGrid( conn ) - conn; + + shifts[gridpt]++; + + if( shifts[gridpt] > max_count ) + { + most_common = gridpt; + max_count = shifts[most_common]; + } + } + + if( most_common != VECTOR2I( 0, 0 ) ) + { + for( auto dritem : drag_items ) + { + if( dritem->GetParent() && dritem->GetParent()->IsSelected() ) + continue; + + saveCopyInUndoList( dritem, UNDO_REDO::CHANGED, append_undo ); + append_undo = true; + + moveItem( dritem, most_common ); + updateView( dritem ); + } + } + } + } + + + m_toolMgr->PostEvent( EVENTS::SelectedItemsMoved ); + m_toolMgr->RunAction( EE_ACTIONS::addNeededJunctions, true, &selection ); + + m_frame->SchematicCleanUp(); + m_frame->TestDanglingEnds(); + + m_frame->OnModify(); + return 0; +} + + void SCH_MOVE_TOOL::setTransitions() { Go( &SCH_MOVE_TOOL::Main, EE_ACTIONS::moveActivate.MakeEvent() ); Go( &SCH_MOVE_TOOL::Main, EE_ACTIONS::move.MakeEvent() ); Go( &SCH_MOVE_TOOL::Main, EE_ACTIONS::drag.MakeEvent() ); + Go( &SCH_MOVE_TOOL::AlignElements, EE_ACTIONS::alignToGrid.MakeEvent() ); } diff --git a/eeschema/tools/sch_move_tool.h b/eeschema/tools/sch_move_tool.h index 1362c0f8e3..a9cc771b18 100644 --- a/eeschema/tools/sch_move_tool.h +++ b/eeschema/tools/sch_move_tool.h @@ -50,12 +50,17 @@ public: bool Init() override; /** - * Function Main() - * * Runs an interactive move of the selected items, or the item under the cursor. */ int Main( const TOOL_EVENT& aEvent ); + /** + * Aligns selected elements to the grid + * @param aEvent current event that activated the tool + * @return 0 + */ + int AlignElements( const TOOL_EVENT& aEvent ); + private: void moveItem( EDA_ITEM* aItem, const VECTOR2I& aDelta );