tdestyle.cpp
00001 /* 00002 * 00003 * TDEStyle 00004 * Copyright (C) 2001-2002 Karol Szwed <gallium@kde.org> 00005 * 00006 * TQWindowsStyle CC_ListView and style images were kindly donated by TrollTech, 00007 * Copyright (C) 1998-2000 TrollTech AS. 00008 * 00009 * Many thanks to Bradley T. Hughes for the 3 button scrollbar code. 00010 * 00011 * This library is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU Library General Public 00013 * License version 2 as published by the Free Software Foundation. 00014 * 00015 * This library is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 * Library General Public License for more details. 00019 * 00020 * You should have received a copy of the GNU Library General Public License 00021 * along with this library; see the file COPYING.LIB. If not, write to 00022 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00023 * Boston, MA 02110-1301, USA. 00024 */ 00025 00026 #ifdef HAVE_CONFIG_H 00027 #include "config.h" 00028 #endif 00029 00030 #include "tdestyle.h" 00031 00032 #include <tqapplication.h> 00033 #include <tqbitmap.h> 00034 #include <tqmetaobject.h> 00035 #include <tqcleanuphandler.h> 00036 #include <tqmap.h> 00037 #include <tqimage.h> 00038 #include <tqlistview.h> 00039 #include <tqmenubar.h> 00040 #include <tqpainter.h> 00041 #include <tqpixmap.h> 00042 #include <tqpopupmenu.h> 00043 #include <tqprogressbar.h> 00044 #include <tqscrollbar.h> 00045 #include <tqsettings.h> 00046 #include <tqslider.h> 00047 #include <tqstylefactory.h> 00048 #include <tqtabbar.h> 00049 #include <tqtoolbar.h> 00050 #include <tqframe.h> 00051 00052 #include <kpixmap.h> 00053 #include <kpixmapeffect.h> 00054 #include <kimageeffect.h> 00055 00056 #ifdef Q_WS_X11 00057 # include <X11/Xlib.h> 00058 # ifdef HAVE_XRENDER 00059 # include <X11/extensions/Xrender.h> // schroder 00060 extern bool tqt_use_xrender; 00061 # endif 00062 #else 00063 #undef HAVE_XRENDER 00064 #endif 00065 00066 #ifdef HAVE_XCOMPOSITE 00067 #include <X11/extensions/Xrender.h> 00068 #include <X11/extensions/Xcomposite.h> 00069 #include <dlfcn.h> 00070 #endif 00071 00072 #include <limits.h> 00073 00074 namespace 00075 { 00076 // INTERNAL 00077 enum TransparencyEngine { 00078 Disabled = 0, 00079 SoftwareTint, 00080 SoftwareBlend, 00081 XRender 00082 }; 00083 00084 // Drop Shadow 00085 struct ShadowElements { 00086 TQWidget* w1; 00087 TQWidget* w2; 00088 }; 00089 typedef TQMap<const TQWidget*,ShadowElements> ShadowMap; 00090 static ShadowMap *_shadowMap = 0; 00091 TQSingleCleanupHandler<ShadowMap> cleanupShadowMap; 00092 ShadowMap &shadowMap() { 00093 if ( !_shadowMap ) { 00094 _shadowMap = new ShadowMap; 00095 cleanupShadowMap.set( &_shadowMap ); 00096 } 00097 return *_shadowMap; 00098 } 00099 00100 00101 // DO NOT ASK ME HOW I MADE THESE TABLES! 00102 // (I probably won't remember anyway ;) 00103 const double top_right_corner[16] = 00104 { 0.949, 0.965, 0.980, 0.992, 00105 0.851, 0.890, 0.945, 0.980, 00106 0.706, 0.780, 0.890, 0.960, 00107 0.608, 0.706, 0.851, 0.949 }; 00108 00109 const double bottom_right_corner[16] = 00110 { 0.608, 0.706, 0.851, 0.949, 00111 0.706, 0.780, 0.890, 0.960, 00112 0.851, 0.890, 0.945, 0.980, 00113 0.949, 0.965, 0.980, 0.992 }; 00114 00115 const double bottom_left_corner[16] = 00116 { 0.949, 0.851, 0.706, 0.608, 00117 0.965, 0.890, 0.780, 0.706, 00118 0.980, 0.945, 0.890, 0.851, 00119 0.992, 0.980, 0.960, 0.949 }; 00120 00121 const double shadow_strip[4] = 00122 { 0.565, 0.675, 0.835, 0.945 }; 00123 00124 static bool useDropShadow(TQWidget* w) 00125 { 00126 return w && w->metaObject() && 00127 w->metaObject()->findProperty("TDEStyleMenuDropShadow") != -1; 00128 } 00129 } 00130 00131 namespace 00132 { 00133 class TransparencyHandler : public TQObject 00134 { 00135 public: 00136 TransparencyHandler(TDEStyle* style, TransparencyEngine tEngine, 00137 float menuOpacity, bool useDropShadow); 00138 ~TransparencyHandler(); 00139 bool eventFilter(TQObject* object, TQEvent* event); 00140 00141 protected: 00142 void blendToColor(const TQColor &col); 00143 void blendToPixmap(const TQColorGroup &cg, const TQWidget* p); 00144 #ifdef HAVE_XRENDER 00145 void XRenderBlendToPixmap(const TQWidget* p); 00146 #endif 00147 bool haveX11RGBASupport(); 00148 TQImage handleRealAlpha(TQImage); 00149 void createShadowWindows(const TQWidget* p); 00150 void removeShadowWindows(const TQWidget* p); 00151 void rightShadow(TQImage& dst); 00152 void bottomShadow(TQImage& dst); 00153 private: 00154 bool dropShadow; 00155 float opacity; 00156 TQPixmap pix; 00157 TDEStyle* tdestyle; 00158 TransparencyEngine te; 00159 }; 00160 } // namespace 00161 00162 struct TDEStylePrivate 00163 { 00164 bool highcolor : 1; 00165 bool useFilledFrameWorkaround : 1; 00166 bool etchDisabledText : 1; 00167 bool scrollablePopupmenus : 1; 00168 bool autoHideAccelerators : 1; 00169 bool menuAltKeyNavigation : 1; 00170 bool menuDropShadow : 1; 00171 bool sloppySubMenus : 1; 00172 bool semiTransparentRubberband : 1; 00173 int popupMenuDelay; 00174 float menuOpacity; 00175 00176 TransparencyEngine transparencyEngine; 00177 TDEStyle::TDEStyleScrollBarType scrollbarType; 00178 TransparencyHandler* menuHandler; 00179 TDEStyle::TDEStyleFlags flags; 00180 00181 //For KPE_ListViewBranch 00182 TQBitmap *verticalLine; 00183 TQBitmap *horizontalLine; 00184 }; 00185 00186 // ----------------------------------------------------------------------------- 00187 00188 00189 TDEStyle::TDEStyle( TDEStyleFlags flags, TDEStyleScrollBarType sbtype ) 00190 : TQCommonStyle(), d(new TDEStylePrivate) 00191 { 00192 d->flags = flags; 00193 bool useMenuTransparency = (flags & AllowMenuTransparency); 00194 d->useFilledFrameWorkaround = (flags & FilledFrameWorkaround); 00195 d->scrollbarType = sbtype; 00196 d->highcolor = TQPixmap::defaultDepth() > 8; 00197 00198 // Read style settings 00199 TQSettings settings; 00200 d->popupMenuDelay = settings.readNumEntry ("/TDEStyle/Settings/PopupMenuDelay", 250); 00201 d->sloppySubMenus = settings.readBoolEntry("/TDEStyle/Settings/SloppySubMenus", false); 00202 d->etchDisabledText = settings.readBoolEntry("/TDEStyle/Settings/EtchDisabledText", true); 00203 d->menuAltKeyNavigation = settings.readBoolEntry("/TDEStyle/Settings/MenuAltKeyNavigation", true); 00204 d->scrollablePopupmenus = settings.readBoolEntry("/TDEStyle/Settings/ScrollablePopupMenus", false); 00205 d->autoHideAccelerators = settings.readBoolEntry("/TDEStyle/Settings/AutoHideAccelerators", false); 00206 d->menuDropShadow = settings.readBoolEntry("/TDEStyle/Settings/MenuDropShadow", false); 00207 d->semiTransparentRubberband = settings.readBoolEntry("/TDEStyle/Settings/SemiTransparentRubberband", false); 00208 d->menuHandler = NULL; 00209 00210 if (useMenuTransparency) { 00211 TQString effectEngine = settings.readEntry("/TDEStyle/Settings/MenuTransparencyEngine", "Disabled"); 00212 00213 #ifdef HAVE_XRENDER 00214 if (effectEngine == "XRender") 00215 d->transparencyEngine = XRender; 00216 #else 00217 if (effectEngine == "XRender") 00218 d->transparencyEngine = SoftwareBlend; 00219 #endif 00220 else if (effectEngine == "SoftwareBlend") 00221 d->transparencyEngine = SoftwareBlend; 00222 else if (effectEngine == "SoftwareTint") 00223 d->transparencyEngine = SoftwareTint; 00224 else 00225 d->transparencyEngine = Disabled; 00226 00227 if (d->transparencyEngine != Disabled) { 00228 // Create an instance of the menu transparency handler 00229 d->menuOpacity = settings.readDoubleEntry("/TDEStyle/Settings/MenuOpacity", 0.90); 00230 d->menuHandler = new TransparencyHandler(this, d->transparencyEngine, 00231 d->menuOpacity, d->menuDropShadow); 00232 } 00233 } 00234 00235 d->verticalLine = 0; 00236 d->horizontalLine = 0; 00237 00238 // Create a transparency handler if only drop shadows are enabled. 00239 if (!d->menuHandler && d->menuDropShadow) 00240 d->menuHandler = new TransparencyHandler(this, Disabled, 1.0, d->menuDropShadow); 00241 } 00242 00243 00244 TDEStyle::~TDEStyle() 00245 { 00246 delete d->verticalLine; 00247 delete d->horizontalLine; 00248 00249 delete d->menuHandler; 00250 00251 d->menuHandler = NULL; 00252 delete d; 00253 } 00254 00255 00256 TQString TDEStyle::defaultStyle() 00257 { 00258 if (TQPixmap::defaultDepth() > 8) 00259 return TQString("plastik"); 00260 else 00261 return TQString("light, 3rd revision"); 00262 } 00263 00264 void TDEStyle::polish( const TQStyleControlElementData &ceData, ControlElementFlags elementFlags, void *ptr ) 00265 { 00266 if (ceData.widgetObjectTypes.contains(TQWIDGET_OBJECT_NAME_STRING)) { 00267 TQWidget* widget = reinterpret_cast<TQWidget*>(ptr); 00268 if ( d->useFilledFrameWorkaround ) 00269 { 00270 if ( TQFrame *frame = ::tqqt_cast< TQFrame* >( widget ) ) { 00271 TQFrame::Shape shape = frame->frameShape(); 00272 if (shape == TQFrame::ToolBarPanel || shape == TQFrame::MenuBarPanel) 00273 widget->installEventFilter(this); 00274 } 00275 } 00276 if (widget->isTopLevel()) 00277 { 00278 if (!d->menuHandler && useDropShadow(widget)) 00279 d->menuHandler = new TransparencyHandler(this, Disabled, 1.0, false); 00280 00281 if (d->menuHandler && useDropShadow(widget)) 00282 widget->installEventFilter(d->menuHandler); 00283 } 00284 } 00285 } 00286 00287 00288 void TDEStyle::unPolish( const TQStyleControlElementData &ceData, ControlElementFlags elementFlags, void *ptr ) 00289 { 00290 if (ceData.widgetObjectTypes.contains(TQWIDGET_OBJECT_NAME_STRING)) { 00291 TQWidget* widget = reinterpret_cast<TQWidget*>(ptr); 00292 if ( d->useFilledFrameWorkaround ) 00293 { 00294 if ( TQFrame *frame = ::tqqt_cast< TQFrame* >( widget ) ) { 00295 TQFrame::Shape shape = frame->frameShape(); 00296 if (shape == TQFrame::ToolBarPanel || shape == TQFrame::MenuBarPanel) 00297 widget->removeEventFilter(this); 00298 } 00299 } 00300 if (widget->isTopLevel() && d->menuHandler && useDropShadow(widget)) 00301 widget->removeEventFilter(d->menuHandler); 00302 } 00303 } 00304 00305 00306 // Style changes (should) always re-polish popups. 00307 void TDEStyle::polishPopupMenu( const TQStyleControlElementData &ceData, ControlElementFlags elementFlags, void *ptr ) 00308 { 00309 if ( !(ceData.windowState & WState_Polished ) ) { 00310 widgetActionRequest(ceData, elementFlags, ptr, WAR_SetCheckable); 00311 } 00312 00313 if (ceData.widgetObjectTypes.contains(TQWIDGET_OBJECT_NAME_STRING)) { 00314 TQWidget* widget = reinterpret_cast<TQWidget*>(ptr); 00315 TQPopupMenu *p = dynamic_cast<TQPopupMenu*>(widget); 00316 if (p) { 00317 // Install transparency handler if the effect is enabled. 00318 if ( d->menuHandler && (strcmp(p->name(), "tear off menu") != 0)) { 00319 p->installEventFilter(d->menuHandler); 00320 } 00321 } 00322 } 00323 } 00324 00325 00326 // ----------------------------------------------------------------------------- 00327 // TDEStyle extensions 00328 // ----------------------------------------------------------------------------- 00329 00330 void TDEStyle::setScrollBarType(TDEStyleScrollBarType sbtype) 00331 { 00332 d->scrollbarType = sbtype; 00333 } 00334 00335 TDEStyle::TDEStyleFlags TDEStyle::styleFlags() const 00336 { 00337 return d->flags; 00338 } 00339 00340 void TDEStyle::renderMenuBlendPixmap( KPixmap &pix, const TQColorGroup &cg, 00341 const TQPopupMenu* /* popup */ ) const 00342 { 00343 pix.fill(cg.button()); // Just tint as the default behavior 00344 } 00345 00346 void TDEStyle::drawTDEStylePrimitive( TDEStylePrimitive kpe, 00347 TQPainter* p, 00348 const TQWidget* widget, 00349 const TQRect &r, 00350 const TQColorGroup &cg, 00351 SFlags flags, 00352 const TQStyleOption &opt ) const 00353 { 00354 const TQStyleControlElementData &ceData = populateControlElementDataFromWidget(widget, TQStyleOption()); 00355 drawTDEStylePrimitive(kpe, p, ceData, getControlElementFlagsForObject(widget, TQStyleOption()), r, cg, flags, opt); 00356 } 00357 00358 void TDEStyle::drawTDEStylePrimitive( TDEStylePrimitive kpe, 00359 TQPainter* p, 00360 const TQStyleControlElementData &ceData, 00361 ControlElementFlags elementFlags, 00362 const TQRect &r, 00363 const TQColorGroup &cg, 00364 SFlags flags, 00365 const TQStyleOption&, /* opt */ 00366 const TQWidget* widget ) const 00367 { 00368 switch( kpe ) 00369 { 00370 // Dock / Toolbar / General handles. 00371 // --------------------------------- 00372 00373 case KPE_DockWindowHandle: { 00374 00375 // Draws a nice DockWindow handle including the dock title. 00376 TQWidget* wid = const_cast<TQWidget*>(widget); 00377 bool horizontal = flags & Style_Horizontal; 00378 int x,y,w,h,x2,y2; 00379 00380 r.rect( &x, &y, &w, &h ); 00381 if ((w <= 2) || (h <= 2)) { 00382 p->fillRect(r, cg.highlight()); 00383 return; 00384 } 00385 00386 00387 x2 = x + w - 1; 00388 y2 = y + h - 1; 00389 00390 TQFont fnt; 00391 fnt = TQApplication::font(wid); 00392 fnt.setPointSize( fnt.pointSize()-2 ); 00393 00394 // Draw the item on an off-screen pixmap 00395 // to preserve Xft antialiasing for 00396 // vertically oriented handles. 00397 TQPixmap pix; 00398 if (horizontal) 00399 pix.resize( h-2, w-2 ); 00400 else 00401 pix.resize( w-2, h-2 ); 00402 00403 TQString title = wid->parentWidget()->caption(); 00404 TQPainter p2; 00405 p2.begin(&pix); 00406 p2.fillRect(pix.rect(), cg.brush(TQColorGroup::Highlight)); 00407 p2.setPen(cg.highlightedText()); 00408 p2.setFont(fnt); 00409 p2.drawText(pix.rect(), AlignCenter, title); 00410 p2.end(); 00411 00412 // Draw a sunken bevel 00413 p->setPen(cg.dark()); 00414 p->drawLine(x, y, x2, y); 00415 p->drawLine(x, y, x, y2); 00416 p->setPen(cg.light()); 00417 p->drawLine(x+1, y2, x2, y2); 00418 p->drawLine(x2, y+1, x2, y2); 00419 00420 if (horizontal) { 00421 TQWMatrix m; 00422 m.rotate(-90.0); 00423 TQPixmap vpix = pix.xForm(m); 00424 bitBlt(wid, r.x()+1, r.y()+1, &vpix); 00425 } else 00426 bitBlt(wid, r.x()+1, r.y()+1, &pix); 00427 00428 break; 00429 } 00430 00431 00432 /* 00433 * KPE_ListViewExpander and KPE_ListViewBranch are based on code from 00434 * QWindowStyle's CC_ListView, kindly donated by TrollTech. 00435 * CC_ListView code is Copyright (C) 1998-2000 TrollTech AS. 00436 */ 00437 00438 case KPE_ListViewExpander: { 00439 // Typical Windows style expand/collapse element. 00440 int radius = (r.width() - 4) / 2; 00441 int centerx = r.x() + r.width()/2; 00442 int centery = r.y() + r.height()/2; 00443 00444 // Outer box 00445 p->setPen( cg.mid() ); 00446 p->drawRect( r ); 00447 00448 // plus or minus 00449 p->setPen( cg.text() ); 00450 p->drawLine( centerx - radius, centery, centerx + radius, centery ); 00451 if ( flags & Style_On ) // Collapsed = On 00452 p->drawLine( centerx, centery - radius, centerx, centery + radius ); 00453 break; 00454 } 00455 00456 case KPE_ListViewBranch: { 00457 // Typical Windows style listview branch element (dotted line). 00458 00459 // Create the dotline pixmaps if not already created 00460 if ( !d->verticalLine ) 00461 { 00462 // make 128*1 and 1*128 bitmaps that can be used for 00463 // drawing the right sort of lines. 00464 d->verticalLine = new TQBitmap( 1, 129, true ); 00465 d->horizontalLine = new TQBitmap( 128, 1, true ); 00466 TQPointArray a( 64 ); 00467 TQPainter p2; 00468 p2.begin( d->verticalLine ); 00469 00470 int i; 00471 for( i=0; i < 64; i++ ) 00472 a.setPoint( i, 0, i*2+1 ); 00473 p2.setPen( color1 ); 00474 p2.drawPoints( a ); 00475 p2.end(); 00476 TQApplication::flushX(); 00477 d->verticalLine->setMask( *d->verticalLine ); 00478 00479 p2.begin( d->horizontalLine ); 00480 for( i=0; i < 64; i++ ) 00481 a.setPoint( i, i*2+1, 0 ); 00482 p2.setPen( color1 ); 00483 p2.drawPoints( a ); 00484 p2.end(); 00485 TQApplication::flushX(); 00486 d->horizontalLine->setMask( *d->horizontalLine ); 00487 } 00488 00489 p->setPen( cg.text() ); // cg.dark() is bad for dark color schemes. 00490 00491 if (flags & Style_Horizontal) 00492 { 00493 int point = r.x(); 00494 int other = r.y(); 00495 int end = r.x()+r.width(); 00496 int thickness = r.height(); 00497 00498 while( point < end ) 00499 { 00500 int i = 128; 00501 if ( i+point > end ) 00502 i = end-point; 00503 p->drawPixmap( point, other, *d->horizontalLine, 0, 0, i, thickness ); 00504 point += i; 00505 } 00506 00507 } else { 00508 int point = r.y(); 00509 int other = r.x(); 00510 int end = r.y()+r.height(); 00511 int thickness = r.width(); 00512 int pixmapoffset = (flags & Style_NoChange) ? 0 : 1; // ### Hackish 00513 00514 while( point < end ) 00515 { 00516 int i = 128; 00517 if ( i+point > end ) 00518 i = end-point; 00519 p->drawPixmap( other, point, *d->verticalLine, 0, pixmapoffset, thickness, i ); 00520 point += i; 00521 } 00522 } 00523 00524 break; 00525 } 00526 00527 // Reimplement the other primitives in your styles. 00528 // The current implementation just paints something visibly different. 00529 case KPE_ToolBarHandle: 00530 case KPE_GeneralHandle: 00531 case KPE_SliderHandle: 00532 p->fillRect(r, cg.light()); 00533 break; 00534 00535 case KPE_SliderGroove: 00536 p->fillRect(r, cg.dark()); 00537 break; 00538 00539 default: 00540 p->fillRect(r, Qt::yellow); // Something really bad happened - highlight. 00541 break; 00542 } 00543 } 00544 00545 00546 int TDEStyle::kPixelMetric( TDEStylePixelMetric kpm, const TQStyleControlElementData &ceData, ControlElementFlags elementFlags, const TQWidget* /* widget */) const 00547 { 00548 int value; 00549 switch(kpm) 00550 { 00551 case KPM_ListViewBranchThickness: 00552 value = 1; 00553 break; 00554 00555 case KPM_MenuItemSeparatorHeight: 00556 case KPM_MenuItemHMargin: 00557 case KPM_MenuItemVMargin: 00558 case KPM_MenuItemHFrame: 00559 case KPM_MenuItemVFrame: 00560 case KPM_MenuItemCheckMarkHMargin: 00561 case KPM_MenuItemArrowHMargin: 00562 case KPM_MenuItemTabSpacing: 00563 default: 00564 value = 0; 00565 } 00566 00567 return value; 00568 } 00569 00570 // ----------------------------------------------------------------------------- 00571 00572 // #ifdef USE_QT4 // tdebindings / smoke needs this function declaration available at all times. Furthermore I don't think it would hurt to have the declaration available at all times...so leave these commented out for now 00573 00574 //void TDEStyle::drawPrimitive( TQ_ControlElement pe, 00575 // TQPainter* p, 00576 // const TQStyleControlElementData &ceData, 00577 // ControlElementFlags elementFlags, 00578 // const TQRect &r, 00579 // const TQColorGroup &cg, 00580 // SFlags flags, 00581 // const TQStyleOption& opt ) const 00582 //{ 00583 // // FIXME: 00584 // // What should "widget" be in actuality? How should I get it? From where? 00585 // // Almost certainly it should not be null! 00586 // TQWidget *widget = 0; 00587 // drawControl(pe, p, ceData, elementFlags, r, cg, flags, opt, widget); 00588 //} 00589 00590 // #endif // USE_QT4 00591 00592 // ----------------------------------------------------------------------------- 00593 00594 void TDEStyle::drawPrimitive( TQ_PrimitiveElement pe, 00595 TQPainter* p, 00596 const TQStyleControlElementData &ceData, 00597 ControlElementFlags elementFlags, 00598 const TQRect &r, 00599 const TQColorGroup &cg, 00600 SFlags flags, 00601 const TQStyleOption& opt ) const 00602 { 00603 // TOOLBAR/DOCK WINDOW HANDLE 00604 // ------------------------------------------------------------------------ 00605 if (pe == PE_DockWindowHandle) 00606 { 00607 // Wild workarounds are here. Beware. 00608 TQWidget *widget, *parent; 00609 00610 if (p && p->device()->devType() == TQInternal::Widget) { 00611 widget = static_cast<TQWidget*>(p->device()); 00612 parent = widget->parentWidget(); 00613 } else 00614 return; // Don't paint on non-widgets 00615 00616 // Check if we are a normal toolbar or a hidden dockwidget. 00617 if ( parent && 00618 (parent->inherits(TQTOOLBAR_OBJECT_NAME_STRING) || // Normal toolbar 00619 (parent->inherits(TQMAINWINDOW_OBJECT_NAME_STRING)) )) // Collapsed dock 00620 00621 // Draw a toolbar handle 00622 drawTDEStylePrimitive( KPE_ToolBarHandle, p, ceData, elementFlags, r, cg, flags, opt, widget ); 00623 00624 else if (ceData.widgetObjectTypes.contains(TQDOCKWINDOWHANDLE_OBJECT_NAME_STRING)) 00625 00626 // Draw a dock window handle 00627 drawTDEStylePrimitive( KPE_DockWindowHandle, p, ceData, elementFlags, r, cg, flags, opt, widget ); 00628 00629 else 00630 // General handle, probably a kicker applet handle. 00631 drawTDEStylePrimitive( KPE_GeneralHandle, p, ceData, elementFlags, r, cg, flags, opt, widget ); 00632 #if TQT_VERSION >= 0x030300 00633 #ifdef HAVE_XRENDER 00634 } else if ( d->semiTransparentRubberband && pe == TQStyle::PE_RubberBand ) { 00635 TQRect rect = r.normalize(); 00636 TQPoint point; 00637 point = p->xForm( point ); 00638 00639 static XRenderColor clr = { 0, 0, 0, 0 }; 00640 static unsigned long fillColor = 0; 00641 if ( fillColor != cg.highlight().rgb() ) { 00642 fillColor = cg.highlight().rgb(); 00643 00644 unsigned long color = fillColor << 8 | 0x40; 00645 00646 int red = (color >> 24) & 0xff; 00647 int green = (color >> 16) & 0xff; 00648 int blue = (color >> 8) & 0xff; 00649 int alpha = (color >> 0) & 0xff; 00650 00651 red = red * alpha / 255; 00652 green = green * alpha / 255; 00653 blue = blue * alpha / 255; 00654 00655 clr.red = (red << 8) + red; 00656 clr.green = (green << 8) + green; 00657 clr.blue = (blue << 8) + blue; 00658 clr.alpha = (alpha << 8) + alpha; 00659 } 00660 00661 XRenderFillRectangle( 00662 p->device()->x11Display(), 00663 PictOpOver, 00664 p->device()->x11RenderHandle(), 00665 &clr, 00666 rect.x() + point.x(), 00667 rect.y() + point.y(), 00668 rect.width(), 00669 rect.height() ); 00670 00671 p->save(); 00672 p->setRasterOp( TQt::CopyROP ); 00673 p->setPen( TQPen( cg.highlight().dark( 160 ), 1 ) ); 00674 p->setBrush( NoBrush ); 00675 p->drawRect( 00676 rect.x() + point.x(), 00677 rect.y() + point.y(), 00678 rect.width(), 00679 rect.height() ); 00680 p->restore(); 00681 #endif 00682 #endif 00683 } else 00684 TQCommonStyle::drawPrimitive( pe, p, ceData, elementFlags, r, cg, flags, opt ); 00685 } 00686 00687 00688 00689 void TDEStyle::drawControl( TQ_ControlElement element, 00690 TQPainter* p, 00691 const TQStyleControlElementData &ceData, 00692 ControlElementFlags elementFlags, 00693 const TQRect &r, 00694 const TQColorGroup &cg, 00695 SFlags flags, 00696 const TQStyleOption &opt, 00697 const TQWidget* widget ) const 00698 { 00699 switch (element) 00700 { 00701 // TABS 00702 // ------------------------------------------------------------------------ 00703 case CE_TabBarTab: { 00704 TQTabBar::Shape tbs = ceData.tabBarData.shape; 00705 bool selected = flags & Style_Selected; 00706 int x = r.x(), y=r.y(), bottom=r.bottom(), right=r.right(); 00707 00708 switch (tbs) { 00709 00710 case TQTabBar::RoundedAbove: { 00711 if (!selected) 00712 p->translate(0,1); 00713 p->setPen(selected ? cg.light() : cg.shadow()); 00714 p->drawLine(x, y+4, x, bottom); 00715 p->drawLine(x, y+4, x+4, y); 00716 p->drawLine(x+4, y, right-1, y); 00717 if (selected) 00718 p->setPen(cg.shadow()); 00719 p->drawLine(right, y+1, right, bottom); 00720 00721 p->setPen(cg.midlight()); 00722 p->drawLine(x+1, y+4, x+1, bottom); 00723 p->drawLine(x+1, y+4, x+4, y+1); 00724 p->drawLine(x+5, y+1, right-2, y+1); 00725 00726 if (selected) { 00727 p->setPen(cg.mid()); 00728 p->drawLine(right-1, y+1, right-1, bottom); 00729 } else { 00730 p->setPen(cg.mid()); 00731 p->drawPoint(right-1, y+1); 00732 p->drawLine(x+4, y+2, right-1, y+2); 00733 p->drawLine(x+3, y+3, right-1, y+3); 00734 p->fillRect(x+2, y+4, r.width()-3, r.height()-6, cg.mid()); 00735 00736 p->setPen(cg.light()); 00737 p->drawLine(x, bottom-1, right, bottom-1); 00738 p->translate(0,-1); 00739 } 00740 break; 00741 } 00742 00743 case TQTabBar::RoundedBelow: { 00744 if (!selected) 00745 p->translate(0,-1); 00746 p->setPen(selected ? cg.light() : cg.shadow()); 00747 p->drawLine(x, bottom-4, x, y); 00748 if (selected) 00749 p->setPen(cg.mid()); 00750 p->drawLine(x, bottom-4, x+4, bottom); 00751 if (selected) 00752 p->setPen(cg.shadow()); 00753 p->drawLine(x+4, bottom, right-1, bottom); 00754 p->drawLine(right, bottom-1, right, y); 00755 00756 p->setPen(cg.midlight()); 00757 p->drawLine(x+1, bottom-4, x+1, y); 00758 p->drawLine(x+1, bottom-4, x+4, bottom-1); 00759 p->drawLine(x+5, bottom-1, right-2, bottom-1); 00760 00761 if (selected) { 00762 p->setPen(cg.mid()); 00763 p->drawLine(right-1, y, right-1, bottom-1); 00764 } else { 00765 p->setPen(cg.mid()); 00766 p->drawPoint(right-1, bottom-1); 00767 p->drawLine(x+4, bottom-2, right-1, bottom-2); 00768 p->drawLine(x+3, bottom-3, right-1, bottom-3); 00769 p->fillRect(x+2, y+2, r.width()-3, r.height()-6, cg.mid()); 00770 p->translate(0,1); 00771 p->setPen(cg.dark()); 00772 p->drawLine(x, y, right, y); 00773 } 00774 break; 00775 } 00776 00777 case TQTabBar::TriangularAbove: { 00778 if (!selected) 00779 p->translate(0,1); 00780 p->setPen(selected ? cg.light() : cg.shadow()); 00781 p->drawLine(x, bottom, x, y+6); 00782 p->drawLine(x, y+6, x+6, y); 00783 p->drawLine(x+6, y, right-6, y); 00784 if (selected) 00785 p->setPen(cg.mid()); 00786 p->drawLine(right-5, y+1, right-1, y+5); 00787 p->setPen(cg.shadow()); 00788 p->drawLine(right, y+6, right, bottom); 00789 00790 p->setPen(cg.midlight()); 00791 p->drawLine(x+1, bottom, x+1, y+6); 00792 p->drawLine(x+1, y+6, x+6, y+1); 00793 p->drawLine(x+6, y+1, right-6, y+1); 00794 p->drawLine(right-5, y+2, right-2, y+5); 00795 p->setPen(cg.mid()); 00796 p->drawLine(right-1, y+6, right-1, bottom); 00797 00798 TQPointArray a(6); 00799 a.setPoint(0, x+2, bottom); 00800 a.setPoint(1, x+2, y+7); 00801 a.setPoint(2, x+7, y+2); 00802 a.setPoint(3, right-7, y+2); 00803 a.setPoint(4, right-2, y+7); 00804 a.setPoint(5, right-2, bottom); 00805 p->setPen (selected ? cg.background() : cg.mid()); 00806 p->setBrush(selected ? cg.background() : cg.mid()); 00807 p->drawPolygon(a); 00808 p->setBrush(NoBrush); 00809 if (!selected) { 00810 p->translate(0,-1); 00811 p->setPen(cg.light()); 00812 p->drawLine(x, bottom, right, bottom); 00813 } 00814 break; 00815 } 00816 00817 default: { // TQTabBar::TriangularBelow 00818 if (!selected) 00819 p->translate(0,-1); 00820 p->setPen(selected ? cg.light() : cg.shadow()); 00821 p->drawLine(x, y, x, bottom-6); 00822 if (selected) 00823 p->setPen(cg.mid()); 00824 p->drawLine(x, bottom-6, x+6, bottom); 00825 if (selected) 00826 p->setPen(cg.shadow()); 00827 p->drawLine(x+6, bottom, right-6, bottom); 00828 p->drawLine(right-5, bottom-1, right-1, bottom-5); 00829 if (!selected) 00830 p->setPen(cg.shadow()); 00831 p->drawLine(right, bottom-6, right, y); 00832 00833 p->setPen(cg.midlight()); 00834 p->drawLine(x+1, y, x+1, bottom-6); 00835 p->drawLine(x+1, bottom-6, x+6, bottom-1); 00836 p->drawLine(x+6, bottom-1, right-6, bottom-1); 00837 p->drawLine(right-5, bottom-2, right-2, bottom-5); 00838 p->setPen(cg.mid()); 00839 p->drawLine(right-1, bottom-6, right-1, y); 00840 00841 TQPointArray a(6); 00842 a.setPoint(0, x+2, y); 00843 a.setPoint(1, x+2, bottom-7); 00844 a.setPoint(2, x+7, bottom-2); 00845 a.setPoint(3, right-7, bottom-2); 00846 a.setPoint(4, right-2, bottom-7); 00847 a.setPoint(5, right-2, y); 00848 p->setPen (selected ? cg.background() : cg.mid()); 00849 p->setBrush(selected ? cg.background() : cg.mid()); 00850 p->drawPolygon(a); 00851 p->setBrush(NoBrush); 00852 if (!selected) { 00853 p->translate(0,1); 00854 p->setPen(cg.dark()); 00855 p->drawLine(x, y, right, y); 00856 } 00857 break; 00858 } 00859 }; 00860 00861 break; 00862 } 00863 00864 // Popup menu scroller 00865 // ------------------------------------------------------------------------ 00866 case CE_PopupMenuScroller: { 00867 p->fillRect(r, cg.background()); 00868 drawPrimitive(PE_ButtonTool, p, ceData, elementFlags, r, cg, Style_Enabled); 00869 drawPrimitive((flags & Style_Up) ? PE_ArrowUp : PE_ArrowDown, p, ceData, elementFlags, r, cg, Style_Enabled); 00870 break; 00871 } 00872 00873 00874 // PROGRESSBAR 00875 // ------------------------------------------------------------------------ 00876 case CE_ProgressBarGroove: { 00877 TQRect fr = subRect(SR_ProgressBarGroove, ceData, elementFlags, widget); 00878 drawPrimitive(PE_Panel, p, ceData, elementFlags, fr, cg, Style_Sunken, TQStyleOption::SO_Default); 00879 break; 00880 } 00881 00882 case CE_ProgressBarContents: { 00883 // ### Take into account totalSteps() for busy indicator 00884 TQRect cr = subRect(SR_ProgressBarContents, ceData, elementFlags, widget); 00885 double progress = ceData.currentStep; 00886 bool reverse = TQApplication::reverseLayout(); 00887 int steps = ceData.totalSteps; 00888 00889 if (!cr.isValid()) 00890 return; 00891 00892 // Draw progress bar 00893 if (progress > 0 || steps == 0) { 00894 double pg = (steps == 0) ? 0.1 : progress / steps; 00895 int width = TQMIN(cr.width(), (int)(pg * cr.width())); 00896 if (steps == 0) { //Busy indicator 00897 00898 if (width < 1) width = 1; //A busy indicator with width 0 is kind of useless 00899 00900 int remWidth = cr.width() - width; //Never disappear completely 00901 if (remWidth <= 0) remWidth = 1; //Do something non-crashy when too small... 00902 00903 int pstep = int(progress) % ( 2 * remWidth ); 00904 00905 if ( pstep > remWidth ) { 00906 //Bounce about.. We're remWidth + some delta, we want to be remWidth - delta... 00907 // - ( (remWidth + some delta) - 2* remWidth ) = - (some deleta - remWidth) = remWidth - some delta.. 00908 pstep = - (pstep - 2 * remWidth ); 00909 } 00910 00911 if (reverse) 00912 p->fillRect(cr.x() + cr.width() - width - pstep, cr.y(), width, cr.height(), 00913 cg.brush(TQColorGroup::Highlight)); 00914 else 00915 p->fillRect(cr.x() + pstep, cr.y(), width, cr.height(), 00916 cg.brush(TQColorGroup::Highlight)); 00917 00918 return; 00919 } 00920 00921 00922 // Do fancy gradient for highcolor displays 00923 if (d->highcolor) { 00924 TQColor c(cg.highlight()); 00925 KPixmap pix; 00926 pix.resize(cr.width(), cr.height()); 00927 KPixmapEffect::gradient(pix, reverse ? c.light(150) : c.dark(150), 00928 reverse ? c.dark(150) : c.light(150), 00929 KPixmapEffect::HorizontalGradient); 00930 if (reverse) 00931 p->drawPixmap(cr.x()+(cr.width()-width), cr.y(), pix, 00932 cr.width()-width, 0, width, cr.height()); 00933 else 00934 p->drawPixmap(cr.x(), cr.y(), pix, 0, 0, width, cr.height()); 00935 } else 00936 if (reverse) 00937 p->fillRect(cr.x()+(cr.width()-width), cr.y(), width, cr.height(), 00938 cg.brush(TQColorGroup::Highlight)); 00939 else 00940 p->fillRect(cr.x(), cr.y(), width, cr.height(), 00941 cg.brush(TQColorGroup::Highlight)); 00942 } 00943 break; 00944 } 00945 00946 case CE_ProgressBarLabel: { 00947 TQRect cr = subRect(SR_ProgressBarContents, ceData, elementFlags, widget); 00948 double progress = ceData.currentStep; 00949 bool reverse = TQApplication::reverseLayout(); 00950 int steps = ceData.totalSteps; 00951 00952 if (!cr.isValid()) 00953 return; 00954 00955 TQFont font = p->font(); 00956 font.setBold(true); 00957 p->setFont(font); 00958 00959 // Draw label 00960 if (progress > 0 || steps == 0) { 00961 double pg = (steps == 0) ? 1.0 : progress / steps; 00962 int width = TQMIN(cr.width(), (int)(pg * cr.width())); 00963 TQRect crect; 00964 if (reverse) 00965 crect.setRect(cr.x()+(cr.width()-width), cr.y(), cr.width(), cr.height()); 00966 else 00967 crect.setRect(cr.x()+width, cr.y(), cr.width(), cr.height()); 00968 00969 p->save(); 00970 p->setPen((elementFlags & CEF_IsEnabled) ? (reverse ? cg.text() : cg.highlightedText()) : cg.text()); 00971 p->drawText(r, AlignCenter, ceData.progressText); 00972 p->setClipRect(crect); 00973 p->setPen(reverse ? cg.highlightedText() : cg.text()); 00974 p->drawText(r, AlignCenter, ceData.progressText); 00975 p->restore(); 00976 00977 } else { 00978 p->setPen(cg.text()); 00979 p->drawText(r, AlignCenter, ceData.progressText); 00980 } 00981 00982 break; 00983 } 00984 00985 default: 00986 TQCommonStyle::drawControl(element, p, ceData, elementFlags, r, cg, flags, opt, widget); 00987 } 00988 } 00989 00990 00991 TQRect TDEStyle::subRect(SubRect r, const TQStyleControlElementData &ceData, const ControlElementFlags elementFlags, const TQWidget* widget) const 00992 { 00993 switch(r) 00994 { 00995 // KDE2 look smooth progress bar 00996 // ------------------------------------------------------------------------ 00997 case SR_ProgressBarGroove: 00998 return ceData.rect; 00999 01000 case SR_ProgressBarContents: 01001 case SR_ProgressBarLabel: { 01002 // ### take into account indicatorFollowsStyle() 01003 TQRect rt = ceData.rect; 01004 return TQRect(rt.x()+2, rt.y()+2, rt.width()-4, rt.height()-4); 01005 } 01006 01007 default: 01008 return TQCommonStyle::subRect(r, ceData, elementFlags, widget); 01009 } 01010 } 01011 01012 01013 int TDEStyle::pixelMetric(PixelMetric m, const TQStyleControlElementData &ceData, ControlElementFlags elementFlags, const TQWidget* widget) const 01014 { 01015 switch(m) 01016 { 01017 // BUTTONS 01018 // ------------------------------------------------------------------------ 01019 case PM_ButtonShiftHorizontal: // Offset by 1 01020 case PM_ButtonShiftVertical: // ### Make configurable 01021 return 1; 01022 01023 case PM_DockWindowHandleExtent: 01024 { 01025 // Check that we are not a normal toolbar or a hidden dockwidget, 01026 // in which case we need to adjust the height for font size 01027 if (widget 01028 && !(ceData.parentWidgetData.widgetObjectTypes.contains(TQTOOLBAR_OBJECT_NAME_STRING)) 01029 && !(ceData.parentWidgetData.widgetObjectTypes.contains(TQMAINWINDOW_OBJECT_NAME_STRING)) 01030 && (ceData.widgetObjectTypes.contains(TQDOCKWINDOWHANDLE_OBJECT_NAME_STRING)) ) 01031 return widget->fontMetrics().lineSpacing(); 01032 else 01033 return TQCommonStyle::pixelMetric(m, ceData, elementFlags, widget); 01034 } 01035 01036 // TABS 01037 // ------------------------------------------------------------------------ 01038 case PM_TabBarTabHSpace: 01039 return 24; 01040 01041 case PM_TabBarTabVSpace: { 01042 if ( ceData.tabBarData.shape == TQTabBar::RoundedAbove || 01043 ceData.tabBarData.shape == TQTabBar::RoundedBelow ) 01044 return 10; 01045 else 01046 return 4; 01047 } 01048 01049 case PM_TabBarTabOverlap: { 01050 TQTabBar::Shape tbs = ceData.tabBarData.shape; 01051 01052 if ( (tbs == TQTabBar::RoundedAbove) || 01053 (tbs == TQTabBar::RoundedBelow) ) 01054 return 0; 01055 else 01056 return 2; 01057 } 01058 01059 // SLIDER 01060 // ------------------------------------------------------------------------ 01061 case PM_SliderLength: 01062 return 18; 01063 01064 case PM_SliderThickness: 01065 return 24; 01066 01067 // Determines how much space to leave for the actual non-tickmark 01068 // portion of the slider. 01069 case PM_SliderControlThickness: { 01070 TQSlider::TickSetting ts = (TQSlider::TickSetting)ceData.tickMarkSetting; 01071 int thickness = (ceData.orientation == TQt::Horizontal) ? 01072 ceData.rect.height() : ceData.rect.width(); 01073 switch (ts) { 01074 case TQSlider::NoMarks: // Use total area. 01075 break; 01076 case TQSlider::Both: 01077 thickness = (thickness/2) + 3; // Use approx. 1/2 of area. 01078 break; 01079 default: // Use approx. 2/3 of area 01080 thickness = ((thickness*2)/3) + 3; 01081 break; 01082 }; 01083 return thickness; 01084 } 01085 01086 // SPLITTER 01087 // ------------------------------------------------------------------------ 01088 case PM_SplitterWidth: 01089 if (ceData.widgetObjectTypes.contains(TQDOCKWINDOWRESIZEHANDLE_OBJECT_NAME_STRING)) 01090 return 8; // ### why do we need 2pix extra? 01091 else 01092 return 6; 01093 01094 // FRAMES 01095 // ------------------------------------------------------------------------ 01096 case PM_MenuBarFrameWidth: 01097 return 1; 01098 01099 case PM_DockWindowFrameWidth: 01100 return 1; 01101 01102 // GENERAL 01103 // ------------------------------------------------------------------------ 01104 case PM_MaximumDragDistance: 01105 return -1; 01106 01107 case PM_MenuBarItemSpacing: 01108 return 5; 01109 01110 case PM_ToolBarItemSpacing: 01111 return 0; 01112 01113 case PM_PopupMenuScrollerHeight: 01114 return pixelMetric( PM_ScrollBarExtent, ceData, elementFlags, 0); 01115 01116 default: 01117 return TQCommonStyle::pixelMetric( m, ceData, elementFlags, widget ); 01118 } 01119 } 01120 01121 //Helper to find the next sibling that's not hidden 01122 static TQListViewItem* nextVisibleSibling(TQListViewItem* item) 01123 { 01124 TQListViewItem* sibling = item; 01125 do 01126 { 01127 sibling = sibling->nextSibling(); 01128 } 01129 while (sibling && !sibling->isVisible()); 01130 01131 return sibling; 01132 } 01133 01134 void TDEStyle::drawComplexControl( TQ_ComplexControl control, 01135 TQPainter* p, 01136 const TQStyleControlElementData &ceData, 01137 ControlElementFlags elementFlags, 01138 const TQRect &r, 01139 const TQColorGroup &cg, 01140 SFlags flags, 01141 SCFlags controls, 01142 SCFlags active, 01143 const TQStyleOption &opt, 01144 const TQWidget* widget ) const 01145 { 01146 switch(control) 01147 { 01148 // 3 BUTTON SCROLLBAR 01149 // ------------------------------------------------------------------------ 01150 case CC_ScrollBar: { 01151 // Many thanks to Brad Hughes for contributing this code. 01152 bool useThreeButtonScrollBar = (d->scrollbarType & ThreeButtonScrollBar); 01153 01154 bool maxedOut = (ceData.minSteps == ceData.maxSteps); 01155 bool horizontal = (ceData.orientation == TQt::Horizontal); 01156 SFlags sflags = ((horizontal ? Style_Horizontal : Style_Default) | 01157 (maxedOut ? Style_Default : Style_Enabled)); 01158 01159 TQRect addline, subline, subline2, addpage, subpage, slider, first, last; 01160 subline = querySubControlMetrics(control, ceData, elementFlags, SC_ScrollBarSubLine, opt, widget); 01161 addline = querySubControlMetrics(control, ceData, elementFlags, SC_ScrollBarAddLine, opt, widget); 01162 subpage = querySubControlMetrics(control, ceData, elementFlags, SC_ScrollBarSubPage, opt, widget); 01163 addpage = querySubControlMetrics(control, ceData, elementFlags, SC_ScrollBarAddPage, opt, widget); 01164 slider = querySubControlMetrics(control, ceData, elementFlags, SC_ScrollBarSlider, opt, widget); 01165 first = querySubControlMetrics(control, ceData, elementFlags, SC_ScrollBarFirst, opt, widget); 01166 last = querySubControlMetrics(control, ceData, elementFlags, SC_ScrollBarLast, opt, widget); 01167 subline2 = addline; 01168 01169 if ( useThreeButtonScrollBar ) { 01170 if (horizontal) { 01171 subline2.moveBy(-addline.width(), 0); 01172 } 01173 else { 01174 subline2.moveBy(0, -addline.height()); 01175 } 01176 } 01177 01178 // Draw the up/left button set 01179 if ((controls & SC_ScrollBarSubLine) && subline.isValid()) { 01180 drawPrimitive(PE_ScrollBarSubLine, p, ceData, elementFlags, subline, cg, 01181 sflags | (active == SC_ScrollBarSubLine ? 01182 Style_Down : Style_Default)); 01183 01184 if (useThreeButtonScrollBar && subline2.isValid()) 01185 drawPrimitive(PE_ScrollBarSubLine, p, ceData, elementFlags, subline2, cg, 01186 sflags | (active == SC_ScrollBarSubLine ? 01187 Style_Down : Style_Default)); 01188 } 01189 01190 if ((controls & SC_ScrollBarAddLine) && addline.isValid()) 01191 drawPrimitive(PE_ScrollBarAddLine, p, ceData, elementFlags, addline, cg, 01192 sflags | ((active == SC_ScrollBarAddLine) ? 01193 Style_Down : Style_Default)); 01194 01195 if ((controls & SC_ScrollBarSubPage) && subpage.isValid()) 01196 drawPrimitive(PE_ScrollBarSubPage, p, ceData, elementFlags, subpage, cg, 01197 sflags | ((active == SC_ScrollBarSubPage) ? 01198 Style_Down : Style_Default)); 01199 01200 if ((controls & SC_ScrollBarAddPage) && addpage.isValid()) 01201 drawPrimitive(PE_ScrollBarAddPage, p, ceData, elementFlags, addpage, cg, 01202 sflags | ((active == SC_ScrollBarAddPage) ? 01203 Style_Down : Style_Default)); 01204 01205 if ((controls & SC_ScrollBarFirst) && first.isValid()) 01206 drawPrimitive(PE_ScrollBarFirst, p, ceData, elementFlags, first, cg, 01207 sflags | ((active == SC_ScrollBarFirst) ? 01208 Style_Down : Style_Default)); 01209 01210 if ((controls & SC_ScrollBarLast) && last.isValid()) 01211 drawPrimitive(PE_ScrollBarLast, p, ceData, elementFlags, last, cg, 01212 sflags | ((active == SC_ScrollBarLast) ? 01213 Style_Down : Style_Default)); 01214 01215 if ((controls & SC_ScrollBarSlider) && slider.isValid()) { 01216 drawPrimitive(PE_ScrollBarSlider, p, ceData, elementFlags, slider, cg, 01217 sflags | ((active == SC_ScrollBarSlider) ? 01218 Style_Down : Style_Default)); 01219 // Draw focus rect 01220 if (elementFlags & CEF_HasFocus) { 01221 TQRect fr(slider.x() + 2, slider.y() + 2, 01222 slider.width() - 5, slider.height() - 5); 01223 drawPrimitive(PE_FocusRect, p, ceData, elementFlags, fr, cg, Style_Default); 01224 } 01225 } 01226 break; 01227 } 01228 01229 01230 // SLIDER 01231 // ------------------------------------------------------------------- 01232 case CC_Slider: { 01233 TQRect groove = querySubControlMetrics(CC_Slider, ceData, elementFlags, SC_SliderGroove, opt, widget); 01234 TQRect handle = querySubControlMetrics(CC_Slider, ceData, elementFlags, SC_SliderHandle, opt, widget); 01235 01236 // Double-buffer slider for no flicker 01237 TQPixmap pix(ceData.rect.size()); 01238 TQPainter p2; 01239 p2.begin(&pix); 01240 01241 if ( (elementFlags & CEF_HasParentWidget) && 01242 !ceData.parentWidgetData.bgPixmap.isNull() ) { 01243 TQPixmap pixmap = ceData.parentWidgetData.bgPixmap; 01244 p2.drawTiledPixmap(r, pixmap, ceData.pos); 01245 } else 01246 pix.fill(cg.background()); 01247 01248 // Draw slider groove 01249 if ((controls & SC_SliderGroove) && groove.isValid()) { 01250 drawTDEStylePrimitive( KPE_SliderGroove, &p2, ceData, elementFlags, groove, cg, flags, opt, widget ); 01251 01252 // Draw the focus rect around the groove 01253 if (elementFlags & CEF_HasFocus) { 01254 drawPrimitive(PE_FocusRect, &p2, ceData, elementFlags, groove, cg); 01255 } 01256 } 01257 01258 // Draw the tickmarks 01259 if (controls & SC_SliderTickmarks) 01260 TQCommonStyle::drawComplexControl(control, &p2, ceData, elementFlags, 01261 r, cg, flags, SC_SliderTickmarks, active, opt, widget); 01262 01263 // Draw the slider handle 01264 if ((controls & SC_SliderHandle) && handle.isValid()) { 01265 if (active == SC_SliderHandle) 01266 flags |= Style_Active; 01267 drawTDEStylePrimitive( KPE_SliderHandle, &p2, ceData, elementFlags, handle, cg, flags, opt, widget ); 01268 } 01269 01270 p2.end(); 01271 01272 TQPaintDevice* ppd = p->device(); 01273 if (ppd->isExtDev()) { 01274 p->drawPixmap(0, 0, pix); 01275 } 01276 else { 01277 bitBlt((TQWidget*)widget, r.x(), r.y(), &pix); 01278 } 01279 break; 01280 } 01281 01282 // LISTVIEW 01283 // ------------------------------------------------------------------- 01284 case CC_ListView: { 01285 01286 /* 01287 * Many thanks to TrollTech AS for donating CC_ListView from TQWindowsStyle. 01288 * CC_ListView code is Copyright (C) 1998-2000 TrollTech AS. 01289 */ 01290 01291 // Paint the icon and text. 01292 if ( controls & SC_ListView ) 01293 TQCommonStyle::drawComplexControl( control, p, ceData, elementFlags, r, cg, flags, controls, active, opt, widget ); 01294 01295 // If we're have a branch or are expanded... 01296 if ( controls & (SC_ListViewBranch | SC_ListViewExpand) ) 01297 { 01298 // If no list view item was supplied, break 01299 if (opt.isDefault()) 01300 break; 01301 01302 TQListViewItem *item = opt.listViewItem(); 01303 TQListViewItem *child = item->firstChild(); 01304 01305 int y = r.y(); 01306 int c; // dotline vertice count 01307 int dotoffset = 0; 01308 TQPointArray dotlines; 01309 01310 if ( active == SC_All && controls == SC_ListViewExpand ) { 01311 // We only need to draw a vertical line 01312 c = 2; 01313 dotlines.resize(2); 01314 dotlines[0] = TQPoint( r.right(), r.top() ); 01315 dotlines[1] = TQPoint( r.right(), r.bottom() ); 01316 01317 } else { 01318 01319 int linetop = 0, linebot = 0; 01320 // each branch needs at most two lines, ie. four end points 01321 dotoffset = (item->itemPos() + item->height() - y) % 2; 01322 dotlines.resize( item->childCount() * 4 ); 01323 c = 0; 01324 01325 // skip the stuff above the exposed rectangle 01326 while ( child && y + child->height() <= 0 ) 01327 { 01328 y += child->totalHeight(); 01329 child = nextVisibleSibling(child); 01330 } 01331 01332 int bx = r.width() / 2; 01333 01334 // paint stuff in the magical area 01335 TQListView* v = item->listView(); 01336 int lh = TQMAX( p->fontMetrics().height() + 2 * v->itemMargin(), 01337 TQApplication::globalStrut().height() ); 01338 if ( lh % 2 > 0 ) 01339 lh++; 01340 01341 // Draw all the expand/close boxes... 01342 TQRect boxrect; 01343 TQStyle::StyleFlags boxflags; 01344 while ( child && y < r.height() ) 01345 { 01346 linebot = y + lh/2; 01347 if ( (child->isExpandable() || child->childCount()) && 01348 (child->height() > 0) ) 01349 { 01350 // The primitive requires a rect. 01351 boxrect = TQRect( bx-4, linebot-4, 9, 9 ); 01352 boxflags = child->isOpen() ? TQStyle::Style_Off : TQStyle::Style_On; 01353 01354 // TDEStyle extension: Draw the box and expand/collapse indicator 01355 drawTDEStylePrimitive( KPE_ListViewExpander, p, ceData, elementFlags, boxrect, cg, boxflags, opt, NULL ); 01356 01357 // dotlinery 01358 p->setPen( cg.mid() ); 01359 dotlines[c++] = TQPoint( bx, linetop ); 01360 dotlines[c++] = TQPoint( bx, linebot - 5 ); 01361 dotlines[c++] = TQPoint( bx + 5, linebot ); 01362 dotlines[c++] = TQPoint( r.width(), linebot ); 01363 linetop = linebot + 5; 01364 } else { 01365 // just dotlinery 01366 dotlines[c++] = TQPoint( bx+1, linebot ); 01367 dotlines[c++] = TQPoint( r.width(), linebot ); 01368 } 01369 01370 y += child->totalHeight(); 01371 child = nextVisibleSibling(child); 01372 } 01373 01374 if ( child ) // there's a child to draw, so move linebot to edge of rectangle 01375 linebot = r.height(); 01376 01377 if ( linetop < linebot ) 01378 { 01379 dotlines[c++] = TQPoint( bx, linetop ); 01380 dotlines[c++] = TQPoint( bx, linebot ); 01381 } 01382 } 01383 01384 // Draw all the branches... 01385 static int thickness = kPixelMetric( KPM_ListViewBranchThickness, ceData, elementFlags ); 01386 int line; // index into dotlines 01387 TQRect branchrect; 01388 TQStyle::StyleFlags branchflags; 01389 for( line = 0; line < c; line += 2 ) 01390 { 01391 // assumptions here: lines are horizontal or vertical. 01392 // lines always start with the numerically lowest 01393 // coordinate. 01394 01395 // point ... relevant coordinate of current point 01396 // end ..... same coordinate of the end of the current line 01397 // other ... the other coordinate of the current point/line 01398 if ( dotlines[line].y() == dotlines[line+1].y() ) 01399 { 01400 // Horizontal branch 01401 int end = dotlines[line+1].x(); 01402 int point = dotlines[line].x(); 01403 int other = dotlines[line].y(); 01404 01405 branchrect = TQRect( point, other-(thickness/2), end-point, thickness ); 01406 branchflags = TQStyle::Style_Horizontal; 01407 01408 // TDEStyle extension: Draw the horizontal branch 01409 drawTDEStylePrimitive( KPE_ListViewBranch, p, ceData, elementFlags, branchrect, cg, branchflags, opt, NULL ); 01410 01411 } else { 01412 // Vertical branch 01413 int end = dotlines[line+1].y(); 01414 int point = dotlines[line].y(); 01415 int other = dotlines[line].x(); 01416 int pixmapoffset = ((point & 1) != dotoffset ) ? 1 : 0; 01417 01418 branchrect = TQRect( other-(thickness/2), point, thickness, end-point ); 01419 if (!pixmapoffset) // ### Hackish - used to hint the offset 01420 branchflags = TQStyle::Style_NoChange; 01421 else 01422 branchflags = TQStyle::Style_Default; 01423 01424 // TDEStyle extension: Draw the vertical branch 01425 drawTDEStylePrimitive( KPE_ListViewBranch, p, ceData, elementFlags, branchrect, cg, branchflags, opt, NULL ); 01426 } 01427 } 01428 } 01429 break; 01430 } 01431 01432 default: 01433 TQCommonStyle::drawComplexControl( control, p, ceData, elementFlags, r, cg, 01434 flags, controls, active, opt, widget ); 01435 break; 01436 } 01437 } 01438 01439 01440 TQStyle::SubControl TDEStyle::querySubControl( TQ_ComplexControl control, 01441 const TQStyleControlElementData &ceData, 01442 ControlElementFlags elementFlags, 01443 const TQPoint &pos, 01444 const TQStyleOption &opt, 01445 const TQWidget* widget ) const 01446 { 01447 TQStyle::SubControl ret = TQCommonStyle::querySubControl(control, ceData, elementFlags, pos, opt, widget); 01448 01449 if (d->scrollbarType == ThreeButtonScrollBar) { 01450 // Enable third button 01451 if (control == CC_ScrollBar && ret == SC_None) 01452 ret = SC_ScrollBarSubLine; 01453 } 01454 return ret; 01455 } 01456 01457 01458 TQRect TDEStyle::querySubControlMetrics( TQ_ComplexControl control, 01459 const TQStyleControlElementData &ceData, 01460 ControlElementFlags elementFlags, 01461 SubControl sc, 01462 const TQStyleOption &opt, 01463 const TQWidget* widget ) const 01464 { 01465 TQRect ret; 01466 01467 if (control == CC_ScrollBar) 01468 { 01469 bool threeButtonScrollBar = d->scrollbarType & ThreeButtonScrollBar; 01470 bool platinumScrollBar = d->scrollbarType & PlatinumStyleScrollBar; 01471 bool nextScrollBar = d->scrollbarType & NextStyleScrollBar; 01472 01473 bool horizontal = ceData.orientation == TQt::Horizontal; 01474 int sliderstart = ceData.startStep; 01475 int sbextent = pixelMetric(PM_ScrollBarExtent, ceData, elementFlags, widget); 01476 int maxlen = (horizontal ? ceData.rect.width() : ceData.rect.height()) 01477 - (sbextent * (threeButtonScrollBar ? 3 : 2)); 01478 int sliderlen; 01479 01480 // calculate slider length 01481 if (ceData.maxSteps != ceData.minSteps) 01482 { 01483 uint range = ceData.maxSteps - ceData.minSteps; 01484 sliderlen = (ceData.pageStep * maxlen) / (range + ceData.pageStep); 01485 01486 int slidermin = pixelMetric( PM_ScrollBarSliderMin, ceData, elementFlags, widget ); 01487 if ( sliderlen < slidermin || range > INT_MAX / 2 ) 01488 sliderlen = slidermin; 01489 if ( sliderlen > maxlen ) 01490 sliderlen = maxlen; 01491 } else 01492 sliderlen = maxlen; 01493 01494 // Subcontrols 01495 switch (sc) 01496 { 01497 case SC_ScrollBarSubLine: { 01498 // top/left button 01499 if (platinumScrollBar) { 01500 if (horizontal) 01501 ret.setRect(ceData.rect.width() - 2 * sbextent, 0, sbextent, sbextent); 01502 else 01503 ret.setRect(0, ceData.rect.height() - 2 * sbextent, sbextent, sbextent); 01504 } else 01505 ret.setRect(0, 0, sbextent, sbextent); 01506 break; 01507 } 01508 01509 case SC_ScrollBarAddLine: { 01510 // bottom/right button 01511 if (nextScrollBar) { 01512 if (horizontal) 01513 ret.setRect(sbextent, 0, sbextent, sbextent); 01514 else 01515 ret.setRect(0, sbextent, sbextent, sbextent); 01516 } else { 01517 if (horizontal) 01518 ret.setRect(ceData.rect.width() - sbextent, 0, sbextent, sbextent); 01519 else 01520 ret.setRect(0, ceData.rect.height() - sbextent, sbextent, sbextent); 01521 } 01522 break; 01523 } 01524 01525 case SC_ScrollBarSubPage: { 01526 // between top/left button and slider 01527 if (platinumScrollBar) { 01528 if (horizontal) 01529 ret.setRect(0, 0, sliderstart, sbextent); 01530 else 01531 ret.setRect(0, 0, sbextent, sliderstart); 01532 } else if (nextScrollBar) { 01533 if (horizontal) 01534 ret.setRect(sbextent*2, 0, sliderstart-2*sbextent, sbextent); 01535 else 01536 ret.setRect(0, sbextent*2, sbextent, sliderstart-2*sbextent); 01537 } else { 01538 if (horizontal) 01539 ret.setRect(sbextent, 0, sliderstart - sbextent, sbextent); 01540 else 01541 ret.setRect(0, sbextent, sbextent, sliderstart - sbextent); 01542 } 01543 break; 01544 } 01545 01546 case SC_ScrollBarAddPage: { 01547 // between bottom/right button and slider 01548 int fudge; 01549 01550 if (platinumScrollBar) 01551 fudge = 0; 01552 else if (nextScrollBar) 01553 fudge = 2*sbextent; 01554 else 01555 fudge = sbextent; 01556 01557 if (horizontal) 01558 ret.setRect(sliderstart + sliderlen, 0, 01559 maxlen - sliderstart - sliderlen + fudge, sbextent); 01560 else 01561 ret.setRect(0, sliderstart + sliderlen, sbextent, 01562 maxlen - sliderstart - sliderlen + fudge); 01563 break; 01564 } 01565 01566 case SC_ScrollBarGroove: { 01567 int multi = threeButtonScrollBar ? 3 : 2; 01568 int fudge; 01569 01570 if (platinumScrollBar) 01571 fudge = 0; 01572 else if (nextScrollBar) 01573 fudge = 2*sbextent; 01574 else 01575 fudge = sbextent; 01576 01577 if (horizontal) 01578 ret.setRect(fudge, 0, ceData.rect.width() - sbextent * multi, ceData.rect.height()); 01579 else 01580 ret.setRect(0, fudge, ceData.rect.width(), ceData.rect.height() - sbextent * multi); 01581 break; 01582 } 01583 01584 case SC_ScrollBarSlider: { 01585 if (horizontal) 01586 ret.setRect(sliderstart, 0, sliderlen, sbextent); 01587 else 01588 ret.setRect(0, sliderstart, sbextent, sliderlen); 01589 break; 01590 } 01591 01592 default: 01593 ret = TQCommonStyle::querySubControlMetrics(control, ceData, elementFlags, sc, opt, widget); 01594 break; 01595 } 01596 } else 01597 ret = TQCommonStyle::querySubControlMetrics(control, ceData, elementFlags, sc, opt, widget); 01598 01599 return ret; 01600 } 01601 01602 static const char * const tdestyle_close_xpm[] = { 01603 "12 12 2 1", 01604 "# c #000000", 01605 ". c None", 01606 "............", 01607 "............", 01608 "..##....##..", 01609 "...##..##...", 01610 "....####....", 01611 ".....##.....", 01612 "....####....", 01613 "...##..##...", 01614 "..##....##..", 01615 "............", 01616 "............", 01617 "............"}; 01618 01619 static const char * const tdestyle_maximize_xpm[]={ 01620 "12 12 2 1", 01621 "# c #000000", 01622 ". c None", 01623 "............", 01624 "............", 01625 ".##########.", 01626 ".##########.", 01627 ".#........#.", 01628 ".#........#.", 01629 ".#........#.", 01630 ".#........#.", 01631 ".#........#.", 01632 ".#........#.", 01633 ".##########.", 01634 "............"}; 01635 01636 01637 static const char * const tdestyle_minimize_xpm[] = { 01638 "12 12 2 1", 01639 "# c #000000", 01640 ". c None", 01641 "............", 01642 "............", 01643 "............", 01644 "............", 01645 "............", 01646 "............", 01647 "............", 01648 "...######...", 01649 "...######...", 01650 "............", 01651 "............", 01652 "............"}; 01653 01654 static const char * const tdestyle_normalizeup_xpm[] = { 01655 "12 12 2 1", 01656 "# c #000000", 01657 ". c None", 01658 "............", 01659 "...#######..", 01660 "...#######..", 01661 "...#.....#..", 01662 ".#######.#..", 01663 ".#######.#..", 01664 ".#.....#.#..", 01665 ".#.....###..", 01666 ".#.....#....", 01667 ".#.....#....", 01668 ".#######....", 01669 "............"}; 01670 01671 01672 static const char * const tdestyle_shade_xpm[] = { 01673 "12 12 2 1", 01674 "# c #000000", 01675 ". c None", 01676 "............", 01677 "............", 01678 "............", 01679 "............", 01680 "............", 01681 ".....#......", 01682 "....###.....", 01683 "...#####....", 01684 "..#######...", 01685 "............", 01686 "............", 01687 "............"}; 01688 01689 static const char * const tdestyle_unshade_xpm[] = { 01690 "12 12 2 1", 01691 "# c #000000", 01692 ". c None", 01693 "............", 01694 "............", 01695 "............", 01696 "............", 01697 "..#######...", 01698 "...#####....", 01699 "....###.....", 01700 ".....#......", 01701 "............", 01702 "............", 01703 "............", 01704 "............"}; 01705 01706 static const char * const dock_window_close_xpm[] = { 01707 "8 8 2 1", 01708 "# c #000000", 01709 ". c None", 01710 "##....##", 01711 ".##..##.", 01712 "..####..", 01713 "...##...", 01714 "..####..", 01715 ".##..##.", 01716 "##....##", 01717 "........"}; 01718 01719 // Message box icons, from page 210 of the Windows style guide. 01720 01721 // Hand-drawn to resemble Microsoft's icons, but in the Mac/Netscape 01722 // palette. The "question mark" icon, which Microsoft recommends not 01723 // using but a lot of people still use, is left out. 01724 01725 /* XPM */ 01726 static const char * const information_xpm[]={ 01727 "32 32 5 1", 01728 ". c None", 01729 "c c #000000", 01730 "* c #999999", 01731 "a c #ffffff", 01732 "b c #0000ff", 01733 "...........********.............", 01734 "........***aaaaaaaa***..........", 01735 "......**aaaaaaaaaaaaaa**........", 01736 ".....*aaaaaaaaaaaaaaaaaa*.......", 01737 "....*aaaaaaaabbbbaaaaaaaac......", 01738 "...*aaaaaaaabbbbbbaaaaaaaac.....", 01739 "..*aaaaaaaaabbbbbbaaaaaaaaac....", 01740 ".*aaaaaaaaaaabbbbaaaaaaaaaaac...", 01741 ".*aaaaaaaaaaaaaaaaaaaaaaaaaac*..", 01742 "*aaaaaaaaaaaaaaaaaaaaaaaaaaaac*.", 01743 "*aaaaaaaaaabbbbbbbaaaaaaaaaaac*.", 01744 "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**", 01745 "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**", 01746 "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**", 01747 "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**", 01748 "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**", 01749 ".*aaaaaaaaaaabbbbbaaaaaaaaaac***", 01750 ".*aaaaaaaaaaabbbbbaaaaaaaaaac***", 01751 "..*aaaaaaaaaabbbbbaaaaaaaaac***.", 01752 "...caaaaaaabbbbbbbbbaaaaaac****.", 01753 "....caaaaaaaaaaaaaaaaaaaac****..", 01754 ".....caaaaaaaaaaaaaaaaaac****...", 01755 "......ccaaaaaaaaaaaaaacc****....", 01756 ".......*cccaaaaaaaaccc*****.....", 01757 "........***cccaaaac*******......", 01758 "..........****caaac*****........", 01759 ".............*caaac**...........", 01760 "...............caac**...........", 01761 "................cac**...........", 01762 ".................cc**...........", 01763 "..................***...........", 01764 "...................**..........."}; 01765 /* XPM */ 01766 static const char* const warning_xpm[]={ 01767 "32 32 4 1", 01768 ". c None", 01769 "a c #ffff00", 01770 "* c #000000", 01771 "b c #999999", 01772 ".............***................", 01773 "............*aaa*...............", 01774 "...........*aaaaa*b.............", 01775 "...........*aaaaa*bb............", 01776 "..........*aaaaaaa*bb...........", 01777 "..........*aaaaaaa*bb...........", 01778 ".........*aaaaaaaaa*bb..........", 01779 ".........*aaaaaaaaa*bb..........", 01780 "........*aaaaaaaaaaa*bb.........", 01781 "........*aaaa***aaaa*bb.........", 01782 ".......*aaaa*****aaaa*bb........", 01783 ".......*aaaa*****aaaa*bb........", 01784 "......*aaaaa*****aaaaa*bb.......", 01785 "......*aaaaa*****aaaaa*bb.......", 01786 ".....*aaaaaa*****aaaaaa*bb......", 01787 ".....*aaaaaa*****aaaaaa*bb......", 01788 "....*aaaaaaaa***aaaaaaaa*bb.....", 01789 "....*aaaaaaaa***aaaaaaaa*bb.....", 01790 "...*aaaaaaaaa***aaaaaaaaa*bb....", 01791 "...*aaaaaaaaaa*aaaaaaaaaa*bb....", 01792 "..*aaaaaaaaaaa*aaaaaaaaaaa*bb...", 01793 "..*aaaaaaaaaaaaaaaaaaaaaaa*bb...", 01794 ".*aaaaaaaaaaaa**aaaaaaaaaaa*bb..", 01795 ".*aaaaaaaaaaa****aaaaaaaaaa*bb..", 01796 "*aaaaaaaaaaaa****aaaaaaaaaaa*bb.", 01797 "*aaaaaaaaaaaaa**aaaaaaaaaaaa*bb.", 01798 "*aaaaaaaaaaaaaaaaaaaaaaaaaaa*bbb", 01799 "*aaaaaaaaaaaaaaaaaaaaaaaaaaa*bbb", 01800 ".*aaaaaaaaaaaaaaaaaaaaaaaaa*bbbb", 01801 "..*************************bbbbb", 01802 "....bbbbbbbbbbbbbbbbbbbbbbbbbbb.", 01803 ".....bbbbbbbbbbbbbbbbbbbbbbbbb.."}; 01804 /* XPM */ 01805 static const char* const critical_xpm[]={ 01806 "32 32 4 1", 01807 ". c None", 01808 "a c #999999", 01809 "* c #ff0000", 01810 "b c #ffffff", 01811 "...........********.............", 01812 ".........************...........", 01813 ".......****************.........", 01814 "......******************........", 01815 ".....********************a......", 01816 "....**********************a.....", 01817 "...************************a....", 01818 "..*******b**********b*******a...", 01819 "..******bbb********bbb******a...", 01820 ".******bbbbb******bbbbb******a..", 01821 ".*******bbbbb****bbbbb*******a..", 01822 "*********bbbbb**bbbbb*********a.", 01823 "**********bbbbbbbbbb**********a.", 01824 "***********bbbbbbbb***********aa", 01825 "************bbbbbb************aa", 01826 "************bbbbbb************aa", 01827 "***********bbbbbbbb***********aa", 01828 "**********bbbbbbbbbb**********aa", 01829 "*********bbbbb**bbbbb*********aa", 01830 ".*******bbbbb****bbbbb*******aa.", 01831 ".******bbbbb******bbbbb******aa.", 01832 "..******bbb********bbb******aaa.", 01833 "..*******b**********b*******aa..", 01834 "...************************aaa..", 01835 "....**********************aaa...", 01836 "....a********************aaa....", 01837 ".....a******************aaa.....", 01838 "......a****************aaa......", 01839 ".......aa************aaaa.......", 01840 ".........aa********aaaaa........", 01841 "...........aaaaaaaaaaa..........", 01842 ".............aaaaaaa............"}; 01843 01844 TQPixmap TDEStyle::stylePixmap( StylePixmap stylepixmap, 01845 const TQStyleControlElementData &ceData, 01846 ControlElementFlags elementFlags, 01847 const TQStyleOption& opt, 01848 const TQWidget* widget) const 01849 { 01850 switch (stylepixmap) { 01851 case SP_TitleBarShadeButton: 01852 return TQPixmap(const_cast<const char**>(tdestyle_shade_xpm)); 01853 case SP_TitleBarUnshadeButton: 01854 return TQPixmap(const_cast<const char**>(tdestyle_unshade_xpm)); 01855 case SP_TitleBarNormalButton: 01856 return TQPixmap(const_cast<const char**>(tdestyle_normalizeup_xpm)); 01857 case SP_TitleBarMinButton: 01858 return TQPixmap(const_cast<const char**>(tdestyle_minimize_xpm)); 01859 case SP_TitleBarMaxButton: 01860 return TQPixmap(const_cast<const char**>(tdestyle_maximize_xpm)); 01861 case SP_TitleBarCloseButton: 01862 return TQPixmap(const_cast<const char**>(tdestyle_close_xpm)); 01863 case SP_DockWindowCloseButton: 01864 return TQPixmap(const_cast<const char**>(dock_window_close_xpm )); 01865 case SP_MessageBoxInformation: 01866 return TQPixmap(const_cast<const char**>(information_xpm)); 01867 case SP_MessageBoxWarning: 01868 return TQPixmap(const_cast<const char**>(warning_xpm)); 01869 case SP_MessageBoxCritical: 01870 return TQPixmap(const_cast<const char**>(critical_xpm)); 01871 default: 01872 break; 01873 } 01874 return TQCommonStyle::stylePixmap(stylepixmap, ceData, elementFlags, opt, widget); 01875 } 01876 01877 01878 int TDEStyle::styleHint( TQ_StyleHint sh, const TQStyleControlElementData &ceData, ControlElementFlags elementFlags, 01879 const TQStyleOption &opt, TQStyleHintReturn* shr, const TQWidget* w) const 01880 { 01881 switch (sh) 01882 { 01883 case SH_EtchDisabledText: 01884 return d->etchDisabledText ? 1 : 0; 01885 01886 case SH_PopupMenu_Scrollable: 01887 return d->scrollablePopupmenus ? 1 : 0; 01888 01889 case SH_HideUnderlineAcceleratorWhenAltUp: 01890 return d->autoHideAccelerators ? 1 : 0; 01891 01892 case SH_MenuBar_AltKeyNavigation: 01893 return d->menuAltKeyNavigation ? 1 : 0; 01894 01895 case SH_PopupMenu_SubMenuPopupDelay: 01896 if ( styleHint( SH_PopupMenu_SloppySubMenus, ceData, elementFlags, TQStyleOption::Default, 0, w ) ) 01897 return TQMIN( 100, d->popupMenuDelay ); 01898 else 01899 return d->popupMenuDelay; 01900 01901 case SH_PopupMenu_SloppySubMenus: 01902 return d->sloppySubMenus; 01903 01904 case SH_ItemView_ChangeHighlightOnFocus: 01905 case SH_Slider_SloppyKeyEvents: 01906 case SH_MainWindow_SpaceBelowMenuBar: 01907 case SH_PopupMenu_AllowActiveAndDisabled: 01908 return 0; 01909 01910 case SH_Slider_SnapToValue: 01911 case SH_PrintDialog_RightAlignButtons: 01912 case SH_FontDialog_SelectAssociatedText: 01913 case SH_MenuBar_MouseTracking: 01914 case SH_PopupMenu_MouseTracking: 01915 case SH_ComboBox_ListMouseTracking: 01916 case SH_ScrollBar_MiddleClickAbsolutePosition: 01917 return 1; 01918 case SH_LineEdit_PasswordCharacter: 01919 { 01920 if (w) { 01921 const TQFontMetrics &fm = w->fontMetrics(); 01922 if (fm.inFont(TQChar(0x25CF))) { 01923 return 0x25CF; 01924 } else if (fm.inFont(TQChar(0x2022))) { 01925 return 0x2022; 01926 } 01927 } 01928 return '*'; 01929 } 01930 01931 default: 01932 return TQCommonStyle::styleHint(sh, ceData, elementFlags, opt, shr, w); 01933 } 01934 } 01935 01936 01937 bool TDEStyle::objectEventHandler( const TQStyleControlElementData &ceData, ControlElementFlags elementFlags, void* source, TQEvent *event ) 01938 { 01939 if (ceData.widgetObjectTypes.contains(TQOBJECT_OBJECT_NAME_STRING)) { 01940 TQObject* object = reinterpret_cast<TQObject*>(source); 01941 if ( d->useFilledFrameWorkaround ) 01942 { 01943 // Make the QMenuBar/TQToolBar paintEvent() cover a larger area to 01944 // ensure that the filled frame contents are properly painted. 01945 // We essentially modify the paintEvent's rect to include the 01946 // panel border, which also paints the widget's interior. 01947 // This is nasty, but I see no other way to properly repaint 01948 // filled frames in all QMenuBars and QToolBars. 01949 // -- Karol. 01950 TQFrame *frame = 0; 01951 if ( event->type() == TQEvent::Paint 01952 && (frame = ::tqqt_cast<TQFrame*>(object)) ) 01953 { 01954 if (frame->frameShape() != TQFrame::ToolBarPanel && frame->frameShape() != TQFrame::MenuBarPanel) 01955 return false; 01956 01957 bool horizontal = true; 01958 TQPaintEvent* pe = (TQPaintEvent*)event; 01959 TQToolBar *toolbar = ::tqqt_cast< TQToolBar *>( frame ); 01960 TQRect r = pe->rect(); 01961 01962 if (toolbar && toolbar->orientation() == Qt::Vertical) 01963 horizontal = false; 01964 01965 if (horizontal) { 01966 if ( r.height() == frame->height() ) 01967 return false; // Let TQFrame handle the painting now. 01968 01969 // Else, send a new paint event with an updated paint rect. 01970 TQPaintEvent dummyPE( TQRect( r.x(), 0, r.width(), frame->height()) ); 01971 TQApplication::sendEvent( frame, &dummyPE ); 01972 } 01973 else { // Vertical 01974 if ( r.width() == frame->width() ) 01975 return false; 01976 01977 TQPaintEvent dummyPE( TQRect( 0, r.y(), frame->width(), r.height()) ); 01978 TQApplication::sendEvent( frame, &dummyPE ); 01979 } 01980 01981 // Discard this event as we sent a new paintEvent. 01982 return true; 01983 } 01984 } 01985 } 01986 01987 return false; 01988 } 01989 01990 01991 // ----------------------------------------------------------------------------- 01992 // I N T E R N A L - TDEStyle menu transparency handler 01993 // ----------------------------------------------------------------------------- 01994 01995 TransparencyHandler::TransparencyHandler( TDEStyle* style, 01996 TransparencyEngine tEngine, float menuOpacity, bool useDropShadow ) 01997 : TQObject() 01998 { 01999 te = tEngine; 02000 tdestyle = style; 02001 opacity = menuOpacity; 02002 dropShadow = useDropShadow; 02003 pix.setOptimization(TQPixmap::BestOptim); 02004 } 02005 02006 TransparencyHandler::~TransparencyHandler() 02007 { 02008 } 02009 02010 bool TransparencyHandler::haveX11RGBASupport() 02011 { 02012 // Simple way to determine if we have ARGB support 02013 if (TQPaintDevice::x11AppDepth() == 32) { 02014 return true; 02015 } 02016 else { 02017 return false; 02018 } 02019 } 02020 02021 #define REAL_ALPHA_STRENGTH 255.0 02022 02023 // This is meant to be ugly but fast. 02024 void TransparencyHandler::rightShadow(TQImage& dst) 02025 { 02026 bool have_composite = haveX11RGBASupport(); 02027 02028 if (dst.depth() != 32) 02029 dst = dst.convertDepth(32); 02030 02031 // blend top-right corner. 02032 int pixels = dst.width() * dst.height(); 02033 #ifdef WORDS_BIGENDIAN 02034 unsigned char* data = dst.bits() + 1; // Skip alpha 02035 #else 02036 unsigned char* data = dst.bits(); // Skip alpha 02037 #endif 02038 for(int i = 0; i < 16; i++) { 02039 if (have_composite) { 02040 data++; 02041 data++; 02042 data++; 02043 *data = (unsigned char)(REAL_ALPHA_STRENGTH*(1.0-top_right_corner[i])); data++; 02044 } 02045 else { 02046 *data = (unsigned char)((*data)*top_right_corner[i]); data++; 02047 *data = (unsigned char)((*data)*top_right_corner[i]); data++; 02048 *data = (unsigned char)((*data)*top_right_corner[i]); data++; 02049 data++; // skip alpha 02050 } 02051 } 02052 02053 pixels -= 32; // tint right strip without rounded edges. 02054 int c = 0; 02055 for(int i = 0; i < pixels; i++) { 02056 if (have_composite) { 02057 data++; 02058 data++; 02059 data++;; 02060 *data = (unsigned char)(REAL_ALPHA_STRENGTH*(1.0-shadow_strip[c])); data++; 02061 } 02062 else { 02063 *data = (unsigned char)((*data)*shadow_strip[c]); data++; 02064 *data = (unsigned char)((*data)*shadow_strip[c]); data++; 02065 *data = (unsigned char)((*data)*shadow_strip[c]); data++; 02066 data++; // skip alpha 02067 } 02068 ++c; 02069 c %= 4; 02070 } 02071 02072 // tint bottom edge 02073 for(int i = 0; i < 16; i++) { 02074 if (have_composite) { 02075 data++; 02076 data++; 02077 data++; 02078 *data = (unsigned char)(REAL_ALPHA_STRENGTH*(1.0-bottom_right_corner[i])); data++; 02079 } 02080 else { 02081 *data = (unsigned char)((*data)*bottom_right_corner[i]); data++; 02082 *data = (unsigned char)((*data)*bottom_right_corner[i]); data++; 02083 *data = (unsigned char)((*data)*bottom_right_corner[i]); data++; 02084 data++; // skip alpha 02085 } 02086 } 02087 } 02088 02089 void TransparencyHandler::bottomShadow(TQImage& dst) 02090 { 02091 bool have_composite = haveX11RGBASupport(); 02092 02093 if (dst.depth() != 32) 02094 dst = dst.convertDepth(32); 02095 02096 int line = 0; 02097 int width = dst.width() - 4; 02098 double strip_data = shadow_strip[0]; 02099 double* corner = const_cast<double*>(bottom_left_corner); 02100 02101 #ifdef WORDS_BIGENDIAN 02102 unsigned char* data = dst.bits() + 1; // Skip alpha 02103 #else 02104 unsigned char* data = dst.bits(); // Skip alpha 02105 #endif 02106 02107 for(int y = 0; y < 4; y++) 02108 { 02109 // Bottom-left Corner 02110 for(int x = 0; x < 4; x++) { 02111 if (have_composite) { 02112 data++; 02113 data++; 02114 data++; 02115 *data = (unsigned char)(REAL_ALPHA_STRENGTH*(1.0-(*corner))); data++; 02116 } 02117 else { 02118 *data = (unsigned char)((*data)*(*corner)); data++; 02119 *data = (unsigned char)((*data)*(*corner)); data++; 02120 *data = (unsigned char)((*data)*(*corner)); data++; 02121 data++; // skip alpha 02122 } 02123 corner++; 02124 } 02125 02126 // Scanline 02127 for(int x = 0; x < width; x++) { 02128 if (have_composite) { 02129 data++; 02130 data++; 02131 data++; 02132 *data = (unsigned char)(REAL_ALPHA_STRENGTH*(1.0-strip_data)); data++; 02133 } 02134 else { 02135 *data = (unsigned char)((*data)*strip_data); data++; 02136 *data = (unsigned char)((*data)*strip_data); data++; 02137 *data = (unsigned char)((*data)*strip_data); data++; 02138 data++; // skip alpha 02139 } 02140 } 02141 02142 strip_data = shadow_strip[line++]; 02143 } 02144 } 02145 02146 TQImage TransparencyHandler::handleRealAlpha(TQImage img) { 02147 TQImage clearImage = img.convertDepth(32); 02148 clearImage.setAlphaBuffer(true); 02149 02150 int w = clearImage.width(); 02151 int h = clearImage.height(); 02152 02153 for (int y = 0; y < h; ++y) { 02154 TQRgb *ls = (TQRgb *)clearImage.scanLine( y ); 02155 for (int x = 0; x < w; ++x) { 02156 ls[x] = tqRgba( 0, 0, 0, 0 ); 02157 } 02158 } 02159 02160 return clearImage; 02161 } 02162 02163 // Create a shadow of thickness 4. 02164 void TransparencyHandler::createShadowWindows(const TQWidget* p) 02165 { 02166 #ifdef Q_WS_X11 02167 int x2 = p->x()+p->width(); 02168 int y2 = p->y()+p->height(); 02169 TQRect shadow1(x2, p->y() + 4, 4, p->height()); 02170 TQRect shadow2(p->x() + 4, y2, p->width() - 4, 4); 02171 02172 bool have_composite = haveX11RGBASupport(); 02173 02174 // Create a fake drop-down shadow effect via blended Xwindows 02175 ShadowElements se; 02176 se.w1 = new TQWidget(0, 0, (WFlags)(WStyle_Customize | WType_Popup | WX11BypassWM) ); 02177 se.w2 = new TQWidget(0, 0, (WFlags)(WStyle_Customize | WType_Popup | WX11BypassWM) ); 02178 se.w1->setGeometry(shadow1); 02179 se.w2->setGeometry(shadow2); 02180 XSelectInput(tqt_xdisplay(), se.w1->winId(), StructureNotifyMask ); 02181 XSelectInput(tqt_xdisplay(), se.w2->winId(), StructureNotifyMask ); 02182 02183 // Insert a new ShadowMap entry 02184 shadowMap()[p] = se; 02185 02186 // Some hocus-pocus here to create the drop-shadow. 02187 TQPixmap pix_shadow1; 02188 TQPixmap pix_shadow2; 02189 if (have_composite) { 02190 pix_shadow1 = TQPixmap(shadow1.width(), shadow1.height()); 02191 pix_shadow2 = TQPixmap(shadow2.width(), shadow2.height()); 02192 } 02193 else { 02194 pix_shadow1 = TQPixmap::grabWindow(tqt_xrootwin(), 02195 shadow1.x(), shadow1.y(), shadow1.width(), shadow1.height()); 02196 pix_shadow2 = TQPixmap::grabWindow(tqt_xrootwin(), 02197 shadow2.x(), shadow2.y(), shadow2.width(), shadow2.height()); 02198 } 02199 02200 TQImage img; 02201 img = pix_shadow1.convertToImage(); 02202 if (have_composite) img = handleRealAlpha(img); 02203 rightShadow(img); 02204 pix_shadow1.convertFromImage(img); 02205 img = pix_shadow2.convertToImage(); 02206 if (have_composite) img = handleRealAlpha(img); 02207 bottomShadow(img); 02208 pix_shadow2.convertFromImage(img); 02209 02210 // Set the background pixmaps 02211 se.w1->setErasePixmap(pix_shadow1); 02212 se.w2->setErasePixmap(pix_shadow2); 02213 02214 // Show the 'shadow' just before showing the popup menu window 02215 // Don't use TQWidget::show() so we don't confuse QEffects, thus causing broken focus. 02216 XMapWindow(tqt_xdisplay(), se.w1->winId()); 02217 XMapWindow(tqt_xdisplay(), se.w2->winId()); 02218 #else 02219 Q_UNUSED( p ) 02220 #endif 02221 } 02222 02223 void TransparencyHandler::removeShadowWindows(const TQWidget* p) 02224 { 02225 #ifdef Q_WS_X11 02226 ShadowMap::iterator it = shadowMap().find(p); 02227 if (it != shadowMap().end()) 02228 { 02229 ShadowElements se = it.data(); 02230 XUnmapWindow(tqt_xdisplay(), se.w1->winId()); // hide 02231 XUnmapWindow(tqt_xdisplay(), se.w2->winId()); 02232 XFlush(tqt_xdisplay()); // try to hide faster 02233 delete se.w1; 02234 delete se.w2; 02235 shadowMap().erase(it); 02236 } 02237 #else 02238 Q_UNUSED( p ) 02239 #endif 02240 } 02241 02242 bool TransparencyHandler::eventFilter( TQObject* object, TQEvent* event ) 02243 { 02244 #if !defined Q_WS_MAC && !defined Q_WS_WIN 02245 // Transparency idea was borrowed from KDE2's "MegaGradient" Style, 02246 // Copyright (C) 2000 Daniel M. Duley <mosfet@kde.org> 02247 02248 // Added 'fake' menu shadows <04-Jul-2002> -- Karol 02249 TQWidget* p = (TQWidget*)object; 02250 TQEvent::Type et = event->type(); 02251 02252 if (et == TQEvent::Show) 02253 { 02254 // Handle translucency 02255 if (te != Disabled) 02256 { 02257 pix = TQPixmap::grabWindow(tqt_xrootwin(), 02258 p->x(), p->y(), p->width(), p->height()); 02259 02260 switch (te) { 02261 #ifdef HAVE_XRENDER 02262 case XRender: 02263 if (tqt_use_xrender) { 02264 XRenderBlendToPixmap(p); 02265 break; 02266 } 02267 // Fall through intended 02268 #else 02269 case XRender: 02270 #endif 02271 case SoftwareBlend: 02272 blendToPixmap(p->colorGroup(), p); 02273 break; 02274 02275 case SoftwareTint: 02276 default: 02277 blendToColor(p->colorGroup().button()); 02278 }; 02279 02280 p->setErasePixmap(pix); 02281 } 02282 02283 // Handle drop shadow 02284 // * FIXME : !shadowMap().contains(p) is a workaround for leftover 02285 // * shadows after duplicate show events. 02286 // * TODO : determine real cause for duplicate events 02287 // * till 20021005 02288 if ((dropShadow || useDropShadow(p)) 02289 && p->width() > 16 && p->height() > 16 && !shadowMap().contains( p )) 02290 createShadowWindows(p); 02291 } 02292 else if (et == TQEvent::Resize && p->isShown() && p->isTopLevel()) 02293 { 02294 // Handle drop shadow 02295 if (dropShadow || useDropShadow(p)) 02296 { 02297 removeShadowWindows(p); 02298 createShadowWindows(p); 02299 } 02300 } 02301 else if (et == TQEvent::Hide) 02302 { 02303 // Handle drop shadow 02304 if (dropShadow || useDropShadow(p)) 02305 removeShadowWindows(p); 02306 02307 // Handle translucency 02308 if (te != Disabled) 02309 p->setErasePixmap(TQPixmap()); 02310 } 02311 02312 #endif 02313 return false; 02314 } 02315 02316 02317 // Blends a TQImage to a predefined color, with a given opacity. 02318 void TransparencyHandler::blendToColor(const TQColor &col) 02319 { 02320 if (opacity < 0.0 || opacity > 1.0) 02321 return; 02322 02323 TQImage img = pix.convertToImage(); 02324 KImageEffect::blend(col, img, opacity); 02325 pix.convertFromImage(img); 02326 } 02327 02328 02329 void TransparencyHandler::blendToPixmap(const TQColorGroup &cg, const TQWidget* p) 02330 { 02331 if (opacity < 0.0 || opacity > 1.0) 02332 return; 02333 02334 KPixmap blendPix; 02335 blendPix.resize( pix.width(), pix.height() ); 02336 02337 if (blendPix.width() != pix.width() || 02338 blendPix.height() != pix.height()) 02339 return; 02340 02341 // Allow styles to define the blend pixmap - allows for some interesting effects. 02342 if (::tqqt_cast<TQPopupMenu*>(p)) 02343 tdestyle->renderMenuBlendPixmap( blendPix, cg, ::tqqt_cast<TQPopupMenu*>(p) ); 02344 else 02345 blendPix.fill(cg.button()); // Just tint as the default behavior 02346 02347 TQImage blendImg = blendPix.convertToImage(); 02348 TQImage backImg = pix.convertToImage(); 02349 KImageEffect::blend(blendImg, backImg, opacity); 02350 pix.convertFromImage(backImg); 02351 } 02352 02353 02354 #ifdef HAVE_XRENDER 02355 // Here we go, use XRender in all its glory. 02356 // NOTE: This is actually a bit slower than the above routines 02357 // on non-accelerated displays. -- Karol. 02358 void TransparencyHandler::XRenderBlendToPixmap(const TQWidget* p) 02359 { 02360 KPixmap renderPix; 02361 renderPix.resize( pix.width(), pix.height() ); 02362 02363 // Allow styles to define the blend pixmap - allows for some interesting effects. 02364 if (::tqqt_cast<TQPopupMenu*>(p)) 02365 tdestyle->renderMenuBlendPixmap( renderPix, p->colorGroup(), 02366 ::tqqt_cast<TQPopupMenu*>(p) ); 02367 else 02368 renderPix.fill(p->colorGroup().button()); // Just tint as the default behavior 02369 02370 Display* dpy = tqt_xdisplay(); 02371 Pixmap alphaPixmap; 02372 Picture alphaPicture; 02373 XRenderPictFormat Rpf; 02374 XRenderPictureAttributes Rpa; 02375 XRenderColor clr; 02376 clr.alpha = ((unsigned short)(255*opacity) << 8); 02377 02378 Rpf.type = PictTypeDirect; 02379 Rpf.depth = 8; 02380 Rpf.direct.alphaMask = 0xff; 02381 Rpa.repeat = True; // Tile 02382 02383 XRenderPictFormat* xformat = XRenderFindFormat(dpy, 02384 PictFormatType | PictFormatDepth | PictFormatAlphaMask, &Rpf, 0); 02385 02386 alphaPixmap = XCreatePixmap(dpy, p->handle(), 1, 1, 8); 02387 alphaPicture = XRenderCreatePicture(dpy, alphaPixmap, xformat, CPRepeat, &Rpa); 02388 02389 XRenderFillRectangle(dpy, PictOpSrc, alphaPicture, &clr, 0, 0, 1, 1); 02390 02391 XRenderComposite(dpy, PictOpOver, 02392 renderPix.x11RenderHandle(), alphaPicture, pix.x11RenderHandle(), // src, mask, dst 02393 0, 0, // srcx, srcy 02394 0, 0, // maskx, masky 02395 0, 0, // dstx, dsty 02396 pix.width(), pix.height()); 02397 02398 XRenderFreePicture(dpy, alphaPicture); 02399 XFreePixmap(dpy, alphaPixmap); 02400 } 02401 #endif 02402 02403 void TDEStyle::virtual_hook( int, void* ) 02404 { /*BASE::virtual_hook( id, data );*/ } 02405 02406 // HACK for gtk-qt-engine 02407 02408 extern "C" KDE_EXPORT 02409 void kde_tdestyle_set_scrollbar_type_windows( void* style ) 02410 { 02411 ((TDEStyle*)style)->setScrollBarType( TDEStyle::WindowsStyleScrollBar ); 02412 } 02413 02414 // vim: set noet ts=4 sw=4: 02415 // kate: indent-width 4; replace-tabs off; tab-width 4; space-indent off; 02416 02417 #include "tdestyle.moc"