KiCad PCB EDA Suite
pcb_tool.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.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  newItem->ClearFlags();
136  preview.Remove( newItem.get() );
137 
138  aPlacer->PlaceItem( newItem.get(), commit );
139 
140  if( newItem->Type() == PCB_MODULE_T )
141  {
142  auto module = dyn_cast<MODULE*>( newItem.get() );
143  module->RunOnChildren( std::bind( &KIGFX::VIEW_GROUP::Remove, &preview, _1 ) );
144  }
145 
146  newItem.release();
147  commit.Push( aCommitMessage );
148 
149  controls()->CaptureCursor( false );
150  controls()->SetAutoPan( false );
151  controls()->ShowCursor( true );
152 
153  if( !( aOptions & IPO_REPEAT ) )
154  break;
155 
156  if( aOptions & IPO_SINGLE_CLICK && !( aOptions & IPO_PROPERTIES ) )
157  {
159 
160  newItem = aPlacer->CreateItem();
161 
162  if( newItem )
163  {
164  newItem->SetPosition( wxPoint( pos.x, pos.y ) );
165  preview.Add( newItem.get() );
166  }
167  }
168  }
169  }
170  else if( evt->IsClick( BUT_RIGHT ) )
171  {
173  }
174  else if( newItem && evt->Category() == TC_COMMAND )
175  {
176  /*
177  * Handle any events that can affect the item as we move
178  * it around, eg rotate and flip
179  */
180 
181  if( TOOL_EVT_UTILS::IsRotateToolEvt( *evt ) && ( aOptions & IPO_ROTATE ) )
182  {
183  const int rotationAngle = TOOL_EVT_UTILS::GetEventRotationAngle( *frame(), *evt );
184  newItem->Rotate( newItem->GetPosition(), rotationAngle );
185  view()->Update( &preview );
186  }
187  else if( evt->IsAction( &PCB_ACTIONS::flip ) && ( aOptions & IPO_FLIP ) )
188  {
189  newItem->Flip( newItem->GetPosition() );
190  view()->Update( &preview );
191  }
192  }
193 
194  else if( newItem && evt->IsMotion() )
195  {
196  // track the cursor
197  newItem->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) );
198  aPlacer->SnapItem( newItem.get() );
199 
200  // Show a preview of the item
201  view()->Update( &preview );
202  }
203  }
204 
205  view()->Remove( &preview );
206 }
207 
209 {
210  // A basic context manu. Many (but not all) tools will choose to override this.
211 
212  auto& ctxMenu = m_menu.GetMenu();
213 
214  // cancel current tool goes in main context menu at the top if present
216  ctxMenu.AddSeparator( SELECTION_CONDITIONS::ShowAlways, 1 );
217 
218  // Finally, add the standard zoom/grid items
219  m_menu.AddStandardSubMenus( *getEditFrame<PCB_BASE_FRAME>() );
220 
221  return true;
222 }
223 
224 
226 {
227 
228 }
229 
231 {
232 
233 }
234 
236 {
237  return static_cast<PCB_DISPLAY_OPTIONS*>( frame()->GetDisplayOptions() );
238 }
239 
241 {
242  return static_cast<PCB_DRAW_PANEL_GAL*>( frame()->GetGalCanvas() );
243 }
244 
246 {
247  auto selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
248  const auto& selection = selTool->GetSelection();
249  return selection;
250 }
251 
253 {
254  auto selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
255  auto& selection = selTool->GetSelection();
256  return selection;
257 }
258 
259 
261 {
262  // Base implementation performs no snapping
263 }
264 
266 {
267  aCommit.Add( aItem );
268 }
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:53
virtual void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
Definition: pcb_tool.cpp:230
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).
virtual void PlaceItem(BOARD_ITEM *aItem, BOARD_COMMIT &aCommit)
Definition: pcb_tool.cpp:265
virtual void Clear() override
Function Clear() Removes all the stored items from the group.
Definition: selection.h:90
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction)
Function RunOnChildren.
TOOL_MENU m_menu
Menu model displayed by the tool.
Definition: pcb_tool.h:148
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:81
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:49
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:215
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.h:58
bool IsRotateToolEvt(const TOOL_EVENT &aEvt)
Function isRotateToolEvt()
Casted dyn_cast(From aObject)
Function dyn_cast()
Definition: typeinfo.h:61
virtual void Remove(VIEW_ITEM *aItem) override
Function Remove() Removes a VIEW_ITEM from the view.
Definition: pcb_view.cpp:64
void * GetDisplayOptions() override
Function GetDisplayOptions returns the display options current in use Display options are relative to...
virtual void Add(EDA_ITEM *aItem)
Definition: selection.h:74
virtual void SnapItem(BOARD_ITEM *aItem)
Definition: pcb_tool.cpp:260
PCB_DRAW_PANEL_GAL * canvas() const
Definition: pcb_tool.cpp:240
PCB_DISPLAY_OPTIONS * displayOptions() const
Definition: pcb_tool.cpp:235
KIGFX::VIEW_CONTROLS * controls() const
Definition: pcb_tool.h:138
class MODULE, a footprint
Definition: typeinfo.h:89
Class PCB_DISPLAY_OPTIONS handles display options like enable/disable some optional drawings...
void AddStandardSubMenus(EDA_DRAW_FRAME &aFrame)
Function CreateBasicMenu.
Definition: tool_menu.cpp:95
virtual void CaptureCursor(bool aEnabled)
Function CaptureCursor() Forces the cursor to stay within the drawing panel area. ...
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.
PCB_EDIT_FRAME * frame() const
Definition: pcb_tool.h:139
virtual void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
Definition: pcb_tool.cpp:225
MODULE * module() const
Definition: pcb_tool.h:141
virtual void Remove(VIEW_ITEM *aItem)
Function Remove() Removes an item from the group.
Definition: view_group.cpp:61
const SELECTION & selection() const
Definition: pcb_tool.cpp:245
bool IsCancelInteractive(const TOOL_EVENT &aEvt)
Function IsCancelInteractive()
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...
static TOOL_ACTION flip
Flipping of selected objects.
Definition: pcb_actions.h:105
KIGFX::PCB_VIEW * view() const
Definition: pcb_tool.h:137
virtual bool Init() override
Function Init() Init() is called once upon a registration of the tool.
Definition: pcb_tool.cpp:208
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Function AddItem()
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
TOOL_MANAGER * GetManager() const
Function GetManager() Returns the instance of TOOL_MANAGER that takes care of the tool...
Definition: tool_base.h:144
void Activate()
Function Activate() Runs the tool.
EDA_DRAW_PANEL_GAL * GetGalCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
Definition: draw_frame.h:908
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1) override
Function Add() Adds a VIEW_ITEM to the view.
Definition: pcb_view.cpp:48
Module description (excepted pads)
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...
Definition: pcb_tool.cpp:39
int GetEventRotationAngle(const PCB_BASE_EDIT_FRAME &aFrame, const TOOL_EVENT &aEvt)
Function getEventRotationAngle()
void ShowContextMenu(SELECTION &aSelection)
Function ShowContextMenu.
Definition: tool_menu.cpp:62
OPT< TOOL_EVENT > OPT_TOOL_EVENT
Definition: tool_event.h:495
BOARD * board() const
Definition: pcb_tool.h:140
virtual void Remove(EDA_ITEM *aItem)
Definition: selection.h:82