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 // ---------------------------------------------------------------------------- 
 117 // wxToolBarBase adding/deleting items 
 118 // ---------------------------------------------------------------------------- 
 120 wxToolBarBase::wxToolBarBase() 
 122     // the list owns the pointers 
 123     m_xMargin 
= m_yMargin 
= 0; 
 124     m_maxRows 
= m_maxCols 
= 0; 
 125     m_toolPacking 
= m_toolSeparation 
= 0; 
 127     m_defaultHeight 
= 15; 
 130 wxToolBarToolBase 
*wxToolBarBase::DoAddTool(int id
, 
 131                                             const wxString
& label
, 
 132                                             const wxBitmap
& bitmap
, 
 133                                             const wxBitmap
& bmpDisabled
, 
 135                                             const wxString
& shortHelp
, 
 136                                             const wxString
& longHelp
, 
 137                                             wxObject 
*clientData
, 
 138                                             wxCoord 
WXUNUSED(xPos
), 
 139                                             wxCoord 
WXUNUSED(yPos
)) 
 141     InvalidateBestSize(); 
 142     return InsertTool(GetToolsCount(), id
, label
, bitmap
, bmpDisabled
, 
 143                       kind
, shortHelp
, longHelp
, clientData
); 
 146 wxToolBarToolBase 
*wxToolBarBase::InsertTool(size_t pos
, 
 148                                              const wxString
& label
, 
 149                                              const wxBitmap
& bitmap
, 
 150                                              const wxBitmap
& bmpDisabled
, 
 152                                              const wxString
& shortHelp
, 
 153                                              const wxString
& longHelp
, 
 154                                              wxObject 
*clientData
) 
 156     wxCHECK_MSG( pos 
<= GetToolsCount(), (wxToolBarToolBase 
*)NULL
, 
 157                  _T("invalid position in wxToolBar::InsertTool()") ); 
 159     wxToolBarToolBase 
*tool 
= CreateTool(id
, label
, bitmap
, bmpDisabled
, kind
, 
 160                                          clientData
, shortHelp
, longHelp
); 
 162     if ( !InsertTool(pos
, tool
) ) 
 172 wxToolBarToolBase 
*wxToolBarBase::AddTool(wxToolBarToolBase 
*tool
) 
 174     return InsertTool(GetToolsCount(), tool
); 
 178 wxToolBarBase::InsertTool(size_t pos
, wxToolBarToolBase 
*tool
) 
 180     wxCHECK_MSG( pos 
<= GetToolsCount(), (wxToolBarToolBase 
*)NULL
, 
 181                  _T("invalid position in wxToolBar::InsertTool()") ); 
 183     if ( !tool 
|| !DoInsertTool(pos
, tool
) ) 
 188     m_tools
.Insert(pos
, tool
); 
 193 wxToolBarToolBase 
*wxToolBarBase::AddControl(wxControl 
*control
) 
 195     return InsertControl(GetToolsCount(), control
); 
 198 wxToolBarToolBase 
*wxToolBarBase::InsertControl(size_t pos
, wxControl 
*control
) 
 200     wxCHECK_MSG( control
, (wxToolBarToolBase 
*)NULL
, 
 201                  _T("toolbar: can't insert NULL control") ); 
 203     wxCHECK_MSG( control
->GetParent() == this, (wxToolBarToolBase 
*)NULL
, 
 204                  _T("control must have toolbar as parent") ); 
 206     wxCHECK_MSG( pos 
<= GetToolsCount(), (wxToolBarToolBase 
*)NULL
, 
 207                  _T("invalid position in wxToolBar::InsertControl()") ); 
 209     wxToolBarToolBase 
*tool 
= CreateTool(control
); 
 211     if ( !InsertTool(pos
, tool
) ) 
 221 wxControl 
*wxToolBarBase::FindControl( int id 
) 
 223     for ( wxToolBarToolsList::compatibility_iterator node 
= m_tools
.GetFirst(); 
 225           node 
= node
->GetNext() ) 
 227         const wxToolBarToolBase 
* const tool 
= node
->GetData(); 
 228         if ( tool
->IsControl() ) 
 230             wxControl 
* const control 
= tool
->GetControl(); 
 234                 wxFAIL_MSG( _T("NULL control in toolbar?") ); 
 236             else if ( control
->GetId() == id 
) 
 247 wxToolBarToolBase 
*wxToolBarBase::AddSeparator() 
 249     return InsertSeparator(GetToolsCount()); 
 252 wxToolBarToolBase 
*wxToolBarBase::InsertSeparator(size_t pos
) 
 254     wxCHECK_MSG( pos 
<= GetToolsCount(), (wxToolBarToolBase 
*)NULL
, 
 255                  _T("invalid position in wxToolBar::InsertSeparator()") ); 
 257     wxToolBarToolBase 
*tool 
= CreateTool(wxID_SEPARATOR
, 
 259                                          wxNullBitmap
, wxNullBitmap
, 
 260                                          wxITEM_SEPARATOR
, (wxObject 
*)NULL
, 
 261                                          wxEmptyString
, wxEmptyString
); 
 263     if ( !tool 
|| !DoInsertTool(pos
, tool
) ) 
 270     m_tools
.Insert(pos
, tool
); 
 275 wxToolBarToolBase 
*wxToolBarBase::RemoveTool(int id
) 
 278     wxToolBarToolsList::compatibility_iterator node
; 
 279     for ( node 
= m_tools
.GetFirst(); node
; node 
= node
->GetNext() ) 
 281         if ( node
->GetData()->GetId() == id 
) 
 289         // don't give any error messages - sometimes we might call RemoveTool() 
 290         // without knowing whether the tool is or not in the toolbar 
 291         return (wxToolBarToolBase 
*)NULL
; 
 294     wxToolBarToolBase 
*tool 
= node
->GetData(); 
 295     if ( !DoDeleteTool(pos
, tool
) ) 
 297         return (wxToolBarToolBase 
*)NULL
; 
 305 bool wxToolBarBase::DeleteToolByPos(size_t pos
) 
 307     wxCHECK_MSG( pos 
< GetToolsCount(), false, 
 308                  _T("invalid position in wxToolBar::DeleteToolByPos()") ); 
 310     wxToolBarToolsList::compatibility_iterator node 
= m_tools
.Item(pos
); 
 312     if ( !DoDeleteTool(pos
, node
->GetData()) ) 
 317     delete node
->GetData(); 
 323 bool wxToolBarBase::DeleteTool(int id
) 
 326     wxToolBarToolsList::compatibility_iterator node
; 
 327     for ( node 
= m_tools
.GetFirst(); node
; node 
= node
->GetNext() ) 
 329         if ( node
->GetData()->GetId() == id 
) 
 335     if ( !node 
|| !DoDeleteTool(pos
, node
->GetData()) ) 
 340     delete node
->GetData(); 
 346 wxToolBarToolBase 
*wxToolBarBase::FindById(int id
) const 
 348     wxToolBarToolBase 
*tool 
= (wxToolBarToolBase 
*)NULL
; 
 350     for ( wxToolBarToolsList::compatibility_iterator node 
= m_tools
.GetFirst(); 
 352           node 
= node
->GetNext() ) 
 354         tool 
= node
->GetData(); 
 355         if ( tool
->GetId() == id 
) 
 367 void wxToolBarBase::UnToggleRadioGroup(wxToolBarToolBase 
*tool
) 
 369     wxCHECK_RET( tool
, _T("NULL tool in wxToolBarTool::UnToggleRadioGroup") ); 
 371     if ( !tool
->IsButton() || tool
->GetKind() != wxITEM_RADIO 
) 
 374     wxToolBarToolsList::compatibility_iterator node 
= m_tools
.Find(tool
); 
 375     wxCHECK_RET( node
, _T("invalid tool in wxToolBarTool::UnToggleRadioGroup") ); 
 377     wxToolBarToolsList::compatibility_iterator nodeNext 
= node
->GetNext(); 
 380         wxToolBarToolBase 
*toolNext 
= nodeNext
->GetData(); 
 382         if ( !toolNext
->IsButton() || toolNext
->GetKind() != wxITEM_RADIO 
) 
 385         if ( toolNext
->Toggle(false) ) 
 387             DoToggleTool(toolNext
, false); 
 390         nodeNext 
= nodeNext
->GetNext(); 
 393     wxToolBarToolsList::compatibility_iterator nodePrev 
= node
->GetPrevious(); 
 396         wxToolBarToolBase 
*toolNext 
= nodePrev
->GetData(); 
 398         if ( !toolNext
->IsButton() || toolNext
->GetKind() != wxITEM_RADIO 
) 
 401         if ( toolNext
->Toggle(false) ) 
 403             DoToggleTool(toolNext
, false); 
 406         nodePrev 
= nodePrev
->GetPrevious(); 
 410 void wxToolBarBase::ClearTools() 
 412     while ( GetToolsCount() ) 
 418 bool wxToolBarBase::Realize() 
 423 wxToolBarBase::~wxToolBarBase() 
 425     WX_CLEAR_LIST(wxToolBarToolsList
, m_tools
); 
 427     // notify the frame that it doesn't have a tool bar any longer to avoid 
 429     wxFrame 
*frame 
= wxDynamicCast(GetParent(), wxFrame
); 
 430     if ( frame 
&& frame
->GetToolBar() == this ) 
 432         frame
->SetToolBar(NULL
); 
 436 // ---------------------------------------------------------------------------- 
 437 // wxToolBarBase tools state 
 438 // ---------------------------------------------------------------------------- 
 440 void wxToolBarBase::EnableTool(int id
, bool enable
) 
 442     wxToolBarToolBase 
*tool 
= FindById(id
); 
 445         if ( tool
->Enable(enable
) ) 
 447             DoEnableTool(tool
, enable
); 
 452 void wxToolBarBase::ToggleTool(int id
, bool toggle
) 
 454     wxToolBarToolBase 
*tool 
= FindById(id
); 
 455     if ( tool 
&& tool
->CanBeToggled() ) 
 457         if ( tool
->Toggle(toggle
) ) 
 459             UnToggleRadioGroup(tool
); 
 460             DoToggleTool(tool
, toggle
); 
 465 void wxToolBarBase::SetToggle(int id
, bool toggle
) 
 467     wxToolBarToolBase 
*tool 
= FindById(id
); 
 470         if ( tool
->SetToggle(toggle
) ) 
 472             DoSetToggle(tool
, toggle
); 
 477 void wxToolBarBase::SetToolShortHelp(int id
, const wxString
& help
) 
 479     wxToolBarToolBase 
*tool 
= FindById(id
); 
 482         (void)tool
->SetShortHelp(help
); 
 486 void wxToolBarBase::SetToolLongHelp(int id
, const wxString
& help
) 
 488     wxToolBarToolBase 
*tool 
= FindById(id
); 
 491         (void)tool
->SetLongHelp(help
); 
 495 wxObject 
*wxToolBarBase::GetToolClientData(int id
) const 
 497     wxToolBarToolBase 
*tool 
= FindById(id
); 
 499     return tool 
? tool
->GetClientData() : (wxObject 
*)NULL
; 
 502 void wxToolBarBase::SetToolClientData(int id
, wxObject 
*clientData
) 
 504     wxToolBarToolBase 
*tool 
= FindById(id
); 
 506     wxCHECK_RET( tool
, _T("no such tool in wxToolBar::SetToolClientData") ); 
 508     tool
->SetClientData(clientData
); 
 511 int wxToolBarBase::GetToolPos(int id
) const 
 514     wxToolBarToolsList::compatibility_iterator node
; 
 516     for ( node 
= m_tools
.GetFirst(); node
; node 
= node
->GetNext() ) 
 518         if ( node
->GetData()->GetId() == id 
) 
 527 bool wxToolBarBase::GetToolState(int id
) const 
 529     wxToolBarToolBase 
*tool 
= FindById(id
); 
 530     wxCHECK_MSG( tool
, false, _T("no such tool") ); 
 532     return tool
->IsToggled(); 
 535 bool wxToolBarBase::GetToolEnabled(int id
) const 
 537     wxToolBarToolBase 
*tool 
= FindById(id
); 
 538     wxCHECK_MSG( tool
, false, _T("no such tool") ); 
 540     return tool
->IsEnabled(); 
 543 wxString 
wxToolBarBase::GetToolShortHelp(int id
) const 
 545     wxToolBarToolBase 
*tool 
= FindById(id
); 
 546     wxCHECK_MSG( tool
, wxEmptyString
, _T("no such tool") ); 
 548     return tool
->GetShortHelp(); 
 551 wxString 
wxToolBarBase::GetToolLongHelp(int id
) const 
 553     wxToolBarToolBase 
*tool 
= FindById(id
); 
 554     wxCHECK_MSG( tool
, wxEmptyString
, _T("no such tool") ); 
 556     return tool
->GetLongHelp(); 
 559 // ---------------------------------------------------------------------------- 
 560 // wxToolBarBase geometry 
 561 // ---------------------------------------------------------------------------- 
 563 void wxToolBarBase::SetMargins(int x
, int y
) 
 569 void wxToolBarBase::SetRows(int WXUNUSED(nRows
)) 
 574 // ---------------------------------------------------------------------------- 
 576 // ---------------------------------------------------------------------------- 
 578 // Only allow toggle if returns true 
 579 bool wxToolBarBase::OnLeftClick(int id
, bool toggleDown
) 
 581     wxCommandEvent 
event(wxEVT_COMMAND_TOOL_CLICKED
, id
); 
 582     event
.SetEventObject(this); 
 584     // we use SetInt() to make wxCommandEvent::IsChecked() return toggleDown 
 585     event
.SetInt((int)toggleDown
); 
 587     // and SetExtraLong() for backwards compatibility 
 588     event
.SetExtraLong((long)toggleDown
); 
 590     // Send events to this toolbar instead (and thence up the window hierarchy) 
 591     GetEventHandler()->ProcessEvent(event
); 
 596 // Call when right button down. 
 597 void wxToolBarBase::OnRightClick(int id
, 
 601     wxCommandEvent 
event(wxEVT_COMMAND_TOOL_RCLICKED
, id
); 
 602     event
.SetEventObject(this); 
 605     GetEventHandler()->ProcessEvent(event
); 
 608 // Called when the mouse cursor enters a tool bitmap (no button pressed). 
 609 // Argument is wxID_ANY if mouse is exiting the toolbar. 
 610 // Note that for this event, the id of the window is used, 
 611 // and the integer parameter of wxCommandEvent is used to retrieve 
 613 void wxToolBarBase::OnMouseEnter(int id
) 
 615     wxCommandEvent 
event(wxEVT_COMMAND_TOOL_ENTER
, GetId()); 
 616     event
.SetEventObject(this); 
 619     wxFrame 
*frame 
= wxDynamicCast(GetParent(), wxFrame
); 
 623         wxToolBarToolBase
* tool 
= id 
== wxID_ANY 
? (wxToolBarToolBase
*)NULL 
: FindById(id
); 
 625             help 
= tool
->GetLongHelp(); 
 626         frame
->DoGiveHelp( help
, id 
!= wxID_ANY 
); 
 629     (void)GetEventHandler()->ProcessEvent(event
); 
 632 // ---------------------------------------------------------------------------- 
 634 // ---------------------------------------------------------------------------- 
 636 // Do the toolbar button updates (check for EVT_UPDATE_UI handlers) 
 637 void wxToolBarBase::UpdateWindowUI(long flags
) 
 639     wxWindowBase::UpdateWindowUI(flags
); 
 641     // There is no sense in updating the toolbar UI 
 642     // if the parent window is about to get destroyed 
 643     wxWindow 
*tlw 
= wxGetTopLevelParent( this ); 
 644     if (tlw 
&& wxPendingDelete
.Member( tlw 
)) 
 647     wxEvtHandler
* evtHandler 
= GetEventHandler() ; 
 649     for ( wxToolBarToolsList::compatibility_iterator node 
= m_tools
.GetFirst(); 
 651           node 
= node
->GetNext() ) 
 653         int id 
= node
->GetData()->GetId(); 
 655         wxUpdateUIEvent 
event(id
); 
 656         event
.SetEventObject(this); 
 658         if ( evtHandler
->ProcessEvent(event
) ) 
 660             if ( event
.GetSetEnabled() ) 
 661                 EnableTool(id
, event
.GetEnabled()); 
 662             if ( event
.GetSetChecked() ) 
 663                 ToggleTool(id
, event
.GetChecked()); 
 665             if ( event
.GetSetText() ) 
 675  * Make a greyed-out image suitable for disabled buttons. 
 676  * This code is adapted from wxNewBitmapButton in FL. 
 679 bool wxCreateGreyedImage(const wxImage
& src
, wxImage
& dst
) 
 683     unsigned char rBg
, gBg
, bBg
; 
 686         src
.GetOrFindMaskColour(&rBg
, &gBg
, &bBg
); 
 687         dst
.SetMaskColour(rBg
, gBg
, bBg
); 
 689     else // assuming the pixels along the edges are of the background color 
 691         rBg 
= src
.GetRed(0, 0); 
 692         gBg 
= src
.GetGreen(0, 0); 
 693         bBg 
= src
.GetBlue(0, 0); 
 696     const wxColour 
colBg(rBg
, gBg
, bBg
); 
 698     const wxColour colDark 
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
); 
 699     const wxColour colLight 
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT
); 
 701     // Second attempt, just making things monochrome 
 702     const int width 
= src
.GetWidth(); 
 703     const int height 
= src
.GetHeight(); 
 705     for ( int x 
= 0; x 
< width
; x
++ ) 
 707         for ( int y 
= 0; y 
< height
; y
++ ) 
 709             const int r 
= src
.GetRed(x
, y
); 
 710             const int g 
= src
.GetGreen(x
, y
); 
 711             const int b 
= src
.GetBlue(x
, y
); 
 713             if ( r 
== rBg 
&& g 
== gBg 
&& b 
== bBg 
) 
 715                 // Leave the background colour as-is 
 719             // Change light things to the background colour 
 721             if ( r 
>= (colLight
.Red() - 50) && 
 722                     g 
>= (colLight
.Green() - 50) && 
 723                         b 
>= (colLight
.Blue() - 50) ) 
 727             else // Change dark things to really dark 
 732             dst
.SetRGB(x
, y
, col
.Red(), col
.Green(), col
.Blue()); 
 739 #endif // wxUSE_IMAGE 
 741 #endif // wxUSE_TOOLBAR