00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <klocale.h>
00024 #include <kpixmap.h>
00025 #include <kpixmapeffect.h>
00026 #include <kapplication.h>
00027
00028 #include <qbitmap.h>
00029 #include <qdatetime.h>
00030 #include <qfontmetrics.h>
00031 #include <qimage.h>
00032 #include <qlabel.h>
00033 #include <qlayout.h>
00034 #include <qpainter.h>
00035 #include <qpixmap.h>
00036 #include <qdesktopwidget.h>
00037
00038 #include "plastikclient.h"
00039 #include "plastikclient.moc"
00040 #include "plastikbutton.h"
00041 #include "misc.h"
00042 #include "shadow.h"
00043
00044
00045 static const int TOPMARGIN = 4;
00046 static const int DECOHEIGHT = 2;
00047 static const int SIDETITLEMARGIN = 6;
00048
00049
00050 const char default_left[] = "M";
00051 const char default_right[] = "HIAX";
00052
00053 namespace KWinPlastik
00054 {
00055
00056 PlastikClient::PlastikClient(KDecorationBridge* bridge, KDecorationFactory* factory)
00057 : KDecoration (bridge, factory),
00058 mainLayout_(0),
00059 topSpacer_(0), titleSpacer_(0), leftTitleSpacer_(0), rightTitleSpacer_(0),
00060 decoSpacer_(0), leftSpacer_(0), rightSpacer_(0), bottomSpacer_(0),
00061 aCaptionBuffer(0), iCaptionBuffer(0),
00062 aTitleBarTile(0), iTitleBarTile(0), aTitleBarTopTile(0), iTitleBarTopTile(0),
00063 pixmaps_created(false),
00064 captionBufferDirty(true),
00065 closing(false),
00066 s_titleHeight(0),
00067 s_titleFont(QFont() )
00068 { }
00069
00070 PlastikClient::~PlastikClient()
00071 {
00072 delete_pixmaps();
00073
00074 delete aCaptionBuffer;
00075 delete iCaptionBuffer;
00076
00077 for (int n=0; n<NumButtons; n++) {
00078 if (m_button[n]) delete m_button[n];
00079 }
00080 }
00081
00082 void PlastikClient::init()
00083 {
00084 connect(this, SIGNAL(keepAboveChanged(bool) ), SLOT(keepAboveChange(bool) ) );
00085 connect(this, SIGNAL(keepBelowChanged(bool) ), SLOT(keepBelowChange(bool) ) );
00086
00087 s_titleHeight = isTool() ?
00088 PlastikHandler::titleHeightTool()
00089 : PlastikHandler::titleHeight();
00090 s_titleFont = isTool() ?
00091 PlastikHandler::titleFontTool()
00092 : PlastikHandler::titleFont();
00093
00094 createMainWidget(WNoAutoErase);
00095
00096 widget()->installEventFilter( this );
00097
00098
00099 widget()->setBackgroundMode(NoBackground);
00100
00101 _resetLayout();
00102
00103 create_pixmaps();
00104
00105 aCaptionBuffer = new QPixmap();
00106 iCaptionBuffer = new QPixmap();
00107 captionBufferDirty = true;
00108 widget()->update(titleSpacer_->geometry());
00109 }
00110
00111 const int SUPPORTED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask
00112 | NET::ToolbarMask | NET::MenuMask | NET::DialogMask | NET::OverrideMask | NET::TopMenuMask
00113 | NET::UtilityMask | NET::SplashMask;
00114
00115 bool PlastikClient::isTool()
00116 {
00117 NET::WindowType type = windowType( SUPPORTED_WINDOW_TYPES_MASK );
00118 return ((type==NET::Toolbar)||(type==NET::Utility)||(type==NET::Menu));
00119 }
00120
00121 void PlastikClient::resizeEvent()
00122 {
00123 doShape();
00124
00125
00126
00127
00128 }
00129
00130 void PlastikClient::paintEvent(QPaintEvent*)
00131 {
00132 if (!PlastikHandler::initialized()) return;
00133
00134 if (captionBufferDirty)
00135 update_captionBuffer();
00136
00137 bool active = isActive();
00138
00139 QPainter painter(widget() );
00140
00141 QRegion mask;
00142
00143
00144 const QColor windowContour = PlastikHandler::getColor(WindowContour, active);
00145 const QColor deco = PlastikHandler::getColor(TitleGradientTo, active);
00146 const QColor border = PlastikHandler::getColor(Border, active);
00147 const QColor highlightTop = PlastikHandler::getColor(TitleHighlightTop, active);
00148 const QColor highlightTitleLeft = alphaBlendColors(deco,
00149 PlastikHandler::getColor(SideHighlightLeft, active), 150);
00150 const QColor highlightTitleRight = alphaBlendColors(deco,
00151 PlastikHandler::getColor(SideHighlightRight, active), 150);
00152 const QColor highlightLeft = alphaBlendColors(border,
00153 PlastikHandler::getColor(SideHighlightLeft, active), 150);
00154 const QColor highlightRight = alphaBlendColors(border,
00155 PlastikHandler::getColor(SideHighlightRight, active), 150);
00156 const QColor highlightBottom = alphaBlendColors(border,
00157 PlastikHandler::getColor(SideHighlightBottom, active), 150);
00158 const QColor filledCorner = QColor(0,0,0);
00159
00160 QRect Rtop(topSpacer_->geometry());
00161 QRect Rtitle(titleSpacer_->geometry());
00162 QRect Rltitle(leftTitleSpacer_->geometry());
00163 QRect Rrtitle(rightTitleSpacer_->geometry());
00164 QRect Rdeco(decoSpacer_->geometry());
00165 QRect Rleft(leftSpacer_->geometry());
00166 QRect Rright(rightSpacer_->geometry());
00167 QRect Rbottom(bottomSpacer_->geometry());
00168 QRect tempRect;
00169
00170
00171 if(Rtop.height() > 0)
00172 {
00173 painter.setPen(windowContour );
00174 painter.drawLine(Rtop.left()+2, Rtop.top(), Rtop.right()-2, Rtop.top() );
00175 painter.drawPoint(Rtop.left()+1, Rtop.top()+1 );
00176 painter.drawPoint(Rtop.right()-1, Rtop.top()+1 );
00177 painter.drawLine(Rtop.left(), Rtop.top()+2, Rtop.left(), Rtop.bottom() );
00178 painter.drawLine(Rtop.right(), Rtop.top()+2, Rtop.right(), Rtop.bottom() );
00179 painter.setPen(highlightTop );
00180 painter.drawLine(Rtop.left()+3, Rtop.top()+1, Rtop.right()-3, Rtop.top()+1 );
00181
00182 painter.setPen(alphaBlendColors(highlightTop, windowContour, 150) );
00183 painter.drawPoint(Rtop.left()+2, Rtop.top()+1);
00184 painter.drawPoint(Rtop.right()-2, Rtop.top()+1);
00185 painter.setPen(alphaBlendColors(highlightTitleLeft, windowContour, 150) );
00186 painter.drawPoint(Rtop.left()+1, Rtop.top()+2);
00187 painter.setPen(alphaBlendColors(highlightTitleRight, windowContour, 150) );
00188 painter.drawPoint(Rtop.right()-1, Rtop.top()+2);
00189
00190 painter.setPen(highlightTitleLeft);
00191 painter.drawLine(Rtop.left()+1, Rtop.top()+3, Rtop.left()+1, Rtop.bottom() );
00192 painter.setPen(highlightTitleRight);
00193 painter.drawLine(Rtop.right()-1, Rtop.top()+3, Rtop.right()-1, Rtop.bottom() );
00194
00195 painter.drawTiledPixmap(Rtop.left()+2, Rtop.top()+2,
00196 Rtop.width()-2*2, Rtop.height()-2,
00197 active ? *aTitleBarTopTile : *iTitleBarTopTile );
00198
00199 painter.setPen(filledCorner);
00200 painter.drawLine(Rtop.left(), Rtop.top(), Rtop.left()+1, Rtop.top() );
00201 painter.drawPoint(Rtop.left(), Rtop.top()+1);
00202 painter.drawLine(Rtop.right(), Rtop.top(), Rtop.right()-1, Rtop.top() );
00203 painter.drawPoint(Rtop.right(), Rtop.top()+1);
00204 }
00205
00206
00207 if(Rltitle.width() > 0)
00208 {
00209 painter.setPen(windowContour );
00210 painter.drawLine(Rltitle.left(), Rltitle.top(),
00211 Rltitle.left(), Rltitle.bottom() );
00212 painter.setPen(highlightTitleLeft);
00213 painter.drawLine(Rltitle.left()+1, Rltitle.top(),
00214 Rltitle.left()+1, Rltitle.bottom() );
00215
00216 painter.drawTiledPixmap(Rltitle.left()+2, Rltitle.top(), Rltitle.width()-2, Rltitle.height(),
00217 active ? *aTitleBarTile : *iTitleBarTile );
00218 }
00219
00220
00221 painter.drawTiledPixmap(Rltitle.right()+1, Rtitle.top(),
00222 (Rtitle.left()-1)-Rltitle.right(), Rtitle.height(),
00223 active ? *aTitleBarTile : *iTitleBarTile );
00224
00225
00226
00227 if(Rrtitle.width() > 0)
00228 {
00229 painter.setPen(windowContour );
00230 painter.drawLine(Rrtitle.right(), Rrtitle.top(),
00231 Rrtitle.right(), Rrtitle.bottom() );
00232 painter.setPen(highlightTitleRight);
00233 painter.drawLine(Rrtitle.right()-1, Rrtitle.top(),
00234 Rrtitle.right()-1, Rrtitle.bottom() );
00235
00236 painter.drawTiledPixmap(Rrtitle.left(), Rrtitle.top(), Rrtitle.width()-2, Rrtitle.height(),
00237 active ? *aTitleBarTile : *iTitleBarTile );
00238 }
00239
00240
00241 painter.drawTiledPixmap(Rtitle.right()+1, Rtitle.top(),
00242 (Rrtitle.left()-1)-Rtitle.right(), Rtitle.height(),
00243 active ? *aTitleBarTile : *iTitleBarTile );
00244
00245
00246 QPixmap *titleBfrPtr = active ? aCaptionBuffer : iCaptionBuffer;
00247 if(Rtitle.width() > 0 && titleBfrPtr != 0)
00248 {
00249 const int titleMargin = 5;
00250
00251 int tX, tW;
00252 switch (PlastikHandler::titleAlign())
00253 {
00254
00255 case Qt::AlignHCenter:
00256 tX = (titleBfrPtr->width() > Rtitle.width()-2*titleMargin) ?
00257 (Rtitle.left()+titleMargin)
00258 : Rtitle.left()+(Rtitle.width()- titleBfrPtr->width() )/2;
00259 tW = (titleBfrPtr->width() > Rtitle.width()-2*titleMargin) ?
00260 (Rtitle.width()-2*titleMargin)
00261 : titleBfrPtr->width();
00262 break;
00263
00264 case Qt::AlignRight:
00265 tX = (titleBfrPtr->width() > Rtitle.width()-2*titleMargin) ?
00266 (Rtitle.left()+titleMargin)
00267 : Rtitle.right()-titleMargin-titleBfrPtr->width();
00268 tW = (titleBfrPtr->width() > Rtitle.width()-2*titleMargin) ?
00269 (Rtitle.width()-2*titleMargin)
00270 : titleBfrPtr->width();
00271 break;
00272
00273 default:
00274 tX = (Rtitle.left()+titleMargin);
00275 tW = (titleBfrPtr->width() > Rtitle.width()-2*titleMargin) ?
00276 (Rtitle.width()-2*titleMargin)
00277 : titleBfrPtr->width();
00278 }
00279
00280 if(tW > 0)
00281 {
00282 painter.drawTiledPixmap(tX, Rtitle.top(),
00283 tW, Rtitle.height(),
00284 *titleBfrPtr);
00285 }
00286
00287 painter.drawTiledPixmap(Rtitle.left(), Rtitle.top(),
00288 tX-Rtitle.left(), Rtitle.height(),
00289 active ? *aTitleBarTile : *iTitleBarTile);
00290
00291 painter.drawTiledPixmap(tX+tW, Rtitle.top(),
00292 Rtitle.right()-(tX+tW)+1, Rtitle.height(),
00293 active ? *aTitleBarTile : *iTitleBarTile);
00294 }
00295 titleBfrPtr = 0;
00296
00297
00298 if(Rdeco.height() > 0)
00299 {
00300 int l;
00301 if(Rleft.width() != 0)
00302 l = Rdeco.left()+2;
00303 else
00304 l = Rdeco.left();
00305 int r;
00306 if(Rright.width() != 0)
00307 r = Rdeco.right()-2;
00308 else
00309 r = Rdeco.right();
00310
00311 painter.setPen(deco );
00312 painter.drawLine(l, Rdeco.bottom(), r, Rdeco.bottom() );
00313 painter.drawLine(l, Rdeco.top(), r, Rdeco.top() );
00314 if(Rleft.width() != 0) {
00315 painter.setPen(windowContour );
00316 painter.drawLine(Rdeco.left(), Rdeco.top(), Rdeco.left(), Rdeco.bottom() );
00317 painter.setPen(highlightTitleLeft);
00318 painter.drawLine(Rdeco.left()+1, Rdeco.top(),
00319 Rdeco.left()+1, Rdeco.bottom() );
00320 }
00321 if(Rright.width() != 0) {
00322 painter.setPen(windowContour );
00323 painter.drawLine(Rdeco.right(), Rdeco.top(), Rdeco.right(), Rdeco.bottom() );
00324 painter.setPen(highlightTitleRight);
00325 painter.drawLine(Rdeco.right()-1, Rdeco.top(),
00326 Rdeco.right()-1, Rdeco.bottom() );
00327 }
00328 }
00329
00330
00331 if(Rleft.width() > 0 && Rleft.height() > 0)
00332 {
00333 painter.setPen(windowContour );
00334 painter.drawLine(Rleft.left(), Rleft.top(),
00335 Rleft.left(), Rleft.bottom() );
00336 painter.setPen(highlightLeft );
00337 painter.drawLine(Rleft.left()+1, Rleft.top(),
00338 Rleft.left()+1, Rleft.bottom() );
00339 if(Rleft.width() > 2) {
00340 tempRect.setCoords(Rleft.left()+2, Rleft.top(),
00341 Rleft.right(), Rleft.bottom() );
00342 painter.fillRect(tempRect, border );
00343 }
00344 }
00345
00346
00347 if(Rright.width() > 0 && Rright.height() > 0)
00348 {
00349 painter.setPen(windowContour );
00350 painter.drawLine(Rright.right(), Rright.top(),
00351 Rright.right(), Rright.bottom() );
00352 painter.setPen(highlightRight );
00353 painter.drawLine(Rright.right()-1, Rright.top(),
00354 Rright.right()-1, Rright.bottom() );
00355 if(Rright.width() > 2) {
00356 tempRect.setCoords(Rright.left(), Rright.top(),
00357 Rright.right()-2, Rright.bottom() );
00358 painter.fillRect(tempRect, border );
00359 }
00360 }
00361
00362
00363 if(Rbottom.height() > 0)
00364 {
00365 painter.setPen(windowContour );
00366 painter.drawLine(Rbottom.left()+1, Rbottom.bottom(),
00367 Rbottom.right()-1, Rbottom.bottom() );
00368
00369 if(Rleft.width() != 0) {
00370 painter.setPen(windowContour );
00371 painter.drawLine(Rbottom.left(), Rbottom.top(),
00372 Rbottom.left(), Rbottom.bottom()-1 );
00373 painter.setPen(highlightLeft );
00374 painter.drawLine(Rbottom.left()+1, Rbottom.top(),
00375 Rbottom.left()+1, Rbottom.bottom()-2 );
00376
00377 painter.setPen(alphaBlendColors(border, windowContour, 110) );
00378 painter.drawPoint(Rbottom.left()+1, Rbottom.bottom()-1);
00379 }
00380 if(Rright.width() != 0) {
00381 painter.setPen(windowContour );
00382 painter.drawLine(Rbottom.right(), Rbottom.top(),
00383 Rbottom.right(), Rbottom.bottom()-1 );
00384 painter.setPen(highlightRight );
00385 painter.drawLine(Rbottom.right()-1, Rbottom.top(),
00386 Rbottom.right()-1, Rbottom.bottom()-2 );
00387
00388 painter.setPen(alphaBlendColors(border, windowContour, 110) );
00389 painter.drawPoint(Rbottom.right()-1, Rbottom.bottom()-1);
00390 }
00391
00392 painter.setPen(filledCorner);
00393 painter.drawPoint(Rbottom.left(), Rbottom.bottom());
00394 painter.drawPoint(Rbottom.right(), Rbottom.bottom());
00395
00396 int l;
00397 if(Rleft.width() != 0)
00398 l = Rbottom.left()+2;
00399 else
00400 l = Rbottom.left();
00401 int r;
00402 if(Rright.width() != 0)
00403 r = Rbottom.right()-2;
00404 else
00405 r = Rbottom.right();
00406
00407 painter.setPen(highlightBottom );
00408 painter.drawLine(l, Rbottom.bottom()-1,
00409 r, Rbottom.bottom()-1 );
00410
00411 tempRect.setCoords(l, Rbottom.top(), r, Rbottom.bottom()-2);
00412 painter.fillRect(tempRect, border );
00413 }
00414 }
00415
00416 void PlastikClient::mouseDoubleClickEvent(QMouseEvent *e)
00417 {
00418 if (titleSpacer_->geometry().contains(e->pos()))
00419 titlebarDblClickOperation();
00420 }
00421
00422 void PlastikClient::doShape()
00423 {
00424 int w = widget()->width();
00425 int h = widget()->height();
00426 int r(w);
00427 int b(h);
00428 bool tl=true,tr=true,bl=true,br=true;
00429
00430 QRegion mask(0, 0, w, h);
00431
00432 QDesktopWidget *desktop=KApplication::desktop();
00433
00434
00435 if(topSpacer_->geometry().height() == 0) tl = tr = false;
00436 if(leftTitleSpacer_->geometry().width() == 0) tl = false;
00437 if(rightTitleSpacer_->geometry().width() == 0) tr = false;
00438 if(bottomSpacer_->geometry().height() == 0) bl = br = false;
00439
00440
00441 for(int screen=desktop->numScreens()-1;screen>=0;--screen)
00442 {
00443 QRect fullscreen(desktop->screenGeometry(screen));
00444 QRect wcfullscreen(widget()->mapFromGlobal(fullscreen.topLeft()),
00445 widget()->mapFromGlobal(fullscreen.bottomRight()+QPoint(1,1)));
00446
00447 if(wcfullscreen.topLeft() ==QPoint(0,0)) tl = false;
00448 if(wcfullscreen.topRight() ==QPoint(w,0)) tr = false;
00449 if(wcfullscreen.bottomLeft() ==QPoint(0,h)) bl = false;
00450 if(wcfullscreen.bottomRight()==QPoint(w,h)) br = false;
00451 }
00452
00453 if(tl)
00454 {
00455 mask -= QRegion(0, 0, 1, 2);
00456 mask -= QRegion(1, 0, 1, 1);
00457 }
00458
00459 if(tr)
00460 {
00461 mask -= QRegion(r-1, 0, 1, 2);
00462 mask -= QRegion(r-2, 0, 1, 1);
00463 }
00464
00465 if(bl)
00466 {
00467 mask -= QRegion(0, b-1, 1, 1);
00468 }
00469
00470 if(br)
00471 {
00472 mask -= QRegion(r-1, b-1, 1, 1);
00473 }
00474
00475 setMask( mask );
00476 }
00477
00478 void PlastikClient::_resetLayout()
00479 {
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497 if (!PlastikHandler::initialized()) return;
00498
00499 delete mainLayout_;
00500
00501 delete topSpacer_;
00502 delete titleSpacer_;
00503 delete leftTitleSpacer_;
00504 delete rightTitleSpacer_;
00505 delete decoSpacer_;
00506 delete leftSpacer_;
00507 delete rightSpacer_;
00508 delete bottomSpacer_;
00509
00510 mainLayout_ = new QVBoxLayout(widget(), 0, 0);
00511
00512 topSpacer_ = new QSpacerItem(1, TOPMARGIN, QSizePolicy::Expanding, QSizePolicy::Fixed);
00513 titleSpacer_ = new QSpacerItem(1, s_titleHeight,
00514 QSizePolicy::Expanding, QSizePolicy::Fixed);
00515 leftTitleSpacer_ = new QSpacerItem(SIDETITLEMARGIN, s_titleHeight,
00516 QSizePolicy::Fixed, QSizePolicy::Fixed);
00517 rightTitleSpacer_ = new QSpacerItem(SIDETITLEMARGIN, s_titleHeight,
00518 QSizePolicy::Fixed, QSizePolicy::Fixed);
00519 decoSpacer_ = new QSpacerItem(1, DECOHEIGHT, QSizePolicy::Expanding, QSizePolicy::Fixed);
00520 leftSpacer_ = new QSpacerItem(PlastikHandler::borderSize(), 1,
00521 QSizePolicy::Fixed, QSizePolicy::Expanding);
00522 rightSpacer_ = new QSpacerItem(PlastikHandler::borderSize(), 1,
00523 QSizePolicy::Fixed, QSizePolicy::Expanding);
00524 bottomSpacer_ = new QSpacerItem(1, PlastikHandler::borderSize(),
00525 QSizePolicy::Expanding, QSizePolicy::Fixed);
00526
00527
00528 mainLayout_->addItem(topSpacer_);
00529
00530
00531 QHBoxLayout *titleLayout_ = new QHBoxLayout(mainLayout_, 0, 0);
00532
00533
00534 memset(m_button, 0, sizeof(PlastikButton *) * NumButtons);
00535
00536 titleLayout_->addItem(PlastikHandler::reverseLayout()?rightTitleSpacer_:leftTitleSpacer_);
00537 addButtons(titleLayout_,
00538 options()->customButtonPositions() ? options()->titleButtonsLeft() : QString(default_left),
00539 s_titleHeight-1);
00540 titleLayout_->addItem(titleSpacer_);
00541 addButtons(titleLayout_,
00542 options()->customButtonPositions() ? options()->titleButtonsRight() : QString(default_right),
00543 s_titleHeight-1);
00544 titleLayout_->addItem(PlastikHandler::reverseLayout()?leftTitleSpacer_:rightTitleSpacer_);
00545
00546
00547 mainLayout_->addItem(decoSpacer_);
00548
00549
00550 QHBoxLayout * midLayout = new QHBoxLayout(mainLayout_, 0, 0);
00551 midLayout->addItem(PlastikHandler::reverseLayout()?rightSpacer_:leftSpacer_);
00552 if( isPreview())
00553 midLayout->addWidget(new QLabel( i18n( "<center><b>Plastik preview</b></center>" ), widget()) );
00554 else
00555 midLayout->addItem( new QSpacerItem( 0, 0 ));
00556 midLayout->addItem(PlastikHandler::reverseLayout()?leftSpacer_:rightSpacer_);
00557
00558
00559 mainLayout_->addItem(bottomSpacer_);
00560
00561
00562 }
00563
00564 void PlastikClient::addButtons(QBoxLayout *layout, const QString& s, int buttonSize)
00565 {
00566 if (s.length() > 0) {
00567 for (unsigned n=0; n < s.length(); n++) {
00568 switch (s[n]) {
00569 case 'M':
00570 if (!m_button[MenuButton]){
00571 m_button[MenuButton] = new PlastikButton(this, "menu", i18n("Menu"), MenuButton, buttonSize, LeftButton|RightButton);
00572 connect(m_button[MenuButton], SIGNAL(pressed()), SLOT(menuButtonPressed()));
00573 connect(m_button[MenuButton], SIGNAL(released()), this, SLOT(menuButtonReleased()));
00574 layout->addWidget(m_button[MenuButton], 0, Qt::AlignHCenter | Qt::AlignTop);
00575 }
00576 break;
00577 case 'S':
00578 if (!m_button[OnAllDesktopsButton]){
00579 const bool oad = isOnAllDesktops();
00580 m_button[OnAllDesktopsButton] = new PlastikButton(this, "on_all_desktops",
00581 oad?i18n("Not on all desktops"):i18n("On all desktops"), OnAllDesktopsButton,
00582 buttonSize, true);
00583 m_button[OnAllDesktopsButton]->setOn( oad );
00584 connect(m_button[OnAllDesktopsButton], SIGNAL(clicked()), SLOT(toggleOnAllDesktops()));
00585 layout->addWidget(m_button[OnAllDesktopsButton], 0, Qt::AlignHCenter | Qt::AlignTop);
00586 }
00587 break;
00588 case 'H':
00589 if ((!m_button[HelpButton]) && providesContextHelp()){
00590 m_button[HelpButton] = new PlastikButton(this, "help", i18n("Help"), HelpButton, buttonSize);
00591 connect(m_button[HelpButton], SIGNAL(clicked()), SLOT(showContextHelp()));
00592 layout->addWidget(m_button[HelpButton], 0, Qt::AlignHCenter | Qt::AlignTop);
00593 }
00594 break;
00595 case 'I':
00596 if ((!m_button[MinButton]) && isMinimizable()){
00597 m_button[MinButton] = new PlastikButton(this, "minimize", i18n("Minimize"), MinButton, buttonSize);
00598 connect(m_button[MinButton], SIGNAL(clicked()), SLOT(minimize()));
00599 layout->addWidget(m_button[MinButton], 0, Qt::AlignHCenter | Qt::AlignTop);
00600 }
00601 break;
00602 case 'A':
00603 if ((!m_button[MaxButton]) && isMaximizable()){
00604 const bool max = maximizeMode()!=MaximizeRestore;
00605 m_button[MaxButton] = new PlastikButton(this, "maximize",
00606 max?i18n("Restore"):i18n("Maximize"), MaxButton, buttonSize,
00607 true, LeftButton|MidButton|RightButton);
00608 m_button[MaxButton]->setOn( max );
00609 connect(m_button[MaxButton], SIGNAL(clicked()), SLOT(slotMaximize()));
00610 layout->addWidget(m_button[MaxButton], 0, Qt::AlignHCenter | Qt::AlignTop);
00611 }
00612 break;
00613 case 'X':
00614 if ((!m_button[CloseButton]) && isCloseable()){
00615 m_button[CloseButton] = new PlastikButton(this, "close", i18n("Close"), CloseButton, buttonSize);
00616 connect(m_button[CloseButton], SIGNAL(clicked()), SLOT(closeWindow()));
00617 layout->addWidget(m_button[CloseButton], 0, Qt::AlignHCenter | Qt::AlignTop);
00618 }
00619 break;
00620 case 'F':
00621 if (!m_button[AboveButton]){
00622 bool above = keepAbove();
00623 m_button[AboveButton] = new PlastikButton(this, "above",
00624 above?i18n("Do not keep above others"):i18n("Keep above others"), AboveButton, buttonSize, true);
00625 m_button[AboveButton]->setOn( above );
00626 connect(m_button[AboveButton], SIGNAL(clicked()), SLOT(slotKeepAbove()));
00627 layout->addWidget(m_button[AboveButton], 0, Qt::AlignHCenter | Qt::AlignTop);
00628 }
00629 break;
00630 case 'B':
00631 if (!m_button[BelowButton]){
00632 bool below = keepBelow();
00633 m_button[BelowButton] = new PlastikButton(this, "below",
00634 below?i18n("Do not keep below others"):i18n("Keep below others"), BelowButton, buttonSize, true);
00635 m_button[BelowButton]->setOn( below );
00636 connect(m_button[BelowButton], SIGNAL(clicked()), SLOT(slotKeepBelow()));
00637 layout->addWidget(m_button[BelowButton], 0, Qt::AlignHCenter | Qt::AlignTop);
00638 }
00639 break;
00640 case 'L':
00641 if ((!m_button[ShadeButton]) && isShadeable()){
00642 bool shaded = isSetShade();
00643 m_button[ShadeButton] = new PlastikButton(this, "shade",
00644 shaded?i18n("Unshade"):i18n("Shade"), ShadeButton, buttonSize, true);
00645 m_button[ShadeButton]->setOn( shaded );
00646 connect(m_button[ShadeButton], SIGNAL(clicked()), SLOT(slotShade()));
00647 layout->addWidget(m_button[ShadeButton], 0, Qt::AlignHCenter | Qt::AlignTop);
00648 }
00649 break;
00650 case '_':
00651 layout->addSpacing(3);
00652 }
00653
00654
00655 if(n < (s.length()-1) )
00656 layout->addSpacing (1);
00657 }
00658 }
00659 }
00660
00661 void PlastikClient::captionChange()
00662 {
00663 captionBufferDirty = true;
00664 widget()->update(titleSpacer_->geometry());
00665 }
00666
00667 void PlastikClient::reset( unsigned long changed )
00668 {
00669 if (changed & SettingColors)
00670 {
00671
00672 delete_pixmaps();
00673 create_pixmaps();
00674 captionBufferDirty = true;
00675 widget()->update();
00676 for (int n=0; n<NumButtons; n++) {
00677 if (m_button[n]) m_button[n]->update();
00678 }
00679 } else if (changed & SettingFont) {
00680
00681 s_titleHeight = isTool() ?
00682 PlastikHandler::titleHeightTool()
00683 : PlastikHandler::titleHeight();
00684 s_titleFont = isTool() ?
00685 PlastikHandler::titleFontTool()
00686 : PlastikHandler::titleFont();
00687
00688 for (int n=0; n<NumButtons; n++) {
00689 if (m_button[n]) m_button[n]->setSize(s_titleHeight-1);
00690 }
00691
00692 titleSpacer_->changeSize(1, s_titleHeight,
00693 QSizePolicy::Expanding, QSizePolicy::Fixed);
00694
00695 delete_pixmaps();
00696 create_pixmaps();
00697 captionBufferDirty = true;
00698 widget()->update();
00699 }
00700 }
00701
00702 PlastikClient::Position PlastikClient::mousePosition(const QPoint &point) const
00703 {
00704 const int corner = 18+3*PlastikHandler::borderSize()/2;
00705 Position pos = PositionCenter;
00706
00707
00708 QRect topRect(topSpacer_->geometry());
00709 QRect decoRect(decoSpacer_->geometry());
00710 QRect leftRect(leftSpacer_->geometry());
00711 QRect leftTitleRect(leftTitleSpacer_->geometry());
00712 QRect rightRect(rightSpacer_->geometry());
00713 QRect rightTitleRect(rightTitleSpacer_->geometry());
00714 QRect bottomRect(bottomSpacer_->geometry());
00715
00716 if(bottomRect.contains(point)) {
00717 if (point.x() <= bottomRect.left()+corner) pos = PositionBottomLeft;
00718 else if (point.x() >= bottomRect.right()-corner) pos = PositionBottomRight;
00719 else pos = PositionBottom;
00720 }
00721 else if(leftRect.contains(point)) {
00722 if (point.y() <= topRect.top()+corner) pos = PositionTopLeft;
00723 else if (point.y() >= bottomRect.bottom()-corner) pos = PositionBottomLeft;
00724 else pos = PositionLeft;
00725 }
00726 else if(leftTitleRect.contains(point)) {
00727 if (point.y() <= topRect.top()+corner) pos = PositionTopLeft;
00728 else pos = PositionLeft;
00729 }
00730 else if(rightRect.contains(point)) {
00731 if (point.y() <= topRect.top()+corner) pos = PositionTopRight;
00732 else if (point.y() >= bottomRect.bottom()-corner) pos = PositionBottomRight;
00733 else pos = PositionRight;
00734 }
00735 else if(rightTitleRect.contains(point)) {
00736 if (point.y() <= topRect.top()+corner) pos = PositionTopRight;
00737 else pos = PositionRight;
00738 }
00739 else if(topRect.contains(point)) {
00740 if (point.x() <= topRect.left()+corner) pos = PositionTopLeft;
00741 else if (point.x() >= topRect.right()-corner) pos = PositionTopRight;
00742 else pos = PositionTop;
00743 }
00744 else if(decoRect.contains(point)) {
00745 if(point.x() <= leftTitleRect.right()) {
00746 if(point.y() <= topRect.top()+corner) pos = PositionTopLeft;
00747 else pos = PositionLeft;
00748 }
00749 else if(point.x() >= rightTitleRect.left()) {
00750 if(point.y() <= topRect.top()+corner) pos = PositionTopRight;
00751 else pos = PositionRight;
00752 }
00753 }
00754
00755 return pos;
00756 }
00757
00758 void PlastikClient::iconChange()
00759 {
00760 if (m_button[MenuButton])
00761 {
00762 m_button[MenuButton]->update();
00763 }
00764 }
00765
00766 void PlastikClient::activeChange()
00767 {
00768 for (int n=0; n<NumButtons; n++)
00769 if (m_button[n]) m_button[n]->update();
00770 widget()->update();
00771 }
00772
00773 void PlastikClient::maximizeChange()
00774 {
00775 if (!PlastikHandler::initialized()) return;
00776
00777 if( m_button[MaxButton] ) {
00778 m_button[MaxButton]->setOn( maximizeMode()==MaximizeFull);
00779 m_button[MaxButton]->setTipText( (maximizeMode()!=MaximizeFull) ?
00780 i18n("Maximize")
00781 : i18n("Restore"));
00782 }
00783 }
00784
00785 void PlastikClient::desktopChange()
00786 {
00787 if ( m_button[OnAllDesktopsButton] ) {
00788 m_button[OnAllDesktopsButton]->setOn( isOnAllDesktops() );
00789 m_button[OnAllDesktopsButton]->setTipText( isOnAllDesktops() ?
00790 i18n("Not on all desktops")
00791 : i18n("On all desktops"));
00792 }
00793 }
00794
00795 void PlastikClient::shadeChange()
00796 {
00797 if ( m_button[ShadeButton] ) {
00798 bool shaded = isSetShade();
00799 m_button[ShadeButton]->setOn( shaded );
00800 m_button[ShadeButton]->setTipText( shaded ?
00801 i18n("Unshade")
00802 : i18n("Shade"));
00803 }
00804 }
00805
00806 void PlastikClient::slotMaximize()
00807 {
00808 if (m_button[MaxButton])
00809 {
00810 maximize(m_button[MaxButton]->lastMousePress() );
00811 doShape();
00812 }
00813 }
00814
00815 void PlastikClient::slotShade()
00816 {
00817 setShade( !isSetShade() );
00818 }
00819
00820 void PlastikClient::slotKeepAbove()
00821 {
00822 setKeepAbove(!keepAbove() );
00823 }
00824
00825 void PlastikClient::slotKeepBelow()
00826 {
00827 setKeepBelow(!keepBelow() );
00828 }
00829
00830 void PlastikClient::keepAboveChange(bool above)
00831 {
00832 if (m_button[AboveButton])
00833 {
00834 m_button[AboveButton]->setOn(above);
00835 m_button[AboveButton]->setTipText( above?i18n("Do not keep above others"):i18n("Keep above others") );
00836 }
00837
00838 if (m_button[BelowButton] && m_button[BelowButton]->isOn())
00839 {
00840 m_button[BelowButton]->setOn(false);
00841 m_button[BelowButton]->setTipText( i18n("Keep below others") );
00842 }
00843 }
00844
00845 void PlastikClient::keepBelowChange(bool below)
00846 {
00847 if (m_button[BelowButton])
00848 {
00849 m_button[BelowButton]->setOn(below);
00850 m_button[BelowButton]->setTipText( below?i18n("Do not keep below others"):i18n("Keep below others") );
00851 }
00852
00853 if (m_button[AboveButton] && m_button[AboveButton]->isOn())
00854 {
00855 m_button[AboveButton]->setOn(false);
00856 m_button[AboveButton]->setTipText( i18n("Keep above others") );
00857 }
00858 }
00859
00860 void PlastikClient::menuButtonPressed()
00861 {
00862 static QTime* t = NULL;
00863 static PlastikClient* lastClient = NULL;
00864 if (t == NULL)
00865 t = new QTime;
00866 bool dbl = (lastClient==this && t->elapsed() <= QApplication::doubleClickInterval());
00867 lastClient = this;
00868 t->start();
00869 if (!dbl || !PlastikHandler::menuClose()) {
00870 QRect menuRect = m_button[MenuButton]->rect();
00871 QPoint menutop = m_button[MenuButton]->mapToGlobal(menuRect.topLeft());
00872 QPoint menubottom = m_button[MenuButton]->mapToGlobal(menuRect.bottomRight());
00873 KDecorationFactory* f = factory();
00874 showWindowMenu(QRect(menutop, menubottom));
00875 if( !f->exists( this ))
00876 return;
00877 m_button[MenuButton]->setDown(false);
00878 }
00879 else
00880 closing = true;
00881 }
00882
00883 void PlastikClient::menuButtonReleased()
00884 {
00885 if(closing)
00886 closeWindow();
00887 }
00888
00889 void PlastikClient::create_pixmaps()
00890 {
00891 if(pixmaps_created)
00892 return;
00893
00894 KPixmap tempPixmap;
00895 QPainter painter;
00896
00897
00898 tempPixmap.resize(1, TOPMARGIN-1-1 );
00899 KPixmapEffect::gradient(tempPixmap,
00900 PlastikHandler::getColor(TitleGradientToTop, true),
00901 PlastikHandler::getColor(TitleGradientFrom, true),
00902 KPixmapEffect::VerticalGradient);
00903 aTitleBarTopTile = new QPixmap(1, TOPMARGIN-1-1 );
00904 painter.begin(aTitleBarTopTile);
00905 painter.drawPixmap(0, 0, tempPixmap);
00906 painter.end();
00907
00908
00909 tempPixmap.resize(1, s_titleHeight );
00910 KPixmapEffect::gradient(tempPixmap,
00911 PlastikHandler::getColor(TitleGradientFrom, true),
00912 PlastikHandler::getColor(TitleGradientTo, true),
00913 KPixmapEffect::VerticalGradient);
00914 aTitleBarTile = new QPixmap(1, s_titleHeight );
00915 painter.begin(aTitleBarTile);
00916 painter.drawPixmap(0, 0, tempPixmap);
00917 painter.end();
00918
00919
00920 tempPixmap.resize(1, TOPMARGIN-1-1 );
00921 KPixmapEffect::gradient(tempPixmap,
00922 PlastikHandler::getColor(TitleGradientToTop, false),
00923 PlastikHandler::getColor(TitleGradientFrom, false),
00924 KPixmapEffect::VerticalGradient);
00925 iTitleBarTopTile = new QPixmap(1, TOPMARGIN-1-1 );
00926 painter.begin(iTitleBarTopTile);
00927 painter.drawPixmap(0, 0, tempPixmap);
00928 painter.end();
00929
00930
00931 tempPixmap.resize(1, s_titleHeight );
00932 KPixmapEffect::gradient(tempPixmap,
00933 PlastikHandler::getColor(TitleGradientFrom, false),
00934 PlastikHandler::getColor(TitleGradientTo, false),
00935 KPixmapEffect::VerticalGradient);
00936 iTitleBarTile = new QPixmap(1, s_titleHeight );
00937 painter.begin(iTitleBarTile);
00938 painter.drawPixmap(0, 0, tempPixmap);
00939 painter.end();
00940
00941 pixmaps_created = true;
00942 }
00943
00944 void PlastikClient::delete_pixmaps()
00945 {
00946 delete aTitleBarTopTile;
00947 aTitleBarTopTile = 0;
00948
00949 delete iTitleBarTopTile;
00950 iTitleBarTopTile = 0;
00951
00952 delete aTitleBarTile;
00953 aTitleBarTile = 0;
00954
00955 delete iTitleBarTile;
00956 iTitleBarTile = 0;
00957
00958 pixmaps_created = false;
00959 }
00960
00961 void PlastikClient::update_captionBuffer()
00962 {
00963 if (!PlastikHandler::initialized()) return;
00964
00965 const uint maxCaptionLength = 300;
00966 QString c(caption() );
00967 if (c.length() > maxCaptionLength) {
00968 c.truncate(maxCaptionLength);
00969 c.append(" [...]");
00970 }
00971
00972 QFontMetrics fm(s_titleFont);
00973 int captionWidth = fm.width(c);
00974
00975 QPixmap textPixmap;
00976 QPainter painter;
00977 if(PlastikHandler::titleShadow())
00978 {
00979
00980 textPixmap = QPixmap(captionWidth+2*2, s_titleHeight );
00981 textPixmap.fill(QColor(0,0,0));
00982 textPixmap.setMask( textPixmap.createHeuristicMask(TRUE) );
00983 painter.begin(&textPixmap);
00984 painter.setFont(s_titleFont);
00985 painter.setPen(white);
00986 painter.drawText(textPixmap.rect(), AlignCenter, c );
00987 painter.end();
00988 }
00989
00990 QImage shadow;
00991 ShadowEngine se;
00992
00993
00994 aCaptionBuffer->resize(captionWidth+4, s_titleHeight );
00995 painter.begin(aCaptionBuffer);
00996 painter.drawTiledPixmap(aCaptionBuffer->rect(), *aTitleBarTile);
00997 if(PlastikHandler::titleShadow())
00998 {
00999 QColor shadowColor;
01000 if (qGray(PlastikHandler::getColor(TitleFont,true).rgb()) < 100)
01001 shadowColor = QColor(255, 255, 255);
01002 else
01003 shadowColor = QColor(0,0,0);
01004 shadow = se.makeShadow(textPixmap, shadowColor);
01005 painter.drawImage(1, 1, shadow);
01006 }
01007 painter.setFont(s_titleFont);
01008 painter.setPen(PlastikHandler::getColor(TitleFont,true));
01009 painter.drawText(aCaptionBuffer->rect(), AlignCenter, c );
01010 painter.end();
01011
01012
01013
01014 iCaptionBuffer->resize(captionWidth+4, s_titleHeight );
01015 painter.begin(iCaptionBuffer);
01016 painter.drawTiledPixmap(iCaptionBuffer->rect(), *iTitleBarTile);
01017 if(PlastikHandler::titleShadow())
01018 {
01019 painter.drawImage(1, 1, shadow);
01020 }
01021 painter.setFont(s_titleFont);
01022 painter.setPen(PlastikHandler::getColor(TitleFont,false));
01023 painter.drawText(iCaptionBuffer->rect(), AlignCenter, c );
01024 painter.end();
01025
01026 captionBufferDirty = false;
01027 }
01028
01029 void PlastikClient::borders( int& left, int& right, int& top, int& bottom ) const
01030 {
01031 if ((maximizeMode()==MaximizeFull) && !options()->moveResizeMaximizedWindows()) {
01032 left = right = bottom = 0;
01033 top = s_titleHeight;
01034
01035
01036 topSpacer_->changeSize(1, 0, QSizePolicy::Expanding, QSizePolicy::Fixed);
01037 decoSpacer_->changeSize(1, 0, QSizePolicy::Expanding, QSizePolicy::Fixed);
01038 leftSpacer_->changeSize(left, 1, QSizePolicy::Fixed, QSizePolicy::Expanding);
01039 leftTitleSpacer_->changeSize(left, s_titleHeight, QSizePolicy::Fixed, QSizePolicy::Fixed);
01040 rightSpacer_->changeSize(right, 1, QSizePolicy::Fixed, QSizePolicy::Expanding);
01041 rightTitleSpacer_->changeSize(right, s_titleHeight, QSizePolicy::Fixed, QSizePolicy::Fixed);
01042 bottomSpacer_->changeSize(1, bottom, QSizePolicy::Expanding, QSizePolicy::Fixed);
01043 } else {
01044 left = right = bottom = PlastikHandler::borderSize();
01045 top = s_titleHeight + DECOHEIGHT + TOPMARGIN;
01046
01047
01048 topSpacer_->changeSize(1, TOPMARGIN, QSizePolicy::Expanding, QSizePolicy::Fixed);
01049 decoSpacer_->changeSize(1, DECOHEIGHT, QSizePolicy::Expanding, QSizePolicy::Fixed);
01050 leftSpacer_->changeSize(left, 1, QSizePolicy::Fixed, QSizePolicy::Expanding);
01051 leftTitleSpacer_->changeSize(SIDETITLEMARGIN, s_titleHeight,
01052 QSizePolicy::Fixed, QSizePolicy::Fixed);
01053 rightSpacer_->changeSize(right, 1, QSizePolicy::Fixed, QSizePolicy::Expanding);
01054 rightTitleSpacer_->changeSize(SIDETITLEMARGIN, s_titleHeight,
01055 QSizePolicy::Fixed, QSizePolicy::Fixed);
01056 bottomSpacer_->changeSize(1, bottom, QSizePolicy::Expanding, QSizePolicy::Fixed);
01057 }
01058
01059
01060 widget()->layout()->activate();
01061 }
01062
01063 QSize PlastikClient::minimumSize() const
01064 {
01065 return widget()->minimumSize();
01066 }
01067
01068 void PlastikClient::show()
01069 {
01070 widget()->show();
01071 }
01072
01073 void PlastikClient::resize( const QSize& s )
01074 {
01075 widget()->resize( s );
01076 }
01077
01078 bool PlastikClient::eventFilter( QObject* o, QEvent* e )
01079 {
01080 if( o != widget())
01081 return false;
01082 switch( e->type())
01083 {
01084 case QEvent::Resize:
01085 resizeEvent();
01086 return true;
01087 case QEvent::Paint:
01088 paintEvent( static_cast< QPaintEvent* >( e ));
01089 return true;
01090 case QEvent::MouseButtonDblClick:
01091 mouseDoubleClickEvent( static_cast< QMouseEvent* >( e ));
01092 return true;
01093 case QEvent::MouseButtonPress:
01094 processMousePressEvent( static_cast< QMouseEvent* >( e ));
01095 return true;
01096 default:
01097 break;
01098 }
01099 return false;
01100 }
01101
01102 }