Code::Blocks  SVN r11506
notebookstyles.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
3  * http://www.gnu.org/licenses/gpl-3.0.html
4  */
5 
6 
7 #include <wx/window.h>
8 #include <wx/gdicmn.h>
9 #include <wx/string.h>
10 #include <wx/settings.h>
11 #include <wx/image.h>
12 #include "cbauibook.h"
13 #include "prep.h"
14 #include "notebookstyles.h"
15 
16 #if defined(__WXGTK__) && (USE_GTK_NOTEBOOK) && !wxCHECK_VERSION(3, 0, 0)
17  #define GSocket GLibSocket
18  #include <gtk/gtk.h>
19  #undef GSocket
20  #include <wx/artprov.h>
21  #include <wx/renderer.h>
22 #endif
23 
24 #include <wx/dc.h>
25 #include <wx/dcclient.h>
26 
27 // Some general constants:
28 namespace
29 {
30  const int c_vertical_border_padding = 4;
31 }
32 
33 /******************************************************************************
34 * Renderer for Microsoft (tm) Visual Studio 7.1 like tabs *
35 ******************************************************************************/
36 
38 {
39 }
40 
42 {
43  NbStyleVC71* clone = new NbStyleVC71();
44 
45 #if wxCHECK_VERSION(3, 0, 0)
49 #else
50  clone->SetNormalFont(m_normal_font);
51  clone->SetSelectedFont(m_selected_font);
52  clone->SetMeasuringFont(m_measuring_font);
53 #endif
54 
55  return clone;
56 }
57 
59  const wxAuiNotebookPage& page,
60  const wxRect& in_rect, int close_button_state,
61  wxRect* out_tab_rect, wxRect* out_button_rect,
62  int* x_extent)
63 {
64  // Visual studio 7.1 style
65  // This code is based on the renderer included in wxFlatNotebook:
66  // http://svn.berlios.de/wsvn/codeblocks/trunk/src/sdk/wxFlatNotebook/src/wxFlatNotebook/renderer.cpp?rev=5106
67 
68  // figure out the size of the tab
69 
70  wxSize tab_size = GetTabSize(dc,
71  wnd,
72  page.caption,
73  page.bitmap,
74  page.active,
75  close_button_state,
76  x_extent);
77 
78 #if wxCHECK_VERSION(3, 0, 0)
79  wxCoord tab_height = m_tabCtrlHeight - 3;
80 #else
81  wxCoord tab_height = m_tab_ctrl_height - 3;
82 #endif
83  wxCoord tab_width = tab_size.x;
84  wxCoord tab_x = in_rect.x;
85  wxCoord tab_y = in_rect.y + in_rect.height - tab_height;
86  int clip_width = tab_width;
87  if (tab_x + clip_width > in_rect.x + in_rect.width - 4)
88  clip_width = (in_rect.x + in_rect.width) - tab_x - 4;
89  dc.SetClippingRegion(tab_x, tab_y, clip_width + 1, tab_height - 3);
90  if(m_flags & wxAUI_NB_BOTTOM)
91  tab_y--;
92 
95 
96  if (page.active)
97  {
98 // int tabH = (m_flags & wxAUI_NB_BOTTOM) ? tab_height - 5 : tab_height - 2;
99  int tabH = tab_height - 2;
100 
101  dc.DrawRectangle(tab_x, tab_y, tab_width, tabH);
102 
103  int rightLineY1 = (m_flags & wxAUI_NB_BOTTOM) ? c_vertical_border_padding - 2 : c_vertical_border_padding - 1;
104  int rightLineY2 = tabH + 3;
106  dc.DrawLine(tab_x + tab_width - 1, rightLineY1 + 1, tab_x + tab_width - 1, rightLineY2);
107  if(m_flags & wxAUI_NB_BOTTOM)
108  dc.DrawLine(tab_x + 1, rightLineY2 - 3 , tab_x + tab_width - 1, rightLineY2 - 3);
110  dc.DrawLine(tab_x + tab_width , rightLineY1 , tab_x + tab_width, rightLineY2);
111  if(m_flags & wxAUI_NB_BOTTOM)
112  dc.DrawLine(tab_x , rightLineY2 - 2 , tab_x + tab_width, rightLineY2 - 2);
113 
114  }
115  else
116  {
117  // We dont draw a rectangle for non selected tabs, but only
118  // vertical line on the right
119  int blackLineY1 = (m_flags & wxAUI_NB_BOTTOM) ? c_vertical_border_padding + 2 : c_vertical_border_padding + 1;
120  int blackLineY2 = tab_height - 5;
121  dc.DrawLine(tab_x + tab_width, blackLineY1, tab_x + tab_width, blackLineY2);
122  }
123 
124  wxPoint border_points[2];
125  if (m_flags & wxAUI_NB_BOTTOM)
126  {
127  border_points[0] = wxPoint(tab_x, tab_y);
128  border_points[1] = wxPoint(tab_x, tab_y + tab_height - 6);
129  }
130  else // if (m_flags & wxAUI_NB_TOP)
131  {
132  border_points[0] = wxPoint(tab_x, tab_y + tab_height - 4);
133  border_points[1] = wxPoint(tab_x, tab_y + 2);
134  }
135 
136  int drawn_tab_yoff = border_points[1].y;
137  int drawn_tab_height = border_points[0].y - border_points[1].y;
138 
139  int text_offset = tab_x + 8;
140 
141  int bitmap_offset = 0;
142  if (page.bitmap.IsOk())
143  {
144  bitmap_offset = tab_x + 8;
145 
146  // draw bitmap
147  dc.DrawBitmap(page.bitmap,
148  bitmap_offset,
149  drawn_tab_yoff + (drawn_tab_height/2) - (page.bitmap.GetHeight()/2),
150  true);
151 
152  text_offset = bitmap_offset + page.bitmap.GetWidth();
153  text_offset += 3; // bitmap padding
154  }
155  else
156  {
157  text_offset = tab_x + 8;
158  }
159 
160 
161  // if the caption is empty, measure some temporary text
162  wxString caption = page.caption;
163  if (caption.empty())
164  caption = wxT("Xj");
165 
166  wxCoord textx;
167  wxCoord texty;
168  if (page.active)
169 #if wxCHECK_VERSION(3, 0, 0)
170  dc.SetFont(m_selectedFont);
171 #else
172  dc.SetFont(m_selected_font);
173 #endif
174  else
175 #if wxCHECK_VERSION(3, 0, 0)
176  dc.SetFont(m_normalFont);
177 #else
178  dc.SetFont(m_normal_font);
179 #endif
180  dc.GetTextExtent(caption, &textx, &texty);
181  // draw tab text
182  dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT));
183  dc.DrawText(page.caption, text_offset,
184  drawn_tab_yoff + drawn_tab_height / 2 - texty / 2 - 1);
185 
186  // draw 'x' on tab (if enabled)
187  if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
188  {
189 #if wxCHECK_VERSION(3, 0, 0)
190  int close_button_width = m_activeCloseBmp.GetWidth();
192 #else
193  int close_button_width = m_active_close_bmp.GetWidth();
194  wxBitmap bmp = m_disabled_close_bmp;
195 #endif
196 
197  if ((close_button_state == wxAUI_BUTTON_STATE_HOVER) ||
198  (close_button_state == wxAUI_BUTTON_STATE_PRESSED))
199 #if wxCHECK_VERSION(3, 0, 0)
200  bmp = m_activeCloseBmp;
201 #else
202  bmp = m_active_close_bmp;
203 #endif
204 
205  wxRect rect(tab_x + tab_width - close_button_width - 3,
206  drawn_tab_yoff + (drawn_tab_height / 2) - (bmp.GetHeight() / 2),
207  close_button_width, tab_height);
208 
209  // Indent the button if it is pressed down:
210  if (close_button_state == wxAUI_BUTTON_STATE_PRESSED)
211  {
212  rect.x++;
213  rect.y++;
214  }
215  dc.DrawBitmap(bmp, rect.x, rect.y, true);
216  *out_button_rect = rect;
217  }
218 
219  *out_tab_rect = wxRect(tab_x, tab_y, tab_width, tab_height);
220  dc.DestroyClippingRegion();
221 }
222 
224  const wxAuiNotebookPageArray& WXUNUSED(pages),
225  const wxSize& WXUNUSED(required_bmp_size))
226 {
227 // m_requested_tabctrl_height = -1;
228 // m_tab_ctrl_height = -1;
229  wxClientDC dc(wnd);
230 #if wxCHECK_VERSION(3, 0, 0)
231  dc.SetFont(m_measuringFont);
232 #else
233  dc.SetFont(m_measuring_font);
234 #endif
235  int x_ext = 0;
236  wxSize s = GetTabSize(dc, wnd, wxT("ABCDEFGHIj"), wxNullBitmap, true,
237  wxAUI_BUTTON_STATE_HIDDEN, &x_ext);
238  return s.y + 4;
239 }
240 
242 {
243 }
244 
246 {
247  NbStyleFF2* clone = new NbStyleFF2();
248 
249 #if wxCHECK_VERSION(3, 0, 0)
250  clone->SetNormalFont(m_normalFont);
253 #else
254  clone->SetNormalFont(m_normal_font);
255  clone->SetSelectedFont(m_selected_font);
256  clone->SetMeasuringFont(m_measuring_font);
257 #endif
258 
259  return clone;
260 }
261 
263  const wxAuiNotebookPage& page,
264  const wxRect& in_rect, int close_button_state,
265  wxRect* out_tab_rect, wxRect* out_button_rect,
266  int* x_extent)
267 {
268 
269  // Firefox 2 style
270 
271  // figure out the size of the tab
272  wxSize tab_size = GetTabSize(dc, wnd, page.caption, page.bitmap,
273  page.active, close_button_state, x_extent);
274 
275 #if wxCHECK_VERSION(3, 0, 0)
276  wxCoord tab_height = m_tabCtrlHeight - 2;
277 #else
278  wxCoord tab_height = m_tab_ctrl_height - 2;
279 #endif
280  wxCoord tab_width = tab_size.x;
281  wxCoord tab_x = in_rect.x;
282  wxCoord tab_y = in_rect.y + in_rect.height - tab_height;
283 
284  int clip_width = tab_width;
285  if (tab_x + clip_width > in_rect.x + in_rect.width - 4)
286  clip_width = (in_rect.x + in_rect.width) - tab_x - 4;
287  dc.SetClippingRegion(tab_x, tab_y, clip_width + 1, tab_height - 3);
288 
289  wxPoint tabPoints[7];
290  int adjust = 0;
291  if (!page.active)
292  {
293  adjust = 1;
294  }
295 
296  tabPoints[0].x = tab_x + 3;
297  tabPoints[0].y = (m_flags & wxAUI_NB_BOTTOM) ? 3 : tab_height - 2;
298 
299  tabPoints[1].x = tabPoints[0].x;
300  tabPoints[1].y = (m_flags & wxAUI_NB_BOTTOM) ? tab_height - (c_vertical_border_padding + 2) - adjust : (c_vertical_border_padding + 2) + adjust;
301 
302  tabPoints[2].x = tabPoints[1].x+2;
303  tabPoints[2].y = (m_flags & wxAUI_NB_BOTTOM) ? tab_height - c_vertical_border_padding - adjust: c_vertical_border_padding + adjust;
304 
305  tabPoints[3].x = tab_x +tab_width - 2;
306  tabPoints[3].y = tabPoints[2].y;
307 
308  tabPoints[4].x = tabPoints[3].x + 2;
309  tabPoints[4].y = tabPoints[1].y;
310 
311  tabPoints[5].x = tabPoints[4].x;
312  tabPoints[5].y = tabPoints[0].y;
313 
314  tabPoints[6].x = tabPoints[0].x;
315  tabPoints[6].y = tabPoints[0].y;
316 
317 // dc.SetBrush((page.active) ? wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)) : wxBrush(wxAuiStepColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE),85)));
319 
321 
322  dc.DrawPolygon(7, tabPoints);
323 
325  if (page.active)
326  {
327  dc.DrawLine(tabPoints[0].x + 1, tabPoints[0].y, tabPoints[5].x , tabPoints[0].y);
328  }
329 
330  int drawn_tab_yoff = tabPoints[1].y;
331  int drawn_tab_height = tabPoints[0].y - tabPoints[2].y;
332 
333  int text_offset = tab_x + 8;
334 
335  int bitmap_offset = 0;
336  if (page.bitmap.IsOk())
337  {
338  bitmap_offset = tab_x + 8;
339 
340  // draw bitmap
341  dc.DrawBitmap(page.bitmap,
342  bitmap_offset,
343  drawn_tab_yoff + (drawn_tab_height/2) - (page.bitmap.GetHeight()/2),
344  true);
345 
346  text_offset = bitmap_offset + page.bitmap.GetWidth();
347  text_offset += 3; // bitmap padding
348  }
349  else
350  {
351  text_offset = tab_x + 8;
352  }
353 
354 
355  // if the caption is empty, measure some temporary text
356  wxString caption = page.caption;
357  if (caption.empty())
358  caption = wxT("Xj");
359 
360  wxCoord textx;
361  wxCoord texty;
362  if (page.active)
363 #if wxCHECK_VERSION(3, 0, 0)
364  dc.SetFont(m_selectedFont);
365 #else
366  dc.SetFont(m_selected_font);
367 #endif
368  else
369 #if wxCHECK_VERSION(3, 0, 0)
370  dc.SetFont(m_normalFont);
371 #else
372  dc.SetFont(m_normal_font);
373 #endif
374  dc.GetTextExtent(caption, &textx, &texty);
375  // draw tab text
376  dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT));
377  dc.DrawText(page.caption, text_offset,
378  drawn_tab_yoff + drawn_tab_height / 2 - texty / 2 - 1);
379 
380  // draw 'x' on tab (if enabled)
381  if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
382  {
383 #if wxCHECK_VERSION(3, 0, 0)
384  int close_button_width = m_activeCloseBmp.GetWidth();
386 #else
387  int close_button_width = m_active_close_bmp.GetWidth();
388  wxBitmap bmp = m_disabled_close_bmp;
389 #endif
390 
391  if ((close_button_state == wxAUI_BUTTON_STATE_HOVER) ||
392  (close_button_state == wxAUI_BUTTON_STATE_PRESSED))
393 #if wxCHECK_VERSION(3, 0, 0)
394  bmp = m_activeCloseBmp;
395 #else
396  bmp = m_active_close_bmp;
397 #endif
398 
399  wxRect rect(tab_x + tab_width - close_button_width - 3,
400  drawn_tab_yoff + (drawn_tab_height / 2) - (bmp.GetHeight() / 2),
401  close_button_width, tab_height);
402 
403  // Indent the button if it is pressed down:
404  if (close_button_state == wxAUI_BUTTON_STATE_PRESSED)
405  {
406  rect.x++;
407  rect.y++;
408  }
409  dc.DrawBitmap(bmp, rect.x, rect.y, true);
410  *out_button_rect = rect;
411  }
412 
413  *out_tab_rect = wxRect(tab_x, tab_y, tab_width, tab_height);
414  dc.DestroyClippingRegion();
415 }
416 
418  const wxAuiNotebookPageArray& WXUNUSED(pages),
419  const wxSize& WXUNUSED(required_bmp_size))
420 {
421 // m_requested_tabctrl_height = -1;
422 // m_tab_ctrl_height = -1;
423  wxClientDC dc(wnd);
424 #if wxCHECK_VERSION(3, 0, 0)
425  dc.SetFont(m_measuringFont);
426 #else
427  dc.SetFont(m_measuring_font);
428 #endif
429  int x_ext = 0;
430  wxSize s = GetTabSize(dc, wnd, wxT("ABCDEFGHIj"), wxNullBitmap, true,
431  wxAUI_BUTTON_STATE_HIDDEN, &x_ext);
432  return s.y + 6;
433 }
434 
435 #if defined(__WXGTK__) && (USE_GTK_NOTEBOOK) && !wxCHECK_VERSION(3, 0, 0)
436 
437 namespace
438 {
439 
440 static GtkWidget *g_window = nullptr;
441 static GtkWidget *g_container = nullptr;
442 static GtkWidget *g_notebook = nullptr;
443 static GtkWidget *g_button = nullptr;
444 static int s_CloseIconSize = 16; // default size
445 
446 static void setup_widget_prototype(GtkWidget* widget)
447 {
448  if (!g_window)
449  {
450  g_window = gtk_window_new(GTK_WINDOW_POPUP);
451  gtk_widget_realize(g_window);
452  }
453  if (!g_container)
454  {
455  g_container = gtk_fixed_new();
456  gtk_container_add(GTK_CONTAINER(g_window), g_container);
457  }
458 
459  gtk_container_add(GTK_CONTAINER(g_container), widget);
460  gtk_widget_realize(widget);
461 }
462 
463 static GtkStyle * get_style_button()
464 {
465  if (!g_button)
466  {
467  g_button = gtk_button_new();
468  setup_widget_prototype(g_button);
469  }
470  return gtk_widget_get_style(g_button);
471 }
472 
473 static GtkStyle * get_style_notebook()
474 {
475  if (!g_notebook)
476  {
477  g_notebook = gtk_notebook_new();
478  setup_widget_prototype(g_notebook);
479  }
480  return gtk_widget_get_style(g_notebook);
481 }
482 
483 }
484 
485 NbStyleGTK::NbStyleGTK():
486  m_Xthickness(0),
487  m_Ythickness(0),
488  m_TabHBorder(0),
489  m_TabVBorder(0)
490 
491 {
492 }
493 
494 wxAuiTabArt* NbStyleGTK::Clone()
495 {
496  NbStyleGTK* clone = new NbStyleGTK();
497 
498 #if wxCHECK_VERSION(3, 0, 0)
499  clone->SetNormalFont(m_normalFont);
500  clone->SetSelectedFont(m_normalFont);
501  clone->SetMeasuringFont(m_normalFont);
502 #else
503  clone->SetNormalFont(m_normal_font);
504  clone->SetSelectedFont(m_normal_font);
505  clone->SetMeasuringFont(m_normal_font);
506 #endif
507 
508  return clone;
509 }
510 
511 void NbStyleGTK::DrawBackground(wxDC& dc, wxWindow* wnd, const wxRect& rect)
512 {
513  GtkStyle* style_notebook = get_style_notebook();
514  GtkNotebook* notebook = GTK_NOTEBOOK (g_notebook);
515 
516  // if one of the parameters have changed, the height needs to be recalculated, so we force it,
517  if(m_Xthickness != style_notebook->xthickness ||
518  m_Ythickness != style_notebook->ythickness ||
519  m_TabVBorder != notebook->tab_vborder ||
520  m_TabHBorder != notebook->tab_hborder)
521  {
522  m_Xthickness = style_notebook->xthickness;
523  m_Ythickness = style_notebook->ythickness;
524  m_TabVBorder = notebook->tab_vborder;
525  m_TabHBorder = notebook->tab_hborder;
526  wxAuiNotebook* nb = nullptr;
527  if(wnd)
528  nb = (cbAuiNotebook*)wnd->GetParent();
529  if(nb)
530  nb->SetTabCtrlHeight(-1);
531  }
532 #if wxCHECK_VERSION(3, 0, 0)
533  wxGTKDCImpl *impldc = (wxGTKDCImpl*) dc.GetImpl();
534  GdkWindow* pWin = impldc->GetGDKWindow();
535 #else
536  GdkWindow* pWin = dc.GetGDKWindow();
537 #endif
538  gtk_style_apply_default_background(style_notebook, pWin, 1, GTK_STATE_NORMAL, nullptr,
539  rect.x, rect.y, rect.width, rect.height);
540 }
541 
542 void ButtonStateAndShadow(int button_state, GtkStateType &state, GtkShadowType &shadow)
543 {
544 
545  if (button_state & wxAUI_BUTTON_STATE_DISABLED)
546  {
547  state = GTK_STATE_INSENSITIVE;
548  shadow = GTK_SHADOW_ETCHED_IN;
549  }
550  else if (button_state & wxAUI_BUTTON_STATE_HOVER)
551  {
552  state = GTK_STATE_PRELIGHT;
553  shadow = GTK_SHADOW_OUT;
554  }
555  else if (button_state & wxAUI_BUTTON_STATE_PRESSED)
556  {
557  state = GTK_STATE_ACTIVE;
558  shadow = GTK_SHADOW_IN;
559  }
560  else
561  {
562  state = GTK_STATE_NORMAL;
563  shadow = GTK_SHADOW_OUT;
564  }
565 }
566 
567 wxRect DrawCloseButton(wxDC& dc,
568  GtkWidget *widget,
569  int button_state,
570  wxRect const &in_rect,
571  int orientation,
572  GdkRectangle* clipRect)
573 {
574  GtkStyle *style_button = get_style_button();
575  int xthickness = style_button->xthickness;
576  int ythickness = style_button->ythickness;
577 
578  wxBitmap bmp;
579  bmp.SetPixbuf(gtk_widget_render_icon(widget, GTK_STOCK_CLOSE, GTK_ICON_SIZE_SMALL_TOOLBAR, "tab"));
580 
581  if(bmp.GetWidth() != s_CloseIconSize || bmp.GetHeight() != s_CloseIconSize)
582  {
583  wxImage img = bmp.ConvertToImage();
584  img.Rescale(s_CloseIconSize, s_CloseIconSize);
585  bmp = img;
586  }
587 
588  int button_size = s_CloseIconSize + 2 * xthickness;
589 
590  wxRect out_rect;
591 
592  if (orientation == wxLEFT)
593  out_rect.x = in_rect.x - ythickness;
594  else
595  out_rect.x = in_rect.x + in_rect.width - button_size - ythickness;
596 
597  out_rect.y = in_rect.y + (in_rect.height - button_size) / 2;
598  out_rect.width = button_size;
599  out_rect.height = button_size;
600 
601 #if wxCHECK_VERSION(3, 0, 0)
602  wxGTKDCImpl *impldc = (wxGTKDCImpl*) dc.GetImpl();
603  GdkWindow* pWin = impldc->GetGDKWindow();
604 #else
605  GdkWindow* pWin = dc.GetGDKWindow();
606 #endif
607 
608  if (button_state == wxAUI_BUTTON_STATE_HOVER)
609  {
610  gtk_paint_box(style_button, pWin,
611  GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, clipRect, widget, "button",
612  out_rect.x, out_rect.y, out_rect.width, out_rect.height);
613  }
614  else if (button_state == wxAUI_BUTTON_STATE_PRESSED)
615  {
616  gtk_paint_box(style_button, pWin,
617  GTK_STATE_ACTIVE, GTK_SHADOW_IN, clipRect, widget, "button",
618  out_rect.x, out_rect.y, out_rect.width, out_rect.height);
619  }
620 
621 
622  dc.DrawBitmap(bmp, out_rect.x + xthickness, out_rect.y + ythickness, true);
623 
624  return out_rect;
625 }
626 
627 void NbStyleGTK::DrawTab(wxDC& dc, wxWindow* wnd, const wxAuiNotebookPage& page,
628  const wxRect& in_rect, int close_button_state, wxRect* out_tab_rect,
629  wxRect* out_button_rect, int* x_extent)
630 {
631  GtkWidget *widget = wnd->GetHandle();
632  GtkStyle *style_notebook = get_style_notebook();
633 
634  wxRect const &window_rect = wnd->GetRect();
635 
636  int focus_width = 0;
637 
638  gtk_widget_style_get(g_notebook,
639  "focus-line-width", &focus_width,
640  NULL);
641 
642  int tab_pos;
643  if (m_flags &wxAUI_NB_BOTTOM)
644  tab_pos = wxAUI_NB_BOTTOM;
645  else //if (m_flags & wxAUI_NB_TOP) {}
646  tab_pos = wxAUI_NB_TOP;
647 
648  // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
649  // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
650 
651  // figure out the size of the tab
652  wxSize tab_size = GetTabSize(dc, wnd, page.caption, page.bitmap,
653  page.active, close_button_state, x_extent);
654 
655  wxRect tab_rect = in_rect;
656  tab_rect.width = tab_size.x;
657  tab_rect.height = tab_size.y;
658  tab_rect.y += 2 * m_TabHBorder;
659 
660  if (page.active)
661  tab_rect.height += 2 * m_TabHBorder;
662 #if wxCHECK_VERSION(3, 0, 0)
663  // if no bitmap is set, we need a tiny correction
664  if (! page.bitmap.IsOk())
665  tab_rect.height += 1;
666 #endif
667 
668  int gap_rect_height = 6 * m_TabHBorder;
669  int gap_rect_x = 1, gap_start = 0, gap_width = 0;
670  int gap_rect_y = tab_rect.y - gap_rect_height;
671  int gap_rect_width = window_rect.width;
672 
673  switch (tab_pos)
674  {
675  case wxAUI_NB_TOP:
676  tab_rect.y -= 2 * m_TabHBorder;
677  if (!page.active)
678  tab_rect.y += 2 * m_TabHBorder;
679  gap_rect_y = tab_rect.y + tab_rect.height - m_TabHBorder / 2;
680  // fall through
681  case wxAUI_NB_BOTTOM:
682  gap_start = tab_rect.x - m_TabVBorder / 2;
683  gap_width = tab_rect.width;
684  break;
685  default:
686  break;
687  }
688  tab_rect.y += m_TabHBorder / 2;
689  gap_rect_y += m_TabHBorder / 2;
690 
691  int padding = focus_width + m_TabHBorder;
692 
693  int clip_width = tab_rect.width;
694  if (tab_rect.x + tab_rect.width > in_rect.x + in_rect.width)
695  clip_width = (in_rect.x + in_rect.width) - tab_rect.x;
696 
697  dc.SetClippingRegion(tab_rect.x, tab_rect.y - m_TabVBorder, clip_width, tab_rect.height + m_TabVBorder);
698 
699  GdkRectangle area;
700  area.x = tab_rect.x - m_TabVBorder;
701  area.y = tab_rect.y - 2 * m_TabHBorder;
702  area.width = clip_width + m_TabVBorder;
703  area.height = tab_rect.height + 2 * m_TabHBorder;
704 
705 #if wxCHECK_VERSION(3, 0, 0)
706  wxGTKDCImpl *impldc = (wxGTKDCImpl*) dc.GetImpl();
707  GdkWindow* pWin = impldc->GetGDKWindow();
708 #else
709  GdkWindow* pWin = dc.GetGDKWindow();
710 #endif
711 
712  if (tab_pos == wxAUI_NB_BOTTOM)
713  {
714  if (page.active)
715  {
716  gtk_paint_box_gap(style_notebook, pWin, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
717  NULL, widget, "notebook",
718  gap_rect_x, gap_rect_y,
719  gap_rect_width, gap_rect_height,
720  GTK_POS_BOTTOM, gap_start , gap_width);
721  }
722  gtk_paint_extension(style_notebook, pWin,
723  page.active ? GTK_STATE_NORMAL : GTK_STATE_ACTIVE, GTK_SHADOW_OUT,
724  &area, widget, "tab",
725  tab_rect.x, tab_rect.y,
726  tab_rect.width, tab_rect.height,
727  GTK_POS_TOP);
728  }
729  else
730  {
731  if (page.active)
732  {
733  gtk_paint_box_gap(style_notebook, pWin, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
734  NULL, widget, "notebook",
735  gap_rect_x, gap_rect_y,
736  gap_rect_width, gap_rect_height,
737  GTK_POS_TOP, gap_start , gap_width);
738  }
739  gtk_paint_extension(style_notebook, pWin,
740  page.active ? GTK_STATE_NORMAL : GTK_STATE_ACTIVE, GTK_SHADOW_OUT,
741  &area, widget, "tab",
742  tab_rect.x, tab_rect.y,
743  tab_rect.width, tab_rect.height,
744  GTK_POS_BOTTOM);
745  }
746 
747  wxCoord textX = tab_rect.x + padding + m_Xthickness;
748 
749  int bitmap_offset = 0;
750  if (page.bitmap.IsOk())
751  {
752  bitmap_offset = textX;
753 
754  // draw bitmap
755  int bitmapY = tab_rect.y +(tab_rect.height - page.bitmap.GetHeight()) / 2;
756  if(!page.active)
757  {
758  if (tab_pos == wxAUI_NB_TOP)
759  bitmapY += m_Ythickness / 2;
760  else
761  bitmapY -= m_Ythickness / 2;
762  }
763  dc.DrawBitmap(page.bitmap,
764  bitmap_offset,
765  bitmapY,
766  true);
767 
768  textX += page.bitmap.GetWidth() + padding;
769  }
770 
771  wxCoord textW, textH, textY;
772 
773 #if wxCHECK_VERSION(3, 0, 0)
774  dc.SetFont(m_normalFont);
775 #else
776  dc.SetFont(m_normal_font);
777 #endif
778  dc.GetTextExtent(page.caption, &textW, &textH);
779  textY = tab_rect.y + (tab_rect.height - textH) / 2;
780  if(!page.active)
781  {
782  if (tab_pos == wxAUI_NB_TOP)
783  textY += m_Ythickness / 2;
784  else
785  textY -= m_Ythickness / 2;
786  }
787 
788  // draw tab text
789  GdkColor text_colour = page.active ? style_notebook->fg[GTK_STATE_NORMAL] : style_notebook->fg[GTK_STATE_ACTIVE];
790  dc.SetTextForeground(wxColor(text_colour));
791  GdkRectangle focus_area;
792 
793  int padding_focus = padding - focus_width;
794  focus_area.x = tab_rect.x + padding_focus;
795  focus_area.y = textY - focus_width;
796  focus_area.width = tab_rect.width - 2 * padding_focus;
797  focus_area.height = textH + 2 * focus_width;
798 
799  if(page.active && (wnd->FindFocus() == wnd) && focus_area.x <= (area.x + area.width))
800  {
801  // clipping seems not to work here, so we we have to recalc the focus-area manually
802  if((focus_area.x + focus_area.width) > (area.x + area.width))
803  focus_area.width = area.x + area.width - focus_area.x + focus_width - m_TabVBorder;
804  gtk_paint_focus (style_notebook, pWin,
805  GTK_STATE_ACTIVE, NULL, widget, "tab",
806  focus_area.x, focus_area.y, focus_area.width, focus_area.height);
807  }
808 
809  dc.DrawText(page.caption, textX, textY);
810 
811  // draw close-button on tab (if enabled)
812  if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
813  {
814  wxRect rect(tab_rect.x, tab_rect.y, tab_rect.width - m_Xthickness, tab_rect.height);
815  if(!page.active)
816  {
817  if (tab_pos == wxAUI_NB_TOP)
818  rect.y += m_Ythickness / 2;
819  else
820  rect.y -= m_Ythickness / 2;
821  }
822  *out_button_rect = DrawCloseButton(dc, widget, close_button_state, rect, wxRIGHT, &area);
823  }
824 
825  tab_rect.width = std::min(tab_rect.width, clip_width);
826  *out_tab_rect = tab_rect;
827 
828  dc.DestroyClippingRegion();
829 }
830 
831 wxRect DrawSimpleArrow(wxDC& dc,
832  GtkWidget *widget,
833  int button_state,
834  wxRect const &in_rect,
835  int orientation,
836  GtkArrowType arrow_type)
837 {
838  int scroll_arrow_hlength, scroll_arrow_vlength;
839  gtk_widget_style_get(widget,
840  "scroll-arrow-hlength", &scroll_arrow_hlength,
841  "scroll-arrow-vlength", &scroll_arrow_vlength,
842  NULL);
843 
844  GtkStateType state;
845  GtkShadowType shadow;
846  ButtonStateAndShadow(button_state, state, shadow);
847 
848  wxRect out_rect;
849 
850  if (orientation == wxLEFT)
851  out_rect.x = in_rect.x;
852  else
853  out_rect.x = in_rect.x + in_rect.width - scroll_arrow_hlength;
854  out_rect.y = (in_rect.y + in_rect.height - 3 * get_style_notebook()->ythickness - scroll_arrow_vlength) / 2;
855  out_rect.width = scroll_arrow_hlength;
856  out_rect.height = scroll_arrow_vlength;
857 
858 #if wxCHECK_VERSION(3, 0, 0)
859  wxGTKDCImpl *impldc = (wxGTKDCImpl*) dc.GetImpl();
860  GdkWindow* pWin = impldc->GetGDKWindow();
861 #else
862  GdkWindow* pWin = dc.GetGDKWindow();
863 #endif
864  gtk_paint_arrow (get_style_button(), pWin, state, shadow, nullptr, widget, "notebook",
865  arrow_type, TRUE, out_rect.x, out_rect.y, out_rect.width, out_rect.height);
866 
867  return out_rect;
868 }
869 
870 void NbStyleGTK::DrawButton(wxDC& dc, wxWindow* wnd,
871  const wxRect& in_rect,
872  int bitmap_id,
873  int button_state,
874  int orientation,
875  wxRect* out_rect)
876 {
877  GtkWidget *widget = wnd->GetHandle();
878  wxRect rect = in_rect;
879  if (m_flags &wxAUI_NB_BOTTOM)
880  rect.y += 2 * get_style_button()->ythickness;
881 
882  switch (bitmap_id)
883  {
884  case wxAUI_BUTTON_CLOSE:
885  rect.y -= 2 * get_style_button()->ythickness;
886  rect = DrawCloseButton(dc, widget, button_state, rect, orientation, NULL);
887  break;
888 
889  case wxAUI_BUTTON_LEFT:
890  rect = DrawSimpleArrow(dc, widget, button_state, rect, orientation, GTK_ARROW_LEFT);
891  break;
892 
893  case wxAUI_BUTTON_RIGHT:
894  rect = DrawSimpleArrow(dc, widget, button_state, rect, orientation, GTK_ARROW_RIGHT);
895  break;
896 
898  {
899  rect.height -= 4 * get_style_button()->ythickness;
900  rect.width = rect.height;
901  rect.x = in_rect.x + in_rect.width - rect.width;
902 
903  if (button_state == wxAUI_BUTTON_STATE_HOVER)
904  wxRendererNative::Get().DrawComboBoxDropButton(wnd, dc, rect, wxCONTROL_CURRENT);
905  else if (button_state == wxAUI_BUTTON_STATE_PRESSED)
906  wxRendererNative::Get().DrawComboBoxDropButton(wnd, dc, rect, wxCONTROL_PRESSED);
907  else
908  wxRendererNative::Get().DrawDropArrow(wnd, dc, rect);
909  }
910  break;
911 
912  default:
913  break;
914  }
915 
916  *out_rect = rect;
917 }
918 
919 
920 int NbStyleGTK::GetBestTabCtrlSize(wxWindow* wnd,
921  const wxAuiNotebookPageArray& pages,
922  const wxSize& required_bmp_size)
923 {
924 #if wxCHECK_VERSION(3, 0, 0)
927 #else
928  SetMeasuringFont(m_normal_font);
929  SetSelectedFont(m_normal_font);
930 #endif
931  int tab_height = 3 * get_style_notebook()->ythickness + wxAuiDefaultTabArt::GetBestTabCtrlSize(wnd, pages, required_bmp_size);
932  return tab_height;
933 }
934 
935 wxSize NbStyleGTK::GetTabSize(wxDC& dc,
936  wxWindow* wnd,
937  const wxString& caption,
938  const wxBitmap& bitmap,
939  bool active,
940  int close_button_state,
941  int* x_extent)
942 {
943  wxSize s = wxAuiDefaultTabArt::GetTabSize(dc, wnd, caption, bitmap, active, close_button_state, x_extent);
944 
945  int overlap = 0;
946  gtk_widget_style_get (wnd->GetHandle(),
947  "focus-line-width", &overlap,
948  NULL);
949  *x_extent -= overlap;
950  return s;
951 }
952 
953 #endif // #if defined(__WXGTK__) && (USE_GTK_NOTEBOOK) && !wxCHECK_VERSION(3, 0, 0)
unsigned int m_flags
wxBrush * wxTRANSPARENT_BRUSH
void SetSelectedFont(const wxFont &font)
wxAuiTabArt * Clone()
int GetBestTabCtrlSize(wxWindow *wnd, const wxAuiNotebookPageArray &pages, const wxSize &requiredBmpSize)
int GetBestTabCtrlSize(wxWindow *wnd, const wxAuiNotebookPageArray &pages, const wxSize &required_bmp_size)
wxImage & Rescale(int width, int height, wxImageResizeQuality quality=wxIMAGE_QUALITY_NORMAL)
void SetNormalFont(const wxFont &font)
void DrawTab(wxDC &dc, wxWindow *wnd, const wxAuiNotebookPage &page, const wxRect &in_rect, int close_button_state, wxRect *out_tab_rect, wxRect *out_button_rect, int *x_extent)
virtual wxImage ConvertToImage() const
#define wxT(string)
bool empty() const
virtual void SetTabCtrlHeight(int height)
wxSize GetTabSize(wxDC &dc, wxWindow *wnd, const wxString &caption, const wxBitmap &bitmap, bool active, int closeButtonState, int *xExtent)
virtual int GetWidth() const
wxBitmap m_activeCloseBmp
static wxColour GetColour(wxSystemColour index)
int width
int GetBestTabCtrlSize(wxWindow *wnd, const wxAuiNotebookPageArray &pages, const wxSize &required_bmp_size)
wxAuiTabArt * Clone()
A notebook class This class is derived from wxAuiNotebook, to enhance its abilities.
Definition: cbauibook.h:30
virtual int GetHeight() const
void SetMeasuringFont(const wxFont &font)
int height
wxBitmap wxNullBitmap
int wxCoord
void DrawTab(wxDC &dc, wxWindow *wnd, const wxAuiNotebookPage &page, const wxRect &in_rect, int close_button_state, wxRect *out_tab_rect, wxRect *out_button_rect, int *x_extent)
#define NULL
Definition: prefix.cpp:59
wxBitmap m_disabledCloseBmp