1 /////////////////////////////////////////////////////////////////////////////
2 // Name: common/tbarbase.cpp
3 // Purpose: wxToolBarBase implementation
4 // Author: Julian Smart
5 // Modified by: VZ at 11.12.99 (wxScrollableToolBar splitted 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"
39 #include "wx/settings.h"
41 #include "wx/toolbar.h"
43 // ----------------------------------------------------------------------------
45 // ----------------------------------------------------------------------------
47 BEGIN_EVENT_TABLE(wxToolBarBase
, wxControl
)
50 #include "wx/listimpl.cpp"
52 WX_DEFINE_LIST(wxToolBarToolsList
);
54 // ============================================================================
56 // ============================================================================
58 // ----------------------------------------------------------------------------
60 // ----------------------------------------------------------------------------
62 IMPLEMENT_DYNAMIC_CLASS(wxToolBarToolBase
, wxObject
)
64 bool wxToolBarToolBase::Enable(bool enable
)
71 bool wxToolBarToolBase::Toggle(bool toggle
)
73 wxASSERT_MSG( CanBeToggled(), _T("can't toggle this tool") );
80 bool wxToolBarToolBase::SetToggle(bool toggle
)
82 wxItemKind kind
= toggle
? wxITEM_CHECK
: wxITEM_NORMAL
;
89 bool wxToolBarToolBase::SetShortHelp(const wxString
& help
)
91 m_shortHelpString
= help
;
96 bool wxToolBarToolBase::SetLongHelp(const wxString
& help
)
98 m_longHelpString
= help
;
103 wxToolBarToolBase::~wxToolBarToolBase()
107 // ----------------------------------------------------------------------------
108 // wxToolBarBase adding/deleting items
109 // ----------------------------------------------------------------------------
111 wxToolBarBase::wxToolBarBase()
113 // the list owns the pointers
114 m_xMargin
= m_yMargin
= 0;
116 m_maxRows
= m_maxCols
= 0;
119 wxToolBarToolBase
*wxToolBarBase::DoAddTool(int id
,
120 const wxString
& label
,
121 const wxBitmap
& bitmap
,
122 const wxBitmap
& bmpDisabled
,
124 const wxString
& shortHelp
,
125 const wxString
& longHelp
,
126 wxObject
*clientData
,
127 wxCoord
WXUNUSED(xPos
),
128 wxCoord
WXUNUSED(yPos
))
130 return InsertTool(GetToolsCount(), id
, label
, bitmap
, bmpDisabled
,
131 kind
, shortHelp
, longHelp
, clientData
);
134 wxToolBarToolBase
*wxToolBarBase::InsertTool(size_t pos
,
136 const wxString
& label
,
137 const wxBitmap
& bitmap
,
138 const wxBitmap
& bmpDisabled
,
140 const wxString
& shortHelp
,
141 const wxString
& longHelp
,
142 wxObject
*clientData
)
144 wxCHECK_MSG( pos
<= GetToolsCount(), (wxToolBarToolBase
*)NULL
,
145 _T("invalid position in wxToolBar::InsertTool()") );
147 wxToolBarToolBase
*tool
= CreateTool(id
, label
, bitmap
, bmpDisabled
, kind
,
148 clientData
, shortHelp
, longHelp
);
150 if ( !InsertTool(pos
, tool
) )
160 wxToolBarToolBase
*wxToolBarBase::AddTool(wxToolBarToolBase
*tool
)
162 return InsertTool(GetToolsCount(), tool
);
166 wxToolBarBase::InsertTool(size_t pos
, wxToolBarToolBase
*tool
)
168 wxCHECK_MSG( pos
<= GetToolsCount(), (wxToolBarToolBase
*)NULL
,
169 _T("invalid position in wxToolBar::InsertTool()") );
171 if ( !tool
|| !DoInsertTool(pos
, tool
) )
176 m_tools
.Insert(pos
, tool
);
181 wxToolBarToolBase
*wxToolBarBase::AddControl(wxControl
*control
)
183 return InsertControl(GetToolsCount(), control
);
186 wxToolBarToolBase
*wxToolBarBase::InsertControl(size_t pos
, wxControl
*control
)
188 wxCHECK_MSG( control
, (wxToolBarToolBase
*)NULL
,
189 _T("toolbar: can't insert NULL control") );
191 wxCHECK_MSG( control
->GetParent() == this, (wxToolBarToolBase
*)NULL
,
192 _T("control must have toolbar as parent") );
194 wxCHECK_MSG( pos
<= GetToolsCount(), (wxToolBarToolBase
*)NULL
,
195 _T("invalid position in wxToolBar::InsertControl()") );
197 wxToolBarToolBase
*tool
= CreateTool(control
);
199 if ( !InsertTool(pos
, tool
) )
209 wxControl
*wxToolBarBase::FindControl( int id
)
211 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
213 node
= node
->GetNext() )
215 const wxToolBarToolBase
* const tool
= node
->GetData();
216 if ( tool
->IsControl() )
218 wxControl
* const control
= tool
->GetControl();
222 wxFAIL_MSG( _T("NULL control in toolbar?") );
224 else if ( control
->GetId() == id
)
235 wxToolBarToolBase
*wxToolBarBase::AddSeparator()
237 return InsertSeparator(GetToolsCount());
240 wxToolBarToolBase
*wxToolBarBase::InsertSeparator(size_t pos
)
242 wxCHECK_MSG( pos
<= GetToolsCount(), (wxToolBarToolBase
*)NULL
,
243 _T("invalid position in wxToolBar::InsertSeparator()") );
245 wxToolBarToolBase
*tool
= CreateTool(wxID_SEPARATOR
,
247 wxNullBitmap
, wxNullBitmap
,
248 wxITEM_SEPARATOR
, (wxObject
*)NULL
,
249 wxEmptyString
, wxEmptyString
);
251 if ( !tool
|| !DoInsertTool(pos
, tool
) )
258 m_tools
.Insert(pos
, tool
);
263 wxToolBarToolBase
*wxToolBarBase::RemoveTool(int id
)
266 wxToolBarToolsList::compatibility_iterator node
;
267 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
269 if ( node
->GetData()->GetId() == id
)
277 // don't give any error messages - sometimes we might call RemoveTool()
278 // without knowing whether the tool is or not in the toolbar
279 return (wxToolBarToolBase
*)NULL
;
282 wxToolBarToolBase
*tool
= node
->GetData();
283 if ( !DoDeleteTool(pos
, tool
) )
285 return (wxToolBarToolBase
*)NULL
;
293 bool wxToolBarBase::DeleteToolByPos(size_t pos
)
295 wxCHECK_MSG( pos
< GetToolsCount(), false,
296 _T("invalid position in wxToolBar::DeleteToolByPos()") );
298 wxToolBarToolsList::compatibility_iterator node
= m_tools
.Item(pos
);
300 if ( !DoDeleteTool(pos
, node
->GetData()) )
305 delete node
->GetData();
311 bool wxToolBarBase::DeleteTool(int id
)
314 wxToolBarToolsList::compatibility_iterator node
;
315 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
317 if ( node
->GetData()->GetId() == id
)
323 if ( !node
|| !DoDeleteTool(pos
, node
->GetData()) )
328 delete node
->GetData();
334 wxToolBarToolBase
*wxToolBarBase::FindById(int id
) const
336 wxToolBarToolBase
*tool
= (wxToolBarToolBase
*)NULL
;
338 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
340 node
= node
->GetNext() )
342 tool
= node
->GetData();
343 if ( tool
->GetId() == id
)
355 void wxToolBarBase::UnToggleRadioGroup(wxToolBarToolBase
*tool
)
357 wxCHECK_RET( tool
, _T("NULL tool in wxToolBarTool::UnToggleRadioGroup") );
359 if ( !tool
->IsButton() || tool
->GetKind() != wxITEM_RADIO
)
362 wxToolBarToolsList::compatibility_iterator node
= m_tools
.Find(tool
);
363 wxCHECK_RET( node
, _T("invalid tool in wxToolBarTool::UnToggleRadioGroup") );
365 wxToolBarToolsList::compatibility_iterator nodeNext
= node
->GetNext();
368 wxToolBarToolBase
*tool
= nodeNext
->GetData();
370 if ( !tool
->IsButton() || tool
->GetKind() != wxITEM_RADIO
)
375 nodeNext
= nodeNext
->GetNext();
378 wxToolBarToolsList::compatibility_iterator nodePrev
= node
->GetPrevious();
381 wxToolBarToolBase
*tool
= nodePrev
->GetData();
383 if ( !tool
->IsButton() || tool
->GetKind() != wxITEM_RADIO
)
388 nodePrev
= nodePrev
->GetPrevious();
392 void wxToolBarBase::ClearTools()
394 WX_CLEAR_LIST(wxToolBarToolsList
, m_tools
);
397 bool wxToolBarBase::Realize()
402 wxToolBarBase::~wxToolBarBase()
404 WX_CLEAR_LIST(wxToolBarToolsList
, m_tools
);
407 // ----------------------------------------------------------------------------
408 // wxToolBarBase tools state
409 // ----------------------------------------------------------------------------
411 void wxToolBarBase::EnableTool(int id
, bool enable
)
413 wxToolBarToolBase
*tool
= FindById(id
);
416 if ( tool
->Enable(enable
) )
418 DoEnableTool(tool
, enable
);
423 void wxToolBarBase::ToggleTool(int id
, bool toggle
)
425 wxToolBarToolBase
*tool
= FindById(id
);
426 if ( tool
&& tool
->CanBeToggled() )
428 if ( tool
->Toggle(toggle
) )
430 UnToggleRadioGroup(tool
);
431 DoToggleTool(tool
, toggle
);
436 void wxToolBarBase::SetToggle(int id
, bool toggle
)
438 wxToolBarToolBase
*tool
= FindById(id
);
441 if ( tool
->SetToggle(toggle
) )
443 DoSetToggle(tool
, toggle
);
448 void wxToolBarBase::SetToolShortHelp(int id
, const wxString
& help
)
450 wxToolBarToolBase
*tool
= FindById(id
);
453 (void)tool
->SetShortHelp(help
);
457 void wxToolBarBase::SetToolLongHelp(int id
, const wxString
& help
)
459 wxToolBarToolBase
*tool
= FindById(id
);
462 (void)tool
->SetLongHelp(help
);
466 wxObject
*wxToolBarBase::GetToolClientData(int id
) const
468 wxToolBarToolBase
*tool
= FindById(id
);
470 return tool
? tool
->GetClientData() : (wxObject
*)NULL
;
473 void wxToolBarBase::SetToolClientData(int id
, wxObject
*clientData
)
475 wxToolBarToolBase
*tool
= FindById(id
);
477 wxCHECK_RET( tool
, _T("no such tool in wxToolBar::SetToolClientData") );
479 tool
->SetClientData(clientData
);
482 int wxToolBarBase::GetToolPos(int id
) const
485 wxToolBarToolsList::compatibility_iterator node
;
487 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
489 if ( node
->GetData()->GetId() == id
)
498 bool wxToolBarBase::GetToolState(int id
) const
500 wxToolBarToolBase
*tool
= FindById(id
);
501 wxCHECK_MSG( tool
, false, _T("no such tool") );
503 return tool
->IsToggled();
506 bool wxToolBarBase::GetToolEnabled(int id
) const
508 wxToolBarToolBase
*tool
= FindById(id
);
509 wxCHECK_MSG( tool
, false, _T("no such tool") );
511 return tool
->IsEnabled();
514 wxString
wxToolBarBase::GetToolShortHelp(int id
) const
516 wxToolBarToolBase
*tool
= FindById(id
);
517 wxCHECK_MSG( tool
, _T(""), _T("no such tool") );
519 return tool
->GetShortHelp();
522 wxString
wxToolBarBase::GetToolLongHelp(int id
) const
524 wxToolBarToolBase
*tool
= FindById(id
);
525 wxCHECK_MSG( tool
, _T(""), _T("no such tool") );
527 return tool
->GetLongHelp();
530 // ----------------------------------------------------------------------------
531 // wxToolBarBase geometry
532 // ----------------------------------------------------------------------------
534 void wxToolBarBase::SetMargins(int x
, int y
)
540 void wxToolBarBase::SetRows(int WXUNUSED(nRows
))
545 // ----------------------------------------------------------------------------
547 // ----------------------------------------------------------------------------
549 // Only allow toggle if returns true
550 bool wxToolBarBase::OnLeftClick(int id
, bool toggleDown
)
552 wxCommandEvent
event(wxEVT_COMMAND_TOOL_CLICKED
, id
);
553 event
.SetEventObject(this);
555 // we use SetInt() to make wxCommandEvent::IsChecked() return toggleDown
556 event
.SetInt((int)toggleDown
);
558 // and SetExtraLong() for backwards compatibility
559 event
.SetExtraLong((long)toggleDown
);
561 // Send events to this toolbar instead (and thence up the window hierarchy)
562 GetEventHandler()->ProcessEvent(event
);
567 // Call when right button down.
568 void wxToolBarBase::OnRightClick(int id
,
572 wxCommandEvent
event(wxEVT_COMMAND_TOOL_RCLICKED
, id
);
573 event
.SetEventObject(this);
576 GetEventHandler()->ProcessEvent(event
);
579 // Called when the mouse cursor enters a tool bitmap (no button pressed).
580 // Argument is -1 if mouse is exiting the toolbar.
581 // Note that for this event, the id of the window is used,
582 // and the integer parameter of wxCommandEvent is used to retrieve
584 void wxToolBarBase::OnMouseEnter(int id
)
586 wxCommandEvent
event(wxEVT_COMMAND_TOOL_ENTER
, GetId());
587 event
.SetEventObject(this);
590 wxFrame
*frame
= wxDynamicCast(GetParent(), wxFrame
);
593 wxToolBarToolBase
* tool
= id
== -1 ? (wxToolBarToolBase
*)0 : FindById(id
);
594 wxString help
= tool
? tool
->GetLongHelp() : wxString();
595 frame
->DoGiveHelp( help
, id
!= -1 );
598 (void)GetEventHandler()->ProcessEvent(event
);
601 // ----------------------------------------------------------------------------
603 // ----------------------------------------------------------------------------
605 // Do the toolbar button updates (check for EVT_UPDATE_UI handlers)
606 void wxToolBarBase::UpdateWindowUI(long flags
)
608 wxWindowBase::UpdateWindowUI(flags
);
610 wxEvtHandler
* evtHandler
= GetEventHandler() ;
612 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
614 node
= node
->GetNext() )
616 int id
= node
->GetData()->GetId();
618 wxUpdateUIEvent
event(id
);
619 event
.SetEventObject(this);
621 if ( evtHandler
->ProcessEvent(event
) )
623 if ( event
.GetSetEnabled() )
624 EnableTool(id
, event
.GetEnabled());
625 if ( event
.GetSetChecked() )
626 ToggleTool(id
, event
.GetChecked());
628 if ( event
.GetSetText() )
635 // Helper function, used by wxCreateGreyedImage
637 static void wxGreyOutImage( const wxImage
& src
,
639 const wxColour
& darkCol
,
640 const wxColour
& lightCol
,
641 const wxColour
& bgCol
)
643 // Second attempt, just making things monochrome
644 int width
= src
.GetWidth();
645 int height
= src
.GetHeight();
647 int redCur
, greenCur
, blueCur
;
648 for ( int x
= 0; x
< width
; x
++ )
650 for ( int y
= 1; y
< height
; y
++ )
652 redCur
= src
.GetRed(x
, y
);
653 greenCur
= src
.GetGreen(x
, y
);
654 blueCur
= src
.GetBlue(x
, y
);
656 // Change light things to the background colour
657 if ( redCur
>= (lightCol
.Red() - 50) && greenCur
>= (lightCol
.Green() - 50) && blueCur
>= (lightCol
.Blue() - 50) )
659 dest
.SetRGB(x
,y
, bgCol
.Red(), bgCol
.Green(), bgCol
.Blue());
661 else if ( redCur
== bgCol
.Red() && greenCur
== bgCol
.Green() && blueCur
== bgCol
.Blue() )
663 // Leave the background colour as-is
664 // dest.SetRGB(x,y, bgCol.Red(), bgCol.Green(), bgCol.Blue());
666 else // if ( redCur <= darkCol.Red() && greenCur <= darkCol.Green() && blueCur <= darkCol.Blue() )
668 // Change dark things to really dark
669 dest
.SetRGB(x
,y
, darkCol
.Red(), darkCol
.Green(), darkCol
.Blue());
676 * Make a greyed-out image suitable for disabled buttons.
677 * This code is adapted from wxNewBitmapButton in FL.
680 bool wxCreateGreyedImage(const wxImage
& in
, wxImage
& out
)
684 // assuming the pixels along the edges are of the background color
685 wxColour
bgCol(in
.GetRed(0, 0), in
.GetGreen(0, 0), in
.GetBlue(0, 0));
687 wxColour darkCol
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
) ;
688 wxColour lightCol
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT
) ;
690 wxGreyOutImage(in
, out
, darkCol
, lightCol
, bgCol
);
695 #endif // wxUSE_TOOLBAR