///////////////////////////////////////////////////////////////////////////// // Name: tooltip.cpp // Purpose: wxToolTip implementation // Author: Robert Roebling // Id: $Id$ // Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifdef __GNUG__ #pragma implementation "tooltip.h" #endif #include "wx/defs.h" #if wxUSE_TOOLTIPS #include "wx/app.h" #include "wx/dc.h" #include "wx/window.h" #include "wx/tooltip.h" #include "wx/timer.h" #include "wx/geometry.h" #include "wx/mac/uma.h" //----------------------------------------------------------------------------- // global data //----------------------------------------------------------------------------- class wxMacToolTipTimer ; class wxMacToolTip { public : wxMacToolTip( ) ; ~wxMacToolTip() ; void Setup( WindowRef window , wxString text , wxPoint localPosition ) ; long GetMark() { return m_mark ; } void Draw() ; void Clear() ; bool IsShown() { return m_shown ; } private : wxString m_label ; wxPoint m_position ; Rect m_rect ; WindowRef m_window ; PicHandle m_backpict ; bool m_shown ; long m_mark ; wxMacToolTipTimer* m_timer ; } ; class wxMacToolTipTimer : public wxTimer { public: wxMacToolTipTimer() {} ; wxMacToolTipTimer(wxMacToolTip* tip, int iMilliseconds) ; virtual ~wxMacToolTipTimer() {} ; void Notify() { if ( m_mark == m_tip->GetMark() ) m_tip->Draw() ; } protected: wxMacToolTip* m_tip; long m_mark ; }; //----------------------------------------------------------------------------- // wxToolTip //----------------------------------------------------------------------------- static long s_ToolTipDelay = 500 ; static bool s_ShowToolTips = true ; static wxMacToolTip s_ToolTip ; static wxWindow* s_LastWindowEntered = NULL ; static wxRect2DInt s_ToolTipArea ; static WindowRef s_ToolTipWindowRef = NULL ; IMPLEMENT_ABSTRACT_CLASS(wxToolTip, wxObject) wxToolTip::wxToolTip( const wxString &tip ) { m_text = tip; m_window = (wxWindow*) NULL; } wxToolTip::~wxToolTip() { } void wxToolTip::SetTip( const wxString &tip ) { m_text = tip; if ( m_window ) { /* // update it immediately wxToolInfo ti(GetHwndOf(m_window)); ti.lpszText = (wxChar *)m_text.c_str(); (void)SendTooltipMessage(GetToolTipCtrl(), TTM_UPDATETIPTEXT, 0, &ti); */ } } void wxToolTip::SetWindow( wxWindow *win ) { m_window = win ; } void wxToolTip::Enable( bool flag ) { if ( s_ShowToolTips != flag ) { s_ShowToolTips = flag ; if ( s_ShowToolTips ) { } else { s_ToolTip.Clear() ; } } } void wxToolTip::SetDelay( long msecs ) { s_ToolTipDelay = msecs ; } void wxToolTip::RelayEvent( wxWindow *win , wxMouseEvent &event ) { if ( s_ShowToolTips ) { if ( event.GetEventType() == wxEVT_LEAVE_WINDOW ) { s_ToolTip.Clear() ; } else if (event.GetEventType() == wxEVT_ENTER_WINDOW || event.GetEventType() == wxEVT_MOTION ) { wxPoint2DInt where( event.m_x , event.m_y ) ; if ( s_LastWindowEntered == win && s_ToolTipArea.Contains( where ) ) { } else { s_ToolTip.Clear() ; s_ToolTipArea = wxRect2DInt( event.m_x - 2 , event.m_y - 2 , 4 , 4 ) ; s_LastWindowEntered = win ; WindowRef window = MAC_WXHWND( win->MacGetRootWindow() ) ; int x = event.m_x ; int y = event.m_y ; wxPoint local( x , y ) ; win->MacClientToRootWindow( &x, &y ) ; wxPoint windowlocal( x , y ) ; s_ToolTip.Setup( window , win->MacGetToolTipString( local ) , windowlocal ) ; } } } } void wxToolTip::RemoveToolTips() { s_ToolTip.Clear() ; } // --- mac specific wxMacToolTipTimer::wxMacToolTipTimer( wxMacToolTip *tip , int msec ) { m_tip = tip; m_mark = tip->GetMark() ; Start(msec, true); } wxMacToolTip::wxMacToolTip() { m_window = NULL ; m_backpict = NULL ; m_mark = 0 ; m_shown = false ; m_timer = NULL ; } void wxMacToolTip::Setup( WindowRef win , wxString text , wxPoint localPosition ) { m_mark++ ; Clear() ; m_position = localPosition ; m_label = wxMacMakeMacStringFromPC( text ) ; m_window =win; s_ToolTipWindowRef = m_window ; m_backpict = NULL ; if ( m_timer ) delete m_timer ; m_timer = new wxMacToolTipTimer( this , s_ToolTipDelay ) ; } wxMacToolTip::~wxMacToolTip() { if ( m_timer ) { delete m_timer ; m_timer = NULL; } if ( m_backpict ) Clear() ; } const short kTipBorder = 2 ; const short kTipOffset = 5 ; void wxMacToolTip::Draw() { if ( m_label.Length() == 0 ) return ; if ( m_window == s_ToolTipWindowRef ) { #if TARGET_CARBON /* if ( HMDisplayTag != (void*) kUnresolvedCFragSymbolAddress ) { HMDisplayTag( } else */ #endif { wxMacPortStateHelper help( (GrafPtr) GetWindowPort( m_window ) ); #if TARGET_CARBON bool useDrawThemeText = ( DrawThemeTextBox != (void*) kUnresolvedCFragSymbolAddress ) ; #endif m_shown = true ; FontFamilyID fontId ; Str255 fontName ; SInt16 fontSize ; Style fontStyle ; GetThemeFont(kThemeSmallSystemFont , GetApplicationScript() , fontName , &fontSize , &fontStyle ) ; GetFNum( fontName, &fontId ); TextFont( fontId ) ; TextSize( fontSize ) ; TextFace( fontStyle ) ; FontInfo fontInfo; ::GetFontInfo(&fontInfo); short lineh = fontInfo.ascent + fontInfo.descent + fontInfo.leading; short height = 0 ; // short width = TextWidth( m_label , 0 ,m_label.Length() ) ; int i = 0 ; int length = m_label.Length() ; int width = 0 ; int thiswidth = 0 ; int laststop = 0 ; const char *text = m_label ; while( i < length ) { if( text[i] == 13 || text[i] == 10) { thiswidth = ::TextWidth( text , laststop , i - laststop ) ; if ( thiswidth > width ) width = thiswidth ; height += lineh ; laststop = i+1 ; } i++ ; } if ( i - laststop > 0 ) { thiswidth = ::TextWidth( text , laststop , i - laststop ) ; if ( thiswidth > width ) width = thiswidth ; height += lineh ; } m_rect.left = m_position.x + kTipOffset; m_rect.top = m_position.y + kTipOffset; m_rect.right = m_rect.left + width + 2 * kTipBorder; #if TARGET_CARBON if ( useDrawThemeText ) m_rect.right += kTipBorder ; #endif m_rect.bottom = m_rect.top + height + 2 * kTipBorder; ClipRect( &m_rect ) ; BackColor( whiteColor ) ; ForeColor(blackColor ) ; GWorldPtr port ; NewGWorld( &port , wxDisplayDepth() , &m_rect , NULL , NULL , 0 ) ; CGrafPtr origPort ; GDHandle origDevice ; GetGWorld( &origPort , &origDevice ) ; SetGWorld( port , NULL ) ; m_backpict = OpenPicture(&m_rect); CopyBits(GetPortBitMapForCopyBits(GetWindowPort(m_window)), GetPortBitMapForCopyBits(port), &m_rect, &m_rect, srcCopy, NULL); ClosePicture(); SetGWorld( origPort , origDevice ) ; DisposeGWorld( port ) ; PenNormal() ; RGBColor tooltipbackground = { 0xFFFF , 0xFFFF , 0xC000 } ; BackColor( whiteColor ) ; RGBForeColor( &tooltipbackground ) ; PaintRect( &m_rect ) ; ForeColor(blackColor ) ; FrameRect( &m_rect ) ; SetThemeTextColor(kThemeTextColorNotification,wxDisplayDepth(),true) ; ::MoveTo( m_rect.left + kTipBorder , m_rect.top + fontInfo.ascent + kTipBorder); i = 0 ; laststop = 0 ; height = 0 ; while( i < length ) { if( text[i] == 13 || text[i] == 10) { #if TARGET_CARBON if ( useDrawThemeText ) { Rect frame ; frame.top = m_rect.top + kTipBorder + height ; frame.left = m_rect.left + kTipBorder ; frame.bottom = frame.top + 1000 ; frame.right = frame.left + 1000 ; CFStringRef mString = CFStringCreateWithBytes( NULL , (UInt8*) text + laststop , i - laststop , CFStringGetSystemEncoding(), false ) ; ::DrawThemeTextBox( mString, kThemeCurrentPortFont, kThemeStateActive, true, &frame, teJustLeft, nil ); CFRelease( mString ) ; height += lineh ; } else #endif { ::DrawText( text , laststop , i - laststop ) ; height += lineh ; ::MoveTo( m_rect.left + kTipBorder , m_rect.top + fontInfo.ascent + kTipBorder + height ); } laststop = i+1 ; } i++ ; } #if TARGET_CARBON if ( useDrawThemeText ) { Rect frame ; frame.top = m_rect.top + kTipBorder + height ; frame.left = m_rect.left + kTipBorder ; frame.bottom = frame.top + 1000 ; frame.right = frame.left + 1000 ; CFStringRef mString = CFStringCreateWithCString( NULL , text + laststop , kCFStringEncodingMacRoman ) ; ::DrawThemeTextBox( mString, kThemeCurrentPortFont, kThemeStateActive, true, &frame, teJustLeft, nil ); CFRelease( mString ) ; } else #endif { ::DrawText( text , laststop , i - laststop ) ; } ::TextMode( srcOr ) ; } } } void wxToolTip::NotifyWindowDelete( WXHWND win ) { if ( win == s_ToolTipWindowRef ) { s_ToolTipWindowRef = NULL ; } } void wxMacToolTip::Clear() { m_mark++ ; if ( m_timer ) { delete m_timer ; m_timer = NULL ; } if ( !m_shown ) return ; if ( m_window == s_ToolTipWindowRef && m_backpict ) { wxMacPortStateHelper help( (GrafPtr) GetWindowPort(m_window) ) ; m_shown = false ; BackColor( whiteColor ) ; ForeColor(blackColor ) ; DrawPicture(m_backpict, &m_rect); KillPicture(m_backpict); m_backpict = NULL ; } } #endif