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