added the possibility to hide the tip window automatically when the mouse leave the specified rectangle; fixed a few bugs with the window not disappearing automatically

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@13664 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2002-01-19 21:49:39 +00:00
parent 60178eb439
commit dafbe8c0af
3 changed files with 211 additions and 77 deletions

View File

@@ -1,11 +1,12 @@
\section{\class{wxTipWindow}}\label{wxtipwindow}
Shows simple text in a popup tip window on creation. This is used by \helpref{wxSimpleHelpProvider}{wxsimplehelpprovider} to
show popup help. The window automatically destroys itself when the user clicks on it or it loses
the focus.
Shows simple text in a popup tip window on creation. This is used by
\helpref{wxSimpleHelpProvider}{wxsimplehelpprovider} to show popup help. The
window automatically destroys itself when the user clicks on it or it loses the
focus.
You should not normally need to use it explicitly in your application since a help provider class
will create it when required.
You may also use this class to emulate the tooltips when you need finer
control over them than what the standard tooltips provide.
\wxheading{Derived from}
@@ -23,13 +24,48 @@ wxPopupWindow\\
\membersection{wxTipWindow::wxTipWindow}\label{wxtipwindowwxtipwindow}
\func{}{wxTipWindow}{\param{wxWindow* }{parent}, \param{const wxString\& }{text}, \param{wxCoord }{maxLength = 100}}
\func{}{wxTipWindow}{\param{wxWindow* }{parent}, \param{const wxString\& }{text}, \param{wxCoord }{maxLength = 100}, \param{wxTipWindow** }{windowPtr}}
Constructor. The tip is shown immediately the window is constructed.
\membersection{wxTipWindow::Adjust}\label{wxtipwindowadjust}
\wxheading{Parameters}
\func{void}{Adjust}{\param{const wxString\& }{text}, \param{wxCoord }{maxLength}}
\docparam{parent}{The parent window, must be non {\tt NULL}}
Calculates the client rect we need to display the text.
\docparam{text}{The text to show, may contain the new line characters}
\docparam{windowPtr}{Simply passed to
\helpref{SetTipWindowPtr}{wxtipwindowsettipwindowptr} below, please see its
documentation for the description of this parameter}
\docparam{rectBounds}{If non {\tt NULL}, passed to
\helpref{SetBoundingRect}{wxtipwindowsetboundingrect} below, please see its
documentation for the description of this parameter}
\membersection{wxTipWindow::SetTipWindowPtr}\label{wxtipwindowsettipwindowptr}
\func{void}{SetTipWindowPtr}{\param{wxTipWindow** }{windowPtr}}
When the tip window closes itself (which may happen at any moment and
unexpectedly to the caller) it may {\tt NULL} out the pointer pointed to by
{\it windowPtr}. This is helpful to avoid dereferencing the tip window which
had been already closed and deleted.
\membersection{wxTipWindow::SetBoundingRect}{wxtipwindowsetboundingrect}
\func{void}{SetBoundingRect}{\param{const wxRect\& }{rectBound}}
By default, the tip window disappears when the user clicks the mouse or presses
a keyboard key or if it loses focus in any other way - for example because the
user switched to another application window.
Additionally, if a non empty {\it rectBound} is provided, the tip window will
also automatically close if the mouse leaves this area. This is useful to
dismiss the tip mouse when the mouse leaves the object it is associated with.
\wxheading{Parameters}
\docparam{rectBound}{The bounding rectangle for the mouse in the screen coordinates}

View File

@@ -20,49 +20,80 @@
#if wxUSE_TIPWINDOW
#if wxUSE_POPUPWIN
#include "wx/popupwin.h"
#include "wx/popupwin.h"
#define wxTipWindowBase wxPopupTransientWindow
#else
#include "wx/frame.h"
#include "wx/frame.h"
#define wxTipWindowBase wxFrame
#endif
class WXDLLEXPORT wxTipWindowView;
// ----------------------------------------------------------------------------
// wxTipWindow
// ----------------------------------------------------------------------------
#if wxUSE_POPUPWIN
class WXDLLEXPORT wxTipWindow : public wxPopupTransientWindow
#else
class WXDLLEXPORT wxTipWindow : public wxFrame
#endif
class WXDLLEXPORT wxTipWindow : public wxTipWindowBase
{
friend class wxTipWindowView;
public:
// Supply windowPtr for it to null the given address
// when the window has closed.
// the mandatory ctor parameters are: the parent window and the text to
// show
//
// optionally you may also specify the length at which the lines are going
// to be broken in rows (100 pixels by default)
//
// windowPtr and rectBound are just passed to SetTipWindowPtr() and
// SetBoundingRect() - see below
wxTipWindow(wxWindow *parent,
const wxString& text,
wxCoord maxLength = 100, wxTipWindow** windowPtr = NULL);
~wxTipWindow();
wxCoord maxLength = 100,
wxTipWindow** windowPtr = NULL,
wxRect *rectBound = NULL);
virtual ~wxTipWindow();
// If windowPtr is not NULL the given address will be NULLed when the
// window has closed
void SetTipWindowPtr(wxTipWindow** windowPtr) { m_windowPtr = windowPtr; }
// If rectBound is not NULL, the window will disappear automatically when
// the mouse leave the specified rect: note that rectBound should be in the
// screen coordinates!
void SetBoundingRect(const wxRect& rectBound);
// Hide and destroy the window
void Close();
protected:
// called by wxTipWindowView only
bool CheckMouseInBounds(const wxPoint& pos);
// event handlers
void OnMouseClick(wxMouseEvent& event);
#if !wxUSE_POPUPWIN
void OnActivate(wxActivateEvent& event);
void OnKillFocus(wxFocusEvent& event);
#endif
#else // wxUSE_POPUPWIN
virtual void OnDismiss();
#endif // wxUSE_POPUPWIN/!wxUSE_POPUPWIN
private:
wxArrayString m_textLines;
wxCoord m_heightLine;
wxTipWindowView *m_view;
wxTipWindow** m_windowPtr;
wxRect m_rectBound;
DECLARE_EVENT_TABLE()
friend class wxTipWindowView;
};
#endif // wxUSE_TIPWINDOW
#endif // _WX_TIPWIN_H_

View File

@@ -46,6 +46,38 @@
static const wxCoord TEXT_MARGIN_X = 3;
static const wxCoord TEXT_MARGIN_Y = 3;
// ----------------------------------------------------------------------------
// wxTipWindowView
// ----------------------------------------------------------------------------
// Viewer window to put in the frame
class WXDLLEXPORT wxTipWindowView : public wxWindow
{
public:
wxTipWindowView(wxWindow *parent);
// event handlers
void OnPaint(wxPaintEvent& event);
void OnMouseClick(wxMouseEvent& event);
void OnMouseMove(wxMouseEvent& event);
#if !wxUSE_POPUPWIN
void OnKillFocus(wxFocusEvent& event);
#endif // wxUSE_POPUPWIN
// calculate the client rect we need to display the text
void Adjust(const wxString& text, wxCoord maxLength);
private:
wxTipWindow* m_parent;
#if !wxUSE_POPUPWIN
long m_creationTime;
#endif // !wxUSE_POPUPWIN
DECLARE_EVENT_TABLE()
};
// ============================================================================
// implementation
// ============================================================================
@@ -54,51 +86,29 @@ static const wxCoord TEXT_MARGIN_Y = 3;
// event tables
// ----------------------------------------------------------------------------
#if wxUSE_POPUPWIN
BEGIN_EVENT_TABLE(wxTipWindow, wxPopupTransientWindow)
#else
BEGIN_EVENT_TABLE(wxTipWindow, wxFrame)
#endif
BEGIN_EVENT_TABLE(wxTipWindow, wxTipWindowBase)
EVT_LEFT_DOWN(wxTipWindow::OnMouseClick)
EVT_RIGHT_DOWN(wxTipWindow::OnMouseClick)
EVT_MIDDLE_DOWN(wxTipWindow::OnMouseClick)
#if !wxUSE_POPUPWIN
EVT_KILL_FOCUS(wxTipWindow::OnKillFocus)
EVT_ACTIVATE(wxTipWindow::OnActivate)
#endif
#endif // !wxUSE_POPUPWIN
END_EVENT_TABLE()
// Viewer window to put in the frame
class wxTipWindowView: public wxWindow
{
public:
wxTipWindowView(wxWindow *parent);
// event handlers
void OnPaint(wxPaintEvent& event);
void OnMouseClick(wxMouseEvent& event);
#if !wxUSE_POPUPWIN
void OnKillFocus(wxFocusEvent& event);
#endif
// calculate the client rect we need to display the text
void Adjust(const wxString& text, wxCoord maxLength);
private:
long m_creationTime;
wxTipWindow* m_parent;
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(wxTipWindowView, wxWindow)
EVT_PAINT(wxTipWindowView::OnPaint)
EVT_LEFT_DOWN(wxTipWindowView::OnMouseClick)
EVT_RIGHT_DOWN(wxTipWindowView::OnMouseClick)
EVT_MIDDLE_DOWN(wxTipWindowView::OnMouseClick)
EVT_MOTION(wxTipWindowView::OnMouseMove)
#if !wxUSE_POPUPWIN
EVT_KILL_FOCUS(wxTipWindowView::OnKillFocus)
#endif
#endif // !wxUSE_POPUPWIN
END_EVENT_TABLE()
// ----------------------------------------------------------------------------
@@ -107,7 +117,9 @@ END_EVENT_TABLE()
wxTipWindow::wxTipWindow(wxWindow *parent,
const wxString& text,
wxCoord maxLength, wxTipWindow** windowPtr)
wxCoord maxLength,
wxTipWindow** windowPtr,
wxRect *rectBounds)
#if wxUSE_POPUPWIN
: wxPopupTransientWindow(parent)
#else
@@ -116,36 +128,50 @@ wxTipWindow::wxTipWindow(wxWindow *parent,
wxNO_BORDER | wxFRAME_NO_TASKBAR )
#endif
{
m_windowPtr = windowPtr;
SetTipWindowPtr(windowPtr);
if ( rectBounds )
{
SetBoundingRect(*rectBounds);
}
// set colours
SetForegroundColour(*wxBLACK);
//
// VZ: why don't we use wxSystemSettings for !MSW? (FIXME)
#ifdef __WXMSW__
wxColour bkCol(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK));
SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOTEXT));
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK));
#else
wxColour bkCol(wxColour(255, 255, 225));
SetForegroundColour(*wxBLACK);
SetBackgroundColour(*wxWHITE);
#endif
SetBackgroundColour(bkCol);
// set size, position and show it
wxTipWindowView* tipWindowView = new wxTipWindowView(this);
tipWindowView->Adjust(text, maxLength);
tipWindowView->SetFocus();
m_view = new wxTipWindowView(this);
m_view->Adjust(text, maxLength);
m_view->SetFocus();
int x, y;
wxGetMousePosition(&x, &y);
// we want to show the tip below the mouse, not over it
//
// NB: the reason we use "/ 2" here is that we don't know where the current
// cursors hot spot is... it would be nice if we could find this out
// though
y += wxSystemSettings::GetMetric(wxSYS_CURSOR_Y) / 2;
#if wxUSE_POPUPWIN
Position(wxPoint(x, y+10), wxSize(0,0));
Popup(tipWindowView);
Position(wxPoint(x, y), wxSize(0, 0));
Popup(m_view);
#else
Move(x, y + 10);
Move(x, y);
Show(TRUE);
#endif
}
wxTipWindow::~wxTipWindow()
{
if (m_windowPtr)
if ( m_windowPtr )
{
*m_windowPtr = NULL;
}
@@ -156,7 +182,15 @@ void wxTipWindow::OnMouseClick(wxMouseEvent& WXUNUSED(event))
Close();
}
#if !wxUSE_POPUPWIN
#if wxUSE_POPUPWIN
void wxTipWindow::OnDismiss()
{
Close();
}
#else // !wxUSE_POPUPWIN
void wxTipWindow::OnActivate(wxActivateEvent& event)
{
if (!event.GetActive())
@@ -172,11 +206,22 @@ void wxTipWindow::OnKillFocus(wxFocusEvent& WXUNUSED(event))
Close();
#endif
}
#endif
#endif // wxUSE_POPUPWIN // !wxUSE_POPUPWIN
void wxTipWindow::SetBoundingRect(const wxRect& rectBound)
{
m_rectBound = rectBound;
}
void wxTipWindow::Close()
{
if ( m_windowPtr )
{
*m_windowPtr = NULL;
m_windowPtr = NULL;
}
#if wxUSE_POPUPWIN
Show(FALSE);
Destroy();
@@ -190,19 +235,25 @@ void wxTipWindow::Close()
// ----------------------------------------------------------------------------
wxTipWindowView::wxTipWindowView(wxWindow *parent)
: wxWindow(parent, -1,
wxDefaultPosition, wxDefaultSize,
wxNO_BORDER)
: wxWindow(parent, -1,
wxDefaultPosition, wxDefaultSize,
wxNO_BORDER)
{
// set colours
SetForegroundColour(*wxBLACK);
//
// VZ: why don't we use wxSystemSettings for !MSW? (FIXME)
#ifdef __WXMSW__
wxColour bkCol(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK));
SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOTEXT));
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK));
#else
wxColour bkCol(wxColour(255, 255, 225));
SetForegroundColour(*wxBLACK);
SetBackgroundColour(*wxWHITE);
#endif
SetBackgroundColour(bkCol);
#if !wxUSE_POPUPWIN
m_creationTime = wxGetLocalTime();
#endif // !wxUSE_POPUPWIN
m_parent = (wxTipWindow*)parent;
}
@@ -306,6 +357,22 @@ void wxTipWindowView::OnMouseClick(wxMouseEvent& WXUNUSED(event))
m_parent->Close();
}
void wxTipWindowView::OnMouseMove(wxMouseEvent& event)
{
const wxRect& rectBound = m_parent->m_rectBound;
if ( rectBound.width &&
!rectBound.Inside(ClientToScreen(event.GetPosition())) )
{
// mouse left the bounding rect, disappear
m_parent->Close();
}
else
{
event.Skip();
}
}
#if !wxUSE_POPUPWIN
void wxTipWindowView::OnKillFocus(wxFocusEvent& WXUNUSED(event))
{
@@ -313,6 +380,6 @@ void wxTipWindowView::OnKillFocus(wxFocusEvent& WXUNUSED(event))
if (wxGetLocalTime() > m_creationTime + 1)
m_parent->Close();
}
#endif
#endif // !wxUSE_POPUPWIN
#endif
#endif // wxUSE_TIPWINDOW