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