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