Update ooo320-m1
[ooovba.git] / vcl / win / source / gdi / salnativewidgets-luna.cxx
blob083f9b7c71b6752a72ad3115169a0135afe5c5ea
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salnativewidgets-luna.cxx,v $
10 * $Revision: 1.12 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #define _SV_SALNATIVEWIDGETS_CXX
36 #include "svsys.h"
37 #include "salgdi.h"
38 #include "saldata.hxx"
39 #include "vcl/svapp.hxx"
41 #include "rtl/ustring.h"
42 #include "osl/module.h"
44 #include "uxtheme.h"
45 #include "tmschema.h"
47 #include <map>
48 #include <string>
50 using namespace rtl;
51 using namespace std;
53 typedef map< wstring, HTHEME > ThemeMap;
54 static ThemeMap aThemeMap;
57 /****************************************************
58 wrap visual styles API to avoid linking against it
59 it is not available on all Windows platforms
60 *****************************************************/
62 class VisualStylesAPI
64 private:
65 typedef HTHEME (WINAPI * OpenThemeData_Proc_T) ( HWND hwnd, LPCWSTR pszClassList );
66 typedef HRESULT (WINAPI * CloseThemeData_Proc_T) ( HTHEME hTheme );
67 typedef HRESULT (WINAPI * GetThemeBackgroundContentRect_Proc_T) ( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pBoundingRect, RECT *pContentRect );
68 typedef HRESULT (WINAPI * DrawThemeBackground_Proc_T) ( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect );
69 typedef HRESULT (WINAPI * DrawThemeText_Proc_T) ( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, const RECT *pRect );
70 typedef HRESULT (WINAPI * GetThemePartSize_Proc_T) ( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, RECT *prc, THEMESIZE eSize, SIZE *psz );
72 OpenThemeData_Proc_T lpfnOpenThemeData;
73 CloseThemeData_Proc_T lpfnCloseThemeData;
74 GetThemeBackgroundContentRect_Proc_T lpfnGetThemeBackgroundContentRect;
75 DrawThemeBackground_Proc_T lpfnDrawThemeBackground;
76 DrawThemeText_Proc_T lpfnDrawThemeText;
77 GetThemePartSize_Proc_T lpfnGetThemePartSize;
79 oslModule mhModule;
81 public:
82 VisualStylesAPI();
83 ~VisualStylesAPI();
84 BOOL IsAvailable() { return (mhModule != NULL); }
86 HTHEME OpenThemeData( HWND hwnd, LPCWSTR pszClassList );
87 HRESULT CloseThemeData( HTHEME hTheme );
88 HRESULT GetThemeBackgroundContentRect( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pBoundingRect, RECT *pContentRect );
89 HRESULT DrawThemeBackground( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect );
90 HRESULT DrawThemeText( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, const RECT *pRect );
91 HRESULT GetThemePartSize( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, RECT *prc, THEMESIZE eSize, SIZE *psz );
94 static VisualStylesAPI vsAPI;
96 VisualStylesAPI::VisualStylesAPI()
98 OUString aLibraryName( RTL_CONSTASCII_USTRINGPARAM( "uxtheme.dll" ) );
99 mhModule = osl_loadModule( aLibraryName.pData, SAL_LOADMODULE_DEFAULT );
101 if ( mhModule )
103 lpfnOpenThemeData = (OpenThemeData_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "OpenThemeData" );
104 lpfnCloseThemeData = (CloseThemeData_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "CloseThemeData" );
105 lpfnGetThemeBackgroundContentRect = (GetThemeBackgroundContentRect_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "GetThemeBackgroundContentRect" );
106 lpfnDrawThemeBackground = (DrawThemeBackground_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "DrawThemeBackground" );
107 lpfnDrawThemeText = (DrawThemeText_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "DrawThemeText" );
108 lpfnGetThemePartSize = (GetThemePartSize_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "GetThemePartSize" );
110 else
112 lpfnOpenThemeData = NULL;
113 lpfnCloseThemeData = NULL;
114 lpfnGetThemeBackgroundContentRect = NULL;
115 lpfnDrawThemeBackground = NULL;
116 lpfnDrawThemeText = NULL;
117 lpfnGetThemePartSize = NULL;
120 VisualStylesAPI::~VisualStylesAPI()
122 if( mhModule )
123 osl_unloadModule( mhModule );
125 HTHEME VisualStylesAPI::OpenThemeData( HWND hwnd, LPCWSTR pszClassList )
127 if(lpfnOpenThemeData)
128 return (*lpfnOpenThemeData) (hwnd, pszClassList);
129 else
130 return NULL;
133 HRESULT VisualStylesAPI::CloseThemeData( HTHEME hTheme )
135 if(lpfnCloseThemeData)
136 return (*lpfnCloseThemeData) (hTheme);
137 else
138 return S_FALSE;
140 HRESULT VisualStylesAPI::GetThemeBackgroundContentRect( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pBoundingRect, RECT *pContentRect )
142 if(lpfnGetThemeBackgroundContentRect)
143 return (*lpfnGetThemeBackgroundContentRect) ( hTheme, hdc, iPartId, iStateId, pBoundingRect, pContentRect );
144 else
145 return S_FALSE;
147 HRESULT VisualStylesAPI::DrawThemeBackground( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect )
149 if(lpfnDrawThemeBackground)
150 return (*lpfnDrawThemeBackground) (hTheme, hdc, iPartId, iStateId, pRect, pClipRect);
151 else
152 return S_FALSE;
154 HRESULT VisualStylesAPI::DrawThemeText( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, const RECT *pRect )
156 if(lpfnDrawThemeText)
157 return (*lpfnDrawThemeText) (hTheme, hdc, iPartId, iStateId, pszText, iCharCount, dwTextFlags, dwTextFlags2, pRect);
158 else
159 return S_FALSE;
161 HRESULT VisualStylesAPI::GetThemePartSize( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, RECT *prc, THEMESIZE eSize, SIZE *psz )
163 if(lpfnGetThemePartSize)
164 return (*lpfnGetThemePartSize) (hTheme, hdc, iPartId, iStateId, prc, eSize, psz);
165 else
166 return S_FALSE;
170 /*********************************************************
171 * Initialize XP theming and local stuff
172 *********************************************************/
173 void SalData::initNWF( void )
175 ImplSVData* pSVData = ImplGetSVData();
177 // the menu bar and the top docking area should have a common background (gradient)
178 pSVData->maNWFData.mbMenuBarDockingAreaCommonBG = true;
182 // *********************************************************
183 // * Release theming handles
184 // ********************************************************
185 void SalData::deInitNWF( void )
187 ThemeMap::iterator iter = aThemeMap.begin();
188 while( iter != aThemeMap.end() )
190 vsAPI.CloseThemeData(iter->second);
191 iter++;
193 aThemeMap.clear();
196 static HTHEME getThemeHandle( HWND hWnd, LPCWSTR name )
198 if( GetSalData()->mbThemeChanged )
200 // throw away invalid theme handles
201 GetSalData()->deInitNWF();
202 GetSalData()->mbThemeChanged = FALSE;
205 ThemeMap::iterator iter;
206 if( (iter = aThemeMap.find( name )) != aThemeMap.end() )
207 return iter->second;
208 // theme not found -> add it to map
209 HTHEME hTheme = vsAPI.OpenThemeData( hWnd, name );
210 if( hTheme != NULL )
211 aThemeMap[name] = hTheme;
212 return hTheme;
216 * IsNativeControlSupported()
218 * Returns TRUE if the platform supports native
219 * drawing of the control defined by nPart
221 BOOL WinSalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nPart )
223 HTHEME hTheme = NULL;
225 switch( nType )
227 case CTRL_PUSHBUTTON:
228 case CTRL_RADIOBUTTON:
229 case CTRL_CHECKBOX:
230 if( nPart == PART_ENTIRE_CONTROL )
231 hTheme = getThemeHandle( mhWnd, L"Button");
232 break;
233 case CTRL_SCROLLBAR:
234 if( nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT )
235 return FALSE; // no background painting needed
236 if( nPart == PART_ENTIRE_CONTROL )
237 hTheme = getThemeHandle( mhWnd, L"Scrollbar");
238 break;
239 case CTRL_COMBOBOX:
240 if( nPart == HAS_BACKGROUND_TEXTURE )
241 return FALSE; // we do not paint the inner part (ie the selection background/focus indication)
242 if( nPart == PART_ENTIRE_CONTROL )
243 hTheme = getThemeHandle( mhWnd, L"Edit");
244 else if( nPart == PART_BUTTON_DOWN )
245 hTheme = getThemeHandle( mhWnd, L"Combobox");
246 break;
247 case CTRL_SPINBOX:
248 if( nPart == PART_ENTIRE_CONTROL )
249 hTheme = getThemeHandle( mhWnd, L"Edit");
250 else if( nPart == PART_ALL_BUTTONS ||
251 nPart == PART_BUTTON_UP || nPart == PART_BUTTON_DOWN ||
252 nPart == PART_BUTTON_LEFT|| nPart == PART_BUTTON_RIGHT )
253 hTheme = getThemeHandle( mhWnd, L"Spin");
254 break;
255 case CTRL_SPINBUTTONS:
256 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_ALL_BUTTONS )
257 hTheme = getThemeHandle( mhWnd, L"Spin");
258 break;
259 case CTRL_EDITBOX:
260 case CTRL_MULTILINE_EDITBOX:
261 if( nPart == HAS_BACKGROUND_TEXTURE )
262 return FALSE; // we do not paint the inner part (ie the selection background/focus indication)
263 //return TRUE;
264 if( nPart == PART_ENTIRE_CONTROL )
265 hTheme = getThemeHandle( mhWnd, L"Edit");
266 break;
267 case CTRL_LISTBOX:
268 if( nPart == HAS_BACKGROUND_TEXTURE )
269 return FALSE; // we do not paint the inner part (ie the selection background/focus indication)
270 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_WINDOW )
271 hTheme = getThemeHandle( mhWnd, L"Listview");
272 else if( nPart == PART_BUTTON_DOWN )
273 hTheme = getThemeHandle( mhWnd, L"Combobox");
274 break;
275 case CTRL_TAB_PANE:
276 case CTRL_TAB_BODY:
277 case CTRL_TAB_ITEM:
278 case CTRL_FIXEDBORDER:
279 if( nPart == PART_ENTIRE_CONTROL )
280 hTheme = getThemeHandle( mhWnd, L"Tab");
281 break;
282 case CTRL_TOOLBAR:
283 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_BUTTON )
284 hTheme = getThemeHandle( mhWnd, L"Toolbar");
285 else
286 // use rebar theme for grip and background
287 hTheme = getThemeHandle( mhWnd, L"Rebar");
288 break;
289 case CTRL_MENUBAR:
290 if( nPart == PART_ENTIRE_CONTROL )
291 hTheme = getThemeHandle( mhWnd, L"Rebar");
292 break;
293 case CTRL_PROGRESS:
294 if( nPart == PART_ENTIRE_CONTROL )
295 hTheme = getThemeHandle( mhWnd, L"Progress");
296 break;
297 default:
298 hTheme = NULL;
299 break;
302 return (hTheme != NULL);
307 * HitTestNativeControl()
309 * If the return value is TRUE, bIsInside contains information whether
310 * aPos was or was not inside the native widget specified by the
311 * nType/nPart combination.
313 BOOL WinSalGraphics::hitTestNativeControl( ControlType,
314 ControlPart,
315 const Region&,
316 const Point&,
317 SalControlHandle&,
318 BOOL& )
320 return FALSE;
323 BOOL ImplDrawTheme( HTHEME hTheme, HDC hDC, int iPart, int iState, RECT rc, const OUString& aStr)
325 HRESULT hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
327 if( aStr.getLength() )
329 RECT rcContent;
330 hr = vsAPI.GetThemeBackgroundContentRect( hTheme, hDC, iPart, iState, &rc, &rcContent);
331 hr = vsAPI.DrawThemeText( hTheme, hDC, iPart, iState,
332 reinterpret_cast<LPCWSTR>(aStr.getStr()), -1,
333 DT_CENTER | DT_VCENTER | DT_SINGLELINE,
334 0, &rcContent);
336 return (hr == S_OK);
340 Rectangle ImplGetThemeRect( HTHEME hTheme, HDC hDC, int iPart, int iState, const Rectangle& aRect )
342 SIZE aSz;
343 RECT rc;
344 rc.left = aRect.nLeft;
345 rc.right = aRect.nRight;
346 rc.top = aRect.nTop;
347 rc.bottom = aRect.nBottom;
348 HRESULT hr = vsAPI.GetThemePartSize( hTheme, hDC, iPart, iState, NULL, TS_TRUE, &aSz ); // TS_TRUE returns optimal size
349 if( hr == S_OK )
350 return Rectangle( 0, 0, aSz.cx, aSz.cy );
351 else
352 return Rectangle();
355 // Helper functions
356 // ----
358 void ImplConvertSpinbuttonValues( int nControlPart, const ControlState& rState, const Rectangle& rRect,
359 int* pLunaPart, int *pLunaState, RECT *pRect )
361 if( nControlPart == PART_BUTTON_DOWN )
363 *pLunaPart = SPNP_DOWN;
364 if( rState & CTRL_STATE_PRESSED )
365 *pLunaState = DNS_PRESSED;
366 else if( !(rState & CTRL_STATE_ENABLED) )
367 *pLunaState = DNS_DISABLED;
368 else if( rState & CTRL_STATE_ROLLOVER )
369 *pLunaState = DNS_HOT;
370 else
371 *pLunaState = DNS_NORMAL;
373 if( nControlPart == PART_BUTTON_UP )
375 *pLunaPart = SPNP_UP;
376 if( rState & CTRL_STATE_PRESSED )
377 *pLunaState = UPS_PRESSED;
378 else if( !(rState & CTRL_STATE_ENABLED) )
379 *pLunaState = UPS_DISABLED;
380 else if( rState & CTRL_STATE_ROLLOVER )
381 *pLunaState = UPS_HOT;
382 else
383 *pLunaState = UPS_NORMAL;
385 if( nControlPart == PART_BUTTON_RIGHT )
387 *pLunaPart = SPNP_UPHORZ;
388 if( rState & CTRL_STATE_PRESSED )
389 *pLunaState = DNHZS_PRESSED;
390 else if( !(rState & CTRL_STATE_ENABLED) )
391 *pLunaState = DNHZS_DISABLED;
392 else if( rState & CTRL_STATE_ROLLOVER )
393 *pLunaState = DNHZS_HOT;
394 else
395 *pLunaState = DNHZS_NORMAL;
397 if( nControlPart == PART_BUTTON_LEFT )
399 *pLunaPart = SPNP_DOWNHORZ;
400 if( rState & CTRL_STATE_PRESSED )
401 *pLunaState = UPHZS_PRESSED;
402 else if( !(rState & CTRL_STATE_ENABLED) )
403 *pLunaState = UPHZS_DISABLED;
404 else if( rState & CTRL_STATE_ROLLOVER )
405 *pLunaState = UPHZS_HOT;
406 else
407 *pLunaState = UPHZS_NORMAL;
410 pRect->left = rRect.Left();
411 pRect->right = rRect.Right()+1;
412 pRect->top = rRect.Top();
413 pRect->bottom = rRect.Bottom()+1;
416 // ----
418 BOOL ImplDrawNativeControl( HDC hDC, HTHEME hTheme, RECT rc,
419 ControlType nType,
420 ControlPart nPart,
421 ControlState nState,
422 const ImplControlValue& aValue,
423 SalControlHandle&,
424 OUString aCaption )
426 // a listbox dropdown is actually a combobox dropdown
427 if( nType == CTRL_LISTBOX )
428 if( nPart == PART_BUTTON_DOWN )
429 nType = CTRL_COMBOBOX;
431 // draw entire combobox as a large edit box
432 if( nType == CTRL_COMBOBOX )
433 if( nPart == PART_ENTIRE_CONTROL )
434 nType = CTRL_EDITBOX;
436 // draw entire spinbox as a large edit box
437 if( nType == CTRL_SPINBOX )
438 if( nPart == PART_ENTIRE_CONTROL )
439 nType = CTRL_EDITBOX;
441 int iPart(0), iState(0);
442 if( nType == CTRL_SCROLLBAR )
444 HRESULT hr;
445 if( nPart == PART_BUTTON_UP )
447 iPart = SBP_ARROWBTN;
448 if( nState & CTRL_STATE_PRESSED )
449 iState = ABS_UPPRESSED;
450 else if( !(nState & CTRL_STATE_ENABLED) )
451 iState = ABS_UPDISABLED;
452 else if( nState & CTRL_STATE_ROLLOVER )
453 iState = ABS_UPHOT;
454 else
455 iState = ABS_UPNORMAL;
456 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
457 return (hr == S_OK);
459 if( nPart == PART_BUTTON_DOWN )
461 iPart = SBP_ARROWBTN;
462 if( nState & CTRL_STATE_PRESSED )
463 iState = ABS_DOWNPRESSED;
464 else if( !(nState & CTRL_STATE_ENABLED) )
465 iState = ABS_DOWNDISABLED;
466 else if( nState & CTRL_STATE_ROLLOVER )
467 iState = ABS_DOWNHOT;
468 else
469 iState = ABS_DOWNNORMAL;
470 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
471 return (hr == S_OK);
473 if( nPart == PART_BUTTON_LEFT )
475 iPart = SBP_ARROWBTN;
476 if( nState & CTRL_STATE_PRESSED )
477 iState = ABS_LEFTPRESSED;
478 else if( !(nState & CTRL_STATE_ENABLED) )
479 iState = ABS_LEFTDISABLED;
480 else if( nState & CTRL_STATE_ROLLOVER )
481 iState = ABS_LEFTHOT;
482 else
483 iState = ABS_LEFTNORMAL;
484 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
485 return (hr == S_OK);
487 if( nPart == PART_BUTTON_RIGHT )
489 iPart = SBP_ARROWBTN;
490 if( nState & CTRL_STATE_PRESSED )
491 iState = ABS_RIGHTPRESSED;
492 else if( !(nState & CTRL_STATE_ENABLED) )
493 iState = ABS_RIGHTDISABLED;
494 else if( nState & CTRL_STATE_ROLLOVER )
495 iState = ABS_RIGHTHOT;
496 else
497 iState = ABS_RIGHTNORMAL;
498 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
499 return (hr == S_OK);
501 if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT )
503 iPart = (nPart == PART_THUMB_HORZ) ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT;
504 if( nState & CTRL_STATE_PRESSED )
505 iState = SCRBS_PRESSED;
506 else if( !(nState & CTRL_STATE_ENABLED) )
507 iState = SCRBS_DISABLED;
508 else if( nState & CTRL_STATE_ROLLOVER )
509 iState = SCRBS_HOT;
510 else
511 iState = SCRBS_NORMAL;
513 SIZE sz;
514 vsAPI.GetThemePartSize(hTheme, hDC, iPart, iState, NULL, TS_MIN, &sz);
515 vsAPI.GetThemePartSize(hTheme, hDC, iPart, iState, NULL, TS_TRUE, &sz);
516 vsAPI.GetThemePartSize(hTheme, hDC, iPart, iState, NULL, TS_DRAW, &sz);
518 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
519 // paint gripper on thumb if enough space
520 if( ( (nPart == PART_THUMB_VERT) && (rc.bottom-rc.top > 12) ) ||
521 ( (nPart == PART_THUMB_HORZ) && (rc.right-rc.left > 12) ) )
523 iPart = (nPart == PART_THUMB_HORZ) ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT;
524 iState = 0;
525 vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
527 return (hr == S_OK);
529 if( nPart == PART_TRACK_HORZ_LEFT || nPart == PART_TRACK_HORZ_RIGHT || nPart == PART_TRACK_VERT_UPPER || nPart == PART_TRACK_VERT_LOWER )
531 switch( nPart )
533 case PART_TRACK_HORZ_LEFT: iPart = SBP_UPPERTRACKHORZ; break;
534 case PART_TRACK_HORZ_RIGHT: iPart = SBP_LOWERTRACKHORZ; break;
535 case PART_TRACK_VERT_UPPER: iPart = SBP_UPPERTRACKVERT; break;
536 case PART_TRACK_VERT_LOWER: iPart = SBP_LOWERTRACKVERT; break;
539 if( nState & CTRL_STATE_PRESSED )
540 iState = SCRBS_PRESSED;
541 else if( !(nState & CTRL_STATE_ENABLED) )
542 iState = SCRBS_DISABLED;
543 else if( nState & CTRL_STATE_ROLLOVER )
544 iState = SCRBS_HOT;
545 else
546 iState = SCRBS_NORMAL;
547 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
548 return (hr == S_OK);
551 if( nType == CTRL_SPINBUTTONS && nPart == PART_ALL_BUTTONS )
553 SpinbuttonValue *pValue = (SpinbuttonValue*) aValue.getOptionalVal();
554 if( pValue )
556 BOOL bOk = FALSE;
558 RECT rect;
559 ImplConvertSpinbuttonValues( pValue->mnUpperPart, pValue->mnUpperState, pValue->maUpperRect, &iPart, &iState, &rect );
560 bOk = ImplDrawTheme( hTheme, hDC, iPart, iState, rect, aCaption);
562 if( bOk )
564 ImplConvertSpinbuttonValues( pValue->mnLowerPart, pValue->mnLowerState, pValue->maLowerRect, &iPart, &iState, &rect );
565 bOk = ImplDrawTheme( hTheme, hDC, iPart, iState, rect, aCaption);
568 return bOk;
571 if( nType == CTRL_SPINBOX )
573 // decrease spinbutton rects a little
574 //rc.right--;
575 //rc.bottom--;
576 if( nPart == PART_ALL_BUTTONS )
578 SpinbuttonValue *pValue = (SpinbuttonValue*) aValue.getOptionalVal();
579 if( pValue )
581 BOOL bOk = FALSE;
583 RECT rect;
584 ImplConvertSpinbuttonValues( pValue->mnUpperPart, pValue->mnUpperState, pValue->maUpperRect, &iPart, &iState, &rect );
585 bOk = ImplDrawTheme( hTheme, hDC, iPart, iState, rect, aCaption);
587 if( bOk )
589 ImplConvertSpinbuttonValues( pValue->mnLowerPart, pValue->mnLowerState, pValue->maLowerRect, &iPart, &iState, &rect );
590 bOk = ImplDrawTheme( hTheme, hDC, iPart, iState, rect, aCaption);
593 return bOk;
597 if( nPart == PART_BUTTON_DOWN )
599 iPart = SPNP_DOWN;
600 if( nState & CTRL_STATE_PRESSED )
601 iState = DNS_PRESSED;
602 else if( !(nState & CTRL_STATE_ENABLED) )
603 iState = DNS_DISABLED;
604 else if( nState & CTRL_STATE_ROLLOVER )
605 iState = DNS_HOT;
606 else
607 iState = DNS_NORMAL;
609 if( nPart == PART_BUTTON_UP )
611 iPart = SPNP_UP;
612 if( nState & CTRL_STATE_PRESSED )
613 iState = UPS_PRESSED;
614 else if( !(nState & CTRL_STATE_ENABLED) )
615 iState = UPS_DISABLED;
616 else if( nState & CTRL_STATE_ROLLOVER )
617 iState = UPS_HOT;
618 else
619 iState = UPS_NORMAL;
621 if( nPart == PART_BUTTON_RIGHT )
623 iPart = SPNP_DOWNHORZ;
624 if( nState & CTRL_STATE_PRESSED )
625 iState = DNHZS_PRESSED;
626 else if( !(nState & CTRL_STATE_ENABLED) )
627 iState = DNHZS_DISABLED;
628 else if( nState & CTRL_STATE_ROLLOVER )
629 iState = DNHZS_HOT;
630 else
631 iState = DNHZS_NORMAL;
633 if( nPart == PART_BUTTON_LEFT )
635 iPart = SPNP_UPHORZ;
636 if( nState & CTRL_STATE_PRESSED )
637 iState = UPHZS_PRESSED;
638 else if( !(nState & CTRL_STATE_ENABLED) )
639 iState = UPHZS_DISABLED;
640 else if( nState & CTRL_STATE_ROLLOVER )
641 iState = UPHZS_HOT;
642 else
643 iState = UPHZS_NORMAL;
645 if( nPart == PART_BUTTON_LEFT || nPart == PART_BUTTON_RIGHT || nPart == PART_BUTTON_UP || nPart == PART_BUTTON_DOWN )
646 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
648 if( nType == CTRL_COMBOBOX )
650 if( nPart == PART_BUTTON_DOWN )
652 iPart = CP_DROPDOWNBUTTON;
653 if( nState & CTRL_STATE_PRESSED )
654 iState = CBXS_PRESSED;
655 else if( !(nState & CTRL_STATE_ENABLED) )
656 iState = CBXS_DISABLED;
657 else if( nState & CTRL_STATE_ROLLOVER )
658 iState = CBXS_HOT;
659 else
660 iState = CBXS_NORMAL;
661 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
664 if( nType == CTRL_PUSHBUTTON )
666 iPart = BP_PUSHBUTTON;
667 if( nState & CTRL_STATE_PRESSED )
668 iState = PBS_PRESSED;
669 else if( !(nState & CTRL_STATE_ENABLED) )
670 iState = PBS_DISABLED;
671 else if( nState & CTRL_STATE_ROLLOVER )
672 iState = PBS_HOT;
673 else if( nState & CTRL_STATE_DEFAULT )
674 iState = PBS_DEFAULTED;
675 //else if( nState & CTRL_STATE_FOCUSED )
676 // iState = PBS_DEFAULTED; // may need to draw focus rect
677 else
678 iState = PBS_NORMAL;
680 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
683 if( nType == CTRL_RADIOBUTTON )
685 iPart = BP_RADIOBUTTON;
686 BOOL bChecked = ( aValue.getTristateVal() == BUTTONVALUE_ON );
688 if( nState & CTRL_STATE_PRESSED )
689 iState = bChecked ? RBS_CHECKEDPRESSED : RBS_UNCHECKEDPRESSED;
690 else if( !(nState & CTRL_STATE_ENABLED) )
691 iState = bChecked ? RBS_CHECKEDDISABLED : RBS_UNCHECKEDDISABLED;
692 else if( nState & CTRL_STATE_ROLLOVER )
693 iState = bChecked ? RBS_CHECKEDHOT : RBS_UNCHECKEDHOT;
694 else
695 iState = bChecked ? RBS_CHECKEDNORMAL : RBS_UNCHECKEDNORMAL;
697 //if( nState & CTRL_STATE_FOCUSED )
698 // iState |= PBS_DEFAULTED; // may need to draw focus rect
700 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
703 if( nType == CTRL_CHECKBOX )
705 iPart = BP_CHECKBOX;
706 ButtonValue v = aValue.getTristateVal();
708 if( nState & CTRL_STATE_PRESSED )
709 iState = (v == BUTTONVALUE_ON) ? CBS_CHECKEDPRESSED :
710 ( (v == BUTTONVALUE_OFF) ? CBS_UNCHECKEDPRESSED : CBS_MIXEDPRESSED );
711 else if( !(nState & CTRL_STATE_ENABLED) )
712 iState = (v == BUTTONVALUE_ON) ? CBS_CHECKEDDISABLED :
713 ( (v == BUTTONVALUE_OFF) ? CBS_UNCHECKEDDISABLED : CBS_MIXEDDISABLED );
714 else if( nState & CTRL_STATE_ROLLOVER )
715 iState = (v == BUTTONVALUE_ON) ? CBS_CHECKEDHOT :
716 ( (v == BUTTONVALUE_OFF) ? CBS_UNCHECKEDHOT : CBS_MIXEDHOT );
717 else
718 iState = (v == BUTTONVALUE_ON) ? CBS_CHECKEDNORMAL :
719 ( (v == BUTTONVALUE_OFF) ? CBS_UNCHECKEDNORMAL : CBS_MIXEDNORMAL );
721 //if( nState & CTRL_STATE_FOCUSED )
722 // iState |= PBS_DEFAULTED; // may need to draw focus rect
724 //SIZE sz;
725 //THEMESIZE eSize = TS_DRAW; // TS_MIN, TS_TRUE, TS_DRAW
726 //vsAPI.GetThemePartSize( hTheme, hDC, iPart, iState, &rc, eSize, &sz);
728 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
731 if( ( nType == CTRL_EDITBOX ) || ( nType == CTRL_MULTILINE_EDITBOX ) )
733 iPart = EP_EDITTEXT;
734 if( !(nState & CTRL_STATE_ENABLED) )
735 iState = ETS_DISABLED;
736 else if( nState & CTRL_STATE_FOCUSED )
737 iState = ETS_FOCUSED;
738 else if( nState & CTRL_STATE_ROLLOVER )
739 iState = ETS_HOT;
740 else
741 iState = ETS_NORMAL;
743 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
746 if( nType == CTRL_LISTBOX )
748 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_WINDOW )
750 iPart = LVP_EMPTYTEXT; // ??? no idea which part to choose here
751 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
755 if( nType == CTRL_TAB_PANE )
757 iPart = TABP_PANE;
758 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
761 if( nType == CTRL_FIXEDBORDER )
764 iPart = BP_GROUPBOX;
765 if( !(nState & CTRL_STATE_ENABLED) )
766 iState = GBS_DISABLED;
767 else
768 iState = GBS_NORMAL;
770 // The fixed border is only used around the tools->options tabpage where
771 // TABP_PANE fits best
772 iPart = TABP_PANE;
773 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
776 if( nType == CTRL_TAB_BODY )
778 iPart = TABP_BODY;
779 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
782 if( nType == CTRL_TAB_ITEM )
784 iPart = TABP_TABITEMLEFTEDGE;
785 rc.bottom--;
787 TabitemValue *pValue = (TabitemValue*) aValue.getOptionalVal();
788 if( pValue )
790 if( pValue->isBothAligned() )
792 iPart = TABP_TABITEMLEFTEDGE;
793 rc.right--;
795 else if( pValue->isLeftAligned() )
796 iPart = TABP_TABITEMLEFTEDGE;
797 else if( pValue->isRightAligned() )
798 iPart = TABP_TABITEMRIGHTEDGE;
799 else iPart = TABP_TABITEM;
802 if( !(nState & CTRL_STATE_ENABLED) )
803 iState = TILES_DISABLED;
804 else if( nState & CTRL_STATE_SELECTED )
806 iState = TILES_SELECTED;
807 // increase the selected tab
808 rc.left-=2;
809 if( pValue && !pValue->isBothAligned() )
811 if( pValue->isLeftAligned() || pValue->isNotAligned() )
812 rc.right+=2;
813 if( pValue->isRightAligned() )
814 rc.right+=1;
816 rc.top-=2;
817 rc.bottom+=2;
819 else if( nState & CTRL_STATE_ROLLOVER )
820 iState = TILES_HOT;
821 else if( nState & CTRL_STATE_FOCUSED )
822 iState = TILES_FOCUSED; // may need to draw focus rect
823 else
824 iState = TILES_NORMAL;
825 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
828 if( nType == CTRL_TOOLBAR )
830 if( nPart == PART_BUTTON )
832 iPart = TP_BUTTON;
833 BOOL bChecked = ( aValue.getTristateVal() == BUTTONVALUE_ON );
834 if( !(nState & CTRL_STATE_ENABLED) )
835 //iState = TS_DISABLED;
836 // disabled buttons are typically not painted at all but we need visual
837 // feedback when travelling by keyboard over disabled entries
838 iState = TS_HOT;
839 else if( nState & CTRL_STATE_PRESSED )
840 iState = TS_PRESSED;
841 else if( nState & CTRL_STATE_ROLLOVER )
842 iState = bChecked ? TS_HOTCHECKED : TS_HOT;
843 else
844 iState = bChecked ? TS_CHECKED : TS_NORMAL;
845 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
847 else if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT )
849 // the vertical gripper is not supported in most themes and it makes no
850 // sense to only support horizontal gripper
851 //iPart = (nPart == PART_THUMB_HORZ) ? RP_GRIPPERVERT : RP_GRIPPER;
852 //return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
854 else if( nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT )
856 ToolbarValue *pValue = (ToolbarValue*) aValue.getOptionalVal();
857 if( pValue && pValue->mbIsTopDockingArea )
858 rc.top = 0; // extend potential gradient to cover menu bar as well
859 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
863 if( nType == CTRL_MENUBAR )
865 if( nPart != PART_ENTIRE_CONTROL )
866 return FALSE;
868 MenubarValue *pValue = (MenubarValue*) aValue.getOptionalVal();
869 if( pValue )
870 rc.bottom += pValue->maTopDockingAreaHeight; // extend potential gradient to cover docking area as well
871 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
874 if( nType == CTRL_PROGRESS )
876 if( nPart != PART_ENTIRE_CONTROL )
877 return FALSE;
879 if( ! ImplDrawTheme( hTheme, hDC, PP_BAR, iState, rc, aCaption) )
880 return false;
881 RECT aProgressRect = rc;
882 if( vsAPI.GetThemeBackgroundContentRect( hTheme, hDC, PP_BAR, iState, &rc, &aProgressRect) != S_OK )
883 return false;
885 long nProgressWidth = aValue.getNumericVal();
886 nProgressWidth *= (aProgressRect.right - aProgressRect.left);
887 nProgressWidth /= (rc.right - rc.left);
888 if( Application::GetSettings().GetLayoutRTL() )
889 aProgressRect.left = aProgressRect.right - nProgressWidth;
890 else
891 aProgressRect.right = aProgressRect.left + nProgressWidth;
893 return ImplDrawTheme( hTheme, hDC, PP_CHUNK, iState, aProgressRect, aCaption );
896 return false;
900 * DrawNativeControl()
902 * Draws the requested control described by nPart/nState.
904 * rControlRegion: The bounding region of the complete control in VCL frame coordinates.
905 * aValue: An optional value (tristate/numerical/string)
906 * rControlHandle: Carries platform dependent data and is maintained by the WinSalGraphics implementation.
907 * aCaption: A caption or title string (like button text etc)
909 BOOL WinSalGraphics::drawNativeControl( ControlType nType,
910 ControlPart nPart,
911 const Region& rControlRegion,
912 ControlState nState,
913 const ImplControlValue& aValue,
914 SalControlHandle& rControlHandle,
915 const OUString& aCaption )
917 BOOL bOk = false;
918 HTHEME hTheme = NULL;
920 switch( nType )
922 case CTRL_PUSHBUTTON:
923 case CTRL_RADIOBUTTON:
924 case CTRL_CHECKBOX:
925 hTheme = getThemeHandle( mhWnd, L"Button");
926 break;
927 case CTRL_SCROLLBAR:
928 hTheme = getThemeHandle( mhWnd, L"Scrollbar");
929 break;
930 case CTRL_COMBOBOX:
931 if( nPart == PART_ENTIRE_CONTROL )
932 hTheme = getThemeHandle( mhWnd, L"Edit");
933 else if( nPart == PART_BUTTON_DOWN )
934 hTheme = getThemeHandle( mhWnd, L"Combobox");
935 break;
936 case CTRL_SPINBOX:
937 if( nPart == PART_ENTIRE_CONTROL )
938 hTheme = getThemeHandle( mhWnd, L"Edit");
939 else
940 hTheme = getThemeHandle( mhWnd, L"Spin");
941 break;
942 case CTRL_SPINBUTTONS:
943 hTheme = getThemeHandle( mhWnd, L"Spin");
944 break;
945 case CTRL_EDITBOX:
946 case CTRL_MULTILINE_EDITBOX:
947 hTheme = getThemeHandle( mhWnd, L"Edit");
948 break;
949 case CTRL_LISTBOX:
950 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_WINDOW )
951 hTheme = getThemeHandle( mhWnd, L"Listview");
952 else if( nPart == PART_BUTTON_DOWN )
953 hTheme = getThemeHandle( mhWnd, L"Combobox");
954 break;
955 case CTRL_TAB_PANE:
956 case CTRL_TAB_BODY:
957 case CTRL_TAB_ITEM:
958 case CTRL_FIXEDBORDER:
959 hTheme = getThemeHandle( mhWnd, L"Tab");
960 break;
961 case CTRL_TOOLBAR:
962 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_BUTTON )
963 hTheme = getThemeHandle( mhWnd, L"Toolbar");
964 else
965 // use rebar for grip and background
966 hTheme = getThemeHandle( mhWnd, L"Rebar");
967 break;
968 case CTRL_MENUBAR:
969 if( nPart == PART_ENTIRE_CONTROL )
970 hTheme = getThemeHandle( mhWnd, L"Rebar");
971 break;
972 case CTRL_PROGRESS:
973 if( nPart == PART_ENTIRE_CONTROL )
974 hTheme = getThemeHandle( mhWnd, L"Progress");
975 break;
976 default:
977 hTheme = NULL;
978 break;
981 if( !hTheme )
982 return false;
984 Rectangle buttonRect = rControlRegion.GetBoundRect();
985 RECT rc;
986 rc.left = buttonRect.Left();
987 rc.right = buttonRect.Right()+1;
988 rc.top = buttonRect.Top();
989 rc.bottom = buttonRect.Bottom()+1;
991 // set default text alignment
992 int ta = SetTextAlign( mhDC, TA_LEFT|TA_TOP|TA_NOUPDATECP );
994 OUString aCaptionStr( aCaption.replace('~', '&') ); // translate mnemonics
995 bOk = ImplDrawNativeControl(mhDC, hTheme, rc,
996 nType, nPart, nState, aValue,
997 rControlHandle, aCaptionStr );
999 // restore alignment
1000 SetTextAlign( mhDC, ta );
1003 //GdiFlush();
1005 return bOk;
1010 * DrawNativeControlText()
1012 * OPTIONAL. Draws the requested text for the control described by nPart/nState.
1013 * Used if text not drawn by DrawNativeControl().
1015 * rControlRegion: The bounding region of the complete control in VCL frame coordinates.
1016 * aValue: An optional value (tristate/numerical/string)
1017 * rControlHandle: Carries platform dependent data and is maintained by the WinSalGraphics implementation.
1018 * aCaption: A caption or title string (like button text etc)
1020 BOOL WinSalGraphics::drawNativeControlText( ControlType,
1021 ControlPart,
1022 const Region&,
1023 ControlState,
1024 const ImplControlValue&,
1025 SalControlHandle&,
1026 const OUString& )
1028 return( false );
1033 * GetNativeControlRegion()
1035 * If the return value is TRUE, rNativeBoundingRegion
1036 * contains the true bounding region covered by the control
1037 * including any adornment, while rNativeContentRegion contains the area
1038 * within the control that can be safely drawn into without drawing over
1039 * the borders of the control.
1041 * rControlRegion: The bounding region of the control in VCL frame coordinates.
1042 * aValue: An optional value (tristate/numerical/string)
1043 * rControlHandle: Carries platform dependent data and is maintained by the WinSalGraphics implementation.
1044 * aCaption: A caption or title string (like button text etc)
1046 BOOL WinSalGraphics::getNativeControlRegion( ControlType nType,
1047 ControlPart nPart,
1048 const Region& rControlRegion,
1049 ControlState,
1050 const ImplControlValue&,
1051 SalControlHandle&,
1052 const OUString&,
1053 Region &rNativeBoundingRegion,
1054 Region &rNativeContentRegion )
1056 BOOL bRet = FALSE;
1058 HDC hDC = GetDC( mhWnd );
1059 if( nType == CTRL_TOOLBAR )
1061 if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT )
1064 // the vertical gripper is not supported in most themes and it makes no
1065 // sense to only support horizontal gripper
1067 HTHEME hTheme = getThemeHandle( mhWnd, L"Rebar");
1068 if( hTheme )
1070 Rectangle aRect( ImplGetThemeRect( hTheme, hDC, nPart == PART_THUMB_HORZ ? RP_GRIPPERVERT : RP_GRIPPER,
1071 0, rControlRegion.GetBoundRect() ) );
1072 if( nPart == PART_THUMB_HORZ && !aRect.IsEmpty() )
1074 Rectangle aVertRect( 0, 0, aRect.getHeight(), aRect.getWidth() );
1075 rNativeContentRegion = aVertRect;
1077 else
1078 rNativeContentRegion = aRect;
1079 rNativeBoundingRegion = rNativeContentRegion;
1080 if( !rNativeContentRegion.IsEmpty() )
1081 bRet = TRUE;
1085 if( nPart == PART_BUTTON )
1087 HTHEME hTheme = getThemeHandle( mhWnd, L"Toolbar");
1088 if( hTheme )
1090 Rectangle aRect( ImplGetThemeRect( hTheme, hDC, TP_SPLITBUTTONDROPDOWN,
1091 TS_HOT, rControlRegion.GetBoundRect() ) );
1092 rNativeContentRegion = aRect;
1093 rNativeBoundingRegion = rNativeContentRegion;
1094 if( !rNativeContentRegion.IsEmpty() )
1095 bRet = TRUE;
1099 if( nType == CTRL_PROGRESS && nPart == PART_ENTIRE_CONTROL )
1101 HTHEME hTheme = getThemeHandle( mhWnd, L"Progress");
1102 if( hTheme )
1104 Rectangle aRect( ImplGetThemeRect( hTheme, hDC, PP_BAR,
1105 0, rControlRegion.GetBoundRect() ) );
1106 rNativeContentRegion = aRect;
1107 rNativeBoundingRegion = rNativeContentRegion;
1108 if( !rNativeContentRegion.IsEmpty() )
1109 bRet = TRUE;
1112 ReleaseDC( mhWnd, hDC );
1113 return( bRet );