KiCad PCB EDA Suite
Loading...
Searching...
No Matches
ee_point_editor.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2019 CERN
5 * Copyright (C) 2019-2023 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <functional>
26using namespace std::placeholders;
27
28#include "ee_point_editor.h"
29#include <ee_grid_helper.h>
30#include <tool/tool_manager.h>
31#include <sch_commit.h>
32#include <view/view_controls.h>
34#include <geometry/seg.h>
35#include <tools/ee_actions.h>
37#include <sch_edit_frame.h>
38#include <sch_line.h>
39#include <sch_bitmap.h>
40#include <sch_sheet.h>
41#include <sch_textbox.h>
42#include <sch_table.h>
43#include <sch_tablecell.h>
44#include <sch_shape.h>
45#include <symbol_edit_frame.h>
46
47
48// Few constants to avoid using bare numbers for point indices
50{
52};
53
54
56{
58};
59
60
62{
64};
65
66
68{
70};
71
73{
75};
76
78{
80};
81
82
84{
89};
90
91
93{
94public:
95 static std::shared_ptr<EDIT_POINTS> Make( EDA_ITEM* aItem, SCH_BASE_FRAME* frame )
96 {
97 std::shared_ptr<EDIT_POINTS> points = std::make_shared<EDIT_POINTS>( aItem );
98
99 if( !aItem )
100 return points;
101
102 // Generate list of edit points based on the item type
103 switch( aItem->Type() )
104 {
105 case SCH_SHAPE_T:
106 {
107 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
108 bool invertY = shape->GetLayer() == LAYER_DEVICE;
109
110 switch( shape->GetShape() )
111 {
112 case SHAPE_T::ARC:
113 points->AddPoint( mapCoords( shape->GetPosition(), invertY ) );
114 points->AddPoint( mapCoords( shape->GetStart(), invertY ) );
115 points->AddPoint( mapCoords( shape->GetEnd(), invertY ) );
116 break;
117
118 case SHAPE_T::CIRCLE:
119 points->AddPoint( mapCoords( shape->GetPosition(), invertY ) );
120 points->AddPoint( mapCoords( shape->GetEnd(), invertY ) );
121 break;
122
123 case SHAPE_T::RECTANGLE:
124 {
125 shape->Normalize();
126
127 VECTOR2I topLeft = mapCoords( shape->GetPosition(), invertY );
128 VECTOR2I botRight = mapCoords( shape->GetEnd(), invertY );
129
130 points->AddPoint( topLeft );
131 points->AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
132 points->AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
133 points->AddPoint( botRight );
134
135 points->AddLine( points->Point( RECT_TOPLEFT ), points->Point( RECT_TOPRIGHT ) );
136 points->Line( RECT_TOP ).SetConstraint( new EC_PERPLINE( points->Line( RECT_TOP ) ) );
137 points->AddLine( points->Point( RECT_TOPRIGHT ), points->Point( RECT_BOTRIGHT ) );
138 points->Line( RECT_RIGHT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_RIGHT ) ) );
139 points->AddLine( points->Point( RECT_BOTRIGHT ), points->Point( RECT_BOTLEFT ) );
140 points->Line( RECT_BOT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_BOT ) ) );
141 points->AddLine( points->Point( RECT_BOTLEFT ), points->Point( RECT_TOPLEFT ) );
142 points->Line( RECT_LEFT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_LEFT ) ) );
143
144 break;
145 }
146
147 case SHAPE_T::POLY:
148 for( const VECTOR2I& pt : shape->GetPolyShape().Outline( 0 ).CPoints() )
149 points->AddPoint( mapCoords( pt, invertY ) );
150
151 break;
152
153 case SHAPE_T::BEZIER:
154 points->AddPoint( mapCoords( shape->GetStart(), invertY ) );
155 points->AddPoint( mapCoords( shape->GetBezierC1(), invertY ) );
156 points->AddPoint( mapCoords( shape->GetBezierC2(), invertY ) );
157 points->AddPoint( mapCoords( shape->GetEnd(), invertY ) );
158 break;
159
160 default:
162 }
163
164 break;
165 }
166
167 case SCH_RULE_AREA_T:
168 {
169 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
170
171 for( const VECTOR2I& pt : shape->GetPolyShape().Outline( 0 ).CPoints() )
172 points->AddPoint( pt );
173
174 break;
175 }
176
177 case SCH_TEXTBOX_T:
178 {
179 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( aItem );
180 bool invertY = textbox->GetLayer() == LAYER_DEVICE;
181
182 textbox->Normalize();
183
184 VECTOR2I topLeft = mapCoords( textbox->GetPosition(), invertY );
185 VECTOR2I botRight = mapCoords( textbox->GetEnd(), invertY );
186
187 points->AddPoint( topLeft );
188 points->AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
189 points->AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
190 points->AddPoint( botRight );
191
192 points->AddLine( points->Point( RECT_TOPLEFT ), points->Point( RECT_TOPRIGHT ) );
193 points->Line( RECT_TOP ).SetConstraint( new EC_PERPLINE( points->Line( RECT_TOP ) ) );
194 points->AddLine( points->Point( RECT_TOPRIGHT ), points->Point( RECT_BOTRIGHT ) );
195 points->Line( RECT_RIGHT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_RIGHT ) ) );
196 points->AddLine( points->Point( RECT_BOTRIGHT ), points->Point( RECT_BOTLEFT ) );
197 points->Line( RECT_BOT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_BOT ) ) );
198 points->AddLine( points->Point( RECT_BOTLEFT ), points->Point( RECT_TOPLEFT ) );
199 points->Line( RECT_LEFT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_LEFT ) ) );
200
201 break;
202 }
203
204 case SCH_TABLECELL_T:
205 {
206 SCH_TABLECELL* cell = static_cast<SCH_TABLECELL*>( aItem );
207 points->AddPoint( cell->GetEnd() - VECTOR2I( 0, cell->GetRectangleHeight() / 2 ) );
208 points->AddPoint( cell->GetEnd() - VECTOR2I( cell->GetRectangleWidth() / 2, 0 ) );
209 break;
210 }
211
212 case SCH_SHEET_T:
213 {
214 SCH_SHEET* sheet = (SCH_SHEET*) aItem;
215 VECTOR2I topLeft = sheet->GetPosition();
216 VECTOR2I botRight = sheet->GetPosition() + sheet->GetSize();
217
218 points->AddPoint( topLeft );
219 points->AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
220 points->AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
221 points->AddPoint( botRight );
222
223 points->AddLine( points->Point( RECT_TOPLEFT ), points->Point( RECT_TOPRIGHT ) );
224 points->Line( RECT_TOP ).SetConstraint( new EC_PERPLINE( points->Line( RECT_TOP ) ) );
225 points->AddLine( points->Point( RECT_TOPRIGHT ), points->Point( RECT_BOTRIGHT ) );
226 points->Line( RECT_RIGHT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_RIGHT ) ) );
227 points->AddLine( points->Point( RECT_BOTRIGHT ), points->Point( RECT_BOTLEFT ) );
228 points->Line( RECT_BOT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_BOT ) ) );
229 points->AddLine( points->Point( RECT_BOTLEFT ), points->Point( RECT_TOPLEFT ) );
230 points->Line( RECT_LEFT ).SetConstraint( new EC_PERPLINE( points->Line( RECT_LEFT ) ) );
231
232 break;
233 }
234
235 case SCH_BITMAP_T:
236 {
237 SCH_BITMAP* bitmap = (SCH_BITMAP*) aItem;
238 VECTOR2I topLeft = bitmap->GetPosition() - bitmap->GetSize() / 2;
239 VECTOR2I botRight = bitmap->GetPosition() + bitmap->GetSize() / 2;
240
241 points->AddPoint( topLeft );
242 points->AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
243 points->AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
244 points->AddPoint( botRight );
245 break;
246 }
247
248 case SCH_LINE_T:
249 {
250 SCH_LINE* line = (SCH_LINE*) aItem;
251 std::pair<EDA_ITEM*, int> connectedStart = { nullptr, STARTPOINT };
252 std::pair<EDA_ITEM*, int> connectedEnd = { nullptr, STARTPOINT };
253
254 for( SCH_ITEM* test : frame->GetScreen()->Items().OfType( SCH_LINE_T ) )
255 {
256 if( test->GetLayer() != LAYER_NOTES )
257 continue;
258
259 if( test == aItem )
260 continue;
261
262 SCH_LINE* testLine = static_cast<SCH_LINE*>( test );
263
264 if( testLine->GetStartPoint() == line->GetStartPoint() )
265 {
266 connectedStart = { testLine, STARTPOINT };
267 }
268 else if( testLine->GetEndPoint() == line->GetStartPoint() )
269 {
270 connectedStart = { testLine, ENDPOINT };
271 }
272 else if( testLine->GetStartPoint() == line->GetEndPoint() )
273 {
274 connectedEnd = { testLine, STARTPOINT };
275 }
276 else if( testLine->GetEndPoint() == line->GetEndPoint() )
277 {
278 connectedEnd = { testLine, ENDPOINT };
279 }
280 }
281
282 points->AddPoint( line->GetStartPoint(), connectedStart );
283 points->AddPoint( line->GetEndPoint(), connectedEnd );
284 break;
285 }
286
287 default:
288 points.reset();
289 break;
290 }
291
292 return points;
293 }
294
295private:
297};
298
299
301 EE_TOOL_BASE<SCH_BASE_FRAME>( "eeschema.PointEditor" ),
302 m_editedPoint( nullptr ),
303 m_inPointEditor( false )
304{
305}
306
307
309{
310 EE_TOOL_BASE::Reset( aReason );
311
312 m_editPoints.reset();
313 m_editedPoint = nullptr;
314}
315
316
318{
320
321 auto& menu = m_selectionTool->GetToolMenu().GetMenu();
323 std::bind( &EE_POINT_EDITOR::addCornerCondition, this, _1 ) );
325 std::bind( &EE_POINT_EDITOR::removeCornerCondition, this, _1 ) );
326
327 return true;
328}
329
330
332{
333 setEditedPoint( nullptr );
334
335 return 0;
336}
337
338
340{
341 EDIT_POINT* point = m_editedPoint;
342
343 if( !m_editPoints )
344 {
345 point = nullptr;
346 }
347 else if( aEvent.IsMotion() )
348 {
349 point = m_editPoints->FindPoint( aEvent.Position(), getView() );
350 }
351 else if( aEvent.IsDrag( BUT_LEFT ) )
352 {
353 point = m_editPoints->FindPoint( aEvent.DragOrigin(), getView() );
354 }
355 else
356 {
357 point = m_editPoints->FindPoint( getViewControls()->GetCursorPosition( false ), getView() );
358 }
359
360 if( m_editedPoint != point )
361 setEditedPoint( point );
362}
363
364
366{
367 if( !m_selectionTool )
368 return 0;
369
370 if( m_inPointEditor )
371 return 0;
372
374
375 if( m_isSymbolEditor )
376 {
377 SYMBOL_EDIT_FRAME* editor = getEditFrame<SYMBOL_EDIT_FRAME>();
378
379 if( !editor->IsSymbolEditable() || editor->IsSymbolAlias() )
380 return 0;
381 }
382
383 const EE_SELECTION& selection = m_selectionTool->GetSelection();
384
385 if( selection.Size() != 1 || !selection.Front()->IsType( { SCH_SHAPE_T,
386 SCH_RULE_AREA_T,
387 SCH_TEXTBOX_T,
388 SCH_TABLECELL_T,
389 SCH_SHEET_T,
390 SCH_ITEM_LOCATE_GRAPHIC_LINE_T,
391 SCH_BITMAP_T } ) )
392 {
393 return 0;
394 }
395
396 // Wait till drawing tool is done
397 if( selection.Front()->IsNew() )
398 return 0;
399
400 Activate();
401
404 VECTOR2I cursorPos;
405 KIGFX::VIEW* view = getView();
406 EDA_ITEM* item = selection.Front();
407 SCH_COMMIT commit( m_toolMgr );
408
409 controls->ShowCursor( true );
410
412 view->Add( m_editPoints.get() );
413 setEditedPoint( nullptr );
414 updateEditedPoint( aEvent );
415 bool inDrag = false;
416
417 // Main loop: keep receiving events
418 while( TOOL_EVENT* evt = Wait() )
419 {
420 if( grid )
421 {
422 grid->SetSnap( !evt->Modifier( MD_SHIFT ) );
423 grid->SetUseGrid( getView()->GetGAL()->GetGridSnapping()
424 && !evt->DisableGridSnapping() );
425 }
426 else
427 {
428 // This check is based on the assumption that the grid object must be valid.
429 // If this assumption is wrong, please fix the code above.
430 wxCHECK( false, 0 );
431 }
432
433 if( !m_editPoints || evt->IsSelectionEvent() )
434 break;
435
436 if ( !inDrag )
437 updateEditedPoint( *evt );
438
439 if( evt->IsDrag( BUT_LEFT ) && m_editedPoint )
440 {
441 if( !inDrag )
442 {
443 commit.Modify( m_editPoints->GetParent(), m_frame->GetScreen() );
444
445 if( m_editPoints->GetParent()->Type() == SCH_LINE_T )
446 {
447 std::pair<EDA_ITEM*, int> connected = m_editPoints->Point( LINE_START ).GetConnected();
448
449 if( connected.first )
450 commit.Modify( connected.first, m_frame->GetScreen() );
451
452 connected = m_editPoints->Point( LINE_END ).GetConnected();
453
454 if( connected.first )
455 commit.Modify( connected.first, m_frame->GetScreen() );
456 }
457 else if( m_editPoints->GetParent()->Type() == SCH_TABLECELL_T )
458 {
459 SCH_TABLECELL* cell = static_cast<SCH_TABLECELL*>( m_editPoints->GetParent() );
460 SCH_TABLE* table = static_cast<SCH_TABLE*>( cell->GetParent() );
461
462 commit.Modify( table, m_frame->GetScreen() );
463 }
464
465 inDrag = true;
466 }
467
468 bool snap = !evt->DisableGridSnapping();
469
470 cursorPos =
471 grid->Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
472 controls->ForceCursorPosition( true, cursorPos );
473
474 m_editedPoint->SetPosition( controls->GetCursorPosition( snap ) );
475
476 updateParentItem( snap );
477 updatePoints();
478 }
479 else if( inDrag && evt->IsMouseUp( BUT_LEFT ) )
480 {
481 if( !commit.Empty() )
482 commit.Push( _( "Move Point" ) );
483
484 controls->SetAutoPan( false );
485 inDrag = false;
486 }
487 else if( evt->IsCancelInteractive() || evt->IsActivate() )
488 {
489 if( inDrag ) // Restore the last change
490 {
491 // Currently we are manually managing the lifetime of the grid
492 // helpers because there is a bug in the tool stack that adds
493 // the point editor again when commit.Revert() rebuilds the selection.
494 // We remove this grid here so the its destructor is called before it
495 // is added again.
496 if( grid )
497 {
498 delete grid;
499 grid = nullptr;
500 }
501
502 commit.Revert();
503 inDrag = false;
504 break;
505 }
506 else if( evt->IsCancelInteractive() )
507 {
508 break;
509 }
510
511 if( evt->IsActivate() )
512 break;
513 }
514 else
515 {
516 evt->SetPassEvent();
517 }
518
519 controls->SetAutoPan( inDrag );
520 controls->CaptureCursor( inDrag );
521 }
522
523 controls->SetAutoPan( false );
524 controls->CaptureCursor( false );
525 setEditedPoint( nullptr );
526
527 if( m_editPoints )
528 {
529 view->Remove( m_editPoints.get() );
530
531 m_editPoints.reset();
533 }
534
535 delete grid;
536
537 return 0;
538}
539
550void EE_POINT_EDITOR::pinEditedCorner( int minWidth, int minHeight, VECTOR2I& topLeft,
551 VECTOR2I& topRight, VECTOR2I& botLeft, VECTOR2I& botRight,
552 EE_GRID_HELPER* aGrid ) const
553{
554 if( isModified( m_editPoints->Point( RECT_TOPLEFT ) ) )
555 {
556 // pin edited point within opposite corner
557 topLeft.x = std::min( topLeft.x, botRight.x - minWidth );
558 topLeft.y = std::min( topLeft.y, botRight.y - minHeight );
559
560 if( aGrid->GetSnap() )
561 topLeft = aGrid->AlignGrid( topLeft, GRID_HELPER_GRIDS::GRID_GRAPHICS );
562
563 // push edited point edges to adjacent corners
564 topRight.y = topLeft.y;
565 botLeft.x = topLeft.x;
566 }
567 else if( isModified( m_editPoints->Point( RECT_TOPRIGHT ) ) )
568 {
569 // pin edited point within opposite corner
570 topRight.x = std::max( topRight.x, botLeft.x + minWidth );
571 topRight.y = std::min( topRight.y, botLeft.y - minHeight );
572
573 if( aGrid->GetSnap() )
574 topRight = aGrid->AlignGrid( topRight, GRID_HELPER_GRIDS::GRID_GRAPHICS );
575
576 // push edited point edges to adjacent corners
577 topLeft.y = topRight.y;
578 botRight.x = topRight.x;
579 }
580 else if( isModified( m_editPoints->Point( RECT_BOTLEFT ) ) )
581 {
582 // pin edited point within opposite corner
583 botLeft.x = std::min( botLeft.x, topRight.x - minWidth );
584 botLeft.y = std::max( botLeft.y, topRight.y + minHeight );
585
586 if( aGrid->GetSnap() )
587 botLeft = aGrid->AlignGrid( botLeft, GRID_HELPER_GRIDS::GRID_GRAPHICS );
588
589 // push edited point edges to adjacent corners
590 botRight.y = botLeft.y;
591 topLeft.x = botLeft.x;
592 }
593 else if( isModified( m_editPoints->Point( RECT_BOTRIGHT ) ) )
594 {
595 // pin edited point within opposite corner
596 botRight.x = std::max( botRight.x, topLeft.x + minWidth );
597 botRight.y = std::max( botRight.y, topLeft.y + minHeight );
598
599 if( aGrid->GetSnap() )
600 botRight = aGrid->AlignGrid( botRight, GRID_HELPER_GRIDS::GRID_GRAPHICS );
601
602 // push edited point edges to adjacent corners
603 botLeft.y = botRight.y;
604 topRight.x = botRight.x;
605 }
606 else if( isModified( m_editPoints->Line( RECT_TOP ) ) )
607 {
608 topLeft.y = std::min( topLeft.y, botRight.y - minHeight );
609
610 if( aGrid->GetSnap() )
611 topLeft = aGrid->AlignGrid( topLeft, GRID_HELPER_GRIDS::GRID_GRAPHICS );
612 }
613 else if( isModified( m_editPoints->Line( RECT_LEFT ) ) )
614 {
615 topLeft.x = std::min( topLeft.x, botRight.x - minWidth );
616
617 if( aGrid->GetSnap() )
618 topLeft = aGrid->AlignGrid( topLeft, GRID_HELPER_GRIDS::GRID_GRAPHICS );
619 }
620 else if( isModified( m_editPoints->Line( RECT_BOT ) ) )
621 {
622 botRight.y = std::max( botRight.y, topLeft.y + minHeight );
623
624 if( aGrid->GetSnap() )
625 botRight = aGrid->AlignGrid( botRight, GRID_HELPER_GRIDS::GRID_GRAPHICS );
626 }
627 else if( isModified( m_editPoints->Line( RECT_RIGHT ) ) )
628 {
629 botRight.x = std::max( botRight.x, topLeft.x + minWidth );
630
631 if( aGrid->GetSnap() )
632 botRight = aGrid->AlignGrid( botRight, GRID_HELPER_GRIDS::GRID_GRAPHICS );
633 }
634}
635
636
637void EE_POINT_EDITOR::updateParentItem( bool aSnapToGrid ) const
638{
639 EDA_ITEM* item = m_editPoints->GetParent();
640
641 if( !item )
642 return;
643
644 switch( item->Type() )
645 {
646 case SCH_RULE_AREA_T:
647 case SCH_SHAPE_T:
648 {
649 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( item );
650 bool invertY = shape->GetLayer() == LAYER_DEVICE;
651
652 switch( shape->GetShape() )
653 {
654 case SHAPE_T::ARC:
656 {
657 shape->SetEditState( 4 );
658 shape->CalcEdit( mapCoords( m_editPoints->Point( ARC_CENTER ).GetPosition(), invertY ) );
659 }
660 else if( getEditedPointIndex() == ARC_START )
661 {
662 shape->SetEditState( 2 );
663 shape->CalcEdit( mapCoords( m_editPoints->Point( ARC_START ).GetPosition(), invertY ) );
664 }
665 else if( getEditedPointIndex() == ARC_END )
666 {
667 shape->SetEditState( 3 );
668 shape->CalcEdit( mapCoords( m_editPoints->Point( ARC_END ).GetPosition(), invertY ) );
669 }
670 break;
671
672 case SHAPE_T::CIRCLE:
673 shape->SetPosition( mapCoords( m_editPoints->Point( CIRC_CENTER ).GetPosition(), invertY ) );
674 shape->SetEnd( mapCoords( m_editPoints->Point( CIRC_END ).GetPosition(), invertY ) );
675 break;
676
677 case SHAPE_T::POLY:
679 shape->GetPolyShape().NewOutline();
680
681 for( unsigned i = 0; i < m_editPoints->PointsSize(); ++i )
682 {
683 VECTOR2I pt = mapCoords( m_editPoints->Point( i ).GetPosition(), invertY );
684 shape->GetPolyShape().Append( pt.x, pt.y, -1, -1, true );
685 }
686
687 break;
688
689 case SHAPE_T::RECTANGLE:
690 {
691 EE_GRID_HELPER gridHelper( m_toolMgr );
692 VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
693 VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
694 VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
695 VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
696
697 gridHelper.SetSnap( aSnapToGrid );
698
699 pinEditedCorner( schIUScale.MilsToIU( 1 ), schIUScale.MilsToIU( 1 ), topLeft, topRight,
700 botLeft, botRight, &gridHelper );
701
702 if( isModified( m_editPoints->Point( RECT_TOPLEFT ) )
705 || isModified( m_editPoints->Point( RECT_BOTLEFT ) ) )
706 {
707 shape->SetPosition( mapCoords( topLeft, invertY ) );
708 shape->SetEnd( mapCoords( botRight, invertY ) );
709 }
710 else if( isModified( m_editPoints->Line( RECT_TOP ) ) )
711 {
712 shape->SetStartY( mapCoords( topLeft, invertY ).y );
713 }
714 else if( isModified( m_editPoints->Line( RECT_LEFT ) ) )
715 {
716 shape->SetStartX( mapCoords( topLeft, invertY ).x );
717 }
718 else if( isModified( m_editPoints->Line( RECT_BOT ) ) )
719 {
720 shape->SetEndY( mapCoords( botRight, invertY ).y );
721 }
722 else if( isModified( m_editPoints->Line( RECT_RIGHT ) ) )
723 {
724 shape->SetEndX( mapCoords( botRight, invertY ).x );
725 }
726
727 for( unsigned i = 0; i < m_editPoints->LinesSize(); ++i )
728 {
729 if( !isModified( m_editPoints->Line( i ) ) )
730 {
731 m_editPoints->Line( i ).SetConstraint(
732 new EC_PERPLINE( m_editPoints->Line( i ) ) );
733 }
734 }
735
736 break;
737 }
738
739 case SHAPE_T::BEZIER:
740 shape->SetStart( mapCoords( m_editPoints->Point( BEZIER_START ).GetPosition(), invertY ) );
741 shape->SetBezierC1( mapCoords( m_editPoints->Point( BEZIER_CTRL_PT1 ).GetPosition(), invertY ) );
742 shape->SetBezierC2( mapCoords( m_editPoints->Point( BEZIER_CTRL_PT2 ).GetPosition(), invertY ) );
743 shape->SetEnd( mapCoords( m_editPoints->Point( BEZIER_END ).GetPosition(), invertY ) );
744
746 break;
747
748 default:
750 }
751
752 break;
753 }
754
755 case SCH_TEXTBOX_T:
756 {
757 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( item );
758 bool invertY = textbox->GetLayer() == LAYER_DEVICE;
759 EE_GRID_HELPER gridHelper( m_toolMgr );
760 VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
761 VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
762 VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
763 VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
764
765 gridHelper.SetSnap( aSnapToGrid );
766
767 pinEditedCorner( schIUScale.MilsToIU( 1 ), schIUScale.MilsToIU( 1 ), topLeft, topRight,
768 botLeft, botRight, &gridHelper );
769
770 if( isModified( m_editPoints->Point( RECT_TOPLEFT ) )
773 || isModified( m_editPoints->Point( RECT_BOTLEFT ) ) )
774 {
775 textbox->SetPosition( mapCoords( topLeft, invertY ) );
776 textbox->SetEnd( mapCoords( botRight, invertY ) );
777 }
778 else if( isModified( m_editPoints->Line( RECT_TOP ) ) )
779 {
780 textbox->SetStartY( mapCoords( topLeft, invertY ).y );
781 }
782 else if( isModified( m_editPoints->Line( RECT_LEFT ) ) )
783 {
784 textbox->SetStartX( mapCoords( topLeft, invertY ).x );
785 }
786 else if( isModified( m_editPoints->Line( RECT_BOT ) ) )
787 {
788 textbox->SetEndY( mapCoords( botRight, invertY ).y );
789 }
790 else if( isModified( m_editPoints->Line( RECT_RIGHT ) ) )
791 {
792 textbox->SetEndX( mapCoords( botRight, invertY ).x );
793 }
794
795 for( unsigned i = 0; i < m_editPoints->LinesSize(); ++i )
796 {
797 if( !isModified( m_editPoints->Line( i ) ) )
798 {
799 m_editPoints->Line( i ).SetConstraint(
800 new EC_PERPLINE( m_editPoints->Line( i ) ) );
801 }
802 }
803
804 textbox->ClearRenderCache();
805 break;
806 }
807
808 case SCH_TABLECELL_T:
809 {
810 SCH_TABLECELL* cell = static_cast<SCH_TABLECELL*>( item );
811 SCH_TABLE* table = static_cast<SCH_TABLE*>( cell->GetParent() );
812
813 if( isModified( m_editPoints->Point( COL_WIDTH ) ) )
814 {
815 cell->SetEnd( VECTOR2I( m_editPoints->Point( 0 ).GetX(), cell->GetEndY() ) );
816
817 int colWidth = cell->GetRectangleWidth();
818
819 for( int ii = 0; ii < cell->GetColSpan() - 1; ++ii )
820 colWidth -= table->GetColWidth( cell->GetColumn() + ii );
821
822 table->SetColWidth( cell->GetColumn() + cell->GetColSpan() - 1, colWidth );
823 table->Normalize();
824 }
825 else if( isModified( m_editPoints->Point( ROW_HEIGHT ) ) )
826 {
827 cell->SetEnd( VECTOR2I( cell->GetEndX(), m_editPoints->Point( 1 ).GetY() ) );
828
829 int rowHeight = cell->GetRectangleHeight();
830
831 for( int ii = 0; ii < cell->GetRowSpan() - 1; ++ii )
832 rowHeight -= table->GetRowHeight( cell->GetRow() + ii );
833
834 table->SetRowHeight( cell->GetRow() + cell->GetRowSpan() - 1, rowHeight );
835 table->Normalize();
836 }
837
838 break;
839 }
840
841 case SCH_BITMAP_T:
842 {
843 EE_GRID_HELPER gridHelper( m_toolMgr );
844 SCH_BITMAP* bitmap = (SCH_BITMAP*) item;
845 VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
846 VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
847 VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
848 VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
849
850 gridHelper.SetSnap( aSnapToGrid );
851
852 pinEditedCorner( schIUScale.MilsToIU( 50 ), schIUScale.MilsToIU( 50 ), topLeft, topRight,
853 botLeft, botRight, &gridHelper );
854
855 double oldWidth = bitmap->GetSize().x;
856 double newWidth = topRight.x - topLeft.x;
857 double widthRatio = newWidth / oldWidth;
858
859 double oldHeight = bitmap->GetSize().y;
860 double newHeight = botLeft.y - topLeft.y;
861 double heightRatio = newHeight / oldHeight;
862
863 bitmap->SetImageScale( bitmap->GetImageScale() * std::min( widthRatio, heightRatio ) );
864 break;
865 }
866
867 case SCH_SHEET_T:
868 {
869 SCH_SHEET* sheet = (SCH_SHEET*) item;
870 EE_GRID_HELPER gridHelper( m_toolMgr );
871 VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
872 VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
873 VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
874 VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
875 VECTOR2I sheetNewPos = sheet->GetPosition();
876 VECTOR2I sheetNewSize = sheet->GetSize();
877
878 gridHelper.SetSnap( aSnapToGrid );
879
880 int edited = getEditedPointIndex();
881
882 if( isModified( m_editPoints->Line( RECT_RIGHT ) ) )
883 edited = RECT_TOPRIGHT;
884 else if( isModified( m_editPoints->Line( RECT_BOT ) ) )
885 edited = RECT_BOTLEFT;
886
887 gridHelper.SetSnap( aSnapToGrid );
888
889 pinEditedCorner( sheet->GetMinWidth( edited == RECT_TOPRIGHT || edited == RECT_BOTRIGHT ),
890 sheet->GetMinHeight( edited == RECT_BOTLEFT || edited == RECT_BOTRIGHT ),
891 topLeft, topRight, botLeft, botRight, &gridHelper );
892
893 if( isModified( m_editPoints->Point( RECT_TOPLEFT ) )
896 || isModified( m_editPoints->Point( RECT_BOTLEFT ) ) )
897 {
898 sheetNewPos = topLeft;
899 sheetNewSize = VECTOR2I( botRight.x - topLeft.x, botRight.y - topLeft.y );
900 }
901 else if( isModified( m_editPoints->Line( RECT_TOP ) ) )
902 {
903 sheetNewPos = VECTOR2I( sheet->GetPosition().x, topLeft.y );
904 sheetNewSize = VECTOR2I( sheet->GetSize().x, botRight.y - topLeft.y );
905 }
906 else if( isModified( m_editPoints->Line( RECT_LEFT ) ) )
907 {
908 sheetNewPos = VECTOR2I( topLeft.x, sheet->GetPosition().y );
909 sheetNewSize = VECTOR2I( botRight.x - topLeft.x, sheet->GetSize().y );
910 }
911 else if( isModified( m_editPoints->Line( RECT_BOT ) ) )
912 {
913 sheetNewSize = VECTOR2I( sheet->GetSize().x, botRight.y - topLeft.y );
914 }
915 else if( isModified( m_editPoints->Line( RECT_RIGHT ) ) )
916 {
917 sheetNewSize = VECTOR2I( botRight.x - topLeft.x, sheet->GetSize().y );
918 }
919
920 for( unsigned i = 0; i < m_editPoints->LinesSize(); ++i )
921 {
922 if( !isModified( m_editPoints->Line( i ) ) )
923 {
924 m_editPoints->Line( i ).SetConstraint(
925 new EC_PERPLINE( m_editPoints->Line( i ) ) );
926 }
927 }
928
929 if( sheet->GetPosition() != sheetNewPos )
930 sheet->SetPositionIgnoringPins( sheetNewPos );
931
932 if( sheet->GetSize() != sheetNewSize )
933 sheet->Resize( sheetNewSize );
934
935 break;
936 }
937
938 case SCH_LINE_T:
939 {
940 SCH_LINE* line = (SCH_LINE*) item;
941
942 line->SetStartPoint( m_editPoints->Point( LINE_START ).GetPosition() );
943 line->SetEndPoint( m_editPoints->Point( LINE_END ).GetPosition() );
944
945 std::pair<EDA_ITEM*, int> connected = m_editPoints->Point( LINE_START ).GetConnected();
946
947 if( connected.first )
948 {
949 if( connected.second == STARTPOINT )
950 static_cast<SCH_LINE*>( connected.first )->SetStartPoint( line->GetStartPoint() );
951 else if( connected.second == ENDPOINT )
952 static_cast<SCH_LINE*>( connected.first )->SetEndPoint( line->GetStartPoint() );
953
954 updateItem( connected.first, true );
955 }
956
957 connected = m_editPoints->Point( LINE_END ).GetConnected();
958
959 if( connected.first )
960 {
961 if( connected.second == STARTPOINT )
962 static_cast<SCH_LINE*>( connected.first )->SetStartPoint( line->GetEndPoint() );
963 else if( connected.second == ENDPOINT )
964 static_cast<SCH_LINE*>( connected.first )->SetEndPoint( line->GetEndPoint() );
965
966 updateItem( connected.first, true );
967 }
968
969 break;
970 }
971
972 default:
973 break;
974 }
975
976 updateItem( item, true );
977 m_frame->SetMsgPanel( item );
978}
979
980
982{
983 if( !m_editPoints )
984 return;
985
986 EDA_ITEM* item = m_editPoints->GetParent();
987
988 if( !item )
989 return;
990
991 switch( item->Type() )
992 {
993 case SCH_SHAPE_T:
994 {
995 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( item );
996 bool invertY = shape->GetLayer() == LAYER_DEVICE;
997
998 switch( shape->GetShape() )
999 {
1000 case SHAPE_T::ARC:
1001 m_editPoints->Point( ARC_CENTER ).SetPosition( mapCoords( shape->GetPosition(), invertY ) );
1002 m_editPoints->Point( ARC_START ).SetPosition( mapCoords( shape->GetStart(), invertY ) );
1003 m_editPoints->Point( ARC_END ).SetPosition( mapCoords( shape->GetEnd(), invertY ) );
1004 break;
1005
1006 case SHAPE_T::CIRCLE:
1007 m_editPoints->Point( CIRC_CENTER ).SetPosition( mapCoords( shape->GetPosition(), invertY ) );
1008 m_editPoints->Point( CIRC_END ).SetPosition( mapCoords( shape->GetEnd(), invertY ) );
1009 break;
1010
1011 case SHAPE_T::POLY:
1012 {
1013 if( (int) m_editPoints->PointsSize() != shape->GetPointCount() )
1014 {
1015 getView()->Remove( m_editPoints.get() );
1016 m_editedPoint = nullptr;
1018 getView()->Add( m_editPoints.get() );
1019 }
1020 else
1021 {
1022 int ii = 0;
1023
1024 for( const VECTOR2I& pt : shape->GetPolyShape().Outline( 0 ).CPoints() )
1025 m_editPoints->Point( ii++ ).SetPosition( mapCoords( pt, invertY ) );
1026 }
1027
1028 break;
1029 }
1030
1031 case SHAPE_T::RECTANGLE:
1032 {
1033 // point editor works only with rectangles having width and height > 0
1034 // Some symbols can have rectangles with width or height < 0
1035 // So normalize the size:
1036 BOX2I dummy;
1037 dummy.SetOrigin( mapCoords( shape->GetPosition(), invertY ) );
1038 dummy.SetEnd( mapCoords( shape->GetEnd(), invertY ) );
1039 dummy.Normalize();
1040 VECTOR2I topLeft = dummy.GetPosition();
1041 VECTOR2I botRight = dummy.GetEnd();
1042
1043 m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
1044 m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( VECTOR2I( botRight.x, topLeft.y ) );
1045 m_editPoints->Point( RECT_BOTLEFT ).SetPosition( VECTOR2I( topLeft.x, botRight.y ) );
1046 m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
1047 break;
1048 }
1049
1050 case SHAPE_T::BEZIER:
1051 m_editPoints->Point( BEZIER_START ).SetPosition( mapCoords( shape->GetStart(), invertY ) );
1052 m_editPoints->Point( BEZIER_CTRL_PT1 ).SetPosition( mapCoords( shape->GetBezierC1(), invertY ) );
1053 m_editPoints->Point( BEZIER_CTRL_PT2 ).SetPosition( mapCoords( shape->GetBezierC2(), invertY ) );
1054 m_editPoints->Point( BEZIER_END ).SetPosition( mapCoords( shape->GetEnd(), invertY ) );
1055 break;
1056
1057 default:
1059 }
1060
1061 break;
1062 }
1063
1064 case SCH_TEXTBOX_T:
1065 {
1066 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( item );
1067 bool invertY = textbox->GetLayer() == LAYER_DEVICE;
1068
1069 // point editor works only with rectangles having width and height > 0
1070 // Some symbols can have rectangles with width or height < 0
1071 // So normalize the size:
1072 BOX2I dummy;
1073 dummy.SetOrigin( mapCoords( textbox->GetPosition(), invertY ) );
1074 dummy.SetEnd( mapCoords( textbox->GetEnd(), invertY ) );
1075 dummy.Normalize();
1076 VECTOR2I topLeft = dummy.GetPosition();
1077 VECTOR2I botRight = dummy.GetEnd();
1078
1079 m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
1080 m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( VECTOR2I( botRight.x, topLeft.y ) );
1081 m_editPoints->Point( RECT_BOTLEFT ).SetPosition( VECTOR2I( topLeft.x, botRight.y ) );
1082 m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
1083 break;
1084 }
1085
1086 case SCH_TABLECELL_T:
1087 {
1088 SCH_TABLECELL* cell = static_cast<SCH_TABLECELL*>( item );
1089
1090 m_editPoints->Point( 0 ).SetPosition( cell->GetEndX(),
1091 cell->GetEndY() - cell->GetRectangleHeight() / 2 );
1092 m_editPoints->Point( 1 ).SetPosition( cell->GetEndX() - cell->GetRectangleWidth() / 2,
1093 cell->GetEndY() );
1094 break;
1095 }
1096
1097 case SCH_BITMAP_T:
1098 {
1099 SCH_BITMAP* bitmap = (SCH_BITMAP*) item;
1100 VECTOR2I topLeft = bitmap->GetPosition() - bitmap->GetSize() / 2;
1101 VECTOR2I botRight = bitmap->GetPosition() + bitmap->GetSize() / 2;
1102
1103 m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
1104 m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
1105 m_editPoints->Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
1106 m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
1107 break;
1108 }
1109
1110 case SCH_SHEET_T:
1111 {
1112 SCH_SHEET* sheet = (SCH_SHEET*) item;
1113 VECTOR2I topLeft = sheet->GetPosition();
1114 VECTOR2I botRight = sheet->GetPosition() + sheet->GetSize();
1115
1116 m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
1117 m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
1118 m_editPoints->Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
1119 m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
1120 break;
1121 }
1122
1123 case SCH_LINE_T:
1124 {
1125 SCH_LINE* line = (SCH_LINE*) item;
1126
1127 m_editPoints->Point( LINE_START ).SetPosition( line->GetStartPoint() );
1128 m_editPoints->Point( LINE_END ).SetPosition( line->GetEndPoint() );
1129 break;
1130 }
1131
1132 default:
1133 break;
1134 }
1135
1136 getView()->Update( m_editPoints.get() );
1137}
1138
1139
1141{
1143
1144 if( aPoint )
1145 {
1146 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1147 controls->ForceCursorPosition( true, aPoint->GetPosition() );
1148 controls->ShowCursor( true );
1149 }
1150 else
1151 {
1152 if( m_frame->ToolStackIsEmpty() )
1153 controls->ShowCursor( false );
1154
1155 controls->ForceCursorPosition( false );
1156 }
1157
1158 m_editedPoint = aPoint;
1159}
1160
1161
1163{
1164 bool isRuleArea = false;
1165
1166 if( m_editPoints )
1167 isRuleArea = m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T;
1168
1170 || !( m_editPoints->GetParent()->Type() == SCH_SHAPE_T || isRuleArea ) )
1171 {
1172 return false;
1173 }
1174
1175 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1176 bool invertY = shape->GetLayer() == LAYER_DEVICE;
1177
1178 if( shape->GetPolyShape().IsEmpty() )
1179 return false;
1180
1181 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1182
1183 if( poly.GetPointCount() < 3 )
1184 return false;
1185
1186 for( const VECTOR2I& pt : poly.CPoints() )
1187 {
1188 VECTOR2I adjustedPos = isRuleArea ? m_editedPoint->GetPosition()
1189 : mapCoords( m_editedPoint->GetPosition(), invertY );
1190
1191 if( pt == adjustedPos )
1192 return true;
1193 }
1194
1195 return false;
1196}
1197
1198
1200{
1201 if( !m_editPoints
1202 || !( m_editPoints->GetParent()->Type() == SCH_SHAPE_T
1203 || m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T ) )
1204 {
1205 return false;
1206 }
1207
1208 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1209
1210 if( shape->GetShape() != SHAPE_T::POLY )
1211 return false;
1212
1213 VECTOR2I cursorPos = getViewControls()->GetCursorPosition( false );
1214 double threshold = getView()->ToWorld( EDIT_POINT::POINT_SIZE );
1215
1216 return shape->HitTest( cursorPos, (int) threshold );
1217}
1218
1219
1221{
1222 if( !m_editPoints
1223 || !( m_editPoints->GetParent()->Type() == SCH_SHAPE_T
1224 || m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T ) )
1225 return 0;
1226
1227 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1228 bool invertY = shape->GetLayer() == LAYER_DEVICE;
1229 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1230 SCH_COMMIT commit( m_toolMgr );
1231
1232 commit.Modify( shape, m_frame->GetScreen() );
1233
1235 VECTOR2I pos = mapCoords( cursor, invertY );
1236 int currentMinDistance = INT_MAX;
1237 int closestLineStart = 0;
1238 unsigned numPoints = poly.GetPointCount();
1239
1240 if( !shape->IsClosed() )
1241 numPoints -= 1;
1242
1243 for( unsigned i = 0; i < numPoints; ++i )
1244 {
1245 int distance = (int) DistanceLinePoint( poly.CPoint( i ),
1246 poly.CPoint( i + 1 ), pos );
1247
1248 if( distance < currentMinDistance )
1249 {
1250 currentMinDistance = distance;
1251 closestLineStart = i;
1252 }
1253 }
1254
1255 poly.Insert( closestLineStart + 1, pos );
1256
1257 updateItem( shape, true );
1258 updatePoints();
1259
1260 commit.Push( _( "Add Corner" ) );
1261 return 0;
1262}
1263
1264
1266{
1268 || !( m_editPoints->GetParent()->Type() == SCH_SHAPE_T
1269 || m_editPoints->GetParent()->Type() == SCH_RULE_AREA_T ) )
1270 {
1271 return 0;
1272 }
1273
1274 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( m_editPoints->GetParent() );
1275 SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
1276 SCH_COMMIT commit( m_toolMgr );
1277
1278 commit.Modify( shape, m_frame->GetScreen() );
1279
1280 if( poly.GetPointCount() < 3 )
1281 return 0;
1282
1283 poly.Remove( getEditedPointIndex() );
1284
1285 updateItem( shape, true );
1286 updatePoints();
1287
1288 commit.Push( _( "Remove Corner" ) );
1289 return 0;
1290}
1291
1292
1294{
1295 updatePoints();
1296 return 0;
1297}
1298
1299
1301{
1309}
1310
1311
VECTOR2D mapCoords(const VECTOR2D &aSource)
Definition: PS_plotter.cpp:531
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:110
static TOOL_ACTION activatePointEditor
Definition: actions.h:205
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Create an undo entry for an item that has been already modified.
Definition: commit.h:105
bool Empty() const
Returns status of an item.
Definition: commit.h:144
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Add a menu entry to run a TOOL_ACTION on selected items.
EDIT_CONSTRAINT for a EDIT_LINE, that constrains the line to move perpendicular to the line itself.
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
void SetCurrentCursor(KICURSOR aCursor)
Set the current cursor shape for this panel.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:88
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:100
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition: eda_item.h:175
EDA_ITEM * GetParent() const
Definition: eda_item.h:102
bool IsNew() const
Definition: eda_item.h:106
void SetStartX(int x)
Definition: eda_shape.h:141
const VECTOR2I & GetBezierC2() const
Definition: eda_shape.h:189
void SetBezierC2(const VECTOR2I &aPt)
Definition: eda_shape.h:188
void SetEndY(int aY)
Definition: eda_shape.h:160
void RebuildBezierToSegmentsPointsList(int aMinSegLen)
Rebuild the m_bezierPoints vertex list that approximate the Bezier curve by a list of segments.
Definition: eda_shape.cpp:478
int GetEndX() const
Definition: eda_shape.h:152
int GetRectangleWidth() const
Definition: eda_shape.cpp:163
void SetStartY(int y)
Definition: eda_shape.h:135
SHAPE_POLY_SET & GetPolyShape()
Definition: eda_shape.h:262
SHAPE_T GetShape() const
Definition: eda_shape.h:120
int GetEndY() const
Definition: eda_shape.h:151
void SetEndX(int aX)
Definition: eda_shape.h:166
int GetPointCount() const
Definition: eda_shape.cpp:1329
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:150
bool IsClosed() const
Definition: eda_shape.cpp:210
void SetStart(const VECTOR2I &aStart)
Definition: eda_shape.h:129
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition: eda_shape.h:125
void SetEnd(const VECTOR2I &aEnd)
Definition: eda_shape.h:154
void SetBezierC1(const VECTOR2I &aPt)
Definition: eda_shape.h:185
wxString SHAPE_T_asString() const
Definition: eda_shape.cpp:87
const VECTOR2I & GetBezierC1() const
Definition: eda_shape.h:186
int GetRectangleHeight() const
Definition: eda_shape.cpp:151
virtual int GetWidth() const
Definition: eda_shape.h:110
virtual void ClearRenderCache()
Definition: eda_text.cpp:499
static std::shared_ptr< EDIT_POINTS > Make(EDA_ITEM *aItem, SCH_BASE_FRAME *frame)
Represent a single point that can be used for modifying items.
Definition: edit_points.h:48
static const int POINT_SIZE
Definition: edit_points.h:190
virtual void SetPosition(const VECTOR2I &aPosition)
Set new coordinates for an EDIT_POINT.
Definition: edit_points.h:107
virtual VECTOR2I GetPosition() const
Return coordinates of an EDIT_POINT.
Definition: edit_points.h:71
static TOOL_ACTION pointEditorRemoveCorner
Definition: ee_actions.h:147
static TOOL_ACTION pointEditorAddCorner
Definition: ee_actions.h:146
void updatePoints()
Update which point is being edited.
bool m_inPointEditor
Currently available edit points.
int Main(const TOOL_EVENT &aEvent)
void updateEditedPoint(const TOOL_EVENT &aEvent)
Clear references to the points.
void setEditedPoint(EDIT_POINT *aPoint)
Return true if aPoint is the currently modified point.
int modifiedSelection(const TOOL_EVENT &aEvent)
bool Init() override
Init() is called once upon a registration of the tool.
EDIT_POINT * m_editedPoint
< Currently edited point, NULL if there is none.
bool addCornerCondition(const SELECTION &aSelection)
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
void pinEditedCorner(int minWidth, int minHeight, VECTOR2I &topLeft, VECTOR2I &topRight, VECTOR2I &botLeft, VECTOR2I &botRight, EE_GRID_HELPER *aGrid) const
Update the coordinates of 4 corners of a rectangle, according to constraints and the moved corner.
bool isModified(const EDIT_POINT &aPoint) const
int addCorner(const TOOL_EVENT &aEvent)
TOOL_ACTION handlers.
std::shared_ptr< EDIT_POINTS > m_editPoints
bool removeCornerCondition(const SELECTION &aSelection)
int removeCorner(const TOOL_EVENT &aEvent)
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
int getEditedPointIndex() const
int clearEditedPoints(const TOOL_EVENT &aEvent)
Set the current point being edited. NULL means none.
void updateParentItem(bool aSnapToGrid) const
< Update item's points with edit points.
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:238
EE_SELECTION & GetSelection()
A foundation class for a tool operating on a schematic or symbol.
Definition: ee_tool_base.h:48
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
Definition: ee_tool_base.h:84
void updateItem(EDA_ITEM *aItem, bool aUpdateRTree) const
Similar to getView()->Update(), but handles items that are redrawn by their parents and updating the ...
Definition: ee_tool_base.h:109
EE_SELECTION_TOOL * m_selectionTool
Definition: ee_tool_base.h:200
bool Init() override
Init() is called once upon a registration of the tool.
Definition: ee_tool_base.h:64
static const TOOL_EVENT ClearedEvent
Definition: actions.h:262
static const TOOL_EVENT SelectedEvent
Definition: actions.h:260
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition: actions.h:267
static const TOOL_EVENT PointSelectedEvent
Definition: actions.h:259
bool GetSnap() const
Definition: grid_helper.h:107
void SetSnap(bool aSnap)
Definition: grid_helper.h:106
virtual VECTOR2I AlignGrid(const VECTOR2I &aPoint, GRID_HELPER_GRIDS aGrid) const
Definition: grid_helper.h:65
An interface for classes handling user events controlling the view behavior such as zooming,...
virtual void CaptureCursor(bool aEnabled)
Force the cursor to stay within the drawing panel area.
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Place the cursor immediately at a given point.
virtual void ShowCursor(bool aEnabled)
Enable or disables display of cursor.
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
virtual VECTOR2D GetMousePosition(bool aWorldCoordinates=true) const =0
Return the current mouse pointer position.
virtual void SetAutoPan(bool aEnabled)
Turn on/off auto panning (this feature is used when there is a tool active (eg.
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:68
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:315
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:354
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:1631
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:449
A shim class between EDA_DRAW_FRAME and several derived classes: SYMBOL_EDIT_FRAME,...
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
Object to handle a bitmap image that can be inserted in a schematic.
Definition: sch_bitmap.h:41
double GetImageScale() const
Definition: sch_bitmap.h:67
VECTOR2I GetPosition() const override
Definition: sch_bitmap.h:145
VECTOR2I GetSize() const
Definition: sch_bitmap.cpp:146
void SetImageScale(double aScale)
Definition: sch_bitmap.h:72
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
Definition: sch_commit.cpp:405
virtual void Revert() override
Definition: sch_commit.cpp:483
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:174
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition: sch_item.h:289
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:40
void SetStartPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:136
VECTOR2I GetEndPoint() const
Definition: sch_line.h:140
VECTOR2I GetStartPoint() const
Definition: sch_line.h:135
void SetEndPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:141
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:109
void SetPosition(const VECTOR2I &aPos) override
Definition: sch_shape.h:71
void SetEditState(int aState)
Definition: sch_shape.h:79
void Normalize()
Definition: sch_shape.cpp:75
void AddPoint(const VECTOR2I &aPosition)
Definition: sch_shape.cpp:642
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
Definition: sch_shape.cpp:119
void CalcEdit(const VECTOR2I &aPosition) override
Calculate the attributes of an item at aPosition when it is being edited.
Definition: sch_shape.h:77
VECTOR2I GetPosition() const override
Definition: sch_shape.h:70
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:57
void SetPositionIgnoringPins(const VECTOR2I &aPosition)
Definition: sch_sheet.cpp:822
int GetMinWidth(bool aFromLeft) const
Return the minimum width of the sheet based on the widths of the sheet pin text.
Definition: sch_sheet.cpp:491
VECTOR2I GetSize() const
Definition: sch_sheet.h:112
VECTOR2I GetPosition() const override
Definition: sch_sheet.h:376
int GetMinHeight(bool aFromTop) const
Return the minimum height that the sheet can be resized based on the sheet pin positions.
Definition: sch_sheet.cpp:525
void Resize(const VECTOR2I &aSize)
Resize this sheet to aSize and adjust all of the labels accordingly.
Definition: sch_sheet.cpp:935
int GetColSpan() const
Definition: sch_tablecell.h:61
int GetRowSpan() const
Definition: sch_tablecell.h:64
int GetColumn() const
int GetRow() const
void SetRowHeight(int aRow, int aHeight)
Definition: sch_table.h:121
int GetRowHeight(int aRow) const
Definition: sch_table.h:123
void SetColWidth(int aCol, int aWidth)
Definition: sch_table.h:111
int GetColWidth(int aCol) const
Definition: sch_table.h:113
void Normalize()
Definition: sch_table.cpp:135
EDA_ITEM * Front() const
Definition: selection.h:208
int Size() const
Returns the number of selected parts.
Definition: selection.h:115
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
virtual size_t GetPointCount() const override
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
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
void RemoveAllContours()
Remove all outlines & holes (clears) the polygon set.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
The symbol library editor main window.
bool ToolStackIsEmpty()
Definition: tools_holder.h:125
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:42
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:216
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
Generic, UI-independent tool event.
Definition: tool_event.h:167
bool DisableGridSnapping() const
Definition: tool_event.h:363
const VECTOR2D Position() const
Returns the point where dragging has started.
Definition: tool_event.h:285
bool IsDrag(int aButtonMask=BUT_ANY) const
Definition: tool_event.h:307
const VECTOR2D DragOrigin() const
Returns information about mouse buttons state.
Definition: tool_event.h:291
bool IsMotion() const
Definition: tool_event.h:322
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
TOOL_MENU & GetToolMenu()
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Suspend execution of the tool until an event specified in aEventList arrives.
void Activate()
Run the tool.
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:44
#define _(s)
#define ENDPOINT
ends. (Used to support dragging.)
#define STARTPOINT
When a line is selected, these flags indicate which.
RECTANGLE_POINTS
@ RECT_BOTLEFT
@ RECT_TOPLEFT
@ RECT_TOPRIGHT
@ RECT_BOTRIGHT
RECTANGLE_LINES
@ RECT_RIGHT
@ RECT_LEFT
@ RECT_BOT
@ RECT_TOP
TABLECELL_POINTS
@ ROW_HEIGHT
@ COL_WIDTH
LINE_POINTS
@ LINE_START
@ LINE_END
ARC_POINTS
@ ARC_START
@ ARC_END
@ ARC_CENTER
CIRCLE_POINTS
@ CIRC_END
@ CIRC_CENTER
BEZIER_POINTS
@ BEZIER_END
@ BEZIER_CTRL_PT2
@ BEZIER_START
@ BEZIER_CTRL_PT1
@ LAYER_DEVICE
Definition: layer_ids.h:370
@ LAYER_NOTES
Definition: layer_ids.h:371
#define UNIMPLEMENTED_FOR(type)
Definition: macros.h:96
@ RECT_BOTLEFT
@ RECT_TOPLEFT
@ RECT_TOPRIGHT
@ RECT_BOTRIGHT
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
std::vector< FAB_LAYER_COLOR > dummy
constexpr int MilsToIU(int mils) const
Definition: base_units.h:93
@ MD_SHIFT
Definition: tool_event.h:142
@ BUT_LEFT
Definition: tool_event.h:131
double DistanceLinePoint(const VECTOR2I &linePointA, const VECTOR2I &linePointB, const VECTOR2I &referencePoint)
Compute the distance between a line and a reference point.
Definition: trigo.h:143
@ SCH_LINE_T
Definition: typeinfo.h:163
@ SCH_TABLECELL_T
Definition: typeinfo.h:166
@ SCH_SHEET_T
Definition: typeinfo.h:174
@ SCH_SHAPE_T
Definition: typeinfo.h:149
@ SCH_RULE_AREA_T
Definition: typeinfo.h:170
@ SCH_BITMAP_T
Definition: typeinfo.h:164
@ SCH_TEXTBOX_T
Definition: typeinfo.h:152
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588