KiCad PCB EDA Suite
lib_drawing_tools.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 <ee_actions.h>
26 #include <lib_edit_frame.h>
27 #include <sch_view.h>
28 #include <confirm.h>
29 #include <view/view_controls.h>
30 #include <view/view.h>
31 #include <tool/tool_manager.h>
34 #include <tools/lib_pin_tool.h>
35 #include <class_libentry.h>
36 #include <bitmaps.h>
37 #include <lib_text.h>
39 #include <lib_arc.h>
40 #include <lib_circle.h>
41 #include <lib_polyline.h>
42 #include <lib_rectangle.h>
43 #include "ee_point_editor.h"
44 
45 static void* g_lastPinWeakPtr;
46 
47 
49  EE_TOOL_BASE<LIB_EDIT_FRAME>( "eeschema.SymbolDrawing" )
50 {
51 }
52 
53 
55 {
57 
58  auto isDrawingCondition = [] ( const SELECTION& aSel ) {
59  LIB_ITEM* item = (LIB_ITEM*) aSel.Front();
60  return item && item->IsNew();
61  };
62 
63  m_menu.GetMenu().AddItem( EE_ACTIONS::finishDrawing, isDrawingCondition, 2 );
64 
65  return true;
66 }
67 
68 
70 {
71  KICAD_T type = aEvent.Parameter<KICAD_T>();
72  LIB_PIN_TOOL* pinTool = type == LIB_PIN_T ? m_toolMgr->GetTool<LIB_PIN_TOOL>() : nullptr;
73  VECTOR2I cursorPos;
74  EDA_ITEM* item = nullptr;
75 
77  getViewControls()->ShowCursor( true );
78 
79  std::string tool = aEvent.GetCommandStr().get();
80  m_frame->PushTool( tool );
81  Activate();
82 
83  // Prime the pump
84  if( aEvent.HasPosition() )
86 
87  // Main loop: keep receiving events
88  while( TOOL_EVENT* evt = Wait() )
89  {
90  m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_PENCIL );
91  cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
92 
93  auto cleanup = [&] () {
96  delete item;
97  item = nullptr;
98  };
99 
100  if( evt->IsCancelInteractive() )
101  {
102  if( item )
103  cleanup();
104  else
105  {
106  m_frame->PopTool( tool );
107  break;
108  }
109  }
110  else if( evt->IsActivate() )
111  {
112  if( item )
113  cleanup();
114 
115  if( evt->IsMoveTool() )
116  {
117  // leave ourselves on the stack so we come back after the move
118  break;
119  }
120  else
121  {
122  m_frame->PopTool( tool );
123  break;
124  }
125  }
126 
127  else if( evt->IsClick( BUT_LEFT ) )
128  {
129  LIB_PART* part = m_frame->GetCurPart();
130 
131  if( !part )
132  continue;
133 
134  // First click creates...
135  if( !item )
136  {
138 
139  switch( type )
140  {
141  case LIB_PIN_T:
142  {
143  item = pinTool->CreatePin( wxPoint( cursorPos.x, -cursorPos.y ), part );
144  g_lastPinWeakPtr = item;
145  break;
146  }
147  case LIB_TEXT_T:
148  {
149  LIB_TEXT* text = new LIB_TEXT( part );
150  text->SetPosition( wxPoint( cursorPos.x, -cursorPos.y ) );
153 
154  DIALOG_LIB_EDIT_TEXT dlg( m_frame, text );
155 
156  if( dlg.ShowModal() != wxID_OK )
157  delete text;
158  else
159  item = text;
160 
161  break;
162  }
163  default:
164  wxFAIL_MSG( "TwoClickPlace(): unknown type" );
165  }
166 
167  // Restore cursor after dialog
168  getViewControls()->WarpCursor( getViewControls()->GetCursorPosition(), true );
169 
170  if( item )
171  {
172  item->SetFlags( IS_NEW | IS_MOVED );
173  m_view->ClearPreview();
174  m_view->AddToPreview( item->Clone() );
175  m_selectionTool->AddItemToSel( item );
176  }
177 
178  getViewControls()->SetCursorPosition( cursorPos, false );
179  }
180 
181  // ... and second click places:
182  else
183  {
184  m_frame->SaveCopyInUndoList( part );
185 
186  switch( item->Type() )
187  {
188  case LIB_PIN_T:
189  pinTool->PlacePin( (LIB_PIN*) item );
190  break;
191  case LIB_TEXT_T:
192  part->AddDrawItem( (LIB_TEXT*) item );
193  break;
194  default:
195  wxFAIL_MSG( "TwoClickPlace(): unknown type" );
196  }
197 
198  item->ClearEditFlags();
199  item = nullptr;
200  m_view->ClearPreview();
201 
202  m_frame->RebuildView();
203  m_frame->OnModify();
204  }
205  }
206  else if( evt->IsClick( BUT_RIGHT ) )
207  {
208  // Warp after context menu only if dragging...
209  if( !item )
211 
213  }
214 
215  else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
216  {
217  static_cast<LIB_ITEM*>( item )->SetPosition( wxPoint( cursorPos.x, -cursorPos.y ) );
218  m_view->ClearPreview();
219  m_view->AddToPreview( item->Clone() );
220  }
221 
222  else
223  evt->SetPassEvent();
224 
225  // Enable autopanning and cursor capture only when there is an item to be placed
226  getViewControls()->SetAutoPan( item != nullptr );
227  getViewControls()->CaptureCursor( item != nullptr );
228  }
229 
230  return 0;
231 }
232 
233 
235 {
236  KICAD_T type = aEvent.Parameter<KICAD_T>();
238 
239  // We might be running as the same shape in another co-routine. Make sure that one
240  // gets whacked.
242 
244  getViewControls()->ShowCursor( true );
245 
246  std::string tool = aEvent.GetCommandStr().get();
247  m_frame->PushTool( tool );
248  Activate();
249 
250  LIB_PART* part = m_frame->GetCurPart();
251  LIB_ITEM* item = nullptr;
252 
253  // Prime the pump
254  if( aEvent.HasPosition() )
256 
257  // Main loop: keep receiving events
258  while( TOOL_EVENT* evt = Wait() )
259  {
260  if( !pointEditor->HasPoint() )
261  m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_PENCIL );
262 
263  VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
264 
265  auto cleanup = [&] () {
267  m_view->ClearPreview();
268  delete item;
269  item = nullptr;
270  };
271 
272  if( evt->IsCancelInteractive() )
273  {
274  if( item )
275  cleanup();
276  else
277  {
278  m_frame->PopTool( tool );
279  break;
280  }
281  }
282 
283  else if( evt->IsActivate() )
284  {
285  if( item )
286  cleanup();
287 
288  if( evt->IsPointEditor() )
289  {
290  // don't exit (the point editor runs in the background)
291  }
292  else if( evt->IsMoveTool() )
293  {
294  // leave ourselves on the stack so we come back after the move
295  break;
296  }
297  else
298  {
299  m_frame->PopTool( tool );
300  break;
301  }
302  }
303 
304  else if( evt->IsClick( BUT_LEFT ) && !item )
305  {
306  if( !part )
307  continue;
308 
310 
311  switch( type )
312  {
313  case LIB_ARC_T: item = new LIB_ARC( part ); break;
314  case LIB_CIRCLE_T: item = new LIB_CIRCLE( part ); break;
315  case LIB_POLYLINE_T: item = new LIB_POLYLINE( part ); break;
316  case LIB_RECTANGLE_T: item = new LIB_RECTANGLE( part ); break;
317  default: break; // keep compiler quiet
318  }
319 
320  wxASSERT( item );
321 
324  item->SetFlags( IS_NEW );
325  item->BeginEdit( wxPoint( cursorPos.x, -cursorPos.y ) );
326 
328  item->SetUnit( m_frame->GetUnit() );
329 
331  item->SetConvert( m_frame->GetConvert() );
332 
333  m_selectionTool->AddItemToSel( item );
334  }
335 
336  else if( item && ( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT )
337  || evt->IsAction( &EE_ACTIONS::finishDrawing ) ) )
338  {
339  if( evt->IsDblClick( BUT_LEFT ) || evt->IsAction( &EE_ACTIONS::finishDrawing )
340  || !item->ContinueEdit( wxPoint( cursorPos.x, -cursorPos.y ) ) )
341  {
342  item->EndEdit();
343  item->ClearEditFlags();
344  m_view->ClearPreview();
345 
346  m_frame->SaveCopyInUndoList( part );
347  part->AddDrawItem( item );
348  item = nullptr;
349 
350  m_frame->RebuildView();
351  m_frame->OnModify();
353  }
354  }
355 
356  else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
357  {
358  item->CalcEdit( wxPoint( cursorPos.x, -cursorPos.y) );
359  m_view->ClearPreview();
360  m_view->AddToPreview( item->Clone() );
361  }
362 
363  else if( evt->IsDblClick( BUT_LEFT ) && !item )
364  {
366  }
367 
368  else if( evt->IsClick( BUT_RIGHT ) )
369  {
370  // Warp after context menu only if dragging...
371  if( !item )
373 
375  }
376 
377  else
378  evt->SetPassEvent();
379 
380  // Enable autopanning and cursor capture only when there is a shape being drawn
381  getViewControls()->SetAutoPan( item != nullptr );
382  getViewControls()->CaptureCursor( item != nullptr );
383  }
384 
385  return 0;
386 }
387 
388 
390 {
391  getViewControls()->ShowCursor( true );
392  getViewControls()->SetSnapping( true );
393 
394  std::string tool = aEvent.GetCommandStr().get();
395  m_frame->PushTool( tool );
396  Activate();
397 
398  // Main loop: keep receiving events
399  while( TOOL_EVENT* evt = Wait() )
400  {
401  m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_BULLSEYE );
402 
403  if( evt->IsCancelInteractive() )
404  {
405  m_frame->PopTool( tool );
406  break;
407  }
408  else if( evt->IsActivate() )
409  {
410  m_frame->PopTool( tool );
411  break;
412  }
413  else if( evt->IsClick( BUT_LEFT ) )
414  {
415  LIB_PART* part = m_frame->GetCurPart();
416 
417  if( !part )
418  continue;
419 
420  VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
421  wxPoint offset( -cursorPos.x, cursorPos.y );
422 
423  part->SetOffset( offset );
424 
425  // Refresh the view without changing the viewport
426  auto center = m_view->GetCenter();
427  center.x += offset.x;
428  center.y -= offset.y;
429  m_view->SetCenter( center );
431  m_frame->OnModify();
432  }
433  else if( evt->IsClick( BUT_RIGHT ) )
434  {
436  }
437  else
438  evt->SetPassEvent();
439  }
440 
441  return 0;
442 }
443 
444 
446 {
448  LIB_PART* part = m_frame->GetCurPart();
449  LIB_PIN* sourcePin = nullptr;
450 
451  if( !part )
452  return 0;
453 
454  // See if we have a pin matching our weak ptr
455  for( LIB_PIN* test = part->GetNextPin(); test; test = part->GetNextPin( test ) )
456  {
457  if( (void*) test == g_lastPinWeakPtr )
458  sourcePin = test;
459  }
460 
461  if( sourcePin )
462  {
463  LIB_PIN* pin = pinTool->RepeatPin( sourcePin );
464  g_lastPinWeakPtr = pin;
465 
467 
468  if( pin )
470  }
471 
472  return 0;
473 }
474 
475 
477 {
486 }
void SetTextAngle(double aAngle)
Definition: eda_text.h:150
virtual void ShowCursor(bool aEnabled)
Function ShowCursor() Enables or disables display of cursor.
bool m_DrawSpecificUnit
Specify which component parts the current draw item applies to.
static TOOL_ACTION properties
Definition: ee_actions.h:122
virtual void PushTool(const std::string &actionName)
NB: the definition of "tool" is different at the user level.
static TOOL_ACTION placeSymbolText
Definition: ee_actions.h:105
static TOOL_ACTION drawSymbolLines
Definition: ee_actions.h:109
TOOL_MENU m_menu
functions below are not yet implemented - their interface may change
void AddToPreview(EDA_ITEM *aItem, bool aTakeOwnership=true)
Definition: sch_view.cpp:193
int PlaceAnchor(const TOOL_EVENT &aEvent)
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Function Wait()
static TOOL_ACTION activatePointEditor
Definition: actions.h:163
int GetConvert() const
void SetPosition(const wxPoint &aPosition)
Definition: lib_item.h:260
This file is part of the common library.
Define a symbol library graphical text item.
Definition: lib_text.h:40
const VECTOR2D & GetCenter() const
Function GetCenter() Returns the center point of this VIEW (in world space coordinates)
Definition: view.h:328
void SetCurrentCursor(wxStockCursor aStockCursorID)
Function SetCurrentCursor Set the current cursor shape for this panel.
virtual void SetWidth(int aWidth)=0
VIEW_CONTROLS class definition.
CONDITIONAL_MENU & GetMenu()
Function GetMenu.
Definition: tool_menu.cpp:46
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:218
void RecacheAllItems()
Function RecacheAllItems() Rebuilds GAL display lists.
Definition: view.cpp:1402
static FILL_T g_LastFillStyle
virtual void SetSnapping(bool aEnabled)
Function SetSnapping() Enables/disables snapping cursor to grid.
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:139
static int g_LastLineWidth
int TwoClickPlace(const TOOL_EVENT &aEvent)
static void * g_lastPinWeakPtr
virtual void SetCursorPosition(const VECTOR2D &aPosition, bool aWarpView=true, bool aTriggeredByArrows=false, long aArrowCommand=0)=0
Moves cursor to the requested position expressed in world coordinates.
LIB_PART * GetCurPart()
Return the current part being edited or NULL if none selected.
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:222
virtual void CalcEdit(const wxPoint &aPosition)
Calculates the attributes of an item at aPosition when it is being edited.
Definition: lib_item.h:163
int DrawShape(const TOOL_EVENT &aEvent)
void setTransitions() override
Sets up handlers for various events.
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Function Go()
void DeactivateTool()
Function DeactivateTool() Deactivates the currently active tool.
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:78
virtual EDA_ITEM * Clone() const
Function Clone creates a duplicate of this item with linked list members set to NULL.
The base class for drawable items used by schematic library components.
Definition: lib_item.h:60
bool IsNew() const
Definition: base_struct.h:220
void SetOffset(const wxPoint &aOffset)
Move the part aOffset.
bool m_DrawSpecificConvert
Convert of the item currently being drawn.
static TOOL_ACTION drawSymbolRectangle
Definition: ee_actions.h:106
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
Definition: ee_tool_base.h:69
void AddDrawItem(LIB_ITEM *aItem)
Add a new draw aItem to the draw object list.
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
EE_SELECTION & GetSelection()
Function GetSelection()
#define IS_NEW
New item, just created.
Definition: base_struct.h:120
virtual void WarpCursor(const VECTOR2D &aPosition, bool aWorldCoordinates=false, bool aWarpView=false)=0
Function WarpCursor() If enabled (.
static TOOL_ACTION placeSymbolPin
Definition: ee_actions.h:104
int GetUnit() const
void SetCenter(const VECTOR2D &aCenter)
Function SetCenter() Sets the center point of the VIEW (i.e.
Definition: view.cpp:604
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:257
static TOOL_ACTION addItemToSel
Selects an item (specified as the event parameter).
Definition: ee_actions.h:61
virtual bool ContinueEdit(const wxPoint aPosition)
Continue an edit in progress at aPosition.
Definition: lib_item.h:145
virtual void CaptureCursor(bool aEnabled)
Function CaptureCursor() Forces the cursor to stay within the drawing panel area.
Class LIB_PIN definition.
T Parameter() const
Function Parameter() Returns a non-standard parameter assigned to the event.
Definition: tool_event.h:435
static double g_LastTextAngle
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
TOOL_EVENT.
Definition: tool_event.h:171
void ClearPreview()
Definition: sch_view.cpp:181
static TOOL_ACTION repeatDrawItem
Definition: ee_actions.h:117
static TOOL_ACTION drawSymbolCircle
Definition: ee_actions.h:107
Define a library symbol object.
EE_SELECTION_TOOL * m_selectionTool
Definition: ee_tool_base.h:153
static TOOL_ACTION clearSelection
Clears the current selection.
Definition: ee_actions.h:58
static TOOL_ACTION finishDrawing
Definition: ee_actions.h:111
LIB_PIN * RepeatPin(const LIB_PIN *aSourcePin)
virtual void SetAutoPan(bool aEnabled)
Function SetAutoPan Turns on/off auto panning (this feature is used when there is a tool active (eg.
void SetFillMode(FILL_T aFillMode)
Definition: lib_item.h:314
void SetConvert(int aConvert)
Definition: lib_item.h:311
virtual void BeginEdit(const wxPoint aPosition)
Begin drawing a component library draw item at aPosition.
Definition: lib_item.h:133
OPT< std::string > GetCommandStr() const
Definition: tool_event.h:463
void SetUnit(int aUnit)
Definition: lib_item.h:308
The symbol library editor main window.
int AddItemToSel(const TOOL_EVENT &aEvent)
EE_POINT_EDITOR.
int RepeatDrawItem(const TOOL_EVENT &aEvent)
void VetoContextMenuMouseWarp()
Disables mouse warping after the current context menu is closed.
Definition: tool_manager.h:414
static int g_LastTextSize
static TOOL_ACTION drawSymbolArc
Definition: ee_actions.h:108
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
Definition: base_struct.h:166
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag of the current symbol.
virtual void PopTool(const std::string &actionName)
void Activate()
Function Activate() Runs the tool.
EE_TOOL_BASE.
Definition: ee_tool_base.h:50
bool HasPosition() const
Returns if it this event has a valid position (true for mouse events and context-menu or hotkey-based...
Definition: tool_event.h:260
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:42
void ClearEditFlags()
Definition: base_struct.h:275
virtual void EndEdit()
End an object editing action.
Definition: lib_item.h:152
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Function AddItem()
void ShowContextMenu(SELECTION &aSelection)
Function ShowContextMenu.
Definition: tool_menu.cpp:59
void SaveCopyInUndoList(EDA_ITEM *ItemToCopy, UNDO_REDO_T undoType=UR_LIBEDIT, bool aAppend=false)
Create a copy of the current component, and save it in the undo list.
static TOOL_ACTION placeSymbolAnchor
Definition: ee_actions.h:110
static TOOL_ACTION refreshPreview
Definition: actions.h:101
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.
static TOOL_ACTION cursorClick
Definition: actions.h:118
KICAD_T Type() const
Function Type()
Definition: base_struct.h:212
#define IS_MOVED
Item being moved.
Definition: base_struct.h:119