Scrollbars (GAL).

This commit is contained in:
Maciej Suminski 2015-05-18 13:48:10 +02:00
parent 4fe65715a2
commit 2043d4696f
6 changed files with 132 additions and 52 deletions

View File

@ -35,6 +35,7 @@ set( GAL_SRCS
gal/graphics_abstraction_layer.cpp gal/graphics_abstraction_layer.cpp
gal/stroke_font.cpp gal/stroke_font.cpp
gal/color4d.cpp gal/color4d.cpp
view/view_controls.cpp
view/wx_view_controls.cpp view/wx_view_controls.cpp
geometry/hetriang.cpp geometry/hetriang.cpp

View File

@ -52,7 +52,7 @@
EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWindowId, EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWindowId,
const wxPoint& aPosition, const wxSize& aSize, const wxPoint& aPosition, const wxSize& aSize,
GalType aGalType ) : GalType aGalType ) :
wxWindow( aParentWindow, aWindowId, aPosition, aSize ) wxScrolledCanvas( aParentWindow, aWindowId, aPosition, aSize )
{ {
m_parent = aParentWindow; m_parent = aParentWindow;
m_gal = NULL; m_gal = NULL;
@ -63,6 +63,8 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin
SwitchBackend( aGalType ); SwitchBackend( aGalType );
SetBackgroundStyle( wxBG_STYLE_CUSTOM ); SetBackgroundStyle( wxBG_STYLE_CUSTOM );
ShowScrollbars( wxSHOW_SB_ALWAYS, wxSHOW_SB_ALWAYS );
EnableScrolling( false, false ); // otherwise Zoom Auto disables GAL canvas
m_painter = new KIGFX::PCB_PAINTER( m_gal ); m_painter = new KIGFX::PCB_PAINTER( m_gal );
@ -109,13 +111,13 @@ EDA_DRAW_PANEL_GAL::~EDA_DRAW_PANEL_GAL()
void EDA_DRAW_PANEL_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) ) void EDA_DRAW_PANEL_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) )
{ {
m_pendingRefresh = false; m_pendingRefresh = false;
m_lastRefresh = wxGetLocalTimeMillis();
if( m_drawing ) if( m_drawing )
return; return;
m_drawing = true; m_drawing = true;
m_viewControls->UpdateScrollbars();
m_view->UpdateItems(); m_view->UpdateItems();
m_gal->BeginDrawing(); m_gal->BeginDrawing();
m_gal->ClearScreen( m_painter->GetSettings()->GetBackgroundColor() ); m_gal->ClearScreen( m_painter->GetSettings()->GetBackgroundColor() );
@ -134,6 +136,7 @@ void EDA_DRAW_PANEL_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) )
m_gal->DrawCursor( m_viewControls->GetCursorPosition() ); m_gal->DrawCursor( m_viewControls->GetCursorPosition() );
m_gal->EndDrawing(); m_gal->EndDrawing();
m_lastRefresh = wxGetLocalTimeMillis();
m_drawing = false; m_drawing = false;
} }
@ -298,8 +301,8 @@ bool EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType )
} }
catch( std::runtime_error& err ) catch( std::runtime_error& err )
{ {
DisplayError( m_parent, wxString( err.what() ) ); DisplayError( m_parent, wxString( err.what() ) );
return false; return false;
} }
return true; return true;

View File

@ -0,0 +1,72 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
* Copyright (C) 2013-2015 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* 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
*/
#include <view/view.h>
#include <view/view_controls.h>
#include <gal/graphics_abstraction_layer.h>
using namespace KIGFX;
void VIEW_CONTROLS::ShowCursor( bool aEnabled )
{
m_view->GetGAL()->SetCursorEnabled( aEnabled );
}
void VIEW_CONTROLS::setCenter( const VECTOR2D& aCenter )
{
if( !m_panBoundary.Contains( aCenter ) )
{
VECTOR2D newCenter( aCenter );
if( aCenter.x < m_panBoundary.GetLeft() )
newCenter.x = m_panBoundary.GetLeft();
else if( aCenter.x > m_panBoundary.GetRight() )
newCenter.x = m_panBoundary.GetRight();
if( aCenter.y < m_panBoundary.GetTop() )
newCenter.y = m_panBoundary.GetTop();
else if( aCenter.y > m_panBoundary.GetBottom() )
newCenter.y = m_panBoundary.GetBottom();
m_view->SetCenter( newCenter );
}
else
{
m_view->SetCenter( aCenter );
}
}
void VIEW_CONTROLS::setScale( double aScale, const VECTOR2D& aAnchor )
{
if( aScale < m_minScale )
aScale = m_minScale;
else if( aScale > m_maxScale )
aScale = m_maxScale;
m_view->SetScale( aScale, aAnchor );
}

View File

@ -2,8 +2,9 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de * Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
* Copyright (C) 2013 CERN * Copyright (C) 2013-2015 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Maciej Suminski <maciej.suminski@cern.ch>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -34,8 +35,8 @@ using namespace KIGFX;
const wxEventType WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE = wxNewEventType(); const wxEventType WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE = wxNewEventType();
WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, wxWindow* aParentPanel ) : WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, wxScrolledCanvas* aParentPanel ) :
VIEW_CONTROLS( aView ), m_state( IDLE ), m_parentPanel( aParentPanel ) VIEW_CONTROLS( aView ), m_state( IDLE ), m_parentPanel( aParentPanel ), m_scrollScale( 1.0, 1.0 )
{ {
m_parentPanel->Connect( wxEVT_MOTION, m_parentPanel->Connect( wxEVT_MOTION,
wxMouseEventHandler( WX_VIEW_CONTROLS::onMotion ), NULL, this ); wxMouseEventHandler( WX_VIEW_CONTROLS::onMotion ), NULL, this );
@ -55,6 +56,8 @@ WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, wxWindow* aParentPanel ) :
#endif #endif
m_parentPanel->Connect( wxEVT_LEAVE_WINDOW, m_parentPanel->Connect( wxEVT_LEAVE_WINDOW,
wxMouseEventHandler( WX_VIEW_CONTROLS::onLeave ), NULL, this ); wxMouseEventHandler( WX_VIEW_CONTROLS::onLeave ), NULL, this );
m_parentPanel->Connect( wxEVT_SCROLLWIN_THUMBTRACK,
wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), NULL, this );
m_panTimer.SetOwner( this ); m_panTimer.SetOwner( this );
this->Connect( wxEVT_TIMER, this->Connect( wxEVT_TIMER,
@ -62,48 +65,6 @@ WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, wxWindow* aParentPanel ) :
} }
void VIEW_CONTROLS::ShowCursor( bool aEnabled )
{
m_view->GetGAL()->SetCursorEnabled( aEnabled );
}
void VIEW_CONTROLS::setCenter( const VECTOR2D& aCenter )
{
if( !m_panBoundary.Contains( aCenter ) )
{
VECTOR2D newCenter( aCenter );
if( aCenter.x < m_panBoundary.GetLeft() )
newCenter.x = m_panBoundary.GetLeft();
else if( aCenter.x > m_panBoundary.GetRight() )
newCenter.x = m_panBoundary.GetRight();
if( aCenter.y < m_panBoundary.GetTop() )
newCenter.y = m_panBoundary.GetTop();
else if( aCenter.y > m_panBoundary.GetBottom() )
newCenter.y = m_panBoundary.GetBottom();
m_view->SetCenter( newCenter );
}
else
{
m_view->SetCenter( aCenter );
}
}
void VIEW_CONTROLS::setScale( double aScale, const VECTOR2D& aAnchor )
{
if( aScale < m_minScale )
aScale = m_minScale;
else if( aScale > m_maxScale )
aScale = m_maxScale;
m_view->SetScale( aScale, aAnchor );
}
void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent ) void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
{ {
bool isAutoPanning = false; bool isAutoPanning = false;
@ -298,6 +259,20 @@ void WX_VIEW_CONTROLS::onTimer( wxTimerEvent& aEvent )
} }
void WX_VIEW_CONTROLS::onScroll( wxScrollWinEvent& aEvent )
{
VECTOR2D center = m_view->GetCenter();
if( aEvent.GetOrientation() == wxHORIZONTAL )
center.x = (double) aEvent.GetPosition() * m_panBoundary.GetWidth() / m_scrollScale.x + m_panBoundary.GetLeft();
else if( aEvent.GetOrientation() == wxVERTICAL )
center.y = (double) aEvent.GetPosition() * m_panBoundary.GetHeight() / m_scrollScale.y + m_panBoundary.GetTop();
VIEW_CONTROLS::setCenter( center );
m_parentPanel->Refresh();
}
void WX_VIEW_CONTROLS::SetGrabMouse( bool aEnabled ) void WX_VIEW_CONTROLS::SetGrabMouse( bool aEnabled )
{ {
VIEW_CONTROLS::SetGrabMouse( aEnabled ); VIEW_CONTROLS::SetGrabMouse( aEnabled );
@ -393,3 +368,25 @@ bool WX_VIEW_CONTROLS::handleAutoPanning( const wxMouseEvent& aEvent )
wxASSERT_MSG( false, wxT( "This line should never be reached" ) ); wxASSERT_MSG( false, wxT( "This line should never be reached" ) );
return false; // Should not be reached, just avoid the compiler warnings.. return false; // Should not be reached, just avoid the compiler warnings..
} }
void WX_VIEW_CONTROLS::UpdateScrollbars()
{
const BOX2D viewport = m_view->GetViewport();
m_scrollScale.x = 2e3 * m_panBoundary.GetWidth() / viewport.GetWidth();
m_scrollScale.y = 2e3 * m_panBoundary.GetHeight() / viewport.GetHeight();
// Another example of wxWidgets being broken by design: scroll position is determined by the
// left (or top, if vertical) edge of the slider. Fortunately, slider size seems to be constant
// (at least for wxGTK 3.0), so we have to add its size to allow user to scroll the workspace
// till the end.
m_parentPanel->SetScrollbars( 1, 1,
#ifdef __LINUX__
m_scrollScale.x + 1623, m_scrollScale.y + 1623,
#else
m_scrollScale.x, m_scrollScale.y,
#endif
( viewport.Centre().x - m_panBoundary.GetLeft() ) / m_panBoundary.GetWidth() * m_scrollScale.x,
( viewport.Centre().y - m_panBoundary.GetTop() ) / m_panBoundary.GetHeight() * m_scrollScale.y );
}

View File

@ -48,7 +48,7 @@ class PAINTER;
}; };
class EDA_DRAW_PANEL_GAL : public wxWindow class EDA_DRAW_PANEL_GAL : public wxScrolledCanvas
{ {
public: public:
enum GalType { enum GalType {

View File

@ -47,7 +47,7 @@ namespace KIGFX
class WX_VIEW_CONTROLS : public VIEW_CONTROLS, public wxEvtHandler class WX_VIEW_CONTROLS : public VIEW_CONTROLS, public wxEvtHandler
{ {
public: public:
WX_VIEW_CONTROLS( VIEW* aView, wxWindow* aParentPanel ); WX_VIEW_CONTROLS( VIEW* aView, wxScrolledCanvas* aParentPanel );
~WX_VIEW_CONTROLS() ~WX_VIEW_CONTROLS()
{} {}
@ -58,6 +58,7 @@ public:
void onEnter( wxMouseEvent& WXUNUSED( aEvent ) ); void onEnter( wxMouseEvent& WXUNUSED( aEvent ) );
void onLeave( wxMouseEvent& WXUNUSED( aEvent ) ); void onLeave( wxMouseEvent& WXUNUSED( aEvent ) );
void onTimer( wxTimerEvent& WXUNUSED( aEvent ) ); void onTimer( wxTimerEvent& WXUNUSED( aEvent ) );
void onScroll( wxScrollWinEvent& aEvent );
/** /**
* Function SetGrabMouse() * Function SetGrabMouse()
@ -87,6 +88,9 @@ public:
/// @copydoc VIEW_CONTROLS::GetCursorPosition() /// @copydoc VIEW_CONTROLS::GetCursorPosition()
VECTOR2D GetCursorPosition() const; VECTOR2D GetCursorPosition() const;
/// Adjusts the scrollbars position to match the current viewport.
void UpdateScrollbars();
/// Event that forces mouse move event in the dispatcher (eg. used in autopanning, when mouse /// Event that forces mouse move event in the dispatcher (eg. used in autopanning, when mouse
/// cursor does not move in screen coordinates, but does in world coordinates) /// cursor does not move in screen coordinates, but does in world coordinates)
static const wxEventType EVT_REFRESH_MOUSE; static const wxEventType EVT_REFRESH_MOUSE;
@ -114,7 +118,7 @@ private:
STATE m_state; STATE m_state;
/// Panel that is affected by VIEW_CONTROLS /// Panel that is affected by VIEW_CONTROLS
wxWindow* m_parentPanel; wxScrolledCanvas* m_parentPanel;
/// Stores information about point where dragging has started /// Stores information about point where dragging has started
VECTOR2D m_dragStartPoint; VECTOR2D m_dragStartPoint;
@ -130,6 +134,9 @@ private:
/// Timer repsonsible for handling autopanning /// Timer repsonsible for handling autopanning
wxTimer m_panTimer; wxTimer m_panTimer;
/// Ratio used for scaling world coordinates to scrollbar position.
VECTOR2D m_scrollScale;
}; };
} // namespace KIGFX } // namespace KIGFX