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