KiCad PCB EDA Suite
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-2021 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>
26 using namespace std::placeholders;
27 
28 #include "ee_point_editor.h"
29 #include <tool/tool_manager.h>
30 #include <view/view_controls.h>
31 #include <geometry/seg.h>
32 #include <tools/ee_actions.h>
34 #include <bitmaps.h>
35 #include <sch_edit_frame.h>
36 #include <sch_line.h>
37 #include <sch_bitmap.h>
38 #include <sch_sheet.h>
39 #include <sch_sheet_pin.h>
40 #include <symbol_edit_frame.h>
41 #include <lib_arc.h>
42 #include <lib_circle.h>
43 #include <lib_rectangle.h>
44 #include <lib_polyline.h>
45 
46 
47 // Few constants to avoid using bare numbers for point indices
49 {
51 };
52 
54 {
56 };
57 
59 {
61 };
62 
64 {
66 };
67 
69 {
70 public:
71  static std::shared_ptr<EDIT_POINTS> Make( EDA_ITEM* aItem, SCH_BASE_FRAME* frame )
72  {
73  std::shared_ptr<EDIT_POINTS> points = std::make_shared<EDIT_POINTS>( aItem );
74 
75  if( !aItem )
76  return points;
77 
78  // Generate list of edit points based on the item type
79  switch( aItem->Type() )
80  {
81  case LIB_ARC_T:
82  {
83  LIB_ARC* arc = (LIB_ARC*) aItem;
84 
85  points->AddPoint( mapCoords( arc->GetPosition() ) );
86  points->AddPoint( mapCoords( arc->GetStart() ) );
87  points->AddPoint( mapCoords( arc->GetEnd() ) );
88  break;
89  }
90  case LIB_CIRCLE_T:
91  {
92  LIB_CIRCLE* circle = (LIB_CIRCLE*) aItem;
93 
94  points->AddPoint( mapCoords( circle->GetPosition() ) );
95  points->AddPoint( mapCoords( circle->GetEnd() ) );
96  break;
97  }
98  case LIB_POLYLINE_T:
99  {
100  LIB_POLYLINE* lines = (LIB_POLYLINE*) aItem;
101  const std::vector<wxPoint>& pts = lines->GetPolyPoints();
102 
103  for( wxPoint pt : pts )
104  points->AddPoint( mapCoords( pt ) );
105 
106  break;
107  }
108  case LIB_RECTANGLE_T:
109  {
110  LIB_RECTANGLE* rect = (LIB_RECTANGLE*) aItem;
111  // point editor works only with rectangles having width and height > 0
112  // Some symbols can have rectangles with width or height < 0
113  // So normalize the size:
114  BOX2I dummy;
115  dummy.SetOrigin( mapCoords( rect->GetPosition() ) );
116  dummy.SetEnd( mapCoords( rect->GetEnd() ) );
117  dummy.Normalize();
118  VECTOR2I topLeft = dummy.GetPosition();
119  VECTOR2I botRight = dummy.GetEnd();
120 
121  points->AddPoint( topLeft );
122  points->AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
123  points->AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
124  points->AddPoint( botRight );
125  break;
126  }
127  case SCH_SHEET_T:
128  {
129  SCH_SHEET* sheet = (SCH_SHEET*) aItem;
130  wxPoint topLeft = sheet->GetPosition();
131  wxPoint botRight = sheet->GetPosition() + sheet->GetSize();
132 
133  points->AddPoint( (wxPoint) topLeft );
134  points->AddPoint( wxPoint( botRight.x, topLeft.y ) );
135  points->AddPoint( wxPoint( topLeft.x, botRight.y ) );
136  points->AddPoint( (wxPoint) botRight );
137  break;
138  }
139  case SCH_BITMAP_T:
140  {
141  SCH_BITMAP* bitmap = (SCH_BITMAP*) aItem;
142  wxPoint topLeft = bitmap->GetPosition() - bitmap->GetSize() / 2;
143  wxPoint botRight = bitmap->GetPosition() + bitmap->GetSize() / 2;
144 
145  points->AddPoint( (wxPoint) topLeft );
146  points->AddPoint( wxPoint( botRight.x, topLeft.y ) );
147  points->AddPoint( wxPoint( topLeft.x, botRight.y ) );
148  points->AddPoint( (wxPoint) botRight );
149  break;
150  }
151  case SCH_LINE_T:
152  {
153  SCH_LINE* line = (SCH_LINE*) aItem;
154  std::pair<EDA_ITEM*, int> connectedStart = { nullptr, STARTPOINT };
155  std::pair<EDA_ITEM*, int> connectedEnd = { nullptr, STARTPOINT };
156 
157  for( SCH_ITEM* test : frame->GetScreen()->Items().OfType( SCH_LINE_T ) )
158  {
159  if( test->GetLayer() != LAYER_NOTES )
160  continue;
161 
162  if( test == aItem )
163  continue;
164 
165  SCH_LINE* testLine = static_cast<SCH_LINE*>( test );
166 
167  if( testLine->GetStartPoint() == line->GetStartPoint() )
168  {
169  connectedStart = { testLine, STARTPOINT };
170  }
171  else if( testLine->GetEndPoint() == line->GetStartPoint() )
172  {
173  connectedStart = { testLine, ENDPOINT };
174  }
175  else if( testLine->GetStartPoint() == line->GetEndPoint() )
176  {
177  connectedEnd = { testLine, STARTPOINT };
178  }
179  else if( testLine->GetEndPoint() == line->GetEndPoint() )
180  {
181  connectedEnd = { testLine, ENDPOINT };
182  }
183  }
184 
185 
186  points->AddPoint( line->GetStartPoint(), connectedStart );
187  points->AddPoint( line->GetEndPoint(), connectedEnd );
188  break;
189  }
190  default:
191  points.reset();
192  break;
193  }
194 
195  return points;
196  }
197 
198 private:
200 };
201 
202 
204  EE_TOOL_BASE<SCH_BASE_FRAME>( "eeschema.PointEditor" ),
205  m_editedPoint( nullptr )
206 {
207 }
208 
209 
211 {
212  EE_TOOL_BASE::Reset( aReason );
213 
214  m_editPoints.reset();
215 }
216 
217 
219 {
221 
222  auto& menu = m_selectionTool->GetToolMenu().GetMenu();
224  std::bind( &EE_POINT_EDITOR::addCornerCondition, this, _1 ) );
226  std::bind( &EE_POINT_EDITOR::removeCornerCondition, this, _1 ) );
227 
228  return true;
229 }
230 
231 
233 {
234  EDIT_POINT* point = m_editedPoint;
235 
236  if( aEvent.IsMotion() )
237  {
238  point = m_editPoints->FindPoint( aEvent.Position(), getView() );
239  }
240  else if( aEvent.IsDrag( BUT_LEFT ) )
241  {
242  point = m_editPoints->FindPoint( aEvent.DragOrigin(), getView() );
243  }
244  else
245  {
246  point = m_editPoints->FindPoint( getViewControls()->GetCursorPosition(), getView() );
247  }
248 
249  if( m_editedPoint != point )
250  setEditedPoint( point );
251 }
252 
253 
254 int EE_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
255 {
256  static KICAD_T supportedTypes[] = {
257  LIB_ARC_T,
258  LIB_CIRCLE_T,
261  SCH_SHEET_T,
263  SCH_BITMAP_T,
264  EOT
265  };
266 
267  if( !m_selectionTool )
268  return 0;
269 
270  const EE_SELECTION& selection = m_selectionTool->GetSelection();
271 
272  if( selection.Size() != 1 || !selection.Front()->IsType( supportedTypes ) )
273  return 0;
274 
275  // Wait till drawing tool is done
276  if( selection.Front()->IsNew() )
277  return 0;
278 
279  Activate();
280 
282  KIGFX::VIEW* view = getView();
283  EDA_ITEM* item = (EDA_ITEM*) selection.Front();
284 
285  controls->ShowCursor( true );
286 
288  view->Add( m_editPoints.get() );
289  setEditedPoint( nullptr );
290  updateEditedPoint( aEvent );
291  bool inDrag = false;
292  bool modified = false;
293 
294  // Main loop: keep receiving events
295  while( TOOL_EVENT* evt = Wait() )
296  {
297  if( !m_editPoints || evt->IsSelectionEvent() )
298  break;
299 
300  if ( !inDrag )
301  updateEditedPoint( *evt );
302 
303  if( evt->IsDrag( BUT_LEFT ) && m_editedPoint )
304  {
305  if( !inDrag )
306  {
307  saveItemsToUndo();
308  controls->ForceCursorPosition( false );
309  inDrag = true;
310  modified = true;
311  }
312 
313  bool snap = !evt->DisableGridSnapping();
314 
315  if( item->Type() == LIB_ARC_T && getEditedPointIndex() == ARC_CENTER )
316  snap = false;
317 
318  m_editedPoint->SetPosition( controls->GetCursorPosition( snap ) );
319 
321  updatePoints();
322  }
323  else if( inDrag && evt->IsMouseUp( BUT_LEFT ) )
324  {
325  if( modified )
326  {
327  m_frame->OnModify();
328  modified = false;
329  }
330 
331  controls->SetAutoPan( false );
332  inDrag = false;
333  }
334  else if( evt->IsCancelInteractive() || evt->IsActivate() )
335  {
336  if( inDrag ) // Restore the last change
337  {
339  inDrag = false;
340  modified = false;
341  break;
342  }
343  else if( evt->IsCancelInteractive() )
344  {
345  break;
346  }
347 
348  if( evt->IsActivate() )
349  break;
350  }
351  else
352  {
353  evt->SetPassEvent();
354  }
355 
356  controls->SetAutoPan( inDrag );
357  controls->CaptureCursor( inDrag );
358  }
359 
360  controls->SetAutoPan( false );
361  controls->CaptureCursor( false );
362 
363  if( m_editPoints )
364  {
365  view->Remove( m_editPoints.get() );
366 
367  if( modified )
368  m_frame->OnModify();
369 
370  m_editPoints.reset();
371  m_frame->GetCanvas()->Refresh();
372  }
373 
374  return 0;
375 }
376 
389 static void pinEditedCorner( int aEditedPointIndex, int minWidth, int minHeight,
390  VECTOR2I& topLeft, VECTOR2I& topRight,
391  VECTOR2I& botLeft, VECTOR2I& botRight,
392  int aGridSize = 0 )
393 {
394  auto alignToGrid =
395  [&]( const VECTOR2I& aPoint ) -> VECTOR2I
396  {
397  return VECTOR2I( KiROUND( aPoint.x / aGridSize ) * aGridSize,
398  KiROUND( aPoint.y / aGridSize ) * aGridSize );
399  };
400 
401  switch( aEditedPointIndex )
402  {
403  case RECT_TOPLEFT:
404  // pin edited point within opposite corner
405  topLeft.x = std::min( topLeft.x, botRight.x - minWidth );
406  topLeft.y = std::min( topLeft.y, botRight.y - minHeight );
407 
408  if( aGridSize > 1 ) // Keep point on specified grid size
409  topLeft = alignToGrid( topLeft );
410 
411  // push edited point edges to adjacent corners
412  topRight.y = topLeft.y;
413  botLeft.x = topLeft.x;
414 
415  break;
416 
417  case RECT_TOPRIGHT:
418  // pin edited point within opposite corner
419  topRight.x = std::max( topRight.x, botLeft.x + minWidth );
420  topRight.y = std::min( topRight.y, botLeft.y - minHeight );
421 
422  if( aGridSize > 1 ) // Keep point on specified grid size
423  topRight = alignToGrid( topRight );
424 
425  // push edited point edges to adjacent corners
426  topLeft.y = topRight.y;
427  botRight.x = topRight.x;
428 
429  break;
430 
431  case RECT_BOTLEFT:
432  // pin edited point within opposite corner
433  botLeft.x = std::min( botLeft.x, topRight.x - minWidth );
434  botLeft.y = std::max( botLeft.y, topRight.y + minHeight );
435 
436  if( aGridSize > 1 ) // Keep point on specified grid size
437  botLeft = alignToGrid( botLeft );
438 
439  // push edited point edges to adjacent corners
440  botRight.y = botLeft.y;
441  topLeft.x = botLeft.x;
442 
443  break;
444 
445  case RECT_BOTRIGHT:
446  // pin edited point within opposite corner
447  botRight.x = std::max( botRight.x, topLeft.x + minWidth );
448  botRight.y = std::max( botRight.y, topLeft.y + minHeight );
449 
450  if( aGridSize > 1 ) // Keep point on specified grid size
451  botRight = alignToGrid( botRight );
452 
453  // push edited point edges to adjacent corners
454  botLeft.y = botRight.y;
455  topRight.x = botRight.x;
456 
457  break;
458  }
459 }
460 
461 
463 {
464  EDA_ITEM* item = m_editPoints->GetParent();
465 
466  if( !item )
467  return;
468 
469  switch( item->Type() )
470  {
471  case LIB_ARC_T:
472  {
473  LIB_ARC* arc = (LIB_ARC*) item;
474  int i = getEditedPointIndex();
475 
476  if( i == ARC_CENTER )
477  {
478  arc->SetEditState( 4 );
479  arc->CalcEdit( mapCoords( m_editPoints->Point( ARC_CENTER ).GetPosition() ) );
480  }
481  else if( i == ARC_START )
482  {
483  arc->SetEditState( 2 );
484  arc->CalcEdit( mapCoords( m_editPoints->Point( ARC_START ).GetPosition() ) );
485  }
486  else if( i == ARC_END )
487  {
488  arc->SetEditState( 3 );
489  arc->CalcEdit( mapCoords( m_editPoints->Point( ARC_END ).GetPosition() ) );
490  }
491 
492  break;
493  }
494 
495  case LIB_CIRCLE_T:
496  {
497  LIB_CIRCLE* circle = (LIB_CIRCLE*) item;
498 
499  circle->SetPosition( mapCoords( m_editPoints->Point( CIRC_CENTER ).GetPosition() ) );
500  circle->SetEnd( mapCoords( m_editPoints->Point( CIRC_END ).GetPosition() ) );
501  break;
502  }
503 
504  case LIB_POLYLINE_T:
505  {
506  LIB_POLYLINE* lines = (LIB_POLYLINE*) item;
507 
508  lines->ClearPoints();
509 
510  for( unsigned i = 0; i < m_editPoints->PointsSize(); ++i )
511  lines->AddPoint( mapCoords( m_editPoints->Point( i ).GetPosition() ) );
512 
513  break;
514  }
515 
516  case LIB_RECTANGLE_T:
517  {
518  VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
519  VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
520  VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
521  VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
522 
523  pinEditedCorner( getEditedPointIndex(), Mils2iu( 1 ), Mils2iu( 1 ),
524  topLeft, topRight, botLeft, botRight );
525 
526  LIB_RECTANGLE* rect = (LIB_RECTANGLE*) item;
527  rect->SetPosition( mapCoords( topLeft ) );
528  rect->SetEnd( mapCoords( botRight ) );
529  break;
530  }
531 
532  case SCH_BITMAP_T:
533  {
534  SCH_BITMAP* bitmap = (SCH_BITMAP*) item;
535  VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
536  VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
537  VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
538  VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
539 
540  pinEditedCorner( getEditedPointIndex(), Mils2iu( 50 ), Mils2iu( 50 ),
541  topLeft, topRight, botLeft, botRight );
542 
543  double oldWidth = bitmap->GetSize().x;
544  double newWidth = topRight.x - topLeft.x;
545  double widthRatio = newWidth / oldWidth;
546 
547  double oldHeight = bitmap->GetSize().y;
548  double newHeight = botLeft.y - topLeft.y;
549  double heightRatio = newHeight / oldHeight;
550 
551  bitmap->SetImageScale( bitmap->GetImageScale() * std::min( widthRatio, heightRatio ) );
552  break;
553  }
554 
555  case SCH_SHEET_T:
556  {
557  SCH_SHEET* sheet = (SCH_SHEET*) item;
558  VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
559  VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
560  VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
561  VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
562 
563  // The grid size used to place connected items. because a sheet contains
564  // connected items (sheet pins), keep corners coordinates on this grid.
565  // Otherwise, some sheet pins can be moved off grid
566  int grid_size = Mils2iu( 50 );
567  int edited = getEditedPointIndex();
568 
570  sheet->GetMinWidth( edited == RECT_TOPRIGHT || edited == RECT_BOTRIGHT ),
571  sheet->GetMinHeight( edited == RECT_BOTLEFT || edited == RECT_BOTRIGHT ),
572  topLeft, topRight, botLeft, botRight, grid_size );
573 
574  // Pin positions are relative to origin. Attempt to leave them where they
575  // are if the origin moves.
576  wxPoint originDelta = sheet->GetPosition() - (wxPoint) topLeft;
577 
578  sheet->SetPosition( (wxPoint) topLeft );
579  sheet->SetSize( wxSize( botRight.x - topLeft.x, botRight.y - topLeft.y ) );
580 
581  // Update the fields if we're in autoplace mode
583  sheet->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
584 
585  // Keep sheet pins attached to edges:
586  for( SCH_SHEET_PIN* pin : sheet->GetPins() )
587  {
588  wxPoint pos = pin->GetPosition();
589 
590  pos += originDelta;
591 
592  switch( pin->GetEdge() )
593  {
594  case SHEET_SIDE::LEFT: pos.x = topLeft.x; break;
595  case SHEET_SIDE::RIGHT: pos.x = topRight.x; break;
596  case SHEET_SIDE::TOP: pos.y = topLeft.y; break;
597  case SHEET_SIDE::BOTTOM: pos.y = botLeft.y; break;
598  case SHEET_SIDE::UNDEFINED: break;
599  }
600 
601  pin->SetPosition( pos );
602  }
603 
604  break;
605  }
606 
607  case SCH_LINE_T:
608  {
609  SCH_LINE* line = (SCH_LINE*) item;
610 
611  line->SetStartPoint( (wxPoint) m_editPoints->Point( LINE_START ).GetPosition() );
612  line->SetEndPoint( (wxPoint) m_editPoints->Point( LINE_END ).GetPosition() );
613 
614  std::pair<EDA_ITEM*, int> connected = m_editPoints->Point( LINE_START ).GetConnected();
615 
616  if( connected.first )
617  {
618  if( connected.second == STARTPOINT )
619  static_cast<SCH_LINE*>( connected.first )->SetStartPoint( line->GetPosition() );
620  else if( connected.second == ENDPOINT )
621  static_cast<SCH_LINE*>( connected.first )->SetEndPoint( line->GetPosition() );
622 
623  getView()->Update( connected.first, KIGFX::GEOMETRY );
624  }
625 
626  connected = m_editPoints->Point( LINE_END ).GetConnected();
627 
628  if( connected.first )
629  {
630  if( connected.second == STARTPOINT )
631  static_cast<SCH_LINE*>( connected.first )->SetStartPoint( line->GetEndPoint() );
632  else if( connected.second == ENDPOINT )
633  static_cast<SCH_LINE*>( connected.first )->SetEndPoint( line->GetEndPoint() );
634 
635  getView()->Update( connected.first, KIGFX::GEOMETRY );
636  }
637 
638  break;
639  }
640 
641  default:
642  break;
643  }
644 
645  updateItem( item, true );
646  m_frame->SetMsgPanel( item );
647 }
648 
649 
651 {
652  if( !m_editPoints )
653  return;
654 
655  EDA_ITEM* item = m_editPoints->GetParent();
656 
657  if( !item )
658  return;
659 
660  switch( item->Type() )
661  {
662  case LIB_ARC_T:
663  {
664  LIB_ARC* arc = (LIB_ARC*) item;
665 
666  m_editPoints->Point( ARC_CENTER ).SetPosition( mapCoords( arc->GetPosition() ) );
667  m_editPoints->Point( ARC_START ).SetPosition( mapCoords( arc->GetStart() ) );
668  m_editPoints->Point( ARC_END ).SetPosition( mapCoords( arc->GetEnd() ) );
669  break;
670  }
671 
672  case LIB_CIRCLE_T:
673  {
674  LIB_CIRCLE* circle = (LIB_CIRCLE*) item;
675 
676  m_editPoints->Point( CIRC_CENTER ).SetPosition( mapCoords( circle->GetPosition() ) );
677  m_editPoints->Point( CIRC_END ).SetPosition( mapCoords( circle->GetEnd() ) );
678  break;
679  }
680 
681  case LIB_POLYLINE_T:
682  {
683  LIB_POLYLINE* lines = (LIB_POLYLINE*) item;
684  const std::vector<wxPoint>& pts = lines->GetPolyPoints();
685 
686  if( m_editPoints->PointsSize() != (unsigned) pts.size() )
687  {
688  getView()->Remove( m_editPoints.get() );
689  m_editedPoint = nullptr;
691  getView()->Add(m_editPoints.get() );
692  }
693  else
694  {
695  for( unsigned i = 0; i < pts.size(); i++ )
696  m_editPoints->Point( i ).SetPosition( mapCoords( pts[i] ) );
697  }
698 
699  break;
700  }
701 
702  case LIB_RECTANGLE_T:
703  {
704  LIB_RECTANGLE* rect = (LIB_RECTANGLE*) item;
705  // point editor works only with rectangles having width and height > 0
706  // Some symbols can have rectangles with width or height < 0
707  // So normalize the size:
708  BOX2I dummy;
709  dummy.SetOrigin( mapCoords( rect->GetPosition() ) );
710  dummy.SetEnd( mapCoords( rect->GetEnd() ) );
711  dummy.Normalize();
712  VECTOR2I topLeft = dummy.GetPosition();
713  VECTOR2I botRight = dummy.GetEnd();
714 
715  m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
716  m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( VECTOR2I( botRight.x, topLeft.y ) );
717  m_editPoints->Point( RECT_BOTLEFT ).SetPosition( VECTOR2I( topLeft.x, botRight.y ) );
718  m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
719  break;
720  }
721 
722  case SCH_BITMAP_T:
723  {
724  SCH_BITMAP* bitmap = (SCH_BITMAP*) item;
725  wxPoint topLeft = bitmap->GetPosition() - bitmap->GetSize() / 2;
726  wxPoint botRight = bitmap->GetPosition() + bitmap->GetSize() / 2;
727 
728  m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
729  m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
730  m_editPoints->Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
731  m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
732  break;
733  }
734 
735  case SCH_SHEET_T:
736  {
737  SCH_SHEET* sheet = (SCH_SHEET*) item;
738  wxPoint topLeft = sheet->GetPosition();
739  wxPoint botRight = sheet->GetPosition() + sheet->GetSize();
740 
741  m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
742  m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
743  m_editPoints->Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
744  m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
745  break;
746  }
747 
748  case SCH_LINE_T:
749  {
750  SCH_LINE* line = (SCH_LINE*) item;
751 
752  m_editPoints->Point( LINE_START ).SetPosition( line->GetStartPoint() );
753  m_editPoints->Point( LINE_END ).SetPosition( line->GetEndPoint() );
754  break;
755  }
756 
757  default:
758  break;
759  }
760 
761  getView()->Update( m_editPoints.get() );
762 }
763 
764 
766 {
768 
769  if( aPoint )
770  {
772  controls->ForceCursorPosition( true, aPoint->GetPosition() );
773  controls->ShowCursor( true );
774  }
775  else
776  {
777  if( m_frame->ToolStackIsEmpty() )
778  controls->ShowCursor( false );
779 
780  controls->ForceCursorPosition( false );
781  }
782 
783  m_editedPoint = aPoint;
784 }
785 
786 
788 {
789  if( !m_editPoints || !m_editedPoint )
790  return false;
791 
792  LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() );
793 
794  if( !polyLine || polyLine->GetCornerCount() < 3 )
795  return false;
796 
797  const std::vector<wxPoint>& pts = polyLine->GetPolyPoints();
798 
799  for( unsigned i = 0; i < polyLine->GetCornerCount(); ++i )
800  {
801  if( pts[i] == mapCoords( m_editedPoint->GetPosition() ) )
802  return true;
803  }
804 
805  return false;
806 }
807 
808 
810 {
811  if( !m_editPoints || !m_editedPoint )
812  return false;
813 
814  LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() );
815 
816  if( !polyLine )
817  return false;
818 
819  VECTOR2I cursorPos = getViewControls()->GetCursorPosition();
820  double threshold = getView()->ToWorld( EDIT_POINT::POINT_SIZE );
821 
822  return polyLine->HitTest( mapCoords( cursorPos ), (int) threshold );
823 }
824 
825 
827 {
828  if( !m_editPoints )
829  return 0;
830 
831  LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() );
832 
833  if( !polyLine )
834  return false;
835 
837  polyLine->AddCorner( mapCoords( cursorPos ) );
838 
839  updateItem( polyLine, true );
840  updatePoints();
841 
842  return 0;
843 }
844 
845 
847 {
848  if( !m_editPoints || !m_editedPoint )
849  return 0;
850 
851  LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() );
852 
853  if( !polyLine || polyLine->GetCornerCount() < 3 )
854  return 0;
855 
856  polyLine->RemoveCorner( getEditedPointIndex() );
857 
858  updateItem( polyLine, true );
859  updatePoints();
860 
861  return 0;
862 }
863 
864 
866 {
867  updatePoints();
868  return 0;
869 }
870 
871 
873 {
874  if( m_isSymbolEditor )
875  {
876  saveCopyInUndoList( m_editPoints->GetParent()->GetParent(), UNDO_REDO::LIBEDIT );
877  }
878  else
879  {
881 
882  if( m_editPoints->GetParent()->Type() == SCH_LINE_T )
883  {
884  std::pair<EDA_ITEM*, int> connected = m_editPoints->Point( LINE_START ).GetConnected();
885 
886  if( connected.first )
887  saveCopyInUndoList( (SCH_ITEM*) connected.first, UNDO_REDO::CHANGED, true );
888 
889  connected = m_editPoints->Point( LINE_END ).GetConnected();
890 
891  if( connected.first )
892  saveCopyInUndoList( (SCH_ITEM*) connected.first, UNDO_REDO::CHANGED, true );
893  }
894  }
895 }
896 
897 
899 {
900  if( m_isSymbolEditor )
901  static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->RollbackSymbolFromUndo();
902  else
903  static_cast<SCH_EDIT_FRAME*>( m_frame )->RollbackSchematicFromUndo();
904 }
905 
906 
908 {
914 }
915 
916 
int Main(const TOOL_EVENT &aEvent)
virtual void ShowCursor(bool aEnabled)
Enable or disables display of cursor.
void AddCorner(const wxPoint &aPosition)
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:216
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
Definition: ee_tool_base.h:86
static const TOOL_EVENT SelectedEvent
Definition: actions.h:199
#define STARTPOINT
When a line is selected, these flags indicate which.
void SetCurrentCursor(KICURSOR aCursor)
Set the current cursor shape for this panel.
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.
static TOOL_ACTION activatePointEditor
Definition: actions.h:168
wxPoint GetStartPoint() const
Definition: sch_line.h:90
wxPoint GetEnd() const
Definition: lib_rectangle.h:82
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:452
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:403
static TOOL_ACTION pointEditorAddCorner
Definition: ee_actions.h:132
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:46
void updateEditedPoint(const TOOL_EVENT &aEvent)
Set the current point being edited. NULL means none.
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:353
TOOL_MENU & GetToolMenu()
bool IsMotion() const
Definition: tool_event.h:300
wxPoint GetPosition() const override
Definition: lib_circle.h:66
EDIT_POINT * m_editedPoint
< Currently edited point, NULL if there is none.
void updatePoints()
Update which point is being edited.
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:437
#define ENDPOINT
ends. (Used to support dragging.)
virtual wxPoint GetPosition() const
Definition: eda_item.h:252
wxPoint GetPosition() const override
Definition: sch_bitmap.h:136
VECTOR2< int > VECTOR2I
Definition: vector2d.h:623
int modifiedSelection(const TOOL_EVENT &aEvent)
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).
search types array terminator (End Of Types)
Definition: typeinfo.h:81
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:77
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition: actions.h:204
FIELDS_AUTOPLACED GetFieldsAutoplaced() const
Return whether the fields have been automatically placed.
Definition: sch_item.h:429
unsigned GetCornerCount() const
Definition: lib_polyline.h:67
void SetEndPoint(const wxPoint &aPosition)
Definition: sch_line.h:94
bool IsNew() const
Definition: eda_item.h:119
bool Init() override
Init() is called once upon a registration of the tool.
Definition: ee_tool_base.h:66
bool addCornerCondition(const SELECTION &aSelection)
EE_SELECTION & GetSelection()
Return the set of currently selected items.
const std::vector< wxPoint > & GetPolyPoints() const
Definition: lib_polyline.h:54
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:72
bool HitTest(const wxPoint &aPosition, int aAccuracy=0) const override
Test if aPosition is contained within or on the bounding box of an item.
bool IsDrag(int aButtonMask=BUT_ANY) const
Definition: tool_event.h:285
wxPoint GetEnd() const
Definition: lib_circle.h:69
wxSize GetSize() const
Definition: sch_bitmap.cpp:125
bool Init() override
Init() is called once upon a registration of the tool.
static void pinEditedCorner(int aEditedPointIndex, int minWidth, int minHeight, VECTOR2I &topLeft, VECTOR2I &topRight, VECTOR2I &botLeft, VECTOR2I &botRight, int aGridSize=0)
Update the coordinates of 4 corners of a rectangle, according to constraints and the moved corner.
virtual VECTOR2I GetPosition() const
Return coordinates of an EDIT_POINT.
Definition: edit_points.h:70
static TOOL_ACTION pointEditorRemoveCorner
Definition: ee_actions.h:133
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
void saveCopyInUndoList(EDA_ITEM *aItem, UNDO_REDO aType, bool aAppend=false)
Definition: ee_tool_base.h:134
virtual void OnModify()
Must be called after a model change in order to set the "modify" flag and do other frame-specific pro...
virtual void CaptureCursor(bool aEnabled)
Force the cursor to stay within the drawing panel area.
void SetStartPoint(const wxPoint &aPosition)
Definition: sch_line.h:91
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
void SetImageScale(double aScale)
Definition: sch_bitmap.h:71
Generic, UI-independent tool event.
Definition: tool_event.h:152
int removeCorner(const TOOL_EVENT &aEvent)
wxPoint GetStart() const
Definition: lib_arc.h:92
bool ToolStackIsEmpty()
Definition: tools_holder.h:116
An interface for classes handling user events controlling the view behavior such as zooming,...
EE_SELECTION_TOOL * m_selectionTool
Definition: ee_tool_base.h:177
const VECTOR2D DragOrigin() const
Returns information about mouse buttons state.
Definition: tool_event.h:269
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Place the cursor immediately at a given point.
virtual bool IsType(const KICAD_T aScanTypes[]) const
Check whether the item is one of the listed types.
Definition: eda_item.h:183
void updateParentItem() const
< Update item's points with edit points.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet_pin.h:65
bool DisableGridSnapping() const
Definition: tool_event.h:341
int addCorner(const TOOL_EVENT &aEvent)
TOOL_ACTION handlers.
void AddPoint(const wxPoint &aPoint)
static VECTOR2D mapCoords(const wxPoint &aCoord)
wxPoint GetPosition() const override
Definition: sch_sheet.h:380
LINE_POINTS
Object to handle a bitmap image that can be inserted in a schematic.
Definition: sch_bitmap.h:40
void CalcEdit(const wxPoint &aPosition) override
Calculate the attributes of an item at aPosition when it is being edited.
Definition: lib_arc.cpp:427
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
virtual void SetAutoPan(bool aEnabled)
Turn on/off auto panning (this feature is used when there is a tool active (eg.
bool removeCornerCondition(const SELECTION &aSelection)
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:103
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:54
void SetSize(const wxSize &aSize)
Definition: sch_sheet.h:106
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition: sch_sheet.h:184
void ClearPoints()
Definition: lib_polyline.h:50
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
ARC_POINTS
void SetEnd(const wxPoint &aEnd)
Definition: lib_rectangle.h:81
std::shared_ptr< EDIT_POINTS > m_editPoints
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:37
int getEditedPointIndex() const
wxSize GetSize() const
Definition: sch_sheet.h:105
wxPoint GetPosition() const override
Definition: sch_line.h:217
CIRCLE_POINTS
void SetPosition(const wxPoint &aPosition) override
Definition: sch_sheet.cpp:801
double GetImageScale() const
Definition: sch_bitmap.h:66
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:110
wxPoint GetEnd() const
Definition: lib_arc.h:95
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
int Size() const
Returns the number of selected parts.
Definition: selection.h:103
void setEditedPoint(EDIT_POINT *aPoint)
Return true if aPoint is the currently modified point.
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:73
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:100
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:77
static const int POINT_SIZE
Border size when not hovering.
Definition: edit_points.h:186
void Activate()
Run the tool.
void SetPosition(const wxPoint &aPosition) override
Definition: lib_item.h:225
A foundation class for a tool operating on a schematic or symbol.
Definition: ee_tool_base.h:49
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:323
Represent a single point that can be used for modifying items.
Definition: edit_points.h:47
void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual) override
Definition: sch_sheet.cpp:521
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:42
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:68
void RemoveCorner(int aIdx)
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
RECTANGLE_POINTS
A shim class between EDA_DRAW_FRAME and several derived classes: SYMBOL_EDIT_FRAME,...
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.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:193
static std::shared_ptr< EDIT_POINTS > Make(EDA_ITEM *aItem, SCH_BASE_FRAME *frame)
const VECTOR2D Position() const
Returns the point where dragging has started.
Definition: tool_event.h:263
wxPoint GetPosition() const override
Definition: lib_rectangle.h:69
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
void SetEnd(const wxPoint &aPosition)
Definition: lib_circle.h:68
EDA_ITEM * Front() const
Definition: selection.h:144
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:1518
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113
Position or shape has changed.
Definition: view_item.h:54
wxPoint GetPosition() const override
Definition: lib_arc.h:71
void SetEditState(int aState)
Definition: lib_arc.h:65
virtual void SetPosition(const VECTOR2I &aPosition)
Set new coordinates for an EDIT_POINT.
Definition: edit_points.h:106
wxPoint GetEndPoint() const
Definition: sch_line.h:93