]> git.saurik.com Git - wxWidgets.git/blob - src/univ/toolbar.cpp
call SetHorizontalExtent() from SetString(); also simplified/cleaned up the former...
[wxWidgets.git] / src / univ / toolbar.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/univ/toolbar.cpp
3 // Purpose: implementation of wxToolBar for wxUniversal
4 // Author: Robert Roebling, Vadim Zeitlin (universalization)
5 // Modified by:
6 // Created: 20.02.02
7 // Id: $Id$
8 // Copyright: (c) 2001 Robert Roebling,
9 // (c) 2002 SciTech Software, Inc. (www.scitechsoft.com)
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12
13 // ============================================================================
14 // declarations
15 // ============================================================================
16
17 // ----------------------------------------------------------------------------
18 // headers
19 // ----------------------------------------------------------------------------
20
21 // For compilers that support precompilation, includes "wx.h".
22 #include "wx/wxprec.h"
23
24 #ifdef __BORLANDC__
25 #pragma hdrstop
26 #endif
27
28 #if wxUSE_TOOLBAR
29
30 #include "wx/toolbar.h"
31
32 #ifndef WX_PRECOMP
33 #include "wx/utils.h"
34 #include "wx/app.h"
35 #include "wx/log.h"
36 #include "wx/frame.h"
37 #include "wx/dc.h"
38 #include "wx/image.h"
39 #endif
40
41 #include "wx/univ/renderer.h"
42
43 // ----------------------------------------------------------------------------
44 // constants
45 // ----------------------------------------------------------------------------
46
47 // value meaning that m_widthSeparator is not initialized
48 static const wxCoord INVALID_WIDTH = wxDefaultCoord;
49
50 // ----------------------------------------------------------------------------
51 // wxToolBarTool: our implementation of wxToolBarToolBase
52 // ----------------------------------------------------------------------------
53
54 class WXDLLEXPORT wxToolBarTool : public wxToolBarToolBase
55 {
56 public:
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)
68 {
69 // no position yet
70 m_x =
71 m_y = wxDefaultCoord;
72 m_width =
73 m_height = 0;
74
75 // not pressed yet
76 m_isInverted = false;
77
78 // mouse not here yet
79 m_underMouse = false;
80 }
81
82 wxToolBarTool(wxToolBar *tbar, wxControl *control)
83 : wxToolBarToolBase(tbar, control)
84 {
85 // no position yet
86 m_x =
87 m_y = wxDefaultCoord;
88 m_width =
89 m_height = 0;
90
91 // not pressed yet
92 m_isInverted = false;
93
94 // mouse not here yet
95 m_underMouse = false;
96 }
97
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; }
108
109 // Set underMouse
110 void SetUnderMouse( bool under = true ) { m_underMouse = under; }
111 bool IsUnderMouse() { return m_underMouse; }
112
113 public:
114 // the tool position (for controls)
115 wxCoord m_x;
116 wxCoord m_y;
117 wxCoord m_width;
118 wxCoord m_height;
119
120 private:
121 // true if the tool is pressed
122 bool m_isInverted;
123
124 // true if the tool is under the mouse
125 bool m_underMouse;
126 };
127
128 // ============================================================================
129 // wxToolBar implementation
130 // ============================================================================
131
132 IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl)
133
134 // ----------------------------------------------------------------------------
135 // wxToolBar creation
136 // ----------------------------------------------------------------------------
137
138 void wxToolBar::Init()
139 {
140 // no tools yet
141 m_needsLayout = false;
142
143 // unknown widths for the tools and separators
144 m_widthSeparator = INVALID_WIDTH;
145
146 m_maxWidth =
147 m_maxHeight = 0;
148
149 wxRenderer *renderer = GetRenderer();
150
151 SetToolBitmapSize(renderer->GetToolBarButtonSize(&m_widthSeparator));
152 SetMargins(renderer->GetToolBarMargin());
153 }
154
155 bool 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 {
165 return false;
166 }
167
168 CreateInputHandler(wxINP_HANDLER_TOOLBAR);
169
170 SetBestSize(size);
171
172 return true;
173 }
174
175 wxToolBar::~wxToolBar()
176 {
177 // Make sure the toolbar is removed from the parent.
178 SetSize(0,0);
179 }
180
181 void wxToolBar::SetMargins(int x, int y)
182 {
183 // This required for similar visual effects under
184 // native platforms and wxUniv.
185 wxToolBarBase::SetMargins( x + 3, y + 3 );
186 }
187
188 // ----------------------------------------------------------------------------
189 // wxToolBar tool-related methods
190 // ----------------------------------------------------------------------------
191
192 wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
193 {
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
211 for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
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
229 return NULL;
230 }
231
232 void wxToolBar::SetToolShortHelp(int id, const wxString& help)
233 {
234 wxToolBarToolBase *tool = FindById(id);
235
236 wxCHECK_RET( tool, _T("SetToolShortHelp: no such tool") );
237
238 tool->SetShortHelp(help);
239 }
240
241 bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos),
242 wxToolBarToolBase * WXUNUSED(tool))
243 {
244 // recalculate the toolbar geometry before redrawing it the next time
245 m_needsLayout = true;
246
247 // and ensure that we indeed are going to redraw
248 Refresh();
249
250 return true;
251 }
252
253 bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos),
254 wxToolBarToolBase * WXUNUSED(tool))
255 {
256 // as above
257 m_needsLayout = true;
258
259 Refresh();
260
261 return true;
262 }
263
264 void wxToolBar::DoEnableTool(wxToolBarToolBase *tool, bool enable)
265 {
266 // created disabled-state bitmap on demand
267 if ( !enable && !tool->GetDisabledBitmap().Ok() )
268 {
269 wxImage image( tool->GetNormalBitmap().ConvertToImage() );
270
271 // TODO: don't hardcode 180
272 unsigned char bg_red = 180;
273 unsigned char bg_green = 180;
274 unsigned char bg_blue = 180;
275
276 unsigned char mask_red = image.GetMaskRed();
277 unsigned char mask_green = image.GetMaskGreen();
278 unsigned char mask_blue = image.GetMaskBlue();
279
280 bool has_mask = image.HasMask();
281
282 int x,y;
283 for (y = 0; y < image.GetHeight(); y++)
284 {
285 for (x = 0; x < image.GetWidth(); x++)
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 {
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);
295 image.SetRGB( x, y, red, green, blue );
296 }
297 }
298 }
299
300 for (y = 0; y < image.GetHeight(); y++)
301 {
302 for (x = y % 2; x < image.GetWidth(); x += 2)
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 {
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);
312 image.SetRGB( x, y, red, green, blue );
313 }
314 }
315 }
316
317 tool->SetDisabledBitmap(image);
318 }
319
320 RefreshTool(tool);
321 }
322
323 void wxToolBar::DoToggleTool(wxToolBarToolBase *tool, bool WXUNUSED(toggle))
324 {
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);
328 }
329
330 void wxToolBar::DoSetToggle(wxToolBarToolBase *tool, bool WXUNUSED(toggle))
331 {
332 RefreshTool(tool);
333 }
334
335 wxToolBarToolBase *wxToolBar::CreateTool(int id,
336 const wxString& label,
337 const wxBitmap& bmpNormal,
338 const wxBitmap& bmpDisabled,
339 wxItemKind kind,
340 wxObject *clientData,
341 const wxString& shortHelp,
342 const wxString& longHelp)
343 {
344 return new wxToolBarTool(this, id, label, bmpNormal, bmpDisabled, kind,
345 clientData, shortHelp, longHelp);
346 }
347
348 wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
349 {
350 return new wxToolBarTool(this, control);
351 }
352
353 // ----------------------------------------------------------------------------
354 // wxToolBar geometry
355 // ----------------------------------------------------------------------------
356
357 wxRect wxToolBar::GetToolRect(wxToolBarToolBase *toolBase) const
358 {
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 )
367 {
368 wxConstCast(this, wxToolBar)->DoLayout();
369 }
370
371 rect.x = tool->m_x - m_xMargin;
372 rect.y = tool->m_y - m_yMargin;
373
374 if ( IsVertical() )
375 {
376 if (tool->IsButton())
377 {
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 }
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 }
400 }
401 else // horizontal
402 {
403 if (tool->IsButton())
404 {
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 }
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 }
427 }
428
429 rect.width += 2*m_xMargin;
430 rect.height += 2*m_yMargin;
431
432 return rect;
433 }
434
435 bool wxToolBar::Realize()
436 {
437 if ( !wxToolBarBase::Realize() )
438 return false;
439
440 m_needsLayout = true;
441 DoLayout();
442
443 SetBestSize(wxDefaultSize);
444
445 return true;
446 }
447
448 void wxToolBar::SetWindowStyleFlag( long style )
449 {
450 wxToolBarBase::SetWindowStyleFlag(style);
451
452 m_needsLayout = true;
453
454 Refresh();
455 }
456
457 void wxToolBar::DoLayout()
458 {
459 wxASSERT_MSG( m_needsLayout, _T("why are we called?") );
460
461 m_needsLayout = false;
462
463 wxCoord x = m_xMargin,
464 y = m_yMargin;
465
466 wxCoord widthTool = 0, maxWidthTool = 0;
467 wxCoord heightTool = 0, maxHeightTool = 0;
468 wxCoord margin = IsVertical() ? m_xMargin : m_yMargin;
469 wxCoord *pCur = IsVertical() ? &y : &x;
470
471 // calculate the positions of all elements
472 for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
473 node;
474 node = node->GetNext() )
475 {
476 wxToolBarTool *tool = (wxToolBarTool *) node->GetData();
477
478 tool->m_x = x;
479 tool->m_y = y;
480
481 // TODO ugly number fiddling
482 if (tool->IsButton())
483 {
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
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;
527 }
528
529 // calculate the total toolbar size
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 }
550
551 m_maxWidth = x < xMin ? xMin : x;
552 m_maxHeight = y < yMin ? yMin : y;
553 }
554
555 wxSize wxToolBar::DoGetBestClientSize() const
556 {
557 return wxSize(m_maxWidth, m_maxHeight);
558 }
559
560 void 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);
566
567 // Correct width and height if needed.
568 if ( width == wxDefaultCoord || height == wxDefaultCoord )
569 {
570 int tmp_width, tmp_height;
571 GetSize(&tmp_width, &tmp_height);
572
573 if ( width == wxDefaultCoord )
574 width = tmp_width;
575 if ( height == wxDefaultCoord )
576 height = tmp_height;
577 }
578
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 {
583 // But before we send the size event check it
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
593 // ----------------------------------------------------------------------------
594 // wxToolBar drawing
595 // ----------------------------------------------------------------------------
596
597 void wxToolBar::RefreshTool(wxToolBarToolBase *tool)
598 {
599 RefreshRect(GetToolRect(tool));
600 }
601
602 void 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() )
609 {
610 *start = rect.GetTop();
611 *end = rect.GetBottom();
612 }
613 else // horizontal
614 {
615 *start = rect.GetLeft();
616 *end = rect.GetRight();
617 }
618 }
619
620 void wxToolBar::DoDraw(wxControlRenderer *renderer)
621 {
622 // prepare the variables used below
623 wxDC& dc = renderer->GetDC();
624 wxRenderer *rend = renderer->GetRenderer();
625 dc.SetFont(GetFont());
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
640 for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
641 node;
642 node = node->GetNext() )
643 {
644 wxToolBarTool *tool = (wxToolBarTool*) node->GetData();
645 wxRect rectTool = GetToolRect(tool);
646 wxCoord startTool, endTool;
647 GetRectLimits(rectTool, &startTool, &endTool);
648
649 if ( endTool < start )
650 {
651 // we're still to the left of the area to redraw
652 continue;
653 }
654
655 if ( startTool > end )
656 {
657 // we're beyond the area to redraw, nothing left to do
658 break;
659 }
660
661 if (tool->IsSeparator() && !HasFlag(wxTB_FLAT))
662 {
663 // Draw separators only in flat mode
664 continue;
665 }
666
667 // deal with the flags
668 int flags = 0;
669
670 if ( tool->IsEnabled() )
671 {
672 // The toolbars without wxTB_FLAT don't react to the mouse hovering
673 if ( !HasFlag(wxTB_FLAT) || tool->IsUnderMouse() )
674 flags |= wxCONTROL_CURRENT;
675 }
676 else // disabled tool
677 {
678 flags |= wxCONTROL_DISABLED;
679 }
680
681 //if ( tool == m_toolCaptured )
682 // flags |= wxCONTROL_FOCUSED;
683
684 if ( tool->IsPressed() )
685 flags = wxCONTROL_PRESSED;
686
687 wxString label;
688 wxBitmap bitmap;
689 if ( !tool->IsSeparator() )
690 {
691 label = tool->GetLabel();
692 bitmap = tool->GetBitmap();
693 }
694 //else: leave both the label and the bitmap invalid to draw a separator
695
696 if ( !tool->IsControl() )
697 {
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);
713 }
714 else // control
715 {
716 wxControl *control = tool->GetControl();
717 control->Move(tool->m_x, tool->m_y);
718 }
719 }
720 }
721
722 // ----------------------------------------------------------------------------
723 // wxToolBar actions
724 // ----------------------------------------------------------------------------
725
726 bool wxToolBar::PerformAction(const wxControlAction& action,
727 long numArg,
728 const wxString& strArg)
729 {
730 wxToolBarTool *tool = (wxToolBarTool*) FindById(numArg);
731 if (!tool)
732 return false;
733
734 if ( action == wxACTION_TOOLBAR_TOGGLE )
735 {
736 PerformAction( wxACTION_BUTTON_RELEASE, numArg );
737
738 PerformAction( wxACTION_BUTTON_CLICK, numArg );
739
740 // Write by Danny Raynor to change state again.
741 // Check button still pressed or not
742 if ( tool->CanBeToggled() && tool->IsToggled() )
743 {
744 tool->Toggle(false);
745 }
746
747 if( tool->IsInverted() )
748 {
749 PerformAction( wxACTION_TOOLBAR_RELEASE, numArg );
750 }
751
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 );
755 }
756 else if ( action == wxACTION_TOOLBAR_PRESS )
757 {
758 wxLogTrace(_T("toolbar"), _T("Button '%s' pressed."), tool->GetShortHelp().c_str());
759
760 tool->Invert();
761
762 RefreshTool( tool );
763 }
764 else if ( action == wxACTION_TOOLBAR_RELEASE )
765 {
766 wxLogTrace(_T("toolbar"), _T("Button '%s' released."), tool->GetShortHelp().c_str());
767
768 wxASSERT_MSG( tool->IsInverted(), _T("release unpressed button?") );
769
770 tool->Invert();
771
772 RefreshTool( tool );
773 }
774 else if ( action == wxACTION_TOOLBAR_CLICK )
775 {
776 bool isToggled;
777 if ( tool->CanBeToggled() )
778 {
779 tool->Toggle();
780
781 RefreshTool( tool );
782
783 isToggled = tool->IsToggled();
784 }
785 else // simple non-checkable tool
786 {
787 isToggled = false;
788 }
789 OnLeftClick( tool->GetId(), isToggled );
790 }
791 else if ( action == wxACTION_TOOLBAR_ENTER )
792 {
793 wxCHECK_MSG( tool, false, _T("no tool to enter?") );
794
795 if ( HasFlag(wxTB_FLAT) && tool->IsEnabled() )
796 {
797 tool->SetUnderMouse( true );
798
799 if ( !tool->IsToggled() )
800 RefreshTool( tool );
801 }
802 }
803 else if ( action == wxACTION_TOOLBAR_LEAVE )
804 {
805 wxCHECK_MSG( tool, false, _T("no tool to leave?") );
806
807 if ( HasFlag(wxTB_FLAT) && tool->IsEnabled() )
808 {
809 tool->SetUnderMouse( false );
810
811 if ( !tool->IsToggled() )
812 RefreshTool( tool );
813 }
814 }
815 else
816 return wxControl::PerformAction(action, numArg, strArg);
817
818 return true;
819 }
820
821 // ============================================================================
822 // wxStdToolbarInputHandler implementation
823 // ============================================================================
824
825 wxStdToolbarInputHandler::wxStdToolbarInputHandler(wxInputHandler *handler)
826 : wxStdInputHandler(handler)
827 {
828 m_winCapture = NULL;
829 m_toolCapture = NULL;
830 m_toolLast = NULL;
831 }
832
833 bool 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
842 bool wxStdToolbarInputHandler::HandleMouse(wxInputConsumer *consumer,
843 const wxMouseEvent& event)
844 {
845 wxToolBar *tbar = wxStaticCast(consumer->GetInputWindow(), wxToolBar);
846 wxToolBarToolBase *tool = tbar->FindToolForPosition(event.GetX(), event.GetY());
847
848 if ( event.Button(1) )
849 {
850
851 if ( event.LeftDown() || event.LeftDClick() )
852 {
853 if ( !tool || !tool->IsEnabled() )
854 return true;
855
856 m_winCapture = tbar;
857 m_winCapture->CaptureMouse();
858
859 m_toolCapture = tool;
860
861 consumer->PerformAction( wxACTION_BUTTON_PRESS, tool->GetId() );
862
863 return true;
864 }
865 else if ( event.LeftUp() )
866 {
867 if ( m_winCapture )
868 {
869 m_winCapture->ReleaseMouse();
870 m_winCapture = NULL;
871 }
872
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 }
880
881 m_toolCapture = NULL;
882
883 return true;
884 }
885 //else: don't do anything special about the double click
886 }
887
888 return wxStdInputHandler::HandleMouse(consumer, event);
889 }
890
891 bool wxStdToolbarInputHandler::HandleMouseMove(wxInputConsumer *consumer,
892 const wxMouseEvent& event)
893 {
894 if ( !wxStdInputHandler::HandleMouseMove(consumer, event) )
895 {
896 wxToolBar *tbar = wxStaticCast(consumer->GetInputWindow(), wxToolBar);
897
898 wxToolBarTool *tool;
899 if ( event.Leaving() )
900 {
901 // We cannot possibly be over a tool when
902 // leaving the toolbar
903 tool = NULL;
904 }
905 else
906 {
907 tool = (wxToolBarTool*) tbar->FindToolForPosition( event.GetX(), event.GetY() );
908 }
909
910 if (m_toolCapture)
911 {
912 // During capture we only care of the captured tool
913 if (tool && (tool != m_toolCapture))
914 tool = NULL;
915
916 if (tool == m_toolLast)
917 return true;
918
919 if (tool)
920 consumer->PerformAction( wxACTION_BUTTON_PRESS, m_toolCapture->GetId() );
921 else
922 consumer->PerformAction( wxACTION_BUTTON_RELEASE, m_toolCapture->GetId() );
923
924 m_toolLast = tool;
925 }
926 else
927 {
928 if (tool == m_toolLast)
929 return true;
930
931 if (m_toolLast)
932 {
933 // Leave old tool if any
934 consumer->PerformAction( wxACTION_TOOLBAR_LEAVE, m_toolLast->GetId() );
935 }
936
937 if (tool)
938 {
939 // Enter new tool if any
940 consumer->PerformAction( wxACTION_TOOLBAR_ENTER, tool->GetId() );
941 }
942
943 m_toolLast = tool;
944 }
945
946 return true;
947 }
948
949 return false;
950 }
951
952 bool wxStdToolbarInputHandler::HandleFocus(wxInputConsumer *consumer,
953 const wxFocusEvent& WXUNUSED(event))
954 {
955 if ( m_toolCapture )
956 {
957 // We shouldn't be left with a highlighted button
958 consumer->PerformAction( wxACTION_TOOLBAR_LEAVE, m_toolCapture->GetId() );
959 }
960
961 return true;
962 }
963
964 bool wxStdToolbarInputHandler::HandleActivation(wxInputConsumer *consumer,
965 bool activated)
966 {
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 }
972
973 return true;
974 }
975
976 #endif // wxUSE_TOOLBAR