ultimatepp/bazaar/SliderCtrlX/SliderCtrlX.cpp
koldo af378cb44c SliderCtrlX: SliderCtrl plus some additions by avpavp
git-svn-id: svn://ultimatepp.org/upp/trunk@2901 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2010-12-07 23:44:07 +00:00

361 lines
8.5 KiB
C++

#include <CtrlLib/CtrlLib.h>
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();
}