Introduce platform-dependent wxTLWGeometry class

Previously, TLW geometry was implicitly defined as just its position,
size and the maximized/iconized state by wxPersistentTLW code. This
already wasn't enough for wxGTK which added the decoration sizes to the
geometry being saved/restored, but this had to be done using conditional
compilation, which was not ideal. And it didn't allow using an entirely
different geometry representation as will be done for wxMSW soon.

Change the code to use wxTLWGeometry class defining the geometry, as
used by the current port, explicitly and move wxPersistentTLW logic into
it, as wxPersistentXXX classes are supposed to be very simple, which
wasn't really the case.

Also provide public SaveGeometry() and RestoreToGeometry() methods in
wxTopLevelWindow, which can be useful even to people not using
wxPersistentTLW for whatever reason.

There should be no changes in behaviour so far.
This commit is contained in:
Vadim Zeitlin
2018-04-29 19:37:42 +02:00
parent f04a46364c
commit d97c055514
6 changed files with 410 additions and 92 deletions

View File

@@ -13,7 +13,6 @@
#include "wx/persist/window.h"
#include "wx/toplevel.h"
#include "wx/display.h"
// ----------------------------------------------------------------------------
// string constants used by wxPersistentTLW
@@ -24,21 +23,13 @@
// windows, just persistent controls which have their own specific kind strings
#define wxPERSIST_TLW_KIND "Window"
// names for various persistent options
#define wxPERSIST_TLW_X "x"
#define wxPERSIST_TLW_Y "y"
#define wxPERSIST_TLW_W "w"
#define wxPERSIST_TLW_H "h"
#define wxPERSIST_TLW_MAXIMIZED "Maximized"
#define wxPERSIST_TLW_ICONIZED "Iconized"
// ----------------------------------------------------------------------------
// wxPersistentTLW: supports saving/restoring window position and size as well
// as maximized/iconized/restore state
// ----------------------------------------------------------------------------
class wxPersistentTLW : public wxPersistentWindow<wxTopLevelWindow>
class wxPersistentTLW : public wxPersistentWindow<wxTopLevelWindow>,
private wxTopLevelWindow::GeometrySerializer
{
public:
wxPersistentTLW(wxTopLevelWindow *tlw)
@@ -50,96 +41,28 @@ public:
{
const wxTopLevelWindow * const tlw = Get();
const wxPoint pos = tlw->GetScreenPosition();
SaveValue(wxPERSIST_TLW_X, pos.x);
SaveValue(wxPERSIST_TLW_Y, pos.y);
// notice that we use GetSize() here and not GetClientSize() because
// the latter doesn't return correct results for the minimized windows
// (at least not under Windows)
//
// of course, it shouldn't matter anyhow usually, the client size
// should be preserved as well unless the size of the decorations
// changed between the runs
const wxSize size = tlw->GetSize();
SaveValue(wxPERSIST_TLW_W, size.x);
SaveValue(wxPERSIST_TLW_H, size.y);
SaveValue(wxPERSIST_TLW_MAXIMIZED, tlw->IsMaximized());
SaveValue(wxPERSIST_TLW_ICONIZED, tlw->IsIconized());
#ifdef __WXGTK20__
SaveValue("decor_l", tlw->m_decorSize.left);
SaveValue("decor_r", tlw->m_decorSize.right);
SaveValue("decor_t", tlw->m_decorSize.top);
SaveValue("decor_b", tlw->m_decorSize.bottom);
#endif
tlw->SaveGeometry(*this);
}
virtual bool Restore() wxOVERRIDE
{
wxTopLevelWindow * const tlw = Get();
wxPoint pos;
wxSize size;
const bool hasPos = RestoreValue(wxPERSIST_TLW_X, &pos.x) &&
RestoreValue(wxPERSIST_TLW_Y, &pos.y);
const bool hasSize = RestoreValue(wxPERSIST_TLW_W, &size.x) &&
RestoreValue(wxPERSIST_TLW_H, &size.y);
#ifdef __WXGTK20__
wxTopLevelWindowGTK::DecorSize decorSize;
if (tlw->m_decorSize.top == 0 &&
RestoreValue("decor_l", &decorSize.left) &&
RestoreValue("decor_r", &decorSize.right) &&
RestoreValue("decor_t", &decorSize.top) &&
RestoreValue("decor_b", &decorSize.bottom))
{
tlw->m_decorSize = decorSize;
}
#endif
if ( hasPos )
{
// to avoid making the window completely invisible if it had been
// shown on a monitor which was disconnected since the last run
// (this is pretty common for notebook with external displays)
//
// NB: we should allow window position to be (slightly) off screen,
// it's not uncommon to position the window so that its upper
// left corner has slightly negative coordinate
if ( wxDisplay::GetFromPoint(pos) != wxNOT_FOUND ||
(hasSize && wxDisplay::GetFromPoint(pos + size) != wxNOT_FOUND) )
{
tlw->Move(pos, wxSIZE_ALLOW_MINUS_ONE);
}
//else: should we try to adjust position/size somehow?
}
if ( hasSize )
{
// a previous version of the program could have saved the window
// size which used to be big enough, but which is not big enough
// any more for the new version, so check that the size we restore
// doesn't cut off parts of the window
size.IncTo(tlw->GetBestSize());
tlw->SetSize(size);
}
// note that the window can be both maximized and iconized
bool maximized;
if ( RestoreValue(wxPERSIST_TLW_MAXIMIZED, &maximized) && maximized )
tlw->Maximize();
bool iconized;
if ( RestoreValue(wxPERSIST_TLW_ICONIZED, &iconized) && iconized )
tlw->Iconize();
// the most important property of the window that we restore is its
// size, so disregard the value of hasPos here
return hasSize;
return tlw->RestoreToGeometry(*this);
}
virtual wxString GetKind() const wxOVERRIDE { return wxPERSIST_TLW_KIND; }
private:
virtual bool SaveField(const wxString& name, int value) const wxOVERRIDE
{
return SaveValue(name, value);
}
virtual bool RestoreField(const wxString& name, int* value) wxOVERRIDE
{
return RestoreValue(name, value);
}
};
inline wxPersistentObject *wxCreatePersistentObject(wxTopLevelWindow *tlw)