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 int wxToolBarBase::GetToolPos(int id
) const 
 464     wxToolBarToolsList::Node 
*node
; 
 466     for ( node 
= m_tools
.GetFirst(); node
; node 
= node
->GetNext() ) 
 468         if ( node
->GetData()->GetId() == id 
) 
 477 bool wxToolBarBase::GetToolState(int id
) const 
 479     wxToolBarToolBase 
*tool 
= FindById(id
); 
 480     wxCHECK_MSG( tool
, FALSE
, _T("no such tool") ); 
 482     return tool
->IsToggled(); 
 485 bool wxToolBarBase::GetToolEnabled(int id
) const 
 487     wxToolBarToolBase 
*tool 
= FindById(id
); 
 488     wxCHECK_MSG( tool
, FALSE
, _T("no such tool") ); 
 490     return tool
->IsEnabled(); 
 493 wxString 
wxToolBarBase::GetToolShortHelp(int id
) const 
 495     wxToolBarToolBase 
*tool 
= FindById(id
); 
 496     wxCHECK_MSG( tool
, _T(""), _T("no such tool") ); 
 498     return tool
->GetShortHelp(); 
 501 wxString 
wxToolBarBase::GetToolLongHelp(int id
) const 
 503     wxToolBarToolBase 
*tool 
= FindById(id
); 
 504     wxCHECK_MSG( tool
, _T(""), _T("no such tool") ); 
 506     return tool
->GetLongHelp(); 
 509 // ---------------------------------------------------------------------------- 
 510 // wxToolBarBase geometry 
 511 // ---------------------------------------------------------------------------- 
 513 void wxToolBarBase::SetMargins(int x
, int y
) 
 519 void wxToolBarBase::SetRows(int WXUNUSED(nRows
)) 
 524 // ---------------------------------------------------------------------------- 
 526 // ---------------------------------------------------------------------------- 
 528 // Only allow toggle if returns TRUE 
 529 bool wxToolBarBase::OnLeftClick(int id
, bool toggleDown
) 
 531     wxCommandEvent 
event(wxEVT_COMMAND_TOOL_CLICKED
, id
); 
 532     event
.SetEventObject(this); 
 534     // we use SetInt() to make wxCommandEvent::IsChecked() return toggleDown 
 535     event
.SetInt((int)toggleDown
); 
 537     // and SetExtraLong() for backwards compatibility 
 538     event
.SetExtraLong((long)toggleDown
); 
 540     // Send events to this toolbar instead (and thence up the window hierarchy) 
 541     GetEventHandler()->ProcessEvent(event
); 
 546 // Call when right button down. 
 547 void wxToolBarBase::OnRightClick(int id
, 
 551     wxCommandEvent 
event(wxEVT_COMMAND_TOOL_RCLICKED
, id
); 
 552     event
.SetEventObject(this); 
 555     GetEventHandler()->ProcessEvent(event
); 
 558 // Called when the mouse cursor enters a tool bitmap (no button pressed). 
 559 // Argument is -1 if mouse is exiting the toolbar. 
 560 // Note that for this event, the id of the window is used, 
 561 // and the integer parameter of wxCommandEvent is used to retrieve 
 563 void wxToolBarBase::OnMouseEnter(int id
) 
 565     wxCommandEvent 
event(wxEVT_COMMAND_TOOL_ENTER
, GetId()); 
 566     event
.SetEventObject(this); 
 569     wxFrame 
*frame 
= wxDynamicCast(GetParent(), wxFrame
); 
 572         wxToolBarToolBase
* tool 
= id 
== -1 ? (wxToolBarToolBase
*)0 : FindById(id
); 
 573         wxString help 
= tool 
? tool
->GetLongHelp() : wxString(); 
 574         frame
->DoGiveHelp( help
, id 
!= -1 ); 
 577     (void)GetEventHandler()->ProcessEvent(event
); 
 580 // ---------------------------------------------------------------------------- 
 582 // ---------------------------------------------------------------------------- 
 584 void wxToolBarBase::OnIdle(wxIdleEvent
& event
) 
 586     if (wxUpdateUIEvent::CanUpdate()) 
 592 // Do the toolbar button updates (check for EVT_UPDATE_UI handlers) 
 593 void wxToolBarBase::DoToolbarUpdates() 
 595     wxEvtHandler
* evtHandler 
= GetEventHandler() ; 
 597     for ( wxToolBarToolsList::Node
* node 
= m_tools
.GetFirst(); 
 599           node 
= node
->GetNext() ) 
 601         int id 
= node
->GetData()->GetId(); 
 603         wxUpdateUIEvent 
event(id
); 
 604         event
.SetEventObject(this); 
 606         if ( evtHandler
->ProcessEvent(event
) ) 
 608             if ( event
.GetSetEnabled() ) 
 609                 EnableTool(id
, event
.GetEnabled()); 
 610             if ( event
.GetSetChecked() ) 
 611                 ToggleTool(id
, event
.GetChecked()); 
 613             if ( event
.GetSetText() ) 
 620 // Helper function, used by wxCreateGreyedImage 
 622 static void wxGreyOutImage( const wxImage
& src
, 
 624                             const wxColour
& darkCol
, 
 625                             const wxColour
& lightCol
, 
 626                             const wxColour
& bgCol 
) 
 628     // Second attempt, just making things monochrome 
 629     int width 
= src
.GetWidth(); 
 630     int height 
= src
.GetHeight(); 
 632     int redCur
, greenCur
, blueCur
; 
 633     for ( int x 
= 0; x 
< width
; x
++ ) 
 635         for ( int y 
= 1; y 
< height
; y
++ ) 
 637             redCur 
= src
.GetRed(x
, y
); 
 638             greenCur 
= src
.GetGreen(x
, y
); 
 639             blueCur 
= src
.GetBlue(x
, y
); 
 641             // Change light things to the background colour 
 642             if ( redCur 
>= (lightCol
.Red() - 50) && greenCur 
>= (lightCol
.Green() - 50) && blueCur 
>= (lightCol
.Blue() - 50) ) 
 644                 dest
.SetRGB(x
,y
, bgCol
.Red(), bgCol
.Green(), bgCol
.Blue()); 
 646             else if ( redCur 
== bgCol
.Red() && greenCur 
== bgCol
.Green() && blueCur 
== bgCol
.Blue() ) 
 648                 // Leave the background colour as-is 
 649                 // dest.SetRGB(x,y, bgCol.Red(), bgCol.Green(), bgCol.Blue()); 
 651             else // if ( redCur <= darkCol.Red() && greenCur <= darkCol.Green() && blueCur <= darkCol.Blue() ) 
 653                 // Change dark things to really dark 
 654                 dest
.SetRGB(x
,y
, darkCol
.Red(), darkCol
.Green(), darkCol
.Blue()); 
 661  * Make a greyed-out image suitable for disabled buttons. 
 662  * This code is adapted from wxNewBitmapButton in FL. 
 665 bool wxCreateGreyedImage(const wxImage
& in
, wxImage
& out
) 
 669     // assuming the pixels along the edges are of the background color 
 670     wxColour 
bgCol(in
.GetRed(0, 0), in
.GetGreen(0, 0), in
.GetBlue(0, 0)); 
 672     wxColour darkCol 
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
) ; 
 673     wxColour lightCol 
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT
) ; 
 675     wxGreyOutImage(in
, out
, darkCol
, lightCol
, bgCol
); 
 680 #endif // wxUSE_TOOLBAR