/*
 *	KDE3 dotNET Style (version 0.2)
 *	Copyright (C) 2001-2002, Chris Lee <lee@azsites.com>
 *	                         Carsten Pfeiffer <pfeiffer@kde.org>
 *                           Karol Szwed <gallium@kde.org>
 *
 *	Drawing routines completely reimplemented from KDE3 HighColor, which was
 *	originally based on some stuff from the KDE2 HighColor.
 *
 *	This library is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU Library General Public
 *	License version 2 as published by the Free Software Foundation.
 *
 *	This library is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *	Library General Public License for more details.
 *
 *	You should have received a copy of the GNU Library General Public License
 *	along with this library; see the file COPYING.LIB.  If not, write to
 *	the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 *	Boston, MA 02111-1307, USA.
 */
#include <qstyleplugin.h>
#include <qstylefactory.h>
#include <qwindowsstyle.h>
#include <qpointarray.h>
#include <qpainter.h>
#include <qtabbar.h>
#include <qcombobox.h>
#include <qscrollbar.h>
#include <qpushbutton.h>
#include <qtoolbutton.h>
#include <qtoolbar.h>
#include <qmenubar.h>
#include <qpopupmenu.h>
#include <qdrawutil.h>
#include <qapplication.h>
#include <qvariant.h>
#include <qpixmapcache.h>
#include <qslider.h>
#include <kpixmap.h>

#include "dotnet.h"
#include "dotnet.moc"

// -- Style Plugin Interface -------------------------
class dotNETstylePlugin : public QStylePlugin
{
	public:
		dotNETstylePlugin() {}
		~dotNETstylePlugin() {}

		QStringList keys() const
		{
			return QStringList() << "dotNET";
		}

		QStyle* create( const QString& key )
		{
			if ( key == "dotnet" )
				return new dotNETstyle;
			return 0;
		}
};

Q_EXPORT_PLUGIN( dotNETstylePlugin )

// ---------------------------------------------------

dotNETstyle::dotNETstyle() : KStyle( AllowMenuTransparency )
{
	winstyle = QStyleFactory::create("Windows");
	if(!winstyle) {
		// We don't have the Windows style, neither builtin nor as a plugin.
		// Use any style rather than crashing.
		winstyle = QStyleFactory::create(*(QStyleFactory::keys().begin()));
	}

	if (qApp->inherits("KApplication"))
		connect( qApp, SIGNAL( kdisplayPaletteChanged() ), SLOT( paletteChanged() ));
}


dotNETstyle::~dotNETstyle()
{
}


void dotNETstyle::polish(QWidget* widget)
{
	if (widget->isTopLevel())
		return;

// we can't simply set a palette -- upon color-theme changes, we have
// to update the palette again.
	bool extraPalette = false;

	if (widget->inherits("QComboBox")) {
		widget->installEventFilter (this);
		updatePalette( (QComboBox*) widget );
		extraPalette = true;
	} else {
		winstyle->polish(widget);
	}

	if (!widget->ownPalette()) {
		if ( widget->inherits("QToolBar")) {
			updatePalette( (QToolBar*) widget );
			extraPalette = true;
		} else if (widget->inherits("QMenuBar")) {
			updatePalette( (QMenuBar*) widget );
			extraPalette = true;
		}
	}
}

void dotNETstyle::unPolish(QWidget* widget)
{
	winstyle->unPolish(widget);

	if (widget->inherits("QComboBox")) {
		widget->removeEventFilter (this);
	}
}

void dotNETstyle::renderMenuBlendPixmap( KPixmap &pix, const QColorGroup &cg, const QPopupMenu *popup ) const
{
	QPainter p( &pix );
	if (QApplication::reverseLayout()) {
		p.fillRect( popup->frameRect().width()-22, 0, 22, pix.height(), cg.mid() );
		p.fillRect( 0, 0, popup->frameRect().width()-22, pix.height(), cg.background().light() );
	} else {
		p.fillRect( 0, 0, pix.width(), pix.height(), cg.background().light() );
		p.fillRect( popup->frameRect().left() + 1, 0, 22, pix.height(), cg.mid() );
	}
}

void dotNETstyle::renderButton(QPainter *p,
                               const QRect &r,
                               const QColorGroup &g,
                               bool sunken) const
{
	p->save();
	if (sunken) {
		p->setPen(g.highlight().dark());
		p->setBrush(g.highlight());
		p->drawRect(r);
	} else {
		int x, y, w, h;
	//	Quick way to set x,y and w,h
		r.rect(&x, &y, &w, &h);

		p->setPen(g.background().dark());
		p->setBrush(g.background());
		p->drawRect(r);
		p->setPen(g.background().light());
		p->drawLine(x, y + h - 1, x, y);
		p->drawLine(x, y, x + w - 1, y);
	}
	p->restore();
}


void dotNETstyle::renderPanel(QPainter *p,
                              const QRect &r,
                              const QColorGroup &g,
                              bool sunken) const
{
	int x, y, w, h;
	r.rect(&x,&y,&w,&h);

	p->save();
	if (sunken) {
		p->setPen(g.background().light());
		p->drawRect(x, y, w, h);
		p->setPen(g.background().dark());
		p->drawLine(x, y, x + w, y);
		p->drawLine(x, y, x, y + h);
	} else {
		p->setPen(g.background().light());
		p->drawRect(x, y, w, h);
		p->setPen(g.background().dark());
		p->drawLine(x + w - 1, y + h - 1, x + w - 1, y);
		p->drawLine(x + w - 1, y + h - 1, x, y + h - 1);
	}
	p->restore();
}


void dotNETstyle::drawKStylePrimitive( KStylePrimitive kpe,
		QPainter* p,
		const QWidget* widget,
		const QRect &r,
		const QColorGroup &cg,
		SFlags flags,
		const QStyleOption& opt ) const
{
	// SLIDER
	// ------
	switch( kpe ) {
		case KPE_SliderGroove: {
			const QSlider* slider = (const QSlider*)widget;
			int x, y, w, h;
			r.rect(&x, &y, &w, &h);
			bool horizontal = slider->orientation() == Horizontal;
			int gcenter = (horizontal ? h : w) / 2;

			if (horizontal) {
				gcenter += y;
				p->setPen (cg.background().dark());
				p->drawLine(x, gcenter, x+w, gcenter);
				gcenter++;
				p->setPen (cg.background().light());
				p->drawLine(x, gcenter, x + w, gcenter);
			} else {
				gcenter += x;
				p->setPen (cg.background().dark());
				p->drawLine(gcenter, y, gcenter, y + h);
				gcenter++;
				p->setPen (cg.background().light());
				p->drawLine(gcenter, y, gcenter, y + h);
			}
			break;
		}

		case KPE_SliderHandle: {
			renderButton(p, r, cg);
			break;
		}

		default:
			KStyle::drawKStylePrimitive(kpe, p, widget, r, cg, flags, opt);
	}
}


// This function draws primitive elements as well as their masks.
void dotNETstyle::drawPrimitive(PrimitiveElement pe,
                                QPainter *p,
                                const QRect &r,
                                const QColorGroup &cg,
                                SFlags flags,
                                const QStyleOption &opt ) const
{
	bool down   = flags & Style_Down;
	bool on     = flags & Style_On;
	bool sunken = flags & Style_Sunken;
	bool horiz  = flags & Style_Horizontal;

	int x, y, w, h;
	r.rect(&x, &y, &w, &h);

	switch(pe) {

	//	BUTTONS
	//	-------
		case PE_ButtonBevel:
		case PE_ButtonTool:
		case PE_ButtonDropDown:
		case PE_HeaderSection:
		case PE_ScrollBarSlider:
		case PE_ButtonCommand: {

			if (on || down) {
				renderButton(p, r, cg, true);
				p->setPen( cg.highlightedText() );
			} else {
				renderButton(p, r, cg, false);
			}

			break;
		}

		case PE_ScrollBarAddPage:
		case PE_ScrollBarSubPage: {
			if (on || down) {
				p->fillRect(r, QBrush(cg.mid().dark()));
			} else {
				p->fillRect(r, QBrush(cg.background()));
			}
			p->fillRect(r, QBrush(cg.background().light(), Dense4Pattern));
			break;
		}

	//	SCROLLBAR BUTTONS
	//	-----------------
		case PE_ScrollBarSubLine: {
			drawPrimitive(PE_ButtonBevel, p, r, cg, flags);
			drawPrimitive((horiz ? PE_ArrowLeft : PE_ArrowUp),
			              p, r, cg, flags);
			break;
		}

		case PE_ScrollBarAddLine: {
			drawPrimitive(PE_ButtonBevel, p, r, cg, flags);
			drawPrimitive((horiz ? PE_ArrowRight : PE_ArrowDown),
			              p, r, cg, flags);
			break;
		}

	//	GENERAL PANELS
	//	--------------
		case PE_Splitter:
		case PE_Panel: {
			renderPanel(p, r, cg, sunken);
			break;
		}

		case PE_PanelPopup: {
			p->setPen(cg.shadow());
			p->drawRect(r);
			break;
		}

		case PE_TabBarBase:
		case PE_PanelTabWidget: {
			renderPanel(p, r, cg, false);
			break;
		}

	//	MENU / TOOLBAR PANEL
	//	--------------------
		case PE_PanelMenuBar: 			// Menu
		case PE_PanelDockWindow: {		// Toolbar
			p->save();
			p->setPen(cg.background());
			p->setBrush(cg.background());
			p->drawRect(r);
			p->restore();
			break;
		}

	//	TOOLBAR/DOCK WINDOW HANDLE
	//	--------------------------
		case PE_DockWindowResizeHandle: {
			renderButton(p, r, cg);
			break;
		}

		case PE_DockWindowHandle: {

			int k;

			p->save();
			p->setBrush(cg.background());
			p->setPen(NoPen);
			p->drawRect(x, y, w, h);
			p->setBrush(cg.mid());

			if (horiz) {
				for (k = 4; k < h - 4; k += 3) {
					p->drawRect(x + 3, k, w - 6, 1);
				}
			} else {
				for (k = 4; k < w - 4; k += 3) {
					p->drawRect(k, y + 3, 1, h - 6);
				}
			}

			p->restore();

			break;
		}

	//	TOOLBAR SEPARATOR
	//	-----------------
		case PE_DockWindowSeparator: {
			break;
		}

		case PE_ArrowUp:
		case PE_ArrowDown:
		case PE_ArrowLeft:
		case PE_ArrowRight: {
			QPointArray a;

			switch (pe) {
				case PE_ArrowUp: {
					a.setPoints(7, u_arrow);
					break;
				}
				case PE_ArrowDown: {
					a.setPoints(7, d_arrow);
					break;
				}
				case PE_ArrowLeft: {
					a.setPoints(7, l_arrow);
					break;
				}
				case PE_ArrowRight: {
					a.setPoints(7, r_arrow);
					break;
				}
			}

			p->save();

			if (flags & Style_Down) {
				p->translate(pixelMetric(PM_ButtonShiftHorizontal),
				             pixelMetric(PM_ButtonShiftVertical));
			}

			if (flags & Style_Enabled) {
				a.translate((r.x() + r.width()/2), (r.y() + r.height()/2));
				if (p->pen() == QPen::NoPen) {
					p->setPen(cg.buttonText());
				}
				p->drawLineSegments(a, 0, 3);
				p->drawPoint(a[6]);
			} else {
				a.translate((r.x() + r.width()/2)+1, (r.y() + r.height()/2)+1);
				if (p->pen() == QPen::NoPen) {
					p->setPen(cg.highlightedText());
				}
				p->drawLineSegments(a, 0, 3);
				p->drawPoint(a[6]);

				a.translate(-1,-1);
				if (p->pen() == QPen::NoPen) {
					p->setPen(cg.mid());
				}
				p->drawLineSegments(a, 0, 3);
				p->drawPoint(a[6]);
			}

			p->restore();
			break;
		}

		default: {
			return winstyle->drawPrimitive(pe, p, r, cg, flags, opt);
		}
	}
}


void dotNETstyle::drawControl(ControlElement element,
                              QPainter *p,
                              const QWidget *widget,
                              const QRect &r,
                              const QColorGroup &cg,
                              SFlags flags,
                              const QStyleOption& opt) const
{
	switch (element)
	{
	//	TABS
	//	----
		case CE_TabBarTab: {
			const QTabBar * tb = (const QTabBar *) widget;
			QTabBar::Shape tbs = tb->shape();
			bool selected = flags & Style_Selected;
			int x, y, w, h;
			r.rect(&x, &y, &w, &h);

			switch (tbs)
			{
				case QTabBar::RoundedAbove: {
					p->setPen(cg.background().dark());
					p->drawLine(x + w - 1, y, x + w - 1, y + h - 2);

					p->setPen(cg.background().light());
					p->drawLine(x, y, x + w - 1, y);
					p->drawLine(x, y, x, y + h - 1);
					if (!selected) {
						p->drawLine(x , y + h - 1, x + w - 1, y + h - 1);
						QRect r2(x+1, y+1, w-2, h-2);
						p->fillRect(r2, cg.mid());
					}
					break;
				}

				case QTabBar::RoundedBelow: {
					p->setPen(cg.background().light());
					p->drawLine(x, y, x, y + h - 1);

					p->setPen(cg.background().dark());
					p->drawLine(x + w - 1, y+1, x + w - 1, y + h - 1);
					p->drawLine(x, y+h-1, x + w - 1, y+h-1);

					if (!selected) {
						p->drawLine(x, y, x + w - 1, y);
						QRect r2(x+1, y+1, w-2, h-2);
						p->fillRect(r2, cg.mid());
					}
					break;
				}

				default:
					winstyle->drawControl(element, p, widget, r, cg, flags, opt);
			}

			break;
		}

		case CE_PushButton: {
			drawPrimitive(PE_ButtonBevel, p, r, cg, flags);
			break;
		}

	//	MENUBAR ITEM (sunken panel on mouse over)
	//	-----------------------------------------
		case CE_MenuBarItem: {
			QMenuItem *mi = opt.menuItem();
			bool active  = flags & Style_Active;
			bool focused = flags & Style_HasFocus;

			if ( active && focused ) {
				const int text_flags =
					AlignVCenter | AlignHCenter | ShowPrefix | DontClip | SingleLine;
				p->setPen(cg.highlightedText());
				p->setBrush(cg.highlight());
				p->setPen(cg.highlight().dark());
				p->drawRect(r);

				p->setPen(cg.highlightedText());
				p->drawText(r, text_flags, mi->text());

			} else {
				winstyle->drawControl(element, p, widget, r, cg, flags, opt);
			}
			break;
		}

	//	POPUPMENU ITEM (highlighted on mouseover)
	//	------------------------------------------
		case CE_PopupMenuItem: {
			const QPopupMenu *pum = (const QPopupMenu *) widget;
			static const int itemFrame = 0;
			static const int itemHMargin = 3;
			static const int itemVMargin = 3;
			static const int arrowHMargin = 6;
			static const int rightBorder = 12;
			const int tab = opt.tabWidth();

			int checkcol = QMAX(opt.maxIconWidth(), 26);
			p->save();
			int x, y, w, h;
			r.rect(&x, &y, &w, &h);

			QMenuItem *mi = opt.menuItem();

			if (!mi) {
				return;
			}

			bool active = flags & Style_Active;
			bool disabled = !mi->isEnabled();
			bool checkable = pum->isCheckable();

			int xpos = x;
			int xm = itemFrame + checkcol + itemHMargin;

			if ( pum->erasePixmap() && !pum->erasePixmap()->isNull() ) {
				p->drawPixmap( x, y, *pum->erasePixmap(), x, y, w, h );
			} else {
				p->fillRect( r, cg.background().light() );
				if (!QApplication::reverseLayout())
					p->fillRect( x, y, 22, h, cg.mid() );
				else // i wonder why exactly +1 (diego)
					p->fillRect( w-22, y, 22+1, h, cg.mid() );
			}

			if (mi->isSeparator()) {
				p->setPen(cg.mid());
				if (!QApplication::reverseLayout())
					p->drawLine(x + opt.maxIconWidth() + 6, y, x + w, y);
				else
					p->drawLine(w - (x + opt.maxIconWidth() + 6), y,
					            x, y);
				return;
			}

			if (active && !disabled) {
				p->setPen(cg.highlight().dark());
				p->setBrush(cg.highlight());
				p->drawRect(x+1, y+1, w-2, h-2);
				p->setPen(cg.highlightedText());
			}

			if (mi->iconSet()) {
				p->save();
				QIconSet::Mode mode =
					disabled ? QIconSet::Disabled : QIconSet::Normal;
				QPixmap pixmap = mi->iconSet()->pixmap(QIconSet::Small, mode);
				int pixw = pixmap.width();
				int pixh = pixmap.height();

				QRect cr(xpos, y, opt.maxIconWidth(), h);
				QRect pmr(0, 0, pixw, pixh);
				pmr.moveCenter(cr.center());

				if ( QApplication::reverseLayout() )
					pmr = visualRect( pmr, r );

				p->setPen(cg.highlightedText());
				p->drawPixmap(pmr.topLeft(), pixmap);
				p->restore();
			} else if (checkable) {
				if (mi->isChecked()) {
					int xp = xpos;

					SFlags cflags = Style_Default;
					if (!disabled)
						cflags |= Style_Enabled;
					else
						cflags |= Style_On;

					if (active)
						p->setPen(cg.highlightedText());
					else
						p->setPen(cg.buttonText());

		
					QRect rr = QRect( xp, y, 22, h );
					if ( QApplication::reverseLayout() )
						rr = visualRect( rr, r );

					drawPrimitive(PE_CheckMark, p,
					              rr,
					              cg, cflags);
				}
			}

			p->setPen( active ? cg.highlightedText() : cg.buttonText() );

			xpos += xm;

			if (mi->custom()) {
				int m = itemVMargin;
				p->save();
				/*
/				if (disabled && !active) {
					p->setPen(cg.light());
					mi->custom()->paint(p, cg, active, !disabled,
					                    xpos+1, y+m+1, w-xm-tab+1, h-2*m);
				}*/
				p->setPen(cg.text());
				mi->custom()->paint(p, cg, active, !disabled, x+xm, y+m, w-xm-tab+1, h-2*m);
				p->restore();
				return;
			} else {
				QString s = mi->text();
				if(!s.isNull()) {
					int t = s.find('\t');
					int m = itemVMargin;

					int text_flags =
						AlignVCenter | ShowPrefix | DontClip | SingleLine;

					if (active && !disabled) {
						p->setPen(cg.highlightedText());
					} else if (disabled) {
						p->setPen(cg.mid().light(110));
					} else {
						p->setPen(cg.text());
					}

					if (t >= 0) {
						int xp;
						xp = x + w - tab - rightBorder - itemHMargin - itemFrame + 1;

						QRect rr = QRect( xp, y+m, tab, h-2*m );
						if ( QApplication::reverseLayout() )
							rr = visualRect( rr, r );

						p->drawText(rr, text_flags, s.mid(t+1));
						s = s.left(t);
					}
					
					QRect rr = QRect( xpos, y+m, w-xm-tab+1, h-2*m );
					if ( QApplication::reverseLayout() ){
						rr = visualRect( rr, r );
						text_flags |= AlignRight;
					}
					p->drawText(rr, text_flags, s);

				} else if (mi->pixmap()) {
					QPixmap *pixmap = mi->pixmap();
					if (pixmap->depth() == 1) {
						p->setBackgroundMode(OpaqueMode);
					}
					p->drawPixmap(xpos, y, *pixmap);
					if (pixmap->depth() == 1) {
						p->setBackgroundMode(TransparentMode);
					}
				}
			}

			if (mi->popup()) {
				int dim = pixelMetric(PM_MenuButtonIndicator);

				xpos = x+w - arrowHMargin - 2*itemFrame - dim;

				if (active && !disabled)
					p->setPen(cg.highlightedText());
				else
					p->setPen(cg.text());


				QRect rr = QRect(xpos, y + h/2 - dim/2, dim, dim);
				if ( QApplication::reverseLayout() )
					rr = visualRect( rr, r );
				drawPrimitive((QApplication::reverseLayout() ? PE_ArrowLeft : PE_ArrowRight),
					      p, rr, cg, Style_Enabled);
			}

			p->restore();
			break;
		}

		case PE_CheckMark: {
			const int markW = r.width() > 7 ? 7 : r.width();
			const int markH = markW;
			int posX = r.x() + ( r.width() - markW )/2 + 1;
			int posY = r.y() + ( r.height() - markH )/2;

		// Could do with some optimizing/caching...
			QPointArray a( markH*2 );
			int i, xx, yy;
			xx = posX;
			yy = 3 + posY;
			for ( i=0; i<markW/2; i++ ) {
				a.setPoint( 2*i,   xx, yy );
				a.setPoint( 2*i+1, xx, yy+2 );
				xx++; yy++;
			}
			yy -= 2;
			for ( ; i<markH; i++ ) {
				a.setPoint( 2*i,   xx, yy );
				a.setPoint( 2*i+1, xx, yy+2 );
				xx++; yy--;
			}
			if ( !(flags & Style_Enabled) && !(flags & Style_On)) {
				int pnt;
				p->setPen( cg.highlightedText() );
				QPoint offset(1,1);
				for ( pnt = 0; pnt < (int)a.size(); pnt++ )
					a[pnt] += offset;
				p->drawLineSegments( a );
				for ( pnt = 0; pnt < (int)a.size(); pnt++ )
					a[pnt] -= offset;
			}
			if (p->pen() == QPen::NoPen) {
				p->setPen( cg.text() );
			}
			p->drawLineSegments( a );
			break;
		}

		default:
			winstyle->drawControl(element, p, widget, r, cg, flags, opt);
	}
}



void dotNETstyle::drawComplexControl(ComplexControl control,
                                     QPainter *p,
                                     const QWidget *widget,
                                     const QRect &r,
                                     const QColorGroup &cg,
                                     SFlags flags,
                                     SCFlags controls,
                                     SCFlags active,
                                     const QStyleOption& opt) const
{
	switch(control) {
	//	COMBOBOX
	//	--------
		case CC_ComboBox: {
			int x, y, w, h;
			const QComboBox * cb = (const QComboBox *) widget;
			r.rect(&x, &y, &w, &h);

			if (active & Style_Sunken)
				flags |= Style_Sunken;

			static const unsigned char downarrow_bits[] = {
				0x7f, 0xbe, 0x9c, 0x08, 0x00, 0x00, 0x00, 0x28,
				0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xb8
			};

			static const unsigned int handle_width = 13;
			static const unsigned int handle_offset = handle_width + 1;

			QBitmap downArrow = QBitmap(7, 4, downarrow_bits, true);
			downArrow.setMask(downArrow);

			p->save();

			cb->editable() ? p->fillRect(x + 1, y + 1, w - 2, h - 2, cg.base()) : p->fillRect(x + 1, y + 1, w - 2, h - 2, cg.light());

		//	Draw the panel outside the combobox.
			p->setPen(cg.base());
			p->drawRect(x, y, w, h);
			p->setPen(cg.background().dark());
			p->drawLine(x, y, w, y);
			p->drawLine(x, y, x, h);

		//	Draw the box on the right.
			if ((controls & SC_ComboBoxEditField) && ((active & SC_ListViewExpand) || (flags & Style_HasFocus))) {
				if (cb->editable()) {
					p->setPen(cg.highlight().dark());
					p->setBrush(cg.highlight());
				} else {
					p->setPen(cg.dark());
					p->setBrush(cg.midlight());
				}
			} else {
				p->setPen(cg.dark());
				p->setBrush(cg.midlight());
			}

			QRect rr = QRect( w - handle_offset - 1, y+1, handle_width + 2, h - 1 );
			if (QApplication::reverseLayout())
				rr = visualRect( rr, r );
			p->drawRect(rr);
			p->setBrush(NoBrush);
			rr = QRect( x+1, y+1, w-1, h-1 );
			if (QApplication::reverseLayout())
				rr = visualRect( rr, r );
			p->drawRect( rr );

			if (active)
			        p->setPen(cg.highlightedText());
			else
			        p->setPen(cg.text());

			QRect cr(w - handle_offset, y + 2, handle_width, h - 4);
			QRect pmr(0, 0, 7, 4);
			pmr.moveCenter(cr.center());
			if (QApplication::reverseLayout())
				pmr = visualRect( pmr, r );
			p->drawPixmap(pmr.topLeft(), downArrow);
			p->restore();
			break;
		}

	//	TOOLBUTTON
	//	----------
		case CC_ToolButton: {
			const QToolButton *tb = (const QToolButton *) widget;

			QRect button, menuarea;
			button   = querySubControlMetrics(control, widget, SC_ToolButton, opt);
			menuarea = querySubControlMetrics(control, widget, SC_ToolButtonMenu, opt);

			SFlags bflags = flags,
			       mflags = flags;

			if (active & SC_ToolButton)
				bflags |= Style_Down;

			if (active & SC_ToolButtonMenu)
				mflags |= Style_Down;

			if (controls & SC_ToolButton) {
			//	If we're pressed, on, or raised...
				if (bflags & (Style_Down | Style_On | Style_Raised)) {
					drawPrimitive(PE_ButtonTool, p, button, cg, bflags, opt);
				} else if (tb->parentWidget() &&
				           tb->parentWidget()->backgroundPixmap() &&
				           !tb->parentWidget()->backgroundPixmap()->isNull()) {
					QPixmap pixmap = *(tb->parentWidget()->backgroundPixmap());
					p->drawTiledPixmap( r, pixmap, tb->pos() );
				}
			}

			// Draw a toolbutton menu indicator if required
			if (controls & SC_ToolButtonMenu) {
				if (mflags & (Style_Down | Style_On | Style_Raised)) {
					drawPrimitive(PE_ButtonDropDown, p, menuarea, cg, mflags, opt);
				}
				drawPrimitive(PE_ArrowDown, p, menuarea, cg, mflags, opt);
			}

			if (tb->hasFocus() && !tb->focusProxy()) {
				QRect fr = tb->rect();
				fr.addCoords(2, 2, -2, -2);
				drawPrimitive(PE_FocusRect, p, fr, cg);
			}

			break;
		}

	//	SPINWIDGETS
	//	-----------
		case CC_SpinWidget: {
			const QSpinWidget *sw = (const QSpinWidget *) widget;
			SFlags flags;
			PrimitiveElement pe;

			if (controls & SC_SpinWidgetFrame)
				renderPanel(p, r, cg, true);	// Don't draw the WindowsStyle thick frame.

			if (controls & SC_SpinWidgetUp) {
				flags = Style_Default | Style_Enabled;
				if (active == SC_SpinWidgetUp) {
					flags |= Style_On;
					flags |= Style_Sunken;
				} else
					flags |= Style_Raised;

				if (sw->buttonSymbols() == QSpinWidget::PlusMinus)
					pe = PE_SpinWidgetPlus;
				else
					pe = PE_SpinWidgetUp;

				QRect re = sw->upRect();
				QColorGroup ucg = sw->isUpEnabled() ? cg : sw->palette().disabled();
				drawPrimitive(PE_ButtonBevel, p, re, ucg, flags);
				drawPrimitive(pe, p, re, ucg, flags);
			}

			if (controls & SC_SpinWidgetDown) {
				flags = Style_Default | Style_Enabled;
				if (active == SC_SpinWidgetDown) {
					flags |= Style_On;
					flags |= Style_Sunken;
				} else
					flags |= Style_Raised;

				if (sw->buttonSymbols() == QSpinWidget::PlusMinus)
					pe = PE_SpinWidgetMinus;
				else
					pe = PE_SpinWidgetDown;

				QRect re = sw->downRect();
				QColorGroup dcg = sw->isDownEnabled() ? cg : sw->palette().disabled();
				drawPrimitive(PE_ButtonBevel, p, re, dcg, flags);
				drawPrimitive(pe, p, re, dcg, flags);
			}

			break;
		}

		default:
			KStyle::drawComplexControl(control, p, widget,
			                           r, cg, flags, controls,
			                           active, opt);
			break;
	}
}


QRect dotNETstyle::subRect(SubRect r, const QWidget *widget) const
{
	// Don't use KStyles progressbar subrect
	return QCommonStyle::subRect(r, widget);	
}


int dotNETstyle::pixelMetric(PixelMetric m, const QWidget *widget) const
{
	switch(m)
	{
	//	TABS
	//	----
		case PM_TabBarTabVSpace: {
			const QTabBar * tb = (const QTabBar *) widget;
			if (tb->shape() == QTabBar::RoundedAbove ||
			    tb->shape() == QTabBar::RoundedBelow)
				return 10;
			else
				return 0;
		}

		case PM_TabBarTabOverlap: {
			const QTabBar* tb = (const QTabBar*)widget;
			if (tb->shape() != QTabBar::RoundedAbove &&
				tb->shape() != QTabBar::RoundedBelow)
				return 3;                   // Leave standard size alone
			else
				return 0;                   // Change size for our tabs only
		}

	// PROGRESSBARS
	// ------------
		case PM_ProgressBarChunkWidth:
			return 9;

	// SLIDER
	// ------
		case PM_SliderLength:
			return 11;

	// MENU INDICATOR	
	// --------------
		case PM_MenuButtonIndicator:
			return 8;

	// CHECKBOXES / RADIO BUTTONS
	// --------------------------
		case PM_ExclusiveIndicatorWidth:    // Radiobutton size
		case PM_ExclusiveIndicatorHeight:   // 13x13
		case PM_IndicatorWidth:             // Checkbox size
		case PM_IndicatorHeight:            // 13x13
			return 13;

		case PM_DefaultFrameWidth:
			return 1;

		default:
			return KStyle::pixelMetric(m, widget);
	}
}


QSize dotNETstyle::sizeFromContents(ContentsType t,
                                    const QWidget *widget,
                                    const QSize &s,
                                    const QStyleOption &opt) const
{
	switch (t) {
		case CT_PopupMenuItem: {
		//	const QPopupMenu *popup = (const QPopupMenu *)widget;
			QMenuItem *mi = opt.menuItem();
			if (!widget || opt.isDefault())
				break;

			int w = s.width(), h = s.height();

			if (mi->custom()) {
				w = mi->custom()->sizeHint().width();
				h = mi->custom()->sizeHint().height();
			}
			else if (mi->widget()) {
				// don't change the size in this case.
			}
			else if (mi->isSeparator()) {
				w = 10;
				h = 1;
			} else
				return winstyle->sizeFromContents(t, widget, s, opt);

			return QSize(w, h);
		}

		default: 
			;	// fall though
	}
	return winstyle->sizeFromContents(t, widget, s, opt);
}

void dotNETstyle::paletteChanged()
{
	QComboBox *combo  = 0L;
	QMenuBar *menuBar = 0L;
	QToolBar *toolBar = 0L;
        QWidget  *widget  = 0L;

	QValueListIterator<QWidget*> it = m_widgets.begin();
	for ( ; it != m_widgets.end(); ++it ) {
		widget = *it;
		if ( (combo = dynamic_cast<QComboBox*>( widget )) )
			updatePalette( combo );
		else if ( (toolBar = dynamic_cast<QToolBar*>( widget )) )
			updatePalette( toolBar );
		else if ( (menuBar = dynamic_cast<QMenuBar*>( widget )) )
			updatePalette( menuBar );
	}
}

void dotNETstyle::updatePalette( QComboBox *combo )
{
	QPalette pal = QApplication::palette();
	pal.setColor(QColorGroup::Dark,
	             pal.active().color(QColorGroup::Base));
	pal.setColor(QColorGroup::Midlight,
	             pal.active().color(QColorGroup::Background));
	combo->setPalette(pal);
}

void dotNETstyle::updatePalette( QToolBar *bar )
{
	QPalette pal = QApplication::palette();
	pal.setColor(QColorGroup::Button,
	             pal.active().color(QColorGroup::Background));
	bar->setPalette(pal);
}

void dotNETstyle::updatePalette( QMenuBar *bar )
{
	QPalette pal = QApplication::palette();
	pal.setColor(QColorGroup::Button,
	             pal.active().color(QColorGroup::Background));
	bar->setPalette(pal);
}

void dotNETstyle::slotDestroyed()
{
	m_widgets.remove( (QWidget*) sender() );
}

bool dotNETstyle::eventFilter(QObject *obj, QEvent *ev)
{
	if (obj->inherits("QComboBox")) {
		if (ev->type() == QEvent::Enter) {
			QWidget *btn = (QWidget *)obj;
			if (btn->isEnabled()) {
				QPalette pal = btn->palette();
				pal.setColor(QColorGroup::Dark,
				             pal.active().color(QColorGroup::Highlight).dark());
				pal.setColor(QColorGroup::Midlight,
				             pal.active().color(QColorGroup::Highlight));
				btn->setPalette(pal);
			}
		} else if (ev->type() == QEvent::Leave) {
			QWidget *btn = (QWidget *)obj;
			QPalette pal = btn->palette();
			pal.setColor(QColorGroup::Dark,
			             pal.active().color(QColorGroup::Base));
			pal.setColor(QColorGroup::Midlight,
			             pal.active().color(QColorGroup::Background));
			btn->setPalette(pal);
		}
	}

	return false;
}

// vim: noet ts=4 sw=4
