]> git.saurik.com Git - wxWidgets.git/commitdiff
Further simplificiation of the NSSlider/wxSlider interface such that the
authorDavid Elliott <dfe@tgwbd.org>
Wed, 15 Aug 2007 04:12:44 +0000 (04:12 +0000)
committerDavid Elliott <dfe@tgwbd.org>
Wed, 15 Aug 2007 04:12:44 +0000 (04:12 +0000)
various responder methods don't change the controls action but instead send
all actions through the normal wxCocoaNSControl action handling mechanism.
To determine what caused the action we save the message selector in a global
variable (safe since Cocoa does single-threaded event handling).

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@48078 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/cocoa/NSSlider.h
include/wx/cocoa/slider.h
src/cocoa/NSSlider.mm
src/cocoa/slider.mm

index 3543f3b8d8ceba20a9275c2444091d31678d41d5..9dc637dc5e2639a12ad6f8223ae180a849d26d07 100644 (file)
@@ -2,7 +2,7 @@
 // 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.
@@ -20,34 +20,28 @@ DECLARE_WXCOCOA_OBJC_CLASS(NSSlider);
 
 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
index 2d2d4aaa1fec167d11a69aa8874478154ae0ef27..1d2a164666a2f98c242d04e73a9999aa4724dde7 100644 (file)
@@ -54,25 +54,20 @@ public:
 // Cocoa callbacks
 // ------------------------------------------------------------------------
 protected:
-    // from NSSLider
+    // Override this so we can use wxCocoaNSControl's target
+    void AssociateNSSlider(WX_NSSlider theSlider);
+
+    // Helper method to do the real work
     virtual void ProcessEventType(wxEventType commandType);
-    virtual void Cocoa_wxNSSliderUpArrowKeyDown(void) { ProcessEventType(wxEVT_SCROLL_PAGEDOWN); }
-    virtual void Cocoa_wxNSSliderDownArrowKeyDown(void) { ProcessEventType(wxEVT_SCROLL_PAGEUP); }
-    virtual void Cocoa_wxNSSliderLeftArrowKeyDown(void) { ProcessEventType(wxEVT_SCROLL_PAGEUP); }
-    virtual void Cocoa_wxNSSliderRightArrowKeyDown(void) { ProcessEventType(wxEVT_SCROLL_PAGEDOWN); }
-    virtual void Cocoa_wxNSSliderPageUpKeyDown(void) { ProcessEventType(wxEVT_SCROLL_BOTTOM); }
-    virtual void Cocoa_wxNSSliderPageDownKeyDown(void) { ProcessEventType(wxEVT_SCROLL_TOP); }
-    virtual void Cocoa_wxNSSliderMoveUp(void) { ProcessEventType(wxEVT_SCROLL_PAGEDOWN); }
-    virtual void Cocoa_wxNSSliderMoveDown(void) { ProcessEventType(wxEVT_SCROLL_PAGEUP); }
-    virtual void Cocoa_wxNSSliderMoveLeft(void) { ProcessEventType(wxEVT_SCROLL_PAGEUP); }
-    virtual void Cocoa_wxNSSliderMoveRight(void) { ProcessEventType(wxEVT_SCROLL_PAGEDOWN); }
-    virtual void Cocoa_wxNSSliderPageUp(void) { ProcessEventType(wxEVT_SCROLL_BOTTOM); }
-    virtual void Cocoa_wxNSSliderPageDown(void) { ProcessEventType(wxEVT_SCROLL_TOP); }
+
+    // from wxCocoaNSControl:
+    virtual void CocoaTarget_action();
+
+    // from wxCocoaNSSlider:
     virtual void CocoaNotification_startTracking(WX_NSNotification notification);
     virtual void CocoaNotification_continueTracking(WX_NSNotification notification);
     virtual void CocoaNotification_stopTracking(WX_NSNotification notification);
-    
-    
+
 // ------------------------------------------------------------------------
 // Implementation
 // ------------------------------------------------------------------------
index 5e352332d7164e768cfc5fac9b4deab6859e59fa..3233c5a55a13d18174a41fa4a0a9b83e69619895 100644 (file)
 
 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
@@ -146,83 +56,53 @@ WX_IMPLEMENT_OBJC_INTERFACE_HASHMAP(NSSlider)
     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
@@ -232,10 +112,6 @@ WX_IMPLEMENT_GET_OBJC_CLASS(WXNSSlider,NSSlider)
 // @class WXNSSliderCell
 // ============================================================================
 
-#define kwxNSSliderStartTracking    @"wxNSSliderStartTracking"
-#define kwxNSSliderContinueTracking @"wxNSSliderContinueTracking"
-#define kwxNSSliderStopTracking     @"wxNSSliderStopTracking"
-
 @implementation WXNSSliderCell : NSSliderCell
 - (BOOL)startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView
 {
@@ -273,15 +149,14 @@ WX_IMPLEMENT_GET_OBJC_CLASS(WXNSSliderCell,NSSliderCell)
 // ============================================================================
 // 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];
     }
 }
 
index c94fc98575d0c7edb2d49792e4eee6ffee2c7ec0..b5041e9949fcc82354f54e2d28d6590c492e5847 100644 (file)
     #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)
@@ -85,6 +88,14 @@ wxSlider::~wxSlider()
     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);
@@ -92,6 +103,51 @@ void wxSlider::ProcessEventType(wxEventType commandType)
     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);