%% options copyright owner = Dirk Krause copyright year = 2015-xxxx license = bsd %% header /** @file Dk4WxFrame.h Base class for top level frames. */ #ifndef DK4CONF_H_INCLUDED #include "dk4conf.h" #endif #ifndef DK4TYPES_H_INCLUDED #include "dk4types.h" #endif #ifndef WX_WXPREC_H_INCLUDED #include #define WX_WXPREC_H_INCLUDED 1 #endif #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #ifndef WX_WX_H_INCLUDED #include #define WX_WX_H_INCLUDED 1 #endif #endif #ifndef DK4WXAPPLICATIONHELPER_H_INCLUDED #include "Dk4WxApplicationHelper.h" #endif #ifndef DK4WXHELPCONTROLLER_H_INCLUDED #include "Dk4WxHelpController.h" #endif /** Frame (top level window). */ class Dk4WxFrame : public wxFrame { protected: /** Application helper. */ Dk4WxApplicationHelper *pAppHelp; /** Help controller for online help. */ Dk4WxHelpController *pHelp; /** Application name. */ wxString sAppName; /** Synchronize access to iInstances. */ static wxCriticalSection csInstances; /** Number of instances. */ static int iInstances; public: /** Constructor. @param appName Application name. @param appHelper Application helper. @param helpController Help controller. @param wxid Window ID. */ Dk4WxFrame( const wxString & appName, Dk4WxApplicationHelper *appHelper, Dk4WxHelpController *helpController, int wxid ); /** Restore previously saved window position. */ void RestorePosition(void); /** Handler for close event. @param event Event to process. */ void OnClose(wxCloseEvent & event); /** Decide whether we can close the frame. @param isFinal Flag: Final frame. @return True to close the frame, false to keep it. */ virtual bool CanClose(bool isFinal); /** Open help system. */ void DisplayContents(void); /** Open help section specified by name. @param name Section name. */ void DisplaySection(wxString const & name); /** Open a help section specified by number. @param number Section number (context ID). */ void DisplaySection(int number); protected: /** Save current window position. */ void SavePosition(void); }; %% module #include "Dk4WxFrame.h" $!trace-include /** Protection for number of instances. */ wxCriticalSection Dk4WxFrame::csInstances; /** Number of instances. */ int Dk4WxFrame::iInstances = 0; /** Keywords to save and restore window size and position. */ static const wxChar * const dk4wxframe_kw_size[] = { $!string-table macro=wxT window.x window.y window.w window.h window.maximized window.iconized $!end }; /** Keywords to restore maximized and iconized state. */ static const wxChar * const dk4wxframe_kw_restore[] = { $!string-table macro=wxT window.restore-maximized window.restore-iconized window.restore-size $!end }; Dk4WxFrame::Dk4WxFrame( const wxString & appName, Dk4WxApplicationHelper *appHelper, Dk4WxHelpController *helpController, int wxid ) : wxFrame(NULL, wxid, appName) { pAppHelp = appHelper; pHelp = helpController; sAppName = appName; { wxCriticalSectionLocker lock(csInstances); iInstances++; } Connect(wxid, wxEVT_CLOSE_WINDOW, wxCloseEventHandler(Dk4WxFrame::OnClose)); } void Dk4WxFrame::OnClose(wxCloseEvent & event) { bool doClose = true; bool isFinal = false; bool savePos = false; { wxCriticalSectionLocker lock(csInstances); if (1 == iInstances) { isFinal = true; } } if (event.CanVeto()) { doClose = CanClose(isFinal); } else { (void)CanClose(isFinal); } if (doClose) { { wxCriticalSectionLocker lock(csInstances); if (1 == iInstances--) { savePos = true; } } if (savePos) { SavePosition(); } event.Skip(); } else { event.Veto(); } } bool Dk4WxFrame::CanClose(bool isFinal) { return true; } void Dk4WxFrame::SavePosition(void) { int iv[6]; if (NULL != pAppHelp) { iv[4] = iv[5] = 0; if (IsIconized()) { iv[5] = 1; Iconize(false); } if (IsMaximized()) { iv[4] = 1; Maximize(false); } GetPosition(&(iv[0]), &(iv[1])); GetSize(&(iv[2]), &(iv[3])); $? ". saving current size" $? ". x = %d", iv[0] $? ". y = %d", iv[1] $? ". w = %d", iv[2] $? ". h = %d", iv[3] pAppHelp->SetMultiple(dk4wxframe_kw_size, iv, 6); } } void Dk4WxFrame::RestorePosition(void) { int iv[6]; /* Values stored in config */ bool bv[3]; /* Feature restore */ int x; /* X position */ int y; /* Y position */ int w; /* Width */ int h; /* Height */ $? "+ Dk4WxFrame::RestorePosition" #if wxCHECK_VERSION(3,0,0) bv[2] = false; #else bv[2] = true; #endif /* Initialize variables. */ iv[0] = iv[1] = -1; iv[2] = iv[3] = iv[4] = iv[5] = 0; bv[0] = bv[1] = false; /* Retrieve stored values if found. */ if (NULL != pAppHelp) { pAppHelp->GetMultiple(dk4wxframe_kw_size, iv, 6); pAppHelp->GetMultiple(dk4wxframe_kw_restore, bv, 3); } /* Find size if not stored. */ GetSize(&w, &h); x = iv[0]; y = iv[1]; /* Correct size if size restoration wanted, increase if necessary. */ if (bv[2]) { $? ". bv[2]" if (iv[2] > w) { w = iv[2]; } if (iv[3] > h) { h = iv[3]; } } /* Correct values, no parts of window should be outside screen. */ Dk4WxApplicationHelper::CorrectPosition(x, y, w, h); /* Set position and optionally size. */ if (bv[2]) { $? ". bv[2]" SetSize(x, y, w, h); } else { SetPosition( wxPoint(x,y) ); } /* Restore maximized or iconized state if required. */ if (bv[0]) { $? ". bv[0]" Maximize(0 != iv[4]); } if (bv[1]) { $? ". bv[1]" Iconize(0 != iv[5]); } $? "- Dk4WxFrame::RestorePosition" } void Dk4WxFrame::DisplayContents(void) { if (NULL != pHelp) { pHelp->DisplayContents(); } } void Dk4WxFrame::DisplaySection(wxString const & name) { if (NULL != pHelp) { pHelp->DisplaySection(name); } } void Dk4WxFrame::DisplaySection(int number) { if (NULL != pHelp) { pHelp->DisplaySection(number); } }