You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdemultimedia/kmix/ksmallslider.cpp

517 lines
13 KiB

/*
* KMix -- KDE's full featured mini mixer
*
*
* Copyright (C) 2000 Stefan Schimanski <1Stein@gmx.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <kdebug.h>
#include <tqwidget.h>
#include <tqpainter.h>
#include <tqcolor.h>
#include <tqbrush.h>
#include <tqstyle.h>
#include "tdeglobalsettings.h"
#include "ksmallslider.h"
/*
static const TQColor mutedHighColor2 = "#FFFFFF";
static const TQColor mutedLowColor2 = "#808080";
static const TQColor backColor2 = "#000000";
*/
KSmallSlider::KSmallSlider( TQWidget *parent, const char *name )
: TQWidget( parent, name ), _orientation( TQt::Vertical )
{
init();
}
KSmallSlider::KSmallSlider( TQt::Orientation orientation, TQWidget *parent, const char *name )
: TQWidget( parent, name ), _orientation( orientation )
{
init();
}
KSmallSlider::KSmallSlider( int minValue, int maxValue, int pageStep,
int value, TQt::Orientation orientation,
TQWidget *parent, const char *name )
: TQWidget( parent, name ),
TQRangeControl( minValue, maxValue, 1, pageStep, value ), _orientation( orientation)
{
init();
// sliderVal = value;
}
void KSmallSlider::init()
{
// !! the following 2 values must be -1, to make sure the values are not the real values.
// Otherwise some code below could determine that no change has happened and to send
// no signals or to do no initial paint.
// sliderPos = -1;
// state = Idle;
//track = TRUE;
//setMouseTracking(true);
grayed = false;
setFocusPolicy( TQWidget::TabFocus );
colHigh = TQColor(0,255,0);
colLow = TQColor(255,0,0);
colBack = TQColor(0,0,0);
grayHigh = TQColor(255,255,255);
grayLow = TQColor(128,128,128);
grayBack = TQColor(0,0,0);
}
/*
void KSmallSlider::setTracking( bool enable )
{
track = enable;
}
*/
int KSmallSlider::positionFromValue( int v ) const
{
return TQRangeControl::positionFromValue( v, available() );
}
int KSmallSlider::valueFromPosition( int p ) const
{
if ( _orientation == TQt::Vertical ) {
// Coordiante System starts at TopLeft, but the slider values increase from Bottom to Top
// Thus "revert" the position
int avail = available();
return TQRangeControl::valueFromPosition( avail - p, avail );
}
else {
//Horizontal everything is fine. Slider values match with Coordinate System
return TQRangeControl::valueFromPosition( p, available() );
}
}
void KSmallSlider::rangeChange()
{
/*
int newPos = positionFromValue( TQRangeControl::value() );
if ( newPos != sliderPos ) {
sliderPos = newPos;
}
*/
update();
}
void KSmallSlider::valueChange()
{
//kdDebug(67100) << "KSmallSlider::valueChange() value=" << value() << "\n";
update();
emit valueChanged(value());
/*
if ( sliderVal != TQRangeControl::value() ) {
//int newPos = positionFromValue( TQRangeControl::value() );
//sliderPos = newPos;
sliderVal = TQRangeControl::value();
update();
emit valueChanged(value());
}
*/
}
void KSmallSlider::resizeEvent( TQResizeEvent * )
{
update();
//TQWidget::resizeEvent( ev );
}
// Returns the really available space for the slider. If there is no space, 0 is returned;
int KSmallSlider::available() const
{
int available = 0;
if ( _orientation == TQt::Vertical) {
available = height();
}
else {
available = width();
}
if ( available > 1 ) {
available -= 2;
}
else {
available = 0;
}
return available;
}
namespace
{
void gradient( TQPainter &p, bool hor, const TQRect &rect, const TQColor &ca, const TQColor &cb, int /*ncols*/)
{
int rDiff, gDiff, bDiff;
int rca, gca, bca, rcb, gcb, bcb;
int x, y;
if ((rect.width()<=0) || (rect.height()<=0)) return;
rDiff = (rcb = cb.red()) - (rca = ca.red());
gDiff = (gcb = cb.green()) - (gca = ca.green());
bDiff = (bcb = cb.blue()) - (bca = ca.blue());
int rl = rca << 16;
int gl = gca << 16;
int bl = bca << 16;
int rcdelta = ((1<<16) / ((!hor) ? rect.height() : rect.width())) * rDiff;
int gcdelta = ((1<<16) / ((!hor) ? rect.height() : rect.width())) * gDiff;
int bcdelta = ((1<<16) / ((!hor) ? rect.height() : rect.width())) * bDiff;
// these for-loops could be merged, but the if's in the inner loop
// would make it slow
if (!hor)
{
for ( y = rect.top(); y <= rect.bottom(); y++ ) {
rl += rcdelta;
gl += gcdelta;
bl += bcdelta;
p.setPen(TQColor(rl>>16, gl>>16, bl>>16));
p.drawLine(rect.left(), y, rect.right(), y);
}
} else
{
for( x = rect.left(); x <= rect.right(); x++) {
rl += rcdelta;
gl += gcdelta;
bl += bcdelta;
p.setPen(TQColor(rl>>16, gl>>16, bl>>16));
p.drawLine(x, rect.top(), x, rect.bottom());
}
}
}
TQColor interpolate( TQColor low, TQColor high, int percent ) {
if ( percent<=0 ) return low; else
if ( percent>=100 ) return high; else
return TQColor(
low.red() + (high.red()-low.red()) * percent/100,
low.green() + (high.green()-low.green()) * percent/100,
low.blue() + (high.blue()-low.blue()) * percent/100 );
}
}
void KSmallSlider::paintEvent( TQPaintEvent * )
{
// kdDebug(67100) << "KSmallSlider::paintEvent: width() = " << width() << ", height() = " << height() << endl;
TQPainter p( this );
int sliderPos = positionFromValue( TQRangeControl::value() );
// ------------------------ draw 3d border ---------------------------------------------
style().drawPrimitive ( TQStyle::PE_Panel, &p, TQRect( 0, 0, width(), height() ), colorGroup(), TRUE );
// ------------------------ draw lower/left part ----------------------------------------
if ( width()>2 && height()>2 )
{
if ( _orientation == TQt::Horizontal ) {
TQRect outer = TQRect( 1, 1, sliderPos, height() - 2 );
// kdDebug(67100) << "KSmallSlider::paintEvent: outer = " << outer << endl;
if ( grayed )
gradient( p, true, outer, grayLow,
interpolate( grayLow, grayHigh, 100*sliderPos/(width()-2) ),
32 );
else
gradient( p, true, outer, colLow,
interpolate( colLow, colHigh, 100*sliderPos/(width()-2) ),
32 );
}
else {
TQRect outer = TQRect( 1, height()-sliderPos-1, width() - 2, sliderPos-1 );
/*
kdDebug(67100) << "KSmallSlider::paintEvent: sliderPos=" << sliderPos
<< "height()=" << height()
<< "width()=" << width()
<< "outer = " << outer << endl;
*/
if ( grayed )
gradient( p, false, outer,
interpolate( grayLow, grayHigh, 100*sliderPos/(height()-2) ),
grayLow, 32 );
else
gradient( p, false, outer,
interpolate( colLow, colHigh, 100*sliderPos/(height()-2) ),
colLow, 32 );
}
// -------- draw upper/right part --------------------------------------------------
TQRect inner;
if ( _orientation == TQt::Vertical ) {
inner = TQRect( 1, 1, width() - 2, height() - 2 -sliderPos );
}
else {
inner = TQRect( sliderPos + 1, 1, width() - 2 - sliderPos, height() - 2 );
}
if ( grayed ) {
p.setBrush( grayBack );
p.setPen( grayBack );
} else {
p.setBrush( colBack );
p.setPen( colBack );
}
p.drawRect( inner );
}
}
void KSmallSlider::mousePressEvent( TQMouseEvent *e )
{
//resetState();
if ( e->button() == TQt::RightButton ) {
return;
}
// state = Dragging;
//emit sliderPressed();
int pos = goodPart( e->pos() );
moveSlider( pos );
}
void KSmallSlider::mouseMoveEvent( TQMouseEvent *e )
{
/*
if ( state != Dragging )
return;
*/
int pos = goodPart( e->pos() );
moveSlider( pos );
}
void KSmallSlider::wheelEvent( TQWheelEvent * e)
{
// kdDebug(67100) << "KSmallslider::wheelEvent()" << endl;
/* Unfortunately KSmallSlider is no MixDeviceWidget, so we don't have access to
* the MixDevice.
*/
int inc = ( maxValue() - minValue() ) / 20;
if ( inc < 1)
inc = 1;
//kdDebug(67100) << "KSmallslider::wheelEvent() inc=" << inc << "delta=" << e->delta() << endl;
if ( e->delta() > 0 ) {
TQRangeControl::setValue( TQRangeControl::value() + inc );
}
else {
TQRangeControl::setValue( TQRangeControl::value() - inc );
}
e->accept(); // Accept the event
// Hint: TQt autmatically triggers a valueChange() when we do setValue()
}
void KSmallSlider::mouseReleaseEvent( TQMouseEvent * )
{
//resetState();
}
/*
* Moves slider to a dedicated position. If the value has changed
*/
void KSmallSlider::moveSlider( int pos )
{
int a = available();
int newPos = TQMIN( a, TQMAX( 0, pos ) ); // keep it inside the available bounds of the slider
int newVal = valueFromPosition( newPos );
if ( newVal != TQRangeControl::value() ) {
//TQRangeControl::directSetValue( sliderVal );
TQRangeControl::setValue( newVal );
emit valueChanged( value() ); // Only for external use
}
update();
}
/*
void KSmallSlider::resetState()
{
switch ( state ) {
case Dragging: {
TQRangeControl::setValue( valueFromPosition( sliderPos ) );
emit sliderReleased();
break;
}
case Idle:
break;
default:
tqWarning("KSmallSlider: (%s) in wrong state", name( "unnamed" ) );
}
state = Idle;
}
*/
void KSmallSlider::setValue( int value )
{
TQRangeControl::setValue( value );
}
void KSmallSlider::addStep()
{
addPage();
}
void KSmallSlider::subtractStep()
{
subtractPage();
}
int KSmallSlider::goodPart( const TQPoint &p ) const
{
if ( _orientation == TQt::Vertical ) {
return p.y() - 1;
}
else {
return p.x() - 1;
}
}
/***************** SIZE STUFF START ***************/
TQSize KSmallSlider::sizeHint() const
{
//constPolish();
const int length = 25;
const int thick = 10;
if ( _orientation == TQt::Vertical )
return TQSize( thick, length );
else
return TQSize( length, thick );
}
TQSize KSmallSlider::minimumSizeHint() const
{
TQSize s(10,10);
return s;
}
TQSizePolicy KSmallSlider::sizePolicy() const
{
if ( _orientation == TQt::Vertical ) {
//kdDebug(67100) << "KSmallSlider::sizePolicy() vertical value=(Fixed,MinimumExpanding)\n";
return TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Expanding );
}
else {
//kdDebug(67100) << "KSmallSlider::sizePolicy() horizontal value=(MinimumExpanding,Fixed)\n";
return TQSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Fixed );
}
}
/***************** SIZE STUFF END ***************/
int KSmallSlider::minValue() const
{
return TQRangeControl::minValue();
}
int KSmallSlider::maxValue() const
{
return TQRangeControl::maxValue();
}
int KSmallSlider::lineStep() const
{
return TQRangeControl::lineStep();
}
int KSmallSlider::pageStep() const
{
return TQRangeControl::pageStep();
}
void KSmallSlider::setLineStep( int i )
{
setSteps( i, pageStep() );
}
void KSmallSlider::setPageStep( int i )
{
setSteps( lineStep(), i );
}
// Only for external acces. You MUST use TQRangeControl::value() internally.
int KSmallSlider::value() const
{
return TQRangeControl::value();
}
/*
void KSmallSlider::paletteChange ( const TQPalette &) {
if ( grayed ) {
setColors(mutedLowColor2, mutedHighColor2, backColor2 );
}
else {
// ignore the TQPalette and use the values from TDEGlobalSettings instead
//const TQColorGroup& qcg = palette().active();
setColors(TDEGlobalSettings::baseColor(), TDEGlobalSettings::highlightColor(), backColor2 );
}
}
*/
void KSmallSlider::setGray( bool value )
{
if ( grayed!=value )
{
grayed = value;
update();
//repaint();
}
}
bool KSmallSlider::gray() const
{
return grayed;
}
void KSmallSlider::setColors( TQColor high, TQColor low, TQColor back )
{
colHigh = high;
colLow = low;
colBack = back;
update();
//repaint();
}
void KSmallSlider::setGrayColors( TQColor high, TQColor low, TQColor back )
{
grayHigh = high;
grayLow = low;
grayBack = back;
update();
//repaint();
}
#include "ksmallslider.moc"