KiCad PCB EDA Suite
pcb_tool_base.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) 2017-2019 KiCad Developers, see AUTHORS.txt for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include "pcb_tool_base.h"
25 
26 #include <view/view_controls.h>
27 #include <tool/tool_manager.h>
28 #include <board_commit.h>
29 #include <footprint.h>
30 #include <pcb_draw_panel_gal.h>
31 #include <pcbnew_settings.h>
32 #include "selection_tool.h"
33 #include "pcb_actions.h"
34 #include "tool_event_utils.h"
35 
36 void PCB_TOOL_BASE::doInteractiveItemPlacement( const std::string& aTool,
37  INTERACTIVE_PLACER_BASE* aPlacer,
38  const wxString& aCommitMessage, int aOptions )
39 {
40  using namespace std::placeholders;
41  std::unique_ptr<BOARD_ITEM> newItem;
42 
43  frame()->PushTool( aTool );
44  Activate();
45 
46  BOARD_COMMIT commit( frame() );
47 
49 
50  // do not capture or auto-pan until we start placing an item
51  controls()->ShowCursor( true );
52 
53  // Add a VIEW_GROUP that serves as a preview for the new item
54  PCBNEW_SELECTION preview;
55  view()->Add( &preview );
56 
57  aPlacer->m_board = board();
58  aPlacer->m_frame = frame();
59  aPlacer->m_modifiers = 0;
60 
61  auto makeNewItem =
62  [&]( VECTOR2I aPosition )
63  {
64  if( frame()->GetModel() )
65  newItem = aPlacer->CreateItem();
66 
67  if( newItem )
68  {
69  newItem->SetPosition( (wxPoint) aPosition );
70  preview.Add( newItem.get() );
71 
72  if( newItem->Type() == PCB_FOOTPRINT_T )
73  {
74  FOOTPRINT* fp = dyn_cast<FOOTPRINT*>( newItem.get() );
75 
76  // footprints have more drawable parts
77  fp->RunOnChildren( std::bind( &KIGFX::VIEW_GROUP::Add, &preview, _1 ) );
78  }
79  }
80  };
81 
82  if( aOptions & IPO_SINGLE_CLICK )
83  makeNewItem( controls()->GetCursorPosition() );
84 
85  auto setCursor =
86  [&]()
87  {
88  if( !newItem )
90  else
92  };
93 
94  // Set initial cursor
95  setCursor();
96 
97  // Main loop: keep receiving events
98  while( TOOL_EVENT* evt = Wait() )
99  {
100  setCursor();
101 
102  VECTOR2I cursorPos = controls()->GetCursorPosition();
103  aPlacer->m_modifiers = evt->Modifier();
104 
105  auto cleanup =
106  [&] ()
107  {
108  newItem = nullptr;
109  preview.Clear();
110  view()->Update( &preview );
111  controls()->SetAutoPan( false );
112  controls()->CaptureCursor( false );
113  controls()->ShowCursor( true );
114  };
115 
116  if( evt->IsCancelInteractive() )
117  {
118  if( aOptions & IPO_SINGLE_CLICK )
119  {
120  cleanup();
121  frame()->PopTool( aTool );
122  break;
123  }
124  else if( newItem )
125  cleanup();
126  else
127  {
128  frame()->PopTool( aTool );
129  break;
130  }
131  }
132  else if( evt->IsActivate() )
133  {
134  if( newItem )
135  cleanup();
136 
137  if( evt->IsPointEditor() )
138  {
139  // don't exit (the point editor runs in the background)
140  }
141  else if( evt->IsMoveTool() )
142  {
143  // leave ourselves on the stack so we come back after the move
144  break;
145  }
146  else
147  {
148  frame()->PopTool( aTool );
149  break;
150  }
151  }
152  else if( evt->IsClick( BUT_LEFT ) )
153  {
154  if( !newItem )
155  {
156  // create the item if possible
157  makeNewItem( cursorPos );
158 
159  // no item created, so wait for another click
160  if( !newItem )
161  continue;
162 
163  controls()->CaptureCursor( true );
164  controls()->SetAutoPan( true );
165  }
166  else
167  {
168  auto oldFlags = newItem->GetFlags();
169  newItem->ClearFlags();
170 
171  if( !aPlacer->PlaceItem( newItem.get(), commit ) )
172  {
173  newItem->SetFlags( oldFlags );
174  continue;
175  }
176 
177  preview.Clear();
178  newItem.release();
179  commit.Push( aCommitMessage );
180 
181  controls()->CaptureCursor( false );
182  controls()->SetAutoPan( false );
183  controls()->ShowCursor( true );
184 
185  if( !( aOptions & IPO_REPEAT ) )
186  break;
187 
188  if( aOptions & IPO_SINGLE_CLICK )
189  makeNewItem( controls()->GetCursorPosition() );
190 
191  setCursor();
192  }
193  }
194  else if( evt->IsClick( BUT_RIGHT ) )
195  {
197  }
198  else if( evt->IsAction( &PCB_ACTIONS::trackViaSizeChanged ) )
199  {
201  }
202  else if( newItem && evt->Category() == TC_COMMAND )
203  {
204  /*
205  * Handle any events that can affect the item as we move it around
206  */
207  if( TOOL_EVT_UTILS::IsRotateToolEvt( *evt ) && ( aOptions & IPO_ROTATE ) )
208  {
209  const int rotationAngle = TOOL_EVT_UTILS::GetEventRotationAngle( *frame(), *evt );
210  newItem->Rotate( newItem->GetPosition(), rotationAngle );
211  view()->Update( &preview );
212  }
213  else if( evt->IsAction( &PCB_ACTIONS::flip ) && ( aOptions & IPO_FLIP ) )
214  {
215  newItem->Flip( newItem->GetPosition(), frame()->Settings().m_FlipLeftRight );
216  view()->Update( &preview );
217  }
218  else if( evt->IsAction( &PCB_ACTIONS::viaSizeInc )
219  || evt->IsAction( &PCB_ACTIONS::viaSizeDec ) )
220  {
221  // Refresh preview after event runs
223  }
224  else if( evt->IsAction( &ACTIONS::refreshPreview ) )
225  {
226  preview.Clear();
227  newItem.release();
228 
229  makeNewItem( (wxPoint) cursorPos );
230  aPlacer->SnapItem( newItem.get() );
231  view()->Update( &preview );
232  }
233  }
234  else if( newItem && evt->IsMotion() )
235  {
236  // track the cursor
237  newItem->SetPosition( (wxPoint) cursorPos );
238  aPlacer->SnapItem( newItem.get() );
239 
240  // Show a preview of the item
241  view()->Update( &preview );
242  }
243  else
244  {
245  evt->SetPassEvent();
246  }
247  }
248 
249  view()->Remove( &preview );
251 }
252 
253 
255 {
256  // A basic context manu. Many (but not all) tools will choose to override this.
257  CONDITIONAL_MENU& ctxMenu = m_menu.GetMenu();
258 
259  // cancel current tool goes in main context menu at the top if present
261  ctxMenu.AddSeparator( 1 );
262 
263  // Finally, add the standard zoom/grid items
264  getEditFrame<PCB_BASE_FRAME>()->AddStandardSubMenus( m_menu );
265 
266  return true;
267 }
268 
269 
271 {
272 }
273 
274 
276 {
277 }
278 
279 
281 {
282  return frame()->GetDisplayOptions();
283 }
284 
286 {
287  return static_cast<PCB_DRAW_PANEL_GAL*>( frame()->GetCanvas() );
288 }
289 
290 
292 {
294 
295  return selTool->GetSelection();
296 }
297 
298 
300 {
302 
303  return selTool->GetSelection();
304 }
305 
306 
308 {
309  // Base implementation performs no snapping
310 }
311 
312 
314 {
315  aCommit.Add( aItem );
316  return true;
317 }
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:62
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).
TOOL_MENU m_menu
functions below are not yet implemented - their interface may change
virtual void Clear() override
Function Clear() Removes all the stored items from the group.
Definition: selection.h:94
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Function Wait()
virtual bool PlaceItem(BOARD_ITEM *aItem, BOARD_COMMIT &aCommit)
Handle flip action in the loop by calling the item's flip method.
BOARD * board() const
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
Definition: board_item.h:86
static TOOL_ACTION viaSizeInc
Definition: pcb_actions.h:296
COMMIT & Add(EDA_ITEM *aItem)
Adds a new item to the model
Definition: commit.h:78
virtual std::unique_ptr< BOARD_ITEM > CreateItem()=0
VIEW_CONTROLS class definition.
SELECTION_TOOL.
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
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 trackViaSizeChanged
Definition: pcb_actions.h:299
virtual void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
bool IsRotateToolEvt(const TOOL_EVENT &aEvt)
Function isRotateToolEvt()
const PCB_DISPLAY_OPTIONS & GetDisplayOptions() const
Function GetDisplayOptions Display options control the way tracks, vias, outlines and other things ar...
void SetCurrentCursor(KICURSOR cursor)
Function SetCurrentCursor Set the current cursor shape for this panel.
virtual void Remove(VIEW_ITEM *aItem) override
Function Remove() Removes a VIEW_ITEM from the view.
Definition: pcb_view.cpp:76
virtual void Add(EDA_ITEM *aItem)
Definition: selection.h:75
TOOL_MANAGER * GetManager() const
Function GetManager() Returns the instance of TOOL_MANAGER that takes care of the tool.
Definition: tool_base.h:143
PCBNEW_SELECTION & GetSelection()
Function GetSelection()
PCB_BASE_EDIT_FRAME * frame() const
virtual void SnapItem(BOARD_ITEM *aItem)
PCB_DISPLAY_OPTIONS handles display options like enable/disable some optional drawings.
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const override
For dynamic VIEWs, informs the associated VIEW that the graphical representation of this item has cha...
Definition: pcb_view.cpp:94
const PCBNEW_SELECTION & selection() const
virtual void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
Allow repeat placement of the item.
virtual void PopTool(const std::string &actionName)
virtual void CaptureCursor(bool aEnabled)
Function CaptureCursor() Forces the cursor to stay within the drawing panel area.
TOOL_EVENT.
Definition: tool_event.h:171
KIGFX::PCB_VIEW * view() const
Create an item immediately on placement starting, otherwise show the pencil cursor until the item is ...
virtual void Add(VIEW_ITEM *aItem)
Function Add() Adds an item to the group.
Definition: view_group.cpp:55
virtual void SetAutoPan(bool aEnabled)
Function SetAutoPan Turns on/off auto panning (this feature is used when there is a tool active (eg.
const PCB_DISPLAY_OPTIONS & displayOptions() const
class FOOTPRINT, a footprint
Definition: typeinfo.h:89
void AddSeparator(int aOrder=ANY_ORDER)
Adds a separator to the menu.
virtual BOARD_ITEM_CONTAINER * GetModel() const =0
Function GetModel()
static TOOL_ACTION flip
Flipping of selected objects.
Definition: pcb_actions.h:108
Handle the rotate action in the loop by calling the item's rotate method.
KIGFX::VIEW_CONTROLS * controls() const
virtual bool Init() override
Function Init() Init() is called once upon a registration of the tool.
PCBNEW_SETTINGS & Settings()
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true) override
Executes the changes.
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:79
void Activate()
Function Activate() Runs the tool.
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction) const
Function RunOnChildren.
Definition: footprint.cpp:1089
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1) override
Function Add() Adds a VIEW_ITEM to the view.
Definition: pcb_view.cpp:59
void doInteractiveItemPlacement(const std::string &aTool, INTERACTIVE_PLACER_BASE *aPlacer, const wxString &aCommitMessage, int aOptions=IPO_ROTATE|IPO_FLIP|IPO_REPEAT)
Helper function for performing a common interactive idiom: wait for a left click, place an item there...
PCB_BASE_EDIT_FRAME * m_frame
Definition: pcb_tool_base.h:65
PCB_DRAW_PANEL_GAL * canvas() const
int GetEventRotationAngle(const PCB_BASE_EDIT_FRAME &aFrame, const TOOL_EVENT &aEvt)
Function getEventRotationAngle()
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.
void ShowContextMenu(SELECTION &aSelection)
Function ShowContextMenu.
Definition: tool_menu.cpp:59
static TOOL_ACTION viaSizeDec
Definition: pcb_actions.h:297
static TOOL_ACTION refreshPreview
Definition: actions.h:104
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.