Fix up NSSlider code to not use class posing and instantiate the proper type (now...
[wxWidgets.git] / src / cocoa / NSSlider.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/cocoa/NSSlider.mm
3 // Purpose:     wxCocoaNSSlider class
4 // Author:      Mark Oxenham
5 // Modified by: David Elliott
6 // Created:     2007/08/10
7 // RCS-ID:      $Id$
8 // Copyright:   (c) 2007 Software 2000 Ltd. All rights reserved.
9 // Licence:     wxWidgets licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #ifndef WX_PRECOMP
15     #include "wx/log.h"
16 #endif // WX_PRECOMP
17
18 #include "wx/cocoa/NSSlider.h"
19
20 #import <Foundation/NSNotification.h>
21 #import <Foundation/NSString.h>
22 #import <AppKit/NSEvent.h>
23 #include "wx/cocoa/objc/NSSlider.h"
24
25 WX_IMPLEMENT_OBJC_INTERFACE_HASHMAP(NSSlider)
26
27 // ============================================================================
28 // @class wxNSSliderTarget
29 // ============================================================================
30 @interface wxNSSliderTarget : NSObject
31 {
32 }
33
34 - (void)wxNSSliderUpArrowKeyDown: (id)sender;
35 - (void)wxNSSliderDownArrowKeyDown: (id)sender;
36 - (void)wxNSSliderLeftArrowKeyDown: (id)sender;
37 - (void)wxNSSliderRightArrowKeyDown: (id)sender;
38 - (void)wxNSSliderPageUpKeyDown: (id)sender;
39 - (void)wxNSSliderPageDownKeyDown: (id)sender;
40 - (void)wxNSSliderMoveUp: (id)sender;
41 - (void)wxNSSliderMoveDown: (id)sender;
42 - (void)wxNSSliderMoveLeft: (id)sender;
43 - (void)wxNSSliderMoveRight: (id)sender;
44 - (void)wxNSSliderPageUp: (id)sender;
45 - (void)wxNSSliderPageDown: (id)sender;
46 @end // wxNSSliderTarget
47
48 @implementation wxNSSliderTarget : NSObject
49
50 - (void)wxNSSliderUpArrowKeyDown: (id)sender
51 {
52     wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
53     wxCHECK_RET(slider,wxT("wxNSSliderUpArrowKeyDown received without associated wx object"));
54     slider->Cocoa_wxNSSliderUpArrowKeyDown();
55 }
56
57 - (void)wxNSSliderDownArrowKeyDown: (id)sender
58 {
59     wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
60     wxCHECK_RET(slider,wxT("wxNSSliderDownArrowKeyDown received without associated wx object"));
61     slider->Cocoa_wxNSSliderDownArrowKeyDown();
62 }
63
64 - (void)wxNSSliderLeftArrowKeyDown: (id)sender
65 {
66     wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
67     wxCHECK_RET(slider,wxT("wxNSSliderLeftArrowKeyDown received without associated wx object"));
68     slider->Cocoa_wxNSSliderLeftArrowKeyDown();
69 }
70
71 - (void)wxNSSliderRightArrowKeyDown: (id)sender
72 {
73     wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
74     wxCHECK_RET(slider,wxT("wxNSSliderRightArrowKeyDown received without associated wx object"));
75     slider->Cocoa_wxNSSliderRightArrowKeyDown();
76 }
77
78 - (void)wxNSSliderPageUpKeyDown: (id)sender
79 {
80     wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
81     wxCHECK_RET(slider,wxT("wxNSSliderPageUpKeyDown received without associated wx object"));
82     slider->Cocoa_wxNSSliderPageUpKeyDown();
83 }
84
85 - (void)wxNSSliderPageDownKeyDown: (id)sender
86 {
87     wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
88     wxCHECK_RET(slider,wxT("wxNSSliderPageDownKeyDown received without associated wx object"));
89     slider->Cocoa_wxNSSliderPageDownKeyDown();
90 }
91
92 - (void)wxNSSliderMoveUp: (id)sender
93 {
94     wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
95     wxCHECK_RET(slider,wxT("wxNSSliderMoveUp received without associated wx object"));
96     slider->Cocoa_wxNSSliderMoveUp();
97 }
98
99 - (void)wxNSSliderMoveDown: (id)sender
100 {
101     wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
102     wxCHECK_RET(slider,wxT("wxNSSliderMoveDown received without associated wx object"));
103     slider->Cocoa_wxNSSliderMoveDown();
104 }
105
106 - (void)wxNSSliderMoveLeft: (id)sender
107 {
108     wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
109     wxCHECK_RET(slider,wxT("wxNSSliderMoveLeft received without associated wx object"));
110     slider->Cocoa_wxNSSliderMoveLeft();
111 }
112
113 - (void)wxNSSliderMoveRight: (id)sender
114 {
115     wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
116     wxCHECK_RET(slider,wxT("wxNSSliderMoveRight received without associated wx object"));
117     slider->Cocoa_wxNSSliderMoveRight();
118 }
119
120 - (void)wxNSSliderPageUp: (id)sender
121 {
122     wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
123     wxCHECK_RET(slider,wxT("wxNSSliderPageUp received without associated wx object"));
124     slider->Cocoa_wxNSSliderPageUp();
125 }
126
127 - (void)wxNSSliderPageDown: (id)sender
128 {
129     wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
130     wxCHECK_RET(slider,wxT("wxNSSliderPageDown received without associated wx object"));
131     slider->Cocoa_wxNSSliderPageDown();
132 }
133
134 @end // implementation wxNSSliderTarget
135
136 // ============================================================================
137 // @class WXNSSlider
138 // ============================================================================
139
140
141 @implementation WXNSSlider : NSSlider
142
143 // Override to ensure that WXNSSlider gets created with a WXNSSliderCell
144 + (Class)cellClass
145 {
146     return [WX_GET_OBJC_CLASS(WXNSSliderCell) class];
147 }
148
149 - (void)keyDown:(NSEvent *)theEvent
150 {
151     SEL originalAction = [self action];
152     SEL newAction = originalAction;
153     NSString *theEventCharacters = [theEvent charactersIgnoringModifiers];
154
155     if ([theEventCharacters length] == 1)
156     {
157         switch ([theEventCharacters characterAtIndex:0])
158         {
159             case NSUpArrowFunctionKey:      newAction = @selector(wxNSSliderUpArrowKeyDown:);       break;
160             case NSDownArrowFunctionKey:    newAction = @selector(wxNSSliderDownArrowKeyDown:);     break;
161             case NSLeftArrowFunctionKey:    newAction = @selector(wxNSSliderLeftArrowKeyDown:);     break;
162             case NSRightArrowFunctionKey:   newAction = @selector(wxNSSliderRightArrowKeyDown:);    break;
163             case NSPageUpFunctionKey:       newAction = @selector(wxNSSliderPageUpKeyDown:);        break;
164             case NSPageDownFunctionKey:     newAction = @selector(wxNSSliderPageDownKeyDown:);      break;
165             default:                                                                                break;
166         }
167     }
168
169     [self setAction:newAction];
170     [super keyDown:theEvent];
171     [self setAction:originalAction];
172 }
173
174 - (void)moveUp:(id)sender
175 {
176     SEL originalAction = [self action];
177
178     [self setAction:@selector(wxNSSliderMoveUp:)];
179     [super moveUp:sender];
180     [self setAction:originalAction];
181 }
182
183 - (void)moveDown:(id)sender
184 {
185     SEL originalAction = [self action];
186
187     [self setAction:@selector(wxNSSliderMoveDown:)];
188     [super moveDown:sender];
189     [self setAction:originalAction];
190 }
191
192 - (void)moveLeft:(id)sender
193 {
194     SEL originalAction = [self action];
195
196     [self setAction:@selector(wxNSSliderMoveLeft:)];
197     [super moveLeft:sender];
198     [self setAction:originalAction];
199 }
200
201 - (void)moveRight:(id)sender
202 {
203     SEL originalAction = [self action];
204
205     [self setAction:@selector(wxNSSliderMoveRight:)];
206     [super moveRight:sender];
207     [self setAction:originalAction];
208 }
209
210 - (void)pageUp:(id)sender
211 {
212     SEL originalAction = [self action];
213
214     [self setAction:@selector(wxNSSliderPageUp:)];
215     [super pageUp:sender];
216     [self setAction:originalAction];
217 }
218
219 - (void)pageDown:(id)sender
220 {
221     SEL originalAction = [self action];
222
223     [self setAction:@selector(wxNSSliderPageDown:)];
224     [super pageDown:sender];
225     [self setAction:originalAction];
226 }
227
228 @end
229 WX_IMPLEMENT_GET_OBJC_CLASS(WXNSSlider,NSSlider)
230
231 // ============================================================================
232 // @class WXNSSliderCell
233 // ============================================================================
234
235 #define kwxNSSliderStartTracking    @"wxNSSliderStartTracking"
236 #define kwxNSSliderContinueTracking @"wxNSSliderContinueTracking"
237 #define kwxNSSliderStopTracking     @"wxNSSliderStopTracking"
238
239 @implementation WXNSSliderCell : NSSliderCell
240 - (BOOL)startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView
241 {
242     BOOL result = [super startTrackingAt:startPoint inView:controlView];
243     [[NSNotificationCenter defaultCenter] postNotificationName:kwxNSSliderStartTracking object:controlView];
244     return result;
245 }
246
247 - (BOOL)continueTracking:(NSPoint)lastPoint at:(NSPoint)currentPoint inView:(NSView *)controlView
248 {
249     BOOL result = [super continueTracking:lastPoint at:currentPoint inView:controlView];
250     [[NSNotificationCenter defaultCenter] postNotificationName:kwxNSSliderContinueTracking object:controlView];
251     return result;
252 }
253
254 - (void)stopTracking:(NSPoint)lastPoint at:(NSPoint)stopPoint inView:(NSView *)controlView mouseIsUp:(BOOL)flag
255 {
256     [super stopTracking:lastPoint at:stopPoint inView:controlView mouseIsUp:flag];
257     [[NSNotificationCenter defaultCenter] postNotificationName:kwxNSSliderStopTracking object:controlView];
258 }
259 @end
260 WX_IMPLEMENT_GET_OBJC_CLASS(WXNSSliderCell,NSSliderCell)
261
262 // ============================================================================
263 // @class wxNSSliderNotificationObserver
264 // ============================================================================
265 @interface wxNSSliderNotificationObserver : NSObject
266 {
267 }
268
269 struct objc_object *wxCocoaNSSlider::sm_cocoaObserver = [[wxNSSliderNotificationObserver alloc] init];
270
271 - (void)startTracking: (NSNotification *)notification;
272 - (void)continueTracking: (NSNotification *)notification;
273 - (void)stopTracking: (NSNotification *)notification;
274 @end // interface wxNSSliderNotificationObserver
275
276 @implementation wxNSSliderNotificationObserver : NSObject
277
278 - (void)startTracking: (NSNotification *)notification;
279 {
280     wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa([notification object]);
281     wxCHECK_RET(slider,wxT("startTracking received but no wxSlider exists"));
282     slider->CocoaNotification_startTracking(notification);
283 }
284
285 - (void)continueTracking: (NSNotification *)notification;
286 {
287     wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa([notification object]);
288     wxCHECK_RET(slider,wxT("continueTracking received but no wxSlider exists"));
289     slider->CocoaNotification_continueTracking(notification);
290 }
291
292 - (void)stopTracking: (NSNotification *)notification;
293 {
294     wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa([notification object]);
295     wxCHECK_RET(slider,wxT("stopTracking received but no wxSlider exists"));
296     slider->CocoaNotification_stopTracking(notification);
297 }
298
299 @end // implementation wxNSSliderNotificationObserver
300
301 // ============================================================================
302 // class wxCocoaNSSlider
303 // ============================================================================
304 const wxObjcAutoRefFromAlloc<struct objc_object*> wxCocoaNSSlider::sm_cocoaTarget = [[wxNSSliderTarget alloc] init];
305
306
307 void wxCocoaNSSlider::AssociateNSSlider(WX_NSSlider cocoaNSSlider)
308 {
309     if(cocoaNSSlider)
310     {
311         sm_cocoaHash.insert(wxCocoaNSSliderHash::value_type(cocoaNSSlider,this));
312         [[NSNotificationCenter defaultCenter] addObserver:(id)sm_cocoaObserver selector:@selector(startTracking:) name:kwxNSSliderStartTracking object:cocoaNSSlider];
313         [[NSNotificationCenter defaultCenter] addObserver:(id)sm_cocoaObserver selector:@selector(continueTracking:) name:kwxNSSliderContinueTracking object:cocoaNSSlider];
314         [[NSNotificationCenter defaultCenter] addObserver:(id)sm_cocoaObserver selector:@selector(stopTracking:) name:kwxNSSliderStopTracking object:cocoaNSSlider];
315         [cocoaNSSlider setTarget:sm_cocoaTarget];
316     }
317 }
318
319 void wxCocoaNSSlider::DisassociateNSSlider(WX_NSSlider cocoaNSSlider)
320 {
321     if(cocoaNSSlider)
322     {
323         sm_cocoaHash.erase(cocoaNSSlider);
324         [[NSNotificationCenter defaultCenter] removeObserver:(id)sm_cocoaObserver name:kwxNSSliderStartTracking object:cocoaNSSlider];
325         [[NSNotificationCenter defaultCenter] removeObserver:(id)sm_cocoaObserver name:kwxNSSliderContinueTracking object:cocoaNSSlider];
326         [[NSNotificationCenter defaultCenter] removeObserver:(id)sm_cocoaObserver name:kwxNSSliderStopTracking object:cocoaNSSlider];
327     }
328 }