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