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 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 
25 #include "pcb_tool_base.h"
26 
27 #include <view/view_controls.h>
28 #include <view/view.h>
29 #include <tool/tool_manager.h>
30 #include <board_commit.h>
31 
32 #include <class_module.h>
33 #include <pcb_draw_panel_gal.h>
34 
35 #include "selection_tool.h"
36 #include "pcb_actions.h"
37 #include "tool_event_utils.h"
38 
40  const wxString& aCommitMessage,
41  int aOptions )
42 {
43  using namespace std::placeholders;
44  std::unique_ptr<BOARD_ITEM> newItem;
45 
46  Activate();
47 
48  BOARD_COMMIT commit( frame() );
49 
51 
52  // do not capture or auto-pan until we start placing an item
53  controls()->ShowCursor( true );
54  controls()->SetSnapping( true );
55 
56  // Add a VIEW_GROUP that serves as a preview for the new item
57  SELECTION preview;
58  view()->Add( &preview );
59 
60  aPlacer->m_board = board();
61  aPlacer->m_frame = frame();
62  aPlacer->m_modifiers = 0;
63 
64  if( aOptions & IPO_SINGLE_CLICK && !( aOptions & IPO_PROPERTIES ) )
65  {
66  VECTOR2I cursorPos = controls()->GetCursorPosition();
67 
68  newItem = aPlacer->CreateItem();
69 
70  if( newItem )
71  {
72  newItem->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) );
73  preview.Add( newItem.get() );
74  }
75  }
76 
77  // Main loop: keep receiving events
78  while( OPT_TOOL_EVENT evt = Wait() )
79  {
80  VECTOR2I cursorPos = controls()->GetCursorPosition();
81  aPlacer->m_modifiers = evt->Modifier();
82 
84  {
85  if( newItem )
86  {
87  // Delete the old item and have another try
88  newItem = nullptr;
89 
90  preview.Clear();
91 
92  if( aOptions & IPO_SINGLE_CLICK )
93  break;
94 
95  controls()->SetAutoPan( false );
96  controls()->CaptureCursor( false );
97  controls()->ShowCursor( true );
98  }
99  else
100  {
101  break;
102  }
103 
104  if( evt->IsActivate() ) // now finish unconditionally
105  break;
106  }
107  else if( evt->IsClick( BUT_LEFT ) )
108  {
109  if( !newItem )
110  {
111  // create the item if possible
112  newItem = aPlacer->CreateItem();
113 
114  // no item created, so wait for another click
115  if( !newItem )
116  continue;
117 
118  controls()->CaptureCursor( true );
119  controls()->SetAutoPan( true );
120 
121  newItem->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) );
122 
123  preview.Add( newItem.get() );
124 
125  if( newItem->Type() == PCB_MODULE_T )
126  {
127  auto module = dyn_cast<MODULE*>( newItem.get() );
128 
129  // modules have more drawable parts
130  module->RunOnChildren( std::bind( &KIGFX::VIEW_GROUP::Add, &preview, _1 ) );
131  }
132  }
133  else
134  {
135  auto oldFlags = newItem->GetFlags();
136  newItem->ClearFlags();
137 
138  if( !aPlacer->PlaceItem( newItem.get(), commit ) )
139  {
140  newItem->SetFlags( oldFlags );
141  continue;
142  }
143 
144  preview.Remove( newItem.get() );
145 
146  if( newItem->Type() == PCB_MODULE_T )
147  {
148  auto module = dyn_cast<MODULE*>( newItem.get() );
149  module->RunOnChildren( std::bind( &KIGFX::VIEW_GROUP::Remove, &preview, _1 ) );
150  }
151 
152  newItem.release();
153  commit.Push( aCommitMessage );
154 
155  controls()->CaptureCursor( false );
156  controls()->SetAutoPan( false );
157  controls()->ShowCursor( true );
158 
159  if( !( aOptions & IPO_REPEAT ) )
160  break;
161 
162  if( aOptions & IPO_SINGLE_CLICK && !( aOptions & IPO_PROPERTIES ) )
163  {
165 
166  newItem = aPlacer->CreateItem();
167 
168  if( newItem )
169  {
170  newItem->SetPosition( wxPoint( pos.x, pos.y ) );
171  preview.Add( newItem.get() );
172  }
173  }
174  }
175  }
176  else if( evt->IsClick( BUT_RIGHT ) )
177  {
179  }
180  else if( newItem && evt->Category() == TC_COMMAND )
181  {
182  /*
183  * Handle any events that can affect the item as we move
184  * it around, eg rotate and flip
185  */
186 
187  if( TOOL_EVT_UTILS::IsRotateToolEvt( *evt ) && ( aOptions & IPO_ROTATE ) )
188  {
189  const int rotationAngle = TOOL_EVT_UTILS::GetEventRotationAngle( *frame(), *evt );
190  newItem->Rotate( newItem->GetPosition(), rotationAngle );
191  view()->Update( &preview );
192  }
193  else if( evt->IsAction( &PCB_ACTIONS::flip ) && ( aOptions & IPO_FLIP ) )
194  {
195  newItem->Flip( newItem->GetPosition() );
196  view()->Update( &preview );
197  }
198  }
199 
200  else if( newItem && evt->IsMotion() )
201  {
202  // track the cursor
203  newItem->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) );
204  aPlacer->SnapItem( newItem.get() );
205 
206  // Show a preview of the item
207  view()->Update( &preview );
208  }
209  }
210 
211  view()->Remove( &preview );
212 }
213 
215 {
216  // A basic context manu. Many (but not all) tools will choose to override this.
217 
218  auto& ctxMenu = m_menu.GetMenu();
219 
220  // cancel current tool goes in main context menu at the top if present
222  ctxMenu.AddSeparator( SELECTION_CONDITIONS::ShowAlways, 1 );
223 
224  // Finally, add the standard zoom/grid items
225  m_menu.AddStandardSubMenus( getEditFrame<PCB_BASE_FRAME>() );
226 
227  return true;
228 }
229 
230 
232 {
233 
234 }
235 
237 {
238 
239 }
240 
242 {
243  return static_cast<PCB_DISPLAY_OPTIONS*>( frame()->GetDisplayOptions() );
244 }
245 
247 {
248  return static_cast<PCB_DRAW_PANEL_GAL*>( frame()->GetGalCanvas() );
249 }
250 
252 {
253  auto selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
254  const auto& selection = selTool->GetSelection();
255  return selection;
256 }
257 
259 {
260  auto selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
261  auto& selection = selTool->GetSelection();
262  return selection;
263 }
264 
265 
267 {
268  // Base implementation performs no snapping
269 }
270 
272 {
273  aCommit.Add( aItem );
274  return true;
275 }
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:53
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).
TOOL_MENU m_menu
Menu model displayed by the tool.
void AddStandardSubMenus(EDA_DRAW_FRAME *aFrame)
Function CreateBasicMenu.
Definition: tool_menu.cpp:83
PCB_DISPLAY_OPTIONS * displayOptions() const
virtual void Clear() override
Function Clear() Removes all the stored items from the group.
Definition: selection.h:93
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction)
Function RunOnChildren.
virtual bool PlaceItem(BOARD_ITEM *aItem, BOARD_COMMIT &aCommit)
BOARD * board() const
virtual void Update(VIEW_ITEM *aItem, int aUpdateFlags) override
For dynamic VIEWs, informs the associated VIEW that the graphical representation of this item has cha...
Definition: pcb_view.cpp:91
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
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.
Class SELECTION_TOOL.
CONDITIONAL_MENU & GetMenu()
Function GetMenu.
Definition: tool_menu.cpp:46
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:216
static TOOL_ACTION cancelInteractive
Definition: actions.h:45
OPT_TOOL_EVENT Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Function Wait()
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:125
PCB_EDIT_FRAME * m_frame
Definition: pcb_tool_base.h:58
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()
virtual void Remove(VIEW_ITEM *aItem) override
Function Remove() Removes a VIEW_ITEM from the view.
Definition: pcb_view.cpp:74
virtual void Add(EDA_ITEM *aItem)
Definition: selection.h:74
TOOL_MANAGER * GetManager() const
Function GetManager() Returns the instance of TOOL_MANAGER that takes care of the tool.
Definition: tool_base.h:144
virtual void SnapItem(BOARD_ITEM *aItem)
class MODULE, a footprint
Definition: typeinfo.h:89
Class PCB_DISPLAY_OPTIONS handles display options like enable/disable some optional drawings.
virtual void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
virtual void CaptureCursor(bool aEnabled)
Function CaptureCursor() Forces the cursor to stay within the drawing panel area.
KIGFX::PCB_VIEW * view() const
virtual void Remove(VIEW_ITEM *aItem)
Function Remove() Removes an item from the group.
Definition: view_group.cpp:61
bool IsCancelInteractive(const TOOL_EVENT &aEvt)
Function IsCancelInteractive()
Definition: tool_event.cpp:177
virtual void Add(VIEW_ITEM *aItem)
Function Add() Adds an item to the group.
Definition: view_group.cpp:55
PCB_EDIT_FRAME * frame() const
virtual void SetAutoPan(bool aEnabled)
Function SetAutoPan Turns on/off auto panning (this feature is used when there is a tool active (eg.
static TOOL_ACTION flip
Flipping of selected objects.
Definition: pcb_actions.h:99
KIGFX::VIEW_CONTROLS * controls() const
MODULE * module() const
void doInteractiveItemPlacement(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...
virtual bool Init() override
Function Init() Init() is called once upon a registration of the tool.
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:80
void Activate()
Function Activate() Runs the tool.
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1) override
Function Add() Adds a VIEW_ITEM to the view.
Definition: pcb_view.cpp:58
Module description (excepted pads)
PCB_DRAW_PANEL_GAL * canvas() const
int GetEventRotationAngle(const PCB_BASE_EDIT_FRAME &aFrame, const TOOL_EVENT &aEvt)
Function getEventRotationAngle()
const SELECTION & selection() const
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
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.
OPT< TOOL_EVENT > OPT_TOOL_EVENT
Definition: tool_event.h:486
virtual void Remove(EDA_ITEM *aItem)
Definition: selection.h:85