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/containr.h" // wxControlContainer
|
||||
#include "wx/overlay.h"
|
||||
|
||||
class WXDLLIMPEXP_FWD_CORE wxSplitterEvent;
|
||||
|
||||
|
|
@ -131,9 +132,6 @@ public:
|
|||
// Is the window split?
|
||||
bool IsSplit() const { return (m_windowTwo != nullptr); }
|
||||
|
||||
// Return true if wxSP_LIVE_UPDATE is always used.
|
||||
bool AlwaysUsesLiveUpdate() const;
|
||||
|
||||
// Sets the border size
|
||||
void SetBorderSize(int WXUNUSED(width)) { }
|
||||
|
||||
|
|
@ -293,7 +291,7 @@ protected:
|
|||
int m_minimumPaneSize;
|
||||
wxCursor m_sashCursorWE;
|
||||
wxCursor m_sashCursorNS;
|
||||
wxPen *m_sashTrackerPen;
|
||||
wxOverlay m_overlay;
|
||||
|
||||
// when in live mode, set this to true to resize children in idle
|
||||
bool m_needUpdating:1;
|
||||
|
|
|
|||
|
|
@ -142,20 +142,6 @@ public:
|
|||
*/
|
||||
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.
|
||||
See wxSplitterWindow() for details.
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ MyFrame::MyFrame()
|
|||
"Toggle sash invisibility");
|
||||
splitMenu->AppendSeparator();
|
||||
|
||||
auto itemLive = splitMenu->AppendCheckItem(SPLIT_LIVE,
|
||||
splitMenu->AppendCheckItem(SPLIT_LIVE,
|
||||
"&Live update\tCtrl-L",
|
||||
"Toggle live update mode");
|
||||
splitMenu->AppendCheckItem(SPLIT_BORDER,
|
||||
|
|
@ -306,12 +306,6 @@ MyFrame::MyFrame()
|
|||
menuBar->Check(SPLIT_LIVE, true);
|
||||
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
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -69,19 +69,34 @@ wxBEGIN_EVENT_TABLE(wxSplitterWindow, wxWindow)
|
|||
#endif // wxMSW
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
bool wxSplitterWindow::AlwaysUsesLiveUpdate() const
|
||||
{
|
||||
return !wxClientDC::CanBeUsedForDrawing(this);
|
||||
}
|
||||
|
||||
static bool IsLive(wxSplitterWindow* wnd)
|
||||
{
|
||||
// with wxSP_LIVE_UPDATE style the splitter windows are always resized
|
||||
// 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
|
||||
// dragging is finished -- but drawing the sash is done using wxClientDC,
|
||||
// so check if we can use it and always use live resizing if we can't
|
||||
return wnd->AlwaysUsesLiveUpdate() || wnd->HasFlag(wxSP_LIVE_UPDATE);
|
||||
// dragging is finished
|
||||
return 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,
|
||||
|
|
@ -134,7 +149,6 @@ void wxSplitterWindow::Init()
|
|||
m_minimumPaneSize = 0;
|
||||
m_sashCursorWE = wxCursor(wxCURSOR_SIZEWE);
|
||||
m_sashCursorNS = wxCursor(wxCURSOR_SIZENS);
|
||||
m_sashTrackerPen = new wxPen(*wxBLACK, 2, wxPENSTYLE_SOLID);
|
||||
|
||||
m_needUpdating = false;
|
||||
m_isHot = false;
|
||||
|
|
@ -142,7 +156,6 @@ void wxSplitterWindow::Init()
|
|||
|
||||
wxSplitterWindow::~wxSplitterWindow()
|
||||
{
|
||||
delete m_sashTrackerPen;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
@ -280,10 +293,10 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event)
|
|||
return;
|
||||
}
|
||||
|
||||
// Erase old tracker
|
||||
// Hide sash tracker
|
||||
if ( !isLive )
|
||||
{
|
||||
DrawSashTracker(m_oldX, m_oldY);
|
||||
m_overlay.Reset();
|
||||
}
|
||||
|
||||
// the position of the click doesn't exactly correspond to
|
||||
|
|
@ -361,9 +374,6 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event)
|
|||
|
||||
m_sashPositionCurrent = posSashNew;
|
||||
|
||||
// Erase old tracker
|
||||
DrawSashTracker(m_oldX, m_oldY);
|
||||
|
||||
m_oldX = (m_splitMode == wxSPLIT_VERTICAL ? m_sashPositionCurrent : x);
|
||||
m_oldY = (m_splitMode != wxSPLIT_VERTICAL ? m_sashPositionCurrent : y);
|
||||
|
||||
|
|
@ -380,7 +390,6 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event)
|
|||
m_oldY = 0;
|
||||
#endif // __WXMSW__
|
||||
|
||||
// Draw new one
|
||||
DrawSashTracker(m_oldX, m_oldY);
|
||||
}
|
||||
else
|
||||
|
|
@ -414,10 +423,10 @@ void wxSplitterWindow::OnMouseCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(even
|
|||
|
||||
SetCursor(* wxSTANDARD_CURSOR);
|
||||
|
||||
// Erase old tracker
|
||||
// Erase sash tracker
|
||||
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 x2, y2;
|
||||
|
||||
const int sashTrackerWidth = GetDefaultSashSize();
|
||||
|
||||
if ( m_splitMode == wxSPLIT_VERTICAL )
|
||||
{
|
||||
x1 = x2 = wxClip(x, 0, w) + m_sashTrackerPen->GetWidth()/2;
|
||||
y1 = 2;
|
||||
y2 = h-2;
|
||||
x1 = wxClip(x, 0, w);
|
||||
x2 = sashTrackerWidth;
|
||||
y1 = 0;
|
||||
y2 = h;
|
||||
}
|
||||
else
|
||||
{
|
||||
y1 = y2 = wxClip(y, 0, h) + m_sashTrackerPen->GetWidth()/2;
|
||||
x1 = 2;
|
||||
x2 = w-2;
|
||||
y1 = wxClip(y, 0, h);
|
||||
y2 = sashTrackerWidth;
|
||||
x1 = 0;
|
||||
x2 = w;
|
||||
}
|
||||
|
||||
#if defined(__WXGTK3__)
|
||||
wxClientDC dc(this);
|
||||
wxDCOverlay overlaydc( m_overlay, &dc );
|
||||
overlaydc.Clear();
|
||||
|
||||
// In the ports with wxGraphicsContext-based wxDC, such as wxGTK3 or wxOSX,
|
||||
// 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);
|
||||
const wxRect rect{x1, y1, x2, y2};
|
||||
|
||||
dc.SetPen(*m_sashTrackerPen);
|
||||
#endif
|
||||
|
||||
dc.SetLogicalFunction(wxINVERT);
|
||||
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
|
||||
dc.DrawLine(x1, y1, x2, y2);
|
||||
DrawResizeHint(dc, rect);
|
||||
}
|
||||
|
||||
int wxSplitterWindow::GetWindowSize() const
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue