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
;
68 bool wxToolBarToolBase::Enable(bool enable
)
70 if ( m_enabled
== enable
)
78 bool wxToolBarToolBase::Toggle(bool toggle
)
80 wxASSERT_MSG( CanBeToggled(), _T("can't toggle this tool") );
82 if ( m_toggled
== toggle
)
90 bool wxToolBarToolBase::SetToggle(bool toggle
)
92 wxItemKind kind
= toggle
? wxITEM_CHECK
: wxITEM_NORMAL
;
101 bool wxToolBarToolBase::SetShortHelp(const wxString
& help
)
103 if ( m_shortHelpString
== help
)
106 m_shortHelpString
= help
;
111 bool wxToolBarToolBase::SetLongHelp(const wxString
& help
)
113 if ( m_longHelpString
== help
)
116 m_longHelpString
= help
;
122 void wxToolBarToolBase::SetDropdownMenu(wxMenu
* menu
)
124 delete m_dropdownMenu
;
125 m_dropdownMenu
= menu
;
129 // ----------------------------------------------------------------------------
130 // wxToolBarBase adding/deleting items
131 // ----------------------------------------------------------------------------
133 wxToolBarBase::wxToolBarBase()
135 // the list owns the pointers
136 m_xMargin
= m_yMargin
= 0;
137 m_maxRows
= m_maxCols
= 0;
138 m_toolPacking
= m_toolSeparation
= 0;
140 m_defaultHeight
= 15;
143 void wxToolBarBase::FixupStyle()
145 if ( !HasFlag(wxTB_TOP
| wxTB_LEFT
| wxTB_RIGHT
| wxTB_BOTTOM
) )
147 // this is the default
148 m_windowStyle
|= wxTB_TOP
;
152 wxToolBarToolBase
*wxToolBarBase::DoAddTool(int id
,
153 const wxString
& label
,
154 const wxBitmap
& bitmap
,
155 const wxBitmap
& bmpDisabled
,
157 const wxString
& shortHelp
,
158 const wxString
& longHelp
,
159 wxObject
*clientData
,
160 wxCoord
WXUNUSED(xPos
),
161 wxCoord
WXUNUSED(yPos
))
163 InvalidateBestSize();
164 return InsertTool(GetToolsCount(), id
, label
, bitmap
, bmpDisabled
,
165 kind
, shortHelp
, longHelp
, clientData
);
168 wxToolBarToolBase
*wxToolBarBase::InsertTool(size_t pos
,
170 const wxString
& label
,
171 const wxBitmap
& bitmap
,
172 const wxBitmap
& bmpDisabled
,
174 const wxString
& shortHelp
,
175 const wxString
& longHelp
,
176 wxObject
*clientData
)
178 wxCHECK_MSG( pos
<= GetToolsCount(), (wxToolBarToolBase
*)NULL
,
179 _T("invalid position in wxToolBar::InsertTool()") );
181 wxToolBarToolBase
*tool
= CreateTool(id
, label
, bitmap
, bmpDisabled
, kind
,
182 clientData
, shortHelp
, longHelp
);
184 if ( !InsertTool(pos
, tool
) )
194 wxToolBarToolBase
*wxToolBarBase::AddTool(wxToolBarToolBase
*tool
)
196 return InsertTool(GetToolsCount(), tool
);
200 wxToolBarBase::InsertTool(size_t pos
, wxToolBarToolBase
*tool
)
202 wxCHECK_MSG( pos
<= GetToolsCount(), (wxToolBarToolBase
*)NULL
,
203 _T("invalid position in wxToolBar::InsertTool()") );
205 if ( !tool
|| !DoInsertTool(pos
, tool
) )
210 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
, (wxToolBarToolBase
*)NULL
,
227 _T("toolbar: can't insert NULL control") );
229 wxCHECK_MSG( control
->GetParent() == this, (wxToolBarToolBase
*)NULL
,
230 _T("control must have toolbar as parent") );
232 wxCHECK_MSG( pos
<= GetToolsCount(), (wxToolBarToolBase
*)NULL
,
233 _T("invalid position in wxToolBar::InsertControl()") );
235 wxToolBarToolBase
*tool
= CreateTool(control
, label
);
237 if ( !InsertTool(pos
, tool
) )
247 wxControl
*wxToolBarBase::FindControl( int id
)
249 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
251 node
= node
->GetNext() )
253 const wxToolBarToolBase
* const tool
= node
->GetData();
254 if ( tool
->IsControl() )
256 wxControl
* const control
= tool
->GetControl();
260 wxFAIL_MSG( _T("NULL control in toolbar?") );
262 else if ( control
->GetId() == id
)
273 wxToolBarToolBase
*wxToolBarBase::AddSeparator()
275 return InsertSeparator(GetToolsCount());
278 wxToolBarToolBase
*wxToolBarBase::InsertSeparator(size_t pos
)
280 wxCHECK_MSG( pos
<= GetToolsCount(), (wxToolBarToolBase
*)NULL
,
281 _T("invalid position in wxToolBar::InsertSeparator()") );
283 wxToolBarToolBase
*tool
= CreateTool(wxID_SEPARATOR
,
285 wxNullBitmap
, wxNullBitmap
,
286 wxITEM_SEPARATOR
, (wxObject
*)NULL
,
287 wxEmptyString
, wxEmptyString
);
289 if ( !tool
|| !DoInsertTool(pos
, tool
) )
296 m_tools
.Insert(pos
, tool
);
301 wxToolBarToolBase
*wxToolBarBase::RemoveTool(int id
)
304 wxToolBarToolsList::compatibility_iterator node
;
305 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
307 if ( node
->GetData()->GetId() == id
)
315 // don't give any error messages - sometimes we might call RemoveTool()
316 // without knowing whether the tool is or not in the toolbar
317 return (wxToolBarToolBase
*)NULL
;
320 wxToolBarToolBase
*tool
= node
->GetData();
321 if ( !DoDeleteTool(pos
, tool
) )
323 return (wxToolBarToolBase
*)NULL
;
331 bool wxToolBarBase::DeleteToolByPos(size_t pos
)
333 wxCHECK_MSG( pos
< GetToolsCount(), false,
334 _T("invalid position in wxToolBar::DeleteToolByPos()") );
336 wxToolBarToolsList::compatibility_iterator node
= m_tools
.Item(pos
);
338 if ( !DoDeleteTool(pos
, node
->GetData()) )
343 delete node
->GetData();
349 bool wxToolBarBase::DeleteTool(int id
)
352 wxToolBarToolsList::compatibility_iterator node
;
353 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
355 if ( node
->GetData()->GetId() == id
)
361 if ( !node
|| !DoDeleteTool(pos
, node
->GetData()) )
366 delete node
->GetData();
372 wxToolBarToolBase
*wxToolBarBase::FindById(int id
) const
374 wxToolBarToolBase
*tool
= (wxToolBarToolBase
*)NULL
;
376 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
378 node
= node
->GetNext() )
380 tool
= node
->GetData();
381 if ( tool
->GetId() == id
)
393 void wxToolBarBase::UnToggleRadioGroup(wxToolBarToolBase
*tool
)
395 wxCHECK_RET( tool
, _T("NULL tool in wxToolBarTool::UnToggleRadioGroup") );
397 if ( !tool
->IsButton() || tool
->GetKind() != wxITEM_RADIO
)
400 wxToolBarToolsList::compatibility_iterator node
= m_tools
.Find(tool
);
401 wxCHECK_RET( node
, _T("invalid tool in wxToolBarTool::UnToggleRadioGroup") );
403 wxToolBarToolsList::compatibility_iterator nodeNext
= node
->GetNext();
406 wxToolBarToolBase
*toolNext
= nodeNext
->GetData();
408 if ( !toolNext
->IsButton() || toolNext
->GetKind() != wxITEM_RADIO
)
411 if ( toolNext
->Toggle(false) )
413 DoToggleTool(toolNext
, false);
416 nodeNext
= nodeNext
->GetNext();
419 wxToolBarToolsList::compatibility_iterator nodePrev
= node
->GetPrevious();
422 wxToolBarToolBase
*toolNext
= nodePrev
->GetData();
424 if ( !toolNext
->IsButton() || toolNext
->GetKind() != wxITEM_RADIO
)
427 if ( toolNext
->Toggle(false) )
429 DoToggleTool(toolNext
, false);
432 nodePrev
= nodePrev
->GetPrevious();
436 void wxToolBarBase::ClearTools()
438 while ( GetToolsCount() )
444 bool wxToolBarBase::Realize()
449 wxToolBarBase::~wxToolBarBase()
451 WX_CLEAR_LIST(wxToolBarToolsList
, m_tools
);
453 // notify the frame that it doesn't have a tool bar any longer to avoid
455 wxFrame
*frame
= wxDynamicCast(GetParent(), wxFrame
);
456 if ( frame
&& frame
->GetToolBar() == this )
458 frame
->SetToolBar(NULL
);
462 // ----------------------------------------------------------------------------
463 // wxToolBarBase tools state
464 // ----------------------------------------------------------------------------
466 void wxToolBarBase::EnableTool(int id
, bool enable
)
468 wxToolBarToolBase
*tool
= FindById(id
);
471 if ( tool
->Enable(enable
) )
473 DoEnableTool(tool
, enable
);
478 void wxToolBarBase::ToggleTool(int id
, bool toggle
)
480 wxToolBarToolBase
*tool
= FindById(id
);
481 if ( tool
&& tool
->CanBeToggled() )
483 if ( tool
->Toggle(toggle
) )
485 UnToggleRadioGroup(tool
);
486 DoToggleTool(tool
, toggle
);
491 void wxToolBarBase::SetToggle(int id
, bool toggle
)
493 wxToolBarToolBase
*tool
= FindById(id
);
496 if ( tool
->SetToggle(toggle
) )
498 DoSetToggle(tool
, toggle
);
503 void wxToolBarBase::SetToolShortHelp(int id
, const wxString
& help
)
505 wxToolBarToolBase
*tool
= FindById(id
);
508 (void)tool
->SetShortHelp(help
);
512 void wxToolBarBase::SetToolLongHelp(int id
, const wxString
& help
)
514 wxToolBarToolBase
*tool
= FindById(id
);
517 (void)tool
->SetLongHelp(help
);
521 wxObject
*wxToolBarBase::GetToolClientData(int id
) const
523 wxToolBarToolBase
*tool
= FindById(id
);
525 return tool
? tool
->GetClientData() : (wxObject
*)NULL
;
528 void wxToolBarBase::SetToolClientData(int id
, wxObject
*clientData
)
530 wxToolBarToolBase
*tool
= FindById(id
);
532 wxCHECK_RET( tool
, _T("no such tool in wxToolBar::SetToolClientData") );
534 tool
->SetClientData(clientData
);
537 int wxToolBarBase::GetToolPos(int id
) const
540 wxToolBarToolsList::compatibility_iterator node
;
542 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
544 if ( node
->GetData()->GetId() == id
)
553 bool wxToolBarBase::GetToolState(int id
) const
555 wxToolBarToolBase
*tool
= FindById(id
);
556 wxCHECK_MSG( tool
, false, _T("no such tool") );
558 return tool
->IsToggled();
561 bool wxToolBarBase::GetToolEnabled(int id
) const
563 wxToolBarToolBase
*tool
= FindById(id
);
564 wxCHECK_MSG( tool
, false, _T("no such tool") );
566 return tool
->IsEnabled();
569 wxString
wxToolBarBase::GetToolShortHelp(int id
) const
571 wxToolBarToolBase
*tool
= FindById(id
);
572 wxCHECK_MSG( tool
, wxEmptyString
, _T("no such tool") );
574 return tool
->GetShortHelp();
577 wxString
wxToolBarBase::GetToolLongHelp(int id
) const
579 wxToolBarToolBase
*tool
= FindById(id
);
580 wxCHECK_MSG( tool
, wxEmptyString
, _T("no such tool") );
582 return tool
->GetLongHelp();
585 // ----------------------------------------------------------------------------
586 // wxToolBarBase geometry
587 // ----------------------------------------------------------------------------
589 void wxToolBarBase::SetMargins(int x
, int y
)
595 void wxToolBarBase::SetRows(int WXUNUSED(nRows
))
600 bool wxToolBarBase::IsVertical() const
602 return HasFlag(wxTB_LEFT
| wxTB_RIGHT
);
606 // ----------------------------------------------------------------------------
608 // ----------------------------------------------------------------------------
610 // Only allow toggle if returns true
611 bool wxToolBarBase::OnLeftClick(int id
, bool toggleDown
)
613 wxCommandEvent
event(wxEVT_COMMAND_TOOL_CLICKED
, id
);
614 event
.SetEventObject(this);
616 // we use SetInt() to make wxCommandEvent::IsChecked() return toggleDown
617 event
.SetInt((int)toggleDown
);
619 // and SetExtraLong() for backwards compatibility
620 event
.SetExtraLong((long)toggleDown
);
622 // Send events to this toolbar instead (and thence up the window hierarchy)
623 GetEventHandler()->ProcessEvent(event
);
628 // Call when right button down.
629 void wxToolBarBase::OnRightClick(int id
,
633 wxCommandEvent
event(wxEVT_COMMAND_TOOL_RCLICKED
, id
);
634 event
.SetEventObject(this);
637 GetEventHandler()->ProcessEvent(event
);
640 // Called when the mouse cursor enters a tool bitmap (no button pressed).
641 // Argument is wxID_ANY if mouse is exiting the toolbar.
642 // Note that for this event, the id of the window is used,
643 // and the integer parameter of wxCommandEvent is used to retrieve
645 void wxToolBarBase::OnMouseEnter(int id
)
647 wxCommandEvent
event(wxEVT_COMMAND_TOOL_ENTER
, GetId());
648 event
.SetEventObject(this);
651 wxFrame
*frame
= wxDynamicCast(GetParent(), wxFrame
);
655 if ( id
!= wxID_ANY
)
657 const wxToolBarToolBase
* const tool
= FindById(id
);
659 help
= tool
->GetLongHelp();
662 // call DoGiveHelp() even if help string is empty to avoid showing the
663 // help for the previously selected tool when another one is selected
664 frame
->DoGiveHelp(help
, id
!= wxID_ANY
);
667 (void)GetEventHandler()->ProcessEvent(event
);
670 // ----------------------------------------------------------------------------
672 // ----------------------------------------------------------------------------
674 // Do the toolbar button updates (check for EVT_UPDATE_UI handlers)
675 void wxToolBarBase::UpdateWindowUI(long flags
)
677 wxWindowBase::UpdateWindowUI(flags
);
679 // don't waste time updating state of tools in a hidden toolbar
683 // There is no sense in updating the toolbar UI
684 // if the parent window is about to get destroyed
685 wxWindow
*tlw
= wxGetTopLevelParent( this );
686 if (tlw
&& wxPendingDelete
.Member( tlw
))
689 wxEvtHandler
* evtHandler
= GetEventHandler() ;
691 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
693 node
= node
->GetNext() )
695 int id
= node
->GetData()->GetId();
697 wxUpdateUIEvent
event(id
);
698 event
.SetEventObject(this);
700 if ( evtHandler
->ProcessEvent(event
) )
702 if ( event
.GetSetEnabled() )
703 EnableTool(id
, event
.GetEnabled());
704 if ( event
.GetSetChecked() )
705 ToggleTool(id
, event
.GetChecked());
707 if ( event
.GetSetText() )
714 bool wxToolBarBase::SetDropdownMenu(int toolid
, wxMenu
* menu
)
716 wxToolBarToolBase
* const tool
= FindById(toolid
);
717 wxCHECK_MSG( tool
, false, _T("invalid tool id") );
719 wxCHECK_MSG( tool
->GetKind() == wxITEM_DROPDOWN
, false,
720 _T("menu can be only associated with drop down tools") );
722 tool
->SetDropdownMenu(menu
);
727 #if WXWIN_COMPATIBILITY_2_8
729 bool wxCreateGreyedImage(const wxImage
& in
, wxImage
& out
)
732 out
= in
.ConvertToGreyscale();
735 #endif // wxUSE_IMAGE
739 #endif // WXWIN_COMPATIBILITY_2_8
741 #endif // wxUSE_TOOLBAR