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"
38 // ----------------------------------------------------------------------------
40 // ----------------------------------------------------------------------------
42 BEGIN_EVENT_TABLE(wxToolBarBase
, wxControl
)
45 #include "wx/listimpl.cpp"
47 WX_DEFINE_LIST(wxToolBarToolsList
)
49 // ============================================================================
51 // ============================================================================
53 // ----------------------------------------------------------------------------
55 // ----------------------------------------------------------------------------
57 IMPLEMENT_DYNAMIC_CLASS(wxToolBarToolBase
, wxObject
)
59 bool wxToolBarToolBase::Enable(bool enable
)
61 if ( m_enabled
== enable
)
69 bool wxToolBarToolBase::Toggle(bool toggle
)
71 wxASSERT_MSG( CanBeToggled(), _T("can't toggle this tool") );
73 if ( m_toggled
== toggle
)
81 bool wxToolBarToolBase::SetToggle(bool toggle
)
83 wxItemKind kind
= toggle
? wxITEM_CHECK
: wxITEM_NORMAL
;
92 bool wxToolBarToolBase::SetShortHelp(const wxString
& help
)
94 if ( m_shortHelpString
== help
)
97 m_shortHelpString
= help
;
102 bool wxToolBarToolBase::SetLongHelp(const wxString
& help
)
104 if ( m_longHelpString
== help
)
107 m_longHelpString
= help
;
112 // ----------------------------------------------------------------------------
113 // wxToolBarBase adding/deleting items
114 // ----------------------------------------------------------------------------
116 wxToolBarBase::wxToolBarBase()
118 // the list owns the pointers
119 m_xMargin
= m_yMargin
= 0;
120 m_maxRows
= m_maxCols
= 0;
121 m_toolPacking
= m_toolSeparation
= 0;
123 m_defaultHeight
= 15;
126 void wxToolBarBase::FixupStyle()
128 if ( !HasFlag(wxTB_TOP
| wxTB_LEFT
| wxTB_RIGHT
| wxTB_BOTTOM
) )
130 // this is the default
131 m_windowStyle
|= wxTB_TOP
;
135 wxToolBarToolBase
*wxToolBarBase::DoAddTool(int id
,
136 const wxString
& label
,
137 const wxBitmap
& bitmap
,
138 const wxBitmap
& bmpDisabled
,
140 const wxString
& shortHelp
,
141 const wxString
& longHelp
,
142 wxObject
*clientData
,
143 wxCoord
WXUNUSED(xPos
),
144 wxCoord
WXUNUSED(yPos
))
146 InvalidateBestSize();
147 return InsertTool(GetToolsCount(), id
, label
, bitmap
, bmpDisabled
,
148 kind
, shortHelp
, longHelp
, clientData
);
151 wxToolBarToolBase
*wxToolBarBase::InsertTool(size_t pos
,
153 const wxString
& label
,
154 const wxBitmap
& bitmap
,
155 const wxBitmap
& bmpDisabled
,
157 const wxString
& shortHelp
,
158 const wxString
& longHelp
,
159 wxObject
*clientData
)
161 wxCHECK_MSG( pos
<= GetToolsCount(), (wxToolBarToolBase
*)NULL
,
162 _T("invalid position in wxToolBar::InsertTool()") );
164 wxToolBarToolBase
*tool
= CreateTool(id
, label
, bitmap
, bmpDisabled
, kind
,
165 clientData
, shortHelp
, longHelp
);
167 if ( !InsertTool(pos
, tool
) )
177 wxToolBarToolBase
*wxToolBarBase::AddTool(wxToolBarToolBase
*tool
)
179 return InsertTool(GetToolsCount(), tool
);
183 wxToolBarBase::InsertTool(size_t pos
, wxToolBarToolBase
*tool
)
185 wxCHECK_MSG( pos
<= GetToolsCount(), (wxToolBarToolBase
*)NULL
,
186 _T("invalid position in wxToolBar::InsertTool()") );
188 if ( !tool
|| !DoInsertTool(pos
, tool
) )
193 m_tools
.Insert(pos
, tool
);
198 wxToolBarToolBase
*wxToolBarBase::AddControl(wxControl
*control
)
200 return InsertControl(GetToolsCount(), control
);
203 wxToolBarToolBase
*wxToolBarBase::InsertControl(size_t pos
, wxControl
*control
)
205 wxCHECK_MSG( control
, (wxToolBarToolBase
*)NULL
,
206 _T("toolbar: can't insert NULL control") );
208 wxCHECK_MSG( control
->GetParent() == this, (wxToolBarToolBase
*)NULL
,
209 _T("control must have toolbar as parent") );
211 wxCHECK_MSG( pos
<= GetToolsCount(), (wxToolBarToolBase
*)NULL
,
212 _T("invalid position in wxToolBar::InsertControl()") );
214 wxToolBarToolBase
*tool
= CreateTool(control
);
216 if ( !InsertTool(pos
, tool
) )
226 wxControl
*wxToolBarBase::FindControl( int id
)
228 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
230 node
= node
->GetNext() )
232 const wxToolBarToolBase
* const tool
= node
->GetData();
233 if ( tool
->IsControl() )
235 wxControl
* const control
= tool
->GetControl();
239 wxFAIL_MSG( _T("NULL control in toolbar?") );
241 else if ( control
->GetId() == id
)
252 wxToolBarToolBase
*wxToolBarBase::AddSeparator()
254 return InsertSeparator(GetToolsCount());
257 wxToolBarToolBase
*wxToolBarBase::InsertSeparator(size_t pos
)
259 wxCHECK_MSG( pos
<= GetToolsCount(), (wxToolBarToolBase
*)NULL
,
260 _T("invalid position in wxToolBar::InsertSeparator()") );
262 wxToolBarToolBase
*tool
= CreateTool(wxID_SEPARATOR
,
264 wxNullBitmap
, wxNullBitmap
,
265 wxITEM_SEPARATOR
, (wxObject
*)NULL
,
266 wxEmptyString
, wxEmptyString
);
268 if ( !tool
|| !DoInsertTool(pos
, tool
) )
275 m_tools
.Insert(pos
, tool
);
280 wxToolBarToolBase
*wxToolBarBase::RemoveTool(int id
)
283 wxToolBarToolsList::compatibility_iterator node
;
284 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
286 if ( node
->GetData()->GetId() == id
)
294 // don't give any error messages - sometimes we might call RemoveTool()
295 // without knowing whether the tool is or not in the toolbar
296 return (wxToolBarToolBase
*)NULL
;
299 wxToolBarToolBase
*tool
= node
->GetData();
300 if ( !DoDeleteTool(pos
, tool
) )
302 return (wxToolBarToolBase
*)NULL
;
310 bool wxToolBarBase::DeleteToolByPos(size_t pos
)
312 wxCHECK_MSG( pos
< GetToolsCount(), false,
313 _T("invalid position in wxToolBar::DeleteToolByPos()") );
315 wxToolBarToolsList::compatibility_iterator node
= m_tools
.Item(pos
);
317 if ( !DoDeleteTool(pos
, node
->GetData()) )
322 delete node
->GetData();
328 bool wxToolBarBase::DeleteTool(int id
)
331 wxToolBarToolsList::compatibility_iterator node
;
332 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
334 if ( node
->GetData()->GetId() == id
)
340 if ( !node
|| !DoDeleteTool(pos
, node
->GetData()) )
345 delete node
->GetData();
351 wxToolBarToolBase
*wxToolBarBase::FindById(int id
) const
353 wxToolBarToolBase
*tool
= (wxToolBarToolBase
*)NULL
;
355 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
357 node
= node
->GetNext() )
359 tool
= node
->GetData();
360 if ( tool
->GetId() == id
)
372 void wxToolBarBase::UnToggleRadioGroup(wxToolBarToolBase
*tool
)
374 wxCHECK_RET( tool
, _T("NULL tool in wxToolBarTool::UnToggleRadioGroup") );
376 if ( !tool
->IsButton() || tool
->GetKind() != wxITEM_RADIO
)
379 wxToolBarToolsList::compatibility_iterator node
= m_tools
.Find(tool
);
380 wxCHECK_RET( node
, _T("invalid tool in wxToolBarTool::UnToggleRadioGroup") );
382 wxToolBarToolsList::compatibility_iterator nodeNext
= node
->GetNext();
385 wxToolBarToolBase
*toolNext
= nodeNext
->GetData();
387 if ( !toolNext
->IsButton() || toolNext
->GetKind() != wxITEM_RADIO
)
390 if ( toolNext
->Toggle(false) )
392 DoToggleTool(toolNext
, false);
395 nodeNext
= nodeNext
->GetNext();
398 wxToolBarToolsList::compatibility_iterator nodePrev
= node
->GetPrevious();
401 wxToolBarToolBase
*toolNext
= nodePrev
->GetData();
403 if ( !toolNext
->IsButton() || toolNext
->GetKind() != wxITEM_RADIO
)
406 if ( toolNext
->Toggle(false) )
408 DoToggleTool(toolNext
, false);
411 nodePrev
= nodePrev
->GetPrevious();
415 void wxToolBarBase::ClearTools()
417 while ( GetToolsCount() )
423 bool wxToolBarBase::Realize()
428 wxToolBarBase::~wxToolBarBase()
430 WX_CLEAR_LIST(wxToolBarToolsList
, m_tools
);
432 // notify the frame that it doesn't have a tool bar any longer to avoid
434 wxFrame
*frame
= wxDynamicCast(GetParent(), wxFrame
);
435 if ( frame
&& frame
->GetToolBar() == this )
437 frame
->SetToolBar(NULL
);
441 // ----------------------------------------------------------------------------
442 // wxToolBarBase tools state
443 // ----------------------------------------------------------------------------
445 void wxToolBarBase::EnableTool(int id
, bool enable
)
447 wxToolBarToolBase
*tool
= FindById(id
);
450 if ( tool
->Enable(enable
) )
452 DoEnableTool(tool
, enable
);
457 void wxToolBarBase::ToggleTool(int id
, bool toggle
)
459 wxToolBarToolBase
*tool
= FindById(id
);
460 if ( tool
&& tool
->CanBeToggled() )
462 if ( tool
->Toggle(toggle
) )
464 UnToggleRadioGroup(tool
);
465 DoToggleTool(tool
, toggle
);
470 void wxToolBarBase::SetToggle(int id
, bool toggle
)
472 wxToolBarToolBase
*tool
= FindById(id
);
475 if ( tool
->SetToggle(toggle
) )
477 DoSetToggle(tool
, toggle
);
482 void wxToolBarBase::SetToolShortHelp(int id
, const wxString
& help
)
484 wxToolBarToolBase
*tool
= FindById(id
);
487 (void)tool
->SetShortHelp(help
);
491 void wxToolBarBase::SetToolLongHelp(int id
, const wxString
& help
)
493 wxToolBarToolBase
*tool
= FindById(id
);
496 (void)tool
->SetLongHelp(help
);
500 wxObject
*wxToolBarBase::GetToolClientData(int id
) const
502 wxToolBarToolBase
*tool
= FindById(id
);
504 return tool
? tool
->GetClientData() : (wxObject
*)NULL
;
507 void wxToolBarBase::SetToolClientData(int id
, wxObject
*clientData
)
509 wxToolBarToolBase
*tool
= FindById(id
);
511 wxCHECK_RET( tool
, _T("no such tool in wxToolBar::SetToolClientData") );
513 tool
->SetClientData(clientData
);
516 int wxToolBarBase::GetToolPos(int id
) const
519 wxToolBarToolsList::compatibility_iterator node
;
521 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
523 if ( node
->GetData()->GetId() == id
)
532 bool wxToolBarBase::GetToolState(int id
) const
534 wxToolBarToolBase
*tool
= FindById(id
);
535 wxCHECK_MSG( tool
, false, _T("no such tool") );
537 return tool
->IsToggled();
540 bool wxToolBarBase::GetToolEnabled(int id
) const
542 wxToolBarToolBase
*tool
= FindById(id
);
543 wxCHECK_MSG( tool
, false, _T("no such tool") );
545 return tool
->IsEnabled();
548 wxString
wxToolBarBase::GetToolShortHelp(int id
) const
550 wxToolBarToolBase
*tool
= FindById(id
);
551 wxCHECK_MSG( tool
, wxEmptyString
, _T("no such tool") );
553 return tool
->GetShortHelp();
556 wxString
wxToolBarBase::GetToolLongHelp(int id
) const
558 wxToolBarToolBase
*tool
= FindById(id
);
559 wxCHECK_MSG( tool
, wxEmptyString
, _T("no such tool") );
561 return tool
->GetLongHelp();
564 // ----------------------------------------------------------------------------
565 // wxToolBarBase geometry
566 // ----------------------------------------------------------------------------
568 void wxToolBarBase::SetMargins(int x
, int y
)
574 void wxToolBarBase::SetRows(int WXUNUSED(nRows
))
579 // ----------------------------------------------------------------------------
581 // ----------------------------------------------------------------------------
583 // Only allow toggle if returns true
584 bool wxToolBarBase::OnLeftClick(int id
, bool toggleDown
)
586 wxCommandEvent
event(wxEVT_COMMAND_TOOL_CLICKED
, id
);
587 event
.SetEventObject(this);
589 // we use SetInt() to make wxCommandEvent::IsChecked() return toggleDown
590 event
.SetInt((int)toggleDown
);
592 // and SetExtraLong() for backwards compatibility
593 event
.SetExtraLong((long)toggleDown
);
595 // Send events to this toolbar instead (and thence up the window hierarchy)
596 GetEventHandler()->ProcessEvent(event
);
601 // Call when right button down.
602 void wxToolBarBase::OnRightClick(int id
,
606 wxCommandEvent
event(wxEVT_COMMAND_TOOL_RCLICKED
, id
);
607 event
.SetEventObject(this);
610 GetEventHandler()->ProcessEvent(event
);
613 // Called when the mouse cursor enters a tool bitmap (no button pressed).
614 // Argument is wxID_ANY if mouse is exiting the toolbar.
615 // Note that for this event, the id of the window is used,
616 // and the integer parameter of wxCommandEvent is used to retrieve
618 void wxToolBarBase::OnMouseEnter(int id
)
620 wxCommandEvent
event(wxEVT_COMMAND_TOOL_ENTER
, GetId());
621 event
.SetEventObject(this);
624 wxFrame
*frame
= wxDynamicCast(GetParent(), wxFrame
);
628 wxToolBarToolBase
* tool
= id
== wxID_ANY
? (wxToolBarToolBase
*)NULL
: FindById(id
);
630 help
= tool
->GetLongHelp();
631 frame
->DoGiveHelp( help
, id
!= wxID_ANY
);
634 (void)GetEventHandler()->ProcessEvent(event
);
637 // ----------------------------------------------------------------------------
639 // ----------------------------------------------------------------------------
641 // Do the toolbar button updates (check for EVT_UPDATE_UI handlers)
642 void wxToolBarBase::UpdateWindowUI(long flags
)
644 wxWindowBase::UpdateWindowUI(flags
);
646 // There is no sense in updating the toolbar UI
647 // if the parent window is about to get destroyed
648 wxWindow
*tlw
= wxGetTopLevelParent( this );
649 if (tlw
&& wxPendingDelete
.Member( tlw
))
652 wxEvtHandler
* evtHandler
= GetEventHandler() ;
654 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
656 node
= node
->GetNext() )
658 int id
= node
->GetData()->GetId();
660 wxUpdateUIEvent
event(id
);
661 event
.SetEventObject(this);
663 if ( evtHandler
->ProcessEvent(event
) )
665 if ( event
.GetSetEnabled() )
666 EnableTool(id
, event
.GetEnabled());
667 if ( event
.GetSetChecked() )
668 ToggleTool(id
, event
.GetChecked());
670 if ( event
.GetSetText() )
680 * Make a greyed-out image suitable for disabled buttons.
681 * This code is adapted from wxNewBitmapButton in FL.
684 bool wxCreateGreyedImage(const wxImage
& src
, wxImage
& dst
)
688 unsigned char rBg
, gBg
, bBg
;
691 src
.GetOrFindMaskColour(&rBg
, &gBg
, &bBg
);
692 dst
.SetMaskColour(rBg
, gBg
, bBg
);
694 else // assuming the pixels along the edges are of the background color
696 rBg
= src
.GetRed(0, 0);
697 gBg
= src
.GetGreen(0, 0);
698 bBg
= src
.GetBlue(0, 0);
701 const wxColour
colBg(rBg
, gBg
, bBg
);
703 const wxColour colDark
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
);
704 const wxColour colLight
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT
);
706 // Second attempt, just making things monochrome
707 const int width
= src
.GetWidth();
708 const int height
= src
.GetHeight();
710 for ( int x
= 0; x
< width
; x
++ )
712 for ( int y
= 0; y
< height
; y
++ )
714 const int r
= src
.GetRed(x
, y
);
715 const int g
= src
.GetGreen(x
, y
);
716 const int b
= src
.GetBlue(x
, y
);
718 if ( r
== rBg
&& g
== gBg
&& b
== bBg
)
720 // Leave the background colour as-is
724 // Change light things to the background colour
726 if ( r
>= (colLight
.Red() - 50) &&
727 g
>= (colLight
.Green() - 50) &&
728 b
>= (colLight
.Blue() - 50) )
732 else // Change dark things to really dark
737 dst
.SetRGB(x
, y
, col
.Red(), col
.Green(), col
.Blue());
744 #endif // wxUSE_IMAGE
746 #endif // wxUSE_TOOLBAR