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