1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        common/tbarbase.cpp 
   3 // Purpose:     wxToolBarBase implementation 
   4 // Author:      Julian Smart 
   5 // Modified by: VZ at 11.12.99 (wxScrollableToolBar split off) 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // For compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  30     #include "wx/control.h" 
  37     #include "wx/settings.h" 
  40 #include "wx/toolbar.h" 
  42 // ---------------------------------------------------------------------------- 
  44 // ---------------------------------------------------------------------------- 
  46 BEGIN_EVENT_TABLE(wxToolBarBase
, wxControl
) 
  49 #include "wx/listimpl.cpp" 
  51 WX_DEFINE_LIST(wxToolBarToolsList
); 
  53 // ============================================================================ 
  55 // ============================================================================ 
  57 // ---------------------------------------------------------------------------- 
  59 // ---------------------------------------------------------------------------- 
  61 IMPLEMENT_DYNAMIC_CLASS(wxToolBarToolBase
, wxObject
) 
  63 bool wxToolBarToolBase::Enable(bool enable
) 
  65     if ( m_enabled 
== enable 
) 
  73 bool wxToolBarToolBase::Toggle(bool toggle
) 
  75     wxASSERT_MSG( CanBeToggled(), _T("can't toggle this tool") ); 
  77     if ( m_toggled 
== toggle 
) 
  85 bool wxToolBarToolBase::SetToggle(bool toggle
) 
  87     wxItemKind kind 
= toggle 
? wxITEM_CHECK 
: wxITEM_NORMAL
; 
  96 bool wxToolBarToolBase::SetShortHelp(const wxString
& help
) 
  98     if ( m_shortHelpString 
== help 
) 
 101     m_shortHelpString 
= help
; 
 106 bool wxToolBarToolBase::SetLongHelp(const wxString
& help
) 
 108     if ( m_longHelpString 
== help 
) 
 111     m_longHelpString 
= help
; 
 116 #if WXWIN_COMPATIBILITY_2_2 
 118 const wxBitmap
& wxToolBarToolBase::GetBitmap1() const 
 120     return GetNormalBitmap(); 
 123 const wxBitmap
& wxToolBarToolBase::GetBitmap2() const 
 125     return GetDisabledBitmap(); 
 128 void wxToolBarToolBase::SetBitmap1(const wxBitmap
& bmp
) 
 130     SetNormalBitmap(bmp
); 
 133 void wxToolBarToolBase::SetBitmap2(const wxBitmap
& bmp
) 
 135     SetDisabledBitmap(bmp
); 
 138 #endif // WXWIN_COMPATIBILITY_2_2 
 140 // ---------------------------------------------------------------------------- 
 141 // wxToolBarBase adding/deleting items 
 142 // ---------------------------------------------------------------------------- 
 144 wxToolBarBase::wxToolBarBase() 
 146     // the list owns the pointers 
 147     m_xMargin 
= m_yMargin 
= 0; 
 148     m_maxRows 
= m_maxCols 
= 0; 
 149     m_toolPacking 
= m_toolSeparation 
= 0; 
 151     m_defaultHeight 
= 15; 
 154 wxToolBarToolBase 
*wxToolBarBase::DoAddTool(int id
, 
 155                                             const wxString
& label
, 
 156                                             const wxBitmap
& bitmap
, 
 157                                             const wxBitmap
& bmpDisabled
, 
 159                                             const wxString
& shortHelp
, 
 160                                             const wxString
& longHelp
, 
 161                                             wxObject 
*clientData
, 
 162                                             wxCoord 
WXUNUSED(xPos
), 
 163                                             wxCoord 
WXUNUSED(yPos
)) 
 165     InvalidateBestSize(); 
 166     return InsertTool(GetToolsCount(), id
, label
, bitmap
, bmpDisabled
, 
 167                       kind
, shortHelp
, longHelp
, clientData
); 
 170 wxToolBarToolBase 
*wxToolBarBase::InsertTool(size_t pos
, 
 172                                              const wxString
& label
, 
 173                                              const wxBitmap
& bitmap
, 
 174                                              const wxBitmap
& bmpDisabled
, 
 176                                              const wxString
& shortHelp
, 
 177                                              const wxString
& longHelp
, 
 178                                              wxObject 
*clientData
) 
 180     wxCHECK_MSG( pos 
<= GetToolsCount(), (wxToolBarToolBase 
*)NULL
, 
 181                  _T("invalid position in wxToolBar::InsertTool()") ); 
 183     wxToolBarToolBase 
*tool 
= CreateTool(id
, label
, bitmap
, bmpDisabled
, kind
, 
 184                                          clientData
, shortHelp
, longHelp
); 
 186     if ( !InsertTool(pos
, tool
) ) 
 196 wxToolBarToolBase 
*wxToolBarBase::AddTool(wxToolBarToolBase 
*tool
) 
 198     return InsertTool(GetToolsCount(), tool
); 
 202 wxToolBarBase::InsertTool(size_t pos
, wxToolBarToolBase 
*tool
) 
 204     wxCHECK_MSG( pos 
<= GetToolsCount(), (wxToolBarToolBase 
*)NULL
, 
 205                  _T("invalid position in wxToolBar::InsertTool()") ); 
 207     if ( !tool 
|| !DoInsertTool(pos
, tool
) ) 
 212     m_tools
.Insert(pos
, tool
); 
 217 wxToolBarToolBase 
*wxToolBarBase::AddControl(wxControl 
*control
) 
 219     return InsertControl(GetToolsCount(), control
); 
 222 wxToolBarToolBase 
*wxToolBarBase::InsertControl(size_t pos
, wxControl 
*control
) 
 224     wxCHECK_MSG( control
, (wxToolBarToolBase 
*)NULL
, 
 225                  _T("toolbar: can't insert NULL control") ); 
 227     wxCHECK_MSG( control
->GetParent() == this, (wxToolBarToolBase 
*)NULL
, 
 228                  _T("control must have toolbar as parent") ); 
 230     wxCHECK_MSG( pos 
<= GetToolsCount(), (wxToolBarToolBase 
*)NULL
, 
 231                  _T("invalid position in wxToolBar::InsertControl()") ); 
 233     wxToolBarToolBase 
*tool 
= CreateTool(control
); 
 235     if ( !InsertTool(pos
, tool
) ) 
 245 wxControl 
*wxToolBarBase::FindControl( int id 
) 
 247     for ( wxToolBarToolsList::compatibility_iterator node 
= m_tools
.GetFirst(); 
 249           node 
= node
->GetNext() ) 
 251         const wxToolBarToolBase 
* const tool 
= node
->GetData(); 
 252         if ( tool
->IsControl() ) 
 254             wxControl 
* const control 
= tool
->GetControl(); 
 258                 wxFAIL_MSG( _T("NULL control in toolbar?") ); 
 260             else if ( control
->GetId() == id 
) 
 271 wxToolBarToolBase 
*wxToolBarBase::AddSeparator() 
 273     return InsertSeparator(GetToolsCount()); 
 276 wxToolBarToolBase 
*wxToolBarBase::InsertSeparator(size_t pos
) 
 278     wxCHECK_MSG( pos 
<= GetToolsCount(), (wxToolBarToolBase 
*)NULL
, 
 279                  _T("invalid position in wxToolBar::InsertSeparator()") ); 
 281     wxToolBarToolBase 
*tool 
= CreateTool(wxID_SEPARATOR
, 
 283                                          wxNullBitmap
, wxNullBitmap
, 
 284                                          wxITEM_SEPARATOR
, (wxObject 
*)NULL
, 
 285                                          wxEmptyString
, wxEmptyString
); 
 287     if ( !tool 
|| !DoInsertTool(pos
, tool
) ) 
 294     m_tools
.Insert(pos
, tool
); 
 299 wxToolBarToolBase 
*wxToolBarBase::RemoveTool(int id
) 
 302     wxToolBarToolsList::compatibility_iterator node
; 
 303     for ( node 
= m_tools
.GetFirst(); node
; node 
= node
->GetNext() ) 
 305         if ( node
->GetData()->GetId() == id 
) 
 313         // don't give any error messages - sometimes we might call RemoveTool() 
 314         // without knowing whether the tool is or not in the toolbar 
 315         return (wxToolBarToolBase 
*)NULL
; 
 318     wxToolBarToolBase 
*tool 
= node
->GetData(); 
 319     if ( !DoDeleteTool(pos
, tool
) ) 
 321         return (wxToolBarToolBase 
*)NULL
; 
 329 bool wxToolBarBase::DeleteToolByPos(size_t pos
) 
 331     wxCHECK_MSG( pos 
< GetToolsCount(), false, 
 332                  _T("invalid position in wxToolBar::DeleteToolByPos()") ); 
 334     wxToolBarToolsList::compatibility_iterator node 
= m_tools
.Item(pos
); 
 336     if ( !DoDeleteTool(pos
, node
->GetData()) ) 
 341     delete node
->GetData(); 
 347 bool wxToolBarBase::DeleteTool(int id
) 
 350     wxToolBarToolsList::compatibility_iterator node
; 
 351     for ( node 
= m_tools
.GetFirst(); node
; node 
= node
->GetNext() ) 
 353         if ( node
->GetData()->GetId() == id 
) 
 359     if ( !node 
|| !DoDeleteTool(pos
, node
->GetData()) ) 
 364     delete node
->GetData(); 
 370 wxToolBarToolBase 
*wxToolBarBase::FindById(int id
) const 
 372     wxToolBarToolBase 
*tool 
= (wxToolBarToolBase 
*)NULL
; 
 374     for ( wxToolBarToolsList::compatibility_iterator node 
= m_tools
.GetFirst(); 
 376           node 
= node
->GetNext() ) 
 378         tool 
= node
->GetData(); 
 379         if ( tool
->GetId() == id 
) 
 391 void wxToolBarBase::UnToggleRadioGroup(wxToolBarToolBase 
*tool
) 
 393     wxCHECK_RET( tool
, _T("NULL tool in wxToolBarTool::UnToggleRadioGroup") ); 
 395     if ( !tool
->IsButton() || tool
->GetKind() != wxITEM_RADIO 
) 
 398     wxToolBarToolsList::compatibility_iterator node 
= m_tools
.Find(tool
); 
 399     wxCHECK_RET( node
, _T("invalid tool in wxToolBarTool::UnToggleRadioGroup") ); 
 401     wxToolBarToolsList::compatibility_iterator nodeNext 
= node
->GetNext(); 
 404         wxToolBarToolBase 
*tool 
= nodeNext
->GetData(); 
 406         if ( !tool
->IsButton() || tool
->GetKind() != wxITEM_RADIO 
) 
 409         if ( tool
->Toggle(false) ) 
 411             DoToggleTool(tool
, false); 
 414         nodeNext 
= nodeNext
->GetNext(); 
 417     wxToolBarToolsList::compatibility_iterator nodePrev 
= node
->GetPrevious(); 
 420         wxToolBarToolBase 
*tool 
= nodePrev
->GetData(); 
 422         if ( !tool
->IsButton() || tool
->GetKind() != wxITEM_RADIO 
) 
 425         if ( tool
->Toggle(false) ) 
 427             DoToggleTool(tool
, false); 
 430         nodePrev 
= nodePrev
->GetPrevious(); 
 434 void wxToolBarBase::ClearTools() 
 436     WX_CLEAR_LIST(wxToolBarToolsList
, m_tools
); 
 439 bool wxToolBarBase::Realize() 
 444 wxToolBarBase::~wxToolBarBase() 
 446     WX_CLEAR_LIST(wxToolBarToolsList
, m_tools
); 
 448     // notify the frame that it doesn't have a tool bar any longer to avoid 
 450     wxFrame 
*frame 
= wxDynamicCast(GetParent(), wxFrame
); 
 451     if ( frame 
&& frame
->GetToolBar() == this ) 
 453         frame
->SetToolBar(NULL
); 
 457 // ---------------------------------------------------------------------------- 
 458 // wxToolBarBase tools state 
 459 // ---------------------------------------------------------------------------- 
 461 void wxToolBarBase::EnableTool(int id
, bool enable
) 
 463     wxToolBarToolBase 
*tool 
= FindById(id
); 
 466         if ( tool
->Enable(enable
) ) 
 468             DoEnableTool(tool
, enable
); 
 473 void wxToolBarBase::ToggleTool(int id
, bool toggle
) 
 475     wxToolBarToolBase 
*tool 
= FindById(id
); 
 476     if ( tool 
&& tool
->CanBeToggled() ) 
 478         if ( tool
->Toggle(toggle
) ) 
 480             UnToggleRadioGroup(tool
); 
 481             DoToggleTool(tool
, toggle
); 
 486 void wxToolBarBase::SetToggle(int id
, bool toggle
) 
 488     wxToolBarToolBase 
*tool 
= FindById(id
); 
 491         if ( tool
->SetToggle(toggle
) ) 
 493             DoSetToggle(tool
, toggle
); 
 498 void wxToolBarBase::SetToolShortHelp(int id
, const wxString
& help
) 
 500     wxToolBarToolBase 
*tool 
= FindById(id
); 
 503         (void)tool
->SetShortHelp(help
); 
 507 void wxToolBarBase::SetToolLongHelp(int id
, const wxString
& help
) 
 509     wxToolBarToolBase 
*tool 
= FindById(id
); 
 512         (void)tool
->SetLongHelp(help
); 
 516 wxObject 
*wxToolBarBase::GetToolClientData(int id
) const 
 518     wxToolBarToolBase 
*tool 
= FindById(id
); 
 520     return tool 
? tool
->GetClientData() : (wxObject 
*)NULL
; 
 523 void wxToolBarBase::SetToolClientData(int id
, wxObject 
*clientData
) 
 525     wxToolBarToolBase 
*tool 
= FindById(id
); 
 527     wxCHECK_RET( tool
, _T("no such tool in wxToolBar::SetToolClientData") ); 
 529     tool
->SetClientData(clientData
); 
 532 int wxToolBarBase::GetToolPos(int id
) const 
 535     wxToolBarToolsList::compatibility_iterator node
; 
 537     for ( node 
= m_tools
.GetFirst(); node
; node 
= node
->GetNext() ) 
 539         if ( node
->GetData()->GetId() == id 
) 
 548 bool wxToolBarBase::GetToolState(int id
) const 
 550     wxToolBarToolBase 
*tool 
= FindById(id
); 
 551     wxCHECK_MSG( tool
, false, _T("no such tool") ); 
 553     return tool
->IsToggled(); 
 556 bool wxToolBarBase::GetToolEnabled(int id
) const 
 558     wxToolBarToolBase 
*tool 
= FindById(id
); 
 559     wxCHECK_MSG( tool
, false, _T("no such tool") ); 
 561     return tool
->IsEnabled(); 
 564 wxString 
wxToolBarBase::GetToolShortHelp(int id
) const 
 566     wxToolBarToolBase 
*tool 
= FindById(id
); 
 567     wxCHECK_MSG( tool
, wxEmptyString
, _T("no such tool") ); 
 569     return tool
->GetShortHelp(); 
 572 wxString 
wxToolBarBase::GetToolLongHelp(int id
) const 
 574     wxToolBarToolBase 
*tool 
= FindById(id
); 
 575     wxCHECK_MSG( tool
, wxEmptyString
, _T("no such tool") ); 
 577     return tool
->GetLongHelp(); 
 580 // ---------------------------------------------------------------------------- 
 581 // wxToolBarBase geometry 
 582 // ---------------------------------------------------------------------------- 
 584 void wxToolBarBase::SetMargins(int x
, int y
) 
 590 void wxToolBarBase::SetRows(int WXUNUSED(nRows
)) 
 595 // ---------------------------------------------------------------------------- 
 597 // ---------------------------------------------------------------------------- 
 599 // Only allow toggle if returns true 
 600 bool wxToolBarBase::OnLeftClick(int id
, bool toggleDown
) 
 602     wxCommandEvent 
event(wxEVT_COMMAND_TOOL_CLICKED
, id
); 
 603     event
.SetEventObject(this); 
 605     // we use SetInt() to make wxCommandEvent::IsChecked() return toggleDown 
 606     event
.SetInt((int)toggleDown
); 
 608     // and SetExtraLong() for backwards compatibility 
 609     event
.SetExtraLong((long)toggleDown
); 
 611     // Send events to this toolbar instead (and thence up the window hierarchy) 
 612     GetEventHandler()->ProcessEvent(event
); 
 617 // Call when right button down. 
 618 void wxToolBarBase::OnRightClick(int id
, 
 622     wxCommandEvent 
event(wxEVT_COMMAND_TOOL_RCLICKED
, id
); 
 623     event
.SetEventObject(this); 
 626     GetEventHandler()->ProcessEvent(event
); 
 629 // Called when the mouse cursor enters a tool bitmap (no button pressed). 
 630 // Argument is wxID_ANY if mouse is exiting the toolbar. 
 631 // Note that for this event, the id of the window is used, 
 632 // and the integer parameter of wxCommandEvent is used to retrieve 
 634 void wxToolBarBase::OnMouseEnter(int id
) 
 636     wxCommandEvent 
event(wxEVT_COMMAND_TOOL_ENTER
, GetId()); 
 637     event
.SetEventObject(this); 
 640     wxFrame 
*frame 
= wxDynamicCast(GetParent(), wxFrame
); 
 644         wxToolBarToolBase
* tool 
= id 
== wxID_ANY 
? (wxToolBarToolBase
*)NULL 
: FindById(id
); 
 646             help 
= tool
->GetLongHelp(); 
 647         frame
->DoGiveHelp( help
, id 
!= wxID_ANY 
); 
 650     (void)GetEventHandler()->ProcessEvent(event
); 
 653 // ---------------------------------------------------------------------------- 
 655 // ---------------------------------------------------------------------------- 
 657 // Do the toolbar button updates (check for EVT_UPDATE_UI handlers) 
 658 void wxToolBarBase::UpdateWindowUI(long flags
) 
 660     wxWindowBase::UpdateWindowUI(flags
); 
 662     // There is no sense in updating the toolbar UI 
 663     // if the parent window is about to get destroyed 
 664     wxWindow 
*tlw 
= wxGetTopLevelParent( this ); 
 665     if (tlw 
&& wxPendingDelete
.Member( tlw 
)) 
 668     wxEvtHandler
* evtHandler 
= GetEventHandler() ; 
 670     for ( wxToolBarToolsList::compatibility_iterator node 
= m_tools
.GetFirst(); 
 672           node 
= node
->GetNext() ) 
 674         int id 
= node
->GetData()->GetId(); 
 676         wxUpdateUIEvent 
event(id
); 
 677         event
.SetEventObject(this); 
 679         if ( evtHandler
->ProcessEvent(event
) ) 
 681             if ( event
.GetSetEnabled() ) 
 682                 EnableTool(id
, event
.GetEnabled()); 
 683             if ( event
.GetSetChecked() ) 
 684                 ToggleTool(id
, event
.GetChecked()); 
 686             if ( event
.GetSetText() ) 
 696  * Make a greyed-out image suitable for disabled buttons. 
 697  * This code is adapted from wxNewBitmapButton in FL. 
 700 bool wxCreateGreyedImage(const wxImage
& src
, wxImage
& dst
) 
 704     unsigned char rBg
, gBg
, bBg
; 
 707         src
.GetOrFindMaskColour(&rBg
, &gBg
, &bBg
); 
 708         dst
.SetMaskColour(rBg
, gBg
, bBg
); 
 710     else // assuming the pixels along the edges are of the background color 
 712         rBg 
= src
.GetRed(0, 0); 
 713         gBg 
= src
.GetGreen(0, 0); 
 714         bBg 
= src
.GetBlue(0, 0); 
 717     const wxColour 
colBg(rBg
, gBg
, bBg
); 
 719     const wxColour colDark 
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
); 
 720     const wxColour colLight 
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT
); 
 722     // Second attempt, just making things monochrome 
 723     const int width 
= src
.GetWidth(); 
 724     const int height 
= src
.GetHeight(); 
 726     for ( int x 
= 0; x 
< width
; x
++ ) 
 728         for ( int y 
= 0; y 
< height
; y
++ ) 
 730             const int r 
= src
.GetRed(x
, y
); 
 731             const int g 
= src
.GetGreen(x
, y
); 
 732             const int b 
= src
.GetBlue(x
, y
); 
 734             if ( r 
== rBg 
&& g 
== gBg 
&& b 
== bBg 
) 
 736                 // Leave the background colour as-is 
 740             // Change light things to the background colour 
 742             if ( r 
>= (colLight
.Red() - 50) && 
 743                     g 
>= (colLight
.Green() - 50) && 
 744                         b 
>= (colLight
.Blue() - 50) ) 
 748             else // Change dark things to really dark 
 753             dst
.SetRGB(x
, y
, col
.Red(), col
.Green(), col
.Blue()); 
 760 #endif // wxUSE_IMAGE 
 762 #endif // wxUSE_TOOLBAR