xref: /AOO41X/main/vcl/unx/kde4/KDESalGraphics.cxx (revision 9f62ea84a806e17e6f2bbff75724a7257a0eb5d9)
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 */
vclStateValue2StateFlag(ControlState nControlState,const ImplControlValue & aValue)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 */
region2QRect(const Rectangle & rControlRegion)83 QRect region2QRect( const Rectangle& rControlRegion )
84 {
85     return QRect(rControlRegion.Left(), rControlRegion.Top(), rControlRegion.GetWidth(), rControlRegion.GetHeight());
86 }
87 
KDESalGraphics()88 KDESalGraphics::KDESalGraphics() :
89     m_image(0)
90 {
91 }
92 
~KDESalGraphics()93 KDESalGraphics::~KDESalGraphics()
94 {
95     if (m_image)
96         delete m_image;
97 }
98 
IsNativeControlSupported(ControlType type,ControlPart part)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 
hitTestNativeControl(ControlType,ControlPart,const Rectangle &,const Point &,sal_Bool &)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 {
draw(QStyle::ControlElement element,QStyleOption * option,QImage * image,QStyle::State state)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 
draw(QStyle::PrimitiveElement element,QStyleOption * option,QImage * image,QStyle::State state,int nAdjust=0)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 
draw(QStyle::ComplexControl element,QStyleOptionComplex * option,QImage * image,QStyle::State state)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 
getFrameWidth()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 
lcl_drawFrame(QStyle::PrimitiveElement element,QImage * image,QStyle::State state)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 
drawNativeControl(ControlType type,ControlPart part,const Rectangle & rControlRegion,ControlState nControlState,const ImplControlValue & value,const OUString &)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 
getNativeControlRegion(ControlType type,ControlPart part,const Rectangle & controlRegion,ControlState controlState,const ImplControlValue & val,const OUString &,Rectangle & nativeBoundingRegion,Rectangle & nativeContentRegion)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