1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: univ/themes/gtk.cpp
3 // Purpose: wxUniversal theme implementing GTK-like LNF
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
9 // Licence: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
12 // ===========================================================================
14 // ===========================================================================
16 // ---------------------------------------------------------------------------
18 // ---------------------------------------------------------------------------
20 // for compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
30 #include "wx/dcmemory.h"
31 #include "wx/window.h"
33 #include "wx/button.h"
34 #include "wx/checkbox.h"
35 #include "wx/listbox.h"
36 #include "wx/checklst.h"
37 #include "wx/combobox.h"
38 #include "wx/scrolbar.h"
39 #include "wx/slider.h"
40 #include "wx/textctrl.h"
43 #include "wx/notebook.h"
44 #include "wx/spinbutt.h"
46 #include "wx/univ/renderer.h"
47 #include "wx/univ/inphand.h"
48 #include "wx/univ/colschem.h"
49 #include "wx/univ/theme.h"
51 // ----------------------------------------------------------------------------
52 // constants (to be removed, for testing only)
53 // ----------------------------------------------------------------------------
55 static const size_t BORDER_THICKNESS
= 1;
57 // ----------------------------------------------------------------------------
58 // wxGTKRenderer: draw the GUI elements in GTK style
59 // ----------------------------------------------------------------------------
61 class wxGTKRenderer
: public wxRenderer
64 wxGTKRenderer(const wxColourScheme
*scheme
);
66 // implement the base class pure virtuals
67 virtual void DrawBackground(wxDC
& dc
,
71 virtual void DrawLabel(wxDC
& dc
,
72 const wxString
& label
,
75 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
77 wxRect
*rectBounds
= NULL
);
78 virtual void DrawButtonLabel(wxDC
& dc
,
79 const wxString
& label
,
80 const wxBitmap
& image
,
83 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
85 wxRect
*rectBounds
= NULL
);
86 virtual void DrawBorder(wxDC
& dc
,
90 wxRect
*rectIn
= (wxRect
*)NULL
);
91 virtual void DrawHorizontalLine(wxDC
& dc
,
92 wxCoord y
, wxCoord x1
, wxCoord x2
);
93 virtual void DrawVerticalLine(wxDC
& dc
,
94 wxCoord x
, wxCoord y1
, wxCoord y2
);
95 virtual void DrawFrame(wxDC
& dc
,
96 const wxString
& label
,
99 int alignment
= wxALIGN_LEFT
,
100 int indexAccel
= -1);
101 virtual void DrawTextBorder(wxDC
& dc
,
105 wxRect
*rectIn
= (wxRect
*)NULL
);
106 virtual void DrawButtonBorder(wxDC
& dc
,
109 wxRect
*rectIn
= (wxRect
*)NULL
);
110 virtual void DrawArrow(wxDC
& dc
,
114 virtual void DrawScrollbarArrow(wxDC
& dc
,
118 virtual void DrawScrollbarThumb(wxDC
& dc
,
119 wxOrientation orient
,
122 virtual void DrawScrollbarShaft(wxDC
& dc
,
123 wxOrientation orient
,
126 virtual void DrawScrollCorner(wxDC
& dc
,
128 virtual void DrawItem(wxDC
& dc
,
129 const wxString
& label
,
132 virtual void DrawCheckItem(wxDC
& dc
,
133 const wxString
& label
,
134 const wxBitmap
& bitmap
,
137 virtual void DrawCheckButton(wxDC
& dc
,
138 const wxString
& label
,
139 const wxBitmap
& bitmap
,
142 wxAlignment align
= wxALIGN_LEFT
,
143 int indexAccel
= -1);
145 virtual void DrawRadioButton(wxDC
& dc
,
146 const wxString
& label
,
147 const wxBitmap
& bitmap
,
150 wxAlignment align
= wxALIGN_LEFT
,
151 int indexAccel
= -1);
153 virtual void DrawTextLine(wxDC
& dc
,
154 const wxString
& text
,
159 virtual void DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
);
160 virtual void DrawTab(wxDC
& dc
,
163 const wxString
& label
,
164 const wxBitmap
& bitmap
= wxNullBitmap
,
166 int indexAccel
= -1);
168 virtual void DrawSliderShaft(wxDC
& dc
,
170 wxOrientation orient
,
172 wxRect
*rectShaft
= NULL
);
173 virtual void DrawSliderThumb(wxDC
& dc
,
175 wxOrientation orient
,
177 virtual void DrawSliderTicks(wxDC
& dc
,
179 const wxSize
& sizeThumb
,
180 wxOrientation orient
,
186 // we don't have the ticks in GTK version
189 virtual void DrawMenuBarItem(wxDC
& dc
,
191 const wxString
& label
,
193 int indexAccel
= -1);
194 virtual void DrawMenuItem(wxDC
& dc
,
196 const wxMenuGeometryInfo
& geometryInfo
,
197 const wxString
& label
,
198 const wxString
& accel
,
199 const wxBitmap
& bitmap
= wxNullBitmap
,
201 int indexAccel
= -1);
202 virtual void DrawMenuSeparator(wxDC
& dc
,
204 const wxMenuGeometryInfo
& geomInfo
);
206 virtual void GetComboBitmaps(wxBitmap
*bmpNormal
,
207 wxBitmap
*bmpPressed
,
208 wxBitmap
*bmpDisabled
);
210 virtual void AdjustSize(wxSize
*size
, const wxWindow
*window
);
211 virtual wxRect
GetBorderDimensions(wxBorder border
) const;
212 virtual bool AreScrollbarsInsideBorder() const;
214 // geometry and hit testing
215 virtual wxSize
GetScrollbarArrowSize() const
216 { return m_sizeScrollbarArrow
; }
217 virtual wxRect
GetScrollbarRect(const wxScrollBar
*scrollbar
,
218 wxScrollBar::Element elem
,
219 int thumbPos
= -1) const;
220 virtual wxCoord
GetScrollbarSize(const wxScrollBar
*scrollbar
);
221 virtual wxHitTest
HitTestScrollbar(const wxScrollBar
*scrollbar
,
222 const wxPoint
& pt
) const;
223 virtual wxCoord
ScrollbarToPixel(const wxScrollBar
*scrollbar
,
225 virtual int PixelToScrollbar(const wxScrollBar
*scrollbar
, wxCoord coord
);
226 virtual wxCoord
GetListboxItemHeight(wxCoord fontHeight
)
227 { return fontHeight
+ 2; }
228 virtual wxSize
GetCheckBitmapSize() const
229 { return wxSize(10, 10); }
230 virtual wxSize
GetRadioBitmapSize() const
231 { return wxSize(11, 11); }
232 virtual wxCoord
GetCheckItemMargin() const
235 virtual wxRect
GetTextTotalArea(const wxTextCtrl
*text
,
237 virtual wxRect
GetTextClientArea(const wxTextCtrl
*text
,
239 wxCoord
*extraSpaceBeyond
);
241 virtual wxSize
GetTabIndent() const { return wxSize(2, 2); }
242 virtual wxSize
GetTabPadding() const { return wxSize(6, 6); }
244 virtual wxCoord
GetSliderDim() const { return 15; }
245 virtual wxCoord
GetSliderTickLen() const { return 0; }
246 virtual wxRect
GetSliderShaftRect(const wxRect
& rect
,
247 wxOrientation orient
) const;
248 virtual wxSize
GetSliderThumbSize(const wxRect
& rect
,
249 wxOrientation orient
) const;
250 virtual wxSize
GetProgressBarStep() const { return wxSize(16, 32); }
252 virtual wxSize
GetMenuBarItemSize(const wxSize
& sizeText
) const;
253 virtual wxMenuGeometryInfo
*GetMenuGeometry(wxWindow
*win
,
254 const wxMenu
& menu
) const;
256 // helpers for "wxBitmap wxColourScheme::Get()"
257 void DrawCheckBitmap(wxDC
& dc
, const wxRect
& rect
);
258 void DrawUncheckBitmap(wxDC
& dc
, const wxRect
& rect
, bool isPressed
);
261 // DrawBackground() helpers
263 // get the colour to use for background
264 wxColour
GetBackgroundColour(int flags
) const
266 if ( flags
& wxCONTROL_PRESSED
)
267 return wxSCHEME_COLOUR(m_scheme
, CONTROL_PRESSED
);
268 else if ( flags
& wxCONTROL_CURRENT
)
269 return wxSCHEME_COLOUR(m_scheme
, CONTROL_CURRENT
);
271 return wxSCHEME_COLOUR(m_scheme
, CONTROL
);
274 // draw the background with any colour, not only the default one(s)
275 void DoDrawBackground(wxDC
& dc
,
279 // DrawBorder() helpers: all of them shift and clip the DC after drawing
282 // just draw a rectangle with the given pen
283 void DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
285 // draw the lower left part of rectangle
286 void DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
288 // draw the rectange using the first brush for the left and top sides and
289 // the second one for the bottom and right ones
290 void DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
291 const wxPen
& pen1
, const wxPen
& pen2
);
293 // as DrawShadedRect() but the pixels in the bottom left and upper right
294 // border are drawn with the pen1, not pen2
295 void DrawAntiShadedRect(wxDC
& dc
, wxRect
*rect
,
296 const wxPen
& pen1
, const wxPen
& pen2
);
298 // used for drawing opened rectangles - draws only one side of it at once
299 // (and doesn't adjust the rect)
300 void DrawAntiShadedRectSide(wxDC
& dc
,
306 // draw an opened rect for the arrow in given direction
307 void DrawArrowBorder(wxDC
& dc
,
311 // draw two sides of the rectangle
312 void DrawThumbBorder(wxDC
& dc
,
314 wxOrientation orient
);
316 // draw the normal 3D border
317 void DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
);
319 // just as DrawRaisedBorder() except that the bottom left and up right
320 // pixels of the interior rect are drawn in another colour (i.e. the inner
321 // rect is drawn with DrawAntiShadedRect() and not DrawShadedRect())
322 void DrawAntiRaisedBorder(wxDC
& dc
, wxRect
*rect
);
324 // returns the size of the arrow for the scrollbar (depends on
326 wxSize
GetScrollbarArrowSize(const wxScrollBar
*scrollbar
) const
329 if ( scrollbar
->IsVertical() )
331 size
= m_sizeScrollbarArrow
;
335 size
.x
= m_sizeScrollbarArrow
.y
;
336 size
.y
= m_sizeScrollbarArrow
.x
;
342 // get the line wrap indicator bitmap
343 wxBitmap
GetLineWrapBitmap();
345 // DrawCheckBitmap and DrawRadioBitmap helpers
347 // draw the check bitmaps once and cache them for later use
348 wxBitmap
GetCheckBitmap(int flags
);
350 // draw a /\ or \/ line from (x1, y1) to (x2, y1) passing by the point
352 void DrawUpZag(wxDC
& dc
,
353 wxCoord x1
, wxCoord x2
,
354 wxCoord y1
, wxCoord y2
);
355 void DrawDownZag(wxDC
& dc
,
356 wxCoord x1
, wxCoord x2
,
357 wxCoord y1
, wxCoord y2
);
359 // draw the radio button bitmap for the given state
360 void DrawRadioBitmap(wxDC
& dc
, const wxRect
& rect
, int flags
);
362 // draw check/radio - the bitmap must be a valid one by now
363 void DoDrawCheckOrRadioBitmap(wxDC
& dc
,
364 const wxString
& label
,
365 const wxBitmap
& bitmap
,
366 const wxRect
& rectTotal
,
372 const wxColourScheme
*m_scheme
;
375 wxSize m_sizeScrollbarArrow
;
384 // the checkbox bitmaps: first row is for the normal, second for the
385 // pressed state and the columns are for checked and unchecked status
387 wxBitmap m_bitmapsCheckbox
[2][2];
389 // the line wrap bitmap (drawn at the end of wrapped lines)
390 wxBitmap m_bmpLineWrap
;
393 // ----------------------------------------------------------------------------
394 // wxGTKInputHandler and derived classes: process the keyboard and mouse
395 // messages according to GTK standards
396 // ----------------------------------------------------------------------------
398 class wxGTKInputHandler
: public wxInputHandler
401 wxGTKInputHandler(wxGTKRenderer
*renderer
);
403 virtual bool HandleKey(wxControl
*control
,
404 const wxKeyEvent
& event
,
406 virtual bool HandleMouse(wxControl
*control
,
407 const wxMouseEvent
& event
);
408 virtual bool HandleMouseMove(wxControl
*control
, const wxMouseEvent
& event
);
411 wxGTKRenderer
*m_renderer
;
414 class wxGTKScrollBarInputHandler
: public wxStdScrollBarInputHandler
417 wxGTKScrollBarInputHandler(wxRenderer
*renderer
, wxInputHandler
*handler
)
418 : wxStdScrollBarInputHandler(renderer
, handler
) { }
421 virtual void Highlight(wxScrollBar
*scrollbar
, bool doIt
)
423 // only arrows and the thumb can be highlighted
424 if ( !IsArrow() && m_htLast
!= wxHT_SCROLLBAR_THUMB
)
427 wxStdScrollBarInputHandler::Highlight(scrollbar
, doIt
);
430 virtual void Press(wxScrollBar
*scrollbar
, bool doIt
)
432 // only arrows can be pressed
436 wxStdScrollBarInputHandler::Press(scrollbar
, doIt
);
439 virtual bool IsAllowedButton(int WXUNUSED(button
)) { return TRUE
; }
443 return m_htLast
== wxHT_SCROLLBAR_ARROW_LINE_1
||
444 m_htLast
== wxHT_SCROLLBAR_ARROW_LINE_2
;
448 class wxGTKCheckboxInputHandler
: public wxStdCheckboxInputHandler
451 wxGTKCheckboxInputHandler(wxInputHandler
*handler
)
452 : wxStdCheckboxInputHandler(handler
) { }
454 virtual bool HandleKey(wxControl
*control
,
455 const wxKeyEvent
& event
,
459 class wxGTKTextCtrlInputHandler
: public wxStdTextCtrlInputHandler
462 wxGTKTextCtrlInputHandler(wxInputHandler
*handler
)
463 : wxStdTextCtrlInputHandler(handler
) { }
465 virtual bool HandleKey(wxControl
*control
,
466 const wxKeyEvent
& event
,
470 // ----------------------------------------------------------------------------
471 // wxGTKColourScheme: uses the standard GTK colours
472 // ----------------------------------------------------------------------------
474 class wxGTKColourScheme
: public wxColourScheme
477 virtual wxColour
Get(StdColour col
) const;
478 virtual wxColour
GetBackground(wxWindow
*win
) const;
481 // ----------------------------------------------------------------------------
483 // ----------------------------------------------------------------------------
485 WX_DEFINE_ARRAY(wxInputHandler
*, wxArrayHandlers
);
487 class wxGTKTheme
: public wxTheme
491 virtual ~wxGTKTheme();
493 virtual wxRenderer
*GetRenderer() { return m_renderer
; }
494 virtual wxInputHandler
*GetInputHandler(const wxString
& control
);
495 virtual wxColourScheme
*GetColourScheme() { return m_scheme
; }
498 // get the default input handler
499 wxInputHandler
*GetDefaultInputHandler();
501 wxGTKRenderer
*m_renderer
;
503 // the names of the already created handlers and the handlers themselves
504 // (these arrays are synchronized)
505 wxSortedArrayString m_handlerNames
;
506 wxArrayHandlers m_handlers
;
508 wxGTKInputHandler
*m_handlerDefault
;
510 wxGTKColourScheme
*m_scheme
;
512 WX_DECLARE_THEME(gtk
)
515 // ============================================================================
517 // ============================================================================
519 WX_IMPLEMENT_THEME(wxGTKTheme
, gtk
, wxTRANSLATE("GTK+ theme"));
521 // ----------------------------------------------------------------------------
523 // ----------------------------------------------------------------------------
525 wxGTKTheme::wxGTKTheme()
527 m_scheme
= new wxGTKColourScheme
;
528 m_renderer
= new wxGTKRenderer(m_scheme
);
529 m_handlerDefault
= NULL
;
532 wxGTKTheme::~wxGTKTheme()
534 size_t count
= m_handlers
.GetCount();
535 for ( size_t n
= 0; n
< count
; n
++ )
537 if ( m_handlers
[n
] != m_handlerDefault
)
538 delete m_handlers
[n
];
541 delete m_handlerDefault
;
546 wxInputHandler
*wxGTKTheme::GetDefaultInputHandler()
548 if ( !m_handlerDefault
)
550 m_handlerDefault
= new wxGTKInputHandler(m_renderer
);
553 return m_handlerDefault
;
556 wxInputHandler
*wxGTKTheme::GetInputHandler(const wxString
& control
)
558 wxInputHandler
*handler
;
559 int n
= m_handlerNames
.Index(control
);
560 if ( n
== wxNOT_FOUND
)
562 // create a new handler
563 if ( control
== wxINP_HANDLER_SCROLLBAR
)
564 handler
= new wxGTKScrollBarInputHandler(m_renderer
,
565 GetDefaultInputHandler());
567 else if ( control
== wxINP_HANDLER_BUTTON
)
568 handler
= new wxStdButtonInputHandler(GetDefaultInputHandler());
569 #endif // wxUSE_CHECKBOX
571 else if ( control
== wxINP_HANDLER_CHECKBOX
)
572 handler
= new wxGTKCheckboxInputHandler(GetDefaultInputHandler());
573 #endif // wxUSE_CHECKBOX
575 else if ( control
== wxINP_HANDLER_COMBOBOX
)
576 handler
= new wxStdComboBoxInputHandler(GetDefaultInputHandler());
577 #endif // wxUSE_COMBOBOX
579 else if ( control
== wxINP_HANDLER_LISTBOX
)
580 handler
= new wxStdListboxInputHandler(GetDefaultInputHandler());
581 #endif // wxUSE_LISTBOX
582 #if wxUSE_CHECKLISTBOX
583 else if ( control
== wxINP_HANDLER_CHECKLISTBOX
)
584 handler
= new wxStdCheckListboxInputHandler(GetDefaultInputHandler());
585 #endif // wxUSE_CHECKLISTBOX
587 else if ( control
== wxINP_HANDLER_TEXTCTRL
)
588 handler
= new wxGTKTextCtrlInputHandler(GetDefaultInputHandler());
589 #endif // wxUSE_TEXTCTRL
591 else if ( control
== wxINP_HANDLER_SLIDER
)
592 handler
= new wxStdSliderButtonInputHandler(GetDefaultInputHandler());
593 #endif // wxUSE_SLIDER
595 else if ( control
== wxINP_HANDLER_SPINBTN
)
596 handler
= new wxStdSpinButtonInputHandler(GetDefaultInputHandler());
597 #endif // wxUSE_SPINBTN
599 else if ( control
== wxINP_HANDLER_NOTEBOOK
)
600 handler
= new wxStdNotebookInputHandler(GetDefaultInputHandler());
601 #endif // wxUSE_NOTEBOOK
603 handler
= GetDefaultInputHandler();
605 n
= m_handlerNames
.Add(control
);
606 m_handlers
.Insert(handler
, n
);
608 else // we already have it
610 handler
= m_handlers
[n
];
616 // ============================================================================
618 // ============================================================================
620 wxColour
wxGTKColourScheme::GetBackground(wxWindow
*win
) const
623 if ( win
->UseBgCol() )
625 // use the user specified colour
626 col
= win
->GetBackgroundColour();
629 if ( win
->IsContainerWindow() )
631 // doesn't depend on the state
639 int flags
= win
->GetStateFlags();
641 // the colour set by the user should be used for the normal state
642 // and for the states for which we don't have any specific colours
643 if ( !col
.Ok() || (flags
!= 0) )
645 if ( wxDynamicCast(win
, wxScrollBar
) )
646 col
= Get(SCROLLBAR
);
647 else if ( (flags
& wxCONTROL_CURRENT
) && win
->CanBeHighlighted() )
648 col
= Get(CONTROL_CURRENT
);
649 else if ( flags
& wxCONTROL_PRESSED
)
650 col
= Get(CONTROL_PRESSED
);
659 wxColour
wxGTKColourScheme::Get(wxGTKColourScheme::StdColour col
) const
663 case WINDOW
: return *wxWHITE
;
665 case SHADOW_DARK
: return *wxBLACK
;
666 case SHADOW_HIGHLIGHT
: return *wxWHITE
;
667 case SHADOW_IN
: return wxColour(0xd6d6d6);
668 case SHADOW_OUT
: return wxColour(0x969696);
670 case CONTROL
: return wxColour(0xd6d6d6);
671 case CONTROL_PRESSED
: return wxColour(0xc3c3c3);
672 case CONTROL_CURRENT
: return wxColour(0xeaeaea);
674 case CONTROL_TEXT
: return *wxBLACK
;
675 case CONTROL_TEXT_DISABLED
:
676 return wxColour(0x757575);
677 case CONTROL_TEXT_DISABLED_SHADOW
:
681 case SCROLLBAR_PRESSED
: return wxColour(0xc3c3c3);
683 case HIGHLIGHT
: return wxColour(0x9c0000);
684 case HIGHLIGHT_TEXT
: return wxColour(0xffffff);
688 wxFAIL_MSG(_T("invalid standard colour"));
693 // ============================================================================
695 // ============================================================================
697 // ----------------------------------------------------------------------------
699 // ----------------------------------------------------------------------------
701 wxGTKRenderer::wxGTKRenderer(const wxColourScheme
*scheme
)
705 m_sizeScrollbarArrow
= wxSize(15, 14);
708 m_penBlack
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_DARK
), 0, wxSOLID
);
709 m_penDarkGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_OUT
), 0, wxSOLID
);
710 m_penGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SCROLLBAR
), 0, wxSOLID
);
711 m_penLightGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_IN
), 0, wxSOLID
);
712 m_penHighlight
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_HIGHLIGHT
), 0, wxSOLID
);
715 // ----------------------------------------------------------------------------
717 // ----------------------------------------------------------------------------
719 void wxGTKRenderer::DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
723 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
724 dc
.DrawRectangle(*rect
);
730 void wxGTKRenderer::DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
732 // draw the bottom and right sides
734 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
735 rect
->GetRight() + 1, rect
->GetBottom());
736 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
737 rect
->GetRight(), rect
->GetBottom());
744 void wxGTKRenderer::DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
745 const wxPen
& pen1
, const wxPen
& pen2
)
747 // draw the rectangle
749 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
750 rect
->GetLeft(), rect
->GetBottom());
751 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
752 rect
->GetRight(), rect
->GetTop());
754 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
755 rect
->GetRight(), rect
->GetBottom());
756 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
757 rect
->GetRight() + 1, rect
->GetBottom());
763 void wxGTKRenderer::DrawAntiShadedRectSide(wxDC
& dc
,
769 dc
.SetPen(dir
== wxLEFT
|| dir
== wxUP
? pen1
: pen2
);
774 dc
.DrawLine(rect
.GetLeft(), rect
.GetTop(),
775 rect
.GetLeft(), rect
.GetBottom() + 1);
779 dc
.DrawLine(rect
.GetLeft(), rect
.GetTop(),
780 rect
.GetRight() + 1, rect
.GetTop());
784 dc
.DrawLine(rect
.GetRight(), rect
.GetTop(),
785 rect
.GetRight(), rect
.GetBottom() + 1);
789 dc
.DrawLine(rect
.GetLeft(), rect
.GetBottom(),
790 rect
.GetRight() + 1, rect
.GetBottom());
794 wxFAIL_MSG(_T("unknown rectangle side"));
798 void wxGTKRenderer::DrawAntiShadedRect(wxDC
& dc
, wxRect
*rect
,
799 const wxPen
& pen1
, const wxPen
& pen2
)
801 // draw the rectangle
803 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
804 rect
->GetLeft(), rect
->GetBottom() + 1);
805 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
806 rect
->GetRight() + 1, rect
->GetTop());
808 dc
.DrawLine(rect
->GetRight(), rect
->GetTop() + 1,
809 rect
->GetRight(), rect
->GetBottom());
810 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetBottom(),
811 rect
->GetRight() + 1, rect
->GetBottom());
817 void wxGTKRenderer::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
819 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
820 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
823 void wxGTKRenderer::DrawAntiRaisedBorder(wxDC
& dc
, wxRect
*rect
)
825 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
826 DrawAntiShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
829 void wxGTKRenderer::DrawBorder(wxDC
& dc
,
831 const wxRect
& rectTotal
,
837 wxRect rect
= rectTotal
;
841 case wxBORDER_SUNKEN
:
842 for ( width
= 0; width
< BORDER_THICKNESS
; width
++ )
844 DrawAntiShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
845 DrawShadedRect(dc
, &rect
, m_penBlack
, m_penLightGrey
);
849 case wxBORDER_STATIC
:
850 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
853 case wxBORDER_RAISED
:
854 for ( width
= 0; width
< BORDER_THICKNESS
; width
++ )
856 DrawRaisedBorder(dc
, &rect
);
860 case wxBORDER_DOUBLE
:
861 DrawShadedRect(dc
, &rect
, m_penLightGrey
, m_penBlack
);
862 DrawShadedRect(dc
, &rect
, m_penHighlight
, m_penDarkGrey
);
863 DrawRect(dc
, &rect
, m_penLightGrey
);
866 case wxBORDER_SIMPLE
:
867 DrawRect(dc
, &rect
, m_penBlack
);
871 wxFAIL_MSG(_T("unknown border type"));
874 case wxBORDER_DEFAULT
:
883 wxRect
wxGTKRenderer::GetBorderDimensions(wxBorder border
) const
888 case wxBORDER_RAISED
:
889 case wxBORDER_SUNKEN
:
890 width
= 2*BORDER_THICKNESS
;
893 case wxBORDER_SIMPLE
:
894 case wxBORDER_STATIC
:
898 case wxBORDER_DOUBLE
:
903 wxFAIL_MSG(_T("unknown border type"));
906 case wxBORDER_DEFAULT
:
921 bool wxGTKRenderer::AreScrollbarsInsideBorder() const
923 // no, the scrollbars are outside the border in GTK+
927 // ----------------------------------------------------------------------------
929 // ----------------------------------------------------------------------------
931 void wxGTKRenderer::DrawTextBorder(wxDC
& dc
,
933 const wxRect
& rectOrig
,
937 wxRect rect
= rectOrig
;
939 if ( flags
& wxCONTROL_FOCUSED
)
941 DrawRect(dc
, &rect
, m_penBlack
);
942 DrawAntiShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
946 DrawAntiShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
947 DrawAntiShadedRect(dc
, &rect
, m_penBlack
, m_penHighlight
);
954 void wxGTKRenderer::DrawButtonBorder(wxDC
& dc
,
955 const wxRect
& rectTotal
,
959 wxRect rect
= rectTotal
;
961 if ( flags
& wxCONTROL_PRESSED
)
963 // button pressed: draw a black border around it and an inward shade
964 DrawRect(dc
, &rect
, m_penBlack
);
965 DrawAntiShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
966 DrawAntiShadedRect(dc
, &rect
, m_penBlack
, m_penDarkGrey
);
970 // button not pressed
972 if ( flags
& wxCONTROL_ISDEFAULT
)
977 if ( flags
& wxCONTROL_FOCUSED
)
979 // button is currently default: add an extra border around it
980 DrawRect(dc
, &rect
, m_penBlack
);
983 // now draw a normal button
984 DrawShadedRect(dc
, &rect
, m_penHighlight
, m_penBlack
);
985 DrawAntiShadedRect(dc
, &rect
,
986 wxPen(GetBackgroundColour(flags
), 0, wxSOLID
),
996 // ----------------------------------------------------------------------------
998 // ----------------------------------------------------------------------------
1000 void wxGTKRenderer::DrawHorizontalLine(wxDC
& dc
,
1001 wxCoord y
, wxCoord x1
, wxCoord x2
)
1003 dc
.SetPen(m_penDarkGrey
);
1004 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1005 dc
.SetPen(m_penHighlight
);
1007 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1010 void wxGTKRenderer::DrawVerticalLine(wxDC
& dc
,
1011 wxCoord x
, wxCoord y1
, wxCoord y2
)
1013 dc
.SetPen(m_penDarkGrey
);
1014 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1015 dc
.SetPen(m_penHighlight
);
1017 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1020 void wxGTKRenderer::DrawFrame(wxDC
& dc
,
1021 const wxString
& label
,
1027 wxCoord height
= 0; // of the label
1028 wxRect rectFrame
= rect
;
1029 if ( !label
.empty() )
1031 // the text should touch the top border of the rect, so the frame
1032 // itself should be lower
1033 dc
.GetTextExtent(label
, NULL
, &height
);
1034 rectFrame
.y
+= height
/ 2;
1035 rectFrame
.height
-= height
/ 2;
1037 // TODO: the +4 should be customizable
1040 rectText
.x
= rectFrame
.x
+ 4;
1041 rectText
.y
= rect
.y
;
1042 rectText
.width
= rectFrame
.width
- 8;
1043 rectText
.height
= height
;
1046 DrawLabel(dc
, label
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
1048 rectLabel
.width
+= 2;
1050 StandardDrawFrame(dc
, rectFrame
, rectLabel
);
1052 // GTK+ does it like this
1053 dc
.SetPen(m_penHighlight
);
1054 dc
.DrawPoint(rectText
.x
, rectFrame
.y
);
1055 dc
.DrawPoint(rectText
.x
+ rectLabel
.width
- 3, rectFrame
.y
);
1059 // just draw the complete frame
1060 DrawShadedRect(dc
, &rectFrame
, m_penDarkGrey
, m_penHighlight
);
1061 DrawShadedRect(dc
, &rectFrame
, m_penHighlight
, m_penDarkGrey
);
1065 // ----------------------------------------------------------------------------
1067 // ----------------------------------------------------------------------------
1069 void wxGTKRenderer::DrawLabel(wxDC
& dc
,
1070 const wxString
& label
,
1077 DrawButtonLabel(dc
, label
, wxNullBitmap
, rect
, flags
,
1078 alignment
, indexAccel
, rectBounds
);
1081 void wxGTKRenderer::DrawButtonLabel(wxDC
& dc
,
1082 const wxString
& label
,
1083 const wxBitmap
& image
,
1090 if ( flags
& wxCONTROL_DISABLED
)
1092 // make the text grey and draw a shade for it
1093 dc
.SetTextForeground(*wxWHITE
); // FIXME hardcoded colour
1094 wxRect rectShadow
= rect
;
1097 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
1098 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, CONTROL_TEXT_DISABLED
));
1101 dc
.DrawLabel(label
, image
, rect
, alignment
, indexAccel
, rectBounds
);
1104 void wxGTKRenderer::DrawItem(wxDC
& dc
,
1105 const wxString
& label
,
1109 wxLogTrace(_T("listbox"), _T("drawing item '%s' at (%d, %d)-(%d, %d)"),
1112 rect
.x
+ rect
.width
, rect
.y
+ rect
.height
);
1115 if ( flags
& wxCONTROL_SELECTED
)
1117 dc
.SetBrush(wxBrush(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
), wxSOLID
));
1118 dc
.SetPen(*wxTRANSPARENT_PEN
);
1119 dc
.DrawRectangle(rect
);
1121 colFg
= dc
.GetTextForeground();
1122 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
1125 if ( flags
& wxCONTROL_FOCUSED
)
1127 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1128 wxRect rectFocus
= rect
;
1129 DrawRect(dc
, &rectFocus
, m_penBlack
);
1132 wxRect rectText
= rect
;
1135 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
1137 if ( flags
& wxCONTROL_SELECTED
)
1139 dc
.SetBackgroundMode(wxTRANSPARENT
);
1142 // restore the text colour
1145 dc
.SetTextForeground(colFg
);
1149 void wxGTKRenderer::DrawCheckItem(wxDC
& dc
,
1150 const wxString
& label
,
1151 const wxBitmap
& bitmap
,
1155 wxRect rectBitmap
= rect
;
1157 rectBitmap
.width
= GetCheckBitmapSize().x
;
1158 // never draw the focus rect around the check indicators here
1159 DrawCheckButton(dc
, _T(""), bitmap
, rectBitmap
, flags
& ~wxCONTROL_FOCUSED
);
1161 wxRect rectLabel
= rect
;
1162 wxCoord shift
= rectBitmap
.width
+ 2*GetCheckItemMargin();
1163 rectLabel
.x
+= shift
;
1164 rectLabel
.width
-= shift
;
1165 DrawItem(dc
, label
, rectLabel
, flags
);
1168 // ----------------------------------------------------------------------------
1169 // check/radion buttons
1170 // ----------------------------------------------------------------------------
1172 void wxGTKRenderer::DrawUncheckBitmap(wxDC
& dc
,
1173 const wxRect
& rectTotal
,
1176 wxRect rect
= rectTotal
;
1177 DrawAntiRaisedBorder(dc
, &rect
);
1179 wxColour col
= wxSCHEME_COLOUR(m_scheme
, SHADOW_IN
);
1180 dc
.SetPen(wxPen(col
, 0, wxSOLID
));
1181 dc
.DrawPoint(rect
.GetRight() - 1, rect
.GetBottom() - 1);
1184 col
= wxSCHEME_COLOUR(m_scheme
, CONTROL_PRESSED
);
1185 //else: it is SHADOW_IN, leave as is
1187 dc
.SetPen(*wxTRANSPARENT_PEN
);
1188 dc
.SetBrush(wxBrush(col
, wxSOLID
));
1189 dc
.DrawRectangle(rect
);
1192 void wxGTKRenderer::DrawCheckBitmap(wxDC
& dc
, const wxRect
& rectTotal
)
1194 wxRect rect
= rectTotal
;
1195 DrawAntiShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
1196 DrawShadedRect(dc
, &rect
, m_penBlack
, m_penLightGrey
);
1198 dc
.SetPen(*wxTRANSPARENT_PEN
);
1199 dc
.SetBrush(wxBrush(wxSCHEME_COLOUR(m_scheme
, CONTROL_PRESSED
), wxSOLID
));
1200 dc
.DrawRectangle(rect
);
1203 void wxGTKRenderer::DrawRadioBitmap(wxDC
& dc
,
1209 xRight
= rect
.GetRight(),
1210 yBottom
= rect
.GetBottom();
1212 wxCoord yMid
= (y
+ yBottom
) / 2;
1214 // this looks ugly when the background colour of the control is not the
1215 // same ours - radiobox is not transparent as it should be
1217 // first fill the middle: as FloodFill() is not implemented on all
1218 // platforms, this is the only thing to do
1219 wxColour colBg
= flags
& wxCONTROL_CURRENT
1220 ? wxSCHEME_COLOUR(m_scheme
, CONTROL_CURRENT
)
1221 : wxSCHEME_COLOUR(m_scheme
, SHADOW_IN
);
1222 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
1223 dc
.SetPen(*wxTRANSPARENT_PEN
);
1224 dc
.DrawRectangle(rect
);
1227 // then draw the upper half
1228 dc
.SetPen(flags
& wxCONTROL_CHECKED
? m_penDarkGrey
: m_penHighlight
);
1229 DrawUpZag(dc
, x
, xRight
, yMid
, y
);
1230 DrawUpZag(dc
, x
+ 1, xRight
- 1, yMid
, y
+ 1);
1233 if ( flags
& wxCONTROL_CHECKED
)
1234 dc
.SetPen(m_penBlack
);
1235 else if ( flags
& wxCONTROL_PRESSED
)
1236 dc
.SetPen(wxPen(wxSCHEME_COLOUR(m_scheme
, CONTROL_PRESSED
), 0, wxSOLID
));
1237 else // unchecked and unpressed
1241 DrawUpZag(dc
, x
+ 2, xRight
- 2, yMid
, y
+ 2);
1243 // and then the lower one
1244 dc
.SetPen(flags
& wxCONTROL_CHECKED
? m_penHighlight
: m_penBlack
);
1245 DrawDownZag(dc
, x
, xRight
, yMid
, yBottom
);
1246 if ( !(flags
& wxCONTROL_CHECKED
) )
1247 dc
.SetPen(m_penDarkGrey
);
1248 DrawDownZag(dc
, x
+ 1, xRight
- 1, yMid
, yBottom
- 1);
1250 if ( !(flags
& wxCONTROL_CHECKED
) )
1251 drawIt
= TRUE
; // with the same pen
1252 else if ( flags
& wxCONTROL_PRESSED
)
1254 dc
.SetPen(wxPen(wxSCHEME_COLOUR(m_scheme
, CONTROL_PRESSED
), 0, wxSOLID
));
1257 else // checked and unpressed
1261 DrawDownZag(dc
, x
+ 2, xRight
- 2, yMid
, yBottom
- 2);
1264 void wxGTKRenderer::DrawUpZag(wxDC
& dc
,
1270 wxCoord xMid
= (x1
+ x2
) / 2;
1271 dc
.DrawLine(x1
, y1
, xMid
, y2
);
1272 dc
.DrawLine(xMid
, y2
, x2
+ 1, y1
+ 1);
1275 void wxGTKRenderer::DrawDownZag(wxDC
& dc
,
1281 wxCoord xMid
= (x1
+ x2
) / 2;
1282 dc
.DrawLine(x1
+ 1, y1
+ 1, xMid
, y2
);
1283 dc
.DrawLine(xMid
, y2
, x2
, y1
);
1286 wxBitmap
wxGTKRenderer::GetCheckBitmap(int flags
)
1288 if ( !m_bitmapsCheckbox
[0][0].Ok() )
1290 // init the bitmaps once only
1292 wxSize size
= GetCheckBitmapSize();
1293 rect
.width
= size
.x
;
1294 rect
.height
= size
.y
;
1295 for ( int i
= 0; i
< 2; i
++ )
1297 for ( int j
= 0; j
< 2; j
++ )
1298 m_bitmapsCheckbox
[i
][j
].Create(rect
.width
, rect
.height
);
1304 dc
.SelectObject(m_bitmapsCheckbox
[0][0]);
1305 DrawCheckBitmap(dc
, rect
);
1308 dc
.SelectObject(m_bitmapsCheckbox
[0][1]);
1309 DrawUncheckBitmap(dc
, rect
, FALSE
);
1312 m_bitmapsCheckbox
[1][0] = m_bitmapsCheckbox
[0][0];
1314 // pressed unchecked
1315 dc
.SelectObject(m_bitmapsCheckbox
[1][1]);
1316 DrawUncheckBitmap(dc
, rect
, TRUE
);
1319 int row
= flags
& wxCONTROL_PRESSED
? 1 : 0;
1320 int col
= flags
& wxCONTROL_CHECKED
? 0 : 1;
1322 return m_bitmapsCheckbox
[row
][col
];
1325 wxBitmap
wxGTKRenderer::GetLineWrapBitmap()
1327 if ( !m_bmpLineWrap
.Ok() )
1329 // the line wrap bitmap as used by GTK+
1330 #define line_wrap_width 6
1331 #define line_wrap_height 9
1332 static const char line_wrap_bits
[] =
1334 0x1e, 0x3e, 0x30, 0x30, 0x39, 0x1f, 0x0f, 0x0f, 0x1f,
1337 wxBitmap
bmpLineWrap(line_wrap_bits
, line_wrap_width
, line_wrap_height
);
1338 if ( !bmpLineWrap
.Ok() )
1340 wxFAIL_MSG( _T("Failed to create line wrap XBM") );
1344 m_bmpLineWrap
= bmpLineWrap
;
1348 return m_bmpLineWrap
;
1351 void wxGTKRenderer::DrawCheckButton(wxDC
& dc
,
1352 const wxString
& label
,
1353 const wxBitmap
& bitmapOrig
,
1354 const wxRect
& rectTotal
,
1360 if ( bitmapOrig
.Ok() )
1362 bitmap
= bitmapOrig
;
1366 bitmap
= GetCheckBitmap(flags
);
1369 DoDrawCheckOrRadioBitmap(dc
, label
, bitmap
, rectTotal
,
1370 flags
, align
, indexAccel
);
1373 void wxGTKRenderer::DoDrawCheckOrRadioBitmap(wxDC
& dc
,
1374 const wxString
& label
,
1375 const wxBitmap
& bitmap
,
1376 const wxRect
& rectTotal
,
1381 wxRect rect
= rectTotal
;
1383 if ( flags
& wxCONTROL_FOCUSED
)
1385 // draw the focus border around everything
1386 DrawRect(dc
, &rect
, m_penBlack
);
1390 // the border does not offset the string under GTK
1394 // calculate the position of the bitmap and of the label
1396 yBmp
= rect
.y
+ (rect
.height
- bitmap
.GetHeight()) / 2;
1399 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
1400 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
1402 if ( align
== wxALIGN_RIGHT
)
1404 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
1405 rectLabel
.x
= rect
.x
+ 2;
1406 rectLabel
.SetRight(xBmp
);
1408 else // normal (checkbox to the left of the text) case
1411 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 4;
1412 rectLabel
.SetRight(rect
.GetRight());
1415 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, TRUE
/* use mask */);
1417 DrawLabel(dc
, label
, rectLabel
, flags
,
1418 wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
, indexAccel
);
1421 void wxGTKRenderer::DrawRadioButton(wxDC
& dc
,
1422 const wxString
& label
,
1423 const wxBitmap
& bitmapOrig
,
1424 const wxRect
& rectTotal
,
1430 if ( bitmapOrig
.Ok() )
1432 bitmap
= bitmapOrig
;
1437 wxSize size
= GetRadioBitmapSize();
1438 rect
.width
= size
.x
;
1439 rect
.height
= size
.y
;
1440 bitmap
.Create(rect
.width
, rect
.height
);
1442 dc
.SelectObject(bitmap
);
1443 dc
.SetBackground(*wxLIGHT_GREY_BRUSH
);
1445 DrawRadioBitmap(dc
, rect
, flags
);
1446 bitmap
.SetMask(new wxMask(bitmap
, *wxLIGHT_GREY
));
1449 DoDrawCheckOrRadioBitmap(dc
, label
, bitmap
, rectTotal
,
1450 flags
, align
, indexAccel
);
1453 // ----------------------------------------------------------------------------
1455 // ----------------------------------------------------------------------------
1457 static const int TEXT_BORDER
= 2;
1459 wxRect
wxGTKRenderer::GetTextTotalArea(const wxTextCtrl
*text
,
1462 wxRect rectTotal
= rect
;
1463 rectTotal
.Inflate(TEXT_BORDER
);
1467 wxRect
wxGTKRenderer::GetTextClientArea(const wxTextCtrl
*text
,
1469 wxCoord
*extraSpaceBeyond
)
1471 wxRect rectText
= rect
;
1472 rectText
.Inflate(-TEXT_BORDER
);
1474 if ( text
->WrapLines() )
1476 // leave enough for the line wrap bitmap indicator
1477 wxCoord widthMark
= GetLineWrapBitmap().GetWidth() + 2;
1479 rectText
.width
-= widthMark
;
1481 if ( extraSpaceBeyond
)
1482 *extraSpaceBeyond
= widthMark
;
1488 void wxGTKRenderer::DrawTextLine(wxDC
& dc
,
1489 const wxString
& text
,
1495 // TODO: GTK+ draws selection even for unfocused controls, just with
1496 // different colours
1497 StandardDrawTextLine(dc
, text
, rect
, selStart
, selEnd
, flags
);
1500 void wxGTKRenderer::DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
)
1502 wxBitmap bmpLineWrap
= GetLineWrapBitmap();
1504 // for a mono bitmap he colours it appears in depends on the current text
1505 // colours, so set them correctly
1507 if ( bmpLineWrap
.GetDepth() == 1 )
1509 colFgOld
= dc
.GetTextForeground();
1511 // FIXME: I wonder what should we do if the background is black too?
1512 dc
.SetTextForeground(*wxBLACK
);
1515 dc
.DrawBitmap(bmpLineWrap
,
1516 rect
.x
, rect
.y
+ (rect
.height
- bmpLineWrap
.GetHeight())/2);
1518 if ( colFgOld
.Ok() )
1520 // restore old colour
1521 dc
.SetTextForeground(colFgOld
);
1525 // ----------------------------------------------------------------------------
1527 // ----------------------------------------------------------------------------
1529 void wxGTKRenderer::DrawTab(wxDC
& dc
,
1530 const wxRect
& rectOrig
,
1532 const wxString
& label
,
1533 const wxBitmap
& bitmap
,
1537 wxRect rect
= rectOrig
;
1539 // the current tab is drawn indented (to the top for default case) and
1540 // bigger than the other ones
1541 const wxSize indent
= GetTabIndent();
1542 if ( flags
& wxCONTROL_SELECTED
)
1547 wxFAIL_MSG(_T("invaild notebook tab orientation"));
1551 rect
.Inflate(indent
.x
, 0);
1553 rect
.height
+= indent
.y
;
1557 rect
.Inflate(indent
.x
, 0);
1558 rect
.height
+= indent
.y
;
1563 wxFAIL_MSG(_T("TODO"));
1568 // selected tab has different colour
1569 wxColour col
= flags
& wxCONTROL_SELECTED
1570 ? wxSCHEME_COLOUR(m_scheme
, SHADOW_IN
)
1571 : wxSCHEME_COLOUR(m_scheme
, SCROLLBAR
);
1572 DoDrawBackground(dc
, col
, rect
);
1574 if ( flags
& wxCONTROL_FOCUSED
)
1576 // draw the focus rect
1577 wxRect rectBorder
= rect
;
1578 rectBorder
.Deflate(4, 3);
1579 if ( dir
== wxBOTTOM
)
1580 rectBorder
.Offset(0, -1);
1582 DrawRect(dc
, &rectBorder
, m_penBlack
);
1585 // draw the text, image and the focus around them (if necessary)
1586 wxRect rectLabel
= rect
;
1587 rectLabel
.Deflate(1, 1);
1588 dc
.DrawLabel(label
, bitmap
, rectLabel
, wxALIGN_CENTRE
, indexAccel
);
1590 // now draw the tab itself
1593 x2
= rect
.GetRight(),
1594 y2
= rect
.GetBottom();
1599 dc
.SetPen(m_penHighlight
);
1600 dc
.DrawLine(x
, y2
, x
, y
);
1601 dc
.DrawLine(x
+ 1, y
, x2
, y
);
1603 dc
.SetPen(m_penBlack
);
1604 dc
.DrawLine(x2
, y2
, x2
, y
);
1606 dc
.SetPen(m_penDarkGrey
);
1607 dc
.DrawLine(x2
- 1, y2
, x2
- 1, y
+ 1);
1609 if ( flags
& wxCONTROL_SELECTED
)
1611 dc
.SetPen(m_penLightGrey
);
1613 // overwrite the part of the border below this tab
1614 dc
.DrawLine(x
+ 1, y2
+ 1, x2
- 1, y2
+ 1);
1616 // and the shadow of the tab to the left of us
1617 dc
.DrawLine(x
+ 1, y
+ 2, x
+ 1, y2
+ 1);
1622 dc
.SetPen(m_penHighlight
);
1624 // we need to continue one pixel further to overwrite the corner of
1625 // the border for the selected tab
1626 dc
.DrawLine(x
, y
- (flags
& wxCONTROL_SELECTED
? 1 : 0),
1629 // it doesn't work like this (TODO: implement it properly)
1631 // erase the corner of the tab to the right
1632 dc
.SetPen(m_penLightGrey
);
1633 dc
.DrawPoint(x2
- 1, y
- 2);
1634 dc
.DrawPoint(x2
- 2, y
- 2);
1635 dc
.DrawPoint(x2
- 2, y
- 1);
1638 dc
.SetPen(m_penBlack
);
1639 dc
.DrawLine(x
+ 1, y2
, x2
, y2
);
1640 dc
.DrawLine(x2
, y
, x2
, y2
);
1642 dc
.SetPen(m_penDarkGrey
);
1643 dc
.DrawLine(x
+ 2, y2
- 1, x2
- 1, y2
- 1);
1644 dc
.DrawLine(x2
- 1, y
, x2
- 1, y2
);
1646 if ( flags
& wxCONTROL_SELECTED
)
1648 dc
.SetPen(m_penLightGrey
);
1650 // overwrite the part of the (double!) border above this tab
1651 dc
.DrawLine(x
+ 1, y
- 1, x2
- 1, y
- 1);
1652 dc
.DrawLine(x
+ 1, y
- 2, x2
- 1, y
- 2);
1654 // and the shadow of the tab to the left of us
1655 dc
.DrawLine(x
+ 1, y2
- 1, x
+ 1, y
- 1);
1661 wxFAIL_MSG(_T("TODO"));
1665 // ----------------------------------------------------------------------------
1667 // ----------------------------------------------------------------------------
1669 wxSize
wxGTKRenderer::GetSliderThumbSize(const wxRect
& rect
,
1670 wxOrientation orient
) const
1672 static const wxCoord SLIDER_THUMB_LENGTH
= 30;
1676 wxRect rectShaft
= GetSliderShaftRect(rect
, orient
);
1677 if ( orient
== wxHORIZONTAL
)
1679 size
.x
= wxMin(SLIDER_THUMB_LENGTH
, rectShaft
.width
);
1680 size
.y
= rectShaft
.height
;
1684 size
.y
= wxMin(SLIDER_THUMB_LENGTH
, rectShaft
.height
);
1685 size
.x
= rectShaft
.width
;
1691 wxRect
wxGTKRenderer::GetSliderShaftRect(const wxRect
& rect
,
1692 wxOrientation
WXUNUSED(orient
)) const
1694 return rect
.Deflate(2*BORDER_THICKNESS
, 2*BORDER_THICKNESS
);
1697 void wxGTKRenderer::DrawSliderShaft(wxDC
& dc
,
1698 const wxRect
& rectOrig
,
1699 wxOrientation orient
,
1703 wxRect rect
= rectOrig
;
1705 // draw the border first
1706 if ( flags
& wxCONTROL_FOCUSED
)
1708 DrawRect(dc
, &rect
, m_penBlack
);
1709 DrawAntiShadedRect(dc
, &rect
, m_penBlack
, m_penLightGrey
);
1711 else // not focused, normal
1713 DrawAntiShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
1714 DrawAntiShadedRect(dc
, &rect
, m_penBlack
, m_penLightGrey
);
1717 // and the background
1718 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, SCROLLBAR
), rect
);
1724 void wxGTKRenderer::DrawSliderThumb(wxDC
& dc
,
1725 const wxRect
& rectOrig
,
1726 wxOrientation orient
,
1729 // draw the thumb border
1730 wxRect rect
= rectOrig
;
1731 DrawAntiRaisedBorder(dc
, &rect
);
1733 // draw the handle in the middle
1734 if ( orient
== wxVERTICAL
)
1736 rect
.height
= 2*BORDER_THICKNESS
;
1737 rect
.y
= rectOrig
.y
+ (rectOrig
.height
- rect
.height
) / 2;
1741 rect
.width
= 2*BORDER_THICKNESS
;
1742 rect
.x
= rectOrig
.x
+ (rectOrig
.width
- rect
.width
) / 2;
1745 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
1748 // ----------------------------------------------------------------------------
1750 // ----------------------------------------------------------------------------
1752 void wxGTKRenderer::DrawMenuBarItem(wxDC
& dc
,
1754 const wxString
& label
,
1758 DrawLabel(dc
, label
, rect
, flags
, wxALIGN_CENTRE
, indexAccel
);
1761 void wxGTKRenderer::DrawMenuItem(wxDC
& dc
,
1763 const wxMenuGeometryInfo
& geometryInfo
,
1764 const wxString
& label
,
1765 const wxString
& accel
,
1766 const wxBitmap
& bitmap
,
1770 wxFAIL_MSG(_T("TODO"));
1773 void wxGTKRenderer::DrawMenuSeparator(wxDC
& dc
,
1775 const wxMenuGeometryInfo
& geomInfo
)
1777 wxFAIL_MSG(_T("TODO"));
1780 wxSize
wxGTKRenderer::GetMenuBarItemSize(const wxSize
& sizeText
) const
1785 wxMenuGeometryInfo
*wxGTKRenderer::GetMenuGeometry(wxWindow
*win
,
1786 const wxMenu
& menu
) const
1788 wxFAIL_MSG(_T("TODO"));
1793 // ----------------------------------------------------------------------------
1795 // ----------------------------------------------------------------------------
1797 void wxGTKRenderer::GetComboBitmaps(wxBitmap
*bmpNormal
,
1798 wxBitmap
*bmpPressed
,
1799 wxBitmap
*bmpDisabled
)
1804 // ----------------------------------------------------------------------------
1806 // ----------------------------------------------------------------------------
1808 void wxGTKRenderer::DoDrawBackground(wxDC
& dc
,
1809 const wxColour
& col
,
1812 wxBrush
brush(col
, wxSOLID
);
1814 dc
.SetPen(*wxTRANSPARENT_PEN
);
1815 dc
.DrawRectangle(rect
);
1818 void wxGTKRenderer::DrawBackground(wxDC
& dc
,
1819 const wxColour
& col
,
1823 wxColour colBg
= col
.Ok() ? col
: GetBackgroundColour(flags
);
1824 DoDrawBackground(dc
, colBg
, rect
);
1827 // ----------------------------------------------------------------------------
1829 // ----------------------------------------------------------------------------
1831 void wxGTKRenderer::DrawArrowBorder(wxDC
& dc
,
1835 static const wxDirection sides
[] =
1837 wxUP
, wxLEFT
, wxRIGHT
, wxDOWN
1840 wxRect rect1
, rect2
, rectInner
;
1846 rectInner
.Inflate(-2);
1848 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, SCROLLBAR
), *rect
);
1850 // find the side not to draw and also adjust the rectangles to compensate
1852 wxDirection sideToOmit
;
1856 sideToOmit
= wxDOWN
;
1858 rectInner
.height
+= 1;
1866 rectInner
.height
+= 1;
1870 sideToOmit
= wxRIGHT
;
1872 rectInner
.width
+= 1;
1876 sideToOmit
= wxLEFT
;
1880 rectInner
.width
+= 1;
1884 wxFAIL_MSG(_T("unknown arrow direction"));
1888 // the outer rect first
1890 for ( n
= 0; n
< WXSIZEOF(sides
); n
++ )
1892 wxDirection side
= sides
[n
];
1893 if ( side
== sideToOmit
)
1896 DrawAntiShadedRectSide(dc
, rect1
, m_penDarkGrey
, m_penHighlight
, side
);
1899 // and then the inner one
1900 for ( n
= 0; n
< WXSIZEOF(sides
); n
++ )
1902 wxDirection side
= sides
[n
];
1903 if ( side
== sideToOmit
)
1906 DrawAntiShadedRectSide(dc
, rect2
, m_penBlack
, m_penGrey
, side
);
1912 void wxGTKRenderer::DrawScrollbarArrow(wxDC
& dc
,
1914 const wxRect
& rectArrow
,
1917 // first of all, draw the border around it - but we don't want the border
1918 // on the side opposite to the arrow point
1919 wxRect rect
= rectArrow
;
1920 DrawArrowBorder(dc
, &rect
, dir
);
1922 // then the arrow itself
1923 DrawArrow(dc
, dir
, rect
, flags
);
1926 // gtk_default_draw_arrow() takes ~350 lines and we can't do much better here
1927 // these people are just crazy :-(
1928 void wxGTKRenderer::DrawArrow(wxDC
& dc
,
1941 wxPoint ptArrow
[Point_Max
];
1943 wxColour colInside
= GetBackgroundColour(flags
);
1945 if ( flags
& wxCONTROL_DISABLED
)
1947 penShadow
[0] = m_penDarkGrey
;
1948 penShadow
[1] = m_penDarkGrey
;
1949 penShadow
[2] = wxNullPen
;
1950 penShadow
[3] = wxNullPen
;
1952 else if ( flags
& wxCONTROL_PRESSED
)
1954 penShadow
[0] = m_penDarkGrey
;
1955 penShadow
[1] = m_penHighlight
;
1956 penShadow
[2] = wxNullPen
;
1957 penShadow
[3] = m_penBlack
;
1959 else // normal arrow
1961 penShadow
[0] = m_penHighlight
;
1962 penShadow
[1] = m_penBlack
;
1963 penShadow
[2] = m_penDarkGrey
;
1964 penShadow
[3] = wxNullPen
;
1968 if ( dir
== wxUP
|| dir
== wxDOWN
)
1971 middle
= (rect
.GetRight() + rect
.GetLeft() + 1) / 2;
1975 middle
= (rect
.GetTop() + rect
.GetBottom() + 1) / 2;
1978 // draw the arrow interior
1979 dc
.SetPen(*wxTRANSPARENT_PEN
);
1980 dc
.SetBrush(wxBrush(colInside
, wxSOLID
));
1985 ptArrow
[Point_First
].x
= rect
.GetLeft();
1986 ptArrow
[Point_First
].y
= rect
.GetBottom();
1987 ptArrow
[Point_Second
].x
= middle
;
1988 ptArrow
[Point_Second
].y
= rect
.GetTop();
1989 ptArrow
[Point_Third
].x
= rect
.GetRight();
1990 ptArrow
[Point_Third
].y
= rect
.GetBottom();
1994 ptArrow
[Point_First
] = rect
.GetPosition();
1995 ptArrow
[Point_Second
].x
= middle
;
1996 ptArrow
[Point_Second
].y
= rect
.GetBottom();
1997 ptArrow
[Point_Third
].x
= rect
.GetRight();
1998 ptArrow
[Point_Third
].y
= rect
.GetTop();
2002 ptArrow
[Point_First
].x
= rect
.GetRight();
2003 ptArrow
[Point_First
].y
= rect
.GetTop();
2004 ptArrow
[Point_Second
].x
= rect
.GetLeft();
2005 ptArrow
[Point_Second
].y
= middle
;
2006 ptArrow
[Point_Third
].x
= rect
.GetRight();
2007 ptArrow
[Point_Third
].y
= rect
.GetBottom();
2011 ptArrow
[Point_First
] = rect
.GetPosition();
2012 ptArrow
[Point_Second
].x
= rect
.GetRight();
2013 ptArrow
[Point_Second
].y
= middle
;
2014 ptArrow
[Point_Third
].x
= rect
.GetLeft();
2015 ptArrow
[Point_Third
].y
= rect
.GetBottom();
2019 wxFAIL_MSG(_T("unknown arrow direction"));
2022 dc
.DrawPolygon(WXSIZEOF(ptArrow
), ptArrow
);
2024 // draw the arrow border
2025 dc
.SetPen(penShadow
[0]);
2029 dc
.DrawLine(ptArrow
[Point_Second
], ptArrow
[Point_First
]);
2030 dc
.DrawPoint(ptArrow
[Point_First
]);
2031 if ( penShadow
[3].Ok() )
2033 dc
.SetPen(penShadow
[3]);
2034 dc
.DrawLine(ptArrow
[Point_First
].x
+ 1, ptArrow
[Point_First
].y
,
2035 ptArrow
[Point_Second
].x
, ptArrow
[Point_Second
].y
);
2037 dc
.SetPen(penShadow
[1]);
2038 dc
.DrawLine(ptArrow
[Point_Second
].x
+ 1, ptArrow
[Point_Second
].y
+ 1,
2039 ptArrow
[Point_Third
].x
, ptArrow
[Point_Third
].y
);
2040 dc
.DrawPoint(ptArrow
[Point_Third
]);
2041 dc
.DrawLine(ptArrow
[Point_Third
].x
- 2, ptArrow
[Point_Third
].y
,
2042 ptArrow
[Point_First
].x
+ 1, ptArrow
[Point_First
].y
);
2043 if ( penShadow
[2].Ok() )
2045 dc
.SetPen(penShadow
[2]);
2046 dc
.DrawLine(ptArrow
[Point_Third
].x
- 1, ptArrow
[Point_Third
].y
,
2047 ptArrow
[Point_Second
].x
, ptArrow
[Point_Second
].y
+ 1);
2048 dc
.DrawLine(ptArrow
[Point_Third
].x
- 1, ptArrow
[Point_Third
].y
- 1,
2049 ptArrow
[Point_First
].x
+ 2, ptArrow
[Point_First
].y
- 1);
2054 dc
.DrawLine(ptArrow
[Point_First
], ptArrow
[Point_Second
]);
2055 dc
.DrawLine(ptArrow
[Point_First
].x
+ 2, ptArrow
[Point_First
].y
,
2056 ptArrow
[Point_Third
].x
- 1, ptArrow
[Point_Third
].y
);
2057 if ( penShadow
[2].Ok() )
2059 dc
.SetPen(penShadow
[2]);
2060 dc
.DrawLine(ptArrow
[Point_Second
].x
, ptArrow
[Point_Second
].y
- 1,
2061 ptArrow
[Point_Third
].x
- 1, ptArrow
[Point_Third
].y
- 1);
2063 dc
.SetPen(penShadow
[1]);
2064 dc
.DrawLine(ptArrow
[Point_Second
], ptArrow
[Point_Third
]);
2065 dc
.DrawPoint(ptArrow
[Point_Third
]);
2069 dc
.DrawLine(ptArrow
[Point_Second
], ptArrow
[Point_First
]);
2070 dc
.DrawPoint(ptArrow
[Point_First
]);
2071 if ( penShadow
[2].Ok() )
2073 dc
.SetPen(penShadow
[2]);
2074 dc
.DrawLine(ptArrow
[Point_Third
].x
- 1, ptArrow
[Point_Third
].y
,
2075 ptArrow
[Point_First
].x
- 1, ptArrow
[Point_First
].y
+ 2);
2076 dc
.DrawLine(ptArrow
[Point_Third
].x
, ptArrow
[Point_Third
].y
,
2077 ptArrow
[Point_Second
].x
+ 2, ptArrow
[Point_Second
].y
+ 1);
2079 dc
.SetPen(penShadow
[1]);
2080 dc
.DrawLine(ptArrow
[Point_Third
].x
, ptArrow
[Point_Third
].y
,
2081 ptArrow
[Point_First
].x
, ptArrow
[Point_First
].y
+ 1);
2082 dc
.DrawLine(ptArrow
[Point_Second
].x
+ 1, ptArrow
[Point_Second
].y
+ 1,
2083 ptArrow
[Point_Third
].x
- 1, ptArrow
[Point_Third
].y
);
2087 dc
.DrawLine(ptArrow
[Point_First
], ptArrow
[Point_Third
]);
2088 dc
.DrawLine(ptArrow
[Point_First
].x
+ 2, ptArrow
[Point_First
].y
+ 1,
2089 ptArrow
[Point_Second
].x
, ptArrow
[Point_Second
].y
);
2090 dc
.SetPen(penShadow
[1]);
2091 dc
.DrawLine(ptArrow
[Point_Second
], ptArrow
[Point_Third
]);
2092 dc
.DrawPoint(ptArrow
[Point_Third
]);
2096 wxFAIL_MSG(_T("unknown arrow direction"));
2101 void wxGTKRenderer::DrawThumbBorder(wxDC
& dc
,
2103 wxOrientation orient
)
2105 if ( orient
== wxVERTICAL
)
2107 DrawAntiShadedRectSide(dc
, *rect
, m_penDarkGrey
, m_penHighlight
,
2109 DrawAntiShadedRectSide(dc
, *rect
, m_penDarkGrey
, m_penHighlight
,
2111 rect
->Inflate(-1, 0);
2113 DrawAntiShadedRectSide(dc
, *rect
, m_penBlack
, m_penGrey
,
2115 DrawAntiShadedRectSide(dc
, *rect
, m_penBlack
, m_penGrey
,
2117 rect
->Inflate(-1, 0);
2121 DrawAntiShadedRectSide(dc
, *rect
, m_penDarkGrey
, m_penHighlight
,
2123 DrawAntiShadedRectSide(dc
, *rect
, m_penDarkGrey
, m_penHighlight
,
2125 rect
->Inflate(0, -1);
2127 DrawAntiShadedRectSide(dc
, *rect
, m_penBlack
, m_penGrey
,
2129 DrawAntiShadedRectSide(dc
, *rect
, m_penBlack
, m_penGrey
,
2131 rect
->Inflate(0, -1);
2135 void wxGTKRenderer::DrawScrollbarThumb(wxDC
& dc
,
2136 wxOrientation orient
,
2140 // the thumb is never pressed never has focus border under GTK and the
2141 // scrollbar background never changes at all
2142 int flagsThumb
= flags
& ~(wxCONTROL_PRESSED
| wxCONTROL_FOCUSED
);
2144 // we don't want the border in the direction of the scrollbar movement
2145 wxRect rectThumb
= rect
;
2146 DrawThumbBorder(dc
, &rectThumb
, orient
);
2148 DrawButtonBorder(dc
, rectThumb
, flagsThumb
, &rectThumb
);
2149 DrawBackground(dc
, wxNullColour
, rectThumb
, flagsThumb
);
2152 void wxGTKRenderer::DrawScrollbarShaft(wxDC
& dc
,
2153 wxOrientation orient
,
2157 wxRect rectBar
= rect
;
2158 DrawThumbBorder(dc
, &rectBar
, orient
);
2159 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, SCROLLBAR
), rectBar
);
2162 void wxGTKRenderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
2164 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2167 wxRect
wxGTKRenderer::GetScrollbarRect(const wxScrollBar
*scrollbar
,
2168 wxScrollBar::Element elem
,
2171 // as GTK scrollbars can't be disabled, it makes no sense to remove the
2172 // thumb for a scrollbar with range 0 - instead, make it fill the entire
2174 if ( (elem
== wxScrollBar::Element_Thumb
) && !scrollbar
->GetRange() )
2176 elem
= wxScrollBar::Element_Bar_2
;
2179 return StandardGetScrollbarRect(scrollbar
, elem
,
2181 GetScrollbarArrowSize(scrollbar
));
2184 wxCoord
wxGTKRenderer::GetScrollbarSize(const wxScrollBar
*scrollbar
)
2186 return StandardScrollBarSize(scrollbar
, GetScrollbarArrowSize(scrollbar
));
2189 wxHitTest
wxGTKRenderer::HitTestScrollbar(const wxScrollBar
*scrollbar
,
2190 const wxPoint
& pt
) const
2192 return StandardHitTestScrollbar(scrollbar
, pt
,
2193 GetScrollbarArrowSize(scrollbar
));
2196 wxCoord
wxGTKRenderer::ScrollbarToPixel(const wxScrollBar
*scrollbar
,
2199 return StandardScrollbarToPixel(scrollbar
, thumbPos
,
2200 GetScrollbarArrowSize(scrollbar
));
2203 int wxGTKRenderer::PixelToScrollbar(const wxScrollBar
*scrollbar
,
2206 return StandardPixelToScrollbar(scrollbar
, coord
,
2207 GetScrollbarArrowSize(scrollbar
));
2210 // ----------------------------------------------------------------------------
2212 // ----------------------------------------------------------------------------
2214 void wxGTKRenderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
2216 if ( wxDynamicCast(window
, wxButton
) )
2218 // TODO: this is ad hoc...
2219 size
->x
+= 3*window
->GetCharWidth();
2222 wxCoord minBtnHeight
= 22;
2223 if ( size
->y
< minBtnHeight
)
2224 size
->y
= minBtnHeight
;
2226 // button border width
2229 else if ( wxDynamicCast(window
, wxScrollBar
) )
2231 // we only set the width of vert scrollbars and height of the
2233 if ( window
->GetWindowStyle() & wxSB_HORIZONTAL
)
2234 size
->y
= m_sizeScrollbarArrow
.x
;
2236 size
->x
= m_sizeScrollbarArrow
.x
;
2240 // take into account the border width
2241 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
2242 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
2243 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
2247 // ============================================================================
2249 // ============================================================================
2251 // ----------------------------------------------------------------------------
2252 // wxGTKInputHandler
2253 // ----------------------------------------------------------------------------
2255 wxGTKInputHandler::wxGTKInputHandler(wxGTKRenderer
*renderer
)
2257 m_renderer
= renderer
;
2260 bool wxGTKInputHandler::HandleKey(wxControl
*control
,
2261 const wxKeyEvent
& event
,
2267 bool wxGTKInputHandler::HandleMouse(wxControl
*control
,
2268 const wxMouseEvent
& event
)
2270 // clicking on the control gives it focus
2271 if ( event
.ButtonDown() )
2273 control
->SetFocus();
2281 bool wxGTKInputHandler::HandleMouseMove(wxControl
*control
,
2282 const wxMouseEvent
& event
)
2284 if ( event
.Entering() )
2286 control
->SetCurrent(TRUE
);
2288 else if ( event
.Leaving() )
2290 control
->SetCurrent(FALSE
);
2300 // ----------------------------------------------------------------------------
2301 // wxGTKCheckboxInputHandler
2302 // ----------------------------------------------------------------------------
2304 bool wxGTKCheckboxInputHandler::HandleKey(wxControl
*control
,
2305 const wxKeyEvent
& event
,
2310 int keycode
= event
.GetKeyCode();
2311 if ( keycode
== WXK_SPACE
|| keycode
== WXK_RETURN
)
2313 control
->PerformAction(wxACTION_CHECKBOX_TOGGLE
);
2322 // ----------------------------------------------------------------------------
2323 // wxGTKTextCtrlInputHandler
2324 // ----------------------------------------------------------------------------
2326 bool wxGTKTextCtrlInputHandler::HandleKey(wxControl
*control
,
2327 const wxKeyEvent
& event
,
2330 // handle only GTK-specific text bindings here, the others are handled in
2334 wxControlAction action
;
2335 int keycode
= event
.GetKeyCode();
2336 if ( event
.ControlDown() )
2341 action
= wxACTION_TEXT_HOME
;
2345 action
= wxACTION_TEXT_LEFT
;
2349 action
<< wxACTION_TEXT_PREFIX_DEL
<< wxACTION_TEXT_RIGHT
;
2353 action
= wxACTION_TEXT_END
;
2357 action
= wxACTION_TEXT_RIGHT
;
2361 action
<< wxACTION_TEXT_PREFIX_DEL
<< wxACTION_TEXT_LEFT
;
2365 action
<< wxACTION_TEXT_PREFIX_DEL
<< wxACTION_TEXT_END
;
2369 action
= wxACTION_TEXT_DOWN
;
2373 action
= wxACTION_TEXT_UP
;
2377 //delete the entire line
2378 control
->PerformAction(wxACTION_TEXT_HOME
);
2379 action
<< wxACTION_TEXT_PREFIX_DEL
<< wxACTION_TEXT_END
;
2383 action
<< wxACTION_TEXT_PREFIX_DEL
<< wxACTION_TEXT_WORD_LEFT
;
2387 else if ( event
.AltDown() )
2392 action
= wxACTION_TEXT_WORD_LEFT
;
2396 action
<< wxACTION_TEXT_PREFIX_DEL
<< wxACTION_TEXT_WORD_RIGHT
;
2400 action
= wxACTION_TEXT_WORD_RIGHT
;
2405 if ( action
!= wxACTION_NONE
)
2407 control
->PerformAction(action
);
2413 return wxStdTextCtrlInputHandler::HandleKey(control
, event
, pressed
);