diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:05:53 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:05:53 +0200 |
commit | 618dfb51d93898632830f1b87443d3f748780871 (patch) | |
tree | bac520a2e261154f8d35b0cb8aa345f5ab373811 /RealtimeSync/trayMenu.cpp | |
parent | 3.4 (diff) | |
download | FreeFileSync-618dfb51d93898632830f1b87443d3f748780871.tar.gz FreeFileSync-618dfb51d93898632830f1b87443d3f748780871.tar.bz2 FreeFileSync-618dfb51d93898632830f1b87443d3f748780871.zip |
3.5
Diffstat (limited to 'RealtimeSync/trayMenu.cpp')
-rw-r--r-- | RealtimeSync/trayMenu.cpp | 198 |
1 files changed, 98 insertions, 100 deletions
diff --git a/RealtimeSync/trayMenu.cpp b/RealtimeSync/trayMenu.cpp index ff88a950..79076abd 100644 --- a/RealtimeSync/trayMenu.cpp +++ b/RealtimeSync/trayMenu.cpp @@ -9,24 +9,25 @@ #include <wx/taskbar.h> #include <wx/app.h> #include "resources.h" -#include <memory> +//#include <memory> #include <wx/utils.h> #include <wx/menu.h> #include "watcher.h" -#include <wx/timer.h> #include <wx/utils.h> #include <wx/log.h> #include "../shared/staticAssert.h" #include "../shared/buildInfo.h" #include <wx/icon.h> //Linux needs this +#include <wx/timer.h> -class RtsTrayIcon; +using namespace RealtimeSync; -class WaitCallbackImpl : public RealtimeSync::WaitCallback +class WaitCallbackImpl : private wxEvtHandler, public RealtimeSync::WaitCallback //keep this order: else VC++ generated wrong code { public: WaitCallbackImpl(); + ~WaitCallbackImpl(); virtual void requestUiRefresh(); @@ -35,156 +36,157 @@ public: m_abortRequested = true; } - void requestResume() + void OnRequestResume(wxCommandEvent& event) { m_resumeRequested = true; } + enum Selection + { + CONTEXT_ABORT, + CONTEXT_RESTORE, + CONTEXT_ABOUT + }; + + void OnContextMenuSelection(wxCommandEvent& event); + private: - std::auto_ptr<RtsTrayIcon> trayMenu; + class RtsTrayIcon; + RtsTrayIcon* trayMenu; + bool m_abortRequested; bool m_resumeRequested; }; -class RtsTrayIcon : public wxTaskBarIcon +//RtsTrayIcon shall be a dumb class whose sole purpose is to enable wxWidgets deferred deletion +class WaitCallbackImpl::RtsTrayIcon : public wxTaskBarIcon { public: - RtsTrayIcon(WaitCallbackImpl* callback) : - m_callback(callback) - { -#ifdef FFS_WIN - const wxIcon& realtimeIcon = *GlobalResources::getInstance().programIcon; -#elif defined FFS_LINUX - wxIcon realtimeIcon; - realtimeIcon.CopyFromBitmap(GlobalResources::getInstance().getImageByName(wxT("RTS_tray_linux.png"))); //use a 22x22 bitmap for perfect fit -#endif - wxTaskBarIcon::SetIcon(realtimeIcon, wxString(wxT("RealtimeSync")) + wxT(" - ") + _("Monitoring active...")); + RtsTrayIcon(WaitCallbackImpl* parent) : parent_(parent) {} - //register double-click - Connect(wxEVT_TASKBAR_LEFT_DCLICK, wxCommandEventHandler(RtsTrayIcon::resumeToMain), NULL, this); - } - - void updateSysTray() + void parentHasDied() //call before tray icon is marked for deferred deletion { - wxTheApp->Yield(); + parent_ = NULL; } private: - enum Selection - { - CONTEXT_ABORT, - CONTEXT_RESTORE, - CONTEXT_ABOUT - }; - virtual wxMenu* CreatePopupMenu() { + if (!parent_) + return NULL; + wxMenu* contextMenu = new wxMenu; contextMenu->Append(CONTEXT_RESTORE, _("&Restore")); contextMenu->Append(CONTEXT_ABOUT, _("&About...")); contextMenu->AppendSeparator(); contextMenu->Append(CONTEXT_ABORT, _("&Exit")); //event handling - contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(RtsTrayIcon::OnContextMenuSelection), NULL, this); + contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(WaitCallbackImpl::OnContextMenuSelection), NULL, parent_); - return contextMenu; //ownership transferred to library + return contextMenu; //ownership transferred to caller } - void OnContextMenuSelection(wxCommandEvent& event) - { - const int eventId = event.GetId(); - switch (static_cast<Selection>(eventId)) - { - case CONTEXT_ABORT: - m_callback->requestAbort(); - break; - case CONTEXT_ABOUT: - { - //build information - wxString build = wxString(wxT("(")) + _("Build:") + wxT(" ") + __TDATE__; -#if wxUSE_UNICODE - build += wxT(" - Unicode"); -#else - build += wxT(" - ANSI"); -#endif //wxUSE_UNICODE + WaitCallbackImpl* parent_; +}; +//############################################################################################################## - //compile time info about 32/64-bit build - if (Utility::is64BitBuild) - build += wxT(" x64)"); - else - build += wxT(" x86)"); - assert_static(Utility::is32BitBuild || Utility::is64BitBuild); - wxMessageDialog* aboutDlg = new wxMessageDialog(NULL, wxString(wxT("RealtimeSync")) + wxT("\n\n") + build, _("About"), wxOK); - aboutDlg->ShowModal(); - aboutDlg->Destroy(); - } - break; - case CONTEXT_RESTORE: - m_callback->requestResume(); - break; - } - } +class AbortThisProcess //exception class +{ +public: + AbortThisProcess(MonitorResponse command) : command_(command) {} - void resumeToMain(wxCommandEvent& event) + MonitorResponse getCommand() const { - m_callback->requestResume(); + return command_; } - WaitCallbackImpl* m_callback; +private: + MonitorResponse command_; }; +//############################################################################################################## -bool updateUiIsAllowed() +WaitCallbackImpl::WaitCallbackImpl() : + m_abortRequested(false), + m_resumeRequested(false) { - static wxLongLong lastExec = 0; - const wxLongLong newExec = wxGetLocalTimeMillis(); + trayMenu = new RtsTrayIcon(this); //not in initialization list: give it a valid parent object! - if (newExec - lastExec >= RealtimeSync::UI_UPDATE_INTERVAL) //perform ui updates not more often than necessary - { - lastExec = newExec; - return true; - } - return false; +#ifdef FFS_WIN + const wxIcon& realtimeIcon = *GlobalResources::getInstance().programIcon; +#elif defined FFS_LINUX + wxIcon realtimeIcon; + realtimeIcon.CopyFromBitmap(GlobalResources::getInstance().getImageByName(wxT("RTS_tray_linux.png"))); //use a 22x22 bitmap for perfect fit +#endif + trayMenu->SetIcon(realtimeIcon, wxString(wxT("RealtimeSync")) + wxT(" - ") + _("Monitoring active...")); + + //register double-click + trayMenu->Connect(wxEVT_TASKBAR_LEFT_DCLICK, wxCommandEventHandler(WaitCallbackImpl::OnRequestResume), NULL, this); } -class AbortThisProcess //exception class +WaitCallbackImpl::~WaitCallbackImpl() { -public: - AbortThisProcess(bool backToMain) : m_backToMain(backToMain) {} + trayMenu->Disconnect(wxEVT_TASKBAR_LEFT_DCLICK, wxCommandEventHandler(WaitCallbackImpl::OnRequestResume), NULL, this); + trayMenu->RemoveIcon(); //(try to) hide icon until final deletion takes place + trayMenu->parentHasDied(); - bool backToMainMenu() const - { - return m_backToMain; - } + //use wxWidgets delayed destruction: delete during next idle loop iteration (handle late window messages, e.g. when double-clicking) + if (!wxPendingDelete.Member(trayMenu)) + wxPendingDelete.Append(trayMenu); +} -private: - bool m_backToMain; -}; +void WaitCallbackImpl::OnContextMenuSelection(wxCommandEvent& event) +{ + const int eventId = event.GetId(); + switch (static_cast<Selection>(eventId)) + { + case CONTEXT_ABORT: + requestAbort(); + break; + case CONTEXT_RESTORE: + OnRequestResume(event); //just remember: never throw exceptions through a C-Layer (GUI) ;) + break; + case CONTEXT_ABOUT: + { + //build information + wxString build = wxString(wxT("(")) + _("Build:") + wxT(" ") + __TDATE__; +#if wxUSE_UNICODE + build += wxT(" - Unicode"); +#else + build += wxT(" - ANSI"); +#endif //wxUSE_UNICODE + //compile time info about 32/64-bit build + if (Utility::is64BitBuild) + build += wxT(" x64)"); + else + build += wxT(" x86)"); + assert_static(Utility::is32BitBuild || Utility::is64BitBuild); -WaitCallbackImpl::WaitCallbackImpl() : - m_abortRequested(false), - m_resumeRequested(false) -{ - trayMenu.reset(new RtsTrayIcon(this)); + wxMessageDialog aboutDlg(NULL, wxString(wxT("RealtimeSync")) + wxT("\n\n") + build, _("About"), wxOK); + aboutDlg.ShowModal(); + } + break; + } } void WaitCallbackImpl::requestUiRefresh() { if (updateUiIsAllowed()) - trayMenu->updateSysTray(); + wxTheApp->Yield(); if (m_abortRequested) - throw ::AbortThisProcess(false); + throw ::AbortThisProcess(QUIT); if (m_resumeRequested) - throw ::AbortThisProcess(true); + throw ::AbortThisProcess(RESUME); } +//############################################################################################################## RealtimeSync::MonitorResponse RealtimeSync::startDirectoryMonitor(const xmlAccess::XmlRealConfig& config) @@ -216,10 +218,7 @@ RealtimeSync::MonitorResponse RealtimeSync::startDirectoryMonitor(const xmlAcces } catch (const ::AbortThisProcess& ab) { - if (ab.backToMainMenu()) - return RESUME; - else - return QUIT; + return ab.getCommand(); } catch (const FreeFileSync::FileError& error) { @@ -229,4 +228,3 @@ RealtimeSync::MonitorResponse RealtimeSync::startDirectoryMonitor(const xmlAcces return RESUME; } - |