00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "redmond.h"
00016
00017 #include <qlayout.h>
00018 #include <qdrawutil.h>
00019 #include <qdatetime.h>
00020 #include <kpixmapeffect.h>
00021 #include <kimageeffect.h>
00022 #include <kdrawutil.h>
00023 #include <klocale.h>
00024
00025 #include <qbitmap.h>
00026 #include <qtooltip.h>
00027 #include <qimage.h>
00028 #include <qlabel.h>
00029 #include <qapplication.h>
00030
00031 namespace Redmond {
00032
00033 static const char *kdelogo[] = {
00034
00035 "16 16 8 1",
00036 " c None",
00037 ". c #000000",
00038 "+ c #A0A0A4",
00039 "@ c #FFFFFF",
00040 "# c #585858",
00041 "$ c #C0C0C0",
00042 "% c #808080",
00043 "& c #DCDCDC",
00044 " ",
00045 " .. .. ",
00046 " .+@. .@#. ",
00047 " .@@@. .@@@# ",
00048 " .@@@..$@@$. ",
00049 " .@@@.@@@$. ",
00050 " .@@@%@@$. ",
00051 " .@@@&@@. ",
00052 " .@@@@@@. ",
00053 " .@@@$@@&. ",
00054 " .@@@.@@@. ",
00055 " .@@@.+@@@. ",
00056 " .@@@..$@@&. ",
00057 " .@@%. .@@@. ",
00058 " .... ... ",
00059 " "};
00060
00061 static unsigned char iconify_bits[] = {
00062 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00063 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00};
00064
00065 static unsigned char close_bits[] = {
00066 0x00, 0x00, 0x86, 0x01, 0xcc, 0x00, 0x78, 0x00, 0x30, 0x00, 0x78, 0x00,
00067 0xcc, 0x00, 0x86, 0x01, 0x00, 0x00, 0x00, 0x00};
00068
00069 static unsigned char maximize_bits[] = {
00070 0xff, 0x01, 0xff, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
00071 0x01, 0x01, 0x01, 0x01, 0xff, 0x01, 0x00, 0x00};
00072
00073 static unsigned char minmax_bits[] = {
00074 0xfc, 0x00, 0xfc, 0x00, 0x84, 0x00, 0xbf, 0x00, 0xbf, 0x00, 0xe1, 0x00,
00075 0x21, 0x00, 0x21, 0x00, 0x3f, 0x00, 0x00, 0x00};
00076
00077 static unsigned char question_bits[] = {
00078 0x00, 0x00, 0x3c, 0x00, 0x66, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00,
00079 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00};
00080
00081
00082
00083 static KPixmap *btnPix1;
00084 static KPixmap *iBtnPix1;
00085 static KPixmap *btnDownPix1;
00086 static KPixmap *iBtnDownPix1;
00087
00088 static KPixmap *miniBtnPix1;
00089 static KPixmap *iMiniBtnPix1;
00090 static KPixmap *miniBtnDownPix1;
00091 static KPixmap *iMiniBtnDownPix1;
00092
00093 static QPixmap *defaultMenuPix;
00094 static QColor *btnForeground;
00095 static bool pixmaps_created = false;
00096
00097 static int toolTitleHeight;
00098 static int normalTitleHeight;
00099 static int borderWidth;
00100
00101 static inline const KDecorationOptions *options()
00102 {
00103 return KDecoration::options();
00104 }
00105
00106 static void drawButtonFrame( KPixmap *pix, const QColorGroup &g, bool sunken )
00107 {
00108 QPainter p;
00109 int x2 = pix->width() - 1;
00110 int y2 = pix->height() - 1;
00111 p.begin(pix);
00112
00113
00114 p.setPen( sunken ? g.dark().dark(155) : g.light());
00115 p.drawLine(0, 0, x2-1, 0);
00116 p.drawLine(0, 0, 0, y2-1);
00117
00118 if (sunken)
00119 {
00120 p.setPen( g.mid().dark(135) );
00121 p.drawLine(1, 1, x2-2, 1);
00122 p.drawLine(1, 1, 1, y2-2);
00123 }
00124
00125 p.setPen( sunken ? g.light() : g.mid().dark(135));
00126 p.drawLine(1, y2-1, x2-1, y2-1);
00127 p.drawLine(x2-1, 1, x2-1, y2-1);
00128
00129 p.setPen( sunken ? g.light() : g.dark().dark(155));
00130 p.drawLine(0, y2, x2, y2);
00131 p.drawLine(x2, 0, x2, y2);
00132 }
00133
00134
00135 static void create_pixmaps ()
00136 {
00137 if (pixmaps_created)
00138 return;
00139
00140 pixmaps_created = true;
00141
00142 bool highcolor = QPixmap::defaultDepth() > 8;
00143
00144 btnPix1 = new KPixmap;
00145 btnDownPix1 = new KPixmap;
00146 iBtnPix1 = new KPixmap;
00147 iBtnDownPix1 = new KPixmap;
00148 miniBtnPix1 = new KPixmap;
00149 miniBtnDownPix1 = new KPixmap;
00150 iMiniBtnPix1 = new KPixmap;
00151 iMiniBtnDownPix1 = new KPixmap;
00152 defaultMenuPix = new QPixmap(kdelogo);
00153
00154
00155 QColorGroup g = options()->colorGroup(KDecoration::ColorButtonBg, true);
00156 QColor c = g.background();
00157 btnPix1->resize(normalTitleHeight, normalTitleHeight-2);
00158 btnDownPix1->resize(normalTitleHeight, normalTitleHeight-2);
00159 iBtnPix1->resize(normalTitleHeight, normalTitleHeight-2);
00160 iBtnDownPix1->resize(normalTitleHeight, normalTitleHeight-2);
00161
00162 miniBtnPix1->resize(toolTitleHeight, toolTitleHeight);
00163 miniBtnDownPix1->resize(toolTitleHeight, toolTitleHeight);
00164 iMiniBtnPix1->resize(toolTitleHeight, toolTitleHeight);
00165 iMiniBtnDownPix1->resize(toolTitleHeight, toolTitleHeight);
00166
00167 if (highcolor && false) {
00168 KPixmapEffect::gradient(*btnPix1, c.light(130), c.dark(130),
00169 KPixmapEffect::VerticalGradient);
00170 KPixmapEffect::gradient(*btnDownPix1, c.dark(130), c.light(130),
00171 KPixmapEffect::VerticalGradient);
00172
00173 KPixmapEffect::gradient(*miniBtnPix1, c.light(130), c.dark(130),
00174 KPixmapEffect::VerticalGradient);
00175 KPixmapEffect::gradient(*miniBtnDownPix1, c.dark(130), c.light(130),
00176 KPixmapEffect::VerticalGradient);
00177
00178 g = options()->colorGroup(KDecoration::ColorButtonBg, false);
00179 c = g.background();
00180 KPixmapEffect::gradient(*iBtnPix1, c.light(130), c.dark(130),
00181 KPixmapEffect::VerticalGradient);
00182 KPixmapEffect::gradient(*iBtnDownPix1, c.dark(130), c.light(130),
00183 KPixmapEffect::VerticalGradient);
00184 KPixmapEffect::gradient(*iMiniBtnPix1, c.light(130), c.dark(130),
00185 KPixmapEffect::VerticalGradient);
00186 KPixmapEffect::gradient(*iMiniBtnDownPix1, c.dark(130), c.light(130),
00187 KPixmapEffect::VerticalGradient);
00188 } else {
00189 btnPix1->fill(c.rgb());
00190 btnDownPix1->fill(c.rgb());
00191 miniBtnPix1->fill(c.rgb());
00192 miniBtnDownPix1->fill(c.rgb());
00193
00194 g = options()->colorGroup(KDecoration::ColorButtonBg, false);
00195 c = g.background();
00196 iBtnPix1->fill(c.rgb());
00197 iBtnDownPix1->fill(c.rgb());
00198 iMiniBtnPix1->fill(c.rgb());
00199 iMiniBtnDownPix1->fill(c.rgb());
00200 }
00201
00202 g = options()->colorGroup(KDecoration::ColorButtonBg, true);
00203 drawButtonFrame(btnPix1, g, false);
00204 drawButtonFrame(btnDownPix1, g, true);
00205 drawButtonFrame(miniBtnPix1, g, false);
00206 drawButtonFrame(miniBtnDownPix1, g, true);
00207
00208 g = options()->colorGroup(KDecoration::ColorButtonBg, false);
00209 drawButtonFrame(iBtnPix1, g, false);
00210 drawButtonFrame(iBtnDownPix1, g, true);
00211 drawButtonFrame(iMiniBtnPix1, g, false);
00212 drawButtonFrame(iMiniBtnDownPix1, g, true);
00213
00214
00215 if (qGray(options()->color(KDecoration::ColorButtonBg, true).rgb()) > 127)
00216 btnForeground = new QColor(Qt::black);
00217 else
00218 btnForeground = new QColor(Qt::white);
00219 }
00220
00221 void delete_pixmaps()
00222 {
00223 delete btnPix1;
00224 delete btnDownPix1;
00225 delete iBtnPix1;
00226 delete iBtnDownPix1;
00227 delete miniBtnPix1;
00228 delete miniBtnDownPix1;
00229 delete iMiniBtnPix1;
00230 delete iMiniBtnDownPix1;
00231 delete defaultMenuPix;
00232 delete btnForeground;
00233 pixmaps_created = false;
00234 }
00235
00236
00237 RedmondButton::RedmondButton(RedmondDeco *parent, const char *name,
00238 const unsigned char *bitmap, bool menuButton, bool isMini, int size, const QString& tip, const int realizeBtns)
00239 : QButton(parent->widget(), name),
00240 last_button( NoButton )
00241 {
00242
00243 setBackgroundMode( NoBackground );
00244 setCursor( arrowCursor );
00245
00246 menuBtn = menuButton;
00247 miniBtn = isMini;
00248 client = parent;
00249 this->size = size;
00250 realizeButtons = realizeBtns;
00251
00252
00253 if ( isMini || menuButton ) {
00254 setFixedSize(size, size);
00255 resize(size, size);
00256 } else {
00257 setFixedSize(size, size-2);
00258 resize(size, size-2);
00259 }
00260
00261 if ( bitmap ) {
00262 setBitmap(bitmap);
00263 }
00264
00265 QToolTip::add(this, tip);
00266 }
00267
00268
00269 QSize RedmondButton::sizeHint() const
00270 {
00271 if ( miniBtn || menuBtn )
00272 return( QSize(size, size) );
00273 else
00274 return( QSize(size, size-2) );
00275 }
00276
00277
00278 void RedmondButton::reset()
00279 {
00280 repaint(false);
00281 }
00282
00283
00284 void RedmondButton::setBitmap(const unsigned char *bitmap)
00285 {
00286 pix.resize(0, 0);
00287 deco = QBitmap(10, 10, bitmap, true);
00288 deco.setMask(deco);
00289 repaint( false );
00290 }
00291
00292
00293 void RedmondButton::setPixmap( const QPixmap &p )
00294 {
00295 deco.resize(0, 0);
00296 pix = p;
00297
00298 if (miniBtn || menuBtn)
00299 setMask(QRect(0, 0, size, size));
00300 else
00301 setMask(QRect(0, 0, size, size-2));
00302
00303 repaint(false);
00304 }
00305
00306
00307 void RedmondButton::mousePressEvent( QMouseEvent* e )
00308 {
00309 last_button = e->button();
00310 QMouseEvent me(e->type(), e->pos(), e->globalPos(),
00311 (e->button()&realizeButtons)?LeftButton:NoButton, e->state());
00312 QButton::mousePressEvent( &me );
00313 }
00314
00315
00316 void RedmondButton::mouseReleaseEvent( QMouseEvent* e )
00317 {
00318 last_button = e->button();
00319 QMouseEvent me ( e->type(), e->pos(), e->globalPos(),
00320 (e->button()&realizeButtons)?LeftButton:NoButton, e->state() );
00321 QButton::mouseReleaseEvent( &me );
00322 }
00323
00324
00325 void RedmondButton::drawButton(QPainter *p)
00326 {
00327 if ( pix.isNull() ) {
00328 if ( client->isActive() ) {
00329 if ( isDown() )
00330 p->drawPixmap(0, 0, miniBtn ? *miniBtnDownPix1 : *btnDownPix1);
00331 else
00332 p->drawPixmap(0, 0, miniBtn ? *miniBtnPix1 : *btnPix1);
00333 } else {
00334 if ( isDown() )
00335 p->drawPixmap(0, 0, miniBtn ? *iMiniBtnDownPix1 : *iBtnDownPix1);
00336 else
00337 p->drawPixmap(0, 0, miniBtn ? *iMiniBtnPix1 : *iBtnPix1);
00338 }
00339
00340 p->setPen( *btnForeground );
00341 int xOff = (width()-10)/2;
00342 int yOff = (height()-10)/2;
00343 p->drawPixmap(isDown() ? xOff+1: xOff, isDown() ? yOff+1 : yOff, deco);
00344 } else {
00345 p->fillRect(0, 0, width(), height(),
00346 options()->color(KDecoration::ColorTitleBar, client->isActive()));
00347
00348 if ( menuBtn && size < 16) {
00349 QPixmap tmpPix;
00350
00351
00352 tmpPix.convertFromImage(
00353 pix.convertToImage().smoothScale(size, size));
00354
00355 p->drawPixmap( 0, 0, tmpPix );
00356 } else {
00357 int xOff = (width() -pix.width() )/2;
00358 int yOff = (height()-pix.height())/2;
00359 p->drawPixmap(xOff, yOff, pix );
00360 }
00361 }
00362 }
00363
00364
00365 RedmondDeco::RedmondDeco(KDecorationBridge *b, KDecorationFactory *f)
00366 : KDecoration(b, f)
00367 {
00368 }
00369
00370 void RedmondDeco::init()
00371 {
00372 createMainWidget(WResizeNoErase);
00373 widget()->installEventFilter(this);
00374
00375 widget()->setBackgroundMode(NoBackground);
00376
00377
00378
00379
00380
00381
00382
00383 titleHeight = normalTitleHeight+2;
00384 smallButtons = false;
00385
00386
00387 lastButtonWidth = 0;
00388
00389 QGridLayout* g = new QGridLayout(widget(), 0, 0, 0);
00390 g->setResizeMode(QLayout::FreeResize);
00391 if (isPreview()) {
00392 g->addWidget(new QLabel(i18n("<center><b>Redmond preview</b></center>"), widget()), 3, 1);
00393 } else {
00394 g->addItem(new QSpacerItem( 0, 0 ), 3, 1);
00395 }
00396
00397 g->addRowSpacing(0, borderWidth);
00398
00399 g->addItem(new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding));
00400 g->setRowStretch(3, 10);
00401 g->addRowSpacing(4, borderWidth);
00402 g->addRowSpacing(2, 1);
00403 g->addColSpacing(0, borderWidth);
00404 g->addColSpacing(2, borderWidth);
00405
00406 button[BtnMenu] = new RedmondButton(this, "menu", NULL, true, smallButtons, titleHeight-2, i18n("Menu"), LeftButton|RightButton);
00407 button[BtnClose] = new RedmondButton(this, "close", close_bits, false, smallButtons, titleHeight-2, i18n("Close"));
00408 button[BtnMin] = new RedmondButton(this, "iconify", iconify_bits, false, smallButtons, titleHeight-2, i18n("Minimize"));
00409 button[BtnMax] = new RedmondButton(this, "maximize", maximize_bits, false, smallButtons, titleHeight-2, i18n("Maximize"), LeftButton|MidButton|RightButton);
00410
00411
00412 connect(button[BtnMenu], SIGNAL(pressed()), this, SLOT(menuButtonPressed()));
00413 connect(button[BtnClose], SIGNAL(clicked()), this, SLOT(closeWindow()));
00414 connect(button[BtnMin], SIGNAL(clicked()), this, SLOT(minimize()));
00415 connect(button[BtnMax], SIGNAL(clicked()), this, SLOT(slotMaximize()));
00416
00417
00418 hb = new QBoxLayout(0, QBoxLayout::LeftToRight, 0, 0, 0);
00419 hb->setResizeMode(QLayout::FreeResize);
00420 hb->addSpacing(2);
00421 hb->addWidget(button[BtnMenu]);
00422 titlebar = new QSpacerItem(10, titleHeight, QSizePolicy::Expanding, QSizePolicy::Minimum);
00423 hb->addItem(titlebar);
00424 hb->addSpacing(borderWidth/2);
00425
00426 if ( providesContextHelp() ) {
00427 button[BtnHelp] = new RedmondButton(this, "help", question_bits, false, smallButtons, titleHeight-2, i18n("Help"));
00428 connect( button[BtnHelp], SIGNAL( clicked() ), this, SLOT( showContextHelp() ));
00429 hb->addWidget( button[BtnHelp] );
00430 } else {
00431 button[BtnHelp] = NULL;
00432 }
00433
00434 hb->addWidget(button[BtnMin]);
00435 hb->addWidget(button[BtnMax]);
00436 hb->addSpacing(borderWidth/2);
00437 hb->addWidget(button[BtnClose]);
00438 hb->addSpacing(2);
00439
00440 g->addLayout(hb, 1, 1);
00441
00442
00443
00444 if (!isMinimizable())
00445 button[BtnMin]->hide();
00446 if (!isMaximizable())
00447 button[BtnMax]->hide();
00448 if (!isCloseable())
00449 button[BtnClose]->hide();
00450
00451 hiddenItems = false;
00452
00453
00454 iconChange();
00455 widget()->layout()->activate();
00456 }
00457
00458
00459 void RedmondDeco::slotReset()
00460 {
00461
00462 for(int i = RedmondDeco::BtnHelp; i <= RedmondDeco::BtnClose; i++)
00463 if (button[i])
00464 button[i]->reset();
00465
00466
00467
00468 widget()->repaint( false );
00469 }
00470
00471
00472 void RedmondDeco::iconChange()
00473 {
00474 QPixmap miniIcon = icon().pixmap(QIconSet::Small, QIconSet::Normal);
00475
00476 if (!miniIcon.isNull())
00477 button[BtnMenu]->setPixmap(miniIcon);
00478 else
00479 button[BtnMenu]->setPixmap(*defaultMenuPix);
00480
00481 if (button[BtnMenu]->isVisible())
00482 button[BtnMenu]->repaint(false);
00483 }
00484
00485
00486 void RedmondDeco::slotMaximize()
00487 {
00488 if (button[BtnMax]) {
00489 maximize(button[BtnMax]->last_button);
00490 }
00491 }
00492
00493
00494 void RedmondDeco::resizeEvent(QResizeEvent *)
00495 {
00496 calcHiddenButtons();
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522 }
00523
00524
00525 void RedmondDeco::captionChange( const QString& )
00526 {
00527 widget()->repaint( titlebar->geometry(), false );
00528 }
00529
00530
00531 void RedmondDeco::paintEvent( QPaintEvent* )
00532 {
00533 bool hicolor = QPixmap::defaultDepth() > 8;
00534 int fontoffset = 1;
00535
00536 QPainter p(widget());
00537
00538
00539 QRect r(widget()->rect());
00540 int x = r.x();
00541 int y = r.y();
00542 int x2 = r.width()-1;
00543 int y2 = r.height()-1;
00544 int w = r.width();
00545 int h = r.height();
00546
00547
00548
00549 QColorGroup g = options()->colorGroup(KDecoration::ColorFrame, isActive());
00550 p.setPen( g.background() );
00551 p.drawLine( x, y, x2-1, y );
00552 p.drawLine( x, y, x, y2-1 );
00553
00554
00555 p.drawLine( x+borderWidth, y+titleHeight+borderWidth, x2-borderWidth, y+titleHeight+borderWidth );
00556
00557 p.drawLine( x+borderWidth, y2-borderWidth, x2-borderWidth, y2-borderWidth );
00558
00559
00560 for (int i = 1; i < borderWidth; i++)
00561 p.drawRect( x+i, y+i, w-2*i, h-2*i );
00562
00563
00564 p.setPen(g.light());
00565 for (int i = 1; i <= borderWidth/3; i++) {
00566 p.drawLine( x+i, y+i, x2-i-1, y+i);
00567 p.drawLine( x+i, y+i, x+i, y2-i-1);
00568 }
00569
00570 p.setPen(g.mid().dark(135));
00571 for (int i = 1; i <= borderWidth/3; i++) {
00572 p.drawLine( x2-i, y+i+1, x2-i, y2-i);
00573 p.drawLine( x+i+1, y2-i, x2-i, y2-i);
00574 }
00575
00576
00577 p.setPen( g.dark().dark(155) );
00578 p.drawLine(x2, y, x2, y2);
00579 p.drawLine(x, y2, x2, y2);
00580
00581
00582
00583 r = titlebar->geometry();
00584 QFontMetrics fm(options()->font(true));
00585
00586
00587 QColor c1 = options()->color(KDecoration::ColorTitleBar, isActive() );
00588 QColor c2 = options()->color(KDecoration::ColorTitleBlend, isActive() );
00589
00590
00591
00592 if ((c1 != c2) && hicolor) {
00593
00594
00595
00596 KPixmap* titleBuffer = new KPixmap;
00597 titleBuffer->resize(w-2*borderWidth, titleHeight);
00598
00599 if (titleBuffer->depth() > 16) {
00600 KPixmapEffect::gradient(*titleBuffer, c1, c2,
00601 KPixmapEffect::HorizontalGradient);
00602 } else {
00603
00604
00605 QImage image = KImageEffect::gradient(titleBuffer->size(), c1, c2,
00606 KImageEffect::HorizontalGradient);
00607
00608 titleBuffer->convertFromImage(image, Qt::OrderedDither);
00609 }
00610
00611 QPainter p2( titleBuffer, this );
00612
00613
00614
00615
00616
00617 QFont fnt = options()->font(true);
00618 if ( smallButtons ) {
00619 fnt.setPointSize( fnt.pointSize() - 2 );
00620 fnt.setWeight( QFont::Normal );
00621 fontoffset = 0;
00622 }
00623 p2.setFont( fnt );
00624 p2.setPen( options()->color(KDecoration::ColorFont, isActive() ));
00625 p2.drawText( r.x(), fontoffset, r.width()-3, r.height()-1,
00626 AlignLeft | AlignVCenter, caption() );
00627 p2.end();
00628
00629 p.drawPixmap( borderWidth, borderWidth, *titleBuffer );
00630
00631 delete titleBuffer;
00632
00633 } else {
00634
00635
00636 p.fillRect( borderWidth, borderWidth, w-2*borderWidth, titleHeight, c1 );
00637
00638
00639 QFont fnt = options()->font(true);
00640 if ( smallButtons )
00641 {
00642 fnt.setPointSize( fnt.pointSize() - 2 );
00643 fnt.setWeight( QFont::Normal );
00644 fontoffset = 0;
00645 }
00646 p.setFont( fnt );
00647 p.setPen(options()->color(KDecoration::ColorFont, isActive() ));
00648 p.drawText(r.x()+4, r.y()+fontoffset, r.width()-3, r.height()-1,
00649 AlignLeft | AlignVCenter, caption() );
00650 }
00651
00652 }
00653
00654 void RedmondDeco::showEvent(QShowEvent *)
00655 {
00656 calcHiddenButtons();
00657 widget()->show();
00658 }
00659
00660
00661 void RedmondDeco::mouseDoubleClickEvent( QMouseEvent * e )
00662 {
00663 if (e->button() == LeftButton && titlebar->geometry().contains( e->pos() ) )
00664 titlebarDblClickOperation();
00665 }
00666
00667
00668 void RedmondDeco::maximizeChange(bool m)
00669 {
00670 button[BtnMax]->setBitmap(m ? minmax_bits : maximize_bits);
00671 }
00672
00673 void RedmondDeco::calcHiddenButtons()
00674 {
00675
00676 int minWidth = (2 + 4 + (providesContextHelp() ? 2 : 1 )) * normalTitleHeight;
00677
00678 if (lastButtonWidth > width()) {
00679 lastButtonWidth = width();
00680 if (width() < minWidth) {
00681 hiddenItems = true;
00682
00683 for(int i = RedmondDeco::BtnHelp; i <= RedmondDeco::BtnMenu; i++) {
00684 if (button[i]) {
00685 if ( !button[i]->isHidden() ) {
00686 button[i]->hide();
00687 }
00688 minWidth -= button[i]->sizeHint().width();
00689 if (width() >= minWidth) {
00690 return;
00691 }
00692 }
00693 }
00694 }
00695 } else {
00696 if ( hiddenItems ) {
00697 lastButtonWidth = width();
00698 int totalSize = normalTitleHeight*3;
00699
00700 for (int i = RedmondDeco::BtnMenu; i >= RedmondDeco::BtnHelp; i--) {
00701 if (button[i]) {
00702 if (button[i]->sizeHint().width() + totalSize <= width()) {
00703 totalSize += button[i]->sizeHint().width();
00704 button[i]->resize(button[i]->sizeHint());
00705 button[i]->show();
00706 } else {
00707 return;
00708 }
00709 }
00710 }
00711
00712
00713 hiddenItems = false;
00714 } else {
00715 lastButtonWidth = width();
00716 }
00717 }
00718 }
00719
00720 RedmondDeco::Position RedmondDeco::mousePosition(const QPoint &p) const
00721 {
00722 Position m = PositionCenter;
00723
00724 const int range = 14 + 3*borderWidth/2;
00725
00726 if ( ( p.x() > borderWidth && p.x() < width() - borderWidth )
00727 && ( p.y() > borderWidth && p.y() < height() - borderWidth ) )
00728 m = PositionCenter;
00729 else if ( p.y() <= range && p.x() <= range)
00730 m = PositionTopLeft;
00731 else if ( p.y() >= height()-range && p.x() >= width()-range)
00732 m = PositionBottomRight;
00733 else if ( p.y() >= height()-range && p.x() <= range)
00734 m = PositionBottomLeft;
00735 else if ( p.y() <= range && p.x() >= width()-range)
00736 m = PositionTopRight;
00737 else if ( p.y() <= borderWidth )
00738 m = PositionTop;
00739 else if ( p.y() >= height()-borderWidth )
00740 m = PositionBottom;
00741 else if ( p.x() <= borderWidth )
00742 m = PositionLeft;
00743 else if ( p.x() >= width()-borderWidth )
00744 m = PositionRight;
00745 else
00746 m = PositionCenter;
00747
00748 return m;
00749 }
00750
00751 void RedmondDeco::borders(int &l, int &r, int &t, int &b) const
00752 {
00753
00754 l = borderWidth;
00755 r = borderWidth;
00756 t = borderWidth + titlebar->geometry().height() + 1;
00757 b = borderWidth;
00758 }
00759
00760 void RedmondDeco::resize(const QSize &s)
00761 {
00762 widget()->resize(s);
00763 }
00764
00765 QSize RedmondDeco::minimumSize() const
00766 {
00767 return QSize(50, 50);
00768 }
00769
00770 void RedmondDeco::activeChange()
00771 {
00772 QPixmap miniIcon = icon().pixmap(QIconSet::Small, QIconSet::Normal);
00773 if (!miniIcon.isNull()) {
00774 button[BtnMenu]->setPixmap(miniIcon);
00775 } else {
00776 button[BtnMenu]->setPixmap(kdelogo);
00777 }
00778
00779
00780 for (int i = BtnHelp; i < BtnCount; i++) {
00781 if (button[i]) button[i]->reset();
00782 }
00783
00784 widget()->repaint(false);
00785 }
00786
00787 void RedmondDeco::captionChange()
00788 {
00789 widget()->repaint(titlebar->geometry(), false);
00790 }
00791
00792 void RedmondDeco::maximizeChange()
00793 {
00794 bool m = (maximizeMode() == MaximizeFull);
00795 button[BtnMax]->setBitmap(m ? minmax_bits : maximize_bits);
00796 QToolTip::remove(button[BtnMax]);
00797 QToolTip::add(button[BtnMax], m ? i18n("Restore") : i18n("Maximize"));
00798 }
00799
00800 void RedmondDeco::desktopChange()
00801 {
00802 }
00803
00804 void RedmondDeco::shadeChange()
00805 {
00806 }
00807
00808 void RedmondDeco::menuButtonPressed()
00809 {
00810 static QTime* t = NULL;
00811 static RedmondDeco* lastClient = NULL;
00812 if (t == NULL) t = new QTime;
00813 bool dbl = ( lastClient == this && t->elapsed() <= QApplication::doubleClickInterval());
00814 lastClient = this;
00815 t->start();
00816 if (!dbl) {
00817 QRect menuRect = button[BtnMenu]->rect();
00818 QPoint menuTop = QPoint(menuRect.topLeft().x()-3,
00819 menuRect.topLeft().y());
00820 QPoint menuBottom = QPoint(menuRect.bottomRight().x()+3,
00821 menuRect.bottomRight().y()+4);
00822 KDecorationFactory* f = factory();
00823 showWindowMenu(QRect(button[BtnMenu]->mapToGlobal(menuTop),
00824 button[BtnMenu]->mapToGlobal(menuBottom)));
00825 if( !f->exists( this ))
00826 return;
00827 button[BtnMenu]->setDown(false);
00828 } else {
00829 closeWindow();
00830 }
00831 }
00832
00833 bool RedmondDeco::eventFilter(QObject *o, QEvent *e)
00834 {
00835 if (o != widget()) { return false; }
00836 switch (e->type()) {
00837 case QEvent::Resize: {
00838 resizeEvent(static_cast<QResizeEvent *>(e));
00839 return true;
00840 }
00841 case QEvent::Paint: {
00842 paintEvent(static_cast<QPaintEvent *>(e));
00843 return true;
00844 }
00845 case QEvent::Show: {
00846 showEvent(static_cast<QShowEvent *>(e));
00847 return true;
00848 }
00849 case QEvent::MouseButtonDblClick: {
00850 mouseDoubleClickEvent(static_cast<QMouseEvent *>(e));
00851 return true;
00852 }
00853 case QEvent::MouseButtonPress: {
00854 processMousePressEvent(static_cast<QMouseEvent *>(e));
00855 return true;
00856 }
00857 default: {
00858 break;
00859 }
00860 }
00861
00862 return false;
00863 }
00864
00865 void RedmondDecoFactory::readConfig() {
00866 normalTitleHeight = QFontMetrics(options()->font(true)).height();
00867 toolTitleHeight = QFontMetrics(options()->font(true, true)).height();
00868 switch(options()->preferredBorderSize(this)) {
00869 case BorderLarge:
00870 borderWidth = 8;
00871 if (normalTitleHeight < 20) normalTitleHeight = 20;
00872 if (toolTitleHeight < 20) toolTitleHeight = 20;
00873 break;
00874 case BorderVeryLarge:
00875 borderWidth = 12;
00876 if (normalTitleHeight < 24) normalTitleHeight = 24;
00877 if (toolTitleHeight < 24) toolTitleHeight = 24;
00878 break;
00879 case BorderHuge:
00880 borderWidth = 18;
00881 if (normalTitleHeight < 28) normalTitleHeight = 28;
00882 if (toolTitleHeight < 28) toolTitleHeight = 28;
00883 break;
00884 case BorderVeryHuge:
00885 borderWidth = 27;
00886 if (normalTitleHeight < 33) normalTitleHeight = 33;
00887 if (toolTitleHeight < 33) toolTitleHeight = 33;
00888 break;
00889 case BorderOversized:
00890 borderWidth = 40;
00891 if (normalTitleHeight < 40) normalTitleHeight = 40;
00892 if (toolTitleHeight < 40) toolTitleHeight = 40;
00893 break;
00894 case BorderTiny:
00895 case BorderNormal:
00896 default:
00897 borderWidth = 4;
00898 if (normalTitleHeight < 16) normalTitleHeight = 16;
00899 if (toolTitleHeight < 16) toolTitleHeight = 16;
00900 }
00901 }
00902
00903 RedmondDecoFactory::RedmondDecoFactory()
00904 {
00905 readConfig();
00906 create_pixmaps();
00907 }
00908
00909 RedmondDecoFactory::~RedmondDecoFactory()
00910 {
00911 Redmond::delete_pixmaps();
00912 }
00913
00914 KDecoration *RedmondDecoFactory::createDecoration( KDecorationBridge *b )
00915 {
00916 return new RedmondDeco(b, this);
00917 }
00918
00919 bool RedmondDecoFactory::reset( unsigned long changed )
00920 {
00921 if ( changed & ( SettingFont | SettingBorder | SettingColors ) ) {
00922 delete_pixmaps();
00923 readConfig();
00924 create_pixmaps();
00925 resetDecorations(changed);
00926 return true;
00927 } else {
00928 resetDecorations(changed);
00929 return false;
00930 }
00931 }
00932
00933 bool RedmondDecoFactory::supports( Ability ability )
00934 {
00935 switch( ability )
00936 {
00937 case AbilityAnnounceButtons:
00938 case AbilityButtonMenu:
00939 case AbilityButtonHelp:
00940 case AbilityButtonMinimize:
00941 case AbilityButtonMaximize:
00942 case AbilityButtonClose:
00943 return true;
00944 default:
00945 return false;
00946 };
00947 }
00948
00949 QValueList< RedmondDecoFactory::BorderSize > RedmondDecoFactory::borderSizes() const
00950 {
00951 return QValueList< BorderSize >() << BorderNormal << BorderLarge <<
00952 BorderVeryLarge << BorderHuge << BorderVeryHuge << BorderOversized;
00953 }
00954
00955 }
00956
00957 extern "C" KDE_EXPORT KDecorationFactory *create_factory()
00958 {
00959 return new Redmond::RedmondDecoFactory();
00960 }
00961
00962
00963 #include "redmond.moc"
00964