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
190 virtual void DrawMenuBarItem(wxDC
& dc
,
192 const wxString
& label
,
194 int indexAccel
= -1);
195 virtual void DrawMenuItem(wxDC
& dc
,
197 const wxMenuGeometryInfo
& geometryInfo
,
198 const wxString
& label
,
199 const wxString
& accel
,
200 const wxBitmap
& bitmap
= wxNullBitmap
,
202 int indexAccel
= -1);
203 virtual void DrawMenuSeparator(wxDC
& dc
,
205 const wxMenuGeometryInfo
& geomInfo
);
207 virtual void GetComboBitmaps(wxBitmap
*bmpNormal
,
208 wxBitmap
*bmpPressed
,
209 wxBitmap
*bmpDisabled
);
211 virtual void AdjustSize(wxSize
*size
, const wxWindow
*window
);
212 virtual wxRect
GetBorderDimensions(wxBorder border
) const;
213 virtual bool AreScrollbarsInsideBorder() const;
215 // geometry and hit testing
216 virtual wxSize
GetScrollbarArrowSize() const
217 { return m_sizeScrollbarArrow
; }
218 virtual wxRect
GetScrollbarRect(const wxScrollBar
*scrollbar
,
219 wxScrollBar::Element elem
,
220 int thumbPos
= -1) const;
221 virtual wxCoord
GetScrollbarSize(const wxScrollBar
*scrollbar
);
222 virtual wxHitTest
HitTestScrollbar(const wxScrollBar
*scrollbar
,
223 const wxPoint
& pt
) const;
224 virtual wxCoord
ScrollbarToPixel(const wxScrollBar
*scrollbar
,
226 virtual int PixelToScrollbar(const wxScrollBar
*scrollbar
, wxCoord coord
);
227 virtual wxCoord
GetListboxItemHeight(wxCoord fontHeight
)
228 { return fontHeight
+ 2; }
229 virtual wxSize
GetCheckBitmapSize() const
230 { return wxSize(10, 10); }
231 virtual wxSize
GetRadioBitmapSize() const
232 { return wxSize(11, 11); }
233 virtual wxCoord
GetCheckItemMargin() const
236 virtual wxRect
GetTextTotalArea(const wxTextCtrl
*text
,
238 virtual wxRect
GetTextClientArea(const wxTextCtrl
*text
,
240 wxCoord
*extraSpaceBeyond
);
242 virtual wxSize
GetTabIndent() const { return wxSize(2, 2); }
243 virtual wxSize
GetTabPadding() const { return wxSize(6, 6); }
245 virtual wxCoord
GetSliderDim() const { return 15; }
246 virtual wxCoord
GetSliderTickLen() const { return 0; }
247 virtual wxRect
GetSliderShaftRect(const wxRect
& rect
,
248 wxOrientation orient
) const;
249 virtual wxSize
GetSliderThumbSize(const wxRect
& rect
,
250 wxOrientation orient
) const;
251 virtual wxSize
GetProgressBarStep() const { return wxSize(16, 32); }
254 virtual wxSize
GetMenuBarItemSize(const wxSize
& sizeText
) const;
255 virtual wxMenuGeometryInfo
*GetMenuGeometry(wxWindow
*win
,
256 const wxMenu
& menu
) const;
258 // helpers for "wxBitmap wxColourScheme::Get()"
259 void DrawCheckBitmap(wxDC
& dc
, const wxRect
& rect
);
260 void DrawUncheckBitmap(wxDC
& dc
, const wxRect
& rect
, bool isPressed
);
263 // DrawBackground() helpers
265 // get the colour to use for background
266 wxColour
GetBackgroundColour(int flags
) const
268 if ( flags
& wxCONTROL_PRESSED
)
269 return wxSCHEME_COLOUR(m_scheme
, CONTROL_PRESSED
);
270 else if ( flags
& wxCONTROL_CURRENT
)
271 return wxSCHEME_COLOUR(m_scheme
, CONTROL_CURRENT
);
273 return wxSCHEME_COLOUR(m_scheme
, CONTROL
);
276 // draw the background with any colour, not only the default one(s)
277 void DoDrawBackground(wxDC
& dc
,
281 // DrawBorder() helpers: all of them shift and clip the DC after drawing
284 // just draw a rectangle with the given pen
285 void DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
287 // draw the lower left part of rectangle
288 void DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
290 // draw the rectange using the first brush for the left and top sides and
291 // the second one for the bottom and right ones
292 void DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
293 const wxPen
& pen1
, const wxPen
& pen2
);
295 // as DrawShadedRect() but the pixels in the bottom left and upper right
296 // border are drawn with the pen1, not pen2
297 void DrawAntiShadedRect(wxDC
& dc
, wxRect
*rect
,
298 const wxPen
& pen1
, const wxPen
& pen2
);
300 // used for drawing opened rectangles - draws only one side of it at once
301 // (and doesn't adjust the rect)
302 void DrawAntiShadedRectSide(wxDC
& dc
,
308 // draw an opened rect for the arrow in given direction
309 void DrawArrowBorder(wxDC
& dc
,
313 // draw two sides of the rectangle
314 void DrawThumbBorder(wxDC
& dc
,
316 wxOrientation orient
);
318 // draw the normal 3D border
319 void DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
);
321 // just as DrawRaisedBorder() except that the bottom left and up right
322 // pixels of the interior rect are drawn in another colour (i.e. the inner
323 // rect is drawn with DrawAntiShadedRect() and not DrawShadedRect())
324 void DrawAntiRaisedBorder(wxDC
& dc
, wxRect
*rect
);
326 // returns the size of the arrow for the scrollbar (depends on
328 wxSize
GetScrollbarArrowSize(const wxScrollBar
*scrollbar
) const
331 if ( scrollbar
->IsVertical() )
333 size
= m_sizeScrollbarArrow
;
337 size
.x
= m_sizeScrollbarArrow
.y
;
338 size
.y
= m_sizeScrollbarArrow
.x
;
344 // get the line wrap indicator bitmap
345 wxBitmap
GetLineWrapBitmap();
347 // DrawCheckBitmap and DrawRadioBitmap helpers
349 // draw the check bitmaps once and cache them for later use
350 wxBitmap
GetCheckBitmap(int flags
);
352 // draw a /\ or \/ line from (x1, y1) to (x2, y1) passing by the point
354 void DrawUpZag(wxDC
& dc
,
355 wxCoord x1
, wxCoord x2
,
356 wxCoord y1
, wxCoord y2
);
357 void DrawDownZag(wxDC
& dc
,
358 wxCoord x1
, wxCoord x2
,
359 wxCoord y1
, wxCoord y2
);
361 // draw the radio button bitmap for the given state
362 void DrawRadioBitmap(wxDC
& dc
, const wxRect
& rect
, int flags
);
364 // draw check/radio - the bitmap must be a valid one by now
365 void DoDrawCheckOrRadioBitmap(wxDC
& dc
,
366 const wxString
& label
,
367 const wxBitmap
& bitmap
,
368 const wxRect
& rectTotal
,
374 const wxColourScheme
*m_scheme
;
377 wxSize m_sizeScrollbarArrow
;
386 // the checkbox bitmaps: first row is for the normal, second for the
387 // pressed state and the columns are for checked and unchecked status
389 wxBitmap m_bitmapsCheckbox
[2][2];
391 // the line wrap bitmap (drawn at the end of wrapped lines)
392 wxBitmap m_bmpLineWrap
;
395 // ----------------------------------------------------------------------------
396 // wxGTKInputHandler and derived classes: process the keyboard and mouse
397 // messages according to GTK standards
398 // ----------------------------------------------------------------------------
400 class wxGTKInputHandler
: public wxInputHandler
403 wxGTKInputHandler(wxGTKRenderer
*renderer
);
405 virtual bool HandleKey(wxControl
*control
,
406 const wxKeyEvent
& event
,
408 virtual bool HandleMouse(wxControl
*control
,
409 const wxMouseEvent
& event
);
410 virtual bool HandleMouseMove(wxControl
*control
, const wxMouseEvent
& event
);
413 wxGTKRenderer
*m_renderer
;
416 class wxGTKScrollBarInputHandler
: public wxStdScrollBarInputHandler
419 wxGTKScrollBarInputHandler(wxRenderer
*renderer
, wxInputHandler
*handler
)
420 : wxStdScrollBarInputHandler(renderer
, handler
) { }
423 virtual void Highlight(wxScrollBar
*scrollbar
, bool doIt
)
425 // only arrows and the thumb can be highlighted
426 if ( !IsArrow() && m_htLast
!= wxHT_SCROLLBAR_THUMB
)
429 wxStdScrollBarInputHandler::Highlight(scrollbar
, doIt
);
432 virtual void Press(wxScrollBar
*scrollbar
, bool doIt
)
434 // only arrows can be pressed
438 wxStdScrollBarInputHandler::Press(scrollbar
, doIt
);
441 virtual bool IsAllowedButton(int WXUNUSED(button
)) { return TRUE
; }
445 return m_htLast
== wxHT_SCROLLBAR_ARROW_LINE_1
||
446 m_htLast
== wxHT_SCROLLBAR_ARROW_LINE_2
;
450 class wxGTKCheckboxInputHandler
: public wxStdCheckboxInputHandler
453 wxGTKCheckboxInputHandler(wxInputHandler
*handler
)
454 : wxStdCheckboxInputHandler(handler
) { }
456 virtual bool HandleKey(wxControl
*control
,
457 const wxKeyEvent
& event
,
461 class wxGTKTextCtrlInputHandler
: public wxStdTextCtrlInputHandler
464 wxGTKTextCtrlInputHandler(wxInputHandler
*handler
)
465 : wxStdTextCtrlInputHandler(handler
) { }
467 virtual bool HandleKey(wxControl
*control
,
468 const wxKeyEvent
& event
,
472 // ----------------------------------------------------------------------------
473 // wxGTKColourScheme: uses the standard GTK colours
474 // ----------------------------------------------------------------------------
476 class wxGTKColourScheme
: public wxColourScheme
479 virtual wxColour
Get(StdColour col
) const;
480 virtual wxColour
GetBackground(wxWindow
*win
) const;
483 // ----------------------------------------------------------------------------
485 // ----------------------------------------------------------------------------
487 WX_DEFINE_ARRAY(wxInputHandler
*, wxArrayHandlers
);
489 class wxGTKTheme
: public wxTheme
493 virtual ~wxGTKTheme();
495 virtual wxRenderer
*GetRenderer() { return m_renderer
; }
496 virtual wxInputHandler
*GetInputHandler(const wxString
& control
);
497 virtual wxColourScheme
*GetColourScheme() { return m_scheme
; }
500 // get the default input handler
501 wxInputHandler
*GetDefaultInputHandler();
503 wxGTKRenderer
*m_renderer
;
505 // the names of the already created handlers and the handlers themselves
506 // (these arrays are synchronized)
507 wxSortedArrayString m_handlerNames
;
508 wxArrayHandlers m_handlers
;
510 wxGTKInputHandler
*m_handlerDefault
;
512 wxGTKColourScheme
*m_scheme
;
514 WX_DECLARE_THEME(gtk
)
517 // ============================================================================
519 // ============================================================================
521 WX_IMPLEMENT_THEME(wxGTKTheme
, gtk
, wxTRANSLATE("GTK+ theme"));
523 // ----------------------------------------------------------------------------
525 // ----------------------------------------------------------------------------
527 wxGTKTheme::wxGTKTheme()
529 m_scheme
= new wxGTKColourScheme
;
530 m_renderer
= new wxGTKRenderer(m_scheme
);
531 m_handlerDefault
= NULL
;
534 wxGTKTheme::~wxGTKTheme()
536 size_t count
= m_handlers
.GetCount();
537 for ( size_t n
= 0; n
< count
; n
++ )
539 if ( m_handlers
[n
] != m_handlerDefault
)
540 delete m_handlers
[n
];
543 delete m_handlerDefault
;
548 wxInputHandler
*wxGTKTheme::GetDefaultInputHandler()
550 if ( !m_handlerDefault
)
552 m_handlerDefault
= new wxGTKInputHandler(m_renderer
);
555 return m_handlerDefault
;
558 wxInputHandler
*wxGTKTheme::GetInputHandler(const wxString
& control
)
560 wxInputHandler
*handler
;
561 int n
= m_handlerNames
.Index(control
);
562 if ( n
== wxNOT_FOUND
)
564 // create a new handler
565 if ( control
== wxINP_HANDLER_SCROLLBAR
)
566 handler
= new wxGTKScrollBarInputHandler(m_renderer
,
567 GetDefaultInputHandler());
569 else if ( control
== wxINP_HANDLER_BUTTON
)
570 handler
= new wxStdButtonInputHandler(GetDefaultInputHandler());
571 #endif // wxUSE_CHECKBOX
573 else if ( control
== wxINP_HANDLER_CHECKBOX
)
574 handler
= new wxGTKCheckboxInputHandler(GetDefaultInputHandler());
575 #endif // wxUSE_CHECKBOX
577 else if ( control
== wxINP_HANDLER_COMBOBOX
)
578 handler
= new wxStdComboBoxInputHandler(GetDefaultInputHandler());
579 #endif // wxUSE_COMBOBOX
581 else if ( control
== wxINP_HANDLER_LISTBOX
)
582 handler
= new wxStdListboxInputHandler(GetDefaultInputHandler());
583 #endif // wxUSE_LISTBOX
584 #if wxUSE_CHECKLISTBOX
585 else if ( control
== wxINP_HANDLER_CHECKLISTBOX
)
586 handler
= new wxStdCheckListboxInputHandler(GetDefaultInputHandler());
587 #endif // wxUSE_CHECKLISTBOX
589 else if ( control
== wxINP_HANDLER_TEXTCTRL
)
590 handler
= new wxGTKTextCtrlInputHandler(GetDefaultInputHandler());
591 #endif // wxUSE_TEXTCTRL
593 else if ( control
== wxINP_HANDLER_SLIDER
)
594 handler
= new wxStdSliderButtonInputHandler(GetDefaultInputHandler());
595 #endif // wxUSE_SLIDER
597 else if ( control
== wxINP_HANDLER_SPINBTN
)
598 handler
= new wxStdSpinButtonInputHandler(GetDefaultInputHandler());
599 #endif // wxUSE_SPINBTN
601 else if ( control
== wxINP_HANDLER_NOTEBOOK
)
602 handler
= new wxStdNotebookInputHandler(GetDefaultInputHandler());
603 #endif // wxUSE_NOTEBOOK
605 handler
= GetDefaultInputHandler();
607 n
= m_handlerNames
.Add(control
);
608 m_handlers
.Insert(handler
, n
);
610 else // we already have it
612 handler
= m_handlers
[n
];
618 // ============================================================================
620 // ============================================================================
622 wxColour
wxGTKColourScheme::GetBackground(wxWindow
*win
) const
625 if ( win
->UseBgCol() )
627 // use the user specified colour
628 col
= win
->GetBackgroundColour();
631 if ( win
->IsContainerWindow() )
633 // doesn't depend on the state
641 int flags
= win
->GetStateFlags();
643 // the colour set by the user should be used for the normal state
644 // and for the states for which we don't have any specific colours
645 if ( !col
.Ok() || (flags
!= 0) )
647 if ( wxDynamicCast(win
, wxScrollBar
) )
648 col
= Get(SCROLLBAR
);
649 else if ( (flags
& wxCONTROL_CURRENT
) && win
->CanBeHighlighted() )
650 col
= Get(CONTROL_CURRENT
);
651 else if ( flags
& wxCONTROL_PRESSED
)
652 col
= Get(CONTROL_PRESSED
);
661 wxColour
wxGTKColourScheme::Get(wxGTKColourScheme::StdColour col
) const
665 case WINDOW
: return *wxWHITE
;
667 case SHADOW_DARK
: return *wxBLACK
;
668 case SHADOW_HIGHLIGHT
: return *wxWHITE
;
669 case SHADOW_IN
: return wxColour(0xd6d6d6);
670 case SHADOW_OUT
: return wxColour(0x969696);
672 case CONTROL
: return wxColour(0xd6d6d6);
673 case CONTROL_PRESSED
: return wxColour(0xc3c3c3);
674 case CONTROL_CURRENT
: return wxColour(0xeaeaea);
676 case CONTROL_TEXT
: return *wxBLACK
;
677 case CONTROL_TEXT_DISABLED
:
678 return wxColour(0x757575);
679 case CONTROL_TEXT_DISABLED_SHADOW
:
683 case SCROLLBAR_PRESSED
: return wxColour(0xc3c3c3);
685 case HIGHLIGHT
: return wxColour(0x9c0000);
686 case HIGHLIGHT_TEXT
: return wxColour(0xffffff);
690 wxFAIL_MSG(_T("invalid standard colour"));
695 // ============================================================================
697 // ============================================================================
699 // ----------------------------------------------------------------------------
701 // ----------------------------------------------------------------------------
703 wxGTKRenderer::wxGTKRenderer(const wxColourScheme
*scheme
)
707 m_sizeScrollbarArrow
= wxSize(15, 14);
710 m_penBlack
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_DARK
), 0, wxSOLID
);
711 m_penDarkGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_OUT
), 0, wxSOLID
);
712 m_penGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SCROLLBAR
), 0, wxSOLID
);
713 m_penLightGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_IN
), 0, wxSOLID
);
714 m_penHighlight
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_HIGHLIGHT
), 0, wxSOLID
);
717 // ----------------------------------------------------------------------------
719 // ----------------------------------------------------------------------------
721 void wxGTKRenderer::DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
725 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
726 dc
.DrawRectangle(*rect
);
732 void wxGTKRenderer::DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
734 // draw the bottom and right sides
736 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
737 rect
->GetRight() + 1, rect
->GetBottom());
738 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
739 rect
->GetRight(), rect
->GetBottom());
746 void wxGTKRenderer::DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
747 const wxPen
& pen1
, const wxPen
& pen2
)
749 // draw the rectangle
751 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
752 rect
->GetLeft(), rect
->GetBottom());
753 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
754 rect
->GetRight(), rect
->GetTop());
756 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
757 rect
->GetRight(), rect
->GetBottom());
758 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
759 rect
->GetRight() + 1, rect
->GetBottom());
765 void wxGTKRenderer::DrawAntiShadedRectSide(wxDC
& dc
,
771 dc
.SetPen(dir
== wxLEFT
|| dir
== wxUP
? pen1
: pen2
);
776 dc
.DrawLine(rect
.GetLeft(), rect
.GetTop(),
777 rect
.GetLeft(), rect
.GetBottom() + 1);
781 dc
.DrawLine(rect
.GetLeft(), rect
.GetTop(),
782 rect
.GetRight() + 1, rect
.GetTop());
786 dc
.DrawLine(rect
.GetRight(), rect
.GetTop(),
787 rect
.GetRight(), rect
.GetBottom() + 1);
791 dc
.DrawLine(rect
.GetLeft(), rect
.GetBottom(),
792 rect
.GetRight() + 1, rect
.GetBottom());
796 wxFAIL_MSG(_T("unknown rectangle side"));
800 void wxGTKRenderer::DrawAntiShadedRect(wxDC
& dc
, wxRect
*rect
,
801 const wxPen
& pen1
, const wxPen
& pen2
)
803 // draw the rectangle
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());
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());
819 void wxGTKRenderer::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
821 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
822 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
825 void wxGTKRenderer::DrawAntiRaisedBorder(wxDC
& dc
, wxRect
*rect
)
827 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
828 DrawAntiShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
831 void wxGTKRenderer::DrawBorder(wxDC
& dc
,
833 const wxRect
& rectTotal
,
839 wxRect rect
= rectTotal
;
843 case wxBORDER_SUNKEN
:
844 for ( width
= 0; width
< BORDER_THICKNESS
; width
++ )
846 DrawAntiShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
847 DrawShadedRect(dc
, &rect
, m_penBlack
, m_penLightGrey
);
851 case wxBORDER_STATIC
:
852 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
855 case wxBORDER_RAISED
:
856 for ( width
= 0; width
< BORDER_THICKNESS
; width
++ )
858 DrawRaisedBorder(dc
, &rect
);
862 case wxBORDER_DOUBLE
:
863 DrawShadedRect(dc
, &rect
, m_penLightGrey
, m_penBlack
);
864 DrawShadedRect(dc
, &rect
, m_penHighlight
, m_penDarkGrey
);
865 DrawRect(dc
, &rect
, m_penLightGrey
);
868 case wxBORDER_SIMPLE
:
869 DrawRect(dc
, &rect
, m_penBlack
);
873 wxFAIL_MSG(_T("unknown border type"));
876 case wxBORDER_DEFAULT
:
885 wxRect
wxGTKRenderer::GetBorderDimensions(wxBorder border
) const
890 case wxBORDER_RAISED
:
891 case wxBORDER_SUNKEN
:
892 width
= 2*BORDER_THICKNESS
;
895 case wxBORDER_SIMPLE
:
896 case wxBORDER_STATIC
:
900 case wxBORDER_DOUBLE
:
905 wxFAIL_MSG(_T("unknown border type"));
908 case wxBORDER_DEFAULT
:
923 bool wxGTKRenderer::AreScrollbarsInsideBorder() const
925 // no, the scrollbars are outside the border in GTK+
929 // ----------------------------------------------------------------------------
931 // ----------------------------------------------------------------------------
933 void wxGTKRenderer::DrawTextBorder(wxDC
& dc
,
935 const wxRect
& rectOrig
,
939 wxRect rect
= rectOrig
;
941 if ( flags
& wxCONTROL_FOCUSED
)
943 DrawRect(dc
, &rect
, m_penBlack
);
944 DrawAntiShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
948 DrawAntiShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
949 DrawAntiShadedRect(dc
, &rect
, m_penBlack
, m_penHighlight
);
956 void wxGTKRenderer::DrawButtonBorder(wxDC
& dc
,
957 const wxRect
& rectTotal
,
961 wxRect rect
= rectTotal
;
963 if ( flags
& wxCONTROL_PRESSED
)
965 // button pressed: draw a black border around it and an inward shade
966 DrawRect(dc
, &rect
, m_penBlack
);
967 DrawAntiShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
968 DrawAntiShadedRect(dc
, &rect
, m_penBlack
, m_penDarkGrey
);
972 // button not pressed
974 if ( flags
& wxCONTROL_ISDEFAULT
)
979 if ( flags
& wxCONTROL_FOCUSED
)
981 // button is currently default: add an extra border around it
982 DrawRect(dc
, &rect
, m_penBlack
);
985 // now draw a normal button
986 DrawShadedRect(dc
, &rect
, m_penHighlight
, m_penBlack
);
987 DrawAntiShadedRect(dc
, &rect
,
988 wxPen(GetBackgroundColour(flags
), 0, wxSOLID
),
998 // ----------------------------------------------------------------------------
1000 // ----------------------------------------------------------------------------
1002 void wxGTKRenderer::DrawHorizontalLine(wxDC
& dc
,
1003 wxCoord y
, wxCoord x1
, wxCoord x2
)
1005 dc
.SetPen(m_penDarkGrey
);
1006 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1007 dc
.SetPen(m_penHighlight
);
1009 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1012 void wxGTKRenderer::DrawVerticalLine(wxDC
& dc
,
1013 wxCoord x
, wxCoord y1
, wxCoord y2
)
1015 dc
.SetPen(m_penDarkGrey
);
1016 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1017 dc
.SetPen(m_penHighlight
);
1019 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1022 void wxGTKRenderer::DrawFrame(wxDC
& dc
,
1023 const wxString
& label
,
1029 wxCoord height
= 0; // of the label
1030 wxRect rectFrame
= rect
;
1031 if ( !label
.empty() )
1033 // the text should touch the top border of the rect, so the frame
1034 // itself should be lower
1035 dc
.GetTextExtent(label
, NULL
, &height
);
1036 rectFrame
.y
+= height
/ 2;
1037 rectFrame
.height
-= height
/ 2;
1039 // TODO: the +4 should be customizable
1042 rectText
.x
= rectFrame
.x
+ 4;
1043 rectText
.y
= rect
.y
;
1044 rectText
.width
= rectFrame
.width
- 8;
1045 rectText
.height
= height
;
1048 DrawLabel(dc
, label
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
1050 rectLabel
.width
+= 2;
1052 StandardDrawFrame(dc
, rectFrame
, rectLabel
);
1054 // GTK+ does it like this
1055 dc
.SetPen(m_penHighlight
);
1056 dc
.DrawPoint(rectText
.x
, rectFrame
.y
);
1057 dc
.DrawPoint(rectText
.x
+ rectLabel
.width
- 3, rectFrame
.y
);
1061 // just draw the complete frame
1062 DrawShadedRect(dc
, &rectFrame
, m_penDarkGrey
, m_penHighlight
);
1063 DrawShadedRect(dc
, &rectFrame
, m_penHighlight
, m_penDarkGrey
);
1067 // ----------------------------------------------------------------------------
1069 // ----------------------------------------------------------------------------
1071 void wxGTKRenderer::DrawLabel(wxDC
& dc
,
1072 const wxString
& label
,
1079 DrawButtonLabel(dc
, label
, wxNullBitmap
, rect
, flags
,
1080 alignment
, indexAccel
, rectBounds
);
1083 void wxGTKRenderer::DrawButtonLabel(wxDC
& dc
,
1084 const wxString
& label
,
1085 const wxBitmap
& image
,
1092 if ( flags
& wxCONTROL_DISABLED
)
1094 // make the text grey and draw a shade for it
1095 dc
.SetTextForeground(*wxWHITE
); // FIXME hardcoded colour
1096 wxRect rectShadow
= rect
;
1099 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
1100 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, CONTROL_TEXT_DISABLED
));
1103 dc
.DrawLabel(label
, image
, rect
, alignment
, indexAccel
, rectBounds
);
1106 void wxGTKRenderer::DrawItem(wxDC
& dc
,
1107 const wxString
& label
,
1111 wxLogTrace(_T("listbox"), _T("drawing item '%s' at (%d, %d)-(%d, %d)"),
1114 rect
.x
+ rect
.width
, rect
.y
+ rect
.height
);
1117 if ( flags
& wxCONTROL_SELECTED
)
1119 dc
.SetBrush(wxBrush(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
), wxSOLID
));
1120 dc
.SetPen(*wxTRANSPARENT_PEN
);
1121 dc
.DrawRectangle(rect
);
1123 colFg
= dc
.GetTextForeground();
1124 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
1127 if ( flags
& wxCONTROL_FOCUSED
)
1129 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1130 wxRect rectFocus
= rect
;
1131 DrawRect(dc
, &rectFocus
, m_penBlack
);
1134 wxRect rectText
= rect
;
1137 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
1139 if ( flags
& wxCONTROL_SELECTED
)
1141 dc
.SetBackgroundMode(wxTRANSPARENT
);
1144 // restore the text colour
1147 dc
.SetTextForeground(colFg
);
1151 void wxGTKRenderer::DrawCheckItem(wxDC
& dc
,
1152 const wxString
& label
,
1153 const wxBitmap
& bitmap
,
1157 wxRect rectBitmap
= rect
;
1159 rectBitmap
.width
= GetCheckBitmapSize().x
;
1160 // never draw the focus rect around the check indicators here
1161 DrawCheckButton(dc
, _T(""), bitmap
, rectBitmap
, flags
& ~wxCONTROL_FOCUSED
);
1163 wxRect rectLabel
= rect
;
1164 wxCoord shift
= rectBitmap
.width
+ 2*GetCheckItemMargin();
1165 rectLabel
.x
+= shift
;
1166 rectLabel
.width
-= shift
;
1167 DrawItem(dc
, label
, rectLabel
, flags
);
1170 // ----------------------------------------------------------------------------
1171 // check/radion buttons
1172 // ----------------------------------------------------------------------------
1174 void wxGTKRenderer::DrawUncheckBitmap(wxDC
& dc
,
1175 const wxRect
& rectTotal
,
1178 wxRect rect
= rectTotal
;
1179 DrawAntiRaisedBorder(dc
, &rect
);
1181 wxColour col
= wxSCHEME_COLOUR(m_scheme
, SHADOW_IN
);
1182 dc
.SetPen(wxPen(col
, 0, wxSOLID
));
1183 dc
.DrawPoint(rect
.GetRight() - 1, rect
.GetBottom() - 1);
1186 col
= wxSCHEME_COLOUR(m_scheme
, CONTROL_PRESSED
);
1187 //else: it is SHADOW_IN, leave as is
1189 dc
.SetPen(*wxTRANSPARENT_PEN
);
1190 dc
.SetBrush(wxBrush(col
, wxSOLID
));
1191 dc
.DrawRectangle(rect
);
1194 void wxGTKRenderer::DrawCheckBitmap(wxDC
& dc
, const wxRect
& rectTotal
)
1196 wxRect rect
= rectTotal
;
1197 DrawAntiShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
1198 DrawShadedRect(dc
, &rect
, m_penBlack
, m_penLightGrey
);
1200 dc
.SetPen(*wxTRANSPARENT_PEN
);
1201 dc
.SetBrush(wxBrush(wxSCHEME_COLOUR(m_scheme
, CONTROL_PRESSED
), wxSOLID
));
1202 dc
.DrawRectangle(rect
);
1205 void wxGTKRenderer::DrawRadioBitmap(wxDC
& dc
,
1211 xRight
= rect
.GetRight(),
1212 yBottom
= rect
.GetBottom();
1214 wxCoord yMid
= (y
+ yBottom
) / 2;
1216 // this looks ugly when the background colour of the control is not the
1217 // same ours - radiobox is not transparent as it should be
1219 // first fill the middle: as FloodFill() is not implemented on all
1220 // platforms, this is the only thing to do
1221 wxColour colBg
= flags
& wxCONTROL_CURRENT
1222 ? wxSCHEME_COLOUR(m_scheme
, CONTROL_CURRENT
)
1223 : wxSCHEME_COLOUR(m_scheme
, SHADOW_IN
);
1224 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
1225 dc
.SetPen(*wxTRANSPARENT_PEN
);
1226 dc
.DrawRectangle(rect
);
1229 // then draw the upper half
1230 dc
.SetPen(flags
& wxCONTROL_CHECKED
? m_penDarkGrey
: m_penHighlight
);
1231 DrawUpZag(dc
, x
, xRight
, yMid
, y
);
1232 DrawUpZag(dc
, x
+ 1, xRight
- 1, yMid
, y
+ 1);
1235 if ( flags
& wxCONTROL_CHECKED
)
1236 dc
.SetPen(m_penBlack
);
1237 else if ( flags
& wxCONTROL_PRESSED
)
1238 dc
.SetPen(wxPen(wxSCHEME_COLOUR(m_scheme
, CONTROL_PRESSED
), 0, wxSOLID
));
1239 else // unchecked and unpressed
1243 DrawUpZag(dc
, x
+ 2, xRight
- 2, yMid
, y
+ 2);
1245 // and then the lower one
1246 dc
.SetPen(flags
& wxCONTROL_CHECKED
? m_penHighlight
: m_penBlack
);
1247 DrawDownZag(dc
, x
, xRight
, yMid
, yBottom
);
1248 if ( !(flags
& wxCONTROL_CHECKED
) )
1249 dc
.SetPen(m_penDarkGrey
);
1250 DrawDownZag(dc
, x
+ 1, xRight
- 1, yMid
, yBottom
- 1);
1252 if ( !(flags
& wxCONTROL_CHECKED
) )
1253 drawIt
= TRUE
; // with the same pen
1254 else if ( flags
& wxCONTROL_PRESSED
)
1256 dc
.SetPen(wxPen(wxSCHEME_COLOUR(m_scheme
, CONTROL_PRESSED
), 0, wxSOLID
));
1259 else // checked and unpressed
1263 DrawDownZag(dc
, x
+ 2, xRight
- 2, yMid
, yBottom
- 2);
1266 void wxGTKRenderer::DrawUpZag(wxDC
& dc
,
1272 wxCoord xMid
= (x1
+ x2
) / 2;
1273 dc
.DrawLine(x1
, y1
, xMid
, y2
);
1274 dc
.DrawLine(xMid
, y2
, x2
+ 1, y1
+ 1);
1277 void wxGTKRenderer::DrawDownZag(wxDC
& dc
,
1283 wxCoord xMid
= (x1
+ x2
) / 2;
1284 dc
.DrawLine(x1
+ 1, y1
+ 1, xMid
, y2
);
1285 dc
.DrawLine(xMid
, y2
, x2
, y1
);
1288 wxBitmap
wxGTKRenderer::GetCheckBitmap(int flags
)
1290 if ( !m_bitmapsCheckbox
[0][0].Ok() )
1292 // init the bitmaps once only
1294 wxSize size
= GetCheckBitmapSize();
1295 rect
.width
= size
.x
;
1296 rect
.height
= size
.y
;
1297 for ( int i
= 0; i
< 2; i
++ )
1299 for ( int j
= 0; j
< 2; j
++ )
1300 m_bitmapsCheckbox
[i
][j
].Create(rect
.width
, rect
.height
);
1306 dc
.SelectObject(m_bitmapsCheckbox
[0][0]);
1307 DrawCheckBitmap(dc
, rect
);
1310 dc
.SelectObject(m_bitmapsCheckbox
[0][1]);
1311 DrawUncheckBitmap(dc
, rect
, FALSE
);
1314 m_bitmapsCheckbox
[1][0] = m_bitmapsCheckbox
[0][0];
1316 // pressed unchecked
1317 dc
.SelectObject(m_bitmapsCheckbox
[1][1]);
1318 DrawUncheckBitmap(dc
, rect
, TRUE
);
1321 int row
= flags
& wxCONTROL_PRESSED
? 1 : 0;
1322 int col
= flags
& wxCONTROL_CHECKED
? 0 : 1;
1324 return m_bitmapsCheckbox
[row
][col
];
1327 wxBitmap
wxGTKRenderer::GetLineWrapBitmap()
1329 if ( !m_bmpLineWrap
.Ok() )
1331 // the line wrap bitmap as used by GTK+
1332 #define line_wrap_width 6
1333 #define line_wrap_height 9
1334 static const char line_wrap_bits
[] =
1336 0x1e, 0x3e, 0x30, 0x30, 0x39, 0x1f, 0x0f, 0x0f, 0x1f,
1339 wxBitmap
bmpLineWrap(line_wrap_bits
, line_wrap_width
, line_wrap_height
);
1340 if ( !bmpLineWrap
.Ok() )
1342 wxFAIL_MSG( _T("Failed to create line wrap XBM") );
1346 m_bmpLineWrap
= bmpLineWrap
;
1350 return m_bmpLineWrap
;
1353 void wxGTKRenderer::DrawCheckButton(wxDC
& dc
,
1354 const wxString
& label
,
1355 const wxBitmap
& bitmapOrig
,
1356 const wxRect
& rectTotal
,
1362 if ( bitmapOrig
.Ok() )
1364 bitmap
= bitmapOrig
;
1368 bitmap
= GetCheckBitmap(flags
);
1371 DoDrawCheckOrRadioBitmap(dc
, label
, bitmap
, rectTotal
,
1372 flags
, align
, indexAccel
);
1375 void wxGTKRenderer::DoDrawCheckOrRadioBitmap(wxDC
& dc
,
1376 const wxString
& label
,
1377 const wxBitmap
& bitmap
,
1378 const wxRect
& rectTotal
,
1383 wxRect rect
= rectTotal
;
1385 if ( flags
& wxCONTROL_FOCUSED
)
1387 // draw the focus border around everything
1388 DrawRect(dc
, &rect
, m_penBlack
);
1392 // the border does not offset the string under GTK
1396 // calculate the position of the bitmap and of the label
1398 yBmp
= rect
.y
+ (rect
.height
- bitmap
.GetHeight()) / 2;
1401 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
1402 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
1404 if ( align
== wxALIGN_RIGHT
)
1406 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
1407 rectLabel
.x
= rect
.x
+ 2;
1408 rectLabel
.SetRight(xBmp
);
1410 else // normal (checkbox to the left of the text) case
1413 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 4;
1414 rectLabel
.SetRight(rect
.GetRight());
1417 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, TRUE
/* use mask */);
1419 DrawLabel(dc
, label
, rectLabel
, flags
,
1420 wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
, indexAccel
);
1423 void wxGTKRenderer::DrawRadioButton(wxDC
& dc
,
1424 const wxString
& label
,
1425 const wxBitmap
& bitmapOrig
,
1426 const wxRect
& rectTotal
,
1432 if ( bitmapOrig
.Ok() )
1434 bitmap
= bitmapOrig
;
1439 wxSize size
= GetRadioBitmapSize();
1440 rect
.width
= size
.x
;
1441 rect
.height
= size
.y
;
1442 bitmap
.Create(rect
.width
, rect
.height
);
1444 dc
.SelectObject(bitmap
);
1445 dc
.SetBackground(*wxLIGHT_GREY_BRUSH
);
1447 DrawRadioBitmap(dc
, rect
, flags
);
1448 bitmap
.SetMask(new wxMask(bitmap
, *wxLIGHT_GREY
));
1451 DoDrawCheckOrRadioBitmap(dc
, label
, bitmap
, rectTotal
,
1452 flags
, align
, indexAccel
);
1455 // ----------------------------------------------------------------------------
1457 // ----------------------------------------------------------------------------
1459 static const int TEXT_BORDER
= 2;
1461 wxRect
wxGTKRenderer::GetTextTotalArea(const wxTextCtrl
*text
,
1464 wxRect rectTotal
= rect
;
1465 rectTotal
.Inflate(TEXT_BORDER
);
1469 wxRect
wxGTKRenderer::GetTextClientArea(const wxTextCtrl
*text
,
1471 wxCoord
*extraSpaceBeyond
)
1473 wxRect rectText
= rect
;
1474 rectText
.Inflate(-TEXT_BORDER
);
1476 if ( text
->WrapLines() )
1478 // leave enough for the line wrap bitmap indicator
1479 wxCoord widthMark
= GetLineWrapBitmap().GetWidth() + 2;
1481 rectText
.width
-= widthMark
;
1483 if ( extraSpaceBeyond
)
1484 *extraSpaceBeyond
= widthMark
;
1490 void wxGTKRenderer::DrawTextLine(wxDC
& dc
,
1491 const wxString
& text
,
1497 // TODO: GTK+ draws selection even for unfocused controls, just with
1498 // different colours
1499 StandardDrawTextLine(dc
, text
, rect
, selStart
, selEnd
, flags
);
1502 void wxGTKRenderer::DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
)
1504 wxBitmap bmpLineWrap
= GetLineWrapBitmap();
1506 // for a mono bitmap he colours it appears in depends on the current text
1507 // colours, so set them correctly
1509 if ( bmpLineWrap
.GetDepth() == 1 )
1511 colFgOld
= dc
.GetTextForeground();
1513 // FIXME: I wonder what should we do if the background is black too?
1514 dc
.SetTextForeground(*wxBLACK
);
1517 dc
.DrawBitmap(bmpLineWrap
,
1518 rect
.x
, rect
.y
+ (rect
.height
- bmpLineWrap
.GetHeight())/2);
1520 if ( colFgOld
.Ok() )
1522 // restore old colour
1523 dc
.SetTextForeground(colFgOld
);
1527 // ----------------------------------------------------------------------------
1529 // ----------------------------------------------------------------------------
1531 void wxGTKRenderer::DrawTab(wxDC
& dc
,
1532 const wxRect
& rectOrig
,
1534 const wxString
& label
,
1535 const wxBitmap
& bitmap
,
1539 wxRect rect
= rectOrig
;
1541 // the current tab is drawn indented (to the top for default case) and
1542 // bigger than the other ones
1543 const wxSize indent
= GetTabIndent();
1544 if ( flags
& wxCONTROL_SELECTED
)
1549 wxFAIL_MSG(_T("invaild notebook tab orientation"));
1553 rect
.Inflate(indent
.x
, 0);
1555 rect
.height
+= indent
.y
;
1559 rect
.Inflate(indent
.x
, 0);
1560 rect
.height
+= indent
.y
;
1565 wxFAIL_MSG(_T("TODO"));
1570 // selected tab has different colour
1571 wxColour col
= flags
& wxCONTROL_SELECTED
1572 ? wxSCHEME_COLOUR(m_scheme
, SHADOW_IN
)
1573 : wxSCHEME_COLOUR(m_scheme
, SCROLLBAR
);
1574 DoDrawBackground(dc
, col
, rect
);
1576 if ( flags
& wxCONTROL_FOCUSED
)
1578 // draw the focus rect
1579 wxRect rectBorder
= rect
;
1580 rectBorder
.Deflate(4, 3);
1581 if ( dir
== wxBOTTOM
)
1582 rectBorder
.Offset(0, -1);
1584 DrawRect(dc
, &rectBorder
, m_penBlack
);
1587 // draw the text, image and the focus around them (if necessary)
1588 wxRect rectLabel
= rect
;
1589 rectLabel
.Deflate(1, 1);
1590 dc
.DrawLabel(label
, bitmap
, rectLabel
, wxALIGN_CENTRE
, indexAccel
);
1592 // now draw the tab itself
1595 x2
= rect
.GetRight(),
1596 y2
= rect
.GetBottom();
1601 dc
.SetPen(m_penHighlight
);
1602 dc
.DrawLine(x
, y2
, x
, y
);
1603 dc
.DrawLine(x
+ 1, y
, x2
, y
);
1605 dc
.SetPen(m_penBlack
);
1606 dc
.DrawLine(x2
, y2
, x2
, y
);
1608 dc
.SetPen(m_penDarkGrey
);
1609 dc
.DrawLine(x2
- 1, y2
, x2
- 1, y
+ 1);
1611 if ( flags
& wxCONTROL_SELECTED
)
1613 dc
.SetPen(m_penLightGrey
);
1615 // overwrite the part of the border below this tab
1616 dc
.DrawLine(x
+ 1, y2
+ 1, x2
- 1, y2
+ 1);
1618 // and the shadow of the tab to the left of us
1619 dc
.DrawLine(x
+ 1, y
+ 2, x
+ 1, y2
+ 1);
1624 dc
.SetPen(m_penHighlight
);
1626 // we need to continue one pixel further to overwrite the corner of
1627 // the border for the selected tab
1628 dc
.DrawLine(x
, y
- (flags
& wxCONTROL_SELECTED
? 1 : 0),
1631 // it doesn't work like this (TODO: implement it properly)
1633 // erase the corner of the tab to the right
1634 dc
.SetPen(m_penLightGrey
);
1635 dc
.DrawPoint(x2
- 1, y
- 2);
1636 dc
.DrawPoint(x2
- 2, y
- 2);
1637 dc
.DrawPoint(x2
- 2, y
- 1);
1640 dc
.SetPen(m_penBlack
);
1641 dc
.DrawLine(x
+ 1, y2
, x2
, y2
);
1642 dc
.DrawLine(x2
, y
, x2
, y2
);
1644 dc
.SetPen(m_penDarkGrey
);
1645 dc
.DrawLine(x
+ 2, y2
- 1, x2
- 1, y2
- 1);
1646 dc
.DrawLine(x2
- 1, y
, x2
- 1, y2
);
1648 if ( flags
& wxCONTROL_SELECTED
)
1650 dc
.SetPen(m_penLightGrey
);
1652 // overwrite the part of the (double!) border above this tab
1653 dc
.DrawLine(x
+ 1, y
- 1, x2
- 1, y
- 1);
1654 dc
.DrawLine(x
+ 1, y
- 2, x2
- 1, y
- 2);
1656 // and the shadow of the tab to the left of us
1657 dc
.DrawLine(x
+ 1, y2
- 1, x
+ 1, y
- 1);
1663 wxFAIL_MSG(_T("TODO"));
1667 // ----------------------------------------------------------------------------
1669 // ----------------------------------------------------------------------------
1671 wxSize
wxGTKRenderer::GetSliderThumbSize(const wxRect
& rect
,
1672 wxOrientation orient
) const
1674 static const wxCoord SLIDER_THUMB_LENGTH
= 30;
1678 wxRect rectShaft
= GetSliderShaftRect(rect
, orient
);
1679 if ( orient
== wxHORIZONTAL
)
1681 size
.x
= wxMin(SLIDER_THUMB_LENGTH
, rectShaft
.width
);
1682 size
.y
= rectShaft
.height
;
1686 size
.y
= wxMin(SLIDER_THUMB_LENGTH
, rectShaft
.height
);
1687 size
.x
= rectShaft
.width
;
1693 wxRect
wxGTKRenderer::GetSliderShaftRect(const wxRect
& rect
,
1694 wxOrientation
WXUNUSED(orient
)) const
1696 return rect
.Deflate(2*BORDER_THICKNESS
, 2*BORDER_THICKNESS
);
1699 void wxGTKRenderer::DrawSliderShaft(wxDC
& dc
,
1700 const wxRect
& rectOrig
,
1701 wxOrientation orient
,
1705 wxRect rect
= rectOrig
;
1707 // draw the border first
1708 if ( flags
& wxCONTROL_FOCUSED
)
1710 DrawRect(dc
, &rect
, m_penBlack
);
1711 DrawAntiShadedRect(dc
, &rect
, m_penBlack
, m_penLightGrey
);
1713 else // not focused, normal
1715 DrawAntiShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
1716 DrawAntiShadedRect(dc
, &rect
, m_penBlack
, m_penLightGrey
);
1719 // and the background
1720 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, SCROLLBAR
), rect
);
1726 void wxGTKRenderer::DrawSliderThumb(wxDC
& dc
,
1727 const wxRect
& rectOrig
,
1728 wxOrientation orient
,
1731 // draw the thumb border
1732 wxRect rect
= rectOrig
;
1733 DrawAntiRaisedBorder(dc
, &rect
);
1735 // draw the handle in the middle
1736 if ( orient
== wxVERTICAL
)
1738 rect
.height
= 2*BORDER_THICKNESS
;
1739 rect
.y
= rectOrig
.y
+ (rectOrig
.height
- rect
.height
) / 2;
1743 rect
.width
= 2*BORDER_THICKNESS
;
1744 rect
.x
= rectOrig
.x
+ (rectOrig
.width
- rect
.width
) / 2;
1747 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
1751 // ----------------------------------------------------------------------------
1753 // ----------------------------------------------------------------------------
1755 void wxGTKRenderer::DrawMenuBarItem(wxDC
& dc
,
1757 const wxString
& label
,
1761 DrawLabel(dc
, label
, rect
, flags
, wxALIGN_CENTRE
, indexAccel
);
1764 void wxGTKRenderer::DrawMenuItem(wxDC
& dc
,
1766 const wxMenuGeometryInfo
& geometryInfo
,
1767 const wxString
& label
,
1768 const wxString
& accel
,
1769 const wxBitmap
& bitmap
,
1773 wxFAIL_MSG(_T("TODO"));
1776 void wxGTKRenderer::DrawMenuSeparator(wxDC
& dc
,
1778 const wxMenuGeometryInfo
& geomInfo
)
1780 wxFAIL_MSG(_T("TODO"));
1783 wxSize
wxGTKRenderer::GetMenuBarItemSize(const wxSize
& sizeText
) const
1788 wxMenuGeometryInfo
*wxGTKRenderer::GetMenuGeometry(wxWindow
*win
,
1789 const wxMenu
& menu
) const
1791 wxFAIL_MSG(_T("TODO"));
1796 // ----------------------------------------------------------------------------
1798 // ----------------------------------------------------------------------------
1800 void wxGTKRenderer::GetComboBitmaps(wxBitmap
*bmpNormal
,
1801 wxBitmap
*bmpPressed
,
1802 wxBitmap
*bmpDisabled
)
1807 // ----------------------------------------------------------------------------
1809 // ----------------------------------------------------------------------------
1811 void wxGTKRenderer::DoDrawBackground(wxDC
& dc
,
1812 const wxColour
& col
,
1815 wxBrush
brush(col
, wxSOLID
);
1817 dc
.SetPen(*wxTRANSPARENT_PEN
);
1818 dc
.DrawRectangle(rect
);
1821 void wxGTKRenderer::DrawBackground(wxDC
& dc
,
1822 const wxColour
& col
,
1826 wxColour colBg
= col
.Ok() ? col
: GetBackgroundColour(flags
);
1827 DoDrawBackground(dc
, colBg
, rect
);
1830 // ----------------------------------------------------------------------------
1832 // ----------------------------------------------------------------------------
1834 void wxGTKRenderer::DrawArrowBorder(wxDC
& dc
,
1838 static const wxDirection sides
[] =
1840 wxUP
, wxLEFT
, wxRIGHT
, wxDOWN
1843 wxRect rect1
, rect2
, rectInner
;
1849 rectInner
.Inflate(-2);
1851 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, SCROLLBAR
), *rect
);
1853 // find the side not to draw and also adjust the rectangles to compensate
1855 wxDirection sideToOmit
;
1859 sideToOmit
= wxDOWN
;
1861 rectInner
.height
+= 1;
1869 rectInner
.height
+= 1;
1873 sideToOmit
= wxRIGHT
;
1875 rectInner
.width
+= 1;
1879 sideToOmit
= wxLEFT
;
1883 rectInner
.width
+= 1;
1887 wxFAIL_MSG(_T("unknown arrow direction"));
1891 // the outer rect first
1893 for ( n
= 0; n
< WXSIZEOF(sides
); n
++ )
1895 wxDirection side
= sides
[n
];
1896 if ( side
== sideToOmit
)
1899 DrawAntiShadedRectSide(dc
, rect1
, m_penDarkGrey
, m_penHighlight
, side
);
1902 // and then the inner one
1903 for ( n
= 0; n
< WXSIZEOF(sides
); n
++ )
1905 wxDirection side
= sides
[n
];
1906 if ( side
== sideToOmit
)
1909 DrawAntiShadedRectSide(dc
, rect2
, m_penBlack
, m_penGrey
, side
);
1915 void wxGTKRenderer::DrawScrollbarArrow(wxDC
& dc
,
1917 const wxRect
& rectArrow
,
1920 // first of all, draw the border around it - but we don't want the border
1921 // on the side opposite to the arrow point
1922 wxRect rect
= rectArrow
;
1923 DrawArrowBorder(dc
, &rect
, dir
);
1925 // then the arrow itself
1926 DrawArrow(dc
, dir
, rect
, flags
);
1929 // gtk_default_draw_arrow() takes ~350 lines and we can't do much better here
1930 // these people are just crazy :-(
1931 void wxGTKRenderer::DrawArrow(wxDC
& dc
,
1944 wxPoint ptArrow
[Point_Max
];
1946 wxColour colInside
= GetBackgroundColour(flags
);
1948 if ( flags
& wxCONTROL_DISABLED
)
1950 penShadow
[0] = m_penDarkGrey
;
1951 penShadow
[1] = m_penDarkGrey
;
1952 penShadow
[2] = wxNullPen
;
1953 penShadow
[3] = wxNullPen
;
1955 else if ( flags
& wxCONTROL_PRESSED
)
1957 penShadow
[0] = m_penDarkGrey
;
1958 penShadow
[1] = m_penHighlight
;
1959 penShadow
[2] = wxNullPen
;
1960 penShadow
[3] = m_penBlack
;
1962 else // normal arrow
1964 penShadow
[0] = m_penHighlight
;
1965 penShadow
[1] = m_penBlack
;
1966 penShadow
[2] = m_penDarkGrey
;
1967 penShadow
[3] = wxNullPen
;
1971 if ( dir
== wxUP
|| dir
== wxDOWN
)
1974 middle
= (rect
.GetRight() + rect
.GetLeft() + 1) / 2;
1978 middle
= (rect
.GetTop() + rect
.GetBottom() + 1) / 2;
1981 // draw the arrow interior
1982 dc
.SetPen(*wxTRANSPARENT_PEN
);
1983 dc
.SetBrush(wxBrush(colInside
, wxSOLID
));
1988 ptArrow
[Point_First
].x
= rect
.GetLeft();
1989 ptArrow
[Point_First
].y
= rect
.GetBottom();
1990 ptArrow
[Point_Second
].x
= middle
;
1991 ptArrow
[Point_Second
].y
= rect
.GetTop();
1992 ptArrow
[Point_Third
].x
= rect
.GetRight();
1993 ptArrow
[Point_Third
].y
= rect
.GetBottom();
1997 ptArrow
[Point_First
] = rect
.GetPosition();
1998 ptArrow
[Point_Second
].x
= middle
;
1999 ptArrow
[Point_Second
].y
= rect
.GetBottom();
2000 ptArrow
[Point_Third
].x
= rect
.GetRight();
2001 ptArrow
[Point_Third
].y
= rect
.GetTop();
2005 ptArrow
[Point_First
].x
= rect
.GetRight();
2006 ptArrow
[Point_First
].y
= rect
.GetTop();
2007 ptArrow
[Point_Second
].x
= rect
.GetLeft();
2008 ptArrow
[Point_Second
].y
= middle
;
2009 ptArrow
[Point_Third
].x
= rect
.GetRight();
2010 ptArrow
[Point_Third
].y
= rect
.GetBottom();
2014 ptArrow
[Point_First
] = rect
.GetPosition();
2015 ptArrow
[Point_Second
].x
= rect
.GetRight();
2016 ptArrow
[Point_Second
].y
= middle
;
2017 ptArrow
[Point_Third
].x
= rect
.GetLeft();
2018 ptArrow
[Point_Third
].y
= rect
.GetBottom();
2022 wxFAIL_MSG(_T("unknown arrow direction"));
2025 dc
.DrawPolygon(WXSIZEOF(ptArrow
), ptArrow
);
2027 // draw the arrow border
2028 dc
.SetPen(penShadow
[0]);
2032 dc
.DrawLine(ptArrow
[Point_Second
], ptArrow
[Point_First
]);
2033 dc
.DrawPoint(ptArrow
[Point_First
]);
2034 if ( penShadow
[3].Ok() )
2036 dc
.SetPen(penShadow
[3]);
2037 dc
.DrawLine(ptArrow
[Point_First
].x
+ 1, ptArrow
[Point_First
].y
,
2038 ptArrow
[Point_Second
].x
, ptArrow
[Point_Second
].y
);
2040 dc
.SetPen(penShadow
[1]);
2041 dc
.DrawLine(ptArrow
[Point_Second
].x
+ 1, ptArrow
[Point_Second
].y
+ 1,
2042 ptArrow
[Point_Third
].x
, ptArrow
[Point_Third
].y
);
2043 dc
.DrawPoint(ptArrow
[Point_Third
]);
2044 dc
.DrawLine(ptArrow
[Point_Third
].x
- 2, ptArrow
[Point_Third
].y
,
2045 ptArrow
[Point_First
].x
+ 1, ptArrow
[Point_First
].y
);
2046 if ( penShadow
[2].Ok() )
2048 dc
.SetPen(penShadow
[2]);
2049 dc
.DrawLine(ptArrow
[Point_Third
].x
- 1, ptArrow
[Point_Third
].y
,
2050 ptArrow
[Point_Second
].x
, ptArrow
[Point_Second
].y
+ 1);
2051 dc
.DrawLine(ptArrow
[Point_Third
].x
- 1, ptArrow
[Point_Third
].y
- 1,
2052 ptArrow
[Point_First
].x
+ 2, ptArrow
[Point_First
].y
- 1);
2057 dc
.DrawLine(ptArrow
[Point_First
], ptArrow
[Point_Second
]);
2058 dc
.DrawLine(ptArrow
[Point_First
].x
+ 2, ptArrow
[Point_First
].y
,
2059 ptArrow
[Point_Third
].x
- 1, ptArrow
[Point_Third
].y
);
2060 if ( penShadow
[2].Ok() )
2062 dc
.SetPen(penShadow
[2]);
2063 dc
.DrawLine(ptArrow
[Point_Second
].x
, ptArrow
[Point_Second
].y
- 1,
2064 ptArrow
[Point_Third
].x
- 1, ptArrow
[Point_Third
].y
- 1);
2066 dc
.SetPen(penShadow
[1]);
2067 dc
.DrawLine(ptArrow
[Point_Second
], ptArrow
[Point_Third
]);
2068 dc
.DrawPoint(ptArrow
[Point_Third
]);
2072 dc
.DrawLine(ptArrow
[Point_Second
], ptArrow
[Point_First
]);
2073 dc
.DrawPoint(ptArrow
[Point_First
]);
2074 if ( penShadow
[2].Ok() )
2076 dc
.SetPen(penShadow
[2]);
2077 dc
.DrawLine(ptArrow
[Point_Third
].x
- 1, ptArrow
[Point_Third
].y
,
2078 ptArrow
[Point_First
].x
- 1, ptArrow
[Point_First
].y
+ 2);
2079 dc
.DrawLine(ptArrow
[Point_Third
].x
, ptArrow
[Point_Third
].y
,
2080 ptArrow
[Point_Second
].x
+ 2, ptArrow
[Point_Second
].y
+ 1);
2082 dc
.SetPen(penShadow
[1]);
2083 dc
.DrawLine(ptArrow
[Point_Third
].x
, ptArrow
[Point_Third
].y
,
2084 ptArrow
[Point_First
].x
, ptArrow
[Point_First
].y
+ 1);
2085 dc
.DrawLine(ptArrow
[Point_Second
].x
+ 1, ptArrow
[Point_Second
].y
+ 1,
2086 ptArrow
[Point_Third
].x
- 1, ptArrow
[Point_Third
].y
);
2090 dc
.DrawLine(ptArrow
[Point_First
], ptArrow
[Point_Third
]);
2091 dc
.DrawLine(ptArrow
[Point_First
].x
+ 2, ptArrow
[Point_First
].y
+ 1,
2092 ptArrow
[Point_Second
].x
, ptArrow
[Point_Second
].y
);
2093 dc
.SetPen(penShadow
[1]);
2094 dc
.DrawLine(ptArrow
[Point_Second
], ptArrow
[Point_Third
]);
2095 dc
.DrawPoint(ptArrow
[Point_Third
]);
2099 wxFAIL_MSG(_T("unknown arrow direction"));
2104 void wxGTKRenderer::DrawThumbBorder(wxDC
& dc
,
2106 wxOrientation orient
)
2108 if ( orient
== wxVERTICAL
)
2110 DrawAntiShadedRectSide(dc
, *rect
, m_penDarkGrey
, m_penHighlight
,
2112 DrawAntiShadedRectSide(dc
, *rect
, m_penDarkGrey
, m_penHighlight
,
2114 rect
->Inflate(-1, 0);
2116 DrawAntiShadedRectSide(dc
, *rect
, m_penBlack
, m_penGrey
,
2118 DrawAntiShadedRectSide(dc
, *rect
, m_penBlack
, m_penGrey
,
2120 rect
->Inflate(-1, 0);
2124 DrawAntiShadedRectSide(dc
, *rect
, m_penDarkGrey
, m_penHighlight
,
2126 DrawAntiShadedRectSide(dc
, *rect
, m_penDarkGrey
, m_penHighlight
,
2128 rect
->Inflate(0, -1);
2130 DrawAntiShadedRectSide(dc
, *rect
, m_penBlack
, m_penGrey
,
2132 DrawAntiShadedRectSide(dc
, *rect
, m_penBlack
, m_penGrey
,
2134 rect
->Inflate(0, -1);
2138 void wxGTKRenderer::DrawScrollbarThumb(wxDC
& dc
,
2139 wxOrientation orient
,
2143 // the thumb is never pressed never has focus border under GTK and the
2144 // scrollbar background never changes at all
2145 int flagsThumb
= flags
& ~(wxCONTROL_PRESSED
| wxCONTROL_FOCUSED
);
2147 // we don't want the border in the direction of the scrollbar movement
2148 wxRect rectThumb
= rect
;
2149 DrawThumbBorder(dc
, &rectThumb
, orient
);
2151 DrawButtonBorder(dc
, rectThumb
, flagsThumb
, &rectThumb
);
2152 DrawBackground(dc
, wxNullColour
, rectThumb
, flagsThumb
);
2155 void wxGTKRenderer::DrawScrollbarShaft(wxDC
& dc
,
2156 wxOrientation orient
,
2160 wxRect rectBar
= rect
;
2161 DrawThumbBorder(dc
, &rectBar
, orient
);
2162 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, SCROLLBAR
), rectBar
);
2165 void wxGTKRenderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
2167 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2170 wxRect
wxGTKRenderer::GetScrollbarRect(const wxScrollBar
*scrollbar
,
2171 wxScrollBar::Element elem
,
2174 // as GTK scrollbars can't be disabled, it makes no sense to remove the
2175 // thumb for a scrollbar with range 0 - instead, make it fill the entire
2177 if ( (elem
== wxScrollBar::Element_Thumb
) && !scrollbar
->GetRange() )
2179 elem
= wxScrollBar::Element_Bar_2
;
2182 return StandardGetScrollbarRect(scrollbar
, elem
,
2184 GetScrollbarArrowSize(scrollbar
));
2187 wxCoord
wxGTKRenderer::GetScrollbarSize(const wxScrollBar
*scrollbar
)
2189 return StandardScrollBarSize(scrollbar
, GetScrollbarArrowSize(scrollbar
));
2192 wxHitTest
wxGTKRenderer::HitTestScrollbar(const wxScrollBar
*scrollbar
,
2193 const wxPoint
& pt
) const
2195 return StandardHitTestScrollbar(scrollbar
, pt
,
2196 GetScrollbarArrowSize(scrollbar
));
2199 wxCoord
wxGTKRenderer::ScrollbarToPixel(const wxScrollBar
*scrollbar
,
2202 return StandardScrollbarToPixel(scrollbar
, thumbPos
,
2203 GetScrollbarArrowSize(scrollbar
));
2206 int wxGTKRenderer::PixelToScrollbar(const wxScrollBar
*scrollbar
,
2209 return StandardPixelToScrollbar(scrollbar
, coord
,
2210 GetScrollbarArrowSize(scrollbar
));
2213 // ----------------------------------------------------------------------------
2215 // ----------------------------------------------------------------------------
2217 void wxGTKRenderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
2219 if ( wxDynamicCast(window
, wxButton
) )
2221 // TODO: this is ad hoc...
2222 size
->x
+= 3*window
->GetCharWidth();
2225 wxCoord minBtnHeight
= 22;
2226 if ( size
->y
< minBtnHeight
)
2227 size
->y
= minBtnHeight
;
2229 // button border width
2232 else if ( wxDynamicCast(window
, wxScrollBar
) )
2234 // we only set the width of vert scrollbars and height of the
2236 if ( window
->GetWindowStyle() & wxSB_HORIZONTAL
)
2237 size
->y
= m_sizeScrollbarArrow
.x
;
2239 size
->x
= m_sizeScrollbarArrow
.x
;
2243 // take into account the border width
2244 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
2245 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
2246 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
2250 // ============================================================================
2252 // ============================================================================
2254 // ----------------------------------------------------------------------------
2255 // wxGTKInputHandler
2256 // ----------------------------------------------------------------------------
2258 wxGTKInputHandler::wxGTKInputHandler(wxGTKRenderer
*renderer
)
2260 m_renderer
= renderer
;
2263 bool wxGTKInputHandler::HandleKey(wxControl
*control
,
2264 const wxKeyEvent
& event
,
2270 bool wxGTKInputHandler::HandleMouse(wxControl
*control
,
2271 const wxMouseEvent
& event
)
2273 // clicking on the control gives it focus
2274 if ( event
.ButtonDown() )
2276 control
->SetFocus();
2284 bool wxGTKInputHandler::HandleMouseMove(wxControl
*control
,
2285 const wxMouseEvent
& event
)
2287 if ( event
.Entering() )
2289 control
->SetCurrent(TRUE
);
2291 else if ( event
.Leaving() )
2293 control
->SetCurrent(FALSE
);
2303 // ----------------------------------------------------------------------------
2304 // wxGTKCheckboxInputHandler
2305 // ----------------------------------------------------------------------------
2307 bool wxGTKCheckboxInputHandler::HandleKey(wxControl
*control
,
2308 const wxKeyEvent
& event
,
2313 int keycode
= event
.GetKeyCode();
2314 if ( keycode
== WXK_SPACE
|| keycode
== WXK_RETURN
)
2316 control
->PerformAction(wxACTION_CHECKBOX_TOGGLE
);
2325 // ----------------------------------------------------------------------------
2326 // wxGTKTextCtrlInputHandler
2327 // ----------------------------------------------------------------------------
2329 bool wxGTKTextCtrlInputHandler::HandleKey(wxControl
*control
,
2330 const wxKeyEvent
& event
,
2333 // handle only GTK-specific text bindings here, the others are handled in
2337 wxControlAction action
;
2338 int keycode
= event
.GetKeyCode();
2339 if ( event
.ControlDown() )
2344 action
= wxACTION_TEXT_HOME
;
2348 action
= wxACTION_TEXT_LEFT
;
2352 action
<< wxACTION_TEXT_PREFIX_DEL
<< wxACTION_TEXT_RIGHT
;
2356 action
= wxACTION_TEXT_END
;
2360 action
= wxACTION_TEXT_RIGHT
;
2364 action
<< wxACTION_TEXT_PREFIX_DEL
<< wxACTION_TEXT_LEFT
;
2368 action
<< wxACTION_TEXT_PREFIX_DEL
<< wxACTION_TEXT_END
;
2372 action
= wxACTION_TEXT_DOWN
;
2376 action
= wxACTION_TEXT_UP
;
2380 //delete the entire line
2381 control
->PerformAction(wxACTION_TEXT_HOME
);
2382 action
<< wxACTION_TEXT_PREFIX_DEL
<< wxACTION_TEXT_END
;
2386 action
<< wxACTION_TEXT_PREFIX_DEL
<< wxACTION_TEXT_WORD_LEFT
;
2390 else if ( event
.AltDown() )
2395 action
= wxACTION_TEXT_WORD_LEFT
;
2399 action
<< wxACTION_TEXT_PREFIX_DEL
<< wxACTION_TEXT_WORD_RIGHT
;
2403 action
= wxACTION_TEXT_WORD_RIGHT
;
2408 if ( action
!= wxACTION_NONE
)
2410 control
->PerformAction(action
);
2416 return wxStdTextCtrlInputHandler::HandleKey(control
, event
, pressed
);