]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/slider.cpp
cleanup
[wxWidgets.git] / src / mac / carbon / slider.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: slider.cpp
3 // Purpose: wxSlider
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 1998-01-01
7 // RCS-ID: $Id$
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "slider.h"
14 #endif
15
16 #include "wx/wxprec.h"
17
18 #if wxUSE_SLIDER
19
20 #include "wx/slider.h"
21 #include "wx/mac/uma.h"
22
23 IMPLEMENT_DYNAMIC_CLASS(wxSlider, wxControl)
24
25 BEGIN_EVENT_TABLE(wxSlider, wxControl)
26 END_EVENT_TABLE()
27
28 // The dimensions of the different styles of sliders (From Aqua document)
29 #define wxSLIDER_DIMENSIONACROSS 15
30 #define wxSLIDER_DIMENSIONACROSS_WITHTICKMARKS 24
31 #define wxSLIDER_DIMENSIONACROSS_ARROW 18
32
33 // Distance between slider and text
34 #define wxSLIDER_BORDERTEXT 5
35
36 /* NB! The default orientation for a slider is horizontal however if the user specifies
37 * some slider styles but dosen't specify the orientation we have to assume he wants a
38 * horizontal one. Therefore in this file when testing for the sliders orientation
39 * vertical is tested for if this is not set then we use the horizontal one
40 * eg. if(GetWindowStyle() & wxSL_VERTICAL) {} else { horizontal case }>
41 */
42
43 // Slider
44 wxSlider::wxSlider()
45 {
46 m_pageSize = 1;
47 m_lineSize = 1;
48 m_rangeMax = 0;
49 m_rangeMin = 0;
50 m_tickFreq = 0;
51 }
52
53 bool wxSlider::Create(wxWindow *parent, wxWindowID id,
54 int value, int minValue, int maxValue,
55 const wxPoint& pos,
56 const wxSize& size, long style,
57 const wxValidator& validator,
58 const wxString& name)
59 {
60 m_macIsUserPane = false ;
61
62 if ( !wxControl::Create(parent, id, pos, size, style, validator, name) )
63 return false;
64
65 m_macMinimumStatic = NULL ;
66 m_macMaximumStatic = NULL ;
67 m_macValueStatic = NULL ;
68
69 m_lineSize = 1;
70 m_tickFreq = 0;
71
72 m_rangeMax = maxValue;
73 m_rangeMin = minValue;
74
75 m_pageSize = (int)((maxValue-minValue)/10);
76
77 Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ;
78
79 //
80 // NB: (RN) Ticks here are sometimes off in the GUI if there
81 // is not as many ticks as there are values
82 //
83 UInt16 tickMarks = 0 ;
84 if ( style & wxSL_AUTOTICKS )
85 tickMarks = (maxValue - minValue) + 1; //+1 for the 0 value
86
87 while (tickMarks > 20)
88 tickMarks /= 5; //keep the number of tickmarks from becoming unwieldly
89
90 m_peer = new wxMacControl(this) ;
91 verify_noerr ( CreateSliderControl( MAC_WXHWND(parent->MacGetTopLevelWindowRef()) , &bounds ,
92 value , minValue , maxValue , kControlSliderPointsDownOrRight , tickMarks , true /* liveTracking */ ,
93 GetwxMacLiveScrollbarActionProc() , m_peer->GetControlRefAddr() ) );
94
95
96 if(style & wxSL_VERTICAL) {
97 SetSizeHints(10, -1, 10, -1); // Forces SetSize to use the proper width
98 }
99 else {
100 SetSizeHints(-1, 10, -1, 10); // Forces SetSize to use the proper height
101 }
102 // NB! SetSizeHints is overloaded by wxSlider and will substitute 10 with the
103 // proper dimensions, it also means other people cannot bugger the slider with
104 // other values
105
106 if(style & wxSL_LABELS)
107 {
108 m_macMinimumStatic = new wxStaticText( parent, wxID_ANY, wxEmptyString );
109 m_macMaximumStatic = new wxStaticText( parent, wxID_ANY, wxEmptyString );
110 m_macValueStatic = new wxStaticText( parent, wxID_ANY, wxEmptyString );
111 SetRange(minValue, maxValue);
112 SetValue(value);
113 }
114
115 MacPostControlCreate(pos,size) ;
116
117 return true;
118 }
119
120 wxSlider::~wxSlider()
121 {
122 // this is a special case, as we had to add windows as siblings we are
123 // responsible for their disposal, but only if we are not part of a DestroyAllChildren
124 if ( m_parent && m_parent->IsBeingDeleted() == false )
125 {
126 delete m_macMinimumStatic ;
127 delete m_macMaximumStatic ;
128 delete m_macValueStatic ;
129 }
130 }
131
132 int wxSlider::GetValue() const
133 {
134 // We may need to invert the value returned by the widget
135 return ValueInvertOrNot( m_peer->GetValue() ) ;
136 }
137
138 void wxSlider::SetValue(int value)
139 {
140 wxString valuestring ;
141 valuestring.Printf( wxT("%d") , value ) ;
142 if ( m_macValueStatic )
143 m_macValueStatic->SetLabel( valuestring ) ;
144
145 // We only invert for the setting of the actual native widget
146 m_peer->SetValue( ValueInvertOrNot ( value ) ) ;
147 }
148
149 void wxSlider::SetRange(int minValue, int maxValue)
150 {
151 wxString value;
152
153 m_rangeMin = minValue;
154 m_rangeMax = maxValue;
155
156 m_peer->SetMinimum( m_rangeMin);
157 m_peer->SetMaximum( m_rangeMax);
158
159 if(m_macMinimumStatic) {
160 value.Printf(wxT("%d"), ValueInvertOrNot( m_rangeMin ) );
161 m_macMinimumStatic->SetLabel(value);
162 }
163 if(m_macMaximumStatic) {
164 value.Printf(wxT("%d"), ValueInvertOrNot( m_rangeMax ) );
165 m_macMaximumStatic->SetLabel(value);
166 }
167 SetValue(m_rangeMin);
168 }
169
170 // For trackbars only
171 void wxSlider::SetTickFreq(int n, int pos)
172 {
173 // TODO
174 m_tickFreq = n;
175 }
176
177 void wxSlider::SetPageSize(int pageSize)
178 {
179 // TODO
180 m_pageSize = pageSize;
181 }
182
183 int wxSlider::GetPageSize() const
184 {
185 return m_pageSize;
186 }
187
188 void wxSlider::ClearSel()
189 {
190 // TODO
191 }
192
193 void wxSlider::ClearTicks()
194 {
195 // TODO
196 }
197
198 void wxSlider::SetLineSize(int lineSize)
199 {
200 m_lineSize = lineSize;
201 // TODO
202 }
203
204 int wxSlider::GetLineSize() const
205 {
206 // TODO
207 return 0;
208 }
209
210 int wxSlider::GetSelEnd() const
211 {
212 // TODO
213 return 0;
214 }
215
216 int wxSlider::GetSelStart() const
217 {
218 // TODO
219 return 0;
220 }
221
222 void wxSlider::SetSelection(int minPos, int maxPos)
223 {
224 // TODO
225 }
226
227 void wxSlider::SetThumbLength(int len)
228 {
229 // TODO
230 }
231
232 int wxSlider::GetThumbLength() const
233 {
234 // TODO
235 return 0;
236 }
237
238 void wxSlider::SetTick(int tickPos)
239 {
240 // TODO
241 }
242
243 void wxSlider::Command (wxCommandEvent & event)
244 {
245 SetValue (event.GetInt());
246 ProcessCommand (event);
247 }
248
249 void wxSlider::MacHandleControlClick( WXWidget control , wxInt16 controlpart, bool mouseStillDown )
250 {
251 // Whatever the native value is, we may need to invert it for calling
252 // SetValue and putting the possibly inverted value in the event
253 SInt16 value = ValueInvertOrNot ( m_peer->GetValue() ) ;
254
255 SetValue( value ) ;
256
257 wxEventType scrollEvent = wxEVT_NULL ;
258
259 scrollEvent = wxEVT_SCROLL_THUMBTRACK;
260
261 wxScrollEvent event(scrollEvent, m_windowId);
262 event.SetPosition(value);
263 event.SetEventObject( this );
264 GetEventHandler()->ProcessEvent(event);
265
266 wxCommandEvent cevent( wxEVT_COMMAND_SLIDER_UPDATED, m_windowId );
267 cevent.SetInt( value );
268 cevent.SetEventObject( this );
269
270 GetEventHandler()->ProcessEvent( cevent );
271 }
272
273 wxInt32 wxSlider::MacControlHit( WXEVENTHANDLERREF handler , WXEVENTREF mevent )
274 {
275 // Whatever the native value is, we may need to invert it for calling
276 // SetValue and putting the possibly inverted value in the event
277 SInt16 value = ValueInvertOrNot ( m_peer->GetValue() ) ;
278
279 SetValue( value ) ;
280
281 wxEventType scrollEvent = wxEVT_NULL ;
282
283 scrollEvent = wxEVT_SCROLL_THUMBRELEASE;
284
285 wxScrollEvent event(scrollEvent, m_windowId);
286 event.SetPosition(value);
287 event.SetEventObject( this );
288 GetEventHandler()->ProcessEvent(event);
289
290 wxCommandEvent cevent( wxEVT_COMMAND_SLIDER_UPDATED, m_windowId );
291 cevent.SetInt( value );
292 cevent.SetEventObject( this );
293
294 GetEventHandler()->ProcessEvent( cevent );
295 return noErr ;
296 }
297
298 /* This is overloaded in wxSlider so that the proper width/height will always be used
299 * for the slider different values would cause redrawing and mouse detection problems */
300 void wxSlider::DoSetSizeHints( int minW, int minH,
301 int maxW , int maxH ,
302 int incW , int incH )
303 {
304 wxSize size = GetBestSize();
305
306 if(GetWindowStyle() & wxSL_VERTICAL) {
307 wxWindow::DoSetSizeHints(size.x, minH, size.x, maxH, incW, incH);
308 }
309 else {
310 wxWindow::DoSetSizeHints(minW, size.y, maxW, size.y, incW, incH);
311 }
312 }
313
314 wxSize wxSlider::DoGetBestSize() const
315 {
316 wxSize size;
317 int textwidth, textheight;
318
319 if(GetWindowStyle() & wxSL_LABELS)
320 {
321 wxString text;
322 int ht, wd;
323
324 // Get maximum text label width and height
325 text.Printf(wxT("%d"), ValueInvertOrNot( m_rangeMin ) );
326 GetTextExtent(text, &textwidth, &textheight);
327 text.Printf(wxT("%d"), ValueInvertOrNot( m_rangeMax ) );
328 GetTextExtent(text, &wd, &ht);
329 if(ht > textheight) {
330 textheight = ht;
331 }
332 if (wd > textwidth) {
333 textwidth = wd;
334 }
335 }
336
337 if(GetWindowStyle() & wxSL_VERTICAL)
338 {
339 if(GetWindowStyle() & wxSL_AUTOTICKS) {
340 size.x = wxSLIDER_DIMENSIONACROSS_WITHTICKMARKS;
341 }
342 else {
343 size.x = wxSLIDER_DIMENSIONACROSS_ARROW;
344 }
345 if(GetWindowStyle() & wxSL_LABELS) {
346 size.x += textwidth + wxSLIDER_BORDERTEXT;
347 }
348 size.y = 150;
349 }
350 else
351 {
352 if(GetWindowStyle() & wxSL_AUTOTICKS) {
353 size.y = wxSLIDER_DIMENSIONACROSS_WITHTICKMARKS;
354 }
355 else {
356 size.y = wxSLIDER_DIMENSIONACROSS_ARROW;
357 }
358 if(GetWindowStyle() & wxSL_LABELS) {
359 size.y += textheight + wxSLIDER_BORDERTEXT;
360 }
361 size.x = 150;
362 }
363 return size;
364 }
365
366 void wxSlider::DoSetSize(int x, int y, int w, int h, int sizeFlags)
367 {
368 int xborder, yborder;
369 int minValWidth, maxValWidth, textwidth, textheight;
370 int sliderBreadth;
371 int width = w;
372
373 xborder = yborder = 0;
374
375 if (GetWindowStyle() & wxSL_LABELS)
376 {
377 //Labels have this control's parent as their parent
378 //so if this control is not at 0,0 relative to the parent
379 //the labels need to know the position of this control
380 //relative to its parent in order to size properly, so
381 //move the control first so we can use GetPosition()
382 wxControl::DoSetSize( x, y , w , h ,sizeFlags ) ;
383
384 wxString text;
385 int ht;
386
387 // Get maximum text label width and height
388 text.Printf(wxT("%d"), ValueInvertOrNot( m_rangeMin ) );
389 GetTextExtent(text, &minValWidth, &textheight);
390 text.Printf(wxT("%d"), ValueInvertOrNot( m_rangeMax ) );
391 GetTextExtent(text, &maxValWidth, &ht);
392 if(ht > textheight) {
393 textheight = ht;
394 }
395 textwidth = (minValWidth > maxValWidth ? minValWidth : maxValWidth);
396
397 xborder = textwidth + wxSLIDER_BORDERTEXT;
398 yborder = textheight + wxSLIDER_BORDERTEXT;
399
400 // Get slider breadth
401 if(GetWindowStyle() & wxSL_AUTOTICKS) {
402 sliderBreadth = wxSLIDER_DIMENSIONACROSS_WITHTICKMARKS;
403 }
404 else {
405 sliderBreadth = wxSLIDER_DIMENSIONACROSS_ARROW;
406 }
407
408 if(GetWindowStyle() & wxSL_VERTICAL)
409 {
410 h = h - yborder ;
411
412 if ( m_macMinimumStatic )
413 m_macMinimumStatic->Move(GetPosition().x + sliderBreadth + wxSLIDER_BORDERTEXT,
414 GetPosition().y + h - yborder);
415 if ( m_macMaximumStatic )
416 m_macMaximumStatic->Move(GetPosition().x + sliderBreadth + wxSLIDER_BORDERTEXT, GetPosition().y + 0);
417 if ( m_macValueStatic )
418 m_macValueStatic->Move(GetPosition().x, GetPosition().y + h );
419 }
420 else
421 {
422 w = w - xborder ;
423 if ( m_macMinimumStatic )
424 m_macMinimumStatic->Move(GetPosition().x + 0, GetPosition().y + sliderBreadth + wxSLIDER_BORDERTEXT);
425 if ( m_macMaximumStatic )
426 m_macMaximumStatic->Move(GetPosition().x + w - (maxValWidth/2),
427 GetPosition().y + sliderBreadth + wxSLIDER_BORDERTEXT);
428 if ( m_macValueStatic )
429 m_macValueStatic->Move(GetPosition().x + w, GetPosition().y + 0);
430 }
431 }
432
433 // yet another hack since this is a composite control
434 // when wxSlider has it's size hardcoded, we're not allowed to
435 // change the size. But when the control has labels, we DO need
436 // to resize the internal Mac control to accomodate the text labels.
437 // We need to trick the wxWidgets resize mechanism so that we can
438 // resize the slider part of the control ONLY.
439
440 // TODO: Can all of this code go in the conditional wxSL_LABELS block?
441
442 int minWidth;
443 minWidth = m_minWidth;
444
445 if (GetWindowStyle() & wxSL_LABELS)
446 {
447 // make sure we don't allow the entire control to be resized accidently
448 if (width == GetSize().x)
449 m_minWidth = -1;
450 }
451 //If the control has labels, we still need to call this again because
452 //the labels alter the control's w and h values.
453 wxControl::DoSetSize( x, y , w , h ,sizeFlags ) ;
454
455 m_minWidth = minWidth;
456 }
457
458 void wxSlider::DoMoveWindow(int x, int y, int width, int height)
459 {
460 wxControl::DoMoveWindow(x,y,width,height) ;
461 }
462
463 // Common processing to invert slider values based on wxSL_INVERSE
464 int wxSlider::ValueInvertOrNot(int value) const
465 {
466 if (m_windowStyle & wxSL_VERTICAL)
467 {
468 // The reason for the backwards logic is that Mac's vertical sliders are
469 // inverted compared to Windows and GTK, hence we want inversion to be the
470 // default, and if wxSL_INVERSE is set, then we do not invert (use native)
471 if (m_windowStyle & wxSL_INVERSE)
472 return value;
473 else
474 return (m_rangeMax + m_rangeMin) - value;
475 }
476 else // normal logic applies to HORIZONTAL sliders
477 {
478 return wxSliderBase::ValueInvertOrNot(value);
479 }
480 }
481
482 #endif // wxUSE_SLIDER