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-2024 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 <symbol_viewer_frame.h>
36#include <math/util.h>
37#include <geometry/shape_rect.h>
38#include <sch_painter.h>
40#include <sch_base_frame.h>
41#include <sch_commit.h>
42#include <sch_symbol.h>
43#include <sch_field.h>
44#include <sch_edit_frame.h>
45#include <sch_item.h>
46#include <sch_line.h>
47#include <sch_bus_entry.h>
48#include <sch_marker.h>
49#include <sch_no_connect.h>
50#include <sch_render_settings.h>
51#include <sch_sheet.h>
52#include <sch_sheet_pin.h>
53#include <sch_table.h>
54#include <sch_tablecell.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
68
69
71{
72 if( aSel.GetSize() == 1 )
73 {
74 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aSel.Front() );
75
76 if( symbol )
77 return !symbol->GetLibSymbolRef() || !symbol->GetLibSymbolRef()->IsPower();
78 }
79
80 return false;
81};
82
83
85{
86 return aSel.GetSize() == 1 && aSel.Front()->Type() == SCH_SYMBOL_T;
87};
88
89
91{
92 if( aSel.GetSize() == 1 )
93 {
94 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aSel.Front() );
95
96 if( symbol )
97 return symbol->GetLibSymbolRef() && symbol->GetLibSymbolRef()->HasAlternateBodyStyle();
98 }
99
100 return false;
101};
102
103
105{
106 if( aSel.GetSize() == 1 )
107 {
108 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aSel.Front() );
109
110 if( symbol )
111 return symbol->GetLibSymbolRef() && symbol->GetLibSymbolRef()->GetUnitCount() >= 2;
112 }
113
114 return false;
115};
116
117
119{
120 if( aSel.GetSize() == 1 )
121 {
122 SCH_PIN* pin = dynamic_cast<SCH_PIN*>( aSel.Front() );
123
124 if( pin && pin->GetLibPin() )
125 return !pin->GetLibPin()->GetAlternates().empty();
126 }
127
128 return false;
129};
130
131
133{
134 if( aSel.CountType( SCH_MARKER_T ) != 1 )
135 return false;
136
137 return !static_cast<SCH_MARKER*>( aSel.Front() )->IsExcluded();
138};
139
140
142{
143 return aSel.GetSize() > 1 && aSel.OnlyContains( { SCH_SYMBOL_T } );
144};
145
146
148{
149 return aSel.GetSize() >= 1 && aSel.OnlyContains( { SCH_PIN_T } );
150};
151
152
154{
155 return aSel.GetSize() >= 1 && aSel.OnlyContains( { SCH_PIN_T, SCH_SHEET_PIN_T } );
156};
157
158
159#define HITTEST_THRESHOLD_PIXELS 5
160
161
163 SELECTION_TOOL( "eeschema.InteractiveSelection" ),
164 m_frame( nullptr ),
165 m_nonModifiedCursor( KICURSOR::ARROW ),
166 m_isSymbolEditor( false ),
167 m_isSymbolViewer( false ),
168 m_unit( 0 ),
169 m_bodyStyle( 0 )
170{
173}
174
175
177{
179}
180
181
183
184
185static std::vector<KICAD_T> connectedTypes =
186{
188 SCH_PIN_T,
199};
200
201static std::vector<KICAD_T> connectedLineTypes =
202{
205};
206
207static std::vector<KICAD_T> crossProbingTypes =
208{
210 SCH_PIN_T,
212};
213
214static std::vector<KICAD_T> lineTypes = { SCH_LINE_T };
215static std::vector<KICAD_T> sheetTypes = { SCH_SHEET_T };
216static std::vector<KICAD_T> tableCellTypes = { SCH_TABLECELL_T };
217
219{
220 m_frame = getEditFrame<SCH_BASE_FRAME>();
221
222 SYMBOL_VIEWER_FRAME* symbolViewerFrame = dynamic_cast<SYMBOL_VIEWER_FRAME*>( m_frame );
223 SYMBOL_EDIT_FRAME* symbolEditorFrame = dynamic_cast<SYMBOL_EDIT_FRAME*>( m_frame );
224
225 if( symbolEditorFrame )
226 {
227 m_isSymbolEditor = true;
228 m_unit = symbolEditorFrame->GetUnit();
229 m_bodyStyle = symbolEditorFrame->GetBodyStyle();
230 }
231 else
232 {
233 m_isSymbolViewer = symbolViewerFrame != nullptr;
234 }
235
236 auto linesSelection = E_C::MoreThan( 0 ) && E_C::OnlyTypes( lineTypes );
237 auto wireOrBusSelection = E_C::Count( 1 ) && E_C::OnlyTypes( connectedLineTypes );
238 auto connectedSelection = E_C::Count( 1 ) && E_C::OnlyTypes( connectedTypes );
239 auto sheetSelection = E_C::Count( 1 ) && E_C::OnlyTypes( sheetTypes );
240 auto crossProbingSelection = E_C::MoreThan( 0 ) && E_C::HasTypes( crossProbingTypes );
241 auto tableCellSelection = E_C::MoreThan( 0 ) && E_C::OnlyTypes( tableCellTypes );
242
243 auto schEditSheetPageNumberCondition =
244 [&] ( const SELECTION& aSel )
245 {
247 return false;
248
249 return E_C::LessThan( 2 )( aSel ) && E_C::OnlyTypes( sheetTypes )( aSel );
250 };
251
252 auto schEditCondition =
253 [this] ( const SELECTION& aSel )
254 {
256 };
257
258 auto belowRootSheetCondition =
259 [&]( const SELECTION& aSel )
260 {
261 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
262
263 return editFrame
264 && editFrame->GetCurrentSheet().Last() != &editFrame->Schematic().Root();
265 };
266
267 auto haveHighlight =
268 [&]( const SELECTION& sel )
269 {
270 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
271
272 return editFrame && !editFrame->GetHighlightedConnection().IsEmpty();
273 };
274
275 auto haveSymbol =
276 [&]( const SELECTION& sel )
277 {
278 return m_isSymbolEditor &&
279 static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->GetCurSymbol();
280 };
281
282 auto symbolDisplayNameIsEditable =
283 [&]( const SELECTION& sel )
284 {
285 if ( !m_isSymbolEditor )
286 return false;
287
288 SYMBOL_EDIT_FRAME* symbEditorFrame = dynamic_cast<SYMBOL_EDIT_FRAME*>( m_frame );
289
290 return symbEditorFrame
291 && symbEditorFrame->GetCurSymbol()
292 && symbEditorFrame->GetCurSymbol()->IsMulti()
293 && symbEditorFrame->IsSymbolEditable()
294 && !symbEditorFrame->IsSymbolAlias();
295 };
296
297 auto& menu = m_menu.GetMenu();
298
299 menu.AddItem( EE_ACTIONS::clearHighlight, haveHighlight && EE_CONDITIONS::Idle, 1 );
300 menu.AddSeparator( haveHighlight && EE_CONDITIONS::Idle, 1 );
301
302 menu.AddItem( ACTIONS::selectColumns, tableCellSelection && EE_CONDITIONS::Idle, 2 );
303 menu.AddItem( ACTIONS::selectRows, tableCellSelection && EE_CONDITIONS::Idle, 2 );
304 menu.AddItem( ACTIONS::selectTable, tableCellSelection && EE_CONDITIONS::Idle, 2 );
305
306 menu.AddSeparator( 100 );
307 menu.AddItem( EE_ACTIONS::drawWire, schEditCondition && EE_CONDITIONS::Empty, 100 );
308 menu.AddItem( EE_ACTIONS::drawBus, schEditCondition && EE_CONDITIONS::Empty, 100 );
309
310 menu.AddSeparator( 100 );
311 menu.AddItem( ACTIONS::finishInteractive,
313
314 menu.AddItem( EE_ACTIONS::enterSheet, sheetSelection && EE_CONDITIONS::Idle, 150 );
315 menu.AddItem( EE_ACTIONS::selectOnPCB,
316 crossProbingSelection && EE_CONDITIONS::Idle, 150 );
317 menu.AddItem( EE_ACTIONS::leaveSheet, belowRootSheetCondition, 150 );
318
319 menu.AddSeparator( 200 );
320 menu.AddItem( EE_ACTIONS::placeJunction, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
321 menu.AddItem( EE_ACTIONS::placeLabel, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
322 menu.AddItem( EE_ACTIONS::placeClassLabel, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
323 menu.AddItem( EE_ACTIONS::placeGlobalLabel, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
324 menu.AddItem( EE_ACTIONS::placeHierLabel, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
325 menu.AddItem( EE_ACTIONS::breakWire, linesSelection && EE_CONDITIONS::Idle, 250 );
326 menu.AddItem( EE_ACTIONS::slice, linesSelection && EE_CONDITIONS::Idle, 250 );
327 menu.AddItem( EE_ACTIONS::placeSheetPin, sheetSelection && EE_CONDITIONS::Idle, 250 );
328 menu.AddItem( EE_ACTIONS::syncSheetPins, sheetSelection && EE_CONDITIONS::Idle, 250 );
329 menu.AddItem( EE_ACTIONS::assignNetclass, connectedSelection && EE_CONDITIONS::Idle, 250 );
330 menu.AddItem( EE_ACTIONS::editPageNumber, schEditSheetPageNumberCondition, 250 );
331
332 menu.AddSeparator( 400 );
333 menu.AddItem( EE_ACTIONS::symbolProperties, haveSymbol && EE_CONDITIONS::Empty, 400 );
334 menu.AddItem( EE_ACTIONS::pinTable, haveSymbol && EE_CONDITIONS::Empty, 400 );
335 menu.AddItem( EE_ACTIONS::setUnitDisplayName,
336 haveSymbol && symbolDisplayNameIsEditable && EE_CONDITIONS::Empty, 400 );
337
338 menu.AddSeparator( 1000 );
340
341 m_disambiguateTimer.SetOwner( this );
342 Connect( wxEVT_TIMER, wxTimerEventHandler( EE_SELECTION_TOOL::onDisambiguationExpire ),
343 nullptr, this );
344
345 return true;
346}
347
348
350{
351 m_frame = getEditFrame<SCH_BASE_FRAME>();
352
353 if( aReason != TOOL_BASE::REDRAW )
354 {
355 // Remove pointers to the selected items from containers without changing their
356 // properties (as they are already deleted while a new sheet is loaded)
358 }
359
360 if( aReason == RESET_REASON::SHUTDOWN )
361 return;
362
363 if( aReason == TOOL_BASE::MODEL_RELOAD || aReason == TOOL_BASE::SUPERMODEL_RELOAD )
364 {
365 getView()->GetPainter()->GetSettings()->SetHighlight( false );
366
367 SYMBOL_EDIT_FRAME* symbolEditFrame = dynamic_cast<SYMBOL_EDIT_FRAME*>( m_frame );
368 SYMBOL_VIEWER_FRAME* symbolViewerFrame = dynamic_cast<SYMBOL_VIEWER_FRAME*>( m_frame );
369
370 if( symbolEditFrame )
371 {
372 m_isSymbolEditor = true;
373 m_unit = symbolEditFrame->GetUnit();
374 m_bodyStyle = symbolEditFrame->GetBodyStyle();
375 }
376 else
377 {
378 m_isSymbolViewer = symbolViewerFrame != nullptr;
379 }
380 }
381
382 // Reinsert the VIEW_GROUP, in case it was removed from the VIEW
384 getView()->Add( &m_selection );
385}
386
387
389{
390 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
391
392 KIID lastRolloverItem = niluuid;
394
395 auto pinOrientation =
396 []( EDA_ITEM* aItem )
397 {
398 SCH_PIN* pin = dynamic_cast<SCH_PIN*>( aItem );
399
400 if( pin )
401 {
402 const SCH_SYMBOL* parent = dynamic_cast<const SCH_SYMBOL*>( pin->GetParentSymbol() );
403
404 if( !parent )
405 return pin->GetOrientation();
406 else
407 {
408 SCH_PIN dummy( *pin );
410 return dummy.GetOrientation();
411 }
412 }
413
414 SCH_SHEET_PIN* sheetPin = dynamic_cast<SCH_SHEET_PIN*>( aItem );
415
416 if( sheetPin )
417 {
418 switch( sheetPin->GetSide() )
419 {
420 default:
421 case SHEET_SIDE::LEFT: return PIN_ORIENTATION::PIN_RIGHT;
422 case SHEET_SIDE::RIGHT: return PIN_ORIENTATION::PIN_LEFT;
423 case SHEET_SIDE::TOP: return PIN_ORIENTATION::PIN_DOWN;
424 case SHEET_SIDE::BOTTOM: return PIN_ORIENTATION::PIN_UP;
425 }
426 }
427
428 return PIN_ORIENTATION::PIN_LEFT;
429 };
430
431 // Main loop: keep receiving events
432 while( TOOL_EVENT* evt = Wait() )
433 {
434 bool selCancelled = false;
435 bool displayWireCursor = false;
436 bool displayBusCursor = false;
437 bool displayLineCursor = false;
438 KIID rolloverItem = lastRolloverItem;
439
440 // on left click, a selection is made, depending on modifiers ALT, SHIFT, CTRL:
441 setModifiersState( evt->Modifier( MD_SHIFT ), evt->Modifier( MD_CTRL ),
442 evt->Modifier( MD_ALT ) );
443
444 MOUSE_DRAG_ACTION drag_action = m_frame->GetDragAction();
445
446 if( evt->IsMouseDown( BUT_LEFT ) )
447 {
448 if( !m_frame->ToolStackIsEmpty() )
449 {
450 // Avoid triggering when running under other tools
451 }
454 {
455 // Distinguish point editor from selection modification by checking modifiers
456 if( hasModifier() )
457 {
459 m_disambiguateTimer.StartOnce( ADVANCED_CFG::GetCfg().m_DisambiguationMenuDelay );
460 }
461 }
462 else
463 {
465 m_disambiguateTimer.StartOnce( ADVANCED_CFG::GetCfg().m_DisambiguationMenuDelay );
466 }
467 }
468 // Single click? Select single object
469 else if( evt->IsClick( BUT_LEFT ) )
470 {
471 // If the timer has stopped, then we have already run the disambiguate routine
472 // and we don't want to register an extra click here
473 if( !m_disambiguateTimer.IsRunning() )
474 {
475 evt->SetPassEvent();
476 continue;
477 }
478
479 m_disambiguateTimer.Stop();
480
481 if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
482 schframe->FocusOnItem( nullptr );
483
484 // Collect items at the clicked location (doesn't select them yet)
485 EE_COLLECTOR collector;
486 CollectHits( collector, evt->Position() );
487 narrowSelection( collector, evt->Position(), false );
488
489 if( collector.GetCount() == 1 && !m_isSymbolEditor && !hasModifier() )
490 {
491 OPT_TOOL_EVENT autostart = autostartEvent( evt, grid, collector[0] );
492
493 if( autostart )
494 {
496
497 params->layer = autostart->Parameter<const DRAW_SEGMENT_EVENT_PARAMS*>()->layer;
498 params->quitOnDraw = true;
499 params->sourceSegment = dynamic_cast<SCH_LINE*>( collector[0] );
500
501 autostart->SetParameter<const DRAW_SEGMENT_EVENT_PARAMS*>( params );
502 m_toolMgr->ProcessEvent( *autostart );
503
504 selCancelled = true;
505 }
506 else if( collector[0]->IsHypertext() )
507 {
508 collector[ 0 ]->DoHypertextAction( m_frame );
509 selCancelled = true;
510 }
511 else if( collector[0]->IsBrightened() )
512 {
513 if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
514 {
515 NET_NAVIGATOR_ITEM_DATA itemData( schframe->GetCurrentSheet(),
516 collector[0] );
517
518 schframe->SelectNetNavigatorItem( &itemData );
519 }
520 }
521 }
522
523 if( !selCancelled )
524 {
525 selectPoint( collector, evt->Position(), nullptr, nullptr, m_additive,
527 m_selection.SetIsHover( false );
528 }
529 }
530 else if( evt->IsClick( BUT_RIGHT ) )
531 {
532 m_disambiguateTimer.Stop();
533
534 // right click? if there is any object - show the context menu
535 if( m_selection.Empty() )
536 {
538 SelectPoint( evt->Position(), { SCH_LOCATE_ANY_T }, nullptr, &selCancelled );
539 m_selection.SetIsHover( true );
540 }
541 // If the cursor has moved off the bounding box of the selection by more than
542 // a grid square, check to see if there is another item available for selection
543 // under the cursor. If there is, the user likely meant to get the context menu
544 // for that item. If there is no new item, then keep the original selection and
545 // show the context menu for it.
546 else if( !m_selection.GetBoundingBox().Inflate( grid.GetGrid().x, grid.GetGrid().y )
547 .Contains( evt->Position() ) )
548 {
549 EE_COLLECTOR collector;
550
551 if( CollectHits( collector, evt->Position(), { SCH_LOCATE_ANY_T } ) )
552 {
554
555 SelectPoint( evt->Position(), { SCH_LOCATE_ANY_T }, nullptr, &selCancelled );
556 m_selection.SetIsHover( true );
557 }
558 }
559
560 if( !selCancelled )
562 }
563 else if( evt->IsDblClick( BUT_LEFT ) )
564 {
565 m_disambiguateTimer.Stop();
566
567 // double click? Display the properties window
568 if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
569 schframe->FocusOnItem( nullptr );
570
571 if( m_selection.Empty() )
572 SelectPoint( evt->Position() );
573
574 EDA_ITEM* item = m_selection.Front();
575
576 if( item && item->Type() == SCH_SHEET_T )
578 else
580 }
581 else if( evt->IsDblClick( BUT_MIDDLE ) )
582 {
583 m_disambiguateTimer.Stop();
584
585 // Middle double click? Do zoom to fit or zoom to objects
586 if( evt->Modifier( MD_CTRL ) ) // Is CTRL key down?
588 else
590 }
591 else if( evt->IsDrag( BUT_LEFT ) )
592 {
593 m_disambiguateTimer.Stop();
594
595 // Is another tool already moving a new object? Don't allow a drag start
596 if( !m_selection.Empty() && m_selection[0]->HasFlag( IS_NEW | IS_MOVING ) )
597 {
598 evt->SetPassEvent();
599 continue;
600 }
601
602 // drag with LMB? Select multiple objects (or at least draw a selection box) or
603 // drag them
604 if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
605 schframe->FocusOnItem( nullptr );
606
607 EE_COLLECTOR collector;
608
609 if( CollectHits( collector, evt->DragOrigin(), { SCH_TABLECELL_T } ) )
610 {
611 selectTableCells( static_cast<SCH_TABLE*>( collector[0]->GetParent() ) );
612 }
613 else if( hasModifier() || drag_action == MOUSE_DRAG_ACTION::SELECT )
614 {
616 }
617 else if( m_selection.Empty() && drag_action != MOUSE_DRAG_ACTION::DRAG_ANY )
618 {
620 }
621 else
622 {
623 if( m_isSymbolEditor )
624 {
625 if( static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->IsSymbolAlias() )
626 {
628 }
629 else
630 {
634 SCH_PIN_T,
635 SCH_FIELD_T } );
636 }
637 }
638 else
639 {
641 }
642
643 // Check if dragging has started within any of selected items bounding box
644 if( selectionContains( evt->DragOrigin() ) )
645 {
646 // drag_is_move option exists only in schematic editor, not in symbol editor
647 // (m_frame->eeconfig() returns nullptr in Symbol Editor)
650 else
652 }
653 else
654 {
655 // No -> drag a selection box
657 }
658 }
659 }
660 else if( evt->IsMouseDown( BUT_AUX1 ) )
661 {
663 }
664 else if( evt->IsMouseDown( BUT_AUX2 ) )
665 {
667 }
668 else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CHOICE_MENU_CHOICE )
669 {
670 m_disambiguateTimer.Stop();
671
672 // context sub-menu selection? Handle unit selection or bus unfolding
673 if( *evt->GetCommandId() >= ID_POPUP_SCH_SELECT_UNIT
674 && *evt->GetCommandId() <= ID_POPUP_SCH_SELECT_UNIT_END )
675 {
676 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( m_selection.Front() );
677 int unit = *evt->GetCommandId() - ID_POPUP_SCH_SELECT_UNIT;
678
679 if( symbol )
680 static_cast<SCH_EDIT_FRAME*>( m_frame )->SelectUnit( symbol, unit );
681 }
682 else if( *evt->GetCommandId() >= ID_POPUP_SCH_ALT_PIN_FUNCTION
683 && *evt->GetCommandId() <= ID_POPUP_SCH_ALT_PIN_FUNCTION_END )
684 {
685 SCH_PIN* pin = dynamic_cast<SCH_PIN*>( m_selection.Front() );
686 wxString alt = *evt->Parameter<wxString*>();
687
688 if( pin )
689 static_cast<SCH_EDIT_FRAME*>( m_frame )->SetAltPinFunction( pin, alt );
690 }
691 else if( *evt->GetCommandId() >= ID_POPUP_SCH_PIN_TRICKS_START
692 && *evt->GetCommandId() <= ID_POPUP_SCH_PIN_TRICKS_END )
693 {
695 || m_selection.Empty() )
696 {
697 return 0;
698 }
699
700 // Keep track of new items so we make them the new selection at the end
701 EDA_ITEMS newItems;
702 SCH_COMMIT commit( static_cast<SCH_EDIT_FRAME*>( m_frame ) );
703
704 if( *evt->GetCommandId() == ID_POPUP_SCH_PIN_TRICKS_NO_CONNECT )
705 {
706 for( EDA_ITEM* item : m_selection )
707 {
708 SCH_NO_CONNECT* nc = new SCH_NO_CONNECT( item->GetPosition() );
709 commit.Add( nc, m_frame->GetScreen() );
710 newItems.push_back( nc );
711 }
712
713 commit.Push( wxS( "No Connect Pins" ) );
715 }
716 else if( *evt->GetCommandId() == ID_POPUP_SCH_PIN_TRICKS_WIRE )
717 {
718 VECTOR2I wireGrid = grid.GetGridSize( GRID_HELPER_GRIDS::GRID_WIRES );
719
720 for( EDA_ITEM* item : m_selection )
721 {
722 SCH_LINE* wire = new SCH_LINE( item->GetPosition(), LAYER_WIRE );
723
724 // Add some length to the wire as nothing in our code base handles
725 // 0 length wires very well, least of all the ortho drag algorithm
726 VECTOR2I stub;
727
728 switch( pinOrientation( item ) )
729 {
730 default:
731 case PIN_ORIENTATION::PIN_RIGHT:
732 stub = VECTOR2I( -1 * wireGrid.x, 0 );
733 break;
734 case PIN_ORIENTATION::PIN_LEFT:
735 stub = VECTOR2I( 1 * wireGrid.x, 0 );
736 break;
737 case PIN_ORIENTATION::PIN_UP:
738 stub = VECTOR2I( 0, 1 * wireGrid.y );
739 break;
740 case PIN_ORIENTATION::PIN_DOWN:
741 stub = VECTOR2I( 0, -1 * wireGrid.y );
742 break;
743 }
744
745 wire->SetEndPoint( item->GetPosition() + stub );
746
748 commit.Added( wire, m_frame->GetScreen() );
749 newItems.push_back( wire );
750 }
751
753 AddItemsToSel( &newItems );
754
755 // Select only the ends so we can immediately start dragging them
756 for( EDA_ITEM* item : newItems )
757 static_cast<SCH_LINE*>( item )->SetFlags( ENDPOINT );
758
759 // Put the mouse on the nearest point of the first wire
760 SCH_LINE* first = static_cast<SCH_LINE*>( newItems[0] );
762 getViewControls()->WarpMouseCursor( getViewControls()->GetCursorPosition(),
763 true );
764
765 // Start the drag tool, canceling will remove the wires
766 if( m_toolMgr->RunSynchronousAction( EE_ACTIONS::drag, &commit, false ) )
767 commit.Push( wxS( "Wire Pins" ) );
768 else
769 commit.Revert();
770 }
771 else
772 {
773 // For every pin in the selection, add a label according to menu item
774 // selected by the user
775 for( EDA_ITEM* item : m_selection )
776 {
777 SCH_PIN* pin = dynamic_cast<SCH_PIN*>( item );
778 SCH_SHEET_PIN* sheetPin = dynamic_cast<SCH_SHEET_PIN*>( item );
779 SCH_EDIT_FRAME* sf = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
780 SCH_LABEL_BASE* label = nullptr;
781
782 wxString labelText;
783
784 if( pin )
785 labelText = pin->GetShownName();
786 else if( sheetPin && sf )
787 labelText = sheetPin->GetShownText( &sf->GetCurrentSheet(), false );
788
789 switch( *evt->GetCommandId() )
790 {
792 label = new SCH_LABEL( item->GetPosition(), labelText );
793 break;
795 label = new SCH_HIERLABEL( item->GetPosition(), labelText );
796 break;
798 label = new SCH_GLOBALLABEL( item->GetPosition(), labelText );
799 break;
800 default: continue;
801 }
802
803 switch( pinOrientation( item ) )
804 {
805 default:
806 case PIN_ORIENTATION::PIN_RIGHT:
808 break;
809 case PIN_ORIENTATION::PIN_LEFT:
811 break;
812 case PIN_ORIENTATION::PIN_UP:
814 break;
815 case PIN_ORIENTATION::PIN_DOWN:
817 break;
818 }
819
820 ELECTRICAL_PINTYPE pinType = ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
821
822 if( pin )
823 {
824 pinType = pin->GetType();
825 }
826 else if( sheetPin )
827 {
828 switch( sheetPin->GetLabelShape() )
829 {
830 case LABEL_INPUT: pinType = ELECTRICAL_PINTYPE::PT_INPUT; break;
831 case LABEL_OUTPUT: pinType = ELECTRICAL_PINTYPE::PT_OUTPUT; break;
832 case LABEL_BIDI: pinType = ELECTRICAL_PINTYPE::PT_BIDI; break;
833 case LABEL_TRISTATE: pinType = ELECTRICAL_PINTYPE::PT_TRISTATE; break;
834 case LABEL_PASSIVE: pinType = ELECTRICAL_PINTYPE::PT_PASSIVE; break;
835 }
836 }
837
838 switch( pinType )
839 {
840 case ELECTRICAL_PINTYPE::PT_BIDI:
841 label->SetShape( LABEL_FLAG_SHAPE::L_BIDI );
842 break;
843 case ELECTRICAL_PINTYPE::PT_INPUT:
844 label->SetShape( LABEL_FLAG_SHAPE::L_INPUT );
845 break;
846 case ELECTRICAL_PINTYPE::PT_OUTPUT:
847 label->SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
848 break;
849 case ELECTRICAL_PINTYPE::PT_TRISTATE:
850 label->SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
851 break;
852 case ELECTRICAL_PINTYPE::PT_UNSPECIFIED:
853 label->SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
854 break;
855 default:
856 label->SetShape( LABEL_FLAG_SHAPE::L_INPUT );
857 }
858
859 commit.Add( label, m_frame->GetScreen() );
860 newItems.push_back( label );
861 }
862
863 commit.Push( wxS( "Label Pins" ) );
864
865 // Many users will want to drag these items to wire off of the pins, so
866 // pre-select them.
868 AddItemsToSel( &newItems );
869 }
870 }
871 else if( *evt->GetCommandId() >= ID_POPUP_SCH_UNFOLD_BUS
872 && *evt->GetCommandId() <= ID_POPUP_SCH_UNFOLD_BUS_END )
873 {
874 wxString* net = new wxString( *evt->Parameter<wxString*>() );
875 m_toolMgr->RunAction<wxString*>( EE_ACTIONS::unfoldBus, net );
876 }
877 }
878 else if( evt->IsCancelInteractive() )
879 {
880 m_disambiguateTimer.Stop();
881
882 // We didn't set these, but we have reports that they leak out of some other tools,
883 // so we clear them here.
884 getViewControls()->SetAutoPan( false );
885 getViewControls()->CaptureCursor( false );
886
887 if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
888 schframe->FocusOnItem( nullptr );
889
890 if( !GetSelection().Empty() )
891 {
893 }
894 else if( evt->FirstResponder() == this && evt->GetCommandId() == (int) WXK_ESCAPE )
895 {
897
899 editor->ClearHighlight( *evt );
900 }
901 }
902 else if( evt->Action() == TA_UNDO_REDO_PRE )
903 {
904 if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
905 schframe->FocusOnItem( nullptr );
906 }
907 else if( evt->IsMotion() && !m_isSymbolEditor && evt->FirstResponder() == this )
908 {
909 // Update cursor and rollover item
910 rolloverItem = niluuid;
911 EE_COLLECTOR collector;
912
914
915 if( CollectHits( collector, evt->Position() ) )
916 {
917 narrowSelection( collector, evt->Position(), false );
918
919 if( collector.GetCount() == 1 && !hasModifier() )
920 {
921 OPT_TOOL_EVENT autostartEvt = autostartEvent( evt, grid, collector[0] );
922
923 if( autostartEvt )
924 {
925 if( autostartEvt->Matches( EE_ACTIONS::drawBus.MakeEvent() ) )
926 displayBusCursor = true;
927 else if( autostartEvt->Matches( EE_ACTIONS::drawWire.MakeEvent() ) )
928 displayWireCursor = true;
929 else if( autostartEvt->Matches( EE_ACTIONS::drawLines.MakeEvent() ) )
930 displayLineCursor = true;
931 }
932 else if( collector[0]->IsHypertext() && !collector[0]->IsSelected() )
933 {
934 rolloverItem = collector[0]->m_Uuid;
935 }
936 }
937 }
938 }
939 else
940 {
941 evt->SetPassEvent();
942 }
943
944 if( rolloverItem != lastRolloverItem )
945 {
946 if( EDA_ITEM* item = m_frame->GetItem( lastRolloverItem ) )
947 {
948 item->ClearFlags( IS_ROLLOVER );
949 lastRolloverItem = niluuid;
950
951 if( item->Type() == SCH_FIELD_T )
952 m_frame->GetCanvas()->GetView()->Update( item->GetParent() );
953 else
954 m_frame->GetCanvas()->GetView()->Update( item );
955 }
956 }
957
958 if( rolloverItem != niluuid )
959 {
960 EDA_ITEM* item = m_frame->GetItem( rolloverItem );
961
962 if( item && !( item->GetFlags() & IS_ROLLOVER ) )
963 {
964 item->SetFlags( IS_ROLLOVER );
965 lastRolloverItem = rolloverItem;
966
967 if( item->Type() == SCH_FIELD_T )
968 m_frame->GetCanvas()->GetView()->Update( item->GetParent() );
969 else
970 m_frame->GetCanvas()->GetView()->Update( item );
971 }
972 }
973
975 {
976 if( displayWireCursor )
977 {
978 m_nonModifiedCursor = KICURSOR::LINE_WIRE_ADD;
979 }
980 else if( displayBusCursor )
981 {
982 m_nonModifiedCursor = KICURSOR::LINE_BUS;
983 }
984 else if( displayLineCursor )
985 {
986 m_nonModifiedCursor = KICURSOR::LINE_GRAPHIC;
987 }
988 else if( rolloverItem != niluuid )
989 {
990 m_nonModifiedCursor = KICURSOR::HAND;
991 }
992 else if( !m_selection.Empty()
993 && drag_action == MOUSE_DRAG_ACTION::DRAG_SELECTED
994 && evt->HasPosition()
995 && selectionContains( evt->Position() ) ) //move/drag option prediction
996 {
997 m_nonModifiedCursor = KICURSOR::MOVING;
998 }
999 else
1000 {
1001 m_nonModifiedCursor = KICURSOR::ARROW;
1002 }
1003 }
1004 }
1005
1006 m_disambiguateTimer.Stop();
1007
1008 // Shutting down; clear the selection
1009 m_selection.Clear();
1010
1011 return 0;
1012}
1013
1014
1016 SCH_ITEM* aItem )
1017{
1018 VECTOR2I pos = aGrid.BestSnapAnchor( aEvent->Position(), aGrid.GetItemGrid( aItem ) );
1019
1022 && aItem->IsPointClickableAnchor( pos ) )
1023 {
1025
1026 if( aItem->Type() == SCH_BUS_BUS_ENTRY_T )
1027 {
1028 newEvt = EE_ACTIONS::drawBus.MakeEvent();
1029 }
1030 else if( aItem->Type() == SCH_BUS_WIRE_ENTRY_T )
1031 {
1032 SCH_BUS_WIRE_ENTRY* busEntry = static_cast<SCH_BUS_WIRE_ENTRY*>( aItem );
1033
1034 if( !busEntry->m_connected_bus_item )
1035 newEvt = EE_ACTIONS::drawBus.MakeEvent();
1036 }
1037 else if( aItem->Type() == SCH_LINE_T )
1038 {
1039 SCH_LINE* line = static_cast<SCH_LINE*>( aItem );
1040
1041 if( line->IsBus() )
1042 newEvt = EE_ACTIONS::drawBus.MakeEvent();
1043 else if( line->IsGraphicLine() )
1044 newEvt = EE_ACTIONS::drawLines.MakeEvent();
1045 }
1046 else if( aItem->Type() == SCH_LABEL_T || aItem->Type() == SCH_HIER_LABEL_T
1047 || aItem->Type() == SCH_SHEET_PIN_T )
1048 {
1049 SCH_LABEL_BASE* label = static_cast<SCH_LABEL_BASE*>( aItem );
1050 SCH_CONNECTION possibleConnection( label->Schematic()->ConnectionGraph() );
1051 possibleConnection.ConfigureFromLabel( label->GetShownText( false ) );
1052
1053 if( possibleConnection.IsBus() )
1054 newEvt = EE_ACTIONS::drawBus.MakeEvent();
1055 }
1056 else if( aItem->Type() == SCH_SYMBOL_T )
1057 {
1058 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( aItem );
1059
1060 wxCHECK( symbol, OPT_TOOL_EVENT() );
1061
1062 const SCH_PIN* pin = symbol->GetPin( pos );
1063
1064 wxCHECK( pin, OPT_TOOL_EVENT() );
1065
1066 if( !pin->IsVisible()
1069 {
1070 return OPT_TOOL_EVENT();
1071 }
1072 }
1073
1074 newEvt->SetMousePosition( pos );
1075 newEvt->SetHasPosition( true );
1076 newEvt->SetForceImmediate( true );
1077
1078 getViewControls()->ForceCursorPosition( true, pos );
1079
1080 return newEvt;
1081 }
1082
1083 return OPT_TOOL_EVENT();
1084}
1085
1086
1088{
1089 wxMouseState keyboardState = wxGetMouseState();
1090
1091 setModifiersState( keyboardState.ShiftDown(), keyboardState.ControlDown(),
1092 keyboardState.AltDown() );
1093
1094 m_skip_heuristics = true;
1097 m_skip_heuristics = false;
1098
1099 return 0;
1100}
1101
1102
1103void EE_SELECTION_TOOL::OnIdle( wxIdleEvent& aEvent )
1104{
1106 {
1107 wxMouseState keyboardState = wxGetMouseState();
1108
1109 setModifiersState( keyboardState.ShiftDown(), keyboardState.ControlDown(),
1110 keyboardState.AltDown() );
1111
1112 if( m_additive )
1113 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ADD );
1114 else if( m_subtractive )
1115 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::SUBTRACT );
1116 else if( m_exclusive_or )
1117 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::XOR );
1118 else
1120 }
1121}
1122
1123
1125{
1126 return m_selection;
1127}
1128
1129
1131 const std::vector<KICAD_T>& aScanTypes )
1132{
1133 int pixelThreshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
1134 int gridThreshold = KiROUND( getView()->GetGAL()->GetGridSize().EuclideanNorm() / 2 );
1135 aCollector.m_Threshold = std::max( pixelThreshold, gridThreshold );
1137
1138 if( m_isSymbolEditor )
1139 {
1140 LIB_SYMBOL* symbol = static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->GetCurSymbol();
1141
1142 if( !symbol )
1143 return false;
1144
1145 aCollector.Collect( symbol->GetDrawItems(), aScanTypes, aWhere, m_unit, m_bodyStyle );
1146 }
1147 else
1148 {
1149 aCollector.Collect( m_frame->GetScreen(), aScanTypes, aWhere, m_unit, m_bodyStyle );
1150
1151 // If pins are disabled in the filter, they will be removed later. Let's add the parent
1152 // so that people can use pins to select symbols in this case.
1153 if( !m_filter.pins )
1154 {
1155 int originalCount = aCollector.GetCount();
1156
1157 for( int ii = 0; ii < originalCount; ++ii )
1158 {
1159 if( aCollector[ii]->Type() == SCH_PIN_T )
1160 {
1161 SCH_PIN* pin = static_cast<SCH_PIN*>( aCollector[ii] );
1162
1163 if( !aCollector.HasItem( pin->GetParentSymbol() ) )
1164 aCollector.Append( pin->GetParentSymbol() );
1165 }
1166 }
1167 }
1168 }
1169
1170 return aCollector.GetCount() > 0;
1171}
1172
1173
1175 bool aCheckLocked, bool aSelectedOnly )
1176{
1177 SYMBOL_EDIT_FRAME* symbolEditorFrame = dynamic_cast<SYMBOL_EDIT_FRAME*>( m_frame );
1178
1179 for( int i = collector.GetCount() - 1; i >= 0; --i )
1180 {
1181 if( symbolEditorFrame )
1182 {
1183 // Do not select invisible items if they are not displayed
1184 EDA_ITEM* item = collector[i];
1185
1186 if( item->Type() == SCH_FIELD_T )
1187 {
1188 if( !static_cast<SCH_FIELD*>( item )->IsVisible()
1189 && !symbolEditorFrame->GetShowInvisibleFields() )
1190 {
1191 collector.Remove( i );
1192 continue;
1193 }
1194 }
1195 else if( item->Type() == SCH_PIN_T )
1196 {
1197 if( !static_cast<SCH_PIN*>( item )->IsVisible()
1198 && !symbolEditorFrame->GetShowInvisiblePins() )
1199 {
1200 collector.Remove( i );
1201 continue;
1202 }
1203 }
1204 }
1205
1206 if( !Selectable( collector[i], &aWhere ) )
1207 {
1208 collector.Remove( i );
1209 continue;
1210 }
1211
1212 if( aCheckLocked && collector[i]->IsLocked() )
1213 {
1214 collector.Remove( i );
1215 continue;
1216 }
1217
1218 if( !itemPassesFilter( collector[i] ) )
1219 {
1220 collector.Remove( i );
1221 continue;
1222 }
1223
1224 if( aSelectedOnly && !collector[i]->IsSelected() )
1225 {
1226 collector.Remove( i );
1227 continue;
1228 }
1229 }
1230
1231 // Apply some ugly heuristics to avoid disambiguation menus whenever possible
1232 if( collector.GetCount() > 1 && !m_skip_heuristics )
1233 GuessSelectionCandidates( collector, aWhere );
1234}
1235
1236
1238 EDA_ITEM** aItem, bool* aSelectionCancelledFlag, bool aAdd,
1239 bool aSubtract, bool aExclusiveOr )
1240{
1242
1243 // If still more than one item we're going to have to ask the user.
1244 if( aCollector.GetCount() > 1 )
1245 {
1246 // Try to call selectionMenu via RunAction() to avoid event-loop contention
1247 // But it we cannot handle the event, then we don't have an active tool loop, so
1248 // handle it directly.
1249 if( !m_toolMgr->RunAction<COLLECTOR*>( EE_ACTIONS::selectionMenu, &aCollector ) )
1250 {
1251 if( !doSelectionMenu( &aCollector ) )
1252 aCollector.m_MenuCancelled = true;
1253 }
1254
1255 if( aCollector.m_MenuCancelled )
1256 {
1257 if( aSelectionCancelledFlag )
1258 *aSelectionCancelledFlag = true;
1259
1260 return false;
1261 }
1262 }
1263
1264 if( !aAdd && !aSubtract && !aExclusiveOr )
1266
1267 int addedCount = 0;
1268 bool anySubtracted = false;
1269
1270 if( aCollector.GetCount() > 0 )
1271 {
1272 for( int i = 0; i < aCollector.GetCount(); ++i )
1273 {
1274 EDA_ITEM_FLAGS flags = 0;
1275 bool isLine = aCollector[i]->Type() == SCH_LINE_T;
1276
1277 // Handle line ends specially
1278 if( isLine )
1279 {
1280 SCH_LINE* line = (SCH_LINE*) aCollector[i];
1281
1282 if( line->GetStartPoint().Distance( aWhere ) <= aCollector.m_Threshold )
1283 flags = STARTPOINT;
1284 else if( line->GetEndPoint().Distance( aWhere ) <= aCollector.m_Threshold )
1285 flags = ENDPOINT;
1286 else
1287 flags = STARTPOINT | ENDPOINT;
1288 }
1289
1290 if( aSubtract
1291 || ( aExclusiveOr && aCollector[i]->IsSelected()
1292 && ( !isLine || ( isLine && aCollector[i]->HasFlag( flags ) ) ) ) )
1293 {
1294 aCollector[i]->ClearFlags( flags );
1295
1296 // Need to update end shadows after ctrl-click unselecting one of two selected
1297 // endpoints.
1298 if( isLine )
1299 getView()->Update( aCollector[i] );
1300
1301 if( !aCollector[i]->HasFlag( STARTPOINT ) && !aCollector[i]->HasFlag( ENDPOINT ) )
1302 {
1303 unselect( aCollector[i] );
1304 anySubtracted = true;
1305 }
1306 }
1307 else
1308 {
1309 aCollector[i]->SetFlags( flags );
1310 select( aCollector[i] );
1311 addedCount++;
1312 }
1313 }
1314 }
1315
1316 if( addedCount == 1 )
1317 {
1319
1320 if( aItem && aCollector.GetCount() == 1 )
1321 *aItem = aCollector[0];
1322
1323 return true;
1324 }
1325 else if( addedCount > 1 )
1326 {
1328 return true;
1329 }
1330 else if( anySubtracted )
1331 {
1333 return true;
1334 }
1335
1336 return false;
1337}
1338
1339
1341 const std::vector<KICAD_T>& aScanTypes,
1342 EDA_ITEM** aItem, bool* aSelectionCancelledFlag,
1343 bool aCheckLocked, bool aAdd, bool aSubtract,
1344 bool aExclusiveOr )
1345{
1346 EE_COLLECTOR collector;
1347
1348 if( !CollectHits( collector, aWhere, aScanTypes ) )
1349 return false;
1350
1351 narrowSelection( collector, aWhere, aCheckLocked, aSubtract );
1352
1353 return selectPoint( collector, aWhere, aItem, aSelectionCancelledFlag, aAdd, aSubtract,
1354 aExclusiveOr );
1355}
1356
1357
1359{
1360 m_multiple = true; // Multiple selection mode is active
1361 KIGFX::VIEW* view = getView();
1362
1363 // hold all visible items
1364 std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
1365 std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> sheetPins;
1366
1367 // Filter the view items based on the selection box
1368 BOX2I selectionBox;
1369
1370 selectionBox.SetMaximum();
1371 view->Query( selectionBox, selectedItems ); // Get the list of selected items
1372
1373 // Sheet pins aren't in the view; add them by hand
1374 for( KIGFX::VIEW::LAYER_ITEM_PAIR& pair : selectedItems )
1375 {
1376 SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( pair.first );
1377
1378 if( sheet )
1379 {
1380 int layer = pair.second;
1381
1382 for( SCH_SHEET_PIN* pin : sheet->GetPins() )
1383 sheetPins.emplace_back( KIGFX::VIEW::LAYER_ITEM_PAIR( pin, layer ) );
1384 }
1385 }
1386
1387 selectedItems.insert( selectedItems.end(), sheetPins.begin(), sheetPins.end() );
1388
1389 for( const std::pair<KIGFX::VIEW_ITEM*, int>& item_pair : selectedItems )
1390 {
1391 if( EDA_ITEM* item = dynamic_cast<EDA_ITEM*>( item_pair.first ) )
1392 {
1393 if( Selectable( item ) && itemPassesFilter( item ) )
1394 {
1395 if( item->Type() == SCH_LINE_T )
1396 item->SetFlags( STARTPOINT | ENDPOINT );
1397
1398 select( item );
1399 }
1400 }
1401 }
1402
1403 m_multiple = false;
1404
1406
1407 return 0;
1408}
1409
1411{
1412 m_multiple = true; // Multiple selection mode is active
1413 KIGFX::VIEW* view = getView();
1414
1415 // hold all visible items
1416 std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
1417
1418 // Filter the view items based on the selection box
1419 BOX2I selectionBox;
1420
1421 selectionBox.SetMaximum();
1422 view->Query( selectionBox, selectedItems ); // Get the list of selected items
1423
1424 for( KIGFX::VIEW::LAYER_ITEM_PAIR& pair : selectedItems )
1425 {
1426 SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( pair.first );
1427
1428 if( sheet )
1429 {
1430 for( SCH_SHEET_PIN* pin : sheet->GetPins() )
1431 {
1432 EDA_ITEM* item = dynamic_cast<EDA_ITEM*>( pin );
1433
1434 if( item && Selectable( item ) )
1435 unselect( item );
1436 }
1437 }
1438
1439 if( EDA_ITEM* item = dynamic_cast<EDA_ITEM*>( pair.first ) )
1440 {
1441 if( Selectable( item ) )
1442 unselect( item );
1443 }
1444 }
1445
1446 m_multiple = false;
1447
1449
1450 return 0;
1451}
1452
1453
1455{
1456 // Prefer exact hits to sloppy ones
1457 std::set<EDA_ITEM*> exactHits;
1458
1459 for( int i = collector.GetCount() - 1; i >= 0; --i )
1460 {
1461 EDA_ITEM* item = collector[ i ];
1462 SCH_LINE* line = dynamic_cast<SCH_LINE*>( item );
1463 SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( item );
1464 SCH_TABLE* table = dynamic_cast<SCH_TABLE*>( item );
1465
1466 // Lines are hard to hit. Give them a bit more slop to still be considered "exact".
1467 if( line || ( shape && shape->GetShape() == SHAPE_T::POLY )
1468 || ( shape && shape->GetShape() == SHAPE_T::ARC ) )
1469 {
1470 int pixelThreshold = KiROUND( getView()->ToWorld( 6 ) );
1471
1472 if( item->HitTest( aPos, pixelThreshold ) )
1473 exactHits.insert( item );
1474 }
1475 else if( table )
1476 {
1477 // Consider table cells exact, but not the table itself
1478 }
1479 else
1480 {
1481
1483 item->SetFlags( SHOW_ELEC_TYPE );
1484
1485 if( item->HitTest( aPos, 0 ) )
1486 exactHits.insert( item );
1487
1488 item->ClearFlags( SHOW_ELEC_TYPE );
1489 }
1490 }
1491
1492 if( exactHits.size() > 0 && exactHits.size() < (unsigned) collector.GetCount() )
1493 {
1494 for( int i = collector.GetCount() - 1; i >= 0; --i )
1495 {
1496 EDA_ITEM* item = collector[ i ];
1497
1498 if( !exactHits.contains( item ) )
1499 collector.Transfer( item );
1500 }
1501 }
1502
1503 // Find the closest item. (Note that at this point all hits are either exact or non-exact.)
1504 SEG poss( aPos, aPos );
1505 EDA_ITEM* closest = nullptr;
1506 int closestDist = INT_MAX / 4;
1507
1508 for( EDA_ITEM* item : collector )
1509 {
1510 BOX2I bbox = item->GetBoundingBox();
1511 int dist = INT_MAX / 4;
1512
1513 // A dominating item is one that would unfairly win distance tests
1514 // and mask out other items. For example, a filled rectangle "wins"
1515 // with a zero distance over anything inside it.
1516 bool dominating = false;
1517
1518 if( exactHits.contains( item ) )
1519 {
1520 if( item->Type() == SCH_PIN_T || item->Type() == SCH_JUNCTION_T )
1521 {
1522 closest = item;
1523 break;
1524 }
1525
1526 SCH_LINE* line = dynamic_cast<SCH_LINE*>( item );
1527 SCH_FIELD* field = dynamic_cast<SCH_FIELD*>( item );
1528 EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item );
1529 EDA_SHAPE* shape = dynamic_cast<EDA_SHAPE*>( item );
1530 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item );
1531
1532 if( line )
1533 {
1534 dist = line->GetSeg().Distance( aPos );
1535 }
1536 else if( field )
1537 {
1538 BOX2I box = field->GetBoundingBox();
1539 EDA_ANGLE orient = field->GetTextAngle();
1540
1541 if( field->GetParent() && field->GetParent()->Type() == SCH_SYMBOL_T )
1542 {
1543 if( static_cast<SCH_SYMBOL*>( field->GetParent() )->GetTransform().y1 )
1544 {
1545 if( orient.IsHorizontal() )
1546 orient = ANGLE_VERTICAL;
1547 else
1548 orient = ANGLE_HORIZONTAL;
1549 }
1550 }
1551
1552 field->GetEffectiveTextShape( false, box, orient )
1553 ->Collide( poss, INT_MAX / 4, &dist );
1554 }
1555 else if( text )
1556 {
1557 text->GetEffectiveTextShape( false )->Collide( poss, INT_MAX / 4, &dist );
1558 }
1559 else if( shape )
1560 {
1561 std::vector<SHAPE*> shapes = shape->MakeEffectiveShapes();
1562
1563 for( SHAPE* s : shapes )
1564 {
1565 int shapeDist = dist;
1566 s->Collide( poss, INT_MAX / 4, &shapeDist );
1567
1568 if( shapeDist < dist )
1569 dist = shapeDist;
1570
1571 delete s;
1572 }
1573
1574 // Filled shapes win hit tests anywhere inside them
1575 dominating = shape->IsFilled();
1576 }
1577 else if( symbol )
1578 {
1579 bbox = symbol->GetBodyBoundingBox();
1580
1581 SHAPE_RECT rect( bbox.GetPosition(), bbox.GetWidth(), bbox.GetHeight() );
1582
1583 if( bbox.Contains( aPos ) )
1584 dist = bbox.GetCenter().Distance( aPos );
1585 else
1586 rect.Collide( poss, closestDist, &dist );
1587 }
1588 else
1589 {
1590 dist = bbox.GetCenter().Distance( aPos );
1591 }
1592 }
1593 else
1594 {
1595 SHAPE_RECT rect( bbox.GetPosition(), bbox.GetWidth(), bbox.GetHeight() );
1596 rect.Collide( poss, collector.m_Threshold, &dist );
1597 }
1598
1599 // Don't promote dominating items to be the closest item
1600 // (they'll always win) - they'll still be available for selection, but they
1601 // won't boot out worthy competitors.
1602 if ( !dominating )
1603 {
1604 if( dist == closestDist )
1605 {
1606 if( item->GetParent() == closest )
1607 closest = item;
1608 }
1609 else if( dist < closestDist )
1610 {
1611 closestDist = dist;
1612 closest = item;
1613 }
1614 }
1615 }
1616
1617 // Construct a tight box (1/2 height and width) around the center of the closest item.
1618 // All items which exist at least partly outside this box have sufficient other areas
1619 // for selection and can be dropped.
1620 if( closest ) // Don't try and get a tight bbox if nothing is near the mouse pointer
1621 {
1622 BOX2I tightBox = closest->GetBoundingBox();
1623 tightBox.Inflate( -tightBox.GetWidth() / 4, -tightBox.GetHeight() / 4 );
1624
1625 for( int i = collector.GetCount() - 1; i >= 0; --i )
1626 {
1627 EDA_ITEM* item = collector[i];
1628
1629 if( item == closest )
1630 continue;
1631
1632 if( !item->HitTest( tightBox, true ) )
1633 collector.Transfer( item );
1634 }
1635 }
1636}
1637
1638
1639EE_SELECTION& EE_SELECTION_TOOL::RequestSelection( const std::vector<KICAD_T>& aScanTypes,
1640 bool aPromoteCellSelections )
1641{
1642 bool anyUnselected = false;
1643 bool anySelected = false;
1644
1645 if( m_selection.Empty() )
1646 {
1647 VECTOR2D cursorPos = getViewControls()->GetCursorPosition( true );
1648
1650 SelectPoint( cursorPos, aScanTypes );
1651 m_selection.SetIsHover( true );
1653 }
1654 else // Trim an existing selection by aFilterList
1655 {
1656 bool isMoving = false;
1657
1658 for( int i = (int) m_selection.GetSize() - 1; i >= 0; --i )
1659 {
1660 EDA_ITEM* item = (EDA_ITEM*) m_selection.GetItem( i );
1661 isMoving |= static_cast<SCH_ITEM*>( item )->IsMoving();
1662
1663 if( !item->IsType( aScanTypes ) )
1664 {
1665 unselect( item );
1666 anyUnselected = true;
1667 }
1668 }
1669
1670 if( !isMoving )
1672 }
1673
1674 if( aPromoteCellSelections )
1675 {
1676 std::set<EDA_ITEM*> parents;
1677
1678 for( int i = (int) m_selection.GetSize() - 1; i >= 0; --i )
1679 {
1680 EDA_ITEM* item = (EDA_ITEM*) m_selection.GetItem( i );
1681
1682 if( item->Type() == SCH_TABLECELL_T )
1683 {
1684 parents.insert( item->GetParent() );
1685 unselect( item );
1686 anyUnselected = true;
1687 }
1688 }
1689
1690 for( EDA_ITEM* parent : parents )
1691 {
1692 if( !parent->IsSelected() )
1693 {
1694 select( parent );
1695 anySelected = true;
1696 }
1697 }
1698 }
1699
1700 if( anyUnselected )
1702
1703 if( anySelected )
1705
1706 return m_selection;
1707}
1708
1709
1711{
1712 if( !aItem )
1713 return false;
1714
1715 // Locking is not yet exposed uniformly in the schematic
1716#if 0
1717 if( SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( aItem ) )
1718 {
1719 if( schItem->IsLocked() && !m_filter.lockedItems )
1720 return false;
1721 }
1722#endif
1723
1724 switch( aItem->Type() )
1725 {
1726 case SCH_SYMBOL_T:
1727 case SCH_SHEET_T:
1728 if( !m_filter.symbols )
1729 return false;
1730
1731 break;
1732
1733 case SCH_PIN_T:
1734 case SCH_SHEET_PIN_T:
1735 if( !m_filter.pins )
1736 return false;
1737
1738 break;
1739
1740 case SCH_LINE_T:
1741 {
1742 switch( static_cast<SCH_LINE*>( aItem )->GetLayer() )
1743 {
1744 case LAYER_WIRE:
1745 case LAYER_BUS:
1746 if( !m_filter.wires )
1747 return false;
1748
1749 break;
1750
1751 default:
1752 if( !m_filter.graphics )
1753 return false;
1754 }
1755
1756 break;
1757 }
1758
1759 case SCH_SHAPE_T:
1760 if( !m_filter.graphics )
1761 return false;
1762
1763 break;
1764
1765 case SCH_TEXT_T:
1766 case SCH_TEXTBOX_T:
1767 case SCH_TABLE_T:
1768 case SCH_TABLECELL_T:
1769 case SCH_FIELD_T:
1770 if( !m_filter.text )
1771 return false;
1772
1773 break;
1774
1775 case SCH_LABEL_T:
1776 case SCH_GLOBAL_LABEL_T:
1777 case SCH_HIER_LABEL_T:
1778 if( !m_filter.labels )
1779 return false;
1780
1781 break;
1782
1783 case SCH_BITMAP_T:
1784 if( !m_filter.images )
1785 return false;
1786
1787 break;
1788
1789 default:
1790 if( !m_filter.otherItems )
1791 return false;
1792
1793 break;
1794 }
1795
1796 return true;
1797}
1798
1799
1801{
1802 VECTOR2I refP( 0, 0 );
1803
1804 if( m_selection.Size() > 0 )
1805 refP = static_cast<SCH_ITEM*>( m_selection.GetTopLeftItem() )->GetPosition();
1806
1808}
1809
1810
1811// Some navigation actions are allowed in selectMultiple
1821 &ACTIONS::zoomFitObjects, nullptr };
1822
1823
1825{
1826 bool cancelled = false; // Was the tool canceled while it was running?
1827 m_multiple = true; // Multiple selection mode is active
1828 KIGFX::VIEW* view = getView();
1829
1831 view->Add( &area );
1832
1833 while( TOOL_EVENT* evt = Wait() )
1834 {
1835 int width = area.GetEnd().x - area.GetOrigin().x;
1836 int height = area.GetEnd().y - area.GetOrigin().y;
1837
1838 /* Selection mode depends on direction of drag-selection:
1839 * Left > Right : Select objects that are fully enclosed by selection
1840 * Right > Left : Select objects that are crossed by selection
1841 */
1842 bool isGreedy = width < 0;
1843
1844 if( view->IsMirroredX() )
1845 isGreedy = !isGreedy;
1846
1847 m_frame->GetCanvas()->SetCurrentCursor( isGreedy ? KICURSOR::SELECT_LASSO
1848 : KICURSOR::SELECT_WINDOW );
1849
1850 if( evt->IsCancelInteractive() || evt->IsActivate() )
1851 {
1852 cancelled = true;
1853 break;
1854 }
1855
1856 if( evt->IsDrag( BUT_LEFT ) )
1857 {
1860
1861 // Start drawing a selection box
1862 area.SetOrigin( evt->DragOrigin() );
1863 area.SetEnd( evt->Position() );
1866 area.SetExclusiveOr( false );
1867
1868 view->SetVisible( &area, true );
1869 view->Update( &area );
1870 getViewControls()->SetAutoPan( true );
1871 }
1872
1873 if( evt->IsMouseUp( BUT_LEFT ) )
1874 {
1875 getViewControls()->SetAutoPan( false );
1876
1877 // End drawing the selection box
1878 view->SetVisible( &area, false );
1879
1880 // Fetch items from the RTree that are in our area of interest
1881 std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> nearbyViewItems;
1882 view->Query( area.ViewBBox(), nearbyViewItems );
1883
1884 // Build lists of nearby items and their children
1885 std::unordered_set<EDA_ITEM*> nearbyItems;
1886 std::vector<EDA_ITEM*> nearbyChildren;
1887 std::vector<EDA_ITEM*> flaggedItems;
1888
1889 for( KIGFX::VIEW::LAYER_ITEM_PAIR& pair : nearbyViewItems )
1890 {
1891 if( EDA_ITEM* item = dynamic_cast<EDA_ITEM*>( pair.first ) )
1892 {
1893 if( nearbyItems.insert( item ).second )
1894 {
1895 item->ClearFlags( CANDIDATE );
1896
1897 if( SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( item ) )
1898 {
1899 sch_item->RunOnChildren(
1900 [&]( SCH_ITEM* aChild )
1901 {
1902 // Filter pins by unit
1903 if( SCH_PIN* pin = dynamic_cast<SCH_PIN*>( aChild ) )
1904 {
1905 int unit = pin->GetLibPin()->GetUnit();
1906
1907 if( unit && unit != pin->GetParentSymbol()->GetUnit() )
1908 return;
1909 }
1910
1911 nearbyChildren.push_back( aChild );
1912 } );
1913 }
1914 }
1915 }
1916 }
1917
1918 BOX2I selectionRect( area.GetOrigin(), VECTOR2I( width, height ) );
1919 selectionRect.Normalize();
1920
1921 bool anyAdded = false;
1922 bool anySubtracted = false;
1923
1924 auto selectItem =
1925 [&]( EDA_ITEM* aItem, EDA_ITEM_FLAGS flags )
1926 {
1927 if( m_subtractive || ( m_exclusive_or && aItem->IsSelected() ) )
1928 {
1929 if ( m_exclusive_or )
1930 aItem->XorFlags( flags );
1931 else
1932 aItem->ClearFlags( flags );
1933
1934 if( !aItem->HasFlag( STARTPOINT ) && !aItem->HasFlag( ENDPOINT ) )
1935 {
1936 unselect( aItem );
1937 anySubtracted = true;
1938 }
1939
1940 // We changed one line endpoint on a selected line,
1941 // update the view at least.
1942 if( flags && !anySubtracted )
1943 getView()->Update( aItem );
1944 }
1945 else
1946 {
1947 aItem->SetFlags( flags );
1948 select( aItem );
1949 anyAdded = true;
1950 }
1951 };
1952
1953 for( EDA_ITEM* item : nearbyItems )
1954 {
1955 bool selected = false;
1956 EDA_ITEM_FLAGS flags = 0;
1957
1959 item->SetFlags( SHOW_ELEC_TYPE );
1960
1961 if( Selectable( item ) && itemPassesFilter( item ) )
1962 {
1963 if( item->Type() == SCH_LINE_T )
1964 {
1965 SCH_LINE* line = static_cast<SCH_LINE*>( item );
1966
1967 if( ( isGreedy && line->HitTest( selectionRect, false ) )
1968 || ( selectionRect.Contains( line->GetEndPoint() )
1969 && selectionRect.Contains( line->GetStartPoint() ) ) )
1970 {
1971 selected = true;
1972 flags |= STARTPOINT | ENDPOINT;
1973 }
1974 else if( !isGreedy )
1975 {
1976 if( selectionRect.Contains( line->GetStartPoint() )
1977 && line->IsStartDangling() )
1978 {
1979 selected = true;
1980 flags |= STARTPOINT;
1981 }
1982
1983 if( selectionRect.Contains( line->GetEndPoint() )
1984 && line->IsEndDangling() )
1985 {
1986 selected = true;
1987 flags |= ENDPOINT;
1988 }
1989 }
1990 }
1991 else
1992 {
1993 selected = item->HitTest( selectionRect, !isGreedy );
1994 }
1995 }
1996
1997 if( selected )
1998 {
1999 item->SetFlags( CANDIDATE );
2000 flaggedItems.push_back( item );
2001 selectItem( item, flags );
2002 }
2003
2004 item->ClearFlags( SHOW_ELEC_TYPE );
2005 }
2006
2007 for( EDA_ITEM* item : nearbyChildren )
2008 {
2010 item->SetFlags( SHOW_ELEC_TYPE );
2011
2012 if( Selectable( item )
2013 && itemPassesFilter( item )
2014 && !item->GetParent()->HasFlag( CANDIDATE )
2015 && item->HitTest( selectionRect, !isGreedy ) )
2016 {
2017 selectItem( item, 0 );
2018 }
2019
2020 item->ClearFlags( SHOW_ELEC_TYPE );
2021 }
2022
2023 for( EDA_ITEM* item : flaggedItems )
2024 item->ClearFlags( CANDIDATE );
2025
2026 m_selection.SetIsHover( false );
2027
2028 // Inform other potentially interested tools
2029 if( anyAdded )
2031
2032 if( anySubtracted )
2034
2035 break; // Stop waiting for events
2036 }
2037
2038 // Allow some actions for navigation
2039 for( int i = 0; allowedActions[i]; ++i )
2040 {
2041 if( evt->IsAction( allowedActions[i] ) )
2042 {
2043 evt->SetPassEvent();
2044 break;
2045 }
2046 }
2047 }
2048
2049 getViewControls()->SetAutoPan( false );
2050
2051 // Stop drawing the selection box
2052 view->Remove( &area );
2053 m_multiple = false; // Multiple selection mode is inactive
2054
2055 if( !cancelled )
2057
2058 return cancelled;
2059}
2060
2061
2063{
2064 bool cancelled = false; // Was the tool canceled while it was running?
2065 m_multiple = true; // Multiple selection mode is active
2066
2067 for( SCH_TABLECELL* cell : aTable->GetCells() )
2068 {
2069 if( cell->IsSelected() )
2070 cell->SetFlags( CANDIDATE );
2071 else
2072 cell->ClearFlags( CANDIDATE );
2073 }
2074
2075 auto wasSelected =
2076 []( EDA_ITEM* aItem )
2077 {
2078 return ( aItem->GetFlags() & CANDIDATE ) > 0;
2079 };
2080
2081 while( TOOL_EVENT* evt = Wait() )
2082 {
2083 if( evt->IsCancelInteractive() || evt->IsActivate() )
2084 {
2085 cancelled = true;
2086 break;
2087 }
2088 else if( evt->IsDrag( BUT_LEFT ) )
2089 {
2090 getViewControls()->SetAutoPan( true );
2091
2092 BOX2I selectionRect( evt->DragOrigin(), evt->Position() - evt->DragOrigin() );
2093 selectionRect.Normalize();
2094
2095 for( SCH_TABLECELL* cell : aTable->GetCells() )
2096 {
2097 bool doSelect = false;
2098
2099 if( cell->HitTest( selectionRect, false ) )
2100 {
2101 if( m_subtractive )
2102 doSelect = false;
2103 else if( m_exclusive_or )
2104 doSelect = !wasSelected( cell );
2105 else
2106 doSelect = true;
2107 }
2108 else if( wasSelected( cell ) )
2109 {
2110 doSelect = m_additive || m_subtractive || m_exclusive_or;
2111 }
2112
2113 if( doSelect && !cell->IsSelected() )
2114 select( cell );
2115 else if( !doSelect && cell->IsSelected() )
2116 unselect( cell );
2117 }
2118 }
2119 else if( evt->IsMouseUp( BUT_LEFT ) )
2120 {
2121 m_selection.SetIsHover( false );
2122
2123 bool anyAdded = false;
2124 bool anySubtracted = false;
2125
2126 for( SCH_TABLECELL* cell : aTable->GetCells() )
2127 {
2128 if( cell->IsSelected() && !wasSelected( cell ) )
2129 anyAdded = true;
2130 else if( wasSelected( cell ) && !cell->IsSelected() )
2131 anySubtracted = true;
2132 }
2133
2134 // Inform other potentially interested tools
2135 if( anyAdded )
2137
2138 if( anySubtracted )
2140
2141 break; // Stop waiting for events
2142 }
2143 else
2144 {
2145 // Allow some actions for navigation
2146 for( int i = 0; allowedActions[i]; ++i )
2147 {
2148 if( evt->IsAction( allowedActions[i] ) )
2149 {
2150 evt->SetPassEvent();
2151 break;
2152 }
2153 }
2154 }
2155 }
2156
2157 getViewControls()->SetAutoPan( false );
2158
2159 m_multiple = false; // Multiple selection mode is inactive
2160
2161 if( !cancelled )
2163
2164 return cancelled;
2165}
2166
2167
2169{
2170 EE_COLLECTOR collector;
2171
2172 //TODO(snh): Reimplement after exposing KNN interface
2173 int pixelThreshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
2174 int gridThreshold = KiROUND( getView()->GetGAL()->GetGridSize().EuclideanNorm() );
2175 int thresholdMax = std::max( pixelThreshold, gridThreshold );
2176
2177 for( int threshold : { 0, thresholdMax/4, thresholdMax/2, thresholdMax } )
2178 {
2179 collector.m_Threshold = threshold;
2180 collector.Collect( m_frame->GetScreen(), connectedTypes, aPosition );
2181
2182 if( collector.GetCount() > 0 )
2183 break;
2184 }
2185
2186 return collector.GetCount() ? collector[ 0 ] : nullptr;
2187}
2188
2189
2191{
2192 VECTOR2I cursorPos = getViewControls()->GetCursorPosition( false );
2193
2194 SelectPoint( cursorPos, connectedTypes );
2195 return 0;
2196}
2197
2198
2200{
2203
2204 if( m_selection.Empty() )
2205 return 0;
2206
2207 unsigned done = false;
2208
2210
2211 for( EDA_ITEM* selItem : m_selection.GetItems() )
2212 {
2213 if( selItem->Type() != SCH_LINE_T )
2214 continue;
2215
2216 SCH_LINE* line = static_cast<SCH_LINE*>( selItem );
2217
2218 std::set<SCH_ITEM*> conns = m_frame->GetScreen()->MarkConnections( line, false );
2219 for( SCH_ITEM* item : conns )
2220 {
2221 if( item->IsType( { SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T,
2222 SCH_ITEM_LOCATE_GRAPHIC_LINE_T } )
2223 && !item->IsSelected() )
2224 {
2225 done = true;
2226 }
2227
2228 select( item );
2229 }
2230
2231 if( !done )
2232 {
2233 conns = m_frame->GetScreen()->MarkConnections( line, true );
2234
2235 for( SCH_ITEM* item : conns )
2236 select( item );
2237 }
2238 }
2239
2240 if( m_selection.GetSize() > 1 )
2242
2243 return 0;
2244}
2245
2246
2248{
2249 std::set<std::pair<SCH_TABLE*, int>> columns;
2250 bool added = false;
2251
2252 for( EDA_ITEM* item : m_selection )
2253 {
2254 if( SCH_TABLECELL* cell = dynamic_cast<SCH_TABLECELL*>( item ) )
2255 {
2256 SCH_TABLE* table = static_cast<SCH_TABLE*>( cell->GetParent() );
2257 columns.insert( std::make_pair( table, cell->GetColumn() ) );
2258 }
2259 }
2260
2261 for( auto& [ table, col ] : columns )
2262 {
2263 for( int row = 0; row < table->GetRowCount(); ++row )
2264 {
2265 SCH_TABLECELL* cell = table->GetCell( row, col );
2266
2267 if( !cell->IsSelected() )
2268 {
2269 select( table->GetCell( row, col ) );
2270 added = true;
2271 }
2272 }
2273 }
2274
2275 if( added )
2277
2278 return 0;
2279}
2280
2281
2283{
2284 std::set<std::pair<SCH_TABLE*, int>> rows;
2285 bool added = false;
2286
2287 for( EDA_ITEM* item : m_selection )
2288 {
2289 if( SCH_TABLECELL* cell = dynamic_cast<SCH_TABLECELL*>( item ) )
2290 {
2291 SCH_TABLE* table = static_cast<SCH_TABLE*>( cell->GetParent() );
2292 rows.insert( std::make_pair( table, cell->GetRow() ) );
2293 }
2294 }
2295
2296 for( auto& [ table, row ] : rows )
2297 {
2298 for( int col = 0; col < table->GetColCount(); ++col )
2299 {
2300 SCH_TABLECELL* cell = table->GetCell( row, col );
2301
2302 if( !cell->IsSelected() )
2303 {
2304 select( table->GetCell( row, col ) );
2305 added = true;
2306 }
2307 }
2308 }
2309
2310 if( added )
2312
2313 return 0;
2314}
2315
2316
2318{
2319 std::set<SCH_TABLE*> tables;
2320 bool added = false;
2321
2322 for( EDA_ITEM* item : m_selection )
2323 {
2324 if( SCH_TABLECELL* cell = dynamic_cast<SCH_TABLECELL*>( item ) )
2325 tables.insert( static_cast<SCH_TABLE*>( cell->GetParent() ) );
2326 }
2327
2329
2330 for( SCH_TABLE* table : tables )
2331 {
2332 if( !table->IsSelected() )
2333 {
2334 select( table );
2335 added = true;
2336 }
2337 }
2338
2339 if( added )
2341
2342 return 0;
2343}
2344
2345
2347{
2349 return 0;
2350}
2351
2352
2354{
2355 if( aBBox.GetWidth() == 0 )
2356 return;
2357
2358 BOX2I bbox = aBBox;
2359 bbox.Normalize();
2360
2361 VECTOR2I bbSize = bbox.Inflate( KiROUND( bbox.GetWidth() * 0.2f ) ).GetSize();
2362 VECTOR2D screenSize = getView()->GetViewport().GetSize();
2363
2364 // This code tries to come up with a zoom factor that doesn't simply zoom in to the cross
2365 // probed symbol, but instead shows a reasonable amount of the circuit around it to provide
2366 // context. This reduces the need to manually change the zoom because it's too close.
2367
2368 // Using the default text height as a constant to compare against, use the height of the
2369 // bounding box of visible items for a footprint to figure out if this is a big symbol (like
2370 // a processor) or a small symbol (like a resistor). This ratio is not useful by itself as a
2371 // scaling factor. It must be "bent" to provide good scaling at varying symbol sizes. Bigger
2372 // symbols need less scaling than small ones.
2373 double currTextHeight = schIUScale.MilsToIU( DEFAULT_TEXT_SIZE );
2374
2375 double compRatio = bbSize.y / currTextHeight; // Ratio of symbol to text height
2376 double compRatioBent = 1.0;
2377
2378 // LUT to scale zoom ratio to provide reasonable schematic context. Must work with symbols
2379 // of varying sizes (e.g. 0402 package and 200 pin BGA).
2380 // Each entry represents a compRatio (symbol height / default text height) and an amount to
2381 // scale by.
2382 std::vector<std::pair<double, double>> lut{ { 1.25, 16 },
2383 { 2.5, 12 },
2384 { 5, 8 },
2385 { 6, 6 },
2386 { 10, 4 },
2387 { 20, 2 },
2388 { 40, 1.5 },
2389 { 100, 1 } };
2390
2391 std::vector<std::pair<double, double>>::iterator it;
2392
2393 // Large symbol default is last LUT entry (1:1).
2394 compRatioBent = lut.back().second;
2395
2396 // Use LUT to do linear interpolation of "compRatio" within "first", then use that result to
2397 // linearly interpolate "second" which gives the scaling factor needed.
2398 if( compRatio >= lut.front().first )
2399 {
2400 for( it = lut.begin(); it < lut.end() - 1; ++it )
2401 {
2402 if( it->first <= compRatio && next( it )->first >= compRatio )
2403 {
2404 double diffx = compRatio - it->first;
2405 double diffn = next( it )->first - it->first;
2406
2407 compRatioBent = it->second + ( next( it )->second - it->second ) * diffx / diffn;
2408 break; // We have our interpolated value
2409 }
2410 }
2411 }
2412 else
2413 {
2414 compRatioBent = lut.front().second; // Small symbol default is first entry
2415 }
2416
2417 // This is similar to the original KiCad code that scaled the zoom to make sure symbols were
2418 // visible on screen. It's simply a ratio of screen size to symbol size, and its job is to
2419 // zoom in to make the component fullscreen. Earlier in the code the symbol BBox is given a
2420 // 20% margin to add some breathing room. We compare the height of this enlarged symbol bbox
2421 // to the default text height. If a symbol will end up with the sides clipped, we adjust
2422 // later to make sure it fits on screen.
2423 screenSize.x = std::max( 10.0, screenSize.x );
2424 screenSize.y = std::max( 10.0, screenSize.y );
2425 double ratio = std::max( -1.0, fabs( bbSize.y / screenSize.y ) );
2426
2427 // Original KiCad code for how much to scale the zoom
2428 double kicadRatio = std::max( fabs( bbSize.x / screenSize.x ),
2429 fabs( bbSize.y / screenSize.y ) );
2430
2431 // If the width of the part we're probing is bigger than what the screen width will be after
2432 // the zoom, then punt and use the KiCad zoom algorithm since it guarantees the part's width
2433 // will be encompassed within the screen.
2434 if( bbSize.x > screenSize.x * ratio * compRatioBent )
2435 {
2436 // Use standard KiCad zoom for parts too wide to fit on screen/
2437 ratio = kicadRatio;
2438 compRatioBent = 1.0; // Reset so we don't modify the "KiCad" ratio
2439 wxLogTrace( "CROSS_PROBE_SCALE",
2440 "Part TOO WIDE for screen. Using normal KiCad zoom ratio: %1.5f", ratio );
2441 }
2442
2443 // Now that "compRatioBent" holds our final scaling factor we apply it to the original
2444 // fullscreen zoom ratio to arrive at the final ratio itself.
2445 ratio *= compRatioBent;
2446
2447 bool alwaysZoom = false; // DEBUG - allows us to minimize zooming or not
2448
2449 // Try not to zoom on every cross-probe; it gets very noisy
2450 if( ( ratio < 0.5 || ratio > 1.0 ) || alwaysZoom )
2451 getView()->SetScale( getView()->GetScale() / ratio );
2452}
2453
2454
2455void EE_SELECTION_TOOL::SyncSelection( const std::optional<SCH_SHEET_PATH>& targetSheetPath,
2456 SCH_ITEM* focusItem, const std::vector<SCH_ITEM*>& items )
2457{
2458 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
2459
2460 if( !editFrame )
2461 return;
2462
2463 if( targetSheetPath && targetSheetPath != editFrame->Schematic().CurrentSheet() )
2464 {
2465 editFrame->Schematic().SetCurrentSheet( *targetSheetPath );
2466 editFrame->DisplayCurrentSheet();
2467 }
2468
2469 ClearSelection( items.size() > 0 ? true /*quiet mode*/ : false );
2470
2471 // Perform individual selection of each item before processing the event.
2472 for( SCH_ITEM* item : items )
2473 {
2474 SCH_ITEM* parent = dynamic_cast<SCH_ITEM*>( item->GetParent() );
2475
2476 // Make sure we only select items on the current screen
2477 if( m_frame->GetScreen()->CheckIfOnDrawList( item )
2478 || ( parent && m_frame->GetScreen()->CheckIfOnDrawList( parent ) ) )
2479 {
2480 select( item );
2481 }
2482 }
2483
2485
2486 if( bbox.GetWidth() != 0 && bbox.GetHeight() != 0 )
2487 {
2489 {
2491 ZoomFitCrossProbeBBox( bbox );
2492
2493 editFrame->FocusOnItem( focusItem );
2494
2495 if( !focusItem )
2496 editFrame->FocusOnLocation( bbox.Centre() );
2497 }
2498 }
2499
2500 if( m_selection.Size() > 0 )
2502}
2503
2504
2506{
2508
2509 if( m_isSymbolEditor )
2510 {
2511 LIB_SYMBOL* start = static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->GetCurSymbol();
2512
2513 for( SCH_ITEM& item : start->GetDrawItems() )
2514 {
2515 if( item.IsSelected() )
2516 select( &item );
2517 }
2518 }
2519 else
2520 {
2521 for( SCH_ITEM* item : m_frame->GetScreen()->Items() )
2522 {
2523 // If the field and symbol are selected, only use the symbol
2524 if( item->IsSelected() )
2525 {
2526 select( item );
2527 }
2528 else
2529 {
2530 item->RunOnChildren(
2531 [&]( SCH_ITEM* aChild )
2532 {
2533 if( aChild->IsSelected() )
2534 select( aChild );
2535 } );
2536 }
2537 }
2538 }
2539
2541
2542 // Inform other potentially interested tools
2544}
2545
2546
2547bool EE_SELECTION_TOOL::Selectable( const EDA_ITEM* aItem, const VECTOR2I* aPos,
2548 bool checkVisibilityOnly ) const
2549{
2550 // NOTE: in the future this is where Eeschema layer/itemtype visibility will be handled
2551
2552 SYMBOL_EDIT_FRAME* symEditFrame = dynamic_cast<SYMBOL_EDIT_FRAME*>( m_frame );
2553
2554 // Do not allow selection of anything except fields when the current symbol in the symbol
2555 // editor is a derived symbol.
2556 if( symEditFrame && symEditFrame->IsSymbolAlias() && aItem->Type() != SCH_FIELD_T )
2557 return false;
2558
2559 switch( aItem->Type() )
2560 {
2561 case SCH_PIN_T:
2562 {
2563 const SCH_PIN* pin = static_cast<const SCH_PIN*>( aItem );
2564
2565 if( symEditFrame )
2566 {
2567 if( pin->GetUnit() && pin->GetUnit() != symEditFrame->GetUnit() )
2568 return false;
2569
2570 if( pin->GetBodyStyle() && pin->GetBodyStyle() != symEditFrame->GetBodyStyle() )
2571 return false;
2572 }
2573
2574 if( !pin->IsVisible() && !m_frame->GetShowAllPins() )
2575 return false;
2576
2577 if( !m_filter.pins )
2578 {
2579 // Pin anchors have to be allowed for auto-starting wires.
2580 if( aPos )
2581 {
2583 GRID_HELPER_GRIDS pinGrid = grid.GetItemGrid( pin );
2584
2585 if( pin->IsPointClickableAnchor( grid.BestSnapAnchor( *aPos, pinGrid ) ) )
2586 return true;
2587 }
2588
2589 return false;
2590 }
2591
2592 break;
2593 }
2594
2597 return false;
2598
2599 break;
2600
2601 case LIB_SYMBOL_T: // In symbol_editor we do not want to select the symbol itself.
2602 return false;
2603
2604 case SCH_FIELD_T: // SCH_FIELD objects are not unit/body-style-specific.
2605 {
2606 const SCH_FIELD* field = static_cast<const SCH_FIELD*>( aItem );
2607
2608 if( !field->IsVisible() && !( symEditFrame && symEditFrame->GetShowInvisibleFields() ) )
2609 return false;
2610
2611 break;
2612 }
2613
2614 case SCH_SHAPE_T:
2615 case SCH_TEXT_T:
2616 case SCH_TEXTBOX_T:
2617 if( symEditFrame )
2618 {
2619 const SCH_ITEM* sch_item = static_cast<const SCH_ITEM*>( aItem );
2620
2621 if( sch_item->GetUnit() && sch_item->GetUnit() != symEditFrame->GetUnit() )
2622 return false;
2623
2624 if( sch_item->GetBodyStyle() && sch_item->GetBodyStyle() != symEditFrame->GetBodyStyle() )
2625 return false;
2626 }
2627
2628 break;
2629
2630 case SCH_MARKER_T: // Always selectable
2631 return true;
2632
2633 case SCH_TABLECELL_T:
2634 {
2635 const SCH_TABLECELL* cell = static_cast<const SCH_TABLECELL*>( aItem );
2636
2637 if( cell->GetColSpan() == 0 || cell->GetRowSpan() == 0 )
2638 return false;
2639
2640 break;
2641 }
2642
2643 default: // Suppress warnings
2644 break;
2645 }
2646
2647 return true;
2648}
2649
2650
2652{
2653 if( m_selection.Empty() )
2654 return;
2655
2656 while( m_selection.GetSize() )
2658
2659 getView()->Update( &m_selection );
2660
2661 m_selection.SetIsHover( false );
2663
2664 // Inform other potentially interested tools
2665 if( !aQuietMode )
2667}
2668
2669
2671{
2672 highlight( aItem, SELECTED, &m_selection );
2673}
2674
2675
2677{
2678 unhighlight( aItem, SELECTED, &m_selection );
2679}
2680
2681
2682void EE_SELECTION_TOOL::highlight( EDA_ITEM* aItem, int aMode, SELECTION* aGroup )
2683{
2684 if( aMode == SELECTED )
2685 aItem->SetSelected();
2686 else if( aMode == BRIGHTENED )
2687 aItem->SetBrightened();
2688
2689 if( aGroup )
2690 aGroup->Add( aItem );
2691
2692 // Highlight pins and fields. (All the other symbol children are currently only
2693 // represented in the LIB_SYMBOL and will inherit the settings of the parent symbol.)
2694 if( SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( aItem ) )
2695 {
2696 sch_item->RunOnChildren(
2697 [&]( SCH_ITEM* aChild )
2698 {
2699 if( aMode == SELECTED )
2700 {
2701 aChild->SetSelected();
2702 getView()->Hide( aChild, true );
2703 }
2704 else if( aMode == BRIGHTENED )
2705 {
2706 aChild->SetBrightened();
2707 }
2708 } );
2709 }
2710
2711 if( aGroup && aMode != BRIGHTENED )
2712 getView()->Hide( aItem, true );
2713
2714 if( aItem->GetParent() && aItem->GetParent()->Type() != SCHEMATIC_T )
2715 getView()->Update( aItem->GetParent(), KIGFX::REPAINT );
2716
2717 getView()->Update( aItem, KIGFX::REPAINT );
2718}
2719
2720
2721void EE_SELECTION_TOOL::unhighlight( EDA_ITEM* aItem, int aMode, SELECTION* aGroup )
2722{
2723 if( aMode == SELECTED )
2724 {
2725 aItem->ClearSelected();
2726 // Lines need endpoints cleared here
2727 if( aItem->Type() == SCH_LINE_T )
2728 aItem->ClearFlags( STARTPOINT | ENDPOINT );
2729
2730 if( aMode != BRIGHTENED )
2731 getView()->Hide( aItem, false );
2732 }
2733 else if( aMode == BRIGHTENED )
2734 {
2735 aItem->ClearBrightened();
2736 }
2737
2738 if( aGroup )
2739 aGroup->Remove( aItem );
2740
2741 // Unhighlight pins and fields. (All the other symbol children are currently only
2742 // represented in the LIB_SYMBOL.)
2743 if( SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( aItem ) )
2744 {
2745 sch_item->RunOnChildren(
2746 [&]( SCH_ITEM* aChild )
2747 {
2748 if( aMode == SELECTED )
2749 {
2750 aChild->ClearSelected();
2751 getView()->Hide( aChild, false );
2752 }
2753 else if( aMode == BRIGHTENED )
2754 {
2755 aChild->ClearBrightened();
2756 }
2757
2758 if( aGroup )
2759 aGroup->Remove( aChild );
2760 } );
2761 }
2762
2763 if( aItem->GetParent() && aItem->GetParent()->Type() != SCHEMATIC_T )
2764 getView()->Update( aItem->GetParent(), KIGFX::REPAINT );
2765
2766 getView()->Update( aItem, KIGFX::REPAINT );
2767}
2768
2769
2771{
2772 const unsigned GRIP_MARGIN = 20;
2773 int margin = KiROUND( getView()->ToWorld( GRIP_MARGIN ) );
2774
2775 // Check if the point is located within any of the currently selected items bounding boxes
2776 for( EDA_ITEM* item : m_selection )
2777 {
2778 BOX2I itemBox = item->ViewBBox();
2779 itemBox.Inflate( margin ); // Give some margin for gripping an item
2780
2781 if( itemBox.Contains( aPoint ) )
2782 return true;
2783 }
2784
2785 return false;
2786}
2787
2788
2790{
2792
2799
2801
2807
2810
2812}
2813
2814
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:110
static TOOL_ACTION unselectAll
Definition: actions.h:75
static TOOL_ACTION cursorLeft
Definition: actions.h:151
static TOOL_ACTION zoomOutCenter
Definition: actions.h:120
static TOOL_ACTION zoomIn
Definition: actions.h:117
static TOOL_ACTION cursorLeftFast
Definition: actions.h:156
static TOOL_ACTION selectColumns
Definition: actions.h:87
static TOOL_ACTION cursorDown
Definition: actions.h:150
static TOOL_ACTION zoomOut
Definition: actions.h:118
static TOOL_ACTION cursorRightFast
Definition: actions.h:157
static TOOL_ACTION zoomCenter
Definition: actions.h:125
static TOOL_ACTION panDown
Definition: actions.h:164
static TOOL_ACTION cursorDownFast
Definition: actions.h:155
static TOOL_ACTION selectRows
Definition: actions.h:86
static TOOL_ACTION cursorUpFast
Definition: actions.h:154
static TOOL_ACTION panLeft
Definition: actions.h:165
static TOOL_ACTION updateMenu
Definition: actions.h:209
static TOOL_ACTION zoomFitScreen
Definition: actions.h:126
static TOOL_ACTION panUp
Definition: actions.h:163
static TOOL_ACTION zoomFitObjects
Definition: actions.h:127
static TOOL_ACTION zoomInCenter
Definition: actions.h:119
static TOOL_ACTION panRight
Definition: actions.h:166
static TOOL_ACTION selectTable
Definition: actions.h:88
static TOOL_ACTION cursorUp
Cursor control with keyboard.
Definition: actions.h:149
static TOOL_ACTION finishInteractive
Definition: actions.h:66
static TOOL_ACTION cursorRight
Definition: actions.h:152
static TOOL_ACTION selectAll
Definition: actions.h:74
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:158
BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition: box2.h:136
const Vec & GetPosition() const
Definition: box2.h:201
void SetMaximum()
Definition: box2.h:70
const SizeVec & GetSize() const
Definition: box2.h:196
size_type GetHeight() const
Definition: box2.h:205
const Vec GetCenter() const
Definition: box2.h:220
size_type GetWidth() const
Definition: box2.h:204
bool Contains(const Vec &aPoint) const
Definition: box2.h:158
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:541
Vec Centre() const
Definition: box2.h:87
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:86
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been added.
Definition: commit.h:80
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:138
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:89
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:127
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
void ClearSelected()
Definition: eda_item.h:122
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:129
bool IsSelected() const
Definition: eda_item.h:110
void SetSelected()
Definition: eda_item.h:119
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition: eda_item.h:176
void ClearBrightened()
Definition: eda_item.h:123
void SetBrightened()
Definition: eda_item.h:120
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:216
EDA_ITEM * GetParent() const
Definition: eda_item.h:103
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition: eda_item.h:131
void XorFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:128
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:130
virtual std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const
Make a set of SHAPE objects representing the EDA_SHAPE.
Definition: eda_shape.h:319
bool IsFilled() const
Definition: eda_shape.h:91
SHAPE_T GetShape() const
Definition: eda_shape.h:125
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:79
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:130
virtual bool IsVisible() const
Definition: eda_text.h:147
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:983
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:292
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:221
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:222
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 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 placeSheetPin
Definition: ee_actions.h:92
static TOOL_ACTION drawLines
Definition: ee_actions.h:103
static TOOL_ACTION syncSheetPins
Definition: ee_actions.h:94
static TOOL_ACTION selectOnPCB
Definition: ee_actions.h:246
static TOOL_ACTION leaveSheet
Definition: ee_actions.h:219
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:218
static TOOL_ACTION setUnitDisplayName
Definition: ee_actions.h:214
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
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 AllPinsOrSheetPins
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
SCH_SELECTION_FILTER_OPTIONS m_filter
EE_SELECTION m_selection
void unselect(EDA_ITEM *aItem) override
Take necessary action to mark an item as unselected.
void unhighlight(EDA_ITEM *aItem, int aMode, SELECTION *aGroup=nullptr) override
Unhighlight the item visually.
int SelectColumns(const TOOL_EVENT &aEvent)
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.
EE_SELECTION & RequestSelection(const std::vector< KICAD_T > &aScanTypes={ SCH_LOCATE_ANY_T }, bool aPromoteCellSelections=false)
Return either an existing selection (filtered), or the selection at the current cursor position if th...
bool selectTableCells(SCH_TABLE *aTable)
Handle a table cell drag selection within a table.
EDA_ITEM * GetNode(const VECTOR2I &aPosition)
Finds a connected item at a point (usually the cursor position).
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 SelectTable(const TOOL_EVENT &aEvent)
Clear current selection event handler.
int disambiguateCursor(const TOOL_EVENT &aEvent)
Handle disambiguation actions including displaying the menu.
void highlight(EDA_ITEM *aItem, int aMode, SELECTION *aGroup=nullptr) override
Highlight the item visually.
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)
bool itemPassesFilter(EDA_ITEM *aItem)
Return true if the given item passes the stateful selection filter.
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 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.
int SelectRows(const TOOL_EVENT &aEvent)
EE_SELECTION & GetSelection()
void updateReferencePoint()
Set the reference point to the anchor of the top-left item.
BOX2I GetBoundingBox(bool aOnlyVisible=false) const override
EDA_ITEM * GetTopLeftItem(bool onlyModules=false) const override
static const TOOL_EVENT DisambiguatePoint
Used for hotkey feedback.
Definition: actions.h:287
static const TOOL_EVENT ClearedEvent
Definition: actions.h:272
static const TOOL_EVENT SelectedEvent
Definition: actions.h:270
static const TOOL_EVENT PointSelectedEvent
Definition: actions.h:269
static const TOOL_EVENT UnselectedEvent
Definition: actions.h:271
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:547
virtual void SetScale(double aScale, VECTOR2D aAnchor={ 0, 0 })
Set the scaling factor, zooming around a given anchor point.
Definition: view.cpp:587
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:317
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:357
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:437
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:1687
bool IsMirroredX() const
Return true if view is flipped across the X axis.
Definition: view.h:251
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:1635
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:221
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1614
Definition: kiid.h:49
Define a library symbol object.
Definition: lib_symbol.h:78
bool IsMulti() const override
Definition: lib_symbol.h:554
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition: lib_symbol.h:499
Tree view item data for the net navigator.
SCH_SHEET_PATH & CurrentSheet() const override
Definition: schematic.h:144
CONNECTION_GRAPH * ConnectionGraph() const override
Definition: schematic.h:154
void SetCurrentSheet(const SCH_SHEET_PATH &aPath) override
Definition: schematic.h:149
SCH_SHEET & Root() const
Definition: schematic.h:113
SCH_RENDER_SETTINGS * GetRenderSettings()
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
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:406
virtual void Revert() override
Definition: sch_commit.cpp:484
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:51
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_field.cpp:609
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:166
SCHEMATIC * Schematic() const
Searches the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:150
int GetBodyStyle() const
Definition: sch_item.h:232
virtual bool IsPointClickableAnchor(const VECTOR2I &aPos) const
Definition: sch_item.h:455
int GetUnit() const
Definition: sch_item.h:229
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const override
Definition: sch_label.cpp:867
void SetShape(LABEL_FLAG_SHAPE aShape)
Definition: sch_label.h:178
LABEL_SHAPE GetLabelShape() const
Definition: sch_label.h:181
virtual void SetSpinStyle(SPIN_STYLE aSpinStyle)
Definition: sch_label.cpp:348
static bool IsDrawingLineWireOrBus(const SELECTION &aSelection)
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:41
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:809
bool IsStartDangling() const
Definition: sch_line.h:261
VECTOR2I GetEndPoint() const
Definition: sch_line.h:141
VECTOR2I GetStartPoint() const
Definition: sch_line.h:136
SEG GetSeg() const
Get the geometric aspect of the wire as a SEG.
Definition: sch_line.h:147
bool IsEndDangling() const
Definition: sch_line.h:262
bool IsBus() const
Return true if the line is a bus.
Definition: sch_line.cpp:982
bool IsGraphicLine() const
Return if the line is a graphic (non electrical line)
Definition: sch_line.cpp:970
void SetEndPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:142
bool IsVisible() const
Definition: sch_pin.cpp:340
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:108
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:407
bool CheckIfOnDrawList(const SCH_ITEM *aItem) const
Definition: sch_screen.cpp:385
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_SIDE GetSide() const
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:105
int GetOrientation() const
Get the display symbol orientation.
SCH_PIN * GetPin(const wxString &number) const
Find a symbol pin by number.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:213
BOX2I GetBodyBoundingBox() const
Return a bounding box for the symbol body but not the pins or fields.
int GetColSpan() const
Definition: sch_tablecell.h:61
int GetRowSpan() const
Definition: sch_tablecell.h:64
std::vector< SCH_TABLECELL * > GetCells() const
Definition: sch_table.h:141
Definition: seg.h:42
int Distance(const SEG &aSeg) const
Compute minimum Euclidean distance to segment aSeg.
Definition: seg.cpp:388
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:121
void SetIsHover(bool aIsHover)
Definition: selection.h:79
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:100
EDA_ITEM * Front() const
Definition: selection.h:172
virtual void Clear() override
Remove all the stored items from the group.
Definition: selection.h:93
int Size() const
Returns the number of selected parts.
Definition: selection.h:116
void ClearReferencePoint()
Definition: selection.cpp:186
bool OnlyContains(std::vector< KICAD_T > aList) const
Checks if all items in the selection have a type in aList.
Definition: selection.cpp:213
void SetReferencePoint(const VECTOR2I &aP)
Definition: selection.cpp:180
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:110
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
An abstract shape on 2D plane.
Definition: shape.h:126
The symbol library editor main window.
bool IsSymbolAlias() const
Return true if aLibId is an alias for the editor screen symbol.
int GetBodyStyle() const
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:144
bool ToolStackIsEmpty()
Definition: tools_holder.h:125
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:218
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
@ SHUTDOWN
Tool is being shut down.
Definition: tool_base.h:84
@ 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
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:150
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:235
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:197
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
double Distance(const VECTOR2< extended_type > &aVector) const
Compute the distance between two vectors.
Definition: vector2d.h:550
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_VERTICAL
Definition: eda_angle.h:398
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
Definition: eda_angle.h:397
std::vector< EDA_ITEM * > EDA_ITEMS
Define list of drawing items for screens.
Definition: eda_item.h:536
#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
static std::vector< KICAD_T > tableCellTypes
#define HITTEST_THRESHOLD_PIXELS
static std::vector< KICAD_T > lineTypes
static std::vector< KICAD_T > sheetTypes
const TOOL_ACTION * allowedActions[]
static std::vector< KICAD_T > connectedLineTypes
static std::vector< KICAD_T > crossProbingTypes
@ 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
GRID_HELPER_GRIDS
Definition: grid_helper.h:37
KIID niluuid(0)
@ LAYER_WIRE
Definition: layer_ids.h:357
@ LAYER_BUS
Definition: layer_ids.h:358
@ REPAINT
Item needs to be redrawn.
Definition: view_item.h:57
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
Definition: pin_type.h:36
CITER next(CITER it)
Definition: ptree.cpp:126
@ LABEL_BIDI
Definition: sch_label.h:119
@ LABEL_INPUT
Definition: sch_label.h:117
@ LABEL_OUTPUT
Definition: sch_label.h:118
@ LABEL_PASSIVE
Definition: sch_label.h:121
@ LABEL_TRISTATE
Definition: sch_label.h:120
std::function< bool(const SELECTION &)> SELECTION_CONDITION
Functor type that checks a specific condition for selected items.
std::vector< FAB_LAYER_COLOR > dummy
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:93
bool symbols
Allow selecting symbols and sheet symbols.
bool labels
Net and bus labels.
bool pins
Symbol and sheet pins.
bool graphics
Graphic lines, shapes, polygons.
bool lockedItems
Allow selecting locked items.
bool images
Bitmap/vector images.
bool otherItems
Anything not fitting one of the above categories.
bool wires
Net and bus wires and junctions.
void RotateAndMirrorPin(SCH_PIN &aPin, int aOrientMirror)
Rotate and/or mirror a SCH_PIN according to aOrientMirror.
std::optional< TOOL_EVENT > OPT_TOOL_EVENT
Definition: tool_event.h:629
@ 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
@ SCH_TABLE_T
Definition: typeinfo.h:165
@ SCH_LINE_T
Definition: typeinfo.h:163
@ LIB_SYMBOL_T
Definition: typeinfo.h:148
@ SCH_SYMBOL_T
Definition: typeinfo.h:172
@ SCH_TABLECELL_T
Definition: typeinfo.h:166
@ SCH_ITEM_LOCATE_WIRE_T
Definition: typeinfo.h:185
@ SCH_FIELD_T
Definition: typeinfo.h:150
@ SCH_DIRECTIVE_LABEL_T
Definition: typeinfo.h:171
@ SCH_LABEL_T
Definition: typeinfo.h:167
@ SCH_LOCATE_ANY_T
Definition: typeinfo.h:198
@ SCH_SHEET_T
Definition: typeinfo.h:174
@ SCH_ITEM_LOCATE_BUS_T
Definition: typeinfo.h:186
@ SCH_MARKER_T
Definition: typeinfo.h:158
@ SCH_SHAPE_T
Definition: typeinfo.h:149
@ SCH_HIER_LABEL_T
Definition: typeinfo.h:169
@ SCH_BUS_BUS_ENTRY_T
Definition: typeinfo.h:162
@ SCH_ITEM_LOCATE_GRAPHIC_LINE_T
Definition: typeinfo.h:187
@ SCHEMATIC_T
Definition: typeinfo.h:203
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:173
@ SCH_TEXT_T
Definition: typeinfo.h:151
@ SCH_SYMBOL_LOCATE_POWER_T
Definition: typeinfo.h:195
@ SCH_BUS_WIRE_ENTRY_T
Definition: typeinfo.h:161
@ SCH_BITMAP_T
Definition: typeinfo.h:164
@ SCH_TEXTBOX_T
Definition: typeinfo.h:152
@ SCH_GLOBAL_LABEL_T
Definition: typeinfo.h:168
@ SCH_JUNCTION_T
Definition: typeinfo.h:159
@ SCH_PIN_T
Definition: typeinfo.h:153
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:121
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:673