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"
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 bool wxToolBarToolBase::Enable(bool enable
)
64 if ( m_enabled
== enable
)
72 bool wxToolBarToolBase::Toggle(bool toggle
)
74 wxASSERT_MSG( CanBeToggled(), _T("can't toggle this tool") );
76 if ( m_toggled
== toggle
)
84 bool wxToolBarToolBase::SetToggle(bool toggle
)
86 wxItemKind kind
= toggle
? wxITEM_CHECK
: wxITEM_NORMAL
;
95 bool wxToolBarToolBase::SetShortHelp(const wxString
& help
)
97 if ( m_shortHelpString
== help
)
100 m_shortHelpString
= help
;
105 bool wxToolBarToolBase::SetLongHelp(const wxString
& help
)
107 if ( m_longHelpString
== help
)
110 m_longHelpString
= help
;
115 // ----------------------------------------------------------------------------
116 // wxToolBarBase adding/deleting items
117 // ----------------------------------------------------------------------------
119 wxToolBarBase::wxToolBarBase()
121 // the list owns the pointers
122 m_xMargin
= m_yMargin
= 0;
123 m_maxRows
= m_maxCols
= 0;
124 m_toolPacking
= m_toolSeparation
= 0;
126 m_defaultHeight
= 15;
129 wxToolBarToolBase
*wxToolBarBase::DoAddTool(int id
,
130 const wxString
& label
,
131 const wxBitmap
& bitmap
,
132 const wxBitmap
& bmpDisabled
,
134 const wxString
& shortHelp
,
135 const wxString
& longHelp
,
136 wxObject
*clientData
,
137 wxCoord
WXUNUSED(xPos
),
138 wxCoord
WXUNUSED(yPos
))
140 InvalidateBestSize();
141 return InsertTool(GetToolsCount(), id
, label
, bitmap
, bmpDisabled
,
142 kind
, shortHelp
, longHelp
, clientData
);
145 wxToolBarToolBase
*wxToolBarBase::InsertTool(size_t pos
,
147 const wxString
& label
,
148 const wxBitmap
& bitmap
,
149 const wxBitmap
& bmpDisabled
,
151 const wxString
& shortHelp
,
152 const wxString
& longHelp
,
153 wxObject
*clientData
)
155 wxCHECK_MSG( pos
<= GetToolsCount(), (wxToolBarToolBase
*)NULL
,
156 _T("invalid position in wxToolBar::InsertTool()") );
158 wxToolBarToolBase
*tool
= CreateTool(id
, label
, bitmap
, bmpDisabled
, kind
,
159 clientData
, shortHelp
, longHelp
);
161 if ( !InsertTool(pos
, tool
) )
171 wxToolBarToolBase
*wxToolBarBase::AddTool(wxToolBarToolBase
*tool
)
173 return InsertTool(GetToolsCount(), tool
);
177 wxToolBarBase::InsertTool(size_t pos
, wxToolBarToolBase
*tool
)
179 wxCHECK_MSG( pos
<= GetToolsCount(), (wxToolBarToolBase
*)NULL
,
180 _T("invalid position in wxToolBar::InsertTool()") );
182 if ( !tool
|| !DoInsertTool(pos
, tool
) )
187 m_tools
.Insert(pos
, tool
);
192 wxToolBarToolBase
*wxToolBarBase::AddControl(wxControl
*control
)
194 return InsertControl(GetToolsCount(), control
);
197 wxToolBarToolBase
*wxToolBarBase::InsertControl(size_t pos
, wxControl
*control
)
199 wxCHECK_MSG( control
, (wxToolBarToolBase
*)NULL
,
200 _T("toolbar: can't insert NULL control") );
202 wxCHECK_MSG( control
->GetParent() == this, (wxToolBarToolBase
*)NULL
,
203 _T("control must have toolbar as parent") );
205 wxCHECK_MSG( pos
<= GetToolsCount(), (wxToolBarToolBase
*)NULL
,
206 _T("invalid position in wxToolBar::InsertControl()") );
208 wxToolBarToolBase
*tool
= CreateTool(control
);
210 if ( !InsertTool(pos
, tool
) )
220 wxControl
*wxToolBarBase::FindControl( int id
)
222 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
224 node
= node
->GetNext() )
226 const wxToolBarToolBase
* const tool
= node
->GetData();
227 if ( tool
->IsControl() )
229 wxControl
* const control
= tool
->GetControl();
233 wxFAIL_MSG( _T("NULL control in toolbar?") );
235 else if ( control
->GetId() == id
)
246 wxToolBarToolBase
*wxToolBarBase::AddSeparator()
248 return InsertSeparator(GetToolsCount());
251 wxToolBarToolBase
*wxToolBarBase::InsertSeparator(size_t pos
)
253 wxCHECK_MSG( pos
<= GetToolsCount(), (wxToolBarToolBase
*)NULL
,
254 _T("invalid position in wxToolBar::InsertSeparator()") );
256 wxToolBarToolBase
*tool
= CreateTool(wxID_SEPARATOR
,
258 wxNullBitmap
, wxNullBitmap
,
259 wxITEM_SEPARATOR
, (wxObject
*)NULL
,
260 wxEmptyString
, wxEmptyString
);
262 if ( !tool
|| !DoInsertTool(pos
, tool
) )
269 m_tools
.Insert(pos
, tool
);
274 wxToolBarToolBase
*wxToolBarBase::RemoveTool(int id
)
277 wxToolBarToolsList::compatibility_iterator node
;
278 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
280 if ( node
->GetData()->GetId() == id
)
288 // don't give any error messages - sometimes we might call RemoveTool()
289 // without knowing whether the tool is or not in the toolbar
290 return (wxToolBarToolBase
*)NULL
;
293 wxToolBarToolBase
*tool
= node
->GetData();
294 if ( !DoDeleteTool(pos
, tool
) )
296 return (wxToolBarToolBase
*)NULL
;
304 bool wxToolBarBase::DeleteToolByPos(size_t pos
)
306 wxCHECK_MSG( pos
< GetToolsCount(), false,
307 _T("invalid position in wxToolBar::DeleteToolByPos()") );
309 wxToolBarToolsList::compatibility_iterator node
= m_tools
.Item(pos
);
311 if ( !DoDeleteTool(pos
, node
->GetData()) )
316 delete node
->GetData();
322 bool wxToolBarBase::DeleteTool(int id
)
325 wxToolBarToolsList::compatibility_iterator node
;
326 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
328 if ( node
->GetData()->GetId() == id
)
334 if ( !node
|| !DoDeleteTool(pos
, node
->GetData()) )
339 delete node
->GetData();
345 wxToolBarToolBase
*wxToolBarBase::FindById(int id
) const
347 wxToolBarToolBase
*tool
= (wxToolBarToolBase
*)NULL
;
349 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
351 node
= node
->GetNext() )
353 tool
= node
->GetData();
354 if ( tool
->GetId() == id
)
366 void wxToolBarBase::UnToggleRadioGroup(wxToolBarToolBase
*tool
)
368 wxCHECK_RET( tool
, _T("NULL tool in wxToolBarTool::UnToggleRadioGroup") );
370 if ( !tool
->IsButton() || tool
->GetKind() != wxITEM_RADIO
)
373 wxToolBarToolsList::compatibility_iterator node
= m_tools
.Find(tool
);
374 wxCHECK_RET( node
, _T("invalid tool in wxToolBarTool::UnToggleRadioGroup") );
376 wxToolBarToolsList::compatibility_iterator nodeNext
= node
->GetNext();
379 wxToolBarToolBase
*toolNext
= nodeNext
->GetData();
381 if ( !toolNext
->IsButton() || toolNext
->GetKind() != wxITEM_RADIO
)
384 if ( toolNext
->Toggle(false) )
386 DoToggleTool(toolNext
, false);
389 nodeNext
= nodeNext
->GetNext();
392 wxToolBarToolsList::compatibility_iterator nodePrev
= node
->GetPrevious();
395 wxToolBarToolBase
*toolNext
= nodePrev
->GetData();
397 if ( !toolNext
->IsButton() || toolNext
->GetKind() != wxITEM_RADIO
)
400 if ( toolNext
->Toggle(false) )
402 DoToggleTool(toolNext
, false);
405 nodePrev
= nodePrev
->GetPrevious();
409 void wxToolBarBase::ClearTools()
411 while ( GetToolsCount() )
417 bool wxToolBarBase::Realize()
422 wxToolBarBase::~wxToolBarBase()
424 WX_CLEAR_LIST(wxToolBarToolsList
, m_tools
);
426 // notify the frame that it doesn't have a tool bar any longer to avoid
428 wxFrame
*frame
= wxDynamicCast(GetParent(), wxFrame
);
429 if ( frame
&& frame
->GetToolBar() == this )
431 frame
->SetToolBar(NULL
);
435 // ----------------------------------------------------------------------------
436 // wxToolBarBase tools state
437 // ----------------------------------------------------------------------------
439 void wxToolBarBase::EnableTool(int id
, bool enable
)
441 wxToolBarToolBase
*tool
= FindById(id
);
444 if ( tool
->Enable(enable
) )
446 DoEnableTool(tool
, enable
);
451 void wxToolBarBase::ToggleTool(int id
, bool toggle
)
453 wxToolBarToolBase
*tool
= FindById(id
);
454 if ( tool
&& tool
->CanBeToggled() )
456 if ( tool
->Toggle(toggle
) )
458 UnToggleRadioGroup(tool
);
459 DoToggleTool(tool
, toggle
);
464 void wxToolBarBase::SetToggle(int id
, bool toggle
)
466 wxToolBarToolBase
*tool
= FindById(id
);
469 if ( tool
->SetToggle(toggle
) )
471 DoSetToggle(tool
, toggle
);
476 void wxToolBarBase::SetToolShortHelp(int id
, const wxString
& help
)
478 wxToolBarToolBase
*tool
= FindById(id
);
481 (void)tool
->SetShortHelp(help
);
485 void wxToolBarBase::SetToolLongHelp(int id
, const wxString
& help
)
487 wxToolBarToolBase
*tool
= FindById(id
);
490 (void)tool
->SetLongHelp(help
);
494 wxObject
*wxToolBarBase::GetToolClientData(int id
) const
496 wxToolBarToolBase
*tool
= FindById(id
);
498 return tool
? tool
->GetClientData() : (wxObject
*)NULL
;
501 void wxToolBarBase::SetToolClientData(int id
, wxObject
*clientData
)
503 wxToolBarToolBase
*tool
= FindById(id
);
505 wxCHECK_RET( tool
, _T("no such tool in wxToolBar::SetToolClientData") );
507 tool
->SetClientData(clientData
);
510 int wxToolBarBase::GetToolPos(int id
) const
513 wxToolBarToolsList::compatibility_iterator node
;
515 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
517 if ( node
->GetData()->GetId() == id
)
526 bool wxToolBarBase::GetToolState(int id
) const
528 wxToolBarToolBase
*tool
= FindById(id
);
529 wxCHECK_MSG( tool
, false, _T("no such tool") );
531 return tool
->IsToggled();
534 bool wxToolBarBase::GetToolEnabled(int id
) const
536 wxToolBarToolBase
*tool
= FindById(id
);
537 wxCHECK_MSG( tool
, false, _T("no such tool") );
539 return tool
->IsEnabled();
542 wxString
wxToolBarBase::GetToolShortHelp(int id
) const
544 wxToolBarToolBase
*tool
= FindById(id
);
545 wxCHECK_MSG( tool
, wxEmptyString
, _T("no such tool") );
547 return tool
->GetShortHelp();
550 wxString
wxToolBarBase::GetToolLongHelp(int id
) const
552 wxToolBarToolBase
*tool
= FindById(id
);
553 wxCHECK_MSG( tool
, wxEmptyString
, _T("no such tool") );
555 return tool
->GetLongHelp();
558 // ----------------------------------------------------------------------------
559 // wxToolBarBase geometry
560 // ----------------------------------------------------------------------------
562 void wxToolBarBase::SetMargins(int x
, int y
)
568 void wxToolBarBase::SetRows(int WXUNUSED(nRows
))
573 // ----------------------------------------------------------------------------
575 // ----------------------------------------------------------------------------
577 // Only allow toggle if returns true
578 bool wxToolBarBase::OnLeftClick(int id
, bool toggleDown
)
580 wxCommandEvent
event(wxEVT_COMMAND_TOOL_CLICKED
, id
);
581 event
.SetEventObject(this);
583 // we use SetInt() to make wxCommandEvent::IsChecked() return toggleDown
584 event
.SetInt((int)toggleDown
);
586 // and SetExtraLong() for backwards compatibility
587 event
.SetExtraLong((long)toggleDown
);
589 // Send events to this toolbar instead (and thence up the window hierarchy)
590 GetEventHandler()->ProcessEvent(event
);
595 // Call when right button down.
596 void wxToolBarBase::OnRightClick(int id
,
600 wxCommandEvent
event(wxEVT_COMMAND_TOOL_RCLICKED
, id
);
601 event
.SetEventObject(this);
604 GetEventHandler()->ProcessEvent(event
);
607 // Called when the mouse cursor enters a tool bitmap (no button pressed).
608 // Argument is wxID_ANY if mouse is exiting the toolbar.
609 // Note that for this event, the id of the window is used,
610 // and the integer parameter of wxCommandEvent is used to retrieve
612 void wxToolBarBase::OnMouseEnter(int id
)
614 wxCommandEvent
event(wxEVT_COMMAND_TOOL_ENTER
, GetId());
615 event
.SetEventObject(this);
618 wxFrame
*frame
= wxDynamicCast(GetParent(), wxFrame
);
622 wxToolBarToolBase
* tool
= id
== wxID_ANY
? (wxToolBarToolBase
*)NULL
: FindById(id
);
624 help
= tool
->GetLongHelp();
625 frame
->DoGiveHelp( help
, id
!= wxID_ANY
);
628 (void)GetEventHandler()->ProcessEvent(event
);
631 // ----------------------------------------------------------------------------
633 // ----------------------------------------------------------------------------
635 // Do the toolbar button updates (check for EVT_UPDATE_UI handlers)
636 void wxToolBarBase::UpdateWindowUI(long flags
)
638 wxWindowBase::UpdateWindowUI(flags
);
640 // There is no sense in updating the toolbar UI
641 // if the parent window is about to get destroyed
642 wxWindow
*tlw
= wxGetTopLevelParent( this );
643 if (tlw
&& wxPendingDelete
.Member( tlw
))
646 wxEvtHandler
* evtHandler
= GetEventHandler() ;
648 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
650 node
= node
->GetNext() )
652 int id
= node
->GetData()->GetId();
654 wxUpdateUIEvent
event(id
);
655 event
.SetEventObject(this);
657 if ( evtHandler
->ProcessEvent(event
) )
659 if ( event
.GetSetEnabled() )
660 EnableTool(id
, event
.GetEnabled());
661 if ( event
.GetSetChecked() )
662 ToggleTool(id
, event
.GetChecked());
664 if ( event
.GetSetText() )
674 * Make a greyed-out image suitable for disabled buttons.
675 * This code is adapted from wxNewBitmapButton in FL.
678 bool wxCreateGreyedImage(const wxImage
& src
, wxImage
& dst
)
682 unsigned char rBg
, gBg
, bBg
;
685 src
.GetOrFindMaskColour(&rBg
, &gBg
, &bBg
);
686 dst
.SetMaskColour(rBg
, gBg
, bBg
);
688 else // assuming the pixels along the edges are of the background color
690 rBg
= src
.GetRed(0, 0);
691 gBg
= src
.GetGreen(0, 0);
692 bBg
= src
.GetBlue(0, 0);
695 const wxColour
colBg(rBg
, gBg
, bBg
);
697 const wxColour colDark
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
);
698 const wxColour colLight
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT
);
700 // Second attempt, just making things monochrome
701 const int width
= src
.GetWidth();
702 const int height
= src
.GetHeight();
704 for ( int x
= 0; x
< width
; x
++ )
706 for ( int y
= 0; y
< height
; y
++ )
708 const int r
= src
.GetRed(x
, y
);
709 const int g
= src
.GetGreen(x
, y
);
710 const int b
= src
.GetBlue(x
, y
);
712 if ( r
== rBg
&& g
== gBg
&& b
== bBg
)
714 // Leave the background colour as-is
718 // Change light things to the background colour
720 if ( r
>= (colLight
.Red() - 50) &&
721 g
>= (colLight
.Green() - 50) &&
722 b
>= (colLight
.Blue() - 50) )
726 else // Change dark things to really dark
731 dst
.SetRGB(x
, y
, col
.Red(), col
.Green(), col
.Blue());
738 #endif // wxUSE_IMAGE
740 #endif // wxUSE_TOOLBAR