KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_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 The 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 "sch_point_editor.h"
26
27#include <algorithm>
28#include <ee_grid_helper.h>
29#include <tool/tool_manager.h>
30#include <sch_commit.h>
31#include <view/view_controls.h>
33#include <geometry/seg.h>
37#include <tools/sch_actions.h>
39#include <sch_edit_frame.h>
40#include <sch_line.h>
41#include <sch_bitmap.h>
42#include <sch_sheet.h>
43#include <sch_textbox.h>
44#include <sch_table.h>
45#include <sch_sheet_pin.h>
47#include <sch_no_connect.h>
48
49
57
58
59// Few constants to avoid using bare numbers for point indices
64
65
70
71
76
77
82
83
88
93
94
96{
97public:
99 m_line( aLine ),
100 m_screen( aScreen )
101 {
102 }
103
104 void MakePoints( EDIT_POINTS& aPoints ) override
105 {
106 std::pair<EDA_ITEM*, int> connectedStart = { nullptr, STARTPOINT };
107 std::pair<EDA_ITEM*, int> connectedEnd = { nullptr, STARTPOINT };
108
109 for( SCH_ITEM* test : m_screen.Items().OfType( SCH_LINE_T ) )
110 {
111 if( test->GetLayer() != LAYER_NOTES )
112 continue;
113
114 if( test == &m_line )
115 continue;
116
117 SCH_LINE* testLine = static_cast<SCH_LINE*>( test );
118
119 if( testLine->GetStartPoint() == m_line.GetStartPoint() )
120 {
121 connectedStart = { testLine, STARTPOINT };
122 }
123 else if( testLine->GetEndPoint() == m_line.GetStartPoint() )
124 {
125 connectedStart = { testLine, ENDPOINT };
126 }
127 else if( testLine->GetStartPoint() == m_line.GetEndPoint() )
128 {
129 connectedEnd = { testLine, STARTPOINT };
130 }
131 else if( testLine->GetEndPoint() == m_line.GetEndPoint() )
132 {
133 connectedEnd = { testLine, ENDPOINT };
134 }
135 }
136
137 aPoints.AddPoint( m_line.GetStartPoint(), connectedStart );
138 aPoints.AddPoint( m_line.GetEndPoint(), connectedEnd );
139 }
140
141 bool UpdatePoints( EDIT_POINTS& aPoints ) override
142 {
143 aPoints.Point( LINE_START ).SetPosition( m_line.GetStartPoint() );
144 aPoints.Point( LINE_END ).SetPosition( m_line.GetEndPoint() );
145 return true;
146 }
147
148 void UpdateItem( const EDIT_POINT& aEditedPoints, EDIT_POINTS& aPoints, COMMIT& aCommit,
149 std::vector<EDA_ITEM*>& aUpdatedItems ) override
150 {
151 m_line.SetStartPoint( aPoints.Point( LINE_START ).GetPosition() );
152 m_line.SetEndPoint( aPoints.Point( LINE_END ).GetPosition() );
153
154 std::pair<EDA_ITEM*, int> connected = aPoints.Point( LINE_START ).GetConnected();
155
156 if( connected.first )
157 {
158 aCommit.Modify( connected.first, &m_screen );
159 aUpdatedItems.push_back( connected.first );
160
161 if( connected.second == STARTPOINT )
162 static_cast<SCH_LINE*>( connected.first )->SetStartPoint( m_line.GetStartPoint() );
163 else if( connected.second == ENDPOINT )
164 static_cast<SCH_LINE*>( connected.first )->SetEndPoint( m_line.GetStartPoint() );
165 }
166
167 connected = aPoints.Point( LINE_END ).GetConnected();
168
169 if( connected.first )
170 {
171 aCommit.Modify( connected.first, &m_screen );
172 aUpdatedItems.push_back( connected.first );
173
174 if( connected.second == STARTPOINT )
175 static_cast<SCH_LINE*>( connected.first )->SetStartPoint( m_line.GetEndPoint() );
176 else if( connected.second == ENDPOINT )
177 static_cast<SCH_LINE*>( connected.first )->SetEndPoint( m_line.GetEndPoint() );
178 }
179 }
180
181private:
184};
185
187{
188public:
190 m_bitmap( aBitmap )
191 {}
192
193 void MakePoints( EDIT_POINTS& aPoints ) override
194 {
195 const REFERENCE_IMAGE& refImage = m_bitmap.GetReferenceImage();
196 const VECTOR2I topLeft = refImage.GetPosition() - refImage.GetSize() / 2;
197 const VECTOR2I botRight = refImage.GetPosition() + refImage.GetSize() / 2;
198
199 aPoints.AddPoint( topLeft );
200 aPoints.AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
201 aPoints.AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
202 aPoints.AddPoint( botRight );
203
204 aPoints.AddPoint( refImage.GetPosition() + refImage.GetTransformOriginOffset() );
205 }
206
207 bool UpdatePoints( EDIT_POINTS& aPoints ) override
208 {
209 const REFERENCE_IMAGE& refImage = m_bitmap.GetReferenceImage();
210 const VECTOR2I topLeft = refImage.GetPosition() - refImage.GetSize() / 2;
211 const VECTOR2I botRight = refImage.GetPosition() + refImage.GetSize() / 2;
212
213 aPoints.Point( RECT_TOPLEFT ).SetPosition( topLeft );
214 aPoints.Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
215 aPoints.Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
216 aPoints.Point( RECT_BOTRIGHT ).SetPosition( botRight );
217
218 aPoints.Point( REFIMG_ORIGIN ).SetPosition( refImage.GetPosition() + refImage.GetTransformOriginOffset() );
219 return true;
220 }
221
222 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
223 std::vector<EDA_ITEM*>& aUpdatedItems ) override
224 {
225 REFERENCE_IMAGE& refImg = m_bitmap.GetReferenceImage();
226 const VECTOR2I topLeft = aPoints.Point( RECT_TOPLEFT ).GetPosition();
227 const VECTOR2I topRight = aPoints.Point( RECT_TOPRIGHT ).GetPosition();
228 const VECTOR2I botLeft = aPoints.Point( RECT_BOTLEFT ).GetPosition();
229 const VECTOR2I botRight = aPoints.Point( RECT_BOTRIGHT ).GetPosition();
230 const VECTOR2I xfrmOrigin = aPoints.Point( REFIMG_ORIGIN ).GetPosition();
231
232 if( isModified( aEditedPoint, aPoints.Point( REFIMG_ORIGIN ) ) )
233 {
234 // Moving the transform origin
235 // As the other points didn't move, we can get the image extent from them
236 const VECTOR2I newOffset = xfrmOrigin - ( topLeft + botRight ) / 2;
237 refImg.SetTransformOriginOffset( newOffset );
238 }
239 else
240 {
241 const VECTOR2I oldOrigin = refImg.GetPosition() + refImg.GetTransformOriginOffset();
242 const VECTOR2I oldSize = refImg.GetSize();
243 const VECTOR2I pos = refImg.GetPosition();
244
245 OPT_VECTOR2I newCorner;
246 VECTOR2I oldCorner = pos;
247
248 if( isModified( aEditedPoint, aPoints.Point( RECT_TOPLEFT ) ) )
249 {
250 newCorner = topLeft;
251 oldCorner -= oldSize / 2;
252 }
253 else if( isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) ) )
254 {
255 newCorner = topRight;
256 oldCorner -= VECTOR2I( -oldSize.x, oldSize.y ) / 2;
257 }
258 else if( isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) ) )
259 {
260 newCorner = botLeft;
261 oldCorner -= VECTOR2I( oldSize.x, -oldSize.y ) / 2;
262 }
263 else if( isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) ) )
264 {
265 newCorner = botRight;
266 oldCorner += oldSize / 2;
267 }
268
269 if( newCorner )
270 {
271 // Turn in the respective vectors from the origin
272 *newCorner -= xfrmOrigin;
273 oldCorner -= oldOrigin;
274
275 // If we tried to cross the origin, clamp it to stop it
276 if( sign( newCorner->x ) != sign( oldCorner.x )
277 || sign( newCorner->y ) != sign( oldCorner.y ) )
278 {
279 *newCorner = VECTOR2I( 0, 0 );
280 }
281
282 const double newLength = newCorner->EuclideanNorm();
283 const double oldLength = oldCorner.EuclideanNorm();
284
285 double ratio = oldLength > 0 ? ( newLength / oldLength ) : 1.0;
286
287 // Clamp the scaling to a minimum of 50 mils
288 VECTOR2I newSize = oldSize * ratio;
289 double newWidth = std::max( newSize.x, EDA_UNIT_UTILS::Mils2IU( schIUScale, 50 ) );
290 double newHeight = std::max( newSize.y, EDA_UNIT_UTILS::Mils2IU( schIUScale, 50 ) );
291 ratio = std::min( newWidth / oldSize.x, newHeight / oldSize.y );
292
293 // Also handles the origin offset
294 refImg.SetImageScale( refImg.GetImageScale() * ratio );
295 }
296 }
297 aUpdatedItems.push_back( &m_bitmap );
298 }
299
300private:
302};
303
304
306{
307public:
310 m_cell( aCell ),
311 m_screen( aScreen )
312 {
313 }
314
315 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
316 std::vector<EDA_ITEM*>& aUpdatedItems ) override
317 {
318 SCH_TABLE& table = static_cast<SCH_TABLE&>( *m_cell.GetParent() );
319 bool rotated = !m_cell.GetTextAngle().IsHorizontal();
320
321 aCommit.Modify( &table, &m_screen );
322 aUpdatedItems.push_back( &table );
323
324 if( rotated )
325 {
326 if( isModified( aEditedPoint, aPoints.Point( ROW_HEIGHT ) ) )
327 {
328 m_cell.SetEnd( VECTOR2I( m_cell.GetEndX(), aPoints.Point( ROW_HEIGHT ).GetY() ) );
329
330 int colWidth = std::abs( m_cell.GetRectangleHeight() );
331
332 for( int ii = 0; ii < m_cell.GetColSpan() - 1; ++ii )
333 colWidth -= table.GetColWidth( m_cell.GetColumn() + ii );
334
335 table.SetColWidth( m_cell.GetColumn() + m_cell.GetColSpan() - 1, colWidth );
336 }
337 else if( isModified( aEditedPoint, aPoints.Point( COL_WIDTH ) ) )
338 {
339 m_cell.SetEnd( VECTOR2I( aPoints.Point( COL_WIDTH ).GetX(), m_cell.GetEndY() ) );
340
341 int rowHeight = m_cell.GetRectangleWidth();
342
343 for( int ii = 0; ii < m_cell.GetRowSpan() - 1; ++ii )
344 rowHeight -= table.GetRowHeight( m_cell.GetRow() + ii );
345
346 table.SetRowHeight( m_cell.GetRow() + m_cell.GetRowSpan() - 1, rowHeight );
347 }
348 }
349 else
350 {
351 if( isModified( aEditedPoint, aPoints.Point( COL_WIDTH ) ) )
352 {
353 m_cell.SetEnd( VECTOR2I( aPoints.Point( COL_WIDTH ).GetX(), m_cell.GetEndY() ) );
354
355 int colWidth = m_cell.GetRectangleWidth();
356
357 for( int ii = 0; ii < m_cell.GetColSpan() - 1; ++ii )
358 colWidth -= table.GetColWidth( m_cell.GetColumn() + ii );
359
360 table.SetColWidth( m_cell.GetColumn() + m_cell.GetColSpan() - 1, colWidth );
361 }
362 else if( isModified( aEditedPoint, aPoints.Point( ROW_HEIGHT ) ) )
363 {
364 m_cell.SetEnd( VECTOR2I( m_cell.GetEndX(), aPoints.Point( ROW_HEIGHT ).GetY() ) );
365
366 int rowHeight = m_cell.GetRectangleHeight();
367
368 for( int ii = 0; ii < m_cell.GetRowSpan() - 1; ++ii )
369 rowHeight -= table.GetRowHeight( m_cell.GetRow() + ii );
370
371 table.SetRowHeight( m_cell.GetRow() + m_cell.GetRowSpan() - 1, rowHeight );
372 }
373 }
374
375 table.Normalize();
376 }
377
378private:
381};
382
383
385{
386public:
388 m_rect( aRect ),
389 m_frame( aFrame )
390 {
391 }
392
393 static void MakePoints( SCH_SHAPE& aRect, EDIT_POINTS& aPoints )
394 {
395 VECTOR2I topLeft = aRect.GetPosition();
396 VECTOR2I botRight = aRect.GetEnd();
397
398 aPoints.AddPoint( topLeft );
399 aPoints.AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
400 aPoints.AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
401 aPoints.AddPoint( botRight );
402 aPoints.AddPoint( aRect.GetCenter() );
403 aPoints.AddPoint( VECTOR2I( botRight.x - aRect.GetCornerRadius(), topLeft.y ) );
404 aPoints.Point( RECT_RADIUS ).SetDrawCircle();
405
406 aPoints.AddLine( aPoints.Point( RECT_TOPLEFT ), aPoints.Point( RECT_TOPRIGHT ) );
407 aPoints.Line( RECT_TOP ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_TOP ) ) );
408 aPoints.AddLine( aPoints.Point( RECT_TOPRIGHT ), aPoints.Point( RECT_BOTRIGHT ) );
409 aPoints.Line( RECT_RIGHT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_RIGHT ) ) );
410 aPoints.AddLine( aPoints.Point( RECT_BOTRIGHT ), aPoints.Point( RECT_BOTLEFT ) );
411 aPoints.Line( RECT_BOT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_BOT ) ) );
412 aPoints.AddLine( aPoints.Point( RECT_BOTLEFT ), aPoints.Point( RECT_TOPLEFT ) );
413 aPoints.Line( RECT_LEFT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_LEFT ) ) );
414 }
415
416 static void UpdatePoints( SCH_SHAPE& aRect, EDIT_POINTS& aPoints )
417 {
418 VECTOR2I topLeft = aRect.GetPosition();
419 VECTOR2I botRight = aRect.GetEnd();
420
421 aPoints.Point( RECT_TOPLEFT ).SetPosition( topLeft );
422 aPoints.Point( RECT_RADIUS ).SetPosition( VECTOR2I( botRight.x - aRect.GetCornerRadius(), topLeft.y ) );
423 aPoints.Point( RECT_TOPRIGHT ).SetPosition( VECTOR2I( botRight.x, topLeft.y ) );
424 aPoints.Point( RECT_BOTLEFT ).SetPosition( VECTOR2I( topLeft.x, botRight.y ) );
425 aPoints.Point( RECT_BOTRIGHT ).SetPosition( botRight );
426 aPoints.Point( RECT_CENTER ).SetPosition( aRect.GetCenter() );
427 }
428
439 static void PinEditedCorner( const EDIT_POINT& aEditedPoint, const EDIT_POINTS& aPoints,
440 int minWidth, int minHeight, VECTOR2I& topLeft, VECTOR2I& topRight,
441 VECTOR2I& botLeft, VECTOR2I& botRight )
442 {
443 if( isModified( aEditedPoint, aPoints.Point( RECT_TOPLEFT ) ) )
444 {
445 // pin edited point within opposite corner
446 topLeft.x = std::min( topLeft.x, botRight.x - minWidth );
447 topLeft.y = std::min( topLeft.y, botRight.y - minHeight );
448
449 // push edited point edges to adjacent corners
450 topRight.y = topLeft.y;
451 botLeft.x = topLeft.x;
452 }
453 else if( isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) ) )
454 {
455 // pin edited point within opposite corner
456 topRight.x = std::max( topRight.x, botLeft.x + minWidth );
457 topRight.y = std::min( topRight.y, botLeft.y - minHeight );
458
459 // push edited point edges to adjacent corners
460 topLeft.y = topRight.y;
461 botRight.x = topRight.x;
462 }
463 else if( isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) ) )
464 {
465 // pin edited point within opposite corner
466 botLeft.x = std::min( botLeft.x, topRight.x - minWidth );
467 botLeft.y = std::max( botLeft.y, topRight.y + minHeight );
468
469 // push edited point edges to adjacent corners
470 botRight.y = botLeft.y;
471 topLeft.x = botLeft.x;
472 }
473 else if( isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) ) )
474 {
475 // pin edited point within opposite corner
476 botRight.x = std::max( botRight.x, topLeft.x + minWidth );
477 botRight.y = std::max( botRight.y, topLeft.y + minHeight );
478
479 // push edited point edges to adjacent corners
480 botLeft.y = botRight.y;
481 topRight.x = botRight.x;
482 }
483 else if( isModified( aEditedPoint, aPoints.Line( RECT_TOP ) ) )
484 {
485 topLeft.y = std::min( topLeft.y, botRight.y - minHeight );
486 }
487 else if( isModified( aEditedPoint, aPoints.Line( RECT_LEFT ) ) )
488 {
489 topLeft.x = std::min( topLeft.x, botRight.x - minWidth );
490 }
491 else if( isModified( aEditedPoint, aPoints.Line( RECT_BOT ) ) )
492 {
493 botRight.y = std::max( botRight.y, topLeft.y + minHeight );
494 }
495 else if( isModified( aEditedPoint, aPoints.Line( RECT_RIGHT ) ) )
496 {
497 botRight.x = std::max( botRight.x, topLeft.x + minWidth );
498 }
499 }
500
501 static void UpdateItem( SCH_SHAPE& aRect, const EDIT_POINT& aEditedPoint,
502 EDIT_POINTS& aPoints, const VECTOR2I& aMinSize = { 0, 0 } )
503 {
504 VECTOR2I topLeft = aPoints.Point( RECT_TOPLEFT ).GetPosition();
505 VECTOR2I topRight = aPoints.Point( RECT_TOPRIGHT ).GetPosition();
506 VECTOR2I botLeft = aPoints.Point( RECT_BOTLEFT ).GetPosition();
507 VECTOR2I botRight = aPoints.Point( RECT_BOTRIGHT ).GetPosition();
508
509 int minWidth = std::max( schIUScale.MilsToIU( 1 ), aMinSize.x );
510 int minHeight = std::max( schIUScale.MilsToIU( 1 ), aMinSize.y );
511
512 PinEditedCorner( aEditedPoint, aPoints, minWidth, minHeight,
513 topLeft, topRight, botLeft, botRight );
514
515 if( isModified( aEditedPoint, aPoints.Point( RECT_TOPLEFT ) )
516 || isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) )
517 || isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) )
518 || isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) ) )
519 {
520 aRect.SetPosition( topLeft );
521 aRect.SetEnd( botRight );
522 }
523 else if( isModified( aEditedPoint, aPoints.Line( RECT_TOP ) ) )
524 {
525 aRect.SetStartY( topLeft.y );
526 }
527 else if( isModified( aEditedPoint, aPoints.Line( RECT_LEFT ) ) )
528 {
529 aRect.SetStartX( topLeft.x );
530 }
531 else if( isModified( aEditedPoint, aPoints.Line( RECT_BOT ) ) )
532 {
533 aRect.SetEndY( botRight.y );
534 }
535 else if( isModified( aEditedPoint, aPoints.Line( RECT_RIGHT ) ) )
536 {
537 aRect.SetEndX( botRight.x );
538 }
539
540 for( unsigned i = 0; i < aPoints.LinesSize(); ++i )
541 {
542 if( !isModified( aEditedPoint, aPoints.Line( i ) ) )
543 {
544 aPoints.Line( i ).SetConstraint( new EC_PERPLINE( aPoints.Line( i ) ) );
545 }
546 }
547 }
548
549 void MakePoints( EDIT_POINTS& aPoints ) override
550 {
551 m_rect.Normalize();
552 MakePoints( m_rect, aPoints );
553 }
554
555 bool UpdatePoints( EDIT_POINTS& aPoints ) override
556 {
557 m_rect.Normalize();
558 UpdatePoints( m_rect, aPoints );
559 return true;
560 }
561
562 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
563 std::vector<EDA_ITEM*>& aUpdatedItems ) override
564 {
565 VECTOR2I topLeft = aPoints.Point( RECT_TOPLEFT ).GetPosition();
566 VECTOR2I topRight = aPoints.Point( RECT_TOPRIGHT ).GetPosition();
567 VECTOR2I botLeft = aPoints.Point( RECT_BOTLEFT ).GetPosition();
568 VECTOR2I botRight = aPoints.Point( RECT_BOTRIGHT ).GetPosition();
569
570 PinEditedCorner( aEditedPoint, aPoints, schIUScale.MilsToIU( 1 ), schIUScale.MilsToIU( 1 ),
571 topLeft, topRight, botLeft, botRight );
572
573 const BOX2I oldBox = BOX2I::ByCorners( m_rect.GetStart(), m_rect.GetEnd() );
574 std::vector<SEG> oldSegs;
575 std::vector<VECTOR2I> moveVecs;
576
577 if( isModified( aEditedPoint, aPoints.Point( RECT_TOPLEFT ) )
578 || isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) )
579 || isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) )
580 || isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) ) )
581 {
582 // Corner drags don't update pins. Not only is it an escape hatch to avoid
583 // moving pins, it also avoids tricky problems when the pins "fall off"
584 // the ends of one of the two segments and get either left behind or
585 // "swept up" into the corner.
586 m_rect.SetPosition( topLeft );
587 m_rect.SetEnd( botRight );
588 }
589 else if( isModified( aEditedPoint, aPoints.Point( RECT_CENTER ) ) )
590 {
591 VECTOR2I moveVec = aPoints.Point( RECT_CENTER ).GetPosition() - oldBox.GetCenter();
592 m_rect.Move( moveVec );
593 }
594 else if( isModified( aEditedPoint, aPoints.Point( RECT_RADIUS ) ) )
595 {
596 int width = std::abs( botRight.x - topLeft.x );
597 int height = std::abs( botRight.y - topLeft.y );
598 int maxRadius = std::min( width, height ) / 2;
599 int x = aPoints.Point( RECT_RADIUS ).GetX();
600 x = std::clamp( x, botRight.x - maxRadius, botRight.x );
601 aPoints.Point( RECT_RADIUS ).SetPosition( VECTOR2I( x, topLeft.y ) );
602 m_rect.SetCornerRadius( botRight.x - x );
603 }
604 else if( isModified( aEditedPoint, aPoints.Line( RECT_TOP ) ) )
605 {
607 moveVecs.emplace_back( 0, topLeft.y - oldBox.GetTop() );
608 m_rect.SetStartY( topLeft.y );
609 }
610 else if( isModified( aEditedPoint, aPoints.Line( RECT_LEFT ) ) )
611 {
613 moveVecs.emplace_back( topLeft.x - oldBox.GetLeft(), 0 );
614 m_rect.SetStartX( topLeft.x );
615 }
616 else if( isModified( aEditedPoint, aPoints.Line( RECT_BOT ) ) )
617 {
619 moveVecs.emplace_back( 0, botRight.y - oldBox.GetBottom() );
620 m_rect.SetEndY( botRight.y );
621 }
622 else if( isModified( aEditedPoint, aPoints.Line( RECT_RIGHT ) ) )
623 {
625 moveVecs.emplace_back( botRight.x - oldBox.GetRight(), 0 );
626 m_rect.SetEndX( botRight.x );
627 }
628
629 dragPinsOnEdge( oldSegs, moveVecs, m_rect.GetUnit(), aCommit, aUpdatedItems );
630
631 for( unsigned i = 0; i < aPoints.LinesSize(); ++i )
632 {
633 if( !isModified( aEditedPoint, aPoints.Line( i ) ) )
634 {
635 aPoints.Line( i ).SetConstraint( new EC_PERPLINE( aPoints.Line( i ) ) );
636 }
637 }
638 }
639
640private:
641 void dragPinsOnEdge( const std::vector<SEG>& aOldEdges, const std::vector<VECTOR2I>& aMoveVecs,
642 int aEdgeUnit, COMMIT& aCommit, std::vector<EDA_ITEM*>& aUpdatedItems ) const
643 {
644 wxCHECK( aOldEdges.size() == aMoveVecs.size(), /* void */ );
645
646 // This only make sense in the symbol editor
647 if( !m_frame.IsType( FRAME_SCH_SYMBOL_EDITOR ) )
648 return;
649
651
652 // And only if the setting is enabled
653 if( !editor.GetSettings()->m_dragPinsAlongWithEdges )
654 return;
655
656 // Adjuting pins on a different unit to a unit-limited shape
657 // seems suspect.
658 wxCHECK( aEdgeUnit == 0 || aEdgeUnit == editor.GetUnit(), /* void */ );
659
660 /*
661 * Get a list of pins on a line segment
662 */
663 const auto getPinsOnSeg =
664 []( LIB_SYMBOL& aSymbol, int aUnit, const SEG& aSeg,
665 bool aIncludeEnds ) -> std::vector<SCH_PIN*>
666 {
667 std::vector<SCH_PIN*> pins;
668
669 for( SCH_PIN* pin : aSymbol.GetGraphicalPins( aUnit, 0 ) )
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 = getPinsOnSeg( *symbol, aEdgeUnit, aOldEdges[i], false );
694
695 for( SCH_PIN* pin : pins )
696 {
697 aCommit.Modify( pin, editor.GetScreen() );
698 aUpdatedItems.push_back( pin );
699
700 // Move the pin
701 pin->Move( aMoveVecs[i] );
702 }
703 }
704 }
705
706private:
709};
710
711
713{
714public:
716 m_textbox( aTextbox )
717 {}
718
719 void MakePoints( EDIT_POINTS& aPoints ) override
720 {
721 m_textbox.Normalize();
723 }
724
725 bool UpdatePoints( EDIT_POINTS& aPoints ) override
726 {
727 // point editor works only with rectangles having width and height > 0
728 // Some symbols can have rectangles with width or height < 0
729 // So normalize the size:
730 m_textbox.Normalize();
732 return true;
733 }
734
735 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
736 std::vector<EDA_ITEM*>& aUpdatedItems ) override
737 {
738 m_textbox.ClearBoundingBoxCache();
739 VECTOR2I minSize = m_textbox.GetMinSize();
740
742 m_textbox.ClearRenderCache();
743 }
744
745private:
747};
748
749
751{
752public:
754 m_sheet( aSheet ),
755 m_screen( aScreen )
756 {
757 m_noConnects = m_sheet.GetNoConnects();
758
759 // Find all wires connected to sheet pins and store their connections
760 for( SCH_SHEET_PIN* pin : m_sheet.GetPins() )
761 {
762 VECTOR2I pinPos = pin->GetPosition();
763
764 for( SCH_ITEM* item : m_screen.Items().Overlapping( SCH_LINE_T, pinPos ) )
765 {
766 SCH_LINE* line = static_cast<SCH_LINE*>( item );
767
768 if( !line->IsWire() && !line->IsBus() )
769 continue;
770
771 if( line->GetStartPoint() == pinPos )
772 m_connectedWires.push_back( { pin, line, STARTPOINT } );
773 else if( line->GetEndPoint() == pinPos )
774 m_connectedWires.push_back( { pin, line, ENDPOINT } );
775 }
776 }
777 }
778
779 void MakePoints( EDIT_POINTS& aPoints ) override
780 {
781 VECTOR2I topLeft = m_sheet.GetPosition();
782 VECTOR2I botRight = m_sheet.GetPosition() + m_sheet.GetSize();
783
784 aPoints.AddPoint( topLeft );
785 aPoints.AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
786 aPoints.AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
787 aPoints.AddPoint( botRight );
788
789 aPoints.AddLine( aPoints.Point( RECT_TOPLEFT ), aPoints.Point( RECT_TOPRIGHT ) );
790 aPoints.Line( RECT_TOP ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_TOP ) ) );
791 aPoints.AddLine( aPoints.Point( RECT_TOPRIGHT ), aPoints.Point( RECT_BOTRIGHT ) );
792 aPoints.Line( RECT_RIGHT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_RIGHT ) ) );
793 aPoints.AddLine( aPoints.Point( RECT_BOTRIGHT ), aPoints.Point( RECT_BOTLEFT ) );
794 aPoints.Line( RECT_BOT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_BOT ) ) );
795 aPoints.AddLine( aPoints.Point( RECT_BOTLEFT ), aPoints.Point( RECT_TOPLEFT ) );
796 aPoints.Line( RECT_LEFT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_LEFT ) ) );
797 }
798
799 bool UpdatePoints( EDIT_POINTS& aPoints ) override
800 {
801 VECTOR2I topLeft = m_sheet.GetPosition();
802 VECTOR2I botRight = m_sheet.GetPosition() + m_sheet.GetSize();
803
804 aPoints.Point( RECT_TOPLEFT ).SetPosition( topLeft );
805 aPoints.Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
806 aPoints.Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
807 aPoints.Point( RECT_BOTRIGHT ).SetPosition( botRight );
808 return true;
809 }
810
811 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
812 std::vector<EDA_ITEM*>& aUpdatedItems ) override
813 {
814 VECTOR2I topLeft = aPoints.Point( RECT_TOPLEFT ).GetPosition();
815 VECTOR2I topRight = aPoints.Point( RECT_TOPRIGHT ).GetPosition();
816 VECTOR2I botLeft = aPoints.Point( RECT_BOTLEFT ).GetPosition();
817 VECTOR2I botRight = aPoints.Point( RECT_BOTRIGHT ).GetPosition();
818 VECTOR2I sheetNewPos = m_sheet.GetPosition();
819 VECTOR2I sheetNewSize = m_sheet.GetSize();
820
821 bool editedTopRight = isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) );
822 bool editedBotLeft = isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) );
823 bool editedBotRight = isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) );
824
825 if( isModified( aEditedPoint, aPoints.Line( RECT_RIGHT ) ) )
826 editedTopRight = true;
827 else if( isModified( aEditedPoint, aPoints.Line( RECT_BOT ) ) )
828 editedBotLeft = true;
829
831 aEditedPoint, aPoints, m_sheet.GetMinWidth( editedTopRight || editedBotRight ),
832 m_sheet.GetMinHeight( editedBotLeft || editedBotRight ), topLeft, topRight, botLeft,
833 botRight );
834
835 if( isModified( aEditedPoint, aPoints.Point( RECT_TOPLEFT ) )
836 || isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) )
837 || isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) )
838 || isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) ) )
839 {
840 sheetNewPos = topLeft;
841 sheetNewSize = VECTOR2I( botRight.x - topLeft.x, botRight.y - topLeft.y );
842 }
843 else if( isModified( aEditedPoint, aPoints.Line( RECT_TOP ) ) )
844 {
845 sheetNewPos = VECTOR2I( m_sheet.GetPosition().x, topLeft.y );
846 sheetNewSize = VECTOR2I( m_sheet.GetSize().x, botRight.y - topLeft.y );
847 }
848 else if( isModified( aEditedPoint, aPoints.Line( RECT_LEFT ) ) )
849 {
850 sheetNewPos = VECTOR2I( topLeft.x, m_sheet.GetPosition().y );
851 sheetNewSize = VECTOR2I( botRight.x - topLeft.x, m_sheet.GetSize().y );
852 }
853 else if( isModified( aEditedPoint, aPoints.Line( RECT_BOT ) ) )
854 {
855 sheetNewSize = VECTOR2I( m_sheet.GetSize().x, botRight.y - topLeft.y );
856 }
857 else if( isModified( aEditedPoint, aPoints.Line( RECT_RIGHT ) ) )
858 {
859 sheetNewSize = VECTOR2I( botRight.x - topLeft.x, m_sheet.GetSize().y );
860 }
861
862 for( unsigned i = 0; i < aPoints.LinesSize(); ++i )
863 {
864 if( !isModified( aEditedPoint, aPoints.Line( i ) ) )
865 {
866 aPoints.Line( i ).SetConstraint( new EC_PERPLINE( aPoints.Line( i ) ) );
867 }
868 }
869
870 if( m_sheet.GetPosition() != sheetNewPos )
871 m_sheet.SetPositionIgnoringPins( sheetNewPos );
872
873 if( m_sheet.GetSize() != sheetNewSize )
874 m_sheet.Resize( sheetNewSize );
875
876 // Update no-connects to follow their sheet pins
877 for( auto& [sheetPin, noConnect] : m_noConnects )
878 {
879 if( noConnect->GetPosition() != sheetPin->GetTextPos() )
880 {
881 aCommit.Modify( noConnect, &m_screen );
882 noConnect->SetPosition( sheetPin->GetTextPos() );
883 aUpdatedItems.push_back( noConnect );
884 }
885 }
886
887 // Update connected wires to follow their sheet pins
888 for( auto& [pin, line, endpoint] : m_connectedWires )
889 {
890 VECTOR2I newPinPos = pin->GetPosition();
891 bool needsUpdate = false;
892
893 if( endpoint == STARTPOINT && line->GetStartPoint() != newPinPos )
894 needsUpdate = true;
895 else if( endpoint == ENDPOINT && line->GetEndPoint() != newPinPos )
896 needsUpdate = true;
897
898 if( needsUpdate )
899 {
900 aCommit.Modify( line, &m_screen );
901
902 if( endpoint == STARTPOINT )
903 line->SetStartPoint( newPinPos );
904 else
905 line->SetEndPoint( newPinPos );
906
907 aUpdatedItems.push_back( line );
908 }
909 }
910 }
911
912private:
915 std::map<SCH_SHEET_PIN*, SCH_NO_CONNECT*> m_noConnects;
916 std::vector<std::tuple<SCH_SHEET_PIN*, SCH_LINE*, int>> m_connectedWires;
917};
918
919
921{
922 m_editBehavior = nullptr;
923 m_editPoints = std::make_shared<EDIT_POINTS>( aItem );
924
925 if( !aItem )
926 return;
927
928 // Generate list of edit points based on the item type
929 switch( aItem->Type() )
930 {
931 case SCH_SHAPE_T:
932 {
933 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
934
935 switch( shape->GetShape() )
936 {
937 case SHAPE_T::ARC:
938 // EDA_ARC_POINT_EDIT_BEHAVIOR holds a reference to m_arcEditMode, so the
939 // persisted value must be synced from settings before the behavior is built.
940 if( m_isSymbolEditor )
941 {
942 if( SYMBOL_EDITOR_SETTINGS* cfg = m_frame->libeditconfig() )
943 m_arcEditMode = cfg->m_ArcEditMode;
944 }
945 else if( EESCHEMA_SETTINGS* cfg = m_frame->eeconfig() )
946 {
947 m_arcEditMode = cfg->m_Drawing.arc_edit_mode;
948 }
949
950 m_editBehavior = std::make_unique<EDA_ARC_POINT_EDIT_BEHAVIOR>(
951 *shape, m_arcEditMode, *getViewControls() );
952 break;
953 case SHAPE_T::CIRCLE:
954 m_editBehavior = std::make_unique<EDA_CIRCLE_POINT_EDIT_BEHAVIOR>( *shape );
955 break;
957 m_editBehavior = std::make_unique<RECTANGLE_POINT_EDIT_BEHAVIOR>( *shape, *m_frame );
958 break;
959 case SHAPE_T::POLY:
960 m_editBehavior = std::make_unique<EDA_POLYGON_POINT_EDIT_BEHAVIOR>( *shape );
961 break;
962 case SHAPE_T::BEZIER:
963 {
964 int maxError = schIUScale.mmToIU( ARC_LOW_DEF_MM );
965
966 if( SCHEMATIC* schematic = shape->Schematic() )
967 maxError = schematic->Settings().m_MaxError;
968
969 m_editBehavior = std::make_unique<EDA_BEZIER_POINT_EDIT_BEHAVIOR>( *shape, maxError );
970 break;
971 }
972 case SHAPE_T::ELLIPSE:
973 case SHAPE_T::ELLIPSE_ARC: m_editBehavior = std::make_unique<EDA_ELLIPSE_POINT_EDIT_BEHAVIOR>( *shape ); break;
974 default:
976 }
977
978 break;
979 }
980 case SCH_RULE_AREA_T:
981 {
982 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
983 // Implemented directly as a polygon
984 m_editBehavior = std::make_unique<EDA_POLYGON_POINT_EDIT_BEHAVIOR>( *shape );
985 break;
986 }
987 case SCH_TEXTBOX_T:
988 {
989 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( aItem );
990 m_editBehavior = std::make_unique<TEXTBOX_POINT_EDIT_BEHAVIOR>( *textbox );
991 break;
992 }
993 case SCH_TABLECELL_T:
994 {
995 SCH_TABLECELL* cell = static_cast<SCH_TABLECELL*>( aItem );
996 m_editBehavior = std::make_unique<SCH_TABLECELL_POINT_EDIT_BEHAVIOR>( *cell, *m_frame->GetScreen() );
997 break;
998 }
999 case SCH_SHEET_T:
1000 {
1001 SCH_SHEET& sheet = static_cast<SCH_SHEET&>( *aItem );
1002 m_editBehavior = std::make_unique<SHEET_POINT_EDIT_BEHAVIOR>( sheet, *m_frame->GetScreen() );
1003 break;
1004 }
1005 case SCH_BITMAP_T:
1006 {
1007 SCH_BITMAP& bitmap = static_cast<SCH_BITMAP&>( *aItem );
1008 m_editBehavior = std::make_unique<BITMAP_POINT_EDIT_BEHAVIOR>( bitmap );
1009 break;
1010 }
1011 case SCH_LINE_T:
1012 {
1013 SCH_LINE& line = static_cast<SCH_LINE&>( *aItem );
1014 m_editBehavior = std::make_unique<LINE_POINT_EDIT_BEHAVIOR>( line, *m_frame->GetScreen() );
1015 break;
1016 }
1017 default:
1018 {
1019 m_editPoints.reset();
1020 break;
1021 }
1022 }
1023
1024 // If we got a behavior, generate the points
1025 if( m_editBehavior )
1026 {
1027 wxCHECK( m_editPoints, /* void */ );
1028 m_editBehavior->MakePoints( *m_editPoints );
1029 }
1030}
1031
1032
1040
1041
1043{
1044 SCH_TOOL_BASE::Reset( aReason );
1045
1046 if( KIGFX::VIEW* view = getView() )
1047 {
1048 if( m_angleItem )
1049 view->Remove( m_angleItem.get() );
1050
1051 if( m_editPoints )
1052 view->Remove( m_editPoints.get() );
1053 }
1054
1055 m_angleItem.reset();
1056 m_editPoints.reset();
1057 m_editedPoint = nullptr;
1058}
1059
1060
1062{
1063 using S_C = SELECTION_CONDITIONS;
1064
1066
1067 const auto addCornerCondition = [&]( const SELECTION& aSelection ) -> bool
1068 {
1069 return SCH_POINT_EDITOR::addCornerCondition( aSelection );
1070 };
1071
1072 const auto removeCornerCondition = [&]( const SELECTION& aSelection ) -> bool
1073 {
1074 return SCH_POINT_EDITOR::removeCornerCondition( aSelection );
1075 };
1076
1077 const auto arcIsEdited = [&]( const SELECTION& aSelection ) -> bool
1078 {
1079 const EDA_ITEM* item = aSelection.Front();
1080 return ( item != nullptr ) && ( item->Type() == SCH_SHAPE_T )
1081 && static_cast<const SCH_SHAPE*>( item )->GetShape() == SHAPE_T::ARC;
1082 };
1083
1084 auto& menu = m_selectionTool->GetToolMenu().GetMenu();
1085
1086 // clang-format off
1089 menu.AddItem( ACTIONS::cycleArcEditMode, S_C::Count( 1 ) && arcIsEdited );
1090 // clang-format on
1091
1092 return true;
1093}
1094
1095
1097{
1098 setEditedPoint( nullptr );
1099
1100 return 0;
1101}
1102
1103
1105{
1106 EDIT_POINT* point = m_editedPoint;
1107
1108 if( !m_editPoints )
1109 {
1110 point = nullptr;
1111 }
1112 else if( aEvent.IsMotion() )
1113 {
1114 point = m_editPoints->FindPoint( aEvent.Position(), getView() );
1115 }
1116 else if( aEvent.IsDrag( BUT_LEFT ) )
1117 {
1118 point = m_editPoints->FindPoint( aEvent.DragOrigin(), getView() );
1119 }
1120 else
1121 {
1122 point = m_editPoints->FindPoint( getViewControls()->GetCursorPosition( false ), getView() );
1123 }
1124
1125 if( m_editedPoint != point )
1126 setEditedPoint( point );
1127}
1128
1129
1131{
1132 if( !m_selectionTool )
1133 return 0;
1134
1135 if( m_inPointEditor )
1136 return 0;
1137
1139
1140 if( m_isSymbolEditor )
1141 {
1143
1144 if( !editor->IsSymbolEditable() || editor->IsSymbolAlias() )
1145 return 0;
1146 }
1147
1148 const SCH_SELECTION& selection = m_selectionTool->GetSelection();
1149
1150 if( selection.Size() != 1 || !selection.Front()->IsType( pointEditorTypes ) )
1151 return 0;
1152
1153 // Wait till drawing tool is done
1154 if( selection.Front()->IsNew() )
1155 return 0;
1156
1157 Activate();
1158
1161 VECTOR2I cursorPos;
1162 KIGFX::VIEW* view = getView();
1163 EDA_ITEM* item = selection.Front();
1164 SCH_COMMIT commit( m_toolMgr );
1165
1166 controls->ShowCursor( true );
1167
1168 makePointsAndBehavior( item );
1169 m_angleItem = std::make_unique<KIGFX::PREVIEW::ANGLE_ITEM>( m_editPoints );
1170 view->Add( m_editPoints.get() );
1171 view->Add( m_angleItem.get() );
1172 setEditedPoint( nullptr );
1173 updateEditedPoint( aEvent );
1174 bool inDrag = false;
1175
1176 // Main loop: keep receiving events
1177 while( TOOL_EVENT* evt = Wait() )
1178 {
1179 if( grid )
1180 {
1181 grid->SetSnap( !evt->Modifier( MD_SHIFT ) );
1182 grid->SetUseGrid( getView()->GetGAL()->GetGridSnapping()
1183 && !evt->DisableGridSnapping() );
1184 }
1185 else
1186 {
1187 // This check is based on the assumption that the grid object must be valid.
1188 // If this assumption is wrong, please fix the code above.
1189 wxCHECK( false, 0 );
1190 }
1191
1192 if( !m_editPoints || evt->IsSelectionEvent() )
1193 break;
1194
1195 if ( !inDrag )
1196 updateEditedPoint( *evt );
1197
1198 if( evt->IsDrag( BUT_LEFT ) && m_editedPoint )
1199 {
1200 if( !inDrag )
1201 {
1202 commit.Modify( m_editPoints->GetParent(), m_frame->GetScreen() );
1203
1204 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( item ) )
1205 {
1206 shape->SetFlags( IS_MOVING );
1207 shape->SetHatchingDirty();
1208 shape->UpdateHatching();
1209 }
1210
1211 inDrag = true;
1212 }
1213
1214 bool snap = !evt->DisableGridSnapping();
1215
1216 cursorPos = grid->Align( controls->GetMousePosition(),
1218 controls->ForceCursorPosition( true, cursorPos );
1219
1220 m_editedPoint->SetPosition( controls->GetCursorPosition( snap ) );
1221
1222 updateParentItem( snap, commit );
1223 updatePoints();
1224 }
1225 else if( inDrag && evt->IsMouseUp( BUT_LEFT ) )
1226 {
1227 if( !commit.Empty() )
1228 commit.Push( _( "Move Point" ) );
1229
1230 controls->SetAutoPan( false );
1231
1232 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( item ) )
1233 {
1234 shape->ClearFlags( IS_MOVING );
1235 shape->SetHatchingDirty();
1236 shape->UpdateHatching();
1237 }
1238
1239 inDrag = false;
1240 }
1241 else if( evt->IsCancelInteractive() || evt->IsActivate() )
1242 {
1243 if( inDrag ) // Restore the last change
1244 {
1245 // Currently we are manually managing the lifetime of the grid
1246 // helpers because there is a bug in the tool stack that adds
1247 // the point editor again when commit.Revert() rebuilds the selection.
1248 // We remove this grid here so the its destructor is called before it
1249 // is added again.
1250 if( grid )
1251 {
1252 delete grid;
1253 grid = nullptr;
1254 }
1255
1256 commit.Revert();
1257 inDrag = false;
1258 break;
1259 }
1260 else if( evt->IsCancelInteractive() )
1261 {
1262 break;
1263 }
1264
1265 if( evt->IsActivate() )
1266 break;
1267 }
1268 else
1269 {
1270 evt->SetPassEvent();
1271 }
1272
1273 controls->SetAutoPan( inDrag );
1274 controls->CaptureCursor( inDrag );
1275 }
1276
1277 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( item ) )
1278 {
1279 shape->ClearFlags( IS_MOVING );
1280 shape->SetHatchingDirty();
1281 shape->UpdateHatching();
1282 }
1283
1284 controls->SetAutoPan( false );
1285 controls->CaptureCursor( false );
1286 setEditedPoint( nullptr );
1287
1288 if( m_editPoints )
1289 {
1290 view->Remove( m_editPoints.get() );
1291 view->Remove( m_angleItem.get() );
1292
1293 m_editPoints.reset();
1294 m_angleItem.reset();
1295 m_frame->GetCanvas()->Refresh();
1296 }
1297
1298 delete grid;
1299
1300 return 0;
1301}
1302
1303
1304void SCH_POINT_EDITOR::updateParentItem( bool aSnapToGrid, SCH_COMMIT& aCommit ) const
1305{
1306 EDA_ITEM* item = m_editPoints->GetParent();
1307
1308 if( !item )
1309 return;
1310
1311 if( !m_editBehavior )
1312 return;
1313
1314 std::vector<EDA_ITEM*> updatedItems;
1315 m_editBehavior->UpdateItem( *m_editedPoint, *m_editPoints, aCommit, updatedItems );
1316
1317 for( EDA_ITEM* updatedItem : updatedItems )
1318 updateItem( updatedItem, true );
1319
1320 m_frame->SetMsgPanel( item );
1321}
1322
1323
1325{
1326 if( !m_editPoints || !m_editBehavior )
1327 return;
1328
1329 // Careful; the unit and/or body style may have changed out from under us, meaning the item is no
1330 // longer present on the canvas.
1331 if( m_isSymbolEditor )
1332 {
1334 SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( m_editPoints->GetParent() );
1335
1336 if( ( item && item->GetUnit() != 0 && item->GetUnit() != editor->GetUnit() )
1337 || ( item && item->GetBodyStyle() != 0 && item->GetBodyStyle() != editor->GetBodyStyle() ) )
1338 {
1339 getView()->Remove( m_editPoints.get() );
1340 getView()->Remove( m_angleItem.get() );
1341 m_editPoints.reset();
1342 m_angleItem.reset();
1343 return;
1344 }
1345 }
1346
1347 m_editBehavior->UpdatePoints( *m_editPoints );
1348 getView()->Update( m_editPoints.get() );
1349 getView()->Update( m_angleItem.get() );
1350}
1351
1352
1354{
1356
1357 if( aPoint )
1358 {
1359 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1360 controls->ForceCursorPosition( true, aPoint->GetPosition() );
1361 controls->ShowCursor( true );
1362 }
1363 else
1364 {
1365 if( m_frame->ToolStackIsEmpty() )
1366 controls->ShowCursor( false );
1367
1368 controls->ForceCursorPosition( false );
1369 }
1370
1371 m_editedPoint = aPoint;
1372}
1373
1374
1376{
1377 if( !m_editPoints || !m_editedPoint || !m_editPoints->GetParent()->IsType( { SCH_SHAPE_T, SCH_RULE_AREA_T } ) )
1378 return false;
1379
1380 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1381
1382 if( shape->GetPolyShape().IsEmpty() )
1383 return false;
1384
1385 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1386
1387 if( m_editPoints->GetParent()->Type() == SCH_SHAPE_T && poly.GetPointCount() <= 2 )
1388 return false;
1389 if( m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T && poly.GetPointCount() <= 3 )
1390 return false;
1391
1392 for( const VECTOR2I& pt : poly.CPoints() )
1393 {
1394 if( pt == m_editedPoint->GetPosition() )
1395 return true;
1396 }
1397
1398 return false;
1399}
1400
1401
1403{
1404 if( !m_editPoints || !m_editPoints->GetParent()->IsType( { SCH_SHAPE_T, SCH_RULE_AREA_T } ) )
1405 return false;
1406
1407 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1408
1409 if( shape->GetShape() != SHAPE_T::POLY )
1410 return false;
1411
1412 VECTOR2I cursorPos = getViewControls()->GetCursorPosition( false );
1413 double threshold = getView()->ToWorld( EDIT_POINT::POINT_SIZE );
1414
1415 return shape->HitTest( cursorPos, (int) threshold );
1416}
1417
1418
1420{
1421 if( !m_editPoints || !m_editPoints->GetParent()->IsType( { SCH_SHAPE_T, SCH_RULE_AREA_T } ) )
1422 return 0;
1423
1424 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1425 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1426 SCH_COMMIT commit( m_toolMgr );
1427
1428 commit.Modify( shape, m_frame->GetScreen() );
1429
1431 int currentMinDistance = INT_MAX;
1432 int closestLineStart = 0;
1433 unsigned numPoints = poly.GetPointCount();
1434
1435 if( !shape->IsClosed() )
1436 numPoints -= 1;
1437
1438 for( unsigned i = 0; i < numPoints; ++i )
1439 {
1440 SEG seg = poly.GetSegment( i );
1441 int distance = seg.Distance( cursor );
1442
1443 if( distance < currentMinDistance )
1444 {
1445 currentMinDistance = distance;
1446 closestLineStart = i;
1447 }
1448 }
1449
1450 poly.Insert( closestLineStart + 1, cursor );
1451
1452 updateItem( shape, true );
1453 updatePoints();
1454
1455 commit.Push( _( "Add Corner" ) );
1456 return 0;
1457}
1458
1459
1461{
1462 if( !m_editPoints || !m_editedPoint || !m_editPoints->GetParent()->IsType( { SCH_SHAPE_T, SCH_RULE_AREA_T } ) )
1463 return 0;
1464
1465 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1466 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1467 SCH_COMMIT commit( m_toolMgr );
1468
1469 if( m_editPoints->GetParent()->Type() == SCH_SHAPE_T && poly.GetPointCount() <= 2 )
1470 return 0;
1471 if( m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T && poly.GetPointCount() <= 3 )
1472 return 0;
1473
1474 commit.Modify( shape, m_frame->GetScreen() );
1475
1476 int idx = getEditedPointIndex();
1477 int last = (int) poly.GetPointCount() - 1;
1478
1479 if( idx == 0 && poly.GetPoint( 0 ) == poly.GetPoint( last ) )
1480 {
1481 poly.Remove( idx );
1482 poly.SetPoint( last-1, poly.GetPoint( 0 ) );
1483 }
1484 else
1485 {
1486 poly.Remove( idx );
1487 }
1488
1489 shape->SetHatchingDirty();
1490
1491 setEditedPoint( nullptr );
1492
1493 updateItem( shape, true );
1494 updatePoints();
1495
1496 commit.Push( _( "Remove Corner" ) );
1497 return 0;
1498}
1499
1500
1502{
1503 // The Symbol Editor uses SYMBOL_EDITOR_SETTINGS, not EESCHEMA_SETTINGS, so eeconfig()
1504 // returns nullptr there. Dispatch on frame type to read/write the right settings store.
1505 EESCHEMA_SETTINGS* schCfg = m_isSymbolEditor ? nullptr : m_frame->eeconfig();
1506 SYMBOL_EDITOR_SETTINGS* symCfg = m_isSymbolEditor ? m_frame->libeditconfig() : nullptr;
1507
1508 if( aEvent.Matches( ACTIONS::cycleArcEditMode.MakeEvent() ) )
1509 {
1510 if( schCfg )
1512 else if( symCfg )
1513 m_arcEditMode = symCfg->m_ArcEditMode;
1514
1516 }
1517 else
1518 {
1520 }
1521
1522 if( schCfg )
1524 else if( symCfg )
1525 symCfg->m_ArcEditMode = m_arcEditMode;
1526
1527 return 0;
1528}
1529
1530
1532{
1533 updatePoints();
1534 return 0;
1535}
1536
1537
ARC_EDIT_MODE
Settings for arc editing.
@ KEEP_CENTER_ADJUST_ANGLE_RADIUS
When editing endpoints, the angle and radius are adjusted.
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:127
constexpr double ARC_LOW_DEF_MM
Definition base_units.h:131
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
static TOOL_ACTION cycleArcEditMode
Definition actions.h:272
static TOOL_ACTION pointEditorArcKeepCenter
Definition actions.h:273
static TOOL_ACTION pointEditorArcKeepRadius
Definition actions.h:275
static TOOL_ACTION activatePointEditor
Definition actions.h:271
static TOOL_ACTION pointEditorArcKeepEndpoint
Definition actions.h:274
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.
bool UpdatePoints(EDIT_POINTS &aPoints) override
Update the list of the edit points for the item.
BITMAP_POINT_EDIT_BEHAVIOR(SCH_BITMAP &aBitmap)
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:72
bool Empty() const
Definition commit.h:137
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:106
EDIT_CONSTRAINT for a EDIT_LINE, that constrains the line to move perpendicular to the line itself.
The base class for create windows for drawing purpose.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:100
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:112
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition eda_item.h:199
bool IsNew() const
Definition eda_item.h:126
void SetStartX(int x)
Definition eda_shape.h:212
void SetEndY(int aY)
Definition eda_shape.h:247
void SetStartY(int y)
Definition eda_shape.h:205
SHAPE_POLY_SET & GetPolyShape()
SHAPE_T GetShape() const
Definition eda_shape.h:189
void SetEndX(int aX)
Definition eda_shape.h:254
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:236
bool IsClosed() const
void SetEnd(const VECTOR2I &aEnd)
Definition eda_shape.h:240
wxString SHAPE_T_asString() const
void SetHatchingDirty()
Definition eda_shape.h:167
int GetCornerRadius() const
void SetConstraint(EDIT_CONSTRAINT< EDIT_LINE > *aConstraint)
Set a constraint for and EDIT_POINT.
EDIT_POINTS is a VIEW_ITEM that manages EDIT_POINTs and EDIT_LINEs and draws them.
void AddPoint(const EDIT_POINT &aPoint)
Add an EDIT_POINT.
EDIT_LINE & Line(unsigned int aIndex)
unsigned int LinesSize() const
Return number of stored EDIT_LINEs.
EDIT_POINT & Point(unsigned int aIndex)
void AddLine(const EDIT_LINE &aLine)
Adds an EDIT_LINE.
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:80
int GetY() const
Return Y coordinate of an EDIT_POINT.
Definition edit_points.h:96
static const int POINT_SIZE
Single point size in pixels.
virtual void SetPosition(const VECTOR2I &aPosition)
Set new coordinates for an EDIT_POINT.
virtual VECTOR2I GetPosition() const
Return coordinates of an EDIT_POINT.
Definition edit_points.h:72
int GetX() const
Return X coordinate of an EDIT_POINT.
Definition edit_points.h:88
void SetDrawCircle(bool aDrawCircle=true)
static const TOOL_EVENT ClearedEvent
Definition actions.h:347
static const TOOL_EVENT SelectedEvent
Definition actions.h:345
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition actions.h:352
static const TOOL_EVENT PointSelectedEvent
Definition actions.h:344
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:67
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition view.cpp:304
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition view.cpp:408
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:1828
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:538
Define a library symbol object.
Definition lib_symbol.h:83
std::vector< const SCH_PIN * > GetGraphicalPins(int aUnit=0, int aBodyStyle=0) const
Graphical pins: Return schematic pin objects as drawn (unexpanded), filtered by unit/body.
bool 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, const VECTOR2I &aMinSize={ 0, 0 })
bool UpdatePoints(EDIT_POINTS &aPoints) override
Update the list of the edit points for the item.
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
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.
Holds all the data relating to one schematic.
Definition schematic.h:89
static TOOL_ACTION pointEditorAddCorner
static TOOL_ACTION pointEditorRemoveCorner
A shim class between EDA_DRAW_FRAME and several derived classes: SYMBOL_EDIT_FRAME,...
Object to handle a bitmap image that can be inserted in a schematic.
Definition sch_bitmap.h:40
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Execute the changes.
virtual void Revert() override
Revert the commit by restoring the modified items state.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:168
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:272
int GetBodyStyle() const
Definition sch_item.h:248
int GetUnit() const
Definition sch_item.h:239
Segment description base class to describe items which have 2 end points (track, wire,...
Definition sch_line.h:42
VECTOR2I GetEndPoint() const
Definition sch_line.h:148
VECTOR2I GetStartPoint() const
Definition sch_line.h:139
void updatePoints()
Update which point is being edited.
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
void setEditedPoint(EDIT_POINT *aPoint)
Return true if aPoint is the currently modified point.
bool Init() override
Init() is called once upon a registration of the tool.
ARC_EDIT_MODE m_arcEditMode
Re-entrancy guards.
void updateParentItem(bool aSnapToGrid, SCH_COMMIT &aCommit) const
< Update item's points with edit points.
void updateEditedPoint(const TOOL_EVENT &aEvent)
Clear references to the points.
bool addCornerCondition(const SELECTION &aSelection)
std::unique_ptr< POINT_EDIT_BEHAVIOR > m_editBehavior
EDIT_POINT * m_editedPoint
int modifiedSelection(const TOOL_EVENT &aEvent)
int Main(const TOOL_EVENT &aEvent)
int getEditedPointIndex() const
std::shared_ptr< EDIT_POINTS > m_editPoints
int clearEditedPoints(const TOOL_EVENT &aEvent)
Set the current point being edited. NULL means none.
bool removeCornerCondition(const SELECTION &aSelection)
bool m_inPointEditor
Currently available edit points.
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
void makePointsAndBehavior(EDA_ITEM *aItem)
Currently edited point, NULL if there is none.
std::unique_ptr< KIGFX::PREVIEW::ANGLE_ITEM > m_angleItem
Current item-specific edit behavior.
int changeArcEditMode(const TOOL_EVENT &aEvent)
int removeCorner(const TOOL_EVENT &aEvent)
int addCorner(const TOOL_EVENT &aEvent)
TOOL_ACTION handlers.
void SetPosition(const VECTOR2I &aPos) override
Definition sch_shape.h:89
VECTOR2I GetCenter() const
Definition sch_shape.h:96
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
VECTOR2I GetPosition() const override
Definition sch_shape.h:88
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
SCH_TABLECELL_POINT_EDIT_BEHAVIOR(SCH_TABLECELL &aCell, SCH_SCREEN &aScreen)
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 updateItem(EDA_ITEM *aItem, bool aUpdateRTree) const
bool Init() override
Init() is called once upon a registration of the tool.
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
SCH_TOOL_BASE(const std::string &aName)
SCH_SELECTION_TOOL * m_selectionTool
Definition seg.h:42
int Distance(const SEG &aSeg) const
Compute minimum Euclidean distance to segment aSeg.
Definition seg.cpp:702
Class that groups generic conditions for selected items.
static SELECTION_CONDITION Count(int aNumber)
Create a functor that tests if the number of selected items is equal to the value given as parameter.
EDA_ITEM * Front() const
Definition selection.h:177
int Size() const
Returns the number of selected parts.
Definition selection.h:121
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.
SHEET_POINT_EDIT_BEHAVIOR(SCH_SHEET &aSheet, SCH_SCREEN &aScreen)
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.
std::vector< std::tuple< SCH_SHEET_PIN *, SCH_LINE *, int > > m_connectedWires
std::map< SCH_SHEET_PIN *, SCH_NO_CONNECT * > m_noConnects
bool UpdatePoints(EDIT_POINTS &aPoints) override
Update the list of the edit points for the item.
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.
void MakePoints(EDIT_POINTS &aPoints) override
Construct the initial set of edit points for the item and append to the given list.
bool 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.
TEXTBOX_POINT_EDIT_BEHAVIOR(SCH_TEXTBOX &aTextbox)
SCH_BASE_FRAME * getEditFrame() const
Definition tool_base.h:186
KIGFX::VIEW_CONTROLS * getViewControls() const
Definition tool_base.cpp:44
KIGFX::VIEW * getView() const
Definition tool_base.cpp:38
Generic, UI-independent tool event.
Definition tool_event.h:171
bool DisableGridSnapping() const
Definition tool_event.h:371
bool Matches(const TOOL_EVENT &aEvent) const
Test whether two events match in terms of category & action or command.
Definition tool_event.h:392
const VECTOR2D Position() const
Return mouse cursor position in world coordinates.
Definition tool_event.h:293
bool IsDrag(int aButtonMask=BUT_ANY) const
Definition tool_event.h:315
const VECTOR2D DragOrigin() const
Return the point where dragging has started.
Definition tool_event.h:299
T Parameter() const
Return a parameter assigned to the event.
Definition tool_event.h:473
bool IsMotion() const
Definition tool_event.h:330
void Go(int(SCH_BASE_FRAME::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition vector2d.h:283
@ ARROW
Definition cursors.h:46
const int minSize
Push and Shove router track width and via size dialog.
#define _(s)
#define ENDPOINT
ends. (Used to support dragging.)
#define IS_MOVING
Item being moved.
#define STARTPOINT
When a line is selected, these flags indicate which.
@ ELLIPSE
Definition eda_shape.h:56
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:51
@ ELLIPSE_ARC
Definition eda_shape.h:57
@ FRAME_SCH_SYMBOL_EDITOR
Definition frame_type.h:35
@ GRID_GRAPHICS
Definition grid_helper.h:52
@ LAYER_NOTES
Definition layer_ids.h:469
#define UNIMPLEMENTED_FOR(type)
Definition macros.h:96
constexpr int Mils2IU(const EDA_IU_SCALE &aIuScale, int mils)
Definition eda_units.h:175
std::vector< SEG > GetSegsInDirection(const BOX2I &aBox, DIRECTION_45::Directions aDir)
Get the segments of a box that are in the given direction.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:400
@ RECT_RIGHT
@ RECT_LEFT
@ RECT_CENTER
@ RECT_RADIUS
ARC_EDIT_MODE IncrementArcEditMode(ARC_EDIT_MODE aMode)
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
SCH_CONDITIONS S_C
RECTANGLE_POINTS
@ RECT_BOTLEFT
@ RECT_TOPLEFT
@ RECT_TOPRIGHT
@ RECT_CENTER
@ RECT_BOTRIGHT
@ RECT_RADIUS
RECTANGLE_LINES
@ RECT_RIGHT
@ RECT_LEFT
@ RECT_BOT
@ RECT_TOP
TABLECELL_POINTS
@ ROW_HEIGHT
@ COL_WIDTH
static const std::vector< KICAD_T > pointEditorTypes
@ LINE_START
@ LINE_END
REFIMAGE_POINTS
@ REFIMG_ORIGIN
@ ARC_START
@ ARC_END
@ ARC_CENTER
std::optional< VECTOR2I > OPT_VECTOR2I
Definition seg.h:39
Utility functions for working with shapes.
KIBIS_PIN * pin
std::vector< std::vector< std::string > > table
@ MD_SHIFT
Definition tool_event.h:143
@ BUT_LEFT
Definition tool_event.h:132
@ SCH_LINE_T
Definition typeinfo.h:164
@ SCH_TABLECELL_T
Definition typeinfo.h:167
@ SCH_SHEET_T
Definition typeinfo.h:176
@ SCH_SHAPE_T
Definition typeinfo.h:150
@ SCH_RULE_AREA_T
Definition typeinfo.h:171
@ SCH_ITEM_LOCATE_GRAPHIC_LINE_T
Definition typeinfo.h:189
@ SCH_BITMAP_T
Definition typeinfo.h:165
@ SCH_TEXTBOX_T
Definition typeinfo.h:153
constexpr int sign(T val)
Definition util.h:145
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687