]> git.saurik.com Git - wxWidgets.git/blob - src/univ/themes/gtk.cpp
Add support for generating classes for menus
[wxWidgets.git] / src / univ / themes / gtk.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/univ/themes/gtk.cpp
3 // Purpose: wxUniversal theme implementing GTK-like LNF
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 06.08.00
7 // RCS-ID: $Id$
8 // Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
9 // Licence: wxWindows licence
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
33 #include "wx/menu.h"
34
35 #include "wx/bmpbuttn.h"
36 #include "wx/button.h"
37 #include "wx/checkbox.h"
38 #include "wx/listbox.h"
39 #include "wx/checklst.h"
40 #include "wx/combobox.h"
41 #include "wx/scrolbar.h"
42 #include "wx/slider.h"
43 #include "wx/textctrl.h"
44 #include "wx/toolbar.h"
45 #include "wx/statusbr.h"
46
47 #include "wx/settings.h"
48 #endif // WX_PRECOMP
49
50 #include "wx/notebook.h"
51 #include "wx/spinbutt.h"
52 #include "wx/toplevel.h"
53 #include "wx/artprov.h"
54 #include "wx/image.h"
55 #ifdef wxUSE_TOGGLEBTN
56 #include "wx/tglbtn.h"
57 #endif // wxUSE_TOGGLEBTN
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
64 class WXDLLEXPORT wxGTKMenuGeometryInfo;
65
66 // ----------------------------------------------------------------------------
67 // constants (to be removed, for testing only)
68 // ----------------------------------------------------------------------------
69
70 static const size_t BORDER_THICKNESS = 1;
71
72 // ----------------------------------------------------------------------------
73 // wxGTKRenderer: draw the GUI elements in GTK style
74 // ----------------------------------------------------------------------------
75
76 class wxGTKRenderer : public wxRenderer
77 {
78 public:
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,
85 int flags = 0,
86 wxWindow *window = NULL );
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
169 #if wxUSE_TOOLBAR
170 virtual void DrawToolBarButton(wxDC& dc,
171 const wxString& label,
172 const wxBitmap& bitmap,
173 const wxRect& rect,
174 int flags = 0,
175 long style = 0,
176 int tbarStyle = 0);
177 #endif // wxUSE_TOOLBAR
178
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
194 #if wxUSE_SLIDER
195 virtual void DrawSliderShaft(wxDC& dc,
196 const wxRect& rect,
197 int lenThumb,
198 wxOrientation orient,
199 int flags = 0,
200 long style = 0,
201 wxRect *rectShaft = NULL);
202 virtual void DrawSliderThumb(wxDC& dc,
203 const wxRect& rect,
204 wxOrientation orient,
205 int flags = 0,
206 long style = 0);
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)
216 {
217 // we don't have the ticks in GTK version
218 }
219 #endif // wxUSE_SLIDER
220
221 #if wxUSE_MENUS
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);
238 #endif // wxUSE_MENUS
239
240 #if wxUSE_STATUSBAR
241 virtual void DrawStatusField(wxDC& dc,
242 const wxRect& rect,
243 const wxString& label,
244 int flags = 0, int style = 0);
245 #endif // wxUSE_STATUSBAR
246
247 virtual void DrawFrameTitleBar(wxDC& dc,
248 const wxRect& rect,
249 const wxString& title,
250 const wxIcon& icon,
251 int flags,
252 int specialButton = 0,
253 int specialButtonFlag = 0);
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;
276 virtual wxSize GetFrameMinSize(int flags) const;
277 virtual wxSize GetFrameIconSize() const;
278 virtual int HitTestFrame(const wxRect& rect, const wxPoint& pt, int flags) const;
279
280 virtual void GetComboBitmaps(wxBitmap *bmpNormal,
281 wxBitmap *bmpFocus,
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; }
292 #if wxUSE_SCROLLBAR
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);
302 #endif // wxUSE_SCROLLBAR
303
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
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
318 #if wxUSE_TEXTCTRL
319 virtual wxRect GetTextTotalArea(const wxTextCtrl *text,
320 const wxRect& rect) const;
321 virtual wxRect GetTextClientArea(const wxTextCtrl *text,
322 const wxRect& rect,
323 wxCoord *extraSpaceBeyond) const;
324 #endif // wxUSE_TEXTCTRL
325
326 virtual wxSize GetTabIndent() const { return wxSize(2, 2); }
327 virtual wxSize GetTabPadding() const { return wxSize(6, 6); }
328
329 #if wxUSE_SLIDER
330 virtual wxCoord GetSliderDim() const { return 15; }
331 virtual wxCoord GetSliderTickLen() const { return 0; }
332 virtual wxRect GetSliderShaftRect(const wxRect& rect,
333 int lenThumb,
334 wxOrientation orient,
335 long style = 0) const;
336 virtual wxSize GetSliderThumbSize(const wxRect& rect,
337 int lenThumb,
338 wxOrientation orient) const;
339 #endif // wxUSE_SLIDER
340
341 virtual wxSize GetProgressBarStep() const { return wxSize(16, 32); }
342
343 #if wxUSE_MENUS
344 virtual wxSize GetMenuBarItemSize(const wxSize& sizeText) const;
345 virtual wxMenuGeometryInfo *GetMenuGeometry(wxWindow *win,
346 const wxMenu& menu) const;
347 #endif // wxUSE_MENUS
348
349 #if wxUSE_STATUSBAR
350 virtual wxSize GetStatusBarBorders(wxCoord *borderBetweenFields) const;
351 #endif // wxUSE_STATUSBAR
352
353 // helpers for "wxBitmap wxColourScheme::Get()"
354 void DrawCheckBitmap(wxDC& dc, const wxRect& rect);
355 void DrawUncheckBitmap(wxDC& dc, const wxRect& rect, bool isPressed);
356 void DrawUndeterminedBitmap(wxDC& dc, const wxRect& rect, bool isPressed);
357
358 protected:
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,
375 const wxRect& rect,
376 wxWindow *window = NULL);
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
423 #if wxUSE_SCROLLBAR
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 }
441 #endif // wxUSE_SCROLLBAR
442
443 // get the line wrap indicator bitmap
444 wxBitmap GetLineWrapBitmap() const;
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
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,
478 const wxString& accel = wxEmptyString,
479 const wxBitmap& bitmap = wxNullBitmap,
480 const wxGTKMenuGeometryInfo *geometryInfo = NULL);
481
482 // initialize the combo bitmaps
483 void InitComboBitmaps();
484
485 private:
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
499 // pressed state and the columns are for checked, unchecked and
500 // undeterminated respectively
501 wxBitmap m_bitmapsCheckbox[2][3];
502
503 // the line wrap bitmap (drawn at the end of wrapped lines)
504 wxBitmap m_bmpLineWrap;
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];
517 };
518
519 // ----------------------------------------------------------------------------
520 // wxGTKInputHandler and derived classes: process the keyboard and mouse
521 // messages according to GTK standards
522 // ----------------------------------------------------------------------------
523
524 class wxGTKInputHandler : public wxInputHandler
525 {
526 public:
527 wxGTKInputHandler(wxGTKRenderer *renderer);
528
529 virtual bool HandleKey(wxInputConsumer *control,
530 const wxKeyEvent& event,
531 bool pressed);
532 virtual bool HandleMouse(wxInputConsumer *control,
533 const wxMouseEvent& event);
534 virtual bool HandleMouseMove(wxInputConsumer *control, const wxMouseEvent& event);
535
536 protected:
537 wxGTKRenderer *m_renderer;
538 };
539
540 #if wxUSE_SCROLLBAR
541
542 class wxGTKScrollBarInputHandler : public wxStdScrollBarInputHandler
543 {
544 public:
545 wxGTKScrollBarInputHandler(wxRenderer *renderer, wxInputHandler *handler)
546 : wxStdScrollBarInputHandler(renderer, handler) { }
547
548 protected:
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
567 virtual bool IsAllowedButton(int WXUNUSED(button)) { return true; }
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
576 #endif // wxUSE_SCROLLBAR
577
578 #if wxUSE_CHECKBOX
579
580 class wxGTKCheckboxInputHandler : public wxStdCheckboxInputHandler
581 {
582 public:
583 wxGTKCheckboxInputHandler(wxInputHandler *handler)
584 : wxStdCheckboxInputHandler(handler) { }
585
586 virtual bool HandleKey(wxInputConsumer *control,
587 const wxKeyEvent& event,
588 bool pressed);
589 };
590
591 #endif // wxUSE_CHECKBOX
592
593 #if wxUSE_TEXTCTRL
594
595 class wxGTKTextCtrlInputHandler : public wxStdTextCtrlInputHandler
596 {
597 public:
598 wxGTKTextCtrlInputHandler(wxInputHandler *handler)
599 : wxStdTextCtrlInputHandler(handler) { }
600
601 virtual bool HandleKey(wxInputConsumer *control,
602 const wxKeyEvent& event,
603 bool pressed);
604 };
605
606 #endif // wxUSE_TEXTCTRL
607
608 // ----------------------------------------------------------------------------
609 // wxGTKColourScheme: uses the standard GTK colours
610 // ----------------------------------------------------------------------------
611
612 class wxGTKColourScheme : public wxColourScheme
613 {
614 public:
615 virtual wxColour Get(StdColour col) const;
616 virtual wxColour GetBackground(wxWindow *win) const;
617 };
618
619 // ----------------------------------------------------------------------------
620 // wxGTKArtProvider
621 // ----------------------------------------------------------------------------
622
623 class wxGTKArtProvider : public wxArtProvider
624 {
625 protected:
626 virtual wxBitmap CreateBitmap(const wxArtID& id,
627 const wxArtClient& client,
628 const wxSize& size);
629 };
630
631 // ----------------------------------------------------------------------------
632 // wxGTKTheme
633 // ----------------------------------------------------------------------------
634
635 WX_DEFINE_ARRAY_PTR(wxInputHandler *, wxArrayHandlers);
636
637 class wxGTKTheme : public wxTheme
638 {
639 public:
640 wxGTKTheme();
641 virtual ~wxGTKTheme();
642
643 virtual wxRenderer *GetRenderer();
644 virtual wxArtProvider *GetArtProvider();
645 virtual wxInputHandler *GetInputHandler(const wxString& control);
646 virtual wxColourScheme *GetColourScheme();
647
648 private:
649 // get the default input handler
650 wxInputHandler *GetDefaultInputHandler();
651
652 wxGTKRenderer *m_renderer;
653
654 wxGTKArtProvider *m_artProvider;
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
672 WX_IMPLEMENT_THEME(wxGTKTheme, gtk, wxTRANSLATE("GTK+ theme"));
673
674 // ----------------------------------------------------------------------------
675 // wxGTKTheme
676 // ----------------------------------------------------------------------------
677
678 wxGTKTheme::wxGTKTheme()
679 {
680 m_scheme = NULL;
681 m_renderer = NULL;
682 m_handlerDefault = NULL;
683 m_artProvider = NULL;
684 }
685
686 wxGTKTheme::~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;
698 wxArtProvider::RemoveProvider(m_artProvider);
699 }
700
701 wxRenderer *wxGTKTheme::GetRenderer()
702 {
703 if ( !m_renderer )
704 {
705 m_renderer = new wxGTKRenderer(GetColourScheme());
706 }
707
708 return m_renderer;
709 }
710
711 wxArtProvider *wxGTKTheme::GetArtProvider()
712 {
713 if ( !m_artProvider )
714 {
715 m_artProvider = new wxGTKArtProvider;
716 }
717
718 return m_artProvider;
719 }
720
721 wxColourScheme *wxGTKTheme::GetColourScheme()
722 {
723 if ( !m_scheme )
724 {
725 m_scheme = new wxGTKColourScheme;
726 }
727 return m_scheme;
728 }
729
730 wxInputHandler *wxGTKTheme::GetDefaultInputHandler()
731 {
732 if ( !m_handlerDefault )
733 {
734 m_handlerDefault = new wxGTKInputHandler(m_renderer);
735 }
736
737 return m_handlerDefault;
738 }
739
740 wxInputHandler *wxGTKTheme::GetInputHandler(const wxString& control)
741 {
742 wxInputHandler *handler = NULL;
743 int n = m_handlerNames.Index(control);
744 if ( n == wxNOT_FOUND )
745 {
746 // create a new handler
747 if ( control == wxINP_HANDLER_SCROLLBAR )
748 {
749 #if wxUSE_SCROLLBAR
750 handler = new wxGTKScrollBarInputHandler(m_renderer,
751 GetDefaultInputHandler());
752 #endif // wxUSE_SCROLLBAR
753 }
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
790 #if wxUSE_TOOLBAR
791 else if ( control == wxINP_HANDLER_TOOLBAR )
792 handler = new wxStdToolbarInputHandler(GetDefaultInputHandler());
793 #endif // wxUSE_TOOLBAR
794 else if ( control == wxINP_HANDLER_TOPLEVEL )
795 handler = new wxStdFrameInputHandler(GetDefaultInputHandler());
796
797 if(!handler)
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
815 wxColour 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
824 if ( !win->ShouldInheritColours() )
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 {
840 #if wxUSE_SCROLLBAR
841 if ( wxDynamicCast(win, wxScrollBar) )
842 col = Get(SCROLLBAR);
843 else
844 #endif //wxUSE_SCROLLBAR
845 if ( (flags & wxCONTROL_CURRENT) && win->CanBeHighlighted() )
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
857 wxColour 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
884 case GAUGE: return Get(CONTROL_CURRENT);
885
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
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
909 wxGTKRenderer::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
927 void 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
938 void 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
952 void 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
971 void 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
1006 void 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
1025 void 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
1031 void 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
1037 void wxGTKRenderer::DrawBorder(wxDC& dc,
1038 wxBorder border,
1039 const wxRect& rectTotal,
1040 int WXUNUSED(flags),
1041 wxRect *rectIn)
1042 {
1043 size_t width;
1044
1045 wxRect rect = rectTotal;
1046
1047 switch ( border )
1048 {
1049 case wxBORDER_SUNKEN:
1050 for ( width = 0; width < BORDER_THICKNESS; width++ )
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:
1058 for ( width = 0; width < BORDER_THICKNESS; width++ )
1059 {
1060 DrawShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight);
1061 }
1062 break;
1063
1064 case wxBORDER_RAISED:
1065 for ( width = 0; width < BORDER_THICKNESS; width++ )
1066 {
1067 DrawRaisedBorder(dc, &rect);
1068 }
1069 break;
1070
1071 case wxBORDER_DOUBLE:
1072 for ( width = 0; width < BORDER_THICKNESS; width++ )
1073 {
1074 DrawShadedRect(dc, &rect, m_penLightGrey, m_penBlack);
1075 DrawShadedRect(dc, &rect, m_penHighlight, m_penDarkGrey);
1076 DrawRect(dc, &rect, m_penLightGrey);
1077 }
1078 break;
1079
1080 case wxBORDER_SIMPLE:
1081 for ( width = 0; width < BORDER_THICKNESS; width++ )
1082 {
1083 DrawRect(dc, &rect, m_penBlack);
1084 }
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
1100 wxRect 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:
1112 width = BORDER_THICKNESS;
1113 break;
1114
1115 case wxBORDER_DOUBLE:
1116 width = 3*BORDER_THICKNESS;
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
1138 bool wxGTKRenderer::AreScrollbarsInsideBorder() const
1139 {
1140 // no, the scrollbars are outside the border in GTK+
1141 return false;
1142 }
1143
1144 // ----------------------------------------------------------------------------
1145 // special borders
1146 // ----------------------------------------------------------------------------
1147
1148 void wxGTKRenderer::DrawTextBorder(wxDC& dc,
1149 wxBorder border,
1150 const wxRect& rectOrig,
1151 int flags,
1152 wxRect *rectIn)
1153 {
1154 wxRect rect = rectOrig;
1155
1156 if ( border != wxBORDER_NONE )
1157 {
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 }
1168 }
1169
1170 if ( rectIn )
1171 *rectIn = rect;
1172 }
1173
1174 void 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);
1185
1186 for ( size_t width = 0; width < BORDER_THICKNESS; width++ )
1187 {
1188 DrawAntiShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight);
1189 DrawAntiShadedRect(dc, &rect, m_penBlack, m_penDarkGrey);
1190 }
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
1208 for ( size_t width = 0; width < BORDER_THICKNESS; width++ )
1209 {
1210 DrawShadedRect(dc, &rect, m_penHighlight, m_penBlack);
1211 DrawAntiShadedRect(dc, &rect,
1212 wxPen(GetBackgroundColour(flags), 0, wxSOLID),
1213 m_penDarkGrey);
1214 }
1215 }
1216
1217 if ( rectIn )
1218 {
1219 *rectIn = rect;
1220 }
1221 }
1222
1223 // ----------------------------------------------------------------------------
1224 // lines and frames
1225 // ----------------------------------------------------------------------------
1226
1227 void 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
1237 void 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
1247 void 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
1296 void 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
1308 void 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 }
1327 else
1328 {
1329 dc.SetTextForeground(wxSCHEME_COLOUR(m_scheme, CONTROL_TEXT));
1330 }
1331
1332 dc.DrawLabel(label, image, rect, alignment, indexAccel, rectBounds);
1333 }
1334
1335 void 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
1380 void 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;
1389
1390 // never draw the focus rect around the check indicators here
1391 DrawCheckButton(dc, wxEmptyString, bitmap, rectBitmap, flags & ~wxCONTROL_FOCUSED);
1392
1393 wxRect rectLabel = rect;
1394 wxCoord shift = rectBitmap.width + 2*GetCheckItemMargin();
1395 rectLabel.x += shift;
1396 rectLabel.width -= shift;
1397 DrawItem(dc, label, rectLabel, flags);
1398 }
1399
1400 // ----------------------------------------------------------------------------
1401 // check/radion buttons
1402 // ----------------------------------------------------------------------------
1403
1404 void 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
1433 void 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
1453 void 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
1464 void 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
1493 bool drawIt = true;
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
1499 drawIt = false;
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) )
1512 drawIt = true; // with the same pen
1513 else if ( flags & wxCONTROL_PRESSED )
1514 {
1515 dc.SetPen(wxPen(wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED), 0, wxSOLID));
1516 drawIt = true;
1517 }
1518 else // checked and unpressed
1519 drawIt = false;
1520
1521 if ( drawIt )
1522 DrawDownZag(dc, x + 2, xRight - 2, yMid, yBottom - 2);
1523 }
1524
1525 void 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
1536 void 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
1547 wxBitmap 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 {
1558 for ( int j = 0; j < 3; j++ )
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]);
1570 DrawUncheckBitmap(dc, rect, false);
1571
1572 // normal undeterminated
1573 dc.SelectObject(m_bitmapsCheckbox[0][2]);
1574 DrawUndeterminedBitmap(dc, rect, false);
1575
1576 // pressed checked
1577 m_bitmapsCheckbox[1][0] = m_bitmapsCheckbox[0][0];
1578
1579 // pressed unchecked
1580 dc.SelectObject(m_bitmapsCheckbox[1][1]);
1581 DrawUncheckBitmap(dc, rect, true);
1582
1583 // pressed undeterminated
1584 dc.SelectObject(m_bitmapsCheckbox[1][2]);
1585 DrawUndeterminedBitmap(dc, rect, true);
1586 }
1587
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 );
1596
1597 return m_bitmapsCheckbox[row][col];
1598 }
1599
1600 wxBitmap wxGTKRenderer::GetLineWrapBitmap() const
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 {
1619 wxConstCast(this, wxGTKRenderer)->m_bmpLineWrap = bmpLineWrap;
1620 }
1621 }
1622
1623 return m_bmpLineWrap;
1624 }
1625
1626 void 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
1648 void 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
1690 dc.DrawBitmap(bitmap, xBmp, yBmp, true /* use mask */);
1691
1692 DrawLabel(dc, label, rectLabel, flags,
1693 wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL, indexAccel);
1694 }
1695
1696 void 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);
1721
1722 // must unselect the bitmap before setting a mask for it because of the
1723 // MSW limitations
1724 dc.SelectObject(wxNullBitmap);
1725 bitmap.SetMask(new wxMask(bitmap, *wxLIGHT_GREY));
1726 }
1727
1728 DoDrawCheckOrRadioBitmap(dc, label, bitmap, rectTotal,
1729 flags, align, indexAccel);
1730 }
1731
1732 #if wxUSE_TOOLBAR
1733 void wxGTKRenderer::DrawToolBarButton(wxDC& dc,
1734 const wxString& label,
1735 const wxBitmap& bitmap,
1736 const wxRect& rectOrig,
1737 int flags,
1738 long WXUNUSED(style),
1739 int tbarStyle)
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 {
1749 DrawBorder(dc, wxBORDER_SUNKEN, rect, flags, &rect);
1750
1751 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED), rect);
1752 }
1753 else if ( flags & wxCONTROL_CURRENT )
1754 {
1755 DrawBorder(dc, wxBORDER_RAISED, rect, flags, &rect);
1756
1757 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL_CURRENT), rect);
1758 }
1759
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 }
1777 }
1778 }
1779 #endif // wxUSE_TOOLBAR
1780
1781 // ----------------------------------------------------------------------------
1782 // text control
1783 // ----------------------------------------------------------------------------
1784
1785 #if wxUSE_TEXTCTRL
1786
1787 wxRect wxGTKRenderer::GetTextTotalArea(const wxTextCtrl * WXUNUSED(text),
1788 const wxRect& rect) const
1789 {
1790 wxRect rectTotal = rect;
1791 rectTotal.Inflate(2*BORDER_THICKNESS);
1792 return rectTotal;
1793 }
1794
1795 wxRect wxGTKRenderer::GetTextClientArea(const wxTextCtrl *text,
1796 const wxRect& rect,
1797 wxCoord *extraSpaceBeyond) const
1798 {
1799 wxRect rectText = rect;
1800 rectText.Deflate(2*BORDER_THICKNESS);
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
1816 #endif // wxUSE_TEXTCTRL
1817
1818 void 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
1830 void 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
1859 void 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 {
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
1873 wxRect rect = rectOrig;
1874
1875 bool isVertical = ( dir == wxLEFT ) || ( dir == wxRIGHT );
1876
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 {
1882 rect.Inflate( SELECT_FOR_VERTICAL( indent.x , 0),
1883 SELECT_FOR_VERTICAL( 0, indent.y ));
1884 switch ( dir )
1885 {
1886 default:
1887 wxFAIL_MSG(_T("invaild notebook tab orientation"));
1888 // fall through
1889
1890 case wxTOP:
1891 rect.y -= indent.y;
1892 // fall through
1893 case wxBOTTOM:
1894 rect.height += indent.y;
1895 break;
1896
1897 case wxLEFT:
1898 rect.x -= indent.x;
1899 // fall through
1900 case wxRIGHT:
1901 rect.width += indent.x;
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);
1919 if ( dir == wxRIGHT )
1920 rectBorder.Offset(-1, 0);
1921
1922 DrawRect(dc, &rectBorder, m_penBlack);
1923 }
1924
1925 // draw the text, image and the focus around them (if necessary)
1926 wxRect rectLabel( REVERSE_FOR_VERTICAL(rect.x,rect.y),
1927 REVERSE_FOR_VERTICAL(rect.width,rect.height)
1928 );
1929 rectLabel.Deflate(1, 1);
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();
1942 bitmapRotated =
1943 #if wxUSE_IMAGE
1944 wxBitmap( wxImage( bitmap.ConvertToImage() ).Rotate90(dir==wxLEFT) )
1945 #else
1946 bitmap
1947 #endif // wxUSE_IMAGE
1948 ;
1949 dcMem.DrawLabel(label, bitmapRotated, rectLabel, wxALIGN_CENTRE, indexAccel);
1950 dcMem.SelectObject(wxNullBitmap);
1951 bitmapMem = bitmapMem.GetSubBitmap(rectLabel);
1952 #if wxUSE_IMAGE
1953 bitmapMem = wxBitmap(wxImage(bitmapMem.ConvertToImage()).Rotate90(dir==wxRIGHT))
1954 #endif
1955 ;
1956
1957 dc.DrawBitmap(bitmapMem, rectLabel.y, rectLabel.x, false);
1958 }
1959 else
1960 {
1961 dc.DrawLabel(label, bitmap, rectLabel, wxALIGN_CENTRE, indexAccel);
1962 }
1963
1964 // now draw the tab itself
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());
1969 switch ( dir )
1970 {
1971 default:
1972 // default is top
1973 case wxLEFT:
1974 // left orientation looks like top but IsVertical makes x and y reversed
1975 case wxTOP:
1976 // top is not vertical so use coordinates in written order
1977 dc.SetPen(m_penHighlight);
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));
1982
1983 dc.SetPen(m_penBlack);
1984 dc.DrawLine(REVERSE_FOR_VERTICAL(x2, y2),
1985 REVERSE_FOR_VERTICAL(x2, y));
1986
1987 dc.SetPen(m_penDarkGrey);
1988 dc.DrawLine(REVERSE_FOR_VERTICAL(x2 - 1, y2),
1989 REVERSE_FOR_VERTICAL(x2 - 1, y + 1));
1990
1991 if ( flags & wxCONTROL_SELECTED )
1992 {
1993 dc.SetPen(m_penLightGrey);
1994
1995 // overwrite the part of the border below this tab
1996 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y2 + 1),
1997 REVERSE_FOR_VERTICAL(x2 - 1, y2 + 1));
1998
1999 // and the shadow of the tab to the left of us
2000 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y + 2),
2001 REVERSE_FOR_VERTICAL(x + 1, y2 + 1));
2002 }
2003 break;
2004
2005 case wxRIGHT:
2006 // right orientation looks like bottom but IsVertical makes x and y reversed
2007 case wxBOTTOM:
2008 // bottom is not vertical so use coordinates in written order
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
2013 dc.DrawLine(REVERSE_FOR_VERTICAL(x, y - (flags & wxCONTROL_SELECTED ? 1 : 0)),
2014 REVERSE_FOR_VERTICAL(x, y2));
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);
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));
2023 #endif // 0
2024
2025 dc.SetPen(m_penBlack);
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));
2030
2031 dc.SetPen(m_penDarkGrey);
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));
2036
2037 if ( flags & wxCONTROL_SELECTED )
2038 {
2039 dc.SetPen(m_penLightGrey);
2040
2041 // overwrite the part of the (double!) border above this tab
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));
2046
2047 // and the shadow of the tab to the left of us
2048 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y2 - 1),
2049 REVERSE_FOR_VERTICAL(x + 1, y - 1));
2050 }
2051 break;
2052 }
2053 }
2054
2055 #if wxUSE_SLIDER
2056
2057 // ----------------------------------------------------------------------------
2058 // slider
2059 // ----------------------------------------------------------------------------
2060
2061 wxSize wxGTKRenderer::GetSliderThumbSize(const wxRect& rect,
2062 int lenThumb,
2063 wxOrientation orient) const
2064 {
2065 static const wxCoord SLIDER_THUMB_LENGTH = 30;
2066
2067 wxSize size;
2068
2069 wxRect rectShaft = GetSliderShaftRect(rect, lenThumb, orient);
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
2084 wxRect wxGTKRenderer::GetSliderShaftRect(const wxRect& rect,
2085 int WXUNUSED(lenThumb),
2086 wxOrientation WXUNUSED(orient),
2087 long WXUNUSED(style)) const
2088 {
2089 return rect.Deflate(2*BORDER_THICKNESS, 2*BORDER_THICKNESS);
2090 }
2091
2092 void wxGTKRenderer::DrawSliderShaft(wxDC& dc,
2093 const wxRect& rectOrig,
2094 int WXUNUSED(lenThumb),
2095 wxOrientation WXUNUSED(orient),
2096 int flags,
2097 long WXUNUSED(style),
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
2121 void wxGTKRenderer::DrawSliderThumb(wxDC& dc,
2122 const wxRect& rectOrig,
2123 wxOrientation orient,
2124 int WXUNUSED(flags),
2125 long WXUNUSED(style))
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
2146 #endif // wxUSE_SLIDER
2147
2148 #if wxUSE_MENUS
2149
2150 // ----------------------------------------------------------------------------
2151 // menu and menubar
2152 // ----------------------------------------------------------------------------
2153
2154 // wxGTKMenuGeometryInfo: the wxMenuGeometryInfo used by wxGTKRenderer
2155 class WXDLLEXPORT wxGTKMenuGeometryInfo : public wxMenuGeometryInfo
2156 {
2157 public:
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
2165 private:
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
2183 static const wxCoord MENU_LEFT_MARGIN = 9;
2184 static const wxCoord MENU_RIGHT_MARGIN = 6;
2185
2186 static const wxCoord MENU_HORZ_MARGIN = 6;
2187 static const wxCoord MENU_VERT_MARGIN = 3;
2188
2189 // the margin around bitmap/check marks (on each side)
2190 static const wxCoord MENU_BMP_MARGIN = 2;
2191
2192 // the margin between the labels and accel strings
2193 static 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
2198 static const wxCoord MENU_SEPARATOR_HEIGHT = 3;
2199
2200 // the size of the standard checkmark bitmap
2201 static const wxCoord MENU_CHECK_SIZE = 9;
2202
2203 void wxGTKRenderer::DrawMenuBarItem(wxDC& dc,
2204 const wxRect& rect,
2205 const wxString& label,
2206 int flags,
2207 int indexAccel)
2208 {
2209 DoDrawMenuItem(dc, rect, label, flags, indexAccel);
2210 }
2211
2212 void wxGTKRenderer::DrawMenuItem(wxDC& dc,
2213 wxCoord y,
2214 const wxMenuGeometryInfo& gi,
2215 const wxString& label,
2216 const wxString& accel,
2217 const wxBitmap& bitmap,
2218 int flags,
2219 int indexAccel)
2220 {
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
2232 void 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 }
2304 }
2305
2306 void wxGTKRenderer::DrawMenuSeparator(wxDC& dc,
2307 wxCoord y,
2308 const wxMenuGeometryInfo& geomInfo)
2309 {
2310 DrawHorizontalLine(dc, y + MENU_VERT_MARGIN, 0, geomInfo.GetSize().x);
2311 }
2312
2313 wxSize wxGTKRenderer::GetMenuBarItemSize(const wxSize& sizeText) const
2314 {
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;
2322 }
2323
2324 wxMenuGeometryInfo *wxGTKRenderer::GetMenuGeometry(wxWindow *win,
2325 const wxMenu& menu) const
2326 {
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
2347 for ( wxMenuItemList::compatibility_iterator node = menu.GetMenuItems().GetFirst();
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;
2411
2412 return gi;
2413 }
2414
2415 #endif // wxUSE_MENUS
2416
2417 #if wxUSE_STATUSBAR
2418
2419 // ----------------------------------------------------------------------------
2420 // status bar
2421 // ----------------------------------------------------------------------------
2422
2423 wxSize
2424 wxGTKRenderer::GetStatusBarBorders(wxCoord * WXUNUSED(borderBetweenFields)) const
2425 {
2426 return wxSize(0,0);
2427 }
2428
2429 void wxGTKRenderer::DrawStatusField(wxDC& WXUNUSED(dc),
2430 const wxRect& WXUNUSED(rect),
2431 const wxString& WXUNUSED(label),
2432 int WXUNUSED(flags), int WXUNUSED(style))
2433 {
2434 }
2435
2436 #endif // wxUSE_STATUSBAR
2437
2438 // ----------------------------------------------------------------------------
2439 // combobox
2440 // ----------------------------------------------------------------------------
2441
2442 void 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
2463 wxRect rect(sizeArrow);
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
2476 void wxGTKRenderer::GetComboBitmaps(wxBitmap *bmpNormal,
2477 wxBitmap *bmpFocus,
2478 wxBitmap *bmpPressed,
2479 wxBitmap *bmpDisabled)
2480 {
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];
2494 }
2495
2496 // ----------------------------------------------------------------------------
2497 // background
2498 // ----------------------------------------------------------------------------
2499
2500 void wxGTKRenderer::DoDrawBackground(wxDC& dc,
2501 const wxColour& col,
2502 const wxRect& rect,
2503 wxWindow * WXUNUSED(window))
2504 {
2505 wxBrush brush(col, wxSOLID);
2506 dc.SetBrush(brush);
2507 dc.SetPen(*wxTRANSPARENT_PEN);
2508 dc.DrawRectangle(rect);
2509 }
2510
2511 void wxGTKRenderer::DrawBackground(wxDC& dc,
2512 const wxColour& col,
2513 const wxRect& rect,
2514 int flags,
2515 wxWindow *window )
2516 {
2517 wxColour colBg = col.Ok() ? col : GetBackgroundColour(flags);
2518 DoDrawBackground(dc, colBg, rect, window );
2519 }
2520
2521 // ----------------------------------------------------------------------------
2522 // scrollbar
2523 // ----------------------------------------------------------------------------
2524
2525 void 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
2606 void 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 :-(
2622 void 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
2795 void 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
2829 void 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
2846 void wxGTKRenderer::DrawScrollbarShaft(wxDC& dc,
2847 wxOrientation orient,
2848 const wxRect& rect,
2849 int WXUNUSED(flags))
2850 {
2851 wxRect rectBar = rect;
2852 DrawThumbBorder(dc, &rectBar, orient);
2853 DoDrawBackground(dc, wxSCHEME_COLOUR(m_scheme, SCROLLBAR), rectBar);
2854 }
2855
2856 void wxGTKRenderer::DrawScrollCorner(wxDC& dc, const wxRect& rect)
2857 {
2858 DoDrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rect);
2859 }
2860
2861 #if wxUSE_SCROLLBAR
2862 wxRect 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
2879 wxCoord wxGTKRenderer::GetScrollbarSize(const wxScrollBar *scrollbar)
2880 {
2881 return StandardScrollBarSize(scrollbar, GetScrollbarArrowSize(scrollbar));
2882 }
2883
2884 wxHitTest wxGTKRenderer::HitTestScrollbar(const wxScrollBar *scrollbar,
2885 const wxPoint& pt) const
2886 {
2887 return StandardHitTestScrollbar(scrollbar, pt,
2888 GetScrollbarArrowSize(scrollbar));
2889 }
2890
2891 wxCoord wxGTKRenderer::ScrollbarToPixel(const wxScrollBar *scrollbar,
2892 int thumbPos)
2893 {
2894 return StandardScrollbarToPixel(scrollbar, thumbPos,
2895 GetScrollbarArrowSize(scrollbar));
2896 }
2897
2898 int wxGTKRenderer::PixelToScrollbar(const wxScrollBar *scrollbar,
2899 wxCoord coord)
2900 {
2901 return StandardPixelToScrollbar(scrollbar, coord,
2902 GetScrollbarArrowSize(scrollbar));
2903 }
2904 #endif // wxUSE_SCROLLBAR
2905
2906 // ----------------------------------------------------------------------------
2907 // size adjustments
2908 // ----------------------------------------------------------------------------
2909
2910 void wxGTKRenderer::AdjustSize(wxSize *size, const wxWindow *window)
2911 {
2912 #if wxUSE_BMPBUTTON
2913 if ( wxDynamicCast(window, wxBitmapButton) )
2914 {
2915 size->x += 4;
2916 size->y += 4;
2917 } else
2918 #endif // wxUSE_BMPBUTTON
2919 #if wxUSE_BUTTON || wxUSE_TOGGLEBTN
2920 if ( 0
2921 # if wxUSE_BUTTON
2922 || wxDynamicCast(window, wxButton)
2923 # endif // wxUSE_BUTTON
2924 # if wxUSE_TOGGLEBTN
2925 || wxDynamicCast(window, wxToggleButton)
2926 # endif // wxUSE_TOGGLEBTN
2927 )
2928 {
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 }
2940 } else
2941 #endif // wxUSE_BUTTON || wxUSE_TOGGLEBTN
2942 #if wxUSE_SCROLLBAR
2943 if ( wxDynamicCast(window, wxScrollBar) )
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
2953 #endif // wxUSE_SCROLLBAR
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
2962 // ----------------------------------------------------------------------------
2963 // top level windows
2964 // ----------------------------------------------------------------------------
2965
2966 void 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))
2973 {
2974 }
2975
2976 void wxGTKRenderer::DrawFrameBorder(wxDC& WXUNUSED(dc),
2977 const wxRect& WXUNUSED(rect),
2978 int WXUNUSED(flags))
2979 {
2980 }
2981
2982 void wxGTKRenderer::DrawFrameBackground(wxDC& WXUNUSED(dc),
2983 const wxRect& WXUNUSED(rect),
2984 int WXUNUSED(flags))
2985 {
2986 }
2987
2988 void wxGTKRenderer::DrawFrameTitle(wxDC& WXUNUSED(dc),
2989 const wxRect& WXUNUSED(rect),
2990 const wxString& WXUNUSED(title),
2991 int WXUNUSED(flags))
2992 {
2993 }
2994
2995 void wxGTKRenderer::DrawFrameIcon(wxDC& WXUNUSED(dc),
2996 const wxRect& WXUNUSED(rect),
2997 const wxIcon& WXUNUSED(icon),
2998 int WXUNUSED(flags))
2999 {
3000 }
3001
3002 void wxGTKRenderer::DrawFrameButton(wxDC& WXUNUSED(dc),
3003 wxCoord WXUNUSED(x),
3004 wxCoord WXUNUSED(y),
3005 int WXUNUSED(button),
3006 int WXUNUSED(flags))
3007 {
3008 }
3009
3010 wxRect
3011 wxGTKRenderer::GetFrameClientArea(const wxRect& rect,
3012 int WXUNUSED(flags)) const
3013 {
3014 return rect;
3015 }
3016
3017 wxSize
3018 wxGTKRenderer::GetFrameTotalSize(const wxSize& clientSize,
3019 int WXUNUSED(flags)) const
3020 {
3021 return clientSize;
3022 }
3023
3024 wxSize wxGTKRenderer::GetFrameMinSize(int WXUNUSED(flags)) const
3025 {
3026 return wxSize(0,0);
3027 }
3028
3029 wxSize wxGTKRenderer::GetFrameIconSize() const
3030 {
3031 return wxSize(wxDefaultCoord, wxDefaultCoord);
3032 }
3033
3034 int
3035 wxGTKRenderer::HitTestFrame(const wxRect& WXUNUSED(rect),
3036 const wxPoint& WXUNUSED(pt),
3037 int WXUNUSED(flags)) const
3038 {
3039 return wxHT_TOPLEVEL_CLIENT_AREA;
3040 }
3041
3042
3043 // ----------------------------------------------------------------------------
3044 // standard icons
3045 // ----------------------------------------------------------------------------
3046
3047 /* Copyright (c) Julian Smart */
3048 static const char *error_xpm[] = {
3049 /* columns rows colors chars-per-pixel */
3050 "48 48 4 1",
3051 " c None",
3052 "X c #242424",
3053 "o c #DCDF00",
3054 ". c #C00000",
3055 /* pixels */
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 " "
3104 };
3105
3106 /* Copyright (c) Julian Smart */
3107 static const char *info_xpm[] = {
3108 /* columns rows colors chars-per-pixel */
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",
3119 /* pixels */
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 " "
3168 };
3169
3170 /* Copyright (c) Julian Smart */
3171 static const char *warning_xpm[] = {
3172 /* columns rows colors chars-per-pixel */
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",
3183 /* pixels */
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 " "
3232 };
3233
3234 /* Copyright (c) Julian Smart */
3235 static const char *question_xpm[] = {
3236 /* columns rows colors chars-per-pixel */
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",
3259 /* pixels */
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 " "
3308 };
3309
3310 wxBitmap wxGTKArtProvider::CreateBitmap(const wxArtID& id,
3311 const wxArtClient& WXUNUSED(client),
3312 const wxSize& WXUNUSED(size))
3313 {
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;
3323 }
3324
3325
3326 // ============================================================================
3327 // wxInputHandler
3328 // ============================================================================
3329
3330 // ----------------------------------------------------------------------------
3331 // wxGTKInputHandler
3332 // ----------------------------------------------------------------------------
3333
3334 wxGTKInputHandler::wxGTKInputHandler(wxGTKRenderer *renderer)
3335 {
3336 m_renderer = renderer;
3337 }
3338
3339 bool wxGTKInputHandler::HandleKey(wxInputConsumer * WXUNUSED(control),
3340 const wxKeyEvent& WXUNUSED(event),
3341 bool WXUNUSED(pressed))
3342 {
3343 return false;
3344 }
3345
3346 bool wxGTKInputHandler::HandleMouse(wxInputConsumer *control,
3347 const wxMouseEvent& event)
3348 {
3349 // clicking on the control gives it focus
3350 if ( event.ButtonDown() && wxWindow::FindFocus() != control->GetInputWindow() )
3351 {
3352 control->GetInputWindow()->SetFocus();
3353
3354 return true;
3355 }
3356
3357 return false;
3358 }
3359
3360 bool wxGTKInputHandler::HandleMouseMove(wxInputConsumer *control,
3361 const wxMouseEvent& event)
3362 {
3363 if ( event.Entering() )
3364 {
3365 control->GetInputWindow()->SetCurrent(true);
3366 }
3367 else if ( event.Leaving() )
3368 {
3369 control->GetInputWindow()->SetCurrent(false);
3370 }
3371 else
3372 {
3373 return false;
3374 }
3375
3376 return true;
3377 }
3378
3379 #if wxUSE_CHECKBOX
3380
3381 // ----------------------------------------------------------------------------
3382 // wxGTKCheckboxInputHandler
3383 // ----------------------------------------------------------------------------
3384
3385 bool wxGTKCheckboxInputHandler::HandleKey(wxInputConsumer *control,
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
3396 return true;
3397 }
3398 }
3399
3400 return false;
3401 }
3402
3403 #endif // wxUSE_CHECKBOX
3404
3405 #if wxUSE_TEXTCTRL
3406
3407 // ----------------------------------------------------------------------------
3408 // wxGTKTextCtrlInputHandler
3409 // ----------------------------------------------------------------------------
3410
3411 bool wxGTKTextCtrlInputHandler::HandleKey(wxInputConsumer *control,
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
3494 return true;
3495 }
3496 }
3497
3498 return wxStdTextCtrlInputHandler::HandleKey(control, event, pressed);
3499 }
3500
3501 #endif // wxUSE_TEXTCTRL