diff options
Diffstat (limited to 'client/polyester.cpp')
-rwxr-xr-x | client/polyester.cpp | 1858 |
1 files changed, 1858 insertions, 0 deletions
diff --git a/client/polyester.cpp b/client/polyester.cpp new file mode 100755 index 0000000..91c06fe --- /dev/null +++ b/client/polyester.cpp @@ -0,0 +1,1858 @@ +////////////////////////////////////////////////////////////////////////////// +// polyester.cc +// ------------------- +// Polyester window decoration for KDE +// Copyright (c) 2006 Marco Martin +// ------------------- +// derived from Smooth Blend +// Copyright (c) 2005 Ryan Nickell +// ------------------- +// Shadow engine from Plastik decoration +// Copyright (C) 2003 Sandro Giessl <ceebx@users.sourceforge.net> +// ------------------- +// Please see the header file for copyright and license information. +////////////////////////////////////////////////////////////////////////////// + + +#include <tdeconfig.h> +#include <tdeversion.h> +#include <tdeglobal.h> +#include <tdeglobalsettings.h> +#include <tdelocale.h> +#include <kpixmap.h> +#include <kimageeffect.h> +#include <kpixmapeffect.h> +#include <kpixmap.h> + +#include <tqbitmap.h> +#include <tqlabel.h> +#include <tqlayout.h> +#include <tqpainter.h> +#include <tqtooltip.h> +#include <tqtimer.h> +#include <tqapplication.h> +#include <tqsettings.h> +#include <math.h> +#include <stdlib.h> + +#include "polyester.h" +#include "buttons.h" +#include "shadow.h" +#include "../style/misc.h" + +using namespace polyester; + +////////////////////////////////////////////////////////////////////////////// +// polyesterFactory Class +////////////////////////////////////////////////////////////////////////////// +polyesterFactory* factory=NULL; + +bool polyesterFactory::initialized_ = false; +TQt::AlignmentFlags polyesterFactory::titlealign_ = TQt::AlignHCenter; +int polyesterFactory::contrast_ = 6; +bool polyesterFactory::cornerflags_ = true; +int polyesterFactory::titlesize_ = 22; +int polyesterFactory::buttonsize_ = 18; +bool polyesterFactory::squareButton_ = false; +int polyesterFactory::framesize_ = 2; +int polyesterFactory::roundsize_ = 50; +int polyesterFactory::titleBarStyle_ = 0; +int polyesterFactory::buttonStyle_ = 1; +bool polyesterFactory::titleshadow_ = true; +bool polyesterFactory::nomodalbuttons = false; +bool polyesterFactory::lightBorder_ = true; +bool polyesterFactory::animatebuttons = true; +int polyesterFactory::btnComboBox = 0; +bool polyesterFactory::menuClose = false; + +// global constants +static const int TOPMARGIN = 4; // do not change +static const int DECOHEIGHT = 4; // do not change +static const int SIDETITLEMARGIN = 2; +// Default button layout +const char default_left[] = "M"; +const char default_right[] = "HIAX"; + +static const uint TIMERINTERVAL = 25; // msec +static const uint ANIMATIONSTEPS = 20; + +extern "C" KDE_EXPORT KDecorationFactory* create_factory() { + return new polyester::polyesterFactory(); +} + +////////////////////////////////////////////////////////////////////////////// +// polyesterFactory() +// ---------------- +// Constructor + +polyesterFactory::polyesterFactory() { + readConfig(); + initialized_ = true; +} + +////////////////////////////////////////////////////////////////////////////// +// ~polyesterFactory() +// ----------------- +// Destructor + +polyesterFactory::~polyesterFactory() { + initialized_ = false; +} + +////////////////////////////////////////////////////////////////////////////// +// createDecoration() +// ----------------- +// Create the decoration + +KDecoration* polyesterFactory::createDecoration(KDecorationBridge* b) { + return new polyesterClient(b, this); +} + +////////////////////////////////////////////////////////////////////////////// +// reset() +// ------- +// Reset the handler. Returns true if decorations need to be remade, false if +// only a repaint is necessary + +bool polyesterFactory::reset(unsigned long changed) { + // read in the configuration + initialized_ = false; + bool confchange = readConfig(); + initialized_ = true; + + if (confchange || + (changed & (SettingDecoration | SettingButtons | SettingBorder))) { + return true; + } else { + resetDecorations(changed); + return false; + } +} + +////////////////////////////////////////////////////////////////////////////// +// readConfig() +// ------------ +// Read in the configuration file + +bool polyesterFactory::readConfig() { + // create a config object + TDEConfig config("twinpolyesterrc"); + config.setGroup("General"); + + // grab settings + TQString value = config.readEntry("TitleAlignment", "AlignHCenter"); + if (value == "AlignLeft") + titlealign_ = TQt::AlignLeft; + else if (value == "AlignHCenter") + titlealign_ = TQt::AlignHCenter; + else if (value == "AlignRight") + titlealign_ = TQt::AlignRight; + + TQSettings globalSettings; + contrast_ = globalSettings.readNumEntry("/TQt/KDE/contrast", 6); + cornerflags_ = config.readBoolEntry("RoundCorners", true); + titlesize_ = config.readNumEntry("TitleSize",20); + titleBarStyle_ = config.readNumEntry("TitleBarStyle", 0); + buttonStyle_ = config.readNumEntry("ButtonStyle", 1); + + buttonsize_ = config.readNumEntry("ButtonSize",18); + squareButton_ = config.readBoolEntry("SquareButton", false); + framesize_ = config.readNumEntry("FrameSize",2); + roundsize_ = config.readNumEntry("RoundPercent",50); + + + titleshadow_ = config.readBoolEntry("TitleShadow", true); + lightBorder_ = config.readBoolEntry("LightBorder", true); + animatebuttons = config.readBoolEntry("AnimateButtons", true); + nomodalbuttons = config.readBoolEntry("NoModalButtons", false); + btnComboBox = config.readNumEntry("ButtonComboBox", 0); + menuClose = config.readBoolEntry("CloseOnMenuDoubleClick"); + + if(buttonsize_ > titlesize_ - framesize_) + { + buttonsize_ = titlesize_-framesize_; + } + + return true; +} + +////////////////////////////////////////////////////////////////////////////// +// polyesterButton Class +////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////// +// polyesterButton() +// --------------- +// Constructor +polyesterButton::polyesterButton(polyesterClient *parent, const char *name, const TQString& tip, ButtonType type, int button_size, bool squareButton, bool toggle): TQButton(parent->widget(), name), + client_(parent), + type_(type), + size_(button_size), + deco_(0), + lastmouse_(NoButton), + buttonImgActive_created(false), + buttonImgInactive_created(false), + hover_(false) +{ + setBackgroundMode(NoBackground); + + int buttonWidth = button_size; + if( squareButton ) + buttonProportions_ = 1; + else + { + buttonProportions_ = sqrt(2); + buttonWidth = (int)round(button_size*buttonProportions_); + //makes always centered icons + if( buttonWidth % 2 != 0 ) + buttonWidth++; + } + + setFixedSize( buttonWidth, button_size); + setCursor(arrowCursor); + TQToolTip::add(this, tip); + setToggleButton(toggle); + //button animation setup + animTmr = new TQTimer(this); + connect(animTmr, TQ_SIGNAL(timeout() ), this, TQ_SLOT(animate() ) ); + connect(this, TQ_SIGNAL(pressed() ), this, TQ_SLOT(buttonClicked() ) ); + connect(this, TQ_SIGNAL(released() ), this, TQ_SLOT(buttonReleased() ) ); + animProgress = 0; + m_clicked=false; +} + +polyesterButton::~polyesterButton() { + if ( deco_ ) + delete deco_; +} + +////////////////////////////////////////////////////////////////////////////// +// sizeHint() +// ---------- +// Return size hint + +TQSize polyesterButton::sizeHint() const { + return TQSize(size_, size_); +} + +////////////////////////////////////////////////////////////////////////////// +// buttonClicked() +// ---------- +// Button animation progress reset so we don't get any leave event animation +// when the mouse is still pressed +void polyesterButton::buttonClicked() { + m_clicked=true; + animProgress=0; +} +void polyesterButton::buttonReleased() { + //This doesn't work b/c a released() TQ_SIGNAL is thrown when a leaveEvent occurs + //m_clicked=false; +} + +////////////////////////////////////////////////////////////////////////////// +// animate() +// ---------- +// Button animation timing +void polyesterButton::animate() { + animTmr->stop(); + if (!::factory->animateButtons() ) + return; + + if(hover_) { + if(animProgress < ANIMATIONSTEPS) { + animProgress++; + animTmr->start(TIMERINTERVAL, true); // single-shot + } + } else { + if(animProgress > 0) { + animProgress--; + animTmr->start(TIMERINTERVAL, true); // single-shot + } + } + repaint(false); +} +////////////////////////////////////////////////////////////////////////////// +// enterEvent() +// ------------ +// Mouse has entered the button + +void polyesterButton::enterEvent(TQEvent *e) { + // we wanted to pass on the event + TQButton::enterEvent(e); + // we want to do mouseovers, so keep track of it here + hover_=true; + if(!m_clicked) + { + animate(); + } +} + +////////////////////////////////////////////////////////////////////////////// +// leaveEvent() +// ------------ +// Mouse has left the button + +void polyesterButton::leaveEvent(TQEvent *e) { + // we wanted to pass on the event + TQButton::leaveEvent(e); + // we want to do mouseovers, so keep track of it here + hover_=false; + if(!m_clicked) + { + animate(); + } +} + +////////////////////////////////////////////////////////////////////////////// +// mousePressEvent() +// ----------------- +// Button has been pressed + +void polyesterButton::mousePressEvent(TQMouseEvent* e) { + lastmouse_ = e->button(); + + // translate and pass on mouse event + int button = LeftButton; + if ((type_ != ButtonMax) && (e->button() != LeftButton)) { + button = NoButton; // middle & right buttons inappropriate + } + TQMouseEvent me(e->type(), e->pos(), e->globalPos(), + button, e->state()); + TQButton::mousePressEvent(&me); +} + +////////////////////////////////////////////////////////////////////////////// +// mouseReleaseEvent() +// ----------------- +// Button has been released + +void polyesterButton::mouseReleaseEvent(TQMouseEvent* e) { + lastmouse_ = e->button(); + + // translate and pass on mouse event + int button = LeftButton; + if ((type_ != ButtonMax) && (e->button() != LeftButton)) { + button = NoButton; // middle & right buttons inappropriate + } + TQMouseEvent me(e->type(), e->pos(), e->globalPos(), button, e->state()); + TQButton::mouseReleaseEvent(&me); + if(m_clicked) + { + m_clicked=false; + } +} + +void polyesterButton::setOn(bool on) +{ + TQButton::setOn(on); +} + +void polyesterButton::setDown(bool on) +{ + TQButton::setDown(on); +} + +////////////////////////////////////////////////////////// +// getButtonImage() +// ---------------- +// get the button TQImage based on type and window mode +TQImage polyesterButton::getButtonImage(ButtonType type) +{ + TQImage finalImage; + switch(type) { + case ButtonClose: + finalImage = uic_findImage( "close.png" ); + break; + case ButtonHelp: + finalImage = uic_findImage( "help.png" ); + break; + case ButtonMin: + finalImage = uic_findImage( "minimize.png" ); + break; + case ButtonMax: + if(client_->maximizeMode() == KDecorationDefines::MaximizeFull) + { + finalImage = uic_findImage( "restore.png" ); + } + else + { + finalImage = uic_findImage( "maximize.png" ); + } + break; + case ButtonSticky: + if(client_->isOnAllDesktops()) + { + finalImage = uic_findImage( "circle2.png" ); + } + else + { + finalImage = uic_findImage( "circle.png" ); + } + break; + case ButtonShade: + if(client_->isShade()) + { + finalImage = uic_findImage( "unsplat.png" ); + } + else + { + finalImage = uic_findImage( "splat.png" ); + } + break; + case ButtonAbove: + if(client_->keepAbove()) + { + finalImage = uic_findImage( "keep_above_lit.png" ); + } + else + { + finalImage = uic_findImage( "keep_above.png" ); + } + break; + case ButtonBelow: + if(client_->keepBelow()) + { + finalImage = uic_findImage( "keep_below_lit.png" ); + } + else + { + finalImage = uic_findImage( "keep_below.png" ); + } + break; + default: + finalImage = uic_findImage( "splat.png" ); + break; + } + if(tqGray(KDecoration::options()->color(KDecoration::ColorButtonBg, client_->isActive()).rgb()) < 150) + finalImage.invertPixels(); + + return finalImage; +} + +////////////////////////////////////////////////////////// +// drawButton() +// ------------------------- +// draw the pixmap button + +void polyesterButton::drawButton( TQPainter *painter ) { + if ( !polyesterFactory::initialized() ) + return ; + + int newWidth = width() - 2; + int newHeight = height() - 2; + int dx = (width() - newWidth) / 2; + int dy = (height() - newHeight) / 2; + TQImage tmpResult; + TQColorGroup group; + TQColor redColor(red); + bool active = client_->isActive(); + + genButtonPix(active); + + TQPixmap backgroundTile = client_->getTitleBarTile(active); + group = KDecoration::options()->colorGroup(KDecoration::ColorButtonBg, active); + + //draw the titlebar behind the buttons and app icons + if ((client_->maximizeMode()==client_->MaximizeFull) && !KDecoration::options()->moveResizeMaximizedWindows()) + { + painter->drawTiledPixmap(0, 0, width(), height(), backgroundTile, 0, 1); + } + else + { + painter->drawTiledPixmap(0, 0, width(), height(), backgroundTile, + 0, y()-::factory->frameSize()); + } + + //the menu button doesn't have a button appearance + if (type_ == ButtonMenu) + { + //slight movement to show the menu button is depressed + if (isDown()) { + dx++; + dy++; + } + TQPixmap menuButtonPixmap(client_->icon().pixmap(TQIconSet::Small, TQIconSet::Normal)); + TQImage menuButtonImage(menuButtonPixmap.convertToImage()); + //draw the menu button the same size as the other buttons + //using TQIconSet::Large gives us a 32x32 icon to resize, resizing larger than + //that may produce pixilation of the image + //painter->setPen(group.background()); + + painter->drawImage( dx+(int)round(abs(width()-size_)/2), dy, menuButtonImage.smoothScale(size_-2, newHeight) ); + return; + } + + //build the button image with the icon superimposed to the button + TQImage buttonImage = (active?(buttonImgActive):(buttonImgInactive))->copy(); + KImageEffect::blendOnLower( (int)round(abs(width()-size_)/2), 0, + getButtonImage(type_).smoothScale( size_,size_), + buttonImage ); + + //highlight on a mouse over repaint + double factor = animProgress * 0.05;//0.13; + + //do the animation thing + if( !isDown() && factor != 0.0 ) + { + tmpResult = buttonImage.copy(); + //always colorize with a threatening red color the close button + if( type_ == ButtonClose) + { + //tmpResult = KImageEffect::blend( TQColor(180, 50, 50), buttonImage, factor ); + KImageEffect::desaturate( tmpResult, factor ); + KImageEffect::channelIntensity( tmpResult, factor/3, KImageEffect::Red ); + KImageEffect::channelIntensity( tmpResult, -factor/2, KImageEffect::Green ); + KImageEffect::channelIntensity( tmpResult, -factor/2, KImageEffect::Blue ); + } + else + switch(::factory->getBtnComboBox()) + { + //colorize + case 0: + if( type_ == ButtonMax) + { + KImageEffect::desaturate( tmpResult, factor ); + KImageEffect::channelIntensity( tmpResult, -factor/3, KImageEffect::Red ); + KImageEffect::channelIntensity( tmpResult, factor/2, KImageEffect::Green ); + KImageEffect::channelIntensity( tmpResult, -factor/3, KImageEffect::Blue ); + } + else if( type_ == ButtonMin) + { + KImageEffect::desaturate( tmpResult, factor ); + KImageEffect::channelIntensity( tmpResult, factor/4, KImageEffect::Red ); + KImageEffect::channelIntensity( tmpResult, factor/4, KImageEffect::Green ); + KImageEffect::channelIntensity( tmpResult, -factor/2, KImageEffect::Blue ); + } + else if( type_ == ButtonSticky) + { + KImageEffect::desaturate( tmpResult, factor ); + KImageEffect::channelIntensity( tmpResult, -factor/3, KImageEffect::Red ); + KImageEffect::channelIntensity( tmpResult, -factor/3, KImageEffect::Green ); + KImageEffect::channelIntensity( tmpResult, factor/2, KImageEffect::Blue ); + } + else + { + KImageEffect::desaturate( tmpResult, factor ); + KImageEffect::channelIntensity( tmpResult, -factor/2, KImageEffect::Red ); + KImageEffect::channelIntensity( tmpResult, factor/3, KImageEffect::Green ); + KImageEffect::channelIntensity( tmpResult, factor/3, KImageEffect::Blue ); + } + break; + //intensify + case 1: + KImageEffect::intensity( tmpResult, factor); + break; + //fade + case 2: + KImageEffect::intensity( tmpResult, -factor/2); + + break; + } + } + + KImageEffect::blendOnLower(tmpResult, TQPoint(1,1), buttonImage, TQRect(1,1,width()-2, height()-2) ); + + TQPixmap finalButton = TQPixmap(buttonImage); + + painter->drawPixmap( 0, 0, finalButton ); +} + +void polyesterButton::genButtonPix( bool active ) +{ + if(active && buttonImgActive_created) return; + else if(!active && buttonImgInactive_created) return; + + KPixmap tempPixmap; + TQPixmap *tempButton = new TQPixmap(width(), height()); + TQPainter painter(tempButton); + + TQColorGroup group; + group = KDecoration::options()->colorGroup(KDecoration::ColorButtonBg, client_->isActive()); + + if( ::factory->buttonStyle() == BUTTON_GLASS ) + tempPixmap.resize(width()-2, (height()/2)-1); + else + tempPixmap.resize(width()-2, height()-2); + + /* + if( ::factory->buttonStyle() != BUTTON_FLAT ) + { + tempPixmap = KPixmapEffect::gradient(tempPixmap, + group.background().light(100+(::factory->buttonStyle()!=BUTTON_REVGRADIENT?60:-20)), + group.background().light(100+(::factory->buttonStyle()!=BUTTON_GLASS? + (::factory->buttonStyle()==BUTTON_REVGRADIENT? + 60:-20) + :0)), + KPixmapEffect::VerticalGradient + ); + } + else + { + tempPixmap = KPixmapEffect::gradient(tempPixmap, + group.background(), + group.background(), + KPixmapEffect::VerticalGradient + ); + } +*/ + + int contrast = ::factory->contrast(); + + switch( ::factory->buttonStyle() ) + { + case BUTTON_GRADIENT: + tempPixmap = KPixmapEffect::gradient(tempPixmap, + group.background().light(105+contrast*8), + group.background().dark(100+contrast*2), + KPixmapEffect::VerticalGradient + ); + break; + case BUTTON_GLASS: + tempPixmap = KPixmapEffect::gradient(tempPixmap, + group.background().light(105+contrast*8), + group.background(), + KPixmapEffect::VerticalGradient + ); + break; + case BUTTON_REVGRADIENT: + tempPixmap = KPixmapEffect::gradient(tempPixmap, + group.background().dark(100+contrast*2), + group.background().light(105+contrast*8), + KPixmapEffect::VerticalGradient + ); + break; + + //case BUTTON_FLAT: + default: + tempPixmap = KPixmapEffect::gradient(tempPixmap, + group.background(), + group.background(), + KPixmapEffect::VerticalGradient + ); + break; + } + + //draw the main area of the buttons + //painter.begin(tempButton); + painter.drawPixmap(1, 1, tempPixmap); + + //if the button is glass create the second gradient + if( ::factory->buttonStyle() == BUTTON_GLASS ) + { + tempPixmap = KPixmapEffect::gradient(tempPixmap, + group.background().dark(105+contrast), + group.background(), + KPixmapEffect::VerticalGradient + ); + + painter.drawPixmap(1, (height()/2), tempPixmap); + } + + //border + TQColor borderColor = group.background().dark(160); + painter.setPen( borderColor ); + painter.drawLine(0, 2, 0, height()-3); + painter.drawLine(width()-1, 2, width()-1, height()-3); + painter.drawLine(2, 0, width()-3, 0); + painter.drawLine(2, height()-1, width()-3, height()-1); + painter.drawPoint(1, 1); + painter.drawPoint(width()-2, 1); + painter.drawPoint(1, height()-2); + painter.drawPoint(width()-2, height()-2); + + //little 3d effect + painter.setPen( group.background().light(140) ); + painter.drawLine(1, 2, 1, height()-3); + painter.drawLine(2, 1, width()-3, 1); + if(!::factory->lightBorder()) + painter.setPen( group.background().dark(110) ); + painter.drawLine(width()-2, 2, width()-2, height()-3); + painter.drawLine(2, height()-2, width()-3, height()-2); + painter.end(); + + //border antialiasing + TQImage *tempAlphaImg = new TQImage( tempButton->convertToImage() ); + //tempAlphaImg = tempPixmap.convertToImage(); + tempAlphaImg->setAlphaBuffer(true); + int borderRed = borderColor.red(); + int borderGreen = borderColor.green(); + int borderBlue = borderColor.blue(); + + tempAlphaImg->setPixel(0,0, tqRgba(borderRed, borderGreen , borderBlue, 40)); + tempAlphaImg->setPixel(width()-1, 0, tqRgba(borderRed, borderGreen , borderBlue, 40)); + tempAlphaImg->setPixel(0,height()-1, tqRgba(borderRed, borderGreen , borderBlue, 40)); + tempAlphaImg->setPixel(width()-1,height()-1, tqRgba(borderRed, borderGreen , borderBlue, 40)); + + tempAlphaImg->setPixel(0,1, tqRgba(borderRed, borderGreen , borderBlue, 127)); + tempAlphaImg->setPixel(1,0, tqRgba(borderRed, borderGreen , borderBlue, 127)); + + tempAlphaImg->setPixel(width()-2,0, tqRgba(borderRed, borderGreen , borderBlue, 127)); + tempAlphaImg->setPixel(width()-1,1, tqRgba(borderRed, borderGreen , borderBlue, 127)); + + tempAlphaImg->setPixel(0,height()-2, tqRgba(borderRed, borderGreen , borderBlue, 127)); + tempAlphaImg->setPixel(1,height()-1, tqRgba(borderRed, borderGreen , borderBlue, 127)); + + tempAlphaImg->setPixel(width()-1,height()-2, tqRgba(borderRed, borderGreen , borderBlue, 127)); + tempAlphaImg->setPixel(width()-2,height()-1, tqRgba(borderRed, borderGreen , borderBlue, 127)); + + + if( client_->isActive() ) + { + buttonImgActive = tempAlphaImg; + buttonImgActive_created = true; + } + else + { + buttonImgInactive = tempAlphaImg; + buttonImgInactive_created = true; + } + +} + +////////////////////////////////////////////////////////////////////////////// +// polyesterClient Class +////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////// +// polyesterClient() +// --------------- +// Constructor + +polyesterClient::polyesterClient(KDecorationBridge *b, KDecorationFactory *f) + : KDecoration(b, f), + mainLayout_(0), + titleLayout_(0), + topSpacer_(0), + titleSpacer_(0), + leftTitleSpacer_(0), rightTitleSpacer_(0), + decoSpacer_(0), + leftSpacer_(0), rightSpacer_(0), + bottomSpacer_(0), windowSpacer_(0), + aCaptionBuffer(0), iCaptionBuffer(0), + aTitleBarTile(0), iTitleBarTile(0), aTitleBarTopTile(0), iTitleBarTopTile(0), + pixmaps_created(false), + //captionBufferDirty(true), + closing(false), + s_titleHeight(0), + s_titleFont(TQFont()), + maskDirty(true), + aDoubleBufferDirty(true), + iDoubleBufferDirty(true) + { + aCaptionBuffer = new TQPixmap(); + iCaptionBuffer = new TQPixmap(); + + //copying the most used configuration options + frameSize = ::factory->frameSize(); + + NET::WindowType type = windowType(NET::NormalMask | NET::DesktopMask | + NET::DockMask | NET::ToolbarMask | + NET::MenuMask | NET::DialogMask| + NET::OverrideMask | NET::TopMenuMask | + NET::UtilityMask | NET::SplashMask); + if( type == NET::Utility || type == NET::Menu || type == NET::Toolbar ) + { + titleSize = (int)((double)::factory->titleSize()/1.2); + buttonSize = titleSize - 2; + roundedCorners = false; + } + else + { + titleSize = ::factory->titleSize(); + //don't allow buttonSize > titleSize + buttonSize = titleSize - 2 < ::factory->buttonSize()? + titleSize - 2 : + ::factory->buttonSize(); + roundedCorners = ::factory->roundedCorners(); + } + + //s_titleFont = isTool()?polyesterFactory::titleFontTool():polyesterFactory::titleFont(); + s_titleFont = options()->font(); + s_titleHeight = titleSize; + } + +////////////////////////////////////////////////////////////////////////////////// +// ~polyesterClient() +// -------------------- +// Destructor +polyesterClient::~polyesterClient() { + delete aCaptionBuffer; + delete iCaptionBuffer; +} + +void polyesterClient::create_pixmaps() { + if(pixmaps_created) + return; + KPixmap tempPixmap; + TQPainter painter; + + + // active top title bar tile + tempPixmap.resize(1, s_titleHeight+frameSize); + tempPixmap = KPixmapEffect::gradient(tempPixmap, + KDecoration::options()->color(ColorTitleBar, true).light(160), + KDecoration::options()->color(ColorTitleBlend, true).light(104), + KPixmapEffect::VerticalGradient + ); + // tempPixmap.fill(KDecoration::options()->color(ColorTitleBar, true).light(150)); + aTitleBarTopTile = new TQPixmap(1, s_titleHeight+frameSize); + painter.begin(aTitleBarTopTile); + painter.drawPixmap(0, 0, tempPixmap); + painter.end(); + + // inactive top title bar tile + tempPixmap = KPixmapEffect::gradient(tempPixmap, + KDecoration::options()->color(ColorTitleBar, false).light(160), + KDecoration::options()->color(ColorTitleBlend, false), + KPixmapEffect::VerticalGradient + ); + iTitleBarTopTile = new TQPixmap(1, s_titleHeight+frameSize); + painter.begin(iTitleBarTopTile); + painter.drawPixmap(0, 0, tempPixmap); + painter.end(); + + // active title bar tile + if( ::factory->titleBarStyle() == TITLEBAR_GLASS) + tempPixmap.resize(1, ((s_titleHeight+frameSize)/2) - 1 ); + else + tempPixmap.resize(1, s_titleHeight+frameSize); + + TQColor color1; + TQColor color2; + TQColor glassColor; + if( ::factory->titleBarStyle() == TITLEBAR_GLASS ) + { + glassColor = alphaBlendColors( KDecoration::options()->color(ColorTitleBar, true), + KDecoration::options()->color(ColorTitleBlend, true), + 127 ); + color1 = glassColor.light(105+::factory->contrast()*4); + color2 = glassColor; + } + else + { + color1 = KDecoration::options()->color(ColorTitleBar, true); + color2 = KDecoration::options()->color(ColorTitleBlend, true); + } + + tempPixmap = KPixmapEffect::gradient(tempPixmap, + color1, + color2, + KPixmapEffect::VerticalGradient + ); + + aTitleBarTile = new TQPixmap(1, s_titleHeight+frameSize); + painter.begin(aTitleBarTile); + painter.drawPixmap(0, 0, tempPixmap); + + if( ::factory->titleBarStyle() == TITLEBAR_GLASS ) + { + int y = tempPixmap.height(); + tempPixmap.resize(1, (s_titleHeight+frameSize)-y ); + tempPixmap = KPixmapEffect::gradient(tempPixmap, + glassColor.dark(105+::factory->contrast()), + glassColor, + KPixmapEffect::VerticalGradient + ); + painter.drawPixmap(0, y, tempPixmap); + } + // painter.drawPixmap(0, 0, *aTitleBarTopTile); + painter.end(); + + // inactive title bar tile + //de-glassify inactive titlebar + if( ::factory->titleBarStyle() == TITLEBAR_GLASS ) + tempPixmap.resize(1, s_titleHeight+frameSize); + tempPixmap = KPixmapEffect::gradient(tempPixmap, + KDecoration::options()->color(ColorTitleBar, false), + KDecoration::options()->color(ColorTitleBlend, false), + KPixmapEffect::VerticalGradient + ); + iTitleBarTile = new TQPixmap(1, s_titleHeight+frameSize); + painter.begin(iTitleBarTile); + painter.drawPixmap(0, 0, tempPixmap); + painter.end(); + + + pixmaps_created = true; +} + +void polyesterClient::delete_pixmaps() { + delete aTitleBarTopTile; + aTitleBarTopTile = 0; + + delete iTitleBarTopTile; + iTitleBarTopTile = 0; + + delete aTitleBarTile; + aTitleBarTile = 0; + + delete iTitleBarTile; + iTitleBarTile = 0; + + pixmaps_created = false; +} +////////////////////////////////////////////////////////////////////////////// +// init() +// ------ +// Actual initializer for class + +void polyesterClient::init() { + createMainWidget( WResizeNoErase | WRepaintNoErase); + widget()->installEventFilter(this); + handlebar = frameSize < 4 ? 4 - frameSize : 0; + + // for flicker-free redraws + widget()->setBackgroundMode(NoBackground); + + create_pixmaps(); + _resetLayout(); + +} +void polyesterClient::_resetLayout() +{ + // basic layout: + // _______________________________________________________________ + // | topSpacer | + // |_______________________________________________________________| + // | leftTitleSpacer | btns | titlebar | bts | rightTitleSpacer | + // |_________________|______|_____________|_____|__________________| + // | decoSpacer | + // |_______________________________________________________________| + // | | | | + // | | windowWrapper | | + // | | | | + // |leftSpacer rightSpacer| + // |_|___________________________________________________________|_| + // | bottomSpacer | + // |_______________________________________________________________| + // + if (!::factory->initialized()) return; + + delete mainLayout_; + delete titleLayout_; + delete topSpacer_; + delete titleSpacer_; + delete leftTitleSpacer_; + delete rightTitleSpacer_; + delete decoSpacer_; + delete leftSpacer_; + delete rightSpacer_; + delete bottomSpacer_; + delete windowSpacer_; + + mainLayout_ = new TQVBoxLayout(widget()); + // title + titleLayout_ = new TQHBoxLayout(); + TQHBoxLayout *windowLayout_ = new TQHBoxLayout(); + + + topSpacer_ = new TQSpacerItem(1, frameSize, TQSizePolicy::Expanding, TQSizePolicy::Fixed); + titlebar_ = new TQSpacerItem(1, s_titleHeight, + TQSizePolicy::Expanding, TQSizePolicy::Fixed); + leftTitleSpacer_ = new TQSpacerItem(frameSize, s_titleHeight, + TQSizePolicy::Fixed, TQSizePolicy::Fixed); + rightTitleSpacer_ = new TQSpacerItem(frameSize, s_titleHeight, + TQSizePolicy::Fixed, TQSizePolicy::Fixed); + decoSpacer_ = new TQSpacerItem(1, frameSize, TQSizePolicy::Expanding, TQSizePolicy::Fixed); + leftSpacer_ = new TQSpacerItem(frameSize, 1, + TQSizePolicy::Fixed, TQSizePolicy::Expanding); + rightSpacer_ = new TQSpacerItem(frameSize, 1, + TQSizePolicy::Fixed, TQSizePolicy::Expanding); + bottomSpacer_ = new TQSpacerItem(1, frameSize, + TQSizePolicy::Expanding, TQSizePolicy::Fixed); + + // sizeof(...) is calculated at compile time + memset(button, 0, sizeof(polyesterButton *) * ButtonTypeCount); + + // message in preview widget + if (isPreview()) { + windowLayout_->addWidget( + new TQLabel( i18n("<b><center>Polyester Preview</center></b>"), widget() ), 1 ); + } else { + windowLayout_->addItem(new TQSpacerItem(0, 0)); + } + + // setup titlebar buttons + for (int n=0; n<ButtonTypeCount; n++) + button[n] = 0; + //Deal with the title and buttons + titleLayout_->addItem(leftTitleSpacer_); + + if( !::factory->noModalButtons() || !isModal() || isResizable()) + addButtons(titleLayout_, + options()->customButtonPositions() ? options()->titleButtonsLeft() : TQString(default_left), + buttonSize); + titleLayout_->addItem(titlebar_); + if( !::factory->noModalButtons() || !isModal() || isResizable()) + addButtons(titleLayout_, + options()->customButtonPositions() ? options()->titleButtonsRight() : TQString(default_right), + buttonSize); + titleLayout_->addItem(rightTitleSpacer_); + + //Mid - left side, middle contents and right side + TQHBoxLayout * midLayout_ = new TQHBoxLayout(); + midLayout_->addItem(leftSpacer_); + midLayout_->addLayout(windowLayout_); + midLayout_->addItem(rightSpacer_); + + //Layout order + mainLayout_->addItem( topSpacer_ ); + mainLayout_->addLayout( titleLayout_ ); + mainLayout_->addItem( decoSpacer_ ); + mainLayout_->addLayout( midLayout_ ); + mainLayout_->addItem( bottomSpacer_ ); + + // connections + //TODO: probably these two connections could be removed + // connect(this, TQ_SIGNAL(keepAboveChanged(bool)), TQ_SLOT(keepAboveChange(bool))); + // connect(this, TQ_SIGNAL(keepBelowChanged(bool)), TQ_SLOT(keepBelowChange(bool))); +} + +////////////////////////////////////////////////////////////////////////////// +// addButtons() +// ------------ +// Add buttons to title layout + +void polyesterClient::addButtons(TQBoxLayout *layout, const TQString& s, int button_size) { + TQString tip; + if (s.length() > 0) { + for (unsigned n=0; n < s.length(); n++) { + switch (s[n]) { + case 'M': // Menu button + if (!button[ButtonMenu]) { + button[ButtonMenu] = + new polyesterButton(this, "splat.png", i18n("Menu"),ButtonMenu,button_size,::factory->squareButton()); + connect(button[ButtonMenu], TQ_SIGNAL(pressed()), this, TQ_SLOT(menuButtonPressed())); + connect(button[ButtonMenu], TQ_SIGNAL(released()), this, TQ_SLOT(menuButtonReleased())); + layout->addWidget(button[ButtonMenu]); + if (n < s.length()-1) layout->addSpacing(1); + } + break; + + case 'S': // Sticky button + if (!button[ButtonSticky]) { + if (isOnAllDesktops()) { + tip = i18n("Un-Sticky"); + } else { + tip = i18n("Sticky"); + } + button[ButtonSticky] = + new polyesterButton(this, "circle.png", tip, ButtonSticky, button_size,::factory->squareButton(), true); + connect(button[ButtonSticky], TQ_SIGNAL(clicked()), + this, TQ_SLOT(toggleOnAllDesktops())); + layout->addWidget(button[ButtonSticky]); + if (n < s.length()-1) layout->addSpacing(1); + } + break; + + case 'H': // Help button + if ((!button[ButtonHelp]) && providesContextHelp()) { + button[ButtonHelp] = + new polyesterButton(this, "help.png", i18n("Help"), ButtonHelp, button_size, ::factory->squareButton()); + connect(button[ButtonHelp], TQ_SIGNAL(clicked()), + this, TQ_SLOT(showContextHelp())); + layout->addWidget(button[ButtonHelp]); + if (n < s.length()-1) layout->addSpacing(1); + } + break; + + case 'I': // Minimize button + if ((!button[ButtonMin]) && isMinimizable()) { + button[ButtonMin] = + new polyesterButton(this, "minimize.png", i18n("Minimize"), ButtonMin, button_size,::factory->squareButton()); + connect(button[ButtonMin], TQ_SIGNAL(clicked()), + this, TQ_SLOT(minimize())); + layout->addWidget(button[ButtonMin]); + if (n < s.length()-1) layout->addSpacing(1); + } + break; + + case 'A': // Maximize button + if ((!button[ButtonMax]) && isMaximizable()) { + if (maximizeMode() == MaximizeFull) { + tip = i18n("Restore"); + } else { + tip = i18n("Maximize"); + } + button[ButtonMax] = + new polyesterButton(this, "maximize.png", tip, ButtonMax, button_size,::factory->squareButton(), true); + connect(button[ButtonMax], TQ_SIGNAL(clicked()), + this, TQ_SLOT(maxButtonPressed())); + layout->addWidget(button[ButtonMax]); + if (n < s.length()-1) layout->addSpacing(1); + } + break; + + case 'X': // Close button + if ((!button[ButtonClose]) && isCloseable()) { + button[ButtonClose] = + new polyesterButton(this, "close.png", i18n("Close"), ButtonClose, button_size, ::factory->squareButton()); + connect(button[ButtonClose], TQ_SIGNAL(clicked()), + this, TQ_SLOT(closeWindow())); + layout->addWidget(button[ButtonClose]); + if (n < s.length()-1) layout->addSpacing(1); + } + break; + + case 'F': // Above button + if ((!button[ButtonAbove])) { + button[ButtonAbove] = + new polyesterButton(this, "keep_above.png", + i18n("Keep Above Others"), ButtonAbove, button_size, ::factory->squareButton(), true); + connect(button[ButtonAbove], TQ_SIGNAL(clicked()), + this, TQ_SLOT(aboveButtonPressed())); + layout->addWidget(button[ButtonAbove]); + if (n < s.length()-1) layout->addSpacing(1); + } + break; + + case 'B': // Below button + if ((!button[ButtonBelow])) { + button[ButtonBelow] = + new polyesterButton(this, "keep_below.png", + i18n("Keep Below Others"), ButtonBelow, button_size, ::factory->squareButton(), true); + connect(button[ButtonBelow], TQ_SIGNAL(clicked()), + this, TQ_SLOT(belowButtonPressed())); + layout->addWidget(button[ButtonBelow]); + if (n < s.length()-1) layout->addSpacing(1); + } + break; + + case 'L': // Shade button + if ((!button[ButtonShade && isShadeable()])) { + if ( isSetShade()) { + tip = i18n("Unshade"); + } else { + tip = i18n("Shade"); + } + button[ButtonShade] = + new polyesterButton(this, "splat.png", tip, ButtonShade, button_size, ::factory->squareButton(), true); + connect(button[ButtonShade], TQ_SIGNAL(clicked()), + this, TQ_SLOT(shadeButtonPressed())); + layout->addWidget(button[ButtonShade]); + if (n < s.length()-1) layout->addSpacing(1); + } + break; + + case '_': // Spacer item + layout->addSpacing(frameSize); + } + } + } +} + +////////////////////////////////////////////////////////////////////////////// +// activeChange() +// -------------- +// window active state has changed + +void polyesterClient::activeChange() { + for (int n=0; n<ButtonTypeCount; n++) + if (button[n]) + button[n]->reset(); + maskDirty = true; + widget()->repaint(false); +} + +////////////////////////////////////////////////////////////////////////////// +// captionChange() +// --------------- +// The title has changed + +void polyesterClient::captionChange() { + aDoubleBufferDirty = iDoubleBufferDirty = true; + widget()->repaint(titlebar_->geometry(), false); +} + +////////////////////////////////////////////////////////////////////////////// +// desktopChange() +// --------------- +// Called when desktop/sticky changes + +void polyesterClient::desktopChange() { + bool d = isOnAllDesktops(); + if (button[ButtonSticky]) { + TQToolTip::remove(button[ButtonSticky]); + TQToolTip::add(button[ButtonSticky], d ? i18n("Un-Sticky") : i18n("Sticky")); + button[ButtonSticky]->repaint(false); + } +} + +////////////////////////////////////////////////////////////////////////////// +// iconChange() +// ------------ +// The title has changed + +void polyesterClient::iconChange() { + if (button[ButtonMenu]) { + button[ButtonMenu]->repaint(false); + } +} + +////////////////////////////////////////////////////////////////////////////// +// maximizeChange() +// ---------------- +// Maximized state has changed + +void polyesterClient::maximizeChange() { + maskDirty = aDoubleBufferDirty = iDoubleBufferDirty = true; + bool m = (maximizeMode() == MaximizeFull); + if (button[ButtonMax]) { + TQToolTip::remove(button[ButtonMax]); + TQToolTip::add(button[ButtonMax], m ? i18n("Restore") : i18n("Maximize")); + button[ButtonMax]->repaint(false); + } +} + +////////////////////////////////////////////////////////////////////////////// +// shadeChange() +// ------------- +// Called when window shading changes + +void polyesterClient::shadeChange() { + bool s = isSetShade(); + if (button[ButtonShade]) { + TQToolTip::remove(button[ButtonShade]); + TQToolTip::add(button[ButtonShade], s ? i18n("Unshade") : i18n("Shade")); + button[ButtonShade]->repaint(false); + } +} + +////////////////////////////////////////////////////////////////////////////// +// TODO: probably these two functions can be removed +// keepAboveChange() +// ------------ +// The above state has changed + +void polyesterClient::keepAboveChange(bool a) { + if (button[ButtonAbove]) { + button[ButtonAbove]->setOn(a); + button[ButtonAbove]->repaint(false); + } +} + +////////////////////////////////////////////////////////////////////////////// +// keepBelowChange() +// ------------ +// The below state has changed + +void polyesterClient::keepBelowChange(bool b) { + if (button[ButtonBelow]) { + button[ButtonBelow]->setOn(b); + button[ButtonBelow]->repaint(false); + } +} + +////////////////////////////////////////////////////////////////////////////// +// borders() +// ---------- +// Get the size of the borders + +void polyesterClient::borders(int &left, int &right, int &top, int &bottom) const { + + if ((maximizeMode()==MaximizeFull) && !options()->moveResizeMaximizedWindows()) { + left = right = bottom = 0; + top = s_titleHeight; + + // update layout etc. + topSpacer_->changeSize(1, -1, TQSizePolicy::Expanding, TQSizePolicy::Fixed); + decoSpacer_->changeSize(1, 0, TQSizePolicy::Expanding, TQSizePolicy::Fixed); + leftSpacer_->changeSize(left, 1, TQSizePolicy::Fixed, TQSizePolicy::Expanding); + leftTitleSpacer_->changeSize(left, s_titleHeight, TQSizePolicy::Fixed, TQSizePolicy::Fixed); + rightSpacer_->changeSize(right, 1, TQSizePolicy::Fixed, TQSizePolicy::Expanding); + rightTitleSpacer_->changeSize(right, s_titleHeight, TQSizePolicy::Fixed, TQSizePolicy::Fixed); + bottomSpacer_->changeSize(1, bottom, TQSizePolicy::Expanding, TQSizePolicy::Fixed); + } else { + /*if the borders are rounded add more left and right borders*/ + if( roundedCorners ) + left = right = bottom = frameSize*2; + else + left = right = bottom = frameSize+1; + top = titleSize + (frameSize*2); + + // update layout etc. + topSpacer_->changeSize(1, frameSize, TQSizePolicy::Expanding, TQSizePolicy::Fixed); + decoSpacer_->changeSize(1, frameSize, TQSizePolicy::Expanding, TQSizePolicy::Fixed); + leftSpacer_->changeSize(left, 1, TQSizePolicy::Fixed, TQSizePolicy::Expanding); + leftTitleSpacer_->changeSize(left, s_titleHeight, TQSizePolicy::Fixed, TQSizePolicy::Fixed); + rightSpacer_->changeSize(right, 1, TQSizePolicy::Fixed, TQSizePolicy::Expanding); + rightTitleSpacer_->changeSize(right,s_titleHeight,TQSizePolicy::Fixed, TQSizePolicy::Fixed); + bottomSpacer_->changeSize(1, bottom, TQSizePolicy::Expanding, TQSizePolicy::Fixed); + } + widget()->layout()->activate(); +} + +////////////////////////////////////////////////////////////////////////////// +// resize() +// -------- +// Called to resize the window + +void polyesterClient::resize(const TQSize &size) { + widget()->resize(size); +} + +////////////////////////////////////////////////////////////////////////////// +// minimumSize() +// ------------- +// Return the minimum allowable size for this window + +TQSize polyesterClient::minimumSize() const { + return widget()->minimumSize(); +} + +////////////////////////////////////////////////////////////////////////////// +// mousePosition() +// --------------- +// Return logical mouse position + +KDecoration::Position polyesterClient::mousePosition(const TQPoint &point) const { + const int corner = 24; + Position pos; + int fs = frameSize + handlebar; + //int fs = ::factory->frameSize(); + + if (point.y() <= fs) { + // inside top frame + if (point.x() <= corner) + pos = PositionTopLeft; + else if (point.x() >= (width()-corner)) + pos = PositionTopRight; + else + pos = PositionTop; + } else if (point.y() >= (height()-fs*2)) { + // inside handle + if (point.x() <= corner) + pos = PositionBottomLeft; + else if (point.x() >= (width()-corner)) + pos = PositionBottomRight; + else + pos = PositionBottom; + } else if (point.x() <= fs ) { + // on left frame + if (point.y() <= corner) + pos = PositionTopLeft; + else if (point.y() >= (height()-corner)) + pos = PositionBottomLeft; + else + pos = PositionLeft; + } else if (point.x() >= width()-fs) { + // on right frame + if (point.y() <= corner) + pos = PositionTopRight; + else if (point.y() >= (height()-corner)) + pos = PositionBottomRight; + else + pos = PositionRight; + } else { + // inside the frame + pos = PositionCenter; + } + return pos; +} + +////////////////////////////////////////////////////////////////////////////// +// eventFilter() +// ------------- +// Event filter + +bool polyesterClient::eventFilter(TQObject *obj, TQEvent *e) { + if (obj != widget()) + return false; + + switch (e->type()) { + case TQEvent::MouseButtonDblClick: { + mouseDoubleClickEvent(static_cast<TQMouseEvent *>(e)); + return true; + } + case TQEvent::MouseButtonPress: { + processMousePressEvent(static_cast<TQMouseEvent *>(e)); + return true; + } + case TQEvent::Wheel: { + wheelEvent(static_cast< TQWheelEvent* >(e)); + return true; + } + case TQEvent::Paint: { + paintEvent(static_cast<TQPaintEvent *>(e)); + return true; + } + case TQEvent::Resize: { + resizeEvent(static_cast<TQResizeEvent *>(e)); + return true; + } + case TQEvent::Show: { + showEvent(static_cast<TQShowEvent *>(e)); + return true; + } + default: { + return false; + } + } + + return false; +} + +////////////////////////////////////////////////////////////////////////////// +// mouseDoubleClickEvent() +// ----------------------- +// Doubleclick on title + +void polyesterClient::mouseDoubleClickEvent(TQMouseEvent *e) { + if (titlebar_->geometry().contains(e->pos())) + titlebarDblClickOperation(); +} + +////////////////////////////////////////////////////////////////////////////// +// wheelEvent() +// ----------------------- +// Mousewheel over titlebar + +void polyesterClient::wheelEvent(TQWheelEvent * e) { +#if TDE_VERSION > TDE_MAKE_VERSION(3,4,3) +if (titleLayout_->geometry().contains(e->pos())) +titlebarMouseWheelOperation(e->delta()); +#endif +} + +////////////////////////////////////////////////////////////////////////////// +// paintEvent() +// ------------ +// Repaint the window + +void polyesterClient::paintEvent(TQPaintEvent* e) { + if (!::factory->initialized()) + { + return; + } + + //int frameSize = ::factory->frameSize(); + const uint maxCaptionLength = 200; // truncate captions longer than this! + // FIXME: truncate related to window size +//titlebar_->geometry().width()/(widget()->font().pointSize()); + TQString captionText(caption()); + if (captionText.length() > maxCaptionLength) { + captionText.truncate(maxCaptionLength); + captionText.append(" [...]"); + } + + + TQColor blackColor(black); + TQColor redColor(red); + TQColorGroup group,widgetGroup; + + bool active = isActive(); + + //doublebuffering everything to avoid the flicker + TQPainter finalPainter(widget()); + + //an ugly debug red border used to thest the speed... + //finalPainter.fillRect(e->rect(),red);return; + + // mask off which corners we dont want + // otherwise recycle the old buffer + /*if( doubleBuff.width()>0 ) + { + finalPainter.drawPixmap(0,0, doubleBuff); + finalPainter.end(); + return; + }*/ + if( maskDirty ) + updateMask(); + if( !(active?aDoubleBufferDirty:iDoubleBufferDirty) && ((active?activeBuff.width():inactiveBuff.width()) == widget()->width() )) + { + finalPainter.drawPixmap(0,0, active?activeBuff:inactiveBuff ); + finalPainter.end(); + return; + } + + + if( active ) + activeBuff = TQPixmap(widget()->width(), widget()->height()); + else + inactiveBuff = TQPixmap(widget()->width(), widget()->height()); + + TQPainter painter(active?&activeBuff:&inactiveBuff); + //get group information first + group = options()->colorGroup(KDecoration::ColorTitleBlend, active); + widgetGroup = widget()->colorGroup(); + + TQRect topRect( topSpacer_->geometry() ); + TQRect titleRect( titleLayout_->geometry() ); + TQRect textRect( titlebar_->geometry() ); + TQRect Rltitle( leftTitleSpacer_->geometry() ); + TQRect Rrtitle( rightTitleSpacer_->geometry() ); + TQRect Rdeco( decoSpacer_->geometry() ); + TQRect Rleft( leftSpacer_->geometry() ); + TQRect Rright( rightSpacer_->geometry() ); + TQRect Rbottom( bottomSpacer_->geometry() ); + TQRect tempRect; + + + /* + if(active) + { + tqDebug("topRect.y() = %i\tbottom() = %i",topRect.top(),topRect.bottom()); + tqDebug("titleRect.y() = %i\tbottom() = %i",titleRect.top(),titleRect.bottom()); + tqDebug("textRect.y() = %i\tbottom() = %i",textRect.top(),textRect.bottom()); + tqDebug("Rltitle.y() = %i\tbottom() = %i",Rltitle.top(),Rltitle.bottom()); + tqDebug("Rrtitle.y() = %i\tbottom() = %i",Rrtitle.top(),Rrtitle.bottom()); + tqDebug("Rdeco.y() = %i\tbottom() = %i",Rdeco.top(),Rdeco.bottom()); + tqDebug("Rleft.y() = %i\tbottom() = %i",Rleft.top(),Rleft.bottom()); + tqDebug("Rright.y() = %i\tbottom() = %i",Rright.top(),Rright.bottom()); + tqDebug("Rbottom.y() = %i\tbottom() = %i",Rbottom.top(),Rbottom.bottom()); + } + */ + + // top + painter.drawTiledPixmap(topRect, active ? *aTitleBarTopTile:*iTitleBarTopTile); + painter.drawTiledPixmap(titleRect.x(), + titleRect.y(), + titleRect.width(), + titleRect.height() + Rdeco.height(), + active ? *aTitleBarTile:*iTitleBarTile); + + textRect.setRect(textRect.x()+SIDETITLEMARGIN, + textRect.y(), + textRect.width()-SIDETITLEMARGIN*2, + textRect.height()); + + + //is the title text too long? + bool titleTooLong = false; + TQt::AlignmentFlags titleAlign = ::factory->titleAlign(); + const int gradientWidth = 60; + if( TQFontMetrics(widget()->font()).width(captionText) > (textRect.width() - gradientWidth) ) + { + titleTooLong = true; + titleAlign = TQt::AlignLeft; + } + + //we are shadowing title bar text only if there is some text + if(::factory->titleShadow() && textRect.width()>0 && textRect.height()>0) + { + TQPixmap textPixmap; + TQPainter tempPainter; + TQColor shadowColor; + + textPixmap = TQPixmap(textRect.width(), textRect.height()); + textPixmap.fill(TQColor(0,0,0)); + textPixmap.setMask( textPixmap.createHeuristicMask(TRUE) ); + tempPainter.begin(&textPixmap); + + + //shadow text + tempPainter.setFont(options()->font(isActive(), false)); + + tempPainter.setPen(white); + + tempPainter.drawText(1, 1, textRect.width(), textRect.height(), + titleAlign | AlignVCenter | TQt::SingleLine, + captionText); + tempPainter.end(); + + // make the cute blurred text shadow from Plastik engine + TQImage shadow; + ShadowEngine se; + + //deciding if the shadow will be black or white + if(tqGray(options()->color(KDecoration::ColorFont, isActive()).rgb()) > 150) + shadowColor = blackColor; + else + shadowColor = white; + + shadow = se.makeShadow(textPixmap, shadowColor); + + painter.drawImage(textRect, shadow); + + } + + // draw title text + painter.setFont(options()->font(isActive(), false)); + painter.setPen(options()->color(KDecoration::ColorFont, isActive())); + painter.drawText(textRect, + titleAlign | AlignVCenter | TQt::SingleLine, + captionText); + + // make title fade out when the caption is too long, veery slow but veery cool :-) + if( titleTooLong ) + { + int xGradient = textRect.right()-(gradientWidth-1); + + TQPixmap backLayerP = TQPixmap(gradientWidth, textRect.height()); + TQPainter layerPainter(&backLayerP); + layerPainter.drawTiledPixmap(backLayerP.rect(), active ? *aTitleBarTile:*iTitleBarTile); + layerPainter.end(); + TQImage backLayer = backLayerP.convertToImage(); + + TQImage textLayer = ( active ? + activeBuff.convertToImage(): + inactiveBuff.convertToImage() + ).copy( xGradient, textRect.y(), + gradientWidth, textRect.height() + ); + KImageEffect::blend(backLayer, textLayer, KImageEffect::HorizontalGradient); + painter.drawImage(xGradient, textRect.y(), backLayer); + + } + + //left of buttons and title + painter.drawTiledPixmap(Rltitle.x(), + Rltitle.y(), + Rltitle.width(), + Rltitle.height()+Rdeco.height(), + active ? *aTitleBarTile:*iTitleBarTile); + + //left 3d effect + painter.drawTiledPixmap(Rltitle.x(), + Rltitle.y(), + 2, + Rltitle.height()+Rdeco.height(), + active ? *aTitleBarTopTile:*iTitleBarTopTile); + + // left mid layout + painter.fillRect(Rleft,widgetGroup.background()); + + // right of buttons and title + painter.drawTiledPixmap(Rrtitle.x(), + Rrtitle.y(), + Rrtitle.width(), + Rrtitle.height()+Rdeco.height(), + active ? *aTitleBarTile:*iTitleBarTile); + //right 3d effect + painter.drawTiledPixmap(width()-2, + Rltitle.y(), + 2, + Rltitle.height()+Rdeco.height(), + active ? *aTitleBarTopTile:*iTitleBarTopTile); + + // right mid layout + painter.fillRect(Rright,widgetGroup.background()); + + // bottom + /* + if(isShade()) + { + frame.setRect(0,::factory->titleSize()+FRAMESIZE, width(), FRAMESIZE); + } + else + { + frame.setRect(0, height() - (FRAMESIZE*2), width(), (FRAMESIZE*2)); + } + */ + painter.fillRect(Rbottom, KDecoration::options()->color(ColorTitleBlend, active));//widgetGroup.background()); + + //if the window is maximized the border is invisible + if( (maximizeMode()==MaximizeFull) && !options()->moveResizeMaximizedWindows() ) + painter.setPen(KDecoration::options()->color(ColorTitleBar, active)); + else + painter.setPen(group.background().dark(150)); + + // outline outside the frame but not the corners if they are rounded + tempRect = widget()->rect(); + painter.drawRect(tempRect); + + if(roundedCorners && !maximizeMode()) { + // local temp right and bottom + int r(width()); + painter.setPen(group.background().dark(150)); + painter.drawPoint(4, 1); + painter.drawPoint(3, 1); + painter.drawPoint(2, 2); + painter.drawPoint(1, 3); + painter.drawPoint(1, 4); + painter.drawPoint(r - 5, 1); + painter.drawPoint(r - 4, 1); + painter.drawPoint(r - 3, 2); + painter.drawPoint(r - 2, 3); + painter.drawPoint(r - 2, 4); + + painter.setPen(KDecoration::options()->color(ColorTitleBar, active).light(160)); + painter.drawPoint(4, 2); + painter.drawPoint(3, 2); + painter.drawPoint(2, 3); + painter.drawPoint(2, 4); + + //painter.setPen(KDecoration::options()->color(ColorTitleBlend, active)); + painter.drawPoint(r - 5, 2); + painter.drawPoint(r - 4, 2); + painter.drawPoint(r - 3, 3); + painter.drawPoint(r - 3, 4); + } + + // finally copy the buffer into the widget + //finalPainter.begin(doubleBuff); + finalPainter.drawPixmap(0,0, active?activeBuff:inactiveBuff); + finalPainter.end(); + + if( active ) + aDoubleBufferDirty = false; + else + iDoubleBufferDirty = false; +} + +////////////////////////////////////////////////////////////////////////////// +// updateMask() +// ------------ +// update the frame mask +void polyesterClient::updateMask() { + + if ( (!options()->moveResizeMaximizedWindows() && maximizeMode() & MaximizeFull ) ) + { + setMask(TQRegion(widget()->rect())); + return; + } + + int r(width()); + int b(height()); + TQRegion mask; + + mask=TQRegion(widget()->rect()); + mask=TQRegion( 0, 0, r, b ); + + // Remove top-left corner. + if( roundedCorners && + maximizeMode() != KDecorationDefines::MaximizeFull ) + { + mask -= TQRegion(0, 0, 5, 1); + mask -= TQRegion(0, 1, 3, 1); + mask -= TQRegion(0, 2, 2, 1); + mask -= TQRegion(0, 3, 1, 2); + mask -= TQRegion(r - 5, 0, 5, 1); + mask -= TQRegion(r - 3, 1, 3, 1); + mask -= TQRegion(r - 2, 2, 2, 1); + mask -= TQRegion(r - 1, 3, 1, 2); + } + //always remove one corner pixel so it simulates a soft corner like plastik + mask -= TQRegion(0,0,1,1); + mask -= TQRegion(r-1,0,1,1); + mask -= TQRegion(0, b-1, 1,1); + mask -= TQRegion(r-1,b-1,1,1); + + setMask(mask, 1); + + maskDirty = false; +} + +////////////////////////////////////////////////////////////////////////////// +// resizeEvent() +// ------------- +// Window is being resized + +void polyesterClient::resizeEvent(TQResizeEvent *) { + maskDirty = aDoubleBufferDirty = iDoubleBufferDirty = true; + if (widget()->isShown()) { + TQRegion region = widget()->rect(); + region = region.subtract(titlebar_->geometry()); + widget()->erase(region); + } + updateMask(); +} + +////////////////////////////////////////////////////////////////////////////// +// showEvent() +// ----------- +// Window is being shown + +void polyesterClient::showEvent(TQShowEvent *) { + widget()->repaint(); + updateMask(); +} + +////////////////////////////////////////////////////////////////////////////// +// maxButtonPressed() +// ----------------- +// Max button was pressed + +void polyesterClient::maxButtonPressed() { + if (button[ButtonMax]) { +#if KDE_IS_VERSION(3, 3, 0) + maximize(button[ButtonMax]->lastMousePress()); +#else + + switch (button[ButtonMax]->lastMousePress()) { + case MidButton: + maximize(maximizeMode() ^ MaximizeVertical); + break; + case RightButton: + maximize(maximizeMode() ^ MaximizeHorizontal); + break; + default: + (maximizeMode() == MaximizeFull) ? maximize(MaximizeRestore) + : maximize(MaximizeFull); + } +#endif + + } +} + +////////////////////////////////////////////////////////////////////////////// +// shadeButtonPressed() +// ----------------- +// Shade button was pressed + +void polyesterClient::shadeButtonPressed() { + if (button[ButtonShade]) { + setShade( !isSetShade()); + } +} + +////////////////////////////////////////////////////////////////////////////// +// aboveButtonPressed() +// ----------------- +// Above button was pressed + +void polyesterClient::aboveButtonPressed() { + if (button[ButtonAbove]) { + setKeepAbove( !keepAbove()); + } +} + +////////////////////////////////////////////////////////////////////////////// +// belowButtonPressed() +// ----------------- +// Below button was pressed + +void polyesterClient::belowButtonPressed() { + if (button[ButtonBelow]) { + setKeepBelow( !keepBelow()); + } +} + +////////////////////////////////////////////////////////////////////////////// +// menuButtonPressed() +// ------------------- +// Menu button was pressed (popup the menu) + +void polyesterClient::menuButtonPressed() { + static TQTime* t = NULL; + static polyesterClient* lastClient = NULL; + if (t == NULL) + t = new TQTime; + bool dbl = (lastClient==this && t->elapsed() <= TQApplication::doubleClickInterval()); + lastClient = this; + t->start(); + //if (button[ButtonMenu] && !dbl && !::factory->menuClosed()) { + if ( !dbl || !::factory->menuClosed()) { + TQPoint p(button[ButtonMenu]->rect().bottomLeft().x(), + button[ButtonMenu]->rect().bottomLeft().y()); + KDecorationFactory* f = factory(); + showWindowMenu(button[ButtonMenu]->mapToGlobal(p)); + if (!f->exists(this)) + return; // decoration was destroyed + button[ButtonMenu]->setDown(false); + } + else + { + closing = true; + } +} + +void polyesterClient::menuButtonReleased() +{ + if(closing) + { + closeWindow(); + } +} + +#include "polyester.moc" |