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