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 <eeschema_id.h>
29 #include <confirm.h>
30 #include <view/view_controls.h>
31 #include <view/view.h>
32 #include <tool/tool_manager.h>
35 #include <tools/lib_pin_tool.h>
36 #include <class_libentry.h>
37 #include <bitmaps.h>
38 #include <lib_text.h>
40 #include <lib_arc.h>
41 #include <lib_circle.h>
42 #include <lib_polyline.h>
43 #include <lib_rectangle.h>
44 #include "ee_point_editor.h"
45 
46 static void* g_lastPinWeakPtr;
47 
48 
50  EE_TOOL_BASE<LIB_EDIT_FRAME>( "eeschema.SymbolDrawing" )
51 {
52 }
53 
54 
56 {
58 
59  auto isDrawingCondition = [] ( const SELECTION& aSel ) {
60  LIB_ITEM* item = (LIB_ITEM*) aSel.Front();
61  return item && item->IsNew();
62  };
63 
64  m_menu.GetMenu().AddItem( EE_ACTIONS::finishDrawing, isDrawingCondition, 2 );
65 
66  return true;
67 }
68 
69 
71 {
72  KICAD_T type = aEvent.Parameter<KICAD_T>();
73  LIB_PIN_TOOL* pinTool = type == LIB_PIN_T ? m_toolMgr->GetTool<LIB_PIN_TOOL>() : nullptr;
74  VECTOR2I cursorPos;
75  EDA_ITEM* item = nullptr;
76 
78  getViewControls()->ShowCursor( true );
79 
80  std::string tool = aEvent.GetCommandStr().get();
81  m_frame->PushTool( tool );
82  Activate();
83 
84  // Prime the pump
85  if( aEvent.HasPosition() )
87 
88  // Main loop: keep receiving events
89  while( TOOL_EVENT* evt = Wait() )
90  {
91  m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_PENCIL );
92  cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
93 
94  auto cleanup = [&] () {
97  delete item;
98  item = nullptr;
99  };
100 
101  if( evt->IsCancelInteractive() )
102  {
103  if( item )
104  cleanup();
105  else
106  {
107  m_frame->PopTool( tool );
108  break;
109  }
110  }
111  else if( evt->IsActivate() )
112  {
113  if( item )
114  cleanup();
115 
116  if( evt->IsMoveTool() )
117  {
118  // leave ourselves on the stack so we come back after the move
119  break;
120  }
121  else
122  {
123  m_frame->PopTool( tool );
124  break;
125  }
126  }
127 
128  else if( evt->IsClick( BUT_LEFT ) )
129  {
130  LIB_PART* part = m_frame->GetCurPart();
131 
132  if( !part )
133  continue;
134 
135  // First click creates...
136  if( !item )
137  {
139 
140  switch( type )
141  {
142  case LIB_PIN_T:
143  {
144  item = pinTool->CreatePin( wxPoint( cursorPos.x, -cursorPos.y ), part );
145  g_lastPinWeakPtr = item;
146  break;
147  }
148  case LIB_TEXT_T:
149  {
150  LIB_TEXT* text = new LIB_TEXT( part );
151  text->SetPosition( wxPoint( cursorPos.x, -cursorPos.y ) );
154 
155  DIALOG_LIB_EDIT_TEXT dlg( m_frame, text );
156 
157  if( dlg.ShowModal() != wxID_OK )
158  delete text;
159  else
160  item = text;
161 
162  break;
163  }
164  default:
165  wxFAIL_MSG( "TwoClickPlace(): unknown type" );
166  }
167 
168  // Restore cursor after dialog
169  getViewControls()->WarpCursor( getViewControls()->GetCursorPosition(), true );
170 
171  if( item )
172  {
173  item->SetFlags( IS_NEW | IS_MOVED );
174  m_view->ClearPreview();
175  m_view->AddToPreview( item->Clone() );
176  m_selectionTool->AddItemToSel( item );
177  }
178 
179  getViewControls()->SetCursorPosition( cursorPos, false );
180  }
181 
182  // ... and second click places:
183  else
184  {
185  m_frame->SaveCopyInUndoList( part );
186 
187  switch( item->Type() )
188  {
189  case LIB_PIN_T:
190  pinTool->PlacePin( (LIB_PIN*) item );
191  break;
192  case LIB_TEXT_T:
193  part->AddDrawItem( (LIB_TEXT*) item );
194  break;
195  default:
196  wxFAIL_MSG( "TwoClickPlace(): unknown type" );
197  }
198 
199  item->ClearEditFlags();
200  item = nullptr;
201  m_view->ClearPreview();
202 
203  m_frame->RebuildView();
204  m_frame->OnModify();
205  }
206  }
207  else if( evt->IsClick( BUT_RIGHT ) )
208  {
209  // Warp after context menu only if dragging...
210  if( !item )
212 
214  }
215 
216  else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
217  {
218  static_cast<LIB_ITEM*>( item )->SetPosition( wxPoint( cursorPos.x, -cursorPos.y ) );
219  m_view->ClearPreview();
220  m_view->AddToPreview( item->Clone() );
221  }
222 
223  else
224  evt->SetPassEvent();
225 
226  // Enable autopanning and cursor capture only when there is an item to be placed
227  getViewControls()->SetAutoPan( item != nullptr );
228  getViewControls()->CaptureCursor( item != nullptr );
229  }
230 
231  return 0;
232 }
233 
234 
236 {
237  KICAD_T type = aEvent.Parameter<KICAD_T>();
239 
240  // We might be running as the same shape in another co-routine. Make sure that one
241  // gets whacked.
243 
245  getViewControls()->ShowCursor( true );
246 
247  std::string tool = aEvent.GetCommandStr().get();
248  m_frame->PushTool( tool );
249  Activate();
250 
251  LIB_PART* part = m_frame->GetCurPart();
252  LIB_ITEM* item = nullptr;
253 
254  // Prime the pump
255  if( aEvent.HasPosition() )
257 
258  // Main loop: keep receiving events
259  while( TOOL_EVENT* evt = Wait() )
260  {
261  if( !pointEditor->HasPoint() )
262  m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_PENCIL );
263 
264  VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
265 
266  auto cleanup = [&] () {
268  m_view->ClearPreview();
269  delete item;
270  item = nullptr;
271  };
272 
273  if( evt->IsCancelInteractive() )
274  {
275  if( item )
276  cleanup();
277  else
278  {
279  m_frame->PopTool( tool );
280  break;
281  }
282  }
283 
284  else if( evt->IsActivate() )
285  {
286  if( item )
287  cleanup();
288 
289  if( evt->IsPointEditor() )
290  {
291  // don't exit (the point editor runs in the background)
292  }
293  else if( evt->IsMoveTool() )
294  {
295  // leave ourselves on the stack so we come back after the move
296  break;
297  }
298  else
299  {
300  m_frame->PopTool( tool );
301  break;
302  }
303  }
304 
305  else if( evt->IsClick( BUT_LEFT ) && !item )
306  {
307  if( !part )
308  continue;
309 
311 
312  switch( type )
313  {
314  case LIB_ARC_T: item = new LIB_ARC( part ); break;
315  case LIB_CIRCLE_T: item = new LIB_CIRCLE( part ); break;
316  case LIB_POLYLINE_T: item = new LIB_POLYLINE( part ); break;
317  case LIB_RECTANGLE_T: item = new LIB_RECTANGLE( part ); break;
318  default: break; // keep compiler quiet
319  }
320 
321  wxASSERT( item );
322 
325  item->SetFlags( IS_NEW );
326  item->BeginEdit( wxPoint( cursorPos.x, -cursorPos.y ) );
327 
329  item->SetUnit( m_frame->GetUnit() );
330 
332  item->SetConvert( m_frame->GetConvert() );
333 
334  m_selectionTool->AddItemToSel( item );
335  }
336 
337  else if( item && ( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT )
338  || evt->IsAction( &EE_ACTIONS::finishDrawing ) ) )
339  {
340  if( evt->IsDblClick( BUT_LEFT ) || evt->IsAction( &EE_ACTIONS::finishDrawing )
341  || !item->ContinueEdit( wxPoint( cursorPos.x, -cursorPos.y ) ) )
342  {
343  item->EndEdit();
344  item->ClearEditFlags();
345  m_view->ClearPreview();
346 
347  m_frame->SaveCopyInUndoList( part );
348  part->AddDrawItem( item );
349  item = nullptr;
350 
351  m_frame->RebuildView();
352  m_frame->OnModify();
354  }
355  }
356 
357  else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
358  {
359  item->CalcEdit( wxPoint( cursorPos.x, -cursorPos.y) );
360  m_view->ClearPreview();
361  m_view->AddToPreview( item->Clone() );
362  }
363 
364  else if( evt->IsDblClick( BUT_LEFT ) && !item )
365  {
367  }
368 
369  else if( evt->IsClick( BUT_RIGHT ) )
370  {
371  // Warp after context menu only if dragging...
372  if( !item )
374 
376  }
377 
378  else
379  evt->SetPassEvent();
380 
381  // Enable autopanning and cursor capture only when there is a shape being drawn
382  getViewControls()->SetAutoPan( item != nullptr );
383  getViewControls()->CaptureCursor( item != nullptr );
384  }
385 
386  return 0;
387 }
388 
389 
391 {
392  getViewControls()->ShowCursor( true );
393  getViewControls()->SetSnapping( true );
394 
395  std::string tool = aEvent.GetCommandStr().get();
396  m_frame->PushTool( tool );
397  Activate();
398 
399  // Main loop: keep receiving events
400  while( TOOL_EVENT* evt = Wait() )
401  {
402  m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_BULLSEYE );
403 
404  if( evt->IsCancelInteractive() )
405  {
406  m_frame->PopTool( tool );
407  break;
408  }
409  else if( evt->IsActivate() )
410  {
411  m_frame->PopTool( tool );
412  break;
413  }
414  else if( evt->IsClick( BUT_LEFT ) )
415  {
416  LIB_PART* part = m_frame->GetCurPart();
417 
418  if( !part )
419  continue;
420 
421  VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
422  wxPoint offset( -cursorPos.x, cursorPos.y );
423 
424  part->SetOffset( offset );
425 
426  // Refresh the view without changing the viewport
427  auto center = m_view->GetCenter();
428  center.x += offset.x;
429  center.y -= offset.y;
430  m_view->SetCenter( center );
432  m_frame->OnModify();
433  }
434  else if( evt->IsClick( BUT_RIGHT ) )
435  {
437  }
438  else
439  evt->SetPassEvent();
440  }
441 
442  return 0;
443 }
444 
445 
447 {
449  LIB_PART* part = m_frame->GetCurPart();
450  LIB_PIN* sourcePin = nullptr;
451 
452  if( !part )
453  return 0;
454 
455  // See if we have a pin matching our weak ptr
456  for( LIB_PIN* test = part->GetNextPin(); test; test = part->GetNextPin( test ) )
457  {
458  if( (void*) test == g_lastPinWeakPtr )
459  sourcePin = test;
460  }
461 
462  if( sourcePin )
463  {
464  LIB_PIN* pin = pinTool->RepeatPin( sourcePin );
465  g_lastPinWeakPtr = pin;
466 
468 
469  if( pin )
471  }
472 
473  return 0;
474 }
475 
476 
478 {
487 }
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.
LIB_PART * GetCurPart() const
Return the current part being edited or NULL if none selected.
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:155
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:159
int GetConvert() const
void SetPosition(const wxPoint &aPosition)
Definition: lib_item.h:252
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:219
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:109
static int g_LastLineWidth
int TwoClickPlace(const TOOL_EVENT &aEvent)
static void * g_lastPinWeakPtr
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:155
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:61
bool IsNew() const
Definition: base_struct.h:228
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:265
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:137
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:427
static double g_LastTextAngle
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
Class TOOL_EVENT.
Definition: tool_event.h:168
void ClearPreview()
Definition: sch_view.cpp:143
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:140
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:306
void SetConvert(int aConvert)
Definition: lib_item.h:303
virtual void BeginEdit(const wxPoint aPosition)
Begin drawing a component library draw item at aPosition.
Definition: lib_item.h:125
OPT< std::string > GetCommandStr() const
Definition: tool_event.h:455
void SetUnit(int aUnit)
Definition: lib_item.h:300
The symbol library editor main window.
int AddItemToSel(const TOOL_EVENT &aEvent)
Class 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:372
static int g_LastTextSize
static TOOL_ACTION drawSymbolArc
Definition: ee_actions.h:108
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:163
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.
Class 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:257
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:42
void ClearEditFlags()
Definition: base_struct.h:283
virtual void EndEdit()
End an object editing action.
Definition: lib_item.h:144
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
virtual void SetCursorPosition(const VECTOR2D &aPosition, bool aWarpView=true, bool aTriggeredByArrows=false)=0
Moves cursor to the requested position expressed in world coordinates.
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.
static TOOL_ACTION cursorClick
Definition: actions.h:115
KICAD_T Type() const
Function Type()
Definition: base_struct.h:210
#define IS_MOVED
Item being moved.
Definition: base_struct.h:119