1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/univ/themes/metal.cpp
3 // Purpose: wxUniversal theme implementing Win32-like LNF
4 // Author: Vadim Zeitlin, Robert Roebling
7 // Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 // ===========================================================================
13 // ===========================================================================
15 // ---------------------------------------------------------------------------
17 // ---------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
26 #include "wx/univ/theme.h"
34 #include "wx/window.h"
36 #include "wx/dcmemory.h"
38 #include "wx/button.h"
39 #include "wx/listbox.h"
40 #include "wx/checklst.h"
41 #include "wx/combobox.h"
42 #include "wx/scrolbar.h"
43 #include "wx/slider.h"
44 #include "wx/textctrl.h"
45 #include "wx/toolbar.h"
48 #include "wx/settings.h"
49 #include "wx/toplevel.h"
52 #include "wx/notebook.h"
53 #include "wx/spinbutt.h"
54 #include "wx/artprov.h"
56 #include "wx/univ/scrtimer.h"
57 #include "wx/univ/renderer.h"
58 #include "wx/univ/inpcons.h"
59 #include "wx/univ/inphand.h"
60 #include "wx/univ/colschem.h"
62 // ----------------------------------------------------------------------------
63 // wxMetalRenderer: draw the GUI elements in Metal style
64 // ----------------------------------------------------------------------------
66 class wxMetalRenderer
: public wxDelegateRenderer
68 // FIXME cut'n'paste from Win32
84 Arrow_InvertedDisabled
,
88 wxMetalRenderer(wxRenderer
*renderer
, wxColourScheme
* scheme
);
90 virtual void DrawButtonSurface(wxDC
& dc
,
91 const wxColour
& WXUNUSED(col
),
94 { DrawMetal(dc
, rect
); }
96 virtual void DrawScrollbarThumb(wxDC
& dc
,
101 virtual void DrawScrollbarShaft(wxDC
& dc
,
102 wxOrientation orient
,
103 const wxRect
& rectBar
,
106 virtual void GetComboBitmaps(wxBitmap
*bmpNormal
,
108 wxBitmap
*bmpPressed
,
109 wxBitmap
*bmpDisabled
);
111 virtual void DrawArrow(wxDC
& dc
,
116 void DrawArrowButton(wxDC
& dc
,
117 const wxRect
& rectAll
,
118 wxArrowDirection arrowDir
,
119 wxArrowStyle arrowStyle
);
121 void DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
123 void DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
124 const wxPen
& pen1
, const wxPen
& pen2
);
126 void DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
= false);
128 void DrawArrow(wxDC
& dc
, const wxRect
& rect
,
129 wxArrowDirection arrowDir
, wxArrowStyle arrowStyle
);
131 void DrawMetal(wxDC
&dc
, const wxRect
&rect
);
138 wxBitmap m_bmpArrows
[Arrow_StateMax
][Arrow_Max
];
141 // ----------------------------------------------------------------------------
143 // ----------------------------------------------------------------------------
145 class wxMetalTheme
: public wxDelegateTheme
148 wxMetalTheme() : wxDelegateTheme(wxT("win32")), m_renderer(NULL
) {}
149 ~wxMetalTheme() { delete m_renderer
; }
152 virtual wxRenderer
*GetRenderer()
156 m_renderer
= new wxMetalRenderer(m_theme
->GetRenderer(),
163 wxRenderer
*m_renderer
;
165 WX_DECLARE_THEME(Metal
)
168 WX_IMPLEMENT_THEME(wxMetalTheme
, Metal
, wxTRANSLATE("Metal theme"));
171 // ============================================================================
173 // ============================================================================
175 // ----------------------------------------------------------------------------
177 // ----------------------------------------------------------------------------
179 wxMetalRenderer::wxMetalRenderer(wxRenderer
*renderer
, wxColourScheme
*scheme
)
180 : wxDelegateRenderer(renderer
)
182 // init colours and pens
183 m_penBlack
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_DARK
), 0, wxSOLID
);
184 m_penDarkGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_OUT
), 0, wxSOLID
);
185 m_penLightGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_IN
), 0, wxSOLID
);
186 m_penHighlight
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_HIGHLIGHT
), 0, wxSOLID
);
188 // init the arrow bitmaps
189 static const size_t ARROW_WIDTH
= 7;
190 static const size_t ARROW_LENGTH
= 4;
196 for ( size_t n
= 0; n
< Arrow_Max
; n
++ )
198 bool isVertical
= n
> Arrow_Right
;
211 // disabled arrow is larger because of the shadow
212 m_bmpArrows
[Arrow_Normal
][n
].Create(w
, h
);
213 m_bmpArrows
[Arrow_Disabled
][n
].Create(w
+ 1, h
+ 1);
215 dcNormal
.SelectObject(m_bmpArrows
[Arrow_Normal
][n
]);
216 dcDisabled
.SelectObject(m_bmpArrows
[Arrow_Disabled
][n
]);
218 dcNormal
.SetBackground(*wxWHITE_BRUSH
);
219 dcDisabled
.SetBackground(*wxWHITE_BRUSH
);
223 dcNormal
.SetPen(m_penBlack
);
224 dcDisabled
.SetPen(m_penDarkGrey
);
226 // calculate the position of the point of the arrow
230 x1
= (ARROW_WIDTH
- 1)/2;
231 y1
= n
== Arrow_Up
? 0 : ARROW_LENGTH
- 1;
235 x1
= n
== Arrow_Left
? 0 : ARROW_LENGTH
- 1;
236 y1
= (ARROW_WIDTH
- 1)/2;
247 for ( size_t i
= 0; i
< ARROW_LENGTH
; i
++ )
249 dcNormal
.DrawLine(x1
, y1
, x2
, y2
);
250 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
268 else // left or right arrow
273 if ( n
== Arrow_Left
)
286 // draw the shadow for the disabled one
287 dcDisabled
.SetPen(m_penHighlight
);
292 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
296 x1
= ARROW_LENGTH
- 1;
297 y1
= (ARROW_WIDTH
- 1)/2 + 1;
300 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
301 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
306 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
310 x1
= ARROW_WIDTH
- 1;
312 x2
= (ARROW_WIDTH
- 1)/2;
314 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
315 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
320 // create the inverted bitmap but only for the right arrow as we only
321 // use it for the menus
322 if ( n
== Arrow_Right
)
324 m_bmpArrows
[Arrow_Inverted
][n
].Create(w
, h
);
325 dcInverse
.SelectObject(m_bmpArrows
[Arrow_Inverted
][n
]);
327 dcInverse
.Blit(0, 0, w
, h
,
330 dcInverse
.SelectObject(wxNullBitmap
);
332 mask
= new wxMask(m_bmpArrows
[Arrow_Inverted
][n
], *wxBLACK
);
333 m_bmpArrows
[Arrow_Inverted
][n
].SetMask(mask
);
335 m_bmpArrows
[Arrow_InvertedDisabled
][n
].Create(w
, h
);
336 dcInverse
.SelectObject(m_bmpArrows
[Arrow_InvertedDisabled
][n
]);
338 dcInverse
.Blit(0, 0, w
, h
,
341 dcInverse
.SelectObject(wxNullBitmap
);
343 mask
= new wxMask(m_bmpArrows
[Arrow_InvertedDisabled
][n
], *wxBLACK
);
344 m_bmpArrows
[Arrow_InvertedDisabled
][n
].SetMask(mask
);
347 dcNormal
.SelectObject(wxNullBitmap
);
348 dcDisabled
.SelectObject(wxNullBitmap
);
350 mask
= new wxMask(m_bmpArrows
[Arrow_Normal
][n
], *wxWHITE
);
351 m_bmpArrows
[Arrow_Normal
][n
].SetMask(mask
);
352 mask
= new wxMask(m_bmpArrows
[Arrow_Disabled
][n
], *wxWHITE
);
353 m_bmpArrows
[Arrow_Disabled
][n
].SetMask(mask
);
355 m_bmpArrows
[Arrow_Pressed
][n
] = m_bmpArrows
[Arrow_Normal
][n
];
359 void wxMetalRenderer::DrawScrollbarThumb(wxDC
& dc
,
360 wxOrientation
WXUNUSED(orient
),
364 // we don't use the flags, the thumb never changes appearance
365 wxRect rectThumb
= rect
;
366 DrawArrowBorder(dc
, &rectThumb
);
367 DrawMetal(dc
, rectThumb
);
370 void wxMetalRenderer::DrawScrollbarShaft(wxDC
& dc
,
371 wxOrientation
WXUNUSED(orient
),
372 const wxRect
& rectBar
,
375 DrawMetal(dc
, rectBar
);
378 void wxMetalRenderer::GetComboBitmaps(wxBitmap
*bmpNormal
,
379 wxBitmap
* WXUNUSED(bmpFocus
),
380 wxBitmap
*bmpPressed
,
381 wxBitmap
*bmpDisabled
)
383 static const wxCoord widthCombo
= 16;
384 static const wxCoord heightCombo
= 17;
390 bmpNormal
->Create(widthCombo
, heightCombo
);
391 dcMem
.SelectObject(*bmpNormal
);
392 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
393 Arrow_Down
, Arrow_Normal
);
398 bmpPressed
->Create(widthCombo
, heightCombo
);
399 dcMem
.SelectObject(*bmpPressed
);
400 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
401 Arrow_Down
, Arrow_Pressed
);
406 bmpDisabled
->Create(widthCombo
, heightCombo
);
407 dcMem
.SelectObject(*bmpDisabled
);
408 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
409 Arrow_Down
, Arrow_Disabled
);
413 void wxMetalRenderer::DrawArrow(wxDC
& dc
,
418 // get the bitmap for this arrow
419 wxArrowDirection arrowDir
;
422 case wxLEFT
: arrowDir
= Arrow_Left
; break;
423 case wxRIGHT
: arrowDir
= Arrow_Right
; break;
424 case wxUP
: arrowDir
= Arrow_Up
; break;
425 case wxDOWN
: arrowDir
= Arrow_Down
; break;
428 wxFAIL_MSG(wxT("unknown arrow direction"));
432 wxArrowStyle arrowStyle
;
433 if ( flags
& wxCONTROL_PRESSED
)
435 // can't be pressed and disabled
436 arrowStyle
= Arrow_Pressed
;
440 arrowStyle
= flags
& wxCONTROL_DISABLED
? Arrow_Disabled
: Arrow_Normal
;
443 DrawArrowButton(dc
, rect
, arrowDir
, arrowStyle
);
447 // protected functions
450 void wxMetalRenderer::DrawArrowButton(wxDC
& dc
,
451 const wxRect
& rectAll
,
452 wxArrowDirection arrowDir
,
453 wxArrowStyle arrowStyle
)
455 wxRect rect
= rectAll
;
456 DrawMetal( dc
, rect
);
457 DrawArrowBorder(dc
, &rect
, arrowStyle
== Arrow_Pressed
);
458 DrawArrow(dc
, rect
, arrowDir
, arrowStyle
);
461 void wxMetalRenderer::DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
465 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
466 dc
.DrawRectangle(*rect
);
472 void wxMetalRenderer::DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
473 const wxPen
& pen1
, const wxPen
& pen2
)
475 // draw the rectangle
477 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
478 rect
->GetLeft(), rect
->GetBottom());
479 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
480 rect
->GetRight(), rect
->GetTop());
482 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
483 rect
->GetRight(), rect
->GetBottom());
484 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
485 rect
->GetRight() + 1, rect
->GetBottom());
491 void wxMetalRenderer::DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
)
495 DrawRect(dc
, rect
, m_penDarkGrey
);
497 // the arrow is usually drawn inside border of width 2 and is offset by
498 // another pixel in both directions when it's pressed - as the border
499 // in this case is more narrow as well, we have to adjust rect like
507 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penBlack
);
508 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
512 void wxMetalRenderer::DrawArrow(wxDC
& dc
,
514 wxArrowDirection arrowDir
,
515 wxArrowStyle arrowStyle
)
517 const wxBitmap
& bmp
= m_bmpArrows
[arrowStyle
][arrowDir
];
519 // under Windows the arrows always have the same size so just centre it in
520 // the provided rectangle
521 wxCoord x
= rect
.x
+ (rect
.width
- bmp
.GetWidth()) / 2,
522 y
= rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2;
524 // Windows does it like this...
525 if ( arrowDir
== Arrow_Left
)
529 dc
.DrawBitmap(bmp
, x
, y
, true /* use mask */);
532 // ----------------------------------------------------------------------------
534 // ----------------------------------------------------------------------------
536 void wxMetalRenderer::DrawMetal(wxDC
&dc
, const wxRect
&rect
)
538 dc
.SetPen(*wxTRANSPARENT_PEN
);
539 for (int y
= rect
.y
; y
< rect
.height
+rect
.y
; y
++)
541 unsigned char intens
= (unsigned char)(230 + 80 * (rect
.y
-y
) / rect
.height
);
542 dc
.SetBrush( wxBrush( wxColour(intens
,intens
,intens
), wxSOLID
) );
543 dc
.DrawRectangle( rect
.x
, y
, rect
.width
, 1 );
547 #endif // wxUSE_THEME_METAL