From af99040c70b975e24ac0acee50f1fa13746d1239 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 1 Aug 2003 13:38:43 +0000 Subject: [PATCH] 1. added flags to splitter drawing functions and replaced GetSplitterBorderAndSash() with GetSplitterParams() 2. added support for "hot tracking" to wxSplitterWindow 3. added GTK2 support for the splitter to GTK renderer git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@22427 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/generic/splitter.h | 15 +++++- include/wx/renderer.h | 41 +++++++++++++--- src/generic/renderg.cpp | 34 +++++++++---- src/generic/splitter.cpp | 56 +++++++++++++++++----- src/gtk/renderer.cpp | 89 +++++++++++++++++++++++++---------- src/gtk1/renderer.cpp | 89 +++++++++++++++++++++++++---------- src/mac/carbon/renderer.cpp | 6 ++- src/mac/renderer.cpp | 6 ++- 8 files changed, 254 insertions(+), 82 deletions(-) diff --git a/include/wx/generic/splitter.h b/include/wx/generic/splitter.h index 40a07464de..38420cdd65 100644 --- a/include/wx/generic/splitter.h +++ b/include/wx/generic/splitter.h @@ -245,12 +245,18 @@ protected: // set the sash position and send an event about it having been changed void SetSashPositionAndNotify(int sashPos); + // callbacks executed when we detect that the mouse has entered or left + // the sash + virtual void OnEnterSash(); + virtual void OnLeaveSash(); + // set the cursor appropriate for the current split mode void SetResizeCursor(); + // redraw the splitter if its "hotness" changed if necessary + void RedrawIfHotSensitive(bool isHot); + wxSplitMode m_splitMode; - bool m_permitUnsplitAlways; - bool m_needUpdating; // when in live mode, set this to TRUE to resize children in idle wxWindow* m_windowOne; wxWindow* m_windowTwo; int m_dragMode; @@ -266,6 +272,11 @@ protected: wxCursor m_sashCursorNS; wxPen *m_sashTrackerPen; + // when in live mode, set this to TRUE to resize children in idle + bool m_needUpdating:1; + bool m_permitUnsplitAlways:1; + bool m_isHot:1; + private: WX_DECLARE_CONTROL_CONTAINER(); diff --git a/include/wx/renderer.h b/include/wx/renderer.h index 2906de378a..366583dbde 100644 --- a/include/wx/renderer.h +++ b/include/wx/renderer.h @@ -62,6 +62,29 @@ enum wxCONTROL_DIRTY = 0x80000000 }; +// ---------------------------------------------------------------------------- +// helper structs +// ---------------------------------------------------------------------------- + +// wxSplitterWindow parameters +struct WXDLLEXPORT wxSplitterRenderParams +{ + // the only way to initialize this struct is by using this ctor + wxSplitterRenderParams(wxCoord widthSash_, wxCoord border_, bool isSens_) + : widthSash(widthSash_), border(border_), isHotSensitive(isSens_) + { + } + + // the width of the splitter sash + const wxCoord widthSash; + + // the width of the border of the splitter window + const wxCoord border; + + // true if the splitter changes its appearance when the mouse is over it + const bool isHotSensitive; +}; + // ---------------------------------------------------------------------------- // wxRendererNative: abstracts drawing methods needed by the native controls // ---------------------------------------------------------------------------- @@ -90,14 +113,16 @@ public: // drawn by DrawSash() blends into it well virtual void DrawSplitterBorder(wxWindow *win, wxDC& dc, - const wxRect& rect) = 0; + const wxRect& rect, + int flags = 0) = 0; // draw a (vertical) sash virtual void DrawSplitterSash(wxWindow *win, wxDC& dc, const wxSize& size, wxCoord position, - wxOrientation orient) = 0; + wxOrientation orient, + int flags = 0) = 0; // geometry functions @@ -105,7 +130,7 @@ public: // get the splitter parameters: the x field of the returned point is the // sash width and the y field is the border width - virtual wxPoint GetSplitterSashAndBorder(const wxWindow *win) = 0; + virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win) = 0; // pseudo constructors @@ -149,19 +174,21 @@ public: virtual void DrawSplitterBorder(wxWindow *win, wxDC& dc, - const wxRect& rect) + const wxRect& rect, + int flags = 0) { m_rendererNative.DrawSplitterBorder(win, dc, rect); } virtual void DrawSplitterSash(wxWindow *win, wxDC& dc, const wxSize& size, wxCoord position, - wxOrientation orient) + wxOrientation orient, + int flags = 0) { m_rendererNative.DrawSplitterSash(win, dc, size, position, orient); } - virtual wxPoint GetSplitterSashAndBorder(const wxWindow *win) - { return m_rendererNative.GetSplitterSashAndBorder(win); } + virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win) + { return m_rendererNative.GetSplitterParams(win); } protected: wxRendererNative& m_rendererNative; diff --git a/src/generic/renderg.cpp b/src/generic/renderg.cpp index 15af1286b6..758e30835b 100644 --- a/src/generic/renderg.cpp +++ b/src/generic/renderg.cpp @@ -59,16 +59,18 @@ public: virtual void DrawSplitterBorder(wxWindow *win, wxDC& dc, - const wxRect& rect); + const wxRect& rect, + int flags = 0); virtual void DrawSplitterSash(wxWindow *win, wxDC& dc, const wxSize& size, wxCoord position, - wxOrientation orient); + wxOrientation orient, + int flags = 0); - virtual wxPoint GetSplitterSashAndBorder(const wxWindow *win); + virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win); protected: @@ -197,17 +199,32 @@ wxRendererGeneric::DrawTreeItemButton(wxWindow * WXUNUSED(win), // sash drawing // ---------------------------------------------------------------------------- -wxPoint -wxRendererGeneric::GetSplitterSashAndBorder(const wxWindow *win) +wxSplitterRenderParams +wxRendererGeneric::GetSplitterParams(const wxWindow *win) { // see below - return win->HasFlag(wxSP_3D) ? wxPoint(7, 2) : wxPoint(3, 0); + wxCoord sashWidth, + border; + + if ( win->HasFlag(wxSP_3D) ) + { + sashWidth = 7; + border = 3; + } + else // no 3D effect + { + sashWidth = 2; + border = 0; + } + + return wxSplitterRenderParams(sashWidth, border, false); } void wxRendererGeneric::DrawSplitterBorder(wxWindow *win, wxDC& dc, - const wxRect& rectOrig) + const wxRect& rectOrig, + int WXUNUSED(falgs)) { if ( win->HasFlag(wxSP_3D) ) { @@ -222,7 +239,8 @@ wxRendererGeneric::DrawSplitterSash(wxWindow *win, wxDC& dcReal, const wxSize& sizeReal, wxCoord position, - wxOrientation orient) + wxOrientation orient, + int WXUNUSED(flags)) { // to avoid duplicating the same code for horizontal and vertical sashes, // simply mirror the DC instead if needed (i.e. if horz splitter) diff --git a/src/generic/splitter.cpp b/src/generic/splitter.cpp index 70fbed666e..e4f0ad4b39 100644 --- a/src/generic/splitter.cpp +++ b/src/generic/splitter.cpp @@ -109,6 +109,7 @@ void wxSplitterWindow::Init() m_sashTrackerPen = new wxPen(*wxBLACK, 2, wxSOLID); m_needUpdating = FALSE; + m_isHot = false; } wxSplitterWindow::~wxSplitterWindow() @@ -116,12 +117,46 @@ wxSplitterWindow::~wxSplitterWindow() delete m_sashTrackerPen; } +// ---------------------------------------------------------------------------- +// entering/leaving sash +// ---------------------------------------------------------------------------- + +void wxSplitterWindow::RedrawIfHotSensitive(bool isHot) +{ + if ( wxRendererNative::Get().GetSplitterParams(this).isHotSensitive ) + { + m_isHot = isHot; + + wxClientDC dc(this); + DrawSash(dc); + } + //else: we don't change our appearance, don't redraw to avoid flicker +} + +void wxSplitterWindow::OnEnterSash() +{ + SetResizeCursor(); + + RedrawIfHotSensitive(true); +} + +void wxSplitterWindow::OnLeaveSash() +{ + SetCursor(*wxSTANDARD_CURSOR); + + RedrawIfHotSensitive(false); +} + void wxSplitterWindow::SetResizeCursor() { SetCursor(m_splitMode == wxSPLIT_VERTICAL ? m_sashCursorWE : m_sashCursorNS); } +// ---------------------------------------------------------------------------- +// other event handlers +// ---------------------------------------------------------------------------- + void wxSplitterWindow::OnPaint(wxPaintEvent& WXUNUSED(event)) { wxPaintDC dc(this); @@ -252,15 +287,10 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event) } // left up && dragging else if ((event.Moving() || event.Leaving() || event.Entering()) && (m_dragMode == wxSPLIT_DRAG_NONE)) { - // Just change the cursor as required - if ( !event.Leaving() && SashHitTest(x, y) ) - { - SetResizeCursor(); - } + if ( event.Leaving() || !SashHitTest(x, y) ) + OnLeaveSash(); else - { - SetCursor(* wxSTANDARD_CURSOR); - } + OnEnterSash(); } else if (event.Dragging() && (m_dragMode == wxSPLIT_DRAG_DRAGGING)) { @@ -387,12 +417,12 @@ bool wxSplitterWindow::SashHitTest(int x, int y, int tolerance) int wxSplitterWindow::GetSashSize() const { - return wxRendererNative::Get().GetSplitterSashAndBorder(this).x; + return wxRendererNative::Get().GetSplitterParams(this).widthSash; } int wxSplitterWindow::GetBorderSize() const { - return wxRendererNative::Get().GetSplitterSashAndBorder(this).y; + return wxRendererNative::Get().GetSplitterParams(this).border; } // Draw the sash @@ -419,9 +449,9 @@ void wxSplitterWindow::DrawSash(wxDC& dc) dc, GetClientSize(), m_sashPosition, - m_splitMode == wxSPLIT_VERTICAL - ? wxVERTICAL - : wxHORIZONTAL + m_splitMode == wxSPLIT_VERTICAL ? wxVERTICAL + : wxHORIZONTAL, + m_isHot ? wxCONTROL_CURRENT : 0 ); } diff --git a/src/gtk/renderer.cpp b/src/gtk/renderer.cpp index dea620908f..949fe5da1a 100644 --- a/src/gtk/renderer.cpp +++ b/src/gtk/renderer.cpp @@ -38,6 +38,12 @@ #include "wx/settings.h" #endif // GTK 2.0 +#ifdef __WXGTK20__ + #define WXUNUSED_IN_GTK1(arg) arg +#else + #define WXUNUSED_IN_GTK1(arg) +#endif + // ---------------------------------------------------------------------------- // wxRendererGTK: our wxRendererNative implementation // ---------------------------------------------------------------------------- @@ -61,14 +67,16 @@ public: virtual void DrawSplitterBorder(wxWindow *win, wxDC& dc, - const wxRect& rect) ; + const wxRect& rect, + int flags = 0); virtual void DrawSplitterSash(wxWindow *win, wxDC& dc, const wxSize& size, wxCoord position, - wxOrientation orient); + wxOrientation orient, + int flags = 0); - virtual wxPoint GetSplitterSashAndBorder(const wxWindow *win); + virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win); }; // ============================================================================ @@ -151,24 +159,42 @@ wxRendererGTK::DrawTreeItemButton(wxWindow* WXUNUSED(win), // splitter sash drawing // ---------------------------------------------------------------------------- -// the full sash width (should be even) -static const wxCoord SASH_SIZE = 10; +// all this should probably be read from the current theme settings somehow? +#ifdef __WXGTK20__ + // the full sash size + static const wxCoord SASH_FULL_SIZE = 5; +#else // GTK+ 1.x + // the full sash width (should be even) + static const wxCoord SASH_SIZE = 10; + + // margin around the sash + static const wxCoord SASH_MARGIN = 5; -// margin around the sash -static const wxCoord SASH_MARGIN = 5; + // the full sash size + static const wxCoord SASH_FULL_SIZE = SASH_SIZE + SASH_MARGIN; +#endif // GTK+ 2.x/1.x -wxPoint -wxRendererGTK::GetSplitterSashAndBorder(const wxWindow * WXUNUSED(win)) +wxSplitterRenderParams +wxRendererGTK::GetSplitterParams(const wxWindow * WXUNUSED(win)) { - // we don't draw any border, hence 0 for the second field, but we must - // leave some margin around the sash - return wxPoint(SASH_SIZE + SASH_MARGIN, 0); + // we don't draw any border, hence 0 for the second field + return wxSplitterRenderParams + ( + SASH_FULL_SIZE, + 0, +#ifdef __WXGTK20__ + true // hot sensitive +#else // GTK+ 1.x + false // not +#endif // GTK+ 2.x/1.x + ); } void wxRendererGTK::DrawSplitterBorder(wxWindow * WXUNUSED(win), wxDC& WXUNUSED(dc), - const wxRect& WXUNUSED(rect)) + const wxRect& WXUNUSED(rect), + int WXUNUSED(flags)) { // nothing to do } @@ -178,7 +204,8 @@ wxRendererGTK::DrawSplitterSash(wxWindow *win, wxDC& dc, const wxSize& size, wxCoord position, - wxOrientation orient) + wxOrientation orient, + int WXUNUSED_IN_GTK1(flags)) { if ( !win->m_wxwindow->window ) { @@ -189,26 +216,43 @@ wxRendererGTK::DrawSplitterSash(wxWindow *win, // are we drawing vertical or horizontal splitter? const bool isVert = orient == wxVERTICAL; - // we must erase everything first, otherwise the garbage from the old sash - // is left when dragging it - // - // TODO: is this the right way to draw themed background? GdkRectangle rect; if ( isVert ) { rect.x = position; rect.y = 0; - rect.width = SASH_SIZE + SASH_MARGIN; + rect.width = SASH_FULL_SIZE; rect.height = size.y; } else // horz { rect.x = 0; rect.y = position; - rect.height = SASH_SIZE + SASH_MARGIN; + rect.height = SASH_FULL_SIZE; rect.width = size.x; } +#ifdef __WXGTK20__ + gtk_paint_handle + ( + win->m_wxwindow->style, + GTK_PIZZA(win->m_wxwindow)->bin_window, + flags & wxCONTROL_CURRENT ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL, + GTK_SHADOW_NONE, + NULL /* no clipping */, + win->m_wxwindow, + "paned", + rect.x, + rect.y, + rect.width, + rect.height, + isVert ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL + ); +#else // GTK+ 1.x + // we must erase everything first, otherwise the garbage from the old sash + // is left when dragging it + // + // TODO: is this the right way to draw themed background? gtk_paint_flat_box ( win->m_wxwindow->style, @@ -229,11 +273,7 @@ wxRendererGTK::DrawSplitterSash(wxWindow *win, typedef void (*GtkPaintLineFunc)(GtkStyle *, GdkWindow *, GtkStateType, GdkRectangle *, GtkWidget *, -#ifdef __WXGTK20__ - const gchar *, -#else gchar *, -#endif gint, gint, gint); GtkPaintLineFunc func = isVert ? gtk_paint_vline : gtk_paint_hline; @@ -262,5 +302,6 @@ wxRendererGTK::DrawSplitterSash(wxWindow *win, isVert ? size.y - 2*SASH_SIZE : position, SASH_SIZE, SASH_SIZE ); +#endif // GTK+ 2.x/1.x } diff --git a/src/gtk1/renderer.cpp b/src/gtk1/renderer.cpp index dea620908f..949fe5da1a 100644 --- a/src/gtk1/renderer.cpp +++ b/src/gtk1/renderer.cpp @@ -38,6 +38,12 @@ #include "wx/settings.h" #endif // GTK 2.0 +#ifdef __WXGTK20__ + #define WXUNUSED_IN_GTK1(arg) arg +#else + #define WXUNUSED_IN_GTK1(arg) +#endif + // ---------------------------------------------------------------------------- // wxRendererGTK: our wxRendererNative implementation // ---------------------------------------------------------------------------- @@ -61,14 +67,16 @@ public: virtual void DrawSplitterBorder(wxWindow *win, wxDC& dc, - const wxRect& rect) ; + const wxRect& rect, + int flags = 0); virtual void DrawSplitterSash(wxWindow *win, wxDC& dc, const wxSize& size, wxCoord position, - wxOrientation orient); + wxOrientation orient, + int flags = 0); - virtual wxPoint GetSplitterSashAndBorder(const wxWindow *win); + virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win); }; // ============================================================================ @@ -151,24 +159,42 @@ wxRendererGTK::DrawTreeItemButton(wxWindow* WXUNUSED(win), // splitter sash drawing // ---------------------------------------------------------------------------- -// the full sash width (should be even) -static const wxCoord SASH_SIZE = 10; +// all this should probably be read from the current theme settings somehow? +#ifdef __WXGTK20__ + // the full sash size + static const wxCoord SASH_FULL_SIZE = 5; +#else // GTK+ 1.x + // the full sash width (should be even) + static const wxCoord SASH_SIZE = 10; + + // margin around the sash + static const wxCoord SASH_MARGIN = 5; -// margin around the sash -static const wxCoord SASH_MARGIN = 5; + // the full sash size + static const wxCoord SASH_FULL_SIZE = SASH_SIZE + SASH_MARGIN; +#endif // GTK+ 2.x/1.x -wxPoint -wxRendererGTK::GetSplitterSashAndBorder(const wxWindow * WXUNUSED(win)) +wxSplitterRenderParams +wxRendererGTK::GetSplitterParams(const wxWindow * WXUNUSED(win)) { - // we don't draw any border, hence 0 for the second field, but we must - // leave some margin around the sash - return wxPoint(SASH_SIZE + SASH_MARGIN, 0); + // we don't draw any border, hence 0 for the second field + return wxSplitterRenderParams + ( + SASH_FULL_SIZE, + 0, +#ifdef __WXGTK20__ + true // hot sensitive +#else // GTK+ 1.x + false // not +#endif // GTK+ 2.x/1.x + ); } void wxRendererGTK::DrawSplitterBorder(wxWindow * WXUNUSED(win), wxDC& WXUNUSED(dc), - const wxRect& WXUNUSED(rect)) + const wxRect& WXUNUSED(rect), + int WXUNUSED(flags)) { // nothing to do } @@ -178,7 +204,8 @@ wxRendererGTK::DrawSplitterSash(wxWindow *win, wxDC& dc, const wxSize& size, wxCoord position, - wxOrientation orient) + wxOrientation orient, + int WXUNUSED_IN_GTK1(flags)) { if ( !win->m_wxwindow->window ) { @@ -189,26 +216,43 @@ wxRendererGTK::DrawSplitterSash(wxWindow *win, // are we drawing vertical or horizontal splitter? const bool isVert = orient == wxVERTICAL; - // we must erase everything first, otherwise the garbage from the old sash - // is left when dragging it - // - // TODO: is this the right way to draw themed background? GdkRectangle rect; if ( isVert ) { rect.x = position; rect.y = 0; - rect.width = SASH_SIZE + SASH_MARGIN; + rect.width = SASH_FULL_SIZE; rect.height = size.y; } else // horz { rect.x = 0; rect.y = position; - rect.height = SASH_SIZE + SASH_MARGIN; + rect.height = SASH_FULL_SIZE; rect.width = size.x; } +#ifdef __WXGTK20__ + gtk_paint_handle + ( + win->m_wxwindow->style, + GTK_PIZZA(win->m_wxwindow)->bin_window, + flags & wxCONTROL_CURRENT ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL, + GTK_SHADOW_NONE, + NULL /* no clipping */, + win->m_wxwindow, + "paned", + rect.x, + rect.y, + rect.width, + rect.height, + isVert ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL + ); +#else // GTK+ 1.x + // we must erase everything first, otherwise the garbage from the old sash + // is left when dragging it + // + // TODO: is this the right way to draw themed background? gtk_paint_flat_box ( win->m_wxwindow->style, @@ -229,11 +273,7 @@ wxRendererGTK::DrawSplitterSash(wxWindow *win, typedef void (*GtkPaintLineFunc)(GtkStyle *, GdkWindow *, GtkStateType, GdkRectangle *, GtkWidget *, -#ifdef __WXGTK20__ - const gchar *, -#else gchar *, -#endif gint, gint, gint); GtkPaintLineFunc func = isVert ? gtk_paint_vline : gtk_paint_hline; @@ -262,5 +302,6 @@ wxRendererGTK::DrawSplitterSash(wxWindow *win, isVert ? size.y - 2*SASH_SIZE : position, SASH_SIZE, SASH_SIZE ); +#endif // GTK+ 2.x/1.x } diff --git a/src/mac/carbon/renderer.cpp b/src/mac/carbon/renderer.cpp index 075dd59eb0..07ae99090a 100644 --- a/src/mac/carbon/renderer.cpp +++ b/src/mac/carbon/renderer.cpp @@ -57,7 +57,8 @@ public: wxDC& dc, const wxSize& size, wxCoord position, - wxOrientation orient); + wxOrientation orient, + int flags = 0); private: // the tree buttons @@ -200,7 +201,8 @@ wxRendererMac::DrawSplitterSash(wxWindow *win, wxDC& dc, const wxSize& size, wxCoord position, - wxOrientation orient) + wxOrientation orient, + int WXUNUSED(flags)) { // VZ: we have to somehow determine if we're drawing a normal sash or // a brushed metal one as they look quite differently... this is diff --git a/src/mac/renderer.cpp b/src/mac/renderer.cpp index 075dd59eb0..07ae99090a 100644 --- a/src/mac/renderer.cpp +++ b/src/mac/renderer.cpp @@ -57,7 +57,8 @@ public: wxDC& dc, const wxSize& size, wxCoord position, - wxOrientation orient); + wxOrientation orient, + int flags = 0); private: // the tree buttons @@ -200,7 +201,8 @@ wxRendererMac::DrawSplitterSash(wxWindow *win, wxDC& dc, const wxSize& size, wxCoord position, - wxOrientation orient) + wxOrientation orient, + int WXUNUSED(flags)) { // VZ: we have to somehow determine if we're drawing a normal sash or // a brushed metal one as they look quite differently... this is -- 2.45.2