| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_vcl.hxx" |
| |
| #define _SV_SALNATIVEWIDGETS_KDE_CXX |
| |
| #define Region QtXRegion |
| |
| #include <QStyle> |
| #include <QStyleOption> |
| #include <QPainter> |
| #include <QFrame> |
| #include <QLabel> |
| |
| #include <kapplication.h> |
| |
| #undef Region |
| |
| #include "KDESalGraphics.hxx" |
| |
| #include "vcl/settings.hxx" |
| #include "vcl/decoview.hxx" |
| #include "rtl/ustrbuf.hxx" |
| |
| using namespace ::rtl; |
| |
| /** |
| Conversion function between VCL ControlState together with |
| ImplControlValue and Qt state flags. |
| @param nControlState State of the widget (default, focused, ...) in Native Widget Framework. |
| @param aValue Value held by the widget (on, off, ...) |
| */ |
| QStyle::State vclStateValue2StateFlag( ControlState nControlState, |
| const ImplControlValue& aValue ) |
| { |
| QStyle::State nState = |
| ( (nControlState & CTRL_STATE_DEFAULT)? QStyle::State_None: QStyle::State_None ) | |
| ( (nControlState & CTRL_STATE_ENABLED)? QStyle::State_Enabled: QStyle::State_None ) | |
| ( (nControlState & CTRL_STATE_FOCUSED)? QStyle::State_HasFocus: QStyle::State_None ) | |
| ( (nControlState & CTRL_STATE_PRESSED)? QStyle::State_Sunken: QStyle::State_None ) | |
| ( (nControlState & CTRL_STATE_SELECTED)? QStyle::State_Selected : QStyle::State_None ) | |
| ( (nControlState & CTRL_STATE_ROLLOVER)? QStyle::State_MouseOver: QStyle::State_None ); |
| //TODO ( (nControlState & CTRL_STATE_HIDDEN)? QStyle::State_: QStyle::State_None ) | |
| |
| switch ( aValue.getTristateVal() ) |
| { |
| case BUTTONVALUE_ON: nState |= QStyle::State_On; break; |
| case BUTTONVALUE_OFF: nState |= QStyle::State_Off; break; |
| case BUTTONVALUE_MIXED: nState |= QStyle::State_NoChange; break; |
| default: break; |
| } |
| |
| return nState; |
| } |
| |
| /** |
| Convert VCL Rectangle to QRect. |
| @param rControlRegion The Rectangle to convert. |
| @return The matching QRect |
| */ |
| QRect region2QRect( const Rectangle& rControlRegion ) |
| { |
| return QRect(rControlRegion.Left(), rControlRegion.Top(), rControlRegion.GetWidth(), rControlRegion.GetHeight()); |
| } |
| |
| KDESalGraphics::KDESalGraphics() : |
| m_image(0) |
| { |
| } |
| |
| KDESalGraphics::~KDESalGraphics() |
| { |
| if (m_image) |
| delete m_image; |
| } |
| |
| sal_Bool KDESalGraphics::IsNativeControlSupported( ControlType type, ControlPart part ) |
| { |
| if (type == CTRL_PUSHBUTTON) return true; |
| |
| if (type == CTRL_MENUBAR) return true; |
| |
| if (type == CTRL_MENU_POPUP) return true; |
| |
| if (type == CTRL_EDITBOX) return true; |
| |
| if (type == CTRL_COMBOBOX) return true; |
| |
| if (type == CTRL_TOOLBAR) return true; |
| |
| if (type == CTRL_CHECKBOX) return true; |
| |
| if (type == CTRL_LISTBOX) return true; |
| |
| if (type == CTRL_LISTNODE) return true; |
| |
| if (type == CTRL_FRAME) return true; |
| |
| if (type == CTRL_SCROLLBAR) return true; |
| |
| if (type == CTRL_WINDOW_BACKGROUND) return true; |
| |
| if (type == CTRL_SPINBOX && (part == PART_ENTIRE_CONTROL || part == HAS_BACKGROUND_TEXTURE) ) return true; |
| |
| // no spinbuttons for KDE, paint spinbox complete |
| //if (type == CTRL_SPINBUTTONS) return true; |
| |
| if (type == CTRL_GROUPBOX) return true; |
| |
| if (type == CTRL_FIXEDLINE) return true; |
| |
| if (type == CTRL_FIXEDBORDER) return true; |
| |
| if (type == CTRL_TOOLTIP) return true; |
| |
| if (type == CTRL_RADIOBUTTON) return true; |
| |
| if (type == CTRL_SLIDER && (part == PART_TRACK_HORZ_AREA || part == PART_TRACK_VERT_AREA) ) |
| return true; |
| |
| return false; |
| |
| if ( (type == CTRL_TAB_ITEM) && (part == PART_ENTIRE_CONTROL) ) return true; |
| if ( (type == CTRL_TAB_PANE) && (part == PART_ENTIRE_CONTROL) ) return true; |
| // no CTRL_TAB_BODY for KDE |
| if ( (type == CTRL_PROGRESS) && (part == PART_ENTIRE_CONTROL) ) return true; |
| |
| return false; |
| } |
| |
| sal_Bool KDESalGraphics::hitTestNativeControl( ControlType, ControlPart, |
| const Rectangle&, const Point&, |
| sal_Bool& ) |
| { |
| return FALSE; |
| } |
| |
| /// helper drawing methods |
| namespace |
| { |
| void draw( QStyle::ControlElement element, QStyleOption* option, QImage* image, QStyle::State state ) |
| { |
| option->state |= state; |
| option->rect = image->rect(); |
| |
| QPainter painter(image); |
| kapp->style()->drawControl(element, option, &painter); |
| } |
| |
| void draw( QStyle::PrimitiveElement element, QStyleOption* option, QImage* image, QStyle::State state, int nAdjust = 0 ) |
| { |
| option->state |= state; |
| option->rect = image->rect(); |
| if( nAdjust ) |
| option->rect.adjust( nAdjust, nAdjust, -nAdjust, -nAdjust ); |
| |
| QPainter painter(image); |
| kapp->style()->drawPrimitive(element, option, &painter); |
| } |
| |
| void draw( QStyle::ComplexControl element, QStyleOptionComplex* option, QImage* image, QStyle::State state ) |
| { |
| option->state |= state; |
| option->rect = image->rect(); |
| |
| QPainter painter(image); |
| kapp->style()->drawComplexControl(element, option, &painter); |
| } |
| |
| int getFrameWidth() |
| { |
| static int s_nFrameWidth = -1; |
| if( s_nFrameWidth < 0 ) |
| { |
| // fill in a default |
| s_nFrameWidth = 2; |
| QFrame aFrame( NULL ); |
| aFrame.setFrameRect( QRect(0, 0, 100, 30) ); |
| aFrame.setFrameStyle( QFrame::StyledPanel | QFrame::Sunken ); |
| aFrame.ensurePolished(); |
| s_nFrameWidth = aFrame.frameWidth(); |
| } |
| return s_nFrameWidth; |
| } |
| |
| void lcl_drawFrame(QStyle::PrimitiveElement element, QImage* image, QStyle::State state) |
| { |
| #if ( QT_VERSION >= QT_VERSION_CHECK( 4, 5, 0 ) ) |
| QStyleOptionFrameV3 option; |
| option.frameShape = QFrame::StyledPanel; |
| option.state = QStyle::State_Sunken; |
| #else |
| QStyleOptionFrame option; |
| |
| QFrame aFrame( NULL ); |
| aFrame.setFrameRect( QRect(0, 0, image->width(), image->height()) ); |
| aFrame.setFrameStyle( QFrame::StyledPanel | QFrame::Sunken ); |
| aFrame.ensurePolished(); |
| |
| option.initFrom( &aFrame ); |
| option.lineWidth = aFrame.lineWidth(); |
| option.midLineWidth = aFrame.midLineWidth(); |
| #endif |
| |
| draw(element, &option, image, state); |
| } |
| } |
| |
| sal_Bool KDESalGraphics::drawNativeControl( ControlType type, ControlPart part, |
| const Rectangle& rControlRegion, ControlState nControlState, |
| const ImplControlValue& value, |
| const OUString& ) |
| { |
| // put not implemented types here |
| if (type == CTRL_SPINBUTTONS) |
| { |
| return false; |
| } |
| |
| sal_Bool returnVal = true; |
| |
| QRect widgetRect = region2QRect(rControlRegion); |
| if( type == CTRL_SPINBOX && part == PART_ALL_BUTTONS ) |
| type = CTRL_SPINBUTTONS; |
| if( type == CTRL_SPINBUTTONS ) |
| { |
| OSL_ASSERT( value.getType() != CTRL_SPINBUTTONS ); |
| const SpinbuttonValue* pSpinVal = static_cast<const SpinbuttonValue *>(&value); |
| Rectangle aButtonRect( pSpinVal->maUpperRect); |
| aButtonRect.Union( pSpinVal->maLowerRect );; |
| widgetRect = QRect( aButtonRect.Left(), aButtonRect.Top(), |
| aButtonRect.Right(), aButtonRect.Bottom() ); |
| } |
| |
| //if no image, or resized, make a new image |
| if (!m_image || m_image->size() != widgetRect.size()) |
| { |
| if (m_image) |
| delete m_image; |
| |
| m_image = new QImage( widgetRect.width(), |
| widgetRect.height(), |
| QImage::Format_ARGB32 ); |
| } |
| m_image->fill(KApplication::palette().color(QPalette::Window).rgb()); |
| |
| |
| XLIB_Region pTempClipRegion = 0; |
| |
| if (type == CTRL_PUSHBUTTON) |
| { |
| QStyleOptionButton option; |
| draw( QStyle::CE_PushButton, &option, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| } |
| else if ( (type == CTRL_MENUBAR)) |
| { |
| if (part == PART_MENU_ITEM) |
| { |
| QStyleOptionMenuItem option; |
| draw( QStyle::CE_MenuBarItem, &option, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| } |
| else if (part == PART_ENTIRE_CONTROL) |
| { |
| } |
| else |
| { |
| returnVal = false; |
| } |
| } |
| else if (type == CTRL_MENU_POPUP) |
| { |
| if (part == PART_MENU_ITEM) |
| { |
| QStyleOptionMenuItem option; |
| draw( QStyle::CE_MenuItem, &option, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| } |
| else if (part == PART_MENU_ITEM_CHECK_MARK && (nControlState & CTRL_STATE_PRESSED) ) |
| { |
| QStyleOptionButton option; |
| draw( QStyle::PE_IndicatorMenuCheckMark, &option, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| } |
| else if (part == PART_MENU_ITEM_RADIO_MARK && (nControlState & CTRL_STATE_PRESSED) ) |
| { |
| QStyleOptionButton option; |
| draw( QStyle::PE_IndicatorRadioButton, &option, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| } |
| else |
| { |
| #if ( QT_VERSION >= QT_VERSION_CHECK( 4, 5, 0 ) ) |
| QStyleOptionFrameV3 option; |
| option.frameShape = QFrame::StyledPanel; |
| #else |
| QStyleOptionFrameV2 option; |
| #endif |
| draw( QStyle::PE_FrameMenu, &option, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| } |
| } |
| else if ( (type == CTRL_TOOLBAR) && (part == PART_BUTTON) ) |
| { |
| QStyleOptionToolButton option; |
| |
| option.arrowType = Qt::NoArrow; |
| option.subControls = QStyle::SC_ToolButton; |
| |
| option.state = vclStateValue2StateFlag( nControlState, value ); |
| option.state |= QStyle::State_Raised | QStyle::State_Enabled | QStyle::State_AutoRaise; |
| |
| draw( QStyle::CC_ToolButton, &option, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| } |
| else if ( (type == CTRL_TOOLBAR) && (part == PART_ENTIRE_CONTROL) ) |
| { |
| QStyleOptionToolBar option; |
| |
| option.rect = QRect(0, 0, widgetRect.width(), widgetRect.height()); |
| option.state = vclStateValue2StateFlag( nControlState, value ); |
| |
| draw( QStyle::CE_ToolBar, &option, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| } |
| else if ( (type == CTRL_TOOLBAR) && (part == PART_THUMB_VERT) ) |
| { |
| const int tw = widgetRect.width(); |
| widgetRect.setWidth(kapp->style()->pixelMetric(QStyle::PM_ToolBarHandleExtent)); |
| |
| QStyleOption option; |
| option.state = QStyle::State_Horizontal; |
| |
| draw( QStyle::PE_IndicatorToolBarHandle, &option, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| |
| widgetRect.setWidth(tw); |
| } |
| else if (type == CTRL_EDITBOX) |
| { |
| QStyleOptionFrameV2 option; |
| draw( QStyle::PE_PanelLineEdit, &option, m_image, |
| vclStateValue2StateFlag(nControlState, value), 2 ); |
| |
| draw( QStyle::PE_FrameLineEdit, &option, m_image, |
| vclStateValue2StateFlag(nControlState, value), 0 ); |
| } |
| else if (type == CTRL_COMBOBOX) |
| { |
| QStyleOptionComboBox option; |
| option.editable = true; |
| |
| draw( QStyle::CC_ComboBox, &option, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| } |
| else if (type == CTRL_LISTBOX) |
| { |
| if( part == PART_WINDOW ) |
| { |
| lcl_drawFrame( QStyle::PE_Frame, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| } |
| else |
| { |
| QStyleOptionComboBox option; |
| if (part == PART_SUB_EDIT) |
| { |
| draw( QStyle::CE_ComboBoxLabel, &option, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| } |
| else |
| { |
| draw( QStyle::CC_ComboBox, &option, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| } |
| } |
| } |
| else if (type == CTRL_LISTNODE) |
| { |
| QStyleOption option; |
| option.state = QStyle::State_Item | QStyle::State_Children; |
| |
| if (nControlState & CTRL_STATE_PRESSED) |
| option.state |= QStyle::State_Open; |
| |
| draw( QStyle::PE_IndicatorBranch, &option, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| } |
| else if (type == CTRL_CHECKBOX) |
| { |
| QStyleOptionButton option; |
| draw( QStyle::CE_CheckBox, &option, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| } |
| else if (type == CTRL_SCROLLBAR) |
| { |
| if ((part == PART_DRAW_BACKGROUND_VERT) || (part == PART_DRAW_BACKGROUND_HORZ)) |
| { |
| QStyleOptionSlider option; |
| OSL_ASSERT( value.getType() == CTRL_SCROLLBAR ); |
| const ScrollbarValue* sbVal = static_cast<const ScrollbarValue *>(&value); |
| |
| //if the scroll bar is active (aka not degenrate...allow for hover events |
| if (sbVal->mnVisibleSize < sbVal->mnMax) |
| option.state = QStyle::State_MouseOver; |
| |
| //horizontal or vertical |
| if (part == PART_DRAW_BACKGROUND_VERT) |
| option.orientation = Qt::Vertical; |
| else |
| option.state |= QStyle::State_Horizontal; |
| |
| //setup parameters from the OO values |
| option.minimum = sbVal->mnMin; |
| option.maximum = sbVal->mnMax - sbVal->mnVisibleSize; |
| option.sliderValue = sbVal->mnCur; |
| option.sliderPosition = sbVal->mnCur; |
| option.pageStep = sbVal->mnVisibleSize; |
| |
| //setup the active control...always the slider |
| if (sbVal->mnThumbState & CTRL_STATE_ROLLOVER) |
| option.activeSubControls = QStyle::SC_ScrollBarSlider; |
| |
| draw( QStyle::CC_ScrollBar, &option, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| } |
| else |
| { |
| returnVal = false; |
| } |
| } |
| else if (type == CTRL_SPINBOX) |
| { |
| QStyleOptionSpinBox option; |
| |
| // determine active control |
| if( value.getType() == CTRL_SPINBUTTONS ) |
| { |
| const SpinbuttonValue* pSpinVal = static_cast<const SpinbuttonValue *>(&value); |
| if( (pSpinVal->mnUpperState & CTRL_STATE_PRESSED) ) |
| option.activeSubControls |= QStyle::SC_SpinBoxUp; |
| if( (pSpinVal->mnLowerState & CTRL_STATE_PRESSED) ) |
| option.activeSubControls |= QStyle::SC_SpinBoxDown; |
| } |
| |
| draw( QStyle::CC_SpinBox, &option, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| } |
| else if (type == CTRL_GROUPBOX) |
| { |
| QStyleOptionGroupBox option; |
| draw( QStyle::CC_GroupBox, &option, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| } |
| else if (type == CTRL_RADIOBUTTON) |
| { |
| QStyleOptionButton option; |
| draw( QStyle::CE_RadioButton, &option, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| } |
| else if (type == CTRL_TOOLTIP) |
| { |
| QStyleOption option; |
| draw( QStyle::PE_PanelTipLabel, &option, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| } |
| else if (type == CTRL_FRAME) |
| { |
| lcl_drawFrame( QStyle::PE_Frame, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| |
| // draw just the border, see http://qa.openoffice.org/issues/show_bug.cgi?id=107945 |
| int nFrameWidth = getFrameWidth(); |
| pTempClipRegion = XCreateRegion(); |
| XRectangle xRect = { widgetRect.left(), widgetRect.top(), widgetRect.width(), widgetRect.height() }; |
| XUnionRectWithRegion( &xRect, pTempClipRegion, pTempClipRegion ); |
| xRect.x += nFrameWidth; |
| xRect.y += nFrameWidth; |
| |
| // do not crash for too small widgets, see http://qa.openoffice.org/issues/show_bug.cgi?id=112102 |
| if( xRect.width > 2*nFrameWidth && xRect.height > 2*nFrameWidth ) |
| { |
| xRect.width -= 2*nFrameWidth; |
| xRect.height -= 2*nFrameWidth; |
| |
| XLIB_Region pSubtract = XCreateRegion(); |
| XUnionRectWithRegion( &xRect, pSubtract, pSubtract ); |
| XSubtractRegion( pTempClipRegion, pSubtract, pTempClipRegion ); |
| XDestroyRegion( pSubtract ); |
| } |
| } |
| else if (type == CTRL_FIXEDBORDER) |
| { |
| lcl_drawFrame( QStyle::PE_FrameWindow, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| } |
| else if (type == CTRL_WINDOW_BACKGROUND) |
| { |
| m_image->fill(KApplication::palette().color(QPalette::Window).rgb()); |
| } |
| else if (type == CTRL_FIXEDLINE) |
| { |
| QStyleOptionMenuItem option; |
| option.menuItemType = QStyleOptionMenuItem::Separator; |
| option.state |= QStyle::State_Item; |
| |
| draw( QStyle::CE_MenuItem, &option, m_image, |
| vclStateValue2StateFlag(nControlState, value) ); |
| } |
| else if (type == CTRL_SLIDER && (part == PART_TRACK_HORZ_AREA || part == PART_TRACK_VERT_AREA)) |
| { |
| OSL_ASSERT( value.getType() == CTRL_SLIDER ); |
| const SliderValue* slVal = static_cast<const SliderValue *>(&value); |
| QStyleOptionSlider option; |
| |
| option.rect = QRect(0, 0, widgetRect.width(), widgetRect.height()); |
| option.state = vclStateValue2StateFlag( nControlState, value ); |
| option.maximum = slVal->mnMax; |
| option.minimum = slVal->mnMin; |
| option.sliderPosition = option.sliderValue = slVal->mnCur; |
| option.orientation = (part == PART_TRACK_HORZ_AREA) ? Qt::Horizontal : Qt::Vertical; |
| |
| draw( QStyle::CC_Slider, &option, m_image, vclStateValue2StateFlag(nControlState, value) ); |
| } |
| else |
| { |
| returnVal = false; |
| } |
| |
| if (returnVal) |
| { |
| GC gc = GetFontGC(); |
| |
| if( gc ) |
| { |
| if( pTempClipRegion ) |
| { |
| if( mpClipRegion ) |
| XIntersectRegion( pTempClipRegion, mpClipRegion, pTempClipRegion ); |
| XSetRegion( GetXDisplay(), gc, pTempClipRegion ); |
| } |
| QPixmap pixmap = QPixmap::fromImage(*m_image, Qt::ColorOnly | Qt::OrderedDither | Qt::OrderedAlphaDither); |
| X11SalGraphics::CopyScreenArea( GetXDisplay(), |
| pixmap.handle(), pixmap.x11Info().screen(), pixmap.x11Info().depth(), |
| GetDrawable(), GetScreenNumber(), GetVisual().GetDepth(), |
| gc, 0, 0, widgetRect.width(), widgetRect.height(), widgetRect.left(), widgetRect.top()); |
| |
| if( pTempClipRegion ) |
| { |
| if( mpClipRegion ) |
| XSetRegion( GetXDisplay(), gc, mpClipRegion ); |
| else |
| XSetClipMask( GetXDisplay(), gc, None ); |
| } |
| } |
| else |
| returnVal = false; |
| } |
| if( pTempClipRegion ) |
| XDestroyRegion( pTempClipRegion ); |
| |
| return returnVal; |
| } |
| |
| sal_Bool KDESalGraphics::getNativeControlRegion( ControlType type, ControlPart part, |
| const Rectangle& controlRegion, ControlState controlState, |
| const ImplControlValue& val, |
| const OUString&, |
| Rectangle &nativeBoundingRegion, Rectangle &nativeContentRegion ) |
| { |
| bool retVal = false; |
| |
| QRect boundingRect = region2QRect( controlRegion ); |
| QRect contentRect = boundingRect; |
| QStyleOptionComplex styleOption; |
| |
| switch ( type ) |
| { |
| // Metrics of the push button |
| case CTRL_PUSHBUTTON: |
| if (part == PART_ENTIRE_CONTROL) |
| { |
| styleOption.state = vclStateValue2StateFlag(controlState, val); |
| |
| if ( controlState & CTRL_STATE_DEFAULT ) |
| { |
| int size = kapp->style()->pixelMetric( |
| QStyle::PM_ButtonDefaultIndicator, &styleOption ); |
| |
| boundingRect.adjust( -size, -size, size, size ); |
| |
| retVal = true; |
| } |
| } |
| break; |
| case CTRL_EDITBOX: |
| { |
| int nFontHeight = kapp->fontMetrics().height(); |
| //int nFrameSize = kapp->style()->pixelMetric(QStyle::PM_DefaultFrameWidth); |
| int nLayoutTop = kapp->style()->pixelMetric(QStyle::PM_LayoutTopMargin); |
| int nLayoutBottom = kapp->style()->pixelMetric(QStyle::PM_LayoutBottomMargin); |
| int nLayoutLeft = kapp->style()->pixelMetric(QStyle::PM_LayoutLeftMargin); |
| int nLayoutRight = kapp->style()->pixelMetric(QStyle::PM_LayoutRightMargin); |
| |
| int nMinHeight = (nFontHeight + nLayoutTop + nLayoutBottom); |
| if( boundingRect.height() < nMinHeight ) |
| { |
| int delta = nMinHeight - boundingRect.height(); |
| boundingRect.adjust( 0, 0, 0, delta ); |
| } |
| contentRect = boundingRect; |
| contentRect.adjust( -nLayoutLeft+1, -nLayoutTop+1, nLayoutRight-1, nLayoutBottom-1 ); |
| retVal = true; |
| |
| break; |
| } |
| case CTRL_CHECKBOX: |
| if (part == PART_ENTIRE_CONTROL) |
| { |
| styleOption.state = vclStateValue2StateFlag(controlState, val); |
| |
| contentRect.setWidth(kapp->style()->pixelMetric( |
| QStyle::PM_IndicatorWidth, &styleOption)); |
| contentRect.setHeight(kapp->style()->pixelMetric( |
| QStyle::PM_IndicatorHeight, &styleOption)); |
| |
| contentRect.adjust(0, 0, |
| 2 * kapp->style()->pixelMetric( |
| QStyle::PM_FocusFrameHMargin, &styleOption), |
| 2 * kapp->style()->pixelMetric( |
| QStyle::PM_FocusFrameVMargin, &styleOption) |
| ); |
| |
| boundingRect = contentRect; |
| |
| retVal = true; |
| |
| break; |
| } |
| case CTRL_COMBOBOX: |
| case CTRL_LISTBOX: |
| { |
| QStyleOptionComboBox cbo; |
| |
| cbo.rect = QRect(0, 0, contentRect.width(), contentRect.height()); |
| cbo.state = vclStateValue2StateFlag(controlState, val); |
| |
| switch ( part ) |
| { |
| case PART_ENTIRE_CONTROL: |
| { |
| int size = kapp->style()->pixelMetric(QStyle::PM_ComboBoxFrameWidth) - 2; |
| |
| // find out the minimum size that should be used |
| // assume contents is a text ling |
| int nHeight = kapp->fontMetrics().height(); |
| QSize aContentSize( contentRect.width(), nHeight ); |
| QSize aMinSize = kapp->style()-> |
| sizeFromContents( QStyle::CT_ComboBox, &cbo, aContentSize ); |
| if( aMinSize.height() > contentRect.height() ) |
| contentRect.adjust( 0, 0, 0, aMinSize.height() - contentRect.height() ); |
| boundingRect = contentRect; |
| // FIXME: why this difference between comboboxes and listboxes ? |
| // because a combobox has a sub edit and that is positioned |
| // inside the outer bordered control ? |
| if( type == CTRL_COMBOBOX ) |
| contentRect.adjust(-size,-size,size,size); |
| retVal = true; |
| break; |
| } |
| case PART_BUTTON_DOWN: |
| //the entire control can be used as the "down" button |
| retVal = true; |
| break; |
| case PART_SUB_EDIT: |
| contentRect = kapp->style()->subControlRect( |
| QStyle::CC_ComboBox, &cbo, QStyle::SC_ComboBoxEditField ); |
| |
| contentRect.translate( boundingRect.left(), boundingRect.top() ); |
| |
| retVal = true; |
| break; |
| case PART_WINDOW: |
| retVal = true; |
| break; |
| } |
| break; |
| } |
| case CTRL_SPINBOX: |
| { |
| QStyleOptionSpinBox sbo; |
| |
| sbo.rect = QRect(0, 0, contentRect.width(), contentRect.height()); |
| sbo.state = vclStateValue2StateFlag(controlState, val); |
| |
| switch ( part ) |
| { |
| case PART_BUTTON_UP: |
| contentRect = kapp->style()->subControlRect( |
| QStyle::CC_SpinBox, &sbo, QStyle::SC_SpinBoxUp ); |
| contentRect.translate( boundingRect.left(), boundingRect.top() ); |
| retVal = true; |
| boundingRect = QRect(); |
| break; |
| |
| case PART_BUTTON_DOWN: |
| contentRect = kapp->style()->subControlRect( |
| QStyle::CC_SpinBox, &sbo, QStyle::SC_SpinBoxDown ); |
| retVal = true; |
| contentRect.translate( boundingRect.left(), boundingRect.top() ); |
| boundingRect = QRect(); |
| break; |
| |
| case PART_SUB_EDIT: |
| contentRect = kapp->style()->subControlRect( |
| QStyle::CC_SpinBox, &sbo, QStyle::SC_SpinBoxEditField ); |
| retVal = true; |
| contentRect.translate( boundingRect.left(), boundingRect.top() ); |
| break; |
| default: |
| retVal = true; |
| } |
| break; |
| } |
| case CTRL_MENU_POPUP: |
| //just limit the widget of the menu items |
| //OO isn't very flexible in all reguards with the menu |
| //so we do the best we can |
| if (part == PART_MENU_ITEM_CHECK_MARK) |
| { |
| contentRect.setWidth(contentRect.height()); |
| retVal = true; |
| } |
| else if (part == PART_MENU_ITEM_RADIO_MARK) |
| { |
| contentRect.setWidth(contentRect.height()); |
| retVal = true; |
| } |
| break; |
| case CTRL_FRAME: |
| { |
| if( part == PART_BORDER ) |
| { |
| int nFrameWidth = getFrameWidth(); |
| sal_uInt16 nStyle = val.getNumericVal(); |
| if( nStyle & FRAME_DRAW_NODRAW ) |
| { |
| // in this case the question is: how thick would a frame be |
| // see brdwin.cxx, decoview.cxx |
| // most probably the behavior in decoview.cxx is wrong. |
| contentRect.adjust(nFrameWidth, nFrameWidth, -nFrameWidth, -nFrameWidth); |
| } |
| retVal = true; |
| } |
| break; |
| } |
| case CTRL_RADIOBUTTON: |
| { |
| const int h = kapp->style()->pixelMetric(QStyle::PM_ExclusiveIndicatorHeight); |
| const int w = kapp->style()->pixelMetric(QStyle::PM_ExclusiveIndicatorWidth); |
| |
| contentRect = QRect(boundingRect.left(), boundingRect.top(), w, h); |
| contentRect.adjust(0, 0, |
| 2 * kapp->style()->pixelMetric( |
| QStyle::PM_FocusFrameHMargin, &styleOption), |
| 2 * kapp->style()->pixelMetric( |
| QStyle::PM_FocusFrameVMargin, &styleOption) |
| ); |
| boundingRect = contentRect; |
| |
| retVal = true; |
| break; |
| } |
| case CTRL_SLIDER: |
| { |
| const int w = kapp->style()->pixelMetric(QStyle::PM_SliderLength); |
| if( part == PART_THUMB_HORZ ) |
| { |
| contentRect = QRect(boundingRect.left(), boundingRect.top(), w, boundingRect.height()); |
| boundingRect = contentRect; |
| retVal = true; |
| } |
| else if( part == PART_THUMB_VERT ) |
| { |
| contentRect = QRect(boundingRect.left(), boundingRect.top(), boundingRect.width(), w); |
| boundingRect = contentRect; |
| retVal = true; |
| } |
| break; |
| } |
| default: |
| break; |
| } |
| #if 0 |
| |
| |
| // Metrics of the scroll bar |
| case CTRL_SCROLLBAR: |
| //pWidget = pWidgetPainter->scrollBar( rControlRegion, |
| //( part == PART_BUTTON_LEFT || part == PART_BUTTON_RIGHT ), |
| //ImplControlValue() ); |
| //aStyleOption.initFrom( pWidget ); |
| |
| switch ( part ) |
| { |
| case PART_BUTTON_LEFT: |
| case PART_BUTTON_UP: |
| qRect = kapp->style()->subControlRect( |
| QStyle::CC_ScrollBar, &aStyleOption, QStyle::SC_ScrollBarSubLine ); |
| |
| // Workaround for Platinum style scroll bars. It makes the |
| // left/up button invisible. |
| if ( part == PART_BUTTON_LEFT ) |
| { |
| if ( qRect.left() > kapp->style()->subControlRect( |
| QStyle::CC_ScrollBar, &aStyleOption, |
| QStyle::SC_ScrollBarSubPage ).left() ) |
| { |
| qRect.setLeft( 0 ); |
| qRect.setRight( 0 ); |
| } |
| } |
| else |
| { |
| if ( qRect.top() > kapp->style()->subControlRect( |
| QStyle::CC_ScrollBar, &aStyleOption, |
| QStyle::SC_ScrollBarSubPage ).top() ) |
| { |
| qRect.setTop( 0 ); |
| qRect.setBottom( 0 ); |
| } |
| } |
| |
| qRect.translate( qBoundingRect.left(), qBoundingRect.top() ); |
| |
| bReturn = TRUE; |
| break; |
| |
| case PART_BUTTON_RIGHT: |
| case PART_BUTTON_DOWN: |
| qRect = kapp->style()->subControlRect( |
| QStyle::CC_ScrollBar, &aStyleOption, QStyle::SC_ScrollBarAddLine ); |
| |
| // Workaround for Platinum and 3 button style scroll bars. |
| // It makes the right/down button bigger. |
| if ( part == PART_BUTTON_RIGHT ) |
| qRect.setLeft( kapp->style()->subControlRect( |
| QStyle::CC_ScrollBar, &aStyleOption, |
| QStyle::SC_ScrollBarAddPage ).right() + 1 ); |
| else |
| qRect.setTop( kapp->style()->subControlRect( |
| QStyle::CC_ScrollBar, &aStyleOption, |
| QStyle::SC_ScrollBarAddPage ).bottom() + 1 ); |
| |
| qRect.translate( qBoundingRect.left(), qBoundingRect.top() ); |
| |
| bReturn = TRUE; |
| break; |
| } |
| break; |
| } |
| #endif |
| |
| if (retVal) |
| { |
| // Bounding region |
| Point aBPoint( boundingRect.x(), boundingRect.y() ); |
| Size aBSize( boundingRect.width(), boundingRect.height() ); |
| nativeBoundingRegion = Rectangle( aBPoint, aBSize ); |
| |
| // Region of the content |
| Point aPoint( contentRect.x(), contentRect.y() ); |
| Size aSize( contentRect.width(), contentRect.height() ); |
| nativeContentRegion = Rectangle( aPoint, aSize ); |
| } |
| |
| return retVal; |
| } |