]> git.saurik.com Git - wxWidgets.git/blame - src/univ/themes/metal.cpp
Added wxRichTextTableBlock class to help with table UI operations
[wxWidgets.git] / src / univ / themes / metal.cpp
CommitLineData
3b3dc801
WS
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/univ/themes/metal.cpp
67d947ba
RR
3// Purpose: wxUniversal theme implementing Win32-like LNF
4// Author: Vadim Zeitlin, Robert Roebling
5// Modified by:
6// Created: 06.08.00
67d947ba 7// Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
65571936 8// Licence: wxWindows licence
67d947ba
RR
9///////////////////////////////////////////////////////////////////////////////
10
11// ===========================================================================
12// declarations
13// ===========================================================================
14
15// ---------------------------------------------------------------------------
16// headers
17// ---------------------------------------------------------------------------
18
19// For compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
e7637222
VS
26#include "wx/univ/theme.h"
27
28#if wxUSE_THEME_METAL
4353a8df 29
67d947ba
RR
30#ifndef WX_PRECOMP
31 #include "wx/timer.h"
32 #include "wx/intl.h"
33 #include "wx/dc.h"
34 #include "wx/window.h"
35
36 #include "wx/dcmemory.h"
37
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"
46
3b3dc801 47 #include "wx/menu.h"
9eddec69 48 #include "wx/settings.h"
1832043f 49 #include "wx/toplevel.h"
67d947ba
RR
50#endif // WX_PRECOMP
51
52#include "wx/notebook.h"
53#include "wx/spinbutt.h"
67d947ba 54#include "wx/artprov.h"
67d947ba
RR
55
56#include "wx/univ/scrtimer.h"
57#include "wx/univ/renderer.h"
9467bdb7 58#include "wx/univ/inpcons.h"
67d947ba
RR
59#include "wx/univ/inphand.h"
60#include "wx/univ/colschem.h"
67d947ba 61
eef1a0cc 62// ----------------------------------------------------------------------------
67d947ba
RR
63// wxMetalRenderer: draw the GUI elements in Metal style
64// ----------------------------------------------------------------------------
65
490da436 66class wxMetalRenderer : public wxDelegateRenderer
67d947ba 67{
490da436 68 // FIXME cut'n'paste from Win32
67d947ba
RR
69 enum wxArrowDirection
70 {
71 Arrow_Left,
72 Arrow_Right,
73 Arrow_Up,
74 Arrow_Down,
75 Arrow_Max
76 };
77
78 enum wxArrowStyle
79 {
80 Arrow_Normal,
81 Arrow_Disabled,
82 Arrow_Pressed,
d6922577
JS
83 Arrow_Inverted,
84 Arrow_InvertedDisabled,
67d947ba
RR
85 Arrow_StateMax
86 };
490da436
MB
87public:
88 wxMetalRenderer(wxRenderer *renderer, wxColourScheme* scheme);
67d947ba 89
193e19cf 90 virtual void DrawButtonSurface(wxDC& dc,
61fef19b 91 const wxColour& WXUNUSED(col),
490da436 92 const wxRect& rect,
61fef19b
VZ
93 int WXUNUSED(flags))
94 { DrawMetal(dc, rect); }
490da436 95
67d947ba
RR
96 virtual void DrawScrollbarThumb(wxDC& dc,
97 wxOrientation orient,
98 const wxRect& rect,
490da436
MB
99 int flags);
100
67d947ba
RR
101 virtual void DrawScrollbarShaft(wxDC& dc,
102 wxOrientation orient,
490da436
MB
103 const wxRect& rectBar,
104 int flags);
67d947ba
RR
105
106 virtual void GetComboBitmaps(wxBitmap *bmpNormal,
107 wxBitmap *bmpFocus,
108 wxBitmap *bmpPressed,
109 wxBitmap *bmpDisabled);
110
490da436
MB
111 virtual void DrawArrow(wxDC& dc,
112 wxDirection dir,
113 const wxRect& rect,
114 int flags = 0);
67d947ba 115protected:
490da436
MB
116 void DrawArrowButton(wxDC& dc,
117 const wxRect& rectAll,
118 wxArrowDirection arrowDir,
119 wxArrowStyle arrowStyle);
67d947ba 120
67d947ba
RR
121 void DrawRect(wxDC& dc, wxRect *rect, const wxPen& pen);
122
67d947ba
RR
123 void DrawShadedRect(wxDC& dc, wxRect *rect,
124 const wxPen& pen1, const wxPen& pen2);
125
a290fa5a 126 void DrawArrowBorder(wxDC& dc, wxRect *rect, bool isPressed = false);
67d947ba 127
67d947ba
RR
128 void DrawArrow(wxDC& dc, const wxRect& rect,
129 wxArrowDirection arrowDir, wxArrowStyle arrowStyle);
130
490da436 131 void DrawMetal(wxDC &dc, const wxRect &rect );
67d947ba 132private:
67d947ba
RR
133 wxPen m_penBlack,
134 m_penDarkGrey,
135 m_penLightGrey,
136 m_penHighlight;
137
67d947ba
RR
138 wxBitmap m_bmpArrows[Arrow_StateMax][Arrow_Max];
139};
140
67d947ba
RR
141// ----------------------------------------------------------------------------
142// wxMetalTheme
143// ----------------------------------------------------------------------------
144
eef1a0cc 145class wxMetalTheme : public wxDelegateTheme
67d947ba
RR
146{
147public:
9a83f860 148 wxMetalTheme() : wxDelegateTheme(wxT("win32")), m_renderer(NULL) {}
eef1a0cc 149 ~wxMetalTheme() { delete m_renderer; }
9467bdb7 150
eef1a0cc
VS
151protected:
152 virtual wxRenderer *GetRenderer()
490da436 153 {
eef1a0cc
VS
154 if ( !m_renderer )
155 {
156 m_renderer = new wxMetalRenderer(m_theme->GetRenderer(),
157 GetColourScheme());
158 }
159
160 return m_renderer;
490da436 161 }
9467bdb7 162
eef1a0cc 163 wxRenderer *m_renderer;
32b13913 164
67d947ba
RR
165 WX_DECLARE_THEME(Metal)
166};
167
67d947ba
RR
168WX_IMPLEMENT_THEME(wxMetalTheme, Metal, wxTRANSLATE("Metal theme"));
169
67d947ba 170
eef1a0cc
VS
171// ============================================================================
172// implementation
173// ============================================================================
67d947ba 174
490da436
MB
175// ----------------------------------------------------------------------------
176// wxMetalRenderer
177// ----------------------------------------------------------------------------
67d947ba 178
490da436 179wxMetalRenderer::wxMetalRenderer(wxRenderer *renderer, wxColourScheme *scheme)
9467bdb7 180 : wxDelegateRenderer(renderer)
67d947ba 181{
67d947ba
RR
182 // init colours and pens
183 m_penBlack = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_DARK), 0, wxSOLID);
490da436 184 m_penDarkGrey = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_OUT), 0, wxSOLID);
67d947ba 185 m_penLightGrey = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_IN), 0, wxSOLID);
490da436 186 m_penHighlight = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_HIGHLIGHT), 0, wxSOLID);
67d947ba
RR
187
188 // init the arrow bitmaps
189 static const size_t ARROW_WIDTH = 7;
190 static const size_t ARROW_LENGTH = 4;
191
192 wxMask *mask;
193 wxMemoryDC dcNormal,
194 dcDisabled,
195 dcInverse;
196 for ( size_t n = 0; n < Arrow_Max; n++ )
197 {
198 bool isVertical = n > Arrow_Right;
199 int w, h;
200 if ( isVertical )
201 {
202 w = ARROW_WIDTH;
203 h = ARROW_LENGTH;
204 }
205 else
206 {
207 h = ARROW_WIDTH;
208 w = ARROW_LENGTH;
209 }
210
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);
214
215 dcNormal.SelectObject(m_bmpArrows[Arrow_Normal][n]);
216 dcDisabled.SelectObject(m_bmpArrows[Arrow_Disabled][n]);
217
218 dcNormal.SetBackground(*wxWHITE_BRUSH);
219 dcDisabled.SetBackground(*wxWHITE_BRUSH);
220 dcNormal.Clear();
221 dcDisabled.Clear();
222
223 dcNormal.SetPen(m_penBlack);
224 dcDisabled.SetPen(m_penDarkGrey);
225
226 // calculate the position of the point of the arrow
227 wxCoord x1, y1;
228 if ( isVertical )
229 {
230 x1 = (ARROW_WIDTH - 1)/2;
231 y1 = n == Arrow_Up ? 0 : ARROW_LENGTH - 1;
232 }
233 else // horizontal
234 {
235 x1 = n == Arrow_Left ? 0 : ARROW_LENGTH - 1;
236 y1 = (ARROW_WIDTH - 1)/2;
237 }
238
239 wxCoord x2 = x1,
240 y2 = y1;
241
242 if ( isVertical )
243 x2++;
244 else
245 y2++;
246
247 for ( size_t i = 0; i < ARROW_LENGTH; i++ )
248 {
249 dcNormal.DrawLine(x1, y1, x2, y2);
250 dcDisabled.DrawLine(x1, y1, x2, y2);
251
252 if ( isVertical )
253 {
254 x1--;
255 x2++;
256
257 if ( n == Arrow_Up )
258 {
259 y1++;
260 y2++;
261 }
262 else // down arrow
263 {
264 y1--;
265 y2--;
266 }
267 }
268 else // left or right arrow
269 {
270 y1--;
271 y2++;
272
273 if ( n == Arrow_Left )
274 {
275 x1++;
276 x2++;
277 }
278 else
279 {
280 x1--;
281 x2--;
282 }
283 }
284 }
285
286 // draw the shadow for the disabled one
287 dcDisabled.SetPen(m_penHighlight);
288 switch ( n )
289 {
290 case Arrow_Left:
291 y1 += 2;
292 dcDisabled.DrawLine(x1, y1, x2, y2);
293 break;
294
295 case Arrow_Right:
296 x1 = ARROW_LENGTH - 1;
297 y1 = (ARROW_WIDTH - 1)/2 + 1;
298 x2 = 0;
299 y2 = ARROW_WIDTH;
300 dcDisabled.DrawLine(x1, y1, x2, y2);
301 dcDisabled.DrawLine(++x1, y1, x2, ++y2);
302 break;
303
304 case Arrow_Up:
305 x1 += 2;
306 dcDisabled.DrawLine(x1, y1, x2, y2);
307 break;
308
309 case Arrow_Down:
310 x1 = ARROW_WIDTH - 1;
311 y1 = 1;
312 x2 = (ARROW_WIDTH - 1)/2;
313 y2 = ARROW_LENGTH;
314 dcDisabled.DrawLine(x1, y1, x2, y2);
315 dcDisabled.DrawLine(++x1, y1, x2, ++y2);
316 break;
317
318 }
319
d6922577 320 // create the inverted bitmap but only for the right arrow as we only
67d947ba
RR
321 // use it for the menus
322 if ( n == Arrow_Right )
323 {
d6922577
JS
324 m_bmpArrows[Arrow_Inverted][n].Create(w, h);
325 dcInverse.SelectObject(m_bmpArrows[Arrow_Inverted][n]);
67d947ba
RR
326 dcInverse.Clear();
327 dcInverse.Blit(0, 0, w, h,
328 &dcNormal, 0, 0,
329 wxXOR);
330 dcInverse.SelectObject(wxNullBitmap);
331
d6922577
JS
332 mask = new wxMask(m_bmpArrows[Arrow_Inverted][n], *wxBLACK);
333 m_bmpArrows[Arrow_Inverted][n].SetMask(mask);
67d947ba 334
d6922577
JS
335 m_bmpArrows[Arrow_InvertedDisabled][n].Create(w, h);
336 dcInverse.SelectObject(m_bmpArrows[Arrow_InvertedDisabled][n]);
67d947ba
RR
337 dcInverse.Clear();
338 dcInverse.Blit(0, 0, w, h,
339 &dcDisabled, 0, 0,
340 wxXOR);
341 dcInverse.SelectObject(wxNullBitmap);
342
d6922577
JS
343 mask = new wxMask(m_bmpArrows[Arrow_InvertedDisabled][n], *wxBLACK);
344 m_bmpArrows[Arrow_InvertedDisabled][n].SetMask(mask);
67d947ba
RR
345 }
346
347 dcNormal.SelectObject(wxNullBitmap);
348 dcDisabled.SelectObject(wxNullBitmap);
349
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);
354
355 m_bmpArrows[Arrow_Pressed][n] = m_bmpArrows[Arrow_Normal][n];
356 }
490da436
MB
357}
358
359void wxMetalRenderer::DrawScrollbarThumb(wxDC& dc,
61fef19b 360 wxOrientation WXUNUSED(orient),
490da436 361 const wxRect& rect,
61fef19b 362 int WXUNUSED(flags))
490da436
MB
363{
364 // we don't use the flags, the thumb never changes appearance
365 wxRect rectThumb = rect;
366 DrawArrowBorder(dc, &rectThumb);
367 DrawMetal(dc, rectThumb);
368}
67d947ba 369
490da436 370void wxMetalRenderer::DrawScrollbarShaft(wxDC& dc,
61fef19b 371 wxOrientation WXUNUSED(orient),
490da436 372 const wxRect& rectBar,
61fef19b 373 int WXUNUSED(flags))
490da436 374{
61fef19b 375 DrawMetal(dc, rectBar);
67d947ba
RR
376}
377
490da436 378void wxMetalRenderer::GetComboBitmaps(wxBitmap *bmpNormal,
61fef19b 379 wxBitmap * WXUNUSED(bmpFocus),
490da436
MB
380 wxBitmap *bmpPressed,
381 wxBitmap *bmpDisabled)
382{
383 static const wxCoord widthCombo = 16;
384 static const wxCoord heightCombo = 17;
67d947ba 385
490da436 386 wxMemoryDC dcMem;
67d947ba 387
490da436
MB
388 if ( bmpNormal )
389 {
390 bmpNormal->Create(widthCombo, heightCombo);
391 dcMem.SelectObject(*bmpNormal);
392 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
393 Arrow_Down, Arrow_Normal);
394 }
67d947ba 395
490da436
MB
396 if ( bmpPressed )
397 {
398 bmpPressed->Create(widthCombo, heightCombo);
399 dcMem.SelectObject(*bmpPressed);
400 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
401 Arrow_Down, Arrow_Pressed);
402 }
67d947ba 403
490da436
MB
404 if ( bmpDisabled )
405 {
406 bmpDisabled->Create(widthCombo, heightCombo);
407 dcMem.SelectObject(*bmpDisabled);
408 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
409 Arrow_Down, Arrow_Disabled);
410 }
411}
67d947ba 412
490da436
MB
413void wxMetalRenderer::DrawArrow(wxDC& dc,
414 wxDirection dir,
415 const wxRect& rect,
416 int flags)
417{
418 // get the bitmap for this arrow
419 wxArrowDirection arrowDir;
420 switch ( dir )
421 {
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;
67d947ba 426
490da436 427 default:
9a83f860 428 wxFAIL_MSG(wxT("unknown arrow direction"));
490da436
MB
429 return;
430 }
67d947ba 431
490da436
MB
432 wxArrowStyle arrowStyle;
433 if ( flags & wxCONTROL_PRESSED )
434 {
435 // can't be pressed and disabled
436 arrowStyle = Arrow_Pressed;
437 }
438 else
439 {
440 arrowStyle = flags & wxCONTROL_DISABLED ? Arrow_Disabled : Arrow_Normal;
441 }
67d947ba 442
490da436
MB
443 DrawArrowButton(dc, rect, arrowDir, arrowStyle);
444}
67d947ba 445
490da436
MB
446//
447// protected functions
448//
67d947ba 449
490da436
MB
450void wxMetalRenderer::DrawArrowButton(wxDC& dc,
451 const wxRect& rectAll,
452 wxArrowDirection arrowDir,
453 wxArrowStyle arrowStyle)
454{
455 wxRect rect = rectAll;
456 DrawMetal( dc, rect );
457 DrawArrowBorder(dc, &rect, arrowStyle == Arrow_Pressed);
458 DrawArrow(dc, rect, arrowDir, arrowStyle);
459}
67d947ba
RR
460
461void wxMetalRenderer::DrawRect(wxDC& dc, wxRect *rect, const wxPen& pen)
462{
463 // draw
464 dc.SetPen(pen);
465 dc.SetBrush(*wxTRANSPARENT_BRUSH);
466 dc.DrawRectangle(*rect);
467
468 // adjust the rect
469 rect->Inflate(-1);
470}
471
67d947ba
RR
472void wxMetalRenderer::DrawShadedRect(wxDC& dc, wxRect *rect,
473 const wxPen& pen1, const wxPen& pen2)
474{
475 // draw the rectangle
476 dc.SetPen(pen1);
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());
481 dc.SetPen(pen2);
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());
486
487 // adjust the rect
488 rect->Inflate(-1);
489}
490
67d947ba
RR
491void wxMetalRenderer::DrawArrowBorder(wxDC& dc, wxRect *rect, bool isPressed)
492{
493 if ( isPressed )
494 {
495 DrawRect(dc, rect, m_penDarkGrey);
496
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
500 // this:
501 rect->Inflate(-1);
502 rect->x++;
503 rect->y++;
504 }
505 else
506 {
507 DrawShadedRect(dc, rect, m_penLightGrey, m_penBlack);
508 DrawShadedRect(dc, rect, m_penHighlight, m_penDarkGrey);
509 }
510}
511
490da436
MB
512void wxMetalRenderer::DrawArrow(wxDC& dc,
513 const wxRect& rect,
514 wxArrowDirection arrowDir,
515 wxArrowStyle arrowStyle)
67d947ba 516{
490da436 517 const wxBitmap& bmp = m_bmpArrows[arrowStyle][arrowDir];
67d947ba 518
490da436
MB
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;
67d947ba 523
490da436
MB
524 // Windows does it like this...
525 if ( arrowDir == Arrow_Left )
526 x--;
67d947ba 527
490da436 528 // draw it
a290fa5a 529 dc.DrawBitmap(bmp, x, y, true /* use mask */);
67d947ba
RR
530}
531
532// ----------------------------------------------------------------------------
490da436 533// metal gradient
67d947ba
RR
534// ----------------------------------------------------------------------------
535
490da436 536void wxMetalRenderer::DrawMetal(wxDC &dc, const wxRect &rect )
67d947ba 537{
490da436
MB
538 dc.SetPen(*wxTRANSPARENT_PEN);
539 for (int y = rect.y; y < rect.height+rect.y; y++)
67d947ba 540 {
32b13913 541 unsigned char intens = (unsigned char)(230 + 80 * (rect.y-y) / rect.height);
490da436
MB
542 dc.SetBrush( wxBrush( wxColour(intens,intens,intens), wxSOLID ) );
543 dc.DrawRectangle( rect.x, y, rect.width, 1 );
67d947ba
RR
544 }
545}
4353a8df 546
e7637222 547#endif // wxUSE_THEME_METAL