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