X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/312ebad4cd1fad97a79aaed7102611df88806410..4792d19265f446a15e669ef1cfda20b2dd36d414:/src/mac/carbon/slider.cpp?ds=sidebyside diff --git a/src/mac/carbon/slider.cpp b/src/mac/carbon/slider.cpp index 0c73cb27bf..6080397266 100644 --- a/src/mac/carbon/slider.cpp +++ b/src/mac/carbon/slider.cpp @@ -9,25 +9,19 @@ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "slider.h" -#endif - -#include "wx/defs.h" +#include "wx/wxprec.h" #if wxUSE_SLIDER #include "wx/slider.h" #include "wx/mac/uma.h" -#if !USE_SHARED_LIBRARY IMPLEMENT_DYNAMIC_CLASS(wxSlider, wxControl) BEGIN_EVENT_TABLE(wxSlider, wxControl) END_EVENT_TABLE() -#endif - // The dimensions of the different styles of sliders (From Aqua document) + // The dimensions of the different styles of sliders (from Aqua document) #define wxSLIDER_DIMENSIONACROSS 15 #define wxSLIDER_DIMENSIONACROSS_WITHTICKMARKS 24 #define wxSLIDER_DIMENSIONACROSS_ARROW 18 @@ -35,24 +29,27 @@ END_EVENT_TABLE() // Distance between slider and text #define wxSLIDER_BORDERTEXT 5 -/* NB! The default orientation for a slider is horizontal however if the user specifies - * some slider styles but dosen't specify the orientation we have to assume he wants a - * horizontal one. Therefore in this file when testing for the sliders orientation - * vertical is tested for if this is not set then we use the horizontal one - * eg. if(GetWindowStyle() & wxSL_VERTICAL) {} else { horizontal case }> - */ +/* +* NB! The default orientation for a slider is horizontal however if the user specifies +* some slider styles but doesn't specify the orientation we have to assume he wants a +* horizontal one. Therefore in this file when testing for the slider's orientation +* vertical is tested for if this is not set then we use the horizontal one +* e.g., if (GetWindowStyle() & wxSL_VERTICAL) {} else { horizontal case }. +*/ + - // Slider - wxSlider::wxSlider() +wxSlider::wxSlider() { m_pageSize = 1; m_lineSize = 1; m_rangeMax = 0; m_rangeMin = 0; m_tickFreq = 0; -} -extern ControlActionUPP wxMacLiveScrollbarActionUPP ; + m_macMinimumStatic = NULL; + m_macMaximumStatic = NULL; + m_macValueStatic = NULL; +} bool wxSlider::Create(wxWindow *parent, wxWindowID id, int value, int minValue, int maxValue, @@ -63,14 +60,10 @@ bool wxSlider::Create(wxWindow *parent, wxWindowID id, { m_macIsUserPane = false ; - if ( !wxControl::Create(parent, id, pos, size, style, validator, name) ) - return false; - m_macMinimumStatic = NULL ; m_macMaximumStatic = NULL ; m_macValueStatic = NULL ; - m_lineSize = 1; m_tickFreq = 0; @@ -79,40 +72,74 @@ bool wxSlider::Create(wxWindow *parent, wxWindowID id, m_pageSize = (int)((maxValue-minValue)/10); + // our styles are redundant: wxSL_LEFT/RIGHT imply wxSL_VERTICAL and + // wxSL_TOP/BOTTOM imply wxSL_HORIZONTAL, but for backwards compatibility + // reasons we can't really change it, instead try to infer the orientation + // from the flags given to us here + switch ( style & (wxSL_LEFT | wxSL_RIGHT | wxSL_TOP | wxSL_BOTTOM) ) + { + case wxSL_LEFT: + case wxSL_RIGHT: + style |= wxSL_VERTICAL; + break; + + case wxSL_TOP: + case wxSL_BOTTOM: + style |= wxSL_HORIZONTAL; + break; + + case 0: + default: + // no specific direction, do we have at least the orientation? + if ( !(style & (wxSL_HORIZONTAL | wxSL_VERTICAL)) ) + // no: choose default + style |= wxSL_BOTTOM | wxSL_HORIZONTAL; + break; + } + + wxASSERT_MSG( !(style & wxSL_VERTICAL) || !(style & wxSL_HORIZONTAL), + _T("incompatible slider direction and orientation") ); + + if ( !wxControl::Create(parent, id, pos, size, style, validator, name) ) + return false; + Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ; + // NB: (RN) Ticks here are sometimes off in the GUI if there + // is not as many ticks as there are values + // UInt16 tickMarks = 0 ; if ( style & wxSL_AUTOTICKS ) - tickMarks = (maxValue - minValue); + tickMarks = (maxValue - minValue) + 1; //+1 for the 0 value - if (tickMarks > 20) - tickMarks = tickMarks/5; //keep the number of tickmarks from becoming unwieldly + // keep the number of tickmarks from becoming unwieldly + while (tickMarks > 20) + tickMarks /= 5; - m_peer = new wxMacControl() ; + m_peer = new wxMacControl( this ); verify_noerr ( CreateSliderControl( MAC_WXHWND(parent->MacGetTopLevelWindowRef()) , &bounds , - value , minValue , maxValue , kControlSliderPointsDownOrRight , tickMarks , true /* liveTracking */ , - wxMacLiveScrollbarActionUPP , m_peer->GetControlRefAddr() ) ); + value , minValue , maxValue , kControlSliderPointsDownOrRight , tickMarks , true /* liveTracking */ , + GetwxMacLiveScrollbarActionProc() , m_peer->GetControlRefAddr() ) ); - - if(style & wxSL_VERTICAL) { + if (style & wxSL_VERTICAL) SetSizeHints(10, -1, 10, -1); // Forces SetSize to use the proper width - } - else { + else SetSizeHints(-1, 10, -1, 10); // Forces SetSize to use the proper height - } + // NB! SetSizeHints is overloaded by wxSlider and will substitute 10 with the // proper dimensions, it also means other people cannot bugger the slider with // other values - if(style & wxSL_LABELS) + if (style & wxSL_LABELS) { m_macMinimumStatic = new wxStaticText( parent, wxID_ANY, wxEmptyString ); m_macMaximumStatic = new wxStaticText( parent, wxID_ANY, wxEmptyString ); m_macValueStatic = new wxStaticText( parent, wxID_ANY, wxEmptyString ); - SetRange(minValue, maxValue); - SetValue(value); } + SetRange(minValue, maxValue); + SetValue(value); + MacPostControlCreate(pos,size) ; return true; @@ -120,23 +147,33 @@ bool wxSlider::Create(wxWindow *parent, wxWindowID id, wxSlider::~wxSlider() { - delete m_macMinimumStatic ; - delete m_macMaximumStatic ; - delete m_macValueStatic ; + // this is a special case, as we had to add windows as siblings we are + // responsible for their disposal, but only if we are not part of a DestroyAllChildren + if ( m_parent && !m_parent->IsBeingDeleted() ) + { + delete m_macMinimumStatic ; + delete m_macMaximumStatic ; + delete m_macValueStatic ; + } } int wxSlider::GetValue() const { - return m_peer->GetValue() ; + // We may need to invert the value returned by the widget + return ValueInvertOrNot( m_peer->GetValue() ) ; } void wxSlider::SetValue(int value) { - wxString valuestring ; - valuestring.Printf( wxT("%d") , value ) ; if ( m_macValueStatic ) - m_macValueStatic->SetLabel( valuestring ) ; - m_peer->SetValue( value ) ; + { + wxString valuestring; + valuestring.Printf( wxT("%d") , value ); + m_macValueStatic->SetLabel( valuestring ); + } + + // We only invert for the setting of the actual native widget + m_peer->SetValue( ValueInvertOrNot ( value ) ) ; } void wxSlider::SetRange(int minValue, int maxValue) @@ -149,14 +186,18 @@ void wxSlider::SetRange(int minValue, int maxValue) m_peer->SetMinimum( m_rangeMin); m_peer->SetMaximum( m_rangeMax); - if(m_macMinimumStatic) { - value.Printf(wxT("%d"), m_rangeMin); + if (m_macMinimumStatic) + { + value.Printf(wxT("%d"), ValueInvertOrNot( m_rangeMin ) ); m_macMinimumStatic->SetLabel(value); } - if(m_macMaximumStatic) { - value.Printf(wxT("%d"), m_rangeMax); + + if (m_macMaximumStatic) + { + value.Printf(wxT("%d"), ValueInvertOrNot( m_rangeMax ) ); m_macMaximumStatic->SetLabel(value); } + SetValue(m_rangeMin); } @@ -235,13 +276,15 @@ void wxSlider::SetTick(int tickPos) void wxSlider::Command (wxCommandEvent & event) { - SetValue (event.GetInt()); - ProcessCommand (event); + SetValue(event.GetInt()); + ProcessCommand(event); } void wxSlider::MacHandleControlClick( WXWidget control , wxInt16 controlpart, bool mouseStillDown ) { - SInt16 value = m_peer->GetValue() ; + // Whatever the native value is, we may need to invert it for calling + // SetValue and putting the possibly inverted value in the event + SInt16 value = ValueInvertOrNot ( m_peer->GetValue() ) ; SetValue( value ) ; @@ -263,7 +306,9 @@ void wxSlider::MacHandleControlClick( WXWidget control , wxInt16 controlpart, bo wxInt32 wxSlider::MacControlHit( WXEVENTHANDLERREF handler , WXEVENTREF mevent ) { - SInt16 value = m_peer->GetValue() ; + // Whatever the native value is, we may need to invert it for calling + // SetValue and putting the possibly inverted value in the event + SInt16 value = ValueInvertOrNot ( m_peer->GetValue() ) ; SetValue( value ) ; @@ -281,152 +326,220 @@ wxInt32 wxSlider::MacControlHit( WXEVENTHANDLERREF handler , WXEVENTREF mevent ) cevent.SetEventObject( this ); GetEventHandler()->ProcessEvent( cevent ); - return noErr ; -} + return noErr; +} -/* This is overloaded in wxSlider so that the proper width/height will always be used -* for the slider different values would cause redrawing and mouse detection problems */ -void wxSlider::SetSizeHints( int minW, int minH, - int maxW , int maxH , - int incW , int incH ) +// This is overloaded in wxSlider so that the proper width/height will always be used +// for the slider different values would cause redrawing and mouse detection problems +// +void wxSlider::DoSetSizeHints( int minW, int minH, + int maxW , int maxH , + int incW , int incH ) { wxSize size = GetBestSize(); - if(GetWindowStyle() & wxSL_VERTICAL) { - wxWindow::SetSizeHints(size.x, minH, size.x, maxH, incW, incH); - } - else { - wxWindow::SetSizeHints(minW, size.y, maxW, size.y, incW, incH); - } + if (GetWindowStyle() & wxSL_VERTICAL) + wxWindow::DoSetSizeHints(size.x, minH, size.x, maxH, incW, incH); + else + wxWindow::DoSetSizeHints(minW, size.y, maxW, size.y, incW, incH); } wxSize wxSlider::DoGetBestSize() const { wxSize size; int textwidth, textheight; + int mintwidth, mintheight; + int maxtwidth, maxtheight; - if(GetWindowStyle() & wxSL_LABELS) + textwidth = textheight = 0; + mintwidth = mintheight = 0; + maxtwidth = maxtheight = 0; + + if (GetWindowStyle() & wxSL_LABELS) { wxString text; - int ht, wd; // Get maximum text label width and height - text.Printf(wxT("%d"), m_rangeMin); - GetTextExtent(text, &textwidth, &textheight); - text.Printf(wxT("%d"), m_rangeMax); - GetTextExtent(text, &wd, &ht); - if(ht > textheight) { - textheight = ht; - } - if (wd > textwidth) { - textwidth = wd; - } + text.Printf(wxT("%d"), ValueInvertOrNot( m_rangeMin ) ); + GetTextExtent(text, &mintwidth, &mintheight); + text.Printf(wxT("%d"), ValueInvertOrNot( m_rangeMax ) ); + GetTextExtent(text, &maxtwidth, &maxtheight); + + if (maxtheight > mintheight) + textheight = maxtheight; + else + textheight = mintheight; + + if (maxtwidth > mintwidth) + textwidth = maxtwidth; + else + textwidth = mintwidth; } - if(GetWindowStyle() & wxSL_VERTICAL) + if (GetWindowStyle() & wxSL_VERTICAL) { - if(GetWindowStyle() & wxSL_AUTOTICKS) { + if (GetWindowStyle() & wxSL_AUTOTICKS) size.x = wxSLIDER_DIMENSIONACROSS_WITHTICKMARKS; - } - else { + else size.x = wxSLIDER_DIMENSIONACROSS_ARROW; - } - if(GetWindowStyle() & wxSL_LABELS) { + + if (GetWindowStyle() & wxSL_LABELS) size.x += textwidth + wxSLIDER_BORDERTEXT; - } + size.y = 150; } else { - if(GetWindowStyle() & wxSL_AUTOTICKS) { + if (GetWindowStyle() & wxSL_AUTOTICKS) size.y = wxSLIDER_DIMENSIONACROSS_WITHTICKMARKS; - } - else { + else size.y = wxSLIDER_DIMENSIONACROSS_ARROW; - } - if(GetWindowStyle() & wxSL_LABELS) { + + size.x = 150; + + if (GetWindowStyle() & wxSL_LABELS) + { size.y += textheight + wxSLIDER_BORDERTEXT; + size.x += (mintwidth / 2) + (maxtwidth / 2); } - size.x = 150; } + return size; } void wxSlider::DoSetSize(int x, int y, int w, int h, int sizeFlags) { - int xborder, yborder; - int minValWidth, maxValWidth, textwidth, textheight; - int sliderBreadth; + int xborder, yborder; + int minValWidth, maxValWidth, textheight; + int sliderBreadth; + int width = w; xborder = yborder = 0; if (GetWindowStyle() & wxSL_LABELS) { - //Labels have this control's parent as their parent - //so if this control is not at 0,0 relative to the parent - //the labels need to know the position of this control - //relative to its parent in order to size properly, so - //move the control first so we can use GetPosition() - wxControl::DoSetSize( x, y , w , h ,sizeFlags ) ; - wxString text; - int ht; + int ht, valValWidth; // Get maximum text label width and height - text.Printf(wxT("%d"), m_rangeMin); + text.Printf(wxT("%d"), ValueInvertOrNot( m_rangeMin ) ); GetTextExtent(text, &minValWidth, &textheight); - text.Printf(wxT("%d"), m_rangeMax); + text.Printf(wxT("%d"), ValueInvertOrNot( m_rangeMax ) ); GetTextExtent(text, &maxValWidth, &ht); - if(ht > textheight) { + + if (ht > textheight) textheight = ht; + + if (GetWindowStyle() & wxSL_HORIZONTAL) + { + if ( m_macMinimumStatic ) + { + w -= minValWidth / 2; + x += minValWidth / 2; + } + + if ( m_macMaximumStatic ) + w -= maxValWidth / 2; } - textwidth = (minValWidth > maxValWidth ? minValWidth : maxValWidth); - xborder = textwidth + wxSLIDER_BORDERTEXT; + // Labels have this control's parent as their parent + // so if this control is not at 0,0 relative to the parent + // the labels need to know the position of this control + // relative to its parent in order to size properly, so + // move the control first so we can use GetPosition() + wxControl::DoSetSize( x, y , w , h , sizeFlags ); + + if (GetWindowStyle() & wxSL_VERTICAL) + // If vertical, use current value + text.Printf(wxT("%d"), (int)m_peer->GetValue()); + else + // Use max so that the current value doesn't drift as centering would need to change + text.Printf(wxT("%d"), m_rangeMax); + + GetTextExtent(text, &valValWidth, &ht); + yborder = textheight + wxSLIDER_BORDERTEXT; // Get slider breadth - if(GetWindowStyle() & wxSL_AUTOTICKS) { + if (GetWindowStyle() & wxSL_AUTOTICKS) sliderBreadth = wxSLIDER_DIMENSIONACROSS_WITHTICKMARKS; - } - else { + else sliderBreadth = wxSLIDER_DIMENSIONACROSS_ARROW; - } - if(GetWindowStyle() & wxSL_VERTICAL) + if (GetWindowStyle() & wxSL_VERTICAL) { - h = h - yborder ; + h = h - yborder; if ( m_macMinimumStatic ) - m_macMinimumStatic->Move(GetPosition().x + sliderBreadth + wxSLIDER_BORDERTEXT, - GetPosition().y + h - yborder); + m_macMinimumStatic->Move(GetPosition().x + sliderBreadth + wxSLIDER_BORDERTEXT, GetPosition().y + h - yborder); if ( m_macMaximumStatic ) m_macMaximumStatic->Move(GetPosition().x + sliderBreadth + wxSLIDER_BORDERTEXT, GetPosition().y + 0); if ( m_macValueStatic ) - m_macValueStatic->Move(GetPosition().x, GetPosition().y + h ); + m_macValueStatic->Move(GetPosition().x + sliderBreadth + wxSLIDER_BORDERTEXT, GetPosition().y + (h / 2) - (ht / 2)); } else { - w = w - xborder ; if ( m_macMinimumStatic ) - m_macMinimumStatic->Move(GetPosition().x + 0, GetPosition().y + sliderBreadth + wxSLIDER_BORDERTEXT); + m_macMinimumStatic->Move(GetPosition().x, GetPosition().y + sliderBreadth + wxSLIDER_BORDERTEXT); if ( m_macMaximumStatic ) - m_macMaximumStatic->Move(GetPosition().x + w - (maxValWidth/2), - GetPosition().y + sliderBreadth + wxSLIDER_BORDERTEXT); + m_macMaximumStatic->Move(GetPosition().x + w - maxValWidth, GetPosition().y + sliderBreadth + wxSLIDER_BORDERTEXT); if ( m_macValueStatic ) - m_macValueStatic->Move(GetPosition().x + w, GetPosition().y + 0); + m_macValueStatic->Move(GetPosition().x + (w / 2) - (valValWidth / 2), GetPosition().y + sliderBreadth + wxSLIDER_BORDERTEXT); } } - //If the control has labels, we still need to call this again because - //the labels alter the control's w and h values. - wxControl::DoSetSize( x, y , w , h ,sizeFlags ) ; + // yet another hack since this is a composite control + // when wxSlider has it's size hardcoded, we're not allowed to + // change the size. But when the control has labels, we DO need + // to resize the internal Mac control to accommodate the text labels. + // We need to trick the wxWidgets resize mechanism so that we can + // resize the slider part of the control ONLY. + + // TODO: Can all of this code go in the conditional wxSL_LABELS block? + + int minWidth = m_minWidth; + + if (GetWindowStyle() & wxSL_LABELS) + { + // make sure we don't allow the entire control to be resized accidently + if (width == GetSize().x) + m_minWidth = -1; + } + + // If the control has labels, we still need to call this again because + // the labels alter the control's w and h values. + wxControl::DoSetSize( x, y, w, h, sizeFlags ); + + m_minWidth = minWidth; } void wxSlider::DoMoveWindow(int x, int y, int width, int height) { - wxControl::DoMoveWindow(x,y,width,height) ; + wxControl::DoMoveWindow( x, y, width, height ); +} + +// Common processing to invert slider values based on wxSL_INVERSE +int wxSlider::ValueInvertOrNot(int value) const +{ + int result = 0; + + if (m_windowStyle & wxSL_VERTICAL) + { + // The reason for the backwards logic is that Mac's vertical sliders are + // inverted compared to Windows and GTK, hence we want inversion to be the + // default, and if wxSL_INVERSE is set, then we do not invert (use native) + if (m_windowStyle & wxSL_INVERSE) + result = value; + else + result = (m_rangeMax + m_rangeMin) - value; + } + else // normal logic applies to HORIZONTAL sliders + { + result = wxSliderBase::ValueInvertOrNot(value); + } + + return result; } #endif // wxUSE_SLIDER