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