1 /////////////////////////////////////////////////////////////////////////////
2 // Name: 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"
30 #include "wx/control.h"
37 #include "wx/settings.h"
40 #include "wx/toolbar.h"
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 bool wxToolBarToolBase::Enable(bool enable
)
65 if ( m_enabled
== enable
)
73 bool wxToolBarToolBase::Toggle(bool toggle
)
75 wxASSERT_MSG( CanBeToggled(), _T("can't toggle this tool") );
77 if ( m_toggled
== toggle
)
85 bool wxToolBarToolBase::SetToggle(bool toggle
)
87 wxItemKind kind
= toggle
? wxITEM_CHECK
: wxITEM_NORMAL
;
96 bool wxToolBarToolBase::SetShortHelp(const wxString
& help
)
98 if ( m_shortHelpString
== help
)
101 m_shortHelpString
= help
;
106 bool wxToolBarToolBase::SetLongHelp(const wxString
& help
)
108 if ( m_longHelpString
== help
)
111 m_longHelpString
= help
;
116 #if WXWIN_COMPATIBILITY_2_2
118 const wxBitmap
& wxToolBarToolBase::GetBitmap1() const
120 return GetNormalBitmap();
123 const wxBitmap
& wxToolBarToolBase::GetBitmap2() const
125 return GetDisabledBitmap();
128 void wxToolBarToolBase::SetBitmap1(const wxBitmap
& bmp
)
130 SetNormalBitmap(bmp
);
133 void wxToolBarToolBase::SetBitmap2(const wxBitmap
& bmp
)
135 SetDisabledBitmap(bmp
);
138 #endif // WXWIN_COMPATIBILITY_2_2
140 // ----------------------------------------------------------------------------
141 // wxToolBarBase adding/deleting items
142 // ----------------------------------------------------------------------------
144 wxToolBarBase::wxToolBarBase()
146 // the list owns the pointers
147 m_xMargin
= m_yMargin
= 0;
148 m_maxRows
= m_maxCols
= 0;
149 m_toolPacking
= m_toolSeparation
= 0;
151 m_defaultHeight
= 15;
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(), (wxToolBarToolBase
*)NULL
,
181 _T("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(), (wxToolBarToolBase
*)NULL
,
205 _T("invalid position in wxToolBar::InsertTool()") );
207 if ( !tool
|| !DoInsertTool(pos
, tool
) )
212 m_tools
.Insert(pos
, tool
);
217 wxToolBarToolBase
*wxToolBarBase::AddControl(wxControl
*control
)
219 return InsertControl(GetToolsCount(), control
);
222 wxToolBarToolBase
*wxToolBarBase::InsertControl(size_t pos
, wxControl
*control
)
224 wxCHECK_MSG( control
, (wxToolBarToolBase
*)NULL
,
225 _T("toolbar: can't insert NULL control") );
227 wxCHECK_MSG( control
->GetParent() == this, (wxToolBarToolBase
*)NULL
,
228 _T("control must have toolbar as parent") );
230 wxCHECK_MSG( pos
<= GetToolsCount(), (wxToolBarToolBase
*)NULL
,
231 _T("invalid position in wxToolBar::InsertControl()") );
233 wxToolBarToolBase
*tool
= CreateTool(control
);
235 if ( !InsertTool(pos
, tool
) )
245 wxControl
*wxToolBarBase::FindControl( int id
)
247 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
249 node
= node
->GetNext() )
251 const wxToolBarToolBase
* const tool
= node
->GetData();
252 if ( tool
->IsControl() )
254 wxControl
* const control
= tool
->GetControl();
258 wxFAIL_MSG( _T("NULL control in toolbar?") );
260 else if ( control
->GetId() == id
)
271 wxToolBarToolBase
*wxToolBarBase::AddSeparator()
273 return InsertSeparator(GetToolsCount());
276 wxToolBarToolBase
*wxToolBarBase::InsertSeparator(size_t pos
)
278 wxCHECK_MSG( pos
<= GetToolsCount(), (wxToolBarToolBase
*)NULL
,
279 _T("invalid position in wxToolBar::InsertSeparator()") );
281 wxToolBarToolBase
*tool
= CreateTool(wxID_SEPARATOR
,
283 wxNullBitmap
, wxNullBitmap
,
284 wxITEM_SEPARATOR
, (wxObject
*)NULL
,
285 wxEmptyString
, wxEmptyString
);
287 if ( !tool
|| !DoInsertTool(pos
, tool
) )
294 m_tools
.Insert(pos
, tool
);
299 wxToolBarToolBase
*wxToolBarBase::RemoveTool(int id
)
302 wxToolBarToolsList::compatibility_iterator node
;
303 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
305 if ( node
->GetData()->GetId() == id
)
313 // don't give any error messages - sometimes we might call RemoveTool()
314 // without knowing whether the tool is or not in the toolbar
315 return (wxToolBarToolBase
*)NULL
;
318 wxToolBarToolBase
*tool
= node
->GetData();
319 if ( !DoDeleteTool(pos
, tool
) )
321 return (wxToolBarToolBase
*)NULL
;
329 bool wxToolBarBase::DeleteToolByPos(size_t pos
)
331 wxCHECK_MSG( pos
< GetToolsCount(), false,
332 _T("invalid position in wxToolBar::DeleteToolByPos()") );
334 wxToolBarToolsList::compatibility_iterator node
= m_tools
.Item(pos
);
336 if ( !DoDeleteTool(pos
, node
->GetData()) )
341 delete node
->GetData();
347 bool wxToolBarBase::DeleteTool(int id
)
350 wxToolBarToolsList::compatibility_iterator node
;
351 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
353 if ( node
->GetData()->GetId() == id
)
359 if ( !node
|| !DoDeleteTool(pos
, node
->GetData()) )
364 delete node
->GetData();
370 wxToolBarToolBase
*wxToolBarBase::FindById(int id
) const
372 wxToolBarToolBase
*tool
= (wxToolBarToolBase
*)NULL
;
374 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
376 node
= node
->GetNext() )
378 tool
= node
->GetData();
379 if ( tool
->GetId() == id
)
391 void wxToolBarBase::UnToggleRadioGroup(wxToolBarToolBase
*tool
)
393 wxCHECK_RET( tool
, _T("NULL tool in wxToolBarTool::UnToggleRadioGroup") );
395 if ( !tool
->IsButton() || tool
->GetKind() != wxITEM_RADIO
)
398 wxToolBarToolsList::compatibility_iterator node
= m_tools
.Find(tool
);
399 wxCHECK_RET( node
, _T("invalid tool in wxToolBarTool::UnToggleRadioGroup") );
401 wxToolBarToolsList::compatibility_iterator nodeNext
= node
->GetNext();
404 wxToolBarToolBase
*toolNext
= nodeNext
->GetData();
406 if ( !toolNext
->IsButton() || toolNext
->GetKind() != wxITEM_RADIO
)
409 if ( toolNext
->Toggle(false) )
411 DoToggleTool(toolNext
, false);
414 nodeNext
= nodeNext
->GetNext();
417 wxToolBarToolsList::compatibility_iterator nodePrev
= node
->GetPrevious();
420 wxToolBarToolBase
*toolNext
= nodePrev
->GetData();
422 if ( !toolNext
->IsButton() || toolNext
->GetKind() != wxITEM_RADIO
)
425 if ( toolNext
->Toggle(false) )
427 DoToggleTool(toolNext
, false);
430 nodePrev
= nodePrev
->GetPrevious();
434 void wxToolBarBase::ClearTools()
436 WX_CLEAR_LIST(wxToolBarToolsList
, m_tools
);
439 bool wxToolBarBase::Realize()
444 wxToolBarBase::~wxToolBarBase()
446 WX_CLEAR_LIST(wxToolBarToolsList
, m_tools
);
448 // notify the frame that it doesn't have a tool bar any longer to avoid
450 wxFrame
*frame
= wxDynamicCast(GetParent(), wxFrame
);
451 if ( frame
&& frame
->GetToolBar() == this )
453 frame
->SetToolBar(NULL
);
457 // ----------------------------------------------------------------------------
458 // wxToolBarBase tools state
459 // ----------------------------------------------------------------------------
461 void wxToolBarBase::EnableTool(int id
, bool enable
)
463 wxToolBarToolBase
*tool
= FindById(id
);
466 if ( tool
->Enable(enable
) )
468 DoEnableTool(tool
, enable
);
473 void wxToolBarBase::ToggleTool(int id
, bool toggle
)
475 wxToolBarToolBase
*tool
= FindById(id
);
476 if ( tool
&& tool
->CanBeToggled() )
478 if ( tool
->Toggle(toggle
) )
480 UnToggleRadioGroup(tool
);
481 DoToggleTool(tool
, toggle
);
486 void wxToolBarBase::SetToggle(int id
, bool toggle
)
488 wxToolBarToolBase
*tool
= FindById(id
);
491 if ( tool
->SetToggle(toggle
) )
493 DoSetToggle(tool
, toggle
);
498 void wxToolBarBase::SetToolShortHelp(int id
, const wxString
& help
)
500 wxToolBarToolBase
*tool
= FindById(id
);
503 (void)tool
->SetShortHelp(help
);
507 void wxToolBarBase::SetToolLongHelp(int id
, const wxString
& help
)
509 wxToolBarToolBase
*tool
= FindById(id
);
512 (void)tool
->SetLongHelp(help
);
516 wxObject
*wxToolBarBase::GetToolClientData(int id
) const
518 wxToolBarToolBase
*tool
= FindById(id
);
520 return tool
? tool
->GetClientData() : (wxObject
*)NULL
;
523 void wxToolBarBase::SetToolClientData(int id
, wxObject
*clientData
)
525 wxToolBarToolBase
*tool
= FindById(id
);
527 wxCHECK_RET( tool
, _T("no such tool in wxToolBar::SetToolClientData") );
529 tool
->SetClientData(clientData
);
532 int wxToolBarBase::GetToolPos(int id
) const
535 wxToolBarToolsList::compatibility_iterator node
;
537 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
539 if ( node
->GetData()->GetId() == id
)
548 bool wxToolBarBase::GetToolState(int id
) const
550 wxToolBarToolBase
*tool
= FindById(id
);
551 wxCHECK_MSG( tool
, false, _T("no such tool") );
553 return tool
->IsToggled();
556 bool wxToolBarBase::GetToolEnabled(int id
) const
558 wxToolBarToolBase
*tool
= FindById(id
);
559 wxCHECK_MSG( tool
, false, _T("no such tool") );
561 return tool
->IsEnabled();
564 wxString
wxToolBarBase::GetToolShortHelp(int id
) const
566 wxToolBarToolBase
*tool
= FindById(id
);
567 wxCHECK_MSG( tool
, wxEmptyString
, _T("no such tool") );
569 return tool
->GetShortHelp();
572 wxString
wxToolBarBase::GetToolLongHelp(int id
) const
574 wxToolBarToolBase
*tool
= FindById(id
);
575 wxCHECK_MSG( tool
, wxEmptyString
, _T("no such tool") );
577 return tool
->GetLongHelp();
580 // ----------------------------------------------------------------------------
581 // wxToolBarBase geometry
582 // ----------------------------------------------------------------------------
584 void wxToolBarBase::SetMargins(int x
, int y
)
590 void wxToolBarBase::SetRows(int WXUNUSED(nRows
))
595 // ----------------------------------------------------------------------------
597 // ----------------------------------------------------------------------------
599 // Only allow toggle if returns true
600 bool wxToolBarBase::OnLeftClick(int id
, bool toggleDown
)
602 wxCommandEvent
event(wxEVT_COMMAND_TOOL_CLICKED
, id
);
603 event
.SetEventObject(this);
605 // we use SetInt() to make wxCommandEvent::IsChecked() return toggleDown
606 event
.SetInt((int)toggleDown
);
608 // and SetExtraLong() for backwards compatibility
609 event
.SetExtraLong((long)toggleDown
);
611 // Send events to this toolbar instead (and thence up the window hierarchy)
612 GetEventHandler()->ProcessEvent(event
);
617 // Call when right button down.
618 void wxToolBarBase::OnRightClick(int id
,
622 wxCommandEvent
event(wxEVT_COMMAND_TOOL_RCLICKED
, id
);
623 event
.SetEventObject(this);
626 GetEventHandler()->ProcessEvent(event
);
629 // Called when the mouse cursor enters a tool bitmap (no button pressed).
630 // Argument is wxID_ANY if mouse is exiting the toolbar.
631 // Note that for this event, the id of the window is used,
632 // and the integer parameter of wxCommandEvent is used to retrieve
634 void wxToolBarBase::OnMouseEnter(int id
)
636 wxCommandEvent
event(wxEVT_COMMAND_TOOL_ENTER
, GetId());
637 event
.SetEventObject(this);
640 wxFrame
*frame
= wxDynamicCast(GetParent(), wxFrame
);
644 wxToolBarToolBase
* tool
= id
== wxID_ANY
? (wxToolBarToolBase
*)NULL
: FindById(id
);
646 help
= tool
->GetLongHelp();
647 frame
->DoGiveHelp( help
, id
!= wxID_ANY
);
650 (void)GetEventHandler()->ProcessEvent(event
);
653 // ----------------------------------------------------------------------------
655 // ----------------------------------------------------------------------------
657 // Do the toolbar button updates (check for EVT_UPDATE_UI handlers)
658 void wxToolBarBase::UpdateWindowUI(long flags
)
660 wxWindowBase::UpdateWindowUI(flags
);
662 // There is no sense in updating the toolbar UI
663 // if the parent window is about to get destroyed
664 wxWindow
*tlw
= wxGetTopLevelParent( this );
665 if (tlw
&& wxPendingDelete
.Member( tlw
))
668 wxEvtHandler
* evtHandler
= GetEventHandler() ;
670 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
672 node
= node
->GetNext() )
674 int id
= node
->GetData()->GetId();
676 wxUpdateUIEvent
event(id
);
677 event
.SetEventObject(this);
679 if ( evtHandler
->ProcessEvent(event
) )
681 if ( event
.GetSetEnabled() )
682 EnableTool(id
, event
.GetEnabled());
683 if ( event
.GetSetChecked() )
684 ToggleTool(id
, event
.GetChecked());
686 if ( event
.GetSetText() )
696 * Make a greyed-out image suitable for disabled buttons.
697 * This code is adapted from wxNewBitmapButton in FL.
700 bool wxCreateGreyedImage(const wxImage
& src
, wxImage
& dst
)
704 unsigned char rBg
, gBg
, bBg
;
707 src
.GetOrFindMaskColour(&rBg
, &gBg
, &bBg
);
708 dst
.SetMaskColour(rBg
, gBg
, bBg
);
710 else // assuming the pixels along the edges are of the background color
712 rBg
= src
.GetRed(0, 0);
713 gBg
= src
.GetGreen(0, 0);
714 bBg
= src
.GetBlue(0, 0);
717 const wxColour
colBg(rBg
, gBg
, bBg
);
719 const wxColour colDark
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
);
720 const wxColour colLight
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT
);
722 // Second attempt, just making things monochrome
723 const int width
= src
.GetWidth();
724 const int height
= src
.GetHeight();
726 for ( int x
= 0; x
< width
; x
++ )
728 for ( int y
= 0; y
< height
; y
++ )
730 const int r
= src
.GetRed(x
, y
);
731 const int g
= src
.GetGreen(x
, y
);
732 const int b
= src
.GetBlue(x
, y
);
734 if ( r
== rBg
&& g
== gBg
&& b
== bBg
)
736 // Leave the background colour as-is
740 // Change light things to the background colour
742 if ( r
>= (colLight
.Red() - 50) &&
743 g
>= (colLight
.Green() - 50) &&
744 b
>= (colLight
.Blue() - 50) )
748 else // Change dark things to really dark
753 dst
.SetRGB(x
, y
, col
.Red(), col
.Green(), col
.Blue());
760 #endif // wxUSE_IMAGE
762 #endif // wxUSE_TOOLBAR