From 2043d4696f758c1cc123cf864e7024c1272c1165 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 18 May 2015 13:48:10 +0200 Subject: [PATCH] Scrollbars (GAL). --- common/CMakeLists.txt | 1 + common/draw_panel_gal.cpp | 11 ++-- common/view/view_controls.cpp | 72 ++++++++++++++++++++++++++ common/view/wx_view_controls.cpp | 87 +++++++++++++++----------------- include/class_draw_panel_gal.h | 2 +- include/view/wx_view_controls.h | 11 +++- 6 files changed, 132 insertions(+), 52 deletions(-) create mode 100644 common/view/view_controls.cpp diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index a182fdd362..bf981aeef4 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -35,6 +35,7 @@ set( GAL_SRCS gal/graphics_abstraction_layer.cpp gal/stroke_font.cpp gal/color4d.cpp + view/view_controls.cpp view/wx_view_controls.cpp geometry/hetriang.cpp diff --git a/common/draw_panel_gal.cpp b/common/draw_panel_gal.cpp index 5f6aa6c0ac..b2c5d07500 100644 --- a/common/draw_panel_gal.cpp +++ b/common/draw_panel_gal.cpp @@ -52,7 +52,7 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWindowId, const wxPoint& aPosition, const wxSize& aSize, GalType aGalType ) : - wxWindow( aParentWindow, aWindowId, aPosition, aSize ) + wxScrolledCanvas( aParentWindow, aWindowId, aPosition, aSize ) { m_parent = aParentWindow; m_gal = NULL; @@ -63,6 +63,8 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin SwitchBackend( aGalType ); 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 ); @@ -109,13 +111,13 @@ EDA_DRAW_PANEL_GAL::~EDA_DRAW_PANEL_GAL() void EDA_DRAW_PANEL_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) ) { m_pendingRefresh = false; - m_lastRefresh = wxGetLocalTimeMillis(); if( m_drawing ) return; m_drawing = true; + m_viewControls->UpdateScrollbars(); m_view->UpdateItems(); m_gal->BeginDrawing(); 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->EndDrawing(); + m_lastRefresh = wxGetLocalTimeMillis(); m_drawing = false; } @@ -298,8 +301,8 @@ bool EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType ) } catch( std::runtime_error& err ) { - DisplayError( m_parent, wxString( err.what() ) ); - return false; + DisplayError( m_parent, wxString( err.what() ) ); + return false; } return true; diff --git a/common/view/view_controls.cpp b/common/view/view_controls.cpp new file mode 100644 index 0000000000..41c6edeee1 --- /dev/null +++ b/common/view/view_controls.cpp @@ -0,0 +1,72 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Torsten Hueter, torstenhtr gmx.de + * Copyright (C) 2013-2015 CERN + * @author Tomasz Wlostowski + * @author Maciej Suminski + * + * 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 +#include +#include + +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 ); +} diff --git a/common/view/wx_view_controls.cpp b/common/view/wx_view_controls.cpp index f1814af3d5..4cdcd7a42b 100644 --- a/common/view/wx_view_controls.cpp +++ b/common/view/wx_view_controls.cpp @@ -2,8 +2,9 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2012 Torsten Hueter, torstenhtr gmx.de - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2015 CERN * @author Tomasz Wlostowski + * @author Maciej Suminski * * This program is free software; you can redistribute it and/or * 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(); -WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, wxWindow* aParentPanel ) : - VIEW_CONTROLS( aView ), m_state( IDLE ), m_parentPanel( aParentPanel ) +WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, wxScrolledCanvas* aParentPanel ) : + VIEW_CONTROLS( aView ), m_state( IDLE ), m_parentPanel( aParentPanel ), m_scrollScale( 1.0, 1.0 ) { m_parentPanel->Connect( wxEVT_MOTION, wxMouseEventHandler( WX_VIEW_CONTROLS::onMotion ), NULL, this ); @@ -55,6 +56,8 @@ WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, wxWindow* aParentPanel ) : #endif m_parentPanel->Connect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler( WX_VIEW_CONTROLS::onLeave ), NULL, this ); + m_parentPanel->Connect( wxEVT_SCROLLWIN_THUMBTRACK, + wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), NULL, this ); m_panTimer.SetOwner( this ); 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 ) { 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 ) { 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" ) ); 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 ); +} diff --git a/include/class_draw_panel_gal.h b/include/class_draw_panel_gal.h index 04375ace3d..7a7e57baae 100644 --- a/include/class_draw_panel_gal.h +++ b/include/class_draw_panel_gal.h @@ -48,7 +48,7 @@ class PAINTER; }; -class EDA_DRAW_PANEL_GAL : public wxWindow +class EDA_DRAW_PANEL_GAL : public wxScrolledCanvas { public: enum GalType { diff --git a/include/view/wx_view_controls.h b/include/view/wx_view_controls.h index 323a9a1443..6d1647e3dc 100644 --- a/include/view/wx_view_controls.h +++ b/include/view/wx_view_controls.h @@ -47,7 +47,7 @@ namespace KIGFX class WX_VIEW_CONTROLS : public VIEW_CONTROLS, public wxEvtHandler { public: - WX_VIEW_CONTROLS( VIEW* aView, wxWindow* aParentPanel ); + WX_VIEW_CONTROLS( VIEW* aView, wxScrolledCanvas* aParentPanel ); ~WX_VIEW_CONTROLS() {} @@ -58,6 +58,7 @@ public: void onEnter( wxMouseEvent& WXUNUSED( aEvent ) ); void onLeave( wxMouseEvent& WXUNUSED( aEvent ) ); void onTimer( wxTimerEvent& WXUNUSED( aEvent ) ); + void onScroll( wxScrollWinEvent& aEvent ); /** * Function SetGrabMouse() @@ -87,6 +88,9 @@ public: /// @copydoc VIEW_CONTROLS::GetCursorPosition() 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 /// cursor does not move in screen coordinates, but does in world coordinates) static const wxEventType EVT_REFRESH_MOUSE; @@ -114,7 +118,7 @@ private: STATE m_state; /// Panel that is affected by VIEW_CONTROLS - wxWindow* m_parentPanel; + wxScrolledCanvas* m_parentPanel; /// Stores information about point where dragging has started VECTOR2D m_dragStartPoint; @@ -130,6 +134,9 @@ private: /// Timer repsonsible for handling autopanning wxTimer m_panTimer; + + /// Ratio used for scaling world coordinates to scrollbar position. + VECTOR2D m_scrollScale; }; } // namespace KIGFX