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 if( exactHits.contains( item ) )
1499 {
1500 if( item->Type() == SCH_PIN_T || item->Type() == SCH_JUNCTION_T )
1501 {
1502 closest = item;
1503 break;
1504 }
1505
1506 SCH_LINE* line = dynamic_cast<SCH_LINE*>( item );
1507 SCH_FIELD* field = dynamic_cast<SCH_FIELD*>( item );
1508 EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item );
1509 EDA_SHAPE* shape = dynamic_cast<EDA_SHAPE*>( item );
1510 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item );
1511
1512 if( line )
1513 {
1514 dist = KiROUND( DistanceLinePoint( line->GetStartPoint(),
1515 line->GetEndPoint(), aPos ) );
1516 }
1517 else if( field )
1518 {
1519 BOX2I box = field->GetBoundingBox();
1520 EDA_ANGLE orient = field->GetTextAngle();
1521
1522 if( field->GetParent() && field->GetParent()->Type() == SCH_SYMBOL_T )
1523 {
1524 if( static_cast<SCH_SYMBOL*>( field->GetParent() )->GetTransform().y1 )
1525 {
1526 if( orient.IsHorizontal() )
1527 orient = ANGLE_VERTICAL;
1528 else
1529 orient = ANGLE_HORIZONTAL;
1530 }
1531 }
1532
1533 field->GetEffectiveTextShape( false, box, orient )
1534 ->Collide( poss, INT_MAX / 4, &dist );
1535 }
1536 else if( text )
1537 {
1538 text->GetEffectiveTextShape( false )->Collide( poss, INT_MAX / 4, &dist );
1539 }
1540 else if( shape )
1541 {
1542 std::vector<SHAPE*> shapes = shape->MakeEffectiveShapes();
1543
1544 for( SHAPE* s : shapes )
1545 {
1546 int shapeDist = dist;
1547 s->Collide( poss, INT_MAX / 4, &shapeDist );
1548
1549 if( shapeDist < dist )
1550 dist = shapeDist;
1551
1552 delete s;
1553 }
1554 }
1555 else if( symbol )
1556 {
1557 bbox = symbol->GetBodyBoundingBox();
1558
1559 SHAPE_RECT rect( bbox.GetPosition(), bbox.GetWidth(), bbox.GetHeight() );
1560
1561 if( bbox.Contains( aPos ) )
1562 dist = KiROUND( EuclideanNorm( bbox.GetCenter() - aPos ) );
1563 else
1564 rect.Collide( poss, closestDist, &dist );
1565 }
1566 else
1567 {
1568 dist = KiROUND( EuclideanNorm( bbox.GetCenter() - aPos ) );
1569 }
1570 }
1571 else
1572 {
1573 SHAPE_RECT rect( bbox.GetPosition(), bbox.GetWidth(), bbox.GetHeight() );
1574 rect.Collide( poss, collector.m_Threshold, &dist );
1575 }
1576
1577 if( dist == closestDist )
1578 {
1579 if( item->GetParent() == closest )
1580 closest = item;
1581 }
1582 else if( dist < closestDist )
1583 {
1584 closestDist = dist;
1585 closest = item;
1586 }
1587 }
1588
1589 // Construct a tight box (1/2 height and width) around the center of the closest item.
1590 // All items which exist at least partly outside this box have sufficient other areas
1591 // for selection and can be dropped.
1592 if( closest ) // Don't try and get a tight bbox if nothing is near the mouse pointer
1593 {
1594 BOX2I tightBox = closest->GetBoundingBox();
1595 tightBox.Inflate( -tightBox.GetWidth() / 4, -tightBox.GetHeight() / 4 );
1596
1597 for( int i = collector.GetCount() - 1; i >= 0; --i )
1598 {
1599 EDA_ITEM* item = collector[i];
1600
1601 if( item == closest )
1602 continue;
1603
1604 if( !item->HitTest( tightBox, true ) )
1605 collector.Transfer( item );
1606 }
1607 }
1608}
1609
1610
1611EE_SELECTION& EE_SELECTION_TOOL::RequestSelection( const std::vector<KICAD_T>& aScanTypes,
1612 bool aPromoteCellSelections )
1613{
1614 bool anyUnselected = false;
1615 bool anySelected = false;
1616
1617 if( m_selection.Empty() )
1618 {
1619 VECTOR2D cursorPos = getViewControls()->GetCursorPosition( true );
1620
1622 SelectPoint( cursorPos, aScanTypes );
1623 m_selection.SetIsHover( true );
1625 }
1626 else // Trim an existing selection by aFilterList
1627 {
1628 bool isMoving = false;
1629
1630 for( int i = (int) m_selection.GetSize() - 1; i >= 0; --i )
1631 {
1632 EDA_ITEM* item = (EDA_ITEM*) m_selection.GetItem( i );
1633 isMoving |= static_cast<SCH_ITEM*>( item )->IsMoving();
1634
1635 if( !item->IsType( aScanTypes ) )
1636 {
1637 unselect( item );
1638 anyUnselected = true;
1639 }
1640 }
1641
1642 if( !isMoving )
1644 }
1645
1646 if( aPromoteCellSelections )
1647 {
1648 std::set<EDA_ITEM*> parents;
1649
1650 for( int i = (int) m_selection.GetSize() - 1; i >= 0; --i )
1651 {
1652 EDA_ITEM* item = (EDA_ITEM*) m_selection.GetItem( i );
1653
1654 if( item->Type() == SCH_TABLECELL_T )
1655 {
1656 parents.insert( item->GetParent() );
1657 unselect( item );
1658 anyUnselected = true;
1659 }
1660 }
1661
1662 for( EDA_ITEM* parent : parents )
1663 {
1664 if( !parent->IsSelected() )
1665 {
1666 select( parent );
1667 anySelected = true;
1668 }
1669 }
1670 }
1671
1672 if( anyUnselected )
1674
1675 if( anySelected )
1677
1678 return m_selection;
1679}
1680
1681
1683{
1684 if( !aItem )
1685 return false;
1686
1687 // Locking is not yet exposed uniformly in the schematic
1688#if 0
1689 if( SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( aItem ) )
1690 {
1691 if( schItem->IsLocked() && !m_filter.lockedItems )
1692 return false;
1693 }
1694#endif
1695
1696 switch( aItem->Type() )
1697 {
1698 case SCH_SYMBOL_T:
1699 case SCH_SHEET_T:
1700 if( !m_filter.symbols )
1701 return false;
1702
1703 break;
1704
1705 case SCH_PIN_T:
1706 case SCH_SHEET_PIN_T:
1707 if( !m_filter.pins )
1708 return false;
1709
1710 break;
1711
1712 case SCH_LINE_T:
1713 {
1714 switch( static_cast<SCH_LINE*>( aItem )->GetLayer() )
1715 {
1716 case LAYER_WIRE:
1717 case LAYER_BUS:
1718 if( !m_filter.wires )
1719 return false;
1720
1721 break;
1722
1723 default:
1724 if( !m_filter.graphics )
1725 return false;
1726 }
1727
1728 break;
1729 }
1730
1731 case SCH_SHAPE_T:
1732 if( !m_filter.graphics )
1733 return false;
1734
1735 break;
1736
1737 case SCH_TEXT_T:
1738 case SCH_TEXTBOX_T:
1739 case SCH_TABLE_T:
1740 case SCH_TABLECELL_T:
1741 case SCH_FIELD_T:
1742 if( !m_filter.text )
1743 return false;
1744
1745 break;
1746
1747 case SCH_LABEL_T:
1748 case SCH_GLOBAL_LABEL_T:
1749 case SCH_HIER_LABEL_T:
1750 if( !m_filter.labels )
1751 return false;
1752
1753 break;
1754
1755 case SCH_BITMAP_T:
1756 if( !m_filter.images )
1757 return false;
1758
1759 break;
1760
1761 default:
1762 if( !m_filter.otherItems )
1763 return false;
1764
1765 break;
1766 }
1767
1768 return true;
1769}
1770
1771
1773{
1774 VECTOR2I refP( 0, 0 );
1775
1776 if( m_selection.Size() > 0 )
1777 refP = static_cast<SCH_ITEM*>( m_selection.GetTopLeftItem() )->GetPosition();
1778
1780}
1781
1782
1783// Some navigation actions are allowed in selectMultiple
1793 &ACTIONS::zoomFitObjects, nullptr };
1794
1795
1797{
1798 bool cancelled = false; // Was the tool canceled while it was running?
1799 m_multiple = true; // Multiple selection mode is active
1800 KIGFX::VIEW* view = getView();
1801
1803 view->Add( &area );
1804
1805 while( TOOL_EVENT* evt = Wait() )
1806 {
1807 int width = area.GetEnd().x - area.GetOrigin().x;
1808 int height = area.GetEnd().y - area.GetOrigin().y;
1809
1810 /* Selection mode depends on direction of drag-selection:
1811 * Left > Right : Select objects that are fully enclosed by selection
1812 * Right > Left : Select objects that are crossed by selection
1813 */
1814 bool isGreedy = width < 0;
1815
1816 if( view->IsMirroredX() )
1817 isGreedy = !isGreedy;
1818
1819 m_frame->GetCanvas()->SetCurrentCursor( isGreedy ? KICURSOR::SELECT_LASSO
1820 : KICURSOR::SELECT_WINDOW );
1821
1822 if( evt->IsCancelInteractive() || evt->IsActivate() )
1823 {
1824 cancelled = true;
1825 break;
1826 }
1827
1828 if( evt->IsDrag( BUT_LEFT ) )
1829 {
1832
1833 // Start drawing a selection box
1834 area.SetOrigin( evt->DragOrigin() );
1835 area.SetEnd( evt->Position() );
1838 area.SetExclusiveOr( false );
1839
1840 view->SetVisible( &area, true );
1841 view->Update( &area );
1842 getViewControls()->SetAutoPan( true );
1843 }
1844
1845 if( evt->IsMouseUp( BUT_LEFT ) )
1846 {
1847 getViewControls()->SetAutoPan( false );
1848
1849 // End drawing the selection box
1850 view->SetVisible( &area, false );
1851
1852 // Fetch items from the RTree that are in our area of interest
1853 std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> nearbyViewItems;
1854 view->Query( area.ViewBBox(), nearbyViewItems );
1855
1856 // Build lists of nearby items and their children
1857 std::unordered_set<EDA_ITEM*> nearbyItems;
1858 std::vector<EDA_ITEM*> nearbyChildren;
1859 std::vector<EDA_ITEM*> flaggedItems;
1860
1861 for( KIGFX::VIEW::LAYER_ITEM_PAIR& pair : nearbyViewItems )
1862 {
1863 if( EDA_ITEM* item = dynamic_cast<EDA_ITEM*>( pair.first ) )
1864 {
1865 if( nearbyItems.insert( item ).second )
1866 {
1867 item->ClearFlags( CANDIDATE );
1868
1869 if( SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( item ) )
1870 {
1871 sch_item->RunOnChildren(
1872 [&]( SCH_ITEM* aChild )
1873 {
1874 // Filter pins by unit
1875 if( SCH_PIN* pin = dynamic_cast<SCH_PIN*>( aChild ) )
1876 {
1877 int unit = pin->GetLibPin()->GetUnit();
1878
1879 if( unit && unit != pin->GetParentSymbol()->GetUnit() )
1880 return;
1881 }
1882
1883 nearbyChildren.push_back( aChild );
1884 } );
1885 }
1886 }
1887 }
1888 }
1889
1890 BOX2I selectionRect( area.GetOrigin(), VECTOR2I( width, height ) );
1891 selectionRect.Normalize();
1892
1893 bool anyAdded = false;
1894 bool anySubtracted = false;
1895
1896 auto selectItem =
1897 [&]( EDA_ITEM* aItem, EDA_ITEM_FLAGS flags )
1898 {
1899 if( m_subtractive || ( m_exclusive_or && aItem->IsSelected() ) )
1900 {
1901 if ( m_exclusive_or )
1902 aItem->XorFlags( flags );
1903 else
1904 aItem->ClearFlags( flags );
1905
1906 if( !aItem->HasFlag( STARTPOINT ) && !aItem->HasFlag( ENDPOINT ) )
1907 {
1908 unselect( aItem );
1909 anySubtracted = true;
1910 }
1911
1912 // We changed one line endpoint on a selected line,
1913 // update the view at least.
1914 if( flags && !anySubtracted )
1915 getView()->Update( aItem );
1916 }
1917 else
1918 {
1919 aItem->SetFlags( flags );
1920 select( aItem );
1921 anyAdded = true;
1922 }
1923 };
1924
1925 for( EDA_ITEM* item : nearbyItems )
1926 {
1927 bool selected = false;
1928 EDA_ITEM_FLAGS flags = 0;
1929
1931 item->SetFlags( SHOW_ELEC_TYPE );
1932
1933 if( Selectable( item ) && itemPassesFilter( item ) )
1934 {
1935 if( item->Type() == SCH_LINE_T )
1936 {
1937 SCH_LINE* line = static_cast<SCH_LINE*>( item );
1938
1939 if( ( isGreedy && line->HitTest( selectionRect, false ) )
1940 || ( selectionRect.Contains( line->GetEndPoint() )
1941 && selectionRect.Contains( line->GetStartPoint() ) ) )
1942 {
1943 selected = true;
1944 flags |= STARTPOINT | ENDPOINT;
1945 }
1946 else if( !isGreedy )
1947 {
1948 if( selectionRect.Contains( line->GetStartPoint() )
1949 && line->IsStartDangling() )
1950 {
1951 selected = true;
1952 flags |= STARTPOINT;
1953 }
1954
1955 if( selectionRect.Contains( line->GetEndPoint() )
1956 && line->IsEndDangling() )
1957 {
1958 selected = true;
1959 flags |= ENDPOINT;
1960 }
1961 }
1962 }
1963 else
1964 {
1965 selected = item->HitTest( selectionRect, !isGreedy );
1966 }
1967 }
1968
1969 if( selected )
1970 {
1971 item->SetFlags( CANDIDATE );
1972 flaggedItems.push_back( item );
1973 selectItem( item, flags );
1974 }
1975
1976 item->ClearFlags( SHOW_ELEC_TYPE );
1977 }
1978
1979 for( EDA_ITEM* item : nearbyChildren )
1980 {
1982 item->SetFlags( SHOW_ELEC_TYPE );
1983
1984 if( Selectable( item )
1985 && itemPassesFilter( item )
1986 && !item->GetParent()->HasFlag( CANDIDATE )
1987 && item->HitTest( selectionRect, !isGreedy ) )
1988 {
1989 selectItem( item, 0 );
1990 }
1991
1992 item->ClearFlags( SHOW_ELEC_TYPE );
1993 }
1994
1995 for( EDA_ITEM* item : flaggedItems )
1996 item->ClearFlags( CANDIDATE );
1997
1998 m_selection.SetIsHover( false );
1999
2000 // Inform other potentially interested tools
2001 if( anyAdded )
2003
2004 if( anySubtracted )
2006
2007 break; // Stop waiting for events
2008 }
2009
2010 // Allow some actions for navigation
2011 for( int i = 0; allowedActions[i]; ++i )
2012 {
2013 if( evt->IsAction( allowedActions[i] ) )
2014 {
2015 evt->SetPassEvent();
2016 break;
2017 }
2018 }
2019 }
2020
2021 getViewControls()->SetAutoPan( false );
2022
2023 // Stop drawing the selection box
2024 view->Remove( &area );
2025 m_multiple = false; // Multiple selection mode is inactive
2026
2027 if( !cancelled )
2029
2030 return cancelled;
2031}
2032
2033
2035{
2036 bool cancelled = false; // Was the tool canceled while it was running?
2037 m_multiple = true; // Multiple selection mode is active
2038
2039 for( SCH_TABLECELL* cell : aTable->GetCells() )
2040 {
2041 if( cell->IsSelected() )
2042 cell->SetFlags( CANDIDATE );
2043 else
2044 cell->ClearFlags( CANDIDATE );
2045 }
2046
2047 auto wasSelected =
2048 []( EDA_ITEM* aItem )
2049 {
2050 return ( aItem->GetFlags() & CANDIDATE ) > 0;
2051 };
2052
2053 while( TOOL_EVENT* evt = Wait() )
2054 {
2055 if( evt->IsCancelInteractive() || evt->IsActivate() )
2056 {
2057 cancelled = true;
2058 break;
2059 }
2060 else if( evt->IsDrag( BUT_LEFT ) )
2061 {
2062 getViewControls()->SetAutoPan( true );
2063
2064 BOX2I selectionRect( evt->DragOrigin(), evt->Position() - evt->DragOrigin() );
2065 selectionRect.Normalize();
2066
2067 for( SCH_TABLECELL* cell : aTable->GetCells() )
2068 {
2069 bool doSelect = false;
2070
2071 if( cell->HitTest( selectionRect, false ) )
2072 {
2073 if( m_subtractive )
2074 doSelect = false;
2075 else if( m_exclusive_or )
2076 doSelect = !wasSelected( cell );
2077 else
2078 doSelect = true;
2079 }
2080 else if( wasSelected( cell ) )
2081 {
2082 doSelect = m_additive || m_subtractive || m_exclusive_or;
2083 }
2084
2085 if( doSelect && !cell->IsSelected() )
2086 select( cell );
2087 else if( !doSelect && cell->IsSelected() )
2088 unselect( cell );
2089 }
2090 }
2091 else if( evt->IsMouseUp( BUT_LEFT ) )
2092 {
2093 m_selection.SetIsHover( false );
2094
2095 bool anyAdded = false;
2096 bool anySubtracted = false;
2097
2098 for( SCH_TABLECELL* cell : aTable->GetCells() )
2099 {
2100 if( cell->IsSelected() && !wasSelected( cell ) )
2101 anyAdded = true;
2102 else if( wasSelected( cell ) && !cell->IsSelected() )
2103 anySubtracted = true;
2104 }
2105
2106 // Inform other potentially interested tools
2107 if( anyAdded )
2109
2110 if( anySubtracted )
2112
2113 break; // Stop waiting for events
2114 }
2115 else
2116 {
2117 // Allow some actions for navigation
2118 for( int i = 0; allowedActions[i]; ++i )
2119 {
2120 if( evt->IsAction( allowedActions[i] ) )
2121 {
2122 evt->SetPassEvent();
2123 break;
2124 }
2125 }
2126 }
2127 }
2128
2129 getViewControls()->SetAutoPan( false );
2130
2131 m_multiple = false; // Multiple selection mode is inactive
2132
2133 if( !cancelled )
2135
2136 return cancelled;
2137}
2138
2139
2141{
2142 EE_COLLECTOR collector;
2143
2144 //TODO(snh): Reimplement after exposing KNN interface
2145 int pixelThreshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
2146 int gridThreshold = KiROUND( getView()->GetGAL()->GetGridSize().EuclideanNorm() );
2147 int thresholdMax = std::max( pixelThreshold, gridThreshold );
2148
2149 for( int threshold : { 0, thresholdMax/4, thresholdMax/2, thresholdMax } )
2150 {
2151 collector.m_Threshold = threshold;
2152 collector.Collect( m_frame->GetScreen(), connectedTypes, aPosition );
2153
2154 if( collector.GetCount() > 0 )
2155 break;
2156 }
2157
2158 return collector.GetCount() ? collector[ 0 ] : nullptr;
2159}
2160
2161
2163{
2164 VECTOR2I cursorPos = getViewControls()->GetCursorPosition( false );
2165
2166 SelectPoint( cursorPos, connectedTypes );
2167 return 0;
2168}
2169
2170
2172{
2175
2176 if( m_selection.Empty() )
2177 return 0;
2178
2179 unsigned done = false;
2180
2182
2183 for( EDA_ITEM* selItem : m_selection.GetItems() )
2184 {
2185 if( selItem->Type() != SCH_LINE_T )
2186 continue;
2187
2188 SCH_LINE* line = static_cast<SCH_LINE*>( selItem );
2189
2190 std::set<SCH_ITEM*> conns = m_frame->GetScreen()->MarkConnections( line, false );
2191 for( SCH_ITEM* item : conns )
2192 {
2193 if( item->IsType( { SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T,
2194 SCH_ITEM_LOCATE_GRAPHIC_LINE_T } )
2195 && !item->IsSelected() )
2196 {
2197 done = true;
2198 }
2199
2200 select( item );
2201 }
2202
2203 if( !done )
2204 {
2205 conns = m_frame->GetScreen()->MarkConnections( line, true );
2206
2207 for( SCH_ITEM* item : conns )
2208 select( item );
2209 }
2210 }
2211
2212 if( m_selection.GetSize() > 1 )
2214
2215 return 0;
2216}
2217
2218
2220{
2221 std::set<std::pair<SCH_TABLE*, int>> columns;
2222 bool added = false;
2223
2224 for( EDA_ITEM* item : m_selection )
2225 {
2226 if( SCH_TABLECELL* cell = dynamic_cast<SCH_TABLECELL*>( item ) )
2227 {
2228 SCH_TABLE* table = static_cast<SCH_TABLE*>( cell->GetParent() );
2229 columns.insert( std::make_pair( table, cell->GetColumn() ) );
2230 }
2231 }
2232
2233 for( auto& [ table, col ] : columns )
2234 {
2235 for( int row = 0; row < table->GetRowCount(); ++row )
2236 {
2237 SCH_TABLECELL* cell = table->GetCell( row, col );
2238
2239 if( !cell->IsSelected() )
2240 {
2241 select( table->GetCell( row, col ) );
2242 added = true;
2243 }
2244 }
2245 }
2246
2247 if( added )
2249
2250 return 0;
2251}
2252
2253
2255{
2256 std::set<std::pair<SCH_TABLE*, int>> rows;
2257 bool added = false;
2258
2259 for( EDA_ITEM* item : m_selection )
2260 {
2261 if( SCH_TABLECELL* cell = dynamic_cast<SCH_TABLECELL*>( item ) )
2262 {
2263 SCH_TABLE* table = static_cast<SCH_TABLE*>( cell->GetParent() );
2264 rows.insert( std::make_pair( table, cell->GetRow() ) );
2265 }
2266 }
2267
2268 for( auto& [ table, row ] : rows )
2269 {
2270 for( int col = 0; col < table->GetColCount(); ++col )
2271 {
2272 SCH_TABLECELL* cell = table->GetCell( row, col );
2273
2274 if( !cell->IsSelected() )
2275 {
2276 select( table->GetCell( row, col ) );
2277 added = true;
2278 }
2279 }
2280 }
2281
2282 if( added )
2284
2285 return 0;
2286}
2287
2288
2290{
2291 std::set<SCH_TABLE*> tables;
2292 bool added = false;
2293
2294 for( EDA_ITEM* item : m_selection )
2295 {
2296 if( SCH_TABLECELL* cell = dynamic_cast<SCH_TABLECELL*>( item ) )
2297 tables.insert( static_cast<SCH_TABLE*>( cell->GetParent() ) );
2298 }
2299
2301
2302 for( SCH_TABLE* table : tables )
2303 {
2304 if( !table->IsSelected() )
2305 {
2306 select( table );
2307 added = true;
2308 }
2309 }
2310
2311 if( added )
2313
2314 return 0;
2315}
2316
2317
2319{
2321 return 0;
2322}
2323
2324
2326{
2327 if( aBBox.GetWidth() == 0 )
2328 return;
2329
2330 BOX2I bbox = aBBox;
2331 bbox.Normalize();
2332
2333 VECTOR2I bbSize = bbox.Inflate( KiROUND( bbox.GetWidth() * 0.2f ) ).GetSize();
2334 VECTOR2D screenSize = getView()->GetViewport().GetSize();
2335
2336 // This code tries to come up with a zoom factor that doesn't simply zoom in to the cross
2337 // probed symbol, but instead shows a reasonable amount of the circuit around it to provide
2338 // context. This reduces the need to manually change the zoom because it's too close.
2339
2340 // Using the default text height as a constant to compare against, use the height of the
2341 // bounding box of visible items for a footprint to figure out if this is a big symbol (like
2342 // a processor) or a small symbol (like a resistor). This ratio is not useful by itself as a
2343 // scaling factor. It must be "bent" to provide good scaling at varying symbol sizes. Bigger
2344 // symbols need less scaling than small ones.
2345 double currTextHeight = schIUScale.MilsToIU( DEFAULT_TEXT_SIZE );
2346
2347 double compRatio = bbSize.y / currTextHeight; // Ratio of symbol to text height
2348 double compRatioBent = 1.0;
2349
2350 // LUT to scale zoom ratio to provide reasonable schematic context. Must work with symbols
2351 // of varying sizes (e.g. 0402 package and 200 pin BGA).
2352 // Each entry represents a compRatio (symbol height / default text height) and an amount to
2353 // scale by.
2354 std::vector<std::pair<double, double>> lut{ { 1.25, 16 },
2355 { 2.5, 12 },
2356 { 5, 8 },
2357 { 6, 6 },
2358 { 10, 4 },
2359 { 20, 2 },
2360 { 40, 1.5 },
2361 { 100, 1 } };
2362
2363 std::vector<std::pair<double, double>>::iterator it;
2364
2365 // Large symbol default is last LUT entry (1:1).
2366 compRatioBent = lut.back().second;
2367
2368 // Use LUT to do linear interpolation of "compRatio" within "first", then use that result to
2369 // linearly interpolate "second" which gives the scaling factor needed.
2370 if( compRatio >= lut.front().first )
2371 {
2372 for( it = lut.begin(); it < lut.end() - 1; ++it )
2373 {
2374 if( it->first <= compRatio && next( it )->first >= compRatio )
2375 {
2376 double diffx = compRatio - it->first;
2377 double diffn = next( it )->first - it->first;
2378
2379 compRatioBent = it->second + ( next( it )->second - it->second ) * diffx / diffn;
2380 break; // We have our interpolated value
2381 }
2382 }
2383 }
2384 else
2385 {
2386 compRatioBent = lut.front().second; // Small symbol default is first entry
2387 }
2388
2389 // This is similar to the original KiCad code that scaled the zoom to make sure symbols were
2390 // visible on screen. It's simply a ratio of screen size to symbol size, and its job is to
2391 // zoom in to make the component fullscreen. Earlier in the code the symbol BBox is given a
2392 // 20% margin to add some breathing room. We compare the height of this enlarged symbol bbox
2393 // to the default text height. If a symbol will end up with the sides clipped, we adjust
2394 // later to make sure it fits on screen.
2395 screenSize.x = std::max( 10.0, screenSize.x );
2396 screenSize.y = std::max( 10.0, screenSize.y );
2397 double ratio = std::max( -1.0, fabs( bbSize.y / screenSize.y ) );
2398
2399 // Original KiCad code for how much to scale the zoom
2400 double kicadRatio = std::max( fabs( bbSize.x / screenSize.x ),
2401 fabs( bbSize.y / screenSize.y ) );
2402
2403 // If the width of the part we're probing is bigger than what the screen width will be after
2404 // the zoom, then punt and use the KiCad zoom algorithm since it guarantees the part's width
2405 // will be encompassed within the screen.
2406 if( bbSize.x > screenSize.x * ratio * compRatioBent )
2407 {
2408 // Use standard KiCad zoom for parts too wide to fit on screen/
2409 ratio = kicadRatio;
2410 compRatioBent = 1.0; // Reset so we don't modify the "KiCad" ratio
2411 wxLogTrace( "CROSS_PROBE_SCALE",
2412 "Part TOO WIDE for screen. Using normal KiCad zoom ratio: %1.5f", ratio );
2413 }
2414
2415 // Now that "compRatioBent" holds our final scaling factor we apply it to the original
2416 // fullscreen zoom ratio to arrive at the final ratio itself.
2417 ratio *= compRatioBent;
2418
2419 bool alwaysZoom = false; // DEBUG - allows us to minimize zooming or not
2420
2421 // Try not to zoom on every cross-probe; it gets very noisy
2422 if( ( ratio < 0.5 || ratio > 1.0 ) || alwaysZoom )
2423 getView()->SetScale( getView()->GetScale() / ratio );
2424}
2425
2426
2427void EE_SELECTION_TOOL::SyncSelection( const std::optional<SCH_SHEET_PATH>& targetSheetPath,
2428 SCH_ITEM* focusItem, const std::vector<SCH_ITEM*>& items )
2429{
2430 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
2431
2432 if( !editFrame )
2433 return;
2434
2435 if( targetSheetPath && targetSheetPath != editFrame->Schematic().CurrentSheet() )
2436 {
2437 editFrame->Schematic().SetCurrentSheet( *targetSheetPath );
2438 editFrame->DisplayCurrentSheet();
2439 }
2440
2441 ClearSelection( items.size() > 0 ? true /*quiet mode*/ : false );
2442
2443 // Perform individual selection of each item before processing the event.
2444 for( SCH_ITEM* item : items )
2445 {
2446 SCH_ITEM* parent = dynamic_cast<SCH_ITEM*>( item->GetParent() );
2447
2448 // Make sure we only select items on the current screen
2449 if( m_frame->GetScreen()->CheckIfOnDrawList( item )
2450 || ( parent && m_frame->GetScreen()->CheckIfOnDrawList( parent ) ) )
2451 {
2452 select( item );
2453 }
2454 }
2455
2457
2458 if( bbox.GetWidth() != 0 && bbox.GetHeight() != 0 )
2459 {
2461 {
2463 ZoomFitCrossProbeBBox( bbox );
2464
2465 editFrame->FocusOnItem( focusItem );
2466
2467 if( !focusItem )
2468 editFrame->FocusOnLocation( bbox.Centre() );
2469 }
2470 }
2471
2472 if( m_selection.Size() > 0 )
2474}
2475
2476
2478{
2480
2481 if( m_isSymbolEditor )
2482 {
2483 LIB_SYMBOL* start = static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->GetCurSymbol();
2484
2485 for( SCH_ITEM& item : start->GetDrawItems() )
2486 {
2487 if( item.IsSelected() )
2488 select( &item );
2489 }
2490 }
2491 else
2492 {
2493 for( SCH_ITEM* item : m_frame->GetScreen()->Items() )
2494 {
2495 // If the field and symbol are selected, only use the symbol
2496 if( item->IsSelected() )
2497 {
2498 select( item );
2499 }
2500 else
2501 {
2502 item->RunOnChildren(
2503 [&]( SCH_ITEM* aChild )
2504 {
2505 if( aChild->IsSelected() )
2506 select( aChild );
2507 } );
2508 }
2509 }
2510 }
2511
2513
2514 // Inform other potentially interested tools
2516}
2517
2518
2519bool EE_SELECTION_TOOL::Selectable( const EDA_ITEM* aItem, const VECTOR2I* aPos,
2520 bool checkVisibilityOnly ) const
2521{
2522 // NOTE: in the future this is where Eeschema layer/itemtype visibility will be handled
2523
2524 SYMBOL_EDIT_FRAME* symEditFrame = dynamic_cast<SYMBOL_EDIT_FRAME*>( m_frame );
2525
2526 // Do not allow selection of anything except fields when the current symbol in the symbol
2527 // editor is a derived symbol.
2528 if( symEditFrame && symEditFrame->IsSymbolAlias() && aItem->Type() != SCH_FIELD_T )
2529 return false;
2530
2531 switch( aItem->Type() )
2532 {
2533 case SCH_PIN_T:
2534 {
2535 const SCH_PIN* pin = static_cast<const SCH_PIN*>( aItem );
2536
2537 if( symEditFrame )
2538 {
2539 if( pin->GetUnit() && pin->GetUnit() != symEditFrame->GetUnit() )
2540 return false;
2541
2542 if( pin->GetBodyStyle() && pin->GetBodyStyle() != symEditFrame->GetBodyStyle() )
2543 return false;
2544 }
2545
2546 if( !pin->IsVisible() && !m_frame->GetShowAllPins() )
2547 return false;
2548
2549 if( !m_filter.pins )
2550 {
2551 // Pin anchors have to be allowed for auto-starting wires.
2552 if( aPos )
2553 {
2555 GRID_HELPER_GRIDS pinGrid = grid.GetItemGrid( pin );
2556
2557 if( pin->IsPointClickableAnchor( grid.BestSnapAnchor( *aPos, pinGrid ) ) )
2558 return true;
2559 }
2560
2561 return false;
2562 }
2563
2564 break;
2565 }
2566
2569 return false;
2570
2571 break;
2572
2573 case LIB_SYMBOL_T: // In symbol_editor we do not want to select the symbol itself.
2574 return false;
2575
2576 case SCH_FIELD_T: // SCH_FIELD objects are not unit/body-style-specific.
2577 {
2578 const SCH_FIELD* field = static_cast<const SCH_FIELD*>( aItem );
2579
2580 if( !field->IsVisible() && !( symEditFrame && symEditFrame->GetShowInvisibleFields() ) )
2581 return false;
2582
2583 break;
2584 }
2585
2586 case SCH_SHAPE_T:
2587 case SCH_TEXT_T:
2588 case SCH_TEXTBOX_T:
2589 if( symEditFrame )
2590 {
2591 const SCH_ITEM* sch_item = static_cast<const SCH_ITEM*>( aItem );
2592
2593 if( sch_item->GetUnit() && sch_item->GetUnit() != symEditFrame->GetUnit() )
2594 return false;
2595
2596 if( sch_item->GetBodyStyle() && sch_item->GetBodyStyle() != symEditFrame->GetBodyStyle() )
2597 return false;
2598 }
2599
2600 break;
2601
2602 case SCH_MARKER_T: // Always selectable
2603 return true;
2604
2605 case SCH_TABLECELL_T:
2606 {
2607 const SCH_TABLECELL* cell = static_cast<const SCH_TABLECELL*>( aItem );
2608
2609 if( cell->GetColSpan() == 0 || cell->GetRowSpan() == 0 )
2610 return false;
2611
2612 break;
2613 }
2614
2615 default: // Suppress warnings
2616 break;
2617 }
2618
2619 return true;
2620}
2621
2622
2624{
2625 if( m_selection.Empty() )
2626 return;
2627
2628 while( m_selection.GetSize() )
2630
2631 getView()->Update( &m_selection );
2632
2633 m_selection.SetIsHover( false );
2635
2636 // Inform other potentially interested tools
2637 if( !aQuietMode )
2639}
2640
2641
2643{
2644 highlight( aItem, SELECTED, &m_selection );
2645}
2646
2647
2649{
2650 unhighlight( aItem, SELECTED, &m_selection );
2651}
2652
2653
2654void EE_SELECTION_TOOL::highlight( EDA_ITEM* aItem, int aMode, SELECTION* aGroup )
2655{
2656 if( aMode == SELECTED )
2657 aItem->SetSelected();
2658 else if( aMode == BRIGHTENED )
2659 aItem->SetBrightened();
2660
2661 if( aGroup )
2662 aGroup->Add( aItem );
2663
2664 // Highlight pins and fields. (All the other symbol children are currently only
2665 // represented in the LIB_SYMBOL and will inherit the settings of the parent symbol.)
2666 if( SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( aItem ) )
2667 {
2668 sch_item->RunOnChildren(
2669 [&]( SCH_ITEM* aChild )
2670 {
2671 if( aMode == SELECTED )
2672 {
2673 aChild->SetSelected();
2674 getView()->Hide( aChild, true );
2675 }
2676 else if( aMode == BRIGHTENED )
2677 {
2678 aChild->SetBrightened();
2679 }
2680 } );
2681 }
2682
2683 if( aGroup && aMode != BRIGHTENED )
2684 getView()->Hide( aItem, true );
2685
2686 if( aItem->GetParent() && aItem->GetParent()->Type() != SCHEMATIC_T )
2687 getView()->Update( aItem->GetParent(), KIGFX::REPAINT );
2688
2689 getView()->Update( aItem, KIGFX::REPAINT );
2690}
2691
2692
2693void EE_SELECTION_TOOL::unhighlight( EDA_ITEM* aItem, int aMode, SELECTION* aGroup )
2694{
2695 if( aMode == SELECTED )
2696 {
2697 aItem->ClearSelected();
2698 // Lines need endpoints cleared here
2699 if( aItem->Type() == SCH_LINE_T )
2700 aItem->ClearFlags( STARTPOINT | ENDPOINT );
2701
2702 if( aMode != BRIGHTENED )
2703 getView()->Hide( aItem, false );
2704 }
2705 else if( aMode == BRIGHTENED )
2706 {
2707 aItem->ClearBrightened();
2708 }
2709
2710 if( aGroup )
2711 aGroup->Remove( aItem );
2712
2713 // Unhighlight pins and fields. (All the other symbol children are currently only
2714 // represented in the LIB_SYMBOL.)
2715 if( SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( aItem ) )
2716 {
2717 sch_item->RunOnChildren(
2718 [&]( SCH_ITEM* aChild )
2719 {
2720 if( aMode == SELECTED )
2721 {
2722 aChild->ClearSelected();
2723 getView()->Hide( aChild, false );
2724 }
2725 else if( aMode == BRIGHTENED )
2726 {
2727 aChild->ClearBrightened();
2728 }
2729
2730 if( aGroup )
2731 aGroup->Remove( aChild );
2732 } );
2733 }
2734
2735 if( aItem->GetParent() && aItem->GetParent()->Type() != SCHEMATIC_T )
2736 getView()->Update( aItem->GetParent(), KIGFX::REPAINT );
2737
2738 getView()->Update( aItem, KIGFX::REPAINT );
2739}
2740
2741
2743{
2744 const unsigned GRIP_MARGIN = 20;
2745 int margin = KiROUND( getView()->ToWorld( GRIP_MARGIN ) );
2746
2747 // Check if the point is located within any of the currently selected items bounding boxes
2748 for( EDA_ITEM* item : m_selection )
2749 {
2750 BOX2I itemBox = item->ViewBBox();
2751 itemBox.Inflate( margin ); // Give some margin for gripping an item
2752
2753 if( itemBox.Contains( aPoint ) )
2754 return true;
2755 }
2756
2757 return false;
2758}
2759
2760
2762{
2764
2771
2773
2779
2782
2784}
2785
2786
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
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:978
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:541
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition: lib_symbol.h:486
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:586
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:40
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
Definition: sch_line.cpp:809
bool IsStartDangling() const
Definition: sch_line.h:252
VECTOR2I GetEndPoint() const
Definition: sch_line.h:140
VECTOR2I GetStartPoint() const
Definition: sch_line.h:135
bool IsEndDangling() const
Definition: sch_line.h:253
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:141
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:406
bool CheckIfOnDrawList(const SCH_ITEM *aItem) const
Definition: sch_screen.cpp:384
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