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