KiCad PCB EDA Suite
Loading...
Searching...
No Matches
ee_point_editor.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-2023 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 <functional>
26using namespace std::placeholders;
27
28#include "ee_point_editor.h"
29#include <ee_grid_helper.h>
30#include <tool/tool_manager.h>
31#include <sch_commit.h>
32#include <view/view_controls.h>
34#include <geometry/seg.h>
35#include <tools/ee_actions.h>
37#include <sch_edit_frame.h>
38#include <sch_line.h>
39#include <sch_bitmap.h>
40#include <sch_sheet.h>
41#include <sch_textbox.h>
42#include <sch_table.h>
43#include <sch_tablecell.h>
44#include <sch_shape.h>
45#include <symbol_edit_frame.h>
46
47
48// Few constants to avoid using bare numbers for point indices
50{
52};
53
54
56{
58};
59
60
62{
64};
65
66
68{
70};
71
73{
75};
76
78{
80};
81
82
84{
89};
90
91
93{
94public:
95 static std::shared_ptr<EDIT_POINTS> Make( EDA_ITEM* aItem, SCH_BASE_FRAME* frame )
96 {
97 std::shared_ptr<EDIT_POINTS> points = std::make_shared<EDIT_POINTS>( aItem );
98
99 if( !aItem )
100 return points;
101
102 // Generate list of edit points based on the item type
103 switch( aItem->Type() )
104 {
105 case SCH_SHAPE_T:
106 {
107 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
108
109 switch( shape->GetShape() )
110 {
111 case SHAPE_T::ARC:
112 points->AddPoint( shape->GetPosition() );
113 points->AddPoint( shape->GetStart() );
114 points->AddPoint( shape->GetEnd() );
115 break;
116
117 case SHAPE_T::CIRCLE:
118 points->AddPoint( shape->GetPosition() );
119 points->AddPoint( shape->GetEnd() );
120 break;
121
122 case SHAPE_T::RECTANGLE:
123 {
124 shape->Normalize();
125
126 VECTOR2I topLeft = shape->GetPosition();
127 VECTOR2I botRight = shape->GetEnd();
128
129 points->AddPoint( topLeft );
130 points->AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
131 points->AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
132 points->AddPoint( botRight );
133
134 points->AddLine( points->Point( RECT_TOPLEFT ), points->Point( RECT_TOPRIGHT ) );
135 points->Line( RECT_TOP ).SetConstraint( new EC_PERPLINE( points->Line( RECT_TOP ) ) );
136 points->AddLine( points->Point( RECT_TOPRIGHT ), points->Point( RECT_BOTRIGHT ) );
137 points->Line( RECT_RIGHT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_RIGHT ) ) );
138 points->AddLine( points->Point( RECT_BOTRIGHT ), points->Point( RECT_BOTLEFT ) );
139 points->Line( RECT_BOT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_BOT ) ) );
140 points->AddLine( points->Point( RECT_BOTLEFT ), points->Point( RECT_TOPLEFT ) );
141 points->Line( RECT_LEFT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_LEFT ) ) );
142
143 break;
144 }
145
146 case SHAPE_T::POLY:
147 for( const VECTOR2I& pt : shape->GetPolyShape().Outline( 0 ).CPoints() )
148 points->AddPoint( pt );
149
150 break;
151
152 case SHAPE_T::BEZIER:
153 points->AddPoint( shape->GetStart() );
154 points->AddPoint( shape->GetBezierC1() );
155 points->AddPoint( shape->GetBezierC2() );
156 points->AddPoint( shape->GetEnd() );
157 break;
158
159 default:
161 }
162
163 break;
164 }
165
166 case SCH_RULE_AREA_T:
167 {
168 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
169
170 for( const VECTOR2I& pt : shape->GetPolyShape().Outline( 0 ).CPoints() )
171 points->AddPoint( pt );
172
173 break;
174 }
175
176 case SCH_TEXTBOX_T:
177 {
178 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( aItem );
179
180 textbox->Normalize();
181
182 VECTOR2I topLeft = textbox->GetPosition();
183 VECTOR2I botRight = textbox->GetEnd();
184
185 points->AddPoint( topLeft );
186 points->AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
187 points->AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
188 points->AddPoint( botRight );
189
190 points->AddLine( points->Point( RECT_TOPLEFT ), points->Point( RECT_TOPRIGHT ) );
191 points->Line( RECT_TOP ).SetConstraint( new EC_PERPLINE( points->Line( RECT_TOP ) ) );
192 points->AddLine( points->Point( RECT_TOPRIGHT ), points->Point( RECT_BOTRIGHT ) );
193 points->Line( RECT_RIGHT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_RIGHT ) ) );
194 points->AddLine( points->Point( RECT_BOTRIGHT ), points->Point( RECT_BOTLEFT ) );
195 points->Line( RECT_BOT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_BOT ) ) );
196 points->AddLine( points->Point( RECT_BOTLEFT ), points->Point( RECT_TOPLEFT ) );
197 points->Line( RECT_LEFT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_LEFT ) ) );
198
199 break;
200 }
201
202 case SCH_TABLECELL_T:
203 {
204 SCH_TABLECELL* cell = static_cast<SCH_TABLECELL*>( aItem );
205 points->AddPoint( cell->GetEnd() - VECTOR2I( 0, cell->GetRectangleHeight() / 2 ) );
206 points->AddPoint( cell->GetEnd() - VECTOR2I( cell->GetRectangleWidth() / 2, 0 ) );
207 break;
208 }
209
210 case SCH_SHEET_T:
211 {
212 SCH_SHEET* sheet = (SCH_SHEET*) aItem;
213 VECTOR2I topLeft = sheet->GetPosition();
214 VECTOR2I botRight = sheet->GetPosition() + sheet->GetSize();
215
216 points->AddPoint( topLeft );
217 points->AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
218 points->AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
219 points->AddPoint( botRight );
220
221 points->AddLine( points->Point( RECT_TOPLEFT ), points->Point( RECT_TOPRIGHT ) );
222 points->Line( RECT_TOP ).SetConstraint( new EC_PERPLINE( points->Line( RECT_TOP ) ) );
223 points->AddLine( points->Point( RECT_TOPRIGHT ), points->Point( RECT_BOTRIGHT ) );
224 points->Line( RECT_RIGHT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_RIGHT ) ) );
225 points->AddLine( points->Point( RECT_BOTRIGHT ), points->Point( RECT_BOTLEFT ) );
226 points->Line( RECT_BOT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_BOT ) ) );
227 points->AddLine( points->Point( RECT_BOTLEFT ), points->Point( RECT_TOPLEFT ) );
228 points->Line( RECT_LEFT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_LEFT ) ) );
229
230 break;
231 }
232
233 case SCH_BITMAP_T:
234 {
235 SCH_BITMAP* bitmap = (SCH_BITMAP*) aItem;
236 VECTOR2I topLeft = bitmap->GetPosition() - bitmap->GetSize() / 2;
237 VECTOR2I botRight = bitmap->GetPosition() + bitmap->GetSize() / 2;
238
239 points->AddPoint( topLeft );
240 points->AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
241 points->AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
242 points->AddPoint( botRight );
243 break;
244 }
245
246 case SCH_LINE_T:
247 {
248 SCH_LINE* line = (SCH_LINE*) aItem;
249 std::pair<EDA_ITEM*, int> connectedStart = { nullptr, STARTPOINT };
250 std::pair<EDA_ITEM*, int> connectedEnd = { nullptr, STARTPOINT };
251
252 for( SCH_ITEM* test : frame->GetScreen()->Items().OfType( SCH_LINE_T ) )
253 {
254 if( test->GetLayer() != LAYER_NOTES )
255 continue;
256
257 if( test == aItem )
258 continue;
259
260 SCH_LINE* testLine = static_cast<SCH_LINE*>( test );
261
262 if( testLine->GetStartPoint() == line->GetStartPoint() )
263 {
264 connectedStart = { testLine, STARTPOINT };
265 }
266 else if( testLine->GetEndPoint() == line->GetStartPoint() )
267 {
268 connectedStart = { testLine, ENDPOINT };
269 }
270 else if( testLine->GetStartPoint() == line->GetEndPoint() )
271 {
272 connectedEnd = { testLine, STARTPOINT };
273 }
274 else if( testLine->GetEndPoint() == line->GetEndPoint() )
275 {
276 connectedEnd = { testLine, ENDPOINT };
277 }
278 }
279
280 points->AddPoint( line->GetStartPoint(), connectedStart );
281 points->AddPoint( line->GetEndPoint(), connectedEnd );
282 break;
283 }
284
285 default:
286 points.reset();
287 break;
288 }
289
290 return points;
291 }
292
293private:
295};
296
297
299 EE_TOOL_BASE<SCH_BASE_FRAME>( "eeschema.PointEditor" ),
300 m_editedPoint( nullptr ),
301 m_inPointEditor( false )
302{
303}
304
305
307{
308 EE_TOOL_BASE::Reset( aReason );
309
310 m_editPoints.reset();
311 m_editedPoint = nullptr;
312}
313
314
316{
318
319 auto& menu = m_selectionTool->GetToolMenu().GetMenu();
321 std::bind( &EE_POINT_EDITOR::addCornerCondition, this, _1 ) );
323 std::bind( &EE_POINT_EDITOR::removeCornerCondition, this, _1 ) );
324
325 return true;
326}
327
328
330{
331 setEditedPoint( nullptr );
332
333 return 0;
334}
335
336
338{
339 EDIT_POINT* point = m_editedPoint;
340
341 if( !m_editPoints )
342 {
343 point = nullptr;
344 }
345 else if( aEvent.IsMotion() )
346 {
347 point = m_editPoints->FindPoint( aEvent.Position(), getView() );
348 }
349 else if( aEvent.IsDrag( BUT_LEFT ) )
350 {
351 point = m_editPoints->FindPoint( aEvent.DragOrigin(), getView() );
352 }
353 else
354 {
355 point = m_editPoints->FindPoint( getViewControls()->GetCursorPosition( false ), getView() );
356 }
357
358 if( m_editedPoint != point )
359 setEditedPoint( point );
360}
361
362
364{
365 if( !m_selectionTool )
366 return 0;
367
368 if( m_inPointEditor )
369 return 0;
370
372
373 if( m_isSymbolEditor )
374 {
375 SYMBOL_EDIT_FRAME* editor = getEditFrame<SYMBOL_EDIT_FRAME>();
376
377 if( !editor->IsSymbolEditable() || editor->IsSymbolAlias() )
378 return 0;
379 }
380
381 const EE_SELECTION& selection = m_selectionTool->GetSelection();
382
383 if( selection.Size() != 1 || !selection.Front()->IsType( { SCH_SHAPE_T,
384 SCH_RULE_AREA_T,
385 SCH_TEXTBOX_T,
386 SCH_TABLECELL_T,
387 SCH_SHEET_T,
388 SCH_ITEM_LOCATE_GRAPHIC_LINE_T,
389 SCH_BITMAP_T } ) )
390 {
391 return 0;
392 }
393
394 // Wait till drawing tool is done
395 if( selection.Front()->IsNew() )
396 return 0;
397
398 Activate();
399
402 VECTOR2I cursorPos;
403 KIGFX::VIEW* view = getView();
404 EDA_ITEM* item = selection.Front();
405 SCH_COMMIT commit( m_toolMgr );
406
407 controls->ShowCursor( true );
408
410 view->Add( m_editPoints.get() );
411 setEditedPoint( nullptr );
412 updateEditedPoint( aEvent );
413 bool inDrag = false;
414
415 // Main loop: keep receiving events
416 while( TOOL_EVENT* evt = Wait() )
417 {
418 if( grid )
419 {
420 grid->SetSnap( !evt->Modifier( MD_SHIFT ) );
421 grid->SetUseGrid( getView()->GetGAL()->GetGridSnapping()
422 && !evt->DisableGridSnapping() );
423 }
424 else
425 {
426 // This check is based on the assumption that the grid object must be valid.
427 // If this assumption is wrong, please fix the code above.
428 wxCHECK( false, 0 );
429 }
430
431 if( !m_editPoints || evt->IsSelectionEvent() )
432 break;
433
434 if ( !inDrag )
435 updateEditedPoint( *evt );
436
437 if( evt->IsDrag( BUT_LEFT ) && m_editedPoint )
438 {
439 if( !inDrag )
440 {
441 commit.Modify( m_editPoints->GetParent(), m_frame->GetScreen() );
442
443 if( m_editPoints->GetParent()->Type() == SCH_LINE_T )
444 {
445 std::pair<EDA_ITEM*, int> connected = m_editPoints->Point( LINE_START ).GetConnected();
446
447 if( connected.first )
448 commit.Modify( connected.first, m_frame->GetScreen() );
449
450 connected = m_editPoints->Point( LINE_END ).GetConnected();
451
452 if( connected.first )
453 commit.Modify( connected.first, m_frame->GetScreen() );
454 }
455 else if( m_editPoints->GetParent()->Type() == SCH_TABLECELL_T )
456 {
457 SCH_TABLECELL* cell = static_cast<SCH_TABLECELL*>( m_editPoints->GetParent() );
458 SCH_TABLE* table = static_cast<SCH_TABLE*>( cell->GetParent() );
459
460 commit.Modify( table, m_frame->GetScreen() );
461 }
462
463 inDrag = true;
464 }
465
466 bool snap = !evt->DisableGridSnapping();
467
468 cursorPos =
469 grid->Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
470 controls->ForceCursorPosition( true, cursorPos );
471
472 m_editedPoint->SetPosition( controls->GetCursorPosition( snap ) );
473
474 updateParentItem( snap );
475 updatePoints();
476 }
477 else if( inDrag && evt->IsMouseUp( BUT_LEFT ) )
478 {
479 if( !commit.Empty() )
480 commit.Push( _( "Move Point" ) );
481
482 controls->SetAutoPan( false );
483 inDrag = false;
484 }
485 else if( evt->IsCancelInteractive() || evt->IsActivate() )
486 {
487 if( inDrag ) // Restore the last change
488 {
489 // Currently we are manually managing the lifetime of the grid
490 // helpers because there is a bug in the tool stack that adds
491 // the point editor again when commit.Revert() rebuilds the selection.
492 // We remove this grid here so the its destructor is called before it
493 // is added again.
494 if( grid )
495 {
496 delete grid;
497 grid = nullptr;
498 }
499
500 commit.Revert();
501 inDrag = false;
502 break;
503 }
504 else if( evt->IsCancelInteractive() )
505 {
506 break;
507 }
508
509 if( evt->IsActivate() )
510 break;
511 }
512 else
513 {
514 evt->SetPassEvent();
515 }
516
517 controls->SetAutoPan( inDrag );
518 controls->CaptureCursor( inDrag );
519 }
520
521 controls->SetAutoPan( false );
522 controls->CaptureCursor( false );
523 setEditedPoint( nullptr );
524
525 if( m_editPoints )
526 {
527 view->Remove( m_editPoints.get() );
528
529 m_editPoints.reset();
531 }
532
533 delete grid;
534
535 return 0;
536}
537
548void EE_POINT_EDITOR::pinEditedCorner( int minWidth, int minHeight, VECTOR2I& topLeft,
549 VECTOR2I& topRight, VECTOR2I& botLeft, VECTOR2I& botRight,
550 EE_GRID_HELPER* aGrid ) const
551{
552 if( isModified( m_editPoints->Point( RECT_TOPLEFT ) ) )
553 {
554 // pin edited point within opposite corner
555 topLeft.x = std::min( topLeft.x, botRight.x - minWidth );
556 topLeft.y = std::min( topLeft.y, botRight.y - minHeight );
557
558 if( aGrid->GetSnap() )
559 topLeft = aGrid->AlignGrid( topLeft, GRID_HELPER_GRIDS::GRID_GRAPHICS );
560
561 // push edited point edges to adjacent corners
562 topRight.y = topLeft.y;
563 botLeft.x = topLeft.x;
564 }
565 else if( isModified( m_editPoints->Point( RECT_TOPRIGHT ) ) )
566 {
567 // pin edited point within opposite corner
568 topRight.x = std::max( topRight.x, botLeft.x + minWidth );
569 topRight.y = std::min( topRight.y, botLeft.y - minHeight );
570
571 if( aGrid->GetSnap() )
572 topRight = aGrid->AlignGrid( topRight, GRID_HELPER_GRIDS::GRID_GRAPHICS );
573
574 // push edited point edges to adjacent corners
575 topLeft.y = topRight.y;
576 botRight.x = topRight.x;
577 }
578 else if( isModified( m_editPoints->Point( RECT_BOTLEFT ) ) )
579 {
580 // pin edited point within opposite corner
581 botLeft.x = std::min( botLeft.x, topRight.x - minWidth );
582 botLeft.y = std::max( botLeft.y, topRight.y + minHeight );
583
584 if( aGrid->GetSnap() )
585 botLeft = aGrid->AlignGrid( botLeft, GRID_HELPER_GRIDS::GRID_GRAPHICS );
586
587 // push edited point edges to adjacent corners
588 botRight.y = botLeft.y;
589 topLeft.x = botLeft.x;
590 }
591 else if( isModified( m_editPoints->Point( RECT_BOTRIGHT ) ) )
592 {
593 // pin edited point within opposite corner
594 botRight.x = std::max( botRight.x, topLeft.x + minWidth );
595 botRight.y = std::max( botRight.y, topLeft.y + minHeight );
596
597 if( aGrid->GetSnap() )
598 botRight = aGrid->AlignGrid( botRight, GRID_HELPER_GRIDS::GRID_GRAPHICS );
599
600 // push edited point edges to adjacent corners
601 botLeft.y = botRight.y;
602 topRight.x = botRight.x;
603 }
604 else if( isModified( m_editPoints->Line( RECT_TOP ) ) )
605 {
606 topLeft.y = std::min( topLeft.y, botRight.y - minHeight );
607
608 if( aGrid->GetSnap() )
609 topLeft = aGrid->AlignGrid( topLeft, GRID_HELPER_GRIDS::GRID_GRAPHICS );
610 }
611 else if( isModified( m_editPoints->Line( RECT_LEFT ) ) )
612 {
613 topLeft.x = std::min( topLeft.x, botRight.x - minWidth );
614
615 if( aGrid->GetSnap() )
616 topLeft = aGrid->AlignGrid( topLeft, GRID_HELPER_GRIDS::GRID_GRAPHICS );
617 }
618 else if( isModified( m_editPoints->Line( RECT_BOT ) ) )
619 {
620 botRight.y = std::max( botRight.y, topLeft.y + minHeight );
621
622 if( aGrid->GetSnap() )
623 botRight = aGrid->AlignGrid( botRight, GRID_HELPER_GRIDS::GRID_GRAPHICS );
624 }
625 else if( isModified( m_editPoints->Line( RECT_RIGHT ) ) )
626 {
627 botRight.x = std::max( botRight.x, topLeft.x + minWidth );
628
629 if( aGrid->GetSnap() )
630 botRight = aGrid->AlignGrid( botRight, GRID_HELPER_GRIDS::GRID_GRAPHICS );
631 }
632}
633
634
635void EE_POINT_EDITOR::updateParentItem( bool aSnapToGrid ) const
636{
637 EDA_ITEM* item = m_editPoints->GetParent();
638
639 if( !item )
640 return;
641
642 switch( item->Type() )
643 {
644 case SCH_RULE_AREA_T:
645 case SCH_SHAPE_T:
646 {
647 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( item );
648
649 switch( shape->GetShape() )
650 {
651 case SHAPE_T::ARC:
653 {
654 shape->SetEditState( 4 );
655 shape->CalcEdit( m_editPoints->Point( ARC_CENTER ).GetPosition() );
656 }
657 else if( getEditedPointIndex() == ARC_START )
658 {
659 shape->SetEditState( 2 );
660 shape->CalcEdit( m_editPoints->Point( ARC_START ).GetPosition() );
661 }
662 else if( getEditedPointIndex() == ARC_END )
663 {
664 shape->SetEditState( 3 );
665 shape->CalcEdit( m_editPoints->Point( ARC_END ).GetPosition() );
666 }
667 break;
668
669 case SHAPE_T::CIRCLE:
670 shape->SetPosition( m_editPoints->Point( CIRC_CENTER ).GetPosition() );
671 shape->SetEnd( m_editPoints->Point( CIRC_END ).GetPosition() );
672 break;
673
674 case SHAPE_T::POLY:
676 shape->GetPolyShape().NewOutline();
677
678 for( unsigned i = 0; i < m_editPoints->PointsSize(); ++i )
679 {
680 VECTOR2I pt = m_editPoints->Point( i ).GetPosition();
681 shape->GetPolyShape().Append( pt.x, pt.y, -1, -1, true );
682 }
683
684 break;
685
686 case SHAPE_T::RECTANGLE:
687 {
688 EE_GRID_HELPER gridHelper( m_toolMgr );
689 VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
690 VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
691 VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
692 VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
693
694 gridHelper.SetSnap( aSnapToGrid );
695
696 pinEditedCorner( schIUScale.MilsToIU( 1 ), schIUScale.MilsToIU( 1 ), topLeft, topRight,
697 botLeft, botRight, &gridHelper );
698
699 if( isModified( m_editPoints->Point( RECT_TOPLEFT ) )
702 || isModified( m_editPoints->Point( RECT_BOTLEFT ) ) )
703 {
704 shape->SetPosition( topLeft );
705 shape->SetEnd( botRight );
706 }
707 else if( isModified( m_editPoints->Line( RECT_TOP ) ) )
708 {
709 shape->SetStartY( topLeft.y );
710 }
711 else if( isModified( m_editPoints->Line( RECT_LEFT ) ) )
712 {
713 shape->SetStartX( topLeft.x );
714 }
715 else if( isModified( m_editPoints->Line( RECT_BOT ) ) )
716 {
717 shape->SetEndY( botRight.y );
718 }
719 else if( isModified( m_editPoints->Line( RECT_RIGHT ) ) )
720 {
721 shape->SetEndX( botRight.x );
722 }
723
724 for( unsigned i = 0; i < m_editPoints->LinesSize(); ++i )
725 {
726 if( !isModified( m_editPoints->Line( i ) ) )
727 {
728 m_editPoints->Line( i ).SetConstraint(
729 new EC_PERPLINE( m_editPoints->Line( i ) ) );
730 }
731 }
732
733 break;
734 }
735
736 case SHAPE_T::BEZIER:
737 shape->SetStart( m_editPoints->Point( BEZIER_START ).GetPosition() );
738 shape->SetBezierC1( m_editPoints->Point( BEZIER_CTRL_PT1 ).GetPosition() );
739 shape->SetBezierC2( m_editPoints->Point( BEZIER_CTRL_PT2 ).GetPosition() );
740 shape->SetEnd( m_editPoints->Point( BEZIER_END ).GetPosition() );
741
743 break;
744
745 default:
747 }
748
749 break;
750 }
751
752 case SCH_TEXTBOX_T:
753 {
754 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( item );
755 EE_GRID_HELPER gridHelper( m_toolMgr );
756 VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
757 VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
758 VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
759 VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
760
761 gridHelper.SetSnap( aSnapToGrid );
762
763 pinEditedCorner( schIUScale.MilsToIU( 1 ), schIUScale.MilsToIU( 1 ), topLeft, topRight,
764 botLeft, botRight, &gridHelper );
765
766 if( isModified( m_editPoints->Point( RECT_TOPLEFT ) )
769 || isModified( m_editPoints->Point( RECT_BOTLEFT ) ) )
770 {
771 textbox->SetPosition( topLeft );
772 textbox->SetEnd( botRight );
773 }
774 else if( isModified( m_editPoints->Line( RECT_TOP ) ) )
775 {
776 textbox->SetStartY( topLeft.y );
777 }
778 else if( isModified( m_editPoints->Line( RECT_LEFT ) ) )
779 {
780 textbox->SetStartX( topLeft.x );
781 }
782 else if( isModified( m_editPoints->Line( RECT_BOT ) ) )
783 {
784 textbox->SetEndY( botRight.y );
785 }
786 else if( isModified( m_editPoints->Line( RECT_RIGHT ) ) )
787 {
788 textbox->SetEndX( botRight.x );
789 }
790
791 for( unsigned i = 0; i < m_editPoints->LinesSize(); ++i )
792 {
793 if( !isModified( m_editPoints->Line( i ) ) )
794 {
795 m_editPoints->Line( i ).SetConstraint(
796 new EC_PERPLINE( m_editPoints->Line( i ) ) );
797 }
798 }
799
800 textbox->ClearRenderCache();
801 break;
802 }
803
804 case SCH_TABLECELL_T:
805 {
806 SCH_TABLECELL* cell = static_cast<SCH_TABLECELL*>( item );
807 SCH_TABLE* table = static_cast<SCH_TABLE*>( cell->GetParent() );
808
809 if( isModified( m_editPoints->Point( COL_WIDTH ) ) )
810 {
811 cell->SetEnd( VECTOR2I( m_editPoints->Point( 0 ).GetX(), cell->GetEndY() ) );
812
813 int colWidth = cell->GetRectangleWidth();
814
815 for( int ii = 0; ii < cell->GetColSpan() - 1; ++ii )
816 colWidth -= table->GetColWidth( cell->GetColumn() + ii );
817
818 table->SetColWidth( cell->GetColumn() + cell->GetColSpan() - 1, colWidth );
819 table->Normalize();
820 }
821 else if( isModified( m_editPoints->Point( ROW_HEIGHT ) ) )
822 {
823 cell->SetEnd( VECTOR2I( cell->GetEndX(), m_editPoints->Point( 1 ).GetY() ) );
824
825 int rowHeight = cell->GetRectangleHeight();
826
827 for( int ii = 0; ii < cell->GetRowSpan() - 1; ++ii )
828 rowHeight -= table->GetRowHeight( cell->GetRow() + ii );
829
830 table->SetRowHeight( cell->GetRow() + cell->GetRowSpan() - 1, rowHeight );
831 table->Normalize();
832 }
833
834 break;
835 }
836
837 case SCH_BITMAP_T:
838 {
839 EE_GRID_HELPER gridHelper( m_toolMgr );
840 SCH_BITMAP* bitmap = (SCH_BITMAP*) item;
841 VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
842 VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
843 VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
844 VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
845
846 gridHelper.SetSnap( aSnapToGrid );
847
848 pinEditedCorner( schIUScale.MilsToIU( 50 ), schIUScale.MilsToIU( 50 ), topLeft, topRight,
849 botLeft, botRight, &gridHelper );
850
851 double oldWidth = bitmap->GetSize().x;
852 double newWidth = topRight.x - topLeft.x;
853 double widthRatio = newWidth / oldWidth;
854
855 double oldHeight = bitmap->GetSize().y;
856 double newHeight = botLeft.y - topLeft.y;
857 double heightRatio = newHeight / oldHeight;
858
859 bitmap->SetImageScale( bitmap->GetImageScale() * std::min( widthRatio, heightRatio ) );
860 break;
861 }
862
863 case SCH_SHEET_T:
864 {
865 SCH_SHEET* sheet = (SCH_SHEET*) item;
866 EE_GRID_HELPER gridHelper( m_toolMgr );
867 VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
868 VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
869 VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
870 VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
871 VECTOR2I sheetNewPos = sheet->GetPosition();
872 VECTOR2I sheetNewSize = sheet->GetSize();
873
874 gridHelper.SetSnap( aSnapToGrid );
875
876 int edited = getEditedPointIndex();
877
878 if( isModified( m_editPoints->Line( RECT_RIGHT ) ) )
879 edited = RECT_TOPRIGHT;
880 else if( isModified( m_editPoints->Line( RECT_BOT ) ) )
881 edited = RECT_BOTLEFT;
882
883 gridHelper.SetSnap( aSnapToGrid );
884
885 pinEditedCorner( sheet->GetMinWidth( edited == RECT_TOPRIGHT || edited == RECT_BOTRIGHT ),
886 sheet->GetMinHeight( edited == RECT_BOTLEFT || edited == RECT_BOTRIGHT ),
887 topLeft, topRight, botLeft, botRight, &gridHelper );
888
889 if( isModified( m_editPoints->Point( RECT_TOPLEFT ) )
892 || isModified( m_editPoints->Point( RECT_BOTLEFT ) ) )
893 {
894 sheetNewPos = topLeft;
895 sheetNewSize = VECTOR2I( botRight.x - topLeft.x, botRight.y - topLeft.y );
896 }
897 else if( isModified( m_editPoints->Line( RECT_TOP ) ) )
898 {
899 sheetNewPos = VECTOR2I( sheet->GetPosition().x, topLeft.y );
900 sheetNewSize = VECTOR2I( sheet->GetSize().x, botRight.y - topLeft.y );
901 }
902 else if( isModified( m_editPoints->Line( RECT_LEFT ) ) )
903 {
904 sheetNewPos = VECTOR2I( topLeft.x, sheet->GetPosition().y );
905 sheetNewSize = VECTOR2I( botRight.x - topLeft.x, sheet->GetSize().y );
906 }
907 else if( isModified( m_editPoints->Line( RECT_BOT ) ) )
908 {
909 sheetNewSize = VECTOR2I( sheet->GetSize().x, botRight.y - topLeft.y );
910 }
911 else if( isModified( m_editPoints->Line( RECT_RIGHT ) ) )
912 {
913 sheetNewSize = VECTOR2I( botRight.x - topLeft.x, sheet->GetSize().y );
914 }
915
916 for( unsigned i = 0; i < m_editPoints->LinesSize(); ++i )
917 {
918 if( !isModified( m_editPoints->Line( i ) ) )
919 {
920 m_editPoints->Line( i ).SetConstraint(
921 new EC_PERPLINE( m_editPoints->Line( i ) ) );
922 }
923 }
924
925 if( sheet->GetPosition() != sheetNewPos )
926 sheet->SetPositionIgnoringPins( sheetNewPos );
927
928 if( sheet->GetSize() != sheetNewSize )
929 sheet->Resize( sheetNewSize );
930
931 break;
932 }
933
934 case SCH_LINE_T:
935 {
936 SCH_LINE* line = (SCH_LINE*) item;
937
938 line->SetStartPoint( m_editPoints->Point( LINE_START ).GetPosition() );
939 line->SetEndPoint( m_editPoints->Point( LINE_END ).GetPosition() );
940
941 std::pair<EDA_ITEM*, int> connected = m_editPoints->Point( LINE_START ).GetConnected();
942
943 if( connected.first )
944 {
945 if( connected.second == STARTPOINT )
946 static_cast<SCH_LINE*>( connected.first )->SetStartPoint( line->GetStartPoint() );
947 else if( connected.second == ENDPOINT )
948 static_cast<SCH_LINE*>( connected.first )->SetEndPoint( line->GetStartPoint() );
949
950 updateItem( connected.first, true );
951 }
952
953 connected = m_editPoints->Point( LINE_END ).GetConnected();
954
955 if( connected.first )
956 {
957 if( connected.second == STARTPOINT )
958 static_cast<SCH_LINE*>( connected.first )->SetStartPoint( line->GetEndPoint() );
959 else if( connected.second == ENDPOINT )
960 static_cast<SCH_LINE*>( connected.first )->SetEndPoint( line->GetEndPoint() );
961
962 updateItem( connected.first, true );
963 }
964
965 break;
966 }
967
968 default:
969 break;
970 }
971
972 updateItem( item, true );
973 m_frame->SetMsgPanel( item );
974}
975
976
978{
979 if( !m_editPoints )
980 return;
981
982 EDA_ITEM* item = m_editPoints->GetParent();
983
984 if( !item )
985 return;
986
987 switch( item->Type() )
988 {
989 case SCH_RULE_AREA_T:
990 case SCH_SHAPE_T:
991 {
992 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( item );
993
994 switch( shape->GetShape() )
995 {
996 case SHAPE_T::ARC:
997 m_editPoints->Point( ARC_CENTER ).SetPosition( shape->GetPosition() );
998 m_editPoints->Point( ARC_START ).SetPosition( shape->GetStart() );
999 m_editPoints->Point( ARC_END ).SetPosition( shape->GetEnd() );
1000 break;
1001
1002 case SHAPE_T::CIRCLE:
1003 m_editPoints->Point( CIRC_CENTER ).SetPosition( shape->GetPosition() );
1004 m_editPoints->Point( CIRC_END ).SetPosition( shape->GetEnd() );
1005 break;
1006
1007 case SHAPE_T::POLY:
1008 {
1009 if( (int) m_editPoints->PointsSize() != shape->GetPointCount() )
1010 {
1011 getView()->Remove( m_editPoints.get() );
1012 m_editedPoint = nullptr;
1014 getView()->Add( m_editPoints.get() );
1015 }
1016 else
1017 {
1018 int ii = 0;
1019
1020 for( const VECTOR2I& pt : shape->GetPolyShape().Outline( 0 ).CPoints() )
1021 m_editPoints->Point( ii++ ).SetPosition( pt );
1022 }
1023
1024 break;
1025 }
1026
1027 case SHAPE_T::RECTANGLE:
1028 {
1029 // point editor works only with rectangles having width and height > 0
1030 // Some symbols can have rectangles with width or height < 0
1031 // So normalize the size:
1032 BOX2I dummy;
1033 dummy.SetOrigin( shape->GetPosition() );
1034 dummy.SetEnd( shape->GetEnd() );
1035 dummy.Normalize();
1036 VECTOR2I topLeft = dummy.GetPosition();
1037 VECTOR2I botRight = dummy.GetEnd();
1038
1039 m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
1040 m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( VECTOR2I( botRight.x, topLeft.y ) );
1041 m_editPoints->Point( RECT_BOTLEFT ).SetPosition( VECTOR2I( topLeft.x, botRight.y ) );
1042 m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
1043 break;
1044 }
1045
1046 case SHAPE_T::BEZIER:
1047 m_editPoints->Point( BEZIER_START ).SetPosition( shape->GetStart() );
1048 m_editPoints->Point( BEZIER_CTRL_PT1 ).SetPosition( shape->GetBezierC1() );
1049 m_editPoints->Point( BEZIER_CTRL_PT2 ).SetPosition( shape->GetBezierC2() );
1050 m_editPoints->Point( BEZIER_END ).SetPosition( shape->GetEnd() );
1051 break;
1052
1053 default:
1055 }
1056
1057 break;
1058 }
1059
1060 case SCH_TEXTBOX_T:
1061 {
1062 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( item );
1063
1064 // point editor works only with rectangles having width and height > 0
1065 // Some symbols can have rectangles with width or height < 0
1066 // So normalize the size:
1067 BOX2I dummy;
1068 dummy.SetOrigin( textbox->GetPosition() );
1069 dummy.SetEnd( textbox->GetEnd() );
1070 dummy.Normalize();
1071 VECTOR2I topLeft = dummy.GetPosition();
1072 VECTOR2I botRight = dummy.GetEnd();
1073
1074 m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
1075 m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( VECTOR2I( botRight.x, topLeft.y ) );
1076 m_editPoints->Point( RECT_BOTLEFT ).SetPosition( VECTOR2I( topLeft.x, botRight.y ) );
1077 m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
1078 break;
1079 }
1080
1081 case SCH_TABLECELL_T:
1082 {
1083 SCH_TABLECELL* cell = static_cast<SCH_TABLECELL*>( item );
1084
1085 m_editPoints->Point( 0 ).SetPosition( cell->GetEndX(),
1086 cell->GetEndY() - cell->GetRectangleHeight() / 2 );
1087 m_editPoints->Point( 1 ).SetPosition( cell->GetEndX() - cell->GetRectangleWidth() / 2,
1088 cell->GetEndY() );
1089 break;
1090 }
1091
1092 case SCH_BITMAP_T:
1093 {
1094 SCH_BITMAP* bitmap = (SCH_BITMAP*) item;
1095 VECTOR2I topLeft = bitmap->GetPosition() - bitmap->GetSize() / 2;
1096 VECTOR2I botRight = bitmap->GetPosition() + bitmap->GetSize() / 2;
1097
1098 m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
1099 m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
1100 m_editPoints->Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
1101 m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
1102 break;
1103 }
1104
1105 case SCH_SHEET_T:
1106 {
1107 SCH_SHEET* sheet = (SCH_SHEET*) item;
1108 VECTOR2I topLeft = sheet->GetPosition();
1109 VECTOR2I botRight = sheet->GetPosition() + sheet->GetSize();
1110
1111 m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
1112 m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
1113 m_editPoints->Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
1114 m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
1115 break;
1116 }
1117
1118 case SCH_LINE_T:
1119 {
1120 SCH_LINE* line = (SCH_LINE*) item;
1121
1122 m_editPoints->Point( LINE_START ).SetPosition( line->GetStartPoint() );
1123 m_editPoints->Point( LINE_END ).SetPosition( line->GetEndPoint() );
1124 break;
1125 }
1126
1127 default:
1128 break;
1129 }
1130
1131 getView()->Update( m_editPoints.get() );
1132}
1133
1134
1136{
1138
1139 if( aPoint )
1140 {
1141 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1142 controls->ForceCursorPosition( true, aPoint->GetPosition() );
1143 controls->ShowCursor( true );
1144 }
1145 else
1146 {
1147 if( m_frame->ToolStackIsEmpty() )
1148 controls->ShowCursor( false );
1149
1150 controls->ForceCursorPosition( false );
1151 }
1152
1153 m_editedPoint = aPoint;
1154}
1155
1156
1158{
1159 bool isRuleArea = false;
1160
1161 if( m_editPoints )
1162 isRuleArea = m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T;
1163
1165 || !( m_editPoints->GetParent()->Type() == SCH_SHAPE_T || isRuleArea ) )
1166 {
1167 return false;
1168 }
1169
1170 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1171
1172 if( shape->GetPolyShape().IsEmpty() )
1173 return false;
1174
1175 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1176
1177 if( poly.GetPointCount() < 3 )
1178 return false;
1179
1180 for( const VECTOR2I& pt : poly.CPoints() )
1181 {
1182 if( pt == m_editedPoint->GetPosition() )
1183 return true;
1184 }
1185
1186 return false;
1187}
1188
1189
1191{
1192 if( !m_editPoints
1193 || !( m_editPoints->GetParent()->Type() == SCH_SHAPE_T
1194 || m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T ) )
1195 {
1196 return false;
1197 }
1198
1199 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1200
1201 if( shape->GetShape() != SHAPE_T::POLY )
1202 return false;
1203
1204 VECTOR2I cursorPos = getViewControls()->GetCursorPosition( false );
1205 double threshold = getView()->ToWorld( EDIT_POINT::POINT_SIZE );
1206
1207 return shape->HitTest( cursorPos, (int) threshold );
1208}
1209
1210
1212{
1213 if( !m_editPoints
1214 || !( m_editPoints->GetParent()->Type() == SCH_SHAPE_T
1215 || m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T ) )
1216 return 0;
1217
1218 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1219 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1220 SCH_COMMIT commit( m_toolMgr );
1221
1222 commit.Modify( shape, m_frame->GetScreen() );
1223
1225 int currentMinDistance = INT_MAX;
1226 int closestLineStart = 0;
1227 unsigned numPoints = poly.GetPointCount();
1228
1229 if( !shape->IsClosed() )
1230 numPoints -= 1;
1231
1232 for( unsigned i = 0; i < numPoints; ++i )
1233 {
1234 int distance = (int) DistanceLinePoint( poly.CPoint( i ),
1235 poly.CPoint( i + 1 ), cursor );
1236
1237 if( distance < currentMinDistance )
1238 {
1239 currentMinDistance = distance;
1240 closestLineStart = i;
1241 }
1242 }
1243
1244 poly.Insert( closestLineStart + 1, cursor );
1245
1246 updateItem( shape, true );
1247 updatePoints();
1248
1249 commit.Push( _( "Add Corner" ) );
1250 return 0;
1251}
1252
1253
1255{
1257 || !( m_editPoints->GetParent()->Type() == SCH_SHAPE_T
1258 || m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T ) )
1259 {
1260 return 0;
1261 }
1262
1263 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1264 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1265 SCH_COMMIT commit( m_toolMgr );
1266
1267 if( poly.GetPointCount() <= 3 )
1268 return 0;
1269
1270 commit.Modify( shape, m_frame->GetScreen() );
1271
1272 poly.Remove( getEditedPointIndex() );
1273 setEditedPoint( nullptr );
1274
1275 updateItem( shape, true );
1276 updatePoints();
1277
1278 commit.Push( _( "Remove Corner" ) );
1279 return 0;
1280}
1281
1282
1284{
1285 updatePoints();
1286 return 0;
1287}
1288
1289
1291{
1299}
1300
1301
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:110
static TOOL_ACTION activatePointEditor
Definition: actions.h:205
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Create an undo entry for an item that has been already modified.
Definition: commit.h:105
bool Empty() const
Returns status of an item.
Definition: commit.h:144
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.
EDIT_CONSTRAINT for a EDIT_LINE, that constrains the line to move perpendicular to the line itself.
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
void SetCurrentCursor(KICURSOR aCursor)
Set the current cursor shape for this panel.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:88
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:100
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition: eda_item.h:175
EDA_ITEM * GetParent() const
Definition: eda_item.h:102
bool IsNew() const
Definition: eda_item.h:106
void SetStartX(int x)
Definition: eda_shape.h:141
const VECTOR2I & GetBezierC2() const
Definition: eda_shape.h:201
void SetBezierC2(const VECTOR2I &aPt)
Definition: eda_shape.h:200
void SetEndY(int aY)
Definition: eda_shape.h:172
void RebuildBezierToSegmentsPointsList(int aMinSegLen)
Rebuild the m_bezierPoints vertex list that approximate the Bezier curve by a list of segments.
Definition: eda_shape.cpp:480
int GetEndX() const
Definition: eda_shape.h:164
int GetRectangleWidth() const
Definition: eda_shape.cpp:165
void SetStartY(int y)
Definition: eda_shape.h:135
SHAPE_POLY_SET & GetPolyShape()
Definition: eda_shape.h:274
SHAPE_T GetShape() const
Definition: eda_shape.h:120
int GetEndY() const
Definition: eda_shape.h:163
void SetEndX(int aX)
Definition: eda_shape.h:178
int GetPointCount() const
Definition: eda_shape.cpp:1331
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:162
bool IsClosed() const
Definition: eda_shape.cpp:212
void SetStart(const VECTOR2I &aStart)
Definition: eda_shape.h:129
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition: eda_shape.h:125
void SetEnd(const VECTOR2I &aEnd)
Definition: eda_shape.h:166
void SetBezierC1(const VECTOR2I &aPt)
Definition: eda_shape.h:197
wxString SHAPE_T_asString() const
Definition: eda_shape.cpp:89
const VECTOR2I & GetBezierC1() const
Definition: eda_shape.h:198
int GetRectangleHeight() const
Definition: eda_shape.cpp:153
virtual int GetWidth() const
Definition: eda_shape.h:110
virtual void ClearRenderCache()
Definition: eda_text.cpp:497
static std::shared_ptr< EDIT_POINTS > Make(EDA_ITEM *aItem, SCH_BASE_FRAME *frame)
Represent a single point that can be used for modifying items.
Definition: edit_points.h:48
static const int POINT_SIZE
Definition: edit_points.h:190
virtual void SetPosition(const VECTOR2I &aPosition)
Set new coordinates for an EDIT_POINT.
Definition: edit_points.h:107
virtual VECTOR2I GetPosition() const
Return coordinates of an EDIT_POINT.
Definition: edit_points.h:71
static TOOL_ACTION pointEditorRemoveCorner
Definition: ee_actions.h:147
static TOOL_ACTION pointEditorAddCorner
Definition: ee_actions.h:146
void updatePoints()
Update which point is being edited.
bool m_inPointEditor
Currently available edit points.
int Main(const TOOL_EVENT &aEvent)
void updateEditedPoint(const TOOL_EVENT &aEvent)
Clear references to the points.
void setEditedPoint(EDIT_POINT *aPoint)
Return true if aPoint is the currently modified point.
int modifiedSelection(const TOOL_EVENT &aEvent)
bool Init() override
Init() is called once upon a registration of the tool.
EDIT_POINT * m_editedPoint
< Currently edited point, NULL if there is none.
bool addCornerCondition(const SELECTION &aSelection)
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
void pinEditedCorner(int minWidth, int minHeight, VECTOR2I &topLeft, VECTOR2I &topRight, VECTOR2I &botLeft, VECTOR2I &botRight, EE_GRID_HELPER *aGrid) const
Update the coordinates of 4 corners of a rectangle, according to constraints and the moved corner.
bool isModified(const EDIT_POINT &aPoint) const
int addCorner(const TOOL_EVENT &aEvent)
TOOL_ACTION handlers.
std::shared_ptr< EDIT_POINTS > m_editPoints
bool removeCornerCondition(const SELECTION &aSelection)
int removeCorner(const TOOL_EVENT &aEvent)
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
int getEditedPointIndex() const
int clearEditedPoints(const TOOL_EVENT &aEvent)
Set the current point being edited. NULL means none.
void updateParentItem(bool aSnapToGrid) const
< Update item's points with edit points.
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:238
EE_SELECTION & GetSelection()
A foundation class for a tool operating on a schematic or symbol.
Definition: ee_tool_base.h:48
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
Definition: ee_tool_base.h:84
void updateItem(EDA_ITEM *aItem, bool aUpdateRTree) const
Similar to getView()->Update(), but handles items that are redrawn by their parents and updating the ...
Definition: ee_tool_base.h:109
EE_SELECTION_TOOL * m_selectionTool
Definition: ee_tool_base.h:200
bool Init() override
Init() is called once upon a registration of the tool.
Definition: ee_tool_base.h:64
static const TOOL_EVENT ClearedEvent
Definition: actions.h:262
static const TOOL_EVENT SelectedEvent
Definition: actions.h:260
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition: actions.h:267
static const TOOL_EVENT PointSelectedEvent
Definition: actions.h:259
bool GetSnap() const
Definition: grid_helper.h:107
void SetSnap(bool aSnap)
Definition: grid_helper.h:106
virtual VECTOR2I AlignGrid(const VECTOR2I &aPoint, GRID_HELPER_GRIDS aGrid) const
Definition: grid_helper.h:65
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.
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:68
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:315
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:354
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: view.cpp:1631
VECTOR2D ToWorld(const VECTOR2D &aCoord, bool aAbsolute=true) const
Converts a screen space point/vector to a point/vector in world space coordinates.
Definition: view.cpp:449
A shim class between EDA_DRAW_FRAME and several derived classes: SYMBOL_EDIT_FRAME,...
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.
Object to handle a bitmap image that can be inserted in a schematic.
Definition: sch_bitmap.h:41
double GetImageScale() const
Definition: sch_bitmap.h:67
VECTOR2I GetPosition() const override
Definition: sch_bitmap.h:145
VECTOR2I GetSize() const
Definition: sch_bitmap.cpp:146
void SetImageScale(double aScale)
Definition: sch_bitmap.h:72
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
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:174
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:40
void SetStartPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:136
VECTOR2I GetEndPoint() const
Definition: sch_line.h:140
VECTOR2I GetStartPoint() const
Definition: sch_line.h:135
void SetEndPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:141
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:108
void SetPosition(const VECTOR2I &aPos) override
Definition: sch_shape.h:71
void SetEditState(int aState)
Definition: sch_shape.h:79
void Normalize()
Definition: sch_shape.cpp:75
void AddPoint(const VECTOR2I &aPosition)
Definition: sch_shape.cpp:576
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
Definition: sch_shape.cpp:114
void CalcEdit(const VECTOR2I &aPosition) override
Calculate the attributes of an item at aPosition when it is being edited.
Definition: sch_shape.h:77
VECTOR2I GetPosition() const override
Definition: sch_shape.h:70
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:57
void SetPositionIgnoringPins(const VECTOR2I &aPosition)
Definition: sch_sheet.cpp:822
int GetMinWidth(bool aFromLeft) const
Return the minimum width of the sheet based on the widths of the sheet pin text.
Definition: sch_sheet.cpp:491
VECTOR2I GetSize() const
Definition: sch_sheet.h:112
VECTOR2I GetPosition() const override
Definition: sch_sheet.h:376
int GetMinHeight(bool aFromTop) const
Return the minimum height that the sheet can be resized based on the sheet pin positions.
Definition: sch_sheet.cpp:525
void Resize(const VECTOR2I &aSize)
Resize this sheet to aSize and adjust all of the labels accordingly.
Definition: sch_sheet.cpp:935
int GetColSpan() const
Definition: sch_tablecell.h:61
int GetRowSpan() const
Definition: sch_tablecell.h:64
int GetColumn() const
int GetRow() const
void SetRowHeight(int aRow, int aHeight)
Definition: sch_table.h:121
int GetRowHeight(int aRow) const
Definition: sch_table.h:123
void SetColWidth(int aCol, int aWidth)
Definition: sch_table.h:111
int GetColWidth(int aCol) const
Definition: sch_table.h:113
void Normalize()
Definition: sch_table.cpp:135
EDA_ITEM * Front() const
Definition: selection.h:172
int Size() const
Returns the number of selected parts.
Definition: selection.h:116
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
virtual size_t GetPointCount() const override
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
void Remove(int aStartIndex, int aEndIndex)
Remove the range of points [start_index, end_index] from the line chain.
void Insert(size_t aVertex, const VECTOR2I &aP)
const std::vector< VECTOR2I > & CPoints() const
void RemoveAllContours()
Remove all outlines & holes (clears) the polygon set.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
The symbol library editor main window.
bool ToolStackIsEmpty()
Definition: tools_holder.h:125
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:42
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:217
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
Generic, UI-independent tool event.
Definition: tool_event.h:167
bool DisableGridSnapping() const
Definition: tool_event.h:363
const VECTOR2D Position() const
Returns the point where dragging has started.
Definition: tool_event.h:285
bool IsDrag(int aButtonMask=BUT_ANY) const
Definition: tool_event.h:307
const VECTOR2D DragOrigin() const
Returns information about mouse buttons state.
Definition: tool_event.h:291
bool IsMotion() const
Definition: tool_event.h:322
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 & GetToolMenu()
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.
void Activate()
Run the tool.
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:44
#define _(s)
#define ENDPOINT
ends. (Used to support dragging.)
#define STARTPOINT
When a line is selected, these flags indicate which.
RECTANGLE_POINTS
@ RECT_BOTLEFT
@ RECT_TOPLEFT
@ RECT_TOPRIGHT
@ RECT_BOTRIGHT
RECTANGLE_LINES
@ RECT_RIGHT
@ RECT_LEFT
@ RECT_BOT
@ RECT_TOP
TABLECELL_POINTS
@ ROW_HEIGHT
@ COL_WIDTH
LINE_POINTS
@ LINE_START
@ LINE_END
ARC_POINTS
@ ARC_START
@ ARC_END
@ ARC_CENTER
CIRCLE_POINTS
@ CIRC_END
@ CIRC_CENTER
BEZIER_POINTS
@ BEZIER_END
@ BEZIER_CTRL_PT2
@ BEZIER_START
@ BEZIER_CTRL_PT1
@ LAYER_NOTES
Definition: layer_ids.h:371
#define UNIMPLEMENTED_FOR(type)
Definition: macros.h:96
@ RECT_BOTLEFT
@ RECT_TOPLEFT
@ RECT_TOPRIGHT
@ RECT_BOTRIGHT
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
std::vector< FAB_LAYER_COLOR > dummy
constexpr int MilsToIU(int mils) const
Definition: base_units.h:93
@ MD_SHIFT
Definition: tool_event.h:142
@ BUT_LEFT
Definition: tool_event.h:131
double DistanceLinePoint(const VECTOR2I &linePointA, const VECTOR2I &linePointB, const VECTOR2I &referencePoint)
Compute the distance between a line and a reference point.
Definition: trigo.h:143
@ SCH_LINE_T
Definition: typeinfo.h:163
@ SCH_TABLECELL_T
Definition: typeinfo.h:166
@ SCH_SHEET_T
Definition: typeinfo.h:174
@ SCH_SHAPE_T
Definition: typeinfo.h:149
@ SCH_RULE_AREA_T
Definition: typeinfo.h:170
@ SCH_BITMAP_T
Definition: typeinfo.h:164
@ SCH_TEXTBOX_T
Definition: typeinfo.h:152
VECTOR2< int > VECTOR2I
Definition: vector2d.h:602