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 // ----------------------------------------------------------------------------
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/tbarbase.h"
43 // ----------------------------------------------------------------------------
45 // ----------------------------------------------------------------------------
47 IMPLEMENT_CLASS(wxToolBarBase
, wxControl
)
49 BEGIN_EVENT_TABLE(wxToolBarBase
, wxControl
)
50 EVT_IDLE(wxToolBarBase::OnIdle
)
53 #include "wx/listimpl.cpp"
55 WX_DEFINE_LIST(wxToolBarToolsList
);
57 // ============================================================================
59 // ============================================================================
61 // ----------------------------------------------------------------------------
63 // ----------------------------------------------------------------------------
65 bool wxToolBarToolBase::Enable(bool enable
)
67 if ( m_enabled
== enable
)
75 bool wxToolBarToolBase::Toggle(bool toggle
)
77 wxASSERT_MSG( CanBeToggled(), _T("can't toggle this tool") );
79 if ( m_toggled
== toggle
)
87 bool wxToolBarToolBase::SetToggle(bool toggle
)
89 wxItemKind kind
= toggle
? wxITEM_CHECK
: wxITEM_NORMAL
;
98 bool wxToolBarToolBase::SetShortHelp(const wxString
& help
)
100 if ( m_shortHelpString
== help
)
103 m_shortHelpString
= help
;
108 bool wxToolBarToolBase::SetLongHelp(const wxString
& help
)
110 if ( m_longHelpString
== help
)
113 m_longHelpString
= help
;
118 wxToolBarToolBase::~wxToolBarToolBase()
122 // ----------------------------------------------------------------------------
123 // wxToolBarBase adding/deleting items
124 // ----------------------------------------------------------------------------
126 wxToolBarBase::wxToolBarBase()
128 // the list owns the pointers
129 m_tools
.DeleteContents(TRUE
);
131 m_xMargin
= m_yMargin
= 0;
133 m_maxRows
= m_maxCols
= 0;
136 wxToolBarToolBase
*wxToolBarBase::DoAddTool(int id
,
137 const wxString
& label
,
138 const wxBitmap
& bitmap
,
139 const wxBitmap
& bmpDisabled
,
141 const wxString
& shortHelp
,
142 const wxString
& longHelp
,
143 wxObject
*clientData
,
144 wxCoord
WXUNUSED(xPos
),
145 wxCoord
WXUNUSED(yPos
))
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::Node
* 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::Node
*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
;
305 // the node would delete the data, so set it to NULL to avoid this
308 m_tools
.DeleteNode(node
);
313 bool wxToolBarBase::DeleteToolByPos(size_t pos
)
315 wxCHECK_MSG( pos
< GetToolsCount(), FALSE
,
316 _T("invalid position in wxToolBar::DeleteToolByPos()") );
318 wxToolBarToolsList::Node
*node
= m_tools
.Item(pos
);
320 if ( !DoDeleteTool(pos
, node
->GetData()) )
325 m_tools
.DeleteNode(node
);
330 bool wxToolBarBase::DeleteTool(int id
)
333 wxToolBarToolsList::Node
*node
;
334 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
336 if ( node
->GetData()->GetId() == id
)
342 if ( !node
|| !DoDeleteTool(pos
, node
->GetData()) )
347 m_tools
.DeleteNode(node
);
352 wxToolBarToolBase
*wxToolBarBase::FindById(int id
) const
354 wxToolBarToolBase
*tool
= (wxToolBarToolBase
*)NULL
;
356 for ( wxToolBarToolsList::Node
*node
= m_tools
.GetFirst();
358 node
= node
->GetNext() )
360 tool
= node
->GetData();
361 if ( tool
->GetId() == id
)
373 void wxToolBarBase::ClearTools()
378 bool wxToolBarBase::Realize()
383 wxToolBarBase::~wxToolBarBase()
387 // ----------------------------------------------------------------------------
388 // wxToolBarBase tools state
389 // ----------------------------------------------------------------------------
391 void wxToolBarBase::EnableTool(int id
, bool enable
)
393 wxToolBarToolBase
*tool
= FindById(id
);
396 if ( tool
->Enable(enable
) )
398 DoEnableTool(tool
, enable
);
403 void wxToolBarBase::ToggleTool(int id
, bool toggle
)
405 wxToolBarToolBase
*tool
= FindById(id
);
406 if ( tool
&& tool
->CanBeToggled() )
408 if ( tool
->Toggle(toggle
) )
410 DoToggleTool(tool
, toggle
);
415 void wxToolBarBase::SetToggle(int id
, bool toggle
)
417 wxToolBarToolBase
*tool
= FindById(id
);
420 if ( tool
->SetToggle(toggle
) )
422 DoSetToggle(tool
, toggle
);
427 void wxToolBarBase::SetToolShortHelp(int id
, const wxString
& help
)
429 wxToolBarToolBase
*tool
= FindById(id
);
432 (void)tool
->SetShortHelp(help
);
436 void wxToolBarBase::SetToolLongHelp(int id
, const wxString
& help
)
438 wxToolBarToolBase
*tool
= FindById(id
);
441 (void)tool
->SetLongHelp(help
);
445 wxObject
*wxToolBarBase::GetToolClientData(int id
) const
447 wxToolBarToolBase
*tool
= FindById(id
);
449 return tool
? tool
->GetClientData() : (wxObject
*)NULL
;
452 void wxToolBarBase::SetToolClientData(int id
, wxObject
*clientData
)
454 wxToolBarToolBase
*tool
= FindById(id
);
456 wxCHECK_RET( tool
, _T("no such tool in wxToolBar::SetToolClientData") );
458 tool
->SetClientData(clientData
);
461 bool wxToolBarBase::GetToolState(int id
) const
463 wxToolBarToolBase
*tool
= FindById(id
);
464 wxCHECK_MSG( tool
, FALSE
, _T("no such tool") );
466 return tool
->IsToggled();
469 bool wxToolBarBase::GetToolEnabled(int id
) const
471 wxToolBarToolBase
*tool
= FindById(id
);
472 wxCHECK_MSG( tool
, FALSE
, _T("no such tool") );
474 return tool
->IsEnabled();
477 wxString
wxToolBarBase::GetToolShortHelp(int id
) const
479 wxToolBarToolBase
*tool
= FindById(id
);
480 wxCHECK_MSG( tool
, _T(""), _T("no such tool") );
482 return tool
->GetShortHelp();
485 wxString
wxToolBarBase::GetToolLongHelp(int id
) const
487 wxToolBarToolBase
*tool
= FindById(id
);
488 wxCHECK_MSG( tool
, _T(""), _T("no such tool") );
490 return tool
->GetLongHelp();
493 // ----------------------------------------------------------------------------
494 // wxToolBarBase geometry
495 // ----------------------------------------------------------------------------
497 void wxToolBarBase::SetMargins(int x
, int y
)
503 void wxToolBarBase::SetRows(int WXUNUSED(nRows
))
508 // ----------------------------------------------------------------------------
510 // ----------------------------------------------------------------------------
512 // Only allow toggle if returns TRUE
513 bool wxToolBarBase::OnLeftClick(int id
, bool toggleDown
)
515 wxCommandEvent
event(wxEVT_COMMAND_TOOL_CLICKED
, id
);
516 event
.SetEventObject(this);
518 // we use SetInt() to make wxCommandEvent::IsChecked() return toggleDown
519 event
.SetInt((int)toggleDown
);
521 // and SetExtraLong() for backwards compatibility
522 event
.SetExtraLong((long)toggleDown
);
524 // Send events to this toolbar instead (and thence up the window hierarchy)
525 GetEventHandler()->ProcessEvent(event
);
530 // Call when right button down.
531 void wxToolBarBase::OnRightClick(int id
,
535 wxCommandEvent
event(wxEVT_COMMAND_TOOL_RCLICKED
, id
);
536 event
.SetEventObject(this);
539 GetEventHandler()->ProcessEvent(event
);
542 // Called when the mouse cursor enters a tool bitmap (no button pressed).
543 // Argument is -1 if mouse is exiting the toolbar.
544 // Note that for this event, the id of the window is used,
545 // and the integer parameter of wxCommandEvent is used to retrieve
547 void wxToolBarBase::OnMouseEnter(int id
)
549 wxCommandEvent
event(wxEVT_COMMAND_TOOL_ENTER
, GetId());
550 event
.SetEventObject(this);
553 wxFrame
*frame
= wxDynamicCast(GetParent(), wxFrame
);
556 wxToolBarToolBase
* tool
= id
== -1 ? (wxToolBarToolBase
*)0 : FindById(id
);
557 wxString help
= tool
? tool
->GetLongHelp() : wxString();
558 frame
->DoGiveHelp( help
, id
!= -1 );
561 (void)GetEventHandler()->ProcessEvent(event
);
564 // ----------------------------------------------------------------------------
566 // ----------------------------------------------------------------------------
568 void wxToolBarBase::OnIdle(wxIdleEvent
& event
)
575 // Do the toolbar button updates (check for EVT_UPDATE_UI handlers)
576 void wxToolBarBase::DoToolbarUpdates()
578 wxWindow
* parent
= this;
579 while (parent
->GetParent())
580 parent
= parent
->GetParent();
582 // This kind of #ifdef is a good way to annoy people. It breaks
583 // apps, but only on one platform and due to a hack in officially
584 // platform independent code. It took me hours to fix this. RR.
587 // wxWindow* focusWin = wxFindFocusDescendant(parent);
589 wxWindow
* focusWin
= (wxWindow
*) NULL
;
592 wxEvtHandler
* evtHandler
= focusWin
? focusWin
->GetEventHandler() : GetEventHandler() ;
594 for ( wxToolBarToolsList::Node
* node
= m_tools
.GetFirst();
596 node
= node
->GetNext() )
598 int id
= node
->GetData()->GetId();
600 wxUpdateUIEvent
event(id
);
601 event
.SetEventObject(this);
603 if ( evtHandler
->ProcessEvent(event
) )
605 if ( event
.GetSetEnabled() )
606 EnableTool(id
, event
.GetEnabled());
607 if ( event
.GetSetChecked() )
608 ToggleTool(id
, event
.GetChecked());
610 if ( event
.GetSetText() )
617 // Helper function, used by wxCreateGreyedImage
619 static void wxGreyOutImage( const wxImage
& src
,
621 const wxColour
& darkCol
,
622 const wxColour
& lightCol
,
623 const wxColour
& bgCol
)
625 // Second attempt, just making things monochrome
626 int width
= src
.GetWidth();
627 int height
= src
.GetHeight();
629 int redCur
, greenCur
, blueCur
;
630 for ( int x
= 0; x
< width
; x
++ )
632 for ( int y
= 1; y
< height
; y
++ )
634 redCur
= src
.GetRed(x
, y
);
635 greenCur
= src
.GetGreen(x
, y
);
636 blueCur
= src
.GetBlue(x
, y
);
638 // Change light things to the background colour
639 if ( redCur
>= (lightCol
.Red() - 50) && greenCur
>= (lightCol
.Green() - 50) && blueCur
>= (lightCol
.Blue() - 50) )
641 dest
.SetRGB(x
,y
, bgCol
.Red(), bgCol
.Green(), bgCol
.Blue());
643 else if ( redCur
== bgCol
.Red() && greenCur
== bgCol
.Green() && blueCur
== bgCol
.Blue() )
645 // Leave the background colour as-is
646 // dest.SetRGB(x,y, bgCol.Red(), bgCol.Green(), bgCol.Blue());
648 else // if ( redCur <= darkCol.Red() && greenCur <= darkCol.Green() && blueCur <= darkCol.Blue() )
650 // Change dark things to really dark
651 dest
.SetRGB(x
,y
, darkCol
.Red(), darkCol
.Green(), darkCol
.Blue());
658 * Make a greyed-out image suitable for disabled buttons.
659 * This code is adapted from wxNewBitmapButton in FL.
662 bool wxCreateGreyedImage(const wxImage
& in
, wxImage
& out
)
666 // assuming the pixels along the edges are of the background color
667 wxColour
bgCol(in
.GetRed(0, 0), in
.GetGreen(0, 0), in
.GetBlue(0, 0));
669 wxColour darkCol
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
) ;
670 wxColour lightCol
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT
) ;
672 wxGreyOutImage(in
, out
, darkCol
, lightCol
, bgCol
);
677 #endif // wxUSE_TOOLBAR