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