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