00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "combobox.h"
00021
00022 #include <QPainter>
00023 #include <QApplication>
00024
00025 #include <kcombobox.h>
00026 #include <kmimetype.h>
00027 #include <kiconeffect.h>
00028 #include <kiconloader.h>
00029
00030 #include <plasma/private/style_p.h>
00031 #include "theme.h"
00032 #include "framesvg.h"
00033 #include "animator.h"
00034 #include "paintutils.h"
00035
00036 namespace Plasma
00037 {
00038
00039 class ComboBoxPrivate
00040 {
00041 public:
00042 ComboBoxPrivate(ComboBox *comboBox)
00043 : q(comboBox),
00044 background(0)
00045 {
00046 }
00047
00048 ~ComboBoxPrivate()
00049 {
00050 }
00051
00052 void syncActiveRect();
00053 void syncBorders();
00054 void animationUpdate(qreal progress);
00055
00056 ComboBox *q;
00057
00058 FrameSvg *background;
00059 int animId;
00060 bool fadeIn;
00061 qreal opacity;
00062 QRectF activeRect;
00063 Style::Ptr style;
00064 };
00065
00066 void ComboBoxPrivate::syncActiveRect()
00067 {
00068 background->setElementPrefix("normal");
00069
00070 qreal left, top, right, bottom;
00071 background->getMargins(left, top, right, bottom);
00072
00073 background->setElementPrefix("active");
00074 qreal activeLeft, activeTop, activeRight, activeBottom;
00075 background->getMargins(activeLeft, activeTop, activeRight, activeBottom);
00076
00077 activeRect = QRectF(QPointF(0, 0), q->size());
00078 activeRect.adjust(left - activeLeft, top - activeTop,
00079 -(right - activeRight), -(bottom - activeBottom));
00080
00081 background->setElementPrefix("normal");
00082 }
00083
00084 void ComboBoxPrivate::syncBorders()
00085 {
00086
00087 qreal left, top, right, bottom;
00088
00089 background->setElementPrefix("normal");
00090 background->getMargins(left, top, right, bottom);
00091 q->setContentsMargins(left, top, right, bottom);
00092
00093
00094 syncActiveRect();
00095
00096 KComboBox *native = q->nativeWidget();
00097 native->setFont(Theme::defaultTheme()->font(Theme::DefaultFont));
00098 }
00099
00100 void ComboBoxPrivate::animationUpdate(qreal progress)
00101 {
00102 if (progress == 1) {
00103 animId = -1;
00104 fadeIn = true;
00105 }
00106
00107 opacity = fadeIn ? progress : 1 - progress;
00108
00109
00110 q->update();
00111 }
00112
00113 ComboBox::ComboBox(QGraphicsWidget *parent)
00114 : QGraphicsProxyWidget(parent),
00115 d(new ComboBoxPrivate(this))
00116 {
00117 KComboBox *native = new KComboBox;
00118 connect(native, SIGNAL(activated(const QString &)), this, SIGNAL(activated(const QString &)));
00119 connect(native, SIGNAL(currentIndexChanged(const QString &)),
00120 this, SIGNAL(textChanged(const QString &)));
00121 setWidget(native);
00122 native->setAttribute(Qt::WA_NoSystemBackground);
00123
00124 d->background = new FrameSvg(this);
00125 d->background->setImagePath("widgets/button");
00126 d->background->setCacheAllRenderedFrames(true);
00127 d->background->setElementPrefix("normal");
00128
00129 d->syncBorders();
00130 setAcceptHoverEvents(true);
00131 connect(Theme::defaultTheme(), SIGNAL(themeChanged()), SLOT(syncBorders()));
00132 d->style = Style::sharedStyle();
00133 native->setStyle(d->style.data());
00134 }
00135
00136 ComboBox::~ComboBox()
00137 {
00138 delete d;
00139 Style::doneWithSharedStyle();
00140 }
00141
00142 QString ComboBox::text() const
00143 {
00144 return static_cast<KComboBox*>(widget())->currentText();
00145 }
00146
00147 void ComboBox::setStyleSheet(const QString &stylesheet)
00148 {
00149 widget()->setStyleSheet(stylesheet);
00150 }
00151
00152 QString ComboBox::styleSheet()
00153 {
00154 return widget()->styleSheet();
00155 }
00156
00157 KComboBox *ComboBox::nativeWidget() const
00158 {
00159 return static_cast<KComboBox*>(widget());
00160 }
00161
00162 void ComboBox::addItem(const QString &text)
00163 {
00164 static_cast<KComboBox*>(widget())->addItem(text);
00165 }
00166
00167 void ComboBox::clear()
00168 {
00169 static_cast<KComboBox*>(widget())->clear();
00170 }
00171
00172 void ComboBox::resizeEvent(QGraphicsSceneResizeEvent *event)
00173 {
00174 if (d->background) {
00175
00176 d->syncActiveRect();
00177
00178 d->background->setElementPrefix("focus");
00179 d->background->resizeFrame(size());
00180
00181 d->background->setElementPrefix("active");
00182 d->background->resizeFrame(d->activeRect.size());
00183
00184 d->background->setElementPrefix("normal");
00185 d->background->resizeFrame(size());
00186 }
00187
00188 QGraphicsProxyWidget::resizeEvent(event);
00189 }
00190
00191 void ComboBox::paint(QPainter *painter,
00192 const QStyleOptionGraphicsItem *option,
00193 QWidget *widget)
00194 {
00195 if (!styleSheet().isNull() ||
00196 nativeWidget()->isEditable() ||
00197 Theme::defaultTheme()->useNativeWidgetStyle()) {
00198 QGraphicsProxyWidget::paint(painter, option, widget);
00199 return;
00200 }
00201
00202 QPixmap bufferPixmap;
00203
00204
00205 if (isEnabled()) {
00206 d->background->setElementPrefix("normal");
00207
00208 if (d->animId == -1) {
00209 d->background->paintFrame(painter);
00210 }
00211
00212 } else {
00213 bufferPixmap = QPixmap(rect().size().toSize());
00214 bufferPixmap.fill(Qt::transparent);
00215
00216 QPainter buffPainter(&bufferPixmap);
00217 d->background->paintFrame(&buffPainter);
00218 buffPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
00219 buffPainter.fillRect(bufferPixmap.rect(), QColor(0, 0, 0, 128));
00220
00221 painter->drawPixmap(0, 0, bufferPixmap);
00222 }
00223
00224
00225 if (isEnabled() && acceptHoverEvents()) {
00226 if (d->animId != -1) {
00227 d->background->setElementPrefix("normal");
00228 QPixmap normalPix = d->background->framePixmap();
00229 d->background->setElementPrefix("active");
00230 painter->drawPixmap(
00231 d->activeRect.topLeft(),
00232 PaintUtils::transition(d->background->framePixmap(), normalPix, 1 - d->opacity));
00233 } else if (isUnderMouse()) {
00234 d->background->setElementPrefix("active");
00235 d->background->paintFrame(painter, d->activeRect.topLeft());
00236 }
00237 }
00238
00239 if (nativeWidget()->hasFocus()) {
00240 d->background->setElementPrefix("focus");
00241 d->background->paintFrame(painter);
00242 }
00243
00244 painter->setPen(Theme::defaultTheme()->color(Theme::ButtonTextColor));
00245
00246 QStyleOptionComboBox comboOpt;
00247
00248 comboOpt.initFrom(nativeWidget());
00249
00250 comboOpt.palette.setColor(
00251 QPalette::ButtonText, Theme::defaultTheme()->color(Theme::ButtonTextColor));
00252 comboOpt.currentIcon = nativeWidget()->itemIcon(
00253 nativeWidget()->currentIndex());
00254 comboOpt.currentText = nativeWidget()->itemText(
00255 nativeWidget()->currentIndex());
00256 comboOpt.editable = false;
00257
00258 nativeWidget()->style()->drawControl(
00259 QStyle::CE_ComboBoxLabel, &comboOpt, painter, nativeWidget());
00260 comboOpt.rect = nativeWidget()->style()->subControlRect(
00261 QStyle::CC_ComboBox, &comboOpt, QStyle::SC_ComboBoxArrow, nativeWidget());
00262 nativeWidget()->style()->drawPrimitive(
00263 QStyle::PE_IndicatorArrowDown, &comboOpt, painter, nativeWidget());
00264 }
00265
00266 void ComboBox::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
00267 {
00268 const int FadeInDuration = 75;
00269
00270 if (d->animId != -1) {
00271 Animator::self()->stopCustomAnimation(d->animId);
00272 }
00273 d->animId = Animator::self()->customAnimation(
00274 40 / (1000 / FadeInDuration), FadeInDuration,
00275 Animator::LinearCurve, this, "animationUpdate");
00276
00277 d->background->setElementPrefix("active");
00278
00279 QGraphicsProxyWidget::hoverEnterEvent(event);
00280 }
00281
00282 void ComboBox::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
00283 {
00284 const int FadeOutDuration = 150;
00285
00286 if (d->animId != -1) {
00287 Animator::self()->stopCustomAnimation(d->animId != -1);
00288 }
00289
00290 d->fadeIn = false;
00291 d->animId = Animator::self()->customAnimation(
00292 40 / (1000 / FadeOutDuration),
00293 FadeOutDuration, Animator::LinearCurve, this, "animationUpdate");
00294
00295 d->background->setElementPrefix("active");
00296
00297 QGraphicsProxyWidget::hoverLeaveEvent(event);
00298 }
00299
00300 }
00301
00302 #include <combobox.moc>
00303