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