]>
Commit | Line | Data |
---|---|---|
1 | /////////////////////////////////////////////////////////////////////////////// | |
2 | // Name: src/aui/tabart.cpp | |
3 | // Purpose: wxaui: wx advanced user interface - notebook-art | |
4 | // Author: Benjamin I. Williams | |
5 | // Modified by: Jens Lody (moved from auibook.cpp in extra file) | |
6 | // Created: 2012-03-21 | |
7 | // RCS-ID: $Id:$ | |
8 | // Copyright: (C) Copyright 2006, Kirix Corporation, All Rights Reserved | |
9 | // Licence: wxWindows Library Licence, Version 3.1 | |
10 | /////////////////////////////////////////////////////////////////////////////// | |
11 | ||
12 | // ---------------------------------------------------------------------------- | |
13 | // headers | |
14 | // ---------------------------------------------------------------------------- | |
15 | ||
16 | #include "wx/wxprec.h" | |
17 | ||
18 | #ifdef __BORLANDC__ | |
19 | #pragma hdrstop | |
20 | #endif | |
21 | ||
22 | #if wxUSE_AUI | |
23 | ||
24 | #ifndef WX_PRECOMP | |
25 | #include "wx/dc.h" | |
26 | #include "wx/dcclient.h" | |
27 | #include "wx/settings.h" | |
28 | #include "wx/bitmap.h" | |
29 | #include "wx/menu.h" | |
30 | #endif | |
31 | ||
32 | #include "wx/renderer.h" | |
33 | #include "wx/aui/auibook.h" | |
34 | #include "wx/aui/framemanager.h" | |
35 | #include "wx/aui/dockart.h" | |
36 | ||
37 | #ifdef __WXMAC__ | |
38 | #include "wx/osx/private.h" | |
39 | #endif | |
40 | ||
41 | ||
42 | // -- GUI helper classes and functions -- | |
43 | ||
44 | class wxAuiCommandCapture : public wxEvtHandler | |
45 | { | |
46 | public: | |
47 | ||
48 | wxAuiCommandCapture() { m_lastId = 0; } | |
49 | int GetCommandId() const { return m_lastId; } | |
50 | ||
51 | bool ProcessEvent(wxEvent& evt) | |
52 | { | |
53 | if (evt.GetEventType() == wxEVT_COMMAND_MENU_SELECTED) | |
54 | { | |
55 | m_lastId = evt.GetId(); | |
56 | return true; | |
57 | } | |
58 | ||
59 | if (GetNextHandler()) | |
60 | return GetNextHandler()->ProcessEvent(evt); | |
61 | ||
62 | return false; | |
63 | } | |
64 | ||
65 | private: | |
66 | int m_lastId; | |
67 | }; | |
68 | ||
69 | ||
70 | // these functions live in dockart.cpp -- they'll eventually | |
71 | // be moved to a new utility cpp file | |
72 | ||
73 | wxBitmap wxAuiBitmapFromBits(const unsigned char bits[], int w, int h, | |
74 | const wxColour& color); | |
75 | ||
76 | wxString wxAuiChopText(wxDC& dc, const wxString& text, int max_size); | |
77 | ||
78 | static void DrawButtons(wxDC& dc, | |
79 | const wxRect& _rect, | |
80 | const wxBitmap& bmp, | |
81 | const wxColour& bkcolour, | |
82 | int button_state) | |
83 | { | |
84 | wxRect rect = _rect; | |
85 | ||
86 | if (button_state == wxAUI_BUTTON_STATE_PRESSED) | |
87 | { | |
88 | rect.x++; | |
89 | rect.y++; | |
90 | } | |
91 | ||
92 | if (button_state == wxAUI_BUTTON_STATE_HOVER || | |
93 | button_state == wxAUI_BUTTON_STATE_PRESSED) | |
94 | { | |
95 | dc.SetBrush(wxBrush(bkcolour.ChangeLightness(120))); | |
96 | dc.SetPen(wxPen(bkcolour.ChangeLightness(75))); | |
97 | ||
98 | // draw the background behind the button | |
99 | dc.DrawRectangle(rect.x, rect.y, 15, 15); | |
100 | } | |
101 | ||
102 | // draw the button itself | |
103 | dc.DrawBitmap(bmp, rect.x, rect.y, true); | |
104 | } | |
105 | ||
106 | static void IndentPressedBitmap(wxRect* rect, int button_state) | |
107 | { | |
108 | if (button_state == wxAUI_BUTTON_STATE_PRESSED) | |
109 | { | |
110 | rect->x++; | |
111 | rect->y++; | |
112 | } | |
113 | } | |
114 | ||
115 | // -- bitmaps -- | |
116 | ||
117 | #if defined( __WXMAC__ ) | |
118 | static const unsigned char close_bits[]={ | |
119 | 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3, | |
120 | 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3, | |
121 | 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF }; | |
122 | #elif defined( __WXGTK__) | |
123 | static const unsigned char close_bits[]={ | |
124 | 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8, | |
125 | 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef, | |
126 | 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | |
127 | #else | |
128 | static const unsigned char close_bits[]={ | |
129 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xf3, 0xcf, 0xf9, | |
130 | 0x9f, 0xfc, 0x3f, 0xfe, 0x3f, 0xfe, 0x9f, 0xfc, 0xcf, 0xf9, 0xe7, 0xf3, | |
131 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | |
132 | #endif | |
133 | ||
134 | static const unsigned char left_bits[] = { | |
135 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe, | |
136 | 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe, | |
137 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | |
138 | ||
139 | static const unsigned char right_bits[] = { | |
140 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff, | |
141 | 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff, | |
142 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | |
143 | ||
144 | static const unsigned char list_bits[] = { | |
145 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
146 | 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff, | |
147 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | |
148 | ||
149 | ||
150 | ||
151 | ||
152 | ||
153 | ||
154 | // -- wxAuiGenericTabArt class implementation -- | |
155 | ||
156 | wxAuiGenericTabArt::wxAuiGenericTabArt() | |
157 | { | |
158 | m_normalFont = *wxNORMAL_FONT; | |
159 | m_selectedFont = *wxNORMAL_FONT; | |
160 | m_selectedFont.SetWeight(wxBOLD); | |
161 | m_measuringFont = m_selectedFont; | |
162 | ||
163 | m_fixedTabWidth = 100; | |
164 | m_tabCtrlHeight = 0; | |
165 | ||
166 | #if defined( __WXMAC__ ) && wxOSX_USE_COCOA_OR_CARBON | |
167 | wxColor baseColour = wxColour( wxMacCreateCGColorFromHITheme(kThemeBrushToolbarBackground)); | |
168 | #else | |
169 | wxColor baseColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE); | |
170 | #endif | |
171 | ||
172 | // the baseColour is too pale to use as our base colour, | |
173 | // so darken it a bit -- | |
174 | if ((255-baseColour.Red()) + | |
175 | (255-baseColour.Green()) + | |
176 | (255-baseColour.Blue()) < 60) | |
177 | { | |
178 | baseColour = baseColour.ChangeLightness(92); | |
179 | } | |
180 | ||
181 | m_activeColour = baseColour; | |
182 | m_baseColour = baseColour; | |
183 | wxColor borderColour = baseColour.ChangeLightness(75); | |
184 | ||
185 | m_borderPen = wxPen(borderColour); | |
186 | m_baseColourPen = wxPen(m_baseColour); | |
187 | m_baseColourBrush = wxBrush(m_baseColour); | |
188 | ||
189 | m_activeCloseBmp = wxAuiBitmapFromBits(close_bits, 16, 16, *wxBLACK); | |
190 | m_disabledCloseBmp = wxAuiBitmapFromBits(close_bits, 16, 16, wxColour(128,128,128)); | |
191 | ||
192 | m_activeLeftBmp = wxAuiBitmapFromBits(left_bits, 16, 16, *wxBLACK); | |
193 | m_disabledLeftBmp = wxAuiBitmapFromBits(left_bits, 16, 16, wxColour(128,128,128)); | |
194 | ||
195 | m_activeRightBmp = wxAuiBitmapFromBits(right_bits, 16, 16, *wxBLACK); | |
196 | m_disabledRightBmp = wxAuiBitmapFromBits(right_bits, 16, 16, wxColour(128,128,128)); | |
197 | ||
198 | m_activeWindowListBmp = wxAuiBitmapFromBits(list_bits, 16, 16, *wxBLACK); | |
199 | m_disabledWindowListBmp = wxAuiBitmapFromBits(list_bits, 16, 16, wxColour(128,128,128)); | |
200 | ||
201 | m_flags = 0; | |
202 | } | |
203 | ||
204 | wxAuiGenericTabArt::~wxAuiGenericTabArt() | |
205 | { | |
206 | } | |
207 | ||
208 | wxAuiTabArt* wxAuiGenericTabArt::Clone() | |
209 | { | |
210 | return new wxAuiGenericTabArt(*this); | |
211 | } | |
212 | ||
213 | void wxAuiGenericTabArt::SetFlags(unsigned int flags) | |
214 | { | |
215 | m_flags = flags; | |
216 | } | |
217 | ||
218 | void wxAuiGenericTabArt::SetSizingInfo(const wxSize& tab_ctrl_size, | |
219 | size_t tab_count) | |
220 | { | |
221 | m_fixedTabWidth = 100; | |
222 | ||
223 | int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - 4; | |
224 | ||
225 | if (m_flags & wxAUI_NB_CLOSE_BUTTON) | |
226 | tot_width -= m_activeCloseBmp.GetWidth(); | |
227 | if (m_flags & wxAUI_NB_WINDOWLIST_BUTTON) | |
228 | tot_width -= m_activeWindowListBmp.GetWidth(); | |
229 | ||
230 | if (tab_count > 0) | |
231 | { | |
232 | m_fixedTabWidth = tot_width/(int)tab_count; | |
233 | } | |
234 | ||
235 | ||
236 | if (m_fixedTabWidth < 100) | |
237 | m_fixedTabWidth = 100; | |
238 | ||
239 | if (m_fixedTabWidth > tot_width/2) | |
240 | m_fixedTabWidth = tot_width/2; | |
241 | ||
242 | if (m_fixedTabWidth > 220) | |
243 | m_fixedTabWidth = 220; | |
244 | ||
245 | m_tabCtrlHeight = tab_ctrl_size.y; | |
246 | } | |
247 | ||
248 | ||
249 | void wxAuiGenericTabArt::DrawBorder(wxDC& dc, wxWindow* wnd, const wxRect& rect) | |
250 | { | |
251 | int i, border_width = GetBorderWidth(wnd); | |
252 | ||
253 | wxRect theRect(rect); | |
254 | for (i = 0; i < border_width; ++i) | |
255 | { | |
256 | dc.DrawRectangle(theRect.x, theRect.y, theRect.width, theRect.height); | |
257 | theRect.Deflate(1); | |
258 | } | |
259 | } | |
260 | ||
261 | void wxAuiGenericTabArt::DrawBackground(wxDC& dc, | |
262 | wxWindow* WXUNUSED(wnd), | |
263 | const wxRect& rect) | |
264 | { | |
265 | // draw background | |
266 | ||
267 | wxColor top_color = m_baseColour.ChangeLightness(90); | |
268 | wxColor bottom_color = m_baseColour.ChangeLightness(170); | |
269 | wxRect r; | |
270 | ||
271 | if (m_flags &wxAUI_NB_BOTTOM) | |
272 | r = wxRect(rect.x, rect.y, rect.width+2, rect.height); | |
273 | // TODO: else if (m_flags &wxAUI_NB_LEFT) {} | |
274 | // TODO: else if (m_flags &wxAUI_NB_RIGHT) {} | |
275 | else //for wxAUI_NB_TOP | |
276 | r = wxRect(rect.x, rect.y, rect.width+2, rect.height-3); | |
277 | ||
278 | dc.GradientFillLinear(r, top_color, bottom_color, wxSOUTH); | |
279 | ||
280 | ||
281 | // draw base lines | |
282 | ||
283 | dc.SetPen(m_borderPen); | |
284 | int y = rect.GetHeight(); | |
285 | int w = rect.GetWidth(); | |
286 | ||
287 | if (m_flags &wxAUI_NB_BOTTOM) | |
288 | { | |
289 | dc.SetBrush(wxBrush(bottom_color)); | |
290 | dc.DrawRectangle(-1, 0, w+2, 4); | |
291 | } | |
292 | // TODO: else if (m_flags &wxAUI_NB_LEFT) {} | |
293 | // TODO: else if (m_flags &wxAUI_NB_RIGHT) {} | |
294 | else //for wxAUI_NB_TOP | |
295 | { | |
296 | dc.SetBrush(m_baseColourBrush); | |
297 | dc.DrawRectangle(-1, y-4, w+2, 4); | |
298 | } | |
299 | } | |
300 | ||
301 | ||
302 | // DrawTab() draws an individual tab. | |
303 | // | |
304 | // dc - output dc | |
305 | // in_rect - rectangle the tab should be confined to | |
306 | // caption - tab's caption | |
307 | // active - whether or not the tab is active | |
308 | // out_rect - actual output rectangle | |
309 | // x_extent - the advance x; where the next tab should start | |
310 | ||
311 | void wxAuiGenericTabArt::DrawTab(wxDC& dc, | |
312 | wxWindow* wnd, | |
313 | const wxAuiNotebookPage& page, | |
314 | const wxRect& in_rect, | |
315 | int close_button_state, | |
316 | wxRect* out_tab_rect, | |
317 | wxRect* out_button_rect, | |
318 | int* x_extent) | |
319 | { | |
320 | wxCoord normal_textx, normal_texty; | |
321 | wxCoord selected_textx, selected_texty; | |
322 | wxCoord texty; | |
323 | ||
324 | // if the caption is empty, measure some temporary text | |
325 | wxString caption = page.caption; | |
326 | if (caption.empty()) | |
327 | caption = wxT("Xj"); | |
328 | ||
329 | dc.SetFont(m_selectedFont); | |
330 | dc.GetTextExtent(caption, &selected_textx, &selected_texty); | |
331 | ||
332 | dc.SetFont(m_normalFont); | |
333 | dc.GetTextExtent(caption, &normal_textx, &normal_texty); | |
334 | ||
335 | // figure out the size of the tab | |
336 | wxSize tab_size = GetTabSize(dc, | |
337 | wnd, | |
338 | page.caption, | |
339 | page.bitmap, | |
340 | page.active, | |
341 | close_button_state, | |
342 | x_extent); | |
343 | ||
344 | wxCoord tab_height = m_tabCtrlHeight - 3; | |
345 | wxCoord tab_width = tab_size.x; | |
346 | wxCoord tab_x = in_rect.x; | |
347 | wxCoord tab_y = in_rect.y + in_rect.height - tab_height; | |
348 | ||
349 | ||
350 | caption = page.caption; | |
351 | ||
352 | ||
353 | // select pen, brush and font for the tab to be drawn | |
354 | ||
355 | if (page.active) | |
356 | { | |
357 | dc.SetFont(m_selectedFont); | |
358 | texty = selected_texty; | |
359 | } | |
360 | else | |
361 | { | |
362 | dc.SetFont(m_normalFont); | |
363 | texty = normal_texty; | |
364 | } | |
365 | ||
366 | ||
367 | // create points that will make the tab outline | |
368 | ||
369 | int clip_width = tab_width; | |
370 | if (tab_x + clip_width > in_rect.x + in_rect.width) | |
371 | clip_width = (in_rect.x + in_rect.width) - tab_x; | |
372 | ||
373 | /* | |
374 | wxPoint clip_points[6]; | |
375 | clip_points[0] = wxPoint(tab_x, tab_y+tab_height-3); | |
376 | clip_points[1] = wxPoint(tab_x, tab_y+2); | |
377 | clip_points[2] = wxPoint(tab_x+2, tab_y); | |
378 | clip_points[3] = wxPoint(tab_x+clip_width-1, tab_y); | |
379 | clip_points[4] = wxPoint(tab_x+clip_width+1, tab_y+2); | |
380 | clip_points[5] = wxPoint(tab_x+clip_width+1, tab_y+tab_height-3); | |
381 | ||
382 | // FIXME: these ports don't provide wxRegion ctor from array of points | |
383 | #if !defined(__WXDFB__) && !defined(__WXCOCOA__) | |
384 | // set the clipping region for the tab -- | |
385 | wxRegion clipping_region(WXSIZEOF(clip_points), clip_points); | |
386 | dc.SetClippingRegion(clipping_region); | |
387 | #endif // !wxDFB && !wxCocoa | |
388 | */ | |
389 | // since the above code above doesn't play well with WXDFB or WXCOCOA, | |
390 | // we'll just use a rectangle for the clipping region for now -- | |
391 | dc.SetClippingRegion(tab_x, tab_y, clip_width+1, tab_height-3); | |
392 | ||
393 | ||
394 | wxPoint border_points[6]; | |
395 | if (m_flags &wxAUI_NB_BOTTOM) | |
396 | { | |
397 | border_points[0] = wxPoint(tab_x, tab_y); | |
398 | border_points[1] = wxPoint(tab_x, tab_y+tab_height-6); | |
399 | border_points[2] = wxPoint(tab_x+2, tab_y+tab_height-4); | |
400 | border_points[3] = wxPoint(tab_x+tab_width-2, tab_y+tab_height-4); | |
401 | border_points[4] = wxPoint(tab_x+tab_width, tab_y+tab_height-6); | |
402 | border_points[5] = wxPoint(tab_x+tab_width, tab_y); | |
403 | } | |
404 | else //if (m_flags & wxAUI_NB_TOP) {} | |
405 | { | |
406 | border_points[0] = wxPoint(tab_x, tab_y+tab_height-4); | |
407 | border_points[1] = wxPoint(tab_x, tab_y+2); | |
408 | border_points[2] = wxPoint(tab_x+2, tab_y); | |
409 | border_points[3] = wxPoint(tab_x+tab_width-2, tab_y); | |
410 | border_points[4] = wxPoint(tab_x+tab_width, tab_y+2); | |
411 | border_points[5] = wxPoint(tab_x+tab_width, tab_y+tab_height-4); | |
412 | } | |
413 | // TODO: else if (m_flags &wxAUI_NB_LEFT) {} | |
414 | // TODO: else if (m_flags &wxAUI_NB_RIGHT) {} | |
415 | ||
416 | int drawn_tab_yoff = border_points[1].y; | |
417 | int drawn_tab_height = border_points[0].y - border_points[1].y; | |
418 | ||
419 | ||
420 | if (page.active) | |
421 | { | |
422 | // draw active tab | |
423 | ||
424 | // draw base background color | |
425 | wxRect r(tab_x, tab_y, tab_width, tab_height); | |
426 | dc.SetPen(wxPen(m_activeColour)); | |
427 | dc.SetBrush(wxBrush(m_activeColour)); | |
428 | dc.DrawRectangle(r.x+1, r.y+1, r.width-1, r.height-4); | |
429 | ||
430 | // this white helps fill out the gradient at the top of the tab | |
431 | dc.SetPen(*wxWHITE_PEN); | |
432 | dc.SetBrush(*wxWHITE_BRUSH); | |
433 | dc.DrawRectangle(r.x+2, r.y+1, r.width-3, r.height-4); | |
434 | ||
435 | // these two points help the rounded corners appear more antialiased | |
436 | dc.SetPen(wxPen(m_activeColour)); | |
437 | dc.DrawPoint(r.x+2, r.y+1); | |
438 | dc.DrawPoint(r.x+r.width-2, r.y+1); | |
439 | ||
440 | // set rectangle down a bit for gradient drawing | |
441 | r.SetHeight(r.GetHeight()/2); | |
442 | r.x += 2; | |
443 | r.width -= 3; | |
444 | r.y += r.height; | |
445 | r.y -= 2; | |
446 | ||
447 | // draw gradient background | |
448 | wxColor top_color = *wxWHITE; | |
449 | wxColor bottom_color = m_activeColour; | |
450 | dc.GradientFillLinear(r, bottom_color, top_color, wxNORTH); | |
451 | } | |
452 | else | |
453 | { | |
454 | // draw inactive tab | |
455 | ||
456 | wxRect r(tab_x, tab_y+1, tab_width, tab_height-3); | |
457 | ||
458 | // start the gradent up a bit and leave the inside border inset | |
459 | // by a pixel for a 3D look. Only the top half of the inactive | |
460 | // tab will have a slight gradient | |
461 | r.x += 3; | |
462 | r.y++; | |
463 | r.width -= 4; | |
464 | r.height /= 2; | |
465 | r.height--; | |
466 | ||
467 | // -- draw top gradient fill for glossy look | |
468 | wxColor top_color = m_baseColour; | |
469 | wxColor bottom_color = top_color.ChangeLightness(160); | |
470 | dc.GradientFillLinear(r, bottom_color, top_color, wxNORTH); | |
471 | ||
472 | r.y += r.height; | |
473 | r.y--; | |
474 | ||
475 | // -- draw bottom fill for glossy look | |
476 | top_color = m_baseColour; | |
477 | bottom_color = m_baseColour; | |
478 | dc.GradientFillLinear(r, top_color, bottom_color, wxSOUTH); | |
479 | } | |
480 | ||
481 | // draw tab outline | |
482 | dc.SetPen(m_borderPen); | |
483 | dc.SetBrush(*wxTRANSPARENT_BRUSH); | |
484 | dc.DrawPolygon(WXSIZEOF(border_points), border_points); | |
485 | ||
486 | // there are two horizontal grey lines at the bottom of the tab control, | |
487 | // this gets rid of the top one of those lines in the tab control | |
488 | if (page.active) | |
489 | { | |
490 | if (m_flags &wxAUI_NB_BOTTOM) | |
491 | dc.SetPen(wxPen(m_baseColour.ChangeLightness(170))); | |
492 | // TODO: else if (m_flags &wxAUI_NB_LEFT) {} | |
493 | // TODO: else if (m_flags &wxAUI_NB_RIGHT) {} | |
494 | else //for wxAUI_NB_TOP | |
495 | dc.SetPen(m_baseColourPen); | |
496 | dc.DrawLine(border_points[0].x+1, | |
497 | border_points[0].y, | |
498 | border_points[5].x, | |
499 | border_points[5].y); | |
500 | } | |
501 | ||
502 | ||
503 | int text_offset = tab_x + 8; | |
504 | int close_button_width = 0; | |
505 | if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN) | |
506 | { | |
507 | close_button_width = m_activeCloseBmp.GetWidth(); | |
508 | } | |
509 | ||
510 | int bitmap_offset = 0; | |
511 | if (page.bitmap.IsOk()) | |
512 | { | |
513 | bitmap_offset = tab_x + 8; | |
514 | ||
515 | // draw bitmap | |
516 | dc.DrawBitmap(page.bitmap, | |
517 | bitmap_offset, | |
518 | drawn_tab_yoff + (drawn_tab_height/2) - (page.bitmap.GetHeight()/2), | |
519 | true); | |
520 | ||
521 | text_offset = bitmap_offset + page.bitmap.GetWidth(); | |
522 | text_offset += 3; // bitmap padding | |
523 | ||
524 | } | |
525 | else | |
526 | { | |
527 | text_offset = tab_x + 8; | |
528 | } | |
529 | ||
530 | ||
531 | wxString draw_text = wxAuiChopText(dc, | |
532 | caption, | |
533 | tab_width - (text_offset-tab_x) - close_button_width); | |
534 | ||
535 | // draw tab text | |
536 | dc.DrawText(draw_text, | |
537 | text_offset, | |
538 | drawn_tab_yoff + (drawn_tab_height)/2 - (texty/2) - 1); | |
539 | ||
540 | // draw focus rectangle | |
541 | if (page.active && (wnd->FindFocus() == wnd)) | |
542 | { | |
543 | wxRect focusRectText(text_offset, (drawn_tab_yoff + (drawn_tab_height)/2 - (texty/2) - 1), | |
544 | selected_textx, selected_texty); | |
545 | ||
546 | wxRect focusRect; | |
547 | wxRect focusRectBitmap; | |
548 | ||
549 | if (page.bitmap.IsOk()) | |
550 | focusRectBitmap = wxRect(bitmap_offset, drawn_tab_yoff + (drawn_tab_height/2) - (page.bitmap.GetHeight()/2), | |
551 | page.bitmap.GetWidth(), page.bitmap.GetHeight()); | |
552 | ||
553 | if (page.bitmap.IsOk() && draw_text.IsEmpty()) | |
554 | focusRect = focusRectBitmap; | |
555 | else if (!page.bitmap.IsOk() && !draw_text.IsEmpty()) | |
556 | focusRect = focusRectText; | |
557 | else if (page.bitmap.IsOk() && !draw_text.IsEmpty()) | |
558 | focusRect = focusRectText.Union(focusRectBitmap); | |
559 | ||
560 | focusRect.Inflate(2, 2); | |
561 | ||
562 | wxRendererNative::Get().DrawFocusRect(wnd, dc, focusRect, 0); | |
563 | } | |
564 | ||
565 | // draw close button if necessary | |
566 | if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN) | |
567 | { | |
568 | wxBitmap bmp = m_disabledCloseBmp; | |
569 | ||
570 | if (close_button_state == wxAUI_BUTTON_STATE_HOVER || | |
571 | close_button_state == wxAUI_BUTTON_STATE_PRESSED) | |
572 | { | |
573 | bmp = m_activeCloseBmp; | |
574 | } | |
575 | ||
576 | int offsetY = tab_y-1; | |
577 | if (m_flags & wxAUI_NB_BOTTOM) | |
578 | offsetY = 1; | |
579 | ||
580 | wxRect rect(tab_x + tab_width - close_button_width - 1, | |
581 | offsetY + (tab_height/2) - (bmp.GetHeight()/2), | |
582 | close_button_width, | |
583 | tab_height); | |
584 | ||
585 | IndentPressedBitmap(&rect, close_button_state); | |
586 | dc.DrawBitmap(bmp, rect.x, rect.y, true); | |
587 | ||
588 | *out_button_rect = rect; | |
589 | } | |
590 | ||
591 | *out_tab_rect = wxRect(tab_x, tab_y, tab_width, tab_height); | |
592 | ||
593 | dc.DestroyClippingRegion(); | |
594 | } | |
595 | ||
596 | int wxAuiGenericTabArt::GetIndentSize() | |
597 | { | |
598 | return 5; | |
599 | } | |
600 | ||
601 | int wxAuiGenericTabArt::GetBorderWidth(wxWindow* wnd) | |
602 | { | |
603 | wxAuiManager* mgr = wxAuiManager::GetManager(wnd); | |
604 | if (mgr) | |
605 | { | |
606 | wxAuiDockArt* art = mgr->GetArtProvider(); | |
607 | if (art) | |
608 | return art->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE); | |
609 | } | |
610 | return 1; | |
611 | } | |
612 | ||
613 | int wxAuiGenericTabArt::GetAdditionalBorderSpace(wxWindow* WXUNUSED(wnd)) | |
614 | { | |
615 | return 0; | |
616 | } | |
617 | ||
618 | wxSize wxAuiGenericTabArt::GetTabSize(wxDC& dc, | |
619 | wxWindow* WXUNUSED(wnd), | |
620 | const wxString& caption, | |
621 | const wxBitmap& bitmap, | |
622 | bool WXUNUSED(active), | |
623 | int close_button_state, | |
624 | int* x_extent) | |
625 | { | |
626 | wxCoord measured_textx, measured_texty, tmp; | |
627 | ||
628 | dc.SetFont(m_measuringFont); | |
629 | dc.GetTextExtent(caption, &measured_textx, &measured_texty); | |
630 | ||
631 | dc.GetTextExtent(wxT("ABCDEFXj"), &tmp, &measured_texty); | |
632 | ||
633 | // add padding around the text | |
634 | wxCoord tab_width = measured_textx; | |
635 | wxCoord tab_height = measured_texty; | |
636 | ||
637 | // if the close button is showing, add space for it | |
638 | if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN) | |
639 | tab_width += m_activeCloseBmp.GetWidth() + 3; | |
640 | ||
641 | // if there's a bitmap, add space for it | |
642 | if (bitmap.IsOk()) | |
643 | { | |
644 | tab_width += bitmap.GetWidth(); | |
645 | tab_width += 3; // right side bitmap padding | |
646 | tab_height = wxMax(tab_height, bitmap.GetHeight()); | |
647 | } | |
648 | ||
649 | // add padding | |
650 | tab_width += 16; | |
651 | tab_height += 10; | |
652 | ||
653 | if (m_flags & wxAUI_NB_TAB_FIXED_WIDTH) | |
654 | { | |
655 | tab_width = m_fixedTabWidth; | |
656 | } | |
657 | ||
658 | *x_extent = tab_width; | |
659 | ||
660 | return wxSize(tab_width, tab_height); | |
661 | } | |
662 | ||
663 | ||
664 | void wxAuiGenericTabArt::DrawButton(wxDC& dc, | |
665 | wxWindow* WXUNUSED(wnd), | |
666 | const wxRect& in_rect, | |
667 | int bitmap_id, | |
668 | int button_state, | |
669 | int orientation, | |
670 | wxRect* out_rect) | |
671 | { | |
672 | wxBitmap bmp; | |
673 | wxRect rect; | |
674 | ||
675 | switch (bitmap_id) | |
676 | { | |
677 | case wxAUI_BUTTON_CLOSE: | |
678 | if (button_state & wxAUI_BUTTON_STATE_DISABLED) | |
679 | bmp = m_disabledCloseBmp; | |
680 | else | |
681 | bmp = m_activeCloseBmp; | |
682 | break; | |
683 | case wxAUI_BUTTON_LEFT: | |
684 | if (button_state & wxAUI_BUTTON_STATE_DISABLED) | |
685 | bmp = m_disabledLeftBmp; | |
686 | else | |
687 | bmp = m_activeLeftBmp; | |
688 | break; | |
689 | case wxAUI_BUTTON_RIGHT: | |
690 | if (button_state & wxAUI_BUTTON_STATE_DISABLED) | |
691 | bmp = m_disabledRightBmp; | |
692 | else | |
693 | bmp = m_activeRightBmp; | |
694 | break; | |
695 | case wxAUI_BUTTON_WINDOWLIST: | |
696 | if (button_state & wxAUI_BUTTON_STATE_DISABLED) | |
697 | bmp = m_disabledWindowListBmp; | |
698 | else | |
699 | bmp = m_activeWindowListBmp; | |
700 | break; | |
701 | } | |
702 | ||
703 | ||
704 | if (!bmp.IsOk()) | |
705 | return; | |
706 | ||
707 | rect = in_rect; | |
708 | ||
709 | if (orientation == wxLEFT) | |
710 | { | |
711 | rect.SetX(in_rect.x); | |
712 | rect.SetY(((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2)); | |
713 | rect.SetWidth(bmp.GetWidth()); | |
714 | rect.SetHeight(bmp.GetHeight()); | |
715 | } | |
716 | else | |
717 | { | |
718 | rect = wxRect(in_rect.x + in_rect.width - bmp.GetWidth(), | |
719 | ((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2), | |
720 | bmp.GetWidth(), bmp.GetHeight()); | |
721 | } | |
722 | ||
723 | IndentPressedBitmap(&rect, button_state); | |
724 | dc.DrawBitmap(bmp, rect.x, rect.y, true); | |
725 | ||
726 | *out_rect = rect; | |
727 | } | |
728 | ||
729 | int wxAuiGenericTabArt::ShowDropDown(wxWindow* wnd, | |
730 | const wxAuiNotebookPageArray& pages, | |
731 | int /*active_idx*/) | |
732 | { | |
733 | wxMenu menuPopup; | |
734 | ||
735 | size_t i, count = pages.GetCount(); | |
736 | for (i = 0; i < count; ++i) | |
737 | { | |
738 | const wxAuiNotebookPage& page = pages.Item(i); | |
739 | wxString caption = page.caption; | |
740 | ||
741 | // if there is no caption, make it a space. This will prevent | |
742 | // an assert in the menu code. | |
743 | if (caption.IsEmpty()) | |
744 | caption = wxT(" "); | |
745 | ||
746 | wxMenuItem* item = new wxMenuItem(NULL, 1000+i, caption); | |
747 | if (page.bitmap.IsOk()) | |
748 | item->SetBitmap(page.bitmap); | |
749 | menuPopup.Append(item); | |
750 | } | |
751 | ||
752 | // find out where to put the popup menu of window items | |
753 | wxPoint pt = ::wxGetMousePosition(); | |
754 | pt = wnd->ScreenToClient(pt); | |
755 | ||
756 | // find out the screen coordinate at the bottom of the tab ctrl | |
757 | wxRect cli_rect = wnd->GetClientRect(); | |
758 | pt.y = cli_rect.y + cli_rect.height; | |
759 | ||
760 | wxAuiCommandCapture* cc = new wxAuiCommandCapture; | |
761 | wnd->PushEventHandler(cc); | |
762 | wnd->PopupMenu(&menuPopup, pt); | |
763 | int command = cc->GetCommandId(); | |
764 | wnd->PopEventHandler(true); | |
765 | ||
766 | if (command >= 1000) | |
767 | return command-1000; | |
768 | ||
769 | return -1; | |
770 | } | |
771 | ||
772 | int wxAuiGenericTabArt::GetBestTabCtrlSize(wxWindow* wnd, | |
773 | const wxAuiNotebookPageArray& pages, | |
774 | const wxSize& requiredBmp_size) | |
775 | { | |
776 | wxClientDC dc(wnd); | |
777 | dc.SetFont(m_measuringFont); | |
778 | ||
779 | // sometimes a standard bitmap size needs to be enforced, especially | |
780 | // if some tabs have bitmaps and others don't. This is important because | |
781 | // it prevents the tab control from resizing when tabs are added. | |
782 | wxBitmap measureBmp; | |
783 | if (requiredBmp_size.IsFullySpecified()) | |
784 | { | |
785 | measureBmp.Create(requiredBmp_size.x, | |
786 | requiredBmp_size.y); | |
787 | } | |
788 | ||
789 | ||
790 | int max_y = 0; | |
791 | size_t i, page_count = pages.GetCount(); | |
792 | for (i = 0; i < page_count; ++i) | |
793 | { | |
794 | wxAuiNotebookPage& page = pages.Item(i); | |
795 | ||
796 | wxBitmap bmp; | |
797 | if (measureBmp.IsOk()) | |
798 | bmp = measureBmp; | |
799 | else | |
800 | bmp = page.bitmap; | |
801 | ||
802 | // we don't use the caption text because we don't | |
803 | // want tab heights to be different in the case | |
804 | // of a very short piece of text on one tab and a very | |
805 | // tall piece of text on another tab | |
806 | int x_ext = 0; | |
807 | wxSize s = GetTabSize(dc, | |
808 | wnd, | |
809 | wxT("ABCDEFGHIj"), | |
810 | bmp, | |
811 | true, | |
812 | wxAUI_BUTTON_STATE_HIDDEN, | |
813 | &x_ext); | |
814 | ||
815 | max_y = wxMax(max_y, s.y); | |
816 | } | |
817 | ||
818 | return max_y+2; | |
819 | } | |
820 | ||
821 | void wxAuiGenericTabArt::SetNormalFont(const wxFont& font) | |
822 | { | |
823 | m_normalFont = font; | |
824 | } | |
825 | ||
826 | void wxAuiGenericTabArt::SetSelectedFont(const wxFont& font) | |
827 | { | |
828 | m_selectedFont = font; | |
829 | } | |
830 | ||
831 | void wxAuiGenericTabArt::SetMeasuringFont(const wxFont& font) | |
832 | { | |
833 | m_measuringFont = font; | |
834 | } | |
835 | ||
836 | void wxAuiGenericTabArt::SetColour(const wxColour& colour) | |
837 | { | |
838 | m_baseColour = colour; | |
839 | m_borderPen = wxPen(m_baseColour.ChangeLightness(75)); | |
840 | m_baseColourPen = wxPen(m_baseColour); | |
841 | m_baseColourBrush = wxBrush(m_baseColour); | |
842 | } | |
843 | ||
844 | void wxAuiGenericTabArt::SetActiveColour(const wxColour& colour) | |
845 | { | |
846 | m_activeColour = colour; | |
847 | } | |
848 | ||
849 | // -- wxAuiSimpleTabArt class implementation -- | |
850 | ||
851 | wxAuiSimpleTabArt::wxAuiSimpleTabArt() | |
852 | { | |
853 | m_normalFont = *wxNORMAL_FONT; | |
854 | m_selectedFont = *wxNORMAL_FONT; | |
855 | m_selectedFont.SetWeight(wxBOLD); | |
856 | m_measuringFont = m_selectedFont; | |
857 | ||
858 | m_flags = 0; | |
859 | m_fixedTabWidth = 100; | |
860 | ||
861 | wxColour baseColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE); | |
862 | ||
863 | wxColour backgroundColour = baseColour; | |
864 | wxColour normaltabColour = baseColour; | |
865 | wxColour selectedtabColour = *wxWHITE; | |
866 | ||
867 | m_bkBrush = wxBrush(backgroundColour); | |
868 | m_normalBkBrush = wxBrush(normaltabColour); | |
869 | m_normalBkPen = wxPen(normaltabColour); | |
870 | m_selectedBkBrush = wxBrush(selectedtabColour); | |
871 | m_selectedBkPen = wxPen(selectedtabColour); | |
872 | ||
873 | m_activeCloseBmp = wxAuiBitmapFromBits(close_bits, 16, 16, *wxBLACK); | |
874 | m_disabledCloseBmp = wxAuiBitmapFromBits(close_bits, 16, 16, wxColour(128,128,128)); | |
875 | ||
876 | m_activeLeftBmp = wxAuiBitmapFromBits(left_bits, 16, 16, *wxBLACK); | |
877 | m_disabledLeftBmp = wxAuiBitmapFromBits(left_bits, 16, 16, wxColour(128,128,128)); | |
878 | ||
879 | m_activeRightBmp = wxAuiBitmapFromBits(right_bits, 16, 16, *wxBLACK); | |
880 | m_disabledRightBmp = wxAuiBitmapFromBits(right_bits, 16, 16, wxColour(128,128,128)); | |
881 | ||
882 | m_activeWindowListBmp = wxAuiBitmapFromBits(list_bits, 16, 16, *wxBLACK); | |
883 | m_disabledWindowListBmp = wxAuiBitmapFromBits(list_bits, 16, 16, wxColour(128,128,128)); | |
884 | ||
885 | } | |
886 | ||
887 | wxAuiSimpleTabArt::~wxAuiSimpleTabArt() | |
888 | { | |
889 | } | |
890 | ||
891 | wxAuiTabArt* wxAuiSimpleTabArt::Clone() | |
892 | { | |
893 | return new wxAuiSimpleTabArt(*this); | |
894 | } | |
895 | ||
896 | void wxAuiSimpleTabArt::SetFlags(unsigned int flags) | |
897 | { | |
898 | m_flags = flags; | |
899 | } | |
900 | ||
901 | void wxAuiSimpleTabArt::SetSizingInfo(const wxSize& tab_ctrl_size, | |
902 | size_t tab_count) | |
903 | { | |
904 | m_fixedTabWidth = 100; | |
905 | ||
906 | int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - 4; | |
907 | ||
908 | if (m_flags & wxAUI_NB_CLOSE_BUTTON) | |
909 | tot_width -= m_activeCloseBmp.GetWidth(); | |
910 | if (m_flags & wxAUI_NB_WINDOWLIST_BUTTON) | |
911 | tot_width -= m_activeWindowListBmp.GetWidth(); | |
912 | ||
913 | if (tab_count > 0) | |
914 | { | |
915 | m_fixedTabWidth = tot_width/(int)tab_count; | |
916 | } | |
917 | ||
918 | ||
919 | if (m_fixedTabWidth < 100) | |
920 | m_fixedTabWidth = 100; | |
921 | ||
922 | if (m_fixedTabWidth > tot_width/2) | |
923 | m_fixedTabWidth = tot_width/2; | |
924 | ||
925 | if (m_fixedTabWidth > 220) | |
926 | m_fixedTabWidth = 220; | |
927 | } | |
928 | ||
929 | void wxAuiSimpleTabArt::SetColour(const wxColour& colour) | |
930 | { | |
931 | m_bkBrush = wxBrush(colour); | |
932 | m_normalBkBrush = wxBrush(colour); | |
933 | m_normalBkPen = wxPen(colour); | |
934 | } | |
935 | ||
936 | void wxAuiSimpleTabArt::SetActiveColour(const wxColour& colour) | |
937 | { | |
938 | m_selectedBkBrush = wxBrush(colour); | |
939 | m_selectedBkPen = wxPen(colour); | |
940 | } | |
941 | ||
942 | void wxAuiSimpleTabArt::DrawBorder(wxDC& dc, wxWindow* wnd, const wxRect& rect) | |
943 | { | |
944 | int i, border_width = GetBorderWidth(wnd); | |
945 | ||
946 | wxRect theRect(rect); | |
947 | for (i = 0; i < border_width; ++i) | |
948 | { | |
949 | dc.DrawRectangle(theRect.x, theRect.y, theRect.width, theRect.height); | |
950 | theRect.Deflate(1); | |
951 | } | |
952 | } | |
953 | ||
954 | void wxAuiSimpleTabArt::DrawBackground(wxDC& dc, | |
955 | wxWindow* WXUNUSED(wnd), | |
956 | const wxRect& rect) | |
957 | { | |
958 | // draw background | |
959 | dc.SetBrush(m_bkBrush); | |
960 | dc.SetPen(*wxTRANSPARENT_PEN); | |
961 | dc.DrawRectangle(-1, -1, rect.GetWidth()+2, rect.GetHeight()+2); | |
962 | ||
963 | // draw base line | |
964 | dc.SetPen(*wxGREY_PEN); | |
965 | dc.DrawLine(0, rect.GetHeight()-1, rect.GetWidth(), rect.GetHeight()-1); | |
966 | } | |
967 | ||
968 | ||
969 | // DrawTab() draws an individual tab. | |
970 | // | |
971 | // dc - output dc | |
972 | // in_rect - rectangle the tab should be confined to | |
973 | // caption - tab's caption | |
974 | // active - whether or not the tab is active | |
975 | // out_rect - actual output rectangle | |
976 | // x_extent - the advance x; where the next tab should start | |
977 | ||
978 | void wxAuiSimpleTabArt::DrawTab(wxDC& dc, | |
979 | wxWindow* wnd, | |
980 | const wxAuiNotebookPage& page, | |
981 | const wxRect& in_rect, | |
982 | int close_button_state, | |
983 | wxRect* out_tab_rect, | |
984 | wxRect* out_button_rect, | |
985 | int* x_extent) | |
986 | { | |
987 | wxCoord normal_textx, normal_texty; | |
988 | wxCoord selected_textx, selected_texty; | |
989 | wxCoord textx, texty; | |
990 | ||
991 | // if the caption is empty, measure some temporary text | |
992 | wxString caption = page.caption; | |
993 | if (caption.empty()) | |
994 | caption = wxT("Xj"); | |
995 | ||
996 | dc.SetFont(m_selectedFont); | |
997 | dc.GetTextExtent(caption, &selected_textx, &selected_texty); | |
998 | ||
999 | dc.SetFont(m_normalFont); | |
1000 | dc.GetTextExtent(caption, &normal_textx, &normal_texty); | |
1001 | ||
1002 | // figure out the size of the tab | |
1003 | wxSize tab_size = GetTabSize(dc, | |
1004 | wnd, | |
1005 | page.caption, | |
1006 | page.bitmap, | |
1007 | page.active, | |
1008 | close_button_state, | |
1009 | x_extent); | |
1010 | ||
1011 | wxCoord tab_height = tab_size.y; | |
1012 | wxCoord tab_width = tab_size.x; | |
1013 | wxCoord tab_x = in_rect.x; | |
1014 | wxCoord tab_y = in_rect.y + in_rect.height - tab_height; | |
1015 | ||
1016 | caption = page.caption; | |
1017 | ||
1018 | // select pen, brush and font for the tab to be drawn | |
1019 | ||
1020 | if (page.active) | |
1021 | { | |
1022 | dc.SetPen(m_selectedBkPen); | |
1023 | dc.SetBrush(m_selectedBkBrush); | |
1024 | dc.SetFont(m_selectedFont); | |
1025 | textx = selected_textx; | |
1026 | texty = selected_texty; | |
1027 | } | |
1028 | else | |
1029 | { | |
1030 | dc.SetPen(m_normalBkPen); | |
1031 | dc.SetBrush(m_normalBkBrush); | |
1032 | dc.SetFont(m_normalFont); | |
1033 | textx = normal_textx; | |
1034 | texty = normal_texty; | |
1035 | } | |
1036 | ||
1037 | ||
1038 | // -- draw line -- | |
1039 | ||
1040 | wxPoint points[7]; | |
1041 | points[0].x = tab_x; | |
1042 | points[0].y = tab_y + tab_height - 1; | |
1043 | points[1].x = tab_x + tab_height - 3; | |
1044 | points[1].y = tab_y + 2; | |
1045 | points[2].x = tab_x + tab_height + 3; | |
1046 | points[2].y = tab_y; | |
1047 | points[3].x = tab_x + tab_width - 2; | |
1048 | points[3].y = tab_y; | |
1049 | points[4].x = tab_x + tab_width; | |
1050 | points[4].y = tab_y + 2; | |
1051 | points[5].x = tab_x + tab_width; | |
1052 | points[5].y = tab_y + tab_height - 1; | |
1053 | points[6] = points[0]; | |
1054 | ||
1055 | dc.SetClippingRegion(in_rect); | |
1056 | ||
1057 | dc.DrawPolygon(WXSIZEOF(points) - 1, points); | |
1058 | ||
1059 | dc.SetPen(*wxGREY_PEN); | |
1060 | ||
1061 | //dc.DrawLines(active ? WXSIZEOF(points) - 1 : WXSIZEOF(points), points); | |
1062 | dc.DrawLines(WXSIZEOF(points), points); | |
1063 | ||
1064 | ||
1065 | int text_offset; | |
1066 | ||
1067 | int close_button_width = 0; | |
1068 | if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN) | |
1069 | { | |
1070 | close_button_width = m_activeCloseBmp.GetWidth(); | |
1071 | text_offset = tab_x + (tab_height/2) + ((tab_width-close_button_width)/2) - (textx/2); | |
1072 | } | |
1073 | else | |
1074 | { | |
1075 | text_offset = tab_x + (tab_height/3) + (tab_width/2) - (textx/2); | |
1076 | } | |
1077 | ||
1078 | // set minimum text offset | |
1079 | if (text_offset < tab_x + tab_height) | |
1080 | text_offset = tab_x + tab_height; | |
1081 | ||
1082 | // chop text if necessary | |
1083 | wxString draw_text = wxAuiChopText(dc, | |
1084 | caption, | |
1085 | tab_width - (text_offset-tab_x) - close_button_width); | |
1086 | ||
1087 | // draw tab text | |
1088 | dc.DrawText(draw_text, | |
1089 | text_offset, | |
1090 | (tab_y + tab_height)/2 - (texty/2) + 1); | |
1091 | ||
1092 | ||
1093 | // draw focus rectangle | |
1094 | if (page.active && (wnd->FindFocus() == wnd)) | |
1095 | { | |
1096 | wxRect focusRect(text_offset, ((tab_y + tab_height)/2 - (texty/2) + 1), | |
1097 | selected_textx, selected_texty); | |
1098 | ||
1099 | focusRect.Inflate(2, 2); | |
1100 | ||
1101 | wxRendererNative::Get().DrawFocusRect(wnd, dc, focusRect, 0); | |
1102 | } | |
1103 | ||
1104 | // draw close button if necessary | |
1105 | if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN) | |
1106 | { | |
1107 | wxBitmap bmp; | |
1108 | if (page.active) | |
1109 | bmp = m_activeCloseBmp; | |
1110 | else | |
1111 | bmp = m_disabledCloseBmp; | |
1112 | ||
1113 | wxRect rect(tab_x + tab_width - close_button_width - 1, | |
1114 | tab_y + (tab_height/2) - (bmp.GetHeight()/2) + 1, | |
1115 | close_button_width, | |
1116 | tab_height - 1); | |
1117 | DrawButtons(dc, rect, bmp, *wxWHITE, close_button_state); | |
1118 | ||
1119 | *out_button_rect = rect; | |
1120 | } | |
1121 | ||
1122 | ||
1123 | *out_tab_rect = wxRect(tab_x, tab_y, tab_width, tab_height); | |
1124 | ||
1125 | dc.DestroyClippingRegion(); | |
1126 | } | |
1127 | ||
1128 | int wxAuiSimpleTabArt::GetIndentSize() | |
1129 | { | |
1130 | return 0; | |
1131 | } | |
1132 | ||
1133 | int wxAuiSimpleTabArt::GetBorderWidth(wxWindow* wnd) | |
1134 | { | |
1135 | wxAuiManager* mgr = wxAuiManager::GetManager(wnd); | |
1136 | if (mgr) | |
1137 | { | |
1138 | wxAuiDockArt* art = mgr->GetArtProvider(); | |
1139 | if (art) | |
1140 | return art->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE); | |
1141 | } | |
1142 | return 1; | |
1143 | } | |
1144 | ||
1145 | int wxAuiSimpleTabArt::GetAdditionalBorderSpace(wxWindow* WXUNUSED(wnd)) | |
1146 | { | |
1147 | return 0; | |
1148 | } | |
1149 | ||
1150 | wxSize wxAuiSimpleTabArt::GetTabSize(wxDC& dc, | |
1151 | wxWindow* WXUNUSED(wnd), | |
1152 | const wxString& caption, | |
1153 | const wxBitmap& WXUNUSED(bitmap), | |
1154 | bool WXUNUSED(active), | |
1155 | int close_button_state, | |
1156 | int* x_extent) | |
1157 | { | |
1158 | wxCoord measured_textx, measured_texty; | |
1159 | ||
1160 | dc.SetFont(m_measuringFont); | |
1161 | dc.GetTextExtent(caption, &measured_textx, &measured_texty); | |
1162 | ||
1163 | wxCoord tab_height = measured_texty + 4; | |
1164 | wxCoord tab_width = measured_textx + tab_height + 5; | |
1165 | ||
1166 | if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN) | |
1167 | tab_width += m_activeCloseBmp.GetWidth(); | |
1168 | ||
1169 | if (m_flags & wxAUI_NB_TAB_FIXED_WIDTH) | |
1170 | { | |
1171 | tab_width = m_fixedTabWidth; | |
1172 | } | |
1173 | ||
1174 | *x_extent = tab_width - (tab_height/2) - 1; | |
1175 | ||
1176 | return wxSize(tab_width, tab_height); | |
1177 | } | |
1178 | ||
1179 | ||
1180 | void wxAuiSimpleTabArt::DrawButton(wxDC& dc, | |
1181 | wxWindow* WXUNUSED(wnd), | |
1182 | const wxRect& in_rect, | |
1183 | int bitmap_id, | |
1184 | int button_state, | |
1185 | int orientation, | |
1186 | wxRect* out_rect) | |
1187 | { | |
1188 | wxBitmap bmp; | |
1189 | wxRect rect; | |
1190 | ||
1191 | switch (bitmap_id) | |
1192 | { | |
1193 | case wxAUI_BUTTON_CLOSE: | |
1194 | if (button_state & wxAUI_BUTTON_STATE_DISABLED) | |
1195 | bmp = m_disabledCloseBmp; | |
1196 | else | |
1197 | bmp = m_activeCloseBmp; | |
1198 | break; | |
1199 | case wxAUI_BUTTON_LEFT: | |
1200 | if (button_state & wxAUI_BUTTON_STATE_DISABLED) | |
1201 | bmp = m_disabledLeftBmp; | |
1202 | else | |
1203 | bmp = m_activeLeftBmp; | |
1204 | break; | |
1205 | case wxAUI_BUTTON_RIGHT: | |
1206 | if (button_state & wxAUI_BUTTON_STATE_DISABLED) | |
1207 | bmp = m_disabledRightBmp; | |
1208 | else | |
1209 | bmp = m_activeRightBmp; | |
1210 | break; | |
1211 | case wxAUI_BUTTON_WINDOWLIST: | |
1212 | if (button_state & wxAUI_BUTTON_STATE_DISABLED) | |
1213 | bmp = m_disabledWindowListBmp; | |
1214 | else | |
1215 | bmp = m_activeWindowListBmp; | |
1216 | break; | |
1217 | } | |
1218 | ||
1219 | if (!bmp.IsOk()) | |
1220 | return; | |
1221 | ||
1222 | rect = in_rect; | |
1223 | ||
1224 | if (orientation == wxLEFT) | |
1225 | { | |
1226 | rect.SetX(in_rect.x); | |
1227 | rect.SetY(((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2)); | |
1228 | rect.SetWidth(bmp.GetWidth()); | |
1229 | rect.SetHeight(bmp.GetHeight()); | |
1230 | } | |
1231 | else | |
1232 | { | |
1233 | rect = wxRect(in_rect.x + in_rect.width - bmp.GetWidth(), | |
1234 | ((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2), | |
1235 | bmp.GetWidth(), bmp.GetHeight()); | |
1236 | } | |
1237 | ||
1238 | ||
1239 | DrawButtons(dc, rect, bmp, *wxWHITE, button_state); | |
1240 | ||
1241 | *out_rect = rect; | |
1242 | } | |
1243 | ||
1244 | int wxAuiSimpleTabArt::ShowDropDown(wxWindow* wnd, | |
1245 | const wxAuiNotebookPageArray& pages, | |
1246 | int active_idx) | |
1247 | { | |
1248 | wxMenu menuPopup; | |
1249 | ||
1250 | size_t i, count = pages.GetCount(); | |
1251 | for (i = 0; i < count; ++i) | |
1252 | { | |
1253 | const wxAuiNotebookPage& page = pages.Item(i); | |
1254 | menuPopup.AppendCheckItem(1000+i, page.caption); | |
1255 | } | |
1256 | ||
1257 | if (active_idx != -1) | |
1258 | { | |
1259 | menuPopup.Check(1000+active_idx, true); | |
1260 | } | |
1261 | ||
1262 | // find out where to put the popup menu of window | |
1263 | // items. Subtract 100 for now to center the menu | |
1264 | // a bit, until a better mechanism can be implemented | |
1265 | wxPoint pt = ::wxGetMousePosition(); | |
1266 | pt = wnd->ScreenToClient(pt); | |
1267 | if (pt.x < 100) | |
1268 | pt.x = 0; | |
1269 | else | |
1270 | pt.x -= 100; | |
1271 | ||
1272 | // find out the screen coordinate at the bottom of the tab ctrl | |
1273 | wxRect cli_rect = wnd->GetClientRect(); | |
1274 | pt.y = cli_rect.y + cli_rect.height; | |
1275 | ||
1276 | wxAuiCommandCapture* cc = new wxAuiCommandCapture; | |
1277 | wnd->PushEventHandler(cc); | |
1278 | wnd->PopupMenu(&menuPopup, pt); | |
1279 | int command = cc->GetCommandId(); | |
1280 | wnd->PopEventHandler(true); | |
1281 | ||
1282 | if (command >= 1000) | |
1283 | return command-1000; | |
1284 | ||
1285 | return -1; | |
1286 | } | |
1287 | ||
1288 | int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow* wnd, | |
1289 | const wxAuiNotebookPageArray& WXUNUSED(pages), | |
1290 | const wxSize& WXUNUSED(requiredBmp_size)) | |
1291 | { | |
1292 | wxClientDC dc(wnd); | |
1293 | dc.SetFont(m_measuringFont); | |
1294 | int x_ext = 0; | |
1295 | wxSize s = GetTabSize(dc, | |
1296 | wnd, | |
1297 | wxT("ABCDEFGHIj"), | |
1298 | wxNullBitmap, | |
1299 | true, | |
1300 | wxAUI_BUTTON_STATE_HIDDEN, | |
1301 | &x_ext); | |
1302 | return s.y+3; | |
1303 | } | |
1304 | ||
1305 | void wxAuiSimpleTabArt::SetNormalFont(const wxFont& font) | |
1306 | { | |
1307 | m_normalFont = font; | |
1308 | } | |
1309 | ||
1310 | void wxAuiSimpleTabArt::SetSelectedFont(const wxFont& font) | |
1311 | { | |
1312 | m_selectedFont = font; | |
1313 | } | |
1314 | ||
1315 | void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont& font) | |
1316 | { | |
1317 | m_measuringFont = font; | |
1318 | } | |
1319 | ||
1320 | #endif // wxUSE_AUI |