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