diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | ce4a32fe52ef09d8f5ff1dd22c001110902b60a2 (patch) | |
tree | 5ac38a06f3dde268dc7927dc155896926aaf7012 /kstyles/plastik/plastik.cpp | |
download | tdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.tar.gz tdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kstyles/plastik/plastik.cpp')
-rw-r--r-- | kstyles/plastik/plastik.cpp | 3620 |
1 files changed, 3620 insertions, 0 deletions
diff --git a/kstyles/plastik/plastik.cpp b/kstyles/plastik/plastik.cpp new file mode 100644 index 000000000..98e7e6d49 --- /dev/null +++ b/kstyles/plastik/plastik.cpp @@ -0,0 +1,3620 @@ +/* Plastik widget style for KDE 3 + Copyright (C) 2003 Sandro Giessl <ceebx@users.sourceforge.net> + + based on the KDE style "dotNET": + + Copyright (C) 2001-2002, Chris Lee <clee@kde.org> + Carsten Pfeiffer <pfeiffer@kde.org> + Karol Szwed <gallium@kde.org> + Drawing routines completely reimplemented from KDE3 HighColor, which was + originally based on some stuff from the KDE2 HighColor. + + based on drawing routines of the style "Keramik": + + Copyright (c) 2002 Malte Starostik <malte@kde.org> + (c) 2002,2003 Maksim Orlovich <mo002j@mail.rochester.edu> + based on the KDE3 HighColor Style + Copyright (C) 2001-2002 Karol Szwed <gallium@kde.org> + (C) 2001-2002 Fredrik Höglund <fredrik@kde.org> + Drawing routines adapted from the KDE2 HCStyle, + Copyright (C) 2000 Daniel M. Duley <mosfet@kde.org> + (C) 2000 Dirk Mueller <mueller@kde.org> + (C) 2001 Martijn Klingens <klingens@kde.org> + Progressbar code based on KStyle, + Copyright (C) 2001-2002 Karol Szwed <gallium@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library 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 library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#include <qimage.h> +#include <qstylefactory.h> +#include <qpointarray.h> +#include <qpainter.h> +#include <qtabbar.h> +#include <qprogressbar.h> +#include <qcheckbox.h> +#include <qcombobox.h> +#include <qcleanuphandler.h> +#include <qheader.h> +#include <qlineedit.h> +#include <qlistbox.h> +#include <qscrollbar.h> +#include <qstyleplugin.h> +#include <qpushbutton.h> +#include <qtabwidget.h> +#include <qtimer.h> +#include <qtoolbutton.h> +#include <qtoolbar.h> +#include <qmenubar.h> +#include <qpopupmenu.h> +#include <qdrawutil.h> +#include <qapplication.h> +#include <qvariant.h> +#include <qradiobutton.h> +#include <qregion.h> +#include <qslider.h> +#include <qsettings.h> +#include <kpixmap.h> + +#include "plastik.h" +#include "plastik.moc" +#include "misc.h" + +// some bitmaps for the radio button so it's easier to handle the circle stuff... +// 13x13 +static const unsigned char radiobutton_mask_bits[] = { + 0xf8, 0x03, 0xfc, 0x07, 0xfe, 0x0f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, + 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xfe, 0x0f, 0xfc, 0x07, + 0xf8, 0x03}; +static const unsigned char radiobutton_contour_bits[] = { + 0xf0, 0x01, 0x0c, 0x06, 0x02, 0x08, 0x02, 0x08, 0x01, 0x10, 0x01, 0x10, + 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x02, 0x08, 0x02, 0x08, 0x0c, 0x06, + 0xf0, 0x01}; +static const unsigned char radiobutton_aa_inside_bits[] = { + 0x00, 0x00, 0x10, 0x01, 0x04, 0x04, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x04, 0x04, 0x10, 0x01, + 0x00, 0x00}; +static const unsigned char radiobutton_aa_outside_bits[] = { + 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x02}; +static const unsigned char radiobutton_highlight1_bits[] = { + 0x00, 0x00, 0xf0, 0x01, 0x1c, 0x07, 0x04, 0x04, 0x06, 0x0c, 0x02, 0x08, + 0x02, 0x08, 0x02, 0x08, 0x06, 0x0c, 0x04, 0x04, 0x1c, 0x07, 0xf0, 0x01, + 0x00, 0x00}; +static const unsigned char radiobutton_highlight2_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x18, 0x03, 0x08, 0x02, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x08, 0x02, 0x18, 0x03, 0xe0, 0x00, 0x00, 0x00, + 0x00, 0x00}; +// check mark +const uint CHECKMARKSIZE = 9; // 9x9 +static const unsigned char checkmark_aa_bits[] = { + 0x45, 0x01, 0x28, 0x00, 0x11, 0x01, 0x82, 0x00, 0x44, 0x00, 0x82, 0x00, + 0x11, 0x01, 0x28, 0x00, 0x45, 0x01}; +static const unsigned char checkmark_dark_bits[] = { + 0x82, 0x00, 0x45, 0x01, 0xaa, 0x00, 0x54, 0x00, 0x28, 0x00, 0x74, 0x00, + 0xea, 0x00, 0xc5, 0x01, 0x82, 0x00}; +static const unsigned char checkmark_light_bits[] = { + 0x00, 0xfe, 0x82, 0xfe, 0x44, 0xfe, 0x28, 0xfe, 0x10, 0xfe, 0x08, 0xfe, + 0x04, 0xfe, 0x02, 0xfe, 0x00, 0xfe}; +static const unsigned char checkmark_tristate_bits[] = { + 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0xff, 0x01, + 0x00, 0x00, 0xff, 0x01, 0x00, 0x00}; +// radio mark +const uint RADIOMARKSIZE = 9; // 9x9 +static const unsigned char radiomark_aa_bits[] = { + 0x00, 0x00, 0x44, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x82, 0x00, 0x44, 0x00, 0x00, 0x00}; +static const unsigned char radiomark_dark_bits[] = { + 0x00, 0x00, 0x38, 0x00, 0x44, 0x00, 0xf2, 0x00, 0xfa, 0x00, 0xfa, 0x00, + 0x7c, 0x00, 0x38, 0x00, 0x00, 0x00}; +static const unsigned char radiomark_light_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +// popupmenu item constants... +static const int itemHMargin = 6; +static const int itemFrame = 2; +static const int arrowHMargin = 6; +static const int rightBorder = 12; + +// -- Style Plugin Interface ------------------------- +class PlastikStylePlugin : public QStylePlugin +{ + public: + PlastikStylePlugin() {} + ~PlastikStylePlugin() {} + + QStringList keys() const { + return QStringList() << "Plastik"; + } + + QStyle* create( const QString& key ) { + if (key.lower() == "plastik") + return new PlastikStyle; + return 0; + } +}; + +KDE_Q_EXPORT_PLUGIN( PlastikStylePlugin ) +// -- end -- + +PlastikStyle::PlastikStyle() : KStyle( AllowMenuTransparency, ThreeButtonScrollBar), + kickerMode(false), + kornMode(false), + flatMode(false) +{ + hoverWidget = 0; + hoverTab = 0; + + + horizontalLine = 0; + verticalLine = 0; + + QSettings settings; + _contrast = settings.readNumEntry("/Qt/KDE/contrast", 6); + settings.beginGroup("/plastikstyle/Settings"); + _scrollBarLines = settings.readBoolEntry("/scrollBarLines", false); + _animateProgressBar = settings.readBoolEntry("/animateProgressBar", false); + _drawToolBarSeparator = settings.readBoolEntry("/drawToolBarSeparator", false); + _drawToolBarItemSeparator = settings.readBoolEntry("/drawToolBarItemSeparator", true); + _drawFocusRect = settings.readBoolEntry("/drawFocusRect", true); + _drawTriangularExpander = settings.readBoolEntry("/drawTriangularExpander", false); + _inputFocusHighlight = settings.readBoolEntry("/inputFocusHighlight", true); + _customOverHighlightColor = settings.readBoolEntry("/customOverHighlightColor", false); + _overHighlightColor.setNamedColor( settings.readEntry("/overHighlightColor", "black") ); + _customFocusHighlightColor = settings.readBoolEntry("/customFocusHighlightColor", false); + _focusHighlightColor.setNamedColor( settings.readEntry("/focusHighlightColor", "black") ); + _customCheckMarkColor = settings.readBoolEntry("/customCheckMarkColor", false); + _checkMarkColor.setNamedColor( settings.readEntry("/checkMarkColor", "black") ); + settings.endGroup(); + + // setup pixmap cache... + pixmapCache = new QIntCache<CacheEntry>(150000, 499); + pixmapCache->setAutoDelete(true); + + if ( _animateProgressBar ) + { + animationTimer = new QTimer( this ); + connect( animationTimer, SIGNAL(timeout()), this, SLOT(updateProgressPos()) ); + } +} + + +void PlastikStyle::updateProgressPos() +{ + QProgressBar* pb; + //Update the registered progressbars. + QMap<QWidget*, int>::iterator iter; + bool visible = false; + for (iter = progAnimWidgets.begin(); iter != progAnimWidgets.end(); ++iter) + { + if ( !::qt_cast<QProgressBar*>(iter.key()) ) + continue; + + pb = dynamic_cast<QProgressBar*>(iter.key()); + if ( iter.key() -> isEnabled() && + pb -> progress() != pb->totalSteps() ) + { + // update animation Offset of the current Widget + iter.data() = (iter.data() + 1) % 20; + iter.key()->update(); + } + if (iter.key()->isVisible()) + visible = true; + } + if (!visible) + animationTimer->stop(); +} + + +PlastikStyle::~PlastikStyle() +{ + delete pixmapCache; + delete horizontalLine; + delete verticalLine; +} + +void PlastikStyle::polish(QApplication* app) +{ + if (!qstrcmp(app->argv()[0], "kicker")) + kickerMode = true; + else if (!qstrcmp(app->argv()[0], "korn")) + kornMode = true; +} + +void PlastikStyle::polish(QWidget* widget) +{ + if( !strcmp(widget->name(), "__khtml") ) { // is it a khtml widget...? + khtmlWidgets[widget] = true; + connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(khtmlWidgetDestroyed(QObject*))); + } + + // use qt_cast where possible to check if the widget inheits one of the classes. might improve + // performance compared to QObject::inherits() + if ( ::qt_cast<QPushButton*>(widget) || ::qt_cast<QComboBox*>(widget) || + ::qt_cast<QSpinWidget*>(widget) || ::qt_cast<QSlider*>(widget) || + ::qt_cast<QCheckBox*>(widget) || ::qt_cast<QRadioButton*>(widget) || + ::qt_cast<QToolButton*>(widget) || widget->inherits("QSplitterHandle") ) + { +// widget->setBackgroundMode(PaletteBackground); + widget->installEventFilter(this); + } else if (::qt_cast<QLineEdit*>(widget)) { + widget->installEventFilter(this); + } else if (::qt_cast<QTabBar*>(widget)) { + widget->setMouseTracking(true); + widget->installEventFilter(this); + } else if (::qt_cast<QPopupMenu*>(widget)) { + widget->setBackgroundMode( NoBackground ); + } else if ( !qstrcmp(widget->name(), "kde toolbar widget") ) { + widget->installEventFilter(this); + } + + if( _animateProgressBar && ::qt_cast<QProgressBar*>(widget) ) + { + widget->installEventFilter(this); + progAnimWidgets[widget] = 0; + connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(progressBarDestroyed(QObject*))); + if (!animationTimer->isActive()) + animationTimer->start( 50, false ); + } + + KStyle::polish(widget); +} + +void PlastikStyle::unPolish(QWidget* widget) +{ + if( !strcmp(widget->name(), "__khtml") ) { // is it a khtml widget...? + khtmlWidgets.remove(widget); + } + + // use qt_cast to check if the widget inheits one of the classes. + if ( ::qt_cast<QPushButton*>(widget) || ::qt_cast<QComboBox*>(widget) || + ::qt_cast<QSpinWidget*>(widget) || ::qt_cast<QSlider*>(widget) || + ::qt_cast<QCheckBox*>(widget) || ::qt_cast<QRadioButton*>(widget) || + ::qt_cast<QToolButton*>(widget) || ::qt_cast<QLineEdit*>(widget) || + widget->inherits("QSplitterHandle") ) + { + widget->removeEventFilter(this); + } + else if (::qt_cast<QTabBar*>(widget)) { + widget->setMouseTracking(false); + widget->removeEventFilter(this); + } else if (::qt_cast<QPopupMenu*>(widget)) { + widget->setBackgroundMode( PaletteBackground ); + } else if ( !qstrcmp(widget->name(), "kde toolbar widget") ) { + widget->removeEventFilter(this); + } + + if ( ::qt_cast<QProgressBar*>(widget) ) + { + progAnimWidgets.remove(widget); + } + + KStyle::unPolish(widget); +} + +void PlastikStyle::khtmlWidgetDestroyed(QObject* obj) +{ + khtmlWidgets.remove(static_cast<QWidget*>(obj)); +} + +void PlastikStyle::progressBarDestroyed(QObject* obj) +{ + progAnimWidgets.remove(static_cast<QWidget*>(obj)); +} + +void PlastikStyle::renderContour(QPainter *p, + const QRect &r, + const QColor &backgroundColor, + const QColor &contour, + const uint flags) const +{ + if((r.width() <= 0)||(r.height() <= 0)) + return; + + const bool drawLeft = flags&Draw_Left; + const bool drawRight = flags&Draw_Right; + const bool drawTop = flags&Draw_Top; + const bool drawBottom = flags&Draw_Bottom; + const bool disabled = flags&Is_Disabled; + const bool alphaBlend = flags&Draw_AlphaBlend; + + QColor contourColor; + if (disabled) { + contourColor = backgroundColor.dark(150); + } else { + contourColor = contour; + } + +// sides + p->setPen( alphaBlendColors(backgroundColor, contourColor, 50) ); + if(drawLeft) + p->drawLine(r.left(), drawTop?r.top()+2:r.top(), r.left(), drawBottom?r.bottom()-2:r.bottom()); + if(drawRight) + p->drawLine(r.right(), drawTop?r.top()+2:r.top(), r.right(), drawBottom?r.bottom()-2:r.bottom()); + if(drawTop) + p->drawLine(drawLeft?r.left()+2:r.left(), r.top(), drawRight?r.right()-2:r.right(), r.top()); + if(drawBottom) + p->drawLine(drawLeft?r.left()+2:r.left(), r.bottom(), drawRight?r.right()-2:r.right(), r.bottom()); + +// edges + const int alphaAA = 110; // the alpha value for anti-aliasing... + + // first part... + p->setPen(alphaBlendColors(backgroundColor, contourColor, 50) ); + if(drawLeft && drawTop) { + switch(flags&Round_UpperLeft) { + case false: + p->drawPoint(r.left()+1, r.top()); + p->drawPoint(r.left(), r.top()+1); + break; + default: + p->drawPoint(r.left()+1, r.top()+1); + } + } + if(drawLeft && drawBottom) { + switch(flags&Round_BottomLeft) { + case false: + p->drawPoint(r.left()+1, r.bottom()); + p->drawPoint(r.left(), r.bottom()-1); + break; + default: + p->drawPoint(r.left()+1, r.bottom()-1); + } + } + if(drawRight && drawTop) { + switch(flags&Round_UpperRight) { + case false: + p->drawPoint(r.right()-1, r.top()); + p->drawPoint(r.right(), r.top()+1); + break; + default: + p->drawPoint(r.right()-1, r.top()+1); + } + } + if(drawRight && drawBottom) { + switch(flags&Round_BottomRight) { + case false: + p->drawPoint(r.right()-1, r.bottom()); + p->drawPoint(r.right(), r.bottom()-1); + break; + default: + p->drawPoint(r.right()-1, r.bottom()-1); + } + } + + // second part... fill edges in case we don't paint alpha-blended + p->setPen( backgroundColor ); + if (!alphaBlend) { + if(flags&Round_UpperLeft && drawLeft && drawTop) { + p->drawPoint( r.x(), r.y() ); + } + if(flags&Round_BottomLeft && drawLeft && drawBottom) { + p->drawPoint( r.x(), r.bottom() ); + } + if(flags&Round_UpperRight && drawRight && drawTop) { + p->drawPoint( r.right(), r.y() ); + } + if(flags&Round_BottomRight && drawRight && drawBottom) { + p->drawPoint( r.right(), r.bottom() ); + } + } + + // third part... anti-aliasing... + if(drawLeft && drawTop) { + switch(flags&Round_UpperLeft) { + case false: + renderPixel(p,QPoint(r.left(),r.top()),alphaAA,contourColor,backgroundColor,alphaBlend); + break; + default: + renderPixel(p,QPoint(r.left()+1,r.top()),alphaAA,contourColor,backgroundColor,alphaBlend); + renderPixel(p,QPoint(r.left(),r.top()+1),alphaAA,contourColor,backgroundColor,alphaBlend); + } + } + if(drawLeft && drawBottom) { + switch(flags&Round_BottomLeft) { + case false: + renderPixel(p,QPoint(r.left(),r.bottom()),alphaAA,contourColor,backgroundColor,alphaBlend); + break; + default: + renderPixel(p,QPoint(r.left()+1,r.bottom()),alphaAA,contourColor,backgroundColor,alphaBlend); + renderPixel(p,QPoint(r.left(),r.bottom()-1),alphaAA,contourColor,backgroundColor,alphaBlend); + } + } + if(drawRight && drawTop) { + switch(flags&Round_UpperRight) { + case false: + renderPixel(p,QPoint(r.right(),r.top()),alphaAA,contourColor,backgroundColor,alphaBlend); + break; + default: + renderPixel(p,QPoint(r.right()-1,r.top()),alphaAA,contourColor,backgroundColor,alphaBlend); + renderPixel(p,QPoint(r.right(),r.top()+1),alphaAA,contourColor,backgroundColor,alphaBlend); + } + } + if(drawRight && drawBottom) { + switch(flags&Round_BottomRight) { + case false: + renderPixel(p,QPoint(r.right(),r.bottom()),alphaAA,contourColor,backgroundColor,alphaBlend); + break; + default: + renderPixel(p,QPoint(r.right()-1,r.bottom()),alphaAA,contourColor,backgroundColor,alphaBlend); + renderPixel(p,QPoint(r.right(),r.bottom()-1),alphaAA,contourColor,backgroundColor,alphaBlend); + } + } + +} + +void PlastikStyle::renderMask(QPainter *p, + const QRect &r, + const QColor &color, + const uint flags) const +{ + if((r.width() <= 0)||(r.height() <= 0)) + return; + + const bool roundUpperLeft = flags&Round_UpperLeft; + const bool roundUpperRight = flags&Round_UpperRight; + const bool roundBottomLeft = flags&Round_BottomLeft; + const bool roundBottomRight = flags&Round_BottomRight; + + + p->fillRect (QRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2) , color); + + p->setPen(color); + // sides + p->drawLine(roundUpperLeft?r.x()+1:r.x(), r.y(), + roundUpperRight?r.right()-1:r.right(), r.y() ); + p->drawLine(roundBottomLeft?r.x()+1:r.x(), r.bottom(), + roundBottomRight?r.right()-1:r.right(), r.bottom() ); + p->drawLine(r.x(), roundUpperLeft?r.y()+1:r.y(), + r.x(), roundBottomLeft?r.bottom()-1:r.bottom() ); + p->drawLine(r.right(), roundUpperLeft?r.y()+1:r.y(), + r.right(), roundBottomLeft?r.bottom()-1:r.bottom() ); +} + +void PlastikStyle::renderSurface(QPainter *p, + const QRect &r, + const QColor &backgroundColor, + const QColor &buttonColor, + const QColor &highlightColor, + int intensity, + const uint flags) const +{ + if((r.width() <= 0)||(r.height() <= 0)) + return; + + const bool disabled = flags&Is_Disabled; + + const bool drawLeft = flags&Draw_Left; + const bool drawRight = flags&Draw_Right; + const bool drawTop = flags&Draw_Top; + const bool drawBottom = flags&Draw_Bottom; + const bool roundUpperLeft = flags&Round_UpperLeft; + const bool roundUpperRight = flags&Round_UpperRight; + const bool roundBottomLeft = flags&Round_BottomLeft; + const bool roundBottomRight = flags&Round_BottomRight; + const bool sunken = flags&Is_Sunken; + const bool horizontal = flags&Is_Horizontal; + bool highlight = false, + highlightLeft = false, + highlightRight = false, + highlightTop = false, + highlightBottom = false; + // only highlight if not sunken & not disabled... + if(!sunken && !disabled) { + highlight = (flags&Is_Highlight); + highlightLeft = (flags&Highlight_Left); + highlightRight = (flags&Highlight_Right); + highlightTop = (flags&Highlight_Top); + highlightBottom = (flags&Highlight_Bottom); + } + + QColor baseColor = alphaBlendColors(backgroundColor, disabled?backgroundColor:buttonColor, 10); + if (disabled) { + intensity = 2; + } else if (highlight) { + // blend this _slightly_ with the background + baseColor = alphaBlendColors(baseColor, highlightColor, 240); + } else if (sunken) { + // enforce a common sunken-style... + baseColor = baseColor.dark(110+intensity); + intensity = _contrast/2; + } +// some often needed colors... + // 1 more intensive than 2 and 3. + const QColor colorTop1 = alphaBlendColors(baseColor, + sunken?baseColor.dark(100+intensity*2):baseColor.light(100+intensity*2), 80); + const QColor colorTop2 = alphaBlendColors(baseColor, + sunken?baseColor.dark(100+intensity):baseColor.light(100+intensity), 80); + const QColor colorBottom1 = alphaBlendColors(baseColor, + sunken?baseColor.light(100+intensity*2):baseColor.dark(100+intensity*2), 80); + const QColor colorBottom2 = alphaBlendColors(baseColor, + sunken?baseColor.light(100+intensity):baseColor.dark(100+intensity), 80); + +// sides + if (drawLeft) { + if (horizontal) { + int height = r.height(); + if (roundUpperLeft || !drawTop) height--; + if (roundBottomLeft || !drawBottom) height--; + renderGradient(p, QRect(r.left(), (roundUpperLeft&&drawTop)?r.top()+1:r.top(), 1, height), + colorTop1, baseColor); + } else { + p->setPen(colorTop1 ); + p->drawLine(r.left(), (roundUpperLeft&&drawTop)?r.top()+1:r.top(), + r.left(), (roundBottomLeft&&drawBottom)?r.bottom()-1:r.bottom() ); + } + } + if (drawRight) { + if (horizontal) { + int height = r.height(); + // TODO: there's still a bogus in it: when edge4 is Thick + // and we don't whant to draw the Top, we have a unpainted area + if (roundUpperRight || !drawTop) height--; + if (roundBottomRight || !drawBottom) height--; + renderGradient(p, QRect(r.right(), (roundUpperRight&&drawTop)?r.top()+1:r.top(), 1, height), + baseColor, colorBottom1); + } else { + p->setPen(colorBottom1 ); + p->drawLine(r.right(), (roundUpperRight&&drawTop)?r.top()+1:r.top(), + r.right(), (roundBottomRight&&drawBottom)?r.bottom()-1:r.bottom() ); + } + } + if (drawTop) { + if (horizontal) { + p->setPen(colorTop1 ); + p->drawLine((roundUpperLeft&&drawLeft)?r.left()+1:r.left(), r.top(), + (roundUpperRight&&drawRight)?r.right()-1:r.right(), r.top() ); + } else { + int width = r.width(); + if (roundUpperLeft || !drawLeft) width--; + if (roundUpperRight || !drawRight) width--; + renderGradient(p, QRect((roundUpperLeft&&drawLeft)?r.left()+1:r.left(), r.top(), width, 1), + colorTop1, colorTop2); + } + } + if (drawBottom) { + if (horizontal) { + p->setPen(colorBottom1 ); + p->drawLine((roundBottomLeft&&drawLeft)?r.left()+1:r.left(), r.bottom(), + (roundBottomRight&&drawRight)?r.right()-1:r.right(), r.bottom() ); + } else { + int width = r.width(); + if (roundBottomLeft || !drawLeft) width--; + if (roundBottomRight || !drawRight) width--; + renderGradient(p, QRect((roundBottomLeft&&drawLeft)?r.left()+1:r.left(), r.bottom(), width, 1), + colorBottom2, colorBottom1); + } + } + +// button area... + int width = r.width(); + int height = r.height(); + if (drawLeft) width--; + if (drawRight) width--; + if (drawTop) height--; + if (drawBottom) height--; + renderGradient(p, QRect(drawLeft?r.left()+1:r.left(), drawTop?r.top()+1:r.top(), width, height), + colorTop2, colorBottom2, horizontal); + + +// highlighting... + if(highlightTop) { + p->setPen(alphaBlendColors(colorTop1 , highlightColor, 80) ); + p->drawLine((roundUpperLeft&&drawLeft)?r.left()+1:r.left(), r.top(), + (roundUpperRight&&drawRight)?r.right()-1:r.right(), r.top() ); + p->setPen(alphaBlendColors(colorTop2 , highlightColor, 150) ); + p->drawLine(highlightLeft?r.left()+1:r.left(), r.top()+1, + highlightRight?r.right()-1:r.right(), r.top()+1 ); + } + if(highlightBottom) { + p->setPen(alphaBlendColors(colorBottom1 , highlightColor, 80) ); + p->drawLine((roundBottomLeft&&drawLeft)?r.left()+1:r.left(), r.bottom(), + (roundBottomRight&&drawRight)?r.right()-1:r.right(), r.bottom() ); + p->setPen(alphaBlendColors(colorBottom2 , highlightColor, 150) ); + p->drawLine(highlightLeft?r.left()+1:r.left(), r.bottom()-1, + highlightRight?r.right()-1:r.right(), r.bottom()-1 ); + } + if(highlightLeft) { + p->setPen(alphaBlendColors(colorTop1 , highlightColor, 80) ); + p->drawLine(r.left(), (roundUpperLeft&&drawTop)?r.top()+1:r.top(), + r.left(), (roundBottomLeft&&drawBottom)?r.bottom()-1:r.bottom() ); + p->setPen(alphaBlendColors(colorTop2 , highlightColor, 150) ); + p->drawLine(r.left()+1, highlightTop?r.top()+1:r.top(), + r.left()+1, highlightBottom?r.bottom()-1:r.bottom() ); + } + if(highlightRight) { + p->setPen(alphaBlendColors(colorBottom1 , highlightColor, 80) ); + p->drawLine(r.right(), (roundUpperRight&&drawTop)?r.top()+1:r.top(), + r.right(), (roundBottomRight&&drawBottom)?r.bottom()-1:r.bottom() ); + p->setPen(alphaBlendColors(colorBottom2 , highlightColor, 150) ); + p->drawLine(r.right()-1, highlightTop?r.top()+1:r.top(), + r.right()-1, highlightBottom?r.bottom()-1:r.bottom() ); + } +} + +void PlastikStyle::renderPixel(QPainter *p, + const QPoint &pos, + const int alpha, + const QColor &color, + const QColor &background, + bool fullAlphaBlend) const +{ + if(fullAlphaBlend) + // full alpha blend: paint into an image with alpha buffer and convert to a pixmap ... + { + QRgb rgb = color.rgb(); + // generate a quite unique key -- use the unused width field to store the alpha value. + CacheEntry search(cAlphaDot, alpha, 0, rgb); + int key = search.key(); + + CacheEntry *cacheEntry; + if( (cacheEntry = pixmapCache->find(key)) ) { + if( search == *cacheEntry ) { // match! we can draw now... + if(cacheEntry->pixmap) + p->drawPixmap(pos, *(cacheEntry->pixmap) ); + return; + } else { //Remove old entry in case of a conflict! + pixmapCache->remove( key ); + } + } + + + QImage aImg(1,1,32); // 1x1 + aImg.setAlphaBuffer(true); + aImg.setPixel(0,0,qRgba(qRed(rgb),qGreen(rgb),qBlue(rgb),alpha)); + QPixmap *result = new QPixmap(aImg); + + p->drawPixmap(pos, *result); + + // add to the cache... + CacheEntry *toAdd = new CacheEntry(search); + toAdd->pixmap = result; + bool insertOk = pixmapCache->insert( key, toAdd, result->depth()/8); + if(!insertOk) + delete result; + } else + // don't use an alpha buffer: calculate the resulting color from the alpha value, the fg- and the bg-color. + { + QRgb rgb_a = color.rgb(); + QRgb rgb_b = background.rgb(); + int a = alpha; + if(a>255) a = 255; + if(a<0) a = 0; + int a_inv = 255 - a; + + QColor res = QColor( qRgb(qRed(rgb_b)*a_inv/255 + qRed(rgb_a)*a/255, + qGreen(rgb_b)*a_inv/255 + qGreen(rgb_a)*a/255, + qBlue(rgb_b)*a_inv/255 + qBlue(rgb_a)*a/255) ); + p->setPen(res); + p->drawPoint(pos); + } +} + +void PlastikStyle::renderButton(QPainter *p, + const QRect &r, + const QColorGroup &g, + bool sunken, + bool mouseOver, + bool horizontal, + bool enabled, + bool khtmlMode) const +{ + // small fix for the kicker buttons... + if(kickerMode) enabled = true; + + const QPen oldPen( p->pen() ); + + uint contourFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom; + if(!enabled) contourFlags|=Is_Disabled; + if(khtmlMode) contourFlags|=Draw_AlphaBlend; + + uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom; + if(horizontal) surfaceFlags|=Is_Horizontal; + if(!enabled) surfaceFlags|=Is_Disabled; + else { + if(sunken) surfaceFlags|=Is_Sunken; + else { + if(mouseOver) { + surfaceFlags|=Is_Highlight; + if(horizontal) { + surfaceFlags|=Highlight_Top; + surfaceFlags|=Highlight_Bottom; + } else { + surfaceFlags|=Highlight_Left; + surfaceFlags|=Highlight_Right; + } + } + } + } + + if (!flatMode) { + contourFlags |= Round_UpperLeft|Round_UpperRight|Round_BottomLeft|Round_BottomRight; + surfaceFlags |= Round_UpperLeft|Round_UpperRight|Round_BottomLeft|Round_BottomRight; + + renderContour(p, r, g.background(), getColor(g,ButtonContour), + contourFlags); + renderSurface(p, QRect(r.left()+1, r.top()+1, r.width()-2, r.height()-2), + g.background(), g.button(), getColor(g,MouseOverHighlight), _contrast, surfaceFlags); + } else { + renderContour(p, r, g.background(), g.button().dark(105+_contrast*3), + contourFlags); + renderSurface(p, QRect(r.left()+1, r.top()+1, r.width()-2, r.height()-2), + g.background(), g.button(), getColor(g,MouseOverHighlight), _contrast/2, surfaceFlags); + + flatMode = false; + } + + p->setPen(oldPen); +} + +void PlastikStyle::renderDot(QPainter *p, + const QPoint &point, + const QColor &baseColor, + const bool thick, + const bool sunken) const +{ + const QColor topColor = alphaBlendColors(baseColor, sunken?baseColor.dark(130):baseColor.light(150), 70); + const QColor bottomColor = alphaBlendColors(baseColor, sunken?baseColor.light(150):baseColor.dark(130), 70); + p->setPen(topColor ); + p->drawLine(point.x(), point.y(), point.x()+1, point.y()); + p->drawPoint(point.x(), point.y()+1); + p->setPen(bottomColor ); + if(thick) { + p->drawLine(point.x()+1, point.y()+2, point.x()+2, point.y()+2); + p->drawPoint(point.x()+2, point.y()+1); + } else { + p->drawPoint(point.x()+1, point.y()+1); + } +} + +void PlastikStyle::renderGradient(QPainter *painter, + const QRect &rect, + const QColor &c1, + const QColor &c2, + bool horizontal) const +{ + if((rect.width() <= 0)||(rect.height() <= 0)) + return; + + // generate a quite unique key for this surface. + CacheEntry search(cGradientTile, + horizontal ? 0 : rect.width(), + horizontal ? rect.height() : 0, + c1.rgb(), c2.rgb(), horizontal ); + int key = search.key(); + + CacheEntry *cacheEntry; + if( (cacheEntry = pixmapCache->find(key)) ) { + if( search == *cacheEntry ) { // match! we can draw now... + if(cacheEntry->pixmap) { + painter->drawTiledPixmap(rect, *(cacheEntry->pixmap) ); + } + return; + } else { + // Remove old entry in case of a conflict! + // This shouldn't happen very often, see comment in CacheEntry. + pixmapCache->remove(key); + } + } + + // there wasn't anything matching in the cache, create the pixmap now... + QPixmap *result = new QPixmap(horizontal ? 10 : rect.width(), + horizontal ? rect.height() : 10); + QPainter p(result); + + int r_w = result->rect().width(); + int r_h = result->rect().height(); + int r_x, r_y, r_x2, r_y2; + result->rect().coords(&r_x, &r_y, &r_x2, &r_y2); + + int rDiff, gDiff, bDiff; + int rc, gc, bc; + + register int x, y; + + rDiff = ( c2.red()) - (rc = c1.red()); + gDiff = ( c2.green()) - (gc = c1.green()); + bDiff = ( c2.blue()) - (bc = c1.blue()); + + register int rl = rc << 16; + register int gl = gc << 16; + register int bl = bc << 16; + + int rdelta = ((1<<16) / (horizontal ? r_h : r_w)) * rDiff; + int gdelta = ((1<<16) / (horizontal ? r_h : r_w)) * gDiff; + int bdelta = ((1<<16) / (horizontal ? r_h : r_w)) * bDiff; + + // these for-loops could be merged, but the if's in the inner loop + // would make it slow + if(horizontal) { + for ( y = 0; y < r_h; y++ ) { + rl += rdelta; + gl += gdelta; + bl += bdelta; + + p.setPen(QColor(rl>>16, gl>>16, bl>>16)); + p.drawLine(r_x, r_y+y, r_x2, r_y+y); + } + } else { + for( x = 0; x < r_w; x++) { + rl += rdelta; + gl += gdelta; + bl += bdelta; + + p.setPen(QColor(rl>>16, gl>>16, bl>>16)); + p.drawLine(r_x+x, r_y, r_x+x, r_y2); + } + } + + p.end(); + + // draw the result... + painter->drawTiledPixmap(rect, *result); + + // insert into cache using the previously created key. + CacheEntry *toAdd = new CacheEntry(search); + toAdd->pixmap = result; + bool insertOk = pixmapCache->insert( key, toAdd, result->width()*result->height()*result->depth()/8 ); + + if(!insertOk) + delete result; +} + +void PlastikStyle::renderPanel(QPainter *p, + const QRect &r, + const QColorGroup &g, + const bool pseudo3d, + const bool sunken) const +{ + int x, x2, y, y2, w, h; + r.rect(&x,&y,&w,&h); + r.coords(&x, &y, &x2, &y2); + + if (kickerMode && + p->device() && p->device()->devType() == QInternal::Widget && + QCString(static_cast<QWidget*>(p->device())->className()) == "FittsLawFrame") { + // Stolen wholesale from Keramik. I don't like it, but oh well. + if (sunken) { + const QCOORD corners[] = { x2, y, x2, y2, x, y2, x, y }; + p->setPen(g.background().dark()); + p->drawConvexPolygon(QPointArray(4, corners)); + p->setPen(g.background().light()); + p->drawPolyline(QPointArray(4, corners), 0, 3); + } else { + const QCOORD corners[] = { x, y2, x, y, x2, y, x2, y2 }; + p->setPen(g.background().dark()); + p->drawPolygon(QPointArray(4, corners)); + p->setPen(g.background().light()); + p->drawPolyline(QPointArray(4, corners), 0, 3); + } + } else { + renderContour(p, r, g.background(), getColor(g, PanelContour) ); + + if(pseudo3d) { + if (sunken) { + p->setPen(getColor(g, PanelDark) ); + } else { + p->setPen(getColor(g, PanelLight) ); + } + p->drawLine(r.left()+2, r.top()+1, r.right()-2, r.top()+1); + p->drawLine(r.left()+1, r.top()+2, r.left()+1, r.bottom()-2); + if (sunken) { + p->setPen(getColor(g, PanelLight) ); + } else { + p->setPen(getColor(g, PanelDark) ); + } + p->drawLine(r.left()+2, r.bottom()-1, r.right()-2, r.bottom()-1); + p->drawLine(r.right()-1, r.top()+2, r.right()-1, r.bottom()-2); + } + } +} + +void PlastikStyle::renderMenuBlendPixmap( KPixmap &pix, const QColorGroup &cg, + const QPopupMenu* /* popup */ ) const +{ + pix.fill( cg.background().light(105) ); +} + +void PlastikStyle::renderTab(QPainter *p, + const QRect &r, + const QColorGroup &g, + bool mouseOver, + const bool selected, + const bool bottom, + const TabPosition pos, + const bool triangular, + const bool cornerWidget) const +{ + const bool reverseLayout = QApplication::reverseLayout(); + + const bool isFirst = (pos == First) || (pos == Single); + const bool isLast = (pos == Last); + const bool isSingle = (pos == Single); + + if (selected) { + // is selected + + // the top part of the tab which is nearly the same for all positions + QRect Rc; // contour + if (!bottom) { + if (isFirst && !cornerWidget && !reverseLayout) { + Rc = QRect(r.x(), r.y(), r.width()-1, r.height()-3); + } else if (isFirst && !cornerWidget && reverseLayout) { + Rc = QRect(r.x()+1, r.y(), r.width()-1, r.height()-3); + } else { + Rc = QRect(r.x()+1, r.y(), r.width()-2, r.height()-3); + } + } else { + if (isFirst && !cornerWidget && !reverseLayout) { + Rc = QRect(r.x(), r.y()+3, r.width()-1, r.height()-3); + } else if (isFirst && !cornerWidget && reverseLayout) { + Rc = QRect(r.x()+1, r.y()+3, r.width()-1, r.height()-3); + } else { + Rc = QRect(r.x()+1, r.y()+3, r.width()-2, r.height()-3); + } + } + const QRect Rs(Rc.x()+1, bottom?Rc.y():Rc.y()+1, Rc.width()-2, Rc.height()-1); // the resulting surface + // the area where the fake border shoudl appear + const QRect Rb(r.x(), bottom?r.top():Rc.bottom()+1, r.width(), r.height()-Rc.height() ); + + uint contourFlags = Draw_Left|Draw_Right; + if(!bottom) { + contourFlags |= Draw_Top|Round_UpperLeft|Round_UpperRight; + } else { + contourFlags |= Draw_Bottom|Round_BottomLeft|Round_BottomRight; + } + renderContour(p, Rc, + g.background(), getColor(g,PanelContour), + contourFlags); + + // surface + if(!bottom) { + p->setPen(getColor(g,PanelLight) ); + p->drawLine(Rs.x()+1, Rs.y(), Rs.right()-1, Rs.y() ); + renderGradient(p, QRect(Rs.x(), Rs.y()+1, 1, Rs.height()-1), + getColor(g,PanelLight), getColor(g,PanelLight2)); + renderGradient(p, QRect(Rs.right(), Rs.y()+1, 1, Rs.height()-1), + getColor(g,PanelDark), getColor(g,PanelDark2)); + } else { + p->setPen(alphaBlendColors(g.background(), g.background().dark(160), 100) ); + p->drawLine(Rs.x()+1, Rs.bottom(), Rs.right()-1, Rs.bottom() ); + renderGradient(p, QRect(Rs.x(), Rs.y(), 1, Rs.height()-1), + getColor(g,PanelLight), getColor(g,PanelLight2)); + renderGradient(p, QRect(Rs.right(), Rs.y(), 1, Rs.height()-1), + getColor(g,PanelDark), getColor(g,PanelDark2)); + } + + // some "position specific" paintings... + // draw parts of the inactive tabs around... + if(!isSingle) { + p->setPen(alphaBlendColors(g.background(), getColor(g, ButtonContour), 50) ); + if( (!isFirst&&!reverseLayout) || (!isLast&&reverseLayout) ) { + p->drawPoint(r.left(), bottom?(triangular?r.bottom()-2:r.bottom()-3):(triangular?r.top()+2:r.top()+3) ); + renderSurface(p, QRect(r.left(), bottom?r.top()+3:(triangular?r.top()+3:r.top()+4), 1, (triangular?r.height()-6:r.height()-7) ), + g.background(), g.button(), getColor(g,MouseOverHighlight), _contrast, + Draw_Top|Draw_Bottom|Is_Horizontal); + } + if( (!isLast&&!reverseLayout) || (!isFirst&&reverseLayout) ) { + p->drawPoint(r.right(), bottom?(triangular?r.bottom()-2:r.bottom()-3):(triangular?r.top()+2:r.top()+3) ); + renderSurface(p, QRect(r.right(), bottom?r.top()+3:(triangular?r.top()+3:r.top()+4), 1, (triangular?r.height()-6:r.height()-7) ), + g.background(), g.button(), getColor(g,MouseOverHighlight), _contrast, + Draw_Top|Draw_Bottom|Is_Horizontal); + } + } + // left connection from the panel border to the tab. :) + if(isFirst && !reverseLayout && !cornerWidget) { + p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); + p->drawLine(Rb.x(), Rb.y(), Rb.x(), Rb.bottom() ); + p->setPen(getColor(g,PanelLight) ); + p->drawLine(Rb.x()+1, Rb.y(), Rb.x()+1, Rb.bottom() ); + } else if(isFirst && reverseLayout && !cornerWidget) { + p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); + p->drawLine(Rb.right(), Rb.y(), Rb.right(), Rb.bottom() ); + p->setPen(getColor(g,PanelDark) ); + p->drawLine(Rb.right()-1, Rb.y(), Rb.right()-1, Rb.bottom() ); + } + // rounded connections to the panel... + if(!bottom) { + // left + if( (!isFirst && !reverseLayout) || (reverseLayout) || (isFirst && !reverseLayout && cornerWidget) ) { + p->setPen( alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); + p->drawPoint(Rb.x(), Rb.y()); + p->setPen( alphaBlendColors(g.background(), getColor(g,PanelContour), 150) ); + p->drawPoint(Rb.x(), Rb.y()+1); + p->drawPoint(Rb.x()+1, Rb.y()); + } + // right + if( (!reverseLayout) || (!isFirst && reverseLayout) || (isFirst && reverseLayout && cornerWidget) ) { + p->setPen( alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); + p->drawPoint(Rb.right(), Rb.y()); + p->setPen( alphaBlendColors(g.background(), getColor(g,PanelContour), 150) ); + p->drawPoint(Rb.right(), Rb.y()+1); + p->drawPoint(Rb.right()-1, Rb.y()); + } + } else { + // left + if( (!isFirst && !reverseLayout) || (reverseLayout) || (isFirst && !reverseLayout && cornerWidget) ) { + p->setPen( alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); + p->drawPoint(Rb.x(), Rb.bottom()); + p->setPen( alphaBlendColors(g.background(), getColor(g,PanelContour), 150) ); + p->drawPoint(Rb.x(), Rb.bottom()-1); + p->drawPoint(Rb.x()+1, Rb.bottom()); + } + // right + if( (!reverseLayout) || (!isFirst && reverseLayout) || (isFirst && reverseLayout && cornerWidget) ) { + p->setPen( alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); + p->drawPoint(Rb.right(), Rb.bottom()); + p->setPen( alphaBlendColors(g.background(), getColor(g,PanelContour), 150) ); + p->drawPoint(Rb.right(), Rb.bottom()-1); + p->drawPoint(Rb.right()-1, Rb.bottom()); + } + } + + } else { + // inactive tabs + + // the top part of the tab which is nearly the same for all positions + QRect Rc; // contour + if (isFirst&&reverseLayout ) { + Rc = QRect(r.x()+1, (bottom?r.y()+2:(triangular?r.y()+2:r.y()+3)), r.width()-2, (triangular?r.height()-4:r.height()-5) ); + } else { + Rc = QRect(r.x()+1, (bottom?r.y()+2:(triangular?r.y()+2:r.y()+3)), r.width()-1, (triangular?r.height()-4:r.height()-5) ); + } + QRect Rs; // the resulting surface + if ( (isFirst&&!reverseLayout) || (isLast&&reverseLayout) ) { + Rs = QRect(Rc.x()+1, bottom?Rc.y():Rc.y()+1, Rc.width()-2, Rc.height()-1); + } else { + Rs = QRect(Rc.x(), bottom?Rc.y():Rc.y()+1, Rc.width()-1, Rc.height()-1); + } + // the area where the fake border shoudl appear + const QRect Rb(r.x(), bottom?r.y():Rc.bottom()+1, r.width(), 2 ); + + uint contourFlags; + if(!bottom) { + if ( (isFirst&&!reverseLayout) || (isLast&&reverseLayout) ) { + contourFlags = Draw_Left|Draw_Right|Draw_Top|Round_UpperLeft; + } else if ( (isLast&&!reverseLayout) || (isFirst&&reverseLayout) ) { + contourFlags = Draw_Right|Draw_Top|Round_UpperRight; + } else { + contourFlags = Draw_Right|Draw_Top; + } + } else { + if ( (isFirst&&!reverseLayout) || (isLast&&reverseLayout) ) { + contourFlags = Draw_Left|Draw_Right|Draw_Bottom|Round_BottomLeft; + } else if ( (isLast&&!reverseLayout) || (isFirst&&reverseLayout) ) { + contourFlags = Draw_Right|Draw_Bottom|Round_BottomRight; + } else { + contourFlags = Draw_Right|Draw_Bottom; + } + } + renderContour(p, Rc, + g.background(), getColor(g, ButtonContour), + contourFlags); + + uint surfaceFlags = Is_Horizontal; + if(mouseOver) { + surfaceFlags |= (bottom?Highlight_Bottom:Highlight_Top); + surfaceFlags |= Is_Highlight; + } + if ( (isFirst&&!reverseLayout) || (isLast&&reverseLayout) ) { + if(!bottom) + surfaceFlags |= Draw_Left|Draw_Top|Draw_Bottom|Round_UpperLeft; + else + surfaceFlags |= Draw_Left|Draw_Top|Draw_Bottom|Round_BottomLeft; + } else if ( (isLast&&!reverseLayout) || (isFirst&&reverseLayout) ) { + if(!bottom) + surfaceFlags |= Draw_Right|Draw_Top|Draw_Bottom|Round_UpperRight; + else + surfaceFlags |= Draw_Right|Draw_Top|Draw_Bottom|Round_BottomRight; + } else { + surfaceFlags |= Draw_Top|Draw_Bottom; + } + renderSurface(p, Rs, + g.background(), g.button(), getColor(g,MouseOverHighlight), _contrast, + surfaceFlags); + + // some "position specific" paintings... + // fake parts of the panel border + if(!bottom) { + p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); + p->drawLine(Rb.x(), Rb.y(), ((isLast&&!reverseLayout)||(isFirst&&reverseLayout&&cornerWidget))?Rb.right():Rb.right()-1, Rb.y()); + p->setPen(getColor(g,PanelLight) ); + p->drawLine(Rb.x(), Rb.y()+1, ((isLast&&!reverseLayout)||(isFirst&&reverseLayout&&cornerWidget))?Rb.right():Rb.right()-1, Rb.y()+1 ); + } else { + p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); + p->drawLine(Rb.x(), Rb.bottom(), ((isLast&&!reverseLayout)||(isFirst&&reverseLayout&&cornerWidget))?Rb.right():Rb.right()-1, Rb.bottom()); + p->setPen(getColor(g,PanelDark) ); + p->drawLine(Rb.x(), Rb.bottom()-1, ((isLast&&!reverseLayout)||(isFirst&&reverseLayout&&cornerWidget))?Rb.right():Rb.right()-1, Rb.bottom()-1 ); + } + // fake the panel border edge for tabs which are aligned left-most + // (i.e. only if there is no widget in the corner of the tabwidget!) + if(isFirst&&!reverseLayout&&!cornerWidget) + // normal layout + { + if (!bottom) { + p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); + p->drawPoint(Rb.x()+1, Rb.y()+1 ); + p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 150) ); + p->drawPoint(Rb.x(), Rb.y()+1 ); + p->setPen(g.background() ); + p->drawPoint(Rb.x(), Rb.y() ); + p->setPen(alphaBlendColors( alphaBlendColors(g.background(), getColor(g, ButtonContour), 50), getColor(g,PanelContour), 150) ); + p->drawPoint(Rb.x()+1, Rb.y() ); + } else { + p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); + p->drawPoint(Rb.x()+1, Rb.bottom()-1 ); + p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 150) ); + p->drawPoint(Rb.x(), Rb.bottom()-1 ); + p->setPen(g.background() ); + p->drawPoint(Rb.x(), Rb.bottom() ); + p->setPen(alphaBlendColors( alphaBlendColors(g.background(), getColor(g, ButtonContour), 50), getColor(g,PanelContour), 150) ); + p->drawPoint(Rb.x()+1, Rb.bottom() ); + } + } else if(isFirst&&reverseLayout&&!cornerWidget) + // reverse layout + { + if (!bottom) { + p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); + p->drawPoint(Rb.right()-1, Rb.y()+1 ); + p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 150) ); + p->drawPoint(Rb.right(), Rb.y()+1 ); + p->setPen(g.background() ); + p->drawPoint(Rb.right(), Rb.y() ); + p->setPen(alphaBlendColors( alphaBlendColors(g.background(), getColor(g, ButtonContour), 50), getColor(g,PanelContour), 150) ); + p->drawPoint(Rb.right()-1, Rb.y() ); + } else { + p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); + p->drawPoint(Rb.right()-1, Rb.bottom()-1 ); + p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 150) ); + p->drawPoint(Rb.right(), Rb.bottom()-1 ); + p->setPen(g.background() ); + p->drawPoint(Rb.right(), Rb.bottom() ); + p->setPen(alphaBlendColors( alphaBlendColors(g.background(), getColor(g, ButtonContour), 50), getColor(g,PanelContour), 150) ); + p->drawPoint(Rb.right()-1, Rb.bottom() ); + } + } + } +} + +void PlastikStyle::drawKStylePrimitive(KStylePrimitive kpe, + QPainter *p, + const QWidget* widget, + const QRect &r, + const QColorGroup &cg, + SFlags flags, + const QStyleOption& opt) const +{ + // some "global" vars... + const bool enabled = (flags & Style_Enabled); + +// SLIDER +// ------ + switch( kpe ) { + case KPE_SliderGroove: { + const QSlider* slider = (const QSlider*)widget; + bool horizontal = slider->orientation() == Horizontal; + + if (horizontal) { + int center = r.y()+r.height()/2; + renderContour(p, QRect(r.left(), center-2, r.width(), 4), + cg.background(), cg.background().dark(enabled?150:130), + Draw_Left|Draw_Right|Draw_Top|Draw_Bottom); + } else { + int center = r.x()+r.width()/2; + renderContour(p, QRect(center-2, r.top(), 4, r.height()), + cg.background(), cg.background().dark(enabled?150:130), + Draw_Left|Draw_Right|Draw_Top|Draw_Bottom); + } + break; + } + + case KPE_SliderHandle: { + const QSlider* slider = (const QSlider*)widget; + bool horizontal = slider->orientation() == Horizontal; + + const bool pressed = (flags&Style_Active); + const WidgetState s = enabled?(pressed?IsPressed:IsEnabled):IsDisabled; + const QColor contour = getColor(cg,DragButtonContour,s), + surface = getColor(cg,DragButtonSurface,s); + + int xcenter = (r.left()+r.right()) / 2; + int ycenter = (r.top()+r.bottom()) / 2; + + if (horizontal) { + renderContour(p, QRect(xcenter-5, ycenter-6, 11, 10), + cg.background(), contour, + Draw_Left|Draw_Right|Draw_Top|Round_UpperLeft|Round_UpperRight); + + // manual contour: vertex + p->setPen(alphaBlendColors(cg.background(), contour, 50) ); + p->drawPoint(xcenter-5+1, ycenter+4); + p->drawPoint(xcenter+5-1, ycenter+4); + p->drawPoint(xcenter-5+2, ycenter+5); + p->drawPoint(xcenter+5-2, ycenter+5); + p->drawPoint(xcenter-5+3, ycenter+6); + p->drawPoint(xcenter+5-3, ycenter+6); + p->drawPoint(xcenter-5+4, ycenter+7); + p->drawPoint(xcenter+5-4, ycenter+7); + // anti-aliasing of the contour... sort of. :) + p->setPen(alphaBlendColors(cg.background(), contour, 80) ); + p->drawPoint(xcenter, ycenter+8); + p->setPen(alphaBlendColors(cg.background(), contour, 150) ); + p->drawPoint(xcenter-5, ycenter+4); + p->drawPoint(xcenter+5, ycenter+4); + p->drawPoint(xcenter-5+1, ycenter+5); + p->drawPoint(xcenter+5-1, ycenter+5); + p->drawPoint(xcenter-5+2, ycenter+6); + p->drawPoint(xcenter+5-2, ycenter+6); + p->drawPoint(xcenter-5+3, ycenter+7); + p->drawPoint(xcenter+5-3, ycenter+7); + p->setPen(alphaBlendColors(cg.background(), contour, 190) ); + p->drawPoint(xcenter-5+4, ycenter+8); + p->drawPoint(xcenter+5-4, ycenter+8); + + + QRegion mask(xcenter-4, ycenter-5, 9, 13); + mask -= QRegion(xcenter-4, ycenter+4, 1, 4); + mask -= QRegion(xcenter-3, ycenter+5, 1, 3); + mask -= QRegion(xcenter-2, ycenter+6, 1, 2); + mask -= QRegion(xcenter-1, ycenter+7, 1, 1); + mask -= QRegion(xcenter+1, ycenter+7, 1, 1); + mask -= QRegion(xcenter+2, ycenter+6, 1, 2); + mask -= QRegion(xcenter+3, ycenter+5, 1, 3); + mask -= QRegion(xcenter+4, ycenter+4, 1, 4); + p->setClipRegion(mask); + uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Round_UpperLeft|Round_UpperRight|Is_Horizontal; + if(!enabled) + surfaceFlags |= Is_Disabled; + renderSurface(p, QRect(xcenter-4, ycenter-5, 9, 13), + cg.background(), surface, getColor(cg,MouseOverHighlight), + _contrast+3, surfaceFlags); + renderDot(p, QPoint(xcenter-3, ycenter-3), surface, false, true ); + renderDot(p, QPoint(xcenter+2, ycenter-3), surface, false, true ); + p->setClipping(false); + } else { + renderContour(p, QRect(xcenter-6, ycenter-5, 10, 11), + cg.background(), contour, + Draw_Left|Draw_Top|Draw_Bottom|Round_UpperLeft|Round_BottomLeft); + + // manual contour: vertex + p->setPen(alphaBlendColors(cg.background(), contour, 50) ); + p->drawPoint(xcenter+4, ycenter-5+1); + p->drawPoint(xcenter+4, ycenter+5-1); + p->drawPoint(xcenter+5, ycenter-5+2); + p->drawPoint(xcenter+5, ycenter+5-2); + p->drawPoint(xcenter+6, ycenter-5+3); + p->drawPoint(xcenter+6, ycenter+5-3); + p->drawPoint(xcenter+7, ycenter-5+4); + p->drawPoint(xcenter+7, ycenter+5-4); + // anti-aliasing. ...sort of :) + p->setPen(alphaBlendColors(cg.background(), contour, 80) ); + p->drawPoint(xcenter+8, ycenter); + p->setPen(alphaBlendColors(cg.background(), contour, 150) ); + p->drawPoint(xcenter+4, ycenter-5); + p->drawPoint(xcenter+4, ycenter+5); + p->drawPoint(xcenter+5, ycenter-5+1); + p->drawPoint(xcenter+5, ycenter+5-1); + p->drawPoint(xcenter+6, ycenter-5+2); + p->drawPoint(xcenter+6, ycenter+5-2); + p->drawPoint(xcenter+7, ycenter-5+3); + p->drawPoint(xcenter+7, ycenter+5-3); + p->setPen(alphaBlendColors(cg.background(), contour, 190) ); + p->drawPoint(xcenter+8, ycenter-5+4); + p->drawPoint(xcenter+8, ycenter+5-4); + + QRegion mask(xcenter-5, ycenter-4, 13, 9); + mask -= QRegion(xcenter+4, ycenter-4, 4, 1); + mask -= QRegion(xcenter+5, ycenter-3, 3, 1); + mask -= QRegion(xcenter+6, ycenter-2, 2, 1); + mask -= QRegion(xcenter+7, ycenter-1, 1, 1); + mask -= QRegion(xcenter+7, ycenter+1, 1, 1); + mask -= QRegion(xcenter+6, ycenter+2, 2, 1); + mask -= QRegion(xcenter+5, ycenter+3, 3, 1); + mask -= QRegion(xcenter+4, ycenter+4, 4, 1); + p->setClipRegion(mask); + uint surfaceFlags = Draw_Left|Draw_Top|Draw_Bottom|Round_UpperLeft|Round_BottomLeft| + Round_UpperRight|Is_Horizontal; + if(!enabled) + surfaceFlags |= Is_Disabled; + renderSurface(p, QRect(xcenter-5, ycenter-4, 13, 9), + cg.background(), surface, getColor(cg,MouseOverHighlight), + _contrast+3, surfaceFlags); + renderDot(p, QPoint(xcenter-3, ycenter-3), surface, false, true ); + renderDot(p, QPoint(xcenter-3, ycenter+2), surface, false, true ); + p->setClipping(false); + } + + break; + } + + case KPE_ListViewExpander: { + int radius = (r.width() - 4) / 2; + int centerx = r.x() + r.width()/2; + int centery = r.y() + r.height()/2; + + renderContour(p, r, cg.base(), cg.dark(), Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Round_UpperLeft|Round_UpperRight|Round_BottomLeft|Round_BottomRight ); + + p->setPen( cg.text() ); + if(!_drawTriangularExpander) + { + // plus or minus + p->drawLine( centerx - radius, centery, centerx + radius, centery ); + if ( flags & Style_On ) // Collapsed = On + p->drawLine( centerx, centery - radius, centerx, centery + radius ); + } else if(_drawTriangularExpander) { + if( flags & Style_On ) + drawPrimitive(PE_ArrowRight, p, QRect(r.x()+1,r.y()+1,r.width(),r.height()), cg,ButtonContour, flags); + if( flags & Style_Off ) + drawPrimitive(PE_ArrowDown, p, QRect(r.x()+1,r.y()+1,r.width(),r.height()), cg,ButtonContour, flags); + } + + break; + } + + // copied and slightly modified from KStyle. + case KPE_ListViewBranch: { + // Typical Windows style listview branch element (dotted line). + + // Create the dotline pixmaps if not already created + if ( !verticalLine ) + { + // make 128*1 and 1*128 bitmaps that can be used for + // drawing the right sort of lines. + verticalLine = new QBitmap( 1, 129, true ); + horizontalLine = new QBitmap( 128, 1, true ); + QPointArray a( 64 ); + QPainter p2; + p2.begin( verticalLine ); + + int i; + for( i=0; i < 64; i++ ) + a.setPoint( i, 0, i*2+1 ); + p2.setPen( color1 ); + p2.drawPoints( a ); + p2.end(); + QApplication::flushX(); + verticalLine->setMask( *verticalLine ); + + p2.begin( horizontalLine ); + for( i=0; i < 64; i++ ) + a.setPoint( i, i*2+1, 0 ); + p2.setPen( color1 ); + p2.drawPoints( a ); + p2.end(); + QApplication::flushX(); + horizontalLine->setMask( *horizontalLine ); + } + + p->setPen( cg.mid() ); + + if (flags & Style_Horizontal) + { + int point = r.x(); + int other = r.y(); + int end = r.x()+r.width(); + int thickness = r.height(); + + while( point < end ) + { + int i = 128; + if ( i+point > end ) + i = end-point; + p->drawPixmap( point, other, *horizontalLine, 0, 0, i, thickness ); + point += i; + } + + } else { + int point = r.y(); + int other = r.x(); + int end = r.y()+r.height(); + int thickness = r.width(); + int pixmapoffset = (flags & Style_NoChange) ? 0 : 1; // ### Hackish + + while( point < end ) + { + int i = 128; + if ( i+point > end ) + i = end-point; + p->drawPixmap( other, point, *verticalLine, 0, pixmapoffset, thickness, i ); + point += i; + } + } + + break; + } + + default: + KStyle::drawKStylePrimitive(kpe, p, widget, r, cg, flags, opt); + } +} + + +void PlastikStyle::drawPrimitive(PrimitiveElement pe, + QPainter *p, + const QRect &r, + const QColorGroup &cg, + SFlags flags, + const QStyleOption &opt ) const +{ + bool down = flags & Style_Down; + bool on = flags & Style_On; + bool sunken = flags & Style_Sunken; + bool horiz = flags & Style_Horizontal; + const bool enabled = flags & Style_Enabled; + const bool mouseOver = flags & Style_MouseOver; + + bool hasFocus = flags & Style_HasFocus; + + int x = r.x(); + int y = r.y(); + int w = r.width(); + int h = r.height(); + + int x2, y2; + r.coords(&x, &y, &x2, &y2); + + switch(pe) { + // BUTTONS + // ------- + case PE_FocusRect: { + if(_drawFocusRect) + p->drawWinFocusRect( r ); + break; + } + + case PE_HeaderSection: { + // the taskbar buttons seems to be painted with PE_HeaderSection but I + // want them look like normal buttons (at least for now. :) ) + if(!kickerMode) { + // detect if this is the left most header item + bool isFirst = false; + QHeader *header = dynamic_cast<QHeader*>(p->device() ); + if (header) { + isFirst = header->mapToIndex(header->sectionAt(r.x() ) ) == 0; + } + + uint contourFlags = Draw_Right|Draw_Top|Draw_Bottom; + if (isFirst) + contourFlags |= Draw_Left; + if(!enabled) contourFlags|=Is_Disabled; + renderContour(p, r, cg.background(), getColor(cg,ButtonContour), + contourFlags); + + uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Is_Horizontal; + if(!enabled) surfaceFlags|=Is_Disabled; + else { + if(on||down) surfaceFlags|=Is_Sunken; + else { + if(mouseOver) { + surfaceFlags|=Is_Highlight|Highlight_Top|Highlight_Bottom; + } + } + } + renderSurface(p, QRect(isFirst?r.left()+1:r.left(), r.top()+1, isFirst?r.width()-2:r.width()-1, r.height()-2), + cg.background(), cg.button(), getColor(cg,MouseOverHighlight), _contrast, + surfaceFlags); + + break; + } + } + case PE_ButtonBevel: + case PE_ButtonTool: + case PE_ButtonDropDown: + case PE_ButtonCommand: { + bool khtmlMode = opt.isDefault() ? false : khtmlWidgets.contains(opt.widget()); + renderButton(p, r, cg, (on||down), mouseOver, true, enabled, khtmlMode ); + break; + } + + case PE_ButtonDefault: { + uint contourFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom| + Round_UpperLeft|Round_UpperRight|Round_BottomLeft|Round_BottomRight; + if(!enabled) contourFlags|=Is_Disabled; + renderContour(p, r, cg.background(), cg.background().dark(120), + contourFlags); + break; + } + + case PE_SpinWidgetPlus: + case PE_SpinWidgetMinus: { + p->setPen( cg.buttonText() ); + + int l = QMIN( w-2, h-2 ); + // make the length even so that we get a nice symmetric plus... + if(l%2 != 0) + --l; + QPoint c = r.center(); + + p->drawLine( c.x()-l/2, c.y(), c.x()+l/2, c.y() ); + if ( pe == PE_SpinWidgetPlus ) { + p->drawLine( c.x(), c.y()-l/2, c.x(), c.y()+l/2 ); + } + break; + } + + case PE_ScrollBarSlider: { + const WidgetState s = enabled?(down?IsPressed:IsEnabled):IsDisabled; + const QColor surface = getColor(cg, DragButtonSurface, s); + + uint contourFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom; + if(!enabled) contourFlags|=Is_Disabled; + renderContour(p, r, cg.background(), getColor(cg, DragButtonContour, s), + contourFlags); + + uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom; + if(horiz) surfaceFlags|=Is_Horizontal; + if(!enabled) surfaceFlags|=Is_Disabled; + if(r.height() >= 4) + renderSurface(p, QRect(r.left()+1, r.top()+1, r.width()-2, r.height()-2), + cg.background(), surface, cg.background(), + _contrast+3, surfaceFlags); + + // set contour-like color for the case _scrollBarLines is set and we paint lines instead of dots. + p->setPen(alphaBlendColors(cg.background(), surface.dark(enabled?140:120), 50) ); + + const int d = 4; + int n = ((horiz?r.width():r.height())-8)/d; + if(n>5) n=5; + if(!horiz) { + for(int j = 0; j < n; j++) { + int yPos = r.center().y()-(n*d)/2+d*j+1; + if(_scrollBarLines) + p->drawLine(r.x()+1, yPos, r.right()-1, yPos); + else + { + for(int k = 3; k <= 13; k+=4) { + renderDot(p, QPoint(k, yPos), surface, false, true ); + } + } + } + } else { + for(int j = 0; j < n; j++) { + int xPos = r.center().x()-(n*d)/2+d*j+1; + if(_scrollBarLines) + p->drawLine(xPos, r.y()+1, xPos, r.bottom()-1); + else + { + for(int k = 3; k <= 13; k+=4) { + renderDot(p, QPoint(xPos, k), surface, false, true ); + } + } + } + } + + break; + } + + case PE_ScrollBarAddPage: + case PE_ScrollBarSubPage: { + // draw double buffered to avoid flicker... + QPixmap buffer; + if(flags & Style_Horizontal) { + buffer.resize(2, r.height() ); + } else { + buffer.resize(r.width(), 2 ); + } + QRect br(buffer.rect() ); + QPainter bp(&buffer); + + if (on || down) { + bp.fillRect(br, QBrush(cg.mid().dark())); + } else { + if(flags & Style_Horizontal) { + bp.setPen(cg.background().dark(106)); + bp.drawLine(br.left(), br.top(), br.right(), br.top()); + bp.setPen(cg.background().light(106)); + bp.drawLine(br.left(), br.bottom(), br.right(), br.bottom()); + bp.fillRect(br.left(), br.top()+1, br.width(), br.height()-2,cg.background()); + } else { + bp.setPen(cg.background().dark(106)); + bp.drawLine(br.left(), br.top(), br.left(), br.bottom()); + bp.setPen(cg.background().light(106)); + bp.drawLine(br.right(), br.top(), br.right(), br.bottom()); + bp.fillRect(br.left()+1, br.top(), br.width()-2, br.height(),cg.background()); + } + } + + bp.fillRect(br, QBrush(cg.background().light(), Dense4Pattern)); + + bp.end(); + + p->drawTiledPixmap(r, buffer, QPoint(0, r.top()%2) ); + break; + } + + // SCROLLBAR BUTTONS + // ----------------- + case PE_ScrollBarSubLine: { + uint contourFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom; + uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom; + if(down) surfaceFlags|=Is_Sunken; + if(!enabled) { + contourFlags|=Is_Disabled; + surfaceFlags|=Is_Disabled; + } + if(horiz) { + contourFlags |= Round_UpperLeft|Round_BottomLeft|Is_Horizontal; + surfaceFlags |= Round_UpperLeft|Round_BottomLeft|Is_Horizontal; + } else { + contourFlags |= Round_UpperLeft|Round_UpperRight; + surfaceFlags |= Round_UpperLeft|Round_UpperRight; + } + renderContour(p, r, cg.background(), getColor(cg, ButtonContour), + contourFlags); + renderSurface(p, QRect(r.left()+1, r.top()+1, r.width()-2, r.height()-2), + cg.background(), cg.button(), getColor(cg,MouseOverHighlight), _contrast+3, + surfaceFlags); + + p->setPen(cg.foreground()); + drawPrimitive((horiz ? PE_ArrowLeft : PE_ArrowUp), p, r, cg, flags); + break; + } + + case PE_ScrollBarAddLine: { + uint contourFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom; + uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom; + if(down) surfaceFlags|=Is_Sunken; + if(!enabled) { + contourFlags|=Is_Disabled; + surfaceFlags|=Is_Disabled; + } + if(horiz) { + contourFlags |= Round_UpperRight|Round_BottomRight|Is_Horizontal; + surfaceFlags |= Round_UpperRight|Round_BottomRight|Is_Horizontal; + } else { + contourFlags |= Round_BottomLeft|Round_BottomRight; + surfaceFlags |= Round_BottomLeft|Round_BottomRight; + } + renderContour(p, r, cg.background(), getColor(cg, ButtonContour), + contourFlags); + renderSurface(p, QRect(r.left()+1, r.top()+1, r.width()-2, r.height()-2), + cg.background(), cg.button(), getColor(cg,MouseOverHighlight), _contrast+3, + surfaceFlags); + + p->setPen(cg.foreground()); + drawPrimitive((horiz ? PE_ArrowRight : PE_ArrowDown), p, r, cg, flags); + break; + } + + // CHECKBOXES + // ---------- + case PE_Indicator: { + QColor contentColor = enabled?cg.base():cg.background(); + + uint contourFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom; + if(!enabled) { + contourFlags |= Is_Disabled; + } + renderContour(p, r, cg.background(), getColor(cg, ButtonContour), + contourFlags); + + // surface + uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Is_Horizontal; + if(!enabled) { + surfaceFlags |= Is_Disabled; + } else if(mouseOver) { + contentColor = alphaBlendColors(contentColor, getColor(cg,MouseOverHighlight), 240); + surfaceFlags |= Is_Highlight; + surfaceFlags |= Highlight_Left|Highlight_Right| + Highlight_Top|Highlight_Bottom; + } + renderSurface(p, QRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2), + cg.background(), contentColor, getColor(cg,MouseOverHighlight), enabled?_contrast+3:(_contrast/2), surfaceFlags); + + drawPrimitive(PE_CheckMark, p, r, cg, flags); + + break; + } + + case PE_IndicatorMask: { + p->fillRect (r, color1); + break; + } + + // RADIOBUTTONS + // ------------ + case PE_ExclusiveIndicator: { + const QColor contourColor = getColor(cg, ButtonContour, enabled); + QColor contentColor = enabled?cg.base():cg.background(); + + QBitmap bmp; + bmp = QBitmap(13, 13, radiobutton_mask_bits, true); + // first the surface... + uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Is_Horizontal; + if(!enabled) { + surfaceFlags |= Is_Disabled; + } else if (mouseOver) { + contentColor = alphaBlendColors(contentColor, getColor(cg,MouseOverHighlight), 240); + } + p->setClipRegion(bmp); + renderSurface(p, r, + cg.background(), contentColor, getColor(cg,MouseOverHighlight), enabled?_contrast+3:(_contrast/2), surfaceFlags); + p->setClipping(false); + + // ...then contour, anti-alias, mouseOver... + // contour + bmp = QBitmap(13, 13, radiobutton_contour_bits, true); + bmp.setMask(bmp); + p->setPen(alphaBlendColors(cg.background(), contourColor, 50) ); + p->drawPixmap(x, y, bmp); + // anti-alias outside + bmp = QBitmap(13, 13, radiobutton_aa_outside_bits, true); + bmp.setMask(bmp); + p->setPen(alphaBlendColors(cg.background(), contourColor, 150) ); + p->drawPixmap(x, y, bmp); + // highlighting... + if(mouseOver) { + bmp = QBitmap(13, 13, radiobutton_highlight1_bits, true); + bmp.setMask(bmp); + p->setPen(alphaBlendColors(contentColor, getColor(cg,MouseOverHighlight), 80) ); + p->drawPixmap(x, y, bmp); + bmp = QBitmap(13, 13, radiobutton_highlight2_bits, true); + bmp.setMask(bmp); + p->setPen(alphaBlendColors(contentColor, getColor(cg,MouseOverHighlight), 150) ); + p->drawPixmap(x, y, bmp); + } + // anti-alias inside, "above" the higlighting! + bmp = QBitmap(13, 13, radiobutton_aa_inside_bits, true); + bmp.setMask(bmp); + if(mouseOver) { + p->setPen(alphaBlendColors(getColor(cg,MouseOverHighlight), contourColor, 180) ); + } else { + p->setPen(alphaBlendColors(contentColor, contourColor, 180) ); + } + p->drawPixmap(x, y, bmp); + + + QColor checkmarkColor = enabled?getColor(cg,CheckMark):cg.background(); + if(flags & Style_Down) { + checkmarkColor = alphaBlendColors(contentColor, checkmarkColor, 150); + } + + // draw the radio mark + if (flags & Style_On || flags & Style_Down) { + bmp = QBitmap(CHECKMARKSIZE, CHECKMARKSIZE, radiomark_dark_bits, true); + bmp.setMask(bmp); + p->setPen(alphaBlendColors(contentColor, checkmarkColor.dark(150), 50) ); + p->drawPixmap(x+2, y+2, bmp); + bmp = QBitmap(CHECKMARKSIZE, CHECKMARKSIZE, radiomark_light_bits, true); + bmp.setMask(bmp); + p->setPen(alphaBlendColors(contentColor, checkmarkColor.dark(125), 50) ); + p->drawPixmap(x+2, y+2, bmp); + bmp = QBitmap(CHECKMARKSIZE, CHECKMARKSIZE, radiomark_aa_bits, true); + bmp.setMask(bmp); + p->setPen(alphaBlendColors(contentColor, checkmarkColor.dark(150), 150) ); + p->drawPixmap(x+2, y+2, bmp); + } + + break; + } + + case PE_ExclusiveIndicatorMask: { + p->fillRect(r, color0); + + QBitmap bmp; + bmp = QBitmap(13, 13, radiobutton_mask_bits, true); + bmp.setMask(bmp); + p->setPen(color1); + p->drawPixmap(x, y, bmp); + + break; + } + + // GENERAL PANELS + // -------------- + case PE_Splitter: { + // highlight on mouse over + QColor color = (hoverWidget == p->device())?cg.background().light(100+_contrast):cg.background(); + p->fillRect(r, color); + if (w > h) { + if (h > 4) { + int ycenter = r.height()/2; + for(int k = 2*r.width()/10; k < 8*r.width()/10; k+=5) { + renderDot(p, QPoint(k, ycenter-1), color, false, true); + } + } + } else { + if (w > 4) { + int xcenter = r.width()/2; + for(int k = 2*r.height()/10; k < 8*r.height()/10; k+=5) { + renderDot(p, QPoint(xcenter-1, k), color, false, true); + } + } + } + + break; + } + + case PE_PanelGroupBox: + case PE_GroupBoxFrame: { + if ( opt.isDefault() || opt.lineWidth() <= 0 ) + break; + renderPanel(p, r, cg, false); + + break; + } + + case PE_WindowFrame: + case PE_Panel: { + if ( opt.isDefault() || opt.lineWidth() <= 0 ) + break; + renderPanel(p, r, cg, true, sunken); + break; + } + + case PE_PanelLineEdit: { + bool isReadOnly = false; + bool isEnabled = true; + // panel is highlighted by default if it has focus, but if we have access to the + // widget itself we can try to avoid highlighting in case it's readOnly or disabled. + if (p->device() && dynamic_cast<QLineEdit*>(p->device())) + { + QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(p->device()); + isReadOnly = lineEdit->isReadOnly(); + isEnabled = lineEdit->isEnabled(); + } + + uint contourFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom| + Round_UpperLeft|Round_UpperRight|Round_BottomLeft|Round_BottomRight; + + // HACK!! + // + // In order to draw nice edges in khtml, we need to paint alpha-blended. + // On the other hand, we can't paint alpha-blended in normal widgets. + // + // In this place there is no reliable way to detect if we are in khtml; the + // only thing we know is that khtml buffers its widgets into a pixmap. So + // when the paint device is a QPixmap, chances are high that we are in khtml. + // It's possible that this breaks other things, so let's see how it works... + if (p->device() && dynamic_cast<QPixmap*>(p->device() ) ) { + contourFlags += Draw_AlphaBlend; + } + + if ( _inputFocusHighlight && hasFocus && !isReadOnly && isEnabled) + { + renderContour(p, r, cg.background(), + getColor(cg,FocusHighlight,enabled), contourFlags ); + } + else + { + renderContour(p, r, cg.background(), + getColor(cg, ButtonContour, enabled), contourFlags ); + } + const QColor contentColor = enabled?cg.base():cg.background(); + if (_inputFocusHighlight && hasFocus && !isReadOnly && isEnabled) + { + p->setPen( getColor(cg,FocusHighlight).dark(130) ); + } + else + { + p->setPen(contentColor.dark(130) ); + } + p->drawLine(r.left()+1, r.top()+2, r.left()+1, r.bottom()-2 ); + p->drawLine(r.left()+2, r.top()+1, r.right()-2, r.top()+1 ); + if (_inputFocusHighlight && hasFocus && !isReadOnly && isEnabled) + { + p->setPen( getColor(cg,FocusHighlight).light(130) ); + } + else + { + p->setPen(contentColor.light(130) ); + } + p->drawLine(r.left()+2, r.bottom()-1, r.right()-2, r.bottom()-1 ); + p->drawLine(r.right()-1, r.top()+2, r.right()-1, r.bottom()-2 ); + break; + } + + case PE_StatusBarSection: { + renderContour(p, r, cg.background(), cg.background().dark(160), + Draw_Left|Draw_Right|Draw_Top|Draw_Bottom); + break; + } + + case PE_TabBarBase: // Still not sure what this one does + case PE_PanelTabWidget: { + renderPanel(p, r, cg, true, sunken); + break; + } + + case PE_PanelPopup: { + renderContour(p, r, cg.background(), cg.background().dark(200), + Draw_Left|Draw_Right|Draw_Top|Draw_Bottom); + break; + } + + // MENU / TOOLBAR PANEL + // -------------------- + case PE_PanelMenuBar: + case PE_PanelDockWindow: { + // fix for toolbar lag (from Mosfet Liquid) + QWidget* w = dynamic_cast<QWidget*>(p->device()); + if(w && w->backgroundMode() == PaletteButton) + w->setBackgroundMode(PaletteBackground); + p->fillRect(r, cg.brush(QColorGroup::Background)); + + if ( _drawToolBarSeparator ) { + if ( r.width() > r.height() ) { + p->setPen( getColor(cg, PanelLight) ); + p->drawLine( r.left(), r.top(), r.right(), r.top() ); + p->setPen( getColor(cg, PanelDark) ); + p->drawLine( r.left(), r.bottom(), r.right(), r.bottom() ); + } + else { + p->setPen( getColor(cg, PanelLight) ); + p->drawLine( r.left(), r.top(), r.left(), r.bottom() ); + p->setPen( getColor(cg, PanelDark) ); + p->drawLine( r.right(), r.top(), r.right(), r.bottom() ); + } + } + + break; + } + + // TOOLBAR/DOCK WINDOW HANDLE + // -------------------------- + case PE_DockWindowResizeHandle: { + renderButton(p, r, cg); + break; + } + + case PE_DockWindowHandle: { + + int counter = 1; + + if(horiz) { + int center = r.left()+r.width()/2; + for(int j = r.top()+2; j <= r.bottom()-3; j+=3) { + if(counter%2 == 0) { + renderDot(p, QPoint(center+1, j), cg.background(), true, true); + } else { + renderDot(p, QPoint(center-2, j), cg.background(), true, true); + } + counter++; + } + } else { + int center = r.top()+r.height()/2; + for(int j = r.left()+2; j <= r.right()-3; j+=3) { + if(counter%2 == 0) { + renderDot(p, QPoint(j, center+1), cg.background(), true, true); + } else { + renderDot(p, QPoint(j, center-2), cg.background(), true, true); + } + counter++; + } + } + + break; + } + + // TOOLBAR SEPARATOR + // ----------------- + case PE_DockWindowSeparator: { + p->fillRect(r, cg.background()); + + if(_drawToolBarItemSeparator) { + if(horiz) { + int center = r.left()+r.width()/2; + p->setPen( getColor(cg, PanelDark) ); + p->drawLine( center-1, r.top()+3, center-1, r.bottom()-3 ); + p->setPen( getColor(cg, PanelLight) ); + p->drawLine( center, r.top()+3, center, r.bottom()-3 ); + } else { + int center = r.top()+r.height()/2; + p->setPen( getColor(cg, PanelDark) ); + p->drawLine( r.x()+3, center-1, r.right()-3, center-1 ); + p->setPen( getColor(cg, PanelLight) ); + p->drawLine( r.x()+3, center, r.right()-3, center ); + } + } + break; + } + + case PE_CheckMark: { + const QColor contentColor = enabled?cg.base():cg.background(); + QColor checkmarkColor = enabled?getColor(cg,CheckMark):cg.background(); + if(flags & Style_Down) { + checkmarkColor = alphaBlendColors(contentColor, checkmarkColor, 150); + } + + int x = r.center().x() - 4, y = r.center().y() - 4; + QBitmap bmp; + if( flags & Style_On ) { + bmp = QBitmap(CHECKMARKSIZE, CHECKMARKSIZE, checkmark_dark_bits, true); + bmp.setMask(bmp); + p->setPen(alphaBlendColors(contentColor, checkmarkColor.dark(150), 50) ); + p->drawPixmap(x, y, bmp); + bmp = QBitmap(CHECKMARKSIZE, CHECKMARKSIZE, checkmark_light_bits, true); + bmp.setMask(bmp); + p->setPen(alphaBlendColors(contentColor, checkmarkColor.dark(125), 50) ); + p->drawPixmap(x, y, bmp); + bmp = QBitmap(CHECKMARKSIZE, CHECKMARKSIZE, checkmark_aa_bits, true); + bmp.setMask(bmp); + p->setPen(alphaBlendColors(contentColor, checkmarkColor.dark(150), 150) ); + p->drawPixmap(x, y, bmp); + } else if ( flags & Style_Off ) { + // empty + } else { // tristate + bmp = QBitmap(CHECKMARKSIZE, CHECKMARKSIZE, checkmark_tristate_bits, true); + bmp.setMask(bmp); + p->setPen(alphaBlendColors(contentColor, checkmarkColor.dark(150), 50) ); + p->drawPixmap(x, y, bmp); + } + + break; + } + + case PE_SpinWidgetUp: + case PE_SpinWidgetDown: + case PE_HeaderArrow: + case PE_ArrowUp: + case PE_ArrowDown: + case PE_ArrowLeft: + case PE_ArrowRight: { + QPointArray a; + + switch (pe) { + case PE_SpinWidgetUp: + case PE_ArrowUp: { + a.setPoints(7, u_arrow); + break; + } + case PE_SpinWidgetDown: + case PE_ArrowDown: { + a.setPoints(7, d_arrow); + break; + } + case PE_ArrowLeft: { + a.setPoints(7, l_arrow); + break; + } + case PE_ArrowRight: { + a.setPoints(7, r_arrow); + break; + } + default: { + if (flags & Style_Up) { + a.setPoints(7, u_arrow); + } else { + a.setPoints(7, d_arrow); + } + } + } + + const QWMatrix oldMatrix( p->worldMatrix() ); + + if (flags & Style_Down) { + p->translate(pixelMetric(PM_ButtonShiftHorizontal), + pixelMetric(PM_ButtonShiftVertical)); + } + + a.translate((r.x()+r.width()/2), (r.y()+r.height()/2)); + // extra-pixel-shift, correcting some visual tics... + switch(pe) { + case PE_ArrowLeft: + case PE_ArrowRight: + a.translate(0, -1); + break; + case PE_SpinWidgetUp: + case PE_SpinWidgetDown: + a.translate(+1, 0); + break; + default: + a.translate(0, 0); + } + + if (p->pen() == QPen::NoPen) { + if (flags & Style_Enabled) { + p->setPen(cg.buttonText()); + } else { + p->setPen(cg.highlightedText()); + } + } + p->drawLineSegments(a, 0, 3); + p->drawPoint(a[6]); + + p->setWorldMatrix( oldMatrix ); + + break; + } + + default: { + return KStyle::drawPrimitive(pe, p, r, cg, flags, opt); + } + } +} + + +void PlastikStyle::drawControl(ControlElement element, + QPainter *p, + const QWidget *widget, + const QRect &r, + const QColorGroup &cg, + SFlags flags, + const QStyleOption& opt) const +{ + const bool reverseLayout = QApplication::reverseLayout(); + + const bool enabled = (flags & Style_Enabled); + + switch (element) { + + // PROGRESSBAR + // ----------- + case CE_ProgressBarGroove: { + const QColor content = enabled?cg.base():cg.background(); + renderContour(p, r, cg.background(), getColor(cg, ButtonContour, enabled) ); + p->setPen(content.dark(105) ); + p->drawLine(r.left()+2, r.top()+1, r.right()-2, r.top()+1 ); + p->drawLine(r.left()+1, r.top()+2, r.left()+1, r.bottom()-2); + p->setPen(content.light(105) ); + p->drawLine(r.left()+2, r.bottom()-1, r.right()-2, r.bottom()-1 ); + p->drawLine(r.right()-1, r.top()+2, r.right()-1, r.bottom()-2); + break; + } + + case CE_ProgressBarContents: { + const QProgressBar *pb = dynamic_cast<const QProgressBar*>(widget); + int steps = pb->totalSteps(); + + const QColor bg = enabled?cg.base():cg.background(); // background + const QColor fg = enabled?cg.highlight():cg.background().dark(110); // foreground + + if( steps == 0 ) { // Busy indicator + static const int barWidth = 10; + int progress = pb->progress() % (2*(r.width()-barWidth)); + if( progress < 0) + progress = 0; + if( progress > r.width()-barWidth ) + progress = (r.width()-barWidth)-(progress-(r.width()-barWidth)); + p->fillRect( QRect( r.x(), r.y(), r.width(), r.height() ), bg ); + renderContour( p, QRect( r.x()+progress, r.y(), barWidth, r.height() ), + bg, fg.dark(160), + Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Round_UpperRight| + Round_BottomRight|Round_UpperLeft|Round_BottomLeft ); + renderSurface(p, QRect( r.x()+progress+1, r.y()+1, barWidth-2, r.height()-2 ), + bg, fg, cg.highlight(), + 2*(_contrast/3), + Draw_Right|Draw_Left|Draw_Top|Draw_Bottom| + Round_UpperRight|Round_BottomRight| + Round_UpperLeft|Round_BottomLeft|Is_Horizontal); + } else { + double percent = static_cast<double>(pb->progress()) / static_cast<double>(steps); + + int w = static_cast<int>(r.width() * percent); + // renderContour/renderSurface handle small sizes not very well, so set a minimal + // progressbar width... + if(w<4) w = 4; + int w2 = r.width()-(r.width()-w); + + QRect Rempty(reverseLayout?r.left():r.left()+w-1, r.top(), r.width()-w+1, r.height() ); + QRect Rcontour(reverseLayout?r.right()-w2+1:r.left(), r.top(), w2, r.height() ); + QRect Rsurface(Rcontour.left()+1, Rcontour.top()+1, w2-2, Rcontour.height()-2); + + p->fillRect(Rempty, bg); + + renderContour(p, Rcontour, + bg, fg.dark(160), + reverseLayout ? Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Round_UpperLeft|Round_BottomLeft + : Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Round_UpperRight|Round_BottomRight); + + QRegion mask(Rsurface); + if(reverseLayout) { + mask -= QRegion(Rsurface.left(), Rsurface.top(), 1, 1); + mask -= QRegion(Rsurface.left(), Rsurface.bottom(), 1, 1); + } else { + mask -= QRegion(Rsurface.right(), Rsurface.top(), 1, 1); + mask -= QRegion(Rsurface.right(), Rsurface.bottom(), 1, 1); + } + p->setClipRegion(mask); + int counter = 0; + QPixmap surfaceTile(21, r.height()-2); + QPainter surfacePainter(&surfaceTile); + // - 21 pixel - + // __________ + // | ` `| <- 3 + // | 1 | 2 | + // |____,____,| <- 3 + // 1 = light, 11 pixel, 1 pixel overlapping with 2 + // 2 = dark, 11 pixel, 1 pixel overlapping with 3 + // 3 = light edges + const int tileHeight = surfaceTile.height(); + // 3 + renderSurface(&surfacePainter, + QRect(20, 0, 11, tileHeight), + fg.light(105), fg, cg.highlight(), 2*(_contrast/3), + reverseLayout ? Draw_Right|Draw_Left|Draw_Top|Draw_Bottom| + Round_UpperLeft|Round_BottomLeft|Is_Horizontal + : Draw_Right|Draw_Left|Draw_Top|Draw_Bottom| + Round_UpperRight|Round_BottomRight|Is_Horizontal); + // 2 + renderSurface(&surfacePainter, + QRect(10, 0, 11, tileHeight), + fg, fg.light(105), cg.highlight(), 2*(_contrast/3), + reverseLayout ? Draw_Right|Draw_Left|Draw_Top|Draw_Bottom| + Round_UpperLeft|Round_BottomLeft|Is_Horizontal + : Draw_Right|Draw_Left|Draw_Top|Draw_Bottom| + Round_UpperRight|Round_BottomRight|Is_Horizontal); + // 1 + renderSurface(&surfacePainter, + QRect(0, 0, 11, tileHeight), + fg.light(105), fg, cg.highlight(), 2*(_contrast/3), + reverseLayout ? Draw_Right|Draw_Left|Draw_Top|Draw_Bottom| + Round_UpperLeft|Round_BottomLeft|Is_Horizontal + : Draw_Right|Draw_Left|Draw_Top|Draw_Bottom| + Round_UpperRight|Round_BottomRight|Is_Horizontal); + + surfacePainter.end(); + int staticShift = 0; + int animShift = 0; + if (!_animateProgressBar) { + staticShift = (reverseLayout ? Rsurface.left() : Rsurface.right()) % 40 - 40; + } else { + // find the animation Offset for the current Widget + QWidget* nonConstWidget = const_cast<QWidget*>(widget); + QMapConstIterator<QWidget*, int> iter = progAnimWidgets.find(nonConstWidget); + if (iter != progAnimWidgets.end()) + animShift = iter.data(); + } + while((counter*10) < (Rsurface.width()+20)) { + counter++; + if (reverseLayout) { + // from right to left, overlap 1 pixel with the previously drawn tile + p->drawPixmap(Rsurface.right()-counter*20-animShift+40+staticShift, r.top()+1, + surfaceTile); + } else { + // from left to right, overlap 1 pixel with the previously drawn tile + p->drawPixmap(Rsurface.left()+counter*20+animShift-40+staticShift, r.top()+1, + surfaceTile); + } + } + + p->setClipping(false); + } + + break; + } + + // TABS + // ---- + case CE_TabBarTab: { + const QTabBar * tb = (const QTabBar *) widget; + bool cornerWidget = false; + if( ::qt_cast<QTabWidget*>(tb->parent()) ) { + const QTabWidget *tw = (const QTabWidget*)tb->parent(); + // is there a corner widget in the (top) left edge? + QWidget *cw = tw->cornerWidget(Qt::TopLeft); + if(cw) + cornerWidget = true; + } + QTabBar::Shape tbs = tb->shape(); + bool selected = false; + if (flags & Style_Selected) selected = true; + TabPosition pos; + if (tb->count() == 1) { + pos = Single; + } else if ((tb->indexOf(opt.tab()->identifier()) == 0)) { + pos = First; + } else if (tb->indexOf(opt.tab()->identifier()) == tb->count() - 1) { + pos = Last; + } else { + pos = Middle; + } + + bool mouseOver = false; + if (opt.tab() == hoverTab) { + mouseOver = true; + flags |= Style_MouseOver; + } + + switch (tbs) { + case QTabBar::TriangularAbove: +// renderTriangularTab(p, r, cg, (flags & Style_MouseOver), selected, false, pos); + renderTab(p, r, cg, mouseOver, selected, false, pos, true, cornerWidget); + break; + case QTabBar::RoundedAbove: + renderTab(p, r, cg, mouseOver, selected, false, pos, false, cornerWidget); + break; + case QTabBar::TriangularBelow: +// renderTriangularTab(p, r, cg, (flags & Style_MouseOver), selected, true, pos); + renderTab(p, r, cg, mouseOver, selected, true, pos, true, cornerWidget); + break; + case QTabBar::RoundedBelow: + renderTab(p, r, cg, mouseOver, selected, true, pos, false, cornerWidget); + break; + default: + KStyle::drawControl(element, p, widget, r, cg, flags, opt); + } + + break; + } + + case CE_PushButton: { + QPushButton *button = (QPushButton *)widget; + + const bool isDefault = enabled && button->isDefault(); + + if (button->isFlat() ) + flatMode = true; + + if (widget == hoverWidget) + flags |= Style_MouseOver; + + QColorGroup g2 = cg; + if (isDefault) + g2.setColor(QColorGroup::Background, cg.background().dark(120) ); + drawPrimitive(PE_ButtonBevel, p, + isDefault?QRect(r.x()+1,r.y()+1,r.width()-2,r.height()-2):r, + g2, flags, QStyleOption(button) ); + + if (isDefault ) { + drawPrimitive(PE_ButtonDefault, p, r, cg, flags); + } + + break; + } + + case CE_PushButtonLabel: + { + int x, y, w, h; + r.rect( &x, &y, &w, &h ); + + const QPushButton* button = static_cast<const QPushButton *>( widget ); + bool active = button->isOn() || button->isDown(); + bool cornArrow = false; + + // Shift button contents if pushed. + if ( active ) + { + x += pixelMetric(PM_ButtonShiftHorizontal, widget); + y += pixelMetric(PM_ButtonShiftVertical, widget); + flags |= Style_Sunken; + } + + // Does the button have a popup menu? + if ( button->isMenuButton() ) + { + int dx = pixelMetric( PM_MenuButtonIndicator, widget ); + if ( button->iconSet() && !button->iconSet()->isNull() && + (dx + button->iconSet()->pixmap (QIconSet::Small, QIconSet::Normal, QIconSet::Off ).width()) >= w ) + { + cornArrow = true; //To little room. Draw the arrow in the corner, don't adjust the widget + } + else + { + p->setPen(cg.buttonText()); + drawPrimitive( PE_ArrowDown, p, visualRect( QRect(x + w - dx - 8, y + 2, dx, h - 4), r ), + cg, flags, opt ); + w -= dx; + } + } + + // Draw the icon if there is one + if ( button->iconSet() && !button->iconSet()->isNull() ) + { + QIconSet::Mode mode = QIconSet::Disabled; + QIconSet::State state = QIconSet::Off; + + if (button->isEnabled()) + mode = button->hasFocus() ? QIconSet::Active : QIconSet::Normal; + if (button->isToggleButton() && button->isOn()) + state = QIconSet::On; + + QPixmap pixmap = button->iconSet()->pixmap( QIconSet::Small, mode, state ); + + if (button->text().isEmpty() && !button->pixmap()) + p->drawPixmap( x + w/2 - pixmap.width()/2, y + h / 2 - pixmap.height() / 2, + pixmap ); + else + p->drawPixmap( x + 4, y + h / 2 - pixmap.height() / 2, pixmap ); + + if (cornArrow) //Draw over the icon + drawPrimitive( PE_ArrowDown, p, visualRect( QRect(x + w - 6, x + h - 6, 7, 7), r ), + cg, flags, opt ); + + + int pw = pixmap.width(); + x += pw + 4; + w -= pw + 4; + } + + // Make the label indicate if the button is a default button or not + drawItem( p, QRect(x, y, w, h), AlignCenter|ShowPrefix, button->colorGroup(), + button->isEnabled(), button->pixmap(), button->text(), -1, + &button->colorGroup().buttonText() ); + + + if ( flags & Style_HasFocus ) + drawPrimitive( PE_FocusRect, p, + visualRect( subRect( SR_PushButtonFocusRect, widget ), widget ), + cg, flags ); + break; + } + + // MENUBAR ITEM (sunken panel on mouse over) + // ----------------------------------------- + case CE_MenuBarItem: { + QMenuItem *mi = opt.menuItem(); + bool active = flags & Style_Active; + bool focused = flags & Style_HasFocus; + bool down = flags & Style_Down; + const int text_flags = + AlignVCenter | AlignHCenter | ShowPrefix | DontClip | SingleLine; + + p->fillRect(r, cg.background()); + + if (active && focused) { + if (down) { + drawPrimitive(PE_ButtonTool, p, r, cg, flags|Style_Down, opt); + } else { + drawPrimitive(PE_ButtonTool, p, r, cg, flags, opt); + } + } + + p->setPen(cg.foreground() ); + p->drawText(r, text_flags, mi->text()); + break; + } + + // POPUPMENU ITEM (highlighted on mouseover) + // ------------------------------------------ + case CE_PopupMenuItem: { + const QPopupMenu *popupmenu = static_cast< const QPopupMenu * >( widget ); + QMenuItem *mi = opt.menuItem(); + + if ( !mi ) + { + // Don't leave blank holes if we set NoBackground for the QPopupMenu. + // This only happens when the popupMenu spans more than one column. + if (! ( widget->erasePixmap() && !widget->erasePixmap()->isNull() ) ) + p->fillRect( r, cg.background().light( 105 ) ); + + break; + } + int tab = opt.tabWidth(); + int checkcol = opt.maxIconWidth(); + bool enabled = mi->isEnabled(); + bool checkable = popupmenu->isCheckable(); + bool active = flags & Style_Active; + bool etchtext = styleHint( SH_EtchDisabledText ); + bool reverse = QApplication::reverseLayout(); + if ( checkable ) + checkcol = QMAX( checkcol, 20 ); + + // Draw the menu item background + if (active) { + if (enabled) { + renderSurface(p, r, cg.background(), cg.highlight(), cg.highlight(), + _contrast+3, Draw_Top|Draw_Bottom|Is_Horizontal); + } + else { + if ( widget->erasePixmap() && !widget->erasePixmap()->isNull() ) + p->drawPixmap( r.topLeft(), *widget->erasePixmap(), r ); + else p->fillRect( r, cg.background().light(105) ); + if(_drawFocusRect) + p->drawWinFocusRect( r ); + } + } + // Draw the transparency pixmap + else if ( widget->erasePixmap() && !widget->erasePixmap()->isNull() ) + p->drawPixmap( r.topLeft(), *widget->erasePixmap(), r ); + // Draw a solid background + else + p->fillRect( r, cg.background().light( 105 ) ); + // Are we a menu item separator? + if ( mi->isSeparator() ) + { + p->setPen( cg.mid() ); + p->drawLine( r.x()+5, r.y() + 1, r.right()-5, r.y() + 1 ); + p->setPen( cg.light() ); + p->drawLine( r.x()+5, r.y() + 2, r.right()-5 , r.y() + 2 ); + break; + } + + QRect cr = visualRect( QRect( r.x() + 2, r.y() + 2, checkcol - 1, r.height() - 4 ), r ); + // Do we have an icon? + if ( mi->iconSet() ) + { + QIconSet::Mode mode; + + // Select the correct icon from the iconset + if (active) + mode = enabled?QIconSet::Active:QIconSet::Disabled; + else + mode = enabled?QIconSet::Normal:QIconSet::Disabled; + + // Do we have an icon and are checked at the same time? + // Then draw a "pressed" background behind the icon + if ( checkable && /*!active &&*/ mi->isChecked() ) + qDrawShadePanel( p, cr.x(), cr.y(), cr.width(), cr.height(), + cg, true, 1, &cg.brush(QColorGroup::Midlight) ); + // Draw the icon + QPixmap pixmap = mi->iconSet()->pixmap(QIconSet::Small, mode); + QRect pmr( 0, 0, pixmap.width(), pixmap.height() ); + pmr.moveCenter( cr.center() ); + p->drawPixmap( pmr.topLeft(), pixmap ); + } + + // Are we checked? (This time without an icon) + else if ( checkable && mi->isChecked() ) + { + // We only have to draw the background if the menu item is inactive - + // if it's active the "pressed" background is already drawn + // if ( ! active ) + qDrawShadePanel( p, cr.x(), cr.y(), cr.width(), cr.height(), cg, true, 1, + &cg.brush(QColorGroup::Midlight) ); + + // Draw the checkmark + SFlags cflags = Style_On; + if (enabled) + cflags |= Style_Enabled; + drawPrimitive( PE_CheckMark, p, cr, cg, cflags ); + } + + // Time to draw the menu item label... + int xm = 2 + checkcol + 2; // X position margin + + int xp = reverse ? // X position + r.x() + tab + rightBorder + itemHMargin + itemFrame - 1 : + r.x() + xm; + + int offset = reverse ? -1 : 1; // Shadow offset for etched text + + // Label width (minus the width of the accelerator portion) + int tw = r.width() - xm - tab - arrowHMargin - itemHMargin * 3 - itemFrame + 1; + + // Set the color for enabled and disabled text + // (used for both active and inactive menu items) + p->setPen( enabled ? cg.buttonText() : cg.mid() ); + + // This color will be used instead of the above if the menu item + // is active and disabled at the same time. (etched text) + QColor discol = cg.mid(); + + // Does the menu item draw it's own label? + if ( mi->custom() ) { + int m = 2; + // Save the painter state in case the custom + // paint method changes it in some way + p->save(); + + // Draw etched text if we're inactive and the menu item is disabled + if ( etchtext && !enabled && !active ) { + p->setPen( cg.light() ); + mi->custom()->paint( p, cg, active, enabled, xp+offset, r.y()+m+1, tw, r.height()-2*m ); + p->setPen( discol ); + } + mi->custom()->paint( p, cg, active, enabled, xp, r.y()+m, tw, r.height()-2*m ); + p->restore(); + } + else { + // The menu item doesn't draw it's own label + QString s = mi->text(); + // Does the menu item have a text label? + if ( !s.isNull() ) { + int t = s.find( '\t' ); + int m = 2; + int text_flags = AlignVCenter | ShowPrefix | DontClip | SingleLine; + text_flags |= reverse ? AlignRight : AlignLeft; + + //QColor draw = cg.text(); + QColor draw = (active && enabled) ? cg.highlightedText () : cg.foreground(); + p->setPen(draw); + + + // Does the menu item have a tabstop? (for the accelerator text) + if ( t >= 0 ) { + int tabx = reverse ? r.x() + rightBorder + itemHMargin + itemFrame : + r.x() + r.width() - tab - rightBorder - itemHMargin - itemFrame; + + // Draw the right part of the label (accelerator text) + if ( etchtext && !enabled ) { + // Draw etched text if we're inactive and the menu item is disabled + p->setPen( cg.light() ); + p->drawText( tabx+offset, r.y()+m+1, tab, r.height()-2*m, text_flags, s.mid( t+1 ) ); + p->setPen( discol ); + } + p->drawText( tabx, r.y()+m, tab, r.height()-2*m, text_flags, s.mid( t+1 ) ); + s = s.left( t ); + } + + // Draw the left part of the label (or the whole label + // if there's no accelerator) + if ( etchtext && !enabled ) { + // Etched text again for inactive disabled menu items... + p->setPen( cg.light() ); + p->drawText( xp+offset, r.y()+m+1, tw, r.height()-2*m, text_flags, s, t ); + p->setPen( discol ); + } + + + p->drawText( xp, r.y()+m, tw, r.height()-2*m, text_flags, s, t ); + + p->setPen(cg.text()); + + } + + // The menu item doesn't have a text label + // Check if it has a pixmap instead + else if ( mi->pixmap() ) { + QPixmap *pixmap = mi->pixmap(); + + // Draw the pixmap + if ( pixmap->depth() == 1 ) + p->setBackgroundMode( OpaqueMode ); + + int diffw = ( ( r.width() - pixmap->width() ) / 2 ) + + ( ( r.width() - pixmap->width() ) % 2 ); + p->drawPixmap( r.x()+diffw, r.y()+1, *pixmap ); + + if ( pixmap->depth() == 1 ) + p->setBackgroundMode( TransparentMode ); + } + } + + // Does the menu item have a submenu? + if ( mi->popup() ) { + PrimitiveElement arrow = reverse ? PE_ArrowLeft : PE_ArrowRight; + int dim = pixelMetric(PM_MenuButtonIndicator) - 1; + QRect vr = visualRect( QRect( r.x() + r.width() - 5 - 1 - dim, + r.y() + r.height() / 2 - dim / 2, dim, dim), r ); + + // Draw an arrow at the far end of the menu item + if ( active ) { + if ( enabled ) + discol = cg.buttonText(); + + QColorGroup g2( discol, cg.highlight(), white, white, + enabled ? white : discol, discol, white ); + + drawPrimitive( arrow, p, vr, g2, Style_Enabled ); + } else + drawPrimitive( arrow, p, vr, cg, + enabled ? Style_Enabled : Style_Default ); + } + break; + } + + // Menu and dockwindow empty space + // + case CE_DockWindowEmptyArea: + p->fillRect(r, cg.background()); + break; + + case CE_MenuBarEmptyArea: + p->fillRect(r, cg.background()); + +// if ( _drawToolBarSeparator ) { +// p->setPen( getColor(cg, PanelDark) ); +// p->drawLine( r.left(), r.bottom(), r.right(), r.bottom() ); +// } + + break; + + default: + KStyle::drawControl(element, p, widget, r, cg, flags, opt); + } +} + +void PlastikStyle::drawControlMask(ControlElement element, + QPainter *p, + const QWidget *w, + const QRect &r, + const QStyleOption &opt) const +{ + switch (element) { + case CE_PushButton: { + p->fillRect (r, color0); + renderMask(p, r, color1, + Round_UpperLeft|Round_UpperRight|Round_BottomLeft|Round_BottomRight); + break; + } + + default: { + KStyle::drawControlMask (element, p, w, r, opt); + } + } +} + +void PlastikStyle::drawComplexControlMask(ComplexControl c, + QPainter *p, + const QWidget *w, + const QRect &r, + const QStyleOption &o) const +{ + switch (c) { + case CC_SpinWidget: + case CC_ListView: + case CC_ComboBox: { + p->fillRect (r, color0); + renderMask(p, r, color1, + Round_UpperLeft|Round_UpperRight|Round_BottomLeft|Round_BottomRight); + break; + } + default: { + KStyle::drawComplexControlMask (c, p, w, r, o); + } + } +} + +void PlastikStyle::drawComplexControl(ComplexControl control, + QPainter *p, + const QWidget *widget, + const QRect &r, + const QColorGroup &cg, + SFlags flags, + SCFlags controls, + SCFlags active, + const QStyleOption& opt) const +{ + const bool reverseLayout = QApplication::reverseLayout(); + + const bool enabled = (flags & Style_Enabled); + + switch(control) { + // COMBOBOX + // -------- + case CC_ComboBox: { + static const unsigned int handleWidth = 15; + + const QComboBox *cb = dynamic_cast<const QComboBox *>(widget); + // at the moment cb is only needed to check if the combo box is editable or not. + // if cb doesn't exist, just assume false and the app (gideon! ;) ) at least doesn't crash. + bool editable = false; + bool hasFocus = false; + if (cb) { + editable = cb->editable(); + hasFocus = cb->hasFocus(); + } + + const QColor buttonColor = enabled?cg.button():cg.background(); + const QColor inputColor = enabled?(editable?cg.base():cg.button()) + :cg.background(); + + uint contourFlags = 0; + if( khtmlWidgets.contains(cb) ) + contourFlags |= Draw_AlphaBlend; + + if (_inputFocusHighlight && hasFocus && editable && enabled) + { + QRect editField = querySubControlMetrics(control, widget, SC_ComboBoxEditField); + QRect editFrame = r; + QRect buttonFrame = r; + + uint editFlags = contourFlags; + uint buttonFlags = contourFlags; + + // Hightlight only the part of the contour next to the control button + if (reverseLayout) + { + // querySubControlMetrics doesn't work right for reverse Layout + int dx = r.right() - editField.right(); + editFrame.setLeft(editFrame.left() + dx); + buttonFrame.setRight(editFrame.left() - 1); + editFlags |= Draw_Right|Draw_Top|Draw_Bottom|Round_UpperRight|Round_BottomRight; + buttonFlags |= Draw_Left|Draw_Top|Draw_Bottom|Round_UpperLeft|Round_BottomLeft; + } + else + { + editFrame.setRight(editField.right()); + buttonFrame.setLeft(editField.right() + 1); + + editFlags |= Draw_Left|Draw_Top|Draw_Bottom|Round_UpperLeft|Round_BottomLeft; + buttonFlags |= Draw_Right|Draw_Top|Draw_Bottom|Round_UpperRight|Round_BottomRight; + } + renderContour(p, editFrame, cg.background(), getColor(cg,FocusHighlight,enabled), editFlags); + renderContour(p, buttonFrame, cg.background(), + getColor(cg, ButtonContour, enabled), buttonFlags); + } + else + { + contourFlags |= Draw_Left|Draw_Right|Draw_Top|Draw_Bottom| + Round_UpperLeft|Round_UpperRight|Round_BottomLeft|Round_BottomRight; + renderContour(p, r, cg.background(), getColor(cg, ButtonContour, enabled), contourFlags); + } + //extend the contour: between input and handler... + p->setPen(alphaBlendColors(cg.background(), getColor(cg, ButtonContour, enabled), 50) ); + if(reverseLayout) { + p->drawLine(r.left()+1+handleWidth, r.top()+1, r.left()+1+handleWidth, r.bottom()-1); + } else { + p->drawLine(r.right()-handleWidth-1, r.top()+1, r.right()-handleWidth-1, r.bottom()-1); + } + + const QRect RbuttonSurface(reverseLayout?r.left()+1:r.right()-handleWidth, r.top()+1, + handleWidth, r.height()-2); + const QRect RcontentSurface(reverseLayout?r.left()+1+handleWidth+1:r.left()+1, r.top()+1, + r.width()-handleWidth-3, r.height()-2); + + // handler + + uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Is_Horizontal; + if(reverseLayout) { + surfaceFlags |= Round_UpperLeft|Round_BottomLeft; + } else { + surfaceFlags |= Round_UpperRight|Round_BottomRight; + } + + if ((widget == hoverWidget) || (flags & Style_MouseOver)) { + surfaceFlags |= Is_Highlight; + if(editable) surfaceFlags |= Highlight_Left|Highlight_Right; + surfaceFlags |= Highlight_Top|Highlight_Bottom; + } + renderSurface(p, RbuttonSurface, + cg.background(), buttonColor, getColor(cg,MouseOverHighlight), enabled?_contrast+3:(_contrast/2), + surfaceFlags); + + if(!editable) { + surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Is_Horizontal; + if(reverseLayout) { + surfaceFlags |= Round_UpperRight|Round_BottomRight; + } else { + surfaceFlags |= Round_UpperLeft|Round_BottomLeft; + } + + if ((widget == hoverWidget) || (flags & Style_MouseOver)) { + surfaceFlags |= Is_Highlight; + surfaceFlags |= Highlight_Top|Highlight_Bottom; + } + renderSurface(p, RcontentSurface, + cg.background(), buttonColor, getColor(cg,MouseOverHighlight), enabled?_contrast+3:(_contrast/2), + surfaceFlags); + if (hasFocus) { + drawPrimitive(PE_FocusRect, p, + QRect(RcontentSurface.x() + 2, + RcontentSurface.y() + 2, + RcontentSurface.width() - 4, + RcontentSurface.height() - 4), cg); + } + } else { + // thin frame around the input area + if (_inputFocusHighlight && hasFocus && editable && enabled) + { + p->setPen( getColor(cg,FocusHighlight).dark(130) ); + } + else + { + p->setPen(inputColor.dark(130) ); + } + p->drawLine(RcontentSurface.x(), reverseLayout?RcontentSurface.y():RcontentSurface.y()+1, + RcontentSurface.x(), reverseLayout?RcontentSurface.bottom():RcontentSurface.bottom()-1); + p->drawLine(RcontentSurface.x()+1, RcontentSurface.y(), + reverseLayout?RcontentSurface.right()-1:RcontentSurface.right(), RcontentSurface.y() ); + if (_inputFocusHighlight && hasFocus && editable && enabled) + { + p->setPen( getColor(cg,FocusHighlight).light(130) ); + } + else + { + p->setPen(inputColor.light(130) ); + } + p->drawLine(reverseLayout?RcontentSurface.x():RcontentSurface.x()+1, RcontentSurface.bottom(), + reverseLayout?RcontentSurface.right()-1:RcontentSurface.right(), RcontentSurface.bottom() ); + p->drawLine(RcontentSurface.right(), RcontentSurface.top()+1, + RcontentSurface.right(), RcontentSurface.bottom()-1 ); + + // input area + p->fillRect(RcontentSurface.x()+1, RcontentSurface.y()+1, + RcontentSurface.width()-2, RcontentSurface.height()-2, inputColor ); + } + + p->setPen(cg.foreground()); + drawPrimitive(PE_SpinWidgetDown, p, RbuttonSurface, cg, Style_Default|Style_Enabled|Style_Raised); + + // QComboBox draws the text using cg.text(), we can override this + // from here + p->setPen( cg.buttonText() ); + p->setBackgroundColor( cg.button() ); + break; + } + + // TOOLBUTTON + // ---------- + case CC_ToolButton: { + const QToolButton *tb = (const QToolButton *) widget; + + QRect button, menuarea; + button = querySubControlMetrics(control, widget, SC_ToolButton, opt); + menuarea = querySubControlMetrics(control, widget, SC_ToolButtonMenu, opt); + + SFlags bflags = flags, + mflags = flags; + + if (kornMode) { + drawPrimitive(PE_ButtonTool, p, button, cg, bflags, opt); + break; + } else { + // don't want to have the buttoncolor as the background... + p->fillRect(r, cg.background()); + bflags &= ~Style_MouseOver; + } + + if (active & SC_ToolButton) + bflags |= Style_Down; + + if (active & SC_ToolButtonMenu) + mflags |= Style_Down; + + if (controls & SC_ToolButton) { + // If we're pressed, on, or raised... + if (bflags & (Style_Down | Style_On | Style_Raised) || widget==hoverWidget ) { + drawPrimitive(PE_ButtonTool, p, button, cg, bflags, opt); + } else if (tb->parentWidget() && + tb->parentWidget()->backgroundPixmap() && + !tb->parentWidget()->backgroundPixmap()->isNull()) { + QPixmap pixmap = *(tb->parentWidget()->backgroundPixmap()); + p->drawTiledPixmap( r, pixmap, tb->pos() ); + } + } + + // Draw a toolbutton menu indicator if required + if (controls & SC_ToolButtonMenu) { + if (mflags & (Style_Down | Style_On | Style_Raised)) { + drawPrimitive(PE_ButtonDropDown, p, menuarea, cg, mflags, opt); + } + drawPrimitive(PE_ArrowDown, p, menuarea, cg, mflags, opt); + } + + if (tb->hasFocus() && !tb->focusProxy()) { + QRect fr = tb->rect(); + fr.addCoords(2, 2, -2, -2); + drawPrimitive(PE_FocusRect, p, fr, cg); + } + + // Set the color for the ToolButton menu indicator + p->setPen(cg.buttonText() ); + + break; + } + + // SPINWIDGETS + // ----------- + case CC_SpinWidget: { + static const unsigned int handleWidth = 15; + + const QSpinWidget *sw = dynamic_cast<const QSpinWidget *>(widget); + SFlags sflags = flags; + PrimitiveElement pe; + + bool hasFocus = false; + if (sw) + hasFocus = sw->hasFocus(); + + const QColor buttonColor = enabled?cg.button():cg.background(); + const QColor inputColor = enabled?cg.base():cg.background(); + + // contour + const bool heightDividable = ((r.height()%2) == 0); + if (_inputFocusHighlight && hasFocus && enabled) + { + QRect editField = querySubControlMetrics(control, widget, SC_SpinWidgetEditField); + QRect editFrame = r; + QRect buttonFrame = r; + + uint editFlags = 0; + uint buttonFlags = 0; + + // Hightlight only the part of the contour next to the control buttons + if (reverseLayout) + { + // querySubControlMetrics doesn't work right for reverse Layout + int dx = r.right() - editField.right(); + editFrame.setLeft(editFrame.left() + dx); + buttonFrame.setRight(editFrame.left() - 1); + editFlags |= Draw_Right|Draw_Top|Draw_Bottom|Round_UpperRight|Round_BottomRight; + buttonFlags |= Draw_Left|Draw_Top|Draw_Bottom|Round_UpperLeft|Round_BottomLeft; + } + else + { + editFrame.setRight(editField.right()); + buttonFrame.setLeft(editField.right() + 1); + + editFlags |= Draw_Left|Draw_Top|Draw_Bottom|Round_UpperLeft|Round_BottomLeft; + buttonFlags |= Draw_Right|Draw_Top|Draw_Bottom|Round_UpperRight|Round_BottomRight; + } + renderContour(p, editFrame, cg.background(), cg.highlight(), editFlags); + renderContour(p, buttonFrame, cg.background(), + getColor(cg, ButtonContour, enabled), buttonFlags); + } + else + { + renderContour(p, querySubControlMetrics(control, widget, SC_SpinWidgetFrame), + cg.background(), getColor(cg, ButtonContour, enabled) ); + } + p->setPen(alphaBlendColors(cg.background(), getColor(cg, ButtonContour, enabled), 50) ); + p->drawLine(reverseLayout?r.left()+1+handleWidth:r.right()-handleWidth-1, r.top()+1, + reverseLayout?r.left()+1+handleWidth:r.right()-handleWidth-1, r.bottom()-1); + p->drawLine(reverseLayout?r.left()+1:r.right()-handleWidth, r.top()+1+(r.height()-2)/2, + reverseLayout?r.left()+handleWidth:r.right()-1, r.top()+1+(r.height()-2)/2); + if(heightDividable) + p->drawLine(reverseLayout?r.left()+1:r.right()-handleWidth, r.top()+1+(r.height()-2)/2-1, + reverseLayout?r.left()+handleWidth:r.right()-1, r.top()+1+(r.height()-2)/2-1); + + // surface + QRect upRect = QRect(reverseLayout?r.left()+1:r.right()-handleWidth, r.top()+1, + handleWidth, (r.height()-2)/2); + QRect downRect = QRect(reverseLayout?r.left()+1:r.right()-handleWidth, + heightDividable?r.top()+1+((r.height()-2)/2):r.top()+1+((r.height()-2)/2)+1, + handleWidth, ((r.height()-2)/2) ); + if(heightDividable) { + upRect = QRect(upRect.left(), upRect.top(), upRect.width(), upRect.height()-1 ); + downRect = QRect(downRect.left(), downRect.top()+1, downRect.width(), downRect.height()-1 ); + } + + uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Is_Horizontal; + if(reverseLayout) { + surfaceFlags |= Round_UpperLeft; + } else { + surfaceFlags |= Round_UpperRight; + } + if ((widget == hoverWidget) || (sflags & Style_MouseOver)) { + surfaceFlags |= Is_Highlight; + surfaceFlags |= Highlight_Top|Highlight_Left|Highlight_Right; + } + if (active==SC_SpinWidgetUp) surfaceFlags|=Is_Sunken; + if(!enabled) surfaceFlags|=Is_Disabled; + renderSurface(p, upRect, cg.background(), buttonColor, getColor(cg,MouseOverHighlight), + _contrast, surfaceFlags); + surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Is_Horizontal; + if(reverseLayout) { + surfaceFlags |= Round_BottomLeft; + } else { + surfaceFlags |= Round_BottomRight; + } + if ((widget == hoverWidget) || (sflags & Style_MouseOver)) { + surfaceFlags |= Is_Highlight; + surfaceFlags |= Highlight_Bottom|Highlight_Left|Highlight_Right; + } + if (active==SC_SpinWidgetDown) surfaceFlags|=Is_Sunken; + if(!enabled) surfaceFlags|=Is_Disabled; + renderSurface(p, downRect, cg.background(), buttonColor, getColor(cg,MouseOverHighlight), + _contrast, surfaceFlags); + + // icons... + sflags = Style_Default | Style_Enabled; + if (active == SC_SpinWidgetUp) { + sflags |= Style_On; + sflags |= Style_Sunken; + } else + sflags |= Style_Raised; + if (sw->buttonSymbols() == QSpinWidget::PlusMinus) + pe = PE_SpinWidgetPlus; + else + pe = PE_SpinWidgetUp; + p->setPen(cg.foreground()); + drawPrimitive(pe, p, upRect, cg, sflags); + + sflags = Style_Default | Style_Enabled; + if (active == SC_SpinWidgetDown) { + sflags |= Style_On; + sflags |= Style_Sunken; + } else + sflags |= Style_Raised; + if (sw->buttonSymbols() == QSpinWidget::PlusMinus) + pe = PE_SpinWidgetMinus; + else + pe = PE_SpinWidgetDown; + p->setPen(cg.foreground()); + drawPrimitive(pe, p, downRect, cg, sflags); + + // thin frame around the input area + const QRect Rcontent = QRect(reverseLayout?r.left()+1+handleWidth+1:r.left()+1, r.top()+1, + r.width()-1-2-handleWidth, r.height()-2); + if (_inputFocusHighlight && hasFocus && enabled) + { + p->setPen( getColor(cg,FocusHighlight).dark(130) ); + } + else + { + p->setPen(inputColor.dark(130) ); + } + p->drawLine(Rcontent.left(), reverseLayout?Rcontent.top():Rcontent.top()+1, + Rcontent.left(), reverseLayout?Rcontent.bottom():Rcontent.bottom()-1 ); + p->drawLine(Rcontent.left()+1, Rcontent.top(), + reverseLayout?Rcontent.right()-1:Rcontent.right(), Rcontent.top() ); + if (_inputFocusHighlight && hasFocus && enabled) + { + p->setPen( getColor(cg,FocusHighlight).light(130) ); + } + else + { + p->setPen(inputColor.light(130) ); + } + p->drawLine(Rcontent.left()+1, Rcontent.bottom(), Rcontent.right()-1, Rcontent.bottom() ); + p->drawLine(Rcontent.right(), Rcontent.top()+1, + Rcontent.right(), reverseLayout?Rcontent.bottom()-1:Rcontent.bottom() ); + + break; + } + + default: + KStyle::drawComplexControl(control, p, widget, + r, cg, flags, controls, + active, opt); + break; + } +} + + +QRect PlastikStyle::subRect(SubRect r, const QWidget *widget) const +{ + switch (r) { + case SR_ComboBoxFocusRect: { + return querySubControlMetrics( CC_ComboBox, widget, SC_ComboBoxEditField ); + } + + // Don't use KStyles progressbar subrect + // TODO: + case SR_ProgressBarGroove: { + return QRect(widget->rect()); + } + case SR_ProgressBarContents: + case SR_ProgressBarLabel: { + QRect rw = widget->rect(); + return QRect(rw.left()+2, rw.top()+2, rw.width()-4, rw.height()-4 ); + } + + default: { + return KStyle::subRect(r, widget); + } + } +} + +QRect PlastikStyle::querySubControlMetrics(ComplexControl control, + const QWidget *widget, + SubControl subcontrol, + const QStyleOption &opt) const +{ + if (!widget) { + return QRect(); + } + + QRect r(widget->rect()); + switch (control) { + case CC_ComboBox: { + switch (subcontrol) { + case SC_ComboBoxEditField: { + // TODO: is the handler width in pixelmetric? + return QRect(r.left()+2, r.top()+2, r.width()-4-15-1, r.height()-4); + } + default: { + return KStyle::querySubControlMetrics(control, widget, subcontrol, opt); + } + } + break; + } + case CC_SpinWidget: { + const int fw = 2; // Frame width... + + const bool heightDividable = ((r.height()%2) == 0); + + QSize bs; + if(heightDividable) { + bs.setHeight(QMAX(8, (r.height()-2)/2)); + } else { + bs.setHeight(QMAX(8, (r.height()-2-1)/2)); + } + bs.setWidth(15); + + const int buttonsLeft = /*reverseLayout?r.left()+1:*/r.right()-bs.width(); + + switch (subcontrol) { + case SC_SpinWidgetUp: { + return QRect(buttonsLeft, r.top()+1, bs.width(), bs.height() ); + } + case SC_SpinWidgetDown: { + if(heightDividable) { + return QRect(buttonsLeft, r.top()+1+bs.height(), + bs.width(), r.height()-(bs.height()+2) ); + } else { + return QRect(buttonsLeft, r.top()+1+bs.height()+1, + bs.width(), r.height()-(bs.height()+2+1) ); + } + } + case SC_SpinWidgetFrame: { + return QRect(r.left(), r.top(), r.width(), r.height() ); + } + case SC_SpinWidgetEditField: { + return QRect(r.left()+fw, r.top()+fw, + r.width()-(bs.width()+1+2*fw), r.height()-2*fw); + } + case SC_SpinWidgetButtonField: { + return QRect(buttonsLeft, r.top()+1, bs.width(), r.height()-2); + } + default: { + return KStyle::querySubControlMetrics(control, widget, subcontrol, opt); + } + } + break; + } + default: { + return KStyle::querySubControlMetrics(control, widget, subcontrol, opt); + } + } +} + +int PlastikStyle::pixelMetric(PixelMetric m, const QWidget *widget) const +{ + switch(m) { + // TABS + // ---- + case PM_TabBarTabVSpace: { + const QTabBar * tb = (const QTabBar *) widget; + if (tb->shape() == QTabBar::RoundedAbove || + tb->shape() == QTabBar::RoundedBelow) + return 12; + else + return 4; + } + + case PM_TabBarTabOverlap: { + return 1; + } + + // extra space between menubar items + case PM_MenuBarItemSpacing: { + return 6; + } + +// // extra space between toolbar items +// case PM_ToolBarItemSpacing: { +// return 4; +// } + + // SCROLL BAR + case PM_ScrollBarSliderMin: { + return 21; + } + case PM_ScrollBarExtent: { + return 16; + } + + case PM_DockWindowSeparatorExtent: + return 6; + + // SPLITTERS + // --------- + case PM_SplitterWidth: { + return 6; + } + + // PROGRESSBARS + // ------------ + case PM_ProgressBarChunkWidth: + return 10; + + // SLIDER + // ------ + case PM_SliderLength: + return 11; + + // MENU INDICATOR + // -------------- + case PM_MenuButtonIndicator: + return 8; + + // CHECKBOXES / RADIO BUTTONS + // -------------------------- + case PM_ExclusiveIndicatorWidth: // Radiobutton size + case PM_ExclusiveIndicatorHeight: // 13x13 + case PM_IndicatorWidth: // Checkbox size + case PM_IndicatorHeight: // 13x13 + return 13; + + // FRAMES + // ------ + case PM_SpinBoxFrameWidth: + return 1; + + case PM_MenuBarFrameWidth: + return 1; + + case PM_DefaultFrameWidth: { + if(widget && ::qt_cast<QPopupMenu*>(widget)) + return 1; + else + return 2; + } + + case PM_ButtonDefaultIndicator: { + return 0; + } + + case PM_ButtonMargin: { + return 2; + } + + case PM_ButtonShiftVertical: + case PM_ButtonShiftHorizontal: { + return 1; + } + + default: + return KStyle::pixelMetric(m, widget); + } +} + + +QSize PlastikStyle::sizeFromContents(ContentsType t, + const QWidget *widget, + const QSize &s, + const QStyleOption &opt) const +{ + switch (t) { + case CT_PopupMenuItem: { + if (!widget || opt.isDefault()) + return s; + + const QPopupMenu *popup = dynamic_cast<const QPopupMenu *>(widget); + QMenuItem *mi = opt.menuItem(); + int maxpmw = opt.maxIconWidth(); + int w = s.width(), h = s.height(); + bool checkable = popup->isCheckable(); + + if (mi->custom()) { + w = mi->custom()->sizeHint().width(); + h = mi->custom()->sizeHint().height(); + if (!mi->custom()->fullSpan() ) + h += 4; + } else if (mi->widget()) { + // don't change the size in this case. + } else if (mi->isSeparator()) { + w = 20; + h = 2; + } else { + if (mi->pixmap()) { + h = QMAX(h, mi->pixmap()->height() + 2); + } else { + h = QMAX(h, 16 + 2 ); + h = QMAX(h, popup->fontMetrics().height() + 4 ); + } + + if (mi->iconSet()) { + h = QMAX(h, mi->iconSet()->pixmap(QIconSet::Small, QIconSet::Normal).height() + 2); + } + } + + if (!mi->text().isNull() && (mi->text().find('\t') >= 0)) { + w += itemHMargin + itemFrame*2 + 7; + } else if (mi->popup()) { + w += 2 * arrowHMargin; + } + + if (maxpmw) { + w += maxpmw + 6; + } + if (checkable && maxpmw < 20) { + w += 20 - maxpmw; + } + if (checkable || maxpmw > 0) { + w += 12; + } + + w += rightBorder; + + return QSize(w, h); + } + + case CT_PushButton: + { + const QPushButton* btn = static_cast<const QPushButton*>(widget); + + int w = s.width() + 2 * pixelMetric(PM_ButtonMargin, widget); + int h = s.height() + 2 * pixelMetric(PM_ButtonMargin, widget); + if ( btn->text().isEmpty() && s.width() < 32 ) return QSize(w, h); + + return QSize( w+25, h+5 ); + } + + case CT_ToolButton: + { + if(widget->parent() && ::qt_cast<QToolBar*>(widget->parent()) ) + return QSize( s.width()+2*4, s.height()+2*4 ); + else + return KStyle::sizeFromContents (t, widget, s, opt); + } + + default: + return KStyle::sizeFromContents (t, widget, s, opt); + } + + return KStyle::sizeFromContents (t, widget, s, opt); +} + +int PlastikStyle::styleHint( StyleHint stylehint, + const QWidget *widget, + const QStyleOption &option, + QStyleHintReturn* returnData ) const +{ + switch (stylehint) { + case SH_PopupMenu_SubMenuPopupDelay: + return 96; // Motif-like delay... + + default: + return KStyle::styleHint(stylehint, widget, option, returnData); + } +} + +bool PlastikStyle::eventFilter(QObject *obj, QEvent *ev) +{ + if (KStyle::eventFilter(obj, ev) ) + return true; + + if (!obj->isWidgetType() ) return false; + + // focus highlight + if ( ::qt_cast<QLineEdit*>(obj) ) { + QWidget* widget = static_cast<QWidget*>(obj); + + if ( ::qt_cast<QSpinWidget*>(widget->parentWidget()) ) + { + QWidget* spinbox = widget->parentWidget(); + if ((ev->type() == QEvent::FocusIn) || (ev->type() == QEvent::FocusOut)) + { + spinbox->repaint(false); + } + return false; + } + + if ((ev->type() == QEvent::FocusIn) || (ev->type() == QEvent::FocusOut)) + { + widget->repaint(false); + } + return false; + } + + //Hover highlight... use qt_cast to check if the widget inheits one of the classes. + if ( ::qt_cast<QPushButton*>(obj) || ::qt_cast<QComboBox*>(obj) || + ::qt_cast<QSpinWidget*>(obj) || ::qt_cast<QCheckBox*>(obj) || + ::qt_cast<QRadioButton*>(obj) || ::qt_cast<QToolButton*>(obj) || obj->inherits("QSplitterHandle") ) + { + if ((ev->type() == QEvent::Enter) && static_cast<QWidget*>(obj)->isEnabled()) + { + QWidget* button = static_cast<QWidget*>(obj); + hoverWidget = button; + button->repaint(false); + } + else if ((ev->type() == QEvent::Leave) && (obj == hoverWidget) ) + { + QWidget* button = static_cast<QWidget*>(obj); + hoverWidget = 0; + button->repaint(false); + } + return false; + } + if ( ::qt_cast<QTabBar*>(obj) ) { + if ((ev->type() == QEvent::Enter) && static_cast<QWidget*>(obj)->isEnabled()) + { + QWidget* tabbar = static_cast<QWidget*>(obj); + hoverWidget = tabbar; + hoverTab = 0; + tabbar->repaint(false); + } + else if (ev->type() == QEvent::MouseMove) + { + QTabBar *tabbar = dynamic_cast<QTabBar*>(obj); + QMouseEvent *me = dynamic_cast<QMouseEvent*>(ev); + + if (tabbar && me) { + // avoid unnecessary repaints (which otherwise would occour on every + // MouseMove event causing high cpu load). + + bool repaint = true; + + QTab *tab = tabbar->selectTab(me->pos() ); + if (hoverTab == tab) + repaint = false; + hoverTab = tab; + + if (repaint) + tabbar->repaint(false); + } + } + else if (ev->type() == QEvent::Leave) + { + QWidget* tabbar = static_cast<QWidget*>(obj); + hoverWidget = 0; + hoverTab = 0; + tabbar->repaint(false); + } + return false; + } + // Track show events for progress bars + if ( _animateProgressBar && ::qt_cast<QProgressBar*>(obj) ) + { + if ((ev->type() == QEvent::Show) && !animationTimer->isActive()) + { + animationTimer->start( 50, false ); + } + } + if ( !qstrcmp(obj->name(), "kde toolbar widget") ) + { + QWidget* lb = static_cast<QWidget*>(obj); + if (lb->backgroundMode() == Qt::PaletteButton) + lb->setBackgroundMode(Qt::PaletteBackground); + lb->removeEventFilter(this); + } + + return false; +} + +QColor PlastikStyle::getColor(const QColorGroup &cg, const ColorType t, const bool enabled)const +{ + return getColor(cg, t, enabled?IsEnabled:IsDisabled); +} + +QColor PlastikStyle::getColor(const QColorGroup &cg, const ColorType t, const WidgetState s)const +{ + const bool enabled = (s != IsDisabled) && + ((s == IsEnabled) || (s == IsPressed) || (s == IsHighlighted)); + const bool pressed = (s == IsPressed); + const bool highlighted = (s == IsHighlighted); + switch(t) { + case ButtonContour: + return enabled ? cg.button().dark(130+_contrast*8) + : cg.background().dark(120+_contrast*8); + case DragButtonContour: { + if(enabled) { + if(pressed) + return cg.button().dark(130+_contrast*6); // bright + else if(highlighted) + return cg.button().dark(130+_contrast*9); // dark + else + return cg.button().dark(130+_contrast*8); // normal + } else { + return cg.background().dark(120+_contrast*8); + } + } + case DragButtonSurface: { + if(enabled) { + if(pressed) + return cg.button().dark(100-_contrast); // bright + else if(highlighted) + return cg.button().light(100+_contrast); // dark + else + return cg.button(); // normal + } else { + return cg.background(); + } + } + case PanelContour: + return cg.background().dark(160+_contrast*8); + case PanelDark: + return alphaBlendColors(cg.background(), cg.background().dark(120+_contrast*5), 110); + case PanelDark2: + return alphaBlendColors(cg.background(), cg.background().dark(110+_contrast*5), 110); + case PanelLight: + return alphaBlendColors(cg.background(), cg.background().light(120+_contrast*5), 110); + case PanelLight2: + return alphaBlendColors(cg.background(), cg.background().light(110+_contrast*5), 110); + case MouseOverHighlight: + if( _customOverHighlightColor ) + return _overHighlightColor; + else + return cg.highlight(); + case FocusHighlight: + if( _customFocusHighlightColor ) + return _focusHighlightColor; + else + return cg.highlight(); + case CheckMark: + if( _customCheckMarkColor ) + return _checkMarkColor; + else + return cg.foreground(); + default: + return cg.background(); + } +} |