1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_vcl.hxx" 30 31 #define _SV_SALNATIVEWIDGETS_KDE_CXX 32 33 #define Region QtXRegion 34 35 #include <QStyle> 36 #include <QStyleOption> 37 #include <QPainter> 38 #include <QFrame> 39 #include <QLabel> 40 41 #include <kapplication.h> 42 43 #undef Region 44 45 #include "KDESalGraphics.hxx" 46 47 #include "vcl/settings.hxx" 48 #include "vcl/decoview.hxx" 49 #include "rtl/ustrbuf.hxx" 50 51 using namespace ::rtl; 52 53 /** 54 Conversion function between VCL ControlState together with 55 ImplControlValue and Qt state flags. 56 @param nControlState State of the widget (default, focused, ...) in Native Widget Framework. 57 @param aValue Value held by the widget (on, off, ...) 58 */ 59 QStyle::State vclStateValue2StateFlag( ControlState nControlState, 60 const ImplControlValue& aValue ) 61 { 62 QStyle::State nState = 63 ( (nControlState & CTRL_STATE_DEFAULT)? QStyle::State_None: QStyle::State_None ) | 64 ( (nControlState & CTRL_STATE_ENABLED)? QStyle::State_Enabled: QStyle::State_None ) | 65 ( (nControlState & CTRL_STATE_FOCUSED)? QStyle::State_HasFocus: QStyle::State_None ) | 66 ( (nControlState & CTRL_STATE_PRESSED)? QStyle::State_Sunken: QStyle::State_None ) | 67 ( (nControlState & CTRL_STATE_SELECTED)? QStyle::State_Selected : QStyle::State_None ) | 68 ( (nControlState & CTRL_STATE_ROLLOVER)? QStyle::State_MouseOver: QStyle::State_None ); 69 //TODO ( (nControlState & CTRL_STATE_HIDDEN)? QStyle::State_: QStyle::State_None ) | 70 71 switch ( aValue.getTristateVal() ) 72 { 73 case BUTTONVALUE_ON: nState |= QStyle::State_On; break; 74 case BUTTONVALUE_OFF: nState |= QStyle::State_Off; break; 75 case BUTTONVALUE_MIXED: nState |= QStyle::State_NoChange; break; 76 default: break; 77 } 78 79 return nState; 80 } 81 82 /** 83 Convert VCL Rectangle to QRect. 84 @param rControlRegion The Rectangle to convert. 85 @return The matching QRect 86 */ 87 QRect region2QRect( const Rectangle& rControlRegion ) 88 { 89 return QRect(rControlRegion.Left(), rControlRegion.Top(), rControlRegion.GetWidth(), rControlRegion.GetHeight()); 90 } 91 92 KDESalGraphics::KDESalGraphics() : 93 m_image(0) 94 { 95 } 96 97 KDESalGraphics::~KDESalGraphics() 98 { 99 if (m_image) 100 delete m_image; 101 } 102 103 sal_Bool KDESalGraphics::IsNativeControlSupported( ControlType type, ControlPart part ) 104 { 105 if (type == CTRL_PUSHBUTTON) return true; 106 107 if (type == CTRL_MENUBAR) return true; 108 109 if (type == CTRL_MENU_POPUP) return true; 110 111 if (type == CTRL_EDITBOX) return true; 112 113 if (type == CTRL_COMBOBOX) return true; 114 115 if (type == CTRL_TOOLBAR) return true; 116 117 if (type == CTRL_CHECKBOX) return true; 118 119 if (type == CTRL_LISTBOX) return true; 120 121 if (type == CTRL_LISTNODE) return true; 122 123 if (type == CTRL_FRAME) return true; 124 125 if (type == CTRL_SCROLLBAR) return true; 126 127 if (type == CTRL_WINDOW_BACKGROUND) return true; 128 129 if (type == CTRL_SPINBOX && (part == PART_ENTIRE_CONTROL || part == HAS_BACKGROUND_TEXTURE) ) return true; 130 131 // no spinbuttons for KDE, paint spinbox complete 132 //if (type == CTRL_SPINBUTTONS) return true; 133 134 if (type == CTRL_GROUPBOX) return true; 135 136 if (type == CTRL_FIXEDLINE) return true; 137 138 if (type == CTRL_FIXEDBORDER) return true; 139 140 if (type == CTRL_TOOLTIP) return true; 141 142 if (type == CTRL_RADIOBUTTON) return true; 143 144 if (type == CTRL_SLIDER && (part == PART_TRACK_HORZ_AREA || part == PART_TRACK_VERT_AREA) ) 145 return true; 146 147 return false; 148 149 if ( (type == CTRL_TAB_ITEM) && (part == PART_ENTIRE_CONTROL) ) return true; 150 if ( (type == CTRL_TAB_PANE) && (part == PART_ENTIRE_CONTROL) ) return true; 151 // no CTRL_TAB_BODY for KDE 152 if ( (type == CTRL_PROGRESS) && (part == PART_ENTIRE_CONTROL) ) return true; 153 154 return false; 155 } 156 157 sal_Bool KDESalGraphics::hitTestNativeControl( ControlType, ControlPart, 158 const Rectangle&, const Point&, 159 sal_Bool& ) 160 { 161 return FALSE; 162 } 163 164 /// helper drawing methods 165 namespace 166 { 167 void draw( QStyle::ControlElement element, QStyleOption* option, QImage* image, QStyle::State state ) 168 { 169 option->state |= state; 170 option->rect = image->rect(); 171 172 QPainter painter(image); 173 kapp->style()->drawControl(element, option, &painter); 174 } 175 176 void draw( QStyle::PrimitiveElement element, QStyleOption* option, QImage* image, QStyle::State state, int nAdjust = 0 ) 177 { 178 option->state |= state; 179 option->rect = image->rect(); 180 if( nAdjust ) 181 option->rect.adjust( nAdjust, nAdjust, -nAdjust, -nAdjust ); 182 183 QPainter painter(image); 184 kapp->style()->drawPrimitive(element, option, &painter); 185 } 186 187 void draw( QStyle::ComplexControl element, QStyleOptionComplex* option, QImage* image, QStyle::State state ) 188 { 189 option->state |= state; 190 option->rect = image->rect(); 191 192 QPainter painter(image); 193 kapp->style()->drawComplexControl(element, option, &painter); 194 } 195 196 int getFrameWidth() 197 { 198 static int s_nFrameWidth = -1; 199 if( s_nFrameWidth < 0 ) 200 { 201 // fill in a default 202 s_nFrameWidth = 2; 203 QFrame aFrame( NULL ); 204 aFrame.setFrameRect( QRect(0, 0, 100, 30) ); 205 aFrame.setFrameStyle( QFrame::StyledPanel | QFrame::Sunken ); 206 aFrame.ensurePolished(); 207 s_nFrameWidth = aFrame.frameWidth(); 208 } 209 return s_nFrameWidth; 210 } 211 212 void lcl_drawFrame(QStyle::PrimitiveElement element, QImage* image, QStyle::State state) 213 { 214 #if ( QT_VERSION >= QT_VERSION_CHECK( 4, 5, 0 ) ) 215 QStyleOptionFrameV3 option; 216 option.frameShape = QFrame::StyledPanel; 217 option.state = QStyle::State_Sunken; 218 #else 219 QStyleOptionFrame option; 220 221 QFrame aFrame( NULL ); 222 aFrame.setFrameRect( QRect(0, 0, image->width(), image->height()) ); 223 aFrame.setFrameStyle( QFrame::StyledPanel | QFrame::Sunken ); 224 aFrame.ensurePolished(); 225 226 option.initFrom( &aFrame ); 227 option.lineWidth = aFrame.lineWidth(); 228 option.midLineWidth = aFrame.midLineWidth(); 229 #endif 230 231 draw(element, &option, image, state); 232 } 233 } 234 235 sal_Bool KDESalGraphics::drawNativeControl( ControlType type, ControlPart part, 236 const Rectangle& rControlRegion, ControlState nControlState, 237 const ImplControlValue& value, 238 const OUString& ) 239 { 240 // put not implemented types here 241 if (type == CTRL_SPINBUTTONS) 242 { 243 return false; 244 } 245 246 sal_Bool returnVal = true; 247 248 QRect widgetRect = region2QRect(rControlRegion); 249 if( type == CTRL_SPINBOX && part == PART_ALL_BUTTONS ) 250 type = CTRL_SPINBUTTONS; 251 if( type == CTRL_SPINBUTTONS ) 252 { 253 OSL_ASSERT( value.getType() != CTRL_SPINBUTTONS ); 254 const SpinbuttonValue* pSpinVal = static_cast<const SpinbuttonValue *>(&value); 255 Rectangle aButtonRect( pSpinVal->maUpperRect); 256 aButtonRect.Union( pSpinVal->maLowerRect );; 257 widgetRect = QRect( aButtonRect.Left(), aButtonRect.Top(), 258 aButtonRect.Right(), aButtonRect.Bottom() ); 259 } 260 261 //if no image, or resized, make a new image 262 if (!m_image || m_image->size() != widgetRect.size()) 263 { 264 if (m_image) 265 delete m_image; 266 267 m_image = new QImage( widgetRect.width(), 268 widgetRect.height(), 269 QImage::Format_ARGB32 ); 270 } 271 m_image->fill(KApplication::palette().color(QPalette::Window).rgb()); 272 273 274 XLIB_Region pTempClipRegion = 0; 275 276 if (type == CTRL_PUSHBUTTON) 277 { 278 QStyleOptionButton option; 279 draw( QStyle::CE_PushButton, &option, m_image, 280 vclStateValue2StateFlag(nControlState, value) ); 281 } 282 else if ( (type == CTRL_MENUBAR)) 283 { 284 if (part == PART_MENU_ITEM) 285 { 286 QStyleOptionMenuItem option; 287 draw( QStyle::CE_MenuBarItem, &option, m_image, 288 vclStateValue2StateFlag(nControlState, value) ); 289 } 290 else if (part == PART_ENTIRE_CONTROL) 291 { 292 } 293 else 294 { 295 returnVal = false; 296 } 297 } 298 else if (type == CTRL_MENU_POPUP) 299 { 300 if (part == PART_MENU_ITEM) 301 { 302 QStyleOptionMenuItem option; 303 draw( QStyle::CE_MenuItem, &option, m_image, 304 vclStateValue2StateFlag(nControlState, value) ); 305 } 306 else if (part == PART_MENU_ITEM_CHECK_MARK && (nControlState & CTRL_STATE_PRESSED) ) 307 { 308 QStyleOptionButton option; 309 draw( QStyle::PE_IndicatorMenuCheckMark, &option, m_image, 310 vclStateValue2StateFlag(nControlState, value) ); 311 } 312 else if (part == PART_MENU_ITEM_RADIO_MARK && (nControlState & CTRL_STATE_PRESSED) ) 313 { 314 QStyleOptionButton option; 315 draw( QStyle::PE_IndicatorRadioButton, &option, m_image, 316 vclStateValue2StateFlag(nControlState, value) ); 317 } 318 else 319 { 320 #if ( QT_VERSION >= QT_VERSION_CHECK( 4, 5, 0 ) ) 321 QStyleOptionFrameV3 option; 322 option.frameShape = QFrame::StyledPanel; 323 #else 324 QStyleOptionFrameV2 option; 325 #endif 326 draw( QStyle::PE_FrameMenu, &option, m_image, 327 vclStateValue2StateFlag(nControlState, value) ); 328 } 329 } 330 else if ( (type == CTRL_TOOLBAR) && (part == PART_BUTTON) ) 331 { 332 QStyleOptionToolButton option; 333 334 option.arrowType = Qt::NoArrow; 335 option.subControls = QStyle::SC_ToolButton; 336 337 option.state = vclStateValue2StateFlag( nControlState, value ); 338 option.state |= QStyle::State_Raised | QStyle::State_Enabled | QStyle::State_AutoRaise; 339 340 draw( QStyle::CC_ToolButton, &option, m_image, 341 vclStateValue2StateFlag(nControlState, value) ); 342 } 343 else if ( (type == CTRL_TOOLBAR) && (part == PART_ENTIRE_CONTROL) ) 344 { 345 QStyleOptionToolBar option; 346 347 option.rect = QRect(0, 0, widgetRect.width(), widgetRect.height()); 348 option.state = vclStateValue2StateFlag( nControlState, value ); 349 350 draw( QStyle::CE_ToolBar, &option, m_image, 351 vclStateValue2StateFlag(nControlState, value) ); 352 } 353 else if ( (type == CTRL_TOOLBAR) && (part == PART_THUMB_VERT) ) 354 { 355 const int tw = widgetRect.width(); 356 widgetRect.setWidth(kapp->style()->pixelMetric(QStyle::PM_ToolBarHandleExtent)); 357 358 QStyleOption option; 359 option.state = QStyle::State_Horizontal; 360 361 draw( QStyle::PE_IndicatorToolBarHandle, &option, m_image, 362 vclStateValue2StateFlag(nControlState, value) ); 363 364 widgetRect.setWidth(tw); 365 } 366 else if (type == CTRL_EDITBOX) 367 { 368 QStyleOptionFrameV2 option; 369 draw( QStyle::PE_PanelLineEdit, &option, m_image, 370 vclStateValue2StateFlag(nControlState, value), 2 ); 371 372 draw( QStyle::PE_FrameLineEdit, &option, m_image, 373 vclStateValue2StateFlag(nControlState, value), 0 ); 374 } 375 else if (type == CTRL_COMBOBOX) 376 { 377 QStyleOptionComboBox option; 378 option.editable = true; 379 380 draw( QStyle::CC_ComboBox, &option, m_image, 381 vclStateValue2StateFlag(nControlState, value) ); 382 } 383 else if (type == CTRL_LISTBOX) 384 { 385 if( part == PART_WINDOW ) 386 { 387 lcl_drawFrame( QStyle::PE_Frame, m_image, 388 vclStateValue2StateFlag(nControlState, value) ); 389 } 390 else 391 { 392 QStyleOptionComboBox option; 393 if (part == PART_SUB_EDIT) 394 { 395 draw( QStyle::CE_ComboBoxLabel, &option, m_image, 396 vclStateValue2StateFlag(nControlState, value) ); 397 } 398 else 399 { 400 draw( QStyle::CC_ComboBox, &option, m_image, 401 vclStateValue2StateFlag(nControlState, value) ); 402 } 403 } 404 } 405 else if (type == CTRL_LISTNODE) 406 { 407 QStyleOption option; 408 option.state = QStyle::State_Item | QStyle::State_Children; 409 410 if (nControlState & CTRL_STATE_PRESSED) 411 option.state |= QStyle::State_Open; 412 413 draw( QStyle::PE_IndicatorBranch, &option, m_image, 414 vclStateValue2StateFlag(nControlState, value) ); 415 } 416 else if (type == CTRL_CHECKBOX) 417 { 418 QStyleOptionButton option; 419 draw( QStyle::CE_CheckBox, &option, m_image, 420 vclStateValue2StateFlag(nControlState, value) ); 421 } 422 else if (type == CTRL_SCROLLBAR) 423 { 424 if ((part == PART_DRAW_BACKGROUND_VERT) || (part == PART_DRAW_BACKGROUND_HORZ)) 425 { 426 QStyleOptionSlider option; 427 OSL_ASSERT( value.getType() == CTRL_SCROLLBAR ); 428 const ScrollbarValue* sbVal = static_cast<const ScrollbarValue *>(&value); 429 430 //if the scroll bar is active (aka not degenrate...allow for hover events 431 if (sbVal->mnVisibleSize < sbVal->mnMax) 432 option.state = QStyle::State_MouseOver; 433 434 //horizontal or vertical 435 if (part == PART_DRAW_BACKGROUND_VERT) 436 option.orientation = Qt::Vertical; 437 else 438 option.state |= QStyle::State_Horizontal; 439 440 //setup parameters from the OO values 441 option.minimum = sbVal->mnMin; 442 option.maximum = sbVal->mnMax - sbVal->mnVisibleSize; 443 option.sliderValue = sbVal->mnCur; 444 option.sliderPosition = sbVal->mnCur; 445 option.pageStep = sbVal->mnVisibleSize; 446 447 //setup the active control...always the slider 448 if (sbVal->mnThumbState & CTRL_STATE_ROLLOVER) 449 option.activeSubControls = QStyle::SC_ScrollBarSlider; 450 451 draw( QStyle::CC_ScrollBar, &option, m_image, 452 vclStateValue2StateFlag(nControlState, value) ); 453 } 454 else 455 { 456 returnVal = false; 457 } 458 } 459 else if (type == CTRL_SPINBOX) 460 { 461 QStyleOptionSpinBox option; 462 463 // determine active control 464 if( value.getType() == CTRL_SPINBUTTONS ) 465 { 466 const SpinbuttonValue* pSpinVal = static_cast<const SpinbuttonValue *>(&value); 467 if( (pSpinVal->mnUpperState & CTRL_STATE_PRESSED) ) 468 option.activeSubControls |= QStyle::SC_SpinBoxUp; 469 if( (pSpinVal->mnLowerState & CTRL_STATE_PRESSED) ) 470 option.activeSubControls |= QStyle::SC_SpinBoxDown; 471 } 472 473 draw( QStyle::CC_SpinBox, &option, m_image, 474 vclStateValue2StateFlag(nControlState, value) ); 475 } 476 else if (type == CTRL_GROUPBOX) 477 { 478 QStyleOptionGroupBox option; 479 draw( QStyle::CC_GroupBox, &option, m_image, 480 vclStateValue2StateFlag(nControlState, value) ); 481 } 482 else if (type == CTRL_RADIOBUTTON) 483 { 484 QStyleOptionButton option; 485 draw( QStyle::CE_RadioButton, &option, m_image, 486 vclStateValue2StateFlag(nControlState, value) ); 487 } 488 else if (type == CTRL_TOOLTIP) 489 { 490 QStyleOption option; 491 draw( QStyle::PE_PanelTipLabel, &option, m_image, 492 vclStateValue2StateFlag(nControlState, value) ); 493 } 494 else if (type == CTRL_FRAME) 495 { 496 lcl_drawFrame( QStyle::PE_Frame, m_image, 497 vclStateValue2StateFlag(nControlState, value) ); 498 499 // draw just the border, see http://qa.openoffice.org/issues/show_bug.cgi?id=107945 500 int nFrameWidth = getFrameWidth(); 501 pTempClipRegion = XCreateRegion(); 502 XRectangle xRect = { widgetRect.left(), widgetRect.top(), widgetRect.width(), widgetRect.height() }; 503 XUnionRectWithRegion( &xRect, pTempClipRegion, pTempClipRegion ); 504 xRect.x += nFrameWidth; 505 xRect.y += nFrameWidth; 506 507 // do not crash for too small widgets, see http://qa.openoffice.org/issues/show_bug.cgi?id=112102 508 if( xRect.width > 2*nFrameWidth && xRect.height > 2*nFrameWidth ) 509 { 510 xRect.width -= 2*nFrameWidth; 511 xRect.height -= 2*nFrameWidth; 512 513 XLIB_Region pSubtract = XCreateRegion(); 514 XUnionRectWithRegion( &xRect, pSubtract, pSubtract ); 515 XSubtractRegion( pTempClipRegion, pSubtract, pTempClipRegion ); 516 XDestroyRegion( pSubtract ); 517 } 518 } 519 else if (type == CTRL_FIXEDBORDER) 520 { 521 lcl_drawFrame( QStyle::PE_FrameWindow, m_image, 522 vclStateValue2StateFlag(nControlState, value) ); 523 } 524 else if (type == CTRL_WINDOW_BACKGROUND) 525 { 526 m_image->fill(KApplication::palette().color(QPalette::Window).rgb()); 527 } 528 else if (type == CTRL_FIXEDLINE) 529 { 530 QStyleOptionMenuItem option; 531 option.menuItemType = QStyleOptionMenuItem::Separator; 532 option.state |= QStyle::State_Item; 533 534 draw( QStyle::CE_MenuItem, &option, m_image, 535 vclStateValue2StateFlag(nControlState, value) ); 536 } 537 else if (type == CTRL_SLIDER && (part == PART_TRACK_HORZ_AREA || part == PART_TRACK_VERT_AREA)) 538 { 539 OSL_ASSERT( value.getType() == CTRL_SLIDER ); 540 const SliderValue* slVal = static_cast<const SliderValue *>(&value); 541 QStyleOptionSlider option; 542 543 option.rect = QRect(0, 0, widgetRect.width(), widgetRect.height()); 544 option.state = vclStateValue2StateFlag( nControlState, value ); 545 option.maximum = slVal->mnMax; 546 option.minimum = slVal->mnMin; 547 option.sliderPosition = option.sliderValue = slVal->mnCur; 548 option.orientation = (part == PART_TRACK_HORZ_AREA) ? Qt::Horizontal : Qt::Vertical; 549 550 draw( QStyle::CC_Slider, &option, m_image, vclStateValue2StateFlag(nControlState, value) ); 551 } 552 else 553 { 554 returnVal = false; 555 } 556 557 if (returnVal) 558 { 559 GC gc = GetFontGC(); 560 561 if( gc ) 562 { 563 if( pTempClipRegion ) 564 { 565 if( mpClipRegion ) 566 XIntersectRegion( pTempClipRegion, mpClipRegion, pTempClipRegion ); 567 XSetRegion( GetXDisplay(), gc, pTempClipRegion ); 568 } 569 QPixmap pixmap = QPixmap::fromImage(*m_image, Qt::ColorOnly | Qt::OrderedDither | Qt::OrderedAlphaDither); 570 X11SalGraphics::CopyScreenArea( GetXDisplay(), 571 pixmap.handle(), pixmap.x11Info().screen(), pixmap.x11Info().depth(), 572 GetDrawable(), GetScreenNumber(), GetVisual().GetDepth(), 573 gc, 0, 0, widgetRect.width(), widgetRect.height(), widgetRect.left(), widgetRect.top()); 574 575 if( pTempClipRegion ) 576 { 577 if( mpClipRegion ) 578 XSetRegion( GetXDisplay(), gc, mpClipRegion ); 579 else 580 XSetClipMask( GetXDisplay(), gc, None ); 581 } 582 } 583 else 584 returnVal = false; 585 } 586 if( pTempClipRegion ) 587 XDestroyRegion( pTempClipRegion ); 588 589 return returnVal; 590 } 591 592 sal_Bool KDESalGraphics::getNativeControlRegion( ControlType type, ControlPart part, 593 const Rectangle& controlRegion, ControlState controlState, 594 const ImplControlValue& val, 595 const OUString&, 596 Rectangle &nativeBoundingRegion, Rectangle &nativeContentRegion ) 597 { 598 bool retVal = false; 599 600 QRect boundingRect = region2QRect( controlRegion ); 601 QRect contentRect = boundingRect; 602 QStyleOptionComplex styleOption; 603 604 switch ( type ) 605 { 606 // Metrics of the push button 607 case CTRL_PUSHBUTTON: 608 if (part == PART_ENTIRE_CONTROL) 609 { 610 styleOption.state = vclStateValue2StateFlag(controlState, val); 611 612 if ( controlState & CTRL_STATE_DEFAULT ) 613 { 614 int size = kapp->style()->pixelMetric( 615 QStyle::PM_ButtonDefaultIndicator, &styleOption ); 616 617 boundingRect.adjust( -size, -size, size, size ); 618 619 retVal = true; 620 } 621 } 622 break; 623 case CTRL_EDITBOX: 624 { 625 int nFontHeight = kapp->fontMetrics().height(); 626 //int nFrameSize = kapp->style()->pixelMetric(QStyle::PM_DefaultFrameWidth); 627 int nLayoutTop = kapp->style()->pixelMetric(QStyle::PM_LayoutTopMargin); 628 int nLayoutBottom = kapp->style()->pixelMetric(QStyle::PM_LayoutBottomMargin); 629 int nLayoutLeft = kapp->style()->pixelMetric(QStyle::PM_LayoutLeftMargin); 630 int nLayoutRight = kapp->style()->pixelMetric(QStyle::PM_LayoutRightMargin); 631 632 int nMinHeight = (nFontHeight + nLayoutTop + nLayoutBottom); 633 if( boundingRect.height() < nMinHeight ) 634 { 635 int delta = nMinHeight - boundingRect.height(); 636 boundingRect.adjust( 0, 0, 0, delta ); 637 } 638 contentRect = boundingRect; 639 contentRect.adjust( -nLayoutLeft+1, -nLayoutTop+1, nLayoutRight-1, nLayoutBottom-1 ); 640 retVal = true; 641 642 break; 643 } 644 case CTRL_CHECKBOX: 645 if (part == PART_ENTIRE_CONTROL) 646 { 647 styleOption.state = vclStateValue2StateFlag(controlState, val); 648 649 contentRect.setWidth(kapp->style()->pixelMetric( 650 QStyle::PM_IndicatorWidth, &styleOption)); 651 contentRect.setHeight(kapp->style()->pixelMetric( 652 QStyle::PM_IndicatorHeight, &styleOption)); 653 654 contentRect.adjust(0, 0, 655 2 * kapp->style()->pixelMetric( 656 QStyle::PM_FocusFrameHMargin, &styleOption), 657 2 * kapp->style()->pixelMetric( 658 QStyle::PM_FocusFrameVMargin, &styleOption) 659 ); 660 661 boundingRect = contentRect; 662 663 retVal = true; 664 665 break; 666 } 667 case CTRL_COMBOBOX: 668 case CTRL_LISTBOX: 669 { 670 QStyleOptionComboBox cbo; 671 672 cbo.rect = QRect(0, 0, contentRect.width(), contentRect.height()); 673 cbo.state = vclStateValue2StateFlag(controlState, val); 674 675 switch ( part ) 676 { 677 case PART_ENTIRE_CONTROL: 678 { 679 int size = kapp->style()->pixelMetric(QStyle::PM_ComboBoxFrameWidth) - 2; 680 681 // find out the minimum size that should be used 682 // assume contents is a text ling 683 int nHeight = kapp->fontMetrics().height(); 684 QSize aContentSize( contentRect.width(), nHeight ); 685 QSize aMinSize = kapp->style()-> 686 sizeFromContents( QStyle::CT_ComboBox, &cbo, aContentSize ); 687 if( aMinSize.height() > contentRect.height() ) 688 contentRect.adjust( 0, 0, 0, aMinSize.height() - contentRect.height() ); 689 boundingRect = contentRect; 690 // FIXME: why this difference between comboboxes and listboxes ? 691 // because a combobox has a sub edit and that is positioned 692 // inside the outer bordered control ? 693 if( type == CTRL_COMBOBOX ) 694 contentRect.adjust(-size,-size,size,size); 695 retVal = true; 696 break; 697 } 698 case PART_BUTTON_DOWN: 699 //the entire control can be used as the "down" button 700 retVal = true; 701 break; 702 case PART_SUB_EDIT: 703 contentRect = kapp->style()->subControlRect( 704 QStyle::CC_ComboBox, &cbo, QStyle::SC_ComboBoxEditField ); 705 706 contentRect.translate( boundingRect.left(), boundingRect.top() ); 707 708 retVal = true; 709 break; 710 case PART_WINDOW: 711 retVal = true; 712 break; 713 } 714 break; 715 } 716 case CTRL_SPINBOX: 717 { 718 QStyleOptionSpinBox sbo; 719 720 sbo.rect = QRect(0, 0, contentRect.width(), contentRect.height()); 721 sbo.state = vclStateValue2StateFlag(controlState, val); 722 723 switch ( part ) 724 { 725 case PART_BUTTON_UP: 726 contentRect = kapp->style()->subControlRect( 727 QStyle::CC_SpinBox, &sbo, QStyle::SC_SpinBoxUp ); 728 contentRect.translate( boundingRect.left(), boundingRect.top() ); 729 retVal = true; 730 boundingRect = QRect(); 731 break; 732 733 case PART_BUTTON_DOWN: 734 contentRect = kapp->style()->subControlRect( 735 QStyle::CC_SpinBox, &sbo, QStyle::SC_SpinBoxDown ); 736 retVal = true; 737 contentRect.translate( boundingRect.left(), boundingRect.top() ); 738 boundingRect = QRect(); 739 break; 740 741 case PART_SUB_EDIT: 742 contentRect = kapp->style()->subControlRect( 743 QStyle::CC_SpinBox, &sbo, QStyle::SC_SpinBoxEditField ); 744 retVal = true; 745 contentRect.translate( boundingRect.left(), boundingRect.top() ); 746 break; 747 default: 748 retVal = true; 749 } 750 break; 751 } 752 case CTRL_MENU_POPUP: 753 //just limit the widget of the menu items 754 //OO isn't very flexible in all reguards with the menu 755 //so we do the best we can 756 if (part == PART_MENU_ITEM_CHECK_MARK) 757 { 758 contentRect.setWidth(contentRect.height()); 759 retVal = true; 760 } 761 else if (part == PART_MENU_ITEM_RADIO_MARK) 762 { 763 contentRect.setWidth(contentRect.height()); 764 retVal = true; 765 } 766 break; 767 case CTRL_FRAME: 768 { 769 if( part == PART_BORDER ) 770 { 771 int nFrameWidth = getFrameWidth(); 772 sal_uInt16 nStyle = val.getNumericVal(); 773 if( nStyle & FRAME_DRAW_NODRAW ) 774 { 775 // in this case the question is: how thick would a frame be 776 // see brdwin.cxx, decoview.cxx 777 // most probably the behavior in decoview.cxx is wrong. 778 contentRect.adjust(nFrameWidth, nFrameWidth, -nFrameWidth, -nFrameWidth); 779 } 780 retVal = true; 781 } 782 break; 783 } 784 case CTRL_RADIOBUTTON: 785 { 786 const int h = kapp->style()->pixelMetric(QStyle::PM_ExclusiveIndicatorHeight); 787 const int w = kapp->style()->pixelMetric(QStyle::PM_ExclusiveIndicatorWidth); 788 789 contentRect = QRect(boundingRect.left(), boundingRect.top(), w, h); 790 contentRect.adjust(0, 0, 791 2 * kapp->style()->pixelMetric( 792 QStyle::PM_FocusFrameHMargin, &styleOption), 793 2 * kapp->style()->pixelMetric( 794 QStyle::PM_FocusFrameVMargin, &styleOption) 795 ); 796 boundingRect = contentRect; 797 798 retVal = true; 799 break; 800 } 801 case CTRL_SLIDER: 802 { 803 const int w = kapp->style()->pixelMetric(QStyle::PM_SliderLength); 804 if( part == PART_THUMB_HORZ ) 805 { 806 contentRect = QRect(boundingRect.left(), boundingRect.top(), w, boundingRect.height()); 807 boundingRect = contentRect; 808 retVal = true; 809 } 810 else if( part == PART_THUMB_VERT ) 811 { 812 contentRect = QRect(boundingRect.left(), boundingRect.top(), boundingRect.width(), w); 813 boundingRect = contentRect; 814 retVal = true; 815 } 816 break; 817 } 818 default: 819 break; 820 } 821 #if 0 822 823 824 // Metrics of the scroll bar 825 case CTRL_SCROLLBAR: 826 //pWidget = pWidgetPainter->scrollBar( rControlRegion, 827 //( part == PART_BUTTON_LEFT || part == PART_BUTTON_RIGHT ), 828 //ImplControlValue() ); 829 //aStyleOption.initFrom( pWidget ); 830 831 switch ( part ) 832 { 833 case PART_BUTTON_LEFT: 834 case PART_BUTTON_UP: 835 qRect = kapp->style()->subControlRect( 836 QStyle::CC_ScrollBar, &aStyleOption, QStyle::SC_ScrollBarSubLine ); 837 838 // Workaround for Platinum style scroll bars. It makes the 839 // left/up button invisible. 840 if ( part == PART_BUTTON_LEFT ) 841 { 842 if ( qRect.left() > kapp->style()->subControlRect( 843 QStyle::CC_ScrollBar, &aStyleOption, 844 QStyle::SC_ScrollBarSubPage ).left() ) 845 { 846 qRect.setLeft( 0 ); 847 qRect.setRight( 0 ); 848 } 849 } 850 else 851 { 852 if ( qRect.top() > kapp->style()->subControlRect( 853 QStyle::CC_ScrollBar, &aStyleOption, 854 QStyle::SC_ScrollBarSubPage ).top() ) 855 { 856 qRect.setTop( 0 ); 857 qRect.setBottom( 0 ); 858 } 859 } 860 861 qRect.translate( qBoundingRect.left(), qBoundingRect.top() ); 862 863 bReturn = TRUE; 864 break; 865 866 case PART_BUTTON_RIGHT: 867 case PART_BUTTON_DOWN: 868 qRect = kapp->style()->subControlRect( 869 QStyle::CC_ScrollBar, &aStyleOption, QStyle::SC_ScrollBarAddLine ); 870 871 // Workaround for Platinum and 3 button style scroll bars. 872 // It makes the right/down button bigger. 873 if ( part == PART_BUTTON_RIGHT ) 874 qRect.setLeft( kapp->style()->subControlRect( 875 QStyle::CC_ScrollBar, &aStyleOption, 876 QStyle::SC_ScrollBarAddPage ).right() + 1 ); 877 else 878 qRect.setTop( kapp->style()->subControlRect( 879 QStyle::CC_ScrollBar, &aStyleOption, 880 QStyle::SC_ScrollBarAddPage ).bottom() + 1 ); 881 882 qRect.translate( qBoundingRect.left(), qBoundingRect.top() ); 883 884 bReturn = TRUE; 885 break; 886 } 887 break; 888 } 889 #endif 890 891 if (retVal) 892 { 893 // Bounding region 894 Point aBPoint( boundingRect.x(), boundingRect.y() ); 895 Size aBSize( boundingRect.width(), boundingRect.height() ); 896 nativeBoundingRegion = Rectangle( aBPoint, aBSize ); 897 898 // Region of the content 899 Point aPoint( contentRect.x(), contentRect.y() ); 900 Size aSize( contentRect.width(), contentRect.height() ); 901 nativeContentRegion = Rectangle( aPoint, aSize ); 902 } 903 904 return retVal; 905 } 906