]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/tooltip.cpp
fix a crash when dismissing the popup window because of a key press
[wxWidgets.git] / src / mac / carbon / tooltip.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: tooltip.cpp
3 // Purpose: wxToolTip implementation
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "tooltip.h"
12 #endif
13
14 #include "wx/setup.h"
15
16 #if wxUSE_TOOLTIPS
17
18 #include "wx/app.h"
19 #include "wx/dc.h"
20 #include "wx/window.h"
21 #include "wx/tooltip.h"
22 #include "wx/timer.h"
23 #include "wx/geometry.h"
24 #include "wx/mac/uma.h"
25
26 //-----------------------------------------------------------------------------
27 // global data
28 //-----------------------------------------------------------------------------
29
30 class wxMacToolTipTimer ;
31
32 class wxMacToolTip
33 {
34 public :
35 wxMacToolTip( ) ;
36 ~wxMacToolTip() ;
37
38 void Setup( WindowRef window , wxString text , wxPoint localPosition ) ;
39 long GetMark() { return m_mark ; }
40 void Draw() ;
41 void Clear() ;
42 bool IsShown() { return m_shown ; }
43 private :
44
45 wxString m_label ;
46 wxPoint m_position ;
47 Rect m_rect ;
48 WindowRef m_window ;
49 PicHandle m_backpict ;
50 bool m_shown ;
51 long m_mark ;
52 wxMacToolTipTimer* m_timer ;
53 } ;
54
55 class wxMacToolTipTimer : wxTimer
56 {
57 public:
58 wxMacToolTipTimer() {} ;
59 wxMacToolTipTimer(wxMacToolTip* tip, int iMilliseconds) ;
60 virtual ~wxMacToolTipTimer() {} ;
61 void Notify()
62 {
63 if ( m_mark == m_tip->GetMark() )
64 m_tip->Draw() ;
65
66 }
67 protected:
68 wxMacToolTip* m_tip;
69 long m_mark ;
70 };
71
72 //-----------------------------------------------------------------------------
73 // wxToolTip
74 //-----------------------------------------------------------------------------
75 static long s_ToolTipDelay = 500 ;
76 static bool s_ShowToolTips = true ;
77 static wxMacToolTip s_ToolTip ;
78 static wxWindow* s_LastWindowEntered = NULL ;
79 static wxRect2DInt s_ToolTipArea ;
80 static WindowRef s_ToolTipWindowRef = NULL ;
81 wxToolTip::wxToolTip( const wxString &tip )
82 {
83 m_text = tip;
84 m_window = (wxWindow*) NULL;
85 }
86
87 wxToolTip::~wxToolTip()
88 {
89 }
90
91 void wxToolTip::SetTip( const wxString &tip )
92 {
93 m_text = tip;
94
95 if ( m_window )
96 {
97 /*
98 // update it immediately
99 wxToolInfo ti(GetHwndOf(m_window));
100 ti.lpszText = (wxChar *)m_text.c_str();
101
102 (void)SendTooltipMessage(GetToolTipCtrl(), TTM_UPDATETIPTEXT, 0, &ti);
103 */
104 }
105 }
106
107 void wxToolTip::SetWindow( wxWindow *win )
108 {
109 m_window = win;
110 }
111
112 void wxToolTip::Enable( bool flag )
113 {
114 if ( s_ShowToolTips != flag )
115 {
116 s_ShowToolTips = flag ;
117 if ( s_ShowToolTips )
118 {
119 }
120 else
121 {
122 s_ToolTip.Clear() ;
123 }
124 }
125 }
126
127 void wxToolTip::SetDelay( long msecs )
128 {
129 s_ToolTipDelay = msecs ;
130 }
131
132 void wxToolTip::RelayEvent( wxWindow *win , wxMouseEvent &event )
133 {
134 if ( s_ShowToolTips )
135 {
136 if ( event.GetEventType() == wxEVT_LEAVE_WINDOW )
137 {
138 s_ToolTip.Clear() ;
139 }
140 else if (event.GetEventType() == wxEVT_ENTER_WINDOW || event.GetEventType() == wxEVT_MOTION )
141 {
142 wxPoint2DInt where( event.m_x , event.m_y ) ;
143 if ( s_LastWindowEntered == win && s_ToolTipArea.Contains( where ) )
144 {
145 }
146 else
147 {
148 s_ToolTip.Clear() ;
149 s_ToolTipArea = wxRect2DInt( event.m_x - 2 , event.m_y - 2 , 4 , 4 ) ;
150 s_LastWindowEntered = win ;
151
152 WindowRef window = MAC_WXHWND( win->MacGetRootWindow() ) ;
153 int x = event.m_x ;
154 int y = event.m_y ;
155 wxPoint local( x , y ) ;
156 win->MacClientToRootWindow( &x, &y ) ;
157 wxPoint windowlocal( x , y ) ;
158 s_ToolTip.Setup( window , win->MacGetToolTipString( local ) , windowlocal ) ;
159 }
160 }
161 }
162 }
163
164 void wxToolTip::RemoveToolTips()
165 {
166 s_ToolTip.Clear() ;
167 }
168 // --- mac specific
169
170 wxMacToolTipTimer::wxMacToolTipTimer( wxMacToolTip *tip , int msec )
171 {
172 m_tip = tip;
173 m_mark = tip->GetMark() ;
174 Start(msec, true);
175 }
176
177 wxMacToolTip::wxMacToolTip()
178 {
179 m_window = NULL ;
180 m_backpict = NULL ;
181 m_mark = 0 ;
182 m_shown = false ;
183 m_timer = NULL ;
184 }
185
186 void wxMacToolTip::Setup( WindowRef window , wxString text , wxPoint localPosition )
187 {
188 m_mark++ ;
189 Clear() ;
190 m_position = localPosition ;
191 m_label = wxMacMakeMacStringFromPC( text ) ;
192 m_window = window ;
193 s_ToolTipWindowRef = window ;
194 m_backpict = NULL ;
195 if ( m_timer )
196 delete m_timer ;
197 m_timer = new wxMacToolTipTimer( this , s_ToolTipDelay ) ;
198 }
199
200 wxMacToolTip::~wxMacToolTip()
201 {
202 if ( m_timer )
203 delete m_timer ;
204 if ( m_backpict )
205 Clear() ;
206 }
207
208 const short kTipBorder = 2 ;
209 const short kTipOffset = 5 ;
210
211 void wxMacToolTip::Draw()
212 {
213 if ( m_label.Length() == 0 )
214 return ;
215
216 if ( m_window == s_ToolTipWindowRef )
217 {
218 #if TARGET_CARBON
219 /*
220 if ( HMDisplayTag != (void*) kUnresolvedCFragSymbolAddress )
221 {
222 HMDisplayTag(
223 }
224 else
225 */
226 #endif
227 {
228 wxMacPortStateHelper help( (GrafPtr) GetWindowPort( m_window ) );
229
230 m_shown = true ;
231
232 TextFont( kFontIDGeneva ) ;
233 TextSize( 10 ) ;
234 TextFace( 0 ) ;
235 FontInfo fontInfo;
236 ::GetFontInfo(&fontInfo);
237 short lineh = fontInfo.ascent + fontInfo.descent + fontInfo.leading;
238 short height = 0 ;
239 // short width = TextWidth( m_label , 0 ,m_label.Length() ) ;
240
241 int i = 0 ;
242 int length = m_label.Length() ;
243 int width = 0 ;
244 int thiswidth = 0 ;
245 int laststop = 0 ;
246 const char *text = m_label ;
247 while( i < length )
248 {
249 if( text[i] == 13 || text[i] == 10)
250 {
251 thiswidth = ::TextWidth( text , laststop , i - laststop ) ;
252 if ( thiswidth > width )
253 width = thiswidth ;
254
255 height += lineh ;
256 laststop = i+1 ;
257 }
258 i++ ;
259 }
260 if ( i - laststop > 0 )
261 {
262 thiswidth = ::TextWidth( text , laststop , i - laststop ) ;
263 if ( thiswidth > width )
264 width = thiswidth ;
265 height += lineh ;
266 }
267
268
269 m_rect.left = m_position.x + kTipOffset;
270 m_rect.top = m_position.y + kTipOffset;
271 m_rect.right = m_rect.left + width + 2 * kTipBorder;
272 m_rect.bottom = m_rect.top + height + 2 * kTipBorder;
273 ClipRect( &m_rect ) ;
274 BackColor( whiteColor ) ;
275 ForeColor(blackColor ) ;
276 m_backpict = OpenPicture(&m_rect);
277
278 CopyBits(GetPortBitMapForCopyBits(GetWindowPort(m_window)),
279 GetPortBitMapForCopyBits(GetWindowPort(m_window)),
280 &m_rect,
281 &m_rect,
282 srcCopy,
283 NULL);
284
285 ClosePicture();
286 PenNormal() ;
287 SetThemeBackground(kThemeBrushNotificationWindowBackground,32,true) ;
288 SetThemeTextColor(kThemeTextColorNotification,32,true) ;
289 EraseRect( &m_rect ) ;
290 FrameRect( &m_rect ) ;
291 ::MoveTo( m_rect.left + kTipBorder , m_rect.top + fontInfo.ascent + kTipBorder);
292
293 i = 0 ;
294 laststop = 0 ;
295 height = 0 ;
296 while( i < length )
297 {
298 if( text[i] == 13 || text[i] == 10)
299 {
300 ::DrawText( text , laststop , i - laststop ) ;
301 height += lineh ;
302 ::MoveTo( m_rect.left + kTipBorder , m_rect.top + fontInfo.ascent + kTipBorder + height );
303 laststop = i+1 ;
304 }
305 i++ ;
306 }
307
308 ::DrawText( text , laststop , i - laststop ) ;
309 ::TextMode( srcOr ) ;
310 // DrawText( m_label , 0 , m_label.Length() ) ;
311 }
312 }
313 }
314
315 void wxToolTip::NotifyWindowDelete( WXHWND win )
316 {
317 if ( win == s_ToolTipWindowRef )
318 {
319 s_ToolTipWindowRef = NULL ;
320 }
321 }
322
323 void wxMacToolTip::Clear()
324 {
325 m_mark++ ;
326 if ( m_timer )
327 {
328 delete m_timer ;
329 m_timer = NULL ;
330 }
331 if ( !m_shown )
332 return ;
333
334 if ( m_window == s_ToolTipWindowRef && m_backpict )
335 {
336 wxMacPortStateHelper help( (GrafPtr) GetWindowPort(m_window) ) ;
337
338 m_shown = false ;
339
340 BackColor( whiteColor ) ;
341 ForeColor(blackColor ) ;
342 DrawPicture(m_backpict, &m_rect);
343 KillPicture(m_backpict);
344 m_backpict = NULL ;
345 }
346 }
347
348 #endif
349