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