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
NbStyleVC71()37 NbStyleVC71::NbStyleVC71() : wxAuiDefaultTabArt()
38 {
39 }
40
Clone()41 wxAuiTabArt* NbStyleVC71::Clone()
42 {
43 NbStyleVC71* clone = new NbStyleVC71();
44
45 #if wxCHECK_VERSION(3, 0, 0)
46 clone->SetNormalFont(m_normalFont);
47 clone->SetSelectedFont(m_selectedFont);
48 clone->SetMeasuringFont(m_measuringFont);
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
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)58 void NbStyleVC71::DrawTab(wxDC& dc, wxWindow* wnd,
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
93 dc.SetPen((page.active) ? wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT)) : wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW)));
94 dc.SetBrush((page.active) ? wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)) : wxBrush(*wxTRANSPARENT_BRUSH));
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;
105 dc.SetPen(wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW)));
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);
109 dc.SetPen(wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW)));
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();
191 wxBitmap bmp = m_disabledCloseBmp;
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
GetBestTabCtrlSize(wxWindow * wnd,const wxAuiNotebookPageArray & WXUNUSED (pages),const wxSize & WXUNUSED (required_bmp_size))223 int NbStyleVC71::GetBestTabCtrlSize(wxWindow* wnd,
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
NbStyleFF2()241 NbStyleFF2::NbStyleFF2() : wxAuiDefaultTabArt()
242 {
243 }
244
Clone()245 wxAuiTabArt* NbStyleFF2::Clone()
246 {
247 NbStyleFF2* clone = new NbStyleFF2();
248
249 #if wxCHECK_VERSION(3, 0, 0)
250 clone->SetNormalFont(m_normalFont);
251 clone->SetSelectedFont(m_selectedFont);
252 clone->SetMeasuringFont(m_measuringFont);
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
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)262 void NbStyleFF2::DrawTab(wxDC& dc, wxWindow* wnd,
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)));
318 dc.SetBrush((page.active) ? wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)) : wxBrush(*wxTRANSPARENT_BRUSH));
319
320 dc.SetPen(wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW)));
321
322 dc.DrawPolygon(7, tabPoints);
323
324 dc.SetPen(wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)));
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();
385 wxBitmap bmp = m_disabledCloseBmp;
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
GetBestTabCtrlSize(wxWindow * wnd,const wxAuiNotebookPageArray & WXUNUSED (pages),const wxSize & WXUNUSED (required_bmp_size))417 int NbStyleFF2::GetBestTabCtrlSize(wxWindow* wnd,
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
setup_widget_prototype(GtkWidget * widget)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
get_style_button()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
get_style_notebook()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
NbStyleGTK()485 NbStyleGTK::NbStyleGTK():
486 m_Xthickness(0),
487 m_Ythickness(0),
488 m_TabHBorder(0),
489 m_TabVBorder(0)
490
491 {
492 }
493
Clone()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
DrawBackground(wxDC & dc,wxWindow * wnd,const wxRect & rect)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
ButtonStateAndShadow(int button_state,GtkStateType & state,GtkShadowType & shadow)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
DrawCloseButton(wxDC & dc,GtkWidget * widget,int button_state,wxRect const & in_rect,int orientation,GdkRectangle * clipRect)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
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)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
DrawSimpleArrow(wxDC & dc,GtkWidget * widget,int button_state,wxRect const & in_rect,int orientation,GtkArrowType arrow_type)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
DrawButton(wxDC & dc,wxWindow * wnd,const wxRect & in_rect,int bitmap_id,int button_state,int orientation,wxRect * out_rect)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
897 case wxAUI_BUTTON_WINDOWLIST:
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
GetBestTabCtrlSize(wxWindow * wnd,const wxAuiNotebookPageArray & pages,const wxSize & required_bmp_size)920 int NbStyleGTK::GetBestTabCtrlSize(wxWindow* wnd,
921 const wxAuiNotebookPageArray& pages,
922 const wxSize& required_bmp_size)
923 {
924 #if wxCHECK_VERSION(3, 0, 0)
925 SetMeasuringFont(m_normalFont);
926 SetSelectedFont(m_normalFont);
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
GetTabSize(wxDC & dc,wxWindow * wnd,const wxString & caption,const wxBitmap & bitmap,bool active,int close_button_state,int * x_extent)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)
954