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