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