Schematic Drag: fixes and improvements
Fixes: * Various special cases around junctions on pins and dragging. * Some rotations of endpoints resulting in a 45 degree rotate. * Some cases where it was possible to get a line with neither endpoint selected, and also substractive unselecting only one of two selected endpoints unselecting both. * Use line midpoint for sorting. Start and endpoints aren't consistent in the order they appear on the X or Y axis. So, we need to use the midpoint for our position for consistent sorting when dragging groups of parallel lines where some have the start and end reversed. Other: * Rename TEMP_SELECTED TO SELECTED_BY_DRAG. This is the actual meaning of the flag, and should reduce confusion as to when it should be used. * Move usage of TEMP_SELECTED as an algorithmic mark to CANDIDATE instead. * Fix mistaken clearing of START_POINT and ENDPOINT. * Move endpoint setting and clearing out of narrowSelection, and into selectPoint and selectMultiple. * Don't show dangling end warnings on new lines
This commit is contained in:
parent
4c225cff5b
commit
e51ab86225
|
@ -256,6 +256,7 @@ public:
|
|||
|
||||
VECTOR2I GetPosition() const override { return m_start; }
|
||||
void SetPosition( const VECTOR2I& aPosition ) override;
|
||||
VECTOR2I GetSortPosition() const override { return GetMidPoint(); }
|
||||
|
||||
bool IsPointClickableAnchor( const VECTOR2I& aPos ) const override
|
||||
{
|
||||
|
|
|
@ -1602,6 +1602,11 @@ void SCH_PAINTER::draw( const SCH_LINE *aLine, int aLayer )
|
|||
if( drawingShadows && !( aLine->IsBrightened() || aLine->IsSelected() ) )
|
||||
return;
|
||||
|
||||
// Line end dangling status isn't updated until the line is finished drawing,
|
||||
// so don't warn them about ends that are probably connected
|
||||
if( aLine->IsNew() && drawingDangling )
|
||||
return;
|
||||
|
||||
COLOR4D color = getRenderColor( aLine, aLine->GetLayer(), drawingShadows );
|
||||
float width = getLineWidth( aLine, drawingShadows );
|
||||
PLOT_DASH_TYPE lineStyle = aLine->GetEffectiveLineStyle();
|
||||
|
|
|
@ -1010,9 +1010,9 @@ void EE_POINT_EDITOR::updateParentItem() const
|
|||
if( connected.first )
|
||||
{
|
||||
if( connected.second == STARTPOINT )
|
||||
static_cast<SCH_LINE*>( connected.first )->SetStartPoint( line->GetPosition() );
|
||||
static_cast<SCH_LINE*>( connected.first )->SetStartPoint( line->GetStartPoint() );
|
||||
else if( connected.second == ENDPOINT )
|
||||
static_cast<SCH_LINE*>( connected.first )->SetEndPoint( line->GetPosition() );
|
||||
static_cast<SCH_LINE*>( connected.first )->SetEndPoint( line->GetStartPoint() );
|
||||
|
||||
updateItem( connected.first, true );
|
||||
}
|
||||
|
|
|
@ -377,7 +377,7 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
// Collect items at the clicked location (doesn't select them yet)
|
||||
EE_COLLECTOR collector;
|
||||
CollectHits( collector, evt->Position() );
|
||||
narrowSelection( collector, evt->Position(), false, false );
|
||||
narrowSelection( collector, evt->Position(), false );
|
||||
|
||||
if( collector.GetCount() == 1 && !m_isSymbolEditor && !modifier_enabled )
|
||||
{
|
||||
|
@ -405,7 +405,8 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
|
||||
if( !selCancelled )
|
||||
{
|
||||
selectPoint( collector, nullptr, nullptr, m_additive, m_subtractive, m_exclusive_or );
|
||||
selectPoint( collector, evt->Position(), nullptr, nullptr, m_additive,
|
||||
m_subtractive, m_exclusive_or );
|
||||
m_selection.SetIsHover( false );
|
||||
}
|
||||
}
|
||||
|
@ -580,7 +581,7 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
|
||||
if( CollectHits( collector, evt->Position() ) )
|
||||
{
|
||||
narrowSelection( collector, evt->Position(), false, false );
|
||||
narrowSelection( collector, evt->Position(), false );
|
||||
|
||||
if( collector.GetCount() == 1 && !modifier_enabled )
|
||||
{
|
||||
|
@ -797,7 +798,7 @@ bool EE_SELECTION_TOOL::CollectHits( EE_COLLECTOR& aCollector, const VECTOR2I& a
|
|||
|
||||
|
||||
void EE_SELECTION_TOOL::narrowSelection( EE_COLLECTOR& collector, const VECTOR2I& aWhere,
|
||||
bool aCheckLocked, bool aSelectPoints )
|
||||
bool aCheckLocked )
|
||||
{
|
||||
for( int i = collector.GetCount() - 1; i >= 0; --i )
|
||||
{
|
||||
|
@ -812,20 +813,6 @@ void EE_SELECTION_TOOL::narrowSelection( EE_COLLECTOR& collector, const VECTOR2I
|
|||
collector.Remove( i );
|
||||
continue;
|
||||
}
|
||||
|
||||
// SelectPoint, unlike other selection routines, can select line ends
|
||||
if( aSelectPoints && collector[i]->Type() == SCH_LINE_T )
|
||||
{
|
||||
SCH_LINE* line = (SCH_LINE*) collector[i];
|
||||
line->ClearFlags( STARTPOINT | ENDPOINT );
|
||||
|
||||
if( HitTestPoints( line->GetStartPoint(), aWhere, collector.m_Threshold ) )
|
||||
line->SetFlags( STARTPOINT );
|
||||
else if( HitTestPoints( line->GetEndPoint(), aWhere, collector.m_Threshold ) )
|
||||
line->SetFlags( ENDPOINT );
|
||||
else
|
||||
line->SetFlags( STARTPOINT | ENDPOINT );
|
||||
}
|
||||
}
|
||||
|
||||
// Apply some ugly heuristics to avoid disambiguation menus whenever possible
|
||||
|
@ -836,9 +823,9 @@ void EE_SELECTION_TOOL::narrowSelection( EE_COLLECTOR& collector, const VECTOR2I
|
|||
}
|
||||
|
||||
|
||||
bool EE_SELECTION_TOOL::selectPoint( EE_COLLECTOR& aCollector, EDA_ITEM** aItem,
|
||||
bool* aSelectionCancelledFlag, bool aAdd, bool aSubtract,
|
||||
bool aExclusiveOr )
|
||||
bool EE_SELECTION_TOOL::selectPoint( EE_COLLECTOR& aCollector, const VECTOR2I& aWhere,
|
||||
EDA_ITEM** aItem, bool* aSelectionCancelledFlag, bool aAdd,
|
||||
bool aSubtract, bool aExclusiveOr )
|
||||
{
|
||||
m_selection.ClearReferencePoint();
|
||||
|
||||
|
@ -873,13 +860,33 @@ bool EE_SELECTION_TOOL::selectPoint( EE_COLLECTOR& aCollector, EDA_ITEM** aItem,
|
|||
{
|
||||
for( int i = 0; i < aCollector.GetCount(); ++i )
|
||||
{
|
||||
EDA_ITEM_FLAGS flags = 0;
|
||||
|
||||
// Handle line ends specially
|
||||
if( aCollector[i]->Type() == SCH_LINE_T )
|
||||
{
|
||||
SCH_LINE* line = (SCH_LINE*) aCollector[i];
|
||||
|
||||
if( HitTestPoints( line->GetStartPoint(), aWhere, aCollector.m_Threshold ) )
|
||||
flags = STARTPOINT;
|
||||
else if( HitTestPoints( line->GetEndPoint(), aWhere, aCollector.m_Threshold ) )
|
||||
flags = ENDPOINT;
|
||||
else
|
||||
flags = STARTPOINT | ENDPOINT;
|
||||
}
|
||||
|
||||
if( aSubtract || ( aExclusiveOr && aCollector[i]->IsSelected() ) )
|
||||
{
|
||||
aCollector[i]->ClearFlags( flags );
|
||||
if( !aCollector[i]->HasFlag( STARTPOINT ) && !aCollector[i]->HasFlag( ENDPOINT ) )
|
||||
{
|
||||
unselect( aCollector[i] );
|
||||
anySubtracted = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aCollector[i]->SetFlags( flags );
|
||||
select( aCollector[i] );
|
||||
anyAdded = true;
|
||||
}
|
||||
|
@ -915,9 +922,10 @@ bool EE_SELECTION_TOOL::SelectPoint( const VECTOR2I& aWhere, const KICAD_T* aFil
|
|||
if( !CollectHits( collector, aWhere, aFilterList ) )
|
||||
return false;
|
||||
|
||||
narrowSelection( collector, aWhere, aCheckLocked, true );
|
||||
narrowSelection( collector, aWhere, aCheckLocked );
|
||||
|
||||
return selectPoint( collector, aItem, aSelectionCancelledFlag, aAdd, aSubtract, aExclusiveOr );
|
||||
return selectPoint( collector, aWhere, aItem, aSelectionCancelledFlag, aAdd, aSubtract,
|
||||
aExclusiveOr );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1234,7 +1242,7 @@ bool EE_SELECTION_TOOL::selectMultiple()
|
|||
|
||||
if( item )
|
||||
{
|
||||
item->ClearFlags( TEMP_SELECTED | STARTPOINT | ENDPOINT );
|
||||
item->ClearFlags( CANDIDATE );
|
||||
nearbyItems.push_back( item );
|
||||
}
|
||||
|
||||
|
@ -1253,40 +1261,44 @@ bool EE_SELECTION_TOOL::selectMultiple()
|
|||
|
||||
bool anyAdded = false;
|
||||
bool anySubtracted = false;
|
||||
auto selectItem =
|
||||
[&]( EDA_ITEM* aItem )
|
||||
auto selectItem = [&]( EDA_ITEM* aItem )
|
||||
{
|
||||
EDA_ITEM_FLAGS flags = 0;
|
||||
|
||||
// Handle line ends specially
|
||||
if( aItem->Type() == SCH_LINE_T )
|
||||
{
|
||||
SCH_LINE* line = (SCH_LINE*) aItem;
|
||||
|
||||
if( selectionRect.Contains( line->GetStartPoint() ) )
|
||||
flags |= STARTPOINT;
|
||||
|
||||
if( selectionRect.Contains( line->GetEndPoint() ) )
|
||||
flags |= ENDPOINT;
|
||||
|
||||
|
||||
// If no ends were selected, select whole line (both ends)
|
||||
// Also select both ends if the selection overlaps the midpoint
|
||||
if( ( !( flags & STARTPOINT ) && !( flags & ENDPOINT ) )
|
||||
|| selectionRect.Contains( line->GetMidPoint() ) )
|
||||
{
|
||||
flags = STARTPOINT | ENDPOINT;
|
||||
}
|
||||
}
|
||||
|
||||
if( m_subtractive || ( m_exclusive_or && aItem->IsSelected() ) )
|
||||
{
|
||||
aItem->ClearFlags( flags );
|
||||
if( !aItem->HasFlag( STARTPOINT ) && !aItem->HasFlag( ENDPOINT ) )
|
||||
{
|
||||
unselect( aItem );
|
||||
anySubtracted = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aItem->SetFlags( flags );
|
||||
select( aItem );
|
||||
|
||||
// Lines can have just one end selected
|
||||
if( aItem->Type() == SCH_LINE_T )
|
||||
{
|
||||
SCH_LINE* line = static_cast<SCH_LINE*>( aItem );
|
||||
|
||||
line->ClearFlags( STARTPOINT | ENDPOINT );
|
||||
|
||||
if( selectionRect.Contains( line->GetStartPoint() ) )
|
||||
line->SetFlags( STARTPOINT );
|
||||
|
||||
if( selectionRect.Contains( line->GetEndPoint() ) )
|
||||
line->SetFlags( ENDPOINT );
|
||||
|
||||
// If no ends were selected, select whole line (both ends)
|
||||
// Also select both ends if the selection overlaps the midpoint
|
||||
if( ( !line->HasFlag( STARTPOINT ) && !line->HasFlag( ENDPOINT ) )
|
||||
|| selectionRect.Contains( line->GetMidPoint() ) )
|
||||
{
|
||||
line->SetFlags( STARTPOINT | ENDPOINT );
|
||||
}
|
||||
}
|
||||
|
||||
anyAdded = true;
|
||||
}
|
||||
};
|
||||
|
@ -1295,7 +1307,7 @@ bool EE_SELECTION_TOOL::selectMultiple()
|
|||
{
|
||||
if( Selectable( item ) && item->HitTest( selectionRect, isWindowSelection ) )
|
||||
{
|
||||
item->SetFlags( TEMP_SELECTED );
|
||||
item->SetFlags( CANDIDATE );
|
||||
selectItem( item );
|
||||
}
|
||||
}
|
||||
|
@ -1303,7 +1315,7 @@ bool EE_SELECTION_TOOL::selectMultiple()
|
|||
for( EDA_ITEM* item : nearbyChildren )
|
||||
{
|
||||
if( Selectable( item )
|
||||
&& !item->GetParent()->HasFlag( TEMP_SELECTED )
|
||||
&& !item->GetParent()->HasFlag( CANDIDATE )
|
||||
&& item->HitTest( selectionRect, isWindowSelection ) )
|
||||
{
|
||||
selectItem( item );
|
||||
|
@ -1886,7 +1898,12 @@ void EE_SELECTION_TOOL::unhighlight( EDA_ITEM* aItem, int aMode, EE_SELECTION* a
|
|||
KICAD_T itemType = aItem->Type();
|
||||
|
||||
if( aMode == SELECTED )
|
||||
{
|
||||
aItem->ClearSelected();
|
||||
// Lines need endpoints cleared here
|
||||
if( aItem->Type() == SCH_LINE_T )
|
||||
aItem->ClearFlags( STARTPOINT | ENDPOINT );
|
||||
}
|
||||
else if( aMode == BRIGHTENED )
|
||||
aItem->ClearBrightened();
|
||||
|
||||
|
|
|
@ -197,10 +197,8 @@ private:
|
|||
* @param collector EE_COLLECTOR with elements to filter
|
||||
* @param aWhere point where we should narrow (if relevant)
|
||||
* @param aCheckLocked If false, remove locked elements from #collector
|
||||
* @param aSelectPoints If true, set STARTPOINT/ENDPOINT flags on individual wires
|
||||
*/
|
||||
void narrowSelection( EE_COLLECTOR& collector, const VECTOR2I& aWhere, bool aCheckLocked,
|
||||
bool aSelectPoints );
|
||||
void narrowSelection( EE_COLLECTOR& collector, const VECTOR2I& aWhere, bool aCheckLocked );
|
||||
|
||||
/**
|
||||
* This is the primary SelectPoint method that will prompt the user with a menu to disambiguate
|
||||
|
@ -208,6 +206,7 @@ private:
|
|||
* actual selection group.
|
||||
*
|
||||
* @param aCollector is an EE_COLLECTOR that already has collected items
|
||||
* @param aWhere position of the selected point
|
||||
* @param aItem is set to the newly selected item if only one was selected, otherwise is
|
||||
* unchanged.
|
||||
* @param aSelectionCancelledFlag allows the function to inform its caller that a selection
|
||||
|
@ -217,7 +216,7 @@ private:
|
|||
* @param aSubtract indicates if found item(s) should be subtracted from the selection
|
||||
* @param aExclusiveOr indicates if found item(s) should be toggle in the selection
|
||||
*/
|
||||
bool selectPoint( EE_COLLECTOR& aCollector, EDA_ITEM** aItem = nullptr,
|
||||
bool selectPoint( EE_COLLECTOR& aCollector, const VECTOR2I& aWhere, EDA_ITEM** aItem = nullptr,
|
||||
bool* aSelectionCancelledFlag = nullptr, bool aAdd = false,
|
||||
bool aSubtract = false, bool aExclusiveOr = false );
|
||||
|
||||
|
|
|
@ -139,7 +139,7 @@ protected:
|
|||
|
||||
// IS_SELECTED flag should not be set on undo items which were added for
|
||||
// a drag operation.
|
||||
if( selected && aItem->HasFlag( TEMP_SELECTED ) )
|
||||
if( selected && aItem->HasFlag( SELECTED_BY_DRAG ) )
|
||||
aItem->ClearSelected();
|
||||
|
||||
if( m_isSymbolEditor )
|
||||
|
@ -168,7 +168,7 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
if( selected && aItem->HasFlag( TEMP_SELECTED ) )
|
||||
if( selected && aItem->HasFlag( SELECTED_BY_DRAG ) )
|
||||
aItem->SetSelected();
|
||||
}
|
||||
|
||||
|
|
|
@ -498,7 +498,7 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
|
|||
{
|
||||
SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.GetItem( ii ) );
|
||||
|
||||
if( item->HasFlag( TEMP_SELECTED ) )
|
||||
if( item->HasFlag( SELECTED_BY_DRAG ) )
|
||||
continue;
|
||||
|
||||
principalItemCount++;
|
||||
|
@ -652,7 +652,7 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
|
|||
|
||||
// We've already rotated the user selected item if there was only one. We're just
|
||||
// here to rotate the ends of wires that were attached to it.
|
||||
if( principalItemCount == 1 && !item->HasFlag( TEMP_SELECTED ) )
|
||||
if( principalItemCount == 1 && !item->HasFlag( SELECTED_BY_DRAG ) )
|
||||
continue;
|
||||
|
||||
if( !moving )
|
||||
|
|
|
@ -189,7 +189,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
|
||||
for( SCH_ITEM* it : m_frame->GetScreen()->Items() )
|
||||
{
|
||||
it->ClearFlags( TEMP_SELECTED );
|
||||
it->ClearFlags( SELECTED_BY_DRAG );
|
||||
|
||||
if( !it->IsSelected() )
|
||||
it->ClearFlags( STARTPOINT | ENDPOINT );
|
||||
|
@ -268,7 +268,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
|
||||
if( item->IsNew() )
|
||||
{
|
||||
if( item->HasFlag( TEMP_SELECTED ) && m_isDrag )
|
||||
if( item->HasFlag( SELECTED_BY_DRAG ) && m_isDrag )
|
||||
{
|
||||
// Item was added in getConnectedDragItems
|
||||
saveCopyInUndoList( (SCH_ITEM*) item, UNDO_REDO::NEWITEM, appendUndo );
|
||||
|
@ -448,6 +448,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
// Look for pre-existing lines we can drag with us instead of creating new ones
|
||||
bool foundAttachment = false;
|
||||
bool foundJunction = false;
|
||||
bool foundPin = false;
|
||||
SCH_LINE* foundLine = nullptr;
|
||||
for( EDA_ITEM* cItem : m_lineConnectionCache[line] )
|
||||
{
|
||||
|
@ -455,7 +456,9 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
|
||||
// If the move is the same angle as a connected line,
|
||||
// we can shrink/extend that line endpoint
|
||||
if( cItem->Type() == SCH_LINE_T )
|
||||
switch( cItem->Type() )
|
||||
{
|
||||
case SCH_LINE_T:
|
||||
{
|
||||
SCH_LINE* cLine = static_cast<SCH_LINE*>( cItem );
|
||||
|
||||
|
@ -469,9 +472,19 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
// when we can (otherwise the zero length line will draw overlapping segments on them)
|
||||
if( foundLine == nullptr && cLine->GetLength() == 0 )
|
||||
foundLine = cLine;
|
||||
|
||||
break;
|
||||
}
|
||||
else if( cItem->Type() == SCH_JUNCTION_T )
|
||||
case SCH_JUNCTION_T:
|
||||
foundJunction = true;
|
||||
break;
|
||||
|
||||
case SCH_PIN_T:
|
||||
foundPin = true;
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
// Ok... what if our original line is length zero from moving in its direction,
|
||||
|
@ -491,8 +504,9 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
// If we have found an attachment, but not a line, we want to check if it's
|
||||
// a junction. These are special-cased and get a single line added instead of a
|
||||
// 90-degree bend.
|
||||
else if( !foundLine && foundJunction )
|
||||
// 90-degree bend. Except when we're on a pin, because pins always need bends,
|
||||
// and junctions are just added to pins for visual clarity.
|
||||
else if( !foundLine && foundJunction && !foundPin )
|
||||
{
|
||||
// Create a new wire ending at the unselected end
|
||||
foundLine = new SCH_LINE( unselectedEnd, line->GetLayer() );
|
||||
|
@ -884,18 +898,38 @@ void SCH_MOVE_TOOL::getConnectedItems( SCH_ITEM* aOriginalItem, const VECTOR2I&
|
|||
{
|
||||
EE_RTREE& items = m_frame->GetScreen()->Items();
|
||||
EE_RTREE::EE_TYPE itemsOverlapping = items.Overlapping( aOriginalItem->GetBoundingBox() );
|
||||
SCH_ITEM* foundJunction = nullptr;
|
||||
SCH_ITEM* foundSymbol = nullptr;
|
||||
|
||||
// If you're connected to a junction, you're only connected to the junction
|
||||
// (unless you are the junction)
|
||||
// If you're connected to a junction, you're only connected to the junction.
|
||||
//
|
||||
// But, if you're connected to a junction on a pin, you're only connected to the pin. This
|
||||
// is because junctions and pins have different logic for how bend lines are generated
|
||||
// and we need to prioritize the pin version in some cases.
|
||||
for( SCH_ITEM* item : itemsOverlapping )
|
||||
{
|
||||
if( item != aOriginalItem && item->Type() == SCH_JUNCTION_T && item->IsConnected( aPoint ) )
|
||||
if( item != aOriginalItem && item->IsConnected( aPoint ) )
|
||||
{
|
||||
aList.push_back( item );
|
||||
if( item->Type() == SCH_JUNCTION_T )
|
||||
foundJunction = item;
|
||||
else if( item->Type() == SCH_SYMBOL_T )
|
||||
foundSymbol = item;
|
||||
}
|
||||
}
|
||||
|
||||
if( foundSymbol && foundJunction )
|
||||
{
|
||||
aList.push_back( foundSymbol );
|
||||
return;
|
||||
}
|
||||
|
||||
if( foundJunction )
|
||||
{
|
||||
aList.push_back( foundJunction );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for( SCH_ITEM* test : itemsOverlapping )
|
||||
{
|
||||
if( test == aOriginalItem || !test->CanConnect( aOriginalItem ) )
|
||||
|
@ -1028,11 +1062,11 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aOriginalItem, const VECTOR
|
|||
// already been grabbed during the partial selection process.
|
||||
line->SetFlags( STARTPOINT );
|
||||
|
||||
if( line->HasFlag( SELECTED ) || line->HasFlag( TEMP_SELECTED ) )
|
||||
if( line->HasFlag( SELECTED ) || line->HasFlag( SELECTED_BY_DRAG ) )
|
||||
continue;
|
||||
else
|
||||
{
|
||||
line->SetFlags( TEMP_SELECTED );
|
||||
line->SetFlags( SELECTED_BY_DRAG );
|
||||
aList.push_back( line );
|
||||
}
|
||||
}
|
||||
|
@ -1040,11 +1074,11 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aOriginalItem, const VECTOR
|
|||
{
|
||||
line->SetFlags( ENDPOINT );
|
||||
|
||||
if( line->HasFlag( SELECTED ) || line->HasFlag( TEMP_SELECTED ) )
|
||||
if( line->HasFlag( SELECTED ) || line->HasFlag( SELECTED_BY_DRAG ) )
|
||||
continue;
|
||||
else
|
||||
{
|
||||
line->SetFlags( TEMP_SELECTED );
|
||||
line->SetFlags( SELECTED_BY_DRAG );
|
||||
aList.push_back( line );
|
||||
}
|
||||
}
|
||||
|
@ -1068,7 +1102,7 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aOriginalItem, const VECTOR
|
|||
newWire->SetFlags( IS_NEW );
|
||||
m_frame->AddToScreen( newWire, m_frame->GetScreen() );
|
||||
|
||||
newWire->SetFlags( TEMP_SELECTED | STARTPOINT );
|
||||
newWire->SetFlags( SELECTED_BY_DRAG | STARTPOINT );
|
||||
aList.push_back( newWire );
|
||||
|
||||
//We need to add a connection reference here because the normal
|
||||
|
@ -1100,12 +1134,12 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aOriginalItem, const VECTOR
|
|||
if( label->IsSelected() )
|
||||
continue; // These will be moved on their own because they're selected
|
||||
|
||||
if( label->HasFlag( TEMP_SELECTED ) )
|
||||
if( label->HasFlag( SELECTED_BY_DRAG ) )
|
||||
continue;
|
||||
|
||||
if( label->CanConnect( line ) && line->HitTest( label->GetPosition(), 1 ) )
|
||||
{
|
||||
label->SetFlags( TEMP_SELECTED );
|
||||
label->SetFlags( SELECTED_BY_DRAG );
|
||||
aList.push_back( label );
|
||||
|
||||
SPECIAL_CASE_LABEL_INFO info;
|
||||
|
@ -1141,17 +1175,17 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aOriginalItem, const VECTOR
|
|||
newWire->SetFlags( IS_NEW );
|
||||
m_frame->AddToScreen( newWire, m_frame->GetScreen() );
|
||||
|
||||
newWire->SetFlags( TEMP_SELECTED | STARTPOINT );
|
||||
newWire->SetFlags( SELECTED_BY_DRAG | STARTPOINT );
|
||||
aList.push_back( newWire );
|
||||
}
|
||||
break;
|
||||
|
||||
case SCH_NO_CONNECT_T:
|
||||
// Select no-connects that are connected to items being moved.
|
||||
if( !test->HasFlag( TEMP_SELECTED ) && test->IsConnected( aPoint ) )
|
||||
if( !test->HasFlag( SELECTED_BY_DRAG ) && test->IsConnected( aPoint ) )
|
||||
{
|
||||
aList.push_back( test );
|
||||
test->SetFlags( TEMP_SELECTED );
|
||||
test->SetFlags( SELECTED_BY_DRAG );
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -1161,7 +1195,7 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aOriginalItem, const VECTOR
|
|||
case SCH_HIER_LABEL_T:
|
||||
case SCH_DIRECTIVE_LABEL_T:
|
||||
// Performance optimization:
|
||||
if( test->HasFlag( TEMP_SELECTED ) )
|
||||
if( test->HasFlag( SELECTED_BY_DRAG ) )
|
||||
break;
|
||||
|
||||
// Select labels that are connected to a wire (or bus) being moved.
|
||||
|
@ -1185,7 +1219,7 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aOriginalItem, const VECTOR
|
|||
}
|
||||
else
|
||||
{
|
||||
label->SetFlags( TEMP_SELECTED );
|
||||
label->SetFlags( SELECTED_BY_DRAG );
|
||||
aList.push_back( label );
|
||||
|
||||
if( oneEndFixed )
|
||||
|
@ -1204,7 +1238,7 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aOriginalItem, const VECTOR
|
|||
case SCH_BUS_WIRE_ENTRY_T:
|
||||
case SCH_BUS_BUS_ENTRY_T:
|
||||
// Performance optimization:
|
||||
if( test->HasFlag( TEMP_SELECTED ) )
|
||||
if( test->HasFlag( SELECTED_BY_DRAG ) )
|
||||
break;
|
||||
|
||||
// Select bus entries that are connected to a bus being moved.
|
||||
|
@ -1224,7 +1258,7 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aOriginalItem, const VECTOR
|
|||
{
|
||||
if( line->HitTest( point, 1 ) )
|
||||
{
|
||||
test->SetFlags( TEMP_SELECTED );
|
||||
test->SetFlags( SELECTED_BY_DRAG );
|
||||
aList.push_back( test );
|
||||
|
||||
// A bus entry needs its wire & label as well
|
||||
|
|
|
@ -164,7 +164,7 @@ public:
|
|||
|
||||
void ClearTempFlags()
|
||||
{
|
||||
ClearFlags( CANDIDATE | TEMP_SELECTED | IS_LINKED | SKIP_STRUCT | DO_NOT_DRAW );
|
||||
ClearFlags( CANDIDATE | SELECTED_BY_DRAG | IS_LINKED | SKIP_STRUCT | DO_NOT_DRAW );
|
||||
}
|
||||
|
||||
void ClearEditFlags()
|
||||
|
@ -256,6 +256,15 @@ public:
|
|||
*/
|
||||
virtual const VECTOR2I GetFocusPosition() const { return GetPosition(); }
|
||||
|
||||
/**
|
||||
* Return the coordinates that should be used for sorting this element
|
||||
* visually compared to other elements. For instance, for lines the midpoint
|
||||
* might be a better sorting point than either end.
|
||||
*
|
||||
* @return X,Y coordinate of the sort point
|
||||
*/
|
||||
virtual VECTOR2I GetSortPosition() const { return GetPosition(); }
|
||||
|
||||
/**
|
||||
* Create a duplicate of this item with linked list members set to NULL.
|
||||
*
|
||||
|
|
|
@ -45,8 +45,8 @@
|
|||
#define IS_WIRE_IMAGE (1 << 8) ///< Item to be drawn as wireframe while editing
|
||||
#define STARTPOINT (1 << 9) ///< When a line is selected, these flags indicate which
|
||||
#define ENDPOINT (1 << 10) ///< ends. (Used to support dragging.)
|
||||
#define SELECTED (1 << 11)
|
||||
#define TEMP_SELECTED (1 << 12) ///< flag indicating that the structure has already selected
|
||||
#define SELECTED (1 << 11) ///< Item was manually selected by the user
|
||||
#define SELECTED_BY_DRAG (1 << 12) ///< Item was algorithmically selected as a dragged item
|
||||
#define STRUCT_DELETED (1 << 13) ///< flag indication structures to be erased
|
||||
#define CANDIDATE (1 << 14) ///< flag indicating that the structure is connected
|
||||
#define SKIP_STRUCT (1 << 15) ///< flag indicating that the structure should be ignored
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include <eda_item.h>
|
||||
#include <view/view_group.h>
|
||||
|
||||
class EDA_ITEM;
|
||||
|
||||
class SELECTION : public KIGFX::VIEW_GROUP
|
||||
{
|
||||
|
@ -126,21 +125,21 @@ public:
|
|||
std::sort( sorted_items.begin(), sorted_items.end(), [&]( EDA_ITEM* a, EDA_ITEM* b ) {
|
||||
if( a->Type() == b->Type() )
|
||||
{
|
||||
if( a->GetPosition().x == b->GetPosition().x )
|
||||
if( a->GetSortPosition().x == b->GetSortPosition().x )
|
||||
{
|
||||
// Ensure deterministic sort
|
||||
if( a->GetPosition().y == b->GetPosition().y )
|
||||
if( a->GetSortPosition().y == b->GetSortPosition().y )
|
||||
return a->m_Uuid < b->m_Uuid;
|
||||
|
||||
if( topBeforeBottom )
|
||||
return a->GetPosition().y < b->GetPosition().y;
|
||||
return a->GetSortPosition().y < b->GetSortPosition().y;
|
||||
else
|
||||
return a->GetPosition().y > b->GetPosition().y;
|
||||
return a->GetSortPosition().y > b->GetSortPosition().y;
|
||||
}
|
||||
else if( leftBeforeRight )
|
||||
return a->GetPosition().x < b->GetPosition().x;
|
||||
return a->GetSortPosition().x < b->GetSortPosition().x;
|
||||
else
|
||||
return a->GetPosition().x > b->GetPosition().x;
|
||||
return a->GetSortPosition().x > b->GetSortPosition().x;
|
||||
}
|
||||
else
|
||||
return a->Type() < b->Type();
|
||||
|
|
|
@ -3016,18 +3016,18 @@ void PCB_SELECTION_TOOL::FilterCollectorForHierarchy( GENERAL_COLLECTOR& aCollec
|
|||
{
|
||||
std::unordered_set<BOARD_ITEM*> toAdd;
|
||||
|
||||
// Set TEMP_SELECTED on all parents which are included in the GENERAL_COLLECTOR. This
|
||||
// Set CANDIDATE on all parents which are included in the GENERAL_COLLECTOR. This
|
||||
// algorithm is O3n, whereas checking for the parent inclusion could potentially be On^2.
|
||||
for( int j = 0; j < aCollector.GetCount(); j++ )
|
||||
{
|
||||
if( aCollector[j]->GetParent() )
|
||||
aCollector[j]->GetParent()->ClearFlags( TEMP_SELECTED );
|
||||
aCollector[j]->GetParent()->ClearFlags( CANDIDATE );
|
||||
}
|
||||
|
||||
if( aMultiselect )
|
||||
{
|
||||
for( int j = 0; j < aCollector.GetCount(); j++ )
|
||||
aCollector[j]->SetFlags( TEMP_SELECTED );
|
||||
aCollector[j]->SetFlags( CANDIDATE );
|
||||
}
|
||||
|
||||
for( int j = 0; j < aCollector.GetCount(); )
|
||||
|
@ -3048,7 +3048,7 @@ void PCB_SELECTION_TOOL::FilterCollectorForHierarchy( GENERAL_COLLECTOR& aCollec
|
|||
if( aTop != item )
|
||||
{
|
||||
toAdd.insert( aTop );
|
||||
aTop->SetFlags( TEMP_SELECTED );
|
||||
aTop->SetFlags( CANDIDATE );
|
||||
|
||||
aCollector.Remove( item );
|
||||
continue;
|
||||
|
@ -3063,7 +3063,7 @@ void PCB_SELECTION_TOOL::FilterCollectorForHierarchy( GENERAL_COLLECTOR& aCollec
|
|||
}
|
||||
|
||||
// Footprints are a bit easier as they can't be nested.
|
||||
if( parent && ( parent->GetFlags() & TEMP_SELECTED ) )
|
||||
if( parent && ( parent->GetFlags() & CANDIDATE ) )
|
||||
{
|
||||
// Remove children of selected items
|
||||
aCollector.Remove( item );
|
||||
|
|
Loading…
Reference in New Issue