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