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