Refactor as SCH_DRAWING_TOOL was getting too big.
This commit is contained in:
parent
2774af928a
commit
f4b92e6acf
|
@ -215,7 +215,6 @@ set( EESCHEMA_SRCS
|
||||||
sch_sheet_pin.cpp
|
sch_sheet_pin.cpp
|
||||||
sch_text.cpp
|
sch_text.cpp
|
||||||
sch_validators.cpp
|
sch_validators.cpp
|
||||||
schedit.cpp
|
|
||||||
schematic_undo_redo.cpp
|
schematic_undo_redo.cpp
|
||||||
sch_edit_frame.cpp
|
sch_edit_frame.cpp
|
||||||
selpart.cpp
|
selpart.cpp
|
||||||
|
@ -243,6 +242,7 @@ set( EESCHEMA_SRCS
|
||||||
tools/sch_edit_tool.cpp
|
tools/sch_edit_tool.cpp
|
||||||
tools/sch_editor_control.cpp
|
tools/sch_editor_control.cpp
|
||||||
tools/sch_inspection_tool.cpp
|
tools/sch_inspection_tool.cpp
|
||||||
|
tools/sch_line_drawing_tool.cpp
|
||||||
tools/sch_picker_tool.cpp
|
tools/sch_picker_tool.cpp
|
||||||
tools/sch_selection_tool.cpp
|
tools/sch_selection_tool.cpp
|
||||||
tools/selection.cpp
|
tools/selection.cpp
|
||||||
|
|
|
@ -33,7 +33,10 @@
|
||||||
#include <sch_component.h>
|
#include <sch_component.h>
|
||||||
#include <sch_sheet.h>
|
#include <sch_sheet.h>
|
||||||
#include <sch_view.h>
|
#include <sch_view.h>
|
||||||
|
#include <tools/sch_actions.h>
|
||||||
|
#include <tools/sch_selection_tool.h>
|
||||||
|
#include <tool/tool_manager.h>
|
||||||
|
#include "eeschema_id.h"
|
||||||
|
|
||||||
void SCH_EDIT_FRAME::GetSchematicConnections( std::vector< wxPoint >& aConnections )
|
void SCH_EDIT_FRAME::GetSchematicConnections( std::vector< wxPoint >& aConnections )
|
||||||
{
|
{
|
||||||
|
@ -452,3 +455,106 @@ SCH_JUNCTION* SCH_EDIT_FRAME::AddJunction( const wxPoint& aPosition, bool aAppen
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SCH_EDIT_FRAME::OnUnfoldBus( wxCommandEvent& event )
|
||||||
|
{
|
||||||
|
wxMenuItem* item = static_cast<wxMenuItem*>( event.GetEventUserData() );
|
||||||
|
wxString net = item->GetItemLabelText();
|
||||||
|
|
||||||
|
GetToolManager()->RunAction( SCH_ACTIONS::unfoldBus, true, &net );
|
||||||
|
|
||||||
|
// Now that we have handled the chosen bus unfold, disconnect all the events so they can be
|
||||||
|
// recreated with updated data on the next unfold
|
||||||
|
Unbind( wxEVT_COMMAND_MENU_SELECTED, &SCH_EDIT_FRAME::OnUnfoldBus, this );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SCH_EDIT_FRAME::OnUnfoldBusHotkey( wxCommandEvent& aEvent )
|
||||||
|
{
|
||||||
|
SCH_SELECTION_TOOL* selTool = GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
|
||||||
|
EDA_HOTKEY_CLIENT_DATA* data = (EDA_HOTKEY_CLIENT_DATA*) aEvent.GetClientObject();
|
||||||
|
SCH_ITEM* item = GetScreen()->GetCurItem();
|
||||||
|
|
||||||
|
wxCHECK_RET( data != NULL, wxT( "Invalid hot key client object." ) );
|
||||||
|
|
||||||
|
if( item == NULL )
|
||||||
|
{
|
||||||
|
// If we didn't get here by a hot key, then something has gone wrong.
|
||||||
|
if( aEvent.GetInt() == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
item = selTool->SelectPoint( data->GetPosition(), SCH_COLLECTOR::EditableItems );
|
||||||
|
|
||||||
|
// Exit if no item found at the current location or the item is already being edited.
|
||||||
|
if( item == NULL || item->GetEditFlags() != 0 )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( item->Type() != SCH_LINE_T )
|
||||||
|
return;
|
||||||
|
|
||||||
|
wxMenu* bus_unfold_menu = GetUnfoldBusMenu( static_cast<SCH_LINE*>( item ) );
|
||||||
|
|
||||||
|
if( bus_unfold_menu )
|
||||||
|
{
|
||||||
|
auto controls = GetCanvas()->GetViewControls();
|
||||||
|
auto vmp = controls->GetMousePosition( false );
|
||||||
|
wxPoint mouse_pos( (int) vmp.x, (int) vmp.y );
|
||||||
|
|
||||||
|
GetGalCanvas()->PopupMenu( bus_unfold_menu, mouse_pos );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxMenu* SCH_EDIT_FRAME::GetUnfoldBusMenu( SCH_LINE* aBus )
|
||||||
|
{
|
||||||
|
auto connection = aBus->Connection( *g_CurrentSheet );
|
||||||
|
|
||||||
|
if( !connection || !connection->IsBus() || connection->Members().empty() )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
wxMenu* bus_unfolding_menu = new wxMenu;
|
||||||
|
|
||||||
|
for( const auto& member : connection->Members() )
|
||||||
|
{
|
||||||
|
int id = ID_POPUP_SCH_UNFOLD_BUS + ( idx++ );
|
||||||
|
wxString name = member->Name( true );
|
||||||
|
|
||||||
|
if( member->Type() == CONNECTION_BUS )
|
||||||
|
{
|
||||||
|
wxMenu* submenu = new wxMenu;
|
||||||
|
bus_unfolding_menu->AppendSubMenu( submenu, _( name ) );
|
||||||
|
|
||||||
|
for( const auto& sub_member : member->Members() )
|
||||||
|
{
|
||||||
|
id = ID_POPUP_SCH_UNFOLD_BUS + ( idx++ );
|
||||||
|
|
||||||
|
submenu->Append( id, sub_member->Name( true ), wxEmptyString );
|
||||||
|
|
||||||
|
// See comment in else clause below
|
||||||
|
auto sub_item_clone = new wxMenuItem();
|
||||||
|
sub_item_clone->SetItemLabel( sub_member->Name( true ) );
|
||||||
|
|
||||||
|
Bind( wxEVT_COMMAND_MENU_SELECTED, &SCH_EDIT_FRAME::OnUnfoldBus, this, id, id,
|
||||||
|
sub_item_clone );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bus_unfolding_menu->Append( id, name, wxEmptyString );
|
||||||
|
|
||||||
|
// Because Bind() takes ownership of the user data item, we
|
||||||
|
// make a new menu item here and set its label. Why create a
|
||||||
|
// menu item instead of just a wxString or something? Because
|
||||||
|
// Bind() requires a pointer to wxObject rather than a void
|
||||||
|
// pointer. Maybe at some point I'll think of a better way...
|
||||||
|
auto item_clone = new wxMenuItem();
|
||||||
|
item_clone->SetItemLabel( name );
|
||||||
|
|
||||||
|
Bind( wxEVT_COMMAND_MENU_SELECTED, &SCH_EDIT_FRAME::OnUnfoldBus, this, id, id,
|
||||||
|
item_clone );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bus_unfolding_menu;
|
||||||
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ private:
|
||||||
SCH_SHEET_PATH m_currSheet; // The currently opened scheet in hierarchy
|
SCH_SHEET_PATH m_currSheet; // The currently opened scheet in hierarchy
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HIERARCHY_NAVIG_DLG( SCH_EDIT_FRAME* aParent, const wxPoint& aPos );
|
HIERARCHY_NAVIG_DLG( SCH_EDIT_FRAME* aParent );
|
||||||
|
|
||||||
~HIERARCHY_NAVIG_DLG();
|
~HIERARCHY_NAVIG_DLG();
|
||||||
|
|
||||||
|
@ -130,16 +130,16 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void SCH_EDIT_FRAME::InstallHierarchyFrame( wxPoint& pos )
|
void SCH_EDIT_FRAME::InstallHierarchyFrame( wxCommandEvent& event )
|
||||||
{
|
{
|
||||||
HIERARCHY_NAVIG_DLG* treeframe = new HIERARCHY_NAVIG_DLG( this, pos );
|
HIERARCHY_NAVIG_DLG* treeframe = new HIERARCHY_NAVIG_DLG( this );
|
||||||
|
|
||||||
treeframe->ShowQuasiModal();
|
treeframe->ShowQuasiModal();
|
||||||
treeframe->Destroy();
|
treeframe->Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HIERARCHY_NAVIG_DLG::HIERARCHY_NAVIG_DLG( SCH_EDIT_FRAME* aParent, const wxPoint& aPos ) :
|
HIERARCHY_NAVIG_DLG::HIERARCHY_NAVIG_DLG( SCH_EDIT_FRAME* aParent ) :
|
||||||
DIALOG_SHIM( aParent, wxID_ANY, _( "Navigator" ), wxDefaultPosition, wxDefaultSize,
|
DIALOG_SHIM( aParent, wxID_ANY, _( "Navigator" ), wxDefaultPosition, wxDefaultSize,
|
||||||
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER )
|
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER )
|
||||||
{
|
{
|
||||||
|
|
|
@ -96,8 +96,6 @@ void AddMenusForComponent( wxMenu* PopMenu, SCH_COMPONENT* Component, SYMBOL_LIB
|
||||||
void AddMenusForBus( wxMenu* PopMenu, SCH_LINE* Bus, SCH_EDIT_FRAME* frame )
|
void AddMenusForBus( wxMenu* PopMenu, SCH_LINE* Bus, SCH_EDIT_FRAME* frame )
|
||||||
{
|
{
|
||||||
SCH_SELECTION_TOOL* selTool = frame->GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
|
SCH_SELECTION_TOOL* selTool = frame->GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
|
||||||
wxPoint pos = frame->GetCrossHairPosition();
|
|
||||||
wxString msg;
|
|
||||||
|
|
||||||
// TODO(JE) remove once real-time is enabled
|
// TODO(JE) remove once real-time is enabled
|
||||||
if( !ADVANCED_CFG::GetCfg().m_realTimeConnectivity || !CONNECTION_GRAPH::m_allowRealTime )
|
if( !ADVANCED_CFG::GetCfg().m_realTimeConnectivity || !CONNECTION_GRAPH::m_allowRealTime )
|
||||||
|
@ -105,9 +103,9 @@ void AddMenusForBus( wxMenu* PopMenu, SCH_LINE* Bus, SCH_EDIT_FRAME* frame )
|
||||||
frame->RecalculateConnections();
|
frame->RecalculateConnections();
|
||||||
|
|
||||||
// Have to pick up the pointer again because it may have been changed by SchematicCleanUp
|
// Have to pick up the pointer again because it may have been changed by SchematicCleanUp
|
||||||
bool actionCancelled = false;
|
KICAD_T busType[] = { SCH_LINE_LOCATE_BUS_T, EOT };
|
||||||
Bus = dynamic_cast<SCH_LINE*>( selTool->SelectPoint( pos, SCH_COLLECTOR::AllItemsButPins,
|
SELECTION& selection = selTool->RequestSelection( busType );
|
||||||
&actionCancelled ) );
|
Bus = (SCH_LINE*) selection.Front();
|
||||||
wxASSERT( Bus );
|
wxASSERT( Bus );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -245,7 +245,7 @@ BEGIN_EVENT_TABLE( SCH_EDIT_FRAME, EDA_DRAW_FRAME )
|
||||||
EVT_TOOL( ID_RUN_CVPCB, SCH_EDIT_FRAME::OnOpenCvpcb )
|
EVT_TOOL( ID_RUN_CVPCB, SCH_EDIT_FRAME::OnOpenCvpcb )
|
||||||
|
|
||||||
EVT_TOOL( ID_SHEET_SET, EDA_DRAW_FRAME::Process_PageSettings )
|
EVT_TOOL( ID_SHEET_SET, EDA_DRAW_FRAME::Process_PageSettings )
|
||||||
EVT_TOOL( ID_HIERARCHY, SCH_EDIT_FRAME::Process_Special_Functions )
|
EVT_TOOL( ID_HIERARCHY, SCH_EDIT_FRAME::InstallHierarchyFrame )
|
||||||
EVT_TOOL( wxID_UNDO, SCH_EDIT_FRAME::GetSchematicFromUndoList )
|
EVT_TOOL( wxID_UNDO, SCH_EDIT_FRAME::GetSchematicFromUndoList )
|
||||||
EVT_TOOL( wxID_REDO, SCH_EDIT_FRAME::GetSchematicFromRedoList )
|
EVT_TOOL( wxID_REDO, SCH_EDIT_FRAME::GetSchematicFromRedoList )
|
||||||
EVT_TOOL( ID_GET_ANNOTATE, SCH_EDIT_FRAME::OnAnnotate )
|
EVT_TOOL( ID_GET_ANNOTATE, SCH_EDIT_FRAME::OnAnnotate )
|
||||||
|
@ -270,8 +270,6 @@ BEGIN_EVENT_TABLE( SCH_EDIT_FRAME, EDA_DRAW_FRAME )
|
||||||
EVT_TOOL( ID_SIM_SHOW, SCH_EDIT_FRAME::OnSimulate )
|
EVT_TOOL( ID_SIM_SHOW, SCH_EDIT_FRAME::OnSimulate )
|
||||||
#endif /* KICAD_SPICE */
|
#endif /* KICAD_SPICE */
|
||||||
|
|
||||||
EVT_MENU_RANGE( ID_POPUP_START_RANGE, ID_POPUP_END_RANGE,
|
|
||||||
SCH_EDIT_FRAME::Process_Special_Functions )
|
|
||||||
EVT_MENU( ID_SCH_UNFOLD_BUS, SCH_EDIT_FRAME::OnUnfoldBusHotkey )
|
EVT_MENU( ID_SCH_UNFOLD_BUS, SCH_EDIT_FRAME::OnUnfoldBusHotkey )
|
||||||
|
|
||||||
EVT_MENU( ID_MENU_CANVAS_CAIRO, SCH_EDIT_FRAME::OnSwitchCanvas )
|
EVT_MENU( ID_MENU_CANVAS_CAIRO, SCH_EDIT_FRAME::OnSwitchCanvas )
|
||||||
|
@ -281,8 +279,6 @@ BEGIN_EVENT_TABLE( SCH_EDIT_FRAME, EDA_DRAW_FRAME )
|
||||||
EVT_TOOL( ID_TB_OPTIONS_HIDDEN_PINS, SCH_EDIT_FRAME::OnSelectOptionToolbar )
|
EVT_TOOL( ID_TB_OPTIONS_HIDDEN_PINS, SCH_EDIT_FRAME::OnSelectOptionToolbar )
|
||||||
EVT_TOOL( ID_TB_OPTIONS_BUS_WIRES_ORIENT, SCH_EDIT_FRAME::OnSelectOptionToolbar )
|
EVT_TOOL( ID_TB_OPTIONS_BUS_WIRES_ORIENT, SCH_EDIT_FRAME::OnSelectOptionToolbar )
|
||||||
|
|
||||||
EVT_MENU_RANGE( ID_POPUP_GENERAL_START_RANGE, ID_POPUP_GENERAL_END_RANGE,
|
|
||||||
SCH_EDIT_FRAME::Process_Special_Functions )
|
|
||||||
EVT_MENU_RANGE( ID_POPUP_SCH_SELECT_UNIT1, ID_POPUP_SCH_SELECT_UNIT_CMP_MAX,
|
EVT_MENU_RANGE( ID_POPUP_SCH_SELECT_UNIT1, ID_POPUP_SCH_SELECT_UNIT_CMP_MAX,
|
||||||
SCH_EDIT_FRAME::OnSelectUnit )
|
SCH_EDIT_FRAME::OnSelectUnit )
|
||||||
|
|
||||||
|
|
|
@ -874,7 +874,7 @@ private:
|
||||||
void NormalizeSchematicOnFirstLoad();
|
void NormalizeSchematicOnFirstLoad();
|
||||||
|
|
||||||
// Hierarchical Sheet & PinSheet
|
// Hierarchical Sheet & PinSheet
|
||||||
void InstallHierarchyFrame( wxPoint& pos );
|
void InstallHierarchyFrame( wxCommandEvent& event );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,156 +0,0 @@
|
||||||
/*
|
|
||||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
|
||||||
* Copyright (C) 2008-2017 Wayne Stambaugh <stambaughw@verizon.net>
|
|
||||||
* Copyright (C) 2004-2019 KiCad Developers, see AUTHORS.txt for contributors.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, you may find one here:
|
|
||||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|
||||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
|
||||||
* or you may write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <fctsys.h>
|
|
||||||
#include <kiway.h>
|
|
||||||
#include <gr_basic.h>
|
|
||||||
#include <sch_draw_panel.h>
|
|
||||||
#include <sch_edit_frame.h>
|
|
||||||
#include <hotkeys_basic.h>
|
|
||||||
#include <general.h>
|
|
||||||
#include <eeschema_id.h>
|
|
||||||
#include <sch_bus_entry.h>
|
|
||||||
#include <sch_view.h>
|
|
||||||
#include <tool/tool_manager.h>
|
|
||||||
#include <tools/sch_actions.h>
|
|
||||||
#include <tools/sch_selection_tool.h>
|
|
||||||
|
|
||||||
void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
|
|
||||||
{
|
|
||||||
if( event.GetId() == ID_HIERARCHY )
|
|
||||||
{
|
|
||||||
wxPoint pos = wxGetMousePosition();
|
|
||||||
pos.y += 20;
|
|
||||||
|
|
||||||
SetNoToolSelected();
|
|
||||||
InstallHierarchyFrame( pos );
|
|
||||||
SetRepeatItem( NULL );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SCH_EDIT_FRAME::OnUnfoldBus( wxCommandEvent& event )
|
|
||||||
{
|
|
||||||
wxMenuItem* item = static_cast<wxMenuItem*>( event.GetEventUserData() );
|
|
||||||
wxString net = item->GetItemLabelText();
|
|
||||||
|
|
||||||
GetToolManager()->RunAction( SCH_ACTIONS::unfoldBus, true, &net );
|
|
||||||
|
|
||||||
// Now that we have handled the chosen bus unfold, disconnect all the events so they can be
|
|
||||||
// recreated with updated data on the next unfold
|
|
||||||
Unbind( wxEVT_COMMAND_MENU_SELECTED, &SCH_EDIT_FRAME::OnUnfoldBus, this );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SCH_EDIT_FRAME::OnUnfoldBusHotkey( wxCommandEvent& aEvent )
|
|
||||||
{
|
|
||||||
SCH_SELECTION_TOOL* selTool = GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
|
|
||||||
EDA_HOTKEY_CLIENT_DATA* data = (EDA_HOTKEY_CLIENT_DATA*) aEvent.GetClientObject();
|
|
||||||
SCH_ITEM* item = GetScreen()->GetCurItem();
|
|
||||||
|
|
||||||
wxCHECK_RET( data != NULL, wxT( "Invalid hot key client object." ) );
|
|
||||||
|
|
||||||
if( item == NULL )
|
|
||||||
{
|
|
||||||
// If we didn't get here by a hot key, then something has gone wrong.
|
|
||||||
if( aEvent.GetInt() == 0 )
|
|
||||||
return;
|
|
||||||
|
|
||||||
item = selTool->SelectPoint( data->GetPosition(), SCH_COLLECTOR::EditableItems );
|
|
||||||
|
|
||||||
// Exit if no item found at the current location or the item is already being edited.
|
|
||||||
if( item == NULL || item->GetEditFlags() != 0 )
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( item->Type() != SCH_LINE_T )
|
|
||||||
return;
|
|
||||||
|
|
||||||
wxMenu* bus_unfold_menu = GetUnfoldBusMenu( static_cast<SCH_LINE*>( item ) );
|
|
||||||
|
|
||||||
if( bus_unfold_menu )
|
|
||||||
{
|
|
||||||
auto controls = GetCanvas()->GetViewControls();
|
|
||||||
auto vmp = controls->GetMousePosition( false );
|
|
||||||
wxPoint mouse_pos( (int) vmp.x, (int) vmp.y );
|
|
||||||
|
|
||||||
GetGalCanvas()->PopupMenu( bus_unfold_menu, mouse_pos );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
wxMenu* SCH_EDIT_FRAME::GetUnfoldBusMenu( SCH_LINE* aBus )
|
|
||||||
{
|
|
||||||
auto connection = aBus->Connection( *g_CurrentSheet );
|
|
||||||
|
|
||||||
if( !connection || !connection->IsBus() || connection->Members().empty() )
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
int idx = 0;
|
|
||||||
wxMenu* bus_unfolding_menu = new wxMenu;
|
|
||||||
|
|
||||||
for( const auto& member : connection->Members() )
|
|
||||||
{
|
|
||||||
int id = ID_POPUP_SCH_UNFOLD_BUS + ( idx++ );
|
|
||||||
wxString name = member->Name( true );
|
|
||||||
|
|
||||||
if( member->Type() == CONNECTION_BUS )
|
|
||||||
{
|
|
||||||
wxMenu* submenu = new wxMenu;
|
|
||||||
bus_unfolding_menu->AppendSubMenu( submenu, _( name ) );
|
|
||||||
|
|
||||||
for( const auto& sub_member : member->Members() )
|
|
||||||
{
|
|
||||||
id = ID_POPUP_SCH_UNFOLD_BUS + ( idx++ );
|
|
||||||
|
|
||||||
submenu->Append( id, sub_member->Name( true ), wxEmptyString );
|
|
||||||
|
|
||||||
// See comment in else clause below
|
|
||||||
auto sub_item_clone = new wxMenuItem();
|
|
||||||
sub_item_clone->SetItemLabel( sub_member->Name( true ) );
|
|
||||||
|
|
||||||
Bind( wxEVT_COMMAND_MENU_SELECTED, &SCH_EDIT_FRAME::OnUnfoldBus, this, id, id,
|
|
||||||
sub_item_clone );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bus_unfolding_menu->Append( id, name, wxEmptyString );
|
|
||||||
|
|
||||||
// Because Bind() takes ownership of the user data item, we
|
|
||||||
// make a new menu item here and set its label. Why create a
|
|
||||||
// menu item instead of just a wxString or something? Because
|
|
||||||
// Bind() requires a pointer to wxObject rather than a void
|
|
||||||
// pointer. Maybe at some point I'll think of a better way...
|
|
||||||
auto item_clone = new wxMenuItem();
|
|
||||||
item_clone->SetItemLabel( name );
|
|
||||||
|
|
||||||
Bind( wxEVT_COMMAND_MENU_SELECTED, &SCH_EDIT_FRAME::OnUnfoldBus, this, id, id,
|
|
||||||
item_clone );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return bus_unfolding_menu;
|
|
||||||
}
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <tools/sch_editor_control.h>
|
#include <tools/sch_editor_control.h>
|
||||||
#include <tools/sch_picker_tool.h>
|
#include <tools/sch_picker_tool.h>
|
||||||
#include <tools/sch_drawing_tool.h>
|
#include <tools/sch_drawing_tool.h>
|
||||||
|
#include <tools/sch_line_drawing_tool.h>
|
||||||
#include <tools/sch_selection_tool.h>
|
#include <tools/sch_selection_tool.h>
|
||||||
#include <tools/sch_actions.h>
|
#include <tools/sch_actions.h>
|
||||||
#include <tools/sch_edit_tool.h>
|
#include <tools/sch_edit_tool.h>
|
||||||
|
@ -288,6 +289,7 @@ void SCH_ACTIONS::RegisterAllTools( TOOL_MANAGER* aToolManager )
|
||||||
aToolManager->RegisterTool( new SCH_EDITOR_CONTROL );
|
aToolManager->RegisterTool( new SCH_EDITOR_CONTROL );
|
||||||
aToolManager->RegisterTool( new SCH_PICKER_TOOL );
|
aToolManager->RegisterTool( new SCH_PICKER_TOOL );
|
||||||
aToolManager->RegisterTool( new SCH_DRAWING_TOOL );
|
aToolManager->RegisterTool( new SCH_DRAWING_TOOL );
|
||||||
|
aToolManager->RegisterTool( new SCH_LINE_DRAWING_TOOL );
|
||||||
aToolManager->RegisterTool( new SCH_EDIT_TOOL );
|
aToolManager->RegisterTool( new SCH_EDIT_TOOL );
|
||||||
aToolManager->RegisterTool( new SCH_INSPECTION_TOOL );
|
aToolManager->RegisterTool( new SCH_INSPECTION_TOOL );
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,6 @@
|
||||||
#include <sch_component.h>
|
#include <sch_component.h>
|
||||||
#include <sch_no_connect.h>
|
#include <sch_no_connect.h>
|
||||||
#include <sch_junction.h>
|
#include <sch_junction.h>
|
||||||
#include <sch_line.h>
|
|
||||||
#include <sch_bus_entry.h>
|
#include <sch_bus_entry.h>
|
||||||
#include <sch_text.h>
|
#include <sch_text.h>
|
||||||
#include <sch_sheet.h>
|
#include <sch_sheet.h>
|
||||||
|
@ -59,29 +58,6 @@ TOOL_ACTION SCH_ACTIONS::placePower( "eeschema.InteractiveDrawing.placePowerPort
|
||||||
_( "Add Power" ), _( "Add a power port" ),
|
_( "Add Power" ), _( "Add a power port" ),
|
||||||
add_power_xpm, AF_ACTIVATE );
|
add_power_xpm, AF_ACTIVATE );
|
||||||
|
|
||||||
TOOL_ACTION SCH_ACTIONS::startWire( "eeschema.InteractiveDrawing.startWire",
|
|
||||||
AS_GLOBAL, 0,
|
|
||||||
_( "Start Wire" ), _( "Start drawing a wire" ),
|
|
||||||
add_line_xpm, AF_ACTIVATE );
|
|
||||||
|
|
||||||
TOOL_ACTION SCH_ACTIONS::drawWire( "eeschema.InteractiveDrawing.drawWire",
|
|
||||||
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_BEGIN_WIRE ),
|
|
||||||
_( "Add Wire" ), _( "Add a wire" ),
|
|
||||||
add_line_xpm, AF_ACTIVATE );
|
|
||||||
|
|
||||||
TOOL_ACTION SCH_ACTIONS::startBus( "eeschema.InteractiveDrawing.startBus",
|
|
||||||
AS_GLOBAL, 0,
|
|
||||||
_( "Start Bus" ), _( "Start drawing a bus" ),
|
|
||||||
add_bus_xpm, AF_ACTIVATE );
|
|
||||||
|
|
||||||
TOOL_ACTION SCH_ACTIONS::drawBus( "eeschema.InteractiveDrawing.drawBus",
|
|
||||||
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_BEGIN_BUS ),
|
|
||||||
_( "Add Bus" ), _( "Add a bus" ),
|
|
||||||
add_bus_xpm, AF_ACTIVATE );
|
|
||||||
|
|
||||||
TOOL_ACTION SCH_ACTIONS::unfoldBus( "eeschema.InteractiveDrawing.unfoldBus",
|
|
||||||
AS_GLOBAL, 0, "", "", nullptr, AF_ACTIVATE );
|
|
||||||
|
|
||||||
TOOL_ACTION SCH_ACTIONS::placeNoConnect( "eeschema.InteractiveDrawing.placeNoConnect",
|
TOOL_ACTION SCH_ACTIONS::placeNoConnect( "eeschema.InteractiveDrawing.placeNoConnect",
|
||||||
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_ADD_NOCONN_FLAG ),
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_ADD_NOCONN_FLAG ),
|
||||||
_( "Add No Connect Flag" ), _( "Add a no-connection flag" ),
|
_( "Add No Connect Flag" ), _( "Add a no-connection flag" ),
|
||||||
|
@ -139,36 +115,10 @@ TOOL_ACTION SCH_ACTIONS::placeSchematicText( "eeschema.InteractiveDrawing.placeS
|
||||||
_( "Add Text" ), _( "Add text" ),
|
_( "Add Text" ), _( "Add text" ),
|
||||||
text_xpm, AF_ACTIVATE );
|
text_xpm, AF_ACTIVATE );
|
||||||
|
|
||||||
TOOL_ACTION SCH_ACTIONS::startLines( "eeschema.InteractiveDrawing.startLines",
|
|
||||||
AS_GLOBAL, 0, _( "Begin Lines" ), _( "Start drawing connected graphic lines" ),
|
|
||||||
add_line_xpm, AF_ACTIVATE );
|
|
||||||
|
|
||||||
TOOL_ACTION SCH_ACTIONS::drawLines( "eeschema.InteractiveDrawing.drawLines",
|
|
||||||
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_ADD_GRAPHIC_POLYLINE ),
|
|
||||||
_( "Add Lines" ), _( "Add connected graphic lines" ),
|
|
||||||
add_graphical_segments_xpm, AF_ACTIVATE );
|
|
||||||
|
|
||||||
TOOL_ACTION SCH_ACTIONS::placeImage( "eeschema.InteractiveDrawing.placeImage",
|
TOOL_ACTION SCH_ACTIONS::placeImage( "eeschema.InteractiveDrawing.placeImage",
|
||||||
AS_GLOBAL, 0, _( "Add Image" ), _( "Add bitmap image" ),
|
AS_GLOBAL, 0, _( "Add Image" ), _( "Add bitmap image" ),
|
||||||
image_xpm, AF_ACTIVATE );
|
image_xpm, AF_ACTIVATE );
|
||||||
|
|
||||||
TOOL_ACTION SCH_ACTIONS::finishLineWireOrBus( "eeschema.InteractiveDrawing.finishLineWireOrBus",
|
|
||||||
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_END_CURR_LINEWIREBUS ),
|
|
||||||
_( "Finish Wire or Bus" ), _( "Complete drawing at current segment" ),
|
|
||||||
checked_ok_xpm, AF_NONE );
|
|
||||||
|
|
||||||
TOOL_ACTION SCH_ACTIONS::finishWire( "eeschema.InteractiveDrawing.finishWire",
|
|
||||||
AS_GLOBAL, 0, _( "Finish Wire" ), _( "Complete wire with current segment" ),
|
|
||||||
checked_ok_xpm, AF_NONE );
|
|
||||||
|
|
||||||
TOOL_ACTION SCH_ACTIONS::finishBus( "eeschema.InteractiveDrawing.finishBus",
|
|
||||||
AS_GLOBAL, 0, _( "Finish Bus" ), _( "Complete bus with current segment" ),
|
|
||||||
checked_ok_xpm, AF_NONE );
|
|
||||||
|
|
||||||
TOOL_ACTION SCH_ACTIONS::finishLine( "eeschema.InteractiveDrawing.finishLine",
|
|
||||||
AS_GLOBAL, 0, _( "Finish Lines" ), _( "Complete connected lines with current segment" ),
|
|
||||||
checked_ok_xpm, AF_NONE );
|
|
||||||
|
|
||||||
TOOL_ACTION SCH_ACTIONS::finishSheet( "eeschema.InteractiveDrawing.finishSheet",
|
TOOL_ACTION SCH_ACTIONS::finishSheet( "eeschema.InteractiveDrawing.finishSheet",
|
||||||
AS_GLOBAL, 0, _( "Finish Sheet" ), _( "Finish drawing sheet" ),
|
AS_GLOBAL, 0, _( "Finish Sheet" ), _( "Finish drawing sheet" ),
|
||||||
checked_ok_xpm, AF_NONE );
|
checked_ok_xpm, AF_NONE );
|
||||||
|
@ -198,7 +148,6 @@ SCH_DRAWING_TOOL::SCH_DRAWING_TOOL() :
|
||||||
m_frame( nullptr ),
|
m_frame( nullptr ),
|
||||||
m_menu( *this )
|
m_menu( *this )
|
||||||
{
|
{
|
||||||
m_busUnfold = {};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -209,8 +158,6 @@ SCH_DRAWING_TOOL::~SCH_DRAWING_TOOL()
|
||||||
|
|
||||||
bool SCH_DRAWING_TOOL::Init()
|
bool SCH_DRAWING_TOOL::Init()
|
||||||
{
|
{
|
||||||
static KICAD_T wireOrBusTypes[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT };
|
|
||||||
|
|
||||||
m_frame = getEditFrame<SCH_EDIT_FRAME>();
|
m_frame = getEditFrame<SCH_EDIT_FRAME>();
|
||||||
m_selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
|
m_selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
|
||||||
|
|
||||||
|
@ -218,24 +165,10 @@ bool SCH_DRAWING_TOOL::Init()
|
||||||
return ( m_frame->GetToolId() != ID_NO_TOOL_SELECTED );
|
return ( m_frame->GetToolId() != ID_NO_TOOL_SELECTED );
|
||||||
};
|
};
|
||||||
|
|
||||||
auto wireOrBusTool = [ this ] ( const SELECTION& aSel ) {
|
|
||||||
return ( m_frame->GetToolId() == ID_WIRE_BUTT || m_frame->GetToolId() == ID_BUS_BUTT );
|
|
||||||
};
|
|
||||||
|
|
||||||
auto lineTool = [ this ] ( const SELECTION& aSel ) {
|
|
||||||
return ( m_frame->GetToolId() == ID_LINE_COMMENT_BUTT );
|
|
||||||
};
|
|
||||||
|
|
||||||
auto sheetTool = [ this ] ( const SELECTION& aSel ) {
|
auto sheetTool = [ this ] ( const SELECTION& aSel ) {
|
||||||
return ( m_frame->GetToolId() == ID_SHEET_SYMBOL_BUTT );
|
return ( m_frame->GetToolId() == ID_SHEET_SYMBOL_BUTT );
|
||||||
};
|
};
|
||||||
|
|
||||||
auto wireOrBusSelectionCondition = SELECTION_CONDITIONS::MoreThan( 0 )
|
|
||||||
&& SELECTION_CONDITIONS::OnlyTypes( wireOrBusTypes );
|
|
||||||
|
|
||||||
auto singleSheetCondition = SELECTION_CONDITIONS::Count( 1 )
|
|
||||||
&& SELECTION_CONDITIONS::OnlyType( SCH_SHEET_T );
|
|
||||||
|
|
||||||
auto& ctxMenu = m_menu.GetMenu();
|
auto& ctxMenu = m_menu.GetMenu();
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -243,44 +176,11 @@ bool SCH_DRAWING_TOOL::Init()
|
||||||
//
|
//
|
||||||
ctxMenu.AddItem( ACTIONS::cancelInteractive, activeTool, 1 );
|
ctxMenu.AddItem( ACTIONS::cancelInteractive, activeTool, 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, sheetTool && SCH_CONDITIONS::Idle, 1 );
|
ctxMenu.AddItem( SCH_ACTIONS::resizeSheet, sheetTool && SCH_CONDITIONS::Idle, 1 );
|
||||||
|
|
||||||
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( activeTool, 1000 );
|
ctxMenu.AddSeparator( activeTool, 1000 );
|
||||||
m_menu.AddStandardSubMenus( m_frame );
|
m_menu.AddStandardSubMenus( m_frame );
|
||||||
|
|
||||||
//
|
|
||||||
// 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::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::importSheetPin, singleSheetCondition, 100 );
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,42 +194,6 @@ 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 )
|
int SCH_DRAWING_TOOL::AddJunction( const TOOL_EVENT& aEvent )
|
||||||
{
|
{
|
||||||
m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true );
|
m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true );
|
||||||
|
@ -890,592 +754,6 @@ int SCH_DRAWING_TOOL::doTwoClickPlace( KICAD_T aType )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int SCH_DRAWING_TOOL::StartWire( const TOOL_EVENT& aEvent )
|
|
||||||
{
|
|
||||||
m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true );
|
|
||||||
|
|
||||||
m_frame->GetCanvas()->MoveCursorToCrossHair();
|
|
||||||
SCH_LINE* segment = startSegments( LAYER_WIRE, m_frame->GetCrossHairPosition() );
|
|
||||||
return doDrawSegments( LAYER_WIRE, segment );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int SCH_DRAWING_TOOL::DrawWire( const TOOL_EVENT& aEvent )
|
|
||||||
{
|
|
||||||
if( m_frame->GetToolId() == ID_WIRE_BUTT )
|
|
||||||
return StartWire( aEvent );
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_frame->SetToolID( ID_WIRE_BUTT, wxCURSOR_PENCIL, _( "Add wire" ) );
|
|
||||||
m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true );
|
|
||||||
|
|
||||||
return doDrawSegments( LAYER_WIRE, nullptr );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int SCH_DRAWING_TOOL::StartBus( const TOOL_EVENT& aEvent )
|
|
||||||
{
|
|
||||||
m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true );
|
|
||||||
|
|
||||||
m_frame->GetCanvas()->MoveCursorToCrossHair();
|
|
||||||
SCH_LINE* segment = startSegments( LAYER_BUS, m_frame->GetCrossHairPosition() );
|
|
||||||
return doDrawSegments( LAYER_BUS, segment );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int SCH_DRAWING_TOOL::DrawBus( const TOOL_EVENT& aEvent )
|
|
||||||
{
|
|
||||||
if( m_frame->GetToolId() == ID_BUS_BUTT )
|
|
||||||
return StartBus( aEvent );
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_frame->SetToolID( ID_BUS_BUTT, wxCURSOR_PENCIL, _( "Add bus" ) );
|
|
||||||
m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true );
|
|
||||||
|
|
||||||
return doDrawSegments( LAYER_BUS, nullptr );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int SCH_DRAWING_TOOL::UnfoldBus( const TOOL_EVENT& aEvent )
|
|
||||||
{
|
|
||||||
wxString net = *aEvent.Parameter<wxString*>();
|
|
||||||
wxPoint pos = m_frame->GetCrossHairPosition();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unfolding a bus consists of the following user inputs:
|
|
||||||
* 1) User selects a bus to unfold (see AddMenusForBus())
|
|
||||||
* We land in this event handler.
|
|
||||||
*
|
|
||||||
* 2) User clicks to set the net label location (handled by BeginSegment())
|
|
||||||
* Before this first click, the posture of the bus entry follows the
|
|
||||||
* mouse cursor in X and Y (handled by DrawSegment())
|
|
||||||
*
|
|
||||||
* 3) User is now in normal wiring mode and can exit in any normal way.
|
|
||||||
*/
|
|
||||||
|
|
||||||
wxASSERT( !m_busUnfold.in_progress );
|
|
||||||
|
|
||||||
m_busUnfold.entry = new SCH_BUS_WIRE_ENTRY( pos, '\\' );
|
|
||||||
m_busUnfold.entry->SetParent( m_frame->GetScreen() );
|
|
||||||
m_frame->AddToScreen( m_busUnfold.entry );
|
|
||||||
|
|
||||||
m_busUnfold.label = new SCH_LABEL( m_busUnfold.entry->m_End(), net );
|
|
||||||
m_busUnfold.label->SetTextSize( wxSize( GetDefaultTextSize(), GetDefaultTextSize() ) );
|
|
||||||
m_busUnfold.label->SetLabelSpinStyle( 0 );
|
|
||||||
m_busUnfold.label->SetParent( m_frame->GetScreen() );
|
|
||||||
|
|
||||||
m_busUnfold.in_progress = true;
|
|
||||||
m_busUnfold.origin = pos;
|
|
||||||
m_busUnfold.net_name = net;
|
|
||||||
|
|
||||||
m_frame->SetToolID( ID_WIRE_BUTT, wxCURSOR_PENCIL, _( "Add wire" ) );
|
|
||||||
|
|
||||||
m_frame->SetCrossHairPosition( m_busUnfold.entry->m_End() );
|
|
||||||
|
|
||||||
SCH_LINE* segment = startSegments( LAYER_WIRE, m_busUnfold.entry->m_End() );
|
|
||||||
return doDrawSegments( LAYER_WIRE, segment );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int SCH_DRAWING_TOOL::StartLines( const TOOL_EVENT& aEvent)
|
|
||||||
{
|
|
||||||
m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true );
|
|
||||||
|
|
||||||
m_frame->GetCanvas()->MoveCursorToCrossHair();
|
|
||||||
SCH_LINE* segment = startSegments( LAYER_NOTES, m_frame->GetCrossHairPosition() );
|
|
||||||
return doDrawSegments( LAYER_BUS, segment );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int SCH_DRAWING_TOOL::DrawLines( const TOOL_EVENT& aEvent)
|
|
||||||
{
|
|
||||||
if( m_frame->GetToolId() == ID_LINE_COMMENT_BUTT )
|
|
||||||
return StartLines( aEvent );
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_frame->SetToolID( ID_LINE_COMMENT_BUTT, wxCURSOR_PENCIL, _( "Add lines" ) );
|
|
||||||
m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true );
|
|
||||||
|
|
||||||
return doDrawSegments( LAYER_NOTES, nullptr );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Storage for the line segments while drawing
|
|
||||||
static DLIST<SCH_LINE> s_wires;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A helper function to find any sheet pins at the specified position.
|
|
||||||
*/
|
|
||||||
static const SCH_SHEET_PIN* getSheetPin( SCH_SCREEN* aScreen, const wxPoint& aPosition )
|
|
||||||
{
|
|
||||||
for( SCH_ITEM* item = aScreen->GetDrawItems(); item; item = item->Next() )
|
|
||||||
{
|
|
||||||
if( item->Type() == SCH_SHEET_T )
|
|
||||||
{
|
|
||||||
SCH_SHEET* sheet = (SCH_SHEET*) item;
|
|
||||||
|
|
||||||
for( const SCH_SHEET_PIN& pin : sheet->GetPins() )
|
|
||||||
{
|
|
||||||
if( pin.GetPosition() == aPosition )
|
|
||||||
return &pin;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function ComputeBreakPoint
|
|
||||||
* computes the middle coordinate for 2 segments from the start point to \a aPosition
|
|
||||||
* with the segments kept in the horizontal or vertical axis only.
|
|
||||||
*
|
|
||||||
* @param aSegment A pointer to a #SCH_LINE object containing the first line break point
|
|
||||||
* to compute.
|
|
||||||
* @param aPosition A reference to a wxPoint object containing the coordinates of the
|
|
||||||
* position used to calculate the line break point.
|
|
||||||
*/
|
|
||||||
static void computeBreakPoint( SCH_SCREEN* aScreen, SCH_LINE* aSegment, wxPoint& aPosition )
|
|
||||||
{
|
|
||||||
wxCHECK_RET( aSegment != nullptr, wxT( "Cannot compute break point of NULL line segment." ) );
|
|
||||||
|
|
||||||
SCH_LINE* nextSegment = aSegment->Next();
|
|
||||||
|
|
||||||
wxPoint midPoint;
|
|
||||||
int iDx = aSegment->GetEndPoint().x - aSegment->GetStartPoint().x;
|
|
||||||
int iDy = aSegment->GetEndPoint().y - aSegment->GetStartPoint().y;
|
|
||||||
|
|
||||||
const SCH_SHEET_PIN* connectedPin = getSheetPin( aScreen, aSegment->GetStartPoint() );
|
|
||||||
auto force = connectedPin ? connectedPin->GetEdge() : SCH_SHEET_PIN::SHEET_UNDEFINED_SIDE;
|
|
||||||
|
|
||||||
if( force == SCH_SHEET_PIN::SHEET_LEFT_SIDE || force == SCH_SHEET_PIN::SHEET_RIGHT_SIDE )
|
|
||||||
{
|
|
||||||
if( aPosition.x == connectedPin->GetPosition().x ) // push outside sheet boundary
|
|
||||||
{
|
|
||||||
int direction = ( force == SCH_SHEET_PIN::SHEET_LEFT_SIDE ) ? -1 : 1;
|
|
||||||
aPosition.x += int( aScreen->GetGridSize().x * direction );
|
|
||||||
}
|
|
||||||
|
|
||||||
midPoint.x = aPosition.x;
|
|
||||||
midPoint.y = aSegment->GetStartPoint().y; // force horizontal
|
|
||||||
}
|
|
||||||
else if( iDy != 0 ) // keep the first segment orientation (vertical)
|
|
||||||
{
|
|
||||||
midPoint.x = aSegment->GetStartPoint().x;
|
|
||||||
midPoint.y = aPosition.y;
|
|
||||||
}
|
|
||||||
else if( iDx != 0 ) // keep the first segment orientation (horizontal)
|
|
||||||
{
|
|
||||||
midPoint.x = aPosition.x;
|
|
||||||
midPoint.y = aSegment->GetStartPoint().y;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if( std::abs( aPosition.x - aSegment->GetStartPoint().x ) <
|
|
||||||
std::abs( aPosition.y - aSegment->GetStartPoint().y ) )
|
|
||||||
{
|
|
||||||
midPoint.x = aSegment->GetStartPoint().x;
|
|
||||||
midPoint.y = aPosition.y;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
midPoint.x = aPosition.x;
|
|
||||||
midPoint.y = aSegment->GetStartPoint().y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
aSegment->SetEndPoint( midPoint );
|
|
||||||
nextSegment->SetStartPoint( midPoint );
|
|
||||||
nextSegment->SetEndPoint( aPosition );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int SCH_DRAWING_TOOL::doDrawSegments( int aType, SCH_LINE* aSegment )
|
|
||||||
{
|
|
||||||
bool forceHV = m_frame->GetForceHVLines();
|
|
||||||
SCH_SCREEN* screen = m_frame->GetScreen();
|
|
||||||
|
|
||||||
m_controls->ShowCursor( true );
|
|
||||||
|
|
||||||
Activate();
|
|
||||||
|
|
||||||
// Main loop: keep receiving events
|
|
||||||
while( OPT_TOOL_EVENT evt = Wait() )
|
|
||||||
{
|
|
||||||
wxPoint cursorPos = (wxPoint)m_controls->GetCursorPosition( !evt->Modifier( MD_ALT ) );
|
|
||||||
|
|
||||||
if( TOOL_EVT_UTILS::IsCancelInteractive( evt.get() ) )
|
|
||||||
{
|
|
||||||
if( aSegment || m_busUnfold.in_progress )
|
|
||||||
{
|
|
||||||
m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true );
|
|
||||||
|
|
||||||
aSegment = nullptr;
|
|
||||||
s_wires.DeleteAll();
|
|
||||||
|
|
||||||
if( m_busUnfold.entry )
|
|
||||||
m_frame->RemoveFromScreen( m_busUnfold.entry );
|
|
||||||
|
|
||||||
if( m_busUnfold.label && m_busUnfold.label_placed )
|
|
||||||
m_frame->RemoveFromScreen( m_busUnfold.label );
|
|
||||||
|
|
||||||
delete m_busUnfold.entry;
|
|
||||||
delete m_busUnfold.label;
|
|
||||||
m_busUnfold = {};
|
|
||||||
|
|
||||||
m_view->ClearPreview();
|
|
||||||
m_view->ShowPreview( false );
|
|
||||||
|
|
||||||
// Clear flags used in edit functions.
|
|
||||||
screen->ClearDrawingState();
|
|
||||||
screen->SetCurItem( nullptr );
|
|
||||||
|
|
||||||
if( !evt->IsActivate() )
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( evt->IsAction( &SCH_ACTIONS::drawWire ) && aType == LAYER_WIRE )
|
|
||||||
; // don't cancel tool; we're going to re-enter
|
|
||||||
else if( evt->IsAction( &SCH_ACTIONS::drawBus ) && aType == LAYER_BUS )
|
|
||||||
; // don't cancel tool; we're going to re-enter
|
|
||||||
else
|
|
||||||
m_frame->SetNoToolSelected();
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if( evt->IsAction( &SCH_ACTIONS::finishLineWireOrBus )
|
|
||||||
|| evt->IsAction( &SCH_ACTIONS::finishWire )
|
|
||||||
|| evt->IsAction( &SCH_ACTIONS::finishBus )
|
|
||||||
|| evt->IsAction( &SCH_ACTIONS::finishLine ) )
|
|
||||||
{
|
|
||||||
if( aSegment || m_busUnfold.in_progress )
|
|
||||||
{
|
|
||||||
finishSegments();
|
|
||||||
aSegment = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( m_frame->GetToolId() == ID_NO_TOOL_SELECTED )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if( evt->IsClick( BUT_RIGHT ) )
|
|
||||||
{
|
|
||||||
// Warp after context menu only if dragging...
|
|
||||||
if( !aSegment )
|
|
||||||
m_toolMgr->VetoContextMenuMouseWarp();
|
|
||||||
|
|
||||||
m_menu.ShowContextMenu( m_selectionTool->GetSelection() );
|
|
||||||
}
|
|
||||||
else if( evt->IsClick( BUT_LEFT ) || ( aSegment && evt->IsDblClick( BUT_LEFT ) ) )
|
|
||||||
{
|
|
||||||
// First click when unfolding places the label and wire-to-bus entry
|
|
||||||
if( m_busUnfold.in_progress && !m_busUnfold.label_placed )
|
|
||||||
{
|
|
||||||
wxASSERT( aType == LAYER_WIRE );
|
|
||||||
|
|
||||||
m_frame->AddToScreen( m_busUnfold.label );
|
|
||||||
m_busUnfold.label_placed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !aSegment )
|
|
||||||
{
|
|
||||||
aSegment = startSegments( aType, cursorPos );
|
|
||||||
}
|
|
||||||
// Create a new segment if we're out of previously-created ones
|
|
||||||
else if( !aSegment->IsNull() || ( forceHV && !aSegment->Back()->IsNull() ) )
|
|
||||||
{
|
|
||||||
// Terminate the command if the end point is on a pin, junction, or another
|
|
||||||
// wire or bus.
|
|
||||||
if( !m_busUnfold.in_progress
|
|
||||||
&& screen->IsTerminalPoint( cursorPos, aSegment->GetLayer() ) )
|
|
||||||
{
|
|
||||||
finishSegments();
|
|
||||||
aSegment = nullptr;
|
|
||||||
|
|
||||||
if( m_frame->GetToolId() == ID_NO_TOOL_SELECTED )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
aSegment->SetEndPoint( cursorPos );
|
|
||||||
|
|
||||||
// Create a new segment, and chain it after the current segment.
|
|
||||||
aSegment = new SCH_LINE( *aSegment );
|
|
||||||
aSegment->SetFlags( IS_NEW | IS_MOVED );
|
|
||||||
aSegment->SetStartPoint( cursorPos );
|
|
||||||
s_wires.PushBack( aSegment );
|
|
||||||
m_selectionTool->AddItemToSel( aSegment, true /*quiet mode*/ );
|
|
||||||
screen->SetCurItem( aSegment );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( evt->IsDblClick( BUT_LEFT ) )
|
|
||||||
{
|
|
||||||
finishSegments();
|
|
||||||
aSegment = nullptr;
|
|
||||||
|
|
||||||
if( m_frame->GetToolId() == ID_NO_TOOL_SELECTED )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if( evt->IsMotion() )
|
|
||||||
{
|
|
||||||
m_view->ClearPreview();
|
|
||||||
|
|
||||||
// Update the bus unfold posture based on the mouse movement
|
|
||||||
if( m_busUnfold.in_progress && !m_busUnfold.label_placed )
|
|
||||||
{
|
|
||||||
wxPoint cursor_delta = cursorPos - m_busUnfold.origin;
|
|
||||||
SCH_BUS_WIRE_ENTRY* entry = m_busUnfold.entry;
|
|
||||||
|
|
||||||
bool offset = ( cursor_delta.x < 0 );
|
|
||||||
char shape = ( offset ? ( ( cursor_delta.y >= 0 ) ? '/' : '\\' )
|
|
||||||
: ( ( cursor_delta.y >= 0 ) ? '\\' : '/' ) );
|
|
||||||
|
|
||||||
// Erase and redraw if necessary
|
|
||||||
if( shape != entry->GetBusEntryShape() || offset != m_busUnfold.offset )
|
|
||||||
{
|
|
||||||
entry->SetBusEntryShape( shape );
|
|
||||||
wxPoint entry_pos = m_busUnfold.origin;
|
|
||||||
|
|
||||||
if( offset )
|
|
||||||
entry_pos -= entry->GetSize();
|
|
||||||
|
|
||||||
entry->SetPosition( entry_pos );
|
|
||||||
m_busUnfold.offset = offset;
|
|
||||||
|
|
||||||
m_frame->RefreshItem( entry );
|
|
||||||
|
|
||||||
wxPoint wire_start = offset ? entry->GetPosition() : entry->m_End();
|
|
||||||
s_wires.begin()->SetStartPoint( wire_start );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the label "ghost" position
|
|
||||||
m_busUnfold.label->SetPosition( cursorPos );
|
|
||||||
m_view->AddToPreview( m_busUnfold.label->Clone() );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( aSegment )
|
|
||||||
{
|
|
||||||
// Coerce the line to vertical or horizontal if necessary
|
|
||||||
if( forceHV )
|
|
||||||
computeBreakPoint( screen, aSegment->Back(), cursorPos );
|
|
||||||
else
|
|
||||||
aSegment->SetEndPoint( cursorPos );
|
|
||||||
}
|
|
||||||
|
|
||||||
for( auto seg = s_wires.begin(); seg; seg = seg->Next() )
|
|
||||||
{
|
|
||||||
if( !seg->IsNull() ) // Add to preview if segment length != 0
|
|
||||||
m_view->AddToPreview( seg->Clone() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable autopanning and cursor capture only when there is a segment to be placed
|
|
||||||
m_controls->SetAutoPan( !!aSegment );
|
|
||||||
m_controls->CaptureCursor( !!aSegment );
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SCH_LINE* SCH_DRAWING_TOOL::startSegments( int aType, const wxPoint& aPos )
|
|
||||||
{
|
|
||||||
SCH_LINE* segment = nullptr;
|
|
||||||
bool forceHV = m_frame->GetForceHVLines();
|
|
||||||
|
|
||||||
switch( aType )
|
|
||||||
{
|
|
||||||
default: segment = new SCH_LINE( aPos, LAYER_NOTES ); break;
|
|
||||||
case LAYER_WIRE: segment = new SCH_LINE( aPos, LAYER_WIRE ); break;
|
|
||||||
case LAYER_BUS: segment = new SCH_LINE( aPos, LAYER_BUS ); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
segment->SetFlags( IS_NEW | IS_MOVED );
|
|
||||||
s_wires.PushBack( segment );
|
|
||||||
m_selectionTool->AddItemToSel( segment, true /*quiet mode*/ );
|
|
||||||
m_frame->GetScreen()->SetCurItem( segment );
|
|
||||||
|
|
||||||
// We need 2 segments to go from a given start pin to an end point when the
|
|
||||||
// horizontal and vertical lines only switch is on.
|
|
||||||
if( forceHV )
|
|
||||||
{
|
|
||||||
segment = new SCH_LINE( *segment );
|
|
||||||
segment->SetFlags( IS_NEW | IS_MOVED );
|
|
||||||
s_wires.PushBack( segment );
|
|
||||||
m_selectionTool->AddItemToSel( segment, true /*quiet mode*/ );
|
|
||||||
m_frame->GetScreen()->SetCurItem( segment );
|
|
||||||
}
|
|
||||||
|
|
||||||
return segment;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* In a contiguous list of wires, remove wires that backtrack over the previous
|
|
||||||
* wire. Example:
|
|
||||||
*
|
|
||||||
* Wire is added:
|
|
||||||
* ---------------------------------------->
|
|
||||||
*
|
|
||||||
* A second wire backtracks over it:
|
|
||||||
* -------------------<====================>
|
|
||||||
*
|
|
||||||
* RemoveBacktracks is called:
|
|
||||||
* ------------------->
|
|
||||||
*/
|
|
||||||
static void removeBacktracks( DLIST<SCH_LINE>& aWires )
|
|
||||||
{
|
|
||||||
SCH_LINE* next = nullptr;
|
|
||||||
std::vector<SCH_LINE*> last_lines;
|
|
||||||
|
|
||||||
for( SCH_LINE* line = aWires.GetFirst(); line; line = next )
|
|
||||||
{
|
|
||||||
next = line->Next();
|
|
||||||
|
|
||||||
if( line->IsNull() )
|
|
||||||
{
|
|
||||||
delete s_wires.Remove( line );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !last_lines.empty() )
|
|
||||||
{
|
|
||||||
SCH_LINE* last_line = last_lines[last_lines.size() - 1];
|
|
||||||
bool contiguous = ( last_line->GetEndPoint() == line->GetStartPoint() );
|
|
||||||
bool backtracks = IsPointOnSegment( last_line->GetStartPoint(),
|
|
||||||
last_line->GetEndPoint(), line->GetEndPoint() );
|
|
||||||
bool total_backtrack = ( last_line->GetStartPoint() == line->GetEndPoint() );
|
|
||||||
|
|
||||||
if( contiguous && backtracks )
|
|
||||||
{
|
|
||||||
if( total_backtrack )
|
|
||||||
{
|
|
||||||
delete s_wires.Remove( last_line );
|
|
||||||
delete s_wires.Remove( line );
|
|
||||||
last_lines.pop_back();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
last_line->SetEndPoint( line->GetEndPoint() );
|
|
||||||
delete s_wires.Remove( line );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
last_lines.push_back( line );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
last_lines.push_back( line );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SCH_DRAWING_TOOL::finishSegments()
|
|
||||||
{
|
|
||||||
// Clear selection when done so that a new wire can be started.
|
|
||||||
// NOTE: this must be done before RemoveBacktracks is called or we might end up with
|
|
||||||
// freed selected items.
|
|
||||||
m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true );
|
|
||||||
|
|
||||||
PICKED_ITEMS_LIST itemList;
|
|
||||||
|
|
||||||
// Remove segments backtracking over others
|
|
||||||
removeBacktracks( s_wires );
|
|
||||||
|
|
||||||
// Collect the possible connection points for the new lines
|
|
||||||
std::vector< wxPoint > connections;
|
|
||||||
std::vector< wxPoint > new_ends;
|
|
||||||
m_frame->GetSchematicConnections( connections );
|
|
||||||
|
|
||||||
// Check each new segment for possible junctions and add/split if needed
|
|
||||||
for( SCH_LINE* wire = s_wires.GetFirst(); wire; wire = wire->Next() )
|
|
||||||
{
|
|
||||||
if( wire->GetFlags() & SKIP_STRUCT )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
wire->GetConnectionPoints( new_ends );
|
|
||||||
|
|
||||||
for( auto i : connections )
|
|
||||||
{
|
|
||||||
if( IsPointOnSegment( wire->GetStartPoint(), wire->GetEndPoint(), i ) )
|
|
||||||
new_ends.push_back( i );
|
|
||||||
}
|
|
||||||
itemList.PushItem( ITEM_PICKER( wire, UR_NEW ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( m_busUnfold.in_progress && m_busUnfold.label_placed )
|
|
||||||
{
|
|
||||||
wxASSERT( m_busUnfold.entry && m_busUnfold.label );
|
|
||||||
|
|
||||||
itemList.PushItem( ITEM_PICKER( m_busUnfold.entry, UR_NEW ) );
|
|
||||||
itemList.PushItem( ITEM_PICKER( m_busUnfold.label, UR_NEW ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the last non-null wire (this is the last created segment).
|
|
||||||
m_frame->SetRepeatItem( s_wires.GetLast() );
|
|
||||||
|
|
||||||
// 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_controls->CaptureCursor( false );
|
|
||||||
m_controls->SetAutoPan( false );
|
|
||||||
|
|
||||||
m_frame->SaveCopyInUndoList( itemList, UR_NEW );
|
|
||||||
|
|
||||||
// Correct and remove segments that need to be merged.
|
|
||||||
m_frame->SchematicCleanUp( true );
|
|
||||||
|
|
||||||
for( auto item = m_frame->GetScreen()->GetDrawItems(); item; item = item->Next() )
|
|
||||||
{
|
|
||||||
if( item->Type() != SCH_COMPONENT_T )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
std::vector< wxPoint > pts;
|
|
||||||
item->GetConnectionPoints( pts );
|
|
||||||
|
|
||||||
if( pts.size() > 2 )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for( auto i = pts.begin(); i != pts.end(); i++ )
|
|
||||||
{
|
|
||||||
for( auto j = i + 1; j != pts.end(); j++ )
|
|
||||||
m_frame->TrimWire( *i, *j, true );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for( auto i : new_ends )
|
|
||||||
{
|
|
||||||
if( m_frame->GetScreen()->IsJunctionNeeded( i, true ) )
|
|
||||||
m_frame->AddJunction( i, true, false );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( m_busUnfold.in_progress )
|
|
||||||
m_busUnfold = {};
|
|
||||||
|
|
||||||
m_frame->TestDanglingEnds();
|
|
||||||
|
|
||||||
m_frame->GetScreen()->ClearDrawingState();
|
|
||||||
m_frame->GetScreen()->SetCurItem( nullptr );
|
|
||||||
m_frame->OnModify();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int SCH_DRAWING_TOOL::DrawSheet( const TOOL_EVENT& aEvent )
|
int SCH_DRAWING_TOOL::DrawSheet( const TOOL_EVENT& aEvent )
|
||||||
{
|
{
|
||||||
m_frame->SetToolID( ID_SHEET_SYMBOL_BUTT, wxCURSOR_PENCIL, _( "Add sheet" ) );
|
m_frame->SetToolID( ID_SHEET_SYMBOL_BUTT, wxCURSOR_PENCIL, _( "Add sheet" ) );
|
||||||
|
@ -1642,9 +920,6 @@ void SCH_DRAWING_TOOL::setTransitions()
|
||||||
{
|
{
|
||||||
Go( &SCH_DRAWING_TOOL::PlaceSymbol, SCH_ACTIONS::placeSymbol.MakeEvent() );
|
Go( &SCH_DRAWING_TOOL::PlaceSymbol, SCH_ACTIONS::placeSymbol.MakeEvent() );
|
||||||
Go( &SCH_DRAWING_TOOL::PlacePower, SCH_ACTIONS::placePower.MakeEvent() );
|
Go( &SCH_DRAWING_TOOL::PlacePower, SCH_ACTIONS::placePower.MakeEvent() );
|
||||||
Go( &SCH_DRAWING_TOOL::DrawWire, SCH_ACTIONS::drawWire.MakeEvent() );
|
|
||||||
Go( &SCH_DRAWING_TOOL::DrawBus, SCH_ACTIONS::drawBus.MakeEvent() );
|
|
||||||
Go( &SCH_DRAWING_TOOL::UnfoldBus, SCH_ACTIONS::unfoldBus.MakeEvent() );
|
|
||||||
Go( &SCH_DRAWING_TOOL::PlaceNoConnect, SCH_ACTIONS::placeNoConnect.MakeEvent() );
|
Go( &SCH_DRAWING_TOOL::PlaceNoConnect, SCH_ACTIONS::placeNoConnect.MakeEvent() );
|
||||||
Go( &SCH_DRAWING_TOOL::PlaceJunction, SCH_ACTIONS::placeJunction.MakeEvent() );
|
Go( &SCH_DRAWING_TOOL::PlaceJunction, SCH_ACTIONS::placeJunction.MakeEvent() );
|
||||||
Go( &SCH_DRAWING_TOOL::PlaceBusWireEntry, SCH_ACTIONS::placeBusWireEntry.MakeEvent() );
|
Go( &SCH_DRAWING_TOOL::PlaceBusWireEntry, SCH_ACTIONS::placeBusWireEntry.MakeEvent() );
|
||||||
|
@ -1657,12 +932,8 @@ void SCH_DRAWING_TOOL::setTransitions()
|
||||||
Go( &SCH_DRAWING_TOOL::PlaceSheetPin, SCH_ACTIONS::placeSheetPin.MakeEvent() );
|
Go( &SCH_DRAWING_TOOL::PlaceSheetPin, SCH_ACTIONS::placeSheetPin.MakeEvent() );
|
||||||
Go( &SCH_DRAWING_TOOL::ImportSheetPin, SCH_ACTIONS::importSheetPin.MakeEvent() );
|
Go( &SCH_DRAWING_TOOL::ImportSheetPin, SCH_ACTIONS::importSheetPin.MakeEvent() );
|
||||||
Go( &SCH_DRAWING_TOOL::PlaceSchematicText, SCH_ACTIONS::placeSchematicText.MakeEvent() );
|
Go( &SCH_DRAWING_TOOL::PlaceSchematicText, SCH_ACTIONS::placeSchematicText.MakeEvent() );
|
||||||
Go( &SCH_DRAWING_TOOL::DrawLines, SCH_ACTIONS::drawLines.MakeEvent() );
|
|
||||||
Go( &SCH_DRAWING_TOOL::PlaceImage, SCH_ACTIONS::placeImage.MakeEvent() );
|
Go( &SCH_DRAWING_TOOL::PlaceImage, SCH_ACTIONS::placeImage.MakeEvent() );
|
||||||
|
|
||||||
Go( &SCH_DRAWING_TOOL::StartWire, SCH_ACTIONS::startWire.MakeEvent() );
|
|
||||||
Go( &SCH_DRAWING_TOOL::StartBus, SCH_ACTIONS::startBus.MakeEvent() );
|
|
||||||
Go( &SCH_DRAWING_TOOL::StartLines, SCH_ACTIONS::startLines.MakeEvent() );
|
|
||||||
Go( &SCH_DRAWING_TOOL::AddJunction, SCH_ACTIONS::addJunction.MakeEvent() );
|
Go( &SCH_DRAWING_TOOL::AddJunction, SCH_ACTIONS::addJunction.MakeEvent() );
|
||||||
Go( &SCH_DRAWING_TOOL::AddLabel, SCH_ACTIONS::addLabel.MakeEvent() );
|
Go( &SCH_DRAWING_TOOL::AddLabel, SCH_ACTIONS::addLabel.MakeEvent() );
|
||||||
Go( &SCH_DRAWING_TOOL::AddLabel, SCH_ACTIONS::addGlobalLabel.MakeEvent() );
|
Go( &SCH_DRAWING_TOOL::AddLabel, SCH_ACTIONS::addGlobalLabel.MakeEvent() );
|
||||||
|
|
|
@ -38,21 +38,6 @@ class SCH_EDIT_FRAME;
|
||||||
class SCH_SELECTION_TOOL;
|
class SCH_SELECTION_TOOL;
|
||||||
|
|
||||||
|
|
||||||
/// Collection of data related to the bus unfolding tool
|
|
||||||
struct BUS_UNFOLDING_T
|
|
||||||
{
|
|
||||||
bool in_progress; ///< True if bus unfold operation is running
|
|
||||||
bool offset; ///< True if the bus entry should be offset from origin
|
|
||||||
bool label_placed; ///< True if user has placed the net label
|
|
||||||
|
|
||||||
wxPoint origin; ///< Origin (on the bus) of the unfold
|
|
||||||
wxString net_name; ///< Net label for the unfolding operation
|
|
||||||
|
|
||||||
SCH_BUS_WIRE_ENTRY* entry;
|
|
||||||
SCH_LABEL* label;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class SCH_DRAWING_TOOL
|
* Class SCH_DRAWING_TOOL
|
||||||
*
|
*
|
||||||
|
@ -74,17 +59,11 @@ public:
|
||||||
///> Get the SCH_DRAWING_TOOL top-level context menu
|
///> Get the SCH_DRAWING_TOOL top-level context menu
|
||||||
inline TOOL_MENU& GetToolMenu() { return m_menu; }
|
inline TOOL_MENU& GetToolMenu() { return m_menu; }
|
||||||
|
|
||||||
int StartWire( const TOOL_EVENT& aEvent );
|
|
||||||
int StartBus( const TOOL_EVENT& aEvent );
|
|
||||||
int StartLines( const TOOL_EVENT& aEvent );
|
|
||||||
int AddJunction( const TOOL_EVENT& aEvent );
|
int AddJunction( const TOOL_EVENT& aEvent );
|
||||||
int AddLabel( const TOOL_EVENT& aEvent );
|
int AddLabel( const TOOL_EVENT& aEvent );
|
||||||
|
|
||||||
int PlaceSymbol( const TOOL_EVENT& aEvent );
|
int PlaceSymbol( const TOOL_EVENT& aEvent );
|
||||||
int PlacePower( const TOOL_EVENT& aEvent );
|
int PlacePower( const TOOL_EVENT& aEvent );
|
||||||
int DrawWire( const TOOL_EVENT& aEvent );
|
|
||||||
int DrawBus( const TOOL_EVENT& aEvent );
|
|
||||||
int UnfoldBus( const TOOL_EVENT& aEvent );
|
|
||||||
int PlaceNoConnect( const TOOL_EVENT& aEvent );
|
int PlaceNoConnect( const TOOL_EVENT& aEvent );
|
||||||
int PlaceJunction( const TOOL_EVENT& aEvent );
|
int PlaceJunction( const TOOL_EVENT& aEvent );
|
||||||
int PlaceBusWireEntry( const TOOL_EVENT& aEvent );
|
int PlaceBusWireEntry( const TOOL_EVENT& aEvent );
|
||||||
|
@ -97,19 +76,10 @@ public:
|
||||||
int PlaceSheetPin( const TOOL_EVENT& aEvent );
|
int PlaceSheetPin( const TOOL_EVENT& aEvent );
|
||||||
int ImportSheetPin( const TOOL_EVENT& aEvent );
|
int ImportSheetPin( const TOOL_EVENT& aEvent );
|
||||||
int PlaceSchematicText( const TOOL_EVENT& aEvent );
|
int PlaceSchematicText( const TOOL_EVENT& aEvent );
|
||||||
int DrawLines( const TOOL_EVENT& aEvent );
|
|
||||||
int PlaceImage( 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:
|
private:
|
||||||
|
|
||||||
int doAddItem( KICAD_T aType );
|
|
||||||
|
|
||||||
int doPlaceComponent( SCH_COMPONENT* aComponent, SCHLIB_FILTER* aFilter,
|
int doPlaceComponent( SCH_COMPONENT* aComponent, SCHLIB_FILTER* aFilter,
|
||||||
SCH_BASE_FRAME::HISTORY_LIST aHistoryList );
|
SCH_BASE_FRAME::HISTORY_LIST aHistoryList );
|
||||||
|
|
||||||
|
@ -117,10 +87,6 @@ private:
|
||||||
|
|
||||||
int doTwoClickPlace( KICAD_T aType );
|
int doTwoClickPlace( KICAD_T aType );
|
||||||
|
|
||||||
int doDrawSegments( int aType, SCH_LINE* aSegment );
|
|
||||||
SCH_LINE* startSegments( int aType, const wxPoint& aPos );
|
|
||||||
void finishSegments();
|
|
||||||
|
|
||||||
int doDrawSheet( SCH_SHEET* aSheet );
|
int doDrawSheet( SCH_SHEET* aSheet );
|
||||||
void sizeSheet( SCH_SHEET* aSheet, VECTOR2I aPos );
|
void sizeSheet( SCH_SHEET* aSheet, VECTOR2I aPos );
|
||||||
|
|
||||||
|
@ -133,9 +99,6 @@ private:
|
||||||
KIGFX::VIEW_CONTROLS* m_controls;
|
KIGFX::VIEW_CONTROLS* m_controls;
|
||||||
SCH_EDIT_FRAME* m_frame;
|
SCH_EDIT_FRAME* m_frame;
|
||||||
|
|
||||||
/// Data related to bus unfolding tool.
|
|
||||||
BUS_UNFOLDING_T m_busUnfold;
|
|
||||||
|
|
||||||
TOOL_MENU m_menu;
|
TOOL_MENU m_menu;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <tool/tool_manager.h>
|
#include <tool/tool_manager.h>
|
||||||
#include <tools/sch_edit_tool.h>
|
#include <tools/sch_edit_tool.h>
|
||||||
#include <tools/sch_selection_tool.h>
|
#include <tools/sch_selection_tool.h>
|
||||||
|
#include <tools/sch_line_drawing_tool.h>
|
||||||
#include <tools/sch_picker_tool.h>
|
#include <tools/sch_picker_tool.h>
|
||||||
#include <sch_actions.h>
|
#include <sch_actions.h>
|
||||||
#include <hotkeys.h>
|
#include <hotkeys.h>
|
||||||
|
@ -208,7 +209,7 @@ bool SCH_EDIT_TOOL::Init()
|
||||||
if( aSel.Empty() )
|
if( aSel.Empty() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if( SCH_DRAWING_TOOL::IsDrawingLineWireOrBus( aSel ) )
|
if( SCH_LINE_DRAWING_TOOL::IsDrawingLineWireOrBus( aSel ) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -218,7 +219,7 @@ bool SCH_EDIT_TOOL::Init()
|
||||||
if( aSel.Empty() )
|
if( aSel.Empty() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if( SCH_DRAWING_TOOL::IsDrawingLineWireOrBus( aSel ) )
|
if( SCH_LINE_DRAWING_TOOL::IsDrawingLineWireOrBus( aSel ) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
SCH_ITEM* item = (SCH_ITEM*) aSel.Front();
|
SCH_ITEM* item = (SCH_ITEM*) aSel.Front();
|
||||||
|
@ -334,7 +335,7 @@ bool SCH_EDIT_TOOL::Init()
|
||||||
//
|
//
|
||||||
CONDITIONAL_MENU& drawingMenu = drawingTool->GetToolMenu().GetMenu();
|
CONDITIONAL_MENU& drawingMenu = drawingTool->GetToolMenu().GetMenu();
|
||||||
|
|
||||||
ctxMenu.AddSeparator( SCH_CONDITIONS::NotEmpty, 200 );
|
drawingMenu.AddSeparator( SCH_CONDITIONS::NotEmpty, 200 );
|
||||||
drawingMenu.AddItem( SCH_ACTIONS::rotateCCW, orientCondition, 200 );
|
drawingMenu.AddItem( SCH_ACTIONS::rotateCCW, orientCondition, 200 );
|
||||||
drawingMenu.AddItem( SCH_ACTIONS::rotateCW, orientCondition, 200 );
|
drawingMenu.AddItem( SCH_ACTIONS::rotateCW, orientCondition, 200 );
|
||||||
drawingMenu.AddItem( SCH_ACTIONS::mirrorX, orientCondition, 200 );
|
drawingMenu.AddItem( SCH_ACTIONS::mirrorX, orientCondition, 200 );
|
||||||
|
@ -352,10 +353,6 @@ bool SCH_EDIT_TOOL::Init()
|
||||||
drawingMenu.AddItem( SCH_ACTIONS::toHLabel, toHLabelCondition, 200 );
|
drawingMenu.AddItem( SCH_ACTIONS::toHLabel, toHLabelCondition, 200 );
|
||||||
drawingMenu.AddItem( SCH_ACTIONS::toGLabel, toGLabelCondition, 200 );
|
drawingMenu.AddItem( SCH_ACTIONS::toGLabel, toGLabelCondition, 200 );
|
||||||
drawingMenu.AddItem( SCH_ACTIONS::toText, toTextlCondition, 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
|
// Add editing actions to the selection tool menu
|
||||||
|
@ -384,8 +381,6 @@ bool SCH_EDIT_TOOL::Init()
|
||||||
selToolMenu.AddItem( SCH_ACTIONS::toHLabel, toHLabelCondition, 200 );
|
selToolMenu.AddItem( SCH_ACTIONS::toHLabel, toHLabelCondition, 200 );
|
||||||
selToolMenu.AddItem( SCH_ACTIONS::toGLabel, toGLabelCondition, 200 );
|
selToolMenu.AddItem( SCH_ACTIONS::toGLabel, toGLabelCondition, 200 );
|
||||||
selToolMenu.AddItem( SCH_ACTIONS::toText, toTextlCondition, 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.AddItem( SCH_ACTIONS::cleanupSheetPins, singleSheetCondition, 200 );
|
||||||
|
|
||||||
selToolMenu.AddSeparator( SCH_CONDITIONS::Idle, 200 );
|
selToolMenu.AddSeparator( SCH_CONDITIONS::Idle, 200 );
|
||||||
|
|
|
@ -73,8 +73,8 @@ bool SCH_INSPECTION_TOOL::Init()
|
||||||
//
|
//
|
||||||
CONDITIONAL_MENU& selToolMenu = m_selectionTool->GetToolMenu().GetMenu();
|
CONDITIONAL_MENU& selToolMenu = m_selectionTool->GetToolMenu().GetMenu();
|
||||||
|
|
||||||
selToolMenu.AddItem( SCH_ACTIONS::showDatasheet, SCH_CONDITIONS::SingleSymbol, 400 );
|
selToolMenu.AddItem( SCH_ACTIONS::showDatasheet, SCH_CONDITIONS::SingleSymbol && SCH_CONDITIONS::Idle, 400 );
|
||||||
selToolMenu.AddItem( SCH_ACTIONS::showMarkerInfo, singleMarkerCondition, 400 );
|
selToolMenu.AddItem( SCH_ACTIONS::showMarkerInfo, singleMarkerCondition && SCH_CONDITIONS::Idle, 400 );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,806 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sch_line_drawing_tool.h>
|
||||||
|
#include <sch_selection_tool.h>
|
||||||
|
#include <sch_actions.h>
|
||||||
|
#include <sch_edit_frame.h>
|
||||||
|
#include <sch_view.h>
|
||||||
|
#include <class_draw_panel_gal.h>
|
||||||
|
#include <id.h>
|
||||||
|
#include <eeschema_id.h>
|
||||||
|
#include <confirm.h>
|
||||||
|
#include <view/view_group.h>
|
||||||
|
#include <view/view_controls.h>
|
||||||
|
#include <view/view.h>
|
||||||
|
#include <tool/tool_manager.h>
|
||||||
|
#include <hotkeys.h>
|
||||||
|
#include <sch_junction.h>
|
||||||
|
#include <sch_line.h>
|
||||||
|
#include <sch_bus_entry.h>
|
||||||
|
#include <sch_text.h>
|
||||||
|
#include <sch_sheet.h>
|
||||||
|
|
||||||
|
|
||||||
|
TOOL_ACTION SCH_ACTIONS::startWire( "eeschema.InteractiveLineDrawing.startWire",
|
||||||
|
AS_GLOBAL, 0,
|
||||||
|
_( "Start Wire" ), _( "Start drawing a wire" ),
|
||||||
|
add_line_xpm, AF_ACTIVATE );
|
||||||
|
|
||||||
|
TOOL_ACTION SCH_ACTIONS::drawWire( "eeschema.InteractiveLineDrawing.drawWire",
|
||||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_BEGIN_WIRE ),
|
||||||
|
_( "Add Wire" ), _( "Add a wire" ),
|
||||||
|
add_line_xpm, AF_ACTIVATE );
|
||||||
|
|
||||||
|
TOOL_ACTION SCH_ACTIONS::startBus( "eeschema.InteractiveLineDrawing.startBus",
|
||||||
|
AS_GLOBAL, 0,
|
||||||
|
_( "Start Bus" ), _( "Start drawing a bus" ),
|
||||||
|
add_bus_xpm, AF_ACTIVATE );
|
||||||
|
|
||||||
|
TOOL_ACTION SCH_ACTIONS::drawBus( "eeschema.InteractiveLineDrawing.drawBus",
|
||||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_BEGIN_BUS ),
|
||||||
|
_( "Add Bus" ), _( "Add a bus" ),
|
||||||
|
add_bus_xpm, AF_ACTIVATE );
|
||||||
|
|
||||||
|
TOOL_ACTION SCH_ACTIONS::unfoldBus( "eeschema.InteractiveLineDrawing.unfoldBus",
|
||||||
|
AS_GLOBAL, 0, "", "", nullptr, AF_ACTIVATE );
|
||||||
|
|
||||||
|
TOOL_ACTION SCH_ACTIONS::startLines( "eeschema.InteractiveLineDrawing.startLines",
|
||||||
|
AS_GLOBAL, 0, _( "Begin Lines" ), _( "Start drawing connected graphic lines" ),
|
||||||
|
add_line_xpm, AF_ACTIVATE );
|
||||||
|
|
||||||
|
TOOL_ACTION SCH_ACTIONS::drawLines( "eeschema.InteractiveLineDrawing.drawLines",
|
||||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_ADD_GRAPHIC_POLYLINE ),
|
||||||
|
_( "Add Lines" ), _( "Add connected graphic lines" ),
|
||||||
|
add_graphical_segments_xpm, AF_ACTIVATE );
|
||||||
|
|
||||||
|
TOOL_ACTION SCH_ACTIONS::finishLineWireOrBus( "eeschema.InteractiveLineDrawing.finishLineWireOrBus",
|
||||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_END_CURR_LINEWIREBUS ),
|
||||||
|
_( "Finish Wire or Bus" ), _( "Complete drawing at current segment" ),
|
||||||
|
checked_ok_xpm, AF_NONE );
|
||||||
|
|
||||||
|
TOOL_ACTION SCH_ACTIONS::finishWire( "eeschema.InteractiveLineDrawing.finishWire",
|
||||||
|
AS_GLOBAL, 0, _( "Finish Wire" ), _( "Complete wire with current segment" ),
|
||||||
|
checked_ok_xpm, AF_NONE );
|
||||||
|
|
||||||
|
TOOL_ACTION SCH_ACTIONS::finishBus( "eeschema.InteractiveLineDrawing.finishBus",
|
||||||
|
AS_GLOBAL, 0, _( "Finish Bus" ), _( "Complete bus with current segment" ),
|
||||||
|
checked_ok_xpm, AF_NONE );
|
||||||
|
|
||||||
|
TOOL_ACTION SCH_ACTIONS::finishLine( "eeschema.InteractiveLineDrawing.finishLine",
|
||||||
|
AS_GLOBAL, 0, _( "Finish Lines" ), _( "Complete connected lines with current segment" ),
|
||||||
|
checked_ok_xpm, AF_NONE );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SCH_LINE_DRAWING_TOOL::SCH_LINE_DRAWING_TOOL() :
|
||||||
|
TOOL_INTERACTIVE( "eeschema.InteractiveLineDrawing" ),
|
||||||
|
m_selectionTool( nullptr ),
|
||||||
|
m_view( nullptr ),
|
||||||
|
m_controls( nullptr ),
|
||||||
|
m_frame( nullptr ),
|
||||||
|
m_menu( *this )
|
||||||
|
{
|
||||||
|
m_busUnfold = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
SCH_LINE_DRAWING_TOOL::~SCH_LINE_DRAWING_TOOL()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SCH_LINE_DRAWING_TOOL::Init()
|
||||||
|
{
|
||||||
|
m_frame = getEditFrame<SCH_EDIT_FRAME>();
|
||||||
|
m_selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
|
||||||
|
|
||||||
|
auto activeTool = [ this ] ( const SELECTION& aSel ) {
|
||||||
|
return ( m_frame->GetToolId() != ID_NO_TOOL_SELECTED );
|
||||||
|
};
|
||||||
|
|
||||||
|
auto wireOrBusTool = [ this ] ( const SELECTION& aSel ) {
|
||||||
|
return ( m_frame->GetToolId() == ID_WIRE_BUTT || m_frame->GetToolId() == ID_BUS_BUTT );
|
||||||
|
};
|
||||||
|
|
||||||
|
auto lineTool = [ this ] ( const SELECTION& aSel ) {
|
||||||
|
return ( m_frame->GetToolId() == ID_LINE_COMMENT_BUTT );
|
||||||
|
};
|
||||||
|
|
||||||
|
auto& ctxMenu = m_menu.GetMenu();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Build the tool menu
|
||||||
|
//
|
||||||
|
ctxMenu.AddItem( ACTIONS::cancelInteractive, activeTool, 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.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.AddItem( SCH_ACTIONS::breakWire, wireOrBusTool && SCH_CONDITIONS::Idle, 100 );
|
||||||
|
ctxMenu.AddItem( SCH_ACTIONS::breakBus, wireOrBusTool && SCH_CONDITIONS::Idle, 100 );
|
||||||
|
|
||||||
|
ctxMenu.AddSeparator( wireOrBusTool && SCH_CONDITIONS::Idle, 200 );
|
||||||
|
ctxMenu.AddItem( SCH_ACTIONS::selectNode, wireOrBusTool && SCH_CONDITIONS::Idle, 200 );
|
||||||
|
ctxMenu.AddItem( SCH_ACTIONS::selectConnection, wireOrBusTool && SCH_CONDITIONS::Idle, 200 );
|
||||||
|
|
||||||
|
ctxMenu.AddSeparator( activeTool, 1000 );
|
||||||
|
m_menu.AddStandardSubMenus( m_frame );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SCH_LINE_DRAWING_TOOL::Reset( RESET_REASON aReason )
|
||||||
|
{
|
||||||
|
// Init variables used by every drawing tool
|
||||||
|
m_view = static_cast<KIGFX::SCH_VIEW*>( getView() );
|
||||||
|
m_controls = getViewControls();
|
||||||
|
m_frame = getEditFrame<SCH_EDIT_FRAME>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool isNewSegment( SCH_ITEM* aItem )
|
||||||
|
{
|
||||||
|
return aItem && aItem->IsNew() && aItem->Type() == SCH_LINE_T;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SCH_LINE_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_LINE_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_LINE_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_LINE_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_LINE_DRAWING_TOOL::StartWire( const TOOL_EVENT& aEvent )
|
||||||
|
{
|
||||||
|
m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true );
|
||||||
|
|
||||||
|
m_frame->GetCanvas()->MoveCursorToCrossHair();
|
||||||
|
SCH_LINE* segment = startSegments( LAYER_WIRE, m_frame->GetCrossHairPosition() );
|
||||||
|
return doDrawSegments( LAYER_WIRE, segment );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int SCH_LINE_DRAWING_TOOL::DrawWire( const TOOL_EVENT& aEvent )
|
||||||
|
{
|
||||||
|
if( m_frame->GetToolId() == ID_WIRE_BUTT )
|
||||||
|
return StartWire( aEvent );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_frame->SetToolID( ID_WIRE_BUTT, wxCURSOR_PENCIL, _( "Add wire" ) );
|
||||||
|
m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true );
|
||||||
|
|
||||||
|
return doDrawSegments( LAYER_WIRE, nullptr );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int SCH_LINE_DRAWING_TOOL::StartBus( const TOOL_EVENT& aEvent )
|
||||||
|
{
|
||||||
|
m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true );
|
||||||
|
|
||||||
|
m_frame->GetCanvas()->MoveCursorToCrossHair();
|
||||||
|
SCH_LINE* segment = startSegments( LAYER_BUS, m_frame->GetCrossHairPosition() );
|
||||||
|
return doDrawSegments( LAYER_BUS, segment );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int SCH_LINE_DRAWING_TOOL::DrawBus( const TOOL_EVENT& aEvent )
|
||||||
|
{
|
||||||
|
if( m_frame->GetToolId() == ID_BUS_BUTT )
|
||||||
|
return StartBus( aEvent );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_frame->SetToolID( ID_BUS_BUTT, wxCURSOR_PENCIL, _( "Add bus" ) );
|
||||||
|
m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true );
|
||||||
|
|
||||||
|
return doDrawSegments( LAYER_BUS, nullptr );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int SCH_LINE_DRAWING_TOOL::UnfoldBus( const TOOL_EVENT& aEvent )
|
||||||
|
{
|
||||||
|
wxString net = *aEvent.Parameter<wxString*>();
|
||||||
|
wxPoint pos = m_frame->GetCrossHairPosition();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unfolding a bus consists of the following user inputs:
|
||||||
|
* 1) User selects a bus to unfold (see AddMenusForBus())
|
||||||
|
* We land in this event handler.
|
||||||
|
*
|
||||||
|
* 2) User clicks to set the net label location (handled by BeginSegment())
|
||||||
|
* Before this first click, the posture of the bus entry follows the
|
||||||
|
* mouse cursor in X and Y (handled by DrawSegment())
|
||||||
|
*
|
||||||
|
* 3) User is now in normal wiring mode and can exit in any normal way.
|
||||||
|
*/
|
||||||
|
|
||||||
|
wxASSERT( !m_busUnfold.in_progress );
|
||||||
|
|
||||||
|
m_busUnfold.entry = new SCH_BUS_WIRE_ENTRY( pos, '\\' );
|
||||||
|
m_busUnfold.entry->SetParent( m_frame->GetScreen() );
|
||||||
|
m_frame->AddToScreen( m_busUnfold.entry );
|
||||||
|
|
||||||
|
m_busUnfold.label = new SCH_LABEL( m_busUnfold.entry->m_End(), net );
|
||||||
|
m_busUnfold.label->SetTextSize( wxSize( GetDefaultTextSize(), GetDefaultTextSize() ) );
|
||||||
|
m_busUnfold.label->SetLabelSpinStyle( 0 );
|
||||||
|
m_busUnfold.label->SetParent( m_frame->GetScreen() );
|
||||||
|
|
||||||
|
m_busUnfold.in_progress = true;
|
||||||
|
m_busUnfold.origin = pos;
|
||||||
|
m_busUnfold.net_name = net;
|
||||||
|
|
||||||
|
m_frame->SetToolID( ID_WIRE_BUTT, wxCURSOR_PENCIL, _( "Add wire" ) );
|
||||||
|
|
||||||
|
m_frame->SetCrossHairPosition( m_busUnfold.entry->m_End() );
|
||||||
|
|
||||||
|
SCH_LINE* segment = startSegments( LAYER_WIRE, m_busUnfold.entry->m_End() );
|
||||||
|
return doDrawSegments( LAYER_WIRE, segment );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int SCH_LINE_DRAWING_TOOL::StartLines( const TOOL_EVENT& aEvent)
|
||||||
|
{
|
||||||
|
m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true );
|
||||||
|
|
||||||
|
m_frame->GetCanvas()->MoveCursorToCrossHair();
|
||||||
|
SCH_LINE* segment = startSegments( LAYER_NOTES, m_frame->GetCrossHairPosition() );
|
||||||
|
return doDrawSegments( LAYER_BUS, segment );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int SCH_LINE_DRAWING_TOOL::DrawLines( const TOOL_EVENT& aEvent)
|
||||||
|
{
|
||||||
|
if( m_frame->GetToolId() == ID_LINE_COMMENT_BUTT )
|
||||||
|
return StartLines( aEvent );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_frame->SetToolID( ID_LINE_COMMENT_BUTT, wxCURSOR_PENCIL, _( "Add lines" ) );
|
||||||
|
m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true );
|
||||||
|
|
||||||
|
return doDrawSegments( LAYER_NOTES, nullptr );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Storage for the line segments while drawing
|
||||||
|
static DLIST<SCH_LINE> s_wires;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper function to find any sheet pins at the specified position.
|
||||||
|
*/
|
||||||
|
static const SCH_SHEET_PIN* getSheetPin( SCH_SCREEN* aScreen, const wxPoint& aPosition )
|
||||||
|
{
|
||||||
|
for( SCH_ITEM* item = aScreen->GetDrawItems(); item; item = item->Next() )
|
||||||
|
{
|
||||||
|
if( item->Type() == SCH_SHEET_T )
|
||||||
|
{
|
||||||
|
SCH_SHEET* sheet = (SCH_SHEET*) item;
|
||||||
|
|
||||||
|
for( const SCH_SHEET_PIN& pin : sheet->GetPins() )
|
||||||
|
{
|
||||||
|
if( pin.GetPosition() == aPosition )
|
||||||
|
return &pin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function ComputeBreakPoint
|
||||||
|
* computes the middle coordinate for 2 segments from the start point to \a aPosition
|
||||||
|
* with the segments kept in the horizontal or vertical axis only.
|
||||||
|
*
|
||||||
|
* @param aSegment A pointer to a #SCH_LINE object containing the first line break point
|
||||||
|
* to compute.
|
||||||
|
* @param aPosition A reference to a wxPoint object containing the coordinates of the
|
||||||
|
* position used to calculate the line break point.
|
||||||
|
*/
|
||||||
|
static void computeBreakPoint( SCH_SCREEN* aScreen, SCH_LINE* aSegment, wxPoint& aPosition )
|
||||||
|
{
|
||||||
|
wxCHECK_RET( aSegment != nullptr, wxT( "Cannot compute break point of NULL line segment." ) );
|
||||||
|
|
||||||
|
SCH_LINE* nextSegment = aSegment->Next();
|
||||||
|
|
||||||
|
wxPoint midPoint;
|
||||||
|
int iDx = aSegment->GetEndPoint().x - aSegment->GetStartPoint().x;
|
||||||
|
int iDy = aSegment->GetEndPoint().y - aSegment->GetStartPoint().y;
|
||||||
|
|
||||||
|
const SCH_SHEET_PIN* connectedPin = getSheetPin( aScreen, aSegment->GetStartPoint() );
|
||||||
|
auto force = connectedPin ? connectedPin->GetEdge() : SCH_SHEET_PIN::SHEET_UNDEFINED_SIDE;
|
||||||
|
|
||||||
|
if( force == SCH_SHEET_PIN::SHEET_LEFT_SIDE || force == SCH_SHEET_PIN::SHEET_RIGHT_SIDE )
|
||||||
|
{
|
||||||
|
if( aPosition.x == connectedPin->GetPosition().x ) // push outside sheet boundary
|
||||||
|
{
|
||||||
|
int direction = ( force == SCH_SHEET_PIN::SHEET_LEFT_SIDE ) ? -1 : 1;
|
||||||
|
aPosition.x += int( aScreen->GetGridSize().x * direction );
|
||||||
|
}
|
||||||
|
|
||||||
|
midPoint.x = aPosition.x;
|
||||||
|
midPoint.y = aSegment->GetStartPoint().y; // force horizontal
|
||||||
|
}
|
||||||
|
else if( iDy != 0 ) // keep the first segment orientation (vertical)
|
||||||
|
{
|
||||||
|
midPoint.x = aSegment->GetStartPoint().x;
|
||||||
|
midPoint.y = aPosition.y;
|
||||||
|
}
|
||||||
|
else if( iDx != 0 ) // keep the first segment orientation (horizontal)
|
||||||
|
{
|
||||||
|
midPoint.x = aPosition.x;
|
||||||
|
midPoint.y = aSegment->GetStartPoint().y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( std::abs( aPosition.x - aSegment->GetStartPoint().x ) <
|
||||||
|
std::abs( aPosition.y - aSegment->GetStartPoint().y ) )
|
||||||
|
{
|
||||||
|
midPoint.x = aSegment->GetStartPoint().x;
|
||||||
|
midPoint.y = aPosition.y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
midPoint.x = aPosition.x;
|
||||||
|
midPoint.y = aSegment->GetStartPoint().y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aSegment->SetEndPoint( midPoint );
|
||||||
|
nextSegment->SetStartPoint( midPoint );
|
||||||
|
nextSegment->SetEndPoint( aPosition );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int SCH_LINE_DRAWING_TOOL::doDrawSegments( int aType, SCH_LINE* aSegment )
|
||||||
|
{
|
||||||
|
bool forceHV = m_frame->GetForceHVLines();
|
||||||
|
SCH_SCREEN* screen = m_frame->GetScreen();
|
||||||
|
|
||||||
|
m_controls->ShowCursor( true );
|
||||||
|
|
||||||
|
Activate();
|
||||||
|
|
||||||
|
// Main loop: keep receiving events
|
||||||
|
while( OPT_TOOL_EVENT evt = Wait() )
|
||||||
|
{
|
||||||
|
wxPoint cursorPos = (wxPoint)m_controls->GetCursorPosition( !evt->Modifier( MD_ALT ) );
|
||||||
|
|
||||||
|
if( TOOL_EVT_UTILS::IsCancelInteractive( evt.get() ) )
|
||||||
|
{
|
||||||
|
if( aSegment || m_busUnfold.in_progress )
|
||||||
|
{
|
||||||
|
m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true );
|
||||||
|
|
||||||
|
aSegment = nullptr;
|
||||||
|
s_wires.DeleteAll();
|
||||||
|
|
||||||
|
if( m_busUnfold.entry )
|
||||||
|
m_frame->RemoveFromScreen( m_busUnfold.entry );
|
||||||
|
|
||||||
|
if( m_busUnfold.label && m_busUnfold.label_placed )
|
||||||
|
m_frame->RemoveFromScreen( m_busUnfold.label );
|
||||||
|
|
||||||
|
delete m_busUnfold.entry;
|
||||||
|
delete m_busUnfold.label;
|
||||||
|
m_busUnfold = {};
|
||||||
|
|
||||||
|
m_view->ClearPreview();
|
||||||
|
m_view->ShowPreview( false );
|
||||||
|
|
||||||
|
// Clear flags used in edit functions.
|
||||||
|
screen->ClearDrawingState();
|
||||||
|
screen->SetCurItem( nullptr );
|
||||||
|
|
||||||
|
if( !evt->IsActivate() )
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( evt->IsAction( &SCH_ACTIONS::drawWire ) && aType == LAYER_WIRE )
|
||||||
|
; // don't cancel tool; we're going to re-enter
|
||||||
|
else if( evt->IsAction( &SCH_ACTIONS::drawBus ) && aType == LAYER_BUS )
|
||||||
|
; // don't cancel tool; we're going to re-enter
|
||||||
|
else
|
||||||
|
m_frame->SetNoToolSelected();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if( evt->IsAction( &SCH_ACTIONS::finishLineWireOrBus )
|
||||||
|
|| evt->IsAction( &SCH_ACTIONS::finishWire )
|
||||||
|
|| evt->IsAction( &SCH_ACTIONS::finishBus )
|
||||||
|
|| evt->IsAction( &SCH_ACTIONS::finishLine ) )
|
||||||
|
{
|
||||||
|
if( aSegment || m_busUnfold.in_progress )
|
||||||
|
{
|
||||||
|
finishSegments();
|
||||||
|
aSegment = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_frame->GetToolId() == ID_NO_TOOL_SELECTED )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if( evt->IsClick( BUT_RIGHT ) )
|
||||||
|
{
|
||||||
|
// Warp after context menu only if dragging...
|
||||||
|
if( !aSegment )
|
||||||
|
m_toolMgr->VetoContextMenuMouseWarp();
|
||||||
|
|
||||||
|
m_menu.ShowContextMenu( m_selectionTool->GetSelection() );
|
||||||
|
}
|
||||||
|
else if( evt->IsClick( BUT_LEFT ) || ( aSegment && evt->IsDblClick( BUT_LEFT ) ) )
|
||||||
|
{
|
||||||
|
// First click when unfolding places the label and wire-to-bus entry
|
||||||
|
if( m_busUnfold.in_progress && !m_busUnfold.label_placed )
|
||||||
|
{
|
||||||
|
wxASSERT( aType == LAYER_WIRE );
|
||||||
|
|
||||||
|
m_frame->AddToScreen( m_busUnfold.label );
|
||||||
|
m_busUnfold.label_placed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !aSegment )
|
||||||
|
{
|
||||||
|
aSegment = startSegments( aType, cursorPos );
|
||||||
|
}
|
||||||
|
// Create a new segment if we're out of previously-created ones
|
||||||
|
else if( !aSegment->IsNull() || ( forceHV && !aSegment->Back()->IsNull() ) )
|
||||||
|
{
|
||||||
|
// Terminate the command if the end point is on a pin, junction, or another
|
||||||
|
// wire or bus.
|
||||||
|
if( !m_busUnfold.in_progress
|
||||||
|
&& screen->IsTerminalPoint( cursorPos, aSegment->GetLayer() ) )
|
||||||
|
{
|
||||||
|
finishSegments();
|
||||||
|
aSegment = nullptr;
|
||||||
|
|
||||||
|
if( m_frame->GetToolId() == ID_NO_TOOL_SELECTED )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aSegment->SetEndPoint( cursorPos );
|
||||||
|
|
||||||
|
// Create a new segment, and chain it after the current segment.
|
||||||
|
aSegment = new SCH_LINE( *aSegment );
|
||||||
|
aSegment->SetFlags( IS_NEW | IS_MOVED );
|
||||||
|
aSegment->SetStartPoint( cursorPos );
|
||||||
|
s_wires.PushBack( aSegment );
|
||||||
|
m_selectionTool->AddItemToSel( aSegment, true /*quiet mode*/ );
|
||||||
|
screen->SetCurItem( aSegment );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( evt->IsDblClick( BUT_LEFT ) )
|
||||||
|
{
|
||||||
|
finishSegments();
|
||||||
|
aSegment = nullptr;
|
||||||
|
|
||||||
|
if( m_frame->GetToolId() == ID_NO_TOOL_SELECTED )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( evt->IsMotion() )
|
||||||
|
{
|
||||||
|
m_view->ClearPreview();
|
||||||
|
|
||||||
|
// Update the bus unfold posture based on the mouse movement
|
||||||
|
if( m_busUnfold.in_progress && !m_busUnfold.label_placed )
|
||||||
|
{
|
||||||
|
wxPoint cursor_delta = cursorPos - m_busUnfold.origin;
|
||||||
|
SCH_BUS_WIRE_ENTRY* entry = m_busUnfold.entry;
|
||||||
|
|
||||||
|
bool offset = ( cursor_delta.x < 0 );
|
||||||
|
char shape = ( offset ? ( ( cursor_delta.y >= 0 ) ? '/' : '\\' )
|
||||||
|
: ( ( cursor_delta.y >= 0 ) ? '\\' : '/' ) );
|
||||||
|
|
||||||
|
// Erase and redraw if necessary
|
||||||
|
if( shape != entry->GetBusEntryShape() || offset != m_busUnfold.offset )
|
||||||
|
{
|
||||||
|
entry->SetBusEntryShape( shape );
|
||||||
|
wxPoint entry_pos = m_busUnfold.origin;
|
||||||
|
|
||||||
|
if( offset )
|
||||||
|
entry_pos -= entry->GetSize();
|
||||||
|
|
||||||
|
entry->SetPosition( entry_pos );
|
||||||
|
m_busUnfold.offset = offset;
|
||||||
|
|
||||||
|
m_frame->RefreshItem( entry );
|
||||||
|
|
||||||
|
wxPoint wire_start = offset ? entry->GetPosition() : entry->m_End();
|
||||||
|
s_wires.begin()->SetStartPoint( wire_start );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the label "ghost" position
|
||||||
|
m_busUnfold.label->SetPosition( cursorPos );
|
||||||
|
m_view->AddToPreview( m_busUnfold.label->Clone() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( aSegment )
|
||||||
|
{
|
||||||
|
// Coerce the line to vertical or horizontal if necessary
|
||||||
|
if( forceHV )
|
||||||
|
computeBreakPoint( screen, aSegment->Back(), cursorPos );
|
||||||
|
else
|
||||||
|
aSegment->SetEndPoint( cursorPos );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( auto seg = s_wires.begin(); seg; seg = seg->Next() )
|
||||||
|
{
|
||||||
|
if( !seg->IsNull() ) // Add to preview if segment length != 0
|
||||||
|
m_view->AddToPreview( seg->Clone() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable autopanning and cursor capture only when there is a segment to be placed
|
||||||
|
m_controls->SetAutoPan( !!aSegment );
|
||||||
|
m_controls->CaptureCursor( !!aSegment );
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SCH_LINE* SCH_LINE_DRAWING_TOOL::startSegments( int aType, const wxPoint& aPos )
|
||||||
|
{
|
||||||
|
SCH_LINE* segment = nullptr;
|
||||||
|
bool forceHV = m_frame->GetForceHVLines();
|
||||||
|
|
||||||
|
switch( aType )
|
||||||
|
{
|
||||||
|
default: segment = new SCH_LINE( aPos, LAYER_NOTES ); break;
|
||||||
|
case LAYER_WIRE: segment = new SCH_LINE( aPos, LAYER_WIRE ); break;
|
||||||
|
case LAYER_BUS: segment = new SCH_LINE( aPos, LAYER_BUS ); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
segment->SetFlags( IS_NEW | IS_MOVED );
|
||||||
|
s_wires.PushBack( segment );
|
||||||
|
m_selectionTool->AddItemToSel( segment, true /*quiet mode*/ );
|
||||||
|
m_frame->GetScreen()->SetCurItem( segment );
|
||||||
|
|
||||||
|
// We need 2 segments to go from a given start pin to an end point when the
|
||||||
|
// horizontal and vertical lines only switch is on.
|
||||||
|
if( forceHV )
|
||||||
|
{
|
||||||
|
segment = new SCH_LINE( *segment );
|
||||||
|
segment->SetFlags( IS_NEW | IS_MOVED );
|
||||||
|
s_wires.PushBack( segment );
|
||||||
|
m_selectionTool->AddItemToSel( segment, true /*quiet mode*/ );
|
||||||
|
m_frame->GetScreen()->SetCurItem( segment );
|
||||||
|
}
|
||||||
|
|
||||||
|
return segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In a contiguous list of wires, remove wires that backtrack over the previous
|
||||||
|
* wire. Example:
|
||||||
|
*
|
||||||
|
* Wire is added:
|
||||||
|
* ---------------------------------------->
|
||||||
|
*
|
||||||
|
* A second wire backtracks over it:
|
||||||
|
* -------------------<====================>
|
||||||
|
*
|
||||||
|
* RemoveBacktracks is called:
|
||||||
|
* ------------------->
|
||||||
|
*/
|
||||||
|
static void removeBacktracks( DLIST<SCH_LINE>& aWires )
|
||||||
|
{
|
||||||
|
SCH_LINE* next = nullptr;
|
||||||
|
std::vector<SCH_LINE*> last_lines;
|
||||||
|
|
||||||
|
for( SCH_LINE* line = aWires.GetFirst(); line; line = next )
|
||||||
|
{
|
||||||
|
next = line->Next();
|
||||||
|
|
||||||
|
if( line->IsNull() )
|
||||||
|
{
|
||||||
|
delete s_wires.Remove( line );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !last_lines.empty() )
|
||||||
|
{
|
||||||
|
SCH_LINE* last_line = last_lines[last_lines.size() - 1];
|
||||||
|
bool contiguous = ( last_line->GetEndPoint() == line->GetStartPoint() );
|
||||||
|
bool backtracks = IsPointOnSegment( last_line->GetStartPoint(),
|
||||||
|
last_line->GetEndPoint(), line->GetEndPoint() );
|
||||||
|
bool total_backtrack = ( last_line->GetStartPoint() == line->GetEndPoint() );
|
||||||
|
|
||||||
|
if( contiguous && backtracks )
|
||||||
|
{
|
||||||
|
if( total_backtrack )
|
||||||
|
{
|
||||||
|
delete s_wires.Remove( last_line );
|
||||||
|
delete s_wires.Remove( line );
|
||||||
|
last_lines.pop_back();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
last_line->SetEndPoint( line->GetEndPoint() );
|
||||||
|
delete s_wires.Remove( line );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
last_lines.push_back( line );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
last_lines.push_back( line );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SCH_LINE_DRAWING_TOOL::finishSegments()
|
||||||
|
{
|
||||||
|
// Clear selection when done so that a new wire can be started.
|
||||||
|
// NOTE: this must be done before RemoveBacktracks is called or we might end up with
|
||||||
|
// freed selected items.
|
||||||
|
m_toolMgr->RunAction( SCH_ACTIONS::clearSelection, true );
|
||||||
|
|
||||||
|
PICKED_ITEMS_LIST itemList;
|
||||||
|
|
||||||
|
// Remove segments backtracking over others
|
||||||
|
removeBacktracks( s_wires );
|
||||||
|
|
||||||
|
// Collect the possible connection points for the new lines
|
||||||
|
std::vector< wxPoint > connections;
|
||||||
|
std::vector< wxPoint > new_ends;
|
||||||
|
m_frame->GetSchematicConnections( connections );
|
||||||
|
|
||||||
|
// Check each new segment for possible junctions and add/split if needed
|
||||||
|
for( SCH_LINE* wire = s_wires.GetFirst(); wire; wire = wire->Next() )
|
||||||
|
{
|
||||||
|
if( wire->GetFlags() & SKIP_STRUCT )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
wire->GetConnectionPoints( new_ends );
|
||||||
|
|
||||||
|
for( auto i : connections )
|
||||||
|
{
|
||||||
|
if( IsPointOnSegment( wire->GetStartPoint(), wire->GetEndPoint(), i ) )
|
||||||
|
new_ends.push_back( i );
|
||||||
|
}
|
||||||
|
itemList.PushItem( ITEM_PICKER( wire, UR_NEW ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_busUnfold.in_progress && m_busUnfold.label_placed )
|
||||||
|
{
|
||||||
|
wxASSERT( m_busUnfold.entry && m_busUnfold.label );
|
||||||
|
|
||||||
|
itemList.PushItem( ITEM_PICKER( m_busUnfold.entry, UR_NEW ) );
|
||||||
|
itemList.PushItem( ITEM_PICKER( m_busUnfold.label, UR_NEW ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the last non-null wire (this is the last created segment).
|
||||||
|
m_frame->SetRepeatItem( s_wires.GetLast() );
|
||||||
|
|
||||||
|
// 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_controls->CaptureCursor( false );
|
||||||
|
m_controls->SetAutoPan( false );
|
||||||
|
|
||||||
|
m_frame->SaveCopyInUndoList( itemList, UR_NEW );
|
||||||
|
|
||||||
|
// Correct and remove segments that need to be merged.
|
||||||
|
m_frame->SchematicCleanUp( true );
|
||||||
|
|
||||||
|
for( auto item = m_frame->GetScreen()->GetDrawItems(); item; item = item->Next() )
|
||||||
|
{
|
||||||
|
if( item->Type() != SCH_COMPONENT_T )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::vector< wxPoint > pts;
|
||||||
|
item->GetConnectionPoints( pts );
|
||||||
|
|
||||||
|
if( pts.size() > 2 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for( auto i = pts.begin(); i != pts.end(); i++ )
|
||||||
|
{
|
||||||
|
for( auto j = i + 1; j != pts.end(); j++ )
|
||||||
|
m_frame->TrimWire( *i, *j, true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( auto i : new_ends )
|
||||||
|
{
|
||||||
|
if( m_frame->GetScreen()->IsJunctionNeeded( i, true ) )
|
||||||
|
m_frame->AddJunction( i, true, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_busUnfold.in_progress )
|
||||||
|
m_busUnfold = {};
|
||||||
|
|
||||||
|
m_frame->TestDanglingEnds();
|
||||||
|
|
||||||
|
m_frame->GetScreen()->ClearDrawingState();
|
||||||
|
m_frame->GetScreen()->SetCurItem( nullptr );
|
||||||
|
m_frame->OnModify();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SCH_LINE_DRAWING_TOOL::setTransitions()
|
||||||
|
{
|
||||||
|
Go( &SCH_LINE_DRAWING_TOOL::DrawWire, SCH_ACTIONS::drawWire.MakeEvent() );
|
||||||
|
Go( &SCH_LINE_DRAWING_TOOL::DrawBus, SCH_ACTIONS::drawBus.MakeEvent() );
|
||||||
|
Go( &SCH_LINE_DRAWING_TOOL::UnfoldBus, SCH_ACTIONS::unfoldBus.MakeEvent() );
|
||||||
|
Go( &SCH_LINE_DRAWING_TOOL::DrawLines, SCH_ACTIONS::drawLines.MakeEvent() );
|
||||||
|
|
||||||
|
Go( &SCH_LINE_DRAWING_TOOL::StartWire, SCH_ACTIONS::startWire.MakeEvent() );
|
||||||
|
Go( &SCH_LINE_DRAWING_TOOL::StartBus, SCH_ACTIONS::startBus.MakeEvent() );
|
||||||
|
Go( &SCH_LINE_DRAWING_TOOL::StartLines, SCH_ACTIONS::startLines.MakeEvent() );
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SCH_LINE_DRAWING_TOOL_H
|
||||||
|
#define SCH_LINE_DRAWING_TOOL_H
|
||||||
|
|
||||||
|
#include <tool/tool_interactive.h>
|
||||||
|
#include <tool/tool_menu.h>
|
||||||
|
#include <core/optional.h>
|
||||||
|
#include <sch_base_frame.h>
|
||||||
|
|
||||||
|
|
||||||
|
class SCH_COMPONENT;
|
||||||
|
class SCH_BUS_WIRE_ENTRY;
|
||||||
|
class SCH_LABEL;
|
||||||
|
class SCHLIB_FILTER;
|
||||||
|
class SCH_EDIT_FRAME;
|
||||||
|
class SCH_SELECTION_TOOL;
|
||||||
|
|
||||||
|
|
||||||
|
/// Collection of data related to the bus unfolding tool
|
||||||
|
struct BUS_UNFOLDING_T
|
||||||
|
{
|
||||||
|
bool in_progress; ///< True if bus unfold operation is running
|
||||||
|
bool offset; ///< True if the bus entry should be offset from origin
|
||||||
|
bool label_placed; ///< True if user has placed the net label
|
||||||
|
|
||||||
|
wxPoint origin; ///< Origin (on the bus) of the unfold
|
||||||
|
wxString net_name; ///< Net label for the unfolding operation
|
||||||
|
|
||||||
|
SCH_BUS_WIRE_ENTRY* entry;
|
||||||
|
SCH_LABEL* label;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class SCH_LINE_DRAWING_TOOL
|
||||||
|
*
|
||||||
|
* Tool responsible for drawing/placing items (symbols, wires, busses, labels, etc.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
class SCH_LINE_DRAWING_TOOL : public TOOL_INTERACTIVE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SCH_LINE_DRAWING_TOOL();
|
||||||
|
~SCH_LINE_DRAWING_TOOL();
|
||||||
|
|
||||||
|
/// @copydoc TOOL_INTERACTIVE::Init()
|
||||||
|
bool Init() override;
|
||||||
|
|
||||||
|
/// @copydoc TOOL_INTERACTIVE::Reset()
|
||||||
|
void Reset( RESET_REASON aReason ) override;
|
||||||
|
|
||||||
|
///> Get the SCH_LINE_DRAWING_TOOL top-level context menu
|
||||||
|
inline TOOL_MENU& GetToolMenu() { return m_menu; }
|
||||||
|
|
||||||
|
int StartWire( const TOOL_EVENT& aEvent );
|
||||||
|
int StartBus( const TOOL_EVENT& aEvent );
|
||||||
|
int StartLines( const TOOL_EVENT& aEvent );
|
||||||
|
int AddJunction( const TOOL_EVENT& aEvent );
|
||||||
|
int AddLabel( const TOOL_EVENT& aEvent );
|
||||||
|
|
||||||
|
int DrawWire( const TOOL_EVENT& aEvent );
|
||||||
|
int DrawBus( const TOOL_EVENT& aEvent );
|
||||||
|
int DrawLines( const TOOL_EVENT& aEvent );
|
||||||
|
|
||||||
|
int UnfoldBus( 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 doDrawSegments( int aType, SCH_LINE* aSegment );
|
||||||
|
SCH_LINE* startSegments( int aType, const wxPoint& aPos );
|
||||||
|
void finishSegments();
|
||||||
|
|
||||||
|
///> Sets up handlers for various events.
|
||||||
|
void setTransitions() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SCH_SELECTION_TOOL* m_selectionTool;
|
||||||
|
KIGFX::SCH_VIEW* m_view;
|
||||||
|
KIGFX::VIEW_CONTROLS* m_controls;
|
||||||
|
SCH_EDIT_FRAME* m_frame;
|
||||||
|
|
||||||
|
/// Data related to bus unfolding tool.
|
||||||
|
BUS_UNFOLDING_T m_busUnfold;
|
||||||
|
|
||||||
|
TOOL_MENU m_menu;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* SCH_LINE_DRAWING_TOOL_H */
|
|
@ -37,6 +37,7 @@
|
||||||
#include <preview_items/selection_area.h>
|
#include <preview_items/selection_area.h>
|
||||||
#include <tool/tool_event.h>
|
#include <tool/tool_event.h>
|
||||||
#include <tool/tool_manager.h>
|
#include <tool/tool_manager.h>
|
||||||
|
#include <tools/sch_line_drawing_tool.h>
|
||||||
#include <sch_actions.h>
|
#include <sch_actions.h>
|
||||||
#include <sch_collectors.h>
|
#include <sch_collectors.h>
|
||||||
#include <painter.h>
|
#include <painter.h>
|
||||||
|
@ -150,14 +151,40 @@ bool SCH_SELECTION_TOOL::Init()
|
||||||
m_frame = getEditFrame<SCH_BASE_FRAME>();
|
m_frame = getEditFrame<SCH_BASE_FRAME>();
|
||||||
|
|
||||||
static KICAD_T wireOrBusTypes[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT };
|
static KICAD_T wireOrBusTypes[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT };
|
||||||
|
|
||||||
|
auto wireSelection = SCH_CONDITIONS::MoreThan( 0 )
|
||||||
|
&& SCH_CONDITIONS::OnlyType( SCH_LINE_LOCATE_WIRE_T );
|
||||||
|
|
||||||
|
auto busSelection = SCH_CONDITIONS::MoreThan( 0 )
|
||||||
|
&& SCH_CONDITIONS::OnlyType( SCH_LINE_LOCATE_BUS_T );
|
||||||
|
|
||||||
auto wireOrBusSelection = SCH_CONDITIONS::MoreThan( 0 )
|
auto wireOrBusSelection = SCH_CONDITIONS::MoreThan( 0 )
|
||||||
&& SCH_CONDITIONS::OnlyTypes( wireOrBusTypes );
|
&& SCH_CONDITIONS::OnlyTypes( wireOrBusTypes );
|
||||||
|
|
||||||
auto& ctxMenu = m_menu.GetMenu();
|
auto singleSheetCondition = SELECTION_CONDITIONS::Count( 1 )
|
||||||
|
&& SELECTION_CONDITIONS::OnlyType( SCH_SHEET_T );
|
||||||
|
|
||||||
ctxMenu.AddItem( SCH_ACTIONS::selectConnection, wireOrBusSelection && SCH_CONDITIONS::Idle, 200 );
|
auto& menu = m_menu.GetMenu();
|
||||||
|
|
||||||
ctxMenu.AddSeparator( SELECTION_CONDITIONS::ShowAlways, 1000 );
|
// TODO(JE): add menu access to unfold bus on busSelectionCondition...
|
||||||
|
menu.AddItem( SCH_ACTIONS::resizeSheet, singleSheetCondition && SCH_CONDITIONS::Idle, 1 );
|
||||||
|
|
||||||
|
menu.AddItem( SCH_ACTIONS::startWire, SCH_CONDITIONS::Empty, 1 );
|
||||||
|
menu.AddItem( SCH_ACTIONS::startBus, SCH_CONDITIONS::Empty, 1 );
|
||||||
|
menu.AddItem( SCH_ACTIONS::finishWire, SCH_LINE_DRAWING_TOOL::IsDrawingWire, 1 );
|
||||||
|
menu.AddItem( SCH_ACTIONS::finishBus, SCH_LINE_DRAWING_TOOL::IsDrawingBus, 1 );
|
||||||
|
|
||||||
|
menu.AddSeparator( SCH_CONDITIONS::NotEmpty, 200 );
|
||||||
|
menu.AddItem( SCH_ACTIONS::selectConnection, wireOrBusSelection && SCH_CONDITIONS::Idle, 200 );
|
||||||
|
menu.AddItem( SCH_ACTIONS::addJunction, wireOrBusSelection && SCH_CONDITIONS::Idle, 200 );
|
||||||
|
menu.AddItem( SCH_ACTIONS::addLabel, wireOrBusSelection && SCH_CONDITIONS::Idle, 200 );
|
||||||
|
menu.AddItem( SCH_ACTIONS::addGlobalLabel, wireOrBusSelection && SCH_CONDITIONS::Idle, 200 );
|
||||||
|
menu.AddItem( SCH_ACTIONS::addHierLabel, wireOrBusSelection && SCH_CONDITIONS::Idle, 200 );
|
||||||
|
menu.AddItem( SCH_ACTIONS::breakWire, wireSelection && SCH_CONDITIONS::Idle, 200 );
|
||||||
|
menu.AddItem( SCH_ACTIONS::breakBus, busSelection && SCH_CONDITIONS::Idle, 200 );
|
||||||
|
menu.AddItem( SCH_ACTIONS::importSheetPin, singleSheetCondition && SCH_CONDITIONS::Idle, 200 );
|
||||||
|
|
||||||
|
menu.AddSeparator( SELECTION_CONDITIONS::ShowAlways, 1000 );
|
||||||
m_menu.AddStandardSubMenus( m_frame );
|
m_menu.AddStandardSubMenus( m_frame );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in New Issue