diff options
| author | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
|---|---|---|
| committer | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
| commit | 39ed87570bdb2f86969d4be821c94b722dc71179 (patch) | |
| tree | abc53757f75f40c80278e87650ea92808274aa59 /mp/src/vgui2/vgui_controls/ScrollBarSlider.cpp | |
| download | source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip | |
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/vgui2/vgui_controls/ScrollBarSlider.cpp')
| -rw-r--r-- | mp/src/vgui2/vgui_controls/ScrollBarSlider.cpp | 606 |
1 files changed, 606 insertions, 0 deletions
diff --git a/mp/src/vgui2/vgui_controls/ScrollBarSlider.cpp b/mp/src/vgui2/vgui_controls/ScrollBarSlider.cpp new file mode 100644 index 00000000..da54f3f0 --- /dev/null +++ b/mp/src/vgui2/vgui_controls/ScrollBarSlider.cpp @@ -0,0 +1,606 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#define PROTECTED_THINGS_DISABLE
+
+#include <vgui/IBorder.h>
+#include <vgui/IInput.h>
+#include <vgui/ISystem.h>
+#include <vgui/IScheme.h>
+#include <vgui/ISurface.h>
+#include <vgui/MouseCode.h>
+#include <KeyValues.h>
+
+#include <vgui_controls/ScrollBarSlider.h>
+#include <vgui_controls/Controls.h>
+
+#include <math.h>
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include <tier0/memdbgon.h>
+
+using namespace vgui;
+
+//-----------------------------------------------------------------------------
+// The ScrollBarSlider is the scroll bar nob that moves up and down in through a range.
+//-----------------------------------------------------------------------------
+ScrollBarSlider::ScrollBarSlider(Panel *parent, const char *panelName, bool vertical) : Panel(parent, panelName)
+{
+ _vertical=vertical;
+ _dragging=false;
+ _value=0;
+ _range[0]=0;
+ _range[1]=0;
+ _rangeWindow=0;
+ _buttonOffset=0;
+ _ScrollBarSliderBorder=NULL;
+ RecomputeNobPosFromValue();
+ SetBlockDragChaining( true );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Set the size of the ScrollBarSlider nob
+//-----------------------------------------------------------------------------
+void ScrollBarSlider::SetSize(int wide,int tall)
+{
+ BaseClass::SetSize(wide,tall);
+ RecomputeNobPosFromValue();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Whether the scroll bar is vertical (true) or not (false)
+//-----------------------------------------------------------------------------
+bool ScrollBarSlider::IsVertical()
+{
+ return _vertical;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Set the ScrollBarSlider value of the nob.
+//-----------------------------------------------------------------------------
+void ScrollBarSlider::SetValue(int value)
+{
+ int oldValue = _value;
+
+ if (value > _range[1] - _rangeWindow)
+ {
+ // note our scrolling range must take into acount _rangeWindow
+ value = _range[1] - _rangeWindow;
+ }
+
+ if (value < _range[0])
+ {
+ value = _range[0];
+ }
+
+ _value = value;
+ RecomputeNobPosFromValue();
+
+ if (_value != oldValue)
+ {
+ SendScrollBarSliderMovedMessage();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Get the ScrollBarSlider value of the nob.
+//-----------------------------------------------------------------------------
+int ScrollBarSlider::GetValue()
+{
+ return _value;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void ScrollBarSlider::PerformLayout()
+{
+ RecomputeNobPosFromValue();
+ BaseClass::PerformLayout();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Given the value of the ScrollBarSlider, adjust the ends of the nob.
+//-----------------------------------------------------------------------------
+void ScrollBarSlider::RecomputeNobPosFromValue()
+{
+ int wide, tall;
+ GetPaintSize(wide, tall);
+
+ float fwide = (float)( wide - 1 );
+ float ftall = (float)( tall - 1 );
+ float frange = (float)(_range[1] -_range[0]);
+ float fvalue = (float)(_value - _range[0]);
+ float frangewindow = (float)(_rangeWindow);
+ float fper = ( frange != frangewindow ) ? fvalue / ( frange-frangewindow ) : 0;
+
+// Msg( "fwide: %f ftall: %f frange: %f fvalue: %f frangewindow: %f fper: %f\n",
+// fwide, ftall, frange, fvalue, frangewindow, fper );
+
+ if ( frangewindow > 0 )
+ {
+ if ( frange <= 0.0 )
+ {
+ frange = 1.0;
+ }
+
+ float width, length;
+ if (_vertical)
+ {
+ width = fwide;
+ length = ftall;
+ }
+ else
+ {
+ width = ftall;
+ length = fwide;
+ }
+
+ // our size is proportional to frangewindow/frange
+ // the scroll bar nob's length reflects the amount of stuff on the screen
+ // vs the total amount of stuff we could scroll through in window
+ // so if a window showed half its contents and the other half is hidden the
+ // scroll bar's length is half the window.
+ // if everything is on the screen no nob is displayed
+ // frange is how many 'lines' of stuff we can display
+ // frangewindow is how many 'lines' are in the display window
+
+ // proportion of whole window that is on screen
+ float proportion = frangewindow / frange;
+ float fnobsize = length * proportion;
+ if ( fnobsize < width ) fnobsize = (float)width;
+
+ float freepixels = length - fnobsize;
+
+ float firstpixel = freepixels * fper;
+
+ _nobPos[0] = (int)( firstpixel );
+ _nobPos[1] = (int)( firstpixel + fnobsize );
+
+ if ( _nobPos[1] > length )
+ {
+ _nobPos[0] = (int)( length - fnobsize );
+ _nobPos[1] = (int)length;
+ }
+
+ }
+
+ Repaint();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Get the ScrollBarSlider value using the location of the nob ends.
+//-----------------------------------------------------------------------------
+void ScrollBarSlider::RecomputeValueFromNobPos()
+{
+ int wide, tall;
+ GetPaintSize(wide, tall);
+
+ float fwide = (float)( wide - 1 );
+ float ftall = (float)( tall - 1 );
+ float frange = (float)( _range[1] - _range[0] );
+ float fvalue = (float)( _value - _range[0] );
+ float fnob = (float)_nobPos[0];
+ float frangewindow = (float)(_rangeWindow);
+
+ if ( frangewindow > 0 )
+ {
+ if ( frange <= 0.0 )
+ {
+ frange = 1.0;
+ }
+
+ // set local width and length
+ float width, length;
+ if ( _vertical )
+ {
+ width = fwide;
+ length = ftall;
+ }
+ else
+ {
+ width = ftall;
+ length = fwide;
+ }
+
+ // calculate the size of the nob
+ float proportion = frangewindow / frange;
+ float fnobsize = length * proportion;
+
+ if ( fnobsize < width )
+ {
+ fnobsize = width;
+ }
+
+ // Our scroll bar actually doesnt scroll through all frange lines in the truerange, we
+ // actually only scroll through frange-frangewindow number of lines so we must take that
+ // into account when we calculate the value
+ // convert to our local size system
+
+ // Make sure we don't divide by zero
+ if ( length - fnobsize == 0 )
+ {
+ fvalue = 0.0f;
+ }
+ else
+ {
+ fvalue = (frange - frangewindow) * ( fnob / ( length - fnobsize ) );
+ }
+ }
+
+ // check to see if we should just snap to the bottom
+ if (fabs(fvalue + _rangeWindow - _range[1]) < (0.01f * frange))
+ {
+ // snap to the end
+ _value = _range[1] - _rangeWindow;
+ }
+ else
+ {
+ // Take care of rounding issues.
+ _value = (int)( fvalue + _range[0] + 0.5);
+ }
+
+ // Clamp final result
+ _value = ( _value < (_range[1] - _rangeWindow) ) ? _value : (_range[1] - _rangeWindow);
+
+ if (_value < _range[0])
+ {
+ _value = _range[0];
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Check if the ScrollBarSlider can move through one or more pixels per
+// unit of its range.
+//-----------------------------------------------------------------------------
+bool ScrollBarSlider::HasFullRange()
+{
+ int wide, tall;
+ GetPaintSize(wide, tall);
+
+ float frangewindow = (float)(_rangeWindow);
+
+ float checkAgainst = 0;
+ if(_vertical)
+ {
+ checkAgainst = (float)tall;
+ }
+ else
+ {
+ checkAgainst = (float)wide;
+ }
+
+ if ( frangewindow > 0 )
+ {
+ if( frangewindow <= ( checkAgainst + _buttonOffset ) )
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Inform other watchers that the ScrollBarSlider was moved
+//-----------------------------------------------------------------------------
+void ScrollBarSlider::SendScrollBarSliderMovedMessage()
+{
+ // send a changed message
+ PostActionSignal(new KeyValues("ScrollBarSliderMoved", "position", _value));
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return true if this slider is actually drawing itself
+//-----------------------------------------------------------------------------
+bool ScrollBarSlider::IsSliderVisible( void )
+{
+ int itemRange = _range[1] - _range[0];
+
+ // Don't draw nob, no items in list
+ if ( itemRange <= 0 )
+ return false ;
+
+ // Not enough range
+ if ( itemRange <= _rangeWindow )
+ return false;
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void ScrollBarSlider::ApplySchemeSettings(IScheme *pScheme)
+{
+ BaseClass::ApplySchemeSettings(pScheme);
+
+ SetFgColor(GetSchemeColor("ScrollBarSlider.FgColor", pScheme));
+ SetBgColor(GetSchemeColor("ScrollBarSlider.BgColor", pScheme));
+
+ IBorder *newBorder = pScheme->GetBorder("ScrollBarSliderBorder");
+
+ if ( newBorder )
+ {
+ _ScrollBarSliderBorder = newBorder;
+ }
+ else
+ {
+ _ScrollBarSliderBorder = pScheme->GetBorder("ButtonBorder");
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void ScrollBarSlider::ApplySettings( KeyValues *pInResourceData )
+{
+ BaseClass::ApplySettings( pInResourceData );
+
+ const char *pButtonBorderName = pInResourceData->GetString( "ButtonBorder", NULL );
+ if ( pButtonBorderName )
+ {
+ _ScrollBarSliderBorder = vgui::scheme()->GetIScheme( GetScheme() )->GetBorder( pButtonBorderName );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void ScrollBarSlider::Paint()
+{
+ int wide,tall;
+ GetPaintSize(wide,tall);
+
+ if ( !IsSliderVisible() )
+ return;
+
+ Color col = GetFgColor();
+ surface()->DrawSetColor(col);
+
+ if (_vertical)
+ {
+ if ( GetPaintBackgroundType() == 2 )
+ {
+ DrawBox( 1, _nobPos[0], wide - 2, _nobPos[1] - _nobPos[0], col, 1.0f );
+ }
+ else
+ {
+ // Nob
+ surface()->DrawFilledRect(1, _nobPos[0], wide - 2, _nobPos[1]);
+ }
+
+ // border
+ if (_ScrollBarSliderBorder)
+ {
+ _ScrollBarSliderBorder->Paint(0, _nobPos[0], wide, _nobPos[1]);
+ }
+ }
+ else
+ {
+ // horizontal nob
+ surface()->DrawFilledRect(_nobPos[0], 1, _nobPos[1], tall - 2 );
+
+ // border
+ if (_ScrollBarSliderBorder)
+ {
+ _ScrollBarSliderBorder->Paint(_nobPos[0] - 1, 1, _nobPos[1], tall );
+ }
+ }
+
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void ScrollBarSlider::PaintBackground()
+{
+// BaseClass::PaintBackground();
+
+ int wide,tall;
+ GetPaintSize(wide,tall);
+ surface()->DrawSetColor(GetBgColor());
+ surface()->DrawFilledRect(0, 0, wide-1, tall-1);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Set the range of the ScrollBarSlider
+//-----------------------------------------------------------------------------
+void ScrollBarSlider::SetRange(int min,int max)
+{
+ if(max<min)
+ {
+ max=min;
+ }
+
+ if(min>max)
+ {
+ min=max;
+ }
+
+ _range[0]=min;
+ _range[1]=max;
+
+ // update the value (forces it within the range)
+ SetValue( _value );
+ InvalidateLayout();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Get the range values of the ScrollBarSlider
+//-----------------------------------------------------------------------------
+void ScrollBarSlider::GetRange(int& min,int& max)
+{
+ min=_range[0];
+ max=_range[1];
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Respond to cursor movements, we only care about clicking and dragging
+//-----------------------------------------------------------------------------
+void ScrollBarSlider::OnCursorMoved(int x,int y)
+{
+ if (!_dragging)
+ {
+ return;
+ }
+
+// input()->GetCursorPos(x, y);
+// ScreenToLocal(x, y);
+
+ int wide, tall;
+ GetPaintSize(wide, tall);
+
+ if (_vertical)
+ {
+ _nobPos[0] = _nobDragStartPos[0] + (y - _dragStartPos[1]);
+ _nobPos[1] = _nobDragStartPos[1] + (y - _dragStartPos[1]);
+
+ if (_nobPos[1] > tall)
+ {
+ _nobPos[0] = tall - (_nobPos[1] - _nobPos[0]);
+ _nobPos[1] = tall;
+ SetValue( _range[1] - _rangeWindow );
+ }
+ }
+ else
+ {
+ _nobPos[0] = _nobDragStartPos[0] + (x - _dragStartPos[0]);
+ _nobPos[1] = _nobDragStartPos[1] + (x - _dragStartPos[0]);
+
+ if (_nobPos[1] > wide)
+ {
+ _nobPos[0] = wide - (_nobPos[1] - _nobPos[0]);
+ _nobPos[1] = wide;
+ }
+
+ }
+ if (_nobPos[0] < 0)
+ {
+ _nobPos[1] = _nobPos[1] - _nobPos[0];
+ _nobPos[0] = 0;
+ SetValue(0);
+ }
+
+ InvalidateLayout(); // not invalidatelayout - because it won't draw while we're scrolling the slider
+ RecomputeValueFromNobPos();
+// Repaint();
+ SendScrollBarSliderMovedMessage();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Respond to mouse clicks on the ScrollBarSlider
+//-----------------------------------------------------------------------------
+void ScrollBarSlider::OnMousePressed(MouseCode code)
+{
+ int x,y;
+ input()->GetCursorPos(x,y);
+ ScreenToLocal(x,y);
+
+ if (_vertical)
+ {
+ if ((y >= _nobPos[0]) && (y < _nobPos[1]))
+ {
+ _dragging = true;
+ input()->SetMouseCapture(GetVPanel());
+ _nobDragStartPos[0] = _nobPos[0];
+ _nobDragStartPos[1] = _nobPos[1];
+ _dragStartPos[0] = x;
+ _dragStartPos[1] = y;
+ }
+ else if (y < _nobPos[0])
+ {
+ // jump the bar up by the range window
+ int val = GetValue();
+ val -= _rangeWindow;
+ SetValue(val);
+ }
+ else if (y >= _nobPos[1])
+ {
+ // jump the bar down by the range window
+ int val = GetValue();
+ val += _rangeWindow;
+ SetValue(val);
+ }
+ }
+ else
+ {
+ if((x >= _nobPos[0]) && (x < _nobPos[1]))
+ {
+ _dragging = true;
+ input()->SetMouseCapture(GetVPanel());
+ _nobDragStartPos[0] = _nobPos[0];
+ _nobDragStartPos[1] = _nobPos[1];
+ _dragStartPos[0] = x;
+ _dragStartPos[1] = y;
+ }
+ else if (x < _nobPos[0])
+ {
+ // jump the bar up by the range window
+ int val = GetValue();
+ val -= _rangeWindow;
+ SetValue(val);
+ }
+ else if (x >= _nobPos[1])
+ {
+ // jump the bar down by the range window
+ int val = GetValue();
+ val += _rangeWindow;
+ SetValue(val);
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Treat double clicks as single clicks
+//-----------------------------------------------------------------------------
+void ScrollBarSlider::OnMouseDoublePressed(MouseCode code)
+{
+ OnMousePressed(code);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Stop looking for mouse events when mouse is up.
+//-----------------------------------------------------------------------------
+void ScrollBarSlider::OnMouseReleased(MouseCode code)
+{
+ _dragging = false;
+ input()->SetMouseCapture(null);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Get the position of the ends of the ScrollBarSlider.
+//-----------------------------------------------------------------------------
+void ScrollBarSlider::GetNobPos(int& min, int& max)
+{
+ min=_nobPos[0];
+ max=_nobPos[1];
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Set the number of lines visible in the window the ScrollBarSlider is attached to
+//-----------------------------------------------------------------------------
+void ScrollBarSlider::SetRangeWindow(int rangeWindow)
+{
+ _rangeWindow = rangeWindow;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Get the number of lines visible in the window the ScrollBarSlider is attached to
+//-----------------------------------------------------------------------------
+int ScrollBarSlider::GetRangeWindow()
+{
+ return _rangeWindow;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void ScrollBarSlider::SetButtonOffset(int buttonOffset)
+{
+ _buttonOffset = buttonOffset;
+}
\ No newline at end of file |