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