/********************************************************************
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/

#include "kwmthemeclient.h"

#include <kconfig.h>
#include <kglobal.h>
#include <QLayout>
#include <qdrawutil.h>
#include <QPainter>
#include <kpixmapeffect.h>
#include <kstandarddirs.h>
#include <kdebug.h>
#include <klocale.h>
#include <QBitmap>
#include <QStyle>
#include <QLabel>


namespace KWMTheme {


/* static QPixmap stretchPixmap(QPixmap& src, bool stretchVert){
  QPixmap dest;
  QBitmap *srcMask, *destMask;
  int w, h, w2, h2;
  QPainter p;

  if (src.isNull()) return src;

  w = src.width();
  h = src.height();

  if (stretchVert){
    w2 = w;
    for (h2=h; h2<100; h2=h2<<1)
      ;
  }
  else{
    h2 = h;
    for (w2=w; w2<100; w2=w2<<1)
      ;
  }
  if (w2==w && h2==h) return src;

  dest = src;
  dest.resize(w2, h2);

  p.begin(&dest);
  p.drawTiledPixmap(0, 0, w2, h2, src);
  p.end();

  srcMask = (QBitmap*)src.mask();
  if (srcMask){
    destMask = (QBitmap*)dest.mask();
    p.begin(destMask);
    p.drawTiledPixmap(0, 0, w2, h2, *srcMask);
    p.end();
  }
  return dest;
} */


inline const KDecorationOptions* options() { return KDecoration::options(); }

enum FramePixmap{FrameTop=0, FrameBottom, FrameLeft, FrameRight, FrameTopLeft,
   FrameTopRight, FrameBottomLeft, FrameBottomRight};

static QPixmap *framePixmaps[8];
static QPixmap *menuPix, *iconifyPix, *closePix, *maxPix, *minmaxPix,
    *pinupPix, *pindownPix;
static QPixmap *aTitlePix = 0;
static QPixmap *iTitlePix = 0;
static KPixmapEffect::GradientType grType;
static int maxExtent, titleAlign;
static bool titleGradient = true;
static bool pixmaps_created = false;
static bool titleSunken = false;
static bool titleTransparent;

static void create_pixmaps()
{
    const char *keys[] = {"wm_top", "wm_bottom", "wm_left", "wm_right",
    "wm_topleft", "wm_topright", "wm_bottomleft", "wm_bottomright"};

    if(pixmaps_created)
        return;
    pixmaps_created = true;
    
    KSharedConfig::Ptr _config = KGlobal::config();
    KConfigGroup config(_config, "General");
    
    QString tmpStr;

    for(int i=0; i < 8; ++i)
    {
        framePixmaps[i] = new QPixmap(locate("data",
                                      "kwin/pics/"+config.readEntry(keys[i], " ")));
        if(framePixmaps[i]->isNull())
            kWarning(1212) << "Unable to load frame pixmap for " << keys[i] ;
    }
/*
    *framePixmaps[FrameTop] = stretchPixmap(*framePixmaps[FrameTop], false);
    *framePixmaps[FrameBottom] = stretchPixmap(*framePixmaps[FrameBottom], false);
    *framePixmaps[FrameLeft] = stretchPixmap(*framePixmaps[FrameLeft], true);
    *framePixmaps[FrameRight] = stretchPixmap(*framePixmaps[FrameRight], true);
*/
    maxExtent = framePixmaps[FrameTop]->height();
    if(framePixmaps[FrameBottom]->height() > maxExtent)
        maxExtent = framePixmaps[FrameBottom]->height();
    if(framePixmaps[FrameLeft]->width() > maxExtent)
        maxExtent = framePixmaps[FrameLeft]->width();
    if(framePixmaps[FrameRight]->width() > maxExtent)
        maxExtent = framePixmaps[FrameRight]->width();

    maxExtent++;

    menuPix = new QPixmap(locate("data",
                                 "kwin/pics/"+config.readEntry("menu", " ")));
    iconifyPix = new QPixmap(locate("data",
                                    "kwin/pics/"+config.readEntry("iconify", " ")));
    maxPix = new QPixmap(locate("appdata",
                                "pics/"+config.readEntry("maximize", " ")));
    minmaxPix = new QPixmap(locate("data",
                                   "kwin/pics/"+config.readEntry("maximizedown", " ")));
    closePix = new QPixmap(locate("data",
                                  "kwin/pics/"+config.readEntry("close", " ")));
    pinupPix = new QPixmap(locate("data",
                                  "kwin/pics/"+config.readEntry("pinup", " ")));
    pindownPix = new QPixmap(locate("data",
                                    "kwin/pics/"+config.readEntry("pindown", " ")));
    if(menuPix->isNull())                           
        menuPix->load(locate("data", "kwin/pics/menu.png"));
    if(iconifyPix->isNull())
        iconifyPix->load(locate("data", "kwin/pics/iconify.png"));
    if(maxPix->isNull())
        maxPix->load(locate("data", "kwin/pics/maximize.png"));
    if(minmaxPix->isNull())
        minmaxPix->load(locate("data", "kwin/pics/maximizedown.png"));
    if(closePix->isNull())
        closePix->load(locate("data", "kwin/pics/close.png"));
    if(pinupPix->isNull())
        pinupPix->load(locate("data", "kwin/pics/pinup.png"));
    if(pindownPix->isNull())
        pindownPix->load(locate("data", "kwin/pics/pindown.png"));
    
    tmpStr = config.readEntry("TitleAlignment");
    if(tmpStr == "right")
        titleAlign = Qt::AlignRight | Qt::AlignVCenter;
    else if(tmpStr == "middle")
        titleAlign = Qt::AlignCenter;
    else
        titleAlign = Qt::AlignLeft | Qt::AlignVCenter;
    titleSunken = config.readEntry("TitleFrameShaded", true );
    // titleSunken = true; // is this fixed?
    titleTransparent = config.readEntry("PixmapUnderTitleText", true);

    tmpStr = config.readEntry("TitlebarLook");
    if(tmpStr == "shadedVertical"){
        aTitlePix = new QPixmap;
        aTitlePix->resize(32, 20);
        KPixmapEffect::gradient(*aTitlePix,
                                options()->color(KDecorationOptions::ColorTitleBar, true),
                                options()->color(KDecorationOptions::ColorTitleBlend, true),
                                KPixmapEffect::VerticalGradient);
        iTitlePix = new QPixmap;
        iTitlePix->resize(32, 20);
        KPixmapEffect::gradient(*iTitlePix,
                                options()->color(KDecorationOptions::ColorTitleBar, false),
                                options()->color(KDecorationOptions::ColorTitleBlend, false),
                                KPixmapEffect::VerticalGradient);
        titleGradient = false; // we can just tile this

    }
    else if(tmpStr == "shadedHorizontal")
        grType = KPixmapEffect::HorizontalGradient;
    else if(tmpStr == "shadedDiagonal")
        grType = KPixmapEffect::DiagonalGradient;
    else if(tmpStr == "shadedCrossDiagonal")
        grType = KPixmapEffect::CrossDiagonalGradient;
    else if(tmpStr == "shadedPyramid")
        grType = KPixmapEffect::PyramidGradient;
    else if(tmpStr == "shadedRectangle")
        grType = KPixmapEffect::RectangleGradient;
    else if(tmpStr == "shadedPipeCross")
        grType = KPixmapEffect::PipeCrossGradient;
    else if(tmpStr == "shadedElliptic")
        grType = KPixmapEffect::EllipticGradient;
    else{
        titleGradient = false;
        tmpStr = config.readEntry("TitlebarPixmapActive", "");
        if(!tmpStr.isEmpty()){
            aTitlePix = new QPixmap;
            aTitlePix->load(locate("data", "kwin/pics/" + tmpStr));
        }
        else
            aTitlePix = NULL;
        tmpStr = config.readEntry("TitlebarPixmapInactive", "");
        if(!tmpStr.isEmpty()){
            iTitlePix = new QPixmap;
            iTitlePix->load(locate("data", "kwin/pics/" + tmpStr));
        }
        else
            iTitlePix = NULL;
    }
}

static void delete_pixmaps()
{
   for(int i=0; i < 8; ++i)
        delete framePixmaps[i];

   delete menuPix;
   delete iconifyPix;
   delete closePix;
   delete maxPix;
   delete minmaxPix;
   delete pinupPix;
   delete pindownPix;
   delete aTitlePix;
   aTitlePix = 0;
   delete iTitlePix;
   iTitlePix = 0;

   titleGradient = true;
   pixmaps_created = false;
   titleSunken = false;
}

void MyButton::drawButtonLabel(QPainter *p)
{
    if(pixmap()){
	// If we have a theme who's button covers the entire width or
	// entire height, we shift down/right by 1 pixel so we have
	// some visual notification of button presses. i.e. for MGBriezh
	int offset = (isDown() && ((pixmap()->width() >= width()) || 
                         (pixmap()->height() >= height()))) ? 1 : 0;
        style().drawItem(p, QRect( offset, offset, width(), height() ), 
                         AlignCenter, colorGroup(),
                         true, pixmap(), QString());
    }
}

KWMThemeClient::KWMThemeClient( KDecorationBridge* b, KDecorationFactory* f )
    : KDecoration( b, f )
{
}

void KWMThemeClient::init()
{
    createMainWidget( WResizeNoErase | WStaticContents );
    widget()->installEventFilter( this );

    stickyBtn = maxBtn = mnuBtn = 0;
    layout = new QGridLayout(widget());
    layout->addColSpacing(0, maxExtent);
    layout->addColSpacing(2, maxExtent);

    layout->addRowSpacing(0, maxExtent);

    layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Fixed,
                                    QSizePolicy::Expanding));

    if( isPreview())
        layout->addWidget( new QLabel( i18n( "<center><b>KWMTheme</b></center>" ), widget()), 2, 1);
    else
        layout->addItem( new QSpacerItem( 0, 0 ), 2, 1);

    // Without the next line, shading flickers
    layout->addItem( new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding) );
    layout->addRowSpacing(3, maxExtent);
    layout->setRowStretch(2, 10);
    layout->setColumnStretch(1, 10);
    
    QBoxLayout* hb = new QBoxLayout(0, QBoxLayout::LeftToRight, 0, 0, 0);
    layout->addLayout( hb, 1, 1 );

    KSharedConfig::Ptr _config = KGlobal::config();
    KConfigGroup config(_config, "Buttons");
    QString val;
    MyButton *btn;
    int i;
    static const char *defaultButtons[]={"Menu","Sticky","Off","Iconify",
        "Maximize","Close"};
    static const char keyOffsets[]={"ABCDEF"};
    for(i=0; i < 6; ++i){
        if(i == 3){
            titlebar = new QSpacerItem(10, 20, QSizePolicy::Expanding,
                               QSizePolicy::Minimum );
            hb->addItem( titlebar );
        }
        QString key("Button");
        key += QChar(keyOffsets[i]);
        val = config.readEntry(key, defaultButtons[i]);
        if(val == "Menu"){
            mnuBtn = new MyButton(widget(), "menu");
            mnuBtn->setToolTip( i18n("Menu"));
            iconChange();
            hb->addWidget(mnuBtn);
            mnuBtn->setFixedSize(20, 20);
            connect(mnuBtn, SIGNAL(pressed()), this,
                    SLOT(menuButtonPressed()));
        }
        else if(val == "Sticky"){
            stickyBtn = new MyButton(widget(), "sticky");
            stickyBtn->setToolTip( i18n("Sticky"));
            if (isOnAllDesktops())
                stickyBtn->setPixmap(*pindownPix);
            else
                stickyBtn->setPixmap(*pinupPix);
            connect(stickyBtn, SIGNAL( clicked() ), this, SLOT(toggleOnAllDesktops()));
            hb->addWidget(stickyBtn);
            stickyBtn->setFixedSize(20, 20);
        }
        else if((val == "Iconify") && isMinimizable()){
            btn = new MyButton(widget(), "iconify");
            btn->setToolTip( i18n("Minimize"));
            btn->setPixmap(*iconifyPix);
            connect(btn, SIGNAL(clicked()), this, SLOT(minimize()));
            hb->addWidget(btn);
            btn->setFixedSize(20, 20);
        }
        else if((val == "Maximize") && isMaximizable()){
            maxBtn = new MyButton(widget(), "max");
            maxBtn->setToolTip( i18n("Maximize"));
            maxBtn->setPixmap(*maxPix);
            connect(maxBtn, SIGNAL(clicked()), this, SLOT(maximize()));
            hb->addWidget(maxBtn);
            maxBtn->setFixedSize(20, 20);
        }
        else if((val == "Close") && isCloseable()){
            btn = new MyButton(widget(), "close");
            btn->setToolTip( i18n("Close"));
            btn->setPixmap(*closePix);
            connect(btn, SIGNAL(clicked()), this, SLOT(closeWindow()));
            hb->addWidget(btn);
            btn->setFixedSize(20, 20);
        }
        else{
            if((val != "Off") && 
               ((val == "Iconify") && !isMinimizable()) &&
               ((val == "Maximize") && !isMaximizable()))
                kWarning(1212) << "KWin: Unrecognized button value: " << val ;

        }
    }
    if(titleGradient){
        aGradient = new QPixmap;
        iGradient = new QPixmap;
    }
    else{
        aGradient = 0;
        iGradient = 0;
    }
    widget()->setBackgroundMode(NoBackground);
}

void KWMThemeClient::drawTitle(QPainter &dest)
{
    QRect titleRect = titlebar->geometry();
    QRect r(0, 0, titleRect.width(), titleRect.height());
    QPixmap buffer;

    if(buffer.width() == r.width())
        return;

    buffer.resize(r.size());
    QPainter p;
    p.begin(&buffer);

    if(titleSunken){
			qDrawShadeRect(&p, r, options()->palette(KDecorationOptions::ColorFrame, isActive()).active(),
                       true, 1, 0);
        r.setRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2);
    }
    
    QPixmap *fill = isActive() ? aTitlePix : iTitlePix;
    if(fill)
        p.drawTiledPixmap(r, *fill);
    else if(titleGradient){
        fill = isActive() ? aGradient : iGradient;
        if(fill->width() != r.width()){
            fill->resize(r.width(), 20);
            KPixmapEffect::gradient(*fill,
                                    options()->color(KDecorationOptions::ColorTitleBar, isActive()),
                                    options()->color(KDecorationOptions::ColorTitleBlend, isActive()),
                                    grType);
        }
        p.drawTiledPixmap(r, *fill);
    }
    else{
			p.fillRect(r, options()->palette(KDecorationOptions::ColorTitleBar, isActive()).active().
                   brush(QPalette::Button));
    }
    p.setFont(options()->font(isActive()));
    p.setPen(options()->color(KDecorationOptions::ColorFont, isActive()));
    // Add left & right margin
    r.setLeft(r.left()+5);
    r.setRight(r.right()-5);
    p.drawText(r, titleAlign, caption());
    p.end();

    dest.drawPixmap(titleRect.x(), titleRect.y(), buffer);
}


void KWMThemeClient::resizeEvent( QResizeEvent* )
{
    doShape();
    widget()->repaint();
}

void KWMThemeClient::captionChange()
{
    widget()->repaint( titlebar->geometry(), false );
}

void KWMThemeClient::paintEvent( QPaintEvent *)
{
    QPainter p;
    p.begin(widget());
    int x,y;
    // first the corners
    int w1 = framePixmaps[FrameTopLeft]->width();
    int h1 = framePixmaps[FrameTopLeft]->height();
    if (w1 > width()/2) w1 = width()/2;
    if (h1 > height()/2) h1 = height()/2;
    p.drawPixmap(0,0,*framePixmaps[FrameTopLeft],
		 0,0,w1, h1);
    int w2 = framePixmaps[FrameTopRight]->width();
    int h2 = framePixmaps[FrameTopRight]->height();
    if (w2 > width()/2) w2 = width()/2;
    if (h2 > height()/2) h2 = height()/2;
    p.drawPixmap(width()-w2,0,*framePixmaps[FrameTopRight],
		 framePixmaps[FrameTopRight]->width()-w2,0,w2, h2);

    int w3 = framePixmaps[FrameBottomLeft]->width();
    int h3 = framePixmaps[FrameBottomLeft]->height();
    if (w3 > width()/2) w3 = width()/2;
    if (h3 > height()/2) h3 = height()/2;
    p.drawPixmap(0,height()-h3,*framePixmaps[FrameBottomLeft],
		 0,framePixmaps[FrameBottomLeft]->height()-h3,w3, h3);

    int w4 = framePixmaps[FrameBottomRight]->width();
    int h4 = framePixmaps[FrameBottomRight]->height();
    if (w4 > width()/2) w4 = width()/2;
    if (h4 > height()/2) h4 = height()/2;
    p.drawPixmap(width()-w4,height()-h4,*(framePixmaps[FrameBottomRight]),
		 framePixmaps[FrameBottomRight]->width()-w4,
		 framePixmaps[FrameBottomRight]->height()-h4,
		 w4, h4);

    QPixmap pm;
    QMatrix m;
    int n,s,w;
    //top
    pm = *framePixmaps[FrameTop];

    if (pm.width() > 0){
    s = width()-w2-w1;
    n = s/pm.width();
    w = n>0?s/n:s;
    m.reset();
    m.scale(w/(float)pm.width(), 1);
    pm = pm.transformed(m);

    x = w1;
    while (1){
      if (pm.width() < width()-w2-x){
	p.drawPixmap(x,maxExtent-pm.height()-1,
		     pm);
	x += pm.width();
      }
      else {
	p.drawPixmap(x,maxExtent-pm.height()-1,
		     pm,
		     0,0,width()-w2-x,pm.height());
	break;
      }
    }
    }

    //bottom
    pm = *framePixmaps[FrameBottom];

    if (pm.width() > 0){
    s = width()-w4-w3;
    n = s/pm.width();
    w = n>0?s/n:s;
    m.reset();
    m.scale(w/(float)pm.width(), 1);
    pm = pm.transformed(m);

    x = w3;
    while (1){
      if (pm.width() < width()-w4-x){
	p.drawPixmap(x,height()-maxExtent+1,pm);
	x += pm.width();
      }
      else {
	p.drawPixmap(x,height()-maxExtent+1,pm,
		     0,0,width()-w4-x,pm.height());
	break;
      }
    }
    }

    //left
    pm = *framePixmaps[FrameLeft];

    if (pm.height() > 0){
    s = height()-h3-h1;
    n = s/pm.height();
    w = n>0?s/n:s;
    m.reset();
    m.scale(1, w/(float)pm.height());
    pm = pm.transformed(m);

    y = h1;
    while (1){
      if (pm.height() < height()-h3-y){
	p.drawPixmap(maxExtent-pm.width()-1, y,
		     pm);
	y += pm.height();
      }
      else {
	p.drawPixmap(maxExtent-pm.width()-1, y,
		     pm,
		     0,0, pm.width(),
		     height()-h3-y);
	break;
      }
    }
    }

    //right
    pm = *framePixmaps[FrameRight];

    if (pm.height() > 0){
    s = height()-h4-h2;
    n = s/pm.height();
    w = n>0?s/n:s;
    m.reset();
    m.scale(1, w/(float)pm.height());
    pm = pm.transformed(m);

    y = h2;
    while (1){
      if (pm.height() < height()-h4-y){
	p.drawPixmap(width()-maxExtent+1, y,
		     pm);
	y += pm.height();
      }
      else {
	p.drawPixmap(width()-maxExtent+1, y,
		     pm,
		     0,0, pm.width(),
		     height()-h4-y);
	break;
      }
    }
    }
    drawTitle(p);

    QColor c = widget()->colorGroup().background();

    // KWM evidently had a 1 pixel border around the client window. We
    // emulate it here, but should be removed at some point in order to
    // seamlessly mesh widget themes
    p.setPen(c);
    p.drawRect(maxExtent-1, maxExtent-1, width()-(maxExtent-1)*2,
               height()-(maxExtent-1)*2);

    // We fill the area behind the wrapped widget to ensure that
    // shading animation is drawn as smoothly as possible
    QRect r(layout->cellGeometry(2, 1));
    p.fillRect( r.x(), r.y(), r.width(), r.height(), c);
    p.end();
}

void KWMThemeClient::doShape()
{

    QBitmap shapemask(width(), height());
    shapemask.fill(color0);
    QPainter p;
    p.begin(&shapemask);
    p.setBrush(color1);
    p.setPen(color1);
    int x,y;
    // first the corners
    int w1 = framePixmaps[FrameTopLeft]->width();
    int h1 = framePixmaps[FrameTopLeft]->height();
    if (w1 > width()/2) w1 = width()/2;
    if (h1 > height()/2) h1 = height()/2;
    if (framePixmaps[FrameTopLeft]->mask())
        p.drawPixmap(0,0,*framePixmaps[FrameTopLeft]->mask(),
		     0,0,w1, h1);
    else
        p.fillRect(0,0,w1,h1,color1);
    int w2 = framePixmaps[FrameTopRight]->width();
    int h2 = framePixmaps[FrameTopRight]->height();
    if (w2 > width()/2) w2 = width()/2;
    if (h2 > height()/2) h2 = height()/2;
    if (framePixmaps[FrameTopRight]->mask())
        p.drawPixmap(width()-w2,0,*framePixmaps[FrameTopRight]->mask(),
		     framePixmaps[FrameTopRight]->width()-w2,0,w2, h2);
    else
        p.fillRect(width()-w2,0,w2, h2,color1);

    int w3 = framePixmaps[FrameBottomLeft]->width();
    int h3 = framePixmaps[FrameBottomLeft]->height();
    if (w3 > width()/2) w3 = width()/2;
    if (h3 > height()/2) h3 = height()/2;
    if (framePixmaps[FrameBottomLeft]->mask())
        p.drawPixmap(0,height()-h3,*framePixmaps[FrameBottomLeft]->mask(),
		     0,framePixmaps[FrameBottomLeft]->height()-h3,w3, h3);
    else
        p.fillRect(0,height()-h3,w3,h3,color1);

    int w4 = framePixmaps[FrameBottomRight]->width();
    int h4 = framePixmaps[FrameBottomRight]->height();
    if (w4 > width()/2) w4 = width()/2;
    if (h4 > height()/2) h4 = height()/2;
    if (framePixmaps[FrameBottomRight]->mask())
        p.drawPixmap(width()-w4,height()-h4,*framePixmaps[FrameBottomRight]->mask(),
		     framePixmaps[FrameBottomRight]->width()-w4,
		     framePixmaps[FrameBottomRight]->height()-h4,
		     w4, h4);
    else
        p.fillRect(width()-w4,height()-h4,w4,h4,color1);

    QPixmap pm;
    QMatrix m;
    int n,s,w;
    //top
    if (framePixmaps[FrameTop]->mask())
    {
        pm = *framePixmaps[FrameTop]->mask();

        s = width()-w2-w1;
        n = s/pm.width();
        w = n>0?s/n:s;
        m.reset();
        m.scale(w/(float)pm.width(), 1);
        pm = pm.transformed(m);

        x = w1;
        while (1){
            if (pm.width() < width()-w2-x){
                p.drawPixmap(x,maxExtent-pm.height()-1,
		             pm);
	        x += pm.width();
            }
            else {
	        p.drawPixmap(x,maxExtent-pm.height()-1,
		             pm,
		             0,0,width()-w2-x,pm.height());
	        break;
            }
        }
    }

    //bottom
    if (framePixmaps[FrameBottom]->mask())
    {
        pm = *framePixmaps[FrameBottom]->mask();

        s = width()-w4-w3;
        n = s/pm.width();
        w = n>0?s/n:s;
        m.reset();
        m.scale(w/(float)pm.width(), 1);
        pm = pm.transformed(m);

        x = w3;
        while (1){
          if (pm.width() < width()-w4-x){
	    p.drawPixmap(x,height()-maxExtent+1,pm);
	    x += pm.width();
          }
          else {
	    p.drawPixmap(x,height()-maxExtent+1,pm,
	    		 0,0,width()-w4-x,pm.height());
	    break;
          }
        }
    }

    //left
    if (framePixmaps[FrameLeft]->mask())
    {
        pm = *framePixmaps[FrameLeft]->mask();

        s = height()-h3-h1;
        n = s/pm.height();
        w = n>0?s/n:s;
        m.reset();
        m.scale(1, w/(float)pm.height());
        pm = pm.transformed(m);

        y = h1;
        while (1){
          if (pm.height() < height()-h3-y){
	    p.drawPixmap(maxExtent-pm.width()-1, y,
		         pm);
	    y += pm.height();
          }
          else {
	    p.drawPixmap(maxExtent-pm.width()-1, y,
		         pm,
		         0,0, pm.width(),
		         height()-h3-y);
	    break;
          }
        }
    }

    //right
    if (framePixmaps[FrameRight]->mask())
    {
        pm = *framePixmaps[FrameRight]->mask();

        s = height()-h4-h2;
        n = s/pm.height();
        w = n>0?s/n:s;
        m.reset();
        m.scale(1, w/(float)pm.height());
        pm = pm.transformed(m);

        y = h2;
        while (1){
          if (pm.height() < height()-h4-y){
	    p.drawPixmap(width()-maxExtent+1, y,
		         pm);
	    y += pm.height();
          }
          else {
	    p.drawPixmap(width()-maxExtent+1, y,
		         pm,
		         0,0, pm.width(),
		         height()-h4-y);
	    break;
          }
        }
    }
    p.fillRect(maxExtent-1, maxExtent-1, width()-2*maxExtent+2, height()-2*maxExtent+2, color1);
    setMask(shapemask);
}


void KWMThemeClient::showEvent(QShowEvent *)
{
    doShape();
    widget()->repaint(false);
}

void KWMThemeClient::mouseDoubleClickEvent( QMouseEvent * e )
{
    if (e->button() == LeftButton && titlebar->geometry().contains( e->pos() ) )
        titlebarDblClickOperation();
}

void KWMThemeClient::desktopChange()
{
    if (stickyBtn) {
       bool on = isOnAllDesktops();
       stickyBtn->setPixmap(on ? *pindownPix : *pinupPix);
       stickyBtn->setToolTip( on ? i18n("Unsticky") : i18n("Sticky") );
    }
}

void KWMThemeClient::maximizeChange()
{
    if (maxBtn) {
       bool m = maximizeMode() == MaximizeFull;
       maxBtn->setPixmap(m ? *minmaxPix : *maxPix);
       maxBtn->setToolTip( m ? i18n("Restore") : i18n("Maximize"));
    }
}

void KWMThemeClient::slotMaximize()
{
    maximize( maximizeMode() == MaximizeFull ? MaximizeRestore : MaximizeFull );
}

void KWMThemeClient::activeChange()
{
    widget()->update();
}

KDecoration::Position KWMThemeClient::mousePosition(const QPoint &p) const
{
    Position m = KDecoration::mousePosition(p);
    // corners
    if(p.y() < framePixmaps[FrameTop]->height() &&
       p.x() < framePixmaps[FrameLeft]->width()){
        m = PositionTopLeft;
    }
    else if(p.y() < framePixmaps[FrameTop]->height() &&
            p.x() > width()-framePixmaps[FrameRight]->width()){
        m = PositionTopRight;
    }
    else if(p.y() > height()-framePixmaps[FrameBottom]->height() &&
            p.x() < framePixmaps[FrameLeft]->width()){
        m = PositionBottomLeft;
    }
    else if(p.y() > height()-framePixmaps[FrameBottom]->height() &&
            p.x() > width()-framePixmaps[FrameRight]->width()){
        m = PositionBottomRight;
    } // edges
    else if(p.y() < framePixmaps[FrameTop]->height())
        m = PositionTop;
    else if(p.y() > height()-framePixmaps[FrameBottom]->height())
        m = PositionBottom;
    else if(p.x()  < framePixmaps[FrameLeft]->width())
        m = PositionLeft;
    else if(p.x() > width()-framePixmaps[FrameRight]->width())
        m = PositionRight;
    return(m);
}

void KWMThemeClient::menuButtonPressed()
{
    mnuBtn->setDown(false); // will stay down if I don't do this
    QPoint pos = mnuBtn->mapToGlobal(mnuBtn->rect().bottomLeft());
    showWindowMenu( pos );
}

void KWMThemeClient::iconChange()
{
    if(mnuBtn){
        if( icon().pixmap( QIcon::Small, QIcon::Normal ).isNull()){
            mnuBtn->setPixmap(*menuPix);
        }
        else{
            mnuBtn->setPixmap(icon().pixmap( QIcon::Small, QIcon::Normal ));
        }
    }
}

bool KWMThemeClient::eventFilter( QObject* o, QEvent* e )
{
	if ( o != widget() )
		return false;

	switch ( e->type() )
	{
		case QEvent::Resize:
			resizeEvent( static_cast< QResizeEvent* >( e ) );
			return true;

		case QEvent::Paint:
			paintEvent( static_cast< QPaintEvent* >( e ) );
			return true;

		case QEvent::MouseButtonDblClick:
			mouseDoubleClickEvent( static_cast< QMouseEvent* >( e ) );
			return true;

		case QEvent::MouseButtonPress:
			processMousePressEvent( static_cast< QMouseEvent* >( e ) );
			return true;

		case QEvent::Show:
			showEvent( static_cast< QShowEvent* >( e ) );
			return true;

		default:
	    		return false;
	}
}

QSize KWMThemeClient::minimumSize() const
{
    return widget()->minimumSize().expandedTo( QSize( 100, 50 ));
}

void KWMThemeClient::resize( const QSize& s )
{
    widget()->resize( s );
}

void KWMThemeClient::borders( int& left, int& right, int& top, int& bottom ) const
{
    left =
    right =
    top =
    bottom =
    
TODO
}

KWMThemeFactory::KWMThemeFactory()
{
    create_pixmaps();
}

KWMThemeFactory::~KWMThemeFactory()
{
    delete_pixmaps();
}

KDecoration* KWMThemeFactory::createDecoration( KDecorationBridge* b )
{
    return new KWMThemeClient( b, this );
}

bool KWMThemeFactory::reset( unsigned long mask )
{
    bool needHardReset = false;

TODO

    // doesn't obey the Border size setting
    if( mask & ( SettingFont | SettingButtons ))
        needHardReset = true;

    if( mask & ( SettingFont | SettingColors )) {
        KWMTheme::delete_pixmaps();
        KWMTheme::create_pixmaps();
    }
    
    if( !needHardReset )
        resetDecorations( mask );
    return needHardReset;
}

}

extern "C"
{
	KDE_EXPORT KDecorationFactory *create_factory()
	{
                return new KWMTheme::KWMThemeFactory();
	}
}

#include "kwmthemeclient.moc"
