Use wxOverlay to show sash feedback in non-live resize mode in wxSplitterWindow
Make non-live resizing possible on all supported platforms thanks to wxOverlay. Previously, live resizing was the only supported mode under these platforms: wxMac, wxQt and wxGTK3 under Wayland. Also remove no longer needed function AlwaysUsesLiveUpdate and its documentation.
This commit is contained in:
parent
fafc714057
commit
a38175885c
4 changed files with 44 additions and 70 deletions
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include "wx/window.h" // base class declaration
|
#include "wx/window.h" // base class declaration
|
||||||
#include "wx/containr.h" // wxControlContainer
|
#include "wx/containr.h" // wxControlContainer
|
||||||
|
#include "wx/overlay.h"
|
||||||
|
|
||||||
class WXDLLIMPEXP_FWD_CORE wxSplitterEvent;
|
class WXDLLIMPEXP_FWD_CORE wxSplitterEvent;
|
||||||
|
|
||||||
|
|
@ -131,9 +132,6 @@ public:
|
||||||
// Is the window split?
|
// Is the window split?
|
||||||
bool IsSplit() const { return (m_windowTwo != nullptr); }
|
bool IsSplit() const { return (m_windowTwo != nullptr); }
|
||||||
|
|
||||||
// Return true if wxSP_LIVE_UPDATE is always used.
|
|
||||||
bool AlwaysUsesLiveUpdate() const;
|
|
||||||
|
|
||||||
// Sets the border size
|
// Sets the border size
|
||||||
void SetBorderSize(int WXUNUSED(width)) { }
|
void SetBorderSize(int WXUNUSED(width)) { }
|
||||||
|
|
||||||
|
|
@ -293,7 +291,7 @@ protected:
|
||||||
int m_minimumPaneSize;
|
int m_minimumPaneSize;
|
||||||
wxCursor m_sashCursorWE;
|
wxCursor m_sashCursorWE;
|
||||||
wxCursor m_sashCursorNS;
|
wxCursor m_sashCursorNS;
|
||||||
wxPen *m_sashTrackerPen;
|
wxOverlay m_overlay;
|
||||||
|
|
||||||
// when in live mode, set this to true to resize children in idle
|
// when in live mode, set this to true to resize children in idle
|
||||||
bool m_needUpdating:1;
|
bool m_needUpdating:1;
|
||||||
|
|
|
||||||
|
|
@ -142,20 +142,6 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual ~wxSplitterWindow();
|
virtual ~wxSplitterWindow();
|
||||||
|
|
||||||
/**
|
|
||||||
Returns true if splitter always behaves as if wxSP_LIVE_UPDATE were
|
|
||||||
specified.
|
|
||||||
|
|
||||||
This function returns true if non-live update mode is not supported and
|
|
||||||
live update is always used, even if wxSP_LIVE_UPDATE was not explicitly
|
|
||||||
specified.
|
|
||||||
|
|
||||||
@see wxClientDC::CanBeUsedForDrawing()
|
|
||||||
|
|
||||||
@since 3.3.0
|
|
||||||
*/
|
|
||||||
bool AlwaysUsesLiveUpdate() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Creation function, for two-step construction.
|
Creation function, for two-step construction.
|
||||||
See wxSplitterWindow() for details.
|
See wxSplitterWindow() for details.
|
||||||
|
|
|
||||||
|
|
@ -254,7 +254,7 @@ MyFrame::MyFrame()
|
||||||
"Toggle sash invisibility");
|
"Toggle sash invisibility");
|
||||||
splitMenu->AppendSeparator();
|
splitMenu->AppendSeparator();
|
||||||
|
|
||||||
auto itemLive = splitMenu->AppendCheckItem(SPLIT_LIVE,
|
splitMenu->AppendCheckItem(SPLIT_LIVE,
|
||||||
"&Live update\tCtrl-L",
|
"&Live update\tCtrl-L",
|
||||||
"Toggle live update mode");
|
"Toggle live update mode");
|
||||||
splitMenu->AppendCheckItem(SPLIT_BORDER,
|
splitMenu->AppendCheckItem(SPLIT_BORDER,
|
||||||
|
|
@ -306,12 +306,6 @@ MyFrame::MyFrame()
|
||||||
menuBar->Check(SPLIT_LIVE, true);
|
menuBar->Check(SPLIT_LIVE, true);
|
||||||
m_splitter = new MySplitterWindow(this);
|
m_splitter = new MySplitterWindow(this);
|
||||||
|
|
||||||
if ( m_splitter->AlwaysUsesLiveUpdate() )
|
|
||||||
{
|
|
||||||
// Only live update mode is supported, so this menu item can't be used.
|
|
||||||
itemLive->Enable(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If you use non-zero gravity you must initialize the splitter with its
|
// If you use non-zero gravity you must initialize the splitter with its
|
||||||
// correct initial size, otherwise it will change the sash position by a
|
// correct initial size, otherwise it will change the sash position by a
|
||||||
// huge amount when it's resized from its initial default size to its real
|
// huge amount when it's resized from its initial default size to its real
|
||||||
|
|
|
||||||
|
|
@ -69,19 +69,34 @@ wxBEGIN_EVENT_TABLE(wxSplitterWindow, wxWindow)
|
||||||
#endif // wxMSW
|
#endif // wxMSW
|
||||||
wxEND_EVENT_TABLE()
|
wxEND_EVENT_TABLE()
|
||||||
|
|
||||||
bool wxSplitterWindow::AlwaysUsesLiveUpdate() const
|
|
||||||
{
|
|
||||||
return !wxClientDC::CanBeUsedForDrawing(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool IsLive(wxSplitterWindow* wnd)
|
static bool IsLive(wxSplitterWindow* wnd)
|
||||||
{
|
{
|
||||||
// with wxSP_LIVE_UPDATE style the splitter windows are always resized
|
// with wxSP_LIVE_UPDATE style the splitter windows are always resized
|
||||||
// following the mouse movement while it drags the sash, without it we only
|
// following the mouse movement while it drags the sash, without it we only
|
||||||
// draw the sash at the new position but only resize the windows when the
|
// draw the sash at the new position but only resize the windows when the
|
||||||
// dragging is finished -- but drawing the sash is done using wxClientDC,
|
// dragging is finished
|
||||||
// so check if we can use it and always use live resizing if we can't
|
return wnd->HasFlag(wxSP_LIVE_UPDATE);
|
||||||
return wnd->AlwaysUsesLiveUpdate() || wnd->HasFlag(wxSP_LIVE_UPDATE);
|
}
|
||||||
|
|
||||||
|
static wxBitmap wxPaneCreateStippleBitmap()
|
||||||
|
{
|
||||||
|
// Notice that wxOverlay, under wxMSW, uses the wxBLACK colour i.e.(0,0,0)
|
||||||
|
// as the key colour for transparency. and using it for the stipple bitmap
|
||||||
|
// will make the sash feedback totaly invisible if the window's background
|
||||||
|
// colour is (192,192,192) or so. (1,1,1) is used instead.
|
||||||
|
unsigned char data[] = { 1,1,1,192,192,192, 192,192,192,1,1,1 };
|
||||||
|
wxImage img(2,2,data,true);
|
||||||
|
return wxBitmap(img);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DrawResizeHint(wxDC& dc, const wxRect& rect)
|
||||||
|
{
|
||||||
|
wxBitmap stipple = wxPaneCreateStippleBitmap();
|
||||||
|
wxBrush brush(stipple);
|
||||||
|
dc.SetBrush(brush);
|
||||||
|
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||||
|
|
||||||
|
dc.DrawRectangle(rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxSplitterWindow::Create(wxWindow *parent, wxWindowID id,
|
bool wxSplitterWindow::Create(wxWindow *parent, wxWindowID id,
|
||||||
|
|
@ -134,7 +149,6 @@ void wxSplitterWindow::Init()
|
||||||
m_minimumPaneSize = 0;
|
m_minimumPaneSize = 0;
|
||||||
m_sashCursorWE = wxCursor(wxCURSOR_SIZEWE);
|
m_sashCursorWE = wxCursor(wxCURSOR_SIZEWE);
|
||||||
m_sashCursorNS = wxCursor(wxCURSOR_SIZENS);
|
m_sashCursorNS = wxCursor(wxCURSOR_SIZENS);
|
||||||
m_sashTrackerPen = new wxPen(*wxBLACK, 2, wxPENSTYLE_SOLID);
|
|
||||||
|
|
||||||
m_needUpdating = false;
|
m_needUpdating = false;
|
||||||
m_isHot = false;
|
m_isHot = false;
|
||||||
|
|
@ -142,7 +156,6 @@ void wxSplitterWindow::Init()
|
||||||
|
|
||||||
wxSplitterWindow::~wxSplitterWindow()
|
wxSplitterWindow::~wxSplitterWindow()
|
||||||
{
|
{
|
||||||
delete m_sashTrackerPen;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
@ -280,10 +293,10 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Erase old tracker
|
// Hide sash tracker
|
||||||
if ( !isLive )
|
if ( !isLive )
|
||||||
{
|
{
|
||||||
DrawSashTracker(m_oldX, m_oldY);
|
m_overlay.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// the position of the click doesn't exactly correspond to
|
// the position of the click doesn't exactly correspond to
|
||||||
|
|
@ -361,9 +374,6 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event)
|
||||||
|
|
||||||
m_sashPositionCurrent = posSashNew;
|
m_sashPositionCurrent = posSashNew;
|
||||||
|
|
||||||
// Erase old tracker
|
|
||||||
DrawSashTracker(m_oldX, m_oldY);
|
|
||||||
|
|
||||||
m_oldX = (m_splitMode == wxSPLIT_VERTICAL ? m_sashPositionCurrent : x);
|
m_oldX = (m_splitMode == wxSPLIT_VERTICAL ? m_sashPositionCurrent : x);
|
||||||
m_oldY = (m_splitMode != wxSPLIT_VERTICAL ? m_sashPositionCurrent : y);
|
m_oldY = (m_splitMode != wxSPLIT_VERTICAL ? m_sashPositionCurrent : y);
|
||||||
|
|
||||||
|
|
@ -380,7 +390,6 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event)
|
||||||
m_oldY = 0;
|
m_oldY = 0;
|
||||||
#endif // __WXMSW__
|
#endif // __WXMSW__
|
||||||
|
|
||||||
// Draw new one
|
|
||||||
DrawSashTracker(m_oldX, m_oldY);
|
DrawSashTracker(m_oldX, m_oldY);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -414,10 +423,10 @@ void wxSplitterWindow::OnMouseCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(even
|
||||||
|
|
||||||
SetCursor(* wxSTANDARD_CURSOR);
|
SetCursor(* wxSTANDARD_CURSOR);
|
||||||
|
|
||||||
// Erase old tracker
|
// Erase sash tracker
|
||||||
if ( !IsLive(this) )
|
if ( !IsLive(this) )
|
||||||
{
|
{
|
||||||
DrawSashTracker(m_oldX, m_oldY);
|
m_overlay.Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -612,43 +621,30 @@ void wxSplitterWindow::DrawSashTracker(int x, int y)
|
||||||
int x1, y1;
|
int x1, y1;
|
||||||
int x2, y2;
|
int x2, y2;
|
||||||
|
|
||||||
|
const int sashTrackerWidth = GetDefaultSashSize();
|
||||||
|
|
||||||
if ( m_splitMode == wxSPLIT_VERTICAL )
|
if ( m_splitMode == wxSPLIT_VERTICAL )
|
||||||
{
|
{
|
||||||
x1 = x2 = wxClip(x, 0, w) + m_sashTrackerPen->GetWidth()/2;
|
x1 = wxClip(x, 0, w);
|
||||||
y1 = 2;
|
x2 = sashTrackerWidth;
|
||||||
y2 = h-2;
|
y1 = 0;
|
||||||
|
y2 = h;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
y1 = y2 = wxClip(y, 0, h) + m_sashTrackerPen->GetWidth()/2;
|
y1 = wxClip(y, 0, h);
|
||||||
x1 = 2;
|
y2 = sashTrackerWidth;
|
||||||
x2 = w-2;
|
x1 = 0;
|
||||||
|
x2 = w;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__WXGTK3__)
|
|
||||||
wxClientDC dc(this);
|
wxClientDC dc(this);
|
||||||
|
wxDCOverlay overlaydc( m_overlay, &dc );
|
||||||
|
overlaydc.Clear();
|
||||||
|
|
||||||
// In the ports with wxGraphicsContext-based wxDC, such as wxGTK3 or wxOSX,
|
const wxRect rect{x1, y1, x2, y2};
|
||||||
// wxINVERT only works for inverting the background when using white
|
|
||||||
// foreground (note that this code is not used anyhow for __WXMAC__ due to
|
|
||||||
// always using live-resizing there, see IsLive()).
|
|
||||||
dc.SetPen(*wxWHITE_PEN);
|
|
||||||
#else
|
|
||||||
// We need to use wxScreenDC and not wxClientDC at least for wxMSW where
|
|
||||||
// drawing in this window itself would be hidden by its children windows,
|
|
||||||
// that cover it almost entirely.
|
|
||||||
wxScreenDC dc;
|
|
||||||
ClientToScreen(&x1, &y1);
|
|
||||||
ClientToScreen(&x2, &y2);
|
|
||||||
|
|
||||||
dc.SetPen(*m_sashTrackerPen);
|
DrawResizeHint(dc, rect);
|
||||||
#endif
|
|
||||||
|
|
||||||
dc.SetLogicalFunction(wxINVERT);
|
|
||||||
|
|
||||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
|
||||||
|
|
||||||
dc.DrawLine(x1, y1, x2, y2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int wxSplitterWindow::GetWindowSize() const
|
int wxSplitterWindow::GetWindowSize() const
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue