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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "tbarbase.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
34 #include "wx/control.h"
41 #include "wx/settings.h"
44 #include "wx/toolbar.h"
46 // ----------------------------------------------------------------------------
48 // ----------------------------------------------------------------------------
50 BEGIN_EVENT_TABLE(wxToolBarBase
, wxControl
)
53 #include "wx/listimpl.cpp"
55 WX_DEFINE_LIST(wxToolBarToolsList
);
57 // ============================================================================
59 // ============================================================================
61 // ----------------------------------------------------------------------------
63 // ----------------------------------------------------------------------------
65 IMPLEMENT_DYNAMIC_CLASS(wxToolBarToolBase
, wxObject
)
67 bool wxToolBarToolBase::Enable(bool enable
)
69 if ( m_enabled
== enable
)
77 bool wxToolBarToolBase::Toggle(bool toggle
)
79 wxASSERT_MSG( CanBeToggled(), _T("can't toggle this tool") );
81 if ( m_toggled
== toggle
)
89 bool wxToolBarToolBase::SetToggle(bool toggle
)
91 wxItemKind kind
= toggle
? wxITEM_CHECK
: wxITEM_NORMAL
;
100 bool wxToolBarToolBase::SetShortHelp(const wxString
& help
)
102 if ( m_shortHelpString
== help
)
105 m_shortHelpString
= help
;
110 bool wxToolBarToolBase::SetLongHelp(const wxString
& help
)
112 if ( m_longHelpString
== help
)
115 m_longHelpString
= help
;
120 #if WXWIN_COMPATIBILITY_2_2
122 const wxBitmap
& wxToolBarToolBase::GetBitmap1() const
124 return GetNormalBitmap();
127 const wxBitmap
& wxToolBarToolBase::GetBitmap2() const
129 return GetDisabledBitmap();
132 void wxToolBarToolBase::SetBitmap1(const wxBitmap
& bmp
)
134 SetNormalBitmap(bmp
);
137 void wxToolBarToolBase::SetBitmap2(const wxBitmap
& bmp
)
139 SetDisabledBitmap(bmp
);
142 #endif // WXWIN_COMPATIBILITY_2_2
144 // ----------------------------------------------------------------------------
145 // wxToolBarBase adding/deleting items
146 // ----------------------------------------------------------------------------
148 wxToolBarBase::wxToolBarBase()
150 // the list owns the pointers
151 m_xMargin
= m_yMargin
= 0;
152 m_maxRows
= m_maxCols
= 0;
153 m_toolPacking
= m_toolSeparation
= 0;
155 m_defaultHeight
= 15;
158 wxToolBarToolBase
*wxToolBarBase::DoAddTool(int id
,
159 const wxString
& label
,
160 const wxBitmap
& bitmap
,
161 const wxBitmap
& bmpDisabled
,
163 const wxString
& shortHelp
,
164 const wxString
& longHelp
,
165 wxObject
*clientData
,
166 wxCoord
WXUNUSED(xPos
),
167 wxCoord
WXUNUSED(yPos
))
169 InvalidateBestSize();
170 return InsertTool(GetToolsCount(), id
, label
, bitmap
, bmpDisabled
,
171 kind
, shortHelp
, longHelp
, clientData
);
174 wxToolBarToolBase
*wxToolBarBase::InsertTool(size_t pos
,
176 const wxString
& label
,
177 const wxBitmap
& bitmap
,
178 const wxBitmap
& bmpDisabled
,
180 const wxString
& shortHelp
,
181 const wxString
& longHelp
,
182 wxObject
*clientData
)
184 wxCHECK_MSG( pos
<= GetToolsCount(), (wxToolBarToolBase
*)NULL
,
185 _T("invalid position in wxToolBar::InsertTool()") );
187 wxToolBarToolBase
*tool
= CreateTool(id
, label
, bitmap
, bmpDisabled
, kind
,
188 clientData
, shortHelp
, longHelp
);
190 if ( !InsertTool(pos
, tool
) )
200 wxToolBarToolBase
*wxToolBarBase::AddTool(wxToolBarToolBase
*tool
)
202 return InsertTool(GetToolsCount(), tool
);
206 wxToolBarBase::InsertTool(size_t pos
, wxToolBarToolBase
*tool
)
208 wxCHECK_MSG( pos
<= GetToolsCount(), (wxToolBarToolBase
*)NULL
,
209 _T("invalid position in wxToolBar::InsertTool()") );
211 if ( !tool
|| !DoInsertTool(pos
, tool
) )
216 m_tools
.Insert(pos
, tool
);
221 wxToolBarToolBase
*wxToolBarBase::AddControl(wxControl
*control
)
223 return InsertControl(GetToolsCount(), control
);
226 wxToolBarToolBase
*wxToolBarBase::InsertControl(size_t pos
, wxControl
*control
)
228 wxCHECK_MSG( control
, (wxToolBarToolBase
*)NULL
,
229 _T("toolbar: can't insert NULL control") );
231 wxCHECK_MSG( control
->GetParent() == this, (wxToolBarToolBase
*)NULL
,
232 _T("control must have toolbar as parent") );
234 wxCHECK_MSG( pos
<= GetToolsCount(), (wxToolBarToolBase
*)NULL
,
235 _T("invalid position in wxToolBar::InsertControl()") );
237 wxToolBarToolBase
*tool
= CreateTool(control
);
239 if ( !InsertTool(pos
, tool
) )
249 wxControl
*wxToolBarBase::FindControl( int id
)
251 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
253 node
= node
->GetNext() )
255 const wxToolBarToolBase
* const tool
= node
->GetData();
256 if ( tool
->IsControl() )
258 wxControl
* const control
= tool
->GetControl();
262 wxFAIL_MSG( _T("NULL control in toolbar?") );
264 else if ( control
->GetId() == id
)
275 wxToolBarToolBase
*wxToolBarBase::AddSeparator()
277 return InsertSeparator(GetToolsCount());
280 wxToolBarToolBase
*wxToolBarBase::InsertSeparator(size_t pos
)
282 wxCHECK_MSG( pos
<= GetToolsCount(), (wxToolBarToolBase
*)NULL
,
283 _T("invalid position in wxToolBar::InsertSeparator()") );
285 wxToolBarToolBase
*tool
= CreateTool(wxID_SEPARATOR
,
287 wxNullBitmap
, wxNullBitmap
,
288 wxITEM_SEPARATOR
, (wxObject
*)NULL
,
289 wxEmptyString
, wxEmptyString
);
291 if ( !tool
|| !DoInsertTool(pos
, tool
) )
298 m_tools
.Insert(pos
, tool
);
303 wxToolBarToolBase
*wxToolBarBase::RemoveTool(int id
)
306 wxToolBarToolsList::compatibility_iterator node
;
307 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
309 if ( node
->GetData()->GetId() == id
)
317 // don't give any error messages - sometimes we might call RemoveTool()
318 // without knowing whether the tool is or not in the toolbar
319 return (wxToolBarToolBase
*)NULL
;
322 wxToolBarToolBase
*tool
= node
->GetData();
323 if ( !DoDeleteTool(pos
, tool
) )
325 return (wxToolBarToolBase
*)NULL
;
333 bool wxToolBarBase::DeleteToolByPos(size_t pos
)
335 wxCHECK_MSG( pos
< GetToolsCount(), false,
336 _T("invalid position in wxToolBar::DeleteToolByPos()") );
338 wxToolBarToolsList::compatibility_iterator node
= m_tools
.Item(pos
);
340 if ( !DoDeleteTool(pos
, node
->GetData()) )
345 delete node
->GetData();
351 bool wxToolBarBase::DeleteTool(int id
)
354 wxToolBarToolsList::compatibility_iterator node
;
355 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
357 if ( node
->GetData()->GetId() == id
)
363 if ( !node
|| !DoDeleteTool(pos
, node
->GetData()) )
368 delete node
->GetData();
374 wxToolBarToolBase
*wxToolBarBase::FindById(int id
) const
376 wxToolBarToolBase
*tool
= (wxToolBarToolBase
*)NULL
;
378 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
380 node
= node
->GetNext() )
382 tool
= node
->GetData();
383 if ( tool
->GetId() == id
)
395 void wxToolBarBase::UnToggleRadioGroup(wxToolBarToolBase
*tool
)
397 wxCHECK_RET( tool
, _T("NULL tool in wxToolBarTool::UnToggleRadioGroup") );
399 if ( !tool
->IsButton() || tool
->GetKind() != wxITEM_RADIO
)
402 wxToolBarToolsList::compatibility_iterator node
= m_tools
.Find(tool
);
403 wxCHECK_RET( node
, _T("invalid tool in wxToolBarTool::UnToggleRadioGroup") );
405 wxToolBarToolsList::compatibility_iterator nodeNext
= node
->GetNext();
408 wxToolBarToolBase
*tool
= nodeNext
->GetData();
410 if ( !tool
->IsButton() || tool
->GetKind() != wxITEM_RADIO
)
413 if ( tool
->Toggle(false) )
415 DoToggleTool(tool
, false);
418 nodeNext
= nodeNext
->GetNext();
421 wxToolBarToolsList::compatibility_iterator nodePrev
= node
->GetPrevious();
424 wxToolBarToolBase
*tool
= nodePrev
->GetData();
426 if ( !tool
->IsButton() || tool
->GetKind() != wxITEM_RADIO
)
429 if ( tool
->Toggle(false) )
431 DoToggleTool(tool
, false);
434 nodePrev
= nodePrev
->GetPrevious();
438 void wxToolBarBase::ClearTools()
440 WX_CLEAR_LIST(wxToolBarToolsList
, m_tools
);
443 bool wxToolBarBase::Realize()
448 wxToolBarBase::~wxToolBarBase()
450 WX_CLEAR_LIST(wxToolBarToolsList
, m_tools
);
452 // notify the frame that it doesn't have a tool bar any longer to avoid
454 wxFrame
*frame
= wxDynamicCast(GetParent(), wxFrame
);
455 if ( frame
&& frame
->GetToolBar() == this )
457 frame
->SetToolBar(NULL
);
461 // ----------------------------------------------------------------------------
462 // wxToolBarBase tools state
463 // ----------------------------------------------------------------------------
465 void wxToolBarBase::EnableTool(int id
, bool enable
)
467 wxToolBarToolBase
*tool
= FindById(id
);
470 if ( tool
->Enable(enable
) )
472 DoEnableTool(tool
, enable
);
477 void wxToolBarBase::ToggleTool(int id
, bool toggle
)
479 wxToolBarToolBase
*tool
= FindById(id
);
480 if ( tool
&& tool
->CanBeToggled() )
482 if ( tool
->Toggle(toggle
) )
484 UnToggleRadioGroup(tool
);
485 DoToggleTool(tool
, toggle
);
490 void wxToolBarBase::SetToggle(int id
, bool toggle
)
492 wxToolBarToolBase
*tool
= FindById(id
);
495 if ( tool
->SetToggle(toggle
) )
497 DoSetToggle(tool
, toggle
);
502 void wxToolBarBase::SetToolShortHelp(int id
, const wxString
& help
)
504 wxToolBarToolBase
*tool
= FindById(id
);
507 (void)tool
->SetShortHelp(help
);
511 void wxToolBarBase::SetToolLongHelp(int id
, const wxString
& help
)
513 wxToolBarToolBase
*tool
= FindById(id
);
516 (void)tool
->SetLongHelp(help
);
520 wxObject
*wxToolBarBase::GetToolClientData(int id
) const
522 wxToolBarToolBase
*tool
= FindById(id
);
524 return tool
? tool
->GetClientData() : (wxObject
*)NULL
;
527 void wxToolBarBase::SetToolClientData(int id
, wxObject
*clientData
)
529 wxToolBarToolBase
*tool
= FindById(id
);
531 wxCHECK_RET( tool
, _T("no such tool in wxToolBar::SetToolClientData") );
533 tool
->SetClientData(clientData
);
536 int wxToolBarBase::GetToolPos(int id
) const
539 wxToolBarToolsList::compatibility_iterator node
;
541 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
543 if ( node
->GetData()->GetId() == id
)
552 bool wxToolBarBase::GetToolState(int id
) const
554 wxToolBarToolBase
*tool
= FindById(id
);
555 wxCHECK_MSG( tool
, false, _T("no such tool") );
557 return tool
->IsToggled();
560 bool wxToolBarBase::GetToolEnabled(int id
) const
562 wxToolBarToolBase
*tool
= FindById(id
);
563 wxCHECK_MSG( tool
, false, _T("no such tool") );
565 return tool
->IsEnabled();
568 wxString
wxToolBarBase::GetToolShortHelp(int id
) const
570 wxToolBarToolBase
*tool
= FindById(id
);
571 wxCHECK_MSG( tool
, wxEmptyString
, _T("no such tool") );
573 return tool
->GetShortHelp();
576 wxString
wxToolBarBase::GetToolLongHelp(int id
) const
578 wxToolBarToolBase
*tool
= FindById(id
);
579 wxCHECK_MSG( tool
, wxEmptyString
, _T("no such tool") );
581 return tool
->GetLongHelp();
584 // ----------------------------------------------------------------------------
585 // wxToolBarBase geometry
586 // ----------------------------------------------------------------------------
588 void wxToolBarBase::SetMargins(int x
, int y
)
594 void wxToolBarBase::SetRows(int WXUNUSED(nRows
))
599 // ----------------------------------------------------------------------------
601 // ----------------------------------------------------------------------------
603 // Only allow toggle if returns true
604 bool wxToolBarBase::OnLeftClick(int id
, bool toggleDown
)
606 wxCommandEvent
event(wxEVT_COMMAND_TOOL_CLICKED
, id
);
607 event
.SetEventObject(this);
609 // we use SetInt() to make wxCommandEvent::IsChecked() return toggleDown
610 event
.SetInt((int)toggleDown
);
612 // and SetExtraLong() for backwards compatibility
613 event
.SetExtraLong((long)toggleDown
);
615 // Send events to this toolbar instead (and thence up the window hierarchy)
616 GetEventHandler()->ProcessEvent(event
);
621 // Call when right button down.
622 void wxToolBarBase::OnRightClick(int id
,
626 wxCommandEvent
event(wxEVT_COMMAND_TOOL_RCLICKED
, id
);
627 event
.SetEventObject(this);
630 GetEventHandler()->ProcessEvent(event
);
633 // Called when the mouse cursor enters a tool bitmap (no button pressed).
634 // Argument is wxID_ANY if mouse is exiting the toolbar.
635 // Note that for this event, the id of the window is used,
636 // and the integer parameter of wxCommandEvent is used to retrieve
638 void wxToolBarBase::OnMouseEnter(int id
)
640 wxCommandEvent
event(wxEVT_COMMAND_TOOL_ENTER
, GetId());
641 event
.SetEventObject(this);
644 wxFrame
*frame
= wxDynamicCast(GetParent(), wxFrame
);
648 wxToolBarToolBase
* tool
= id
== wxID_ANY
? (wxToolBarToolBase
*)NULL
: FindById(id
);
650 help
= tool
->GetLongHelp();
651 frame
->DoGiveHelp( help
, id
!= wxID_ANY
);
654 (void)GetEventHandler()->ProcessEvent(event
);
657 // ----------------------------------------------------------------------------
659 // ----------------------------------------------------------------------------
661 // Do the toolbar button updates (check for EVT_UPDATE_UI handlers)
662 void wxToolBarBase::UpdateWindowUI(long flags
)
664 wxWindowBase::UpdateWindowUI(flags
);
666 // There is no sense in updating the toolbar UI
667 // if the parent window is about to get destroyed
668 wxWindow
*tlw
= wxGetTopLevelParent( this );
669 if (tlw
&& wxPendingDelete
.Member( tlw
))
672 wxEvtHandler
* evtHandler
= GetEventHandler() ;
674 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
676 node
= node
->GetNext() )
678 int id
= node
->GetData()->GetId();
680 wxUpdateUIEvent
event(id
);
681 event
.SetEventObject(this);
683 if ( evtHandler
->ProcessEvent(event
) )
685 if ( event
.GetSetEnabled() )
686 EnableTool(id
, event
.GetEnabled());
687 if ( event
.GetSetChecked() )
688 ToggleTool(id
, event
.GetChecked());
690 if ( event
.GetSetText() )
700 * Make a greyed-out image suitable for disabled buttons.
701 * This code is adapted from wxNewBitmapButton in FL.
704 bool wxCreateGreyedImage(const wxImage
& src
, wxImage
& dst
)
708 unsigned char rBg
, gBg
, bBg
;
711 src
.GetOrFindMaskColour(&rBg
, &gBg
, &bBg
);
712 dst
.SetMaskColour(rBg
, gBg
, bBg
);
714 else // assuming the pixels along the edges are of the background color
716 rBg
= src
.GetRed(0, 0);
717 gBg
= src
.GetGreen(0, 0);
718 bBg
= src
.GetBlue(0, 0);
721 const wxColour
colBg(rBg
, gBg
, bBg
);
723 const wxColour colDark
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
);
724 const wxColour colLight
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT
);
726 // Second attempt, just making things monochrome
727 const int width
= src
.GetWidth();
728 const int height
= src
.GetHeight();
730 for ( int x
= 0; x
< width
; x
++ )
732 for ( int y
= 0; y
< height
; y
++ )
734 const int r
= src
.GetRed(x
, y
);
735 const int g
= src
.GetGreen(x
, y
);
736 const int b
= src
.GetBlue(x
, y
);
738 if ( r
== rBg
&& g
== gBg
&& b
== bBg
)
740 // Leave the background colour as-is
744 // Change light things to the background colour
746 if ( r
>= (colLight
.Red() - 50) &&
747 g
>= (colLight
.Green() - 50) &&
748 b
>= (colLight
.Blue() - 50) )
752 else // Change dark things to really dark
757 dst
.SetRGB(x
, y
, col
.Red(), col
.Green(), col
.Blue());
764 #endif // wxUSE_IMAGE
766 #endif // wxUSE_TOOLBAR