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