]> git.saurik.com Git - wxWidgets.git/blame - src/aui/auibar.cpp
avoiding reentrancy problems and congestion
[wxWidgets.git] / src / aui / auibar.cpp
CommitLineData
1154f91b
BW
1///////////////////////////////////////////////////////////////////////////////
2
80fdcdb9 3// Name: src/aui/auibar.cpp
1154f91b
BW
4// Purpose: wxaui: wx advanced user interface - docking window manager
5// Author: Benjamin I. Williams
6// Modified by:
7// Created: 2005-05-17
054f177b 8// RCS-ID: $Id$
1154f91b
BW
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
eecf97a5
VZ
39#ifdef __WXMAC__
40#include "wx/osx/private.h"
1154f91b
BW
41#endif
42
43#include "wx/arrimpl.cpp"
44WX_DEFINE_OBJARRAY(wxAuiToolBarItemArray)
45
46
ce7fe42e
VZ
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 );
1154f91b
BW
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
1154f91b
BW
72static wxColor GetBaseColor()
73{
74
eecf97a5 75#if defined( __WXMAC__ ) && wxOSX_USE_COCOA_OR_CARBON
9a29fe70 76 wxColor baseColour = wxColour( wxMacCreateCGColorFromHITheme(kThemeBrushToolbarBackground));
1154f91b 77#else
9a29fe70 78 wxColor baseColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
1154f91b
BW
79#endif
80
9a29fe70 81 // the baseColour is too pale to use as our base colour,
1154f91b 82 // so darken it a bit --
9a29fe70
VZ
83 if ((255-baseColour.Red()) +
84 (255-baseColour.Green()) +
85 (255-baseColour.Blue()) < 60)
1154f91b 86 {
9a29fe70 87 baseColour = baseColour.ChangeLightness(92);
1154f91b
BW
88 }
89
9a29fe70 90 return baseColour;
1154f91b
BW
91}
92
93
94
95class ToolbarCommandCapture : public wxEvtHandler
96{
97public:
98
9a29fe70
VZ
99 ToolbarCommandCapture() { m_lastId = 0; }
100 int GetCommandId() const { return m_lastId; }
1154f91b
BW
101
102 bool ProcessEvent(wxEvent& evt)
103 {
ce7fe42e 104 if (evt.GetEventType() == wxEVT_MENU)
1154f91b 105 {
9a29fe70 106 m_lastId = evt.GetId();
1154f91b
BW
107 return true;
108 }
109
110 if (GetNextHandler())
111 return GetNextHandler()->ProcessEvent(evt);
112
113 return false;
114 }
115
116private:
9a29fe70 117 int m_lastId;
1154f91b
BW
118};
119
120
121
eecf97a5 122static const unsigned char
a310c91c 123 DISABLED_TEXT_GREY_HUE = wxColour::AlphaBlend(0, 255, 0.4);
eecf97a5
VZ
124const wxColour DISABLED_TEXT_COLOR(DISABLED_TEXT_GREY_HUE,
125 DISABLED_TEXT_GREY_HUE,
126 DISABLED_TEXT_GREY_HUE);
1154f91b
BW
127
128wxAuiDefaultToolBarArt::wxAuiDefaultToolBarArt()
129{
9a29fe70 130 m_baseColour = GetBaseColor();
1154f91b
BW
131
132 m_flags = 0;
9a29fe70
VZ
133 m_textOrientation = wxAUI_TBTOOL_TEXT_BOTTOM;
134 m_highlightColour = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
eecf97a5 135
9a29fe70
VZ
136 m_separatorSize = 7;
137 m_gripperSize = 7;
138 m_overflowSize = 16;
1154f91b 139
9a29fe70
VZ
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);
1154f91b 145
9a29fe70
VZ
146 m_gripperPen1 = wxPen(darker5Colour);
147 m_gripperPen2 = wxPen(darker3Colour);
148 m_gripperPen3 = *wxWHITE_PEN;
eecf97a5 149
9a29fe70
VZ
150 static const unsigned char buttonDropdownBits[] = { 0xe0, 0xf1, 0xfb };
151 static const unsigned char overflowBits[] = { 0x80, 0xff, 0x80, 0xc1, 0xe3, 0xf7 };
eecf97a5 152
9a29fe70 153 m_buttonDropDownBmp = wxAuiBitmapFromBits(buttonDropdownBits, 5, 3,
1154f91b 154 *wxBLACK);
9a29fe70
VZ
155 m_disabledButtonDropDownBmp = wxAuiBitmapFromBits(
156 buttonDropdownBits, 5, 3,
1154f91b 157 wxColor(128,128,128));
9a29fe70
VZ
158 m_overflowBmp = wxAuiBitmapFromBits(overflowBits, 7, 6, *wxBLACK);
159 m_disabledOverflowBmp = wxAuiBitmapFromBits(overflowBits, 7, 6, wxColor(128,128,128));
1154f91b
BW
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{
9a29fe70 187 m_textOrientation = orientation;
1154f91b
BW
188}
189
8bc10f32
BW
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{
9a29fe70 202 return m_textOrientation;
8bc10f32
BW
203}
204
1154f91b
BW
205void wxAuiDefaultToolBarArt::DrawBackground(
206 wxDC& dc,
207 wxWindow* WXUNUSED(wnd),
208 const wxRect& _rect)
209{
210 wxRect rect = _rect;
211 rect.height++;
9a29fe70
VZ
212 wxColour startColour = m_baseColour.ChangeLightness(150);
213 wxColour endColour = m_baseColour.ChangeLightness(90);
214 dc.GradientFillLinear(rect, startColour, endColour, wxSOUTH);
1154f91b
BW
215}
216
526502d1
VZ
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
1154f91b
BW
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
9a29fe70
VZ
241 int textWidth = 0, textHeight = 0;
242 dc.GetTextExtent(wxT("ABCDHgj"), &textWidth, &textHeight);
1154f91b
BW
243
244 // set the clipping region
9a29fe70
VZ
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);
1154f91b
BW
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{
9a29fe70 263 int textWidth = 0, textHeight = 0;
eecf97a5 264
1154f91b
BW
265 if (m_flags & wxAUI_TB_TEXT)
266 {
267 dc.SetFont(m_font);
eecf97a5 268
1154f91b
BW
269 int tx, ty;
270
9a29fe70
VZ
271 dc.GetTextExtent(wxT("ABCDHgj"), &tx, &textHeight);
272 textWidth = 0;
273 dc.GetTextExtent(item.GetLabel(), &textWidth, &ty);
1154f91b
BW
274 }
275
9a29fe70
VZ
276 int bmpX = 0, bmpY = 0;
277 int textX = 0, textY = 0;
eecf97a5 278
9a29fe70 279 if (m_textOrientation == wxAUI_TBTOOL_TEXT_BOTTOM)
1154f91b 280 {
9a29fe70 281 bmpX = rect.x +
1154f91b 282 (rect.width/2) -
e42f2c16 283 (item.GetBitmap().GetWidth()/2);
eecf97a5 284
9a29fe70
VZ
285 bmpY = rect.y +
286 ((rect.height-textHeight)/2) -
e42f2c16 287 (item.GetBitmap().GetHeight()/2);
eecf97a5 288
9a29fe70
VZ
289 textX = rect.x + (rect.width/2) - (textWidth/2) + 1;
290 textY = rect.y + rect.height - textHeight - 1;
1154f91b 291 }
9a29fe70 292 else if (m_textOrientation == wxAUI_TBTOOL_TEXT_RIGHT)
1154f91b 293 {
9a29fe70 294 bmpX = rect.x + 3;
eecf97a5 295
9a29fe70 296 bmpY = rect.y +
1154f91b 297 (rect.height/2) -
e42f2c16 298 (item.GetBitmap().GetHeight()/2);
eecf97a5 299
9a29fe70
VZ
300 textX = bmpX + 3 + item.GetBitmap().GetWidth();
301 textY = rect.y +
1154f91b 302 (rect.height/2) -
9a29fe70 303 (textHeight/2);
1154f91b
BW
304 }
305
306
e42f2c16 307 if (!(item.GetState() & wxAUI_BUTTON_STATE_DISABLED))
1154f91b 308 {
e42f2c16 309 if (item.GetState() & wxAUI_BUTTON_STATE_PRESSED)
1154f91b 310 {
9a29fe70
VZ
311 dc.SetPen(wxPen(m_highlightColour));
312 dc.SetBrush(wxBrush(m_highlightColour.ChangeLightness(150)));
1154f91b
BW
313 dc.DrawRectangle(rect);
314 }
e42f2c16 315 else if ((item.GetState() & wxAUI_BUTTON_STATE_HOVER) || item.IsSticky())
1154f91b 316 {
9a29fe70
VZ
317 dc.SetPen(wxPen(m_highlightColour));
318 dc.SetBrush(wxBrush(m_highlightColour.ChangeLightness(170)));
eecf97a5 319
1154f91b
BW
320 // draw an even lighter background for checked item hovers (since
321 // the hover background is the same color as the check background)
e42f2c16 322 if (item.GetState() & wxAUI_BUTTON_STATE_CHECKED)
9a29fe70 323 dc.SetBrush(wxBrush(m_highlightColour.ChangeLightness(180)));
eecf97a5 324
1154f91b
BW
325 dc.DrawRectangle(rect);
326 }
e42f2c16 327 else if (item.GetState() & wxAUI_BUTTON_STATE_CHECKED)
1154f91b 328 {
c81f528f 329 // it's important to put this code in an else statement after the
1154f91b 330 // hover, otherwise hovers won't draw properly for checked items
9a29fe70
VZ
331 dc.SetPen(wxPen(m_highlightColour));
332 dc.SetBrush(wxBrush(m_highlightColour.ChangeLightness(170)));
1154f91b
BW
333 dc.DrawRectangle(rect);
334 }
335 }
336
337 wxBitmap bmp;
e42f2c16
BW
338 if (item.GetState() & wxAUI_BUTTON_STATE_DISABLED)
339 bmp = item.GetDisabledBitmap();
8b385bf8 340 else
e42f2c16 341 bmp = item.GetBitmap();
eecf97a5 342
2347971e 343 if ( bmp.IsOk() )
9a29fe70 344 dc.DrawBitmap(bmp, bmpX, bmpY, true);
1154f91b
BW
345
346 // set the item's text color based on if it is disabled
347 dc.SetTextForeground(*wxBLACK);
e42f2c16 348 if (item.GetState() & wxAUI_BUTTON_STATE_DISABLED)
1154f91b 349 dc.SetTextForeground(DISABLED_TEXT_COLOR);
eecf97a5 350
e42f2c16 351 if ( (m_flags & wxAUI_TB_TEXT) && !item.GetLabel().empty() )
1154f91b 352 {
9a29fe70 353 dc.DrawText(item.GetLabel(), textX, textY);
1154f91b
BW
354 }
355}
356
357
358void wxAuiDefaultToolBarArt::DrawDropDownButton(
359 wxDC& dc,
360 wxWindow* WXUNUSED(wnd),
361 const wxAuiToolBarItem& item,
362 const wxRect& rect)
363{
9a29fe70
VZ
364 int textWidth = 0, textHeight = 0, textX = 0, textY = 0;
365 int bmpX = 0, bmpY = 0, dropBmpX = 0, dropBmpY = 0;
eecf97a5 366
9a29fe70 367 wxRect buttonRect = wxRect(rect.x,
1154f91b
BW
368 rect.y,
369 rect.width-BUTTON_DROPDOWN_WIDTH,
370 rect.height);
9a29fe70 371 wxRect dropDownRect = wxRect(rect.x+rect.width-BUTTON_DROPDOWN_WIDTH-1,
1154f91b
BW
372 rect.y,
373 BUTTON_DROPDOWN_WIDTH+1,
374 rect.height);
eecf97a5 375
1154f91b
BW
376 if (m_flags & wxAUI_TB_TEXT)
377 {
378 dc.SetFont(m_font);
eecf97a5 379
1154f91b
BW
380 int tx, ty;
381 if (m_flags & wxAUI_TB_TEXT)
382 {
9a29fe70
VZ
383 dc.GetTextExtent(wxT("ABCDHgj"), &tx, &textHeight);
384 textWidth = 0;
eecf97a5
VZ
385 }
386
9a29fe70 387 dc.GetTextExtent(item.GetLabel(), &textWidth, &ty);
1154f91b
BW
388 }
389
390
eecf97a5 391
9a29fe70
VZ
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);
eecf97a5
VZ
398
399
9a29fe70 400 if (m_textOrientation == wxAUI_TBTOOL_TEXT_BOTTOM)
1154f91b 401 {
9a29fe70
VZ
402 bmpX = buttonRect.x +
403 (buttonRect.width/2) -
e42f2c16 404 (item.GetBitmap().GetWidth()/2);
9a29fe70
VZ
405 bmpY = buttonRect.y +
406 ((buttonRect.height-textHeight)/2) -
e42f2c16 407 (item.GetBitmap().GetHeight()/2);
eecf97a5 408
9a29fe70
VZ
409 textX = rect.x + (rect.width/2) - (textWidth/2) + 1;
410 textY = rect.y + rect.height - textHeight - 1;
1154f91b 411 }
9a29fe70 412 else if (m_textOrientation == wxAUI_TBTOOL_TEXT_RIGHT)
1154f91b 413 {
9a29fe70 414 bmpX = rect.x + 3;
eecf97a5 415
9a29fe70 416 bmpY = rect.y +
1154f91b 417 (rect.height/2) -
e42f2c16 418 (item.GetBitmap().GetHeight()/2);
eecf97a5 419
9a29fe70
VZ
420 textX = bmpX + 3 + item.GetBitmap().GetWidth();
421 textY = rect.y +
1154f91b 422 (rect.height/2) -
9a29fe70 423 (textHeight/2);
1154f91b 424 }
eecf97a5
VZ
425
426
e42f2c16 427 if (item.GetState() & wxAUI_BUTTON_STATE_PRESSED)
1154f91b 428 {
9a29fe70
VZ
429 dc.SetPen(wxPen(m_highlightColour));
430 dc.SetBrush(wxBrush(m_highlightColour.ChangeLightness(140)));
431 dc.DrawRectangle(buttonRect);
4a21ea9d 432
9a29fe70
VZ
433 dc.SetBrush(wxBrush(m_highlightColour.ChangeLightness(170)));
434 dc.DrawRectangle(dropDownRect);
1154f91b 435 }
e42f2c16
BW
436 else if (item.GetState() & wxAUI_BUTTON_STATE_HOVER ||
437 item.IsSticky())
1154f91b 438 {
9a29fe70
VZ
439 dc.SetPen(wxPen(m_highlightColour));
440 dc.SetBrush(wxBrush(m_highlightColour.ChangeLightness(170)));
441 dc.DrawRectangle(buttonRect);
442 dc.DrawRectangle(dropDownRect);
1154f91b 443 }
026c6eff
VZ
444 else if (item.GetState() & wxAUI_BUTTON_STATE_CHECKED)
445 {
446 // Notice that this branch must come after the hover one to ensure the
9a29fe70
VZ
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);
026c6eff 452 }
1154f91b
BW
453
454 wxBitmap bmp;
455 wxBitmap dropbmp;
e42f2c16 456 if (item.GetState() & wxAUI_BUTTON_STATE_DISABLED)
1154f91b 457 {
e42f2c16 458 bmp = item.GetDisabledBitmap();
9a29fe70 459 dropbmp = m_disabledButtonDropDownBmp;
1154f91b 460 }
8b385bf8 461 else
1154f91b 462 {
e42f2c16 463 bmp = item.GetBitmap();
9a29fe70 464 dropbmp = m_buttonDropDownBmp;
1154f91b 465 }
eecf97a5 466
1154f91b
BW
467 if (!bmp.IsOk())
468 return;
eecf97a5 469
9a29fe70
VZ
470 dc.DrawBitmap(bmp, bmpX, bmpY, true);
471 dc.DrawBitmap(dropbmp, dropBmpX, dropBmpY, true);
1154f91b
BW
472
473 // set the item's text color based on if it is disabled
474 dc.SetTextForeground(*wxBLACK);
e42f2c16 475 if (item.GetState() & wxAUI_BUTTON_STATE_DISABLED)
1154f91b 476 dc.SetTextForeground(DISABLED_TEXT_COLOR);
eecf97a5 477
e42f2c16 478 if ( (m_flags & wxAUI_TB_TEXT) && !item.GetLabel().empty() )
1154f91b 479 {
9a29fe70 480 dc.DrawText(item.GetLabel(), textX, textY);
1154f91b
BW
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
9a29fe70 493 if (m_textOrientation != wxAUI_TBTOOL_TEXT_BOTTOM)
1154f91b 494 return;
eecf97a5 495
9a29fe70
VZ
496 int textX = 0, textY = 0;
497 int textWidth = 0, textHeight = 0;
1154f91b
BW
498
499 dc.SetFont(m_font);
eecf97a5 500
1154f91b
BW
501 int tx, ty;
502 if (m_flags & wxAUI_TB_TEXT)
503 {
9a29fe70
VZ
504 dc.GetTextExtent(wxT("ABCDHgj"), &tx, &textHeight);
505 textWidth = 0;
eecf97a5
VZ
506 }
507
9a29fe70 508 dc.GetTextExtent(item.GetLabel(), &textWidth, &ty);
eecf97a5 509
1154f91b 510 // don't draw the label if it is wider than the item width
9a29fe70 511 if (textWidth > rect.width)
1154f91b 512 return;
eecf97a5 513
1154f91b
BW
514 // set the label's text color
515 dc.SetTextForeground(*wxBLACK);
eecf97a5 516
9a29fe70
VZ
517 textX = rect.x + (rect.width/2) - (textWidth/2) + 1;
518 textY = rect.y + rect.height - textHeight - 1;
eecf97a5 519
e42f2c16 520 if ( (m_flags & wxAUI_TB_TEXT) && !item.GetLabel().empty() )
1154f91b 521 {
9a29fe70 522 dc.DrawText(item.GetLabel(), textX, textY);
1154f91b
BW
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
e42f2c16 538 width = item.GetMinSize().GetWidth();
45496810 539
e54e92e6
BW
540 if (width == -1)
541 {
542 // no width specified, measure the text ourselves
543 width = dc.GetTextExtent(item.GetLabel()).GetX();
544 }
45496810 545
1154f91b
BW
546 return wxSize(width, height);
547}
548
549wxSize wxAuiDefaultToolBarArt::GetToolSize(
550 wxDC& dc,
551 wxWindow* WXUNUSED(wnd),
552 const wxAuiToolBarItem& item)
553{
e42f2c16 554 if (!item.GetBitmap().IsOk() && !(m_flags & wxAUI_TB_TEXT))
1154f91b 555 return wxSize(16,16);
eecf97a5 556
e42f2c16
BW
557 int width = item.GetBitmap().GetWidth();
558 int height = item.GetBitmap().GetHeight();
eecf97a5 559
1154f91b
BW
560 if (m_flags & wxAUI_TB_TEXT)
561 {
562 dc.SetFont(m_font);
563 int tx, ty;
eecf97a5 564
9a29fe70 565 if (m_textOrientation == wxAUI_TBTOOL_TEXT_BOTTOM)
1154f91b
BW
566 {
567 dc.GetTextExtent(wxT("ABCDHgj"), &tx, &ty);
568 height += ty;
eecf97a5 569
e42f2c16 570 if ( !item.GetLabel().empty() )
1154f91b 571 {
e42f2c16 572 dc.GetTextExtent(item.GetLabel(), &tx, &ty);
1154f91b
BW
573 width = wxMax(width, tx+6);
574 }
575 }
9a29fe70 576 else if ( m_textOrientation == wxAUI_TBTOOL_TEXT_RIGHT &&
e42f2c16 577 !item.GetLabel().empty() )
1154f91b
BW
578 {
579 width += 3; // space between left border and bitmap
580 width += 3; // space between bitmap and text
eecf97a5 581
e42f2c16 582 if ( !item.GetLabel().empty() )
1154f91b 583 {
e42f2c16 584 dc.GetTextExtent(item.GetLabel(), &tx, &ty);
1154f91b
BW
585 width += tx;
586 height = wxMax(height, ty);
587 }
588 }
eecf97a5 589 }
1154f91b
BW
590
591 // if the tool has a dropdown button, add it to the width
e42f2c16 592 if (item.HasDropDown())
1154f91b 593 width += (BUTTON_DROPDOWN_WIDTH+4);
eecf97a5 594
1154f91b
BW
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;
eecf97a5 606
1154f91b 607 wxRect rect = _rect;
eecf97a5 608
1154f91b
BW
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 }
8b385bf8 617 else
1154f91b
BW
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 }
eecf97a5 625
9a29fe70
VZ
626 wxColour startColour = m_baseColour.ChangeLightness(80);
627 wxColour endColour = m_baseColour.ChangeLightness(80);
628 dc.GradientFillLinear(rect, startColour, endColour, horizontal ? wxSOUTH : wxEAST);
1154f91b 629}
eecf97a5 630
1154f91b
BW
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;
eecf97a5 639
1154f91b
BW
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 }
8b385bf8 647 else
1154f91b
BW
648 {
649 x = rect.x + 3;
650 y = rect.y + (i*4) + 5;
651 if (y > rect.GetHeight()-5)
652 break;
653 }
eecf97a5 654
9a29fe70 655 dc.SetPen(m_gripperPen1);
1154f91b 656 dc.DrawPoint(x, y);
9a29fe70 657 dc.SetPen(m_gripperPen2);
1154f91b
BW
658 dc.DrawPoint(x, y+1);
659 dc.DrawPoint(x+1, y);
9a29fe70 660 dc.SetPen(m_gripperPen3);
1154f91b
BW
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}
eecf97a5 669
1154f91b 670void wxAuiDefaultToolBarArt::DrawOverflowButton(wxDC& dc,
36307fdf 671 wxWindow* /*wnd*/,
1154f91b
BW
672 const wxRect& rect,
673 int state)
674{
675 if (state & wxAUI_BUTTON_STATE_HOVER ||
676 state & wxAUI_BUTTON_STATE_PRESSED)
677 {
9a29fe70 678 wxColor light_gray_bg = m_highlightColour.ChangeLightness(170);
eecf97a5 679
1154f91b
BW
680 if (m_flags & wxAUI_TB_VERTICAL)
681 {
9a29fe70 682 dc.SetPen(wxPen(m_highlightColour));
1154f91b
BW
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 {
9a29fe70 690 dc.SetPen(wxPen(m_highlightColour));
1154f91b
BW
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
9a29fe70
VZ
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);
1154f91b
BW
701}
702
703int wxAuiDefaultToolBarArt::GetElementSize(int element_id)
704{
705 switch (element_id)
706 {
9a29fe70
VZ
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;
1154f91b
BW
710 default: return 0;
711 }
712}
713
714void wxAuiDefaultToolBarArt::SetElementSize(int element_id, int size)
715{
716 switch (element_id)
717 {
9a29fe70
VZ
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;
1154f91b
BW
721 }
722}
723
724int wxAuiDefaultToolBarArt::ShowDropDown(wxWindow* wnd,
725 const wxAuiToolBarItemArray& items)
726{
727 wxMenu menuPopup;
728
729 size_t items_added = 0;
eecf97a5 730
1154f91b
BW
731 size_t i, count = items.GetCount();
732 for (i = 0; i < count; ++i)
733 {
734 wxAuiToolBarItem& item = items.Item(i);
eecf97a5 735
e42f2c16 736 if (item.GetKind() == wxITEM_NORMAL)
1154f91b 737 {
e42f2c16 738 wxString text = item.GetShortHelp();
1154f91b 739 if (text.empty())
e42f2c16 740 text = item.GetLabel();
eecf97a5 741
1154f91b
BW
742 if (text.empty())
743 text = wxT(" ");
eecf97a5 744
e42f2c16 745 wxMenuItem* m = new wxMenuItem(&menuPopup, item.GetId(), text, item.GetShortHelp());
1154f91b 746
e42f2c16 747 m->SetBitmap(item.GetBitmap());
1154f91b
BW
748 menuPopup.Append(m);
749 items_added++;
750 }
e42f2c16 751 else if (item.GetKind() == wxITEM_SEPARATOR)
1154f91b
BW
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
e5dcae09
VZ
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
1154f91b
BW
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)
4a21ea9d 810 EVT_MOUSE_CAPTURE_LOST(wxAuiToolBar::OnCaptureLost)
1154f91b
BW
811 EVT_SET_CURSOR(wxAuiToolBar::OnSetCursor)
812END_EVENT_TABLE()
813
46e67202 814void wxAuiToolBar::Init()
1154f91b
BW
815{
816 m_sizer = new wxBoxSizer(wxHORIZONTAL);
9a29fe70
VZ
817 m_buttonWidth = -1;
818 m_buttonHeight = -1;
819 m_sizerElementCount = 0;
51d2b636 820 m_actionPos = wxDefaultPosition;
9a29fe70
VZ
821 m_actionItem = NULL;
822 m_tipItem = NULL;
1154f91b 823 m_art = new wxAuiDefaultToolBarArt;
9a29fe70
VZ
824 m_toolPacking = 2;
825 m_toolBorderPadding = 3;
826 m_toolTextOrientation = wxAUI_TBTOOL_TEXT_BOTTOM;
827 m_gripperSizerItem = NULL;
828 m_overflowSizerItem = NULL;
1154f91b 829 m_dragging = false;
51d2b636
VZ
830 m_gripperVisible = false;
831 m_overflowVisible = false;
46e67202 832 m_overflowState = 0;
51d2b636 833 m_orientation = wxHORIZONTAL;
46e67202
VZ
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
a69b365f 847 m_windowStyle = style;
51d2b636
VZ
848
849 m_gripperVisible = (style & wxAUI_TB_GRIPPER) ? true : false;
850 m_overflowVisible = (style & wxAUI_TB_OVERFLOW) ? true : false;
851
e5dcae09
VZ
852 m_orientation = GetOrientation(style);
853 if (m_orientation == wxBOTH)
854 {
855 m_orientation = wxHORIZONTAL;
856 }
46e67202 857
1154f91b
BW
858 SetMargins(5, 5, 2, 2);
859 SetFont(*wxNORMAL_FONT);
e5dcae09 860 SetArtFlags();
1154f91b 861 SetExtraStyle(wxWS_EX_PROCESS_IDLE);
9578058d 862 if (style & wxAUI_TB_HORZ_LAYOUT)
1154f91b 863 SetToolTextOrientation(wxAUI_TBTOOL_TEXT_RIGHT);
66ad3095 864 SetBackgroundStyle(wxBG_STYLE_CUSTOM);
1154f91b 865
46e67202
VZ
866 return true;
867}
1154f91b
BW
868
869wxAuiToolBar::~wxAuiToolBar()
870{
871 delete m_art;
872 delete m_sizer;
873}
874
875void wxAuiToolBar::SetWindowStyleFlag(long style)
876{
e5dcae09
VZ
877 GetOrientation(style); // assert if style is invalid
878 wxCHECK_RET(IsPaneValid(style),
879 "window settings and pane settings are incompatible");
880
1154f91b
BW
881 wxControl::SetWindowStyleFlag(style);
882
a69b365f 883 m_windowStyle = style;
eecf97a5 884
1154f91b
BW
885 if (m_art)
886 {
e5dcae09 887 SetArtFlags();
1154f91b 888 }
eecf97a5 889
a69b365f 890 if (m_windowStyle & wxAUI_TB_GRIPPER)
9a29fe70 891 m_gripperVisible = true;
8b385bf8 892 else
9a29fe70 893 m_gripperVisible = false;
1154f91b
BW
894
895
a69b365f 896 if (m_windowStyle & wxAUI_TB_OVERFLOW)
9a29fe70 897 m_overflowVisible = true;
8b385bf8 898 else
9a29fe70 899 m_overflowVisible = false;
eecf97a5 900
9578058d 901 if (style & wxAUI_TB_HORZ_LAYOUT)
1154f91b 902 SetToolTextOrientation(wxAUI_TBTOOL_TEXT_RIGHT);
8b385bf8 903 else
1154f91b
BW
904 SetToolTextOrientation(wxAUI_TBTOOL_TEXT_BOTTOM);
905}
906
1154f91b
BW
907void wxAuiToolBar::SetArtProvider(wxAuiToolBarArt* art)
908{
909 delete m_art;
eecf97a5 910
1154f91b 911 m_art = art;
eecf97a5 912
1154f91b
BW
913 if (m_art)
914 {
e5dcae09 915 SetArtFlags();
9a29fe70 916 m_art->SetTextOrientation(m_toolTextOrientation);
1154f91b
BW
917 }
918}
919
920wxAuiToolBarArt* wxAuiToolBar::GetArtProvider() const
921{
922 return m_art;
923}
924
925
926
927
7bce8439 928wxAuiToolBarItem* wxAuiToolBar::AddTool(int tool_id,
1154f91b
BW
929 const wxString& label,
930 const wxBitmap& bitmap,
9a29fe70 931 const wxString& shortHelp_string,
1154f91b
BW
932 wxItemKind kind)
933{
7bce8439 934 return AddTool(tool_id,
1154f91b
BW
935 label,
936 bitmap,
937 wxNullBitmap,
938 kind,
9a29fe70 939 shortHelp_string,
1154f91b
BW
940 wxEmptyString,
941 NULL);
942}
943
944
7bce8439 945wxAuiToolBarItem* wxAuiToolBar::AddTool(int tool_id,
1154f91b
BW
946 const wxString& label,
947 const wxBitmap& bitmap,
9a29fe70 948 const wxBitmap& disabledBitmap,
1154f91b 949 wxItemKind kind,
9a29fe70
VZ
950 const wxString& shortHelpString,
951 const wxString& longHelpString,
1154f91b
BW
952 wxObject* WXUNUSED(client_data))
953{
954 wxAuiToolBarItem item;
9a29fe70
VZ
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())
1154f91b
BW
977 {
978 // no disabled bitmap specified, we need to make one
9a29fe70 979 if (item.m_bitmap.IsOk())
1154f91b 980 {
9a29fe70 981 item.m_disabledBitmap = item.m_bitmap.ConvertToDisabled();
1154f91b
BW
982 }
983 }
1154f91b 984 m_items.Add(item);
7bce8439 985 return &m_items.Last();
1154f91b
BW
986}
987
7bce8439 988wxAuiToolBarItem* wxAuiToolBar::AddControl(wxControl* control,
1154f91b
BW
989 const wxString& label)
990{
991 wxAuiToolBarItem item;
9a29fe70
VZ
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;
1154f91b
BW
1007
1008 m_items.Add(item);
7bce8439 1009 return &m_items.Last();
1154f91b
BW
1010}
1011
7bce8439 1012wxAuiToolBarItem* wxAuiToolBar::AddLabel(int tool_id,
1154f91b
BW
1013 const wxString& label,
1014 const int width)
1015{
1016 wxSize min_size = wxDefaultSize;
1017 if (width != -1)
1018 min_size.x = width;
eecf97a5 1019
1154f91b 1020 wxAuiToolBarItem item;
9a29fe70
VZ
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();
45496810 1039
1154f91b 1040 m_items.Add(item);
7bce8439 1041 return &m_items.Last();
1154f91b
BW
1042}
1043
7bce8439 1044wxAuiToolBarItem* wxAuiToolBar::AddSeparator()
1154f91b
BW
1045{
1046 wxAuiToolBarItem item;
9a29fe70
VZ
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;
1154f91b
BW
1061
1062 m_items.Add(item);
7bce8439 1063 return &m_items.Last();
1154f91b
BW
1064}
1065
7bce8439 1066wxAuiToolBarItem* wxAuiToolBar::AddSpacer(int pixels)
1154f91b
BW
1067{
1068 wxAuiToolBarItem item;
9a29fe70
VZ
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;
1154f91b
BW
1084
1085 m_items.Add(item);
7bce8439 1086 return &m_items.Last();
1154f91b
BW
1087}
1088
7bce8439 1089wxAuiToolBarItem* wxAuiToolBar::AddStretchSpacer(int proportion)
1154f91b
BW
1090{
1091 wxAuiToolBarItem item;
9a29fe70
VZ
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;
1154f91b
BW
1107
1108 m_items.Add(item);
7bce8439 1109 return &m_items.Last();
1154f91b
BW
1110}
1111
1112void wxAuiToolBar::Clear()
1113{
1114 m_items.Clear();
9a29fe70 1115 m_sizerElementCount = 0;
1154f91b
BW
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 }
eecf97a5 1127
1154f91b
BW
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 }
eecf97a5 1139
1154f91b
BW
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);
9a29fe70 1156 if (item.m_toolId == tool_id)
1154f91b
BW
1157 return &item;
1158 }
eecf97a5 1159
1154f91b
BW
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);
eecf97a5 1169
9a29fe70 1170 if (!item.m_sizerItem)
1154f91b 1171 continue;
eecf97a5 1172
9a29fe70 1173 wxRect rect = item.m_sizerItem->GetRect();
1154f91b
BW
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;
eecf97a5 1179
1154f91b
BW
1180 return &item;
1181 }
1182 }
eecf97a5 1183
1154f91b
BW
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);
eecf97a5 1193
9a29fe70 1194 if (!item.m_sizerItem)
1154f91b 1195 continue;
eecf97a5 1196
9a29fe70 1197 wxRect rect = item.m_sizerItem->GetRect();
eecf97a5 1198
1154f91b
BW
1199 // apply tool packing
1200 if (i+1 < count)
9a29fe70 1201 rect.width += m_toolPacking;
eecf97a5 1202
1154f91b
BW
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;
eecf97a5 1208
1154f91b
BW
1209 return &item;
1210 }
1211 }
eecf97a5 1212
1154f91b
BW
1213 return NULL;
1214}
1215
1216wxAuiToolBarItem* wxAuiToolBar::FindToolByIndex(int idx) const
1217{
1218 if (idx < 0)
1219 return NULL;
eecf97a5 1220
1154f91b
BW
1221 if (idx >= (int)m_items.size())
1222 return NULL;
eecf97a5 1223
1154f91b
BW
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}
eecf97a5 1237
1154f91b
BW
1238void wxAuiToolBar::SetToolProportion(int tool_id, int proportion)
1239{
1240 wxAuiToolBarItem* item = FindTool(tool_id);
1241 if (!item)
1242 return;
eecf97a5 1243
9a29fe70 1244 item->m_proportion = proportion;
1154f91b
BW
1245}
1246
1247int wxAuiToolBar::GetToolProportion(int tool_id) const
1248{
1249 wxAuiToolBarItem* item = FindTool(tool_id);
1250 if (!item)
1251 return 0;
eecf97a5 1252
9a29fe70 1253 return item->m_proportion;
1154f91b
BW
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);
8b385bf8 1266 else
1154f91b
BW
1267 return 5;
1268}
eecf97a5 1269
1154f91b
BW
1270
1271void wxAuiToolBar::SetToolDropDown(int tool_id, bool dropdown)
1272{
eecf97a5 1273 wxAuiToolBarItem* item = FindTool(tool_id);
1154f91b
BW
1274 if (!item)
1275 return;
1276
72ae0b51 1277 item->SetHasDropDown(dropdown);
1154f91b
BW
1278}
1279
1280bool wxAuiToolBar::GetToolDropDown(int tool_id) const
1281{
1282 wxAuiToolBarItem* item = FindTool(tool_id);
1283 if (!item)
72ae0b51 1284 return false;
eecf97a5 1285
72ae0b51 1286 return item->HasDropDown();
1154f91b
BW
1287}
1288
1289void wxAuiToolBar::SetToolSticky(int tool_id, bool sticky)
1290{
1291 // ignore separators
1292 if (tool_id == -1)
1293 return;
eecf97a5
VZ
1294
1295 wxAuiToolBarItem* item = FindTool(tool_id);
1154f91b
BW
1296 if (!item)
1297 return;
eecf97a5 1298
9a29fe70 1299 if (item->m_sticky == sticky)
1154f91b 1300 return;
eecf97a5 1301
9a29fe70 1302 item->m_sticky = sticky;
eecf97a5 1303
1154f91b
BW
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;
eecf97a5 1313
9a29fe70 1314 return item->m_sticky;
1154f91b
BW
1315}
1316
1317
1318
1319
1320void wxAuiToolBar::SetToolBorderPadding(int padding)
1321{
9a29fe70 1322 m_toolBorderPadding = padding;
1154f91b
BW
1323}
1324
1325int wxAuiToolBar::GetToolBorderPadding() const
1326{
9a29fe70 1327 return m_toolBorderPadding;
1154f91b
BW
1328}
1329
1330void wxAuiToolBar::SetToolTextOrientation(int orientation)
1331{
9a29fe70 1332 m_toolTextOrientation = orientation;
1154f91b
BW
1333
1334 if (m_art)
1335 {
1336 m_art->SetTextOrientation(orientation);
1337 }
1338}
1339
1340int wxAuiToolBar::GetToolTextOrientation() const
1341{
9a29fe70 1342 return m_toolTextOrientation;
1154f91b
BW
1343}
1344
1345void wxAuiToolBar::SetToolPacking(int packing)
1346{
9a29fe70 1347 m_toolPacking = packing;
1154f91b
BW
1348}
1349
1350int wxAuiToolBar::GetToolPacking() const
1351{
9a29fe70 1352 return m_toolPacking;
1154f91b
BW
1353}
1354
1355
e5dcae09 1356void wxAuiToolBar::SetOrientation(int orientation)
1154f91b 1357{
e5dcae09
VZ
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 }
1154f91b
BW
1366}
1367
1368void wxAuiToolBar::SetMargins(int left, int right, int top, int bottom)
1369{
1370 if (left != -1)
9a29fe70 1371 m_leftPadding = left;
1154f91b 1372 if (right != -1)
9a29fe70 1373 m_rightPadding = right;
1154f91b 1374 if (top != -1)
9a29fe70 1375 m_topPadding = top;
1154f91b 1376 if (bottom != -1)
9a29fe70 1377 m_bottomPadding = bottom;
1154f91b
BW
1378}
1379
1380bool wxAuiToolBar::GetGripperVisible() const
1381{
9a29fe70 1382 return m_gripperVisible;
1154f91b
BW
1383}
1384
1385void wxAuiToolBar::SetGripperVisible(bool visible)
1386{
9a29fe70 1387 m_gripperVisible = visible;
1154f91b 1388 if (visible)
a69b365f 1389 m_windowStyle |= wxAUI_TB_GRIPPER;
e7b8af65 1390 else
a69b365f 1391 m_windowStyle &= ~wxAUI_TB_GRIPPER;
1154f91b
BW
1392 Realize();
1393 Refresh(false);
1394}
1395
1396
1397bool wxAuiToolBar::GetOverflowVisible() const
1398{
9a29fe70 1399 return m_overflowVisible;
1154f91b
BW
1400}
1401
1402void wxAuiToolBar::SetOverflowVisible(bool visible)
1403{
9a29fe70 1404 m_overflowVisible = visible;
1154f91b 1405 if (visible)
a69b365f 1406 m_windowStyle |= wxAUI_TB_OVERFLOW;
e7b8af65 1407 else
a69b365f 1408 m_windowStyle &= ~wxAUI_TB_OVERFLOW;
1154f91b
BW
1409 Refresh(false);
1410}
1411
1412bool wxAuiToolBar::SetFont(const wxFont& font)
1413{
1414 bool res = wxWindow::SetFont(font);
eecf97a5 1415
1154f91b
BW
1416 if (m_art)
1417 {
1418 m_art->SetFont(font);
1419 }
eecf97a5 1420
1154f91b
BW
1421 return res;
1422}
1423
1424
1425void wxAuiToolBar::SetHoverItem(wxAuiToolBarItem* pitem)
1426{
c2211811
VZ
1427 if (pitem && (pitem->m_state & wxAUI_BUTTON_STATE_DISABLED))
1428 pitem = NULL;
1429
1154f91b 1430 wxAuiToolBarItem* former_hover = NULL;
eecf97a5 1431
1154f91b
BW
1432 size_t i, count;
1433 for (i = 0, count = m_items.GetCount(); i < count; ++i)
1434 {
1435 wxAuiToolBarItem& item = m_items.Item(i);
9a29fe70 1436 if (item.m_state & wxAUI_BUTTON_STATE_HOVER)
1154f91b 1437 former_hover = &item;
9a29fe70 1438 item.m_state &= ~wxAUI_BUTTON_STATE_HOVER;
1154f91b 1439 }
eecf97a5 1440
1154f91b
BW
1441 if (pitem)
1442 {
9a29fe70 1443 pitem->m_state |= wxAUI_BUTTON_STATE_HOVER;
1154f91b 1444 }
eecf97a5 1445
1154f91b
BW
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;
eecf97a5 1456
1154f91b
BW
1457 size_t i, count;
1458 for (i = 0, count = m_items.GetCount(); i < count; ++i)
1459 {
1460 wxAuiToolBarItem& item = m_items.Item(i);
9a29fe70 1461 if (item.m_state & wxAUI_BUTTON_STATE_PRESSED)
1154f91b 1462 former_item = &item;
9a29fe70 1463 item.m_state &= ~wxAUI_BUTTON_STATE_PRESSED;
1154f91b 1464 }
eecf97a5 1465
1154f91b
BW
1466 if (pitem)
1467 {
9a29fe70
VZ
1468 pitem->m_state &= ~wxAUI_BUTTON_STATE_HOVER;
1469 pitem->m_state |= wxAUI_BUTTON_STATE_PRESSED;
1154f91b 1470 }
eecf97a5 1471
1154f91b
BW
1472 if (former_item != pitem)
1473 {
1474 Refresh(false);
1475 Update();
1476 }
1477}
1478
1479void wxAuiToolBar::RefreshOverflowState()
1480{
9a29fe70 1481 if (!m_overflowSizerItem)
1154f91b 1482 {
9a29fe70 1483 m_overflowState = 0;
1154f91b
BW
1484 return;
1485 }
eecf97a5 1486
1154f91b 1487 int overflow_state = 0;
eecf97a5 1488
1154f91b
BW
1489 wxRect overflow_rect = GetOverflowRect();
1490
eecf97a5 1491
1154f91b
BW
1492 // find out the mouse's current position
1493 wxPoint pt = ::wxGetMousePosition();
1494 pt = this->ScreenToClient(pt);
eecf97a5 1495
1154f91b
BW
1496 // find out if the mouse cursor is inside the dropdown rectangle
1497 if (overflow_rect.Contains(pt.x, pt.y))
1498 {
45496810 1499 if (::wxGetMouseState().LeftIsDown())
1154f91b 1500 overflow_state = wxAUI_BUTTON_STATE_PRESSED;
8b385bf8 1501 else
1154f91b
BW
1502 overflow_state = wxAUI_BUTTON_STATE_HOVER;
1503 }
eecf97a5 1504
9a29fe70 1505 if (overflow_state != m_overflowState)
1154f91b 1506 {
9a29fe70 1507 m_overflowState = overflow_state;
1154f91b
BW
1508 Refresh(false);
1509 Update();
1510 }
eecf97a5 1511
9a29fe70 1512 m_overflowState = overflow_state;
1154f91b
BW
1513}
1514
1515void wxAuiToolBar::ToggleTool(int tool_id, bool state)
1516{
1517 wxAuiToolBarItem* tool = FindTool(tool_id);
eecf97a5 1518
9a29fe70 1519 if (tool && (tool->m_kind == wxITEM_CHECK || tool->m_kind == wxITEM_RADIO))
1154f91b 1520 {
9a29fe70 1521 if (tool->m_kind == wxITEM_RADIO)
cae51973
BW
1522 {
1523 int i, idx, count;
1524 idx = GetToolIndex(tool_id);
1525 count = (int)m_items.GetCount();
45496810 1526
cae51973
BW
1527 if (idx >= 0 && idx < count)
1528 {
587151f7 1529 for (i = idx + 1; i < count; ++i)
cae51973 1530 {
9a29fe70 1531 if (m_items[i].m_kind != wxITEM_RADIO)
cae51973 1532 break;
9a29fe70 1533 m_items[i].m_state &= ~wxAUI_BUTTON_STATE_CHECKED;
cae51973 1534 }
587151f7 1535 for (i = idx - 1; i >= 0; i--)
cae51973 1536 {
9a29fe70 1537 if (m_items[i].m_kind != wxITEM_RADIO)
cae51973 1538 break;
9a29fe70 1539 m_items[i].m_state &= ~wxAUI_BUTTON_STATE_CHECKED;
cae51973
BW
1540 }
1541 }
45496810 1542
9a29fe70 1543 tool->m_state |= wxAUI_BUTTON_STATE_CHECKED;
cae51973 1544 }
9a29fe70 1545 else if (tool->m_kind == wxITEM_CHECK)
cae51973
BW
1546 {
1547 if (state == true)
9a29fe70 1548 tool->m_state |= wxAUI_BUTTON_STATE_CHECKED;
cae51973 1549 else
9a29fe70 1550 tool->m_state &= ~wxAUI_BUTTON_STATE_CHECKED;
cae51973 1551 }
1154f91b
BW
1552 }
1553}
1554
1555bool wxAuiToolBar::GetToolToggled(int tool_id) const
1556{
1557 wxAuiToolBarItem* tool = FindTool(tool_id);
eecf97a5 1558
1154f91b
BW
1559 if (tool)
1560 {
9a29fe70 1561 if ( (tool->m_kind != wxITEM_CHECK) && (tool->m_kind != wxITEM_RADIO) )
1154f91b 1562 return false;
eecf97a5 1563
9a29fe70 1564 return (tool->m_state & wxAUI_BUTTON_STATE_CHECKED) ? true : false;
1154f91b 1565 }
eecf97a5 1566
1154f91b
BW
1567 return false;
1568}
1569
1570void wxAuiToolBar::EnableTool(int tool_id, bool state)
1571{
1572 wxAuiToolBarItem* tool = FindTool(tool_id);
eecf97a5 1573
1154f91b
BW
1574 if (tool)
1575 {
1576 if (state == true)
9a29fe70 1577 tool->m_state &= ~wxAUI_BUTTON_STATE_DISABLED;
8b385bf8 1578 else
9a29fe70 1579 tool->m_state |= wxAUI_BUTTON_STATE_DISABLED;
1154f91b
BW
1580 }
1581}
1582
1583bool wxAuiToolBar::GetToolEnabled(int tool_id) const
1584{
1585 wxAuiToolBarItem* tool = FindTool(tool_id);
eecf97a5 1586
1154f91b 1587 if (tool)
9a29fe70 1588 return (tool->m_state & wxAUI_BUTTON_STATE_DISABLED) ? false : true;
eecf97a5 1589
1154f91b
BW
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;
eecf97a5 1599
9a29fe70 1600 return tool->m_label;
1154f91b
BW
1601}
1602
1603void wxAuiToolBar::SetToolLabel(int tool_id, const wxString& label)
1604{
1605 wxAuiToolBarItem* tool = FindTool(tool_id);
1606 if (tool)
1607 {
9a29fe70 1608 tool->m_label = label;
1154f91b
BW
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;
eecf97a5 1618
9a29fe70 1619 return tool->m_bitmap;
1154f91b
BW
1620}
1621
1622void wxAuiToolBar::SetToolBitmap(int tool_id, const wxBitmap& bitmap)
1623{
1624 wxAuiToolBarItem* tool = FindTool(tool_id);
1625 if (tool)
1626 {
9a29fe70 1627 tool->m_bitmap = bitmap;
1154f91b
BW
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;
eecf97a5 1637
9a29fe70 1638 return tool->m_shortHelp;
1154f91b
BW
1639}
1640
1641void wxAuiToolBar::SetToolShortHelp(int tool_id, const wxString& help_string)
1642{
1643 wxAuiToolBarItem* tool = FindTool(tool_id);
1644 if (tool)
1645 {
9a29fe70 1646 tool->m_shortHelp = help_string;
1154f91b
BW
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;
eecf97a5 1656
9a29fe70 1657 return tool->m_longHelp;
1154f91b
BW
1658}
1659
1660void wxAuiToolBar::SetToolLongHelp(int tool_id, const wxString& help_string)
1661{
1662 wxAuiToolBarItem* tool = FindTool(tool_id);
1663 if (tool)
1664 {
9a29fe70 1665 tool->m_longHelp = help_string;
1154f91b
BW
1666 }
1667}
1668
1669void wxAuiToolBar::SetCustomOverflowItems(const wxAuiToolBarItemArray& prepend,
1670 const wxAuiToolBarItemArray& append)
1671{
9a29fe70
VZ
1672 m_customOverflowPrepend = prepend;
1673 m_customOverflowAppend = append;
1154f91b
BW
1674}
1675
e5dcae09
VZ
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:
71929371 1688 wxFAIL_MSG("invalid dock location value");
e5dcae09 1689 }
71929371 1690 return wxDefaultSize;
e5dcae09
VZ
1691}
1692
1693bool wxAuiToolBar::IsPaneValid(const wxAuiPaneInfo& pane) const
1694{
a69b365f 1695 return IsPaneValid(m_windowStyle, pane);
e5dcae09
VZ
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{
a69b365f 1729 unsigned int artflags = m_windowStyle & ~wxAUI_ORIENTATION_MASK;
e5dcae09
VZ
1730 if (m_orientation == wxVERTICAL)
1731 {
1732 artflags |= wxAUI_TB_VERTICAL;
1733 }
1734 m_art->SetFlags(artflags);
1735}
1154f91b
BW
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;
eecf97a5 1748
1154f91b
BW
1749 size_t i, count = m_items.GetCount();
1750 for (i = 0; i < count; ++i)
1751 {
1752 wxAuiToolBarItem& item = m_items.Item(i);
9a29fe70 1753 if (item.m_toolId == tool_id)
1154f91b
BW
1754 return i;
1755 }
eecf97a5 1756
1154f91b
BW
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;
eecf97a5 1764
9a29fe70 1765 if (!m_items[tool_idx].m_sizerItem)
1154f91b 1766 return false;
eecf97a5 1767
1154f91b
BW
1768 int cli_w, cli_h;
1769 GetClientSize(&cli_w, &cli_h);
eecf97a5 1770
9a29fe70 1771 wxRect rect = m_items[tool_idx].m_sizerItem->GetRect();
eecf97a5 1772
e5dcae09 1773 if (m_orientation == wxVERTICAL)
1154f91b
BW
1774 {
1775 // take the dropdown size into account
9a29fe70
VZ
1776 if (m_overflowVisible)
1777 cli_h -= m_overflowSizerItem->GetSize().y;
eecf97a5 1778
1154f91b
BW
1779 if (rect.y+rect.height < cli_h)
1780 return true;
1781 }
8b385bf8 1782 else
1154f91b
BW
1783 {
1784 // take the dropdown size into account
9a29fe70
VZ
1785 if (m_overflowVisible)
1786 cli_w -= m_overflowSizerItem->GetSize().x;
eecf97a5 1787
1154f91b
BW
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);
9a29fe70 1804 if (tool && tool->m_sizerItem)
1154f91b 1805 {
9a29fe70 1806 return tool->m_sizerItem->GetRect();
1154f91b 1807 }
eecf97a5 1808
1154f91b
BW
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 }
eecf97a5 1819
1154f91b
BW
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
e5dcae09
VZ
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 }
eecf97a5 1857
e5dcae09
VZ
1858 Refresh(false);
1859 return retval;
1860}
eecf97a5 1861
e5dcae09
VZ
1862bool wxAuiToolBar::RealizeHelper(wxClientDC& dc, bool horizontal)
1863{
1154f91b
BW
1864 // create the new sizer to add toolbar elements to
1865 wxBoxSizer* sizer = new wxBoxSizer(horizontal ? wxHORIZONTAL : wxVERTICAL);
eecf97a5 1866
1154f91b 1867 // add gripper area
9a29fe70
VZ
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)
1154f91b
BW
1871 {
1872 if (horizontal)
9a29fe70 1873 m_gripperSizerItem = sizer->Add(gripperSize, 1, 0, wxEXPAND);
8b385bf8 1874 else
9a29fe70 1875 m_gripperSizerItem = sizer->Add(1, gripperSize, 0, wxEXPAND);
1154f91b 1876 }
8b385bf8 1877 else
1154f91b 1878 {
9a29fe70 1879 m_gripperSizerItem = NULL;
1154f91b 1880 }
eecf97a5 1881
1154f91b 1882 // add "left" padding
9a29fe70 1883 if (m_leftPadding > 0)
1154f91b
BW
1884 {
1885 if (horizontal)
9a29fe70 1886 sizer->Add(m_leftPadding, 1);
8b385bf8 1887 else
9a29fe70 1888 sizer->Add(1, m_leftPadding);
1154f91b 1889 }
eecf97a5 1890
1154f91b
BW
1891 size_t i, count;
1892 for (i = 0, count = m_items.GetCount(); i < count; ++i)
1893 {
1894 wxAuiToolBarItem& item = m_items.Item(i);
9a29fe70 1895 wxSizerItem* m_sizerItem = NULL;
eecf97a5 1896
9a29fe70 1897 switch (item.m_kind)
eecf97a5 1898 {
1154f91b
BW
1899 case wxITEM_LABEL:
1900 {
1901 wxSize size = m_art->GetLabelSize(dc, this, item);
9a29fe70
VZ
1902 m_sizerItem = sizer->Add(size.x + (m_toolBorderPadding*2),
1903 size.y + (m_toolBorderPadding*2),
1904 item.m_proportion,
1905 item.m_alignment);
1154f91b
BW
1906 if (i+1 < count)
1907 {
9a29fe70 1908 sizer->AddSpacer(m_toolPacking);
1154f91b 1909 }
eecf97a5 1910
1154f91b
BW
1911 break;
1912 }
eecf97a5 1913
1154f91b
BW
1914 case wxITEM_CHECK:
1915 case wxITEM_NORMAL:
cae51973 1916 case wxITEM_RADIO:
1154f91b
BW
1917 {
1918 wxSize size = m_art->GetToolSize(dc, this, item);
9a29fe70
VZ
1919 m_sizerItem = sizer->Add(size.x + (m_toolBorderPadding*2),
1920 size.y + (m_toolBorderPadding*2),
1154f91b 1921 0,
9a29fe70 1922 item.m_alignment);
1154f91b
BW
1923 // add tool packing
1924 if (i+1 < count)
1925 {
9a29fe70 1926 sizer->AddSpacer(m_toolPacking);
1154f91b 1927 }
eecf97a5 1928
1154f91b
BW
1929 break;
1930 }
eecf97a5 1931
1154f91b
BW
1932 case wxITEM_SEPARATOR:
1933 {
1934 if (horizontal)
9a29fe70 1935 m_sizerItem = sizer->Add(separatorSize, 1, 0, wxEXPAND);
8b385bf8 1936 else
9a29fe70 1937 m_sizerItem = sizer->Add(1, separatorSize, 0, wxEXPAND);
1154f91b
BW
1938
1939 // add tool packing
1940 if (i+1 < count)
1941 {
9a29fe70 1942 sizer->AddSpacer(m_toolPacking);
1154f91b 1943 }
eecf97a5 1944
1154f91b
BW
1945 break;
1946 }
eecf97a5 1947
1154f91b 1948 case wxITEM_SPACER:
9a29fe70
VZ
1949 if (item.m_proportion > 0)
1950 m_sizerItem = sizer->AddStretchSpacer(item.m_proportion);
8b385bf8 1951 else
9a29fe70 1952 m_sizerItem = sizer->Add(item.m_spacerPixels, 1);
1154f91b 1953 break;
eecf97a5 1954
1154f91b
BW
1955 case wxITEM_CONTROL:
1956 {
9a29fe70
VZ
1957 //m_sizerItem = sizer->Add(item.m_window, item.m_proportion, wxEXPAND);
1958 wxSizerItem* ctrl_m_sizerItem;
eecf97a5 1959
1154f91b
BW
1960 wxBoxSizer* vert_sizer = new wxBoxSizer(wxVERTICAL);
1961 vert_sizer->AddStretchSpacer(1);
9a29fe70 1962 ctrl_m_sizerItem = vert_sizer->Add(item.m_window, 0, wxEXPAND);
1154f91b 1963 vert_sizer->AddStretchSpacer(1);
a69b365f 1964 if ( (m_windowStyle & wxAUI_TB_TEXT) &&
9a29fe70 1965 m_toolTextOrientation == wxAUI_TBTOOL_TEXT_BOTTOM &&
23511cdb 1966 !item.GetLabel().empty() )
1154f91b 1967 {
e42f2c16 1968 wxSize s = GetLabelSize(item.GetLabel());
1154f91b
BW
1969 vert_sizer->Add(1, s.y);
1970 }
eecf97a5
VZ
1971
1972
9a29fe70 1973 m_sizerItem = sizer->Add(vert_sizer, item.m_proportion, wxEXPAND);
eecf97a5 1974
9a29fe70 1975 wxSize min_size = item.m_minSize;
eecf97a5 1976
1154f91b
BW
1977
1978 // proportional items will disappear from the toolbar if
1979 // their min width is not set to something really small
9a29fe70 1980 if (item.m_proportion != 0)
1154f91b
BW
1981 {
1982 min_size.x = 1;
1983 }
eecf97a5 1984
1154f91b
BW
1985 if (min_size.IsFullySpecified())
1986 {
9a29fe70
VZ
1987 m_sizerItem->SetMinSize(min_size);
1988 ctrl_m_sizerItem->SetMinSize(min_size);
1154f91b
BW
1989 }
1990
1991 // add tool packing
1992 if (i+1 < count)
1993 {
9a29fe70 1994 sizer->AddSpacer(m_toolPacking);
1154f91b
BW
1995 }
1996 }
1997 }
eecf97a5 1998
9a29fe70 1999 item.m_sizerItem = m_sizerItem;
1154f91b
BW
2000 }
2001
2002 // add "right" padding
9a29fe70 2003 if (m_rightPadding > 0)
1154f91b
BW
2004 {
2005 if (horizontal)
9a29fe70 2006 sizer->Add(m_rightPadding, 1);
8b385bf8 2007 else
9a29fe70 2008 sizer->Add(1, m_rightPadding);
1154f91b 2009 }
eecf97a5 2010
1154f91b 2011 // add drop down area
9a29fe70 2012 m_overflowSizerItem = NULL;
eecf97a5 2013
a69b365f 2014 if (m_windowStyle & wxAUI_TB_OVERFLOW)
1154f91b
BW
2015 {
2016 int overflow_size = m_art->GetElementSize(wxAUI_TBART_OVERFLOW_SIZE);
9a29fe70 2017 if (overflow_size > 0 && m_overflowVisible)
1154f91b
BW
2018 {
2019 if (horizontal)
9a29fe70 2020 m_overflowSizerItem = sizer->Add(overflow_size, 1, 0, wxEXPAND);
8b385bf8 2021 else
9a29fe70 2022 m_overflowSizerItem = sizer->Add(1, overflow_size, 0, wxEXPAND);
1154f91b 2023 }
8b385bf8 2024 else
1154f91b 2025 {
9a29fe70 2026 m_overflowSizerItem = NULL;
1154f91b
BW
2027 }
2028 }
eecf97a5 2029
1154f91b
BW
2030
2031 // the outside sizer helps us apply the "top" and "bottom" padding
2032 wxBoxSizer* outside_sizer = new wxBoxSizer(horizontal ? wxVERTICAL : wxHORIZONTAL);
eecf97a5 2033
1154f91b 2034 // add "top" padding
9a29fe70 2035 if (m_topPadding > 0)
1154f91b
BW
2036 {
2037 if (horizontal)
9a29fe70 2038 outside_sizer->Add(1, m_topPadding);
8b385bf8 2039 else
9a29fe70 2040 outside_sizer->Add(m_topPadding, 1);
1154f91b
BW
2041 }
2042
2043 // add the sizer that contains all of the toolbar elements
2044 outside_sizer->Add(sizer, 1, wxEXPAND);
eecf97a5 2045
1154f91b 2046 // add "bottom" padding
9a29fe70 2047 if (m_bottomPadding > 0)
1154f91b
BW
2048 {
2049 if (horizontal)
9a29fe70 2050 outside_sizer->Add(1, m_bottomPadding);
8b385bf8 2051 else
9a29fe70 2052 outside_sizer->Add(m_bottomPadding, 1);
1154f91b 2053 }
eecf97a5 2054
1154f91b
BW
2055 delete m_sizer; // remove old sizer
2056 m_sizer = outside_sizer;
eecf97a5 2057
1154f91b
BW
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);
9a29fe70
VZ
2062 if (item.m_sizerItem && item.m_proportion > 0 && item.m_minSize.IsFullySpecified())
2063 item.m_sizerItem->SetMinSize(0,0);
1154f91b 2064 }
eecf97a5 2065
9a29fe70 2066 m_absoluteMinSize = m_sizer->GetMinSize();
eecf97a5 2067
1154f91b
BW
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);
9a29fe70
VZ
2072 if (item.m_sizerItem && item.m_proportion > 0 && item.m_minSize.IsFullySpecified())
2073 item.m_sizerItem->SetMinSize(item.m_minSize);
eecf97a5 2074 }
1154f91b
BW
2075
2076 // set control size
2077 wxSize size = m_sizer->GetMinSize();
2078 m_minWidth = size.x;
2079 m_minHeight = size.y;
eecf97a5 2080
a69b365f 2081 if ((m_windowStyle & wxAUI_TB_NO_AUTORESIZE) == 0)
1154f91b 2082 {
9a29fe70 2083 wxSize curSize = GetClientSize();
1154f91b 2084 wxSize new_size = GetMinSize();
9a29fe70 2085 if (new_size != curSize)
1154f91b
BW
2086 {
2087 SetClientSize(new_size);
2088 }
8b385bf8 2089 else
1154f91b 2090 {
9a29fe70 2091 m_sizer->SetDimension(0, 0, curSize.x, curSize.y);
1154f91b 2092 }
eecf97a5 2093 }
8b385bf8 2094 else
1154f91b 2095 {
9a29fe70
VZ
2096 wxSize curSize = GetClientSize();
2097 m_sizer->SetDimension(0, 0, curSize.x, curSize.y);
1154f91b 2098 }
eecf97a5 2099
1154f91b
BW
2100 return true;
2101}
2102
2103int wxAuiToolBar::GetOverflowState() const
2104{
9a29fe70 2105 return m_overflowState;
1154f91b
BW
2106}
2107
2108wxRect wxAuiToolBar::GetOverflowRect() const
eecf97a5 2109{
1154f91b 2110 wxRect cli_rect(wxPoint(0,0), GetClientSize());
9a29fe70 2111 wxRect overflow_rect = m_overflowSizerItem->GetRect();
1154f91b
BW
2112 int overflow_size = m_art->GetElementSize(wxAUI_TBART_OVERFLOW_SIZE);
2113
e5dcae09 2114 if (m_orientation == wxVERTICAL)
1154f91b
BW
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 }
8b385bf8 2121 else
1154f91b
BW
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 }
eecf97a5 2128
1154f91b
BW
2129 return overflow_rect;
2130}
2131
2132wxSize wxAuiToolBar::GetLabelSize(const wxString& label)
2133{
2134 wxClientDC dc(this);
eecf97a5 2135
1154f91b 2136 int tx, ty;
9a29fe70 2137 int textWidth = 0, textHeight = 0;
1154f91b
BW
2138
2139 dc.SetFont(m_font);
eecf97a5 2140
1154f91b 2141 // get the text height
9a29fe70 2142 dc.GetTextExtent(wxT("ABCDHgj"), &tx, &textHeight);
1154f91b
BW
2143
2144 // get the text width
9a29fe70 2145 dc.GetTextExtent(label, &textWidth, &ty);
1154f91b 2146
9a29fe70 2147 return wxSize(textWidth, textHeight);
1154f91b
BW
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);
eecf97a5 2161
9a29fe70 2162 if (item.m_toolId == -1)
1154f91b 2163 continue;
eecf97a5 2164
9a29fe70 2165 wxUpdateUIEvent evt(item.m_toolId);
1154f91b
BW
2166 evt.SetEventObject(this);
2167
2168 if (handler->ProcessEvent(evt))
2169 {
2170 if (evt.GetSetEnabled())
2171 {
2172 bool is_enabled;
9a29fe70 2173 if (item.m_window)
03dc350f 2174 is_enabled = item.m_window->IsThisEnabled();
8b385bf8 2175 else
9a29fe70 2176 is_enabled = (item.m_state & wxAUI_BUTTON_STATE_DISABLED) ? false : true;
eecf97a5 2177
1154f91b
BW
2178 bool new_enabled = evt.GetEnabled();
2179 if (new_enabled != is_enabled)
2180 {
9a29fe70 2181 if (item.m_window)
1154f91b 2182 {
9a29fe70 2183 item.m_window->Enable(new_enabled);
1154f91b 2184 }
8b385bf8 2185 else
1154f91b
BW
2186 {
2187 if (new_enabled)
9a29fe70 2188 item.m_state &= ~wxAUI_BUTTON_STATE_DISABLED;
8b385bf8 2189 else
9a29fe70 2190 item.m_state |= wxAUI_BUTTON_STATE_DISABLED;
1154f91b
BW
2191 }
2192 need_refresh = true;
2193 }
2194 }
eecf97a5 2195
1154f91b
BW
2196 if (evt.GetSetChecked())
2197 {
2198 // make sure we aren't checking an item that can't be
9a29fe70 2199 if (item.m_kind != wxITEM_CHECK && item.m_kind != wxITEM_RADIO)
1154f91b
BW
2200 continue;
2201
9a29fe70 2202 bool is_checked = (item.m_state & wxAUI_BUTTON_STATE_CHECKED) ? true : false;
1154f91b
BW
2203 bool new_checked = evt.GetChecked();
2204
2205 if (new_checked != is_checked)
2206 {
2207 if (new_checked)
9a29fe70 2208 item.m_state |= wxAUI_BUTTON_STATE_CHECKED;
8b385bf8 2209 else
9a29fe70 2210 item.m_state &= ~wxAUI_BUTTON_STATE_CHECKED;
eecf97a5 2211
1154f91b
BW
2212 need_refresh = true;
2213 }
2214 }
2215
2216 }
2217 }
eecf97a5 2218
1154f91b
BW
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
9a29fe70
VZ
2232 if (((x >= y) && m_absoluteMinSize.x > x) ||
2233 ((y > x) && m_absoluteMinSize.y > y))
1154f91b
BW
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);
9a29fe70 2240 if (item.m_sizerItem && item.m_proportion > 0 && item.m_sizerItem->IsShown())
1154f91b 2241 {
9a29fe70
VZ
2242 item.m_sizerItem->Show(false);
2243 item.m_sizerItem->SetProportion(0);
1154f91b
BW
2244 }
2245 }
2246 }
8b385bf8 2247 else
1154f91b
BW
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);
9a29fe70 2254 if (item.m_sizerItem && item.m_proportion > 0 && !item.m_sizerItem->IsShown())
1154f91b 2255 {
9a29fe70
VZ
2256 item.m_sizerItem->Show(true);
2257 item.m_sizerItem->SetProportion(item.m_proportion);
1154f91b
BW
2258 }
2259 }
2260 }
2261
2262 m_sizer->SetDimension(0, 0, x, y);
2263
2264 Refresh(false);
2265 Update();
e5dcae09
VZ
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);
1154f91b
BW
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{
e5dcae09
VZ
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();
a69b365f 2301 wxCHECK2_MSG(!ok || IsPaneValid(m_windowStyle, pane), ok = false,
e5dcae09
VZ
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() &&
a69b365f 2323 GetOrientation(m_windowStyle) == wxBOTH)
e5dcae09
VZ
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 }
1154f91b
BW
2362 evt.Skip();
2363}
2364
3ac17397
VZ
2365void wxAuiToolBar::UpdateWindowUI(long flags)
2366{
2367 if ( flags & wxUPDATE_UI_FROMIDLE )
2368 {
2369 DoIdleUpdate();
2370 }
2371
2372 wxControl::UpdateWindowUI(flags);
2373}
2374
1154f91b
BW
2375void wxAuiToolBar::OnPaint(wxPaintEvent& WXUNUSED(evt))
2376{
66ad3095 2377 wxAutoBufferedPaintDC dc(this);
1154f91b 2378 wxRect cli_rect(wxPoint(0,0), GetClientSize());
eecf97a5
VZ
2379
2380
e5dcae09 2381 bool horizontal = m_orientation == wxHORIZONTAL;
1154f91b 2382
526502d1
VZ
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);
eecf97a5 2387
9a29fe70 2388 int gripperSize = m_art->GetElementSize(wxAUI_TBART_GRIPPER_SIZE);
1154f91b 2389 int dropdown_size = m_art->GetElementSize(wxAUI_TBART_OVERFLOW_SIZE);
eecf97a5 2390
1154f91b 2391 // paint the gripper
9a29fe70 2392 if (gripperSize > 0 && m_gripperSizerItem)
1154f91b 2393 {
9a29fe70 2394 wxRect gripper_rect = m_gripperSizerItem->GetRect();
1154f91b 2395 if (horizontal)
9a29fe70 2396 gripper_rect.width = gripperSize;
8b385bf8 2397 else
9a29fe70 2398 gripper_rect.height = gripperSize;
1154f91b
BW
2399 m_art->DrawGripper(dc, this, gripper_rect);
2400 }
eecf97a5 2401
1154f91b
BW
2402 // calculated how far we can draw items
2403 int last_extent;
2404 if (horizontal)
2405 last_extent = cli_rect.width;
8b385bf8 2406 else
1154f91b 2407 last_extent = cli_rect.height;
9a29fe70 2408 if (m_overflowVisible)
1154f91b 2409 last_extent -= dropdown_size;
eecf97a5 2410
1154f91b
BW
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);
eecf97a5 2416
9a29fe70 2417 if (!item.m_sizerItem)
1154f91b 2418 continue;
eecf97a5 2419
9a29fe70 2420 wxRect item_rect = item.m_sizerItem->GetRect();
eecf97a5
VZ
2421
2422
1154f91b
BW
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 }
eecf97a5 2428
72ae0b51 2429 switch ( item.m_kind )
1154f91b 2430 {
72ae0b51
VZ
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
026c6eff 2442 m_art->DrawButton(dc, this, item, item_rect);
72ae0b51
VZ
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;
1154f91b
BW
2459 }
2460
2461 // fire a signal to see if the item wants to be custom-rendered
2462 OnCustomRender(dc, item, item_rect);
2463 }
eecf97a5 2464
1154f91b 2465 // paint the overflow button
9a29fe70 2466 if (dropdown_size > 0 && m_overflowSizerItem)
1154f91b 2467 {
9a29fe70
VZ
2468 wxRect dropDownRect = GetOverflowRect();
2469 m_art->DrawOverflowButton(dc, this, dropDownRect, m_overflowState);
1154f91b
BW
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());
eecf97a5 2481
9a29fe70 2482 if (m_gripperSizerItem)
1154f91b 2483 {
9a29fe70 2484 wxRect gripper_rect = m_gripperSizerItem->GetRect();
1154f91b
BW
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;
eecf97a5 2491
1154f91b
BW
2492 int x_drag_offset = evt.GetX() - gripper_rect.GetX();
2493 int y_drag_offset = evt.GetY() - gripper_rect.GetY();
eecf97a5 2494
1154f91b
BW
2495 // gripper was clicked
2496 manager->StartPaneDrag(this, wxPoint(x_drag_offset, y_drag_offset));
2497 return;
2498 }
2499 }
eecf97a5 2500
9a29fe70 2501 if (m_overflowSizerItem)
1154f91b
BW
2502 {
2503 wxRect overflow_rect = GetOverflowRect();
eecf97a5
VZ
2504
2505 if (m_art &&
9a29fe70 2506 m_overflowVisible &&
1154f91b
BW
2507 overflow_rect.Contains(evt.m_x, evt.m_y))
2508 {
ce7fe42e 2509 wxAuiToolBarEvent e(wxEVT_AUITOOLBAR_OVERFLOW_CLICK, -1);
1154f91b
BW
2510 e.SetEventObject(this);
2511 e.SetToolId(-1);
2512 e.SetClickPoint(wxPoint(evt.GetX(), evt.GetY()));
004867db 2513 bool processed = GetEventHandler()->ProcessEvent(e);
eecf97a5 2514
1154f91b
BW
2515 if (processed)
2516 {
2517 DoIdleUpdate();
2518 }
8b385bf8 2519 else
1154f91b
BW
2520 {
2521 size_t i, count;
2522 wxAuiToolBarItemArray overflow_items;
eecf97a5 2523
1154f91b
BW
2524
2525 // add custom overflow prepend items, if any
9a29fe70 2526 count = m_customOverflowPrepend.GetCount();
1154f91b 2527 for (i = 0; i < count; ++i)
9a29fe70 2528 overflow_items.Add(m_customOverflowPrepend[i]);
eecf97a5 2529
1154f91b
BW
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
9a29fe70 2539 count = m_customOverflowAppend.GetCount();
1154f91b 2540 for (i = 0; i < count; ++i)
9a29fe70 2541 overflow_items.Add(m_customOverflowAppend[i]);
eecf97a5 2542
1154f91b 2543 int res = m_art->ShowDropDown(this, overflow_items);
9a29fe70 2544 m_overflowState = 0;
1154f91b
BW
2545 Refresh(false);
2546 if (res != -1)
2547 {
ce7fe42e 2548 wxCommandEvent event(wxEVT_MENU, res);
7d1214cd
PC
2549 event.SetEventObject(this);
2550 GetParent()->GetEventHandler()->ProcessEvent(event);
1154f91b
BW
2551 }
2552 }
eecf97a5 2553
1154f91b
BW
2554 return;
2555 }
2556 }
eecf97a5 2557
1154f91b 2558 m_dragging = false;
9a29fe70
VZ
2559 m_actionPos = wxPoint(evt.GetX(), evt.GetY());
2560 m_actionItem = FindToolByPosition(evt.GetX(), evt.GetY());
eecf97a5 2561
9a29fe70 2562 if (m_actionItem)
1154f91b 2563 {
9a29fe70 2564 if (m_actionItem->m_state & wxAUI_BUTTON_STATE_DISABLED)
1154f91b 2565 {
9a29fe70
VZ
2566 m_actionPos = wxPoint(-1,-1);
2567 m_actionItem = NULL;
1154f91b
BW
2568 return;
2569 }
eecf97a5 2570
4a21ea9d 2571 UnsetToolTip();
eecf97a5 2572
1154f91b 2573 // fire the tool dropdown event
ce7fe42e 2574 wxAuiToolBarEvent e(wxEVT_AUITOOLBAR_TOOL_DROPDOWN, m_actionItem->m_toolId);
1154f91b 2575 e.SetEventObject(this);
9a29fe70 2576 e.SetToolId(m_actionItem->m_toolId);
eecf97a5 2577
1154f91b 2578 int mouse_x = evt.GetX();
9a29fe70
VZ
2579 wxRect rect = m_actionItem->m_sizerItem->GetRect();
2580 const bool dropDownHit = m_actionItem->m_dropDown &&
4a21ea9d
VZ
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
9a29fe70 2590 SetPressedItem(dropDownHit ? 0 : m_actionItem);
eecf97a5 2591
4a21ea9d 2592 if(dropDownHit)
1154f91b 2593 {
9a29fe70
VZ
2594 m_actionPos = wxPoint(-1,-1);
2595 m_actionItem = NULL;
1154f91b 2596 }
eecf97a5 2597
4a21ea9d
VZ
2598 if(!GetEventHandler()->ProcessEvent(e) || e.GetSkipped())
2599 CaptureMouse();
2600
c2211811
VZ
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
1154f91b
BW
2606 DoIdleUpdate();
2607 }
2608}
2609
2610void wxAuiToolBar::OnLeftUp(wxMouseEvent& evt)
2611{
4a21ea9d
VZ
2612 if (!HasCapture())
2613 return;
2614
1154f91b
BW
2615 SetPressedItem(NULL);
2616
c2211811
VZ
2617 wxAuiToolBarItem* hitItem;
2618 hitItem = FindToolByPosition(evt.GetX(), evt.GetY());
2619 SetHoverItem(hitItem);
1154f91b 2620
1154f91b
BW
2621 if (m_dragging)
2622 {
4a21ea9d
VZ
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();
1154f91b 2630 }
8b385bf8 2631 else
1154f91b 2632 {
9a29fe70 2633 if (m_actionItem && hitItem == m_actionItem)
1154f91b 2634 {
8b385bf8 2635 UnsetToolTip();
eecf97a5 2636
ce7fe42e 2637 wxCommandEvent e(wxEVT_MENU, m_actionItem->m_toolId);
4a21ea9d
VZ
2638 e.SetEventObject(this);
2639
9a29fe70 2640 if (hitItem->m_kind == wxITEM_CHECK || hitItem->m_kind == wxITEM_RADIO)
1154f91b 2641 {
9a29fe70 2642 const bool toggle = !(m_actionItem->m_state & wxAUI_BUTTON_STATE_CHECKED);
eecf97a5 2643
9a29fe70 2644 ToggleTool(m_actionItem->m_toolId, toggle);
45496810 2645
cae51973
BW
2646 // repaint immediately
2647 Refresh(false);
2648 Update();
45496810 2649
4a21ea9d 2650 e.SetInt(toggle);
1154f91b 2651 }
4a21ea9d
VZ
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);
c2211811
VZ
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
4a21ea9d 2666 DoIdleUpdate();
1154f91b 2667 }
4a21ea9d
VZ
2668 else
2669 ReleaseMouse();
1154f91b 2670 }
1154f91b
BW
2671}
2672
2673void wxAuiToolBar::OnRightDown(wxMouseEvent& evt)
2674{
2675 wxRect cli_rect(wxPoint(0,0), GetClientSize());
eecf97a5 2676
9a29fe70 2677 if (m_gripperSizerItem)
1154f91b 2678 {
9a29fe70 2679 wxRect gripper_rect = m_gripperSizerItem->GetRect();
1154f91b
BW
2680 if (gripper_rect.Contains(evt.GetX(), evt.GetY()))
2681 return;
2682 }
eecf97a5 2683
f90b69e0 2684 if (m_overflowSizerItem && m_art)
1154f91b
BW
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 &&
f90b69e0 2690 evt.m_y < cli_rect.height)
1154f91b
BW
2691 {
2692 return;
2693 }
2694 }
eecf97a5 2695
9a29fe70
VZ
2696 m_actionPos = wxPoint(evt.GetX(), evt.GetY());
2697 m_actionItem = FindToolByPosition(evt.GetX(), evt.GetY());
eecf97a5 2698
9a29fe70 2699 if (m_actionItem && m_actionItem->m_state & wxAUI_BUTTON_STATE_DISABLED)
1154f91b 2700 {
9a29fe70
VZ
2701 m_actionPos = wxPoint(-1,-1);
2702 m_actionItem = NULL;
4a21ea9d 2703 return;
1154f91b 2704 }
4a21ea9d
VZ
2705
2706 UnsetToolTip();
1154f91b
BW
2707}
2708
2709void wxAuiToolBar::OnRightUp(wxMouseEvent& evt)
2710{
9a29fe70
VZ
2711 wxAuiToolBarItem* hitItem;
2712 hitItem = FindToolByPosition(evt.GetX(), evt.GetY());
eecf97a5 2713
9a29fe70 2714 if (m_actionItem && hitItem == m_actionItem)
1154f91b 2715 {
ce7fe42e 2716 wxAuiToolBarEvent e(wxEVT_AUITOOLBAR_RIGHT_CLICK, m_actionItem->m_toolId);
f5fccd52
VZ
2717 e.SetEventObject(this);
2718 e.SetToolId(m_actionItem->m_toolId);
2719 e.SetClickPoint(m_actionPos);
2720 GetEventHandler()->ProcessEvent(e);
2721 DoIdleUpdate();
1154f91b 2722 }
8b385bf8 2723 else
1154f91b
BW
2724 {
2725 // right-clicked on the invalid area of the toolbar
ce7fe42e 2726 wxAuiToolBarEvent e(wxEVT_AUITOOLBAR_RIGHT_CLICK, -1);
1154f91b
BW
2727 e.SetEventObject(this);
2728 e.SetToolId(-1);
9a29fe70 2729 e.SetClickPoint(m_actionPos);
004867db 2730 GetEventHandler()->ProcessEvent(e);
1154f91b
BW
2731 DoIdleUpdate();
2732 }
2733
2734 // reset member variables
9a29fe70
VZ
2735 m_actionPos = wxPoint(-1,-1);
2736 m_actionItem = NULL;
1154f91b
BW
2737}
2738
2739void wxAuiToolBar::OnMiddleDown(wxMouseEvent& evt)
2740{
2741 wxRect cli_rect(wxPoint(0,0), GetClientSize());
eecf97a5 2742
9a29fe70 2743 if (m_gripperSizerItem)
1154f91b 2744 {
9a29fe70 2745 wxRect gripper_rect = m_gripperSizerItem->GetRect();
1154f91b
BW
2746 if (gripper_rect.Contains(evt.GetX(), evt.GetY()))
2747 return;
2748 }
eecf97a5 2749
f90b69e0 2750 if (m_overflowSizerItem && m_art)
1154f91b
BW
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 &&
f90b69e0 2756 evt.m_y < cli_rect.height)
1154f91b
BW
2757 {
2758 return;
2759 }
2760 }
eecf97a5 2761
9a29fe70
VZ
2762 m_actionPos = wxPoint(evt.GetX(), evt.GetY());
2763 m_actionItem = FindToolByPosition(evt.GetX(), evt.GetY());
eecf97a5 2764
9a29fe70 2765 if (m_actionItem)
1154f91b 2766 {
9a29fe70 2767 if (m_actionItem->m_state & wxAUI_BUTTON_STATE_DISABLED)
1154f91b 2768 {
9a29fe70
VZ
2769 m_actionPos = wxPoint(-1,-1);
2770 m_actionItem = NULL;
1154f91b
BW
2771 return;
2772 }
2773 }
4a21ea9d
VZ
2774
2775 UnsetToolTip();
1154f91b
BW
2776}
2777
2778void wxAuiToolBar::OnMiddleUp(wxMouseEvent& evt)
2779{
9a29fe70
VZ
2780 wxAuiToolBarItem* hitItem;
2781 hitItem = FindToolByPosition(evt.GetX(), evt.GetY());
eecf97a5 2782
9a29fe70 2783 if (m_actionItem && hitItem == m_actionItem)
1154f91b 2784 {
9a29fe70 2785 if (hitItem->m_kind == wxITEM_NORMAL)
1154f91b 2786 {
ce7fe42e 2787 wxAuiToolBarEvent e(wxEVT_AUITOOLBAR_MIDDLE_CLICK, m_actionItem->m_toolId);
1154f91b 2788 e.SetEventObject(this);
9a29fe70
VZ
2789 e.SetToolId(m_actionItem->m_toolId);
2790 e.SetClickPoint(m_actionPos);
004867db 2791 GetEventHandler()->ProcessEvent(e);
1154f91b
BW
2792 DoIdleUpdate();
2793 }
2794 }
2795
2796 // reset member variables
9a29fe70
VZ
2797 m_actionPos = wxPoint(-1,-1);
2798 m_actionItem = NULL;
1154f91b
BW
2799}
2800
2801void wxAuiToolBar::OnMotion(wxMouseEvent& evt)
2802{
4a21ea9d
VZ
2803 const bool button_pressed = HasCapture();
2804
1154f91b 2805 // start a drag event
4a21ea9d 2806 if (!m_dragging && button_pressed &&
9a29fe70 2807 abs(evt.GetX() - m_actionPos.x) + abs(evt.GetY() - m_actionPos.y) > 5)
1154f91b 2808 {
4a21ea9d
VZ
2809 // TODO: sending this event only makes sense if there is an 'END_DRAG'
2810 // event sent sometime in the future (see OnLeftUp())
ce7fe42e 2811 wxAuiToolBarEvent e(wxEVT_AUITOOLBAR_BEGIN_DRAG, GetId());
1154f91b 2812 e.SetEventObject(this);
9a29fe70 2813 e.SetToolId(m_actionItem->m_toolId);
4a21ea9d
VZ
2814 m_dragging = GetEventHandler()->ProcessEvent(e) && !e.GetSkipped();
2815
1154f91b 2816 DoIdleUpdate();
1154f91b
BW
2817 }
2818
4a21ea9d
VZ
2819 if(m_dragging)
2820 return;
2821
9a29fe70 2822 wxAuiToolBarItem* hitItem = FindToolByPosition(evt.GetX(), evt.GetY());
4a21ea9d 2823 if(button_pressed)
1154f91b 2824 {
4a21ea9d
VZ
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'
9a29fe70
VZ
2828 if (hitItem == m_actionItem)
2829 SetPressedItem(m_actionItem);
8b385bf8 2830 else
4a21ea9d
VZ
2831 {
2832 SetPressedItem(NULL);
9a29fe70 2833 SetHoverItem(m_actionItem);
4a21ea9d 2834 }
1154f91b 2835 }
8b385bf8 2836 else
1154f91b 2837 {
c2211811 2838 SetHoverItem(hitItem);
eecf97a5 2839
4a21ea9d 2840 // tooltips handling
9a29fe70
VZ
2841 wxAuiToolBarItem* packingHitItem;
2842 packingHitItem = FindToolByPositionWithPacking(evt.GetX(), evt.GetY());
2843 if (packingHitItem)
1154f91b 2844 {
9a29fe70 2845 if (packingHitItem != m_tipItem)
4a21ea9d 2846 {
9a29fe70 2847 m_tipItem = packingHitItem;
eecf97a5 2848
9a29fe70
VZ
2849 if ( !packingHitItem->m_shortHelp.empty() )
2850 SetToolTip(packingHitItem->m_shortHelp);
4a21ea9d
VZ
2851 else
2852 UnsetToolTip();
2853 }
1154f91b 2854 }
8b385bf8 2855 else
4a21ea9d
VZ
2856 {
2857 UnsetToolTip();
9a29fe70 2858 m_tipItem = NULL;
4a21ea9d 2859 }
eecf97a5 2860
4a21ea9d
VZ
2861 // figure out the dropdown button state (are we hovering or pressing it?)
2862 RefreshOverflowState();
2863 }
1154f91b
BW
2864}
2865
4a21ea9d 2866void wxAuiToolBar::DoResetMouseState()
1154f91b
BW
2867{
2868 RefreshOverflowState();
2869 SetHoverItem(NULL);
2870 SetPressedItem(NULL);
eecf97a5 2871
9a29fe70 2872 m_tipItem = NULL;
4a21ea9d
VZ
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
9a29fe70
VZ
2877 m_actionPos = wxPoint(-1,-1);
2878 m_actionItem = NULL;
1154f91b
BW
2879}
2880
4a21ea9d
VZ
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}
1154f91b
BW
2898
2899void wxAuiToolBar::OnSetCursor(wxSetCursorEvent& evt)
2900{
2901 wxCursor cursor = wxNullCursor;
eecf97a5 2902
9a29fe70 2903 if (m_gripperSizerItem)
1154f91b 2904 {
9a29fe70 2905 wxRect gripper_rect = m_gripperSizerItem->GetRect();
1154f91b
BW
2906 if (gripper_rect.Contains(evt.GetX(), evt.GetY()))
2907 {
2908 cursor = wxCursor(wxCURSOR_SIZING);
2909 }
2910 }
eecf97a5 2911
1154f91b
BW
2912 evt.SetCursor(cursor);
2913}
2914
2915
2916#endif // wxUSE_AUI
2917