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 wxRect
wxGTKRenderer::GetTextTotalArea(const wxTextCtrl
*text
,
1460 wxRect rectTotal
= rect
;
1461 rectTotal
.Inflate(2);
1465 wxRect
wxGTKRenderer::GetTextClientArea(const wxTextCtrl
*text
,
1467 wxCoord
*extraSpaceBeyond
)
1469 wxRect rectText
= rect
;
1470 rectText
.Inflate(-2);
1472 if ( text
->WrapLines() )
1474 // leave enough for the line wrap bitmap indicator
1475 wxCoord widthMark
= GetLineWrapBitmap().GetWidth() + 2;
1477 rectText
.width
-= widthMark
;
1479 if ( extraSpaceBeyond
)
1480 *extraSpaceBeyond
= widthMark
;
1486 void wxGTKRenderer::DrawTextLine(wxDC
& dc
,
1487 const wxString
& text
,
1493 // TODO: GTK+ draws selection even for unfocused controls, just with
1494 // different colours
1495 StandardDrawTextLine(dc
, text
, rect
, selStart
, selEnd
, flags
);
1498 void wxGTKRenderer::DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
)
1500 wxBitmap bmpLineWrap
= GetLineWrapBitmap();
1502 // for a mono bitmap he colours it appears in depends on the current text
1503 // colours, so set them correctly
1505 if ( bmpLineWrap
.GetDepth() == 1 )
1507 colFgOld
= dc
.GetTextForeground();
1509 // FIXME: I wonder what should we do if the background is black too?
1510 dc
.SetTextForeground(*wxBLACK
);
1513 dc
.DrawBitmap(bmpLineWrap
,
1514 rect
.x
, rect
.y
+ (rect
.height
- bmpLineWrap
.GetHeight())/2);
1516 if ( colFgOld
.Ok() )
1518 // restore old colour
1519 dc
.SetTextForeground(colFgOld
);
1523 // ----------------------------------------------------------------------------
1525 // ----------------------------------------------------------------------------
1527 void wxGTKRenderer::DrawTab(wxDC
& dc
,
1528 const wxRect
& rectOrig
,
1530 const wxString
& label
,
1531 const wxBitmap
& bitmap
,
1535 wxRect rect
= rectOrig
;
1537 // the current tab is drawn indented (to the top for default case) and
1538 // bigger than the other ones
1539 const wxSize indent
= GetTabIndent();
1540 if ( flags
& wxCONTROL_SELECTED
)
1545 wxFAIL_MSG(_T("invaild notebook tab orientation"));
1549 rect
.Inflate(indent
.x
, 0);
1551 rect
.height
+= indent
.y
;
1555 rect
.Inflate(indent
.x
, 0);
1556 rect
.height
+= indent
.y
;
1561 wxFAIL_MSG(_T("TODO"));
1566 // selected tab has different colour
1567 wxColour col
= flags
& wxCONTROL_SELECTED
1568 ? wxSCHEME_COLOUR(m_scheme
, SHADOW_IN
)
1569 : wxSCHEME_COLOUR(m_scheme
, SCROLLBAR
);
1570 DoDrawBackground(dc
, col
, rect
);
1572 if ( flags
& wxCONTROL_FOCUSED
)
1574 // draw the focus rect
1575 wxRect rectBorder
= rect
;
1576 rectBorder
.Deflate(4, 3);
1577 if ( dir
== wxBOTTOM
)
1578 rectBorder
.Offset(0, -1);
1580 DrawRect(dc
, &rectBorder
, m_penBlack
);
1583 // draw the text, image and the focus around them (if necessary)
1584 wxRect rectLabel
= rect
;
1585 rectLabel
.Deflate(1, 1);
1586 dc
.DrawLabel(label
, bitmap
, rectLabel
, wxALIGN_CENTRE
, indexAccel
);
1588 // now draw the tab itself
1591 x2
= rect
.GetRight(),
1592 y2
= rect
.GetBottom();
1597 dc
.SetPen(m_penHighlight
);
1598 dc
.DrawLine(x
, y2
, x
, y
);
1599 dc
.DrawLine(x
+ 1, y
, x2
, y
);
1601 dc
.SetPen(m_penBlack
);
1602 dc
.DrawLine(x2
, y2
, x2
, y
);
1604 dc
.SetPen(m_penDarkGrey
);
1605 dc
.DrawLine(x2
- 1, y2
, x2
- 1, y
+ 1);
1607 if ( flags
& wxCONTROL_SELECTED
)
1609 dc
.SetPen(m_penLightGrey
);
1611 // overwrite the part of the border below this tab
1612 dc
.DrawLine(x
+ 1, y2
+ 1, x2
- 1, y2
+ 1);
1614 // and the shadow of the tab to the left of us
1615 dc
.DrawLine(x
+ 1, y
+ 2, x
+ 1, y2
+ 1);
1620 dc
.SetPen(m_penHighlight
);
1622 // we need to continue one pixel further to overwrite the corner of
1623 // the border for the selected tab
1624 dc
.DrawLine(x
, y
- (flags
& wxCONTROL_SELECTED
? 1 : 0),
1627 // it doesn't work like this (TODO: implement it properly)
1629 // erase the corner of the tab to the right
1630 dc
.SetPen(m_penLightGrey
);
1631 dc
.DrawPoint(x2
- 1, y
- 2);
1632 dc
.DrawPoint(x2
- 2, y
- 2);
1633 dc
.DrawPoint(x2
- 2, y
- 1);
1636 dc
.SetPen(m_penBlack
);
1637 dc
.DrawLine(x
+ 1, y2
, x2
, y2
);
1638 dc
.DrawLine(x2
, y
, x2
, y2
);
1640 dc
.SetPen(m_penDarkGrey
);
1641 dc
.DrawLine(x
+ 2, y2
- 1, x2
- 1, y2
- 1);
1642 dc
.DrawLine(x2
- 1, y
, x2
- 1, y2
);
1644 if ( flags
& wxCONTROL_SELECTED
)
1646 dc
.SetPen(m_penLightGrey
);
1648 // overwrite the part of the (double!) border above this tab
1649 dc
.DrawLine(x
+ 1, y
- 1, x2
- 1, y
- 1);
1650 dc
.DrawLine(x
+ 1, y
- 2, x2
- 1, y
- 2);
1652 // and the shadow of the tab to the left of us
1653 dc
.DrawLine(x
+ 1, y2
- 1, x
+ 1, y
- 1);
1659 wxFAIL_MSG(_T("TODO"));
1663 // ----------------------------------------------------------------------------
1665 // ----------------------------------------------------------------------------
1667 wxSize
wxGTKRenderer::GetSliderThumbSize(const wxRect
& rect
,
1668 wxOrientation orient
) const
1670 static const wxCoord SLIDER_THUMB_LENGTH
= 30;
1674 wxRect rectShaft
= GetSliderShaftRect(rect
, orient
);
1675 if ( orient
== wxHORIZONTAL
)
1677 size
.x
= wxMin(SLIDER_THUMB_LENGTH
, rectShaft
.width
);
1678 size
.y
= rectShaft
.height
;
1682 size
.y
= wxMin(SLIDER_THUMB_LENGTH
, rectShaft
.height
);
1683 size
.x
= rectShaft
.width
;
1689 wxRect
wxGTKRenderer::GetSliderShaftRect(const wxRect
& rect
,
1690 wxOrientation
WXUNUSED(orient
)) const
1692 return rect
.Deflate(2*BORDER_THICKNESS
, 2*BORDER_THICKNESS
);
1695 void wxGTKRenderer::DrawSliderShaft(wxDC
& dc
,
1696 const wxRect
& rectOrig
,
1697 wxOrientation orient
,
1701 wxRect rect
= rectOrig
;
1703 // draw the border first
1704 if ( flags
& wxCONTROL_FOCUSED
)
1706 DrawRect(dc
, &rect
, m_penBlack
);
1707 DrawAntiShadedRect(dc
, &rect
, m_penBlack
, m_penLightGrey
);
1709 else // not focused, normal
1711 DrawAntiShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
1712 DrawAntiShadedRect(dc
, &rect
, m_penBlack
, m_penLightGrey
);
1715 // and the background
1716 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, SCROLLBAR
), rect
);
1722 void wxGTKRenderer::DrawSliderThumb(wxDC
& dc
,
1723 const wxRect
& rectOrig
,
1724 wxOrientation orient
,
1727 // draw the thumb border
1728 wxRect rect
= rectOrig
;
1729 DrawAntiRaisedBorder(dc
, &rect
);
1731 // draw the handle in the middle
1732 if ( orient
== wxVERTICAL
)
1734 rect
.height
= 2*BORDER_THICKNESS
;
1735 rect
.y
= rectOrig
.y
+ (rectOrig
.height
- rect
.height
) / 2;
1739 rect
.width
= 2*BORDER_THICKNESS
;
1740 rect
.x
= rectOrig
.x
+ (rectOrig
.width
- rect
.width
) / 2;
1743 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
1746 // ----------------------------------------------------------------------------
1748 // ----------------------------------------------------------------------------
1750 void wxGTKRenderer::DrawMenuBarItem(wxDC
& dc
,
1752 const wxString
& label
,
1756 DrawLabel(dc
, label
, rect
, flags
, wxALIGN_CENTRE
, indexAccel
);
1759 void wxGTKRenderer::DrawMenuItem(wxDC
& dc
,
1761 const wxMenuGeometryInfo
& geometryInfo
,
1762 const wxString
& label
,
1763 const wxString
& accel
,
1764 const wxBitmap
& bitmap
,
1768 wxFAIL_MSG(_T("TODO"));
1771 void wxGTKRenderer::DrawMenuSeparator(wxDC
& dc
,
1773 const wxMenuGeometryInfo
& geomInfo
)
1775 wxFAIL_MSG(_T("TODO"));
1778 wxSize
wxGTKRenderer::GetMenuBarItemSize(const wxSize
& sizeText
) const
1783 wxMenuGeometryInfo
*wxGTKRenderer::GetMenuGeometry(wxWindow
*win
,
1784 const wxMenu
& menu
) const
1786 wxFAIL_MSG(_T("TODO"));
1791 // ----------------------------------------------------------------------------
1793 // ----------------------------------------------------------------------------
1795 void wxGTKRenderer::GetComboBitmaps(wxBitmap
*bmpNormal
,
1796 wxBitmap
*bmpPressed
,
1797 wxBitmap
*bmpDisabled
)
1802 // ----------------------------------------------------------------------------
1804 // ----------------------------------------------------------------------------
1806 void wxGTKRenderer::DoDrawBackground(wxDC
& dc
,
1807 const wxColour
& col
,
1810 wxBrush
brush(col
, wxSOLID
);
1812 dc
.SetPen(*wxTRANSPARENT_PEN
);
1813 dc
.DrawRectangle(rect
);
1816 void wxGTKRenderer::DrawBackground(wxDC
& dc
,
1817 const wxColour
& col
,
1821 wxColour colBg
= col
.Ok() ? col
: GetBackgroundColour(flags
);
1822 DoDrawBackground(dc
, colBg
, rect
);
1825 // ----------------------------------------------------------------------------
1827 // ----------------------------------------------------------------------------
1829 void wxGTKRenderer::DrawArrowBorder(wxDC
& dc
,
1833 static const wxDirection sides
[] =
1835 wxUP
, wxLEFT
, wxRIGHT
, wxDOWN
1838 wxRect rect1
, rect2
, rectInner
;
1844 rectInner
.Inflate(-2);
1846 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, SCROLLBAR
), *rect
);
1848 // find the side not to draw and also adjust the rectangles to compensate
1850 wxDirection sideToOmit
;
1854 sideToOmit
= wxDOWN
;
1856 rectInner
.height
+= 1;
1864 rectInner
.height
+= 1;
1868 sideToOmit
= wxRIGHT
;
1870 rectInner
.width
+= 1;
1874 sideToOmit
= wxLEFT
;
1878 rectInner
.width
+= 1;
1882 wxFAIL_MSG(_T("unknown arrow direction"));
1886 // the outer rect first
1888 for ( n
= 0; n
< WXSIZEOF(sides
); n
++ )
1890 wxDirection side
= sides
[n
];
1891 if ( side
== sideToOmit
)
1894 DrawAntiShadedRectSide(dc
, rect1
, m_penDarkGrey
, m_penHighlight
, side
);
1897 // and then the inner one
1898 for ( n
= 0; n
< WXSIZEOF(sides
); n
++ )
1900 wxDirection side
= sides
[n
];
1901 if ( side
== sideToOmit
)
1904 DrawAntiShadedRectSide(dc
, rect2
, m_penBlack
, m_penGrey
, side
);
1910 void wxGTKRenderer::DrawScrollbarArrow(wxDC
& dc
,
1912 const wxRect
& rectArrow
,
1915 // first of all, draw the border around it - but we don't want the border
1916 // on the side opposite to the arrow point
1917 wxRect rect
= rectArrow
;
1918 DrawArrowBorder(dc
, &rect
, dir
);
1920 // then the arrow itself
1921 DrawArrow(dc
, dir
, rect
, flags
);
1924 // gtk_default_draw_arrow() takes ~350 lines and we can't do much better here
1925 // these people are just crazy :-(
1926 void wxGTKRenderer::DrawArrow(wxDC
& dc
,
1939 wxPoint ptArrow
[Point_Max
];
1941 wxColour colInside
= GetBackgroundColour(flags
);
1943 if ( flags
& wxCONTROL_DISABLED
)
1945 penShadow
[0] = m_penDarkGrey
;
1946 penShadow
[1] = m_penDarkGrey
;
1947 penShadow
[2] = wxNullPen
;
1948 penShadow
[3] = wxNullPen
;
1950 else if ( flags
& wxCONTROL_PRESSED
)
1952 penShadow
[0] = m_penDarkGrey
;
1953 penShadow
[1] = m_penHighlight
;
1954 penShadow
[2] = wxNullPen
;
1955 penShadow
[3] = m_penBlack
;
1957 else // normal arrow
1959 penShadow
[0] = m_penHighlight
;
1960 penShadow
[1] = m_penBlack
;
1961 penShadow
[2] = m_penDarkGrey
;
1962 penShadow
[3] = wxNullPen
;
1966 if ( dir
== wxUP
|| dir
== wxDOWN
)
1969 middle
= (rect
.GetRight() + rect
.GetLeft() + 1) / 2;
1973 middle
= (rect
.GetTop() + rect
.GetBottom() + 1) / 2;
1976 // draw the arrow interior
1977 dc
.SetPen(*wxTRANSPARENT_PEN
);
1978 dc
.SetBrush(wxBrush(colInside
, wxSOLID
));
1983 ptArrow
[Point_First
].x
= rect
.GetLeft();
1984 ptArrow
[Point_First
].y
= rect
.GetBottom();
1985 ptArrow
[Point_Second
].x
= middle
;
1986 ptArrow
[Point_Second
].y
= rect
.GetTop();
1987 ptArrow
[Point_Third
].x
= rect
.GetRight();
1988 ptArrow
[Point_Third
].y
= rect
.GetBottom();
1992 ptArrow
[Point_First
] = rect
.GetPosition();
1993 ptArrow
[Point_Second
].x
= middle
;
1994 ptArrow
[Point_Second
].y
= rect
.GetBottom();
1995 ptArrow
[Point_Third
].x
= rect
.GetRight();
1996 ptArrow
[Point_Third
].y
= rect
.GetTop();
2000 ptArrow
[Point_First
].x
= rect
.GetRight();
2001 ptArrow
[Point_First
].y
= rect
.GetTop();
2002 ptArrow
[Point_Second
].x
= rect
.GetLeft();
2003 ptArrow
[Point_Second
].y
= middle
;
2004 ptArrow
[Point_Third
].x
= rect
.GetRight();
2005 ptArrow
[Point_Third
].y
= rect
.GetBottom();
2009 ptArrow
[Point_First
] = rect
.GetPosition();
2010 ptArrow
[Point_Second
].x
= rect
.GetRight();
2011 ptArrow
[Point_Second
].y
= middle
;
2012 ptArrow
[Point_Third
].x
= rect
.GetLeft();
2013 ptArrow
[Point_Third
].y
= rect
.GetBottom();
2017 wxFAIL_MSG(_T("unknown arrow direction"));
2020 dc
.DrawPolygon(WXSIZEOF(ptArrow
), ptArrow
);
2022 // draw the arrow border
2023 dc
.SetPen(penShadow
[0]);
2027 dc
.DrawLine(ptArrow
[Point_Second
], ptArrow
[Point_First
]);
2028 dc
.DrawPoint(ptArrow
[Point_First
]);
2029 if ( penShadow
[3].Ok() )
2031 dc
.SetPen(penShadow
[3]);
2032 dc
.DrawLine(ptArrow
[Point_First
].x
+ 1, ptArrow
[Point_First
].y
,
2033 ptArrow
[Point_Second
].x
, ptArrow
[Point_Second
].y
);
2035 dc
.SetPen(penShadow
[1]);
2036 dc
.DrawLine(ptArrow
[Point_Second
].x
+ 1, ptArrow
[Point_Second
].y
+ 1,
2037 ptArrow
[Point_Third
].x
, ptArrow
[Point_Third
].y
);
2038 dc
.DrawPoint(ptArrow
[Point_Third
]);
2039 dc
.DrawLine(ptArrow
[Point_Third
].x
- 2, ptArrow
[Point_Third
].y
,
2040 ptArrow
[Point_First
].x
+ 1, ptArrow
[Point_First
].y
);
2041 if ( penShadow
[2].Ok() )
2043 dc
.SetPen(penShadow
[2]);
2044 dc
.DrawLine(ptArrow
[Point_Third
].x
- 1, ptArrow
[Point_Third
].y
,
2045 ptArrow
[Point_Second
].x
, ptArrow
[Point_Second
].y
+ 1);
2046 dc
.DrawLine(ptArrow
[Point_Third
].x
- 1, ptArrow
[Point_Third
].y
- 1,
2047 ptArrow
[Point_First
].x
+ 2, ptArrow
[Point_First
].y
- 1);
2052 dc
.DrawLine(ptArrow
[Point_First
], ptArrow
[Point_Second
]);
2053 dc
.DrawLine(ptArrow
[Point_First
].x
+ 2, ptArrow
[Point_First
].y
,
2054 ptArrow
[Point_Third
].x
- 1, ptArrow
[Point_Third
].y
);
2055 if ( penShadow
[2].Ok() )
2057 dc
.SetPen(penShadow
[2]);
2058 dc
.DrawLine(ptArrow
[Point_Second
].x
, ptArrow
[Point_Second
].y
- 1,
2059 ptArrow
[Point_Third
].x
- 1, ptArrow
[Point_Third
].y
- 1);
2061 dc
.SetPen(penShadow
[1]);
2062 dc
.DrawLine(ptArrow
[Point_Second
], ptArrow
[Point_Third
]);
2063 dc
.DrawPoint(ptArrow
[Point_Third
]);
2067 dc
.DrawLine(ptArrow
[Point_Second
], ptArrow
[Point_First
]);
2068 dc
.DrawPoint(ptArrow
[Point_First
]);
2069 if ( penShadow
[2].Ok() )
2071 dc
.SetPen(penShadow
[2]);
2072 dc
.DrawLine(ptArrow
[Point_Third
].x
- 1, ptArrow
[Point_Third
].y
,
2073 ptArrow
[Point_First
].x
- 1, ptArrow
[Point_First
].y
+ 2);
2074 dc
.DrawLine(ptArrow
[Point_Third
].x
, ptArrow
[Point_Third
].y
,
2075 ptArrow
[Point_Second
].x
+ 2, ptArrow
[Point_Second
].y
+ 1);
2077 dc
.SetPen(penShadow
[1]);
2078 dc
.DrawLine(ptArrow
[Point_Third
].x
, ptArrow
[Point_Third
].y
,
2079 ptArrow
[Point_First
].x
, ptArrow
[Point_First
].y
+ 1);
2080 dc
.DrawLine(ptArrow
[Point_Second
].x
+ 1, ptArrow
[Point_Second
].y
+ 1,
2081 ptArrow
[Point_Third
].x
- 1, ptArrow
[Point_Third
].y
);
2085 dc
.DrawLine(ptArrow
[Point_First
], ptArrow
[Point_Third
]);
2086 dc
.DrawLine(ptArrow
[Point_First
].x
+ 2, ptArrow
[Point_First
].y
+ 1,
2087 ptArrow
[Point_Second
].x
, ptArrow
[Point_Second
].y
);
2088 dc
.SetPen(penShadow
[1]);
2089 dc
.DrawLine(ptArrow
[Point_Second
], ptArrow
[Point_Third
]);
2090 dc
.DrawPoint(ptArrow
[Point_Third
]);
2094 wxFAIL_MSG(_T("unknown arrow direction"));
2099 void wxGTKRenderer::DrawThumbBorder(wxDC
& dc
,
2101 wxOrientation orient
)
2103 if ( orient
== wxVERTICAL
)
2105 DrawAntiShadedRectSide(dc
, *rect
, m_penDarkGrey
, m_penHighlight
,
2107 DrawAntiShadedRectSide(dc
, *rect
, m_penDarkGrey
, m_penHighlight
,
2109 rect
->Inflate(-1, 0);
2111 DrawAntiShadedRectSide(dc
, *rect
, m_penBlack
, m_penGrey
,
2113 DrawAntiShadedRectSide(dc
, *rect
, m_penBlack
, m_penGrey
,
2115 rect
->Inflate(-1, 0);
2119 DrawAntiShadedRectSide(dc
, *rect
, m_penDarkGrey
, m_penHighlight
,
2121 DrawAntiShadedRectSide(dc
, *rect
, m_penDarkGrey
, m_penHighlight
,
2123 rect
->Inflate(0, -1);
2125 DrawAntiShadedRectSide(dc
, *rect
, m_penBlack
, m_penGrey
,
2127 DrawAntiShadedRectSide(dc
, *rect
, m_penBlack
, m_penGrey
,
2129 rect
->Inflate(0, -1);
2133 void wxGTKRenderer::DrawScrollbarThumb(wxDC
& dc
,
2134 wxOrientation orient
,
2138 // the thumb is never pressed never has focus border under GTK and the
2139 // scrollbar background never changes at all
2140 int flagsThumb
= flags
& ~(wxCONTROL_PRESSED
| wxCONTROL_FOCUSED
);
2142 // we don't want the border in the direction of the scrollbar movement
2143 wxRect rectThumb
= rect
;
2144 DrawThumbBorder(dc
, &rectThumb
, orient
);
2146 DrawButtonBorder(dc
, rectThumb
, flagsThumb
, &rectThumb
);
2147 DrawBackground(dc
, wxNullColour
, rectThumb
, flagsThumb
);
2150 void wxGTKRenderer::DrawScrollbarShaft(wxDC
& dc
,
2151 wxOrientation orient
,
2155 wxRect rectBar
= rect
;
2156 DrawThumbBorder(dc
, &rectBar
, orient
);
2157 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, SCROLLBAR
), rectBar
);
2160 void wxGTKRenderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
2162 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2165 wxRect
wxGTKRenderer::GetScrollbarRect(const wxScrollBar
*scrollbar
,
2166 wxScrollBar::Element elem
,
2169 // as GTK scrollbars can't be disabled, it makes no sense to remove the
2170 // thumb for a scrollbar with range 0 - instead, make it fill the entire
2172 if ( (elem
== wxScrollBar::Element_Thumb
) && !scrollbar
->GetRange() )
2174 elem
= wxScrollBar::Element_Bar_2
;
2177 return StandardGetScrollbarRect(scrollbar
, elem
,
2179 GetScrollbarArrowSize(scrollbar
));
2182 wxCoord
wxGTKRenderer::GetScrollbarSize(const wxScrollBar
*scrollbar
)
2184 return StandardScrollBarSize(scrollbar
, GetScrollbarArrowSize(scrollbar
));
2187 wxHitTest
wxGTKRenderer::HitTestScrollbar(const wxScrollBar
*scrollbar
,
2188 const wxPoint
& pt
) const
2190 return StandardHitTestScrollbar(scrollbar
, pt
,
2191 GetScrollbarArrowSize(scrollbar
));
2194 wxCoord
wxGTKRenderer::ScrollbarToPixel(const wxScrollBar
*scrollbar
,
2197 return StandardScrollbarToPixel(scrollbar
, thumbPos
,
2198 GetScrollbarArrowSize(scrollbar
));
2201 int wxGTKRenderer::PixelToScrollbar(const wxScrollBar
*scrollbar
,
2204 return StandardPixelToScrollbar(scrollbar
, coord
,
2205 GetScrollbarArrowSize(scrollbar
));
2208 // ----------------------------------------------------------------------------
2210 // ----------------------------------------------------------------------------
2212 void wxGTKRenderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
2214 if ( wxDynamicCast(window
, wxButton
) )
2216 // TODO: this is ad hoc...
2217 size
->x
+= 3*window
->GetCharWidth();
2220 wxCoord minBtnHeight
= 22;
2221 if ( size
->y
< minBtnHeight
)
2222 size
->y
= minBtnHeight
;
2224 // button border width
2227 else if ( wxDynamicCast(window
, wxScrollBar
) )
2229 // we only set the width of vert scrollbars and height of the
2231 if ( window
->GetWindowStyle() & wxSB_HORIZONTAL
)
2232 size
->y
= m_sizeScrollbarArrow
.x
;
2234 size
->x
= m_sizeScrollbarArrow
.x
;
2238 // take into account the border width
2239 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
2240 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
2241 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
2245 // ============================================================================
2247 // ============================================================================
2249 // ----------------------------------------------------------------------------
2250 // wxGTKInputHandler
2251 // ----------------------------------------------------------------------------
2253 wxGTKInputHandler::wxGTKInputHandler(wxGTKRenderer
*renderer
)
2255 m_renderer
= renderer
;
2258 bool wxGTKInputHandler::HandleKey(wxControl
*control
,
2259 const wxKeyEvent
& event
,
2265 bool wxGTKInputHandler::HandleMouse(wxControl
*control
,
2266 const wxMouseEvent
& event
)
2268 // clicking on the control gives it focus
2269 if ( event
.ButtonDown() )
2271 control
->SetFocus();
2279 bool wxGTKInputHandler::HandleMouseMove(wxControl
*control
,
2280 const wxMouseEvent
& event
)
2282 if ( event
.Entering() )
2284 control
->SetCurrent(TRUE
);
2286 else if ( event
.Leaving() )
2288 control
->SetCurrent(FALSE
);
2298 // ----------------------------------------------------------------------------
2299 // wxGTKCheckboxInputHandler
2300 // ----------------------------------------------------------------------------
2302 bool wxGTKCheckboxInputHandler::HandleKey(wxControl
*control
,
2303 const wxKeyEvent
& event
,
2308 int keycode
= event
.GetKeyCode();
2309 if ( keycode
== WXK_SPACE
|| keycode
== WXK_RETURN
)
2311 control
->PerformAction(wxACTION_CHECKBOX_TOGGLE
);
2320 // ----------------------------------------------------------------------------
2321 // wxGTKTextCtrlInputHandler
2322 // ----------------------------------------------------------------------------
2324 bool wxGTKTextCtrlInputHandler::HandleKey(wxControl
*control
,
2325 const wxKeyEvent
& event
,
2328 // handle only GTK-specific text bindings here, the others are handled in
2332 wxControlAction action
;
2333 int keycode
= event
.GetKeyCode();
2334 if ( event
.ControlDown() )
2339 action
= wxACTION_TEXT_HOME
;
2343 action
= wxACTION_TEXT_LEFT
;
2347 action
<< wxACTION_TEXT_PREFIX_DEL
<< wxACTION_TEXT_RIGHT
;
2351 action
= wxACTION_TEXT_END
;
2355 action
= wxACTION_TEXT_RIGHT
;
2359 action
<< wxACTION_TEXT_PREFIX_DEL
<< wxACTION_TEXT_LEFT
;
2363 action
<< wxACTION_TEXT_PREFIX_DEL
<< wxACTION_TEXT_END
;
2367 action
= wxACTION_TEXT_DOWN
;
2371 action
= wxACTION_TEXT_UP
;
2375 //delete the entire line
2376 control
->PerformAction(wxACTION_TEXT_HOME
);
2377 action
<< wxACTION_TEXT_PREFIX_DEL
<< wxACTION_TEXT_END
;
2381 action
<< wxACTION_TEXT_PREFIX_DEL
<< wxACTION_TEXT_WORD_LEFT
;
2385 else if ( event
.AltDown() )
2390 action
= wxACTION_TEXT_WORD_LEFT
;
2394 action
<< wxACTION_TEXT_PREFIX_DEL
<< wxACTION_TEXT_WORD_RIGHT
;
2398 action
= wxACTION_TEXT_WORD_RIGHT
;
2403 if ( action
!= wxACTION_NONE
)
2405 control
->PerformAction(action
);
2411 return wxStdTextCtrlInputHandler::HandleKey(control
, event
, pressed
);