Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / runtime / kstyles / keramik / keramik.cpp
blobb87ef58bc939be82ee79e31051f469144bb668cd
1 /* Keramik Style
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.
22 #include "kstyle.h"
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[] =
36 0, -4, 0, -4,
37 -1, -3, 1, -3,
38 -2, -2, 2, -2,
39 -3, -1, 3, -1,
40 -4, 0, 4, 0,
41 -2, 1, 2, 1,
42 -2, 2, 2, 2,
43 -2, 3, 2, 3,
44 -2, 4, 2, 4
47 static const int keramik_down_arrow[] =
49 0, 4, 0, 4,
50 -1, 3, 1, 3,
51 -2, 2, 2, 2,
52 -3, 1, 3, 1,
53 -4, 0, 4, 0,
54 -2, -1, 2, -1,
55 -2, -2, 2, -2,
56 -2, -3, 2, -3,
57 -2, -4, 2, -4
61 static const int keramik_right_arrow[] =
63 4, 0, 4, 0,
64 3, -1, 3, 1,
65 2, -2, 2, 2,
66 1, -3, 1, 3,
67 0, -4, 0, 4,
68 -1, -2, -1, 2,
69 -2, -2, -2, 2,
70 -3, -2, -3, 2,
71 -4, -2, -4, 2
74 static const int keramik_left_arrow[] =
76 -4, 0, -4, 0,
77 -3, -1, -3, 1,
78 -2, -2, -2, 2,
79 -1, -3, -1, 3,
80 0, -4, 0, 4,
81 1, -2, 1, 2,
82 2, -2, 2, 2,
83 3, -2, 3, 2,
84 4, -2, 4, 2
89 #define POLY_LEN(x) sizeof(x)/(sizeof(int)*2)
93 class KeramikStyle: public KStyle
95 public:
96 KeramikStyle()
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));
120 //### HACK,for now.
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,
135 QPainter* p,
136 const QWidget* widget,
137 KStyle::Option* kOpt) const
139 bool disabled = !(flags & State_Enabled);
140 switch (widgetType)
142 case WT_PushButton:
144 switch (primitive)
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);
156 int name;
158 if (sunken)
159 name = keramik_pushbutton_pressed;
160 else
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);
167 //, pmode() );
169 return;
172 case PushButton::DefaultButtonFrame:
174 bool sunken = (flags & State_On) || (flags & State_Sunken);
176 int id;
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));
185 //, pmode() );
186 break; // TODO!! this break seems strange, have a look at it later (giessl)
188 return;
192 break;
194 case WT_ProgressBar:
196 switch (primitive)
198 case ProgressBar::BusyIndicator:
199 Keramik::RowPainter(keramik_progressbar).draw(p, r,
200 pal.color(QPalette::Highlight), pal.background().color());
201 return;
202 case ProgressBar::Indicator:
203 Keramik::ProgressBarPainter(keramik_progressbar, opt->direction == Qt::RightToLeft).draw(p, r,
204 pal.color(QPalette::Highlight), pal.background().color());
205 return;
208 break;
211 case WT_MenuBarItem:
213 switch (primitive)
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));
224 else
225 Keramik::GradientPainter::renderGradient( p, miOpt->menuRect, pal.color(QPalette::Button), true, true);
226 return;
230 break;
232 case WT_Menu:
234 switch (primitive)
236 case Generic::Frame:
238 qDrawShadePanel(p, r, pal);
239 return;
242 case Menu::Background:
244 p->fillRect( r, pal.background().color().light( 105 ) );
245 return;
248 case Menu::TearOff:
250 //### hmm,may be KStyle should do a default for this.
251 //### FIXME
252 return;
255 case Menu::Scroller:
257 //TODO:scrollr
259 return;
263 break;
265 case WT_MenuBar:
267 switch (primitive)
269 case MenuBar::EmptyArea:
271 Keramik::GradientPainter::renderGradient( p, r, pal.color(QPalette::Button), true, true);
272 return;
276 break;
278 case WT_Splitter:
280 switch (primitive)
282 case Splitter::HandleHor:
283 case Splitter::HandleVert:
285 int x,y,w,h;
286 r.getRect(&x, &y, &w, &h);
287 int x2 = x+w-1;
288 int y2 = y+h-1;
290 //### should probably use color() directly to avoid creating a brush
291 p->setPen(pal.dark().color());
292 p->drawRect( r );
293 p->setPen(pal.background().color());
294 p->drawPoint(x, y);
295 p->drawPoint(x2, y);
296 p->drawPoint(x, y2);
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));
309 return;
313 break;
315 case WT_MenuItem:
317 switch (primitive)
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);
326 return;
329 case MenuItem::ItemIndicator:
331 if (flags & State_Enabled)
332 Keramik::RowPainter( keramik_menuitem ).draw(p, r, pal.color(QPalette::Highlight), pal.background().color());
333 else
334 drawKStylePrimitive(WT_Generic, Generic::FocusIndicator, opt, r, pal, flags, p, widget, kOpt);
335 return;
339 break;
341 case WT_CheckBox:
343 switch(primitive)
345 case CheckBox::CheckOn:
347 Keramik::CenteredPainter(keramik_checkbox_on).draw(p, r, pal.color(QPalette::Button),
348 pal.background().color(), disabled);//, pmode() );
349 return;
351 case CheckBox::CheckOff:
353 Keramik::CenteredPainter(keramik_checkbox_off).draw(p, r, pal.color(QPalette::Button),
354 pal.background().color(), disabled);//, pmode() );
355 return;
357 case CheckBox::CheckTriState:
359 Keramik::CenteredPainter(keramik_checkbox_tri).draw(p, r, pal.color(QPalette::Button),
360 pal.background().color(), disabled);//, pmode() );
361 return;
365 break;
367 case WT_RadioButton:
369 switch(primitive)
371 case RadioButton::RadioOn:
373 Keramik::CenteredPainter(keramik_radiobutton_on).draw(p, r, pal.color(QPalette::Button),
374 pal.background().color(), disabled);//, pmode() );
375 return;
377 case RadioButton::RadioOff:
379 Keramik::CenteredPainter(keramik_radiobutton_off).draw(p, r, pal.color(QPalette::Button),
380 pal.background().color(), disabled);//, pmode() );
381 return;
385 break;
387 case WT_ScrollBar:
389 bool down = (flags & State_Sunken);
390 switch (primitive)
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;
401 int w = r.width();
402 int h = r.height();
404 if ( horizontal )
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 ) )
409 count = 5;
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 ) )
414 count = 5;
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();
423 if (!active)
424 Keramik::ScrollBarPainter( name, count, horizontal ).draw( p, r, col, pal.background().color(), false);
425 else
426 Keramik::ScrollBarPainter( name, count, horizontal ).draw( p, r, Keramik::ColorUtil::lighten(col ,110),
427 pal.background().color(), false );
429 return;
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);
436 return;
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);
443 return;
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));
467 else
468 { //Left
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);
477 return;
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)
497 { //down
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));
502 else
503 { //up.
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);
512 return;
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);
520 return;
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);
528 return;
532 if (primitive >= Generic::ArrowUp && primitive <= Generic::ArrowLeft)
534 KStyle::ColorOption* colorOpt = extractOption<KStyle::ColorOption*>(kOpt);
535 QColor arrowColor = colorOpt->color.color(pal);
537 QPolygon poly;
538 switch (primitive)
540 case Generic::ArrowUp:
541 poly.setPoints(POLY_LEN(keramik_up_arrow), keramik_up_arrow);
542 break;
544 case Generic::ArrowDown:
545 poly.setPoints(POLY_LEN(keramik_down_arrow), keramik_down_arrow);
546 break;
548 case Generic::ArrowLeft:
549 poly.setPoints(POLY_LEN(keramik_left_arrow), keramik_left_arrow);
550 break;
552 default:
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);
565 else
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);
577 return;
582 case WT_TabBar:
584 const QStyleOptionTab* tabOpt = qstyleoption_cast<const QStyleOptionTab*>(opt);
585 switch (primitive)
587 case TabBar::NorthTab:
588 case TabBar::SouthTab:
590 QStyleOptionTab::TabPosition pos = tabOpt->position;
591 //Adjust for RTL
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 )
602 QRect tabRect = r;
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(),
610 disabled);
612 else
614 int x, y, w, h;
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(),
620 disabled);
621 p->setPen (pal.dark().color());
622 p->drawLine(x, y, x + w, y);
624 else
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);
633 return;
634 //### TODO: Handle east, west tabs
636 } //WT_Tab
637 break;
639 case WT_Slider:
641 switch (primitive)
643 case Slider::GrooveVert:
644 Keramik::RectTilePainter(keramik_slider_vgroove, true, false).draw(
645 p, r, pal.color(QPalette::Button), pal.background().color(), disabled);
646 return;
647 case Slider::GrooveHor:
648 Keramik::RectTilePainter(keramik_slider_hgroove, false).draw(
649 p, r, pal.color(QPalette::Button), pal.background().color(), disabled);
650 return;
651 case Slider::HandleVert:
652 case Slider::HandleHor:
654 QRect lr = r;
655 if (primitive == Slider::HandleHor)
656 lr.setY(lr.y() + 2);
657 else
658 lr.setX(lr.x() + 2);
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);
669 return;
672 } //WT_Slider
674 default:
675 break;
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;