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)
7 // Copyright: (c) Julian Smart
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
28 #include "wx/toolbar.h"
31 #include "wx/control.h"
33 #include "wx/settings.h"
34 #if WXWIN_COMPATIBILITY_2_8
36 #endif // WXWIN_COMPATIBILITY_2_8
40 extern WXDLLEXPORT_DATA(const char) wxToolBarNameStr
[] = "toolbar";
42 // ----------------------------------------------------------------------------
44 // ----------------------------------------------------------------------------
46 BEGIN_EVENT_TABLE(wxToolBarBase
, wxControl
)
49 #include "wx/listimpl.cpp"
51 WX_DEFINE_LIST(wxToolBarToolsList
)
53 // ============================================================================
55 // ============================================================================
57 // ----------------------------------------------------------------------------
59 // ----------------------------------------------------------------------------
61 IMPLEMENT_DYNAMIC_CLASS(wxToolBarToolBase
, wxObject
)
63 wxToolBarToolBase::~wxToolBarToolBase()
66 delete m_dropdownMenu
;
70 GetControl()->Destroy();
74 bool wxToolBarToolBase::Enable(bool enable
)
76 if ( m_enabled
== enable
)
84 bool wxToolBarToolBase::Toggle(bool toggle
)
86 wxASSERT_MSG( CanBeToggled(), wxT("can't toggle this tool") );
88 if ( m_toggled
== toggle
)
96 bool wxToolBarToolBase::SetToggle(bool toggle
)
98 wxItemKind kind
= toggle
? wxITEM_CHECK
: wxITEM_NORMAL
;
107 bool wxToolBarToolBase::SetShortHelp(const wxString
& help
)
109 if ( m_shortHelpString
== help
)
112 m_shortHelpString
= help
;
117 bool wxToolBarToolBase::SetLongHelp(const wxString
& help
)
119 if ( m_longHelpString
== help
)
122 m_longHelpString
= help
;
129 void wxToolBarToolBase::SetDropdownMenu(wxMenu
* menu
)
131 delete m_dropdownMenu
;
132 m_dropdownMenu
= menu
;
137 // ----------------------------------------------------------------------------
138 // wxToolBarBase adding/deleting items
139 // ----------------------------------------------------------------------------
141 wxToolBarBase::wxToolBarBase()
143 // the list owns the pointers
144 m_xMargin
= m_yMargin
= 0;
145 m_maxRows
= m_maxCols
= 0;
146 m_toolPacking
= m_toolSeparation
= 0;
148 m_defaultHeight
= 15;
151 void wxToolBarBase::FixupStyle()
153 if ( !HasFlag(wxTB_TOP
| wxTB_LEFT
| wxTB_RIGHT
| wxTB_BOTTOM
) )
155 // this is the default
156 m_windowStyle
|= wxTB_TOP
;
160 wxToolBarToolBase
*wxToolBarBase::DoAddTool(int toolid
,
161 const wxString
& label
,
162 const wxBitmap
& bitmap
,
163 const wxBitmap
& bmpDisabled
,
165 const wxString
& shortHelp
,
166 const wxString
& longHelp
,
167 wxObject
*clientData
,
168 wxCoord
WXUNUSED(xPos
),
169 wxCoord
WXUNUSED(yPos
))
171 InvalidateBestSize();
172 return InsertTool(GetToolsCount(), toolid
, label
, bitmap
, bmpDisabled
,
173 kind
, shortHelp
, longHelp
, clientData
);
176 wxToolBarToolBase
*wxToolBarBase::InsertTool(size_t pos
,
178 const wxString
& label
,
179 const wxBitmap
& bitmap
,
180 const wxBitmap
& bmpDisabled
,
182 const wxString
& shortHelp
,
183 const wxString
& longHelp
,
184 wxObject
*clientData
)
186 wxCHECK_MSG( pos
<= GetToolsCount(), NULL
,
187 wxT("invalid position in wxToolBar::InsertTool()") );
189 return DoInsertNewTool(pos
, CreateTool(toolid
, label
, bitmap
, bmpDisabled
, kind
,
190 clientData
, shortHelp
, longHelp
));
193 wxToolBarToolBase
*wxToolBarBase::AddTool(wxToolBarToolBase
*tool
)
195 return InsertTool(GetToolsCount(), tool
);
199 wxToolBarBase::InsertTool(size_t pos
, wxToolBarToolBase
*tool
)
201 wxCHECK_MSG( pos
<= GetToolsCount(), NULL
,
202 wxT("invalid position in wxToolBar::InsertTool()") );
204 if ( !tool
|| !DoInsertTool(pos
, tool
) )
209 m_tools
.Insert(pos
, tool
);
216 wxToolBarBase::AddControl(wxControl
*control
, const wxString
& label
)
218 return InsertControl(GetToolsCount(), control
, label
);
222 wxToolBarBase::InsertControl(size_t pos
,
224 const wxString
& label
)
226 wxCHECK_MSG( control
, NULL
,
227 wxT("toolbar: can't insert NULL control") );
229 wxCHECK_MSG( control
->GetParent() == this, NULL
,
230 wxT("control must have toolbar as parent") );
232 return DoInsertNewTool(pos
, CreateTool(control
, label
));
235 wxControl
*wxToolBarBase::FindControl( int toolid
)
237 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
239 node
= node
->GetNext() )
241 const wxToolBarToolBase
* const tool
= node
->GetData();
242 if ( tool
->IsControl() )
244 wxControl
* const control
= tool
->GetControl();
248 wxFAIL_MSG( wxT("NULL control in toolbar?") );
250 else if ( control
->GetId() == toolid
)
261 wxToolBarToolBase
*wxToolBarBase::AddSeparator()
263 return InsertSeparator(GetToolsCount());
266 wxToolBarToolBase
*wxToolBarBase::InsertSeparator(size_t pos
)
268 return DoInsertNewTool(pos
, CreateSeparator());
271 wxToolBarToolBase
*wxToolBarBase::AddStretchableSpace()
273 return InsertStretchableSpace(GetToolsCount());
276 wxToolBarToolBase
*wxToolBarBase::InsertStretchableSpace(size_t pos
)
278 wxToolBarToolBase
* const tool
= CreateSeparator();
281 // this is a hack but we know that all the current implementations
282 // don't really use the tool when it's created, they will do it
283 // InsertTool() at earliest and maybe even in Realize() much later
285 // so we can create the tool as a plain separator and mark it as being
286 // a stretchable space later
287 tool
->MakeStretchable();
290 return DoInsertNewTool(pos
, tool
);
293 wxToolBarToolBase
*wxToolBarBase::RemoveTool(int toolid
)
296 wxToolBarToolsList::compatibility_iterator node
;
297 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
299 if ( node
->GetData()->GetId() == toolid
)
307 // don't give any error messages - sometimes we might call RemoveTool()
308 // without knowing whether the tool is or not in the toolbar
312 wxToolBarToolBase
*tool
= node
->GetData();
313 wxCHECK_MSG( tool
, NULL
, "NULL tool in the tools list?" );
315 if ( !DoDeleteTool(pos
, tool
) )
325 bool wxToolBarBase::DeleteToolByPos(size_t pos
)
327 wxCHECK_MSG( pos
< GetToolsCount(), false,
328 wxT("invalid position in wxToolBar::DeleteToolByPos()") );
330 wxToolBarToolsList::compatibility_iterator node
= m_tools
.Item(pos
);
332 if ( !DoDeleteTool(pos
, node
->GetData()) )
337 delete node
->GetData();
343 bool wxToolBarBase::DeleteTool(int toolid
)
346 wxToolBarToolsList::compatibility_iterator node
;
347 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
349 if ( node
->GetData()->GetId() == toolid
)
355 if ( !node
|| !DoDeleteTool(pos
, node
->GetData()) )
360 delete node
->GetData();
366 wxToolBarToolBase
*wxToolBarBase::FindById(int toolid
) const
368 wxToolBarToolBase
*tool
= NULL
;
370 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
372 node
= node
->GetNext() )
374 tool
= node
->GetData();
375 if ( tool
->GetId() == toolid
)
387 void wxToolBarBase::UnToggleRadioGroup(wxToolBarToolBase
*tool
)
389 wxCHECK_RET( tool
, wxT("NULL tool in wxToolBarTool::UnToggleRadioGroup") );
391 if ( !tool
->IsButton() || tool
->GetKind() != wxITEM_RADIO
)
394 wxToolBarToolsList::compatibility_iterator node
= m_tools
.Find(tool
);
395 wxCHECK_RET( node
, wxT("invalid tool in wxToolBarTool::UnToggleRadioGroup") );
397 wxToolBarToolsList::compatibility_iterator nodeNext
= node
->GetNext();
400 wxToolBarToolBase
*toolNext
= nodeNext
->GetData();
402 if ( !toolNext
->IsButton() || toolNext
->GetKind() != wxITEM_RADIO
)
405 if ( toolNext
->Toggle(false) )
407 DoToggleTool(toolNext
, false);
410 nodeNext
= nodeNext
->GetNext();
413 wxToolBarToolsList::compatibility_iterator nodePrev
= node
->GetPrevious();
416 wxToolBarToolBase
*toolNext
= nodePrev
->GetData();
418 if ( !toolNext
->IsButton() || toolNext
->GetKind() != wxITEM_RADIO
)
421 if ( toolNext
->Toggle(false) )
423 DoToggleTool(toolNext
, false);
426 nodePrev
= nodePrev
->GetPrevious();
430 void wxToolBarBase::ClearTools()
432 while ( GetToolsCount() )
438 void wxToolBarBase::AdjustToolBitmapSize()
440 const wxSize
sizeOrig(m_defaultWidth
, m_defaultHeight
);
442 wxSize
sizeActual(sizeOrig
);
444 for ( wxToolBarToolsList::const_iterator i
= m_tools
.begin();
448 const wxBitmap
& bmp
= (*i
)->GetNormalBitmap();
450 sizeActual
.IncTo(bmp
.GetSize());
453 if ( sizeActual
!= sizeOrig
)
454 SetToolBitmapSize(sizeActual
);
457 bool wxToolBarBase::Realize()
459 // check if we have anything to do
460 if ( m_tools
.empty() )
463 // make sure tool size is large enough for all bitmaps to fit in
464 AdjustToolBitmapSize();
469 wxToolBarBase::~wxToolBarBase()
471 WX_CLEAR_LIST(wxToolBarToolsList
, m_tools
);
473 // notify the frame that it doesn't have a tool bar any longer to avoid
475 wxFrame
*frame
= wxDynamicCast(GetParent(), wxFrame
);
476 if ( frame
&& frame
->GetToolBar() == this )
478 frame
->SetToolBar(NULL
);
482 // ----------------------------------------------------------------------------
483 // wxToolBarBase tools state
484 // ----------------------------------------------------------------------------
486 void wxToolBarBase::EnableTool(int toolid
, bool enable
)
488 wxToolBarToolBase
*tool
= FindById(toolid
);
491 if ( tool
->Enable(enable
) )
493 DoEnableTool(tool
, enable
);
498 void wxToolBarBase::ToggleTool(int toolid
, bool toggle
)
500 wxToolBarToolBase
*tool
= FindById(toolid
);
501 if ( tool
&& tool
->CanBeToggled() )
503 if ( tool
->Toggle(toggle
) )
505 UnToggleRadioGroup(tool
);
506 DoToggleTool(tool
, toggle
);
511 void wxToolBarBase::SetToggle(int toolid
, bool toggle
)
513 wxToolBarToolBase
*tool
= FindById(toolid
);
516 if ( tool
->SetToggle(toggle
) )
518 DoSetToggle(tool
, toggle
);
523 void wxToolBarBase::SetToolShortHelp(int toolid
, const wxString
& help
)
525 wxToolBarToolBase
*tool
= FindById(toolid
);
528 (void)tool
->SetShortHelp(help
);
532 void wxToolBarBase::SetToolLongHelp(int toolid
, const wxString
& help
)
534 wxToolBarToolBase
*tool
= FindById(toolid
);
537 (void)tool
->SetLongHelp(help
);
541 wxObject
*wxToolBarBase::GetToolClientData(int toolid
) const
543 wxToolBarToolBase
*tool
= FindById(toolid
);
545 return tool
? tool
->GetClientData() : NULL
;
548 void wxToolBarBase::SetToolClientData(int toolid
, wxObject
*clientData
)
550 wxToolBarToolBase
*tool
= FindById(toolid
);
552 wxCHECK_RET( tool
, wxT("no such tool in wxToolBar::SetToolClientData") );
554 tool
->SetClientData(clientData
);
557 int wxToolBarBase::GetToolPos(int toolid
) const
560 wxToolBarToolsList::compatibility_iterator node
;
562 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
564 if ( node
->GetData()->GetId() == toolid
)
573 bool wxToolBarBase::GetToolState(int toolid
) const
575 wxToolBarToolBase
*tool
= FindById(toolid
);
576 wxCHECK_MSG( tool
, false, wxT("no such tool") );
578 return tool
->IsToggled();
581 bool wxToolBarBase::GetToolEnabled(int toolid
) const
583 wxToolBarToolBase
*tool
= FindById(toolid
);
584 wxCHECK_MSG( tool
, false, wxT("no such tool") );
586 return tool
->IsEnabled();
589 wxString
wxToolBarBase::GetToolShortHelp(int toolid
) const
591 wxToolBarToolBase
*tool
= FindById(toolid
);
592 wxCHECK_MSG( tool
, wxEmptyString
, wxT("no such tool") );
594 return tool
->GetShortHelp();
597 wxString
wxToolBarBase::GetToolLongHelp(int toolid
) const
599 wxToolBarToolBase
*tool
= FindById(toolid
);
600 wxCHECK_MSG( tool
, wxEmptyString
, wxT("no such tool") );
602 return tool
->GetLongHelp();
605 // ----------------------------------------------------------------------------
606 // wxToolBarBase geometry
607 // ----------------------------------------------------------------------------
609 void wxToolBarBase::SetMargins(int x
, int y
)
615 void wxToolBarBase::SetRows(int WXUNUSED(nRows
))
620 bool wxToolBarBase::IsVertical() const
622 return HasFlag(wxTB_LEFT
| wxTB_RIGHT
);
626 // ----------------------------------------------------------------------------
628 // ----------------------------------------------------------------------------
630 // Only allow toggle if returns true
631 bool wxToolBarBase::OnLeftClick(int toolid
, bool toggleDown
)
633 wxCommandEvent
event(wxEVT_TOOL
, toolid
);
634 event
.SetEventObject(this);
636 // we use SetInt() to make wxCommandEvent::IsChecked() return toggleDown
637 event
.SetInt((int)toggleDown
);
639 // and SetExtraLong() for backwards compatibility
640 event
.SetExtraLong((long)toggleDown
);
642 // Send events to this toolbar instead (and thence up the window hierarchy)
643 HandleWindowEvent(event
);
648 // Call when right button down.
649 void wxToolBarBase::OnRightClick(int toolid
,
653 wxCommandEvent
event(wxEVT_TOOL_RCLICKED
, toolid
);
654 event
.SetEventObject(this);
655 event
.SetInt(toolid
);
657 GetEventHandler()->ProcessEvent(event
);
660 // Called when the mouse cursor enters a tool bitmap (no button pressed).
661 // Argument is wxID_ANY if mouse is exiting the toolbar.
662 // Note that for this event, the toolid of the window is used,
663 // and the integer parameter of wxCommandEvent is used to retrieve
665 void wxToolBarBase::OnMouseEnter(int toolid
)
667 wxCommandEvent
event(wxEVT_TOOL_ENTER
, GetId());
668 event
.SetEventObject(this);
669 event
.SetInt(toolid
);
671 wxFrame
*frame
= wxDynamicCast(GetParent(), wxFrame
);
675 if ( toolid
!= wxID_ANY
)
677 const wxToolBarToolBase
* const tool
= FindById(toolid
);
679 help
= tool
->GetLongHelp();
682 // call DoGiveHelp() even if help string is empty to avoid showing the
683 // help for the previously selected tool when another one is selected
684 frame
->DoGiveHelp(help
, toolid
!= wxID_ANY
);
687 (void)GetEventHandler()->ProcessEvent(event
);
690 // ----------------------------------------------------------------------------
692 // ----------------------------------------------------------------------------
694 // Do the toolbar button updates (check for EVT_UPDATE_UI handlers)
695 void wxToolBarBase::UpdateWindowUI(long flags
)
697 wxWindowBase::UpdateWindowUI(flags
);
699 // don't waste time updating state of tools in a hidden toolbar
703 wxEvtHandler
* evtHandler
= GetEventHandler() ;
705 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
707 node
= node
->GetNext() )
709 wxToolBarToolBase
* const tool
= node
->GetData();
710 if ( tool
->IsSeparator() )
713 int toolid
= tool
->GetId();
715 wxUpdateUIEvent
event(toolid
);
716 event
.SetEventObject(this);
718 if ( evtHandler
->ProcessEvent(event
) )
720 if ( event
.GetSetEnabled() )
721 EnableTool(toolid
, event
.GetEnabled());
722 if ( event
.GetSetChecked() )
723 ToggleTool(toolid
, event
.GetChecked());
725 if ( event
.GetSetText() )
733 bool wxToolBarBase::SetDropdownMenu(int toolid
, wxMenu
* menu
)
735 wxToolBarToolBase
* const tool
= FindById(toolid
);
736 wxCHECK_MSG( tool
, false, wxT("invalid tool toolid") );
738 wxCHECK_MSG( tool
->GetKind() == wxITEM_DROPDOWN
, false,
739 wxT("menu can be only associated with drop down tools") );
741 tool
->SetDropdownMenu(menu
);
747 #if WXWIN_COMPATIBILITY_2_8
749 bool wxCreateGreyedImage(const wxImage
& in
, wxImage
& out
)
752 out
= in
.ConvertToGreyscale();
755 #endif // wxUSE_IMAGE
759 #endif // WXWIN_COMPATIBILITY_2_8
761 #endif // wxUSE_TOOLBAR