KiCad PCB EDA Suite
Loading...
Searching...
No Matches
ee_selection_tool.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2019 CERN
5 * Copyright (C) 2019-2023 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <advanced_config.h>
26#include <core/typeinfo.h>
27#include <core/kicad_algo.h>
30#include <ee_actions.h>
31#include <ee_collectors.h>
32#include <ee_selection_tool.h>
33#include <eeschema_id.h>
34#include <symbol_edit_frame.h>
35#include <lib_item.h>
36#include <symbol_viewer_frame.h>
37#include <math/util.h>
38#include <geometry/shape_rect.h>
39#include <sch_painter.h>
41#include <sch_base_frame.h>
42#include <sch_commit.h>
43#include <sch_symbol.h>
44#include <sch_field.h>
45#include <sch_edit_frame.h>
46#include <sch_item.h>
47#include <sch_line.h>
48#include <sch_bus_entry.h>
49#include <sch_junction.h>
50#include <sch_marker.h>
51#include <sch_no_connect.h>
52#include <sch_sheet.h>
53#include <sch_sheet_pin.h>
54#include <lib_shape.h>
55#include <schematic.h>
56#include <tool/tool_event.h>
57#include <tool/tool_manager.h>
62#include <trigo.h>
63#include <view/view.h>
64#include <view/view_controls.h>
65#include <wx/log.h>
66
67
69{
70 if( aSel.GetSize() == 1 )
71 {
72 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aSel.Front() );
73
74 if( symbol )
75 return !symbol->GetLibSymbolRef() || !symbol->GetLibSymbolRef()->IsPower();
76 }
77
78 return false;
79};
80
81
83{
84 return aSel.GetSize() == 1 && aSel.Front()->Type() == SCH_SYMBOL_T;
85};
86
87
89{
90 if( aSel.GetSize() == 1 )
91 {
92 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aSel.Front() );
93
94 if( symbol )
95 return symbol->GetLibSymbolRef() && symbol->GetLibSymbolRef()->HasConversion();
96 }
97
98 return false;
99};
100
101
103{
104 if( aSel.GetSize() == 1 )
105 {
106 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aSel.Front() );
107
108 if( symbol )
109 return symbol->GetLibSymbolRef() && symbol->GetLibSymbolRef()->GetUnitCount() >= 2;
110 }
111
112 return false;
113};
114
115
117{
118 if( aSel.GetSize() == 1 )
119 {
120 SCH_PIN* pin = dynamic_cast<SCH_PIN*>( aSel.Front() );
121
122 if( pin && pin->GetLibPin() )
123 return !pin->GetLibPin()->GetAlternates().empty();
124 }
125
126 return false;
127};
128
129
131{
132 if( aSel.CountType( SCH_MARKER_T ) != 1 )
133 return false;
134
135 return !static_cast<SCH_MARKER*>( aSel.Front() )->IsExcluded();
136};
137
138
140{
141 return aSel.GetSize() > 1 && aSel.OnlyContains( { SCH_SYMBOL_T } );
142};
143
144
146{
147 return aSel.GetSize() >= 1 && aSel.OnlyContains( { SCH_PIN_T } );
148};
149
150
151#define HITTEST_THRESHOLD_PIXELS 5
152
153
155 SELECTION_TOOL( "eeschema.InteractiveSelection" ),
156 m_frame( nullptr ),
157 m_nonModifiedCursor( KICURSOR::ARROW ),
158 m_isSymbolEditor( false ),
159 m_isSymbolViewer( false ),
160 m_unit( 0 ),
161 m_convert( 0 )
162{
164}
165
166
168{
170}
171
172
174
175
176static std::vector<KICAD_T> connectedTypes =
177{
179 SCH_PIN_T,
190};
191
192
194{
195 m_frame = getEditFrame<SCH_BASE_FRAME>();
196
197 SYMBOL_VIEWER_FRAME* symbolViewerFrame = dynamic_cast<SYMBOL_VIEWER_FRAME*>( m_frame );
198 SYMBOL_EDIT_FRAME* symbolEditorFrame = dynamic_cast<SYMBOL_EDIT_FRAME*>( m_frame );
199
200 if( symbolEditorFrame )
201 {
202 m_isSymbolEditor = true;
203 m_unit = symbolEditorFrame->GetUnit();
204 m_convert = symbolEditorFrame->GetConvert();
205 }
206 else
207 {
208 m_isSymbolViewer = symbolViewerFrame != nullptr;
209 }
210
213 auto wireOrBusSelection = E_C::Count( 1 ) && E_C::OnlyTypes( { SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T } );
214 auto connectedSelection = E_C::Count( 1 ) && E_C::OnlyTypes( connectedTypes );
215 auto sheetSelection = E_C::Count( 1 ) && E_C::OnlyTypes( { SCH_SHEET_T } );
216 auto crossProbingSelection = E_C::MoreThan( 0 ) && E_C::HasTypes( { SCH_SYMBOL_T, SCH_PIN_T, SCH_SHEET_T } );
217
218 auto schEditSheetPageNumberCondition =
219 [&] ( const SELECTION& aSel )
220 {
222 return false;
223
224 return E_C::LessThan( 2 )( aSel ) && E_C::OnlyTypes( { SCH_SHEET_T } )( aSel );
225 };
226
227 auto schEditCondition =
228 [this] ( const SELECTION& aSel )
229 {
231 };
232
233 auto belowRootSheetCondition =
234 [&]( const SELECTION& aSel )
235 {
236 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
237
238 return editFrame
239 && editFrame->GetCurrentSheet().Last() != &editFrame->Schematic().Root();
240 };
241
242 auto haveHighlight =
243 [&]( const SELECTION& sel )
244 {
245 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
246
247 return editFrame && !editFrame->GetHighlightedConnection().IsEmpty();
248 };
249
250 auto haveSymbol =
251 [&]( const SELECTION& sel )
252 {
253 return m_isSymbolEditor &&
254 static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->GetCurSymbol();
255 };
256
257 auto symbolDisplayNameIsEditable =
258 [&]( const SELECTION& sel )
259 {
260 if ( !m_isSymbolEditor )
261 return false;
262
263 SYMBOL_EDIT_FRAME* symbEditorFrame = dynamic_cast<SYMBOL_EDIT_FRAME*>( m_frame );
264
265 return symbEditorFrame
266 && symbEditorFrame->GetCurSymbol()
267 && symbEditorFrame->GetCurSymbol()->IsMulti()
268 && symbEditorFrame->IsSymbolEditable()
269 && !symbEditorFrame->IsSymbolAlias();
270 };
271
272 auto& menu = m_menu.GetMenu();
273
274 menu.AddItem( EE_ACTIONS::clearHighlight, haveHighlight && EE_CONDITIONS::Idle, 1 );
275 menu.AddSeparator( haveHighlight && EE_CONDITIONS::Idle, 1 );
276
277 menu.AddItem( EE_ACTIONS::enterSheet, sheetSelection && EE_CONDITIONS::Idle, 2 );
278 menu.AddItem( EE_ACTIONS::selectOnPCB, crossProbingSelection && EE_CONDITIONS::Idle, 2 );
279 menu.AddItem( EE_ACTIONS::leaveSheet, belowRootSheetCondition, 2 );
280
281 menu.AddSeparator( 100 );
282 menu.AddItem( EE_ACTIONS::drawWire, schEditCondition && EE_CONDITIONS::Empty, 100 );
283 menu.AddItem( EE_ACTIONS::drawBus, schEditCondition && EE_CONDITIONS::Empty, 100 );
284
285 menu.AddSeparator( 100 );
287
288 menu.AddSeparator( 100 );
290
291 menu.AddSeparator( 200 );
292 menu.AddItem( EE_ACTIONS::selectConnection, connectedSelection && EE_CONDITIONS::Idle, 250 );
293 menu.AddItem( EE_ACTIONS::placeJunction, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
294 menu.AddItem( EE_ACTIONS::placeLabel, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
295 menu.AddItem( EE_ACTIONS::placeClassLabel, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
296 menu.AddItem( EE_ACTIONS::placeGlobalLabel, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
297 menu.AddItem( EE_ACTIONS::placeHierLabel, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
298 menu.AddItem( EE_ACTIONS::breakWire, linesSelection && EE_CONDITIONS::Idle, 250 );
299 menu.AddItem( EE_ACTIONS::slice, linesSelection && EE_CONDITIONS::Idle, 250 );
300 menu.AddItem( EE_ACTIONS::importSheetPin, sheetSelection && EE_CONDITIONS::Idle, 250 );
301 menu.AddItem( EE_ACTIONS::assignNetclass, connectedSelection && EE_CONDITIONS::Idle, 250 );
302 menu.AddItem( EE_ACTIONS::editPageNumber, schEditSheetPageNumberCondition, 250 );
303
304 menu.AddSeparator( 400 );
305 menu.AddItem( EE_ACTIONS::symbolProperties, haveSymbol && EE_CONDITIONS::Empty, 400 );
306 menu.AddItem( EE_ACTIONS::pinTable, haveSymbol && EE_CONDITIONS::Empty, 400 );
307 menu.AddItem( EE_ACTIONS::setUnitDisplayName,
308 haveSymbol && symbolDisplayNameIsEditable && EE_CONDITIONS::Empty, 400 );
309
310 menu.AddSeparator( 1000 );
312
313 m_disambiguateTimer.SetOwner( this );
314 Connect( wxEVT_TIMER, wxTimerEventHandler( EE_SELECTION_TOOL::onDisambiguationExpire ), nullptr, this );
315
316 return true;
317}
318
319
321{
322 m_frame = getEditFrame<SCH_BASE_FRAME>();
323
324 if( aReason != TOOL_BASE::REDRAW )
325 {
326 // Remove pointers to the selected items from containers without changing their
327 // properties (as they are already deleted while a new sheet is loaded)
329 }
330
331 if( aReason == TOOL_BASE::MODEL_RELOAD || aReason == TOOL_BASE::SUPERMODEL_RELOAD )
332 {
333 getView()->GetPainter()->GetSettings()->SetHighlight( false );
334
335 SYMBOL_EDIT_FRAME* symbolEditFrame = dynamic_cast<SYMBOL_EDIT_FRAME*>( m_frame );
336 SYMBOL_VIEWER_FRAME* symbolViewerFrame = dynamic_cast<SYMBOL_VIEWER_FRAME*>( m_frame );
337
338 if( symbolEditFrame )
339 {
340 m_isSymbolEditor = true;
341 m_unit = symbolEditFrame->GetUnit();
342 m_convert = symbolEditFrame->GetConvert();
343 }
344 else
345 {
346 m_isSymbolViewer = symbolViewerFrame != nullptr;
347 }
348 }
349
350 // Reinsert the VIEW_GROUP, in case it was removed from the VIEW
352 getView()->Add( &m_selection );
353}
354
355
357{
358 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
359
360 KIID lastRolloverItem = niluuid;
362
363 // Main loop: keep receiving events
364 while( TOOL_EVENT* evt = Wait() )
365 {
366 bool selCancelled = false;
367 bool displayWireCursor = false;
368 bool displayBusCursor = false;
369 bool displayLineCursor = false;
370 KIID rolloverItem = lastRolloverItem;
371
372 // on left click, a selection is made, depending on modifiers ALT, SHIFT, CTRL:
373 setModifiersState( evt->Modifier( MD_SHIFT ), evt->Modifier( MD_CTRL ),
374 evt->Modifier( MD_ALT ) );
375
376 MOUSE_DRAG_ACTION drag_action = m_frame->GetDragAction();
377
378 if( evt->IsMouseDown( BUT_LEFT ) )
379 {
380 if( !m_frame->ToolStackIsEmpty() )
381 {
382 // Avoid triggering when running under other tools
383 }
386 {
387 // Distinguish point editor from selection modification by checking modifiers
388 if( hasModifier() )
389 {
391 m_disambiguateTimer.StartOnce( ADVANCED_CFG::GetCfg().m_DisambiguationMenuDelay );
392 }
393 }
394 else
395 {
397 m_disambiguateTimer.StartOnce( ADVANCED_CFG::GetCfg().m_DisambiguationMenuDelay );
398 }
399 }
400 // Single click? Select single object
401 else if( evt->IsClick( BUT_LEFT ) )
402 {
403 // If the timer has stopped, then we have already run the disambiguate routine
404 // and we don't want to register an extra click here
405 if( !m_disambiguateTimer.IsRunning() )
406 {
407 evt->SetPassEvent();
408 continue;
409 }
410
411 m_disambiguateTimer.Stop();
412
413 if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
414 schframe->FocusOnItem( nullptr );
415
416 // Collect items at the clicked location (doesn't select them yet)
417 EE_COLLECTOR collector;
418 CollectHits( collector, evt->Position() );
419 narrowSelection( collector, evt->Position(), false );
420
421 if( collector.GetCount() == 1 && !m_isSymbolEditor && !hasModifier() )
422 {
423 OPT_TOOL_EVENT autostart = autostartEvent( evt, grid, collector[0] );
424
425 if( autostart )
426 {
428
429 params->layer = autostart->Parameter<const DRAW_SEGMENT_EVENT_PARAMS*>()->layer;
430 params->quitOnDraw = true;
431 params->sourceSegment = dynamic_cast<SCH_LINE*>( collector[0] );
432
433 autostart->SetParameter<const DRAW_SEGMENT_EVENT_PARAMS*>( params );
434 m_toolMgr->ProcessEvent( *autostart );
435
436 selCancelled = true;
437 }
438 else if( collector[0]->IsHypertext() )
439 {
440 collector[ 0 ]->DoHypertextAction( m_frame );
441 selCancelled = true;
442 }
443 else if( collector[0]->IsBrightened() )
444 {
445 if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
446 {
447 NET_NAVIGATOR_ITEM_DATA itemData( schframe->GetCurrentSheet(),
448 collector[0] );
449
450 schframe->SelectNetNavigatorItem( &itemData );
451 }
452 }
453 }
454
455 if( !selCancelled )
456 {
457 selectPoint( collector, evt->Position(), nullptr, nullptr, m_additive,
459 m_selection.SetIsHover( false );
460 }
461 }
462 else if( evt->IsClick( BUT_RIGHT ) )
463 {
464 m_disambiguateTimer.Stop();
465
466 // right click? if there is any object - show the context menu
467 if( m_selection.Empty() )
468 {
470 SelectPoint( evt->Position(), { SCH_LOCATE_ANY_T }, nullptr, &selCancelled );
471 m_selection.SetIsHover( true );
472 }
473 // If the cursor has moved off the bounding box of the selection by more than
474 // a grid square, check to see if there is another item available for selection
475 // under the cursor. If there is, the user likely meant to get the context menu
476 // for that item. If there is no new item, then keep the original selection and
477 // show the context menu for it.
478 else if( !m_selection.GetBoundingBox().Inflate( grid.GetGrid().x, grid.GetGrid().y )
479 .Contains( evt->Position() ) )
480 {
481 EE_COLLECTOR collector;
482
483 if( CollectHits( collector, evt->Position(), { SCH_LOCATE_ANY_T } ) )
484 {
486
487 SelectPoint( evt->Position(), { SCH_LOCATE_ANY_T }, nullptr, &selCancelled );
488 m_selection.SetIsHover( true );
489 }
490 }
491
492 if( !selCancelled )
494 }
495 else if( evt->IsDblClick( BUT_LEFT ) )
496 {
497 m_disambiguateTimer.Stop();
498
499 // double click? Display the properties window
500 if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
501 schframe->FocusOnItem( nullptr );
502
503 if( m_selection.Empty() )
504 SelectPoint( evt->Position() );
505
506 EDA_ITEM* item = m_selection.Front();
507
508 if( item && item->Type() == SCH_SHEET_T )
510 else
512 }
513 else if( evt->IsDblClick( BUT_MIDDLE ) )
514 {
515 m_disambiguateTimer.Stop();
516
517 // Middle double click? Do zoom to fit or zoom to objects
518 if( evt->Modifier( MD_CTRL ) ) // Is CTRL key down?
520 else
522 }
523 else if( evt->IsDrag( BUT_LEFT ) )
524 {
525 m_disambiguateTimer.Stop();
526
527 // Is another tool already moving a new object? Don't allow a drag start
528 if( !m_selection.Empty() && m_selection[0]->HasFlag( IS_NEW | IS_MOVING ) )
529 {
530 evt->SetPassEvent();
531 continue;
532 }
533
534 // drag with LMB? Select multiple objects (or at least draw a selection box) or
535 // drag them
536 if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
537 schframe->FocusOnItem( nullptr );
538
539 if( hasModifier() || drag_action == MOUSE_DRAG_ACTION::SELECT )
540 {
542 }
543 else if( m_selection.Empty() && drag_action != MOUSE_DRAG_ACTION::DRAG_ANY )
544 {
546 }
547 else
548 {
549 if( m_isSymbolEditor )
550 {
551 if( static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->IsSymbolAlias() )
552 {
554 }
555 else
556 {
560 LIB_PIN_T,
561 LIB_FIELD_T } );
562 }
563 }
564 else
565 {
567 }
568
569 // Check if dragging has started within any of selected items bounding box
570 if( selectionContains( evt->DragOrigin() ) )
571 {
572 // drag_is_move option exists only in schematic editor, not in symbol editor
573 // (m_frame->eeconfig() returns nullptr in Symbol Editor)
576 else
578 }
579 else
580 {
581 // No -> drag a selection box
583 }
584 }
585 }
586 else if( evt->IsMouseDown( BUT_AUX1 ) )
587 {
589 }
590 else if( evt->IsMouseDown( BUT_AUX2 ) )
591 {
593 }
594 else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CHOICE_MENU_CHOICE )
595 {
596 m_disambiguateTimer.Stop();
597
598 // context sub-menu selection? Handle unit selection or bus unfolding
599 if( *evt->GetCommandId() >= ID_POPUP_SCH_SELECT_UNIT
600 && *evt->GetCommandId() <= ID_POPUP_SCH_SELECT_UNIT_END )
601 {
602 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( m_selection.Front() );
603 int unit = *evt->GetCommandId() - ID_POPUP_SCH_SELECT_UNIT;
604
605 if( symbol )
606 static_cast<SCH_EDIT_FRAME*>( m_frame )->SelectUnit( symbol, unit );
607 }
608 else if( *evt->GetCommandId() >= ID_POPUP_SCH_ALT_PIN_FUNCTION
609 && *evt->GetCommandId() <= ID_POPUP_SCH_ALT_PIN_FUNCTION_END )
610 {
611 SCH_PIN* pin = dynamic_cast<SCH_PIN*>( m_selection.Front() );
612 wxString alt = *evt->Parameter<wxString*>();
613
614 if( pin )
615 static_cast<SCH_EDIT_FRAME*>( m_frame )->SetAltPinFunction( pin, alt );
616 }
617 else if( *evt->GetCommandId() >= ID_POPUP_SCH_PIN_TRICKS_START
618 && *evt->GetCommandId() <= ID_POPUP_SCH_PIN_TRICKS_END )
619 {
621 return 0;
622
623 // Keep track of new items so we make them the new selection at the end
624 EDA_ITEMS newItems;
625 SCH_COMMIT commit( static_cast<SCH_EDIT_FRAME*>( m_frame ) );
626
627 if( *evt->GetCommandId() == ID_POPUP_SCH_PIN_TRICKS_NO_CONNECT )
628 {
629 for( EDA_ITEM* item : m_selection )
630 {
631 SCH_PIN* pin = static_cast<SCH_PIN*>( item );
632 SCH_NO_CONNECT* nc = new SCH_NO_CONNECT( pin->GetPosition() );
633 commit.Add( nc, m_frame->GetScreen() );
634 newItems.push_back( nc );
635 }
636
637 commit.Push( wxS( "No Connect Pins" ) );
639 }
640 else if( *evt->GetCommandId() == ID_POPUP_SCH_PIN_TRICKS_WIRE )
641 {
642 VECTOR2I wireGrid = grid.GetGridSize( GRID_HELPER_GRIDS::GRID_WIRES );
643
644 for( EDA_ITEM* item : m_selection )
645 {
646 SCH_PIN* pin = static_cast<SCH_PIN*>( item );
647 SCH_LINE* wire = new SCH_LINE( pin->GetPosition(), LAYER_WIRE );
648
649 // Add some length to the wire as nothing in our code base handles
650 // 0 length wires very well, least of all the ortho drag algorithm
651 VECTOR2I stub;
652
653 switch( pin->GetOrientation() )
654 {
655 case PIN_ORIENTATION::PIN_LEFT: stub = VECTOR2I( 1 * wireGrid.x, 0 ); break;
656 case PIN_ORIENTATION::PIN_RIGHT: stub = VECTOR2I( -1 * wireGrid.x, 0 ); break;
657 case PIN_ORIENTATION::PIN_UP: stub = VECTOR2I( 0, 1 * wireGrid.y ); break;
658 case PIN_ORIENTATION::PIN_DOWN: stub = VECTOR2I( 0, -1 * wireGrid.y ); break;
659 }
660
661 wire->SetEndPoint( pin->GetPosition() + stub );
662
664 commit.Added( wire, m_frame->GetScreen() );
665 newItems.push_back( wire );
666 }
667
669 AddItemsToSel( &newItems );
670
671 // Select only the ends so we can immediately start dragging them
672 for( EDA_ITEM* item : newItems )
673 static_cast<SCH_LINE*>( item )->SetFlags( ENDPOINT );
674
675 // Put the mouse on the nearest point of the first wire
676 SCH_LINE* first = static_cast<SCH_LINE*>( newItems[0] );
678 getViewControls()->WarpMouseCursor( getViewControls()->GetCursorPosition(),
679 true );
680
681 // Start the drag tool, canceling will remove the wires
682 if( m_toolMgr->RunSynchronousAction( EE_ACTIONS::drag, &commit, false ) )
683 commit.Push( wxS( "Wire Pins" ) );
684 else
685 commit.Revert();
686 }
687 else
688 {
689 // For every pin in the selection, add a label according to menu item
690 // selected by the user
691 for( EDA_ITEM* item : m_selection )
692 {
693 SCH_PIN* pin = static_cast<SCH_PIN*>( item );
694 SCH_LABEL_BASE* label = nullptr;
695
696 switch( *evt->GetCommandId() )
697 {
699 label = new SCH_LABEL( pin->GetPosition(), pin->GetShownName() );
700 break;
702 label = new SCH_HIERLABEL( pin->GetPosition(), pin->GetShownName() );
703 break;
705 label = new SCH_GLOBALLABEL( pin->GetPosition(), pin->GetShownName() );
706 break;
707 default: continue;
708 }
709
710 switch( pin->GetOrientation() )
711 {
712 case PIN_ORIENTATION::PIN_LEFT:
714 break;
715 case PIN_ORIENTATION::PIN_RIGHT:
717 break;
718 case PIN_ORIENTATION::PIN_UP:
720 break;
721 case PIN_ORIENTATION::PIN_DOWN:
723 break;
724 }
725
726 switch( pin->GetType() )
727 {
728 case ELECTRICAL_PINTYPE::PT_BIDI:
729 label->SetShape( LABEL_FLAG_SHAPE::L_BIDI );
730 break;
731 case ELECTRICAL_PINTYPE::PT_INPUT:
732 label->SetShape( LABEL_FLAG_SHAPE::L_INPUT );
733 break;
734 case ELECTRICAL_PINTYPE::PT_OUTPUT:
735 label->SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
736 break;
737 case ELECTRICAL_PINTYPE::PT_TRISTATE:
738 label->SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
739 break;
740 case ELECTRICAL_PINTYPE::PT_UNSPECIFIED:
741 label->SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
742 break;
743 default:
744 label->SetShape( LABEL_FLAG_SHAPE::L_INPUT );
745 }
746
747 commit.Add( label, m_frame->GetScreen() );
748 newItems.push_back( label );
749 }
750
751 commit.Push( wxS( "Label Pins" ) );
752
753 // Many users will want to drag these items to wire off of the pins, so pre-select them
755 AddItemsToSel( &newItems );
756 }
757 }
758 else if( *evt->GetCommandId() >= ID_POPUP_SCH_UNFOLD_BUS
759 && *evt->GetCommandId() <= ID_POPUP_SCH_UNFOLD_BUS_END )
760 {
761 wxString* net = new wxString( *evt->Parameter<wxString*>() );
762 m_toolMgr->RunAction<wxString*>( EE_ACTIONS::unfoldBus, net );
763 }
764 }
765 else if( evt->IsCancelInteractive() )
766 {
767 m_disambiguateTimer.Stop();
768
769 // We didn't set these, but we have reports that they leak out of some other tools,
770 // so we clear them here.
771 getViewControls()->SetAutoPan( false );
772 getViewControls()->CaptureCursor( false );
773
774 if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
775 schframe->FocusOnItem( nullptr );
776
777 if( !GetSelection().Empty() )
778 {
780 }
781 else if( evt->FirstResponder() == this && evt->GetCommandId() == (int) WXK_ESCAPE )
782 {
784
786 editor->ClearHighlight( *evt );
787 }
788 }
789 else if( evt->Action() == TA_UNDO_REDO_PRE )
790 {
791 if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
792 schframe->FocusOnItem( nullptr );
793
795 }
796 else if( evt->IsMotion() && !m_isSymbolEditor && evt->FirstResponder() == this )
797 {
798 // Update cursor and rollover item
799 rolloverItem = niluuid;
800 EE_COLLECTOR collector;
801
803
804 if( CollectHits( collector, evt->Position() ) )
805 {
806 narrowSelection( collector, evt->Position(), false );
807
808 if( collector.GetCount() == 1 && !hasModifier() )
809 {
810 OPT_TOOL_EVENT autostartEvt = autostartEvent( evt, grid, collector[0] );
811
812 if( autostartEvt )
813 {
814 if( autostartEvt->Matches( EE_ACTIONS::drawBus.MakeEvent() ) )
815 displayBusCursor = true;
816 else if( autostartEvt->Matches( EE_ACTIONS::drawWire.MakeEvent() ) )
817 displayWireCursor = true;
818 else if( autostartEvt->Matches( EE_ACTIONS::drawLines.MakeEvent() ) )
819 displayLineCursor = true;
820 }
821 else if( collector[0]->IsHypertext() && !collector[0]->IsSelected() )
822 {
823 rolloverItem = collector[0]->m_Uuid;
824 }
825 }
826 }
827 }
828 else
829 {
830 evt->SetPassEvent();
831 }
832
833 if( rolloverItem != lastRolloverItem )
834 {
835 if( EDA_ITEM* item = m_frame->GetItem( lastRolloverItem ) )
836 {
837 item->ClearFlags( IS_ROLLOVER );
838 lastRolloverItem = niluuid;
839
840 if( item->Type() == SCH_FIELD_T )
841 m_frame->GetCanvas()->GetView()->Update( item->GetParent() );
842 else
843 m_frame->GetCanvas()->GetView()->Update( item );
844 }
845 }
846
847 if( rolloverItem != niluuid )
848 {
849 EDA_ITEM* item = m_frame->GetItem( rolloverItem );
850
851 if( item && !( item->GetFlags() & IS_ROLLOVER ) )
852 {
853 item->SetFlags( IS_ROLLOVER );
854 lastRolloverItem = rolloverItem;
855
856 if( item->Type() == SCH_FIELD_T )
857 m_frame->GetCanvas()->GetView()->Update( item->GetParent() );
858 else
859 m_frame->GetCanvas()->GetView()->Update( item );
860 }
861 }
862
864 {
865 if( displayWireCursor )
866 {
867 m_nonModifiedCursor = KICURSOR::LINE_WIRE_ADD;
868 }
869 else if( displayBusCursor )
870 {
871 m_nonModifiedCursor = KICURSOR::LINE_BUS;
872 }
873 else if( displayLineCursor )
874 {
875 m_nonModifiedCursor = KICURSOR::LINE_GRAPHIC;
876 }
877 else if( rolloverItem != niluuid )
878 {
879 m_nonModifiedCursor = KICURSOR::HAND;
880 }
881 else if( !m_selection.Empty()
882 && drag_action == MOUSE_DRAG_ACTION::DRAG_SELECTED
883 && evt->HasPosition()
884 && selectionContains( evt->Position() ) ) //move/drag option prediction
885 {
886 m_nonModifiedCursor = KICURSOR::MOVING;
887 }
888 else
889 {
890 m_nonModifiedCursor = KICURSOR::ARROW;
891 }
892 }
893 }
894
895 m_disambiguateTimer.Stop();
896
897 // Shutting down; clear the selection
898 m_selection.Clear();
899
900 return 0;
901}
902
903
905 SCH_ITEM* aItem )
906{
907 VECTOR2I pos = aGrid.BestSnapAnchor( aEvent->Position(), aGrid.GetItemGrid( aItem ) );
908
911 && aItem->IsPointClickableAnchor( pos ) )
912 {
914
915 if( aItem->Type() == SCH_BUS_BUS_ENTRY_T )
916 {
918 }
919 else if( aItem->Type() == SCH_BUS_WIRE_ENTRY_T )
920 {
921 SCH_BUS_WIRE_ENTRY* busEntry = static_cast<SCH_BUS_WIRE_ENTRY*>( aItem );
922
923 if( !busEntry->m_connected_bus_item )
925 }
926 else if( aItem->Type() == SCH_LINE_T )
927 {
928 SCH_LINE* line = static_cast<SCH_LINE*>( aItem );
929
930 if( line->IsBus() )
931 newEvt = EE_ACTIONS::drawBus.MakeEvent();
932 else if( line->IsGraphicLine() )
933 newEvt = EE_ACTIONS::drawLines.MakeEvent();
934 }
935 else if( aItem->Type() == SCH_LABEL_T || aItem->Type() == SCH_HIER_LABEL_T
936 || aItem->Type() == SCH_SHEET_PIN_T )
937 {
938 SCH_LABEL_BASE* label = static_cast<SCH_LABEL_BASE*>( aItem );
939 SCH_CONNECTION possibleConnection( label->Schematic()->ConnectionGraph() );
940 possibleConnection.ConfigureFromLabel( label->GetText() );
941
942 if( possibleConnection.IsBus() )
944 }
945
946 newEvt->SetMousePosition( pos );
947 newEvt->SetHasPosition( true );
948 newEvt->SetForceImmediate( true );
949
950 getViewControls()->ForceCursorPosition( true, pos );
951
952 return newEvt;
953 }
954
955 return OPT_TOOL_EVENT();
956}
957
958
960{
961 wxMouseState keyboardState = wxGetMouseState();
962
963 setModifiersState( keyboardState.ShiftDown(), keyboardState.ControlDown(),
964 keyboardState.AltDown() );
965
966 m_skip_heuristics = true;
969 m_skip_heuristics = false;
970
971 return 0;
972}
973
974
975void EE_SELECTION_TOOL::OnIdle( wxIdleEvent& aEvent )
976{
978 {
979 wxMouseState keyboardState = wxGetMouseState();
980
981 setModifiersState( keyboardState.ShiftDown(), keyboardState.ControlDown(),
982 keyboardState.AltDown() );
983
984 if( m_additive )
985 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ADD );
986 else if( m_subtractive )
987 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::SUBTRACT );
988 else if( m_exclusive_or )
989 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::XOR );
990 else
992 }
993}
994
995
997{
998 return m_selection;
999}
1000
1001
1003 const std::vector<KICAD_T>& aScanTypes )
1004{
1005 int pixelThreshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
1006 int gridThreshold = KiROUND( getView()->GetGAL()->GetGridSize().EuclideanNorm() / 2 );
1007 aCollector.m_Threshold = std::max( pixelThreshold, gridThreshold );
1009
1010 if( m_isSymbolEditor )
1011 {
1012 LIB_SYMBOL* symbol = static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->GetCurSymbol();
1013
1014 if( !symbol )
1015 return false;
1016
1017 aCollector.Collect( symbol->GetDrawItems(), aScanTypes, aWhere, m_unit, m_convert );
1018 }
1019 else
1020 {
1021 aCollector.Collect( m_frame->GetScreen(), aScanTypes, aWhere, m_unit, m_convert );
1022
1024 {
1025 int originalCount = aCollector.GetCount();
1026
1027 for( int ii = 0; ii < originalCount; ++ii )
1028 {
1029 if( aCollector[ii]->Type() == SCH_PIN_T )
1030 {
1031 SCH_PIN* pin = static_cast<SCH_PIN*>( aCollector[ii] );
1032
1033 if( !aCollector.HasItem( pin->GetParentSymbol() ) )
1034 aCollector.Append( pin->GetParentSymbol() );
1035 }
1036 }
1037 }
1038 }
1039
1040 return aCollector.GetCount() > 0;
1041}
1042
1043
1045 bool aCheckLocked, bool aSelectedOnly )
1046{
1047 for( int i = collector.GetCount() - 1; i >= 0; --i )
1048 {
1049 if( !Selectable( collector[i], &aWhere ) )
1050 {
1051 collector.Remove( i );
1052 continue;
1053 }
1054
1055 if( aCheckLocked && collector[i]->IsLocked() )
1056 {
1057 collector.Remove( i );
1058 continue;
1059 }
1060
1061 if( aSelectedOnly && !collector[i]->IsSelected() )
1062 {
1063 collector.Remove( i );
1064 continue;
1065 }
1066 }
1067
1068 // Apply some ugly heuristics to avoid disambiguation menus whenever possible
1069 if( collector.GetCount() > 1 && !m_skip_heuristics )
1070 GuessSelectionCandidates( collector, aWhere );
1071}
1072
1073
1075 EDA_ITEM** aItem, bool* aSelectionCancelledFlag, bool aAdd,
1076 bool aSubtract, bool aExclusiveOr )
1077{
1079
1080 // If still more than one item we're going to have to ask the user.
1081 if( aCollector.GetCount() > 1 )
1082 {
1083 // Try to call selectionMenu via RunAction() to avoid event-loop contention
1084 // But it we cannot handle the event, then we don't have an active tool loop, so
1085 // handle it directly.
1086 if( !m_toolMgr->RunAction<COLLECTOR*>( EE_ACTIONS::selectionMenu, &aCollector ) )
1087 {
1088 if( !doSelectionMenu( &aCollector ) )
1089 aCollector.m_MenuCancelled = true;
1090 }
1091
1092 if( aCollector.m_MenuCancelled )
1093 {
1094 if( aSelectionCancelledFlag )
1095 *aSelectionCancelledFlag = true;
1096
1097 return false;
1098 }
1099 }
1100
1101 if( !aAdd && !aSubtract && !aExclusiveOr )
1103
1104 int addedCount = 0;
1105 bool anySubtracted = false;
1106
1107 if( aCollector.GetCount() > 0 )
1108 {
1109 for( int i = 0; i < aCollector.GetCount(); ++i )
1110 {
1111 EDA_ITEM_FLAGS flags = 0;
1112 bool isLine = aCollector[i]->Type() == SCH_LINE_T;
1113
1114 // Handle line ends specially
1115 if( isLine )
1116 {
1117 SCH_LINE* line = (SCH_LINE*) aCollector[i];
1118
1119 if( HitTestPoints( line->GetStartPoint(), aWhere, aCollector.m_Threshold ) )
1120 flags = STARTPOINT;
1121 else if( HitTestPoints( line->GetEndPoint(), aWhere, aCollector.m_Threshold ) )
1122 flags = ENDPOINT;
1123 else
1124 flags = STARTPOINT | ENDPOINT;
1125 }
1126
1127 if( aSubtract
1128 || ( aExclusiveOr && aCollector[i]->IsSelected()
1129 && ( !isLine || ( isLine && aCollector[i]->HasFlag( flags ) ) ) ) )
1130 {
1131 aCollector[i]->ClearFlags( flags );
1132
1133 // Need to update end shadows after ctrl-click unselecting one of two selected endpoints
1134 if( isLine )
1135 getView()->Update( aCollector[i] );
1136
1137 if( !aCollector[i]->HasFlag( STARTPOINT ) && !aCollector[i]->HasFlag( ENDPOINT ) )
1138 {
1139 unselect( aCollector[i] );
1140 anySubtracted = true;
1141 }
1142 }
1143 else
1144 {
1145 aCollector[i]->SetFlags( flags );
1146 select( aCollector[i] );
1147 addedCount++;
1148 }
1149 }
1150 }
1151
1152 if( addedCount == 1 )
1153 {
1155
1156 if( aItem && aCollector.GetCount() == 1 )
1157 *aItem = aCollector[0];
1158
1159 return true;
1160 }
1161 else if( addedCount > 1 )
1162 {
1164 return true;
1165 }
1166 else if( anySubtracted )
1167 {
1169 return true;
1170 }
1171
1172 return false;
1173}
1174
1175
1177 const std::vector<KICAD_T>& aScanTypes,
1178 EDA_ITEM** aItem, bool* aSelectionCancelledFlag,
1179 bool aCheckLocked, bool aAdd, bool aSubtract,
1180 bool aExclusiveOr )
1181{
1182 EE_COLLECTOR collector;
1183
1184 if( !CollectHits( collector, aWhere, aScanTypes ) )
1185 return false;
1186
1187 narrowSelection( collector, aWhere, aCheckLocked, aSubtract );
1188
1189 return selectPoint( collector, aWhere, aItem, aSelectionCancelledFlag, aAdd, aSubtract,
1190 aExclusiveOr );
1191}
1192
1193
1195{
1196 m_multiple = true; // Multiple selection mode is active
1197 KIGFX::VIEW* view = getView();
1198
1199 // hold all visible items
1200 std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
1201 std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> sheetPins;
1202
1203 // Filter the view items based on the selection box
1204 BOX2I selectionBox;
1205
1206 selectionBox.SetMaximum();
1207 view->Query( selectionBox, selectedItems ); // Get the list of selected items
1208
1209 // Sheet pins aren't in the view; add them by hand
1210 for( KIGFX::VIEW::LAYER_ITEM_PAIR& pair : selectedItems )
1211 {
1212 SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( pair.first );
1213
1214 if( sheet )
1215 {
1216 int layer = pair.second;
1217
1218 for( SCH_SHEET_PIN* pin : sheet->GetPins() )
1219 sheetPins.emplace_back( KIGFX::VIEW::LAYER_ITEM_PAIR( pin, layer ) );
1220 }
1221 }
1222
1223 selectedItems.insert( selectedItems.end(), sheetPins.begin(), sheetPins.end() );
1224
1225 for( const std::pair<KIGFX::VIEW_ITEM*, int>& item_pair : selectedItems )
1226 {
1227 if( EDA_ITEM* item = dynamic_cast<EDA_ITEM*>( item_pair.first ) )
1228 {
1229 if( Selectable( item ) )
1230 {
1231 if( item->Type() == SCH_LINE_T )
1232 item->SetFlags( STARTPOINT | ENDPOINT );
1233
1234 select( item );
1235 }
1236 }
1237 }
1238
1239 m_multiple = false;
1240
1242
1243 return 0;
1244}
1245
1247{
1248 m_multiple = true; // Multiple selection mode is active
1249 KIGFX::VIEW* view = getView();
1250
1251 // hold all visible items
1252 std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
1253
1254 // Filter the view items based on the selection box
1255 BOX2I selectionBox;
1256
1257 selectionBox.SetMaximum();
1258 view->Query( selectionBox, selectedItems ); // Get the list of selected items
1259
1260 for( KIGFX::VIEW::LAYER_ITEM_PAIR& pair : selectedItems )
1261 {
1262 SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( pair.first );
1263
1264 if( sheet )
1265 {
1266 for( SCH_SHEET_PIN* pin : sheet->GetPins() )
1267 {
1268 EDA_ITEM* item = dynamic_cast<EDA_ITEM*>( pin );
1269
1270 if( item && Selectable( item ) )
1271 unselect( item );
1272 }
1273 }
1274
1275 if( EDA_ITEM* item = dynamic_cast<EDA_ITEM*>( pair.first ) )
1276 {
1277 if( Selectable( item ) )
1278 unselect( item );
1279 }
1280 }
1281
1282 m_multiple = false;
1283
1285
1286 return 0;
1287}
1288
1289
1291{
1292 // Prefer exact hits to sloppy ones
1293 std::set<EDA_ITEM*> exactHits;
1294
1295 for( int i = collector.GetCount() - 1; i >= 0; --i )
1296 {
1297 EDA_ITEM* item = collector[ i ];
1298 SCH_LINE* line = dynamic_cast<SCH_LINE*>( item );
1299 LIB_SHAPE* shape = dynamic_cast<LIB_SHAPE*>( item );
1300 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item );
1301
1302 // Lines are hard to hit. Give them a bit more slop to still be considered "exact".
1303
1304 if( line || ( shape && shape->GetShape() == SHAPE_T::POLY )
1305 || ( shape && shape->GetShape() == SHAPE_T::ARC ) )
1306 {
1307 int pixelThreshold = KiROUND( getView()->ToWorld( 6 ) );
1308
1309 if( item->HitTest( aPos, pixelThreshold ) )
1310 exactHits.insert( item );
1311 }
1312 else if( symbol && m_frame->eeconfig()->m_Selection.select_pin_selects_symbol )
1313 {
1314 if( symbol->GetBodyAndPinsBoundingBox().Contains( aPos ) )
1315 exactHits.insert( item );
1316 }
1317 else
1318 {
1319 if( item->HitTest( aPos, 0 ) )
1320 exactHits.insert( item );
1321 }
1322 }
1323
1324 if( exactHits.size() > 0 && exactHits.size() < (unsigned) collector.GetCount() )
1325 {
1326 for( int i = collector.GetCount() - 1; i >= 0; --i )
1327 {
1328 EDA_ITEM* item = collector[ i ];
1329
1330 if( !exactHits.count( item ) )
1331 collector.Transfer( item );
1332 }
1333 }
1334
1335 // Find the closest item. (Note that at this point all hits are either exact or non-exact.)
1336 VECTOR2I pos( aPos );
1337 SEG poss( m_isSymbolEditor ? mapCoords( pos ) : pos,
1338 m_isSymbolEditor ? mapCoords( pos ) : pos );
1339 EDA_ITEM* closest = nullptr;
1340 int closestDist = INT_MAX / 2;
1341
1342 for( EDA_ITEM* item : collector )
1343 {
1344 BOX2I bbox = item->GetBoundingBox();
1345 int dist = INT_MAX / 2;
1346
1347 if( exactHits.count( item ) )
1348 {
1349 if( item->Type() == SCH_PIN_T || item->Type() == SCH_JUNCTION_T )
1350 {
1351 closest = item;
1352 break;
1353 }
1354
1355 SCH_LINE* line = dynamic_cast<SCH_LINE*>( item );
1356 SCH_FIELD* field = dynamic_cast<SCH_FIELD*>( item );
1357 EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item );
1358 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item );
1359
1360 if( line )
1361 {
1362 dist = KiROUND( DistanceLinePoint( line->GetStartPoint(), line->GetEndPoint(), pos ) );
1363 }
1364 else if( field )
1365 {
1366 BOX2I box = field->GetBoundingBox();
1367 EDA_ANGLE orient = field->GetTextAngle();
1368
1369 if( field->GetParent() && field->GetParent()->Type() == SCH_SYMBOL_T )
1370 {
1371 if( static_cast<SCH_SYMBOL*>( field->GetParent() )->GetTransform().y1 )
1372 {
1373 if( orient.IsHorizontal() )
1374 orient = ANGLE_VERTICAL;
1375 else
1376 orient = ANGLE_HORIZONTAL;
1377 }
1378 }
1379
1380 field->GetEffectiveTextShape( false, box, orient )->Collide( poss, INT_MAX / 2,
1381 &dist );
1382 }
1383 else if( text )
1384 {
1385 text->GetEffectiveTextShape( false )->Collide( poss, INT_MAX / 2, &dist );
1386 }
1387 else if( symbol )
1388 {
1389 bbox = symbol->GetBodyBoundingBox();
1390
1391 SHAPE_RECT rect( bbox.GetPosition(), bbox.GetWidth(), bbox.GetHeight() );
1392
1393 if( bbox.Contains( pos ) )
1394 dist = KiROUND( EuclideanNorm( bbox.GetCenter() - pos ) );
1395 else
1396 rect.Collide( poss, closestDist, &dist );
1397 }
1398 else
1399 {
1400 dist = KiROUND( EuclideanNorm( bbox.GetCenter() - pos ) );
1401 }
1402 }
1403 else
1404 {
1405 SHAPE_RECT rect( bbox.GetPosition(), bbox.GetWidth(), bbox.GetHeight() );
1406 rect.Collide( poss, collector.m_Threshold, &dist );
1407 }
1408
1409 if( dist == closestDist )
1410 {
1411 if( item->GetParent() == closest )
1412 closest = item;
1413 }
1414 else if( dist < closestDist )
1415 {
1416 closestDist = dist;
1417 closest = item;
1418 }
1419 }
1420
1421 // Construct a tight box (1/2 height and width) around the center of the closest item.
1422 // All items which exist at least partly outside this box have sufficient other areas
1423 // for selection and can be dropped.
1424 if( closest ) // Don't try and get a tight bbox if nothing is near the mouse pointer
1425 {
1426 BOX2I tightBox = closest->GetBoundingBox();
1427 tightBox.Inflate( -tightBox.GetWidth() / 4, -tightBox.GetHeight() / 4 );
1428
1429 for( int i = collector.GetCount() - 1; i >= 0; --i )
1430 {
1431 EDA_ITEM* item = collector[i];
1432
1433 if( item == closest )
1434 continue;
1435
1436 if( !item->HitTest( tightBox, true ) )
1437 collector.Transfer( item );
1438 }
1439 }
1440}
1441
1442
1443EE_SELECTION& EE_SELECTION_TOOL::RequestSelection( const std::vector<KICAD_T>& aScanTypes )
1444{
1445 if( m_selection.Empty() )
1446 {
1447 VECTOR2D cursorPos = getViewControls()->GetCursorPosition( true );
1448
1450 SelectPoint( cursorPos, aScanTypes );
1451 m_selection.SetIsHover( true );
1453 }
1454 else // Trim an existing selection by aFilterList
1455 {
1456 bool isMoving = false;
1457 bool anyUnselected = false;
1458
1459 for( int i = (int) m_selection.GetSize() - 1; i >= 0; --i )
1460 {
1461 EDA_ITEM* item = (EDA_ITEM*) m_selection.GetItem( i );
1462 isMoving |= static_cast<SCH_ITEM*>( item )->IsMoving();
1463
1464 if( !item->IsType( aScanTypes ) )
1465 {
1466 unselect( item );
1467 anyUnselected = true;
1468 }
1469 }
1470
1471 if( anyUnselected )
1473
1474 if( !isMoving )
1476 }
1477
1478 return m_selection;
1479}
1480
1481
1483{
1484 VECTOR2I refP( 0, 0 );
1485
1486 if( m_selection.Size() > 0 )
1487 {
1488 if( m_isSymbolEditor )
1489 refP = static_cast<LIB_ITEM*>( m_selection.GetTopLeftItem() )->GetPosition();
1490 else
1491 refP = static_cast<SCH_ITEM*>( m_selection.GetTopLeftItem() )->GetPosition();
1492 }
1493
1495}
1496
1497
1498// Some navigation actions are allowed in selectMultiple
1508 &ACTIONS::zoomFitObjects, nullptr };
1509
1510
1512{
1513 bool cancelled = false; // Was the tool canceled while it was running?
1514 m_multiple = true; // Multiple selection mode is active
1515 KIGFX::VIEW* view = getView();
1516
1518 view->Add( &area );
1519
1520 while( TOOL_EVENT* evt = Wait() )
1521 {
1522 int width = area.GetEnd().x - area.GetOrigin().x;
1523 int height = area.GetEnd().y - area.GetOrigin().y;
1524
1525 /* Selection mode depends on direction of drag-selection:
1526 * Left > Right : Select objects that are fully enclosed by selection
1527 * Right > Left : Select objects that are crossed by selection
1528 */
1529 bool isGreedy = width < 0;
1530
1531 if( view->IsMirroredX() )
1532 isGreedy = !isGreedy;
1533
1534 m_frame->GetCanvas()->SetCurrentCursor( isGreedy ? KICURSOR::SELECT_LASSO
1535 : KICURSOR::SELECT_WINDOW );
1536
1537 if( evt->IsCancelInteractive() || evt->IsActivate() )
1538 {
1539 cancelled = true;
1540 break;
1541 }
1542
1543 if( evt->IsDrag( BUT_LEFT ) )
1544 {
1547
1548 // Start drawing a selection box
1549 area.SetOrigin( evt->DragOrigin() );
1550 area.SetEnd( evt->Position() );
1553 area.SetExclusiveOr( false );
1554
1555 view->SetVisible( &area, true );
1556 view->Update( &area );
1557 getViewControls()->SetAutoPan( true );
1558 }
1559
1560 if( evt->IsMouseUp( BUT_LEFT ) )
1561 {
1562 getViewControls()->SetAutoPan( false );
1563
1564 // End drawing the selection box
1565 view->SetVisible( &area, false );
1566
1567 // Fetch items from the RTree that are in our area of interest
1568 std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> nearbyViewItems;
1569 view->Query( area.ViewBBox(), nearbyViewItems );
1570
1571 // Build lists of nearby items and their children
1572 std::unordered_set<EDA_ITEM*> nearbyItems;
1573 std::vector<EDA_ITEM*> nearbyChildren;
1574 std::vector<EDA_ITEM*> flaggedItems;
1575
1576 for( KIGFX::VIEW::LAYER_ITEM_PAIR& pair : nearbyViewItems )
1577 {
1578 if( EDA_ITEM* item = dynamic_cast<EDA_ITEM*>( pair.first ) )
1579 {
1580 if( nearbyItems.insert( item ).second )
1581 {
1582 item->ClearFlags( CANDIDATE );
1583
1584 if( SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( item ) )
1585 {
1586 sch_item->RunOnChildren(
1587 [&]( SCH_ITEM* aChild )
1588 {
1589 // Filter pins by unit
1590 if( SCH_PIN* pin = dynamic_cast<SCH_PIN*>( aChild ) )
1591 {
1592 int unit = pin->GetLibPin()->GetUnit();
1593
1594 if( unit && unit != pin->GetParentSymbol()->GetUnit() )
1595 return;
1596 }
1597
1598 nearbyChildren.push_back( aChild );
1599 } );
1600 }
1601 }
1602 }
1603 }
1604
1605 BOX2I selectionRect( area.GetOrigin(), VECTOR2I( width, height ) );
1606 selectionRect.Normalize();
1607
1608 bool anyAdded = false;
1609 bool anySubtracted = false;
1610
1611 auto selectItem =
1612 [&]( EDA_ITEM* aItem, EDA_ITEM_FLAGS flags )
1613 {
1614 if( m_subtractive || ( m_exclusive_or && aItem->IsSelected() ) )
1615 {
1616 if ( m_exclusive_or )
1617 aItem->XorFlags( flags );
1618 else
1619 aItem->ClearFlags( flags );
1620
1621 if( !aItem->HasFlag( STARTPOINT ) && !aItem->HasFlag( ENDPOINT ) )
1622 {
1623 unselect( aItem );
1624 anySubtracted = true;
1625 }
1626
1627 // We changed one line endpoint on a selected line,
1628 // update the view at least.
1629 if( flags && !anySubtracted )
1630 getView()->Update( aItem );
1631 }
1632 else
1633 {
1634 aItem->SetFlags( flags );
1635 select( aItem );
1636 anyAdded = true;
1637 }
1638 };
1639
1640 for( EDA_ITEM* item : nearbyItems )
1641 {
1642 bool selected = false;
1643 EDA_ITEM_FLAGS flags = 0;
1644
1646 item->SetFlags( SHOW_ELEC_TYPE );
1647
1648 if( Selectable( item ) )
1649 {
1650 if( item->Type() == SCH_LINE_T )
1651 {
1652 SCH_LINE* line = static_cast<SCH_LINE*>( item );
1653
1654 if( ( isGreedy && line->HitTest( selectionRect, false ) )
1655 || ( selectionRect.Contains( line->GetEndPoint() )
1656 && selectionRect.Contains( line->GetStartPoint() ) ) )
1657 {
1658 selected = true;
1659 flags |= STARTPOINT | ENDPOINT;
1660 }
1661 else if( !isGreedy )
1662 {
1663 if( selectionRect.Contains( line->GetStartPoint() )
1664 && line->IsStartDangling() )
1665 {
1666 selected = true;
1667 flags |= STARTPOINT;
1668 }
1669
1670 if( selectionRect.Contains( line->GetEndPoint() )
1671 && line->IsEndDangling() )
1672 {
1673 selected = true;
1674 flags |= ENDPOINT;
1675 }
1676 }
1677 }
1678 else
1679 {
1680 selected = item->HitTest( selectionRect, !isGreedy );
1681 }
1682 }
1683
1684 if( selected )
1685 {
1686 item->SetFlags( CANDIDATE );
1687 flaggedItems.push_back( item );
1688 selectItem( item, flags );
1689 }
1690
1691 item->ClearFlags( SHOW_ELEC_TYPE );
1692 }
1693
1694 for( EDA_ITEM* item : nearbyChildren )
1695 {
1697 item->SetFlags( SHOW_ELEC_TYPE );
1698
1699 if( Selectable( item )
1700 && !item->GetParent()->HasFlag( CANDIDATE )
1701 && item->HitTest( selectionRect, !isGreedy ) )
1702 {
1703 selectItem( item, 0 );
1704 }
1705
1706 item->ClearFlags( SHOW_ELEC_TYPE );
1707 }
1708
1709 for( EDA_ITEM* item : flaggedItems )
1710 item->ClearFlags( CANDIDATE );
1711
1712 m_selection.SetIsHover( false );
1713
1714 // Inform other potentially interested tools
1715 if( anyAdded )
1717
1718 if( anySubtracted )
1720
1721 break; // Stop waiting for events
1722 }
1723
1724 // Allow some actions for navigation
1725 for( int i = 0; allowedActions[i]; ++i )
1726 {
1727 if( evt->IsAction( allowedActions[i] ) )
1728 {
1729 evt->SetPassEvent();
1730 break;
1731 }
1732 }
1733 }
1734
1735 getViewControls()->SetAutoPan( false );
1736
1737 // Stop drawing the selection box
1738 view->Remove( &area );
1739 m_multiple = false; // Multiple selection mode is inactive
1740
1741 if( !cancelled )
1743
1744 return cancelled;
1745}
1746
1747
1749{
1750 EE_COLLECTOR collector;
1751
1752 //TODO(snh): Reimplement after exposing KNN interface
1753 int pixelThreshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
1754 int gridThreshold = KiROUND( getView()->GetGAL()->GetGridSize().EuclideanNorm() );
1755 int thresholdMax = std::max( pixelThreshold, gridThreshold );
1756
1757 for( int threshold : { 0, thresholdMax/4, thresholdMax/2, thresholdMax } )
1758 {
1759 collector.m_Threshold = threshold;
1760 collector.Collect( m_frame->GetScreen(), connectedTypes, aPosition );
1761
1762 if( collector.GetCount() > 0 )
1763 break;
1764 }
1765
1766 return collector.GetCount() ? collector[ 0 ] : nullptr;
1767}
1768
1769
1771{
1772 VECTOR2I cursorPos = getViewControls()->GetCursorPosition( false );
1773
1774 SelectPoint( cursorPos, connectedTypes );
1775 return 0;
1776}
1777
1778
1780{
1783
1784 if( m_selection.Empty() )
1785 return 0;
1786
1787 unsigned done = false;
1788
1790
1791 for( EDA_ITEM* selItem : m_selection.GetItems() )
1792 {
1793 if( selItem->Type() != SCH_LINE_T )
1794 continue;
1795
1796 SCH_LINE* line = static_cast<SCH_LINE*>( selItem );
1797
1798 std::set<SCH_ITEM*> conns = m_frame->GetScreen()->MarkConnections( line, false );
1799 for( SCH_ITEM* item : conns )
1800 {
1801 if( item->IsType( { SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T,
1802 SCH_ITEM_LOCATE_GRAPHIC_LINE_T } )
1803 && !item->IsSelected() )
1804 {
1805 done = true;
1806 }
1807
1808 select( item );
1809 }
1810
1811 if( !done )
1812 {
1813 conns = m_frame->GetScreen()->MarkConnections( line, true );
1814
1815 for( SCH_ITEM* item : conns )
1816 select( item );
1817 }
1818 }
1819
1820 if( m_selection.GetSize() > 1 )
1822
1823 return 0;
1824}
1825
1826
1828{
1830 return 0;
1831}
1832
1833
1835{
1836 if( aBBox.GetWidth() == 0 )
1837 return;
1838
1839 BOX2I bbox = aBBox;
1840 bbox.Normalize();
1841
1842 VECTOR2I bbSize = bbox.Inflate( bbox.GetWidth() * 0.2f ).GetSize();
1843 VECTOR2D screenSize = getView()->GetViewport().GetSize();
1844
1845 // This code tries to come up with a zoom factor that doesn't simply zoom in
1846 // to the cross probed symbol, but instead shows a reasonable amount of the
1847 // circuit around it to provide context. This reduces or eliminates the need
1848 // to manually change the zoom because it's too close.
1849
1850 // Using the default text height as a constant to compare against, use the
1851 // height of the bounding box of visible items for a footprint to figure out
1852 // if this is a big symbol (like a processor) or a small symbol (like a resistor).
1853 // This ratio is not useful by itself as a scaling factor. It must be "bent" to
1854 // provide good scaling at varying symbol sizes. Bigger symbols need less
1855 // scaling than small ones.
1856 double currTextHeight = schIUScale.MilsToIU( DEFAULT_TEXT_SIZE );
1857
1858 double compRatio = bbSize.y / currTextHeight; // Ratio of symbol to text height
1859 double compRatioBent = 1.0;
1860
1861 // LUT to scale zoom ratio to provide reasonable schematic context. Must work
1862 // with symbols of varying sizes (e.g. 0402 package and 200 pin BGA).
1863 // "first" is used as the input and "second" as the output
1864 //
1865 // "first" = compRatio (symbol height / default text height)
1866 // "second" = Amount to scale ratio by
1867 std::vector<std::pair<double, double>> lut{ { 1.25, 16 }, // 32
1868 { 2.5, 12 }, //24
1869 { 5, 8 }, // 16
1870 { 6, 6 }, //
1871 { 10, 4 }, //8
1872 { 20, 2 }, //4
1873 { 40, 1.5 }, // 2
1874 { 100, 1 } };
1875
1876 std::vector<std::pair<double, double>>::iterator it;
1877
1878 // Large symbol default is last LUT entry (1:1).
1879 compRatioBent = lut.back().second;
1880
1881 // Use LUT to do linear interpolation of "compRatio" within "first", then
1882 // use that result to linearly interpolate "second" which gives the scaling
1883 // factor needed.
1884 if( compRatio >= lut.front().first )
1885 {
1886 for( it = lut.begin(); it < lut.end() - 1; it++ )
1887 {
1888 if( it->first <= compRatio && next( it )->first >= compRatio )
1889 {
1890 double diffx = compRatio - it->first;
1891 double diffn = next( it )->first - it->first;
1892
1893 compRatioBent = it->second + ( next( it )->second - it->second ) * diffx / diffn;
1894 break; // We have our interpolated value
1895 }
1896 }
1897 }
1898 else
1899 {
1900 compRatioBent = lut.front().second; // Small symbol default is first entry
1901 }
1902
1903 // This is similar to the original KiCad code that scaled the zoom to make sure
1904 // symbols were visible on screen. It's simply a ratio of screen size to
1905 // symbol size, and its job is to zoom in to make the component fullscreen.
1906 // Earlier in the code the symbol BBox is given a 20% margin to add some
1907 // breathing room. We compare the height of this enlarged symbol bbox to the
1908 // default text height. If a symbol will end up with the sides clipped, we
1909 // adjust later to make sure it fits on screen.
1910 screenSize.x = std::max( 10.0, screenSize.x );
1911 screenSize.y = std::max( 10.0, screenSize.y );
1912 double ratio = std::max( -1.0, fabs( bbSize.y / screenSize.y ) );
1913
1914 // Original KiCad code for how much to scale the zoom
1915 double kicadRatio =
1916 std::max( fabs( bbSize.x / screenSize.x ), fabs( bbSize.y / screenSize.y ) );
1917
1918 // If the width of the part we're probing is bigger than what the screen width
1919 // will be after the zoom, then punt and use the KiCad zoom algorithm since it
1920 // guarantees the part's width will be encompassed within the screen.
1921 if( bbSize.x > screenSize.x * ratio * compRatioBent )
1922 {
1923 // Use standard KiCad zoom for parts too wide to fit on screen/
1924 ratio = kicadRatio;
1925 compRatioBent = 1.0; // Reset so we don't modify the "KiCad" ratio
1926 wxLogTrace( "CROSS_PROBE_SCALE",
1927 "Part TOO WIDE for screen. Using normal KiCad zoom ratio: %1.5f", ratio );
1928 }
1929
1930 // Now that "compRatioBent" holds our final scaling factor we apply it to the
1931 // original fullscreen zoom ratio to arrive at the final ratio itself.
1932 ratio *= compRatioBent;
1933
1934 bool alwaysZoom = false; // DEBUG - allows us to minimize zooming or not
1935
1936 // Try not to zoom on every cross-probe; it gets very noisy
1937 if( ( ratio < 0.5 || ratio > 1.0 ) || alwaysZoom )
1938 getView()->SetScale( getView()->GetScale() / ratio );
1939}
1940
1941
1942void EE_SELECTION_TOOL::SyncSelection( const std::optional<SCH_SHEET_PATH>& targetSheetPath,
1943 SCH_ITEM* focusItem, const std::vector<SCH_ITEM*>& items )
1944{
1945 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
1946
1947 if( !editFrame )
1948 return;
1949
1950 if( targetSheetPath && targetSheetPath != editFrame->Schematic().CurrentSheet() )
1951 {
1952 editFrame->Schematic().SetCurrentSheet( *targetSheetPath );
1953 editFrame->DisplayCurrentSheet();
1954 }
1955
1956 ClearSelection( items.size() > 0 ? true /*quiet mode*/ : false );
1957
1958 // Perform individual selection of each item before processing the event.
1959 for( SCH_ITEM* item : items )
1960 {
1961 // Make sure we only select items on the current screen
1962 if( m_frame->GetScreen()->CheckIfOnDrawList( item ) )
1963 select( item );
1964 }
1965
1967
1968 if( bbox.GetWidth() != 0 && bbox.GetHeight() != 0 )
1969 {
1971 {
1973 ZoomFitCrossProbeBBox( bbox );
1974
1975 editFrame->FocusOnItem( focusItem );
1976
1977 if( !focusItem )
1978 editFrame->FocusOnLocation( bbox.Centre() );
1979 }
1980 }
1981
1982 if( m_selection.Size() > 0 )
1984}
1985
1986
1988{
1990
1991 if( m_isSymbolEditor )
1992 {
1993 LIB_SYMBOL* start = static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->GetCurSymbol();
1994
1995 for( LIB_ITEM& item : start->GetDrawItems() )
1996 {
1997 if( item.IsSelected() )
1998 select( &item );
1999 }
2000 }
2001 else
2002 {
2003 for( SCH_ITEM* item : m_frame->GetScreen()->Items() )
2004 {
2005 // If the field and symbol are selected, only use the symbol
2006 if( item->IsSelected() )
2007 {
2008 select( item );
2009 }
2010 else
2011 {
2012 item->RunOnChildren(
2013 [&]( SCH_ITEM* aChild )
2014 {
2015 if( aChild->IsSelected() )
2016 select( aChild );
2017 } );
2018 }
2019 }
2020 }
2021
2023
2024 // Inform other potentially interested tools
2026}
2027
2028
2029bool EE_SELECTION_TOOL::Selectable( const EDA_ITEM* aItem, const VECTOR2I* aPos,
2030 bool checkVisibilityOnly ) const
2031{
2032 // NOTE: in the future this is where Eeschema layer/itemtype visibility will be handled
2033
2034 SYMBOL_EDIT_FRAME* symEditFrame = dynamic_cast<SYMBOL_EDIT_FRAME*>( m_frame );
2035
2036 // Do not allow selection of anything except fields when the current symbol in the symbol
2037 // editor is a derived symbol.
2038 if( symEditFrame && symEditFrame->IsSymbolAlias() && aItem->Type() != LIB_FIELD_T )
2039 return false;
2040
2041 switch( aItem->Type() )
2042 {
2043 case SCH_PIN_T:
2044 {
2045 const SCH_PIN* pin = static_cast<const SCH_PIN*>( aItem );
2046
2047 if( !pin->IsVisible() && !m_frame->GetShowAllPins() )
2048 return false;
2049
2051 {
2052 // Pin anchors have to be allowed for auto-starting wires.
2053 if( aPos )
2054 {
2056
2057 if( pin->IsPointClickableAnchor( grid.BestSnapAnchor(
2058 *aPos, grid.GetItemGrid( static_cast<const SCH_ITEM*>( aItem ) ) ) ) )
2059 return true;
2060 }
2061
2062 return false;
2063 }
2064
2065 break;
2066 }
2067
2070 return false;
2071
2072 break;
2073
2074 case LIB_SYMBOL_T: // In symbol_editor we do not want to select the symbol itself.
2075 return false;
2076
2077 case LIB_FIELD_T: // LIB_FIELD object can always be edited.
2078 break;
2079
2080 case LIB_SHAPE_T:
2081 case LIB_TEXT_T:
2082 case LIB_PIN_T:
2083 if( symEditFrame )
2084 {
2085 LIB_ITEM* lib_item = (LIB_ITEM*) aItem;
2086
2087 if( lib_item->GetUnit() && lib_item->GetUnit() != symEditFrame->GetUnit() )
2088 return false;
2089
2090 if( lib_item->GetConvert() && lib_item->GetConvert() != symEditFrame->GetConvert() )
2091 return false;
2092 }
2093
2094 break;
2095
2096 case SCH_MARKER_T: // Always selectable
2097 return true;
2098
2099 default: // Suppress warnings
2100 break;
2101 }
2102
2103 return true;
2104}
2105
2106
2108{
2109 if( m_selection.Empty() )
2110 return;
2111
2112 while( m_selection.GetSize() )
2114
2115 getView()->Update( &m_selection );
2116
2117 m_selection.SetIsHover( false );
2119
2120 // Inform other potentially interested tools
2121 if( !aQuietMode )
2123}
2124
2125
2127{
2128 highlight( aItem, SELECTED, &m_selection );
2129}
2130
2131
2133{
2134 unhighlight( aItem, SELECTED, &m_selection );
2135}
2136
2137
2138void EE_SELECTION_TOOL::highlight( EDA_ITEM* aItem, int aMode, SELECTION* aGroup )
2139{
2140 KICAD_T itemType = aItem->Type();
2141
2142 if( aMode == SELECTED )
2143 aItem->SetSelected();
2144 else if( aMode == BRIGHTENED )
2145 aItem->SetBrightened();
2146
2147 if( aGroup )
2148 aGroup->Add( aItem );
2149
2150 // Highlight pins and fields. (All the other symbol children are currently only
2151 // represented in the LIB_SYMBOL and will inherit the settings of the parent symbol.)
2152 if( SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( aItem ) )
2153 {
2154 sch_item->RunOnChildren(
2155 [&]( SCH_ITEM* aChild )
2156 {
2157 if( aMode == SELECTED )
2158 {
2159 aChild->SetSelected();
2160 getView()->Hide( aChild, true );
2161 }
2162 else if( aMode == BRIGHTENED )
2163 {
2164 aChild->SetBrightened();
2165 }
2166 } );
2167 }
2168
2169 if( aGroup && aMode != BRIGHTENED )
2170 getView()->Hide( aItem, true );
2171
2172 if( itemType == SCH_PIN_T || itemType == SCH_FIELD_T || itemType == SCH_SHEET_PIN_T )
2173 getView()->Update( aItem->GetParent(), KIGFX::REPAINT );
2174 else
2175 getView()->Update( aItem, KIGFX::REPAINT );
2176}
2177
2178
2179void EE_SELECTION_TOOL::unhighlight( EDA_ITEM* aItem, int aMode, SELECTION* aGroup )
2180{
2181 KICAD_T itemType = aItem->Type();
2182
2183 if( aMode == SELECTED )
2184 {
2185 aItem->ClearSelected();
2186 // Lines need endpoints cleared here
2187 if( aItem->Type() == SCH_LINE_T )
2188 aItem->ClearFlags( STARTPOINT | ENDPOINT );
2189
2190 if( aMode != BRIGHTENED )
2191 getView()->Hide( aItem, false );
2192 }
2193 else if( aMode == BRIGHTENED )
2194 {
2195 aItem->ClearBrightened();
2196 }
2197
2198 if( aGroup )
2199 aGroup->Remove( aItem );
2200
2201 // Unhighlight pins and fields. (All the other symbol children are currently only
2202 // represented in the LIB_SYMBOL.)
2203 if( SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( aItem ) )
2204 {
2205 sch_item->RunOnChildren(
2206 [&]( SCH_ITEM* aChild )
2207 {
2208 if( aMode == SELECTED )
2209 {
2210 aChild->ClearSelected();
2211 getView()->Hide( aChild, false );
2212 }
2213 else if( aMode == BRIGHTENED )
2214 {
2215 aChild->ClearBrightened();
2216 }
2217
2218 if( aGroup )
2219 aGroup->Remove( aChild );
2220 } );
2221 }
2222
2223 if( itemType == SCH_PIN_T || itemType == SCH_FIELD_T || itemType == SCH_SHEET_PIN_T )
2224 getView()->Update( aItem->GetParent(), KIGFX::REPAINT );
2225 else
2226 getView()->Update( aItem, KIGFX::REPAINT );
2227}
2228
2229
2231{
2232 const unsigned GRIP_MARGIN = 20;
2233 double margin = getView()->ToWorld( GRIP_MARGIN );
2234
2235 // Check if the point is located within any of the currently selected items bounding boxes
2236 for( EDA_ITEM* item : m_selection )
2237 {
2238 BOX2I itemBox = item->ViewBBox();
2239 itemBox.Inflate( margin ); // Give some margin for gripping an item
2240
2241 if( itemBox.Contains( aPoint ) )
2242 return true;
2243 }
2244
2245 return false;
2246}
2247
2248
2250{
2252
2257
2263
2266
2268}
2269
2270
VECTOR2D mapCoords(const VECTOR2D &aSource)
Definition: PS_plotter.cpp:525
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:111
static TOOL_ACTION unselectAll
Definition: actions.h:72
static TOOL_ACTION cursorLeft
Definition: actions.h:122
static TOOL_ACTION zoomOutCenter
Definition: actions.h:98
static TOOL_ACTION zoomIn
Definition: actions.h:95
static TOOL_ACTION cursorLeftFast
Definition: actions.h:127
static TOOL_ACTION cursorDown
Definition: actions.h:121
static TOOL_ACTION zoomOut
Definition: actions.h:96
static TOOL_ACTION cursorRightFast
Definition: actions.h:128
static TOOL_ACTION zoomCenter
Definition: actions.h:99
static TOOL_ACTION panDown
Definition: actions.h:135
static TOOL_ACTION cursorDownFast
Definition: actions.h:126
static TOOL_ACTION cursorUpFast
Definition: actions.h:125
static TOOL_ACTION panLeft
Definition: actions.h:136
static TOOL_ACTION updateMenu
Definition: actions.h:180
static TOOL_ACTION zoomFitScreen
Definition: actions.h:100
static TOOL_ACTION panUp
Definition: actions.h:134
static TOOL_ACTION zoomFitObjects
Definition: actions.h:101
static TOOL_ACTION zoomInCenter
Definition: actions.h:97
static TOOL_ACTION panRight
Definition: actions.h:137
static TOOL_ACTION cursorUp
Cursor control with keyboard.
Definition: actions.h:120
static TOOL_ACTION cursorRight
Definition: actions.h:123
static TOOL_ACTION selectAll
Definition: actions.h:71
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
CROSS_PROBING_SETTINGS m_CrossProbing
Definition: app_settings.h:155
BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition: box2.h:120
const Vec & GetPosition() const
Definition: box2.h:185
void SetMaximum()
Definition: box2.h:64
const Vec GetCenter() const
Definition: box2.h:196
coord_type GetHeight() const
Definition: box2.h:189
coord_type GetWidth() const
Definition: box2.h:188
bool Contains(const Vec &aPoint) const
Definition: box2.h:142
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:507
Vec Centre() const
Definition: box2.h:71
const Vec & GetSize() const
Definition: box2.h:180
An abstract class that will find and hold all the objects according to an inspection done by the Insp...
Definition: collector.h:48
void Transfer(int aIndex)
Move the item at aIndex (first position is 0) to the backup list.
Definition: collector.h:151
bool m_MenuCancelled
Definition: collector.h:237
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:81
bool HasItem(const EDA_ITEM *aItem) const
Tests if aItem has already been collected.
Definition: collector.h:195
void Remove(int aIndex)
Remove the item at aIndex (first position is 0).
Definition: collector.h:109
int m_Threshold
Definition: collector.h:234
void Append(EDA_ITEM *item)
Add an item to the end of the list.
Definition: collector.h:99
COMMIT & Added(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Remove a new item from the model.
Definition: commit.h:84
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been added.
Definition: commit.h:78
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Add a menu entry to run a TOOL_ACTION on selected items.
bool IsHorizontal() const
Definition: eda_angle.h:174
void AddStandardSubMenus(TOOL_MENU &aMenu)
Construct a "basic" menu for a tool, containing only items that apply to all tools (e....
void FocusOnLocation(const VECTOR2I &aPos)
Useful to focus on a particular location, in find functions.
virtual EDA_ITEM * GetItem(const KIID &aId) const
Fetch an item by KIID.
void SetCurrentCursor(KICURSOR aCursor)
Set the current cursor shape for this panel.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:74
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:123
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
void ClearSelected()
Definition: eda_item.h:118
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:125
bool IsSelected() const
Definition: eda_item.h:106
void SetSelected()
Definition: eda_item.h:115
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition: eda_item.h:172
void ClearBrightened()
Definition: eda_item.h:119
void SetBrightened()
Definition: eda_item.h:116
virtual bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const
Test if aPosition is inside or on the boundary of this item.
Definition: eda_item.h:212
EDA_ITEM * GetParent() const
Definition: eda_item.h:99
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition: eda_item.h:127
void XorFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:124
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:126
SHAPE_T GetShape() const
Definition: eda_shape.h:119
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:80
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:131
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:95
std::shared_ptr< SHAPE_COMPOUND > GetEffectiveTextShape(bool aTriangulate=true, const BOX2I &aBBox=BOX2I(), const EDA_ANGLE &aAngle=ANGLE_0) const
build a list of segments (SHAPE_SEGMENT) to describe a text shape.
Definition: eda_text.cpp:952
static TOOL_ACTION selectionActivate
Activation of the selection tool.
Definition: ee_actions.h:46
static TOOL_ACTION properties
Definition: ee_actions.h:129
static TOOL_ACTION addItemsToSel
Selects a list of items (specified as the event parameter)
Definition: ee_actions.h:63
static TOOL_ACTION move
Definition: ee_actions.h:121
static TOOL_ACTION clearHighlight
Definition: ee_actions.h:285
static TOOL_ACTION selectConnection
If current selection is a wire or bus, expand to entire connection.
Definition: ee_actions.h:53
static TOOL_ACTION pinTable
Definition: ee_actions.h:156
static TOOL_ACTION navigateForward
Definition: ee_actions.h:219
static TOOL_ACTION slice
Definition: ee_actions.h:145
static TOOL_ACTION assignNetclass
Definition: ee_actions.h:162
static TOOL_ACTION clearSelection
Clears the current selection.
Definition: ee_actions.h:56
static TOOL_ACTION drag
Definition: ee_actions.h:122
static TOOL_ACTION navigateBack
Definition: ee_actions.h:220
static TOOL_ACTION selectionMenu
Runs a selection menu to select from a list of items.
Definition: ee_actions.h:67
static TOOL_ACTION placeClassLabel
Definition: ee_actions.h:88
static TOOL_ACTION drawWire
Definition: ee_actions.h:81
static TOOL_ACTION removeItemsFromSel
Definition: ee_actions.h:64
static TOOL_ACTION drawBus
Definition: ee_actions.h:82
static TOOL_ACTION finishWire
Definition: ee_actions.h:104
static TOOL_ACTION selectNode
Select the junction, wire or bus segment under the cursor.
Definition: ee_actions.h:49
static TOOL_ACTION breakWire
Definition: ee_actions.h:144
static TOOL_ACTION drawLines
Definition: ee_actions.h:98
static TOOL_ACTION importSheetPin
Definition: ee_actions.h:92
static TOOL_ACTION selectOnPCB
Definition: ee_actions.h:241
static TOOL_ACTION leaveSheet
Definition: ee_actions.h:217
static TOOL_ACTION placeGlobalLabel
Definition: ee_actions.h:89
static TOOL_ACTION removeItemFromSel
Definition: ee_actions.h:60
static TOOL_ACTION placeHierLabel
Definition: ee_actions.h:90
static TOOL_ACTION addItemToSel
Selects an item (specified as the event parameter).
Definition: ee_actions.h:59
static TOOL_ACTION symbolProperties
Definition: ee_actions.h:155
static TOOL_ACTION editPageNumber
Definition: ee_actions.h:164
static TOOL_ACTION enterSheet
Definition: ee_actions.h:216
static TOOL_ACTION setUnitDisplayName
Definition: ee_actions.h:212
static TOOL_ACTION unfoldBus
Definition: ee_actions.h:83
static TOOL_ACTION placeLabel
Definition: ee_actions.h:87
static TOOL_ACTION placeJunction
Definition: ee_actions.h:85
static TOOL_ACTION finishBus
Definition: ee_actions.h:105
bool m_ShowPinElectricalTypes
static const std::vector< KICAD_T > MovableItems
Definition: ee_collectors.h:43
void Collect(SCH_SCREEN *aScreen, const std::vector< KICAD_T > &aScanTypes, const VECTOR2I &aPos, int aUnit=0, int aConvert=0)
Scan a EDA_ITEM using this class's Inspector method which does the collection.
static SELECTION_CONDITION SingleSymbol
static SELECTION_CONDITION SingleMultiFunctionPin
static SELECTION_CONDITION SingleSymbolOrPower
static SELECTION_CONDITION SingleMultiUnitSymbol
static SELECTION_CONDITION SingleNonExcludedMarker
static SELECTION_CONDITION SingleDeMorganSymbol
static SELECTION_CONDITION AllPins
static SELECTION_CONDITION MultipleSymbolsOrPower
GRID_HELPER_GRIDS GetItemGrid(const EDA_ITEM *aItem) const override
Gets the coarsest grid that applies to an item.
VECTOR2I BestSnapAnchor(const VECTOR2I &aOrigin, GRID_HELPER_GRIDS aGrid, SCH_ITEM *aSkip)
Tool that displays edit points allowing to modify items by dragging the points.
bool HasPoint()
Indicate the cursor is over an edit point.
bool Selectable(const EDA_ITEM *aItem, const VECTOR2I *aPos=nullptr, bool checkVisibilityOnly=false) const
Check conditions for an item to be selected.
void GuessSelectionCandidates(EE_COLLECTOR &collector, const VECTOR2I &aPos)
Apply heuristics to try and determine a single object when multiple are found under the cursor.
bool selectMultiple()
Handle drawing a selection box that allows one to select many items at the same time.
bool selectionContains(const VECTOR2I &aPoint) const
Set up handlers for various events.
void unhighlight(EDA_ITEM *aItem, int aHighlightMode, SELECTION *aGroup=nullptr) override
Unhighlight the item visually.
EE_SELECTION m_selection
void unselect(EDA_ITEM *aItem) override
Take necessary action to mark an item as unselected.
void SyncSelection(const std::optional< SCH_SHEET_PATH > &targetSheetPath, SCH_ITEM *focusItem, const std::vector< SCH_ITEM * > &items)
int SelectConnection(const TOOL_EVENT &aEvent)
If a connected item is selected then expand the selection to the entire connection,...
bool CollectHits(EE_COLLECTOR &aCollector, const VECTOR2I &aWhere, const std::vector< KICAD_T > &aScanTypes={ SCH_LOCATE_ANY_T })
Collect one or more items at a given point.
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
bool selectPoint(EE_COLLECTOR &aCollector, const VECTOR2I &aWhere, EDA_ITEM **aItem=nullptr, bool *aSelectionCancelledFlag=nullptr, bool aAdd=false, bool aSubtract=false, bool aExclusiveOr=false)
Perform a click-type selection at a point (usually the cursor position).
int SelectAll(const TOOL_EVENT &aEvent)
Unselect all visible items in sheet.
EDA_ITEM * GetNode(const VECTOR2I &aPosition)
Finds a connected item at a point (usually the cursor position).
EE_SELECTION & RequestSelection(const std::vector< KICAD_T > &aScanTypes={ SCH_LOCATE_ANY_T })
Return either an existing selection (filtered), or the selection at the current cursor position if th...
void ZoomFitCrossProbeBBox(const BOX2I &aBBox)
bool SelectPoint(const VECTOR2I &aWhere, const std::vector< KICAD_T > &aScanTypes={ SCH_LOCATE_ANY_T }, EDA_ITEM **aItem=nullptr, bool *aSelectionCancelledFlag=nullptr, bool aCheckLocked=false, bool aAdd=false, bool aSubtract=false, bool aExclusiveOr=false)
Perform a click-type selection at a point (usually the cursor position).
int Main(const TOOL_EVENT &aEvent)
The main loop.
int UnselectAll(const TOOL_EVENT &aEvent)
int disambiguateCursor(const TOOL_EVENT &aEvent)
Handle disambiguation actions including displaying the menu.
int SelectNode(const TOOL_EVENT &aEvent)
Selects the connected item at the current cursor position.
bool Init() override
Init() is called once upon a registration of the tool.
int ClearSelection(const TOOL_EVENT &aEvent)
Select all visible items in sheet.
OPT_TOOL_EVENT autostartEvent(TOOL_EVENT *aEvent, EE_GRID_HELPER &aGrid, SCH_ITEM *aItem)
void RebuildSelection()
Rebuild the selection from the EDA_ITEMs' selection flags.
void OnIdle(wxIdleEvent &aEvent)
Zoom the screen to fit the bounding box for cross probing/selection sync.
SCH_BASE_FRAME * m_frame
void narrowSelection(EE_COLLECTOR &collector, const VECTOR2I &aWhere, bool aCheckLocked, bool aSelectedOnly=false)
Apply rules to narrow the collection down to selectable objects, and then heuristics to try and narro...
void highlight(EDA_ITEM *aItem, int aHighlightMode, SELECTION *aGroup=nullptr) override
Highlight the item visually.
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
void select(EDA_ITEM *aItem) override
Take necessary action to mark an item as selected.
EE_SELECTION & GetSelection()
void updateReferencePoint()
Set the reference point to the anchor of the top-left item.
BOX2I GetBoundingBox() const override
EDA_ITEM * GetTopLeftItem(bool onlyModules=false) const override
static const TOOL_EVENT DisambiguatePoint
Used for hotkey feedback.
Definition: actions.h:250
static const TOOL_EVENT ClearedEvent
Definition: actions.h:235
static const TOOL_EVENT SelectedEvent
Definition: actions.h:233
static const TOOL_EVENT PointSelectedEvent
Definition: actions.h:232
static const TOOL_EVENT UnselectedEvent
Definition: actions.h:234
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
Represent a selection area (currently a rectangle) in a VIEW, drawn corner-to-corner between two poin...
void SetSubtractive(bool aSubtractive)
void SetAdditive(bool aAdditive)
void SetOrigin(const VECTOR2I &aOrigin)
const BOX2I ViewBBox() const override
Set the origin of the rectangle (the fixed corner)
void SetExclusiveOr(bool aExclusiveOr)
void SetEnd(const VECTOR2I &aEnd)
Set the current end of the rectangle (the corner that moves with the cursor.
void SetHighlight(bool aEnabled, int aNetcode=-1, bool aMulti=false)
Turns on/off highlighting.
virtual void CaptureCursor(bool aEnabled)
Force the cursor to stay within the drawing panel area.
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Place the cursor immediately at a given point.
virtual void WarpMouseCursor(const VECTOR2D &aPosition, bool aWorldCoordinates=false, bool aWarpView=false)=0
If enabled (.
virtual void SetCrossHairCursorPosition(const VECTOR2D &aPosition, bool aWarpView=true)=0
Move the graphic crosshair cursor to the requested position expressed in world coordinates.
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
virtual void SetAutoPan(bool aEnabled)
Turn on/off auto panning (this feature is used when there is a tool active (eg.
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:68
BOX2D GetViewport() const
Return the current viewport visible area rectangle.
Definition: view.cpp:507
virtual void SetScale(double aScale, VECTOR2D aAnchor={ 0, 0 })
Set the scaling factor, zooming around a given anchor point.
Definition: view.cpp:547
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:313
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:350
virtual int Query(const BOX2I &aRect, std::vector< LAYER_ITEM_PAIR > &aResult) const
Find all visible items that touch or are within the rectangle aRect.
Definition: view.cpp:421
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: view.cpp:1618
VECTOR2D ToWorld(const VECTOR2D &aCoord, bool aAbsolute=true) const
Converts a screen space point/vector to a point/vector in world space coordinates.
Definition: view.cpp:444
bool IsMirroredX() const
Return true if view is flipped across the X axis.
Definition: view.h:245
std::pair< VIEW_ITEM *, int > LAYER_ITEM_PAIR
Definition: view.h:72
void Hide(VIEW_ITEM *aItem, bool aHide=true, bool aHideOverlay=false)
Temporarily hide the item in the view (e.g.
Definition: view.cpp:1566
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:215
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1545
Definition: kiid.h:49
The base class for drawable items used by schematic library symbols.
Definition: lib_item.h:68
int GetUnit() const
Definition: lib_item.h:336
int GetConvert() const
Definition: lib_item.h:339
Define a library symbol object.
Definition: lib_symbol.h:99
bool IsMulti() const
Definition: lib_symbol.h:599
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition: lib_symbol.h:544
Tree view item data for the net navigator.
SCH_SHEET_PATH & CurrentSheet() const override
Definition: schematic.h:136
CONNECTION_GRAPH * ConnectionGraph() const override
Definition: schematic.h:146
void SetCurrentSheet(const SCH_SHEET_PATH &aPath) override
Definition: schematic.h:141
SCH_SHEET & Root() const
Definition: schematic.h:105
void AddToScreen(EDA_ITEM *aItem, SCH_SCREEN *aScreen=nullptr)
Add an item to the screen (and view) aScreen is the screen the item is located on,...
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
EESCHEMA_SETTINGS * eeconfig() const
KIGFX::SCH_RENDER_SETTINGS * GetRenderSettings()
virtual bool GetShowAllPins() const
Allow some frames to show/hide hidden pins.
Class for a wire to bus entry.
SCH_ITEM * m_connected_bus_item
Pointer to the bus item (usually a bus wire) connected to this bus-wire entry, if it is connected to ...
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
Definition: sch_commit.cpp:353
virtual void Revert() override
Definition: sch_commit.cpp:417
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
void ConfigureFromLabel(const wxString &aLabel)
Configures the connection given a label.
bool IsBus() const
KIGFX::SCH_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
Handle actions specific to the schematic editor.
Schematic editor (Eeschema) main window.
SCH_SHEET_PATH & GetCurrentSheet() const
SCHEMATIC & Schematic() const
void DisplayCurrentSheet()
Draw the current sheet on the display.
const wxString & GetHighlightedConnection() const
void FocusOnItem(SCH_ITEM *aItem)
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:52
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_field.cpp:505
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:151
SCHEMATIC * Schematic() const
Searches the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:113
virtual bool IsPointClickableAnchor(const VECTOR2I &aPos) const
Definition: sch_item.h:378
void SetShape(LABEL_FLAG_SHAPE aShape)
Definition: sch_label.h:168
virtual void SetSpinStyle(SPIN_STYLE aSpinStyle)
Definition: sch_label.cpp:337
static bool IsDrawingWire(const SELECTION &aSelection)
static bool IsDrawingBus(const SELECTION &aSelection)
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:40
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
Definition: sch_line.cpp:806
bool IsStartDangling() const
Definition: sch_line.h:260
VECTOR2I GetEndPoint() const
Definition: sch_line.h:145
VECTOR2I GetStartPoint() const
Definition: sch_line.h:140
bool IsEndDangling() const
Definition: sch_line.h:261
bool IsBus() const
Return true if the line is a bus.
Definition: sch_line.cpp:979
bool IsGraphicLine() const
Return if the line is a graphic (non electrical line)
Definition: sch_line.cpp:967
void SetEndPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:146
void ClearDrawingState()
Clear the state flags of all the items in the screen.
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:109
std::set< SCH_ITEM * > MarkConnections(SCH_LINE *aSegment, bool aSecondPass)
Return all wires and junctions connected to aSegment which are not connected any symbol pin.
Definition: sch_screen.cpp:405
bool CheckIfOnDrawList(const SCH_ITEM *aItem) const
Definition: sch_screen.cpp:383
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet_pin.h:66
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:57
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition: sch_sheet.h:181
Schematic symbol object.
Definition: sch_symbol.h:81
TRANSFORM & GetTransform()
Definition: sch_symbol.h:285
BOX2I GetBodyAndPinsBoundingBox() const
Return a bounding box for the symbol body and pins but not the fields.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:192
BOX2I GetBodyBoundingBox() const
Return a bounding box for the symbol body but not the pins or fields.
Definition: seg.h:42
static SELECTION_CONDITION HasTypes(std::vector< KICAD_T > aTypes)
Create a functor that tests if among the selected items there is at least one of a given types.
static bool Empty(const SELECTION &aSelection)
Test if there are no items selected.
static SELECTION_CONDITION MoreThan(int aNumber)
Create a functor that tests if the number of selected items is greater than the value given as parame...
static bool Idle(const SELECTION &aSelection)
Test if there no items selected or being edited.
static SELECTION_CONDITION LessThan(int aNumber)
Create a functor that tests if the number of selected items is smaller than the value given as parame...
static SELECTION_CONDITION Count(int aNumber)
Create a functor that tests if the number of selected items is equal to the value given as parameter.
static SELECTION_CONDITION OnlyTypes(std::vector< KICAD_T > aTypes)
Create a functor that tests if the selected items are only of given types.
int RemoveItemFromSel(const TOOL_EVENT &aEvent)
bool doSelectionMenu(COLLECTOR *aCollector)
wxTimer m_disambiguateTimer
int AddItemsToSel(const TOOL_EVENT &aEvent)
int AddItemToSel(const TOOL_EVENT &aEvent)
int UpdateMenu(const TOOL_EVENT &aEvent)
Update a menu's state based on the current selection.
void setModifiersState(bool aShiftState, bool aCtrlState, bool aAltState)
Set the configuration of m_additive, m_subtractive, m_exclusive_or, m_skip_heuristics from the state ...
VECTOR2I m_originalCursor
int SelectionMenu(const TOOL_EVENT &aEvent)
Show a popup menu to trim the COLLECTOR passed as aEvent's parameter down to a single item.
int RemoveItemsFromSel(const TOOL_EVENT &aEvent)
bool hasModifier()
True if a selection modifier is enabled, false otherwise.
void onDisambiguationExpire(wxTimerEvent &aEvent)
Start the process to show our disambiguation menu once the user has kept the mouse down for the minim...
virtual void Add(EDA_ITEM *aItem)
Definition: selection.cpp:42
virtual KIGFX::VIEW_ITEM * GetItem(unsigned int aIdx) const override
Definition: selection.cpp:75
const std::deque< EDA_ITEM * > GetItems() const
Definition: selection.h:120
void SetIsHover(bool aIsHover)
Definition: selection.h:78
virtual void Remove(EDA_ITEM *aItem)
Definition: selection.cpp:60
virtual unsigned int GetSize() const override
Return the number of stored items.
Definition: selection.h:99
EDA_ITEM * Front() const
Definition: selection.h:208
virtual void Clear() override
Remove all the stored items from the group.
Definition: selection.h:92
int Size() const
Returns the number of selected parts.
Definition: selection.h:115
void ClearReferencePoint()
Definition: selection.h:265
bool OnlyContains(std::vector< KICAD_T > aList) const
Checks if all items in the selection have a type in aList.
Definition: selection.cpp:191
void SetReferencePoint(const VECTOR2I &aP)
Definition: selection.h:260
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:109
bool Collide(const SHAPE *aShape, int aClearance, VECTOR2I *aMTV) const override
Check if the boundary of shape (this) lies closer to the shape aShape than aClearance,...
Definition: shape_rect.h:109
The symbol library editor main window.
bool IsSymbolAlias() const
Return true if aLibId is an alias for the editor screen symbol.
bool IsSymbolEditable() const
Test if a symbol is loaded and can be edited.
LIB_SYMBOL * GetCurSymbol() const
Return the current symbol being edited or NULL if none selected.
Symbol library viewer main window.
MOUSE_DRAG_ACTION GetDragAction() const
Indicates whether a drag should draw a selection rectangle or drag selected (or unselected) objects.
Definition: tools_holder.h:142
bool ToolStackIsEmpty()
Definition: tools_holder.h:123
Represent a single user action.
Definition: tool_action.h:269
TOOL_EVENT MakeEvent() const
Return the event associated with the action (i.e.
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:42
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:216
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
@ REDRAW
Full drawing refresh.
Definition: tool_base.h:83
@ MODEL_RELOAD
Model changes (the sheet for a schematic)
Definition: tool_base.h:80
@ SUPERMODEL_RELOAD
For schematics, the entire schematic changed, not just the sheet.
Definition: tool_base.h:81
Generic, UI-independent tool event.
Definition: tool_event.h:167
void SetMousePosition(const VECTOR2D &aP)
Definition: tool_event.h:525
const VECTOR2D Position() const
Returns the point where dragging has started.
Definition: tool_event.h:285
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
TOOL_MENU m_menu
The functions below are not yet implemented - their interface may change.
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Suspend execution of the tool until an event specified in aEventList arrives.
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagate an event to tools that requested events of matching type(s).
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:145
VECTOR2D GetMousePosition() const
bool PostAction(const std::string &aActionName, T aParam)
Run the specified action after the current action (coroutine) ends.
Definition: tool_manager.h:230
bool RunSynchronousAction(const TOOL_ACTION &aAction, COMMIT *aCommit, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:192
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:44
void ShowContextMenu(SELECTION &aSelection)
Helper function to set and immediately show a CONDITIONAL_MENU in concert with the given SELECTION.
Definition: tool_menu.cpp:57
int y1
Definition: transform.h:49
MOUSE_DRAG_ACTION
KICURSOR
Definition: cursors.h:34
#define DEFAULT_TEXT_SIZE
Ratio of the font height to the baseline of the text above the wire.
static constexpr EDA_ANGLE & ANGLE_HORIZONTAL
Definition: eda_angle.h:433
static constexpr EDA_ANGLE & ANGLE_VERTICAL
Definition: eda_angle.h:434
std::vector< EDA_ITEM * > EDA_ITEMS
Define list of drawing items for screens.
Definition: eda_item.h:529
#define BRIGHTENED
item is drawn with a bright contour
#define IS_NEW
New item, just created.
#define SELECTED
Item was manually selected by the user.
#define ENDPOINT
ends. (Used to support dragging.)
std::uint32_t EDA_ITEM_FLAGS
#define CANDIDATE
flag indicating that the structure is connected
#define IS_ROLLOVER
Rollover active. Used for hyperlink highlighting.
#define IS_MOVING
Item being moved.
#define SHOW_ELEC_TYPE
Show pin electrical type. Shared with IS_ROLLOVER.
#define STARTPOINT
When a line is selected, these flags indicate which.
static std::vector< KICAD_T > connectedTypes
#define HITTEST_THRESHOLD_PIXELS
const TOOL_ACTION * allowedActions[]
@ ID_POPUP_SCH_PIN_TRICKS_START
Definition: eeschema_id.h:88
@ ID_POPUP_SCH_PIN_TRICKS_HIER_LABEL
Definition: eeschema_id.h:92
@ ID_POPUP_SCH_PIN_TRICKS_WIRE
Definition: eeschema_id.h:90
@ ID_POPUP_SCH_ALT_PIN_FUNCTION
Definition: eeschema_id.h:96
@ ID_POPUP_SCH_UNFOLD_BUS_END
Definition: eeschema_id.h:79
@ ID_POPUP_SCH_SELECT_UNIT
Definition: eeschema_id.h:82
@ ID_POPUP_SCH_PIN_TRICKS_NET_LABEL
Definition: eeschema_id.h:91
@ ID_POPUP_SCH_PIN_TRICKS_NO_CONNECT
Definition: eeschema_id.h:89
@ ID_POPUP_SCH_UNFOLD_BUS
Definition: eeschema_id.h:78
@ ID_POPUP_SCH_SELECT_UNIT_END
Definition: eeschema_id.h:86
@ ID_POPUP_SCH_ALT_PIN_FUNCTION_END
Definition: eeschema_id.h:97
@ ID_POPUP_SCH_PIN_TRICKS_GLOBAL_LABEL
Definition: eeschema_id.h:93
@ ID_POPUP_SCH_PIN_TRICKS_END
Definition: eeschema_id.h:94
KIID niluuid(0)
@ LAYER_WIRE
Definition: layer_ids.h:349
@ REPAINT
Item needs to be redrawn.
Definition: view_item.h:57
CITER next(CITER it)
Definition: ptree.cpp:126
std::function< bool(const SELECTION &)> SELECTION_CONDITION
< Functor type that checks a specific condition for selected items.
bool zoom_to_fit
Zoom to fit items (ignored if center_on_items is off)
Definition: app_settings.h:35
bool center_on_items
Automatically pan to cross-probed items.
Definition: app_settings.h:34
constexpr int MilsToIU(int mils) const
Definition: base_units.h:94
std::optional< TOOL_EVENT > OPT_TOOL_EVENT
Definition: tool_event.h:628
@ TA_CHOICE_MENU_CHOICE
Definition: tool_event.h:97
@ TA_UNDO_REDO_PRE
Definition: tool_event.h:105
@ TC_COMMAND
Definition: tool_event.h:56
@ MD_ALT
Definition: tool_event.h:144
@ MD_CTRL
Definition: tool_event.h:143
@ MD_SHIFT
Definition: tool_event.h:142
@ BUT_AUX1
Definition: tool_event.h:134
@ BUT_MIDDLE
Definition: tool_event.h:133
@ BUT_LEFT
Definition: tool_event.h:131
@ BUT_RIGHT
Definition: tool_event.h:132
@ BUT_AUX2
Definition: tool_event.h:135
double DistanceLinePoint(const VECTOR2I &linePointA, const VECTOR2I &linePointB, const VECTOR2I &referencePoint)
Compute the distance between a line and a reference point.
Definition: trigo.h:143
bool HitTestPoints(const VECTOR2I &pointA, const VECTOR2I &pointB, double threshold)
Test if two points are near each other.
Definition: trigo.h:165
double EuclideanNorm(const VECTOR2I &vector)
Definition: trigo.h:128
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
@ SCH_LINE_T
Definition: typeinfo.h:146
@ LIB_SYMBOL_T
Definition: typeinfo.h:198
@ LIB_TEXT_T
Definition: typeinfo.h:200
@ SCH_SYMBOL_T
Definition: typeinfo.h:156
@ LIB_TEXTBOX_T
Definition: typeinfo.h:201
@ SCH_ITEM_LOCATE_WIRE_T
Definition: typeinfo.h:170
@ SCH_FIELD_T
Definition: typeinfo.h:155
@ SCH_DIRECTIVE_LABEL_T
Definition: typeinfo.h:154
@ SCH_LABEL_T
Definition: typeinfo.h:151
@ SCH_LOCATE_ANY_T
Definition: typeinfo.h:183
@ SCH_SHEET_T
Definition: typeinfo.h:158
@ SCH_ITEM_LOCATE_BUS_T
Definition: typeinfo.h:171
@ LIB_SHAPE_T
Definition: typeinfo.h:199
@ SCH_MARKER_T
Definition: typeinfo.h:141
@ SCH_HIER_LABEL_T
Definition: typeinfo.h:153
@ SCH_BUS_BUS_ENTRY_T
Definition: typeinfo.h:145
@ LIB_PIN_T
Definition: typeinfo.h:202
@ SCH_ITEM_LOCATE_GRAPHIC_LINE_T
Definition: typeinfo.h:172
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:157
@ LIB_FIELD_T
Definition: typeinfo.h:208
@ SCH_SYMBOL_LOCATE_POWER_T
Definition: typeinfo.h:180
@ SCH_BUS_WIRE_ENTRY_T
Definition: typeinfo.h:144
@ SCH_GLOBAL_LABEL_T
Definition: typeinfo.h:152
@ SCH_JUNCTION_T
Definition: typeinfo.h:142
@ SCH_PIN_T
Definition: typeinfo.h:159
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588