KiCad PCB EDA Suite
draw_panel.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) 2009 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.fr
5  * Copyright (C) 2007 Wayne Stambaugh <stambaughw@gmail.com>
6  * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
30 #include <fctsys.h>
31 #include <wx/timer.h>
32 #include <pgm_base.h>
33 #include <kiface_i.h>
34 #include <gr_basic.h>
35 #include <common.h>
36 #include <macros.h>
37 #include <id.h>
38 #include <class_drawpanel.h>
39 #include <class_draw_panel_gal.h>
40 #include <base_screen.h>
41 #include <draw_frame.h>
42 #include <view/view_controls.h>
44 #include <trace_helpers.h>
45 
46 #include <kicad_device_context.h>
47 
48 static const int CURSOR_SIZE = 12;
49 
50 #define CLIP_BOX_PADDING 2
51 
54 
55 #define ENBL_ZOOM_NO_CENTER_KEY wxT( "ZoomNoCenter" )
56 #define ENBL_MOUSEWHEEL_PAN_KEY wxT( "MousewheelPAN" )
57 #define ENBL_MIDDLE_BUTT_PAN_KEY wxT( "MiddleButtonPAN" )
58 #define MIDDLE_BUTT_PAN_LIMITED_KEY wxT( "MiddleBtnPANLimited" )
59 #define ENBL_AUTO_PAN_KEY wxT( "AutoPAN" )
60 
62 
63 
64 // Definitions for enabling and disabling debugging features in drawpanel.cpp.
65 // Please don't forget to turn these off before making any commits to Launchpad.
66 #define DEBUG_SHOW_CLIP_RECT 0 // Set to 1 to draw clipping rectangle.
67 
68 
69 // Events used by EDA_DRAW_PANEL
70 BEGIN_EVENT_TABLE( EDA_DRAW_PANEL, wxScrolledWindow )
71  EVT_LEAVE_WINDOW( EDA_DRAW_PANEL::OnMouseLeaving )
72  EVT_ENTER_WINDOW( EDA_DRAW_PANEL::OnMouseEntering )
73  EVT_MOUSEWHEEL( EDA_DRAW_PANEL::OnMouseWheel )
74 #if wxCHECK_VERSION( 3, 1, 0 ) || defined( USE_OSX_MAGNIFY_EVENT )
75  EVT_MAGNIFY( EDA_DRAW_PANEL::OnMagnify )
76 #endif
77  EVT_MOUSE_EVENTS( EDA_DRAW_PANEL::OnMouseEvent )
78  EVT_CHAR( EDA_DRAW_PANEL::OnKeyEvent )
79  EVT_CHAR_HOOK( EDA_DRAW_PANEL::OnKeyEvent )
80  EVT_PAINT( EDA_DRAW_PANEL::OnPaint )
81  EVT_ERASE_BACKGROUND( EDA_DRAW_PANEL::OnEraseBackground )
82  EVT_SCROLLWIN( EDA_DRAW_PANEL::OnScroll )
83  EVT_ACTIVATE( EDA_DRAW_PANEL::OnActivate )
84  EVT_TIMER( ID_MOUSE_DOUBLECLICK, EDA_DRAW_PANEL::OnTimer )
86 END_EVENT_TABLE()
87 
88 
89 /***********************************************************************/
90 /* EDA_DRAW_PANEL base functions (EDA_DRAW_PANEL is the main panel)*/
91 /***********************************************************************/
92 
93 #ifdef __WXMAC__
94 const int drawPanelStyle = wxBORDER | wxHSCROLL | wxVSCROLL | wxALWAYS_SHOW_SB;
95 #else
96 const int drawPanelStyle = wxBORDER | wxHSCROLL | wxVSCROLL;
97 #endif
98 
100  const wxPoint& pos, const wxSize& size ) :
101  wxScrolledWindow( parent, id, pos, size, drawPanelStyle )
102 {
103  wxASSERT( parent );
104 
105  ShowScrollbars( wxSHOW_SB_ALWAYS, wxSHOW_SB_ALWAYS );
106  DisableKeyboardScrolling();
107 
108  m_scrollIncrementX = std::min( size.x / 8, 10 );
109  m_scrollIncrementY = std::min( size.y / 8, 10 );
110 
111  SetLayoutDirection( wxLayout_LeftToRight );
112 
113  SetBackgroundColour( parent->GetDrawBgColor().ToColour() );
114 
115 #if KICAD_USE_BUFFERED_DC || KICAD_USE_BUFFERED_PAINTDC
116  SetBackgroundStyle( wxBG_STYLE_CUSTOM );
117 #endif
118 
119  m_ClipBox.SetSize( size );
120  m_ClipBox.SetX( 0 );
121  m_ClipBox.SetY( 0 );
122  m_canStartBlock = -1; // Command block can start if >= 0
123  m_abortRequest = false;
124  m_enableMousewheelPan = false;
125  m_enableZoomNoCenter = false;
126  m_enableAutoPan = true;
127  m_ignoreMouseEvents = false;
128  // Be sure a mouse release button event will be ignored when creating the canvas
129  // if the mouse click was not made inside the canvas (can happen sometimes, when
130  // launching a editor from a double click made in another frame)
132 
133  m_mouseCaptureCallback = NULL;
135 
136  wxConfigBase* cfg = Kiface().KifaceSettings();
137 
138  if( cfg )
139  {
140  cfg->Read( ENBL_MOUSEWHEEL_PAN_KEY, &m_enableMousewheelPan, false );
141  cfg->Read( ENBL_ZOOM_NO_CENTER_KEY, &m_enableZoomNoCenter, false );
142  cfg->Read( ENBL_AUTO_PAN_KEY, &m_enableAutoPan, true );
143  }
144 
145  m_requestAutoPan = false;
146  m_enableBlockCommands = false;
148 
149 #ifdef __WXMAC__
150  m_defaultCursor = m_currentCursor = wxCURSOR_CROSS;
151  m_showCrossHair = false;
152 #else
153  m_defaultCursor = m_currentCursor = wxCURSOR_ARROW;
154  m_showCrossHair = true;
155 #endif
156 
157  m_cursorLevel = 0;
158  m_PrintIsMirrored = false;
159 
160  m_ClickTimer = (wxTimer*) NULL;
161  m_doubleClickInterval = 250;
162 }
163 
164 
166 {
167  wxConfigBase* cfg = Kiface().KifaceSettings();
168 
169  if( cfg )
170  {
173  cfg->Write( ENBL_AUTO_PAN_KEY, m_enableAutoPan );
174  }
175 
176  wxDELETE( m_ClickTimer );
177 }
178 
179 
181 {
182  wxWindow* mom = wxScrolledWindow::GetParent();
183  return (EDA_DRAW_FRAME*) mom;
184 }
185 
186 
188 {
189  return GetParent()->GetDisplayOptions();
190 }
191 
192 
194 {
195  EDA_DRAW_FRAME* parentFrame = GetParent();
196 
197  return parentFrame->GetScreen();
198 }
199 
200 
202 {
203  wxPoint ret;
204  INSTALL_UNBUFFERED_DC( dc, this );
205  ret.x = dc.LogicalToDeviceX( pos.x );
206  ret.y = dc.LogicalToDeviceY( pos.y );
207  return ret;
208 }
209 
210 
212 {
213  wxPoint ret;
214  INSTALL_UNBUFFERED_DC( dc, this );
215  ret.x = dc.DeviceToLogicalX( pos.x );
216  ret.y = dc.DeviceToLogicalY( pos.y );
217  return ret;
218 }
219 
220 
221 void EDA_DRAW_PANEL::DrawCrossHair( wxDC* aDC, COLOR4D aColor )
222 {
223  if( m_cursorLevel != 0 || aDC == NULL || !m_showCrossHair )
224  return;
225 
226  wxPoint cursor = GetParent()->GetCrossHairPosition();
227 
228 #ifdef USE_WX_GRAPHICS_CONTEXT
229  // Normally cursor color is set to white, so when it is xored with white
230  // background, it is painted black effectively. wxGraphicsContext does not have
231  // xor operation, so we need to invert the color manually.
232  aColor.Invert();
233 #else
234  GRSetDrawMode( aDC, GR_XOR );
235 #endif
236 
237  if( GetParent()->GetGalDisplayOptions().m_fullscreenCursor )
238  {
239  wxSize clientSize = GetClientSize();
240 
241  // Y axis
242  wxPoint lineStart( cursor.x, aDC->DeviceToLogicalY( 0 ) );
243  wxPoint lineEnd( cursor.x, aDC->DeviceToLogicalY( clientSize.y ) );
244 
245  GRLine( &m_ClipBox, aDC, lineStart, lineEnd, 0, aColor );
246 
247  // X axis
248  lineStart = wxPoint( aDC->DeviceToLogicalX( 0 ), cursor.y );
249  lineEnd = wxPoint( aDC->DeviceToLogicalX( clientSize.x ), cursor.y );
250 
251  GRLine( &m_ClipBox, aDC, lineStart, lineEnd, 0, aColor );
252  }
253  else
254  {
255  int len = aDC->DeviceToLogicalXRel( CURSOR_SIZE );
256 
257  GRLine( &m_ClipBox, aDC, cursor.x - len, cursor.y,
258  cursor.x + len, cursor.y, 0, aColor );
259  GRLine( &m_ClipBox, aDC, cursor.x, cursor.y - len,
260  cursor.x, cursor.y + len, 0, aColor );
261  }
262 }
263 
264 
266 {
267  DrawCrossHair( DC );
268  --m_cursorLevel;
269 }
270 
271 
273 {
274  ++m_cursorLevel;
275  DrawCrossHair( DC );
276 
277  if( m_cursorLevel > 0 ) // Shouldn't happen, but just in case ..
278  m_cursorLevel = 0;
279 }
280 
281 
283 {
284  return GetScreen()->GetZoom();
285 }
286 
287 
288 void EDA_DRAW_PANEL::SetZoom( double zoom )
289 {
290  GetScreen()->SetZoom( zoom );
291 }
292 
293 
295 {
296  return GetScreen()->GetGridSize();
297 }
298 
299 
301 {
302  wxPoint pos;
303  EDA_RECT display_rect;
304 
305  INSTALL_UNBUFFERED_DC( dc, this ); // Refresh the clip box to the entire screen size.
306  SetClipBox( dc );
307 
308  display_rect = m_ClipBox;
309 
310  // Slightly decreased the size of the useful screen area to avoid drawing limits.
311  #define PIXEL_MARGIN 8
312  display_rect.Inflate( -PIXEL_MARGIN );
313 
314  return display_rect.Contains( aPosition );
315 }
316 
317 
318 void EDA_DRAW_PANEL::RefreshDrawingRect( const EDA_RECT& aRect, bool aEraseBackground )
319 {
320  INSTALL_UNBUFFERED_DC( dc, this );
321 
322  wxRect rect = aRect;
323 
324  rect.x = dc.LogicalToDeviceX( rect.x );
325  rect.y = dc.LogicalToDeviceY( rect.y );
326  rect.width = dc.LogicalToDeviceXRel( rect.width );
327  rect.height = dc.LogicalToDeviceYRel( rect.height );
328 
329  wxLogTrace( kicadTraceCoords,
330  wxT( "Refresh area: drawing (%d, %d, %d, %d), device (%d, %d, %d, %d)" ),
331  aRect.GetX(), aRect.GetY(), aRect.GetWidth(), aRect.GetHeight(),
332  rect.x, rect.y, rect.width, rect.height );
333 
334  RefreshRect( rect, aEraseBackground );
335 }
336 
337 
338 void EDA_DRAW_PANEL::Refresh( bool eraseBackground, const wxRect* rect )
339 {
340  if( GetParent()->IsGalCanvasActive() )
341  {
343  }
344  else
345  {
346  wxScrolledWindow::Refresh( eraseBackground, rect );
347  }
348 }
349 
350 
352 {
353  wxSize size = GetClientSize() / 2;
354  INSTALL_UNBUFFERED_DC( dc, this );
355 
356  return wxPoint( dc.DeviceToLogicalX( size.x ), dc.DeviceToLogicalY( size.y ) );
357 }
358 
359 
361 {
362  MoveCursor( GetParent()->GetCrossHairPosition() );
363 }
364 
365 
366 void EDA_DRAW_PANEL::MoveCursor( const wxPoint& aPosition )
367 {
368  if( GetParent()->IsGalCanvasActive() )
369  return;
370 
371  int x, y, xPpu, yPpu;
372  wxPoint screenPos, drawingPos;
373  wxRect clientRect( wxPoint( 0, 0 ), GetClientSize() );
374 
375  INSTALL_UNBUFFERED_DC( dc, this );
376  screenPos.x = dc.LogicalToDeviceX( aPosition.x );
377  screenPos.y = dc.LogicalToDeviceY( aPosition.y );
378 
379  // Scroll if the requested mouse position cursor is outside the drawing area.
380  if( !clientRect.Contains( screenPos ) )
381  {
382  GetViewStart( &x, &y );
383  GetScrollPixelsPerUnit( &xPpu, &yPpu );
384  CalcUnscrolledPosition( screenPos.x, screenPos.y, &drawingPos.x, &drawingPos.y );
385 
386  wxLogTrace( kicadTraceCoords,
387  wxT( "MoveCursor() initial screen position(%d, %d) " ) \
388  wxT( "rectangle(%d, %d, %d, %d) view(%d, %d)" ),
389  screenPos.x, screenPos.y, clientRect.x, clientRect.y,
390  clientRect.width, clientRect.height, x, y );
391 
392  if( screenPos.y < clientRect.GetTop() )
393  y -= m_scrollIncrementY * yPpu;
394  else if( screenPos.y > clientRect.GetBottom() )
395  y += m_scrollIncrementY * yPpu;
396  else if( clientRect.GetRight() < screenPos.x )
397  x += m_scrollIncrementX * xPpu;
398  else
399  x -= m_scrollIncrementX * xPpu;
400 
401  Scroll( x, y );
402  CalcScrolledPosition( drawingPos.x, drawingPos.y, &screenPos.x, &screenPos.y );
403 
404  wxLogTrace( kicadTraceCoords,
405  wxT( "MoveCursor() scrolled screen position(%d, %d) view(%d, %d)" ),
406  screenPos.x, screenPos.y, x, y );
407  }
408 
409  WarpPointer( screenPos.x, screenPos.y );
410 }
411 
412 
413 void EDA_DRAW_PANEL::OnActivate( wxActivateEvent& event )
414 {
415  m_canStartBlock = -1; // Block Command can't start
416  event.Skip();
417 }
418 
419 
420 void EDA_DRAW_PANEL::OnTimer( wxTimerEvent& event )
421 {
422  INSTALL_UNBUFFERED_DC( DC, this );
423  DC.SetBackground( *wxBLACK_BRUSH );
425 }
426 
427 
428 void EDA_DRAW_PANEL::OnScroll( wxScrollWinEvent& event )
429 {
430  int id = event.GetEventType();
431  int x, y;
432  int ppux, ppuy;
433  int csizeX, csizeY;
434  int unitsX, unitsY;
435 
436  GetViewStart( &x, &y );
437  GetScrollPixelsPerUnit( &ppux, &ppuy );
438  GetClientSize( &csizeX, &csizeY );
439  GetVirtualSize( &unitsX, &unitsY );
440 
441  int tmpX = x;
442  int tmpY = y;
443 
444  csizeX /= ppux;
445  csizeY /= ppuy;
446 
447  unitsX /= ppux;
448  unitsY /= ppuy;
449 
450  int dir = event.GetOrientation(); // wxHORIZONTAL or wxVERTICAL
451 
452  // On windows and on wxWidgets >= 2.9.5 and < 3.1,
453  // there is a bug in mousewheel event which always generates 2 scroll events
454  // (should be the case only for the default mousewheel event)
455  // with id = wxEVT_SCROLLWIN_LINEUP or wxEVT_SCROLLWIN_LINEDOWN
456  // so we skip these events.
457  // Note they are here just in case, because they are not actually used
458  // in Kicad
459 #if wxCHECK_VERSION( 3, 1, 0 ) || !wxCHECK_VERSION( 2, 9, 5 ) || ( !defined (__WINDOWS__) && !defined (__WXMAC__) )
460  int maxX = unitsX - csizeX;
461  int maxY = unitsY - csizeY;
462 
463  if( id == wxEVT_SCROLLWIN_LINEUP )
464  {
465  if( dir == wxHORIZONTAL )
466  {
467  x -= m_scrollIncrementX;
468 
469  if( x < 0 )
470  x = 0;
471  }
472  else
473  {
474  y -= m_scrollIncrementY;
475 
476  if( y < 0 )
477  y = 0;
478  }
479  }
480  else if( id == wxEVT_SCROLLWIN_LINEDOWN )
481  {
482  if( dir == wxHORIZONTAL )
483  {
484  x += m_scrollIncrementX;
485  if( x > maxX )
486  x = maxX;
487  }
488  else
489  {
490  y += m_scrollIncrementY;
491 
492  if( y > maxY )
493  y = maxY;
494  }
495  }
496  else
497 #endif
498  if( id == wxEVT_SCROLLWIN_THUMBTRACK )
499  {
500  if( dir == wxHORIZONTAL )
501  x = event.GetPosition();
502  else
503  y = event.GetPosition();
504  }
505  else
506  {
507  event.Skip();
508  return;
509  }
510 
511  wxLogTrace( kicadTraceCoords,
512  wxT( "Setting scroll bars ppuX=%d, ppuY=%d, unitsX=%d, unitsY=%d, posX=%d, posY=%d" ),
513  ppux, ppuy, unitsX, unitsY, x, y );
514 
515  double scale = GetParent()->GetScreen()->GetScalingFactor();
516 
518  center.x += KiROUND( (double) ( x - tmpX ) / scale );
519  center.y += KiROUND( (double) ( y - tmpY ) / scale );
520  GetParent()->SetScrollCenterPosition( center );
521 
522  Scroll( x, y );
523  event.Skip();
524 }
525 
526 
527 void EDA_DRAW_PANEL::SetClipBox( wxDC& aDC, const wxRect* aRect )
528 {
529  wxRect clipBox;
530 
531  // Use the entire visible device area if no clip area was defined.
532  if( aRect == NULL )
533  {
534  BASE_SCREEN* Screen = GetScreen();
535 
536  if( !Screen )
537  return;
538 
539  Screen->m_StartVisu = CalcUnscrolledPosition( wxPoint( 0, 0 ) );
540  clipBox.SetSize( GetClientSize() );
541 
542  int scrollX, scrollY;
543 
544  double scalar = Screen->GetScalingFactor();
545  scrollX = KiROUND( Screen->GetGridSize().x * scalar );
546  scrollY = KiROUND( Screen->GetGridSize().y * scalar );
547 
548  m_scrollIncrementX = std::max( GetClientSize().x / 8, scrollX );
549  m_scrollIncrementY = std::max( GetClientSize().y / 8, scrollY );
550  Screen->m_ScrollbarPos.x = GetScrollPos( wxHORIZONTAL );
551  Screen->m_ScrollbarPos.y = GetScrollPos( wxVERTICAL );
552  }
553  else
554  {
555  clipBox = *aRect;
556  }
557 
558  // Pad clip box in device units.
559  clipBox.Inflate( CLIP_BOX_PADDING );
560 
561  // Convert from device units to drawing units.
562  m_ClipBox.SetOrigin( wxPoint( aDC.DeviceToLogicalX( clipBox.x ),
563  aDC.DeviceToLogicalY( clipBox.y ) ) );
564  m_ClipBox.SetSize( wxSize( aDC.DeviceToLogicalXRel( clipBox.width ),
565  aDC.DeviceToLogicalYRel( clipBox.height ) ) );
566 
567  wxLogTrace( kicadTraceCoords,
568  wxT( "Device clip box=(%d, %d, %d, %d), Logical clip box=(%d, %d, %d, %d)" ),
569  clipBox.x, clipBox.y, clipBox.width, clipBox.height,
571 }
572 
573 
575 {
576  GRSetDrawMode( DC, GR_COPY );
577 
578  COLOR4D bgColor = GetParent()->GetDrawBgColor();
579 
580  GRSFilledRect( NULL, DC, m_ClipBox.GetX(), m_ClipBox.GetY(),
582  0, bgColor, bgColor );
583 
584  // Set to one (1) to draw bounding box validate bounding box calculation.
585 #if DEBUG_SHOW_CLIP_RECT
586  EDA_RECT bBox = m_ClipBox;
587  GRRect( NULL, DC, bBox.GetOrigin().x, bBox.GetOrigin().y,
588  bBox.GetEnd().x, bBox.GetEnd().y, 0, LIGHTMAGENTA );
589 #endif
590 }
591 
592 
594 {
595  wxScrolledWindow::DoPrepareDC( dc );
596 
597  if( GetScreen() != NULL )
598  {
599  double scale = GetScreen()->GetScalingFactor();
600  dc.SetUserScale( scale, scale );
601 
602  wxPoint pt = GetScreen()->m_DrawOrg;
603  dc.SetLogicalOrigin( pt.x, pt.y );
604  }
605 
606  SetClipBox( dc ); // Reset the clip box to the entire screen.
607  GRResetPenAndBrush( &dc );
608  dc.SetBackgroundMode( wxTRANSPARENT );
609 }
610 
611 
612 void EDA_DRAW_PANEL::OnPaint( wxPaintEvent& event )
613 {
614  if( GetScreen() == NULL )
615  {
616  event.Skip();
617  return;
618  }
619 
620  INSTALL_PAINTDC( paintDC, this );
621 
622  wxRect region = GetUpdateRegion().GetBox();
623  SetClipBox( paintDC, &region );
624  ReDraw( &paintDC, true );
625 }
626 
627 
628 void EDA_DRAW_PANEL::ReDraw( wxDC* DC, bool erasebg )
629 {
630  BASE_SCREEN* Screen = GetScreen();
631 
632  if( Screen == NULL )
633  return;
634 
635  COLOR4D bgColor = GetParent()->GetDrawBgColor();
636 
637  // TODO(JE): Is this correct?
638  if( bgColor.GetBrightness() > 0.5 )
639  {
640  g_XorMode = GR_NXOR;
642  }
643  else
644  {
645  g_XorMode = GR_XOR;
647  }
648 
649  GRResetPenAndBrush( DC );
650 
651  DC->SetBackground( wxBrush( bgColor.ToColour() ) );
652  DC->SetBackgroundMode( wxSOLID );
653 
654  if( erasebg )
655  EraseScreen( DC );
656 
657  GetParent()->RedrawActiveWindow( DC, erasebg );
658 
659  // Verfies that the clipping is working correctly. If these two sets of numbers are
660  // not the same or really close. The clipping algorithms are broken.
661  wxLogTrace( kicadTraceCoords,
662  wxT( "Clip box: (%d, %d, %d, %d), Draw extents (%d, %d, %d, %d)" ),
664  DC->MinX(), DC->MinY(), DC->MaxX(), DC->MaxY() );
665 }
666 
667 
669 {
670  m_enableMousewheelPan = aEnable;
671 
672  if( GetParent()->IsGalCanvasActive() )
674 }
675 
677 {
678  m_enableAutoPan = aEnable;
679 
680  if( GetParent()->IsGalCanvasActive() )
682 }
683 
684 
686 {
687  m_enableZoomNoCenter = aEnable;
688 
689  if( GetParent()->IsGalCanvasActive() )
691 }
692 
693 
695 {
696  GRSetDrawMode( DC, GR_COPY );
697 
698  if( GetParent()->IsGridVisible() )
699  DrawGrid( DC );
700 
701  // Draw axis
702  if( GetParent()->m_showAxis )
703  {
704  COLOR4D axis_color = COLOR4D( BLUE );
705  wxSize pageSize = GetParent()->GetPageSizeIU();
706 
707  // Draw the Y axis
708  GRLine( &m_ClipBox, DC, 0, -pageSize.y, 0, pageSize.y, 0, axis_color );
709 
710  // Draw the X axis
711  GRLine( &m_ClipBox, DC, -pageSize.x, 0, pageSize.x, 0, 0, axis_color );
712  }
713 
714  if( GetParent()->m_showOriginAxis )
715  DrawAuxiliaryAxis( DC, GR_COPY );
716 
717  if( GetParent()->m_showGridAxis )
718  DrawGridAxis( DC, GR_COPY, GetParent()->GetGridOrigin() );
719 }
720 
721 
722 void EDA_DRAW_PANEL::DrawGrid( wxDC* aDC )
723 {
724  #define MIN_GRID_SIZE 10 // min grid size in pixels to allow drawing
725  BASE_SCREEN* screen = GetScreen();
726  wxRealPoint gridSize;
727  wxSize screenSize;
728  wxPoint org;
729  wxRealPoint screenGridSize;
730 
731  /* The grid must be visible. this is possible only is grid value
732  * and zoom value are sufficient
733  */
734  gridSize = screen->GetGridSize();
735  screen->m_StartVisu = CalcUnscrolledPosition( wxPoint( 0, 0 ) );
736  screenSize = GetClientSize();
737 
738  screenGridSize.x = aDC->LogicalToDeviceXRel( KiROUND( gridSize.x ) );
739  screenGridSize.y = aDC->LogicalToDeviceYRel( KiROUND( gridSize.y ) );
740 
741  org = m_ClipBox.GetPosition();
742 
743  if( screenGridSize.x < MIN_GRID_SIZE || screenGridSize.y < MIN_GRID_SIZE )
744  {
745  screenGridSize.x *= 2.0;
746  screenGridSize.y *= 2.0;
747  gridSize.x *= 2.0;
748  gridSize.y *= 2.0;
749  }
750 
751  if( screenGridSize.x < MIN_GRID_SIZE || screenGridSize.y < MIN_GRID_SIZE )
752  return;
753 
754  org = GetParent()->GetNearestGridPosition( org, &gridSize );
755 
756  // Setting the nearest grid position can select grid points outside the clip box.
757  // Incrementing the start point by one grid step should prevent drawing grid points
758  // outside the clip box.
759  if( org.x < m_ClipBox.GetX() )
760  org.x += KiROUND( gridSize.x );
761 
762  if( org.y < m_ClipBox.GetY() )
763  org.y += KiROUND( gridSize.y );
764 
765  // Use a pixel based draw to display grid. There are a lot of calls, so the cost is
766  // high and grid is slowly drawn on some platforms. Another way using blit transfert was used,
767  // a long time ago, but it did not give very good results.
768  // The better way is highly dependent on the platform and the graphic card.
769  int xpos;
770  double right = ( double ) m_ClipBox.GetRight();
771  double bottom = ( double ) m_ClipBox.GetBottom();
772 
773 #if defined( USE_WX_GRAPHICS_CONTEXT )
774  wxGCDC *gcdc = wxDynamicCast( aDC, wxGCDC );
775 
776  if( gcdc )
777  {
778  // Much faster grid drawing on systems using wxGraphicsContext
779  wxGraphicsContext *gc = gcdc->GetGraphicsContext();
780 
781  // Grid point size
782  const int gsz = 1;
783  const double w = aDC->DeviceToLogicalXRel( gsz );
784  const double h = aDC->DeviceToLogicalYRel( gsz );
785 
786  // Use our own pen
787  wxPen pen( GetParent()->GetGridColor().ToColour(), h );
788  pen.SetCap( wxCAP_BUTT );
789  gc->SetPen( pen );
790 
791  // draw grid
792  wxGraphicsPath path = gc->CreatePath();
793  for( double x = (double) org.x - w/2.0; x <= right - w/2.0; x += gridSize.x )
794  {
795  for( double y = (double) org.y; y <= bottom; y += gridSize.y )
796  {
797  path.MoveToPoint( x, y );
798  path.AddLineToPoint( x+w, y );
799  }
800  }
801  gc->StrokePath( path );
802  }
803  else
804 #endif
805  {
806  GRSetColorPen( aDC, GetParent()->GetGridColor() );
807 
808  for( double x = (double) org.x; x <= right; x += gridSize.x )
809  {
810  xpos = KiROUND( x );
811 
812  for( double y = (double) org.y; y <= bottom; y += gridSize.y )
813  {
814  aDC->DrawPoint( xpos, KiROUND( y ) );
815  }
816  }
817  }
818 }
819 
820 // Set to 1 to draw auxirilary axis as lines, 0 to draw as target (circle with cross)
821 #define DRAW_AXIS_AS_LINES 0
822 // Size in pixels of the target shape
823 #define AXIS_SIZE_IN_PIXELS 15
824 
825 void EDA_DRAW_PANEL::DrawAuxiliaryAxis( wxDC* aDC, GR_DRAWMODE aDrawMode )
826 {
827  wxPoint origin = GetParent()->GetAuxOrigin();
828 
829  if( origin == wxPoint( 0, 0 ) )
830  return;
831 
832  COLOR4D color = COLOR4D( RED );
833 
834  GRSetDrawMode( aDC, aDrawMode );
835 
836 #if DRAW_AXIS_AS_LINES
837  wxSize pageSize = GetParent()->GetPageSizeIU();
838  // Draw the Y axis
839  GRLine( &m_ClipBox, aDC, origin.x, -pageSize.y,
840  origin.x, pageSize.y, 0, color );
841 
842  // Draw the X axis
843  GRLine( &m_ClipBox, aDC, -pageSize.x, origin.y,
844  pageSize.x, origin.y, 0, color );
845 #else
846  int radius = aDC->DeviceToLogicalXRel( AXIS_SIZE_IN_PIXELS );
847  int linewidth = aDC->DeviceToLogicalXRel( 1 );
848 
849  GRSetColorPen( aDC, color, linewidth );
850 
851  GRLine( &m_ClipBox, aDC, origin.x, origin.y-radius,
852  origin.x, origin.y+radius, 0, color );
853 
854  // Draw the + shape
855  GRLine( &m_ClipBox, aDC, origin.x-radius, origin.y,
856  origin.x+radius, origin.y, 0, color );
857 
858  GRCircle( &m_ClipBox, aDC, origin, radius, linewidth, color );
859 #endif
860 }
861 
862 
863 void EDA_DRAW_PANEL::DrawGridAxis( wxDC* aDC, GR_DRAWMODE aDrawMode, const wxPoint& aGridOrigin )
864 {
865  if( !GetParent()->m_showGridAxis || ( !aGridOrigin.x && !aGridOrigin.y ) )
866  return;
867 
869 
870  GRSetDrawMode( aDC, aDrawMode );
871 
872 #if DRAW_AXIS_AS_LINES
873  wxSize pageSize = GetParent()->GetPageSizeIU();
874  // Draw the Y axis
875  GRLine( &m_ClipBox, aDC, aGridOrigin.x, -pageSize.y,
876  aGridOrigin.x, pageSize.y, 0, color );
877 
878  // Draw the X axis
879  GRLine( &m_ClipBox, aDC, -pageSize.x, aGridOrigin.y,
880  pageSize.x, aGridOrigin.y, 0, color );
881 #else
882  int radius = aDC->DeviceToLogicalXRel( AXIS_SIZE_IN_PIXELS );
883  int linewidth = aDC->DeviceToLogicalXRel( 1 );
884 
885  GRSetColorPen( aDC, GetParent()->GetGridColor(), linewidth );
886 
887  GRLine( &m_ClipBox, aDC, aGridOrigin.x-radius, aGridOrigin.y-radius,
888  aGridOrigin.x+radius, aGridOrigin.y+radius, 0, color );
889 
890  // Draw the X shape
891  GRLine( &m_ClipBox, aDC, aGridOrigin.x+radius, aGridOrigin.y-radius,
892  aGridOrigin.x-radius, aGridOrigin.y+radius, 0, color );
893 
894  GRCircle( &m_ClipBox, aDC, aGridOrigin, radius, linewidth, color );
895 #endif
896 }
897 
898 
899 bool EDA_DRAW_PANEL::OnRightClick( wxMouseEvent& event )
900 {
901  wxPoint pos;
902  wxMenu MasterMenu;
903 
904  INSTALL_UNBUFFERED_DC( dc, this );
905 
906  pos = event.GetLogicalPosition( dc );
907 
908  if( !GetParent()->OnRightClick( pos, &MasterMenu ) )
909  return false;
910 
911  GetParent()->AddMenuZoomAndGrid( &MasterMenu );
912 
913  pos = event.GetPosition();
914  m_ignoreMouseEvents = true;
915  PopupMenu( &MasterMenu, pos );
916 
917  // The ZoomAndGrid menu is only invoked over empty space so there's no point in warping
918  // the cursor back to the crosshair, and it's very annoying if one clicked out of the menu.
919 
920  m_ignoreMouseEvents = false;
921 
922  return true;
923 }
924 
925 
926 void EDA_DRAW_PANEL::OnMouseEntering( wxMouseEvent& aEvent )
927 {
928  // This is an ugly hack that fixes some cross hair display bugs when the mouse leaves the
929  // canvas area during middle button mouse panning.
930  if( m_cursorLevel != 0 )
931  m_cursorLevel = 0;
932 
933  aEvent.Skip();
934 }
935 
936 
937 void EDA_DRAW_PANEL::OnMouseLeaving( wxMouseEvent& event )
938 {
939  if( m_mouseCaptureCallback == NULL ) // No command in progress.
940  m_requestAutoPan = false;
941 
943  return;
944 
945  // Auto pan when mouse has left the client window
946  // Ensure the cross_hair position is updated,
947  // because it will be used to center the screen.
948  // We use a position inside the client window
949  wxRect area( wxPoint( 0, 0 ), GetClientSize() );
950  wxPoint cross_hair_pos = event.GetPosition();
951 
952  // Certain window managers (e.g. awesome wm) incorrectly trigger "on leave" event,
953  // therefore test if the cursor has really left the panel area
954  if( !area.Contains( cross_hair_pos ) )
955  {
956  INSTALL_UNBUFFERED_DC( dc, this );
957  cross_hair_pos.x = dc.DeviceToLogicalX( cross_hair_pos.x );
958  cross_hair_pos.y = dc.DeviceToLogicalY( cross_hair_pos.y );
959 
960  GetParent()->SetCrossHairPosition( cross_hair_pos );
961 
962  wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED, ID_POPUP_ZOOM_CENTER );
963  cmd.SetEventObject( this );
964  GetEventHandler()->ProcessEvent( cmd );
965  }
966 
967  event.Skip();
968 }
969 
970 
971 void EDA_DRAW_PANEL::OnMouseWheel( wxMouseEvent& event )
972 {
973  if( m_ignoreMouseEvents )
974  return;
975 
976  wxRect rect = wxRect( wxPoint( 0, 0 ), GetClientSize() );
977 
978  // Ignore scroll events if the cursor is outside the drawing area.
979  if( event.GetWheelRotation() == 0 || !GetParent()->IsEnabled()
980  || !rect.Contains( event.GetPosition() ) )
981  {
982  wxLogTrace( kicadTraceCoords,
983  wxT( "OnMouseWheel() position(%d, %d) rectangle(%d, %d, %d, %d)" ),
984  event.GetPosition().x, event.GetPosition().y,
985  rect.x, rect.y, rect.width, rect.height );
986  event.Skip();
987  return;
988  }
989 
990  INSTALL_UNBUFFERED_DC( dc, this );
991  GetParent()->SetCrossHairPosition( event.GetLogicalPosition( dc ) );
992 
993  wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED );
994  cmd.SetEventObject( this );
995 
996  bool offCenterReq = event.ControlDown() && event.ShiftDown();
997  offCenterReq = offCenterReq || m_enableZoomNoCenter;
998 
999  int axis = event.GetWheelAxis();
1000  int wheelRotation = event.GetWheelRotation();
1001 
1002  if( m_enableMousewheelPan )
1003  {
1004  // MousewheelPAN + Ctrl = zooming
1005  if( event.ControlDown() && !event.ShiftDown() )
1006  {
1007  if( wheelRotation > 0 )
1008  cmd.SetId( ID_POPUP_ZOOM_IN );
1009  else if( wheelRotation < 0)
1010  cmd.SetId( ID_POPUP_ZOOM_OUT );
1011  }
1012  // MousewheelPAN + Shift = horizontal scrolling
1013  // Without modifiers MousewheelPAN - just pan
1014  else
1015  {
1016  if( event.ShiftDown() && !event.ControlDown() )
1017  axis = wxMOUSE_WHEEL_HORIZONTAL;
1018 
1019  wxPoint newStart = GetViewStart();
1021  double scale = GetParent()->GetScreen()->GetScalingFactor();
1022 
1023  if( axis == wxMOUSE_WHEEL_HORIZONTAL )
1024  {
1025  newStart.x += wheelRotation;
1026  center.x += KiROUND( (double) wheelRotation / scale );
1027  }
1028  else
1029  {
1030  newStart.y -= wheelRotation;
1031  center.y -= KiROUND( (double) wheelRotation / scale );
1032  }
1033  Scroll( newStart );
1034 
1035  GetParent()->SetScrollCenterPosition( center );
1036  GetParent()->SetCrossHairPosition( center, true );
1037  GetParent()->RedrawScreen( center, false );
1038  }
1039  }
1040  else if( wheelRotation > 0 )
1041  {
1042  if( event.ShiftDown() && !event.ControlDown() )
1043  cmd.SetId( ID_PAN_UP );
1044  else if( event.ControlDown() && !event.ShiftDown() )
1045  cmd.SetId( ID_PAN_LEFT );
1046  else if( offCenterReq )
1047  cmd.SetId( ID_OFFCENTER_ZOOM_IN );
1048  else
1049  cmd.SetId( ID_POPUP_ZOOM_IN );
1050  }
1051  else if( wheelRotation < 0 )
1052  {
1053  if( event.ShiftDown() && !event.ControlDown() )
1054  cmd.SetId( ID_PAN_DOWN );
1055  else if( event.ControlDown() && !event.ShiftDown() )
1056  cmd.SetId( ID_PAN_RIGHT );
1057  else if( offCenterReq )
1058  cmd.SetId( ID_OFFCENTER_ZOOM_OUT );
1059  else
1060  cmd.SetId( ID_POPUP_ZOOM_OUT );
1061  }
1062 
1063  if( cmd.GetId() )
1064  GetEventHandler()->ProcessEvent( cmd );
1065  event.Skip();
1066 }
1067 
1068 
1069 #if wxCHECK_VERSION( 3, 1, 0 ) || defined( USE_OSX_MAGNIFY_EVENT )
1070 void EDA_DRAW_PANEL::OnMagnify( wxMouseEvent& event )
1071 {
1072  // Scale the panel around our cursor position.
1073  bool warpCursor = false;
1074 
1075  wxPoint cursorPosition = GetParent()->GetCursorPosition( false );
1076  wxPoint centerPosition = GetParent()->GetScrollCenterPosition();
1077  wxPoint vector = centerPosition - cursorPosition;
1078 
1079  double magnification = ( event.GetMagnification() + 1.0f );
1080  double scaleFactor = GetZoom() / magnification;
1081 
1082  // Scale the vector between the cursor and center point
1083  vector.x /= magnification;
1084  vector.y /= magnification;
1085 
1086  SetZoom(scaleFactor);
1087 
1088  // Recenter the window along our scaled vector such that the
1089  // cursor becomes our scale axis, remaining fixed on screen
1090  GetParent()->RedrawScreen( cursorPosition + vector, warpCursor );
1091 
1092  event.Skip();
1093 }
1094 #endif
1095 
1096 
1097 void EDA_DRAW_PANEL::OnMouseEvent( wxMouseEvent& event )
1098 {
1099  int localbutt = 0;
1100  BASE_SCREEN* screen = GetScreen();
1101 
1102  if( !screen )
1103  return;
1104 
1105  /* Adjust value to filter mouse displacement before consider the drag
1106  * mouse is really a drag command, not just a movement while click
1107  */
1108 #define MIN_DRAG_COUNT_FOR_START_BLOCK_COMMAND 5
1109 
1110  if( event.Leaving() )
1111  m_canStartBlock = -1;
1112 
1113  if( !IsMouseCaptured() ) // No mouse capture in progress.
1114  m_requestAutoPan = false;
1115 
1116  if( GetParent()->IsActive() )
1117  SetFocus();
1118  else
1119  return;
1120 
1121  if( !event.IsButton() && !event.Moving() && !event.Dragging() )
1122  return;
1123 
1124  if( event.RightDown() )
1125  {
1126  OnRightClick( event );
1127  return;
1128  }
1129 
1130  if( m_ignoreMouseEvents )
1131  return;
1132 
1133  if( event.LeftDown() )
1134  localbutt = GR_M_LEFT_DOWN;
1135 
1136  if( event.ButtonDClick( 1 ) )
1137  localbutt = GR_M_LEFT_DOWN | GR_M_DCLICK;
1138 
1139  if( event.MiddleDown() )
1140  localbutt = GR_M_MIDDLE_DOWN;
1141 
1142  INSTALL_UNBUFFERED_DC( DC, this );
1143  DC.SetBackground( *wxBLACK_BRUSH );
1144 
1145  // Compute the cursor position in drawing (logical) units.
1146  GetParent()->SetMousePosition( event.GetLogicalPosition( DC ) );
1147 
1148  int kbstat = 0;
1149 
1150  if( event.ShiftDown() )
1151  kbstat |= GR_KB_SHIFT;
1152 
1153  if( event.ControlDown() )
1154  kbstat |= GR_KB_CTRL;
1155 
1156  if( event.AltDown() )
1157  kbstat |= GR_KB_ALT;
1158 
1159  // Calling Double Click and Click functions :
1160  if( localbutt == (int) ( GR_M_LEFT_DOWN | GR_M_DCLICK ) )
1161  {
1162  if( m_ClickTimer )
1163  {
1164  m_ClickTimer->Stop();
1165  wxDELETE( m_ClickTimer );
1166  }
1167  GetParent()->OnLeftDClick( &DC, GetParent()->RefPos( true ) );
1168 
1169  // inhibit a response to the mouse left button release,
1170  // because we have a double click, and we do not want a new
1171  // OnLeftClick command at end of this Double Click
1173  }
1174  else if( event.LeftUp() )
1175  {
1176  // A block command is in progress: a left up is the end of block
1177  // or this is the end of a double click, already seen
1178  // Note also m_ignoreNextLeftButtonRelease can be set by
1179  // the call to OnLeftClick(), so do not change it after calling OnLeftClick
1180  bool ignoreEvt = m_ignoreNextLeftButtonRelease;
1182 
1183  if( screen->m_BlockLocate.GetState() == STATE_NO_BLOCK && !ignoreEvt )
1184  {
1185  EDA_ITEM* item = screen->GetCurItem();
1186  m_CursorClickPos = GetParent()->RefPos( true );
1187 
1188  // If we have an item already selected, or we are using a tool,
1189  // we won't use the disambiguation menu so process the click immediately
1190  if( ( item && item->GetFlags() ) || GetParent()->GetToolId() != ID_NO_TOOL_SELECTED )
1192  else
1193  {
1194  wxDELETE( m_ClickTimer );
1195  m_ClickTimer = new wxTimer(this, ID_MOUSE_DOUBLECLICK);
1196  m_ClickTimer->StartOnce( m_doubleClickInterval );
1197  }
1198  }
1199 
1200  }
1201  else if( !event.LeftIsDown() )
1202  {
1203  /* be sure there is a response to a left button release command
1204  * even when a LeftUp event is not seen. This happens when a
1205  * double click opens a dialog box, and the release mouse button
1206  * is made when the dialog box is opened.
1207  */
1209  }
1210 
1211  if( event.ButtonDown( wxMOUSE_BTN_MIDDLE ) )
1212  {
1214  m_PanStartEventPosition = event.GetPosition();
1215 
1216  INSTALL_UNBUFFERED_DC( dc, this );
1217  CrossHairOff( &dc );
1218  SetCursor( wxCURSOR_SIZING );
1219  }
1220 
1221  if( event.ButtonUp( wxMOUSE_BTN_MIDDLE ) )
1222  {
1223  INSTALL_UNBUFFERED_DC( dc, this );
1224  CrossHairOn( &dc );
1225  SetCursor( (wxStockCursor) m_currentCursor );
1226  }
1227 
1228  if( event.MiddleIsDown() )
1229  {
1230  wxPoint currentPosition = event.GetPosition();
1231 
1232  double scale = GetParent()->GetScreen()->GetScalingFactor();
1233  int x = m_PanStartCenter.x +
1234  KiROUND( (double) ( m_PanStartEventPosition.x - currentPosition.x ) / scale );
1235  int y = m_PanStartCenter.y +
1236  KiROUND( (double) ( m_PanStartEventPosition.y - currentPosition.y ) / scale );
1237 
1238  GetParent()->RedrawScreen( wxPoint( x, y ), false );
1239  }
1240 
1241  // Calling the general function on mouse changes (and pseudo key commands)
1242  GetParent()->GeneralControl( &DC, event.GetLogicalPosition( DC ), 0 );
1243 
1244  /*******************************/
1245  /* Control of block commands : */
1246  /*******************************/
1247 
1248  // Command block can't start if mouse is dragging a new panel
1249  static EDA_DRAW_PANEL* lastPanel;
1250  if( lastPanel != this )
1251  {
1252  m_minDragEventCount = 0;
1253  m_canStartBlock = -1;
1254  }
1255 
1256  /* A new command block can start after a release buttons
1257  * and if the drag is enough
1258  * This is to avoid a false start block when a dialog box is dismissed,
1259  * or when changing panels in hierarchy navigation
1260  * or when clicking while and moving mouse
1261  */
1262  if( !event.LeftIsDown() && !event.MiddleIsDown() )
1263  {
1264  m_minDragEventCount = 0;
1265  m_canStartBlock = 0;
1266 
1267  /* Remember the last cursor position when a drag mouse starts
1268  * this is the last position ** before ** clicking a button
1269  * this is useful to start a block command from the point where the
1270  * mouse was clicked first
1271  * (a filter creates a delay for the real block command start, and
1272  * we must remember this point)
1273  */
1275  }
1276 
1277  if( m_enableBlockCommands && !(localbutt & GR_M_DCLICK) )
1278  {
1279  if( !screen->IsBlockActive() )
1280  {
1282  }
1283 
1284  if( event.LeftDown() )
1285  {
1286  if( screen->m_BlockLocate.GetState() == STATE_BLOCK_MOVE )
1287  {
1288  m_requestAutoPan = false;
1289  GetParent()->HandleBlockPlace( &DC );
1291  }
1292  }
1293  else if( ( m_canStartBlock >= 0 ) && event.LeftIsDown() && !IsMouseCaptured() )
1294  {
1295  // Mouse is dragging: if no block in progress, start a block command.
1296  if( screen->m_BlockLocate.GetState() == STATE_NO_BLOCK )
1297  {
1298  // Start a block command
1299  int cmd_type = kbstat;
1300 
1301  // A block command is started if the drag is enough. A small
1302  // drag is ignored (it is certainly a little mouse move when
1303  // clicking) not really a drag mouse
1306  else
1307  {
1308  auto cmd = (GetParent()->GetToolId() == ID_ZOOM_SELECTION) ? BLOCK_ZOOM : 0;
1309 
1310  if( !GetParent()->HandleBlockBegin( &DC, cmd_type, m_CursorStartPos, cmd ) )
1311  {
1312  // should not occur: error
1314  wxT( "EDA_DRAW_PANEL::OnMouseEvent() Block Error" ) );
1315  }
1316  else
1317  {
1318  m_requestAutoPan = true;
1319  SetCursor( wxCURSOR_SIZING );
1320  }
1321  }
1322  }
1323  }
1324 
1325  if( event.ButtonUp( wxMOUSE_BTN_LEFT ) )
1326  {
1327  /* Release the mouse button: end of block.
1328  * The command can finish (DELETE) or have a next command (MOVE,
1329  * COPY). However the block command is canceled if the block
1330  * size is small because a block command filtering is already
1331  * made, this case happens, but only when the on grid cursor has
1332  * not moved.
1333  */
1334  #define BLOCK_MINSIZE_LIMIT 1
1335  bool BlockIsSmall =
1337  && ( std::abs( screen->m_BlockLocate.GetHeight() ) < BLOCK_MINSIZE_LIMIT );
1338 
1339  if( (screen->m_BlockLocate.GetState() != STATE_NO_BLOCK) && BlockIsSmall )
1340  {
1342  {
1343  m_endMouseCaptureCallback( this, &DC );
1344  m_requestAutoPan = false;
1345  }
1346 
1347  SetCursor( (wxStockCursor) m_currentCursor );
1348  }
1349  else if( screen->m_BlockLocate.GetState() == STATE_BLOCK_END )
1350  {
1351  m_requestAutoPan = false;
1352  GetParent()->HandleBlockEnd( &DC );
1353  SetCursor( (wxStockCursor) m_currentCursor );
1354  if( screen->m_BlockLocate.GetState() == STATE_BLOCK_MOVE )
1355  {
1356  m_requestAutoPan = true;
1357  SetCursor( wxCURSOR_HAND );
1358  }
1359  }
1360  }
1361  }
1362 
1363  // End of block command on a double click
1364  // To avoid an unwanted block move command if the mouse is moved while double clicking
1365  if( localbutt == (int) ( GR_M_LEFT_DOWN | GR_M_DCLICK ) )
1366  {
1367  if( !screen->IsBlockActive() && IsMouseCaptured() )
1368  {
1369  m_endMouseCaptureCallback( this, &DC );
1370  }
1371  }
1372 
1373  lastPanel = this;
1374 
1375 #ifdef WXGTK3
1376  // Screen has to be updated on every operation, otherwise the cursor leaves a trail (when xor
1377  // operation is changed to copy) or is not updated at all.
1378  Refresh();
1379 #endif
1380 }
1381 
1382 
1383 void EDA_DRAW_PANEL::OnCharHook( wxKeyEvent& event )
1384 {
1385  wxLogTrace( kicadTraceKeyEvent, "EDA_DRAW_PANEL::OnCharHook %s", dump( event ) );
1386  event.Skip();
1387 }
1388 
1389 
1390 void EDA_DRAW_PANEL::OnKeyEvent( wxKeyEvent& event )
1391 {
1392  int localkey;
1393  wxPoint pos;
1394 
1395  wxLogTrace( kicadTraceKeyEvent, "EDA_DRAW_PANEL::OnKeyEvent %s", dump( event ) );
1396 
1397  localkey = event.GetKeyCode();
1398 
1399  switch( localkey )
1400  {
1401  default:
1402  break;
1403 
1404  case WXK_ESCAPE:
1405  m_abortRequest = true;
1406 
1407  if( IsMouseCaptured() )
1408  EndMouseCapture();
1409  else
1411  break;
1412  }
1413 
1414  /* Normalize keys code to easily handle keys from Ctrl+A to Ctrl+Z
1415  * They have an ascii code from 1 to 27 remapped
1416  * to GR_KB_CTRL + 'A' to GR_KB_CTRL + 'Z'
1417  */
1418  if( event.ControlDown() && localkey >= WXK_CONTROL_A && localkey <= WXK_CONTROL_Z )
1419  localkey += 'A' - 1;
1420 
1421  /* Disallow shift for keys that have two keycodes on them (e.g. number and
1422  * punctuation keys) leaving only the "letter keys" of A-Z.
1423  * Then, you can have, e.g. Ctrl-5 and Ctrl-% (GB layout)
1424  * and Ctrl-( and Ctrl-5 (FR layout).
1425  * Otherwise, you'd have to have to say Ctrl-Shift-5 on a FR layout
1426  */
1427  bool keyIsLetter = ( localkey >= 'A' && localkey <= 'Z' ) ||
1428  ( localkey >= 'a' && localkey <= 'z' );
1429 
1430  if( event.ShiftDown() && ( keyIsLetter || localkey > 256 ) )
1431  localkey |= GR_KB_SHIFT;
1432 
1433  if( event.ControlDown() )
1434  localkey |= GR_KB_CTRL;
1435 
1436  if( event.AltDown() )
1437  localkey |= GR_KB_ALT;
1438 
1439  INSTALL_UNBUFFERED_DC( DC, this );
1440 
1441  // Some key commands use the current mouse position: refresh it.
1442  pos = wxGetMousePosition() - GetScreenPosition();
1443 
1444  // Compute the cursor position in drawing units. Also known as logical units to wxDC.
1445  pos = wxPoint( DC.DeviceToLogicalX( pos.x ), DC.DeviceToLogicalY( pos.y ) );
1446 
1447  GetParent()->SetMousePosition( pos );
1448 
1449  if( !GetParent()->GeneralControl( &DC, pos, localkey ) )
1450  event.Skip();
1451 }
1452 
1453 
1454 void EDA_DRAW_PANEL::OnPan( wxCommandEvent& event )
1455 {
1456  int x, y;
1457  int ppux, ppuy;
1458  int unitsX, unitsY;
1459  int maxX, maxY;
1460  int tmpX, tmpY;
1461 
1462  GetViewStart( &x, &y );
1463  GetScrollPixelsPerUnit( &ppux, &ppuy );
1464  GetVirtualSize( &unitsX, &unitsY );
1465  tmpX = x;
1466  tmpY = y;
1467  maxX = unitsX;
1468  maxY = unitsY;
1469  unitsX /= ppux;
1470  unitsY /= ppuy;
1471 
1472  wxLogTrace( kicadTraceCoords,
1473  wxT( "Scroll center position before pan: (%d, %d)" ), tmpX, tmpY );
1474 
1475  switch( event.GetId() )
1476  {
1477  case ID_PAN_UP:
1478  y -= m_scrollIncrementY;
1479  break;
1480 
1481  case ID_PAN_DOWN:
1482  y += m_scrollIncrementY;
1483  break;
1484 
1485  case ID_PAN_LEFT:
1486  x -= m_scrollIncrementX;
1487  break;
1488 
1489  case ID_PAN_RIGHT:
1490  x += m_scrollIncrementX;
1491  break;
1492 
1493  default:
1494  wxLogDebug( wxT( "Unknown ID %d in EDA_DRAW_PANEL::OnPan()." ), event.GetId() );
1495  }
1496 
1497  bool updateCenterScrollPos = true;
1498 
1499  if( x < 0 )
1500  {
1501  x = 0;
1502  updateCenterScrollPos = false;
1503  }
1504 
1505  if( y < 0 )
1506  {
1507  y = 0;
1508  updateCenterScrollPos = false;
1509  }
1510 
1511  if( x > maxX )
1512  {
1513  x = maxX;
1514  updateCenterScrollPos = false;
1515  }
1516 
1517  if( y > maxY )
1518  {
1519  y = maxY;
1520  updateCenterScrollPos = false;
1521  }
1522 
1523  // Don't update the scroll position beyond the scroll limits.
1524  if( updateCenterScrollPos )
1525  {
1526  double scale = GetParent()->GetScreen()->GetScalingFactor();
1527 
1529  center.x += KiROUND( (double) ( x - tmpX ) / scale );
1530  center.y += KiROUND( (double) ( y - tmpY ) / scale );
1531  GetParent()->SetScrollCenterPosition( center );
1532 
1533  wxLogTrace( kicadTraceCoords,
1534  wxT( "Scroll center position after pan: (%d, %d)" ), center.x, center.y );
1535  }
1536 
1537  Scroll( x/ppux, y/ppuy );
1538 }
1539 
1540 
1541 void EDA_DRAW_PANEL::EndMouseCapture( int id, int cursor, const wxString& title,
1542  bool aCallEndFunc )
1543 {
1544  if( m_mouseCaptureCallback && m_endMouseCaptureCallback && aCallEndFunc )
1545  {
1546  INSTALL_UNBUFFERED_DC( dc, this );
1547  m_endMouseCaptureCallback( this, &dc );
1548  }
1549 
1550  m_mouseCaptureCallback = NULL;
1552  m_requestAutoPan = false;
1553 
1554  if( id != -1 && cursor != -1 )
1555  {
1556  wxASSERT( cursor > wxCURSOR_NONE && cursor < wxCURSOR_MAX );
1557  GetParent()->SetToolID( id, cursor, title );
1558  }
1559 }
1560 
1561 
1562 void EDA_DRAW_PANEL::CallMouseCapture( wxDC* aDC, const wxPoint& aPosition, bool aErase )
1563 {
1564  wxCHECK_RET( aDC != NULL, wxT( "Invalid device context." ) );
1565  wxCHECK_RET( m_mouseCaptureCallback != NULL, wxT( "Mouse capture callback not set." ) );
1566 
1567  m_mouseCaptureCallback( this, aDC, aPosition, aErase );
1568 }
1569 
1570 
1572 {
1573  wxCHECK_RET( aDC != NULL, wxT( "Invalid device context." ) );
1574 
1575  // CallEndMouseCapture is sometimes called with m_endMouseCaptureCallback == NULL
1576  // for instance after an ABORT in block paste.
1578  m_endMouseCaptureCallback( this, aDC );
1579 }
Definition: colors.h:57
GR_DRAWMODE g_XorMode
Definition: gr_basic.cpp:73
#define GR_M_DCLICK
Definition: gr_basic.h:77
void GRResetPenAndBrush(wxDC *DC)
Definition: gr_basic.cpp:218
bool m_abortRequest
Flag used to abort long commands.
double GetZoom()
Definition: draw_panel.cpp:282
int m_canStartBlock
useful to avoid false start block in certain cases (like switch from a sheet to another sheet >= 0 (o...
STATUS_FLAGS GetFlags() const
Definition: base_struct.h:266
COLOR4D & Invert()
Function Invert Makes the color inverted, alpha remains the same.
Definition: color4d.h:185
#define AXIS_SIZE_IN_PIXELS
Definition: draw_panel.cpp:823
wxPoint GetScreenCenterLogicalPosition()
Function GetScreenCenterLogicalPosition.
Definition: draw_panel.cpp:351
BLOCK_SELECTOR m_BlockLocate
Block description for block commands.
Definition: base_screen.h:214
#define GR_M_MIDDLE_DOWN
Definition: gr_basic.h:76
#define PIXEL_MARGIN
void GRSetDrawMode(wxDC *DC, GR_DRAWMODE draw_mode)
Definition: gr_basic.cpp:318
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:106
EDA_ITEM * GetCurItem() const
Definition: base_screen.h:233
virtual void HandleBlockPlace(wxDC *DC)
Function HandleBlockPlace( ) Called after HandleBlockEnd, when a block command needs to be executed a...
Definition: draw_frame.cpp:713
virtual void Refresh(bool eraseBackground=true, const wxRect *rect=NULL) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
Definition: draw_panel.cpp:338
wxPoint ToDeviceXY(const wxPoint &pos)
Function ToDeviceXY transforms logical to device coordinates.
Definition: draw_panel.cpp:201
double GetScalingFactor() const
Function GetScalingFactor returns the inverse of the current scale used to draw items on screen...
Definition: base_screen.cpp:92
void GRSFilledRect(EDA_RECT *aClipBox, wxDC *aDC, int x1, int y1, int x2, int y2, int aWidth, COLOR4D aColor, COLOR4D aBgColor)
Definition: gr_basic.cpp:1173
wxRealPoint GetGrid()
Definition: draw_panel.cpp:294
void SetEnableZoomNoCenter(bool aEnable)
Definition: draw_panel.cpp:685
bool m_enableZoomNoCenter
True to enable zooming around the crosshair instead of the center.
int m_scrollIncrementX
X axis scroll increment in pixels per unit.
bool Contains(const wxPoint &aPoint) const
Function Contains.
VIEW_CONTROLS class definition.
bool m_requestAutoPan
true to request an auto pan. Valid only when m_enableAutoPan = true.
EDA_RECT m_ClipBox
The drawing area used to redraw the screen which is usually the visible area of the drawing in intern...
EDA_DRAW_PANEL(EDA_DRAW_FRAME *parent, int id, const wxPoint &pos, const wxSize &size)
Definition: draw_panel.cpp:99
double GetZoom() const
Function GetZoom returns the current "zoom factor", which is a measure of "internal units per device ...
Definition: base_screen.h:340
void SetScrollCenterPosition(const wxPoint &aPoint)
int color
Definition: DXF_plotter.cpp:62
void DrawCrossHair(wxDC *aDC, COLOR4D aColor=COLOR4D::WHITE)
Function DrawCrossHair draws the user cross hair.
Definition: draw_panel.cpp:221
KICAD_MANAGER_FRAME::language_change EVT_MENU_RANGE(ID_PREFERENCES_HOTKEY_START, ID_PREFERENCES_HOTKEY_END, KICAD_MANAGER_FRAME::Process_Config) EVT_MENU_RANGE(ID_KICAD_SELECT_ICONS_OPTIONS
bool m_PrintIsMirrored
True when drawing in mirror mode.
void DrawGrid(wxDC *aDC)
Function DrawGrid draws a grid to aDC.
Definition: draw_panel.cpp:722
int GetHeight() const
Definition: eda_rect.h:118
END_MOUSE_CAPTURE_CALLBACK m_endMouseCaptureCallback
Abort mouse capture callback function.
virtual void EnableMousewheelPan(bool aEnable)
Function EnableMousewheelPan() Enables or disables mousewheel panning.
void EndMouseCapture(int aId=-1, int aCursorId=-1, const wxString &aTitle=wxEmptyString, bool aCallEndFunc=true)
Function EndMouseCapture ends mouse a capture.
void OnKeyEvent(wxKeyEvent &event)
wxPoint GetCursorPosition(bool aOnGrid, wxRealPoint *aGridSize=NULL) const
Function GetCursorPosition returns the current cursor position in logical (drawing) units...
void SetOrigin(const wxPoint &pos)
Definition: eda_rect.h:124
const wxPoint & GetScrollCenterPosition() const
#define INSTALL_PAINTDC(name, parent)
void RefreshDrawingRect(const EDA_RECT &aRect, bool aEraseBackground=true)
Function RefreshDrawingRect redraws the contents of aRect in drawing units.
Definition: draw_panel.cpp:318
wxPoint m_PanStartEventPosition
Initial position of mouse event when pan started.
void MoveCursor(const wxPoint &aPosition)
Function MoveCursor moves the mouse pointer to aPosition in logical (drawing) units.
Definition: draw_panel.cpp:366
void OnPan(wxCommandEvent &event)
Class EDA_DRAW_FRAME is the base class for create windows for drawing purpose.
Definition: draw_frame.h:63
void MoveCursorToCrossHair()
Function MoveCursorToCrossHair warps the cursor to the current cross hair position.
Definition: draw_panel.cpp:360
bool m_enableBlockCommands
True enables block commands.
#define abs(a)
Definition: auxiliary.h:84
#define GR_KB_ALT
Definition: common.h:65
void CallEndMouseCapture(wxDC *aDC)
Function CallEndMouseCapture calls the end mouse capture callback.
virtual const wxSize GetPageSizeIU() const =0
Function GetPageSizeIU works off of GetPageSettings() to return the size of the paper page in the int...
const int drawPanelStyle
Definition: draw_panel.cpp:96
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
Definition: kicad.cpp:52
void OnMouseEvent(wxMouseEvent &event)
#define ENBL_ZOOM_NO_CENTER_KEY
Definition: draw_panel.cpp:55
void SetClipBox(const EDA_RECT &aRect)
This file contains miscellaneous commonly used macros and functions.
MOUSE_CAPTURE_CALLBACK m_mouseCaptureCallback
Mouse capture move callback function.
void DrawGridAxis(wxDC *aDC, GR_DRAWMODE aDrawMode, const wxPoint &aGridOrigin)
Function DrawGridAxis Draw on auxiliary axis, used in Pcbnew to show grid origin, when the grid origi...
Definition: draw_panel.cpp:863
wxPoint ToLogicalXY(const wxPoint &pos)
Function ToLogicalXY transforms device to logical coordinates.
Definition: draw_panel.cpp:211
virtual bool HandleBlockBegin(wxDC *aDC, EDA_KEY aKey, const wxPoint &aPosition, int aExplicitCommand=0)
Initialize a block command.
Definition: draw_frame.cpp:881
void EnableCursorWarping(bool aEnable)
Function EnableCursorWarping() Enables or disables warping the cursor.
wxPoint m_StartVisu
Coordinates in drawing units of the current view position (upper left corner of device) ...
Definition: base_screen.h:198
bool IsBlockActive() const
Definition: base_screen.h:499
void OnTimer(wxTimerEvent &event)
Function OnTimer handle timer events.
Definition: draw_panel.cpp:420
void OnPaint(wxPaintEvent &event)
Definition: draw_panel.cpp:612
bool IsPointOnDisplay(const wxPoint &aPosition)
Function IsPointOnDisplay.
Definition: draw_panel.cpp:300
void GRRect(EDA_RECT *aClipBox, wxDC *aDC, int x1, int y1, int x2, int y2, COLOR4D aColor)
Definition: gr_basic.cpp:1098
#define ENBL_AUTO_PAN_KEY
Definition: draw_panel.cpp:59
virtual BASE_SCREEN * GetScreen() const
Function GetScreen returns a pointer to a BASE_SCREEN or one of its derivatives.
Definition: draw_frame.h:369
a helper to handle the real device context used in KiCad
virtual COLOR4D GetDrawBgColor() const
Definition: draw_frame.h:346
wxString dump(const wxArrayString &aArray)
Debug helper for printing wxArrayString contents.
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
#define GR_KB_SHIFT
Definition: common.h:66
GR_DRAWMODE
Drawmode. Compositing mode plus a flag or two.
Definition: gr_basic.h:37
virtual void OnLeftClick(wxDC *DC, const wxPoint &MousePos)=0
void OnMouseLeaving(wxMouseEvent &event)
Definition: draw_panel.cpp:937
bool IsMouseCaptured() const
Class BASE_SCREEN handles how to draw a screen (a board, a schematic ...)
Definition: base_screen.h:76
#define BLOCK_MINSIZE_LIMIT
double GetBrightness() const
Function GetBrightness Returns the brightness value of the color ranged from 0.0 to 1...
Definition: color4d.h:259
bool m_ignoreMouseEvents
Ignore mouse events when true.
void CallMouseCapture(wxDC *aDC, const wxPoint &aPosition, bool aErase)
Function CallMouseCapture calls the mouse capture callback.
void SetZoom(double mode)
Definition: draw_panel.cpp:288
#define ENBL_MOUSEWHEEL_PAN_KEY
Definition: draw_panel.cpp:56
wxConfigBase * KifaceSettings() const
Definition: kiface_i.h:103
void SetX(int val)
Definition: eda_rect.h:130
#define MIN_GRID_SIZE
wxLogTrace helper definitions.
Definition: colors.h:60
EDA_DRAW_FRAME * GetParent() const
Definition: draw_panel.cpp:180
virtual void EnableAutoPan(bool aEnabled)
Function EnableAutoPan Turns on/off auto panning (user setting to disable it entirely).
int GetBottom() const
Definition: eda_rect.h:122
bool SetZoom(double iu_per_du)
Function SetZoom adjusts the current zoom factor.
virtual void SetToolID(int aId, int aCursor, const wxString &aToolMsg)
Function SetToolID sets the tool command ID to aId and sets the cursor to aCursor.
Definition: draw_frame.cpp:590
int GetRight() const
Definition: eda_rect.h:119
#define CLIP_BOX_PADDING
Definition: draw_panel.cpp:50
void OnMouseEntering(wxMouseEvent &aEvent)
Definition: draw_panel.cpp:926
#define MIN_DRAG_COUNT_FOR_START_BLOCK_COMMAND
void GRLine(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, COLOR4D Color, wxPenStyle aStyle)
Definition: gr_basic.cpp:380
virtual COLOR4D GetGridColor()
Function GetGridColor() , virtual.
Definition: draw_frame.h:525
void CrossHairOff(wxDC *DC)
Definition: draw_panel.cpp:265
bool m_ignoreNextLeftButtonRelease
Ignore the next mouse left button release when true.
const wxPoint GetPosition() const
Definition: eda_rect.h:113
void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
wxPoint m_ScrollbarPos
Current scroll bar position in scroll units.
Definition: base_screen.h:196
void SetY(int val)
Definition: eda_rect.h:131
void OnMouseWheel(wxMouseEvent &event)
Function OnMouseWheel handles mouse wheel events.
Definition: draw_panel.cpp:971
virtual const wxPoint & GetAuxOrigin() const =0
Function GetAuxOrigin returns the origin of the axis used for plotting and various exports...
virtual bool HandleBlockEnd(wxDC *DC)
Function HandleBlockEnd( ) Handle the "end" of a block command, i.e.
Definition: draw_frame.cpp:718
wxString title
Definition: plotter.h:566
wxPoint m_PanStartCenter
Initial scroll center position when pan started.
wxPoint RefPos(bool useMouse) const
Function RefPos Return the reference position, coming from either the mouse position or the cursor po...
virtual void RedrawActiveWindow(wxDC *DC, bool EraseBg)=0
bool m_showCrossHair
Indicate if cross hair is to be shown.
void RedrawScreen(const wxPoint &aCenterPoint, bool aWarpPointer)
Function RedrawScreen redraws the entire screen area by updating the scroll bars and mouse pointer in...
Definition: zoom.cpp:46
#define GR_M_LEFT_DOWN
Definition: gr_basic.h:74
void SetSize(const wxSize &size)
Definition: eda_rect.h:126
wxPoint m_CursorClickPos
Used for maintaining click position.
void CrossHairOn(wxDC *DC)
Definition: draw_panel.cpp:272
wxPoint GetNearestGridPosition(const wxPoint &aPosition, wxRealPoint *aGridSize=NULL) const
Function GetNearestGridPosition returns the nearest aGridSize location to aPosition.
const int scale
void DisplayToolMsg(const wxString &msg)
Definition: draw_frame.cpp:552
see class PGM_BASE
void SetMousePosition(const wxPoint &aPosition)
void ReDraw(wxDC *aDC, bool aEraseBackground=true)
Definition: draw_panel.cpp:628
void OnCharHook(wxKeyEvent &event)
BLOCK_STATE_T GetState() const
#define max(a, b)
Definition: auxiliary.h:86
#define INSTALL_UNBUFFERED_DC(name, parent)
bool m_enableMousewheelPan
True to enable mousewheel panning by default.
void OnActivate(wxActivateEvent &event)
Function OnActivate handles window activation events.
Definition: draw_panel.cpp:413
int m_currentCursor
Current mouse cursor shape id.
int GetToolId() const
Definition: draw_frame.h:496
int m_defaultCursor
The default mouse cursor shape id.
wxTimer * m_ClickTimer
void GRCircle(EDA_RECT *ClipBox, wxDC *DC, int xc, int yc, int r, int width, COLOR4D Color)
Definition: gr_basic.cpp:850
const wxRealPoint & GetGridSize() const
Return the grid size of the currently selected grid.
Definition: base_screen.h:410
void GRSetColorPen(wxDC *DC, COLOR4D Color, int width, wxPenStyle style)
Function GRSetColorPen sets a pen style, width, color, and alpha into the given device context...
Definition: gr_basic.cpp:231
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
wxPoint m_DrawOrg
offsets for drawing the circuit on the screen
Definition: base_screen.h:183
void SetEnableMousewheelPan(bool aEnable)
Definition: draw_panel.cpp:668
int GetX() const
Definition: eda_rect.h:109
BASE_SCREEN * GetScreen()
Definition: draw_panel.cpp:193
const wxChar *const kicadTraceKeyEvent
Flag to enable wxKeyEvent debug tracing.
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:162
The common library.
int GetWidth() const
Definition: eda_rect.h:117
bool OnRightClick(wxMouseEvent &event)
Function OnRightClick builds and displays a context menu on a right mouse button click.
Definition: draw_panel.cpp:899
static const int CURSOR_SIZE
Cursor size in pixels.
Definition: draw_panel.cpp:48
Definition: colors.h:49
int GetY() const
Definition: eda_rect.h:110
void DrawAuxiliaryAxis(wxDC *aDC, GR_DRAWMODE aDrawMode)
Function DrawAuxiliaryAxis Draw the Auxiliary Axis, used in Pcbnew which as origin coordinates for ge...
Definition: draw_panel.cpp:825
KIGFX::VIEW_CONTROLS * GetViewControls() const
Function GetViewControls() Returns a pointer to the VIEW_CONTROLS instance used in the panel...
int m_minDragEventCount
Count the drag events.
wxPoint m_CursorStartPos
Used for testing the cursor movement.
Definition: id.h:256
virtual bool GeneralControl(wxDC *aDC, const wxPoint &aPosition, EDA_KEY aHotKey=0)
Function GeneralControl performs application specific control using aDC at aPosition in logical units...
Definition: draw_frame.h:614
EDA_DRAW_PANEL_GAL * GetGalCanvas() const
Function GetGalCanvas returns a pointer to GAL-based canvas of given EDA draw frame.
Definition: draw_frame.h:903
virtual void AddMenuZoomAndGrid(wxMenu *aMasterMenu)
Function AddMenuZoomAndGrid (virtual) Add standard zoom commands and submenu zoom and grid selection ...
Definition: zoom.cpp:266
void DrawBackGround(wxDC *DC)
Function DrawBackGround.
Definition: draw_panel.cpp:694
bool m_enableAutoPan
True to enable automatic panning.
Definition: colors.h:45
void * GetDisplayOptions()
Function GetDisplayOptions A way to pass info to draw functions.
Definition: draw_panel.cpp:187
void SetCrossHairPosition(const wxPoint &aPosition, bool aSnapToGrid=true)
Function SetCrossHairPosition sets the screen cross hair position to aPosition in logical (drawing) u...
BASE_SCREEN class implementation.
void EraseScreen(wxDC *DC)
Definition: draw_panel.cpp:574
virtual void OnLeftDClick(wxDC *DC, const wxPoint &MousePos)
Definition: draw_frame.cpp:547
#define GR_KB_CTRL
Definition: common.h:64
const wxChar *const kicadTraceCoords
Flag to enable draw panel coordinate debug tracing.
void SetEnableAutoPan(bool aEnable)
Definition: draw_panel.cpp:676
wxPoint GetCrossHairPosition(bool aInvertY=false) const
Function GetCrossHairPosition return the current cross hair position in logical (drawing) coordinates...
int m_cursorLevel
Index for cursor redraw in XOR mode.
virtual void DoPrepareDC(wxDC &aDC) override
Function DoPrepareDC sets up the device context aDC for drawing.
Definition: draw_panel.cpp:593
virtual void * GetDisplayOptions()
Function GetDisplayOptions A way to pass info to draw functions.
Definition: draw_frame.h:918
void OnScroll(wxScrollWinEvent &event)
Definition: draw_panel.cpp:428
COLOR4D g_GhostColor
Draw color for moving objects.
Definition: common.cpp:58
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
int m_scrollIncrementY
Y axis scroll increment in pixels per unit.
#define min(a, b)
Definition: auxiliary.h:85
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39