Branch libreoffice-5-0-4
[LibreOffice.git] / vcl / win / source / gdi / salnativewidgets-luna.cxx
blobec3d79f4497276e40c07d7bb2818bd36b0bef91e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 // General info:
21 // http://msdn.microsoft.com/en-us/library/windows/desktop/hh270423%28v=vs.85%29.aspx
22 // http://msdn.microsoft.com/en-us/library/windows/desktop/bb773178%28v=vs.85%29.aspx
24 // Useful tool to explore the themes & their rendering:
25 // http://privat.rejbrand.se/UxExplore.exe
26 // (found at http://stackoverflow.com/questions/4009701/windows-visual-themes-gallery-of-parts-and-states/4009712#4009712)
28 // Theme subclasses:
29 // http://msdn.microsoft.com/en-us/library/windows/desktop/bb773218%28v=vs.85%29.aspx
31 // Drawing in non-client area (general DWM-related info):
32 // http://msdn.microsoft.com/en-us/library/windows/desktop/bb688195%28v=vs.85%29.aspx
34 #include "rtl/ustring.h"
36 #include "osl/module.h"
38 #include <opengl/win/gdiimpl.hxx>
39 #include "vcl/svapp.hxx"
40 #include <vcl/settings.hxx>
42 #include "win/svsys.h"
43 #include "win/salgdi.h"
44 #include "win/saldata.hxx"
46 #include "uxtheme.h"
47 #include "vssym32.h"
49 #include <map>
50 #include <string>
52 using namespace std;
54 typedef map< wstring, HTHEME > ThemeMap;
55 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 );
71 typedef BOOL (WINAPI * IsThemeActive_Proc_T) ( void );
73 OpenThemeData_Proc_T lpfnOpenThemeData;
74 CloseThemeData_Proc_T lpfnCloseThemeData;
75 GetThemeBackgroundContentRect_Proc_T lpfnGetThemeBackgroundContentRect;
76 DrawThemeBackground_Proc_T lpfnDrawThemeBackground;
77 DrawThemeText_Proc_T lpfnDrawThemeText;
78 GetThemePartSize_Proc_T lpfnGetThemePartSize;
79 IsThemeActive_Proc_T lpfnIsThemeActive;
81 oslModule mhModule;
83 public:
84 VisualStylesAPI();
85 ~VisualStylesAPI();
86 bool IsAvailable() { return (mhModule != NULL); }
88 HTHEME OpenThemeData( HWND hwnd, LPCWSTR pszClassList );
89 HRESULT CloseThemeData( HTHEME hTheme );
90 HRESULT GetThemeBackgroundContentRect( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pBoundingRect, RECT *pContentRect );
91 HRESULT DrawThemeBackground( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect );
92 HRESULT DrawThemeText( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, const RECT *pRect );
93 HRESULT GetThemePartSize( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, RECT *prc, THEMESIZE eSize, SIZE *psz );
94 BOOL IsThemeActive();
97 static VisualStylesAPI vsAPI;
99 VisualStylesAPI::VisualStylesAPI()
100 : lpfnOpenThemeData( NULL ),
101 lpfnCloseThemeData( NULL ),
102 lpfnGetThemeBackgroundContentRect( NULL ),
103 lpfnDrawThemeBackground( NULL ),
104 lpfnDrawThemeText( NULL ),
105 lpfnGetThemePartSize( NULL ),
106 lpfnIsThemeActive( NULL )
108 OUString aLibraryName( "uxtheme.dll" );
109 mhModule = osl_loadModule( aLibraryName.pData, SAL_LOADMODULE_DEFAULT );
111 if ( mhModule )
113 lpfnOpenThemeData = (OpenThemeData_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "OpenThemeData" );
114 lpfnCloseThemeData = (CloseThemeData_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "CloseThemeData" );
115 lpfnGetThemeBackgroundContentRect = (GetThemeBackgroundContentRect_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "GetThemeBackgroundContentRect" );
116 lpfnDrawThemeBackground = (DrawThemeBackground_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "DrawThemeBackground" );
117 lpfnDrawThemeText = (DrawThemeText_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "DrawThemeText" );
118 lpfnGetThemePartSize = (GetThemePartSize_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "GetThemePartSize" );
119 lpfnIsThemeActive = (IsThemeActive_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "IsThemeActive" );
123 VisualStylesAPI::~VisualStylesAPI()
125 if( mhModule )
126 osl_unloadModule( mhModule );
129 HTHEME VisualStylesAPI::OpenThemeData( HWND hwnd, LPCWSTR pszClassList )
131 if(lpfnOpenThemeData)
132 return (*lpfnOpenThemeData) (hwnd, pszClassList);
133 else
134 return NULL;
137 HRESULT VisualStylesAPI::CloseThemeData( HTHEME hTheme )
139 if(lpfnCloseThemeData)
140 return (*lpfnCloseThemeData) (hTheme);
141 else
142 return S_FALSE;
145 HRESULT VisualStylesAPI::GetThemeBackgroundContentRect( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pBoundingRect, RECT *pContentRect )
147 if(lpfnGetThemeBackgroundContentRect)
148 return (*lpfnGetThemeBackgroundContentRect) ( hTheme, hdc, iPartId, iStateId, pBoundingRect, pContentRect );
149 else
150 return S_FALSE;
153 HRESULT VisualStylesAPI::DrawThemeBackground( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect )
155 if(lpfnDrawThemeBackground)
156 return (*lpfnDrawThemeBackground) (hTheme, hdc, iPartId, iStateId, pRect, pClipRect);
157 else
158 return S_FALSE;
161 HRESULT VisualStylesAPI::DrawThemeText( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, const RECT *pRect )
163 if(lpfnDrawThemeText)
164 return (*lpfnDrawThemeText) (hTheme, hdc, iPartId, iStateId, pszText, iCharCount, dwTextFlags, dwTextFlags2, pRect);
165 else
166 return S_FALSE;
169 HRESULT VisualStylesAPI::GetThemePartSize( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, RECT *prc, THEMESIZE eSize, SIZE *psz )
171 if(lpfnGetThemePartSize)
172 return (*lpfnGetThemePartSize) (hTheme, hdc, iPartId, iStateId, prc, eSize, psz);
173 else
174 return S_FALSE;
177 BOOL VisualStylesAPI::IsThemeActive()
179 if(lpfnIsThemeActive)
180 return (*lpfnIsThemeActive) ();
181 else
182 return FALSE;
185 /*********************************************************
186 * Initialize XP theming and local stuff
187 *********************************************************/
188 void SalData::initNWF()
190 ImplSVData* pSVData = ImplGetSVData();
192 // the menu bar and the top docking area should have a common background (gradient)
193 pSVData->maNWFData.mbMenuBarDockingAreaCommonBG = true;
196 // *********************************************************
197 // * Release theming handles
198 // ********************************************************
199 void SalData::deInitNWF()
201 ThemeMap::iterator iter = aThemeMap.begin();
202 while( iter != aThemeMap.end() )
204 vsAPI.CloseThemeData(iter->second);
205 ++iter;
207 aThemeMap.clear();
208 if( maDwmLib )
209 osl_unloadModule( maDwmLib );
212 static HTHEME getThemeHandle( HWND hWnd, LPCWSTR name )
214 if( GetSalData()->mbThemeChanged )
216 // throw away invalid theme handles
217 GetSalData()->deInitNWF();
218 GetSalData()->mbThemeChanged = FALSE;
221 ThemeMap::iterator iter;
222 if( (iter = aThemeMap.find( name )) != aThemeMap.end() )
223 return iter->second;
224 // theme not found -> add it to map
225 HTHEME hTheme = vsAPI.OpenThemeData( hWnd, name );
226 if( hTheme != NULL )
227 aThemeMap[name] = hTheme;
228 return hTheme;
232 * IsNativeControlSupported()
234 * Returns TRUE if the platform supports native
235 * drawing of the control defined by nPart
237 bool WinSalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nPart )
239 HTHEME hTheme = NULL;
241 switch( nType )
243 case CTRL_PUSHBUTTON:
244 case CTRL_RADIOBUTTON:
245 case CTRL_CHECKBOX:
246 if( nPart == PART_ENTIRE_CONTROL )
247 hTheme = getThemeHandle( mhWnd, L"Button");
248 break;
249 case CTRL_SCROLLBAR:
250 if( nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT )
251 return FALSE; // no background painting needed
252 if( nPart == PART_ENTIRE_CONTROL )
253 hTheme = getThemeHandle( mhWnd, L"Scrollbar");
254 break;
255 case CTRL_COMBOBOX:
256 if( nPart == HAS_BACKGROUND_TEXTURE )
257 return FALSE; // we do not paint the inner part (ie the selection background/focus indication)
258 if( nPart == PART_ENTIRE_CONTROL )
259 hTheme = getThemeHandle( mhWnd, L"Edit");
260 else if( nPart == PART_BUTTON_DOWN )
261 hTheme = getThemeHandle( mhWnd, L"Combobox");
262 break;
263 case CTRL_SPINBOX:
264 if( nPart == PART_ENTIRE_CONTROL )
265 hTheme = getThemeHandle( mhWnd, L"Edit");
266 else if( nPart == PART_ALL_BUTTONS ||
267 nPart == PART_BUTTON_UP || nPart == PART_BUTTON_DOWN ||
268 nPart == PART_BUTTON_LEFT|| nPart == PART_BUTTON_RIGHT )
269 hTheme = getThemeHandle( mhWnd, L"Spin");
270 break;
271 case CTRL_SPINBUTTONS:
272 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_ALL_BUTTONS )
273 hTheme = getThemeHandle( mhWnd, L"Spin");
274 break;
275 case CTRL_EDITBOX:
276 case CTRL_MULTILINE_EDITBOX:
277 if( nPart == HAS_BACKGROUND_TEXTURE )
278 return FALSE; // we do not paint the inner part (ie the selection background/focus indication)
279 //return TRUE;
280 if( nPart == PART_ENTIRE_CONTROL )
281 hTheme = getThemeHandle( mhWnd, L"Edit");
282 break;
283 case CTRL_LISTBOX:
284 if( nPart == HAS_BACKGROUND_TEXTURE )
285 return FALSE; // we do not paint the inner part (ie the selection background/focus indication)
286 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_WINDOW )
287 hTheme = getThemeHandle( mhWnd, L"Listview");
288 else if( nPart == PART_BUTTON_DOWN )
289 hTheme = getThemeHandle( mhWnd, L"Combobox");
290 break;
291 case CTRL_TAB_PANE:
292 case CTRL_TAB_BODY:
293 case CTRL_TAB_ITEM:
294 if( nPart == PART_ENTIRE_CONTROL )
295 hTheme = getThemeHandle( mhWnd, L"Tab");
296 break;
297 case CTRL_TOOLBAR:
298 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_BUTTON )
299 hTheme = getThemeHandle( mhWnd, L"Toolbar");
300 else
301 // use rebar theme for grip and background
302 hTheme = getThemeHandle( mhWnd, L"Rebar");
303 break;
304 case CTRL_MENUBAR:
305 if( nPart == PART_ENTIRE_CONTROL )
306 hTheme = getThemeHandle( mhWnd, L"Rebar");
307 else if( GetSalData()->mbThemeMenuSupport )
309 if( nPart == PART_MENU_ITEM )
310 hTheme = getThemeHandle( mhWnd, L"Menu" );
312 break;
313 case CTRL_MENU_POPUP:
314 if( GetSalData()->mbThemeMenuSupport )
316 if( nPart == PART_ENTIRE_CONTROL ||
317 nPart == PART_MENU_ITEM ||
318 nPart == PART_MENU_ITEM_CHECK_MARK ||
319 nPart == PART_MENU_ITEM_RADIO_MARK ||
320 nPart == PART_MENU_SEPARATOR )
321 hTheme = getThemeHandle( mhWnd, L"Menu" );
323 break;
324 case CTRL_PROGRESS:
325 if( nPart == PART_ENTIRE_CONTROL )
326 hTheme = getThemeHandle( mhWnd, L"Progress");
327 break;
328 case CTRL_SLIDER:
329 if( nPart == PART_TRACK_HORZ_AREA || nPart == PART_TRACK_VERT_AREA )
330 hTheme = getThemeHandle( mhWnd, L"Trackbar" );
331 break;
332 case CTRL_LISTNODE:
333 if( nPart == PART_ENTIRE_CONTROL )
334 hTheme = getThemeHandle( mhWnd, L"TreeView" );
335 break;
336 default:
337 hTheme = NULL;
338 break;
341 return (hTheme != NULL);
345 * HitTestNativeControl()
347 * If the return value is TRUE, bIsInside contains information whether
348 * aPos was or was not inside the native widget specified by the
349 * nType/nPart combination.
351 bool WinSalGraphics::hitTestNativeControl( ControlType,
352 ControlPart,
353 const Rectangle&,
354 const Point&,
355 bool& )
357 return FALSE;
360 bool ImplDrawTheme( HTHEME hTheme, HDC hDC, int iPart, int iState, RECT rc, const OUString& aStr)
362 HRESULT hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
364 if( aStr.getLength() )
366 RECT rcContent;
367 hr = vsAPI.GetThemeBackgroundContentRect( hTheme, hDC, iPart, iState, &rc, &rcContent);
368 hr = vsAPI.DrawThemeText( hTheme, hDC, iPart, iState,
369 reinterpret_cast<LPCWSTR>(aStr.getStr()), -1,
370 DT_CENTER | DT_VCENTER | DT_SINGLELINE,
371 0, &rcContent);
373 return (hr == S_OK);
376 Rectangle ImplGetThemeRect( HTHEME hTheme, HDC hDC, int iPart, int iState, const Rectangle& /* aRect */, THEMESIZE eTS = TS_TRUE )
378 SIZE aSz;
379 HRESULT hr = vsAPI.GetThemePartSize( hTheme, hDC, iPart, iState, NULL, eTS, &aSz ); // TS_TRUE returns optimal size
380 if( hr == S_OK )
381 return Rectangle( 0, 0, aSz.cx, aSz.cy );
382 else
383 return Rectangle();
386 // Helper functions
388 void ImplConvertSpinbuttonValues( int nControlPart, const ControlState& rState, const Rectangle& rRect,
389 int* pLunaPart, int *pLunaState, RECT *pRect )
391 if( nControlPart == PART_BUTTON_DOWN )
393 *pLunaPart = SPNP_DOWN;
394 if( rState & ControlState::PRESSED )
395 *pLunaState = DNS_PRESSED;
396 else if( !(rState & ControlState::ENABLED) )
397 *pLunaState = DNS_DISABLED;
398 else if( rState & ControlState::ROLLOVER )
399 *pLunaState = DNS_HOT;
400 else
401 *pLunaState = DNS_NORMAL;
403 if( nControlPart == PART_BUTTON_UP )
405 *pLunaPart = SPNP_UP;
406 if( rState & ControlState::PRESSED )
407 *pLunaState = UPS_PRESSED;
408 else if( !(rState & ControlState::ENABLED) )
409 *pLunaState = UPS_DISABLED;
410 else if( rState & ControlState::ROLLOVER )
411 *pLunaState = UPS_HOT;
412 else
413 *pLunaState = UPS_NORMAL;
415 if( nControlPart == PART_BUTTON_RIGHT )
417 *pLunaPart = SPNP_UPHORZ;
418 if( rState & ControlState::PRESSED )
419 *pLunaState = DNHZS_PRESSED;
420 else if( !(rState & ControlState::ENABLED) )
421 *pLunaState = DNHZS_DISABLED;
422 else if( rState & ControlState::ROLLOVER )
423 *pLunaState = DNHZS_HOT;
424 else
425 *pLunaState = DNHZS_NORMAL;
427 if( nControlPart == PART_BUTTON_LEFT )
429 *pLunaPart = SPNP_DOWNHORZ;
430 if( rState & ControlState::PRESSED )
431 *pLunaState = UPHZS_PRESSED;
432 else if( !(rState & ControlState::ENABLED) )
433 *pLunaState = UPHZS_DISABLED;
434 else if( rState & ControlState::ROLLOVER )
435 *pLunaState = UPHZS_HOT;
436 else
437 *pLunaState = UPHZS_NORMAL;
440 pRect->left = rRect.Left();
441 pRect->right = rRect.Right()+1;
442 pRect->top = rRect.Top();
443 pRect->bottom = rRect.Bottom()+1;
446 /// Draw an own toolbar style on Windows Vista or later, looks better there
447 static void impl_drawAeroToolbar( HDC hDC, RECT rc, bool bHorizontal )
449 if ( rc.top == 0 && bHorizontal )
451 const long GRADIENT_HEIGHT = 32;
453 long gradient_break = rc.top;
454 long gradient_bottom = rc.bottom - 1;
455 GRADIENT_RECT g_rect[1] = { { 0, 1 } };
457 // very slow gradient at the top (if we have space for that)
458 if ( gradient_bottom - rc.top > GRADIENT_HEIGHT )
460 gradient_break = gradient_bottom - GRADIENT_HEIGHT;
462 TRIVERTEX vert[2] = {
463 { rc.left, rc.top, 0xff00, 0xff00, 0xff00, 0xff00 },
464 { rc.right, gradient_break, 0xfa00, 0xfa00, 0xfa00, 0xff00 },
466 GradientFill( hDC, vert, 2, g_rect, 1, GRADIENT_FILL_RECT_V );
469 // gradient at the bottom
470 TRIVERTEX vert[2] = {
471 { rc.left, gradient_break, 0xfa00, 0xfa00, 0xfa00, 0xff00 },
472 { rc.right, gradient_bottom, 0xf000, 0xf000, 0xf000, 0xff00 }
474 GradientFill( hDC, vert, 2, g_rect, 1, GRADIENT_FILL_RECT_V );
476 // and a darker horizontal line under that
477 HPEN hpen = CreatePen( PS_SOLID, 1, RGB( 0xb0, 0xb0, 0xb0 ) );
478 HPEN hOrigPen = (HPEN) SelectObject(hDC, hpen);
480 MoveToEx( hDC, rc.left, gradient_bottom, NULL );
481 LineTo( hDC, rc.right, gradient_bottom );
483 SelectObject(hDC, hOrigPen);
484 DeleteObject(hpen);
486 else
488 HBRUSH hbrush = CreateSolidBrush( RGB( 0xf0, 0xf0, 0xf0 ) );
489 FillRect( hDC, &rc, hbrush );
490 DeleteObject( hbrush );
492 // darker line to distinguish the toolbar and viewshell
493 // it is drawn only for the horizontal toolbars; it did not look well
494 // when done for the vertical ones too
495 if ( bHorizontal )
497 long from_x, from_y, to_x, to_y;
499 from_x = rc.left;
500 to_x = rc.right;
501 from_y = to_y = rc.top;
503 HPEN hpen = CreatePen( PS_SOLID, 1, RGB( 0xb0, 0xb0, 0xb0 ) );
504 HPEN hOrigPen = (HPEN) SelectObject(hDC, hpen);
506 MoveToEx( hDC, from_x, from_y, NULL );
507 LineTo( hDC, to_x, to_y );
509 SelectObject(hDC, hOrigPen);
510 DeleteObject(hpen);
515 bool ImplDrawNativeControl( HDC hDC, HTHEME hTheme, RECT rc,
516 ControlType nType,
517 ControlPart nPart,
518 ControlState nState,
519 const ImplControlValue& aValue,
520 OUString aCaption )
522 // a listbox dropdown is actually a combobox dropdown
523 if( nType == CTRL_LISTBOX )
524 if( nPart == PART_BUTTON_DOWN )
525 nType = CTRL_COMBOBOX;
527 // draw entire combobox as a large edit box
528 if( nType == CTRL_COMBOBOX )
529 if( nPart == PART_ENTIRE_CONTROL )
530 nType = CTRL_EDITBOX;
532 // draw entire spinbox as a large edit box
533 if( nType == CTRL_SPINBOX )
534 if( nPart == PART_ENTIRE_CONTROL )
535 nType = CTRL_EDITBOX;
537 int iPart(0), iState(0);
538 if( nType == CTRL_SCROLLBAR )
540 HRESULT hr;
541 if( nPart == PART_BUTTON_UP )
543 iPart = SBP_ARROWBTN;
544 if( nState & ControlState::PRESSED )
545 iState = ABS_UPPRESSED;
546 else if( !(nState & ControlState::ENABLED) )
547 iState = ABS_UPDISABLED;
548 else if( nState & ControlState::ROLLOVER )
549 iState = ABS_UPHOT;
550 else
551 iState = ABS_UPNORMAL;
552 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
553 return (hr == S_OK);
555 if( nPart == PART_BUTTON_DOWN )
557 iPart = SBP_ARROWBTN;
558 if( nState & ControlState::PRESSED )
559 iState = ABS_DOWNPRESSED;
560 else if( !(nState & ControlState::ENABLED) )
561 iState = ABS_DOWNDISABLED;
562 else if( nState & ControlState::ROLLOVER )
563 iState = ABS_DOWNHOT;
564 else
565 iState = ABS_DOWNNORMAL;
566 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
567 return (hr == S_OK);
569 if( nPart == PART_BUTTON_LEFT )
571 iPart = SBP_ARROWBTN;
572 if( nState & ControlState::PRESSED )
573 iState = ABS_LEFTPRESSED;
574 else if( !(nState & ControlState::ENABLED) )
575 iState = ABS_LEFTDISABLED;
576 else if( nState & ControlState::ROLLOVER )
577 iState = ABS_LEFTHOT;
578 else
579 iState = ABS_LEFTNORMAL;
580 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
581 return (hr == S_OK);
583 if( nPart == PART_BUTTON_RIGHT )
585 iPart = SBP_ARROWBTN;
586 if( nState & ControlState::PRESSED )
587 iState = ABS_RIGHTPRESSED;
588 else if( !(nState & ControlState::ENABLED) )
589 iState = ABS_RIGHTDISABLED;
590 else if( nState & ControlState::ROLLOVER )
591 iState = ABS_RIGHTHOT;
592 else
593 iState = ABS_RIGHTNORMAL;
594 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
595 return (hr == S_OK);
597 if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT )
599 iPart = (nPart == PART_THUMB_HORZ) ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT;
600 if( nState & ControlState::PRESSED )
601 iState = SCRBS_PRESSED;
602 else if( !(nState & ControlState::ENABLED) )
603 iState = SCRBS_DISABLED;
604 else if( nState & ControlState::ROLLOVER )
605 iState = SCRBS_HOT;
606 else
607 iState = SCRBS_NORMAL;
609 SIZE sz;
610 vsAPI.GetThemePartSize(hTheme, hDC, iPart, iState, NULL, TS_MIN, &sz);
611 vsAPI.GetThemePartSize(hTheme, hDC, iPart, iState, NULL, TS_TRUE, &sz);
612 vsAPI.GetThemePartSize(hTheme, hDC, iPart, iState, NULL, TS_DRAW, &sz);
614 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
615 // paint gripper on thumb if enough space
616 if( ( (nPart == PART_THUMB_VERT) && (rc.bottom-rc.top > 12) ) ||
617 ( (nPart == PART_THUMB_HORZ) && (rc.right-rc.left > 12) ) )
619 iPart = (nPart == PART_THUMB_HORZ) ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT;
620 iState = 0;
621 vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
623 return (hr == S_OK);
625 if( nPart == PART_TRACK_HORZ_LEFT || nPart == PART_TRACK_HORZ_RIGHT || nPart == PART_TRACK_VERT_UPPER || nPart == PART_TRACK_VERT_LOWER )
627 switch( nPart )
629 case PART_TRACK_HORZ_LEFT: iPart = SBP_UPPERTRACKHORZ; break;
630 case PART_TRACK_HORZ_RIGHT: iPart = SBP_LOWERTRACKHORZ; break;
631 case PART_TRACK_VERT_UPPER: iPart = SBP_UPPERTRACKVERT; break;
632 case PART_TRACK_VERT_LOWER: iPart = SBP_LOWERTRACKVERT; break;
635 if( nState & ControlState::PRESSED )
636 iState = SCRBS_PRESSED;
637 else if( !(nState & ControlState::ENABLED) )
638 iState = SCRBS_DISABLED;
639 else if( nState & ControlState::ROLLOVER )
640 iState = SCRBS_HOT;
641 else
642 iState = SCRBS_NORMAL;
643 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
644 return (hr == S_OK);
647 if( nType == CTRL_SPINBUTTONS && nPart == PART_ALL_BUTTONS )
649 if( aValue.getType() == CTRL_SPINBUTTONS )
651 const SpinbuttonValue* pValue = (aValue.getType() == CTRL_SPINBUTTONS) ? static_cast<const SpinbuttonValue*>(&aValue) : NULL;
653 RECT rect;
654 ImplConvertSpinbuttonValues( pValue->mnUpperPart, pValue->mnUpperState, pValue->maUpperRect, &iPart, &iState, &rect );
655 bool bOk = ImplDrawTheme( hTheme, hDC, iPart, iState, rect, aCaption);
657 if( bOk )
659 ImplConvertSpinbuttonValues( pValue->mnLowerPart, pValue->mnLowerState, pValue->maLowerRect, &iPart, &iState, &rect );
660 bOk = ImplDrawTheme( hTheme, hDC, iPart, iState, rect, aCaption);
663 return bOk;
666 if( nType == CTRL_SPINBOX )
668 // decrease spinbutton rects a little
669 //rc.right--;
670 //rc.bottom--;
671 if( nPart == PART_ALL_BUTTONS )
673 if( aValue.getType() == CTRL_SPINBUTTONS )
675 const SpinbuttonValue *pValue = static_cast<const SpinbuttonValue*>(&aValue);
677 RECT rect;
678 ImplConvertSpinbuttonValues( pValue->mnUpperPart, pValue->mnUpperState, pValue->maUpperRect, &iPart, &iState, &rect );
679 bool bOk = ImplDrawTheme( hTheme, hDC, iPart, iState, rect, aCaption);
681 if( bOk )
683 ImplConvertSpinbuttonValues( pValue->mnLowerPart, pValue->mnLowerState, pValue->maLowerRect, &iPart, &iState, &rect );
684 bOk = ImplDrawTheme( hTheme, hDC, iPart, iState, rect, aCaption);
687 return bOk;
691 if( nPart == PART_BUTTON_DOWN )
693 iPart = SPNP_DOWN;
694 if( nState & ControlState::PRESSED )
695 iState = DNS_PRESSED;
696 else if( !(nState & ControlState::ENABLED) )
697 iState = DNS_DISABLED;
698 else if( nState & ControlState::ROLLOVER )
699 iState = DNS_HOT;
700 else
701 iState = DNS_NORMAL;
703 if( nPart == PART_BUTTON_UP )
705 iPart = SPNP_UP;
706 if( nState & ControlState::PRESSED )
707 iState = UPS_PRESSED;
708 else if( !(nState & ControlState::ENABLED) )
709 iState = UPS_DISABLED;
710 else if( nState & ControlState::ROLLOVER )
711 iState = UPS_HOT;
712 else
713 iState = UPS_NORMAL;
715 if( nPart == PART_BUTTON_RIGHT )
717 iPart = SPNP_DOWNHORZ;
718 if( nState & ControlState::PRESSED )
719 iState = DNHZS_PRESSED;
720 else if( !(nState & ControlState::ENABLED) )
721 iState = DNHZS_DISABLED;
722 else if( nState & ControlState::ROLLOVER )
723 iState = DNHZS_HOT;
724 else
725 iState = DNHZS_NORMAL;
727 if( nPart == PART_BUTTON_LEFT )
729 iPart = SPNP_UPHORZ;
730 if( nState & ControlState::PRESSED )
731 iState = UPHZS_PRESSED;
732 else if( !(nState & ControlState::ENABLED) )
733 iState = UPHZS_DISABLED;
734 else if( nState & ControlState::ROLLOVER )
735 iState = UPHZS_HOT;
736 else
737 iState = UPHZS_NORMAL;
739 if( nPart == PART_BUTTON_LEFT || nPart == PART_BUTTON_RIGHT || nPart == PART_BUTTON_UP || nPart == PART_BUTTON_DOWN )
740 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
742 if( nType == CTRL_COMBOBOX )
744 if( nPart == PART_BUTTON_DOWN )
746 iPart = CP_DROPDOWNBUTTON;
747 if( nState & ControlState::PRESSED )
748 iState = CBXS_PRESSED;
749 else if( !(nState & ControlState::ENABLED) )
750 iState = CBXS_DISABLED;
751 else if( nState & ControlState::ROLLOVER )
752 iState = CBXS_HOT;
753 else
754 iState = CBXS_NORMAL;
755 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
758 if( nType == CTRL_PUSHBUTTON )
760 iPart = BP_PUSHBUTTON;
761 if( nState & ControlState::PRESSED )
762 iState = PBS_PRESSED;
763 else if( !(nState & ControlState::ENABLED) )
764 iState = PBS_DISABLED;
765 else if( nState & ControlState::ROLLOVER )
766 iState = PBS_HOT;
767 else if( nState & ControlState::DEFAULT )
768 iState = PBS_DEFAULTED;
769 //else if( nState & ControlState::FOCUSED )
770 // iState = PBS_DEFAULTED; // may need to draw focus rect
771 else
772 iState = PBS_NORMAL;
774 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
777 if( nType == CTRL_RADIOBUTTON )
779 iPart = BP_RADIOBUTTON;
780 bool bChecked = ( aValue.getTristateVal() == BUTTONVALUE_ON );
782 if( nState & ControlState::PRESSED )
783 iState = bChecked ? RBS_CHECKEDPRESSED : RBS_UNCHECKEDPRESSED;
784 else if( !(nState & ControlState::ENABLED) )
785 iState = bChecked ? RBS_CHECKEDDISABLED : RBS_UNCHECKEDDISABLED;
786 else if( nState & ControlState::ROLLOVER )
787 iState = bChecked ? RBS_CHECKEDHOT : RBS_UNCHECKEDHOT;
788 else
789 iState = bChecked ? RBS_CHECKEDNORMAL : RBS_UNCHECKEDNORMAL;
791 //if( nState & ControlState::FOCUSED )
792 // iState |= PBS_DEFAULTED; // may need to draw focus rect
794 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
797 if( nType == CTRL_CHECKBOX )
799 iPart = BP_CHECKBOX;
800 ButtonValue v = aValue.getTristateVal();
802 if( nState & ControlState::PRESSED )
803 iState = (v == BUTTONVALUE_ON) ? CBS_CHECKEDPRESSED :
804 ( (v == BUTTONVALUE_OFF) ? CBS_UNCHECKEDPRESSED : CBS_MIXEDPRESSED );
805 else if( !(nState & ControlState::ENABLED) )
806 iState = (v == BUTTONVALUE_ON) ? CBS_CHECKEDDISABLED :
807 ( (v == BUTTONVALUE_OFF) ? CBS_UNCHECKEDDISABLED : CBS_MIXEDDISABLED );
808 else if( nState & ControlState::ROLLOVER )
809 iState = (v == BUTTONVALUE_ON) ? CBS_CHECKEDHOT :
810 ( (v == BUTTONVALUE_OFF) ? CBS_UNCHECKEDHOT : CBS_MIXEDHOT );
811 else
812 iState = (v == BUTTONVALUE_ON) ? CBS_CHECKEDNORMAL :
813 ( (v == BUTTONVALUE_OFF) ? CBS_UNCHECKEDNORMAL : CBS_MIXEDNORMAL );
815 //if( nState & ControlState::FOCUSED )
816 // iState |= PBS_DEFAULTED; // may need to draw focus rect
818 //SIZE sz;
819 //THEMESIZE eSize = TS_DRAW; // TS_MIN, TS_TRUE, TS_DRAW
820 //vsAPI.GetThemePartSize( hTheme, hDC, iPart, iState, &rc, eSize, &sz);
822 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
825 if( ( nType == CTRL_EDITBOX ) || ( nType == CTRL_MULTILINE_EDITBOX ) )
827 iPart = EP_EDITTEXT;
828 if( !(nState & ControlState::ENABLED) )
829 iState = ETS_DISABLED;
830 else if( nState & ControlState::FOCUSED )
831 iState = ETS_FOCUSED;
832 else if( nState & ControlState::ROLLOVER )
833 iState = ETS_HOT;
834 else
835 iState = ETS_NORMAL;
837 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
840 if( nType == CTRL_LISTBOX )
842 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_WINDOW )
844 iPart = LVP_EMPTYTEXT; // ??? no idea which part to choose here
845 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
849 if( nType == CTRL_TAB_PANE )
851 iPart = TABP_PANE;
852 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
855 if( nType == CTRL_TAB_BODY )
857 iPart = TABP_BODY;
858 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
861 if( nType == CTRL_TAB_ITEM )
863 iPart = TABP_TABITEMLEFTEDGE;
864 rc.bottom--;
866 OSL_ASSERT( aValue.getType() == CTRL_TAB_ITEM );
868 const TabitemValue *pValue = static_cast<const TabitemValue*>(&aValue);
869 if( pValue->isBothAligned() )
871 iPart = TABP_TABITEMLEFTEDGE;
872 rc.right--;
874 else if( pValue->isLeftAligned() )
875 iPart = TABP_TABITEMLEFTEDGE;
876 else if( pValue->isRightAligned() )
877 iPart = TABP_TABITEMRIGHTEDGE;
878 else iPart = TABP_TABITEM;
880 if( !(nState & ControlState::ENABLED) )
881 iState = TILES_DISABLED;
882 else if( nState & ControlState::SELECTED )
884 iState = TILES_SELECTED;
885 // increase the selected tab
886 rc.left-=2;
887 if( pValue && !pValue->isBothAligned() )
889 if( pValue->isLeftAligned() || pValue->isNotAligned() )
890 rc.right+=2;
891 if( pValue->isRightAligned() )
892 rc.right+=1;
894 rc.top-=2;
895 rc.bottom+=2;
897 else if( nState & ControlState::ROLLOVER )
898 iState = TILES_HOT;
899 else if( nState & ControlState::FOCUSED )
900 iState = TILES_FOCUSED; // may need to draw focus rect
901 else
902 iState = TILES_NORMAL;
903 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
906 if( nType == CTRL_TOOLBAR )
908 if( nPart == PART_BUTTON )
910 iPart = TP_BUTTON;
911 bool bChecked = ( aValue.getTristateVal() == BUTTONVALUE_ON );
912 if( !(nState & ControlState::ENABLED) )
913 //iState = TS_DISABLED;
914 // disabled buttons are typically not painted at all but we need visual
915 // feedback when travelling by keyboard over disabled entries
916 iState = TS_HOT;
917 else if( nState & ControlState::PRESSED )
918 iState = TS_PRESSED;
919 else if( nState & ControlState::ROLLOVER )
920 iState = bChecked ? TS_HOTCHECKED : TS_HOT;
921 else
922 iState = bChecked ? TS_CHECKED : TS_NORMAL;
923 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
925 else if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT )
927 // the vertical gripper is not supported in most themes and it makes no
928 // sense to only support horizontal gripper
929 //iPart = (nPart == PART_THUMB_HORZ) ? RP_GRIPPERVERT : RP_GRIPPER;
930 //return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
932 else if( nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT )
934 if( aValue.getType() == CTRL_TOOLBAR )
936 const ToolbarValue *pValue = static_cast<const ToolbarValue*>(&aValue);
937 if( pValue->mbIsTopDockingArea )
938 rc.top = 0; // extend potential gradient to cover menu bar as well
941 // make it more compatible with Aero
942 if( ImplGetSVData()->maNWFData.mbDockingAreaAvoidTBFrames )
944 impl_drawAeroToolbar( hDC, rc, nPart == PART_DRAW_BACKGROUND_HORZ );
945 return true;
948 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
952 if( nType == CTRL_MENUBAR )
954 if( nPart == PART_ENTIRE_CONTROL )
956 if( aValue.getType() == CTRL_MENUBAR )
958 const MenubarValue *pValue = static_cast<const MenubarValue*>(&aValue);
959 rc.bottom += pValue->maTopDockingAreaHeight; // extend potential gradient to cover docking area as well
961 // make it more compatible with Aero
962 if( ImplGetSVData()->maNWFData.mbDockingAreaAvoidTBFrames )
964 impl_drawAeroToolbar( hDC, rc, true );
965 return true;
968 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
970 else if( nPart == PART_MENU_ITEM )
972 if( nState & ControlState::ENABLED )
974 if( nState & ControlState::SELECTED )
975 iState = MBI_PUSHED;
976 else if( nState & ControlState::ROLLOVER )
977 iState = MBI_HOT;
978 else
979 iState = MBI_NORMAL;
981 else
983 if( nState & ControlState::SELECTED )
984 iState = MBI_DISABLEDPUSHED;
985 else if( nState & ControlState::ROLLOVER )
986 iState = MBI_DISABLEDHOT;
987 else
988 iState = MBI_DISABLED;
990 return ImplDrawTheme( hTheme, hDC, MENU_BARITEM, iState, rc, aCaption );
994 if( nType == CTRL_PROGRESS )
996 if( nPart != PART_ENTIRE_CONTROL )
997 return FALSE;
999 if( ! ImplDrawTheme( hTheme, hDC, PP_BAR, iState, rc, aCaption) )
1000 return false;
1001 RECT aProgressRect = rc;
1002 if( vsAPI.GetThemeBackgroundContentRect( hTheme, hDC, PP_BAR, iState, &rc, &aProgressRect) != S_OK )
1003 return false;
1005 long nProgressWidth = aValue.getNumericVal();
1006 nProgressWidth *= (aProgressRect.right - aProgressRect.left);
1007 nProgressWidth /= (rc.right - rc.left);
1008 if( AllSettings::GetLayoutRTL() )
1009 aProgressRect.left = aProgressRect.right - nProgressWidth;
1010 else
1011 aProgressRect.right = aProgressRect.left + nProgressWidth;
1013 return ImplDrawTheme( hTheme, hDC, PP_CHUNK, iState, aProgressRect, aCaption );
1016 if( nType == CTRL_SLIDER )
1018 iPart = (nPart == PART_TRACK_HORZ_AREA) ? TKP_TRACK : TKP_TRACKVERT;
1019 iState = (nPart == PART_TRACK_HORZ_AREA) ? static_cast<int>(TRS_NORMAL) : static_cast<int>(TRVS_NORMAL);
1021 Rectangle aTrackRect = ImplGetThemeRect( hTheme, hDC, iPart, iState, Rectangle() );
1022 RECT aTRect = rc;
1023 if( nPart == PART_TRACK_HORZ_AREA )
1025 long nH = aTrackRect.GetHeight();
1026 aTRect.top += (rc.bottom - rc.top - nH)/2;
1027 aTRect.bottom = aTRect.top + nH;
1029 else
1031 long nW = aTrackRect.GetWidth();
1032 aTRect.left += (rc.right - rc.left - nW)/2;
1033 aTRect.right = aTRect.left + nW;
1035 ImplDrawTheme( hTheme, hDC, iPart, iState, aTRect, aCaption );
1037 RECT aThumbRect;
1038 OSL_ASSERT( aValue.getType() == CTRL_SLIDER );
1039 const SliderValue* pVal = static_cast<const SliderValue*>(&aValue);
1040 aThumbRect.left = pVal->maThumbRect.Left();
1041 aThumbRect.top = pVal->maThumbRect.Top();
1042 aThumbRect.right = pVal->maThumbRect.Right();
1043 aThumbRect.bottom = pVal->maThumbRect.Bottom();
1044 iPart = (nPart == PART_TRACK_HORZ_AREA) ? TKP_THUMB : TKP_THUMBVERT;
1045 iState = (nState & ControlState::ENABLED) ? TUS_NORMAL : TUS_DISABLED;
1046 return ImplDrawTheme( hTheme, hDC, iPart, iState, aThumbRect, aCaption );
1049 if( nType == CTRL_LISTNODE )
1051 if( nPart != PART_ENTIRE_CONTROL )
1052 return FALSE;
1054 ButtonValue aButtonValue = aValue.getTristateVal();
1055 iPart = TVP_GLYPH;
1056 switch( aButtonValue )
1058 case BUTTONVALUE_ON:
1059 iState = GLPS_OPENED;
1060 break;
1061 case BUTTONVALUE_OFF:
1062 iState = GLPS_CLOSED;
1063 break;
1064 default:
1065 return FALSE;
1067 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption );
1070 if( GetSalData()->mbThemeMenuSupport )
1072 if( nType == CTRL_MENU_POPUP )
1074 if( nPart == PART_ENTIRE_CONTROL )
1076 RECT aGutterRC = rc;
1077 if( AllSettings::GetLayoutRTL() )
1079 aGutterRC.right -= aValue.getNumericVal()+1;
1080 aGutterRC.left = aGutterRC.right-3;
1082 else
1084 aGutterRC.left += aValue.getNumericVal();
1085 aGutterRC.right = aGutterRC.left+3;
1087 return
1088 ImplDrawTheme( hTheme, hDC, MENU_POPUPBACKGROUND, 0, rc, aCaption ) &&
1089 ImplDrawTheme( hTheme, hDC, MENU_POPUPGUTTER, 0, aGutterRC, aCaption )
1092 else if( nPart == PART_MENU_ITEM )
1094 if( (nState & ControlState::ENABLED) )
1095 iState = (nState & ControlState::SELECTED) ? MPI_HOT : MPI_NORMAL;
1096 else
1097 iState = (nState & ControlState::SELECTED) ? MPI_DISABLEDHOT : MPI_DISABLED;
1098 return ImplDrawTheme( hTheme, hDC, MENU_POPUPITEM, iState, rc, aCaption );
1100 else if( nPart == PART_MENU_ITEM_CHECK_MARK || nPart == PART_MENU_ITEM_RADIO_MARK )
1102 if( (nState & ControlState::PRESSED) )
1104 RECT aBGRect = rc;
1105 if( aValue.getType() == CTRL_MENU_POPUP )
1107 const MenupopupValue& rMVal( static_cast<const MenupopupValue&>(aValue) );
1108 aBGRect.top = rMVal.maItemRect.Top();
1109 aBGRect.bottom = rMVal.maItemRect.Bottom()+1; // see below in drawNativeControl
1110 if( AllSettings::GetLayoutRTL() )
1112 aBGRect.right = rMVal.maItemRect.Right()+1;
1113 aBGRect.left = aBGRect.right - (rMVal.getNumericVal()-rMVal.maItemRect.Left());
1115 else
1117 aBGRect.right = rMVal.getNumericVal();
1118 aBGRect.left = rMVal.maItemRect.Left();
1120 rc = aBGRect;
1122 iState = (nState & ControlState::ENABLED) ? MCB_NORMAL : MCB_DISABLED;
1123 ImplDrawTheme( hTheme, hDC, MENU_POPUPCHECKBACKGROUND, iState, aBGRect, aCaption );
1124 if( nPart == PART_MENU_ITEM_CHECK_MARK )
1125 iState = (nState & ControlState::ENABLED) ? MC_CHECKMARKNORMAL : MC_CHECKMARKDISABLED;
1126 else
1127 iState = (nState & ControlState::ENABLED) ? MC_BULLETNORMAL : MC_BULLETDISABLED;
1128 return ImplDrawTheme( hTheme, hDC, MENU_POPUPCHECK, iState, rc, aCaption );
1130 else
1131 return true; // unchecked: do nothing
1133 else if( nPart == PART_MENU_SEPARATOR )
1135 // adjust for gutter position
1136 if( AllSettings::GetLayoutRTL() )
1137 rc.right -= aValue.getNumericVal()+1;
1138 else
1139 rc.left += aValue.getNumericVal()+1;
1140 Rectangle aRect( ImplGetThemeRect( hTheme, hDC,
1141 MENU_POPUPSEPARATOR, 0, Rectangle( rc.left, rc.top, rc.right, rc.bottom ) ) );
1142 // center the separator inside the passed rectangle
1143 long nDY = ((rc.bottom - rc.top + 1) - aRect.GetHeight()) / 2;
1144 rc.top += nDY;
1145 rc.bottom = rc.top+aRect.GetHeight()-1;
1146 return ImplDrawTheme( hTheme, hDC, MENU_POPUPSEPARATOR, 0, rc, aCaption );
1151 return false;
1155 * DrawNativeControl()
1157 * Draws the requested control described by nPart/nState.
1159 * rControlRegion: The bounding region of the complete control in VCL frame coordinates.
1160 * aValue: An optional value (tristate/numerical/string)
1161 * aCaption: A caption or title string (like button text etc)
1163 bool WinSalGraphics::drawNativeControl( ControlType nType,
1164 ControlPart nPart,
1165 const Rectangle& rControlRegion,
1166 ControlState nState,
1167 const ImplControlValue& aValue,
1168 const OUString& aCaption )
1170 bool bOk = false;
1171 HTHEME hTheme = NULL;
1173 Rectangle buttonRect = rControlRegion;
1175 WinOpenGLSalGraphicsImpl* pImpl = dynamic_cast<WinOpenGLSalGraphicsImpl*>(mpImpl.get());
1177 ControlCacheKey aControlCacheKey(nType, nPart, nState, buttonRect.GetSize());
1178 if (pImpl != NULL && pImpl->TryRenderCachedNativeControl(aControlCacheKey, buttonRect.Left(), buttonRect.Top()))
1180 return true;
1183 switch( nType )
1185 case CTRL_PUSHBUTTON:
1186 case CTRL_RADIOBUTTON:
1187 case CTRL_CHECKBOX:
1188 hTheme = getThemeHandle( mhWnd, L"Button");
1189 break;
1190 case CTRL_SCROLLBAR:
1191 hTheme = getThemeHandle( mhWnd, L"Scrollbar");
1192 break;
1193 case CTRL_COMBOBOX:
1194 if( nPart == PART_ENTIRE_CONTROL )
1195 hTheme = getThemeHandle( mhWnd, L"Edit");
1196 else if( nPart == PART_BUTTON_DOWN )
1197 hTheme = getThemeHandle( mhWnd, L"Combobox");
1198 break;
1199 case CTRL_SPINBOX:
1200 if( nPart == PART_ENTIRE_CONTROL )
1201 hTheme = getThemeHandle( mhWnd, L"Edit");
1202 else
1203 hTheme = getThemeHandle( mhWnd, L"Spin");
1204 break;
1205 case CTRL_SPINBUTTONS:
1206 hTheme = getThemeHandle( mhWnd, L"Spin");
1207 break;
1208 case CTRL_EDITBOX:
1209 case CTRL_MULTILINE_EDITBOX:
1210 hTheme = getThemeHandle( mhWnd, L"Edit");
1211 break;
1212 case CTRL_LISTBOX:
1213 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_WINDOW )
1214 hTheme = getThemeHandle( mhWnd, L"Listview");
1215 else if( nPart == PART_BUTTON_DOWN )
1216 hTheme = getThemeHandle( mhWnd, L"Combobox");
1217 break;
1218 case CTRL_TAB_PANE:
1219 case CTRL_TAB_BODY:
1220 case CTRL_TAB_ITEM:
1221 hTheme = getThemeHandle( mhWnd, L"Tab");
1222 break;
1223 case CTRL_TOOLBAR:
1224 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_BUTTON )
1225 hTheme = getThemeHandle( mhWnd, L"Toolbar");
1226 else
1227 // use rebar for grip and background
1228 hTheme = getThemeHandle( mhWnd, L"Rebar");
1229 break;
1230 case CTRL_MENUBAR:
1231 if( nPart == PART_ENTIRE_CONTROL )
1232 hTheme = getThemeHandle( mhWnd, L"Rebar");
1233 else if( GetSalData()->mbThemeMenuSupport )
1235 if( nPart == PART_MENU_ITEM )
1236 hTheme = getThemeHandle( mhWnd, L"Menu" );
1238 break;
1239 case CTRL_PROGRESS:
1240 if( nPart == PART_ENTIRE_CONTROL )
1241 hTheme = getThemeHandle( mhWnd, L"Progress");
1242 break;
1243 case CTRL_LISTNODE:
1244 if( nPart == PART_ENTIRE_CONTROL )
1245 hTheme = getThemeHandle( mhWnd, L"TreeView");
1246 break;
1247 case CTRL_SLIDER:
1248 if( nPart == PART_TRACK_HORZ_AREA || nPart == PART_TRACK_VERT_AREA )
1249 hTheme = getThemeHandle( mhWnd, L"Trackbar" );
1250 break;
1251 case CTRL_MENU_POPUP:
1252 if( GetSalData()->mbThemeMenuSupport )
1254 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_MENU_ITEM ||
1255 nPart == PART_MENU_ITEM_CHECK_MARK || nPart == PART_MENU_ITEM_RADIO_MARK ||
1256 nPart == PART_MENU_SEPARATOR
1258 hTheme = getThemeHandle( mhWnd, L"Menu" );
1260 break;
1261 default:
1262 hTheme = NULL;
1263 break;
1266 if( !hTheme )
1267 return false;
1269 RECT rc;
1270 rc.left = buttonRect.Left();
1271 rc.right = buttonRect.Right()+1;
1272 rc.top = buttonRect.Top();
1273 rc.bottom = buttonRect.Bottom()+1;
1275 OUString aCaptionStr(aCaption.replace('~', '&')); // translate mnemonics
1277 if (pImpl == NULL)
1279 // set default text alignment
1280 int ta = SetTextAlign(getHDC(), TA_LEFT|TA_TOP|TA_NOUPDATECP);
1282 bOk = ImplDrawNativeControl(getHDC(), hTheme, rc, nType, nPart, nState, aValue, aCaptionStr);
1284 // restore alignment
1285 SetTextAlign(getHDC(), ta);
1287 else
1289 // We can do OpenGL
1290 OpenGLCompatibleDC aBlackDC(*this, buttonRect.Left(), buttonRect.Top(), buttonRect.GetWidth(), buttonRect.GetHeight());
1291 SetTextAlign(aBlackDC.getCompatibleHDC(), TA_LEFT|TA_TOP|TA_NOUPDATECP);
1292 aBlackDC.fill(MAKE_SALCOLOR(0, 0, 0));
1294 OpenGLCompatibleDC aWhiteDC(*this, buttonRect.Left(), buttonRect.Top(), buttonRect.GetWidth(), buttonRect.GetHeight());
1295 SetTextAlign(aWhiteDC.getCompatibleHDC(), TA_LEFT|TA_TOP|TA_NOUPDATECP);
1296 aWhiteDC.fill(MAKE_SALCOLOR(0xff, 0xff, 0xff));
1298 if (ImplDrawNativeControl(aBlackDC.getCompatibleHDC(), hTheme, rc, nType, nPart, nState, aValue, aCaptionStr) &&
1299 ImplDrawNativeControl(aWhiteDC.getCompatibleHDC(), hTheme, rc, nType, nPart, nState, aValue, aCaptionStr))
1301 bOk = pImpl->RenderAndCacheNativeControl(aWhiteDC, aBlackDC, buttonRect.Left(), buttonRect.Top(), aControlCacheKey);
1305 return bOk;
1309 * GetNativeControlRegion()
1311 * If the return value is TRUE, rNativeBoundingRegion
1312 * contains the true bounding region covered by the control
1313 * including any adornment, while rNativeContentRegion contains the area
1314 * within the control that can be safely drawn into without drawing over
1315 * the borders of the control.
1317 * rControlRegion: The bounding region of the control in VCL frame coordinates.
1318 * aValue: An optional value (tristate/numerical/string)
1319 * aCaption: A caption or title string (like button text etc)
1321 bool WinSalGraphics::getNativeControlRegion( ControlType nType,
1322 ControlPart nPart,
1323 const Rectangle& rControlRegion,
1324 ControlState nState,
1325 const ImplControlValue& rControlValue,
1326 const OUString&,
1327 Rectangle &rNativeBoundingRegion,
1328 Rectangle &rNativeContentRegion )
1330 bool bRet = FALSE;
1332 HDC hDC = GetDC( mhWnd );
1333 if( nType == CTRL_TOOLBAR )
1335 if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT )
1338 // the vertical gripper is not supported in most themes and it makes no
1339 // sense to only support horizontal gripper
1341 HTHEME hTheme = getThemeHandle( mhWnd, L"Rebar");
1342 if( hTheme )
1344 Rectangle aRect( ImplGetThemeRect( hTheme, hDC, nPart == PART_THUMB_HORZ ? RP_GRIPPERVERT : RP_GRIPPER,
1345 0, rControlRegion.GetBoundRect() ) );
1346 if( nPart == PART_THUMB_HORZ && !aRect.IsEmpty() )
1348 Rectangle aVertRect( 0, 0, aRect.getHeight(), aRect.getWidth() );
1349 rNativeContentRegion = aVertRect;
1351 else
1352 rNativeContentRegion = aRect;
1353 rNativeBoundingRegion = rNativeContentRegion;
1354 if( !rNativeContentRegion.IsEmpty() )
1355 bRet = TRUE;
1359 if( nPart == PART_BUTTON )
1361 HTHEME hTheme = getThemeHandle( mhWnd, L"Toolbar");
1362 if( hTheme )
1364 Rectangle aRect( ImplGetThemeRect( hTheme, hDC, TP_SPLITBUTTONDROPDOWN,
1365 TS_HOT, rControlRegion ) );
1366 rNativeContentRegion = aRect;
1367 rNativeBoundingRegion = rNativeContentRegion;
1368 if( !rNativeContentRegion.IsEmpty() )
1369 bRet = TRUE;
1373 if( nType == CTRL_PROGRESS && nPart == PART_ENTIRE_CONTROL )
1375 HTHEME hTheme = getThemeHandle( mhWnd, L"Progress");
1376 if( hTheme )
1378 Rectangle aRect( ImplGetThemeRect( hTheme, hDC, PP_BAR,
1379 0, rControlRegion ) );
1380 rNativeContentRegion = aRect;
1381 rNativeBoundingRegion = rNativeContentRegion;
1382 if( !rNativeContentRegion.IsEmpty() )
1383 bRet = TRUE;
1386 if( (nType == CTRL_LISTBOX || nType == CTRL_COMBOBOX ) && nPart == PART_ENTIRE_CONTROL )
1388 HTHEME hTheme = getThemeHandle( mhWnd, L"Combobox");
1389 if( hTheme )
1391 Rectangle aBoxRect( rControlRegion );
1392 Rectangle aRect( ImplGetThemeRect( hTheme, hDC, CP_DROPDOWNBUTTON,
1393 CBXS_NORMAL, aBoxRect ) );
1394 if( aRect.GetHeight() > aBoxRect.GetHeight() )
1395 aBoxRect.Bottom() = aBoxRect.Top() + aRect.GetHeight();
1396 if( aRect.GetWidth() > aBoxRect.GetWidth() )
1397 aBoxRect.Right() = aBoxRect.Left() + aRect.GetWidth();
1398 rNativeContentRegion = aBoxRect;
1399 rNativeBoundingRegion = rNativeContentRegion;
1400 if( !aRect.IsEmpty() )
1401 bRet = TRUE;
1405 if( (nType == CTRL_EDITBOX || nType == CTRL_SPINBOX) && nPart == PART_ENTIRE_CONTROL )
1407 HTHEME hTheme = getThemeHandle( mhWnd, L"Edit");
1408 if( hTheme )
1410 // get border size
1411 Rectangle aBoxRect( rControlRegion );
1412 Rectangle aRect( ImplGetThemeRect( hTheme, hDC, EP_BACKGROUNDWITHBORDER,
1413 EBWBS_HOT, aBoxRect ) );
1414 // ad app font height
1415 NONCLIENTMETRICSW aNonClientMetrics;
1416 aNonClientMetrics.cbSize = sizeof( aNonClientMetrics );
1417 if ( SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, sizeof( aNonClientMetrics ), &aNonClientMetrics, 0 ) )
1419 long nFontHeight = aNonClientMetrics.lfMessageFont.lfHeight;
1420 if( nFontHeight < 0 )
1421 nFontHeight = -nFontHeight;
1423 if( aRect.GetHeight() && nFontHeight )
1425 aRect.Bottom() += aRect.GetHeight();
1426 aRect.Bottom() += nFontHeight;
1427 if( aRect.GetHeight() > aBoxRect.GetHeight() )
1428 aBoxRect.Bottom() = aBoxRect.Top() + aRect.GetHeight();
1429 if( aRect.GetWidth() > aBoxRect.GetWidth() )
1430 aBoxRect.Right() = aBoxRect.Left() + aRect.GetWidth();
1431 rNativeContentRegion = aBoxRect;
1432 rNativeBoundingRegion = rNativeContentRegion;
1433 bRet = TRUE;
1439 if( GetSalData()->mbThemeMenuSupport )
1441 if( nType == CTRL_MENU_POPUP )
1443 if( nPart == PART_MENU_ITEM_CHECK_MARK ||
1444 nPart == PART_MENU_ITEM_RADIO_MARK )
1446 HTHEME hTheme = getThemeHandle( mhWnd, L"Menu");
1447 Rectangle aBoxRect( rControlRegion );
1448 Rectangle aRect( ImplGetThemeRect( hTheme, hDC,
1449 MENU_POPUPCHECK,
1450 MC_CHECKMARKNORMAL,
1451 aBoxRect ) );
1452 if( aBoxRect.GetWidth() && aBoxRect.GetHeight() )
1454 rNativeContentRegion = aRect;
1455 rNativeBoundingRegion = rNativeContentRegion;
1456 bRet = TRUE;
1462 if( nType == CTRL_SLIDER && ( (nPart == PART_THUMB_HORZ) || (nPart == PART_THUMB_VERT) ) )
1464 HTHEME hTheme = getThemeHandle( mhWnd, L"Trackbar");
1465 if( hTheme )
1467 int iPart = (nPart == PART_THUMB_HORZ) ? TKP_THUMB : TKP_THUMBVERT;
1468 int iState = (nPart == PART_THUMB_HORZ) ? static_cast<int>(TUS_NORMAL) : static_cast<int>(TUVS_NORMAL);
1469 Rectangle aThumbRect = ImplGetThemeRect( hTheme, hDC, iPart, iState, Rectangle() );
1470 if( nPart == PART_THUMB_HORZ )
1472 long nW = aThumbRect.GetWidth();
1473 Rectangle aRect( rControlRegion );
1474 aRect.Right() = aRect.Left() + nW - 1;
1475 rNativeContentRegion = aRect;
1476 rNativeBoundingRegion = rNativeContentRegion;
1478 else
1480 long nH = aThumbRect.GetHeight();
1481 Rectangle aRect( rControlRegion );
1482 aRect.Bottom() = aRect.Top() + nH - 1;
1483 rNativeContentRegion = aRect;
1484 rNativeBoundingRegion = rNativeContentRegion;
1486 bRet = TRUE;
1490 if ( ( nType == CTRL_TAB_ITEM ) && ( nPart == PART_ENTIRE_CONTROL ) )
1492 Rectangle aControlRect( rControlRegion );
1493 rNativeContentRegion = aControlRect;
1495 --aControlRect.Bottom();
1497 if( rControlValue.getType() == CTRL_TAB_ITEM )
1499 const TabitemValue *pValue = static_cast<const TabitemValue*>(&rControlValue);
1500 if ( pValue->isBothAligned() )
1501 --aControlRect.Right();
1503 if ( nState & ControlState::SELECTED )
1505 aControlRect.Left() -= 2;
1506 if ( pValue && !pValue->isBothAligned() )
1508 if ( pValue->isLeftAligned() || pValue->isNotAligned() )
1509 aControlRect.Right() += 2;
1510 if ( pValue->isRightAligned() )
1511 aControlRect.Right() += 1;
1513 aControlRect.Top() -= 2;
1514 aControlRect.Bottom() += 2;
1517 rNativeBoundingRegion = aControlRect;
1518 bRet = TRUE;
1521 ReleaseDC( mhWnd, hDC );
1522 return bRet;
1525 void WinSalGraphics::updateSettingsNative( AllSettings& rSettings )
1527 if ( !vsAPI.IsThemeActive() )
1528 return;
1530 StyleSettings aStyleSettings = rSettings.GetStyleSettings();
1531 ImplSVData* pSVData = ImplGetSVData();
1533 // don't draw frame around each and every toolbar
1534 pSVData->maNWFData.mbDockingAreaAvoidTBFrames = true;
1536 // check if vista or newer runs
1537 // in Aero theme (and similar ?) the menu text color does not change
1538 // for selected items; also on WinXP and earlier menus are not themed
1539 // FIXME get the color directly from the theme, not from the settings
1540 if (aSalShlData.mbWVista)
1542 Color aMenuBarTextColor = aStyleSettings.GetPersonaMenuBarTextColor().get_value_or( aStyleSettings.GetMenuTextColor() );
1543 // in aero menuitem highlight text is drawn in the same color as normal
1544 aStyleSettings.SetMenuHighlightTextColor( aStyleSettings.GetMenuTextColor() );
1545 aStyleSettings.SetMenuBarRolloverTextColor( aMenuBarTextColor );
1546 aStyleSettings.SetMenuBarHighlightTextColor( aMenuBarTextColor );
1547 pSVData->maNWFData.mnMenuFormatBorderX = 2;
1548 pSVData->maNWFData.mnMenuFormatBorderY = 2;
1549 pSVData->maNWFData.maMenuBarHighlightTextColor = aMenuBarTextColor;
1550 GetSalData()->mbThemeMenuSupport = TRUE;
1553 rSettings.SetStyleSettings( aStyleSettings );
1556 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */