diff --git a/bazaar/SliderCtrlX/SliderCtrlX.cpp b/bazaar/SliderCtrlX/SliderCtrlX.cpp new file mode 100644 index 000000000..2fa7f5c98 --- /dev/null +++ b/bazaar/SliderCtrlX/SliderCtrlX.cpp @@ -0,0 +1,361 @@ +#include + +using namespace Upp; + +#include "SliderCtrlX.h" + + +#define BORDER_SIZE 2 +#define BORDER1 BORDER_SIZE +#define BORDER2 ( 2 * BORDER_SIZE ) + + +SliderCtrlX::SliderCtrlX() +: m_nMin(0) +, m_nMax(100) +, m_nStep(1) +, m_bRound_step(true) +, m_bJump(false) +, m_bUseCustomThumbs( 0 ) +, m_nMajorTicks( 0 ) +, m_nMinorTicks( 0 ) +, m_nMajorTickSize( 30 ) +, m_nMinorTickSize( 20 ) +, m_TickPosition( TOP ) +{ + SetValue( 0 ); + + Transparent(); + NoWantFocus(); +} + +SliderCtrlX::~SliderCtrlX() {} + + +bool SliderCtrlX::IsVert() const +{ + return GetSize().cx < GetSize().cy; +} + +int SliderCtrlX::HoVe(int x, int y) const +{ + return IsVert() ? y : x; +} + +int& SliderCtrlX::HoVeR(int& x, int& y) const +{ + return IsVert() ? y : x; +} + +void SliderCtrlX::Paint(Draw& w) +{ + Size size = GetSize(); + + // draw gradations + for( int i = Min(); + ( m_nMajorTicks > 0 ) && ( i <= Max() ) ; + i += ( m_nMinorTicks == 0 ? m_nMajorTicks : m_nMinorTicks ) ) { + + int nPos = SliderToClient( i ); + + if( ( m_nMajorTicks != 0 ) && ( i % m_nMajorTicks ) == 0 ) + DrawTick( w, MAJOR, (HOVE)HoVe( HORZ, VERT ), nPos, i ); + else if( ( m_nMinorTicks != 0 ) && ( i % m_nMinorTicks ) == 0 ) + DrawTick( w, MINOR, (HOVE)HoVe( HORZ, VERT ), nPos, i ); + } + + if(IsVert()) { // Vertical slider + // Draw Line Border + int half = size.cx >> 1; + DrawBorder(w, half - BORDER1, BORDER1, BORDER2, size.cy - BORDER2, InsetBorder); + + // Draw thumbs + for( int i = m_vValues.GetCount() - 1 ; i >= 0 ; i-- ) { + if(!IsNull(m_vValues[i])) + w.DrawImage((size.cx - ( m_bUseCustomThumbs ? m_vThumbImgs[i].GetSize().cx : CtrlImg::vthumb().GetSize().cx ) ) >> 1, + max( SliderToClient(m_vValues[i]) - ( ( m_bUseCustomThumbs ? m_vThumbImgs[i].GetSize().cy : CtrlImg::vthumb().GetSize().cy ) >> 1 ), 0 ), + HasCapture() || HasFocus() ? ( m_bUseCustomThumbs ? m_vThumbImgsFocus[i] : CtrlImg::vthumb1() ) : ( m_bUseCustomThumbs ? m_vThumbImgs[i] : CtrlImg::vthumb() ) ); + } + } + else { // Horz slider + // Draw Line Border + int half = size.cy >> 1; + DrawBorder(w, BORDER1, half - BORDER1, size.cx - BORDER2, BORDER2, InsetBorder); + + // draw thumbs + for( int i = m_vValues.GetCount() - 1 ; i >= 0 ; i-- ) { + if(!IsNull(m_vValues[i])) + w.DrawImage(max( SliderToClient(m_vValues[i]) - ( ( m_bUseCustomThumbs ? m_vThumbImgs[i].GetSize().cx : CtrlImg::hthumb().GetSize().cx ) >> 1 ), 0), + (size.cy - ( m_bUseCustomThumbs ? m_vThumbImgs[i].GetSize().cy : CtrlImg::hthumb().GetSize().cy )) >> 1, + HasCapture() || HasFocus() ? (m_bUseCustomThumbs ? m_vThumbImgsFocus[i] : CtrlImg::hthumb1()) : (m_bUseCustomThumbs ? m_vThumbImgs[i] : CtrlImg::hthumb() )); + } + } + if(HasFocus()) + DrawFocus(w, size); +} + +void SliderCtrlX::DrawTick( Draw &w, MAJORMINOR Type, HOVE Orientation, int nPos, int nVal ) +{ + Size size = GetSize(); + int nMajorWidth = 3; + + String txt; + + if (LabelFormat) + LabelFormat(txt, nVal); + else + txt = AsString(nVal); + + if( Orientation == HORZ ) { + if( Type == MAJOR ) { + int nSize = (int)( m_nMajorTickSize / 100.0f * size.cy * .5 + 0.5f ); + w.DrawLine( max( nPos, nMajorWidth >> 1 ), (int)( size.cy * .5 + .5), max( nPos, nMajorWidth >> 1 ), (int)(size.cy * .5 + ( m_TickPosition == TOP ? -nSize : nSize ) + 0.5f), nMajorWidth ); + + Size sz = GetTextSize( txt, StdFont() ); + int nTextPos = nPos - (int)( sz.cx / 2.0f + 0.5f ); + nTextPos = min( max( 0, nTextPos ), size.cx - sz.cx ); + w.DrawText( nTextPos, 0, txt ); + } + else { + int nSize = (int)( m_nMinorTickSize / 100.0f * size.cy * .5 + 0.5f ); + w.DrawLine( nPos, size.cy / 2, nPos, (int)(size.cy * .5 + ( m_TickPosition == TOP ? -nSize : nSize ) + 0.5f) ); + } + } + else {// vert + if( Type == MAJOR ) { + int nSize = (int)( m_nMajorTickSize / 100.0f * size.cx * .5 + 0.5f ); + w.DrawLine( (int)( size.cx * .5 + .5), max( nPos, nMajorWidth >> 1 ), (int)(size.cx * .5 + ( m_TickPosition == TOP ? -nSize : nSize ) + 0.5f), max( nPos, nMajorWidth >> 1 ), nMajorWidth ); + + Size sz = GetTextSize( txt, StdFont() ); + int nTextPos = nPos - (int)( sz.cy / 2.0f + 0.5f ); + nTextPos = min( max( 0, nTextPos ), size.cy - sz.cy ); + w.DrawText( 0, nTextPos, txt ); + } + else { + int nSize = (int)( m_nMinorTickSize / 100.0f * size.cx * .5 + 0.5f ); + w.DrawLine( size.cx / 2, nPos, (int)(size.cx * .5 + ( m_TickPosition == TOP ? -nSize : nSize ) + 0.5f), nPos ); + } + } +} + +bool SliderCtrlX::Key(dword key, int repcnt) +{ + if(IsEditable()) + switch(key) { + case K_LEFT: + case K_UP: + Dec(); + return true; + case K_RIGHT: + case K_DOWN: + Inc(); + return true; + } + return Ctrl::Key(key, repcnt); +} + +void SliderCtrlX::LeftDown(Point pos, dword keyflags) +{ + if(!IsEditable()) + return; + SetWantFocus(); + int thumbPos = SliderToClient(m_vValues[0]); + int p = HoVe(pos.x, pos.y); + int nHalfThumb = HoVe(m_bUseCustomThumbs ? m_vThumbImgs[0].GetSize().cx : CtrlImg::hthumb().GetSize().cx, + m_bUseCustomThumbs ? m_vThumbImgs[0].GetSize().cy : CtrlImg::vthumb().GetSize().cy) >> 1; + + if(IsNull(thumbPos)) { + SetValue( ClientToSlider(p) ); + WhenSlideFinish(); + UpdateActionRefresh(); + } + // Did we click on the thumb? + else if( ( p >= ( thumbPos - nHalfThumb ) ) && + ( p < ( thumbPos + nHalfThumb ) ) ) + SetCapture(); + + else if( m_bJump ) + { + m_vValues[0] = ClientToSlider(p); + WhenSlideFinish(); + UpdateActionRefresh(); + } + else + { + if( ( ( p < thumbPos) && (m_nMin == Min() ) ) || ( (p > thumbPos) && ( m_nMin == Max() ) ) ) + Dec(); + else + Inc(); + } + + Refresh(); +} + +void SliderCtrlX::LeftRepeat(Point p, dword f) +{ + if(!HasCapture()) + LeftDown(p, f); +} + +void SliderCtrlX::LeftUp(Point pos, dword keyflags) +{ + if (HasCapture()) + WhenSlideFinish(); + Refresh(); +} + +void SliderCtrlX::MouseMove(Point pos, dword keyflags) +{ + if(HasCapture()) { + int n = ClientToSlider(HoVe(pos.x, pos.y)); + if(n != m_vValues[0]) { + SetValue( n ); + UpdateActionRefresh(); + } + } +} + +SliderCtrlX& SliderCtrlX::MinMax(int _min, int _max) +{ + if(m_nMin != _min || m_nMax != _max) { + m_nMin = _min; + m_nMax = _max; + if(!IsNull(m_vValues[0])) { + int v = minmax(m_vValues[0], Min(), Max()); + if(m_vValues[0] != v) { + SetValue( v ); + Update(); + } + } + Refresh(); + } + return *this; +} + +int SliderCtrlX::SliderToClient(int v) const +{ + if(IsNull(v)) + return Null; + v = minmax(v, Min(), Max()); + + if( v < 0 ) + v = iscalefloor(v - m_nMin, HoVe(GetSize().cx - BORDER2, + GetSize().cy - BORDER2), m_nMax - m_nMin); + else + v = iscaleceil(v - m_nMin, HoVe(GetSize().cx - BORDER2, + GetSize().cy - BORDER2), m_nMax - m_nMin); + return v; +} + +int SliderCtrlX::ClientToSlider(int p) const +{ + return minmax(m_nMin + iscale(p, m_nMax - m_nMin, + HoVe(GetSize().cx - BORDER2, GetSize().cy - BORDER2)), Min(), Max()); +} + +void SliderCtrlX::Dec() +{ + int n = m_vValues[0]; + if(IsNull(m_vValues[0])) + n = Max(); + else + if(n > Min()) { + if(m_bRound_step && m_nStep > 1) + n = idivfloor(n - 1, m_nStep) * m_nStep; + else + n -= m_nStep; + if(n < Min()) + n = Min(); + } + if(n != m_vValues[0]) { + SetValue( n ); + WhenSlideFinish(); + UpdateActionRefresh(); + } +} + +void SliderCtrlX::Inc() +{ + int n = m_vValues[0]; + if(IsNull(m_vValues[0])) + n = Min(); + else + if(n < Max()) { + if(m_bRound_step && m_nStep > 1) + n = idivceil(n + 1, m_nStep) * m_nStep; + else + n += m_nStep; + if(n > Max()) + n = Max(); + } + if(n != m_vValues[0]) { + SetValue( n ); + WhenSlideFinish(); + UpdateActionRefresh(); + } +} + + +SliderCtrlX& SliderCtrlX::AddOutCtrl( Ctrl* c ) +{ + m_vctrlOutput.Add( c ); + + return *this; +} + + +void SliderCtrlX::SetData(const Value& v) +{ + SetValue( v ); +/* int i = v; + if(!IsNull(i)) + i = minmax(i, Min(), Max() ); + + if(i != m_vValues[0]) { + SetValue( i ); + UpdateRefresh(); + }*/ +} + +Value SliderCtrlX::GetData( int nIndex ) const +{ + return m_vValues[nIndex]; +} + +Value SliderCtrlX::GetData() const +{ + return m_vValues[0]; +} + +Value SliderCtrlX::SetValue( const Value& v, int nIndex /*= 0 */ ) +{ + int n = v; + + if(!IsNull(n)) + { + n = minmax(n, Min(), Max() ); + + if( m_vValues.At(nIndex) != n ) + { + m_vValues.At(nIndex) = n; + + if( m_vctrlOutput.GetCount() > nIndex ) + m_vctrlOutput[nIndex]->SetData( n ); + + UpdateRefresh(); + } + } + + return m_vValues.At(nIndex); +} + +void SliderCtrlX::GotFocus() +{ + Refresh(); +} + +void SliderCtrlX::LostFocus() +{ + Refresh(); +} + diff --git a/bazaar/SliderCtrlX/SliderCtrlX.h b/bazaar/SliderCtrlX/SliderCtrlX.h new file mode 100644 index 000000000..39eb9830b --- /dev/null +++ b/bazaar/SliderCtrlX/SliderCtrlX.h @@ -0,0 +1,95 @@ + +class SliderCtrlX : public Ctrl { + + typedef enum { HORZ, VERT } HOVE; + + typedef enum { MAJOR, MINOR } MAJORMINOR; + +public: + typedef enum { TOP, MIDDLE_TOP, MIDDLE_BOTTOM, BOTTOM, + RIGHT = TOP, LEFT = BOTTOM, MIDDLE_LEFT = MIDDLE_BOTTOM, MIDDLE_RIGHT = MIDDLE_TOP } TICK_ALIGNMENT; + +private: + Vector m_vValues; + Vector m_vThumbImgs; + Vector m_vThumbImgsFocus; + + int m_nMin, m_nMax, m_nStep; + bool m_bRound_step; + bool m_bJump; + bool m_bUseCustomThumbs; + + int SliderToClient(int value) const; + int ClientToSlider(int x) const; + + int HoVe(int x, int y) const; + int& HoVeR(int& x, int& y) const; + + int Min() const { return Upp::min( m_nMin, m_nMax ); }; + int Max() const { return Upp::max( m_nMin, m_nMax ); }; + + Vector m_vctrlOutput; + + // eg a slider from -180 to 180, setting MajorTix to 30 would put Major tix + // on the endpoints, as well as every 30, so: -180, -150, -120, -90, -60, -30, 0, 30... + // Text Labels are drawn on all Major Tick points. + // Setting MinorTix to 5 would draw minor tix every 5, eg: -175, -170, -165... + int m_nMajorTicks; // This is the "increment" for major tix + int m_nMinorTicks; // This is the "increment" for minor tix + int m_nMajorTickSize; // Percent of the space from the line to the edge, eg 30 + int m_nMinorTickSize; // Percent of the space from the line to the edge, eg 20 + TICK_ALIGNMENT m_TextAlign, m_TickPosition; + +protected: + + void DrawTick( Draw &w, MAJORMINOR Type, HOVE Orientation, int nPos, int nVal ); + +public: + typedef SliderCtrl CLASSNAME; + + Callback WhenSlideFinish; + Callback2 LabelFormat; + + SliderCtrlX(); + virtual ~SliderCtrlX(); + + void Inc(); + void Dec(); + + SliderCtrlX& MinMax(int _min, int _max); + SliderCtrlX& Range(int max) { return MinMax(0, max); } + + int GetMin() const { return m_nMin; } + int GetMax() const { return m_nMax; } + + bool IsVert() const; + + SliderCtrlX& Step(int _step, bool _r = true) { m_nStep = _step; m_bRound_step = _r; return *this; } + int GetStep() const { return m_nStep; } + bool IsRoundStep() const { return m_bRound_step; } + + void Jump(bool v = true) { m_bJump = v; } + + virtual void Paint(Draw& draw); + virtual bool Key(dword key, int repcnt); + virtual void LeftDown(Point pos, dword keyflags); + virtual void LeftRepeat(Point pos, dword keyflags); + virtual void LeftUp(Point pos, dword keyflags); + virtual void MouseMove(Point pos, dword keyflags); + virtual void GotFocus(); + virtual void LostFocus(); + + virtual void SetData(const Value& value); + Value SetValue( const Value& v, int nIndex = 0 ); + virtual Value GetData( int nIndex ) const; + virtual Value GetData() const; + + SliderCtrlX& AddOutCtrl( Ctrl* c ); + SliderCtrlX& SetMajorTicks( int n ) { m_nMajorTicks = n; return *this; }; + SliderCtrlX& SetMinorTicks( int n ) { m_nMinorTicks = n; return *this; }; + SliderCtrlX& SetMajorTicksSize( int n ) { m_nMajorTickSize = n; return *this; }; + SliderCtrlX& SetMinorTicksSize( int n ) { m_nMinorTickSize = n; return *this; }; + SliderCtrlX& SetTickPosition( TICK_ALIGNMENT n ) { m_TickPosition = n; return *this; }; + SliderCtrlX& UseCustomThumbs( bool b = true ) { m_bUseCustomThumbs = b; return *this; }; + SliderCtrlX& SetCustomThumb( Image i, int nIndex = 0 ) { m_vThumbImgs.At( nIndex ) = i; m_vThumbImgsFocus.At( nIndex ) = i; return *this; }; +}; diff --git a/bazaar/SliderCtrlX/SliderCtrlX.upp b/bazaar/SliderCtrlX/SliderCtrlX.upp new file mode 100644 index 000000000..0921e5db9 --- /dev/null +++ b/bazaar/SliderCtrlX/SliderCtrlX.upp @@ -0,0 +1,8 @@ +uses + CtrlLib; + + +file + SliderCtrlX.cpp, + SliderCtrlX.h; +