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