]> git.saurik.com Git - wxWidgets.git/blame - src/msw/notifmsg.cpp
added wxArtProvider::GetMessageBoxIcon() to avoid duplicating the same code in generi...
[wxWidgets.git] / src / msw / notifmsg.cpp
CommitLineData
e2d5abbf
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/msw/notifmsg.cpp
3// Purpose: implementation of wxNotificationMessage for Windows
4// Author: Vadim Zeitlin
5// Created: 2007-12-01
6// RCS-ID: $Id$
7// Copyright: (c) 2007 Vadim Zeitlin <vadim@wxwindows.org>
8// Licence: wxWindows licence
9///////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// for compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
26#if wxUSE_NOTIFICATION_MESSAGE && wxUSE_TASKBARICON
27
28#ifndef WX_PRECOMP
29 #include "wx/string.h"
30#endif // WX_PRECOMP
31
32#include "wx/notifmsg.h"
33#include "wx/generic/notifmsg.h"
34
35#include "wx/taskbar.h"
36
37// ----------------------------------------------------------------------------
38// different implementations used by wxNotificationMessage
39// ----------------------------------------------------------------------------
40
41// base class for all available implementations
42class wxNotifMsgImpl
43{
44public:
45 wxNotifMsgImpl() { }
46 virtual ~wxNotifMsgImpl() { }
47
48 virtual bool DoShow(const wxString& title,
49 const wxString& message,
50 int timeout,
51 int flags) = 0;
52 virtual bool DoClose() = 0;
53
54private:
55 DECLARE_NO_COPY_CLASS(wxNotifMsgImpl)
56};
57
58// implementation which is simply a bridge to wxGenericNotificationMessage
59class wxGenericNotifMsgImpl : public wxNotifMsgImpl
60{
61public:
62 wxGenericNotifMsgImpl() : m_notif(new wxGenericNotificationMessage) { }
63 virtual ~wxGenericNotifMsgImpl() { delete m_notif; }
64
65 virtual bool DoShow(const wxString& title,
66 const wxString& message,
67 int timeout,
68 int flags)
69 {
70 m_notif->SetTitle(title);
71 m_notif->SetMessage(message);
72 m_notif->SetFlags(flags);
73 return m_notif->Show(timeout);
74 }
75
76 virtual bool DoClose()
77 {
78 return m_notif->Close();
79 }
80
81private:
82 wxGenericNotificationMessage * const m_notif;
83};
84
85// common base class for implementations using a taskbar icon and balloons
86class wxBalloonNotifMsgImpl : public wxNotifMsgImpl
87{
88public:
89 // ctor sets up m_icon (using the icon of the top level parent of the given
90 // window) which can be used to show an attached balloon later by the
91 // derived classes
92 wxBalloonNotifMsgImpl(wxWindow *win) { SetUpIcon(win); }
93
94 // implementation of wxNotificationMessage method with the same name
95 static wxTaskBarIcon *UseTaskBarIcon(wxTaskBarIcon *icon);
96
97 virtual bool DoShow(const wxString& title,
98 const wxString& message,
99 int timeout,
100 int flags);
101
102protected:
103 // sets up m_icon (doesn't do anything with the old value, caller beware)
104 void SetUpIcon(wxWindow *win);
105
106
107 static wxTaskBarIcon *ms_iconToUse;
108
109 // the icon we attach our notification to, either ms_iconToUse or a
110 // temporary one which we will destroy when done
111 wxTaskBarIcon *m_icon;
112
113 // should be only used if m_icon != NULL and indicates whether we should
114 // delete it
115 bool m_ownsIcon;
116};
117
118// implementation for automatically hidden notifications
119class wxAutoNotifMsgImpl : public wxBalloonNotifMsgImpl
120{
121public:
122 wxAutoNotifMsgImpl(wxWindow *win);
123
124 virtual bool DoShow(const wxString& title,
125 const wxString& message,
126 int timeout,
127 int flags);
128
129 // can't close automatic notification [currently]
130 virtual bool DoClose() { return false; }
131
132private:
133 // custom event handler connected to m_icon which will receive the icon
134 // close event and delete it and itself when it happens
135 wxEvtHandler * const m_iconEvtHandler;
136};
137
138// implementation for manually closed notifications
139class wxManualNotifMsgImpl : public wxBalloonNotifMsgImpl
140{
141public:
142 wxManualNotifMsgImpl(wxWindow *win);
143 virtual ~wxManualNotifMsgImpl();
144
145 virtual bool DoShow(const wxString& title,
146 const wxString& message,
147 int timeout,
148 int flags);
149 virtual bool DoClose();
150
151private:
152 // store ctor parameter as we need it to recreate the icon later if we're
153 // closed and shown again
154 wxWindow * const m_win;
155};
156
157// ----------------------------------------------------------------------------
158// custom event handler for task bar icons
159// ----------------------------------------------------------------------------
160
161// normally we'd just use a custom taskbar icon class but this is impossible
162// because we can be asked to attach the notifications to an existing icon
163// which we didn't create, hence we install a special event handler allowing us
164// to get the events we need (and, crucially, to delete the icon when it's not
165// needed any more) in any case
166
167class wxNotificationIconEvtHandler : public wxEvtHandler
168{
169public:
170 wxNotificationIconEvtHandler(wxTaskBarIcon *icon);
171
172private:
173 void OnTimeout(wxTaskBarIconEvent& event);
174 void OnClick(wxTaskBarIconEvent& event);
175
176 void OnIconHidden();
177
178
179 wxTaskBarIcon * const m_icon;
180
181 DECLARE_NO_COPY_CLASS(wxNotificationIconEvtHandler)
182};
183
184// ============================================================================
185// implementation
186// ============================================================================
187
188// ----------------------------------------------------------------------------
189// wxNotificationIconEvtHandler
190// ----------------------------------------------------------------------------
191
192wxNotificationIconEvtHandler::wxNotificationIconEvtHandler(wxTaskBarIcon *icon)
193 : m_icon(icon)
194{
195 m_icon->Connect
196 (
197 wxEVT_TASKBAR_BALLOON_TIMEOUT,
198 wxTaskBarIconEventHandler(wxNotificationIconEvtHandler::OnTimeout),
199 NULL,
200 this
201 );
202
203 m_icon->Connect
204 (
205 wxEVT_TASKBAR_BALLOON_CLICK,
64336927 206 wxTaskBarIconEventHandler(wxNotificationIconEvtHandler::OnClick),
e2d5abbf
VZ
207 NULL,
208 this
209 );
210}
211
212void wxNotificationIconEvtHandler::OnIconHidden()
213{
214 delete m_icon;
215
216 delete this;
217}
218
219void
220wxNotificationIconEvtHandler::OnTimeout(wxTaskBarIconEvent& WXUNUSED(event))
221{
222 OnIconHidden();
223}
224
225void wxNotificationIconEvtHandler::OnClick(wxTaskBarIconEvent& WXUNUSED(event))
226{
227 // TODO: generate an event notifying the user code?
228
229 OnIconHidden();
230}
231
232// ----------------------------------------------------------------------------
233// wxBalloonNotifMsgImpl
234// ----------------------------------------------------------------------------
235
236wxTaskBarIcon *wxBalloonNotifMsgImpl::ms_iconToUse = NULL;
237
238/* static */
239wxTaskBarIcon *wxBalloonNotifMsgImpl::UseTaskBarIcon(wxTaskBarIcon *icon)
240{
241 wxTaskBarIcon * const iconOld = ms_iconToUse;
242 ms_iconToUse = icon;
243 return iconOld;
244}
245
246void wxBalloonNotifMsgImpl::SetUpIcon(wxWindow *win)
247{
248 if ( ms_iconToUse )
249 {
250 // use an existing icon
251 m_ownsIcon = false;
252 m_icon = ms_iconToUse;
253 }
254 else // no user-specified icon to attach to
255 {
256 // create our own one
257 m_ownsIcon = true;
258 m_icon = new wxTaskBarIcon;
259
260 // use the icon of the associated (or main, if none) frame
261 wxIcon icon;
262 if ( win )
263 win = wxGetTopLevelParent(win);
264 if ( !win )
265 win = wxTheApp->GetTopWindow();
266 if ( win )
267 {
268 const wxTopLevelWindow * const
269 tlw = wxDynamicCast(win, wxTopLevelWindow);
270 if ( tlw )
271 icon = tlw->GetIcon();
272 }
273
274 if ( !icon.IsOk() )
275 {
276 // we really must have some icon
277 icon = wxIcon(_T("wxICON_AAA"));
278 }
279
280 m_icon->SetIcon(icon);
281 }
282}
283
284bool
285wxBalloonNotifMsgImpl::DoShow(const wxString& title,
286 const wxString& message,
287 int timeout,
288 int flags)
289{
290 timeout *= 1000; // Windows expresses timeout in milliseconds
291
292 return m_icon->ShowBalloon(title, message, timeout, flags);
293}
294
295// ----------------------------------------------------------------------------
296// wxManualNotifMsgImpl
297// ----------------------------------------------------------------------------
298
299wxManualNotifMsgImpl::wxManualNotifMsgImpl(wxWindow *win)
300 : wxBalloonNotifMsgImpl(win),
301 m_win(win)
302{
303}
304
305wxManualNotifMsgImpl::~wxManualNotifMsgImpl()
306{
307 if ( m_icon )
308 DoClose();
309}
310
311bool
312wxManualNotifMsgImpl::DoShow(const wxString& title,
313 const wxString& message,
314 int timeout,
315 int flags)
316{
317 wxASSERT_MSG( timeout == wxNotificationMessage::Timeout_Never,
318 _T("shouldn't be used") );
319
320 // base class creates the icon for us initially but we could have destroyed
321 // it in DoClose(), recreate it if this was the case
322 if ( !m_icon )
323 SetUpIcon(m_win);
324
325 // use maximal (in current Windows versions) timeout (but it will still
326 // disappear on its own)
327 return wxBalloonNotifMsgImpl::DoShow(title, message, 30, flags);
328}
329
330bool wxManualNotifMsgImpl::DoClose()
331{
332 if ( m_ownsIcon )
333 {
334 // we don't need the icon any more
335 delete m_icon;
336 }
337 else // using an existing icon
338 {
339 // just hide the balloon
340 m_icon->ShowBalloon("", "");
341 }
342
343 m_icon = NULL;
344
345 return true;
346}
347
348// ----------------------------------------------------------------------------
349// wxAutoNotifMsgImpl
350// ----------------------------------------------------------------------------
351
352wxAutoNotifMsgImpl::wxAutoNotifMsgImpl(wxWindow *win)
353 : wxBalloonNotifMsgImpl(win),
354 m_iconEvtHandler(new wxNotificationIconEvtHandler(m_icon))
355{
356}
357
358bool
359wxAutoNotifMsgImpl::DoShow(const wxString& title,
360 const wxString& message,
361 int timeout,
362 int flags)
363{
364 wxASSERT_MSG( timeout != wxNotificationMessage::Timeout_Never,
365 _T("shouldn't be used") );
366
367 if ( timeout == wxNotificationMessage::Timeout_Auto )
368 {
369 // choose a value more or less in the middle of the allowed range
370 timeout = 1;
371 }
372
373 return wxBalloonNotifMsgImpl::DoShow(title, message, timeout, flags);
374}
375
376// ----------------------------------------------------------------------------
377// wxNotificationMessage
378// ----------------------------------------------------------------------------
379
380/* static */
381wxTaskBarIcon *wxNotificationMessage::UseTaskBarIcon(wxTaskBarIcon *icon)
382{
383 return wxBalloonNotifMsgImpl::UseTaskBarIcon(icon);
384}
385
386bool wxNotificationMessage::Show(int timeout)
387{
388 if ( !m_impl )
389 {
390 if ( wxTheApp->GetShell32Version() >= 500 )
391 {
392 if ( timeout == Timeout_Never )
393 m_impl = new wxManualNotifMsgImpl(GetParent());
394 else
395 m_impl = new wxAutoNotifMsgImpl(GetParent());
396 }
397 else // no support for balloon tooltips
398 {
399 m_impl = new wxGenericNotifMsgImpl;
400 }
401 }
402 //else: reuse the same implementation for the subsequent calls, it would
403 // be too confusing if it changed
404
405 return m_impl->DoShow(GetTitle(), GetMessage(), timeout, GetFlags());
406}
407
408bool wxNotificationMessage::Close()
409{
410 wxCHECK_MSG( m_impl, false, "must show the notification first" );
411
412 return m_impl->DoClose();
413}
414
415wxNotificationMessage::~wxNotificationMessage()
416{
417 delete m_impl;
418}
419
420#endif // wxUSE_NOTIFICATION_MESSAGE && wxUSE_TASKBARICON