2011-10-19 20:32:21 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
2012-03-19 07:48:29 +00:00
|
|
|
* Copyright (C) 2004 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.fr
|
2011-10-19 20:32:21 +00:00
|
|
|
* Copyright (C) 2004-2011 KiCad Developers, see change_log.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
|
|
|
|
*/
|
|
|
|
|
2011-10-07 14:41:30 +00:00
|
|
|
/**
|
|
|
|
* @file bus-wire-junction.cpp
|
|
|
|
* @brief Code for editing buses, wires, and junctions.
|
|
|
|
*/
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2012-01-23 04:33:36 +00:00
|
|
|
#include <fctsys.h>
|
|
|
|
#include <gr_basic.h>
|
|
|
|
#include <class_drawpanel.h>
|
2015-02-21 09:46:44 +00:00
|
|
|
#include <schframe.h>
|
2009-02-04 15:25:03 +00:00
|
|
|
|
2012-01-23 04:33:36 +00:00
|
|
|
#include <lib_draw_item.h>
|
|
|
|
#include <lib_pin.h>
|
|
|
|
#include <general.h>
|
|
|
|
#include <sch_bus_entry.h>
|
|
|
|
#include <sch_junction.h>
|
|
|
|
#include <sch_line.h>
|
|
|
|
#include <sch_no_connect.h>
|
|
|
|
#include <sch_text.h>
|
|
|
|
#include <sch_component.h>
|
|
|
|
#include <sch_sheet.h>
|
2007-05-06 16:03:28 +00:00
|
|
|
|
|
|
|
|
2015-04-10 11:22:44 +00:00
|
|
|
static void AbortCreateNewLine( EDA_DRAW_PANEL* aPanel, wxDC* aDC );
|
2009-12-02 21:44:03 +00:00
|
|
|
static void ComputeBreakPoint( SCH_LINE* segment, const wxPoint& new_pos );
|
2007-06-05 12:10:51 +00:00
|
|
|
|
2012-07-05 11:37:48 +00:00
|
|
|
static DLIST< SCH_ITEM > s_wires; // when creating a new set of wires,
|
|
|
|
// stores here the new wires.
|
2007-06-05 12:10:51 +00:00
|
|
|
|
2009-12-02 21:44:03 +00:00
|
|
|
|
2015-06-23 15:01:34 +00:00
|
|
|
/**
|
|
|
|
* 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_ITEM>& aWires )
|
|
|
|
{
|
|
|
|
SCH_LINE* last_line = NULL;
|
|
|
|
|
|
|
|
EDA_ITEM* first = aWires.GetFirst();
|
|
|
|
for( EDA_ITEM* p = first; p; )
|
|
|
|
{
|
|
|
|
SCH_LINE *line = dynamic_cast<SCH_LINE*>( p );
|
|
|
|
if( !line )
|
|
|
|
{
|
|
|
|
wxFAIL_MSG( "RemoveBacktracks() requires SCH_LINE items" );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
p = line->Next();
|
|
|
|
|
|
|
|
if( last_line )
|
|
|
|
{
|
|
|
|
wxASSERT_MSG( last_line->GetEndPoint() == line->GetStartPoint(),
|
|
|
|
"RemoveBacktracks() requires contiguous lines" );
|
|
|
|
if( IsPointOnSegment( last_line->GetStartPoint(), line->GetStartPoint(),
|
|
|
|
line->GetEndPoint() ) )
|
|
|
|
{
|
|
|
|
last_line->SetEndPoint( line->GetEndPoint() );
|
|
|
|
delete s_wires.Remove( line );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
last_line = line;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
last_line = line;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-12-08 20:12:46 +00:00
|
|
|
/**
|
|
|
|
* Mouse capture callback for drawing line segments.
|
|
|
|
*/
|
2011-02-03 19:27:28 +00:00
|
|
|
static void DrawSegment( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition,
|
|
|
|
bool aErase )
|
2010-12-08 20:12:46 +00:00
|
|
|
{
|
|
|
|
SCH_LINE* segment;
|
|
|
|
|
2012-02-26 18:39:39 +00:00
|
|
|
if( s_wires.GetCount() == 0 )
|
2010-12-08 20:12:46 +00:00
|
|
|
return;
|
|
|
|
|
2012-02-26 18:39:39 +00:00
|
|
|
segment = (SCH_LINE*) s_wires.begin();
|
2013-04-04 21:35:01 +00:00
|
|
|
EDA_COLOR_T color = GetLayerColor( segment->GetLayer() );
|
2012-09-02 12:06:47 +00:00
|
|
|
ColorChangeHighlightFlag( &color, !(color & HIGHLIGHT_FLAG) );
|
2010-12-08 20:12:46 +00:00
|
|
|
|
|
|
|
if( aErase )
|
|
|
|
{
|
|
|
|
while( segment )
|
|
|
|
{
|
|
|
|
if( !segment->IsNull() ) // Redraw if segment length != 0
|
2011-01-10 16:50:40 +00:00
|
|
|
segment->Draw( aPanel, aDC, wxPoint( 0, 0 ), g_XorMode, color );
|
2010-12-08 20:12:46 +00:00
|
|
|
|
|
|
|
segment = segment->Next();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-03 05:15:23 +00:00
|
|
|
SCH_EDIT_FRAME* frame = (SCH_EDIT_FRAME*) aPanel->GetParent();
|
|
|
|
|
|
|
|
wxPoint endpos = frame->GetCrossHairPosition();
|
2010-12-08 20:12:46 +00:00
|
|
|
|
2012-09-28 17:47:41 +00:00
|
|
|
if( frame->GetForceHVLines() ) /* Coerce the line to vertical or horizontal one: */
|
2012-02-26 18:39:39 +00:00
|
|
|
ComputeBreakPoint( (SCH_LINE*) s_wires.GetLast()->Back(), endpos );
|
2010-12-08 20:12:46 +00:00
|
|
|
else
|
2012-02-26 18:39:39 +00:00
|
|
|
( (SCH_LINE*) s_wires.GetLast() )->SetEndPoint( endpos );
|
2010-12-08 20:12:46 +00:00
|
|
|
|
2012-02-26 18:39:39 +00:00
|
|
|
segment = (SCH_LINE*) s_wires.begin();
|
2010-12-08 20:12:46 +00:00
|
|
|
|
|
|
|
while( segment )
|
|
|
|
{
|
|
|
|
if( !segment->IsNull() ) // Redraw if segment length != 0
|
2011-01-10 16:50:40 +00:00
|
|
|
segment->Draw( aPanel, aDC, wxPoint( 0, 0 ), g_XorMode, color );
|
2010-12-08 20:12:46 +00:00
|
|
|
|
|
|
|
segment = segment->Next();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SCH_EDIT_FRAME::BeginSegment( wxDC* DC, int type )
|
2009-12-02 21:44:03 +00:00
|
|
|
{
|
2012-02-26 18:39:39 +00:00
|
|
|
SCH_LINE* segment;
|
|
|
|
SCH_LINE* nextSegment;
|
2013-08-03 05:15:23 +00:00
|
|
|
wxPoint cursorpos = GetCrossHairPosition();
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2012-03-19 07:48:29 +00:00
|
|
|
// We should know if a segment is currently in progress
|
2012-02-26 18:39:39 +00:00
|
|
|
segment = (SCH_LINE*) GetScreen()->GetCurItem();
|
2012-03-16 19:08:57 +00:00
|
|
|
if( segment ) // a current item exists, but not necessary a currently edited item
|
|
|
|
{
|
|
|
|
if( !segment->GetFlags() || ( segment->Type() != SCH_LINE_T ) )
|
|
|
|
{
|
|
|
|
if( segment->GetFlags() )
|
|
|
|
{
|
|
|
|
wxLogDebug( wxT( "BeginSegment: item->GetFlags()== %X" ),
|
|
|
|
segment->GetFlags() );
|
|
|
|
}
|
|
|
|
// no wire, bus or graphic line in progress
|
|
|
|
segment = NULL;
|
|
|
|
}
|
|
|
|
}
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2015-04-10 11:22:44 +00:00
|
|
|
if( !segment ) // first point : Create the first wire or bus segment
|
2007-08-20 01:20:48 +00:00
|
|
|
{
|
|
|
|
switch( type )
|
|
|
|
{
|
|
|
|
default:
|
2012-02-26 18:39:39 +00:00
|
|
|
segment = new SCH_LINE( cursorpos, LAYER_NOTES );
|
2007-08-20 01:20:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case LAYER_WIRE:
|
2012-02-26 18:39:39 +00:00
|
|
|
segment = new SCH_LINE( cursorpos, LAYER_WIRE );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2009-11-03 13:26:31 +00:00
|
|
|
/* A junction will be created later, when we'll know the
|
|
|
|
* segment end position, and if the junction is really needed */
|
2007-08-20 01:20:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case LAYER_BUS:
|
2012-02-26 18:39:39 +00:00
|
|
|
segment = new SCH_LINE( cursorpos, LAYER_BUS );
|
2007-08-20 01:20:48 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-02-26 18:39:39 +00:00
|
|
|
segment->SetFlags( IS_NEW );
|
|
|
|
s_wires.PushBack( segment );
|
|
|
|
GetScreen()->SetCurItem( segment );
|
2010-12-08 20:12:46 +00:00
|
|
|
|
2012-02-26 18:39:39 +00:00
|
|
|
// 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.
|
2012-09-28 17:47:41 +00:00
|
|
|
if( GetForceHVLines() )
|
2007-08-20 01:20:48 +00:00
|
|
|
{
|
2012-02-26 18:39:39 +00:00
|
|
|
nextSegment = new SCH_LINE( *segment );
|
|
|
|
nextSegment->SetFlags( IS_NEW );
|
|
|
|
s_wires.PushBack( nextSegment );
|
|
|
|
GetScreen()->SetCurItem( nextSegment );
|
2007-08-20 01:20:48 +00:00
|
|
|
}
|
2010-12-08 20:12:46 +00:00
|
|
|
|
2011-12-22 13:28:11 +00:00
|
|
|
m_canvas->SetMouseCapture( DrawSegment, AbortCreateNewLine );
|
2013-08-05 21:02:41 +00:00
|
|
|
SetRepeatItem( NULL );
|
2007-08-20 01:20:48 +00:00
|
|
|
}
|
2010-12-08 20:12:46 +00:00
|
|
|
else // A segment is in progress: terminates the current segment and add a new segment.
|
2007-08-20 01:20:48 +00:00
|
|
|
{
|
2015-11-03 19:44:05 +00:00
|
|
|
SCH_LINE* prevSegment = segment->Back();
|
2012-02-26 18:39:39 +00:00
|
|
|
|
2012-07-21 16:52:29 +00:00
|
|
|
// Be aware prevSegment can be null when the horizontal and vertical lines only switch is off
|
|
|
|
// when we create the first segment.
|
2010-12-08 20:12:46 +00:00
|
|
|
|
2012-09-28 17:47:41 +00:00
|
|
|
if( !GetForceHVLines() )
|
2009-11-03 13:26:31 +00:00
|
|
|
{
|
2012-02-26 18:39:39 +00:00
|
|
|
// If only one segment is needed and it has a zero length, do not create a new one.
|
|
|
|
if( segment->IsNull() )
|
2007-08-20 01:20:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-02-26 18:39:39 +00:00
|
|
|
wxCHECK_RET( prevSegment != NULL, wxT( "Failed to create second line segment." ) );
|
|
|
|
|
|
|
|
// If two segments are required and they both have zero length, do not
|
|
|
|
// create a new one.
|
|
|
|
if( prevSegment && prevSegment->IsNull() && segment->IsNull() )
|
2007-08-20 01:20:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-12-29 20:11:42 +00:00
|
|
|
m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2012-02-26 18:39:39 +00:00
|
|
|
// Terminate the command if the end point is on a pin, junction, or another wire or bus.
|
|
|
|
if( GetScreen()->IsTerminalPoint( cursorpos, segment->GetLayer() ) )
|
2007-08-20 01:20:48 +00:00
|
|
|
{
|
2010-12-08 20:12:46 +00:00
|
|
|
EndSegment( DC );
|
|
|
|
return;
|
2007-08-20 01:20:48 +00:00
|
|
|
}
|
|
|
|
|
2012-02-26 18:39:39 +00:00
|
|
|
// Create a new segment, and chain it after the current new segment.
|
|
|
|
nextSegment = new SCH_LINE( *segment );
|
|
|
|
nextSegment->SetStartPoint( cursorpos );
|
|
|
|
s_wires.PushBack( nextSegment );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2012-02-26 18:39:39 +00:00
|
|
|
segment->SetEndPoint( cursorpos );
|
|
|
|
segment->ClearFlags( IS_NEW );
|
|
|
|
segment->SetFlags( SELECTED );
|
|
|
|
nextSegment->SetFlags( IS_NEW );
|
|
|
|
GetScreen()->SetCurItem( nextSegment );
|
2011-12-29 20:11:42 +00:00
|
|
|
m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
|
2007-08-20 01:20:48 +00:00
|
|
|
}
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-12-08 20:12:46 +00:00
|
|
|
void SCH_EDIT_FRAME::EndSegment( wxDC* DC )
|
2009-12-02 21:44:03 +00:00
|
|
|
{
|
2012-02-26 18:39:39 +00:00
|
|
|
SCH_SCREEN* screen = GetScreen();
|
|
|
|
SCH_LINE* segment = (SCH_LINE*) screen->GetCurItem();
|
2010-12-08 20:12:46 +00:00
|
|
|
|
2012-02-26 18:39:39 +00:00
|
|
|
if( segment == NULL || segment->Type() != SCH_LINE_T || !segment->IsNew() )
|
2007-08-20 01:20:48 +00:00
|
|
|
return;
|
|
|
|
|
2012-02-26 18:39:39 +00:00
|
|
|
// Delete zero length segments and clear item flags.
|
|
|
|
SCH_ITEM* item = s_wires.begin();
|
2010-12-08 20:12:46 +00:00
|
|
|
|
2012-02-26 18:39:39 +00:00
|
|
|
while( item )
|
2007-08-20 01:20:48 +00:00
|
|
|
{
|
2012-02-26 18:39:39 +00:00
|
|
|
item->ClearFlags();
|
2010-12-08 20:12:46 +00:00
|
|
|
|
2012-02-26 18:39:39 +00:00
|
|
|
wxCHECK_RET( item->Type() == SCH_LINE_T, wxT( "Unexpected object type in wire list." ) );
|
2010-12-08 20:12:46 +00:00
|
|
|
|
2012-02-26 18:39:39 +00:00
|
|
|
segment = (SCH_LINE*) item;
|
2012-07-05 11:37:48 +00:00
|
|
|
item = item->Next();
|
2010-12-08 20:12:46 +00:00
|
|
|
|
2012-02-26 18:39:39 +00:00
|
|
|
if( segment->IsNull() )
|
2012-07-05 11:37:48 +00:00
|
|
|
delete s_wires.Remove( segment );
|
2007-08-20 01:20:48 +00:00
|
|
|
}
|
|
|
|
|
2012-02-26 18:39:39 +00:00
|
|
|
if( s_wires.GetCount() == 0 )
|
|
|
|
return;
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2012-07-05 11:37:48 +00:00
|
|
|
// Get the last non-null wire (this is the last created segment).
|
2013-08-05 21:02:41 +00:00
|
|
|
SetRepeatItem( segment = (SCH_LINE*) s_wires.GetLast() );
|
|
|
|
|
2012-02-26 18:39:39 +00:00
|
|
|
screen->SetCurItem( NULL );
|
2011-12-22 13:28:11 +00:00
|
|
|
m_canvas->EndMouseCapture( -1, -1, wxEmptyString, false );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2012-07-05 11:37:48 +00:00
|
|
|
// store the terminal point of this last segment: a junction could be needed
|
|
|
|
// (the last wire could be merged/deleted/modified, and lost)
|
|
|
|
wxPoint endpoint = segment->GetEndPoint();
|
|
|
|
|
|
|
|
// store the starting point of this first segment: a junction could be needed
|
|
|
|
SCH_LINE* firstsegment = (SCH_LINE*) s_wires.GetFirst();
|
|
|
|
wxPoint startPoint = firstsegment->GetStartPoint();
|
|
|
|
|
2015-04-10 11:22:44 +00:00
|
|
|
// Save the old wires for the undo command
|
|
|
|
DLIST< SCH_ITEM > oldWires; // stores here the old wires
|
|
|
|
GetScreen()->ExtractWires( oldWires, true ); // Save them in oldWires list
|
|
|
|
// Put the snap shot of the previous wire, buses, and junctions in the undo/redo list.
|
|
|
|
PICKED_ITEMS_LIST oldItems;
|
|
|
|
oldItems.m_Status = UR_WIRE_IMAGE;
|
|
|
|
|
|
|
|
while( oldWires.GetCount() != 0 )
|
|
|
|
{
|
|
|
|
ITEM_PICKER picker = ITEM_PICKER( oldWires.PopFront(), UR_WIRE_IMAGE );
|
|
|
|
oldItems.PushItem( picker );
|
|
|
|
}
|
|
|
|
|
|
|
|
SaveCopyInUndoList( oldItems, UR_WIRE_IMAGE );
|
|
|
|
|
2015-06-23 15:01:34 +00:00
|
|
|
// Remove segments backtracking over others
|
|
|
|
RemoveBacktracks( s_wires );
|
|
|
|
|
2015-04-10 11:22:44 +00:00
|
|
|
// Add the new wires
|
2012-06-20 09:52:29 +00:00
|
|
|
screen->Append( s_wires );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2012-07-05 11:37:48 +00:00
|
|
|
// Correct and remove segments that need to be merged.
|
2012-03-09 18:58:58 +00:00
|
|
|
screen->SchematicCleanUp( NULL, DC );
|
2010-12-08 20:12:46 +00:00
|
|
|
|
2012-07-05 11:37:48 +00:00
|
|
|
// A junction could be needed to connect the end point of the last created segment.
|
|
|
|
if( screen->IsJunctionNeeded( endpoint ) )
|
|
|
|
screen->Append( AddJunction( DC, endpoint ) );
|
|
|
|
|
|
|
|
// A junction could be needed to connect the start point of the set of new created wires
|
|
|
|
if( screen->IsJunctionNeeded( startPoint ) )
|
|
|
|
screen->Append( AddJunction( DC, startPoint ) );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2012-03-09 18:58:58 +00:00
|
|
|
m_canvas->Refresh();
|
2010-12-08 20:12:46 +00:00
|
|
|
|
2012-02-26 18:39:39 +00:00
|
|
|
OnModify();
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2011-11-10 15:55:05 +00:00
|
|
|
/**
|
|
|
|
* 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.
|
2012-02-26 18:39:39 +00:00
|
|
|
*
|
|
|
|
* @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.
|
2007-08-20 01:20:48 +00:00
|
|
|
*/
|
2011-11-10 15:55:05 +00:00
|
|
|
static void ComputeBreakPoint( SCH_LINE* aSegment, const wxPoint& aPosition )
|
2009-12-02 21:44:03 +00:00
|
|
|
{
|
2012-02-26 18:39:39 +00:00
|
|
|
wxCHECK_RET( aSegment != NULL, wxT( "Cannot compute break point of NULL line segment." ) );
|
|
|
|
|
|
|
|
SCH_LINE* nextSegment = aSegment->Next();
|
|
|
|
wxPoint midPoint = aPosition;
|
|
|
|
|
|
|
|
wxCHECK_RET( nextSegment != NULL,
|
|
|
|
wxT( "Cannot compute break point of NULL second line segment." ) );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
|
|
|
#if 0
|
2012-02-26 18:39:39 +00:00
|
|
|
if( ABS( midPoint.x - aSegment->GetStartPoint().x ) <
|
|
|
|
ABS( midPoint.y - aSegment->GetStartPoint().y ) )
|
|
|
|
midPoint.x = aSegment->GetStartPoint().x;
|
2007-08-20 01:20:48 +00:00
|
|
|
else
|
2012-02-26 18:39:39 +00:00
|
|
|
midPoint.y = aSegment->GetStartPoint().y;
|
2007-05-06 16:03:28 +00:00
|
|
|
#else
|
2011-12-07 20:19:29 +00:00
|
|
|
int iDx = aSegment->GetEndPoint().x - aSegment->GetStartPoint().x;
|
|
|
|
int iDy = aSegment->GetEndPoint().y - aSegment->GetStartPoint().y;
|
2010-12-08 20:12:46 +00:00
|
|
|
|
|
|
|
if( iDy != 0 ) // keep the first segment orientation (currently horizontal)
|
2007-08-20 01:20:48 +00:00
|
|
|
{
|
2012-02-26 18:39:39 +00:00
|
|
|
midPoint.x = aSegment->GetStartPoint().x;
|
2007-08-20 01:20:48 +00:00
|
|
|
}
|
2010-12-08 20:12:46 +00:00
|
|
|
else if( iDx != 0 ) // keep the first segment orientation (currently vertical)
|
2007-08-20 01:20:48 +00:00
|
|
|
{
|
2012-02-26 18:39:39 +00:00
|
|
|
midPoint.y = aSegment->GetStartPoint().y;
|
2007-08-20 01:20:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-09-22 11:19:37 +00:00
|
|
|
if( std::abs( midPoint.x - aSegment->GetStartPoint().x ) <
|
|
|
|
std::abs( midPoint.y - aSegment->GetStartPoint().y ) )
|
2012-02-26 18:39:39 +00:00
|
|
|
midPoint.x = aSegment->GetStartPoint().x;
|
2007-08-20 01:20:48 +00:00
|
|
|
else
|
2012-02-26 18:39:39 +00:00
|
|
|
midPoint.y = aSegment->GetStartPoint().y;
|
2007-08-20 01:20:48 +00:00
|
|
|
}
|
2007-05-06 16:03:28 +00:00
|
|
|
#endif
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2012-02-26 18:39:39 +00:00
|
|
|
aSegment->SetEndPoint( midPoint );
|
|
|
|
nextSegment->SetStartPoint( midPoint );
|
|
|
|
nextSegment->SetEndPoint( aPosition );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2010-12-08 20:12:46 +00:00
|
|
|
void SCH_EDIT_FRAME::DeleteCurrentSegment( wxDC* DC )
|
2009-12-02 21:44:03 +00:00
|
|
|
{
|
2011-02-05 02:21:11 +00:00
|
|
|
SCH_SCREEN* screen = GetScreen();
|
|
|
|
|
2013-08-05 21:02:41 +00:00
|
|
|
SetRepeatItem( NULL );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2011-02-05 02:21:11 +00:00
|
|
|
if( ( screen->GetCurItem() == NULL ) || !screen->GetCurItem()->IsNew() )
|
2007-08-20 01:20:48 +00:00
|
|
|
return;
|
|
|
|
|
2013-04-06 12:28:02 +00:00
|
|
|
DrawSegment( m_canvas, DC, wxDefaultPosition, false );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2012-02-26 18:39:39 +00:00
|
|
|
screen->Remove( screen->GetCurItem() );
|
2011-12-29 20:11:42 +00:00
|
|
|
m_canvas->SetMouseCaptureCallback( NULL );
|
2011-02-05 02:21:11 +00:00
|
|
|
screen->SetCurItem( NULL );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-05 02:21:11 +00:00
|
|
|
SCH_JUNCTION* SCH_EDIT_FRAME::AddJunction( wxDC* aDC, const wxPoint& aPosition,
|
|
|
|
bool aPutInUndoList )
|
2009-12-02 21:44:03 +00:00
|
|
|
{
|
2011-02-05 02:21:11 +00:00
|
|
|
SCH_JUNCTION* junction = new SCH_JUNCTION( aPosition );
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2013-08-05 21:02:41 +00:00
|
|
|
SetRepeatItem( junction );
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2011-12-22 13:28:11 +00:00
|
|
|
m_canvas->CrossHairOff( aDC ); // Erase schematic cursor
|
|
|
|
junction->Draw( m_canvas, aDC, wxPoint( 0, 0 ), GR_DEFAULT_DRAWMODE );
|
|
|
|
m_canvas->CrossHairOn( aDC ); // Display schematic cursor
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2011-02-05 02:21:11 +00:00
|
|
|
if( aPutInUndoList )
|
2012-02-26 18:39:39 +00:00
|
|
|
{
|
|
|
|
GetScreen()->Append( junction );
|
2011-02-05 02:21:11 +00:00
|
|
|
SaveCopyInUndoList( junction, UR_NEW );
|
2012-02-26 18:39:39 +00:00
|
|
|
OnModify();
|
|
|
|
}
|
2010-12-08 20:12:46 +00:00
|
|
|
|
2011-02-05 02:21:11 +00:00
|
|
|
return junction;
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2011-02-03 19:27:28 +00:00
|
|
|
SCH_NO_CONNECT* SCH_EDIT_FRAME::AddNoConnect( wxDC* aDC, const wxPoint& aPosition )
|
2009-12-02 21:44:03 +00:00
|
|
|
{
|
2013-08-05 21:02:41 +00:00
|
|
|
SCH_NO_CONNECT* no_connect = new SCH_NO_CONNECT( aPosition );
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2013-08-05 21:02:41 +00:00
|
|
|
SetRepeatItem( no_connect );
|
|
|
|
GetScreen()->Append( no_connect );
|
2015-06-24 15:39:44 +00:00
|
|
|
GetScreen()->SchematicCleanUp( m_canvas, aDC );
|
2010-12-08 20:12:46 +00:00
|
|
|
OnModify();
|
2015-06-24 15:39:44 +00:00
|
|
|
m_canvas->Refresh();
|
2013-08-05 21:02:41 +00:00
|
|
|
SaveCopyInUndoList( no_connect, UR_NEW );
|
|
|
|
return no_connect;
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Abort function for wire, bus or line creation
|
2007-08-20 01:20:48 +00:00
|
|
|
*/
|
2015-04-10 11:22:44 +00:00
|
|
|
static void AbortCreateNewLine( EDA_DRAW_PANEL* aPanel, wxDC* aDC )
|
2009-12-02 21:44:03 +00:00
|
|
|
{
|
2015-04-10 11:22:44 +00:00
|
|
|
SCH_SCREEN* screen = (SCH_SCREEN*) aPanel->GetScreen();
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2011-02-05 02:21:11 +00:00
|
|
|
if( screen->GetCurItem() )
|
2007-08-20 01:20:48 +00:00
|
|
|
{
|
2015-04-10 11:22:44 +00:00
|
|
|
s_wires.DeleteAll(); // Free the list, for a future usage
|
2011-02-05 02:21:11 +00:00
|
|
|
screen->SetCurItem( NULL );
|
2015-04-10 11:22:44 +00:00
|
|
|
aPanel->Refresh();
|
2007-08-20 01:20:48 +00:00
|
|
|
}
|
|
|
|
else
|
2011-01-12 21:47:54 +00:00
|
|
|
{
|
2015-04-10 11:22:44 +00:00
|
|
|
SCH_EDIT_FRAME* parent = ( SCH_EDIT_FRAME* ) aPanel->GetParent();
|
2011-01-12 21:47:54 +00:00
|
|
|
parent->SetRepeatItem( NULL );
|
|
|
|
}
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2011-03-10 19:36:30 +00:00
|
|
|
// Clear flags used in edit functions.
|
|
|
|
screen->ClearDrawingState();
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-12-08 20:12:46 +00:00
|
|
|
void SCH_EDIT_FRAME::RepeatDrawItem( wxDC* DC )
|
2009-12-02 21:44:03 +00:00
|
|
|
{
|
2013-08-05 21:02:41 +00:00
|
|
|
SCH_ITEM* repeater = GetRepeatItem();
|
|
|
|
|
|
|
|
if( !repeater )
|
2007-08-20 01:20:48 +00:00
|
|
|
return;
|
|
|
|
|
2013-08-05 21:02:41 +00:00
|
|
|
//D( repeater>Show( 0, std::cout ); )
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2013-08-05 21:02:41 +00:00
|
|
|
// clone the repeater, move it, insert into display list, then save a copy
|
|
|
|
// via SetRepeatItem();
|
|
|
|
|
|
|
|
SCH_ITEM* my_clone = (SCH_ITEM*) repeater->Clone();
|
|
|
|
|
|
|
|
// If cloning a component then put into 'move' mode.
|
|
|
|
if( my_clone->Type() == SCH_COMPONENT_T )
|
2010-12-21 15:13:09 +00:00
|
|
|
{
|
2013-08-03 05:15:23 +00:00
|
|
|
wxPoint pos = GetCrossHairPosition() -
|
2013-08-05 21:02:41 +00:00
|
|
|
( (SCH_COMPONENT*) my_clone )->GetPosition();
|
2013-08-03 05:15:23 +00:00
|
|
|
|
2013-08-05 21:02:41 +00:00
|
|
|
my_clone->SetFlags( IS_NEW );
|
|
|
|
( (SCH_COMPONENT*) my_clone )->SetTimeStamp( GetNewTimeStamp() );
|
|
|
|
my_clone->Move( pos );
|
|
|
|
my_clone->Draw( m_canvas, DC, wxPoint( 0, 0 ), g_XorMode );
|
2015-02-28 16:56:09 +00:00
|
|
|
PrepareMoveItem( my_clone, DC );
|
2010-12-21 15:13:09 +00:00
|
|
|
}
|
2013-08-05 21:02:41 +00:00
|
|
|
else
|
|
|
|
{
|
2015-04-22 11:39:00 +00:00
|
|
|
my_clone->Move( GetRepeatStep() );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2013-08-05 21:02:41 +00:00
|
|
|
if( my_clone->CanIncrementLabel() )
|
2015-04-22 11:39:00 +00:00
|
|
|
( (SCH_TEXT*) my_clone )->IncrementLabel( GetRepeatDeltaLabel() );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2013-08-05 21:02:41 +00:00
|
|
|
GetScreen()->Append( my_clone );
|
2011-01-21 19:30:59 +00:00
|
|
|
GetScreen()->TestDanglingEnds();
|
2013-08-05 21:02:41 +00:00
|
|
|
my_clone->Draw( m_canvas, DC, wxPoint( 0, 0 ), GR_DEFAULT_DRAWMODE );
|
|
|
|
SaveCopyInUndoList( my_clone, UR_NEW );
|
|
|
|
my_clone->ClearFlags();
|
2007-08-20 01:20:48 +00:00
|
|
|
}
|
2013-08-05 21:02:41 +00:00
|
|
|
|
|
|
|
// clone my_clone, now that it has been moved, thus saving new position.
|
|
|
|
SetRepeatItem( my_clone );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|