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