2 Copyright (c) 2002 Malte Starostik <malte@kde.org>
3 (c) 2002-2005 Maksim Orlovich <maksim@kde.org>
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
23 #include <QtGui/qdrawutil.h>
24 #include <QtGui/QPainter>
25 #include <QtGui/QStyleOption>
26 #include "colorutil.h"
27 #include "pixmaploader.h"
28 #include "gradients.h"
29 #include "keramikimage.h"
30 #include <QtGui/QPolygon>
32 #define loader Keramik::PixmapLoader::the()
34 static const int keramik_up_arrow
[] =
47 static const int keramik_down_arrow
[] =
61 static const int keramik_right_arrow
[] =
74 static const int keramik_left_arrow
[] =
89 #define POLY_LEN(x) sizeof(x)/(sizeof(int)*2)
93 class KeramikStyle
: public KStyle
98 //Just for the heck of it, make the focus rect's RHS nearly flush
99 setWidgetLayoutProp(WT_PushButton
, PushButton::FocusMargin
, 3);
100 setWidgetLayoutProp(WT_PushButton
, PushButton::FocusMargin
+ Right
, 2);
101 setWidgetLayoutProp(WT_PushButton
, PushButton::FocusMargin
+ Top
, 2);
102 setWidgetLayoutProp(WT_PushButton
, PushButton::FocusMargin
+ Bot
, 2);
104 setWidgetLayoutProp(WT_MenuBar
, MenuBar::ItemSpacing
, 10);
106 setWidgetLayoutProp(WT_MenuBarItem
, MenuBarItem::Margin
+ Left
, 2);
107 setWidgetLayoutProp(WT_MenuBarItem
, MenuBarItem::Margin
+ Right
, 2);
109 setWidgetLayoutProp(WT_ScrollBar
, ScrollBar::MinimumSliderHeight
,
110 loader
.size( keramik_scrollbar_vbar
+ KeramikSlider1
).height() +
111 loader
.size( keramik_scrollbar_vbar
+ KeramikSlider3
).height());
114 setWidgetLayoutProp(WT_ScrollBar
, ScrollBar::ArrowColor
,
115 ColorMode(ColorMode::BWAutoContrastMode
, QPalette::Button
));
117 setWidgetLayoutProp(WT_ScrollBar
, ScrollBar::ActiveArrowColor
,
118 ColorMode(ColorMode::BWAutoContrastMode
, QPalette::ButtonText
));
121 //setWidgetLayoutProp(WT_DockWidgetTitle, DockWidgetTitle::Margin, 8);
123 //setWidgetLayoutProp(WT_ProgressBar, ProgressBar::SideText, 1);
125 setWidgetLayoutProp(WT_ScrollBar
, ScrollBar::SingleButtonHeight
,
126 loader
.size(keramik_scrollbar_vbar_arrow1
).height());
128 setWidgetLayoutProp(WT_Slider
, Slider::HandleLength
, 12);
129 setWidgetLayoutProp(WT_Slider
, Slider::HandleThickness
, loader
.size(keramik_slider
).height());
132 void drawKStylePrimitive(WidgetType widgetType
, int primitive
,
133 const QStyleOption
* opt
,
134 const QRect
&r
, const QPalette
&pal
, State flags
,
136 const QWidget
* widget
,
137 KStyle::Option
* kOpt
) const
139 bool disabled
= !(flags
& State_Enabled
);
146 case PushButton::Panel
:
148 const QStyleOptionButton
* bOpt
= qstyleoption_cast
<const QStyleOptionButton
*>(opt
);
149 if (bOpt
&& //### helper function in KStyle?
150 (bOpt
->features
& QStyleOptionButton::DefaultButton
))
151 return; //The default indicator does the job for us.
153 bool sunken
= (flags
& State_On
) || (flags
& State_Sunken
);
154 bool disabled
= !(flags
& State_Enabled
);
159 name
= keramik_pushbutton_pressed
;
161 name
= keramik_pushbutton
;
163 if (flags
& State_MouseOver
&& name
== keramik_pushbutton
)
164 name
= keramik_pushbutton_hov
;
166 Keramik::RectTilePainter( name
, false ).draw(p
, r
, pal
.color(QPalette::Button
), pal
.background().color(), disabled
);
172 case PushButton::DefaultButtonFrame
:
174 bool sunken
= (flags
& State_On
) || (flags
& State_Sunken
);
177 if ( sunken
) id
= keramik_pushbutton_default_pressed
;
178 else id
= keramik_pushbutton_default
;
180 if (flags
& State_MouseOver
&& id
== keramik_pushbutton_default
)
181 id
= keramik_pushbutton_default_hov
;
184 Keramik::RectTilePainter( id
, false ).draw(p
, r
, pal
.color(QPalette::Button
), pal
.background().color(), !(flags
& State_Enabled
));
186 break; // TODO!! this break seems strange, have a look at it later (giessl)
198 case ProgressBar::BusyIndicator
:
199 Keramik::RowPainter(keramik_progressbar
).draw(p
, r
,
200 pal
.color(QPalette::Highlight
), pal
.background().color());
202 case ProgressBar::Indicator
:
203 Keramik::ProgressBarPainter(keramik_progressbar
, opt
->direction
== Qt::RightToLeft
).draw(p
, r
,
204 pal
.color(QPalette::Highlight
), pal
.background().color());
215 case MenuBarItem::Panel
:
217 const QStyleOptionMenuItem
* miOpt
= ::qstyleoption_cast
<const QStyleOptionMenuItem
*>(opt
);
218 bool active
= flags
& State_Selected
;
219 bool focused
= flags
& State_HasFocus
;
221 if ( active
&& focused
)
222 qDrawShadePanel(p
, r
.x(), r
.y(), r
.width(), r
.height(),
223 pal
, true, 1, &pal
.brush(QPalette::Midlight
));
225 Keramik::GradientPainter::renderGradient( p
, miOpt
->menuRect
, pal
.color(QPalette::Button
), true, true);
238 qDrawShadePanel(p
, r
, pal
);
242 case Menu::Background
:
244 p
->fillRect( r
, pal
.background().color().light( 105 ) );
250 //### hmm,may be KStyle should do a default for this.
269 case MenuBar::EmptyArea
:
271 Keramik::GradientPainter::renderGradient( p
, r
, pal
.color(QPalette::Button
), true, true);
282 case Splitter::HandleHor
:
283 case Splitter::HandleVert
:
286 r
.getRect(&x
, &y
, &w
, &h
);
290 //### should probably use color() directly to avoid creating a brush
291 p
->setPen(pal
.dark().color());
293 p
->setPen(pal
.background().color());
297 p
->drawPoint(x2
, y2
);
298 p
->setPen(pal
.color(QPalette::Light
));
299 p
->drawLine(x
+1, y
+1, x
+1, y2
-1);
300 p
->drawLine(x
+1, y
+1, x2
-1, y
+1);
301 p
->setPen(pal
.midlight().color());
302 p
->drawLine(x
+2, y
+2, x
+2, y2
-2);
303 p
->drawLine(x
+2, y
+2, x2
-2, y
+2);
304 p
->setPen(pal
.mid().color());
305 p
->drawLine(x2
-1, y
+1, x2
-1, y2
-1);
306 p
->drawLine(x
+1, y2
-1, x2
-1, y2
-1);
307 p
->fillRect(x
+3, y
+3, w
-5, h
-5, pal
.brush(QPalette::Background
));
319 case MenuItem::Separator
:
321 QRect lr
= centerRect(r
, r
.width(), 2); //Center...
322 p
->setPen( pal
.mid().color() );
323 p
->drawLine(lr
.x()+5, lr
.y(), lr
.right()-4, lr
.y());
324 p
->setPen( pal
.color(QPalette::Light
) );
325 p
->drawLine(lr
.x()+5, lr
.y() + 1, lr
.right()-4, lr
.y() + 1);
329 case MenuItem::ItemIndicator
:
331 if (flags
& State_Enabled
)
332 Keramik::RowPainter( keramik_menuitem
).draw(p
, r
, pal
.color(QPalette::Highlight
), pal
.background().color());
334 drawKStylePrimitive(WT_Generic
, Generic::FocusIndicator
, opt
, r
, pal
, flags
, p
, widget
, kOpt
);
345 case CheckBox::CheckOn
:
347 Keramik::CenteredPainter(keramik_checkbox_on
).draw(p
, r
, pal
.color(QPalette::Button
),
348 pal
.background().color(), disabled
);//, pmode() );
351 case CheckBox::CheckOff
:
353 Keramik::CenteredPainter(keramik_checkbox_off
).draw(p
, r
, pal
.color(QPalette::Button
),
354 pal
.background().color(), disabled
);//, pmode() );
357 case CheckBox::CheckTriState
:
359 Keramik::CenteredPainter(keramik_checkbox_tri
).draw(p
, r
, pal
.color(QPalette::Button
),
360 pal
.background().color(), disabled
);//, pmode() );
371 case RadioButton::RadioOn
:
373 Keramik::CenteredPainter(keramik_radiobutton_on
).draw(p
, r
, pal
.color(QPalette::Button
),
374 pal
.background().color(), disabled
);//, pmode() );
377 case RadioButton::RadioOff
:
379 Keramik::CenteredPainter(keramik_radiobutton_off
).draw(p
, r
, pal
.color(QPalette::Button
),
380 pal
.background().color(), disabled
);//, pmode() );
389 bool down
= (flags
& State_Sunken
);
392 case ScrollBar::SliderHor
:
393 case ScrollBar::SliderVert
:
395 bool horizontal
= (flags
& State_Horizontal
);
397 bool active
= (flags
& State_Sunken
);
398 int name
= KeramikSlider1
;
399 unsigned int count
= 3;
406 if ( w
> ( loader
.size( keramik_scrollbar_hbar
+KeramikSlider1
).width() +
407 loader
.size( keramik_scrollbar_hbar
+KeramikSlider4
).width() +
408 loader
.size( keramik_scrollbar_hbar
+KeramikSlider3
).width() + 2 ) )
411 else if ( h
> ( loader
.size( keramik_scrollbar_vbar
+KeramikSlider1
).height() +
412 loader
.size( keramik_scrollbar_vbar
+KeramikSlider4
).height() +
413 loader
.size( keramik_scrollbar_vbar
+KeramikSlider3
).height() + 2 ) )
416 QColor col
= pal
.color(QPalette::Highlight
);
418 //### what to do with the customScrollMode stuff?
419 //I suppose KStyle can take care of it, somehow?
420 //if (customScrollMode || !highlightScrollBar)
421 // col = pal.button();
424 Keramik::ScrollBarPainter( name
, count
, horizontal
).draw( p
, r
, col
, pal
.background().color(), false);
426 Keramik::ScrollBarPainter( name
, count
, horizontal
).draw( p
, r
, Keramik::ColorUtil::lighten(col
,110),
427 pal
.background().color(), false );
431 case ScrollBar::GrooveAreaHorLeft
:
432 case ScrollBar::GrooveAreaHorRight
:
434 Keramik::ScrollBarPainter(KeramikGroove1
, 2, true).draw(
435 p
, r
, pal
.color(QPalette::Button
), pal
.background().color(), disabled
);
438 case ScrollBar::GrooveAreaVertTop
:
439 case ScrollBar::GrooveAreaVertBottom
:
441 Keramik::ScrollBarPainter(KeramikGroove1
, 2, false).draw(
442 p
, r
, pal
.color(QPalette::Button
), pal
.background().color(), disabled
);
446 case ScrollBar::DoubleButtonHor
:
448 const DoubleButtonOption
* bOpt
= extractOption
<const DoubleButtonOption
*>(kOpt
);
450 //Draw the entire, unselected bevel.
451 Keramik::CenteredPainter
painter(keramik_scrollbar_hbar_arrow2
);
452 painter
.draw(p
, r
, pal
.color(QPalette::Button
), pal
.background().color(), !(flags
& State_Enabled
));
454 p
->setPen(pal
.buttonText().color());
455 p
->drawLine(r
.x()+r
.width()/2 - 1, r
.y() + r
.height()/2 - 3,
456 r
.x()+r
.width()/2 - 1, r
.y() + r
.height()/2 + 3);
458 //Check whether we need to draw any of the buttons
459 if (bOpt
->activeButton
!= DoubleButtonOption::None
)
461 if (bOpt
->activeButton
== DoubleButtonOption::Right
)
463 p
->setClipRect(r
.x() + r
.width()/2, r
.y(), r
.width()/2, r
.height());
464 painter
.draw(p
, r
, pal
.buttonText().color(), pal
.background().color(),
465 !(flags
& State_Enabled
));
469 p
->setClipRect(r
.x(), r
.y(), r
.width()/2, r
.height());
470 painter
.draw(p
, r
, pal
.buttonText().color(), pal
.background().color(),
471 !(flags
& State_Enabled
));
474 p
->setClipping(false);
480 case ScrollBar::DoubleButtonVert
:
482 const DoubleButtonOption
* bOpt
= extractOption
<const DoubleButtonOption
*>(kOpt
);
484 //Draw the entire, unselected bevel.
485 Keramik::CenteredPainter
painter(keramik_scrollbar_vbar_arrow2
);
486 painter
.draw(p
, r
, pal
.color(QPalette::Button
), pal
.background().color(), !(flags
& State_Enabled
));
488 p
->setPen(pal
.buttonText().color());
489 p
->drawLine(r
.x()+r
.width()/2 - 4, r
.y()+r
.height()/2,
490 r
.x()+r
.width()/2 + 2, r
.y()+r
.height()/2);
493 //Check whether any of the buttons is down
494 if (bOpt
->activeButton
!= DoubleButtonOption::None
)
496 if (bOpt
->activeButton
== DoubleButtonOption::Bottom
)
498 p
->setClipRect(r
.x(), r
.y() + r
.height()/2, r
.width(), r
.height()/2);
499 painter
.draw(p
, r
, pal
.buttonText().color(), pal
.background().color(),
500 !(flags
& State_Enabled
));
504 p
->setClipRect(r
.x(), r
.y(), r
.width(), r
.height()/2);
505 painter
.draw(p
, r
, pal
.buttonText().color(), pal
.background().color(),
506 !(flags
& State_Enabled
));
509 p
->setClipping(false);
515 case ScrollBar::SingleButtonHor
:
517 Keramik::CenteredPainter
painter(keramik_scrollbar_hbar_arrow1
);
518 painter
.draw( p
, r
, down
? pal
.buttonText().color() : pal
.color(QPalette::Button
),
519 pal
.background().color(), disabled
);
523 case ScrollBar::SingleButtonVert
:
525 Keramik::CenteredPainter
painter(keramik_scrollbar_vbar_arrow1
);
526 painter
.draw( p
, r
, down
? pal
.buttonText().color() : pal
.color(QPalette::Button
),
527 pal
.background().color(), disabled
);
532 if (primitive
>= Generic::ArrowUp
&& primitive
<= Generic::ArrowLeft
)
534 KStyle::ColorOption
* colorOpt
= extractOption
<KStyle::ColorOption
*>(kOpt
);
535 QColor arrowColor
= colorOpt
->color
.color(pal
);
540 case Generic::ArrowUp
:
541 poly
.setPoints(POLY_LEN(keramik_up_arrow
), keramik_up_arrow
);
544 case Generic::ArrowDown
:
545 poly
.setPoints(POLY_LEN(keramik_down_arrow
), keramik_down_arrow
);
548 case Generic::ArrowLeft
:
549 poly
.setPoints(POLY_LEN(keramik_left_arrow
), keramik_left_arrow
);
553 poly
.setPoints(POLY_LEN(keramik_right_arrow
), keramik_right_arrow
);
557 if ( flags
& State_Enabled
)
559 //CHECKME: Why is the -1 needed?
560 poly
.translate(r
.x() + r
.width()/2 - 1, r
.y() + r
.height()/2);
562 p
->setPen(arrowColor
);
563 p
->drawPolygon(poly
);
567 //Disabled ones ignore color parameter
568 poly
.translate(r
.x() + r
.width()/2, r
.y() + r
.height()/2 + 1);
569 p
->setPen(pal
.color(QPalette::Light
));
570 p
->drawPolygon(poly
);
572 poly
.translate(-1,-1);
573 p
->setPen(pal
.mid().color());
574 p
->drawPolygon(poly
);
584 const QStyleOptionTab
* tabOpt
= qstyleoption_cast
<const QStyleOptionTab
*>(opt
);
587 case TabBar::NorthTab
:
588 case TabBar::SouthTab
:
590 QStyleOptionTab::TabPosition pos
= tabOpt
->position
;
592 if (tabOpt
->direction
== Qt::RightToLeft
)
594 if (pos
== QStyleOptionTab::End
)
595 pos
= QStyleOptionTab::Beginning
;
596 else if (pos
== QStyleOptionTab::Beginning
)
597 pos
= QStyleOptionTab::End
;
600 if ( flags
& State_Selected
)
603 //If not the right-most tab, readjust the painting to be one pixel wider
604 //to avoid a doubled line
605 if (pos
!= QStyleOptionTab::End
)
606 tabRect
.setWidth( tabRect
.width() + 1);
608 Keramik::ActiveTabPainter(primitive
== TabBar::SouthTab
).draw(p
, tabRect
,
609 pal
.color(QPalette::Button
).light(110), pal
.background().color(),
615 r
.getRect(&x
, &y
, &w
, &h
);
616 if (primitive
== TabBar::SouthTab
)
618 Keramik::InactiveTabPainter(pos
, true).draw(
619 p
, x
, y
, w
, h
- 3, pal
.color(QPalette::Button
), pal
.background().color(),
621 p
->setPen (pal
.dark().color());
622 p
->drawLine(x
, y
, x
+ w
, y
);
626 Keramik::InactiveTabPainter(pos
, false).draw(
627 p
, x
, y
+ 3, w
, h
- 3, pal
.color(QPalette::Button
), pal
.background().color(), disabled
);
628 p
->setPen (pal
.color(QPalette::Light
));
629 p
->drawLine(x
, y
+ h
- 1, x
+ w
, y
+ h
- 1);
634 //### TODO: Handle east, west tabs
643 case Slider::GrooveVert
:
644 Keramik::RectTilePainter(keramik_slider_vgroove
, true, false).draw(
645 p
, r
, pal
.color(QPalette::Button
), pal
.background().color(), disabled
);
647 case Slider::GrooveHor
:
648 Keramik::RectTilePainter(keramik_slider_hgroove
, false).draw(
649 p
, r
, pal
.color(QPalette::Button
), pal
.background().color(), disabled
);
651 case Slider::HandleVert
:
652 case Slider::HandleHor
:
655 if (primitive
== Slider::HandleHor
)
660 QColor hl
= pal
.color(QPalette::Highlight
);
661 if (!disabled
&& flags
& State_Active
)
662 hl
= Keramik::ColorUtil::lighten(pal
.color(QPalette::Highlight
) ,110);
664 int primCode
= (primitive
== Slider::HandleVert
) ?
665 keramik_vslider
: keramik_slider
;
667 Keramik::ScaledPainter(primCode
).draw(
668 p
, lr
, disabled
? pal
.color(QPalette::Button
) : hl
, Qt::black
, disabled
, Keramik::TilePainter::PaintFullBlend
);
678 //Handle default fallbacks
680 KStyle::drawKStylePrimitive(widgetType
, primitive
, opt
,
681 r
, pal
, flags
, p
, widget
, kOpt
);
686 K_EXPORT_STYLE("Keramik", KeramikStyle
)
688 // kate: indent-width 4; replace-tabs off; tab-width 4; space-indent off;