Files
cappuccino/AppKit/_CPToolTip.j
T
Alexander Ljungberg 23cc507b12 Refs #1264. Make tooltip delay a constant and reduce it to 1.0 second to match Cocoa a little more closely.
Perhaps we should implement something like [[CPToolTipManager sharedToolTipManager] setInitialToolTipDelay:X] for completeness.
2011-05-15 19:01:26 -04:00

297 lines
7.9 KiB
Plaintext

/*
* _CPToolTip.j
* AppKit
*
* Created by Antoine Mercadal
* Copyright 2011 <primalmotion@archipelproject.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPTextField.j"
@import "CPView.j"
@import "CPWindow.j"
_CPToolTipWindowMask = 1 << 27;
var _CPToolTipHeight = 24.0,
_CPToolTipFontSize = 11.0,
_CPCurrentToolTip,
_CPCurrentToolTipTimer,
_CPToolTipDelay = 1.0;
/*! @ingroup appkit
This is a basic tooltip that behaves mostly like Cocoa ones.
*/
@implementation _CPToolTip : CPWindow
{
CPTextField _content;
}
#pragma mark -
#pragma mark Class Methods
/*! Returns an initialized _CPToolTip with the given text and attach it to given view.
@param aString the content of the tooltip
*/
+ (_CPToolTip)toolTipWithString:(CPString)aString
{
var tooltip = [[_CPToolTip alloc] initWithString:aString styleMask:_CPToolTipWindowMask];
[tooltip showToolTip];
return tooltip;
}
/*!
Compute a cool size for the given string.
@param aToolTipSize a frame with the maximum width desired for the tooltip
@param aText the wanted text
@return CPArray containing the computer toolTipSize and textFrameSize
*/
+ (CPSize)computeCorrectSize:(CPSize)aToolTipSize text:(CPString)aText
{
var font = [CPFont systemFontOfSize:_CPToolTipFontSize],
textFrameSizeSingleLine = [aText sizeWithFont:font],
textFrameSize = [aText sizeWithFont:font inWidth:(aToolTipSize.width)];
// If the text fully fits within the maximum width, shrink to fit.
if (textFrameSizeSingleLine.width < aToolTipSize.width)
{
var textField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()],
inset = [textField currentValueForThemeAttribute:@"content-inset"] || CGInsetMakeZero();
textFrameSize = textFrameSizeSingleLine;
textFrameSize.width += inset.left + inset.right;
aToolTipSize.width = textFrameSize.width;
}
if (textFrameSize.height < 100)
{
aToolTipSize.height = textFrameSize.height + 4;
return [aToolTipSize, textFrameSize];
}
var newWidth = aToolTipSize.width + ((parseInt(textFrameSize.height - 100) / _CPToolTipHeight) * _CPToolTipHeight);
textFrameSize = [aText sizeWithFont:font inWidth:newWidth - 4];
aToolTipSize.width = newWidth + 2;
aToolTipSize.height = textFrameSize.height + 4;
return [aToolTipSize, textFrameSize];
}
/*!
Override default windowView class loader.
@param aStyleMask the window mask
@return the windowView class
*/
+ (Class)_windowViewClassForStyleMask:(unsigned)aStyleMask
{
return _CPToolTipWindowView;
}
#pragma mark -
#pragma mark Initialization
/*!
Returns an initialized _CPToolTip with string.
@param aString the content of the tooltip
@param aStyleMask the tooltip's style mask
*/
- (id)initWithString:(CPString)aString styleMask:(unsigned)aStyleMask
{
var toolTipFrame = CPRectMake(0.0, 0.0, 250.0, _CPToolTipHeight),
layout = [_CPToolTip computeCorrectSize:toolTipFrame.size text:aString],
textFrameSize = layout[1];
toolTipFrame.size = layout[0];
if (self = [super initWithContentRect:toolTipFrame styleMask:aStyleMask])
{
textFrameSize.height += 4;
_content = [CPTextField labelWithTitle:aString];
[_content setFont:[CPFont systemFontOfSize:_CPToolTipFontSize]]
[_content setLineBreakMode:CPLineBreakByCharWrapping];
[_content setAlignment:CPJustifiedTextAlignment];
[_content setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[_content setFrameOrigin:CPPointMake(0.0, 0.0)];
[_content setFrameSize:textFrameSize];
[_content setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_content setTextColor:[CPColor blackColor]];
[[self contentView] addSubview:_content];
[self setLevel:CPStatusWindowLevel];
[self setAlphaValue:0.9];
[_windowView setNeedsDisplay:YES];
}
return self;
}
#pragma mark -
#pragma mark Controls
/*!
Show the tooltip after computing the position.
*/
- (void)showToolTip
{
var mousePosition = [[CPApp currentEvent] globalLocation],
nativeRect = [[[CPApp mainWindow] platformWindow] nativeContentRect];
mousePosition.y += 20;
if (mousePosition.x < 0)
mousePosition.x = 5;
if (mousePosition.x + CPRectGetWidth([self frame]) > nativeRect.size.width)
mousePosition.x = nativeRect.size.width - CPRectGetWidth([self frame]) - 5;
if (mousePosition.y < 0)
mousePosition.y = 5;
if (mousePosition.y + CPRectGetHeight([self frame]) > nativeRect.size.height)
mousePosition.y = nativeRect.size.height - CPRectGetHeight([self frame]) - 5;
[self setFrameOrigin:mousePosition];
[self orderFront:nil];
}
@end
/*! @ingroup appkit
Add tooltip support to CPView.
*/
@implementation CPView (toolTips)
/*!
Sets the tooltip for the receiver.
@param aToolTip the tooltip
*/
- (void)setToolTip:(CPString)aToolTip
{
if (_toolTip == aToolTip)
return;
_toolTip = aToolTip;
if (!_DOMElement)
return;
var fIn = function(e)
{
[self _fireToolTip];
},
fOut = function(e)
{
[self _invalidateToolTip];
};
if (_toolTip)
{
if (_DOMElement.addEventListener)
{
_DOMElement.addEventListener("mouseover", fIn, NO);
_DOMElement.addEventListener("keypress", fOut, NO);
_DOMElement.addEventListener("mouseout", fOut, NO);
}
else if (_DOMElement.attachEvent)
{
_DOMElement.attachEvent("onmouseover", fIn);
_DOMElement.attachEvent("onkeypress", fOut);
_DOMElement.attachEvent("onmouseout", fOut);
}
}
else
{
if (_DOMElement.removeEventListener)
{
_DOMElement.removeEventListener("mouseover", fIn, NO);
_DOMElement.removeEventListener("keypress", fOut, NO);
_DOMElement.removeEventListener("mouseout", fOut, NO);
}
else if (_DOMElement.detachEvent)
{
_DOMElement.detachEvent("onmouseover", fIn);
_DOMElement.detachEvent("onkeypress", fOut);
_DOMElement.detachEvent("onmouseout", fOut);
}
}
}
/*!
Returns the receiver's tooltip.
*/
- (CPString)toolTip
{
return _toolTip;
}
/*! @ignore
Starts the tooltip timer.
*/
- (void)_fireToolTip
{
if (_CPCurrentToolTipTimer)
{
[_CPCurrentToolTipTimer invalidate];
if (_CPCurrentToolTip)
[_CPCurrentToolTip close:nil];
_CPCurrentToolTip = nil;
}
if (_toolTip)
_CPCurrentToolTipTimer = [CPTimer scheduledTimerWithTimeInterval:_CPToolTipDelay target:self selector:@selector(_showToolTip:) userInfo:nil repeats:NO];
}
/*! @ignore
Stop the tooltip timer if any
*/
- (void)_invalidateToolTip
{
if (_CPCurrentToolTipTimer)
{
[_CPCurrentToolTipTimer invalidate];
_CPCurrentToolTipTimer = nil;
}
if (_CPCurrentToolTip)
{
[_CPCurrentToolTip close];
_CPCurrentToolTip = nil;
}
}
/*! @ignore
Actually shows the tooltip if any
*/
- (void)_showToolTip:(CPTimer)aTimer
{
if (_CPCurrentToolTip)
[_CPCurrentToolTip close:nil];
_CPCurrentToolTip = [_CPToolTip toolTipWithString:_toolTip];
}
@end