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