1///////////////////////////////////////////////////////////////////////////// 2// Name: src/cocoa/slider.mm 3// Purpose: wxSlider 4// Author: David Elliott 5// Mark Oxenham 6// Modified by: 7// Created: 2003/06/19 8// RCS-ID: $Id: slider.mm 48590 2007-09-06 16:47:01Z DE $ 9// Copyright: (c) 2003 David Elliott 10// (c) 2007 Software 2000 Ltd. 11// Licence: wxWidgets licence 12///////////////////////////////////////////////////////////////////////////// 13 14#include "wx/wxprec.h" 15 16#if wxUSE_SLIDER 17 18#include "wx/slider.h" 19 20#ifndef WX_PRECOMP 21 #include "wx/app.h" 22#endif //WX_PRECOMP 23 24#import <Foundation/NSString.h> 25#include "wx/cocoa/objc/NSSlider.h" 26#import <AppKit/NSEvent.h> 27#import <AppKit/NSWindow.h> 28 29IMPLEMENT_DYNAMIC_CLASS(wxSlider, wxControl) 30 BEGIN_EVENT_TABLE(wxSlider, wxSliderBase) 31END_EVENT_TABLE() 32WX_IMPLEMENT_COCOA_OWNER(wxSlider,NSSlider,NSControl,NSView) 33 34 35inline void AdjustDimension( 36 bool isTicksStyle, 37 int &pos, 38 wxSize &size, 39 int (wxSize::*GetDimension)() const, 40 void (wxSize::*SetDimension)(int)) 41{ 42 const int dimension = (size.*GetDimension)(); 43 const int minSize = (isTicksStyle) ? 23 : 20; 44 45 // prevent clipping of overly "thin" sliders 46 if (dimension < minSize) 47 { 48 (size.*SetDimension)(minSize); 49 } 50 51 // move the slider control to the middle of the dimension that is not 52 // being used to define its length 53 pos += (dimension - (size.*GetDimension)() + 1) / 2; 54} 55 56bool wxSlider::Create(wxWindow *parent, wxWindowID winid, 57 int value, int minValue, int maxValue, 58 const wxPoint& pos, const wxSize& size, long style, 59 const wxValidator& validator, const wxString& name) 60{ 61 wxSize adjustedSize(size); 62 wxPoint adjustedPos(pos); 63 const bool isTicksStyle = (style & wxSL_TICKS) != 0; 64 65 if ((style & wxSL_HORIZONTAL) && (size.GetHeight() != wxDefaultCoord)) 66 { 67 AdjustDimension(isTicksStyle, adjustedPos.y, adjustedSize, &wxSize::GetHeight, &wxSize::SetHeight); 68 } 69 else if ((style & wxSL_VERTICAL) && (size.GetWidth() != wxDefaultCoord)) 70 { 71 AdjustDimension(isTicksStyle, adjustedPos.x, adjustedSize, &wxSize::GetWidth, &wxSize::SetWidth); 72 } 73 74 if(!CreateControl(parent,winid,adjustedPos,adjustedSize,style,validator,name)) 75 return false; 76 SetNSSlider([[WX_GET_OBJC_CLASS(WXNSSlider) alloc] initWithFrame: MakeDefaultNSRect(adjustedSize)]); 77 [m_cocoaNSView release]; 78 79 if(m_parent) 80 m_parent->CocoaAddChild(this); 81 SetInitialFrameRect(adjustedPos,adjustedSize); 82 83 SetRange(minValue, maxValue); 84 SetValue(value); 85 86 // -1 default for wxSL_AUTOTICKS == false 87 int tickMarks = -1; 88 // minValue > maxValue not handled, tickMarks set to 0 89 if ( style & wxSL_AUTOTICKS ) 90 tickMarks = ((maxValue - minValue >= 0) ? (maxValue - minValue) : 0); 91 // arg2 needed a value, doesnt do anything 92 SetTickFreq(tickMarks,1); 93 94 return true; 95} 96 97wxSlider::~wxSlider() 98{ 99 DisassociateNSSlider(GetNSSlider()); 100} 101 102// NOTE: We don't derive from wxCocoaNSSlider in 2.8 due to ABI 103 104void wxSlider::AssociateNSSlider(WX_NSSlider theSlider) 105{ 106 // Set the target/action.. we don't really need to unset these 107 [theSlider setTarget:wxCocoaNSControl::sm_cocoaTarget]; 108 [theSlider setAction:@selector(wxNSControlAction:)]; 109} 110 111void wxSlider::DisassociateNSSlider(WX_NSSlider theSlider) 112{ 113} 114 115void wxSlider::ProcessEventType(wxEventType commandType) 116{ 117 wxScrollEvent event(commandType, GetId(), GetValue(), HasFlag(wxSL_VERTICAL)?wxVERTICAL:wxHORIZONTAL); 118 event.SetEventObject(this); 119 GetEventHandler()->ProcessEvent(event); 120} 121 122static inline wxEventType wxSliderEventTypeForKeyFromEvent(NSEvent *theEvent) 123{ 124 NSString *theEventCharacters = [theEvent charactersIgnoringModifiers]; 125 126 if ([theEventCharacters length] == 1) 127 { 128 switch ([theEventCharacters characterAtIndex:0]) 129 { 130 case NSUpArrowFunctionKey: 131 case NSRightArrowFunctionKey: return wxEVT_SCROLL_PAGEDOWN; 132 case NSDownArrowFunctionKey: 133 case NSLeftArrowFunctionKey: return wxEVT_SCROLL_PAGEUP; 134 case NSPageUpFunctionKey: return wxEVT_SCROLL_BOTTOM; 135 case NSPageDownFunctionKey: return wxEVT_SCROLL_TOP; 136 } 137 } 138 return wxEVT_NULL; 139} 140 141void wxSlider::CocoaTarget_action() 142{ 143 wxEventType sliderEventType; 144 SEL theSelector = wxCocoaNSSlider::GetLastResponderSelector(); 145 146 if( theSelector == @selector(moveUp:) 147 || theSelector == @selector(moveRight:)) 148 sliderEventType = wxEVT_SCROLL_PAGEDOWN; 149 else if( theSelector == @selector(moveDown:) 150 || theSelector == @selector(moveLeft:)) 151 sliderEventType = wxEVT_SCROLL_PAGEUP; 152 else if( theSelector == @selector(pageUp:)) 153 sliderEventType = wxEVT_SCROLL_BOTTOM; 154 else if( theSelector == @selector(pageDown:)) 155 sliderEventType = wxEVT_SCROLL_TOP; 156 else if( theSelector == @selector(keyDown:)) 157 // This case should ideally never be reached. 158 sliderEventType = wxSliderEventTypeForKeyFromEvent([[GetNSSlider() window] currentEvent]); 159 else 160 // Don't generate an event. 161 return; 162 if(sliderEventType != wxEVT_NULL) 163 ProcessEventType(sliderEventType); 164} 165 166void wxSlider::CocoaNotification_startTracking(WX_NSNotification notification) 167{ 168 CocoaNotification_continueTracking(notification); 169} 170 171void wxSlider::CocoaNotification_continueTracking(WX_NSNotification notification) 172{ 173 const double realValue = [GetNSSlider() doubleValue]; 174 175 if (realValue != [GetNSSlider() intValue]) 176 { 177 SetValue(rint(realValue)); 178 } 179 180 ProcessEventType(wxEVT_SCROLL_THUMBTRACK); 181} 182 183void wxSlider::CocoaNotification_stopTracking(WX_NSNotification notification) 184{ 185 ProcessEventType(wxEVT_SCROLL_THUMBRELEASE); 186} 187 188int wxSlider::GetValue() const 189{ 190 return [GetNSSlider() intValue]; 191} 192 193void wxSlider::SetValue(int value) 194{ 195 [GetNSSlider() setIntValue:value]; 196} 197 198void wxSlider::SetRange(int minValue, int maxValue) 199{ 200 [GetNSSlider() setMinValue:minValue]; 201 [GetNSSlider() setMaxValue:maxValue]; 202} 203 204int wxSlider::GetMin() const 205{ 206 return [GetNSSlider() minValue]; 207} 208 209int wxSlider::GetMax() const 210{ 211 return [GetNSSlider() maxValue]; 212} 213 214void wxSlider::SetTickFreq(int n, int pos) 215{ 216 const int numTicks = (n > 0) ? ((GetMax() - GetMin()) / n) + 1 : 0; 217 [GetNSSlider() setNumberOfTickMarks:numTicks]; 218} 219 220int wxSlider::GetTickFreq() const 221{ 222 const int numTicks = [GetNSSlider() numberOfTickMarks]; 223 return ((numTicks != 0) ? (GetMax() - GetMin()) / (numTicks - 1) : 0); 224} 225 226void wxSlider::SetTickPos(int pos) 227{ 228 NSTickMarkPosition thePos = NSTickMarkBelow; 229 wxSize size = GetSize(); 230 231 if (size.GetWidth() < size.GetHeight()) // NSSlider isVertical method can return -1 if it has not been displayed. 232 { 233 thePos = (pos != 1) ? NSTickMarkLeft : NSTickMarkRight; 234 } 235 else 236 { 237 thePos = (pos != 1) ? NSTickMarkBelow : NSTickMarkAbove; 238 } 239 240 [GetNSSlider() setTickMarkPosition:thePos]; 241} 242 243void wxSlider::SetLineSize(int lineSize) 244{ 245 // to do 246} 247 248void wxSlider::SetPageSize(int pageSize) 249{ 250 // to do 251} 252 253int wxSlider::GetLineSize() const 254{ 255 return 1; 256} 257 258int wxSlider::GetPageSize() const 259{ 260 return 1; 261} 262 263int wxSlider::GetThumbLength() const 264{ 265 return 1; 266} 267 268void wxSlider::SetThumbLength(int lenPixels) 269{ 270 // to do 271} 272 273#endif // wxUSE_SLIDER 274