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