]> git.saurik.com Git - wxWidgets.git/blame - src/univ/toolbar.cpp
generate middle click events (patch 1521314)
[wxWidgets.git] / src / univ / toolbar.cpp
CommitLineData
c08a4f00
RR
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/univ/toolbar.cpp
3216dbf5
VZ
3// Purpose: implementation of wxToolBar for wxUniversal
4// Author: Robert Roebling, Vadim Zeitlin (universalization)
5// Modified by:
6// Created: 20.02.02
c08a4f00 7// Id: $Id$
3216dbf5
VZ
8// Copyright: (c) 2001 Robert Roebling,
9// (c) 2002 SciTech Software, Inc. (www.scitechsoft.com)
65571936 10// Licence: wxWindows licence
c08a4f00
RR
11/////////////////////////////////////////////////////////////////////////////
12
13// ============================================================================
14// declarations
15// ============================================================================
16
17// ----------------------------------------------------------------------------
18// headers
19// ----------------------------------------------------------------------------
20
c08a4f00
RR
21// For compilers that support precompilation, includes "wx.h".
22#include "wx/wxprec.h"
23
24#ifdef __BORLANDC__
25 #pragma hdrstop
26#endif
27
6a317e61
VZ
28#if wxUSE_TOOLBAR
29
e4db172a
WS
30#include "wx/toolbar.h"
31
c08a4f00
RR
32#ifndef WX_PRECOMP
33 #include "wx/utils.h"
34 #include "wx/app.h"
e4db172a 35 #include "wx/log.h"
76b49cf4 36 #include "wx/frame.h"
370efbe7 37 #include "wx/dc.h"
155ecd4c 38 #include "wx/image.h"
c08a4f00
RR
39#endif
40
a9b33d6b
VZ
41#include "wx/univ/renderer.h"
42
3216dbf5
VZ
43// ----------------------------------------------------------------------------
44// constants
45// ----------------------------------------------------------------------------
46
47// value meaning that m_widthSeparator is not initialized
a290fa5a 48static const wxCoord INVALID_WIDTH = wxDefaultCoord;
3216dbf5
VZ
49
50// ----------------------------------------------------------------------------
51// wxToolBarTool: our implementation of wxToolBarToolBase
52// ----------------------------------------------------------------------------
53
54class WXDLLEXPORT wxToolBarTool : public wxToolBarToolBase
16c9a425 55{
3216dbf5 56public:
d448aec3
VZ
57 wxToolBarTool(wxToolBar *tbar,
58 int id,
59 const wxString& label,
60 const wxBitmap& bmpNormal,
61 const wxBitmap& bmpDisabled,
62 wxItemKind kind,
63 wxObject *clientData,
64 const wxString& shortHelp,
65 const wxString& longHelp)
66 : wxToolBarToolBase(tbar, id, label, bmpNormal, bmpDisabled, kind,
67 clientData, shortHelp, longHelp)
3216dbf5
VZ
68 {
69 // no position yet
70 m_x =
a290fa5a 71 m_y = wxDefaultCoord;
a8f4cabe
JS
72 m_width =
73 m_height = 0;
74
75 // not pressed yet
a290fa5a 76 m_isInverted = false;
32b13913 77
a8f4cabe 78 // mouse not here yet
a290fa5a 79 m_underMouse = false;
a8f4cabe
JS
80 }
81
82 wxToolBarTool(wxToolBar *tbar, wxControl *control)
83 : wxToolBarToolBase(tbar, control)
84 {
85 // no position yet
86 m_x =
a290fa5a 87 m_y = wxDefaultCoord;
a8f4cabe
JS
88 m_width =
89 m_height = 0;
5a73d082
VZ
90
91 // not pressed yet
a290fa5a 92 m_isInverted = false;
32b13913 93
34d26f42 94 // mouse not here yet
a290fa5a 95 m_underMouse = false;
3216dbf5
VZ
96 }
97
5a73d082
VZ
98 // is this tool pressed, even temporarily? (this is different from being
99 // permanently toggled which is what IsToggled() returns)
100 bool IsPressed() const
101 { return CanBeToggled() ? IsToggled() != m_isInverted : m_isInverted; }
102
103 // are we temporarily pressed/unpressed?
104 bool IsInverted() const { return m_isInverted; }
105
106 // press the tool temporarily by inverting its toggle state
107 void Invert() { m_isInverted = !m_isInverted; }
32b13913 108
34d26f42 109 // Set underMouse
a290fa5a 110 void SetUnderMouse( bool under = true ) { m_underMouse = under; }
34d26f42 111 bool IsUnderMouse() { return m_underMouse; }
5a73d082 112
3216dbf5 113public:
a8f4cabe
JS
114 // the tool position (for controls)
115 wxCoord m_x;
116 wxCoord m_y;
117 wxCoord m_width;
118 wxCoord m_height;
5a73d082
VZ
119
120private:
a290fa5a 121 // true if the tool is pressed
5a73d082 122 bool m_isInverted;
32b13913 123
a290fa5a 124 // true if the tool is under the mouse
34d26f42 125 bool m_underMouse;
3216dbf5
VZ
126};
127
128// ============================================================================
129// wxToolBar implementation
130// ============================================================================
131
412e0d47 132IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl)
3216dbf5
VZ
133
134// ----------------------------------------------------------------------------
135// wxToolBar creation
136// ----------------------------------------------------------------------------
c08a4f00
RR
137
138void wxToolBar::Init()
139{
3216dbf5 140 // no tools yet
a290fa5a 141 m_needsLayout = false;
3216dbf5
VZ
142
143 // unknown widths for the tools and separators
144 m_widthSeparator = INVALID_WIDTH;
145
146 m_maxWidth =
16c9a425
JS
147 m_maxHeight = 0;
148
3216dbf5
VZ
149 wxRenderer *renderer = GetRenderer();
150
151 SetToolBitmapSize(renderer->GetToolBarButtonSize(&m_widthSeparator));
152 SetMargins(renderer->GetToolBarMargin());
c08a4f00
RR
153}
154
3216dbf5
VZ
155bool wxToolBar::Create(wxWindow *parent,
156 wxWindowID id,
157 const wxPoint& pos,
158 const wxSize& size,
159 long style,
160 const wxString& name)
161{
162 if ( !wxToolBarBase::Create(parent, id, pos, size, style,
163 wxDefaultValidator, name) )
164 {
a290fa5a 165 return false;
3216dbf5
VZ
166 }
167
168 CreateInputHandler(wxINP_HANDLER_TOOLBAR);
169
170 SetBestSize(size);
171
a290fa5a 172 return true;
3216dbf5
VZ
173}
174
175wxToolBar::~wxToolBar()
176{
dda4f6c0
JS
177 // Make sure the toolbar is removed from the parent.
178 SetSize(0,0);
3216dbf5
VZ
179}
180
34d26f42
RR
181void wxToolBar::SetMargins(int x, int y)
182{
183 // This required for similar visual effects under
184 // native platforms and wxUniv.
72726d27 185 wxToolBarBase::SetMargins( x + 3, y + 3 );
34d26f42
RR
186}
187
3216dbf5
VZ
188// ----------------------------------------------------------------------------
189// wxToolBar tool-related methods
190// ----------------------------------------------------------------------------
191
c08a4f00
RR
192wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
193{
3216dbf5
VZ
194 // check the "other" direction first: it must be inside the toolbar or we
195 // don't risk finding anything
196 if ( IsVertical() )
197 {
198 if ( x < 0 || x > m_maxWidth )
199 return NULL;
200
201 // we always use x, even for a vertical toolbar, this makes the code
202 // below simpler
203 x = y;
204 }
205 else // horizontal
206 {
207 if ( y < 0 || y > m_maxHeight )
208 return NULL;
209 }
210
ac32ba44 211 for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
3216dbf5
VZ
212 node;
213 node = node->GetNext() )
214 {
215 wxToolBarToolBase *tool = node->GetData();
216 wxRect rectTool = GetToolRect(tool);
217
218 wxCoord startTool, endTool;
219 GetRectLimits(rectTool, &startTool, &endTool);
220
221 if ( x >= startTool && x <= endTool )
222 {
223 // don't return the separators from here, they don't accept any
224 // input anyhow
225 return tool->IsSeparator() ? NULL : tool;
226 }
227 }
228
c08a4f00
RR
229 return NULL;
230}
231
3216dbf5 232void wxToolBar::SetToolShortHelp(int id, const wxString& help)
c08a4f00 233{
3216dbf5
VZ
234 wxToolBarToolBase *tool = FindById(id);
235
236 wxCHECK_RET( tool, _T("SetToolShortHelp: no such tool") );
237
238 tool->SetShortHelp(help);
c08a4f00
RR
239}
240
3216dbf5
VZ
241bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos),
242 wxToolBarToolBase * WXUNUSED(tool))
c08a4f00 243{
3216dbf5 244 // recalculate the toolbar geometry before redrawing it the next time
a290fa5a 245 m_needsLayout = true;
3216dbf5
VZ
246
247 // and ensure that we indeed are going to redraw
248 Refresh();
249
a290fa5a 250 return true;
c08a4f00
RR
251}
252
3216dbf5
VZ
253bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos),
254 wxToolBarToolBase * WXUNUSED(tool))
c08a4f00 255{
3216dbf5 256 // as above
a290fa5a 257 m_needsLayout = true;
3216dbf5
VZ
258
259 Refresh();
260
a290fa5a 261 return true;
c08a4f00
RR
262}
263
264void wxToolBar::DoEnableTool(wxToolBarToolBase *tool, bool enable)
265{
3216dbf5
VZ
266 // created disabled-state bitmap on demand
267 if ( !enable && !tool->GetDisabledBitmap().Ok() )
c229e50d 268 {
d448aec3 269 wxImage image( tool->GetNormalBitmap().ConvertToImage() );
c229e50d 270
3216dbf5 271 // TODO: don't hardcode 180
bb312b54
RR
272 unsigned char bg_red = 180;
273 unsigned char bg_green = 180;
274 unsigned char bg_blue = 180;
3216dbf5 275
bb312b54
RR
276 unsigned char mask_red = image.GetMaskRed();
277 unsigned char mask_green = image.GetMaskGreen();
278 unsigned char mask_blue = image.GetMaskBlue();
3216dbf5 279
bb312b54 280 bool has_mask = image.HasMask();
3216dbf5 281
bb312b54
RR
282 int x,y;
283 for (y = 0; y < image.GetHeight(); y++)
284 {
3216dbf5 285 for (x = 0; x < image.GetWidth(); x++)
bb312b54
RR
286 {
287 unsigned char red = image.GetRed(x,y);
288 unsigned char green = image.GetGreen(x,y);
289 unsigned char blue = image.GetBlue(x,y);
290 if (!has_mask || red != mask_red || green != mask_green || blue != mask_blue)
291 {
32b13913
WS
292 red = (unsigned char)((((wxInt32) red - bg_red) >> 1) + bg_red);
293 green = (unsigned char)((((wxInt32) green - bg_green) >> 1) + bg_green);
294 blue = (unsigned char)((((wxInt32) blue - bg_blue) >> 1) + bg_blue);
3216dbf5 295 image.SetRGB( x, y, red, green, blue );
bb312b54
RR
296 }
297 }
298 }
c229e50d 299
bb312b54
RR
300 for (y = 0; y < image.GetHeight(); y++)
301 {
3216dbf5 302 for (x = y % 2; x < image.GetWidth(); x += 2)
bb312b54
RR
303 {
304 unsigned char red = image.GetRed(x,y);
305 unsigned char green = image.GetGreen(x,y);
306 unsigned char blue = image.GetBlue(x,y);
307 if (!has_mask || red != mask_red || green != mask_green || blue != mask_blue)
308 {
32b13913
WS
309 red = (unsigned char)((((wxInt32) red - bg_red) >> 1) + bg_red);
310 green = (unsigned char)((((wxInt32) green - bg_green) >> 1) + bg_green);
311 blue = (unsigned char)((((wxInt32) blue - bg_blue) >> 1) + bg_blue);
bb312b54
RR
312 image.SetRGB( x, y, red, green, blue );
313 }
314 }
315 }
316
d448aec3 317 tool->SetDisabledBitmap(image);
c229e50d 318 }
3216dbf5
VZ
319
320 RefreshTool(tool);
c08a4f00
RR
321}
322
3216dbf5 323void wxToolBar::DoToggleTool(wxToolBarToolBase *tool, bool WXUNUSED(toggle))
c08a4f00 324{
3216dbf5
VZ
325 // note that if we're called the tool did change state (the base class
326 // checks for it), so it's not necessary to check for this again here
327 RefreshTool(tool);
c08a4f00
RR
328}
329
3216dbf5 330void wxToolBar::DoSetToggle(wxToolBarToolBase *tool, bool WXUNUSED(toggle))
c08a4f00 331{
3216dbf5 332 RefreshTool(tool);
c08a4f00
RR
333}
334
335wxToolBarToolBase *wxToolBar::CreateTool(int id,
d448aec3
VZ
336 const wxString& label,
337 const wxBitmap& bmpNormal,
338 const wxBitmap& bmpDisabled,
339 wxItemKind kind,
3216dbf5 340 wxObject *clientData,
d448aec3
VZ
341 const wxString& shortHelp,
342 const wxString& longHelp)
c08a4f00 343{
d448aec3
VZ
344 return new wxToolBarTool(this, id, label, bmpNormal, bmpDisabled, kind,
345 clientData, shortHelp, longHelp);
c08a4f00 346}
3216dbf5 347
c08a4f00
RR
348wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
349{
a8f4cabe 350 return new wxToolBarTool(this, control);
c08a4f00
RR
351}
352
3216dbf5
VZ
353// ----------------------------------------------------------------------------
354// wxToolBar geometry
355// ----------------------------------------------------------------------------
c08a4f00 356
3216dbf5 357wxRect wxToolBar::GetToolRect(wxToolBarToolBase *toolBase) const
c08a4f00 358{
3216dbf5
VZ
359 const wxToolBarTool *tool = (wxToolBarTool *)toolBase;
360
361 wxRect rect;
362
363 wxCHECK_MSG( tool, rect, _T("GetToolRect: NULL tool") );
364
365 // ensure that we always have the valid tool position
366 if ( m_needsLayout )
bb312b54 367 {
3216dbf5 368 wxConstCast(this, wxToolBar)->DoLayout();
bb312b54 369 }
3216dbf5
VZ
370
371 rect.x = tool->m_x - m_xMargin;
372 rect.y = tool->m_y - m_yMargin;
373
374 if ( IsVertical() )
c08a4f00 375 {
a290fa5a 376 if (tool->IsButton())
a8f4cabe 377 {
370efbe7
WS
378 if(!HasFlag(wxTB_TEXT))
379 {
380 rect.width = m_defaultWidth;
381 rect.height = m_defaultHeight;
382 }
383 else
384 {
385 rect.width = m_defaultWidth +
386 GetFont().GetPointSize() * tool->GetLabel().length();
387 rect.height = m_defaultHeight;
388 }
a8f4cabe
JS
389 }
390 else if (tool->IsSeparator())
391 {
392 rect.width = m_defaultWidth;
393 rect.height = m_widthSeparator;
394 }
395 else // control
396 {
397 rect.width = tool->m_width;
398 rect.height = tool->m_height;
399 }
c08a4f00 400 }
3216dbf5 401 else // horizontal
c08a4f00 402 {
a8f4cabe
JS
403 if (tool->IsButton())
404 {
370efbe7
WS
405 if(!HasFlag(wxTB_TEXT))
406 {
407 rect.width = m_defaultWidth;
408 rect.height = m_defaultHeight;
409 }
410 else
411 {
412 rect.width = m_defaultWidth +
413 GetFont().GetPointSize() * tool->GetLabel().length();
414 rect.height = m_defaultHeight;
415 }
a8f4cabe
JS
416 }
417 else if (tool->IsSeparator())
418 {
419 rect.width = m_widthSeparator;
420 rect.height = m_defaultHeight;
421 }
422 else // control
423 {
424 rect.width = tool->m_width;
425 rect.height = tool->m_height;
426 }
c08a4f00 427 }
3216dbf5
VZ
428
429 rect.width += 2*m_xMargin;
430 rect.height += 2*m_yMargin;
431
432 return rect;
c08a4f00
RR
433}
434
3216dbf5 435bool wxToolBar::Realize()
c08a4f00 436{
3216dbf5 437 if ( !wxToolBarBase::Realize() )
a290fa5a 438 return false;
3216dbf5 439
a290fa5a 440 m_needsLayout = true;
3216dbf5
VZ
441 DoLayout();
442
443 SetBestSize(wxDefaultSize);
444
a290fa5a 445 return true;
3216dbf5
VZ
446}
447
370efbe7
WS
448void wxToolBar::SetWindowStyleFlag( long style )
449{
450 wxToolBarBase::SetWindowStyleFlag(style);
451
452 m_needsLayout = true;
453
454 Refresh();
455}
456
3216dbf5
VZ
457void wxToolBar::DoLayout()
458{
459 wxASSERT_MSG( m_needsLayout, _T("why are we called?") );
460
a290fa5a 461 m_needsLayout = false;
3216dbf5
VZ
462
463 wxCoord x = m_xMargin,
464 y = m_yMargin;
465
370efbe7
WS
466 wxCoord widthTool = 0, maxWidthTool = 0;
467 wxCoord heightTool = 0, maxHeightTool = 0;
32b13913
WS
468 wxCoord margin = IsVertical() ? m_xMargin : m_yMargin;
469 wxCoord *pCur = IsVertical() ? &y : &x;
3216dbf5
VZ
470
471 // calculate the positions of all elements
ac32ba44 472 for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
c08a4f00
RR
473 node;
474 node = node->GetNext() )
475 {
3216dbf5
VZ
476 wxToolBarTool *tool = (wxToolBarTool *) node->GetData();
477
478 tool->m_x = x;
479 tool->m_y = y;
480
72726d27 481 // TODO ugly number fiddling
a8f4cabe
JS
482 if (tool->IsButton())
483 {
370efbe7
WS
484 if (IsVertical())
485 {
486 widthTool = m_defaultHeight;
487 heightTool = m_defaultWidth;
488 if(HasFlag(wxTB_TEXT))
489 heightTool += GetFont().GetPointSize() * tool->GetLabel().length();
490 }
491 else
492 {
493 widthTool = m_defaultWidth;
494 if(HasFlag(wxTB_TEXT))
495 widthTool += GetFont().GetPointSize() * tool->GetLabel().length();
496
497 heightTool = m_defaultHeight;
498 }
499
500 if(widthTool > maxWidthTool) // Record max width of tool
501 {
502 maxWidthTool = widthTool;
503 }
504
505 if(heightTool > maxHeightTool) // Record max width of tool
506 {
507 maxHeightTool = heightTool;
508 }
509
a8f4cabe
JS
510 *pCur += widthTool;
511 }
512 else if (tool->IsSeparator())
513 {
514 *pCur += m_widthSeparator;
515 }
516 else if (!IsVertical()) // horizontal control
517 {
518 wxControl *control = tool->GetControl();
519 wxSize size = control->GetSize();
520 tool->m_y += (m_defaultHeight - size.y)/2;
521 tool->m_width = size.x;
522 tool->m_height = size.y;
523
524 *pCur += tool->m_width;
525 }
526 *pCur += margin;
c08a4f00 527 }
3216dbf5
VZ
528
529 // calculate the total toolbar size
370efbe7
WS
530 wxCoord xMin, yMin;
531
532 if(!HasFlag(wxTB_TEXT))
533 {
534 xMin = m_defaultWidth + 2*m_xMargin;
535 yMin = m_defaultHeight + 2*m_yMargin;
536 }
537 else
538 {
539 if (IsVertical())
540 {
541 xMin = heightTool + 2*m_xMargin;
542 yMin = widthTool + 2*m_xMargin;
543 }
544 else
545 {
546 xMin = maxWidthTool + 2*m_xMargin;
547 yMin = heightTool + 2*m_xMargin;
548 }
549 }
3216dbf5
VZ
550
551 m_maxWidth = x < xMin ? xMin : x;
552 m_maxHeight = y < yMin ? yMin : y;
c08a4f00
RR
553}
554
3216dbf5 555wxSize wxToolBar::DoGetBestClientSize() const
c08a4f00 556{
3216dbf5
VZ
557 return wxSize(m_maxWidth, m_maxHeight);
558}
559
dda4f6c0
JS
560void wxToolBar::DoSetSize(int x, int y, int width, int height, int sizeFlags)
561{
562 int old_width, old_height;
563 GetSize(&old_width, &old_height);
564
565 wxToolBarBase::DoSetSize(x, y, width, height, sizeFlags);
32b13913 566
dda4f6c0 567 // Correct width and height if needed.
a290fa5a 568 if ( width == wxDefaultCoord || height == wxDefaultCoord )
dda4f6c0
JS
569 {
570 int tmp_width, tmp_height;
571 GetSize(&tmp_width, &tmp_height);
572
a290fa5a 573 if ( width == wxDefaultCoord )
dda4f6c0 574 width = tmp_width;
a290fa5a 575 if ( height == wxDefaultCoord )
dda4f6c0
JS
576 height = tmp_height;
577 }
32b13913 578
dda4f6c0
JS
579 // We must refresh the frame size when the toolbar changes size
580 // otherwise the toolbar can be shown incorrectly
581 if ( old_width != width || old_height != height )
582 {
32b13913 583 // But before we send the size event check it
dda4f6c0
JS
584 // we have a frame that is not being deleted.
585 wxFrame *frame = wxDynamicCast(GetParent(), wxFrame);
586 if ( frame && !frame->IsBeingDeleted() )
587 {
588 frame->SendSizeEvent();
589 }
590 }
591}
592
3216dbf5
VZ
593// ----------------------------------------------------------------------------
594// wxToolBar drawing
595// ----------------------------------------------------------------------------
c08a4f00 596
3216dbf5
VZ
597void wxToolBar::RefreshTool(wxToolBarToolBase *tool)
598{
599 RefreshRect(GetToolRect(tool));
600}
601
602void wxToolBar::GetRectLimits(const wxRect& rect,
603 wxCoord *start,
604 wxCoord *end) const
605{
606 wxCHECK_RET( start && end, _T("NULL pointer in GetRectLimits") );
607
608 if ( IsVertical() )
16c9a425 609 {
3216dbf5
VZ
610 *start = rect.GetTop();
611 *end = rect.GetBottom();
16c9a425 612 }
3216dbf5 613 else // horizontal
16c9a425 614 {
3216dbf5
VZ
615 *start = rect.GetLeft();
616 *end = rect.GetRight();
16c9a425 617 }
3216dbf5 618}
c08a4f00 619
3216dbf5
VZ
620void wxToolBar::DoDraw(wxControlRenderer *renderer)
621{
622 // prepare the variables used below
623 wxDC& dc = renderer->GetDC();
624 wxRenderer *rend = renderer->GetRenderer();
370efbe7 625 dc.SetFont(GetFont());
3216dbf5
VZ
626
627 // draw the border separating us from the menubar (if there is no menubar
628 // we probably shouldn't draw it?)
629 if ( !IsVertical() )
630 {
631 rend->DrawHorizontalLine(dc, 0, 0, GetClientSize().x);
632 }
633
634 // get the update rect and its limits depending on the orientation
635 wxRect rectUpdate = GetUpdateClientRect();
636 wxCoord start, end;
637 GetRectLimits(rectUpdate, &start, &end);
638
639 // and redraw all the tools intersecting it
ac32ba44 640 for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
c08a4f00
RR
641 node;
642 node = node->GetNext() )
643 {
34d26f42 644 wxToolBarTool *tool = (wxToolBarTool*) node->GetData();
3216dbf5
VZ
645 wxRect rectTool = GetToolRect(tool);
646 wxCoord startTool, endTool;
647 GetRectLimits(rectTool, &startTool, &endTool);
648
649 if ( endTool < start )
c08a4f00 650 {
3216dbf5
VZ
651 // we're still to the left of the area to redraw
652 continue;
16c9a425 653 }
3216dbf5
VZ
654
655 if ( startTool > end )
16c9a425 656 {
3216dbf5
VZ
657 // we're beyond the area to redraw, nothing left to do
658 break;
659 }
32b13913 660
72726d27
RR
661 if (tool->IsSeparator() && !HasFlag(wxTB_FLAT))
662 {
d6922577 663 // Draw separators only in flat mode
72726d27
RR
664 continue;
665 }
32b13913 666
3216dbf5
VZ
667 // deal with the flags
668 int flags = 0;
669
670 if ( tool->IsEnabled() )
671 {
34d26f42
RR
672 // The toolbars without wxTB_FLAT don't react to the mouse hovering
673 if ( !HasFlag(wxTB_FLAT) || tool->IsUnderMouse() )
3216dbf5
VZ
674 flags |= wxCONTROL_CURRENT;
675 }
676 else // disabled tool
677 {
678 flags |= wxCONTROL_DISABLED;
c08a4f00 679 }
3216dbf5 680
34d26f42
RR
681 //if ( tool == m_toolCaptured )
682 // flags |= wxCONTROL_FOCUSED;
5a73d082 683
34d26f42
RR
684 if ( tool->IsPressed() )
685 flags = wxCONTROL_PRESSED;
3216dbf5
VZ
686
687 wxString label;
688 wxBitmap bitmap;
689 if ( !tool->IsSeparator() )
690 {
370efbe7 691 label = tool->GetLabel();
3216dbf5
VZ
692 bitmap = tool->GetBitmap();
693 }
694 //else: leave both the label and the bitmap invalid to draw a separator
695
a8f4cabe
JS
696 if ( !tool->IsControl() )
697 {
370efbe7
WS
698 int tbStyle = 0;
699 if(HasFlag(wxTB_TEXT))
700 {
701 tbStyle |= wxTB_TEXT;
702 }
703
704 if(HasFlag(wxTB_VERTICAL))
705 {
706 tbStyle |= wxTB_VERTICAL;
707 }
708 else
709 {
710 tbStyle |= wxTB_HORIZONTAL;
711 }
712 rend->DrawToolBarButton(dc, label, bitmap, rectTool, flags, tool->GetStyle(), tbStyle);
a8f4cabe
JS
713 }
714 else // control
715 {
716 wxControl *control = tool->GetControl();
717 control->Move(tool->m_x, tool->m_y);
718 }
16c9a425 719 }
3216dbf5 720}
16c9a425 721
3216dbf5
VZ
722// ----------------------------------------------------------------------------
723// wxToolBar actions
724// ----------------------------------------------------------------------------
725
34d26f42
RR
726bool wxToolBar::PerformAction(const wxControlAction& action,
727 long numArg,
728 const wxString& strArg)
bb312b54 729{
34d26f42 730 wxToolBarTool *tool = (wxToolBarTool*) FindById(numArg);
23219626
JS
731 if (!tool)
732 return false;
32b13913 733
34d26f42
RR
734 if ( action == wxACTION_TOOLBAR_TOGGLE )
735 {
736 PerformAction( wxACTION_BUTTON_RELEASE, numArg );
bb312b54 737
34d26f42 738 PerformAction( wxACTION_BUTTON_CLICK, numArg );
e4db172a
WS
739
740 // Write by Danny Raynor to change state again.
c4709ea5 741 // Check button still pressed or not
cc92fd84
WS
742 if ( tool->CanBeToggled() && tool->IsToggled() )
743 {
744 tool->Toggle(false);
745 }
746
c4709ea5 747 if( tool->IsInverted() )
e4db172a
WS
748 {
749 PerformAction( wxACTION_TOOLBAR_RELEASE, numArg );
c4709ea5 750 }
e4db172a 751
c4709ea5
JS
752 // Set mouse leave toolbar button range (If still in the range,
753 // toolbar button would get focus again
754 PerformAction( wxACTION_TOOLBAR_LEAVE, numArg );
34d26f42
RR
755 }
756 else if ( action == wxACTION_TOOLBAR_PRESS )
757 {
758 wxLogTrace(_T("toolbar"), _T("Button '%s' pressed."), tool->GetShortHelp().c_str());
32b13913 759
34d26f42 760 tool->Invert();
3216dbf5 761
34d26f42
RR
762 RefreshTool( tool );
763 }
764 else if ( action == wxACTION_TOOLBAR_RELEASE )
5a73d082 765 {
34d26f42 766 wxLogTrace(_T("toolbar"), _T("Button '%s' released."), tool->GetShortHelp().c_str());
5a73d082 767
34d26f42 768 wxASSERT_MSG( tool->IsInverted(), _T("release unpressed button?") );
32b13913 769
34d26f42 770 tool->Invert();
5a73d082 771
34d26f42 772 RefreshTool( tool );
5a73d082 773 }
34d26f42 774 else if ( action == wxACTION_TOOLBAR_CLICK )
5a73d082 775 {
34d26f42
RR
776 bool isToggled;
777 if ( tool->CanBeToggled() )
778 {
779 tool->Toggle();
5a73d082 780
34d26f42 781 RefreshTool( tool );
bb312b54 782
34d26f42
RR
783 isToggled = tool->IsToggled();
784 }
785 else // simple non-checkable tool
786 {
a290fa5a 787 isToggled = false;
34d26f42
RR
788 }
789 OnLeftClick( tool->GetId(), isToggled );
790 }
3216dbf5 791 else if ( action == wxACTION_TOOLBAR_ENTER )
c08a4f00 792 {
a290fa5a 793 wxCHECK_MSG( tool, false, _T("no tool to enter?") );
32b13913 794
34d26f42 795 if ( HasFlag(wxTB_FLAT) && tool->IsEnabled() )
c08a4f00 796 {
a290fa5a 797 tool->SetUnderMouse( true );
32b13913 798
34d26f42
RR
799 if ( !tool->IsToggled() )
800 RefreshTool( tool );
c08a4f00
RR
801 }
802 }
3216dbf5 803 else if ( action == wxACTION_TOOLBAR_LEAVE )
bb312b54 804 {
a290fa5a 805 wxCHECK_MSG( tool, false, _T("no tool to leave?") );
32b13913 806
34d26f42 807 if ( HasFlag(wxTB_FLAT) && tool->IsEnabled() )
bb312b54 808 {
a290fa5a 809 tool->SetUnderMouse( false );
32b13913 810
34d26f42
RR
811 if ( !tool->IsToggled() )
812 RefreshTool( tool );
bb312b54 813 }
c08a4f00 814 }
3216dbf5
VZ
815 else
816 return wxControl::PerformAction(action, numArg, strArg);
817
a290fa5a 818 return true;
3216dbf5
VZ
819}
820
821// ============================================================================
822// wxStdToolbarInputHandler implementation
823// ============================================================================
824
825wxStdToolbarInputHandler::wxStdToolbarInputHandler(wxInputHandler *handler)
34d26f42 826 : wxStdInputHandler(handler)
3216dbf5 827{
34d26f42
RR
828 m_winCapture = NULL;
829 m_toolCapture = NULL;
830 m_toolLast = NULL;
3216dbf5
VZ
831}
832
833bool wxStdToolbarInputHandler::HandleKey(wxInputConsumer *consumer,
834 const wxKeyEvent& event,
835 bool pressed)
836{
837 // TODO: when we have a current button we should allow the arrow
838 // keys to move it
839 return wxStdInputHandler::HandleKey(consumer, event, pressed);
840}
841
4e89ceb1
VZ
842bool wxStdToolbarInputHandler::HandleMouse(wxInputConsumer *consumer,
843 const wxMouseEvent& event)
844{
4e89ceb1
VZ
845 wxToolBar *tbar = wxStaticCast(consumer->GetInputWindow(), wxToolBar);
846 wxToolBarToolBase *tool = tbar->FindToolForPosition(event.GetX(), event.GetY());
847
34d26f42
RR
848 if ( event.Button(1) )
849 {
34d26f42
RR
850
851 if ( event.LeftDown() || event.LeftDClick() )
852 {
72726d27 853 if ( !tool || !tool->IsEnabled() )
a290fa5a 854 return true;
32b13913 855
34d26f42
RR
856 m_winCapture = tbar;
857 m_winCapture->CaptureMouse();
32b13913 858
34d26f42
RR
859 m_toolCapture = tool;
860
861 consumer->PerformAction( wxACTION_BUTTON_PRESS, tool->GetId() );
862
a290fa5a 863 return true;
34d26f42
RR
864 }
865 else if ( event.LeftUp() )
866 {
867 if ( m_winCapture )
868 {
869 m_winCapture->ReleaseMouse();
870 m_winCapture = NULL;
871 }
872
2b5f62a0
VZ
873 if (m_toolCapture)
874 {
875 if ( tool == m_toolCapture )
876 consumer->PerformAction( wxACTION_BUTTON_TOGGLE, m_toolCapture->GetId() );
877 else
878 consumer->PerformAction( wxACTION_TOOLBAR_LEAVE, m_toolCapture->GetId() );
879 }
32b13913 880
34d26f42 881 m_toolCapture = NULL;
32b13913 882
a290fa5a 883 return true;
34d26f42
RR
884 }
885 //else: don't do anything special about the double click
886 }
887
888 return wxStdInputHandler::HandleMouse(consumer, event);
4e89ceb1
VZ
889}
890
3216dbf5
VZ
891bool wxStdToolbarInputHandler::HandleMouseMove(wxInputConsumer *consumer,
892 const wxMouseEvent& event)
893{
34d26f42 894 if ( !wxStdInputHandler::HandleMouseMove(consumer, event) )
c08a4f00 895 {
34d26f42 896 wxToolBar *tbar = wxStaticCast(consumer->GetInputWindow(), wxToolBar);
32b13913 897
34d26f42 898 wxToolBarTool *tool;
3216dbf5 899 if ( event.Leaving() )
c08a4f00 900 {
34d26f42
RR
901 // We cannot possibly be over a tool when
902 // leaving the toolbar
3216dbf5 903 tool = NULL;
c08a4f00 904 }
3216dbf5 905 else
c08a4f00 906 {
34d26f42 907 tool = (wxToolBarTool*) tbar->FindToolForPosition( event.GetX(), event.GetY() );
c08a4f00 908 }
32b13913 909
72726d27 910 if (m_toolCapture)
34d26f42 911 {
72726d27
RR
912 // During capture we only care of the captured tool
913 if (tool && (tool != m_toolCapture))
914 tool = NULL;
32b13913 915
72726d27 916 if (tool == m_toolLast)
a290fa5a 917 return true;
32b13913 918
72726d27
RR
919 if (tool)
920 consumer->PerformAction( wxACTION_BUTTON_PRESS, m_toolCapture->GetId() );
921 else
922 consumer->PerformAction( wxACTION_BUTTON_RELEASE, m_toolCapture->GetId() );
32b13913 923
72726d27 924 m_toolLast = tool;
34d26f42 925 }
72726d27 926 else
34d26f42 927 {
72726d27 928 if (tool == m_toolLast)
a290fa5a 929 return true;
32b13913 930
72726d27
RR
931 if (m_toolLast)
932 {
933 // Leave old tool if any
934 consumer->PerformAction( wxACTION_TOOLBAR_LEAVE, m_toolLast->GetId() );
935 }
32b13913 936
72726d27
RR
937 if (tool)
938 {
939 // Enter new tool if any
940 consumer->PerformAction( wxACTION_TOOLBAR_ENTER, tool->GetId() );
941 }
32b13913 942
34d26f42 943 m_toolLast = tool;
34d26f42 944 }
32b13913 945
a290fa5a 946 return true;
bb312b54 947 }
3216dbf5 948
a290fa5a 949 return false;
3216dbf5
VZ
950}
951
952bool wxStdToolbarInputHandler::HandleFocus(wxInputConsumer *consumer,
61fef19b 953 const wxFocusEvent& WXUNUSED(event))
3216dbf5 954{
32b13913 955 if ( m_toolCapture )
34d26f42
RR
956 {
957 // We shouldn't be left with a highlighted button
958 consumer->PerformAction( wxACTION_TOOLBAR_LEAVE, m_toolCapture->GetId() );
959 }
3216dbf5 960
a290fa5a 961 return true;
3216dbf5
VZ
962}
963
964bool wxStdToolbarInputHandler::HandleActivation(wxInputConsumer *consumer,
965 bool activated)
966{
34d26f42
RR
967 if (m_toolCapture && !activated)
968 {
969 // We shouldn't be left with a highlighted button
970 consumer->PerformAction( wxACTION_TOOLBAR_LEAVE, m_toolCapture->GetId() );
971 }
3216dbf5 972
a290fa5a 973 return true;
c08a4f00
RR
974}
975
6a317e61 976#endif // wxUSE_TOOLBAR