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