home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / generic / tipwin.cpp < prev    next >
C/C++ Source or Header  |  2002-01-22  |  10KB  |  372 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name:        src/generic/tipwin.cpp
  3. // Purpose:     implementation of wxTipWindow
  4. // Author:      Vadim Zeitlin
  5. // Modified by:
  6. // Created:     10.09.00
  7. // RCS-ID:      $Id: tipwin.cpp,v 1.19 2002/01/22 15:39:40 VZ Exp $
  8. // Copyright:   (c) 2000 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
  9. // Licence:     wxWindows license
  10. ///////////////////////////////////////////////////////////////////////////////
  11.  
  12. // ============================================================================
  13. // declarations
  14. // ============================================================================
  15.  
  16. // ----------------------------------------------------------------------------
  17. // headers
  18. // ----------------------------------------------------------------------------
  19.  
  20. #ifdef __GNUG__
  21.     #pragma implementation "tipwin.h"
  22. #endif
  23.  
  24. // For compilers that support precompilatixon, includes "wx/wx.h".
  25. #include "wx/wxprec.h"
  26.  
  27. #ifdef __BORLANDC__
  28.     #pragma hdrstop
  29. #endif
  30.  
  31. #ifndef WX_PRECOMP
  32.     #include "wx/dcclient.h"
  33. #endif // WX_PRECOMP
  34.  
  35. #include "wx/tipwin.h"
  36.  
  37. #if wxUSE_TIPWINDOW
  38.  
  39. #include "wx/timer.h"
  40. #include "wx/settings.h"
  41.  
  42. // ----------------------------------------------------------------------------
  43. // constants
  44. // ----------------------------------------------------------------------------
  45.  
  46. static const wxCoord TEXT_MARGIN_X = 3;
  47. static const wxCoord TEXT_MARGIN_Y = 3;
  48.  
  49. // ----------------------------------------------------------------------------
  50. // wxTipWindowView
  51. // ----------------------------------------------------------------------------
  52.  
  53. // Viewer window to put in the frame
  54. class WXDLLEXPORT wxTipWindowView : public wxWindow
  55. {
  56. public:
  57.     wxTipWindowView(wxWindow *parent);
  58.  
  59.     // event handlers
  60.     void OnPaint(wxPaintEvent& event);
  61.     void OnMouseClick(wxMouseEvent& event);
  62.     void OnMouseMove(wxMouseEvent& event);
  63.  
  64. #if !wxUSE_POPUPWIN
  65.     void OnKillFocus(wxFocusEvent& event);
  66. #endif // wxUSE_POPUPWIN
  67.  
  68.     // calculate the client rect we need to display the text
  69.     void Adjust(const wxString& text, wxCoord maxLength);
  70.  
  71. private:
  72.     wxTipWindow* m_parent;
  73.  
  74. #if !wxUSE_POPUPWIN
  75.     long m_creationTime;
  76. #endif // !wxUSE_POPUPWIN
  77.  
  78.     DECLARE_EVENT_TABLE()
  79. };
  80.  
  81. // ============================================================================
  82. // implementation
  83. // ============================================================================
  84.  
  85. // ----------------------------------------------------------------------------
  86. // event tables
  87. // ----------------------------------------------------------------------------
  88.  
  89. BEGIN_EVENT_TABLE(wxTipWindow, wxTipWindowBase)
  90.     EVT_LEFT_DOWN(wxTipWindow::OnMouseClick)
  91.     EVT_RIGHT_DOWN(wxTipWindow::OnMouseClick)
  92.     EVT_MIDDLE_DOWN(wxTipWindow::OnMouseClick)
  93.  
  94. #if !wxUSE_POPUPWIN
  95.     EVT_KILL_FOCUS(wxTipWindow::OnKillFocus)
  96.     EVT_ACTIVATE(wxTipWindow::OnActivate)
  97. #endif // !wxUSE_POPUPWIN
  98. END_EVENT_TABLE()
  99.  
  100. BEGIN_EVENT_TABLE(wxTipWindowView, wxWindow)
  101.     EVT_PAINT(wxTipWindowView::OnPaint)
  102.  
  103.     EVT_LEFT_DOWN(wxTipWindowView::OnMouseClick)
  104.     EVT_RIGHT_DOWN(wxTipWindowView::OnMouseClick)
  105.     EVT_MIDDLE_DOWN(wxTipWindowView::OnMouseClick)
  106.  
  107.     EVT_MOTION(wxTipWindowView::OnMouseMove)
  108.  
  109. #if !wxUSE_POPUPWIN
  110.     EVT_KILL_FOCUS(wxTipWindowView::OnKillFocus)
  111. #endif // !wxUSE_POPUPWIN
  112. END_EVENT_TABLE()
  113.  
  114. // ----------------------------------------------------------------------------
  115. // wxTipWindow
  116. // ----------------------------------------------------------------------------
  117.  
  118. wxTipWindow::wxTipWindow(wxWindow *parent,
  119.                          const wxString& text,
  120.                          wxCoord maxLength,
  121.                          wxTipWindow** windowPtr,
  122.                          wxRect *rectBounds)
  123. #if wxUSE_POPUPWIN
  124.            : wxPopupTransientWindow(parent)
  125. #else
  126.            : wxFrame(parent, -1, _T(""),
  127.                      wxDefaultPosition, wxDefaultSize,
  128.                      wxNO_BORDER | wxFRAME_NO_TASKBAR )
  129. #endif
  130. {
  131.     SetTipWindowPtr(windowPtr);
  132.     if ( rectBounds )
  133.     {
  134.         SetBoundingRect(*rectBounds);
  135.     }
  136.  
  137.     // set colours
  138.     SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOTEXT));
  139.     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK));
  140.  
  141.     // set size, position and show it
  142.     m_view = new wxTipWindowView(this);
  143.     m_view->Adjust(text, maxLength);
  144.     m_view->SetFocus();
  145.  
  146.     int x, y;
  147.     wxGetMousePosition(&x, &y);
  148.  
  149.     // we want to show the tip below the mouse, not over it
  150.     //
  151.     // NB: the reason we use "/ 2" here is that we don't know where the current
  152.     //     cursors hot spot is... it would be nice if we could find this out
  153.     //     though
  154.     y += wxSystemSettings::GetMetric(wxSYS_CURSOR_Y) / 2;
  155.  
  156. #if wxUSE_POPUPWIN
  157.     Position(wxPoint(x, y), wxSize(0, 0));
  158.     Popup(m_view);
  159. #else
  160.     Move(x, y);
  161.     Show(TRUE);
  162. #endif
  163. }
  164.  
  165. wxTipWindow::~wxTipWindow()
  166. {
  167.     if ( m_windowPtr )
  168.     {
  169.         *m_windowPtr = NULL;
  170.     }
  171. }
  172.  
  173. void wxTipWindow::OnMouseClick(wxMouseEvent& WXUNUSED(event))
  174. {
  175.     Close();
  176. }
  177.  
  178. #if wxUSE_POPUPWIN
  179.  
  180. void wxTipWindow::OnDismiss()
  181. {
  182.     Close();
  183. }
  184.  
  185. #else // !wxUSE_POPUPWIN
  186.  
  187. void wxTipWindow::OnActivate(wxActivateEvent& event)
  188. {
  189.     if (!event.GetActive())
  190.         Close();
  191. }
  192.  
  193. void wxTipWindow::OnKillFocus(wxFocusEvent& WXUNUSED(event))
  194. {
  195.     // Under Windows at least, we will get this immediately
  196.     // because when the view window is focussed, the
  197.     // tip window goes out of focus.
  198. #ifdef __WXGTK__
  199.     Close();
  200. #endif
  201. }
  202.  
  203. #endif // wxUSE_POPUPWIN // !wxUSE_POPUPWIN
  204.  
  205. void wxTipWindow::SetBoundingRect(const wxRect& rectBound)
  206. {
  207.     m_rectBound = rectBound;
  208. }
  209.  
  210. void wxTipWindow::Close()
  211. {
  212.     if ( m_windowPtr )
  213.     {
  214.         *m_windowPtr = NULL;
  215.         m_windowPtr = NULL;
  216.     }
  217.  
  218. #if wxUSE_POPUPWIN
  219.     Show(FALSE);
  220.     Destroy();
  221. #else
  222.     wxFrame::Close();
  223. #endif
  224. }
  225.  
  226. // ----------------------------------------------------------------------------
  227. // wxTipWindowView
  228. // ----------------------------------------------------------------------------
  229.  
  230. wxTipWindowView::wxTipWindowView(wxWindow *parent)
  231.                : wxWindow(parent, -1,
  232.                           wxDefaultPosition, wxDefaultSize,
  233.                           wxNO_BORDER)
  234. {
  235.     // set colours
  236.     SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOTEXT));
  237.     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK));
  238.  
  239. #if !wxUSE_POPUPWIN
  240.     m_creationTime = wxGetLocalTime();
  241. #endif // !wxUSE_POPUPWIN
  242.  
  243.     m_parent = (wxTipWindow*)parent;
  244. }
  245.  
  246. void wxTipWindowView::Adjust(const wxString& text, wxCoord maxLength)
  247. {
  248.     wxClientDC dc(this);
  249.     dc.SetFont(GetFont());
  250.  
  251.     // calculate the length: we want each line be no longer than maxLength
  252.     // pixels and we only break lines at words boundary
  253.     wxString current;
  254.     wxCoord height, width,
  255.             widthMax = 0;
  256.     m_parent->m_heightLine = 0;
  257.  
  258.     bool breakLine = FALSE;
  259.     for ( const wxChar *p = text.c_str(); ; p++ )
  260.     {
  261.         if ( *p == _T('\n') || *p == _T('\0') )
  262.         {
  263.             dc.GetTextExtent(current, &width, &height);
  264.             if ( width > widthMax )
  265.                 widthMax = width;
  266.  
  267.             if ( height > m_parent->m_heightLine )
  268.                 m_parent->m_heightLine = height;
  269.  
  270.             m_parent->m_textLines.Add(current);
  271.  
  272.             if ( !*p )
  273.             {
  274.                 // end of text
  275.                 break;
  276.             }
  277.  
  278.             current.clear();
  279.             breakLine = FALSE;
  280.         }
  281.         else if ( breakLine && (*p == _T(' ') || *p == _T('\t')) )
  282.         {
  283.             // word boundary - break the line here
  284.             m_parent->m_textLines.Add(current);
  285.             current.clear();
  286.             breakLine = FALSE;
  287.         }
  288.         else // line goes on
  289.         {
  290.             current += *p;
  291.             dc.GetTextExtent(current, &width, &height);
  292.             if ( width > maxLength )
  293.                 breakLine = TRUE;
  294.  
  295.             if ( width > widthMax )
  296.                 widthMax = width;
  297.  
  298.             if ( height > m_parent->m_heightLine )
  299.                 m_parent->m_heightLine = height;
  300.         }
  301.     }
  302.  
  303.     // take into account the border size and the margins
  304.     width  = 2*(TEXT_MARGIN_X + 1) + widthMax;
  305.     height = 2*(TEXT_MARGIN_Y + 1) + m_parent->m_textLines.GetCount()*m_parent->m_heightLine;
  306.     m_parent->SetClientSize(width, height);
  307.     SetSize(0, 0, width, height);
  308. }
  309.  
  310. void wxTipWindowView::OnPaint(wxPaintEvent& WXUNUSED(event))
  311. {
  312.     wxPaintDC dc(this);
  313.  
  314.     wxRect rect;
  315.     wxSize size = GetClientSize();
  316.     rect.width = size.x;
  317.     rect.height = size.y;
  318.  
  319.     // first filll the background
  320.     dc.SetBrush(wxBrush(GetBackgroundColour(), wxSOLID));
  321.     dc.SetPen( wxPen(GetForegroundColour(), 1, wxSOLID) );
  322.     dc.DrawRectangle(rect);
  323.  
  324.     // and then draw the text line by line
  325.     dc.SetTextBackground(GetBackgroundColour());
  326.     dc.SetTextForeground(GetForegroundColour());
  327.     dc.SetFont(GetFont());
  328.  
  329.     wxPoint pt;
  330.     pt.x = TEXT_MARGIN_X;
  331.     pt.y = TEXT_MARGIN_Y;
  332.     size_t count = m_parent->m_textLines.GetCount();
  333.     for ( size_t n = 0; n < count; n++ )
  334.     {
  335.         dc.DrawText(m_parent->m_textLines[n], pt);
  336.  
  337.         pt.y += m_parent->m_heightLine;
  338.     }
  339. }
  340.  
  341. void wxTipWindowView::OnMouseClick(wxMouseEvent& WXUNUSED(event))
  342. {
  343.     m_parent->Close();
  344. }
  345.  
  346. void wxTipWindowView::OnMouseMove(wxMouseEvent& event)
  347. {
  348.     const wxRect& rectBound = m_parent->m_rectBound;
  349.  
  350.     if ( rectBound.width &&
  351.             !rectBound.Inside(ClientToScreen(event.GetPosition())) )
  352.     {
  353.         // mouse left the bounding rect, disappear
  354.         m_parent->Close();
  355.     }
  356.     else
  357.     {
  358.         event.Skip();
  359.     }
  360. }
  361.  
  362. #if !wxUSE_POPUPWIN
  363. void wxTipWindowView::OnKillFocus(wxFocusEvent& WXUNUSED(event))
  364. {
  365.     // Workaround the kill focus event happening just after creation in wxGTK
  366.     if (wxGetLocalTime() > m_creationTime + 1)
  367.         m_parent->Close();
  368. }
  369. #endif // !wxUSE_POPUPWIN
  370.  
  371. #endif // wxUSE_TIPWINDOW
  372.