]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/tooltip.cpp
fixed crash introduced in v1.41
[wxWidgets.git] / src / mac / carbon / tooltip.cpp
CommitLineData
ee6b1d97
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: tooltip.cpp
3// Purpose: wxToolTip implementation
92e6d869 4// Author: Stefan Csomor
ee6b1d97 5// Id: $Id$
92e6d869 6// Copyright: (c) Stefan Csomor
65571936 7// Licence: wxWindows licence
ee6b1d97
SC
8/////////////////////////////////////////////////////////////////////////////
9
3d1a4878 10#include "wx/wxprec.h"
ee6b1d97
SC
11
12#if wxUSE_TOOLTIPS
13
03e11df5 14#include "wx/app.h"
5fde6fcc 15#include "wx/dc.h"
ee6b1d97
SC
16#include "wx/window.h"
17#include "wx/tooltip.h"
03e11df5 18#include "wx/timer.h"
ee6b1d97 19#include "wx/geometry.h"
ee6b1d97
SC
20#include "wx/mac/uma.h"
21
22//-----------------------------------------------------------------------------
23// global data
24//-----------------------------------------------------------------------------
25
76a5e5d2
SC
26class wxMacToolTipTimer ;
27
ee6b1d97
SC
28class wxMacToolTip
29{
991f71dc
DS
30public :
31 wxMacToolTip() ;
32 ~wxMacToolTip() ;
33
34 void Setup( WindowRef window , const wxString& text , const wxPoint& localPosition ) ;
35 void Draw() ;
36 void Clear() ;
37
38 long GetMark()
39 { return m_mark ; }
40
41 bool IsShown()
42 { return m_shown ; }
43
44private :
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
427ff662 54#if TARGET_CARBON
991f71dc 55 wxMacCFStringHolder m_helpTextRef ;
6ef7c8e0 56#endif
ee6b1d97
SC
57} ;
58
853e3ce9 59class wxMacToolTipTimer : public wxTimer
ee6b1d97
SC
60{
61public:
853e3ce9 62 wxMacToolTipTimer(wxMacToolTip* tip, int iMilliseconds) ;
991f71dc 63 wxMacToolTipTimer() {} ;
12cd5f34 64 virtual ~wxMacToolTipTimer() {} ;
991f71dc 65
853e3ce9
GD
66 void Notify()
67 {
68 if ( m_mark == m_tip->GetMark() )
69 m_tip->Draw() ;
70 }
991f71dc 71
ee6b1d97 72protected:
e40298d5
JS
73 wxMacToolTip* m_tip;
74 long m_mark ;
ee6b1d97
SC
75};
76
77//-----------------------------------------------------------------------------
78// wxToolTip
79//-----------------------------------------------------------------------------
80static long s_ToolTipDelay = 500 ;
81static bool s_ShowToolTips = true ;
82static wxMacToolTip s_ToolTip ;
83static wxWindow* s_LastWindowEntered = NULL ;
84static wxRect2DInt s_ToolTipArea ;
85static WindowRef s_ToolTipWindowRef = NULL ;
f5ebf253
SC
86
87IMPLEMENT_ABSTRACT_CLASS(wxToolTip, wxObject)
88
991f71dc 89
ee6b1d97
SC
90wxToolTip::wxToolTip( const wxString &tip )
91{
92 m_text = tip;
93 m_window = (wxWindow*) NULL;
94}
95
96wxToolTip::~wxToolTip()
97{
98}
99
100void wxToolTip::SetTip( const wxString &tip )
101{
e40298d5
JS
102 m_text = tip;
103
ee6b1d97
SC
104 if ( m_window )
105 {
991f71dc 106#if 0
e40298d5
JS
107 // update it immediately
108 wxToolInfo ti(GetHwndOf(m_window));
109 ti.lpszText = (wxChar *)m_text.c_str();
110
111 (void)SendTooltipMessage(GetToolTipCtrl(), TTM_UPDATETIPTEXT, 0, &ti);
991f71dc 112#endif
ee6b1d97
SC
113 }
114}
115
116void wxToolTip::SetWindow( wxWindow *win )
117{
7eb67c00 118 m_window = win ;
ee6b1d97
SC
119}
120
121void wxToolTip::Enable( bool flag )
122{
e40298d5
JS
123 if ( s_ShowToolTips != flag )
124 {
125 s_ShowToolTips = flag ;
991f71dc 126
e40298d5
JS
127 if ( s_ShowToolTips )
128 {
129 }
130 else
131 {
132 s_ToolTip.Clear() ;
133 }
134 }
ee6b1d97
SC
135}
136
137void wxToolTip::SetDelay( long msecs )
138{
e40298d5 139 s_ToolTipDelay = msecs ;
ee6b1d97
SC
140}
141
142void wxToolTip::RelayEvent( wxWindow *win , wxMouseEvent &event )
143{
e40298d5
JS
144 if ( s_ShowToolTips )
145 {
146 if ( event.GetEventType() == wxEVT_LEAVE_WINDOW )
147 {
148 s_ToolTip.Clear() ;
149 }
150 else if (event.GetEventType() == wxEVT_ENTER_WINDOW || event.GetEventType() == wxEVT_MOTION )
151 {
152 wxPoint2DInt where( event.m_x , event.m_y ) ;
153 if ( s_LastWindowEntered == win && s_ToolTipArea.Contains( where ) )
154 {
155 }
156 else
157 {
158 s_ToolTip.Clear() ;
159 s_ToolTipArea = wxRect2DInt( event.m_x - 2 , event.m_y - 2 , 4 , 4 ) ;
160 s_LastWindowEntered = win ;
161
facd6764 162 WindowRef window = MAC_WXHWND( win->MacGetTopLevelWindowRef() ) ;
e40298d5
JS
163 int x = event.m_x ;
164 int y = event.m_y ;
165 wxPoint local( x , y ) ;
166 win->MacClientToRootWindow( &x, &y ) ;
167 wxPoint windowlocal( x , y ) ;
168 s_ToolTip.Setup( window , win->MacGetToolTipString( local ) , windowlocal ) ;
169 }
170 }
171 }
ee6b1d97
SC
172}
173
174void wxToolTip::RemoveToolTips()
175{
e40298d5 176 s_ToolTip.Clear() ;
ee6b1d97 177}
991f71dc 178
ee6b1d97
SC
179// --- mac specific
180
181wxMacToolTipTimer::wxMacToolTipTimer( wxMacToolTip *tip , int msec )
182{
e40298d5
JS
183 m_tip = tip;
184 m_mark = tip->GetMark() ;
185 Start(msec, true);
ee6b1d97
SC
186}
187
188wxMacToolTip::wxMacToolTip()
189{
e40298d5
JS
190 m_window = NULL ;
191 m_backpict = NULL ;
991f71dc 192 m_timer = NULL ;
e40298d5
JS
193 m_mark = 0 ;
194 m_shown = false ;
ee6b1d97
SC
195}
196
fbfb8bcc 197void wxMacToolTip::Setup( WindowRef win , const wxString& text , const wxPoint& localPosition )
ee6b1d97 198{
e40298d5 199 m_mark++ ;
991f71dc 200
e40298d5
JS
201 Clear() ;
202 m_position = localPosition ;
427ff662 203 m_label = text ;
7eb67c00 204 m_window =win;
e40298d5
JS
205 s_ToolTipWindowRef = m_window ;
206 m_backpict = NULL ;
991f71dc 207
e40298d5
JS
208 if ( m_timer )
209 delete m_timer ;
991f71dc 210
e40298d5 211 m_timer = new wxMacToolTipTimer( this , s_ToolTipDelay ) ;
ee6b1d97
SC
212}
213
214wxMacToolTip::~wxMacToolTip()
215{
991f71dc
DS
216 if ( m_timer )
217 {
76a5e5d2 218 delete m_timer ;
f5bb2251
GD
219 m_timer = NULL;
220 }
991f71dc 221
f5bb2251
GD
222 if ( m_backpict )
223 Clear() ;
ee6b1d97
SC
224}
225
226const short kTipBorder = 2 ;
227const short kTipOffset = 5 ;
228
229void wxMacToolTip::Draw()
230{
e40298d5
JS
231 if ( m_label.Length() == 0 )
232 return ;
233
234 if ( m_window == s_ToolTipWindowRef )
235 {
236 m_shown = true ;
991f71dc 237
a7b04cfc 238#if TARGET_CARBON
427ff662
SC
239 HMHelpContentRec tag ;
240 tag.version = kMacHelpVersion;
241 SetRect( &tag.absHotRect , m_position.x - 2 , m_position.y - 2 , m_position.x + 2 , m_position.y + 2 ) ;
a9de2608
SC
242
243 QDLocalToGlobalRect( GetWindowPort( m_window ) , &tag.absHotRect ) ;
244
991f71dc 245 m_helpTextRef.Assign( m_label , wxFONTENCODING_DEFAULT ) ;
427ff662
SC
246 tag.content[kHMMinimumContentIndex].contentType = kHMCFStringContent ;
247 tag.content[kHMMinimumContentIndex].u.tagCFString = m_helpTextRef ;
248 tag.content[kHMMaximumContentIndex].contentType = kHMCFStringContent ;
249 tag.content[kHMMaximumContentIndex].u.tagCFString = m_helpTextRef ;
250 tag.tagSide = kHMDefaultSide;
251 HMDisplayTag( &tag );
252#else
991f71dc 253 wxMacPortStateHelper help( (GrafPtr)GetWindowPort( m_window ) );
427ff662
SC
254 FontFamilyID fontId ;
255 Str255 fontName ;
256 SInt16 fontSize ;
257 Style fontStyle ;
991f71dc 258 GetThemeFont( kThemeSmallSystemFont , GetApplicationScript() , fontName , &fontSize , &fontStyle ) ;
427ff662 259 GetFNum( fontName, &fontId );
991f71dc 260
427ff662
SC
261 TextFont( fontId ) ;
262 TextSize( fontSize ) ;
263 TextFace( fontStyle ) ;
264 FontInfo fontInfo;
265 ::GetFontInfo(&fontInfo);
266 short lineh = fontInfo.ascent + fontInfo.descent + fontInfo.leading;
267 short height = 0 ;
991f71dc 268
427ff662
SC
269 int i = 0 ;
270 int length = m_label.Length() ;
271 int width = 0 ;
272 int thiswidth = 0 ;
273 int laststop = 0 ;
991f71dc 274 wxCharBuffer text = m_label.mb_str( wxConvLocal ) ;
427ff662 275
991f71dc 276 while ( i < length )
e40298d5 277 {
991f71dc 278 if ( text[i] == 13 || text[i] == 10)
e40298d5
JS
279 {
280 thiswidth = ::TextWidth( text , laststop , i - laststop ) ;
281 if ( thiswidth > width )
282 width = thiswidth ;
991f71dc 283
e40298d5 284 height += lineh ;
991f71dc 285 laststop = i + 1 ;
e40298d5 286 }
991f71dc 287
427ff662
SC
288 i++ ;
289 }
991f71dc 290
427ff662
SC
291 if ( i - laststop > 0 )
292 {
293 thiswidth = ::TextWidth( text , laststop , i - laststop ) ;
294 if ( thiswidth > width )
295 width = thiswidth ;
296 height += lineh ;
297 }
991f71dc 298
427ff662
SC
299 m_rect.left = m_position.x + kTipOffset;
300 m_rect.top = m_position.y + kTipOffset;
301 m_rect.right = m_rect.left + width + 2 * kTipBorder;
302
303 m_rect.bottom = m_rect.top + height + 2 * kTipBorder;
304 Rect r ;
991f71dc 305
427ff662
SC
306 GetPortBounds( GetWindowPort( m_window ) , &r ) ;
307 if ( m_rect.top < 0 )
308 {
309 m_rect.bottom += -m_rect.top ;
310 m_rect.top = 0 ;
311 }
312 if ( m_rect.left < 0 )
313 {
314 m_rect.right += -m_rect.left ;
315 m_rect.left = 0 ;
316 }
317 if ( m_rect.right > r.right )
318 {
319 m_rect.left -= (m_rect.right - r.right ) ;
320 m_rect.right = r.right ;
321 }
322 if ( m_rect.bottom > r.bottom )
323 {
324 m_rect.top -= (m_rect.bottom - r.bottom) ;
325 m_rect.bottom = r.bottom ;
326 }
991f71dc
DS
327
328 GWorldPtr port ;
329 CGrafPtr origPort ;
330 GDHandle origDevice ;
331
427ff662
SC
332 ClipRect( &m_rect ) ;
333 BackColor( whiteColor ) ;
334 ForeColor(blackColor ) ;
427ff662 335 NewGWorld( &port , wxDisplayDepth() , &m_rect , NULL , NULL , 0 ) ;
991f71dc 336
427ff662
SC
337 GetGWorld( &origPort , &origDevice ) ;
338 SetGWorld( port , NULL ) ;
991f71dc 339
427ff662 340 m_backpict = OpenPicture(&m_rect);
991f71dc 341
427ff662
SC
342 CopyBits(GetPortBitMapForCopyBits(GetWindowPort(m_window)),
343 GetPortBitMapForCopyBits(port),
344 &m_rect,
345 &m_rect,
346 srcCopy,
347 NULL);
348 ClosePicture();
349 SetGWorld( origPort , origDevice ) ;
350 DisposeGWorld( port ) ;
351 PenNormal() ;
991f71dc 352
427ff662
SC
353 RGBColor tooltipbackground = { 0xFFFF , 0xFFFF , 0xC000 } ;
354 BackColor( whiteColor ) ;
355 RGBForeColor( &tooltipbackground ) ;
991f71dc 356
427ff662
SC
357 PaintRect( &m_rect ) ;
358 ForeColor(blackColor ) ;
359 FrameRect( &m_rect ) ;
360 SetThemeTextColor(kThemeTextColorNotification,wxDisplayDepth(),true) ;
361 ::MoveTo( m_rect.left + kTipBorder , m_rect.top + fontInfo.ascent + kTipBorder);
362
363 i = 0 ;
364 laststop = 0 ;
365 height = 0 ;
366
991f71dc 367 while ( i < length )
427ff662 368 {
991f71dc 369 if ( text[i] == 13 || text[i] == 10)
e40298d5
JS
370 {
371 ::DrawText( text , laststop , i - laststop ) ;
427ff662
SC
372 height += lineh ;
373 ::MoveTo( m_rect.left + kTipBorder , m_rect.top + fontInfo.ascent + kTipBorder + height );
374 laststop = i+1 ;
e40298d5 375 }
991f71dc 376
427ff662
SC
377 i++ ;
378 }
991f71dc 379
427ff662
SC
380 ::DrawText( text , laststop , i - laststop ) ;
381 ::TextMode( srcOr ) ;
382#endif
e40298d5 383 }
ee6b1d97
SC
384}
385
76a5e5d2 386void wxToolTip::NotifyWindowDelete( WXHWND win )
ee6b1d97 387{
e40298d5 388 if ( win == s_ToolTipWindowRef )
e40298d5 389 s_ToolTipWindowRef = NULL ;
ee6b1d97
SC
390}
391
392void wxMacToolTip::Clear()
393{
e40298d5 394 m_mark++ ;
991f71dc 395
e40298d5
JS
396 if ( m_timer )
397 {
398 delete m_timer ;
399 m_timer = NULL ;
400 }
991f71dc 401
e40298d5
JS
402 if ( !m_shown )
403 return ;
991f71dc 404
a19f009b 405#if TARGET_CARBON
e40298d5 406 HMHideTag() ;
427ff662 407 m_helpTextRef.Release() ;
e40298d5
JS
408#else
409 if ( m_window == s_ToolTipWindowRef && m_backpict )
410 {
991f71dc 411 wxMacPortStateHelper help( (GrafPtr)GetWindowPort( m_window ) ) ;
76a5e5d2 412
e40298d5 413 m_shown = false ;
ee6b1d97 414
e40298d5 415 BackColor( whiteColor ) ;
991f71dc
DS
416 ForeColor( blackColor ) ;
417 DrawPicture( m_backpict, &m_rect );
418 KillPicture( m_backpict );
e40298d5
JS
419 m_backpict = NULL ;
420 }
a19f009b 421#endif
ee6b1d97
SC
422}
423
424#endif
425