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