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
) 
  66     if ( m_enabled 
== enable 
) 
  74 bool wxToolBarToolBase::Toggle(bool toggle
) 
  76     wxASSERT_MSG( CanBeToggled(), _T("can't toggle this tool") ); 
  78     if ( m_toggled 
== toggle 
) 
  86 bool wxToolBarToolBase::SetToggle(bool toggle
) 
  88     wxItemKind kind 
= toggle 
? wxITEM_CHECK 
: wxITEM_NORMAL
; 
  97 bool wxToolBarToolBase::SetShortHelp(const wxString
& help
) 
  99     if ( m_shortHelpString 
== help 
) 
 102     m_shortHelpString 
= help
; 
 107 bool wxToolBarToolBase::SetLongHelp(const wxString
& help
) 
 109     if ( m_longHelpString 
== help 
) 
 112     m_longHelpString 
= help
; 
 117 wxToolBarToolBase::~wxToolBarToolBase() 
 121 // ---------------------------------------------------------------------------- 
 122 // wxToolBarBase adding/deleting items 
 123 // ---------------------------------------------------------------------------- 
 125 wxToolBarBase::wxToolBarBase() 
 127     // the list owns the pointers 
 128     m_xMargin 
= m_yMargin 
= 0; 
 130     m_maxRows 
= m_maxCols 
= 0; 
 133 wxToolBarToolBase 
*wxToolBarBase::DoAddTool(int id
, 
 134                                             const wxString
& label
, 
 135                                             const wxBitmap
& bitmap
, 
 136                                             const wxBitmap
& bmpDisabled
, 
 138                                             const wxString
& shortHelp
, 
 139                                             const wxString
& longHelp
, 
 140                                             wxObject 
*clientData
, 
 141                                             wxCoord 
WXUNUSED(xPos
), 
 142                                             wxCoord 
WXUNUSED(yPos
)) 
 144     return InsertTool(GetToolsCount(), id
, label
, bitmap
, bmpDisabled
, 
 145                       kind
, shortHelp
, longHelp
, clientData
); 
 148 wxToolBarToolBase 
*wxToolBarBase::InsertTool(size_t pos
, 
 150                                              const wxString
& label
, 
 151                                              const wxBitmap
& bitmap
, 
 152                                              const wxBitmap
& bmpDisabled
, 
 154                                              const wxString
& shortHelp
, 
 155                                              const wxString
& longHelp
, 
 156                                              wxObject 
*clientData
) 
 158     wxCHECK_MSG( pos 
<= GetToolsCount(), (wxToolBarToolBase 
*)NULL
, 
 159                  _T("invalid position in wxToolBar::InsertTool()") ); 
 161     wxToolBarToolBase 
*tool 
= CreateTool(id
, label
, bitmap
, bmpDisabled
, kind
, 
 162                                          clientData
, shortHelp
, longHelp
); 
 164     if ( !InsertTool(pos
, tool
) ) 
 174 wxToolBarToolBase 
*wxToolBarBase::AddTool(wxToolBarToolBase 
*tool
) 
 176     return InsertTool(GetToolsCount(), tool
); 
 180 wxToolBarBase::InsertTool(size_t pos
, wxToolBarToolBase 
*tool
) 
 182     wxCHECK_MSG( pos 
<= GetToolsCount(), (wxToolBarToolBase 
*)NULL
, 
 183                  _T("invalid position in wxToolBar::InsertTool()") ); 
 185     if ( !tool 
|| !DoInsertTool(pos
, tool
) ) 
 190     m_tools
.Insert(pos
, tool
); 
 195 wxToolBarToolBase 
*wxToolBarBase::AddControl(wxControl 
*control
) 
 197     return InsertControl(GetToolsCount(), control
); 
 200 wxToolBarToolBase 
*wxToolBarBase::InsertControl(size_t pos
, wxControl 
*control
) 
 202     wxCHECK_MSG( control
, (wxToolBarToolBase 
*)NULL
, 
 203                  _T("toolbar: can't insert NULL control") ); 
 205     wxCHECK_MSG( control
->GetParent() == this, (wxToolBarToolBase 
*)NULL
, 
 206                  _T("control must have toolbar as parent") ); 
 208     wxCHECK_MSG( pos 
<= GetToolsCount(), (wxToolBarToolBase 
*)NULL
, 
 209                  _T("invalid position in wxToolBar::InsertControl()") ); 
 211     wxToolBarToolBase 
*tool 
= CreateTool(control
); 
 213     if ( !InsertTool(pos
, tool
) ) 
 223 wxControl 
*wxToolBarBase::FindControl( int id 
) 
 225     for ( wxToolBarToolsList::compatibility_iterator node 
= m_tools
.GetFirst(); 
 227           node 
= node
->GetNext() ) 
 229         const wxToolBarToolBase 
* const tool 
= node
->GetData(); 
 230         if ( tool
->IsControl() ) 
 232             wxControl 
* const control 
= tool
->GetControl(); 
 236                 wxFAIL_MSG( _T("NULL control in toolbar?") ); 
 238             else if ( control
->GetId() == id 
) 
 249 wxToolBarToolBase 
*wxToolBarBase::AddSeparator() 
 251     return InsertSeparator(GetToolsCount()); 
 254 wxToolBarToolBase 
*wxToolBarBase::InsertSeparator(size_t pos
) 
 256     wxCHECK_MSG( pos 
<= GetToolsCount(), (wxToolBarToolBase 
*)NULL
, 
 257                  _T("invalid position in wxToolBar::InsertSeparator()") ); 
 259     wxToolBarToolBase 
*tool 
= CreateTool(wxID_SEPARATOR
, 
 261                                          wxNullBitmap
, wxNullBitmap
, 
 262                                          wxITEM_SEPARATOR
, (wxObject 
*)NULL
, 
 263                                          wxEmptyString
, wxEmptyString
); 
 265     if ( !tool 
|| !DoInsertTool(pos
, tool
) ) 
 272     m_tools
.Insert(pos
, tool
); 
 277 wxToolBarToolBase 
*wxToolBarBase::RemoveTool(int id
) 
 280     wxToolBarToolsList::compatibility_iterator node
; 
 281     for ( node 
= m_tools
.GetFirst(); node
; node 
= node
->GetNext() ) 
 283         if ( node
->GetData()->GetId() == id 
) 
 291         // don't give any error messages - sometimes we might call RemoveTool() 
 292         // without knowing whether the tool is or not in the toolbar 
 293         return (wxToolBarToolBase 
*)NULL
; 
 296     wxToolBarToolBase 
*tool 
= node
->GetData(); 
 297     if ( !DoDeleteTool(pos
, tool
) ) 
 299         return (wxToolBarToolBase 
*)NULL
; 
 307 bool wxToolBarBase::DeleteToolByPos(size_t pos
) 
 309     wxCHECK_MSG( pos 
< GetToolsCount(), false, 
 310                  _T("invalid position in wxToolBar::DeleteToolByPos()") ); 
 312     wxToolBarToolsList::compatibility_iterator node 
= m_tools
.Item(pos
); 
 314     if ( !DoDeleteTool(pos
, node
->GetData()) ) 
 319     delete node
->GetData(); 
 325 bool wxToolBarBase::DeleteTool(int id
) 
 328     wxToolBarToolsList::compatibility_iterator node
; 
 329     for ( node 
= m_tools
.GetFirst(); node
; node 
= node
->GetNext() ) 
 331         if ( node
->GetData()->GetId() == id 
) 
 337     if ( !node 
|| !DoDeleteTool(pos
, node
->GetData()) ) 
 342     delete node
->GetData(); 
 348 wxToolBarToolBase 
*wxToolBarBase::FindById(int id
) const 
 350     wxToolBarToolBase 
*tool 
= (wxToolBarToolBase 
*)NULL
; 
 352     for ( wxToolBarToolsList::compatibility_iterator node 
= m_tools
.GetFirst(); 
 354           node 
= node
->GetNext() ) 
 356         tool 
= node
->GetData(); 
 357         if ( tool
->GetId() == id 
) 
 369 void wxToolBarBase::UnToggleRadioGroup(wxToolBarToolBase 
*tool
) 
 371     wxCHECK_RET( tool
, _T("NULL tool in wxToolBarTool::UnToggleRadioGroup") ); 
 373     if ( !tool
->IsButton() || tool
->GetKind() != wxITEM_RADIO 
) 
 376     wxToolBarToolsList::compatibility_iterator node 
= m_tools
.Find(tool
); 
 377     wxCHECK_RET( node
, _T("invalid tool in wxToolBarTool::UnToggleRadioGroup") ); 
 379     wxToolBarToolsList::compatibility_iterator nodeNext 
= node
->GetNext(); 
 382         wxToolBarToolBase 
*tool 
= nodeNext
->GetData(); 
 384         if ( !tool
->IsButton() || tool
->GetKind() != wxITEM_RADIO 
) 
 389         nodeNext 
= nodeNext
->GetNext(); 
 392     wxToolBarToolsList::compatibility_iterator nodePrev 
= node
->GetPrevious(); 
 395         wxToolBarToolBase 
*tool 
= nodePrev
->GetData(); 
 397         if ( !tool
->IsButton() || tool
->GetKind() != wxITEM_RADIO 
) 
 402         nodePrev 
= nodePrev
->GetPrevious(); 
 406 void wxToolBarBase::ClearTools() 
 408     WX_CLEAR_LIST(wxToolBarToolsList
, m_tools
); 
 411 bool wxToolBarBase::Realize() 
 416 wxToolBarBase::~wxToolBarBase() 
 418     WX_CLEAR_LIST(wxToolBarToolsList
, m_tools
); 
 421 // ---------------------------------------------------------------------------- 
 422 // wxToolBarBase tools state 
 423 // ---------------------------------------------------------------------------- 
 425 void wxToolBarBase::EnableTool(int id
, bool enable
) 
 427     wxToolBarToolBase 
*tool 
= FindById(id
); 
 430         if ( tool
->Enable(enable
) ) 
 432             DoEnableTool(tool
, enable
); 
 437 void wxToolBarBase::ToggleTool(int id
, bool toggle
) 
 439     wxToolBarToolBase 
*tool 
= FindById(id
); 
 440     if ( tool 
&& tool
->CanBeToggled() ) 
 442         if ( tool
->Toggle(toggle
) ) 
 444             UnToggleRadioGroup(tool
); 
 445             DoToggleTool(tool
, toggle
); 
 450 void wxToolBarBase::SetToggle(int id
, bool toggle
) 
 452     wxToolBarToolBase 
*tool 
= FindById(id
); 
 455         if ( tool
->SetToggle(toggle
) ) 
 457             DoSetToggle(tool
, toggle
); 
 462 void wxToolBarBase::SetToolShortHelp(int id
, const wxString
& help
) 
 464     wxToolBarToolBase 
*tool 
= FindById(id
); 
 467         (void)tool
->SetShortHelp(help
); 
 471 void wxToolBarBase::SetToolLongHelp(int id
, const wxString
& help
) 
 473     wxToolBarToolBase 
*tool 
= FindById(id
); 
 476         (void)tool
->SetLongHelp(help
); 
 480 wxObject 
*wxToolBarBase::GetToolClientData(int id
) const 
 482     wxToolBarToolBase 
*tool 
= FindById(id
); 
 484     return tool 
? tool
->GetClientData() : (wxObject 
*)NULL
; 
 487 void wxToolBarBase::SetToolClientData(int id
, wxObject 
*clientData
) 
 489     wxToolBarToolBase 
*tool 
= FindById(id
); 
 491     wxCHECK_RET( tool
, _T("no such tool in wxToolBar::SetToolClientData") ); 
 493     tool
->SetClientData(clientData
); 
 496 int wxToolBarBase::GetToolPos(int id
) const 
 499     wxToolBarToolsList::compatibility_iterator node
; 
 501     for ( node 
= m_tools
.GetFirst(); node
; node 
= node
->GetNext() ) 
 503         if ( node
->GetData()->GetId() == id 
) 
 512 bool wxToolBarBase::GetToolState(int id
) const 
 514     wxToolBarToolBase 
*tool 
= FindById(id
); 
 515     wxCHECK_MSG( tool
, false, _T("no such tool") ); 
 517     return tool
->IsToggled(); 
 520 bool wxToolBarBase::GetToolEnabled(int id
) const 
 522     wxToolBarToolBase 
*tool 
= FindById(id
); 
 523     wxCHECK_MSG( tool
, false, _T("no such tool") ); 
 525     return tool
->IsEnabled(); 
 528 wxString 
wxToolBarBase::GetToolShortHelp(int id
) const 
 530     wxToolBarToolBase 
*tool 
= FindById(id
); 
 531     wxCHECK_MSG( tool
, _T(""), _T("no such tool") ); 
 533     return tool
->GetShortHelp(); 
 536 wxString 
wxToolBarBase::GetToolLongHelp(int id
) const 
 538     wxToolBarToolBase 
*tool 
= FindById(id
); 
 539     wxCHECK_MSG( tool
, _T(""), _T("no such tool") ); 
 541     return tool
->GetLongHelp(); 
 544 // ---------------------------------------------------------------------------- 
 545 // wxToolBarBase geometry 
 546 // ---------------------------------------------------------------------------- 
 548 void wxToolBarBase::SetMargins(int x
, int y
) 
 554 void wxToolBarBase::SetRows(int WXUNUSED(nRows
)) 
 559 // ---------------------------------------------------------------------------- 
 561 // ---------------------------------------------------------------------------- 
 563 // Only allow toggle if returns true 
 564 bool wxToolBarBase::OnLeftClick(int id
, bool toggleDown
) 
 566     wxCommandEvent 
event(wxEVT_COMMAND_TOOL_CLICKED
, id
); 
 567     event
.SetEventObject(this); 
 569     // we use SetInt() to make wxCommandEvent::IsChecked() return toggleDown 
 570     event
.SetInt((int)toggleDown
); 
 572     // and SetExtraLong() for backwards compatibility 
 573     event
.SetExtraLong((long)toggleDown
); 
 575     // Send events to this toolbar instead (and thence up the window hierarchy) 
 576     GetEventHandler()->ProcessEvent(event
); 
 581 // Call when right button down. 
 582 void wxToolBarBase::OnRightClick(int id
, 
 586     wxCommandEvent 
event(wxEVT_COMMAND_TOOL_RCLICKED
, id
); 
 587     event
.SetEventObject(this); 
 590     GetEventHandler()->ProcessEvent(event
); 
 593 // Called when the mouse cursor enters a tool bitmap (no button pressed). 
 594 // Argument is -1 if mouse is exiting the toolbar. 
 595 // Note that for this event, the id of the window is used, 
 596 // and the integer parameter of wxCommandEvent is used to retrieve 
 598 void wxToolBarBase::OnMouseEnter(int id
) 
 600     wxCommandEvent 
event(wxEVT_COMMAND_TOOL_ENTER
, GetId()); 
 601     event
.SetEventObject(this); 
 604     wxFrame 
*frame 
= wxDynamicCast(GetParent(), wxFrame
); 
 607         wxToolBarToolBase
* tool 
= id 
== -1 ? (wxToolBarToolBase
*)0 : FindById(id
); 
 608         wxString help 
= tool 
? tool
->GetLongHelp() : wxString(); 
 609         frame
->DoGiveHelp( help
, id 
!= -1 ); 
 612     (void)GetEventHandler()->ProcessEvent(event
); 
 615 // ---------------------------------------------------------------------------- 
 617 // ---------------------------------------------------------------------------- 
 619 // Do the toolbar button updates (check for EVT_UPDATE_UI handlers) 
 620 void wxToolBarBase::UpdateWindowUI(long flags
) 
 622     wxWindowBase::UpdateWindowUI(flags
); 
 624     wxEvtHandler
* evtHandler 
= GetEventHandler() ; 
 626     for ( wxToolBarToolsList::compatibility_iterator node 
= m_tools
.GetFirst(); 
 628           node 
= node
->GetNext() ) 
 630         int id 
= node
->GetData()->GetId(); 
 632         wxUpdateUIEvent 
event(id
); 
 633         event
.SetEventObject(this); 
 635         if ( evtHandler
->ProcessEvent(event
) ) 
 637             if ( event
.GetSetEnabled() ) 
 638                 EnableTool(id
, event
.GetEnabled()); 
 639             if ( event
.GetSetChecked() ) 
 640                 ToggleTool(id
, event
.GetChecked()); 
 642             if ( event
.GetSetText() ) 
 649 // Helper function, used by wxCreateGreyedImage 
 651 static void wxGreyOutImage( const wxImage
& src
, 
 653                             const wxColour
& darkCol
, 
 654                             const wxColour
& lightCol
, 
 655                             const wxColour
& bgCol 
) 
 657     // Second attempt, just making things monochrome 
 658     int width 
= src
.GetWidth(); 
 659     int height 
= src
.GetHeight(); 
 661     int redCur
, greenCur
, blueCur
; 
 662     for ( int x 
= 0; x 
< width
; x
++ ) 
 664         for ( int y 
= 1; y 
< height
; y
++ ) 
 666             redCur 
= src
.GetRed(x
, y
); 
 667             greenCur 
= src
.GetGreen(x
, y
); 
 668             blueCur 
= src
.GetBlue(x
, y
); 
 670             // Change light things to the background colour 
 671             if ( redCur 
>= (lightCol
.Red() - 50) && greenCur 
>= (lightCol
.Green() - 50) && blueCur 
>= (lightCol
.Blue() - 50) ) 
 673                 dest
.SetRGB(x
,y
, bgCol
.Red(), bgCol
.Green(), bgCol
.Blue()); 
 675             else if ( redCur 
== bgCol
.Red() && greenCur 
== bgCol
.Green() && blueCur 
== bgCol
.Blue() ) 
 677                 // Leave the background colour as-is 
 678                 // dest.SetRGB(x,y, bgCol.Red(), bgCol.Green(), bgCol.Blue()); 
 680             else // if ( redCur <= darkCol.Red() && greenCur <= darkCol.Green() && blueCur <= darkCol.Blue() ) 
 682                 // Change dark things to really dark 
 683                 dest
.SetRGB(x
,y
, darkCol
.Red(), darkCol
.Green(), darkCol
.Blue()); 
 690  * Make a greyed-out image suitable for disabled buttons. 
 691  * This code is adapted from wxNewBitmapButton in FL. 
 694 bool wxCreateGreyedImage(const wxImage
& in
, wxImage
& out
) 
 698     // assuming the pixels along the edges are of the background color 
 699     wxColour 
bgCol(in
.GetRed(0, 0), in
.GetGreen(0, 0), in
.GetBlue(0, 0)); 
 701     wxColour darkCol 
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
) ; 
 702     wxColour lightCol 
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT
) ; 
 704     wxGreyOutImage(in
, out
, darkCol
, lightCol
, bgCol
); 
 709 #endif // wxUSE_TOOLBAR