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