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( auto test : frame->GetScreen()->Items().OfType( SCH_LINE_T ) )
157  {
158  if( test->GetLayer() != LAYER_NOTES )
159  continue;
160 
161  if( test == aItem )
162  continue;
163 
164  auto testLine = static_cast<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 
190  points->AddPoint( line->GetStartPoint(), connectedStart );
191  points->AddPoint( line->GetEndPoint(), connectedEnd );
192  break;
193  }
194  default:
195  points.reset();
196  break;
197  }
198 
199  return points;
200  }
201 
202 private:
204 };
205 
206 
208  EE_TOOL_BASE<SCH_BASE_FRAME>( "eeschema.PointEditor" ),
209  m_editedPoint( nullptr )
210 {
211 }
212 
213 
215 {
216  EE_TOOL_BASE::Reset( aReason );
217 
218  m_editPoints.reset();
219 }
220 
221 
223 {
225 
226  auto& menu = m_selectionTool->GetToolMenu().GetMenu();
228  std::bind( &EE_POINT_EDITOR::addCornerCondition, this, _1 ) );
230  std::bind( &EE_POINT_EDITOR::removeCornerCondition, this, _1 ) );
231 
232  return true;
233 }
234 
235 
237 {
238  EDIT_POINT* point = m_editedPoint;
239 
240  if( aEvent.IsMotion() )
241  {
242  point = m_editPoints->FindPoint( aEvent.Position(), getView() );
243  }
244  else if( aEvent.IsDrag( BUT_LEFT ) )
245  {
246  point = m_editPoints->FindPoint( aEvent.DragOrigin(), getView() );
247  }
248  else
249  {
250  point = m_editPoints->FindPoint( getViewControls()->GetCursorPosition(), getView() );
251  }
252 
253  if( m_editedPoint != point )
254  setEditedPoint( point );
255 }
256 
257 
258 int EE_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
259 {
260  static KICAD_T supportedTypes[] = {
261  LIB_ARC_T,
262  LIB_CIRCLE_T,
265  SCH_SHEET_T,
267  SCH_BITMAP_T,
268  EOT
269  };
270 
271  if( !m_selectionTool )
272  return 0;
273 
274  const EE_SELECTION& selection = m_selectionTool->GetSelection();
275 
276  if( selection.Size() != 1 || !selection.Front()->IsType( supportedTypes ) )
277  return 0;
278 
279  // Wait till drawing tool is done
280  if( selection.Front()->IsNew() )
281  return 0;
282 
283  Activate();
284 
286  KIGFX::VIEW* view = getView();
287  EDA_ITEM* item = (EDA_ITEM*) selection.Front();
288 
289  controls->ShowCursor( true );
290 
292  view->Add( m_editPoints.get() );
293  setEditedPoint( nullptr );
294  updateEditedPoint( aEvent );
295  bool inDrag = false;
296  bool modified = false;
297 
298  // Main loop: keep receiving events
299  while( TOOL_EVENT* evt = Wait() )
300  {
301  if( !m_editPoints || evt->IsSelectionEvent() )
302  break;
303 
304  if ( !inDrag )
305  updateEditedPoint( *evt );
306 
307  if( evt->IsDrag( BUT_LEFT ) && m_editedPoint )
308  {
309  if( !inDrag )
310  {
311  saveItemsToUndo();
312  controls->ForceCursorPosition( false );
313  inDrag = true;
314  modified = true;
315  }
316 
317  bool snap = !evt->Modifier( MD_ALT );
318 
319  if( item->Type() == LIB_ARC_T && getEditedPointIndex() == ARC_CENTER )
320  snap = false;
321 
322  m_editedPoint->SetPosition( controls->GetCursorPosition( snap ) );
323 
324  updateItem();
325  updatePoints();
326  }
327 
328  else if( inDrag && evt->IsMouseUp( BUT_LEFT ) )
329  {
330  controls->SetAutoPan( false );
331  inDrag = false;
332  }
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  break;
345 
346  if( evt->IsActivate() && !evt->IsMoveTool() )
347  break;
348  }
349 
350  else
351  evt->SetPassEvent();
352 
353  controls->SetAutoPan( inDrag );
354  controls->CaptureCursor( inDrag );
355  }
356 
357  controls->SetAutoPan( false );
358  controls->CaptureCursor( false );
359 
360  if( m_editPoints )
361  {
362  view->Remove( m_editPoints.get() );
363 
364  if( modified )
365  m_frame->OnModify();
366 
367  m_editPoints.reset();
368  m_frame->GetCanvas()->Refresh();
369  }
370 
371  return 0;
372 }
373 
374 
375 void pinEditedCorner( int editedPointIndex, int minWidth, int minHeight, VECTOR2I& topLeft,
376  VECTOR2I& topRight, VECTOR2I& botLeft, VECTOR2I& botRight )
377 {
378  switch( editedPointIndex )
379  {
380  case RECT_TOPLEFT:
381  // pin edited point within opposite corner
382  topLeft.x = std::min( topLeft.x, botRight.x - minWidth );
383  topLeft.y = std::min( topLeft.y, botRight.y - minHeight );
384 
385  // push edited point edges to adjacent corners
386  topRight.y = topLeft.y;
387  botLeft.x = topLeft.x;
388 
389  break;
390 
391  case RECT_TOPRIGHT:
392  // pin edited point within opposite corner
393  topRight.x = std::max( topRight.x, botLeft.x + minWidth );
394  topRight.y = std::min( topRight.y, botLeft.y - minHeight );
395 
396  // push edited point edges to adjacent corners
397  topLeft.y = topRight.y;
398  botRight.x = topRight.x;
399 
400  break;
401 
402  case RECT_BOTLEFT:
403  // pin edited point within opposite corner
404  botLeft.x = std::min( botLeft.x, topRight.x - minWidth );
405  botLeft.y = std::max( botLeft.y, topRight.y + minHeight );
406 
407  // push edited point edges to adjacent corners
408  botRight.y = botLeft.y;
409  topLeft.x = botLeft.x;
410 
411  break;
412 
413  case RECT_BOTRIGHT:
414  // pin edited point within opposite corner
415  botRight.x = std::max( botRight.x, topLeft.x + minWidth );
416  botRight.y = std::max( botRight.y, topLeft.y + minHeight );
417 
418  // push edited point edges to adjacent corners
419  botLeft.y = botRight.y;
420  topRight.x = botRight.x;
421 
422  break;
423  }
424 }
425 
426 
428 {
429  EDA_ITEM* item = m_editPoints->GetParent();
430 
431  if( !item )
432  return;
433 
434  switch( item->Type() )
435  {
436  case LIB_ARC_T:
437  {
438  LIB_ARC* arc = (LIB_ARC*) item;
439  int i = getEditedPointIndex();
440 
441  if( i == ARC_CENTER )
442  {
443  arc->SetEditState( 4 );
444  arc->CalcEdit( mapCoords( m_editPoints->Point( ARC_CENTER ).GetPosition() ) );
445  }
446  else if( i == ARC_START )
447  {
448  arc->SetEditState( 2 );
449  arc->CalcEdit( mapCoords( m_editPoints->Point( ARC_START ).GetPosition() ) );
450  }
451  else if( i == ARC_END )
452  {
453  arc->SetEditState( 3 );
454  arc->CalcEdit( mapCoords( m_editPoints->Point( ARC_END ).GetPosition() ) );
455  }
456 
457  break;
458  }
459 
460  case LIB_CIRCLE_T:
461  {
462  LIB_CIRCLE* circle = (LIB_CIRCLE*) item;
463 
464  circle->SetPosition( mapCoords( m_editPoints->Point( CIRC_CENTER ).GetPosition() ) );
465  circle->SetEnd( mapCoords( m_editPoints->Point( CIRC_END ).GetPosition() ) );
466  break;
467  }
468 
469  case LIB_POLYLINE_T:
470  {
471  LIB_POLYLINE* lines = (LIB_POLYLINE*) item;
472 
473  lines->ClearPoints();
474 
475  for( unsigned i = 0; i < m_editPoints->PointsSize(); ++i )
476  lines->AddPoint( mapCoords( m_editPoints->Point( i ).GetPosition() ) );
477 
478  break;
479  }
480 
481  case LIB_RECTANGLE_T:
482  {
483  VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
484  VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
485  VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
486  VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
487 
488  pinEditedCorner( getEditedPointIndex(), Mils2iu( 1 ), Mils2iu( 1 ),
489  topLeft, topRight, botLeft, botRight );
490 
491  LIB_RECTANGLE* rect = (LIB_RECTANGLE*) item;
492  rect->SetPosition( mapCoords( topLeft ) );
493  rect->SetEnd( mapCoords( botRight ) );
494  break;
495  }
496 
497  case SCH_BITMAP_T:
498  {
499  SCH_BITMAP* bitmap = (SCH_BITMAP*) item;
500  VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
501  VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
502  VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
503  VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
504 
505  pinEditedCorner( getEditedPointIndex(), Mils2iu( 50 ), Mils2iu( 50 ),
506  topLeft, topRight, botLeft, botRight );
507 
508  double oldWidth = bitmap->GetSize().x;
509  double newWidth = topRight.x - topLeft.x;
510  double widthRatio = newWidth / oldWidth;
511 
512  double oldHeight = bitmap->GetSize().y;
513  double newHeight = botLeft.y - topLeft.y;
514  double heightRatio = newHeight / oldHeight;
515 
516  bitmap->SetImageScale( bitmap->GetImageScale() * std::min( widthRatio, heightRatio ) );
517  break;
518  }
519 
520  case SCH_SHEET_T:
521  {
522  SCH_SHEET* sheet = (SCH_SHEET*) item;
523  VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
524  VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
525  VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
526  VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
527 
529  topLeft, topRight, botLeft, botRight );
530 
531  sheet->SetPosition( (wxPoint) topLeft );
532  sheet->SetSize( wxSize( botRight.x - topLeft.x, botRight.y - topLeft.y ) );
533 
534  // Keep sheet pins attached to edges:
535  for( SCH_SHEET_PIN* pin : sheet->GetPins() )
536  {
537  wxPoint pos = pin->GetPosition();
538 
539  switch( pin->GetEdge() )
540  {
541  case SHEET_LEFT_SIDE: pos.x = topLeft.x; break;
542  case SHEET_RIGHT_SIDE: pos.x = topRight.x; break;
543  case SHEET_TOP_SIDE: pos.y = topLeft.y; break;
544  case SHEET_BOTTOM_SIDE: pos.y = botLeft.y; break;
545  case SHEET_UNDEFINED_SIDE: break;
546  }
547 
548  pin->SetPosition( pos );
549  }
550 
551  break;
552  }
553 
554  case SCH_LINE_T:
555  {
556  SCH_LINE* line = (SCH_LINE*) item;
557 
558  line->SetStartPoint( (wxPoint) m_editPoints->Point( LINE_START ).GetPosition() );
559  line->SetEndPoint( (wxPoint) m_editPoints->Point( LINE_END ).GetPosition() );
560 
561  SCH_LINE* connection = (SCH_LINE*) ( m_editPoints->Point( LINE_START ).GetConnection() );
562 
563  if( connection )
564  {
565  if( connection->HasFlag( STARTPOINT ) )
566  connection->SetStartPoint( line->GetPosition() );
567  else if( connection->HasFlag( ENDPOINT ) )
568  connection->SetEndPoint( line->GetPosition() );
569 
570  getView()->Update( connection, KIGFX::GEOMETRY );
571  }
572 
573  connection = (SCH_LINE*) ( m_editPoints->Point( LINE_END ).GetConnection() );
574 
575  if( connection )
576  {
577  if( connection->HasFlag( STARTPOINT ) )
578  connection->SetStartPoint( line->GetEndPoint() );
579  else if( connection->HasFlag( ENDPOINT ) )
580  connection->SetEndPoint( line->GetEndPoint() );
581 
582  getView()->Update( connection, KIGFX::GEOMETRY );
583  }
584 
585  break;
586  }
587 
588  default:
589  break;
590  }
591 
592  updateView( item );
593  m_frame->SetMsgPanel( item );
594 }
595 
596 
598 {
599  if( !m_editPoints )
600  return;
601 
602  EDA_ITEM* item = m_editPoints->GetParent();
603 
604  if( !item )
605  return;
606 
607  switch( item->Type() )
608  {
609  case LIB_ARC_T:
610  {
611  LIB_ARC* arc = (LIB_ARC*) item;
612 
613  m_editPoints->Point( ARC_CENTER ).SetPosition( mapCoords( arc->GetPosition() ) );
614  m_editPoints->Point( ARC_START ).SetPosition( mapCoords( arc->GetStart() ) );
615  m_editPoints->Point( ARC_END ).SetPosition( mapCoords( arc->GetEnd() ) );
616  break;
617  }
618 
619  case LIB_CIRCLE_T:
620  {
621  LIB_CIRCLE* circle = (LIB_CIRCLE*) item;
622 
623  m_editPoints->Point( CIRC_CENTER ).SetPosition( mapCoords( circle->GetPosition() ) );
624  m_editPoints->Point( CIRC_END ).SetPosition( mapCoords( circle->GetEnd() ) );
625  break;
626  }
627 
628  case LIB_POLYLINE_T:
629  {
630  LIB_POLYLINE* lines = (LIB_POLYLINE*) item;
631  const std::vector<wxPoint>& pts = lines->GetPolyPoints();
632 
633  if( m_editPoints->PointsSize() != (unsigned) pts.size() )
634  {
635  getView()->Remove( m_editPoints.get() );
636  m_editedPoint = nullptr;
638  getView()->Add(m_editPoints.get() );
639  }
640  else
641  {
642  for( unsigned i = 0; i < pts.size(); i++ )
643  m_editPoints->Point( i ).SetPosition( mapCoords( pts[i] ) );
644  }
645 
646  break;
647  }
648 
649  case LIB_RECTANGLE_T:
650  {
651  LIB_RECTANGLE* rect = (LIB_RECTANGLE*) item;
652  // point editor works only with rectangles having width and height > 0
653  // Some symbols can have rectangles with width or height < 0
654  // So normalize the size:
655  BOX2I dummy;
656  dummy.SetOrigin( mapCoords( rect->GetPosition() ) );
657  dummy.SetEnd( mapCoords( rect->GetEnd() ) );
658  dummy.Normalize();
659  VECTOR2I topLeft = dummy.GetPosition();
660  VECTOR2I botRight = dummy.GetEnd();
661 
662  m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
663  m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( VECTOR2I( botRight.x, topLeft.y ) );
664  m_editPoints->Point( RECT_BOTLEFT ).SetPosition( VECTOR2I( topLeft.x, botRight.y ) );
665  m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
666  break;
667  }
668 
669  case SCH_BITMAP_T:
670  {
671  SCH_BITMAP* bitmap = (SCH_BITMAP*) item;
672  wxPoint topLeft = bitmap->GetPosition() - bitmap->GetSize() / 2;
673  wxPoint botRight = bitmap->GetPosition() + bitmap->GetSize() / 2;
674 
675  m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
676  m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
677  m_editPoints->Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
678  m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
679  break;
680  }
681 
682  case SCH_SHEET_T:
683  {
684  SCH_SHEET* sheet = (SCH_SHEET*) item;
685  wxPoint topLeft = sheet->GetPosition();
686  wxPoint botRight = sheet->GetPosition() + sheet->GetSize();
687 
688  m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
689  m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
690  m_editPoints->Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
691  m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
692  break;
693  }
694 
695  case SCH_LINE_T:
696  {
697  SCH_LINE* line = (SCH_LINE*) item;
698 
699  m_editPoints->Point( LINE_START ).SetPosition( line->GetStartPoint() );
700  m_editPoints->Point( LINE_END ).SetPosition( line->GetEndPoint() );
701  break;
702  }
703 
704  default:
705  break;
706  }
707 
708  getView()->Update( m_editPoints.get() );
709 }
710 
711 
713 {
715 
716  if( aPoint )
717  {
718  m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
719  controls->ForceCursorPosition( true, aPoint->GetPosition() );
720  controls->ShowCursor( true );
721  }
722  else
723  {
724  if( m_frame->ToolStackIsEmpty() )
725  controls->ShowCursor( false );
726 
727  controls->ForceCursorPosition( false );
728  }
729 
730  m_editedPoint = aPoint;
731 }
732 
733 
735 {
736  if( !m_editPoints || !m_editedPoint )
737  return false;
738 
739  LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() );
740 
741  if( !polyLine || polyLine->GetCornerCount() < 3 )
742  return false;
743 
744  const std::vector<wxPoint>& pts = polyLine->GetPolyPoints();
745 
746  for( unsigned i = 0; i < polyLine->GetCornerCount(); ++i )
747  {
748  if( pts[i] == mapCoords( m_editedPoint->GetPosition() ) )
749  return true;
750  }
751 
752  return false;
753 }
754 
755 
757 {
758  if( !m_editPoints || !m_editedPoint )
759  return false;
760 
761  LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() );
762 
763  if( !polyLine )
764  return false;
765 
766  VECTOR2I cursorPos = getViewControls()->GetCursorPosition();
767  double threshold = getView()->ToWorld( EDIT_POINT::POINT_SIZE );
768 
769  return polyLine->HitTest( mapCoords( cursorPos ), (int) threshold );
770 }
771 
772 
774 {
775  if( !m_editPoints )
776  return 0;
777 
778  LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() );
779 
780  if( !polyLine )
781  return false;
782 
783  VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !aEvent.Modifier( MD_ALT ) );
784  polyLine->AddCorner( mapCoords( cursorPos ) );
785 
786  updateView( polyLine );
787  updatePoints();
788 
789  return 0;
790 }
791 
792 
794 {
795  if( !m_editPoints || !m_editedPoint )
796  return 0;
797 
798  LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() );
799 
800  if( !polyLine || polyLine->GetCornerCount() < 3 )
801  return 0;
802 
803  polyLine->RemoveCorner( getEditedPointIndex() );
804 
805  updateView( polyLine );
806  updatePoints();
807 
808  return 0;
809 }
810 
811 
813 {
814  updatePoints();
815  return 0;
816 }
817 
818 
820 {
821  if( m_isLibEdit )
822  {
823  saveCopyInUndoList( m_editPoints->GetParent()->GetParent(), UR_LIBEDIT );
824  }
825  else
826  {
828 
829  if( m_editPoints->GetParent()->Type() == SCH_LINE_T )
830  {
831  EDA_ITEM* connection = m_editPoints->Point( LINE_START ).GetConnection();
832 
833  if( connection )
834  saveCopyInUndoList( (SCH_ITEM*) connection, UR_CHANGED, true );
835 
836  connection = m_editPoints->Point( LINE_END ).GetConnection();
837 
838  if( connection )
839  saveCopyInUndoList( (SCH_ITEM*) connection, UR_CHANGED, true );
840  }
841  }
842 }
843 
844 
846 {
847  if( m_isLibEdit )
848  static_cast<LIB_EDIT_FRAME*>( m_frame )->RollbackPartFromUndo();
849  else
850  static_cast<SCH_EDIT_FRAME*>( m_frame )->RollbackSchematicFromUndo();
851 }
852 
853 
855 {
861 }
862 
863 
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:197
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Function Wait()
static TOOL_ACTION activatePointEditor
Definition: actions.h:159
wxPoint GetStartPoint() const
Definition: sch_line.h:97
void SetPosition(const wxPoint &aPosition)
Definition: lib_item.h:251
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
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.
EE_TYPE OfType(KICAD_T aType)
Definition: sch_rtree.h:219
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:306
wxPoint GetPosition() const override
Definition: lib_circle.h:76
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:140
VECTOR2< int > VECTOR2I
Definition: vector2d.h:594
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:201
unsigned GetCornerCount() const
Definition: lib_polyline.h:73
void SetEndPoint(const wxPoint &aPosition)
Definition: sch_line.h:101
bool IsNew() const
Definition: base_struct.h:218
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:296
wxPoint GetEnd() const
Definition: lib_circle.h:79
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:255
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:98
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
TOOL_EVENT.
Definition: tool_event.h:171
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:305
VIEW_CONTROLS is an interface for classes handling user events controlling the view behaviour (such a...
EE_SELECTION_TOOL * m_selectionTool
Definition: ee_tool_base.h:153
const VECTOR2D DragOrigin() const
Returns the point where dragging has started.
Definition: tool_event.h:280
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Function ForceCursorPosition() Places the cursor immediately at a given point.
virtual bool IsType(const KICAD_T aScanTypes[]) const
Function IsType Checks whether the item is one of the listed types.
Definition: base_struct.h:284
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:538
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:433
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:206
void SetSize(const wxSize &aSize)
Definition: sch_sheet.h:281
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition: sch_sheet.h:332
int Modifier(int aMask=MD_MODIFIER_MASK) const
Returns information about key modifiers state (Ctrl, Alt, etc.)
Definition: tool_event.h:342
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:265
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
ARC_POINTS
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:38
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
int getEditedPointIndex() const
wxPoint GetPosition() const override
Function GetPosition.
Definition: sch_line.h:203
CIRCLE_POINTS
void SetPosition(const wxPoint &aPosition) override
Function SetPosition set the schematic item position to aPosition.
Definition: sch_sheet.cpp:676
double GetImageScale() const
Definition: sch_bitmap.h:71
EE_RTREE & Items()
Definition: sch_screen.h:127
#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:126
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
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
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 Activate()
Function Activate() Runs the tool.
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
EDIT_POINT.
Definition: edit_points.h:46
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:42
VIEW.
Definition: view.h:61
void RemoveCorner(int aIdx)
bool HasFlag(STATUS_FLAGS aFlag)
Definition: base_struct.h:258
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()
SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:136
static std::shared_ptr< EDIT_POINTS > Make(EDA_ITEM *aItem, SCH_BASE_FRAME *frame)
wxSize GetSize()
Definition: sch_sheet.h:280
const VECTOR2D Position() const
Returns mouse cursor position in world coordinates.
Definition: tool_event.h:274
wxPoint GetPosition() const override
Definition: lib_rectangle.h:76
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.
void SetEnd(const wxPoint &aPosition)
Definition: lib_circle.h:78
EDA_ITEM * Front() const
Definition: selection.h:183
KICAD_T Type() const
Function Type()
Definition: base_struct.h:207
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
virtual void SetPosition(const VECTOR2I &aPosition)
Function SetPosition()
Definition: edit_points.h:105
wxPoint GetEndPoint() const
Definition: sch_line.h:100