wxTipWindow is now a wxPopupTransientWindow instead of a wxFrame.
[wxWidgets.git] / src / generic / tipwin.cpp
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 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 #include "wx/timer.h"
37 #include "wx/settings.h"
38
39 // ----------------------------------------------------------------------------
40 // constants
41 // ----------------------------------------------------------------------------
42
43 static const wxCoord TEXT_MARGIN_X = 3;
44 static const wxCoord TEXT_MARGIN_Y = 3;
45
46 // ============================================================================
47 // implementation
48 // ============================================================================
49
50 // ----------------------------------------------------------------------------
51 // event tables
52 // ----------------------------------------------------------------------------
53
54 BEGIN_EVENT_TABLE(wxTipWindow, wxPopupTransientWindow)
55 EVT_LEFT_DOWN(wxTipWindow::OnMouseClick)
56 EVT_RIGHT_DOWN(wxTipWindow::OnMouseClick)
57 EVT_MIDDLE_DOWN(wxTipWindow::OnMouseClick)
58 EVT_PAINT(wxTipWindow::OnPaint)
59 END_EVENT_TABLE()
60
61
62 #if 0
63 // Viewer window to put in the frame
64 class wxTipWindowView: public wxWindow
65 {
66 public:
67 wxTipWindowView(wxWindow *parent);
68
69 // event handlers
70 void OnPaint(wxPaintEvent& event);
71 void OnMouseClick(wxMouseEvent& event);
72 void OnKillFocus(wxFocusEvent& event);
73
74 // calculate the client rect we need to display the text
75 void Adjust(const wxString& text, wxCoord maxLength);
76
77 long m_creationTime;
78
79 DECLARE_EVENT_TABLE()
80 };
81
82 BEGIN_EVENT_TABLE(wxTipWindowView, wxWindow)
83 EVT_PAINT(wxTipWindowView::OnPaint)
84 EVT_LEFT_DOWN(wxTipWindowView::OnMouseClick)
85 EVT_RIGHT_DOWN(wxTipWindowView::OnMouseClick)
86 EVT_MIDDLE_DOWN(wxTipWindowView::OnMouseClick)
87 EVT_KILL_FOCUS(wxTipWindowView::OnKillFocus)
88 END_EVENT_TABLE()
89 #endif
90
91 // ----------------------------------------------------------------------------
92 // wxTipWindow
93 // ----------------------------------------------------------------------------
94
95 wxTipWindow::wxTipWindow(wxWindow *parent,
96 const wxString& text,
97 wxCoord maxLength, wxTipWindow** windowPtr)
98 : wxPopupTransientWindow(parent)
99 {
100 m_windowPtr = windowPtr;
101
102 // set colours
103 SetForegroundColour(*wxBLACK);
104
105 #ifdef __WXMSW__
106 wxColour bkCol(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_INFOBK));
107 #else
108 wxColour bkCol(wxColour(255, 255, 225));
109 #endif
110 SetBackgroundColour(bkCol);
111
112 // set size and position
113 Adjust(text, maxLength);
114 int x, y;
115 wxGetMousePosition(&x, &y);
116 Position(wxPoint(x, y+10), wxSize(0,0));
117
118 //Show(TRUE);
119 Popup();
120 SetFocus();
121 }
122
123 wxTipWindow::~wxTipWindow()
124 {
125 if (m_windowPtr)
126 {
127 *m_windowPtr = NULL;
128 }
129 }
130
131 void wxTipWindow::OnMouseClick(wxMouseEvent& WXUNUSED(event))
132 {
133 Close();
134 }
135
136
137 void wxTipWindow::OnPaint(wxPaintEvent& WXUNUSED(event))
138 {
139 wxPaintDC dc(this);
140
141 wxRect rect;
142 wxSize size = GetClientSize();
143 rect.width = size.x;
144 rect.height = size.y;
145
146 // first filll the background
147 dc.SetBrush(wxBrush(GetBackgroundColour(), wxSOLID));
148
149 dc.SetPen( * wxBLACK_PEN );
150 dc.DrawRectangle(rect);
151
152 // and then draw the text line by line
153 dc.SetFont(GetFont());
154
155 wxPoint pt;
156 pt.x = TEXT_MARGIN_X;
157 pt.y = TEXT_MARGIN_Y;
158 size_t count = m_textLines.GetCount();
159 for ( size_t n = 0; n < count; n++ )
160 {
161 dc.DrawText(m_textLines[n], pt);
162
163 pt.y += m_heightLine;
164 }
165 }
166
167
168 void wxTipWindow::Adjust(const wxString& text, wxCoord maxLength)
169 {
170 wxClientDC dc(this);
171 dc.SetFont(GetFont());
172
173 // calculate the length: we want each line be no longer than maxLength
174 // pixels and we only break lines at words boundary
175 wxString current;
176 wxCoord height, width,
177 widthMax = 0;
178 m_heightLine = 0;
179
180 bool breakLine = FALSE;
181 for ( const wxChar *p = text.c_str(); ; p++ )
182 {
183 if ( *p == _T('\n') || *p == _T('\0') )
184 {
185 dc.GetTextExtent(current, &width, &height);
186 if ( width > widthMax )
187 widthMax = width;
188
189 if ( height > m_heightLine )
190 m_heightLine = height;
191
192 m_textLines.Add(current);
193
194 if ( !*p )
195 {
196 // end of text
197 break;
198 }
199
200 current.clear();
201 breakLine = FALSE;
202 }
203 else if ( breakLine && (*p == _T(' ') || *p == _T('\t')) )
204 {
205 // word boundary - break the line here
206 m_textLines.Add(current);
207 current.clear();
208 breakLine = FALSE;
209 }
210 else // line goes on
211 {
212 current += *p;
213 dc.GetTextExtent(current, &width, &height);
214 if ( width > maxLength )
215 breakLine = TRUE;
216
217 if ( width > widthMax )
218 widthMax = width;
219
220 if ( height > m_heightLine )
221 m_heightLine = height;
222 }
223 }
224
225 // take into account the border size and the margins
226 SetClientSize(2*(TEXT_MARGIN_X + 1) + widthMax,
227 2*(TEXT_MARGIN_Y + 1) + m_textLines.GetCount() * m_heightLine);
228 }
229
230
231 void wxTipWindow::Close()
232 {
233 Show(FALSE);
234 Destroy();
235 }
236
237
238 // ----------------------------------------------------------------------------
239 // wxTipWindowView
240 // ----------------------------------------------------------------------------
241 #if 0
242 wxTipWindowView::wxTipWindowView(wxWindow *parent)
243 : wxWindow(parent, -1,
244 wxDefaultPosition, wxDefaultSize,
245 wxNO_BORDER)
246 {
247 // set colours
248 SetForegroundColour(*wxBLACK);
249 #ifdef __WXMSW__
250 wxColour bkCol(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_INFOBK));
251 #else
252 wxColour bkCol(wxColour(255, 255, 225));
253 #endif
254 SetBackgroundColour(bkCol);
255 m_creationTime = wxGetLocalTime();
256 }
257
258 void wxTipWindowView::Adjust(const wxString& text, wxCoord maxLength)
259 {
260 wxTipWindow* parent = (wxTipWindow*) GetParent();
261 wxClientDC dc(this);
262 dc.SetFont(GetFont());
263
264 // calculate the length: we want each line be no longer than maxLength
265 // pixels and we only break lines at words boundary
266 wxString current;
267 wxCoord height, width,
268 widthMax = 0;
269 parent->m_heightLine = 0;
270
271 bool breakLine = FALSE;
272 for ( const wxChar *p = text.c_str(); ; p++ )
273 {
274 if ( *p == _T('\n') || *p == _T('\0') )
275 {
276 dc.GetTextExtent(current, &width, &height);
277 if ( width > widthMax )
278 widthMax = width;
279
280 if ( height > parent->m_heightLine )
281 parent->m_heightLine = height;
282
283 parent->m_textLines.Add(current);
284
285 if ( !*p )
286 {
287 // end of text
288 break;
289 }
290
291 current.clear();
292 breakLine = FALSE;
293 }
294 else if ( breakLine && (*p == _T(' ') || *p == _T('\t')) )
295 {
296 // word boundary - break the line here
297 parent->m_textLines.Add(current);
298 current.clear();
299 breakLine = FALSE;
300 }
301 else // line goes on
302 {
303 current += *p;
304 dc.GetTextExtent(current, &width, &height);
305 if ( width > maxLength )
306 breakLine = TRUE;
307
308 if ( width > widthMax )
309 widthMax = width;
310
311 if ( height > parent->m_heightLine )
312 parent->m_heightLine = height;
313 }
314 }
315
316 // take into account the border size and the margins
317 GetParent()->SetClientSize(2*(TEXT_MARGIN_X + 1) + widthMax,
318 2*(TEXT_MARGIN_Y + 1) + parent->m_textLines.GetCount()*parent->m_heightLine);
319 }
320
321 void wxTipWindowView::OnPaint(wxPaintEvent& WXUNUSED(event))
322 {
323 wxTipWindow* parent = (wxTipWindow*) GetParent();
324 if (!parent)
325 return;
326
327 wxPaintDC dc(this);
328
329 wxRect rect;
330 wxSize size = GetClientSize();
331 rect.width = size.x;
332 rect.height = size.y;
333
334 // first filll the background
335 dc.SetBrush(wxBrush(GetBackgroundColour(), wxSOLID));
336
337 dc.SetPen( * wxBLACK_PEN );
338 dc.DrawRectangle(rect);
339
340 // and then draw the text line by line
341 dc.SetFont(GetFont());
342
343 wxPoint pt;
344 pt.x = TEXT_MARGIN_X;
345 pt.y = TEXT_MARGIN_Y;
346 size_t count = parent->m_textLines.GetCount();
347 for ( size_t n = 0; n < count; n++ )
348 {
349 dc.DrawText(parent->m_textLines[n], pt);
350
351 pt.y += parent->m_heightLine;
352 }
353 }
354
355 void wxTipWindowView::OnMouseClick(wxMouseEvent& WXUNUSED(event))
356 {
357 GetParent()->Close();
358 }
359
360 void wxTipWindowView::OnKillFocus(wxFocusEvent& WXUNUSED(event))
361 {
362 // Workaround the kill focus event happening just after creation in wxGTK
363 if (wxGetLocalTime() > m_creationTime + 1)
364 GetParent()->Close();
365 }
366
367 #endif