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