]> git.saurik.com Git - wxWidgets.git/blame - src/univ/themes/gtk.cpp
Fix crash in wxStaticBox::HandleEraseBkgnd() in wxMSW on closing.
[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"
23205be8 35 #include "wx/dcclient.h"
1e6feb95
VZ
36 #include "wx/window.h"
37
0fe5e8fe
VZ
38 #include "wx/menu.h"
39
e4606ed9 40 #include "wx/bmpbuttn.h"
1e6feb95
VZ
41 #include "wx/button.h"
42 #include "wx/checkbox.h"
43 #include "wx/listbox.h"
44 #include "wx/checklst.h"
8cb172b4 45 #include "wx/combobox.h"
1e6feb95
VZ
46 #include "wx/scrolbar.h"
47 #include "wx/slider.h"
48 #include "wx/textctrl.h"
3216dbf5 49 #include "wx/toolbar.h"
c2919ab3 50 #include "wx/statusbr.h"
0fe5e8fe
VZ
51
52 #include "wx/settings.h"
1832043f 53 #include "wx/toplevel.h"
155ecd4c 54 #include "wx/image.h"
1e6feb95
VZ
55#endif // WX_PRECOMP
56
57#include "wx/notebook.h"
58#include "wx/spinbutt.h"
536b70ac 59#include "wx/artprov.h"
43be3c33 60#include "wx/tglbtn.h"
1e6feb95 61
147b8a4a 62#include "wx/univ/stdrend.h"
9467bdb7 63#include "wx/univ/inpcons.h"
1e6feb95
VZ
64#include "wx/univ/inphand.h"
65#include "wx/univ/colschem.h"
1e6feb95 66
b5dbe15d 67class wxGTKMenuGeometryInfo;
0fe5e8fe 68
1e6feb95 69// ----------------------------------------------------------------------------
147b8a4a 70// constants
1e6feb95
VZ
71// ----------------------------------------------------------------------------
72
147b8a4a
VZ
73// standard border size
74static const int BORDER_THICKNESS = 2;
1e6feb95
VZ
75
76// ----------------------------------------------------------------------------
77// wxGTKRenderer: draw the GUI elements in GTK style
78// ----------------------------------------------------------------------------
79
147b8a4a 80class wxGTKRenderer : public wxStdRenderer
1e6feb95
VZ
81{
82public:
83 wxGTKRenderer(const wxColourScheme *scheme);
84
147b8a4a 85 // wxRenderer methods
6d789987 86 virtual void DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags = 0);
147b8a4a
VZ
87 virtual void DrawTextBorder(wxDC& dc,
88 wxBorder border,
1e6feb95 89 const wxRect& rect,
193e19cf 90 int flags = 0,
147b8a4a 91 wxRect *rectIn = NULL);
1e6feb95
VZ
92 virtual void DrawButtonLabel(wxDC& dc,
93 const wxString& label,
94 const wxBitmap& image,
95 const wxRect& rect,
147b8a4a
VZ
96 int flags,
97 int alignment,
98 int indexAccel,
99 wxRect *rectBounds);
1e6feb95
VZ
100 virtual void DrawButtonBorder(wxDC& dc,
101 const wxRect& rect,
102 int flags = 0,
147b8a4a 103 wxRect *rectIn = NULL);
1e6feb95
VZ
104 virtual void DrawArrow(wxDC& dc,
105 wxDirection dir,
106 const wxRect& rect,
107 int flags = 0);
108 virtual void DrawScrollbarArrow(wxDC& dc,
109 wxDirection dir,
110 const wxRect& rect,
111 int flags = 0);
112 virtual void DrawScrollbarThumb(wxDC& dc,
113 wxOrientation orient,
114 const wxRect& rect,
115 int flags = 0);
116 virtual void DrawScrollbarShaft(wxDC& dc,
117 wxOrientation orient,
118 const wxRect& rect,
119 int flags = 0);
1e6feb95 120
9a6384ca 121#if wxUSE_TOOLBAR
3216dbf5
VZ
122 virtual void DrawToolBarButton(wxDC& dc,
123 const wxString& label,
124 const wxBitmap& bitmap,
125 const wxRect& rect,
a8f4cabe 126 int flags = 0,
370efbe7
WS
127 long style = 0,
128 int tbarStyle = 0);
9a6384ca 129#endif // wxUSE_TOOLBAR
3216dbf5 130
147b8a4a 131#if wxUSE_TEXTCTRL
1e6feb95 132 virtual void DrawLineWrapMark(wxDC& dc, const wxRect& rect);
147b8a4a
VZ
133#endif // wxUSE_TEXTCTRL
134
c4036939 135#if wxUSE_NOTEBOOK
1e6feb95
VZ
136 virtual void DrawTab(wxDC& dc,
137 const wxRect& rect,
138 wxDirection dir,
139 const wxString& label,
140 const wxBitmap& bitmap = wxNullBitmap,
141 int flags = 0,
142 int indexAccel = -1);
c4036939 143#endif // wxUSE_NOTEBOOK
1e6feb95 144
9a6384ca 145#if wxUSE_SLIDER
1e6feb95
VZ
146 virtual void DrawSliderShaft(wxDC& dc,
147 const wxRect& rect,
6766e5d1 148 int lenThumb,
1e6feb95
VZ
149 wxOrientation orient,
150 int flags = 0,
6766e5d1 151 long style = 0,
1e6feb95
VZ
152 wxRect *rectShaft = NULL);
153 virtual void DrawSliderThumb(wxDC& dc,
154 const wxRect& rect,
155 wxOrientation orient,
6766e5d1
JS
156 int flags = 0,
157 long style = 0);
61fef19b
VZ
158 virtual void DrawSliderTicks(wxDC& WXUNUSED(dc),
159 const wxRect& WXUNUSED(rect),
160 int WXUNUSED(lenThumb),
161 wxOrientation WXUNUSED(orient),
162 int WXUNUSED(start),
163 int WXUNUSED(end),
164 int WXUNUSED(step) = 1,
165 int WXUNUSED(flags) = 0,
166 long WXUNUSED(style) = 0)
1e6feb95
VZ
167 {
168 // we don't have the ticks in GTK version
169 }
9a6384ca 170#endif // wxUSE_SLIDER
1e6feb95 171
9a6384ca 172#if wxUSE_MENUS
1e6feb95
VZ
173 virtual void DrawMenuBarItem(wxDC& dc,
174 const wxRect& rect,
175 const wxString& label,
176 int flags = 0,
177 int indexAccel = -1);
178 virtual void DrawMenuItem(wxDC& dc,
179 wxCoord y,
180 const wxMenuGeometryInfo& geometryInfo,
181 const wxString& label,
182 const wxString& accel,
183 const wxBitmap& bitmap = wxNullBitmap,
184 int flags = 0,
185 int indexAccel = -1);
186 virtual void DrawMenuSeparator(wxDC& dc,
187 wxCoord y,
188 const wxMenuGeometryInfo& geomInfo);
9a6384ca 189#endif // wxUSE_MENUS
71e03035 190
1e6feb95 191 virtual void GetComboBitmaps(wxBitmap *bmpNormal,
1b488c0e 192 wxBitmap *bmpFocus,
1e6feb95
VZ
193 wxBitmap *bmpPressed,
194 wxBitmap *bmpDisabled);
195
196 virtual void AdjustSize(wxSize *size, const wxWindow *window);
1e6feb95
VZ
197
198 // geometry and hit testing
56195504 199#if wxUSE_SCROLLBAR
1e6feb95
VZ
200 virtual wxSize GetScrollbarArrowSize() const
201 { return m_sizeScrollbarArrow; }
9a6384ca
WS
202#endif // wxUSE_SCROLLBAR
203
1e6feb95
VZ
204 virtual wxSize GetCheckBitmapSize() const
205 { return wxSize(10, 10); }
206 virtual wxSize GetRadioBitmapSize() const
207 { return wxSize(11, 11); }
208 virtual wxCoord GetCheckItemMargin() const
209 { return 2; }
210
dd267523 211#if wxUSE_TOOLBAR
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); }
dd267523 216#endif // wxUSE_TOOLBAR
3216dbf5 217
9a6384ca 218#if wxUSE_TEXTCTRL
1e6feb95
VZ
219 virtual wxRect GetTextClientArea(const wxTextCtrl *text,
220 const wxRect& rect,
3216dbf5 221 wxCoord *extraSpaceBeyond) const;
9a6384ca 222#endif // wxUSE_TEXTCTRL
1e6feb95 223
c4036939 224#if wxUSE_NOTEBOOK
1e6feb95
VZ
225 virtual wxSize GetTabIndent() const { return wxSize(2, 2); }
226 virtual wxSize GetTabPadding() const { return wxSize(6, 6); }
c4036939 227#endif // wxUSE_NOTEBOOK
1e6feb95 228
9a6384ca 229#if wxUSE_SLIDER
1e6feb95
VZ
230 virtual wxCoord GetSliderDim() const { return 15; }
231 virtual wxCoord GetSliderTickLen() const { return 0; }
232 virtual wxRect GetSliderShaftRect(const wxRect& rect,
6766e5d1
JS
233 int lenThumb,
234 wxOrientation orient,
235 long style = 0) const;
1e6feb95 236 virtual wxSize GetSliderThumbSize(const wxRect& rect,
6766e5d1 237 int lenThumb,
1e6feb95 238 wxOrientation orient) const;
9a6384ca
WS
239#endif // wxUSE_SLIDER
240
1e6feb95
VZ
241 virtual wxSize GetProgressBarStep() const { return wxSize(16, 32); }
242
9a6384ca 243#if wxUSE_MENUS
1e6feb95
VZ
244 virtual wxSize GetMenuBarItemSize(const wxSize& sizeText) const;
245 virtual wxMenuGeometryInfo *GetMenuGeometry(wxWindow *win,
246 const wxMenu& menu) const;
9a6384ca 247#endif // wxUSE_MENUS
71e03035 248
1e6feb95
VZ
249 // helpers for "wxBitmap wxColourScheme::Get()"
250 void DrawCheckBitmap(wxDC& dc, const wxRect& rect);
251 void DrawUncheckBitmap(wxDC& dc, const wxRect& rect, bool isPressed);
415a0ff1 252 void DrawUndeterminedBitmap(wxDC& dc, const wxRect& rect, bool isPressed);
1e6feb95
VZ
253
254protected:
6229b92f 255 // overridden wxStdRenderer methods
147b8a4a
VZ
256 virtual void DrawSunkenBorder(wxDC& dc, wxRect *rect);
257
258 virtual void DrawFrameWithLabel(wxDC& dc,
259 const wxString& label,
260 const wxRect& rectFrame,
261 const wxRect& rectText,
262 int flags,
263 int alignment,
264 int indexAccel);
1e6feb95 265
6229b92f
VZ
266 virtual void DrawCheckItemBitmap(wxDC& dc,
267 const wxBitmap& bitmap,
268 const wxRect& rect,
269 int flags);
270
1e6feb95
VZ
271 // get the colour to use for background
272 wxColour GetBackgroundColour(int flags) const
273 {
274 if ( flags & wxCONTROL_PRESSED )
275 return wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED);
276 else if ( flags & wxCONTROL_CURRENT )
277 return wxSCHEME_COLOUR(m_scheme, CONTROL_CURRENT);
278 else
279 return wxSCHEME_COLOUR(m_scheme, CONTROL);
280 }
281
1e6feb95
VZ
282 // as DrawShadedRect() but the pixels in the bottom left and upper right
283 // border are drawn with the pen1, not pen2
284 void DrawAntiShadedRect(wxDC& dc, wxRect *rect,
285 const wxPen& pen1, const wxPen& pen2);
286
287 // used for drawing opened rectangles - draws only one side of it at once
288 // (and doesn't adjust the rect)
289 void DrawAntiShadedRectSide(wxDC& dc,
290 const wxRect& rect,
291 const wxPen& pen1,
292 const wxPen& pen2,
293 wxDirection dir);
294
295 // draw an opened rect for the arrow in given direction
296 void DrawArrowBorder(wxDC& dc,
297 wxRect *rect,
298 wxDirection dir);
299
300 // draw two sides of the rectangle
301 void DrawThumbBorder(wxDC& dc,
302 wxRect *rect,
303 wxOrientation orient);
304
1e6feb95
VZ
305 // just as DrawRaisedBorder() except that the bottom left and up right
306 // pixels of the interior rect are drawn in another colour (i.e. the inner
307 // rect is drawn with DrawAntiShadedRect() and not DrawShadedRect())
308 void DrawAntiRaisedBorder(wxDC& dc, wxRect *rect);
309
147b8a4a
VZ
310 // draw inner GTK shadow
311 void DrawInnerShadedRect(wxDC& dc, wxRect *rect);
312
1e6feb95 313 // get the line wrap indicator bitmap
3216dbf5 314 wxBitmap GetLineWrapBitmap() const;
1e6feb95 315
147b8a4a
VZ
316 virtual wxBitmap GetCheckBitmap(int flags);
317 virtual wxBitmap GetRadioBitmap(int flags);
1e6feb95
VZ
318
319 // draw a /\ or \/ line from (x1, y1) to (x2, y1) passing by the point
320 // ((x1 + x2)/2, y2)
321 void DrawUpZag(wxDC& dc,
322 wxCoord x1, wxCoord x2,
323 wxCoord y1, wxCoord y2);
324 void DrawDownZag(wxDC& dc,
325 wxCoord x1, wxCoord x2,
326 wxCoord y1, wxCoord y2);
327
328 // draw the radio button bitmap for the given state
6e6b532c 329 void DrawRadioButtonBitmap(wxDC& dc, const wxRect& rect, int flags);
1e6feb95 330
0fe5e8fe
VZ
331 // common part of DrawMenuItem() and DrawMenuBarItem()
332 void DoDrawMenuItem(wxDC& dc,
333 const wxRect& rect,
334 const wxString& label,
335 int flags,
336 int indexAccel,
8b5d5223 337 const wxString& accel = wxEmptyString,
0fe5e8fe
VZ
338 const wxBitmap& bitmap = wxNullBitmap,
339 const wxGTKMenuGeometryInfo *geometryInfo = NULL);
340
1b488c0e
VZ
341 // initialize the combo bitmaps
342 void InitComboBitmaps();
343
249803fb
VZ
344 virtual wxBitmap GetFrameButtonBitmap(FrameButtonType WXUNUSED(type))
345 {
346 return wxNullBitmap;
347 }
348
1e6feb95 349private:
1e6feb95
VZ
350 // data
351 wxSize m_sizeScrollbarArrow;
352
353 // GDI objects
147b8a4a 354 wxPen m_penGrey;
1e6feb95 355
147b8a4a
VZ
356 // the checkbox and radio button bitmaps: first row is for the normal,
357 // second for the pressed state and the columns are for checked, unchecked
358 // and undeterminated respectively
359 wxBitmap m_bitmapsCheckbox[IndicatorState_MaxCtrl][IndicatorStatus_Max],
360 m_bitmapsRadiobtn[IndicatorState_MaxCtrl][IndicatorStatus_Max];
1e6feb95
VZ
361
362 // the line wrap bitmap (drawn at the end of wrapped lines)
363 wxBitmap m_bmpLineWrap;
1b488c0e
VZ
364
365 // the combobox bitmaps
366 enum
367 {
368 ComboState_Normal,
369 ComboState_Focus,
370 ComboState_Pressed,
371 ComboState_Disabled,
372 ComboState_Max
373 };
374
375 wxBitmap m_bitmapsCombo[ComboState_Max];
1e6feb95
VZ
376};
377
378// ----------------------------------------------------------------------------
379// wxGTKInputHandler and derived classes: process the keyboard and mouse
380// messages according to GTK standards
381// ----------------------------------------------------------------------------
382
383class wxGTKInputHandler : public wxInputHandler
384{
385public:
9467bdb7 386 wxGTKInputHandler() { }
1e6feb95 387
67e49a98 388 virtual bool HandleKey(wxInputConsumer *control,
1e6feb95
VZ
389 const wxKeyEvent& event,
390 bool pressed);
67e49a98 391 virtual bool HandleMouse(wxInputConsumer *control,
1e6feb95 392 const wxMouseEvent& event);
9467bdb7
VZ
393 virtual bool HandleMouseMove(wxInputConsumer *control,
394 const wxMouseEvent& event);
1e6feb95
VZ
395};
396
9a6384ca
WS
397#if wxUSE_SCROLLBAR
398
1e6feb95
VZ
399class wxGTKScrollBarInputHandler : public wxStdScrollBarInputHandler
400{
401public:
402 wxGTKScrollBarInputHandler(wxRenderer *renderer, wxInputHandler *handler)
403 : wxStdScrollBarInputHandler(renderer, handler) { }
404
405protected:
406 virtual void Highlight(wxScrollBar *scrollbar, bool doIt)
407 {
408 // only arrows and the thumb can be highlighted
409 if ( !IsArrow() && m_htLast != wxHT_SCROLLBAR_THUMB )
410 return;
411
412 wxStdScrollBarInputHandler::Highlight(scrollbar, doIt);
413 }
414
415 virtual void Press(wxScrollBar *scrollbar, bool doIt)
416 {
417 // only arrows can be pressed
418 if ( !IsArrow() )
419 return;
420
421 wxStdScrollBarInputHandler::Press(scrollbar, doIt);
422 }
423
9467bdb7
VZ
424 // any button can be used to drag the scrollbar under GTK+
425 virtual bool IsAllowedButton(int WXUNUSED(button)) const { return true; }
1e6feb95
VZ
426
427 bool IsArrow() const
428 {
429 return m_htLast == wxHT_SCROLLBAR_ARROW_LINE_1 ||
430 m_htLast == wxHT_SCROLLBAR_ARROW_LINE_2;
431 }
432};
433
9a6384ca
WS
434#endif // wxUSE_SCROLLBAR
435
436#if wxUSE_CHECKBOX
437
9467bdb7 438class wxGTKCheckboxInputHandler : public wxStdInputHandler
1e6feb95
VZ
439{
440public:
441 wxGTKCheckboxInputHandler(wxInputHandler *handler)
9467bdb7 442 : wxStdInputHandler(handler) { }
1e6feb95 443
67e49a98 444 virtual bool HandleKey(wxInputConsumer *control,
1e6feb95
VZ
445 const wxKeyEvent& event,
446 bool pressed);
447};
448
9a6384ca
WS
449#endif // wxUSE_CHECKBOX
450
451#if wxUSE_TEXTCTRL
452
9467bdb7 453class wxGTKTextCtrlInputHandler : public wxStdInputHandler
1e6feb95
VZ
454{
455public:
456 wxGTKTextCtrlInputHandler(wxInputHandler *handler)
9467bdb7 457 : wxStdInputHandler(handler) { }
1e6feb95 458
67e49a98 459 virtual bool HandleKey(wxInputConsumer *control,
1e6feb95
VZ
460 const wxKeyEvent& event,
461 bool pressed);
462};
463
9a6384ca
WS
464#endif // wxUSE_TEXTCTRL
465
1e6feb95
VZ
466// ----------------------------------------------------------------------------
467// wxGTKColourScheme: uses the standard GTK colours
468// ----------------------------------------------------------------------------
469
470class wxGTKColourScheme : public wxColourScheme
471{
472public:
473 virtual wxColour Get(StdColour col) const;
474 virtual wxColour GetBackground(wxWindow *win) const;
475};
476
536b70ac
VS
477// ----------------------------------------------------------------------------
478// wxGTKArtProvider
479// ----------------------------------------------------------------------------
480
481class wxGTKArtProvider : public wxArtProvider
482{
483protected:
484 virtual wxBitmap CreateBitmap(const wxArtID& id,
485 const wxArtClient& client,
486 const wxSize& size);
487};
488
1e6feb95
VZ
489// ----------------------------------------------------------------------------
490// wxGTKTheme
491// ----------------------------------------------------------------------------
492
d5d29b8a 493WX_DEFINE_ARRAY_PTR(wxInputHandler *, wxArrayHandlers);
1e6feb95
VZ
494
495class wxGTKTheme : public wxTheme
496{
497public:
498 wxGTKTheme();
499 virtual ~wxGTKTheme();
500
240889a1 501 virtual wxRenderer *GetRenderer();
536b70ac 502 virtual wxArtProvider *GetArtProvider();
9467bdb7
VZ
503 virtual wxInputHandler *GetInputHandler(const wxString& control,
504 wxInputConsumer *consumer);
240889a1 505 virtual wxColourScheme *GetColourScheme();
1e6feb95
VZ
506
507private:
1e6feb95 508 wxGTKRenderer *m_renderer;
9ef3ebfb 509
536b70ac 510 wxGTKArtProvider *m_artProvider;
1e6feb95
VZ
511
512 // the names of the already created handlers and the handlers themselves
513 // (these arrays are synchronized)
514 wxSortedArrayString m_handlerNames;
515 wxArrayHandlers m_handlers;
516
1e6feb95
VZ
517 wxGTKColourScheme *m_scheme;
518
519 WX_DECLARE_THEME(gtk)
520};
521
522// ============================================================================
523// implementation
524// ============================================================================
525
526WX_IMPLEMENT_THEME(wxGTKTheme, gtk, wxTRANSLATE("GTK+ theme"));
527
528// ----------------------------------------------------------------------------
529// wxGTKTheme
530// ----------------------------------------------------------------------------
531
532wxGTKTheme::wxGTKTheme()
533{
240889a1
VS
534 m_scheme = NULL;
535 m_renderer = NULL;
9ef3ebfb 536 m_artProvider = NULL;
1e6feb95
VZ
537}
538
539wxGTKTheme::~wxGTKTheme()
540{
1e6feb95
VZ
541 delete m_renderer;
542 delete m_scheme;
571d2e0f 543 delete m_artProvider;
1e6feb95
VZ
544}
545
240889a1
VS
546wxRenderer *wxGTKTheme::GetRenderer()
547{
548 if ( !m_renderer )
549 {
550 m_renderer = new wxGTKRenderer(GetColourScheme());
551 }
552
553 return m_renderer;
554}
555
536b70ac
VS
556wxArtProvider *wxGTKTheme::GetArtProvider()
557{
558 if ( !m_artProvider )
559 {
560 m_artProvider = new wxGTKArtProvider;
561 }
562
563 return m_artProvider;
564}
565
240889a1
VS
566wxColourScheme *wxGTKTheme::GetColourScheme()
567{
568 if ( !m_scheme )
569 {
570 m_scheme = new wxGTKColourScheme;
571 }
572 return m_scheme;
573}
574
9467bdb7
VZ
575wxInputHandler *wxGTKTheme::GetInputHandler(const wxString& control,
576 wxInputConsumer *consumer)
1e6feb95 577{
9a6384ca 578 wxInputHandler *handler = NULL;
1e6feb95
VZ
579 int n = m_handlerNames.Index(control);
580 if ( n == wxNOT_FOUND )
581 {
9467bdb7
VZ
582 static wxGTKInputHandler s_handlerDef;
583
584 wxInputHandler * const
585 handlerStd = consumer->DoGetStdInputHandler(&s_handlerDef);
586
1e6feb95 587 // create a new handler
9467bdb7
VZ
588#if wxUSE_CHECKBOX
589 if ( control == wxINP_HANDLER_CHECKBOX )
9a6384ca 590 {
9467bdb7
VZ
591 static wxGTKCheckboxInputHandler s_handler(handlerStd);
592
593 handler = &s_handler;
9a6384ca 594 }
9467bdb7 595 else
1e6feb95 596#endif // wxUSE_CHECKBOX
9467bdb7
VZ
597#if wxUSE_SCROLLBAR
598 if ( control == wxINP_HANDLER_SCROLLBAR )
599 {
600 static wxGTKScrollBarInputHandler s_handler(m_renderer, handlerStd);
601
602 handler = &s_handler;
603 }
604 else
605#endif // wxUSE_SCROLLBAR
1e6feb95 606#if wxUSE_TEXTCTRL
9467bdb7
VZ
607 if ( control == wxINP_HANDLER_TEXTCTRL )
608 {
609 static wxGTKTextCtrlInputHandler s_handler(handlerStd);
9a6384ca 610
9467bdb7
VZ
611 handler = &s_handler;
612 }
613 else
614#endif // wxUSE_TEXTCTRL
615 {
616 // no special handler for this control
617 handler = handlerStd;
618 }
1e6feb95
VZ
619
620 n = m_handlerNames.Add(control);
621 m_handlers.Insert(handler, n);
622 }
623 else // we already have it
624 {
625 handler = m_handlers[n];
626 }
627
628 return handler;
629}
630
631// ============================================================================
632// wxGTKColourScheme
633// ============================================================================
634
635wxColour wxGTKColourScheme::GetBackground(wxWindow *win) const
636{
637 wxColour col;
638 if ( win->UseBgCol() )
639 {
640 // use the user specified colour
641 col = win->GetBackgroundColour();
642 }
643
230205ae 644 if ( !win->ShouldInheritColours() )
1e6feb95
VZ
645 {
646 // doesn't depend on the state
a1b806b9 647 if ( !col.IsOk() )
1e6feb95
VZ
648 {
649 col = Get(WINDOW);
650 }
651 }
652 else
653 {
654 int flags = win->GetStateFlags();
655
656 // the colour set by the user should be used for the normal state
657 // and for the states for which we don't have any specific colours
a1b806b9 658 if ( !col.IsOk() || (flags != 0) )
1e6feb95 659 {
9a6384ca 660#if wxUSE_SCROLLBAR
1e6feb95
VZ
661 if ( wxDynamicCast(win, wxScrollBar) )
662 col = Get(SCROLLBAR);
9a6384ca
WS
663 else
664#endif //wxUSE_SCROLLBAR
665 if ( (flags & wxCONTROL_CURRENT) && win->CanBeHighlighted() )
1e6feb95
VZ
666 col = Get(CONTROL_CURRENT);
667 else if ( flags & wxCONTROL_PRESSED )
668 col = Get(CONTROL_PRESSED);
669 else
670 col = Get(CONTROL);
671 }
672 }
673
674 return col;
675}
676
677wxColour wxGTKColourScheme::Get(wxGTKColourScheme::StdColour col) const
678{
679 switch ( col )
680 {
9c6d8b7c 681 case FRAME:
1e6feb95
VZ
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:
9a83f860 717 wxFAIL_MSG(wxT("invalid standard colour"));
1e6feb95
VZ
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:
9a83f860 773 wxFAIL_MSG(wxT("unknown rectangle side"));
1e6feb95
VZ
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 814void
6d789987 815wxGTKRenderer::DrawFocusRect(wxWindow* WXUNUSED(win), 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// ----------------------------------------------------------------------------
4efffd87 926// check/radio 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
6e6b532c
VZ
998void wxGTKRenderer::DrawRadioButtonBitmap(wxDC& dc,
999 const wxRect& rect,
1000 int flags)
1e6feb95
VZ
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{
a1b806b9 1070 if ( !m_bitmapsCheckbox[0][0].IsOk() )
1e6feb95
VZ
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];
a1b806b9 1127 if ( !bmp.IsOk() )
147b8a4a
VZ
1128 {
1129 const wxSize size = GetRadioBitmapSize();
1130
1131 wxMemoryDC dc;
1132 bmp.Create(size.x, size.y);
1133 dc.SelectObject(bmp);
1134
6e6b532c 1135 DrawRadioButtonBitmap(dc, size, flags);
147b8a4a
VZ
1136 }
1137
1138 return bmp;
1e6feb95
VZ
1139}
1140
3216dbf5 1141wxBitmap wxGTKRenderer::GetLineWrapBitmap() const
1e6feb95 1142{
a1b806b9 1143 if ( !m_bmpLineWrap.IsOk() )
1e6feb95
VZ
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);
a1b806b9 1154 if ( !bmpLineWrap.IsOk() )
1e6feb95 1155 {
9a83f860 1156 wxFAIL_MSG( wxT("Failed to create line wrap XBM") );
1e6feb95
VZ
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
a1b806b9 1177 if ( !label.empty() || bitmap.IsOk() )
3216dbf5
VZ
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
a1b806b9 1261 if ( colFgOld.IsOk() )
1e6feb95
VZ
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:
9a83f860 1304 wxFAIL_MSG(wxT("invaild notebook tab orientation"));
1e6feb95
VZ
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 1573// wxGTKMenuGeometryInfo: the wxMenuGeometryInfo used by wxGTKRenderer
b5dbe15d 1574class wxGTKMenuGeometryInfo : public wxMenuGeometryInfo
0fe5e8fe
VZ
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;
a1b806b9 1678 if ( !bmp.IsOk() && (flags & wxCONTROL_CHECKABLE) )
0fe5e8fe
VZ
1679 {
1680 bmp = GetCheckBitmap(flags);
1681 }
1682
a1b806b9 1683 if ( bmp.IsOk() )
0fe5e8fe
VZ
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
9a83f860 1704 wxCHECK_RET( geometryInfo, wxT("accel strings only valid for menus") );
0fe5e8fe
VZ
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 {
9a83f860 1716 wxCHECK_RET( geometryInfo, wxT("wxCONTROL_ISSUBMENU only valid for menus") );
0fe5e8fe
VZ
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;
c267759c 1783 dc.GetTextExtent(item->GetItemLabelText(), &widthLabel, NULL);
0fe5e8fe
VZ
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();
a1b806b9 1797 if ( bmp.IsOk() )
0fe5e8fe
VZ
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{
a1b806b9 1879 if ( !m_bitmapsCombo[ComboState_Normal].IsOk() )
1b488c0e
VZ
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:
9a83f860 1951 wxFAIL_MSG(wxT("unknown arrow direction"));
1e6feb95
VZ
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:
9a83f860 2086 wxFAIL_MSG(wxT("unknown arrow direction"));
1e6feb95
VZ
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]);
a1b806b9 2098 if ( penShadow[3].IsOk() )
1e6feb95
VZ
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);
a1b806b9 2110 if ( penShadow[2].IsOk() )
1e6feb95
VZ
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);
a1b806b9 2124 if ( penShadow[2].IsOk() )
1e6feb95
VZ
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]);
a1b806b9 2138 if ( penShadow[2].IsOk() )
1e6feb95
VZ
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:
9a83f860 2163 wxFAIL_MSG(wxT("unknown arrow direction"));
1e6feb95
VZ
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 2267 {
82e17295
DS
2268 /*
2269 Don't adjust the size for a scrollbar as its DoGetBestClientSize
2270 already has the correct size set. Any size changes here would get
2271 added to the best size, making the scrollbar larger.
2272 Also skip border width adjustments, they don't make sense for us.
2273 */
2274 return;
1e6feb95
VZ
2275 }
2276 else
9a6384ca 2277#endif // wxUSE_SCROLLBAR
1e6feb95
VZ
2278 {
2279 // take into account the border width
1cd9779f 2280 wxStdRenderer::AdjustSize(size, window);
1e6feb95
VZ
2281 }
2282}
2283
63f06c22
VS
2284// ----------------------------------------------------------------------------
2285// standard icons
2286// ----------------------------------------------------------------------------
2287
13b22a67 2288/* Copyright (c) Julian Smart */
2b5f62a0 2289static const char *error_xpm[] = {
63f06c22 2290/* columns rows colors chars-per-pixel */
13b22a67
JS
2291"48 48 4 1",
2292" c None",
2293"X c #242424",
2294"o c #DCDF00",
2295". c #C00000",
63f06c22 2296/* pixels */
13b22a67
JS
2297" ",
2298" ",
2299" ",
2300" ",
2301" ",
2302" ..... ",
2303" ............. ",
2304" ................. ",
2305" ................... ",
2306" ....................... ",
2307" ......................... ",
2308" ........................... ",
2309" ...........................X ",
2310" .............................X ",
2311" ............................... ",
2312" ...............................X ",
2313" .................................X ",
2314" .................................X ",
2315" .................................XX ",
2316" ...ooooooooooooooooooooooooooo...XX ",
2317" ....ooooooooooooooooooooooooooo....X ",
2318" ....ooooooooooooooooooooooooooo....X ",
2319" ....ooooooooooooooooooooooooooo....XX ",
2320" ....ooooooooooooooooooooooooooo....XX ",
2321" ....ooooooooooooooooooooooooooo....XX ",
2322" ...ooooooooooooooooooooooooooo...XXX ",
2323" ...ooooooooooooooooooooooooooo...XXX ",
2324" .................................XX ",
2325" .................................XX ",
2326" ...............................XXX ",
2327" ...............................XXX ",
2328" .............................XXX ",
2329" ...........................XXXX ",
2330" ...........................XXX ",
2331" .........................XXX ",
2332" .......................XXXX ",
2333" X...................XXXXX ",
2334" X.................XXXXX ",
2335" X.............XXXXX ",
2336" XXXX.....XXXXXXXX ",
2337" XXXXXXXXXXXXX ",
2338" XXXXX ",
2339" ",
2340" ",
2341" ",
2342" ",
2343" ",
2344" "
63f06c22
VS
2345};
2346
13b22a67 2347/* Copyright (c) Julian Smart */
2b5f62a0 2348static const char *info_xpm[] = {
63f06c22 2349/* columns rows colors chars-per-pixel */
13b22a67
JS
2350"48 48 9 1",
2351"$ c Black",
2352"O c #FFFFFF",
2353"@ c #808080",
2354"+ c #000080",
2355"o c #E8EB01",
2356" c None",
2357"X c #FFFF40",
2358"# c #C0C0C0",
2359". c #ABAD01",
63f06c22 2360/* pixels */
13b22a67
JS
2361" ",
2362" ",
2363" ",
2364" ",
2365" ",
2366" ",
2367" ",
2368" ",
2369" ",
2370" ..... ",
2371" ..XXXXX.. ",
2372" ..XXXXXXXXo.. ",
2373" .XXXOXXXXXXXoo. ",
2374" .XOOXXX+XXXXXo. ",
2375" .XOOOXX+++XXXXoo. ",
2376" .XOOXXX+++XXXXXo. ",
2377" .XOOOXXX+++XXXXXXo. ",
2378" .XOOXXXX+++XXXXXXo. ",
2379" .XXXXXXX+++XXXXXXX. ",
2380" .XXXXXXX+++XXXXXXo. ",
2381" .XXXXXXX+++XXXXXoo. ",
2382" .XXXXXX+++XXXXXo. ",
2383" .XXXXXXX+XXXXXXo. ",
2384" .XXXXXXXXXXXXo. ",
2385" .XXXXX+++XXXoo. ",
2386" .XXXX+++XXoo. ",
2387" .XXXXXXXXo. ",
2388" ..XXXXXXo.. ",
2389" .XXXXXo.. ",
2390" @#######@ ",
2391" @@@@@@@@@ ",
2392" @#######@ ",
2393" @@@@@@@@@ ",
2394" @#######@ ",
2395" @@@@@@@ ",
2396" ### ",
2397" $$$ ",
2398" ",
2399" ",
2400" ",
2401" ",
2402" ",
2403" ",
2404" ",
2405" ",
2406" ",
2407" ",
2408" "
63f06c22
VS
2409};
2410
13b22a67 2411/* Copyright (c) Julian Smart */
2b5f62a0 2412static const char *warning_xpm[] = {
63f06c22 2413/* columns rows colors chars-per-pixel */
13b22a67
JS
2414"48 48 9 1",
2415"@ c Black",
2416"o c #A6A800",
2417"+ c #8A8C00",
2418"$ c #B8BA00",
2419" c None",
2420"O c #6E7000",
2421"X c #DCDF00",
2422". c #C00000",
2423"# c #373800",
63f06c22 2424/* pixels */
13b22a67
JS
2425" ",
2426" ",
2427" ",
2428" ",
2429" ",
2430" ",
2431" ",
2432" . ",
2433" ... ",
2434" ... ",
2435" ..... ",
2436" ...X.. ",
2437" ..XXX.. ",
2438" ...XXX... ",
2439" ..XXXXX.. ",
2440" ..XXXXXX... ",
2441" ...XXoO+XX.. ",
2442" ..XXXO@#XXX.. ",
2443" ..XXXXO@#XXX... ",
2444" ...XXXXO@#XXXX.. ",
2445" ..XXXXXO@#XXXX... ",
2446" ...XXXXXo@OXXXXX.. ",
2447" ...XXXXXXo@OXXXXXX.. ",
2448" ..XXXXXXX$@OXXXXXX... ",
2449" ...XXXXXXXX@XXXXXXXX.. ",
2450" ...XXXXXXXXXXXXXXXXXX... ",
2451" ..XXXXXXXXXXOXXXXXXXXX.. ",
2452" ...XXXXXXXXXO@#XXXXXXXXX.. ",
2453" ..XXXXXXXXXXX#XXXXXXXXXX... ",
2454" ...XXXXXXXXXXXXXXXXXXXXXXX.. ",
2455" ...XXXXXXXXXXXXXXXXXXXXXXXX... ",
2456" .............................. ",
2457" .............................. ",
2458" ",
2459" ",
2460" ",
2461" ",
2462" ",
2463" ",
2464" ",
2465" ",
2466" ",
2467" ",
2468" ",
2469" ",
2470" ",
2471" ",
2472" "
63f06c22
VS
2473};
2474
13b22a67 2475/* Copyright (c) Julian Smart */
2b5f62a0 2476static const char *question_xpm[] = {
63f06c22 2477/* columns rows colors chars-per-pixel */
13b22a67
JS
2478"48 48 21 1",
2479". c Black",
2480"> c #696969",
2481"O c #1F1F00",
2482"+ c #181818",
2483"o c #F6F900",
2484"; c #3F3F00",
2485"$ c #111111",
2486" c None",
2487"& c #202020",
2488"X c #AAAA00",
2489"@ c #949400",
2490": c #303030",
2491"1 c #383838",
2492"% c #2A2A00",
2493", c #404040",
2494"= c #B4B400",
2495"- c #484848",
2496"# c #151500",
2497"< c #9F9F00",
2498"2 c #6A6A00",
2499"* c #353500",
63f06c22 2500/* pixels */
13b22a67
JS
2501" ",
2502" ",
2503" ",
2504" ",
2505" ......... ",
2506" ...XXXXXXX.. ",
2507" ..XXXXoooooXXXO+ ",
2508" ..XXooooooooooooX@.. ",
2509" ..XoooooooooooooooXX#. ",
2510" $%XoooooooooooooooooXX#. ",
2511" &.XoooooooXXXXXXooooooXX.. ",
2512" .XooooooXX.$...$XXoooooX*. ",
2513" $.XoooooX%.$ .*oooooo=.. ",
2514" .XooooooX.. -.XoooooX.. ",
2515" .XoooooX..+ .XoooooX;. ",
2516" ...XXXX..: .XoooooX;. ",
2517" ........ >.XoooooX;. ",
2518" +.XoooooX.. ",
2519" ,.Xoooooo<.. ",
2520" 1#XooooooXO.. ",
2521" &#XooooooX2.. ",
2522" $%XooooooXX.. ",
2523" $%XooooooXX.. ",
2524" $%XooooooXX.. ",
2525" &.XooooooXX.. ",
2526" .XooooooXX.. ",
2527" &.XoooooXX.. ",
2528" ..XooooXX.. ",
2529" ..XooooX... ",
2530" ..XXooXX..& ",
2531" ...XXXXX.. ",
2532" ........ ",
2533" ",
2534" ",
2535" ....... ",
2536" ..XXXXX.. ",
2537" ..XXoooXX.. ",
2538" ..XoooooX.. ",
2539" ..XoooooX.. ",
2540" ..XXoooXX.. ",
2541" ..XXXXX.. ",
2542" ....... ",
2543" ",
2544" ",
2545" ",
2546" ",
2547" ",
2548" "
63f06c22
VS
2549};
2550
536b70ac
VS
2551wxBitmap wxGTKArtProvider::CreateBitmap(const wxArtID& id,
2552 const wxArtClient& WXUNUSED(client),
2553 const wxSize& WXUNUSED(size))
63f06c22 2554{
536b70ac
VS
2555 if ( id == wxART_INFORMATION )
2556 return wxBitmap(info_xpm);
2557 if ( id == wxART_ERROR )
2558 return wxBitmap(error_xpm);
2559 if ( id == wxART_WARNING )
2560 return wxBitmap(warning_xpm);
2561 if ( id == wxART_QUESTION )
2562 return wxBitmap(question_xpm);
2563 return wxNullBitmap;
63f06c22
VS
2564}
2565
24a23c35 2566
1e6feb95
VZ
2567// ============================================================================
2568// wxInputHandler
2569// ============================================================================
2570
2571// ----------------------------------------------------------------------------
2572// wxGTKInputHandler
2573// ----------------------------------------------------------------------------
2574
61fef19b
VZ
2575bool wxGTKInputHandler::HandleKey(wxInputConsumer * WXUNUSED(control),
2576 const wxKeyEvent& WXUNUSED(event),
2577 bool WXUNUSED(pressed))
1e6feb95 2578{
a290fa5a 2579 return false;
1e6feb95
VZ
2580}
2581
67e49a98 2582bool wxGTKInputHandler::HandleMouse(wxInputConsumer *control,
1e6feb95
VZ
2583 const wxMouseEvent& event)
2584{
2585 // clicking on the control gives it focus
67e49a98 2586 if ( event.ButtonDown() && wxWindow::FindFocus() != control->GetInputWindow() )
1e6feb95 2587 {
67e49a98 2588 control->GetInputWindow()->SetFocus();
1e6feb95 2589
a290fa5a 2590 return true;
1e6feb95
VZ
2591 }
2592
a290fa5a 2593 return false;
1e6feb95
VZ
2594}
2595
67e49a98 2596bool wxGTKInputHandler::HandleMouseMove(wxInputConsumer *control,
1e6feb95
VZ
2597 const wxMouseEvent& event)
2598{
2599 if ( event.Entering() )
2600 {
a290fa5a 2601 control->GetInputWindow()->SetCurrent(true);
1e6feb95
VZ
2602 }
2603 else if ( event.Leaving() )
2604 {
a290fa5a 2605 control->GetInputWindow()->SetCurrent(false);
1e6feb95
VZ
2606 }
2607 else
2608 {
a290fa5a 2609 return false;
1e6feb95
VZ
2610 }
2611
a290fa5a 2612 return true;
1e6feb95
VZ
2613}
2614
9a6384ca
WS
2615#if wxUSE_CHECKBOX
2616
1e6feb95
VZ
2617// ----------------------------------------------------------------------------
2618// wxGTKCheckboxInputHandler
2619// ----------------------------------------------------------------------------
2620
67e49a98 2621bool wxGTKCheckboxInputHandler::HandleKey(wxInputConsumer *control,
1e6feb95
VZ
2622 const wxKeyEvent& event,
2623 bool pressed)
2624{
2625 if ( pressed )
2626 {
2627 int keycode = event.GetKeyCode();
2628 if ( keycode == WXK_SPACE || keycode == WXK_RETURN )
2629 {
2630 control->PerformAction(wxACTION_CHECKBOX_TOGGLE);
2631
a290fa5a 2632 return true;
1e6feb95
VZ
2633 }
2634 }
2635
a290fa5a 2636 return false;
1e6feb95
VZ
2637}
2638
9a6384ca
WS
2639#endif // wxUSE_CHECKBOX
2640
2641#if wxUSE_TEXTCTRL
2642
1e6feb95
VZ
2643// ----------------------------------------------------------------------------
2644// wxGTKTextCtrlInputHandler
2645// ----------------------------------------------------------------------------
2646
67e49a98 2647bool wxGTKTextCtrlInputHandler::HandleKey(wxInputConsumer *control,
1e6feb95
VZ
2648 const wxKeyEvent& event,
2649 bool pressed)
2650{
2651 // handle only GTK-specific text bindings here, the others are handled in
2652 // the base class
2653 if ( pressed )
2654 {
2655 wxControlAction action;
2656 int keycode = event.GetKeyCode();
2657 if ( event.ControlDown() )
2658 {
2659 switch ( keycode )
2660 {
2661 case 'A':
2662 action = wxACTION_TEXT_HOME;
2663 break;
2664
2665 case 'B':
2666 action = wxACTION_TEXT_LEFT;
2667 break;
2668
2669 case 'D':
2670 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_RIGHT;
2671 break;
2672
2673 case 'E':
2674 action = wxACTION_TEXT_END;
2675 break;
2676
2677 case 'F':
2678 action = wxACTION_TEXT_RIGHT;
2679 break;
2680
2681 case 'H':
2682 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_LEFT;
2683 break;
2684
2685 case 'K':
2686 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_END;
2687 break;
2688
2689 case 'N':
2690 action = wxACTION_TEXT_DOWN;
2691 break;
2692
2693 case 'P':
2694 action = wxACTION_TEXT_UP;
2695 break;
2696
2697 case 'U':
2698 //delete the entire line
2699 control->PerformAction(wxACTION_TEXT_HOME);
2700 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_END;
2701 break;
2702
2703 case 'W':
2704 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_WORD_LEFT;
2705 break;
2706 }
2707 }
2708 else if ( event.AltDown() )
2709 {
2710 switch ( keycode )
2711 {
2712 case 'B':
2713 action = wxACTION_TEXT_WORD_LEFT;
2714 break;
2715
2716 case 'D':
2717 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_WORD_RIGHT;
2718 break;
2719
2720 case 'F':
2721 action = wxACTION_TEXT_WORD_RIGHT;
2722 break;
2723 }
2724 }
2725
2726 if ( action != wxACTION_NONE )
2727 {
2728 control->PerformAction(action);
2729
a290fa5a 2730 return true;
1e6feb95
VZ
2731 }
2732 }
2733
9467bdb7 2734 return wxStdInputHandler::HandleKey(control, event, pressed);
1e6feb95 2735}
9a6384ca
WS
2736
2737#endif // wxUSE_TEXTCTRL
4353a8df 2738
e7637222 2739#endif // wxUSE_THEME_GTK