1 //////////////////////////////////////////////////////////////////////////////
4 // Oxygen window decoration for KDE. Buttons.
6 // Copyright (c) 2006, 2007 Riccardo Iaconelli <riccardo@kde.org>
7 // Copyright (c) 2006, 2007 Casper Boemann <cbr@boemann.dk>
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
26 //////////////////////////////////////////////////////////////////////////////
28 #include "oxygenbutton.h"
29 #include <kcommondecoration.h>
32 #include <QPainterPath>
37 #include <kdecoration.h>
39 #include <KColorUtils>
41 #include <KColorScheme>
43 #include "oxygenclient.h"
48 // class OxygenClient;
50 extern int BUTTONSIZE;
51 extern int DECOSIZE;*/
53 // static const int DECOSIZE = 8;
54 //////////////////////////////////////////////////////////////////////////////
55 // OxygenButton Class //
56 //////////////////////////////////////////////////////////////////////////////
58 //////////////////////////////////////////////////////////////////////////////
63 OxygenButton::OxygenButton(OxygenClient
&parent
,
64 const QString
& tip
, ButtonType type
)
65 : KCommonDecorationButton((::ButtonType
)type
, &parent
)
67 , helper_(parent
.helper_
)
70 , colorCacheInvalid_(true)
72 setAutoFillBackground(false);
73 setAttribute(Qt::WA_OpaquePaintEvent
, false);
74 setFixedSize(OXYGEN_BUTTONSIZE
, OXYGEN_BUTTONSIZE
);
75 setCursor(Qt::ArrowCursor
);
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
);
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 //////////////////////////////////////////////////////////////////////////////
110 QSize
OxygenButton::sizeHint() const
112 return QSize(OXYGEN_BUTTONSIZE
, OXYGEN_BUTTONSIZE
);
115 //////////////////////////////////////////////////////////////////////////////
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
;
129 //////////////////////////////////////////////////////////////////////////////
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
;
142 //////////////////////////////////////////////////////////////////////////////
145 // Mouse has pressed the button
147 void OxygenButton::mousePressEvent(QMouseEvent
*e
)
149 status_
= Oxygen::Pressed
;
152 KCommonDecorationButton::mousePressEvent(e
);
155 //////////////////////////////////////////////////////////////////////////////
156 // mouseReleaseEvent()
158 // Mouse has released the button
160 void OxygenButton::mouseReleaseEvent(QMouseEvent
*e
)
162 status_
= Oxygen::Normal
;
165 KCommonDecorationButton::mouseReleaseEvent(e
);
168 //////////////////////////////////////////////////////////////////////////////
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
);
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
);
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));
218 if(client_
.maximizeMode() == OxygenClient::MaximizeRestore
)
220 painter
.translate(0,-1);
223 QColor bg
= helper_
.backgroundTopColor(pal
.window().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();
235 color
= KColorScheme(pal
.currentColorGroup()).decoration(KColorScheme::HoverColor
).color();
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_
);
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
)
280 QPen newPen
= p
->pen();
281 newPen
.setColor(KColorScheme(pal
.currentColorGroup()).decoration(KColorScheme::HoverColor
).color());
284 p
->drawPoint(QPointF(10.5,10.5));
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);
291 p
->translate(-1.5, -1.5);
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));
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));
306 case OxygenClient::MaximizeFull
:
308 p
->translate(1.5, 1.5);
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);
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));
324 QPen newPen
= p
->pen();
325 newPen
.setColor(KColorScheme(pal
.currentColorGroup()).decoration(KColorScheme::HoverColor
).color());
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));
336 QPen newPen
= p
->pen();
337 newPen
.setColor(KColorScheme(pal
.currentColorGroup()).decoration(KColorScheme::HoverColor
).color());
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));
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));