// Name: wx/cocoa/NSSlider.h
// Purpose: wxCocoaNSSlider class
// Author: Mark Oxenham
-// Modified by:
+// Modified by: David Elliott
// Created: 2007/08/10
// RCS-ID: $Id$
// Copyright: (c) 2007 Software 2000 Ltd. All rights reserved.
WX_DECLARE_OBJC_HASHMAP(NSSlider);
+// For when we're not in Objective-C mode:
+typedef struct objc_selector *SEL;
+
+class wxCocoaNSSliderLastSelectorChanger;
+
class wxCocoaNSSlider
{
+ friend class wxCocoaNSSliderLastSelectorChanger;
WX_DECLARE_OBJC_INTERFACE_HASHMAP(NSSlider);
public:
void AssociateNSSlider(WX_NSSlider cocoaNSSlider);
void DisassociateNSSlider(WX_NSSlider cocoaNSSlider);
- virtual void Cocoa_wxNSSliderUpArrowKeyDown(void) = 0;
- virtual void Cocoa_wxNSSliderDownArrowKeyDown(void) = 0;
- virtual void Cocoa_wxNSSliderLeftArrowKeyDown(void) = 0;
- virtual void Cocoa_wxNSSliderRightArrowKeyDown(void) = 0;
- virtual void Cocoa_wxNSSliderPageUpKeyDown(void) = 0;
- virtual void Cocoa_wxNSSliderPageDownKeyDown(void) = 0;
- virtual void Cocoa_wxNSSliderMoveUp(void) = 0;
- virtual void Cocoa_wxNSSliderMoveDown(void) = 0;
- virtual void Cocoa_wxNSSliderMoveLeft(void) = 0;
- virtual void Cocoa_wxNSSliderMoveRight(void) = 0;
- virtual void Cocoa_wxNSSliderPageUp(void) = 0;
- virtual void Cocoa_wxNSSliderPageDown(void) = 0;
virtual void CocoaNotification_startTracking(WX_NSNotification notification) = 0;
virtual void CocoaNotification_continueTracking(WX_NSNotification notification) = 0;
virtual void CocoaNotification_stopTracking(WX_NSNotification notification) = 0;
- virtual ~wxCocoaNSSlider() { }
+ static SEL GetLastResponderSelector()
+ { return sm_lastResponderSelector; }
protected:
- static const wxObjcAutoRefFromAlloc<struct objc_object*> sm_cocoaTarget;
- static struct objc_object *sm_cocoaObserver;
-
+ virtual ~wxCocoaNSSlider() { }
+ static SEL sm_lastResponderSelector;
};
#endif
WX_IMPLEMENT_OBJC_INTERFACE_HASHMAP(NSSlider)
-// ============================================================================
-// @class wxNSSliderTarget
-// ============================================================================
-@interface wxNSSliderTarget : NSObject
-{
-}
-
-- (void)wxNSSliderUpArrowKeyDown: (id)sender;
-- (void)wxNSSliderDownArrowKeyDown: (id)sender;
-- (void)wxNSSliderLeftArrowKeyDown: (id)sender;
-- (void)wxNSSliderRightArrowKeyDown: (id)sender;
-- (void)wxNSSliderPageUpKeyDown: (id)sender;
-- (void)wxNSSliderPageDownKeyDown: (id)sender;
-- (void)wxNSSliderMoveUp: (id)sender;
-- (void)wxNSSliderMoveDown: (id)sender;
-- (void)wxNSSliderMoveLeft: (id)sender;
-- (void)wxNSSliderMoveRight: (id)sender;
-- (void)wxNSSliderPageUp: (id)sender;
-- (void)wxNSSliderPageDown: (id)sender;
-@end // wxNSSliderTarget
-
-@implementation wxNSSliderTarget : NSObject
-
-- (void)wxNSSliderUpArrowKeyDown: (id)sender
-{
- wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
- wxCHECK_RET(slider,wxT("wxNSSliderUpArrowKeyDown received without associated wx object"));
- slider->Cocoa_wxNSSliderUpArrowKeyDown();
-}
-
-- (void)wxNSSliderDownArrowKeyDown: (id)sender
-{
- wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
- wxCHECK_RET(slider,wxT("wxNSSliderDownArrowKeyDown received without associated wx object"));
- slider->Cocoa_wxNSSliderDownArrowKeyDown();
-}
-
-- (void)wxNSSliderLeftArrowKeyDown: (id)sender
-{
- wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
- wxCHECK_RET(slider,wxT("wxNSSliderLeftArrowKeyDown received without associated wx object"));
- slider->Cocoa_wxNSSliderLeftArrowKeyDown();
-}
-
-- (void)wxNSSliderRightArrowKeyDown: (id)sender
-{
- wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
- wxCHECK_RET(slider,wxT("wxNSSliderRightArrowKeyDown received without associated wx object"));
- slider->Cocoa_wxNSSliderRightArrowKeyDown();
-}
-
-- (void)wxNSSliderPageUpKeyDown: (id)sender
+class wxCocoaNSSliderLastSelectorChanger
{
- wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
- wxCHECK_RET(slider,wxT("wxNSSliderPageUpKeyDown received without associated wx object"));
- slider->Cocoa_wxNSSliderPageUpKeyDown();
-}
-
-- (void)wxNSSliderPageDownKeyDown: (id)sender
-{
- wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
- wxCHECK_RET(slider,wxT("wxNSSliderPageDownKeyDown received without associated wx object"));
- slider->Cocoa_wxNSSliderPageDownKeyDown();
-}
-
-- (void)wxNSSliderMoveUp: (id)sender
-{
- wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
- wxCHECK_RET(slider,wxT("wxNSSliderMoveUp received without associated wx object"));
- slider->Cocoa_wxNSSliderMoveUp();
-}
-
-- (void)wxNSSliderMoveDown: (id)sender
-{
- wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
- wxCHECK_RET(slider,wxT("wxNSSliderMoveDown received without associated wx object"));
- slider->Cocoa_wxNSSliderMoveDown();
-}
-
-- (void)wxNSSliderMoveLeft: (id)sender
-{
- wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
- wxCHECK_RET(slider,wxT("wxNSSliderMoveLeft received without associated wx object"));
- slider->Cocoa_wxNSSliderMoveLeft();
-}
-
-- (void)wxNSSliderMoveRight: (id)sender
-{
- wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
- wxCHECK_RET(slider,wxT("wxNSSliderMoveRight received without associated wx object"));
- slider->Cocoa_wxNSSliderMoveRight();
-}
-
-- (void)wxNSSliderPageUp: (id)sender
-{
- wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
- wxCHECK_RET(slider,wxT("wxNSSliderPageUp received without associated wx object"));
- slider->Cocoa_wxNSSliderPageUp();
-}
-
-- (void)wxNSSliderPageDown: (id)sender
-{
- wxCocoaNSSlider *slider = wxCocoaNSSlider::GetFromCocoa(sender);
- wxCHECK_RET(slider,wxT("wxNSSliderPageDown received without associated wx object"));
- slider->Cocoa_wxNSSliderPageDown();
-}
-
-@end // implementation wxNSSliderTarget
+public:
+ wxCocoaNSSliderLastSelectorChanger(SEL newSelector)
+ {
+ m_savedResponderSelector = wxCocoaNSSlider::sm_lastResponderSelector;
+ wxCocoaNSSlider::sm_lastResponderSelector = newSelector;
+ }
+ ~wxCocoaNSSliderLastSelectorChanger()
+ {
+ wxCocoaNSSlider::sm_lastResponderSelector = m_savedResponderSelector;
+ }
+private:
+ SEL m_savedResponderSelector;
+// Don't allow any default or copy construction
+ wxCocoaNSSliderLastSelectorChanger();
+ wxCocoaNSSliderLastSelectorChanger(const wxCocoaNSSliderLastSelectorChanger&);
+ void operator=(const wxCocoaNSSliderLastSelectorChanger&);
+};
// ============================================================================
// @class WXNSSlider
// ============================================================================
-
@implementation WXNSSlider : NSSlider
// Override to ensure that WXNSSlider gets created with a WXNSSliderCell
return [WX_GET_OBJC_CLASS(WXNSSliderCell) class];
}
+// The following methods are all NSResponder methods which NSSlider responds
+// to in order to change its state and send the action message. We override
+// them simply to record which one was called. This allows code listening
+// only for the action message to determine what caused the action.
+// Note that this is perfectly fine being a global because Cocoa processes
+// events synchronously and only in the main thread.
+
- (void)keyDown:(NSEvent *)theEvent
{
- SEL originalAction = [self action];
- SEL newAction = originalAction;
- NSString *theEventCharacters = [theEvent charactersIgnoringModifiers];
-
- if ([theEventCharacters length] == 1)
- {
- switch ([theEventCharacters characterAtIndex:0])
- {
- case NSUpArrowFunctionKey: newAction = @selector(wxNSSliderUpArrowKeyDown:); break;
- case NSDownArrowFunctionKey: newAction = @selector(wxNSSliderDownArrowKeyDown:); break;
- case NSLeftArrowFunctionKey: newAction = @selector(wxNSSliderLeftArrowKeyDown:); break;
- case NSRightArrowFunctionKey: newAction = @selector(wxNSSliderRightArrowKeyDown:); break;
- case NSPageUpFunctionKey: newAction = @selector(wxNSSliderPageUpKeyDown:); break;
- case NSPageDownFunctionKey: newAction = @selector(wxNSSliderPageDownKeyDown:); break;
- default: break;
- }
- }
-
- [self setAction:newAction];
+ wxCocoaNSSliderLastSelectorChanger savedSelector(_cmd);
[super keyDown:theEvent];
- [self setAction:originalAction];
}
- (void)moveUp:(id)sender
{
- SEL originalAction = [self action];
-
- [self setAction:@selector(wxNSSliderMoveUp:)];
+ wxCocoaNSSliderLastSelectorChanger savedSelector(_cmd);
[super moveUp:sender];
- [self setAction:originalAction];
}
- (void)moveDown:(id)sender
{
- SEL originalAction = [self action];
-
- [self setAction:@selector(wxNSSliderMoveDown:)];
+ wxCocoaNSSliderLastSelectorChanger savedSelector(_cmd);
[super moveDown:sender];
- [self setAction:originalAction];
}
- (void)moveLeft:(id)sender
{
- SEL originalAction = [self action];
-
- [self setAction:@selector(wxNSSliderMoveLeft:)];
+ wxCocoaNSSliderLastSelectorChanger savedSelector(_cmd);
[super moveLeft:sender];
- [self setAction:originalAction];
}
- (void)moveRight:(id)sender
{
- SEL originalAction = [self action];
-
- [self setAction:@selector(wxNSSliderMoveRight:)];
+ wxCocoaNSSliderLastSelectorChanger savedSelector(_cmd);
[super moveRight:sender];
- [self setAction:originalAction];
}
- (void)pageUp:(id)sender
{
- SEL originalAction = [self action];
-
- [self setAction:@selector(wxNSSliderPageUp:)];
+ wxCocoaNSSliderLastSelectorChanger savedSelector(_cmd);
[super pageUp:sender];
- [self setAction:originalAction];
}
- (void)pageDown:(id)sender
{
- SEL originalAction = [self action];
-
- [self setAction:@selector(wxNSSliderPageDown:)];
+ wxCocoaNSSliderLastSelectorChanger savedSelector(_cmd);
[super pageDown:sender];
- [self setAction:originalAction];
}
@end
// @class WXNSSliderCell
// ============================================================================
-#define kwxNSSliderStartTracking @"wxNSSliderStartTracking"
-#define kwxNSSliderContinueTracking @"wxNSSliderContinueTracking"
-#define kwxNSSliderStopTracking @"wxNSSliderStopTracking"
-
@implementation WXNSSliderCell : NSSliderCell
- (BOOL)startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView
{
// ============================================================================
// class wxCocoaNSSlider
// ============================================================================
-const wxObjcAutoRefFromAlloc<struct objc_object*> wxCocoaNSSlider::sm_cocoaTarget = [[wxNSSliderTarget alloc] init];
+SEL wxCocoaNSSlider::sm_lastResponderSelector;
void wxCocoaNSSlider::AssociateNSSlider(WX_NSSlider cocoaNSSlider)
{
if(cocoaNSSlider)
{
sm_cocoaHash.insert(wxCocoaNSSliderHash::value_type(cocoaNSSlider,this));
- [cocoaNSSlider setTarget:sm_cocoaTarget];
}
}
#include "wx/app.h"
#endif //WX_PRECOMP
+#import <Foundation/NSString.h>
#include "wx/cocoa/objc/NSSlider.h"
+#import <AppKit/NSEvent.h>
+#import <AppKit/NSWindow.h>
IMPLEMENT_DYNAMIC_CLASS(wxSlider, wxControl)
BEGIN_EVENT_TABLE(wxSlider, wxSliderBase)
DisassociateNSSlider(GetNSSlider());
}
+void wxSlider::AssociateNSSlider(WX_NSSlider theSlider)
+{
+ wxCocoaNSSlider::AssociateNSSlider(theSlider);
+ // Set the target/action.. we don't really need to unset these
+ [theSlider setTarget:wxCocoaNSControl::sm_cocoaTarget];
+ [theSlider setAction:@selector(wxNSControlAction:)];
+}
+
void wxSlider::ProcessEventType(wxEventType commandType)
{
wxScrollEvent event(commandType, GetId(), GetValue(), HasFlag(wxSL_VERTICAL)?wxVERTICAL:wxHORIZONTAL);
GetEventHandler()->ProcessEvent(event);
}
+static inline wxEventType wxSliderEventTypeForKeyFromEvent(NSEvent *theEvent)
+{
+ NSString *theEventCharacters = [theEvent charactersIgnoringModifiers];
+
+ if ([theEventCharacters length] == 1)
+ {
+ switch ([theEventCharacters characterAtIndex:0])
+ {
+ case NSUpArrowFunctionKey:
+ case NSRightArrowFunctionKey: return wxEVT_SCROLL_PAGEDOWN;
+ case NSDownArrowFunctionKey:
+ case NSLeftArrowFunctionKey: return wxEVT_SCROLL_PAGEUP;
+ case NSPageUpFunctionKey: return wxEVT_SCROLL_BOTTOM;
+ case NSPageDownFunctionKey: return wxEVT_SCROLL_TOP;
+ }
+ }
+ // Overload wxEVT_ANY to mean we can't determine the event type.
+ return wxEVT_ANY;
+}
+
+void wxSlider::CocoaTarget_action()
+{
+ wxEventType sliderEventType;
+ SEL theSelector = wxCocoaNSSlider::GetLastResponderSelector();
+
+ if( theSelector == @selector(moveUp:)
+ || theSelector == @selector(moveRight:))
+ sliderEventType = wxEVT_SCROLL_PAGEDOWN;
+ else if( theSelector == @selector(moveDown:)
+ || theSelector == @selector(moveLeft:))
+ sliderEventType = wxEVT_SCROLL_PAGEUP;
+ else if( theSelector == @selector(pageUp:))
+ sliderEventType = wxEVT_SCROLL_BOTTOM;
+ else if( theSelector == @selector(pageDown:))
+ sliderEventType = wxEVT_SCROLL_TOP;
+ else if( theSelector == @selector(keyDown:))
+ // This case should ideally never be reached.
+ sliderEventType = wxSliderEventTypeForKeyFromEvent([[GetNSSlider() window] currentEvent]);
+ else
+ // Don't generate an event.
+ return;
+ if(sliderEventType != wxEVT_ANY)
+ ProcessEventType(sliderEventType);
+}
+
void wxSlider::CocoaNotification_startTracking(WX_NSNotification notification)
{
CocoaNotification_continueTracking(notification);