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