]> git.saurik.com Git - wxWidgets.git/blob - src/aui/tabartgtk.cpp
Fix generic wxTimePickerCtrl on DST change dates.
[wxWidgets.git] / src / aui / tabartgtk.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/aui/tabartgtk.cpp
3 // Purpose: implementation of the wxAuiGTKTabArt
4 // Author: Jens Lody and Teodor Petrov
5 // Modified by:
6 // Created: 2012-03-23
7 // RCS-ID: $Id:$
8 // Copyright: (c) 2012 Jens Lody <jens@codeblocks.org>
9 // and Teodor Petrov
10 // Licence: wxWindows licence
11 ///////////////////////////////////////////////////////////////////////////////
12
13 // ============================================================================
14 // declarations
15 // ============================================================================
16
17 // ----------------------------------------------------------------------------
18 // headers
19 // ----------------------------------------------------------------------------
20
21 // For compilers that support precompilation, includes "wx.h".
22 #include "wx/wxprec.h"
23
24 #ifdef __BORLANDC__
25 #pragma hdrstop
26 #endif
27
28 #if wxUSE_AUI
29
30 #ifndef WX_PRECOMP
31 #include "wx/dc.h"
32 #include "wx/dcclient.h"
33 #include "wx/settings.h"
34 #include "wx/image.h"
35 #endif
36
37 #include "wx/gtk/dc.h"
38 #include "wx/gtk/private.h"
39
40 #include <gtk/gtk.h>
41
42 #include "wx/aui/auibook.h"
43 #include "wx/aui/tabartgtk.h"
44 #include "wx/renderer.h"
45
46 namespace
47 {
48
49 static int s_CloseIconSize = 16; // default size
50
51 }
52
53 wxAuiGtkTabArt::wxAuiGtkTabArt()//:
54 // m_Xthickness(0),
55 // m_Ythickness(0),
56 // m_TabHBorder(0),
57 // m_TabVBorder(0)
58
59 {
60 }
61
62 wxAuiTabArt* wxAuiGtkTabArt::Clone()
63 {
64 wxAuiGtkTabArt* clone = new wxAuiGtkTabArt();
65
66 clone->SetNormalFont(m_normalFont);
67 clone->SetSelectedFont(m_normalFont);
68 clone->SetMeasuringFont(m_normalFont);
69
70 return clone;
71 }
72
73 void wxAuiGtkTabArt::DrawBackground(wxDC& dc, wxWindow* WXUNUSED(wnd), const wxRect& rect)
74 {
75 wxGTKDCImpl *impldc = (wxGTKDCImpl*) dc.GetImpl();
76 GdkWindow* window = impldc->GetGDKWindow();
77
78 gtk_style_apply_default_background(gtk_widget_get_style(wxGTKPrivate::GetNotebookWidget()),
79 window,
80 true,
81 GTK_STATE_NORMAL,
82 NULL,
83 rect.x, rect.y, rect.width, rect.height);
84 }
85
86 void ButtonStateAndShadow(int button_state, GtkStateType &state, GtkShadowType &shadow)
87 {
88
89 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
90 {
91 state = GTK_STATE_INSENSITIVE;
92 shadow = GTK_SHADOW_ETCHED_IN;
93 }
94 else if (button_state & wxAUI_BUTTON_STATE_HOVER)
95 {
96 state = GTK_STATE_PRELIGHT;
97 shadow = GTK_SHADOW_OUT;
98 }
99 else if (button_state & wxAUI_BUTTON_STATE_PRESSED)
100 {
101 state = GTK_STATE_ACTIVE;
102 shadow = GTK_SHADOW_IN;
103 }
104 else
105 {
106 state = GTK_STATE_NORMAL;
107 shadow = GTK_SHADOW_OUT;
108 }
109 }
110
111 wxRect DrawCloseButton(wxDC& dc,
112 GtkWidget *widget,
113 int button_state,
114 wxRect const &in_rect,
115 int orientation,
116 GdkRectangle* clipRect)
117 {
118 GtkStyle *style_button = gtk_widget_get_style(wxGTKPrivate::GetButtonWidget());
119 int xthickness = style_button->xthickness;
120 int ythickness = style_button->ythickness;
121
122 wxBitmap bmp;
123 bmp.SetPixbuf(gtk_widget_render_icon(widget, GTK_STOCK_CLOSE, GTK_ICON_SIZE_SMALL_TOOLBAR, "tab"));
124
125 if(bmp.GetWidth() != s_CloseIconSize || bmp.GetHeight() != s_CloseIconSize)
126 {
127 wxImage img = bmp.ConvertToImage();
128 img.Rescale(s_CloseIconSize, s_CloseIconSize);
129 bmp = img;
130 }
131
132 int button_size = s_CloseIconSize + 2 * xthickness;
133
134 wxRect out_rect;
135
136 if (orientation == wxLEFT)
137 out_rect.x = in_rect.x - ythickness;
138 else
139 out_rect.x = in_rect.x + in_rect.width - button_size - ythickness;
140
141 out_rect.y = in_rect.y + (in_rect.height - button_size) / 2;
142 out_rect.width = button_size;
143 out_rect.height = button_size;
144
145 wxGTKDCImpl *impldc = (wxGTKDCImpl*) dc.GetImpl();
146 GdkWindow* window = impldc->GetGDKWindow();
147
148 if (button_state == wxAUI_BUTTON_STATE_HOVER)
149 {
150 gtk_paint_box(style_button, window,
151 GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, clipRect, widget, "button",
152 out_rect.x, out_rect.y, out_rect.width, out_rect.height);
153 }
154 else if (button_state == wxAUI_BUTTON_STATE_PRESSED)
155 {
156 gtk_paint_box(style_button, window,
157 GTK_STATE_ACTIVE, GTK_SHADOW_IN, clipRect, widget, "button",
158 out_rect.x, out_rect.y, out_rect.width, out_rect.height);
159 }
160
161
162 dc.DrawBitmap(bmp, out_rect.x + xthickness, out_rect.y + ythickness, true);
163
164 return out_rect;
165 }
166
167 void wxAuiGtkTabArt::DrawTab(wxDC& dc, wxWindow* wnd, const wxAuiNotebookPage& page,
168 const wxRect& in_rect, int close_button_state, wxRect* out_tab_rect,
169 wxRect* out_button_rect, int* x_extent)
170 {
171 GtkWidget *widget = wnd->GetHandle();
172 GtkStyle *style_notebook = gtk_widget_get_style(wxGTKPrivate::GetNotebookWidget());
173
174 wxRect const &window_rect = wnd->GetRect();
175
176 int focus_width = 0;
177
178 gtk_widget_style_get(wxGTKPrivate::GetNotebookWidget(),
179 "focus-line-width", &focus_width,
180 NULL);
181
182 int gap_x = 0, gap_width = 0;
183 int tab_pos;
184 if (m_flags &wxAUI_NB_BOTTOM)
185 tab_pos = wxAUI_NB_BOTTOM;
186 else //if (m_flags & wxAUI_NB_TOP) {}
187 tab_pos = wxAUI_NB_TOP;
188
189 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
190 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
191
192 // figure out the size of the tab
193 wxSize tab_size = GetTabSize(dc, wnd, page.caption, page.bitmap,
194 page.active, close_button_state, x_extent);
195
196 wxRect tab_rect = in_rect;
197 tab_rect.width = tab_size.x;
198 tab_rect.height = tab_size.y;
199 tab_rect.y += 2 * GTK_NOTEBOOK (wxGTKPrivate::GetNotebookWidget())->tab_hborder;
200
201 if (page.active)
202 tab_rect.height += 2 * GTK_NOTEBOOK (wxGTKPrivate::GetNotebookWidget())->tab_hborder;
203 // if no bitmap is set, we need a tiny correction
204 if (! page.bitmap.IsOk())
205 tab_rect.height += 1;
206
207 int gap_height = 6 * GTK_NOTEBOOK (wxGTKPrivate::GetNotebookWidget())->tab_hborder;
208 int gap_y = tab_rect.y - gap_height;
209
210 switch (tab_pos)
211 {
212 case wxAUI_NB_TOP:
213 tab_rect.y -= 2 * GTK_NOTEBOOK (wxGTKPrivate::GetNotebookWidget())->tab_hborder;
214 if (!page.active)
215 tab_rect.y += 2 * GTK_NOTEBOOK (wxGTKPrivate::GetNotebookWidget())->tab_hborder;
216 gap_y = tab_rect.y + tab_rect.height;
217 // fall through
218 case wxAUI_NB_BOTTOM:
219 gap_x = tab_rect.x - GTK_NOTEBOOK (wxGTKPrivate::GetNotebookWidget())->tab_vborder / 2;
220 gap_width = tab_rect.width;
221 break;
222 }
223 tab_rect.y += GTK_NOTEBOOK (wxGTKPrivate::GetNotebookWidget())->tab_hborder / 2;
224 gap_y += GTK_NOTEBOOK (wxGTKPrivate::GetNotebookWidget())->tab_hborder / 2;
225
226 int padding = focus_width + GTK_NOTEBOOK (wxGTKPrivate::GetNotebookWidget())->tab_hborder;
227
228 int clip_width = tab_rect.width;
229 if (tab_rect.x + tab_rect.width > in_rect.x + in_rect.width)
230 clip_width = (in_rect.x + in_rect.width) - tab_rect.x;
231
232 dc.SetClippingRegion(tab_rect.x, tab_rect.y - GTK_NOTEBOOK (wxGTKPrivate::GetNotebookWidget())->tab_vborder, clip_width, tab_rect.height + GTK_NOTEBOOK (wxGTKPrivate::GetNotebookWidget())->tab_vborder);
233
234 GdkRectangle area;
235 area.x = tab_rect.x - GTK_NOTEBOOK (wxGTKPrivate::GetNotebookWidget())->tab_vborder;
236 area.y = tab_rect.y - 2 * GTK_NOTEBOOK (wxGTKPrivate::GetNotebookWidget())->tab_hborder;
237 area.width = clip_width + GTK_NOTEBOOK (wxGTKPrivate::GetNotebookWidget())->tab_vborder;
238 area.height = tab_rect.height + 2 * GTK_NOTEBOOK (wxGTKPrivate::GetNotebookWidget())->tab_hborder;
239
240 wxGTKDCImpl *impldc = (wxGTKDCImpl*) dc.GetImpl();
241 GdkWindow* window = impldc->GetGDKWindow();
242
243 if (tab_pos == wxAUI_NB_BOTTOM)
244 {
245 if (page.active)
246 {
247 gtk_paint_box_gap(style_notebook, window, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
248 NULL, widget,
249 const_cast<char*>("notebook"),
250 window_rect.x, gap_y,
251 window_rect.width, gap_height,
252 GTK_POS_BOTTOM, gap_x , gap_width);
253 }
254 gtk_paint_extension(style_notebook, window,
255 page.active ? GTK_STATE_NORMAL : GTK_STATE_ACTIVE, GTK_SHADOW_OUT,
256 &area, widget,
257 const_cast<char*>("tab"),
258 tab_rect.x, tab_rect.y,
259 tab_rect.width, tab_rect.height,
260 GTK_POS_TOP);
261 }
262 else
263 {
264 if (page.active)
265 {
266 gtk_paint_box_gap(style_notebook, window, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
267 NULL, widget,
268 const_cast<char*>("notebook"),
269 window_rect.x, gap_y,
270 window_rect.width, gap_height,
271 GTK_POS_TOP, gap_x , gap_width);
272 }
273 gtk_paint_extension(style_notebook, window,
274 page.active ? GTK_STATE_NORMAL : GTK_STATE_ACTIVE, GTK_SHADOW_OUT,
275 &area, widget,
276 const_cast<char*>("tab"),
277 tab_rect.x, tab_rect.y,
278 tab_rect.width, tab_rect.height,
279 GTK_POS_BOTTOM);
280 }
281
282 wxCoord textX = tab_rect.x + padding + style_notebook->xthickness;
283
284 int bitmap_offset = 0;
285 if (page.bitmap.IsOk())
286 {
287 bitmap_offset = textX;
288
289 // draw bitmap
290 int bitmapY = tab_rect.y +(tab_rect.height - page.bitmap.GetHeight()) / 2;
291 if(!page.active)
292 {
293 if (tab_pos == wxAUI_NB_TOP)
294 bitmapY += style_notebook->ythickness / 2;
295 else
296 bitmapY -= style_notebook->ythickness / 2;
297 }
298 dc.DrawBitmap(page.bitmap,
299 bitmap_offset,
300 bitmapY,
301 true);
302
303 textX += page.bitmap.GetWidth() + padding;
304 }
305
306 wxCoord textW, textH, textY;
307
308 dc.SetFont(m_normalFont);
309 dc.GetTextExtent(page.caption, &textW, &textH);
310 textY = tab_rect.y + (tab_rect.height - textH) / 2;
311 if(!page.active)
312 {
313 if (tab_pos == wxAUI_NB_TOP)
314 textY += style_notebook->ythickness / 2;
315 else
316 textY -= style_notebook->ythickness / 2;
317 }
318
319 // draw tab text
320 GdkColor text_colour = page.active ? style_notebook->fg[GTK_STATE_NORMAL] : style_notebook->fg[GTK_STATE_ACTIVE];
321 dc.SetTextForeground(wxColor(text_colour));
322 GdkRectangle focus_area;
323
324 int padding_focus = padding - focus_width;
325 focus_area.x = tab_rect.x + padding_focus;
326 focus_area.y = textY - focus_width;
327 focus_area.width = tab_rect.width - 2 * padding_focus;
328 focus_area.height = textH + 2 * focus_width;
329
330 if(page.active && (wnd->FindFocus() == wnd) && focus_area.x <= (area.x + area.width))
331 {
332 // clipping seems not to work here, so we we have to recalc the focus-area manually
333 if((focus_area.x + focus_area.width) > (area.x + area.width))
334 focus_area.width = area.x + area.width - focus_area.x + focus_width - GTK_NOTEBOOK (wxGTKPrivate::GetNotebookWidget())->tab_vborder;
335 gtk_paint_focus (style_notebook, window,
336 GTK_STATE_ACTIVE, NULL, widget, "tab",
337 focus_area.x, focus_area.y, focus_area.width, focus_area.height);
338 }
339
340 dc.DrawText(page.caption, textX, textY);
341
342 // draw close-button on tab (if enabled)
343 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
344 {
345 wxRect rect(tab_rect.x, tab_rect.y, tab_rect.width - style_notebook->xthickness, tab_rect.height);
346 if(!page.active)
347 {
348 if (tab_pos == wxAUI_NB_TOP)
349 rect.y += style_notebook->ythickness / 2;
350 else
351 rect.y -= style_notebook->ythickness / 2;
352 }
353 *out_button_rect = DrawCloseButton(dc, widget, close_button_state, rect, wxRIGHT, &area);
354 }
355
356 tab_rect.width = std::min(tab_rect.width, clip_width);
357 *out_tab_rect = tab_rect;
358
359 dc.DestroyClippingRegion();
360 }
361
362 wxRect DrawSimpleArrow(wxDC& dc,
363 GtkWidget *widget,
364 int button_state,
365 wxRect const &in_rect,
366 int orientation,
367 GtkArrowType arrow_type)
368 {
369 int scroll_arrow_hlength, scroll_arrow_vlength;
370 gtk_widget_style_get(widget,
371 "scroll-arrow-hlength", &scroll_arrow_hlength,
372 "scroll-arrow-vlength", &scroll_arrow_vlength,
373 NULL);
374
375 GtkStateType state;
376 GtkShadowType shadow;
377 ButtonStateAndShadow(button_state, state, shadow);
378
379 wxRect out_rect;
380
381 if (orientation == wxLEFT)
382 out_rect.x = in_rect.x;
383 else
384 out_rect.x = in_rect.x + in_rect.width - scroll_arrow_hlength;
385 out_rect.y = (in_rect.y + in_rect.height - 3 * gtk_widget_get_style(wxGTKPrivate::GetNotebookWidget())->ythickness - scroll_arrow_vlength) / 2;
386 out_rect.width = scroll_arrow_hlength;
387 out_rect.height = scroll_arrow_vlength;
388
389 wxGTKDCImpl *impldc = (wxGTKDCImpl*) dc.GetImpl();
390 GdkWindow* window = impldc->GetGDKWindow();
391 gtk_paint_arrow (gtk_widget_get_style(wxGTKPrivate::GetButtonWidget()), window, state, shadow, NULL, widget, "notebook",
392 arrow_type, TRUE, out_rect.x, out_rect.y, out_rect.width, out_rect.height);
393
394 return out_rect;
395 }
396
397 void wxAuiGtkTabArt::DrawButton(wxDC& dc, wxWindow* wnd,
398 const wxRect& in_rect,
399 int bitmap_id,
400 int button_state,
401 int orientation,
402 wxRect* out_rect)
403 {
404 GtkWidget *widget = wnd->GetHandle();
405 wxRect rect = in_rect;
406 if (m_flags &wxAUI_NB_BOTTOM)
407 rect.y += 2 * gtk_widget_get_style(wxGTKPrivate::GetButtonWidget())->ythickness;
408
409 switch (bitmap_id)
410 {
411 case wxAUI_BUTTON_CLOSE:
412 rect.y -= 2 * gtk_widget_get_style(wxGTKPrivate::GetButtonWidget())->ythickness;
413 rect = DrawCloseButton(dc, widget, button_state, rect, orientation, NULL);
414 break;
415
416 case wxAUI_BUTTON_LEFT:
417 rect = DrawSimpleArrow(dc, widget, button_state, rect, orientation, GTK_ARROW_LEFT);
418 break;
419
420 case wxAUI_BUTTON_RIGHT:
421 rect = DrawSimpleArrow(dc, widget, button_state, rect, orientation, GTK_ARROW_RIGHT);
422 break;
423
424 case wxAUI_BUTTON_WINDOWLIST:
425 {
426 rect.height -= 4 * gtk_widget_get_style(wxGTKPrivate::GetButtonWidget())->ythickness;
427 rect.width = rect.height;
428 rect.x = in_rect.x + in_rect.width - rect.width;
429
430 if (button_state == wxAUI_BUTTON_STATE_HOVER)
431 wxRendererNative::Get().DrawComboBoxDropButton(wnd, dc, rect, wxCONTROL_CURRENT);
432 else if (button_state == wxAUI_BUTTON_STATE_PRESSED)
433 wxRendererNative::Get().DrawComboBoxDropButton(wnd, dc, rect, wxCONTROL_PRESSED);
434 else
435 wxRendererNative::Get().DrawDropArrow(wnd, dc, rect);
436 }
437 break;
438 }
439
440 *out_rect = rect;
441 }
442
443
444 int wxAuiGtkTabArt::GetBestTabCtrlSize(wxWindow* wnd,
445 const wxAuiNotebookPageArray& pages,
446 const wxSize& required_bmp_size)
447 {
448 SetMeasuringFont(m_normalFont);
449 SetSelectedFont(m_normalFont);
450 int tab_height = 3 * gtk_widget_get_style(wxGTKPrivate::GetNotebookWidget())->ythickness + wxAuiGenericTabArt::GetBestTabCtrlSize(wnd, pages, required_bmp_size);
451 return tab_height;
452 }
453
454 wxSize wxAuiGtkTabArt::GetTabSize(wxDC& dc,
455 wxWindow* wnd,
456 const wxString& caption,
457 const wxBitmap& bitmap,
458 bool active,
459 int close_button_state,
460 int* x_extent)
461 {
462 wxSize s = wxAuiGenericTabArt::GetTabSize(dc, wnd, caption, bitmap, active, close_button_state, x_extent);
463
464 int overlap = 0;
465 gtk_widget_style_get (wnd->GetHandle(),
466 "focus-line-width", &overlap,
467 NULL);
468 *x_extent -= overlap;
469 return s;
470 }
471 #endif // wxUSE_AUI