]> git.saurik.com Git - wxWidgets.git/blame - src/univ/themes/gtk.cpp
fixed another typo in pen/brush style validation
[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
VZ
86 // wxRenderer methods
87 virtual void DrawFocusRect(wxDC& dc, const wxRect& rect);
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
147b8a4a 837void wxGTKRenderer::DrawFocusRect(wxDC& dc, const wxRect& rect)
1e6feb95 838{
147b8a4a
VZ
839 dc.SetBrush(*wxTRANSPARENT_BRUSH);
840 wxRect rectFocus = rect;
841 DrawRect(dc, &rectFocus, m_penBlack);
1e6feb95
VZ
842}
843
1e6feb95
VZ
844void wxGTKRenderer::DrawTextBorder(wxDC& dc,
845 wxBorder border,
846 const wxRect& rectOrig,
847 int flags,
848 wxRect *rectIn)
849{
850 wxRect rect = rectOrig;
851
89e7a223 852 if ( border != wxBORDER_NONE )
1e6feb95 853 {
e4606ed9
VZ
854 if ( flags & wxCONTROL_FOCUSED )
855 {
856 DrawRect(dc, &rect, m_penBlack);
857 DrawAntiShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight);
858 }
859 else // !focused
860 {
147b8a4a 861 DrawInnerShadedRect(dc, &rect);
e4606ed9 862 }
1e6feb95
VZ
863 }
864
865 if ( rectIn )
866 *rectIn = rect;
867}
868
147b8a4a
VZ
869void wxGTKRenderer::DrawButtonLabel(wxDC& dc,
870 const wxString& label,
871 const wxBitmap& image,
872 const wxRect& rect,
873 int flags,
874 int alignment,
875 int indexAccel,
876 wxRect *rectBounds)
877{
878 // no focus rect around buttons label in GTK+
879 wxStdRenderer::DrawButtonLabel(dc, label, image, rect, flags,
880 alignment, indexAccel, rectBounds);
881}
882
1e6feb95
VZ
883void wxGTKRenderer::DrawButtonBorder(wxDC& dc,
884 const wxRect& rectTotal,
885 int flags,
886 wxRect *rectIn)
887{
888 wxRect rect = rectTotal;
889
890 if ( flags & wxCONTROL_PRESSED )
891 {
892 // button pressed: draw a black border around it and an inward shade
893 DrawRect(dc, &rect, m_penBlack);
e4606ed9 894
147b8a4a 895 DrawInnerShadedRect(dc, &rect);
1e6feb95 896 }
147b8a4a 897 else // button not pressed
1e6feb95 898 {
1e6feb95
VZ
899 if ( flags & wxCONTROL_ISDEFAULT )
900 {
901 // TODO
902 }
903
904 if ( flags & wxCONTROL_FOCUSED )
905 {
906 // button is currently default: add an extra border around it
907 DrawRect(dc, &rect, m_penBlack);
908 }
909
910 // now draw a normal button
147b8a4a
VZ
911 DrawShadedRect(dc, &rect, m_penHighlight, m_penBlack);
912 DrawAntiShadedRect(dc, &rect, GetBackgroundColour(flags), m_penDarkGrey);
1e6feb95
VZ
913 }
914
915 if ( rectIn )
1e6feb95 916 *rectIn = rect;
1e6feb95
VZ
917}
918
919// ----------------------------------------------------------------------------
920// lines and frames
921// ----------------------------------------------------------------------------
922
147b8a4a
VZ
923void wxGTKRenderer::DrawFrameWithLabel(wxDC& dc,
924 const wxString& label,
925 const wxRect& rectFrame,
926 const wxRect& rectTextOrig,
927 int flags,
928 int alignment,
929 int indexAccel)
1e6feb95 930{
147b8a4a
VZ
931 wxRect rectText(rectTextOrig);
932 rectText.Inflate(1, 0);
1e6feb95 933
147b8a4a
VZ
934 wxRect rectLabel;
935 DrawLabel(dc, label, rectText, flags, alignment, indexAccel, &rectLabel);
936 rectLabel.x -= 1;
937 rectLabel.width += 2;
1e6feb95 938
147b8a4a 939 DrawFrameWithoutLabel(dc, rectFrame, rectLabel);
1e6feb95 940
147b8a4a
VZ
941 // GTK+ does it like this
942 dc.SetPen(m_penHighlight);
943 dc.DrawPoint(rectText.x, rectFrame.y);
944 dc.DrawPoint(rectText.x + rectLabel.width - 3, rectFrame.y);
1e6feb95
VZ
945}
946
947// ----------------------------------------------------------------------------
6229b92f 948// check/radion buttons
1e6feb95
VZ
949// ----------------------------------------------------------------------------
950
6229b92f
VZ
951void wxGTKRenderer::DrawCheckItemBitmap(wxDC& dc,
952 const wxBitmap& bitmap,
953 const wxRect& rect,
954 int flags)
1e6feb95 955{
1e6feb95 956 // never draw the focus rect around the check indicators here
6229b92f 957 DrawCheckButton(dc, wxEmptyString, bitmap, rect, flags & ~wxCONTROL_FOCUSED);
1e6feb95
VZ
958}
959
415a0ff1
WS
960void wxGTKRenderer::DrawUndeterminedBitmap(wxDC& dc,
961 const wxRect& rectTotal,
962 bool isPressed)
963{
964 // FIXME: For sure it is not GTK look but it is better than nothing.
965 // Show me correct look and I will immediatelly make it better (ABX)
966 wxRect rect = rectTotal;
967
968 wxColour col1, col2;
969
970 if ( isPressed )
971 {
972 col1 = wxSCHEME_COLOUR(m_scheme, SHADOW_DARK);
973 col2 = wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED);
974 }
975 else
976 {
977 col1 = wxSCHEME_COLOUR(m_scheme, SHADOW_DARK);
978 col2 = wxSCHEME_COLOUR(m_scheme, SHADOW_IN);
979 }
980
981 dc.SetPen(*wxTRANSPARENT_PEN);
147b8a4a 982 dc.SetBrush(col1);
415a0ff1
WS
983 dc.DrawRectangle(rect);
984 rect.Deflate(1);
147b8a4a 985 dc.SetBrush(col2);
415a0ff1
WS
986 dc.DrawRectangle(rect);
987}
988
1e6feb95
VZ
989void wxGTKRenderer::DrawUncheckBitmap(wxDC& dc,
990 const wxRect& rectTotal,
991 bool isPressed)
992{
993 wxRect rect = rectTotal;
994 DrawAntiRaisedBorder(dc, &rect);
995
996 wxColour col = wxSCHEME_COLOUR(m_scheme, SHADOW_IN);
147b8a4a 997 dc.SetPen(wxPen(col));
1e6feb95
VZ
998 dc.DrawPoint(rect.GetRight() - 1, rect.GetBottom() - 1);
999
1000 if ( isPressed )
1001 col = wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED);
1002 //else: it is SHADOW_IN, leave as is
1003
1004 dc.SetPen(*wxTRANSPARENT_PEN);
147b8a4a 1005 dc.SetBrush(col);
1e6feb95
VZ
1006 dc.DrawRectangle(rect);
1007}
1008
1009void wxGTKRenderer::DrawCheckBitmap(wxDC& dc, const wxRect& rectTotal)
1010{
1011 wxRect rect = rectTotal;
1012 DrawAntiShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight);
1013 DrawShadedRect(dc, &rect, m_penBlack, m_penLightGrey);
1014
1015 dc.SetPen(*wxTRANSPARENT_PEN);
147b8a4a 1016 dc.SetBrush(wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED));
1e6feb95
VZ
1017 dc.DrawRectangle(rect);
1018}
1019
1020void wxGTKRenderer::DrawRadioBitmap(wxDC& dc,
1021 const wxRect& rect,
1022 int flags)
1023{
1024 wxCoord x = rect.x,
1025 y = rect.y,
1026 xRight = rect.GetRight(),
1027 yBottom = rect.GetBottom();
1028
1029 wxCoord yMid = (y + yBottom) / 2;
1030
1e6feb95
VZ
1031 // then draw the upper half
1032 dc.SetPen(flags & wxCONTROL_CHECKED ? m_penDarkGrey : m_penHighlight);
1033 DrawUpZag(dc, x, xRight, yMid, y);
1034 DrawUpZag(dc, x + 1, xRight - 1, yMid, y + 1);
1035
a290fa5a 1036 bool drawIt = true;
1e6feb95
VZ
1037 if ( flags & wxCONTROL_CHECKED )
1038 dc.SetPen(m_penBlack);
1039 else if ( flags & wxCONTROL_PRESSED )
147b8a4a 1040 dc.SetPen(wxPen(wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED)));
1e6feb95 1041 else // unchecked and unpressed
a290fa5a 1042 drawIt = false;
1e6feb95
VZ
1043
1044 if ( drawIt )
1045 DrawUpZag(dc, x + 2, xRight - 2, yMid, y + 2);
1046
1047 // and then the lower one
1048 dc.SetPen(flags & wxCONTROL_CHECKED ? m_penHighlight : m_penBlack);
1049 DrawDownZag(dc, x, xRight, yMid, yBottom);
1050 if ( !(flags & wxCONTROL_CHECKED) )
1051 dc.SetPen(m_penDarkGrey);
1052 DrawDownZag(dc, x + 1, xRight - 1, yMid, yBottom - 1);
1053
1054 if ( !(flags & wxCONTROL_CHECKED) )
a290fa5a 1055 drawIt = true; // with the same pen
1e6feb95
VZ
1056 else if ( flags & wxCONTROL_PRESSED )
1057 {
147b8a4a 1058 dc.SetPen(wxPen(wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED)));
a290fa5a 1059 drawIt = true;
1e6feb95
VZ
1060 }
1061 else // checked and unpressed
a290fa5a 1062 drawIt = false;
1e6feb95
VZ
1063
1064 if ( drawIt )
1065 DrawDownZag(dc, x + 2, xRight - 2, yMid, yBottom - 2);
1066}
1067
1068void wxGTKRenderer::DrawUpZag(wxDC& dc,
1069 wxCoord x1,
1070 wxCoord x2,
1071 wxCoord y1,
1072 wxCoord y2)
1073{
1074 wxCoord xMid = (x1 + x2) / 2;
1075 dc.DrawLine(x1, y1, xMid, y2);
1076 dc.DrawLine(xMid, y2, x2 + 1, y1 + 1);
1077}
1078
1079void wxGTKRenderer::DrawDownZag(wxDC& dc,
1080 wxCoord x1,
1081 wxCoord x2,
1082 wxCoord y1,
1083 wxCoord y2)
1084{
1085 wxCoord xMid = (x1 + x2) / 2;
1086 dc.DrawLine(x1 + 1, y1 + 1, xMid, y2);
1087 dc.DrawLine(xMid, y2, x2, y1);
1088}
1089
1090wxBitmap wxGTKRenderer::GetCheckBitmap(int flags)
1091{
1092 if ( !m_bitmapsCheckbox[0][0].Ok() )
1093 {
1094 // init the bitmaps once only
1095 wxRect rect;
1096 wxSize size = GetCheckBitmapSize();
1097 rect.width = size.x;
1098 rect.height = size.y;
1099 for ( int i = 0; i < 2; i++ )
1100 {
415a0ff1 1101 for ( int j = 0; j < 3; j++ )
1e6feb95
VZ
1102 m_bitmapsCheckbox[i][j].Create(rect.width, rect.height);
1103 }
1104
1105 wxMemoryDC dc;
1106
1107 // normal checked
1108 dc.SelectObject(m_bitmapsCheckbox[0][0]);
1109 DrawCheckBitmap(dc, rect);
1110
1111 // normal unchecked
1112 dc.SelectObject(m_bitmapsCheckbox[0][1]);
a290fa5a 1113 DrawUncheckBitmap(dc, rect, false);
1e6feb95 1114
415a0ff1
WS
1115 // normal undeterminated
1116 dc.SelectObject(m_bitmapsCheckbox[0][2]);
1117 DrawUndeterminedBitmap(dc, rect, false);
1118
1e6feb95
VZ
1119 // pressed checked
1120 m_bitmapsCheckbox[1][0] = m_bitmapsCheckbox[0][0];
1121
1122 // pressed unchecked
1123 dc.SelectObject(m_bitmapsCheckbox[1][1]);
a290fa5a 1124 DrawUncheckBitmap(dc, rect, true);
415a0ff1
WS
1125
1126 // pressed undeterminated
1127 dc.SelectObject(m_bitmapsCheckbox[1][2]);
1128 DrawUndeterminedBitmap(dc, rect, true);
1e6feb95
VZ
1129 }
1130
147b8a4a
VZ
1131 IndicatorState state;
1132 IndicatorStatus status;
1133 GetIndicatorsFromFlags(flags, state, status);
1e6feb95 1134
147b8a4a
VZ
1135 // disabled looks the same as normal
1136 if ( state == IndicatorState_Disabled )
1137 state = IndicatorState_Normal;
1138
1139 return m_bitmapsCheckbox[state][status];
1140}
1141
1142wxBitmap wxGTKRenderer::GetRadioBitmap(int flags)
1143{
1144 IndicatorState state;
1145 IndicatorStatus status;
1146 GetIndicatorsFromFlags(flags, state, status);
1147
1148 wxBitmap& bmp = m_bitmapsRadiobtn[state][status];
1149 if ( !bmp.Ok() )
1150 {
1151 const wxSize size = GetRadioBitmapSize();
1152
1153 wxMemoryDC dc;
1154 bmp.Create(size.x, size.y);
1155 dc.SelectObject(bmp);
1156
1157 DrawRadioBitmap(dc, size, flags);
1158 }
1159
1160 return bmp;
1e6feb95
VZ
1161}
1162
3216dbf5 1163wxBitmap wxGTKRenderer::GetLineWrapBitmap() const
1e6feb95
VZ
1164{
1165 if ( !m_bmpLineWrap.Ok() )
1166 {
1167 // the line wrap bitmap as used by GTK+
1168 #define line_wrap_width 6
1169 #define line_wrap_height 9
1170 static const char line_wrap_bits[] =
1171 {
1172 0x1e, 0x3e, 0x30, 0x30, 0x39, 0x1f, 0x0f, 0x0f, 0x1f,
1173 };
1174
1175 wxBitmap bmpLineWrap(line_wrap_bits, line_wrap_width, line_wrap_height);
1176 if ( !bmpLineWrap.Ok() )
1177 {
1178 wxFAIL_MSG( _T("Failed to create line wrap XBM") );
1179 }
1180 else
1181 {
3216dbf5 1182 wxConstCast(this, wxGTKRenderer)->m_bmpLineWrap = bmpLineWrap;
1e6feb95
VZ
1183 }
1184 }
1185
1186 return m_bmpLineWrap;
1187}
1188
9a6384ca 1189#if wxUSE_TOOLBAR
3216dbf5
VZ
1190void wxGTKRenderer::DrawToolBarButton(wxDC& dc,
1191 const wxString& label,
1192 const wxBitmap& bitmap,
1193 const wxRect& rectOrig,
a8f4cabe 1194 int flags,
370efbe7
WS
1195 long WXUNUSED(style),
1196 int tbarStyle)
3216dbf5
VZ
1197{
1198 // we don't draw the separators at all
1199 if ( !label.empty() || bitmap.Ok() )
1200 {
1201 wxRect rect = rectOrig;
1202 rect.Deflate(BORDER_THICKNESS);
1203
1204 if ( flags & wxCONTROL_PRESSED )
1205 {
2e7b0a16
VZ
1206 DrawBorder(dc, wxBORDER_SUNKEN, rect, flags, &rect);
1207
1208 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED), rect);
3216dbf5
VZ
1209 }
1210 else if ( flags & wxCONTROL_CURRENT )
1211 {
2e7b0a16
VZ
1212 DrawBorder(dc, wxBORDER_RAISED, rect, flags, &rect);
1213
1214 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL_CURRENT), rect);
3216dbf5
VZ
1215 }
1216
370efbe7
WS
1217 if(tbarStyle & wxTB_TEXT)
1218 {
1219 if(tbarStyle & wxTB_HORIZONTAL)
1220 {
1221 dc.DrawLabel(label, bitmap, rect, wxALIGN_CENTRE);
1222 }
1223 else
1224 {
1225 dc.DrawLabel(label, bitmap, rect, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL);
1226 }
1227 }
1228 else
1229 {
1230 int xpoint = (rect.GetLeft() + rect.GetRight() + 1 - bitmap.GetWidth()) / 2;
1231 int ypoint = (rect.GetTop() + rect.GetBottom() + 1 - bitmap.GetHeight()) / 2;
1232 dc.DrawBitmap(bitmap, xpoint, ypoint);
1233 }
3216dbf5
VZ
1234 }
1235}
9a6384ca 1236#endif // wxUSE_TOOLBAR
3216dbf5 1237
1e6feb95
VZ
1238// ----------------------------------------------------------------------------
1239// text control
1240// ----------------------------------------------------------------------------
1241
9a6384ca
WS
1242#if wxUSE_TEXTCTRL
1243
1e6feb95
VZ
1244wxRect wxGTKRenderer::GetTextClientArea(const wxTextCtrl *text,
1245 const wxRect& rect,
3216dbf5 1246 wxCoord *extraSpaceBeyond) const
1e6feb95 1247{
6229b92f
VZ
1248 wxRect
1249 rectText = wxStdRenderer::GetTextClientArea(text, rect, extraSpaceBeyond);
1e6feb95
VZ
1250
1251 if ( text->WrapLines() )
1252 {
1253 // leave enough for the line wrap bitmap indicator
1254 wxCoord widthMark = GetLineWrapBitmap().GetWidth() + 2;
1255
1256 rectText.width -= widthMark;
1257
1258 if ( extraSpaceBeyond )
1259 *extraSpaceBeyond = widthMark;
1260 }
1261
1262 return rectText;
1263}
1264
1e6feb95
VZ
1265void wxGTKRenderer::DrawLineWrapMark(wxDC& dc, const wxRect& rect)
1266{
1267 wxBitmap bmpLineWrap = GetLineWrapBitmap();
1268
1269 // for a mono bitmap he colours it appears in depends on the current text
1270 // colours, so set them correctly
1271 wxColour colFgOld;
1272 if ( bmpLineWrap.GetDepth() == 1 )
1273 {
1274 colFgOld = dc.GetTextForeground();
1275
1276 // FIXME: I wonder what should we do if the background is black too?
1277 dc.SetTextForeground(*wxBLACK);
1278 }
1279
1280 dc.DrawBitmap(bmpLineWrap,
1281 rect.x, rect.y + (rect.height - bmpLineWrap.GetHeight())/2);
1282
1283 if ( colFgOld.Ok() )
1284 {
1285 // restore old colour
1286 dc.SetTextForeground(colFgOld);
1287 }
1288}
1289
6229b92f
VZ
1290#endif // wxUSE_TEXTCTRL
1291
1e6feb95
VZ
1292// ----------------------------------------------------------------------------
1293// notebook
1294// ----------------------------------------------------------------------------
1295
c4036939
VZ
1296#if wxUSE_NOTEBOOK
1297
1e6feb95
VZ
1298void wxGTKRenderer::DrawTab(wxDC& dc,
1299 const wxRect& rectOrig,
1300 wxDirection dir,
1301 const wxString& label,
1302 const wxBitmap& bitmap,
1303 int flags,
1304 int indexAccel)
1305{
7166a05d
WS
1306 #define SELECT_FOR_VERTICAL(X,Y) ( isVertical ? Y : X )
1307 #define REVERSE_FOR_VERTICAL(X,Y) \
1308 SELECT_FOR_VERTICAL(X,Y) \
1309 , \
1310 SELECT_FOR_VERTICAL(Y,X)
1311
1e6feb95
VZ
1312 wxRect rect = rectOrig;
1313
7166a05d
WS
1314 bool isVertical = ( dir == wxLEFT ) || ( dir == wxRIGHT );
1315
1e6feb95
VZ
1316 // the current tab is drawn indented (to the top for default case) and
1317 // bigger than the other ones
1318 const wxSize indent = GetTabIndent();
1319 if ( flags & wxCONTROL_SELECTED )
1320 {
7166a05d
WS
1321 rect.Inflate( SELECT_FOR_VERTICAL( indent.x , 0),
1322 SELECT_FOR_VERTICAL( 0, indent.y ));
1e6feb95
VZ
1323 switch ( dir )
1324 {
1325 default:
1326 wxFAIL_MSG(_T("invaild notebook tab orientation"));
1327 // fall through
1328
1329 case wxTOP:
1e6feb95 1330 rect.y -= indent.y;
7166a05d 1331 // fall through
1e6feb95 1332 case wxBOTTOM:
1e6feb95
VZ
1333 rect.height += indent.y;
1334 break;
1335
1336 case wxLEFT:
7166a05d
WS
1337 rect.x -= indent.x;
1338 // fall through
1e6feb95 1339 case wxRIGHT:
7166a05d 1340 rect.width += indent.x;
1e6feb95
VZ
1341 break;
1342 }
1343 }
1344
1345 // selected tab has different colour
1346 wxColour col = flags & wxCONTROL_SELECTED
1347 ? wxSCHEME_COLOUR(m_scheme, SHADOW_IN)
1348 : wxSCHEME_COLOUR(m_scheme, SCROLLBAR);
147b8a4a 1349 DrawSolidRect(dc, col, rect);
1e6feb95
VZ
1350
1351 if ( flags & wxCONTROL_FOCUSED )
1352 {
1353 // draw the focus rect
1354 wxRect rectBorder = rect;
1355 rectBorder.Deflate(4, 3);
1356 if ( dir == wxBOTTOM )
1357 rectBorder.Offset(0, -1);
7166a05d
WS
1358 if ( dir == wxRIGHT )
1359 rectBorder.Offset(-1, 0);
1e6feb95
VZ
1360
1361 DrawRect(dc, &rectBorder, m_penBlack);
1362 }
1363
1364 // draw the text, image and the focus around them (if necessary)
7166a05d
WS
1365 wxRect rectLabel( REVERSE_FOR_VERTICAL(rect.x,rect.y),
1366 REVERSE_FOR_VERTICAL(rect.width,rect.height)
1367 );
1e6feb95 1368 rectLabel.Deflate(1, 1);
7166a05d
WS
1369 if ( isVertical )
1370 {
1371 // draw it horizontally into memory and rotate for screen
1372 wxMemoryDC dcMem;
1373 wxBitmap bitmapRotated,
1374 bitmapMem( rectLabel.x + rectLabel.width,
1375 rectLabel.y + rectLabel.height );
1376 dcMem.SelectObject(bitmapMem);
1377 dcMem.SetBackground(dc.GetBackground());
1378 dcMem.SetFont(dc.GetFont());
1379 dcMem.SetTextForeground(dc.GetTextForeground());
1380 dcMem.Clear();
9a6384ca
WS
1381 bitmapRotated =
1382#if wxUSE_IMAGE
1383 wxBitmap( wxImage( bitmap.ConvertToImage() ).Rotate90(dir==wxLEFT) )
1384#else
1385 bitmap
1386#endif // wxUSE_IMAGE
1387 ;
7166a05d
WS
1388 dcMem.DrawLabel(label, bitmapRotated, rectLabel, wxALIGN_CENTRE, indexAccel);
1389 dcMem.SelectObject(wxNullBitmap);
1390 bitmapMem = bitmapMem.GetSubBitmap(rectLabel);
9a6384ca
WS
1391#if wxUSE_IMAGE
1392 bitmapMem = wxBitmap(wxImage(bitmapMem.ConvertToImage()).Rotate90(dir==wxRIGHT))
1393#endif
1394 ;
1395
7166a05d
WS
1396 dc.DrawBitmap(bitmapMem, rectLabel.y, rectLabel.x, false);
1397 }
1398 else
1399 {
1400 dc.DrawLabel(label, bitmap, rectLabel, wxALIGN_CENTRE, indexAccel);
1401 }
1e6feb95
VZ
1402
1403 // now draw the tab itself
7166a05d
WS
1404 wxCoord x = SELECT_FOR_VERTICAL(rect.x,rect.y),
1405 y = SELECT_FOR_VERTICAL(rect.y,rect.x),
1406 x2 = SELECT_FOR_VERTICAL(rect.GetRight(),rect.GetBottom()),
1407 y2 = SELECT_FOR_VERTICAL(rect.GetBottom(),rect.GetRight());
1e6feb95
VZ
1408 switch ( dir )
1409 {
1410 default:
7166a05d
WS
1411 // default is top
1412 case wxLEFT:
1413 // left orientation looks like top but IsVertical makes x and y reversed
1e6feb95 1414 case wxTOP:
7166a05d 1415 // top is not vertical so use coordinates in written order
1e6feb95 1416 dc.SetPen(m_penHighlight);
7166a05d
WS
1417 dc.DrawLine(REVERSE_FOR_VERTICAL(x, y2),
1418 REVERSE_FOR_VERTICAL(x, y));
1419 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y),
1420 REVERSE_FOR_VERTICAL(x2, y));
1e6feb95
VZ
1421
1422 dc.SetPen(m_penBlack);
7166a05d
WS
1423 dc.DrawLine(REVERSE_FOR_VERTICAL(x2, y2),
1424 REVERSE_FOR_VERTICAL(x2, y));
1e6feb95
VZ
1425
1426 dc.SetPen(m_penDarkGrey);
7166a05d
WS
1427 dc.DrawLine(REVERSE_FOR_VERTICAL(x2 - 1, y2),
1428 REVERSE_FOR_VERTICAL(x2 - 1, y + 1));
1e6feb95
VZ
1429
1430 if ( flags & wxCONTROL_SELECTED )
1431 {
1432 dc.SetPen(m_penLightGrey);
1433
1434 // overwrite the part of the border below this tab
7166a05d
WS
1435 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y2 + 1),
1436 REVERSE_FOR_VERTICAL(x2 - 1, y2 + 1));
1e6feb95
VZ
1437
1438 // and the shadow of the tab to the left of us
7166a05d
WS
1439 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y + 2),
1440 REVERSE_FOR_VERTICAL(x + 1, y2 + 1));
1e6feb95
VZ
1441 }
1442 break;
1443
7166a05d
WS
1444 case wxRIGHT:
1445 // right orientation looks like bottom but IsVertical makes x and y reversed
1e6feb95 1446 case wxBOTTOM:
7166a05d 1447 // bottom is not vertical so use coordinates in written order
1e6feb95
VZ
1448 dc.SetPen(m_penHighlight);
1449
1450 // we need to continue one pixel further to overwrite the corner of
1451 // the border for the selected tab
7166a05d
WS
1452 dc.DrawLine(REVERSE_FOR_VERTICAL(x, y - (flags & wxCONTROL_SELECTED ? 1 : 0)),
1453 REVERSE_FOR_VERTICAL(x, y2));
1e6feb95
VZ
1454
1455 // it doesn't work like this (TODO: implement it properly)
1456#if 0
1457 // erase the corner of the tab to the right
1458 dc.SetPen(m_penLightGrey);
7166a05d
WS
1459 dc.DrawPoint(REVERSE_FOR_VERTICAL(x2 - 1, y - 2));
1460 dc.DrawPoint(REVERSE_FOR_VERTICAL(x2 - 2, y - 2));
1461 dc.DrawPoint(REVERSE_FOR_VERTICAL(x2 - 2, y - 1));
1e6feb95
VZ
1462#endif // 0
1463
1464 dc.SetPen(m_penBlack);
7166a05d
WS
1465 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y2),
1466 REVERSE_FOR_VERTICAL(x2, y2));
1467 dc.DrawLine(REVERSE_FOR_VERTICAL(x2, y),
1468 REVERSE_FOR_VERTICAL(x2, y2));
1e6feb95
VZ
1469
1470 dc.SetPen(m_penDarkGrey);
7166a05d
WS
1471 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 2, y2 - 1),
1472 REVERSE_FOR_VERTICAL(x2 - 1, y2 - 1));
1473 dc.DrawLine(REVERSE_FOR_VERTICAL(x2 - 1, y),
1474 REVERSE_FOR_VERTICAL(x2 - 1, y2));
1e6feb95
VZ
1475
1476 if ( flags & wxCONTROL_SELECTED )
1477 {
1478 dc.SetPen(m_penLightGrey);
1479
1480 // overwrite the part of the (double!) border above this tab
7166a05d
WS
1481 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y - 1),
1482 REVERSE_FOR_VERTICAL(x2 - 1, y - 1));
1483 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y - 2),
1484 REVERSE_FOR_VERTICAL(x2 - 1, y - 2));
1e6feb95
VZ
1485
1486 // and the shadow of the tab to the left of us
7166a05d
WS
1487 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y2 - 1),
1488 REVERSE_FOR_VERTICAL(x + 1, y - 1));
1e6feb95
VZ
1489 }
1490 break;
1e6feb95
VZ
1491 }
1492}
1493
c4036939 1494#endif // wxUSE_NOTEBOOK
9a6384ca 1495
1e6feb95
VZ
1496// ----------------------------------------------------------------------------
1497// slider
1498// ----------------------------------------------------------------------------
1499
c4036939
VZ
1500#if wxUSE_SLIDER
1501
1e6feb95 1502wxSize wxGTKRenderer::GetSliderThumbSize(const wxRect& rect,
6766e5d1 1503 int lenThumb,
1e6feb95
VZ
1504 wxOrientation orient) const
1505{
1506 static const wxCoord SLIDER_THUMB_LENGTH = 30;
1507
1508 wxSize size;
1509
6766e5d1 1510 wxRect rectShaft = GetSliderShaftRect(rect, lenThumb, orient);
1e6feb95
VZ
1511 if ( orient == wxHORIZONTAL )
1512 {
1513 size.x = wxMin(SLIDER_THUMB_LENGTH, rectShaft.width);
1514 size.y = rectShaft.height;
1515 }
1516 else // vertical
1517 {
1518 size.y = wxMin(SLIDER_THUMB_LENGTH, rectShaft.height);
1519 size.x = rectShaft.width;
1520 }
1521
1522 return size;
1523}
1524
1525wxRect wxGTKRenderer::GetSliderShaftRect(const wxRect& rect,
61fef19b 1526 int WXUNUSED(lenThumb),
6766e5d1 1527 wxOrientation WXUNUSED(orient),
61fef19b 1528 long WXUNUSED(style)) const
1e6feb95
VZ
1529{
1530 return rect.Deflate(2*BORDER_THICKNESS, 2*BORDER_THICKNESS);
1531}
1532
1533void wxGTKRenderer::DrawSliderShaft(wxDC& dc,
1534 const wxRect& rectOrig,
61fef19b
VZ
1535 int WXUNUSED(lenThumb),
1536 wxOrientation WXUNUSED(orient),
1e6feb95 1537 int flags,
61fef19b 1538 long WXUNUSED(style),
1e6feb95
VZ
1539 wxRect *rectShaft)
1540{
1541 wxRect rect = rectOrig;
1542
1543 // draw the border first
1544 if ( flags & wxCONTROL_FOCUSED )
1545 {
1546 DrawRect(dc, &rect, m_penBlack);
1e6feb95
VZ
1547 }
1548 else // not focused, normal
1549 {
1550 DrawAntiShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight);
1e6feb95
VZ
1551 }
1552
147b8a4a
VZ
1553 DrawAntiShadedRect(dc, &rect, m_penBlack, m_penLightGrey);
1554
1e6feb95 1555 // and the background
147b8a4a 1556 DrawSolidRect(dc, wxSCHEME_COLOUR(m_scheme, SCROLLBAR), rect);
1e6feb95
VZ
1557
1558 if ( rectShaft )
1559 *rectShaft = rect;
1560}
1561
1562void wxGTKRenderer::DrawSliderThumb(wxDC& dc,
1563 const wxRect& rectOrig,
1564 wxOrientation orient,
61fef19b
VZ
1565 int WXUNUSED(flags),
1566 long WXUNUSED(style))
1e6feb95
VZ
1567{
1568 // draw the thumb border
1569 wxRect rect = rectOrig;
1570 DrawAntiRaisedBorder(dc, &rect);
1571
1572 // draw the handle in the middle
1573 if ( orient == wxVERTICAL )
1574 {
1575 rect.height = 2*BORDER_THICKNESS;
1576 rect.y = rectOrig.y + (rectOrig.height - rect.height) / 2;
1577 }
1578 else // horz
1579 {
1580 rect.width = 2*BORDER_THICKNESS;
1581 rect.x = rectOrig.x + (rectOrig.width - rect.width) / 2;
1582 }
1583
1584 DrawShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight);
1585}
1586
9a6384ca
WS
1587#endif // wxUSE_SLIDER
1588
1589#if wxUSE_MENUS
1590
1e6feb95
VZ
1591// ----------------------------------------------------------------------------
1592// menu and menubar
1593// ----------------------------------------------------------------------------
1594
0fe5e8fe
VZ
1595// wxGTKMenuGeometryInfo: the wxMenuGeometryInfo used by wxGTKRenderer
1596class WXDLLEXPORT wxGTKMenuGeometryInfo : public wxMenuGeometryInfo
1597{
1598public:
1599 virtual wxSize GetSize() const { return m_size; }
1600
1601 wxCoord GetLabelOffset() const { return m_ofsLabel; }
1602 wxCoord GetAccelOffset() const { return m_ofsAccel; }
1603
1604 wxCoord GetItemHeight() const { return m_heightItem; }
1605
1606private:
1607 // the total size of the menu
1608 wxSize m_size;
1609
1610 // the offset of the start of the menu item label
1611 wxCoord m_ofsLabel;
1612
1613 // the offset of the start of the accel label
1614 wxCoord m_ofsAccel;
1615
1616 // the height of a normal (not separator) item
1617 wxCoord m_heightItem;
1618
1619 friend wxMenuGeometryInfo *
1620 wxGTKRenderer::GetMenuGeometry(wxWindow *, const wxMenu&) const;
1621};
1622
1623// FIXME: all constants are hardcoded but shouldn't be
1624static const wxCoord MENU_LEFT_MARGIN = 9;
1625static const wxCoord MENU_RIGHT_MARGIN = 6;
1626
1627static const wxCoord MENU_HORZ_MARGIN = 6;
1628static const wxCoord MENU_VERT_MARGIN = 3;
1629
1630// the margin around bitmap/check marks (on each side)
1631static const wxCoord MENU_BMP_MARGIN = 2;
1632
1633// the margin between the labels and accel strings
1634static const wxCoord MENU_ACCEL_MARGIN = 8;
1635
1636// the separator height in pixels: in fact, strangely enough, the real height
1637// is 2 but Windows adds one extra pixel in the bottom margin, so take it into
1638// account here
1639static const wxCoord MENU_SEPARATOR_HEIGHT = 3;
1640
1641// the size of the standard checkmark bitmap
1642static const wxCoord MENU_CHECK_SIZE = 9;
1643
1e6feb95
VZ
1644void wxGTKRenderer::DrawMenuBarItem(wxDC& dc,
1645 const wxRect& rect,
1646 const wxString& label,
1647 int flags,
1648 int indexAccel)
1649{
0fe5e8fe 1650 DoDrawMenuItem(dc, rect, label, flags, indexAccel);
1e6feb95
VZ
1651}
1652
1653void wxGTKRenderer::DrawMenuItem(wxDC& dc,
1654 wxCoord y,
0fe5e8fe 1655 const wxMenuGeometryInfo& gi,
1e6feb95
VZ
1656 const wxString& label,
1657 const wxString& accel,
1658 const wxBitmap& bitmap,
1659 int flags,
1660 int indexAccel)
1661{
0fe5e8fe
VZ
1662 const wxGTKMenuGeometryInfo& geomInfo = (const wxGTKMenuGeometryInfo&)gi;
1663
1664 wxRect rect;
1665 rect.x = 0;
1666 rect.y = y;
1667 rect.width = geomInfo.GetSize().x;
1668 rect.height = geomInfo.GetItemHeight();
1669
1670 DoDrawMenuItem(dc, rect, label, flags, indexAccel, accel, bitmap, &geomInfo);
1671}
1672
1673void wxGTKRenderer::DoDrawMenuItem(wxDC& dc,
1674 const wxRect& rectOrig,
1675 const wxString& label,
1676 int flags,
1677 int indexAccel,
1678 const wxString& accel,
1679 const wxBitmap& bitmap,
1680 const wxGTKMenuGeometryInfo *geometryInfo)
1681{
1682 wxRect rect = rectOrig;
1683
1684 // draw the selected item specially
1685 if ( flags & wxCONTROL_SELECTED )
1686 {
1687 wxRect rectIn;
1688 DrawBorder(dc, wxBORDER_RAISED, rect, flags, &rectIn);
1689
1690 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL_CURRENT), rectIn);
1691 }
1692
1693 rect.Deflate(MENU_HORZ_MARGIN, MENU_VERT_MARGIN);
1694
1695 // draw the bitmap: use the bitmap provided or the standard checkmark for
1696 // the checkable items
1697 if ( geometryInfo )
1698 {
1699 wxBitmap bmp = bitmap;
1700 if ( !bmp.Ok() && (flags & wxCONTROL_CHECKABLE) )
1701 {
1702 bmp = GetCheckBitmap(flags);
1703 }
1704
1705 if ( bmp.Ok() )
1706 {
1707 rect.SetRight(geometryInfo->GetLabelOffset());
1708 wxControlRenderer::DrawBitmap(dc, bmp, rect);
1709 }
1710 }
1711 //else: menubar items don't have bitmaps
1712
1713 // draw the label
1714 if ( geometryInfo )
1715 {
1716 rect.x = geometryInfo->GetLabelOffset();
1717 rect.SetRight(geometryInfo->GetAccelOffset());
1718 }
1719
1720 DrawLabel(dc, label, rect, flags, wxALIGN_CENTRE_VERTICAL, indexAccel);
1721
1722 // draw the accel string
1723 if ( !accel.empty() )
1724 {
1725 // menubar items shouldn't have them
1726 wxCHECK_RET( geometryInfo, _T("accel strings only valid for menus") );
1727
1728 rect.x = geometryInfo->GetAccelOffset();
1729 rect.SetRight(geometryInfo->GetSize().x);
1730
1731 // NB: no accel index here
1732 DrawLabel(dc, accel, rect, flags, wxALIGN_CENTRE_VERTICAL);
1733 }
1734
1735 // draw the submenu indicator
1736 if ( flags & wxCONTROL_ISSUBMENU )
1737 {
1738 wxCHECK_RET( geometryInfo, _T("wxCONTROL_ISSUBMENU only valid for menus") );
1739
1740 rect.x = geometryInfo->GetSize().x - MENU_RIGHT_MARGIN;
1741 rect.width = MENU_RIGHT_MARGIN;
1742
1743 DrawArrow(dc, wxRIGHT, rect, flags);
1744 }
1e6feb95
VZ
1745}
1746
1747void wxGTKRenderer::DrawMenuSeparator(wxDC& dc,
1748 wxCoord y,
1749 const wxMenuGeometryInfo& geomInfo)
1750{
0fe5e8fe 1751 DrawHorizontalLine(dc, y + MENU_VERT_MARGIN, 0, geomInfo.GetSize().x);
1e6feb95
VZ
1752}
1753
1754wxSize wxGTKRenderer::GetMenuBarItemSize(const wxSize& sizeText) const
1755{
0fe5e8fe
VZ
1756 wxSize size = sizeText;
1757
1758 // TODO: make this configurable
1759 size.x += 2*MENU_HORZ_MARGIN;
1760 size.y += 2*MENU_VERT_MARGIN;
1761
1762 return size;
1e6feb95
VZ
1763}
1764
1765wxMenuGeometryInfo *wxGTKRenderer::GetMenuGeometry(wxWindow *win,
1766 const wxMenu& menu) const
1767{
0fe5e8fe
VZ
1768 // prepare the dc: for now we draw all the items with the system font
1769 wxClientDC dc(win);
1770 dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
1771
1772 // the height of a normal item
1773 wxCoord heightText = dc.GetCharHeight();
1774
1775 // the total height
1776 wxCoord height = 0;
1777
1778 // the max length of label and accel strings: the menu width is the sum of
1779 // them, even if they're for different items (as the accels should be
1780 // aligned)
1781 //
1782 // the max length of the bitmap is never 0 as Windows always leaves enough
1783 // space for a check mark indicator
1784 wxCoord widthLabelMax = 0,
1785 widthAccelMax = 0,
1786 widthBmpMax = MENU_LEFT_MARGIN;
1787
ac32ba44 1788 for ( wxMenuItemList::compatibility_iterator node = menu.GetMenuItems().GetFirst();
0fe5e8fe
VZ
1789 node;
1790 node = node->GetNext() )
1791 {
1792 // height of this item
1793 wxCoord h;
1794
1795 wxMenuItem *item = node->GetData();
1796 if ( item->IsSeparator() )
1797 {
1798 h = MENU_SEPARATOR_HEIGHT;
1799 }
1800 else // not separator
1801 {
1802 h = heightText;
1803
1804 wxCoord widthLabel;
1805 dc.GetTextExtent(item->GetLabel(), &widthLabel, NULL);
1806 if ( widthLabel > widthLabelMax )
1807 {
1808 widthLabelMax = widthLabel;
1809 }
1810
1811 wxCoord widthAccel;
1812 dc.GetTextExtent(item->GetAccelString(), &widthAccel, NULL);
1813 if ( widthAccel > widthAccelMax )
1814 {
1815 widthAccelMax = widthAccel;
1816 }
1817
1818 const wxBitmap& bmp = item->GetBitmap();
1819 if ( bmp.Ok() )
1820 {
1821 wxCoord widthBmp = bmp.GetWidth();
1822 if ( widthBmp > widthBmpMax )
1823 widthBmpMax = widthBmp;
1824 }
1825 //else if ( item->IsCheckable() ): no need to check for this as
1826 // MENU_LEFT_MARGIN is big enough to show the check mark
1827 }
1828
1829 h += 2*MENU_VERT_MARGIN;
1830
1831 // remember the item position and height
1832 item->SetGeometry(height, h);
1833
1834 height += h;
1835 }
1836
1837 // bundle the metrics into a struct and return it
1838 wxGTKMenuGeometryInfo *gi = new wxGTKMenuGeometryInfo;
1839
1840 gi->m_ofsLabel = widthBmpMax + 2*MENU_BMP_MARGIN;
1841 gi->m_ofsAccel = gi->m_ofsLabel + widthLabelMax;
1842 if ( widthAccelMax > 0 )
1843 {
1844 // if we actually have any accesl, add a margin
1845 gi->m_ofsAccel += MENU_ACCEL_MARGIN;
1846 }
1847
1848 gi->m_heightItem = heightText + 2*MENU_VERT_MARGIN;
1849
1850 gi->m_size.x = gi->m_ofsAccel + widthAccelMax + MENU_RIGHT_MARGIN;
1851 gi->m_size.y = height;
1e6feb95 1852
0fe5e8fe 1853 return gi;
1e6feb95 1854}
71e03035 1855
9a6384ca
WS
1856#endif // wxUSE_MENUS
1857
1e6feb95
VZ
1858// ----------------------------------------------------------------------------
1859// combobox
1860// ----------------------------------------------------------------------------
1861
1b488c0e
VZ
1862void wxGTKRenderer::InitComboBitmaps()
1863{
1864 wxSize sizeArrow = m_sizeScrollbarArrow;
1865 sizeArrow.x -= 2;
1866 sizeArrow.y -= 2;
1867
1868 size_t n;
1869
1870 for ( n = ComboState_Normal; n < ComboState_Max; n++ )
1871 {
1872 m_bitmapsCombo[n].Create(sizeArrow.x, sizeArrow.y);
1873 }
1874
1875 static const int comboButtonFlags[ComboState_Max] =
1876 {
1877 0,
1878 wxCONTROL_CURRENT,
1879 wxCONTROL_PRESSED,
1880 wxCONTROL_DISABLED,
1881 };
1882
8d8fbb9d 1883 wxRect rect(sizeArrow);
1b488c0e
VZ
1884
1885 wxMemoryDC dc;
1886 for ( n = ComboState_Normal; n < ComboState_Max; n++ )
1887 {
1888 int flags = comboButtonFlags[n];
1889
1890 dc.SelectObject(m_bitmapsCombo[n]);
147b8a4a 1891 DrawSolidRect(dc, GetBackgroundColour(flags), rect);
1b488c0e
VZ
1892 DrawArrow(dc, wxDOWN, rect, flags);
1893 }
1894}
1895
1e6feb95 1896void wxGTKRenderer::GetComboBitmaps(wxBitmap *bmpNormal,
1b488c0e 1897 wxBitmap *bmpFocus,
1e6feb95
VZ
1898 wxBitmap *bmpPressed,
1899 wxBitmap *bmpDisabled)
1900{
1b488c0e
VZ
1901 if ( !m_bitmapsCombo[ComboState_Normal].Ok() )
1902 {
1903 InitComboBitmaps();
1904 }
1905
1906 if ( bmpNormal )
1907 *bmpNormal = m_bitmapsCombo[ComboState_Normal];
1908 if ( bmpFocus )
1909 *bmpFocus = m_bitmapsCombo[ComboState_Focus];
1910 if ( bmpPressed )
1911 *bmpPressed = m_bitmapsCombo[ComboState_Pressed];
1912 if ( bmpDisabled )
1913 *bmpDisabled = m_bitmapsCombo[ComboState_Disabled];
1e6feb95
VZ
1914}
1915
1e6feb95
VZ
1916// ----------------------------------------------------------------------------
1917// scrollbar
1918// ----------------------------------------------------------------------------
1919
1920void wxGTKRenderer::DrawArrowBorder(wxDC& dc,
1921 wxRect *rect,
1922 wxDirection dir)
1923{
1924 static const wxDirection sides[] =
1925 {
1926 wxUP, wxLEFT, wxRIGHT, wxDOWN
1927 };
1928
1929 wxRect rect1, rect2, rectInner;
1930 rect1 =
1931 rect2 =
1932 rectInner = *rect;
1933
1934 rect2.Inflate(-1);
1935 rectInner.Inflate(-2);
1936
147b8a4a 1937 DrawSolidRect(dc, wxSCHEME_COLOUR(m_scheme, SCROLLBAR), *rect);
1e6feb95
VZ
1938
1939 // find the side not to draw and also adjust the rectangles to compensate
1940 // for it
1941 wxDirection sideToOmit;
1942 switch ( dir )
1943 {
1944 case wxUP:
1945 sideToOmit = wxDOWN;
1946 rect2.height += 1;
1947 rectInner.height += 1;
1948 break;
1949
1950 case wxDOWN:
1951 sideToOmit = wxUP;
1952 rect2.y -= 1;
1953 rect2.height += 1;
1954 rectInner.y -= 2;
1955 rectInner.height += 1;
1956 break;
1957
1958 case wxLEFT:
1959 sideToOmit = wxRIGHT;
1960 rect2.width += 1;
1961 rectInner.width += 1;
1962 break;
1963
1964 case wxRIGHT:
1965 sideToOmit = wxLEFT;
1966 rect2.x -= 1;
1967 rect2.width += 1;
1968 rectInner.x -= 2;
1969 rectInner.width += 1;
1970 break;
1971
1972 default:
1973 wxFAIL_MSG(_T("unknown arrow direction"));
1974 return;
1975 }
1976
1977 // the outer rect first
1978 size_t n;
1979 for ( n = 0; n < WXSIZEOF(sides); n++ )
1980 {
1981 wxDirection side = sides[n];
1982 if ( side == sideToOmit )
1983 continue;
1984
1985 DrawAntiShadedRectSide(dc, rect1, m_penDarkGrey, m_penHighlight, side);
1986 }
1987
1988 // and then the inner one
1989 for ( n = 0; n < WXSIZEOF(sides); n++ )
1990 {
1991 wxDirection side = sides[n];
1992 if ( side == sideToOmit )
1993 continue;
1994
1995 DrawAntiShadedRectSide(dc, rect2, m_penBlack, m_penGrey, side);
1996 }
1997
1998 *rect = rectInner;
1999}
2000
2001void wxGTKRenderer::DrawScrollbarArrow(wxDC& dc,
2002 wxDirection dir,
2003 const wxRect& rectArrow,
2004 int flags)
2005{
2006 // first of all, draw the border around it - but we don't want the border
2007 // on the side opposite to the arrow point
2008 wxRect rect = rectArrow;
2009 DrawArrowBorder(dc, &rect, dir);
2010
2011 // then the arrow itself
2012 DrawArrow(dc, dir, rect, flags);
2013}
2014
2015// gtk_default_draw_arrow() takes ~350 lines and we can't do much better here
2016// these people are just crazy :-(
2017void wxGTKRenderer::DrawArrow(wxDC& dc,
2018 wxDirection dir,
2019 const wxRect& rect,
2020 int flags)
2021{
2022 enum
2023 {
2024 Point_First,
2025 Point_Second,
2026 Point_Third,
2027 Point_Max
2028 };
2029
2030 wxPoint ptArrow[Point_Max];
2031
2032 wxColour colInside = GetBackgroundColour(flags);
2033 wxPen penShadow[4];
2034 if ( flags & wxCONTROL_DISABLED )
2035 {
2036 penShadow[0] = m_penDarkGrey;
2037 penShadow[1] = m_penDarkGrey;
2038 penShadow[2] = wxNullPen;
2039 penShadow[3] = wxNullPen;
2040 }
2041 else if ( flags & wxCONTROL_PRESSED )
2042 {
2043 penShadow[0] = m_penDarkGrey;
2044 penShadow[1] = m_penHighlight;
2045 penShadow[2] = wxNullPen;
2046 penShadow[3] = m_penBlack;
2047 }
2048 else // normal arrow
2049 {
2050 penShadow[0] = m_penHighlight;
2051 penShadow[1] = m_penBlack;
2052 penShadow[2] = m_penDarkGrey;
2053 penShadow[3] = wxNullPen;
2054 }
2055
2056 wxCoord middle;
2057 if ( dir == wxUP || dir == wxDOWN )
2058 {
2059 // horz middle
2060 middle = (rect.GetRight() + rect.GetLeft() + 1) / 2;
2061 }
2062 else // horz arrow
2063 {
2064 middle = (rect.GetTop() + rect.GetBottom() + 1) / 2;
2065 }
2066
2067 // draw the arrow interior
2068 dc.SetPen(*wxTRANSPARENT_PEN);
147b8a4a 2069 dc.SetBrush(colInside);
1e6feb95
VZ
2070
2071 switch ( dir )
2072 {
2073 case wxUP:
2074 ptArrow[Point_First].x = rect.GetLeft();
2075 ptArrow[Point_First].y = rect.GetBottom();
2076 ptArrow[Point_Second].x = middle;
2077 ptArrow[Point_Second].y = rect.GetTop();
2078 ptArrow[Point_Third].x = rect.GetRight();
2079 ptArrow[Point_Third].y = rect.GetBottom();
2080 break;
2081
2082 case wxDOWN:
2083 ptArrow[Point_First] = rect.GetPosition();
2084 ptArrow[Point_Second].x = middle;
2085 ptArrow[Point_Second].y = rect.GetBottom();
2086 ptArrow[Point_Third].x = rect.GetRight();
2087 ptArrow[Point_Third].y = rect.GetTop();
2088 break;
2089
2090 case wxLEFT:
2091 ptArrow[Point_First].x = rect.GetRight();
2092 ptArrow[Point_First].y = rect.GetTop();
2093 ptArrow[Point_Second].x = rect.GetLeft();
2094 ptArrow[Point_Second].y = middle;
2095 ptArrow[Point_Third].x = rect.GetRight();
2096 ptArrow[Point_Third].y = rect.GetBottom();
2097 break;
2098
2099 case wxRIGHT:
2100 ptArrow[Point_First] = rect.GetPosition();
2101 ptArrow[Point_Second].x = rect.GetRight();
2102 ptArrow[Point_Second].y = middle;
2103 ptArrow[Point_Third].x = rect.GetLeft();
2104 ptArrow[Point_Third].y = rect.GetBottom();
2105 break;
2106
2107 default:
2108 wxFAIL_MSG(_T("unknown arrow direction"));
2109 }
2110
2111 dc.DrawPolygon(WXSIZEOF(ptArrow), ptArrow);
2112
2113 // draw the arrow border
2114 dc.SetPen(penShadow[0]);
2115 switch ( dir )
2116 {
2117 case wxUP:
2118 dc.DrawLine(ptArrow[Point_Second], ptArrow[Point_First]);
2119 dc.DrawPoint(ptArrow[Point_First]);
2120 if ( penShadow[3].Ok() )
2121 {
2122 dc.SetPen(penShadow[3]);
2123 dc.DrawLine(ptArrow[Point_First].x + 1, ptArrow[Point_First].y,
2124 ptArrow[Point_Second].x, ptArrow[Point_Second].y);
2125 }
2126 dc.SetPen(penShadow[1]);
2127 dc.DrawLine(ptArrow[Point_Second].x + 1, ptArrow[Point_Second].y + 1,
2128 ptArrow[Point_Third].x, ptArrow[Point_Third].y);
2129 dc.DrawPoint(ptArrow[Point_Third]);
2130 dc.DrawLine(ptArrow[Point_Third].x - 2, ptArrow[Point_Third].y,
2131 ptArrow[Point_First].x + 1, ptArrow[Point_First].y);
2132 if ( penShadow[2].Ok() )
2133 {
2134 dc.SetPen(penShadow[2]);
2135 dc.DrawLine(ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y,
2136 ptArrow[Point_Second].x, ptArrow[Point_Second].y + 1);
2137 dc.DrawLine(ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y - 1,
2138 ptArrow[Point_First].x + 2, ptArrow[Point_First].y - 1);
2139 }
2140 break;
2141
2142 case wxDOWN:
2143 dc.DrawLine(ptArrow[Point_First], ptArrow[Point_Second]);
2144 dc.DrawLine(ptArrow[Point_First].x + 2, ptArrow[Point_First].y,
2145 ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y);
2146 if ( penShadow[2].Ok() )
2147 {
2148 dc.SetPen(penShadow[2]);
2149 dc.DrawLine(ptArrow[Point_Second].x, ptArrow[Point_Second].y - 1,
2150 ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y - 1);
2151 }
2152 dc.SetPen(penShadow[1]);
2153 dc.DrawLine(ptArrow[Point_Second], ptArrow[Point_Third]);
2154 dc.DrawPoint(ptArrow[Point_Third]);
2155 break;
2156
2157 case wxLEFT:
2158 dc.DrawLine(ptArrow[Point_Second], ptArrow[Point_First]);
2159 dc.DrawPoint(ptArrow[Point_First]);
2160 if ( penShadow[2].Ok() )
2161 {
2162 dc.SetPen(penShadow[2]);
2163 dc.DrawLine(ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y,
2164 ptArrow[Point_First].x - 1, ptArrow[Point_First].y + 2);
2165 dc.DrawLine(ptArrow[Point_Third].x, ptArrow[Point_Third].y,
2166 ptArrow[Point_Second].x + 2, ptArrow[Point_Second].y + 1);
2167 }
2168 dc.SetPen(penShadow[1]);
2169 dc.DrawLine(ptArrow[Point_Third].x, ptArrow[Point_Third].y,
2170 ptArrow[Point_First].x, ptArrow[Point_First].y + 1);
2171 dc.DrawLine(ptArrow[Point_Second].x + 1, ptArrow[Point_Second].y + 1,
2172 ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y);
2173 break;
2174
2175 case wxRIGHT:
2176 dc.DrawLine(ptArrow[Point_First], ptArrow[Point_Third]);
2177 dc.DrawLine(ptArrow[Point_First].x + 2, ptArrow[Point_First].y + 1,
2178 ptArrow[Point_Second].x, ptArrow[Point_Second].y);
2179 dc.SetPen(penShadow[1]);
2180 dc.DrawLine(ptArrow[Point_Second], ptArrow[Point_Third]);
2181 dc.DrawPoint(ptArrow[Point_Third]);
2182 break;
2183
2184 default:
2185 wxFAIL_MSG(_T("unknown arrow direction"));
2186 return;
2187 }
2188}
2189
2190void wxGTKRenderer::DrawThumbBorder(wxDC& dc,
2191 wxRect *rect,
2192 wxOrientation orient)
2193{
2194 if ( orient == wxVERTICAL )
2195 {
2196 DrawAntiShadedRectSide(dc, *rect, m_penDarkGrey, m_penHighlight,
2197 wxLEFT);
2198 DrawAntiShadedRectSide(dc, *rect, m_penDarkGrey, m_penHighlight,
2199 wxRIGHT);
2200 rect->Inflate(-1, 0);
2201
2202 DrawAntiShadedRectSide(dc, *rect, m_penBlack, m_penGrey,
2203 wxLEFT);
2204 DrawAntiShadedRectSide(dc, *rect, m_penBlack, m_penGrey,
2205 wxRIGHT);
2206 rect->Inflate(-1, 0);
2207 }
2208 else
2209 {
2210 DrawAntiShadedRectSide(dc, *rect, m_penDarkGrey, m_penHighlight,
2211 wxUP);
2212 DrawAntiShadedRectSide(dc, *rect, m_penDarkGrey, m_penHighlight,
2213 wxDOWN);
2214 rect->Inflate(0, -1);
2215
2216 DrawAntiShadedRectSide(dc, *rect, m_penBlack, m_penGrey,
2217 wxUP);
2218 DrawAntiShadedRectSide(dc, *rect, m_penBlack, m_penGrey,
2219 wxDOWN);
2220 rect->Inflate(0, -1);
2221 }
2222}
2223
2224void wxGTKRenderer::DrawScrollbarThumb(wxDC& dc,
2225 wxOrientation orient,
2226 const wxRect& rect,
2227 int flags)
2228{
2229 // the thumb is never pressed never has focus border under GTK and the
2230 // scrollbar background never changes at all
2231 int flagsThumb = flags & ~(wxCONTROL_PRESSED | wxCONTROL_FOCUSED);
2232
2233 // we don't want the border in the direction of the scrollbar movement
2234 wxRect rectThumb = rect;
2235 DrawThumbBorder(dc, &rectThumb, orient);
2236
2237 DrawButtonBorder(dc, rectThumb, flagsThumb, &rectThumb);
2238 DrawBackground(dc, wxNullColour, rectThumb, flagsThumb);
2239}
2240
2241void wxGTKRenderer::DrawScrollbarShaft(wxDC& dc,
2242 wxOrientation orient,
2243 const wxRect& rect,
61fef19b 2244 int WXUNUSED(flags))
1e6feb95
VZ
2245{
2246 wxRect rectBar = rect;
2247 DrawThumbBorder(dc, &rectBar, orient);
147b8a4a 2248 DrawSolidRect(dc, wxSCHEME_COLOUR(m_scheme, SCROLLBAR), rectBar);
1e6feb95
VZ
2249}
2250
9a6384ca 2251#if wxUSE_SCROLLBAR
1e6feb95
VZ
2252wxRect wxGTKRenderer::GetScrollbarRect(const wxScrollBar *scrollbar,
2253 wxScrollBar::Element elem,
2254 int thumbPos) const
2255{
2256 // as GTK scrollbars can't be disabled, it makes no sense to remove the
2257 // thumb for a scrollbar with range 0 - instead, make it fill the entire
2258 // scrollbar shaft
2259 if ( (elem == wxScrollBar::Element_Thumb) && !scrollbar->GetRange() )
2260 {
2261 elem = wxScrollBar::Element_Bar_2;
2262 }
2263
147b8a4a 2264 return wxStdRenderer::GetScrollbarRect(scrollbar, elem, thumbPos);
1e6feb95
VZ
2265}
2266
9a6384ca 2267#endif // wxUSE_SCROLLBAR
1e6feb95
VZ
2268
2269// ----------------------------------------------------------------------------
2270// size adjustments
2271// ----------------------------------------------------------------------------
2272
2273void wxGTKRenderer::AdjustSize(wxSize *size, const wxWindow *window)
2274{
e4606ed9
VZ
2275#if wxUSE_BMPBUTTON
2276 if ( wxDynamicCast(window, wxBitmapButton) )
2277 {
2278 size->x += 4;
2279 size->y += 4;
2280 } else
2281#endif // wxUSE_BMPBUTTON
43be3c33 2282#if wxUSE_BUTTON || wxUSE_TOGGLEBTN
370efbe7 2283 if ( 0
43be3c33 2284# if wxUSE_BUTTON
370efbe7 2285 || wxDynamicCast(window, wxButton)
43be3c33
JS
2286# endif // wxUSE_BUTTON
2287# if wxUSE_TOGGLEBTN
370efbe7 2288 || wxDynamicCast(window, wxToggleButton)
43be3c33
JS
2289# endif // wxUSE_TOGGLEBTN
2290 )
1e6feb95 2291 {
1b465102
VZ
2292 if ( !(window->GetWindowStyle() & wxBU_EXACTFIT) )
2293 {
2294 // TODO: this is ad hoc...
2295 size->x += 3*window->GetCharWidth();
2296 wxCoord minBtnHeight = 18;
2297 if ( size->y < minBtnHeight )
2298 size->y = minBtnHeight;
2299
2300 // button border width
2301 size->y += 4;
2302 }
e4606ed9 2303 } else
43be3c33 2304#endif // wxUSE_BUTTON || wxUSE_TOGGLEBTN
9a6384ca 2305#if wxUSE_SCROLLBAR
e4606ed9 2306 if ( wxDynamicCast(window, wxScrollBar) )
1e6feb95
VZ
2307 {
2308 // we only set the width of vert scrollbars and height of the
2309 // horizontal ones
2310 if ( window->GetWindowStyle() & wxSB_HORIZONTAL )
2311 size->y = m_sizeScrollbarArrow.x;
2312 else
2313 size->x = m_sizeScrollbarArrow.x;
2314 }
2315 else
9a6384ca 2316#endif // wxUSE_SCROLLBAR
1e6feb95
VZ
2317 {
2318 // take into account the border width
1cd9779f 2319 wxStdRenderer::AdjustSize(size, window);
1e6feb95
VZ
2320 }
2321}
2322
63f06c22
VS
2323// ----------------------------------------------------------------------------
2324// standard icons
2325// ----------------------------------------------------------------------------
2326
13b22a67 2327/* Copyright (c) Julian Smart */
2b5f62a0 2328static const char *error_xpm[] = {
63f06c22 2329/* columns rows colors chars-per-pixel */
13b22a67
JS
2330"48 48 4 1",
2331" c None",
2332"X c #242424",
2333"o c #DCDF00",
2334". c #C00000",
63f06c22 2335/* pixels */
13b22a67
JS
2336" ",
2337" ",
2338" ",
2339" ",
2340" ",
2341" ..... ",
2342" ............. ",
2343" ................. ",
2344" ................... ",
2345" ....................... ",
2346" ......................... ",
2347" ........................... ",
2348" ...........................X ",
2349" .............................X ",
2350" ............................... ",
2351" ...............................X ",
2352" .................................X ",
2353" .................................X ",
2354" .................................XX ",
2355" ...ooooooooooooooooooooooooooo...XX ",
2356" ....ooooooooooooooooooooooooooo....X ",
2357" ....ooooooooooooooooooooooooooo....X ",
2358" ....ooooooooooooooooooooooooooo....XX ",
2359" ....ooooooooooooooooooooooooooo....XX ",
2360" ....ooooooooooooooooooooooooooo....XX ",
2361" ...ooooooooooooooooooooooooooo...XXX ",
2362" ...ooooooooooooooooooooooooooo...XXX ",
2363" .................................XX ",
2364" .................................XX ",
2365" ...............................XXX ",
2366" ...............................XXX ",
2367" .............................XXX ",
2368" ...........................XXXX ",
2369" ...........................XXX ",
2370" .........................XXX ",
2371" .......................XXXX ",
2372" X...................XXXXX ",
2373" X.................XXXXX ",
2374" X.............XXXXX ",
2375" XXXX.....XXXXXXXX ",
2376" XXXXXXXXXXXXX ",
2377" XXXXX ",
2378" ",
2379" ",
2380" ",
2381" ",
2382" ",
2383" "
63f06c22
VS
2384};
2385
13b22a67 2386/* Copyright (c) Julian Smart */
2b5f62a0 2387static const char *info_xpm[] = {
63f06c22 2388/* columns rows colors chars-per-pixel */
13b22a67
JS
2389"48 48 9 1",
2390"$ c Black",
2391"O c #FFFFFF",
2392"@ c #808080",
2393"+ c #000080",
2394"o c #E8EB01",
2395" c None",
2396"X c #FFFF40",
2397"# c #C0C0C0",
2398". c #ABAD01",
63f06c22 2399/* pixels */
13b22a67
JS
2400" ",
2401" ",
2402" ",
2403" ",
2404" ",
2405" ",
2406" ",
2407" ",
2408" ",
2409" ..... ",
2410" ..XXXXX.. ",
2411" ..XXXXXXXXo.. ",
2412" .XXXOXXXXXXXoo. ",
2413" .XOOXXX+XXXXXo. ",
2414" .XOOOXX+++XXXXoo. ",
2415" .XOOXXX+++XXXXXo. ",
2416" .XOOOXXX+++XXXXXXo. ",
2417" .XOOXXXX+++XXXXXXo. ",
2418" .XXXXXXX+++XXXXXXX. ",
2419" .XXXXXXX+++XXXXXXo. ",
2420" .XXXXXXX+++XXXXXoo. ",
2421" .XXXXXX+++XXXXXo. ",
2422" .XXXXXXX+XXXXXXo. ",
2423" .XXXXXXXXXXXXo. ",
2424" .XXXXX+++XXXoo. ",
2425" .XXXX+++XXoo. ",
2426" .XXXXXXXXo. ",
2427" ..XXXXXXo.. ",
2428" .XXXXXo.. ",
2429" @#######@ ",
2430" @@@@@@@@@ ",
2431" @#######@ ",
2432" @@@@@@@@@ ",
2433" @#######@ ",
2434" @@@@@@@ ",
2435" ### ",
2436" $$$ ",
2437" ",
2438" ",
2439" ",
2440" ",
2441" ",
2442" ",
2443" ",
2444" ",
2445" ",
2446" ",
2447" "
63f06c22
VS
2448};
2449
13b22a67 2450/* Copyright (c) Julian Smart */
2b5f62a0 2451static const char *warning_xpm[] = {
63f06c22 2452/* columns rows colors chars-per-pixel */
13b22a67
JS
2453"48 48 9 1",
2454"@ c Black",
2455"o c #A6A800",
2456"+ c #8A8C00",
2457"$ c #B8BA00",
2458" c None",
2459"O c #6E7000",
2460"X c #DCDF00",
2461". c #C00000",
2462"# c #373800",
63f06c22 2463/* pixels */
13b22a67
JS
2464" ",
2465" ",
2466" ",
2467" ",
2468" ",
2469" ",
2470" ",
2471" . ",
2472" ... ",
2473" ... ",
2474" ..... ",
2475" ...X.. ",
2476" ..XXX.. ",
2477" ...XXX... ",
2478" ..XXXXX.. ",
2479" ..XXXXXX... ",
2480" ...XXoO+XX.. ",
2481" ..XXXO@#XXX.. ",
2482" ..XXXXO@#XXX... ",
2483" ...XXXXO@#XXXX.. ",
2484" ..XXXXXO@#XXXX... ",
2485" ...XXXXXo@OXXXXX.. ",
2486" ...XXXXXXo@OXXXXXX.. ",
2487" ..XXXXXXX$@OXXXXXX... ",
2488" ...XXXXXXXX@XXXXXXXX.. ",
2489" ...XXXXXXXXXXXXXXXXXX... ",
2490" ..XXXXXXXXXXOXXXXXXXXX.. ",
2491" ...XXXXXXXXXO@#XXXXXXXXX.. ",
2492" ..XXXXXXXXXXX#XXXXXXXXXX... ",
2493" ...XXXXXXXXXXXXXXXXXXXXXXX.. ",
2494" ...XXXXXXXXXXXXXXXXXXXXXXXX... ",
2495" .............................. ",
2496" .............................. ",
2497" ",
2498" ",
2499" ",
2500" ",
2501" ",
2502" ",
2503" ",
2504" ",
2505" ",
2506" ",
2507" ",
2508" ",
2509" ",
2510" ",
2511" "
63f06c22
VS
2512};
2513
13b22a67 2514/* Copyright (c) Julian Smart */
2b5f62a0 2515static const char *question_xpm[] = {
63f06c22 2516/* columns rows colors chars-per-pixel */
13b22a67
JS
2517"48 48 21 1",
2518". c Black",
2519"> c #696969",
2520"O c #1F1F00",
2521"+ c #181818",
2522"o c #F6F900",
2523"; c #3F3F00",
2524"$ c #111111",
2525" c None",
2526"& c #202020",
2527"X c #AAAA00",
2528"@ c #949400",
2529": c #303030",
2530"1 c #383838",
2531"% c #2A2A00",
2532", c #404040",
2533"= c #B4B400",
2534"- c #484848",
2535"# c #151500",
2536"< c #9F9F00",
2537"2 c #6A6A00",
2538"* c #353500",
63f06c22 2539/* pixels */
13b22a67
JS
2540" ",
2541" ",
2542" ",
2543" ",
2544" ......... ",
2545" ...XXXXXXX.. ",
2546" ..XXXXoooooXXXO+ ",
2547" ..XXooooooooooooX@.. ",
2548" ..XoooooooooooooooXX#. ",
2549" $%XoooooooooooooooooXX#. ",
2550" &.XoooooooXXXXXXooooooXX.. ",
2551" .XooooooXX.$...$XXoooooX*. ",
2552" $.XoooooX%.$ .*oooooo=.. ",
2553" .XooooooX.. -.XoooooX.. ",
2554" .XoooooX..+ .XoooooX;. ",
2555" ...XXXX..: .XoooooX;. ",
2556" ........ >.XoooooX;. ",
2557" +.XoooooX.. ",
2558" ,.Xoooooo<.. ",
2559" 1#XooooooXO.. ",
2560" &#XooooooX2.. ",
2561" $%XooooooXX.. ",
2562" $%XooooooXX.. ",
2563" $%XooooooXX.. ",
2564" &.XooooooXX.. ",
2565" .XooooooXX.. ",
2566" &.XoooooXX.. ",
2567" ..XooooXX.. ",
2568" ..XooooX... ",
2569" ..XXooXX..& ",
2570" ...XXXXX.. ",
2571" ........ ",
2572" ",
2573" ",
2574" ....... ",
2575" ..XXXXX.. ",
2576" ..XXoooXX.. ",
2577" ..XoooooX.. ",
2578" ..XoooooX.. ",
2579" ..XXoooXX.. ",
2580" ..XXXXX.. ",
2581" ....... ",
2582" ",
2583" ",
2584" ",
2585" ",
2586" ",
2587" "
63f06c22
VS
2588};
2589
536b70ac
VS
2590wxBitmap wxGTKArtProvider::CreateBitmap(const wxArtID& id,
2591 const wxArtClient& WXUNUSED(client),
2592 const wxSize& WXUNUSED(size))
63f06c22 2593{
536b70ac
VS
2594 if ( id == wxART_INFORMATION )
2595 return wxBitmap(info_xpm);
2596 if ( id == wxART_ERROR )
2597 return wxBitmap(error_xpm);
2598 if ( id == wxART_WARNING )
2599 return wxBitmap(warning_xpm);
2600 if ( id == wxART_QUESTION )
2601 return wxBitmap(question_xpm);
2602 return wxNullBitmap;
63f06c22
VS
2603}
2604
24a23c35 2605
1e6feb95
VZ
2606// ============================================================================
2607// wxInputHandler
2608// ============================================================================
2609
2610// ----------------------------------------------------------------------------
2611// wxGTKInputHandler
2612// ----------------------------------------------------------------------------
2613
61fef19b
VZ
2614bool wxGTKInputHandler::HandleKey(wxInputConsumer * WXUNUSED(control),
2615 const wxKeyEvent& WXUNUSED(event),
2616 bool WXUNUSED(pressed))
1e6feb95 2617{
a290fa5a 2618 return false;
1e6feb95
VZ
2619}
2620
67e49a98 2621bool wxGTKInputHandler::HandleMouse(wxInputConsumer *control,
1e6feb95
VZ
2622 const wxMouseEvent& event)
2623{
2624 // clicking on the control gives it focus
67e49a98 2625 if ( event.ButtonDown() && wxWindow::FindFocus() != control->GetInputWindow() )
1e6feb95 2626 {
67e49a98 2627 control->GetInputWindow()->SetFocus();
1e6feb95 2628
a290fa5a 2629 return true;
1e6feb95
VZ
2630 }
2631
a290fa5a 2632 return false;
1e6feb95
VZ
2633}
2634
67e49a98 2635bool wxGTKInputHandler::HandleMouseMove(wxInputConsumer *control,
1e6feb95
VZ
2636 const wxMouseEvent& event)
2637{
2638 if ( event.Entering() )
2639 {
a290fa5a 2640 control->GetInputWindow()->SetCurrent(true);
1e6feb95
VZ
2641 }
2642 else if ( event.Leaving() )
2643 {
a290fa5a 2644 control->GetInputWindow()->SetCurrent(false);
1e6feb95
VZ
2645 }
2646 else
2647 {
a290fa5a 2648 return false;
1e6feb95
VZ
2649 }
2650
a290fa5a 2651 return true;
1e6feb95
VZ
2652}
2653
9a6384ca
WS
2654#if wxUSE_CHECKBOX
2655
1e6feb95
VZ
2656// ----------------------------------------------------------------------------
2657// wxGTKCheckboxInputHandler
2658// ----------------------------------------------------------------------------
2659
67e49a98 2660bool wxGTKCheckboxInputHandler::HandleKey(wxInputConsumer *control,
1e6feb95
VZ
2661 const wxKeyEvent& event,
2662 bool pressed)
2663{
2664 if ( pressed )
2665 {
2666 int keycode = event.GetKeyCode();
2667 if ( keycode == WXK_SPACE || keycode == WXK_RETURN )
2668 {
2669 control->PerformAction(wxACTION_CHECKBOX_TOGGLE);
2670
a290fa5a 2671 return true;
1e6feb95
VZ
2672 }
2673 }
2674
a290fa5a 2675 return false;
1e6feb95
VZ
2676}
2677
9a6384ca
WS
2678#endif // wxUSE_CHECKBOX
2679
2680#if wxUSE_TEXTCTRL
2681
1e6feb95
VZ
2682// ----------------------------------------------------------------------------
2683// wxGTKTextCtrlInputHandler
2684// ----------------------------------------------------------------------------
2685
67e49a98 2686bool wxGTKTextCtrlInputHandler::HandleKey(wxInputConsumer *control,
1e6feb95
VZ
2687 const wxKeyEvent& event,
2688 bool pressed)
2689{
2690 // handle only GTK-specific text bindings here, the others are handled in
2691 // the base class
2692 if ( pressed )
2693 {
2694 wxControlAction action;
2695 int keycode = event.GetKeyCode();
2696 if ( event.ControlDown() )
2697 {
2698 switch ( keycode )
2699 {
2700 case 'A':
2701 action = wxACTION_TEXT_HOME;
2702 break;
2703
2704 case 'B':
2705 action = wxACTION_TEXT_LEFT;
2706 break;
2707
2708 case 'D':
2709 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_RIGHT;
2710 break;
2711
2712 case 'E':
2713 action = wxACTION_TEXT_END;
2714 break;
2715
2716 case 'F':
2717 action = wxACTION_TEXT_RIGHT;
2718 break;
2719
2720 case 'H':
2721 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_LEFT;
2722 break;
2723
2724 case 'K':
2725 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_END;
2726 break;
2727
2728 case 'N':
2729 action = wxACTION_TEXT_DOWN;
2730 break;
2731
2732 case 'P':
2733 action = wxACTION_TEXT_UP;
2734 break;
2735
2736 case 'U':
2737 //delete the entire line
2738 control->PerformAction(wxACTION_TEXT_HOME);
2739 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_END;
2740 break;
2741
2742 case 'W':
2743 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_WORD_LEFT;
2744 break;
2745 }
2746 }
2747 else if ( event.AltDown() )
2748 {
2749 switch ( keycode )
2750 {
2751 case 'B':
2752 action = wxACTION_TEXT_WORD_LEFT;
2753 break;
2754
2755 case 'D':
2756 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_WORD_RIGHT;
2757 break;
2758
2759 case 'F':
2760 action = wxACTION_TEXT_WORD_RIGHT;
2761 break;
2762 }
2763 }
2764
2765 if ( action != wxACTION_NONE )
2766 {
2767 control->PerformAction(action);
2768
a290fa5a 2769 return true;
1e6feb95
VZ
2770 }
2771 }
2772
9467bdb7 2773 return wxStdInputHandler::HandleKey(control, event, pressed);
1e6feb95 2774}
9a6384ca
WS
2775
2776#endif // wxUSE_TEXTCTRL
4353a8df 2777
e7637222 2778#endif // wxUSE_THEME_GTK