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