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