]> git.saurik.com Git - wxWidgets.git/blob - src/osx/cocoa/taskbar.mm
fixing non-precomp headers
[wxWidgets.git] / src / osx / cocoa / taskbar.mm
1 /////////////////////////////////////////////////////////////////////////
2 // File: src/osx/cocoa/taskbar.mm
3 // Purpose: Implements wxTaskBarIcon class
4 // Author: David Elliott, Stefan Csomor
5 // Modified by:
6 // Created: 2004/01/24
7 // RCS-ID: $Id: taskbar.mm 35650 2005-09-23 12:56:45Z MR $
8 // Copyright: (c) 2004 David Elliott, Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13 #if wxUSE_TASKBARICON
14
15 #ifndef WX_PRECOMP
16 #include "wx/toplevel.h"
17 #include "wx/menu.h"
18 #include "wx/icon.h"
19 #include "wx/log.h"
20 #include "wx/dcclient.h"
21 #endif
22
23 #include "wx/taskbar.h"
24
25 #include "wx/osx/private.h"
26
27 class wxTaskBarIconWindow;
28
29 //-----------------------------------------------------------------------------
30 //
31 // wxTaskBarIconWindow
32 //
33 // Event handler for menus
34 // NB: Since wxWindows in Mac HAVE to have parents we need this to be
35 // a top level window...
36 //-----------------------------------------------------------------------------
37
38 class wxTaskBarIconWindow : public wxTopLevelWindow
39 {
40 public:
41 wxTaskBarIconWindow(wxTaskBarIconImpl *impl);
42
43 void OnMenuEvent(wxCommandEvent& event);
44 void OnUpdateUIEvent(wxUpdateUIEvent& event);
45
46 private:
47 wxTaskBarIconImpl *m_impl;
48 DECLARE_EVENT_TABLE()
49 };
50
51 // ============================================================================
52 // wxTaskBarIconImpl
53 // Base class for the various Cocoa implementations.
54 // ============================================================================
55 class wxTaskBarIconImpl
56 {
57 public:
58 wxTaskBarIconImpl(wxTaskBarIcon *taskBarIcon);
59
60 virtual bool IsStatusItem() const { return false; }
61
62 virtual bool SetIcon(const wxIcon& icon, const wxString& tooltip = wxEmptyString) = 0;
63 virtual bool RemoveIcon() = 0;
64
65 bool IsIconInstalled() const { return m_icon.Ok(); }
66
67 virtual bool PopupMenu(wxMenu *menu) = 0;
68 virtual ~wxTaskBarIconImpl();
69 inline wxTaskBarIcon* GetTaskBarIcon() { return m_taskBarIcon; }
70 wxMenu * CreatePopupMenu()
71 { return m_taskBarIcon->CreatePopupMenu(); }
72
73 wxDECLARE_NO_COPY_CLASS(wxTaskBarIconImpl);
74
75 protected:
76 wxTaskBarIcon *m_taskBarIcon;
77 wxBitmap m_icon;
78 wxTaskBarIconWindow *m_eventWindow;
79 private:
80 wxTaskBarIconImpl();
81 };
82
83 // ============================================================================
84 // wxTaskBarIconDockImpl
85 // An implementation using the Dock icon.
86 // ============================================================================
87 class wxTaskBarIconDockImpl: public wxTaskBarIconImpl
88 {
89 public:
90 wxTaskBarIconDockImpl(wxTaskBarIcon *taskBarIcon);
91 virtual ~wxTaskBarIconDockImpl();
92 virtual bool SetIcon(const wxIcon& icon, const wxString& tooltip = wxEmptyString);
93 virtual bool RemoveIcon();
94 virtual bool PopupMenu(wxMenu *menu);
95
96 static WX_NSMenu OSXGetDockHMenu();
97 protected:
98 WX_NSMenu OSXDoGetDockHMenu();
99 // There can be only one Dock icon, so make sure we keep it that way
100 static wxTaskBarIconDockImpl *sm_dockIcon;
101 private:
102 wxTaskBarIconDockImpl();
103 wxMenu *m_pMenu;
104 };
105
106 class wxTaskBarIconCustomStatusItemImpl;
107
108 @interface wxOSXStatusItemTarget : NSObject
109 {
110 wxTaskBarIconCustomStatusItemImpl* impl;
111 }
112 @end
113
114 // ============================================================================
115 // wxTaskBarIconCustomStatusItemImpl
116 // An implementation using an NSStatusItem with a custom NSView
117 // ============================================================================
118 class wxTaskBarIconCustomStatusItemImpl: public wxTaskBarIconImpl
119 {
120 public:
121 wxTaskBarIconCustomStatusItemImpl(wxTaskBarIcon *taskBarIcon);
122 virtual ~wxTaskBarIconCustomStatusItemImpl();
123
124 virtual bool IsStatusItem() const { return true; }
125
126 virtual bool SetIcon(const wxIcon& icon, const wxString& tooltip = wxEmptyString);
127 virtual bool RemoveIcon();
128 virtual bool PopupMenu(wxMenu *menu);
129 protected:
130 NSStatusItem *m_statusItem;
131 wxOSXStatusItemTarget *m_target;
132 private:
133 wxTaskBarIconCustomStatusItemImpl();
134 };
135
136 // ============================================================================
137 // wxTaskBarIcon implementation
138 // The facade class.
139 // ============================================================================
140 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler)
141
142 wxTaskBarIcon::wxTaskBarIcon(wxTaskBarIconType iconType)
143 {
144 if(iconType == DOCK)
145 m_impl = new wxTaskBarIconDockImpl(this);
146 else if(iconType == CUSTOM_STATUSITEM)
147 m_impl = new wxTaskBarIconCustomStatusItemImpl(this);
148 else
149 { m_impl = NULL;
150 wxFAIL_MSG(wxT("Invalid wxTaskBarIcon type"));
151 }
152 }
153
154 wxTaskBarIcon::~wxTaskBarIcon()
155 {
156 if ( m_impl )
157 {
158 if ( m_impl->IsIconInstalled() )
159 m_impl->RemoveIcon();
160 delete m_impl;
161 m_impl = NULL;
162 }
163 }
164
165 bool wxTaskBarIcon::OSXIsStatusItem()
166 {
167 if ( m_impl )
168 return m_impl->IsStatusItem();
169
170 return false;
171 }
172
173 // Operations
174
175 bool wxTaskBarIcon::IsIconInstalled() const
176 {
177 if ( m_impl )
178 return m_impl->IsIconInstalled();
179
180 return false;
181 }
182
183 bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
184 {
185 if ( m_impl )
186 return m_impl->SetIcon(icon,tooltip);
187
188 return false;
189 }
190
191 bool wxTaskBarIcon::RemoveIcon()
192 {
193 if ( m_impl )
194 return m_impl->RemoveIcon();
195
196 return false;
197 }
198
199 bool wxTaskBarIcon::PopupMenu(wxMenu *menu)
200 {
201 if ( m_impl )
202 return m_impl->PopupMenu(menu);
203
204 return false;
205 }
206
207 // ============================================================================
208 // wxTaskBarIconImpl
209 // ============================================================================
210
211 wxTaskBarIconImpl::wxTaskBarIconImpl(wxTaskBarIcon* taskBarIcon)
212 : m_taskBarIcon(taskBarIcon), m_eventWindow(new wxTaskBarIconWindow(this))
213 {
214 }
215
216 wxTaskBarIconImpl::~wxTaskBarIconImpl()
217 {
218 delete m_eventWindow;
219 }
220
221 // ============================================================================
222 // wxTaskBarIconDockImpl
223 // ============================================================================
224 wxTaskBarIconDockImpl *wxTaskBarIconDockImpl::sm_dockIcon = NULL;
225
226 wxTaskBarIconDockImpl::wxTaskBarIconDockImpl(wxTaskBarIcon *taskBarIcon)
227 : wxTaskBarIconImpl(taskBarIcon)
228 {
229 wxASSERT_MSG(!sm_dockIcon, wxT("You should never have more than one dock icon!"));
230 sm_dockIcon = this;
231 m_pMenu = NULL;
232 }
233
234 wxTaskBarIconDockImpl::~wxTaskBarIconDockImpl()
235 {
236 if(sm_dockIcon == this)
237 sm_dockIcon = NULL;
238 }
239
240 WX_NSMenu wxTaskBarIconDockImpl::OSXGetDockHMenu()
241 {
242 if(sm_dockIcon)
243 return sm_dockIcon->OSXDoGetDockHMenu();
244
245 return nil;
246 }
247
248 WX_NSMenu wxTaskBarIconDockImpl::OSXDoGetDockHMenu()
249 {
250 wxMenu *dockMenu = CreatePopupMenu();
251
252 if(!dockMenu)
253 return nil;
254
255 wxDELETE(m_pMenu);
256
257 m_pMenu = dockMenu;
258
259 m_pMenu->SetInvokingWindow(m_eventWindow);
260
261 m_pMenu->UpdateUI();
262
263 return (WX_NSMenu)dockMenu->GetHMenu();
264 }
265
266 bool wxTaskBarIconDockImpl::SetIcon(const wxIcon& icon, const wxString& WXUNUSED(tooltip))
267 {
268 m_icon.CopyFromIcon(icon);
269 [[NSApplication sharedApplication] setApplicationIconImage:m_icon.GetNSImage()];
270 return true;
271 }
272
273 bool wxTaskBarIconDockImpl::RemoveIcon()
274 {
275 wxDELETE(m_pMenu);
276 m_icon = wxBitmap();
277 [[NSApplication sharedApplication] setApplicationIconImage:nil];
278 return true;
279 }
280
281 bool wxTaskBarIconDockImpl::PopupMenu(wxMenu *WXUNUSED(menu))
282 {
283 wxFAIL_MSG(wxT("You cannot force the Dock icon menu to popup"));
284 return false;
285 }
286
287 @interface wxNSAppController(wxTaskBarIconNSApplicationDelegateCategory)
288 - (NSMenu*)applicationDockMenu:(NSApplication *)sender;
289 @end
290
291 @implementation wxNSAppController(wxTaskBarIconNSApplicationDelegateCategory)
292 - (NSMenu*)applicationDockMenu:(NSApplication *)sender
293 {
294 return wxTaskBarIconDockImpl::OSXGetDockHMenu();
295 }
296 @end
297
298 // ============================================================================
299 // wxTaskBarIconCustomStatusItemImpl
300 // ============================================================================
301
302 @implementation wxOSXStatusItemTarget
303
304 - (void) clickedAction: (id) sender
305 {
306 wxMenu *menu = impl->CreatePopupMenu();
307 if (menu)
308 {
309 impl->PopupMenu(menu);
310 delete menu;
311 }
312 }
313
314 - (void)setImplementation: (wxTaskBarIconCustomStatusItemImpl *) theImplementation
315 {
316 impl = theImplementation;
317 }
318
319 - (wxTaskBarIconCustomStatusItemImpl*) implementation
320 {
321 return impl;
322 }
323
324 @end
325
326
327 wxTaskBarIconCustomStatusItemImpl::wxTaskBarIconCustomStatusItemImpl(wxTaskBarIcon *taskBarIcon)
328 : wxTaskBarIconImpl(taskBarIcon)
329 {
330 m_statusItem = nil;
331 m_target = nil;
332 }
333
334 wxTaskBarIconCustomStatusItemImpl::~wxTaskBarIconCustomStatusItemImpl()
335 {
336 }
337
338 bool wxTaskBarIconCustomStatusItemImpl::SetIcon(const wxIcon& icon, const wxString& WXUNUSED(tooltip))
339 {
340 if(!m_statusItem)
341 {
342 m_statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
343 [m_statusItem retain];
344
345 m_target = [[wxOSXStatusItemTarget alloc] init];
346 [m_target setImplementation:this];
347 [m_statusItem setTarget:m_target];
348 [m_statusItem setAction:@selector(clickedAction:)];
349 [m_statusItem sendActionOn:NSLeftMouseDownMask];
350 }
351
352 m_icon.CopyFromIcon(icon);
353
354 // status item doesn't scale automatically
355
356 int dimension = m_icon.GetHeight();
357 if ( m_icon.GetWidth() > dimension )
358 dimension = m_icon.GetWidth();
359 if ( dimension > 16 )
360 {
361 wxImage img = m_icon.ConvertToImage();
362 int factor = (dimension+15)/16;
363 m_icon = img.ShrinkBy(factor, factor);
364 }
365
366 [m_statusItem setImage:m_icon.GetNSImage()];
367 return true;
368 }
369
370 bool wxTaskBarIconCustomStatusItemImpl::RemoveIcon()
371 {
372 [m_statusItem release];
373 m_statusItem = nil;
374 [m_target release];
375 m_target = nil;
376
377 m_icon = wxBitmap();
378
379 return true;
380 }
381
382 bool wxTaskBarIconCustomStatusItemImpl::PopupMenu(wxMenu *menu)
383 {
384 wxASSERT(menu);
385
386 menu->SetInvokingWindow(m_eventWindow);
387 menu->UpdateUI();
388
389 [m_statusItem popUpStatusItemMenu:(NSMenu*)menu->GetHMenu()];
390
391 menu->SetInvokingWindow(NULL);
392 return true;
393 }
394
395 // ============================================================================
396 // wxTaskBarIconWindow
397 // ============================================================================
398
399 BEGIN_EVENT_TABLE(wxTaskBarIconWindow, wxWindow)
400 EVT_MENU(-1, wxTaskBarIconWindow::OnMenuEvent)
401 EVT_UPDATE_UI(-1, wxTaskBarIconWindow::OnUpdateUIEvent)
402 END_EVENT_TABLE()
403
404 wxTaskBarIconWindow::wxTaskBarIconWindow(wxTaskBarIconImpl *impl)
405 : m_impl(impl)
406 {
407 }
408
409 void wxTaskBarIconWindow::OnMenuEvent(wxCommandEvent& event)
410 {
411 m_impl->GetTaskBarIcon()->ProcessEvent(event);
412 }
413
414 void wxTaskBarIconWindow::OnUpdateUIEvent(wxUpdateUIEvent& event)
415 {
416 m_impl->GetTaskBarIcon()->ProcessEvent(event);
417 }
418
419 #endif //def wxHAS_TASK_BAR_ICON