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 m_editBehavior = std::make_unique<EDA_ARC_POINT_EDIT_BEHAVIOR>(
939 *shape, m_arcEditMode, *getViewControls() );
940 break;
941 case SHAPE_T::CIRCLE:
942 m_editBehavior = std::make_unique<EDA_CIRCLE_POINT_EDIT_BEHAVIOR>( *shape );
943 break;
945 m_editBehavior = std::make_unique<RECTANGLE_POINT_EDIT_BEHAVIOR>( *shape, *m_frame );
946 break;
947 case SHAPE_T::POLY:
948 m_editBehavior = std::make_unique<EDA_POLYGON_POINT_EDIT_BEHAVIOR>( *shape );
949 break;
950 case SHAPE_T::BEZIER:
951 {
952 int maxError = schIUScale.mmToIU( ARC_LOW_DEF_MM );
953
954 if( SCHEMATIC* schematic = shape->Schematic() )
955 maxError = schematic->Settings().m_MaxError;
956
957 m_editBehavior = std::make_unique<EDA_BEZIER_POINT_EDIT_BEHAVIOR>( *shape, maxError );
958 break;
959 }
960 default:
962 }
963
964 break;
965 }
966 case SCH_RULE_AREA_T:
967 {
968 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
969 // Implemented directly as a polygon
970 m_editBehavior = std::make_unique<EDA_POLYGON_POINT_EDIT_BEHAVIOR>( *shape );
971 break;
972 }
973 case SCH_TEXTBOX_T:
974 {
975 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( aItem );
976 m_editBehavior = std::make_unique<TEXTBOX_POINT_EDIT_BEHAVIOR>( *textbox );
977 break;
978 }
979 case SCH_TABLECELL_T:
980 {
981 SCH_TABLECELL* cell = static_cast<SCH_TABLECELL*>( aItem );
982 m_editBehavior = std::make_unique<SCH_TABLECELL_POINT_EDIT_BEHAVIOR>( *cell, *m_frame->GetScreen() );
983 break;
984 }
985 case SCH_SHEET_T:
986 {
987 SCH_SHEET& sheet = static_cast<SCH_SHEET&>( *aItem );
988 m_editBehavior = std::make_unique<SHEET_POINT_EDIT_BEHAVIOR>( sheet, *m_frame->GetScreen() );
989 break;
990 }
991 case SCH_BITMAP_T:
992 {
993 SCH_BITMAP& bitmap = static_cast<SCH_BITMAP&>( *aItem );
994 m_editBehavior = std::make_unique<BITMAP_POINT_EDIT_BEHAVIOR>( bitmap );
995 break;
996 }
997 case SCH_LINE_T:
998 {
999 SCH_LINE& line = static_cast<SCH_LINE&>( *aItem );
1000 m_editBehavior = std::make_unique<LINE_POINT_EDIT_BEHAVIOR>( line, *m_frame->GetScreen() );
1001 break;
1002 }
1003 default:
1004 {
1005 m_editPoints.reset();
1006 break;
1007 }
1008 }
1009
1010 // If we got a behavior, generate the points
1011 if( m_editBehavior )
1012 {
1013 wxCHECK( m_editPoints, /* void */ );
1014 m_editBehavior->MakePoints( *m_editPoints );
1015 }
1016}
1017
1018
1026
1027
1029{
1030 SCH_TOOL_BASE::Reset( aReason );
1031
1032 if( KIGFX::VIEW* view = getView() )
1033 {
1034 if( m_angleItem )
1035 view->Remove( m_angleItem.get() );
1036
1037 if( m_editPoints )
1038 view->Remove( m_editPoints.get() );
1039 }
1040
1041 m_angleItem.reset();
1042 m_editPoints.reset();
1043 m_editedPoint = nullptr;
1044}
1045
1046
1048{
1049 using S_C = SELECTION_CONDITIONS;
1050
1052
1053 const auto addCornerCondition = [&]( const SELECTION& aSelection ) -> bool
1054 {
1055 return SCH_POINT_EDITOR::addCornerCondition( aSelection );
1056 };
1057
1058 const auto removeCornerCondition = [&]( const SELECTION& aSelection ) -> bool
1059 {
1060 return SCH_POINT_EDITOR::removeCornerCondition( aSelection );
1061 };
1062
1063 const auto arcIsEdited = [&]( const SELECTION& aSelection ) -> bool
1064 {
1065 const EDA_ITEM* item = aSelection.Front();
1066 return ( item != nullptr ) && ( item->Type() == SCH_SHAPE_T )
1067 && static_cast<const SCH_SHAPE*>( item )->GetShape() == SHAPE_T::ARC;
1068 };
1069
1070 auto& menu = m_selectionTool->GetToolMenu().GetMenu();
1071
1072 // clang-format off
1075 menu.AddItem( ACTIONS::cycleArcEditMode, S_C::Count( 1 ) && arcIsEdited );
1076 // clang-format on
1077
1078 return true;
1079}
1080
1081
1083{
1084 setEditedPoint( nullptr );
1085
1086 return 0;
1087}
1088
1089
1091{
1092 EDIT_POINT* point = m_editedPoint;
1093
1094 if( !m_editPoints )
1095 {
1096 point = nullptr;
1097 }
1098 else if( aEvent.IsMotion() )
1099 {
1100 point = m_editPoints->FindPoint( aEvent.Position(), getView() );
1101 }
1102 else if( aEvent.IsDrag( BUT_LEFT ) )
1103 {
1104 point = m_editPoints->FindPoint( aEvent.DragOrigin(), getView() );
1105 }
1106 else
1107 {
1108 point = m_editPoints->FindPoint( getViewControls()->GetCursorPosition( false ), getView() );
1109 }
1110
1111 if( m_editedPoint != point )
1112 setEditedPoint( point );
1113}
1114
1115
1117{
1118 if( !m_selectionTool )
1119 return 0;
1120
1121 if( m_inPointEditor )
1122 return 0;
1123
1125
1126 if( m_isSymbolEditor )
1127 {
1129
1130 if( !editor->IsSymbolEditable() || editor->IsSymbolAlias() )
1131 return 0;
1132 }
1133
1134 const SCH_SELECTION& selection = m_selectionTool->GetSelection();
1135
1136 if( selection.Size() != 1 || !selection.Front()->IsType( pointEditorTypes ) )
1137 return 0;
1138
1139 // Wait till drawing tool is done
1140 if( selection.Front()->IsNew() )
1141 return 0;
1142
1143 Activate();
1144
1147 VECTOR2I cursorPos;
1148 KIGFX::VIEW* view = getView();
1149 EDA_ITEM* item = selection.Front();
1150 SCH_COMMIT commit( m_toolMgr );
1151
1152 controls->ShowCursor( true );
1153
1154 makePointsAndBehavior( item );
1155 m_angleItem = std::make_unique<KIGFX::PREVIEW::ANGLE_ITEM>( m_editPoints );
1156 view->Add( m_editPoints.get() );
1157 view->Add( m_angleItem.get() );
1158 setEditedPoint( nullptr );
1159 updateEditedPoint( aEvent );
1160 bool inDrag = false;
1161
1162 // Main loop: keep receiving events
1163 while( TOOL_EVENT* evt = Wait() )
1164 {
1165 if( grid )
1166 {
1167 grid->SetSnap( !evt->Modifier( MD_SHIFT ) );
1168 grid->SetUseGrid( getView()->GetGAL()->GetGridSnapping()
1169 && !evt->DisableGridSnapping() );
1170 }
1171 else
1172 {
1173 // This check is based on the assumption that the grid object must be valid.
1174 // If this assumption is wrong, please fix the code above.
1175 wxCHECK( false, 0 );
1176 }
1177
1178 if( !m_editPoints || evt->IsSelectionEvent() )
1179 break;
1180
1181 if ( !inDrag )
1182 updateEditedPoint( *evt );
1183
1184 if( evt->IsDrag( BUT_LEFT ) && m_editedPoint )
1185 {
1186 if( !inDrag )
1187 {
1188 commit.Modify( m_editPoints->GetParent(), m_frame->GetScreen() );
1189
1190 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( item ) )
1191 {
1192 shape->SetFlags( IS_MOVING );
1193 shape->SetHatchingDirty();
1194 shape->UpdateHatching();
1195 }
1196
1197 inDrag = true;
1198 }
1199
1200 bool snap = !evt->DisableGridSnapping();
1201
1202 cursorPos = grid->Align( controls->GetMousePosition(),
1204 controls->ForceCursorPosition( true, cursorPos );
1205
1206 m_editedPoint->SetPosition( controls->GetCursorPosition( snap ) );
1207
1208 updateParentItem( snap, commit );
1209 updatePoints();
1210 }
1211 else if( inDrag && evt->IsMouseUp( BUT_LEFT ) )
1212 {
1213 if( !commit.Empty() )
1214 commit.Push( _( "Move Point" ) );
1215
1216 controls->SetAutoPan( false );
1217
1218 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( item ) )
1219 {
1220 shape->ClearFlags( IS_MOVING );
1221 shape->SetHatchingDirty();
1222 shape->UpdateHatching();
1223 }
1224
1225 inDrag = false;
1226 }
1227 else if( evt->IsCancelInteractive() || evt->IsActivate() )
1228 {
1229 if( inDrag ) // Restore the last change
1230 {
1231 // Currently we are manually managing the lifetime of the grid
1232 // helpers because there is a bug in the tool stack that adds
1233 // the point editor again when commit.Revert() rebuilds the selection.
1234 // We remove this grid here so the its destructor is called before it
1235 // is added again.
1236 if( grid )
1237 {
1238 delete grid;
1239 grid = nullptr;
1240 }
1241
1242 commit.Revert();
1243 inDrag = false;
1244 break;
1245 }
1246 else if( evt->IsCancelInteractive() )
1247 {
1248 break;
1249 }
1250
1251 if( evt->IsActivate() )
1252 break;
1253 }
1254 else
1255 {
1256 evt->SetPassEvent();
1257 }
1258
1259 controls->SetAutoPan( inDrag );
1260 controls->CaptureCursor( inDrag );
1261 }
1262
1263 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( item ) )
1264 {
1265 shape->ClearFlags( IS_MOVING );
1266 shape->SetHatchingDirty();
1267 shape->UpdateHatching();
1268 }
1269
1270 controls->SetAutoPan( false );
1271 controls->CaptureCursor( false );
1272 setEditedPoint( nullptr );
1273
1274 if( m_editPoints )
1275 {
1276 view->Remove( m_editPoints.get() );
1277 view->Remove( m_angleItem.get() );
1278
1279 m_editPoints.reset();
1280 m_angleItem.reset();
1281 m_frame->GetCanvas()->Refresh();
1282 }
1283
1284 delete grid;
1285
1286 return 0;
1287}
1288
1289
1290void SCH_POINT_EDITOR::updateParentItem( bool aSnapToGrid, SCH_COMMIT& aCommit ) const
1291{
1292 EDA_ITEM* item = m_editPoints->GetParent();
1293
1294 if( !item )
1295 return;
1296
1297 if( !m_editBehavior )
1298 return;
1299
1300 std::vector<EDA_ITEM*> updatedItems;
1301 m_editBehavior->UpdateItem( *m_editedPoint, *m_editPoints, aCommit, updatedItems );
1302
1303 for( EDA_ITEM* updatedItem : updatedItems )
1304 updateItem( updatedItem, true );
1305
1306 m_frame->SetMsgPanel( item );
1307}
1308
1309
1311{
1312 if( !m_editPoints || !m_editBehavior )
1313 return;
1314
1315 // Careful; the unit and/or body style may have changed out from under us, meaning the item is no
1316 // longer present on the canvas.
1317 if( m_isSymbolEditor )
1318 {
1320 SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( m_editPoints->GetParent() );
1321
1322 if( ( item && item->GetUnit() != 0 && item->GetUnit() != editor->GetUnit() )
1323 || ( item && item->GetBodyStyle() != 0 && item->GetBodyStyle() != editor->GetBodyStyle() ) )
1324 {
1325 getView()->Remove( m_editPoints.get() );
1326 getView()->Remove( m_angleItem.get() );
1327 m_editPoints.reset();
1328 m_angleItem.reset();
1329 return;
1330 }
1331 }
1332
1333 m_editBehavior->UpdatePoints( *m_editPoints );
1334 getView()->Update( m_editPoints.get() );
1335 getView()->Update( m_angleItem.get() );
1336}
1337
1338
1340{
1342
1343 if( aPoint )
1344 {
1345 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1346 controls->ForceCursorPosition( true, aPoint->GetPosition() );
1347 controls->ShowCursor( true );
1348 }
1349 else
1350 {
1351 if( m_frame->ToolStackIsEmpty() )
1352 controls->ShowCursor( false );
1353
1354 controls->ForceCursorPosition( false );
1355 }
1356
1357 m_editedPoint = aPoint;
1358}
1359
1360
1362{
1363 if( !m_editPoints || !m_editedPoint || !m_editPoints->GetParent()->IsType( { SCH_SHAPE_T, SCH_RULE_AREA_T } ) )
1364 return false;
1365
1366 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1367
1368 if( shape->GetPolyShape().IsEmpty() )
1369 return false;
1370
1371 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1372
1373 if( m_editPoints->GetParent()->Type() == SCH_SHAPE_T && poly.GetPointCount() <= 2 )
1374 return false;
1375 if( m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T && poly.GetPointCount() <= 3 )
1376 return false;
1377
1378 for( const VECTOR2I& pt : poly.CPoints() )
1379 {
1380 if( pt == m_editedPoint->GetPosition() )
1381 return true;
1382 }
1383
1384 return false;
1385}
1386
1387
1389{
1390 if( !m_editPoints || !m_editPoints->GetParent()->IsType( { SCH_SHAPE_T, SCH_RULE_AREA_T } ) )
1391 return false;
1392
1393 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1394
1395 if( shape->GetShape() != SHAPE_T::POLY )
1396 return false;
1397
1398 VECTOR2I cursorPos = getViewControls()->GetCursorPosition( false );
1399 double threshold = getView()->ToWorld( EDIT_POINT::POINT_SIZE );
1400
1401 return shape->HitTest( cursorPos, (int) threshold );
1402}
1403
1404
1406{
1407 if( !m_editPoints || !m_editPoints->GetParent()->IsType( { SCH_SHAPE_T, SCH_RULE_AREA_T } ) )
1408 return 0;
1409
1410 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1411 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1412 SCH_COMMIT commit( m_toolMgr );
1413
1414 commit.Modify( shape, m_frame->GetScreen() );
1415
1417 int currentMinDistance = INT_MAX;
1418 int closestLineStart = 0;
1419 unsigned numPoints = poly.GetPointCount();
1420
1421 if( !shape->IsClosed() )
1422 numPoints -= 1;
1423
1424 for( unsigned i = 0; i < numPoints; ++i )
1425 {
1426 SEG seg = poly.GetSegment( i );
1427 int distance = seg.Distance( cursor );
1428
1429 if( distance < currentMinDistance )
1430 {
1431 currentMinDistance = distance;
1432 closestLineStart = i;
1433 }
1434 }
1435
1436 poly.Insert( closestLineStart + 1, cursor );
1437
1438 updateItem( shape, true );
1439 updatePoints();
1440
1441 commit.Push( _( "Add Corner" ) );
1442 return 0;
1443}
1444
1445
1447{
1448 if( !m_editPoints || !m_editedPoint || !m_editPoints->GetParent()->IsType( { SCH_SHAPE_T, SCH_RULE_AREA_T } ) )
1449 return 0;
1450
1451 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1452 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1453 SCH_COMMIT commit( m_toolMgr );
1454
1455 if( m_editPoints->GetParent()->Type() == SCH_SHAPE_T && poly.GetPointCount() <= 2 )
1456 return 0;
1457 if( m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T && poly.GetPointCount() <= 3 )
1458 return 0;
1459
1460 commit.Modify( shape, m_frame->GetScreen() );
1461
1462 int idx = getEditedPointIndex();
1463 int last = (int) poly.GetPointCount() - 1;
1464
1465 if( idx == 0 && poly.GetPoint( 0 ) == poly.GetPoint( last ) )
1466 {
1467 poly.Remove( idx );
1468 poly.SetPoint( last-1, poly.GetPoint( 0 ) );
1469 }
1470 else
1471 {
1472 poly.Remove( idx );
1473 }
1474
1475 shape->SetHatchingDirty();
1476
1477 setEditedPoint( nullptr );
1478
1479 updateItem( shape, true );
1480 updatePoints();
1481
1482 commit.Push( _( "Remove Corner" ) );
1483 return 0;
1484}
1485
1486
1488{
1489 if( aEvent.Matches( ACTIONS::cycleArcEditMode.MakeEvent() ) )
1490 {
1491 m_arcEditMode = m_frame->eeconfig()->m_Drawing.arc_edit_mode;
1493 }
1494 else
1495 {
1497 }
1498
1499 m_frame->eeconfig()->m_Drawing.arc_edit_mode = m_arcEditMode;
1500
1501 return 0;
1502}
1503
1504
1506{
1507 updatePoints();
1508 return 0;
1509}
1510
1511
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:114
constexpr double ARC_LOW_DEF_MM
Definition base_units.h:118
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:99
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:111
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition eda_item.h:198
bool IsNew() const
Definition eda_item.h:125
void SetStartX(int x)
Definition eda_shape.h:192
void SetEndY(int aY)
Definition eda_shape.h:227
void SetStartY(int y)
Definition eda_shape.h:185
SHAPE_POLY_SET & GetPolyShape()
Definition eda_shape.h:337
SHAPE_T GetShape() const
Definition eda_shape.h:169
void SetEndX(int aX)
Definition eda_shape.h:234
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:216
bool IsClosed() const
void SetEnd(const VECTOR2I &aEnd)
Definition eda_shape.h:220
wxString SHAPE_T_asString() const
void SetHatchingDirty()
Definition eda_shape.h:147
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:299
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition view.cpp:342
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:1700
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:472
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:88
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:254
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:86
VECTOR2I GetCenter() const
Definition sch_shape.h:88
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:85
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.
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:46
@ FRAME_SCH_SYMBOL_EDITOR
Definition frame_type.h:35
@ GRID_GRAPHICS
Definition grid_helper.h:52
@ LAYER_NOTES
Definition layer_ids.h:467
#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
@ MD_SHIFT
Definition tool_event.h:143
@ BUT_LEFT
Definition tool_event.h:132
@ SCH_LINE_T
Definition typeinfo.h:167
@ SCH_TABLECELL_T
Definition typeinfo.h:170
@ SCH_SHEET_T
Definition typeinfo.h:179
@ SCH_SHAPE_T
Definition typeinfo.h:153
@ SCH_RULE_AREA_T
Definition typeinfo.h:174
@ SCH_ITEM_LOCATE_GRAPHIC_LINE_T
Definition typeinfo.h:192
@ SCH_BITMAP_T
Definition typeinfo.h:168
@ SCH_TEXTBOX_T
Definition typeinfo.h:156
constexpr int sign(T val)
Definition util.h:145
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695