]> git.saurik.com Git - wxWidgets.git/blame - src/univ/themes/metal.cpp
call gtk_toolbar_set_tooltips() from GtkSetStyle(); removed erroneous wxTB_TOOLTIPS
[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
7// RCS-ID: $Id$
8// Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
65571936 9// Licence: wxWindows licence
67d947ba
RR
10///////////////////////////////////////////////////////////////////////////////
11
12// ===========================================================================
13// declarations
14// ===========================================================================
15
16// ---------------------------------------------------------------------------
17// headers
18// ---------------------------------------------------------------------------
19
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#ifndef WX_PRECOMP
28 #include "wx/timer.h"
29 #include "wx/intl.h"
30 #include "wx/dc.h"
31 #include "wx/window.h"
32
33 #include "wx/dcmemory.h"
34
35 #include "wx/button.h"
36 #include "wx/listbox.h"
37 #include "wx/checklst.h"
38 #include "wx/combobox.h"
39 #include "wx/scrolbar.h"
40 #include "wx/slider.h"
41 #include "wx/textctrl.h"
42 #include "wx/toolbar.h"
43
44 #ifdef __WXMSW__
45 // for COLOR_* constants
46 #include "wx/msw/private.h"
47 #endif
3b3dc801 48 #include "wx/menu.h"
9eddec69 49 #include "wx/settings.h"
67d947ba
RR
50#endif // WX_PRECOMP
51
52#include "wx/notebook.h"
53#include "wx/spinbutt.h"
67d947ba
RR
54#include "wx/artprov.h"
55#include "wx/toplevel.h"
56
57#include "wx/univ/scrtimer.h"
58#include "wx/univ/renderer.h"
59#include "wx/univ/inphand.h"
60#include "wx/univ/colschem.h"
61#include "wx/univ/theme.h"
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
d5d29b8a 145WX_DEFINE_ARRAY_PTR(wxInputHandler *, wxArrayHandlers);
67d947ba
RR
146
147class wxMetalTheme : public wxTheme
148{
149public:
150 wxMetalTheme();
151 virtual ~wxMetalTheme();
152
153 virtual wxRenderer *GetRenderer();
154 virtual wxArtProvider *GetArtProvider();
155 virtual wxInputHandler *GetInputHandler(const wxString& control);
156 virtual wxColourScheme *GetColourScheme();
67d947ba 157private:
490da436
MB
158 bool GetOrCreateTheme()
159 {
160 if ( !m_win32Theme )
2b5f62a0 161 m_win32Theme = wxTheme::Create( wxT("win32") );
36633c5c 162 return m_win32Theme != NULL;
490da436
MB
163 }
164private:
165 wxTheme *m_win32Theme;
67d947ba 166 wxMetalRenderer *m_renderer;
32b13913 167
67d947ba
RR
168 WX_DECLARE_THEME(Metal)
169};
170
67d947ba
RR
171// ============================================================================
172// implementation
173// ============================================================================
174
175WX_IMPLEMENT_THEME(wxMetalTheme, Metal, wxTRANSLATE("Metal theme"));
176
177// ----------------------------------------------------------------------------
178// wxMetalTheme
179// ----------------------------------------------------------------------------
180
181wxMetalTheme::wxMetalTheme()
182{
490da436 183 m_win32Theme = NULL;
67d947ba 184 m_renderer = NULL;
67d947ba
RR
185}
186
187wxMetalTheme::~wxMetalTheme()
188{
490da436 189 delete m_win32Theme;
67d947ba 190 delete m_renderer;
67d947ba
RR
191}
192
193wxRenderer *wxMetalTheme::GetRenderer()
194{
490da436
MB
195 if ( !GetOrCreateTheme() )
196 return 0;
67d947ba 197 if ( !m_renderer )
490da436
MB
198 m_renderer = new wxMetalRenderer(m_win32Theme->GetRenderer(),
199 m_win32Theme->GetColourScheme());
67d947ba
RR
200
201 return m_renderer;
202}
203
204wxArtProvider *wxMetalTheme::GetArtProvider()
205{
490da436
MB
206 if ( !GetOrCreateTheme() )
207 return 0;
208 return m_win32Theme->GetArtProvider();
67d947ba
RR
209}
210
211wxInputHandler *wxMetalTheme::GetInputHandler(const wxString& control)
212{
490da436
MB
213 if ( !GetOrCreateTheme() )
214 return 0;
215 return m_win32Theme->GetInputHandler(control);
67d947ba
RR
216}
217
218wxColourScheme *wxMetalTheme::GetColourScheme()
219{
490da436
MB
220 if ( !GetOrCreateTheme() )
221 return 0;
222 return m_win32Theme->GetColourScheme();
67d947ba
RR
223}
224
490da436
MB
225// ----------------------------------------------------------------------------
226// wxMetalRenderer
227// ----------------------------------------------------------------------------
67d947ba 228
490da436
MB
229wxMetalRenderer::wxMetalRenderer(wxRenderer *renderer, wxColourScheme *scheme)
230 : wxDelegateRenderer(renderer)
67d947ba 231{
67d947ba
RR
232 // init colours and pens
233 m_penBlack = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_DARK), 0, wxSOLID);
490da436 234 m_penDarkGrey = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_OUT), 0, wxSOLID);
67d947ba 235 m_penLightGrey = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_IN), 0, wxSOLID);
490da436 236 m_penHighlight = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_HIGHLIGHT), 0, wxSOLID);
67d947ba
RR
237
238 // init the arrow bitmaps
239 static const size_t ARROW_WIDTH = 7;
240 static const size_t ARROW_LENGTH = 4;
241
242 wxMask *mask;
243 wxMemoryDC dcNormal,
244 dcDisabled,
245 dcInverse;
246 for ( size_t n = 0; n < Arrow_Max; n++ )
247 {
248 bool isVertical = n > Arrow_Right;
249 int w, h;
250 if ( isVertical )
251 {
252 w = ARROW_WIDTH;
253 h = ARROW_LENGTH;
254 }
255 else
256 {
257 h = ARROW_WIDTH;
258 w = ARROW_LENGTH;
259 }
260
261 // disabled arrow is larger because of the shadow
262 m_bmpArrows[Arrow_Normal][n].Create(w, h);
263 m_bmpArrows[Arrow_Disabled][n].Create(w + 1, h + 1);
264
265 dcNormal.SelectObject(m_bmpArrows[Arrow_Normal][n]);
266 dcDisabled.SelectObject(m_bmpArrows[Arrow_Disabled][n]);
267
268 dcNormal.SetBackground(*wxWHITE_BRUSH);
269 dcDisabled.SetBackground(*wxWHITE_BRUSH);
270 dcNormal.Clear();
271 dcDisabled.Clear();
272
273 dcNormal.SetPen(m_penBlack);
274 dcDisabled.SetPen(m_penDarkGrey);
275
276 // calculate the position of the point of the arrow
277 wxCoord x1, y1;
278 if ( isVertical )
279 {
280 x1 = (ARROW_WIDTH - 1)/2;
281 y1 = n == Arrow_Up ? 0 : ARROW_LENGTH - 1;
282 }
283 else // horizontal
284 {
285 x1 = n == Arrow_Left ? 0 : ARROW_LENGTH - 1;
286 y1 = (ARROW_WIDTH - 1)/2;
287 }
288
289 wxCoord x2 = x1,
290 y2 = y1;
291
292 if ( isVertical )
293 x2++;
294 else
295 y2++;
296
297 for ( size_t i = 0; i < ARROW_LENGTH; i++ )
298 {
299 dcNormal.DrawLine(x1, y1, x2, y2);
300 dcDisabled.DrawLine(x1, y1, x2, y2);
301
302 if ( isVertical )
303 {
304 x1--;
305 x2++;
306
307 if ( n == Arrow_Up )
308 {
309 y1++;
310 y2++;
311 }
312 else // down arrow
313 {
314 y1--;
315 y2--;
316 }
317 }
318 else // left or right arrow
319 {
320 y1--;
321 y2++;
322
323 if ( n == Arrow_Left )
324 {
325 x1++;
326 x2++;
327 }
328 else
329 {
330 x1--;
331 x2--;
332 }
333 }
334 }
335
336 // draw the shadow for the disabled one
337 dcDisabled.SetPen(m_penHighlight);
338 switch ( n )
339 {
340 case Arrow_Left:
341 y1 += 2;
342 dcDisabled.DrawLine(x1, y1, x2, y2);
343 break;
344
345 case Arrow_Right:
346 x1 = ARROW_LENGTH - 1;
347 y1 = (ARROW_WIDTH - 1)/2 + 1;
348 x2 = 0;
349 y2 = ARROW_WIDTH;
350 dcDisabled.DrawLine(x1, y1, x2, y2);
351 dcDisabled.DrawLine(++x1, y1, x2, ++y2);
352 break;
353
354 case Arrow_Up:
355 x1 += 2;
356 dcDisabled.DrawLine(x1, y1, x2, y2);
357 break;
358
359 case Arrow_Down:
360 x1 = ARROW_WIDTH - 1;
361 y1 = 1;
362 x2 = (ARROW_WIDTH - 1)/2;
363 y2 = ARROW_LENGTH;
364 dcDisabled.DrawLine(x1, y1, x2, y2);
365 dcDisabled.DrawLine(++x1, y1, x2, ++y2);
366 break;
367
368 }
369
d6922577 370 // create the inverted bitmap but only for the right arrow as we only
67d947ba
RR
371 // use it for the menus
372 if ( n == Arrow_Right )
373 {
d6922577
JS
374 m_bmpArrows[Arrow_Inverted][n].Create(w, h);
375 dcInverse.SelectObject(m_bmpArrows[Arrow_Inverted][n]);
67d947ba
RR
376 dcInverse.Clear();
377 dcInverse.Blit(0, 0, w, h,
378 &dcNormal, 0, 0,
379 wxXOR);
380 dcInverse.SelectObject(wxNullBitmap);
381
d6922577
JS
382 mask = new wxMask(m_bmpArrows[Arrow_Inverted][n], *wxBLACK);
383 m_bmpArrows[Arrow_Inverted][n].SetMask(mask);
67d947ba 384
d6922577
JS
385 m_bmpArrows[Arrow_InvertedDisabled][n].Create(w, h);
386 dcInverse.SelectObject(m_bmpArrows[Arrow_InvertedDisabled][n]);
67d947ba
RR
387 dcInverse.Clear();
388 dcInverse.Blit(0, 0, w, h,
389 &dcDisabled, 0, 0,
390 wxXOR);
391 dcInverse.SelectObject(wxNullBitmap);
392
d6922577
JS
393 mask = new wxMask(m_bmpArrows[Arrow_InvertedDisabled][n], *wxBLACK);
394 m_bmpArrows[Arrow_InvertedDisabled][n].SetMask(mask);
67d947ba
RR
395 }
396
397 dcNormal.SelectObject(wxNullBitmap);
398 dcDisabled.SelectObject(wxNullBitmap);
399
400 mask = new wxMask(m_bmpArrows[Arrow_Normal][n], *wxWHITE);
401 m_bmpArrows[Arrow_Normal][n].SetMask(mask);
402 mask = new wxMask(m_bmpArrows[Arrow_Disabled][n], *wxWHITE);
403 m_bmpArrows[Arrow_Disabled][n].SetMask(mask);
404
405 m_bmpArrows[Arrow_Pressed][n] = m_bmpArrows[Arrow_Normal][n];
406 }
490da436
MB
407}
408
409void wxMetalRenderer::DrawScrollbarThumb(wxDC& dc,
61fef19b 410 wxOrientation WXUNUSED(orient),
490da436 411 const wxRect& rect,
61fef19b 412 int WXUNUSED(flags))
490da436
MB
413{
414 // we don't use the flags, the thumb never changes appearance
415 wxRect rectThumb = rect;
416 DrawArrowBorder(dc, &rectThumb);
417 DrawMetal(dc, rectThumb);
418}
67d947ba 419
490da436 420void wxMetalRenderer::DrawScrollbarShaft(wxDC& dc,
61fef19b 421 wxOrientation WXUNUSED(orient),
490da436 422 const wxRect& rectBar,
61fef19b 423 int WXUNUSED(flags))
490da436 424{
61fef19b 425 DrawMetal(dc, rectBar);
67d947ba
RR
426}
427
490da436 428void wxMetalRenderer::GetComboBitmaps(wxBitmap *bmpNormal,
61fef19b 429 wxBitmap * WXUNUSED(bmpFocus),
490da436
MB
430 wxBitmap *bmpPressed,
431 wxBitmap *bmpDisabled)
432{
433 static const wxCoord widthCombo = 16;
434 static const wxCoord heightCombo = 17;
67d947ba 435
490da436 436 wxMemoryDC dcMem;
67d947ba 437
490da436
MB
438 if ( bmpNormal )
439 {
440 bmpNormal->Create(widthCombo, heightCombo);
441 dcMem.SelectObject(*bmpNormal);
442 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
443 Arrow_Down, Arrow_Normal);
444 }
67d947ba 445
490da436
MB
446 if ( bmpPressed )
447 {
448 bmpPressed->Create(widthCombo, heightCombo);
449 dcMem.SelectObject(*bmpPressed);
450 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
451 Arrow_Down, Arrow_Pressed);
452 }
67d947ba 453
490da436
MB
454 if ( bmpDisabled )
455 {
456 bmpDisabled->Create(widthCombo, heightCombo);
457 dcMem.SelectObject(*bmpDisabled);
458 DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
459 Arrow_Down, Arrow_Disabled);
460 }
461}
67d947ba 462
490da436
MB
463void wxMetalRenderer::DrawArrow(wxDC& dc,
464 wxDirection dir,
465 const wxRect& rect,
466 int flags)
467{
468 // get the bitmap for this arrow
469 wxArrowDirection arrowDir;
470 switch ( dir )
471 {
472 case wxLEFT: arrowDir = Arrow_Left; break;
473 case wxRIGHT: arrowDir = Arrow_Right; break;
474 case wxUP: arrowDir = Arrow_Up; break;
475 case wxDOWN: arrowDir = Arrow_Down; break;
67d947ba 476
490da436
MB
477 default:
478 wxFAIL_MSG(_T("unknown arrow direction"));
479 return;
480 }
67d947ba 481
490da436
MB
482 wxArrowStyle arrowStyle;
483 if ( flags & wxCONTROL_PRESSED )
484 {
485 // can't be pressed and disabled
486 arrowStyle = Arrow_Pressed;
487 }
488 else
489 {
490 arrowStyle = flags & wxCONTROL_DISABLED ? Arrow_Disabled : Arrow_Normal;
491 }
67d947ba 492
490da436
MB
493 DrawArrowButton(dc, rect, arrowDir, arrowStyle);
494}
67d947ba 495
490da436
MB
496//
497// protected functions
498//
67d947ba 499
490da436
MB
500void wxMetalRenderer::DrawArrowButton(wxDC& dc,
501 const wxRect& rectAll,
502 wxArrowDirection arrowDir,
503 wxArrowStyle arrowStyle)
504{
505 wxRect rect = rectAll;
506 DrawMetal( dc, rect );
507 DrawArrowBorder(dc, &rect, arrowStyle == Arrow_Pressed);
508 DrawArrow(dc, rect, arrowDir, arrowStyle);
509}
67d947ba
RR
510
511void wxMetalRenderer::DrawRect(wxDC& dc, wxRect *rect, const wxPen& pen)
512{
513 // draw
514 dc.SetPen(pen);
515 dc.SetBrush(*wxTRANSPARENT_BRUSH);
516 dc.DrawRectangle(*rect);
517
518 // adjust the rect
519 rect->Inflate(-1);
520}
521
67d947ba
RR
522void wxMetalRenderer::DrawShadedRect(wxDC& dc, wxRect *rect,
523 const wxPen& pen1, const wxPen& pen2)
524{
525 // draw the rectangle
526 dc.SetPen(pen1);
527 dc.DrawLine(rect->GetLeft(), rect->GetTop(),
528 rect->GetLeft(), rect->GetBottom());
529 dc.DrawLine(rect->GetLeft() + 1, rect->GetTop(),
530 rect->GetRight(), rect->GetTop());
531 dc.SetPen(pen2);
532 dc.DrawLine(rect->GetRight(), rect->GetTop(),
533 rect->GetRight(), rect->GetBottom());
534 dc.DrawLine(rect->GetLeft(), rect->GetBottom(),
535 rect->GetRight() + 1, rect->GetBottom());
536
537 // adjust the rect
538 rect->Inflate(-1);
539}
540
67d947ba
RR
541void wxMetalRenderer::DrawArrowBorder(wxDC& dc, wxRect *rect, bool isPressed)
542{
543 if ( isPressed )
544 {
545 DrawRect(dc, rect, m_penDarkGrey);
546
547 // the arrow is usually drawn inside border of width 2 and is offset by
548 // another pixel in both directions when it's pressed - as the border
549 // in this case is more narrow as well, we have to adjust rect like
550 // this:
551 rect->Inflate(-1);
552 rect->x++;
553 rect->y++;
554 }
555 else
556 {
557 DrawShadedRect(dc, rect, m_penLightGrey, m_penBlack);
558 DrawShadedRect(dc, rect, m_penHighlight, m_penDarkGrey);
559 }
560}
561
490da436
MB
562void wxMetalRenderer::DrawArrow(wxDC& dc,
563 const wxRect& rect,
564 wxArrowDirection arrowDir,
565 wxArrowStyle arrowStyle)
67d947ba 566{
490da436 567 const wxBitmap& bmp = m_bmpArrows[arrowStyle][arrowDir];
67d947ba 568
490da436
MB
569 // under Windows the arrows always have the same size so just centre it in
570 // the provided rectangle
571 wxCoord x = rect.x + (rect.width - bmp.GetWidth()) / 2,
572 y = rect.y + (rect.height - bmp.GetHeight()) / 2;
67d947ba 573
490da436
MB
574 // Windows does it like this...
575 if ( arrowDir == Arrow_Left )
576 x--;
67d947ba 577
490da436 578 // draw it
a290fa5a 579 dc.DrawBitmap(bmp, x, y, true /* use mask */);
67d947ba
RR
580}
581
582// ----------------------------------------------------------------------------
490da436 583// metal gradient
67d947ba
RR
584// ----------------------------------------------------------------------------
585
490da436 586void wxMetalRenderer::DrawMetal(wxDC &dc, const wxRect &rect )
67d947ba 587{
490da436
MB
588 dc.SetPen(*wxTRANSPARENT_PEN);
589 for (int y = rect.y; y < rect.height+rect.y; y++)
67d947ba 590 {
32b13913 591 unsigned char intens = (unsigned char)(230 + 80 * (rect.y-y) / rect.height);
490da436
MB
592 dc.SetBrush( wxBrush( wxColour(intens,intens,intens), wxSOLID ) );
593 dc.DrawRectangle( rect.x, y, rect.width, 1 );
67d947ba
RR
594 }
595}