]> git.saurik.com Git - wxWidgets.git/blob - src/univ/themes/gtk.cpp
deTABified
[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, int flags = 0);
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
838 wxGTKRenderer::DrawFocusRect(wxDC& dc, const wxRect& rect, int WXUNUSED(flags))
839 {
840 dc.SetBrush(*wxTRANSPARENT_BRUSH);
841 wxRect rectFocus = rect;
842 DrawRect(dc, &rectFocus, m_penBlack);
843 }
844
845 void wxGTKRenderer::DrawTextBorder(wxDC& dc,
846 wxBorder border,
847 const wxRect& rectOrig,
848 int flags,
849 wxRect *rectIn)
850 {
851 wxRect rect = rectOrig;
852
853 if ( border != wxBORDER_NONE )
854 {
855 if ( flags & wxCONTROL_FOCUSED )
856 {
857 DrawRect(dc, &rect, m_penBlack);
858 DrawAntiShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight);
859 }
860 else // !focused
861 {
862 DrawInnerShadedRect(dc, &rect);
863 }
864 }
865
866 if ( rectIn )
867 *rectIn = rect;
868 }
869
870 void wxGTKRenderer::DrawButtonLabel(wxDC& dc,
871 const wxString& label,
872 const wxBitmap& image,
873 const wxRect& rect,
874 int flags,
875 int alignment,
876 int indexAccel,
877 wxRect *rectBounds)
878 {
879 // no focus rect around buttons label in GTK+
880 wxStdRenderer::DrawButtonLabel(dc, label, image, rect, flags,
881 alignment, indexAccel, rectBounds);
882 }
883
884 void wxGTKRenderer::DrawButtonBorder(wxDC& dc,
885 const wxRect& rectTotal,
886 int flags,
887 wxRect *rectIn)
888 {
889 wxRect rect = rectTotal;
890
891 if ( flags & wxCONTROL_PRESSED )
892 {
893 // button pressed: draw a black border around it and an inward shade
894 DrawRect(dc, &rect, m_penBlack);
895
896 DrawInnerShadedRect(dc, &rect);
897 }
898 else // button not pressed
899 {
900 if ( flags & wxCONTROL_ISDEFAULT )
901 {
902 // TODO
903 }
904
905 if ( flags & wxCONTROL_FOCUSED )
906 {
907 // button is currently default: add an extra border around it
908 DrawRect(dc, &rect, m_penBlack);
909 }
910
911 // now draw a normal button
912 DrawShadedRect(dc, &rect, m_penHighlight, m_penBlack);
913 DrawAntiShadedRect(dc, &rect, GetBackgroundColour(flags), m_penDarkGrey);
914 }
915
916 if ( rectIn )
917 *rectIn = rect;
918 }
919
920 // ----------------------------------------------------------------------------
921 // lines and frames
922 // ----------------------------------------------------------------------------
923
924 void wxGTKRenderer::DrawFrameWithLabel(wxDC& dc,
925 const wxString& label,
926 const wxRect& rectFrame,
927 const wxRect& rectTextOrig,
928 int flags,
929 int alignment,
930 int indexAccel)
931 {
932 wxRect rectText(rectTextOrig);
933 rectText.Inflate(1, 0);
934
935 wxRect rectLabel;
936 DrawLabel(dc, label, rectText, flags, alignment, indexAccel, &rectLabel);
937 rectLabel.x -= 1;
938 rectLabel.width += 2;
939
940 DrawFrameWithoutLabel(dc, rectFrame, rectLabel);
941
942 // GTK+ does it like this
943 dc.SetPen(m_penHighlight);
944 dc.DrawPoint(rectText.x, rectFrame.y);
945 dc.DrawPoint(rectText.x + rectLabel.width - 3, rectFrame.y);
946 }
947
948 // ----------------------------------------------------------------------------
949 // check/radion buttons
950 // ----------------------------------------------------------------------------
951
952 void wxGTKRenderer::DrawCheckItemBitmap(wxDC& dc,
953 const wxBitmap& bitmap,
954 const wxRect& rect,
955 int flags)
956 {
957 // never draw the focus rect around the check indicators here
958 DrawCheckButton(dc, wxEmptyString, bitmap, rect, flags & ~wxCONTROL_FOCUSED);
959 }
960
961 void wxGTKRenderer::DrawUndeterminedBitmap(wxDC& dc,
962 const wxRect& rectTotal,
963 bool isPressed)
964 {
965 // FIXME: For sure it is not GTK look but it is better than nothing.
966 // Show me correct look and I will immediatelly make it better (ABX)
967 wxRect rect = rectTotal;
968
969 wxColour col1, col2;
970
971 if ( isPressed )
972 {
973 col1 = wxSCHEME_COLOUR(m_scheme, SHADOW_DARK);
974 col2 = wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED);
975 }
976 else
977 {
978 col1 = wxSCHEME_COLOUR(m_scheme, SHADOW_DARK);
979 col2 = wxSCHEME_COLOUR(m_scheme, SHADOW_IN);
980 }
981
982 dc.SetPen(*wxTRANSPARENT_PEN);
983 dc.SetBrush(col1);
984 dc.DrawRectangle(rect);
985 rect.Deflate(1);
986 dc.SetBrush(col2);
987 dc.DrawRectangle(rect);
988 }
989
990 void wxGTKRenderer::DrawUncheckBitmap(wxDC& dc,
991 const wxRect& rectTotal,
992 bool isPressed)
993 {
994 wxRect rect = rectTotal;
995 DrawAntiRaisedBorder(dc, &rect);
996
997 wxColour col = wxSCHEME_COLOUR(m_scheme, SHADOW_IN);
998 dc.SetPen(wxPen(col));
999 dc.DrawPoint(rect.GetRight() - 1, rect.GetBottom() - 1);
1000
1001 if ( isPressed )
1002 col = wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED);
1003 //else: it is SHADOW_IN, leave as is
1004
1005 dc.SetPen(*wxTRANSPARENT_PEN);
1006 dc.SetBrush(col);
1007 dc.DrawRectangle(rect);
1008 }
1009
1010 void wxGTKRenderer::DrawCheckBitmap(wxDC& dc, const wxRect& rectTotal)
1011 {
1012 wxRect rect = rectTotal;
1013 DrawAntiShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight);
1014 DrawShadedRect(dc, &rect, m_penBlack, m_penLightGrey);
1015
1016 dc.SetPen(*wxTRANSPARENT_PEN);
1017 dc.SetBrush(wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED));
1018 dc.DrawRectangle(rect);
1019 }
1020
1021 void wxGTKRenderer::DrawRadioBitmap(wxDC& dc,
1022 const wxRect& rect,
1023 int flags)
1024 {
1025 wxCoord x = rect.x,
1026 y = rect.y,
1027 xRight = rect.GetRight(),
1028 yBottom = rect.GetBottom();
1029
1030 wxCoord yMid = (y + yBottom) / 2;
1031
1032 // then draw the upper half
1033 dc.SetPen(flags & wxCONTROL_CHECKED ? m_penDarkGrey : m_penHighlight);
1034 DrawUpZag(dc, x, xRight, yMid, y);
1035 DrawUpZag(dc, x + 1, xRight - 1, yMid, y + 1);
1036
1037 bool drawIt = true;
1038 if ( flags & wxCONTROL_CHECKED )
1039 dc.SetPen(m_penBlack);
1040 else if ( flags & wxCONTROL_PRESSED )
1041 dc.SetPen(wxPen(wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED)));
1042 else // unchecked and unpressed
1043 drawIt = false;
1044
1045 if ( drawIt )
1046 DrawUpZag(dc, x + 2, xRight - 2, yMid, y + 2);
1047
1048 // and then the lower one
1049 dc.SetPen(flags & wxCONTROL_CHECKED ? m_penHighlight : m_penBlack);
1050 DrawDownZag(dc, x, xRight, yMid, yBottom);
1051 if ( !(flags & wxCONTROL_CHECKED) )
1052 dc.SetPen(m_penDarkGrey);
1053 DrawDownZag(dc, x + 1, xRight - 1, yMid, yBottom - 1);
1054
1055 if ( !(flags & wxCONTROL_CHECKED) )
1056 drawIt = true; // with the same pen
1057 else if ( flags & wxCONTROL_PRESSED )
1058 {
1059 dc.SetPen(wxPen(wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED)));
1060 drawIt = true;
1061 }
1062 else // checked and unpressed
1063 drawIt = false;
1064
1065 if ( drawIt )
1066 DrawDownZag(dc, x + 2, xRight - 2, yMid, yBottom - 2);
1067 }
1068
1069 void wxGTKRenderer::DrawUpZag(wxDC& dc,
1070 wxCoord x1,
1071 wxCoord x2,
1072 wxCoord y1,
1073 wxCoord y2)
1074 {
1075 wxCoord xMid = (x1 + x2) / 2;
1076 dc.DrawLine(x1, y1, xMid, y2);
1077 dc.DrawLine(xMid, y2, x2 + 1, y1 + 1);
1078 }
1079
1080 void wxGTKRenderer::DrawDownZag(wxDC& dc,
1081 wxCoord x1,
1082 wxCoord x2,
1083 wxCoord y1,
1084 wxCoord y2)
1085 {
1086 wxCoord xMid = (x1 + x2) / 2;
1087 dc.DrawLine(x1 + 1, y1 + 1, xMid, y2);
1088 dc.DrawLine(xMid, y2, x2, y1);
1089 }
1090
1091 wxBitmap wxGTKRenderer::GetCheckBitmap(int flags)
1092 {
1093 if ( !m_bitmapsCheckbox[0][0].Ok() )
1094 {
1095 // init the bitmaps once only
1096 wxRect rect;
1097 wxSize size = GetCheckBitmapSize();
1098 rect.width = size.x;
1099 rect.height = size.y;
1100 for ( int i = 0; i < 2; i++ )
1101 {
1102 for ( int j = 0; j < 3; j++ )
1103 m_bitmapsCheckbox[i][j].Create(rect.width, rect.height);
1104 }
1105
1106 wxMemoryDC dc;
1107
1108 // normal checked
1109 dc.SelectObject(m_bitmapsCheckbox[0][0]);
1110 DrawCheckBitmap(dc, rect);
1111
1112 // normal unchecked
1113 dc.SelectObject(m_bitmapsCheckbox[0][1]);
1114 DrawUncheckBitmap(dc, rect, false);
1115
1116 // normal undeterminated
1117 dc.SelectObject(m_bitmapsCheckbox[0][2]);
1118 DrawUndeterminedBitmap(dc, rect, false);
1119
1120 // pressed checked
1121 m_bitmapsCheckbox[1][0] = m_bitmapsCheckbox[0][0];
1122
1123 // pressed unchecked
1124 dc.SelectObject(m_bitmapsCheckbox[1][1]);
1125 DrawUncheckBitmap(dc, rect, true);
1126
1127 // pressed undeterminated
1128 dc.SelectObject(m_bitmapsCheckbox[1][2]);
1129 DrawUndeterminedBitmap(dc, rect, true);
1130 }
1131
1132 IndicatorState state;
1133 IndicatorStatus status;
1134 GetIndicatorsFromFlags(flags, state, status);
1135
1136 // disabled looks the same as normal
1137 if ( state == IndicatorState_Disabled )
1138 state = IndicatorState_Normal;
1139
1140 return m_bitmapsCheckbox[state][status];
1141 }
1142
1143 wxBitmap wxGTKRenderer::GetRadioBitmap(int flags)
1144 {
1145 IndicatorState state;
1146 IndicatorStatus status;
1147 GetIndicatorsFromFlags(flags, state, status);
1148
1149 wxBitmap& bmp = m_bitmapsRadiobtn[state][status];
1150 if ( !bmp.Ok() )
1151 {
1152 const wxSize size = GetRadioBitmapSize();
1153
1154 wxMemoryDC dc;
1155 bmp.Create(size.x, size.y);
1156 dc.SelectObject(bmp);
1157
1158 DrawRadioBitmap(dc, size, flags);
1159 }
1160
1161 return bmp;
1162 }
1163
1164 wxBitmap wxGTKRenderer::GetLineWrapBitmap() const
1165 {
1166 if ( !m_bmpLineWrap.Ok() )
1167 {
1168 // the line wrap bitmap as used by GTK+
1169 #define line_wrap_width 6
1170 #define line_wrap_height 9
1171 static const char line_wrap_bits[] =
1172 {
1173 0x1e, 0x3e, 0x30, 0x30, 0x39, 0x1f, 0x0f, 0x0f, 0x1f,
1174 };
1175
1176 wxBitmap bmpLineWrap(line_wrap_bits, line_wrap_width, line_wrap_height);
1177 if ( !bmpLineWrap.Ok() )
1178 {
1179 wxFAIL_MSG( _T("Failed to create line wrap XBM") );
1180 }
1181 else
1182 {
1183 wxConstCast(this, wxGTKRenderer)->m_bmpLineWrap = bmpLineWrap;
1184 }
1185 }
1186
1187 return m_bmpLineWrap;
1188 }
1189
1190 #if wxUSE_TOOLBAR
1191 void wxGTKRenderer::DrawToolBarButton(wxDC& dc,
1192 const wxString& label,
1193 const wxBitmap& bitmap,
1194 const wxRect& rectOrig,
1195 int flags,
1196 long WXUNUSED(style),
1197 int tbarStyle)
1198 {
1199 // we don't draw the separators at all
1200 if ( !label.empty() || bitmap.Ok() )
1201 {
1202 wxRect rect = rectOrig;
1203 rect.Deflate(BORDER_THICKNESS);
1204
1205 if ( flags & wxCONTROL_PRESSED )
1206 {
1207 DrawBorder(dc, wxBORDER_SUNKEN, rect, flags, &rect);
1208
1209 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED), rect);
1210 }
1211 else if ( flags & wxCONTROL_CURRENT )
1212 {
1213 DrawBorder(dc, wxBORDER_RAISED, rect, flags, &rect);
1214
1215 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL_CURRENT), rect);
1216 }
1217
1218 if(tbarStyle & wxTB_TEXT)
1219 {
1220 if(tbarStyle & wxTB_HORIZONTAL)
1221 {
1222 dc.DrawLabel(label, bitmap, rect, wxALIGN_CENTRE);
1223 }
1224 else
1225 {
1226 dc.DrawLabel(label, bitmap, rect, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL);
1227 }
1228 }
1229 else
1230 {
1231 int xpoint = (rect.GetLeft() + rect.GetRight() + 1 - bitmap.GetWidth()) / 2;
1232 int ypoint = (rect.GetTop() + rect.GetBottom() + 1 - bitmap.GetHeight()) / 2;
1233 dc.DrawBitmap(bitmap, xpoint, ypoint);
1234 }
1235 }
1236 }
1237 #endif // wxUSE_TOOLBAR
1238
1239 // ----------------------------------------------------------------------------
1240 // text control
1241 // ----------------------------------------------------------------------------
1242
1243 #if wxUSE_TEXTCTRL
1244
1245 wxRect wxGTKRenderer::GetTextClientArea(const wxTextCtrl *text,
1246 const wxRect& rect,
1247 wxCoord *extraSpaceBeyond) const
1248 {
1249 wxRect
1250 rectText = wxStdRenderer::GetTextClientArea(text, rect, extraSpaceBeyond);
1251
1252 if ( text->WrapLines() )
1253 {
1254 // leave enough for the line wrap bitmap indicator
1255 wxCoord widthMark = GetLineWrapBitmap().GetWidth() + 2;
1256
1257 rectText.width -= widthMark;
1258
1259 if ( extraSpaceBeyond )
1260 *extraSpaceBeyond = widthMark;
1261 }
1262
1263 return rectText;
1264 }
1265
1266 void wxGTKRenderer::DrawLineWrapMark(wxDC& dc, const wxRect& rect)
1267 {
1268 wxBitmap bmpLineWrap = GetLineWrapBitmap();
1269
1270 // for a mono bitmap he colours it appears in depends on the current text
1271 // colours, so set them correctly
1272 wxColour colFgOld;
1273 if ( bmpLineWrap.GetDepth() == 1 )
1274 {
1275 colFgOld = dc.GetTextForeground();
1276
1277 // FIXME: I wonder what should we do if the background is black too?
1278 dc.SetTextForeground(*wxBLACK);
1279 }
1280
1281 dc.DrawBitmap(bmpLineWrap,
1282 rect.x, rect.y + (rect.height - bmpLineWrap.GetHeight())/2);
1283
1284 if ( colFgOld.Ok() )
1285 {
1286 // restore old colour
1287 dc.SetTextForeground(colFgOld);
1288 }
1289 }
1290
1291 #endif // wxUSE_TEXTCTRL
1292
1293 // ----------------------------------------------------------------------------
1294 // notebook
1295 // ----------------------------------------------------------------------------
1296
1297 #if wxUSE_NOTEBOOK
1298
1299 void wxGTKRenderer::DrawTab(wxDC& dc,
1300 const wxRect& rectOrig,
1301 wxDirection dir,
1302 const wxString& label,
1303 const wxBitmap& bitmap,
1304 int flags,
1305 int indexAccel)
1306 {
1307 #define SELECT_FOR_VERTICAL(X,Y) ( isVertical ? Y : X )
1308 #define REVERSE_FOR_VERTICAL(X,Y) \
1309 SELECT_FOR_VERTICAL(X,Y) \
1310 , \
1311 SELECT_FOR_VERTICAL(Y,X)
1312
1313 wxRect rect = rectOrig;
1314
1315 bool isVertical = ( dir == wxLEFT ) || ( dir == wxRIGHT );
1316
1317 // the current tab is drawn indented (to the top for default case) and
1318 // bigger than the other ones
1319 const wxSize indent = GetTabIndent();
1320 if ( flags & wxCONTROL_SELECTED )
1321 {
1322 rect.Inflate( SELECT_FOR_VERTICAL( indent.x , 0),
1323 SELECT_FOR_VERTICAL( 0, indent.y ));
1324 switch ( dir )
1325 {
1326 default:
1327 wxFAIL_MSG(_T("invaild notebook tab orientation"));
1328 // fall through
1329
1330 case wxTOP:
1331 rect.y -= indent.y;
1332 // fall through
1333 case wxBOTTOM:
1334 rect.height += indent.y;
1335 break;
1336
1337 case wxLEFT:
1338 rect.x -= indent.x;
1339 // fall through
1340 case wxRIGHT:
1341 rect.width += indent.x;
1342 break;
1343 }
1344 }
1345
1346 // selected tab has different colour
1347 wxColour col = flags & wxCONTROL_SELECTED
1348 ? wxSCHEME_COLOUR(m_scheme, SHADOW_IN)
1349 : wxSCHEME_COLOUR(m_scheme, SCROLLBAR);
1350 DrawSolidRect(dc, col, rect);
1351
1352 if ( flags & wxCONTROL_FOCUSED )
1353 {
1354 // draw the focus rect
1355 wxRect rectBorder = rect;
1356 rectBorder.Deflate(4, 3);
1357 if ( dir == wxBOTTOM )
1358 rectBorder.Offset(0, -1);
1359 if ( dir == wxRIGHT )
1360 rectBorder.Offset(-1, 0);
1361
1362 DrawRect(dc, &rectBorder, m_penBlack);
1363 }
1364
1365 // draw the text, image and the focus around them (if necessary)
1366 wxRect rectLabel( REVERSE_FOR_VERTICAL(rect.x,rect.y),
1367 REVERSE_FOR_VERTICAL(rect.width,rect.height)
1368 );
1369 rectLabel.Deflate(1, 1);
1370 if ( isVertical )
1371 {
1372 // draw it horizontally into memory and rotate for screen
1373 wxMemoryDC dcMem;
1374 wxBitmap bitmapRotated,
1375 bitmapMem( rectLabel.x + rectLabel.width,
1376 rectLabel.y + rectLabel.height );
1377 dcMem.SelectObject(bitmapMem);
1378 dcMem.SetBackground(dc.GetBackground());
1379 dcMem.SetFont(dc.GetFont());
1380 dcMem.SetTextForeground(dc.GetTextForeground());
1381 dcMem.Clear();
1382 bitmapRotated =
1383 #if wxUSE_IMAGE
1384 wxBitmap( wxImage( bitmap.ConvertToImage() ).Rotate90(dir==wxLEFT) )
1385 #else
1386 bitmap
1387 #endif // wxUSE_IMAGE
1388 ;
1389 dcMem.DrawLabel(label, bitmapRotated, rectLabel, wxALIGN_CENTRE, indexAccel);
1390 dcMem.SelectObject(wxNullBitmap);
1391 bitmapMem = bitmapMem.GetSubBitmap(rectLabel);
1392 #if wxUSE_IMAGE
1393 bitmapMem = wxBitmap(wxImage(bitmapMem.ConvertToImage()).Rotate90(dir==wxRIGHT))
1394 #endif
1395 ;
1396
1397 dc.DrawBitmap(bitmapMem, rectLabel.y, rectLabel.x, false);
1398 }
1399 else
1400 {
1401 dc.DrawLabel(label, bitmap, rectLabel, wxALIGN_CENTRE, indexAccel);
1402 }
1403
1404 // now draw the tab itself
1405 wxCoord x = SELECT_FOR_VERTICAL(rect.x,rect.y),
1406 y = SELECT_FOR_VERTICAL(rect.y,rect.x),
1407 x2 = SELECT_FOR_VERTICAL(rect.GetRight(),rect.GetBottom()),
1408 y2 = SELECT_FOR_VERTICAL(rect.GetBottom(),rect.GetRight());
1409 switch ( dir )
1410 {
1411 default:
1412 // default is top
1413 case wxLEFT:
1414 // left orientation looks like top but IsVertical makes x and y reversed
1415 case wxTOP:
1416 // top is not vertical so use coordinates in written order
1417 dc.SetPen(m_penHighlight);
1418 dc.DrawLine(REVERSE_FOR_VERTICAL(x, y2),
1419 REVERSE_FOR_VERTICAL(x, y));
1420 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y),
1421 REVERSE_FOR_VERTICAL(x2, y));
1422
1423 dc.SetPen(m_penBlack);
1424 dc.DrawLine(REVERSE_FOR_VERTICAL(x2, y2),
1425 REVERSE_FOR_VERTICAL(x2, y));
1426
1427 dc.SetPen(m_penDarkGrey);
1428 dc.DrawLine(REVERSE_FOR_VERTICAL(x2 - 1, y2),
1429 REVERSE_FOR_VERTICAL(x2 - 1, y + 1));
1430
1431 if ( flags & wxCONTROL_SELECTED )
1432 {
1433 dc.SetPen(m_penLightGrey);
1434
1435 // overwrite the part of the border below this tab
1436 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y2 + 1),
1437 REVERSE_FOR_VERTICAL(x2 - 1, y2 + 1));
1438
1439 // and the shadow of the tab to the left of us
1440 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y + 2),
1441 REVERSE_FOR_VERTICAL(x + 1, y2 + 1));
1442 }
1443 break;
1444
1445 case wxRIGHT:
1446 // right orientation looks like bottom but IsVertical makes x and y reversed
1447 case wxBOTTOM:
1448 // bottom is not vertical so use coordinates in written order
1449 dc.SetPen(m_penHighlight);
1450
1451 // we need to continue one pixel further to overwrite the corner of
1452 // the border for the selected tab
1453 dc.DrawLine(REVERSE_FOR_VERTICAL(x, y - (flags & wxCONTROL_SELECTED ? 1 : 0)),
1454 REVERSE_FOR_VERTICAL(x, y2));
1455
1456 // it doesn't work like this (TODO: implement it properly)
1457 #if 0
1458 // erase the corner of the tab to the right
1459 dc.SetPen(m_penLightGrey);
1460 dc.DrawPoint(REVERSE_FOR_VERTICAL(x2 - 1, y - 2));
1461 dc.DrawPoint(REVERSE_FOR_VERTICAL(x2 - 2, y - 2));
1462 dc.DrawPoint(REVERSE_FOR_VERTICAL(x2 - 2, y - 1));
1463 #endif // 0
1464
1465 dc.SetPen(m_penBlack);
1466 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y2),
1467 REVERSE_FOR_VERTICAL(x2, y2));
1468 dc.DrawLine(REVERSE_FOR_VERTICAL(x2, y),
1469 REVERSE_FOR_VERTICAL(x2, y2));
1470
1471 dc.SetPen(m_penDarkGrey);
1472 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 2, y2 - 1),
1473 REVERSE_FOR_VERTICAL(x2 - 1, y2 - 1));
1474 dc.DrawLine(REVERSE_FOR_VERTICAL(x2 - 1, y),
1475 REVERSE_FOR_VERTICAL(x2 - 1, y2));
1476
1477 if ( flags & wxCONTROL_SELECTED )
1478 {
1479 dc.SetPen(m_penLightGrey);
1480
1481 // overwrite the part of the (double!) border above this tab
1482 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y - 1),
1483 REVERSE_FOR_VERTICAL(x2 - 1, y - 1));
1484 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y - 2),
1485 REVERSE_FOR_VERTICAL(x2 - 1, y - 2));
1486
1487 // and the shadow of the tab to the left of us
1488 dc.DrawLine(REVERSE_FOR_VERTICAL(x + 1, y2 - 1),
1489 REVERSE_FOR_VERTICAL(x + 1, y - 1));
1490 }
1491 break;
1492 }
1493 }
1494
1495 #endif // wxUSE_NOTEBOOK
1496
1497 // ----------------------------------------------------------------------------
1498 // slider
1499 // ----------------------------------------------------------------------------
1500
1501 #if wxUSE_SLIDER
1502
1503 wxSize wxGTKRenderer::GetSliderThumbSize(const wxRect& rect,
1504 int lenThumb,
1505 wxOrientation orient) const
1506 {
1507 static const wxCoord SLIDER_THUMB_LENGTH = 30;
1508
1509 wxSize size;
1510
1511 wxRect rectShaft = GetSliderShaftRect(rect, lenThumb, orient);
1512 if ( orient == wxHORIZONTAL )
1513 {
1514 size.x = wxMin(SLIDER_THUMB_LENGTH, rectShaft.width);
1515 size.y = rectShaft.height;
1516 }
1517 else // vertical
1518 {
1519 size.y = wxMin(SLIDER_THUMB_LENGTH, rectShaft.height);
1520 size.x = rectShaft.width;
1521 }
1522
1523 return size;
1524 }
1525
1526 wxRect wxGTKRenderer::GetSliderShaftRect(const wxRect& rect,
1527 int WXUNUSED(lenThumb),
1528 wxOrientation WXUNUSED(orient),
1529 long WXUNUSED(style)) const
1530 {
1531 return rect.Deflate(2*BORDER_THICKNESS, 2*BORDER_THICKNESS);
1532 }
1533
1534 void wxGTKRenderer::DrawSliderShaft(wxDC& dc,
1535 const wxRect& rectOrig,
1536 int WXUNUSED(lenThumb),
1537 wxOrientation WXUNUSED(orient),
1538 int flags,
1539 long WXUNUSED(style),
1540 wxRect *rectShaft)
1541 {
1542 wxRect rect = rectOrig;
1543
1544 // draw the border first
1545 if ( flags & wxCONTROL_FOCUSED )
1546 {
1547 DrawRect(dc, &rect, m_penBlack);
1548 }
1549 else // not focused, normal
1550 {
1551 DrawAntiShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight);
1552 }
1553
1554 DrawAntiShadedRect(dc, &rect, m_penBlack, m_penLightGrey);
1555
1556 // and the background
1557 DrawSolidRect(dc, wxSCHEME_COLOUR(m_scheme, SCROLLBAR), rect);
1558
1559 if ( rectShaft )
1560 *rectShaft = rect;
1561 }
1562
1563 void wxGTKRenderer::DrawSliderThumb(wxDC& dc,
1564 const wxRect& rectOrig,
1565 wxOrientation orient,
1566 int WXUNUSED(flags),
1567 long WXUNUSED(style))
1568 {
1569 // draw the thumb border
1570 wxRect rect = rectOrig;
1571 DrawAntiRaisedBorder(dc, &rect);
1572
1573 // draw the handle in the middle
1574 if ( orient == wxVERTICAL )
1575 {
1576 rect.height = 2*BORDER_THICKNESS;
1577 rect.y = rectOrig.y + (rectOrig.height - rect.height) / 2;
1578 }
1579 else // horz
1580 {
1581 rect.width = 2*BORDER_THICKNESS;
1582 rect.x = rectOrig.x + (rectOrig.width - rect.width) / 2;
1583 }
1584
1585 DrawShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight);
1586 }
1587
1588 #endif // wxUSE_SLIDER
1589
1590 #if wxUSE_MENUS
1591
1592 // ----------------------------------------------------------------------------
1593 // menu and menubar
1594 // ----------------------------------------------------------------------------
1595
1596 // wxGTKMenuGeometryInfo: the wxMenuGeometryInfo used by wxGTKRenderer
1597 class WXDLLEXPORT wxGTKMenuGeometryInfo : public wxMenuGeometryInfo
1598 {
1599 public:
1600 virtual wxSize GetSize() const { return m_size; }
1601
1602 wxCoord GetLabelOffset() const { return m_ofsLabel; }
1603 wxCoord GetAccelOffset() const { return m_ofsAccel; }
1604
1605 wxCoord GetItemHeight() const { return m_heightItem; }
1606
1607 private:
1608 // the total size of the menu
1609 wxSize m_size;
1610
1611 // the offset of the start of the menu item label
1612 wxCoord m_ofsLabel;
1613
1614 // the offset of the start of the accel label
1615 wxCoord m_ofsAccel;
1616
1617 // the height of a normal (not separator) item
1618 wxCoord m_heightItem;
1619
1620 friend wxMenuGeometryInfo *
1621 wxGTKRenderer::GetMenuGeometry(wxWindow *, const wxMenu&) const;
1622 };
1623
1624 // FIXME: all constants are hardcoded but shouldn't be
1625 static const wxCoord MENU_LEFT_MARGIN = 9;
1626 static const wxCoord MENU_RIGHT_MARGIN = 6;
1627
1628 static const wxCoord MENU_HORZ_MARGIN = 6;
1629 static const wxCoord MENU_VERT_MARGIN = 3;
1630
1631 // the margin around bitmap/check marks (on each side)
1632 static const wxCoord MENU_BMP_MARGIN = 2;
1633
1634 // the margin between the labels and accel strings
1635 static const wxCoord MENU_ACCEL_MARGIN = 8;
1636
1637 // the separator height in pixels: in fact, strangely enough, the real height
1638 // is 2 but Windows adds one extra pixel in the bottom margin, so take it into
1639 // account here
1640 static const wxCoord MENU_SEPARATOR_HEIGHT = 3;
1641
1642 // the size of the standard checkmark bitmap
1643 static const wxCoord MENU_CHECK_SIZE = 9;
1644
1645 void wxGTKRenderer::DrawMenuBarItem(wxDC& dc,
1646 const wxRect& rect,
1647 const wxString& label,
1648 int flags,
1649 int indexAccel)
1650 {
1651 DoDrawMenuItem(dc, rect, label, flags, indexAccel);
1652 }
1653
1654 void wxGTKRenderer::DrawMenuItem(wxDC& dc,
1655 wxCoord y,
1656 const wxMenuGeometryInfo& gi,
1657 const wxString& label,
1658 const wxString& accel,
1659 const wxBitmap& bitmap,
1660 int flags,
1661 int indexAccel)
1662 {
1663 const wxGTKMenuGeometryInfo& geomInfo = (const wxGTKMenuGeometryInfo&)gi;
1664
1665 wxRect rect;
1666 rect.x = 0;
1667 rect.y = y;
1668 rect.width = geomInfo.GetSize().x;
1669 rect.height = geomInfo.GetItemHeight();
1670
1671 DoDrawMenuItem(dc, rect, label, flags, indexAccel, accel, bitmap, &geomInfo);
1672 }
1673
1674 void wxGTKRenderer::DoDrawMenuItem(wxDC& dc,
1675 const wxRect& rectOrig,
1676 const wxString& label,
1677 int flags,
1678 int indexAccel,
1679 const wxString& accel,
1680 const wxBitmap& bitmap,
1681 const wxGTKMenuGeometryInfo *geometryInfo)
1682 {
1683 wxRect rect = rectOrig;
1684
1685 // draw the selected item specially
1686 if ( flags & wxCONTROL_SELECTED )
1687 {
1688 wxRect rectIn;
1689 DrawBorder(dc, wxBORDER_RAISED, rect, flags, &rectIn);
1690
1691 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL_CURRENT), rectIn);
1692 }
1693
1694 rect.Deflate(MENU_HORZ_MARGIN, MENU_VERT_MARGIN);
1695
1696 // draw the bitmap: use the bitmap provided or the standard checkmark for
1697 // the checkable items
1698 if ( geometryInfo )
1699 {
1700 wxBitmap bmp = bitmap;
1701 if ( !bmp.Ok() && (flags & wxCONTROL_CHECKABLE) )
1702 {
1703 bmp = GetCheckBitmap(flags);
1704 }
1705
1706 if ( bmp.Ok() )
1707 {
1708 rect.SetRight(geometryInfo->GetLabelOffset());
1709 wxControlRenderer::DrawBitmap(dc, bmp, rect);
1710 }
1711 }
1712 //else: menubar items don't have bitmaps
1713
1714 // draw the label
1715 if ( geometryInfo )
1716 {
1717 rect.x = geometryInfo->GetLabelOffset();
1718 rect.SetRight(geometryInfo->GetAccelOffset());
1719 }
1720
1721 DrawLabel(dc, label, rect, flags, wxALIGN_CENTRE_VERTICAL, indexAccel);
1722
1723 // draw the accel string
1724 if ( !accel.empty() )
1725 {
1726 // menubar items shouldn't have them
1727 wxCHECK_RET( geometryInfo, _T("accel strings only valid for menus") );
1728
1729 rect.x = geometryInfo->GetAccelOffset();
1730 rect.SetRight(geometryInfo->GetSize().x);
1731
1732 // NB: no accel index here
1733 DrawLabel(dc, accel, rect, flags, wxALIGN_CENTRE_VERTICAL);
1734 }
1735
1736 // draw the submenu indicator
1737 if ( flags & wxCONTROL_ISSUBMENU )
1738 {
1739 wxCHECK_RET( geometryInfo, _T("wxCONTROL_ISSUBMENU only valid for menus") );
1740
1741 rect.x = geometryInfo->GetSize().x - MENU_RIGHT_MARGIN;
1742 rect.width = MENU_RIGHT_MARGIN;
1743
1744 DrawArrow(dc, wxRIGHT, rect, flags);
1745 }
1746 }
1747
1748 void wxGTKRenderer::DrawMenuSeparator(wxDC& dc,
1749 wxCoord y,
1750 const wxMenuGeometryInfo& geomInfo)
1751 {
1752 DrawHorizontalLine(dc, y + MENU_VERT_MARGIN, 0, geomInfo.GetSize().x);
1753 }
1754
1755 wxSize wxGTKRenderer::GetMenuBarItemSize(const wxSize& sizeText) const
1756 {
1757 wxSize size = sizeText;
1758
1759 // TODO: make this configurable
1760 size.x += 2*MENU_HORZ_MARGIN;
1761 size.y += 2*MENU_VERT_MARGIN;
1762
1763 return size;
1764 }
1765
1766 wxMenuGeometryInfo *wxGTKRenderer::GetMenuGeometry(wxWindow *win,
1767 const wxMenu& menu) const
1768 {
1769 // prepare the dc: for now we draw all the items with the system font
1770 wxClientDC dc(win);
1771 dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
1772
1773 // the height of a normal item
1774 wxCoord heightText = dc.GetCharHeight();
1775
1776 // the total height
1777 wxCoord height = 0;
1778
1779 // the max length of label and accel strings: the menu width is the sum of
1780 // them, even if they're for different items (as the accels should be
1781 // aligned)
1782 //
1783 // the max length of the bitmap is never 0 as Windows always leaves enough
1784 // space for a check mark indicator
1785 wxCoord widthLabelMax = 0,
1786 widthAccelMax = 0,
1787 widthBmpMax = MENU_LEFT_MARGIN;
1788
1789 for ( wxMenuItemList::compatibility_iterator node = menu.GetMenuItems().GetFirst();
1790 node;
1791 node = node->GetNext() )
1792 {
1793 // height of this item
1794 wxCoord h;
1795
1796 wxMenuItem *item = node->GetData();
1797 if ( item->IsSeparator() )
1798 {
1799 h = MENU_SEPARATOR_HEIGHT;
1800 }
1801 else // not separator
1802 {
1803 h = heightText;
1804
1805 wxCoord widthLabel;
1806 dc.GetTextExtent(item->GetLabel(), &widthLabel, NULL);
1807 if ( widthLabel > widthLabelMax )
1808 {
1809 widthLabelMax = widthLabel;
1810 }
1811
1812 wxCoord widthAccel;
1813 dc.GetTextExtent(item->GetAccelString(), &widthAccel, NULL);
1814 if ( widthAccel > widthAccelMax )
1815 {
1816 widthAccelMax = widthAccel;
1817 }
1818
1819 const wxBitmap& bmp = item->GetBitmap();
1820 if ( bmp.Ok() )
1821 {
1822 wxCoord widthBmp = bmp.GetWidth();
1823 if ( widthBmp > widthBmpMax )
1824 widthBmpMax = widthBmp;
1825 }
1826 //else if ( item->IsCheckable() ): no need to check for this as
1827 // MENU_LEFT_MARGIN is big enough to show the check mark
1828 }
1829
1830 h += 2*MENU_VERT_MARGIN;
1831
1832 // remember the item position and height
1833 item->SetGeometry(height, h);
1834
1835 height += h;
1836 }
1837
1838 // bundle the metrics into a struct and return it
1839 wxGTKMenuGeometryInfo *gi = new wxGTKMenuGeometryInfo;
1840
1841 gi->m_ofsLabel = widthBmpMax + 2*MENU_BMP_MARGIN;
1842 gi->m_ofsAccel = gi->m_ofsLabel + widthLabelMax;
1843 if ( widthAccelMax > 0 )
1844 {
1845 // if we actually have any accesl, add a margin
1846 gi->m_ofsAccel += MENU_ACCEL_MARGIN;
1847 }
1848
1849 gi->m_heightItem = heightText + 2*MENU_VERT_MARGIN;
1850
1851 gi->m_size.x = gi->m_ofsAccel + widthAccelMax + MENU_RIGHT_MARGIN;
1852 gi->m_size.y = height;
1853
1854 return gi;
1855 }
1856
1857 #endif // wxUSE_MENUS
1858
1859 // ----------------------------------------------------------------------------
1860 // combobox
1861 // ----------------------------------------------------------------------------
1862
1863 void wxGTKRenderer::InitComboBitmaps()
1864 {
1865 wxSize sizeArrow = m_sizeScrollbarArrow;
1866 sizeArrow.x -= 2;
1867 sizeArrow.y -= 2;
1868
1869 size_t n;
1870
1871 for ( n = ComboState_Normal; n < ComboState_Max; n++ )
1872 {
1873 m_bitmapsCombo[n].Create(sizeArrow.x, sizeArrow.y);
1874 }
1875
1876 static const int comboButtonFlags[ComboState_Max] =
1877 {
1878 0,
1879 wxCONTROL_CURRENT,
1880 wxCONTROL_PRESSED,
1881 wxCONTROL_DISABLED,
1882 };
1883
1884 wxRect rect(sizeArrow);
1885
1886 wxMemoryDC dc;
1887 for ( n = ComboState_Normal; n < ComboState_Max; n++ )
1888 {
1889 int flags = comboButtonFlags[n];
1890
1891 dc.SelectObject(m_bitmapsCombo[n]);
1892 DrawSolidRect(dc, GetBackgroundColour(flags), rect);
1893 DrawArrow(dc, wxDOWN, rect, flags);
1894 }
1895 }
1896
1897 void wxGTKRenderer::GetComboBitmaps(wxBitmap *bmpNormal,
1898 wxBitmap *bmpFocus,
1899 wxBitmap *bmpPressed,
1900 wxBitmap *bmpDisabled)
1901 {
1902 if ( !m_bitmapsCombo[ComboState_Normal].Ok() )
1903 {
1904 InitComboBitmaps();
1905 }
1906
1907 if ( bmpNormal )
1908 *bmpNormal = m_bitmapsCombo[ComboState_Normal];
1909 if ( bmpFocus )
1910 *bmpFocus = m_bitmapsCombo[ComboState_Focus];
1911 if ( bmpPressed )
1912 *bmpPressed = m_bitmapsCombo[ComboState_Pressed];
1913 if ( bmpDisabled )
1914 *bmpDisabled = m_bitmapsCombo[ComboState_Disabled];
1915 }
1916
1917 // ----------------------------------------------------------------------------
1918 // scrollbar
1919 // ----------------------------------------------------------------------------
1920
1921 void wxGTKRenderer::DrawArrowBorder(wxDC& dc,
1922 wxRect *rect,
1923 wxDirection dir)
1924 {
1925 static const wxDirection sides[] =
1926 {
1927 wxUP, wxLEFT, wxRIGHT, wxDOWN
1928 };
1929
1930 wxRect rect1, rect2, rectInner;
1931 rect1 =
1932 rect2 =
1933 rectInner = *rect;
1934
1935 rect2.Inflate(-1);
1936 rectInner.Inflate(-2);
1937
1938 DrawSolidRect(dc, wxSCHEME_COLOUR(m_scheme, SCROLLBAR), *rect);
1939
1940 // find the side not to draw and also adjust the rectangles to compensate
1941 // for it
1942 wxDirection sideToOmit;
1943 switch ( dir )
1944 {
1945 case wxUP:
1946 sideToOmit = wxDOWN;
1947 rect2.height += 1;
1948 rectInner.height += 1;
1949 break;
1950
1951 case wxDOWN:
1952 sideToOmit = wxUP;
1953 rect2.y -= 1;
1954 rect2.height += 1;
1955 rectInner.y -= 2;
1956 rectInner.height += 1;
1957 break;
1958
1959 case wxLEFT:
1960 sideToOmit = wxRIGHT;
1961 rect2.width += 1;
1962 rectInner.width += 1;
1963 break;
1964
1965 case wxRIGHT:
1966 sideToOmit = wxLEFT;
1967 rect2.x -= 1;
1968 rect2.width += 1;
1969 rectInner.x -= 2;
1970 rectInner.width += 1;
1971 break;
1972
1973 default:
1974 wxFAIL_MSG(_T("unknown arrow direction"));
1975 return;
1976 }
1977
1978 // the outer rect first
1979 size_t n;
1980 for ( n = 0; n < WXSIZEOF(sides); n++ )
1981 {
1982 wxDirection side = sides[n];
1983 if ( side == sideToOmit )
1984 continue;
1985
1986 DrawAntiShadedRectSide(dc, rect1, m_penDarkGrey, m_penHighlight, side);
1987 }
1988
1989 // and then the inner one
1990 for ( n = 0; n < WXSIZEOF(sides); n++ )
1991 {
1992 wxDirection side = sides[n];
1993 if ( side == sideToOmit )
1994 continue;
1995
1996 DrawAntiShadedRectSide(dc, rect2, m_penBlack, m_penGrey, side);
1997 }
1998
1999 *rect = rectInner;
2000 }
2001
2002 void wxGTKRenderer::DrawScrollbarArrow(wxDC& dc,
2003 wxDirection dir,
2004 const wxRect& rectArrow,
2005 int flags)
2006 {
2007 // first of all, draw the border around it - but we don't want the border
2008 // on the side opposite to the arrow point
2009 wxRect rect = rectArrow;
2010 DrawArrowBorder(dc, &rect, dir);
2011
2012 // then the arrow itself
2013 DrawArrow(dc, dir, rect, flags);
2014 }
2015
2016 // gtk_default_draw_arrow() takes ~350 lines and we can't do much better here
2017 // these people are just crazy :-(
2018 void wxGTKRenderer::DrawArrow(wxDC& dc,
2019 wxDirection dir,
2020 const wxRect& rect,
2021 int flags)
2022 {
2023 enum
2024 {
2025 Point_First,
2026 Point_Second,
2027 Point_Third,
2028 Point_Max
2029 };
2030
2031 wxPoint ptArrow[Point_Max];
2032
2033 wxColour colInside = GetBackgroundColour(flags);
2034 wxPen penShadow[4];
2035 if ( flags & wxCONTROL_DISABLED )
2036 {
2037 penShadow[0] = m_penDarkGrey;
2038 penShadow[1] = m_penDarkGrey;
2039 penShadow[2] = wxNullPen;
2040 penShadow[3] = wxNullPen;
2041 }
2042 else if ( flags & wxCONTROL_PRESSED )
2043 {
2044 penShadow[0] = m_penDarkGrey;
2045 penShadow[1] = m_penHighlight;
2046 penShadow[2] = wxNullPen;
2047 penShadow[3] = m_penBlack;
2048 }
2049 else // normal arrow
2050 {
2051 penShadow[0] = m_penHighlight;
2052 penShadow[1] = m_penBlack;
2053 penShadow[2] = m_penDarkGrey;
2054 penShadow[3] = wxNullPen;
2055 }
2056
2057 wxCoord middle;
2058 if ( dir == wxUP || dir == wxDOWN )
2059 {
2060 // horz middle
2061 middle = (rect.GetRight() + rect.GetLeft() + 1) / 2;
2062 }
2063 else // horz arrow
2064 {
2065 middle = (rect.GetTop() + rect.GetBottom() + 1) / 2;
2066 }
2067
2068 // draw the arrow interior
2069 dc.SetPen(*wxTRANSPARENT_PEN);
2070 dc.SetBrush(colInside);
2071
2072 switch ( dir )
2073 {
2074 case wxUP:
2075 ptArrow[Point_First].x = rect.GetLeft();
2076 ptArrow[Point_First].y = rect.GetBottom();
2077 ptArrow[Point_Second].x = middle;
2078 ptArrow[Point_Second].y = rect.GetTop();
2079 ptArrow[Point_Third].x = rect.GetRight();
2080 ptArrow[Point_Third].y = rect.GetBottom();
2081 break;
2082
2083 case wxDOWN:
2084 ptArrow[Point_First] = rect.GetPosition();
2085 ptArrow[Point_Second].x = middle;
2086 ptArrow[Point_Second].y = rect.GetBottom();
2087 ptArrow[Point_Third].x = rect.GetRight();
2088 ptArrow[Point_Third].y = rect.GetTop();
2089 break;
2090
2091 case wxLEFT:
2092 ptArrow[Point_First].x = rect.GetRight();
2093 ptArrow[Point_First].y = rect.GetTop();
2094 ptArrow[Point_Second].x = rect.GetLeft();
2095 ptArrow[Point_Second].y = middle;
2096 ptArrow[Point_Third].x = rect.GetRight();
2097 ptArrow[Point_Third].y = rect.GetBottom();
2098 break;
2099
2100 case wxRIGHT:
2101 ptArrow[Point_First] = rect.GetPosition();
2102 ptArrow[Point_Second].x = rect.GetRight();
2103 ptArrow[Point_Second].y = middle;
2104 ptArrow[Point_Third].x = rect.GetLeft();
2105 ptArrow[Point_Third].y = rect.GetBottom();
2106 break;
2107
2108 default:
2109 wxFAIL_MSG(_T("unknown arrow direction"));
2110 }
2111
2112 dc.DrawPolygon(WXSIZEOF(ptArrow), ptArrow);
2113
2114 // draw the arrow border
2115 dc.SetPen(penShadow[0]);
2116 switch ( dir )
2117 {
2118 case wxUP:
2119 dc.DrawLine(ptArrow[Point_Second], ptArrow[Point_First]);
2120 dc.DrawPoint(ptArrow[Point_First]);
2121 if ( penShadow[3].Ok() )
2122 {
2123 dc.SetPen(penShadow[3]);
2124 dc.DrawLine(ptArrow[Point_First].x + 1, ptArrow[Point_First].y,
2125 ptArrow[Point_Second].x, ptArrow[Point_Second].y);
2126 }
2127 dc.SetPen(penShadow[1]);
2128 dc.DrawLine(ptArrow[Point_Second].x + 1, ptArrow[Point_Second].y + 1,
2129 ptArrow[Point_Third].x, ptArrow[Point_Third].y);
2130 dc.DrawPoint(ptArrow[Point_Third]);
2131 dc.DrawLine(ptArrow[Point_Third].x - 2, ptArrow[Point_Third].y,
2132 ptArrow[Point_First].x + 1, ptArrow[Point_First].y);
2133 if ( penShadow[2].Ok() )
2134 {
2135 dc.SetPen(penShadow[2]);
2136 dc.DrawLine(ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y,
2137 ptArrow[Point_Second].x, ptArrow[Point_Second].y + 1);
2138 dc.DrawLine(ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y - 1,
2139 ptArrow[Point_First].x + 2, ptArrow[Point_First].y - 1);
2140 }
2141 break;
2142
2143 case wxDOWN:
2144 dc.DrawLine(ptArrow[Point_First], ptArrow[Point_Second]);
2145 dc.DrawLine(ptArrow[Point_First].x + 2, ptArrow[Point_First].y,
2146 ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y);
2147 if ( penShadow[2].Ok() )
2148 {
2149 dc.SetPen(penShadow[2]);
2150 dc.DrawLine(ptArrow[Point_Second].x, ptArrow[Point_Second].y - 1,
2151 ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y - 1);
2152 }
2153 dc.SetPen(penShadow[1]);
2154 dc.DrawLine(ptArrow[Point_Second], ptArrow[Point_Third]);
2155 dc.DrawPoint(ptArrow[Point_Third]);
2156 break;
2157
2158 case wxLEFT:
2159 dc.DrawLine(ptArrow[Point_Second], ptArrow[Point_First]);
2160 dc.DrawPoint(ptArrow[Point_First]);
2161 if ( penShadow[2].Ok() )
2162 {
2163 dc.SetPen(penShadow[2]);
2164 dc.DrawLine(ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y,
2165 ptArrow[Point_First].x - 1, ptArrow[Point_First].y + 2);
2166 dc.DrawLine(ptArrow[Point_Third].x, ptArrow[Point_Third].y,
2167 ptArrow[Point_Second].x + 2, ptArrow[Point_Second].y + 1);
2168 }
2169 dc.SetPen(penShadow[1]);
2170 dc.DrawLine(ptArrow[Point_Third].x, ptArrow[Point_Third].y,
2171 ptArrow[Point_First].x, ptArrow[Point_First].y + 1);
2172 dc.DrawLine(ptArrow[Point_Second].x + 1, ptArrow[Point_Second].y + 1,
2173 ptArrow[Point_Third].x - 1, ptArrow[Point_Third].y);
2174 break;
2175
2176 case wxRIGHT:
2177 dc.DrawLine(ptArrow[Point_First], ptArrow[Point_Third]);
2178 dc.DrawLine(ptArrow[Point_First].x + 2, ptArrow[Point_First].y + 1,
2179 ptArrow[Point_Second].x, ptArrow[Point_Second].y);
2180 dc.SetPen(penShadow[1]);
2181 dc.DrawLine(ptArrow[Point_Second], ptArrow[Point_Third]);
2182 dc.DrawPoint(ptArrow[Point_Third]);
2183 break;
2184
2185 default:
2186 wxFAIL_MSG(_T("unknown arrow direction"));
2187 return;
2188 }
2189 }
2190
2191 void wxGTKRenderer::DrawThumbBorder(wxDC& dc,
2192 wxRect *rect,
2193 wxOrientation orient)
2194 {
2195 if ( orient == wxVERTICAL )
2196 {
2197 DrawAntiShadedRectSide(dc, *rect, m_penDarkGrey, m_penHighlight,
2198 wxLEFT);
2199 DrawAntiShadedRectSide(dc, *rect, m_penDarkGrey, m_penHighlight,
2200 wxRIGHT);
2201 rect->Inflate(-1, 0);
2202
2203 DrawAntiShadedRectSide(dc, *rect, m_penBlack, m_penGrey,
2204 wxLEFT);
2205 DrawAntiShadedRectSide(dc, *rect, m_penBlack, m_penGrey,
2206 wxRIGHT);
2207 rect->Inflate(-1, 0);
2208 }
2209 else
2210 {
2211 DrawAntiShadedRectSide(dc, *rect, m_penDarkGrey, m_penHighlight,
2212 wxUP);
2213 DrawAntiShadedRectSide(dc, *rect, m_penDarkGrey, m_penHighlight,
2214 wxDOWN);
2215 rect->Inflate(0, -1);
2216
2217 DrawAntiShadedRectSide(dc, *rect, m_penBlack, m_penGrey,
2218 wxUP);
2219 DrawAntiShadedRectSide(dc, *rect, m_penBlack, m_penGrey,
2220 wxDOWN);
2221 rect->Inflate(0, -1);
2222 }
2223 }
2224
2225 void wxGTKRenderer::DrawScrollbarThumb(wxDC& dc,
2226 wxOrientation orient,
2227 const wxRect& rect,
2228 int flags)
2229 {
2230 // the thumb is never pressed never has focus border under GTK and the
2231 // scrollbar background never changes at all
2232 int flagsThumb = flags & ~(wxCONTROL_PRESSED | wxCONTROL_FOCUSED);
2233
2234 // we don't want the border in the direction of the scrollbar movement
2235 wxRect rectThumb = rect;
2236 DrawThumbBorder(dc, &rectThumb, orient);
2237
2238 DrawButtonBorder(dc, rectThumb, flagsThumb, &rectThumb);
2239 DrawBackground(dc, wxNullColour, rectThumb, flagsThumb);
2240 }
2241
2242 void wxGTKRenderer::DrawScrollbarShaft(wxDC& dc,
2243 wxOrientation orient,
2244 const wxRect& rect,
2245 int WXUNUSED(flags))
2246 {
2247 wxRect rectBar = rect;
2248 DrawThumbBorder(dc, &rectBar, orient);
2249 DrawSolidRect(dc, wxSCHEME_COLOUR(m_scheme, SCROLLBAR), rectBar);
2250 }
2251
2252 #if wxUSE_SCROLLBAR
2253 wxRect wxGTKRenderer::GetScrollbarRect(const wxScrollBar *scrollbar,
2254 wxScrollBar::Element elem,
2255 int thumbPos) const
2256 {
2257 // as GTK scrollbars can't be disabled, it makes no sense to remove the
2258 // thumb for a scrollbar with range 0 - instead, make it fill the entire
2259 // scrollbar shaft
2260 if ( (elem == wxScrollBar::Element_Thumb) && !scrollbar->GetRange() )
2261 {
2262 elem = wxScrollBar::Element_Bar_2;
2263 }
2264
2265 return wxStdRenderer::GetScrollbarRect(scrollbar, elem, thumbPos);
2266 }
2267
2268 #endif // wxUSE_SCROLLBAR
2269
2270 // ----------------------------------------------------------------------------
2271 // size adjustments
2272 // ----------------------------------------------------------------------------
2273
2274 void wxGTKRenderer::AdjustSize(wxSize *size, const wxWindow *window)
2275 {
2276 #if wxUSE_BMPBUTTON
2277 if ( wxDynamicCast(window, wxBitmapButton) )
2278 {
2279 size->x += 4;
2280 size->y += 4;
2281 } else
2282 #endif // wxUSE_BMPBUTTON
2283 #if wxUSE_BUTTON || wxUSE_TOGGLEBTN
2284 if ( 0
2285 # if wxUSE_BUTTON
2286 || wxDynamicCast(window, wxButton)
2287 # endif // wxUSE_BUTTON
2288 # if wxUSE_TOGGLEBTN
2289 || wxDynamicCast(window, wxToggleButton)
2290 # endif // wxUSE_TOGGLEBTN
2291 )
2292 {
2293 if ( !(window->GetWindowStyle() & wxBU_EXACTFIT) )
2294 {
2295 // TODO: this is ad hoc...
2296 size->x += 3*window->GetCharWidth();
2297 wxCoord minBtnHeight = 18;
2298 if ( size->y < minBtnHeight )
2299 size->y = minBtnHeight;
2300
2301 // button border width
2302 size->y += 4;
2303 }
2304 } else
2305 #endif // wxUSE_BUTTON || wxUSE_TOGGLEBTN
2306 #if wxUSE_SCROLLBAR
2307 if ( wxDynamicCast(window, wxScrollBar) )
2308 {
2309 // we only set the width of vert scrollbars and height of the
2310 // horizontal ones
2311 if ( window->GetWindowStyle() & wxSB_HORIZONTAL )
2312 size->y = m_sizeScrollbarArrow.x;
2313 else
2314 size->x = m_sizeScrollbarArrow.x;
2315 }
2316 else
2317 #endif // wxUSE_SCROLLBAR
2318 {
2319 // take into account the border width
2320 wxStdRenderer::AdjustSize(size, window);
2321 }
2322 }
2323
2324 // ----------------------------------------------------------------------------
2325 // standard icons
2326 // ----------------------------------------------------------------------------
2327
2328 /* Copyright (c) Julian Smart */
2329 static const char *error_xpm[] = {
2330 /* columns rows colors chars-per-pixel */
2331 "48 48 4 1",
2332 " c None",
2333 "X c #242424",
2334 "o c #DCDF00",
2335 ". c #C00000",
2336 /* pixels */
2337 " ",
2338 " ",
2339 " ",
2340 " ",
2341 " ",
2342 " ..... ",
2343 " ............. ",
2344 " ................. ",
2345 " ................... ",
2346 " ....................... ",
2347 " ......................... ",
2348 " ........................... ",
2349 " ...........................X ",
2350 " .............................X ",
2351 " ............................... ",
2352 " ...............................X ",
2353 " .................................X ",
2354 " .................................X ",
2355 " .................................XX ",
2356 " ...ooooooooooooooooooooooooooo...XX ",
2357 " ....ooooooooooooooooooooooooooo....X ",
2358 " ....ooooooooooooooooooooooooooo....X ",
2359 " ....ooooooooooooooooooooooooooo....XX ",
2360 " ....ooooooooooooooooooooooooooo....XX ",
2361 " ....ooooooooooooooooooooooooooo....XX ",
2362 " ...ooooooooooooooooooooooooooo...XXX ",
2363 " ...ooooooooooooooooooooooooooo...XXX ",
2364 " .................................XX ",
2365 " .................................XX ",
2366 " ...............................XXX ",
2367 " ...............................XXX ",
2368 " .............................XXX ",
2369 " ...........................XXXX ",
2370 " ...........................XXX ",
2371 " .........................XXX ",
2372 " .......................XXXX ",
2373 " X...................XXXXX ",
2374 " X.................XXXXX ",
2375 " X.............XXXXX ",
2376 " XXXX.....XXXXXXXX ",
2377 " XXXXXXXXXXXXX ",
2378 " XXXXX ",
2379 " ",
2380 " ",
2381 " ",
2382 " ",
2383 " ",
2384 " "
2385 };
2386
2387 /* Copyright (c) Julian Smart */
2388 static const char *info_xpm[] = {
2389 /* columns rows colors chars-per-pixel */
2390 "48 48 9 1",
2391 "$ c Black",
2392 "O c #FFFFFF",
2393 "@ c #808080",
2394 "+ c #000080",
2395 "o c #E8EB01",
2396 " c None",
2397 "X c #FFFF40",
2398 "# c #C0C0C0",
2399 ". c #ABAD01",
2400 /* pixels */
2401 " ",
2402 " ",
2403 " ",
2404 " ",
2405 " ",
2406 " ",
2407 " ",
2408 " ",
2409 " ",
2410 " ..... ",
2411 " ..XXXXX.. ",
2412 " ..XXXXXXXXo.. ",
2413 " .XXXOXXXXXXXoo. ",
2414 " .XOOXXX+XXXXXo. ",
2415 " .XOOOXX+++XXXXoo. ",
2416 " .XOOXXX+++XXXXXo. ",
2417 " .XOOOXXX+++XXXXXXo. ",
2418 " .XOOXXXX+++XXXXXXo. ",
2419 " .XXXXXXX+++XXXXXXX. ",
2420 " .XXXXXXX+++XXXXXXo. ",
2421 " .XXXXXXX+++XXXXXoo. ",
2422 " .XXXXXX+++XXXXXo. ",
2423 " .XXXXXXX+XXXXXXo. ",
2424 " .XXXXXXXXXXXXo. ",
2425 " .XXXXX+++XXXoo. ",
2426 " .XXXX+++XXoo. ",
2427 " .XXXXXXXXo. ",
2428 " ..XXXXXXo.. ",
2429 " .XXXXXo.. ",
2430 " @#######@ ",
2431 " @@@@@@@@@ ",
2432 " @#######@ ",
2433 " @@@@@@@@@ ",
2434 " @#######@ ",
2435 " @@@@@@@ ",
2436 " ### ",
2437 " $$$ ",
2438 " ",
2439 " ",
2440 " ",
2441 " ",
2442 " ",
2443 " ",
2444 " ",
2445 " ",
2446 " ",
2447 " ",
2448 " "
2449 };
2450
2451 /* Copyright (c) Julian Smart */
2452 static const char *warning_xpm[] = {
2453 /* columns rows colors chars-per-pixel */
2454 "48 48 9 1",
2455 "@ c Black",
2456 "o c #A6A800",
2457 "+ c #8A8C00",
2458 "$ c #B8BA00",
2459 " c None",
2460 "O c #6E7000",
2461 "X c #DCDF00",
2462 ". c #C00000",
2463 "# c #373800",
2464 /* pixels */
2465 " ",
2466 " ",
2467 " ",
2468 " ",
2469 " ",
2470 " ",
2471 " ",
2472 " . ",
2473 " ... ",
2474 " ... ",
2475 " ..... ",
2476 " ...X.. ",
2477 " ..XXX.. ",
2478 " ...XXX... ",
2479 " ..XXXXX.. ",
2480 " ..XXXXXX... ",
2481 " ...XXoO+XX.. ",
2482 " ..XXXO@#XXX.. ",
2483 " ..XXXXO@#XXX... ",
2484 " ...XXXXO@#XXXX.. ",
2485 " ..XXXXXO@#XXXX... ",
2486 " ...XXXXXo@OXXXXX.. ",
2487 " ...XXXXXXo@OXXXXXX.. ",
2488 " ..XXXXXXX$@OXXXXXX... ",
2489 " ...XXXXXXXX@XXXXXXXX.. ",
2490 " ...XXXXXXXXXXXXXXXXXX... ",
2491 " ..XXXXXXXXXXOXXXXXXXXX.. ",
2492 " ...XXXXXXXXXO@#XXXXXXXXX.. ",
2493 " ..XXXXXXXXXXX#XXXXXXXXXX... ",
2494 " ...XXXXXXXXXXXXXXXXXXXXXXX.. ",
2495 " ...XXXXXXXXXXXXXXXXXXXXXXXX... ",
2496 " .............................. ",
2497 " .............................. ",
2498 " ",
2499 " ",
2500 " ",
2501 " ",
2502 " ",
2503 " ",
2504 " ",
2505 " ",
2506 " ",
2507 " ",
2508 " ",
2509 " ",
2510 " ",
2511 " ",
2512 " "
2513 };
2514
2515 /* Copyright (c) Julian Smart */
2516 static const char *question_xpm[] = {
2517 /* columns rows colors chars-per-pixel */
2518 "48 48 21 1",
2519 ". c Black",
2520 "> c #696969",
2521 "O c #1F1F00",
2522 "+ c #181818",
2523 "o c #F6F900",
2524 "; c #3F3F00",
2525 "$ c #111111",
2526 " c None",
2527 "& c #202020",
2528 "X c #AAAA00",
2529 "@ c #949400",
2530 ": c #303030",
2531 "1 c #383838",
2532 "% c #2A2A00",
2533 ", c #404040",
2534 "= c #B4B400",
2535 "- c #484848",
2536 "# c #151500",
2537 "< c #9F9F00",
2538 "2 c #6A6A00",
2539 "* c #353500",
2540 /* pixels */
2541 " ",
2542 " ",
2543 " ",
2544 " ",
2545 " ......... ",
2546 " ...XXXXXXX.. ",
2547 " ..XXXXoooooXXXO+ ",
2548 " ..XXooooooooooooX@.. ",
2549 " ..XoooooooooooooooXX#. ",
2550 " $%XoooooooooooooooooXX#. ",
2551 " &.XoooooooXXXXXXooooooXX.. ",
2552 " .XooooooXX.$...$XXoooooX*. ",
2553 " $.XoooooX%.$ .*oooooo=.. ",
2554 " .XooooooX.. -.XoooooX.. ",
2555 " .XoooooX..+ .XoooooX;. ",
2556 " ...XXXX..: .XoooooX;. ",
2557 " ........ >.XoooooX;. ",
2558 " +.XoooooX.. ",
2559 " ,.Xoooooo<.. ",
2560 " 1#XooooooXO.. ",
2561 " &#XooooooX2.. ",
2562 " $%XooooooXX.. ",
2563 " $%XooooooXX.. ",
2564 " $%XooooooXX.. ",
2565 " &.XooooooXX.. ",
2566 " .XooooooXX.. ",
2567 " &.XoooooXX.. ",
2568 " ..XooooXX.. ",
2569 " ..XooooX... ",
2570 " ..XXooXX..& ",
2571 " ...XXXXX.. ",
2572 " ........ ",
2573 " ",
2574 " ",
2575 " ....... ",
2576 " ..XXXXX.. ",
2577 " ..XXoooXX.. ",
2578 " ..XoooooX.. ",
2579 " ..XoooooX.. ",
2580 " ..XXoooXX.. ",
2581 " ..XXXXX.. ",
2582 " ....... ",
2583 " ",
2584 " ",
2585 " ",
2586 " ",
2587 " ",
2588 " "
2589 };
2590
2591 wxBitmap wxGTKArtProvider::CreateBitmap(const wxArtID& id,
2592 const wxArtClient& WXUNUSED(client),
2593 const wxSize& WXUNUSED(size))
2594 {
2595 if ( id == wxART_INFORMATION )
2596 return wxBitmap(info_xpm);
2597 if ( id == wxART_ERROR )
2598 return wxBitmap(error_xpm);
2599 if ( id == wxART_WARNING )
2600 return wxBitmap(warning_xpm);
2601 if ( id == wxART_QUESTION )
2602 return wxBitmap(question_xpm);
2603 return wxNullBitmap;
2604 }
2605
2606
2607 // ============================================================================
2608 // wxInputHandler
2609 // ============================================================================
2610
2611 // ----------------------------------------------------------------------------
2612 // wxGTKInputHandler
2613 // ----------------------------------------------------------------------------
2614
2615 bool wxGTKInputHandler::HandleKey(wxInputConsumer * WXUNUSED(control),
2616 const wxKeyEvent& WXUNUSED(event),
2617 bool WXUNUSED(pressed))
2618 {
2619 return false;
2620 }
2621
2622 bool wxGTKInputHandler::HandleMouse(wxInputConsumer *control,
2623 const wxMouseEvent& event)
2624 {
2625 // clicking on the control gives it focus
2626 if ( event.ButtonDown() && wxWindow::FindFocus() != control->GetInputWindow() )
2627 {
2628 control->GetInputWindow()->SetFocus();
2629
2630 return true;
2631 }
2632
2633 return false;
2634 }
2635
2636 bool wxGTKInputHandler::HandleMouseMove(wxInputConsumer *control,
2637 const wxMouseEvent& event)
2638 {
2639 if ( event.Entering() )
2640 {
2641 control->GetInputWindow()->SetCurrent(true);
2642 }
2643 else if ( event.Leaving() )
2644 {
2645 control->GetInputWindow()->SetCurrent(false);
2646 }
2647 else
2648 {
2649 return false;
2650 }
2651
2652 return true;
2653 }
2654
2655 #if wxUSE_CHECKBOX
2656
2657 // ----------------------------------------------------------------------------
2658 // wxGTKCheckboxInputHandler
2659 // ----------------------------------------------------------------------------
2660
2661 bool wxGTKCheckboxInputHandler::HandleKey(wxInputConsumer *control,
2662 const wxKeyEvent& event,
2663 bool pressed)
2664 {
2665 if ( pressed )
2666 {
2667 int keycode = event.GetKeyCode();
2668 if ( keycode == WXK_SPACE || keycode == WXK_RETURN )
2669 {
2670 control->PerformAction(wxACTION_CHECKBOX_TOGGLE);
2671
2672 return true;
2673 }
2674 }
2675
2676 return false;
2677 }
2678
2679 #endif // wxUSE_CHECKBOX
2680
2681 #if wxUSE_TEXTCTRL
2682
2683 // ----------------------------------------------------------------------------
2684 // wxGTKTextCtrlInputHandler
2685 // ----------------------------------------------------------------------------
2686
2687 bool wxGTKTextCtrlInputHandler::HandleKey(wxInputConsumer *control,
2688 const wxKeyEvent& event,
2689 bool pressed)
2690 {
2691 // handle only GTK-specific text bindings here, the others are handled in
2692 // the base class
2693 if ( pressed )
2694 {
2695 wxControlAction action;
2696 int keycode = event.GetKeyCode();
2697 if ( event.ControlDown() )
2698 {
2699 switch ( keycode )
2700 {
2701 case 'A':
2702 action = wxACTION_TEXT_HOME;
2703 break;
2704
2705 case 'B':
2706 action = wxACTION_TEXT_LEFT;
2707 break;
2708
2709 case 'D':
2710 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_RIGHT;
2711 break;
2712
2713 case 'E':
2714 action = wxACTION_TEXT_END;
2715 break;
2716
2717 case 'F':
2718 action = wxACTION_TEXT_RIGHT;
2719 break;
2720
2721 case 'H':
2722 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_LEFT;
2723 break;
2724
2725 case 'K':
2726 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_END;
2727 break;
2728
2729 case 'N':
2730 action = wxACTION_TEXT_DOWN;
2731 break;
2732
2733 case 'P':
2734 action = wxACTION_TEXT_UP;
2735 break;
2736
2737 case 'U':
2738 //delete the entire line
2739 control->PerformAction(wxACTION_TEXT_HOME);
2740 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_END;
2741 break;
2742
2743 case 'W':
2744 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_WORD_LEFT;
2745 break;
2746 }
2747 }
2748 else if ( event.AltDown() )
2749 {
2750 switch ( keycode )
2751 {
2752 case 'B':
2753 action = wxACTION_TEXT_WORD_LEFT;
2754 break;
2755
2756 case 'D':
2757 action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_WORD_RIGHT;
2758 break;
2759
2760 case 'F':
2761 action = wxACTION_TEXT_WORD_RIGHT;
2762 break;
2763 }
2764 }
2765
2766 if ( action != wxACTION_NONE )
2767 {
2768 control->PerformAction(action);
2769
2770 return true;
2771 }
2772 }
2773
2774 return wxStdInputHandler::HandleKey(control, event, pressed);
2775 }
2776
2777 #endif // wxUSE_TEXTCTRL
2778
2779 #endif // wxUSE_THEME_GTK