⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smoothtooltiptracker.mm

📁 lumaqq
💻 MM
字号:
/*
 * LumaQQ - Cross platform QQ client, special edition for Mac
 *
 * Copyright (C) 2007 luma <stubma@163.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#import "SmoothTooltipTracker.h"
#import "SmoothTooltipTrackerDelegate.h"
#import "Constants.h"

#define TOOL_TIP_CHECK_INTERVAL			45.0	//Check for mouse X times a second
#define DEFAULT_TOOL_TIP_DELAY			35.0	//Number of check intervals of no movement before a tip is displayed

@implementation SmoothTooltipTracker

+ (SmoothTooltipTracker *)smoothTooltipTrackerForView:(NSView *)inView withDelegate:(id)inDelegate {
	return [[[self alloc] initForView:inView withDelegate:inDelegate] autorelease];
}

- (SmoothTooltipTracker *)initForView:(NSView *)inView withDelegate:(id)inDelegate {
	if ((self = [super init])) {
		view = [inView retain];
		delegate = inDelegate;
		tooltipTrackingTag = -1;
		tooltipLocation = NSZeroPoint;
		m_tooltipDelay = DEFAULT_TOOL_TIP_DELAY;

		//Reset cursor tracking when the view's frame changes
		[[NSNotificationCenter defaultCenter] addObserver:self
												 selector:@selector(resetCursorTracking)
													 name:NSViewFrameDidChangeNotification
												   object:view];
		[[NSNotificationCenter defaultCenter] addObserver:self
												 selector:@selector(resetCursorTracking)
													 name:kMainToolbarToggledVisibilityNotificationName
												   object:[view window]];

		[self installCursorRect];
	}
	
	return self;
}

- (void)dealloc {
	[[NSNotificationCenter defaultCenter] removeObserver:self];

	[self removeCursorRect];
	[self _stopTrackingMouse];

	[view release]; 
	view = nil;
	
	[super dealloc];
}

- (void)setDelegate:(id)inDelegate {
	if (delegate != inDelegate) {
		[self _stopTrackingMouse];
		
		delegate = inDelegate;
	}
}

- (void)viewWillBeRemovedFromWindow {
	[[NSNotificationCenter defaultCenter] removeObserver:self
													name:kMainToolbarToggledVisibilityNotificationName
												  object:[view window]];
	
	[self removeCursorRect];
	[self _stopTrackingMouse];
}

- (void)viewWasAddedToWindow {
	[[NSNotificationCenter defaultCenter] addObserver:self
											 selector:@selector(resetCursorTracking)
												 name:kMainToolbarToggledVisibilityNotificationName
											   object:[view window]];
	
	[self installCursorRect];
}

- (void)installCursorRect {
	if (tooltipTrackingTag == -1) {
		NSRect	 		trackingRect;
		BOOL			mouseInside;
		
		//Add a new tracking rect
		trackingRect = [view frame];
		trackingRect.origin = NSMakePoint(0,0);
		
		mouseInside = NSPointInRect([view convertPoint:[[view window] convertScreenToBase:[NSEvent mouseLocation]] fromView:[[view window] contentView]],
									trackingRect);
		tooltipTrackingTag = [view addTrackingRect:trackingRect owner:self userData:nil assumeInside:mouseInside];
		
		//If the mouse is already inside, begin tracking the mouse immediately
		if (mouseInside) 
			[self _startTrackingMouse];
	}
}

- (void)removeCursorRect {
	if (tooltipTrackingTag != -1) {
		[view removeTrackingRect:tooltipTrackingTag];
		tooltipTrackingTag = -1;
		[self _stopTrackingMouse];		
	}
}

- (void)resetCursorTracking {
	[self removeCursorRect];
	[self installCursorRect];
}

- (void)mouseEntered:(NSEvent *)theEvent {
	[self _startTrackingMouse];
}

- (void)mouseExited:(NSEvent *)theEvent {
	[self _stopTrackingMouse];
}

- (void)_startTrackingMouse {
	if (!tooltipMouseLocationTimer) {
		tooltipCount = 0;
		tooltipMouseLocationTimer = [[NSTimer scheduledTimerWithTimeInterval:(1.0 / TOOL_TIP_CHECK_INTERVAL)
																	  target:self
																	selector:@selector(mouseMovementTimer:)
																	userInfo:nil
																	 repeats:YES] retain];
	}
}

- (void)_stopTrackingMouse {
	//Invalidate tracking
	if (tooltipMouseLocationTimer) {
		//Hide the tooltip before releasing the timer, as the timer may be the last object retaining self
		//and we want to communicate with the delegate before a potential call to dealloc.
		[self _hideTooltip];
		
		NSTimer* theTimer = tooltipMouseLocationTimer;
		tooltipMouseLocationTimer = nil;
		
		[theTimer invalidate];
		[theTimer release]; 
		theTimer = nil;
	}
}

- (void)_hideTooltip {
	tooltipCount = 0;

	//If the tooltip was being shown before, hide it
	if (!NSEqualPoints(tooltipLocation,NSZeroPoint)) {
		lastMouseLocation = NSZeroPoint;
		tooltipLocation = NSZeroPoint;
		
		//Hide tooltip
		[delegate hideTooltip];
	}
}

- (void)mouseMovementTimer:(NSTimer *)inTimer {
	NSPoint		mouseLocation = [NSEvent mouseLocation];
	NSWindow	*theWindow = [view window];
	
	if ([theWindow isVisible] && 
	   NSPointInRect([theWindow convertScreenToBase:mouseLocation],[[theWindow contentView] convertRect:[view frame] fromView:[view superview]])) {
		//tooltipCount is used for delaying the appearence of tooltips.  We reset it to 0 when the mouse moves.  When
		//the mouse is left still tooltipCount will eventually grow greater than TOOL_TIP_DELAY, and we will begin
		//displaying the tooltips
		if (tooltipCount > m_tooltipDelay) {
			if (!NSEqualPoints(tooltipLocation, mouseLocation)) {
				[delegate showTooltipAtPoint:mouseLocation];
				tooltipLocation = mouseLocation;
			}			
		} else {
			if (!NSEqualPoints(mouseLocation,lastMouseLocation)) {
				lastMouseLocation = mouseLocation;
				tooltipCount = 0; //reset tooltipCount to 0 since the mouse has moved
			} else {
				tooltipCount++;
			}
		}
	} else {
		//If the cursor has left our frame or the window is no logner visible, manually hide the tooltip.
		//This protects us in the cases where we do not receive a mouse exited message; we don't stop tracking
		//because we could reenter the tracking area without receiving a mouseEntered: message.
		[self _hideTooltip];
	}
}

- (void)setTooltipDelay:(float)tooltipDelay {
	m_tooltipDelay = tooltipDelay;
}

@end

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -