]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/slider.cpp
support mac on little endian systems
[wxWidgets.git] / src / mac / carbon / slider.cpp
CommitLineData
e9576ca5
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: slider.cpp
3// Purpose: wxSlider
a31a5f85 4// Author: Stefan Csomor
e9576ca5 5// Modified by:
a31a5f85 6// Created: 1998-01-01
e9576ca5 7// RCS-ID: $Id$
a31a5f85 8// Copyright: (c) Stefan Csomor
65571936 9// Licence: wxWindows licence
e9576ca5
SC
10/////////////////////////////////////////////////////////////////////////////
11
3d1a4878 12#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
e9576ca5
SC
13#pragma implementation "slider.h"
14#endif
15
3d1a4878 16#include "wx/wxprec.h"
312ebad4
WS
17
18#if wxUSE_SLIDER
19
e9576ca5 20#include "wx/slider.h"
519cb848 21#include "wx/mac/uma.h"
e9576ca5 22
e9576ca5
SC
23IMPLEMENT_DYNAMIC_CLASS(wxSlider, wxControl)
24
25BEGIN_EVENT_TABLE(wxSlider, wxControl)
26END_EVENT_TABLE()
e9576ca5 27
9453cf2b 28 // The dimensions of the different styles of sliders (From Aqua document)
e40298d5
JS
29#define wxSLIDER_DIMENSIONACROSS 15
30#define wxSLIDER_DIMENSIONACROSS_WITHTICKMARKS 24
31#define wxSLIDER_DIMENSIONACROSS_ARROW 18
312ebad4 32
e40298d5
JS
33// Distance between slider and text
34#define wxSLIDER_BORDERTEXT 5
312ebad4 35
e40298d5
JS
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
312ebad4 40 * eg. if(GetWindowStyle() & wxSL_VERTICAL) {} else { horizontal case }>
e40298d5
JS
41 */
42
43 // Slider
44 wxSlider::wxSlider()
e9576ca5 45{
e40298d5
JS
46 m_pageSize = 1;
47 m_lineSize = 1;
48 m_rangeMax = 0;
49 m_rangeMin = 0;
50 m_tickFreq = 0;
e9576ca5
SC
51}
52
53bool wxSlider::Create(wxWindow *parent, wxWindowID id,
e40298d5
JS
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)
e9576ca5 59{
312ebad4
WS
60 m_macIsUserPane = false ;
61
b45ed7a2
VZ
62 if ( !wxControl::Create(parent, id, pos, size, style, validator, name) )
63 return false;
64
e40298d5
JS
65 m_macMinimumStatic = NULL ;
66 m_macMaximumStatic = NULL ;
67 m_macValueStatic = NULL ;
312ebad4 68
e40298d5
JS
69 m_lineSize = 1;
70 m_tickFreq = 0;
312ebad4 71
e40298d5
JS
72 m_rangeMax = maxValue;
73 m_rangeMin = minValue;
312ebad4 74
e40298d5 75 m_pageSize = (int)((maxValue-minValue)/10);
312ebad4
WS
76
77 Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ;
78
344d4802
RN
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 //
4c37f124
SC
83 UInt16 tickMarks = 0 ;
84 if ( style & wxSL_AUTOTICKS )
344d4802 85 tickMarks = (maxValue - minValue) + 1; //+1 for the 0 value
312ebad4 86
344d4802 87 while (tickMarks > 20)
02812785 88 tickMarks /= 5; //keep the number of tickmarks from becoming unwieldly
312ebad4 89
b905d6cc 90 m_peer = new wxMacControl(this) ;
312ebad4 91 verify_noerr ( CreateSliderControl( MAC_WXHWND(parent->MacGetTopLevelWindowRef()) , &bounds ,
02812785 92 value , minValue , maxValue , kControlSliderPointsDownOrRight , tickMarks , true /* liveTracking */ ,
cd780027 93 GetwxMacLiveScrollbarActionProc() , m_peer->GetControlRefAddr() ) );
312ebad4
WS
94
95
e40298d5
JS
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
312ebad4 105
facd6764
SC
106 if(style & wxSL_LABELS)
107 {
312ebad4
WS
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 );
facd6764
SC
111 SetRange(minValue, maxValue);
112 SetValue(value);
113 }
114
115 MacPostControlCreate(pos,size) ;
312ebad4 116
e40298d5 117 return true;
e9576ca5
SC
118}
119
120wxSlider::~wxSlider()
121{
01526d4f 122 // this is a special case, as we had to add windows as siblings we are
33b35531
SC
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 }
e9576ca5
SC
130}
131
132int wxSlider::GetValue() const
133{
02812785 134 // We may need to invert the value returned by the widget
01526d4f 135 return ValueInvertOrNot( m_peer->GetValue() ) ;
e9576ca5
SC
136}
137
138void wxSlider::SetValue(int value)
139{
e40298d5 140 wxString valuestring ;
312ebad4 141 valuestring.Printf( wxT("%d") , value ) ;
e40298d5
JS
142 if ( m_macValueStatic )
143 m_macValueStatic->SetLabel( valuestring ) ;
02812785
KH
144
145 // We only invert for the setting of the actual native widget
01526d4f 146 m_peer->SetValue( ValueInvertOrNot ( value ) ) ;
e9576ca5
SC
147}
148
149void wxSlider::SetRange(int minValue, int maxValue)
150{
e40298d5 151 wxString value;
312ebad4 152
e40298d5
JS
153 m_rangeMin = minValue;
154 m_rangeMax = maxValue;
312ebad4 155
5ca0d812
SC
156 m_peer->SetMinimum( m_rangeMin);
157 m_peer->SetMaximum( m_rangeMax);
312ebad4 158
e40298d5 159 if(m_macMinimumStatic) {
01526d4f 160 value.Printf(wxT("%d"), ValueInvertOrNot( m_rangeMin ) );
e40298d5
JS
161 m_macMinimumStatic->SetLabel(value);
162 }
163 if(m_macMaximumStatic) {
01526d4f 164 value.Printf(wxT("%d"), ValueInvertOrNot( m_rangeMax ) );
e40298d5
JS
165 m_macMaximumStatic->SetLabel(value);
166 }
167 SetValue(m_rangeMin);
e9576ca5
SC
168}
169
170// For trackbars only
171void wxSlider::SetTickFreq(int n, int pos)
172{
173 // TODO
174 m_tickFreq = n;
175}
176
177void wxSlider::SetPageSize(int pageSize)
178{
179 // TODO
180 m_pageSize = pageSize;
181}
182
183int wxSlider::GetPageSize() const
184{
185 return m_pageSize;
186}
187
188void wxSlider::ClearSel()
189{
190 // TODO
191}
192
193void wxSlider::ClearTicks()
194{
195 // TODO
196}
197
198void wxSlider::SetLineSize(int lineSize)
199{
200 m_lineSize = lineSize;
201 // TODO
202}
203
204int wxSlider::GetLineSize() const
205{
206 // TODO
207 return 0;
208}
209
210int wxSlider::GetSelEnd() const
211{
212 // TODO
213 return 0;
214}
215
216int wxSlider::GetSelStart() const
217{
218 // TODO
219 return 0;
220}
221
222void wxSlider::SetSelection(int minPos, int maxPos)
223{
224 // TODO
225}
226
227void wxSlider::SetThumbLength(int len)
228{
229 // TODO
230}
231
232int wxSlider::GetThumbLength() const
233{
234 // TODO
235 return 0;
236}
237
238void wxSlider::SetTick(int tickPos)
239{
240 // TODO
241}
242
243void wxSlider::Command (wxCommandEvent & event)
244{
e40298d5
JS
245 SetValue (event.GetInt());
246 ProcessCommand (event);
e9576ca5
SC
247}
248
312ebad4 249void wxSlider::MacHandleControlClick( WXWidget control , wxInt16 controlpart, bool mouseStillDown )
519cb848 250{
02812785
KH
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
01526d4f 253 SInt16 value = ValueInvertOrNot ( m_peer->GetValue() ) ;
312ebad4
WS
254
255 SetValue( value ) ;
256
cea9c546 257 wxEventType scrollEvent = wxEVT_NULL ;
312ebad4 258
4c37f124 259 scrollEvent = wxEVT_SCROLL_THUMBTRACK;
312ebad4 260
cea9c546 261 wxScrollEvent event(scrollEvent, m_windowId);
e40298d5
JS
262 event.SetPosition(value);
263 event.SetEventObject( this );
264 GetEventHandler()->ProcessEvent(event);
312ebad4 265
e40298d5
JS
266 wxCommandEvent cevent( wxEVT_COMMAND_SLIDER_UPDATED, m_windowId );
267 cevent.SetInt( value );
268 cevent.SetEventObject( this );
312ebad4 269
e40298d5
JS
270 GetEventHandler()->ProcessEvent( cevent );
271}
272
312ebad4 273wxInt32 wxSlider::MacControlHit( WXEVENTHANDLERREF handler , WXEVENTREF mevent )
4c37f124 274{
02812785
KH
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
01526d4f 277 SInt16 value = ValueInvertOrNot ( m_peer->GetValue() ) ;
312ebad4
WS
278
279 SetValue( value ) ;
280
4c37f124 281 wxEventType scrollEvent = wxEVT_NULL ;
312ebad4 282
4c37f124 283 scrollEvent = wxEVT_SCROLL_THUMBRELEASE;
312ebad4 284
4c37f124
SC
285 wxScrollEvent event(scrollEvent, m_windowId);
286 event.SetPosition(value);
287 event.SetEventObject( this );
288 GetEventHandler()->ProcessEvent(event);
312ebad4 289
4c37f124
SC
290 wxCommandEvent cevent( wxEVT_COMMAND_SLIDER_UPDATED, m_windowId );
291 cevent.SetInt( value );
292 cevent.SetEventObject( this );
312ebad4 293
4c37f124
SC
294 GetEventHandler()->ProcessEvent( cevent );
295 return noErr ;
296}
297
e40298d5
JS
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 */
024f89f9
VS
300void wxSlider::DoSetSizeHints( int minW, int minH,
301 int maxW , int maxH ,
302 int incW , int incH )
e40298d5
JS
303{
304 wxSize size = GetBestSize();
312ebad4 305
e40298d5 306 if(GetWindowStyle() & wxSL_VERTICAL) {
024f89f9 307 wxWindow::DoSetSizeHints(size.x, minH, size.x, maxH, incW, incH);
e40298d5
JS
308 }
309 else {
024f89f9 310 wxWindow::DoSetSizeHints(minW, size.y, maxW, size.y, incW, incH);
e40298d5 311 }
519cb848 312}
9453cf2b 313
e40298d5
JS
314wxSize wxSlider::DoGetBestSize() const
315{
316 wxSize size;
317 int textwidth, textheight;
312ebad4 318
e40298d5
JS
319 if(GetWindowStyle() & wxSL_LABELS)
320 {
321 wxString text;
322 int ht, wd;
312ebad4 323
e40298d5 324 // Get maximum text label width and height
01526d4f 325 text.Printf(wxT("%d"), ValueInvertOrNot( m_rangeMin ) );
e40298d5 326 GetTextExtent(text, &textwidth, &textheight);
01526d4f 327 text.Printf(wxT("%d"), ValueInvertOrNot( m_rangeMax ) );
e40298d5
JS
328 GetTextExtent(text, &wd, &ht);
329 if(ht > textheight) {
330 textheight = ht;
331 }
332 if (wd > textwidth) {
333 textwidth = wd;
334 }
335 }
312ebad4 336
e40298d5
JS
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
facd6764 366void wxSlider::DoSetSize(int x, int y, int w, int h, int sizeFlags)
327788ac 367{
e40298d5
JS
368 int xborder, yborder;
369 int minValWidth, maxValWidth, textwidth, textheight;
370 int sliderBreadth;
09ff2ee1 371 int width = w;
312ebad4 372
e40298d5 373 xborder = yborder = 0;
f26ca7f8 374
e40298d5
JS
375 if (GetWindowStyle() & wxSL_LABELS)
376 {
f26ca7f8
KO
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 ) ;
312ebad4 383
e40298d5
JS
384 wxString text;
385 int ht;
312ebad4 386
e40298d5 387 // Get maximum text label width and height
01526d4f 388 text.Printf(wxT("%d"), ValueInvertOrNot( m_rangeMin ) );
e40298d5 389 GetTextExtent(text, &minValWidth, &textheight);
01526d4f 390 text.Printf(wxT("%d"), ValueInvertOrNot( m_rangeMax ) );
e40298d5
JS
391 GetTextExtent(text, &maxValWidth, &ht);
392 if(ht > textheight) {
393 textheight = ht;
394 }
395 textwidth = (minValWidth > maxValWidth ? minValWidth : maxValWidth);
312ebad4 396
e40298d5
JS
397 xborder = textwidth + wxSLIDER_BORDERTEXT;
398 yborder = textheight + wxSLIDER_BORDERTEXT;
312ebad4 399
e40298d5
JS
400 // Get slider breadth
401 if(GetWindowStyle() & wxSL_AUTOTICKS) {
402 sliderBreadth = wxSLIDER_DIMENSIONACROSS_WITHTICKMARKS;
403 }
404 else {
405 sliderBreadth = wxSLIDER_DIMENSIONACROSS_ARROW;
406 }
312ebad4 407
e40298d5
JS
408 if(GetWindowStyle() & wxSL_VERTICAL)
409 {
f26ca7f8 410 h = h - yborder ;
312ebad4 411
facd6764 412 if ( m_macMinimumStatic )
f26ca7f8 413 m_macMinimumStatic->Move(GetPosition().x + sliderBreadth + wxSLIDER_BORDERTEXT,
6dfa00e8 414 GetPosition().y + h - yborder);
facd6764 415 if ( m_macMaximumStatic )
f26ca7f8 416 m_macMaximumStatic->Move(GetPosition().x + sliderBreadth + wxSLIDER_BORDERTEXT, GetPosition().y + 0);
facd6764 417 if ( m_macValueStatic )
6dfa00e8 418 m_macValueStatic->Move(GetPosition().x, GetPosition().y + h );
e40298d5
JS
419 }
420 else
421 {
1dc1b891 422 w = w - xborder ;
facd6764 423 if ( m_macMinimumStatic )
f26ca7f8 424 m_macMinimumStatic->Move(GetPosition().x + 0, GetPosition().y + sliderBreadth + wxSLIDER_BORDERTEXT);
facd6764 425 if ( m_macMaximumStatic )
f26ca7f8
KO
426 m_macMaximumStatic->Move(GetPosition().x + w - (maxValWidth/2),
427 GetPosition().y + sliderBreadth + wxSLIDER_BORDERTEXT);
facd6764 428 if ( m_macValueStatic )
f26ca7f8 429 m_macValueStatic->Move(GetPosition().x + w, GetPosition().y + 0);
e40298d5
JS
430 }
431 }
01526d4f 432
09ff2ee1 433 // yet another hack since this is a composite control
01526d4f
WS
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
3103e8a9 436 // to resize the internal Mac control to accommodate the text labels.
09ff2ee1 437 // We need to trick the wxWidgets resize mechanism so that we can
01526d4f
WS
438 // resize the slider part of the control ONLY.
439
09ff2ee1 440 // TODO: Can all of this code go in the conditional wxSL_LABELS block?
01526d4f 441
09ff2ee1 442 int minWidth;
900a8765 443 minWidth = m_minWidth;
01526d4f 444
900a8765 445 if (GetWindowStyle() & wxSL_LABELS)
09ff2ee1 446 {
900a8765
KH
447 // make sure we don't allow the entire control to be resized accidently
448 if (width == GetSize().x)
449 m_minWidth = -1;
450 }
01526d4f 451 //If the control has labels, we still need to call this again because
312ebad4 452 //the labels alter the control's w and h values.
facd6764 453 wxControl::DoSetSize( x, y , w , h ,sizeFlags ) ;
09ff2ee1 454
900a8765 455 m_minWidth = minWidth;
327788ac
SC
456}
457
eb22f2a6
GD
458void wxSlider::DoMoveWindow(int x, int y, int width, int height)
459{
327788ac 460 wxControl::DoMoveWindow(x,y,width,height) ;
eb22f2a6 461}
312ebad4 462
02812785 463// Common processing to invert slider values based on wxSL_INVERSE
01526d4f 464int wxSlider::ValueInvertOrNot(int value) const
02812785
KH
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 {
01526d4f 478 return wxSliderBase::ValueInvertOrNot(value);
02812785
KH
479 }
480}
481
312ebad4 482#endif // wxUSE_SLIDER