]> git.saurik.com Git - wxWidgets.git/blame - src/generic/tipwin.cpp
patch from Dimitri fixing crashes when decoding the invalid GIFs
[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>
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"
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
49// ============================================================================
50// implementation
51// ============================================================================
52
53// ----------------------------------------------------------------------------
54// event tables
55// ----------------------------------------------------------------------------
56
961c54c3 57#if wxUSE_POPUPWIN
8962e1d9 58BEGIN_EVENT_TABLE(wxTipWindow, wxPopupTransientWindow)
961c54c3
RD
59#else
60BEGIN_EVENT_TABLE(wxTipWindow, wxFrame)
61#endif
01fa3fe7
VZ
62 EVT_LEFT_DOWN(wxTipWindow::OnMouseClick)
63 EVT_RIGHT_DOWN(wxTipWindow::OnMouseClick)
64 EVT_MIDDLE_DOWN(wxTipWindow::OnMouseClick)
961c54c3
RD
65#if !wxUSE_POPUPWIN
66 EVT_KILL_FOCUS(wxTipWindow::OnKillFocus)
67 EVT_ACTIVATE(wxTipWindow::OnActivate)
68#endif
01fa3fe7
VZ
69END_EVENT_TABLE()
70
8962e1d9 71
961c54c3
RD
72// Viewer window to put in the frame
73class wxTipWindowView: public wxWindow
74{
75public:
76 wxTipWindowView(wxWindow *parent);
77
78 // event handlers
79 void OnPaint(wxPaintEvent& event);
80 void OnMouseClick(wxMouseEvent& event);
81#if !wxUSE_POPUPWIN
82 void OnKillFocus(wxFocusEvent& event);
83#endif
84 // calculate the client rect we need to display the text
85 void Adjust(const wxString& text, wxCoord maxLength);
86
87private:
88 long m_creationTime;
89 wxTipWindow* m_parent;
90
91 DECLARE_EVENT_TABLE()
92};
93
94BEGIN_EVENT_TABLE(wxTipWindowView, wxWindow)
95 EVT_PAINT(wxTipWindowView::OnPaint)
96 EVT_LEFT_DOWN(wxTipWindowView::OnMouseClick)
97 EVT_RIGHT_DOWN(wxTipWindowView::OnMouseClick)
98 EVT_MIDDLE_DOWN(wxTipWindowView::OnMouseClick)
99#if !wxUSE_POPUPWIN
100 EVT_KILL_FOCUS(wxTipWindowView::OnKillFocus)
101#endif
102END_EVENT_TABLE()
103
01fa3fe7
VZ
104// ----------------------------------------------------------------------------
105// wxTipWindow
106// ----------------------------------------------------------------------------
107
108wxTipWindow::wxTipWindow(wxWindow *parent,
109 const wxString& text,
173e8bbf 110 wxCoord maxLength, wxTipWindow** windowPtr)
961c54c3 111#if wxUSE_POPUPWIN
8962e1d9 112 : wxPopupTransientWindow(parent)
961c54c3
RD
113#else
114 : wxFrame(parent, -1, _T(""),
115 wxDefaultPosition, wxDefaultSize,
116 wxNO_BORDER | wxFRAME_NO_TASKBAR )
117#endif
01fa3fe7 118{
8962e1d9
RD
119 m_windowPtr = windowPtr;
120
01fa3fe7
VZ
121 // set colours
122 SetForegroundColour(*wxBLACK);
04ef50df
JS
123
124#ifdef __WXMSW__
125 wxColour bkCol(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_INFOBK));
126#else
127 wxColour bkCol(wxColour(255, 255, 225));
128#endif
129 SetBackgroundColour(bkCol);
130
961c54c3
RD
131 // set size, position and show it
132 wxTipWindowView* tipWindowView = new wxTipWindowView(this);
133 tipWindowView->Adjust(text, maxLength);
134 tipWindowView->SetFocus();
01fa3fe7
VZ
135 int x, y;
136 wxGetMousePosition(&x, &y);
961c54c3 137#if wxUSE_POPUPWIN
8962e1d9 138 Position(wxPoint(x, y+10), wxSize(0,0));
961c54c3
RD
139 Popup(tipWindowView);
140#else
141 Move(x, y + 10);
142 Show(TRUE);
143#endif
173e8bbf
JS
144}
145
146wxTipWindow::~wxTipWindow()
147{
148 if (m_windowPtr)
149 {
150 *m_windowPtr = NULL;
151 }
152}
153
33ac7e6f 154void wxTipWindow::OnMouseClick(wxMouseEvent& WXUNUSED(event))
173e8bbf
JS
155{
156 Close();
157}
158
961c54c3
RD
159#if !wxUSE_POPUPWIN
160void wxTipWindow::OnActivate(wxActivateEvent& event)
173e8bbf 161{
961c54c3
RD
162 if (!event.GetActive())
163 Close();
164}
8962e1d9 165
961c54c3
RD
166void wxTipWindow::OnKillFocus(wxFocusEvent& WXUNUSED(event))
167{
168 // Under Windows at least, we will get this immediately
169 // because when the view window is focussed, the
170 // tip window goes out of focus.
171#ifdef __WXGTK__
172 Close();
173#endif
174}
175#endif
8962e1d9 176
8962e1d9 177
961c54c3
RD
178void wxTipWindow::Close()
179{
180#if wxUSE_POPUPWIN
181 Show(FALSE);
182 Destroy();
183#else
184 wxFrame::Close();
185#endif
186}
8962e1d9 187
961c54c3
RD
188// ----------------------------------------------------------------------------
189// wxTipWindowView
190// ----------------------------------------------------------------------------
8962e1d9 191
961c54c3
RD
192wxTipWindowView::wxTipWindowView(wxWindow *parent)
193 : wxWindow(parent, -1,
194 wxDefaultPosition, wxDefaultSize,
195 wxNO_BORDER)
196{
197 // set colours
198 SetForegroundColour(*wxBLACK);
199#ifdef __WXMSW__
200 wxColour bkCol(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_INFOBK));
201#else
202 wxColour bkCol(wxColour(255, 255, 225));
203#endif
204 SetBackgroundColour(bkCol);
205 m_creationTime = wxGetLocalTime();
206 m_parent = (wxTipWindow*)parent;
173e8bbf
JS
207}
208
961c54c3 209void wxTipWindowView::Adjust(const wxString& text, wxCoord maxLength)
173e8bbf 210{
8962e1d9
RD
211 wxClientDC dc(this);
212 dc.SetFont(GetFont());
213
214 // calculate the length: we want each line be no longer than maxLength
215 // pixels and we only break lines at words boundary
216 wxString current;
217 wxCoord height, width,
218 widthMax = 0;
961c54c3 219 m_parent->m_heightLine = 0;
8962e1d9
RD
220
221 bool breakLine = FALSE;
222 for ( const wxChar *p = text.c_str(); ; p++ )
223 {
224 if ( *p == _T('\n') || *p == _T('\0') )
225 {
226 dc.GetTextExtent(current, &width, &height);
227 if ( width > widthMax )
228 widthMax = width;
229
961c54c3
RD
230 if ( height > m_parent->m_heightLine )
231 m_parent->m_heightLine = height;
8962e1d9 232
961c54c3 233 m_parent->m_textLines.Add(current);
8962e1d9
RD
234
235 if ( !*p )
236 {
237 // end of text
238 break;
239 }
240
241 current.clear();
242 breakLine = FALSE;
243 }
244 else if ( breakLine && (*p == _T(' ') || *p == _T('\t')) )
245 {
246 // word boundary - break the line here
961c54c3 247 m_parent->m_textLines.Add(current);
8962e1d9
RD
248 current.clear();
249 breakLine = FALSE;
250 }
251 else // line goes on
252 {
253 current += *p;
254 dc.GetTextExtent(current, &width, &height);
255 if ( width > maxLength )
256 breakLine = TRUE;
257
258 if ( width > widthMax )
259 widthMax = width;
260
961c54c3
RD
261 if ( height > m_parent->m_heightLine )
262 m_parent->m_heightLine = height;
8962e1d9
RD
263 }
264 }
265
266 // take into account the border size and the margins
961c54c3
RD
267 width = 2*(TEXT_MARGIN_X + 1) + widthMax;
268 height = 2*(TEXT_MARGIN_Y + 1) + m_parent->m_textLines.GetCount()*m_parent->m_heightLine;
269 m_parent->SetClientSize(width, height);
270 SetSize(0, 0, width, height);
173e8bbf
JS
271}
272
961c54c3
RD
273void wxTipWindowView::OnPaint(wxPaintEvent& WXUNUSED(event))
274{
275 wxPaintDC dc(this);
8962e1d9 276
961c54c3
RD
277 wxRect rect;
278 wxSize size = GetClientSize();
279 rect.width = size.x;
280 rect.height = size.y;
281
282 // first filll the background
283 dc.SetBrush(wxBrush(GetBackgroundColour(), wxSOLID));
284 dc.SetPen( wxPen(GetForegroundColour(), 1, wxSOLID) );
285 dc.DrawRectangle(rect);
286
287 // and then draw the text line by line
288 dc.SetTextBackground(GetBackgroundColour());
289 dc.SetTextForeground(GetForegroundColour());
290 dc.SetFont(GetFont());
291
292 wxPoint pt;
293 pt.x = TEXT_MARGIN_X;
294 pt.y = TEXT_MARGIN_Y;
295 size_t count = m_parent->m_textLines.GetCount();
296 for ( size_t n = 0; n < count; n++ )
297 {
298 dc.DrawText(m_parent->m_textLines[n], pt);
299
300 pt.y += m_parent->m_heightLine;
301 }
302}
303
304void wxTipWindowView::OnMouseClick(wxMouseEvent& WXUNUSED(event))
8962e1d9 305{
961c54c3 306 m_parent->Close();
8962e1d9
RD
307}
308
961c54c3
RD
309#if !wxUSE_POPUPWIN
310void wxTipWindowView::OnKillFocus(wxFocusEvent& WXUNUSED(event))
311{
312 // Workaround the kill focus event happening just after creation in wxGTK
313 if (wxGetLocalTime() > m_creationTime + 1)
314 m_parent->Close();
315}
316#endif
8962e1d9 317
961c54c3 318#endif