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 "ee_point_editor.h"
26
27#include <functional>
28using namespace std::placeholders;
29
30#include <ee_grid_helper.h>
31#include <tool/tool_manager.h>
32#include <sch_commit.h>
33#include <view/view_controls.h>
35#include <geometry/seg.h>
38#include <tools/ee_actions.h>
40#include <sch_edit_frame.h>
41#include <sch_line.h>
42#include <sch_bitmap.h>
43#include <sch_sheet.h>
44#include <sch_textbox.h>
45#include <sch_table.h>
47
48
49static const std::vector<KICAD_T> pointEditorTypes = { SCH_SHAPE_T,
56
57
58// Few constants to avoid using bare numbers for point indices
60{
62};
63
64
66{
68};
69
70
72{
74};
75
76
78{
80};
81
82
84{
86};
87
89{
91};
92
93
95{
96public:
98 m_line( aLine ), m_screen( aScreen )
99 {
100 }
101
102 void MakePoints( EDIT_POINTS& aPoints ) override
103 {
104 std::pair<EDA_ITEM*, int> connectedStart = { nullptr, STARTPOINT };
105 std::pair<EDA_ITEM*, int> connectedEnd = { nullptr, STARTPOINT };
106
108 {
109 if( test->GetLayer() != LAYER_NOTES )
110 continue;
111
112 if( test == &m_line )
113 continue;
114
115 SCH_LINE* testLine = static_cast<SCH_LINE*>( test );
116
117 if( testLine->GetStartPoint() == m_line.GetStartPoint() )
118 {
119 connectedStart = { testLine, STARTPOINT };
120 }
121 else if( testLine->GetEndPoint() == m_line.GetStartPoint() )
122 {
123 connectedStart = { testLine, ENDPOINT };
124 }
125 else if( testLine->GetStartPoint() == m_line.GetEndPoint() )
126 {
127 connectedEnd = { testLine, STARTPOINT };
128 }
129 else if( testLine->GetEndPoint() == m_line.GetEndPoint() )
130 {
131 connectedEnd = { testLine, ENDPOINT };
132 }
133 }
134
135 aPoints.AddPoint( m_line.GetStartPoint(), connectedStart );
136 aPoints.AddPoint( m_line.GetEndPoint(), connectedEnd );
137 }
138
139 void UpdatePoints( EDIT_POINTS& aPoints ) override
140 {
143 }
144
145 void UpdateItem( const EDIT_POINT& aEditedPoints, EDIT_POINTS& aPoints, COMMIT& aCommit,
146 std::vector<EDA_ITEM*>& aUpdatedItems ) override
147 {
150
151 std::pair<EDA_ITEM*, int> connected = aPoints.Point( LINE_START ).GetConnected();
152
153 if( connected.first )
154 {
155 aCommit.Modify( connected.first, &m_screen );
156 aUpdatedItems.push_back( connected.first );
157
158 if( connected.second == STARTPOINT )
159 static_cast<SCH_LINE*>( connected.first )->SetStartPoint( m_line.GetStartPoint() );
160 else if( connected.second == ENDPOINT )
161 static_cast<SCH_LINE*>( connected.first )->SetEndPoint( m_line.GetStartPoint() );
162 }
163
164 connected = aPoints.Point( LINE_END ).GetConnected();
165
166 if( connected.first )
167 {
168 aCommit.Modify( connected.first, &m_screen );
169 aUpdatedItems.push_back( connected.first );
170
171 if( connected.second == STARTPOINT )
172 static_cast<SCH_LINE*>( connected.first )->SetStartPoint( m_line.GetEndPoint() );
173 else if( connected.second == ENDPOINT )
174 static_cast<SCH_LINE*>( connected.first )->SetEndPoint( m_line.GetEndPoint() );
175 }
176 }
177
178private:
181};
182
183
185{
186public:
188 m_arc( aArc )
189 {
190 wxASSERT( m_arc.GetShape() == SHAPE_T::ARC );
191 }
192
193 void MakePoints( EDIT_POINTS& aPoints ) override
194 {
195 aPoints.AddPoint( m_arc.GetStart() );
196 aPoints.AddPoint( m_arc.GetEnd() );
197 aPoints.AddPoint( m_arc.GetPosition() );
198
199 aPoints.AddIndicatorLine( aPoints.Point( ARC_CENTER ), aPoints.Point( ARC_START ) );
200 aPoints.AddIndicatorLine( aPoints.Point( ARC_CENTER ), aPoints.Point( ARC_END ) );
201 }
202
203 void UpdatePoints( EDIT_POINTS& aPoints ) override
204 {
205 aPoints.Point( ARC_START ).SetPosition( m_arc.GetStart() );
206 aPoints.Point( ARC_END ).SetPosition( m_arc.GetEnd() );
208 }
209
210 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
211 std::vector<EDA_ITEM*>& aUpdatedItems ) override
212 {
213 if( isModified( aEditedPoint, aPoints.Point( ARC_START ) ) )
214
215 {
216 m_arc.SetEditState( 2 );
217 m_arc.CalcEdit( aPoints.Point( ARC_START ).GetPosition() );
218 }
219 else if( isModified( aEditedPoint, aPoints.Point( ARC_END ) ) )
220 {
221 m_arc.SetEditState( 3 );
222 m_arc.CalcEdit( aPoints.Point( ARC_END ).GetPosition() );
223 }
224 else if( isModified( aEditedPoint, aPoints.Point( ARC_CENTER ) ) )
225 {
226 m_arc.SetEditState( 4 );
227 m_arc.CalcEdit( aPoints.Point( ARC_CENTER ).GetPosition() );
228 }
229
230 aUpdatedItems.push_back( &m_arc );
231 }
232private:
234};
235
236
238{
239public:
241
242 void MakePoints( EDIT_POINTS& aPoints ) override
243 {
244 const REFERENCE_IMAGE& refImage = m_bitmap.GetReferenceImage();
245 const VECTOR2I topLeft = refImage.GetPosition() - refImage.GetSize() / 2;
246 const VECTOR2I botRight = refImage.GetPosition() + refImage.GetSize() / 2;
247
248 aPoints.AddPoint( topLeft );
249 aPoints.AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
250 aPoints.AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
251 aPoints.AddPoint( botRight );
252
253 aPoints.AddPoint( refImage.GetPosition() + refImage.GetTransformOriginOffset() );
254 }
255
256 void UpdatePoints( EDIT_POINTS& aPoints ) override
257 {
258 const REFERENCE_IMAGE& refImage = m_bitmap.GetReferenceImage();
259 const VECTOR2I topLeft = refImage.GetPosition() - refImage.GetSize() / 2;
260 const VECTOR2I botRight = refImage.GetPosition() + refImage.GetSize() / 2;
261
262 aPoints.Point( RECT_TOPLEFT ).SetPosition( topLeft );
263 aPoints.Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
264 aPoints.Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
265 aPoints.Point( RECT_BOTRIGHT ).SetPosition( botRight );
266
267 aPoints.Point( REFIMG_ORIGIN )
268 .SetPosition( refImage.GetPosition() + refImage.GetTransformOriginOffset() );
269 }
270
271 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
272 std::vector<EDA_ITEM*>& aUpdatedItems ) override
273 {
275 const VECTOR2I topLeft = aPoints.Point( RECT_TOPLEFT ).GetPosition();
276 const VECTOR2I topRight = aPoints.Point( RECT_TOPRIGHT ).GetPosition();
277 const VECTOR2I botLeft = aPoints.Point( RECT_BOTLEFT ).GetPosition();
278 const VECTOR2I botRight = aPoints.Point( RECT_BOTRIGHT ).GetPosition();
279 const VECTOR2I xfrmOrigin = aPoints.Point( REFIMG_ORIGIN ).GetPosition();
280
281 if( isModified( aEditedPoint, aPoints.Point( REFIMG_ORIGIN ) ) )
282 {
283 // Moving the transform origin
284 // As the other points didn't move, we can get the image extent from them
285 const VECTOR2I newOffset = xfrmOrigin - ( topLeft + botRight ) / 2;
286 refImg.SetTransformOriginOffset( newOffset );
287 }
288 else
289 {
290 const VECTOR2I oldOrigin = refImg.GetPosition() + refImg.GetTransformOriginOffset();
291 const VECTOR2I oldSize = refImg.GetSize();
292 const VECTOR2I pos = refImg.GetPosition();
293
294 OPT_VECTOR2I newCorner;
295 VECTOR2I oldCorner = pos;
296
297 if( isModified( aEditedPoint, aPoints.Point( RECT_TOPLEFT ) ) )
298 {
299 newCorner = topLeft;
300 oldCorner -= oldSize / 2;
301 }
302 else if( isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) ) )
303 {
304 newCorner = topRight;
305 oldCorner -= VECTOR2I( -oldSize.x, oldSize.y ) / 2;
306 }
307 else if( isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) ) )
308 {
309 newCorner = botLeft;
310 oldCorner -= VECTOR2I( oldSize.x, -oldSize.y ) / 2;
311 }
312 else if( isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) ) )
313 {
314 newCorner = botRight;
315 oldCorner += oldSize / 2;
316 }
317
318 if( newCorner )
319 {
320 // Turn in the respective vectors from the origin
321 *newCorner -= xfrmOrigin;
322 oldCorner -= oldOrigin;
323
324 // If we tried to cross the origin, clamp it to stop it
325 if( sign( newCorner->x ) != sign( oldCorner.x )
326 || sign( newCorner->y ) != sign( oldCorner.y ) )
327 {
328 *newCorner = VECTOR2I( 0, 0 );
329 }
330
331 const double newLength = newCorner->EuclideanNorm();
332 const double oldLength = oldCorner.EuclideanNorm();
333
334 double ratio = oldLength > 0 ? ( newLength / oldLength ) : 1.0;
335
336 // Clamp the scaling to a minimum of 50 mils
337 VECTOR2I newSize = oldSize * ratio;
338 double newWidth = std::max( newSize.x, EDA_UNIT_UTILS::Mils2IU( schIUScale, 50 ) );
339 double newHeight = std::max( newSize.y, EDA_UNIT_UTILS::Mils2IU( schIUScale, 50 ) );
340 ratio = std::min( newWidth / oldSize.x, newHeight / oldSize.y );
341
342 // Also handles the origin offset
343 refImg.SetImageScale( refImg.GetImageScale() * ratio );
344 }
345 }
346 aUpdatedItems.push_back( &m_bitmap );
347 }
348
349private:
351};
352
353
355{
356public:
359 {
360 }
361
362 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
363 std::vector<EDA_ITEM*>& aUpdatedItems ) override
364 {
365 SCH_TABLE& table = static_cast<SCH_TABLE&>( *m_cell.GetParent() );
366 aCommit.Modify( &table );
367 aUpdatedItems.push_back( &table );
368
369 if( isModified( aEditedPoint, aPoints.Point( COL_WIDTH ) ) )
370 {
371 m_cell.SetEnd( VECTOR2I( aPoints.Point( 0 ).GetX(), m_cell.GetEndY() ) );
372
373 int colWidth = m_cell.GetRectangleWidth();
374
375 for( int ii = 0; ii < m_cell.GetColSpan() - 1; ++ii )
376 colWidth -= table.GetColWidth( m_cell.GetColumn() + ii );
377
378 table.SetColWidth( m_cell.GetColumn() + m_cell.GetColSpan() - 1, colWidth );
379 }
380 else if( isModified( aEditedPoint, aPoints.Point( ROW_HEIGHT ) ) )
381 {
382 m_cell.SetEnd( VECTOR2I( m_cell.GetEndX(), aPoints.Point( 1 ).GetY() ) );
383
384 int rowHeight = m_cell.GetRectangleHeight();
385
386 for( int ii = 0; ii < m_cell.GetRowSpan() - 1; ++ii )
387 rowHeight -= table.GetRowHeight( m_cell.GetRow() + ii );
388
389 table.SetRowHeight( m_cell.GetRow() + m_cell.GetRowSpan() - 1, rowHeight );
390 }
391
392 table.Normalize();
393 }
394
395private:
397};
398
399
401{
402public:
404 m_rect( aRect ), m_frame( aFrame )
405 {
406 }
407
408 static void MakePoints( SCH_SHAPE& aRect, EDIT_POINTS& aPoints )
409 {
410 VECTOR2I topLeft = aRect.GetPosition();
411 VECTOR2I botRight = aRect.GetEnd();
412
413 aPoints.AddPoint( topLeft );
414 aPoints.AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
415 aPoints.AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
416 aPoints.AddPoint( botRight );
417 aPoints.AddPoint( aRect.GetCenter() );
418
419 aPoints.AddLine( aPoints.Point( RECT_TOPLEFT ), aPoints.Point( RECT_TOPRIGHT ) );
420 aPoints.Line( RECT_TOP ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_TOP ) ) );
421 aPoints.AddLine( aPoints.Point( RECT_TOPRIGHT ), aPoints.Point( RECT_BOTRIGHT ) );
422 aPoints.Line( RECT_RIGHT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_RIGHT ) ) );
423 aPoints.AddLine( aPoints.Point( RECT_BOTRIGHT ), aPoints.Point( RECT_BOTLEFT ) );
424 aPoints.Line( RECT_BOT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_BOT ) ) );
425 aPoints.AddLine( aPoints.Point( RECT_BOTLEFT ), aPoints.Point( RECT_TOPLEFT ) );
426 aPoints.Line( RECT_LEFT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_LEFT ) ) );
427 }
428
429 static void UpdatePoints( SCH_SHAPE& aRect, EDIT_POINTS& aPoints )
430 {
431 VECTOR2I topLeft = aRect.GetPosition();
432 VECTOR2I botRight = aRect.GetEnd();
433
434 aPoints.Point( RECT_TOPLEFT ).SetPosition( topLeft );
435 aPoints.Point( RECT_TOPRIGHT ).SetPosition( VECTOR2I( botRight.x, topLeft.y ) );
436 aPoints.Point( RECT_BOTLEFT ).SetPosition( VECTOR2I( topLeft.x, botRight.y ) );
437 aPoints.Point( RECT_BOTRIGHT ).SetPosition( botRight );
438 aPoints.Point( RECT_CENTER ).SetPosition( aRect.GetCenter() );
439 }
440
451 static void PinEditedCorner( const EDIT_POINT& aEditedPoint, const EDIT_POINTS& aPoints,
452 int minWidth, int minHeight, VECTOR2I& topLeft, VECTOR2I& topRight,
453 VECTOR2I& botLeft, VECTOR2I& botRight )
454 {
455 if( isModified( aEditedPoint, aPoints.Point( RECT_TOPLEFT ) ) )
456 {
457 // pin edited point within opposite corner
458 topLeft.x = std::min( topLeft.x, botRight.x - minWidth );
459 topLeft.y = std::min( topLeft.y, botRight.y - minHeight );
460
461 // push edited point edges to adjacent corners
462 topRight.y = topLeft.y;
463 botLeft.x = topLeft.x;
464 }
465 else if( isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) ) )
466 {
467 // pin edited point within opposite corner
468 topRight.x = std::max( topRight.x, botLeft.x + minWidth );
469 topRight.y = std::min( topRight.y, botLeft.y - minHeight );
470
471 // push edited point edges to adjacent corners
472 topLeft.y = topRight.y;
473 botRight.x = topRight.x;
474 }
475 else if( isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) ) )
476 {
477 // pin edited point within opposite corner
478 botLeft.x = std::min( botLeft.x, topRight.x - minWidth );
479 botLeft.y = std::max( botLeft.y, topRight.y + minHeight );
480
481 // push edited point edges to adjacent corners
482 botRight.y = botLeft.y;
483 topLeft.x = botLeft.x;
484 }
485 else if( isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) ) )
486 {
487 // pin edited point within opposite corner
488 botRight.x = std::max( botRight.x, topLeft.x + minWidth );
489 botRight.y = std::max( botRight.y, topLeft.y + minHeight );
490
491 // push edited point edges to adjacent corners
492 botLeft.y = botRight.y;
493 topRight.x = botRight.x;
494 }
495 else if( isModified( aEditedPoint, aPoints.Line( RECT_TOP ) ) )
496 {
497 topLeft.y = std::min( topLeft.y, botRight.y - minHeight );
498 }
499 else if( isModified( aEditedPoint, aPoints.Line( RECT_LEFT ) ) )
500 {
501 topLeft.x = std::min( topLeft.x, botRight.x - minWidth );
502 }
503 else if( isModified( aEditedPoint, aPoints.Line( RECT_BOT ) ) )
504 {
505 botRight.y = std::max( botRight.y, topLeft.y + minHeight );
506 }
507 else if( isModified( aEditedPoint, aPoints.Line( RECT_RIGHT ) ) )
508 {
509 botRight.x = std::max( botRight.x, topLeft.x + minWidth );
510 }
511 }
512
513 static void UpdateItem( SCH_SHAPE& aRect, const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints )
514 {
515 VECTOR2I topLeft = aPoints.Point( RECT_TOPLEFT ).GetPosition();
516 VECTOR2I topRight = aPoints.Point( RECT_TOPRIGHT ).GetPosition();
517 VECTOR2I botLeft = aPoints.Point( RECT_BOTLEFT ).GetPosition();
518 VECTOR2I botRight = aPoints.Point( RECT_BOTRIGHT ).GetPosition();
519
520 PinEditedCorner( aEditedPoint, aPoints, schIUScale.MilsToIU( 1 ), schIUScale.MilsToIU( 1 ),
521 topLeft, topRight, botLeft, botRight );
522
523 if( isModified( aEditedPoint, aPoints.Point( RECT_TOPLEFT ) )
524 || isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) )
525 || isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) )
526 || isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) ) )
527 {
528 aRect.SetPosition( topLeft );
529 aRect.SetEnd( botRight );
530 }
531 else if( isModified( aEditedPoint, aPoints.Line( RECT_TOP ) ) )
532 {
533 aRect.SetStartY( topLeft.y );
534 }
535 else if( isModified( aEditedPoint, aPoints.Line( RECT_LEFT ) ) )
536 {
537 aRect.SetStartX( topLeft.x );
538 }
539 else if( isModified( aEditedPoint, aPoints.Line( RECT_BOT ) ) )
540 {
541 aRect.SetEndY( botRight.y );
542 }
543 else if( isModified( aEditedPoint, aPoints.Line( RECT_RIGHT ) ) )
544 {
545 aRect.SetEndX( botRight.x );
546 }
547
548 for( unsigned i = 0; i < aPoints.LinesSize(); ++i )
549 {
550 if( !isModified( aEditedPoint, aPoints.Line( i ) ) )
551 {
552 aPoints.Line( i ).SetConstraint( new EC_PERPLINE( aPoints.Line( i ) ) );
553 }
554 }
555 }
556
557 void MakePoints( EDIT_POINTS& aPoints ) override
558 {
560 MakePoints( m_rect, aPoints );
561 }
562
563 void UpdatePoints( EDIT_POINTS& aPoints ) override
564 {
566 UpdatePoints( m_rect, aPoints );
567 }
568
569 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
570 std::vector<EDA_ITEM*>& aUpdatedItems ) override
571 {
572 VECTOR2I topLeft = aPoints.Point( RECT_TOPLEFT ).GetPosition();
573 VECTOR2I topRight = aPoints.Point( RECT_TOPRIGHT ).GetPosition();
574 VECTOR2I botLeft = aPoints.Point( RECT_BOTLEFT ).GetPosition();
575 VECTOR2I botRight = aPoints.Point( RECT_BOTRIGHT ).GetPosition();
576
577 PinEditedCorner( aEditedPoint, aPoints, schIUScale.MilsToIU( 1 ), schIUScale.MilsToIU( 1 ),
578 topLeft, topRight, botLeft, botRight );
579
580 const BOX2I oldBox = BOX2I::ByCorners( m_rect.GetStart(), m_rect.GetEnd() );
581 std::vector<SEG> oldSegs;
582 std::vector<VECTOR2I> moveVecs;
583
584 if( isModified( aEditedPoint, aPoints.Point( RECT_TOPLEFT ) )
585 || isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) )
586 || isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) )
587 || isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) ) )
588 {
589 // Corner drags don't update pins. Not only is it an escape hatch to avoid
590 // moving pins, it also avoids tricky problems when the pins "fall off"
591 // the ends of one of the two segments and get either left behind or
592 // "swept up" into the corner.
593 m_rect.SetPosition( topLeft );
594 m_rect.SetEnd( botRight );
595 }
596 else if( isModified( aEditedPoint, aPoints.Point( RECT_CENTER ) ) )
597 {
598 VECTOR2I moveVec = aPoints.Point( RECT_CENTER ).GetPosition() - oldBox.GetCenter();
599 m_rect.Move( moveVec );
600 }
601 else if( isModified( aEditedPoint, aPoints.Line( RECT_TOP ) ) )
602 {
604 moveVecs.emplace_back( 0, topLeft.y - oldBox.GetTop() );
605 m_rect.SetStartY( topLeft.y );
606 }
607 else if( isModified( aEditedPoint, aPoints.Line( RECT_LEFT ) ) )
608 {
610 moveVecs.emplace_back( topLeft.x - oldBox.GetLeft(), 0 );
611 m_rect.SetStartX( topLeft.x );
612 }
613 else if( isModified( aEditedPoint, aPoints.Line( RECT_BOT ) ) )
614 {
616 moveVecs.emplace_back( 0, botRight.y - oldBox.GetBottom() );
617 m_rect.SetEndY( botRight.y );
618 }
619 else if( isModified( aEditedPoint, aPoints.Line( RECT_RIGHT ) ) )
620 {
622 moveVecs.emplace_back( botRight.x - oldBox.GetRight(), 0 );
623 m_rect.SetEndX( botRight.x );
624 }
625
626 dragPinsOnEdge( oldSegs, moveVecs, m_rect.GetUnit(), aCommit, aUpdatedItems );
627
628 for( unsigned i = 0; i < aPoints.LinesSize(); ++i )
629 {
630 if( !isModified( aEditedPoint, aPoints.Line( i ) ) )
631 {
632 aPoints.Line( i ).SetConstraint( new EC_PERPLINE( aPoints.Line( i ) ) );
633 }
634 }
635 }
636
637private:
638 void dragPinsOnEdge( const std::vector<SEG>& aOldEdges, const std::vector<VECTOR2I>& aMoveVecs,
639 int aEdgeUnit, COMMIT& aCommit,
640 std::vector<EDA_ITEM*>& aUpdatedItems ) const
641 {
642 wxCHECK( aOldEdges.size() == aMoveVecs.size(), /* void */ );
643
644 // This only make sense in the symbol editor
646 return;
647
649
650 // And only if the setting is enabled
651 if( !editor.GetSettings()->m_dragPinsAlongWithEdges )
652 return;
653
654 // Adjuting pins on a different unit to a unit-limited shape
655 // seems suspect.
656 wxCHECK( aEdgeUnit == 0 || aEdgeUnit == editor.GetUnit(), /* void */ );
657
658 /*
659 * Get a list of pins on a line segment
660 */
661 const auto getPinsOnSeg = []( LIB_SYMBOL& aSymbol, int aUnit, const SEG& aSeg,
662 bool aIncludeEnds ) -> std::vector<SCH_PIN*>
663 {
664 // const BOX2I segBox = BOX2I::ByCorners( aSeg.A, aSeg.B ).GetInflated( 1 );
665 // const EE_RTREE& rtree = m_frame->GetScreen()->Items().Overlapping( SCH_PIN_T, segBox );
666
667 std::vector<SCH_PIN*> pins;
668
669 for( SCH_PIN* pin : aSymbol.GetPins( aUnit ) )
670 {
671 // Figure out if the pin "connects" to the line
672 const VECTOR2I pinRootPos = pin->GetPinRoot();
673
674 if( aSeg.Contains( pinRootPos ) )
675 {
676 if( aIncludeEnds || ( pinRootPos != aSeg.A && pinRootPos != aSeg.B ) )
677 {
678 pins.push_back( pin );
679 }
680 }
681 }
682
683 return pins;
684 };
685
686 LIB_SYMBOL* const symbol = editor.GetCurSymbol();
687
688 for( std::size_t i = 0; i < aOldEdges.size(); ++i )
689 {
690 if( aMoveVecs[i] == VECTOR2I( 0, 0 ) || !symbol )
691 continue;
692
693 const std::vector<SCH_PIN*> pins =
694 getPinsOnSeg( *symbol, aEdgeUnit, aOldEdges[i], false );
695
696 for( SCH_PIN* pin : pins )
697 {
698 aCommit.Modify( pin );
699 aUpdatedItems.push_back( pin );
700
701 // Move the pin
702 pin->Move( aMoveVecs[i] );
703 }
704 }
705 }
706
709};
710
711
713{
714public:
716
717 void MakePoints( EDIT_POINTS& aPoints ) override
718 {
721 }
722
723 void UpdatePoints( EDIT_POINTS& aPoints ) override
724 {
725 // point editor works only with rectangles having width and height > 0
726 // Some symbols can have rectangles with width or height < 0
727 // So normalize the size:
730 }
731
732 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
733 std::vector<EDA_ITEM*>& aUpdatedItems ) override
734 {
737 }
738
739private:
741};
742
743
745{
746public:
748
749 void MakePoints( EDIT_POINTS& aPoints ) override
750 {
751 VECTOR2I topLeft = m_sheet.GetPosition();
752 VECTOR2I botRight = m_sheet.GetPosition() + m_sheet.GetSize();
753
754 aPoints.AddPoint( topLeft );
755 aPoints.AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
756 aPoints.AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
757 aPoints.AddPoint( botRight );
758
759 aPoints.AddLine( aPoints.Point( RECT_TOPLEFT ), aPoints.Point( RECT_TOPRIGHT ) );
760 aPoints.Line( RECT_TOP ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_TOP ) ) );
761 aPoints.AddLine( aPoints.Point( RECT_TOPRIGHT ), aPoints.Point( RECT_BOTRIGHT ) );
762 aPoints.Line( RECT_RIGHT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_RIGHT ) ) );
763 aPoints.AddLine( aPoints.Point( RECT_BOTRIGHT ), aPoints.Point( RECT_BOTLEFT ) );
764 aPoints.Line( RECT_BOT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_BOT ) ) );
765 aPoints.AddLine( aPoints.Point( RECT_BOTLEFT ), aPoints.Point( RECT_TOPLEFT ) );
766 aPoints.Line( RECT_LEFT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_LEFT ) ) );
767 }
768
769 void UpdatePoints( EDIT_POINTS& aPoints ) override
770 {
771 VECTOR2I topLeft = m_sheet.GetPosition();
772 VECTOR2I botRight = m_sheet.GetPosition() + m_sheet.GetSize();
773
774 aPoints.Point( RECT_TOPLEFT ).SetPosition( topLeft );
775 aPoints.Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
776 aPoints.Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
777 aPoints.Point( RECT_BOTRIGHT ).SetPosition( botRight );
778 }
779
780 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
781 std::vector<EDA_ITEM*>& aUpdatedItems ) override
782 {
783 VECTOR2I topLeft = aPoints.Point( RECT_TOPLEFT ).GetPosition();
784 VECTOR2I topRight = aPoints.Point( RECT_TOPRIGHT ).GetPosition();
785 VECTOR2I botLeft = aPoints.Point( RECT_BOTLEFT ).GetPosition();
786 VECTOR2I botRight = aPoints.Point( RECT_BOTRIGHT ).GetPosition();
787 VECTOR2I sheetNewPos = m_sheet.GetPosition();
788 VECTOR2I sheetNewSize = m_sheet.GetSize();
789
790 bool editedTopRight = isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) );
791 bool editedBotLeft = isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) );
792 bool editedBotRight = isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) );
793
794 if( isModified( aEditedPoint, aPoints.Line( RECT_RIGHT ) ) )
795 editedTopRight = true;
796 else if( isModified( aEditedPoint, aPoints.Line( RECT_BOT ) ) )
797 editedBotLeft = true;
798
800 aEditedPoint, aPoints, m_sheet.GetMinWidth( editedTopRight || editedBotRight ),
801 m_sheet.GetMinHeight( editedBotLeft || editedBotRight ), topLeft, topRight, botLeft,
802 botRight );
803
804 if( isModified( aEditedPoint, aPoints.Point( RECT_TOPLEFT ) )
805 || isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) )
806 || isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) )
807 || isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) ) )
808 {
809 sheetNewPos = topLeft;
810 sheetNewSize = VECTOR2I( botRight.x - topLeft.x, botRight.y - topLeft.y );
811 }
812 else if( isModified( aEditedPoint, aPoints.Line( RECT_TOP ) ) )
813 {
814 sheetNewPos = VECTOR2I( m_sheet.GetPosition().x, topLeft.y );
815 sheetNewSize = VECTOR2I( m_sheet.GetSize().x, botRight.y - topLeft.y );
816 }
817 else if( isModified( aEditedPoint, aPoints.Line( RECT_LEFT ) ) )
818 {
819 sheetNewPos = VECTOR2I( topLeft.x, m_sheet.GetPosition().y );
820 sheetNewSize = VECTOR2I( botRight.x - topLeft.x, m_sheet.GetSize().y );
821 }
822 else if( isModified( aEditedPoint, aPoints.Line( RECT_BOT ) ) )
823 {
824 sheetNewSize = VECTOR2I( m_sheet.GetSize().x, botRight.y - topLeft.y );
825 }
826 else if( isModified( aEditedPoint, aPoints.Line( RECT_RIGHT ) ) )
827 {
828 sheetNewSize = VECTOR2I( botRight.x - topLeft.x, m_sheet.GetSize().y );
829 }
830
831 for( unsigned i = 0; i < aPoints.LinesSize(); ++i )
832 {
833 if( !isModified( aEditedPoint, aPoints.Line( i ) ) )
834 {
835 aPoints.Line( i ).SetConstraint( new EC_PERPLINE( aPoints.Line( i ) ) );
836 }
837 }
838
839 if( m_sheet.GetPosition() != sheetNewPos )
840 m_sheet.SetPositionIgnoringPins( sheetNewPos );
841
842 if( m_sheet.GetSize() != sheetNewSize )
843 m_sheet.Resize( sheetNewSize );
844 }
845
846private:
848};
849
850
852{
853 m_editBehavior = nullptr;
854 m_editPoints = std::make_shared<EDIT_POINTS>( aItem );
855
856 if( !aItem )
857 return;
858
859 // Generate list of edit points based on the item type
860 switch( aItem->Type() )
861 {
862 case SCH_SHAPE_T:
863 {
864 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
865
866 switch( shape->GetShape() )
867 {
868 case SHAPE_T::ARC:
869 m_editBehavior = std::make_unique<ARC_POINT_EDIT_BEHAVIOR>( *shape );
870 break;
871 case SHAPE_T::CIRCLE:
872 m_editBehavior = std::make_unique<EDA_CIRCLE_POINT_EDIT_BEHAVIOR>( *shape );
873 break;
874 case SHAPE_T::RECTANGLE:
875 m_editBehavior = std::make_unique<RECTANGLE_POINT_EDIT_BEHAVIOR>( *shape, *m_frame );
876 break;
877 case SHAPE_T::POLY:
878 m_editBehavior = std::make_unique<EDA_POLYGON_POINT_EDIT_BEHAVIOR>( *shape );
879 break;
880 case SHAPE_T::BEZIER:
881 m_editBehavior = std::make_unique<EDA_BEZIER_POINT_EDIT_BEHAVIOR>( *shape );
882 break;
883 default:
885 }
886
887 break;
888 }
889 case SCH_RULE_AREA_T:
890 {
891 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
892 // Implemented directly as a polygon
893 m_editBehavior = std::make_unique<EDA_POLYGON_POINT_EDIT_BEHAVIOR>( *shape );
894 break;
895 }
896 case SCH_TEXTBOX_T:
897 {
898 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( aItem );
899 m_editBehavior = std::make_unique<TEXTBOX_POINT_EDIT_BEHAVIOR>( *textbox );
900 break;
901 }
902 case SCH_TABLECELL_T:
903 {
904 SCH_TABLECELL* cell = static_cast<SCH_TABLECELL*>( aItem );
905 m_editBehavior = std::make_unique<SCH_TABLECELL_POINT_EDIT_BEHAVIOR>( *cell );
906 break;
907 }
908 case SCH_SHEET_T:
909 {
910 SCH_SHEET& sheet = static_cast<SCH_SHEET&>( *aItem );
911 m_editBehavior = std::make_unique<SHEET_POINT_EDIT_BEHAVIOR>( sheet );
912 break;
913 }
914 case SCH_BITMAP_T:
915 {
916 SCH_BITMAP& bitmap = static_cast<SCH_BITMAP&>( *aItem );
917 m_editBehavior = std::make_unique<BITMAP_POINT_EDIT_BEHAVIOR>( bitmap );
918 break;
919 }
920 case SCH_LINE_T:
921 {
922 SCH_LINE& line = static_cast<SCH_LINE&>( *aItem );
923 m_editBehavior = std::make_unique<LINE_POINT_EDIT_BEHAVIOR>( line, *m_frame->GetScreen() );
924 break;
925 }
926 default:
927 {
928 m_editPoints.reset();
929 break;
930 }
931 }
932
933 // If we got a behavior, generate the points
934 if( m_editBehavior )
935 {
936 wxCHECK( m_editPoints, /* void */ );
937 m_editBehavior->MakePoints( *m_editPoints );
938 }
939}
940
941
943 EE_TOOL_BASE<SCH_BASE_FRAME>( "eeschema.PointEditor" ),
944 m_editedPoint( nullptr ),
945 m_inPointEditor( false )
946{
947}
948
949
951{
952 EE_TOOL_BASE::Reset( aReason );
953
954 m_editPoints.reset();
955 m_editedPoint = nullptr;
956}
957
958
960{
962
963 auto& menu = m_selectionTool->GetToolMenu().GetMenu();
965 std::bind( &EE_POINT_EDITOR::addCornerCondition, this, _1 ) );
967 std::bind( &EE_POINT_EDITOR::removeCornerCondition, this, _1 ) );
968
969 return true;
970}
971
972
974{
975 setEditedPoint( nullptr );
976
977 return 0;
978}
979
980
982{
983 EDIT_POINT* point = m_editedPoint;
984
985 if( !m_editPoints )
986 {
987 point = nullptr;
988 }
989 else if( aEvent.IsMotion() )
990 {
991 point = m_editPoints->FindPoint( aEvent.Position(), getView() );
992 }
993 else if( aEvent.IsDrag( BUT_LEFT ) )
994 {
995 point = m_editPoints->FindPoint( aEvent.DragOrigin(), getView() );
996 }
997 else
998 {
999 point = m_editPoints->FindPoint( getViewControls()->GetCursorPosition( false ), getView() );
1000 }
1001
1002 if( m_editedPoint != point )
1003 setEditedPoint( point );
1004}
1005
1006
1008{
1009 if( !m_selectionTool )
1010 return 0;
1011
1012 if( m_inPointEditor )
1013 return 0;
1014
1016
1017 if( m_isSymbolEditor )
1018 {
1019 SYMBOL_EDIT_FRAME* editor = getEditFrame<SYMBOL_EDIT_FRAME>();
1020
1021 if( !editor->IsSymbolEditable() || editor->IsSymbolAlias() )
1022 return 0;
1023 }
1024
1025 const EE_SELECTION& selection = m_selectionTool->GetSelection();
1026
1027 if( selection.Size() != 1 || !selection.Front()->IsType( pointEditorTypes ) )
1028 {
1029 return 0;
1030 }
1031
1032 // Wait till drawing tool is done
1033 if( selection.Front()->IsNew() )
1034 return 0;
1035
1036 Activate();
1037
1040 VECTOR2I cursorPos;
1041 KIGFX::VIEW* view = getView();
1042 EDA_ITEM* item = selection.Front();
1043 SCH_COMMIT commit( m_toolMgr );
1044
1045 controls->ShowCursor( true );
1046
1047 makePointsAndBehavior( item );
1048 view->Add( m_editPoints.get() );
1049 setEditedPoint( nullptr );
1050 updateEditedPoint( aEvent );
1051 bool inDrag = false;
1052
1053 // Main loop: keep receiving events
1054 while( TOOL_EVENT* evt = Wait() )
1055 {
1056 if( grid )
1057 {
1058 grid->SetSnap( !evt->Modifier( MD_SHIFT ) );
1059 grid->SetUseGrid( getView()->GetGAL()->GetGridSnapping()
1060 && !evt->DisableGridSnapping() );
1061 }
1062 else
1063 {
1064 // This check is based on the assumption that the grid object must be valid.
1065 // If this assumption is wrong, please fix the code above.
1066 wxCHECK( false, 0 );
1067 }
1068
1069 if( !m_editPoints || evt->IsSelectionEvent() )
1070 break;
1071
1072 if ( !inDrag )
1073 updateEditedPoint( *evt );
1074
1075 if( evt->IsDrag( BUT_LEFT ) && m_editedPoint )
1076 {
1077 if( !inDrag )
1078 {
1079 commit.Modify( m_editPoints->GetParent(), m_frame->GetScreen() );
1080 inDrag = true;
1081 }
1082
1083 bool snap = !evt->DisableGridSnapping();
1084
1085 cursorPos =
1086 grid->Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
1087 controls->ForceCursorPosition( true, cursorPos );
1088
1089 m_editedPoint->SetPosition( controls->GetCursorPosition( snap ) );
1090
1091 updateParentItem( snap, commit );
1092 updatePoints();
1093 }
1094 else if( inDrag && evt->IsMouseUp( BUT_LEFT ) )
1095 {
1096 if( !commit.Empty() )
1097 commit.Push( _( "Move Point" ) );
1098
1099 controls->SetAutoPan( false );
1100 inDrag = false;
1101 }
1102 else if( evt->IsCancelInteractive() || evt->IsActivate() )
1103 {
1104 if( inDrag ) // Restore the last change
1105 {
1106 // Currently we are manually managing the lifetime of the grid
1107 // helpers because there is a bug in the tool stack that adds
1108 // the point editor again when commit.Revert() rebuilds the selection.
1109 // We remove this grid here so the its destructor is called before it
1110 // is added again.
1111 if( grid )
1112 {
1113 delete grid;
1114 grid = nullptr;
1115 }
1116
1117 commit.Revert();
1118 inDrag = false;
1119 break;
1120 }
1121 else if( evt->IsCancelInteractive() )
1122 {
1123 break;
1124 }
1125
1126 if( evt->IsActivate() )
1127 break;
1128 }
1129 else
1130 {
1131 evt->SetPassEvent();
1132 }
1133
1134 controls->SetAutoPan( inDrag );
1135 controls->CaptureCursor( inDrag );
1136 }
1137
1138 controls->SetAutoPan( false );
1139 controls->CaptureCursor( false );
1140 setEditedPoint( nullptr );
1141
1142 if( m_editPoints )
1143 {
1144 view->Remove( m_editPoints.get() );
1145
1146 m_editPoints.reset();
1148 }
1149
1150 delete grid;
1151
1152 return 0;
1153}
1154
1155
1156void EE_POINT_EDITOR::updateParentItem( bool aSnapToGrid, SCH_COMMIT& aCommit ) const
1157{
1158 EDA_ITEM* item = m_editPoints->GetParent();
1159
1160 if( !item )
1161 return;
1162
1163 if( !m_editBehavior )
1164 return;
1165
1166 std::vector<EDA_ITEM*> updatedItems;
1167 m_editBehavior->UpdateItem( *m_editedPoint, *m_editPoints, aCommit, updatedItems );
1168
1169 for( EDA_ITEM* updatedItem : updatedItems )
1170 {
1171 updateItem( updatedItem, true );
1172 }
1173 m_frame->SetMsgPanel( item );
1174}
1175
1176
1178{
1179 if( !m_editPoints || !m_editBehavior )
1180 return;
1181
1182 m_editBehavior->UpdatePoints( *m_editPoints );
1183 getView()->Update( m_editPoints.get() );
1184}
1185
1186
1188{
1190
1191 if( aPoint )
1192 {
1193 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1194 controls->ForceCursorPosition( true, aPoint->GetPosition() );
1195 controls->ShowCursor( true );
1196 }
1197 else
1198 {
1199 if( m_frame->ToolStackIsEmpty() )
1200 controls->ShowCursor( false );
1201
1202 controls->ForceCursorPosition( false );
1203 }
1204
1205 m_editedPoint = aPoint;
1206}
1207
1208
1210{
1211 bool isRuleArea = false;
1212
1213 if( m_editPoints )
1214 isRuleArea = m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T;
1215
1217 || !( m_editPoints->GetParent()->Type() == SCH_SHAPE_T || isRuleArea ) )
1218 {
1219 return false;
1220 }
1221
1222 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1223
1224 if( shape->GetPolyShape().IsEmpty() )
1225 return false;
1226
1227 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1228
1229 if( m_editPoints->GetParent()->Type() == SCH_SHAPE_T && poly.GetPointCount() <= 2 )
1230 return false;
1231 if( m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T && poly.GetPointCount() <= 3 )
1232 return false;
1233
1234 for( const VECTOR2I& pt : poly.CPoints() )
1235 {
1236 if( pt == m_editedPoint->GetPosition() )
1237 return true;
1238 }
1239
1240 return false;
1241}
1242
1243
1245{
1246 if( !m_editPoints
1247 || !( m_editPoints->GetParent()->Type() == SCH_SHAPE_T
1248 || m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T ) )
1249 {
1250 return false;
1251 }
1252
1253 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1254
1255 if( shape->GetShape() != SHAPE_T::POLY )
1256 return false;
1257
1258 VECTOR2I cursorPos = getViewControls()->GetCursorPosition( false );
1259 double threshold = getView()->ToWorld( EDIT_POINT::POINT_SIZE );
1260
1261 return shape->HitTest( cursorPos, (int) threshold );
1262}
1263
1264
1266{
1267 if( !m_editPoints
1268 || !( m_editPoints->GetParent()->Type() == SCH_SHAPE_T
1269 || m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T ) )
1270 return 0;
1271
1272 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1273 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1274 SCH_COMMIT commit( m_toolMgr );
1275
1276 commit.Modify( shape, m_frame->GetScreen() );
1277
1279 int currentMinDistance = INT_MAX;
1280 int closestLineStart = 0;
1281 unsigned numPoints = poly.GetPointCount();
1282
1283 if( !shape->IsClosed() )
1284 numPoints -= 1;
1285
1286 for( unsigned i = 0; i < numPoints; ++i )
1287 {
1288 SEG seg = poly.GetSegment( i );
1289 int distance = seg.Distance( cursor );
1290
1291 if( distance < currentMinDistance )
1292 {
1293 currentMinDistance = distance;
1294 closestLineStart = i;
1295 }
1296 }
1297
1298 poly.Insert( closestLineStart + 1, cursor );
1299
1300 updateItem( shape, true );
1301 updatePoints();
1302
1303 commit.Push( _( "Add Corner" ) );
1304 return 0;
1305}
1306
1307
1309{
1311 || !m_editPoints->GetParent()->IsType( { SCH_SHAPE_T, SCH_RULE_AREA_T } ) )
1312 {
1313 return 0;
1314 }
1315
1316 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1317 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1318 SCH_COMMIT commit( m_toolMgr );
1319
1320 if( m_editPoints->GetParent()->Type() == SCH_SHAPE_T && poly.GetPointCount() <= 2 )
1321 return 0;
1322 if( m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T && poly.GetPointCount() <= 3 )
1323 return 0;
1324
1325 commit.Modify( shape, m_frame->GetScreen() );
1326
1327 int idx = getEditedPointIndex();
1328 int last = (int) poly.GetPointCount() - 1;
1329
1330 if( idx == 0 && poly.GetPoint( 0 ) == poly.GetPoint( last ) )
1331 {
1332 poly.Remove( idx );
1333 poly.SetPoint( last-1, poly.GetPoint( 0 ) );
1334 }
1335 else
1336 {
1337 poly.Remove( idx );
1338 }
1339
1340 setEditedPoint( nullptr );
1341
1342 updateItem( shape, true );
1343 updatePoints();
1344
1345 commit.Push( _( "Remove Corner" ) );
1346 return 0;
1347}
1348
1349
1351{
1352 updatePoints();
1353 return 0;
1354}
1355
1356
1358{
1366}
1367
1368
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:110
static TOOL_ACTION activatePointEditor
Definition: actions.h:221
void MakePoints(EDIT_POINTS &aPoints) override
Construct the initial set of edit points for the item and append to the given list.
ARC_POINT_EDIT_BEHAVIOR(SCH_SHAPE &aArc)
void UpdatePoints(EDIT_POINTS &aPoints) override
Update the list of the edit points for the item.
void UpdateItem(const EDIT_POINT &aEditedPoint, EDIT_POINTS &aPoints, COMMIT &aCommit, std::vector< EDA_ITEM * > &aUpdatedItems) override
Update the item with the new positions of the edit points.
void MakePoints(EDIT_POINTS &aPoints) override
Construct the initial set of edit points for the item and append to the given list.
void UpdateItem(const EDIT_POINT &aEditedPoint, EDIT_POINTS &aPoints, COMMIT &aCommit, std::vector< EDA_ITEM * > &aUpdatedItems) override
Update the item with the new positions of the edit points.
BITMAP_POINT_EDIT_BEHAVIOR(SCH_BITMAP &aBitmap)
void UpdatePoints(EDIT_POINTS &aPoints) override
Update the list of the edit points for the item.
static constexpr BOX2< VECTOR2I > ByCorners(const VECTOR2I &aCorner1, const VECTOR2I &aCorner2)
Definition: box2.h:70
constexpr const Vec GetCenter() const
Definition: box2.h:230
constexpr coord_type GetLeft() const
Definition: box2.h:228
constexpr coord_type GetRight() const
Definition: box2.h:217
constexpr coord_type GetTop() const
Definition: box2.h:229
constexpr coord_type GetBottom() const
Definition: box2.h:222
Represent a set of changes (additions, deletions or modifications) of a data model (e....
Definition: commit.h:74
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.
bool IsType(FRAME_T aType) const
The base class for create windows for drawing purpose.
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
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
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:167
bool IsClosed() const
Definition: eda_shape.cpp:247
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
wxString SHAPE_T_asString() const
Definition: eda_shape.cpp:89
int GetRectangleHeight() const
Definition: eda_shape.cpp:153
"Standard" table-cell editing behavior.
virtual void ClearRenderCache()
Definition: eda_text.cpp:544
void SetConstraint(EDIT_CONSTRAINT< EDIT_LINE > *aConstraint)
Set a constraint for and EDIT_POINT.
Definition: edit_points.h:267
EDIT_POINTS is a VIEW_ITEM that manages EDIT_POINTs and EDIT_LINEs and draws them.
Definition: edit_points.h:353
void AddPoint(const EDIT_POINT &aPoint)
Add an EDIT_POINT.
Definition: edit_points.h:390
EDIT_LINE & Line(unsigned int aIndex)
Definition: edit_points.h:521
void AddIndicatorLine(EDIT_POINT &aOrigin, EDIT_POINT &aEnd)
Adds an EDIT_LINE that is shown as an indicator, rather than an editable line (no center point drag,...
Definition: edit_points.h:434
unsigned int LinesSize() const
Return number of stored EDIT_LINEs.
Definition: edit_points.h:542
EDIT_POINT & Point(unsigned int aIndex)
Definition: edit_points.h:511
void AddLine(const EDIT_LINE &aLine)
Adds an EDIT_LINE.
Definition: edit_points.h:410
Represent a single point that can be used for modifying items.
Definition: edit_points.h:48
virtual std::pair< EDA_ITEM *, int > GetConnected() const
Return a connected item record comprising an EDA_ITEM* and a STARTPOINT/ENDPOINT flag.
Definition: edit_points.h:79
int GetY() const
Return Y coordinate of an EDIT_POINT.
Definition: edit_points.h:95
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
int GetX() const
Return X coordinate of an EDIT_POINT.
Definition: edit_points.h:87
static TOOL_ACTION pointEditorRemoveCorner
Definition: ee_actions.h:153
static TOOL_ACTION pointEditorAddCorner
Definition: ee_actions.h:152
void updatePoints()
Update which point is being edited.
bool m_inPointEditor
Currently available edit points.
void updateParentItem(bool aSnapToGrid, SCH_COMMIT &aCommit) const
< Update item's points with edit points.
int Main(const TOOL_EVENT &aEvent)
void makePointsAndBehavior(EDA_ITEM *aItem)
Currently edited point, NULL if there is none.
std::unique_ptr< POINT_EDIT_BEHAVIOR > m_editBehavior
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
Re-entrancy guards.
bool addCornerCondition(const SELECTION &aSelection)
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
int addCorner(const TOOL_EVENT &aEvent)
TOOL_ACTION handlers.
std::shared_ptr< EDIT_POINTS > m_editPoints
Current item-specific edit behavior.
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.
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:294
static const TOOL_EVENT SelectedEvent
Definition: actions.h:292
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition: actions.h:299
static const TOOL_EVENT PointSelectedEvent
Definition: actions.h:291
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
Define a library symbol object.
Definition: lib_symbol.h:78
std::vector< SCH_PIN * > GetPins(int aUnit=0, int aBodyStyle=0) const
Return a list of pin object pointers from the draw item list.
Definition: lib_symbol.cpp:810
void UpdatePoints(EDIT_POINTS &aPoints) override
Update the list of the edit points for the item.
void UpdateItem(const EDIT_POINT &aEditedPoints, EDIT_POINTS &aPoints, COMMIT &aCommit, std::vector< EDA_ITEM * > &aUpdatedItems) override
Update the item with the new positions of the edit points.
void MakePoints(EDIT_POINTS &aPoints) override
Construct the initial set of edit points for the item and append to the given list.
LINE_POINT_EDIT_BEHAVIOR(SCH_LINE &aLine, SCH_SCREEN &aScreen)
A helper class interface to manage the edit points for a single item.
static bool isModified(const EDIT_POINT &aEditedPoint, const EDIT_POINT &aPoint)
Checks if two points are the same instance - which means the point is being edited.
static void UpdateItem(SCH_SHAPE &aRect, const EDIT_POINT &aEditedPoint, EDIT_POINTS &aPoints)
static void UpdatePoints(SCH_SHAPE &aRect, EDIT_POINTS &aPoints)
static void PinEditedCorner(const EDIT_POINT &aEditedPoint, const EDIT_POINTS &aPoints, int minWidth, int minHeight, VECTOR2I &topLeft, VECTOR2I &topRight, VECTOR2I &botLeft, VECTOR2I &botRight)
Update the coordinates of 4 corners of a rectangle, according to constraints and the moved corner.
static void MakePoints(SCH_SHAPE &aRect, EDIT_POINTS &aPoints)
void UpdateItem(const EDIT_POINT &aEditedPoint, EDIT_POINTS &aPoints, COMMIT &aCommit, std::vector< EDA_ITEM * > &aUpdatedItems) override
Update the item with the new positions of the edit points.
void MakePoints(EDIT_POINTS &aPoints) override
Construct the initial set of edit points for the item and append to the given list.
RECTANGLE_POINT_EDIT_BEHAVIOR(SCH_SHAPE &aRect, EDA_DRAW_FRAME &aFrame)
void dragPinsOnEdge(const std::vector< SEG > &aOldEdges, const std::vector< VECTOR2I > &aMoveVecs, int aEdgeUnit, COMMIT &aCommit, std::vector< EDA_ITEM * > &aUpdatedItems) const
void UpdatePoints(EDIT_POINTS &aPoints) override
Update the list of the edit points for the item.
A REFERENCE_IMAGE is a wrapper around a BITMAP_IMAGE that is displayed in an editor as a reference fo...
void SetTransformOriginOffset(const VECTOR2I &aCenter)
VECTOR2I GetTransformOriginOffset() const
Get the center of scaling, etc, relative to the image center (GetPosition()).
VECTOR2I GetPosition() const
VECTOR2I GetSize() const
double GetImageScale() const
void SetImageScale(double aScale)
Set the image "zoom" value.
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:40
REFERENCE_IMAGE & GetReferenceImage()
Definition: sch_bitmap.h:51
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:432
virtual void Revert() override
Definition: sch_commit.cpp:510
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:166
int GetUnit() const
Definition: sch_item.h:229
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 Move(const VECTOR2I &aOffset) override
Move the item by aMoveVector to a new position.
Definition: sch_shape.cpp:69
void SetEditState(int aState)
Definition: sch_shape.h:79
VECTOR2I GetCenter() const
Definition: sch_shape.h:73
void Normalize()
Definition: sch_shape.cpp:75
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:900
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:548
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:582
void Resize(const VECTOR2I &aSize)
Resize this sheet to aSize and adjust all of the labels accordingly.
Definition: sch_sheet.cpp:1013
void UpdateItem(const EDIT_POINT &aEditedPoint, EDIT_POINTS &aPoints, COMMIT &aCommit, std::vector< EDA_ITEM * > &aUpdatedItems) override
Update the item with the new positions of the edit points.
SCH_TABLECELL_POINT_EDIT_BEHAVIOR(SCH_TABLECELL &aCell)
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
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
void UpdatePoints(EDIT_POINTS &aPoints) override
Update the list of the edit points for the item.
SHEET_POINT_EDIT_BEHAVIOR(SCH_SHEET &aSheet)
void UpdateItem(const EDIT_POINT &aEditedPoint, EDIT_POINTS &aPoints, COMMIT &aCommit, std::vector< EDA_ITEM * > &aUpdatedItems) override
Update the item with the new positions of the edit points.
void MakePoints(EDIT_POINTS &aPoints) override
Construct the initial set of edit points for the item and append to the given list.
The symbol library editor main window.
A textbox is edited as a rectnagle when it is orthogonally aligned.
void MakePoints(EDIT_POINTS &aPoints) override
Construct the initial set of edit points for the item and append to the given list.
void UpdateItem(const EDIT_POINT &aEditedPoint, EDIT_POINTS &aPoints, COMMIT &aCommit, std::vector< EDA_ITEM * > &aUpdatedItems) override
Update the item with the new positions of the edit points.
void UpdatePoints(EDIT_POINTS &aPoints) override
Update the list of the edit points for the item.
TEXTBOX_POINT_EDIT_BEHAVIOR(SCH_TEXTBOX &aTextbox)
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
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:283
#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_CENTER
@ 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
REFIMAGE_POINTS
@ REFIMG_ORIGIN
ARC_POINTS
@ ARC_START
@ ARC_END
@ ARC_CENTER
@ FRAME_SCH_SYMBOL_EDITOR
Definition: frame_type.h:35
@ LAYER_NOTES
Definition: layer_ids.h:371
#define UNIMPLEMENTED_FOR(type)
Definition: macros.h:96
constexpr int Mils2IU(const EDA_IU_SCALE &aIuScale, int mils)
Definition: eda_units.h:157
std::vector< SEG > GetSegsInDirection(const BOX2I &aBox, DIRECTION_45::Directions aDir)
Get the segments of a box that are in the given direction.
Definition: shape_utils.cpp:92
@ RECT_RIGHT
@ RECT_LEFT
@ RECT_BOT
@ RECT_TOP
@ RECT_CENTER
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
std::optional< VECTOR2I > OPT_VECTOR2I
Definition: seg.h:39
Utility functions for working with shapes.
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
constexpr int sign(T val)
Definition: util.h:159
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:691