%% options copyright owner = Dirk Krause copyright year = 2011-xxxx license = bsd %% header #include #include #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include #endif #include "DkWxAppHelper.h" #include "DkWxHelpController.h" /** Base class for top-level frames. This class keeps pointers to an application helper for file search and localization and a pointer to a help controller object managing online help for both *.chm and *.htb based help. Derive your applications frames from this class. */ class DkWxFrame : public wxFrame { private: /** Number of windows currently open. */ static int iInstances; /** Keywords to save and retrieve size and position data. */ static wxChar const * const kwSizePos[]; /** Preference keys whether or not to restore maxizmed and iconized. */ static dkChar const * const kwRestoreFeatures[]; protected: /** Helper object for file search and internationalization. */ DkWxAppHelper *pHelper; /** Help controller for chm and htb based help files. */ DkWxHelpController *helpController; /** Save current position. */ void savePosition(); public: /** Constructor. @param applicationName Application name. @param applicationHelper Helper object. @param applicationHelp Help controller. @param wxid Window ID. */ DkWxFrame( wxChar const *applicationName, DkWxAppHelper *applicationHelper, DkWxHelpController *applicationHelp, int wxid ); /** Restore previous position or center on screen. */ void restorePosition(); /** Handler for close event. @param event Event to process. */ void OnClose(wxCloseEvent & event); /** Check whether we can close the frame. @param isLast Flag: Last frame instance of application. @return Permission to close. */ virtual bool canClose(bool isLast); /** Open help system if help controller available. */ void openHelp(); /** Open help section specified by name. @param name Section name. */ void openHelpSectionByName(wxString const & name); /** Open help section specified by section number. @param number Section number (context ID). */ void openHelpSectionByNumber(int number); }; %% module /** @file DkWxFrame.cpp Implementation of DkWxFrame. */ #include "DkWxFrame.h" $!trace-include int DkWxFrame::iInstances = 0; wxChar const * const DkWxFrame::kwSizePos[] = { /* 0 */ wxT("window.x"), /* 1 */ wxT("window.y"), /* 2 */ wxT("window.w"), /* 3 */ wxT("window.h"), /* 4 */ wxT("window.maximized"), /* 5 */ wxT("window.iconized"), NULL }; dkChar const * const DkWxFrame::kwRestoreFeatures[] = { /* 0 */ dkT("/window/restore-maximized"), /* 1 */ dkT("/window/restore-iconized"), /* 2 */ dkT("/window/restore-size"), NULL }; DkWxFrame::DkWxFrame( wxChar const *applicationName, DkWxAppHelper *applicationHelper, DkWxHelpController *applicationHelp, int wxid ) : wxFrame(NULL, wxid, applicationName) { $? "+ DkWxFrame::DkWxFrame" /* Initialize elements. */ pHelper = NULL; helpController = applicationHelp; /* Set elements. */ pHelper = applicationHelper; iInstances++; Connect(wxid, wxEVT_CLOSE_WINDOW, wxCloseEventHandler(DkWxFrame::OnClose)); $? "- DkWxFrame::DkWxFrame" } void DkWxFrame::OnClose(wxCloseEvent & event) { bool doClose = true; $? "+ DkWxFrame::OnClose" if(event.CanVeto()) { doClose = canClose(iInstances == 1); } else { canClose(iInstances == 1); } if(doClose) { $? ". close window" /* For last instance save position. */ if(iInstances-- == 1) { $? ". save position" savePosition(); } /* Process close event. */ event.Skip(); } else { $? ". veto event" /* Do not close the window. */ event.Veto(); } $? "- DkWxFrame::OnClose" } void DkWxFrame::restorePosition() { int p[6]; /* Values retrieved from application helper */ wxSize scsz; /* Screen size */ int x; /* X position */ int y; /* Y position */ int w; /* Width */ int h; /* Height */ int rs; /* Flag: Attempt to restore size */ p[0] = p[1] = -1; p[2] = p[3] = p[4] = w = h = 0; pHelper->retrieveMultipleInts(kwSizePos, p); if ((0 > p[0]) || (0 > p[1])) { CentreOnScreen(); } else { scsz = wxGetDisplaySize(); x = p[0]; y = p[1]; GetSize(&w, &h); #if wxCHECK_VERSION(3,0,0) rs = 0; #else rs = 1; #endif rs = dk3app_get_pref_bool(pHelper->getApp(), kwRestoreFeatures[2], rs); if (0 != rs) { if (p[2] > w) { w = p[2]; } if (p[3] > h) { h = p[3]; } } if ((x + w) >= scsz.GetWidth()) { x = scsz.GetWidth() - w; } if ((y + h) >= scsz.GetHeight()) { y = scsz.GetHeight() - h; } if (0 > x) { x = 0; } if (0 > y) { y = 0; } if (0 != rs) { SetSize(x, y, w, h); } else { SetPosition(wxPoint(x, y)); } if (0 != dk3app_get_pref_bool(pHelper->getApp(), kwRestoreFeatures[0], 0)) { if (0 != p[4]) { Maximize(true); } } if (0 != dk3app_get_pref_bool(pHelper->getApp(), kwRestoreFeatures[1], 0)) { if (0 != p[5]) { Iconize(true); } } } } #if VERSION_BEFORE_20160902 void DkWxFrame::restorePosition() { #if 1 int p[6]; size_t num; int w, h; int restoreFeature; $? "+ DkWxFrame::restorePosition" p[0] = p[1] = p[2] = p[3] p[4] = p[5] = w = h = 0; if((num = pHelper->retrieveMultipleInts(kwSizePos, p)) >= 4) { $? ". saved coordinates" $? ". x = %d", p[0] $? ". y = %d", p[1] $? ". w = %d", p[2] $? ". h = %d", p[3] $? ". m = %d", p[4] $? ". i = %d", p[5] wxSize scsz = wxGetDisplaySize(); GetSize(&w, &h); $? ". current coordinates" $? ". w = %d", w $? ". h = %d", h if(w > p[2]) { p[2] = w; } if(h > p[3]) { p[3] = h; } $? ". screen width = %d %d", scsz.GetWidth(), scsz.x $? ". screen height = %d %d", scsz.GetHeight(), scsz.y #if wxCHECK_VERSION(3,0,0) { wxSize minSize = GetMinSize(); if (p[2] < minSize.x) { p[2] = minSize.x; } if (p[3] < minSize.y) { p[3] = minSize.y; } } #endif if((p[0] + p[2]) > scsz.GetWidth()) { p[0] = scsz.GetWidth() - p[2]; } if((p[1] + p[3]) > scsz.GetHeight()) { p[1] = scsz.GetHeight() - p[3]; } if(p[0] < 0) { p[0] = 0; } if(p[1] < 0) { p[1] = 0; } $? ". new coordinates" $? ". x = %d", p[0] $? ". y = %d", p[1] $? ". w = %d", p[2] $? ". h = %d", p[3] /* This variant allows to decrease the frame below the minimum size. */ #if wxCHECK_VERSION(3,0,0) SetPosition(wxPoint(p[0], p[1])); #else SetSize(p[0], p[1], p[2], p[3]); #endif restoreFeature = dk3app_get_pref_bool( pHelper->getApp(), kwRestoreFeatures[0], 0 ); if((restoreFeature) && (4 < num)) { if(0 != p[4]) { Maximize(true); } } restoreFeature = dk3app_get_pref_bool( pHelper->getApp(), kwRestoreFeatures[1], 0 ); if((restoreFeature) && (5 < num)) { if(0 != p[5]) { Iconize(true); } } } else { CentreOnScreen(); } $? "- DkWxFrame::restorePosition" #else int x = 0; int y = 0; int w = 0; int h = 0; wxSize scsz = wxGetDisplaySize(); GetPosition(&x, &y); GetSize(&w, &h); #endif } #endif /* VERSION_BEFORE_20160902 */ void DkWxFrame::savePosition() { int p[6]; $? "+ DkWxFrame::savePosition" p[4] = 0; p[5] = 0; if(IsIconized()) { p[5] = 1; Iconize(false); } if(IsMaximized()) { p[4] = 1; Maximize(false); } GetPosition(&(p[0]), &(p[1])); GetSize(&(p[2]), &(p[3])); if(pHelper) { $? ". x = %d", p[0] $? ". y = %d", p[1] $? ". w = %d", p[2] $? ". h = %d", p[3] pHelper->saveMultipleInts(kwSizePos, p); } $? "- DkWxFrame::savePosition" } bool DkWxFrame::canClose(bool isLast) { $? "= DkWxFrame::canClose 1" return true; } void DkWxFrame::openHelp() { $? "+ DkWxFrame::openHelp" if(helpController) { helpController->openHelp((wxFrame *)this); } $? "- DkWxFrame::openHelp" } void DkWxFrame::openHelpSectionByName(wxString const & name) { $? "+ DkWxFrame::openHelpSectionByName" if (helpController) { helpController->openHelpSectionByName((wxFrame *)this, name); } $? "- DkWxFrame::openHelpSectionByName" } void DkWxFrame::openHelpSectionByNumber(int number) { $? "+ DkWxFrame::openHelpSectionByNumber" if (helpController) { helpController->openHelpSectionByNumber((wxFrame *)this, number); } $? "- DkWxFrame::openHelpSectionByNumber" }