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