KiCad PCB EDA Suite
Loading...
Searching...
No Matches
ee_graphic_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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#include <tool/tool_manager.h>
22
23#include <wx/msgdlg.h>
24
25#include <default_values.h>
26#include <scoped_set_reset.h>
27
29#include <eeschema_settings.h>
34#include <sch_actions.h>
35#include <sch_commit.h>
36#include <sch_edit_frame.h>
37#include <sch_group.h>
38#include <sch_line.h>
39#include <sch_shape.h>
40#include <sch_textbox.h>
41#include <schematic.h>
42#include <symbol_edit_frame.h>
51#include <view/view_controls.h>
52#include <view/view.h>
53
54
56
57
75
76
78{
80
81 const auto inDrawingArc =
82 [this]( const SELECTION& aSel )
83 {
84 return m_mode == MODE::ARC;
85 };
86
87 const auto inManagedShape = [this]( const SELECTION& aSel )
88 {
90 };
91
92 CONDITIONAL_MENU& ctxMenu = m_menu->GetMenu();
93
94 // clang-format off
95 ctxMenu.AddItem( ACTIONS::arcPosture, inDrawingArc, 200 );
96 ctxMenu.AddCheckItem( SCH_ACTIONS::drawArcCenter, inDrawingArc, 200 );
97 ctxMenu.AddCheckItem( SCH_ACTIONS::drawArcStartEndMid, inDrawingArc, 200 );
98 ctxMenu.AddCheckItem( SCH_ACTIONS::drawArcStartEndCenter, inDrawingArc, 200 );
99 ctxMenu.AddCheckItem( SCH_ACTIONS::drawArcTangent, inDrawingArc, 200 );
100 ctxMenu.AddCheckItem( SCH_ACTIONS::drawArcStartDirEnd, inDrawingArc, 200 );
101 ctxMenu.AddItem( ACTIONS::cycleArcDrawMode, inDrawingArc, 200 );
102 ctxMenu.AddItem( ACTIONS::deleteLastPoint, inManagedShape, 200 );
103 ctxMenu.AddItem( ACTIONS::finishInteractive, inManagedShape, 200 );
104 // clang-format on
105
106 return true;
107}
108
109
114
115
117{
118 if( IsSymbolEditor() )
119 {
120 const SYMBOL_EDITOR_SETTINGS* cfg = frame<SYMBOL_EDIT_FRAME>()->libeditconfig();
121
122 return schIUScale.MilsToIU( cfg ? cfg->m_Defaults.text_size : DEFAULT_TEXT_SIZE );
123 }
124
125 return getModel<SCHEMATIC>()->Settings().m_DefaultTextSize;
126}
127
128
130{
131 if( !IsSymbolEditor() )
132 return;
133
135
136 if( symFrame->GetDrawSpecificUnit() )
137 aItem.SetUnit( symFrame->GetUnit() );
138
139 if( symFrame->GetDrawSpecificBodyStyle() )
140 aItem.SetBodyStyle( symFrame->GetBodyStyle() );
141}
142
143
144void EE_GRAPHIC_TOOL::commitItem( SCH_COMMIT& aCommit, std::unique_ptr<SCH_ITEM> aItem, const wxString& aDescription )
145{
146 aItem->ClearEditFlags();
147
148 if( IsSymbolEditor() )
149 {
151 LIB_SYMBOL* symbol = symFrame->GetCurSymbol();
152
153 aCommit.Modify( symbol, frame()->GetScreen() );
154 symbol->AddDrawItem( aItem.release() );
155 aCommit.Push( aDescription );
156 symFrame->RebuildView();
157 }
158 else
159 {
160 aCommit.Add( aItem.release(), frame()->GetScreen() );
161 aCommit.Push( aDescription );
162 }
163}
164
165
167{
168 EDA_ITEM* parent = getDrawParent();
169
170 if( !parent )
171 return 0;
172
173 int defaultTextSize = getDefaultTextSize();
174 bool isTextBox = aEvent.IsAction( &SCH_ACTIONS::drawTextBox )
176 bool isLineTool = aEvent.IsAction( &SCH_ACTIONS::drawSymbolLines );
177 SHAPE_T type = isTextBox ? SHAPE_T::RECTANGLE : aEvent.Parameter<SHAPE_T>();
178
179 if( m_inDrawingTool )
180 return 0;
181
183
186 VECTOR2I cursorPos;
187
188 std::unique_ptr<SCH_SHAPE> item;
189
190 // We might be running as the same shape in another co-routine. Make sure that one
191 // gets whacked.
192 m_toolMgr->DeactivateTool();
193
195
196 TOOL_EVENT originalEvent = aEvent;
197 SCOPED_TOOL_PUSHER raii( frame(), originalEvent );
198
199 auto setCursor =
200 [&]()
201 {
202 frame()->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
203 };
204
205 auto cleanup =
206 [&] ()
207 {
209 m_view->ClearPreview();
210 item.reset();
211 };
212
213 Activate();
214
215 // Must be done after Activate() so that it gets set into the correct context
216 getViewControls()->ShowCursor( true );
217
218 // Set initial cursor
219 setCursor();
220
221 if( aEvent.HasPosition() )
222 m_toolMgr->PrimeTool( aEvent.Position() );
223
224 SCH_LAYER_ID shapeLayer = getShapeLayer();
225
226 // Main loop: keep receiving events
227 while( TOOL_EVENT* evt = Wait() )
228 {
229 setCursor();
230 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
231 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
232
233 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
234 controls->ForceCursorPosition( true, cursorPos );
235
236 // The tool hotkey is interpreted as a click when drawing
237 bool isSyntheticClick = item && evt->IsActivate() && evt->HasPosition() && evt->Matches( aEvent );
238
239 if( evt->IsCancelInteractive() || ( item && evt->IsAction( &ACTIONS::undo ) ) )
240 {
241 if( item )
242 cleanup();
243 else
244 break;
245 }
246 else if( evt->IsActivate() && !isSyntheticClick )
247 {
248 if( item && evt->IsMoveTool() )
249 {
250 // we're already drawing our own item; ignore the move tool
251 evt->SetPassEvent( false );
252 continue;
253 }
254
255 if( item )
256 cleanup();
257
258 if( evt->IsPointEditor() )
259 {
260 // don't exit (the point editor runs in the background)
261 continue;
262 }
263
264 if( evt->IsMoveTool() )
265 {
266 // Make sure we come back after the move tool runs
267 frame()->PushTool( originalEvent );
268 }
269
270 break;
271 }
272 else if( !item && ( evt->IsClick( BUT_LEFT )
273 || evt->IsAction( &ACTIONS::cursorClick ) ) )
274 {
276
277 if( isTextBox )
278 {
279 auto textbox = std::make_unique<SCH_TEXTBOX>( shapeLayer, 0, m_lastTextboxFillStyle );
280
281 textbox->SetTextSize( VECTOR2I( defaultTextSize, defaultTextSize ) );
282
283 // Must come after SetTextSize()
284 textbox->SetBold( m_lastTextBold );
285 textbox->SetItalic( m_lastTextItalic );
286
287 textbox->SetTextAngle( m_lastTextboxAngle );
288 textbox->SetHorizJustify( m_lastTextboxHJustify );
289 textbox->SetVertJustify( m_lastTextboxVJustify );
290 textbox->SetStroke( m_lastTextboxStroke );
291 textbox->SetFillColor( m_lastTextboxFillColor );
292 textbox->SetParent( parent );
293
294 item = std::move( textbox );
295 }
296 else
297 {
298 item = std::make_unique<SCH_SHAPE>( type, shapeLayer, 0, m_lastFillStyle );
299
300 item->SetStroke( m_lastStroke );
301 item->SetFillColor( m_lastFillColor );
302 item->SetParent( parent );
303 }
304
305 item->SetFlags( IS_NEW );
306
307 applySymbolEditorFlags( *item );
308
309 item->BeginEdit( cursorPos );
310
311 m_view->ClearPreview();
312 m_view->AddToPreview( item->Clone() );
313 }
314 else if( item && ( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT )
315 || isSyntheticClick
316 || evt->IsAction( &ACTIONS::cursorClick ) || evt->IsAction( &ACTIONS::cursorDblClick )
317 || evt->IsAction( &ACTIONS::finishInteractive ) ) )
318 {
319 bool finished = false;
320 bool closedShape = false;
321
322 if( evt->IsDblClick( BUT_LEFT )
323 || evt->IsAction( &ACTIONS::cursorDblClick )
324 || evt->IsAction( &ACTIONS::finishInteractive ) )
325 {
326 finished = true;
327 closedShape = !isLineTool;
328 }
329 else
330 {
331 finished = !item->ContinueEdit( cursorPos );
332 }
333
334 if( finished )
335 {
336 item->EndEdit( closedShape );
337 item->SetFlags( IS_NEW );
338
339 if( isTextBox )
340 {
341 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( item.get() );
342 DIALOG_TEXT_PROPERTIES dlg( frame(), textbox );
343
344 getViewControls()->SetAutoPan( false );
345 getViewControls()->CaptureCursor( false );
346
347 // QuasiModal required for syntax help and Scintilla auto-complete
348 if( dlg.ShowQuasiModal() != wxID_OK )
349 {
350 cleanup();
351 continue;
352 }
353
354 m_lastTextBold = textbox->IsBold();
355 m_lastTextItalic = textbox->IsItalic();
356 m_lastTextboxAngle = textbox->GetTextAngle();
359 m_lastTextboxStroke = textbox->GetStroke();
362 }
363 else
364 {
365 m_lastStroke = item->GetStroke();
366 m_lastFillStyle = item->GetFillMode();
367 m_lastFillColor = item->GetFillColor();
368 }
369
370 m_selectionTool->AddItemToSel( item.get() );
371
372 SCH_COMMIT commit( m_toolMgr );
373 wxString msg = wxString::Format( _( "Draw %s" ), item->GetClass() );
374
375 commitItem( commit, std::move( item ), msg );
376 item = nullptr;
377
378 m_view->ClearPreview();
380 }
381 }
382 else if( evt->IsAction( &ACTIONS::duplicate )
383 || evt->IsAction( &SCH_ACTIONS::repeatDrawItem )
384 || evt->IsAction( &ACTIONS::paste ) )
385 {
386 if( item )
387 {
388 wxBell();
389 continue;
390 }
391
392 // Exit. The duplicate/repeat/paste will run in its own loop.
393 evt->SetPassEvent();
394 break;
395 }
396 else if( item && ( evt->IsAction( &ACTIONS::refreshPreview )
397 || evt->IsMotion() ) )
398 {
399 item->CalcEdit( cursorPos );
400 m_view->ClearPreview();
401 m_view->AddToPreview( item->Clone() );
402
403 frame()->SetMsgPanel( item.get() );
404 }
405 else if( !item && ( evt->IsDblClick( BUT_LEFT )
406 || evt->IsAction( &ACTIONS::cursorDblClick ) ) )
407 {
409 }
410 else if( evt->IsClick( BUT_RIGHT ) )
411 {
412 // Warp after context menu only if dragging...
413 if( !item )
414 m_toolMgr->VetoContextMenuMouseWarp();
415
416 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
417 }
418 else if( item && evt->IsAction( &ACTIONS::redo ) )
419 {
420 wxBell();
421 }
422 else
423 {
424 evt->SetPassEvent();
425 }
426
427 // Enable autopanning and cursor capture only when there is a shape being drawn
428 getViewControls()->SetAutoPan( item != nullptr );
429 getViewControls()->CaptureCursor( item != nullptr );
430 }
431
432 getViewControls()->SetAutoPan( false );
433 getViewControls()->CaptureCursor( false );
434 frame()->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
435 return 0;
436}
437
438
440{
441 if( m_inDrawingTool )
442 return 0;
443
444 EDA_ITEM* parent = getDrawParent();
445
446 if( !parent )
447 return 0;
448
450 SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ARC );
451
452 SCH_LAYER_ID shapeLayer = getShapeLayer();
453 std::vector<VECTOR2D> initialPts;
454
455 const auto makeNewArc =
456 [&]()
457 {
458 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC, shapeLayer, 0,
460 arc->SetStroke( m_lastStroke );
461 arc->SetFillColor( m_lastFillColor );
462 arc->SetParent( parent );
463 arc->SetFlags( IS_NEW );
464
466
467 return arc;
468 };
469
470 std::unique_ptr<SCH_SHAPE> arc = makeNewArc();
471
472 arc->SetFlags( IS_NEW );
473
474 TOOL_EVENT originalEvent = aEvent;
475 SCOPED_TOOL_PUSHER raii( m_frame, originalEvent );
476 Activate();
477
478 if( aEvent.HasPosition() )
479 initialPts.push_back( snapEventPosition( aEvent ) );
480
481 ARC_DRAW_BEHAVIOR arcBehavior( schIUScale, frame()->GetUserUnits() );
482
483 APP_SETTINGS_BASE* cfg = frame()->config();
484
485 frame()->SelectToolbarAction( SCH_ACTIONS::DrawArcForMode( StartArcDrawMode( aEvent, cfg, arcBehavior ) ) );
486
487 std::optional<ARC_TANGENT_SEED> tangentSeed;
488 VECTOR2I lastClick;
489
491
493 {
494 result = drawManagedShape( originalEvent, arc, arcBehavior, initialPts, tangentSeed, &lastClick );
495
496 tangentSeed.reset();
497
498 if( arc )
499 {
500 // The mode can change mid-draw so chain from whatever the settings hold now
502 tangentSeed = ArcTangentSeedNear( *arc, lastClick );
503
504 m_lastStroke = arc->GetStroke();
505 m_lastFillStyle = arc->GetFillMode();
506 m_lastFillColor = arc->GetFillColor();
507
508 m_selectionTool->AddItemToSel( arc.get() );
509
510 SCH_COMMIT commit( m_toolMgr );
511 commitItem( commit, std::move( arc ), _( "Draw Arc" ) );
512
514 }
515
516 arc = makeNewArc();
517 initialPts.clear();
518 }
519
520 return 0;
521}
522
523
525{
526 if( m_inDrawingTool )
527 return 0;
528
529 EDA_ITEM* parent = getDrawParent();
530
531 if( !parent )
532 return 0;
533
535 SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ELLIPSE_ARC );
536
537 SCH_LAYER_ID shapeLayer = getShapeLayer();
538 std::vector<VECTOR2D> initialPts;
539
540 const auto makeNewEllipseArc =
541 [&]()
542 {
543 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ELLIPSE_ARC, shapeLayer,
544 0, m_lastFillStyle );
545 arc->SetStroke( m_lastStroke );
546 arc->SetFillColor( m_lastFillColor );
547 arc->SetParent( parent );
548 arc->SetFlags( IS_NEW );
549
551
552 return arc;
553 };
554
555 std::unique_ptr<SCH_SHAPE> arc = makeNewEllipseArc();
556
557 TOOL_EVENT originalEvent = aEvent; // This can change out from under us when the event loop runs
558 SCOPED_TOOL_PUSHER raii( m_frame, originalEvent );
559 Activate();
560
561 if( aEvent.HasPosition() )
562 initialPts.push_back( snapEventPosition( aEvent ) );
563
564 ELLIPSE_ARC_DRAW_BEHAVIOR ellipseBehavior( schIUScale, frame()->GetUserUnits() );
565
567
569 {
570 result = drawManagedShape( originalEvent, arc, ellipseBehavior, initialPts );
571
572 if( arc )
573 {
574 m_lastStroke = arc->GetStroke();
575 m_lastFillStyle = arc->GetFillMode();
576 m_lastFillColor = arc->GetFillColor();
577
578 m_selectionTool->AddItemToSel( arc.get() );
579
580 SCH_COMMIT commit( m_toolMgr );
581 commitItem( commit, std::move( arc ), _( "Draw Elliptical Arc" ) );
582
584 }
585
586 arc = makeNewEllipseArc();
587 initialPts.clear();
588 }
589
590 return 0;
591}
592
593
595{
596 if( m_inDrawingTool )
597 return 0;
598
599 EDA_ITEM* parent = getDrawParent();
600
601 if( !parent )
602 return 0;
603
605 SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::BEZIER );
606
607 SCH_LAYER_ID shapeLayer = getShapeLayer();
608 std::vector<VECTOR2D> initialPts;
609
610 const auto makeNewBezier =
611 [&]()
612 {
613 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER, shapeLayer, 0,
615 bezier->SetStroke( m_lastStroke );
616 bezier->SetFillColor( m_lastFillColor );
617 bezier->SetParent( parent );
618 bezier->SetFlags( IS_NEW );
619
620 applySymbolEditorFlags( *bezier );
621
622 return bezier;
623 };
624
625 std::unique_ptr<SCH_SHAPE> bezier = makeNewBezier();
626
627 TOOL_EVENT originalEvent = aEvent; // This can change out from under us when the event loop runs
628 SCOPED_TOOL_PUSHER raii( m_frame, originalEvent );
629 Activate();
630
631 if( aEvent.HasPosition() )
632 initialPts.push_back( snapEventPosition( aEvent ) );
633
634 BEZIER_DRAW_BEHAVIOR bezierBehavior( schIUScale, frame()->GetUserUnits() );
635
637
639 {
640 result = drawManagedShape( originalEvent, bezier, bezierBehavior, initialPts );
641
642 if( bezier )
643 {
644 m_lastStroke = bezier->GetStroke();
645 m_lastFillStyle = bezier->GetFillMode();
646 m_lastFillColor = bezier->GetFillColor();
647
648 // Chain: next bezier starts at the end of this one
649 initialPts.clear();
650 initialPts.push_back( bezier->GetEnd() );
651
652 // If the last control arm is non-zero, mirror it for tangent continuity
653 if( bezier->GetEnd() != bezier->GetBezierC2() )
654 {
655 VECTOR2D mirroredC1 = bezier->GetEnd() - ( bezier->GetBezierC2() - bezier->GetEnd() );
656 initialPts.push_back( mirroredC1 );
657 }
658
659 m_selectionTool->AddItemToSel( bezier.get() );
660
661 SCH_COMMIT commit( m_toolMgr );
662 commitItem( commit, std::move( bezier ), _( "Draw Bezier" ) );
663
665 }
666 else
667 {
668 initialPts.clear();
669 }
670
671 bezier = makeNewBezier();
672 }
673
674 return 0;
675}
676
677
679{
681 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() );
682
683 return grid.Align( aEvent.Position(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
684}
685
686
687SHAPE_DRAW_RESULT EE_GRAPHIC_TOOL::drawManagedShape( const TOOL_EVENT& aTool, std::unique_ptr<SCH_SHAPE>& aShape,
688 SHAPE_DRAW_BEHAVIOR& aBehavior,
689 const std::vector<VECTOR2D>& aInitialPts,
690 const std::optional<ARC_TANGENT_SEED>& aTangentSeed,
691 VECTOR2I* aLastClick )
692{
693 if( !aShape )
695
696 aBehavior.Reset();
697
698 SELECTION preview;
701 VECTOR2I cursorPos;
702 EDA_ITEM* parent = getDrawParent();
703
704 m_view->Add( &preview );
705 m_view->Add( &aBehavior.GetAssistant() );
706
707 auto setCursor =
708 [&]()
709 {
710 frame()->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
711 };
712
713 auto cleanup =
714 [&]()
715 {
717 preview.Clear();
718 aShape.reset();
719 };
720
721 // Clicking a graphic on the drawing layer starts a tangent arc from it instead of placing a start point
722 auto findTangentSeed =
723 [&]( const VECTOR2I& aMouse, const VECTOR2I& aPos ) -> std::optional<ARC_TANGENT_SEED>
724 {
725 const int tolerance = KiROUND( getView()->ToWorld( ARC_SEED_PICK_PIXELS ) );
726 const SCH_LAYER_ID layer = getShapeLayer();
727
728 auto seedFrom =
729 [&]( SCH_ITEM* aItem, const VECTOR2I& aSeedPos ) -> std::optional<ARC_TANGENT_SEED>
730 {
731 if( !aItem || aItem->GetLayer() != layer )
732 return std::nullopt;
733
734 BOX2I reach = aItem->GetBoundingBox();
735
736 if( !reach.Inflate( tolerance ).Contains( aSeedPos ) )
737 return std::nullopt;
738
739 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( aItem ) )
740 return ArcTangentSeedAt( *shape, aSeedPos, tolerance );
741
742 if( SCH_LINE* line = dynamic_cast<SCH_LINE*>( aItem ); line && line->IsGraphicLine() )
743 {
744 return ArcTangentSeedAt( SEG( line->GetStartPoint(), line->GetEndPoint() ), aSeedPos,
745 tolerance );
746 }
747
748 return std::nullopt;
749 };
750
751 SNAP_RESULT snap = grid.ResolveSnap( aMouse, GRID_HELPER_GRIDS::GRID_GRAPHICS, aShape.get() );
752
753 if( std::optional<ARC_TANGENT_SEED> seed = seedFrom( grid.GetSnapped(), snap.position ) )
754 return seed;
755
756 if( IsSymbolEditor() )
757 {
759
760 if( LIB_SYMBOL* symbol = symFrame->GetCurSymbol() )
761 {
762 for( SCH_ITEM& item : symbol->GetDrawItems() )
763 {
764 bool inUnit = item.GetUnit() == ALL_UNITS
765 || item.GetUnit() == symFrame->GetUnit();
766 bool inBodyStyle = item.GetBodyStyle() == ALL_BODY_STYLES
767 || item.GetBodyStyle() == symFrame->GetBodyStyle();
768
769 if( !inUnit || !inBodyStyle )
770 continue;
771
772 if( std::optional<ARC_TANGENT_SEED> seed = seedFrom( &item, aPos ) )
773 return seed;
774 }
775 }
776
777 return std::nullopt;
778 }
779
780 for( KICAD_T type : { SCH_SHAPE_T, SCH_LINE_T } )
781 {
782 for( SCH_ITEM* item : frame()->GetScreen()->Items().Overlapping( type, aPos, tolerance ) )
783 {
784 if( std::optional<ARC_TANGENT_SEED> seed = seedFrom( item, aPos ) )
785 return seed;
786 }
787 }
788
789 return std::nullopt;
790 };
791
792 ARC_MODE_SESSION arcSession( aBehavior, frame()->config(), m_mode == MODE::ARC, aTangentSeed, findTangentSeed,
793 [&]( ARC_DRAW_MODE aMode )
794 {
795 frame()->SelectToolbarAction( SCH_ACTIONS::DrawArcForMode( aMode ) );
796 m_toolMgr->PostAction( ACTIONS::refreshPreview );
797 } );
798
799 controls->ShowCursor( true );
800 setCursor();
801
802 bool started = false;
803 bool cancelled = false;
804 bool finished = false;
805
806 m_toolMgr->PostAction( ACTIONS::refreshPreview );
807
808 // Pre-load any initial points into the behaviour, advancing the construction
809 // state machine so that the next user click adds the subsequent point.
810 // The user can still undo these points if they want to change them.
811 for( const VECTOR2D& pt : aInitialPts )
812 arcSession.PlacePoint( pt, pt );
813
814 if( !aInitialPts.empty() || aTangentSeed )
815 {
817
818 controls->SetAutoPan( true );
819 controls->CaptureCursor( true );
820
821 preview.Add( aShape.get() );
822 frame()->SetMsgPanel( aShape.get() );
823
824 started = true;
825 }
826
827 TOOL_EVENT* evt = nullptr;
828
829 while( ( evt = Wait() ) )
830 {
831 setCursor();
832 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
833 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
834
835 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
836 controls->ForceCursorPosition( true, cursorPos );
837
838 if( evt->IsCancelInteractive() )
839 {
840 cleanup();
841
842 if( !started )
843 {
844 evt->SetPassEvent( false );
845 cancelled = true;
846 }
847
848 break;
849 }
850 else if( started && evt->IsAction( &ACTIONS::undo ) )
851 {
852 cleanup();
853 break;
854 }
855 else if( arcSession.HandleModeEvent( *evt ) )
856 {
857 // A mode switch keeps the tool running rather than restarting it
858 }
859 else if( evt->IsActivate() )
860 {
861 if( evt->IsPointEditor() )
862 {
863 // don't exit (the point editor runs in the background)
864 continue;
865 }
866
867 if( evt->IsMoveTool() )
868 {
869 // Make sure we come back after the move tool runs
870 m_frame->PushTool( aTool );
871 }
872
873 cleanup();
874 cancelled = true;
875 break;
876 }
877 else if( evt->IsClick( BUT_LEFT ) || evt->IsAction( &ACTIONS::cursorClick ) )
878 {
879 if( !started )
880 {
882
883 controls->SetAutoPan( true );
884 controls->CaptureCursor( true );
885
886 preview.Add( aShape.get() );
887 frame()->SetMsgPanel( aShape.get() );
888 started = true;
889 }
890
891 arcSession.PlacePoint( controls->GetMousePosition(), cursorPos );
892
893 if( aLastClick )
894 *aLastClick = cursorPos;
895 }
896 else if( evt->IsDblClick( BUT_LEFT )
899 {
900 // Keep whatever we have so far, and report that we're finished.
901 if( !started )
902 cleanup();
903
904 finished = true;
905 break;
906 }
907 else if( evt->IsAction( &ACTIONS::arcPosture ) )
908 {
909 aBehavior.ToggleClockwise();
910 }
911 else if( evt->IsAction( &ACTIONS::deleteLastPoint ) || ( started && evt->IsAction( &ACTIONS::doDelete ) ) )
912 {
913 // Backspace is also doDelete's alternate hotkey, so a backup can arrive as either action
914 grid.FullReset();
915
916 arcSession.RemoveLastPoint();
917 }
918 else if( evt->IsMotion() || evt->IsAction( &ACTIONS::refreshPreview ) )
919 {
920 aBehavior.SetCursorPosition( cursorPos );
921 }
922 else if( evt->IsClick( BUT_RIGHT ) )
923 {
924 if( !aShape )
925 m_toolMgr->VetoContextMenuMouseWarp();
926
927 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
928 }
929 else if( evt->IsAction( &ACTIONS::updateUnits ) )
930 {
931 aBehavior.SetUnits( frame()->GetUserUnits() );
932 m_view->Update( &aBehavior.GetAssistant() );
933 evt->SetPassEvent();
934 }
935 else if( started && evt->IsAction( &ACTIONS::redo ) )
936 {
937 wxBell();
938 }
939 else
940 {
941 evt->SetPassEvent();
942 }
943
944 if( aBehavior.IsComplete() )
945 {
946 break;
947 }
948 else if( aBehavior.HasGeometryChanged() )
949 {
950 aBehavior.ApplyToShape( *aShape );
951 m_view->Update( &preview );
952 m_view->Update( &aBehavior.GetAssistant() );
953 aBehavior.ClearGeometryChanged();
954
955 if( started )
956 frame()->SetMsgPanel( aShape.get() );
957 else
958 frame()->SetMsgPanel( parent );
959 }
960 }
961
962 // A shutdown must end the caller's loop rather than start another shape
963 if( !evt )
964 cancelled = true;
965
966 preview.Remove( aShape.get() );
967 m_view->Remove( &aBehavior.GetAssistant() );
968 m_view->Remove( &preview );
969
970 if( !started )
971 frame()->SetMsgPanel( parent );
972
973 controls->SetAutoPan( false );
974 controls->CaptureCursor( false );
975 controls->ForceCursorPosition( false );
976 frame()->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
977
978 if( cancelled )
979 {
980 aShape.reset();
982 }
983
985}
986
987
989{
990 if( m_inDrawingTool )
991 return 0;
992
993 EDA_ITEM* parent = getDrawParent();
994
995 if( !parent )
996 return 0;
997
998 if( IsSymbolEditor() )
999 {
1001
1002 if( !symFrame->IsSymbolGraphicallyEditable() )
1003 return 0;
1004 }
1005
1007
1008 std::unique_ptr<GRAPHICS_IMPORTER> importer;
1009
1010 if( IsSymbolEditor() )
1011 {
1013 importer = std::make_unique<GRAPHICS_IMPORTER_LIB_SYMBOL>( symFrame->GetCurSymbol(), symFrame->GetUnit() );
1014 }
1015 else
1016 {
1017 importer = std::make_unique<GRAPHICS_IMPORTER_SCH>();
1018 }
1019
1020 // A symbol holds its own draw items, so a group on the screen would not be saved with it.
1021 DIALOG_IMPORT_GFX dlg( frame(), std::move( importer ), !IsSymbolEditor() );
1022
1023 // Set filename on drag-and-drop
1024 if( aEvent.HasParameter() )
1025 dlg.SetFilenameOverride( *aEvent.Parameter<wxString*>() );
1026
1027 int dlgResult = dlg.ShowModal();
1028
1029 std::list<std::unique_ptr<EDA_ITEM>>& list = dlg.GetImportedItems();
1030
1031 if( dlgResult != wxID_OK )
1032 return 0;
1033
1034 // Ensure the list is not empty:
1035 if( list.empty() )
1036 {
1037 wxMessageBox( _( "No graphic items found in file." ) );
1038 return 0;
1039 }
1040
1042
1044 std::vector<SCH_ITEM*> newItems;
1045 std::vector<SCH_ITEM*> selectedItems;
1046 SCH_SELECTION preview;
1047 SCH_COMMIT commit( m_toolMgr );
1048 SCH_GROUP* group = nullptr;
1049
1050 if( !IsSymbolEditor() && dlg.ShouldGroupItems() && list.size() >= 2 )
1051 {
1052 group = new SCH_GROUP( frame()->GetScreen() );
1053
1054 newItems.push_back( group );
1055 selectedItems.push_back( group );
1056 preview.Add( group );
1057 }
1058
1059 auto commitImport =
1060 [&]( const std::vector<SCH_ITEM*>& aItems )
1061 {
1062 if( IsSymbolEditor() )
1063 {
1064 LIB_SYMBOL* symbol = static_cast<LIB_SYMBOL*>( parent );
1065 commit.Modify( symbol, frame()->GetScreen() );
1066
1067 for( SCH_ITEM* item : aItems )
1068 {
1069 symbol->AddDrawItem( item );
1070 item->ClearEditFlags();
1071 }
1072 }
1073 else
1074 {
1075 for( SCH_ITEM* item : aItems )
1076 commit.Add( item, frame()->GetScreen() );
1077 }
1078
1079 commit.Push( _( "Import Graphic" ) );
1080
1081 if( IsSymbolEditor() )
1082 frame<SYMBOL_EDIT_FRAME>()->RebuildView();
1083 };
1084
1085 for( std::unique_ptr<EDA_ITEM>& ptr : list )
1086 {
1087 EDA_ITEM* eda_item = ptr.release();
1088 SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( eda_item );
1089
1090 wxCHECK2_MSG( item, continue, wxString::Format( "Bad item type: ", eda_item->Type() ) );
1091
1092 newItems.push_back( item );
1093 preview.Add( item );
1094
1095 if( group )
1096 group->AddItem( item );
1097 else
1098 selectedItems.push_back( item );
1099 }
1100
1101 if( !dlg.IsPlacementInteractive() )
1102 {
1103 commitImport( newItems );
1104 return 0;
1105 }
1106
1107 m_view->Add( &preview );
1108
1109 m_toolMgr->RunAction( ACTIONS::selectionClear );
1110
1111 EDA_ITEMS selItems( selectedItems.begin(), selectedItems.end() );
1112 m_toolMgr->RunAction<EDA_ITEMS*>( ACTIONS::selectItems, &selItems );
1113
1114 SCOPED_TOOL_PUSHER raii( frame(), aEvent );
1115
1116 auto setCursor =
1117 [&]()
1118 {
1119 frame()->GetCanvas()->SetCurrentCursor( KICURSOR::MOVING );
1120 };
1121
1122 Activate();
1123 controls->ShowCursor( true );
1124 controls->ForceCursorPosition( false );
1125 setCursor();
1126
1128
1129 VECTOR2I cursorPos = controls->GetCursorPosition( !aEvent.DisableGridSnapping() );
1130 VECTOR2I delta = cursorPos;
1131 VECTOR2I currentOffset;
1132
1133 for( SCH_ITEM* item : selectedItems )
1134 item->Move( delta );
1135
1136 currentOffset += delta;
1137 m_view->Update( &preview );
1138
1139 // Main loop: keep receiving events
1140 while( TOOL_EVENT* evt = Wait() )
1141 {
1142 setCursor();
1143
1144 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1145 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
1146
1147 cursorPos = grid.Align( controls->GetMousePosition(), GRID_GRAPHICS );
1148 controls->ForceCursorPosition( true, cursorPos );
1149
1150 if( evt->IsCancelInteractive() || evt->IsActivate() )
1151 {
1152 m_toolMgr->RunAction( ACTIONS::selectionClear );
1153
1154 for( SCH_ITEM* item : newItems )
1155 delete item;
1156
1157 break;
1158 }
1159 else if( evt->IsMotion() || evt->IsAction( &ACTIONS::refreshPreview ) )
1160 {
1161 delta = cursorPos - currentOffset;
1162
1163 for( SCH_ITEM* item : selectedItems )
1164 item->Move( delta );
1165
1166 currentOffset += delta;
1167 m_view->Update( &preview );
1168 }
1169 else if( evt->IsClick( BUT_RIGHT ) )
1170 {
1171 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
1172 }
1173 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT )
1174 || evt->IsAction( &ACTIONS::cursorClick ) || evt->IsAction( &ACTIONS::cursorDblClick ) )
1175 {
1176 commitImport( newItems );
1177 break;
1178 }
1179 else
1180 {
1181 evt->SetPassEvent();
1182 }
1183 }
1184
1185 preview.Clear();
1186 m_view->Remove( &preview );
1187
1188 frame()->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1189 controls->ForceCursorPosition( false );
1190
1191 return 0;
1192}
1193
1194
1196{
1197 // clang-format off
1216 // clang-format on
1217}
ARC_DRAW_MODE
Construction sequence used when interactively drawing a circular arc.
@ TANGENT
End only; start and departure direction come from a tangent seed.
ARC_DRAW_MODE StartArcDrawMode(const TOOL_EVENT &aEvent, APP_SETTINGS_BASE *aSettings, SHAPE_DRAW_BEHAVIOR &aBehavior)
Pick the mode a Draw Arc action starts in and apply it to aBehavior.
std::optional< ARC_TANGENT_SEED > ArcTangentSeedNear(const EDA_SHAPE &aShape, const VECTOR2I &aNear)
Seed the next tangent arc from whichever endpoint of aShape lies nearest aNear.
std::optional< ARC_TANGENT_SEED > ArcTangentSeedAt(const SEG &aSegment, const VECTOR2I &aPoint, int aTolerance)
Tangent seed for a point on or near a segment, arc or Bezier shape.
constexpr int ARC_SEED_PICK_PIXELS
Screen distance in pixels within which a click picks a graphic to start a tangent arc from.
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:130
BOX2< VECTOR2I > BOX2I
Definition box2.h:914
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:982
static TOOL_ACTION paste
Definition actions.h:76
static TOOL_ACTION cancelInteractive
Definition actions.h:68
static TOOL_ACTION arcPosture
Definition actions.h:269
static TOOL_ACTION updateUnits
Definition actions.h:203
static TOOL_ACTION deleteLastPoint
Definition actions.h:271
static TOOL_ACTION cursorDblClick
Definition actions.h:177
static TOOL_ACTION undo
Definition actions.h:71
static TOOL_ACTION duplicate
Definition actions.h:80
static TOOL_ACTION cycleArcDrawMode
Definition actions.h:270
static TOOL_ACTION activatePointEditor
Definition actions.h:268
static TOOL_ACTION doDelete
Definition actions.h:81
static TOOL_ACTION cursorClick
Definition actions.h:176
static TOOL_ACTION redo
Definition actions.h:72
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:220
static TOOL_ACTION refreshPreview
Definition actions.h:155
static TOOL_ACTION finishInteractive
Definition actions.h:69
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
Definition actions.h:228
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
ARC_DRAW_MODE m_ArcDrawMode
Construction sequence last used by the arc drawing tool in this application.
Interactive arc drawing behaviour.
Arc drawing mode and tangent seed bookkeeping for one pass of an editor's managed-shape draw loop.
Interactive bezier drawing behaviour: start -> control1 -> end -> control2.
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:553
constexpr bool Contains(const Vec &aPoint) const
Definition box2.h:165
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:102
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
Definition commit.h:74
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.
void AddCheckItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Add a checked menu entry to run a TOOL_ACTION on selected items.
Import a graphics file into whichever editor opened the dialog.
std::list< std::unique_ptr< EDA_ITEM > > & GetImportedItems()
void SetFilenameOverride(const wxString &aFilenameOverride)
Set the filename override to be applied in TransferDataToWindow.
int ShowModal() override
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition eda_item.cpp:270
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
FILL_T GetFillMode() const
Definition eda_shape.h:150
COLOR4D GetFillColor() const
Definition eda_shape.h:161
bool IsItalic() const
Definition eda_text.h:200
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition eda_text.h:239
virtual EDA_ANGLE GetTextAngle() const
Definition eda_text.h:178
bool IsBold() const
Definition eda_text.h:215
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition eda_text.h:242
bool Init() override
Init() is called once upon a registration of the tool.
COLOR4D m_lastTextboxFillColor
void applySymbolEditorFlags(SCH_ITEM &aItem) const
When in the symbol editor, apply unit and body-style restrictions to aItem according to the current d...
int getDefaultTextSize() const
Return the default text size (in IU) for the active editor.
int DrawEllipseArc(const TOOL_EVENT &aEvent)
STROKE_PARAMS m_lastStroke
SHAPE_DRAW_RESULT drawManagedShape(const TOOL_EVENT &aTool, std::unique_ptr< SCH_SHAPE > &aShape, SHAPE_DRAW_BEHAVIOR &aBehavior, const std::vector< VECTOR2D > &aInitialPts, const std::optional< ARC_TANGENT_SEED > &aTangentSeed=std::nullopt, VECTOR2I *aLastClick=nullptr)
Run the interactive drawing event loop for any shape driven by a SHAPE_DRAW_BEHAVIOR (arcs,...
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
GR_TEXT_H_ALIGN_T m_lastTextboxHJustify
GR_TEXT_V_ALIGN_T m_lastTextboxVJustify
int DrawArc(const TOOL_EVENT &aEvent)
void commitItem(SCH_COMMIT &aCommit, std::unique_ptr< SCH_ITEM > aItem, const wxString &aDescription)
Commit a completed item.
EDA_ANGLE m_lastTextboxAngle
VECTOR2I snapEventPosition(const TOOL_EVENT &aEvent)
Snap a tool event's position the way a click is snapped.
int DrawBezier(const TOOL_EVENT &aEvent)
int DrawShape(const TOOL_EVENT &aEvent)
STROKE_PARAMS m_lastTextboxStroke
FILL_T m_lastTextboxFillStyle
int ImportGraphics(const TOOL_EVENT &aEvent)
SCH_LAYER_ID getShapeLayer() const
The layer to use for new shapes in the current editor.
Interactive elliptical-arc drawing behaviour: bbox corner 1 -> bbox corner 2 -> start angle -> end an...
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
An interface for classes handling user events controlling the view behavior such as zooming,...
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 ShowCursor(bool aEnabled)
Enable or disables display of cursor.
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
virtual VECTOR2D GetMousePosition(bool aWorldCoordinates=true) const =0
Return the current mouse pointer position.
virtual void SetAutoPan(bool aEnabled)
Turn on/off auto panning (this feature is used when there is a tool active (eg.
Define a library symbol object.
Definition lib_symbol.h:114
void AddDrawItem(SCH_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
static TOOL_ACTION drawArcCenter
static TOOL_ACTION drawArcStartEndCenter
static TOOL_ACTION drawEllipseArc
static TOOL_ACTION drawTextBox
Definition sch_actions.h:99
static TOOL_ACTION drawArc
static TOOL_ACTION drawSymbolLines
static TOOL_ACTION drawSymbolTextBox
static TOOL_ACTION properties
static TOOL_ACTION ddImportGraphics
static TOOL_ACTION drawRectangle
static TOOL_ACTION drawEllipse
static TOOL_ACTION drawCircle
static TOOL_ACTION importGraphics
static TOOL_ACTION drawArcTangent
static TOOL_ACTION drawBezier
static TOOL_ACTION drawSymbolPolygon
static TOOL_ACTION drawPolygon
static TOOL_ACTION drawArcStartDirEnd
static TOOL_ACTION drawArcStartEndMid
static TOOL_ACTION repeatDrawItem
static const TOOL_ACTION & DrawArcForMode(ARC_DRAW_MODE aMode)
Tool action that starts the arc tool in the given mode.
A shim class between EDA_DRAW_FRAME and several derived classes: SYMBOL_EDIT_FRAME,...
Commit for the schematic and symbol editors.
Definition sch_commit.h:54
void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
A set of SCH_ITEMs (i.e., without duplicates).
Definition sch_group.h:48
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:170
virtual void SetBodyStyle(int aBodyStyle)
Definition sch_item.h:252
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition sch_item.h:353
virtual void SetUnit(int aUnit)
Definition sch_item.h:242
Segment description base class to describe items which have 2 end points (track, wire,...
Definition sch_line.h:39
bool IsGraphicLine() const
Return if the line is a graphic (non electrical line)
STROKE_PARAMS GetStroke() const override
Definition sch_shape.h:59
bool Init() override
Init() is called once upon a registration of the tool.
SCH_TOOL_BASE(const std::string &aName)
SCH_SELECTION_TOOL * m_selectionTool
RAII class that sets an value at construction and resets it to the original value at destruction.
Definition seg.h:38
virtual void Add(EDA_ITEM *aItem)
A null aItem is ignored; the selection never holds null members.
Definition selection.cpp:38
virtual void Remove(EDA_ITEM *aItem)
Definition selection.cpp:60
virtual void Clear() override
Remove all the stored items from the group.
Definition selection.h:97
Abstract interface for interactive shape-drawing behaviours.
virtual void Reset()=0
Reset the behaviour to its initial state for chained object creation loops.
virtual bool IsComplete() const =0
True when all points have been locked in.
virtual void SetCursorPosition(const VECTOR2I &aPosition)=0
Preview the cursor position without advancing state.
virtual void SetUnits(EDA_UNITS aUnits)=0
Forward a units change to the assistant overlay.
virtual bool HasGeometryChanged() const =0
True if the geometry changed since the last call to ClearGeometryChanged().
virtual EDA_ITEM & GetAssistant()=0
Return the visual assistant overlay item.
virtual void ClearGeometryChanged()=0
Reset the geometry-changed flag (call after updating the preview).
virtual void ApplyToShape(EDA_SHAPE &aShape) const =0
Transfer the current geometry to an EDA_SHAPE.
virtual void ToggleClockwise()
Flip arc direction (applies only when the shape has such a concept of directionality,...
The symbol library editor main window.
bool GetDrawSpecificUnit() const
bool GetDrawSpecificBodyStyle() const
LIB_SYMBOL * GetCurSymbol() const
Return the current symbol being edited or NULL if none selected.
bool IsSymbolGraphicallyEditable() const
Test if a symbol is loaded and can be edited graphically.
SCH_BASE_FRAME * getModel() const
Definition tool_base.h:195
KIGFX::VIEW_CONTROLS * getViewControls() const
Definition tool_base.cpp:40
KIGFX::VIEW * getView() const
Definition tool_base.cpp:34
Generic, UI-independent tool event.
Definition tool_event.h:167
bool HasPosition() const
Returns if it this event has a valid position (true for mouse events and context-menu or hotkey-based...
Definition tool_event.h:256
bool DisableGridSnapping() const
Definition tool_event.h:367
bool HasParameter() const
Definition tool_event.h:460
bool IsCancelInteractive() const
Indicate the event should restart/end an ongoing interactive tool's event loop (eg esc key,...
bool IsActivate() const
Definition tool_event.h:341
const VECTOR2D Position() const
Return mouse cursor position in world coordinates.
Definition tool_event.h:289
bool IsClick(int aButtonMask=BUT_ANY) const
int Modifier(int aMask=MD_MODIFIER_MASK) const
Return information about key modifiers state (Ctrl, Alt, etc.).
Definition tool_event.h:362
bool IsMoveTool() const
Indicate if the event is from one of the move tools.
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
T Parameter() const
Return a parameter assigned to the event.
Definition tool_event.h:484
bool IsDblClick(int aButtonMask=BUT_ANY) const
bool IsPointEditor() const
Indicate if the event is from one of the point editors.
void SetPassEvent(bool aPass=true)
Definition tool_event.h:252
bool IsMotion() const
Definition tool_event.h:326
void Go(int(SCH_BASE_FRAME::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
std::unique_ptr< TOOL_MENU > m_menu
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
@ MOVING
Definition cursors.h:45
@ ARROW
Definition cursors.h:43
@ PENCIL
Definition cursors.h:49
#define DEFAULT_TEXT_SIZE
The default text size in mils. (can be changed in preference menu)
#define UNSPECIFIED
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:448
FILL_T
Definition eda_fill.h:29
@ NO_FILL
Definition eda_fill.h:30
#define IS_NEW
New item, just created.
SHAPE_T
Definition eda_shape.h:54
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:57
@ ELLIPSE_ARC
Definition eda_shape.h:63
SCOPED_SET_RESET< EE_GRAPHIC_TOOL::MODE > SCOPED_DRAW_MODE
@ GRID_GRAPHICS
Definition grid_helper.h:63
SCH_LAYER_ID
Eeschema drawing layers.
Definition layer_ids.h:477
@ LAYER_DEVICE
Definition layer_ids.h:494
@ LAYER_NOTES
Definition layer_ids.h:495
Class to handle a set of SCH_ITEMs.
std::vector< EDA_ITEM * > EDA_ITEMS
SHAPE_DRAW_RESULT
Outcome of an interactive shape drawing loop, telling the caller how to continue.
@ NEXT_SHAPE
Commit the shape, if any, and start drawing another.
@ FINISHED
The user finished; commit the shape, if any, and stop drawing.
@ CANCELLED
The user cancelled; nothing to commit, stop drawing.
LINE_STYLE
Dashed line types.
VECTOR2I position
#define ALL_UNITS
Definition symbol.h:150
#define ALL_BODY_STYLES
Definition symbol.h:151
wxString result
Test unit parsing edge cases and error handling.
int delta
@ GR_TEXT_H_ALIGN_LEFT
@ GR_TEXT_V_ALIGN_TOP
@ MD_SHIFT
Definition tool_event.h:139
@ BUT_LEFT
Definition tool_event.h:128
@ BUT_RIGHT
Definition tool_event.h:129
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:70
@ SCH_LINE_T
Definition typeinfo.h:159
@ SCH_SHAPE_T
Definition typeinfo.h:145
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708
VECTOR2< double > VECTOR2D
Definition vector2d.h:707