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 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 <lib_edit_frame.h>
40 #include <lib_arc.h>
41 #include <lib_circle.h>
42 #include <lib_rectangle.h>
43 #include <lib_polyline.h>
44 
45 
46 // Few constants to avoid using bare numbers for point indices
48 {
50 };
51 
53 {
55 };
56 
58 {
60 };
61 
63 {
65 };
66 
68 {
69 public:
70  static std::shared_ptr<EDIT_POINTS> Make( EDA_ITEM* aItem, SCH_BASE_FRAME* frame )
71  {
72  std::shared_ptr<EDIT_POINTS> points = std::make_shared<EDIT_POINTS>( aItem );
73 
74  if( !aItem )
75  return points;
76 
77  // Generate list of edit points based on the item type
78  switch( aItem->Type() )
79  {
80  case LIB_ARC_T:
81  {
82  LIB_ARC* arc = (LIB_ARC*) aItem;
83 
84  points->AddPoint( mapCoords( arc->GetPosition() ) );
85  points->AddPoint( mapCoords( arc->GetStart() ) );
86  points->AddPoint( mapCoords( arc->GetEnd() ) );
87  break;
88  }
89  case LIB_CIRCLE_T:
90  {
91  LIB_CIRCLE* circle = (LIB_CIRCLE*) aItem;
92 
93  points->AddPoint( mapCoords( circle->GetPosition() ) );
94  points->AddPoint( mapCoords( circle->GetEnd() ) );
95  break;
96  }
97  case LIB_POLYLINE_T:
98  {
99  LIB_POLYLINE* lines = (LIB_POLYLINE*) aItem;
100  const std::vector<wxPoint>& pts = lines->GetPolyPoints();
101 
102  for( wxPoint pt : pts )
103  points->AddPoint( mapCoords( pt ) );
104 
105  break;
106  }
107  case LIB_RECTANGLE_T:
108  {
109  LIB_RECTANGLE* rect = (LIB_RECTANGLE*) aItem;
110  // point editor works only with rectangles having width and height > 0
111  // Some symbols can have rectangles with width or height < 0
112  // So normalize the size:
113  BOX2I dummy;
114  dummy.SetOrigin( mapCoords( rect->GetPosition() ) );
115  dummy.SetEnd( mapCoords( rect->GetEnd() ) );
116  dummy.Normalize();
117  VECTOR2I topLeft = dummy.GetPosition();
118  VECTOR2I botRight = dummy.GetEnd();
119 
120  points->AddPoint( topLeft );
121  points->AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
122  points->AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
123  points->AddPoint( botRight );
124  break;
125  }
126  case SCH_SHEET_T:
127  {
128  SCH_SHEET* sheet = (SCH_SHEET*) aItem;
129  wxPoint topLeft = sheet->GetPosition();
130  wxPoint botRight = sheet->GetPosition() + sheet->GetSize();
131 
132  points->AddPoint( (wxPoint) topLeft );
133  points->AddPoint( wxPoint( botRight.x, topLeft.y ) );
134  points->AddPoint( wxPoint( topLeft.x, botRight.y ) );
135  points->AddPoint( (wxPoint) botRight );
136  break;
137  }
138  case SCH_BITMAP_T:
139  {
140  SCH_BITMAP* bitmap = (SCH_BITMAP*) aItem;
141  wxPoint topLeft = bitmap->GetPosition() - bitmap->GetSize() / 2;
142  wxPoint botRight = bitmap->GetPosition() + bitmap->GetSize() / 2;
143 
144  points->AddPoint( (wxPoint) topLeft );
145  points->AddPoint( wxPoint( botRight.x, topLeft.y ) );
146  points->AddPoint( wxPoint( topLeft.x, botRight.y ) );
147  points->AddPoint( (wxPoint) botRight );
148  break;
149  }
150  case SCH_LINE_T:
151  {
152  SCH_LINE* line = (SCH_LINE*) aItem;
153  SCH_LINE* connectedStart = nullptr;
154  SCH_LINE* connectedEnd = nullptr;
155 
156  for( SCH_ITEM* test = frame->GetScreen()->GetDrawItems(); test; test = test->Next() )
157  {
158  if( test->Type() != SCH_LINE_T || test->GetLayer() != LAYER_NOTES )
159  continue;
160 
161  if( test == aItem )
162  continue;
163 
164  SCH_LINE* testLine = (SCH_LINE*) test;
165  testLine->ClearFlags( STARTPOINT | ENDPOINT );
166 
167  if( testLine->GetStartPoint() == line->GetStartPoint() )
168  {
169  connectedStart = testLine;
170  testLine->SetFlags( STARTPOINT );
171  }
172  else if( testLine->GetEndPoint() == line->GetStartPoint() )
173  {
174  connectedStart = testLine;
175  testLine->SetFlags( ENDPOINT );
176  }
177  else if( testLine->GetStartPoint() == line->GetEndPoint() )
178  {
179  connectedEnd = testLine;
180  testLine->SetFlags( STARTPOINT );
181  }
182  else if( testLine->GetEndPoint() == line->GetEndPoint() )
183  {
184  connectedEnd = testLine;
185  testLine->SetFlags( ENDPOINT );
186  }
187  }
188 
189  points->AddPoint( line->GetStartPoint(), connectedStart );
190  points->AddPoint( line->GetEndPoint(), connectedEnd );
191  break;
192  }
193  default:
194  points.reset();
195  break;
196  }
197 
198  return points;
199  }
200 
201 private:
203 };
204 
205 
207  EE_TOOL_BASE<SCH_BASE_FRAME>( "eeschema.PointEditor" ),
208  m_editedPoint( nullptr )
209 {
210 }
211 
212 
214 {
215  EE_TOOL_BASE::Reset( aReason );
216 
217  m_editPoints.reset();
218 }
219 
220 
222 {
224 
225  auto& menu = m_selectionTool->GetToolMenu().GetMenu();
227  std::bind( &EE_POINT_EDITOR::addCornerCondition, this, _1 ) );
229  std::bind( &EE_POINT_EDITOR::removeCornerCondition, this, _1 ) );
230 
231  return true;
232 }
233 
234 
236 {
237  EDIT_POINT* point = m_editedPoint;
238 
239  if( aEvent.IsMotion() )
240  {
241  point = m_editPoints->FindPoint( aEvent.Position(), getView() );
242  }
243  else if( aEvent.IsDrag( BUT_LEFT ) )
244  {
245  point = m_editPoints->FindPoint( aEvent.DragOrigin(), getView() );
246  }
247  else
248  {
249  point = m_editPoints->FindPoint( getViewControls()->GetCursorPosition(), getView() );
250  }
251 
252  if( m_editedPoint != point )
253  setEditedPoint( point );
254 }
255 
256 
257 int EE_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
258 {
259  static KICAD_T supportedTypes[] = {
260  LIB_ARC_T,
261  LIB_CIRCLE_T,
264  SCH_SHEET_T,
266  SCH_BITMAP_T,
267  EOT
268  };
269 
270  if( !m_selectionTool )
271  return 0;
272 
273  const EE_SELECTION& selection = m_selectionTool->GetSelection();
274 
275  if( selection.Size() != 1 || !selection.Front()->IsType( supportedTypes ) )
276  return 0;
277 
278  // Wait till drawing tool is done
279  if( selection.Front()->IsNew() )
280  return 0;
281 
282  Activate();
283 
285  KIGFX::VIEW* view = getView();
286  EDA_ITEM* item = (EDA_ITEM*) selection.Front();
287 
288  controls->ShowCursor( true );
289 
291  view->Add( m_editPoints.get() );
292  setEditedPoint( nullptr );
293  updateEditedPoint( aEvent );
294  bool inDrag = false;
295  bool modified = false;
296 
297  // Main loop: keep receiving events
298  while( TOOL_EVENT* evt = Wait() )
299  {
300  if( !m_editPoints || evt->IsSelectionEvent() )
301  break;
302 
303  if ( !inDrag )
304  updateEditedPoint( *evt );
305 
306  if( evt->IsDrag( BUT_LEFT ) && m_editedPoint )
307  {
308  if( !inDrag )
309  {
310  saveItemsToUndo();
311  controls->ForceCursorPosition( false );
312  inDrag = true;
313  modified = true;
314  }
315 
316  bool snap = !evt->Modifier( MD_ALT );
317 
318  if( item->Type() == LIB_ARC_T && getEditedPointIndex() == ARC_CENTER )
319  snap = false;
320 
321  m_editedPoint->SetPosition( controls->GetCursorPosition( snap ) );
322 
323  updateItem();
324  updatePoints();
325  }
326 
327  else if( inDrag && evt->IsMouseUp( BUT_LEFT ) )
328  {
329  controls->SetAutoPan( false );
330  inDrag = false;
331  }
332 
333  else if( evt->IsCancelInteractive() || evt->IsActivate() )
334  {
335  if( inDrag ) // Restore the last change
336  {
338  inDrag = false;
339  modified = false;
340  break;
341  }
342  else if( evt->IsCancelInteractive() )
343  break;
344 
345  if( evt->IsActivate() && !evt->IsMoveTool() )
346  break;
347  }
348 
349  else
350  evt->SetPassEvent();
351 
352  controls->SetAutoPan( inDrag );
353  controls->CaptureCursor( inDrag );
354  }
355 
356  controls->SetAutoPan( false );
357  controls->CaptureCursor( false );
358 
359  if( m_editPoints )
360  {
361  view->Remove( m_editPoints.get() );
362 
363  if( modified )
364  m_frame->OnModify();
365 
366  m_editPoints.reset();
367  m_frame->GetCanvas()->Refresh();
368  }
369 
370  return 0;
371 }
372 
373 
374 void pinEditedCorner( int editedPointIndex, int minWidth, int minHeight, VECTOR2I& topLeft,
375  VECTOR2I& topRight, VECTOR2I& botLeft, VECTOR2I& botRight )
376 {
377  switch( editedPointIndex )
378  {
379  case RECT_TOPLEFT:
380  // pin edited point within opposite corner
381  topLeft.x = std::min( topLeft.x, botRight.x - minWidth );
382  topLeft.y = std::min( topLeft.y, botRight.y - minHeight );
383 
384  // push edited point edges to adjacent corners
385  topRight.y = topLeft.y;
386  botLeft.x = topLeft.x;
387 
388  break;
389 
390  case RECT_TOPRIGHT:
391  // pin edited point within opposite corner
392  topRight.x = std::max( topRight.x, botLeft.x + minWidth );
393  topRight.y = std::min( topRight.y, botLeft.y - minHeight );
394 
395  // push edited point edges to adjacent corners
396  topLeft.y = topRight.y;
397  botRight.x = topRight.x;
398 
399  break;
400 
401  case RECT_BOTLEFT:
402  // pin edited point within opposite corner
403  botLeft.x = std::min( botLeft.x, topRight.x - minWidth );
404  botLeft.y = std::max( botLeft.y, topRight.y + minHeight );
405 
406  // push edited point edges to adjacent corners
407  botRight.y = botLeft.y;
408  topLeft.x = botLeft.x;
409 
410  break;
411 
412  case RECT_BOTRIGHT:
413  // pin edited point within opposite corner
414  botRight.x = std::max( botRight.x, topLeft.x + minWidth );
415  botRight.y = std::max( botRight.y, topLeft.y + minHeight );
416 
417  // push edited point edges to adjacent corners
418  botLeft.y = botRight.y;
419  topRight.x = botRight.x;
420 
421  break;
422  }
423 }
424 
425 
427 {
428  EDA_ITEM* item = m_editPoints->GetParent();
429 
430  if( !item )
431  return;
432 
433  switch( item->Type() )
434  {
435  case LIB_ARC_T:
436  {
437  LIB_ARC* arc = (LIB_ARC*) item;
438  int i = getEditedPointIndex();
439 
440  if( i == ARC_CENTER )
441  {
442  arc->SetEditState( 4 );
443  arc->CalcEdit( mapCoords( m_editPoints->Point( ARC_CENTER ).GetPosition() ) );
444  }
445  else if( i == ARC_START )
446  {
447  arc->SetEditState( 2 );
448  arc->CalcEdit( mapCoords( m_editPoints->Point( ARC_START ).GetPosition() ) );
449  }
450  else if( i == ARC_END )
451  {
452  arc->SetEditState( 3 );
453  arc->CalcEdit( mapCoords( m_editPoints->Point( ARC_END ).GetPosition() ) );
454  }
455 
456  break;
457  }
458 
459  case LIB_CIRCLE_T:
460  {
461  LIB_CIRCLE* circle = (LIB_CIRCLE*) item;
462 
463  circle->SetPosition( mapCoords( m_editPoints->Point( CIRC_CENTER ).GetPosition() ) );
464  circle->SetEnd( mapCoords( m_editPoints->Point( CIRC_END ).GetPosition() ) );
465  break;
466  }
467 
468  case LIB_POLYLINE_T:
469  {
470  LIB_POLYLINE* lines = (LIB_POLYLINE*) item;
471 
472  lines->ClearPoints();
473 
474  for( unsigned i = 0; i < m_editPoints->PointsSize(); ++i )
475  lines->AddPoint( mapCoords( m_editPoints->Point( i ).GetPosition() ) );
476 
477  break;
478  }
479 
480  case LIB_RECTANGLE_T:
481  {
482  VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
483  VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
484  VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
485  VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
486 
487  pinEditedCorner( getEditedPointIndex(), Mils2iu( 1 ), Mils2iu( 1 ),
488  topLeft, topRight, botLeft, botRight );
489 
490  LIB_RECTANGLE* rect = (LIB_RECTANGLE*) item;
491  rect->SetPosition( mapCoords( topLeft ) );
492  rect->SetEnd( mapCoords( botRight ) );
493  break;
494  }
495 
496  case SCH_BITMAP_T:
497  {
498  SCH_BITMAP* bitmap = (SCH_BITMAP*) item;
499  VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
500  VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
501  VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
502  VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
503 
504  pinEditedCorner( getEditedPointIndex(), Mils2iu( 50 ), Mils2iu( 50 ),
505  topLeft, topRight, botLeft, botRight );
506 
507  double oldWidth = bitmap->GetSize().x;
508  double newWidth = topRight.x - topLeft.x;
509  double widthRatio = newWidth / oldWidth;
510 
511  double oldHeight = bitmap->GetSize().y;
512  double newHeight = botLeft.y - topLeft.y;
513  double heightRatio = newHeight / oldHeight;
514 
515  bitmap->SetImageScale( bitmap->GetImageScale() * std::min( widthRatio, heightRatio ) );
516  break;
517  }
518 
519  case SCH_SHEET_T:
520  {
521  SCH_SHEET* sheet = (SCH_SHEET*) item;
522  VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
523  VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
524  VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
525  VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
526 
528  topLeft, topRight, botLeft, botRight );
529 
530  sheet->SetPosition( (wxPoint) topLeft );
531  sheet->SetSize( wxSize( botRight.x - topLeft.x, botRight.y - topLeft.y ) );
532 
533  // Keep sheet pins attached to edges:
534  for( SCH_SHEET_PIN& pin : sheet->GetPins() )
535  {
536  wxPoint pos = pin.GetPosition();
537 
538  switch( pin.GetEdge() )
539  {
540  case SHEET_LEFT_SIDE: pos.x = topLeft.x; break;
541  case SHEET_RIGHT_SIDE: pos.x = topRight.x; break;
542  case SHEET_TOP_SIDE: pos.y = topLeft.y; break;
543  case SHEET_BOTTOM_SIDE: pos.y = botLeft.y; break;
544  case SHEET_UNDEFINED_SIDE: break;
545  }
546 
547  pin.SetPosition( pos );
548  }
549 
550  break;
551  }
552 
553  case SCH_LINE_T:
554  {
555  SCH_LINE* line = (SCH_LINE*) item;
556 
557  line->SetStartPoint( (wxPoint) m_editPoints->Point( LINE_START ).GetPosition() );
558  line->SetEndPoint( (wxPoint) m_editPoints->Point( LINE_END ).GetPosition() );
559 
560  SCH_LINE* connection = (SCH_LINE*) ( m_editPoints->Point( LINE_START ).GetConnection() );
561 
562  if( connection )
563  {
564  if( ( connection->GetFlags() & STARTPOINT ) != 0 )
565  connection->SetStartPoint( line->GetPosition() );
566  else if( ( connection->GetFlags() & ENDPOINT ) != 0 )
567  connection->SetEndPoint( line->GetPosition() );
568 
569  getView()->Update( connection, KIGFX::GEOMETRY );
570  }
571 
572  connection = (SCH_LINE*) ( m_editPoints->Point( LINE_END ).GetConnection() );
573 
574  if( connection )
575  {
576  if( ( connection->GetFlags() & STARTPOINT ) != 0 )
577  connection->SetStartPoint( line->GetEndPoint() );
578  else if( ( connection->GetFlags() & ENDPOINT ) != 0 )
579  connection->SetEndPoint( line->GetEndPoint() );
580 
581  getView()->Update( connection, KIGFX::GEOMETRY );
582  }
583 
584  break;
585  }
586 
587  default:
588  break;
589  }
590 
591  updateView( item );
592  m_frame->SetMsgPanel( item );
593 }
594 
595 
597 {
598  if( !m_editPoints )
599  return;
600 
601  EDA_ITEM* item = m_editPoints->GetParent();
602 
603  if( !item )
604  return;
605 
606  switch( item->Type() )
607  {
608  case LIB_ARC_T:
609  {
610  LIB_ARC* arc = (LIB_ARC*) item;
611 
612  m_editPoints->Point( ARC_CENTER ).SetPosition( mapCoords( arc->GetPosition() ) );
613  m_editPoints->Point( ARC_START ).SetPosition( mapCoords( arc->GetStart() ) );
614  m_editPoints->Point( ARC_END ).SetPosition( mapCoords( arc->GetEnd() ) );
615  break;
616  }
617 
618  case LIB_CIRCLE_T:
619  {
620  LIB_CIRCLE* circle = (LIB_CIRCLE*) item;
621 
622  m_editPoints->Point( CIRC_CENTER ).SetPosition( mapCoords( circle->GetPosition() ) );
623  m_editPoints->Point( CIRC_END ).SetPosition( mapCoords( circle->GetEnd() ) );
624  break;
625  }
626 
627  case LIB_POLYLINE_T:
628  {
629  LIB_POLYLINE* lines = (LIB_POLYLINE*) item;
630  const std::vector<wxPoint>& pts = lines->GetPolyPoints();
631 
632  if( m_editPoints->PointsSize() != (unsigned) pts.size() )
633  {
634  getView()->Remove( m_editPoints.get() );
635  m_editedPoint = nullptr;
637  getView()->Add(m_editPoints.get() );
638  }
639  else
640  {
641  for( unsigned i = 0; i < pts.size(); i++ )
642  m_editPoints->Point( i ).SetPosition( mapCoords( pts[i] ) );
643  }
644 
645  break;
646  }
647 
648  case LIB_RECTANGLE_T:
649  {
650  LIB_RECTANGLE* rect = (LIB_RECTANGLE*) item;
651  // point editor works only with rectangles having width and height > 0
652  // Some symbols can have rectangles with width or height < 0
653  // So normalize the size:
654  BOX2I dummy;
655  dummy.SetOrigin( mapCoords( rect->GetPosition() ) );
656  dummy.SetEnd( mapCoords( rect->GetEnd() ) );
657  dummy.Normalize();
658  VECTOR2I topLeft = dummy.GetPosition();
659  VECTOR2I botRight = dummy.GetEnd();
660 
661  m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
662  m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( VECTOR2I( botRight.x, topLeft.y ) );
663  m_editPoints->Point( RECT_BOTLEFT ).SetPosition( VECTOR2I( topLeft.x, botRight.y ) );
664  m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
665  break;
666  }
667 
668  case SCH_BITMAP_T:
669  {
670  SCH_BITMAP* bitmap = (SCH_BITMAP*) item;
671  wxPoint topLeft = bitmap->GetPosition() - bitmap->GetSize() / 2;
672  wxPoint botRight = bitmap->GetPosition() + bitmap->GetSize() / 2;
673 
674  m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
675  m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
676  m_editPoints->Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
677  m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
678  break;
679  }
680 
681  case SCH_SHEET_T:
682  {
683  SCH_SHEET* sheet = (SCH_SHEET*) item;
684  wxPoint topLeft = sheet->GetPosition();
685  wxPoint botRight = sheet->GetPosition() + sheet->GetSize();
686 
687  m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
688  m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
689  m_editPoints->Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
690  m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
691  break;
692  }
693 
694  case SCH_LINE_T:
695  {
696  SCH_LINE* line = (SCH_LINE*) item;
697 
698  m_editPoints->Point( LINE_START ).SetPosition( line->GetStartPoint() );
699  m_editPoints->Point( LINE_END ).SetPosition( line->GetEndPoint() );
700  break;
701  }
702 
703  default:
704  break;
705  }
706 
707  getView()->Update( m_editPoints.get() );
708 }
709 
710 
712 {
714 
715  if( aPoint )
716  {
717  m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
718  controls->ForceCursorPosition( true, aPoint->GetPosition() );
719  controls->ShowCursor( true );
720  }
721  else
722  {
723  if( m_frame->ToolStackIsEmpty() )
724  controls->ShowCursor( false );
725 
726  controls->ForceCursorPosition( false );
727  }
728 
729  m_editedPoint = aPoint;
730 }
731 
732 
734 {
735  if( !m_editPoints || !m_editedPoint )
736  return false;
737 
738  LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() );
739 
740  if( !polyLine || polyLine->GetCornerCount() < 3 )
741  return false;
742 
743  const std::vector<wxPoint>& pts = polyLine->GetPolyPoints();
744 
745  for( unsigned i = 0; i < polyLine->GetCornerCount(); ++i )
746  {
747  if( pts[i] == mapCoords( m_editedPoint->GetPosition() ) )
748  return true;
749  }
750 
751  return false;
752 }
753 
754 
756 {
757  if( !m_editPoints || !m_editedPoint )
758  return false;
759 
760  LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() );
761 
762  if( !polyLine )
763  return false;
764 
765  VECTOR2I cursorPos = getViewControls()->GetCursorPosition();
766  double threshold = getView()->ToWorld( EDIT_POINT::POINT_SIZE );
767 
768  return polyLine->HitTest( mapCoords( cursorPos ), (int) threshold );
769 }
770 
771 
773 {
774  if( !m_editPoints )
775  return 0;
776 
777  LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() );
778 
779  if( !polyLine )
780  return false;
781 
782  VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !aEvent.Modifier( MD_ALT ) );
783  polyLine->AddCorner( mapCoords( cursorPos ) );
784 
785  updateView( polyLine );
786  updatePoints();
787 
788  return 0;
789 }
790 
791 
793 {
794  if( !m_editPoints || !m_editedPoint )
795  return 0;
796 
797  LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() );
798 
799  if( !polyLine || polyLine->GetCornerCount() < 3 )
800  return 0;
801 
802  polyLine->RemoveCorner( getEditedPointIndex() );
803 
804  updateView( polyLine );
805  updatePoints();
806 
807  return 0;
808 }
809 
810 
812 {
813  updatePoints();
814  return 0;
815 }
816 
817 
819 {
820  if( m_isLibEdit )
821  {
822  saveCopyInUndoList( m_editPoints->GetParent()->GetParent(), UR_LIBEDIT );
823  }
824  else
825  {
827 
828  if( m_editPoints->GetParent()->Type() == SCH_LINE_T )
829  {
830  EDA_ITEM* connection = m_editPoints->Point( LINE_START ).GetConnection();
831 
832  if( connection )
833  saveCopyInUndoList( (SCH_ITEM*) connection, UR_CHANGED, true );
834 
835  connection = m_editPoints->Point( LINE_END ).GetConnection();
836 
837  if( connection )
838  saveCopyInUndoList( (SCH_ITEM*) connection, UR_CHANGED, true );
839  }
840  }
841 }
842 
843 
845 {
846  if( m_isLibEdit )
847  static_cast<LIB_EDIT_FRAME*>( m_frame )->RollbackPartFromUndo();
848  else
849  static_cast<SCH_EDIT_FRAME*>( m_frame )->RollbackSchematicFromUndo();
850 }
851 
852 
854 {
860 }
861 
862 
int Main(const TOOL_EVENT &aEvent)
virtual void ShowCursor(bool aEnabled)
Function ShowCursor() Enables or disables display of cursor.
void AddCorner(const wxPoint &aPosition)
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
Definition: ee_tool_base.h:90
static const TOOL_EVENT SelectedEvent
Definition: actions.h:196
SCH_SHEET_PINS & GetPins()
Definition: sch_sheet.h:325
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Function Wait()
static TOOL_ACTION activatePointEditor
Definition: actions.h:158
wxPoint GetStartPoint() const
Definition: sch_line.h:90
void SetPosition(const wxPoint &aPosition)
Definition: lib_item.h:252
wxPoint GetEnd() const
Definition: lib_rectangle.h:89
VECTOR2D ToWorld(const VECTOR2D &aCoord, bool aAbsolute=true) const
Function ToWorld() Converts a screen space point/vector to a point/vector in world space coordinates.
Definition: view.cpp:475
SCH_ITEM * Next() const
Definition: sch_item.h:153
void SetCurrentCursor(wxStockCursor aStockCursorID)
Function SetCurrentCursor Set the current cursor shape for this panel.
VIEW_CONTROLS class definition.
static TOOL_ACTION pointEditorAddCorner
Definition: ee_actions.h:139
void pinEditedCorner(int editedPointIndex, int minWidth, int minHeight, VECTOR2I &topLeft, VECTOR2I &topRight, VECTOR2I &botLeft, VECTOR2I &botRight)
CONDITIONAL_MENU & GetMenu()
Function GetMenu.
Definition: tool_menu.cpp:46
void updateEditedPoint(const TOOL_EVENT &aEvent)
Updates which point is being edited.
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
virtual void Remove(VIEW_ITEM *aItem)
Function Remove() Removes a VIEW_ITEM from the view.
Definition: view.cpp:376
TOOL_MENU & GetToolMenu()
bool IsMotion() const
Definition: tool_event.h:303
wxPoint GetPosition() const override
Definition: lib_circle.h:75
virtual bool IsType(const KICAD_T aScanTypes[])
Function IsType Checks whether the item is one of the listed types.
Definition: base_struct.h:293
EDIT_POINT * m_editedPoint
Currently edited point, NULL if there is none.
void updatePoints()
Updates edit points with item's points.
wxPoint GetPosition() const override
Function GetPosition.
Definition: sch_bitmap.h:135
CIRCLE_POINTS
VECTOR2< int > VECTOR2I
Definition: vector2d.h:587
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))
Function Go()
search types array terminator (End Of Types)
Definition: typeinfo.h:82
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:78
static const TOOL_EVENT SelectedItemsModified
Definition: actions.h:200
unsigned GetCornerCount() const
Definition: lib_polyline.h:73
void SetEndPoint(const wxPoint &aPosition)
Definition: sch_line.h:94
bool IsNew() const
Definition: base_struct.h:228
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
Definition: ee_tool_base.h:69
bool addCornerCondition(const SELECTION &aSelection)
EE_SELECTION & GetSelection()
Function GetSelection()
const std::vector< wxPoint > & GetPolyPoints() const
Definition: lib_polyline.h:60
bool HitTest(const wxPoint &aPosition, int aAccuracy=0) const override
Function HitTest tests if aPosition is contained within or on the bounding box of an item.
bool IsDrag(int aButtonMask=BUT_ANY) const
Definition: tool_event.h:293
wxPoint GetEnd() const
Definition: lib_circle.h:78
wxSize GetSize() const
Definition: sch_bitmap.cpp:123
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:265
virtual VECTOR2I GetPosition() const
Function GetPosition()
Definition: edit_points.h:68
static TOOL_ACTION pointEditorRemoveCorner
Definition: ee_actions.h:140
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
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)
Function CaptureCursor() Forces 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:76
Class TOOL_EVENT.
Definition: tool_event.h:168
int removeCorner(const TOOL_EVENT &aEvent)
wxPoint GetStart() const
Definition: lib_arc.h:113
int GetMinHeight() const
Return the minimum height that the sheet can be resized based on the sheet pin positions.
Definition: sch_sheet.cpp:301
Class VIEW_CONTROLS is an interface for classes handling user events controlling the view behaviour (...
EE_SELECTION_TOOL * m_selectionTool
Definition: ee_tool_base.h:140
const VECTOR2D DragOrigin() const
Returns the point where dragging has started.
Definition: tool_event.h:277
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Function ForceCursorPosition() Places the cursor immediately at a given point.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet.h:75
int addCorner(const TOOL_EVENT &aEvent)
TOOL_ACTION handlers.
void AddPoint(const wxPoint &aPoint)
static VECTOR2D mapCoords(const wxPoint &aCoord)
virtual void Update(VIEW_ITEM *aItem, int aUpdateFlags)
For dynamic VIEWs, informs the associated VIEW that the graphical representation of this item has cha...
Definition: view.cpp:1540
wxPoint GetPosition() const override
Function GetPosition.
Definition: sch_sheet.h:533
LINE_POINTS
Object to handle a bitmap image that can be inserted in a schematic.
Definition: sch_bitmap.h:42
void CalcEdit(const wxPoint &aPosition) override
Calculates the attributes of an item at aPosition when it is being edited.
Definition: lib_arc.cpp:431
KIGFX::VIEW * getView() const
Function getView()
Definition: tool_base.cpp:36
virtual void SetAutoPan(bool aEnabled)
Function SetAutoPan Turns on/off auto panning (this feature is used when there is a tool active (eg.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
bool removeCornerCondition(const SELECTION &aSelection)
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:204
void SetSize(const wxSize &aSize)
Definition: sch_sheet.h:274
int Modifier(int aMask=MD_MODIFIER_MASK) const
Returns information about key modifiers state (Ctrl, Alt, etc.)
Definition: tool_event.h:334
void ClearPoints()
Definition: lib_polyline.h:56
int GetMinWidth() const
Return the minimum width of the sheet based on the widths of the sheet pin text.
Definition: sch_sheet.cpp:261
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
void updateView(EDA_ITEM *aItem) const
Similar to getView()->Update(), but handles items that are redrawn by their parents.
Definition: ee_tool_base.h:104
void SetEnd(const wxPoint &aEnd)
Definition: lib_rectangle.h:88
void updateItem() const
Updates item's points with edit points.
std::shared_ptr< EDIT_POINTS > m_editPoints
Currently available edit points.
bool ToolStackIsEmpty()
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:37
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
#define max(a, b)
Definition: auxiliary.h:86
int getEditedPointIndex() const
wxPoint GetPosition() const override
Function GetPosition.
Definition: sch_line.h:195
void SetPosition(const wxPoint &aPosition) override
Function SetPosition set the schematic item position to aPosition.
Definition: sch_sheet.cpp:695
double GetImageScale() const
Definition: sch_bitmap.h:71
size_t i
Definition: json11.cpp:597
#define ENDPOINT
ends. (Used to support dragging.)
Definition: base_struct.h:126
wxPoint GetEnd() const
Definition: lib_arc.h:116
int Size() const
Returns the number of selected parts.
Definition: selection.h:125
void setEditedPoint(EDIT_POINT *aPoint)
Sets the current point being edited. NULL means none.
void saveCopyInUndoList(EDA_ITEM *aItem, UNDO_REDO_T aType, bool aAppend=false)
Similar to m_frame->SaveCopyInUndoList(), but handles items that are owned by their parents.
Definition: ee_tool_base.h:117
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:163
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:79
static const int POINT_SIZE
Single point size in pixels
Definition: edit_points.h:185
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: base_struct.h:266
void Activate()
Function Activate() Runs the tool.
Class EE_TOOL_BASE.
Definition: ee_tool_base.h:50
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Function Add() Adds a VIEW_ITEM to the view.
Definition: view.cpp:346
Class EDIT_POINT.
Definition: edit_points.h:46
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:42
Class VIEW.
Definition: view.h:61
void RemoveCorner(int aIdx)
STATUS_FLAGS GetFlags() const
Definition: base_struct.h:267
void setTransitions() override
Sets up handlers for various events.
RECTANGLE_POINTS
A shim class between EDA_DRAW_FRAME and several derived classes: LIB_EDIT_FRAME, LIB_VIEW_FRAME,...
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Function AddItem()
Class SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container clas...
Definition: sch_item.h:114
static std::shared_ptr< EDIT_POINTS > Make(EDA_ITEM *aItem, SCH_BASE_FRAME *frame)
wxSize GetSize()
Definition: sch_sheet.h:273
const VECTOR2D Position() const
Returns mouse cursor position in world coordinates.
Definition: tool_event.h:271
wxPoint GetPosition() const override
Definition: lib_rectangle.h:76
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.
ARC_POINTS
void SetEnd(const wxPoint &aPosition)
Definition: lib_circle.h:77
EDA_ITEM * Front() const
Definition: selection.h:182
KICAD_T Type() const
Function Type()
Definition: base_struct.h:210
#define min(a, b)
Definition: auxiliary.h:85
Color has changed.
Definition: view_item.h:57
wxPoint GetPosition() const override
Definition: lib_arc.h:92
#define STARTPOINT
When a line is selected, these flags indicate which.
Definition: base_struct.h:125
void SetEditState(int aState)
Definition: lib_arc.h:84
static std::shared_ptr< EDIT_POINTS > Make(EDA_ITEM *aItem, KIGFX::GAL *aGal)
virtual void SetPosition(const VECTOR2I &aPosition)
Function SetPosition()
Definition: edit_points.h:105
SCH_ITEM * GetDrawItems() const
Definition: sch_screen.h:147
wxPoint GetEndPoint() const
Definition: sch_line.h:93