KiCad PCB EDA Suite
pl_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 <class_draw_panel_gal.h>
26 #include <confirm.h>
27 #include <view/view_group.h>
28 #include <view/view_controls.h>
29 #include <view/view.h>
30 #include <tool/tool_manager.h>
31 #include <bitmaps.h>
34 
36 #include "pl_editor_frame.h"
37 #include "pl_editor_id.h"
38 #include "pl_point_editor.h"
39 #include "tools/pl_actions.h"
41 #include "tools/pl_drawing_tools.h"
42 
44  TOOL_INTERACTIVE( "plEditor.InteractiveDrawing" ),
45  m_frame( nullptr ),
46  m_selectionTool( nullptr )
47 {
48 }
49 
50 
52 {
53  m_frame = getEditFrame<PL_EDITOR_FRAME>();
55 
56  auto& ctxMenu = m_menu.GetMenu();
57 
58  // cancel current tool goes in main context menu at the top if present
60  ctxMenu.AddSeparator( 1 );
61 
62  // Finally, add the standard zoom/grid items
64 
65  return true;
66 }
67 
68 
70 {
71  if( aReason == MODEL_RELOAD )
72  m_frame = getEditFrame<PL_EDITOR_FRAME>();
73 }
74 
75 
77 {
79  VECTOR2I cursorPos;
80  WS_DRAW_ITEM_BASE* item = nullptr;
81  bool isText = aEvent.IsAction( &PL_ACTIONS::placeText );
82 
84  getViewControls()->ShowCursor( true );
85 
86  std::string tool = aEvent.GetCommandStr().get();
87  m_frame->PushTool( tool );
88  Activate();
89 
90  // Prime the pump
91  if( aEvent.HasPosition() )
93 
94  auto setCursor =
95  [&]()
96  {
97  if( item )
99  else
101  };
102 
103  setCursor();
104 
105  // Main loop: keep receiving events
106  while( TOOL_EVENT* evt = Wait() )
107  {
108  setCursor();
109 
110  cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
111 
112  auto cleanup =
113  [&] ()
114  {
116  item = nullptr;
117 
118  // There's nothing to roll-back, but we still need to pop the undo stack
119  // This also deletes the item being placed.
121  };
122 
123  if( evt->IsCancelInteractive() )
124  {
125  if( item )
126  cleanup();
127  else
128  {
129  m_frame->PopTool( tool );
130  break;
131  }
132  }
133  else if( evt->IsActivate() )
134  {
135  if( item )
136  cleanup();
137 
138  if( evt->IsMoveTool() )
139  {
140  // leave ourselves on the stack so we come back after the move
141  break;
142  }
143  else
144  {
145  m_frame->PopTool( tool );
146  break;
147  }
148  }
149  else if( evt->IsClick( BUT_LEFT ) )
150  {
151  // First click creates...
152  if( !item )
153  {
154  WS_DATA_ITEM* dataItem = m_frame->AddPageLayoutItem( type );
155 
156  if( dataItem ) // dataItem = nullptr can happens if the command was cancelled
157  {
159 
161 
162  item = dataItem->GetDrawItems()[0];
163  item->SetFlags( IS_NEW | IS_MOVED );
164  m_selectionTool->AddItemToSel( item );
165 
166  // update the cursor so it looks correct before another event
167  setCursor();
168  }
169  }
170  // ... and second click places:
171  else
172  {
173  item->GetPeer()->MoveStartPointToUi( (wxPoint) cursorPos );
174  item->SetPosition( item->GetPeer()->GetStartPosUi( 0 ) );
175  item->ClearEditFlags();
176  getView()->Update( item );
177 
178  item = nullptr;
179 
180  m_frame->OnModify();
181  }
182  }
183  else if( evt->IsClick( BUT_RIGHT ) )
184  {
185  // Warp after context menu only if dragging...
186  if( !item )
188 
190  }
191  else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
192  {
193  item->GetPeer()->MoveStartPointToUi( (wxPoint) cursorPos );
194  item->SetPosition( item->GetPeer()->GetStartPosUi( 0 ) );
195  getView()->Update( item );
196  }
197  else
198  evt->SetPassEvent();
199 
200  // Enable autopanning and cursor capture only when there is an item to be placed
201  getViewControls()->SetAutoPan( item != nullptr );
202  getViewControls()->CaptureCursor( item != nullptr );
203  }
204 
205  return 0;
206 }
207 
208 
210 {
212  WS_DRAW_ITEM_BASE* item = nullptr;
213 
214  // We might be running as the same shape in another co-routine. Make sure that one
215  // gets whacked.
217 
219  getViewControls()->ShowCursor( true );
220 
221  std::string tool = aEvent.GetCommandStr().get();
222  m_frame->PushTool( tool );
223  Activate();
224 
225  // Prime the pump
226  if( aEvent.HasPosition() )
228 
229  auto setCursor =
230  [&]()
231  {
233  };
234 
235  // Set initial cursor
236  setCursor();
237 
238  // Main loop: keep receiving events
239  while( TOOL_EVENT* evt = Wait() )
240  {
241  setCursor();
242 
243  VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
244 
245  if( evt->IsCancelInteractive() || evt->IsActivate() )
246  {
248 
249  if( item )
250  {
251  item = nullptr;
252 
253  // Pop the undo stack and delete the item being placed
255  }
256  else if( evt->IsCancelInteractive() )
257  {
258  break;
259  }
260 
261  if( evt->IsActivate() && !evt->IsPointEditor() && !evt->IsMoveTool() )
262  break;
263  }
264 
265  else if( evt->IsClick( BUT_LEFT ) )
266  {
267  if( !item ) // start drawing
268  {
271 
272  WS_DATA_ITEM* dataItem = m_frame->AddPageLayoutItem( type );
273  dataItem->MoveToUi( (wxPoint) cursorPos );
274 
275  item = dataItem->GetDrawItems()[0];
276  item->SetFlags( IS_NEW );
277  m_selectionTool->AddItemToSel( item );
278  }
279  else // finish drawing
280  {
281  item->ClearEditFlags();
282  item = nullptr;
284 
285  m_frame->OnModify();
286  }
287  }
288 
289  else if( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() )
290  {
291  if( item )
292  {
293  item->GetPeer()->MoveEndPointToUi( (wxPoint) cursorPos );
294  item->SetEnd( item->GetPeer()->GetEndPosUi( 0 ) );
295  getView()->Update( item );
296  }
297  }
298 
299  else if( evt->IsClick( BUT_RIGHT ) )
300  {
301  // Warp after context menu only if dragging...
302  if( !item )
304 
306  }
307 
308  else
309  evt->SetPassEvent();
310 
311  // Enable autopanning and cursor capture only when there is a shape being drawn
312  getViewControls()->SetAutoPan( item != nullptr );
313  getViewControls()->CaptureCursor( item != nullptr );
314  }
315 
316  m_frame->PopTool( tool );
317  return 0;
318 }
319 
320 
322 {
327 }
virtual void ShowCursor(bool aEnabled)
Function ShowCursor() Enables or disables display of cursor.
static bool ShowAlways(const SELECTION &aSelection)
The default condition function (always returns true).
WS_DATA_ITEM * GetPeer() const
Definition: ws_draw_item.h:75
void AddStandardSubMenus(TOOL_MENU &aMenu)
Function CreateBasicMenu.
TOOL_MENU m_menu
functions below are not yet implemented - their interface may change
void MoveToUi(wxPoint aPosition)
move item to a new position
void setTransitions() override
Sets up handlers for various events.
PL_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Function Wait()
static TOOL_ACTION activatePointEditor
Definition: actions.h:168
Work sheet structure type definitions.
Definition: ws_data_item.h:97
Model changes (required full reload)
Definition: tool_base.h:82
This file is part of the common library.
virtual void SetPosition(const wxPoint &aPos)
Definition: eda_item.h:327
static TOOL_ACTION drawLine
Definition: pl_actions.h:67
VIEW_CONTROLS class definition.
static TOOL_ACTION placeImage
Definition: pl_actions.h:65
CONDITIONAL_MENU & GetMenu()
Function GetMenu.
Definition: tool_menu.cpp:46
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:219
static TOOL_ACTION cancelInteractive
Definition: actions.h:65
virtual void PushTool(const std::string &actionName)
NB: the definition of "tool" is different at the user level.
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:141
static TOOL_ACTION placeText
Definition: pl_actions.h:64
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Function Go()
int AddItemToSel(const TOOL_EVENT &aEvent)
void DeactivateTool()
Function DeactivateTool() Deactivates the currently active tool.
void SetCurrentCursor(KICURSOR cursor)
Function SetCurrentCursor Set the current cursor shape for this panel.
PL_SELECTION & GetSelection()
Function GetSelection()
bool IsAction(const TOOL_ACTION *aAction) const
Function IsAction() Tests if the event contains an action issued upon activation of the given TOOL_AC...
Definition: tool_event.cpp:67
const wxPoint GetStartPosUi(int ii=0) const
void OnModify()
Must be called after a change in order to set the "modify" flag.
int PlaceItem(const TOOL_EVENT &aEvent)
void SetFlags(STATUS_FLAGS aMask)
Definition: eda_item.h:221
int DrawShape(const TOOL_EVENT &aEvent)
virtual void PopTool(const std::string &actionName)
virtual void CaptureCursor(bool aEnabled)
Function CaptureCursor() Forces the cursor to stay within the drawing panel area.
WS_DATA_ITEM * AddPageLayoutItem(int aType)
Function AddPageLayoutItem Add a new item to the page layout item list.
T Parameter() const
Function Parameter() Returns a non-standard parameter assigned to the event.
Definition: tool_event.h:435
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
TOOL_EVENT.
Definition: tool_event.h:171
VIEW_GROUP extends VIEW_ITEM by possibility of grouping items into a single object.
static TOOL_ACTION drawRectangle
Definition: pl_actions.h:66
virtual void Update(VIEW_ITEM *aItem, int aUpdateFlags)
For dynamic VIEWs, informs the associated VIEW that the graphical representation of this item has cha...
Definition: view.cpp:1513
#define IS_MOVED
Item being moved.
Definition: eda_item.h:105
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.
PL_SELECTION_TOOL * m_selectionTool
static TOOL_ACTION clearSelection
Clears the current selection.
Definition: pl_actions.h:49
const std::vector< WS_DRAW_ITEM_BASE * > & GetDrawItems() const
Definition: ws_data_item.h:132
OPT< std::string > GetCommandStr() const
Definition: tool_event.h:463
void MoveStartPointToUi(wxPoint aPosition)
move the starting point of the item to a new position
void VetoContextMenuMouseWarp()
Disables mouse warping after the current context menu is closed.
Definition: tool_manager.h:414
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:79
Helper classes to handle basic graphic items used to draw/plot title blocks and frame references segm...
Definition: ws_draw_item.h:56
void SaveCopyInUndoList()
Save a copy of the description (in a S expr string) for Undo/redo commands.
void Activate()
Function Activate() Runs the tool.
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
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
PL_EDITOR_FRAME * m_frame
void ClearEditFlags()
Definition: eda_item.h:240
void RollbackFromUndo()
Apply the last command in Undo List without stacking a Redo.
void ShowContextMenu(SELECTION &aSelection)
Function ShowContextMenu.
Definition: tool_menu.cpp:59
#define IS_NEW
New item, just created.
Definition: eda_item.h:106
static TOOL_ACTION refreshPreview
Definition: actions.h:104
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.
static TOOL_ACTION cursorClick
Definition: actions.h:121