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