1 //////////////////////////////////////////////////////////////////////////////
4 // Ozone 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"
50 // class OxygenClient;
52 extern int BUTTONSIZE;
53 extern int DECOSIZE;*/
55 // static const int DECOSIZE = 8;
56 //////////////////////////////////////////////////////////////////////////////
57 // OxygenButton Class //
58 //////////////////////////////////////////////////////////////////////////////
60 //////////////////////////////////////////////////////////////////////////////
65 OxygenButton::OxygenButton(OxygenClient
&parent
,
66 const QString
& tip
, ButtonType type
)
67 : KCommonDecorationButton((::ButtonType
)type
, &parent
)
69 , helper_(parent
.helper_
)
72 , colorCacheInvalid_(true)
74 setAutoFillBackground(false);
75 setAttribute(Qt::WA_OpaquePaintEvent
, false);
76 setFixedSize(OXYGEN_BUTTONSIZE
, OXYGEN_BUTTONSIZE
);
77 setCursor(Qt::ArrowCursor
);
81 OxygenButton::~OxygenButton()
85 //declare function from oxygenclient.cpp
86 QColor
reduceContrast(const QColor
&c0
, const QColor
&c1
, double t
);
89 QColor
OxygenButton::buttonDetailColor(const QPalette
&palette
)
91 if (client_
.isActive())
92 return palette
.color(QPalette::Active
, QPalette::ButtonText
);
94 if (colorCacheInvalid_
) {
95 QColor ab
= palette
.color(QPalette::Active
, QPalette::Button
);
96 QColor af
= palette
.color(QPalette::Active
, QPalette::ButtonText
);
97 QColor nb
= palette
.color(QPalette::Inactive
, QPalette::Button
);
98 QColor nf
= palette
.color(QPalette::Inactive
, QPalette::ButtonText
);
100 colorCacheInvalid_
= false;
101 cachedButtonDetailColor_
= reduceContrast(nb
, nf
, qMax(qreal(2.5), KColorUtils::contrastRatio(ab
, KColorUtils::mix(ab
, af
, 0.4))));
103 return cachedButtonDetailColor_
;
107 //////////////////////////////////////////////////////////////////////////////
112 QSize
OxygenButton::sizeHint() const
114 return QSize(OXYGEN_BUTTONSIZE
, OXYGEN_BUTTONSIZE
);
117 //////////////////////////////////////////////////////////////////////////////
120 // Mouse has entered the button
122 void OxygenButton::enterEvent(QEvent
*e
)
124 KCommonDecorationButton::enterEvent(e
);
125 if (status_
!= Oxygen::Pressed
) {
126 status_
= Oxygen::Hovered
;
131 //////////////////////////////////////////////////////////////////////////////
134 // Mouse has left the button
136 void OxygenButton::leaveEvent(QEvent
*e
)
138 KCommonDecorationButton::leaveEvent(e
);
139 // if we wanted to do mouseovers, we would keep track of it here
140 status_
= Oxygen::Normal
;
144 //////////////////////////////////////////////////////////////////////////////
147 // Mouse has pressed the button
149 void OxygenButton::mousePressEvent(QMouseEvent
*e
)
151 status_
= Oxygen::Pressed
;
154 KCommonDecorationButton::mousePressEvent(e
);
157 //////////////////////////////////////////////////////////////////////////////
158 // mouseReleaseEvent()
160 // Mouse has released the button
162 void OxygenButton::mouseReleaseEvent(QMouseEvent
*e
)
164 status_
= Oxygen::Normal
;
167 KCommonDecorationButton::mouseReleaseEvent(e
);
170 //////////////////////////////////////////////////////////////////////////////
175 void OxygenButton::paintEvent(QPaintEvent
*)
177 QPainter
painter(this);
178 QPalette pal
= palette(); // de-const-ify
180 // Set palette to the right group.
181 // TODO - fix KWin to do this for us :-).
182 if (client_
.isActive())
183 pal
.setCurrentColorGroup(QPalette::Active
);
185 pal
.setCurrentColorGroup(QPalette::Inactive
);
187 QPalette
pal2( pal
);
188 if( !OxygenFactory::blendTitlebarColors()) {
189 pal2
.setColor( window()->backgroundRole(), client_
.options()->color(
190 KDecorationDefines::ColorTitleBar
, client_
.isActive()));
192 // fill the grey square
193 helper_
.renderWindowBackground(&painter
, this->rect(), this, pal2
, 0);
194 painter
.setClipRect(this->rect());
196 // draw dividing line
197 painter
.setRenderHints(QPainter::Antialiasing
);
198 QRect frame
= client_
.widget()->rect();
199 int x
= -this->geometry().x()+1;
200 int w
= frame
.width()-2;
202 const int titleHeight
= client_
.layoutMetric(KCommonDecoration::LM_TitleHeight
);
204 QColor color
= OxygenFactory::blendTitlebarColors()?pal
.window().color()
205 :client_
.options()->color( KDecorationDefines::ColorTitleBar
, client_
.isActive());
206 QColor light
= helper_
.calcLightColor( color
);
207 QColor dark
= helper_
.calcDarkColor( color
);
211 if(client_
.isActive()) {
212 helper_
.drawSeparator(&painter
, QRect(x
, titleHeight
-1.5, w
, 2), color
, Qt::Horizontal
);
215 if (type_
== ButtonMenu
) {
216 // we paint the mini icon (which is 16 pixels high)
217 int dx
= (width() - 16) / 2;
218 int dy
= (height() - 16) / 2;
219 painter
.drawPixmap(dx
, dy
, client_
.icon().pixmap(16));
224 if(client_
.maximizeMode() == OxygenClient::MaximizeRestore
)
225 painter
.translate(0,-1);
227 QColor bg
= helper_
.backgroundTopColor(OxygenFactory::blendTitlebarColors()?pal
.window().color()
228 :client_
.options()->color(KDecorationDefines::ColorTitleBar
,client_
.isActive()));
230 color
= buttonDetailColor(pal
);
231 if(status_
== Oxygen::Hovered
|| status_
== Oxygen::Pressed
) {
232 if(type_
== ButtonClose
)
233 color
= KColorScheme(pal
.currentColorGroup()).foreground(KColorScheme::NegativeText
).color();
235 color
= KColorScheme(pal
.currentColorGroup()).decoration(KColorScheme::HoverColor
).color();
238 QLinearGradient lg
= helper_
.decoGradient(QRect(4,4,13,13), color
);
239 QColor bt
= OxygenFactory::blendTitlebarColors()?pal
.window().color()
240 :client_
.options()->color(KDecorationDefines::ColorButtonBg
,client_
.isActive());
241 painter
.drawPixmap(0, 0, helper_
.windecoButton(bt
, status_
== Oxygen::Pressed
));
243 if (client_
.isActive()) {
244 painter
.setRenderHints(QPainter::Antialiasing
);
245 painter
.setBrush(Qt::NoBrush
);
246 painter
.setPen(QPen(lg
, 2.2, Qt::SolidLine
, Qt::RoundCap
, Qt::RoundJoin
));
247 drawIcon(&painter
, pal
, type_
);
251 QPixmap
pixmap(size());
252 pixmap
.fill(Qt::transparent
);
253 QPainter
pp(&pixmap
);
254 pp
.setRenderHints(QPainter::Antialiasing
);
255 pp
.setBrush(Qt::NoBrush
);
256 pp
.setPen(QPen(color
, 3.0, Qt::SolidLine
, Qt::RoundCap
, Qt::RoundJoin
));
257 drawIcon(&pp
, pal
, type_
);
259 pp
.setCompositionMode(QPainter::CompositionMode_DestinationOut
);
260 pp
.setPen(QPen(color
, 1.0, Qt::SolidLine
, Qt::RoundCap
, Qt::RoundJoin
));
261 drawIcon(&pp
, pal
, type_
);
263 painter
.drawPixmap(QPoint(0,0), pixmap
);
267 void OxygenButton::drawIcon(QPainter
*p
, QPalette
&pal
, ButtonType
&type
)
273 QPen newPen
= p
->pen();
274 newPen
.setColor(KColorScheme(pal
.currentColorGroup()).decoration(KColorScheme::HoverColor
).color());
277 p
->drawPoint(QPointF(10.5,10.5));
280 p
->translate(1.5, 1.5);
281 p
->drawArc(7,5,4,4,135*16, -180*16);
282 p
->drawArc(9,8,4,4,135*16,45*16);
284 p
->translate(-1.5, -1.5);
287 p
->drawLine(QPointF( 7.5, 9.5), QPointF(10.5,12.5));
288 p
->drawLine(QPointF(10.5,12.5), QPointF(13.5, 9.5));
291 switch(client_
.maximizeMode())
293 case OxygenClient::MaximizeRestore
:
294 case OxygenClient::MaximizeVertical
:
295 case OxygenClient::MaximizeHorizontal
:
296 p
->drawLine(QPointF( 7.5,11.5), QPointF(10.5, 8.5));
297 p
->drawLine(QPointF(10.5, 8.5), QPointF(13.5,11.5));
299 case OxygenClient::MaximizeFull
:
301 p
->translate(1.5, 1.5);
303 QPoint points
[4] = {QPoint(9, 6), QPoint(12, 9), QPoint(9, 12), QPoint(6, 9)};
304 //QPoint points[4] = {QPoint(9, 5), QPoint(13, 9), QPoint(9, 13), QPoint(5, 9)};
305 p
->drawPolygon(points
, 4);
306 p
->translate(-1.5, -1.5);
312 p
->drawLine(QPointF( 7.5,7.5), QPointF(13.5,13.5));
313 p
->drawLine(QPointF(13.5,7.5), QPointF( 7.5,13.5));
317 QPen newPen
= p
->pen();
318 newPen
.setColor(KColorScheme(pal
.currentColorGroup()).decoration(KColorScheme::HoverColor
).color());
322 p
->drawLine(QPointF( 7.5,14), QPointF(10.5,11));
323 p
->drawLine(QPointF(10.5,11), QPointF(13.5,14));
324 p
->drawLine(QPointF( 7.5,10), QPointF(10.5, 7));
325 p
->drawLine(QPointF(10.5, 7), QPointF(13.5,10));
329 QPen newPen
= p
->pen();
330 newPen
.setColor(KColorScheme(pal
.currentColorGroup()).decoration(KColorScheme::HoverColor
).color());
334 p
->drawLine(QPointF( 7.5,11), QPointF(10.5,14));
335 p
->drawLine(QPointF(10.5,14), QPointF(13.5,11));
336 p
->drawLine(QPointF( 7.5, 7), QPointF(10.5,10));
337 p
->drawLine(QPointF(10.5,10), QPointF(13.5, 7));
340 if (!isChecked()) // shade button
342 p
->drawLine(QPointF( 7.5, 7.5), QPointF(10.5,10.5));
343 p
->drawLine(QPointF(10.5,10.5), QPointF(13.5, 7.5));
344 p
->drawLine(QPointF( 7.5,13.0), QPointF(13.5,13.0));
345 } else { // unshade button
346 p
->drawLine(QPointF( 7.5,10.5), QPointF(10.5, 7.5));
347 p
->drawLine(QPointF(10.5, 7.5), QPointF(13.5,10.5));
348 p
->drawLine(QPointF( 7.5,13.0), QPointF(13.5,13.0));