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, see <https://www.gnu.org/licenses/>.
19 */
20
21#include "sch_point_editor.h"
22
23#include <algorithm>
24#include <ee_grid_helper.h>
25#include <tool/tool_manager.h>
26#include <sch_commit.h>
27#include <view/view_controls.h>
29#include <geometry/seg.h>
33#include <tools/sch_actions.h>
35#include <sch_edit_frame.h>
36#include <sch_line.h>
37#include <sch_bitmap.h>
38#include <sch_sheet.h>
39#include <sch_textbox.h>
40#include <sch_table.h>
41#include <sch_sheet_pin.h>
43#include <sch_no_connect.h>
44
45
53
54
55// Few constants to avoid using bare numbers for point indices
60
61
66
67
72
73
78
79
84
89
90
92{
93public:
95 m_line( aLine ),
96 m_screen( aScreen )
97 {
98 }
99
100 void MakePoints( EDIT_POINTS& aPoints ) override
101 {
102 std::pair<EDA_ITEM*, int> connectedStart = { nullptr, STARTPOINT };
103 std::pair<EDA_ITEM*, int> connectedEnd = { nullptr, STARTPOINT };
104
105 for( SCH_ITEM* test : m_screen.Items().OfType( SCH_LINE_T ) )
106 {
107 if( test->GetLayer() != LAYER_NOTES )
108 continue;
109
110 if( test == &m_line )
111 continue;
112
113 SCH_LINE* testLine = static_cast<SCH_LINE*>( test );
114
115 if( testLine->GetStartPoint() == m_line.GetStartPoint() )
116 {
117 connectedStart = { testLine, STARTPOINT };
118 }
119 else if( testLine->GetEndPoint() == m_line.GetStartPoint() )
120 {
121 connectedStart = { testLine, ENDPOINT };
122 }
123 else if( testLine->GetStartPoint() == m_line.GetEndPoint() )
124 {
125 connectedEnd = { testLine, STARTPOINT };
126 }
127 else if( testLine->GetEndPoint() == m_line.GetEndPoint() )
128 {
129 connectedEnd = { testLine, ENDPOINT };
130 }
131 }
132
133 aPoints.AddPoint( m_line.GetStartPoint(), connectedStart );
134 aPoints.AddPoint( m_line.GetEndPoint(), connectedEnd );
135 }
136
137 bool UpdatePoints( EDIT_POINTS& aPoints ) override
138 {
139 aPoints.Point( LINE_START ).SetPosition( m_line.GetStartPoint() );
140 aPoints.Point( LINE_END ).SetPosition( m_line.GetEndPoint() );
141 return true;
142 }
143
144 void UpdateItem( const EDIT_POINT& aEditedPoints, EDIT_POINTS& aPoints, COMMIT& aCommit,
145 std::vector<EDA_ITEM*>& aUpdatedItems ) override
146 {
147 m_line.SetStartPoint( aPoints.Point( LINE_START ).GetPosition() );
148 m_line.SetEndPoint( aPoints.Point( LINE_END ).GetPosition() );
149
150 std::pair<EDA_ITEM*, int> connected = aPoints.Point( LINE_START ).GetConnected();
151
152 if( connected.first )
153 {
154 aCommit.Modify( connected.first, &m_screen );
155 aUpdatedItems.push_back( connected.first );
156
157 if( connected.second == STARTPOINT )
158 static_cast<SCH_LINE*>( connected.first )->SetStartPoint( m_line.GetStartPoint() );
159 else if( connected.second == ENDPOINT )
160 static_cast<SCH_LINE*>( connected.first )->SetEndPoint( m_line.GetStartPoint() );
161 }
162
163 connected = aPoints.Point( LINE_END ).GetConnected();
164
165 if( connected.first )
166 {
167 aCommit.Modify( connected.first, &m_screen );
168 aUpdatedItems.push_back( connected.first );
169
170 if( connected.second == STARTPOINT )
171 static_cast<SCH_LINE*>( connected.first )->SetStartPoint( m_line.GetEndPoint() );
172 else if( connected.second == ENDPOINT )
173 static_cast<SCH_LINE*>( connected.first )->SetEndPoint( m_line.GetEndPoint() );
174 }
175 }
176
177private:
180};
181
183{
184public:
186 m_bitmap( aBitmap )
187 {}
188
189 void MakePoints( EDIT_POINTS& aPoints ) override
190 {
191 const REFERENCE_IMAGE& refImage = m_bitmap.GetReferenceImage();
192 const VECTOR2I topLeft = refImage.GetPosition() - refImage.GetSize() / 2;
193 const VECTOR2I botRight = refImage.GetPosition() + refImage.GetSize() / 2;
194
195 aPoints.AddPoint( topLeft );
196 aPoints.AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
197 aPoints.AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
198 aPoints.AddPoint( botRight );
199
200 aPoints.AddPoint( refImage.GetPosition() + refImage.GetTransformOriginOffset() );
201 }
202
203 bool UpdatePoints( EDIT_POINTS& aPoints ) override
204 {
205 const REFERENCE_IMAGE& refImage = m_bitmap.GetReferenceImage();
206 const VECTOR2I topLeft = refImage.GetPosition() - refImage.GetSize() / 2;
207 const VECTOR2I botRight = refImage.GetPosition() + refImage.GetSize() / 2;
208
209 aPoints.Point( RECT_TOPLEFT ).SetPosition( topLeft );
210 aPoints.Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
211 aPoints.Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
212 aPoints.Point( RECT_BOTRIGHT ).SetPosition( botRight );
213
214 aPoints.Point( REFIMG_ORIGIN ).SetPosition( refImage.GetPosition() + refImage.GetTransformOriginOffset() );
215 return true;
216 }
217
218 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
219 std::vector<EDA_ITEM*>& aUpdatedItems ) override
220 {
221 REFERENCE_IMAGE& refImg = m_bitmap.GetReferenceImage();
222 const VECTOR2I topLeft = aPoints.Point( RECT_TOPLEFT ).GetPosition();
223 const VECTOR2I topRight = aPoints.Point( RECT_TOPRIGHT ).GetPosition();
224 const VECTOR2I botLeft = aPoints.Point( RECT_BOTLEFT ).GetPosition();
225 const VECTOR2I botRight = aPoints.Point( RECT_BOTRIGHT ).GetPosition();
226 const VECTOR2I xfrmOrigin = aPoints.Point( REFIMG_ORIGIN ).GetPosition();
227
228 if( isModified( aEditedPoint, aPoints.Point( REFIMG_ORIGIN ) ) )
229 {
230 // Moving the transform origin
231 // As the other points didn't move, we can get the image extent from them
232 const VECTOR2I newOffset = xfrmOrigin - ( topLeft + botRight ) / 2;
233 refImg.SetTransformOriginOffset( newOffset );
234 }
235 else
236 {
237 const VECTOR2I oldOrigin = refImg.GetPosition() + refImg.GetTransformOriginOffset();
238 const VECTOR2I oldSize = refImg.GetSize();
239 const VECTOR2I pos = refImg.GetPosition();
240
241 OPT_VECTOR2I newCorner;
242 VECTOR2I oldCorner = pos;
243
244 if( isModified( aEditedPoint, aPoints.Point( RECT_TOPLEFT ) ) )
245 {
246 newCorner = topLeft;
247 oldCorner -= oldSize / 2;
248 }
249 else if( isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) ) )
250 {
251 newCorner = topRight;
252 oldCorner -= VECTOR2I( -oldSize.x, oldSize.y ) / 2;
253 }
254 else if( isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) ) )
255 {
256 newCorner = botLeft;
257 oldCorner -= VECTOR2I( oldSize.x, -oldSize.y ) / 2;
258 }
259 else if( isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) ) )
260 {
261 newCorner = botRight;
262 oldCorner += oldSize / 2;
263 }
264
265 if( newCorner )
266 {
267 // Turn in the respective vectors from the origin
268 *newCorner -= xfrmOrigin;
269 oldCorner -= oldOrigin;
270
271 // If we tried to cross the origin, clamp it to stop it
272 if( sign( newCorner->x ) != sign( oldCorner.x )
273 || sign( newCorner->y ) != sign( oldCorner.y ) )
274 {
275 *newCorner = VECTOR2I( 0, 0 );
276 }
277
278 const double newLength = newCorner->EuclideanNorm();
279 const double oldLength = oldCorner.EuclideanNorm();
280
281 double ratio = oldLength > 0 ? ( newLength / oldLength ) : 1.0;
282
283 // Clamp the scaling to a minimum of 50 mils
284 VECTOR2I newSize = oldSize * ratio;
285 double newWidth = std::max( newSize.x, EDA_UNIT_UTILS::Mils2IU( schIUScale, 50 ) );
286 double newHeight = std::max( newSize.y, EDA_UNIT_UTILS::Mils2IU( schIUScale, 50 ) );
287 ratio = std::min( newWidth / oldSize.x, newHeight / oldSize.y );
288
289 // Also handles the origin offset
290 refImg.SetImageScale( refImg.GetImageScale() * ratio );
291 }
292 }
293 aUpdatedItems.push_back( &m_bitmap );
294 }
295
296private:
298};
299
300
302{
303public:
306 m_cell( aCell ),
307 m_screen( aScreen )
308 {
309 }
310
311 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
312 std::vector<EDA_ITEM*>& aUpdatedItems ) override
313 {
314 SCH_TABLE& table = static_cast<SCH_TABLE&>( *m_cell.GetParent() );
315 bool rotated = !m_cell.GetTextAngle().IsHorizontal();
316
317 aCommit.Modify( &table, &m_screen );
318 aUpdatedItems.push_back( &table );
319
320 if( rotated )
321 {
322 if( isModified( aEditedPoint, aPoints.Point( ROW_HEIGHT ) ) )
323 {
324 m_cell.SetEnd( VECTOR2I( m_cell.GetEndX(), aPoints.Point( ROW_HEIGHT ).GetY() ) );
325
326 int colWidth = std::abs( m_cell.GetRectangleHeight() );
327
328 for( int ii = 0; ii < m_cell.GetColSpan() - 1; ++ii )
329 colWidth -= table.GetColWidth( m_cell.GetColumn() + ii );
330
331 table.SetColWidth( m_cell.GetColumn() + m_cell.GetColSpan() - 1, colWidth );
332 }
333 else if( isModified( aEditedPoint, aPoints.Point( COL_WIDTH ) ) )
334 {
335 m_cell.SetEnd( VECTOR2I( aPoints.Point( COL_WIDTH ).GetX(), m_cell.GetEndY() ) );
336
337 int rowHeight = m_cell.GetRectangleWidth();
338
339 for( int ii = 0; ii < m_cell.GetRowSpan() - 1; ++ii )
340 rowHeight -= table.GetRowHeight( m_cell.GetRow() + ii );
341
342 table.SetRowHeight( m_cell.GetRow() + m_cell.GetRowSpan() - 1, rowHeight );
343 }
344 }
345 else
346 {
347 if( isModified( aEditedPoint, aPoints.Point( COL_WIDTH ) ) )
348 {
349 m_cell.SetEnd( VECTOR2I( aPoints.Point( COL_WIDTH ).GetX(), m_cell.GetEndY() ) );
350
351 int colWidth = m_cell.GetRectangleWidth();
352
353 for( int ii = 0; ii < m_cell.GetColSpan() - 1; ++ii )
354 colWidth -= table.GetColWidth( m_cell.GetColumn() + ii );
355
356 table.SetColWidth( m_cell.GetColumn() + m_cell.GetColSpan() - 1, colWidth );
357 }
358 else if( isModified( aEditedPoint, aPoints.Point( ROW_HEIGHT ) ) )
359 {
360 m_cell.SetEnd( VECTOR2I( m_cell.GetEndX(), aPoints.Point( ROW_HEIGHT ).GetY() ) );
361
362 int rowHeight = m_cell.GetRectangleHeight();
363
364 for( int ii = 0; ii < m_cell.GetRowSpan() - 1; ++ii )
365 rowHeight -= table.GetRowHeight( m_cell.GetRow() + ii );
366
367 table.SetRowHeight( m_cell.GetRow() + m_cell.GetRowSpan() - 1, rowHeight );
368 }
369 }
370
371 table.Normalize();
372 }
373
374private:
377};
378
379
381{
382public:
384 m_rect( aRect ),
385 m_frame( aFrame )
386 {
387 }
388
389 static void MakePoints( SCH_SHAPE& aRect, EDIT_POINTS& aPoints )
390 {
391 VECTOR2I topLeft = aRect.GetPosition();
392 VECTOR2I botRight = aRect.GetEnd();
393
394 aPoints.AddPoint( topLeft );
395 aPoints.AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
396 aPoints.AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
397 aPoints.AddPoint( botRight );
398 aPoints.AddPoint( aRect.GetCenter() );
399 aPoints.AddPoint( VECTOR2I( botRight.x - aRect.GetCornerRadius(), topLeft.y ) );
400 aPoints.Point( RECT_RADIUS ).SetDrawCircle();
401
402 aPoints.AddLine( aPoints.Point( RECT_TOPLEFT ), aPoints.Point( RECT_TOPRIGHT ) );
403 aPoints.Line( RECT_TOP ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_TOP ) ) );
404 aPoints.AddLine( aPoints.Point( RECT_TOPRIGHT ), aPoints.Point( RECT_BOTRIGHT ) );
405 aPoints.Line( RECT_RIGHT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_RIGHT ) ) );
406 aPoints.AddLine( aPoints.Point( RECT_BOTRIGHT ), aPoints.Point( RECT_BOTLEFT ) );
407 aPoints.Line( RECT_BOT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_BOT ) ) );
408 aPoints.AddLine( aPoints.Point( RECT_BOTLEFT ), aPoints.Point( RECT_TOPLEFT ) );
409 aPoints.Line( RECT_LEFT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_LEFT ) ) );
410 }
411
412 static void UpdatePoints( SCH_SHAPE& aRect, EDIT_POINTS& aPoints )
413 {
414 VECTOR2I topLeft = aRect.GetPosition();
415 VECTOR2I botRight = aRect.GetEnd();
416
417 aPoints.Point( RECT_TOPLEFT ).SetPosition( topLeft );
418 aPoints.Point( RECT_RADIUS ).SetPosition( VECTOR2I( botRight.x - aRect.GetCornerRadius(), topLeft.y ) );
419 aPoints.Point( RECT_TOPRIGHT ).SetPosition( VECTOR2I( botRight.x, topLeft.y ) );
420 aPoints.Point( RECT_BOTLEFT ).SetPosition( VECTOR2I( topLeft.x, botRight.y ) );
421 aPoints.Point( RECT_BOTRIGHT ).SetPosition( botRight );
422 aPoints.Point( RECT_CENTER ).SetPosition( aRect.GetCenter() );
423 }
424
435 static void PinEditedCorner( const EDIT_POINT& aEditedPoint, const EDIT_POINTS& aPoints,
436 int minWidth, int minHeight, VECTOR2I& topLeft, VECTOR2I& topRight,
437 VECTOR2I& botLeft, VECTOR2I& botRight )
438 {
439 if( isModified( aEditedPoint, aPoints.Point( RECT_TOPLEFT ) ) )
440 {
441 // pin edited point within opposite corner
442 topLeft.x = std::min( topLeft.x, botRight.x - minWidth );
443 topLeft.y = std::min( topLeft.y, botRight.y - minHeight );
444
445 // push edited point edges to adjacent corners
446 topRight.y = topLeft.y;
447 botLeft.x = topLeft.x;
448 }
449 else if( isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) ) )
450 {
451 // pin edited point within opposite corner
452 topRight.x = std::max( topRight.x, botLeft.x + minWidth );
453 topRight.y = std::min( topRight.y, botLeft.y - minHeight );
454
455 // push edited point edges to adjacent corners
456 topLeft.y = topRight.y;
457 botRight.x = topRight.x;
458 }
459 else if( isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) ) )
460 {
461 // pin edited point within opposite corner
462 botLeft.x = std::min( botLeft.x, topRight.x - minWidth );
463 botLeft.y = std::max( botLeft.y, topRight.y + minHeight );
464
465 // push edited point edges to adjacent corners
466 botRight.y = botLeft.y;
467 topLeft.x = botLeft.x;
468 }
469 else if( isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) ) )
470 {
471 // pin edited point within opposite corner
472 botRight.x = std::max( botRight.x, topLeft.x + minWidth );
473 botRight.y = std::max( botRight.y, topLeft.y + minHeight );
474
475 // push edited point edges to adjacent corners
476 botLeft.y = botRight.y;
477 topRight.x = botRight.x;
478 }
479 else if( isModified( aEditedPoint, aPoints.Line( RECT_TOP ) ) )
480 {
481 topLeft.y = std::min( topLeft.y, botRight.y - minHeight );
482 }
483 else if( isModified( aEditedPoint, aPoints.Line( RECT_LEFT ) ) )
484 {
485 topLeft.x = std::min( topLeft.x, botRight.x - minWidth );
486 }
487 else if( isModified( aEditedPoint, aPoints.Line( RECT_BOT ) ) )
488 {
489 botRight.y = std::max( botRight.y, topLeft.y + minHeight );
490 }
491 else if( isModified( aEditedPoint, aPoints.Line( RECT_RIGHT ) ) )
492 {
493 botRight.x = std::max( botRight.x, topLeft.x + minWidth );
494 }
495 }
496
497 static void UpdateItem( SCH_SHAPE& aRect, const EDIT_POINT& aEditedPoint,
498 EDIT_POINTS& aPoints, const VECTOR2I& aMinSize = { 0, 0 } )
499 {
500 VECTOR2I topLeft = aPoints.Point( RECT_TOPLEFT ).GetPosition();
501 VECTOR2I topRight = aPoints.Point( RECT_TOPRIGHT ).GetPosition();
502 VECTOR2I botLeft = aPoints.Point( RECT_BOTLEFT ).GetPosition();
503 VECTOR2I botRight = aPoints.Point( RECT_BOTRIGHT ).GetPosition();
504
505 int minWidth = std::max( schIUScale.MilsToIU( 1 ), aMinSize.x );
506 int minHeight = std::max( schIUScale.MilsToIU( 1 ), aMinSize.y );
507
508 PinEditedCorner( aEditedPoint, aPoints, minWidth, minHeight,
509 topLeft, topRight, botLeft, botRight );
510
511 if( isModified( aEditedPoint, aPoints.Point( RECT_TOPLEFT ) )
512 || isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) )
513 || isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) )
514 || isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) ) )
515 {
516 aRect.SetPosition( topLeft );
517 aRect.SetEnd( botRight );
518 }
519 else if( isModified( aEditedPoint, aPoints.Line( RECT_TOP ) ) )
520 {
521 aRect.SetStartY( topLeft.y );
522 }
523 else if( isModified( aEditedPoint, aPoints.Line( RECT_LEFT ) ) )
524 {
525 aRect.SetStartX( topLeft.x );
526 }
527 else if( isModified( aEditedPoint, aPoints.Line( RECT_BOT ) ) )
528 {
529 aRect.SetEndY( botRight.y );
530 }
531 else if( isModified( aEditedPoint, aPoints.Line( RECT_RIGHT ) ) )
532 {
533 aRect.SetEndX( botRight.x );
534 }
535
536 for( unsigned i = 0; i < aPoints.LinesSize(); ++i )
537 {
538 if( !isModified( aEditedPoint, aPoints.Line( i ) ) )
539 {
540 aPoints.Line( i ).SetConstraint( new EC_PERPLINE( aPoints.Line( i ) ) );
541 }
542 }
543 }
544
545 void MakePoints( EDIT_POINTS& aPoints ) override
546 {
547 m_rect.Normalize();
548 MakePoints( m_rect, aPoints );
549 }
550
551 bool UpdatePoints( EDIT_POINTS& aPoints ) override
552 {
553 m_rect.Normalize();
554 UpdatePoints( m_rect, aPoints );
555 return true;
556 }
557
558 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
559 std::vector<EDA_ITEM*>& aUpdatedItems ) override
560 {
561 VECTOR2I topLeft = aPoints.Point( RECT_TOPLEFT ).GetPosition();
562 VECTOR2I topRight = aPoints.Point( RECT_TOPRIGHT ).GetPosition();
563 VECTOR2I botLeft = aPoints.Point( RECT_BOTLEFT ).GetPosition();
564 VECTOR2I botRight = aPoints.Point( RECT_BOTRIGHT ).GetPosition();
565
566 PinEditedCorner( aEditedPoint, aPoints, schIUScale.MilsToIU( 1 ), schIUScale.MilsToIU( 1 ),
567 topLeft, topRight, botLeft, botRight );
568
569 const BOX2I oldBox = BOX2I::ByCorners( m_rect.GetStart(), m_rect.GetEnd() );
570 std::vector<SEG> oldSegs;
571 std::vector<VECTOR2I> moveVecs;
572
573 if( isModified( aEditedPoint, aPoints.Point( RECT_TOPLEFT ) )
574 || isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) )
575 || isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) )
576 || isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) ) )
577 {
578 // Corner drags don't update pins. Not only is it an escape hatch to avoid
579 // moving pins, it also avoids tricky problems when the pins "fall off"
580 // the ends of one of the two segments and get either left behind or
581 // "swept up" into the corner.
582 m_rect.SetPosition( topLeft );
583 m_rect.SetEnd( botRight );
584 }
585 else if( isModified( aEditedPoint, aPoints.Point( RECT_CENTER ) ) )
586 {
587 VECTOR2I moveVec = aPoints.Point( RECT_CENTER ).GetPosition() - oldBox.GetCenter();
588 m_rect.Move( moveVec );
589 }
590 else if( isModified( aEditedPoint, aPoints.Point( RECT_RADIUS ) ) )
591 {
592 int width = std::abs( botRight.x - topLeft.x );
593 int height = std::abs( botRight.y - topLeft.y );
594 int maxRadius = std::min( width, height ) / 2;
595 int x = aPoints.Point( RECT_RADIUS ).GetX();
596 x = std::clamp( x, botRight.x - maxRadius, botRight.x );
597 aPoints.Point( RECT_RADIUS ).SetPosition( VECTOR2I( x, topLeft.y ) );
598 m_rect.SetCornerRadius( botRight.x - x );
599 }
600 else if( isModified( aEditedPoint, aPoints.Line( RECT_TOP ) ) )
601 {
603 moveVecs.emplace_back( 0, topLeft.y - oldBox.GetTop() );
604 m_rect.SetStartY( topLeft.y );
605 }
606 else if( isModified( aEditedPoint, aPoints.Line( RECT_LEFT ) ) )
607 {
609 moveVecs.emplace_back( topLeft.x - oldBox.GetLeft(), 0 );
610 m_rect.SetStartX( topLeft.x );
611 }
612 else if( isModified( aEditedPoint, aPoints.Line( RECT_BOT ) ) )
613 {
615 moveVecs.emplace_back( 0, botRight.y - oldBox.GetBottom() );
616 m_rect.SetEndY( botRight.y );
617 }
618 else if( isModified( aEditedPoint, aPoints.Line( RECT_RIGHT ) ) )
619 {
621 moveVecs.emplace_back( botRight.x - oldBox.GetRight(), 0 );
622 m_rect.SetEndX( botRight.x );
623 }
624
625 dragPinsOnEdge( oldSegs, moveVecs, m_rect.GetUnit(), aCommit, aUpdatedItems );
626
627 for( unsigned i = 0; i < aPoints.LinesSize(); ++i )
628 {
629 if( !isModified( aEditedPoint, aPoints.Line( i ) ) )
630 {
631 aPoints.Line( i ).SetConstraint( new EC_PERPLINE( aPoints.Line( i ) ) );
632 }
633 }
634 }
635
636private:
637 void dragPinsOnEdge( const std::vector<SEG>& aOldEdges, const std::vector<VECTOR2I>& aMoveVecs,
638 int aEdgeUnit, COMMIT& aCommit, std::vector<EDA_ITEM*>& aUpdatedItems ) const
639 {
640 wxCHECK( aOldEdges.size() == aMoveVecs.size(), /* void */ );
641
642 // This only make sense in the symbol editor
643 if( !m_frame.IsType( FRAME_SCH_SYMBOL_EDITOR ) )
644 return;
645
647
648 // And only if the setting is enabled
649 if( !editor.GetSettings()->m_dragPinsAlongWithEdges )
650 return;
651
652 // Adjuting pins on a different unit to a unit-limited shape
653 // seems suspect.
654 wxCHECK( aEdgeUnit == 0 || aEdgeUnit == editor.GetUnit(), /* void */ );
655
656 /*
657 * Get a list of pins on a line segment
658 */
659 const auto getPinsOnSeg =
660 []( LIB_SYMBOL& aSymbol, int aUnit, const SEG& aSeg,
661 bool aIncludeEnds ) -> std::vector<SCH_PIN*>
662 {
663 std::vector<SCH_PIN*> pins;
664
665 for( SCH_PIN* pin : aSymbol.GetGraphicalPins( aUnit, 0 ) )
666 {
667 // Figure out if the pin "connects" to the line
668 const VECTOR2I pinRootPos = pin->GetPinRoot();
669
670 if( aSeg.Contains( pinRootPos ) )
671 {
672 if( aIncludeEnds || ( pinRootPos != aSeg.A && pinRootPos != aSeg.B ) )
673 {
674 pins.push_back( pin );
675 }
676 }
677 }
678
679 return pins;
680 };
681
682 LIB_SYMBOL* const symbol = editor.GetCurSymbol();
683
684 for( std::size_t i = 0; i < aOldEdges.size(); ++i )
685 {
686 if( aMoveVecs[i] == VECTOR2I( 0, 0 ) || !symbol )
687 continue;
688
689 const std::vector<SCH_PIN*> pins = getPinsOnSeg( *symbol, aEdgeUnit, aOldEdges[i], false );
690
691 for( SCH_PIN* pin : pins )
692 {
693 aCommit.Modify( pin, editor.GetScreen() );
694 aUpdatedItems.push_back( pin );
695
696 // Move the pin
697 pin->Move( aMoveVecs[i] );
698 }
699 }
700 }
701
702private:
705};
706
707
709{
710public:
712 m_textbox( aTextbox )
713 {}
714
715 void MakePoints( EDIT_POINTS& aPoints ) override
716 {
717 m_textbox.Normalize();
719 }
720
721 bool UpdatePoints( EDIT_POINTS& aPoints ) override
722 {
723 // point editor works only with rectangles having width and height > 0
724 // Some symbols can have rectangles with width or height < 0
725 // So normalize the size:
726 m_textbox.Normalize();
728 return true;
729 }
730
731 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
732 std::vector<EDA_ITEM*>& aUpdatedItems ) override
733 {
734 m_textbox.ClearBoundingBoxCache();
735 VECTOR2I minSize = m_textbox.GetMinSize();
736
738 m_textbox.ClearRenderCache();
739 }
740
741private:
743};
744
745
747{
748public:
750 m_sheet( aSheet ),
751 m_screen( aScreen )
752 {
753 m_noConnects = m_sheet.GetNoConnects();
754
755 // Find all wires connected to sheet pins and store their connections
756 for( SCH_SHEET_PIN* pin : m_sheet.GetPins() )
757 {
758 VECTOR2I pinPos = pin->GetPosition();
759
760 for( SCH_ITEM* item : m_screen.Items().Overlapping( SCH_LINE_T, pinPos ) )
761 {
762 SCH_LINE* line = static_cast<SCH_LINE*>( item );
763
764 if( !line->IsWire() && !line->IsBus() )
765 continue;
766
767 if( line->GetStartPoint() == pinPos )
768 m_connectedWires.push_back( { pin, line, STARTPOINT } );
769 else if( line->GetEndPoint() == pinPos )
770 m_connectedWires.push_back( { pin, line, ENDPOINT } );
771 }
772 }
773 }
774
775 void MakePoints( EDIT_POINTS& aPoints ) override
776 {
777 VECTOR2I topLeft = m_sheet.GetPosition();
778 VECTOR2I botRight = m_sheet.GetPosition() + m_sheet.GetSize();
779
780 aPoints.AddPoint( topLeft );
781 aPoints.AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
782 aPoints.AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
783 aPoints.AddPoint( botRight );
784
785 aPoints.AddLine( aPoints.Point( RECT_TOPLEFT ), aPoints.Point( RECT_TOPRIGHT ) );
786 aPoints.Line( RECT_TOP ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_TOP ) ) );
787 aPoints.AddLine( aPoints.Point( RECT_TOPRIGHT ), aPoints.Point( RECT_BOTRIGHT ) );
788 aPoints.Line( RECT_RIGHT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_RIGHT ) ) );
789 aPoints.AddLine( aPoints.Point( RECT_BOTRIGHT ), aPoints.Point( RECT_BOTLEFT ) );
790 aPoints.Line( RECT_BOT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_BOT ) ) );
791 aPoints.AddLine( aPoints.Point( RECT_BOTLEFT ), aPoints.Point( RECT_TOPLEFT ) );
792 aPoints.Line( RECT_LEFT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_LEFT ) ) );
793 }
794
795 bool UpdatePoints( EDIT_POINTS& aPoints ) override
796 {
797 VECTOR2I topLeft = m_sheet.GetPosition();
798 VECTOR2I botRight = m_sheet.GetPosition() + m_sheet.GetSize();
799
800 aPoints.Point( RECT_TOPLEFT ).SetPosition( topLeft );
801 aPoints.Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
802 aPoints.Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
803 aPoints.Point( RECT_BOTRIGHT ).SetPosition( botRight );
804 return true;
805 }
806
807 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
808 std::vector<EDA_ITEM*>& aUpdatedItems ) override
809 {
810 VECTOR2I topLeft = aPoints.Point( RECT_TOPLEFT ).GetPosition();
811 VECTOR2I topRight = aPoints.Point( RECT_TOPRIGHT ).GetPosition();
812 VECTOR2I botLeft = aPoints.Point( RECT_BOTLEFT ).GetPosition();
813 VECTOR2I botRight = aPoints.Point( RECT_BOTRIGHT ).GetPosition();
814 VECTOR2I sheetNewPos = m_sheet.GetPosition();
815 VECTOR2I sheetNewSize = m_sheet.GetSize();
816
817 bool editedTopRight = isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) );
818 bool editedBotLeft = isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) );
819 bool editedBotRight = isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) );
820
821 if( isModified( aEditedPoint, aPoints.Line( RECT_RIGHT ) ) )
822 editedTopRight = true;
823 else if( isModified( aEditedPoint, aPoints.Line( RECT_BOT ) ) )
824 editedBotLeft = true;
825
827 aEditedPoint, aPoints, m_sheet.GetMinWidth( editedTopRight || editedBotRight ),
828 m_sheet.GetMinHeight( editedBotLeft || editedBotRight ), topLeft, topRight, botLeft,
829 botRight );
830
831 if( isModified( aEditedPoint, aPoints.Point( RECT_TOPLEFT ) )
832 || isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) )
833 || isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) )
834 || isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) ) )
835 {
836 sheetNewPos = topLeft;
837 sheetNewSize = VECTOR2I( botRight.x - topLeft.x, botRight.y - topLeft.y );
838 }
839 else if( isModified( aEditedPoint, aPoints.Line( RECT_TOP ) ) )
840 {
841 sheetNewPos = VECTOR2I( m_sheet.GetPosition().x, topLeft.y );
842 sheetNewSize = VECTOR2I( m_sheet.GetSize().x, botRight.y - topLeft.y );
843 }
844 else if( isModified( aEditedPoint, aPoints.Line( RECT_LEFT ) ) )
845 {
846 sheetNewPos = VECTOR2I( topLeft.x, m_sheet.GetPosition().y );
847 sheetNewSize = VECTOR2I( botRight.x - topLeft.x, m_sheet.GetSize().y );
848 }
849 else if( isModified( aEditedPoint, aPoints.Line( RECT_BOT ) ) )
850 {
851 sheetNewSize = VECTOR2I( m_sheet.GetSize().x, botRight.y - topLeft.y );
852 }
853 else if( isModified( aEditedPoint, aPoints.Line( RECT_RIGHT ) ) )
854 {
855 sheetNewSize = VECTOR2I( botRight.x - topLeft.x, m_sheet.GetSize().y );
856 }
857
858 for( unsigned i = 0; i < aPoints.LinesSize(); ++i )
859 {
860 if( !isModified( aEditedPoint, aPoints.Line( i ) ) )
861 {
862 aPoints.Line( i ).SetConstraint( new EC_PERPLINE( aPoints.Line( i ) ) );
863 }
864 }
865
866 if( m_sheet.GetPosition() != sheetNewPos )
867 m_sheet.SetPositionIgnoringPins( sheetNewPos );
868
869 if( m_sheet.GetSize() != sheetNewSize )
870 m_sheet.Resize( sheetNewSize );
871
872 // Update no-connects to follow their sheet pins
873 for( auto& [sheetPin, noConnect] : m_noConnects )
874 {
875 if( noConnect->GetPosition() != sheetPin->GetTextPos() )
876 {
877 aCommit.Modify( noConnect, &m_screen );
878 noConnect->SetPosition( sheetPin->GetTextPos() );
879 aUpdatedItems.push_back( noConnect );
880 }
881 }
882
883 // Update connected wires to follow their sheet pins
884 for( auto& [pin, line, endpoint] : m_connectedWires )
885 {
886 VECTOR2I newPinPos = pin->GetPosition();
887 bool needsUpdate = false;
888
889 if( endpoint == STARTPOINT && line->GetStartPoint() != newPinPos )
890 needsUpdate = true;
891 else if( endpoint == ENDPOINT && line->GetEndPoint() != newPinPos )
892 needsUpdate = true;
893
894 if( needsUpdate )
895 {
896 aCommit.Modify( line, &m_screen );
897
898 if( endpoint == STARTPOINT )
899 line->SetStartPoint( newPinPos );
900 else
901 line->SetEndPoint( newPinPos );
902
903 aUpdatedItems.push_back( line );
904 }
905 }
906 }
907
908private:
911 std::map<SCH_SHEET_PIN*, SCH_NO_CONNECT*> m_noConnects;
912 std::vector<std::tuple<SCH_SHEET_PIN*, SCH_LINE*, int>> m_connectedWires;
913};
914
915
917{
918 m_editBehavior = nullptr;
919 m_editPoints = std::make_shared<EDIT_POINTS>( aItem );
920
921 if( !aItem )
922 return;
923
924 // Generate list of edit points based on the item type
925 switch( aItem->Type() )
926 {
927 case SCH_SHAPE_T:
928 {
929 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
930
931 switch( shape->GetShape() )
932 {
933 case SHAPE_T::ARC:
934 // EDA_ARC_POINT_EDIT_BEHAVIOR holds a reference to m_arcEditMode, so the
935 // persisted value must be synced from settings before the behavior is built.
936 if( m_isSymbolEditor )
937 {
938 if( SYMBOL_EDITOR_SETTINGS* cfg = m_frame->libeditconfig() )
939 m_arcEditMode = cfg->m_ArcEditMode;
940 }
941 else if( EESCHEMA_SETTINGS* cfg = m_frame->eeconfig() )
942 {
943 m_arcEditMode = cfg->m_Drawing.arc_edit_mode;
944 }
945
946 m_editBehavior = std::make_unique<EDA_ARC_POINT_EDIT_BEHAVIOR>(
948 break;
949 case SHAPE_T::CIRCLE:
950 m_editBehavior = std::make_unique<EDA_CIRCLE_POINT_EDIT_BEHAVIOR>( *shape );
951 break;
953 m_editBehavior = std::make_unique<RECTANGLE_POINT_EDIT_BEHAVIOR>( *shape, *m_frame );
954 break;
955 case SHAPE_T::POLY:
956 m_editBehavior = std::make_unique<EDA_POLYGON_POINT_EDIT_BEHAVIOR>( *shape );
957 break;
958 case SHAPE_T::BEZIER:
959 {
960 int maxError = schIUScale.mmToIU( ARC_LOW_DEF_MM );
961
962 if( SCHEMATIC* schematic = shape->Schematic() )
963 maxError = schematic->Settings().m_MaxError;
964
965 m_editBehavior = std::make_unique<EDA_BEZIER_POINT_EDIT_BEHAVIOR>( *shape, maxError );
966 break;
967 }
968 case SHAPE_T::ELLIPSE:
969 case SHAPE_T::ELLIPSE_ARC: m_editBehavior = std::make_unique<EDA_ELLIPSE_POINT_EDIT_BEHAVIOR>( *shape ); break;
970 default:
972 }
973
974 break;
975 }
976 case SCH_RULE_AREA_T:
977 {
978 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
979 // Implemented directly as a polygon
980 m_editBehavior = std::make_unique<EDA_POLYGON_POINT_EDIT_BEHAVIOR>( *shape );
981 break;
982 }
983 case SCH_TEXTBOX_T:
984 {
985 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( aItem );
986 m_editBehavior = std::make_unique<TEXTBOX_POINT_EDIT_BEHAVIOR>( *textbox );
987 break;
988 }
989 case SCH_TABLECELL_T:
990 {
991 SCH_TABLECELL* cell = static_cast<SCH_TABLECELL*>( aItem );
992 m_editBehavior = std::make_unique<SCH_TABLECELL_POINT_EDIT_BEHAVIOR>( *cell, *m_frame->GetScreen() );
993 break;
994 }
995 case SCH_SHEET_T:
996 {
997 SCH_SHEET& sheet = static_cast<SCH_SHEET&>( *aItem );
998 m_editBehavior = std::make_unique<SHEET_POINT_EDIT_BEHAVIOR>( sheet, *m_frame->GetScreen() );
999 break;
1000 }
1001 case SCH_BITMAP_T:
1002 {
1003 SCH_BITMAP& bitmap = static_cast<SCH_BITMAP&>( *aItem );
1004 m_editBehavior = std::make_unique<BITMAP_POINT_EDIT_BEHAVIOR>( bitmap );
1005 break;
1006 }
1007 case SCH_LINE_T:
1008 {
1009 SCH_LINE& line = static_cast<SCH_LINE&>( *aItem );
1010 m_editBehavior = std::make_unique<LINE_POINT_EDIT_BEHAVIOR>( line, *m_frame->GetScreen() );
1011 break;
1012 }
1013 default:
1014 {
1015 m_editPoints.reset();
1016 break;
1017 }
1018 }
1019
1020 // If we got a behavior, generate the points
1021 if( m_editBehavior )
1022 {
1023 wxCHECK( m_editPoints, /* void */ );
1024 m_editBehavior->MakePoints( *m_editPoints );
1025 }
1026}
1027
1028
1030 SCH_TOOL_BASE<SCH_BASE_FRAME>( "eeschema.PointEditor" ),
1031 m_editedPoint( nullptr ),
1032 m_inDrag( false ),
1034 m_inPointEditor( false )
1035{
1036}
1037
1038
1040{
1041 SCH_TOOL_BASE::Reset( aReason );
1042
1043 if( KIGFX::VIEW* view = getView() )
1044 {
1045 if( m_angleItem )
1046 view->Remove( m_angleItem.get() );
1047
1048 if( m_editPoints )
1049 view->Remove( m_editPoints.get() );
1050 }
1051
1052 m_angleItem.reset();
1053 m_editPoints.reset();
1054 m_editedPoint = nullptr;
1055
1056 // A reset can tear down the Main() loop mid-drag, so clear the drag flag here too.
1057 m_inDrag = false;
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 // Mirror the drag state so IsDragging() lets the frame defer the autosave snapshot,
1274 // which would otherwise serialize the whole schematic over a live point edit.
1275 m_inDrag = inDrag;
1276
1277 controls->SetAutoPan( inDrag );
1278 controls->CaptureCursor( inDrag );
1279 }
1280
1281 m_inDrag = false;
1282
1283 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( item ) )
1284 {
1285 shape->ClearFlags( IS_MOVING );
1286 shape->SetHatchingDirty();
1287 shape->UpdateHatching();
1288 }
1289
1290 controls->SetAutoPan( false );
1291 controls->CaptureCursor( false );
1292 setEditedPoint( nullptr );
1293
1294 if( m_editPoints )
1295 {
1296 view->Remove( m_editPoints.get() );
1297 view->Remove( m_angleItem.get() );
1298
1299 m_editPoints.reset();
1300 m_angleItem.reset();
1301 m_frame->GetCanvas()->Refresh();
1302 }
1303
1304 delete grid;
1305
1306 return 0;
1307}
1308
1309
1310void SCH_POINT_EDITOR::updateParentItem( bool aSnapToGrid, SCH_COMMIT& aCommit ) const
1311{
1312 EDA_ITEM* item = m_editPoints->GetParent();
1313
1314 if( !item )
1315 return;
1316
1317 if( !m_editBehavior )
1318 return;
1319
1320 std::vector<EDA_ITEM*> updatedItems;
1321 m_editBehavior->UpdateItem( *m_editedPoint, *m_editPoints, aCommit, updatedItems );
1322
1323 for( EDA_ITEM* updatedItem : updatedItems )
1324 updateItem( updatedItem, true );
1325
1326 m_frame->SetMsgPanel( item );
1327}
1328
1329
1331{
1332 if( !m_editPoints || !m_editBehavior )
1333 return;
1334
1335 // Careful; the unit and/or body style may have changed out from under us, meaning the item is no
1336 // longer present on the canvas.
1337 if( m_isSymbolEditor )
1338 {
1340 SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( m_editPoints->GetParent() );
1341
1342 if( ( item && item->GetUnit() != 0 && item->GetUnit() != editor->GetUnit() )
1343 || ( item && item->GetBodyStyle() != 0 && item->GetBodyStyle() != editor->GetBodyStyle() ) )
1344 {
1345 getView()->Remove( m_editPoints.get() );
1346 getView()->Remove( m_angleItem.get() );
1347 m_editPoints.reset();
1348 m_angleItem.reset();
1349 return;
1350 }
1351 }
1352
1353 m_editBehavior->UpdatePoints( *m_editPoints );
1354 getView()->Update( m_editPoints.get() );
1355 getView()->Update( m_angleItem.get() );
1356}
1357
1358
1360{
1362
1363 if( aPoint )
1364 {
1365 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1366 controls->ForceCursorPosition( true, aPoint->GetPosition() );
1367 controls->ShowCursor( true );
1368 }
1369 else
1370 {
1371 if( m_frame->ToolStackIsEmpty() )
1372 controls->ShowCursor( false );
1373
1374 controls->ForceCursorPosition( false );
1375 }
1376
1377 m_editedPoint = aPoint;
1378}
1379
1380
1382{
1383 if( !m_editPoints || !m_editedPoint || !m_editPoints->GetParent()->IsType( { SCH_SHAPE_T, SCH_RULE_AREA_T } ) )
1384 return false;
1385
1386 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1387
1388 if( shape->GetPolyShape().IsEmpty() )
1389 return false;
1390
1391 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1392
1393 if( m_editPoints->GetParent()->Type() == SCH_SHAPE_T && poly.GetPointCount() <= 2 )
1394 return false;
1395 if( m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T && poly.GetPointCount() <= 3 )
1396 return false;
1397
1398 for( const VECTOR2I& pt : poly.CPoints() )
1399 {
1400 if( pt == m_editedPoint->GetPosition() )
1401 return true;
1402 }
1403
1404 return false;
1405}
1406
1407
1409{
1410 if( !m_editPoints || !m_editPoints->GetParent()->IsType( { SCH_SHAPE_T, SCH_RULE_AREA_T } ) )
1411 return false;
1412
1413 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1414
1415 if( shape->GetShape() != SHAPE_T::POLY )
1416 return false;
1417
1418 VECTOR2I cursorPos = getViewControls()->GetCursorPosition( false );
1419 double threshold = getView()->ToWorld( EDIT_POINT::POINT_SIZE );
1420
1421 return shape->HitTest( cursorPos, (int) threshold );
1422}
1423
1424
1426{
1427 if( !m_editPoints || !m_editPoints->GetParent()->IsType( { SCH_SHAPE_T, SCH_RULE_AREA_T } ) )
1428 return 0;
1429
1430 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1431 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1432 SCH_COMMIT commit( m_toolMgr );
1433
1434 commit.Modify( shape, m_frame->GetScreen() );
1435
1437 int currentMinDistance = INT_MAX;
1438 int closestLineStart = 0;
1439 unsigned numPoints = poly.GetPointCount();
1440
1441 if( !shape->IsClosed() )
1442 numPoints -= 1;
1443
1444 for( unsigned i = 0; i < numPoints; ++i )
1445 {
1446 SEG seg = poly.GetSegment( i );
1447 int distance = seg.Distance( cursor );
1448
1449 if( distance < currentMinDistance )
1450 {
1451 currentMinDistance = distance;
1452 closestLineStart = i;
1453 }
1454 }
1455
1456 poly.Insert( closestLineStart + 1, cursor );
1457
1458 updateItem( shape, true );
1459 updatePoints();
1460
1461 commit.Push( _( "Add Corner" ) );
1462 return 0;
1463}
1464
1465
1467{
1468 if( !m_editPoints || !m_editedPoint || !m_editPoints->GetParent()->IsType( { SCH_SHAPE_T, SCH_RULE_AREA_T } ) )
1469 return 0;
1470
1471 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1472 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1473 SCH_COMMIT commit( m_toolMgr );
1474
1475 if( m_editPoints->GetParent()->Type() == SCH_SHAPE_T && poly.GetPointCount() <= 2 )
1476 return 0;
1477 if( m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T && poly.GetPointCount() <= 3 )
1478 return 0;
1479
1480 commit.Modify( shape, m_frame->GetScreen() );
1481
1482 int idx = getEditedPointIndex();
1483 int last = (int) poly.GetPointCount() - 1;
1484
1485 if( idx == 0 && poly.GetPoint( 0 ) == poly.GetPoint( last ) )
1486 {
1487 poly.Remove( idx );
1488 poly.SetPoint( last-1, poly.GetPoint( 0 ) );
1489 }
1490 else
1491 {
1492 poly.Remove( idx );
1493 }
1494
1495 shape->SetHatchingDirty();
1496
1497 setEditedPoint( nullptr );
1498
1499 updateItem( shape, true );
1500 updatePoints();
1501
1502 commit.Push( _( "Remove Corner" ) );
1503 return 0;
1504}
1505
1506
1508{
1509 // The Symbol Editor uses SYMBOL_EDITOR_SETTINGS, not EESCHEMA_SETTINGS, so eeconfig()
1510 // returns nullptr there. Dispatch on frame type to read/write the right settings store.
1511 EESCHEMA_SETTINGS* schCfg = m_isSymbolEditor ? nullptr : m_frame->eeconfig();
1512 SYMBOL_EDITOR_SETTINGS* symCfg = m_isSymbolEditor ? m_frame->libeditconfig() : nullptr;
1513
1514 if( aEvent.Matches( ACTIONS::cycleArcEditMode.MakeEvent() ) )
1515 {
1516 if( schCfg )
1518 else if( symCfg )
1519 m_arcEditMode = symCfg->m_ArcEditMode;
1520
1522 }
1523 else
1524 {
1526 }
1527
1528 if( schCfg )
1530 else if( symCfg )
1531 symCfg->m_ArcEditMode = m_arcEditMode;
1532
1533 return 0;
1534}
1535
1536
1538{
1539 updatePoints();
1540 return 0;
1541}
1542
1543
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:123
constexpr double ARC_LOW_DEF_MM
Definition base_units.h:127
BOX2< VECTOR2I > BOX2I
Definition box2.h:918
static TOOL_ACTION cycleArcEditMode
Definition actions.h:268
static TOOL_ACTION pointEditorArcKeepCenter
Definition actions.h:269
static TOOL_ACTION pointEditorArcKeepRadius
Definition actions.h:271
static TOOL_ACTION activatePointEditor
Definition actions.h:267
static TOOL_ACTION pointEditorArcKeepEndpoint
Definition actions.h:270
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:66
constexpr const Vec GetCenter() const
Definition box2.h:226
constexpr coord_type GetLeft() const
Definition box2.h:224
constexpr coord_type GetRight() const
Definition box2.h:213
constexpr coord_type GetTop() const
Definition box2.h:225
constexpr coord_type GetBottom() const
Definition box2.h:218
Represent a set of changes (additions, deletions or modifications) of a data model (e....
Definition commit.h:68
bool Empty() const
Definition commit.h:134
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:102
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:96
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:108
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition eda_item.h:202
bool IsNew() const
Definition eda_item.h:129
virtual void SetEnd(const VECTOR2I &aEnd)
Definition eda_shape.h:244
void SetStartX(int x)
Definition eda_shape.h:208
void SetEndY(int aY)
Definition eda_shape.h:251
void SetStartY(int y)
Definition eda_shape.h:201
SHAPE_POLY_SET & GetPolyShape()
SHAPE_T GetShape() const
Definition eda_shape.h:185
void SetEndX(int aX)
Definition eda_shape.h:258
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:240
bool IsClosed() const
wxString SHAPE_T_asString() const
void SetHatchingDirty()
Definition eda_shape.h:163
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:44
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:76
int GetY() const
Return Y coordinate of an EDIT_POINT.
Definition edit_points.h:92
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:68
int GetX() const
Return X coordinate of an EDIT_POINT.
Definition edit_points.h:84
void SetDrawCircle(bool aDrawCircle=true)
static const TOOL_EVENT ClearedEvent
Definition actions.h:343
static const TOOL_EVENT SelectedEvent
Definition actions.h:341
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition actions.h:348
static const TOOL_EVENT PointSelectedEvent
Definition actions.h:340
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:63
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition view.cpp:300
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition view.cpp:404
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:1835
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:534
Define a library symbol object.
Definition lib_symbol.h:80
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:90
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:36
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:162
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:268
int GetBodyStyle() const
Definition sch_item.h:242
int GetUnit() const
Definition sch_item.h:233
Segment description base class to describe items which have 2 end points (track, wire,...
Definition sch_line.h:38
VECTOR2I GetEndPoint() const
Definition sch_line.h:144
VECTOR2I GetStartPoint() const
Definition sch_line.h:135
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
True while a point drag is in progress (between grab and release).
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:85
VECTOR2I GetCenter() const
Definition sch_shape.h:92
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:84
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:44
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:38
int Distance(const SEG &aSeg) const
Compute minimum Euclidean distance to segment aSeg.
Definition seg.cpp:698
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:173
int Size() const
Returns the number of selected parts.
Definition selection.h:117
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:182
KIGFX::VIEW_CONTROLS * getViewControls() const
Definition tool_base.cpp:40
KIGFX::VIEW * getView() const
Definition tool_base.cpp:34
Generic, UI-independent tool event.
Definition tool_event.h:167
bool DisableGridSnapping() const
Definition tool_event.h:367
bool Matches(const TOOL_EVENT &aEvent) const
Test whether two events match in terms of category & action or command.
Definition tool_event.h:388
const VECTOR2D Position() const
Return mouse cursor position in world coordinates.
Definition tool_event.h:289
bool IsDrag(int aButtonMask=BUT_ANY) const
Definition tool_event.h:311
const VECTOR2D DragOrigin() const
Return the point where dragging has started.
Definition tool_event.h:295
T Parameter() const
Return a parameter assigned to the event.
Definition tool_event.h:469
bool IsMotion() const
Definition tool_event.h:326
void Go(int(SCH_BASE_FRAME::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
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:279
@ ARROW
Definition cursors.h:42
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:52
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:47
@ ELLIPSE_ARC
Definition eda_shape.h:53
@ FRAME_SCH_SYMBOL_EDITOR
Definition frame_type.h:31
@ GRID_GRAPHICS
Definition grid_helper.h:48
@ LAYER_NOTES
Definition layer_ids.h:465
#define UNIMPLEMENTED_FOR(type)
Definition macros.h:92
constexpr int Mils2IU(const EDA_IU_SCALE &aIuScale, int mils)
Definition eda_units.h:171
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:35
Utility functions for working with shapes.
KIBIS_PIN * pin
std::vector< std::vector< std::string > > table
@ MD_SHIFT
Definition tool_event.h:139
@ BUT_LEFT
Definition tool_event.h:128
@ SCH_LINE_T
Definition typeinfo.h:160
@ SCH_TABLECELL_T
Definition typeinfo.h:163
@ SCH_SHEET_T
Definition typeinfo.h:172
@ SCH_SHAPE_T
Definition typeinfo.h:146
@ SCH_RULE_AREA_T
Definition typeinfo.h:167
@ SCH_ITEM_LOCATE_GRAPHIC_LINE_T
Definition typeinfo.h:185
@ SCH_BITMAP_T
Definition typeinfo.h:161
@ SCH_TEXTBOX_T
Definition typeinfo.h:149
constexpr int sign(T val)
Definition util.h:141
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683