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  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 
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 
386 static void pinEditedCorner( int aEditedPointIndex, int minWidth, int minHeight,
387  VECTOR2I& topLeft, VECTOR2I& topRight,
388  VECTOR2I& botLeft, VECTOR2I& botRight,
389  int aGridSize = 0 )
390 {
391  // A macro to keep a coordinate on the grid:
392  #define MOVE_TO_GRID(z) { z.x = ( (z.x +1 ) / aGridSize ) * aGridSize;\
393  z.y = ( (z.y +1 ) / aGridSize ) * aGridSize; }
394  switch( aEditedPointIndex )
395  {
396  case RECT_TOPLEFT:
397  // pin edited point within opposite corner
398  topLeft.x = std::min( topLeft.x, botRight.x - minWidth );
399  topLeft.y = std::min( topLeft.y, botRight.y - minHeight );
400 
401  if( aGridSize > 1 ) // Keep point on specified grid size
402  {
403  topLeft.x = ( topLeft.x / aGridSize ) * aGridSize;
404  topLeft.y = ( topLeft.y / aGridSize ) * aGridSize;
405  }
406 
407  // push edited point edges to adjacent corners
408  topRight.y = topLeft.y;
409  botLeft.x = topLeft.x;
410 
411  break;
412 
413  case RECT_TOPRIGHT:
414  // pin edited point within opposite corner
415  topRight.x = std::max( topRight.x, botLeft.x + minWidth );
416  topRight.y = std::min( topRight.y, botLeft.y - minHeight );
417 
418  if( aGridSize > 1 ) // Keep point on specified grid size
419  {
420  topRight.x = ( ( topRight.x+1 ) / aGridSize ) * aGridSize;
421  topRight.y = ( topRight.y / aGridSize ) * aGridSize;
422  }
423 
424  // push edited point edges to adjacent corners
425  topLeft.y = topRight.y;
426  botRight.x = topRight.x;
427 
428  break;
429 
430  case RECT_BOTLEFT:
431  // pin edited point within opposite corner
432  botLeft.x = std::min( botLeft.x, topRight.x - minWidth );
433  botLeft.y = std::max( botLeft.y, topRight.y + minHeight );
434 
435  if( aGridSize > 1 ) // Keep point on specified grid size
436  {
437  botLeft.x = ( botLeft.x / aGridSize ) * aGridSize;
438  botLeft.y = ( ( botLeft.y+1 ) / aGridSize ) * aGridSize;
439  }
440 
441  // push edited point edges to adjacent corners
442  botRight.y = botLeft.y;
443  topLeft.x = botLeft.x;
444 
445  break;
446 
447  case RECT_BOTRIGHT:
448  // pin edited point within opposite corner
449  botRight.x = std::max( botRight.x, topLeft.x + minWidth );
450  botRight.y = std::max( botRight.y, topLeft.y + minHeight );
451 
452  if( aGridSize > 1 ) // Keep point on specified grid size
453  {
454  botRight.x = ( ( botRight.x+1 ) / aGridSize ) * aGridSize;
455  botRight.y = ( ( botRight.y+1 ) / aGridSize ) * aGridSize;
456  }
457 
458  // push edited point edges to adjacent corners
459  botLeft.y = botRight.y;
460  topRight.x = botRight.x;
461 
462  break;
463  }
464 }
465 
466 
468 {
469  EDA_ITEM* item = m_editPoints->GetParent();
470 
471  if( !item )
472  return;
473 
474  switch( item->Type() )
475  {
476  case LIB_ARC_T:
477  {
478  LIB_ARC* arc = (LIB_ARC*) item;
479  int i = getEditedPointIndex();
480 
481  if( i == ARC_CENTER )
482  {
483  arc->SetEditState( 4 );
484  arc->CalcEdit( mapCoords( m_editPoints->Point( ARC_CENTER ).GetPosition() ) );
485  }
486  else if( i == ARC_START )
487  {
488  arc->SetEditState( 2 );
489  arc->CalcEdit( mapCoords( m_editPoints->Point( ARC_START ).GetPosition() ) );
490  }
491  else if( i == ARC_END )
492  {
493  arc->SetEditState( 3 );
494  arc->CalcEdit( mapCoords( m_editPoints->Point( ARC_END ).GetPosition() ) );
495  }
496 
497  break;
498  }
499 
500  case LIB_CIRCLE_T:
501  {
502  LIB_CIRCLE* circle = (LIB_CIRCLE*) item;
503 
504  circle->SetPosition( mapCoords( m_editPoints->Point( CIRC_CENTER ).GetPosition() ) );
505  circle->SetEnd( mapCoords( m_editPoints->Point( CIRC_END ).GetPosition() ) );
506  break;
507  }
508 
509  case LIB_POLYLINE_T:
510  {
511  LIB_POLYLINE* lines = (LIB_POLYLINE*) item;
512 
513  lines->ClearPoints();
514 
515  for( unsigned i = 0; i < m_editPoints->PointsSize(); ++i )
516  lines->AddPoint( mapCoords( m_editPoints->Point( i ).GetPosition() ) );
517 
518  break;
519  }
520 
521  case LIB_RECTANGLE_T:
522  {
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 
528  pinEditedCorner( getEditedPointIndex(), Mils2iu( 1 ), Mils2iu( 1 ),
529  topLeft, topRight, botLeft, botRight );
530 
531  LIB_RECTANGLE* rect = (LIB_RECTANGLE*) item;
532  rect->SetPosition( mapCoords( topLeft ) );
533  rect->SetEnd( mapCoords( botRight ) );
534  break;
535  }
536 
537  case SCH_BITMAP_T:
538  {
539  SCH_BITMAP* bitmap = (SCH_BITMAP*) item;
540  VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
541  VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
542  VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
543  VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
544 
545  pinEditedCorner( getEditedPointIndex(), Mils2iu( 50 ), Mils2iu( 50 ),
546  topLeft, topRight, botLeft, botRight );
547 
548  double oldWidth = bitmap->GetSize().x;
549  double newWidth = topRight.x - topLeft.x;
550  double widthRatio = newWidth / oldWidth;
551 
552  double oldHeight = bitmap->GetSize().y;
553  double newHeight = botLeft.y - topLeft.y;
554  double heightRatio = newHeight / oldHeight;
555 
556  bitmap->SetImageScale( bitmap->GetImageScale() * std::min( widthRatio, heightRatio ) );
557  break;
558  }
559 
560  case SCH_SHEET_T:
561  {
562  SCH_SHEET* sheet = (SCH_SHEET*) item;
563  VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
564  VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
565  VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
566  VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
567 
568  // The grid size used to place connected items. because a sheet contains
569  // connected items (sheet pins), keep corners coordinates on this grid.
570  // Otherwise, some sheet pins can be moved off grid
571  int grid_size = Mils2iu( 50 );
573  topLeft, topRight, botLeft, botRight, grid_size );
574 
575  // Pin positions are relative to origin. Attempt to leave them where they
576  // are if the origin moves.
577  wxPoint originDelta = sheet->GetPosition() - (wxPoint) topLeft;
578 
579  sheet->SetPosition( (wxPoint) topLeft );
580  sheet->SetSize( wxSize( botRight.x - topLeft.x, botRight.y - topLeft.y ) );
581 
582  // Update the fields if we're in autoplace mode
584  sheet->AutoplaceFields( /* aScreen */ NULL, /* aManual */ false );
585 
586  // Keep sheet pins attached to edges:
587  for( SCH_SHEET_PIN* pin : sheet->GetPins() )
588  {
589  wxPoint pos = pin->GetPosition();
590 
591  pos += originDelta;
592 
593  switch( pin->GetEdge() )
594  {
595  case SHEET_LEFT_SIDE: pos.x = topLeft.x; break;
596  case SHEET_RIGHT_SIDE: pos.x = topRight.x; break;
597  case SHEET_TOP_SIDE: pos.y = topLeft.y; break;
598  case SHEET_BOTTOM_SIDE: pos.y = botLeft.y; break;
599  case SHEET_UNDEFINED_SIDE: break;
600  }
601 
602  pin->SetPosition( pos );
603  }
604 
605  break;
606  }
607 
608  case SCH_LINE_T:
609  {
610  SCH_LINE* line = (SCH_LINE*) item;
611 
612  line->SetStartPoint( (wxPoint) m_editPoints->Point( LINE_START ).GetPosition() );
613  line->SetEndPoint( (wxPoint) m_editPoints->Point( LINE_END ).GetPosition() );
614 
615  SCH_LINE* connection = (SCH_LINE*) ( m_editPoints->Point( LINE_START ).GetConnection() );
616 
617  if( connection )
618  {
619  if( connection->HasFlag( STARTPOINT ) )
620  connection->SetStartPoint( line->GetPosition() );
621  else if( connection->HasFlag( ENDPOINT ) )
622  connection->SetEndPoint( line->GetPosition() );
623 
624  getView()->Update( connection, KIGFX::GEOMETRY );
625  }
626 
627  connection = (SCH_LINE*) ( m_editPoints->Point( LINE_END ).GetConnection() );
628 
629  if( connection )
630  {
631  if( connection->HasFlag( STARTPOINT ) )
632  connection->SetStartPoint( line->GetEndPoint() );
633  else if( connection->HasFlag( ENDPOINT ) )
634  connection->SetEndPoint( line->GetEndPoint() );
635 
636  getView()->Update( connection, KIGFX::GEOMETRY );
637  }
638 
639  break;
640  }
641 
642  default:
643  break;
644  }
645 
646  updateItem( item, true );
647  m_frame->SetMsgPanel( item );
648 }
649 
650 
652 {
653  if( !m_editPoints )
654  return;
655 
656  EDA_ITEM* item = m_editPoints->GetParent();
657 
658  if( !item )
659  return;
660 
661  switch( item->Type() )
662  {
663  case LIB_ARC_T:
664  {
665  LIB_ARC* arc = (LIB_ARC*) item;
666 
667  m_editPoints->Point( ARC_CENTER ).SetPosition( mapCoords( arc->GetPosition() ) );
668  m_editPoints->Point( ARC_START ).SetPosition( mapCoords( arc->GetStart() ) );
669  m_editPoints->Point( ARC_END ).SetPosition( mapCoords( arc->GetEnd() ) );
670  break;
671  }
672 
673  case LIB_CIRCLE_T:
674  {
675  LIB_CIRCLE* circle = (LIB_CIRCLE*) item;
676 
677  m_editPoints->Point( CIRC_CENTER ).SetPosition( mapCoords( circle->GetPosition() ) );
678  m_editPoints->Point( CIRC_END ).SetPosition( mapCoords( circle->GetEnd() ) );
679  break;
680  }
681 
682  case LIB_POLYLINE_T:
683  {
684  LIB_POLYLINE* lines = (LIB_POLYLINE*) item;
685  const std::vector<wxPoint>& pts = lines->GetPolyPoints();
686 
687  if( m_editPoints->PointsSize() != (unsigned) pts.size() )
688  {
689  getView()->Remove( m_editPoints.get() );
690  m_editedPoint = nullptr;
692  getView()->Add(m_editPoints.get() );
693  }
694  else
695  {
696  for( unsigned i = 0; i < pts.size(); i++ )
697  m_editPoints->Point( i ).SetPosition( mapCoords( pts[i] ) );
698  }
699 
700  break;
701  }
702 
703  case LIB_RECTANGLE_T:
704  {
705  LIB_RECTANGLE* rect = (LIB_RECTANGLE*) item;
706  // point editor works only with rectangles having width and height > 0
707  // Some symbols can have rectangles with width or height < 0
708  // So normalize the size:
709  BOX2I dummy;
710  dummy.SetOrigin( mapCoords( rect->GetPosition() ) );
711  dummy.SetEnd( mapCoords( rect->GetEnd() ) );
712  dummy.Normalize();
713  VECTOR2I topLeft = dummy.GetPosition();
714  VECTOR2I botRight = dummy.GetEnd();
715 
716  m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
717  m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( VECTOR2I( botRight.x, topLeft.y ) );
718  m_editPoints->Point( RECT_BOTLEFT ).SetPosition( VECTOR2I( topLeft.x, botRight.y ) );
719  m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
720  break;
721  }
722 
723  case SCH_BITMAP_T:
724  {
725  SCH_BITMAP* bitmap = (SCH_BITMAP*) item;
726  wxPoint topLeft = bitmap->GetPosition() - bitmap->GetSize() / 2;
727  wxPoint botRight = bitmap->GetPosition() + bitmap->GetSize() / 2;
728 
729  m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
730  m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
731  m_editPoints->Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
732  m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
733  break;
734  }
735 
736  case SCH_SHEET_T:
737  {
738  SCH_SHEET* sheet = (SCH_SHEET*) item;
739  wxPoint topLeft = sheet->GetPosition();
740  wxPoint botRight = sheet->GetPosition() + sheet->GetSize();
741 
742  m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
743  m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
744  m_editPoints->Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
745  m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
746  break;
747  }
748 
749  case SCH_LINE_T:
750  {
751  SCH_LINE* line = (SCH_LINE*) item;
752 
753  m_editPoints->Point( LINE_START ).SetPosition( line->GetStartPoint() );
754  m_editPoints->Point( LINE_END ).SetPosition( line->GetEndPoint() );
755  break;
756  }
757 
758  default:
759  break;
760  }
761 
762  getView()->Update( m_editPoints.get() );
763 }
764 
765 
767 {
769 
770  if( aPoint )
771  {
773  controls->ForceCursorPosition( true, aPoint->GetPosition() );
774  controls->ShowCursor( true );
775  }
776  else
777  {
778  if( m_frame->ToolStackIsEmpty() )
779  controls->ShowCursor( false );
780 
781  controls->ForceCursorPosition( false );
782  }
783 
784  m_editedPoint = aPoint;
785 }
786 
787 
789 {
790  if( !m_editPoints || !m_editedPoint )
791  return false;
792 
793  LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() );
794 
795  if( !polyLine || polyLine->GetCornerCount() < 3 )
796  return false;
797 
798  const std::vector<wxPoint>& pts = polyLine->GetPolyPoints();
799 
800  for( unsigned i = 0; i < polyLine->GetCornerCount(); ++i )
801  {
802  if( pts[i] == mapCoords( m_editedPoint->GetPosition() ) )
803  return true;
804  }
805 
806  return false;
807 }
808 
809 
811 {
812  if( !m_editPoints || !m_editedPoint )
813  return false;
814 
815  LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() );
816 
817  if( !polyLine )
818  return false;
819 
820  VECTOR2I cursorPos = getViewControls()->GetCursorPosition();
821  double threshold = getView()->ToWorld( EDIT_POINT::POINT_SIZE );
822 
823  return polyLine->HitTest( mapCoords( cursorPos ), (int) threshold );
824 }
825 
826 
828 {
829  if( !m_editPoints )
830  return 0;
831 
832  LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() );
833 
834  if( !polyLine )
835  return false;
836 
837  VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !aEvent.Modifier( MD_ALT ) );
838  polyLine->AddCorner( mapCoords( cursorPos ) );
839 
840  updateItem( polyLine, true );
841  updatePoints();
842 
843  return 0;
844 }
845 
846 
848 {
849  if( !m_editPoints || !m_editedPoint )
850  return 0;
851 
852  LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() );
853 
854  if( !polyLine || polyLine->GetCornerCount() < 3 )
855  return 0;
856 
857  polyLine->RemoveCorner( getEditedPointIndex() );
858 
859  updateItem( polyLine, true );
860  updatePoints();
861 
862  return 0;
863 }
864 
865 
867 {
868  updatePoints();
869  return 0;
870 }
871 
872 
874 {
875  if( m_isSymbolEditor )
876  {
877  saveCopyInUndoList( m_editPoints->GetParent()->GetParent(), UNDO_REDO::LIBEDIT );
878  }
879  else
880  {
882 
883  if( m_editPoints->GetParent()->Type() == SCH_LINE_T )
884  {
885  EDA_ITEM* connection = m_editPoints->Point( LINE_START ).GetConnection();
886 
887  if( connection )
888  saveCopyInUndoList( (SCH_ITEM*) connection, UNDO_REDO::CHANGED, true );
889 
890  connection = m_editPoints->Point( LINE_END ).GetConnection();
891 
892  if( connection )
893  saveCopyInUndoList( (SCH_ITEM*) connection, UNDO_REDO::CHANGED, true );
894  }
895  }
896 }
897 
898 
900 {
901  if( m_isSymbolEditor )
902  static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->RollbackSymbolFromUndo();
903  else
904  static_cast<SCH_EDIT_FRAME*>( m_frame )->RollbackSchematicFromUndo();
905 }
906 
907 
909 {
915 }
916 
917 
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:208
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Function Wait()
static TOOL_ACTION activatePointEditor
Definition: actions.h:168
wxPoint GetStartPoint() const
Definition: sch_line.h:94
wxPoint GetEnd() const
Definition: lib_rectangle.h:87
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:456
VIEW_CONTROLS class definition.
static TOOL_ACTION pointEditorAddCorner
Definition: ee_actions.h:136
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:357
TOOL_MENU & GetToolMenu()
bool IsMotion() const
Definition: tool_event.h:306
wxPoint GetPosition() const override
Definition: lib_circle.h:72
EDIT_POINT * m_editedPoint
Currently edited point, NULL if there is none.
void updatePoints()
Updates edit points with item's points.
virtual wxPoint GetPosition() const
Definition: eda_item.h:325
wxPoint GetPosition() const override
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()
void SetCurrentCursor(KICURSOR cursor)
Function SetCurrentCursor Set the current cursor shape for this panel.
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:213
FIELDS_AUTOPLACED GetFieldsAutoplaced() const
Return whether the fields have been automatically placed.
Definition: sch_item.h:453
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:187
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:75
wxSize GetSize() const
Definition: sch_bitmap.cpp:125
bool Init() override
Function Init() 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.
void SetFlags(STATUS_FLAGS aMask)
Definition: eda_item.h:220
virtual VECTOR2I GetPosition() const
Function GetPosition()
Definition: edit_points.h:71
#define NULL
static TOOL_ACTION pointEditorRemoveCorner
Definition: ee_actions.h:137
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)
Similar to m_frame->SaveCopyInUndoList(), but handles items that are owned by their parents.
Definition: ee_tool_base.h:138
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: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
TOOL_EVENT.
Definition: tool_event.h:171
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:416
bool ToolStackIsEmpty()
Definition: tools_holder.h:136
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:181
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: eda_item.h:250
void updateParentItem() const
Updates 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:571
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)
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:107
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:287
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition: sch_sheet.h:364
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
#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:376
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
ARC_POINTS
void SetEnd(const wxPoint &aEnd)
Definition: lib_rectangle.h:86
std::shared_ptr< EDIT_POINTS > m_editPoints
Currently available edit points.
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.
int getEditedPointIndex() const
wxPoint GetPosition() const override
Definition: sch_line.h:231
CIRCLE_POINTS
void SetPosition(const wxPoint &aPosition) override
Definition: sch_sheet.cpp:785
double GetImageScale() const
Definition: sch_bitmap.h:71
EE_RTREE & Items()
Definition: sch_screen.h:159
wxPoint GetEnd() const
Definition: lib_arc.h:114
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.
EDA_ITEM is a base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:148
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:197
void Activate()
Function Activate() Runs the tool.
void SetPosition(const wxPoint &aPosition) override
Definition: lib_item.h:249
#define ENDPOINT
ends. (Used to support dragging.)
Definition: eda_item.h:112
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:327
EDIT_POINT.
Definition: edit_points.h:46
void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual) override
Definition: sch_sheet.cpp:499
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:42
VIEW.
Definition: view.h:63
void RemoveCorner(int aIdx)
bool HasFlag(STATUS_FLAGS aFlag)
Definition: eda_item.h:223
void setTransitions() override
Sets up handlers for various 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)
Adds 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:194
static std::shared_ptr< EDIT_POINTS > Make(EDA_ITEM *aItem, SCH_BASE_FRAME *frame)
wxSize GetSize()
Definition: sch_sheet.h:286
const VECTOR2D Position() const
Returns mouse cursor position in world coordinates.
Definition: tool_event.h:274
wxPoint GetPosition() const override
Definition: lib_rectangle.h:74
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.
void SetEnd(const wxPoint &aPosition)
Definition: lib_circle.h:74
EDA_ITEM * Front() const
Definition: selection.h:201
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, informs the associated VIEW that the graphical representation of this item has cha...
Definition: view.cpp:1513
KICAD_T Type() const
Function Type()
Definition: eda_item.h:181
Color has changed.
Definition: view_item.h:59
wxPoint GetPosition() const override
Definition: lib_arc.h:90
void SetEditState(int aState)
Definition: lib_arc.h:84
virtual void SetPosition(const VECTOR2I &aPosition)
Function SetPosition()
Definition: edit_points.h:108
wxPoint GetEndPoint() const
Definition: sch_line.h:97