home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / common / tbarbase.cpp < prev    next >
C/C++ Source or Header  |  2002-06-02  |  18KB  |  653 lines

  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)
  6. // Created:     04/01/98
  7. // RCS-ID:      $Id: tbarbase.cpp,v 1.46 2002/06/02 10:57:13 RR Exp $
  8. // Copyright:   (c) Julian Smart and Markus Holzem
  9. // Licence:     wxWindows license
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. // ============================================================================
  13. // declarations
  14. // ============================================================================
  15.  
  16. // ----------------------------------------------------------------------------
  17. // headers
  18. // ----------------------------------------------------------------------------
  19.  
  20. #ifdef __GNUG__
  21.     #pragma implementation "tbarbase.h"
  22. #endif
  23.  
  24. // For compilers that support precompilation, includes "wx.h".
  25. #include "wx/wxprec.h"
  26.  
  27. #ifdef __BORLANDC__
  28.     #pragma hdrstop
  29. #endif
  30.  
  31. #if wxUSE_TOOLBAR
  32.  
  33. #ifndef WX_PRECOMP
  34.     #include "wx/control.h"
  35. #endif
  36.  
  37. #include "wx/frame.h"
  38. #include "wx/image.h"
  39. #include "wx/settings.h"
  40.  
  41. #include "wx/tbarbase.h"
  42.  
  43. // ----------------------------------------------------------------------------
  44. // wxWindows macros
  45. // ----------------------------------------------------------------------------
  46.  
  47. IMPLEMENT_CLASS(wxToolBarBase, wxControl)
  48.  
  49. BEGIN_EVENT_TABLE(wxToolBarBase, wxControl)
  50.     EVT_IDLE(wxToolBarBase::OnIdle)
  51. END_EVENT_TABLE()
  52.  
  53. #include "wx/listimpl.cpp"
  54.  
  55. WX_DEFINE_LIST(wxToolBarToolsList);
  56.  
  57. // ============================================================================
  58. // implementation
  59. // ============================================================================
  60.  
  61. // ----------------------------------------------------------------------------
  62. // wxToolBarToolBase
  63. // ----------------------------------------------------------------------------
  64.  
  65. bool wxToolBarToolBase::Enable(bool enable)
  66. {
  67.     if ( m_enabled == enable )
  68.         return FALSE;
  69.  
  70.     m_enabled = enable;
  71.  
  72.     return TRUE;
  73. }
  74.  
  75. bool wxToolBarToolBase::Toggle(bool toggle)
  76. {
  77.     wxASSERT_MSG( CanBeToggled(), _T("can't toggle this tool") );
  78.  
  79.     if ( m_toggled == toggle )
  80.         return FALSE;
  81.  
  82.     m_toggled = toggle;
  83.  
  84.     return TRUE;
  85. }
  86.  
  87. bool wxToolBarToolBase::SetToggle(bool toggle)
  88. {
  89.     wxItemKind kind = toggle ? wxITEM_CHECK : wxITEM_NORMAL;
  90.     if ( m_kind == kind )
  91.         return FALSE;
  92.  
  93.     m_kind = kind;
  94.  
  95.     return TRUE;
  96. }
  97.  
  98. bool wxToolBarToolBase::SetShortHelp(const wxString& help)
  99. {
  100.     if ( m_shortHelpString == help )
  101.         return FALSE;
  102.  
  103.     m_shortHelpString = help;
  104.  
  105.     return TRUE;
  106. }
  107.  
  108. bool wxToolBarToolBase::SetLongHelp(const wxString& help)
  109. {
  110.     if ( m_longHelpString == help )
  111.         return FALSE;
  112.  
  113.     m_longHelpString = help;
  114.  
  115.     return TRUE;
  116. }
  117.  
  118. wxToolBarToolBase::~wxToolBarToolBase()
  119. {
  120. }
  121.  
  122. // ----------------------------------------------------------------------------
  123. // wxToolBarBase adding/deleting items
  124. // ----------------------------------------------------------------------------
  125.  
  126. wxToolBarBase::wxToolBarBase()
  127. {
  128.     // the list owns the pointers
  129.     m_tools.DeleteContents(TRUE);
  130.  
  131.     m_xMargin = m_yMargin = 0;
  132.  
  133.     m_maxRows = m_maxCols = 0;
  134. }
  135.  
  136. wxToolBarToolBase *wxToolBarBase::DoAddTool(int id,
  137.                                             const wxString& label,
  138.                                             const wxBitmap& bitmap,
  139.                                             const wxBitmap& bmpDisabled,
  140.                                             wxItemKind kind,
  141.                                             const wxString& shortHelp,
  142.                                             const wxString& longHelp,
  143.                                             wxObject *clientData,
  144.                                             wxCoord WXUNUSED(xPos),
  145.                                             wxCoord WXUNUSED(yPos))
  146. {
  147.     return InsertTool(GetToolsCount(), id, label, bitmap, bmpDisabled,
  148.                       kind, shortHelp, longHelp, clientData);
  149. }
  150.  
  151. wxToolBarToolBase *wxToolBarBase::InsertTool(size_t pos,
  152.                                              int id,
  153.                                              const wxString& label,
  154.                                              const wxBitmap& bitmap,
  155.                                              const wxBitmap& bmpDisabled,
  156.                                              wxItemKind kind,
  157.                                              const wxString& shortHelp,
  158.                                              const wxString& longHelp,
  159.                                              wxObject *clientData)
  160. {
  161.     wxCHECK_MSG( pos <= GetToolsCount(), (wxToolBarToolBase *)NULL,
  162.                  _T("invalid position in wxToolBar::InsertTool()") );
  163.  
  164.     wxToolBarToolBase *tool = CreateTool(id, label, bitmap, bmpDisabled, kind,
  165.                                          clientData, shortHelp, longHelp);
  166.  
  167.     if ( !tool || !DoInsertTool(pos, tool) )
  168.     {
  169.         delete tool;
  170.  
  171.         return NULL;
  172.     }
  173.  
  174.     m_tools.Insert(pos, tool);
  175.  
  176.     return tool;
  177. }
  178.  
  179. wxToolBarToolBase *wxToolBarBase::AddControl(wxControl *control)
  180. {
  181.     return InsertControl(GetToolsCount(), control);
  182. }
  183.  
  184. wxToolBarToolBase *wxToolBarBase::InsertControl(size_t pos, wxControl *control)
  185. {
  186.     wxCHECK_MSG( control, (wxToolBarToolBase *)NULL,
  187.                  _T("toolbar: can't insert NULL control") );
  188.  
  189.     wxCHECK_MSG( control->GetParent() == this, (wxToolBarToolBase *)NULL,
  190.                  _T("control must have toolbar as parent") );
  191.  
  192.     wxCHECK_MSG( pos <= GetToolsCount(), (wxToolBarToolBase *)NULL,
  193.                  _T("invalid position in wxToolBar::InsertControl()") );
  194.  
  195.     wxToolBarToolBase *tool = CreateTool(control);
  196.  
  197.     if ( !tool || !DoInsertTool(pos, tool) )
  198.     {
  199.         delete tool;
  200.  
  201.         return NULL;
  202.     }
  203.  
  204.     m_tools.Insert(pos, tool);
  205.  
  206.     return tool;
  207. }
  208.  
  209. wxControl *wxToolBarBase::FindControl( int id )
  210. {
  211.     for ( wxToolBarToolsList::Node* node = m_tools.GetFirst();
  212.           node;
  213.           node = node->GetNext() )
  214.     {
  215.         wxControl *control = node->GetData()->GetControl();
  216.         
  217.         if (control)
  218.         {
  219.             if (control->GetId() == id)
  220.                 return control;
  221.         }
  222.     }
  223.  
  224.    return NULL;
  225. }
  226.  
  227. wxToolBarToolBase *wxToolBarBase::AddSeparator()
  228. {
  229.     return InsertSeparator(GetToolsCount());
  230. }
  231.  
  232. wxToolBarToolBase *wxToolBarBase::InsertSeparator(size_t pos)
  233. {
  234.     wxCHECK_MSG( pos <= GetToolsCount(), (wxToolBarToolBase *)NULL,
  235.                  _T("invalid position in wxToolBar::InsertSeparator()") );
  236.  
  237.     wxToolBarToolBase *tool = CreateTool(wxID_SEPARATOR,
  238.                                          wxEmptyString,
  239.                                          wxNullBitmap, wxNullBitmap,
  240.                                          wxITEM_SEPARATOR, (wxObject *)NULL,
  241.                                          wxEmptyString, wxEmptyString);
  242.  
  243.     if ( !tool || !DoInsertTool(pos, tool) )
  244.     {
  245.         delete tool;
  246.  
  247.         return NULL;
  248.     }
  249.  
  250.     m_tools.Insert(pos, tool);
  251.  
  252.     return tool;
  253. }
  254.  
  255. wxToolBarToolBase *wxToolBarBase::RemoveTool(int id)
  256. {
  257.     size_t pos = 0;
  258.     wxToolBarToolsList::Node *node;
  259.     for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
  260.     {
  261.         if ( node->GetData()->GetId() == id )
  262.             break;
  263.  
  264.         pos++;
  265.     }
  266.  
  267.     if ( !node )
  268.     {
  269.         // don't give any error messages - sometimes we might call RemoveTool()
  270.         // without knowing whether the tool is or not in the toolbar
  271.         return (wxToolBarToolBase *)NULL;
  272.     }
  273.  
  274.     wxToolBarToolBase *tool = node->GetData();
  275.     if ( !DoDeleteTool(pos, tool) )
  276.     {
  277.         return (wxToolBarToolBase *)NULL;
  278.     }
  279.  
  280.     // the node would delete the data, so set it to NULL to avoid this
  281.     node->SetData(NULL);
  282.  
  283.     m_tools.DeleteNode(node);
  284.  
  285.     return tool;
  286. }
  287.  
  288. bool wxToolBarBase::DeleteToolByPos(size_t pos)
  289. {
  290.     wxCHECK_MSG( pos < GetToolsCount(), FALSE,
  291.                  _T("invalid position in wxToolBar::DeleteToolByPos()") );
  292.  
  293.     wxToolBarToolsList::Node *node = m_tools.Item(pos);
  294.  
  295.     if ( !DoDeleteTool(pos, node->GetData()) )
  296.     {
  297.         return FALSE;
  298.     }
  299.  
  300.     m_tools.DeleteNode(node);
  301.  
  302.     return TRUE;
  303. }
  304.  
  305. bool wxToolBarBase::DeleteTool(int id)
  306. {
  307.     size_t pos = 0;
  308.     wxToolBarToolsList::Node *node;
  309.     for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
  310.     {
  311.         if ( node->GetData()->GetId() == id )
  312.             break;
  313.  
  314.         pos++;
  315.     }
  316.  
  317.     if ( !node || !DoDeleteTool(pos, node->GetData()) )
  318.     {
  319.         return FALSE;
  320.     }
  321.  
  322.     m_tools.DeleteNode(node);
  323.  
  324.     return TRUE;
  325. }
  326.  
  327. wxToolBarToolBase *wxToolBarBase::FindById(int id) const
  328. {
  329.     wxToolBarToolBase *tool = (wxToolBarToolBase *)NULL;
  330.  
  331.     for ( wxToolBarToolsList::Node *node = m_tools.GetFirst();
  332.           node;
  333.           node = node->GetNext() )
  334.     {
  335.         tool = node->GetData();
  336.         if ( tool->GetId() == id )
  337.         {
  338.             // found
  339.             break;
  340.         }
  341.  
  342.         tool = NULL;
  343.     }
  344.  
  345.     return tool;
  346. }
  347.  
  348. void wxToolBarBase::ClearTools()
  349. {
  350.     m_tools.Clear();
  351. }
  352.  
  353. bool wxToolBarBase::Realize()
  354. {
  355.     return TRUE;
  356. }
  357.  
  358. wxToolBarBase::~wxToolBarBase()
  359. {
  360. }
  361.  
  362. // ----------------------------------------------------------------------------
  363. // wxToolBarBase tools state
  364. // ----------------------------------------------------------------------------
  365.  
  366. void wxToolBarBase::EnableTool(int id, bool enable)
  367. {
  368.     wxToolBarToolBase *tool = FindById(id);
  369.     if ( tool )
  370.     {
  371.         if ( tool->Enable(enable) )
  372.         {
  373.             DoEnableTool(tool, enable);
  374.         }
  375.     }
  376. }
  377.  
  378. void wxToolBarBase::ToggleTool(int id, bool toggle)
  379. {
  380.     wxToolBarToolBase *tool = FindById(id);
  381.     if ( tool && tool->CanBeToggled() )
  382.     {
  383.         if ( tool->Toggle(toggle) )
  384.         {
  385.             DoToggleTool(tool, toggle);
  386.         }
  387.     }
  388. }
  389.  
  390. void wxToolBarBase::SetToggle(int id, bool toggle)
  391. {
  392.     wxToolBarToolBase *tool = FindById(id);
  393.     if ( tool )
  394.     {
  395.         if ( tool->SetToggle(toggle) )
  396.         {
  397.             DoSetToggle(tool, toggle);
  398.         }
  399.     }
  400. }
  401.  
  402. void wxToolBarBase::SetToolShortHelp(int id, const wxString& help)
  403. {
  404.     wxToolBarToolBase *tool = FindById(id);
  405.     if ( tool )
  406.     {
  407.         (void)tool->SetShortHelp(help);
  408.     }
  409. }
  410.  
  411. void wxToolBarBase::SetToolLongHelp(int id, const wxString& help)
  412. {
  413.     wxToolBarToolBase *tool = FindById(id);
  414.     if ( tool )
  415.     {
  416.         (void)tool->SetLongHelp(help);
  417.     }
  418. }
  419.  
  420. wxObject *wxToolBarBase::GetToolClientData(int id) const
  421. {
  422.     wxToolBarToolBase *tool = FindById(id);
  423.  
  424.     return tool ? tool->GetClientData() : (wxObject *)NULL;
  425. }
  426.  
  427. void wxToolBarBase::SetToolClientData(int id, wxObject *clientData)
  428. {
  429.     wxToolBarToolBase *tool = FindById(id);
  430.  
  431.     wxCHECK_RET( tool, _T("no such tool in wxToolBar::SetToolClientData") );
  432.  
  433.     tool->SetClientData(clientData);
  434. }
  435.  
  436. bool wxToolBarBase::GetToolState(int id) const
  437. {
  438.     wxToolBarToolBase *tool = FindById(id);
  439.     wxCHECK_MSG( tool, FALSE, _T("no such tool") );
  440.  
  441.     return tool->IsToggled();
  442. }
  443.  
  444. bool wxToolBarBase::GetToolEnabled(int id) const
  445. {
  446.     wxToolBarToolBase *tool = FindById(id);
  447.     wxCHECK_MSG( tool, FALSE, _T("no such tool") );
  448.  
  449.     return tool->IsEnabled();
  450. }
  451.  
  452. wxString wxToolBarBase::GetToolShortHelp(int id) const
  453. {
  454.     wxToolBarToolBase *tool = FindById(id);
  455.     wxCHECK_MSG( tool, _T(""), _T("no such tool") );
  456.  
  457.     return tool->GetShortHelp();
  458. }
  459.  
  460. wxString wxToolBarBase::GetToolLongHelp(int id) const
  461. {
  462.     wxToolBarToolBase *tool = FindById(id);
  463.     wxCHECK_MSG( tool, _T(""), _T("no such tool") );
  464.  
  465.     return tool->GetLongHelp();
  466. }
  467.  
  468. // ----------------------------------------------------------------------------
  469. // wxToolBarBase geometry
  470. // ----------------------------------------------------------------------------
  471.  
  472. void wxToolBarBase::SetMargins(int x, int y)
  473. {
  474.     m_xMargin = x;
  475.     m_yMargin = y;
  476. }
  477.  
  478. void wxToolBarBase::SetRows(int WXUNUSED(nRows))
  479. {
  480.     // nothing
  481. }
  482.  
  483. // ----------------------------------------------------------------------------
  484. // event processing
  485. // ----------------------------------------------------------------------------
  486.  
  487. // Only allow toggle if returns TRUE
  488. bool wxToolBarBase::OnLeftClick(int id, bool toggleDown)
  489. {
  490.     wxCommandEvent event(wxEVT_COMMAND_TOOL_CLICKED, id);
  491.     event.SetEventObject(this);
  492.  
  493.     // we use SetInt() to make wxCommandEvent::IsChecked() return toggleDown
  494.     event.SetInt((int)toggleDown);
  495.  
  496.     // and SetExtraLong() for backwards compatibility
  497.     event.SetExtraLong((long)toggleDown);
  498.  
  499.     // Send events to this toolbar instead (and thence up the window hierarchy)
  500.     GetEventHandler()->ProcessEvent(event);
  501.  
  502.     return TRUE;
  503. }
  504.  
  505. // Call when right button down.
  506. void wxToolBarBase::OnRightClick(int id,
  507.                                  long WXUNUSED(x),
  508.                                  long WXUNUSED(y))
  509. {
  510.     wxCommandEvent event(wxEVT_COMMAND_TOOL_RCLICKED, id);
  511.     event.SetEventObject(this);
  512.     event.SetInt(id);
  513.  
  514.     GetEventHandler()->ProcessEvent(event);
  515. }
  516.  
  517. // Called when the mouse cursor enters a tool bitmap (no button pressed).
  518. // Argument is -1 if mouse is exiting the toolbar.
  519. // Note that for this event, the id of the window is used,
  520. // and the integer parameter of wxCommandEvent is used to retrieve
  521. // the tool id.
  522. void wxToolBarBase::OnMouseEnter(int id)
  523. {
  524.     wxCommandEvent event(wxEVT_COMMAND_TOOL_ENTER, GetId());
  525.     event.SetEventObject(this);
  526.     event.SetInt(id);
  527.  
  528.     wxFrame *frame = wxDynamicCast(GetParent(), wxFrame);
  529.     if( frame )
  530.     {
  531.         wxToolBarToolBase* tool = id == -1 ? (wxToolBarToolBase*)0 : FindById(id);
  532.         wxString help = tool ? tool->GetLongHelp() : wxString();
  533.         frame->DoGiveHelp( help, id != -1 );
  534.     }
  535.  
  536.     (void)GetEventHandler()->ProcessEvent(event);
  537. }
  538.  
  539. // ----------------------------------------------------------------------------
  540. // UI updates
  541. // ----------------------------------------------------------------------------
  542.  
  543. void wxToolBarBase::OnIdle(wxIdleEvent& event)
  544. {
  545.     DoToolbarUpdates();
  546.  
  547.     event.Skip();
  548. }
  549.  
  550. // Do the toolbar button updates (check for EVT_UPDATE_UI handlers)
  551. void wxToolBarBase::DoToolbarUpdates()
  552. {
  553.     wxWindow* parent = this;
  554.     while (parent->GetParent())
  555.         parent = parent->GetParent();
  556.  
  557. // This kind of #ifdef is a good way to annoy people. It breaks
  558. // apps, but only on one platform and due to a hack in officially
  559. // platform independent code. It took me hours to fix this. RR.
  560. //
  561. // #ifdef __WXMSW__
  562. //    wxWindow* focusWin = wxFindFocusDescendant(parent);
  563. // #else
  564.     wxWindow* focusWin = (wxWindow*) NULL;
  565. // #endif
  566.  
  567.     wxEvtHandler* evtHandler = focusWin ? focusWin->GetEventHandler() : GetEventHandler() ;
  568.  
  569.     for ( wxToolBarToolsList::Node* node = m_tools.GetFirst();
  570.           node;
  571.           node = node->GetNext() )
  572.     {
  573.         int id = node->GetData()->GetId();
  574.  
  575.         wxUpdateUIEvent event(id);
  576.         event.SetEventObject(this);
  577.  
  578.         if ( evtHandler->ProcessEvent(event) )
  579.         {
  580.             if ( event.GetSetEnabled() )
  581.                 EnableTool(id, event.GetEnabled());
  582.             if ( event.GetSetChecked() )
  583.                 ToggleTool(id, event.GetChecked());
  584. #if 0
  585.             if ( event.GetSetText() )
  586.                 // Set tooltip?
  587. #endif // 0
  588.         }
  589.     }
  590. }
  591.  
  592. // Helper function, used by wxCreateGreyedImage
  593.  
  594. static void wxGreyOutImage( const wxImage& src,
  595.                             wxImage& dest,
  596.                             const wxColour& darkCol,
  597.                             const wxColour& lightCol,
  598.                             const wxColour& bgCol )
  599. {
  600.     // Second attempt, just making things monochrome
  601.     int width = src.GetWidth();
  602.     int height = src.GetHeight();
  603.  
  604.     int redCur, greenCur, blueCur;
  605.     for ( int x = 0; x < width; x++ )
  606.     {
  607.         for ( int y = 1; y < height; y++ )
  608.         {
  609.             redCur = src.GetRed(x, y);
  610.             greenCur = src.GetGreen(x, y);
  611.             blueCur = src.GetBlue(x, y);
  612.  
  613.             // Change light things to the background colour
  614.             if ( redCur >= (lightCol.Red() - 50) && greenCur >= (lightCol.Green() - 50) && blueCur >= (lightCol.Blue() - 50) )
  615.             {
  616.                 dest.SetRGB(x,y, bgCol.Red(), bgCol.Green(), bgCol.Blue());
  617.             }
  618.             else if ( redCur == bgCol.Red() && greenCur == bgCol.Green() && blueCur == bgCol.Blue() )
  619.             {
  620.                 // Leave the background colour as-is
  621.                 // dest.SetRGB(x,y, bgCol.Red(), bgCol.Green(), bgCol.Blue());
  622.             }
  623.             else // if ( redCur <= darkCol.Red() && greenCur <= darkCol.Green() && blueCur <= darkCol.Blue() )
  624.             {
  625.                 // Change dark things to really dark
  626.                 dest.SetRGB(x,y, darkCol.Red(), darkCol.Green(), darkCol.Blue());
  627.             }
  628.         }
  629.     }
  630. }
  631.  
  632. /*
  633.  * Make a greyed-out image suitable for disabled buttons.
  634.  * This code is adapted from wxNewBitmapButton in FL.
  635.  */
  636.  
  637. bool wxCreateGreyedImage(const wxImage& in, wxImage& out)
  638. {
  639.     out = in.Copy();
  640.  
  641.     // assuming the pixels along the edges are of the background color
  642.     wxColour bgCol(in.GetRed(0, 0), in.GetGreen(0, 0), in.GetBlue(0, 0));
  643.  
  644.     wxColour darkCol = wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW) ;
  645.     wxColour lightCol = wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT) ;
  646.  
  647.     wxGreyOutImage(in, out, darkCol, lightCol, bgCol);
  648.  
  649.     return TRUE;
  650. }
  651.  
  652. #endif // wxUSE_TOOLBAR
  653.