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