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
44
45static const std::vector<KICAD_T> pointEditorTypes = { SCH_SHAPE_T,
52
53
54// Few constants to avoid using bare numbers for point indices
56{
58};
59
60
62{
64};
65
66
68{
70};
71
72
74{
76};
77
79{
81};
82
84{
86};
87
88
90{
95};
96
97
99{
100public:
101 static std::shared_ptr<EDIT_POINTS> Make( EDA_ITEM* aItem, SCH_BASE_FRAME* frame )
102 {
103 std::shared_ptr<EDIT_POINTS> points = std::make_shared<EDIT_POINTS>( aItem );
104
105 if( !aItem )
106 return points;
107
108 // Generate list of edit points based on the item type
109 switch( aItem->Type() )
110 {
111 case SCH_SHAPE_T:
112 {
113 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
114
115 switch( shape->GetShape() )
116 {
117 case SHAPE_T::ARC:
118 points->AddPoint( shape->GetStart() );
119 points->AddPoint( shape->GetEnd() );
120 points->AddPoint( shape->GetPosition() );
121 break;
122
123 case SHAPE_T::CIRCLE:
124 points->AddPoint( shape->GetPosition() );
125 points->AddPoint( shape->GetEnd() );
126 break;
127
128 case SHAPE_T::RECTANGLE:
129 {
130 shape->Normalize();
131
132 VECTOR2I topLeft = shape->GetPosition();
133 VECTOR2I botRight = shape->GetEnd();
134
135 points->AddPoint( topLeft );
136 points->AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
137 points->AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
138 points->AddPoint( botRight );
139
140 points->AddLine( points->Point( RECT_TOPLEFT ), points->Point( RECT_TOPRIGHT ) );
141 points->Line( RECT_TOP ).SetConstraint( new EC_PERPLINE( points->Line( RECT_TOP ) ) );
142 points->AddLine( points->Point( RECT_TOPRIGHT ), points->Point( RECT_BOTRIGHT ) );
143 points->Line( RECT_RIGHT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_RIGHT ) ) );
144 points->AddLine( points->Point( RECT_BOTRIGHT ), points->Point( RECT_BOTLEFT ) );
145 points->Line( RECT_BOT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_BOT ) ) );
146 points->AddLine( points->Point( RECT_BOTLEFT ), points->Point( RECT_TOPLEFT ) );
147 points->Line( RECT_LEFT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_LEFT ) ) );
148
149 break;
150 }
151
152 case SHAPE_T::POLY:
153 for( const VECTOR2I& pt : shape->GetPolyShape().Outline( 0 ).CPoints() )
154 points->AddPoint( pt );
155
156 break;
157
158 case SHAPE_T::BEZIER:
159 points->AddPoint( shape->GetStart() );
160 points->AddPoint( shape->GetBezierC1() );
161 points->AddPoint( shape->GetBezierC2() );
162 points->AddPoint( shape->GetEnd() );
163 break;
164
165 default:
167 }
168
169 break;
170 }
171
172 case SCH_RULE_AREA_T:
173 {
174 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
175
176 for( const VECTOR2I& pt : shape->GetPolyShape().Outline( 0 ).CPoints() )
177 points->AddPoint( pt );
178
179 break;
180 }
181
182 case SCH_TEXTBOX_T:
183 {
184 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( aItem );
185
186 textbox->Normalize();
187
188 VECTOR2I topLeft = textbox->GetPosition();
189 VECTOR2I botRight = textbox->GetEnd();
190
191 points->AddPoint( topLeft );
192 points->AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
193 points->AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
194 points->AddPoint( botRight );
195
196 points->AddLine( points->Point( RECT_TOPLEFT ), points->Point( RECT_TOPRIGHT ) );
197 points->Line( RECT_TOP ).SetConstraint( new EC_PERPLINE( points->Line( RECT_TOP ) ) );
198 points->AddLine( points->Point( RECT_TOPRIGHT ), points->Point( RECT_BOTRIGHT ) );
199 points->Line( RECT_RIGHT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_RIGHT ) ) );
200 points->AddLine( points->Point( RECT_BOTRIGHT ), points->Point( RECT_BOTLEFT ) );
201 points->Line( RECT_BOT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_BOT ) ) );
202 points->AddLine( points->Point( RECT_BOTLEFT ), points->Point( RECT_TOPLEFT ) );
203 points->Line( RECT_LEFT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_LEFT ) ) );
204
205 break;
206 }
207
208 case SCH_TABLECELL_T:
209 {
210 SCH_TABLECELL* cell = static_cast<SCH_TABLECELL*>( aItem );
211 points->AddPoint( cell->GetEnd() - VECTOR2I( 0, cell->GetRectangleHeight() / 2 ) );
212 points->AddPoint( cell->GetEnd() - VECTOR2I( cell->GetRectangleWidth() / 2, 0 ) );
213 break;
214 }
215
216 case SCH_SHEET_T:
217 {
218 SCH_SHEET* sheet = (SCH_SHEET*) aItem;
219 VECTOR2I topLeft = sheet->GetPosition();
220 VECTOR2I botRight = sheet->GetPosition() + sheet->GetSize();
221
222 points->AddPoint( topLeft );
223 points->AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
224 points->AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
225 points->AddPoint( botRight );
226
227 points->AddLine( points->Point( RECT_TOPLEFT ), points->Point( RECT_TOPRIGHT ) );
228 points->Line( RECT_TOP ).SetConstraint( new EC_PERPLINE( points->Line( RECT_TOP ) ) );
229 points->AddLine( points->Point( RECT_TOPRIGHT ), points->Point( RECT_BOTRIGHT ) );
230 points->Line( RECT_RIGHT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_RIGHT ) ) );
231 points->AddLine( points->Point( RECT_BOTRIGHT ), points->Point( RECT_BOTLEFT ) );
232 points->Line( RECT_BOT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_BOT ) ) );
233 points->AddLine( points->Point( RECT_BOTLEFT ), points->Point( RECT_TOPLEFT ) );
234 points->Line( RECT_LEFT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_LEFT ) ) );
235
236 break;
237 }
238
239 case SCH_BITMAP_T:
240 {
241 SCH_BITMAP* bitmap = (SCH_BITMAP*) aItem;
242 VECTOR2I topLeft = bitmap->GetPosition() - bitmap->GetSize() / 2;
243 VECTOR2I botRight = bitmap->GetPosition() + bitmap->GetSize() / 2;
244
245 points->AddPoint( topLeft );
246 points->AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
247 points->AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
248 points->AddPoint( botRight );
249 break;
250 }
251
252 case SCH_LINE_T:
253 {
254 SCH_LINE* line = (SCH_LINE*) aItem;
255 std::pair<EDA_ITEM*, int> connectedStart = { nullptr, STARTPOINT };
256 std::pair<EDA_ITEM*, int> connectedEnd = { nullptr, STARTPOINT };
257
258 for( SCH_ITEM* test : frame->GetScreen()->Items().OfType( SCH_LINE_T ) )
259 {
260 if( test->GetLayer() != LAYER_NOTES )
261 continue;
262
263 if( test == aItem )
264 continue;
265
266 SCH_LINE* testLine = static_cast<SCH_LINE*>( test );
267
268 if( testLine->GetStartPoint() == line->GetStartPoint() )
269 {
270 connectedStart = { testLine, STARTPOINT };
271 }
272 else if( testLine->GetEndPoint() == line->GetStartPoint() )
273 {
274 connectedStart = { testLine, ENDPOINT };
275 }
276 else if( testLine->GetStartPoint() == line->GetEndPoint() )
277 {
278 connectedEnd = { testLine, STARTPOINT };
279 }
280 else if( testLine->GetEndPoint() == line->GetEndPoint() )
281 {
282 connectedEnd = { testLine, ENDPOINT };
283 }
284 }
285
286 points->AddPoint( line->GetStartPoint(), connectedStart );
287 points->AddPoint( line->GetEndPoint(), connectedEnd );
288 break;
289 }
290
291 default:
292 points.reset();
293 break;
294 }
295
296 return points;
297 }
298
299private:
301};
302
303
305 EE_TOOL_BASE<SCH_BASE_FRAME>( "eeschema.PointEditor" ),
306 m_editedPoint( nullptr ),
307 m_inPointEditor( false )
308{
309}
310
311
313{
314 EE_TOOL_BASE::Reset( aReason );
315
316 m_editPoints.reset();
317 m_editedPoint = nullptr;
318}
319
320
322{
324
325 auto& menu = m_selectionTool->GetToolMenu().GetMenu();
327 std::bind( &EE_POINT_EDITOR::addCornerCondition, this, _1 ) );
329 std::bind( &EE_POINT_EDITOR::removeCornerCondition, this, _1 ) );
330
331 return true;
332}
333
334
336{
337 setEditedPoint( nullptr );
338
339 return 0;
340}
341
342
344{
345 EDIT_POINT* point = m_editedPoint;
346
347 if( !m_editPoints )
348 {
349 point = nullptr;
350 }
351 else if( aEvent.IsMotion() )
352 {
353 point = m_editPoints->FindPoint( aEvent.Position(), getView() );
354 }
355 else if( aEvent.IsDrag( BUT_LEFT ) )
356 {
357 point = m_editPoints->FindPoint( aEvent.DragOrigin(), getView() );
358 }
359 else
360 {
361 point = m_editPoints->FindPoint( getViewControls()->GetCursorPosition( false ), getView() );
362 }
363
364 if( m_editedPoint != point )
365 setEditedPoint( point );
366}
367
368
370{
371 if( !m_selectionTool )
372 return 0;
373
374 if( m_inPointEditor )
375 return 0;
376
378
379 if( m_isSymbolEditor )
380 {
381 SYMBOL_EDIT_FRAME* editor = getEditFrame<SYMBOL_EDIT_FRAME>();
382
383 if( !editor->IsSymbolEditable() || editor->IsSymbolAlias() )
384 return 0;
385 }
386
387 const EE_SELECTION& selection = m_selectionTool->GetSelection();
388
389 if( selection.Size() != 1 || !selection.Front()->IsType( pointEditorTypes ) )
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( 2 );
655 shape->CalcEdit( m_editPoints->Point( ARC_START ).GetPosition() );
656 }
657 else if( getEditedPointIndex() == ARC_END )
658 {
659 shape->SetEditState( 3 );
660 shape->CalcEdit( m_editPoints->Point( ARC_END ).GetPosition() );
661 }
662 else if( getEditedPointIndex() == ARC_CENTER )
663 {
664 shape->SetEditState( 4 );
665 shape->CalcEdit( m_editPoints->Point( ARC_CENTER ).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
742 shape->RebuildBezierToSegmentsPointsList( shape->GetWidth() / 2 );
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_START ).SetPosition( shape->GetStart() );
998 m_editPoints->Point( ARC_END ).SetPosition( shape->GetEnd() );
999 m_editPoints->Point( ARC_CENTER ).SetPosition( shape->GetPosition() );
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( m_editPoints->GetParent()->Type() == SCH_SHAPE_T && poly.GetPointCount() <= 2 )
1178 return false;
1179 if( m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T && poly.GetPointCount() <= 3 )
1180 return false;
1181
1182 for( const VECTOR2I& pt : poly.CPoints() )
1183 {
1184 if( pt == m_editedPoint->GetPosition() )
1185 return true;
1186 }
1187
1188 return false;
1189}
1190
1191
1193{
1194 if( !m_editPoints
1195 || !( m_editPoints->GetParent()->Type() == SCH_SHAPE_T
1196 || m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T ) )
1197 {
1198 return false;
1199 }
1200
1201 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1202
1203 if( shape->GetShape() != SHAPE_T::POLY )
1204 return false;
1205
1206 VECTOR2I cursorPos = getViewControls()->GetCursorPosition( false );
1207 double threshold = getView()->ToWorld( EDIT_POINT::POINT_SIZE );
1208
1209 return shape->HitTest( cursorPos, (int) threshold );
1210}
1211
1212
1214{
1215 if( !m_editPoints
1216 || !( m_editPoints->GetParent()->Type() == SCH_SHAPE_T
1217 || m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T ) )
1218 return 0;
1219
1220 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1221 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1222 SCH_COMMIT commit( m_toolMgr );
1223
1224 commit.Modify( shape, m_frame->GetScreen() );
1225
1227 int currentMinDistance = INT_MAX;
1228 int closestLineStart = 0;
1229 unsigned numPoints = poly.GetPointCount();
1230
1231 if( !shape->IsClosed() )
1232 numPoints -= 1;
1233
1234 for( unsigned i = 0; i < numPoints; ++i )
1235 {
1236 SEG seg = poly.GetSegment( i );
1237 int distance = seg.Distance( cursor );
1238
1239 if( distance < currentMinDistance )
1240 {
1241 currentMinDistance = distance;
1242 closestLineStart = i;
1243 }
1244 }
1245
1246 poly.Insert( closestLineStart + 1, cursor );
1247
1248 updateItem( shape, true );
1249 updatePoints();
1250
1251 commit.Push( _( "Add Corner" ) );
1252 return 0;
1253}
1254
1255
1257{
1259 || !m_editPoints->GetParent()->IsType( { SCH_SHAPE_T, SCH_RULE_AREA_T } ) )
1260 {
1261 return 0;
1262 }
1263
1264 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1265 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1266 SCH_COMMIT commit( m_toolMgr );
1267
1268 if( m_editPoints->GetParent()->Type() == SCH_SHAPE_T && poly.GetPointCount() <= 2 )
1269 return 0;
1270 if( m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T && poly.GetPointCount() <= 3 )
1271 return 0;
1272
1273 commit.Modify( shape, m_frame->GetScreen() );
1274
1275 int idx = getEditedPointIndex();
1276 int last = (int) poly.GetPointCount() - 1;
1277
1278 if( idx == 0 && poly.GetPoint( 0 ) == poly.GetPoint( last ) )
1279 {
1280 poly.Remove( idx );
1281 poly.SetPoint( last-1, poly.GetPoint( 0 ) );
1282 }
1283 else
1284 {
1285 poly.Remove( idx );
1286 }
1287
1288 setEditedPoint( nullptr );
1289
1290 updateItem( shape, true );
1291 updatePoints();
1292
1293 commit.Push( _( "Remove Corner" ) );
1294 return 0;
1295}
1296
1297
1299{
1300 updatePoints();
1301 return 0;
1302}
1303
1304
1306{
1314}
1315
1316
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:110
static TOOL_ACTION activatePointEditor
Definition: actions.h:210
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:89
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition: eda_item.h:176
EDA_ITEM * GetParent() const
Definition: eda_item.h:103
bool IsNew() const
Definition: eda_item.h:107
void SetStartX(int x)
Definition: eda_shape.h:146
const VECTOR2I & GetBezierC2() const
Definition: eda_shape.h:206
void SetBezierC2(const VECTOR2I &aPt)
Definition: eda_shape.h:205
void SetEndY(int aY)
Definition: eda_shape.h:177
int GetEndX() const
Definition: eda_shape.h:169
int GetRectangleWidth() const
Definition: eda_shape.cpp:166
void SetStartY(int y)
Definition: eda_shape.h:140
SHAPE_POLY_SET & GetPolyShape()
Definition: eda_shape.h:279
SHAPE_T GetShape() const
Definition: eda_shape.h:125
int GetEndY() const
Definition: eda_shape.h:168
void SetEndX(int aX)
Definition: eda_shape.h:183
void RebuildBezierToSegmentsPointsList(int aMaxError)
Rebuild the m_bezierPoints vertex list that approximate the Bezier curve by a list of segments.
Definition: eda_shape.cpp:511
int GetPointCount() const
Definition: eda_shape.cpp:1363
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:167
bool IsClosed() const
Definition: eda_shape.cpp:247
void SetStart(const VECTOR2I &aStart)
Definition: eda_shape.h:134
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition: eda_shape.h:130
void SetEnd(const VECTOR2I &aEnd)
Definition: eda_shape.h:171
void SetBezierC1(const VECTOR2I &aPt)
Definition: eda_shape.h:202
wxString SHAPE_T_asString() const
Definition: eda_shape.cpp:89
const VECTOR2I & GetBezierC1() const
Definition: eda_shape.h:203
int GetRectangleHeight() const
Definition: eda_shape.cpp:153
virtual int GetWidth() const
Definition: eda_shape.h:115
virtual void ClearRenderCache()
Definition: eda_text.cpp:498
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:272
static const TOOL_EVENT SelectedEvent
Definition: actions.h:270
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition: actions.h:277
static const TOOL_EVENT PointSelectedEvent
Definition: actions.h:269
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:317
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:357
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: view.cpp:1687
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:484
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:166
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:41
void SetStartPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:137
VECTOR2I GetEndPoint() const
Definition: sch_line.h:141
VECTOR2I GetStartPoint() const
Definition: sch_line.h:136
void SetEndPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:142
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:897
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:545
VECTOR2I GetSize() const
Definition: sch_sheet.h:112
VECTOR2I GetPosition() const override
Definition: sch_sheet.h:400
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:579
void Resize(const VECTOR2I &aSize)
Resize this sheet to aSize and adjust all of the labels accordingly.
Definition: sch_sheet.cpp:1010
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
Definition: seg.h:42
int Distance(const SEG &aSeg) const
Compute minimum Euclidean distance to segment aSeg.
Definition: seg.cpp:388
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 const VECTOR2I GetPoint(int aIndex) const override
void SetPoint(int aIndex, const VECTOR2I &aPos)
Move a point to a specific location.
virtual size_t GetPointCount() const override
virtual const SEG GetSegment(int aIndex) const override
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:218
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
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
static const std::vector< KICAD_T > pointEditorTypes
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:372
#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
@ 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_ITEM_LOCATE_GRAPHIC_LINE_T
Definition: typeinfo.h:187
@ SCH_BITMAP_T
Definition: typeinfo.h:164
@ SCH_TEXTBOX_T
Definition: typeinfo.h:152
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:673