xref: /trunk/main/vcl/unx/kde4/KDESalGraphics.cxx (revision 9f62ea84)
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