KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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-2024 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
26#include <wx/clipbrd.h>
27
31#include <kiplatform/ui.h>
32#include <pcb_base_frame.h>
33#include <pcbnew_settings.h>
35#include <pgm_base.h>
37#include <tool/actions.h>
39#include <tools/pcb_actions.h>
40
41
43{
44 // Populate the context menu displayed during the tool (primarily the measure tool)
45 auto activeToolCondition =
46 [ this ] ( const SELECTION& aSel )
47 {
48 return !frame()->ToolStackIsEmpty();
49 };
50
51 CONDITIONAL_MENU& ctxMenu = m_menu->GetMenu();
52
53 // "Cancel" goes at the top of the context menu when a tool is active
54 ctxMenu.AddItem( ACTIONS::cancelInteractive, activeToolCondition, 1 );
55 ctxMenu.AddSeparator( 1 );
56
57 ctxMenu.AddCheckItem( PCB_ACTIONS::toggleHV45Mode, activeToolCondition, 2 );
58 ctxMenu.AddSeparator( activeToolCondition, 2 );
59
60 ctxMenu.AddItem( ACTIONS::copy, activeToolCondition, 3 );
61 ctxMenu.AddSeparator( activeToolCondition, 3 );
62
63 frame()->AddStandardSubMenus( *m_menu.get() );
64
65 return true;
66}
67
68
70{
71}
72
73
75{
76 bool do_reload_board = true; // reload board flag
77
78 // At EDA_3D_VIEWER_FRAME creation, the current board is loaded, so disable loading
79 // the current board if the 3D frame is not yet created
80 if( frame()->Get3DViewerFrame() == nullptr )
81 do_reload_board = false;
82
84
85 if( frame()->IsType( FRAME_FOOTPRINT_VIEWER )
86 || frame()->IsType( FRAME_FOOTPRINT_WIZARD ) )
87 {
88 // A stronger version of Raise() which promotes the window to its parent's level.
89 KIPLATFORM::UI::ReparentModal( draw3DFrame );
90 }
91
92 // And load or update the current board (if needed)
93 if( do_reload_board )
94 frame()->Update3DView( true, true );
95
96 return 0;
97}
98
99
100template<class T> void Flip( T& aValue )
101{
102 aValue = !aValue;
103}
104
105
107{
110
111 for( FOOTPRINT* fp : board()->Footprints() )
112 {
113 for( PAD* pad : fp->Pads() )
115 }
116
117 canvas()->Refresh();
118
119 return 0;
120}
121
122
124{
127
128 for( FOOTPRINT* fp : board()->Footprints() )
129 {
130 for( PAD* pad : fp->Pads() )
132 }
133
134 canvas()->Refresh();
135
136 return 0;
137}
138
139
141{
144
145 for( FOOTPRINT* fp : board()->Footprints() )
146 {
147 for( BOARD_ITEM* item : fp->GraphicalItems() )
148 {
149 KICAD_T t = item->Type();
150
151 if( t == PCB_SHAPE_T || BaseType( t ) == PCB_DIMENSION_T )
152 view()->Update( item, KIGFX::REPAINT );
153 }
154 }
155
156 for( BOARD_ITEM* item : board()->Drawings() )
157 {
158 KICAD_T t = item->Type();
159
160 if( t == PCB_SHAPE_T || BaseType( t ) == PCB_DIMENSION_T || t == PCB_TARGET_T )
161 view()->Update( item, KIGFX::REPAINT );
162 }
163
164 canvas()->Refresh();
165
166 return 0;
167}
168
169
171{
174
175 for( FOOTPRINT* fp : board()->Footprints() )
176 {
177 for( PCB_FIELD* field : fp->Fields() )
178 {
179 view()->Update( field, KIGFX::REPAINT );
180 }
181
182 for( BOARD_ITEM* item : fp->GraphicalItems() )
183 {
184 if( item->Type() == PCB_TEXT_T )
185 view()->Update( item, KIGFX::REPAINT );
186 }
187 }
188
189 for( BOARD_ITEM* item : board()->Drawings() )
190 {
191 KICAD_T t = item->Type();
192
193 if( t == PCB_TEXT_T || t == PCB_TEXTBOX_T || BaseType( t ) == PCB_DIMENSION_T )
194 view()->Update( item, KIGFX::REPAINT );
195 }
196
197 canvas()->Refresh();
198
199 return 0;
200}
201
202
204
205
207{
208 if( IsFootprintFrame() && !frame()->GetModel() )
209 return 0;
210
211 if( frame()->IsCurrentTool( ACTIONS::measureTool ) )
212 return 0;
213
214 auto& view = *getView();
215 auto& controls = *getViewControls();
216
217 frame()->PushTool( aEvent );
218
219 bool invertXAxis = displayOptions().m_DisplayInvertXAxis;
220 bool invertYAxis = displayOptions().m_DisplayInvertYAxis;
221
222 if( IsFootprintFrame() )
223 {
226 }
227
229 PCB_GRID_HELPER grid( m_toolMgr, frame()->GetMagneticItemsSettings() );
230 bool originSet = false;
231 EDA_UNITS units = frame()->GetUserUnits();
232 KIGFX::PREVIEW::RULER_ITEM ruler( twoPtMgr, pcbIUScale, units, invertXAxis, invertYAxis );
233
234 view.Add( &ruler );
235 view.SetVisible( &ruler, false );
236
237 auto setCursor =
238 [&]()
239 {
240 frame()->GetCanvas()->SetCurrentCursor( KICURSOR::MEASURE );
241 };
242
243 auto cleanup =
244 [&] ()
245 {
246 view.SetVisible( &ruler, false );
247 controls.SetAutoPan( false );
248 controls.CaptureCursor( false );
249 controls.ForceCursorPosition( false );
250 originSet = false;
251 };
252
253 Activate();
254 // Must be done after Activate() so that it gets set into the correct context
255 controls.ShowCursor( true );
256 controls.SetAutoPan( false );
257 controls.CaptureCursor( false );
258 controls.ForceCursorPosition( false );
259
260 // Set initial cursor
261 setCursor();
262
263 while( TOOL_EVENT* evt = Wait() )
264 {
265 setCursor();
266 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
267 grid.SetUseGrid( view.GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
268 VECTOR2I cursorPos = evt->HasPosition() ? evt->Position() : controls.GetMousePosition();
269 cursorPos = grid.BestSnapAnchor( cursorPos, nullptr );
270 controls.ForceCursorPosition( true, cursorPos );
271
272 if( evt->IsCancelInteractive() )
273 {
274 if( originSet )
275 {
276 cleanup();
277 }
278 else
279 {
280 frame()->PopTool( aEvent );
281 break;
282 }
283 }
284 else if( evt->IsActivate() )
285 {
286 if( originSet )
287 cleanup();
288
289 if( evt->IsMoveTool() )
290 {
291 // leave ourselves on the stack so we come back after the move
292 break;
293 }
294 else
295 {
296 frame()->PopTool( aEvent );
297 break;
298 }
299 }
300 // click or drag starts
301 else if( !originSet && ( evt->IsDrag( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) )
302 {
303 twoPtMgr.SetOrigin( cursorPos );
304 twoPtMgr.SetEnd( cursorPos );
305
306 controls.CaptureCursor( true );
307 controls.SetAutoPan( true );
308
309 originSet = true;
310 }
311 // second click or mouse up after drag ends
312 else if( originSet && ( evt->IsClick( BUT_LEFT ) || evt->IsMouseUp( BUT_LEFT ) ) )
313 {
314 originSet = false;
315
316 controls.SetAutoPan( false );
317 controls.CaptureCursor( false );
318 }
319 // move or drag when origin set updates rules
320 else if( originSet && ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) )
321 {
323 bool force45Deg;
324
325 if( frame()->IsType( FRAME_PCB_EDITOR ) )
326 force45Deg = mgr.GetAppSettings<PCBNEW_SETTINGS>()->m_Use45DegreeLimit;
327 else
328 force45Deg = mgr.GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>()->m_Use45Limit;
329
330 twoPtMgr.SetAngleSnap( force45Deg );
331 twoPtMgr.SetEnd( cursorPos );
332
333 view.SetVisible( &ruler, true );
334 view.Update( &ruler, KIGFX::GEOMETRY );
335 }
336 else if( evt->IsAction( &ACTIONS::updateUnits ) )
337 {
338 if( frame()->GetUserUnits() != units )
339 {
340 units = frame()->GetUserUnits();
341 ruler.SwitchUnits( units );
342 view.Update( &ruler, KIGFX::GEOMETRY );
343 canvas()->Refresh();
344 }
345
346 evt->SetPassEvent();
347 }
348 else if( evt->IsAction( &ACTIONS::updatePreferences ) )
349 {
350 invertXAxis = displayOptions().m_DisplayInvertXAxis;
351 invertYAxis = displayOptions().m_DisplayInvertYAxis;
352
353 if( IsFootprintFrame() )
354 {
357 }
358
359 ruler.UpdateDir( invertXAxis, invertYAxis );
360
361 view.Update( &ruler, KIGFX::GEOMETRY );
362 canvas()->Refresh();
363 evt->SetPassEvent();
364 }
365 else if( evt->IsAction( &ACTIONS::copy ) )
366 {
367 if( originSet )
368 {
369 wxArrayString cursorStrings = ruler.GetDimensionStrings();
370 wxString text = wxJoin( cursorStrings, '\n' );
371
372 if( wxTheClipboard->Open() )
373 {
374 wxTheClipboard->SetData( new wxTextDataObject( text ) );
375 wxTheClipboard->Close();
376 }
377 }
378 }
379 else if( evt->IsClick( BUT_RIGHT ) )
380 {
381 m_menu->ShowContextMenu();
382 }
383 else
384 {
385 evt->SetPassEvent();
386 }
387 }
388
389 view.SetVisible( &ruler, false );
390 view.Remove( &ruler );
391
392 frame()->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
393 controls.SetAutoPan( false );
394 controls.CaptureCursor( false );
395 controls.ForceCursorPosition( false );
396 return 0;
397}
398
399
401{
402 // clang-format off
404
405 // Display modes
410
412 // clang-format on
413}
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
static TOOL_ACTION cancelInteractive
Definition: actions.h:65
static TOOL_ACTION show3DViewer
Definition: actions.h:209
static TOOL_ACTION updatePreferences
Definition: actions.h:223
static TOOL_ACTION copy
Definition: actions.h:71
static TOOL_ACTION updateUnits
Definition: actions.h:196
static TOOL_ACTION measureTool
Definition: actions.h:203
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:79
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 AddSeparator(int aOrder=ANY_ORDER)
Add a separator to the menu.
void AddCheckItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Add a checked menu entry to run a TOOL_ACTION on selected items.
Create and handle a window for the 3d viewer connected to a Kiway and a pcbboard.
void AddStandardSubMenus(TOOL_MENU &aMenu)
Construct a "basic" menu for a tool, containing only items that apply to all tools (e....
void SetCurrentCursor(KICURSOR aCursor)
Set the current cursor shape for this panel.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
bool GetGridSnapping() const
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:91
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1) override
Add a VIEW_ITEM to the view.
Definition: pcb_view.cpp:57
virtual void Remove(VIEW_ITEM *aItem) override
Remove a VIEW_ITEM from the view.
Definition: pcb_view.cpp:74
A drawn ruler item for showing the distance between two points.
Definition: ruler_item.h:45
wxArrayString GetDimensionStrings() const
Get the strings for the dimensions of the ruler.
Definition: ruler_item.cpp:373
void SwitchUnits(EDA_UNITS aUnits)
Switch the ruler units.
Definition: ruler_item.h:90
void UpdateDir(bool aFlipX, bool aFlipY)
Definition: ruler_item.h:92
Represent a very simple geometry manager for items that have a start and end point.
void SetOrigin(const VECTOR2I &aOrigin)
< Set the origin of the ruler (the fixed end)
void SetEnd(const VECTOR2I &aEnd)
Set the current end of the rectangle (the end that moves with the cursor.
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:199
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1596
Definition: pad.h:54
static TOOL_ACTION toggleHV45Mode
Definition: pcb_actions.h:524
static TOOL_ACTION padDisplayMode
Definition: pcb_actions.h:340
static TOOL_ACTION graphicsOutlines
Display footprint graphics as outlines.
Definition: pcb_actions.h:496
static TOOL_ACTION textOutlines
Display texts as lines.
Definition: pcb_actions.h:499
static TOOL_ACTION showPadNumbers
Definition: pcb_actions.h:347
virtual PCB_VIEWERS_SETTINGS_BASE * GetViewerSettingsBase() const
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
FOOTPRINT_EDITOR_SETTINGS * GetFootprintEditorSettings() const
EDA_3D_VIEWER_FRAME * CreateAndShow3D_Frame()
Shows the 3D view frame.
virtual void Update3DView(bool aMarkDirty, bool aRefresh, const wxString *aTitle=nullptr)
Update the 3D view, if the viewer is opened by this frame.
VIEWERS_DISPLAY_OPTIONS m_ViewersDisplay
bool Init() override
Init() is called once upon a registration of the tool.
PCBNEW_SETTINGS::DISPLAY_OPTIONS & displayOptions() const
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
PCB_BASE_FRAME * frame() const
int PadDisplayMode(const TOOL_EVENT &aEvent)
BOARD * board() const
KIGFX::PCB_VIEW * view() const
int MeasureTool(const TOOL_EVENT &aEvent)
int TextOutlines(const TOOL_EVENT &aEvent)
PCB_DRAW_PANEL_GAL * canvas() const
bool IsFootprintFrame() const
int Show3DViewer(const TOOL_EVENT &aEvent)
Show the 3D viewer.
int GraphicOutlines(const TOOL_EVENT &aEvent)
int ShowPadNumbers(const TOOL_EVENT &aEvent)
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:142
T * GetAppSettings()
Returns a handle to the a given settings by type If the settings have already been loaded,...
virtual void PopTool(const TOOL_EVENT &aEvent)
Pops a tool from the stack.
virtual void PushTool(const TOOL_EVENT &aEvent)
NB: the definition of "tool" is different at the user level.
bool ToolStackIsEmpty()
Definition: tools_holder.h:125
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:42
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:218
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
Generic, UI-independent tool event.
Definition: tool_event.h:167
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).
std::unique_ptr< TOOL_MENU > m_menu
The functions below are not yet implemented - their interface may change.
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.
void Activate()
Run the tool.
EDA_UNITS GetUserUnits() const
Declaration of the eda_3d_viewer class.
EDA_UNITS
Definition: eda_units.h:46
@ FRAME_PCB_EDITOR
Definition: frame_type.h:42
@ FRAME_FOOTPRINT_VIEWER
Definition: frame_type.h:45
@ FRAME_FOOTPRINT_WIZARD
Definition: frame_type.h:46
@ REPAINT
Item needs to be redrawn.
Definition: view_item.h:57
@ GEOMETRY
Position or shape has changed.
Definition: view_item.h:54
void ReparentModal(wxNonOwnedWindow *aWindow)
Move a window's parent to be the top-level window and force the window to be on top.
Definition: wxgtk/ui.cpp:88
void Flip(T &aValue)
void Flip(T &aValue)
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: pgm_base.cpp:1060
see class PGM_BASE
@ MD_SHIFT
Definition: tool_event.h:142
@ BUT_LEFT
Definition: tool_event.h:131
@ BUT_RIGHT
Definition: tool_event.h:132
constexpr KICAD_T BaseType(const KICAD_T aType)
Return the underlying type of the given type.
Definition: typeinfo.h:249
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:88
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:93
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:92
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:106
@ PCB_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
Definition: typeinfo.h:100