From bf5e403a684fea1521b7b9960d8200fa5a461288 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Wed, 9 Sep 2015 22:59:21 +0200 Subject: [PATCH] Restructure wxNotificationMessage. wxNotificationMessage has been refactored to always use wxNotificationMessageImpl (this was previously already done in the MSW implementation) This adds various features and fixes to wxNotificationMessage: - OS X Notification Center implementation - Generic "toast" notifications - SetIcon() to specify a custom icon - AddAction() to add actions to notifications - Events to get notify of notification clicks, dismiss or actions --- Makefile.in | 63 ++- build/bakefiles/files.bkl | 4 +- build/files | 4 +- build/msw/makefile.bcc | 24 + build/msw/makefile.gcc | 24 + build/msw/makefile.vc | 24 + build/msw/wx_adv.vcxproj | 2 +- build/msw/wx_adv.vcxproj.filters | 8 +- build/msw/wx_vc7_adv.vcproj | 6 +- build/msw/wx_vc7_core.vcproj | 3 - build/msw/wx_vc8_adv.vcproj | 8 +- build/msw/wx_vc8_core.vcproj | 4 - build/msw/wx_vc9_adv.vcproj | 8 +- build/msw/wx_vc9_core.vcproj | 4 - build/osx/wxcocoa.xcodeproj/project.pbxproj | 16 + include/wx/generic/notifmsg.h | 33 +- include/wx/generic/private/notifmsg.h | 52 ++ include/wx/gtk/notifmsg.h | 51 -- include/wx/msw/notifmsg.h | 74 --- include/wx/msw/taskbar.h | 3 +- include/wx/notifmsg.h | 144 +++--- include/wx/private/notifmsg.h | 76 +++ interface/wx/notifmsg.h | 54 ++- samples/dialogs/dialogs.cpp | 452 ++++++++++++++--- samples/dialogs/dialogs.h | 12 +- src/common/notifmsgcmn.cpp | 103 ++++ src/generic/notifmsgg.cpp | 511 +++++++++++++++----- src/gtk/notifmsg.cpp | 371 ++++++++++---- src/msw/notifmsg.cpp | 398 +++++---------- src/msw/taskbar.cpp | 26 +- src/osx/cocoa/notifmsg.mm | 254 ++++++++++ 31 files changed, 1999 insertions(+), 817 deletions(-) create mode 100644 include/wx/generic/private/notifmsg.h delete mode 100644 include/wx/gtk/notifmsg.h delete mode 100644 include/wx/msw/notifmsg.h create mode 100644 include/wx/private/notifmsg.h create mode 100644 src/common/notifmsgcmn.cpp create mode 100644 src/osx/cocoa/notifmsg.mm diff --git a/Makefile.in b/Makefile.in index ececa01420..dc1879b412 100644 --- a/Makefile.in +++ b/Makefile.in @@ -3367,13 +3367,11 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION__ADVANCED_PLATFORM_HDR = \ @COND_TOOLKIT_GTK_TOOLKIT_VERSION_@ADVANCED_PLATFORM_HDR = $(COND_TOOLKIT_GTK_TOOLKIT_VERSION__ADVANCED_PLATFORM_HDR) COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_ADVANCED_PLATFORM_HDR = \ $(ADVANCED_GTK_PLATFORM_HDR) \ - wx/gtk/notifmsg.h \ wx/gtk/taskbar.h \ wx/generic/activityindicator.h @COND_TOOLKIT_GTK_TOOLKIT_VERSION_2@ADVANCED_PLATFORM_HDR = $(COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_ADVANCED_PLATFORM_HDR) COND_TOOLKIT_GTK_TOOLKIT_VERSION_3_ADVANCED_PLATFORM_HDR = \ $(ADVANCED_GTK_PLATFORM_HDR) \ - wx/gtk/notifmsg.h \ wx/gtk/taskbar.h \ wx/generic/activityindicator.h @COND_TOOLKIT_GTK_TOOLKIT_VERSION_3@ADVANCED_PLATFORM_HDR = $(COND_TOOLKIT_GTK_TOOLKIT_VERSION_3_ADVANCED_PLATFORM_HDR) @@ -3384,9 +3382,8 @@ COND_TOOLKIT_MOTIF_ADVANCED_PLATFORM_HDR = \ wx/generic/animate.h \ wx/generic/animateanimate.h @COND_TOOLKIT_MOTIF@ADVANCED_PLATFORM_HDR = $(COND_TOOLKIT_MOTIF_ADVANCED_PLATFORM_HDR) -@COND_TOOLKIT_MSW@ADVANCED_PLATFORM_HDR = \ -@COND_TOOLKIT_MSW@ wx/msw/notifmsg.h wx/msw/sound.h wx/msw/taskbar.h \ -@COND_TOOLKIT_MSW@ wx/msw/joystick.h +@COND_TOOLKIT_MSW@ADVANCED_PLATFORM_HDR = wx/msw/sound.h \ +@COND_TOOLKIT_MSW@ wx/msw/taskbar.h wx/msw/joystick.h COND_TOOLKIT_OSX_COCOA_ADVANCED_PLATFORM_HDR = \ wx/generic/animate.h \ wx/osx/activityindicator.h \ @@ -5789,6 +5786,7 @@ COND_WXUNIV_0___ADVANCED_SRC_OBJECTS = \ monodll_treelist.o \ monodll_wizard.o \ monodll_addremovectrl.o \ + monodll_notifmsgcmn.o \ $(__ADVANCED_PLATFORM_SRC_OBJECTS) \ $(__ADVANCED_PLATFORM_NATIVE_SRC_OBJECTS) @COND_WXUNIV_0@__ADVANCED_SRC_OBJECTS = $(COND_WXUNIV_0___ADVANCED_SRC_OBJECTS) @@ -5827,6 +5825,7 @@ COND_WXUNIV_1___ADVANCED_SRC_OBJECTS = \ monodll_treelist.o \ monodll_wizard.o \ monodll_addremovectrl.o \ + monodll_notifmsgcmn.o \ $(__ADVANCED_PLATFORM_SRC_OBJECTS_1) \ $(__ADVANCED_UNIV_SRC_OBJECTS) @COND_WXUNIV_1@__ADVANCED_SRC_OBJECTS = $(COND_WXUNIV_1___ADVANCED_SRC_OBJECTS) @@ -5890,7 +5889,8 @@ COND_TOOLKIT_OSX_COCOA___ADVANCED_PLATFORM_SRC_OBJECTS = \ monodll_cocoa_datetimectrl.o \ monodll_osx_cocoa_taskbar.o \ monodll_hidjoystick.o \ - monodll_cocoa_activityindicator.o + monodll_cocoa_activityindicator.o \ + monodll_cocoa_notifmsg.o @COND_TOOLKIT_OSX_COCOA@__ADVANCED_PLATFORM_SRC_OBJECTS = $(COND_TOOLKIT_OSX_COCOA___ADVANCED_PLATFORM_SRC_OBJECTS) @COND_TOOLKIT_OSX_IPHONE@__ADVANCED_PLATFORM_SRC_OBJECTS \ @COND_TOOLKIT_OSX_IPHONE@ = monodll_animateg.o monodll_sound_osx.o \ @@ -6004,7 +6004,8 @@ COND_TOOLKIT_OSX_COCOA___ADVANCED_PLATFORM_SRC_OBJECTS_1 = \ monodll_cocoa_datetimectrl.o \ monodll_osx_cocoa_taskbar.o \ monodll_hidjoystick.o \ - monodll_cocoa_activityindicator.o + monodll_cocoa_activityindicator.o \ + monodll_cocoa_notifmsg.o @COND_TOOLKIT_OSX_COCOA@__ADVANCED_PLATFORM_SRC_OBJECTS_1 = $(COND_TOOLKIT_OSX_COCOA___ADVANCED_PLATFORM_SRC_OBJECTS_1) @COND_TOOLKIT_OSX_IPHONE@__ADVANCED_PLATFORM_SRC_OBJECTS_1 \ @COND_TOOLKIT_OSX_IPHONE@ = monodll_animateg.o monodll_sound_osx.o \ @@ -7785,6 +7786,7 @@ COND_WXUNIV_0___ADVANCED_SRC_OBJECTS_1 = \ monolib_treelist.o \ monolib_wizard.o \ monolib_addremovectrl.o \ + monolib_notifmsgcmn.o \ $(__ADVANCED_PLATFORM_SRC_OBJECTS_2) \ $(__ADVANCED_PLATFORM_NATIVE_SRC_OBJECTS_1) @COND_WXUNIV_0@__ADVANCED_SRC_OBJECTS_1 = $(COND_WXUNIV_0___ADVANCED_SRC_OBJECTS_1) @@ -7823,6 +7825,7 @@ COND_WXUNIV_1___ADVANCED_SRC_OBJECTS_1 = \ monolib_treelist.o \ monolib_wizard.o \ monolib_addremovectrl.o \ + monolib_notifmsgcmn.o \ $(__ADVANCED_PLATFORM_SRC_OBJECTS_3) \ $(__ADVANCED_UNIV_SRC_OBJECTS_1) @COND_WXUNIV_1@__ADVANCED_SRC_OBJECTS_1 = $(COND_WXUNIV_1___ADVANCED_SRC_OBJECTS_1) @@ -7886,7 +7889,8 @@ COND_TOOLKIT_OSX_COCOA___ADVANCED_PLATFORM_SRC_OBJECTS_2 = \ monolib_cocoa_datetimectrl.o \ monolib_osx_cocoa_taskbar.o \ monolib_hidjoystick.o \ - monolib_cocoa_activityindicator.o + monolib_cocoa_activityindicator.o \ + monolib_cocoa_notifmsg.o @COND_TOOLKIT_OSX_COCOA@__ADVANCED_PLATFORM_SRC_OBJECTS_2 = $(COND_TOOLKIT_OSX_COCOA___ADVANCED_PLATFORM_SRC_OBJECTS_2) @COND_TOOLKIT_OSX_IPHONE@__ADVANCED_PLATFORM_SRC_OBJECTS_2 \ @COND_TOOLKIT_OSX_IPHONE@ = monolib_animateg.o monolib_sound_osx.o \ @@ -8000,7 +8004,8 @@ COND_TOOLKIT_OSX_COCOA___ADVANCED_PLATFORM_SRC_OBJECTS_3 = \ monolib_cocoa_datetimectrl.o \ monolib_osx_cocoa_taskbar.o \ monolib_hidjoystick.o \ - monolib_cocoa_activityindicator.o + monolib_cocoa_activityindicator.o \ + monolib_cocoa_notifmsg.o @COND_TOOLKIT_OSX_COCOA@__ADVANCED_PLATFORM_SRC_OBJECTS_3 = $(COND_TOOLKIT_OSX_COCOA___ADVANCED_PLATFORM_SRC_OBJECTS_3) @COND_TOOLKIT_OSX_IPHONE@__ADVANCED_PLATFORM_SRC_OBJECTS_3 \ @COND_TOOLKIT_OSX_IPHONE@ = monolib_animateg.o monolib_sound_osx.o \ @@ -11458,6 +11463,7 @@ COND_WXUNIV_0___ADVANCED_SRC_OBJECTS_2 = \ advdll_treelist.o \ advdll_wizard.o \ advdll_addremovectrl.o \ + advdll_notifmsgcmn.o \ $(__ADVANCED_PLATFORM_SRC_OBJECTS_4) \ $(__ADVANCED_PLATFORM_NATIVE_SRC_OBJECTS_2) @COND_WXUNIV_0@__ADVANCED_SRC_OBJECTS_2 = $(COND_WXUNIV_0___ADVANCED_SRC_OBJECTS_2) @@ -11496,6 +11502,7 @@ COND_WXUNIV_1___ADVANCED_SRC_OBJECTS_2 = \ advdll_treelist.o \ advdll_wizard.o \ advdll_addremovectrl.o \ + advdll_notifmsgcmn.o \ $(__ADVANCED_PLATFORM_SRC_OBJECTS_5) \ $(__ADVANCED_UNIV_SRC_OBJECTS_2) @COND_WXUNIV_1@__ADVANCED_SRC_OBJECTS_2 = $(COND_WXUNIV_1___ADVANCED_SRC_OBJECTS_2) @@ -11559,7 +11566,8 @@ COND_TOOLKIT_OSX_COCOA___ADVANCED_PLATFORM_SRC_OBJECTS_4 = \ advdll_cocoa_datetimectrl.o \ advdll_osx_cocoa_taskbar.o \ advdll_hidjoystick.o \ - advdll_cocoa_activityindicator.o + advdll_cocoa_activityindicator.o \ + advdll_cocoa_notifmsg.o @COND_TOOLKIT_OSX_COCOA@__ADVANCED_PLATFORM_SRC_OBJECTS_4 = $(COND_TOOLKIT_OSX_COCOA___ADVANCED_PLATFORM_SRC_OBJECTS_4) @COND_TOOLKIT_OSX_IPHONE@__ADVANCED_PLATFORM_SRC_OBJECTS_4 \ @COND_TOOLKIT_OSX_IPHONE@ = advdll_animateg.o advdll_sound_osx.o \ @@ -11673,7 +11681,8 @@ COND_TOOLKIT_OSX_COCOA___ADVANCED_PLATFORM_SRC_OBJECTS_5 = \ advdll_cocoa_datetimectrl.o \ advdll_osx_cocoa_taskbar.o \ advdll_hidjoystick.o \ - advdll_cocoa_activityindicator.o + advdll_cocoa_activityindicator.o \ + advdll_cocoa_notifmsg.o @COND_TOOLKIT_OSX_COCOA@__ADVANCED_PLATFORM_SRC_OBJECTS_5 = $(COND_TOOLKIT_OSX_COCOA___ADVANCED_PLATFORM_SRC_OBJECTS_5) @COND_TOOLKIT_OSX_IPHONE@__ADVANCED_PLATFORM_SRC_OBJECTS_5 \ @COND_TOOLKIT_OSX_IPHONE@ = advdll_animateg.o advdll_sound_osx.o \ @@ -11750,6 +11759,7 @@ COND_WXUNIV_0___ADVANCED_SRC_OBJECTS_3 = \ advlib_treelist.o \ advlib_wizard.o \ advlib_addremovectrl.o \ + advlib_notifmsgcmn.o \ $(__ADVANCED_PLATFORM_SRC_OBJECTS_6) \ $(__ADVANCED_PLATFORM_NATIVE_SRC_OBJECTS_3) @COND_WXUNIV_0@__ADVANCED_SRC_OBJECTS_3 = $(COND_WXUNIV_0___ADVANCED_SRC_OBJECTS_3) @@ -11788,6 +11798,7 @@ COND_WXUNIV_1___ADVANCED_SRC_OBJECTS_3 = \ advlib_treelist.o \ advlib_wizard.o \ advlib_addremovectrl.o \ + advlib_notifmsgcmn.o \ $(__ADVANCED_PLATFORM_SRC_OBJECTS_7) \ $(__ADVANCED_UNIV_SRC_OBJECTS_3) @COND_WXUNIV_1@__ADVANCED_SRC_OBJECTS_3 = $(COND_WXUNIV_1___ADVANCED_SRC_OBJECTS_3) @@ -11851,7 +11862,8 @@ COND_TOOLKIT_OSX_COCOA___ADVANCED_PLATFORM_SRC_OBJECTS_6 = \ advlib_cocoa_datetimectrl.o \ advlib_osx_cocoa_taskbar.o \ advlib_hidjoystick.o \ - advlib_cocoa_activityindicator.o + advlib_cocoa_activityindicator.o \ + advlib_cocoa_notifmsg.o @COND_TOOLKIT_OSX_COCOA@__ADVANCED_PLATFORM_SRC_OBJECTS_6 = $(COND_TOOLKIT_OSX_COCOA___ADVANCED_PLATFORM_SRC_OBJECTS_6) @COND_TOOLKIT_OSX_IPHONE@__ADVANCED_PLATFORM_SRC_OBJECTS_6 \ @COND_TOOLKIT_OSX_IPHONE@ = advlib_animateg.o advlib_sound_osx.o \ @@ -11965,7 +11977,8 @@ COND_TOOLKIT_OSX_COCOA___ADVANCED_PLATFORM_SRC_OBJECTS_7 = \ advlib_cocoa_datetimectrl.o \ advlib_osx_cocoa_taskbar.o \ advlib_hidjoystick.o \ - advlib_cocoa_activityindicator.o + advlib_cocoa_activityindicator.o \ + advlib_cocoa_notifmsg.o @COND_TOOLKIT_OSX_COCOA@__ADVANCED_PLATFORM_SRC_OBJECTS_7 = $(COND_TOOLKIT_OSX_COCOA___ADVANCED_PLATFORM_SRC_OBJECTS_7) @COND_TOOLKIT_OSX_IPHONE@__ADVANCED_PLATFORM_SRC_OBJECTS_7 \ @COND_TOOLKIT_OSX_IPHONE@ = advlib_animateg.o advlib_sound_osx.o \ @@ -19940,6 +19953,9 @@ monodll_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(MONODLL_ODEP) @COND_USE_GUI_1@monodll_addremovectrl.o: $(srcdir)/src/common/addremovectrl.cpp $(MONODLL_ODEP) @COND_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/common/addremovectrl.cpp +@COND_USE_GUI_1@monodll_notifmsgcmn.o: $(srcdir)/src/common/notifmsgcmn.cpp $(MONODLL_ODEP) +@COND_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/common/notifmsgcmn.cpp + @COND_TOOLKIT_MSW_USE_GUI_1@monodll_taskbarcmn.o: $(srcdir)/src/common/taskbarcmn.cpp $(MONODLL_ODEP) @COND_TOOLKIT_MSW_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/common/taskbarcmn.cpp @@ -20084,6 +20100,9 @@ monodll_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(MONODLL_ODEP) @COND_TOOLKIT_OSX_COCOA_USE_GUI_1@monodll_cocoa_activityindicator.o: $(srcdir)/src/osx/cocoa/activityindicator.mm $(MONODLL_ODEP) @COND_TOOLKIT_OSX_COCOA_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_OBJCXXFLAGS) $(srcdir)/src/osx/cocoa/activityindicator.mm +@COND_TOOLKIT_OSX_COCOA_USE_GUI_1@monodll_cocoa_notifmsg.o: $(srcdir)/src/osx/cocoa/notifmsg.mm $(MONODLL_ODEP) +@COND_TOOLKIT_OSX_COCOA_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_OBJCXXFLAGS) $(srcdir)/src/osx/cocoa/notifmsg.mm + @COND_TOOLKIT_COCOA_USE_GUI_1@monodll_src_cocoa_taskbar.o: $(srcdir)/src/cocoa/taskbar.mm $(MONODLL_ODEP) @COND_TOOLKIT_COCOA_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_OBJCXXFLAGS) $(srcdir)/src/cocoa/taskbar.mm @@ -24743,6 +24762,9 @@ monolib_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(MONOLIB_ODEP) @COND_USE_GUI_1@monolib_addremovectrl.o: $(srcdir)/src/common/addremovectrl.cpp $(MONOLIB_ODEP) @COND_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/common/addremovectrl.cpp +@COND_USE_GUI_1@monolib_notifmsgcmn.o: $(srcdir)/src/common/notifmsgcmn.cpp $(MONOLIB_ODEP) +@COND_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/common/notifmsgcmn.cpp + @COND_TOOLKIT_MSW_USE_GUI_1@monolib_taskbarcmn.o: $(srcdir)/src/common/taskbarcmn.cpp $(MONOLIB_ODEP) @COND_TOOLKIT_MSW_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/common/taskbarcmn.cpp @@ -24887,6 +24909,9 @@ monolib_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(MONOLIB_ODEP) @COND_TOOLKIT_OSX_COCOA_USE_GUI_1@monolib_cocoa_activityindicator.o: $(srcdir)/src/osx/cocoa/activityindicator.mm $(MONOLIB_ODEP) @COND_TOOLKIT_OSX_COCOA_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_OBJCXXFLAGS) $(srcdir)/src/osx/cocoa/activityindicator.mm +@COND_TOOLKIT_OSX_COCOA_USE_GUI_1@monolib_cocoa_notifmsg.o: $(srcdir)/src/osx/cocoa/notifmsg.mm $(MONOLIB_ODEP) +@COND_TOOLKIT_OSX_COCOA_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_OBJCXXFLAGS) $(srcdir)/src/osx/cocoa/notifmsg.mm + @COND_TOOLKIT_COCOA_USE_GUI_1@monolib_src_cocoa_taskbar.o: $(srcdir)/src/cocoa/taskbar.mm $(MONOLIB_ODEP) @COND_TOOLKIT_COCOA_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_OBJCXXFLAGS) $(srcdir)/src/cocoa/taskbar.mm @@ -33014,6 +33039,9 @@ advdll_wizard.o: $(srcdir)/src/generic/wizard.cpp $(ADVDLL_ODEP) advdll_addremovectrl.o: $(srcdir)/src/common/addremovectrl.cpp $(ADVDLL_ODEP) $(CXXC) -c -o $@ $(ADVDLL_CXXFLAGS) $(srcdir)/src/common/addremovectrl.cpp +advdll_notifmsgcmn.o: $(srcdir)/src/common/notifmsgcmn.cpp $(ADVDLL_ODEP) + $(CXXC) -c -o $@ $(ADVDLL_CXXFLAGS) $(srcdir)/src/common/notifmsgcmn.cpp + @COND_TOOLKIT_MSW@advdll_taskbarcmn.o: $(srcdir)/src/common/taskbarcmn.cpp $(ADVDLL_ODEP) @COND_TOOLKIT_MSW@ $(CXXC) -c -o $@ $(ADVDLL_CXXFLAGS) $(srcdir)/src/common/taskbarcmn.cpp @@ -33158,6 +33186,9 @@ advdll_addremovectrl.o: $(srcdir)/src/common/addremovectrl.cpp $(ADVDLL_ODEP) @COND_TOOLKIT_OSX_COCOA@advdll_cocoa_activityindicator.o: $(srcdir)/src/osx/cocoa/activityindicator.mm $(ADVDLL_ODEP) @COND_TOOLKIT_OSX_COCOA@ $(CXXC) -c -o $@ $(ADVDLL_OBJCXXFLAGS) $(srcdir)/src/osx/cocoa/activityindicator.mm +@COND_TOOLKIT_OSX_COCOA@advdll_cocoa_notifmsg.o: $(srcdir)/src/osx/cocoa/notifmsg.mm $(ADVDLL_ODEP) +@COND_TOOLKIT_OSX_COCOA@ $(CXXC) -c -o $@ $(ADVDLL_OBJCXXFLAGS) $(srcdir)/src/osx/cocoa/notifmsg.mm + @COND_TOOLKIT_COCOA@advdll_src_cocoa_taskbar.o: $(srcdir)/src/cocoa/taskbar.mm $(ADVDLL_ODEP) @COND_TOOLKIT_COCOA@ $(CXXC) -c -o $@ $(ADVDLL_OBJCXXFLAGS) $(srcdir)/src/cocoa/taskbar.mm @@ -33455,6 +33486,9 @@ advlib_wizard.o: $(srcdir)/src/generic/wizard.cpp $(ADVLIB_ODEP) advlib_addremovectrl.o: $(srcdir)/src/common/addremovectrl.cpp $(ADVLIB_ODEP) $(CXXC) -c -o $@ $(ADVLIB_CXXFLAGS) $(srcdir)/src/common/addremovectrl.cpp +advlib_notifmsgcmn.o: $(srcdir)/src/common/notifmsgcmn.cpp $(ADVLIB_ODEP) + $(CXXC) -c -o $@ $(ADVLIB_CXXFLAGS) $(srcdir)/src/common/notifmsgcmn.cpp + @COND_TOOLKIT_MSW@advlib_taskbarcmn.o: $(srcdir)/src/common/taskbarcmn.cpp $(ADVLIB_ODEP) @COND_TOOLKIT_MSW@ $(CXXC) -c -o $@ $(ADVLIB_CXXFLAGS) $(srcdir)/src/common/taskbarcmn.cpp @@ -33599,6 +33633,9 @@ advlib_addremovectrl.o: $(srcdir)/src/common/addremovectrl.cpp $(ADVLIB_ODEP) @COND_TOOLKIT_OSX_COCOA@advlib_cocoa_activityindicator.o: $(srcdir)/src/osx/cocoa/activityindicator.mm $(ADVLIB_ODEP) @COND_TOOLKIT_OSX_COCOA@ $(CXXC) -c -o $@ $(ADVLIB_OBJCXXFLAGS) $(srcdir)/src/osx/cocoa/activityindicator.mm +@COND_TOOLKIT_OSX_COCOA@advlib_cocoa_notifmsg.o: $(srcdir)/src/osx/cocoa/notifmsg.mm $(ADVLIB_ODEP) +@COND_TOOLKIT_OSX_COCOA@ $(CXXC) -c -o $@ $(ADVLIB_OBJCXXFLAGS) $(srcdir)/src/osx/cocoa/notifmsg.mm + @COND_TOOLKIT_COCOA@advlib_src_cocoa_taskbar.o: $(srcdir)/src/cocoa/taskbar.mm $(ADVLIB_ODEP) @COND_TOOLKIT_COCOA@ $(CXXC) -c -o $@ $(ADVLIB_OBJCXXFLAGS) $(srcdir)/src/cocoa/taskbar.mm diff --git a/build/bakefiles/files.bkl b/build/bakefiles/files.bkl index 94f3e22073..073c850a02 100644 --- a/build/bakefiles/files.bkl +++ b/build/bakefiles/files.bkl @@ -2663,6 +2663,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! src/generic/treelist.cpp src/generic/wizard.cpp src/common/addremovectrl.cpp + src/common/notifmsgcmn.cpp @@ -2728,7 +2729,6 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! src/msw/taskbar.cpp - wx/msw/notifmsg.h wx/msw/sound.h wx/msw/taskbar.h @@ -2782,6 +2782,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! src/osx/cocoa/taskbar.mm src/osx/core/hidjoystick.cpp src/osx/cocoa/activityindicator.mm + src/osx/cocoa/notifmsg.mm @@ -2879,7 +2880,6 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! $(ADVANCED_GTK_PLATFORM_HDR) - wx/gtk/notifmsg.h wx/gtk/taskbar.h wx/generic/activityindicator.h diff --git a/build/files b/build/files index 101dcc076a..7a741064e2 100644 --- a/build/files +++ b/build/files @@ -2253,6 +2253,7 @@ ADVANCED_CMN_SRC = src/common/datavcmn.cpp src/common/gridcmn.cpp src/common/hyperlnkcmn.cpp + src/common/notifmsgcmn.cpp src/common/odcombocmn.cpp src/common/richtooltipcmn.cpp src/generic/aboutdlgg.cpp @@ -2342,7 +2343,6 @@ ADVANCED_MSW_SRC = src/msw/sound.cpp src/msw/taskbar.cpp ADVANCED_MSW_HDR = - wx/msw/notifmsg.h wx/msw/sound.h wx/msw/taskbar.h @@ -2389,6 +2389,7 @@ ADVANCED_OSX_COCOA_SRC = src/osx/dataview_osx.cpp src/osx/cocoa/dataview.mm src/osx/cocoa/datetimectrl.mm + src/osx/cocoa/notifmsg.mm src/osx/cocoa/taskbar.mm src/osx/core/hidjoystick.cpp @@ -2464,7 +2465,6 @@ ADVANCED_GTK2_SRC = ADVANCED_GTK_HDR = $(ADVANCED_GTK_PLATFORM_HDR) wx/generic/activityindicator.h - wx/gtk/notifmsg.h wx/gtk/taskbar.h ADVANCED_GTK2_HDR = $(ADVANCED_GTK_HDR) diff --git a/build/msw/makefile.bcc b/build/msw/makefile.bcc index 743da82751..70f891216e 100644 --- a/build/msw/makefile.bcc +++ b/build/msw/makefile.bcc @@ -2371,6 +2371,7 @@ ____ADVANCED_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_treelist.obj \ $(OBJS)\monodll_wizard.obj \ $(OBJS)\monodll_addremovectrl.obj \ + $(OBJS)\monodll_notifmsgcmn.obj \ $(OBJS)\monodll_taskbarcmn.obj \ $(OBJS)\monodll_aboutdlg.obj \ $(OBJS)\monodll_notifmsg.obj \ @@ -2425,6 +2426,7 @@ ____ADVANCED_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_treelist.obj \ $(OBJS)\monodll_wizard.obj \ $(OBJS)\monodll_addremovectrl.obj \ + $(OBJS)\monodll_notifmsgcmn.obj \ $(OBJS)\monodll_taskbarcmn.obj \ $(OBJS)\monodll_aboutdlg.obj \ $(OBJS)\monodll_notifmsg.obj \ @@ -3193,6 +3195,7 @@ ____ADVANCED_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_treelist.obj \ $(OBJS)\monolib_wizard.obj \ $(OBJS)\monolib_addremovectrl.obj \ + $(OBJS)\monolib_notifmsgcmn.obj \ $(OBJS)\monolib_taskbarcmn.obj \ $(OBJS)\monolib_aboutdlg.obj \ $(OBJS)\monolib_notifmsg.obj \ @@ -3247,6 +3250,7 @@ ____ADVANCED_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_treelist.obj \ $(OBJS)\monolib_wizard.obj \ $(OBJS)\monolib_addremovectrl.obj \ + $(OBJS)\monolib_notifmsgcmn.obj \ $(OBJS)\monolib_taskbarcmn.obj \ $(OBJS)\monolib_aboutdlg.obj \ $(OBJS)\monolib_notifmsg.obj \ @@ -4466,6 +4470,7 @@ ____ADVANCED_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\advdll_treelist.obj \ $(OBJS)\advdll_wizard.obj \ $(OBJS)\advdll_addremovectrl.obj \ + $(OBJS)\advdll_notifmsgcmn.obj \ $(OBJS)\advdll_taskbarcmn.obj \ $(OBJS)\advdll_aboutdlg.obj \ $(OBJS)\advdll_notifmsg.obj \ @@ -4520,6 +4525,7 @@ ____ADVANCED_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\advdll_treelist.obj \ $(OBJS)\advdll_wizard.obj \ $(OBJS)\advdll_addremovectrl.obj \ + $(OBJS)\advdll_notifmsgcmn.obj \ $(OBJS)\advdll_taskbarcmn.obj \ $(OBJS)\advdll_aboutdlg.obj \ $(OBJS)\advdll_notifmsg.obj \ @@ -4569,6 +4575,7 @@ ____ADVANCED_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\advlib_treelist.obj \ $(OBJS)\advlib_wizard.obj \ $(OBJS)\advlib_addremovectrl.obj \ + $(OBJS)\advlib_notifmsgcmn.obj \ $(OBJS)\advlib_taskbarcmn.obj \ $(OBJS)\advlib_aboutdlg.obj \ $(OBJS)\advlib_notifmsg.obj \ @@ -4623,6 +4630,7 @@ ____ADVANCED_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\advlib_treelist.obj \ $(OBJS)\advlib_wizard.obj \ $(OBJS)\advlib_addremovectrl.obj \ + $(OBJS)\advlib_notifmsgcmn.obj \ $(OBJS)\advlib_taskbarcmn.obj \ $(OBJS)\advlib_aboutdlg.obj \ $(OBJS)\advlib_notifmsg.obj \ @@ -8801,6 +8809,11 @@ $(OBJS)\monodll_addremovectrl.obj: ..\..\src\common\addremovectrl.cpp $(CXX) -q -c -P -o$@ $(MONODLL_CXXFLAGS) ..\..\src\common\addremovectrl.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\monodll_notifmsgcmn.obj: ..\..\src\common\notifmsgcmn.cpp + $(CXX) -q -c -P -o$@ $(MONODLL_CXXFLAGS) ..\..\src\common\notifmsgcmn.cpp +!endif + !if "$(USE_GUI)" == "1" $(OBJS)\monodll_taskbarcmn.obj: ..\..\src\common\taskbarcmn.cpp $(CXX) -q -c -P -o$@ $(MONODLL_CXXFLAGS) ..\..\src\common\taskbarcmn.cpp @@ -11311,6 +11324,11 @@ $(OBJS)\monolib_addremovectrl.obj: ..\..\src\common\addremovectrl.cpp $(CXX) -q -c -P -o$@ $(MONOLIB_CXXFLAGS) ..\..\src\common\addremovectrl.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\monolib_notifmsgcmn.obj: ..\..\src\common\notifmsgcmn.cpp + $(CXX) -q -c -P -o$@ $(MONOLIB_CXXFLAGS) ..\..\src\common\notifmsgcmn.cpp +!endif + !if "$(USE_GUI)" == "1" $(OBJS)\monolib_taskbarcmn.obj: ..\..\src\common\taskbarcmn.cpp $(CXX) -q -c -P -o$@ $(MONOLIB_CXXFLAGS) ..\..\src\common\taskbarcmn.cpp @@ -15189,6 +15207,9 @@ $(OBJS)\advdll_wizard.obj: ..\..\src\generic\wizard.cpp $(OBJS)\advdll_addremovectrl.obj: ..\..\src\common\addremovectrl.cpp $(CXX) -q -c -P -o$@ $(ADVDLL_CXXFLAGS) ..\..\src\common\addremovectrl.cpp +$(OBJS)\advdll_notifmsgcmn.obj: ..\..\src\common\notifmsgcmn.cpp + $(CXX) -q -c -P -o$@ $(ADVDLL_CXXFLAGS) ..\..\src\common\notifmsgcmn.cpp + $(OBJS)\advdll_taskbarcmn.obj: ..\..\src\common\taskbarcmn.cpp $(CXX) -q -c -P -o$@ $(ADVDLL_CXXFLAGS) ..\..\src\common\taskbarcmn.cpp @@ -15345,6 +15366,9 @@ $(OBJS)\advlib_wizard.obj: ..\..\src\generic\wizard.cpp $(OBJS)\advlib_addremovectrl.obj: ..\..\src\common\addremovectrl.cpp $(CXX) -q -c -P -o$@ $(ADVLIB_CXXFLAGS) ..\..\src\common\addremovectrl.cpp +$(OBJS)\advlib_notifmsgcmn.obj: ..\..\src\common\notifmsgcmn.cpp + $(CXX) -q -c -P -o$@ $(ADVLIB_CXXFLAGS) ..\..\src\common\notifmsgcmn.cpp + $(OBJS)\advlib_taskbarcmn.obj: ..\..\src\common\taskbarcmn.cpp $(CXX) -q -c -P -o$@ $(ADVLIB_CXXFLAGS) ..\..\src\common\taskbarcmn.cpp diff --git a/build/msw/makefile.gcc b/build/msw/makefile.gcc index f51f1d2274..969609d25e 100644 --- a/build/msw/makefile.gcc +++ b/build/msw/makefile.gcc @@ -2393,6 +2393,7 @@ ____ADVANCED_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_treelist.o \ $(OBJS)\monodll_wizard.o \ $(OBJS)\monodll_addremovectrl.o \ + $(OBJS)\monodll_notifmsgcmn.o \ $(OBJS)\monodll_taskbarcmn.o \ $(OBJS)\monodll_aboutdlg.o \ $(OBJS)\monodll_notifmsg.o \ @@ -2447,6 +2448,7 @@ ____ADVANCED_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_treelist.o \ $(OBJS)\monodll_wizard.o \ $(OBJS)\monodll_addremovectrl.o \ + $(OBJS)\monodll_notifmsgcmn.o \ $(OBJS)\monodll_taskbarcmn.o \ $(OBJS)\monodll_aboutdlg.o \ $(OBJS)\monodll_notifmsg.o \ @@ -3221,6 +3223,7 @@ ____ADVANCED_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_treelist.o \ $(OBJS)\monolib_wizard.o \ $(OBJS)\monolib_addremovectrl.o \ + $(OBJS)\monolib_notifmsgcmn.o \ $(OBJS)\monolib_taskbarcmn.o \ $(OBJS)\monolib_aboutdlg.o \ $(OBJS)\monolib_notifmsg.o \ @@ -3275,6 +3278,7 @@ ____ADVANCED_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_treelist.o \ $(OBJS)\monolib_wizard.o \ $(OBJS)\monolib_addremovectrl.o \ + $(OBJS)\monolib_notifmsgcmn.o \ $(OBJS)\monolib_taskbarcmn.o \ $(OBJS)\monolib_aboutdlg.o \ $(OBJS)\monolib_notifmsg.o \ @@ -4522,6 +4526,7 @@ ____ADVANCED_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\advdll_treelist.o \ $(OBJS)\advdll_wizard.o \ $(OBJS)\advdll_addremovectrl.o \ + $(OBJS)\advdll_notifmsgcmn.o \ $(OBJS)\advdll_taskbarcmn.o \ $(OBJS)\advdll_aboutdlg.o \ $(OBJS)\advdll_notifmsg.o \ @@ -4576,6 +4581,7 @@ ____ADVANCED_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\advdll_treelist.o \ $(OBJS)\advdll_wizard.o \ $(OBJS)\advdll_addremovectrl.o \ + $(OBJS)\advdll_notifmsgcmn.o \ $(OBJS)\advdll_taskbarcmn.o \ $(OBJS)\advdll_aboutdlg.o \ $(OBJS)\advdll_notifmsg.o \ @@ -4629,6 +4635,7 @@ ____ADVANCED_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\advlib_treelist.o \ $(OBJS)\advlib_wizard.o \ $(OBJS)\advlib_addremovectrl.o \ + $(OBJS)\advlib_notifmsgcmn.o \ $(OBJS)\advlib_taskbarcmn.o \ $(OBJS)\advlib_aboutdlg.o \ $(OBJS)\advlib_notifmsg.o \ @@ -4683,6 +4690,7 @@ ____ADVANCED_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\advlib_treelist.o \ $(OBJS)\advlib_wizard.o \ $(OBJS)\advlib_addremovectrl.o \ + $(OBJS)\advlib_notifmsgcmn.o \ $(OBJS)\advlib_taskbarcmn.o \ $(OBJS)\advlib_aboutdlg.o \ $(OBJS)\advlib_notifmsg.o \ @@ -8976,6 +8984,11 @@ $(OBJS)\monodll_addremovectrl.o: ../../src/common/addremovectrl.cpp $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< endif +ifeq ($(USE_GUI),1) +$(OBJS)\monodll_notifmsgcmn.o: ../../src/common/notifmsgcmn.cpp + $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< +endif + ifeq ($(USE_GUI),1) $(OBJS)\monodll_taskbarcmn.o: ../../src/common/taskbarcmn.cpp $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< @@ -11486,6 +11499,11 @@ $(OBJS)\monolib_addremovectrl.o: ../../src/common/addremovectrl.cpp $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< endif +ifeq ($(USE_GUI),1) +$(OBJS)\monolib_notifmsgcmn.o: ../../src/common/notifmsgcmn.cpp + $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< +endif + ifeq ($(USE_GUI),1) $(OBJS)\monolib_taskbarcmn.o: ../../src/common/taskbarcmn.cpp $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< @@ -15364,6 +15382,9 @@ $(OBJS)\advdll_wizard.o: ../../src/generic/wizard.cpp $(OBJS)\advdll_addremovectrl.o: ../../src/common/addremovectrl.cpp $(CXX) -c -o $@ $(ADVDLL_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\advdll_notifmsgcmn.o: ../../src/common/notifmsgcmn.cpp + $(CXX) -c -o $@ $(ADVDLL_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\advdll_taskbarcmn.o: ../../src/common/taskbarcmn.cpp $(CXX) -c -o $@ $(ADVDLL_CXXFLAGS) $(CPPDEPS) $< @@ -15520,6 +15541,9 @@ $(OBJS)\advlib_wizard.o: ../../src/generic/wizard.cpp $(OBJS)\advlib_addremovectrl.o: ../../src/common/addremovectrl.cpp $(CXX) -c -o $@ $(ADVLIB_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\advlib_notifmsgcmn.o: ../../src/common/notifmsgcmn.cpp + $(CXX) -c -o $@ $(ADVLIB_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\advlib_taskbarcmn.o: ../../src/common/taskbarcmn.cpp $(CXX) -c -o $@ $(ADVLIB_CXXFLAGS) $(CPPDEPS) $< diff --git a/build/msw/makefile.vc b/build/msw/makefile.vc index 090f83bcc1..422eea6e50 100644 --- a/build/msw/makefile.vc +++ b/build/msw/makefile.vc @@ -2671,6 +2671,7 @@ ____ADVANCED_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_treelist.obj \ $(OBJS)\monodll_wizard.obj \ $(OBJS)\monodll_addremovectrl.obj \ + $(OBJS)\monodll_notifmsgcmn.obj \ $(OBJS)\monodll_taskbarcmn.obj \ $(OBJS)\monodll_aboutdlg.obj \ $(OBJS)\monodll_notifmsg.obj \ @@ -2725,6 +2726,7 @@ ____ADVANCED_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_treelist.obj \ $(OBJS)\monodll_wizard.obj \ $(OBJS)\monodll_addremovectrl.obj \ + $(OBJS)\monodll_notifmsgcmn.obj \ $(OBJS)\monodll_taskbarcmn.obj \ $(OBJS)\monodll_aboutdlg.obj \ $(OBJS)\monodll_notifmsg.obj \ @@ -3499,6 +3501,7 @@ ____ADVANCED_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_treelist.obj \ $(OBJS)\monolib_wizard.obj \ $(OBJS)\monolib_addremovectrl.obj \ + $(OBJS)\monolib_notifmsgcmn.obj \ $(OBJS)\monolib_taskbarcmn.obj \ $(OBJS)\monolib_aboutdlg.obj \ $(OBJS)\monolib_notifmsg.obj \ @@ -3553,6 +3556,7 @@ ____ADVANCED_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_treelist.obj \ $(OBJS)\monolib_wizard.obj \ $(OBJS)\monolib_addremovectrl.obj \ + $(OBJS)\monolib_notifmsgcmn.obj \ $(OBJS)\monolib_taskbarcmn.obj \ $(OBJS)\monolib_aboutdlg.obj \ $(OBJS)\monolib_notifmsg.obj \ @@ -4862,6 +4866,7 @@ ____ADVANCED_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\advdll_treelist.obj \ $(OBJS)\advdll_wizard.obj \ $(OBJS)\advdll_addremovectrl.obj \ + $(OBJS)\advdll_notifmsgcmn.obj \ $(OBJS)\advdll_taskbarcmn.obj \ $(OBJS)\advdll_aboutdlg.obj \ $(OBJS)\advdll_notifmsg.obj \ @@ -4916,6 +4921,7 @@ ____ADVANCED_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\advdll_treelist.obj \ $(OBJS)\advdll_wizard.obj \ $(OBJS)\advdll_addremovectrl.obj \ + $(OBJS)\advdll_notifmsgcmn.obj \ $(OBJS)\advdll_taskbarcmn.obj \ $(OBJS)\advdll_aboutdlg.obj \ $(OBJS)\advdll_notifmsg.obj \ @@ -4971,6 +4977,7 @@ ____ADVANCED_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\advlib_treelist.obj \ $(OBJS)\advlib_wizard.obj \ $(OBJS)\advlib_addremovectrl.obj \ + $(OBJS)\advlib_notifmsgcmn.obj \ $(OBJS)\advlib_taskbarcmn.obj \ $(OBJS)\advlib_aboutdlg.obj \ $(OBJS)\advlib_notifmsg.obj \ @@ -5025,6 +5032,7 @@ ____ADVANCED_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\advlib_treelist.obj \ $(OBJS)\advlib_wizard.obj \ $(OBJS)\advlib_addremovectrl.obj \ + $(OBJS)\advlib_notifmsgcmn.obj \ $(OBJS)\advlib_taskbarcmn.obj \ $(OBJS)\advlib_aboutdlg.obj \ $(OBJS)\advlib_notifmsg.obj \ @@ -9493,6 +9501,11 @@ $(OBJS)\monodll_addremovectrl.obj: ..\..\src\common\addremovectrl.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\common\addremovectrl.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\monodll_notifmsgcmn.obj: ..\..\src\common\notifmsgcmn.cpp + $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\common\notifmsgcmn.cpp +!endif + !if "$(USE_GUI)" == "1" $(OBJS)\monodll_taskbarcmn.obj: ..\..\src\common\taskbarcmn.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\common\taskbarcmn.cpp @@ -12003,6 +12016,11 @@ $(OBJS)\monolib_addremovectrl.obj: ..\..\src\common\addremovectrl.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\common\addremovectrl.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\monolib_notifmsgcmn.obj: ..\..\src\common\notifmsgcmn.cpp + $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\common\notifmsgcmn.cpp +!endif + !if "$(USE_GUI)" == "1" $(OBJS)\monolib_taskbarcmn.obj: ..\..\src\common\taskbarcmn.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\common\taskbarcmn.cpp @@ -15881,6 +15899,9 @@ $(OBJS)\advdll_wizard.obj: ..\..\src\generic\wizard.cpp $(OBJS)\advdll_addremovectrl.obj: ..\..\src\common\addremovectrl.cpp $(CXX) /c /nologo /TP /Fo$@ $(ADVDLL_CXXFLAGS) ..\..\src\common\addremovectrl.cpp +$(OBJS)\advdll_notifmsgcmn.obj: ..\..\src\common\notifmsgcmn.cpp + $(CXX) /c /nologo /TP /Fo$@ $(ADVDLL_CXXFLAGS) ..\..\src\common\notifmsgcmn.cpp + $(OBJS)\advdll_taskbarcmn.obj: ..\..\src\common\taskbarcmn.cpp $(CXX) /c /nologo /TP /Fo$@ $(ADVDLL_CXXFLAGS) ..\..\src\common\taskbarcmn.cpp @@ -16037,6 +16058,9 @@ $(OBJS)\advlib_wizard.obj: ..\..\src\generic\wizard.cpp $(OBJS)\advlib_addremovectrl.obj: ..\..\src\common\addremovectrl.cpp $(CXX) /c /nologo /TP /Fo$@ $(ADVLIB_CXXFLAGS) ..\..\src\common\addremovectrl.cpp +$(OBJS)\advlib_notifmsgcmn.obj: ..\..\src\common\notifmsgcmn.cpp + $(CXX) /c /nologo /TP /Fo$@ $(ADVLIB_CXXFLAGS) ..\..\src\common\notifmsgcmn.cpp + $(OBJS)\advlib_taskbarcmn.obj: ..\..\src\common\taskbarcmn.cpp $(CXX) /c /nologo /TP /Fo$@ $(ADVLIB_CXXFLAGS) ..\..\src\common\taskbarcmn.cpp diff --git a/build/msw/wx_adv.vcxproj b/build/msw/wx_adv.vcxproj index f4259082c1..db284de3ce 100644 --- a/build/msw/wx_adv.vcxproj +++ b/build/msw/wx_adv.vcxproj @@ -462,6 +462,7 @@ + @@ -544,7 +545,6 @@ - diff --git a/build/msw/wx_adv.vcxproj.filters b/build/msw/wx_adv.vcxproj.filters index 982ac7865a..1707dd9520 100644 --- a/build/msw/wx_adv.vcxproj.filters +++ b/build/msw/wx_adv.vcxproj.filters @@ -48,6 +48,9 @@ Common Sources + + Common Sources + Common Sources @@ -331,9 +334,6 @@ MSW Headers - - MSW Headers - MSW Headers @@ -388,4 +388,4 @@ MSW Headers - + \ No newline at end of file diff --git a/build/msw/wx_vc7_adv.vcproj b/build/msw/wx_vc7_adv.vcproj index 1401d0f420..5df855d911 100644 --- a/build/msw/wx_vc7_adv.vcproj +++ b/build/msw/wx_vc7_adv.vcproj @@ -324,6 +324,9 @@ + + @@ -587,9 +590,6 @@ - - diff --git a/build/msw/wx_vc7_core.vcproj b/build/msw/wx_vc7_core.vcproj index c07148bb87..9d26e38ba0 100644 --- a/build/msw/wx_vc7_core.vcproj +++ b/build/msw/wx_vc7_core.vcproj @@ -1505,9 +1505,6 @@ - - diff --git a/build/msw/wx_vc8_adv.vcproj b/build/msw/wx_vc8_adv.vcproj index 84da1eeab3..027d4b9056 100644 --- a/build/msw/wx_vc8_adv.vcproj +++ b/build/msw/wx_vc8_adv.vcproj @@ -837,6 +837,10 @@ RelativePath="..\..\src\common\hyperlnkcmn.cpp" > + + @@ -1285,10 +1289,6 @@ RelativePath="..\..\include\wx\msw\joystick.h" > - - diff --git a/build/msw/wx_vc8_core.vcproj b/build/msw/wx_vc8_core.vcproj index d4b862b4a1..6a6ee15189 100644 --- a/build/msw/wx_vc8_core.vcproj +++ b/build/msw/wx_vc8_core.vcproj @@ -2509,10 +2509,6 @@ RelativePath="..\..\include\wx\msw\notebook.h" > - - diff --git a/build/msw/wx_vc9_adv.vcproj b/build/msw/wx_vc9_adv.vcproj index 4cf1b51694..eda236aeba 100644 --- a/build/msw/wx_vc9_adv.vcproj +++ b/build/msw/wx_vc9_adv.vcproj @@ -833,6 +833,10 @@ RelativePath="..\..\src\common\hyperlnkcmn.cpp" > + + @@ -1281,10 +1285,6 @@ RelativePath="..\..\include\wx\msw\joystick.h" > - - diff --git a/build/msw/wx_vc9_core.vcproj b/build/msw/wx_vc9_core.vcproj index 0ffe069944..eb1fa98da3 100644 --- a/build/msw/wx_vc9_core.vcproj +++ b/build/msw/wx_vc9_core.vcproj @@ -2505,10 +2505,6 @@ RelativePath="..\..\include\wx\msw\notebook.h" > - - diff --git a/build/osx/wxcocoa.xcodeproj/project.pbxproj b/build/osx/wxcocoa.xcodeproj/project.pbxproj index 1198bede33..ef21984639 100644 --- a/build/osx/wxcocoa.xcodeproj/project.pbxproj +++ b/build/osx/wxcocoa.xcodeproj/project.pbxproj @@ -511,6 +511,12 @@ 23E9AF567E873B948EFEA180 /* gauge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 98A7F0605AAC3D28A8C9F253 /* gauge.mm */; }; 23E9AF567E873B948EFEA181 /* gauge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 98A7F0605AAC3D28A8C9F253 /* gauge.mm */; }; 23E9AF567E873B948EFEA182 /* gauge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 98A7F0605AAC3D28A8C9F253 /* gauge.mm */; }; + 24133CCD1B78C2E80019C10F /* notifmsg.mm in Sources */ = {isa = PBXBuildFile; fileRef = 24133CCC1B78C2E80019C10F /* notifmsg.mm */; }; + 24133CCF1B78C3230019C10F /* notifmsgcmn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 24133CCE1B78C3230019C10F /* notifmsgcmn.cpp */; }; + 24133CD01B78C3390019C10F /* notifmsgcmn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 24133CCE1B78C3230019C10F /* notifmsgcmn.cpp */; }; + 24133CD11B78C3390019C10F /* notifmsg.mm in Sources */ = {isa = PBXBuildFile; fileRef = 24133CCC1B78C2E80019C10F /* notifmsg.mm */; }; + 24133CD21B78C33A0019C10F /* notifmsgcmn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 24133CCE1B78C3230019C10F /* notifmsgcmn.cpp */; }; + 24133CD31B78C33A0019C10F /* notifmsg.mm in Sources */ = {isa = PBXBuildFile; fileRef = 24133CCC1B78C2E80019C10F /* notifmsg.mm */; }; 242E1D1A9BF331BA918134EC /* pngwtran.c in Sources */ = {isa = PBXBuildFile; fileRef = 0964797530CF3FE7B8DB6242 /* pngwtran.c */; }; 242E1D1A9BF331BA918134ED /* pngwtran.c in Sources */ = {isa = PBXBuildFile; fileRef = 0964797530CF3FE7B8DB6242 /* pngwtran.c */; }; 242E1D1A9BF331BA918134EE /* pngwtran.c in Sources */ = {isa = PBXBuildFile; fileRef = 0964797530CF3FE7B8DB6242 /* pngwtran.c */; }; @@ -3962,6 +3968,8 @@ 238741BDA2C73E56899CCB04 /* dcprint.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = dcprint.cpp; path = ../../src/osx/carbon/dcprint.cpp; sourceTree = ""; }; 239D386E9D7D39C5A1E859C6 /* clipcmn.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = clipcmn.cpp; path = ../../src/common/clipcmn.cpp; sourceTree = ""; }; 23FC98E2305230E2990471E3 /* wxcrt.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = wxcrt.cpp; path = ../../src/common/wxcrt.cpp; sourceTree = ""; }; + 24133CCC1B78C2E80019C10F /* notifmsg.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = notifmsg.mm; path = ../../src/osx/cocoa/notifmsg.mm; sourceTree = ""; }; + 24133CCE1B78C3230019C10F /* notifmsgcmn.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = notifmsgcmn.cpp; path = ../../src/common/notifmsgcmn.cpp; sourceTree = ""; }; 242BF97B558634A79322052C /* prntbase.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = prntbase.cpp; path = ../../src/common/prntbase.cpp; sourceTree = ""; }; 243367CA1C6B91A9000B8ED5 /* utils_base.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = utils_base.mm; path = ../../src/osx/cocoa/utils_base.mm; sourceTree = ""; }; 24396D584D053948A3FF0DCD /* imagpng.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = imagpng.cpp; path = ../../src/common/imagpng.cpp; sourceTree = ""; }; @@ -5557,6 +5565,8 @@ 2FF0B5E0505D3AEA9A4ACF11 /* adv */ = { isa = PBXGroup; children = ( + 24133CCE1B78C3230019C10F /* notifmsgcmn.cpp */, + 24133CCC1B78C2E80019C10F /* notifmsg.mm */, A8ABD099BCEA30DCBF7A04F4 /* animatecmn.cpp */, 8CF560E06F2A3B6088203D09 /* bmpcboxcmn.cpp */, 8D0EF4BDCB5F329ABE15EEED /* calctrlcmn.cpp */, @@ -7773,6 +7783,8 @@ B4425B59CC27389CA9FF81D3 /* datectlg.cpp in Sources */, 5557AA36FBCC3ED9A5F5751C /* editlbox.cpp in Sources */, A139B846584436BCBEBAE3C1 /* grid.cpp in Sources */, + 24133CD21B78C33A0019C10F /* notifmsgcmn.cpp in Sources */, + 24133CD31B78C33A0019C10F /* notifmsg.mm in Sources */, 2E930206397C3EDCBD8206FE /* gridctrl.cpp in Sources */, E5D698D2606A304DA743AF94 /* grideditors.cpp in Sources */, 187F921A95DA3594B0AD980F /* gridsel.cpp in Sources */, @@ -8649,6 +8661,7 @@ 42260A6F1853361083803B0D /* zutil.c in Sources */, 99E7A46106C03484BA70D29F /* tif_unix.c in Sources */, 4E396D8D2E9138D797F320C7 /* tif_aux.c in Sources */, + 24133CD01B78C3390019C10F /* notifmsgcmn.cpp in Sources */, 1EE845DDFDDE36CA8A218206 /* tif_close.c in Sources */, 8E674574343A3C009B1BCD01 /* tif_codec.c in Sources */, D95C5F467D37339AB8DF2355 /* tif_color.c in Sources */, @@ -8796,6 +8809,7 @@ E3AD8574E13B39BDB8D4E92F /* LexKVIrc.cxx in Sources */, 62331487C17B32E081B8FEA8 /* LexLaTeX.cxx in Sources */, DF8124E5E17D386A84CEEA28 /* LexLisp.cxx in Sources */, + 24133CD11B78C3390019C10F /* notifmsg.mm in Sources */, D13AE659C3AC37B68D39B2CA /* LexLout.cxx in Sources */, 9D003890CB7035A298DB7057 /* LexLua.cxx in Sources */, E80BEED62EBF34F09B3F4020 /* LexMagik.cxx in Sources */, @@ -9732,6 +9746,7 @@ D5C304182151365FA9FF8A3D /* xh_bttn.cpp in Sources */, FE9A662A1F9B34D099C45C1D /* xh_cald.cpp in Sources */, 6138BCBC8E4438FA91E0EF9F /* xh_chckb.cpp in Sources */, + 24133CCF1B78C3230019C10F /* notifmsgcmn.cpp in Sources */, 5F2C2A46781739D897CF293D /* xh_chckl.cpp in Sources */, CE17002B5B7E375582747639 /* xh_choic.cpp in Sources */, 26E4813A97DE323E88119163 /* xh_choicbk.cpp in Sources */, @@ -10009,6 +10024,7 @@ E0E40333B61C33B58787078E /* LexMarkdown.cxx in Sources */, 5AEA6E94FB76371D928D371C /* LexMatlab.cxx in Sources */, 1A4F9F18BBEB3515AC7C7CC6 /* LexMetapost.cxx in Sources */, + 24133CCD1B78C2E80019C10F /* notifmsg.mm in Sources */, 3C394FBD47B6310C80577E3B /* LexMMIXAL.cxx in Sources */, 7CC211E10D853B958250A4CE /* LexModula.cxx in Sources */, EC43AFB3670A3D459D9B388D /* LexMPT.cxx in Sources */, diff --git a/include/wx/generic/notifmsg.h b/include/wx/generic/notifmsg.h index 1cd74ba7f0..ccc55108c5 100644 --- a/include/wx/generic/notifmsg.h +++ b/include/wx/generic/notifmsg.h @@ -10,8 +10,6 @@ #ifndef _WX_GENERIC_NOTIFMSG_H_ #define _WX_GENERIC_NOTIFMSG_H_ -class wxNotificationMessageDialog; - // ---------------------------------------------------------------------------- // wxGenericNotificationMessage // ---------------------------------------------------------------------------- @@ -19,40 +17,29 @@ class wxNotificationMessageDialog; class WXDLLIMPEXP_ADV wxGenericNotificationMessage : public wxNotificationMessageBase { public: - wxGenericNotificationMessage() { Init(); } - wxGenericNotificationMessage(const wxString& title, - const wxString& message = wxString(), - wxWindow *parent = NULL, - int flags = wxICON_INFORMATION) - : wxNotificationMessageBase(title, message, parent, flags) + wxGenericNotificationMessage() { Init(); } - virtual ~wxGenericNotificationMessage(); - - - virtual bool Show(int timeout = Timeout_Auto); - virtual bool Close(); + wxGenericNotificationMessage(const wxString& title, + const wxString& message = wxString(), + wxWindow *parent = NULL, + int flags = wxICON_INFORMATION) + { + Init(); + Create(title, message, parent, flags); + } // generic implementation-specific methods // get/set the default timeout (used if Timeout_Auto is specified) - static int GetDefaultTimeout() { return ms_timeout; } + static int GetDefaultTimeout(); static void SetDefaultTimeout(int timeout); private: void Init(); - - // default timeout - static int ms_timeout; - - // notification message is represented by a modeless dialog in this - // implementation - wxNotificationMessageDialog *m_dialog; - - wxDECLARE_NO_COPY_CLASS(wxGenericNotificationMessage); }; diff --git a/include/wx/generic/private/notifmsg.h b/include/wx/generic/private/notifmsg.h new file mode 100644 index 0000000000..6c5fd90874 --- /dev/null +++ b/include/wx/generic/private/notifmsg.h @@ -0,0 +1,52 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/generic/private/notifmsg.h +// Purpose: wxGenericNotificationMessage declarations +// Author: Tobias Taschner +// Created: 2015-08-04 +// Copyright: (c) 2015 wxWidgets development team +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_GENERIC_PRIVATE_NOTIFMSG_H_ +#define _WX_GENERIC_PRIVATE_NOTIFMSG_H_ + +#include "wx/private/notifmsg.h" + +class wxGenericNotificationMessageImpl : public wxNotificationMessageImpl +{ +public: + wxGenericNotificationMessageImpl(wxNotificationMessageBase* notification); + + virtual ~wxGenericNotificationMessageImpl(); + + virtual bool Show(int timeout) wxOVERRIDE; + + virtual bool Close() wxOVERRIDE; + + virtual void SetTitle(const wxString& title) wxOVERRIDE; + + virtual void SetMessage(const wxString& message) wxOVERRIDE; + + virtual void SetParent(wxWindow *parent) wxOVERRIDE; + + virtual void SetFlags(int flags) wxOVERRIDE; + + virtual void SetIcon(const wxIcon& icon) wxOVERRIDE; + + virtual bool AddAction(wxWindowID actionid, const wxString &label) wxOVERRIDE; + + // get/set the default timeout (used if Timeout_Auto is specified) + static int GetDefaultTimeout() { return ms_timeout; } + static void SetDefaultTimeout(int timeout); + +private: + // default timeout + static int ms_timeout; + + // notification message is represented by a frame in this implementation + class wxNotificationMessageWindow *m_window; + + wxDECLARE_NO_COPY_CLASS(wxGenericNotificationMessageImpl); +}; + +#endif // _WX_GENERIC_PRIVATE_NOTIFMSG_H_ diff --git a/include/wx/gtk/notifmsg.h b/include/wx/gtk/notifmsg.h deleted file mode 100644 index 6547a5f90b..0000000000 --- a/include/wx/gtk/notifmsg.h +++ /dev/null @@ -1,51 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Name: wx/gtk/notifmsg.h -// Purpose: wxNotificationMessage for wxGTK. -// Author: Vadim Zeitlin -// Created: 2012-07-25 -// Copyright: (c) 2012 Vadim Zeitlin -// Licence: wxWindows licence -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _WX_GTK_NOTIFMSG_H_ -#define _WX_GTK_NOTIFMSG_H_ - -typedef struct _NotifyNotification NotifyNotification; - -// ---------------------------------------------------------------------------- -// wxNotificationMessage -// ---------------------------------------------------------------------------- - -class WXDLLIMPEXP_ADV wxNotificationMessage : public wxNotificationMessageBase -{ -public: - wxNotificationMessage() { Init(); } - wxNotificationMessage(const wxString& title, - const wxString& message = wxString(), - wxWindow *parent = NULL, - int flags = wxICON_INFORMATION) - : wxNotificationMessageBase(title, message, parent, flags) - { - Init(); - } - - virtual ~wxNotificationMessage(); - - - virtual bool Show(int timeout = Timeout_Auto) wxOVERRIDE; - virtual bool Close() wxOVERRIDE; - - // Set the name of the icon to use, overriding the default icon determined - // by the flags. Call with empty string to reset custom icon. - bool GTKSetIconName(const wxString& name); - -private: - void Init() { m_notification = NULL; } - - NotifyNotification* m_notification; - wxString m_iconName; - - wxDECLARE_NO_COPY_CLASS(wxNotificationMessage); -}; - -#endif // _WX_GTK_NOTIFMSG_H_ diff --git a/include/wx/msw/notifmsg.h b/include/wx/msw/notifmsg.h deleted file mode 100644 index b7e0e0e867..0000000000 --- a/include/wx/msw/notifmsg.h +++ /dev/null @@ -1,74 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Name: wx/msw/notifmsg.h -// Purpose: implementation of wxNotificationMessage for Windows -// Author: Vadim Zeitlin -// Created: 2007-12-01 -// Copyright: (c) 2007 Vadim Zeitlin -// Licence: wxWindows licence -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _WX_MSW_NOTIFMSG_H_ -#define _WX_MSW_NOTIFMSG_H_ - -class WXDLLIMPEXP_FWD_ADV wxTaskBarIcon; - -// ---------------------------------------------------------------------------- -// wxNotificationMessage -// ---------------------------------------------------------------------------- - -class WXDLLIMPEXP_ADV wxNotificationMessage : public wxNotificationMessageBase -{ -public: - wxNotificationMessage() { Init(); } - wxNotificationMessage(const wxString& title, - const wxString& message = wxString(), - wxWindow *parent = NULL, - int flags = wxICON_INFORMATION) - : wxNotificationMessageBase(title, message, parent, flags) - { - Init(); - } - - virtual ~wxNotificationMessage(); - - - virtual bool Show(int timeout = Timeout_Auto); - virtual bool Close(); - - // MSW implementation-specific methods - - // by default, wxNotificationMessage under MSW creates a temporary taskbar - // icon to which it attaches the notification, if there is an existing - // taskbar icon object in the application you may want to call this method - // to attach the notification to it instead (we won't take ownership of it - // and you can also pass NULL to not use the icon for notifications any - // more) - // - // returns the task bar icon which was used previously (may be NULL) - static wxTaskBarIcon *UseTaskBarIcon(wxTaskBarIcon *icon); - - // call this to always use the generic implementation, even if the system - // supports the balloon tooltips used by the native one - static void AlwaysUseGeneric(bool alwaysUseGeneric) - { - ms_alwaysUseGeneric = alwaysUseGeneric; - } - -private: - // common part of all ctors - void Init() { m_impl = NULL; } - - - // flag indicating whether we should always use generic implementation - static bool ms_alwaysUseGeneric; - - // the real implementation of this class (selected during run-time because - // the balloon task bar icons are not available in all Windows versions) - class wxNotifMsgImpl *m_impl; - - - wxDECLARE_NO_COPY_CLASS(wxNotificationMessage); -}; - -#endif // _WX_MSW_NOTIFMSG_H_ - diff --git a/include/wx/msw/taskbar.h b/include/wx/msw/taskbar.h index 5728a424f0..3fe5c9b61b 100644 --- a/include/wx/msw/taskbar.h +++ b/include/wx/msw/taskbar.h @@ -49,7 +49,8 @@ public: bool ShowBalloon(const wxString& title, const wxString& text, unsigned msec = 0, - int flags = 0); + int flags = 0, + const wxIcon& icon = wxNullIcon); #endif // wxUSE_TASKBARICON_BALLOONS protected: diff --git a/include/wx/notifmsg.h b/include/wx/notifmsg.h index a5298f8c45..bb4dae0a3b 100644 --- a/include/wx/notifmsg.h +++ b/include/wx/notifmsg.h @@ -29,8 +29,7 @@ public: // default ctor, use setters below to initialize it later wxNotificationMessageBase() { - m_parent = NULL; - m_flags = wxICON_INFORMATION; + Init(); } // create a notification object with the given title and message (the @@ -39,39 +38,38 @@ public: const wxString& message = wxEmptyString, wxWindow *parent = NULL, int flags = wxICON_INFORMATION) - : m_title(title), - m_message(message), - m_parent(parent) { - SetFlags(flags); + Init(); + Create(title, message, parent, flags); } + virtual ~wxNotificationMessageBase(); + // note that the setters must be called before Show() // set the title: short string, markup not allowed - void SetTitle(const wxString& title) { m_title = title; } + void SetTitle(const wxString& title); // set the text of the message: this is a longer string than the title and // some platforms allow simple HTML-like markup in it - void SetMessage(const wxString& message) { m_message = message; } + void SetMessage(const wxString& message); // set the parent for this notification: we'll be associated with the top // level parent of this window or, if this method is not called, with the // main application window by default - void SetParent(wxWindow *parent) { m_parent = parent; } + void SetParent(wxWindow *parent); // this method can currently be used to choose a standard icon to use: the // parameter may be one of wxICON_INFORMATION, wxICON_WARNING or // wxICON_ERROR only (but not wxICON_QUESTION) - void SetFlags(int flags) - { - wxASSERT_MSG( flags == wxICON_INFORMATION || - flags == wxICON_WARNING || flags == wxICON_ERROR, - "Invalid icon flags specified" ); + void SetFlags(int flags); - m_flags = flags; - } + // set a custom icon to use instead of the system provided specified via SetFlags + virtual void SetIcon(const wxIcon& icon); + // Add a button to the notification, returns false if the platform does not support + // actions in notifications + virtual bool AddAction(wxWindowID actionid, const wxString &label = wxString()); // showing and hiding // ------------------ @@ -87,70 +85,92 @@ public: // pass (special values Timeout_Auto and Timeout_Never can be used) // // returns false if an error occurred - virtual bool Show(int timeout = Timeout_Auto) = 0; + bool Show(int timeout = Timeout_Auto); // hide the notification, returns true if it was hidden or false if it // couldn't be done (e.g. on some systems automatically hidden // notifications can't be hidden manually) - virtual bool Close() = 0; + bool Close(); protected: - // accessors for the derived classes - const wxString& GetTitle() const { return m_title; } - const wxString& GetMessage() const { return m_message; } - wxWindow *GetParent() const { return m_parent; } - int GetFlags() const { return m_flags; } - - // return the concatenation of title and message separated by a new line, - // this is suitable for simple implementation which have no support for - // separate title and message parts of the notification - wxString GetFullMessage() const + // Common part of all ctors. + void Create(const wxString& title = wxEmptyString, + const wxString& message = wxEmptyString, + wxWindow *parent = NULL, + int flags = wxICON_INFORMATION) { - wxString text(m_title); - if ( !m_message.empty() ) - { - text << "\n\n" << m_message; - } - - return text; + SetTitle(title); + SetMessage(message); + SetParent(parent); + SetFlags(flags); } + class wxNotificationMessageImpl* m_impl; + private: - wxString m_title, - m_message; - wxWindow *m_parent; - - int m_flags; + void Init() + { + m_impl = NULL; + } wxDECLARE_NO_COPY_CLASS(wxNotificationMessageBase); }; -/* - TODO: Implement under OS X using notification centre (10.8+) or - Growl (http://growl.info/) for the previous versions. - */ -#if defined(__WXGTK__) && wxUSE_LIBNOTIFY - #include "wx/gtk/notifmsg.h" -#elif defined(__WXMSW__) && wxUSE_TASKBARICON && wxUSE_TASKBARICON_BALLOONS - #include "wx/msw/notifmsg.h" -#else - #include "wx/generic/notifmsg.h" +wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_ADV, wxEVT_NOTIFICATION_MESSAGE_CLICK, wxCommandEvent ); +wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_ADV, wxEVT_NOTIFICATION_MESSAGE_DISMISSED, wxCommandEvent ); +wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_ADV, wxEVT_NOTIFICATION_MESSAGE_ACTION, wxCommandEvent ); - class wxNotificationMessage : public wxGenericNotificationMessage - { - public: - wxNotificationMessage() { } - wxNotificationMessage(const wxString& title, - const wxString& message = wxEmptyString, - wxWindow *parent = NULL, - int flags = wxICON_INFORMATION) - : wxGenericNotificationMessage(title, message, parent, flags) - { - } - }; +#if (defined(__WXGTK__) && wxUSE_LIBNOTIFY) || \ + (defined(__WXMSW__) && wxUSE_TASKBARICON && wxUSE_TASKBARICON_BALLOONS) || \ + (defined(__WXOSX_COCOA__) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8)) + #define wxHAS_NATIVE_NOTIFICATION_MESSAGE #endif +// ---------------------------------------------------------------------------- +// wxNotificationMessage +// ---------------------------------------------------------------------------- + +#ifdef wxHAS_NATIVE_NOTIFICATION_MESSAGE + +#if defined(__WXMSW__) +class WXDLLIMPEXP_FWD_ADV wxTaskBarIcon; +#endif // defined(__WXMSW__) + +#else +#include "wx/generic/notifmsg.h" +#endif // wxHAS_NATIVE_NOTIFICATION_MESSAGE + +class WXDLLIMPEXP_ADV wxNotificationMessage : public +#ifdef wxHAS_NATIVE_NOTIFICATION_MESSAGE + wxNotificationMessageBase +#else + wxGenericNotificationMessage +#endif +{ +public: + wxNotificationMessage() { Init(); } + wxNotificationMessage(const wxString& title, + const wxString& message = wxString(), + wxWindow *parent = NULL, + int flags = wxICON_INFORMATION) + { + Init(); + Create(title, message, parent, flags); + } + +#if defined(__WXMSW__) && defined(wxHAS_NATIVE_NOTIFICATION_MESSAGE) + // returns the task bar icon which was used previously (may be NULL) + static wxTaskBarIcon *UseTaskBarIcon(wxTaskBarIcon *icon); +#endif + +private: + // common part of all ctors + void Init(); + + wxDECLARE_NO_COPY_CLASS(wxNotificationMessage); +}; + #endif // wxUSE_NOTIFICATION_MESSAGE #endif // _WX_NOTIFMSG_H_ diff --git a/include/wx/private/notifmsg.h b/include/wx/private/notifmsg.h new file mode 100644 index 0000000000..772a9c308e --- /dev/null +++ b/include/wx/private/notifmsg.h @@ -0,0 +1,76 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/private/notifmsg.h +// Purpose: wxNotificationMessage declarations +// Author: Tobias Taschner +// Created: 2015-08-04 +// Copyright: (c) 2015 wxWidgets development team +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_PRIVATE_NOTIFMSG_H_ +#define _WX_PRIVATE_NOTIFMSG_H_ + +class wxNotificationMessageImpl +{ +public: + wxNotificationMessageImpl(wxNotificationMessageBase* notification): + m_notification(notification), + m_active(false) + { + + } + + virtual ~wxNotificationMessageImpl() { } + + virtual bool Show(int timeout) = 0; + + virtual bool Close() = 0; + + virtual void SetTitle(const wxString& title) = 0; + + virtual void SetMessage(const wxString& message) = 0; + + virtual void SetParent(wxWindow *parent) = 0; + + virtual void SetFlags(int flags) = 0; + + virtual void SetIcon(const wxIcon& icon) = 0; + + virtual bool AddAction(wxWindowID actionid, const wxString &label) = 0; + + virtual void Detach() + { + if (m_active) + m_notification = NULL; + else + delete this; + } + + bool ProcessNotificationEvent(wxEvent& event) + { + if (m_notification) + return m_notification->ProcessEvent(event); + else + return false; + } + + wxNotificationMessageBase* GetNotification() const + { + return m_notification; + } + +protected: + wxNotificationMessageBase* m_notification; + bool m_active; + + void SetActive(bool active) + { + m_active = active; + + // Delete the implementation if the notification is detached + if (!m_notification && !active) + delete this; + } +}; + +#endif // _WX_PRIVATE_NOTIFMSG_H_ diff --git a/interface/wx/notifmsg.h b/interface/wx/notifmsg.h index 82d2769cd0..7b35be6f82 100644 --- a/interface/wx/notifmsg.h +++ b/interface/wx/notifmsg.h @@ -10,12 +10,36 @@ This class allows to show the user a message non intrusively. - Currently it is implemented natively for Windows and GTK and uses - (non-modal) dialogs for the display of the notifications under the other - platforms. + Currently it is implemented natively for Windows, OS X, GTK and uses + generic toast notifications under the other platforms. It's not recommended + but @c wxGenericNotificationMessage can be used instead of the native ones. + This might make sense if your application requires features not available in + the native implementation. Notice that this class is not a window and so doesn't derive from wxWindow. + @section platform_notes Platform Notes + + @par OS X + The OS X implementation uses Notification Center to display native notifications. + In order to use actions your notifications must use the alert style. This can + be enabled by the user in system settings or by setting the + @c NSUserNotificationAlertStyle value in Info.plist to @c alert. Please note + that the user always has the option to change the notification style. + + + @beginEventEmissionTable{wxCommandEvent} + @event{EVT_NOTIFICATION_MESSAGE_CLICK(id, func)} + Process a @c EVT_NOTIFICATION_MESSAGE_CLICK event, when a notification + is clicked. + @event{wxEVT_NOTIFICATION_MESSAGE_DISMISSED(id, func)} + Process a @c wxEVT_NOTIFICATION_MESSAGE_DISMISSED event, when a notification + is dismissed by the user or times out. + @event{wxEVT_NOTIFICATION_MESSAGE_ACTION(id, func)} + Process a @c wxEVT_NOTIFICATION_MESSAGE_ACTION event, when the user + selects on of the actions added by AddAction() + @endEventTable + @since 2.9.0 @library{wxadv} @category{misc} @@ -53,6 +77,17 @@ public: */ virtual ~wxNotificationMessage(); + /** + Add an action to the notification. If supported by the implementation + this are usually buttons in the notification selectable by the user. + + @return @false if the current implementation or OS version + does not support actions in notifications. + + @since 3.1.0 + */ + bool AddAction(wxWindowID actionid, const wxString &label = wxString()); + /** Hides the notification. @@ -69,9 +104,22 @@ public: Valid values are @c wxICON_INFORMATION, @c wxICON_WARNING and @c wxICON_ERROR (notice that @c wxICON_QUESTION is not allowed here). Some implementations of this class may not support the icons. + + @see SetIcon() */ void SetFlags(int flags); + /** + Specify a custom icon to be displayed in the notification. + + Some implementations of this class may not support custom icons. + + @see SetFlags() + + @since 3.1.0 + */ + void SetIcon(const wxIcon& icon); + /** Set the main text of the notification. diff --git a/samples/dialogs/dialogs.cpp b/samples/dialogs/dialogs.cpp index 5ee454bb09..ba16c55edf 100644 --- a/samples/dialogs/dialogs.cpp +++ b/samples/dialogs/dialogs.cpp @@ -32,8 +32,13 @@ #include "wx/minifram.h" #include "wx/sysopt.h" #include "wx/notifmsg.h" +#include "wx/generic/notifmsg.h" #include "wx/modalhook.h" +#if defined(__WXMSW__) && wxUSE_TASKBARICON +#include "wx/taskbar.h" +#endif + #if wxUSE_RICHMSGDLG #include "wx/richmsgdlg.h" #endif // wxUSE_RICHMSGDLG @@ -267,9 +272,7 @@ wxBEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(DIALOGS_REQUEST, MyFrame::OnRequestUserAttention) #if wxUSE_NOTIFICATION_MESSAGE - EVT_MENU(DIALOGS_NOTIFY_AUTO, MyFrame::OnNotifMsgAuto) - EVT_MENU(DIALOGS_NOTIFY_SHOW, MyFrame::OnNotifMsgShow) - EVT_MENU(DIALOGS_NOTIFY_HIDE, MyFrame::OnNotifMsgHide) + EVT_MENU(DIALOGS_NOTIFY_MSG, MyFrame::OnNotifMsg) #endif // wxUSE_NOTIFICATION_MESSAGE #if wxUSE_RICHTOOLTIP @@ -553,9 +556,8 @@ bool MyApp::OnInit() wxMenu *menuNotif = new wxMenu; menuNotif->Append(DIALOGS_REQUEST, wxT("&Request user attention\tCtrl-Shift-R")); #if wxUSE_NOTIFICATION_MESSAGE - menuNotif->Append(DIALOGS_NOTIFY_AUTO, "&Automatically hidden notification"); - menuNotif->Append(DIALOGS_NOTIFY_SHOW, "&Show manual notification"); - menuNotif->Append(DIALOGS_NOTIFY_HIDE, "&Hide manual notification"); + menuNotif->AppendSeparator(); + menuNotif->Append(DIALOGS_NOTIFY_MSG, "User &Notification\tCtrl-Shift-N"); #endif // wxUSE_NOTIFICATION_MESSAGE menuDlg->AppendSubMenu(menuNotif, "&User notifications"); @@ -632,10 +634,6 @@ MyFrame::MyFrame(const wxString& title) } #endif // wxUSE_COLOURDLG -#if wxUSE_NOTIFICATION_MESSAGE - m_notifMsg = NULL; -#endif // wxUSE_NOTIFICATION_MESSAGE - #if wxUSE_STATUSBAR CreateStatusBar(); #endif // wxUSE_STATUSBAR @@ -708,9 +706,6 @@ MyFrame::MyFrame(const wxString& title) MyFrame::~MyFrame() { -#if wxUSE_NOTIFICATION_MESSAGE - delete m_notifMsg; -#endif // wxUSE_NOTIFICATION_MESSAGE } #if wxUSE_COLOURDLG @@ -1900,53 +1895,402 @@ void MyFrame::OnRequestUserAttention(wxCommandEvent& WXUNUSED(event)) RequestUserAttention(wxUSER_ATTENTION_ERROR); } +#if wxUSE_RICHTOOLTIP || wxUSE_NOTIFICATION_MESSAGE + +#include "tip.xpm" + +#endif + #if wxUSE_NOTIFICATION_MESSAGE -void MyFrame::OnNotifMsgAuto(wxCommandEvent& WXUNUSED(event)) +// ---------------------------------------------------------------------------- +// TestNotificationMessageDialog +// ---------------------------------------------------------------------------- + +class TestNotificationMessageWindow : public wxFrame { - // Notice that the notification remains shown even after the - // wxNotificationMessage object itself is destroyed so we can show simple - // notifications using temporary objects. - if ( !wxNotificationMessage - ( - "Automatic Notification", - "Nothing important has happened\n" - "this notification will disappear soon." - ).Show() ) +public: + TestNotificationMessageWindow(wxWindow *parent) : + wxFrame(parent, wxID_ANY, "User Notification Test Dialog") { - wxLogStatus("Failed to show notification message"); +#ifdef __WXMSW__ + SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); +#endif + wxSizer * const sizerTop = new wxBoxSizer(wxVERTICAL); + + wxSizer* sizerText = new wxStaticBoxSizer(wxVERTICAL, this, "Notification Texts"); + + sizerText->Add(new wxStaticText(this, wxID_ANY, "&Title:"), + wxSizerFlags()); + m_textTitle = new wxTextCtrl(this, wxID_ANY, "Notification Title"); + sizerText->Add(m_textTitle, wxSizerFlags().Expand()); + + sizerText->Add(new wxStaticText(this, wxID_ANY, "&Message:"), + wxSizerFlags()); + m_textMessage = new wxTextCtrl(this, wxID_ANY, "A message within the notification", + wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE); + m_textMessage->SetMinSize(wxSize(300, -1)); + sizerText->Add(m_textMessage, wxSizerFlags().Expand()); + + sizerTop->Add(sizerText, wxSizerFlags().Expand().Border()); + + const wxString icons[] = + { + "De&fault", + "None", + "&Information", + "&Warning", + "&Error", + "&Custom" + }; + wxCOMPILE_TIME_ASSERT(WXSIZEOF(icons) == Icon_Max, IconMismatch); + m_icons = new wxRadioBox(this, wxID_ANY, "Ic&on in notification", + wxDefaultPosition, wxDefaultSize, + WXSIZEOF(icons), icons, + 1, wxRA_SPECIFY_ROWS); + m_icons->SetSelection(Icon_Default); + sizerTop->Add(m_icons, wxSizerFlags().Expand().Border()); + + const wxString timeouts[] = + { + "&Automatic", + "&Never", + "&5 sec", + "&15 sec" + }; + m_showTimeout = new wxRadioBox(this, wxID_ANY, "&Timeout for notification", + wxDefaultPosition, wxDefaultSize, + WXSIZEOF(timeouts), timeouts, + 1, wxRA_SPECIFY_ROWS); + m_showTimeout->SetSelection(0); + sizerTop->Add(m_showTimeout, wxSizerFlags().Expand().Border()); + + wxSizer* sizerActions = new wxStaticBoxSizer(wxVERTICAL, this, "Additional Actions"); + + m_actionList = new wxListBox(this, wxID_ANY); + sizerActions->Add(m_actionList, wxSizerFlags().Expand()); + + wxSizer* sizerActionMod = new wxBoxSizer(wxHORIZONTAL); + sizerActionMod->Add(new wxStaticText(this, wxID_ANY, "ID:"), wxSizerFlags().Center()); + const wxString actionIds[] = + { + "wxID_DELETE", + "wxID_CLOSE", + "wxID_OK", + "wxID_CANCEL" + }; + m_actionChoice = new wxChoice(this, wxID_ANY, + wxDefaultPosition, wxDefaultSize, + WXSIZEOF(actionIds), actionIds + ); + m_actionChoice->SetSelection(0); + sizerActionMod->Add(m_actionChoice); + sizerActionMod->Add(new wxStaticText(this, wxID_ANY, "Custom label:"), wxSizerFlags().Center()); + m_actionCaption = new wxTextCtrl(this, wxID_ANY); + sizerActionMod->Add(m_actionCaption); + wxButton* actionAddBtn = new wxButton(this, wxID_ADD); + actionAddBtn->Bind(wxEVT_BUTTON, &TestNotificationMessageWindow::OnActionAddClicked, this); + sizerActionMod->Add(actionAddBtn); + wxButton* actionRemoveBtn = new wxButton(this, wxID_REMOVE); + actionRemoveBtn->Bind(wxEVT_BUTTON, &TestNotificationMessageWindow::OnActionRemoveClicked, this); + sizerActionMod->Add(actionRemoveBtn); + + sizerActions->Add(sizerActionMod, wxSizerFlags().Border()); + + sizerTop->Add(sizerActions, wxSizerFlags().Expand().Border()); + + wxSizer* sizerSettings = new wxStaticBoxSizer(wxVERTICAL, this, "Notification Settings"); + +#ifdef wxHAS_NATIVE_NOTIFICATION_MESSAGE + m_useGeneric = new wxCheckBox(this, wxID_ANY, "Use &generic notifications"); + sizerSettings->Add(m_useGeneric); +#endif + + m_delayShow = new wxCheckBox(this, wxID_ANY, "&Delay show"); +#if defined(__WXOSX__) + m_delayShow->SetValue(true); +#endif + sizerSettings->Add(m_delayShow); + + m_handleEvents = new wxCheckBox(this, wxID_ANY, "&Handle events"); + m_handleEvents->SetValue(true); + sizerSettings->Add(m_handleEvents); + +#if defined(__WXMSW__) && wxUSE_TASKBARICON + m_taskbarIcon = NULL; + m_useTaskbar = new wxCheckBox(this, wxID_ANY, "Use persistent &taskbar icon"); + m_useTaskbar->SetValue(false); + sizerSettings->Add(m_useTaskbar); +#endif + + sizerTop->Add(sizerSettings, wxSizerFlags().Expand().Border()); + + m_textStatus = new wxStaticText(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, + wxST_NO_AUTORESIZE | wxALIGN_CENTRE_HORIZONTAL); + m_textStatus->SetForegroundColour(*wxBLUE); + sizerTop->Add(m_textStatus, wxSizerFlags().Expand().Border()); + + wxSizer* sizerButtons = new wxBoxSizer(wxHORIZONTAL); + sizerButtons->Add(new wxButton(this, wxID_NEW, "&Show")); + m_closeButton = new wxButton(this, wxID_CLOSE, "&Close"); + m_closeButton->Disable(); + sizerButtons->Add(m_closeButton); + sizerTop->Add(sizerButtons, wxSizerFlags().Center()); + + SetSizerAndFit(sizerTop); + + Center(); + + Bind(wxEVT_BUTTON, &TestNotificationMessageWindow::OnShowClicked, this, wxID_NEW); + Bind(wxEVT_BUTTON, &TestNotificationMessageWindow::OnCloseClicked, this, wxID_CLOSE); } - // But it doesn't have to be a temporary, of course. - wxNotificationMessage n("Dummy Warning", "Example of a warning notification."); - n.SetFlags(wxICON_ERROR); - n.Show(5); // Just for testing, use 5 second delay. -} +private: + enum + { + Icon_Default, + Icon_None, + Icon_Info, + Icon_Warning, + Icon_Error, + Icon_Custom, + Icon_Max + }; -void MyFrame::OnNotifMsgShow(wxCommandEvent& WXUNUSED(event)) + class ActionInfo : public wxClientData + { + public: + ActionInfo(wxWindowID actionId, const wxString& actionCaption): + id(actionId), + customCaption(actionCaption) + { + + } + + wxWindowID id; + wxString customCaption; + }; + + wxTextCtrl* m_textTitle; + wxTextCtrl* m_textMessage; + wxRadioBox* m_icons; + wxRadioBox* m_showTimeout; + wxListBox* m_actionList; + wxChoice* m_actionChoice; + wxTextCtrl* m_actionCaption; +#ifdef wxHAS_NATIVE_NOTIFICATION_MESSAGE + wxCheckBox* m_useGeneric; +#endif + wxCheckBox* m_delayShow; + wxCheckBox* m_handleEvents; + wxStaticText* m_textStatus; + wxButton* m_closeButton; + +#if defined(__WXMSW__) && wxUSE_TASKBARICON + wxCheckBox* m_useTaskbar; + wxTaskBarIcon* m_taskbarIcon; +#endif + + wxSharedPtr< wxNotificationMessageBase> m_notif; + + void DoShowNotification() + { + if ( m_delayShow->GetValue() ) + { + ShowStatus("Sleeping for 3 seconds to allow you to switch to another window"); + wxYield(); + wxSleep(3); + } + + m_closeButton->Enable(); + ShowStatus("Showing notification..."); +#ifdef wxHAS_NATIVE_NOTIFICATION_MESSAGE + if ( m_useGeneric->GetValue() ) + m_notif = new wxGenericNotificationMessage( + m_textTitle->GetValue(), + m_textMessage->GetValue(), + this); + else +#endif + { + m_notif = new wxNotificationMessage( + m_textTitle->GetValue(), + m_textMessage->GetValue(), + this); + +#if defined(__WXMSW__) && wxUSE_TASKBARICON + if ( m_useTaskbar->GetValue() ) + { + if ( !m_taskbarIcon ) + { + m_taskbarIcon = new wxTaskBarIcon(); + m_taskbarIcon->SetIcon(reinterpret_cast(GetParent())->GetIcon(), + "Dialogs Sample (Persistent)"); + } + wxNotificationMessage::UseTaskBarIcon(m_taskbarIcon); + } + else + if ( m_taskbarIcon ) + { + wxNotificationMessage::UseTaskBarIcon(NULL); + delete m_taskbarIcon; + m_taskbarIcon = NULL; + } +#endif + } + + switch (m_icons->GetSelection()) + { + case Icon_Default: + // Don't call SetFlags or SetIcon to see the implementations default + break; + case Icon_None: + m_notif->SetFlags(0); + break; + case Icon_Info: + m_notif->SetFlags(wxICON_INFORMATION); + break; + case Icon_Warning: + m_notif->SetFlags(wxICON_WARNING); + break; + case Icon_Error: + m_notif->SetFlags(wxICON_ERROR); + break; + case Icon_Custom: + m_notif->SetIcon(tip_xpm); + break; + } + + int timeout; + switch (m_showTimeout->GetSelection()) + { + case 1: + timeout = wxNotificationMessage::Timeout_Never; + break; + case 2: + timeout = 5; + break; + case 3: + timeout = 10; + break; + default: + timeout = wxNotificationMessage::Timeout_Auto; + break; + } + + for (unsigned int i = 0; i < m_actionList->GetCount(); i++) + { + ActionInfo* ai = reinterpret_cast(m_actionList->GetClientObject(i)); + if ( !m_notif->AddAction(ai->id, ai->customCaption) ) + wxLogWarning("Could not add action: %s", m_actionList->GetString(i)); + } + + if ( m_handleEvents->GetValue() ) + { + m_notif->Bind(wxEVT_NOTIFICATION_MESSAGE_ACTION, &TestNotificationMessageWindow::OnNotificationAction, this); + m_notif->Bind(wxEVT_NOTIFICATION_MESSAGE_CLICK, &TestNotificationMessageWindow::OnNotificationClicked, this); + m_notif->Bind(wxEVT_NOTIFICATION_MESSAGE_DISMISSED, &TestNotificationMessageWindow::OnNotificationDismissed, this); + } + + m_notif->Show(timeout); + + // Free the notification if we don't handle it's events + if ( !m_handleEvents->GetValue() ) + { + // Notice that the notification remains shown even after the + // wxNotificationMessage object itself is destroyed so we can show simple + // notifications using temporary objects. + m_notif.reset(); + ShowStatus("Showing notification, deleted object"); + } + } + + void OnShowClicked(wxCommandEvent& WXUNUSED(event)) + { + DoShowNotification(); + } + + void OnCloseClicked(wxCommandEvent& WXUNUSED(event)) + { + if ( m_notif ) + m_notif->Close(); + } + + void OnActionAddClicked(wxCommandEvent& WXUNUSED(event)) + { + wxWindowID actionId; + switch (m_actionChoice->GetSelection()) + { + case 1: + actionId = wxID_CLOSE; + break; + case 2: + actionId = wxID_OK; + break; + case 3: + actionId = wxID_CANCEL; + break; + default: + actionId = wxID_DELETE; + break; + } + + wxString actionCaption = m_actionCaption->GetValue(); + wxString desc = m_actionChoice->GetStringSelection(); + if ( !actionCaption.empty() ) + desc += " (" + actionCaption + ")"; + m_actionList->SetSelection( m_actionList->Append( desc, new ActionInfo(actionId, actionCaption) ) ); + } + + void OnActionRemoveClicked(wxCommandEvent& WXUNUSED(event)) + { + int pos = m_actionList->GetSelection(); + if ( pos != wxNOT_FOUND ) + { + m_actionList->Delete(pos); + if ( pos > 0 && m_actionList->GetCount() > 0 ) + m_actionList->SetSelection(pos - 1); + } + else + wxLogError("No action selected"); + } + + void OnNotificationClicked(wxCommandEvent& event) + { + ShowStatus("Notification was clicked"); + + Raise(); + + event.Skip(); + } + + void OnNotificationDismissed(wxCommandEvent& event) + { + ShowStatus("Notification was dismissed"); + + Raise(); + + event.Skip(); + } + + void OnNotificationAction(wxCommandEvent& event) + { + ShowStatus(wxString::Format("Selected %s action in notification", wxGetStockLabel(event.GetId(), 0)) ); + + event.Skip(); + } + + void ShowStatus(const wxString& text) + { + m_textStatus->SetLabelText(text); + } + +}; + +void MyFrame::OnNotifMsg(wxCommandEvent& WXUNUSED(event)) { - if ( !m_notifMsg ) - { - m_notifMsg = new wxNotificationMessage - ( - "wxWidgets Manual Notification", - "You can hide this notification from the menu", - this - ); - } - - if ( !m_notifMsg->Show(wxNotificationMessage::Timeout_Never) ) - { - wxLogStatus("Failed to show manual notification message"); - } -} - -void MyFrame::OnNotifMsgHide(wxCommandEvent& WXUNUSED(event)) -{ - if ( m_notifMsg && !m_notifMsg->Close() ) - { - wxLogStatus("Failed to hide manual notification message"); - } + TestNotificationMessageWindow* dlg = new TestNotificationMessageWindow(this); + dlg->Show(); } #endif // wxUSE_NOTIFICATION_MESSAGE @@ -1955,8 +2299,6 @@ void MyFrame::OnNotifMsgHide(wxCommandEvent& WXUNUSED(event)) #include "wx/richtooltip.h" -#include "tip.xpm" - class RichTipDialog : public wxDialog { public: @@ -2225,7 +2567,7 @@ TestDefaultActionDialog::TestDefaultActionDialog( wxWindow *parent ) : main_sizer->Add( grid_sizer, 0, wxALL, 10 ); wxSizer *button_sizer = CreateSeparatedButtonSizer( wxOK|wxCANCEL ); - if (button_sizer) + if ( button_sizer ) main_sizer->Add( button_sizer, 0, wxALL|wxGROW, 5 ); SetSizerAndFit( main_sizer ); diff --git a/samples/dialogs/dialogs.h b/samples/dialogs/dialogs.h index c3f8b4cfda..e611a355db 100644 --- a/samples/dialogs/dialogs.h +++ b/samples/dialogs/dialogs.h @@ -485,9 +485,7 @@ public: void OnRequestUserAttention(wxCommandEvent& event); #if wxUSE_NOTIFICATION_MESSAGE - void OnNotifMsgAuto(wxCommandEvent& event); - void OnNotifMsgShow(wxCommandEvent& event); - void OnNotifMsgHide(wxCommandEvent& event); + void OnNotifMsg(wxCommandEvent& event); #endif // wxUSE_NOTIFICATION_MESSAGE #if wxUSE_RICHTOOLTIP @@ -517,10 +515,6 @@ private: *m_dlgReplace; #endif // wxUSE_FINDREPLDLG -#if wxUSE_NOTIFICATION_MESSAGE - wxNotificationMessage *m_notifMsg; -#endif // wxUSE_NOTIFICATION_MESSAGE - wxColourData m_clrData; // just a window which we use to show the effect of font/colours selection @@ -612,9 +606,7 @@ enum DIALOGS_FIND, DIALOGS_REPLACE, DIALOGS_REQUEST, - DIALOGS_NOTIFY_AUTO, - DIALOGS_NOTIFY_SHOW, - DIALOGS_NOTIFY_HIDE, + DIALOGS_NOTIFY_MSG, DIALOGS_RICHTIP_DIALOG, DIALOGS_PROPERTY_SHEET, DIALOGS_PROPERTY_SHEET_TOOLBOOK, diff --git a/src/common/notifmsgcmn.cpp b/src/common/notifmsgcmn.cpp new file mode 100644 index 0000000000..10033b96f9 --- /dev/null +++ b/src/common/notifmsgcmn.cpp @@ -0,0 +1,103 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: src/common/notifmsgcmn.cpp +// Purpose: wxNotificationMessageBase implementation +// Author: Tobias Taschner +// Created: 2015-08-04 +// Copyright: (c) 2015 wxWidgets development team +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#if wxUSE_NOTIFICATION_MESSAGE + +#include "wx/notifmsg.h" + +#include "wx/private/notifmsg.h" + +#ifndef wxHAS_NATIVE_NOTIFICATION_MESSAGE +#include "wx/generic/private/notifmsg.h" +#endif + +wxDEFINE_EVENT( wxEVT_NOTIFICATION_MESSAGE_CLICK, wxCommandEvent ); +wxDEFINE_EVENT( wxEVT_NOTIFICATION_MESSAGE_DISMISSED, wxCommandEvent ); +wxDEFINE_EVENT( wxEVT_NOTIFICATION_MESSAGE_ACTION, wxCommandEvent ); + +// ---------------------------------------------------------------------------- +// wxNotificationMessageBase +// ---------------------------------------------------------------------------- + +wxNotificationMessageBase::~wxNotificationMessageBase() +{ + m_impl->Detach(); +} + +bool wxNotificationMessageBase::Show(int timeout) +{ + return m_impl->Show(timeout); +} + +bool wxNotificationMessageBase::Close() +{ + return m_impl->Close(); +} + +void wxNotificationMessageBase::SetTitle(const wxString& title) +{ + m_impl->SetTitle(title); +} + +void wxNotificationMessageBase::SetMessage(const wxString& message) +{ + m_impl->SetMessage(message); +} + +void wxNotificationMessageBase::SetParent(wxWindow *parent) +{ + m_impl->SetParent(parent); +} + +void wxNotificationMessageBase::SetFlags(int flags) +{ + wxASSERT_MSG(flags == wxICON_INFORMATION || + flags == wxICON_WARNING || flags == wxICON_ERROR || + flags == 0, + "Invalid icon flags specified"); + + m_impl->SetFlags(flags); +} + +void wxNotificationMessageBase::SetIcon(const wxIcon& icon) +{ + m_impl->SetIcon(icon); +} + +bool wxNotificationMessageBase::AddAction(wxWindowID actionid, const wxString &label) +{ + return m_impl->AddAction(actionid, label); +} + +// +// wxNotificationMessage +// + +#ifndef wxHAS_NATIVE_NOTIFICATION_MESSAGE + +void wxNotificationMessage::Init() +{ + m_impl = new wxGenericNotificationMessageImpl(this); +} + +#endif + +#endif // wxUSE_NOTIFICATION_MESSAGE diff --git a/src/generic/notifmsgg.cpp b/src/generic/notifmsgg.cpp index 3118c3be6a..26fd26593a 100644 --- a/src/generic/notifmsgg.cpp +++ b/src/generic/notifmsgg.cpp @@ -25,13 +25,16 @@ #if wxUSE_NOTIFICATION_MESSAGE #ifndef WX_PRECOMP - #include "wx/dialog.h" - #include "wx/timer.h" + #include "wx/frame.h" + #include "wx/timer.h" #include "wx/sizer.h" #include "wx/statbmp.h" + #include "wx/settings.h" + #include "wx/panel.h" #endif //WX_PRECOMP #include "wx/artprov.h" +#include "wx/bmpbuttn.h" // even if the platform has the native implementation, we still normally want // to use the generic one (unless it's totally unsuitable for the target UI) @@ -41,93 +44,220 @@ // uses the generic version, the second inclusion will do no harm) #include "wx/notifmsg.h" #include "wx/generic/notifmsg.h" +#include "wx/generic/private/notifmsg.h" +#include "wx/display.h" +#include "wx/textwrapper.h" // ---------------------------------------------------------------------------- -// wxNotificationMessageDialog +// wxNotificationMessageWindow // ---------------------------------------------------------------------------- -class wxNotificationMessageDialog : public wxDialog +class wxNotificationMessageWindow : public wxFrame { public: - wxNotificationMessageDialog(wxWindow *parent, - const wxString& text, - int timeout, - int flags); + wxNotificationMessageWindow(wxGenericNotificationMessageImpl* notificationImpl); - void Set(wxWindow *parent, - const wxString& text, - int timeout, - int flags); + virtual ~wxNotificationMessageWindow(); - bool IsAutomatic() const { return m_timer.IsRunning(); } - void SetDeleteOnHide() { m_deleteOnHide = true; } + void Set(int timeout); + + bool Hide(); + + void SetMessageTitle(const wxString& title); + + void SetMessage(const wxString& message); + + void SetMessageIcon(const wxIcon& icon); + + bool AddAction(wxWindowID actionid, const wxString &label); private: void OnClose(wxCloseEvent& event); void OnTimer(wxTimerEvent& event); + void OnNotificationClicked(wxMouseEvent& event); + void OnNotificationMouseEnter(wxMouseEvent& event); + void OnNotificationMouseLeave(wxMouseEvent& event); + void OnCloseClicked(wxCommandEvent& event); + void OnActionButtonClicked(wxCommandEvent& event); - // if true, delete the dialog when it should disappear, otherwise just hide - // it (initially false) - bool m_deleteOnHide; + // Dialog elements + wxPanel* m_messagePanel; + wxStaticBitmap* m_messageBmp; + wxStaticText* m_messageText; + wxStaticText* m_messageTitle; + wxBitmapButton* m_closeBtn; + wxBoxSizer* m_buttonSizer; - // timer which will hide this dialog when it expires, if it's not running - // it means we were created without timeout wxTimer m_timer; + int m_timeout; + long m_timeoutTargetTime; + int m_mouseActiveCount; + wxGenericNotificationMessageImpl* m_notificationImpl; + + void PrepareNotificationControl(wxWindow* ctrl, bool handleClick = true); + + static wxPoint ms_presentationPos; + + static int ms_presentationDirection; + + static wxVector ms_visibleNotifications; + + static void AddVisibleNotification(wxNotificationMessageWindow* notif); + + static void RemoveVisibleNotification(wxNotificationMessageWindow* notif); + + static void ResizeAndFitVisibleNotifications(); wxDECLARE_EVENT_TABLE(); - wxDECLARE_NO_COPY_CLASS(wxNotificationMessageDialog); + wxDECLARE_NO_COPY_CLASS(wxNotificationMessageWindow); }; +int wxNotificationMessageWindow::ms_presentationDirection = 0; +wxPoint wxNotificationMessageWindow::ms_presentationPos = wxDefaultPosition; + // ============================================================================ -// wxNotificationMessageDialog implementation +// wxNotificationMessageWindow implementation // ============================================================================ -wxBEGIN_EVENT_TABLE(wxNotificationMessageDialog, wxDialog) - EVT_CLOSE(wxNotificationMessageDialog::OnClose) +wxBEGIN_EVENT_TABLE(wxNotificationMessageWindow, wxFrame) + EVT_CLOSE(wxNotificationMessageWindow::OnClose) - EVT_TIMER(wxID_ANY, wxNotificationMessageDialog::OnTimer) + EVT_TIMER(wxID_ANY, wxNotificationMessageWindow::OnTimer) wxEND_EVENT_TABLE() -wxNotificationMessageDialog::wxNotificationMessageDialog(wxWindow *parent, - const wxString& text, - int timeout, - int flags) - : wxDialog(parent, wxID_ANY, _("Notice"), - wxDefaultPosition, wxDefaultSize, - 0 /* no caption, no border styles */), - m_timer(this) -{ - m_deleteOnHide = false; +wxVector wxNotificationMessageWindow::ms_visibleNotifications; - Set(parent, text, timeout, flags); +wxNotificationMessageWindow::wxNotificationMessageWindow(wxGenericNotificationMessageImpl* notificationImpl) + : wxFrame(NULL, wxID_ANY, _("Notice"), + wxDefaultPosition, wxDefaultSize, + wxBORDER_NONE | wxFRAME_TOOL_WINDOW | wxSTAY_ON_TOP /* no caption, no border styles */), + m_timer(this), + m_mouseActiveCount(0), + m_notificationImpl(notificationImpl) +{ + m_buttonSizer = NULL; + + SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW)); + + m_messagePanel = new wxPanel(this, wxID_ANY); + wxSizer * const msgSizer = new wxBoxSizer(wxHORIZONTAL); + m_messagePanel->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); + m_messagePanel->SetSizer(msgSizer); + PrepareNotificationControl(m_messagePanel); + + // Add message icon to layout + m_messageBmp = new wxStaticBitmap + ( + m_messagePanel, + wxID_ANY, + wxArtProvider::GetMessageBoxIcon(wxICON_INFORMATION) + ); + m_messageBmp->Hide(); + PrepareNotificationControl(m_messageBmp); + msgSizer->Add(m_messageBmp, wxSizerFlags().Centre().DoubleBorder()); + + // Create title and message sizers + wxSizer* textSizer = new wxBoxSizer(wxVERTICAL); + + m_messageTitle = new wxStaticText(m_messagePanel, wxID_ANY, wxString()); + m_messageTitle->SetFont(m_messageTitle->GetFont().MakeBold()); + textSizer->Add(m_messageTitle, wxSizerFlags(0).Border()); + m_messageTitle->Hide(); + PrepareNotificationControl(m_messageTitle); + + m_messageText = new wxStaticText(m_messagePanel, wxID_ANY, wxString()); + textSizer->Add(m_messageText, wxSizerFlags(0).Border(wxLEFT | wxRIGHT | wxBOTTOM)); + PrepareNotificationControl(m_messageText); + + msgSizer->Add(textSizer, wxSizerFlags(1).Center()); + + // Add a single close button if no actions are specified + m_closeBtn = wxBitmapButton::NewCloseButton(m_messagePanel, wxID_ANY); + msgSizer->Add(m_closeBtn, wxSizerFlags(0).Border(wxALL, 3).Top()); + m_closeBtn->Bind(wxEVT_BUTTON, &wxNotificationMessageWindow::OnCloseClicked, this); + PrepareNotificationControl(m_closeBtn, false); + + wxSizer * const sizerTop = new wxBoxSizer(wxHORIZONTAL); + sizerTop->Add(m_messagePanel, wxSizerFlags().Border(wxALL, FromDIP(1))); + SetSizer(sizerTop); } -void -wxNotificationMessageDialog::Set(wxWindow * WXUNUSED(parent), - const wxString& text, - int timeout, - int flags) +wxNotificationMessageWindow::~wxNotificationMessageWindow() { - wxSizer * const sizerTop = new wxBoxSizer(wxHORIZONTAL); - if ( flags & wxICON_MASK ) + RemoveVisibleNotification(this); +} + +void wxNotificationMessageWindow::PrepareNotificationControl(wxWindow* ctrl, bool handleClick) +{ + ctrl->Bind(wxEVT_ENTER_WINDOW, &wxNotificationMessageWindow::OnNotificationMouseEnter, this); + ctrl->Bind(wxEVT_LEAVE_WINDOW, &wxNotificationMessageWindow::OnNotificationMouseLeave, this); + + if ( handleClick ) + ctrl->Bind(wxEVT_LEFT_DOWN, &wxNotificationMessageWindow::OnNotificationClicked, this); +} + +void wxNotificationMessageWindow::SetMessageTitle(const wxString& title) +{ + m_messageTitle->SetLabelText(title); + m_messageTitle->Show(!title.empty()); +} + +void wxNotificationMessageWindow::SetMessage(const wxString& message) +{ + m_messageText->SetLabelText(message); + m_messageText->Show(!message.empty()); +} + +void wxNotificationMessageWindow::SetMessageIcon(const wxIcon& icon) +{ + m_messageBmp->SetBitmap(icon); + m_messageBmp->Show(icon.IsOk()); +} + +bool wxNotificationMessageWindow::AddAction(wxWindowID actionid, const wxString &label) +{ + wxSizer* msgSizer = m_messagePanel->GetSizer(); + if ( m_buttonSizer == NULL ) { - sizerTop->Add(new wxStaticBitmap - ( - this, - wxID_ANY, - wxArtProvider::GetMessageBoxIcon(flags) - ), - wxSizerFlags().Centre().Border()); + msgSizer->Detach(m_closeBtn); + m_closeBtn->Hide(); + m_buttonSizer = new wxBoxSizer(wxVERTICAL); + msgSizer->Add(m_buttonSizer, wxSizerFlags(0).Center().Border()); } - sizerTop->Add(CreateTextSizer(text), wxSizerFlags(1).Border()); - SetSizerAndFit(sizerTop); + wxButton* actionButton = new wxButton(m_messagePanel, actionid, label); + actionButton->Bind(wxEVT_BUTTON, &wxNotificationMessageWindow::OnActionButtonClicked, this); + PrepareNotificationControl(actionButton, false); + int borderDir = (m_buttonSizer->GetChildren().empty()) ? 0 : wxTOP; + m_buttonSizer->Add(actionButton, wxSizerFlags(0).Border(borderDir).Expand()); + + return true; +} + + +bool wxNotificationMessageWindow::Hide() +{ + if ( m_timer.IsRunning() ) + m_timer.Stop(); + + RemoveVisibleNotification(this); + return wxFrame::HideWithEffect(wxSHOW_EFFECT_BLEND); +} + +void wxNotificationMessageWindow::Set(int timeout) +{ + Layout(); + Fit(); + + AddVisibleNotification(this); if ( timeout != wxGenericNotificationMessage::Timeout_Never ) { // wxTimer uses ms, timeout is in seconds - m_timer.Start(timeout*1000, true /* one shot only */); + m_timer.Start(500); + m_timeout = timeout; + m_timeoutTargetTime = wxGetUTCTime() + timeout; } else if ( m_timer.IsRunning() ) { @@ -135,102 +265,263 @@ wxNotificationMessageDialog::Set(wxWindow * WXUNUSED(parent), } } -void wxNotificationMessageDialog::OnClose(wxCloseEvent& event) +void wxNotificationMessageWindow::OnClose(wxCloseEvent& WXUNUSED(event)) { - if ( m_deleteOnHide ) - { - // we don't need to keep this dialog alive any more - Destroy(); - } - else // don't really close, just hide, as we can be shown again later - { - event.Veto(); + wxCommandEvent evt(wxEVT_NOTIFICATION_MESSAGE_DISMISSED); + m_notificationImpl->ProcessNotificationEvent(evt); - Hide(); + if ( m_timer.IsRunning() ) + m_timer.Stop(); + + m_notificationImpl->Close(); +} + +void wxNotificationMessageWindow::OnTimer(wxTimerEvent& WXUNUSED(event)) +{ + if ( m_mouseActiveCount > 0 ) + { + m_timeoutTargetTime = wxGetUTCTime() + m_timeout; + } + else if ( m_timeoutTargetTime != -1 && + wxGetUTCTime() >= m_timeoutTargetTime ) + { + m_notificationImpl->Close(); } } -void wxNotificationMessageDialog::OnTimer(wxTimerEvent& WXUNUSED(event)) +void wxNotificationMessageWindow::OnNotificationClicked(wxMouseEvent& WXUNUSED(event)) { - if ( m_deleteOnHide ) - Destroy(); - else - Hide(); + wxCommandEvent evt(wxEVT_NOTIFICATION_MESSAGE_CLICK); + m_notificationImpl->ProcessNotificationEvent(evt); + + m_notificationImpl->Close(); +} + +void wxNotificationMessageWindow::OnNotificationMouseEnter(wxMouseEvent& WXUNUSED(event)) +{ + m_mouseActiveCount++; +} + +void wxNotificationMessageWindow::OnNotificationMouseLeave(wxMouseEvent& WXUNUSED(event)) +{ + m_mouseActiveCount--; +} + +void wxNotificationMessageWindow::OnCloseClicked(wxCommandEvent& WXUNUSED(event)) +{ + wxCommandEvent evt(wxEVT_NOTIFICATION_MESSAGE_DISMISSED); + m_notificationImpl->ProcessNotificationEvent(evt); + + m_notificationImpl->Close(); +} + +void wxNotificationMessageWindow::OnActionButtonClicked(wxCommandEvent& event) +{ + wxCommandEvent evt(wxEVT_NOTIFICATION_MESSAGE_ACTION, event.GetId()); + m_notificationImpl->ProcessNotificationEvent(evt); + + m_notificationImpl->Close(); +} + +void wxNotificationMessageWindow::AddVisibleNotification(wxNotificationMessageWindow* notif) +{ + bool found = false; + for ( wxVector::iterator it = ms_visibleNotifications.begin(); + it != ms_visibleNotifications.end(); it++ ) + { + if ( *it == notif ) + { + found = true; + break; + } + } + + if ( !found ) + ms_visibleNotifications.push_back(notif); + + ResizeAndFitVisibleNotifications(); +} + +void wxNotificationMessageWindow::RemoveVisibleNotification(wxNotificationMessageWindow* notif) +{ + for ( wxVector::iterator it = ms_visibleNotifications.begin(); + it != ms_visibleNotifications.end(); it++ ) + { + if ( *it == notif ) + { + ms_visibleNotifications.erase(it); + break; + } + } + ResizeAndFitVisibleNotifications(); +} + +void wxNotificationMessageWindow::ResizeAndFitVisibleNotifications() +{ + if ( ms_presentationDirection == 0 ) + { + // Determine presentation position + + wxDisplay display; + wxRect clientArea = display.GetClientArea(); + wxRect geom = display.GetGeometry(); + if ( clientArea.y > 0 ) // Taskbar is at top + { + ms_presentationDirection = 1; + ms_presentationPos = clientArea.GetTopRight(); + } + else if ( clientArea.GetHeight() != geom.GetHeight() ) // Taskbar at bottom + { + ms_presentationDirection = -1; + ms_presentationPos = clientArea.GetBottomRight(); + } + else // Default to upper right screen corner with some padding + { + ms_presentationDirection = 1; + ms_presentationPos.x = geom.GetWidth() - 30; + ms_presentationPos.y = 30; + } + } + + int maxWidth = -1; + + // Determine max width + for (wxVector::iterator notif = ms_visibleNotifications.begin(); + notif != ms_visibleNotifications.end(); ++notif) + { + wxSize notifSize = (*notif)->GetSize(); + if ( notifSize.GetWidth() > maxWidth ) + maxWidth = notifSize.GetWidth(); + } + + int notifPadding = 2; + + wxPoint presentPos = ms_presentationPos; + presentPos.x -= notifPadding + maxWidth; + + int prevNotifHeight = 0; + + for (wxVector::iterator notif = ms_visibleNotifications.begin(); + notif != ms_visibleNotifications.end(); ++notif) + { + // Modify existing maxwidth + wxSize notifSize = (*notif)->GetSize(); + if ( notifSize.GetWidth() < maxWidth ) + { + notifSize.SetWidth(maxWidth); + (*notif)->SetSize(notifSize); + (*notif)->Layout(); + } + + if ( ms_presentationDirection > 0 ) + { + presentPos.y += (notifPadding + prevNotifHeight); + prevNotifHeight = notifSize.GetHeight(); + } + else + { + presentPos.y -= (notifPadding + notifSize.GetHeight()); + } + + (*notif)->SetPosition(presentPos); + } } // ============================================================================ // wxGenericNotificationMessage implementation // ============================================================================ -int wxGenericNotificationMessage::ms_timeout = 10; - /* static */ void wxGenericNotificationMessage::SetDefaultTimeout(int timeout) { - wxASSERT_MSG( timeout > 0, - "negative or zero default timeout doesn't make sense" ); - - ms_timeout = timeout; + wxGenericNotificationMessageImpl::SetDefaultTimeout(timeout); } void wxGenericNotificationMessage::Init() { - m_dialog = NULL; + m_impl = new wxGenericNotificationMessageImpl(this); } -wxGenericNotificationMessage::~wxGenericNotificationMessage() +// ---------------------------------------------------------------------------- +// wxGenericNotificationMessageImpl +// ---------------------------------------------------------------------------- + +int wxGenericNotificationMessageImpl::ms_timeout = 3; + +wxGenericNotificationMessageImpl::wxGenericNotificationMessageImpl(wxNotificationMessageBase* notification) : + wxNotificationMessageImpl(notification) { - if ( m_dialog->IsAutomatic() ) - { - // we want to allow the user to create an automatically hidden - // notification just by creating a local wxGenericNotificationMessage object - // and so we shouldn't hide the notification when this object goes out - // of scope - m_dialog->SetDeleteOnHide(); - } - else // manual dialog, hide it immediately - { - // OTOH for permanently shown dialogs only the code can hide them and - // if the object is deleted, we must do it now as it won't be - // accessible programmatically any more - delete m_dialog; - } + m_window = new wxNotificationMessageWindow(this); } -bool wxGenericNotificationMessage::Show(int timeout) +wxGenericNotificationMessageImpl::~wxGenericNotificationMessageImpl() { - if ( timeout == Timeout_Auto ) + m_window->Destroy(); +} + +/* static */ void wxGenericNotificationMessageImpl::SetDefaultTimeout(int timeout) +{ + wxASSERT_MSG(timeout > 0, + "negative or zero default timeout doesn't make sense"); + + ms_timeout = timeout; +} + +bool wxGenericNotificationMessageImpl::Show(int timeout) +{ + if ( timeout == wxNotificationMessageBase::Timeout_Auto ) { timeout = GetDefaultTimeout(); } - if ( !m_dialog ) - { - m_dialog = new wxNotificationMessageDialog - ( - GetParent(), - GetFullMessage(), - timeout, - GetFlags() - ); - } - else // update the existing dialog - { - m_dialog->Set(GetParent(), GetFullMessage(), timeout, GetFlags()); - } + SetActive(true); + m_window->Set(timeout); - m_dialog->Show(); + m_window->ShowWithEffect(wxSHOW_EFFECT_BLEND); return true; } -bool wxGenericNotificationMessage::Close() +bool wxGenericNotificationMessageImpl::Close() { - if ( !m_dialog ) + if ( !m_window ) return false; - m_dialog->Hide(); + m_window->Hide(); + + SetActive(false); return true; } +void wxGenericNotificationMessageImpl::SetTitle(const wxString& title) +{ + m_window->SetMessageTitle(title); +} + +void wxGenericNotificationMessageImpl::SetMessage(const wxString& message) +{ + m_window->SetMessage(message); +} + +void wxGenericNotificationMessageImpl::SetParent(wxWindow *WXUNUSED(parent)) +{ + +} + +void wxGenericNotificationMessageImpl::SetFlags(int flags) +{ + m_window->SetMessageIcon( wxArtProvider::GetMessageBoxIcon(flags) ); +} + +void wxGenericNotificationMessageImpl::SetIcon(const wxIcon& icon) +{ + m_window->SetMessageIcon(icon); +} + +bool wxGenericNotificationMessageImpl::AddAction(wxWindowID actionid, const wxString &label) +{ + return m_window->AddAction(actionid, label); +} + + #endif // wxUSE_NOTIFICATION_MESSAGE diff --git a/src/gtk/notifmsg.cpp b/src/gtk/notifmsg.cpp index 63670ee2a5..6f59041ad9 100644 --- a/src/gtk/notifmsg.cpp +++ b/src/gtk/notifmsg.cpp @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////////// -// Name: src/gtk/notifmsg.cpp -// Purpose: wxNotificationMessage for wxGTK using libnotify. -// Author: Vadim Zeitlin -// Created: 2012-07-25 -// Copyright: (c) 2012 Vadim Zeitlin -// Licence: wxWindows licence +// Name: src/gtk/notifmsg.cpp +// Purpose: wxNotificationMessage for wxGTK using libnotify. +// Author: Vadim Zeitlin +// Created: 2012-07-25 +// Copyright: (c) 2012 Vadim Zeitlin +// Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// // ============================================================================ @@ -28,11 +28,14 @@ #ifndef WX_PRECOMP #include "wx/app.h" + #include "wx/icon.h" #endif // WX_PRECOMP #include #include "wx/module.h" +#include "wx/private/notifmsg.h" +#include // General note about error handling: as notifications are meant to be // non-intrusive, we use wxLogDebug() and not wxLogError() if anything goes @@ -82,136 +85,290 @@ wxIMPLEMENT_DYNAMIC_CLASS(wxLibnotifyModule, wxModule); // wxNotificationMessage implementation // ============================================================================ -bool wxNotificationMessage::GTKSetIconName(const wxString& name) -{ - m_iconName = name; +class wxLibNotifyMsgImpl; - return true; +void wxLibNotifyMsgImplActionCallback(NotifyNotification *notification, + char *action, + gpointer user_data); + +extern "C" { +static gboolean closed_notification(NotifyNotification *notification, + const char* WXUNUSED(data), void* user_data); } -bool wxNotificationMessage::Show(int timeout) +class wxLibNotifyMsgImpl : public wxNotificationMessageImpl { - if ( !wxLibnotifyModule::Initialize() ) - return false; - - // Determine the GTK+ icon to use from flags and also set the urgency - // appropriately. - const char* icon; - NotifyUrgency urgency; - switch ( GetFlags() ) +public: + wxLibNotifyMsgImpl(wxNotificationMessageBase* notification) : + wxNotificationMessageImpl(notification), + m_notification(NULL), + m_flags(wxICON_INFORMATION) { - case wxICON_INFORMATION: - icon = "dialog-information"; - urgency = NOTIFY_URGENCY_LOW; - break; + if ( !wxLibnotifyModule::Initialize() ) + wxLogError(_("Could not initalize libnotify.")); + + } - case wxICON_WARNING: - icon = "dialog-warning"; - urgency = NOTIFY_URGENCY_NORMAL; - break; - - case wxICON_ERROR: - icon = "dialog-error"; - urgency = NOTIFY_URGENCY_CRITICAL; - break; - - default: - wxFAIL_MSG( "Unknown notification message flags." ); + virtual ~wxLibNotifyMsgImpl() + { + if ( m_notification ) + g_object_unref(m_notification); + } + + bool CreateOrUpdateNotification() + { + if ( !wxLibnotifyModule::Initialize() ) return false; - } - // Explicitly specified icon name overrides the implicit one determined by - // the flags. - wxScopedCharBuffer buf; - if ( !m_iconName.empty() ) - { - buf = m_iconName.utf8_str(); - icon = buf; - } + // Determine the GTK+ icon to use from flags and also set the urgency + // appropriately. + const char* icon; + switch ( m_flags ) + { + case wxICON_INFORMATION: + icon = "dialog-information"; + break; - // Create the notification or update an existing one if we had already been - // shown before. - if ( !m_notification ) - { - m_notification = notify_notification_new - ( - GetTitle().utf8_str(), - GetMessage().utf8_str(), - icon -#if !wxUSE_LIBNOTIFY_0_7 - // There used to be an "associated window" - // parameter in this function but it has - // disappeared by 0.7, so use it for previous - // versions only. - , 0 -#endif // libnotify < 0.7 - ); + case wxICON_WARNING: + icon = "dialog-warning"; + break; + + case wxICON_ERROR: + icon = "dialog-error"; + break; + + default: + wxFAIL_MSG( "Unknown notification message flags." ); + return false; + } + + // Create the notification or update an existing one if we had already been + // shown before. if ( !m_notification ) { - wxLogDebug("Failed to creation notification."); + m_notification = notify_notification_new + ( + m_title.utf8_str(), + m_message.utf8_str(), + icon +#if !wxUSE_LIBNOTIFY_0_7 + // There used to be an "associated window" + // parameter in this function but it has + // disappeared by 0.7, so use it for previous + // versions only. + , 0 +#endif // libnotify < 0.7 + ); + if ( !m_notification ) + { + wxLogDebug("Failed to creation notification."); + + return false; + } + + + g_signal_connect(m_notification, "closed", G_CALLBACK(closed_notification), this); + + } + else + { + if ( !notify_notification_update + ( + m_notification, + m_title.utf8_str(), + m_message.utf8_str(), + icon + ) ) + { + wxLogDebug(wxS("notify_notification_update() unexpectedly failed.")); + } + } + + // Explicitly specified icon name overrides the implicit one determined by + // the flags. + if ( m_icon.IsOk() ) + { +#ifdef __WXGTK3__ + notify_notification_set_image_from_pixbuf( + m_notification, + m_icon.GetPixbufNoMask() + ); +#endif + } + + return true; + } + + virtual bool Show(int timeout) wxOVERRIDE + { + if ( !CreateOrUpdateNotification() ) + return false; + + // Set the notification parameters not specified during creation. + notify_notification_set_timeout + ( + m_notification, + timeout == wxNotificationMessage::Timeout_Auto ? NOTIFY_EXPIRES_DEFAULT + : timeout == wxNotificationMessage::Timeout_Never ? NOTIFY_EXPIRES_NEVER + : 1000*timeout + ); + + NotifyUrgency urgency; + switch ( m_flags ) + { + case wxICON_INFORMATION: + urgency = NOTIFY_URGENCY_LOW; + break; + + case wxICON_WARNING: + urgency = NOTIFY_URGENCY_NORMAL; + break; + + case wxICON_ERROR: + urgency = NOTIFY_URGENCY_CRITICAL; + break; + + default: + wxFAIL_MSG( "Unknown notification message flags." ); + return false; + } + notify_notification_set_urgency(m_notification, urgency); + + + // Finally do show the notification. + wxGtkError error; + if ( !notify_notification_show(m_notification, error.Out()) ) + { + wxLogDebug("Failed to shown notification: %s", error.GetMessage()); return false; } + + return true; } - else + + virtual bool Close() wxOVERRIDE { - if ( !notify_notification_update - ( - m_notification, - GetTitle().utf8_str(), - GetMessage().utf8_str(), - icon - ) ) + wxCHECK_MSG( m_notification, false, + wxS("Can't close not shown notification.") ); + + wxGtkError error; + if ( !notify_notification_close(m_notification, error.Out()) ) { - wxLogDebug(wxS("notify_notification_update() unexpectedly failed.")); + wxLogDebug("Failed to hide notification: %s", error.GetMessage()); + + return false; } + + return true; } - - - // Set the notification parameters not specified during creation. - notify_notification_set_timeout - ( - m_notification, - timeout == Timeout_Auto ? NOTIFY_EXPIRES_DEFAULT - : timeout == Timeout_Never ? NOTIFY_EXPIRES_NEVER - : 1000*timeout - ); - - notify_notification_set_urgency(m_notification, urgency); - - - // Finally do show the notification. - wxGtkError error; - if ( !notify_notification_show(m_notification, error.Out()) ) + + virtual void SetTitle(const wxString& title) wxOVERRIDE { - wxLogDebug("Failed to shown notification: %s", error.GetMessage()); - - return false; + m_title = title; } + + virtual void SetMessage(const wxString& message) wxOVERRIDE + { + m_message = message; + } + + virtual void SetParent(wxWindow *WXUNUSED(parent)) wxOVERRIDE + { + } + + virtual void SetFlags(int flags) wxOVERRIDE + { + m_flags = flags; + } + + virtual void SetIcon(const wxIcon& icon) wxOVERRIDE + { + m_icon = icon; + CreateOrUpdateNotification(); + } + + virtual bool AddAction(wxWindowID actionid, const wxString &label) + { + if ( !CreateOrUpdateNotification() ) + return false; + + wxString labelStr = label; + if ( labelStr.empty() ) + labelStr = wxGetStockLabel(actionid, wxSTOCK_NOFLAGS); + + notify_notification_add_action + ( + m_notification, + wxString::Format("%d", actionid).utf8_str(), + labelStr.utf8_str(), + &wxLibNotifyMsgImplActionCallback, + this, + NULL + ); + + return true; + } + + void NotifyClose(int closeReason) + { + // Values according to the OpenDesktop specification at: + // https://developer.gnome.org/notification-spec/ + + switch (closeReason) + { + case 1: // Expired + case 2: // The notification was dismissed by the user. + { + wxCommandEvent evt(wxEVT_NOTIFICATION_MESSAGE_DISMISSED); + ProcessNotificationEvent(evt); + break; + } + } + + } + + void NotifyAction(wxWindowID actionid) + { + wxCommandEvent evt(wxEVT_NOTIFICATION_MESSAGE_ACTION, actionid); + ProcessNotificationEvent(evt); + } + +private: + NotifyNotification* m_notification; + wxString m_title; + wxString m_message; + wxIcon m_icon; + int m_flags; +}; - return true; +void wxLibNotifyMsgImplActionCallback(NotifyNotification *WXUNUSED(notification), + char *action, + gpointer user_data) +{ + wxLibNotifyMsgImpl* impl = (wxLibNotifyMsgImpl*) user_data; + + impl->NotifyAction(wxAtoi(action)); } -bool wxNotificationMessage::Close() +extern "C" { +static gboolean closed_notification(NotifyNotification *notification, + const char* WXUNUSED(data), void* user_data) { - wxCHECK_MSG( m_notification, false, - wxS("Can't close not shown notification.") ); - - wxGtkError error; - if ( !notify_notification_close(m_notification, error.Out()) ) - { - wxLogDebug("Failed to hide notification: %s", error.GetMessage()); - - return false; - } - + wxLibNotifyMsgImpl* impl = (wxLibNotifyMsgImpl*) user_data; + gint closeReason = notify_notification_get_closed_reason(notification); + impl->NotifyClose(closeReason); return true; } +} -wxNotificationMessage::~wxNotificationMessage() +// ---------------------------------------------------------------------------- +// wxNotificationMessage +// ---------------------------------------------------------------------------- + +void wxNotificationMessage::Init() { - if ( m_notification ) - g_object_unref(m_notification); + m_impl = new wxLibNotifyMsgImpl(this); } #endif // wxUSE_NOTIFICATION_MESSAGE && wxUSE_LIBNOTIFY diff --git a/src/msw/notifmsg.cpp b/src/msw/notifmsg.cpp index d25e9ab5fe..b1a91330a0 100644 --- a/src/msw/notifmsg.cpp +++ b/src/msw/notifmsg.cpp @@ -35,7 +35,9 @@ #include "wx/string.h" #endif // WX_PRECOMP +#include "wx/private/notifmsg.h" #include "wx/generic/notifmsg.h" +#include "wx/generic/private/notifmsg.h" #include "wx/taskbar.h" @@ -43,69 +45,62 @@ // different implementations used by wxNotificationMessage // ---------------------------------------------------------------------------- -// base class for all available implementations -class wxNotifMsgImpl -{ -public: - wxNotifMsgImpl() { } - virtual ~wxNotifMsgImpl() { } - - virtual bool DoShow(const wxString& title, - const wxString& message, - int timeout, - int flags) = 0; - virtual bool DoClose() = 0; - -private: - wxDECLARE_NO_COPY_CLASS(wxNotifMsgImpl); -}; - -// implementation which is simply a bridge to wxGenericNotificationMessage -class wxGenericNotifMsgImpl : public wxNotifMsgImpl -{ -public: - wxGenericNotifMsgImpl() : m_notif(new wxGenericNotificationMessage) { } - virtual ~wxGenericNotifMsgImpl() { delete m_notif; } - - virtual bool DoShow(const wxString& title, - const wxString& message, - int timeout, - int flags) - { - m_notif->SetTitle(title); - m_notif->SetMessage(message); - m_notif->SetFlags(flags); - return m_notif->Show(timeout); - } - - virtual bool DoClose() - { - return m_notif->Close(); - } - -private: - wxGenericNotificationMessage * const m_notif; -}; - -// common base class for implementations using a taskbar icon and balloons -class wxBalloonNotifMsgImpl : public wxNotifMsgImpl +// implementations using a taskbar icon and balloons +class wxBalloonNotifMsgImpl : public wxNotificationMessageImpl { public: // Ctor creates the associated taskbar icon (using the icon of the top // level parent of the given window) unless UseTaskBarIcon() had been // previously called which can be used to show an attached balloon later // by the derived classes. - wxBalloonNotifMsgImpl(wxWindow *win) { SetUpIcon(win); } + wxBalloonNotifMsgImpl(wxNotificationMessageBase* notification) : + wxNotificationMessageImpl(notification), + m_flags(0), + m_parent(NULL) + { + + } + + virtual ~wxBalloonNotifMsgImpl(); + + virtual bool Show(int timeout) wxOVERRIDE; + + virtual bool Close() wxOVERRIDE; + + virtual void SetTitle(const wxString& title) wxOVERRIDE + { + m_title = title; + } + + virtual void SetMessage(const wxString& message) wxOVERRIDE + { + m_message = message; + } + + virtual void SetParent(wxWindow *parent) wxOVERRIDE + { + m_parent = parent; + } + + virtual void SetFlags(int flags) wxOVERRIDE + { + m_flags = flags; + } + + virtual void SetIcon(const wxIcon& icon) wxOVERRIDE + { + m_icon = icon; + } + + virtual bool AddAction(wxWindowID WXUNUSED(actionid), const wxString &WXUNUSED(label)) + { + // Actions are not supported in balloon notifications + return false; + } // implementation of wxNotificationMessage method with the same name static wxTaskBarIcon *UseTaskBarIcon(wxTaskBarIcon *icon); - virtual bool DoShow(const wxString& title, - const wxString& message, - int timeout, - int flags); - - // Returns true if we're using our own icon or false if we're hitching a // ride on the application icon provided to us via UseTaskBarIcon(). static bool IsUsingOwnIcon() @@ -124,7 +119,7 @@ public: wxASSERT_MSG( ms_refCountIcon != -1, wxS("Must not be called when not using own icon") ); - if ( !--ms_refCountIcon ) + if ( ms_refCountIcon > 0 && !--ms_refCountIcon ) { delete ms_icon; ms_icon = NULL; @@ -152,117 +147,25 @@ protected: // the icon is only destroyed when it reaches 0. static wxTaskBarIcon *ms_icon; static int ms_refCountIcon; -}; - -// implementation for automatically hidden notifications -class wxAutoNotifMsgImpl : public wxBalloonNotifMsgImpl -{ -public: - wxAutoNotifMsgImpl(wxWindow *win); - - virtual bool DoShow(const wxString& title, - const wxString& message, - int timeout, - int flags); - - // can't close automatic notification [currently] - virtual bool DoClose() { return false; } -}; - -// implementation for manually closed notifications -class wxManualNotifMsgImpl : public wxBalloonNotifMsgImpl -{ -public: - wxManualNotifMsgImpl(wxWindow *win); - virtual ~wxManualNotifMsgImpl(); - - virtual bool DoShow(const wxString& title, - const wxString& message, - int timeout, - int flags); - virtual bool DoClose(); - private: - // store ctor parameter as we need it to recreate the icon later if we're - // closed and shown again - wxWindow * const m_win; -}; + wxString m_title; + wxString m_message; + int m_flags; + wxIcon m_icon; + wxWindow* m_parent; -// ---------------------------------------------------------------------------- -// custom event handler for task bar icons -// ---------------------------------------------------------------------------- - -// normally we'd just use a custom taskbar icon class but this is impossible -// because we can be asked to attach the notifications to an existing icon -// which we didn't create, hence we install a special event handler allowing us -// to get the events we need (and, crucially, to delete the icon when it's not -// needed any more) in any case - -class wxNotificationIconEvtHandler : public wxEvtHandler -{ -public: - wxNotificationIconEvtHandler(wxTaskBarIcon *icon); - -private: void OnTimeout(wxTaskBarIconEvent& event); void OnClick(wxTaskBarIconEvent& event); void OnIconHidden(); - - - wxTaskBarIcon * const m_icon; - - wxDECLARE_NO_COPY_CLASS(wxNotificationIconEvtHandler); }; +// ---------------------------------------------------------------------------- + // ============================================================================ // implementation // ============================================================================ -// ---------------------------------------------------------------------------- -// wxNotificationIconEvtHandler -// ---------------------------------------------------------------------------- - -wxNotificationIconEvtHandler::wxNotificationIconEvtHandler(wxTaskBarIcon *icon) - : m_icon(icon) -{ - m_icon->Connect - ( - wxEVT_TASKBAR_BALLOON_TIMEOUT, - wxTaskBarIconEventHandler(wxNotificationIconEvtHandler::OnTimeout), - NULL, - this - ); - - m_icon->Connect - ( - wxEVT_TASKBAR_BALLOON_CLICK, - wxTaskBarIconEventHandler(wxNotificationIconEvtHandler::OnClick), - NULL, - this - ); -} - -void wxNotificationIconEvtHandler::OnIconHidden() -{ - wxBalloonNotifMsgImpl::ReleaseIcon(); - - delete this; -} - -void -wxNotificationIconEvtHandler::OnTimeout(wxTaskBarIconEvent& WXUNUSED(event)) -{ - OnIconHidden(); -} - -void wxNotificationIconEvtHandler::OnClick(wxTaskBarIconEvent& WXUNUSED(event)) -{ - // TODO: generate an event notifying the user code? - - OnIconHidden(); -} - // ---------------------------------------------------------------------------- // wxBalloonNotifMsgImpl // ---------------------------------------------------------------------------- @@ -282,6 +185,39 @@ wxTaskBarIcon *wxBalloonNotifMsgImpl::UseTaskBarIcon(wxTaskBarIcon *icon) return iconOld; } +wxBalloonNotifMsgImpl::~wxBalloonNotifMsgImpl() +{ +} + +void wxBalloonNotifMsgImpl::OnIconHidden() +{ + SetActive(false); + if ( ms_icon ) + { + ms_icon->Unbind(wxEVT_TASKBAR_BALLOON_CLICK, &wxBalloonNotifMsgImpl::OnClick, this); + ms_icon->Unbind(wxEVT_TASKBAR_BALLOON_TIMEOUT, &wxBalloonNotifMsgImpl::OnTimeout, this); + } + + if ( IsUsingOwnIcon() ) + wxBalloonNotifMsgImpl::ReleaseIcon(); +} + +void wxBalloonNotifMsgImpl::OnTimeout(wxTaskBarIconEvent& WXUNUSED(event)) +{ + wxCommandEvent evt(wxEVT_NOTIFICATION_MESSAGE_DISMISSED); + ProcessNotificationEvent(evt); + + OnIconHidden(); +} + +void wxBalloonNotifMsgImpl::OnClick(wxTaskBarIconEvent& WXUNUSED(event)) +{ + wxCommandEvent evt(wxEVT_NOTIFICATION_MESSAGE_CLICK); + ProcessNotificationEvent(evt); + + OnIconHidden(); +} + void wxBalloonNotifMsgImpl::SetUpIcon(wxWindow *win) { if ( ms_icon ) @@ -322,12 +258,15 @@ void wxBalloonNotifMsgImpl::SetUpIcon(wxWindow *win) } } -bool -wxBalloonNotifMsgImpl::DoShow(const wxString& title, - const wxString& message, - int timeout, - int flags) +bool +wxBalloonNotifMsgImpl::Show(int timeout) { + // timout active event + wxTaskBarIconEvent event(wxEVT_TASKBAR_BALLOON_TIMEOUT, ms_icon); + OnTimeout(event); + + SetUpIcon(m_parent); + if ( !ms_icon->IsIconInstalled() ) { // If we failed to install the icon (which does happen sometimes, @@ -346,54 +285,40 @@ wxBalloonNotifMsgImpl::DoShow(const wxString& title, return false; } + // Since Windows Vista timeout is ignored so this values are only for XP + if ( timeout == wxNotificationMessage::Timeout_Auto ) + { + // choose a value more or less in the middle of the allowed range + timeout = 1; + } + else if ( timeout == wxNotificationMessage::Timeout_Never ) + { + // use maximal (in Windows XP) timeout (but it will still + // disappear on its own) + timeout = 30; + } + timeout *= 1000; // Windows expresses timeout in milliseconds - return ms_icon->ShowBalloon(title, message, timeout, flags); -} - -// ---------------------------------------------------------------------------- -// wxManualNotifMsgImpl -// ---------------------------------------------------------------------------- - -wxManualNotifMsgImpl::wxManualNotifMsgImpl(wxWindow *win) - : wxBalloonNotifMsgImpl(win), - m_win(win) -{ -} - -wxManualNotifMsgImpl::~wxManualNotifMsgImpl() -{ - if ( ms_icon ) - DoClose(); -} - -bool -wxManualNotifMsgImpl::DoShow(const wxString& title, - const wxString& message, - int WXUNUSED_UNLESS_DEBUG(timeout), - int flags) -{ - wxASSERT_MSG( timeout == wxNotificationMessage::Timeout_Never, - wxT("shouldn't be used") ); - - // base class creates the icon for us initially but we could have destroyed - // it in DoClose(), recreate it if this was the case - if ( !ms_icon ) - SetUpIcon(m_win); - - // use maximal (in current Windows versions) timeout (but it will still - // disappear on its own) - return wxBalloonNotifMsgImpl::DoShow(title, message, 30, flags); -} - -bool wxManualNotifMsgImpl::DoClose() -{ - if ( IsUsingOwnIcon() ) + bool res = ms_icon->ShowBalloon(m_title, m_message, timeout, m_flags, m_icon); + if ( res ) { - // we don't need the icon any more - ReleaseIcon(); + ms_icon->Bind(wxEVT_TASKBAR_BALLOON_CLICK, &wxBalloonNotifMsgImpl::OnClick, this); + ms_icon->Bind(wxEVT_TASKBAR_BALLOON_TIMEOUT, &wxBalloonNotifMsgImpl::OnTimeout, this); + SetActive(true); } - else // using an existing icon + + return res; +} + +bool wxBalloonNotifMsgImpl::Close() +{ + wxCommandEvent evt(wxEVT_NOTIFICATION_MESSAGE_DISMISSED); + ProcessNotificationEvent(evt); + + OnIconHidden(); + + if ( !IsUsingOwnIcon() && ms_icon ) { // just hide the balloon ms_icon->ShowBalloon("", ""); @@ -402,84 +327,19 @@ bool wxManualNotifMsgImpl::DoClose() return true; } -// ---------------------------------------------------------------------------- -// wxAutoNotifMsgImpl -// ---------------------------------------------------------------------------- - -wxAutoNotifMsgImpl::wxAutoNotifMsgImpl(wxWindow *win) - : wxBalloonNotifMsgImpl(win) -{ - if ( ms_refCountIcon != -1 ) - { - // This object will self-destruct and decrease the ref count of the - // icon when the notification is hidden. - new wxNotificationIconEvtHandler(ms_icon); - } -} - -bool -wxAutoNotifMsgImpl::DoShow(const wxString& title, - const wxString& message, - int timeout, - int flags) -{ - wxASSERT_MSG( timeout != wxNotificationMessage::Timeout_Never, - wxT("shouldn't be used") ); - - if ( timeout == wxNotificationMessage::Timeout_Auto ) - { - // choose a value more or less in the middle of the allowed range - timeout = 1; - } - - return wxBalloonNotifMsgImpl::DoShow(title, message, timeout, flags); -} - // ---------------------------------------------------------------------------- // wxNotificationMessage // ---------------------------------------------------------------------------- -/* static */ -bool wxNotificationMessage::ms_alwaysUseGeneric = false; - /* static */ wxTaskBarIcon *wxNotificationMessage::UseTaskBarIcon(wxTaskBarIcon *icon) { return wxBalloonNotifMsgImpl::UseTaskBarIcon(icon); } -bool wxNotificationMessage::Show(int timeout) +void wxNotificationMessage::Init() { - if ( !m_impl ) - { - if ( !ms_alwaysUseGeneric ) - { - if ( timeout == Timeout_Never ) - m_impl = new wxManualNotifMsgImpl(GetParent()); - else - m_impl = new wxAutoNotifMsgImpl(GetParent()); - } - else // no support for balloon tooltips - { - m_impl = new wxGenericNotifMsgImpl; - } - } - //else: reuse the same implementation for the subsequent calls, it would - // be too confusing if it changed - - return m_impl->DoShow(GetTitle(), GetMessage(), timeout, GetFlags()); -} - -bool wxNotificationMessage::Close() -{ - wxCHECK_MSG( m_impl, false, "must show the notification first" ); - - return m_impl->DoClose(); -} - -wxNotificationMessage::~wxNotificationMessage() -{ - delete m_impl; + m_impl = new wxBalloonNotifMsgImpl(this); } #endif // wxUSE_NOTIFICATION_MESSAGE && wxUSE_TASKBARICON diff --git a/src/msw/taskbar.cpp b/src/msw/taskbar.cpp index a09cff9964..5d4e066993 100644 --- a/src/msw/taskbar.cpp +++ b/src/msw/taskbar.cpp @@ -30,6 +30,7 @@ #include #include "wx/taskbar.h" +#include "wx/platinfo.h" #include "wx/msw/private.h" #ifndef NIN_BALLOONTIMEOUT @@ -109,13 +110,12 @@ struct NotifyIconData : public NOTIFYICONDATA { memset(this, 0, sizeof(NOTIFYICONDATA)); - // Do _not_ use sizeof(NOTIFYICONDATA) here, it may be too big if we're - // compiled with newer headers but running on an older system and while - // we could do complicated tests for the exact system version it's - // easier to just use an old size which should be supported everywhere - // from Windows 2000 up and which is all we need as we don't use any - // newer features so far. - cbSize = NOTIFYICONDATA_V2_SIZE; + // Since Vista there is a new member hBalloonIcon which will be used + // if a user specified icon is specified in ShowBalloon(). For XP + // use the old size + cbSize = wxPlatformInfo::Get().CheckOSVersion(6, 0) + ? sizeof(NOTIFYICONDATA) + : NOTIFYICONDATA_V2_SIZE; hWnd = (HWND) hwnd; uCallbackMessage = gs_msgTaskbar; @@ -203,7 +203,8 @@ bool wxTaskBarIcon::ShowBalloon(const wxString& title, const wxString& text, unsigned msec, - int flags) + int flags, + const wxIcon& icon) { wxCHECK_MSG( m_iconAdded, false, wxT("can't be used before the icon is created") ); @@ -229,6 +230,15 @@ wxTaskBarIcon::ShowBalloon(const wxString& title, wxStrlcpy(notifyData.szInfoTitle, title.t_str(), WXSIZEOF(notifyData.szInfoTitle)); +#ifdef NIIF_LARGE_ICON + // User specified icon is only supported since Vista + if ( icon.IsOk() && wxPlatformInfo::Get().CheckOSVersion(6, 0) ) + { + notifyData.hBalloonIcon = GetHiconOf(icon); + notifyData.dwInfoFlags |= NIIF_USER | NIIF_LARGE_ICON; + } + else +#endif if ( flags & wxICON_INFORMATION ) notifyData.dwInfoFlags |= NIIF_INFO; else if ( flags & wxICON_WARNING ) diff --git a/src/osx/cocoa/notifmsg.mm b/src/osx/cocoa/notifmsg.mm new file mode 100644 index 0000000000..692efdaa4b --- /dev/null +++ b/src/osx/cocoa/notifmsg.mm @@ -0,0 +1,254 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: src/osx/notifmsg.cpp +// Purpose: implementation of wxNotificationMessage for OSX +// Author: Tobias Taschner +// Created: 2015-08-06 +// Copyright: (c) 2015 wxWidgets development team +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +// for compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#include "wx/notifmsg.h" + +#if wxUSE_NOTIFICATION_MESSAGE && defined(wxHAS_NATIVE_NOTIFICATION_MESSAGE) + +#ifndef WX_PRECOMP + #include "wx/string.h" +#endif // WX_PRECOMP + +#include "wx/osx/private.h" +#include "wx/generic/notifmsg.h" +#include "wx/private/notifmsg.h" +#include "wx/generic/private/notifmsg.h" +#include "wx/timer.h" +#include "wx/platinfo.h" +#include "wx/artprov.h" +#include "wx/vector.h" +#include "wx/stockitem.h" + +#include "wx/utils.h" +#include + +@interface wxUserNotificationHandler : NSObject + +@end + +// ---------------------------------------------------------------------------- +// wxUserNotificationMsgImpl +// ---------------------------------------------------------------------------- + +class wxUserNotificationMsgImpl : public wxNotificationMessageImpl +{ +public: + wxUserNotificationMsgImpl(wxNotificationMessageBase* notification) : + wxNotificationMessageImpl(notification) + { + UseHandler(); + m_notif = [[NSUserNotification alloc] init]; + + // Build Id to unqiuely idendify this notification + m_id = wxString::Format("%d_%d", (int)wxGetProcessId(), ms_notifIdBase++); + + // Register the notification + ms_activeNotifications[m_id] = this; + + wxCFStringRef cfId(m_id); + m_notif.userInfo = @{ + @"wxId" : cfId.AsNSString() + }; + } + + virtual ~wxUserNotificationMsgImpl() + { + ms_activeNotifications[m_id] = NULL; + ReleaseHandler(); + [m_notif release]; + } + + virtual bool Show(int WXUNUSED(timeout)) wxOVERRIDE + { + NSUserNotificationCenter* nc = [NSUserNotificationCenter defaultUserNotificationCenter]; + [nc deliverNotification:m_notif]; + + return true; + } + + virtual bool Close() wxOVERRIDE + { + NSUserNotificationCenter* nc = [NSUserNotificationCenter defaultUserNotificationCenter]; + [nc removeDeliveredNotification:m_notif]; + + return true; + } + + virtual void SetTitle(const wxString& title) wxOVERRIDE + { + wxCFStringRef cftitle(title); + m_notif.title = cftitle.AsNSString(); + } + + virtual void SetMessage(const wxString& message) wxOVERRIDE + { + wxCFStringRef cfmsg(message); + m_notif.informativeText = cfmsg.AsNSString(); + } + + virtual void SetParent(wxWindow *WXUNUSED(parent)) wxOVERRIDE + { + } + + virtual void SetFlags(int WXUNUSED(flags)) wxOVERRIDE + { + // On OS X we do not add an icon based on the flags, + // as this is primarily meant for custom icons + } + + virtual void SetIcon(const wxIcon& icon) wxOVERRIDE + { + // Additional icon in the notification is only supported on OS X 10.9+ + if ([NSUserNotification instancesRespondToSelector:@selector(setContentImage:)]) + m_notif.contentImage = icon.GetNSImage(); + } + + virtual bool AddAction(wxWindowID actionid, const wxString &label) + { + if (m_actions.size() >= 1) // Currently only 1 actions are supported + return false; + + wxString strLabel = label; + if (strLabel.empty()) + strLabel = wxGetStockLabel(actionid, wxSTOCK_NOFLAGS); + wxCFStringRef cflabel(strLabel); + + m_actions.push_back(actionid); + + if (m_actions.size() == 1) + m_notif.actionButtonTitle = cflabel.AsNSString(); + + return true; + } + + void Activated(NSUserNotificationActivationType activationType) + { + switch (activationType) + { + case NSUserNotificationActivationTypeNone: + { + wxCommandEvent evt(wxEVT_NOTIFICATION_MESSAGE_DISMISSED); + ProcessNotificationEvent(evt); + break; + } + case NSUserNotificationActivationTypeContentsClicked: + { + wxCommandEvent evt(wxEVT_NOTIFICATION_MESSAGE_CLICK); + ProcessNotificationEvent(evt); + Close(); + break; + } + case NSUserNotificationActivationTypeActionButtonClicked: + { + if (m_actions.empty()) + { + // Without actions the action button is handled as a message click + wxCommandEvent evt(wxEVT_NOTIFICATION_MESSAGE_CLICK); + ProcessNotificationEvent(evt); + } + else + { + wxCommandEvent evt(wxEVT_NOTIFICATION_MESSAGE_ACTION); + evt.SetId(m_actions[0]); + ProcessNotificationEvent(evt); + } + Close(); + break; + } + + default: + break; + }; + } + + static void NotificationActivated(const wxString& notificationId, NSUserNotificationActivationType activationType) + { + wxUserNotificationMsgImpl* impl = ms_activeNotifications[notificationId]; + if (impl) + impl->Activated(activationType); + } + + static void UseHandler() + { + if (!ms_handler) + { + ms_handler = [wxUserNotificationHandler alloc]; + [NSUserNotificationCenter defaultUserNotificationCenter].delegate = ms_handler; + } + } + + static void ReleaseHandler() + { + + } + +private: + NSUserNotification* m_notif; + wxString m_id; + wxVector m_actions; + + static wxUserNotificationHandler* ms_handler; + static std::map ms_activeNotifications; + static int ms_notifIdBase; +}; + +wxUserNotificationHandler* wxUserNotificationMsgImpl::ms_handler = nil; +std::map wxUserNotificationMsgImpl::ms_activeNotifications; +int wxUserNotificationMsgImpl::ms_notifIdBase = 1000; + +// ---------------------------------------------------------------------------- +// wxUserNotificationHandler +// ---------------------------------------------------------------------------- + +@implementation wxUserNotificationHandler + +- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification +{ + NSString* notifId = [notification.userInfo objectForKey:@"wxId"]; + if (notifId) + wxUserNotificationMsgImpl::NotificationActivated(wxCFStringRef::AsString(notifId), notification.activationType); +} + +@end + +// ============================================================================ +// implementation +// ============================================================================ + + +// ---------------------------------------------------------------------------- +// wxNotificationMessage +// ---------------------------------------------------------------------------- + +void wxNotificationMessage::Init() +{ + // Native notifications are not available prior to 10.8, fallback + // to generic ones on 10.7 + if (wxPlatformInfo::Get().CheckOSVersion(10, 8)) + m_impl = new wxUserNotificationMsgImpl(this); + else + m_impl = new wxGenericNotificationMessageImpl(this); +} + +#endif // wxUSE_NOTIFICATION_MESSAGE && defined(wxHAS_NATIVE_NOTIFICATION_MESSAGE)