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 <pl_editor_frame.h>
26 #include <class_draw_panel_gal.h>
27 #include <pl_editor_id.h>
28 #include <confirm.h>
29 #include <view/view_group.h>
30 #include <view/view_controls.h>
31 #include <view/view.h>
32 #include <tool/tool_manager.h>
33 #include <tools/pl_actions.h>
35 #include <tools/pl_drawing_tools.h>
36 #include <bitmaps.h>
37 #include <ws_draw_item.h>
38 #include <ws_data_item.h>
40 #include "pl_point_editor.h"
41 
43  TOOL_INTERACTIVE( "plEditor.InteractiveDrawing" ),
44  m_frame( nullptr ),
45  m_selectionTool( nullptr )
46 {
47 }
48 
49 
51 {
52  m_frame = getEditFrame<PL_EDITOR_FRAME>();
54 
55  auto& ctxMenu = m_menu.GetMenu();
56 
57  // cancel current tool goes in main context menu at the top if present
59  ctxMenu.AddSeparator( 1 );
60 
61  // Finally, add the standard zoom/grid items
63 
64  return true;
65 }
66 
67 
69 {
70  if( aReason == MODEL_RELOAD )
71  m_frame = getEditFrame<PL_EDITOR_FRAME>();
72 }
73 
74 
76 {
78  VECTOR2I cursorPos;
79  WS_DRAW_ITEM_BASE* item = nullptr;
80 
82  getViewControls()->ShowCursor( true );
83 
84  std::string tool = aEvent.GetCommandStr().get();
85  m_frame->PushTool( tool );
86  Activate();
87 
88  // Prime the pump
89  if( aEvent.HasPosition() )
91 
92  // Main loop: keep receiving events
93  while( TOOL_EVENT* evt = Wait() )
94  {
95  m_frame->GetCanvas()->SetCurrentCursor( item ? wxCURSOR_ARROW : wxCURSOR_PENCIL );
96  cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
97 
98  auto cleanup = [&] () {
100  delete item;
101  item = nullptr;
102 
103  // There's nothing to roll-back, but we still need to pop the undo stack
105  };
106 
107  if( evt->IsCancelInteractive() )
108  {
109  if( item )
110  cleanup();
111  else
112  {
113  m_frame->PopTool( tool );
114  break;
115  }
116  }
117  else if( evt->IsActivate() )
118  {
119  if( item )
120  cleanup();
121 
122  if( evt->IsMoveTool() )
123  {
124  // leave ourselves on the stack so we come back after the move
125  break;
126  }
127  else
128  {
129  m_frame->PopTool( tool );
130  break;
131  }
132  }
133  else if( evt->IsClick( BUT_LEFT ) )
134  {
135  // First click creates...
136  if( !item )
137  {
138  WS_DATA_ITEM* dataItem = m_frame->AddPageLayoutItem( type );
139 
140  if( dataItem ) // dataItem = nullptr can happens if the command was cancelled
141  {
143 
145 
146  item = dataItem->GetDrawItems()[0];
147  item->SetFlags( IS_NEW | IS_MOVED );
148  m_selectionTool->AddItemToSel( item );
149  }
150  }
151  // ... and second click places:
152  else
153  {
154  item->GetPeer()->MoveStartPointToUi( (wxPoint) cursorPos );
155  item->SetPosition( item->GetPeer()->GetStartPosUi( 0 ) );
156  item->ClearEditFlags();
157  getView()->Update( item );
158 
159  item = nullptr;
160 
161  m_frame->OnModify();
162  }
163  }
164  else if( evt->IsClick( BUT_RIGHT ) )
165  {
166  // Warp after context menu only if dragging...
167  if( !item )
169 
171  }
172  else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
173  {
174  item->GetPeer()->MoveStartPointToUi( (wxPoint) cursorPos );
175  item->SetPosition( item->GetPeer()->GetStartPosUi( 0 ) );
176  getView()->Update( item );
177  }
178  else
179  evt->SetPassEvent();
180 
181  // Enable autopanning and cursor capture only when there is an item to be placed
182  getViewControls()->SetAutoPan( item != nullptr );
183  getViewControls()->CaptureCursor( item != nullptr );
184  }
185 
186  return 0;
187 }
188 
189 
191 {
194  WS_DRAW_ITEM_BASE* item = nullptr;
195 
196  // We might be running as the same shape in another co-routine. Make sure that one
197  // gets whacked.
199 
201  getViewControls()->ShowCursor( true );
202 
203  std::string tool = aEvent.GetCommandStr().get();
204  m_frame->PushTool( tool );
205  Activate();
206 
207  // Prime the pump
208  if( aEvent.HasPosition() )
210 
211  // Main loop: keep receiving events
212  while( TOOL_EVENT* evt = Wait() )
213  {
214  if( !pointEditor->HasPoint() )
215  m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_PENCIL );
216 
217  VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
218 
219  if( evt->IsCancelInteractive() || evt->IsActivate() )
220  {
222 
223  if( item )
224  {
225  item = nullptr;
227  }
228  else if( evt->IsCancelInteractive() )
229  {
230  break;
231  }
232 
233  if( evt->IsActivate() && !evt->IsPointEditor() && !evt->IsMoveTool() )
234  break;
235  }
236 
237  else if( evt->IsClick( BUT_LEFT ) )
238  {
239  if( !item ) // start drawing
240  {
243 
244  WS_DATA_ITEM* dataItem = m_frame->AddPageLayoutItem( type );
245  dataItem->MoveToUi( (wxPoint) cursorPos );
246 
247  item = dataItem->GetDrawItems()[0];
248  item->SetFlags( IS_NEW );
249  m_selectionTool->AddItemToSel( item );
250  }
251  else // finish drawing
252  {
253  item->ClearEditFlags();
254  item = nullptr;
256 
257  m_frame->OnModify();
258  }
259  }
260 
261  else if( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() )
262  {
263  if( item )
264  {
265  item->GetPeer()->MoveEndPointToUi( (wxPoint) cursorPos );
266  item->SetEnd( item->GetPeer()->GetEndPosUi( 0 ) );
267  getView()->Update( item );
268  }
269  }
270 
271  else if( evt->IsClick( BUT_RIGHT ) )
272  {
273  // Warp after context menu only if dragging...
274  if( !item )
276 
278  }
279 
280  else
281  evt->SetPassEvent();
282 
283  // Enable autopanning and cursor capture only when there is a shape being drawn
284  getViewControls()->SetAutoPan( item != nullptr );
285  getViewControls()->CaptureCursor( item != nullptr );
286  }
287 
288  m_frame->PopTool( tool );
289  return 0;
290 }
291 
292 
294 {
299 }
virtual void ShowCursor(bool aEnabled)
Function ShowCursor() Enables or disables display of cursor.
static bool ShowAlways(const SELECTION &aSelection)
Function ShowAlways The default condition function (always returns true).
WS_DATA_ITEM * GetPeer() const
Definition: ws_draw_item.h:66
void SaveCopyInUndoList(bool aSavePageSettingsAndTitleBlock=false)
Save a copy of the description (in a S expr string) for Undo/redo commands.
void AddStandardSubMenus(TOOL_MENU &aMenu)
Function CreateBasicMenu.
virtual void PushTool(const std::string &actionName)
NB: the definition of "tool" is different at the user level.
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:158
Work sheet structure type definitions.
Definition: ws_data_item.h:93
Model changes (required full reload)
Definition: tool_base.h:82
This file is part of the common library.
static TOOL_ACTION drawLine
Definition: pl_actions.h:67
void SetCurrentCursor(wxStockCursor aStockCursorID)
Function SetCurrentCursor Set the current cursor shape for this panel.
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
virtual void SetPosition(wxPoint aPos)=0
static TOOL_ACTION cancelInteractive
Definition: actions.h:65
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:109
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.
PL_SELECTION & GetSelection()
Function GetSelection()
const wxPoint GetStartPosUi(int ii=0) const
void OnModify()
Must be called after a change in order to set the "modify" flag.
#define IS_NEW
New item, just created.
Definition: base_struct.h:120
bool HasPoint()
Indicates the cursor is over an edit point.
int PlaceItem(const TOOL_EVENT &aEvent)
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:265
int DrawShape(const TOOL_EVENT &aEvent)
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:427
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
Class TOOL_EVENT.
Definition: tool_event.h:168
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:1540
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:128
OPT< std::string > GetCommandStr() const
Definition: tool_event.h:455
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:372
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:79
virtual void PopTool(const std::string &actionName)
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:257
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:42
PL_EDITOR_FRAME * m_frame
void ClearEditFlags()
Definition: base_struct.h:282
void RollbackFromUndo()
Apply the last command in Undo List without stacking a Redo.
void ShowContextMenu(SELECTION &aSelection)
Function ShowContextMenu.
Definition: tool_menu.cpp:59
static TOOL_ACTION refreshPreview
Definition: actions.h:100
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.
static TOOL_ACTION cursorClick
Definition: actions.h:114
Class PL_POINT_EDITOR.
#define IS_MOVED
Item being moved.
Definition: base_struct.h:119