From: David Elliott Date: Wed, 15 Aug 2007 04:12:44 +0000 (+0000) Subject: Further simplificiation of the NSSlider/wxSlider interface such that the X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/4f46c20bc4cc5be9b358a6e6caad39c1f8498cae Further simplificiation of the NSSlider/wxSlider interface such that the 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 --- diff --git a/include/wx/cocoa/NSSlider.h b/include/wx/cocoa/NSSlider.h index 3543f3b8d8..9dc637dc5e 100644 --- a/include/wx/cocoa/NSSlider.h +++ b/include/wx/cocoa/NSSlider.h @@ -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 sm_cocoaTarget; - static struct objc_object *sm_cocoaObserver; - + virtual ~wxCocoaNSSlider() { } + static SEL sm_lastResponderSelector; }; #endif diff --git a/include/wx/cocoa/slider.h b/include/wx/cocoa/slider.h index 2d2d4aaa1f..1d2a164666 100644 --- a/include/wx/cocoa/slider.h +++ b/include/wx/cocoa/slider.h @@ -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 // ------------------------------------------------------------------------ diff --git a/src/cocoa/NSSlider.mm b/src/cocoa/NSSlider.mm index 5e352332d7..3233c5a55a 100644 --- a/src/cocoa/NSSlider.mm +++ b/src/cocoa/NSSlider.mm @@ -24,120 +24,30 @@ 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 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]; } } diff --git a/src/cocoa/slider.mm b/src/cocoa/slider.mm index c94fc98575..b5041e9949 100644 --- a/src/cocoa/slider.mm +++ b/src/cocoa/slider.mm @@ -21,7 +21,10 @@ #include "wx/app.h" #endif //WX_PRECOMP +#import #include "wx/cocoa/objc/NSSlider.h" +#import +#import 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);