1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/cocoa/slider.mm
4 // Author: David Elliott
9 // Copyright: (c) 2003 David Elliott
10 // (c) 2007 Software 2000 Ltd.
11 // Licence: wxWindows licence
12 /////////////////////////////////////////////////////////////////////////////
14 #include "wx/wxprec.h"
18 #include "wx/slider.h"
24 #import <Foundation/NSString.h>
25 #include "wx/cocoa/objc/NSSlider.h"
26 #import <AppKit/NSEvent.h>
27 #import <AppKit/NSWindow.h>
29 BEGIN_EVENT_TABLE(wxSlider, wxSliderBase)
31 WX_IMPLEMENT_COCOA_OWNER(wxSlider,NSSlider,NSControl,NSView)
34 inline void AdjustDimension(
38 int (wxSize::*GetDimension)() const,
39 void (wxSize::*SetDimension)(int))
41 const int dimension = (size.*GetDimension)();
42 const int minSize = (isTicksStyle) ? 23 : 20;
44 // prevent clipping of overly "thin" sliders
45 if (dimension < minSize)
47 (size.*SetDimension)(minSize);
50 // move the slider control to the middle of the dimension that is not
51 // being used to define its length
52 pos += (dimension - (size.*GetDimension)() + 1) / 2;
55 bool wxSlider::Create(wxWindow *parent, wxWindowID winid,
56 int value, int minValue, int maxValue,
57 const wxPoint& pos, const wxSize& size, long style,
58 const wxValidator& validator, const wxString& name)
60 wxSize adjustedSize(size);
61 wxPoint adjustedPos(pos);
62 const bool isTicksStyle = (style & wxSL_TICKS) != 0;
64 if ((style & wxSL_HORIZONTAL) && (size.GetHeight() != wxDefaultCoord))
66 AdjustDimension(isTicksStyle, adjustedPos.y, adjustedSize, &wxSize::GetHeight, &wxSize::SetHeight);
68 else if ((style & wxSL_VERTICAL) && (size.GetWidth() != wxDefaultCoord))
70 AdjustDimension(isTicksStyle, adjustedPos.x, adjustedSize, &wxSize::GetWidth, &wxSize::SetWidth);
73 if(!CreateControl(parent,winid,adjustedPos,adjustedSize,style,validator,name))
75 SetNSSlider([[WX_GET_OBJC_CLASS(WXNSSlider) alloc] initWithFrame: MakeDefaultNSRect(adjustedSize)]);
76 [m_cocoaNSView release];
79 m_parent->CocoaAddChild(this);
80 SetInitialFrameRect(adjustedPos,adjustedSize);
82 SetRange(minValue, maxValue);
85 // -1 default for wxSL_AUTOTICKS == false
87 // minValue > maxValue not handled, tickMarks set to 0
88 if ( style & wxSL_AUTOTICKS )
89 tickMarks = ((maxValue - minValue >= 0) ? (maxValue - minValue) : 0);
90 // arg2 needed a value, doesnt do anything
91 SetTickFreq(tickMarks,1);
98 DisassociateNSSlider(GetNSSlider());
101 void wxSlider::AssociateNSSlider(WX_NSSlider theSlider)
103 wxCocoaNSSlider::AssociateNSSlider(theSlider);
104 // Set the target/action.. we don't really need to unset these
105 [theSlider setTarget:wxCocoaNSControl::sm_cocoaTarget];
106 [theSlider setAction:@selector(wxNSControlAction:)];
109 void wxSlider::ProcessEventType(wxEventType commandType)
111 wxScrollEvent event(commandType, GetId(), GetValue(), HasFlag(wxSL_VERTICAL)?wxVERTICAL:wxHORIZONTAL);
112 event.SetEventObject(this);
113 HandleWindowEvent(event);
116 static inline wxEventType wxSliderEventTypeForKeyFromEvent(NSEvent *theEvent)
118 NSString *theEventCharacters = [theEvent charactersIgnoringModifiers];
120 if ([theEventCharacters length] == 1)
122 switch ([theEventCharacters characterAtIndex:0])
124 case NSUpArrowFunctionKey:
125 case NSRightArrowFunctionKey: return wxEVT_SCROLL_PAGEDOWN;
126 case NSDownArrowFunctionKey:
127 case NSLeftArrowFunctionKey: return wxEVT_SCROLL_PAGEUP;
128 case NSPageUpFunctionKey: return wxEVT_SCROLL_BOTTOM;
129 case NSPageDownFunctionKey: return wxEVT_SCROLL_TOP;
132 // Overload wxEVT_ANY to mean we can't determine the event type.
136 void wxSlider::CocoaTarget_action()
138 wxEventType sliderEventType;
139 SEL theSelector = wxCocoaNSSlider::GetLastResponderSelector();
141 if( theSelector == @selector(moveUp:)
142 || theSelector == @selector(moveRight:))
143 sliderEventType = wxEVT_SCROLL_PAGEDOWN;
144 else if( theSelector == @selector(moveDown:)
145 || theSelector == @selector(moveLeft:))
146 sliderEventType = wxEVT_SCROLL_PAGEUP;
147 else if( theSelector == @selector(pageUp:))
148 sliderEventType = wxEVT_SCROLL_BOTTOM;
149 else if( theSelector == @selector(pageDown:))
150 sliderEventType = wxEVT_SCROLL_TOP;
151 else if( theSelector == @selector(keyDown:))
152 // This case should ideally never be reached.
153 sliderEventType = wxSliderEventTypeForKeyFromEvent([[GetNSSlider() window] currentEvent]);
155 // Don't generate an event.
157 if(sliderEventType != wxEVT_ANY)
158 ProcessEventType(sliderEventType);
161 void wxSlider::CocoaNotification_startTracking(WX_NSNotification notification)
163 CocoaNotification_continueTracking(notification);
166 void wxSlider::CocoaNotification_continueTracking(WX_NSNotification notification)
168 const double realValue = [GetNSSlider() doubleValue];
170 if (realValue != [GetNSSlider() intValue])
172 SetValue(rint(realValue));
175 ProcessEventType(wxEVT_SCROLL_THUMBTRACK);
178 void wxSlider::CocoaNotification_stopTracking(WX_NSNotification notification)
180 ProcessEventType(wxEVT_SCROLL_THUMBRELEASE);
183 int wxSlider::GetValue() const
185 return [GetNSSlider() intValue];
188 void wxSlider::SetValue(int value)
190 [GetNSSlider() setIntValue:value];
193 void wxSlider::SetRange(int minValue, int maxValue)
195 [GetNSSlider() setMinValue:minValue];
196 [GetNSSlider() setMaxValue:maxValue];
199 int wxSlider::GetMin() const
201 return [GetNSSlider() minValue];
204 int wxSlider::GetMax() const
206 return [GetNSSlider() maxValue];
209 void wxSlider::SetTickFreq(int n, int pos)
211 const int numTicks = (n > 0) ? ((GetMax() - GetMin()) / n) + 1 : 0;
212 [GetNSSlider() setNumberOfTickMarks:numTicks];
215 int wxSlider::GetTickFreq() const
217 const int numTicks = [GetNSSlider() numberOfTickMarks];
218 return ((numTicks != 0) ? (GetMax() - GetMin()) / (numTicks - 1) : 0);
221 void wxSlider::SetTickPos(int pos)
223 NSTickMarkPosition thePos = NSTickMarkBelow;
224 wxSize size = GetSize();
226 if (size.GetWidth() < size.GetHeight()) // NSSlider isVertical method can return -1 if it has not been displayed.
228 thePos = (pos != 1) ? NSTickMarkLeft : NSTickMarkRight;
232 thePos = (pos != 1) ? NSTickMarkBelow : NSTickMarkAbove;
235 [GetNSSlider() setTickMarkPosition:thePos];
238 void wxSlider::SetLineSize(int lineSize)
243 void wxSlider::SetPageSize(int pageSize)
248 int wxSlider::GetLineSize() const
253 int wxSlider::GetPageSize() const
258 int wxSlider::GetThumbLength() const
263 void wxSlider::SetThumbLength(int lenPixels)
268 #endif // wxUSE_SLIDER