]> git.saurik.com Git - wxWidgets.git/blame - src/univ/themes/gtk.cpp
[ 1505048 ] wxHtml rendering of underlined text
[wxWidgets.git] / src / univ / themes / gtk.cpp
CommitLineData
1e6feb95 1///////////////////////////////////////////////////////////////////////////////
370efbe7 2// Name: src/univ/themes/gtk.cpp
1e6feb95
VZ
3// Purpose: wxUniversal theme implementing GTK-like LNF
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 06.08.00
7// RCS-ID: $Id$
442b35b5 8// Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
65571936 9// Licence: wxWindows licence
1e6feb95
VZ
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/intl.h"
29 #include "wx/log.h"
30 #include "wx/dcmemory.h"
31 #include "wx/window.h"
32
0fe5e8fe
VZ
33 #include "wx/menu.h"
34
e4606ed9 35 #include "wx/bmpbuttn.h"
1e6feb95
VZ
36 #include "wx/button.h"
37 #include "wx/checkbox.h"
38 #include "wx/listbox.h"
39 #include "wx/checklst.h"
8cb172b4 40 #include "wx/combobox.h"
1e6feb95
VZ
41 #include "wx/scrolbar.h"
42 #include "wx/slider.h"
43 #include "wx/textctrl.h"
3216dbf5 44 #include "wx/toolbar.h"
c2919ab3 45 #include "wx/statusbr.h"
0fe5e8fe
VZ
46
47 #include "wx/settings.h"
1832043f 48 #include "wx/toplevel.h"
155ecd4c 49 #include "wx/image.h"
1e6feb95
VZ
50#endif // WX_PRECOMP
51
52#include "wx/notebook.h"
53#include "wx/spinbutt.h"
536b70ac 54#include "wx/artprov.h"
43be3c33
JS
55#ifdef wxUSE_TOGGLEBTN
56#include "wx/tglbtn.h"
57#endif // wxUSE_TOGGLEBTN
1e6feb95 58
147b8a4a 59#include "wx/univ/stdrend.h"
9467bdb7 60#include "wx/univ/inpcons.h"
1e6feb95
VZ
61#include "wx/univ/inphand.h"
62#include "wx/univ/colschem.h"
63#include "wx/univ/theme.h"
64
0fe5e8fe
VZ
65class WXDLLEXPORT wxGTKMenuGeometryInfo;
66
1e6feb95 67// ----------------------------------------------------------------------------
147b8a4a 68// constants
1e6feb95
VZ
69// ----------------------------------------------------------------------------
70
147b8a4a
VZ
71// standard border size
72static const int BORDER_THICKNESS = 2;
1e6feb95
VZ
73
74// ----------------------------------------------------------------------------
75// wxGTKRenderer: draw the GUI elements in GTK style
76// ----------------------------------------------------------------------------
77
147b8a4a 78class wxGTKRenderer : public wxStdRenderer
1e6feb95
VZ
79{
80public:
81 wxGTKRenderer(const wxColourScheme *scheme);
82
147b8a4a
VZ
83 // wxRenderer methods
84 virtual void DrawFocusRect(wxDC& dc, const wxRect& rect);
85 virtual void DrawTextBorder(wxDC& dc,
86 wxBorder border,
1e6feb95 87 const wxRect& rect,
193e19cf 88 int flags = 0,
147b8a4a 89 wxRect *rectIn = NULL);
1e6feb95
VZ
90 virtual void DrawButtonLabel(wxDC& dc,
91 const wxString& label,
92 const wxBitmap& image,
93 const wxRect& rect,
147b8a4a
VZ
94 int flags,
95 int alignment,
96 int indexAccel,
97 wxRect *rectBounds);
1e6feb95
VZ
98 virtual void DrawButtonBorder(wxDC& dc,
99 const wxRect& rect,
100 int flags = 0,
147b8a4a 101 wxRect *rectIn = NULL);
1e6feb95
VZ
102 virtual void DrawArrow(wxDC& dc,
103 wxDirection dir,
104 const wxRect& rect,
105 int flags = 0);
106 virtual void DrawScrollbarArrow(wxDC& dc,
107 wxDirection dir,
108 const wxRect& rect,
109 int flags = 0);
110 virtual void DrawScrollbarThumb(wxDC& dc,
111 wxOrientation orient,
112 const wxRect& rect,
113 int flags = 0);
114 virtual void DrawScrollbarShaft(wxDC& dc,
115 wxOrientation orient,
116 const wxRect& rect,
117 int flags = 0);
118 virtual void DrawScrollCorner(wxDC& dc,
119 const wxRect& rect);
1e6feb95
VZ
120 virtual void DrawCheckItem(wxDC& dc,
121 const wxString& label,
122 const wxBitmap& bitmap,
123 const wxRect& rect,
124 int flags = 0);
1e6feb95 125
9a6384ca 126#if wxUSE_TOOLBAR
3216dbf5
VZ
127 virtual void DrawToolBarButton(wxDC& dc,
128 const wxString& label,
129 const wxBitmap& bitmap,
130 const wxRect& rect,
a8f4cabe 131 int flags = 0,
370efbe7
WS
132 long style = 0,
133 int tbarStyle = 0);
9a6384ca 134#endif // wxUSE_TOOLBAR
3216dbf5 135
147b8a4a 136#if wxUSE_TEXTCTRL
1e6feb95 137 virtual void DrawLineWrapMark(wxDC& dc, const wxRect& rect);
147b8a4a
VZ
138#endif // wxUSE_TEXTCTRL
139
c4036939 140#if wxUSE_NOTEBOOK
1e6feb95
VZ
141 virtual void DrawTab(wxDC& dc,
142 const wxRect& rect,
143 wxDirection dir,
144 const wxString& label,
145 const wxBitmap& bitmap = wxNullBitmap,
146 int flags = 0,
147 int indexAccel = -1);
c4036939 148#endif // wxUSE_NOTEBOOK
1e6feb95 149
9a6384ca 150#if wxUSE_SLIDER
1e6feb95
VZ
151 virtual void DrawSliderShaft(wxDC& dc,
152 const wxRect& rect,
6766e5d1 153 int lenThumb,
1e6feb95
VZ
154 wxOrientation orient,
155 int flags = 0,
6766e5d1 156 long style = 0,
1e6feb95
VZ
157 wxRect *rectShaft = NULL);
158 virtual void DrawSliderThumb(wxDC& dc,
159 const wxRect& rect,
160 wxOrientation orient,
6766e5d1
JS
161 int flags = 0,
162 long style = 0);
61fef19b
VZ
163 virtual void DrawSliderTicks(wxDC& WXUNUSED(dc),
164 const wxRect& WXUNUSED(rect),
165 int WXUNUSED(lenThumb),
166 wxOrientation WXUNUSED(orient),
167 int WXUNUSED(start),
168 int WXUNUSED(end),
169 int WXUNUSED(step) = 1,
170 int WXUNUSED(flags) = 0,
171 long WXUNUSED(style) = 0)
1e6feb95
VZ
172 {
173 // we don't have the ticks in GTK version
174 }
9a6384ca 175#endif // wxUSE_SLIDER
1e6feb95 176
9a6384ca 177#if wxUSE_MENUS
1e6feb95
VZ
178 virtual void DrawMenuBarItem(wxDC& dc,
179 const wxRect& rect,
180 const wxString& label,
181 int flags = 0,
182 int indexAccel = -1);
183 virtual void DrawMenuItem(wxDC& dc,
184 wxCoord y,
185 const wxMenuGeometryInfo& geometryInfo,
186 const wxString& label,
187 const wxString& accel,
188 const wxBitmap& bitmap = wxNullBitmap,
189 int flags = 0,
190 int indexAccel = -1);
191 virtual void DrawMenuSeparator(wxDC& dc,
192 wxCoord y,
193 const wxMenuGeometryInfo& geomInfo);
9a6384ca 194#endif // wxUSE_MENUS
71e03035 195
9a6384ca 196#if wxUSE_STATUSBAR
71e03035
VZ
197 virtual void DrawStatusField(wxDC& dc,
198 const wxRect& rect,
199 const wxString& label,
c2919ab3 200 int flags = 0, int style = 0);
9a6384ca 201#endif // wxUSE_STATUSBAR
24a23c35
VS
202
203 virtual void DrawFrameTitleBar(wxDC& dc,
204 const wxRect& rect,
205 const wxString& title,
206 const wxIcon& icon,
207 int flags,
813edf09
VS
208 int specialButton = 0,
209 int specialButtonFlag = 0);
24a23c35
VS
210 virtual void DrawFrameBorder(wxDC& dc,
211 const wxRect& rect,
212 int flags);
213 virtual void DrawFrameBackground(wxDC& dc,
214 const wxRect& rect,
215 int flags);
216 virtual void DrawFrameTitle(wxDC& dc,
217 const wxRect& rect,
218 const wxString& title,
219 int flags);
220 virtual void DrawFrameIcon(wxDC& dc,
221 const wxRect& rect,
222 const wxIcon& icon,
223 int flags);
224 virtual void DrawFrameButton(wxDC& dc,
225 wxCoord x, wxCoord y,
226 int button,
227 int flags = 0);
228
229 // titlebars
230 virtual wxRect GetFrameClientArea(const wxRect& rect, int flags) const;
231 virtual wxSize GetFrameTotalSize(const wxSize& clientSize, int flags) const;
e7dda1ff 232 virtual wxSize GetFrameMinSize(int flags) const;
24a23c35 233 virtual wxSize GetFrameIconSize() const;
813edf09 234 virtual int HitTestFrame(const wxRect& rect, const wxPoint& pt, int flags) const;
9ef3ebfb 235
1e6feb95 236 virtual void GetComboBitmaps(wxBitmap *bmpNormal,
1b488c0e 237 wxBitmap *bmpFocus,
1e6feb95
VZ
238 wxBitmap *bmpPressed,
239 wxBitmap *bmpDisabled);
240
241 virtual void AdjustSize(wxSize *size, const wxWindow *window);
1e6feb95
VZ
242
243 // geometry and hit testing
244 virtual wxSize GetScrollbarArrowSize() const
245 { return m_sizeScrollbarArrow; }
9a6384ca 246#if wxUSE_SCROLLBAR
1e6feb95
VZ
247 virtual wxRect GetScrollbarRect(const wxScrollBar *scrollbar,
248 wxScrollBar::Element elem,
249 int thumbPos = -1) const;
9a6384ca
WS
250#endif // wxUSE_SCROLLBAR
251
1e6feb95
VZ
252 virtual wxCoord GetListboxItemHeight(wxCoord fontHeight)
253 { return fontHeight + 2; }
254 virtual wxSize GetCheckBitmapSize() const
255 { return wxSize(10, 10); }
256 virtual wxSize GetRadioBitmapSize() const
257 { return wxSize(11, 11); }
258 virtual wxCoord GetCheckItemMargin() const
259 { return 2; }
260
3216dbf5
VZ
261 virtual wxSize GetToolBarButtonSize(wxCoord *separator) const
262 { if ( separator ) *separator = 5; return wxSize(16, 15); }
263 virtual wxSize GetToolBarMargin() const
264 { return wxSize(6, 6); }
265
9a6384ca 266#if wxUSE_TEXTCTRL
1e6feb95 267 virtual wxRect GetTextTotalArea(const wxTextCtrl *text,
3216dbf5 268 const wxRect& rect) const;
1e6feb95
VZ
269 virtual wxRect GetTextClientArea(const wxTextCtrl *text,
270 const wxRect& rect,
3216dbf5 271 wxCoord *extraSpaceBeyond) const;
9a6384ca 272#endif // wxUSE_TEXTCTRL
1e6feb95 273
c4036939 274#if wxUSE_NOTEBOOK
1e6feb95
VZ
275 virtual wxSize GetTabIndent() const { return wxSize(2, 2); }
276 virtual wxSize GetTabPadding() const { return wxSize(6, 6); }
c4036939 277#endif // wxUSE_NOTEBOOK
1e6feb95 278
9a6384ca 279#if wxUSE_SLIDER
1e6feb95
VZ
280 virtual wxCoord GetSliderDim() const { return 15; }
281 virtual wxCoord GetSliderTickLen() const { return 0; }
282 virtual wxRect GetSliderShaftRect(const wxRect& rect,
6766e5d1
JS
283 int lenThumb,
284 wxOrientation orient,
285 long style = 0) const;
1e6feb95 286 virtual wxSize GetSliderThumbSize(const wxRect& rect,
6766e5d1 287 int lenThumb,
1e6feb95 288 wxOrientation orient) const;
9a6384ca
WS
289#endif // wxUSE_SLIDER
290
1e6feb95
VZ
291 virtual wxSize GetProgressBarStep() const { return wxSize(16, 32); }
292
9a6384ca 293#if wxUSE_MENUS
1e6feb95
VZ
294 virtual wxSize GetMenuBarItemSize(const wxSize& sizeText) const;
295 virtual wxMenuGeometryInfo *GetMenuGeometry(wxWindow *win,
296 const wxMenu& menu) const;
9a6384ca 297#endif // wxUSE_MENUS
71e03035 298
9a6384ca 299#if wxUSE_STATUSBAR
71e03035 300 virtual wxSize GetStatusBarBorders(wxCoord *borderBetweenFields) const;
9a6384ca 301#endif // wxUSE_STATUSBAR
71e03035 302
1e6feb95
VZ
303 // helpers for "wxBitmap wxColourScheme::Get()"
304 void DrawCheckBitmap(wxDC& dc, const wxRect& rect);
305 void DrawUncheckBitmap(wxDC& dc, const wxRect& rect, bool isPressed);
415a0ff1 306 void DrawUndeterminedBitmap(wxDC& dc, const wxRect& rect, bool isPressed);
1e6feb95
VZ
307
308protected:
147b8a4a
VZ
309 virtual void DrawSunkenBorder(wxDC& dc, wxRect *rect);
310
311 virtual void DrawFrameWithLabel(wxDC& dc,
312 const wxString& label,
313 const wxRect& rectFrame,
314 const wxRect& rectText,
315 int flags,
316 int alignment,
317 int indexAccel);
1e6feb95
VZ
318
319 // get the colour to use for background
320 wxColour GetBackgroundColour(int flags) const
321 {
322 if ( flags & wxCONTROL_PRESSED )
323 return wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED);
324 else if ( flags & wxCONTROL_CURRENT )
325 return wxSCHEME_COLOUR(m_scheme, CONTROL_CURRENT);
326 else
327 return wxSCHEME_COLOUR(m_scheme, CONTROL);
328 }
329
1e6feb95
VZ
330 // as DrawShadedRect() but the pixels in the bottom left and upper right
331 // border are drawn with the pen1, not pen2
332 void DrawAntiShadedRect(wxDC& dc, wxRect *rect,
333 const wxPen& pen1, const wxPen& pen2);
334
335 // used for drawing opened rectangles - draws only one side of it at once
336 // (and doesn't adjust the rect)
337 void DrawAntiShadedRectSide(wxDC& dc,
338 const wxRect& rect,
339 const wxPen& pen1,
340 const wxPen& pen2,
341 wxDirection dir);
342
343 // draw an opened rect for the arrow in given direction
344 void DrawArrowBorder(wxDC& dc,
345 wxRect *rect,
346 wxDirection dir);
347
348 // draw two sides of the rectangle
349 void DrawThumbBorder(wxDC& dc,
350 wxRect *rect,
351 wxOrientation orient);
352
1e6feb95
VZ
353 // just as DrawRaisedBorder() except that the bottom left and up right
354 // pixels of the interior rect are drawn in another colour (i.e. the inner
355 // rect is drawn with DrawAntiShadedRect() and not DrawShadedRect())
356 void DrawAntiRaisedBorder(wxDC& dc, wxRect *rect);
357
147b8a4a
VZ
358 // draw inner GTK shadow
359 void DrawInnerShadedRect(wxDC& dc, wxRect *rect);
360
9a6384ca 361#if wxUSE_SCROLLBAR
1e6feb95
VZ
362 // returns the size of the arrow for the scrollbar (depends on
363 // orientation)
364 wxSize GetScrollbarArrowSize(const wxScrollBar *scrollbar) const
365 {
366 wxSize size;
367 if ( scrollbar->IsVertical() )
368 {
369 size = m_sizeScrollbarArrow;
370 }
371 else
372 {
373 size.x = m_sizeScrollbarArrow.y;
374 size.y = m_sizeScrollbarArrow.x;
375 }
376
377 return size;
378 }
9a6384ca 379#endif // wxUSE_SCROLLBAR
1e6feb95
VZ
380
381 // get the line wrap indicator bitmap
3216dbf5 382 wxBitmap GetLineWrapBitmap() const;
1e6feb95 383
147b8a4a
VZ
384 virtual wxBitmap GetCheckBitmap(int flags);
385 virtual wxBitmap GetRadioBitmap(int flags);
1e6feb95
VZ
386
387 // draw a /\ or \/ line from (x1, y1) to (x2, y1) passing by the point
388 // ((x1 + x2)/2, y2)
389 void DrawUpZag(wxDC& dc,
390 wxCoord x1, wxCoord x2,
391 wxCoord y1, wxCoord y2);
392 void DrawDownZag(wxDC& dc,
393 wxCoord x1, wxCoord x2,
394 wxCoord y1, wxCoord y2);
395
396 // draw the radio button bitmap for the given state
397 void DrawRadioBitmap(wxDC& dc, const wxRect& rect, int flags);
398
399 // draw check/radio - the bitmap must be a valid one by now
400 void DoDrawCheckOrRadioBitmap(wxDC& dc,
401 const wxString& label,
402 const wxBitmap& bitmap,
403 const wxRect& rectTotal,
404 int flags,
405 wxAlignment align,
406 int indexAccel);
407
0fe5e8fe
VZ
408 // common part of DrawMenuItem() and DrawMenuBarItem()
409 void DoDrawMenuItem(wxDC& dc,
410 const wxRect& rect,
411 const wxString& label,
412 int flags,
413 int indexAccel,
8b5d5223 414 const wxString& accel = wxEmptyString,
0fe5e8fe
VZ
415 const wxBitmap& bitmap = wxNullBitmap,
416 const wxGTKMenuGeometryInfo *geometryInfo = NULL);
417
1b488c0e
VZ
418 // initialize the combo bitmaps
419 void InitComboBitmaps();
420
1e6feb95
VZ
421private:
422 const wxColourScheme *m_scheme;
423
424 // data
425 wxSize m_sizeScrollbarArrow;
426
427 // GDI objects
147b8a4a 428 wxPen m_penGrey;
1e6feb95 429
147b8a4a
VZ
430 // the checkbox and radio button bitmaps: first row is for the normal,
431 // second for the pressed state and the columns are for checked, unchecked
432 // and undeterminated respectively
433 wxBitmap m_bitmapsCheckbox[IndicatorState_MaxCtrl][IndicatorStatus_Max],
434 m_bitmapsRadiobtn[IndicatorState_MaxCtrl][IndicatorStatus_Max];
1e6feb95
VZ
435
436 // the line wrap bitmap (drawn at the end of wrapped lines)
437 wxBitmap m_bmpLineWrap;
1b488c0e
VZ
438
439 // the combobox bitmaps
440 enum
441 {
442 ComboState_Normal,
443 ComboState_Focus,
444 ComboState_Pressed,
445 ComboState_Disabled,
446 ComboState_Max
447 };
448
449 wxBitmap m_bitmapsCombo[ComboState_Max];
1e6feb95
VZ
450};
451
452// ----------------------------------------------------------------------------
453// wxGTKInputHandler and derived classes: process the keyboard and mouse
454// messages according to GTK standards
455// ----------------------------------------------------------------------------
456
457class wxGTKInputHandler : public wxInputHandler
458{
459public:
9467bdb7 460 wxGTKInputHandler() { }
1e6feb95 461
67e49a98 462 virtual bool HandleKey(wxInputConsumer *control,
1e6feb95
VZ
463 const wxKeyEvent& event,
464 bool pressed);
67e49a98 465 virtual bool HandleMouse(wxInputConsumer *control,
1e6feb95 466 const wxMouseEvent& event);
9467bdb7
VZ
467 virtual bool HandleMouseMove(wxInputConsumer *control,
468 const wxMouseEvent& event);
1e6feb95
VZ
469};
470
9a6384ca
WS
471#if wxUSE_SCROLLBAR
472
1e6feb95
VZ
473class wxGTKScrollBarInputHandler : public wxStdScrollBarInputHandler
474{
475public:
476 wxGTKScrollBarInputHandler(wxRenderer *renderer, wxInputHandler *handler)
477 : wxStdScrollBarInputHandler(renderer, handler) { }
478
479protected:
480 virtual void Highlight(wxScrollBar *scrollbar, bool doIt)
481 {
482 // only arrows and the thumb can be highlighted
483 if ( !IsArrow() && m_htLast != wxHT_SCROLLBAR_THUMB )
484 return;
485
486 wxStdScrollBarInputHandler::Highlight(scrollbar, doIt);
487 }
488
489 virtual void Press(wxScrollBar *scrollbar, bool doIt)
490 {
491 // only arrows can be pressed
492 if ( !IsArrow() )
493 return;
494
495 wxStdScrollBarInputHandler::Press(scrollbar, doIt);
496 }
497
9467bdb7
VZ
498 // any button can be used to drag the scrollbar under GTK+
499 virtual bool IsAllowedButton(int WXUNUSED(button)) const { return true; }
1e6feb95
VZ
500
501 bool IsArrow() const
502 {
503 return m_htLast == wxHT_SCROLLBAR_ARROW_LINE_1 ||
504 m_htLast == wxHT_SCROLLBAR_ARROW_LINE_2;
505 }
506};
507
9a6384ca
WS
508#endif // wxUSE_SCROLLBAR
509
510#if wxUSE_CHECKBOX
511
9467bdb7 512class wxGTKCheckboxInputHandler : public wxStdInputHandler
1e6feb95
VZ
513{
514public:
515 wxGTKCheckboxInputHandler(wxInputHandler *handler)
9467bdb7 516 : wxStdInputHandler(handler) { }
1e6feb95 517
67e49a98 518 virtual bool HandleKey(wxInputConsumer *control,
1e6feb95
VZ
519 const wxKeyEvent& event,
520 bool pressed);
521};
522
9a6384ca
WS
523#endif // wxUSE_CHECKBOX
524
525#if wxUSE_TEXTCTRL
526
9467bdb7 527class wxGTKTextCtrlInputHandler : public wxStdInputHandler
1e6feb95
VZ
528{
529public:
530 wxGTKTextCtrlInputHandler(wxInputHandler *handler)
9467bdb7 531 : wxStdInputHandler(handler) { }
1e6feb95 532
67e49a98 533 virtual bool HandleKey(wxInputConsumer *control,
1e6feb95
VZ
534 const wxKeyEvent& event,
535 bool pressed);
536};
537
9a6384ca
WS
538#endif // wxUSE_TEXTCTRL
539
1e6feb95
VZ
540// ----------------------------------------------------------------------------
541// wxGTKColourScheme: uses the standard GTK colours
542// ----------------------------------------------------------------------------
543
544class wxGTKColourScheme : public wxColourScheme
545{
546public:
547 virtual wxColour Get(StdColour col) const;
548 virtual wxColour GetBackground(wxWindow *win) const;
549};
550
536b70ac
VS
551// ----------------------------------------------------------------------------
552// wxGTKArtProvider
553// ----------------------------------------------------------------------------
554
555class wxGTKArtProvider : public wxArtProvider
556{
557protected:
558 virtual wxBitmap CreateBitmap(const wxArtID& id,
559 const wxArtClient& client,
560 const wxSize& size);
561};
562
1e6feb95
VZ
563// ----------------------------------------------------------------------------
564// wxGTKTheme
565// ----------------------------------------------------------------------------
566
d5d29b8a 567WX_DEFINE_ARRAY_PTR(wxInputHandler *, wxArrayHandlers);
1e6feb95
VZ
568
569class wxGTKTheme : public wxTheme
570{
571public:
572 wxGTKTheme();
573 virtual ~wxGTKTheme();
574
240889a1 575 virtual wxRenderer *GetRenderer();
536b70ac 576 virtual wxArtProvider *GetArtProvider();
9467bdb7
VZ
577 virtual wxInputHandler *GetInputHandler(const wxString& control,
578 wxInputConsumer *consumer);
240889a1 579 virtual wxColourScheme *GetColourScheme();
1e6feb95
VZ
580
581private:
1e6feb95 582 wxGTKRenderer *m_renderer;
9ef3ebfb 583
536b70ac 584 wxGTKArtProvider *m_artProvider;
1e6feb95
VZ
585
586 // the names of the already created handlers and the handlers themselves
587 // (these arrays are synchronized)
588 wxSortedArrayString m_handlerNames;
589 wxArrayHandlers m_handlers;
590
1e6feb95
VZ
591 wxGTKColourScheme *m_scheme;
592
593 WX_DECLARE_THEME(gtk)
594};
595
596// ============================================================================
597// implementation
598// ============================================================================
599
600WX_IMPLEMENT_THEME(wxGTKTheme, gtk, wxTRANSLATE("GTK+ theme"));
601
602// ----------------------------------------------------------------------------
603// wxGTKTheme
604// ----------------------------------------------------------------------------
605
606wxGTKTheme::wxGTKTheme()
607{
240889a1
VS
608 m_scheme = NULL;
609 m_renderer = NULL;
9ef3ebfb 610 m_artProvider = NULL;
1e6feb95
VZ
611}
612
613wxGTKTheme::~wxGTKTheme()
614{
1e6feb95
VZ
615 delete m_renderer;
616 delete m_scheme;
9ef3ebfb 617 wxArtProvider::RemoveProvider(m_artProvider);
1e6feb95
VZ
618}
619
240889a1
VS
620wxRenderer *wxGTKTheme::GetRenderer()
621{
622 if ( !m_renderer )
623 {
624 m_renderer = new wxGTKRenderer(GetColourScheme());
625 }
626
627 return m_renderer;
628}
629
536b70ac
VS
630wxArtProvider *wxGTKTheme::GetArtProvider()
631{
632 if ( !m_artProvider )
633 {
634 m_artProvider = new wxGTKArtProvider;
635 }
636
637 return m_artProvider;
638}
639
240889a1
VS
640wxColourScheme *wxGTKTheme::GetColourScheme()
641{
642 if ( !m_scheme )
643 {
644 m_scheme = new wxGTKColourScheme;
645 }
646 return m_scheme;
647}
648
9467bdb7
VZ
649wxInputHandler *wxGTKTheme::GetInputHandler(const wxString& control,
650 wxInputConsumer *consumer)
1e6feb95 651{
9a6384ca 652 wxInputHandler *handler = NULL;
1e6feb95
VZ
653 int n = m_handlerNames.Index(control);
654 if ( n == wxNOT_FOUND )
655 {
9467bdb7
VZ
656 static wxGTKInputHandler s_handlerDef;
657
658 wxInputHandler * const
659 handlerStd = consumer->DoGetStdInputHandler(&s_handlerDef);
660
1e6feb95 661 // create a new handler
9467bdb7
VZ
662#if wxUSE_CHECKBOX
663 if ( control == wxINP_HANDLER_CHECKBOX )
9a6384ca 664 {
9467bdb7
VZ
665 static wxGTKCheckboxInputHandler s_handler(handlerStd);
666
667 handler = &s_handler;
9a6384ca 668 }
9467bdb7 669 else
1e6feb95 670#endif // wxUSE_CHECKBOX
9467bdb7
VZ
671#if wxUSE_SCROLLBAR
672 if ( control == wxINP_HANDLER_SCROLLBAR )
673 {
674 static wxGTKScrollBarInputHandler s_handler(m_renderer, handlerStd);
675
676 handler = &s_handler;
677 }
678 else
679#endif // wxUSE_SCROLLBAR
1e6feb95 680#if wxUSE_TEXTCTRL
9467bdb7
VZ
681 if ( control == wxINP_HANDLER_TEXTCTRL )
682 {
683 static wxGTKTextCtrlInputHandler s_handler(handlerStd);
9a6384ca 684
9467bdb7
VZ
685 handler = &s_handler;
686 }
687 else
688#endif // wxUSE_TEXTCTRL
689 {
690 // no special handler for this control
691 handler = handlerStd;
692 }
1e6feb95
VZ
693
694 n = m_handlerNames.Add(control);
695 m_handlers.Insert(handler, n);
696 }
697 else // we already have it
698 {
699 handler = m_handlers[n];
700 }
701
702 return handler;
703}
704
705// ============================================================================
706// wxGTKColourScheme
707// ============================================================================
708
709wxColour wxGTKColourScheme::GetBackground(wxWindow *win) const
710{
711 wxColour col;
712 if ( win->UseBgCol() )
713 {
714 // use the user specified colour
715 col = win->GetBackgroundColour();
716 }
717
230205ae 718 if ( !win->ShouldInheritColours() )
1e6feb95
VZ
719 {
720 // doesn't depend on the state
721 if ( !col.Ok() )
722 {
723 col = Get(WINDOW);
724 }
725 }
726 else
727 {
728 int flags = win->GetStateFlags();
729
730 // the colour set by the user should be used for the normal state
731 // and for the states for which we don't have any specific colours
732 if ( !col.Ok() || (flags != 0) )
733 {
9a6384ca 734#if wxUSE_SCROLLBAR
1e6feb95
VZ
735 if ( wxDynamicCast(win, wxScrollBar) )
736 col = Get(SCROLLBAR);
9a6384ca
WS
737 else
738#endif //wxUSE_SCROLLBAR
739 if ( (flags & wxCONTROL_CURRENT) && win->CanBeHighlighted() )
1e6feb95
VZ
740 col = Get(CONTROL_CURRENT);
741 else if ( flags & wxCONTROL_PRESSED )
742 col = Get(CONTROL_PRESSED);
743 else
744 col = Get(CONTROL);
745 }
746 }
747
748 return col;
749}
750
751wxColour wxGTKColourScheme::Get(wxGTKColourScheme::StdColour col) const
752{
753 switch ( col )
754 {
755 case WINDOW: return *wxWHITE;
756
757 case SHADOW_DARK: return *wxBLACK;
758 case SHADOW_HIGHLIGHT: return *wxWHITE;
759 case SHADOW_IN: return wxColour(0xd6d6d6);
760 case SHADOW_OUT: return wxColour(0x969696);
761
762 case CONTROL: return wxColour(0xd6d6d6);
763 case CONTROL_PRESSED: return wxColour(0xc3c3c3);
764 case CONTROL_CURRENT: return wxColour(0xeaeaea);
765
766 case CONTROL_TEXT: return *wxBLACK;
767 case CONTROL_TEXT_DISABLED:
768 return wxColour(0x757575);
769 case CONTROL_TEXT_DISABLED_SHADOW:
770 return *wxWHITE;
771
772 case SCROLLBAR:
773 case SCROLLBAR_PRESSED: return wxColour(0xc3c3c3);
774
775 case HIGHLIGHT: return wxColour(0x9c0000);
776 case HIGHLIGHT_TEXT: return wxColour(0xffffff);
777
a407ff6a
VZ
778 case GAUGE: return Get(CONTROL_CURRENT);
779
9a6384ca
WS
780 case TITLEBAR: return wxColour(0xaeaaae);
781 case TITLEBAR_ACTIVE: return wxColour(0x820300);
782 case TITLEBAR_TEXT: return wxColour(0xc0c0c0);
783 case TITLEBAR_ACTIVE_TEXT:
784 return *wxWHITE;
785
786 case DESKTOP: return *wxBLACK;
787
1e6feb95
VZ
788 case MAX:
789 default:
790 wxFAIL_MSG(_T("invalid standard colour"));
791 return *wxBLACK;
792 }
793}
794
795// ============================================================================
796// wxGTKRenderer
797// ============================================================================
798
799// ----------------------------------------------------------------------------
800// construction
801// ----------------------------------------------------------------------------
802
803wxGTKRenderer::wxGTKRenderer(const wxColourScheme *scheme)
147b8a4a 804 : wxStdRenderer(scheme)
1e6feb95 805{
1e6feb95
VZ
806 m_sizeScrollbarArrow = wxSize(15, 14);
807
147b8a4a 808 m_penGrey = wxPen(wxSCHEME_COLOUR(scheme, SCROLLBAR));
1e6feb95
VZ
809}
810
811// ----------------------------------------------------------------------------
812// border stuff
813// ----------------------------------------------------------------------------
814
1e6feb95
VZ
815void wxGTKRenderer::DrawAntiShadedRectSide(wxDC& dc,
816 const wxRect& rect,
817 const wxPen& pen1,
818 const wxPen& pen2,
819 wxDirection dir)
820{
821 dc.SetPen(dir == wxLEFT || dir == wxUP ? pen1 : pen2);
822
823 switch ( dir )
824 {
825 case wxLEFT:
826 dc.DrawLine(rect.GetLeft(), rect.GetTop(),
827 rect.GetLeft(), rect.GetBottom() + 1);
828 break;
829
830 case wxUP:
831 dc.DrawLine(rect.GetLeft(), rect.GetTop(),
832 rect.GetRight() + 1, rect.GetTop());
833 break;
834
835 case wxRIGHT:
836 dc.DrawLine(rect.GetRight(), rect.GetTop(),
837 rect.GetRight(), rect.GetBottom() + 1);
838 break;
839
840 case wxDOWN:
841 dc.DrawLine(rect.GetLeft(), rect.GetBottom(),
842 rect.GetRight() + 1, rect.GetBottom());
843 break;
844
845 default:
846 wxFAIL_MSG(_T("unknown rectangle side"));
847 }
848}
849
850void wxGTKRenderer::DrawAntiShadedRect(wxDC& dc, wxRect *rect,
851 const wxPen& pen1, const wxPen& pen2)
852{
853 // draw the rectangle
854 dc.SetPen(pen1);
855 dc.DrawLine(rect->GetLeft(), rect->GetTop(),
856 rect->GetLeft(), rect->GetBottom() + 1);
857 dc.DrawLine(rect->GetLeft() + 1, rect->GetTop(),
858 rect->GetRight() + 1, rect->GetTop());
859 dc.SetPen(pen2);
860 dc.DrawLine(rect->GetRight(), rect->GetTop() + 1,
861 rect->GetRight(), rect->GetBottom());
862 dc.DrawLine(rect->GetLeft() + 1, rect->GetBottom(),
863 rect->GetRight() + 1, rect->GetBottom());
864
865 // adjust the rect
866 rect->Inflate(-1);
867}
868
147b8a4a 869void wxGTKRenderer::DrawInnerShadedRect(wxDC& dc, wxRect *rect)
1e6feb95 870{
147b8a4a
VZ
871 DrawAntiShadedRect(dc, rect, m_penDarkGrey, m_penHighlight);
872 DrawAntiShadedRect(dc, rect, m_penBlack, m_penHighlight);
1e6feb95
VZ
873}
874
875void wxGTKRenderer::DrawAntiRaisedBorder(wxDC& dc, wxRect *rect)
876{
877 DrawShadedRect(dc, rect, m_penHighlight, m_penBlack);
878 DrawAntiShadedRect(dc, rect, m_penLightGrey, m_penDarkGrey);
879}
880
147b8a4a 881void wxGTKRenderer::DrawSunkenBorder(wxDC& dc, wxRect *rect)
1e6feb95 882{
147b8a4a
VZ
883 DrawAntiShadedRect(dc, rect, m_penDarkGrey, m_penHighlight);
884 DrawShadedRect(dc, rect, m_penBlack, m_penLightGrey);
1e6feb95
VZ
885}
886
147b8a4a 887void wxGTKRenderer::DrawFocusRect(wxDC& dc, const wxRect& rect)
1e6feb95 888{
147b8a4a
VZ
889 dc.SetBrush(*wxTRANSPARENT_BRUSH);
890 wxRect rectFocus = rect;
891 DrawRect(dc, &rectFocus, m_penBlack);
1e6feb95
VZ
892}
893
1e6feb95
VZ
894void wxGTKRenderer::DrawTextBorder(wxDC& dc,
895 wxBorder border,
896 const wxRect& rectOrig,
897 int flags,
898 wxRect *rectIn)
899{
900 wxRect rect = rectOrig;
901
89e7a223 902 if ( border != wxBORDER_NONE )
1e6feb95 903 {
e4606ed9
VZ
904 if ( flags & wxCONTROL_FOCUSED )
905 {
906 DrawRect(dc, &rect, m_penBlack);
907 DrawAntiShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight);
908 }
909 else // !focused
910 {
147b8a4a 911 DrawInnerShadedRect(dc, &rect);
e4606ed9 912 }
1e6feb95
VZ
913 }
914
915 if ( rectIn )
916 *rectIn = rect;
917}
918
147b8a4a
VZ
919void wxGTKRenderer::DrawButtonLabel(wxDC& dc,
920 const wxString& label,
921 const wxBitmap& image,
922 const wxRect& rect,
923 int flags,
924 int alignment,
925 int indexAccel,
926 wxRect *rectBounds)
927{
928 // no focus rect around buttons label in GTK+
929 wxStdRenderer::DrawButtonLabel(dc, label, image, rect, flags,
930 alignment, indexAccel, rectBounds);
931}
932
1e6feb95
VZ
933void wxGTKRenderer::DrawButtonBorder(wxDC& dc,
934 const wxRect& rectTotal,
935 int flags,
936 wxRect *rectIn)
937{
938 wxRect rect = rectTotal;
939
940 if ( flags & wxCONTROL_PRESSED )
941 {
942 // button pressed: draw a black border around it and an inward shade
943 DrawRect(dc, &rect, m_penBlack);
e4606ed9 944
147b8a4a 945 DrawInnerShadedRect(dc, &rect);
1e6feb95 946 }
147b8a4a 947 else // button not pressed
1e6feb95 948 {
1e6feb95
VZ
949 if ( flags & wxCONTROL_ISDEFAULT )
950 {
951 // TODO
952 }
953
954 if ( flags & wxCONTROL_FOCUSED )
955 {
956 // button is currently default: add an extra border around it
957 DrawRect(dc, &rect, m_penBlack);
958 }
959
960 // now draw a normal button
147b8a4a
VZ
961 DrawShadedRect(dc, &rect, m_penHighlight, m_penBlack);
962 DrawAntiShadedRect(dc, &rect, GetBackgroundColour(flags), m_penDarkGrey);
1e6feb95
VZ
963 }
964
965 if ( rectIn )
1e6feb95 966 *rectIn = rect;
1e6feb95
VZ
967}
968
969// ----------------------------------------------------------------------------
970// lines and frames
971// ----------------------------------------------------------------------------
972
147b8a4a
VZ
973void wxGTKRenderer::DrawFrameWithLabel(wxDC& dc,
974 const wxString& label,
975 const wxRect& rectFrame,
976 const wxRect& rectTextOrig,
977 int flags,
978 int alignment,
979 int indexAccel)
1e6feb95 980{
147b8a4a
VZ
981 wxRect rectText(rectTextOrig);
982 rectText.Inflate(1, 0);
1e6feb95 983
147b8a4a
VZ
984 wxRect rectLabel;
985 DrawLabel(dc, label, rectText, flags, alignment, indexAccel, &rectLabel);
986 rectLabel.x -= 1;
987 rectLabel.width += 2;
1e6feb95 988
147b8a4a 989 DrawFrameWithoutLabel(dc, rectFrame, rectLabel);
1e6feb95 990
147b8a4a
VZ
991 // GTK+ does it like this
992 dc.SetPen(m_penHighlight);
993 dc.DrawPoint(rectText.x, rectFrame.y);
994 dc.DrawPoint(rectText.x + rectLabel.width - 3, rectFrame.y);
1e6feb95
VZ
995}
996
997// ----------------------------------------------------------------------------
998// label
999// ----------------------------------------------------------------------------
1000
1e6feb95
VZ
1001void wxGTKRenderer::DrawCheckItem(wxDC& dc,
1002 const wxString& label,
1003 const wxBitmap& bitmap,
1004 const wxRect& rect,
1005 int flags)
1006{
1007 wxRect rectBitmap = rect;
1008 rectBitmap.x -= 1;
1009 rectBitmap.width = GetCheckBitmapSize().x;
0fe5e8fe 1010
1e6feb95 1011 // never draw the focus rect around the check indicators here
8b5d5223 1012 DrawCheckButton(dc, wxEmptyString, bitmap, rectBitmap, flags & ~wxCONTROL_FOCUSED);
1e6feb95
VZ
1013
1014 wxRect rectLabel = rect;
9ef3ebfb 1015 wxCoord shift = rectBitmap.width + 2*GetCheckItemMargin();
1e6feb95
VZ
1016 rectLabel.x += shift;
1017 rectLabel.width -= shift;
1018 DrawItem(dc, label, rectLabel, flags);
1019}
1020
1021// ----------------------------------------------------------------------------
1022// check/radion buttons
1023// ----------------------------------------------------------------------------
1024
415a0ff1
WS
1025void wxGTKRenderer::DrawUndeterminedBitmap(wxDC& dc,
1026 const wxRect& rectTotal,
1027 bool isPressed)
1028{
1029 // FIXME: For sure it is not GTK look but it is better than nothing.
1030 // Show me correct look and I will immediatelly make it better (ABX)
1031 wxRect rect = rectTotal;
1032
1033 wxColour col1, col2;
1034
1035 if ( isPressed )
1036 {
1037 col1 = wxSCHEME_COLOUR(m_scheme, SHADOW_DARK);
1038 col2 = wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED);
1039 }
1040 else
1041 {
1042 col1 = wxSCHEME_COLOUR(m_scheme, SHADOW_DARK);
1043 col2 = wxSCHEME_COLOUR(m_scheme, SHADOW_IN);
1044 }
1045
1046 dc.SetPen(*wxTRANSPARENT_PEN);
147b8a4a 1047 dc.SetBrush(col1);
415a0ff1
WS
1048 dc.DrawRectangle(rect);
1049 rect.Deflate(1);
147b8a4a 1050 dc.SetBrush(col2);
415a0ff1
WS
1051 dc.DrawRectangle(rect);
1052}
1053
1e6feb95
VZ
1054void wxGTKRenderer::DrawUncheckBitmap(wxDC& dc,
1055 const wxRect& rectTotal,
1056 bool isPressed)
1057{
1058 wxRect rect = rectTotal;
1059 DrawAntiRaisedBorder(dc, &rect);
1060
1061 wxColour col = wxSCHEME_COLOUR(m_scheme, SHADOW_IN);
147b8a4a 1062 dc.SetPen(wxPen(col));
1e6feb95
VZ
1063 dc.DrawPoint(rect.GetRight() - 1, rect.GetBottom() - 1);
1064
1065 if ( isPressed )
1066 col = wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED);
1067 //else: it is SHADOW_IN, leave as is
1068
1069 dc.SetPen(*wxTRANSPARENT_PEN);
147b8a4a 1070 dc.SetBrush(col);
1e6feb95
VZ
1071 dc.DrawRectangle(rect);
1072}
1073
1074void wxGTKRenderer::DrawCheckBitmap(wxDC& dc, const wxRect& rectTotal)
1075{
1076 wxRect rect = rectTotal;
1077 DrawAntiShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight);
1078 DrawShadedRect(dc, &rect, m_penBlack, m_penLightGrey);
1079
1080 dc.SetPen(*wxTRANSPARENT_PEN);
147b8a4a 1081 dc.SetBrush(wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED));
1e6feb95
VZ
1082 dc.DrawRectangle(rect);
1083}
1084
1085void wxGTKRenderer::DrawRadioBitmap(wxDC& dc,
1086 const wxRect& rect,
1087 int flags)
1088{
1089 wxCoord x = rect.x,
1090 y = rect.y,
1091 xRight = rect.GetRight(),
1092 yBottom = rect.GetBottom();
1093
1094 wxCoord yMid = (y + yBottom) / 2;
1095
1e6feb95
VZ
1096 // then draw the upper half
1097 dc.SetPen(flags & wxCONTROL_CHECKED ? m_penDarkGrey : m_penHighlight);
1098 DrawUpZag(dc, x, xRight, yMid, y);
1099 DrawUpZag(dc, x + 1, xRight - 1, yMid, y + 1);
1100
a290fa5a 1101 bool drawIt = true;
1e6feb95
VZ
1102 if ( flags & wxCONTROL_CHECKED )
1103 dc.SetPen(m_penBlack);
1104 else if ( flags & wxCONTROL_PRESSED )
147b8a4a 1105 dc.SetPen(wxPen(wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED)));
1e6feb95 1106 else // unchecked and unpressed
a290fa5a 1107 drawIt = false;
1e6feb95
VZ
1108
1109 if ( drawIt )
1110 DrawUpZag(dc, x + 2, xRight - 2, yMid, y + 2);
1111
1112 // and then the lower one
1113 dc.SetPen(flags & wxCONTROL_CHECKED ? m_penHighlight : m_penBlack);
1114 DrawDownZag(dc, x, xRight, yMid, yBottom);
1115 if ( !(flags & wxCONTROL_CHECKED) )
1116 dc.SetPen(m_penDarkGrey);
1117 DrawDownZag(dc, x + 1, xRight - 1, yMid, yBottom - 1);
1118
1119 if ( !(flags & wxCONTROL_CHECKED) )
a290fa5a 1120 drawIt = true; // with the same pen
1e6feb95
VZ
1121 else if ( flags & wxCONTROL_PRESSED )
1122 {
147b8a4a 1123 dc.SetPen(wxPen(wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED)));
a290fa5a 1124 drawIt = true;
1e6feb95
VZ
1125 }
1126 else // checked and unpressed
a290fa5a 1127 drawIt = false;
1e6feb95
VZ
1128
1129 if ( drawIt )
1130 DrawDownZag(dc, x + 2, xRight - 2, yMid, yBottom - 2);
1131}
1132
1133void wxGTKRenderer::DrawUpZag(wxDC& dc,
1134 wxCoord x1,
1135 wxCoord x2,
1136 wxCoord y1,
1137 wxCoord y2)
1138{
1139 wxCoord xMid = (x1 + x2) / 2;
1140 dc.DrawLine(x1, y1, xMid, y2);
1141 dc.DrawLine(xMid, y2, x2 + 1, y1 + 1);
1142}
1143
1144void wxGTKRenderer::DrawDownZag(wxDC& dc,
1145 wxCoord x1,
1146 wxCoord x2,
1147 wxCoord y1,
1148 wxCoord y2)
1149{
1150 wxCoord xMid = (x1 + x2) / 2;
1151 dc.DrawLine(x1 + 1, y1 + 1, xMid, y2);
1152 dc.DrawLine(xMid, y2, x2, y1);
1153}
1154
1155wxBitmap wxGTKRenderer::GetCheckBitmap(int flags)
1156{
1157 if ( !m_bitmapsCheckbox[0][0].Ok() )
1158 {
1159 // init the bitmaps once only
1160 wxRect rect;
1161 wxSize size = GetCheckBitmapSize();
1162 rect.width = size.x;
1163 rect.height = size.y;
1164 for ( int i = 0; i < 2; i++ )
1165 {
415a0ff1 1166 for ( int j = 0; j < 3; j++ )
1e6feb95
VZ
1167 m_bitmapsCheckbox[i][j].Create(rect.width, rect.height);
1168 }
1169
1170 wxMemoryDC dc;
1171
1172 // normal checked
1173 dc.SelectObject(m_bitmapsCheckbox[0][0]);
1174 DrawCheckBitmap(dc, rect);
1175
1176 // normal unchecked
1177 dc.SelectObject(m_bitmapsCheckbox[0][1]);
a290fa5a 1178 DrawUncheckBitmap(dc, rect, false);
1e6feb95 1179
415a0ff1
WS
1180 // normal undeterminated
1181 dc.SelectObject(m_bitmapsCheckbox[0][2]);
1182 DrawUndeterminedBitmap(dc, rect, false);
1183
1e6feb95
VZ
1184 // pressed checked
1185 m_bitmapsCheckbox[1][0] = m_bitmapsCheckbox[0][0];
1186
1187 // pressed unchecked
1188 dc.SelectObject(m_bitmapsCheckbox[1][1]);
a290fa5a 1189 DrawUncheckBitmap(dc, rect, true);
415a0ff1
WS
1190
1191 // pressed undeterminated
1192 dc.SelectObject(m_bitmapsCheckbox[1][2]);
1193 DrawUndeterminedBitmap(dc, rect, true);
1e6feb95
VZ
1194 }
1195
147b8a4a
VZ
1196 IndicatorState state;
1197 IndicatorStatus status;
1198 GetIndicatorsFromFlags(flags, state, status);
1e6feb95 1199
147b8a4a
VZ
1200 // disabled looks the same as normal
1201 if ( state == IndicatorState_Disabled )
1202 state = IndicatorState_Normal;
1203
1204 return m_bitmapsCheckbox[state][status];
1205}
1206
1207wxBitmap wxGTKRenderer::GetRadioBitmap(int flags)
1208{
1209 IndicatorState state;
1210 IndicatorStatus status;
1211 GetIndicatorsFromFlags(flags, state, status);
1212
1213 wxBitmap& bmp = m_bitmapsRadiobtn[state][status];
1214 if ( !bmp.Ok() )
1215 {
1216 const wxSize size = GetRadioBitmapSize();
1217
1218 wxMemoryDC dc;
1219 bmp.Create(size.x, size.y);
1220 dc.SelectObject(bmp);
1221
1222 DrawRadioBitmap(dc, size, flags);
1223 }
1224
1225 return bmp;
1e6feb95
VZ
1226}
1227
3216dbf5 1228wxBitmap wxGTKRenderer::GetLineWrapBitmap() const
1e6feb95
VZ
1229{
1230 if ( !m_bmpLineWrap.Ok() )
1231 {
1232 // the line wrap bitmap as used by GTK+
1233 #define line_wrap_width 6
1234 #define line_wrap_height 9
1235 static const char line_wrap_bits[] =
1236 {
1237 0x1e, 0x3e, 0x30, 0x30, 0x39, 0x1f, 0x0f, 0x0f, 0x1f,
1238 };
1239
1240 wxBitmap bmpLineWrap(line_wrap_bits, line_wrap_width, line_wrap_height);
1241 if ( !bmpLineWrap.Ok() )
1242 {
1243 wxFAIL_MSG( _T("Failed to create line wrap XBM") );
1244 }
1245 else
1246 {
3216dbf5 1247 wxConstCast(this, wxGTKRenderer)->m_bmpLineWrap = bmpLineWrap;
1e6feb95
VZ
1248 }
1249 }
1250
1251 return m_bmpLineWrap;
1252}
1253
9a6384ca 1254#if wxUSE_TOOLBAR
3216dbf5
VZ
1255void wxGTKRenderer::DrawToolBarButton(wxDC& dc,
1256 const wxString& label,
1257 const wxBitmap& bitmap,
1258 const wxRect& rectOrig,
a8f4cabe 1259 int flags,
370efbe7
WS
1260 long WXUNUSED(style),
1261 int tbarStyle)
3216dbf5
VZ
1262{
1263 // we don't draw the separators at all
1264 if ( !label.empty() || bitmap.Ok() )
1265 {
1266 wxRect rect = rectOrig;
1267 rect.Deflate(BORDER_THICKNESS);
1268
1269 if ( flags & wxCONTROL_PRESSED )
1270 {
2e7b0a16
VZ
1271 DrawBorder(dc, wxBORDER_SUNKEN, rect, flags, &rect);
1272
1273 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED), rect);
3216dbf5
VZ
1274 }
1275 else if ( flags & wxCONTROL_CURRENT )
1276 {
2e7b0a16
VZ
1277 DrawBorder(dc, wxBORDER_RAISED, rect, flags, &rect);
1278
1279 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL_CURRENT), rect);
3216dbf5
VZ
1280 }
1281
370efbe7
WS
1282 if(tbarStyle & wxTB_TEXT)
1283 {
1284 if(tbarStyle & wxTB_HORIZONTAL)
1285 {
1286 dc.DrawLabel(label, bitmap, rect, wxALIGN_CENTRE);
1287 }
1288 else
1289 {
1290 dc.DrawLabel(label, bitmap, rect, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL);
1291 }
1292 }
1293 else
1294 {
1295 int xpoint = (rect.GetLeft() + rect.GetRight() + 1 - bitmap.GetWidth()) / 2;
1296 int ypoint = (rect.GetTop() + rect.GetBottom() + 1 - bitmap.GetHeight()) / 2;
1297 dc.DrawBitmap(bitmap, xpoint, ypoint);
1298 }
3216dbf5
VZ
1299 }
1300}
9a6384ca 1301#endif // wxUSE_TOOLBAR
3216dbf5 1302
1e6feb95
VZ
1303// ----------------------------------------------------------------------------
1304// text control
1305// ----------------------------------------------------------------------------
1306
9a6384ca
WS
1307#if wxUSE_TEXTCTRL
1308
61fef19b 1309wxRect wxGTKRenderer::GetTextTotalArea(const wxTextCtrl * WXUNUSED(text),
3216dbf5 1310 const wxRect& rect) const
1e6feb95
VZ
1311{
1312 wxRect rectTotal = rect;
89e7a223 1313 rectTotal.Inflate(2*BORDER_THICKNESS);
1e6feb95
VZ
1314 return rectTotal;
1315}
1316
1317wxRect wxGTKRenderer::GetTextClientArea(const wxTextCtrl *text,
1318 const wxRect& rect,
3216dbf5 1319 wxCoord *extraSpaceBeyond) const
1e6feb95
VZ
1320{
1321 wxRect rectText = rect;
5836c908 1322 rectText.Deflate(2*BORDER_THICKNESS);
1e6feb95
VZ
1323
1324 if ( text->WrapLines() )
1325 {
1326 // leave enough for the line wrap bitmap indicator
1327 wxCoord widthMark = GetLineWrapBitmap().GetWidth() + 2;
1328
1329 rectText.width -= widthMark;
1330
1331 if ( extraSpaceBeyond )
1332 *extraSpaceBeyond = widthMark;
1333 }
1334
1335 return rectText;
1336}
1337
9a6384ca
WS
1338#endif // wxUSE_TEXTCTRL
1339
1e6feb95
VZ
1340void wxGTKRenderer::DrawLineWrapMark(wxDC& dc, const wxRect& rect)
1341{
1342 wxBitmap bmpLineWrap = GetLineWrapBitmap();
1343
1344 // for a mono bitmap he colours it appears in depends on the current text
1345 // colours, so set them correctly
1346 wxColour colFgOld;
1347 if ( bmpLineWrap.GetDepth() == 1 )
1348 {
1349 colFgOld = dc.GetTextForeground();
1350
1351 // FIXME: I wonder what should we do if the background is black too?
1352 dc.SetTextForeground(*wxBLACK);
1353 }
1354
1355 dc.DrawBitmap(bmpLineWrap,
1356 rect.x, rect.y + (rect.height - bmpLineWrap.GetHeight())/2);
1357
1358 if ( colFgOld.Ok() )
1359 {
1360 // restore old colour
1361 dc.SetTextForeground(colFgOld);
1362 }
1363}
1364
1365// ----------------------------------------------------------------------------
1366// notebook
1367// ----------------------------------------------------------------------------
1368
c4036939
VZ
1369#if wxUSE_NOTEBOOK
1370
1e6feb95
VZ
1371void wxGTKRenderer::DrawTab(wxDC& dc,
1372 const wxRect& rectOrig,
1373 wxDirection dir,
1374 const wxString& label,
1375 const wxBitmap& bitmap,
1376 int flags,
1377 int indexAccel)
1378{
7166a05d
WS
1379 #define SELECT_FOR_VERTICAL(X,Y) ( isVertical ? Y : X )
1380 #define REVERSE_FOR_VERTICAL(X,Y) \
1381 SELECT_FOR_VERTICAL(X,Y) \
1382 , \
1383 SELECT_FOR_VERTICAL(Y,X)
1384
1e6feb95
VZ
1385 wxRect rect = rectOrig;
1386
7166a05d
WS
1387 bool isVertical = ( dir == wxLEFT ) || ( dir == wxRIGHT );
1388
1e6feb95
VZ
1389 // the current tab is drawn indented (to the top for default case) and
1390 // bigger than the other ones
1391 const wxSize indent = GetTabIndent();
1392 if ( flags & wxCONTROL_SELECTED )
1393 {
7166a05d
WS
1394 rect.Inflate( SELECT_FOR_VERTICAL( indent.x , 0),
1395 SELECT_FOR_VERTICAL( 0, indent.y ));
1e6feb95
VZ
1396 switch ( dir )
1397 {
1398 default:
1399 wxFAIL_MSG(_T("invaild notebook tab orientation"));
1400 // fall through
1401
1402 case wxTOP:
1e6feb95 1403 rect.y -= indent.y;
7166a05d 1404 // fall through
1e6feb95 1405 case wxBOTTOM:
1e6feb95
VZ
1406 rect.height += indent.y;
1407 break;
1408
1409 case wxLEFT:
7166a05d
WS
1410 rect.x -= indent.x;
1411 // fall through
1e6feb95 1412 case wxRIGHT:
7166a05d 1413 rect.width += indent.x;
1e6feb95
VZ
1414 break;
1415 }
1416 }
1417
1418 // selected tab has different colour
1419 wxColour col = flags & wxCONTROL_SELECTED
1420 ? wxSCHEME_COLOUR(m_scheme, SHADOW_IN)
1421 : wxSCHEME_COLOUR(m_scheme, SCROLLBAR);
147b8a4a 1422 DrawSolidRect(dc, col, rect);
1e6feb95
VZ
1423
1424 if ( flags & wxCONTROL_FOCUSED )
1425 {
1426 // draw the focus rect
1427 wxRect rectBorder = rect;
1428 rectBorder.Deflate(4, 3);
1429 if ( dir == wxBOTTOM )
1430 rectBorder.Offset(0, -1);
7166a05d
WS
1431 if ( dir == wxRIGHT )
1432 rectBorder.Offset(-1, 0);
1e6feb95
VZ
1433
1434 DrawRect(dc, &rectBorder, m_penBlack);
1435 }
1436
1437 // draw the text, image and the focus around them (if necessary)
7166a05d
WS
1438 wxRect rectLabel( REVERSE_FOR_VERTICAL(rect.x,rect.y),
1439 REVERSE_FOR_VERTICAL(rect.width,rect.height)
1440 );
1e6feb95 1441 rectLabel.Deflate(1, 1);
7166a05d
WS
1442 if ( isVertical )
1443 {
1444 // draw it horizontally into memory and rotate for screen
1445 wxMemoryDC dcMem;
1446 wxBitmap bitmapRotated,
1447 bitmapMem( rectLabel.x + rectLabel.width,
1448 rectLabel.y + rectLabel.height );
1449 dcMem.SelectObject(bitmapMem);
1450 dcMem.SetBackground(dc.GetBackground());
1451 dcMem.SetFont(dc.GetFont());
1452 dcMem.SetTextForeground(dc.GetTextForeground());
1453 dcMem.Clear();
9a6384ca
WS
1454 bitmapRotated =
1455#if wxUSE_IMAGE
1456 wxBitmap( wxImage( bitmap.ConvertToImage() ).Rotate90(dir==wxLEFT) )
1457#else
1458 bitmap
1459#endif // wxUSE_IMAGE
1460 ;
7166a05d
WS
1461 dcMem.DrawLabel(label, bitmapRotated, rectLabel, wxALIGN_CENTRE, indexAccel);
1462 dcMem.SelectObject(wxNullBitmap);
1463 bitmapMem = bitmapMem.GetSubBitmap(rectLabel);
9a6384ca
WS
1464#if wxUSE_IMAGE
1465 bitmapMem = wxBitmap(wxImage(bitmapMem.ConvertToImage()).Rotate90(dir==wxRIGHT))
1466#endif
1467 ;
1468
7166a05d
WS
1469 dc.DrawBitmap(bitmapMem, rectLabel.y, rectLabel.x, false);
1470 }
1471 else
1472 {
1473 dc.DrawLabel(label, bitmap, rectLabel, wxALIGN_CENTRE, indexAccel);
1474 }
1e6feb95
VZ
1475
1476 // now draw the tab itself
7166a05d
WS
1477 wxCoord x = SELECT_FOR_VERTICAL(rect.x,rect.y),
1478 y = SELECT_FOR_VERTICAL(rect.y,rect.x),
1479 x2 = SELECT_FOR_VERTICAL(rect.GetRight(),rect.GetBottom()),
1480 y2 = SELECT_FOR_VERTICAL(rect.GetBottom(),rect.GetRight());
1e6feb95
VZ
1481 switch ( dir )
1482 {
1483 default:
7166a05d
WS
1484 // default is top
1485 case wxLEFT:
1486 // left orientation looks like top but IsVertical makes x and y reversed
1e6feb95 1487 case wxTOP:
7166a05d 1488 // top is not vertical so use coordinates in written order
1e6feb95 1489 dc.SetPen(m_penHighlight);
7166a05d
WS
1490 dc.DrawLine(REVERSE_FOR_VERTICAL(x, y2),
1491 REVERSE_FOR_VERTICAL(x, y));
1492 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y),
1493 REVERSE_FOR_VERTICAL(x2, y));
1e6feb95
VZ
1494
1495 dc.SetPen(m_penBlack);
7166a05d
WS
1496 dc.DrawLine(REVERSE_FOR_VERTICAL(x2, y2),
1497 REVERSE_FOR_VERTICAL(x2, y));
1e6feb95
VZ
1498
1499 dc.SetPen(m_penDarkGrey);
7166a05d
WS
1500 dc.DrawLine(REVERSE_FOR_VERTICAL(x2 - 1, y2),
1501 REVERSE_FOR_VERTICAL(x2 - 1, y + 1));
1e6feb95
VZ
1502
1503 if ( flags & wxCONTROL_SELECTED )
1504 {
1505 dc.SetPen(m_penLightGrey);
1506
1507 // overwrite the part of the border below this tab
7166a05d
WS
1508 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y2 + 1),
1509 REVERSE_FOR_VERTICAL(x2 - 1, y2 + 1));
1e6feb95
VZ
1510
1511 // and the shadow of the tab to the left of us
7166a05d
WS
1512 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y + 2),
1513 REVERSE_FOR_VERTICAL(x + 1, y2 + 1));
1e6feb95
VZ
1514 }
1515 break;
1516
7166a05d
WS
1517 case wxRIGHT:
1518 // right orientation looks like bottom but IsVertical makes x and y reversed
1e6feb95 1519 case wxBOTTOM:
7166a05d 1520 // bottom is not vertical so use coordinates in written order
1e6feb95
VZ
1521 dc.SetPen(m_penHighlight);
1522
1523 // we need to continue one pixel further to overwrite the corner of
1524 // the border for the selected tab
7166a05d
WS
1525 dc.DrawLine(REVERSE_FOR_VERTICAL(x, y - (flags & wxCONTROL_SELECTED ? 1 : 0)),
1526 REVERSE_FOR_VERTICAL(x, y2));
1e6feb95
VZ
1527
1528 // it doesn't work like this (TODO: implement it properly)
1529#if 0
1530 // erase the corner of the tab to the right
1531 dc.SetPen(m_penLightGrey);
7166a05d
WS
1532 dc.DrawPoint(REVERSE_FOR_VERTICAL(x2 - 1, y - 2));
1533 dc.DrawPoint(REVERSE_FOR_VERTICAL(x2 - 2, y - 2));
1534 dc.DrawPoint(REVERSE_FOR_VERTICAL(x2 - 2, y - 1));
1e6feb95
VZ
1535#endif // 0
1536
1537 dc.SetPen(m_penBlack);
7166a05d
WS
1538 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y2),
1539 REVERSE_FOR_VERTICAL(x2, y2));
1540 dc.DrawLine(REVERSE_FOR_VERTICAL(x2, y),
1541 REVERSE_FOR_VERTICAL(x2, y2));
1e6feb95
VZ
1542
1543 dc.SetPen(m_penDarkGrey);
7166a05d
WS
1544 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 2, y2 - 1),
1545 REVERSE_FOR_VERTICAL(x2 - 1, y2 - 1));
1546 dc.DrawLine(REVERSE_FOR_VERTICAL(x2 - 1, y),
1547 REVERSE_FOR_VERTICAL(x2 - 1, y2));
1e6feb95
VZ
1548
1549 if ( flags & wxCONTROL_SELECTED )
1550 {
1551 dc.SetPen(m_penLightGrey);
1552
1553 // overwrite the part of the (double!) border above this tab
7166a05d
WS
1554 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y - 1),
1555 REVERSE_FOR_VERTICAL(x2 - 1, y - 1));
1556 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y - 2),
1557 REVERSE_FOR_VERTICAL(x2 - 1, y - 2));
1e6feb95
VZ
1558
1559 // and the shadow of the tab to the left of us
7166a05d
WS
1560 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y2 - 1),
1561 REVERSE_FOR_VERTICAL(x + 1, y - 1));
1e6feb95
VZ
1562 }
1563 break;
1e6feb95
VZ
1564 }
1565}
1566
c4036939 1567#endif // wxUSE_NOTEBOOK
9a6384ca 1568
1e6feb95
VZ
1569// ----------------------------------------------------------------------------
1570// slider
1571// ----------------------------------------------------------------------------
1572
c4036939
VZ
1573#if wxUSE_SLIDER
1574
1e6feb95 1575wxSize wxGTKRenderer::GetSliderThumbSize(const wxRect& rect,
6766e5d1 1576 int lenThumb,
1e6feb95
VZ
1577 wxOrientation orient) const
1578{
1579 static const wxCoord SLIDER_THUMB_LENGTH = 30;
1580
1581 wxSize size;
1582
6766e5d1 1583 wxRect rectShaft = GetSliderShaftRect(rect, lenThumb, orient);
1e6feb95
VZ
1584 if ( orient == wxHORIZONTAL )
1585 {
1586 size.x = wxMin(SLIDER_THUMB_LENGTH, rectShaft.width);
1587 size.y = rectShaft.height;
1588 }
1589 else // vertical
1590 {
1591 size.y = wxMin(SLIDER_THUMB_LENGTH, rectShaft.height);
1592 size.x = rectShaft.width;
1593 }
1594
1595 return size;
1596}
1597
1598wxRect wxGTKRenderer::GetSliderShaftRect(const wxRect& rect,
61fef19b 1599 int WXUNUSED(lenThumb),
6766e5d1 1600 wxOrientation WXUNUSED(orient),
61fef19b 1601 long WXUNUSED(style)) const
1e6feb95
VZ
1602{
1603 return rect.Deflate(2*BORDER_THICKNESS, 2*BORDER_THICKNESS);
1604}
1605
1606void wxGTKRenderer::DrawSliderShaft(wxDC& dc,
1607 const wxRect& rectOrig,
61fef19b
VZ
1608 int WXUNUSED(lenThumb),
1609 wxOrientation WXUNUSED(orient),
1e6feb95 1610 int flags,
61fef19b 1611 long WXUNUSED(style),
1e6feb95
VZ
1612 wxRect *rectShaft)
1613{
1614 wxRect rect = rectOrig;
1615
1616 // draw the border first
1617 if ( flags & wxCONTROL_FOCUSED )
1618 {
1619 DrawRect(dc, &rect, m_penBlack);
1e6feb95
VZ
1620 }
1621 else // not focused, normal
1622 {
1623 DrawAntiShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight);
1e6feb95
VZ
1624 }
1625
147b8a4a
VZ
1626 DrawAntiShadedRect(dc, &rect, m_penBlack, m_penLightGrey);
1627
1e6feb95 1628 // and the background
147b8a4a 1629 DrawSolidRect(dc, wxSCHEME_COLOUR(m_scheme, SCROLLBAR), rect);
1e6feb95
VZ
1630
1631 if ( rectShaft )
1632 *rectShaft = rect;
1633}
1634
1635void wxGTKRenderer::DrawSliderThumb(wxDC& dc,
1636 const wxRect& rectOrig,
1637 wxOrientation orient,
61fef19b
VZ
1638 int WXUNUSED(flags),
1639 long WXUNUSED(style))
1e6feb95
VZ
1640{
1641 // draw the thumb border
1642 wxRect rect = rectOrig;
1643 DrawAntiRaisedBorder(dc, &rect);
1644
1645 // draw the handle in the middle
1646 if ( orient == wxVERTICAL )
1647 {
1648 rect.height = 2*BORDER_THICKNESS;
1649 rect.y = rectOrig.y + (rectOrig.height - rect.height) / 2;
1650 }
1651 else // horz
1652 {
1653 rect.width = 2*BORDER_THICKNESS;
1654 rect.x = rectOrig.x + (rectOrig.width - rect.width) / 2;
1655 }
1656
1657 DrawShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight);
1658}
1659
9a6384ca
WS
1660#endif // wxUSE_SLIDER
1661
1662#if wxUSE_MENUS
1663
1e6feb95
VZ
1664// ----------------------------------------------------------------------------
1665// menu and menubar
1666// ----------------------------------------------------------------------------
1667
0fe5e8fe
VZ
1668// wxGTKMenuGeometryInfo: the wxMenuGeometryInfo used by wxGTKRenderer
1669class WXDLLEXPORT wxGTKMenuGeometryInfo : public wxMenuGeometryInfo
1670{
1671public:
1672 virtual wxSize GetSize() const { return m_size; }
1673
1674 wxCoord GetLabelOffset() const { return m_ofsLabel; }
1675 wxCoord GetAccelOffset() const { return m_ofsAccel; }
1676
1677 wxCoord GetItemHeight() const { return m_heightItem; }
1678
1679private:
1680 // the total size of the menu
1681 wxSize m_size;
1682
1683 // the offset of the start of the menu item label
1684 wxCoord m_ofsLabel;
1685
1686 // the offset of the start of the accel label
1687 wxCoord m_ofsAccel;
1688
1689 // the height of a normal (not separator) item
1690 wxCoord m_heightItem;
1691
1692 friend wxMenuGeometryInfo *
1693 wxGTKRenderer::GetMenuGeometry(wxWindow *, const wxMenu&) const;
1694};
1695
1696// FIXME: all constants are hardcoded but shouldn't be
1697static const wxCoord MENU_LEFT_MARGIN = 9;
1698static const wxCoord MENU_RIGHT_MARGIN = 6;
1699
1700static const wxCoord MENU_HORZ_MARGIN = 6;
1701static const wxCoord MENU_VERT_MARGIN = 3;
1702
1703// the margin around bitmap/check marks (on each side)
1704static const wxCoord MENU_BMP_MARGIN = 2;
1705
1706// the margin between the labels and accel strings
1707static const wxCoord MENU_ACCEL_MARGIN = 8;
1708
1709// the separator height in pixels: in fact, strangely enough, the real height
1710// is 2 but Windows adds one extra pixel in the bottom margin, so take it into
1711// account here
1712static const wxCoord MENU_SEPARATOR_HEIGHT = 3;
1713
1714// the size of the standard checkmark bitmap
1715static const wxCoord MENU_CHECK_SIZE = 9;
1716
1e6feb95
VZ
1717void wxGTKRenderer::DrawMenuBarItem(wxDC& dc,
1718 const wxRect& rect,
1719 const wxString& label,
1720 int flags,
1721 int indexAccel)
1722{
0fe5e8fe 1723 DoDrawMenuItem(dc, rect, label, flags, indexAccel);
1e6feb95
VZ
1724}
1725
1726void wxGTKRenderer::DrawMenuItem(wxDC& dc,
1727 wxCoord y,
0fe5e8fe 1728 const wxMenuGeometryInfo& gi,
1e6feb95
VZ
1729 const wxString& label,
1730 const wxString& accel,
1731 const wxBitmap& bitmap,
1732 int flags,
1733 int indexAccel)
1734{
0fe5e8fe
VZ
1735 const wxGTKMenuGeometryInfo& geomInfo = (const wxGTKMenuGeometryInfo&)gi;
1736
1737 wxRect rect;
1738 rect.x = 0;
1739 rect.y = y;
1740 rect.width = geomInfo.GetSize().x;
1741 rect.height = geomInfo.GetItemHeight();
1742
1743 DoDrawMenuItem(dc, rect, label, flags, indexAccel, accel, bitmap, &geomInfo);
1744}
1745
1746void wxGTKRenderer::DoDrawMenuItem(wxDC& dc,
1747 const wxRect& rectOrig,
1748 const wxString& label,
1749 int flags,
1750 int indexAccel,
1751 const wxString& accel,
1752 const wxBitmap& bitmap,
1753 const wxGTKMenuGeometryInfo *geometryInfo)
1754{
1755 wxRect rect = rectOrig;
1756
1757 // draw the selected item specially
1758 if ( flags & wxCONTROL_SELECTED )
1759 {
1760 wxRect rectIn;
1761 DrawBorder(dc, wxBORDER_RAISED, rect, flags, &rectIn);
1762
1763 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL_CURRENT), rectIn);
1764 }
1765
1766 rect.Deflate(MENU_HORZ_MARGIN, MENU_VERT_MARGIN);
1767
1768 // draw the bitmap: use the bitmap provided or the standard checkmark for
1769 // the checkable items
1770 if ( geometryInfo )
1771 {
1772 wxBitmap bmp = bitmap;
1773 if ( !bmp.Ok() && (flags & wxCONTROL_CHECKABLE) )
1774 {
1775 bmp = GetCheckBitmap(flags);
1776 }
1777
1778 if ( bmp.Ok() )
1779 {
1780 rect.SetRight(geometryInfo->GetLabelOffset());
1781 wxControlRenderer::DrawBitmap(dc, bmp, rect);
1782 }
1783 }
1784 //else: menubar items don't have bitmaps
1785
1786 // draw the label
1787 if ( geometryInfo )
1788 {
1789 rect.x = geometryInfo->GetLabelOffset();
1790 rect.SetRight(geometryInfo->GetAccelOffset());
1791 }
1792
1793 DrawLabel(dc, label, rect, flags, wxALIGN_CENTRE_VERTICAL, indexAccel);
1794
1795 // draw the accel string
1796 if ( !accel.empty() )
1797 {
1798 // menubar items shouldn't have them
1799 wxCHECK_RET( geometryInfo, _T("accel strings only valid for menus") );
1800
1801 rect.x = geometryInfo->GetAccelOffset();
1802 rect.SetRight(geometryInfo->GetSize().x);
1803
1804 // NB: no accel index here
1805 DrawLabel(dc, accel, rect, flags, wxALIGN_CENTRE_VERTICAL);
1806 }
1807
1808 // draw the submenu indicator
1809 if ( flags & wxCONTROL_ISSUBMENU )
1810 {
1811 wxCHECK_RET( geometryInfo, _T("wxCONTROL_ISSUBMENU only valid for menus") );
1812
1813 rect.x = geometryInfo->GetSize().x - MENU_RIGHT_MARGIN;
1814 rect.width = MENU_RIGHT_MARGIN;
1815
1816 DrawArrow(dc, wxRIGHT, rect, flags);
1817 }
1e6feb95
VZ
1818}
1819
1820void wxGTKRenderer::DrawMenuSeparator(wxDC& dc,
1821 wxCoord y,
1822 const wxMenuGeometryInfo& geomInfo)
1823{
0fe5e8fe 1824 DrawHorizontalLine(dc, y + MENU_VERT_MARGIN, 0, geomInfo.GetSize().x);
1e6feb95
VZ
1825}
1826
1827wxSize wxGTKRenderer::GetMenuBarItemSize(const wxSize& sizeText) const
1828{
0fe5e8fe
VZ
1829 wxSize size = sizeText;
1830
1831 // TODO: make this configurable
1832 size.x += 2*MENU_HORZ_MARGIN;
1833 size.y += 2*MENU_VERT_MARGIN;
1834
1835 return size;
1e6feb95
VZ
1836}
1837
1838wxMenuGeometryInfo *wxGTKRenderer::GetMenuGeometry(wxWindow *win,
1839 const wxMenu& menu) const
1840{
0fe5e8fe
VZ
1841 // prepare the dc: for now we draw all the items with the system font
1842 wxClientDC dc(win);
1843 dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
1844
1845 // the height of a normal item
1846 wxCoord heightText = dc.GetCharHeight();
1847
1848 // the total height
1849 wxCoord height = 0;
1850
1851 // the max length of label and accel strings: the menu width is the sum of
1852 // them, even if they're for different items (as the accels should be
1853 // aligned)
1854 //
1855 // the max length of the bitmap is never 0 as Windows always leaves enough
1856 // space for a check mark indicator
1857 wxCoord widthLabelMax = 0,
1858 widthAccelMax = 0,
1859 widthBmpMax = MENU_LEFT_MARGIN;
1860
ac32ba44 1861 for ( wxMenuItemList::compatibility_iterator node = menu.GetMenuItems().GetFirst();
0fe5e8fe
VZ
1862 node;
1863 node = node->GetNext() )
1864 {
1865 // height of this item
1866 wxCoord h;
1867
1868 wxMenuItem *item = node->GetData();
1869 if ( item->IsSeparator() )
1870 {
1871 h = MENU_SEPARATOR_HEIGHT;
1872 }
1873 else // not separator
1874 {
1875 h = heightText;
1876
1877 wxCoord widthLabel;
1878 dc.GetTextExtent(item->GetLabel(), &widthLabel, NULL);
1879 if ( widthLabel > widthLabelMax )
1880 {
1881 widthLabelMax = widthLabel;
1882 }
1883
1884 wxCoord widthAccel;
1885 dc.GetTextExtent(item->GetAccelString(), &widthAccel, NULL);
1886 if ( widthAccel > widthAccelMax )
1887 {
1888 widthAccelMax = widthAccel;
1889 }
1890
1891 const wxBitmap& bmp = item->GetBitmap();
1892 if ( bmp.Ok() )
1893 {
1894 wxCoord widthBmp = bmp.GetWidth();
1895 if ( widthBmp > widthBmpMax )
1896 widthBmpMax = widthBmp;
1897 }
1898 //else if ( item->IsCheckable() ): no need to check for this as
1899 // MENU_LEFT_MARGIN is big enough to show the check mark
1900 }
1901
1902 h += 2*MENU_VERT_MARGIN;
1903
1904 // remember the item position and height
1905 item->SetGeometry(height, h);
1906
1907 height += h;
1908 }
1909
1910 // bundle the metrics into a struct and return it
1911 wxGTKMenuGeometryInfo *gi = new wxGTKMenuGeometryInfo;
1912
1913 gi->m_ofsLabel = widthBmpMax + 2*MENU_BMP_MARGIN;
1914 gi->m_ofsAccel = gi->m_ofsLabel + widthLabelMax;
1915 if ( widthAccelMax > 0 )
1916 {
1917 // if we actually have any accesl, add a margin
1918 gi->m_ofsAccel += MENU_ACCEL_MARGIN;
1919 }
1920
1921 gi->m_heightItem = heightText + 2*MENU_VERT_MARGIN;
1922
1923 gi->m_size.x = gi->m_ofsAccel + widthAccelMax + MENU_RIGHT_MARGIN;
1924 gi->m_size.y = height;
1e6feb95 1925
0fe5e8fe 1926 return gi;
1e6feb95 1927}
71e03035 1928
9a6384ca
WS
1929#endif // wxUSE_MENUS
1930
1931#if wxUSE_STATUSBAR
1932
71e03035
VZ
1933// ----------------------------------------------------------------------------
1934// status bar
1935// ----------------------------------------------------------------------------
1936
61fef19b
VZ
1937wxSize
1938wxGTKRenderer::GetStatusBarBorders(wxCoord * WXUNUSED(borderBetweenFields)) const
71e03035 1939{
c47addef 1940 return wxSize(0,0);
71e03035
VZ
1941}
1942
61fef19b
VZ
1943void wxGTKRenderer::DrawStatusField(wxDC& WXUNUSED(dc),
1944 const wxRect& WXUNUSED(rect),
1945 const wxString& WXUNUSED(label),
c2919ab3 1946 int WXUNUSED(flags), int WXUNUSED(style))
71e03035
VZ
1947{
1948}
1b488c0e 1949
9a6384ca
WS
1950#endif // wxUSE_STATUSBAR
1951
1e6feb95
VZ
1952// ----------------------------------------------------------------------------
1953// combobox
1954// ----------------------------------------------------------------------------
1955
1b488c0e
VZ
1956void wxGTKRenderer::InitComboBitmaps()
1957{
1958 wxSize sizeArrow = m_sizeScrollbarArrow;
1959 sizeArrow.x -= 2;
1960 sizeArrow.y -= 2;
1961
1962 size_t n;
1963
1964 for ( n = ComboState_Normal; n < ComboState_Max; n++ )
1965 {
1966 m_bitmapsCombo[n].Create(sizeArrow.x, sizeArrow.y);
1967 }
1968
1969 static const int comboButtonFlags[ComboState_Max] =
1970 {
1971 0,
1972 wxCONTROL_CURRENT,
1973 wxCONTROL_PRESSED,
1974 wxCONTROL_DISABLED,
1975 };
1976
8d8fbb9d 1977 wxRect rect(sizeArrow);
1b488c0e
VZ
1978
1979 wxMemoryDC dc;
1980 for ( n = ComboState_Normal; n < ComboState_Max; n++ )
1981 {
1982 int flags = comboButtonFlags[n];
1983
1984 dc.SelectObject(m_bitmapsCombo[n]);
147b8a4a 1985 DrawSolidRect(dc, GetBackgroundColour(flags), rect);
1b488c0e
VZ
1986 DrawArrow(dc, wxDOWN, rect, flags);
1987 }
1988}
1989
1e6feb95 1990void wxGTKRenderer::GetComboBitmaps(wxBitmap *bmpNormal,
1b488c0e 1991 wxBitmap *bmpFocus,
1e6feb95
VZ
1992 wxBitmap *bmpPressed,
1993 wxBitmap *bmpDisabled)
1994{
1b488c0e
VZ
1995 if ( !m_bitmapsCombo[ComboState_Normal].Ok() )
1996 {
1997 InitComboBitmaps();
1998 }
1999
2000 if ( bmpNormal )
2001 *bmpNormal = m_bitmapsCombo[ComboState_Normal];
2002 if ( bmpFocus )
2003 *bmpFocus = m_bitmapsCombo[ComboState_Focus];
2004 if ( bmpPressed )
2005 *bmpPressed = m_bitmapsCombo[ComboState_Pressed];
2006 if ( bmpDisabled )
2007 *bmpDisabled = m_bitmapsCombo[ComboState_Disabled];
1e6feb95
VZ
2008}
2009
1e6feb95
VZ
2010// ----------------------------------------------------------------------------
2011// scrollbar
2012// ----------------------------------------------------------------------------
2013
2014void wxGTKRenderer::DrawArrowBorder(wxDC& dc,
2015 wxRect *rect,
2016 wxDirection dir)
2017{
2018 static const wxDirection sides[] =
2019 {
2020 wxUP, wxLEFT, wxRIGHT, wxDOWN
2021 };
2022
2023 wxRect rect1, rect2, rectInner;
2024 rect1 =
2025 rect2 =
2026 rectInner = *rect;
2027
2028 rect2.Inflate(-1);
2029 rectInner.Inflate(-2);
2030
147b8a4a 2031 DrawSolidRect(dc, wxSCHEME_COLOUR(m_scheme, SCROLLBAR), *rect);
1e6feb95
VZ
2032
2033 // find the side not to draw and also adjust the rectangles to compensate
2034 // for it
2035 wxDirection sideToOmit;
2036 switch ( dir )
2037 {
2038 case wxUP:
2039 sideToOmit = wxDOWN;
2040 rect2.height += 1;
2041 rectInner.height += 1;
2042 break;
2043
2044 case wxDOWN:
2045 sideToOmit = wxUP;
2046 rect2.y -= 1;
2047 rect2.height += 1;
2048 rectInner.y -= 2;
2049 rectInner.height += 1;
2050 break;
2051
2052 case wxLEFT:
2053 sideToOmit = wxRIGHT;
2054 rect2.width += 1;
2055 rectInner.width += 1;
2056 break;
2057
2058 case wxRIGHT:
2059 sideToOmit = wxLEFT;
2060 rect2.x -= 1;
2061 rect2.width += 1;
2062 rectInner.x -= 2;
2063 rectInner.width += 1;
2064 break;
2065
2066 default:
2067 wxFAIL_MSG(_T("unknown arrow direction"));
2068 return;
2069 }
2070
2071 // the outer rect first
2072 size_t n;
2073 for ( n = 0; n < WXSIZEOF(sides); n++ )
2074 {
2075 wxDirection side = sides[n];
2076 if ( side == sideToOmit )
2077 continue;
2078
2079 DrawAntiShadedRectSide(dc, rect1, m_penDarkGrey, m_penHighlight, side);
2080 }
2081
2082 // and then the inner one
2083 for ( n = 0; n < WXSIZEOF(sides); n++ )
2084 {
2085 wxDirection side = sides[n];
2086 if ( side == sideToOmit )
2087 continue;
2088
2089 DrawAntiShadedRectSide(dc, rect2, m_penBlack, m_penGrey, side);
2090 }
2091
2092 *rect = rectInner;
2093}
2094
2095void wxGTKRenderer::DrawScrollbarArrow(wxDC& dc,
2096 wxDirection dir,
2097 const wxRect& rectArrow,
2098 int flags)
2099{
2100 // first of all, draw the border around it - but we don't want the border
2101 // on the side opposite to the arrow point
2102 wxRect rect = rectArrow;
2103 DrawArrowBorder(dc, &rect, dir);
2104
2105 // then the arrow itself
2106 DrawArrow(dc, dir, rect, flags);
2107}
2108
2109// gtk_default_draw_arrow() takes ~350 lines and we can't do much better here
2110// these people are just crazy :-(
2111void wxGTKRenderer::DrawArrow(wxDC& dc,
2112 wxDirection dir,
2113 const wxRect& rect,
2114 int flags)
2115{
2116 enum
2117 {
2118 Point_First,
2119 Point_Second,
2120 Point_Third,
2121 Point_Max
2122 };
2123
2124 wxPoint ptArrow[Point_Max];
2125
2126 wxColour colInside = GetBackgroundColour(flags);
2127 wxPen penShadow[4];
2128 if ( flags & wxCONTROL_DISABLED )
2129 {
2130 penShadow[0] = m_penDarkGrey;
2131 penShadow[1] = m_penDarkGrey;
2132 penShadow[2] = wxNullPen;
2133 penShadow[3] = wxNullPen;
2134 }
2135 else if ( flags & wxCONTROL_PRESSED )
2136 {
2137 penShadow[0] = m_penDarkGrey;
2138 penShadow[1] = m_penHighlight;
2139 penShadow[2] = wxNullPen;
2140 penShadow[3] = m_penBlack;
2141 }
2142 else // normal arrow
2143 {
2144 penShadow[0] = m_penHighlight;
2145 penShadow[1] = m_penBlack;
2146 penShadow[2] = m_penDarkGrey;
2147 penShadow[3] = wxNullPen;
2148 }
2149
2150 wxCoord middle;
2151 if ( dir == wxUP || dir == wxDOWN )
2152 {
2153 // horz middle
2154 middle = (rect.GetRight() + rect.GetLeft() + 1) / 2;
2155 }
2156 else // horz arrow
2157 {
2158 middle = (rect.GetTop() + rect.GetBottom() + 1) / 2;
2159 }
2160
2161 // draw the arrow interior
2162 dc.SetPen(*wxTRANSPARENT_PEN);
147b8a4a 2163 dc.SetBrush(colInside);
1e6feb95
VZ
2164
2165 switch ( dir )
2166 {
2167 case wxUP:
2168 ptArrow[Point_First].x = rect.GetLeft();
2169 ptArrow[Point_First].y = rect.GetBottom();
2170 ptArrow[Point_Second].x = middle;
2171 ptArrow[Point_Second].y = rect.GetTop();
2172 ptArrow[Point_Third].x = rect.GetRight();
2173 ptArrow[Point_Third].y = rect.GetBottom();
2174 break;
2175
2176 case wxDOWN:
2177 ptArrow[Point_First] = rect.GetPosition();
2178 ptArrow[Point_Second].x = middle;
2179 ptArrow[Point_Second].y = rect.GetBottom();
2180 ptArrow[Point_Third].x = rect.GetRight();
2181 ptArrow[Point_Third].y = rect.GetTop();
2182 break;
2183
2184 case wxLEFT:
2185 ptArrow[Point_First].x = rect.GetRight();
2186 ptArrow[Point_First].y = rect.GetTop();
2187 ptArrow[Point_Second].x = rect.GetLeft();
2188 ptArrow[Point_Second].y = middle;
2189 ptArrow[Point_Third].x = rect.GetRight();
2190 ptArrow[Point_Third].y = rect.GetBottom();
2191 break;
2192
2193 case wxRIGHT:
2194 ptArrow[Point_First] = rect.GetPosition();
2195 ptArrow[Point_Second].x = rect.GetRight();
2196 ptArrow[Point_Second].y = middle;
2197 ptArrow[Point_Third].x = rect.GetLeft();
2198 ptArrow[Point_Third].y = rect.GetBottom();
2199 break;
2200
2201 default:
2202 wxFAIL_MSG(_T("unknown arrow direction"));
2203 }
2204
2205 dc.DrawPolygon(WXSIZEOF(ptArrow), ptArrow);
2206
2207 // draw the arrow border
2208 dc.SetPen(penShadow[0]);
2209 switch ( dir )
2210 {
2211 case wxUP:
2212 dc.DrawLine(ptArrow[Point_Second], ptArrow[Point_First]);
2213 dc.DrawPoint(ptArrow[Point_First]);
2214 if ( penShadow[3].Ok() )
2215 {
2216 dc.SetPen(penShadow[3]);
2217 dc.DrawLine(ptArrow[Point_First].x + 1, ptArrow[Point_First].y,
2218 ptArrow[Point_Second].x, ptArrow[Point_Second].y);
2219 }
2220 dc.SetPen(penShadow[1]);
2221 dc.DrawLine(ptArrow[Point_Second].x + 1, ptArrow[Point_Second].y + 1,
2222 ptArrow[Point_Third].x, ptArrow[Point_Third].y);
2223 dc.DrawPoint(ptArrow[Point_Third]);
2224 dc.DrawLine(ptArrow[Point_Third].x - 2, ptArrow[Point_Third].y,
2225 ptArrow[Point_First].x + 1, ptArrow[Point_First].y);
2226 if ( penShadow[2].Ok() )
2227 {
2228 dc.SetPen(penShadow[2]);
2229 dc.DrawLine(ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y,
2230 ptArrow[Point_Second].x, ptArrow[Point_Second].y + 1);
2231 dc.DrawLine(ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y - 1,
2232 ptArrow[Point_First].x + 2, ptArrow[Point_First].y - 1);
2233 }
2234 break;
2235
2236 case wxDOWN:
2237 dc.DrawLine(ptArrow[Point_First], ptArrow[Point_Second]);
2238 dc.DrawLine(ptArrow[Point_First].x + 2, ptArrow[Point_First].y,
2239 ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y);
2240 if ( penShadow[2].Ok() )
2241 {
2242 dc.SetPen(penShadow[2]);
2243 dc.DrawLine(ptArrow[Point_Second].x, ptArrow[Point_Second].y - 1,
2244 ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y - 1);
2245 }
2246 dc.SetPen(penShadow[1]);
2247 dc.DrawLine(ptArrow[Point_Second], ptArrow[Point_Third]);
2248 dc.DrawPoint(ptArrow[Point_Third]);
2249 break;
2250
2251 case wxLEFT:
2252 dc.DrawLine(ptArrow[Point_Second], ptArrow[Point_First]);
2253 dc.DrawPoint(ptArrow[Point_First]);
2254 if ( penShadow[2].Ok() )
2255 {
2256 dc.SetPen(penShadow[2]);
2257 dc.DrawLine(ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y,
2258 ptArrow[Point_First].x - 1, ptArrow[Point_First].y + 2);
2259 dc.DrawLine(ptArrow[Point_Third].x, ptArrow[Point_Third].y,
2260 ptArrow[Point_Second].x + 2, ptArrow[Point_Second].y + 1);
2261 }
2262 dc.SetPen(penShadow[1]);
2263 dc.DrawLine(ptArrow[Point_Third].x, ptArrow[Point_Third].y,
2264 ptArrow[Point_First].x, ptArrow[Point_First].y + 1);
2265 dc.DrawLine(ptArrow[Point_Second].x + 1, ptArrow[Point_Second].y + 1,
2266 ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y);
2267 break;
2268
2269 case wxRIGHT:
2270 dc.DrawLine(ptArrow[Point_First], ptArrow[Point_Third]);
2271 dc.DrawLine(ptArrow[Point_First].x + 2, ptArrow[Point_First].y + 1,
2272 ptArrow[Point_Second].x, ptArrow[Point_Second].y);
2273 dc.SetPen(penShadow[1]);
2274 dc.DrawLine(ptArrow[Point_Second], ptArrow[Point_Third]);
2275 dc.DrawPoint(ptArrow[Point_Third]);
2276 break;
2277
2278 default:
2279 wxFAIL_MSG(_T("unknown arrow direction"));
2280 return;
2281 }
2282}
2283
2284void wxGTKRenderer::DrawThumbBorder(wxDC& dc,
2285 wxRect *rect,
2286 wxOrientation orient)
2287{
2288 if ( orient == wxVERTICAL )
2289 {
2290 DrawAntiShadedRectSide(dc, *rect, m_penDarkGrey, m_penHighlight,
2291 wxLEFT);
2292 DrawAntiShadedRectSide(dc, *rect, m_penDarkGrey, m_penHighlight,
2293 wxRIGHT);
2294 rect->Inflate(-1, 0);
2295
2296 DrawAntiShadedRectSide(dc, *rect, m_penBlack, m_penGrey,
2297 wxLEFT);
2298 DrawAntiShadedRectSide(dc, *rect, m_penBlack, m_penGrey,
2299 wxRIGHT);
2300 rect->Inflate(-1, 0);
2301 }
2302 else
2303 {
2304 DrawAntiShadedRectSide(dc, *rect, m_penDarkGrey, m_penHighlight,
2305 wxUP);
2306 DrawAntiShadedRectSide(dc, *rect, m_penDarkGrey, m_penHighlight,
2307 wxDOWN);
2308 rect->Inflate(0, -1);
2309
2310 DrawAntiShadedRectSide(dc, *rect, m_penBlack, m_penGrey,
2311 wxUP);
2312 DrawAntiShadedRectSide(dc, *rect, m_penBlack, m_penGrey,
2313 wxDOWN);
2314 rect->Inflate(0, -1);
2315 }
2316}
2317
2318void wxGTKRenderer::DrawScrollbarThumb(wxDC& dc,
2319 wxOrientation orient,
2320 const wxRect& rect,
2321 int flags)
2322{
2323 // the thumb is never pressed never has focus border under GTK and the
2324 // scrollbar background never changes at all
2325 int flagsThumb = flags & ~(wxCONTROL_PRESSED | wxCONTROL_FOCUSED);
2326
2327 // we don't want the border in the direction of the scrollbar movement
2328 wxRect rectThumb = rect;
2329 DrawThumbBorder(dc, &rectThumb, orient);
2330
2331 DrawButtonBorder(dc, rectThumb, flagsThumb, &rectThumb);
2332 DrawBackground(dc, wxNullColour, rectThumb, flagsThumb);
2333}
2334
2335void wxGTKRenderer::DrawScrollbarShaft(wxDC& dc,
2336 wxOrientation orient,
2337 const wxRect& rect,
61fef19b 2338 int WXUNUSED(flags))
1e6feb95
VZ
2339{
2340 wxRect rectBar = rect;
2341 DrawThumbBorder(dc, &rectBar, orient);
147b8a4a 2342 DrawSolidRect(dc, wxSCHEME_COLOUR(m_scheme, SCROLLBAR), rectBar);
1e6feb95
VZ
2343}
2344
2345void wxGTKRenderer::DrawScrollCorner(wxDC& dc, const wxRect& rect)
2346{
147b8a4a 2347 DrawSolidRect(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rect);
1e6feb95
VZ
2348}
2349
9a6384ca 2350#if wxUSE_SCROLLBAR
1e6feb95
VZ
2351wxRect wxGTKRenderer::GetScrollbarRect(const wxScrollBar *scrollbar,
2352 wxScrollBar::Element elem,
2353 int thumbPos) const
2354{
2355 // as GTK scrollbars can't be disabled, it makes no sense to remove the
2356 // thumb for a scrollbar with range 0 - instead, make it fill the entire
2357 // scrollbar shaft
2358 if ( (elem == wxScrollBar::Element_Thumb) && !scrollbar->GetRange() )
2359 {
2360 elem = wxScrollBar::Element_Bar_2;
2361 }
2362
147b8a4a 2363 return wxStdRenderer::GetScrollbarRect(scrollbar, elem, thumbPos);
1e6feb95
VZ
2364}
2365
9a6384ca 2366#endif // wxUSE_SCROLLBAR
1e6feb95
VZ
2367
2368// ----------------------------------------------------------------------------
2369// size adjustments
2370// ----------------------------------------------------------------------------
2371
2372void wxGTKRenderer::AdjustSize(wxSize *size, const wxWindow *window)
2373{
e4606ed9
VZ
2374#if wxUSE_BMPBUTTON
2375 if ( wxDynamicCast(window, wxBitmapButton) )
2376 {
2377 size->x += 4;
2378 size->y += 4;
2379 } else
2380#endif // wxUSE_BMPBUTTON
43be3c33 2381#if wxUSE_BUTTON || wxUSE_TOGGLEBTN
370efbe7 2382 if ( 0
43be3c33 2383# if wxUSE_BUTTON
370efbe7 2384 || wxDynamicCast(window, wxButton)
43be3c33
JS
2385# endif // wxUSE_BUTTON
2386# if wxUSE_TOGGLEBTN
370efbe7 2387 || wxDynamicCast(window, wxToggleButton)
43be3c33
JS
2388# endif // wxUSE_TOGGLEBTN
2389 )
1e6feb95 2390 {
1b465102
VZ
2391 if ( !(window->GetWindowStyle() & wxBU_EXACTFIT) )
2392 {
2393 // TODO: this is ad hoc...
2394 size->x += 3*window->GetCharWidth();
2395 wxCoord minBtnHeight = 18;
2396 if ( size->y < minBtnHeight )
2397 size->y = minBtnHeight;
2398
2399 // button border width
2400 size->y += 4;
2401 }
e4606ed9 2402 } else
43be3c33 2403#endif // wxUSE_BUTTON || wxUSE_TOGGLEBTN
9a6384ca 2404#if wxUSE_SCROLLBAR
e4606ed9 2405 if ( wxDynamicCast(window, wxScrollBar) )
1e6feb95
VZ
2406 {
2407 // we only set the width of vert scrollbars and height of the
2408 // horizontal ones
2409 if ( window->GetWindowStyle() & wxSB_HORIZONTAL )
2410 size->y = m_sizeScrollbarArrow.x;
2411 else
2412 size->x = m_sizeScrollbarArrow.x;
2413 }
2414 else
9a6384ca 2415#endif // wxUSE_SCROLLBAR
1e6feb95
VZ
2416 {
2417 // take into account the border width
2418 wxRect rectBorder = GetBorderDimensions(window->GetBorder());
2419 size->x += rectBorder.x + rectBorder.width;
2420 size->y += rectBorder.y + rectBorder.height;
2421 }
2422}
2423
24a23c35
VS
2424// ----------------------------------------------------------------------------
2425// top level windows
2426// ----------------------------------------------------------------------------
2427
61fef19b
VZ
2428void wxGTKRenderer::DrawFrameTitleBar(wxDC& WXUNUSED(dc),
2429 const wxRect& WXUNUSED(rect),
2430 const wxString& WXUNUSED(title),
2431 const wxIcon& WXUNUSED(icon),
2432 int WXUNUSED(flags),
2433 int WXUNUSED(specialButton),
2434 int WXUNUSED(specialButtonFlag))
24a23c35
VS
2435{
2436}
2437
61fef19b
VZ
2438void wxGTKRenderer::DrawFrameBorder(wxDC& WXUNUSED(dc),
2439 const wxRect& WXUNUSED(rect),
2440 int WXUNUSED(flags))
24a23c35
VS
2441{
2442}
2443
61fef19b
VZ
2444void wxGTKRenderer::DrawFrameBackground(wxDC& WXUNUSED(dc),
2445 const wxRect& WXUNUSED(rect),
2446 int WXUNUSED(flags))
24a23c35
VS
2447{
2448}
2449
61fef19b
VZ
2450void wxGTKRenderer::DrawFrameTitle(wxDC& WXUNUSED(dc),
2451 const wxRect& WXUNUSED(rect),
2452 const wxString& WXUNUSED(title),
2453 int WXUNUSED(flags))
24a23c35
VS
2454{
2455}
2456
61fef19b
VZ
2457void wxGTKRenderer::DrawFrameIcon(wxDC& WXUNUSED(dc),
2458 const wxRect& WXUNUSED(rect),
2459 const wxIcon& WXUNUSED(icon),
2460 int WXUNUSED(flags))
24a23c35
VS
2461{
2462}
2463
61fef19b
VZ
2464void wxGTKRenderer::DrawFrameButton(wxDC& WXUNUSED(dc),
2465 wxCoord WXUNUSED(x),
2466 wxCoord WXUNUSED(y),
2467 int WXUNUSED(button),
2468 int WXUNUSED(flags))
24a23c35
VS
2469{
2470}
2471
61fef19b
VZ
2472wxRect
2473wxGTKRenderer::GetFrameClientArea(const wxRect& rect,
2474 int WXUNUSED(flags)) const
24a23c35
VS
2475{
2476 return rect;
2477}
2478
61fef19b
VZ
2479wxSize
2480wxGTKRenderer::GetFrameTotalSize(const wxSize& clientSize,
2481 int WXUNUSED(flags)) const
24a23c35
VS
2482{
2483 return clientSize;
2484}
2485
61fef19b 2486wxSize wxGTKRenderer::GetFrameMinSize(int WXUNUSED(flags)) const
e7dda1ff 2487{
c47addef 2488 return wxSize(0,0);
e7dda1ff
VS
2489}
2490
24a23c35
VS
2491wxSize wxGTKRenderer::GetFrameIconSize() const
2492{
a290fa5a 2493 return wxSize(wxDefaultCoord, wxDefaultCoord);
24a23c35
VS
2494}
2495
61fef19b
VZ
2496int
2497wxGTKRenderer::HitTestFrame(const wxRect& WXUNUSED(rect),
2498 const wxPoint& WXUNUSED(pt),
2499 int WXUNUSED(flags)) const
813edf09
VS
2500{
2501 return wxHT_TOPLEVEL_CLIENT_AREA;
2502}
2503
24a23c35 2504
63f06c22
VS
2505// ----------------------------------------------------------------------------
2506// standard icons
2507// ----------------------------------------------------------------------------
2508
13b22a67 2509/* Copyright (c) Julian Smart */
2b5f62a0 2510static const char *error_xpm[] = {
63f06c22 2511/* columns rows colors chars-per-pixel */
13b22a67
JS
2512"48 48 4 1",
2513" c None",
2514"X c #242424",
2515"o c #DCDF00",
2516". c #C00000",
63f06c22 2517/* pixels */
13b22a67
JS
2518" ",
2519" ",
2520" ",
2521" ",
2522" ",
2523" ..... ",
2524" ............. ",
2525" ................. ",
2526" ................... ",
2527" ....................... ",
2528" ......................... ",
2529" ........................... ",
2530" ...........................X ",
2531" .............................X ",
2532" ............................... ",
2533" ...............................X ",
2534" .................................X ",
2535" .................................X ",
2536" .................................XX ",
2537" ...ooooooooooooooooooooooooooo...XX ",
2538" ....ooooooooooooooooooooooooooo....X ",
2539" ....ooooooooooooooooooooooooooo....X ",
2540" ....ooooooooooooooooooooooooooo....XX ",
2541" ....ooooooooooooooooooooooooooo....XX ",
2542" ....ooooooooooooooooooooooooooo....XX ",
2543" ...ooooooooooooooooooooooooooo...XXX ",
2544" ...ooooooooooooooooooooooooooo...XXX ",
2545" .................................XX ",
2546" .................................XX ",
2547" ...............................XXX ",
2548" ...............................XXX ",
2549" .............................XXX ",
2550" ...........................XXXX ",
2551" ...........................XXX ",
2552" .........................XXX ",
2553" .......................XXXX ",
2554" X...................XXXXX ",
2555" X.................XXXXX ",
2556" X.............XXXXX ",
2557" XXXX.....XXXXXXXX ",
2558" XXXXXXXXXXXXX ",
2559" XXXXX ",
2560" ",
2561" ",
2562" ",
2563" ",
2564" ",
2565" "
63f06c22
VS
2566};
2567
13b22a67 2568/* Copyright (c) Julian Smart */
2b5f62a0 2569static const char *info_xpm[] = {
63f06c22 2570/* columns rows colors chars-per-pixel */
13b22a67
JS
2571"48 48 9 1",
2572"$ c Black",
2573"O c #FFFFFF",
2574"@ c #808080",
2575"+ c #000080",
2576"o c #E8EB01",
2577" c None",
2578"X c #FFFF40",
2579"# c #C0C0C0",
2580". c #ABAD01",
63f06c22 2581/* pixels */
13b22a67
JS
2582" ",
2583" ",
2584" ",
2585" ",
2586" ",
2587" ",
2588" ",
2589" ",
2590" ",
2591" ..... ",
2592" ..XXXXX.. ",
2593" ..XXXXXXXXo.. ",
2594" .XXXOXXXXXXXoo. ",
2595" .XOOXXX+XXXXXo. ",
2596" .XOOOXX+++XXXXoo. ",
2597" .XOOXXX+++XXXXXo. ",
2598" .XOOOXXX+++XXXXXXo. ",
2599" .XOOXXXX+++XXXXXXo. ",
2600" .XXXXXXX+++XXXXXXX. ",
2601" .XXXXXXX+++XXXXXXo. ",
2602" .XXXXXXX+++XXXXXoo. ",
2603" .XXXXXX+++XXXXXo. ",
2604" .XXXXXXX+XXXXXXo. ",
2605" .XXXXXXXXXXXXo. ",
2606" .XXXXX+++XXXoo. ",
2607" .XXXX+++XXoo. ",
2608" .XXXXXXXXo. ",
2609" ..XXXXXXo.. ",
2610" .XXXXXo.. ",
2611" @#######@ ",
2612" @@@@@@@@@ ",
2613" @#######@ ",
2614" @@@@@@@@@ ",
2615" @#######@ ",
2616" @@@@@@@ ",
2617" ### ",
2618" $$$ ",
2619" ",
2620" ",
2621" ",
2622" ",
2623" ",
2624" ",
2625" ",
2626" ",
2627" ",
2628" ",
2629" "
63f06c22
VS
2630};
2631
13b22a67 2632/* Copyright (c) Julian Smart */
2b5f62a0 2633static const char *warning_xpm[] = {
63f06c22 2634/* columns rows colors chars-per-pixel */
13b22a67
JS
2635"48 48 9 1",
2636"@ c Black",
2637"o c #A6A800",
2638"+ c #8A8C00",
2639"$ c #B8BA00",
2640" c None",
2641"O c #6E7000",
2642"X c #DCDF00",
2643". c #C00000",
2644"# c #373800",
63f06c22 2645/* pixels */
13b22a67
JS
2646" ",
2647" ",
2648" ",
2649" ",
2650" ",
2651" ",
2652" ",
2653" . ",
2654" ... ",
2655" ... ",
2656" ..... ",
2657" ...X.. ",
2658" ..XXX.. ",
2659" ...XXX... ",
2660" ..XXXXX.. ",
2661" ..XXXXXX... ",
2662" ...XXoO+XX.. ",
2663" ..XXXO@#XXX.. ",
2664" ..XXXXO@#XXX... ",
2665" ...XXXXO@#XXXX.. ",
2666" ..XXXXXO@#XXXX... ",
2667" ...XXXXXo@OXXXXX.. ",
2668" ...XXXXXXo@OXXXXXX.. ",
2669" ..XXXXXXX$@OXXXXXX... ",
2670" ...XXXXXXXX@XXXXXXXX.. ",
2671" ...XXXXXXXXXXXXXXXXXX... ",
2672" ..XXXXXXXXXXOXXXXXXXXX.. ",
2673" ...XXXXXXXXXO@#XXXXXXXXX.. ",
2674" ..XXXXXXXXXXX#XXXXXXXXXX... ",
2675" ...XXXXXXXXXXXXXXXXXXXXXXX.. ",
2676" ...XXXXXXXXXXXXXXXXXXXXXXXX... ",
2677" .............................. ",
2678" .............................. ",
2679" ",
2680" ",
2681" ",
2682" ",
2683" ",
2684" ",
2685" ",
2686" ",
2687" ",
2688" ",
2689" ",
2690" ",
2691" ",
2692" ",
2693" "
63f06c22
VS
2694};
2695
13b22a67 2696/* Copyright (c) Julian Smart */
2b5f62a0 2697static const char *question_xpm[] = {
63f06c22 2698/* columns rows colors chars-per-pixel */
13b22a67
JS
2699"48 48 21 1",
2700". c Black",
2701"> c #696969",
2702"O c #1F1F00",
2703"+ c #181818",
2704"o c #F6F900",
2705"; c #3F3F00",
2706"$ c #111111",
2707" c None",
2708"& c #202020",
2709"X c #AAAA00",
2710"@ c #949400",
2711": c #303030",
2712"1 c #383838",
2713"% c #2A2A00",
2714", c #404040",
2715"= c #B4B400",
2716"- c #484848",
2717"# c #151500",
2718"< c #9F9F00",
2719"2 c #6A6A00",
2720"* c #353500",
63f06c22 2721/* pixels */
13b22a67
JS
2722" ",
2723" ",
2724" ",
2725" ",
2726" ......... ",
2727" ...XXXXXXX.. ",
2728" ..XXXXoooooXXXO+ ",
2729" ..XXooooooooooooX@.. ",
2730" ..XoooooooooooooooXX#. ",
2731" $%XoooooooooooooooooXX#. ",
2732" &.XoooooooXXXXXXooooooXX.. ",
2733" .XooooooXX.$...$XXoooooX*. ",
2734" $.XoooooX%.$ .*oooooo=.. ",
2735" .XooooooX.. -.XoooooX.. ",
2736" .XoooooX..+ .XoooooX;. ",
2737" ...XXXX..: .XoooooX;. ",
2738" ........ >.XoooooX;. ",
2739" +.XoooooX.. ",
2740" ,.Xoooooo<.. ",
2741" 1#XooooooXO.. ",
2742" &#XooooooX2.. ",
2743" $%XooooooXX.. ",
2744" $%XooooooXX.. ",
2745" $%XooooooXX.. ",
2746" &.XooooooXX.. ",
2747" .XooooooXX.. ",
2748" &.XoooooXX.. ",
2749" ..XooooXX.. ",
2750" ..XooooX... ",
2751" ..XXooXX..& ",
2752" ...XXXXX.. ",
2753" ........ ",
2754" ",
2755" ",
2756" ....... ",
2757" ..XXXXX.. ",
2758" ..XXoooXX.. ",
2759" ..XoooooX.. ",
2760" ..XoooooX.. ",
2761" ..XXoooXX.. ",
2762" ..XXXXX.. ",
2763" ....... ",
2764" ",
2765" ",
2766" ",
2767" ",
2768" ",
2769" "
63f06c22
VS
2770};
2771
536b70ac
VS
2772wxBitmap wxGTKArtProvider::CreateBitmap(const wxArtID& id,
2773 const wxArtClient& WXUNUSED(client),
2774 const wxSize& WXUNUSED(size))
63f06c22 2775{
536b70ac
VS
2776 if ( id == wxART_INFORMATION )
2777 return wxBitmap(info_xpm);
2778 if ( id == wxART_ERROR )
2779 return wxBitmap(error_xpm);
2780 if ( id == wxART_WARNING )
2781 return wxBitmap(warning_xpm);
2782 if ( id == wxART_QUESTION )
2783 return wxBitmap(question_xpm);
2784 return wxNullBitmap;
63f06c22
VS
2785}
2786
24a23c35 2787
1e6feb95
VZ
2788// ============================================================================
2789// wxInputHandler
2790// ============================================================================
2791
2792// ----------------------------------------------------------------------------
2793// wxGTKInputHandler
2794// ----------------------------------------------------------------------------
2795
61fef19b
VZ
2796bool wxGTKInputHandler::HandleKey(wxInputConsumer * WXUNUSED(control),
2797 const wxKeyEvent& WXUNUSED(event),
2798 bool WXUNUSED(pressed))
1e6feb95 2799{
a290fa5a 2800 return false;
1e6feb95
VZ
2801}
2802
67e49a98 2803bool wxGTKInputHandler::HandleMouse(wxInputConsumer *control,
1e6feb95
VZ
2804 const wxMouseEvent& event)
2805{
2806 // clicking on the control gives it focus
67e49a98 2807 if ( event.ButtonDown() && wxWindow::FindFocus() != control->GetInputWindow() )
1e6feb95 2808 {
67e49a98 2809 control->GetInputWindow()->SetFocus();
1e6feb95 2810
a290fa5a 2811 return true;
1e6feb95
VZ
2812 }
2813
a290fa5a 2814 return false;
1e6feb95
VZ
2815}
2816
67e49a98 2817bool wxGTKInputHandler::HandleMouseMove(wxInputConsumer *control,
1e6feb95
VZ
2818 const wxMouseEvent& event)
2819{
2820 if ( event.Entering() )
2821 {
a290fa5a 2822 control->GetInputWindow()->SetCurrent(true);
1e6feb95
VZ
2823 }
2824 else if ( event.Leaving() )
2825 {
a290fa5a 2826 control->GetInputWindow()->SetCurrent(false);
1e6feb95
VZ
2827 }
2828 else
2829 {
a290fa5a 2830 return false;
1e6feb95
VZ
2831 }
2832
a290fa5a 2833 return true;
1e6feb95
VZ
2834}
2835
9a6384ca
WS
2836#if wxUSE_CHECKBOX
2837
1e6feb95
VZ
2838// ----------------------------------------------------------------------------
2839// wxGTKCheckboxInputHandler
2840// ----------------------------------------------------------------------------
2841
67e49a98 2842bool wxGTKCheckboxInputHandler::HandleKey(wxInputConsumer *control,
1e6feb95
VZ
2843 const wxKeyEvent& event,
2844 bool pressed)
2845{
2846 if ( pressed )
2847 {
2848 int keycode = event.GetKeyCode();
2849 if ( keycode == WXK_SPACE || keycode == WXK_RETURN )
2850 {
2851 control->PerformAction(wxACTION_CHECKBOX_TOGGLE);
2852
a290fa5a 2853 return true;
1e6feb95
VZ
2854 }
2855 }
2856
a290fa5a 2857 return false;
1e6feb95
VZ
2858}
2859
9a6384ca
WS
2860#endif // wxUSE_CHECKBOX
2861
2862#if wxUSE_TEXTCTRL
2863
1e6feb95
VZ
2864// ----------------------------------------------------------------------------
2865// wxGTKTextCtrlInputHandler
2866// ----------------------------------------------------------------------------
2867
67e49a98 2868bool wxGTKTextCtrlInputHandler::HandleKey(wxInputConsumer *control,
1e6feb95
VZ
2869 const wxKeyEvent& event,
2870 bool pressed)
2871{
2872 // handle only GTK-specific text bindings here, the others are handled in
2873 // the base class
2874 if ( pressed )
2875 {
2876 wxControlAction action;
2877 int keycode = event.GetKeyCode();
2878 if ( event.ControlDown() )
2879 {
2880 switch ( keycode )
2881 {
2882 case 'A':
2883 action = wxACTION_TEXT_HOME;
2884 break;
2885
2886 case 'B':
2887 action = wxACTION_TEXT_LEFT;
2888 break;
2889
2890 case 'D':
2891 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_RIGHT;
2892 break;
2893
2894 case 'E':
2895 action = wxACTION_TEXT_END;
2896 break;
2897
2898 case 'F':
2899 action = wxACTION_TEXT_RIGHT;
2900 break;
2901
2902 case 'H':
2903 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_LEFT;
2904 break;
2905
2906 case 'K':
2907 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_END;
2908 break;
2909
2910 case 'N':
2911 action = wxACTION_TEXT_DOWN;
2912 break;
2913
2914 case 'P':
2915 action = wxACTION_TEXT_UP;
2916 break;
2917
2918 case 'U':
2919 //delete the entire line
2920 control->PerformAction(wxACTION_TEXT_HOME);
2921 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_END;
2922 break;
2923
2924 case 'W':
2925 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_WORD_LEFT;
2926 break;
2927 }
2928 }
2929 else if ( event.AltDown() )
2930 {
2931 switch ( keycode )
2932 {
2933 case 'B':
2934 action = wxACTION_TEXT_WORD_LEFT;
2935 break;
2936
2937 case 'D':
2938 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_WORD_RIGHT;
2939 break;
2940
2941 case 'F':
2942 action = wxACTION_TEXT_WORD_RIGHT;
2943 break;
2944 }
2945 }
2946
2947 if ( action != wxACTION_NONE )
2948 {
2949 control->PerformAction(action);
2950
a290fa5a 2951 return true;
1e6feb95
VZ
2952 }
2953 }
2954
9467bdb7 2955 return wxStdInputHandler::HandleKey(control, event, pressed);
1e6feb95 2956}
9a6384ca
WS
2957
2958#endif // wxUSE_TEXTCTRL