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