2011-10-13 19:56:32 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
2012-03-08 17:47:23 +00:00
|
|
|
* Copyright (C) 2009 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.fr
|
2011-10-18 19:59:19 +00:00
|
|
|
* Copyright (C) 2007-2011 Wayne Stambaugh <stambaughw@verizon.net>
|
2011-10-13 19:56:32 +00:00
|
|
|
* Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, you may find one here:
|
|
|
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|
|
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
|
|
|
* or you may write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
2011-03-09 20:09:11 +00:00
|
|
|
/**
|
|
|
|
* @file drawpanel.cpp
|
|
|
|
*/
|
2009-02-04 15:25:03 +00:00
|
|
|
|
2012-01-23 04:33:36 +00:00
|
|
|
#include <fctsys.h>
|
|
|
|
#include <appl_wxstruct.h>
|
|
|
|
#include <gr_basic.h>
|
|
|
|
#include <common.h>
|
|
|
|
#include <macros.h>
|
|
|
|
#include <id.h>
|
|
|
|
#include <class_drawpanel.h>
|
Introduction of Graphics Abstraction Layer based rendering for pcbnew.
New classes:
- VIEW - represents view that is seen by user, takes care of layer ordering & visibility and how it is displayed (which location, how much zoomed, etc.)
- VIEW_ITEM - Base class for every item that can be displayed on VIEW (the biggest change is that now it may be necessary to override ViewBBox & ViewGetLayers method for derived classes).
- EDA_DRAW_PANEL_GAL - Inherits after EDA_DRAW_PANEL, displays VIEW output, right now it is not editable (in opposite to usual EDA_DRAW_PANEL).
- GAL/OPENGL_GAL/CAIRO_GAL - Base Graphics Abstraction Layer class + two different flavours (Cairo is not fully supported yet), that offers methods to draw primitives using different libraries.
- WX_VIEW_CONTROLS - Controller for VIEW, handles user events, allows zooming, panning, etc.
- PAINTER/PCB_PAINTER - Classes that uses GAL interface to draw items (as you may have already guessed - PCB_PAINTER is a class for drawing PCB specific object, PAINTER is an abstract class). Its methods are invoked by VIEW, when an item has to be drawn. To display a new type of item - you need to implement draw(ITEM_TYPE*) method that draws it using GAL methods.
- STROKE_FONT - Implements stroke font drawing using GAL methods.
Most important changes to Kicad original code:
* EDA_ITEM now inherits from VIEW_ITEM, which is a base class for all drawable objects.
* EDA_DRAW_FRAME contains both usual EDA_DRAW_PANEL and new EDA_DRAW_PANEL_GAL, that can be switched anytime.
* There are some new layers for displaying multilayer pads, vias & pads holes (these are not shown yet on the right sidebar in pcbnew)
* Display order of layers is different than in previous versions (if you are curious - you may check m_galLayerOrder@pcbnew/basepcbframe.cpp). Preserving usual order would result in not very natural display, such as showing silkscreen texts on the bottom.
* Introduced new hotkey (Alt+F12) and new menu option (View->Switch canvas) for switching canvas during runtime.
* Some of classes (mostly derived from BOARD_ITEM) now includes ViewBBox & ViewGetLayers methods.
* Removed tools/class_painter.h, as now it is extended and included in source code.
Build changes:
* GAL-based rendering option is turned on by a new compilation CMake option KICAD_GAL.
* When compiling with CMake option KICAD_GAL=ON, GLEW and Cairo libraries are required.
* GAL-related code is compiled into a static library (common/libgal).
* Build with KICAD_GAL=OFF should not need any new libraries and should come out as a standard version of Kicad
Currently most of items in pcbnew can be displayed using OpenGL (to be done are DIMENSIONS and MARKERS).
More details about GAL can be found in: http://www.ohwr.org/attachments/1884/view-spec.pdf
2013-04-02 06:54:03 +00:00
|
|
|
#include <class_drawpanel_gal.h>
|
2012-01-23 04:33:36 +00:00
|
|
|
#include <class_base_screen.h>
|
|
|
|
#include <wxstruct.h>
|
2009-02-04 15:25:03 +00:00
|
|
|
|
2012-01-23 04:33:36 +00:00
|
|
|
#include <kicad_device_context.h>
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2012-05-27 00:19:12 +00:00
|
|
|
static const int CURSOR_SIZE = 12; ///< Cursor size in pixels
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2011-02-21 13:54:29 +00:00
|
|
|
#define CLIP_BOX_PADDING 2
|
2009-12-19 16:10:25 +00:00
|
|
|
|
2012-04-11 18:54:20 +00:00
|
|
|
// keys to store options in config:
|
2013-02-02 19:10:48 +00:00
|
|
|
#define ENBL_ZOOM_NO_CENTER_KEY wxT( "ZoomNoCenter" )
|
2012-04-11 18:54:20 +00:00
|
|
|
#define ENBL_MIDDLE_BUTT_PAN_KEY wxT( "MiddleButtonPAN" )
|
|
|
|
#define MIDDLE_BUTT_PAN_LIMITED_KEY wxT( "MiddleBtnPANLimited" )
|
|
|
|
#define ENBL_AUTO_PAN_KEY wxT( "AutoPAN" )
|
|
|
|
|
2010-02-22 16:45:35 +00:00
|
|
|
/* Definitions for enabling and disabling debugging features in drawpanel.cpp.
|
2011-01-30 22:22:38 +00:00
|
|
|
* Please don't forget to turn these off before making any commits to Launchpad.
|
2010-02-22 16:45:35 +00:00
|
|
|
*/
|
|
|
|
#define DEBUG_SHOW_CLIP_RECT 0 // Set to 1 to draw clipping rectangle.
|
2011-02-09 19:47:33 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Trace mask used to enable or disable the trace output of coordinates during drawing
|
|
|
|
* functions. The coordinate dumping can be turned on by setting the WXTRACE environment
|
|
|
|
* variable to "kicad_dump_coords". See the wxWidgets documentation on wxLogTrace for
|
|
|
|
* more information.
|
|
|
|
*/
|
|
|
|
#define KICAD_TRACE_COORDS wxT( "kicad_dump_coords" )
|
2009-12-19 16:10:25 +00:00
|
|
|
|
|
|
|
|
2011-01-21 19:30:59 +00:00
|
|
|
// Events used by EDA_DRAW_PANEL
|
|
|
|
BEGIN_EVENT_TABLE( EDA_DRAW_PANEL, wxScrolledWindow )
|
|
|
|
EVT_LEAVE_WINDOW( EDA_DRAW_PANEL::OnMouseLeaving )
|
|
|
|
EVT_MOUSEWHEEL( EDA_DRAW_PANEL::OnMouseWheel )
|
|
|
|
EVT_MOUSE_EVENTS( EDA_DRAW_PANEL::OnMouseEvent )
|
|
|
|
EVT_CHAR( EDA_DRAW_PANEL::OnKeyEvent )
|
2011-12-17 21:21:03 +00:00
|
|
|
EVT_CHAR_HOOK( EDA_DRAW_PANEL::OnCharHook )
|
2011-01-21 19:30:59 +00:00
|
|
|
EVT_PAINT( EDA_DRAW_PANEL::OnPaint )
|
2011-01-30 22:22:38 +00:00
|
|
|
EVT_ERASE_BACKGROUND( EDA_DRAW_PANEL::OnEraseBackground )
|
2011-01-21 19:30:59 +00:00
|
|
|
EVT_SCROLLWIN( EDA_DRAW_PANEL::OnScroll )
|
|
|
|
EVT_ACTIVATE( EDA_DRAW_PANEL::OnActivate )
|
|
|
|
EVT_MENU_RANGE( ID_PAN_UP, ID_PAN_RIGHT, EDA_DRAW_PANEL::OnPan )
|
2007-05-06 16:03:28 +00:00
|
|
|
END_EVENT_TABLE()
|
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
|
2009-11-23 15:16:50 +00:00
|
|
|
/***********************************************************************/
|
2011-01-21 19:30:59 +00:00
|
|
|
/* EDA_DRAW_PANEL base functions (EDA_DRAW_PANEL is the main panel)*/
|
2009-11-23 15:16:50 +00:00
|
|
|
/***********************************************************************/
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2011-01-21 19:30:59 +00:00
|
|
|
EDA_DRAW_PANEL::EDA_DRAW_PANEL( EDA_DRAW_FRAME* parent, int id,
|
|
|
|
const wxPoint& pos, const wxSize& size ) :
|
2012-06-20 09:57:36 +00:00
|
|
|
wxScrolledWindow( parent, id, pos, size, wxBORDER | wxHSCROLL | wxVSCROLL | wxALWAYS_SHOW_SB )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2011-02-09 19:47:33 +00:00
|
|
|
wxASSERT( parent );
|
2010-02-08 18:15:42 +00:00
|
|
|
|
2012-09-22 11:19:37 +00:00
|
|
|
m_scrollIncrementX = std::min( size.x / 8, 10 );
|
|
|
|
m_scrollIncrementY = std::min( size.y / 8, 10 );
|
2011-01-30 22:22:38 +00:00
|
|
|
|
2011-02-09 19:47:33 +00:00
|
|
|
SetBackgroundColour( MakeColour( g_DrawBgColor ) );
|
2011-01-30 22:22:38 +00:00
|
|
|
|
|
|
|
#if KICAD_USE_BUFFERED_DC || KICAD_USE_BUFFERED_PAINTDC
|
2009-12-29 10:35:11 +00:00
|
|
|
SetBackgroundStyle( wxBG_STYLE_CUSTOM );
|
2010-01-14 20:20:59 +00:00
|
|
|
#endif
|
2011-01-30 22:22:38 +00:00
|
|
|
|
2007-08-22 05:11:01 +00:00
|
|
|
m_ClipBox.SetSize( size );
|
|
|
|
m_ClipBox.SetX( 0 );
|
|
|
|
m_ClipBox.SetY( 0 );
|
2011-12-29 20:11:42 +00:00
|
|
|
m_canStartBlock = -1; // Command block can start if >= 0
|
|
|
|
m_abortRequest = false;
|
2012-04-11 18:54:20 +00:00
|
|
|
m_enableMiddleButtonPan = false;
|
2013-02-02 19:10:48 +00:00
|
|
|
m_enableZoomNoCenter = false;
|
2012-04-11 18:54:20 +00:00
|
|
|
m_panScrollbarLimits = false;
|
2011-12-29 20:11:42 +00:00
|
|
|
m_enableAutoPan = true;
|
|
|
|
m_ignoreMouseEvents = false;
|
2012-12-06 21:53:00 +00:00
|
|
|
m_ignoreNextLeftButtonRelease = false;
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2011-02-11 20:48:13 +00:00
|
|
|
m_mouseCaptureCallback = NULL;
|
|
|
|
m_endMouseCaptureCallback = NULL;
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2011-12-16 20:12:49 +00:00
|
|
|
if( wxGetApp().GetSettings() )
|
2012-04-11 18:54:20 +00:00
|
|
|
{
|
|
|
|
wxGetApp().GetSettings()->Read( ENBL_MIDDLE_BUTT_PAN_KEY, &m_enableMiddleButtonPan, false );
|
2013-02-02 19:10:48 +00:00
|
|
|
wxGetApp().GetSettings()->Read( ENBL_ZOOM_NO_CENTER_KEY, &m_enableZoomNoCenter, false );
|
2012-04-11 18:54:20 +00:00
|
|
|
wxGetApp().GetSettings()->Read( MIDDLE_BUTT_PAN_LIMITED_KEY, &m_panScrollbarLimits, false );
|
|
|
|
wxGetApp().GetSettings()->Read( ENBL_AUTO_PAN_KEY, &m_enableAutoPan, true );
|
|
|
|
}
|
2008-04-17 16:25:29 +00:00
|
|
|
|
2011-12-29 20:11:42 +00:00
|
|
|
m_requestAutoPan = false;
|
|
|
|
m_enableBlockCommands = false;
|
2012-12-06 21:53:00 +00:00
|
|
|
m_minDragEventCount = 0;
|
2011-02-09 19:47:33 +00:00
|
|
|
|
|
|
|
#ifdef __WXMAC__
|
2011-03-09 20:09:11 +00:00
|
|
|
m_defaultCursor = m_currentCursor = wxCURSOR_CROSS;
|
2011-02-09 19:47:33 +00:00
|
|
|
m_showCrossHair = false;
|
|
|
|
#else
|
2011-03-09 20:09:11 +00:00
|
|
|
m_defaultCursor = m_currentCursor = wxCURSOR_ARROW;
|
2011-02-09 19:47:33 +00:00
|
|
|
m_showCrossHair = true;
|
|
|
|
#endif
|
2011-01-30 22:22:38 +00:00
|
|
|
|
2011-12-29 20:11:42 +00:00
|
|
|
m_cursorLevel = 0;
|
2011-02-09 19:47:33 +00:00
|
|
|
m_PrintIsMirrored = false;
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-15 02:43:57 +00:00
|
|
|
|
2011-01-21 19:30:59 +00:00
|
|
|
EDA_DRAW_PANEL::~EDA_DRAW_PANEL()
|
2009-04-08 18:06:22 +00:00
|
|
|
{
|
2012-04-11 18:54:20 +00:00
|
|
|
wxGetApp().GetSettings()->Write( ENBL_MIDDLE_BUTT_PAN_KEY, m_enableMiddleButtonPan );
|
2013-02-02 19:10:48 +00:00
|
|
|
wxGetApp().GetSettings()->Write( ENBL_ZOOM_NO_CENTER_KEY, m_enableZoomNoCenter );
|
2012-04-11 18:54:20 +00:00
|
|
|
wxGetApp().GetSettings()->Write( MIDDLE_BUTT_PAN_LIMITED_KEY, m_panScrollbarLimits );
|
|
|
|
wxGetApp().GetSettings()->Write( ENBL_AUTO_PAN_KEY, m_enableAutoPan );
|
2009-04-08 18:06:22 +00:00
|
|
|
}
|
|
|
|
|
2011-02-09 19:47:33 +00:00
|
|
|
EDA_DRAW_FRAME* EDA_DRAW_PANEL::GetParent()
|
|
|
|
{
|
|
|
|
return ( EDA_DRAW_FRAME* ) wxWindow::GetParent();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-21 19:30:59 +00:00
|
|
|
BASE_SCREEN* EDA_DRAW_PANEL::GetScreen()
|
2008-04-17 16:25:29 +00:00
|
|
|
{
|
2011-02-09 19:47:33 +00:00
|
|
|
EDA_DRAW_FRAME* parentFrame = GetParent();
|
2010-01-17 14:20:29 +00:00
|
|
|
|
2011-02-05 02:21:11 +00:00
|
|
|
return parentFrame->GetScreen();
|
2008-04-17 16:25:29 +00:00
|
|
|
}
|
|
|
|
|
2013-02-02 19:10:48 +00:00
|
|
|
wxPoint EDA_DRAW_PANEL::ToDeviceXY( const wxPoint& pos )
|
|
|
|
{
|
2013-02-12 03:56:46 +00:00
|
|
|
wxPoint ret;
|
|
|
|
INSTALL_UNBUFFERED_DC( dc, this );
|
|
|
|
ret.x = dc.LogicalToDeviceX( pos.x );
|
|
|
|
ret.y = dc.LogicalToDeviceY( pos.y );
|
|
|
|
return ret;
|
2013-02-02 19:10:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
wxPoint EDA_DRAW_PANEL::ToLogicalXY( const wxPoint& pos )
|
|
|
|
{
|
2013-02-12 03:56:46 +00:00
|
|
|
wxPoint ret;
|
|
|
|
INSTALL_UNBUFFERED_DC( dc, this );
|
|
|
|
ret.x = dc.DeviceToLogicalX( pos.x );
|
|
|
|
ret.y = dc.DeviceToLogicalY( pos.y );
|
|
|
|
return ret;
|
2013-02-02 19:10:48 +00:00
|
|
|
}
|
2008-04-17 16:25:29 +00:00
|
|
|
|
2012-09-02 12:06:47 +00:00
|
|
|
void EDA_DRAW_PANEL::DrawCrossHair( wxDC* aDC, EDA_COLOR_T aColor )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2011-02-09 19:47:33 +00:00
|
|
|
if( m_cursorLevel != 0 || aDC == NULL || !m_showCrossHair )
|
2007-08-22 05:11:01 +00:00
|
|
|
return;
|
|
|
|
|
2012-04-23 21:56:26 +00:00
|
|
|
wxPoint cursor = GetScreen()->GetCrossHairPosition();
|
2007-10-06 16:16:48 +00:00
|
|
|
|
2010-01-22 18:13:43 +00:00
|
|
|
GRSetDrawMode( aDC, GR_XOR );
|
2010-02-10 21:39:32 +00:00
|
|
|
|
2012-04-23 21:56:26 +00:00
|
|
|
if( GetParent()->m_cursorShape != 0 ) // Draws full screen crosshair.
|
2007-08-22 05:11:01 +00:00
|
|
|
{
|
2012-04-23 21:56:26 +00:00
|
|
|
wxSize clientSize = GetClientSize();
|
|
|
|
|
|
|
|
// Y axis
|
|
|
|
wxPoint lineStart( cursor.x, aDC->DeviceToLogicalY( 0 ) );
|
|
|
|
wxPoint lineEnd( cursor.x, aDC->DeviceToLogicalY( clientSize.y ) );
|
|
|
|
|
|
|
|
GRLine( &m_ClipBox, aDC, lineStart, lineEnd, 0, aColor );
|
|
|
|
|
|
|
|
// X axis
|
|
|
|
lineStart = wxPoint( aDC->DeviceToLogicalX( 0 ), cursor.y );
|
|
|
|
lineEnd = wxPoint( aDC->DeviceToLogicalX( clientSize.x ), cursor.y );
|
|
|
|
|
|
|
|
GRLine( &m_ClipBox, aDC, lineStart, lineEnd, 0, aColor );
|
2007-08-22 05:11:01 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-02-08 18:15:42 +00:00
|
|
|
int len = aDC->DeviceToLogicalXRel( CURSOR_SIZE );
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2012-04-23 21:56:26 +00:00
|
|
|
GRLine( &m_ClipBox, aDC, cursor.x - len, cursor.y,
|
|
|
|
cursor.x + len, cursor.y, 0, aColor );
|
|
|
|
GRLine( &m_ClipBox, aDC, cursor.x, cursor.y - len,
|
|
|
|
cursor.x, cursor.y + len, 0, aColor );
|
2007-08-22 05:11:01 +00:00
|
|
|
}
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-15 02:43:57 +00:00
|
|
|
|
2011-02-11 20:48:13 +00:00
|
|
|
void EDA_DRAW_PANEL::CrossHairOff( wxDC* DC )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2011-02-11 20:48:13 +00:00
|
|
|
DrawCrossHair( DC );
|
2011-02-09 19:47:33 +00:00
|
|
|
--m_cursorLevel;
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-15 02:43:57 +00:00
|
|
|
|
2011-02-11 20:48:13 +00:00
|
|
|
void EDA_DRAW_PANEL::CrossHairOn( wxDC* DC )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2011-02-09 19:47:33 +00:00
|
|
|
++m_cursorLevel;
|
2011-02-11 20:48:13 +00:00
|
|
|
DrawCrossHair( DC );
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2011-02-09 19:47:33 +00:00
|
|
|
if( m_cursorLevel > 0 ) // Shouldn't happen, but just in case ..
|
|
|
|
m_cursorLevel = 0;
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-07 21:47:25 +00:00
|
|
|
double EDA_DRAW_PANEL::GetZoom()
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2007-08-22 05:11:01 +00:00
|
|
|
return GetScreen()->GetZoom();
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-15 02:43:57 +00:00
|
|
|
|
2012-05-07 21:47:25 +00:00
|
|
|
void EDA_DRAW_PANEL::SetZoom( double zoom )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2007-08-22 05:11:01 +00:00
|
|
|
GetScreen()->SetZoom( zoom );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-15 02:43:57 +00:00
|
|
|
|
2011-01-21 19:30:59 +00:00
|
|
|
wxRealPoint EDA_DRAW_PANEL::GetGrid()
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2009-10-14 19:43:31 +00:00
|
|
|
return GetScreen()->GetGridSize();
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-09 19:47:33 +00:00
|
|
|
bool EDA_DRAW_PANEL::IsPointOnDisplay( const wxPoint& aPosition )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2007-08-22 05:11:01 +00:00
|
|
|
wxPoint pos;
|
2011-03-29 19:33:07 +00:00
|
|
|
EDA_RECT display_rect;
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2011-02-09 19:47:33 +00:00
|
|
|
INSTALL_UNBUFFERED_DC( dc, this ); // Refresh the clip box to the entire screen size.
|
2011-01-30 22:22:38 +00:00
|
|
|
SetClipBox( dc );
|
2010-02-08 18:15:42 +00:00
|
|
|
|
2007-08-22 05:11:01 +00:00
|
|
|
display_rect = m_ClipBox;
|
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
// Slightly decreased the size of the useful screen area to avoid drawing limits.
|
2007-08-22 05:11:01 +00:00
|
|
|
#define PIXEL_MARGIN 8
|
2009-12-29 10:35:11 +00:00
|
|
|
display_rect.Inflate( -PIXEL_MARGIN );
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2011-02-09 19:47:33 +00:00
|
|
|
return display_rect.Contains( aPosition );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-03-29 19:33:07 +00:00
|
|
|
void EDA_DRAW_PANEL::RefreshDrawingRect( const EDA_RECT& aRect, bool aEraseBackground )
|
2008-03-10 15:00:22 +00:00
|
|
|
{
|
2011-01-30 22:22:38 +00:00
|
|
|
INSTALL_UNBUFFERED_DC( dc, this );
|
2008-03-10 15:00:22 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
wxRect rect = aRect;
|
2008-03-11 01:19:08 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
rect.x = dc.LogicalToDeviceX( rect.x );
|
|
|
|
rect.y = dc.LogicalToDeviceY( rect.y );
|
|
|
|
rect.width = dc.LogicalToDeviceXRel( rect.width );
|
|
|
|
rect.height = dc.LogicalToDeviceYRel( rect.height );
|
2008-03-10 15:00:22 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
wxLogTrace( KICAD_TRACE_COORDS,
|
|
|
|
wxT( "Refresh area: drawing (%d, %d, %d, %d), device (%d, %d, %d, %d)" ),
|
|
|
|
aRect.GetX(), aRect.GetY(), aRect.GetWidth(), aRect.GetHeight(),
|
|
|
|
rect.x, rect.y, rect.width, rect.height );
|
2008-05-17 19:08:23 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
RefreshRect( rect, aEraseBackground );
|
2008-03-10 08:14:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-31 18:26:12 +00:00
|
|
|
wxPoint EDA_DRAW_PANEL::GetScreenCenterLogicalPosition()
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2011-01-31 18:26:12 +00:00
|
|
|
wxSize size = GetClientSize() / 2;
|
|
|
|
INSTALL_UNBUFFERED_DC( dc, this );
|
2010-02-08 18:15:42 +00:00
|
|
|
|
2011-01-31 18:26:12 +00:00
|
|
|
return wxPoint( dc.DeviceToLogicalX( size.x ), dc.DeviceToLogicalY( size.y ) );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-11 20:48:13 +00:00
|
|
|
void EDA_DRAW_PANEL::MoveCursorToCrossHair()
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2011-02-11 20:48:13 +00:00
|
|
|
MoveCursor( GetScreen()->GetCrossHairPosition() );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-15 02:43:57 +00:00
|
|
|
|
2011-02-01 15:46:25 +00:00
|
|
|
void EDA_DRAW_PANEL::MoveCursor( const wxPoint& aPosition )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2009-02-05 20:53:08 +00:00
|
|
|
int x, y, xPpu, yPpu;
|
|
|
|
wxPoint screenPos, drawingPos;
|
|
|
|
wxRect clientRect( wxPoint( 0, 0 ), GetClientSize() );
|
|
|
|
|
2011-02-01 15:46:25 +00:00
|
|
|
INSTALL_UNBUFFERED_DC( dc, this );
|
|
|
|
screenPos.x = dc.LogicalToDeviceX( aPosition.x );
|
|
|
|
screenPos.y = dc.LogicalToDeviceY( aPosition.y );
|
2009-02-05 20:53:08 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
// Scroll if the requested mouse position cursor is outside the drawing area.
|
2009-02-05 20:53:08 +00:00
|
|
|
if( !clientRect.Contains( screenPos ) )
|
|
|
|
{
|
|
|
|
GetViewStart( &x, &y );
|
|
|
|
GetScrollPixelsPerUnit( &xPpu, &yPpu );
|
2011-01-30 22:22:38 +00:00
|
|
|
CalcUnscrolledPosition( screenPos.x, screenPos.y, &drawingPos.x, &drawingPos.y );
|
2009-02-05 20:53:08 +00:00
|
|
|
|
2011-02-11 20:48:13 +00:00
|
|
|
wxLogTrace( KICAD_TRACE_COORDS,
|
|
|
|
wxT( "MoveCursor() initial screen position(%d, %d) " ) \
|
2009-05-21 17:42:42 +00:00
|
|
|
wxT( "rectangle(%d, %d, %d, %d) view(%d, %d)" ),
|
2009-02-05 20:53:08 +00:00
|
|
|
screenPos.x, screenPos.y, clientRect.x, clientRect.y,
|
|
|
|
clientRect.width, clientRect.height, x, y );
|
|
|
|
|
|
|
|
if( screenPos.y < clientRect.GetTop() )
|
2010-02-08 18:15:42 +00:00
|
|
|
y -= m_scrollIncrementY * yPpu;
|
2009-02-05 20:53:08 +00:00
|
|
|
else if( screenPos.y > clientRect.GetBottom() )
|
2010-02-08 18:15:42 +00:00
|
|
|
y += m_scrollIncrementY * yPpu;
|
2009-02-05 20:53:08 +00:00
|
|
|
else if( clientRect.GetRight() < screenPos.x )
|
2010-02-08 18:15:42 +00:00
|
|
|
x += m_scrollIncrementX * xPpu;
|
2009-02-05 20:53:08 +00:00
|
|
|
else
|
2010-02-08 18:15:42 +00:00
|
|
|
x -= m_scrollIncrementX * xPpu;
|
2009-02-05 20:53:08 +00:00
|
|
|
|
|
|
|
Scroll( x, y );
|
2011-01-30 22:22:38 +00:00
|
|
|
CalcScrolledPosition( drawingPos.x, drawingPos.y, &screenPos.x, &screenPos.y );
|
2009-02-05 20:53:08 +00:00
|
|
|
|
2011-02-11 20:48:13 +00:00
|
|
|
wxLogTrace( KICAD_TRACE_COORDS,
|
|
|
|
wxT( "MoveCursor() scrolled screen position(%d, %d) view(%d, %d)" ),
|
2011-01-30 22:22:38 +00:00
|
|
|
screenPos.x, screenPos.y, x, y );
|
2009-02-05 20:53:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
WarpPointer( screenPos.x, screenPos.y );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2011-01-21 19:30:59 +00:00
|
|
|
void EDA_DRAW_PANEL::OnActivate( wxActivateEvent& event )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2011-12-29 20:11:42 +00:00
|
|
|
m_canStartBlock = -1; // Block Command can't start
|
2007-08-22 05:11:01 +00:00
|
|
|
event.Skip();
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
|
2011-01-21 19:30:59 +00:00
|
|
|
void EDA_DRAW_PANEL::OnScroll( wxScrollWinEvent& event )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2007-08-22 05:11:01 +00:00
|
|
|
int id = event.GetEventType();
|
2010-02-22 16:45:35 +00:00
|
|
|
int dir;
|
2007-08-22 05:11:01 +00:00
|
|
|
int x, y;
|
2010-02-22 16:45:35 +00:00
|
|
|
int ppux, ppuy;
|
2012-04-11 18:54:20 +00:00
|
|
|
int csizeX, csizeY;
|
2010-02-22 16:45:35 +00:00
|
|
|
int unitsX, unitsY;
|
|
|
|
int maxX, maxY;
|
2007-08-22 05:11:01 +00:00
|
|
|
|
|
|
|
GetViewStart( &x, &y );
|
2010-02-22 16:45:35 +00:00
|
|
|
GetScrollPixelsPerUnit( &ppux, &ppuy );
|
2012-04-11 18:54:20 +00:00
|
|
|
GetClientSize( &csizeX, &csizeY );
|
2010-02-22 16:45:35 +00:00
|
|
|
GetVirtualSize( &unitsX, &unitsY );
|
2012-04-11 18:54:20 +00:00
|
|
|
|
2012-04-12 07:58:12 +00:00
|
|
|
int tmpX = x;
|
|
|
|
int tmpY = y;
|
|
|
|
|
2012-04-11 18:54:20 +00:00
|
|
|
csizeX /= ppux;
|
|
|
|
csizeY /= ppuy;
|
2010-02-22 16:45:35 +00:00
|
|
|
|
|
|
|
unitsX /= ppux;
|
|
|
|
unitsY /= ppuy;
|
|
|
|
|
2012-04-11 18:54:20 +00:00
|
|
|
maxX = unitsX - csizeX;
|
|
|
|
maxY = unitsY - csizeY;
|
|
|
|
|
2007-10-06 16:16:48 +00:00
|
|
|
dir = event.GetOrientation(); // wxHORIZONTAL or wxVERTICAL
|
2007-08-22 05:11:01 +00:00
|
|
|
|
|
|
|
if( id == wxEVT_SCROLLWIN_LINEUP )
|
2010-02-22 16:45:35 +00:00
|
|
|
{
|
|
|
|
if( dir == wxHORIZONTAL )
|
|
|
|
{
|
|
|
|
x -= m_scrollIncrementX;
|
2011-01-30 22:22:38 +00:00
|
|
|
|
2010-02-22 16:45:35 +00:00
|
|
|
if( x < 0 )
|
|
|
|
x = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
y -= m_scrollIncrementY;
|
2011-01-30 22:22:38 +00:00
|
|
|
|
2010-02-22 16:45:35 +00:00
|
|
|
if( y < 0 )
|
|
|
|
y = 0;
|
|
|
|
}
|
|
|
|
}
|
2007-08-22 05:11:01 +00:00
|
|
|
else if( id == wxEVT_SCROLLWIN_LINEDOWN )
|
2010-02-22 16:45:35 +00:00
|
|
|
{
|
|
|
|
if( dir == wxHORIZONTAL )
|
|
|
|
{
|
|
|
|
x += m_scrollIncrementX;
|
|
|
|
if( x > maxX )
|
|
|
|
x = maxX;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
y += m_scrollIncrementY;
|
2011-01-30 22:22:38 +00:00
|
|
|
|
2010-02-22 16:45:35 +00:00
|
|
|
if( y > maxY )
|
|
|
|
y = maxY;
|
|
|
|
}
|
|
|
|
}
|
2007-08-22 05:11:01 +00:00
|
|
|
else if( id == wxEVT_SCROLLWIN_THUMBTRACK )
|
|
|
|
{
|
|
|
|
if( dir == wxHORIZONTAL )
|
2010-02-22 16:45:35 +00:00
|
|
|
x = event.GetPosition();
|
2007-08-22 05:11:01 +00:00
|
|
|
else
|
2010-02-22 16:45:35 +00:00
|
|
|
y = event.GetPosition();
|
2007-08-22 05:11:01 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
event.Skip();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-02-09 19:47:33 +00:00
|
|
|
wxLogTrace( KICAD_TRACE_COORDS,
|
2011-02-16 19:16:38 +00:00
|
|
|
wxT( "Setting scroll bars ppuX=%d, ppuY=%d, unitsX=%d, unitsY=%d, posX=%d, posY=%d" ),
|
|
|
|
ppux, ppuy, unitsX, unitsY, x, y );
|
2010-02-10 21:39:32 +00:00
|
|
|
|
2012-04-12 07:58:12 +00:00
|
|
|
double scale = GetParent()->GetScreen()->GetScalingFactor();
|
|
|
|
|
|
|
|
wxPoint center = GetParent()->GetScreen()->GetScrollCenterPosition();
|
// Dick Hollenbeck's KiROUND R&D
// This provides better project control over rounding to int from double
// than wxRound() did. This scheme provides better logging in Debug builds
// and it provides for compile time calculation of constants.
#include <stdio.h>
#include <assert.h>
#include <limits.h>
//-----<KiROUND KIT>------------------------------------------------------------
/**
* KiROUND
* rounds a floating point number to an int using
* "round halfway cases away from zero".
* In Debug build an assert fires if will not fit into an int.
*/
#if defined( DEBUG )
// DEBUG: a macro to capture line and file, then calls this inline
static inline int KiRound( double v, int line, const char* filename )
{
v = v < 0 ? v - 0.5 : v + 0.5;
if( v > INT_MAX + 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n", __FUNCTION__, filename, line, v );
}
else if( v < INT_MIN - 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n", __FUNCTION__, filename, line, v );
}
return int( v );
}
#define KiROUND( v ) KiRound( v, __LINE__, __FILE__ )
#else
// RELEASE: a macro so compile can pre-compute constants.
#define KiROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 )
#endif
//-----</KiROUND KIT>-----------------------------------------------------------
// Only a macro is compile time calculated, an inline function causes a static constructor
// in a situation like this.
// Therefore the Release build is best done with a MACRO not an inline function.
int Computed = KiROUND( 14.3 * 8 );
int main( int argc, char** argv )
{
for( double d = double(INT_MAX)-1; d < double(INT_MAX)+8; d += 2.0 )
{
int i = KiROUND( d );
printf( "t: %d %.16g\n", i, d );
}
return 0;
}
2012-04-19 06:55:45 +00:00
|
|
|
center.x += KiROUND( (double) ( x - tmpX ) / scale );
|
|
|
|
center.y += KiROUND( (double) ( y - tmpY ) / scale );
|
2012-04-12 07:58:12 +00:00
|
|
|
GetParent()->GetScreen()->SetScrollCenterPosition( center );
|
|
|
|
|
2012-04-11 18:54:20 +00:00
|
|
|
Scroll( x, y );
|
2007-08-22 05:11:01 +00:00
|
|
|
event.Skip();
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2010-02-22 16:45:35 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
void EDA_DRAW_PANEL::SetClipBox( wxDC& aDC, const wxRect* aRect )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2011-01-30 22:22:38 +00:00
|
|
|
wxRect clipBox;
|
|
|
|
|
|
|
|
// Use the entire visible device area if no clip area was defined.
|
|
|
|
if( aRect == NULL )
|
|
|
|
{
|
|
|
|
BASE_SCREEN* Screen = GetScreen();
|
2010-02-08 18:15:42 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
if( !Screen )
|
|
|
|
return;
|
2008-03-10 08:14:20 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
Screen->m_StartVisu = CalcUnscrolledPosition( wxPoint( 0, 0 ) );
|
|
|
|
clipBox.SetSize( GetClientSize() );
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
int scrollX, scrollY;
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
double scalar = Screen->GetScalingFactor();
|
// Dick Hollenbeck's KiROUND R&D
// This provides better project control over rounding to int from double
// than wxRound() did. This scheme provides better logging in Debug builds
// and it provides for compile time calculation of constants.
#include <stdio.h>
#include <assert.h>
#include <limits.h>
//-----<KiROUND KIT>------------------------------------------------------------
/**
* KiROUND
* rounds a floating point number to an int using
* "round halfway cases away from zero".
* In Debug build an assert fires if will not fit into an int.
*/
#if defined( DEBUG )
// DEBUG: a macro to capture line and file, then calls this inline
static inline int KiRound( double v, int line, const char* filename )
{
v = v < 0 ? v - 0.5 : v + 0.5;
if( v > INT_MAX + 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n", __FUNCTION__, filename, line, v );
}
else if( v < INT_MIN - 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n", __FUNCTION__, filename, line, v );
}
return int( v );
}
#define KiROUND( v ) KiRound( v, __LINE__, __FILE__ )
#else
// RELEASE: a macro so compile can pre-compute constants.
#define KiROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 )
#endif
//-----</KiROUND KIT>-----------------------------------------------------------
// Only a macro is compile time calculated, an inline function causes a static constructor
// in a situation like this.
// Therefore the Release build is best done with a MACRO not an inline function.
int Computed = KiROUND( 14.3 * 8 );
int main( int argc, char** argv )
{
for( double d = double(INT_MAX)-1; d < double(INT_MAX)+8; d += 2.0 )
{
int i = KiROUND( d );
printf( "t: %d %.16g\n", i, d );
}
return 0;
}
2012-04-19 06:55:45 +00:00
|
|
|
scrollX = KiROUND( Screen->GetGridSize().x * scalar );
|
|
|
|
scrollY = KiROUND( Screen->GetGridSize().y * scalar );
|
2010-02-08 18:15:42 +00:00
|
|
|
|
2012-09-22 11:19:37 +00:00
|
|
|
m_scrollIncrementX = std::max( GetClientSize().x / 8, scrollX );
|
|
|
|
m_scrollIncrementY = std::max( GetClientSize().y / 8, scrollY );
|
2011-01-30 22:22:38 +00:00
|
|
|
Screen->m_ScrollbarPos.x = GetScrollPos( wxHORIZONTAL );
|
|
|
|
Screen->m_ScrollbarPos.y = GetScrollPos( wxVERTICAL );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
clipBox = *aRect;
|
|
|
|
}
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
// Pad clip box in device units.
|
|
|
|
clipBox.Inflate( CLIP_BOX_PADDING );
|
2010-02-08 18:15:42 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
// Convert from device units to drawing units.
|
2011-12-21 13:42:02 +00:00
|
|
|
m_ClipBox.SetOrigin( wxPoint( aDC.DeviceToLogicalX( clipBox.x ),
|
|
|
|
aDC.DeviceToLogicalY( clipBox.y ) ) );
|
|
|
|
m_ClipBox.SetSize( wxSize( aDC.DeviceToLogicalXRel( clipBox.width ),
|
|
|
|
aDC.DeviceToLogicalYRel( clipBox.height ) ) );
|
2010-02-08 18:15:42 +00:00
|
|
|
|
2011-02-09 19:47:33 +00:00
|
|
|
wxLogTrace( KICAD_TRACE_COORDS,
|
|
|
|
wxT( "Device clip box=(%d, %d, %d, %d), Logical clip box=(%d, %d, %d, %d)" ),
|
2011-01-30 22:22:38 +00:00
|
|
|
clipBox.x, clipBox.y, clipBox.width, clipBox.height,
|
2011-12-21 13:42:02 +00:00
|
|
|
m_ClipBox.GetX(), m_ClipBox.GetY(), m_ClipBox.GetWidth(), m_ClipBox.GetHeight() );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-21 19:30:59 +00:00
|
|
|
void EDA_DRAW_PANEL::EraseScreen( wxDC* DC )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2007-08-22 05:11:01 +00:00
|
|
|
GRSetDrawMode( DC, GR_COPY );
|
2008-03-10 15:51:44 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
GRSFilledRect( NULL, DC, m_ClipBox.GetX(), m_ClipBox.GetY(),
|
2009-04-15 19:53:41 +00:00
|
|
|
m_ClipBox.GetRight(), m_ClipBox.GetBottom(),
|
2009-12-30 18:06:12 +00:00
|
|
|
0, g_DrawBgColor, g_DrawBgColor );
|
2010-02-22 16:45:35 +00:00
|
|
|
|
2012-04-23 21:56:26 +00:00
|
|
|
// Set to one (1) to draw bounding box validate bounding box calculation.
|
2010-02-22 16:45:35 +00:00
|
|
|
#if DEBUG_SHOW_CLIP_RECT
|
2011-03-29 19:33:07 +00:00
|
|
|
EDA_RECT bBox = m_ClipBox;
|
2010-02-22 16:45:35 +00:00
|
|
|
GRRect( NULL, DC, bBox.GetOrigin().x, bBox.GetOrigin().y,
|
|
|
|
bBox.GetEnd().x, bBox.GetEnd().y, 0, LIGHTMAGENTA );
|
|
|
|
#endif
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
void EDA_DRAW_PANEL::DoPrepareDC( wxDC& dc )
|
2010-02-08 18:15:42 +00:00
|
|
|
{
|
2011-01-30 22:22:38 +00:00
|
|
|
wxScrolledWindow::DoPrepareDC( dc );
|
|
|
|
|
2010-02-08 18:15:42 +00:00
|
|
|
if( GetScreen() != NULL )
|
|
|
|
{
|
|
|
|
double scale = GetScreen()->GetScalingFactor();
|
2010-02-22 16:45:35 +00:00
|
|
|
dc.SetUserScale( scale, scale );
|
2010-01-17 14:20:29 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
wxPoint pt = GetScreen()->m_DrawOrg;
|
2010-02-22 16:45:35 +00:00
|
|
|
dc.SetLogicalOrigin( pt.x, pt.y );
|
2010-02-08 18:15:42 +00:00
|
|
|
}
|
2009-01-04 18:52:57 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
SetClipBox( dc ); // Reset the clip box to the entire screen.
|
2010-02-08 18:15:42 +00:00
|
|
|
GRResetPenAndBrush( &dc );
|
|
|
|
dc.SetBackgroundMode( wxTRANSPARENT );
|
|
|
|
}
|
|
|
|
|
2009-11-23 15:16:50 +00:00
|
|
|
|
2011-01-21 19:30:59 +00:00
|
|
|
void EDA_DRAW_PANEL::OnPaint( wxPaintEvent& event )
|
2008-03-06 01:46:30 +00:00
|
|
|
{
|
2009-06-26 17:24:32 +00:00
|
|
|
if( GetScreen() == NULL )
|
|
|
|
{
|
|
|
|
event.Skip();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-02-08 18:15:42 +00:00
|
|
|
INSTALL_PAINTDC( paintDC, this );
|
2010-01-17 14:20:29 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
wxRect region = GetUpdateRegion().GetBox();
|
|
|
|
SetClipBox( paintDC, ®ion );
|
2011-02-08 14:48:38 +00:00
|
|
|
ReDraw( &paintDC, true );
|
2008-03-06 01:46:30 +00:00
|
|
|
}
|
|
|
|
|
2008-03-10 08:14:20 +00:00
|
|
|
|
2011-01-21 19:30:59 +00:00
|
|
|
void EDA_DRAW_PANEL::ReDraw( wxDC* DC, bool erasebg )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2007-08-22 05:11:01 +00:00
|
|
|
BASE_SCREEN* Screen = GetScreen();
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2007-08-22 05:11:01 +00:00
|
|
|
if( Screen == NULL )
|
2007-08-15 02:43:57 +00:00
|
|
|
return;
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2008-12-05 16:03:05 +00:00
|
|
|
if( ( g_DrawBgColor != WHITE ) && ( g_DrawBgColor != BLACK ) )
|
2007-08-15 02:43:57 +00:00
|
|
|
g_DrawBgColor = BLACK;
|
2007-08-22 05:11:01 +00:00
|
|
|
|
|
|
|
if( g_DrawBgColor == WHITE )
|
|
|
|
{
|
|
|
|
g_XorMode = GR_NXOR;
|
|
|
|
g_GhostColor = BLACK;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_XorMode = GR_XOR;
|
|
|
|
g_GhostColor = WHITE;
|
|
|
|
}
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2007-08-22 05:11:01 +00:00
|
|
|
if( erasebg )
|
2009-04-15 19:53:41 +00:00
|
|
|
EraseScreen( DC );
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2007-08-22 05:11:01 +00:00
|
|
|
GRResetPenAndBrush( DC );
|
|
|
|
|
|
|
|
DC->SetBackground( *wxBLACK_BRUSH );
|
2011-02-08 14:48:38 +00:00
|
|
|
DC->SetBackgroundMode( wxSOLID );
|
2011-02-09 19:47:33 +00:00
|
|
|
GetParent()->RedrawActiveWindow( DC, erasebg );
|
2011-02-08 14:48:38 +00:00
|
|
|
|
|
|
|
// Verfies that the clipping is working correctly. If these two sets of numbers are
|
|
|
|
// not the same or really close. The clipping algorithms are broken.
|
|
|
|
wxLogTrace( KICAD_TRACE_COORDS,
|
|
|
|
wxT( "Clip box: (%d, %d, %d, %d), Draw extents (%d, %d, %d, %d)" ),
|
|
|
|
m_ClipBox.GetX(), m_ClipBox.GetY(), m_ClipBox.GetRight(), m_ClipBox.GetBottom(),
|
|
|
|
DC->MinX(), DC->MinY(), DC->MaxX(), DC->MaxY() );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-15 02:43:57 +00:00
|
|
|
|
2011-01-21 19:30:59 +00:00
|
|
|
void EDA_DRAW_PANEL::DrawBackGround( wxDC* DC )
|
2010-01-17 14:20:29 +00:00
|
|
|
{
|
2012-09-02 12:06:47 +00:00
|
|
|
EDA_COLOR_T axis_color = BLUE;
|
2010-01-17 14:20:29 +00:00
|
|
|
|
|
|
|
GRSetDrawMode( DC, GR_COPY );
|
|
|
|
|
2011-02-09 19:47:33 +00:00
|
|
|
if( GetParent()->IsGridVisible() )
|
2010-01-17 14:20:29 +00:00
|
|
|
DrawGrid( DC );
|
|
|
|
|
2011-12-22 21:57:50 +00:00
|
|
|
// Draw axis
|
2011-12-14 20:03:15 +00:00
|
|
|
if( GetParent()->m_showAxis )
|
2010-01-17 14:20:29 +00:00
|
|
|
{
|
2011-12-22 21:57:50 +00:00
|
|
|
wxSize pageSize = GetParent()->GetPageSizeIU();
|
2010-01-17 14:20:29 +00:00
|
|
|
|
2011-12-22 21:57:50 +00:00
|
|
|
// Draw the Y axis
|
|
|
|
GRDashedLine( &m_ClipBox, DC, 0, -pageSize.y,
|
|
|
|
0, pageSize.y, 0, axis_color );
|
|
|
|
|
|
|
|
// Draw the X axis
|
|
|
|
GRDashedLine( &m_ClipBox, DC, -pageSize.x, 0,
|
|
|
|
pageSize.x, 0, 0, axis_color );
|
2010-01-17 14:20:29 +00:00
|
|
|
}
|
|
|
|
|
2011-12-14 20:03:15 +00:00
|
|
|
if( GetParent()->m_showOriginAxis )
|
2010-01-17 14:20:29 +00:00
|
|
|
DrawAuxiliaryAxis( DC, GR_COPY );
|
2010-07-13 10:42:32 +00:00
|
|
|
|
2011-12-14 20:03:15 +00:00
|
|
|
if( GetParent()->m_showGridAxis )
|
2010-07-13 10:42:32 +00:00
|
|
|
DrawGridAxis( DC, GR_COPY );
|
2010-01-17 14:20:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-09 19:47:33 +00:00
|
|
|
void EDA_DRAW_PANEL::DrawGrid( wxDC* aDC )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2010-09-23 14:04:08 +00:00
|
|
|
#define MIN_GRID_SIZE 10 // min grid size in pixels to allow drawing
|
2007-08-22 05:11:01 +00:00
|
|
|
BASE_SCREEN* screen = GetScreen();
|
2011-01-30 22:22:38 +00:00
|
|
|
wxRealPoint gridSize;
|
|
|
|
wxSize screenSize;
|
2007-08-22 05:11:01 +00:00
|
|
|
wxPoint org;
|
2011-01-30 22:22:38 +00:00
|
|
|
wxRealPoint screenGridSize;
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2007-12-09 09:00:15 +00:00
|
|
|
/* The grid must be visible. this is possible only is grid value
|
|
|
|
* and zoom value are sufficient
|
|
|
|
*/
|
2011-01-30 22:22:38 +00:00
|
|
|
gridSize = screen->GetGridSize();
|
|
|
|
screen->m_StartVisu = CalcUnscrolledPosition( wxPoint( 0, 0 ) );
|
|
|
|
screenSize = GetClientSize();
|
2010-02-08 18:15:42 +00:00
|
|
|
|
// Dick Hollenbeck's KiROUND R&D
// This provides better project control over rounding to int from double
// than wxRound() did. This scheme provides better logging in Debug builds
// and it provides for compile time calculation of constants.
#include <stdio.h>
#include <assert.h>
#include <limits.h>
//-----<KiROUND KIT>------------------------------------------------------------
/**
* KiROUND
* rounds a floating point number to an int using
* "round halfway cases away from zero".
* In Debug build an assert fires if will not fit into an int.
*/
#if defined( DEBUG )
// DEBUG: a macro to capture line and file, then calls this inline
static inline int KiRound( double v, int line, const char* filename )
{
v = v < 0 ? v - 0.5 : v + 0.5;
if( v > INT_MAX + 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n", __FUNCTION__, filename, line, v );
}
else if( v < INT_MIN - 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n", __FUNCTION__, filename, line, v );
}
return int( v );
}
#define KiROUND( v ) KiRound( v, __LINE__, __FILE__ )
#else
// RELEASE: a macro so compile can pre-compute constants.
#define KiROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 )
#endif
//-----</KiROUND KIT>-----------------------------------------------------------
// Only a macro is compile time calculated, an inline function causes a static constructor
// in a situation like this.
// Therefore the Release build is best done with a MACRO not an inline function.
int Computed = KiROUND( 14.3 * 8 );
int main( int argc, char** argv )
{
for( double d = double(INT_MAX)-1; d < double(INT_MAX)+8; d += 2.0 )
{
int i = KiROUND( d );
printf( "t: %d %.16g\n", i, d );
}
return 0;
}
2012-04-19 06:55:45 +00:00
|
|
|
screenGridSize.x = aDC->LogicalToDeviceXRel( KiROUND( gridSize.x ) );
|
|
|
|
screenGridSize.y = aDC->LogicalToDeviceYRel( KiROUND( gridSize.y ) );
|
2009-02-26 20:06:51 +00:00
|
|
|
|
2011-12-21 13:42:02 +00:00
|
|
|
org = m_ClipBox.GetPosition();
|
2010-01-17 14:20:29 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
if( screenGridSize.x < MIN_GRID_SIZE || screenGridSize.y < MIN_GRID_SIZE )
|
2007-08-22 05:11:01 +00:00
|
|
|
{
|
2011-01-30 22:22:38 +00:00
|
|
|
screenGridSize.x *= 2.0;
|
|
|
|
screenGridSize.y *= 2.0;
|
|
|
|
gridSize.x *= 2.0;
|
|
|
|
gridSize.y *= 2.0;
|
2007-08-22 05:11:01 +00:00
|
|
|
}
|
2007-12-09 09:00:15 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
if( screenGridSize.x < MIN_GRID_SIZE || screenGridSize.y < MIN_GRID_SIZE )
|
|
|
|
return;
|
2010-01-17 14:20:29 +00:00
|
|
|
|
2011-02-11 20:48:13 +00:00
|
|
|
org = screen->GetNearestGridPosition( org, &gridSize );
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2011-01-31 18:26:12 +00:00
|
|
|
// Setting the nearest grid position can select grid points outside the clip box.
|
|
|
|
// Incrementing the start point by one grid step should prevent drawing grid points
|
|
|
|
// outside the clip box.
|
|
|
|
if( org.x < m_ClipBox.GetX() )
|
// Dick Hollenbeck's KiROUND R&D
// This provides better project control over rounding to int from double
// than wxRound() did. This scheme provides better logging in Debug builds
// and it provides for compile time calculation of constants.
#include <stdio.h>
#include <assert.h>
#include <limits.h>
//-----<KiROUND KIT>------------------------------------------------------------
/**
* KiROUND
* rounds a floating point number to an int using
* "round halfway cases away from zero".
* In Debug build an assert fires if will not fit into an int.
*/
#if defined( DEBUG )
// DEBUG: a macro to capture line and file, then calls this inline
static inline int KiRound( double v, int line, const char* filename )
{
v = v < 0 ? v - 0.5 : v + 0.5;
if( v > INT_MAX + 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n", __FUNCTION__, filename, line, v );
}
else if( v < INT_MIN - 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n", __FUNCTION__, filename, line, v );
}
return int( v );
}
#define KiROUND( v ) KiRound( v, __LINE__, __FILE__ )
#else
// RELEASE: a macro so compile can pre-compute constants.
#define KiROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 )
#endif
//-----</KiROUND KIT>-----------------------------------------------------------
// Only a macro is compile time calculated, an inline function causes a static constructor
// in a situation like this.
// Therefore the Release build is best done with a MACRO not an inline function.
int Computed = KiROUND( 14.3 * 8 );
int main( int argc, char** argv )
{
for( double d = double(INT_MAX)-1; d < double(INT_MAX)+8; d += 2.0 )
{
int i = KiROUND( d );
printf( "t: %d %.16g\n", i, d );
}
return 0;
}
2012-04-19 06:55:45 +00:00
|
|
|
org.x += KiROUND( gridSize.x );
|
2011-01-31 18:26:12 +00:00
|
|
|
|
|
|
|
if( org.y < m_ClipBox.GetY() )
|
// Dick Hollenbeck's KiROUND R&D
// This provides better project control over rounding to int from double
// than wxRound() did. This scheme provides better logging in Debug builds
// and it provides for compile time calculation of constants.
#include <stdio.h>
#include <assert.h>
#include <limits.h>
//-----<KiROUND KIT>------------------------------------------------------------
/**
* KiROUND
* rounds a floating point number to an int using
* "round halfway cases away from zero".
* In Debug build an assert fires if will not fit into an int.
*/
#if defined( DEBUG )
// DEBUG: a macro to capture line and file, then calls this inline
static inline int KiRound( double v, int line, const char* filename )
{
v = v < 0 ? v - 0.5 : v + 0.5;
if( v > INT_MAX + 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n", __FUNCTION__, filename, line, v );
}
else if( v < INT_MIN - 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n", __FUNCTION__, filename, line, v );
}
return int( v );
}
#define KiROUND( v ) KiRound( v, __LINE__, __FILE__ )
#else
// RELEASE: a macro so compile can pre-compute constants.
#define KiROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 )
#endif
//-----</KiROUND KIT>-----------------------------------------------------------
// Only a macro is compile time calculated, an inline function causes a static constructor
// in a situation like this.
// Therefore the Release build is best done with a MACRO not an inline function.
int Computed = KiROUND( 14.3 * 8 );
int main( int argc, char** argv )
{
for( double d = double(INT_MAX)-1; d < double(INT_MAX)+8; d += 2.0 )
{
int i = KiROUND( d );
printf( "t: %d %.16g\n", i, d );
}
return 0;
}
2012-04-19 06:55:45 +00:00
|
|
|
org.y += KiROUND( gridSize.y );
|
2011-01-31 18:26:12 +00:00
|
|
|
|
2011-02-23 13:48:19 +00:00
|
|
|
#if ( defined( __WXMAC__ ) || 1 )
|
2011-02-09 19:47:33 +00:00
|
|
|
// Use a pixel based draw to display grid. There are a lot of calls, so the cost is
|
|
|
|
// high and grid is slowly drawn on some platforms. Please note that this should
|
|
|
|
// always be enabled until the bitmap based solution below is fixed.
|
2012-01-10 22:27:31 +00:00
|
|
|
#ifndef __WXMAC__
|
2011-02-09 19:47:33 +00:00
|
|
|
GRSetColorPen( aDC, GetParent()->GetGridColor() );
|
2012-01-10 22:27:31 +00:00
|
|
|
#else
|
|
|
|
// On mac (Cocoa), a point isn't a pixel and being of size 1 don't survive to antialiasing
|
|
|
|
GRSetColorPen( aDC, GetParent()->GetGridColor(), aDC->DeviceToLogicalXRel(2) );
|
|
|
|
#endif
|
2010-01-13 20:03:33 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
int xpos;
|
|
|
|
double right = ( double ) m_ClipBox.GetRight();
|
|
|
|
double bottom = ( double ) m_ClipBox.GetBottom();
|
2010-01-14 08:55:45 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
for( double x = (double) org.x; x <= right; x += gridSize.x )
|
2010-09-19 10:23:53 +00:00
|
|
|
{
|
// Dick Hollenbeck's KiROUND R&D
// This provides better project control over rounding to int from double
// than wxRound() did. This scheme provides better logging in Debug builds
// and it provides for compile time calculation of constants.
#include <stdio.h>
#include <assert.h>
#include <limits.h>
//-----<KiROUND KIT>------------------------------------------------------------
/**
* KiROUND
* rounds a floating point number to an int using
* "round halfway cases away from zero".
* In Debug build an assert fires if will not fit into an int.
*/
#if defined( DEBUG )
// DEBUG: a macro to capture line and file, then calls this inline
static inline int KiRound( double v, int line, const char* filename )
{
v = v < 0 ? v - 0.5 : v + 0.5;
if( v > INT_MAX + 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n", __FUNCTION__, filename, line, v );
}
else if( v < INT_MIN - 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n", __FUNCTION__, filename, line, v );
}
return int( v );
}
#define KiROUND( v ) KiRound( v, __LINE__, __FILE__ )
#else
// RELEASE: a macro so compile can pre-compute constants.
#define KiROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 )
#endif
//-----</KiROUND KIT>-----------------------------------------------------------
// Only a macro is compile time calculated, an inline function causes a static constructor
// in a situation like this.
// Therefore the Release build is best done with a MACRO not an inline function.
int Computed = KiROUND( 14.3 * 8 );
int main( int argc, char** argv )
{
for( double d = double(INT_MAX)-1; d < double(INT_MAX)+8; d += 2.0 )
{
int i = KiROUND( d );
printf( "t: %d %.16g\n", i, d );
}
return 0;
}
2012-04-19 06:55:45 +00:00
|
|
|
xpos = KiROUND( x );
|
2010-09-19 10:23:53 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
for( double y = (double) org.y; y <= bottom; y += gridSize.y )
|
2010-01-13 20:03:33 +00:00
|
|
|
{
|
// Dick Hollenbeck's KiROUND R&D
// This provides better project control over rounding to int from double
// than wxRound() did. This scheme provides better logging in Debug builds
// and it provides for compile time calculation of constants.
#include <stdio.h>
#include <assert.h>
#include <limits.h>
//-----<KiROUND KIT>------------------------------------------------------------
/**
* KiROUND
* rounds a floating point number to an int using
* "round halfway cases away from zero".
* In Debug build an assert fires if will not fit into an int.
*/
#if defined( DEBUG )
// DEBUG: a macro to capture line and file, then calls this inline
static inline int KiRound( double v, int line, const char* filename )
{
v = v < 0 ? v - 0.5 : v + 0.5;
if( v > INT_MAX + 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n", __FUNCTION__, filename, line, v );
}
else if( v < INT_MIN - 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n", __FUNCTION__, filename, line, v );
}
return int( v );
}
#define KiROUND( v ) KiRound( v, __LINE__, __FILE__ )
#else
// RELEASE: a macro so compile can pre-compute constants.
#define KiROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 )
#endif
//-----</KiROUND KIT>-----------------------------------------------------------
// Only a macro is compile time calculated, an inline function causes a static constructor
// in a situation like this.
// Therefore the Release build is best done with a MACRO not an inline function.
int Computed = KiROUND( 14.3 * 8 );
int main( int argc, char** argv )
{
for( double d = double(INT_MAX)-1; d < double(INT_MAX)+8; d += 2.0 )
{
int i = KiROUND( d );
printf( "t: %d %.16g\n", i, d );
}
return 0;
}
2012-04-19 06:55:45 +00:00
|
|
|
aDC->DrawPoint( xpos, KiROUND( y ) );
|
2010-01-13 20:03:33 +00:00
|
|
|
}
|
2007-08-22 05:11:01 +00:00
|
|
|
}
|
2010-01-17 14:20:29 +00:00
|
|
|
#else
|
2011-02-09 19:47:33 +00:00
|
|
|
/* This is fast only if the Blit function is fast. Not true on all platforms.
|
2011-01-30 22:22:38 +00:00
|
|
|
*
|
|
|
|
* A first grid column is drawn in a temporary bitmap, and after is duplicated using
|
|
|
|
* the Blit function (copy from a screen area to an other screen area).
|
2010-01-17 14:20:29 +00:00
|
|
|
*/
|
2010-01-24 16:27:36 +00:00
|
|
|
wxMemoryDC tmpDC;
|
2011-02-09 19:47:33 +00:00
|
|
|
wxBitmap tmpBM( 1, aDC->LogicalToDeviceYRel( m_ClipBox.GetHeight() ) );
|
|
|
|
tmpDC.SelectObject( tmpBM );
|
|
|
|
tmpDC.SetLogicalFunction( wxCOPY );
|
|
|
|
tmpDC.SetBackground( wxBrush( GetBackgroundColour() ) );
|
|
|
|
tmpDC.Clear();
|
|
|
|
tmpDC.SetPen( MakeColour( GetParent()->GetGridColor() ) );
|
|
|
|
|
|
|
|
double usx, usy;
|
|
|
|
int lox, loy, dox, doy;
|
|
|
|
|
|
|
|
aDC->GetUserScale( &usx, &usy );
|
|
|
|
aDC->GetLogicalOrigin( &lox, &loy );
|
|
|
|
aDC->GetDeviceOrigin( &dox, &doy );
|
|
|
|
|
|
|
|
// Create a dummy DC for coordinate translation because the actual DC scale and origin
|
|
|
|
// must be reset in order to work correctly.
|
|
|
|
wxBitmap tmpBitmap( 1, 1 );
|
|
|
|
wxMemoryDC scaleDC( tmpBitmap );
|
|
|
|
scaleDC.SetUserScale( usx, usy );
|
|
|
|
scaleDC.SetLogicalOrigin( lox, loy );
|
|
|
|
scaleDC.SetDeviceOrigin( dox, doy );
|
2011-01-30 22:22:38 +00:00
|
|
|
|
|
|
|
double bottom = ( double ) m_ClipBox.GetBottom();
|
|
|
|
|
2011-02-09 19:47:33 +00:00
|
|
|
// Draw a column of grid points.
|
|
|
|
for( double y = (double) org.y; y <= bottom; y += gridSize.y )
|
2010-01-17 14:20:29 +00:00
|
|
|
{
|
// Dick Hollenbeck's KiROUND R&D
// This provides better project control over rounding to int from double
// than wxRound() did. This scheme provides better logging in Debug builds
// and it provides for compile time calculation of constants.
#include <stdio.h>
#include <assert.h>
#include <limits.h>
//-----<KiROUND KIT>------------------------------------------------------------
/**
* KiROUND
* rounds a floating point number to an int using
* "round halfway cases away from zero".
* In Debug build an assert fires if will not fit into an int.
*/
#if defined( DEBUG )
// DEBUG: a macro to capture line and file, then calls this inline
static inline int KiRound( double v, int line, const char* filename )
{
v = v < 0 ? v - 0.5 : v + 0.5;
if( v > INT_MAX + 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n", __FUNCTION__, filename, line, v );
}
else if( v < INT_MIN - 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n", __FUNCTION__, filename, line, v );
}
return int( v );
}
#define KiROUND( v ) KiRound( v, __LINE__, __FILE__ )
#else
// RELEASE: a macro so compile can pre-compute constants.
#define KiROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 )
#endif
//-----</KiROUND KIT>-----------------------------------------------------------
// Only a macro is compile time calculated, an inline function causes a static constructor
// in a situation like this.
// Therefore the Release build is best done with a MACRO not an inline function.
int Computed = KiROUND( 14.3 * 8 );
int main( int argc, char** argv )
{
for( double d = double(INT_MAX)-1; d < double(INT_MAX)+8; d += 2.0 )
{
int i = KiROUND( d );
printf( "t: %d %.16g\n", i, d );
}
return 0;
}
2012-04-19 06:55:45 +00:00
|
|
|
tmpDC.DrawPoint( 0, scaleDC.LogicalToDeviceY( KiROUND( y ) ) );
|
2010-01-17 14:20:29 +00:00
|
|
|
}
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2011-02-09 19:47:33 +00:00
|
|
|
// Reset the device context scale and origin and restore on exit.
|
|
|
|
EDA_BLIT_NORMALIZER blitNorm( aDC );
|
|
|
|
|
|
|
|
// Mask of everything but the grid points.
|
2010-12-18 16:09:06 +00:00
|
|
|
tmpDC.SelectObject( wxNullBitmap );
|
2011-02-09 19:47:33 +00:00
|
|
|
tmpBM.SetMask( new wxMask( tmpBM, GetBackgroundColour() ) );
|
2010-12-18 16:09:06 +00:00
|
|
|
tmpDC.SelectObject( tmpBM );
|
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
double right = m_ClipBox.GetRight();
|
|
|
|
|
2011-02-09 19:47:33 +00:00
|
|
|
// Blit the column for each row of the damaged region.
|
2011-01-30 22:22:38 +00:00
|
|
|
for( double x = (double) org.x; x <= right; x += gridSize.x )
|
2010-01-17 14:20:29 +00:00
|
|
|
{
|
// Dick Hollenbeck's KiROUND R&D
// This provides better project control over rounding to int from double
// than wxRound() did. This scheme provides better logging in Debug builds
// and it provides for compile time calculation of constants.
#include <stdio.h>
#include <assert.h>
#include <limits.h>
//-----<KiROUND KIT>------------------------------------------------------------
/**
* KiROUND
* rounds a floating point number to an int using
* "round halfway cases away from zero".
* In Debug build an assert fires if will not fit into an int.
*/
#if defined( DEBUG )
// DEBUG: a macro to capture line and file, then calls this inline
static inline int KiRound( double v, int line, const char* filename )
{
v = v < 0 ? v - 0.5 : v + 0.5;
if( v > INT_MAX + 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n", __FUNCTION__, filename, line, v );
}
else if( v < INT_MIN - 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n", __FUNCTION__, filename, line, v );
}
return int( v );
}
#define KiROUND( v ) KiRound( v, __LINE__, __FILE__ )
#else
// RELEASE: a macro so compile can pre-compute constants.
#define KiROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 )
#endif
//-----</KiROUND KIT>-----------------------------------------------------------
// Only a macro is compile time calculated, an inline function causes a static constructor
// in a situation like this.
// Therefore the Release build is best done with a MACRO not an inline function.
int Computed = KiROUND( 14.3 * 8 );
int main( int argc, char** argv )
{
for( double d = double(INT_MAX)-1; d < double(INT_MAX)+8; d += 2.0 )
{
int i = KiROUND( d );
printf( "t: %d %.16g\n", i, d );
}
return 0;
}
2012-04-19 06:55:45 +00:00
|
|
|
aDC->Blit( scaleDC.LogicalToDeviceX( KiROUND( x ) ),
|
2011-12-21 13:42:02 +00:00
|
|
|
scaleDC.LogicalToDeviceY( m_ClipBox.GetY() ),
|
2011-02-09 19:47:33 +00:00
|
|
|
1, tmpBM.GetHeight(), &tmpDC, 0, 0, wxCOPY, true );
|
2007-08-22 05:11:01 +00:00
|
|
|
}
|
2010-01-17 14:20:29 +00:00
|
|
|
#endif
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2012-09-01 13:38:27 +00:00
|
|
|
void EDA_DRAW_PANEL::DrawAuxiliaryAxis( wxDC* aDC, GR_DRAWMODE aDrawMode )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2011-12-31 05:44:00 +00:00
|
|
|
wxPoint origin = GetParent()->GetOriginAxisPosition();
|
|
|
|
|
|
|
|
if( origin == wxPoint( 0, 0 ) )
|
2007-08-22 05:11:01 +00:00
|
|
|
return;
|
|
|
|
|
2012-09-02 12:06:47 +00:00
|
|
|
EDA_COLOR_T color = DARKRED;
|
2011-12-22 21:57:50 +00:00
|
|
|
wxSize pageSize = GetParent()->GetPageSizeIU();
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2010-12-29 17:47:32 +00:00
|
|
|
GRSetDrawMode( aDC, aDrawMode );
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2011-12-22 21:57:50 +00:00
|
|
|
// Draw the Y axis
|
2010-12-29 17:47:32 +00:00
|
|
|
GRDashedLine( &m_ClipBox, aDC,
|
2011-12-31 05:44:00 +00:00
|
|
|
origin.x,
|
2011-12-22 21:57:50 +00:00
|
|
|
-pageSize.y,
|
2011-12-31 05:44:00 +00:00
|
|
|
origin.x,
|
2011-12-22 21:57:50 +00:00
|
|
|
pageSize.y,
|
|
|
|
0, color );
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2011-12-22 21:57:50 +00:00
|
|
|
// Draw the X axis
|
2010-12-29 17:47:32 +00:00
|
|
|
GRDashedLine( &m_ClipBox, aDC,
|
2011-12-22 21:57:50 +00:00
|
|
|
-pageSize.x,
|
2011-12-31 05:44:00 +00:00
|
|
|
origin.y,
|
2011-12-22 21:57:50 +00:00
|
|
|
pageSize.x,
|
2011-12-31 05:44:00 +00:00
|
|
|
origin.y,
|
2011-12-22 21:57:50 +00:00
|
|
|
0, color );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2011-01-21 19:30:59 +00:00
|
|
|
|
2012-09-01 13:38:27 +00:00
|
|
|
void EDA_DRAW_PANEL::DrawGridAxis( wxDC* aDC, GR_DRAWMODE aDrawMode )
|
2010-07-13 10:42:32 +00:00
|
|
|
{
|
|
|
|
BASE_SCREEN* screen = GetScreen();
|
2011-01-30 22:22:38 +00:00
|
|
|
|
2011-12-14 20:03:15 +00:00
|
|
|
if( !GetParent()->m_showGridAxis
|
2011-01-30 22:22:38 +00:00
|
|
|
|| ( screen->m_GridOrigin.x == 0 && screen->m_GridOrigin.y == 0 ) )
|
2010-07-13 10:42:32 +00:00
|
|
|
return;
|
|
|
|
|
2012-09-02 12:06:47 +00:00
|
|
|
EDA_COLOR_T color = GetParent()->GetGridColor();
|
2011-12-22 21:57:50 +00:00
|
|
|
wxSize pageSize = GetParent()->GetPageSizeIU();
|
2010-07-13 10:42:32 +00:00
|
|
|
|
2010-12-29 17:47:32 +00:00
|
|
|
GRSetDrawMode( aDC, aDrawMode );
|
2010-07-13 10:42:32 +00:00
|
|
|
|
2011-12-22 21:57:50 +00:00
|
|
|
// Draw the Y axis
|
2010-12-29 17:47:32 +00:00
|
|
|
GRDashedLine( &m_ClipBox, aDC,
|
2010-07-13 10:42:32 +00:00
|
|
|
screen->m_GridOrigin.x,
|
2011-12-22 21:57:50 +00:00
|
|
|
-pageSize.y,
|
2010-07-13 10:42:32 +00:00
|
|
|
screen->m_GridOrigin.x,
|
2011-12-22 21:57:50 +00:00
|
|
|
pageSize.y,
|
|
|
|
0, color );
|
2010-07-13 10:42:32 +00:00
|
|
|
|
2011-12-22 21:57:50 +00:00
|
|
|
// Draw the X axis
|
2010-12-29 17:47:32 +00:00
|
|
|
GRDashedLine( &m_ClipBox, aDC,
|
2011-12-22 21:57:50 +00:00
|
|
|
-pageSize.x,
|
2010-07-13 10:42:32 +00:00
|
|
|
screen->m_GridOrigin.y,
|
2011-12-22 21:57:50 +00:00
|
|
|
pageSize.x,
|
2010-07-13 10:42:32 +00:00
|
|
|
screen->m_GridOrigin.y,
|
2011-12-22 21:57:50 +00:00
|
|
|
0, color );
|
2010-07-13 10:42:32 +00:00
|
|
|
}
|
2007-08-15 02:43:57 +00:00
|
|
|
|
2011-01-21 19:30:59 +00:00
|
|
|
|
|
|
|
bool EDA_DRAW_PANEL::OnRightClick( wxMouseEvent& event )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2007-08-22 05:11:01 +00:00
|
|
|
wxPoint pos;
|
|
|
|
wxMenu MasterMenu;
|
|
|
|
|
2011-02-02 19:01:21 +00:00
|
|
|
INSTALL_UNBUFFERED_DC( dc, this );
|
|
|
|
|
|
|
|
pos = event.GetLogicalPosition( dc );
|
2007-12-09 09:00:15 +00:00
|
|
|
|
2011-02-09 19:47:33 +00:00
|
|
|
if( !GetParent()->OnRightClick( pos, &MasterMenu ) )
|
2007-12-09 09:00:15 +00:00
|
|
|
return false;
|
|
|
|
|
2011-02-09 19:47:33 +00:00
|
|
|
GetParent()->AddMenuZoomAndGrid( &MasterMenu );
|
2007-12-09 09:00:15 +00:00
|
|
|
|
2011-02-02 19:01:21 +00:00
|
|
|
pos = event.GetPosition();
|
2011-12-29 20:11:42 +00:00
|
|
|
m_ignoreMouseEvents = true;
|
2007-08-22 05:11:01 +00:00
|
|
|
PopupMenu( &MasterMenu, pos );
|
2011-02-11 20:48:13 +00:00
|
|
|
MoveCursorToCrossHair();
|
2011-12-29 20:11:42 +00:00
|
|
|
m_ignoreMouseEvents = false;
|
2007-12-09 09:00:15 +00:00
|
|
|
|
|
|
|
return true;
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-21 19:30:59 +00:00
|
|
|
void EDA_DRAW_PANEL::OnMouseLeaving( wxMouseEvent& event )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2011-02-11 20:48:13 +00:00
|
|
|
if( m_mouseCaptureCallback == NULL ) // No command in progress.
|
2011-12-29 20:11:42 +00:00
|
|
|
m_requestAutoPan = false;
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2011-12-29 20:11:42 +00:00
|
|
|
if( !m_enableAutoPan || !m_requestAutoPan || m_ignoreMouseEvents )
|
2007-08-22 05:11:01 +00:00
|
|
|
return;
|
|
|
|
|
2009-04-05 20:49:15 +00:00
|
|
|
// Auto pan if mouse is leave working area:
|
2007-08-22 05:11:01 +00:00
|
|
|
wxSize size = GetClientSize();
|
2009-01-07 15:59:49 +00:00
|
|
|
|
|
|
|
if( ( size.x < event.GetX() ) || ( size.y < event.GetY() )
|
2010-01-17 14:20:29 +00:00
|
|
|
|| ( event.GetX() <= 0) || ( event.GetY() <= 0 ) )
|
2009-01-07 15:59:49 +00:00
|
|
|
{
|
|
|
|
wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED, ID_POPUP_ZOOM_CENTER );
|
|
|
|
cmd.SetEventObject( this );
|
|
|
|
GetEventHandler()->ProcessEvent( cmd );
|
|
|
|
}
|
2011-02-21 13:54:29 +00:00
|
|
|
|
|
|
|
event.Skip();
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-21 19:30:59 +00:00
|
|
|
void EDA_DRAW_PANEL::OnMouseWheel( wxMouseEvent& event )
|
2008-12-19 13:51:48 +00:00
|
|
|
{
|
2011-12-29 20:11:42 +00:00
|
|
|
if( m_ignoreMouseEvents )
|
2010-01-15 10:02:47 +00:00
|
|
|
return;
|
|
|
|
|
2010-01-17 14:20:29 +00:00
|
|
|
wxRect rect = wxRect( wxPoint( 0, 0 ), GetClientSize() );
|
2009-01-07 15:59:49 +00:00
|
|
|
|
2012-04-23 21:56:26 +00:00
|
|
|
// Ignore scroll events if the cursor is outside the drawing area.
|
2009-01-07 15:59:49 +00:00
|
|
|
if( event.GetWheelRotation() == 0 || !GetParent()->IsEnabled()
|
2010-01-17 14:20:29 +00:00
|
|
|
|| !rect.Contains( event.GetPosition() ) )
|
2008-12-19 13:51:48 +00:00
|
|
|
{
|
2011-02-09 19:47:33 +00:00
|
|
|
wxLogTrace( KICAD_TRACE_COORDS,
|
|
|
|
wxT( "OnMouseWheel() position(%d, %d) rectangle(%d, %d, %d, %d)" ),
|
2009-01-17 20:31:19 +00:00
|
|
|
event.GetPosition().x, event.GetPosition().y,
|
|
|
|
rect.x, rect.y, rect.width, rect.height );
|
2008-12-19 13:51:48 +00:00
|
|
|
event.Skip();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-02-09 19:47:33 +00:00
|
|
|
INSTALL_UNBUFFERED_DC( dc, this );
|
2011-02-11 20:48:13 +00:00
|
|
|
GetScreen()->SetCrossHairPosition( event.GetLogicalPosition( dc ) );
|
2009-04-05 20:49:15 +00:00
|
|
|
|
2009-01-07 15:59:49 +00:00
|
|
|
wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED );
|
2008-12-19 13:51:48 +00:00
|
|
|
cmd.SetEventObject( this );
|
|
|
|
|
2009-01-07 15:59:49 +00:00
|
|
|
// This is a zoom in or out command
|
2008-12-19 13:51:48 +00:00
|
|
|
if( event.GetWheelRotation() > 0 )
|
|
|
|
{
|
|
|
|
if( event.ShiftDown() && !event.ControlDown() )
|
|
|
|
cmd.SetId( ID_PAN_UP );
|
|
|
|
else if( event.ControlDown() && !event.ShiftDown() )
|
|
|
|
cmd.SetId( ID_PAN_LEFT );
|
2013-02-21 20:53:50 +00:00
|
|
|
else if( (event.ControlDown() && event.ShiftDown() )
|
|
|
|
|| m_enableZoomNoCenter)
|
2013-02-02 19:10:48 +00:00
|
|
|
cmd.SetId( ID_OFFCENTER_ZOOM_IN );
|
2008-12-19 13:51:48 +00:00
|
|
|
else
|
|
|
|
cmd.SetId( ID_POPUP_ZOOM_IN );
|
|
|
|
}
|
2010-01-17 14:20:29 +00:00
|
|
|
else if( event.GetWheelRotation() < 0 )
|
2008-12-19 13:51:48 +00:00
|
|
|
{
|
|
|
|
if( event.ShiftDown() && !event.ControlDown() )
|
|
|
|
cmd.SetId( ID_PAN_DOWN );
|
|
|
|
else if( event.ControlDown() && !event.ShiftDown() )
|
|
|
|
cmd.SetId( ID_PAN_RIGHT );
|
2013-02-02 19:10:48 +00:00
|
|
|
else if( event.AltDown() || m_enableZoomNoCenter)
|
|
|
|
cmd.SetId( ID_OFFCENTER_ZOOM_OUT );
|
2008-12-19 13:51:48 +00:00
|
|
|
else
|
|
|
|
cmd.SetId( ID_POPUP_ZOOM_OUT );
|
|
|
|
}
|
|
|
|
|
|
|
|
GetEventHandler()->ProcessEvent( cmd );
|
2010-02-22 16:45:35 +00:00
|
|
|
event.Skip();
|
2008-12-19 13:51:48 +00:00
|
|
|
}
|
|
|
|
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2011-01-21 19:30:59 +00:00
|
|
|
void EDA_DRAW_PANEL::OnMouseEvent( wxMouseEvent& event )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2012-12-06 21:53:00 +00:00
|
|
|
int localrealbutt = 0, localbutt = 0;
|
|
|
|
BASE_SCREEN* screen = GetScreen();
|
2007-12-09 09:00:15 +00:00
|
|
|
|
2008-03-10 08:14:20 +00:00
|
|
|
if( !screen )
|
|
|
|
return;
|
2009-11-23 15:16:50 +00:00
|
|
|
|
|
|
|
/* Adjust value to filter mouse displacement before consider the drag
|
|
|
|
* mouse is really a drag command, not just a movement while click
|
|
|
|
*/
|
|
|
|
#define MIN_DRAG_COUNT_FOR_START_BLOCK_COMMAND 5
|
|
|
|
|
2010-09-23 14:04:08 +00:00
|
|
|
if( event.Leaving() )
|
2011-12-29 20:11:42 +00:00
|
|
|
m_canStartBlock = -1;
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2011-02-11 20:48:13 +00:00
|
|
|
if( !IsMouseCaptured() ) // No mouse capture in progress.
|
2011-12-29 20:11:42 +00:00
|
|
|
m_requestAutoPan = false;
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2011-10-13 19:56:32 +00:00
|
|
|
if( GetParent()->IsActive() )
|
2007-08-22 05:11:01 +00:00
|
|
|
SetFocus();
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
|
2011-02-22 16:43:03 +00:00
|
|
|
if( !event.IsButton() && !event.Moving() && !event.Dragging() )
|
2007-08-22 05:11:01 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
if( event.RightDown() )
|
|
|
|
{
|
2007-12-09 09:00:15 +00:00
|
|
|
OnRightClick( event );
|
2007-09-11 04:11:48 +00:00
|
|
|
return;
|
2007-08-22 05:11:01 +00:00
|
|
|
}
|
|
|
|
|
2011-12-29 20:11:42 +00:00
|
|
|
if( m_ignoreMouseEvents )
|
2007-08-22 05:11:01 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
if( event.LeftIsDown() )
|
|
|
|
localrealbutt |= GR_M_LEFT_DOWN;
|
2007-12-09 09:00:15 +00:00
|
|
|
|
2007-08-22 05:11:01 +00:00
|
|
|
if( event.MiddleIsDown() )
|
|
|
|
localrealbutt |= GR_M_MIDDLE_DOWN;
|
|
|
|
|
|
|
|
if( event.LeftDown() )
|
|
|
|
localbutt = GR_M_LEFT_DOWN;
|
|
|
|
|
|
|
|
if( event.ButtonDClick( 1 ) )
|
|
|
|
localbutt = GR_M_LEFT_DOWN | GR_M_DCLICK;
|
2007-12-09 09:00:15 +00:00
|
|
|
|
2007-08-22 05:11:01 +00:00
|
|
|
if( event.MiddleDown() )
|
|
|
|
localbutt = GR_M_MIDDLE_DOWN;
|
2007-12-09 09:00:15 +00:00
|
|
|
|
2012-04-23 21:56:26 +00:00
|
|
|
localrealbutt |= localbutt; // compensation default wxGTK
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2011-02-02 19:01:21 +00:00
|
|
|
INSTALL_UNBUFFERED_DC( DC, this );
|
|
|
|
DC.SetBackground( *wxBLACK_BRUSH );
|
|
|
|
|
2012-04-23 21:56:26 +00:00
|
|
|
// Compute the cursor position in drawing (logical) units.
|
2011-02-21 13:54:29 +00:00
|
|
|
screen->SetMousePosition( event.GetLogicalPosition( DC ) );
|
2009-12-19 16:10:25 +00:00
|
|
|
|
2010-01-17 14:20:29 +00:00
|
|
|
int kbstat = 0;
|
2007-08-22 05:11:01 +00:00
|
|
|
|
|
|
|
if( event.ShiftDown() )
|
|
|
|
kbstat |= GR_KB_SHIFT;
|
2011-01-30 22:22:38 +00:00
|
|
|
|
2007-08-22 05:11:01 +00:00
|
|
|
if( event.ControlDown() )
|
|
|
|
kbstat |= GR_KB_CTRL;
|
2011-01-30 22:22:38 +00:00
|
|
|
|
2007-08-22 05:11:01 +00:00
|
|
|
if( event.AltDown() )
|
|
|
|
kbstat |= GR_KB_ALT;
|
|
|
|
|
2007-12-09 09:00:15 +00:00
|
|
|
// Calling Double Click and Click functions :
|
2010-01-17 14:20:29 +00:00
|
|
|
if( localbutt == (int) ( GR_M_LEFT_DOWN | GR_M_DCLICK ) )
|
2007-12-09 09:00:15 +00:00
|
|
|
{
|
2011-02-21 13:54:29 +00:00
|
|
|
GetParent()->OnLeftDClick( &DC, screen->RefPos( true ) );
|
2008-08-26 09:06:26 +00:00
|
|
|
|
|
|
|
// inhibit a response to the mouse left button release,
|
2009-11-23 15:16:50 +00:00
|
|
|
// because we have a double click, and we do not want a new
|
|
|
|
// OnLeftClick command at end of this Double Click
|
2012-12-06 21:53:00 +00:00
|
|
|
m_ignoreNextLeftButtonRelease = true;
|
2007-12-09 09:00:15 +00:00
|
|
|
}
|
2007-10-09 12:29:02 +00:00
|
|
|
else if( event.LeftUp() )
|
|
|
|
{
|
2009-11-23 15:16:50 +00:00
|
|
|
// A block command is in progress: a left up is the end of block
|
|
|
|
// or this is the end of a double click, already seen
|
2012-12-06 21:53:00 +00:00
|
|
|
// Note also m_ignoreNextLeftButtonRelease can be set by
|
|
|
|
// the call to OnLeftClick(), so do not change it after calling OnLeftClick
|
|
|
|
bool ignoreEvt = m_ignoreNextLeftButtonRelease;
|
|
|
|
m_ignoreNextLeftButtonRelease = false;
|
|
|
|
|
|
|
|
if( screen->m_BlockLocate.GetState() == STATE_NO_BLOCK && !ignoreEvt )
|
2011-02-21 13:54:29 +00:00
|
|
|
GetParent()->OnLeftClick( &DC, screen->RefPos( true ) );
|
2007-12-09 09:00:15 +00:00
|
|
|
|
2008-08-26 09:06:26 +00:00
|
|
|
}
|
2012-12-06 21:53:00 +00:00
|
|
|
else if( !event.LeftIsDown() )
|
2008-08-26 09:06:26 +00:00
|
|
|
{
|
|
|
|
/* be sure there is a response to a left button release command
|
2009-11-23 15:16:50 +00:00
|
|
|
* even when a LeftUp event is not seen. This happens when a
|
|
|
|
* double click opens a dialog box, and the release mouse button
|
2012-12-06 21:53:00 +00:00
|
|
|
* is made when the dialog box is opened.
|
2008-08-26 09:06:26 +00:00
|
|
|
*/
|
2012-12-06 21:53:00 +00:00
|
|
|
m_ignoreNextLeftButtonRelease = false;
|
2007-10-09 12:29:02 +00:00
|
|
|
}
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2012-04-11 18:54:20 +00:00
|
|
|
if( event.ButtonDown( wxMOUSE_BTN_MIDDLE ) && m_enableMiddleButtonPan )
|
|
|
|
{
|
|
|
|
if( m_panScrollbarLimits )
|
|
|
|
{
|
|
|
|
int ppux, ppuy;
|
|
|
|
GetScrollPixelsPerUnit( &ppux, &ppuy );
|
|
|
|
GetViewStart( &m_PanStartCenter.x, &m_PanStartCenter.y );
|
|
|
|
m_PanStartCenter.x *= ppux;
|
|
|
|
m_PanStartCenter.y *= ppuy;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
m_PanStartCenter = GetParent()->GetScreen()->GetScrollCenterPosition();
|
|
|
|
|
|
|
|
m_PanStartEventPosition = event.GetPosition();
|
|
|
|
|
|
|
|
INSTALL_UNBUFFERED_DC( dc, this );
|
|
|
|
CrossHairOff( &dc );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( event.ButtonUp( wxMOUSE_BTN_MIDDLE ) && m_enableMiddleButtonPan )
|
|
|
|
{
|
|
|
|
INSTALL_UNBUFFERED_DC( dc, this );
|
|
|
|
CrossHairOn( &dc );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( event.MiddleIsDown() && m_enableMiddleButtonPan )
|
|
|
|
{
|
|
|
|
wxPoint currentPosition = event.GetPosition();
|
|
|
|
if( m_panScrollbarLimits )
|
|
|
|
{
|
|
|
|
int x, y;
|
2012-04-12 07:58:12 +00:00
|
|
|
int tmpX, tmpY;
|
2012-04-11 18:54:20 +00:00
|
|
|
int ppux, ppuy;
|
|
|
|
int maxX, maxY;
|
|
|
|
int vsizeX, vsizeY;
|
|
|
|
int csizeX, csizeY;
|
|
|
|
|
2012-04-12 07:58:12 +00:00
|
|
|
GetViewStart( &tmpX, &tmpY );
|
2012-04-11 18:54:20 +00:00
|
|
|
GetScrollPixelsPerUnit( &ppux, &ppuy );
|
|
|
|
GetVirtualSize( &vsizeX, &vsizeY );
|
|
|
|
GetClientSize( &csizeX, &csizeY );
|
|
|
|
|
|
|
|
maxX = vsizeX - csizeX;
|
|
|
|
maxY = vsizeY - csizeY;
|
|
|
|
|
|
|
|
x = m_PanStartCenter.x + m_PanStartEventPosition.x - currentPosition.x;
|
|
|
|
y = m_PanStartCenter.y + m_PanStartEventPosition.y - currentPosition.y;
|
|
|
|
|
|
|
|
bool shouldMoveCursor = false;
|
|
|
|
|
|
|
|
if( x < 0 )
|
|
|
|
{
|
|
|
|
currentPosition.x += x;
|
|
|
|
x = 0;
|
|
|
|
shouldMoveCursor = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( y < 0 )
|
|
|
|
{
|
|
|
|
currentPosition.y += y;
|
|
|
|
y = 0;
|
|
|
|
shouldMoveCursor = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( x > maxX )
|
|
|
|
{
|
|
|
|
currentPosition.x += ( x - maxX );
|
|
|
|
x = maxX;
|
|
|
|
shouldMoveCursor = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( y > maxY )
|
|
|
|
{
|
|
|
|
currentPosition.y += ( y - maxY );
|
|
|
|
y = maxY;
|
|
|
|
shouldMoveCursor = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( shouldMoveCursor )
|
|
|
|
WarpPointer( currentPosition.x, currentPosition.y );
|
|
|
|
|
|
|
|
Scroll( x/ppux, y/ppuy );
|
|
|
|
|
2012-04-12 07:58:12 +00:00
|
|
|
double scale = GetParent()->GetScreen()->GetScalingFactor();
|
|
|
|
|
|
|
|
wxPoint center = GetParent()->GetScreen()->GetScrollCenterPosition();
|
// Dick Hollenbeck's KiROUND R&D
// This provides better project control over rounding to int from double
// than wxRound() did. This scheme provides better logging in Debug builds
// and it provides for compile time calculation of constants.
#include <stdio.h>
#include <assert.h>
#include <limits.h>
//-----<KiROUND KIT>------------------------------------------------------------
/**
* KiROUND
* rounds a floating point number to an int using
* "round halfway cases away from zero".
* In Debug build an assert fires if will not fit into an int.
*/
#if defined( DEBUG )
// DEBUG: a macro to capture line and file, then calls this inline
static inline int KiRound( double v, int line, const char* filename )
{
v = v < 0 ? v - 0.5 : v + 0.5;
if( v > INT_MAX + 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n", __FUNCTION__, filename, line, v );
}
else if( v < INT_MIN - 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n", __FUNCTION__, filename, line, v );
}
return int( v );
}
#define KiROUND( v ) KiRound( v, __LINE__, __FILE__ )
#else
// RELEASE: a macro so compile can pre-compute constants.
#define KiROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 )
#endif
//-----</KiROUND KIT>-----------------------------------------------------------
// Only a macro is compile time calculated, an inline function causes a static constructor
// in a situation like this.
// Therefore the Release build is best done with a MACRO not an inline function.
int Computed = KiROUND( 14.3 * 8 );
int main( int argc, char** argv )
{
for( double d = double(INT_MAX)-1; d < double(INT_MAX)+8; d += 2.0 )
{
int i = KiROUND( d );
printf( "t: %d %.16g\n", i, d );
}
return 0;
}
2012-04-19 06:55:45 +00:00
|
|
|
center.x += KiROUND( (double) ( x - tmpX ) / scale ) / ppux;
|
|
|
|
center.y += KiROUND( (double) ( y - tmpY ) / scale ) / ppuy;
|
2012-04-12 07:58:12 +00:00
|
|
|
GetParent()->GetScreen()->SetScrollCenterPosition( center );
|
|
|
|
|
2012-04-11 18:54:20 +00:00
|
|
|
Refresh();
|
|
|
|
Update();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
double scale = GetParent()->GetScreen()->GetScalingFactor();
|
|
|
|
int x = m_PanStartCenter.x +
|
// Dick Hollenbeck's KiROUND R&D
// This provides better project control over rounding to int from double
// than wxRound() did. This scheme provides better logging in Debug builds
// and it provides for compile time calculation of constants.
#include <stdio.h>
#include <assert.h>
#include <limits.h>
//-----<KiROUND KIT>------------------------------------------------------------
/**
* KiROUND
* rounds a floating point number to an int using
* "round halfway cases away from zero".
* In Debug build an assert fires if will not fit into an int.
*/
#if defined( DEBUG )
// DEBUG: a macro to capture line and file, then calls this inline
static inline int KiRound( double v, int line, const char* filename )
{
v = v < 0 ? v - 0.5 : v + 0.5;
if( v > INT_MAX + 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n", __FUNCTION__, filename, line, v );
}
else if( v < INT_MIN - 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n", __FUNCTION__, filename, line, v );
}
return int( v );
}
#define KiROUND( v ) KiRound( v, __LINE__, __FILE__ )
#else
// RELEASE: a macro so compile can pre-compute constants.
#define KiROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 )
#endif
//-----</KiROUND KIT>-----------------------------------------------------------
// Only a macro is compile time calculated, an inline function causes a static constructor
// in a situation like this.
// Therefore the Release build is best done with a MACRO not an inline function.
int Computed = KiROUND( 14.3 * 8 );
int main( int argc, char** argv )
{
for( double d = double(INT_MAX)-1; d < double(INT_MAX)+8; d += 2.0 )
{
int i = KiROUND( d );
printf( "t: %d %.16g\n", i, d );
}
return 0;
}
2012-04-19 06:55:45 +00:00
|
|
|
KiROUND( (double) ( m_PanStartEventPosition.x - currentPosition.x ) / scale );
|
2012-04-11 18:54:20 +00:00
|
|
|
int y = m_PanStartCenter.y +
|
// Dick Hollenbeck's KiROUND R&D
// This provides better project control over rounding to int from double
// than wxRound() did. This scheme provides better logging in Debug builds
// and it provides for compile time calculation of constants.
#include <stdio.h>
#include <assert.h>
#include <limits.h>
//-----<KiROUND KIT>------------------------------------------------------------
/**
* KiROUND
* rounds a floating point number to an int using
* "round halfway cases away from zero".
* In Debug build an assert fires if will not fit into an int.
*/
#if defined( DEBUG )
// DEBUG: a macro to capture line and file, then calls this inline
static inline int KiRound( double v, int line, const char* filename )
{
v = v < 0 ? v - 0.5 : v + 0.5;
if( v > INT_MAX + 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n", __FUNCTION__, filename, line, v );
}
else if( v < INT_MIN - 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n", __FUNCTION__, filename, line, v );
}
return int( v );
}
#define KiROUND( v ) KiRound( v, __LINE__, __FILE__ )
#else
// RELEASE: a macro so compile can pre-compute constants.
#define KiROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 )
#endif
//-----</KiROUND KIT>-----------------------------------------------------------
// Only a macro is compile time calculated, an inline function causes a static constructor
// in a situation like this.
// Therefore the Release build is best done with a MACRO not an inline function.
int Computed = KiROUND( 14.3 * 8 );
int main( int argc, char** argv )
{
for( double d = double(INT_MAX)-1; d < double(INT_MAX)+8; d += 2.0 )
{
int i = KiROUND( d );
printf( "t: %d %.16g\n", i, d );
}
return 0;
}
2012-04-19 06:55:45 +00:00
|
|
|
KiROUND( (double) ( m_PanStartEventPosition.y - currentPosition.y ) / scale );
|
2012-04-11 18:54:20 +00:00
|
|
|
|
|
|
|
GetParent()->RedrawScreen( wxPoint( x, y ), false );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( event.ButtonUp( wxMOUSE_BTN_MIDDLE ) && !m_enableMiddleButtonPan &&
|
|
|
|
(screen->m_BlockLocate.GetState() == STATE_NO_BLOCK) )
|
2007-12-09 09:00:15 +00:00
|
|
|
{
|
2009-04-05 20:49:15 +00:00
|
|
|
// The middle button has been released, with no block command:
|
2009-01-07 15:59:49 +00:00
|
|
|
// We use it for a zoom center at cursor position command
|
2011-01-30 22:22:38 +00:00
|
|
|
wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED, ID_POPUP_ZOOM_CENTER );
|
2009-01-07 15:59:49 +00:00
|
|
|
cmd.SetEventObject( this );
|
|
|
|
GetEventHandler()->ProcessEvent( cmd );
|
2007-08-22 05:11:01 +00:00
|
|
|
}
|
|
|
|
|
2012-04-23 21:56:26 +00:00
|
|
|
// Calling the general function on mouse changes (and pseudo key commands)
|
2011-02-22 16:43:03 +00:00
|
|
|
GetParent()->GeneralControl( &DC, event.GetLogicalPosition( DC ), 0 );
|
2007-08-22 05:11:01 +00:00
|
|
|
|
|
|
|
/*******************************/
|
|
|
|
/* Control of block commands : */
|
|
|
|
/*******************************/
|
|
|
|
|
|
|
|
// Command block can't start if mouse is dragging a new panel
|
2012-12-06 21:53:00 +00:00
|
|
|
static EDA_DRAW_PANEL* lastPanel;
|
|
|
|
if( lastPanel != this )
|
2008-01-18 20:27:14 +00:00
|
|
|
{
|
2012-12-06 21:53:00 +00:00
|
|
|
m_minDragEventCount = 0;
|
2011-12-29 20:11:42 +00:00
|
|
|
m_canStartBlock = -1;
|
2008-01-18 20:27:14 +00:00
|
|
|
}
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2008-01-18 20:27:14 +00:00
|
|
|
/* A new command block can start after a release buttons
|
2009-04-05 20:49:15 +00:00
|
|
|
* and if the drag is enough
|
2009-11-23 15:16:50 +00:00
|
|
|
* This is to avoid a false start block when a dialog box is dismissed,
|
2009-04-05 20:49:15 +00:00
|
|
|
* or when changing panels in hierarchy navigation
|
2008-01-18 20:27:14 +00:00
|
|
|
* or when clicking while and moving mouse
|
|
|
|
*/
|
2007-08-22 05:11:01 +00:00
|
|
|
if( !event.LeftIsDown() && !event.MiddleIsDown() )
|
|
|
|
{
|
2012-12-06 21:53:00 +00:00
|
|
|
m_minDragEventCount = 0;
|
2011-12-29 20:11:42 +00:00
|
|
|
m_canStartBlock = 0;
|
2008-01-18 20:27:14 +00:00
|
|
|
|
2009-11-23 15:16:50 +00:00
|
|
|
/* Remember the last cursor position when a drag mouse starts
|
2009-04-05 20:49:15 +00:00
|
|
|
* this is the last position ** before ** clicking a button
|
2009-11-23 15:16:50 +00:00
|
|
|
* this is useful to start a block command from the point where the
|
|
|
|
* mouse was clicked first
|
|
|
|
* (a filter creates a delay for the real block command start, and
|
|
|
|
* we must remember this point)
|
2008-01-18 20:27:14 +00:00
|
|
|
*/
|
2011-02-11 20:48:13 +00:00
|
|
|
m_CursorStartPos = screen->GetCrossHairPosition();
|
2007-08-22 05:11:01 +00:00
|
|
|
}
|
|
|
|
|
2011-12-29 20:11:42 +00:00
|
|
|
if( m_enableBlockCommands && !(localbutt & GR_M_DCLICK) )
|
2007-08-22 05:11:01 +00:00
|
|
|
{
|
2011-02-05 19:22:58 +00:00
|
|
|
if( !screen->IsBlockActive() )
|
2007-08-22 05:11:01 +00:00
|
|
|
{
|
2009-07-25 04:53:39 +00:00
|
|
|
screen->m_BlockLocate.SetOrigin( m_CursorStartPos );
|
2007-08-22 05:11:01 +00:00
|
|
|
}
|
2011-01-30 22:22:38 +00:00
|
|
|
|
2012-04-11 18:54:20 +00:00
|
|
|
if( event.LeftDown() || ( !m_enableMiddleButtonPan && event.MiddleDown() ) )
|
2007-08-22 05:11:01 +00:00
|
|
|
{
|
2012-03-26 23:47:08 +00:00
|
|
|
if( screen->m_BlockLocate.GetState() == STATE_BLOCK_MOVE )
|
2007-08-22 05:11:01 +00:00
|
|
|
{
|
2011-12-29 20:11:42 +00:00
|
|
|
m_requestAutoPan = false;
|
2011-02-09 19:47:33 +00:00
|
|
|
GetParent()->HandleBlockPlace( &DC );
|
2012-12-06 21:53:00 +00:00
|
|
|
m_ignoreNextLeftButtonRelease = true;
|
2007-08-22 05:11:01 +00:00
|
|
|
}
|
|
|
|
}
|
2011-12-29 20:11:42 +00:00
|
|
|
else if( ( m_canStartBlock >= 0 )
|
2012-04-11 18:54:20 +00:00
|
|
|
&& ( event.LeftIsDown() || ( !m_enableMiddleButtonPan && event.MiddleIsDown() ) )
|
2011-02-11 20:48:13 +00:00
|
|
|
&& !IsMouseCaptured() )
|
2009-11-23 15:16:50 +00:00
|
|
|
{
|
2011-01-30 22:22:38 +00:00
|
|
|
// Mouse is dragging: if no block in progress, start a block command.
|
2012-03-26 23:47:08 +00:00
|
|
|
if( screen->m_BlockLocate.GetState() == STATE_NO_BLOCK )
|
2010-01-17 14:20:29 +00:00
|
|
|
{
|
|
|
|
// Start a block command
|
2007-08-22 05:11:01 +00:00
|
|
|
int cmd_type = kbstat;
|
2007-12-09 09:00:15 +00:00
|
|
|
|
2012-04-11 18:54:20 +00:00
|
|
|
if( !m_enableMiddleButtonPan && event.MiddleIsDown() )
|
2007-08-22 05:11:01 +00:00
|
|
|
cmd_type |= MOUSE_MIDDLE;
|
2007-12-09 09:00:15 +00:00
|
|
|
|
2012-04-23 21:56:26 +00:00
|
|
|
// A block command is started if the drag is enough. A small
|
|
|
|
// drag is ignored (it is certainly a little mouse move when
|
|
|
|
// clicking) not really a drag mouse
|
2012-12-06 21:53:00 +00:00
|
|
|
if( m_minDragEventCount < MIN_DRAG_COUNT_FOR_START_BLOCK_COMMAND )
|
|
|
|
m_minDragEventCount++;
|
2007-08-22 05:11:01 +00:00
|
|
|
else
|
|
|
|
{
|
2011-02-09 19:47:33 +00:00
|
|
|
if( !GetParent()->HandleBlockBegin( &DC, cmd_type, m_CursorStartPos ) )
|
2008-01-18 20:27:14 +00:00
|
|
|
{
|
2012-04-23 21:56:26 +00:00
|
|
|
// should not occur: error
|
2011-02-09 19:47:33 +00:00
|
|
|
GetParent()->DisplayToolMsg(
|
2011-01-21 19:30:59 +00:00
|
|
|
wxT( "EDA_DRAW_PANEL::OnMouseEvent() Block Error" ) );
|
2008-01-18 20:27:14 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-12-29 20:11:42 +00:00
|
|
|
m_requestAutoPan = true;
|
2011-03-09 20:09:11 +00:00
|
|
|
SetCursor( wxCURSOR_SIZING );
|
2008-01-18 20:27:14 +00:00
|
|
|
}
|
2007-08-22 05:11:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-11 18:54:20 +00:00
|
|
|
if( event.ButtonUp( wxMOUSE_BTN_LEFT ) ||
|
|
|
|
( !m_enableMiddleButtonPan && event.ButtonUp( wxMOUSE_BTN_MIDDLE ) ) )
|
2007-12-09 09:00:15 +00:00
|
|
|
{
|
|
|
|
/* Release the mouse button: end of block.
|
2009-11-23 15:16:50 +00:00
|
|
|
* The command can finish (DELETE) or have a next command (MOVE,
|
|
|
|
* COPY). However the block command is canceled if the block
|
|
|
|
* size is small because a block command filtering is already
|
|
|
|
* made, this case happens, but only when the on grid cursor has
|
|
|
|
* not moved.
|
2007-08-22 05:11:01 +00:00
|
|
|
*/
|
2008-03-06 01:46:30 +00:00
|
|
|
#define BLOCK_MINSIZE_LIMIT 1
|
2007-08-22 05:11:01 +00:00
|
|
|
bool BlockIsSmall =
|
2012-09-22 11:19:37 +00:00
|
|
|
( std::abs( screen->m_BlockLocate.GetWidth() ) < BLOCK_MINSIZE_LIMIT )
|
|
|
|
&& ( std::abs( screen->m_BlockLocate.GetHeight() ) < BLOCK_MINSIZE_LIMIT );
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2012-03-26 23:47:08 +00:00
|
|
|
if( (screen->m_BlockLocate.GetState() != STATE_NO_BLOCK) && BlockIsSmall )
|
2007-08-22 05:11:01 +00:00
|
|
|
{
|
2011-02-11 20:48:13 +00:00
|
|
|
if( m_endMouseCaptureCallback )
|
2007-08-22 05:11:01 +00:00
|
|
|
{
|
2011-02-11 20:48:13 +00:00
|
|
|
m_endMouseCaptureCallback( this, &DC );
|
2011-12-29 20:11:42 +00:00
|
|
|
m_requestAutoPan = false;
|
2007-08-22 05:11:01 +00:00
|
|
|
}
|
2011-01-30 22:22:38 +00:00
|
|
|
|
2012-02-26 18:49:00 +00:00
|
|
|
SetCursor( (wxStockCursor) m_currentCursor );
|
2011-03-09 20:09:11 +00:00
|
|
|
}
|
2012-03-26 23:47:08 +00:00
|
|
|
else if( screen->m_BlockLocate.GetState() == STATE_BLOCK_END )
|
2007-08-22 05:11:01 +00:00
|
|
|
{
|
2011-12-29 20:11:42 +00:00
|
|
|
m_requestAutoPan = false;
|
2011-02-09 19:47:33 +00:00
|
|
|
GetParent()->HandleBlockEnd( &DC );
|
2012-02-26 18:49:00 +00:00
|
|
|
SetCursor( (wxStockCursor) m_currentCursor );
|
2012-03-26 23:47:08 +00:00
|
|
|
if( screen->m_BlockLocate.GetState() == STATE_BLOCK_MOVE )
|
2007-08-22 05:11:01 +00:00
|
|
|
{
|
2011-12-29 20:11:42 +00:00
|
|
|
m_requestAutoPan = true;
|
2011-02-08 14:48:38 +00:00
|
|
|
SetCursor( wxCURSOR_HAND );
|
2007-08-22 05:11:01 +00:00
|
|
|
}
|
2011-03-09 20:09:11 +00:00
|
|
|
}
|
2007-08-22 05:11:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-09 09:00:15 +00:00
|
|
|
// End of block command on a double click
|
2011-01-30 22:22:38 +00:00
|
|
|
// To avoid an unwanted block move command if the mouse is moved while double clicking
|
2009-11-23 15:16:50 +00:00
|
|
|
if( localbutt == (int) ( GR_M_LEFT_DOWN | GR_M_DCLICK ) )
|
2007-08-22 05:11:01 +00:00
|
|
|
{
|
2011-02-11 20:48:13 +00:00
|
|
|
if( !screen->IsBlockActive() && IsMouseCaptured() )
|
2007-08-22 05:11:01 +00:00
|
|
|
{
|
2011-02-11 20:48:13 +00:00
|
|
|
m_endMouseCaptureCallback( this, &DC );
|
2007-08-22 05:11:01 +00:00
|
|
|
}
|
|
|
|
}
|
2007-05-06 16:03:28 +00:00
|
|
|
|
|
|
|
#if 0
|
2007-08-22 05:11:01 +00:00
|
|
|
wxString msg_debug;
|
|
|
|
msg_debug.Printf( " block state %d, cmd %d",
|
2012-03-26 23:47:08 +00:00
|
|
|
screen->m_BlockLocate.GetState(),
|
|
|
|
screen->m_BlockLocate.GetCommand() );
|
2011-02-09 19:47:33 +00:00
|
|
|
GetParent()->PrintMsg( msg_debug );
|
2007-05-06 16:03:28 +00:00
|
|
|
#endif
|
|
|
|
|
2012-12-06 21:53:00 +00:00
|
|
|
lastPanel = this;
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2011-12-17 21:21:03 +00:00
|
|
|
|
|
|
|
void EDA_DRAW_PANEL::OnCharHook( wxKeyEvent& event )
|
|
|
|
{
|
|
|
|
event.Skip();
|
|
|
|
}
|
|
|
|
|
2011-01-21 19:30:59 +00:00
|
|
|
void EDA_DRAW_PANEL::OnKeyEvent( wxKeyEvent& event )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2011-02-22 16:43:03 +00:00
|
|
|
int localkey;
|
2009-01-17 20:31:19 +00:00
|
|
|
wxPoint pos;
|
2007-08-22 05:11:01 +00:00
|
|
|
|
2011-12-31 05:44:00 +00:00
|
|
|
localkey = event.GetKeyCode();
|
2007-08-22 05:11:01 +00:00
|
|
|
|
|
|
|
switch( localkey )
|
|
|
|
{
|
2012-04-23 21:56:26 +00:00
|
|
|
default:
|
|
|
|
break;
|
2007-08-22 05:11:01 +00:00
|
|
|
|
|
|
|
case WXK_ESCAPE:
|
2011-12-29 20:11:42 +00:00
|
|
|
m_abortRequest = true;
|
2011-02-08 14:48:38 +00:00
|
|
|
|
2011-02-11 20:48:13 +00:00
|
|
|
if( IsMouseCaptured() )
|
2011-11-10 15:55:05 +00:00
|
|
|
EndMouseCapture();
|
2011-02-08 14:48:38 +00:00
|
|
|
else
|
2011-03-09 20:09:11 +00:00
|
|
|
EndMouseCapture( ID_NO_TOOL_SELECTED, m_defaultCursor, wxEmptyString );
|
2007-08-22 05:11:01 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( event.ControlDown() )
|
|
|
|
localkey |= GR_KB_CTRL;
|
|
|
|
if( event.AltDown() )
|
|
|
|
localkey |= GR_KB_ALT;
|
2011-02-22 16:43:03 +00:00
|
|
|
if( event.ShiftDown() && (event.GetKeyCode() > 256) )
|
2007-08-22 05:11:01 +00:00
|
|
|
localkey |= GR_KB_SHIFT;
|
|
|
|
|
2010-01-20 18:59:46 +00:00
|
|
|
/* Normalize keys code to easily handle keys from Ctrl+A to Ctrl+Z
|
|
|
|
* They have an ascii code from 1 to 27 remapped
|
2010-08-28 18:02:24 +00:00
|
|
|
* to GR_KB_CTRL + 'A' to GR_KB_CTRL + 'Z'
|
2010-01-20 18:59:46 +00:00
|
|
|
*/
|
2010-08-28 18:02:24 +00:00
|
|
|
if( (localkey > GR_KB_CTRL) && (localkey <= GR_KB_CTRL+26) )
|
2010-01-20 18:59:46 +00:00
|
|
|
localkey += 'A' - 1;
|
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
INSTALL_UNBUFFERED_DC( DC, this );
|
2009-12-19 16:10:25 +00:00
|
|
|
|
2007-08-22 05:11:01 +00:00
|
|
|
BASE_SCREEN* Screen = GetScreen();
|
|
|
|
|
2011-02-02 19:01:21 +00:00
|
|
|
// Some key commands use the current mouse position: refresh it.
|
2011-02-01 15:46:25 +00:00
|
|
|
pos = wxGetMousePosition() - GetScreenPosition();
|
2007-12-09 09:00:15 +00:00
|
|
|
|
2011-01-30 22:22:38 +00:00
|
|
|
// Compute the cursor position in drawing units. Also known as logical units to wxDC.
|
2011-02-01 15:46:25 +00:00
|
|
|
pos = wxPoint( DC.DeviceToLogicalX( pos.x ), DC.DeviceToLogicalY( pos.y ) );
|
2011-02-21 13:54:29 +00:00
|
|
|
Screen->SetMousePosition( pos );
|
2007-12-06 16:58:12 +00:00
|
|
|
|
2011-02-22 16:43:03 +00:00
|
|
|
GetParent()->GeneralControl( &DC, pos, localkey );
|
2007-06-26 10:42:11 +00:00
|
|
|
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
2008-12-19 13:51:48 +00:00
|
|
|
|
2009-11-23 15:16:50 +00:00
|
|
|
|
2011-01-21 19:30:59 +00:00
|
|
|
void EDA_DRAW_PANEL::OnPan( wxCommandEvent& event )
|
2008-12-19 13:51:48 +00:00
|
|
|
{
|
2010-01-17 14:20:29 +00:00
|
|
|
int x, y;
|
2010-02-22 16:45:35 +00:00
|
|
|
int ppux, ppuy;
|
|
|
|
int unitsX, unitsY;
|
|
|
|
int maxX, maxY;
|
2008-12-19 13:51:48 +00:00
|
|
|
|
2010-02-22 16:45:35 +00:00
|
|
|
GetViewStart( &x, &y );
|
|
|
|
GetScrollPixelsPerUnit( &ppux, &ppuy );
|
|
|
|
GetVirtualSize( &unitsX, &unitsY );
|
|
|
|
maxX = unitsX;
|
|
|
|
maxY = unitsY;
|
|
|
|
unitsX /= ppux;
|
|
|
|
unitsY /= ppuy;
|
2008-12-19 13:51:48 +00:00
|
|
|
|
|
|
|
switch( event.GetId() )
|
|
|
|
{
|
|
|
|
case ID_PAN_UP:
|
2010-02-08 18:15:42 +00:00
|
|
|
y -= m_scrollIncrementY;
|
2008-12-19 13:51:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ID_PAN_DOWN:
|
2010-02-08 18:15:42 +00:00
|
|
|
y += m_scrollIncrementY;
|
2008-12-19 13:51:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ID_PAN_LEFT:
|
2010-02-08 18:15:42 +00:00
|
|
|
x -= m_scrollIncrementX;
|
2008-12-19 13:51:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ID_PAN_RIGHT:
|
2010-02-08 18:15:42 +00:00
|
|
|
x += m_scrollIncrementX;
|
2008-12-19 13:51:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2011-01-21 19:30:59 +00:00
|
|
|
wxLogDebug( wxT( "Unknown ID %d in EDA_DRAW_PANEL::OnPan()." ), event.GetId() );
|
2008-12-19 13:51:48 +00:00
|
|
|
}
|
|
|
|
|
2010-02-22 16:45:35 +00:00
|
|
|
if( x < 0 )
|
|
|
|
x = 0;
|
2011-01-30 22:22:38 +00:00
|
|
|
|
2010-02-22 16:45:35 +00:00
|
|
|
if( y < 0 )
|
|
|
|
y = 0;
|
2011-01-30 22:22:38 +00:00
|
|
|
|
2010-02-22 16:45:35 +00:00
|
|
|
if( x > maxX )
|
|
|
|
x = maxX;
|
2011-01-30 22:22:38 +00:00
|
|
|
|
2010-02-22 16:45:35 +00:00
|
|
|
if( y > maxY )
|
|
|
|
y = maxY;
|
|
|
|
|
2010-02-23 20:22:31 +00:00
|
|
|
Scroll( x/ppux, y/ppuy );
|
2008-12-19 13:51:48 +00:00
|
|
|
}
|
2009-09-14 13:24:17 +00:00
|
|
|
|
|
|
|
|
2011-11-10 15:55:05 +00:00
|
|
|
void EDA_DRAW_PANEL::EndMouseCapture( int id, int cursor, const wxString& title,
|
|
|
|
bool aCallEndFunc )
|
2009-09-14 13:24:17 +00:00
|
|
|
{
|
2011-11-10 15:55:05 +00:00
|
|
|
if( m_mouseCaptureCallback && m_endMouseCaptureCallback && aCallEndFunc )
|
2009-09-14 13:24:17 +00:00
|
|
|
{
|
2011-01-30 22:22:38 +00:00
|
|
|
INSTALL_UNBUFFERED_DC( dc, this );
|
2011-02-11 20:48:13 +00:00
|
|
|
m_endMouseCaptureCallback( this, &dc );
|
2009-12-20 19:48:58 +00:00
|
|
|
}
|
2011-02-24 20:22:12 +00:00
|
|
|
|
2011-02-17 18:34:27 +00:00
|
|
|
m_mouseCaptureCallback = NULL;
|
|
|
|
m_endMouseCaptureCallback = NULL;
|
2011-12-29 20:11:42 +00:00
|
|
|
m_requestAutoPan = false;
|
2011-01-30 22:22:38 +00:00
|
|
|
|
2009-12-20 19:48:58 +00:00
|
|
|
if( id != -1 && cursor != -1 )
|
|
|
|
{
|
|
|
|
wxASSERT( cursor > wxCURSOR_NONE && cursor < wxCURSOR_MAX );
|
2011-02-09 19:47:33 +00:00
|
|
|
GetParent()->SetToolID( id, cursor, title );
|
2009-09-14 13:24:17 +00:00
|
|
|
}
|
|
|
|
}
|
2011-12-29 20:11:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
void EDA_DRAW_PANEL::CallMouseCapture( wxDC* aDC, const wxPoint& aPosition, bool aErase )
|
|
|
|
{
|
|
|
|
wxCHECK_RET( aDC != NULL, wxT( "Invalid device context." ) );
|
|
|
|
wxCHECK_RET( m_mouseCaptureCallback != NULL, wxT( "Mouse capture callback not set." ) );
|
|
|
|
|
|
|
|
m_mouseCaptureCallback( this, aDC, aPosition, aErase );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void EDA_DRAW_PANEL::CallEndMouseCapture( wxDC* aDC )
|
|
|
|
{
|
|
|
|
wxCHECK_RET( aDC != NULL, wxT( "Invalid device context." ) );
|
|
|
|
wxCHECK_RET( m_endMouseCaptureCallback != NULL, wxT( "End mouse capture callback not set." ) );
|
|
|
|
|
|
|
|
m_endMouseCaptureCallback( this, aDC );
|
|
|
|
}
|