not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / kwin / clients / oxygen / oxygenbutton.cpp
blob6a0618eb938740a44d4dc92155de4beeb51f5a83
1 //////////////////////////////////////////////////////////////////////////////
2 // oxygenbutton.cpp
3 // -------------------
4 // Oxygen window decoration for KDE. Buttons.
5 // -------------------
6 // Copyright (c) 2006, 2007 Riccardo Iaconelli <riccardo@kde.org>
7 // Copyright (c) 2006, 2007 Casper Boemann <cbr@boemann.dk>
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining a copy
10 // of this software and associated documentation files (the "Software"), to
11 // deal in the Software without restriction, including without limitation the
12 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
13 // sell copies of the Software, and to permit persons to whom the Software is
14 // furnished to do so, subject to the following conditions:
16 // The above copyright notice and this permission notice shall be included in
17 // all copies or substantial portions of the Software.
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25 // IN THE SOFTWARE.
26 //////////////////////////////////////////////////////////////////////////////
28 #include "oxygenbutton.h"
29 #include <kcommondecoration.h>
31 #include <math.h>
32 #include <QPainterPath>
33 #include <QPainter>
34 #include <QPen>
35 #include <QBitmap>
37 #include <kdecoration.h>
38 #include <kglobal.h>
39 #include <KColorUtils>
40 #include <kdebug.h>
41 #include <KColorScheme>
43 #include "oxygenclient.h"
44 #include "oxygen.h"
46 namespace Oxygen
48 // class OxygenClient;
50 extern int BUTTONSIZE;
51 extern int DECOSIZE;*/
53 // static const int DECOSIZE = 8;
54 //////////////////////////////////////////////////////////////////////////////
55 // OxygenButton Class //
56 //////////////////////////////////////////////////////////////////////////////
58 //////////////////////////////////////////////////////////////////////////////
59 // OxygenButton()
60 // ---------------
61 // Constructor
63 OxygenButton::OxygenButton(OxygenClient &parent,
64 const QString& tip, ButtonType type)
65 : KCommonDecorationButton((::ButtonType)type, &parent)
66 , client_(parent)
67 , helper_(parent.helper_)
68 , type_(type)
69 , lastmouse_(0)
70 , colorCacheInvalid_(true)
72 setAutoFillBackground(false);
73 setAttribute(Qt::WA_OpaquePaintEvent, false);
74 setFixedSize(OXYGEN_BUTTONSIZE, OXYGEN_BUTTONSIZE);
75 setCursor(Qt::ArrowCursor);
76 setToolTip(tip);
79 OxygenButton::~OxygenButton()
83 //declare function from oxygenclient.cpp
84 QColor reduceContrast(const QColor &c0, const QColor &c1, double t);
87 QColor OxygenButton::buttonDetailColor(const QPalette &palette)
89 if (client_.isActive())
90 return palette.color(QPalette::Active, QPalette::ButtonText);
91 else {
92 if (colorCacheInvalid_) {
93 QColor ab = palette.color(QPalette::Active, QPalette::Button);
94 QColor af = palette.color(QPalette::Active, QPalette::ButtonText);
95 QColor nb = palette.color(QPalette::Inactive, QPalette::Button);
96 QColor nf = palette.color(QPalette::Inactive, QPalette::ButtonText);
98 colorCacheInvalid_ = false;
99 cachedButtonDetailColor_ = reduceContrast(nb, nf, qMax(qreal(2.5), KColorUtils::contrastRatio(ab, KColorUtils::mix(ab, af, 0.4))));
101 return cachedButtonDetailColor_;
105 //////////////////////////////////////////////////////////////////////////////
106 // sizeHint()
107 // ----------
108 // Return size hint
110 QSize OxygenButton::sizeHint() const
112 return QSize(OXYGEN_BUTTONSIZE, OXYGEN_BUTTONSIZE);
115 //////////////////////////////////////////////////////////////////////////////
116 // enterEvent()
117 // ------------
118 // Mouse has entered the button
120 void OxygenButton::enterEvent(QEvent *e)
122 KCommonDecorationButton::enterEvent(e);
123 if (status_ != Oxygen::Pressed) {
124 status_ = Oxygen::Hovered;
126 update();
129 //////////////////////////////////////////////////////////////////////////////
130 // leaveEvent()
131 // ------------
132 // Mouse has left the button
134 void OxygenButton::leaveEvent(QEvent *e)
136 KCommonDecorationButton::leaveEvent(e);
137 // if we wanted to do mouseovers, we would keep track of it here
138 status_ = Oxygen::Normal;
139 update();
142 //////////////////////////////////////////////////////////////////////////////
143 // mousePressEvent()
144 // ------------
145 // Mouse has pressed the button
147 void OxygenButton::mousePressEvent(QMouseEvent *e)
149 status_ = Oxygen::Pressed;
150 update();
152 KCommonDecorationButton::mousePressEvent(e);
155 //////////////////////////////////////////////////////////////////////////////
156 // mouseReleaseEvent()
157 // ------------
158 // Mouse has released the button
160 void OxygenButton::mouseReleaseEvent(QMouseEvent *e)
162 status_ = Oxygen::Normal;
163 update();
165 KCommonDecorationButton::mouseReleaseEvent(e);
168 //////////////////////////////////////////////////////////////////////////////
169 // drawButton()
170 // ------------
171 // Draw the button
173 void OxygenButton::paintEvent(QPaintEvent *)
175 QPainter painter(this);
176 QPalette pal = palette(); // de-const-ify
178 // Set palette to the right group.
179 // TODO - fix KWin to do this for us :-).
180 if (client_.isActive())
181 pal.setCurrentColorGroup(QPalette::Active);
182 else
183 pal.setCurrentColorGroup(QPalette::Inactive);
185 // fill the grey square
186 helper_.renderWindowBackground(&painter, this->rect(), this, pal, 0);
187 painter.setClipRect(this->rect());
189 // draw dividing line
190 painter.setRenderHints(QPainter::Antialiasing);
191 QRect frame = client_.widget()->rect();
192 int x = -this->geometry().x()+1;
193 int w = frame.width()-2;
195 const int titleHeight = client_.layoutMetric(KCommonDecoration::LM_TitleHeight);
197 QColor color = pal.window().color();
198 QColor light = helper_.calcLightColor( color );
199 QColor dark = helper_.calcDarkColor( color );
201 dark.setAlpha(120);
203 if (client_.isActive())
205 helper_.drawSeparator(&painter, QRect(x, titleHeight-1.5, w, 2), color, Qt::Horizontal);
208 if (type_ == ButtonMenu)
210 // we paint the mini icon (which is 16 pixels high)
211 int dx = (width() - 16) / 2;
212 int dy = (height() - 16) / 2;
213 painter.drawPixmap(dx, dy, client_.icon().pixmap(16));
214 return;
218 if(client_.maximizeMode() == OxygenClient::MaximizeRestore)
220 painter.translate(0,-1);
223 QColor bg = helper_.backgroundTopColor(pal.window().color());
225 // get icon color
226 color = buttonDetailColor(pal);
227 if (status_ == Oxygen::Hovered || status_ == Oxygen::Pressed)
229 if (type_ == ButtonClose)
231 color = KColorScheme(pal.currentColorGroup()).foreground(KColorScheme::NegativeText).color();
233 else
235 color = KColorScheme(pal.currentColorGroup()).decoration(KColorScheme::HoverColor).color();
239 // draw button
240 painter.drawPixmap(0, 0, helper_.windecoButton(pal.window().color(), status_ == Oxygen::Pressed));
242 // draw glow on hover
243 if (status_ == Oxygen::Hovered)
245 painter.drawPixmap(0, 0, helper_.windecoButtonGlow(color));
248 if (client_.isActive())
250 painter.setRenderHints(QPainter::Antialiasing);
251 painter.setBrush(Qt::NoBrush);
252 painter.setPen(QPen(color, 1.4, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
253 drawIcon(&painter, pal, type_);
255 else
257 // outlined mode
258 QPixmap pixmap(size());
259 pixmap.fill(Qt::transparent);
260 QPainter pp(&pixmap);
261 pp.setRenderHints(QPainter::Antialiasing);
262 pp.setBrush(Qt::NoBrush);
263 pp.setPen(QPen(color, 3.0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
264 drawIcon(&pp, pal, type_);
266 pp.setCompositionMode(QPainter::CompositionMode_DestinationOut);
267 pp.setPen(QPen(color, 1.0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
268 drawIcon(&pp, pal, type_);
270 painter.drawPixmap(QPoint(0,0), pixmap);
274 void OxygenButton::drawIcon(QPainter *p, QPalette &pal, ButtonType &type)
276 switch(type)
278 case ButtonSticky:
279 if(isChecked()) {
280 QPen newPen = p->pen();
281 newPen.setColor(KColorScheme(pal.currentColorGroup()).decoration(KColorScheme::HoverColor).color());
282 p->setPen(newPen);
284 p->drawPoint(QPointF(10.5,10.5));
285 break;
286 case ButtonHelp:
287 p->translate(1.5, 1.5);
288 p->drawArc(7,5,4,4,135*16, -180*16);
289 p->drawArc(9,8,4,4,135*16,45*16);
290 p->drawPoint(9,12);
291 p->translate(-1.5, -1.5);
292 break;
293 case ButtonMin:
294 p->drawLine(QPointF( 7.5, 9.5), QPointF(10.5,12.5));
295 p->drawLine(QPointF(10.5,12.5), QPointF(13.5, 9.5));
296 break;
297 case ButtonMax:
298 switch(client_.maximizeMode())
300 case OxygenClient::MaximizeRestore:
301 case OxygenClient::MaximizeVertical:
302 case OxygenClient::MaximizeHorizontal:
303 p->drawLine(QPointF( 7.5,11.5), QPointF(10.5, 8.5));
304 p->drawLine(QPointF(10.5, 8.5), QPointF(13.5,11.5));
305 break;
306 case OxygenClient::MaximizeFull:
308 p->translate(1.5, 1.5);
309 //p->setBrush(lg);
310 QPoint points[4] = {QPoint(9, 6), QPoint(12, 9), QPoint(9, 12), QPoint(6, 9)};
311 //QPoint points[4] = {QPoint(9, 5), QPoint(13, 9), QPoint(9, 13), QPoint(5, 9)};
312 p->drawPolygon(points, 4);
313 p->translate(-1.5, -1.5);
314 break;
317 break;
318 case ButtonClose:
319 p->drawLine(QPointF( 7.5,7.5), QPointF(13.5,13.5));
320 p->drawLine(QPointF(13.5,7.5), QPointF( 7.5,13.5));
321 break;
322 case ButtonAbove:
323 if(isChecked()) {
324 QPen newPen = p->pen();
325 newPen.setColor(KColorScheme(pal.currentColorGroup()).decoration(KColorScheme::HoverColor).color());
326 p->setPen(newPen);
329 p->drawLine(QPointF( 7.5,14), QPointF(10.5,11));
330 p->drawLine(QPointF(10.5,11), QPointF(13.5,14));
331 p->drawLine(QPointF( 7.5,10), QPointF(10.5, 7));
332 p->drawLine(QPointF(10.5, 7), QPointF(13.5,10));
333 break;
334 case ButtonBelow:
335 if(isChecked()) {
336 QPen newPen = p->pen();
337 newPen.setColor(KColorScheme(pal.currentColorGroup()).decoration(KColorScheme::HoverColor).color());
338 p->setPen(newPen);
341 p->drawLine(QPointF( 7.5,11), QPointF(10.5,14));
342 p->drawLine(QPointF(10.5,14), QPointF(13.5,11));
343 p->drawLine(QPointF( 7.5, 7), QPointF(10.5,10));
344 p->drawLine(QPointF(10.5,10), QPointF(13.5, 7));
345 break;
346 case ButtonShade:
347 if (!isChecked()) // shade button
349 p->drawLine(QPointF( 7.5, 7.5), QPointF(10.5,10.5));
350 p->drawLine(QPointF(10.5,10.5), QPointF(13.5, 7.5));
351 p->drawLine(QPointF( 7.5,13.0), QPointF(13.5,13.0));
352 } else { // unshade button
353 p->drawLine(QPointF( 7.5,10.5), QPointF(10.5, 7.5));
354 p->drawLine(QPointF(10.5, 7.5), QPointF(13.5,10.5));
355 p->drawLine(QPointF( 7.5,13.0), QPointF(13.5,13.0));
357 break;
358 default:
359 break;
370 } //namespace Oxygen