Support for tooltips on CPControls

This commit is contained in:
Antoine Mercadal committed 2011-04-26 14:46:30 +02:00
1 parent 1b3792a1cc
commit 3ddf6031fb
17 files changed
+1221 -10

No files matched your search

+1
View File
@@ -87,6 +87,7 @@
@import "CPTokenField.j"
@import "CPToolbar.j"
@import "CPToolbarItem.j"
@import "CPToolTip.j"
@import "CPTreeNode.j"
@import "CPView.j"
@import "CPViewAnimation.j"
+394
View File
@@ -0,0 +1,394 @@
/*
* CPAttachedWindow.j
* AppKit
*
* Created by Antoine Mercadal
* Copyright 2009, Antoine Mercadal
*
* 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 "CPButton.j"
@import "CPColor.j"
@import "CPImage.j"
@import "CPImageView.j"
@import "CPView.j"
@import "CPWindow.j"
CPClosableOnBlurWindowMask = 1 << 4;
CPAttachedWhiteWindowMask = 1 << 25;
CPAttachedBlackWindowMask = 1 << 26;
/*! @ingroup appkit
This is a simple attached window like the one that pops up
when you double click on a meeting in iCal
*/
@implementation CPAttachedWindow : CPWindow
{
id _targetView @accessors(property=targetView);
BOOL _isClosed;
BOOL _closeOnBlur;
CPButton _closeButton;
}
/*! override default windowView class loader
@param aStyleMask the window mask
@return the windowView class
*/
+ (Class)_windowViewClassForStyleMask:(unsigned)aStyleMask
{
if (aStyleMask & CPAttachedWhiteWindowMask)
return _CPAttachedWindowViewWhite;
return _CPAttachedWindowViewBlack;
}
#pragma mark -
#pragma mark Initialization
/*! create and init a CPAttachedWindow with given size of and view
@param aSize the size of the attached window
@param aView the target view
@return ready to use CPAttachedWindow
*/
+ (id)attachedWindowWithSize:(CGSize)aSize forView:(CPView)aView
{
return [CPAttachedWindow attachedWindowWithSize:aSize forView:aView styleMask:nil];
}
/*! create and init a CPAttachedWindow with given size of and view
@param aSize the size of the attached window
@param aView the target view
@return ready to use CPAttachedWindow
@param styleMask the window style mask (combine CPClosableWindowMask, CPAttachedWhiteWindowMask, CPAttachedBlackWindowMask and CPClosableOnBlurWindowMask)
*/
+ (id)attachedWindowWithSize:(CGSize)aSize forView:(CPView)aView styleMask:(int)aMask
{
var attachedWindow = [[CPAttachedWindow alloc] initWithContentRect:CPRectMake(0.0, 0.0, aSize.width, aSize.height) styleMask:aMask];
[attachedWindow attachToView:aView];
return attachedWindow;
}
/*! create and init a CPAttachedWindow with given frame
@param aFrame the frame of the attached window
@return ready to use CPAttachedWindow
*/
- (id)initWithContentRect:(CGRect)aFrame
{
self = [self initWithContentRect:aFrame styleMask:CPAttachedWhiteWindowMask]
return self;
}
/*! create and init a CPAttachedWindow with given frame
@param aFrame the frame of the attached window
@param styleMask the window style mask (combine CPClosableWindowMask, CPAttachedWhiteWindowMask, CPAttachedBlackWindowMask and CPClosableOnBlurWindowMask)
@return ready to use CPAttachedWindow
*/
- (id)initWithContentRect:(CGRect)aFrame styleMask:(unsigned)aStyleMask
{
if (self = [super initWithContentRect:aFrame styleMask:aStyleMask])
{
_isClosed = NO;
var bundle = [CPBundle bundleForClass:[self class]],
buttonClose = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPAttachedWindow/attached-window-button-close.png"] size:CPSizeMake(15.0, 15.0)],
buttonClosePressed = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPAttachedWindow/attached-window-button-close-highlighted.png"] size:CPSizeMake(15.0, 15.0)];
if (aStyleMask & CPClosableWindowMask)
{
_closeButton = [[CPButton alloc] initWithFrame:CPRectMake(8.0, 1.0, 14.0, 14.0)];
[_closeButton setImageScaling:CPScaleProportionally];
[_closeButton setBordered:NO];
[_closeButton setImage:buttonClose]; // this avoid the blinking..
[_closeButton setValue:buttonClose forThemeAttribute:@"image"];
[_closeButton setValue:buttonClosePressed forThemeAttribute:@"image" inState:CPThemeStateHighlighted];
[_closeButton setTarget:self];
[_closeButton setAction:@selector(close:)];
[[self contentView] addSubview:_closeButton];
}
_closeOnBlur = (aStyleMask & CPClosableOnBlurWindowMask);
[self setLevel:CPStatusWindowLevel];
[self setMovableByWindowBackground:YES];
[self setHasShadow:NO];
[_windowView setNeedsDisplay:YES];
}
return self;
}
#pragma mark -
#pragma mark Window actions
/*! called when the window is loowing focus and close the window
if CPClosableOnBlurWindowMask is setted
*/
- (void)resignMainWindow
{
if (_closeOnBlur && !_isClosed)
{
// set a close flag to avoid infinite loop
_isClosed = YES;
[self close];
if (_delegate && [_delegate respondsToSelector:@selector(didAttachedWindowClose:)])
[_delegate didAttachedWindowClose:self];
}
}
#pragma mark -
#pragma mark Utilities
- (CPPoint)computeOrigin:(CPView)aView gravity:(int)gravity
{
var frameView = [aView frame],
currentView = aView,
origin = [aView frameOrigin],
nativeRect = [[[CPApp mainWindow] platformWindow] nativeContentRect],
lastView;
// if somebody succeed to use the conversion function of CPView
// to get this working, please do.
while (currentView = [currentView superview])
{
origin.x += [currentView frameOrigin].x;
origin.y += [currentView frameOrigin].y;
lastView = currentView;
}
origin.x += [[lastView window] frame].origin.x;
origin.y += [[lastView window] frame].origin.y;
// take care of the scrolling point
if ([aView enclosingScrollView])
{
var offsetPoint = [[[aView enclosingScrollView] contentView] boundsOrigin];
origin.x -= offsetPoint.x;
origin.y -= offsetPoint.y;
}
var originLeft = CPPointCreateCopy(origin),
originRight = CPPointCreateCopy(origin),
originTop = CPPointCreateCopy(origin),
originBottom = CPPointCreateCopy(origin);
// CPAttachedWindowGravityRight
originRight.x += CPRectGetWidth(frameView);
originRight.y += (CPRectGetHeight(frameView) / 2.0) - (CPRectGetHeight([self frame]) / 2.0)
// CPAttachedWindowGravityLeft
originLeft.x -= CPRectGetWidth([self frame]);
originLeft.y += (CPRectGetHeight(frameView) / 2.0) - (CPRectGetHeight([self frame]) / 2.0)
// CPAttachedWindowGravityBottom
originBottom.x += CPRectGetWidth(frameView) / 2.0 - CPRectGetWidth([self frame]) / 2.0;
originBottom.y += CPRectGetHeight(frameView);
// CPAttachedWindowGravityTop
originTop.x += CPRectGetWidth(frameView) / 2.0 - CPRectGetWidth([self frame]) / 2.0;
originTop.y -= CPRectGetHeight([self frame]);
if (gravity === CPAttachedWindowGravityAuto)
{
var frameCopy = CPRectCreateCopy([self frame]);
nativeRect.origin.x = 0.0;
nativeRect.origin.y = 0.0;
var tests = [originRight, originLeft, originTop, originBottom];
gravity = CPAttachedWindowGravityRight;
for (var i = 0; i < tests.length; i++)
{
frameCopy.origin = tests[i];
if (CPRectContainsRect(nativeRect, frameCopy))
{
if (CPPointEqualToPoint(tests[i], originRight))
{
gravity = CPAttachedWindowGravityRight
break;
}
else if (CPPointEqualToPoint(tests[i], originLeft))
{
gravity = CPAttachedWindowGravityLeft
break;
}
else if (CPPointEqualToPoint(tests[i], originTop))
{
gravity = CPAttachedWindowGravityUp
break;
}
else if (CPPointEqualToPoint(tests[i], originBottom))
{
gravity = CPAttachedWindowGravityDown
break;
}
}
}
}
var originToBeReturned;
switch (gravity)
{
case CPAttachedWindowGravityRight:
originToBeReturned = originRight;
break;
case CPAttachedWindowGravityLeft:
originToBeReturned = originLeft;
break;
case CPAttachedWindowGravityDown:
originToBeReturned = originBottom;
break;
case CPAttachedWindowGravityUp:
originToBeReturned = originTop;
break;
}
[_windowView setGravity:gravity];
var o = originToBeReturned;
if (o.x < 0)
{
[_windowView setGravity:nil];
o.x = 0;
}
if (o.x + CPRectGetWidth([self frame]) > nativeRect.size.width)
{
[_windowView setGravity:nil];
o.x = nativeRect.size.width - CPRectGetWidth([self frame]);
}
if (o.y < 0)
{
[_windowView setGravity:nil];
o.y = 0;
}
if (o.y + CPRectGetHeight([self frame]) > nativeRect.size.height)
{
[_windowView setGravity:nil];
o.y = nativeRect.size.height - CPRectGetHeight([self frame]);
}
return originToBeReturned;
}
#pragma mark -
#pragma mark Notification handlers
- (void)_attachedWindowDidMove:(CPNotification)aNotification
{
if ([_windowView isMouseDownPressed])
{
[_windowView hideCursor];
[self setLevel:CPNormalWindowLevel];
[_closeButton setFrameOrigin:CPPointMake(1.0, 1.0)];
[[CPNotificationCenter defaultCenter] removeObserver:self name:CPWindowDidMoveNotification object:self];
}
}
#pragma mark -
#pragma mark Utilities
/*! compute the frame needed to be placed to the given view
and position the attached window according to this view (gravity will be CPAttachedWindowGravityAuto)
@param aView the view where CPAttachedWindow must be attached
*/
- (void)positionRelativeToView:(CPView)aView
{
[self positionRelativeToView:aView gravity:CPAttachedWindowGravityAuto];
}
/*! compute the frame needed to be placed to the given view
and position the attached window according to this view
@param aView the view where CPAttachedWindow must be attached
@param aGravity the gravity to use
*/
- (void)positionRelativeToView:(CPView)aView gravity:(int)aGravity
{
var frameView = [aView frame],
posX = frameView.origin.x + CPRectGetWidth(frameView),
posY = frameView.origin.y + (CPRectGetHeight(frameView) / 2.0) - (CPRectGetHeight([self frame]) / 2.0),
point = [self computeOrigin:aView gravity:aGravity];
point.y = MAX(point.y, 0);
[self setFrameOrigin:point];
[_windowView showCursor];
[self setLevel:CPStatusWindowLevel];
[_closeButton setFrameOrigin:CPPointMake(1.0, 1.0)];
[_windowView setNeedsDisplay:YES];
[self makeKeyAndOrderFront:nil];
}
/*! set the _targetView and attach the CPAttachedWindow to it
@param aView the view where CPAttachedWindow must be attached
*/
- (void)attachToView:(CPView)aView
{
_targetView = aView;
[self positionRelativeToView:_targetView];
[_targetView addObserver:self forKeyPath:@"window.frame" options:nil context:nil];
}
#pragma mark -
#pragma mark Actions
/*! closes the CPAttachedWindow
@param sender the sender of the action
*/
- (IBAction)close:(id)aSender
{
[self close];
[_targetView removeObserver:self forKeyPath:@"window.frame"];
if (_delegate && [_delegate respondsToSelector:@selector(didAttachedWindowClose:)])
[_delegate didAttachedWindowClose:self];
}
/*! order front the window as usual and add listener for CPWindowDidMoveNotification
@param sender the sender of the action
*/
- (IBAction)makeKeyAndOrderFront:(is)aSender
{
[super makeKeyAndOrderFront:aSender];
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_attachedWindowDidMove:) name:CPWindowDidMoveNotification object:self];
}
/*! update the CPAttachedWindow frame if a resize event is observed
*/
- (void)observeValueForKeyPath:(CPString)aPath ofObject:(id)anObject change:(CPDictionary)theChange context:(void)aContext
{
if ([aPath isEqual:@"window.frame"])
{
[self positionRelativeToView:_targetView];
}
}
@end
+92 -10
View File
@@ -25,7 +25,6 @@
@import "CPView.j"
@import "CPKeyValueBinding.j"
CPLeftTextAlignment = 0;
CPRightTextAlignment = 1;
CPCenterTextAlignment = 2;
@@ -72,7 +71,9 @@ CPControlTextDidBeginEditingNotification = "CPControlTextDidBeginEditingNotif
CPControlTextDidChangeNotification = "CPControlTextDidChangeNotification";
CPControlTextDidEndEditingNotification = "CPControlTextDidEndEditingNotification";
var CPControlBlackColor = [CPColor blackColor];
var CPControlBlackColor = [CPColor blackColor],
CPCurrentToolTip,
CPCurrentToolTipTimer;
/*!
@ingroup appkit
@@ -244,28 +245,109 @@ var CPControlBlackColor = [CPColor blackColor];
@param aToolTip the tooltip
*/
/*
-(void)setToolTip:(CPString)aToolTip
- (void)setToolTip:(CPString)aToolTip
{
if (_toolTip == aToolTip)
return;
_toolTip = aToolTip;
#if PLATFORM(DOM)
_DOMElement.title = aToolTip;
#endif
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
- (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:2.0 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:nil];
CPCurrentToolTip = nil;
}
}
/*! @ignore
Actually shows the tooltip if any
*/
- (void)_showToolTip:(CPTimer)aTimer
{
if (CPCurrentToolTip)
[CPCurrentToolTip close:nil];
CPCurrentToolTip = [CPToolTip toolTipWithString:_toolTip forView:self];
}
/*!
Returns whether the control can continuously send its action messages.
+117
View File
@@ -0,0 +1,117 @@
/*
* CPStepper.j
* AppKit
*
* Created by Antoine Mercadal
* Copyright 2009, Antoine Mercadal
*
* 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 "CPAttachedWindow.j"
CPToolTipDefaultColorMask = CPAttachedBlackWindowMask;
/*! @ingroup appkit
subclass of CPAttachedWindow in order to build quick tooltip
*/
@implementation CPToolTip : CPAttachedWindow
{
CPTextField _content;
}
#pragma mark -
#pragma mark Class Methods
/*! returns an initialized CPToolTip with string and attach it to given view
@param aString the content of the tooltip
@param aView the view where the tooltip will be attached
*/
+ (CPToolTip)toolTipWithString:(CPString)aString forView:(CPView)aView
{
var tooltip = [[CPToolTip alloc] initWithString:aString styleMask:CPToolTipDefaultColorMask];
[tooltip setAlphaValue:0.9];
[tooltip attachToView:aView];
[tooltip resignMainWindow];
return tooltip;
}
/*! compute a cool size for the given string
@param aToolTipSize the original wanted tool tip size
@param aText the wanted text
@return CPArray containing the computer toolTipSize and textFrameSize
*/
+ (CPSize)computeCorrectSize:(CPSize)aToolTipSize text:(CPString)aText
{
var font = [CPFont systemFontOfSize:12.0],
textFrameSize = [aText sizeWithFont:font inWidth:(aToolTipSize.width - 10)];
if (textFrameSize.height < 100)
{
aToolTipSize.height = textFrameSize.height + 10;
return [aToolTipSize, textFrameSize];
}
var newWidth = aToolTipSize.width + ((parseInt(textFrameSize.height - 100) / 30) * 30);
textFrameSize = [aText sizeWithFont:font inWidth:newWidth - 10];
aToolTipSize.width = newWidth + 5;
aToolTipSize.height = textFrameSize.height + 10;
return [aToolTipSize, textFrameSize];
}
#pragma mark -
#pragma mark Initialization
/*! returns an initialized CPToolTip with string
@param aString the content of the tooltip
*/
- (id)initWithString:(CPString)aString styleMask:(unsigned)aStyleMask
{
var toolTipFrame = CPRectMake(0.0, 0.0, 250.0, 30.0),
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 setLineBreakMode:CPLineBreakByCharWrapping];
[_content setAlignment:CPJustifiedTextAlignment];
[_content setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[_content setFrameOrigin:CPPointMake(5.0, 5.0)];
[_content setFrameSize:textFrameSize];
[_content setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_content setTextColor:(aStyleMask & CPAttachedWhiteWindowMask) ? [CPColor blackColor] : [CPColor whiteColor]];
[_content setValue:((aStyleMask & CPAttachedWhiteWindowMask) ? [CPColor whiteColor] : [CPColor blackColor]) forThemeAttribute:@"text-shadow-color"];
[[self contentView] addSubview:_content];
[self setMovableByWindowBackground:NO];
}
return self;
}
@end
+4
View File
@@ -849,6 +849,10 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
view = [[_CPToolbarItemView alloc] initWithToolbarItem:item toolbar:self];
_viewsForToolbarItems[[item UID]] = view;
if ([item toolTip] && [view respondsToSelector:@selector(setToolTip:)])
[view setToolTip:[item toolTip]];
[self addSubview:view];
_minWidth += [view minSize].width + TOOLBAR_ITEM_MARGIN;
+1
View File
@@ -2910,6 +2910,7 @@ CPCustomWindowShadowStyle = 3;
@import "_CPWindowView.j"
@import "_CPStandardWindowView.j"
@import "_CPDocModalWindowView.j"
@import "_CPAttachedWindowView.j"
@import "_CPHUDWindowView.j"
@import "_CPBorderlessWindowView.j"
@import "_CPBorderlessBridgeWindowView.j"
+241
View File
@@ -0,0 +1,241 @@
/*
* _CPAttachedWindowView.j
* AppKit
*
* Created by Antoine Mercadal
* Copyright 2011 <antoine.mercadal@inframonde.eu>
*
* 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 "_CPWindowView.j"
CPAttachedWindowGravityUp = 0;
CPAttachedWindowGravityDown = 1;
CPAttachedWindowGravityLeft = 2;
CPAttachedWindowGravityRight = 3;
CPAttachedWindowGravityAuto = 4;
/*! a custom CPWindowView that manage border and cursor
*/
@implementation _CPAttachedWindowView : _CPWindowView
{
BOOL _mouseDownPressed @accessors(getter=isMouseDownPressed, setter=setMouseDownPressed:);
unsigned _gravity @accessors(property=gravity);
BOOL _useGlowingEffect;
CPColor _backgroundTopColor;
CPColor _backgroundBottomColor;
CPColor _strokeColor;
CPImage _cursorBackgroundBottom;
CPImage _cursorBackgroundLeft;
CPImage _cursorBackgroundRight;
CPImage _cursorBackgroundTop;
CPSize _cursorSize;
}
/*! compute the contentView frame from a given window frame
@param aFrameRect the window frame
*/
+ (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
{
var contentRect = CGRectMakeCopy(aFrameRect);
// @todo change border art and remove this pixel perfect adaptation
// return CGRectInset(contentRect, 20, 20);
contentRect.origin.x += 18;
contentRect.origin.y += 17;
contentRect.size.width -= 35;
contentRect.size.height -= 37;
return contentRect;
}
/*! compute the window frame from a given contentView frame
@param aContentRect the contentView frame
*/
+ (CGRect)frameRectForContentRect:(CGRect)aContentRect
{
var frameRect = CGRectMakeCopy(aContentRect);
// @todo change border art and remove this pixel perfect adaptation
//return CGRectOffset(frameRect, 20, 20);
frameRect.origin.x -= 18;
frameRect.origin.y -= 17;
frameRect.size.width += 35;
frameRect.size.height += 37;
return frameRect;
}
- (id)initWithFrame:(CPRect)aFrame styleMask:(unsigned)aStyleMask
{
if (self = [super initWithFrame:aFrame styleMask:aStyleMask])
{
_cursorSize = CPSizeMake(15, 10);
}
return self;
}
- (void)hideCursor
{
_cursorSize = CPSizeMakeZero();
[self setNeedsDisplay:YES];
}
- (void)showCursor
{
_cursorSize = CPSizeMake(15, 10);
[self setNeedsDisplay:YES];
_mouseDownPressed = NO;
}
- (void)drawRect:(CGRect)aRect
{
[super drawRect:aRect];
var context = [[CPGraphicsContext currentContext] graphicsPort],
gradientColor = [[_backgroundTopColor redComponent], [_backgroundTopColor greenComponent], [_backgroundTopColor blueComponent],1.0, [_backgroundBottomColor redComponent], [_backgroundBottomColor greenComponent], [_backgroundBottomColor blueComponent],1.0],
gradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), gradientColor, [0,1], 2),
radius = 5,
arrowWidth = _cursorSize.width,
arrowHeight = _cursorSize.height,
strokeWidth = 2;
CGContextSetStrokeColor(context, _strokeColor);
CGContextSetLineWidth(context, strokeWidth);
CGContextBeginPath(context);
aRect.origin.x += strokeWidth;
aRect.origin.y += strokeWidth;
aRect.size.width -= strokeWidth * 2;
aRect.size.height -= strokeWidth * 2;
if (_useGlowingEffect)
{
var shadowColor = [[CPColor blackColor] colorWithAlphaComponent:.1],
shadowSize = CGSizeMake(0, 0),
shadowBlur = 5;
//compensate for the shadow blur
aRect.origin.x += shadowBlur;
aRect.origin.y += shadowBlur;
aRect.size.width -= shadowBlur * 2;
aRect.size.height -= shadowBlur * 2;
//set the shadow
CGContextSetShadow(context, CGSizeMake(0,0), 20);
CGContextSetShadowWithColor(context, shadowSize, shadowBlur, shadowColor);
}
//Remodulate size and origin
aRect.size.width -= 10;
aRect.origin.x += 5;
aRect.size.height -= 10;
aRect.origin.y += 5;
CGContextAddPath(context, CGPathWithRoundedRectangleInRect(aRect, radius, radius, YES, YES, YES, YES));
CGContextDrawLinearGradient(context, gradient, CGPointMake(CPRectGetMidX(aRect), 0.0), CGPointMake(CPRectGetMidX(aRect), aRect.size.height), 0);
CGContextClosePath(context);
//Start the arrow
switch (_gravity)
{
case CPAttachedWindowGravityLeft:
CGContextMoveToPoint(context, aRect.size.width + aRect.origin.x, (aRect.size.height / 2 - (arrowWidth / 2)) + aRect.origin.y);
CGContextAddLineToPoint(context, aRect.size.width + arrowHeight + aRect.origin.x, (aRect.size.height / 2) + aRect.origin.y);
CGContextAddLineToPoint(context, aRect.size.width + aRect.origin.x, (aRect.size.height / 2 + (arrowWidth / 2)) + aRect.origin.y);
break;
case CPAttachedWindowGravityRight:
CGContextMoveToPoint(context, aRect.origin.x, (aRect.size.height / 2 - (arrowWidth / 2)) + aRect.origin.y);
CGContextAddLineToPoint(context, aRect.origin.x - arrowHeight, (aRect.size.height / 2) + aRect.origin.y);
CGContextAddLineToPoint(context, aRect.origin.x, (aRect.size.height / 2 + (arrowWidth / 2) + aRect.origin.y));
break;
case CPAttachedWindowGravityDown:
CGContextMoveToPoint(context, (aRect.size.width / 2 - (arrowWidth / 2)) + aRect.origin.x, aRect.origin.y);
CGContextAddLineToPoint(context, (aRect.size.width / 2) + aRect.origin.x, aRect.origin.y - arrowHeight);
CGContextAddLineToPoint(context, (aRect.size.width / 2) + (arrowWidth / 2) + aRect.origin.x , aRect.origin.y);
break;
case CPAttachedWindowGravityUp:
CGContextMoveToPoint(context, (aRect.size.width / 2 - (arrowWidth / 2)) + aRect.origin.x, aRect.size.height + aRect.origin.y);
CGContextAddLineToPoint(context, (aRect.size.width / 2) + aRect.origin.x, aRect.size.height + aRect.origin.y + arrowHeight);
CGContextAddLineToPoint(context, (aRect.size.width / 2) + (arrowWidth / 2) + aRect.origin.x , aRect.size.height + aRect.origin.y);
break;
}
//Draw it
CGContextStrokePath(context);
CGContextFillPath(context);
}
- (void)mouseDown:(CPEvent)anEvent
{
_mouseDownPressed = YES;
[super mouseDown:anEvent];
}
- (void)mouseUp:(CPEvent)anEvent
{
_mouseDownPressed = NO;
[super mouseUp:anEvent];
}
@end
@implementation _CPAttachedWindowViewBlack : _CPAttachedWindowView
- (id)initWithFrame:(CPRect)aFrame styleMask:(unsigned)aStyleMask
{
if (self = [super initWithFrame:aFrame styleMask:aStyleMask])
{
_useGlowingEffect = YES;
_strokeColor = [CPColor colorWithHexString:@"131313"];
_backgroundTopColor = [CPColor colorWithHexString:@"363636"];
_backgroundBottomColor = [CPColor colorWithHexString:@"212121"];
_cursorSize = CPSizeMake(15, 10);
}
return self;
}
@end
@implementation _CPAttachedWindowViewWhite : _CPAttachedWindowView
- (id)initWithFrame:(CPRect)aFrame styleMask:(unsigned)aStyleMask
{
if (self = [super initWithFrame:aFrame styleMask:aStyleMask])
{
_useGlowingEffect = YES;
_strokeColor = [CPColor colorWithHexString:@"ADEDFF"];
_backgroundTopColor = [CPColor colorWithHexString:@"ffffff"];
_backgroundBottomColor = [CPColor colorWithHexString:@"ebebeb"];
_cursorSize = CPSizeMake(15, 10);
}
return self;
}
@end
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

+67
View File
@@ -0,0 +1,67 @@
/*
* AppController.j
* tooltips
*
* Created by You on April 26, 2011.
* Copyright 2011, Your Company All rights reserved.
*/
@import <Foundation/CPObject.j>
@import <AppKit/AppKit.j>
@implementation AppController : CPObject
{
CPArray _toolbarItems;
}
- (void)applicationDidFinishLaunching:(CPNotification)aNotification
{
var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask],
contentView = [theWindow contentView];
var b = [CPButton buttonWithTitle:@"Small tooltip"];
[b setFrameOrigin:CPPointMake(10.0, 30.0)];
[b setToolTip:@"Lorem ipsum dolor sit amet."];
[contentView addSubview:b];
var b = [CPButton buttonWithTitle:@"Medium tooltip"];
[b setFrameOrigin:CPPointMake(10.0, 80.0)];
[b setToolTip:@"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi."];
[contentView addSubview:b];
var b = [CPButton buttonWithTitle:@"Big tooltip"];
[b setFrameOrigin:CPPointMake(10.0, 130.0)];
[b setToolTip:@"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat. Duis semper. Duis arcu massa, scelerisque vitae, consequat in, pretium a, enim. Pellentesque congue. Ut in risus volutpat libero pharetra tempor. Cras vestibulum bibendum augue. Praesent egestas leo in pede. Praesent blandit odio eu enim. Pellentesque sed dui ut augue blandit sodales. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aliquam nibh. Mauris ac mauris sed pede pellentesque fermentum. Maecenas adipiscing ante non diam sodales hendrerit. Ut velit mauris, egestas sed, gravida nec, ornare ut, mi. Aenean ut orci vel massa suscipit pulvinar. Nulla sollicitudin. Fusce varius, ligula non tempus aliquam, nunc turpis ullamcorper nibh, in tempus sapien eros vitae ligula. Pellentesque rhoncus nunc et augue. Integer id felis. Curabitur aliquet pellentesque diam. Integer quis metus vitae elit lobortis egestas. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi vel erat non mauris convallis vehicula. Nulla et sapien. Integer tortor tellus, aliquam faucibus, convallis id, congue eu, quam. Mauris ullamcorper felis vitae erat. Proin feugiat, augue non elementum posuere, metus purus iaculis lectus, et tristique ligula justo vitae magna. Aliquam convallis sollicitudin purus. Praesent aliquam, enim at fermentum mollis, ligula massa adipiscing nisl, ac euismod nibh nisl eu lectus. Fusce vulputate sem at sapien. Vivamus leo. Aliquam euismod libero eu enim. Nulla nec felis sed leo placerat imperdiet. Aenean suscipit nulla in justo. Suspendisse cursus rutrum augue. Nulla tincidunt tincidunt mi. Curabitur iaculis, lorem vel rhoncus faucibus, felis magna fermentum augue, et ultricies lacus lorem varius purus. Curabitur eu amet."];
[contentView addSubview:b];
[theWindow orderFront:self];
// Uncomment the following line to turn on the standard menu bar.
[CPMenu setMenuBarVisible:YES];
var tbItem1 = [[CPToolbarItem alloc] initWithItemIdentifier:@"1"];
[tbItem1 setLabel:@"Mouse over me"];
[tbItem1 setImage:[[CPImage alloc] initWithContentsOfFile:[[CPBundle mainBundle] pathForResource:@"test.png"] size:CPSizeMake(35, 32)]];
[tbItem1 setToolTip:@"Hey guys, I'm a toolbar tooltip! Isn't it cool?"];
_toolbarItems = [tbItem1];
var tb = [[CPToolbar alloc] init];
[tb setDelegate:self];
[theWindow setToolbar:tb];
}
- (CPArray)toolbarDefaultItemIdentifiers:(CPToolbar)toolbar
{
return _toolbarItems;
}
- (CPArray)toolbarAllowedItemIdentifiers:(CPToolbar)toolbar
{
return _toolbarItems;
}
- (CPToolbarItem)toolbar:(CPToolbar)toolbar itemForItemIdentifier:(CPString)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
{
return _toolbarItems[0];
}
@end
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CPApplicationDelegateClass</key>
<string>AppController</string>
<key>CPBundleName</key>
<string>tooltips</string>
<key>CPPrincipalClass</key>
<string>CPApplication</string>
</dict>
</plist>
+93
View File
@@ -0,0 +1,93 @@
/*
* Jakefile
* tooltips
*
* Created by You on April 26, 2011.
* Copyright 2011, Your Company All rights reserved.
*/
var ENV = require("system").env,
FILE = require("file"),
JAKE = require("jake"),
task = JAKE.task,
FileList = JAKE.FileList,
app = require("cappuccino/jake").app,
configuration = ENV["CONFIG"] || ENV["CONFIGURATION"] || ENV["c"] || "Debug",
OS = require("os");
app ("tooltips", function(task)
{
task.setBuildIntermediatesPath(FILE.join("Build", "tooltips.build", configuration));
task.setBuildPath(FILE.join("Build", configuration));
task.setProductName("tooltips");
task.setIdentifier("com.yourcompany.tooltips");
task.setVersion("1.0");
task.setAuthor("Your Company");
task.setEmail("feedback @nospam@ yourcompany.com");
task.setSummary("tooltips");
task.setSources((new FileList("**/*.j")).exclude(FILE.join("Build", "**")));
task.setResources(new FileList("Resources/**"));
task.setIndexFilePath("index.html");
task.setInfoPlistPath("Info.plist");
if (configuration === "Debug")
task.setCompilerFlags("-DDEBUG -g");
else
task.setCompilerFlags("-O");
});
task ("default", ["tooltips"], function()
{
printResults(configuration);
});
task ("build", ["default"]);
task ("debug", function()
{
ENV["CONFIGURATION"] = "Debug";
JAKE.subjake(["."], "build", ENV);
});
task ("release", function()
{
ENV["CONFIGURATION"] = "Release";
JAKE.subjake(["."], "build", ENV);
});
task ("run", ["debug"], function()
{
OS.system(["open", FILE.join("Build", "Debug", "tooltips", "index.html")]);
});
task ("run-release", ["release"], function()
{
OS.system(["open", FILE.join("Build", "Release", "tooltips", "index.html")]);
});
task ("deploy", ["release"], function()
{
FILE.mkdirs(FILE.join("Build", "Deployment", "tooltips"));
OS.system(["press", "-f", FILE.join("Build", "Release", "tooltips"), FILE.join("Build", "Deployment", "tooltips")]);
printResults("Deployment")
});
task ("desktop", ["release"], function()
{
FILE.mkdirs(FILE.join("Build", "Desktop", "tooltips"));
require("cappuccino/nativehost").buildNativeHost(FILE.join("Build", "Release", "tooltips"), FILE.join("Build", "Desktop", "tooltips", "tooltips.app"));
printResults("Desktop")
});
task ("run-desktop", ["desktop"], function()
{
OS.system([FILE.join("Build", "Desktop", "tooltips", "tooltips.app", "Contents", "MacOS", "NativeHost"), "-i"]);
});
function printResults(configuration)
{
print("----------------------------");
print(configuration+" app built at path: "+FILE.join("Build", configuration, "tooltips"));
print("----------------------------");
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

+103
View File
@@ -0,0 +1,103 @@
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<!--
index-debug.html
tooltips
Created by You on April 26, 2011.
Copyright 2011, Your Company All rights reserved.
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7, chrome=1" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<link rel="apple-touch-icon" href="Resources/icon.png" />
<link rel="apple-touch-startup-image" href="Resources/default.png" />
<title>tooltips</title>
<script type="text/javascript">
OBJJ_MAIN_FILE = "main.j";
OBJJ_INCLUDE_PATHS = ["Frameworks/Debug", "Frameworks", "SomethingElse"];
</script>
<script src="Frameworks/Debug/Objective-J/Objective-J.js" type="text/javascript" charset="UTF-8"></script>
<script type="text/javascript">
objj_msgSend_reset();
// DEBUG OPTIONS:
// Uncomment to enable printing of backtraces on exceptions:
//objj_msgSend_decorate(objj_backtrace_decorator);
// Uncomment to supress exceptions that take place inside a message
//objj_msgSend_decorate(objj_supress_exceptions_decorator)
// Uncomment to enable runtime type checking:
//objj_msgSend_decorate(objj_typecheck_decorator);
// Uncomment (along with both above) to print backtraces on type check errors:
//objj_typecheck_prints_backtrace = true;
// Uncomment to disable the default logger (CPLogConsole if window.console exists, CPLogPopup otherwise):
//CPLogUnregister(CPLogDefault);
// Uncomment to enable a specific logger:
//CPLogRegister(CPLogConsole);
//CPLogRegister(CPLogPopup);
</script>
<style type="text/css">
body{margin:0; padding:0;}
#container {position: absolute; top:50%; left:50%;}
#content {width:800px; text-align:center; margin-left: -400px; height:50px; margin-top:-25px; line-height: 50px;}
#content {font-family: "Helvetica", "Arial", sans-serif; font-size: 18px; color: black; text-shadow: 0px 1px 0px white; }
#loadgraphic {margin-right: 0.2em; margin-bottom:-2px;}
</style>
<!--[if lt IE 7]>
<STYLE type="text/css">
#container { position: relative; top: 50%; }
#content { position: relative;}
</STYLE>
<![endif]-->
</head>
<body style="">
<div id="cappuccino-body">
<div id="loadingcontainer" style="background-color: #eeeeee; overflow:hidden; width:100%; height:100%; position: absolute; top: 0; left: 0;">
<script type="text/javascript">
document.write("<div id='container'><p id='content'>" +
"<img id='loadgraphic' width='16' height='16' src='Resources/spinner.gif' /> " +
"Loading tooltips...</p></div>");
</script>
<noscript>
<div id="container">
<div style="width: 440px; padding: 10px 25px 20px 25px; font-family: sans-serif; background-color: #ffffff; position: relative; left: -245px; top: -120px; text-align: center; -moz-border-radius: 20px; -webkit-border-radius: 20px; color: #555555">
<p style="line-height: 1.4em;">JavaScript is required for this site to work correctly but is either disabled or not supported by your browser.</p>
<p style="font-size:120%; padding:10px;"><a href="http://cappuccino.org/noscript">Show me how to enable JavaScript</a></p>
<p style="font-size:80%;">You may want to upgrade to a newer browser while you're at it:</p>
<ul style="margin:0;padding:0; text-align: center; font-size:80%;" >
<li style="display: inline;"><a href="http://www.apple.com/safari/download/">Safari</a></li>
<li style="display: inline;"><a href="http://www.mozilla.com/en-US/firefox/">Firefox</a></li>
<li style="display: inline;"><a href="http://www.google.com/chrome/">Chrome</a></li>
<li style="display: inline;"><a href="http://www.opera.com/download/">Opera</a></li>
<li style="display: inline;"><a href="http://www.microsoft.com/windows/downloads/ie/getitnow.mspx">Internet Explorer</a></li>
</ul>
</div>
</div>
</noscript>
</div>
</div>
</body>
</html>
+78
View File
@@ -0,0 +1,78 @@
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<!--
index.html
tooltips
Created by You on April 26, 2011.
Copyright 2011, Your Company All rights reserved.
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7, chrome=1" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<link rel="apple-touch-icon" href="Resources/icon.png" />
<link rel="apple-touch-startup-image" href="Resources/default.png" />
<title>tooltips</title>
<script type="text/javascript">
OBJJ_MAIN_FILE = "main.j";
</script>
<script type="text/javascript" src="Frameworks/Objective-J/Objective-J.js" charset="UTF-8"></script>
<style type="text/css">
body{margin:0; padding:0;}
#container {position: absolute; top:50%; left:50%;}
#content {width:800px; text-align:center; margin-left: -400px; height:50px; margin-top:-25px; line-height: 50px;}
#content {font-family: "Helvetica", "Arial", sans-serif; font-size: 18px; color: black; text-shadow: 0px 1px 0px white; }
#loadgraphic {margin-right: 0.2em; margin-bottom:-2px;}
</style>
<!--[if lt IE 7]>
<STYLE type="text/css">
#container { position: relative; top: 50%; }
#content { position: relative;}
</STYLE>
<![endif]-->
</head>
<body style="">
<div id="cappuccino-body">
<div id="loadingcontainer" style="background-color: #eeeeee; overflow:hidden; width:100%; height:100%; position: absolute; top: 0; left: 0;">
<script type="text/javascript">
document.write("<div id='container'><p id='content'>" +
"<img id='loadgraphic' width='16' height='16' src='Resources/spinner.gif' /> " +
"Loading tooltips...</p></div>");
</script>
<noscript>
<div id="container">
<div style="width: 440px; padding: 10px 25px 20px 25px; font-family: sans-serif; background-color: #ffffff; position: relative; left: -245px; top: -120px; text-align: center; -moz-border-radius: 20px; -webkit-border-radius: 20px; color: #555555">
<p style="line-height: 1.4em;">JavaScript is required for this site to work correctly but is either disabled or not supported by your browser.</p>
<p style="font-size:120%; padding:10px;"><a href="http://cappuccino.org/noscript">Show me how to enable JavaScript</a></p>
<p style="font-size:80%;">You may want to upgrade to a newer browser while you're at it:</p>
<ul style="margin:0;padding:0; text-align: center; font-size:80%;" >
<li style="display: inline;"><a href="http://www.apple.com/safari/download/">Safari</a></li>
<li style="display: inline;"><a href="http://www.mozilla.com/en-US/firefox/">Firefox</a></li>
<li style="display: inline;"><a href="http://www.google.com/chrome/">Chrome</a></li>
<li style="display: inline;"><a href="http://www.opera.com/download/">Opera</a></li>
<li style="display: inline;"><a href="http://www.microsoft.com/windows/downloads/ie/getitnow.mspx">Internet Explorer</a></li>
</ul>
</div>
</div>
</noscript>
</div>
</div>
</body>
</html>
+18
View File
@@ -0,0 +1,18 @@
/*
* AppController.j
* tooltips
*
* Created by You on April 26, 2011.
* Copyright 2011, Your Company All rights reserved.
*/
@import <Foundation/Foundation.j>
@import <AppKit/AppKit.j>
@import "AppController.j"
function main(args, namedArgs)
{
CPApplicationMain(args, namedArgs);
}