15 changed files with 1081 additions and 957 deletions
-
2eeschema/CMakeLists.txt
-
108eeschema/bus-wire-junction.cpp
-
8eeschema/hierarch.cpp
-
8eeschema/onrightclick.cpp
-
6eeschema/sch_edit_frame.cpp
-
2eeschema/sch_edit_frame.h
-
156eeschema/schedit.cpp
-
2eeschema/tools/sch_actions.cpp
-
729eeschema/tools/sch_drawing_tool.cpp
-
37eeschema/tools/sch_drawing_tool.h
-
21eeschema/tools/sch_edit_tool.cpp
-
4eeschema/tools/sch_inspection_tool.cpp
-
806eeschema/tools/sch_line_drawing_tool.cpp
-
116eeschema/tools/sch_line_drawing_tool.h
-
33eeschema/tools/sch_selection_tool.cpp
@ -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; |
|||
} |
@ -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 */ |
Write
Preview
Loading…
Cancel
Save
Reference in new issue