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