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