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 <symbol_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  std::pair<EDA_ITEM*, int> connectedStart = { nullptr, STARTPOINT };
154  std::pair<EDA_ITEM*, int> connectedEnd = { nullptr, STARTPOINT };
155 
156  for( SCH_ITEM* 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  SCH_LINE* testLine = static_cast<SCH_LINE*>( test );
165 
166  if( testLine->GetStartPoint() == line->GetStartPoint() )
167  {
168  connectedStart = { testLine, STARTPOINT };
169  }
170  else if( testLine->GetEndPoint() == line->GetStartPoint() )
171  {
172  connectedStart = { testLine, ENDPOINT };
173  }
174  else if( testLine->GetStartPoint() == line->GetEndPoint() )
175  {
176  connectedEnd = { testLine, STARTPOINT };
177  }
178  else if( testLine->GetEndPoint() == line->GetEndPoint() )
179  {
180  connectedEnd = { testLine, ENDPOINT };
181  }
182  }
183 
184 
185  points->AddPoint( line->GetStartPoint(), connectedStart );
186  points->AddPoint( line->GetEndPoint(), connectedEnd );
187  break;
188  }
189  default:
190  points.reset();
191  break;
192  }
193 
194  return points;
195  }
196 
197 private:
199 };
200 
201 
203  EE_TOOL_BASE<SCH_BASE_FRAME>( "eeschema.PointEditor" ),
204  m_editedPoint( nullptr )
205 {
206 }
207 
208 
210 {
211  EE_TOOL_BASE::Reset( aReason );
212 
213  m_editPoints.reset();
214 }
215 
216 
218 {
220 
221  auto& menu = m_selectionTool->GetToolMenu().GetMenu();
223  std::bind( &EE_POINT_EDITOR::addCornerCondition, this, _1 ) );
225  std::bind( &EE_POINT_EDITOR::removeCornerCondition, this, _1 ) );
226 
227  return true;
228 }
229 
230 
232 {
233  EDIT_POINT* point = m_editedPoint;
234 
235  if( aEvent.IsMotion() )
236  {
237  point = m_editPoints->FindPoint( aEvent.Position(), getView() );
238  }
239  else if( aEvent.IsDrag( BUT_LEFT ) )
240  {
241  point = m_editPoints->FindPoint( aEvent.DragOrigin(), getView() );
242  }
243  else
244  {
245  point = m_editPoints->FindPoint( getViewControls()->GetCursorPosition(), getView() );
246  }
247 
248  if( m_editedPoint != point )
249  setEditedPoint( point );
250 }
251 
252 
253 int EE_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
254 {
255  static KICAD_T supportedTypes[] = {
256  LIB_ARC_T,
257  LIB_CIRCLE_T,
260  SCH_SHEET_T,
262  SCH_BITMAP_T,
263  EOT
264  };
265 
266  if( !m_selectionTool )
267  return 0;
268 
269  const EE_SELECTION& selection = m_selectionTool->GetSelection();
270 
271  if( selection.Size() != 1 || !selection.Front()->IsType( supportedTypes ) )
272  return 0;
273 
274  // Wait till drawing tool is done
275  if( selection.Front()->IsNew() )
276  return 0;
277 
278  Activate();
279 
281  KIGFX::VIEW* view = getView();
282  EDA_ITEM* item = (EDA_ITEM*) selection.Front();
283 
284  controls->ShowCursor( true );
285 
287  view->Add( m_editPoints.get() );
288  setEditedPoint( nullptr );
289  updateEditedPoint( aEvent );
290  bool inDrag = false;
291  bool modified = false;
292 
293  // Main loop: keep receiving events
294  while( TOOL_EVENT* evt = Wait() )
295  {
296  if( !m_editPoints || evt->IsSelectionEvent() )
297  break;
298 
299  if ( !inDrag )
300  updateEditedPoint( *evt );
301 
302  if( evt->IsDrag( BUT_LEFT ) && m_editedPoint )
303  {
304  if( !inDrag )
305  {
306  saveItemsToUndo();
307  controls->ForceCursorPosition( false );
308  inDrag = true;
309  modified = true;
310  }
311 
312  bool snap = !evt->Modifier( MD_ALT );
313 
314  if( item->Type() == LIB_ARC_T && getEditedPointIndex() == ARC_CENTER )
315  snap = false;
316 
317  m_editedPoint->SetPosition( controls->GetCursorPosition( snap ) );
318 
320  updatePoints();
321  }
322  else if( inDrag && evt->IsMouseUp( BUT_LEFT ) )
323  {
324  if( modified )
325  {
326  m_frame->OnModify();
327  modified = false;
328  }
329 
330  controls->SetAutoPan( false );
331  inDrag = false;
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  {
344  break;
345  }
346 
347  if( evt->IsActivate() )
348  break;
349  }
350  else
351  {
352  evt->SetPassEvent();
353  }
354 
355  controls->SetAutoPan( inDrag );
356  controls->CaptureCursor( inDrag );
357  }
358 
359  controls->SetAutoPan( false );
360  controls->CaptureCursor( false );
361 
362  if( m_editPoints )
363  {
364  view->Remove( m_editPoints.get() );
365 
366  if( modified )
367  m_frame->OnModify();
368 
369  m_editPoints.reset();
370  m_frame->GetCanvas()->Refresh();
371  }
372 
373  return 0;
374 }
375 
388 static void pinEditedCorner( int aEditedPointIndex, int minWidth, int minHeight,
389  VECTOR2I& topLeft, VECTOR2I& topRight,
390  VECTOR2I& botLeft, VECTOR2I& botRight,
391  int aGridSize = 0 )
392 {
393  // A macro to keep a coordinate on the grid:
394  #define MOVE_TO_GRID(z) { z.x = ( (z.x +1 ) / aGridSize ) * aGridSize;\
395  z.y = ( (z.y +1 ) / aGridSize ) * aGridSize; }
396  switch( aEditedPointIndex )
397  {
398  case RECT_TOPLEFT:
399  // pin edited point within opposite corner
400  topLeft.x = std::min( topLeft.x, botRight.x - minWidth );
401  topLeft.y = std::min( topLeft.y, botRight.y - minHeight );
402 
403  if( aGridSize > 1 ) // Keep point on specified grid size
404  {
405  topLeft.x = ( topLeft.x / aGridSize ) * aGridSize;
406  topLeft.y = ( topLeft.y / aGridSize ) * aGridSize;
407  }
408 
409  // push edited point edges to adjacent corners
410  topRight.y = topLeft.y;
411  botLeft.x = topLeft.x;
412 
413  break;
414 
415  case RECT_TOPRIGHT:
416  // pin edited point within opposite corner
417  topRight.x = std::max( topRight.x, botLeft.x + minWidth );
418  topRight.y = std::min( topRight.y, botLeft.y - minHeight );
419 
420  if( aGridSize > 1 ) // Keep point on specified grid size
421  {
422  topRight.x = ( ( topRight.x+1 ) / aGridSize ) * aGridSize;
423  topRight.y = ( topRight.y / aGridSize ) * aGridSize;
424  }
425 
426  // push edited point edges to adjacent corners
427  topLeft.y = topRight.y;
428  botRight.x = topRight.x;
429 
430  break;
431 
432  case RECT_BOTLEFT:
433  // pin edited point within opposite corner
434  botLeft.x = std::min( botLeft.x, topRight.x - minWidth );
435  botLeft.y = std::max( botLeft.y, topRight.y + minHeight );
436 
437  if( aGridSize > 1 ) // Keep point on specified grid size
438  {
439  botLeft.x = ( botLeft.x / aGridSize ) * aGridSize;
440  botLeft.y = ( ( botLeft.y+1 ) / aGridSize ) * aGridSize;
441  }
442 
443  // push edited point edges to adjacent corners
444  botRight.y = botLeft.y;
445  topLeft.x = botLeft.x;
446 
447  break;
448 
449  case RECT_BOTRIGHT:
450  // pin edited point within opposite corner
451  botRight.x = std::max( botRight.x, topLeft.x + minWidth );
452  botRight.y = std::max( botRight.y, topLeft.y + minHeight );
453 
454  if( aGridSize > 1 ) // Keep point on specified grid size
455  {
456  botRight.x = ( ( botRight.x+1 ) / aGridSize ) * aGridSize;
457  botRight.y = ( ( botRight.y+1 ) / aGridSize ) * aGridSize;
458  }
459 
460  // push edited point edges to adjacent corners
461  botLeft.y = botRight.y;
462  topRight.x = botRight.x;
463 
464  break;
465  }
466 }
467 
468 
470 {
471  EDA_ITEM* item = m_editPoints->GetParent();
472 
473  if( !item )
474  return;
475 
476  switch( item->Type() )
477  {
478  case LIB_ARC_T:
479  {
480  LIB_ARC* arc = (LIB_ARC*) item;
481  int i = getEditedPointIndex();
482 
483  if( i == ARC_CENTER )
484  {
485  arc->SetEditState( 4 );
486  arc->CalcEdit( mapCoords( m_editPoints->Point( ARC_CENTER ).GetPosition() ) );
487  }
488  else if( i == ARC_START )
489  {
490  arc->SetEditState( 2 );
491  arc->CalcEdit( mapCoords( m_editPoints->Point( ARC_START ).GetPosition() ) );
492  }
493  else if( i == ARC_END )
494  {
495  arc->SetEditState( 3 );
496  arc->CalcEdit( mapCoords( m_editPoints->Point( ARC_END ).GetPosition() ) );
497  }
498 
499  break;
500  }
501 
502  case LIB_CIRCLE_T:
503  {
504  LIB_CIRCLE* circle = (LIB_CIRCLE*) item;
505 
506  circle->SetPosition( mapCoords( m_editPoints->Point( CIRC_CENTER ).GetPosition() ) );
507  circle->SetEnd( mapCoords( m_editPoints->Point( CIRC_END ).GetPosition() ) );
508  break;
509  }
510 
511  case LIB_POLYLINE_T:
512  {
513  LIB_POLYLINE* lines = (LIB_POLYLINE*) item;
514 
515  lines->ClearPoints();
516 
517  for( unsigned i = 0; i < m_editPoints->PointsSize(); ++i )
518  lines->AddPoint( mapCoords( m_editPoints->Point( i ).GetPosition() ) );
519 
520  break;
521  }
522 
523  case LIB_RECTANGLE_T:
524  {
525  VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
526  VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
527  VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
528  VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
529 
530  pinEditedCorner( getEditedPointIndex(), Mils2iu( 1 ), Mils2iu( 1 ),
531  topLeft, topRight, botLeft, botRight );
532 
533  LIB_RECTANGLE* rect = (LIB_RECTANGLE*) item;
534  rect->SetPosition( mapCoords( topLeft ) );
535  rect->SetEnd( mapCoords( botRight ) );
536  break;
537  }
538 
539  case SCH_BITMAP_T:
540  {
541  SCH_BITMAP* bitmap = (SCH_BITMAP*) item;
542  VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
543  VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
544  VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
545  VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
546 
547  pinEditedCorner( getEditedPointIndex(), Mils2iu( 50 ), Mils2iu( 50 ),
548  topLeft, topRight, botLeft, botRight );
549 
550  double oldWidth = bitmap->GetSize().x;
551  double newWidth = topRight.x - topLeft.x;
552  double widthRatio = newWidth / oldWidth;
553 
554  double oldHeight = bitmap->GetSize().y;
555  double newHeight = botLeft.y - topLeft.y;
556  double heightRatio = newHeight / oldHeight;
557 
558  bitmap->SetImageScale( bitmap->GetImageScale() * std::min( widthRatio, heightRatio ) );
559  break;
560  }
561 
562  case SCH_SHEET_T:
563  {
564  SCH_SHEET* sheet = (SCH_SHEET*) item;
565  VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
566  VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
567  VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
568  VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
569 
570  // The grid size used to place connected items. because a sheet contains
571  // connected items (sheet pins), keep corners coordinates on this grid.
572  // Otherwise, some sheet pins can be moved off grid
573  int grid_size = Mils2iu( 50 );
575  topLeft, topRight, botLeft, botRight, grid_size );
576 
577  // Pin positions are relative to origin. Attempt to leave them where they
578  // are if the origin moves.
579  wxPoint originDelta = sheet->GetPosition() - (wxPoint) topLeft;
580 
581  sheet->SetPosition( (wxPoint) topLeft );
582  sheet->SetSize( wxSize( botRight.x - topLeft.x, botRight.y - topLeft.y ) );
583 
584  // Update the fields if we're in autoplace mode
586  sheet->AutoplaceFields( /* aScreen */ NULL, /* aManual */ false );
587 
588  // Keep sheet pins attached to edges:
589  for( SCH_SHEET_PIN* pin : sheet->GetPins() )
590  {
591  wxPoint pos = pin->GetPosition();
592 
593  pos += originDelta;
594 
595  switch( pin->GetEdge() )
596  {
597  case SHEET_LEFT_SIDE: pos.x = topLeft.x; break;
598  case SHEET_RIGHT_SIDE: pos.x = topRight.x; break;
599  case SHEET_TOP_SIDE: pos.y = topLeft.y; break;
600  case SHEET_BOTTOM_SIDE: pos.y = botLeft.y; break;
601  case SHEET_UNDEFINED_SIDE: break;
602  }
603 
604  pin->SetPosition( pos );
605  }
606 
607  break;
608  }
609 
610  case SCH_LINE_T:
611  {
612  SCH_LINE* line = (SCH_LINE*) item;
613 
614  line->SetStartPoint( (wxPoint) m_editPoints->Point( LINE_START ).GetPosition() );
615  line->SetEndPoint( (wxPoint) m_editPoints->Point( LINE_END ).GetPosition() );
616 
617  std::pair<EDA_ITEM*, int> connected = m_editPoints->Point( LINE_START ).GetConnected();
618 
619  if( connected.first )
620  {
621  if( connected.second == STARTPOINT )
622  static_cast<SCH_LINE*>( connected.first )->SetStartPoint( line->GetPosition() );
623  else if( connected.second == ENDPOINT )
624  static_cast<SCH_LINE*>( connected.first )->SetEndPoint( line->GetPosition() );
625 
626  getView()->Update( connected.first, KIGFX::GEOMETRY );
627  }
628 
629  connected = m_editPoints->Point( LINE_END ).GetConnected();
630 
631  if( connected.first )
632  {
633  if( connected.second == STARTPOINT )
634  static_cast<SCH_LINE*>( connected.first )->SetStartPoint( line->GetEndPoint() );
635  else if( connected.second == ENDPOINT )
636  static_cast<SCH_LINE*>( connected.first )->SetEndPoint( line->GetEndPoint() );
637 
638  getView()->Update( connected.first, KIGFX::GEOMETRY );
639  }
640 
641  break;
642  }
643 
644  default:
645  break;
646  }
647 
648  updateItem( item, true );
649  m_frame->SetMsgPanel( item );
650 }
651 
652 
654 {
655  if( !m_editPoints )
656  return;
657 
658  EDA_ITEM* item = m_editPoints->GetParent();
659 
660  if( !item )
661  return;
662 
663  switch( item->Type() )
664  {
665  case LIB_ARC_T:
666  {
667  LIB_ARC* arc = (LIB_ARC*) item;
668 
669  m_editPoints->Point( ARC_CENTER ).SetPosition( mapCoords( arc->GetPosition() ) );
670  m_editPoints->Point( ARC_START ).SetPosition( mapCoords( arc->GetStart() ) );
671  m_editPoints->Point( ARC_END ).SetPosition( mapCoords( arc->GetEnd() ) );
672  break;
673  }
674 
675  case LIB_CIRCLE_T:
676  {
677  LIB_CIRCLE* circle = (LIB_CIRCLE*) item;
678 
679  m_editPoints->Point( CIRC_CENTER ).SetPosition( mapCoords( circle->GetPosition() ) );
680  m_editPoints->Point( CIRC_END ).SetPosition( mapCoords( circle->GetEnd() ) );
681  break;
682  }
683 
684  case LIB_POLYLINE_T:
685  {
686  LIB_POLYLINE* lines = (LIB_POLYLINE*) item;
687  const std::vector<wxPoint>& pts = lines->GetPolyPoints();
688 
689  if( m_editPoints->PointsSize() != (unsigned) pts.size() )
690  {
691  getView()->Remove( m_editPoints.get() );
692  m_editedPoint = nullptr;
694  getView()->Add(m_editPoints.get() );
695  }
696  else
697  {
698  for( unsigned i = 0; i < pts.size(); i++ )
699  m_editPoints->Point( i ).SetPosition( mapCoords( pts[i] ) );
700  }
701 
702  break;
703  }
704 
705  case LIB_RECTANGLE_T:
706  {
707  LIB_RECTANGLE* rect = (LIB_RECTANGLE*) item;
708  // point editor works only with rectangles having width and height > 0
709  // Some symbols can have rectangles with width or height < 0
710  // So normalize the size:
711  BOX2I dummy;
712  dummy.SetOrigin( mapCoords( rect->GetPosition() ) );
713  dummy.SetEnd( mapCoords( rect->GetEnd() ) );
714  dummy.Normalize();
715  VECTOR2I topLeft = dummy.GetPosition();
716  VECTOR2I botRight = dummy.GetEnd();
717 
718  m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
719  m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( VECTOR2I( botRight.x, topLeft.y ) );
720  m_editPoints->Point( RECT_BOTLEFT ).SetPosition( VECTOR2I( topLeft.x, botRight.y ) );
721  m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
722  break;
723  }
724 
725  case SCH_BITMAP_T:
726  {
727  SCH_BITMAP* bitmap = (SCH_BITMAP*) item;
728  wxPoint topLeft = bitmap->GetPosition() - bitmap->GetSize() / 2;
729  wxPoint botRight = bitmap->GetPosition() + bitmap->GetSize() / 2;
730 
731  m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
732  m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
733  m_editPoints->Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
734  m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
735  break;
736  }
737 
738  case SCH_SHEET_T:
739  {
740  SCH_SHEET* sheet = (SCH_SHEET*) item;
741  wxPoint topLeft = sheet->GetPosition();
742  wxPoint botRight = sheet->GetPosition() + sheet->GetSize();
743 
744  m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
745  m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
746  m_editPoints->Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
747  m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
748  break;
749  }
750 
751  case SCH_LINE_T:
752  {
753  SCH_LINE* line = (SCH_LINE*) item;
754 
755  m_editPoints->Point( LINE_START ).SetPosition( line->GetStartPoint() );
756  m_editPoints->Point( LINE_END ).SetPosition( line->GetEndPoint() );
757  break;
758  }
759 
760  default:
761  break;
762  }
763 
764  getView()->Update( m_editPoints.get() );
765 }
766 
767 
769 {
771 
772  if( aPoint )
773  {
775  controls->ForceCursorPosition( true, aPoint->GetPosition() );
776  controls->ShowCursor( true );
777  }
778  else
779  {
780  if( m_frame->ToolStackIsEmpty() )
781  controls->ShowCursor( false );
782 
783  controls->ForceCursorPosition( false );
784  }
785 
786  m_editedPoint = aPoint;
787 }
788 
789 
791 {
792  if( !m_editPoints || !m_editedPoint )
793  return false;
794 
795  LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() );
796 
797  if( !polyLine || polyLine->GetCornerCount() < 3 )
798  return false;
799 
800  const std::vector<wxPoint>& pts = polyLine->GetPolyPoints();
801 
802  for( unsigned i = 0; i < polyLine->GetCornerCount(); ++i )
803  {
804  if( pts[i] == mapCoords( m_editedPoint->GetPosition() ) )
805  return true;
806  }
807 
808  return false;
809 }
810 
811 
813 {
814  if( !m_editPoints || !m_editedPoint )
815  return false;
816 
817  LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() );
818 
819  if( !polyLine )
820  return false;
821 
822  VECTOR2I cursorPos = getViewControls()->GetCursorPosition();
823  double threshold = getView()->ToWorld( EDIT_POINT::POINT_SIZE );
824 
825  return polyLine->HitTest( mapCoords( cursorPos ), (int) threshold );
826 }
827 
828 
830 {
831  if( !m_editPoints )
832  return 0;
833 
834  LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() );
835 
836  if( !polyLine )
837  return false;
838 
839  VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !aEvent.Modifier( MD_ALT ) );
840  polyLine->AddCorner( mapCoords( cursorPos ) );
841 
842  updateItem( polyLine, true );
843  updatePoints();
844 
845  return 0;
846 }
847 
848 
850 {
851  if( !m_editPoints || !m_editedPoint )
852  return 0;
853 
854  LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() );
855 
856  if( !polyLine || polyLine->GetCornerCount() < 3 )
857  return 0;
858 
859  polyLine->RemoveCorner( getEditedPointIndex() );
860 
861  updateItem( polyLine, true );
862  updatePoints();
863 
864  return 0;
865 }
866 
867 
869 {
870  updatePoints();
871  return 0;
872 }
873 
874 
876 {
877  if( m_isSymbolEditor )
878  {
879  saveCopyInUndoList( m_editPoints->GetParent()->GetParent(), UNDO_REDO::LIBEDIT );
880  }
881  else
882  {
884 
885  if( m_editPoints->GetParent()->Type() == SCH_LINE_T )
886  {
887  std::pair<EDA_ITEM*, int> connected = m_editPoints->Point( LINE_START ).GetConnected();
888 
889  if( connected.first )
890  saveCopyInUndoList( (SCH_ITEM*) connected.first, UNDO_REDO::CHANGED, true );
891 
892  connected = m_editPoints->Point( LINE_END ).GetConnected();
893 
894  if( connected.first )
895  saveCopyInUndoList( (SCH_ITEM*) connected.first, UNDO_REDO::CHANGED, true );
896  }
897  }
898 }
899 
900 
902 {
903  if( m_isSymbolEditor )
904  static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->RollbackSymbolFromUndo();
905  else
906  static_cast<SCH_EDIT_FRAME*>( m_frame )->RollbackSchematicFromUndo();
907 }
908 
909 
911 {
917 }
918 
919 
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:219
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
Definition: ee_tool_base.h:85
static const TOOL_EVENT SelectedEvent
Definition: actions.h:209
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:171
wxPoint GetStartPoint() const
Definition: sch_line.h:94
wxPoint GetEnd() const
Definition: lib_rectangle.h:89
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:450
static TOOL_ACTION pointEditorAddCorner
Definition: ee_actions.h:133
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:351
TOOL_MENU & GetToolMenu()
bool IsMotion() const
Definition: tool_event.h:316
wxPoint GetPosition() const override
Definition: lib_circle.h:72
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
Definition: sch_symbol.cpp:69
EDIT_POINT * m_editedPoint
< Currently edited point, NULL if there is none.
void updatePoints()
Update which point is being edited.
virtual wxPoint GetPosition() const
Definition: eda_item.h:301
wxPoint GetPosition() const override
Definition: sch_bitmap.h:140
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).
void SetCurrentCursor(KICURSOR cursor)
Set the current cursor shape for this panel.
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:214
FIELDS_AUTOPLACED GetFieldsAutoplaced() const
Return whether the fields have been automatically placed.
Definition: sch_item.h:446
unsigned GetCornerCount() const
Definition: lib_polyline.h:73
void SetEndPoint(const wxPoint &aPosition)
Definition: sch_line.h:98
bool IsNew() const
Definition: eda_item.h:168
bool Init() override
Init() is called once upon a registration of the tool.
Definition: ee_tool_base.h:65
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:60
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:306
wxPoint GetEnd() const
Definition: lib_circle.h:75
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, accordint to constraints and the moved corner.
virtual VECTOR2I GetPosition() const
Return coordinates of an EDIT_POINT.
Definition: edit_points.h:70
#define NULL
static TOOL_ACTION pointEditorRemoveCorner
Definition: ee_actions.h:134
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:133
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:95
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
Generic, UI-independent tool event.
Definition: tool_event.h:173
int removeCorner(const TOOL_EVENT &aEvent)
wxPoint GetStart() const
Definition: lib_arc.h:111
int GetMinHeight() const
Return the minimum height that the sheet can be resized based on the sheet pin positions.
Definition: sch_sheet.cpp:433
bool ToolStackIsEmpty()
Definition: tools_holder.h:117
An interface for classes handling user events controlling the view behavior such as zooming,...
EE_SELECTION_TOOL * m_selectionTool
Definition: ee_tool_base.h:176
const VECTOR2D DragOrigin() const
Returns information about mouse buttons state.
Definition: tool_event.h:290
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:232
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.h:85
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:572
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
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.
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)
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:102
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:219
void SetSize(const wxSize &aSize)
Definition: sch_sheet.h:288
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition: sch_sheet.h:365
int Modifier(int aMask=MD_MODIFIER_MASK) const
Definition: tool_event.h:352
void ClearPoints()
Definition: lib_polyline.h:56
#define STARTPOINT
When a line is selected, these flags indicate which.
Definition: eda_item.h:111
int GetMinWidth() const
Return the minimum width of the sheet based on the widths of the sheet pin text.
Definition: sch_sheet.cpp:393
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:88
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:287
wxPoint GetPosition() const override
Definition: sch_line.h:231
CIRCLE_POINTS
void SetPosition(const wxPoint &aPosition) override
Definition: sch_sheet.cpp:784
double GetImageScale() const
Definition: sch_bitmap.h:71
EE_RTREE & Items()
Definition: sch_screen.h:162
wxPoint GetEnd() const
Definition: lib_arc.h:114
int Size() const
Returns the number of selected parts.
Definition: selection.h:128
void setEditedPoint(EDIT_POINT *aPoint)
Return true if aPoint is the currently modified point.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:149
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
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:215
#define ENDPOINT
ends. (Used to support dragging.)
Definition: eda_item.h:112
A foundation class for a tool operating on a schematic or symbol.
Definition: ee_tool_base.h:48
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:321
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:516
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:67
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:196
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:284
wxPoint GetPosition() const override
Definition: lib_rectangle.h:76
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
void SetEnd(const wxPoint &aPosition)
Definition: lib_circle.h:74
EDA_ITEM * Front() const
Definition: selection.h:203
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:1508
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:162
Position or shape has changed.
Definition: view_item.h:54
wxPoint GetPosition() const override
Definition: lib_arc.h:90
void SetEditState(int aState)
Definition: lib_arc.h:84
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:97