1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/tbarbase.cpp
3 // Purpose: wxToolBarBase implementation
4 // Author: Julian Smart
5 // Modified by: VZ at 11.12.99 (wxScrollableToolBar split off)
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
29 #include "wx/toolbar.h"
32 #include "wx/control.h"
34 #include "wx/settings.h"
35 #if WXWIN_COMPATIBILITY_2_8
37 #endif // WXWIN_COMPATIBILITY_2_8
41 // ----------------------------------------------------------------------------
43 // ----------------------------------------------------------------------------
45 BEGIN_EVENT_TABLE(wxToolBarBase
, wxControl
)
48 #include "wx/listimpl.cpp"
50 WX_DEFINE_LIST(wxToolBarToolsList
)
52 // ============================================================================
54 // ============================================================================
56 // ----------------------------------------------------------------------------
58 // ----------------------------------------------------------------------------
60 IMPLEMENT_DYNAMIC_CLASS(wxToolBarToolBase
, wxObject
)
62 wxToolBarToolBase::~wxToolBarToolBase()
64 delete m_dropdownMenu
;
66 GetControl()->Destroy();
70 bool wxToolBarToolBase::Enable(bool enable
)
72 if ( m_enabled
== enable
)
80 bool wxToolBarToolBase::Toggle(bool toggle
)
82 wxASSERT_MSG( CanBeToggled(), wxT("can't toggle this tool") );
84 if ( m_toggled
== toggle
)
92 bool wxToolBarToolBase::SetToggle(bool toggle
)
94 wxItemKind kind
= toggle
? wxITEM_CHECK
: wxITEM_NORMAL
;
103 bool wxToolBarToolBase::SetShortHelp(const wxString
& help
)
105 if ( m_shortHelpString
== help
)
108 m_shortHelpString
= help
;
113 bool wxToolBarToolBase::SetLongHelp(const wxString
& help
)
115 if ( m_longHelpString
== help
)
118 m_longHelpString
= help
;
124 void wxToolBarToolBase::SetDropdownMenu(wxMenu
* menu
)
126 delete m_dropdownMenu
;
127 m_dropdownMenu
= menu
;
131 // ----------------------------------------------------------------------------
132 // wxToolBarBase adding/deleting items
133 // ----------------------------------------------------------------------------
135 wxToolBarBase::wxToolBarBase()
137 // the list owns the pointers
138 m_xMargin
= m_yMargin
= 0;
139 m_maxRows
= m_maxCols
= 0;
140 m_toolPacking
= m_toolSeparation
= 0;
142 m_defaultHeight
= 15;
145 void wxToolBarBase::FixupStyle()
147 if ( !HasFlag(wxTB_TOP
| wxTB_LEFT
| wxTB_RIGHT
| wxTB_BOTTOM
) )
149 // this is the default
150 m_windowStyle
|= wxTB_TOP
;
154 wxToolBarToolBase
*wxToolBarBase::DoAddTool(int id
,
155 const wxString
& label
,
156 const wxBitmap
& bitmap
,
157 const wxBitmap
& bmpDisabled
,
159 const wxString
& shortHelp
,
160 const wxString
& longHelp
,
161 wxObject
*clientData
,
162 wxCoord
WXUNUSED(xPos
),
163 wxCoord
WXUNUSED(yPos
))
165 InvalidateBestSize();
166 return InsertTool(GetToolsCount(), id
, label
, bitmap
, bmpDisabled
,
167 kind
, shortHelp
, longHelp
, clientData
);
170 wxToolBarToolBase
*wxToolBarBase::InsertTool(size_t pos
,
172 const wxString
& label
,
173 const wxBitmap
& bitmap
,
174 const wxBitmap
& bmpDisabled
,
176 const wxString
& shortHelp
,
177 const wxString
& longHelp
,
178 wxObject
*clientData
)
180 wxCHECK_MSG( pos
<= GetToolsCount(), NULL
,
181 wxT("invalid position in wxToolBar::InsertTool()") );
183 wxToolBarToolBase
*tool
= CreateTool(id
, label
, bitmap
, bmpDisabled
, kind
,
184 clientData
, shortHelp
, longHelp
);
186 if ( !InsertTool(pos
, tool
) )
196 wxToolBarToolBase
*wxToolBarBase::AddTool(wxToolBarToolBase
*tool
)
198 return InsertTool(GetToolsCount(), tool
);
202 wxToolBarBase::InsertTool(size_t pos
, wxToolBarToolBase
*tool
)
204 wxCHECK_MSG( pos
<= GetToolsCount(), NULL
,
205 wxT("invalid position in wxToolBar::InsertTool()") );
207 if ( !tool
|| !DoInsertTool(pos
, tool
) )
212 m_tools
.Insert(pos
, tool
);
219 wxToolBarBase::AddControl(wxControl
*control
, const wxString
& label
)
221 return InsertControl(GetToolsCount(), control
, label
);
225 wxToolBarBase::InsertControl(size_t pos
,
227 const wxString
& label
)
229 wxCHECK_MSG( control
, NULL
,
230 wxT("toolbar: can't insert NULL control") );
232 wxCHECK_MSG( control
->GetParent() == this, NULL
,
233 wxT("control must have toolbar as parent") );
235 wxCHECK_MSG( pos
<= GetToolsCount(), NULL
,
236 wxT("invalid position in wxToolBar::InsertControl()") );
238 wxToolBarToolBase
*tool
= CreateTool(control
, label
);
240 if ( !InsertTool(pos
, tool
) )
250 wxControl
*wxToolBarBase::FindControl( int id
)
252 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
254 node
= node
->GetNext() )
256 const wxToolBarToolBase
* const tool
= node
->GetData();
257 if ( tool
->IsControl() )
259 wxControl
* const control
= tool
->GetControl();
263 wxFAIL_MSG( wxT("NULL control in toolbar?") );
265 else if ( control
->GetId() == id
)
276 wxToolBarToolBase
*wxToolBarBase::AddSeparator()
278 return InsertSeparator(GetToolsCount());
281 wxToolBarToolBase
*wxToolBarBase::InsertSeparator(size_t pos
)
283 wxCHECK_MSG( pos
<= GetToolsCount(), NULL
,
284 wxT("invalid position in wxToolBar::InsertSeparator()") );
286 wxToolBarToolBase
*tool
= CreateTool(wxID_SEPARATOR
,
288 wxNullBitmap
, wxNullBitmap
,
289 wxITEM_SEPARATOR
, NULL
,
290 wxEmptyString
, wxEmptyString
);
292 if ( !tool
|| !DoInsertTool(pos
, tool
) )
299 m_tools
.Insert(pos
, tool
);
304 wxToolBarToolBase
*wxToolBarBase::RemoveTool(int id
)
307 wxToolBarToolsList::compatibility_iterator node
;
308 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
310 if ( node
->GetData()->GetId() == id
)
318 // don't give any error messages - sometimes we might call RemoveTool()
319 // without knowing whether the tool is or not in the toolbar
323 wxToolBarToolBase
*tool
= node
->GetData();
324 wxCHECK_MSG( tool
, NULL
, "NULL tool in the tools list?" );
326 if ( !DoDeleteTool(pos
, tool
) )
336 bool wxToolBarBase::DeleteToolByPos(size_t pos
)
338 wxCHECK_MSG( pos
< GetToolsCount(), false,
339 wxT("invalid position in wxToolBar::DeleteToolByPos()") );
341 wxToolBarToolsList::compatibility_iterator node
= m_tools
.Item(pos
);
343 if ( !DoDeleteTool(pos
, node
->GetData()) )
348 delete node
->GetData();
354 bool wxToolBarBase::DeleteTool(int id
)
357 wxToolBarToolsList::compatibility_iterator node
;
358 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
360 if ( node
->GetData()->GetId() == id
)
366 if ( !node
|| !DoDeleteTool(pos
, node
->GetData()) )
371 delete node
->GetData();
377 wxToolBarToolBase
*wxToolBarBase::FindById(int id
) const
379 wxToolBarToolBase
*tool
= NULL
;
381 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
383 node
= node
->GetNext() )
385 tool
= node
->GetData();
386 if ( tool
->GetId() == id
)
398 void wxToolBarBase::UnToggleRadioGroup(wxToolBarToolBase
*tool
)
400 wxCHECK_RET( tool
, wxT("NULL tool in wxToolBarTool::UnToggleRadioGroup") );
402 if ( !tool
->IsButton() || tool
->GetKind() != wxITEM_RADIO
)
405 wxToolBarToolsList::compatibility_iterator node
= m_tools
.Find(tool
);
406 wxCHECK_RET( node
, wxT("invalid tool in wxToolBarTool::UnToggleRadioGroup") );
408 wxToolBarToolsList::compatibility_iterator nodeNext
= node
->GetNext();
411 wxToolBarToolBase
*toolNext
= nodeNext
->GetData();
413 if ( !toolNext
->IsButton() || toolNext
->GetKind() != wxITEM_RADIO
)
416 if ( toolNext
->Toggle(false) )
418 DoToggleTool(toolNext
, false);
421 nodeNext
= nodeNext
->GetNext();
424 wxToolBarToolsList::compatibility_iterator nodePrev
= node
->GetPrevious();
427 wxToolBarToolBase
*toolNext
= nodePrev
->GetData();
429 if ( !toolNext
->IsButton() || toolNext
->GetKind() != wxITEM_RADIO
)
432 if ( toolNext
->Toggle(false) )
434 DoToggleTool(toolNext
, false);
437 nodePrev
= nodePrev
->GetPrevious();
441 void wxToolBarBase::ClearTools()
443 while ( GetToolsCount() )
449 void wxToolBarBase::AdjustToolBitmapSize()
451 const wxSize
sizeOrig(m_defaultWidth
, m_defaultHeight
);
453 wxSize
sizeActual(sizeOrig
);
455 for ( wxToolBarToolsList::const_iterator i
= m_tools
.begin();
459 const wxBitmap
& bmp
= (*i
)->GetNormalBitmap();
461 sizeActual
.IncTo(bmp
.GetSize());
464 if ( sizeActual
!= sizeOrig
)
465 SetToolBitmapSize(sizeActual
);
468 bool wxToolBarBase::Realize()
470 // check if we have anything to do
471 if ( m_tools
.empty() )
474 // make sure tool size is larger enough for all all bitmaps to fit in
475 // (this is consistent with what other ports do):
476 AdjustToolBitmapSize();
481 wxToolBarBase::~wxToolBarBase()
483 WX_CLEAR_LIST(wxToolBarToolsList
, m_tools
);
485 // notify the frame that it doesn't have a tool bar any longer to avoid
487 wxFrame
*frame
= wxDynamicCast(GetParent(), wxFrame
);
488 if ( frame
&& frame
->GetToolBar() == this )
490 frame
->SetToolBar(NULL
);
494 // ----------------------------------------------------------------------------
495 // wxToolBarBase tools state
496 // ----------------------------------------------------------------------------
498 void wxToolBarBase::EnableTool(int id
, bool enable
)
500 wxToolBarToolBase
*tool
= FindById(id
);
503 if ( tool
->Enable(enable
) )
505 DoEnableTool(tool
, enable
);
510 void wxToolBarBase::ToggleTool(int id
, bool toggle
)
512 wxToolBarToolBase
*tool
= FindById(id
);
513 if ( tool
&& tool
->CanBeToggled() )
515 if ( tool
->Toggle(toggle
) )
517 UnToggleRadioGroup(tool
);
518 DoToggleTool(tool
, toggle
);
523 void wxToolBarBase::SetToggle(int id
, bool toggle
)
525 wxToolBarToolBase
*tool
= FindById(id
);
528 if ( tool
->SetToggle(toggle
) )
530 DoSetToggle(tool
, toggle
);
535 void wxToolBarBase::SetToolShortHelp(int id
, const wxString
& help
)
537 wxToolBarToolBase
*tool
= FindById(id
);
540 (void)tool
->SetShortHelp(help
);
544 void wxToolBarBase::SetToolLongHelp(int id
, const wxString
& help
)
546 wxToolBarToolBase
*tool
= FindById(id
);
549 (void)tool
->SetLongHelp(help
);
553 wxObject
*wxToolBarBase::GetToolClientData(int id
) const
555 wxToolBarToolBase
*tool
= FindById(id
);
557 return tool
? tool
->GetClientData() : NULL
;
560 void wxToolBarBase::SetToolClientData(int id
, wxObject
*clientData
)
562 wxToolBarToolBase
*tool
= FindById(id
);
564 wxCHECK_RET( tool
, wxT("no such tool in wxToolBar::SetToolClientData") );
566 tool
->SetClientData(clientData
);
569 int wxToolBarBase::GetToolPos(int id
) const
572 wxToolBarToolsList::compatibility_iterator node
;
574 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
576 if ( node
->GetData()->GetId() == id
)
585 bool wxToolBarBase::GetToolState(int id
) const
587 wxToolBarToolBase
*tool
= FindById(id
);
588 wxCHECK_MSG( tool
, false, wxT("no such tool") );
590 return tool
->IsToggled();
593 bool wxToolBarBase::GetToolEnabled(int id
) const
595 wxToolBarToolBase
*tool
= FindById(id
);
596 wxCHECK_MSG( tool
, false, wxT("no such tool") );
598 return tool
->IsEnabled();
601 wxString
wxToolBarBase::GetToolShortHelp(int id
) const
603 wxToolBarToolBase
*tool
= FindById(id
);
604 wxCHECK_MSG( tool
, wxEmptyString
, wxT("no such tool") );
606 return tool
->GetShortHelp();
609 wxString
wxToolBarBase::GetToolLongHelp(int id
) const
611 wxToolBarToolBase
*tool
= FindById(id
);
612 wxCHECK_MSG( tool
, wxEmptyString
, wxT("no such tool") );
614 return tool
->GetLongHelp();
617 // ----------------------------------------------------------------------------
618 // wxToolBarBase geometry
619 // ----------------------------------------------------------------------------
621 void wxToolBarBase::SetMargins(int x
, int y
)
627 void wxToolBarBase::SetRows(int WXUNUSED(nRows
))
632 bool wxToolBarBase::IsVertical() const
634 return HasFlag(wxTB_LEFT
| wxTB_RIGHT
);
638 // ----------------------------------------------------------------------------
640 // ----------------------------------------------------------------------------
642 // Only allow toggle if returns true
643 bool wxToolBarBase::OnLeftClick(int id
, bool toggleDown
)
645 wxCommandEvent
event(wxEVT_COMMAND_TOOL_CLICKED
, id
);
646 event
.SetEventObject(this);
648 // we use SetInt() to make wxCommandEvent::IsChecked() return toggleDown
649 event
.SetInt((int)toggleDown
);
651 // and SetExtraLong() for backwards compatibility
652 event
.SetExtraLong((long)toggleDown
);
654 // Send events to this toolbar instead (and thence up the window hierarchy)
655 HandleWindowEvent(event
);
660 // Call when right button down.
661 void wxToolBarBase::OnRightClick(int id
,
665 wxCommandEvent
event(wxEVT_COMMAND_TOOL_RCLICKED
, id
);
666 event
.SetEventObject(this);
669 GetEventHandler()->ProcessEvent(event
);
672 // Called when the mouse cursor enters a tool bitmap (no button pressed).
673 // Argument is wxID_ANY if mouse is exiting the toolbar.
674 // Note that for this event, the id of the window is used,
675 // and the integer parameter of wxCommandEvent is used to retrieve
677 void wxToolBarBase::OnMouseEnter(int id
)
679 wxCommandEvent
event(wxEVT_COMMAND_TOOL_ENTER
, GetId());
680 event
.SetEventObject(this);
683 wxFrame
*frame
= wxDynamicCast(GetParent(), wxFrame
);
687 if ( id
!= wxID_ANY
)
689 const wxToolBarToolBase
* const tool
= FindById(id
);
691 help
= tool
->GetLongHelp();
694 // call DoGiveHelp() even if help string is empty to avoid showing the
695 // help for the previously selected tool when another one is selected
696 frame
->DoGiveHelp(help
, id
!= wxID_ANY
);
699 (void)GetEventHandler()->ProcessEvent(event
);
702 // ----------------------------------------------------------------------------
704 // ----------------------------------------------------------------------------
706 // Do the toolbar button updates (check for EVT_UPDATE_UI handlers)
707 void wxToolBarBase::UpdateWindowUI(long flags
)
709 wxWindowBase::UpdateWindowUI(flags
);
711 // don't waste time updating state of tools in a hidden toolbar
715 // There is no sense in updating the toolbar UI
716 // if the parent window is about to get destroyed
717 wxWindow
*tlw
= wxGetTopLevelParent( this );
718 if (tlw
&& wxPendingDelete
.Member( tlw
))
721 wxEvtHandler
* evtHandler
= GetEventHandler() ;
723 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
725 node
= node
->GetNext() )
727 wxToolBarToolBase
* const tool
= node
->GetData();
728 if ( tool
->IsSeparator() )
731 int id
= tool
->GetId();
733 wxUpdateUIEvent
event(id
);
734 event
.SetEventObject(this);
736 if ( evtHandler
->ProcessEvent(event
) )
738 if ( event
.GetSetEnabled() )
739 EnableTool(id
, event
.GetEnabled());
740 if ( event
.GetSetChecked() )
741 ToggleTool(id
, event
.GetChecked());
743 if ( event
.GetSetText() )
750 bool wxToolBarBase::SetDropdownMenu(int toolid
, wxMenu
* menu
)
752 wxToolBarToolBase
* const tool
= FindById(toolid
);
753 wxCHECK_MSG( tool
, false, wxT("invalid tool id") );
755 wxCHECK_MSG( tool
->GetKind() == wxITEM_DROPDOWN
, false,
756 wxT("menu can be only associated with drop down tools") );
758 tool
->SetDropdownMenu(menu
);
763 #if WXWIN_COMPATIBILITY_2_8
765 bool wxCreateGreyedImage(const wxImage
& in
, wxImage
& out
)
768 out
= in
.ConvertToGreyscale();
771 #endif // wxUSE_IMAGE
775 #endif // WXWIN_COMPATIBILITY_2_8
777 #endif // wxUSE_TOOLBAR