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