From 20b63174dca6c8678c635077b4d44913db537aa1 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Thu, 2 May 2019 11:59:36 +0100 Subject: [PATCH] Support wire & bus drawing from selection tool. --- eeschema/tools/sch_drawing_tool.cpp | 170 +++++++++-------- eeschema/tools/sch_drawing_tool.h | 9 +- eeschema/tools/sch_edit_tool.cpp | 247 ++++++++++--------------- eeschema/tools/sch_inspection_tool.cpp | 19 +- eeschema/tools/sch_selection_tool.cpp | 72 +++++-- eeschema/tools/sch_selection_tool.h | 13 ++ include/tool/selection.h | 2 +- 7 files changed, 271 insertions(+), 261 deletions(-) diff --git a/eeschema/tools/sch_drawing_tool.cpp b/eeschema/tools/sch_drawing_tool.cpp index f7c96b098c..a24c59c8df 100644 --- a/eeschema/tools/sch_drawing_tool.cpp +++ b/eeschema/tools/sch_drawing_tool.cpp @@ -61,7 +61,7 @@ TOOL_ACTION SCH_ACTIONS::placePower( "eeschema.InteractiveDrawing.placePowerPort TOOL_ACTION SCH_ACTIONS::startWire( "eeschema.InteractiveDrawing.startWire", AS_GLOBAL, 0, - _( "Begin Wire" ), _( "Start drawing a wire" ), + _( "Start Wire" ), _( "Start drawing a wire" ), add_line_xpm, AF_ACTIVATE ); TOOL_ACTION SCH_ACTIONS::drawWire( "eeschema.InteractiveDrawing.drawWire", @@ -71,7 +71,7 @@ TOOL_ACTION SCH_ACTIONS::drawWire( "eeschema.InteractiveDrawing.drawWire", TOOL_ACTION SCH_ACTIONS::startBus( "eeschema.InteractiveDrawing.startBus", AS_GLOBAL, 0, - _( "Begin Bus" ), _( "Start drawing a bus" ), + _( "Start Bus" ), _( "Start drawing a bus" ), add_bus_xpm, AF_ACTIVATE ); TOOL_ACTION SCH_ACTIONS::drawBus( "eeschema.InteractiveDrawing.drawBus", @@ -214,80 +214,71 @@ bool SCH_DRAWING_TOOL::Init() m_frame = getEditFrame(); m_selectionTool = m_toolMgr->GetTool(); - auto activeToolCondition = [ this ] ( const SELECTION& aSel ) { + auto activeTool = [ this ] ( const SELECTION& aSel ) { return ( m_frame->GetToolId() != ID_NO_TOOL_SELECTED ); }; - auto wireToolCondition = [ this ] ( const SELECTION& aSel ) { - return ( m_frame->GetToolId() == ID_WIRE_BUTT ); + auto wireOrBusTool = [ this ] ( const SELECTION& aSel ) { + return ( m_frame->GetToolId() == ID_WIRE_BUTT || m_frame->GetToolId() == ID_BUS_BUTT ); }; - auto busToolCondition = [ this ] ( const SELECTION& aSel ) { - return ( m_frame->GetToolId() == ID_BUS_BUTT ); - }; - - auto lineToolCondition = [ this ] ( const SELECTION& aSel ) { + auto lineTool = [ this ] ( const SELECTION& aSel ) { return ( m_frame->GetToolId() == ID_LINE_COMMENT_BUTT ); }; - auto sheetToolCondition = [ this ] ( const SELECTION& aSel ) { + auto sheetTool = [ this ] ( const SELECTION& aSel ) { return ( m_frame->GetToolId() == ID_SHEET_SYMBOL_BUTT ); }; - auto idleCondition = [] ( const SELECTION& aSel ) { - SCH_ITEM* item = (SCH_ITEM*) aSel.Front(); - return ( !item || !item->GetEditFlags() ); - }; - - auto idleBusOrLineToolCondition = ( busToolCondition || lineToolCondition ) && idleCondition; - auto wireOrBusSelectionCondition = SELECTION_CONDITIONS::MoreThan( 0 ) && SELECTION_CONDITIONS::OnlyTypes( wireOrBusTypes ); - auto drawingSegmentsCondition = [] ( const SELECTION& aSel ) { - SCH_ITEM* item = (SCH_ITEM*) aSel.Front(); - return ( item && item->Type() == SCH_LINE_T && item->IsNew() ); - }; - auto singleSheetCondition = SELECTION_CONDITIONS::Count( 1 ) && SELECTION_CONDITIONS::OnlyType( SCH_SHEET_T ); auto& ctxMenu = m_menu.GetMenu(); - // cancel current tool goes in main context menu at the top if present - ctxMenu.AddItem( ACTIONS::cancelInteractive, activeToolCondition, 1 ); + // + // Build the drawing tool menu + // + ctxMenu.AddItem( ACTIONS::cancelInteractive, activeTool, 1 ); - ctxMenu.AddItem( SCH_ACTIONS::startWire, wireToolCondition && idleCondition, 1 ); - ctxMenu.AddItem( SCH_ACTIONS::startBus, busToolCondition && idleCondition, 1 ); - ctxMenu.AddItem( SCH_ACTIONS::startLines, lineToolCondition && idleCondition, 1 ); - ctxMenu.AddItem( SCH_ACTIONS::finishWire, wireToolCondition && drawingSegmentsCondition, 1 ); - ctxMenu.AddItem( SCH_ACTIONS::finishBus, busToolCondition && drawingSegmentsCondition, 1 ); - ctxMenu.AddItem( SCH_ACTIONS::finishLine, lineToolCondition && drawingSegmentsCondition, 1 ); + ctxMenu.AddItem( SCH_ACTIONS::startWire, wireOrBusTool && SCH_CONDITIONS::Idle, 1 ); + ctxMenu.AddItem( SCH_ACTIONS::startBus, wireOrBusTool && SCH_CONDITIONS::Idle, 1 ); + ctxMenu.AddItem( SCH_ACTIONS::startLines, lineTool && SCH_CONDITIONS::Idle, 1 ); + ctxMenu.AddItem( SCH_ACTIONS::finishWire, IsDrawingWire, 1 ); + ctxMenu.AddItem( SCH_ACTIONS::finishBus, IsDrawingBus, 1 ); + ctxMenu.AddItem( SCH_ACTIONS::finishLine, IsDrawingLine, 1 ); // TODO(JE): add menu access to unfold bus... - ctxMenu.AddItem( SCH_ACTIONS::resizeSheet, sheetToolCondition && idleCondition, 1 ); + ctxMenu.AddItem( SCH_ACTIONS::resizeSheet, sheetTool && SCH_CONDITIONS::Idle, 1 ); - ctxMenu.AddSeparator( idleBusOrLineToolCondition, 100 ); - ctxMenu.AddItem( SCH_ACTIONS::addJunction, idleBusOrLineToolCondition, 100 ); - ctxMenu.AddItem( SCH_ACTIONS::addLabel, idleBusOrLineToolCondition, 100 ); - ctxMenu.AddItem( SCH_ACTIONS::addGlobalLabel, idleBusOrLineToolCondition, 100 ); - ctxMenu.AddItem( SCH_ACTIONS::addHierLabel, idleBusOrLineToolCondition, 100 ); + ctxMenu.AddSeparator( wireOrBusTool && SCH_CONDITIONS::Idle, 100 ); + ctxMenu.AddItem( SCH_ACTIONS::addJunction, wireOrBusTool && SCH_CONDITIONS::Idle, 100 ); + ctxMenu.AddItem( SCH_ACTIONS::addLabel, wireOrBusTool && SCH_CONDITIONS::Idle, 100 ); + ctxMenu.AddItem( SCH_ACTIONS::addGlobalLabel, wireOrBusTool && SCH_CONDITIONS::Idle, 100 ); + ctxMenu.AddItem( SCH_ACTIONS::addHierLabel, wireOrBusTool && SCH_CONDITIONS::Idle, 100 ); - ctxMenu.AddSeparator( activeToolCondition, 1000 ); + ctxMenu.AddSeparator( activeTool, 1000 ); m_menu.AddStandardSubMenus( m_frame ); - // Add editing actions to the selection tool menu + // + // Add drawing actions to the selection tool menu // CONDITIONAL_MENU& selToolMenu = m_selectionTool->GetToolMenu().GetMenu(); // TODO(JE): add menu access to unfold bus on busSelectionCondition... - selToolMenu.AddItem( SCH_ACTIONS::resizeSheet, singleSheetCondition, 1 ); - selToolMenu.AddItem( SCH_ACTIONS::addJunction, wireOrBusSelectionCondition, 100 ); - selToolMenu.AddItem( SCH_ACTIONS::addLabel, wireOrBusSelectionCondition, 100 ); + selToolMenu.AddItem( SCH_ACTIONS::startWire, SCH_CONDITIONS::Empty, 1 ); + selToolMenu.AddItem( SCH_ACTIONS::startBus, SCH_CONDITIONS::Empty, 1 ); + selToolMenu.AddItem( SCH_ACTIONS::finishWire, IsDrawingWire, 1 ); + selToolMenu.AddItem( SCH_ACTIONS::finishBus, IsDrawingBus, 1 ); + + selToolMenu.AddItem( SCH_ACTIONS::addJunction, wireOrBusSelectionCondition, 100 ); + selToolMenu.AddItem( SCH_ACTIONS::addLabel, wireOrBusSelectionCondition, 100 ); selToolMenu.AddItem( SCH_ACTIONS::addGlobalLabel, wireOrBusSelectionCondition, 100 ); - selToolMenu.AddItem( SCH_ACTIONS::addHierLabel, wireOrBusSelectionCondition, 100 ); + selToolMenu.AddItem( SCH_ACTIONS::addHierLabel, wireOrBusSelectionCondition, 100 ); selToolMenu.AddItem( SCH_ACTIONS::importSheetPin, singleSheetCondition, 100 ); return true; @@ -303,6 +294,42 @@ void SCH_DRAWING_TOOL::Reset( RESET_REASON aReason ) } +static bool isNewSegment( SCH_ITEM* aItem ) +{ + return aItem && aItem->IsNew() && aItem->Type() == SCH_LINE_T; +} + + +bool SCH_DRAWING_TOOL::IsDrawingLine( const SELECTION& aSelection ) +{ + static KICAD_T wireOrBusTypes[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT }; + return IsDrawingLineWireOrBus( aSelection ) && !aSelection.Front()->IsType( wireOrBusTypes ); +} + + +bool SCH_DRAWING_TOOL::IsDrawingWire( const SELECTION& aSelection ) +{ + static KICAD_T wireType[] = { SCH_LINE_LOCATE_WIRE_T, EOT }; + return IsDrawingLineWireOrBus( aSelection ) && aSelection.Front()->IsType( wireType ); +} + + +bool SCH_DRAWING_TOOL::IsDrawingBus( const SELECTION& aSelection ) +{ + static KICAD_T busType[] = { SCH_LINE_LOCATE_BUS_T, EOT }; + return IsDrawingLineWireOrBus( aSelection ) && aSelection.Front()->IsType( busType ); +} + + +bool SCH_DRAWING_TOOL::IsDrawingLineWireOrBus( const SELECTION& aSelection ) +{ + // NOTE: for immediate hotkeys, it is NOT required that the line, wire or bus tool + // be selected + SCH_ITEM* item = (SCH_ITEM*) aSelection.Front(); + return isNewSegment( item ); +} + + int SCH_DRAWING_TOOL::AddJunction( const TOOL_EVENT& aEvent ) { m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true ); @@ -315,42 +342,21 @@ int SCH_DRAWING_TOOL::AddJunction( const TOOL_EVENT& aEvent ) int SCH_DRAWING_TOOL::AddLabel( const TOOL_EVENT& aEvent ) -{ - return doAddItem( SCH_LABEL_T ); -} - - -int SCH_DRAWING_TOOL::AddGlobalLabel( const TOOL_EVENT& aEvent ) -{ - return doAddItem( SCH_GLOBAL_LABEL_T ); -} - - -int SCH_DRAWING_TOOL::AddHierLabel( const TOOL_EVENT& aEvent ) -{ - return doAddItem( SCH_HIER_LABEL_T ); -} - - -int SCH_DRAWING_TOOL::doAddItem( KICAD_T aType ) { m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true ); - SCH_ITEM* item = nullptr; + int layer = LAYER_NOTES; - switch( aType ) - { - case SCH_LABEL_T: item = m_frame->CreateNewText( LAYER_LOCLABEL ); break; - case SCH_GLOBAL_LABEL_T: item = m_frame->CreateNewText( LAYER_GLOBLABEL ); break; - case SCH_HIER_LABEL_T: item = m_frame->CreateNewText( LAYER_HIERLABEL ); break; - case SCH_TEXT_T: item = m_frame->CreateNewText( LAYER_NOTES ); break; - default: wxFAIL_MSG( "doAddItem(): unknown type" ); - } + if( aEvent.IsAction( &SCH_ACTIONS::addLabel ) ) + layer = LAYER_LOCLABEL; + else if( aEvent.IsAction( &SCH_ACTIONS::addGlobalLabel ) ) + layer = LAYER_GLOBLABEL; + else if( aEvent.IsAction( &SCH_ACTIONS::addHierLabel ) ) + layer = LAYER_HIERLABEL; + SCH_ITEM* item = m_frame->CreateNewText( layer ); m_frame->AddItemToScreenAndUndoList( item ); - m_frame->SetNoToolSelected(); - return 0; } @@ -886,7 +892,6 @@ int SCH_DRAWING_TOOL::doTwoClickPlace( KICAD_T aType ) int SCH_DRAWING_TOOL::StartWire( const TOOL_EVENT& aEvent ) { - m_frame->SetToolID( ID_WIRE_BUTT, wxCURSOR_PENCIL, _( "Add wire" ) ); m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true ); m_frame->GetCanvas()->MoveCursorToCrossHair(); @@ -911,7 +916,6 @@ int SCH_DRAWING_TOOL::DrawWire( const TOOL_EVENT& aEvent ) int SCH_DRAWING_TOOL::StartBus( const TOOL_EVENT& aEvent ) { - m_frame->SetToolID( ID_BUS_BUTT, wxCURSOR_PENCIL, _( "Add bus" ) ); m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true ); m_frame->GetCanvas()->MoveCursorToCrossHair(); @@ -977,7 +981,6 @@ int SCH_DRAWING_TOOL::UnfoldBus( const TOOL_EVENT& aEvent ) int SCH_DRAWING_TOOL::StartLines( const TOOL_EVENT& aEvent) { - m_frame->SetToolID( ID_LINE_COMMENT_BUTT, wxCURSOR_PENCIL, _( "Add lines" ) ); m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true ); m_frame->GetCanvas()->MoveCursorToCrossHair(); @@ -1155,6 +1158,9 @@ int SCH_DRAWING_TOOL::doDrawSegments( int aType, SCH_LINE* aSegment ) finishSegments(); aSegment = nullptr; } + + if( m_frame->GetToolId() == ID_NO_TOOL_SELECTED ) + break; } else if( evt->IsClick( BUT_RIGHT ) ) { @@ -1189,6 +1195,9 @@ int SCH_DRAWING_TOOL::doDrawSegments( int aType, SCH_LINE* aSegment ) { finishSegments(); aSegment = nullptr; + + if( m_frame->GetToolId() == ID_NO_TOOL_SELECTED ) + break; } else { @@ -1208,6 +1217,9 @@ int SCH_DRAWING_TOOL::doDrawSegments( int aType, SCH_LINE* aSegment ) { finishSegments(); aSegment = nullptr; + + if( m_frame->GetToolId() == ID_NO_TOOL_SELECTED ) + break; } } else if( evt->IsMotion() ) @@ -1413,11 +1425,13 @@ void SCH_DRAWING_TOOL::finishSegments() // Add the new wires while( s_wires.GetFirst() ) + { + s_wires.GetFirst()->ClearFlags( IS_NEW | IS_MOVED ); m_frame->AddToScreen( s_wires.PopFront() ); + } m_view->ClearPreview(); m_view->ShowPreview( false ); - m_view->ClearHiddenFlags(); m_controls->CaptureCursor( false ); m_controls->SetAutoPan( false ); @@ -1651,6 +1665,6 @@ void SCH_DRAWING_TOOL::setTransitions() Go( &SCH_DRAWING_TOOL::StartLines, SCH_ACTIONS::startLines.MakeEvent() ); Go( &SCH_DRAWING_TOOL::AddJunction, SCH_ACTIONS::addJunction.MakeEvent() ); Go( &SCH_DRAWING_TOOL::AddLabel, SCH_ACTIONS::addLabel.MakeEvent() ); - Go( &SCH_DRAWING_TOOL::AddGlobalLabel, SCH_ACTIONS::addGlobalLabel.MakeEvent() ); - Go( &SCH_DRAWING_TOOL::AddHierLabel, SCH_ACTIONS::addHierLabel.MakeEvent() ); + Go( &SCH_DRAWING_TOOL::AddLabel, SCH_ACTIONS::addGlobalLabel.MakeEvent() ); + Go( &SCH_DRAWING_TOOL::AddLabel, SCH_ACTIONS::addHierLabel.MakeEvent() ); } diff --git a/eeschema/tools/sch_drawing_tool.h b/eeschema/tools/sch_drawing_tool.h index 6c9f2a47cd..5c73385bdb 100644 --- a/eeschema/tools/sch_drawing_tool.h +++ b/eeschema/tools/sch_drawing_tool.h @@ -79,9 +79,6 @@ public: int StartLines( const TOOL_EVENT& aEvent ); int AddJunction( const TOOL_EVENT& aEvent ); int AddLabel( const TOOL_EVENT& aEvent ); - int AddGlobalLabel( const TOOL_EVENT& aEvent ); - int AddHierLabel( const TOOL_EVENT& aEvent ); - int ImportHierLable( const TOOL_EVENT& aEvent ); int PlaceSymbol( const TOOL_EVENT& aEvent ); int PlacePower( const TOOL_EVENT& aEvent ); @@ -103,6 +100,12 @@ public: int DrawLines( const TOOL_EVENT& aEvent ); int PlaceImage( const TOOL_EVENT& aEvent ); + // SELECTION_CONDITIONs: + static bool IsDrawingLine( const SELECTION& aSelection ); + static bool IsDrawingWire( const SELECTION& aSelection ); + static bool IsDrawingBus( const SELECTION& aSelection ); + static bool IsDrawingLineWireOrBus( const SELECTION& aSelection ); + private: int doAddItem( KICAD_T aType ); diff --git a/eeschema/tools/sch_edit_tool.cpp b/eeschema/tools/sch_edit_tool.cpp index 40619da154..7660533378 100644 --- a/eeschema/tools/sch_edit_tool.cpp +++ b/eeschema/tools/sch_edit_tool.cpp @@ -204,26 +204,27 @@ bool SCH_EDIT_TOOL::Init() return ( m_frame->GetToolId() != ID_NO_TOOL_SELECTED ); }; - auto noActiveToolCondition = [ this ] ( const SELECTION& aSel ) { - return ( m_frame->GetToolId() == ID_NO_TOOL_SELECTED ); + auto moveCondition = [] ( const SELECTION& aSel ) { + if( aSel.Empty() ) + return false; + + if( SCH_DRAWING_TOOL::IsDrawingLineWireOrBus( aSel ) ) + return false; + + return true; }; - auto orientatableCondition = [ this ] ( const SELECTION& aSel ) { + auto orientCondition = [] ( const SELECTION& aSel ) { if( aSel.Empty() ) return false; + if( SCH_DRAWING_TOOL::IsDrawingLineWireOrBus( aSel ) ) + return false; + SCH_ITEM* item = (SCH_ITEM*) aSel.Front(); if( aSel.GetSize() > 1 ) - { - // In general a group is orientatable, except when we're drawing wires/busses - if( m_frame->GetToolId() == ID_WIRE_BUTT || m_frame->GetToolId() == ID_BUS_BUTT ) - { - if( item->Type() == SCH_LINE_T && item->IsNew() ) - return false; - } return true; - } switch( item->Type() ) { @@ -241,7 +242,7 @@ bool SCH_EDIT_TOOL::Init() } }; - auto hasPropertiesCondition = [] ( const SELECTION& aSel ) { + auto propertiesCondition = [] ( const SELECTION& aSel ) { if( aSel.GetSize() != 1 ) return false; @@ -261,93 +262,45 @@ bool SCH_EDIT_TOOL::Init() } }; - auto notJustMarkersCondition = SELECTION_CONDITIONS::MoreThan( 0 ) - && ! SELECTION_CONDITIONS::OnlyType( SCH_MARKER_T ); + KICAD_T toLabelTypes[] = { SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T, SCH_TEXT_T, EOT }; + auto toLabelCondition = SCH_CONDITIONS::Count( 1 ) + && SCH_CONDITIONS::OnlyTypes( toLabelTypes ); - auto toLabelCondition = SELECTION_CONDITIONS::Count( 1 ) - && ( SELECTION_CONDITIONS::HasType( SCH_GLOBAL_LABEL_T ) - || SELECTION_CONDITIONS::HasType( SCH_HIER_LABEL_T ) - || SELECTION_CONDITIONS::HasType( SCH_TEXT_T ) ); + KICAD_T toHLableTypes[] = { SCH_LABEL_T, SCH_GLOBAL_LABEL_T, SCH_TEXT_T, EOT }; + auto toHLabelCondition = SCH_CONDITIONS::Count( 1 ) + && SCH_CONDITIONS::OnlyTypes( toHLableTypes); - auto toHLabelCondition = SELECTION_CONDITIONS::Count( 1 ) - && ( SELECTION_CONDITIONS::HasType( SCH_LABEL_T ) - || SELECTION_CONDITIONS::HasType( SCH_GLOBAL_LABEL_T ) - || SELECTION_CONDITIONS::HasType( SCH_TEXT_T ) ); + KICAD_T toGLableTypes[] = { SCH_LABEL_T, SCH_HIER_LABEL_T, SCH_TEXT_T, EOT }; + auto toGLabelCondition = SCH_CONDITIONS::Count( 1 ) + && SCH_CONDITIONS::OnlyTypes( toGLableTypes); - auto toGLabelCondition = SELECTION_CONDITIONS::Count( 1 ) - && ( SELECTION_CONDITIONS::HasType( SCH_LABEL_T ) - || SELECTION_CONDITIONS::HasType( SCH_HIER_LABEL_T ) - || SELECTION_CONDITIONS::HasType( SCH_TEXT_T ) ); + KICAD_T toTextTypes[] = { SCH_LABEL_T, SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T, EOT }; + auto toTextlCondition = SCH_CONDITIONS::Count( 1 ) + && SCH_CONDITIONS::OnlyTypes( toTextTypes); - auto toTextlCondition = SELECTION_CONDITIONS::Count( 1 ) - && ( SELECTION_CONDITIONS::HasType( SCH_LABEL_T ) - || SELECTION_CONDITIONS::HasType( SCH_GLOBAL_LABEL_T ) - || SELECTION_CONDITIONS::HasType( SCH_HIER_LABEL_T ) ); + KICAD_T entryTypes[] = { SCH_BUS_WIRE_ENTRY_T, SCH_BUS_BUS_ENTRY_T, EOT }; + auto entryCondition = SCH_CONDITIONS::MoreThan( 0 ) + && SCH_CONDITIONS::OnlyTypes( entryTypes ); - auto entryCondition = SELECTION_CONDITIONS::HasType( SCH_BUS_WIRE_ENTRY_T ) - || SELECTION_CONDITIONS::HasType( SCH_BUS_BUS_ENTRY_T ); + auto singleComponentCondition = SCH_CONDITIONS::Count( 1 ) + && SCH_CONDITIONS::OnlyType( SCH_COMPONENT_T ); - auto singleComponentCondition = SELECTION_CONDITIONS::Count( 1 ) - && SELECTION_CONDITIONS::OnlyType( SCH_COMPONENT_T ); + auto wireSelectionCondition = SCH_CONDITIONS::MoreThan( 0 ) + && SCH_CONDITIONS::OnlyType( SCH_LINE_LOCATE_WIRE_T ); - auto singleSheetCondition = SELECTION_CONDITIONS::Count( 1 ) - && SELECTION_CONDITIONS::OnlyType( SCH_SHEET_T ); + auto busSelectionCondition = SCH_CONDITIONS::MoreThan( 0 ) + && SCH_CONDITIONS::OnlyType( SCH_LINE_LOCATE_BUS_T ); - auto singleSymbolCondition = [] ( const SELECTION& aSel ) { - if( aSel.GetSize() == 1 ) - { - SCH_COMPONENT* comp = dynamic_cast( aSel.Front() ); + auto singleSheetCondition = SCH_CONDITIONS::Count( 1 ) + && SCH_CONDITIONS::OnlyType( SCH_SHEET_T ); - if( comp ) - { - auto partRef = comp->GetPartRef().lock(); - return !partRef || !partRef->IsPower(); - } - } - - return false; + auto wireOrBusTool = [ this ] ( const SELECTION& aSel ) { + return ( m_frame->GetToolId() == ID_WIRE_BUTT + || m_frame->GetToolId() == ID_BUS_BUTT + || m_frame->GetToolId() == ID_JUNCTION_BUTT ); }; - auto singleDeMorganSymbolCondition = [] ( const SELECTION& aSel ) { - if( aSel.GetSize() == 1 ) - { - SCH_COMPONENT* comp = dynamic_cast( aSel.Front() ); - - if( comp ) - { - auto partRef = comp->GetPartRef().lock(); - return partRef && partRef->HasConversion(); - } - } - - return false; - }; - - auto wireTool = [ this ] ( const SELECTION& aSel ) { - return ( m_frame->GetToolId() == ID_WIRE_BUTT ); - }; - - auto busTool = [ this ] ( const SELECTION& aSel ) { - return ( m_frame->GetToolId() == ID_BUS_BUTT ); - }; - - auto junctionTool = [ this ] ( const SELECTION& aSel ) { - return ( m_frame->GetToolId() == ID_JUNCTION_BUTT ); - }; - - auto idleCondition = [] ( const SELECTION& aSel ) { - SCH_ITEM* item = (SCH_ITEM*) aSel.Front(); - return ( !item || !item->GetEditFlags() ); - }; - - auto idleWireOrBusTool = ( wireTool || busTool || junctionTool ) && idleCondition; - - auto wireSelectionCondition = SELECTION_CONDITIONS::MoreThan( 0 ) - && SELECTION_CONDITIONS::OnlyType( SCH_LINE_LOCATE_WIRE_T ); - - auto busSelectionCondition = SELECTION_CONDITIONS::MoreThan( 0 ) - && SELECTION_CONDITIONS::OnlyType( SCH_LINE_LOCATE_BUS_T ); - + // // Build the edit tool menu (shown when moving or dragging) // CONDITIONAL_MENU& ctxMenu = m_menu.GetMenu(); @@ -355,91 +308,91 @@ bool SCH_EDIT_TOOL::Init() ctxMenu.AddItem( ACTIONS::cancelInteractive, activeToolCondition, 1 ); ctxMenu.AddSeparator( SELECTION_CONDITIONS::NotEmpty ); - ctxMenu.AddItem( SCH_ACTIONS::rotateCCW, orientatableCondition ); - ctxMenu.AddItem( SCH_ACTIONS::rotateCW, orientatableCondition ); - ctxMenu.AddItem( SCH_ACTIONS::mirrorX, orientatableCondition ); - ctxMenu.AddItem( SCH_ACTIONS::mirrorY, orientatableCondition ); - ctxMenu.AddItem( SCH_ACTIONS::duplicate, notJustMarkersCondition ); - ctxMenu.AddItem( SCH_ACTIONS::doDelete, SELECTION_CONDITIONS::NotEmpty ); + ctxMenu.AddItem( SCH_ACTIONS::rotateCCW, orientCondition ); + ctxMenu.AddItem( SCH_ACTIONS::rotateCW, orientCondition ); + ctxMenu.AddItem( SCH_ACTIONS::mirrorX, orientCondition ); + ctxMenu.AddItem( SCH_ACTIONS::mirrorY, orientCondition ); + ctxMenu.AddItem( SCH_ACTIONS::duplicate, moveCondition ); + ctxMenu.AddItem( SCH_ACTIONS::doDelete, SCH_CONDITIONS::NotEmpty ); - ctxMenu.AddItem( SCH_ACTIONS::properties, hasPropertiesCondition ); - ctxMenu.AddItem( SCH_ACTIONS::editReference, singleComponentCondition ); - ctxMenu.AddItem( SCH_ACTIONS::editValue, singleComponentCondition ); - ctxMenu.AddItem( SCH_ACTIONS::editFootprint, singleComponentCondition ); - ctxMenu.AddItem( SCH_ACTIONS::convertDeMorgan, singleDeMorganSymbolCondition ); + ctxMenu.AddItem( SCH_ACTIONS::properties, propertiesCondition ); + ctxMenu.AddItem( SCH_ACTIONS::editReference, singleComponentCondition ); + ctxMenu.AddItem( SCH_ACTIONS::editValue, singleComponentCondition ); + ctxMenu.AddItem( SCH_ACTIONS::editFootprint, singleComponentCondition ); + ctxMenu.AddItem( SCH_ACTIONS::convertDeMorgan, SCH_CONDITIONS::SingleDeMorganSymbol ); // JEY TODO: add menu access for changing symbol unit - ctxMenu.AddSeparator( SELECTION_CONDITIONS::NotEmpty ); - ctxMenu.AddItem( SCH_ACTIONS::cut, SELECTION_CONDITIONS::NotEmpty ); - ctxMenu.AddItem( SCH_ACTIONS::copy, SELECTION_CONDITIONS::NotEmpty ); + ctxMenu.AddSeparator( SCH_CONDITIONS::IdleSelection ); + ctxMenu.AddItem( SCH_ACTIONS::cut, SCH_CONDITIONS::IdleSelection ); + ctxMenu.AddItem( SCH_ACTIONS::copy, SCH_CONDITIONS::IdleSelection ); ctxMenu.AddSeparator( SELECTION_CONDITIONS::NotEmpty, 1000 ); m_menu.AddStandardSubMenus( m_frame ); + // // Add editing actions to the drawing tool menu // CONDITIONAL_MENU& drawingMenu = drawingTool->GetToolMenu().GetMenu(); - ctxMenu.AddSeparator( SELECTION_CONDITIONS::NotEmpty, 200 ); - drawingMenu.AddItem( SCH_ACTIONS::rotateCCW, orientatableCondition, 200 ); - drawingMenu.AddItem( SCH_ACTIONS::rotateCW, orientatableCondition, 200 ); - drawingMenu.AddItem( SCH_ACTIONS::mirrorX, orientatableCondition, 200 ); - drawingMenu.AddItem( SCH_ACTIONS::mirrorY, orientatableCondition, 200 ); + ctxMenu.AddSeparator( SCH_CONDITIONS::NotEmpty, 200 ); + drawingMenu.AddItem( SCH_ACTIONS::rotateCCW, orientCondition, 200 ); + drawingMenu.AddItem( SCH_ACTIONS::rotateCW, orientCondition, 200 ); + drawingMenu.AddItem( SCH_ACTIONS::mirrorX, orientCondition, 200 ); + drawingMenu.AddItem( SCH_ACTIONS::mirrorY, orientCondition, 200 ); - drawingMenu.AddItem( SCH_ACTIONS::properties, hasPropertiesCondition, 200 ); - drawingMenu.AddItem( SCH_ACTIONS::editReference, singleComponentCondition, 200 ); - drawingMenu.AddItem( SCH_ACTIONS::editValue, singleComponentCondition, 200 ); - drawingMenu.AddItem( SCH_ACTIONS::editFootprint, singleComponentCondition, 200 ); - drawingMenu.AddItem( SCH_ACTIONS::convertDeMorgan, singleDeMorganSymbolCondition, 200 ); + drawingMenu.AddItem( SCH_ACTIONS::properties, propertiesCondition, 200 ); + drawingMenu.AddItem( SCH_ACTIONS::editReference, singleComponentCondition, 200 ); + drawingMenu.AddItem( SCH_ACTIONS::editValue, singleComponentCondition, 200 ); + drawingMenu.AddItem( SCH_ACTIONS::editFootprint, singleComponentCondition, 200 ); + drawingMenu.AddItem( SCH_ACTIONS::convertDeMorgan, SCH_CONDITIONS::SingleDeMorganSymbol, 200 ); // JEY TODO: add menu access for changing symbol unit - drawingMenu.AddItem( SCH_ACTIONS::toShapeSlash, entryCondition, 200 ); + drawingMenu.AddItem( SCH_ACTIONS::toShapeSlash, entryCondition, 200 ); drawingMenu.AddItem( SCH_ACTIONS::toShapeBackslash, entryCondition, 200 ); - drawingMenu.AddItem( SCH_ACTIONS::toLabel, toLabelCondition, 200 ); + drawingMenu.AddItem( SCH_ACTIONS::toLabel, toLabelCondition, 200 ); drawingMenu.AddItem( SCH_ACTIONS::toHLabel, toHLabelCondition, 200 ); drawingMenu.AddItem( SCH_ACTIONS::toGLabel, toGLabelCondition, 200 ); - drawingMenu.AddItem( SCH_ACTIONS::toText, toTextlCondition, 200 ); - drawingMenu.AddItem( SCH_ACTIONS::selectNode, idleWireOrBusTool, 200 ); - drawingMenu.AddItem( SCH_ACTIONS::selectConnection, idleWireOrBusTool, 200 ); - drawingMenu.AddItem( SCH_ACTIONS::breakWire, idleWireOrBusTool, 200 ); - drawingMenu.AddItem( SCH_ACTIONS::breakBus, idleWireOrBusTool, 200 ); + drawingMenu.AddItem( SCH_ACTIONS::toText, toTextlCondition, 200 ); + drawingMenu.AddItem( SCH_ACTIONS::selectNode, SCH_CONDITIONS::Idle && wireOrBusTool, 200 ); + drawingMenu.AddItem( SCH_ACTIONS::selectConnection, SCH_CONDITIONS::Idle && wireOrBusTool, 200 ); + drawingMenu.AddItem( SCH_ACTIONS::breakWire, SCH_CONDITIONS::Idle && wireOrBusTool, 200 ); + drawingMenu.AddItem( SCH_ACTIONS::breakBus, SCH_CONDITIONS::Idle && wireOrBusTool, 200 ); + // // Add editing actions to the selection tool menu // CONDITIONAL_MENU& selToolMenu = m_selectionTool->GetToolMenu().GetMenu(); - selToolMenu.AddItem( SCH_ACTIONS::move, SELECTION_CONDITIONS::NotEmpty, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::drag, SELECTION_CONDITIONS::NotEmpty, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::rotateCCW, orientatableCondition, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::rotateCW, orientatableCondition, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::mirrorX, orientatableCondition, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::mirrorY, orientatableCondition, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::duplicate, notJustMarkersCondition, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::doDelete, SELECTION_CONDITIONS::NotEmpty, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::move, moveCondition, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::drag, moveCondition, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::rotateCCW, orientCondition, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::rotateCW, orientCondition, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::mirrorX, orientCondition, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::mirrorY, orientCondition, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::duplicate, moveCondition, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::doDelete, SCH_CONDITIONS::NotEmpty, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::properties, hasPropertiesCondition, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::editReference, singleSymbolCondition, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::editValue, singleSymbolCondition, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::editFootprint, singleSymbolCondition, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::autoplaceFields, singleComponentCondition, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::convertDeMorgan, singleDeMorganSymbolCondition, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::properties, propertiesCondition, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::editReference, SCH_CONDITIONS::SingleSymbol, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::editValue, SCH_CONDITIONS::SingleSymbol, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::editFootprint, SCH_CONDITIONS::SingleSymbol, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::autoplaceFields, singleComponentCondition, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::convertDeMorgan, SCH_CONDITIONS::SingleSymbol, 200 ); // JEY TODO: add menu access for changing symbol unit - selToolMenu.AddItem( SCH_ACTIONS::showDatasheet, singleSymbolCondition, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::toShapeSlash, entryCondition, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::showDatasheet, SCH_CONDITIONS::SingleSymbol, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::toShapeSlash, entryCondition, 200 ); selToolMenu.AddItem( SCH_ACTIONS::toShapeBackslash, entryCondition, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::toLabel, toLabelCondition, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::toHLabel, toHLabelCondition, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::toGLabel, toGLabelCondition, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::toText, toTextlCondition, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::breakWire, wireSelectionCondition, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::breakBus, busSelectionCondition, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::toLabel, toLabelCondition, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::toHLabel, toHLabelCondition, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::toGLabel, toGLabelCondition, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::toText, toTextlCondition, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::breakWire, wireSelectionCondition, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::breakBus, busSelectionCondition, 200 ); selToolMenu.AddItem( SCH_ACTIONS::cleanupSheetPins, singleSheetCondition, 200 ); - selToolMenu.AddSeparator( SELECTION_CONDITIONS::NotEmpty, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::cut, SELECTION_CONDITIONS::NotEmpty, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::copy, SELECTION_CONDITIONS::NotEmpty, 200 ); - // Selection tool handles the context menu for some other tools, such as the Picker. - // Don't add things like Paste when another tool is active. - selToolMenu.AddItem( SCH_ACTIONS::paste, noActiveToolCondition, 200 ); + selToolMenu.AddSeparator( SCH_CONDITIONS::Idle, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::cut, SCH_CONDITIONS::IdleSelection, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::copy, SCH_CONDITIONS::IdleSelection, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::paste, SCH_CONDITIONS::Idle, 200 ); return true; } diff --git a/eeschema/tools/sch_inspection_tool.cpp b/eeschema/tools/sch_inspection_tool.cpp index 65f55fe0f5..48c149a319 100644 --- a/eeschema/tools/sch_inspection_tool.cpp +++ b/eeschema/tools/sch_inspection_tool.cpp @@ -67,28 +67,13 @@ bool SCH_INSPECTION_TOOL::Init() wxASSERT_MSG( m_selectionTool, "eeshema.InteractiveSelection tool is not available" ); auto singleMarkerCondition = SELECTION_CONDITIONS::OnlyType( SCH_MARKER_T ) - && SELECTION_CONDITIONS::Count( 1 ); - - auto singleSymbolCondition = [] (const SELECTION& aSel ) { - if( aSel.GetSize() == 1 ) - { - SCH_COMPONENT* comp = dynamic_cast( aSel.Front() ); - - if( comp ) - { - auto partRef = comp->GetPartRef().lock(); - return !partRef || !partRef->IsPower(); - } - } - - return false; - }; + && SELECTION_CONDITIONS::Count( 1 ); // Add inspection actions to the selection tool menu // CONDITIONAL_MENU& selToolMenu = m_selectionTool->GetToolMenu().GetMenu(); - selToolMenu.AddItem( SCH_ACTIONS::showDatasheet, singleSymbolCondition, 400 ); + selToolMenu.AddItem( SCH_ACTIONS::showDatasheet, SCH_CONDITIONS::SingleSymbol, 400 ); selToolMenu.AddItem( SCH_ACTIONS::showMarkerInfo, singleMarkerCondition, 400 ); return true; diff --git a/eeschema/tools/sch_selection_tool.cpp b/eeschema/tools/sch_selection_tool.cpp index ef446d4caa..e295ab2231 100644 --- a/eeschema/tools/sch_selection_tool.cpp +++ b/eeschema/tools/sch_selection_tool.cpp @@ -74,7 +74,59 @@ TOOL_ACTION SCH_ACTIONS::removeItemsFromSel( "eeschema.InteractiveSelection.Remo TOOL_ACTION SCH_ACTIONS::clearSelection( "eeschema.InteractiveSelection.ClearSelection", AS_GLOBAL, 0, "", "" ); // No description, it is not supposed to be shown anywhere - + +SELECTION_CONDITION SCH_CONDITIONS::Empty = [] (const SELECTION& aSelection ) +{ + return aSelection.Empty(); +}; + + +SELECTION_CONDITION SCH_CONDITIONS::Idle = [] (const SELECTION& aSelection ) +{ + return ( !aSelection.Front() || aSelection.Front()->GetEditFlags() == 0 ); +}; + + +SELECTION_CONDITION SCH_CONDITIONS::IdleSelection = [] (const SELECTION& aSelection ) +{ + return ( aSelection.Front() && aSelection.Front()->GetEditFlags() == 0 ); +}; + + +SELECTION_CONDITION SCH_CONDITIONS::SingleSymbol = [] (const SELECTION& aSel ) +{ + if( aSel.GetSize() == 1 ) + { + SCH_COMPONENT* comp = dynamic_cast( aSel.Front() ); + + if( comp ) + { + auto partRef = comp->GetPartRef().lock(); + return !partRef || !partRef->IsPower(); + } + } + + return false; +}; + + +SELECTION_CONDITION SCH_CONDITIONS::SingleDeMorganSymbol = [] ( const SELECTION& aSel ) +{ + if( aSel.GetSize() == 1 ) + { + SCH_COMPONENT* comp = dynamic_cast( aSel.Front() ); + + if( comp ) + { + auto partRef = comp->GetPartRef().lock(); + return partRef && partRef->HasConversion(); + } + } + + return false; +}; + + SCH_SELECTION_TOOL::SCH_SELECTION_TOOL() : TOOL_INTERACTIVE( "eeschema.InteractiveSelection" ), m_frame( nullptr ), @@ -95,25 +147,15 @@ SCH_SELECTION_TOOL::~SCH_SELECTION_TOOL() bool SCH_SELECTION_TOOL::Init() { - static KICAD_T wireOrBusTypes[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT }; - m_frame = getEditFrame(); - auto wireOrBusSelectionCondition = [] ( const SELECTION& aSel ) { - for( unsigned i = 0; i < aSel.GetSize(); ++i ) - { - SCH_ITEM* item = (SCH_ITEM*) aSel.GetItem( i ); - - if( !item->IsType( wireOrBusTypes ) || item->IsNew() ) - return false; - } - - return aSel.GetSize() >= 1; - }; + static KICAD_T wireOrBusTypes[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT }; + auto wireOrBusSelection = SCH_CONDITIONS::MoreThan( 0 ) + && SCH_CONDITIONS::OnlyTypes( wireOrBusTypes ); auto& ctxMenu = m_menu.GetMenu(); - ctxMenu.AddItem( SCH_ACTIONS::selectConnection, wireOrBusSelectionCondition, 200 ); + ctxMenu.AddItem( SCH_ACTIONS::selectConnection, wireOrBusSelection && SCH_CONDITIONS::Idle, 200 ); ctxMenu.AddSeparator( SELECTION_CONDITIONS::ShowAlways, 1000 ); m_menu.AddStandardSubMenus( m_frame ); diff --git a/eeschema/tools/sch_selection_tool.h b/eeschema/tools/sch_selection_tool.h index 7226f5e3c3..44cf5e0a2e 100644 --- a/eeschema/tools/sch_selection_tool.h +++ b/eeschema/tools/sch_selection_tool.h @@ -29,6 +29,7 @@ #include #include #include +#include class SCH_BASE_FRAME; class SCH_ITEM; @@ -40,6 +41,18 @@ namespace KIGFX } +class SCH_CONDITIONS : public SELECTION_CONDITIONS +{ +public: + static SELECTION_CONDITION Empty; + static SELECTION_CONDITION Idle; + static SELECTION_CONDITION IdleSelection; + + static SELECTION_CONDITION SingleSymbol; + static SELECTION_CONDITION SingleDeMorganSymbol; +}; + + class SCH_SELECTION_TOOL : public TOOL_INTERACTIVE { public: diff --git a/include/tool/selection.h b/include/tool/selection.h index da5d56b086..7180479cfd 100644 --- a/include/tool/selection.h +++ b/include/tool/selection.h @@ -154,7 +154,7 @@ public: EDA_ITEM* Front() const { - return m_items.front(); + return m_items.size() ? m_items.front() : nullptr; } std::deque& Items()