KiCad PCB EDA Suite
pcb_viewer_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) 2020 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 
25 #include <kiplatform/ui.h>
26 #include <pcb_base_frame.h>
27 #include <pcbnew_settings.h>
29 #include <tool/actions.h>
30 #include <tools/pcb_grid_helper.h>
31 #include <tools/pcb_actions.h>
32 #include <tools/pcb_viewer_tools.h>
33 #include <view/view_controls.h>
34 #include <wx/debug.h>
35 
36 
38 {
39  // Populate the context menu displayed during the tool (primarily the measure tool)
40  auto activeToolCondition =
41  [ this ] ( const SELECTION& aSel )
42  {
43  return !frame()->ToolStackIsEmpty();
44  };
45 
46  auto& ctxMenu = m_menu.GetMenu();
47 
48  // "Cancel" goes at the top of the context menu when a tool is active
49  ctxMenu.AddItem( ACTIONS::cancelInteractive, activeToolCondition, 1 );
50  ctxMenu.AddSeparator( 1 );
51 
53 
54  return true;
55 }
56 
57 
59 {
60 }
61 
62 
64 {
66 
67  if( frame()->IsType( FRAME_FOOTPRINT_VIEWER )
68  || frame()->IsType( FRAME_FOOTPRINT_VIEWER_MODAL )
69  || frame()->IsType( FRAME_FOOTPRINT_WIZARD ) )
70  {
71  // A stronger version of Raise() which promotes the window to its parent's level.
73  }
74 
75  // And load or update the current board
76  frame()->Update3DView( true, true );
77 
78  return 0;
79 }
80 
81 
82 template<class T> void Flip( T& aValue )
83 {
84  aValue = !aValue;
85 }
86 
87 
89 {
90  auto opts = displayOptions();
91 
92  Flip( opts.m_DisplayPadNum );
93  frame()->SetDisplayOptions( opts );
94 
95  for( FOOTPRINT* fp : board()->Footprints() )
96  {
97  for( PAD* pad : fp->Pads() )
99  }
100 
101  canvas()->Refresh();
102 
103  return 0;
104 }
105 
106 
108 {
109  auto opts = displayOptions();
110 
111  Flip( opts.m_DisplayPadFill );
112  frame()->SetDisplayOptions( opts );
113 
114  for( FOOTPRINT* fp : board()->Footprints() )
115  {
116  for( PAD* pad : fp->Pads() )
117  view()->Update( pad, KIGFX::REPAINT );
118  }
119 
120  canvas()->Refresh();
121 
122  return 0;
123 }
124 
125 
127 {
129 
130  Flip( opts.m_DisplayGraphicsFill );
131  frame()->SetDisplayOptions( opts );
132 
133  for( FOOTPRINT* fp : board()->Footprints() )
134  {
135  for( BOARD_ITEM* item : fp->GraphicalItems() )
136  {
137  if( item->Type() == PCB_FP_SHAPE_T )
138  view()->Update( item, KIGFX::REPAINT );
139  }
140  }
141 
142  for( BOARD_ITEM* item : board()->Drawings() )
143  {
144  KICAD_T t = item->Type();
145 
146  if( t == PCB_SHAPE_T || BaseType( t ) == PCB_DIMENSION_T || t == PCB_TARGET_T )
147  view()->Update( item, KIGFX::REPAINT );
148  }
149 
150  canvas()->Refresh();
151 
152  return 0;
153 }
154 
155 
157 {
159 
160  Flip( opts.m_DisplayTextFill );
161  frame()->SetDisplayOptions( opts );
162 
163  for( FOOTPRINT* fp : board()->Footprints() )
164  {
165  view()->Update( &fp->Reference(), KIGFX::REPAINT );
166  view()->Update( &fp->Value(), KIGFX::REPAINT );
167 
168  for( BOARD_ITEM* item : fp->GraphicalItems() )
169  {
170  if( item->Type() == PCB_FP_TEXT_T )
171  view()->Update( item, KIGFX::REPAINT );
172  }
173  }
174 
175  for( BOARD_ITEM* item : board()->Drawings() )
176  {
177  KICAD_T t = item->Type();
178 
179  if( t == PCB_TEXT_T || BaseType( t ) == PCB_DIMENSION_T )
180  view()->Update( item, KIGFX::REPAINT );
181  }
182 
183  canvas()->Refresh();
184 
185  return 0;
186 }
187 
188 
190 
191 
193 {
194  if( IsFootprintFrame() && !frame()->GetModel() )
195  return 0;
196 
197  if( frame()->IsCurrentTool( ACTIONS::measureTool ) )
198  return 0;
199 
200  auto& view = *getView();
201  auto& controls = *getViewControls();
202 
203  std::string tool = aEvent.GetCommandStr().get();
204  frame()->PushTool( tool );
205 
207  PCB_GRID_HELPER grid( m_toolMgr, frame()->GetMagneticItemsSettings() );
208  bool originSet = false;
209  EDA_UNITS units = frame()->GetUserUnits();
210  KIGFX::PREVIEW::RULER_ITEM ruler( twoPtMgr, units,
211  frame()->GetDisplayOptions().m_DisplayInvertXAxis,
212  frame()->GetDisplayOptions().m_DisplayInvertYAxis );
213 
214  view.Add( &ruler );
215  view.SetVisible( &ruler, false );
216 
217  auto setCursor =
218  [&]()
219  {
221  };
222 
223  auto cleanup =
224  [&] ()
225  {
226  view.SetVisible( &ruler, false );
227  controls.SetAutoPan( false );
228  controls.CaptureCursor( false );
229  originSet = false;
230  };
231 
232  Activate();
233  // Must be done after Activate() so that it gets set into the correct context
234  controls.ShowCursor( true );
235  controls.SetAutoPan( false );
236  controls.CaptureCursor( false );
237  // Set initial cursor
238  setCursor();
239 
240  while( TOOL_EVENT* evt = Wait() )
241  {
242  setCursor();
243  grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
244  grid.SetUseGrid( view.GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
245  const VECTOR2I cursorPos = grid.BestSnapAnchor( controls.GetMousePosition(), nullptr );
246  controls.ForceCursorPosition(true, cursorPos );
247 
248  if( evt->IsCancelInteractive() )
249  {
250  if( originSet )
251  {
252  cleanup();
253  }
254  else
255  {
256  frame()->PopTool( tool );
257  break;
258  }
259  }
260  else if( evt->IsActivate() )
261  {
262  if( originSet )
263  cleanup();
264 
265  if( evt->IsMoveTool() )
266  {
267  // leave ourselves on the stack so we come back after the move
268  break;
269  }
270  else
271  {
272  frame()->PopTool( tool );
273  break;
274  }
275  }
276  // click or drag starts
277  else if( !originSet && ( evt->IsDrag( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) )
278  {
279  twoPtMgr.SetOrigin( cursorPos );
280  twoPtMgr.SetEnd( cursorPos );
281 
282  controls.CaptureCursor( true );
283  controls.SetAutoPan( true );
284 
285  originSet = true;
286  }
287  // second click or mouse up after drag ends
288  else if( originSet && ( evt->IsClick( BUT_LEFT ) || evt->IsMouseUp( BUT_LEFT ) ) )
289  {
290  originSet = false;
291 
292  controls.SetAutoPan( false );
293  controls.CaptureCursor( false );
294  }
295  // move or drag when origin set updates rules
296  else if( originSet && ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) )
297  {
298  bool force45Deg = frame()->Settings().m_PcbUse45DegreeLimit;
299 
300  if( !frame()->IsType( FRAME_PCB_EDITOR ) )
301  force45Deg = frame()->Settings().m_FpeditUse45DegreeLimit;
302 
303  twoPtMgr.SetAngleSnap( force45Deg );
304  twoPtMgr.SetEnd( cursorPos );
305 
306  view.SetVisible( &ruler, true );
307  view.Update( &ruler, KIGFX::GEOMETRY );
308  }
309  else if( evt->IsAction( &ACTIONS::updateUnits ) )
310  {
311  if( frame()->GetUserUnits() != units )
312  {
313  units = frame()->GetUserUnits();
314  ruler.SwitchUnits( units );
315  view.Update( &ruler, KIGFX::GEOMETRY );
316  canvas()->Refresh();
317  }
318 
319  evt->SetPassEvent();
320  }
321  else if( evt->IsAction( &ACTIONS::updatePreferences ) )
322  {
323  ruler.UpdateDir( frame()->GetDisplayOptions().m_DisplayInvertXAxis,
324  frame()->GetDisplayOptions().m_DisplayInvertYAxis );
325 
326  view.Update( &ruler, KIGFX::GEOMETRY );
327  canvas()->Refresh();
328  evt->SetPassEvent();
329  }
330  else if( evt->IsClick( BUT_RIGHT ) )
331  {
333  }
334  else
335  {
336  evt->SetPassEvent();
337  }
338  }
339 
340  view.SetVisible( &ruler, false );
341  view.Remove( &ruler );
342 
344  controls.SetAutoPan( false );
345  controls.CaptureCursor( false );
346  return 0;
347 }
348 
349 
351 {
353 
354  // Display modes
359 
361 }
int ShowPadNumbers(const TOOL_EVENT &aEvent)
static TOOL_ACTION show3DViewer
Definition: actions.h:158
void AddStandardSubMenus(TOOL_MENU &aMenu)
Construct a "basic" menu for a tool, containing only items that apply to all tools (e....
TOOL_MENU m_menu
The functions below are not yet implemented - their interface may change.
void SetCurrentCursor(KICURSOR aCursor)
Set the current cursor shape for this panel.
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Suspend execution of the tool until an event specified in aEventList arrives.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:49
constexpr KICAD_T BaseType(const KICAD_T aType)
Return the underlying type of the given type.
Definition: typeinfo.h:231
int MeasureTool(const TOOL_EVENT &aEvent)
Represent a very simple geometry manager for items that have a start and end point.
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:46
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:214
static TOOL_ACTION cancelInteractive
Definition: actions.h:62
virtual void PushTool(const std::string &actionName)
NB: the definition of "tool" is different at the user level.
class PCB_TEXT, text on a layer
Definition: typeinfo.h:91
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:190
PCB_BASE_FRAME * frame() const
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:93
void SwitchUnits(EDA_UNITS aUnits)
Switch the ruler units.
Definition: ruler_item.h:77
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
virtual void Remove(VIEW_ITEM *aItem) override
Remove a VIEW_ITEM from the view.
Definition: pcb_view.cpp:75
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:77
KIGFX::PCB_VIEW * view() const
Classes used in Pcbnew, CvPcb and GerbView.
static TOOL_ACTION measureTool
Definition: actions.h:154
bool GetGridSnapping() const
Container for display options like enable/disable some optional drawings.
void SetDisplayOptions(const PCB_DISPLAY_OPTIONS &aOptions, bool aRefresh=true)
Updates the current display options from the given options struct.
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const override
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: pcb_view.cpp:92
Item needs to be redrawn.
Definition: view_item.h:52
int Show3DViewer(const TOOL_EVENT &aEvent)
Show the 3D viewer.
void UpdateDir(bool aFlipX, bool aFlipY)
Definition: ruler_item.h:79
Create and handle a window for the 3d viewer connected to a Kiway and a pcbboard.
virtual void PopTool(const std::string &actionName)
static TOOL_ACTION showPadNumbers
Definition: pcb_actions.h:248
static TOOL_ACTION updatePreferences
Definition: actions.h:170
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
Generic, UI-independent tool event.
Definition: tool_event.h:152
void SetOrigin(const VECTOR2I &aOrigin)
< Set the origin of the ruler (the fixed end)
bool ToolStackIsEmpty()
Definition: tools_holder.h:116
A drawn ruler item for showing the distance between two points.
Definition: ruler_item.h:41
class PCB_DIMENSION_BASE: abstract dimension meta-type
Definition: typeinfo.h:99
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:104
static TOOL_ACTION padDisplayMode
Definition: pcb_actions.h:241
static TOOL_ACTION graphicsOutlines
Display footprint graphics as outlines.
Definition: pcb_actions.h:393
bool IsFootprintFrame() const
EDA_UNITS
Definition: eda_units.h:38
OPT< std::string > GetCommandStr() const
Definition: tool_event.h:460
static TOOL_ACTION updateUnits
Definition: actions.h:147
void Flip(T &aValue)
virtual void Update3DView(bool aMarkDirty, bool aRefresh, const wxString *aTitle=nullptr)
Update the 3D view, if the viewer is opened by this frame.
const PCB_DISPLAY_OPTIONS & displayOptions() const
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
int GraphicOutlines(const TOOL_EVENT &aEvent)
PCBNEW_SETTINGS & Settings()
BOARD * board() const
PCB_DRAW_PANEL_GAL * canvas() const
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:77
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1516
void Activate()
Run the tool.
EDA_3D_VIEWER_FRAME * CreateAndShow3D_Frame()
Shows the 3D view frame.
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1) override
Add a VIEW_ITEM to the view.
Definition: pcb_view.cpp:58
int TextOutlines(const TOOL_EVENT &aEvent)
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:42
SGLIB_API S3DMODEL * GetModel(SCENEGRAPH *aNode)
Function GetModel creates an S3DMODEL representation of aNode (raw data, no transforms)
Definition: ifsg_api.cpp:338
Definition: pad.h:57
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:90
void ReparentQuasiModal(wxNonOwnedWindow *aWindow)
Move a window's parent to be the top-level window and force the window to be on top.
Definition: gtk/ui.cpp:65
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Add a menu entry to run a TOOL_ACTION on selected items.
void ShowContextMenu(SELECTION &aSelection)
Helper function to set and immediately show a CONDITIONAL_MENU in concert with the given SELECTION.
Definition: tool_menu.cpp:59
bool Init() override
Init() is called once upon a registration of the tool.
int PadDisplayMode(const TOOL_EVENT &aEvent)
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
void SetEnd(const VECTOR2I &aEnd)
Set the current end of the rectangle (the end that moves with the cursor.
Position or shape has changed.
Definition: view_item.h:49
static TOOL_ACTION textOutlines
Display texts as lines.
Definition: pcb_actions.h:396