KiCad PCB EDA Suite
common_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) 2014-2016 CERN
5  * @author Maciej Suminski <maciej.suminski@cern.ch>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <tool/actions.h>
26 #include <tool/tool_manager.h>
27 #include <draw_frame.h>
28 #include <class_draw_panel_gal.h>
29 #include <view/view.h>
30 #include <view/view_controls.h>
32 #include <base_screen.h>
33 #include <hotkeys.h>
34 
35 #include <tool/common_tools.h>
36 
37 
38 static TOOL_ACTION ACT_toggleCursor( "common.Control.toggleCursor",
40  _( "Toggle Always Show Cursor" ),
41  _( "Toggle display of the cursor, even when not in an interactive tool" ) );
42 
43 
45  TOOL_INTERACTIVE( "common.Control" ), m_frame( NULL )
46 {
47 }
48 
49 
51 {
52 }
53 
54 
56 {
57  m_frame = getEditFrame<EDA_DRAW_FRAME>();
58 }
59 
60 
61 // Cursor control
63 {
64  long type = aEvent.Parameter<intptr_t>();
65  bool fastMove = type & ACTIONS::CURSOR_FAST_MOVE;
66  type &= ~ACTIONS::CURSOR_FAST_MOVE;
67  bool mirroredX = getView()->IsMirroredX();
68 
69  VECTOR2D cursor = getViewControls()->GetRawCursorPosition( true );
70  VECTOR2I gridSize = VECTOR2D( m_frame->GetScreen()->GetGridSize() );
71 
72  if( fastMove )
73  gridSize = gridSize * 10;
74 
75  switch( type )
76  {
77  case ACTIONS::CURSOR_UP:
78  cursor -= VECTOR2D( 0, gridSize.y );
79  break;
80 
82  cursor += VECTOR2D( 0, gridSize.y );
83  break;
84 
86  cursor -= VECTOR2D( mirroredX ? -gridSize.x : gridSize.x, 0 );
87  break;
88 
90  cursor += VECTOR2D( mirroredX ? -gridSize.x : gridSize.x, 0 );
91  break;
92 
93  case ACTIONS::CURSOR_CLICK: // fall through
95  {
96  TOOL_ACTIONS action = TA_NONE;
97  int modifiers = 0;
98 
99  modifiers |= wxGetKeyState( WXK_SHIFT ) ? MD_SHIFT : 0;
100  modifiers |= wxGetKeyState( WXK_CONTROL ) ? MD_CTRL : 0;
101  modifiers |= wxGetKeyState( WXK_ALT ) ? MD_ALT : 0;
102 
103  if( type == ACTIONS::CURSOR_CLICK )
104  action = TA_MOUSE_CLICK;
105  else if( type == ACTIONS::CURSOR_DBL_CLICK )
106  action = TA_MOUSE_DBLCLICK;
107  else
108  wxFAIL;
109 
110  TOOL_EVENT evt( TC_MOUSE, action, BUT_LEFT | modifiers );
111  evt.SetMousePosition( getViewControls()->GetCursorPosition() );
112  m_toolMgr->ProcessEvent( evt );
113 
114  return 0;
115  }
116  break;
117  }
118 
119  getViewControls()->SetCursorPosition( cursor );
120 
121  return 0;
122 }
123 
124 
126 {
127  long type = aEvent.Parameter<intptr_t>();
128  KIGFX::VIEW* view = getView();
129  VECTOR2D center = view->GetCenter();
130  VECTOR2I gridSize = VECTOR2D( m_frame->GetScreen()->GetGridSize() ) * 10;
131  bool mirroredX = view->IsMirroredX();
132 
133  switch( type )
134  {
135  case ACTIONS::CURSOR_UP:
136  center -= VECTOR2D( 0, gridSize.y );
137  break;
138 
140  center += VECTOR2D( 0, gridSize.y );
141  break;
142 
144  center -= VECTOR2D( mirroredX ? -gridSize.x : gridSize.x, 0 );
145  break;
146 
148  center += VECTOR2D( mirroredX ? -gridSize.x : gridSize.x, 0 );
149  break;
150 
151  default:
152  wxFAIL;
153  break;
154  }
155 
156  view->SetCenter( center );
157 
158  return 0;
159 }
160 
161 
163 {
164  bool direction = aEvent.IsAction( &ACTIONS::zoomIn );
165  return doZoomInOut( direction, true );
166 }
167 
168 
170 {
171  bool direction = aEvent.IsAction( &ACTIONS::zoomInCenter );
172  return doZoomInOut( direction, false );
173 }
174 
175 
176 int COMMON_TOOLS::doZoomInOut( bool aDirection, bool aCenterOnCursor )
177 {
178  double zoom = m_frame->GetGalCanvas()->GetLegacyZoom();
179 
180  // Step must be AT LEAST 1.3
181  if( aDirection )
182  zoom /= 1.3;
183  else
184  zoom *= 1.3;
185 
186  // Now look for the next closest menu step
187  std::vector<double>& zoomList = m_frame->GetScreen()->m_ZoomList;
188  int idx;
189 
190  if( aDirection )
191  {
192  for( idx = zoomList.size() - 1; idx >= 0; --idx )
193  {
194  if( zoomList[idx] <= zoom )
195  break;
196  }
197 
198  if( idx < 0 )
199  idx = 0; // if we ran off the end then peg to the end
200  }
201  else
202  {
203  for( idx = 0; idx < (int)zoomList.size(); ++idx )
204  {
205  if( zoomList[idx] >= zoom )
206  break;
207  }
208 
209  if( idx >= (int)zoomList.size() )
210  idx = zoomList.size() - 1; // if we ran off the end then peg to the end
211  }
212 
213  return doZoomToPreset( idx + 1, aCenterOnCursor );
214 }
215 
216 
218 {
220 
221  ctls->CenterOnCursor();
222 
223  return 0;
224 }
225 
226 
228 {
229  KIGFX::VIEW* view = getView();
230  EDA_DRAW_PANEL_GAL* galCanvas = m_frame->GetGalCanvas();
231  EDA_ITEM* model = getModel<EDA_ITEM>();
232  EDA_BASE_FRAME* frame = getEditFrame<EDA_BASE_FRAME>();
233 
234  BOX2I bBox = model->ViewBBox();
235  VECTOR2D scrollbarSize = VECTOR2D( galCanvas->GetSize() - galCanvas->GetClientSize() );
236  VECTOR2D screenSize = view->ToWorld( galCanvas->GetClientSize(), false );
237 
238  if( bBox.GetWidth() == 0 || bBox.GetHeight() == 0 )
239  {
240  bBox = galCanvas->GetDefaultViewBBox();
241  }
242 
243  VECTOR2D vsize = bBox.GetSize();
244  double scale = view->GetScale() / std::max( fabs( vsize.x / screenSize.x ),
245  fabs( vsize.y / screenSize.y ) );
246 
247  // Reserve a 10% margin around component bounding box.
248  double margin_scale_factor = 1.1;
249 
250  // Leave 20% for library editors & viewers
251  if( frame->IsType( FRAME_PCB_MODULE_VIEWER ) || frame->IsType( FRAME_PCB_MODULE_VIEWER_MODAL )
252  || frame->IsType( FRAME_SCH_VIEWER ) || frame->IsType( FRAME_SCH_VIEWER_MODAL )
253  || frame->IsType( FRAME_SCH_LIB_EDITOR ) || frame->IsType( FRAME_PCB_MODULE_EDITOR ) )
254  {
255  margin_scale_factor = 1.2;
256  }
257 
258  view->SetScale( scale / margin_scale_factor );
259  view->SetCenter( bBox.Centre() );
260 
261  // Take scrollbars into account
262  VECTOR2D worldScrollbarSize = view->ToWorld( scrollbarSize, false );
263  view->SetCenter( view->GetCenter() + worldScrollbarSize / 2.0 );
264 
265  return 0;
266 }
267 
268 
270 {
271  EDA_DRAW_PANEL_GAL* galCanvas = m_frame->GetGalCanvas();
272  BOX2I bBox = getModel<EDA_ITEM>()->ViewBBox();
273 
274  if( bBox.GetWidth() == 0 || bBox.GetHeight() == 0 )
275  bBox = galCanvas->GetDefaultViewBBox();
276 
277  getView()->SetCenter( bBox.Centre() );
278 
279  // Take scrollbars into account
280  VECTOR2D scrollbarSize = VECTOR2D( galCanvas->GetSize() - galCanvas->GetClientSize() );
281  VECTOR2D worldScrollbarSize = getView()->ToWorld( scrollbarSize, false );
282  getView()->SetCenter( getView()->GetCenter() + worldScrollbarSize / 2.0 );
283 
284  return 0;
285 }
286 
287 
289 {
290  unsigned int idx = aEvent.Parameter<intptr_t>();
291  return doZoomToPreset( idx, false );
292 }
293 
294 
295 // Note: idx == 0 is Auto; idx == 1 is first entry in zoomList
296 int COMMON_TOOLS::doZoomToPreset( int idx, bool aCenterOnCursor )
297 {
298  std::vector<double>& zoomList = m_frame->GetScreen()->m_ZoomList;
299  KIGFX::VIEW* view = m_frame->GetGalCanvas()->GetView();
300  KIGFX::GAL* gal = m_frame->GetGalCanvas()->GetGAL();
301 
302  m_frame->SetPresetZoom( idx );
303 
304  if( idx == 0 ) // Zoom Auto
305  {
307  return ZoomFitScreen( dummy );
308  }
309  else
310  idx--;
311 
312  double selectedZoom = zoomList[idx];
313  double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor();
314  double scale = 1.0 / ( zoomFactor * selectedZoom );
315 
316  if( aCenterOnCursor )
317  {
318  view->SetScale( scale, getViewControls()->GetCursorPosition() );
319 
320  if( getViewControls()->IsCursorWarpingEnabled() )
322  }
323  else
324  view->SetScale( scale );
325 
326  return 0;
327 }
328 
329 
330 // Grid control
331 int COMMON_TOOLS::GridNext( const TOOL_EVENT& aEvent )
332 {
333  m_frame->SetNextGrid();
334  updateGrid();
335 
336  return 0;
337 }
338 
339 
340 int COMMON_TOOLS::GridPrev( const TOOL_EVENT& aEvent )
341 {
342  m_frame->SetPrevGrid();
343  updateGrid();
344 
345  return 0;
346 }
347 
348 
350 {
351  long idx = aEvent.Parameter<intptr_t>();
352 
353  m_frame->SetPresetGrid( idx );
354  updateGrid();
355 
356  return 0;
357 }
358 
359 
361 {
362  auto& galOpts = m_frame->GetGalDisplayOptions();
363 
364  galOpts.m_forceDisplayCursor = !galOpts.m_forceDisplayCursor;
365  galOpts.NotifyChanged();
366 
367  return 0;
368 }
369 
370 
372 {
373  // Cursor control
382 
385 
386  // Pan control
387  Go( &COMMON_TOOLS::PanControl, ACTIONS::panUp.MakeEvent() );
391 
392  // Zoom control
393  Go( &COMMON_TOOLS::ZoomInOut, ACTIONS::zoomIn.MakeEvent() );
400 
402 
406 
408 }
409 
410 
412 {
413  BASE_SCREEN* screen = m_frame->GetScreen();
414  getView()->GetGAL()->SetGridSize( VECTOR2D( screen->GetGridSize() ) );
416 }
EDA_DRAW_FRAME * m_frame
Pointer to the currently used edit frame.
Definition: common_tools.h:72
const VECTOR2D & GetCenter() const
Function GetCenter() Returns the center point of this VIEW (in world space coordinates) ...
Definition: view.h:341
int ZoomFitScreen(const TOOL_EVENT &aEvent)
static TOOL_ACTION zoomPreset
Definition: actions.h:57
static TOOL_ACTION zoomInCenter
Definition: actions.h:53
KIGFX::GAL_DISPLAY_OPTIONS & GetGalDisplayOptions()
Function GetGalDisplayOptions Returns a reference to the gal rendering options used by GAL for render...
Definition: draw_frame.h:945
double GetWorldScale() const
Get the world scale.
bool IsMirroredX() const
Function IsMirroredX() Returns true if view is flipped across the X axis.
Definition: view.h:232
double GetLegacyZoom() const
Function GetLegacyZoom() Returns current view scale converted to zoom value used by the legacy canvas...
VIEW_CONTROLS class definition.
TOOL_ACTIONS
Definition: tool_event.h:61
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:215
VECTOR2D ToWorld(const VECTOR2D &aCoord, bool aAbsolute=true) const
Function ToWorld() Converts a screen space point/vector to a point/vector in world space coordinates...
Definition: view.cpp:465
static TOOL_ACTION cursorRight
Definition: actions.h:65
static TOOL_ACTION zoomFitScreen
Definition: actions.h:56
static TOOL_ACTION cursorRightFast
Definition: actions.h:70
static int LegacyHotKey(int aHotKey)
Creates a hot key code that refers to a legacy hot key setting, instead of a particular key...
Definition: tool_action.h:174
bool IsAction(const TOOL_ACTION *aAction) const
Function IsAction() Tests if the event contains an action issued upon activation of the given TOOL_AC...
Definition: tool_event.cpp:54
int GridPreset(const TOOL_EVENT &aEvent)
void updateGrid()
Applies the legacy canvas grid settings for GAL.
KIGFX::VIEW * GetView() const
Function GetView() Returns a pointer to the VIEW instance used in the panel.
static TOOL_ACTION panLeft
Definition: actions.h:78
bool m_forceDisplayCursor
Force cursor display
virtual void SetPrevGrid()
Function SetPrevGrid() changes the grid size settings to the previous one available.
void SetScale(double aScale)
Function SetScale() Sets the scaling factor.
Definition: view.h:252
void SetMousePosition(const VECTOR2D &aP)
Definition: tool_event.h:414
int doZoomToPreset(int idx, bool aCenterOnCursor)
Note: idx == 0 is Auto; idx == 1 is first entry in zoomList
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Function Go()
static TOOL_ACTION zoomOutCenter
Definition: actions.h:54
Pcbnew hotkeys.
Auxiliary rendering target (noncached)
Definition: definitions.h:42
int GridNext(const TOOL_EVENT &aEvent)
coord_type GetWidth() const
Definition: box2.h:195
int ZoomInOutCenter(const TOOL_EVENT &aEvent)
virtual void SetCursorPosition(const VECTOR2D &aPosition, bool aWarpView=true)=0
Moves cursor to the requested position expressed in world coordinates.
virtual void CenterOnCursor() const =0
Function CenterOnCursor() Sets the viewport center to the current cursor position and warps the curso...
KIGFX::GAL * GetGAL() const
Function GetGAL() Returns a pointer to the GAL instance used in the panel.
static TOOL_ACTION centerContents
Definition: actions.h:59
virtual BASE_SCREEN * GetScreen() const
Function GetScreen returns a pointer to a BASE_SCREEN or one of its derivatives.
Definition: draw_frame.h:385
void SetCenter(const VECTOR2D &aCenter)
Function SetCenter() Sets the center point of the VIEW (i.e.
Definition: view.cpp:589
static TOOL_ACTION gridPreset
Definition: actions.h:88
static TOOL_ACTION gridPrev
Definition: actions.h:85
VECTOR2< double > VECTOR2D
Definition: vector2d.h:586
static TOOL_ACTION panDown
Definition: actions.h:77
GAL * GetGAL() const
Function GetGAL() Returns the GAL this view is using to draw graphical primitives.
Definition: view.h:182
void MarkTargetDirty(int aTarget)
Function MarkTargetDirty() Sets or clears target &#39;dirty&#39; flag.
Definition: view.h:602
int GridPrev(const TOOL_EVENT &aEvent)
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagates an event to tools that requested events of matching type(s).
int doZoomInOut(bool aDirection, bool aCenterOnCursor)
Class BASE_SCREEN handles how to draw a screen (a board, a schematic ...)
Definition: base_screen.h:76
Class TOOL_EVENT.
Definition: tool_event.h:168
static TOOL_ACTION cursorUpFast
Definition: actions.h:67
static TOOL_ACTION cursorDownFast
Definition: actions.h:68
static TOOL_ACTION cursorLeft
Definition: actions.h:64
static TOOL_ACTION panRight
Definition: actions.h:79
int ZoomCenter(const TOOL_EVENT &aEvent)
Class VIEW_CONTROLS is an interface for classes handling user events controlling the view behaviour (...
int ZoomInOut(const TOOL_EVENT &aEvent)
void SetPresetZoom(int aIndex)
Function SetPresetZoom() changes zoom to one of the preset values.
static TOOL_ACTION cursorLeftFast
Definition: actions.h:69
void SetPresetGrid(int aIndex)
Function SetPresetGrid() changes the grid size to one of the preset values.
All active tools
Definition: tool_event.h:144
int CursorControl(const TOOL_EVENT &aEvent)
int ToggleCursor(const TOOL_EVENT &aEvent)
virtual BOX2I GetDefaultViewBBox() const
Returns the bounding box of the view that should be used if model is not valid For example...
void SetGridSize(const VECTOR2D &aGridSize)
Set the grid size.
Vec Centre() const
Definition: box2.h:77
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:41
void setTransitions() override
Sets up handlers for various events.
virtual void SetNextGrid()
Function SetNextGrid() changes the grid size settings to the next one available.
KIGFX::VIEW * getView() const
Function getView()
Definition: tool_base.cpp:35
int CenterContents(const TOOL_EVENT &aEvent)
coord_type GetHeight() const
Definition: box2.h:196
T Parameter() const
Function Parameter() Returns a non-standard parameter assigned to the event.
Definition: tool_event.h:387
TOOL_EVENT MakeEvent() const
Function HasHotKey() Checks if the action has a hot key assigned.
Definition: tool_action.h:104
const int scale
virtual VECTOR2D GetRawCursorPosition(bool aSnappingEnabled=true) const =0
Returns the current cursor position in world coordinates - ingoring the cursorUp position force mode...
static TOOL_ACTION zoomCenter
Definition: actions.h:55
static LIB_PART * dummy()
Used when a LIB_PART is not found in library to draw a dummy shape This component is a 400 mils squar...
#define max(a, b)
Definition: auxiliary.h:86
static TOOL_ACTION cursorUp
Cursor control with keyboard.
Definition: actions.h:62
static TOOL_ACTION cursorDblClick
Definition: actions.h:73
int ZoomPreset(const TOOL_EVENT &aEvent)
Class EDA_BASE_FRAME is the base frame for deriving all KiCad main window classes.
Class TOOL_ACTION.
Definition: tool_action.h:46
const wxRealPoint & GetGridSize() const
Return the grid size of the currently selected grid.
Definition: base_screen.h:410
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:151
double GetZoomFactor() const
Get the zoom factor.
static TOOL_ACTION gridNext
Definition: actions.h:84
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:80
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
double GetScale() const
Function GetScale()
Definition: view.h:270
Class ACTIONS.
Definition: actions.h:41
static TOOL_ACTION panUp
Definition: actions.h:76
static TOOL_ACTION zoomIn
Definition: actions.h:51
static TOOL_ACTION zoomOut
Definition: actions.h:52
EDA_DRAW_PANEL_GAL * GetGalCanvas() const
Function GetGalCanvas returns a pointer to GAL-based canvas of given EDA draw frame.
Definition: draw_frame.h:924
Class VIEW.
Definition: view.h:61
BASE_SCREEN class implementation.
virtual const BOX2I ViewBBox() const override
Function ViewBBox() returns the bounding box of the item covering all its layers. ...
static TOOL_ACTION cursorDown
Definition: actions.h:63
int PanControl(const TOOL_EVENT &aEvent)
static TOOL_ACTION ACT_toggleCursor("common.Control.toggleCursor", AS_GLOBAL, TOOL_ACTION::LegacyHotKey(HK_TOGGLE_CURSOR), _("Toggle Always Show Cursor"), _("Toggle display of the cursor, even when not in an interactive tool"))
static TOOL_ACTION cursorClick
Definition: actions.h:72
std::vector< double > m_ZoomList
standard zoom (i.e. scale) coefficients.
Definition: base_screen.h:219
Class GAL is the abstract interface for drawing on a 2D-surface.