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