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