Draw wxAuiToolbar button text even if it has no bitmap.
[wxWidgets.git] / src / aui / auibar.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2
3 // Name: src/aui/auibar.cpp
4 // Purpose: wxaui: wx advanced user interface - docking window manager
5 // Author: Benjamin I. Williams
6 // Modified by:
7 // Created: 2005-05-17
8 // RCS-ID: $Id$
9 // Copyright: (C) Copyright 2005-2006, Kirix Corporation, All Rights Reserved
10 // Licence: wxWindows Library Licence, Version 3.1
11 ///////////////////////////////////////////////////////////////////////////////
12
13 // ============================================================================
14 // declarations
15 // ============================================================================
16
17 // ----------------------------------------------------------------------------
18 // headers
19 // ----------------------------------------------------------------------------
20
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #if wxUSE_AUI
28
29 #include "wx/statline.h"
30 #include "wx/dcbuffer.h"
31 #include "wx/sizer.h"
32 #include "wx/image.h"
33 #include "wx/settings.h"
34 #include "wx/menu.h"
35
36 #include "wx/aui/auibar.h"
37 #include "wx/aui/framemanager.h"
38
39 #ifdef __WXMAC__
40 #include "wx/osx/private.h"
41 #endif
42
43 #include "wx/arrimpl.cpp"
44 WX_DEFINE_OBJARRAY(wxAuiToolBarItemArray)
45
46
47 wxDEFINE_EVENT( wxEVT_COMMAND_AUITOOLBAR_TOOL_DROPDOWN, wxAuiToolBarEvent );
48 wxDEFINE_EVENT( wxEVT_COMMAND_AUITOOLBAR_OVERFLOW_CLICK, wxAuiToolBarEvent );
49 wxDEFINE_EVENT( wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK, wxAuiToolBarEvent );
50 wxDEFINE_EVENT( wxEVT_COMMAND_AUITOOLBAR_MIDDLE_CLICK, wxAuiToolBarEvent );
51 wxDEFINE_EVENT( wxEVT_COMMAND_AUITOOLBAR_BEGIN_DRAG, wxAuiToolBarEvent );
52
53
54 IMPLEMENT_CLASS(wxAuiToolBar, wxControl)
55 IMPLEMENT_DYNAMIC_CLASS(wxAuiToolBarEvent, wxEvent)
56
57
58 // missing wxITEM_* items
59 enum
60 {
61 wxITEM_CONTROL = wxITEM_MAX,
62 wxITEM_LABEL,
63 wxITEM_SPACER
64 };
65
66 const int BUTTON_DROPDOWN_WIDTH = 10;
67
68
69 wxBitmap wxAuiBitmapFromBits(const unsigned char bits[], int w, int h,
70 const wxColour& color);
71
72 static wxBitmap MakeDisabledBitmap(wxBitmap& bmp)
73 {
74 wxImage image = bmp.ConvertToImage();
75
76 int mr, mg, mb;
77 mr = image.GetMaskRed();
78 mg = image.GetMaskGreen();
79 mb = image.GetMaskBlue();
80
81 unsigned char* data = image.GetData();
82 int width = image.GetWidth();
83 int height = image.GetHeight();
84 bool has_mask = image.HasMask();
85
86 for (int y = height-1; y >= 0; --y)
87 {
88 for (int x = width-1; x >= 0; --x)
89 {
90 data = image.GetData() + (y*(width*3))+(x*3);
91 unsigned char* r = data;
92 unsigned char* g = data+1;
93 unsigned char* b = data+2;
94
95 if (has_mask && *r == mr && *g == mg && *b == mb)
96 continue;
97
98 *r = wxColour::AlphaBlend(*r, 255, 0.4);
99 *g = wxColour::AlphaBlend(*g, 255, 0.4);
100 *b = wxColour::AlphaBlend(*b, 255, 0.4);
101 }
102 }
103
104 return wxBitmap(image);
105 }
106
107 static wxColor GetBaseColor()
108 {
109
110 #if defined( __WXMAC__ ) && wxOSX_USE_COCOA_OR_CARBON
111 wxColor base_colour = wxColour( wxMacCreateCGColorFromHITheme(kThemeBrushToolbarBackground));
112 #else
113 wxColor base_colour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
114 #endif
115
116 // the base_colour is too pale to use as our base colour,
117 // so darken it a bit --
118 if ((255-base_colour.Red()) +
119 (255-base_colour.Green()) +
120 (255-base_colour.Blue()) < 60)
121 {
122 base_colour = base_colour.ChangeLightness(92);
123 }
124
125 return base_colour;
126 }
127
128
129
130 class ToolbarCommandCapture : public wxEvtHandler
131 {
132 public:
133
134 ToolbarCommandCapture() { m_last_id = 0; }
135 int GetCommandId() const { return m_last_id; }
136
137 bool ProcessEvent(wxEvent& evt)
138 {
139 if (evt.GetEventType() == wxEVT_COMMAND_MENU_SELECTED)
140 {
141 m_last_id = evt.GetId();
142 return true;
143 }
144
145 if (GetNextHandler())
146 return GetNextHandler()->ProcessEvent(evt);
147
148 return false;
149 }
150
151 private:
152 int m_last_id;
153 };
154
155
156
157 static const unsigned char
158 DISABLED_TEXT_GREY_HUE = wxColour::AlphaBlend(0, 255, 0.4);
159 const wxColour DISABLED_TEXT_COLOR(DISABLED_TEXT_GREY_HUE,
160 DISABLED_TEXT_GREY_HUE,
161 DISABLED_TEXT_GREY_HUE);
162
163 wxAuiDefaultToolBarArt::wxAuiDefaultToolBarArt()
164 {
165 m_base_colour = GetBaseColor();
166
167 m_flags = 0;
168 m_text_orientation = wxAUI_TBTOOL_TEXT_BOTTOM;
169 m_highlight_colour = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
170
171 m_separator_size = 7;
172 m_gripper_size = 7;
173 m_overflow_size = 16;
174
175 wxColor darker1_colour = m_base_colour.ChangeLightness(85);
176 wxColor darker2_colour = m_base_colour.ChangeLightness(75);
177 wxColor darker3_colour = m_base_colour.ChangeLightness(60);
178 wxColor darker4_colour = m_base_colour.ChangeLightness(50);
179 wxColor darker5_colour = m_base_colour.ChangeLightness(40);
180
181 m_gripper_pen1 = wxPen(darker5_colour);
182 m_gripper_pen2 = wxPen(darker3_colour);
183 m_gripper_pen3 = *wxWHITE_PEN;
184
185 static const unsigned char button_dropdown_bits[] = { 0xe0, 0xf1, 0xfb };
186 static const unsigned char overflow_bits[] = { 0x80, 0xff, 0x80, 0xc1, 0xe3, 0xf7 };
187
188 m_button_dropdown_bmp = wxAuiBitmapFromBits(button_dropdown_bits, 5, 3,
189 *wxBLACK);
190 m_disabled_button_dropdown_bmp = wxAuiBitmapFromBits(
191 button_dropdown_bits, 5, 3,
192 wxColor(128,128,128));
193 m_overflow_bmp = wxAuiBitmapFromBits(overflow_bits, 7, 6, *wxBLACK);
194 m_disabled_overflow_bmp = wxAuiBitmapFromBits(overflow_bits, 7, 6, wxColor(128,128,128));
195
196 m_font = *wxNORMAL_FONT;
197 }
198
199 wxAuiDefaultToolBarArt::~wxAuiDefaultToolBarArt()
200 {
201 m_font = *wxNORMAL_FONT;
202 }
203
204
205 wxAuiToolBarArt* wxAuiDefaultToolBarArt::Clone()
206 {
207 return static_cast<wxAuiToolBarArt*>(new wxAuiDefaultToolBarArt);
208 }
209
210 void wxAuiDefaultToolBarArt::SetFlags(unsigned int flags)
211 {
212 m_flags = flags;
213 }
214
215 void wxAuiDefaultToolBarArt::SetFont(const wxFont& font)
216 {
217 m_font = font;
218 }
219
220 void wxAuiDefaultToolBarArt::SetTextOrientation(int orientation)
221 {
222 m_text_orientation = orientation;
223 }
224
225 unsigned int wxAuiDefaultToolBarArt::GetFlags()
226 {
227 return m_flags;
228 }
229
230 wxFont wxAuiDefaultToolBarArt::GetFont()
231 {
232 return m_font;
233 }
234
235 int wxAuiDefaultToolBarArt::GetTextOrientation()
236 {
237 return m_text_orientation;
238 }
239
240 void wxAuiDefaultToolBarArt::DrawBackground(
241 wxDC& dc,
242 wxWindow* WXUNUSED(wnd),
243 const wxRect& _rect)
244 {
245 wxRect rect = _rect;
246 rect.height++;
247 wxColour start_colour = m_base_colour.ChangeLightness(150);
248 wxColour end_colour = m_base_colour.ChangeLightness(90);
249 dc.GradientFillLinear(rect, start_colour, end_colour, wxSOUTH);
250 }
251
252 void wxAuiDefaultToolBarArt::DrawLabel(
253 wxDC& dc,
254 wxWindow* WXUNUSED(wnd),
255 const wxAuiToolBarItem& item,
256 const wxRect& rect)
257 {
258 dc.SetFont(m_font);
259 dc.SetTextForeground(*wxBLACK);
260
261 // we only care about the text height here since the text
262 // will get cropped based on the width of the item
263 int text_width = 0, text_height = 0;
264 dc.GetTextExtent(wxT("ABCDHgj"), &text_width, &text_height);
265
266 // set the clipping region
267 wxRect clip_rect = rect;
268 clip_rect.width -= 1;
269 dc.SetClippingRegion(clip_rect);
270
271 int text_x, text_y;
272 text_x = rect.x + 1;
273 text_y = rect.y + (rect.height-text_height)/2;
274 dc.DrawText(item.GetLabel(), text_x, text_y);
275 dc.DestroyClippingRegion();
276 }
277
278
279 void wxAuiDefaultToolBarArt::DrawButton(
280 wxDC& dc,
281 wxWindow* WXUNUSED(wnd),
282 const wxAuiToolBarItem& item,
283 const wxRect& rect)
284 {
285 int text_width = 0, text_height = 0;
286
287 if (m_flags & wxAUI_TB_TEXT)
288 {
289 dc.SetFont(m_font);
290
291 int tx, ty;
292
293 dc.GetTextExtent(wxT("ABCDHgj"), &tx, &text_height);
294 text_width = 0;
295 dc.GetTextExtent(item.GetLabel(), &text_width, &ty);
296 }
297
298 int bmp_x = 0, bmp_y = 0;
299 int text_x = 0, text_y = 0;
300
301 if (m_text_orientation == wxAUI_TBTOOL_TEXT_BOTTOM)
302 {
303 bmp_x = rect.x +
304 (rect.width/2) -
305 (item.GetBitmap().GetWidth()/2);
306
307 bmp_y = rect.y +
308 ((rect.height-text_height)/2) -
309 (item.GetBitmap().GetHeight()/2);
310
311 text_x = rect.x + (rect.width/2) - (text_width/2) + 1;
312 text_y = rect.y + rect.height - text_height - 1;
313 }
314 else if (m_text_orientation == wxAUI_TBTOOL_TEXT_RIGHT)
315 {
316 bmp_x = rect.x + 3;
317
318 bmp_y = rect.y +
319 (rect.height/2) -
320 (item.GetBitmap().GetHeight()/2);
321
322 text_x = bmp_x + 3 + item.GetBitmap().GetWidth();
323 text_y = rect.y +
324 (rect.height/2) -
325 (text_height/2);
326 }
327
328
329 if (!(item.GetState() & wxAUI_BUTTON_STATE_DISABLED))
330 {
331 if (item.GetState() & wxAUI_BUTTON_STATE_PRESSED)
332 {
333 dc.SetPen(wxPen(m_highlight_colour));
334 dc.SetBrush(wxBrush(m_highlight_colour.ChangeLightness(150)));
335 dc.DrawRectangle(rect);
336 }
337 else if ((item.GetState() & wxAUI_BUTTON_STATE_HOVER) || item.IsSticky())
338 {
339 dc.SetPen(wxPen(m_highlight_colour));
340 dc.SetBrush(wxBrush(m_highlight_colour.ChangeLightness(170)));
341
342 // draw an even lighter background for checked item hovers (since
343 // the hover background is the same color as the check background)
344 if (item.GetState() & wxAUI_BUTTON_STATE_CHECKED)
345 dc.SetBrush(wxBrush(m_highlight_colour.ChangeLightness(180)));
346
347 dc.DrawRectangle(rect);
348 }
349 else if (item.GetState() & wxAUI_BUTTON_STATE_CHECKED)
350 {
351 // it's important to put this code in an else statment after the
352 // hover, otherwise hovers won't draw properly for checked items
353 dc.SetPen(wxPen(m_highlight_colour));
354 dc.SetBrush(wxBrush(m_highlight_colour.ChangeLightness(170)));
355 dc.DrawRectangle(rect);
356 }
357 }
358
359 wxBitmap bmp;
360 if (item.GetState() & wxAUI_BUTTON_STATE_DISABLED)
361 bmp = item.GetDisabledBitmap();
362 else
363 bmp = item.GetBitmap();
364
365 if ( bmp.IsOk() )
366 dc.DrawBitmap(bmp, bmp_x, bmp_y, true);
367
368 // set the item's text color based on if it is disabled
369 dc.SetTextForeground(*wxBLACK);
370 if (item.GetState() & wxAUI_BUTTON_STATE_DISABLED)
371 dc.SetTextForeground(DISABLED_TEXT_COLOR);
372
373 if ( (m_flags & wxAUI_TB_TEXT) && !item.GetLabel().empty() )
374 {
375 dc.DrawText(item.GetLabel(), text_x, text_y);
376 }
377 }
378
379
380 void wxAuiDefaultToolBarArt::DrawDropDownButton(
381 wxDC& dc,
382 wxWindow* WXUNUSED(wnd),
383 const wxAuiToolBarItem& item,
384 const wxRect& rect)
385 {
386 int text_width = 0, text_height = 0, text_x = 0, text_y = 0;
387 int bmp_x = 0, bmp_y = 0, dropbmp_x = 0, dropbmp_y = 0;
388
389 wxRect button_rect = wxRect(rect.x,
390 rect.y,
391 rect.width-BUTTON_DROPDOWN_WIDTH,
392 rect.height);
393 wxRect dropdown_rect = wxRect(rect.x+rect.width-BUTTON_DROPDOWN_WIDTH-1,
394 rect.y,
395 BUTTON_DROPDOWN_WIDTH+1,
396 rect.height);
397
398 if (m_flags & wxAUI_TB_TEXT)
399 {
400 dc.SetFont(m_font);
401
402 int tx, ty;
403 if (m_flags & wxAUI_TB_TEXT)
404 {
405 dc.GetTextExtent(wxT("ABCDHgj"), &tx, &text_height);
406 text_width = 0;
407 }
408
409 dc.GetTextExtent(item.GetLabel(), &text_width, &ty);
410 }
411
412
413
414 dropbmp_x = dropdown_rect.x +
415 (dropdown_rect.width/2) -
416 (m_button_dropdown_bmp.GetWidth()/2);
417 dropbmp_y = dropdown_rect.y +
418 (dropdown_rect.height/2) -
419 (m_button_dropdown_bmp.GetHeight()/2);
420
421
422 if (m_text_orientation == wxAUI_TBTOOL_TEXT_BOTTOM)
423 {
424 bmp_x = button_rect.x +
425 (button_rect.width/2) -
426 (item.GetBitmap().GetWidth()/2);
427 bmp_y = button_rect.y +
428 ((button_rect.height-text_height)/2) -
429 (item.GetBitmap().GetHeight()/2);
430
431 text_x = rect.x + (rect.width/2) - (text_width/2) + 1;
432 text_y = rect.y + rect.height - text_height - 1;
433 }
434 else if (m_text_orientation == wxAUI_TBTOOL_TEXT_RIGHT)
435 {
436 bmp_x = rect.x + 3;
437
438 bmp_y = rect.y +
439 (rect.height/2) -
440 (item.GetBitmap().GetHeight()/2);
441
442 text_x = bmp_x + 3 + item.GetBitmap().GetWidth();
443 text_y = rect.y +
444 (rect.height/2) -
445 (text_height/2);
446 }
447
448
449 if (item.GetState() & wxAUI_BUTTON_STATE_PRESSED)
450 {
451 dc.SetPen(wxPen(m_highlight_colour));
452 dc.SetBrush(wxBrush(m_highlight_colour.ChangeLightness(140)));
453 dc.DrawRectangle(button_rect);
454
455 dc.SetBrush(wxBrush(m_highlight_colour.ChangeLightness(170)));
456 dc.DrawRectangle(dropdown_rect);
457 }
458 else if (item.GetState() & wxAUI_BUTTON_STATE_HOVER ||
459 item.IsSticky())
460 {
461 dc.SetPen(wxPen(m_highlight_colour));
462 dc.SetBrush(wxBrush(m_highlight_colour.ChangeLightness(170)));
463 dc.DrawRectangle(button_rect);
464 dc.DrawRectangle(dropdown_rect);
465 }
466
467 wxBitmap bmp;
468 wxBitmap dropbmp;
469 if (item.GetState() & wxAUI_BUTTON_STATE_DISABLED)
470 {
471 bmp = item.GetDisabledBitmap();
472 dropbmp = m_disabled_button_dropdown_bmp;
473 }
474 else
475 {
476 bmp = item.GetBitmap();
477 dropbmp = m_button_dropdown_bmp;
478 }
479
480 if (!bmp.IsOk())
481 return;
482
483 dc.DrawBitmap(bmp, bmp_x, bmp_y, true);
484 dc.DrawBitmap(dropbmp, dropbmp_x, dropbmp_y, true);
485
486 // set the item's text color based on if it is disabled
487 dc.SetTextForeground(*wxBLACK);
488 if (item.GetState() & wxAUI_BUTTON_STATE_DISABLED)
489 dc.SetTextForeground(DISABLED_TEXT_COLOR);
490
491 if ( (m_flags & wxAUI_TB_TEXT) && !item.GetLabel().empty() )
492 {
493 dc.DrawText(item.GetLabel(), text_x, text_y);
494 }
495 }
496
497 void wxAuiDefaultToolBarArt::DrawControlLabel(
498 wxDC& dc,
499 wxWindow* WXUNUSED(wnd),
500 const wxAuiToolBarItem& item,
501 const wxRect& rect)
502 {
503 if (!(m_flags & wxAUI_TB_TEXT))
504 return;
505
506 if (m_text_orientation != wxAUI_TBTOOL_TEXT_BOTTOM)
507 return;
508
509 int text_x = 0, text_y = 0;
510 int text_width = 0, text_height = 0;
511
512 dc.SetFont(m_font);
513
514 int tx, ty;
515 if (m_flags & wxAUI_TB_TEXT)
516 {
517 dc.GetTextExtent(wxT("ABCDHgj"), &tx, &text_height);
518 text_width = 0;
519 }
520
521 dc.GetTextExtent(item.GetLabel(), &text_width, &ty);
522
523 // don't draw the label if it is wider than the item width
524 if (text_width > rect.width)
525 return;
526
527 // set the label's text color
528 dc.SetTextForeground(*wxBLACK);
529
530 text_x = rect.x + (rect.width/2) - (text_width/2) + 1;
531 text_y = rect.y + rect.height - text_height - 1;
532
533 if ( (m_flags & wxAUI_TB_TEXT) && !item.GetLabel().empty() )
534 {
535 dc.DrawText(item.GetLabel(), text_x, text_y);
536 }
537 }
538
539 wxSize wxAuiDefaultToolBarArt::GetLabelSize(
540 wxDC& dc,
541 wxWindow* WXUNUSED(wnd),
542 const wxAuiToolBarItem& item)
543 {
544 dc.SetFont(m_font);
545
546 // get label's height
547 int width = 0, height = 0;
548 dc.GetTextExtent(wxT("ABCDHgj"), &width, &height);
549
550 // get item's width
551 width = item.GetMinSize().GetWidth();
552
553 if (width == -1)
554 {
555 // no width specified, measure the text ourselves
556 width = dc.GetTextExtent(item.GetLabel()).GetX();
557 }
558
559 return wxSize(width, height);
560 }
561
562 wxSize wxAuiDefaultToolBarArt::GetToolSize(
563 wxDC& dc,
564 wxWindow* WXUNUSED(wnd),
565 const wxAuiToolBarItem& item)
566 {
567 if (!item.GetBitmap().IsOk() && !(m_flags & wxAUI_TB_TEXT))
568 return wxSize(16,16);
569
570 int width = item.GetBitmap().GetWidth();
571 int height = item.GetBitmap().GetHeight();
572
573 if (m_flags & wxAUI_TB_TEXT)
574 {
575 dc.SetFont(m_font);
576 int tx, ty;
577
578 if (m_text_orientation == wxAUI_TBTOOL_TEXT_BOTTOM)
579 {
580 dc.GetTextExtent(wxT("ABCDHgj"), &tx, &ty);
581 height += ty;
582
583 if ( !item.GetLabel().empty() )
584 {
585 dc.GetTextExtent(item.GetLabel(), &tx, &ty);
586 width = wxMax(width, tx+6);
587 }
588 }
589 else if ( m_text_orientation == wxAUI_TBTOOL_TEXT_RIGHT &&
590 !item.GetLabel().empty() )
591 {
592 width += 3; // space between left border and bitmap
593 width += 3; // space between bitmap and text
594
595 if ( !item.GetLabel().empty() )
596 {
597 dc.GetTextExtent(item.GetLabel(), &tx, &ty);
598 width += tx;
599 height = wxMax(height, ty);
600 }
601 }
602 }
603
604 // if the tool has a dropdown button, add it to the width
605 if (item.HasDropDown())
606 width += (BUTTON_DROPDOWN_WIDTH+4);
607
608 return wxSize(width, height);
609 }
610
611 void wxAuiDefaultToolBarArt::DrawSeparator(
612 wxDC& dc,
613 wxWindow* WXUNUSED(wnd),
614 const wxRect& _rect)
615 {
616 bool horizontal = true;
617 if (m_flags & wxAUI_TB_VERTICAL)
618 horizontal = false;
619
620 wxRect rect = _rect;
621
622 if (horizontal)
623 {
624 rect.x += (rect.width/2);
625 rect.width = 1;
626 int new_height = (rect.height*3)/4;
627 rect.y += (rect.height/2) - (new_height/2);
628 rect.height = new_height;
629 }
630 else
631 {
632 rect.y += (rect.height/2);
633 rect.height = 1;
634 int new_width = (rect.width*3)/4;
635 rect.x += (rect.width/2) - (new_width/2);
636 rect.width = new_width;
637 }
638
639 wxColour start_colour = m_base_colour.ChangeLightness(80);
640 wxColour end_colour = m_base_colour.ChangeLightness(80);
641 dc.GradientFillLinear(rect, start_colour, end_colour, horizontal ? wxSOUTH : wxEAST);
642 }
643
644 void wxAuiDefaultToolBarArt::DrawGripper(wxDC& dc,
645 wxWindow* WXUNUSED(wnd),
646 const wxRect& rect)
647 {
648 int i = 0;
649 while (1)
650 {
651 int x, y;
652
653 if (m_flags & wxAUI_TB_VERTICAL)
654 {
655 x = rect.x + (i*4) + 5;
656 y = rect.y + 3;
657 if (x > rect.GetWidth()-5)
658 break;
659 }
660 else
661 {
662 x = rect.x + 3;
663 y = rect.y + (i*4) + 5;
664 if (y > rect.GetHeight()-5)
665 break;
666 }
667
668 dc.SetPen(m_gripper_pen1);
669 dc.DrawPoint(x, y);
670 dc.SetPen(m_gripper_pen2);
671 dc.DrawPoint(x, y+1);
672 dc.DrawPoint(x+1, y);
673 dc.SetPen(m_gripper_pen3);
674 dc.DrawPoint(x+2, y+1);
675 dc.DrawPoint(x+2, y+2);
676 dc.DrawPoint(x+1, y+2);
677
678 i++;
679 }
680
681 }
682
683 void wxAuiDefaultToolBarArt::DrawOverflowButton(wxDC& dc,
684 wxWindow* wnd,
685 const wxRect& rect,
686 int state)
687 {
688 if (state & wxAUI_BUTTON_STATE_HOVER ||
689 state & wxAUI_BUTTON_STATE_PRESSED)
690 {
691 wxRect cli_rect = wnd->GetClientRect();
692 wxColor light_gray_bg = m_highlight_colour.ChangeLightness(170);
693
694 if (m_flags & wxAUI_TB_VERTICAL)
695 {
696 dc.SetPen(wxPen(m_highlight_colour));
697 dc.DrawLine(rect.x, rect.y, rect.x+rect.width, rect.y);
698 dc.SetPen(wxPen(light_gray_bg));
699 dc.SetBrush(wxBrush(light_gray_bg));
700 dc.DrawRectangle(rect.x, rect.y+1, rect.width, rect.height);
701 }
702 else
703 {
704 dc.SetPen(wxPen(m_highlight_colour));
705 dc.DrawLine(rect.x, rect.y, rect.x, rect.y+rect.height);
706 dc.SetPen(wxPen(light_gray_bg));
707 dc.SetBrush(wxBrush(light_gray_bg));
708 dc.DrawRectangle(rect.x+1, rect.y, rect.width, rect.height);
709 }
710 }
711
712 int x = rect.x+1+(rect.width-m_overflow_bmp.GetWidth())/2;
713 int y = rect.y+1+(rect.height-m_overflow_bmp.GetHeight())/2;
714 dc.DrawBitmap(m_overflow_bmp, x, y, true);
715 }
716
717 int wxAuiDefaultToolBarArt::GetElementSize(int element_id)
718 {
719 switch (element_id)
720 {
721 case wxAUI_TBART_SEPARATOR_SIZE: return m_separator_size;
722 case wxAUI_TBART_GRIPPER_SIZE: return m_gripper_size;
723 case wxAUI_TBART_OVERFLOW_SIZE: return m_overflow_size;
724 default: return 0;
725 }
726 }
727
728 void wxAuiDefaultToolBarArt::SetElementSize(int element_id, int size)
729 {
730 switch (element_id)
731 {
732 case wxAUI_TBART_SEPARATOR_SIZE: m_separator_size = size; break;
733 case wxAUI_TBART_GRIPPER_SIZE: m_gripper_size = size; break;
734 case wxAUI_TBART_OVERFLOW_SIZE: m_overflow_size = size; break;
735 }
736 }
737
738 int wxAuiDefaultToolBarArt::ShowDropDown(wxWindow* wnd,
739 const wxAuiToolBarItemArray& items)
740 {
741 wxMenu menuPopup;
742
743 size_t items_added = 0;
744
745 size_t i, count = items.GetCount();
746 for (i = 0; i < count; ++i)
747 {
748 wxAuiToolBarItem& item = items.Item(i);
749
750 if (item.GetKind() == wxITEM_NORMAL)
751 {
752 wxString text = item.GetShortHelp();
753 if (text.empty())
754 text = item.GetLabel();
755
756 if (text.empty())
757 text = wxT(" ");
758
759 wxMenuItem* m = new wxMenuItem(&menuPopup, item.GetId(), text, item.GetShortHelp());
760
761 m->SetBitmap(item.GetBitmap());
762 menuPopup.Append(m);
763 items_added++;
764 }
765 else if (item.GetKind() == wxITEM_SEPARATOR)
766 {
767 if (items_added > 0)
768 menuPopup.AppendSeparator();
769 }
770 }
771
772 // find out where to put the popup menu of window items
773 wxPoint pt = ::wxGetMousePosition();
774 pt = wnd->ScreenToClient(pt);
775
776 // find out the screen coordinate at the bottom of the tab ctrl
777 wxRect cli_rect = wnd->GetClientRect();
778 pt.y = cli_rect.y + cli_rect.height;
779
780 ToolbarCommandCapture* cc = new ToolbarCommandCapture;
781 wnd->PushEventHandler(cc);
782 wnd->PopupMenu(&menuPopup, pt);
783 int command = cc->GetCommandId();
784 wnd->PopEventHandler(true);
785
786 return command;
787 }
788
789
790
791
792 static wxOrientation GetOrientation(long& style)
793 {
794 switch (style & wxAUI_ORIENTATION_MASK)
795 {
796 case wxAUI_TB_HORIZONTAL:
797 return wxHORIZONTAL;
798 case wxAUI_TB_VERTICAL:
799 return wxVERTICAL;
800 default:
801 wxFAIL_MSG("toolbar cannot be locked in both horizontal and vertical orientations (maybe no lock was intended?)");
802 // fall through
803 case 0:
804 return wxBOTH;
805 }
806 }
807
808 BEGIN_EVENT_TABLE(wxAuiToolBar, wxControl)
809 EVT_SIZE(wxAuiToolBar::OnSize)
810 EVT_IDLE(wxAuiToolBar::OnIdle)
811 EVT_ERASE_BACKGROUND(wxAuiToolBar::OnEraseBackground)
812 EVT_PAINT(wxAuiToolBar::OnPaint)
813 EVT_LEFT_DOWN(wxAuiToolBar::OnLeftDown)
814 EVT_LEFT_DCLICK(wxAuiToolBar::OnLeftDown)
815 EVT_LEFT_UP(wxAuiToolBar::OnLeftUp)
816 EVT_RIGHT_DOWN(wxAuiToolBar::OnRightDown)
817 EVT_RIGHT_DCLICK(wxAuiToolBar::OnRightDown)
818 EVT_RIGHT_UP(wxAuiToolBar::OnRightUp)
819 EVT_MIDDLE_DOWN(wxAuiToolBar::OnMiddleDown)
820 EVT_MIDDLE_DCLICK(wxAuiToolBar::OnMiddleDown)
821 EVT_MIDDLE_UP(wxAuiToolBar::OnMiddleUp)
822 EVT_MOTION(wxAuiToolBar::OnMotion)
823 EVT_LEAVE_WINDOW(wxAuiToolBar::OnLeaveWindow)
824 EVT_MOUSE_CAPTURE_LOST(wxAuiToolBar::OnCaptureLost)
825 EVT_SET_CURSOR(wxAuiToolBar::OnSetCursor)
826 END_EVENT_TABLE()
827
828
829 wxAuiToolBar::wxAuiToolBar(wxWindow* parent,
830 wxWindowID id,
831 const wxPoint& position,
832 const wxSize& size,
833 long style)
834 : wxControl(parent,
835 id,
836 position,
837 size,
838 style | wxBORDER_NONE)
839 {
840 m_sizer = new wxBoxSizer(wxHORIZONTAL);
841 m_button_width = -1;
842 m_button_height = -1;
843 m_sizer_element_count = 0;
844 m_action_pos = wxPoint(-1,-1);
845 m_action_item = NULL;
846 m_tip_item = NULL;
847 m_art = new wxAuiDefaultToolBarArt;
848 m_tool_packing = 2;
849 m_tool_border_padding = 3;
850 m_tool_text_orientation = wxAUI_TBTOOL_TEXT_BOTTOM;
851 m_gripper_sizer_item = NULL;
852 m_overflow_sizer_item = NULL;
853 m_dragging = false;
854 m_orientation = GetOrientation(style);
855 if (m_orientation == wxBOTH)
856 {
857 m_orientation = wxHORIZONTAL;
858 }
859 m_style = style | wxBORDER_NONE;
860 m_gripper_visible = (m_style & wxAUI_TB_GRIPPER) ? true : false;
861 m_overflow_visible = (m_style & wxAUI_TB_OVERFLOW) ? true : false;
862 m_overflow_state = 0;
863 SetMargins(5, 5, 2, 2);
864 SetFont(*wxNORMAL_FONT);
865 SetArtFlags();
866 SetExtraStyle(wxWS_EX_PROCESS_IDLE);
867 if (style & wxAUI_TB_HORZ_LAYOUT)
868 SetToolTextOrientation(wxAUI_TBTOOL_TEXT_RIGHT);
869 SetBackgroundStyle(wxBG_STYLE_CUSTOM);
870 }
871
872
873 wxAuiToolBar::~wxAuiToolBar()
874 {
875 delete m_art;
876 delete m_sizer;
877 }
878
879 void wxAuiToolBar::SetWindowStyleFlag(long style)
880 {
881 GetOrientation(style); // assert if style is invalid
882 wxCHECK_RET(IsPaneValid(style),
883 "window settings and pane settings are incompatible");
884
885 wxControl::SetWindowStyleFlag(style);
886
887 m_style = style;
888
889 if (m_art)
890 {
891 SetArtFlags();
892 }
893
894 if (m_style & wxAUI_TB_GRIPPER)
895 m_gripper_visible = true;
896 else
897 m_gripper_visible = false;
898
899
900 if (m_style & wxAUI_TB_OVERFLOW)
901 m_overflow_visible = true;
902 else
903 m_overflow_visible = false;
904
905 if (style & wxAUI_TB_HORZ_LAYOUT)
906 SetToolTextOrientation(wxAUI_TBTOOL_TEXT_RIGHT);
907 else
908 SetToolTextOrientation(wxAUI_TBTOOL_TEXT_BOTTOM);
909 }
910
911 long wxAuiToolBar::GetWindowStyleFlag() const
912 {
913 return m_style;
914 }
915
916 void wxAuiToolBar::SetArtProvider(wxAuiToolBarArt* art)
917 {
918 delete m_art;
919
920 m_art = art;
921
922 if (m_art)
923 {
924 SetArtFlags();
925 m_art->SetTextOrientation(m_tool_text_orientation);
926 }
927 }
928
929 wxAuiToolBarArt* wxAuiToolBar::GetArtProvider() const
930 {
931 return m_art;
932 }
933
934
935
936
937 wxAuiToolBarItem* wxAuiToolBar::AddTool(int tool_id,
938 const wxString& label,
939 const wxBitmap& bitmap,
940 const wxString& short_help_string,
941 wxItemKind kind)
942 {
943 return AddTool(tool_id,
944 label,
945 bitmap,
946 wxNullBitmap,
947 kind,
948 short_help_string,
949 wxEmptyString,
950 NULL);
951 }
952
953
954 wxAuiToolBarItem* wxAuiToolBar::AddTool(int tool_id,
955 const wxString& label,
956 const wxBitmap& bitmap,
957 const wxBitmap& disabled_bitmap,
958 wxItemKind kind,
959 const wxString& short_help_string,
960 const wxString& long_help_string,
961 wxObject* WXUNUSED(client_data))
962 {
963 wxAuiToolBarItem item;
964 item.window = NULL;
965 item.label = label;
966 item.bitmap = bitmap;
967 item.disabled_bitmap = disabled_bitmap;
968 item.short_help = short_help_string;
969 item.long_help = long_help_string;
970 item.active = true;
971 item.dropdown = false;
972 item.spacer_pixels = 0;
973 item.toolid = tool_id;
974 item.state = 0;
975 item.proportion = 0;
976 item.kind = kind;
977 item.sizer_item = NULL;
978 item.min_size = wxDefaultSize;
979 item.user_data = 0;
980 item.sticky = false;
981
982 if (item.toolid == wxID_ANY)
983 item.toolid = wxNewId();
984
985 if (!item.disabled_bitmap.IsOk())
986 {
987 // no disabled bitmap specified, we need to make one
988 if (item.bitmap.IsOk())
989 {
990 //wxImage img = item.bitmap.ConvertToImage();
991 //wxImage grey_version = img.ConvertToGreyscale();
992 //item.disabled_bitmap = wxBitmap(grey_version);
993 item.disabled_bitmap = MakeDisabledBitmap(item.bitmap);
994 }
995 }
996 m_items.Add(item);
997 return &m_items.Last();
998 }
999
1000 wxAuiToolBarItem* wxAuiToolBar::AddControl(wxControl* control,
1001 const wxString& label)
1002 {
1003 wxAuiToolBarItem item;
1004 item.window = (wxWindow*)control;
1005 item.label = label;
1006 item.bitmap = wxNullBitmap;
1007 item.disabled_bitmap = wxNullBitmap;
1008 item.active = true;
1009 item.dropdown = false;
1010 item.spacer_pixels = 0;
1011 item.toolid = control->GetId();
1012 item.state = 0;
1013 item.proportion = 0;
1014 item.kind = wxITEM_CONTROL;
1015 item.sizer_item = NULL;
1016 item.min_size = control->GetEffectiveMinSize();
1017 item.user_data = 0;
1018 item.sticky = false;
1019
1020 m_items.Add(item);
1021 return &m_items.Last();
1022 }
1023
1024 wxAuiToolBarItem* wxAuiToolBar::AddLabel(int tool_id,
1025 const wxString& label,
1026 const int width)
1027 {
1028 wxSize min_size = wxDefaultSize;
1029 if (width != -1)
1030 min_size.x = width;
1031
1032 wxAuiToolBarItem item;
1033 item.window = NULL;
1034 item.label = label;
1035 item.bitmap = wxNullBitmap;
1036 item.disabled_bitmap = wxNullBitmap;
1037 item.active = true;
1038 item.dropdown = false;
1039 item.spacer_pixels = 0;
1040 item.toolid = tool_id;
1041 item.state = 0;
1042 item.proportion = 0;
1043 item.kind = wxITEM_LABEL;
1044 item.sizer_item = NULL;
1045 item.min_size = min_size;
1046 item.user_data = 0;
1047 item.sticky = false;
1048
1049 if (item.toolid == wxID_ANY)
1050 item.toolid = wxNewId();
1051
1052 m_items.Add(item);
1053 return &m_items.Last();
1054 }
1055
1056 wxAuiToolBarItem* wxAuiToolBar::AddSeparator()
1057 {
1058 wxAuiToolBarItem item;
1059 item.window = NULL;
1060 item.label = wxEmptyString;
1061 item.bitmap = wxNullBitmap;
1062 item.disabled_bitmap = wxNullBitmap;
1063 item.active = true;
1064 item.dropdown = false;
1065 item.toolid = -1;
1066 item.state = 0;
1067 item.proportion = 0;
1068 item.kind = wxITEM_SEPARATOR;
1069 item.sizer_item = NULL;
1070 item.min_size = wxDefaultSize;
1071 item.user_data = 0;
1072 item.sticky = false;
1073
1074 m_items.Add(item);
1075 return &m_items.Last();
1076 }
1077
1078 wxAuiToolBarItem* wxAuiToolBar::AddSpacer(int pixels)
1079 {
1080 wxAuiToolBarItem item;
1081 item.window = NULL;
1082 item.label = wxEmptyString;
1083 item.bitmap = wxNullBitmap;
1084 item.disabled_bitmap = wxNullBitmap;
1085 item.active = true;
1086 item.dropdown = false;
1087 item.spacer_pixels = pixels;
1088 item.toolid = -1;
1089 item.state = 0;
1090 item.proportion = 0;
1091 item.kind = wxITEM_SPACER;
1092 item.sizer_item = NULL;
1093 item.min_size = wxDefaultSize;
1094 item.user_data = 0;
1095 item.sticky = false;
1096
1097 m_items.Add(item);
1098 return &m_items.Last();
1099 }
1100
1101 wxAuiToolBarItem* wxAuiToolBar::AddStretchSpacer(int proportion)
1102 {
1103 wxAuiToolBarItem item;
1104 item.window = NULL;
1105 item.label = wxEmptyString;
1106 item.bitmap = wxNullBitmap;
1107 item.disabled_bitmap = wxNullBitmap;
1108 item.active = true;
1109 item.dropdown = false;
1110 item.spacer_pixels = 0;
1111 item.toolid = -1;
1112 item.state = 0;
1113 item.proportion = proportion;
1114 item.kind = wxITEM_SPACER;
1115 item.sizer_item = NULL;
1116 item.min_size = wxDefaultSize;
1117 item.user_data = 0;
1118 item.sticky = false;
1119
1120 m_items.Add(item);
1121 return &m_items.Last();
1122 }
1123
1124 void wxAuiToolBar::Clear()
1125 {
1126 m_items.Clear();
1127 m_sizer_element_count = 0;
1128 }
1129
1130 bool wxAuiToolBar::DeleteTool(int tool_id)
1131 {
1132 int idx = GetToolIndex(tool_id);
1133 if (idx >= 0 && idx < (int)m_items.GetCount())
1134 {
1135 m_items.RemoveAt(idx);
1136 Realize();
1137 return true;
1138 }
1139
1140 return false;
1141 }
1142
1143 bool wxAuiToolBar::DeleteByIndex(int idx)
1144 {
1145 if (idx >= 0 && idx < (int)m_items.GetCount())
1146 {
1147 m_items.RemoveAt(idx);
1148 Realize();
1149 return true;
1150 }
1151
1152 return false;
1153 }
1154
1155
1156 wxControl* wxAuiToolBar::FindControl(int id)
1157 {
1158 wxWindow* wnd = FindWindow(id);
1159 return (wxControl*)wnd;
1160 }
1161
1162 wxAuiToolBarItem* wxAuiToolBar::FindTool(int tool_id) const
1163 {
1164 size_t i, count;
1165 for (i = 0, count = m_items.GetCount(); i < count; ++i)
1166 {
1167 wxAuiToolBarItem& item = m_items.Item(i);
1168 if (item.toolid == tool_id)
1169 return &item;
1170 }
1171
1172 return NULL;
1173 }
1174
1175 wxAuiToolBarItem* wxAuiToolBar::FindToolByPosition(wxCoord x, wxCoord y) const
1176 {
1177 size_t i, count;
1178 for (i = 0, count = m_items.GetCount(); i < count; ++i)
1179 {
1180 wxAuiToolBarItem& item = m_items.Item(i);
1181
1182 if (!item.sizer_item)
1183 continue;
1184
1185 wxRect rect = item.sizer_item->GetRect();
1186 if (rect.Contains(x,y))
1187 {
1188 // if the item doesn't fit on the toolbar, return NULL
1189 if (!GetToolFitsByIndex(i))
1190 return NULL;
1191
1192 return &item;
1193 }
1194 }
1195
1196 return NULL;
1197 }
1198
1199 wxAuiToolBarItem* wxAuiToolBar::FindToolByPositionWithPacking(wxCoord x, wxCoord y) const
1200 {
1201 size_t i, count;
1202 for (i = 0, count = m_items.GetCount(); i < count; ++i)
1203 {
1204 wxAuiToolBarItem& item = m_items.Item(i);
1205
1206 if (!item.sizer_item)
1207 continue;
1208
1209 wxRect rect = item.sizer_item->GetRect();
1210
1211 // apply tool packing
1212 if (i+1 < count)
1213 rect.width += m_tool_packing;
1214
1215 if (rect.Contains(x,y))
1216 {
1217 // if the item doesn't fit on the toolbar, return NULL
1218 if (!GetToolFitsByIndex(i))
1219 return NULL;
1220
1221 return &item;
1222 }
1223 }
1224
1225 return NULL;
1226 }
1227
1228 wxAuiToolBarItem* wxAuiToolBar::FindToolByIndex(int idx) const
1229 {
1230 if (idx < 0)
1231 return NULL;
1232
1233 if (idx >= (int)m_items.size())
1234 return NULL;
1235
1236 return &(m_items[idx]);
1237 }
1238
1239 void wxAuiToolBar::SetToolBitmapSize(const wxSize& WXUNUSED(size))
1240 {
1241 // TODO: wxToolBar compatibility
1242 }
1243
1244 wxSize wxAuiToolBar::GetToolBitmapSize() const
1245 {
1246 // TODO: wxToolBar compatibility
1247 return wxSize(16,15);
1248 }
1249
1250 void wxAuiToolBar::SetToolProportion(int tool_id, int proportion)
1251 {
1252 wxAuiToolBarItem* item = FindTool(tool_id);
1253 if (!item)
1254 return;
1255
1256 item->proportion = proportion;
1257 }
1258
1259 int wxAuiToolBar::GetToolProportion(int tool_id) const
1260 {
1261 wxAuiToolBarItem* item = FindTool(tool_id);
1262 if (!item)
1263 return 0;
1264
1265 return item->proportion;
1266 }
1267
1268 void wxAuiToolBar::SetToolSeparation(int separation)
1269 {
1270 if (m_art)
1271 m_art->SetElementSize(wxAUI_TBART_SEPARATOR_SIZE, separation);
1272 }
1273
1274 int wxAuiToolBar::GetToolSeparation() const
1275 {
1276 if (m_art)
1277 return m_art->GetElementSize(wxAUI_TBART_SEPARATOR_SIZE);
1278 else
1279 return 5;
1280 }
1281
1282
1283 void wxAuiToolBar::SetToolDropDown(int tool_id, bool dropdown)
1284 {
1285 wxAuiToolBarItem* item = FindTool(tool_id);
1286 if (!item)
1287 return;
1288
1289 item->dropdown = dropdown;
1290 }
1291
1292 bool wxAuiToolBar::GetToolDropDown(int tool_id) const
1293 {
1294 wxAuiToolBarItem* item = FindTool(tool_id);
1295 if (!item)
1296 return 0;
1297
1298 return item->dropdown;
1299 }
1300
1301 void wxAuiToolBar::SetToolSticky(int tool_id, bool sticky)
1302 {
1303 // ignore separators
1304 if (tool_id == -1)
1305 return;
1306
1307 wxAuiToolBarItem* item = FindTool(tool_id);
1308 if (!item)
1309 return;
1310
1311 if (item->sticky == sticky)
1312 return;
1313
1314 item->sticky = sticky;
1315
1316 Refresh(false);
1317 Update();
1318 }
1319
1320 bool wxAuiToolBar::GetToolSticky(int tool_id) const
1321 {
1322 wxAuiToolBarItem* item = FindTool(tool_id);
1323 if (!item)
1324 return 0;
1325
1326 return item->sticky;
1327 }
1328
1329
1330
1331
1332 void wxAuiToolBar::SetToolBorderPadding(int padding)
1333 {
1334 m_tool_border_padding = padding;
1335 }
1336
1337 int wxAuiToolBar::GetToolBorderPadding() const
1338 {
1339 return m_tool_border_padding;
1340 }
1341
1342 void wxAuiToolBar::SetToolTextOrientation(int orientation)
1343 {
1344 m_tool_text_orientation = orientation;
1345
1346 if (m_art)
1347 {
1348 m_art->SetTextOrientation(orientation);
1349 }
1350 }
1351
1352 int wxAuiToolBar::GetToolTextOrientation() const
1353 {
1354 return m_tool_text_orientation;
1355 }
1356
1357 void wxAuiToolBar::SetToolPacking(int packing)
1358 {
1359 m_tool_packing = packing;
1360 }
1361
1362 int wxAuiToolBar::GetToolPacking() const
1363 {
1364 return m_tool_packing;
1365 }
1366
1367
1368 void wxAuiToolBar::SetOrientation(int orientation)
1369 {
1370 wxCHECK_RET(orientation == wxHORIZONTAL ||
1371 orientation == wxVERTICAL,
1372 "invalid orientation value");
1373 if (orientation != m_orientation)
1374 {
1375 m_orientation = wxOrientation(orientation);
1376 SetArtFlags();
1377 }
1378 }
1379
1380 void wxAuiToolBar::SetMargins(int left, int right, int top, int bottom)
1381 {
1382 if (left != -1)
1383 m_left_padding = left;
1384 if (right != -1)
1385 m_right_padding = right;
1386 if (top != -1)
1387 m_top_padding = top;
1388 if (bottom != -1)
1389 m_bottom_padding = bottom;
1390 }
1391
1392 bool wxAuiToolBar::GetGripperVisible() const
1393 {
1394 return m_gripper_visible;
1395 }
1396
1397 void wxAuiToolBar::SetGripperVisible(bool visible)
1398 {
1399 m_gripper_visible = visible;
1400 if (visible)
1401 m_style |= wxAUI_TB_GRIPPER;
1402 else
1403 m_style &= ~wxAUI_TB_GRIPPER;
1404 Realize();
1405 Refresh(false);
1406 }
1407
1408
1409 bool wxAuiToolBar::GetOverflowVisible() const
1410 {
1411 return m_overflow_visible;
1412 }
1413
1414 void wxAuiToolBar::SetOverflowVisible(bool visible)
1415 {
1416 m_overflow_visible = visible;
1417 if (visible)
1418 m_style |= wxAUI_TB_OVERFLOW;
1419 else
1420 m_style &= ~wxAUI_TB_OVERFLOW;
1421 Refresh(false);
1422 }
1423
1424 bool wxAuiToolBar::SetFont(const wxFont& font)
1425 {
1426 bool res = wxWindow::SetFont(font);
1427
1428 if (m_art)
1429 {
1430 m_art->SetFont(font);
1431 }
1432
1433 return res;
1434 }
1435
1436
1437 void wxAuiToolBar::SetHoverItem(wxAuiToolBarItem* pitem)
1438 {
1439 wxAuiToolBarItem* former_hover = NULL;
1440
1441 size_t i, count;
1442 for (i = 0, count = m_items.GetCount(); i < count; ++i)
1443 {
1444 wxAuiToolBarItem& item = m_items.Item(i);
1445 if (item.state & wxAUI_BUTTON_STATE_HOVER)
1446 former_hover = &item;
1447 item.state &= ~wxAUI_BUTTON_STATE_HOVER;
1448 }
1449
1450 if (pitem)
1451 {
1452 pitem->state |= wxAUI_BUTTON_STATE_HOVER;
1453 }
1454
1455 if (former_hover != pitem)
1456 {
1457 Refresh(false);
1458 Update();
1459 }
1460 }
1461
1462 void wxAuiToolBar::SetPressedItem(wxAuiToolBarItem* pitem)
1463 {
1464 wxAuiToolBarItem* former_item = NULL;
1465
1466 size_t i, count;
1467 for (i = 0, count = m_items.GetCount(); i < count; ++i)
1468 {
1469 wxAuiToolBarItem& item = m_items.Item(i);
1470 if (item.state & wxAUI_BUTTON_STATE_PRESSED)
1471 former_item = &item;
1472 item.state &= ~wxAUI_BUTTON_STATE_PRESSED;
1473 }
1474
1475 if (pitem)
1476 {
1477 pitem->state &= ~wxAUI_BUTTON_STATE_HOVER;
1478 pitem->state |= wxAUI_BUTTON_STATE_PRESSED;
1479 }
1480
1481 if (former_item != pitem)
1482 {
1483 Refresh(false);
1484 Update();
1485 }
1486 }
1487
1488 void wxAuiToolBar::RefreshOverflowState()
1489 {
1490 if (!m_overflow_sizer_item)
1491 {
1492 m_overflow_state = 0;
1493 return;
1494 }
1495
1496 int overflow_state = 0;
1497
1498 wxRect overflow_rect = GetOverflowRect();
1499
1500
1501 // find out the mouse's current position
1502 wxPoint pt = ::wxGetMousePosition();
1503 pt = this->ScreenToClient(pt);
1504
1505 // find out if the mouse cursor is inside the dropdown rectangle
1506 if (overflow_rect.Contains(pt.x, pt.y))
1507 {
1508 if (::wxGetMouseState().LeftIsDown())
1509 overflow_state = wxAUI_BUTTON_STATE_PRESSED;
1510 else
1511 overflow_state = wxAUI_BUTTON_STATE_HOVER;
1512 }
1513
1514 if (overflow_state != m_overflow_state)
1515 {
1516 m_overflow_state = overflow_state;
1517 Refresh(false);
1518 Update();
1519 }
1520
1521 m_overflow_state = overflow_state;
1522 }
1523
1524 void wxAuiToolBar::ToggleTool(int tool_id, bool state)
1525 {
1526 wxAuiToolBarItem* tool = FindTool(tool_id);
1527
1528 if (tool && (tool->kind == wxITEM_CHECK || tool->kind == wxITEM_RADIO))
1529 {
1530 if (tool->kind == wxITEM_RADIO)
1531 {
1532 int i, idx, count;
1533 idx = GetToolIndex(tool_id);
1534 count = (int)m_items.GetCount();
1535
1536 if (idx >= 0 && idx < count)
1537 {
1538 for (i = idx; i < count; ++i)
1539 {
1540 if (m_items[i].kind != wxITEM_RADIO)
1541 break;
1542 m_items[i].state &= ~wxAUI_BUTTON_STATE_CHECKED;
1543 }
1544 for (i = idx; i > 0; i--)
1545 {
1546 if (m_items[i].kind != wxITEM_RADIO)
1547 break;
1548 m_items[i].state &= ~wxAUI_BUTTON_STATE_CHECKED;
1549 }
1550 }
1551
1552 tool->state |= wxAUI_BUTTON_STATE_CHECKED;
1553 }
1554 else if (tool->kind == wxITEM_CHECK)
1555 {
1556 if (state == true)
1557 tool->state |= wxAUI_BUTTON_STATE_CHECKED;
1558 else
1559 tool->state &= ~wxAUI_BUTTON_STATE_CHECKED;
1560 }
1561 }
1562 }
1563
1564 bool wxAuiToolBar::GetToolToggled(int tool_id) const
1565 {
1566 wxAuiToolBarItem* tool = FindTool(tool_id);
1567
1568 if (tool)
1569 {
1570 if ( (tool->kind != wxITEM_CHECK) && (tool->kind != wxITEM_RADIO) )
1571 return false;
1572
1573 return (tool->state & wxAUI_BUTTON_STATE_CHECKED) ? true : false;
1574 }
1575
1576 return false;
1577 }
1578
1579 void wxAuiToolBar::EnableTool(int tool_id, bool state)
1580 {
1581 wxAuiToolBarItem* tool = FindTool(tool_id);
1582
1583 if (tool)
1584 {
1585 if (state == true)
1586 tool->state &= ~wxAUI_BUTTON_STATE_DISABLED;
1587 else
1588 tool->state |= wxAUI_BUTTON_STATE_DISABLED;
1589 }
1590 }
1591
1592 bool wxAuiToolBar::GetToolEnabled(int tool_id) const
1593 {
1594 wxAuiToolBarItem* tool = FindTool(tool_id);
1595
1596 if (tool)
1597 return (tool->state & wxAUI_BUTTON_STATE_DISABLED) ? false : true;
1598
1599 return false;
1600 }
1601
1602 wxString wxAuiToolBar::GetToolLabel(int tool_id) const
1603 {
1604 wxAuiToolBarItem* tool = FindTool(tool_id);
1605 wxASSERT_MSG(tool, wxT("can't find tool in toolbar item array"));
1606 if (!tool)
1607 return wxEmptyString;
1608
1609 return tool->label;
1610 }
1611
1612 void wxAuiToolBar::SetToolLabel(int tool_id, const wxString& label)
1613 {
1614 wxAuiToolBarItem* tool = FindTool(tool_id);
1615 if (tool)
1616 {
1617 tool->label = label;
1618 }
1619 }
1620
1621 wxBitmap wxAuiToolBar::GetToolBitmap(int tool_id) const
1622 {
1623 wxAuiToolBarItem* tool = FindTool(tool_id);
1624 wxASSERT_MSG(tool, wxT("can't find tool in toolbar item array"));
1625 if (!tool)
1626 return wxNullBitmap;
1627
1628 return tool->bitmap;
1629 }
1630
1631 void wxAuiToolBar::SetToolBitmap(int tool_id, const wxBitmap& bitmap)
1632 {
1633 wxAuiToolBarItem* tool = FindTool(tool_id);
1634 if (tool)
1635 {
1636 tool->bitmap = bitmap;
1637 }
1638 }
1639
1640 wxString wxAuiToolBar::GetToolShortHelp(int tool_id) const
1641 {
1642 wxAuiToolBarItem* tool = FindTool(tool_id);
1643 wxASSERT_MSG(tool, wxT("can't find tool in toolbar item array"));
1644 if (!tool)
1645 return wxEmptyString;
1646
1647 return tool->short_help;
1648 }
1649
1650 void wxAuiToolBar::SetToolShortHelp(int tool_id, const wxString& help_string)
1651 {
1652 wxAuiToolBarItem* tool = FindTool(tool_id);
1653 if (tool)
1654 {
1655 tool->short_help = help_string;
1656 }
1657 }
1658
1659 wxString wxAuiToolBar::GetToolLongHelp(int tool_id) const
1660 {
1661 wxAuiToolBarItem* tool = FindTool(tool_id);
1662 wxASSERT_MSG(tool, wxT("can't find tool in toolbar item array"));
1663 if (!tool)
1664 return wxEmptyString;
1665
1666 return tool->long_help;
1667 }
1668
1669 void wxAuiToolBar::SetToolLongHelp(int tool_id, const wxString& help_string)
1670 {
1671 wxAuiToolBarItem* tool = FindTool(tool_id);
1672 if (tool)
1673 {
1674 tool->long_help = help_string;
1675 }
1676 }
1677
1678 void wxAuiToolBar::SetCustomOverflowItems(const wxAuiToolBarItemArray& prepend,
1679 const wxAuiToolBarItemArray& append)
1680 {
1681 m_custom_overflow_prepend = prepend;
1682 m_custom_overflow_append = append;
1683 }
1684
1685 // get size of hint rectangle for a particular dock location
1686 wxSize wxAuiToolBar::GetHintSize(int dock_direction) const
1687 {
1688 switch (dock_direction)
1689 {
1690 case wxAUI_DOCK_TOP:
1691 case wxAUI_DOCK_BOTTOM:
1692 return m_horzHintSize;
1693 case wxAUI_DOCK_RIGHT:
1694 case wxAUI_DOCK_LEFT:
1695 return m_vertHintSize;
1696 default:
1697 wxCHECK_MSG(false, wxDefaultSize, "invalid dock location value");
1698 }
1699 }
1700
1701 bool wxAuiToolBar::IsPaneValid(const wxAuiPaneInfo& pane) const
1702 {
1703 return IsPaneValid(m_style, pane);
1704 }
1705
1706 bool wxAuiToolBar::IsPaneValid(long style, const wxAuiPaneInfo& pane)
1707 {
1708 if (style & wxAUI_TB_HORIZONTAL)
1709 {
1710 if (pane.IsLeftDockable() || pane.IsRightDockable())
1711 {
1712 return false;
1713 }
1714 }
1715 else if (style & wxAUI_TB_VERTICAL)
1716 {
1717 if (pane.IsTopDockable() || pane.IsBottomDockable())
1718 {
1719 return false;
1720 }
1721 }
1722 return true;
1723 }
1724
1725 bool wxAuiToolBar::IsPaneValid(long style) const
1726 {
1727 wxAuiManager* manager = wxAuiManager::GetManager(const_cast<wxAuiToolBar*>(this));
1728 if (manager)
1729 {
1730 return IsPaneValid(style, manager->GetPane(const_cast<wxAuiToolBar*>(this)));
1731 }
1732 return true;
1733 }
1734
1735 void wxAuiToolBar::SetArtFlags() const
1736 {
1737 unsigned int artflags = m_style & ~wxAUI_ORIENTATION_MASK;
1738 if (m_orientation == wxVERTICAL)
1739 {
1740 artflags |= wxAUI_TB_VERTICAL;
1741 }
1742 m_art->SetFlags(artflags);
1743 }
1744
1745 size_t wxAuiToolBar::GetToolCount() const
1746 {
1747 return m_items.size();
1748 }
1749
1750 int wxAuiToolBar::GetToolIndex(int tool_id) const
1751 {
1752 // this will prevent us from returning the index of the
1753 // first separator in the toolbar since its id is equal to -1
1754 if (tool_id == -1)
1755 return wxNOT_FOUND;
1756
1757 size_t i, count = m_items.GetCount();
1758 for (i = 0; i < count; ++i)
1759 {
1760 wxAuiToolBarItem& item = m_items.Item(i);
1761 if (item.toolid == tool_id)
1762 return i;
1763 }
1764
1765 return wxNOT_FOUND;
1766 }
1767
1768 bool wxAuiToolBar::GetToolFitsByIndex(int tool_idx) const
1769 {
1770 if (tool_idx < 0 || tool_idx >= (int)m_items.GetCount())
1771 return false;
1772
1773 if (!m_items[tool_idx].sizer_item)
1774 return false;
1775
1776 int cli_w, cli_h;
1777 GetClientSize(&cli_w, &cli_h);
1778
1779 wxRect rect = m_items[tool_idx].sizer_item->GetRect();
1780
1781 if (m_orientation == wxVERTICAL)
1782 {
1783 // take the dropdown size into account
1784 if (m_overflow_visible)
1785 cli_h -= m_overflow_sizer_item->GetSize().y;
1786
1787 if (rect.y+rect.height < cli_h)
1788 return true;
1789 }
1790 else
1791 {
1792 // take the dropdown size into account
1793 if (m_overflow_visible)
1794 cli_w -= m_overflow_sizer_item->GetSize().x;
1795
1796 if (rect.x+rect.width < cli_w)
1797 return true;
1798 }
1799
1800 return false;
1801 }
1802
1803
1804 bool wxAuiToolBar::GetToolFits(int tool_id) const
1805 {
1806 return GetToolFitsByIndex(GetToolIndex(tool_id));
1807 }
1808
1809 wxRect wxAuiToolBar::GetToolRect(int tool_id) const
1810 {
1811 wxAuiToolBarItem* tool = FindTool(tool_id);
1812 if (tool && tool->sizer_item)
1813 {
1814 return tool->sizer_item->GetRect();
1815 }
1816
1817 return wxRect();
1818 }
1819
1820 bool wxAuiToolBar::GetToolBarFits() const
1821 {
1822 if (m_items.GetCount() == 0)
1823 {
1824 // empty toolbar always 'fits'
1825 return true;
1826 }
1827
1828 // entire toolbar content fits if the last tool fits
1829 return GetToolFitsByIndex(m_items.GetCount() - 1);
1830 }
1831
1832 bool wxAuiToolBar::Realize()
1833 {
1834 wxClientDC dc(this);
1835 if (!dc.IsOk())
1836 return false;
1837
1838 // calculate hint sizes for both horizontal and vertical
1839 // in the order that leaves toolbar in correct final state
1840 bool retval = false;
1841 if (m_orientation == wxHORIZONTAL)
1842 {
1843 if (RealizeHelper(dc, false))
1844 {
1845 m_vertHintSize = GetSize();
1846 if (RealizeHelper(dc, true))
1847 {
1848 m_horzHintSize = GetSize();
1849 retval = true;
1850 }
1851 }
1852 }
1853 else
1854 {
1855 if (RealizeHelper(dc, true))
1856 {
1857 m_horzHintSize = GetSize();
1858 if (RealizeHelper(dc, false))
1859 {
1860 m_vertHintSize = GetSize();
1861 retval = true;
1862 }
1863 }
1864 }
1865
1866 Refresh(false);
1867 return retval;
1868 }
1869
1870 bool wxAuiToolBar::RealizeHelper(wxClientDC& dc, bool horizontal)
1871 {
1872 // create the new sizer to add toolbar elements to
1873 wxBoxSizer* sizer = new wxBoxSizer(horizontal ? wxHORIZONTAL : wxVERTICAL);
1874
1875 // add gripper area
1876 int separator_size = m_art->GetElementSize(wxAUI_TBART_SEPARATOR_SIZE);
1877 int gripper_size = m_art->GetElementSize(wxAUI_TBART_GRIPPER_SIZE);
1878 if (gripper_size > 0 && m_gripper_visible)
1879 {
1880 if (horizontal)
1881 m_gripper_sizer_item = sizer->Add(gripper_size, 1, 0, wxEXPAND);
1882 else
1883 m_gripper_sizer_item = sizer->Add(1, gripper_size, 0, wxEXPAND);
1884 }
1885 else
1886 {
1887 m_gripper_sizer_item = NULL;
1888 }
1889
1890 // add "left" padding
1891 if (m_left_padding > 0)
1892 {
1893 if (horizontal)
1894 sizer->Add(m_left_padding, 1);
1895 else
1896 sizer->Add(1, m_left_padding);
1897 }
1898
1899 size_t i, count;
1900 for (i = 0, count = m_items.GetCount(); i < count; ++i)
1901 {
1902 wxAuiToolBarItem& item = m_items.Item(i);
1903 wxSizerItem* sizer_item = NULL;
1904
1905 switch (item.kind)
1906 {
1907 case wxITEM_LABEL:
1908 {
1909 wxSize size = m_art->GetLabelSize(dc, this, item);
1910 sizer_item = sizer->Add(size.x + (m_tool_border_padding*2),
1911 size.y + (m_tool_border_padding*2),
1912 item.proportion,
1913 item.alignment);
1914 if (i+1 < count)
1915 {
1916 sizer->AddSpacer(m_tool_packing);
1917 }
1918
1919 break;
1920 }
1921
1922 case wxITEM_CHECK:
1923 case wxITEM_NORMAL:
1924 case wxITEM_RADIO:
1925 {
1926 wxSize size = m_art->GetToolSize(dc, this, item);
1927 sizer_item = sizer->Add(size.x + (m_tool_border_padding*2),
1928 size.y + (m_tool_border_padding*2),
1929 0,
1930 item.alignment);
1931 // add tool packing
1932 if (i+1 < count)
1933 {
1934 sizer->AddSpacer(m_tool_packing);
1935 }
1936
1937 break;
1938 }
1939
1940 case wxITEM_SEPARATOR:
1941 {
1942 if (horizontal)
1943 sizer_item = sizer->Add(separator_size, 1, 0, wxEXPAND);
1944 else
1945 sizer_item = sizer->Add(1, separator_size, 0, wxEXPAND);
1946
1947 // add tool packing
1948 if (i+1 < count)
1949 {
1950 sizer->AddSpacer(m_tool_packing);
1951 }
1952
1953 break;
1954 }
1955
1956 case wxITEM_SPACER:
1957 if (item.proportion > 0)
1958 sizer_item = sizer->AddStretchSpacer(item.proportion);
1959 else
1960 sizer_item = sizer->Add(item.spacer_pixels, 1);
1961 break;
1962
1963 case wxITEM_CONTROL:
1964 {
1965 //sizer_item = sizer->Add(item.window, item.proportion, wxEXPAND);
1966 wxSizerItem* ctrl_sizer_item;
1967
1968 wxBoxSizer* vert_sizer = new wxBoxSizer(wxVERTICAL);
1969 vert_sizer->AddStretchSpacer(1);
1970 ctrl_sizer_item = vert_sizer->Add(item.window, 0, wxEXPAND);
1971 vert_sizer->AddStretchSpacer(1);
1972 if ( (m_style & wxAUI_TB_TEXT) &&
1973 m_tool_text_orientation == wxAUI_TBTOOL_TEXT_BOTTOM &&
1974 !item.GetLabel().empty() )
1975 {
1976 wxSize s = GetLabelSize(item.GetLabel());
1977 vert_sizer->Add(1, s.y);
1978 }
1979
1980
1981 sizer_item = sizer->Add(vert_sizer, item.proportion, wxEXPAND);
1982
1983 wxSize min_size = item.min_size;
1984
1985
1986 // proportional items will disappear from the toolbar if
1987 // their min width is not set to something really small
1988 if (item.proportion != 0)
1989 {
1990 min_size.x = 1;
1991 }
1992
1993 if (min_size.IsFullySpecified())
1994 {
1995 sizer_item->SetMinSize(min_size);
1996 ctrl_sizer_item->SetMinSize(min_size);
1997 }
1998
1999 // add tool packing
2000 if (i+1 < count)
2001 {
2002 sizer->AddSpacer(m_tool_packing);
2003 }
2004 }
2005 }
2006
2007 item.sizer_item = sizer_item;
2008 }
2009
2010 // add "right" padding
2011 if (m_right_padding > 0)
2012 {
2013 if (horizontal)
2014 sizer->Add(m_right_padding, 1);
2015 else
2016 sizer->Add(1, m_right_padding);
2017 }
2018
2019 // add drop down area
2020 m_overflow_sizer_item = NULL;
2021
2022 if (m_style & wxAUI_TB_OVERFLOW)
2023 {
2024 int overflow_size = m_art->GetElementSize(wxAUI_TBART_OVERFLOW_SIZE);
2025 if (overflow_size > 0 && m_overflow_visible)
2026 {
2027 if (horizontal)
2028 m_overflow_sizer_item = sizer->Add(overflow_size, 1, 0, wxEXPAND);
2029 else
2030 m_overflow_sizer_item = sizer->Add(1, overflow_size, 0, wxEXPAND);
2031 }
2032 else
2033 {
2034 m_overflow_sizer_item = NULL;
2035 }
2036 }
2037
2038
2039 // the outside sizer helps us apply the "top" and "bottom" padding
2040 wxBoxSizer* outside_sizer = new wxBoxSizer(horizontal ? wxVERTICAL : wxHORIZONTAL);
2041
2042 // add "top" padding
2043 if (m_top_padding > 0)
2044 {
2045 if (horizontal)
2046 outside_sizer->Add(1, m_top_padding);
2047 else
2048 outside_sizer->Add(m_top_padding, 1);
2049 }
2050
2051 // add the sizer that contains all of the toolbar elements
2052 outside_sizer->Add(sizer, 1, wxEXPAND);
2053
2054 // add "bottom" padding
2055 if (m_bottom_padding > 0)
2056 {
2057 if (horizontal)
2058 outside_sizer->Add(1, m_bottom_padding);
2059 else
2060 outside_sizer->Add(m_bottom_padding, 1);
2061 }
2062
2063 delete m_sizer; // remove old sizer
2064 m_sizer = outside_sizer;
2065
2066 // calculate the rock-bottom minimum size
2067 for (i = 0, count = m_items.GetCount(); i < count; ++i)
2068 {
2069 wxAuiToolBarItem& item = m_items.Item(i);
2070 if (item.sizer_item && item.proportion > 0 && item.min_size.IsFullySpecified())
2071 item.sizer_item->SetMinSize(0,0);
2072 }
2073
2074 m_absolute_min_size = m_sizer->GetMinSize();
2075
2076 // reset the min sizes to what they were
2077 for (i = 0, count = m_items.GetCount(); i < count; ++i)
2078 {
2079 wxAuiToolBarItem& item = m_items.Item(i);
2080 if (item.sizer_item && item.proportion > 0 && item.min_size.IsFullySpecified())
2081 item.sizer_item->SetMinSize(item.min_size);
2082 }
2083
2084 // set control size
2085 wxSize size = m_sizer->GetMinSize();
2086 m_minWidth = size.x;
2087 m_minHeight = size.y;
2088
2089 if ((m_style & wxAUI_TB_NO_AUTORESIZE) == 0)
2090 {
2091 wxSize cur_size = GetClientSize();
2092 wxSize new_size = GetMinSize();
2093 if (new_size != cur_size)
2094 {
2095 SetClientSize(new_size);
2096 }
2097 else
2098 {
2099 m_sizer->SetDimension(0, 0, cur_size.x, cur_size.y);
2100 }
2101 }
2102 else
2103 {
2104 wxSize cur_size = GetClientSize();
2105 m_sizer->SetDimension(0, 0, cur_size.x, cur_size.y);
2106 }
2107
2108 return true;
2109 }
2110
2111 int wxAuiToolBar::GetOverflowState() const
2112 {
2113 return m_overflow_state;
2114 }
2115
2116 wxRect wxAuiToolBar::GetOverflowRect() const
2117 {
2118 wxRect cli_rect(wxPoint(0,0), GetClientSize());
2119 wxRect overflow_rect = m_overflow_sizer_item->GetRect();
2120 int overflow_size = m_art->GetElementSize(wxAUI_TBART_OVERFLOW_SIZE);
2121
2122 if (m_orientation == wxVERTICAL)
2123 {
2124 overflow_rect.y = cli_rect.height - overflow_size;
2125 overflow_rect.x = 0;
2126 overflow_rect.width = cli_rect.width;
2127 overflow_rect.height = overflow_size;
2128 }
2129 else
2130 {
2131 overflow_rect.x = cli_rect.width - overflow_size;
2132 overflow_rect.y = 0;
2133 overflow_rect.width = overflow_size;
2134 overflow_rect.height = cli_rect.height;
2135 }
2136
2137 return overflow_rect;
2138 }
2139
2140 wxSize wxAuiToolBar::GetLabelSize(const wxString& label)
2141 {
2142 wxClientDC dc(this);
2143
2144 int tx, ty;
2145 int text_width = 0, text_height = 0;
2146
2147 dc.SetFont(m_font);
2148
2149 // get the text height
2150 dc.GetTextExtent(wxT("ABCDHgj"), &tx, &text_height);
2151
2152 // get the text width
2153 dc.GetTextExtent(label, &text_width, &ty);
2154
2155 return wxSize(text_width, text_height);
2156 }
2157
2158
2159 void wxAuiToolBar::DoIdleUpdate()
2160 {
2161 wxEvtHandler* handler = GetEventHandler();
2162
2163 bool need_refresh = false;
2164
2165 size_t i, count;
2166 for (i = 0, count = m_items.GetCount(); i < count; ++i)
2167 {
2168 wxAuiToolBarItem& item = m_items.Item(i);
2169
2170 if (item.toolid == -1)
2171 continue;
2172
2173 wxUpdateUIEvent evt(item.toolid);
2174 evt.SetEventObject(this);
2175
2176 if (handler->ProcessEvent(evt))
2177 {
2178 if (evt.GetSetEnabled())
2179 {
2180 bool is_enabled;
2181 if (item.window)
2182 is_enabled = item.window->IsEnabled();
2183 else
2184 is_enabled = (item.state & wxAUI_BUTTON_STATE_DISABLED) ? false : true;
2185
2186 bool new_enabled = evt.GetEnabled();
2187 if (new_enabled != is_enabled)
2188 {
2189 if (item.window)
2190 {
2191 item.window->Enable(new_enabled);
2192 }
2193 else
2194 {
2195 if (new_enabled)
2196 item.state &= ~wxAUI_BUTTON_STATE_DISABLED;
2197 else
2198 item.state |= wxAUI_BUTTON_STATE_DISABLED;
2199 }
2200 need_refresh = true;
2201 }
2202 }
2203
2204 if (evt.GetSetChecked())
2205 {
2206 // make sure we aren't checking an item that can't be
2207 if (item.kind != wxITEM_CHECK && item.kind != wxITEM_RADIO)
2208 continue;
2209
2210 bool is_checked = (item.state & wxAUI_BUTTON_STATE_CHECKED) ? true : false;
2211 bool new_checked = evt.GetChecked();
2212
2213 if (new_checked != is_checked)
2214 {
2215 if (new_checked)
2216 item.state |= wxAUI_BUTTON_STATE_CHECKED;
2217 else
2218 item.state &= ~wxAUI_BUTTON_STATE_CHECKED;
2219
2220 need_refresh = true;
2221 }
2222 }
2223
2224 }
2225 }
2226
2227
2228 if (need_refresh)
2229 {
2230 Refresh(false);
2231 }
2232 }
2233
2234
2235 void wxAuiToolBar::OnSize(wxSizeEvent& WXUNUSED(evt))
2236 {
2237 int x, y;
2238 GetClientSize(&x, &y);
2239
2240 if (((x >= y) && m_absolute_min_size.x > x) ||
2241 ((y > x) && m_absolute_min_size.y > y))
2242 {
2243 // hide all flexible items
2244 size_t i, count;
2245 for (i = 0, count = m_items.GetCount(); i < count; ++i)
2246 {
2247 wxAuiToolBarItem& item = m_items.Item(i);
2248 if (item.sizer_item && item.proportion > 0 && item.sizer_item->IsShown())
2249 {
2250 item.sizer_item->Show(false);
2251 item.sizer_item->SetProportion(0);
2252 }
2253 }
2254 }
2255 else
2256 {
2257 // show all flexible items
2258 size_t i, count;
2259 for (i = 0, count = m_items.GetCount(); i < count; ++i)
2260 {
2261 wxAuiToolBarItem& item = m_items.Item(i);
2262 if (item.sizer_item && item.proportion > 0 && !item.sizer_item->IsShown())
2263 {
2264 item.sizer_item->Show(true);
2265 item.sizer_item->SetProportion(item.proportion);
2266 }
2267 }
2268 }
2269
2270 m_sizer->SetDimension(0, 0, x, y);
2271
2272 Refresh(false);
2273 Update();
2274
2275 // idle events aren't sent while user is resizing frame (why?),
2276 // but resizing toolbar here causes havoc,
2277 // so force idle handler to run after size handling complete
2278 QueueEvent(new wxIdleEvent);
2279 }
2280
2281
2282
2283 void wxAuiToolBar::DoSetSize(int x,
2284 int y,
2285 int width,
2286 int height,
2287 int sizeFlags)
2288 {
2289 wxSize parent_size = GetParent()->GetClientSize();
2290 if (x + width > parent_size.x)
2291 width = wxMax(0, parent_size.x - x);
2292 if (y + height > parent_size.y)
2293 height = wxMax(0, parent_size.y - y);
2294
2295 wxWindow::DoSetSize(x, y, width, height, sizeFlags);
2296 }
2297
2298
2299 void wxAuiToolBar::OnIdle(wxIdleEvent& evt)
2300 {
2301 // if orientation doesn't match dock, fix it
2302 wxAuiManager* manager = wxAuiManager::GetManager(this);
2303 if (manager)
2304 {
2305 wxAuiPaneInfo& pane = manager->GetPane(this);
2306 // pane state member is public, so it might have been changed
2307 // without going through wxPaneInfo::SetFlag() check
2308 bool ok = pane.IsOk();
2309 wxCHECK2_MSG(!ok || IsPaneValid(m_style, pane), ok = false,
2310 "window settings and pane settings are incompatible");
2311 if (ok)
2312 {
2313 wxOrientation newOrientation = m_orientation;
2314 if (pane.IsDocked())
2315 {
2316 switch (pane.dock_direction)
2317 {
2318 case wxAUI_DOCK_TOP:
2319 case wxAUI_DOCK_BOTTOM:
2320 newOrientation = wxHORIZONTAL;
2321 break;
2322 case wxAUI_DOCK_LEFT:
2323 case wxAUI_DOCK_RIGHT:
2324 newOrientation = wxVERTICAL;
2325 break;
2326 default:
2327 wxFAIL_MSG("invalid dock location value");
2328 }
2329 }
2330 else if (pane.IsResizable() &&
2331 GetOrientation(m_style) == wxBOTH)
2332 {
2333 // changing orientation in OnSize causes havoc
2334 int x, y;
2335 GetClientSize(&x, &y);
2336
2337 if (x > y)
2338 {
2339 newOrientation = wxHORIZONTAL;
2340 }
2341 else
2342 {
2343 newOrientation = wxVERTICAL;
2344 }
2345 }
2346 if (newOrientation != m_orientation)
2347 {
2348 SetOrientation(newOrientation);
2349 Realize();
2350 if (newOrientation == wxHORIZONTAL)
2351 {
2352 pane.best_size = GetHintSize(wxAUI_DOCK_TOP);
2353 }
2354 else
2355 {
2356 pane.best_size = GetHintSize(wxAUI_DOCK_LEFT);
2357 }
2358 if (pane.IsDocked())
2359 {
2360 pane.floating_size = wxDefaultSize;
2361 }
2362 else
2363 {
2364 SetSize(GetParent()->GetClientSize());
2365 }
2366 manager->Update();
2367 }
2368 }
2369 }
2370
2371 DoIdleUpdate();
2372 evt.Skip();
2373 }
2374
2375 void wxAuiToolBar::OnPaint(wxPaintEvent& WXUNUSED(evt))
2376 {
2377 wxAutoBufferedPaintDC dc(this);
2378 wxRect cli_rect(wxPoint(0,0), GetClientSize());
2379
2380
2381 bool horizontal = m_orientation == wxHORIZONTAL;
2382
2383
2384 m_art->DrawBackground(dc, this, cli_rect);
2385
2386 int gripper_size = m_art->GetElementSize(wxAUI_TBART_GRIPPER_SIZE);
2387 int dropdown_size = m_art->GetElementSize(wxAUI_TBART_OVERFLOW_SIZE);
2388
2389 // paint the gripper
2390 if (gripper_size > 0 && m_gripper_sizer_item)
2391 {
2392 wxRect gripper_rect = m_gripper_sizer_item->GetRect();
2393 if (horizontal)
2394 gripper_rect.width = gripper_size;
2395 else
2396 gripper_rect.height = gripper_size;
2397 m_art->DrawGripper(dc, this, gripper_rect);
2398 }
2399
2400 // calculated how far we can draw items
2401 int last_extent;
2402 if (horizontal)
2403 last_extent = cli_rect.width;
2404 else
2405 last_extent = cli_rect.height;
2406 if (m_overflow_visible)
2407 last_extent -= dropdown_size;
2408
2409 // paint each individual tool
2410 size_t i, count = m_items.GetCount();
2411 for (i = 0; i < count; ++i)
2412 {
2413 wxAuiToolBarItem& item = m_items.Item(i);
2414
2415 if (!item.sizer_item)
2416 continue;
2417
2418 wxRect item_rect = item.sizer_item->GetRect();
2419
2420
2421 if ((horizontal && item_rect.x + item_rect.width >= last_extent) ||
2422 (!horizontal && item_rect.y + item_rect.height >= last_extent))
2423 {
2424 break;
2425 }
2426
2427 if (item.kind == wxITEM_SEPARATOR)
2428 {
2429 // draw a separator
2430 m_art->DrawSeparator(dc, this, item_rect);
2431 }
2432 else if (item.kind == wxITEM_LABEL)
2433 {
2434 // draw a text label only
2435 m_art->DrawLabel(dc, this, item, item_rect);
2436 }
2437 else if (item.kind == wxITEM_NORMAL)
2438 {
2439 // draw a regular button or dropdown button
2440 if (!item.dropdown)
2441 m_art->DrawButton(dc, this, item, item_rect);
2442 else
2443 m_art->DrawDropDownButton(dc, this, item, item_rect);
2444 }
2445 else if (item.kind == wxITEM_CHECK)
2446 {
2447 // draw a toggle button
2448 m_art->DrawButton(dc, this, item, item_rect);
2449 }
2450 else if (item.kind == wxITEM_RADIO)
2451 {
2452 // draw a toggle button
2453 m_art->DrawButton(dc, this, item, item_rect);
2454 }
2455 else if (item.kind == wxITEM_CONTROL)
2456 {
2457 // draw the control's label
2458 m_art->DrawControlLabel(dc, this, item, item_rect);
2459 }
2460
2461 // fire a signal to see if the item wants to be custom-rendered
2462 OnCustomRender(dc, item, item_rect);
2463 }
2464
2465 // paint the overflow button
2466 if (dropdown_size > 0 && m_overflow_sizer_item)
2467 {
2468 wxRect dropdown_rect = GetOverflowRect();
2469 m_art->DrawOverflowButton(dc, this, dropdown_rect, m_overflow_state);
2470 }
2471 }
2472
2473 void wxAuiToolBar::OnEraseBackground(wxEraseEvent& WXUNUSED(evt))
2474 {
2475 // empty
2476 }
2477
2478 void wxAuiToolBar::OnLeftDown(wxMouseEvent& evt)
2479 {
2480 wxRect cli_rect(wxPoint(0,0), GetClientSize());
2481
2482 if (m_gripper_sizer_item)
2483 {
2484 wxRect gripper_rect = m_gripper_sizer_item->GetRect();
2485 if (gripper_rect.Contains(evt.GetX(), evt.GetY()))
2486 {
2487 // find aui manager
2488 wxAuiManager* manager = wxAuiManager::GetManager(this);
2489 if (!manager)
2490 return;
2491
2492 int x_drag_offset = evt.GetX() - gripper_rect.GetX();
2493 int y_drag_offset = evt.GetY() - gripper_rect.GetY();
2494
2495 // gripper was clicked
2496 manager->StartPaneDrag(this, wxPoint(x_drag_offset, y_drag_offset));
2497 return;
2498 }
2499 }
2500
2501 if (m_overflow_sizer_item)
2502 {
2503 wxRect overflow_rect = GetOverflowRect();
2504
2505 if (m_art &&
2506 m_overflow_visible &&
2507 overflow_rect.Contains(evt.m_x, evt.m_y))
2508 {
2509 wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_OVERFLOW_CLICK, -1);
2510 e.SetEventObject(this);
2511 e.SetToolId(-1);
2512 e.SetClickPoint(wxPoint(evt.GetX(), evt.GetY()));
2513 bool processed = GetEventHandler()->ProcessEvent(e);
2514
2515 if (processed)
2516 {
2517 DoIdleUpdate();
2518 }
2519 else
2520 {
2521 size_t i, count;
2522 wxAuiToolBarItemArray overflow_items;
2523
2524
2525 // add custom overflow prepend items, if any
2526 count = m_custom_overflow_prepend.GetCount();
2527 for (i = 0; i < count; ++i)
2528 overflow_items.Add(m_custom_overflow_prepend[i]);
2529
2530 // only show items that don't fit in the dropdown
2531 count = m_items.GetCount();
2532 for (i = 0; i < count; ++i)
2533 {
2534 if (!GetToolFitsByIndex(i))
2535 overflow_items.Add(m_items[i]);
2536 }
2537
2538 // add custom overflow append items, if any
2539 count = m_custom_overflow_append.GetCount();
2540 for (i = 0; i < count; ++i)
2541 overflow_items.Add(m_custom_overflow_append[i]);
2542
2543 int res = m_art->ShowDropDown(this, overflow_items);
2544 m_overflow_state = 0;
2545 Refresh(false);
2546 if (res != -1)
2547 {
2548 wxCommandEvent e(wxEVT_COMMAND_MENU_SELECTED, res);
2549 e.SetEventObject(this);
2550 GetParent()->GetEventHandler()->ProcessEvent(e);
2551 }
2552 }
2553
2554 return;
2555 }
2556 }
2557
2558 m_dragging = false;
2559 m_action_pos = wxPoint(evt.GetX(), evt.GetY());
2560 m_action_item = FindToolByPosition(evt.GetX(), evt.GetY());
2561
2562 if (m_action_item)
2563 {
2564 if (m_action_item->state & wxAUI_BUTTON_STATE_DISABLED)
2565 {
2566 m_action_pos = wxPoint(-1,-1);
2567 m_action_item = NULL;
2568 return;
2569 }
2570
2571 UnsetToolTip();
2572
2573 // fire the tool dropdown event
2574 wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_TOOL_DROPDOWN, m_action_item->toolid);
2575 e.SetEventObject(this);
2576 e.SetToolId(m_action_item->toolid);
2577
2578 int mouse_x = evt.GetX();
2579 wxRect rect = m_action_item->sizer_item->GetRect();
2580 const bool dropDownHit = m_action_item->dropdown &&
2581 mouse_x >= (rect.x+rect.width-BUTTON_DROPDOWN_WIDTH-1) &&
2582 mouse_x < (rect.x+rect.width);
2583 e.SetDropDownClicked(dropDownHit);
2584
2585 e.SetClickPoint(evt.GetPosition());
2586 e.SetItemRect(rect);
2587
2588 // we only set the 'pressed button' state if we hit the actual button
2589 // and not just the drop-down
2590 SetPressedItem(dropDownHit ? 0 : m_action_item);
2591
2592 if(dropDownHit)
2593 {
2594 m_action_pos = wxPoint(-1,-1);
2595 m_action_item = NULL;
2596 }
2597
2598 if(!GetEventHandler()->ProcessEvent(e) || e.GetSkipped())
2599 CaptureMouse();
2600
2601 DoIdleUpdate();
2602 }
2603 }
2604
2605 void wxAuiToolBar::OnLeftUp(wxMouseEvent& evt)
2606 {
2607 if (!HasCapture())
2608 return;
2609
2610 SetPressedItem(NULL);
2611
2612 wxAuiToolBarItem* hit_item = FindToolByPosition(evt.GetX(), evt.GetY());
2613 if (hit_item && !(hit_item->state & wxAUI_BUTTON_STATE_DISABLED))
2614 {
2615 SetHoverItem(hit_item);
2616 }
2617
2618 if (m_dragging)
2619 {
2620 // TODO: it would make sense to send out an 'END_DRAG' event here,
2621 // otherwise a client would never know what to do with the 'BEGIN_DRAG'
2622 // event
2623
2624 // OnCaptureLost() will be called now and this will reset all our state
2625 // tracking variables
2626 ReleaseMouse();
2627 }
2628 else
2629 {
2630 wxAuiToolBarItem* hit_item;
2631 hit_item = FindToolByPosition(evt.GetX(), evt.GetY());
2632
2633 if (m_action_item && hit_item == m_action_item)
2634 {
2635 UnsetToolTip();
2636
2637 wxCommandEvent e(wxEVT_COMMAND_MENU_SELECTED, m_action_item->toolid);
2638 e.SetEventObject(this);
2639
2640 if (hit_item->kind == wxITEM_CHECK || hit_item->kind == wxITEM_RADIO)
2641 {
2642 const bool toggle = !(m_action_item->state & wxAUI_BUTTON_STATE_CHECKED);
2643
2644 ToggleTool(m_action_item->toolid, toggle);
2645
2646 // repaint immediately
2647 Refresh(false);
2648 Update();
2649
2650 e.SetInt(toggle);
2651 }
2652
2653 // we have to release the mouse *before* sending the event, because
2654 // we don't know what a handler might do. It could open up a popup
2655 // menu for example and that would make us lose our capture anyway.
2656
2657 ReleaseMouse();
2658
2659 GetEventHandler()->ProcessEvent(e);
2660 DoIdleUpdate();
2661 }
2662 else
2663 ReleaseMouse();
2664 }
2665 }
2666
2667 void wxAuiToolBar::OnRightDown(wxMouseEvent& evt)
2668 {
2669 wxRect cli_rect(wxPoint(0,0), GetClientSize());
2670
2671 if (m_gripper_sizer_item)
2672 {
2673 wxRect gripper_rect = m_gripper_sizer_item->GetRect();
2674 if (gripper_rect.Contains(evt.GetX(), evt.GetY()))
2675 return;
2676 }
2677
2678 if (m_overflow_sizer_item)
2679 {
2680 int dropdown_size = m_art->GetElementSize(wxAUI_TBART_OVERFLOW_SIZE);
2681 if (dropdown_size > 0 &&
2682 evt.m_x > cli_rect.width - dropdown_size &&
2683 evt.m_y >= 0 &&
2684 evt.m_y < cli_rect.height &&
2685 m_art)
2686 {
2687 return;
2688 }
2689 }
2690
2691 m_action_pos = wxPoint(evt.GetX(), evt.GetY());
2692 m_action_item = FindToolByPosition(evt.GetX(), evt.GetY());
2693
2694 if (m_action_item && m_action_item->state & wxAUI_BUTTON_STATE_DISABLED)
2695 {
2696 m_action_pos = wxPoint(-1,-1);
2697 m_action_item = NULL;
2698 return;
2699 }
2700
2701 UnsetToolTip();
2702 }
2703
2704 void wxAuiToolBar::OnRightUp(wxMouseEvent& evt)
2705 {
2706 wxAuiToolBarItem* hit_item;
2707 hit_item = FindToolByPosition(evt.GetX(), evt.GetY());
2708
2709 if (m_action_item && hit_item == m_action_item)
2710 {
2711 if (hit_item->kind == wxITEM_NORMAL)
2712 {
2713 wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK, m_action_item->toolid);
2714 e.SetEventObject(this);
2715 e.SetToolId(m_action_item->toolid);
2716 e.SetClickPoint(m_action_pos);
2717 GetEventHandler()->ProcessEvent(e);
2718 DoIdleUpdate();
2719 }
2720 }
2721 else
2722 {
2723 // right-clicked on the invalid area of the toolbar
2724 wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK, -1);
2725 e.SetEventObject(this);
2726 e.SetToolId(-1);
2727 e.SetClickPoint(m_action_pos);
2728 GetEventHandler()->ProcessEvent(e);
2729 DoIdleUpdate();
2730 }
2731
2732 // reset member variables
2733 m_action_pos = wxPoint(-1,-1);
2734 m_action_item = NULL;
2735 }
2736
2737 void wxAuiToolBar::OnMiddleDown(wxMouseEvent& evt)
2738 {
2739 wxRect cli_rect(wxPoint(0,0), GetClientSize());
2740
2741 if (m_gripper_sizer_item)
2742 {
2743 wxRect gripper_rect = m_gripper_sizer_item->GetRect();
2744 if (gripper_rect.Contains(evt.GetX(), evt.GetY()))
2745 return;
2746 }
2747
2748 if (m_overflow_sizer_item)
2749 {
2750 int dropdown_size = m_art->GetElementSize(wxAUI_TBART_OVERFLOW_SIZE);
2751 if (dropdown_size > 0 &&
2752 evt.m_x > cli_rect.width - dropdown_size &&
2753 evt.m_y >= 0 &&
2754 evt.m_y < cli_rect.height &&
2755 m_art)
2756 {
2757 return;
2758 }
2759 }
2760
2761 m_action_pos = wxPoint(evt.GetX(), evt.GetY());
2762 m_action_item = FindToolByPosition(evt.GetX(), evt.GetY());
2763
2764 if (m_action_item)
2765 {
2766 if (m_action_item->state & wxAUI_BUTTON_STATE_DISABLED)
2767 {
2768 m_action_pos = wxPoint(-1,-1);
2769 m_action_item = NULL;
2770 return;
2771 }
2772 }
2773
2774 UnsetToolTip();
2775 }
2776
2777 void wxAuiToolBar::OnMiddleUp(wxMouseEvent& evt)
2778 {
2779 wxAuiToolBarItem* hit_item;
2780 hit_item = FindToolByPosition(evt.GetX(), evt.GetY());
2781
2782 if (m_action_item && hit_item == m_action_item)
2783 {
2784 if (hit_item->kind == wxITEM_NORMAL)
2785 {
2786 wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_MIDDLE_CLICK, m_action_item->toolid);
2787 e.SetEventObject(this);
2788 e.SetToolId(m_action_item->toolid);
2789 e.SetClickPoint(m_action_pos);
2790 GetEventHandler()->ProcessEvent(e);
2791 DoIdleUpdate();
2792 }
2793 }
2794
2795 // reset member variables
2796 m_action_pos = wxPoint(-1,-1);
2797 m_action_item = NULL;
2798 }
2799
2800 void wxAuiToolBar::OnMotion(wxMouseEvent& evt)
2801 {
2802 const bool button_pressed = HasCapture();
2803
2804 // start a drag event
2805 if (!m_dragging && button_pressed &&
2806 abs(evt.GetX() - m_action_pos.x) + abs(evt.GetY() - m_action_pos.y) > 5)
2807 {
2808 // TODO: sending this event only makes sense if there is an 'END_DRAG'
2809 // event sent sometime in the future (see OnLeftUp())
2810 wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_BEGIN_DRAG, GetId());
2811 e.SetEventObject(this);
2812 e.SetToolId(m_action_item->toolid);
2813 m_dragging = GetEventHandler()->ProcessEvent(e) && !e.GetSkipped();
2814
2815 DoIdleUpdate();
2816 }
2817
2818 if(m_dragging)
2819 return;
2820
2821 wxAuiToolBarItem* hit_item = FindToolByPosition(evt.GetX(), evt.GetY());
2822 if(button_pressed)
2823 {
2824 // if we have a button pressed we want it to be shown in 'depressed'
2825 // state unless we move the mouse outside the button, then we want it
2826 // to show as just 'highlighted'
2827 if (hit_item == m_action_item)
2828 SetPressedItem(m_action_item);
2829 else
2830 {
2831 SetPressedItem(NULL);
2832 SetHoverItem(m_action_item);
2833 }
2834 }
2835 else
2836 {
2837 if (hit_item && (hit_item->state & wxAUI_BUTTON_STATE_DISABLED))
2838 SetHoverItem(NULL);
2839 else
2840 SetHoverItem(hit_item);
2841
2842 // tooltips handling
2843 wxAuiToolBarItem* packing_hit_item;
2844 packing_hit_item = FindToolByPositionWithPacking(evt.GetX(), evt.GetY());
2845 if (packing_hit_item)
2846 {
2847 if (packing_hit_item != m_tip_item)
2848 {
2849 m_tip_item = packing_hit_item;
2850
2851 if ( !packing_hit_item->short_help.empty() )
2852 SetToolTip(packing_hit_item->short_help);
2853 else
2854 UnsetToolTip();
2855 }
2856 }
2857 else
2858 {
2859 UnsetToolTip();
2860 m_tip_item = NULL;
2861 }
2862
2863 // figure out the dropdown button state (are we hovering or pressing it?)
2864 RefreshOverflowState();
2865 }
2866 }
2867
2868 void wxAuiToolBar::DoResetMouseState()
2869 {
2870 RefreshOverflowState();
2871 SetHoverItem(NULL);
2872 SetPressedItem(NULL);
2873
2874 m_tip_item = NULL;
2875
2876 // we have to reset those here, because the mouse-up handlers which do
2877 // it usually won't be called if we let go of a mouse button while we
2878 // are outside of the window
2879 m_action_pos = wxPoint(-1,-1);
2880 m_action_item = NULL;
2881 }
2882
2883 void wxAuiToolBar::OnLeaveWindow(wxMouseEvent& evt)
2884 {
2885 if(HasCapture())
2886 {
2887 evt.Skip();
2888 return;
2889 }
2890
2891 DoResetMouseState();
2892 }
2893
2894 void wxAuiToolBar::OnCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(evt))
2895 {
2896 m_dragging = false;
2897
2898 DoResetMouseState();
2899 }
2900
2901 void wxAuiToolBar::OnSetCursor(wxSetCursorEvent& evt)
2902 {
2903 wxCursor cursor = wxNullCursor;
2904
2905 if (m_gripper_sizer_item)
2906 {
2907 wxRect gripper_rect = m_gripper_sizer_item->GetRect();
2908 if (gripper_rect.Contains(evt.GetX(), evt.GetY()))
2909 {
2910 cursor = wxCursor(wxCURSOR_SIZING);
2911 }
2912 }
2913
2914 evt.SetCursor(cursor);
2915 }
2916
2917
2918 #endif // wxUSE_AUI
2919