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