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