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, EDIT_POINTS& aPoints )
502 {
503 VECTOR2I topLeft = aPoints.Point( RECT_TOPLEFT ).GetPosition();
504 VECTOR2I topRight = aPoints.Point( RECT_TOPRIGHT ).GetPosition();
505 VECTOR2I botLeft = aPoints.Point( RECT_BOTLEFT ).GetPosition();
506 VECTOR2I botRight = aPoints.Point( RECT_BOTRIGHT ).GetPosition();
507
508 PinEditedCorner( aEditedPoint, aPoints, schIUScale.MilsToIU( 1 ), schIUScale.MilsToIU( 1 ),
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 {
735 m_textbox.ClearRenderCache();
736 }
737
738private:
740};
741
742
744{
745public:
747 m_sheet( aSheet ),
748 m_screen( aScreen )
749 {
750 m_noConnects = m_sheet.GetNoConnects();
751
752 // Find all wires connected to sheet pins and store their connections
753 for( SCH_SHEET_PIN* pin : m_sheet.GetPins() )
754 {
755 VECTOR2I pinPos = pin->GetPosition();
756
757 for( SCH_ITEM* item : m_screen.Items().Overlapping( SCH_LINE_T, pinPos ) )
758 {
759 SCH_LINE* line = static_cast<SCH_LINE*>( item );
760
761 if( !line->IsWire() && !line->IsBus() )
762 continue;
763
764 if( line->GetStartPoint() == pinPos )
765 m_connectedWires.push_back( { pin, line, STARTPOINT } );
766 else if( line->GetEndPoint() == pinPos )
767 m_connectedWires.push_back( { pin, line, ENDPOINT } );
768 }
769 }
770 }
771
772 void MakePoints( EDIT_POINTS& aPoints ) override
773 {
774 VECTOR2I topLeft = m_sheet.GetPosition();
775 VECTOR2I botRight = m_sheet.GetPosition() + m_sheet.GetSize();
776
777 aPoints.AddPoint( topLeft );
778 aPoints.AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
779 aPoints.AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
780 aPoints.AddPoint( botRight );
781
782 aPoints.AddLine( aPoints.Point( RECT_TOPLEFT ), aPoints.Point( RECT_TOPRIGHT ) );
783 aPoints.Line( RECT_TOP ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_TOP ) ) );
784 aPoints.AddLine( aPoints.Point( RECT_TOPRIGHT ), aPoints.Point( RECT_BOTRIGHT ) );
785 aPoints.Line( RECT_RIGHT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_RIGHT ) ) );
786 aPoints.AddLine( aPoints.Point( RECT_BOTRIGHT ), aPoints.Point( RECT_BOTLEFT ) );
787 aPoints.Line( RECT_BOT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_BOT ) ) );
788 aPoints.AddLine( aPoints.Point( RECT_BOTLEFT ), aPoints.Point( RECT_TOPLEFT ) );
789 aPoints.Line( RECT_LEFT ).SetConstraint( new EC_PERPLINE( aPoints.Line( RECT_LEFT ) ) );
790 }
791
792 bool UpdatePoints( EDIT_POINTS& aPoints ) override
793 {
794 VECTOR2I topLeft = m_sheet.GetPosition();
795 VECTOR2I botRight = m_sheet.GetPosition() + m_sheet.GetSize();
796
797 aPoints.Point( RECT_TOPLEFT ).SetPosition( topLeft );
798 aPoints.Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
799 aPoints.Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
800 aPoints.Point( RECT_BOTRIGHT ).SetPosition( botRight );
801 return true;
802 }
803
804 void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
805 std::vector<EDA_ITEM*>& aUpdatedItems ) override
806 {
807 VECTOR2I topLeft = aPoints.Point( RECT_TOPLEFT ).GetPosition();
808 VECTOR2I topRight = aPoints.Point( RECT_TOPRIGHT ).GetPosition();
809 VECTOR2I botLeft = aPoints.Point( RECT_BOTLEFT ).GetPosition();
810 VECTOR2I botRight = aPoints.Point( RECT_BOTRIGHT ).GetPosition();
811 VECTOR2I sheetNewPos = m_sheet.GetPosition();
812 VECTOR2I sheetNewSize = m_sheet.GetSize();
813
814 bool editedTopRight = isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) );
815 bool editedBotLeft = isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) );
816 bool editedBotRight = isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) );
817
818 if( isModified( aEditedPoint, aPoints.Line( RECT_RIGHT ) ) )
819 editedTopRight = true;
820 else if( isModified( aEditedPoint, aPoints.Line( RECT_BOT ) ) )
821 editedBotLeft = true;
822
824 aEditedPoint, aPoints, m_sheet.GetMinWidth( editedTopRight || editedBotRight ),
825 m_sheet.GetMinHeight( editedBotLeft || editedBotRight ), topLeft, topRight, botLeft,
826 botRight );
827
828 if( isModified( aEditedPoint, aPoints.Point( RECT_TOPLEFT ) )
829 || isModified( aEditedPoint, aPoints.Point( RECT_TOPRIGHT ) )
830 || isModified( aEditedPoint, aPoints.Point( RECT_BOTRIGHT ) )
831 || isModified( aEditedPoint, aPoints.Point( RECT_BOTLEFT ) ) )
832 {
833 sheetNewPos = topLeft;
834 sheetNewSize = VECTOR2I( botRight.x - topLeft.x, botRight.y - topLeft.y );
835 }
836 else if( isModified( aEditedPoint, aPoints.Line( RECT_TOP ) ) )
837 {
838 sheetNewPos = VECTOR2I( m_sheet.GetPosition().x, topLeft.y );
839 sheetNewSize = VECTOR2I( m_sheet.GetSize().x, botRight.y - topLeft.y );
840 }
841 else if( isModified( aEditedPoint, aPoints.Line( RECT_LEFT ) ) )
842 {
843 sheetNewPos = VECTOR2I( topLeft.x, m_sheet.GetPosition().y );
844 sheetNewSize = VECTOR2I( botRight.x - topLeft.x, m_sheet.GetSize().y );
845 }
846 else if( isModified( aEditedPoint, aPoints.Line( RECT_BOT ) ) )
847 {
848 sheetNewSize = VECTOR2I( m_sheet.GetSize().x, botRight.y - topLeft.y );
849 }
850 else if( isModified( aEditedPoint, aPoints.Line( RECT_RIGHT ) ) )
851 {
852 sheetNewSize = VECTOR2I( botRight.x - topLeft.x, m_sheet.GetSize().y );
853 }
854
855 for( unsigned i = 0; i < aPoints.LinesSize(); ++i )
856 {
857 if( !isModified( aEditedPoint, aPoints.Line( i ) ) )
858 {
859 aPoints.Line( i ).SetConstraint( new EC_PERPLINE( aPoints.Line( i ) ) );
860 }
861 }
862
863 if( m_sheet.GetPosition() != sheetNewPos )
864 m_sheet.SetPositionIgnoringPins( sheetNewPos );
865
866 if( m_sheet.GetSize() != sheetNewSize )
867 m_sheet.Resize( sheetNewSize );
868
869 // Update no-connects to follow their sheet pins
870 for( auto& [sheetPin, noConnect] : m_noConnects )
871 {
872 if( noConnect->GetPosition() != sheetPin->GetTextPos() )
873 {
874 aCommit.Modify( noConnect, &m_screen );
875 noConnect->SetPosition( sheetPin->GetTextPos() );
876 aUpdatedItems.push_back( noConnect );
877 }
878 }
879
880 // Update connected wires to follow their sheet pins
881 for( auto& [pin, line, endpoint] : m_connectedWires )
882 {
883 VECTOR2I newPinPos = pin->GetPosition();
884 bool needsUpdate = false;
885
886 if( endpoint == STARTPOINT && line->GetStartPoint() != newPinPos )
887 needsUpdate = true;
888 else if( endpoint == ENDPOINT && line->GetEndPoint() != newPinPos )
889 needsUpdate = true;
890
891 if( needsUpdate )
892 {
893 aCommit.Modify( line, &m_screen );
894
895 if( endpoint == STARTPOINT )
896 line->SetStartPoint( newPinPos );
897 else
898 line->SetEndPoint( newPinPos );
899
900 aUpdatedItems.push_back( line );
901 }
902 }
903 }
904
905private:
908 std::map<SCH_SHEET_PIN*, SCH_NO_CONNECT*> m_noConnects;
909 std::vector<std::tuple<SCH_SHEET_PIN*, SCH_LINE*, int>> m_connectedWires;
910};
911
912
914{
915 m_editBehavior = nullptr;
916 m_editPoints = std::make_shared<EDIT_POINTS>( aItem );
917
918 if( !aItem )
919 return;
920
921 // Generate list of edit points based on the item type
922 switch( aItem->Type() )
923 {
924 case SCH_SHAPE_T:
925 {
926 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
927
928 switch( shape->GetShape() )
929 {
930 case SHAPE_T::ARC:
931 m_editBehavior = std::make_unique<EDA_ARC_POINT_EDIT_BEHAVIOR>(
932 *shape, m_arcEditMode, *getViewControls() );
933 break;
934 case SHAPE_T::CIRCLE:
935 m_editBehavior = std::make_unique<EDA_CIRCLE_POINT_EDIT_BEHAVIOR>( *shape );
936 break;
938 m_editBehavior = std::make_unique<RECTANGLE_POINT_EDIT_BEHAVIOR>( *shape, *m_frame );
939 break;
940 case SHAPE_T::POLY:
941 m_editBehavior = std::make_unique<EDA_POLYGON_POINT_EDIT_BEHAVIOR>( *shape );
942 break;
943 case SHAPE_T::BEZIER:
944 {
945 int maxError = schIUScale.mmToIU( ARC_LOW_DEF_MM );
946
947 if( SCHEMATIC* schematic = shape->Schematic() )
948 maxError = schematic->Settings().m_MaxError;
949
950 m_editBehavior = std::make_unique<EDA_BEZIER_POINT_EDIT_BEHAVIOR>( *shape, maxError );
951 break;
952 }
953 default:
955 }
956
957 break;
958 }
959 case SCH_RULE_AREA_T:
960 {
961 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
962 // Implemented directly as a polygon
963 m_editBehavior = std::make_unique<EDA_POLYGON_POINT_EDIT_BEHAVIOR>( *shape );
964 break;
965 }
966 case SCH_TEXTBOX_T:
967 {
968 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( aItem );
969 m_editBehavior = std::make_unique<TEXTBOX_POINT_EDIT_BEHAVIOR>( *textbox );
970 break;
971 }
972 case SCH_TABLECELL_T:
973 {
974 SCH_TABLECELL* cell = static_cast<SCH_TABLECELL*>( aItem );
975 m_editBehavior = std::make_unique<SCH_TABLECELL_POINT_EDIT_BEHAVIOR>( *cell, *m_frame->GetScreen() );
976 break;
977 }
978 case SCH_SHEET_T:
979 {
980 SCH_SHEET& sheet = static_cast<SCH_SHEET&>( *aItem );
981 m_editBehavior = std::make_unique<SHEET_POINT_EDIT_BEHAVIOR>( sheet, *m_frame->GetScreen() );
982 break;
983 }
984 case SCH_BITMAP_T:
985 {
986 SCH_BITMAP& bitmap = static_cast<SCH_BITMAP&>( *aItem );
987 m_editBehavior = std::make_unique<BITMAP_POINT_EDIT_BEHAVIOR>( bitmap );
988 break;
989 }
990 case SCH_LINE_T:
991 {
992 SCH_LINE& line = static_cast<SCH_LINE&>( *aItem );
993 m_editBehavior = std::make_unique<LINE_POINT_EDIT_BEHAVIOR>( line, *m_frame->GetScreen() );
994 break;
995 }
996 default:
997 {
998 m_editPoints.reset();
999 break;
1000 }
1001 }
1002
1003 // If we got a behavior, generate the points
1004 if( m_editBehavior )
1005 {
1006 wxCHECK( m_editPoints, /* void */ );
1007 m_editBehavior->MakePoints( *m_editPoints );
1008 }
1009}
1010
1011
1019
1020
1022{
1023 SCH_TOOL_BASE::Reset( aReason );
1024
1025 if( KIGFX::VIEW* view = getView() )
1026 {
1027 if( m_angleItem )
1028 view->Remove( m_angleItem.get() );
1029
1030 if( m_editPoints )
1031 view->Remove( m_editPoints.get() );
1032 }
1033
1034 m_angleItem.reset();
1035 m_editPoints.reset();
1036 m_editedPoint = nullptr;
1037}
1038
1039
1041{
1042 using S_C = SELECTION_CONDITIONS;
1043
1045
1046 const auto addCornerCondition = [&]( const SELECTION& aSelection ) -> bool
1047 {
1048 return SCH_POINT_EDITOR::addCornerCondition( aSelection );
1049 };
1050
1051 const auto removeCornerCondition = [&]( const SELECTION& aSelection ) -> bool
1052 {
1053 return SCH_POINT_EDITOR::removeCornerCondition( aSelection );
1054 };
1055
1056 const auto arcIsEdited = [&]( const SELECTION& aSelection ) -> bool
1057 {
1058 const EDA_ITEM* item = aSelection.Front();
1059 return ( item != nullptr ) && ( item->Type() == SCH_SHAPE_T )
1060 && static_cast<const SCH_SHAPE*>( item )->GetShape() == SHAPE_T::ARC;
1061 };
1062
1063 auto& menu = m_selectionTool->GetToolMenu().GetMenu();
1064
1065 // clang-format off
1068 menu.AddItem( ACTIONS::cycleArcEditMode, S_C::Count( 1 ) && arcIsEdited );
1069 // clang-format on
1070
1071 return true;
1072}
1073
1074
1076{
1077 setEditedPoint( nullptr );
1078
1079 return 0;
1080}
1081
1082
1084{
1085 EDIT_POINT* point = m_editedPoint;
1086
1087 if( !m_editPoints )
1088 {
1089 point = nullptr;
1090 }
1091 else if( aEvent.IsMotion() )
1092 {
1093 point = m_editPoints->FindPoint( aEvent.Position(), getView() );
1094 }
1095 else if( aEvent.IsDrag( BUT_LEFT ) )
1096 {
1097 point = m_editPoints->FindPoint( aEvent.DragOrigin(), getView() );
1098 }
1099 else
1100 {
1101 point = m_editPoints->FindPoint( getViewControls()->GetCursorPosition( false ), getView() );
1102 }
1103
1104 if( m_editedPoint != point )
1105 setEditedPoint( point );
1106}
1107
1108
1110{
1111 if( !m_selectionTool )
1112 return 0;
1113
1114 if( m_inPointEditor )
1115 return 0;
1116
1118
1119 if( m_isSymbolEditor )
1120 {
1122
1123 if( !editor->IsSymbolEditable() || editor->IsSymbolAlias() )
1124 return 0;
1125 }
1126
1127 const SCH_SELECTION& selection = m_selectionTool->GetSelection();
1128
1129 if( selection.Size() != 1 || !selection.Front()->IsType( pointEditorTypes ) )
1130 return 0;
1131
1132 // Wait till drawing tool is done
1133 if( selection.Front()->IsNew() )
1134 return 0;
1135
1136 Activate();
1137
1140 VECTOR2I cursorPos;
1141 KIGFX::VIEW* view = getView();
1142 EDA_ITEM* item = selection.Front();
1143 SCH_COMMIT commit( m_toolMgr );
1144
1145 controls->ShowCursor( true );
1146
1147 makePointsAndBehavior( item );
1148 m_angleItem = std::make_unique<KIGFX::PREVIEW::ANGLE_ITEM>( m_editPoints );
1149 view->Add( m_editPoints.get() );
1150 view->Add( m_angleItem.get() );
1151 setEditedPoint( nullptr );
1152 updateEditedPoint( aEvent );
1153 bool inDrag = false;
1154
1155 // Main loop: keep receiving events
1156 while( TOOL_EVENT* evt = Wait() )
1157 {
1158 if( grid )
1159 {
1160 grid->SetSnap( !evt->Modifier( MD_SHIFT ) );
1161 grid->SetUseGrid( getView()->GetGAL()->GetGridSnapping()
1162 && !evt->DisableGridSnapping() );
1163 }
1164 else
1165 {
1166 // This check is based on the assumption that the grid object must be valid.
1167 // If this assumption is wrong, please fix the code above.
1168 wxCHECK( false, 0 );
1169 }
1170
1171 if( !m_editPoints || evt->IsSelectionEvent() )
1172 break;
1173
1174 if ( !inDrag )
1175 updateEditedPoint( *evt );
1176
1177 if( evt->IsDrag( BUT_LEFT ) && m_editedPoint )
1178 {
1179 if( !inDrag )
1180 {
1181 commit.Modify( m_editPoints->GetParent(), m_frame->GetScreen() );
1182
1183 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( item ) )
1184 {
1185 shape->SetFlags( IS_MOVING );
1186 shape->SetHatchingDirty();
1187 shape->UpdateHatching();
1188 }
1189
1190 inDrag = true;
1191 }
1192
1193 bool snap = !evt->DisableGridSnapping();
1194
1195 cursorPos = grid->Align( controls->GetMousePosition(),
1197 controls->ForceCursorPosition( true, cursorPos );
1198
1199 m_editedPoint->SetPosition( controls->GetCursorPosition( snap ) );
1200
1201 updateParentItem( snap, commit );
1202 updatePoints();
1203 }
1204 else if( inDrag && evt->IsMouseUp( BUT_LEFT ) )
1205 {
1206 if( !commit.Empty() )
1207 commit.Push( _( "Move Point" ) );
1208
1209 controls->SetAutoPan( false );
1210
1211 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( item ) )
1212 {
1213 shape->ClearFlags( IS_MOVING );
1214 shape->SetHatchingDirty();
1215 shape->UpdateHatching();
1216 }
1217
1218 inDrag = false;
1219 }
1220 else if( evt->IsCancelInteractive() || evt->IsActivate() )
1221 {
1222 if( inDrag ) // Restore the last change
1223 {
1224 // Currently we are manually managing the lifetime of the grid
1225 // helpers because there is a bug in the tool stack that adds
1226 // the point editor again when commit.Revert() rebuilds the selection.
1227 // We remove this grid here so the its destructor is called before it
1228 // is added again.
1229 if( grid )
1230 {
1231 delete grid;
1232 grid = nullptr;
1233 }
1234
1235 commit.Revert();
1236 inDrag = false;
1237 break;
1238 }
1239 else if( evt->IsCancelInteractive() )
1240 {
1241 break;
1242 }
1243
1244 if( evt->IsActivate() )
1245 break;
1246 }
1247 else
1248 {
1249 evt->SetPassEvent();
1250 }
1251
1252 controls->SetAutoPan( inDrag );
1253 controls->CaptureCursor( inDrag );
1254 }
1255
1256 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( item ) )
1257 {
1258 shape->ClearFlags( IS_MOVING );
1259 shape->SetHatchingDirty();
1260 shape->UpdateHatching();
1261 }
1262
1263 controls->SetAutoPan( false );
1264 controls->CaptureCursor( false );
1265 setEditedPoint( nullptr );
1266
1267 if( m_editPoints )
1268 {
1269 view->Remove( m_editPoints.get() );
1270 view->Remove( m_angleItem.get() );
1271
1272 m_editPoints.reset();
1273 m_angleItem.reset();
1274 m_frame->GetCanvas()->Refresh();
1275 }
1276
1277 delete grid;
1278
1279 return 0;
1280}
1281
1282
1283void SCH_POINT_EDITOR::updateParentItem( bool aSnapToGrid, SCH_COMMIT& aCommit ) const
1284{
1285 EDA_ITEM* item = m_editPoints->GetParent();
1286
1287 if( !item )
1288 return;
1289
1290 if( !m_editBehavior )
1291 return;
1292
1293 std::vector<EDA_ITEM*> updatedItems;
1294 m_editBehavior->UpdateItem( *m_editedPoint, *m_editPoints, aCommit, updatedItems );
1295
1296 for( EDA_ITEM* updatedItem : updatedItems )
1297 updateItem( updatedItem, true );
1298
1299 m_frame->SetMsgPanel( item );
1300}
1301
1302
1304{
1305 if( !m_editPoints || !m_editBehavior )
1306 return;
1307
1308 // Careful; the unit and/or body style may have changed out from under us, meaning the item is no
1309 // longer present on the canvas.
1310 if( m_isSymbolEditor )
1311 {
1313 SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( m_editPoints->GetParent() );
1314
1315 if( ( item && item->GetUnit() != 0 && item->GetUnit() != editor->GetUnit() )
1316 || ( item && item->GetBodyStyle() != 0 && item->GetBodyStyle() != editor->GetBodyStyle() ) )
1317 {
1318 getView()->Remove( m_editPoints.get() );
1319 getView()->Remove( m_angleItem.get() );
1320 m_editPoints.reset();
1321 m_angleItem.reset();
1322 return;
1323 }
1324 }
1325
1326 m_editBehavior->UpdatePoints( *m_editPoints );
1327 getView()->Update( m_editPoints.get() );
1328 getView()->Update( m_angleItem.get() );
1329}
1330
1331
1333{
1335
1336 if( aPoint )
1337 {
1338 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1339 controls->ForceCursorPosition( true, aPoint->GetPosition() );
1340 controls->ShowCursor( true );
1341 }
1342 else
1343 {
1344 if( m_frame->ToolStackIsEmpty() )
1345 controls->ShowCursor( false );
1346
1347 controls->ForceCursorPosition( false );
1348 }
1349
1350 m_editedPoint = aPoint;
1351}
1352
1353
1355{
1356 if( !m_editPoints || !m_editedPoint || !m_editPoints->GetParent()->IsType( { SCH_SHAPE_T, SCH_RULE_AREA_T } ) )
1357 return false;
1358
1359 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1360
1361 if( shape->GetPolyShape().IsEmpty() )
1362 return false;
1363
1364 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1365
1366 if( m_editPoints->GetParent()->Type() == SCH_SHAPE_T && poly.GetPointCount() <= 2 )
1367 return false;
1368 if( m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T && poly.GetPointCount() <= 3 )
1369 return false;
1370
1371 for( const VECTOR2I& pt : poly.CPoints() )
1372 {
1373 if( pt == m_editedPoint->GetPosition() )
1374 return true;
1375 }
1376
1377 return false;
1378}
1379
1380
1382{
1383 if( !m_editPoints || !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->GetShape() != SHAPE_T::POLY )
1389 return false;
1390
1391 VECTOR2I cursorPos = getViewControls()->GetCursorPosition( false );
1392 double threshold = getView()->ToWorld( EDIT_POINT::POINT_SIZE );
1393
1394 return shape->HitTest( cursorPos, (int) threshold );
1395}
1396
1397
1399{
1400 if( !m_editPoints || !m_editPoints->GetParent()->IsType( { SCH_SHAPE_T, SCH_RULE_AREA_T } ) )
1401 return 0;
1402
1403 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1404 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1405 SCH_COMMIT commit( m_toolMgr );
1406
1407 commit.Modify( shape, m_frame->GetScreen() );
1408
1410 int currentMinDistance = INT_MAX;
1411 int closestLineStart = 0;
1412 unsigned numPoints = poly.GetPointCount();
1413
1414 if( !shape->IsClosed() )
1415 numPoints -= 1;
1416
1417 for( unsigned i = 0; i < numPoints; ++i )
1418 {
1419 SEG seg = poly.GetSegment( i );
1420 int distance = seg.Distance( cursor );
1421
1422 if( distance < currentMinDistance )
1423 {
1424 currentMinDistance = distance;
1425 closestLineStart = i;
1426 }
1427 }
1428
1429 poly.Insert( closestLineStart + 1, cursor );
1430
1431 updateItem( shape, true );
1432 updatePoints();
1433
1434 commit.Push( _( "Add Corner" ) );
1435 return 0;
1436}
1437
1438
1440{
1441 if( !m_editPoints || !m_editedPoint || !m_editPoints->GetParent()->IsType( { SCH_SHAPE_T, SCH_RULE_AREA_T } ) )
1442 return 0;
1443
1444 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1445 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1446 SCH_COMMIT commit( m_toolMgr );
1447
1448 if( m_editPoints->GetParent()->Type() == SCH_SHAPE_T && poly.GetPointCount() <= 2 )
1449 return 0;
1450 if( m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T && poly.GetPointCount() <= 3 )
1451 return 0;
1452
1453 commit.Modify( shape, m_frame->GetScreen() );
1454
1455 int idx = getEditedPointIndex();
1456 int last = (int) poly.GetPointCount() - 1;
1457
1458 if( idx == 0 && poly.GetPoint( 0 ) == poly.GetPoint( last ) )
1459 {
1460 poly.Remove( idx );
1461 poly.SetPoint( last-1, poly.GetPoint( 0 ) );
1462 }
1463 else
1464 {
1465 poly.Remove( idx );
1466 }
1467
1468 shape->SetHatchingDirty();
1469
1470 setEditedPoint( nullptr );
1471
1472 updateItem( shape, true );
1473 updatePoints();
1474
1475 commit.Push( _( "Remove Corner" ) );
1476 return 0;
1477}
1478
1479
1481{
1482 if( aEvent.Matches( ACTIONS::cycleArcEditMode.MakeEvent() ) )
1483 {
1484 m_arcEditMode = m_frame->eeconfig()->m_Drawing.arc_edit_mode;
1486 }
1487 else
1488 {
1490 }
1491
1492 m_frame->eeconfig()->m_Drawing.arc_edit_mode = m_arcEditMode;
1493
1494 return 0;
1495}
1496
1497
1499{
1500 updatePoints();
1501 return 0;
1502}
1503
1504
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:98
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
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:124
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:66
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition view.cpp:298
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition view.cpp:341
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:1685
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:467
Define a library symbol object.
Definition lib_symbol.h:83
std::vector< 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)
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:167
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:247
int GetBodyStyle() const
Definition sch_item.h:247
int GetUnit() const
Definition sch_item.h:238
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
#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