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