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 // ---------------------------------------------------------------------------- 
 118 // wxToolBarBase adding/deleting items 
 119 // ---------------------------------------------------------------------------- 
 121 wxToolBarBase::wxToolBarBase() 
 123     // the list owns the pointers 
 124     m_xMargin 
= m_yMargin 
= 0; 
 126     m_maxRows 
= m_maxCols 
= 0; 
 129 wxToolBarToolBase 
*wxToolBarBase::DoAddTool(int id
, 
 130                                             const wxString
& label
, 
 131                                             const wxBitmap
& bitmap
, 
 132                                             const wxBitmap
& bmpDisabled
, 
 134                                             const wxString
& shortHelp
, 
 135                                             const wxString
& longHelp
, 
 136                                             wxObject 
*clientData
, 
 137                                             wxCoord 
WXUNUSED(xPos
), 
 138                                             wxCoord 
WXUNUSED(yPos
)) 
 140     InvalidateBestSize(); 
 141     return InsertTool(GetToolsCount(), id
, label
, bitmap
, bmpDisabled
, 
 142                       kind
, shortHelp
, longHelp
, clientData
); 
 145 wxToolBarToolBase 
*wxToolBarBase::InsertTool(size_t pos
, 
 147                                              const wxString
& label
, 
 148                                              const wxBitmap
& bitmap
, 
 149                                              const wxBitmap
& bmpDisabled
, 
 151                                              const wxString
& shortHelp
, 
 152                                              const wxString
& longHelp
, 
 153                                              wxObject 
*clientData
) 
 155     wxCHECK_MSG( pos 
<= GetToolsCount(), (wxToolBarToolBase 
*)NULL
, 
 156                  _T("invalid position in wxToolBar::InsertTool()") ); 
 158     wxToolBarToolBase 
*tool 
= CreateTool(id
, label
, bitmap
, bmpDisabled
, kind
, 
 159                                          clientData
, shortHelp
, longHelp
); 
 161     if ( !InsertTool(pos
, tool
) ) 
 171 wxToolBarToolBase 
*wxToolBarBase::AddTool(wxToolBarToolBase 
*tool
) 
 173     return InsertTool(GetToolsCount(), tool
); 
 177 wxToolBarBase::InsertTool(size_t pos
, wxToolBarToolBase 
*tool
) 
 179     wxCHECK_MSG( pos 
<= GetToolsCount(), (wxToolBarToolBase 
*)NULL
, 
 180                  _T("invalid position in wxToolBar::InsertTool()") ); 
 182     if ( !tool 
|| !DoInsertTool(pos
, tool
) ) 
 187     m_tools
.Insert(pos
, tool
); 
 192 wxToolBarToolBase 
*wxToolBarBase::AddControl(wxControl 
*control
) 
 194     return InsertControl(GetToolsCount(), control
); 
 197 wxToolBarToolBase 
*wxToolBarBase::InsertControl(size_t pos
, wxControl 
*control
) 
 199     wxCHECK_MSG( control
, (wxToolBarToolBase 
*)NULL
, 
 200                  _T("toolbar: can't insert NULL control") ); 
 202     wxCHECK_MSG( control
->GetParent() == this, (wxToolBarToolBase 
*)NULL
, 
 203                  _T("control must have toolbar as parent") ); 
 205     wxCHECK_MSG( pos 
<= GetToolsCount(), (wxToolBarToolBase 
*)NULL
, 
 206                  _T("invalid position in wxToolBar::InsertControl()") ); 
 208     wxToolBarToolBase 
*tool 
= CreateTool(control
); 
 210     if ( !InsertTool(pos
, tool
) ) 
 220 wxControl 
*wxToolBarBase::FindControl( int id 
) 
 222     for ( wxToolBarToolsList::compatibility_iterator node 
= m_tools
.GetFirst(); 
 224           node 
= node
->GetNext() ) 
 226         const wxToolBarToolBase 
* const tool 
= node
->GetData(); 
 227         if ( tool
->IsControl() ) 
 229             wxControl 
* const control 
= tool
->GetControl(); 
 233                 wxFAIL_MSG( _T("NULL control in toolbar?") ); 
 235             else if ( control
->GetId() == id 
) 
 246 wxToolBarToolBase 
*wxToolBarBase::AddSeparator() 
 248     return InsertSeparator(GetToolsCount()); 
 251 wxToolBarToolBase 
*wxToolBarBase::InsertSeparator(size_t pos
) 
 253     wxCHECK_MSG( pos 
<= GetToolsCount(), (wxToolBarToolBase 
*)NULL
, 
 254                  _T("invalid position in wxToolBar::InsertSeparator()") ); 
 256     wxToolBarToolBase 
*tool 
= CreateTool(wxID_SEPARATOR
, 
 258                                          wxNullBitmap
, wxNullBitmap
, 
 259                                          wxITEM_SEPARATOR
, (wxObject 
*)NULL
, 
 260                                          wxEmptyString
, wxEmptyString
); 
 262     if ( !tool 
|| !DoInsertTool(pos
, tool
) ) 
 269     m_tools
.Insert(pos
, tool
); 
 274 wxToolBarToolBase 
*wxToolBarBase::RemoveTool(int id
) 
 277     wxToolBarToolsList::compatibility_iterator node
; 
 278     for ( node 
= m_tools
.GetFirst(); node
; node 
= node
->GetNext() ) 
 280         if ( node
->GetData()->GetId() == id 
) 
 288         // don't give any error messages - sometimes we might call RemoveTool() 
 289         // without knowing whether the tool is or not in the toolbar 
 290         return (wxToolBarToolBase 
*)NULL
; 
 293     wxToolBarToolBase 
*tool 
= node
->GetData(); 
 294     if ( !DoDeleteTool(pos
, tool
) ) 
 296         return (wxToolBarToolBase 
*)NULL
; 
 304 bool wxToolBarBase::DeleteToolByPos(size_t pos
) 
 306     wxCHECK_MSG( pos 
< GetToolsCount(), false, 
 307                  _T("invalid position in wxToolBar::DeleteToolByPos()") ); 
 309     wxToolBarToolsList::compatibility_iterator node 
= m_tools
.Item(pos
); 
 311     if ( !DoDeleteTool(pos
, node
->GetData()) ) 
 316     delete node
->GetData(); 
 322 bool wxToolBarBase::DeleteTool(int id
) 
 325     wxToolBarToolsList::compatibility_iterator node
; 
 326     for ( node 
= m_tools
.GetFirst(); node
; node 
= node
->GetNext() ) 
 328         if ( node
->GetData()->GetId() == id 
) 
 334     if ( !node 
|| !DoDeleteTool(pos
, node
->GetData()) ) 
 339     delete node
->GetData(); 
 345 wxToolBarToolBase 
*wxToolBarBase::FindById(int id
) const 
 347     wxToolBarToolBase 
*tool 
= (wxToolBarToolBase 
*)NULL
; 
 349     for ( wxToolBarToolsList::compatibility_iterator node 
= m_tools
.GetFirst(); 
 351           node 
= node
->GetNext() ) 
 353         tool 
= node
->GetData(); 
 354         if ( tool
->GetId() == id 
) 
 366 void wxToolBarBase::UnToggleRadioGroup(wxToolBarToolBase 
*tool
) 
 368     wxCHECK_RET( tool
, _T("NULL tool in wxToolBarTool::UnToggleRadioGroup") ); 
 370     if ( !tool
->IsButton() || tool
->GetKind() != wxITEM_RADIO 
) 
 373     wxToolBarToolsList::compatibility_iterator node 
= m_tools
.Find(tool
); 
 374     wxCHECK_RET( node
, _T("invalid tool in wxToolBarTool::UnToggleRadioGroup") ); 
 376     wxToolBarToolsList::compatibility_iterator nodeNext 
= node
->GetNext(); 
 379         wxToolBarToolBase 
*tool 
= nodeNext
->GetData(); 
 381         if ( !tool
->IsButton() || tool
->GetKind() != wxITEM_RADIO 
) 
 384         if ( tool
->Toggle(false) ) 
 386             DoToggleTool(tool
, false); 
 389         nodeNext 
= nodeNext
->GetNext(); 
 392     wxToolBarToolsList::compatibility_iterator nodePrev 
= node
->GetPrevious(); 
 395         wxToolBarToolBase 
*tool 
= nodePrev
->GetData(); 
 397         if ( !tool
->IsButton() || tool
->GetKind() != wxITEM_RADIO 
) 
 400         if ( tool
->Toggle(false) ) 
 402             DoToggleTool(tool
, false); 
 405         nodePrev 
= nodePrev
->GetPrevious(); 
 409 void wxToolBarBase::ClearTools() 
 411     WX_CLEAR_LIST(wxToolBarToolsList
, m_tools
); 
 414 bool wxToolBarBase::Realize() 
 419 wxToolBarBase::~wxToolBarBase() 
 421     WX_CLEAR_LIST(wxToolBarToolsList
, m_tools
); 
 423     // notify the frame that it doesn't have a tool bar any longer to avoid 
 425     wxFrameBase 
*frame 
= wxDynamicCast(GetParent(), wxFrameBase
); 
 426     if ( frame 
&& frame
->GetToolBar() == this ) 
 428         frame
->SetToolBar(NULL
); 
 432 // ---------------------------------------------------------------------------- 
 433 // wxToolBarBase tools state 
 434 // ---------------------------------------------------------------------------- 
 436 void wxToolBarBase::EnableTool(int id
, bool enable
) 
 438     wxToolBarToolBase 
*tool 
= FindById(id
); 
 441         if ( tool
->Enable(enable
) ) 
 443             DoEnableTool(tool
, enable
); 
 448 void wxToolBarBase::ToggleTool(int id
, bool toggle
) 
 450     wxToolBarToolBase 
*tool 
= FindById(id
); 
 451     if ( tool 
&& tool
->CanBeToggled() ) 
 453         if ( tool
->Toggle(toggle
) ) 
 455             UnToggleRadioGroup(tool
); 
 456             DoToggleTool(tool
, toggle
); 
 461 void wxToolBarBase::SetToggle(int id
, bool toggle
) 
 463     wxToolBarToolBase 
*tool 
= FindById(id
); 
 466         if ( tool
->SetToggle(toggle
) ) 
 468             DoSetToggle(tool
, toggle
); 
 473 void wxToolBarBase::SetToolShortHelp(int id
, const wxString
& help
) 
 475     wxToolBarToolBase 
*tool 
= FindById(id
); 
 478         (void)tool
->SetShortHelp(help
); 
 482 void wxToolBarBase::SetToolLongHelp(int id
, const wxString
& help
) 
 484     wxToolBarToolBase 
*tool 
= FindById(id
); 
 487         (void)tool
->SetLongHelp(help
); 
 491 wxObject 
*wxToolBarBase::GetToolClientData(int id
) const 
 493     wxToolBarToolBase 
*tool 
= FindById(id
); 
 495     return tool 
? tool
->GetClientData() : (wxObject 
*)NULL
; 
 498 void wxToolBarBase::SetToolClientData(int id
, wxObject 
*clientData
) 
 500     wxToolBarToolBase 
*tool 
= FindById(id
); 
 502     wxCHECK_RET( tool
, _T("no such tool in wxToolBar::SetToolClientData") ); 
 504     tool
->SetClientData(clientData
); 
 507 int wxToolBarBase::GetToolPos(int id
) const 
 510     wxToolBarToolsList::compatibility_iterator node
; 
 512     for ( node 
= m_tools
.GetFirst(); node
; node 
= node
->GetNext() ) 
 514         if ( node
->GetData()->GetId() == id 
) 
 523 bool wxToolBarBase::GetToolState(int id
) const 
 525     wxToolBarToolBase 
*tool 
= FindById(id
); 
 526     wxCHECK_MSG( tool
, false, _T("no such tool") ); 
 528     return tool
->IsToggled(); 
 531 bool wxToolBarBase::GetToolEnabled(int id
) const 
 533     wxToolBarToolBase 
*tool 
= FindById(id
); 
 534     wxCHECK_MSG( tool
, false, _T("no such tool") ); 
 536     return tool
->IsEnabled(); 
 539 wxString 
wxToolBarBase::GetToolShortHelp(int id
) const 
 541     wxToolBarToolBase 
*tool 
= FindById(id
); 
 542     wxCHECK_MSG( tool
, _T(""), _T("no such tool") ); 
 544     return tool
->GetShortHelp(); 
 547 wxString 
wxToolBarBase::GetToolLongHelp(int id
) const 
 549     wxToolBarToolBase 
*tool 
= FindById(id
); 
 550     wxCHECK_MSG( tool
, _T(""), _T("no such tool") ); 
 552     return tool
->GetLongHelp(); 
 555 // ---------------------------------------------------------------------------- 
 556 // wxToolBarBase geometry 
 557 // ---------------------------------------------------------------------------- 
 559 void wxToolBarBase::SetMargins(int x
, int y
) 
 565 void wxToolBarBase::SetRows(int WXUNUSED(nRows
)) 
 570 // ---------------------------------------------------------------------------- 
 572 // ---------------------------------------------------------------------------- 
 574 // Only allow toggle if returns true 
 575 bool wxToolBarBase::OnLeftClick(int id
, bool toggleDown
) 
 577     wxCommandEvent 
event(wxEVT_COMMAND_TOOL_CLICKED
, id
); 
 578     event
.SetEventObject(this); 
 580     // we use SetInt() to make wxCommandEvent::IsChecked() return toggleDown 
 581     event
.SetInt((int)toggleDown
); 
 583     // and SetExtraLong() for backwards compatibility 
 584     event
.SetExtraLong((long)toggleDown
); 
 586     // Send events to this toolbar instead (and thence up the window hierarchy) 
 587     GetEventHandler()->ProcessEvent(event
); 
 592 // Call when right button down. 
 593 void wxToolBarBase::OnRightClick(int id
, 
 597     wxCommandEvent 
event(wxEVT_COMMAND_TOOL_RCLICKED
, id
); 
 598     event
.SetEventObject(this); 
 601     GetEventHandler()->ProcessEvent(event
); 
 604 // Called when the mouse cursor enters a tool bitmap (no button pressed). 
 605 // Argument is wxID_ANY if mouse is exiting the toolbar. 
 606 // Note that for this event, the id of the window is used, 
 607 // and the integer parameter of wxCommandEvent is used to retrieve 
 609 void wxToolBarBase::OnMouseEnter(int id
) 
 611     wxCommandEvent 
event(wxEVT_COMMAND_TOOL_ENTER
, GetId()); 
 612     event
.SetEventObject(this); 
 615     wxFrame 
*frame 
= wxDynamicCast(GetParent(), wxFrame
); 
 619         wxToolBarToolBase
* tool 
= id 
== wxID_ANY 
? (wxToolBarToolBase
*)NULL 
: FindById(id
); 
 621             help 
= tool
->GetLongHelp(); 
 622         frame
->DoGiveHelp( help
, id 
!= wxID_ANY 
); 
 625     (void)GetEventHandler()->ProcessEvent(event
); 
 628 // ---------------------------------------------------------------------------- 
 630 // ---------------------------------------------------------------------------- 
 632 // Do the toolbar button updates (check for EVT_UPDATE_UI handlers) 
 633 void wxToolBarBase::UpdateWindowUI(long flags
) 
 635     wxWindowBase::UpdateWindowUI(flags
); 
 637     // There is no sense in updating the toolbar UI 
 638     // if the parent window is about to get destroyed 
 639     wxWindow 
*tlw 
= wxGetTopLevelParent( this ); 
 640     if (tlw 
&& wxPendingDelete
.Member( tlw 
)) 
 643     wxEvtHandler
* evtHandler 
= GetEventHandler() ; 
 645     for ( wxToolBarToolsList::compatibility_iterator node 
= m_tools
.GetFirst(); 
 647           node 
= node
->GetNext() ) 
 649         int id 
= node
->GetData()->GetId(); 
 651         wxUpdateUIEvent 
event(id
); 
 652         event
.SetEventObject(this); 
 654         if ( evtHandler
->ProcessEvent(event
) ) 
 656             if ( event
.GetSetEnabled() ) 
 657                 EnableTool(id
, event
.GetEnabled()); 
 658             if ( event
.GetSetChecked() ) 
 659                 ToggleTool(id
, event
.GetChecked()); 
 661             if ( event
.GetSetText() ) 
 668 // Helper function, used by wxCreateGreyedImage 
 670 static void wxGreyOutImage( const wxImage
& src
, 
 672                             const wxColour
& darkCol
, 
 673                             const wxColour
& lightCol
, 
 674                             const wxColour
& bgCol 
) 
 676     // Second attempt, just making things monochrome 
 677     int width 
= src
.GetWidth(); 
 678     int height 
= src
.GetHeight(); 
 680     int redCur
, greenCur
, blueCur
; 
 681     for ( int x 
= 0; x 
< width
; x
++ ) 
 683         for ( int y 
= 1; y 
< height
; y
++ ) 
 685             redCur 
= src
.GetRed(x
, y
); 
 686             greenCur 
= src
.GetGreen(x
, y
); 
 687             blueCur 
= src
.GetBlue(x
, y
); 
 689             // Change light things to the background colour 
 690             if ( redCur 
>= (lightCol
.Red() - 50) && greenCur 
>= (lightCol
.Green() - 50) && blueCur 
>= (lightCol
.Blue() - 50) ) 
 692                 dest
.SetRGB(x
,y
, bgCol
.Red(), bgCol
.Green(), bgCol
.Blue()); 
 694             else if ( redCur 
== bgCol
.Red() && greenCur 
== bgCol
.Green() && blueCur 
== bgCol
.Blue() ) 
 696                 // Leave the background colour as-is 
 697                 // dest.SetRGB(x,y, bgCol.Red(), bgCol.Green(), bgCol.Blue()); 
 699             else // if ( redCur <= darkCol.Red() && greenCur <= darkCol.Green() && blueCur <= darkCol.Blue() ) 
 701                 // Change dark things to really dark 
 702                 dest
.SetRGB(x
,y
, darkCol
.Red(), darkCol
.Green(), darkCol
.Blue()); 
 709  * Make a greyed-out image suitable for disabled buttons. 
 710  * This code is adapted from wxNewBitmapButton in FL. 
 713 bool wxCreateGreyedImage(const wxImage
& in
, wxImage
& out
) 
 717     // assuming the pixels along the edges are of the background color 
 718     wxColour 
bgCol(in
.GetRed(0, 0), in
.GetGreen(0, 0), in
.GetBlue(0, 0)); 
 720     wxColour darkCol 
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
) ; 
 721     wxColour lightCol 
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT
) ; 
 723     wxGreyOutImage(in
, out
, darkCol
, lightCol
, bgCol
); 
 728 #endif // wxUSE_TOOLBAR