Compare commits

..
3 Commits
635 changed files with 7712 additions and 39947 deletions
+4 -9
View File
@@ -36,8 +36,8 @@
@import "CPCibLoading.j"
@import "CPCibOutletConnector.j"
@import "CPClipView.j"
@import "CPCollectionView.j"
@import "CPCollectionViewItem.j"
@import "CPCollectionView.j"
@import "CPColor.j"
@import "CPColorPanel.j"
@import "CPColorWell.j"
@@ -53,10 +53,8 @@
@import "CPFont.j"
@import "CPFontManager.j"
@import "CPGeometry.j"
@import "CPGraphics.j"
@import "CPImage.j"
@import "CPImageView.j"
@import "CPKeyBinding.j"
@import "CPMenu.j"
@import "CPMenuItem.j"
@import "CPOpenPanel.j"
@@ -67,22 +65,20 @@
@import "CPProgressIndicator.j"
@import "CPRadio.j"
@import "CPResponder.j"
@import "CPScroller.j"
@import "CPScrollView.j"
@import "CPSearchField.j"
@import "CPScrollView.j"
@import "CPScroller.j"
@import "CPSecureTextField.j"
@import "CPSegmentedControl.j"
@import "CPShadow.j"
@import "CPSlider.j"
@import "CPSplitView.j"
@import "CPTabView.j"
@import "CPTableColumn.j"
@import "CPTableView.j"
@import "CPTabView.j"
@import "CPText.j"
@import "CPTextField.j"
@import "CPToolbar.j"
@import "CPToolbarItem.j"
@import "CPTokenField.j"
@import "CPTreeNode.j"
@import "CPView.j"
@import "CPViewAnimation.j"
@@ -90,4 +86,3 @@
@import "CPWebView.j"
@import "CPWindow.j"
@import "CPWindowController.j"
@import "CPArrayController.j"
+11 -46
View File
@@ -26,16 +26,11 @@
@import <Foundation/CPIndexSet.j>
@import <Foundation/CPString.j>
@import "CPView.j"
@import "CPButton.j"
@import <AppKit/CPView.j>
#import "CoreGraphics/CGGeometry.h"
/*!
@ingroup appkit
@class CPAccordionViewItem
<p>A CPAccordionViewItem represents a single section of a CPAccordionView.</p>
*/
@implementation CPAccordionViewItem : CPObject
{
CPString _identifier @accessors(property=identifier);
@@ -48,10 +43,6 @@
return [self initWithIdentifier:@""];
}
/*!
Initializes a new CPAccordionViewItem with the specified identifier. This identifier may
then be used in subsequent methods to provide abstract introspection of the CPAccordionView.
*/
- (id)initWithIdentifier:(CPString)anIdentifier
{
self = [super init];
@@ -64,25 +55,6 @@
@end
/*!
@ingroup appkit
@class CPAccordionView
<p>CPAccordionView provides a container for CPAccordionViewItem objects and manages layout state
for all sublayout items.</p>
<strong>Example</strong><br />
<pre>
var myAccordionView = [[CPAccordionView alloc] initWithFrame:CGRectMakeZero()];
var firstItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"firstSection"]];
[firstItem setView:[[CPView alloc] initWithFrame:CGRectMakeZero()]];
var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection"]];
[secondItem setView:[[CPView alloc] initWithFrame:CGRectMakeZero()]];
[myAccordionView addItem:firstItem];
[myAccordionView addItem:secondItem];
[myAccordionView setAutoresizingMask: CPViewWidthSizable | CPViewHeightSizable];
</pre>
*/
@implementation CPAccordionView : CPView
{
CPInteger _dirtyItemIndex;
@@ -92,10 +64,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
CPMutableArray _itemViews;
CPIndexSet _expandedItemIndexes;
}
/*!
Initializes the receiver for usage with the specified bounding rectangle
@return the initialized view
*/
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
@@ -126,11 +95,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
{
return _items;
}
/*!
Append a CPAccordionViewItem to the receiver. Note that the CPAccordionViewItem must contain
a valid CPView derived component or a TypeError will be generated when the contents of the
ViewItem are disclosed.
*/
- (void)addItem:(CPAccordionViewItem)anItem
{
[self insertItem:anItem atIndex:_items.length];
@@ -213,7 +178,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
if ([itemView isCollapsed])
[self expandItemAtIndex:anIndex];
else
[self collapseItemAtIndex:anIndex];
}
@@ -237,12 +202,12 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
var itemView = _itemViews[anIndex];
if (!itemView)
return;
if (!isEnabled)
[self collapseItemAtIndex:anIndex];
else
[self expandItemAtIndex:anIndex];
[itemView setEnabled:isEnabled];
}
@@ -270,7 +235,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
{
if (_items.length <= 0)
return [self setFrameSize:_CGSizeMake(_CGRectGetWidth([self frame]), 0.0)];
if (_dirtyItemIndex === CPNotFound)
return;
@@ -391,7 +356,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
[_contentView setFrameSize:_CGSizeMake(aWidth, contentHeight)];
[self setFrame:_CGRectMake(0.0, aY, aWidth, contentHeight + headerHeight)];
}
}
}
- (void)resizeSubviewsWithOldSize:(CGSize)aSize
@@ -408,7 +373,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
/*
else if (aKeyPath === "itemHeaderPrototype")
{
}
*/
}
+102 -256
View File
@@ -26,34 +26,39 @@
@import <Foundation/CPObject.j>
@import <Foundation/CPString.j>
@import "CPApplication.j"
@import "CPButton.j"
@import "CPColor.j"
@import "CPFont.j"
@import "CPImage.j"
@import "CPImageView.j"
@import "CPPanel.j"
@import "CPTextField.j"
@import <AppKit/CPApplication.j>
@import <AppKit/CPButton.j>
@import <AppKit/CPColor.j>
@import <AppKit/CPFont.j>
@import <AppKit/CPImage.j>
@import <AppKit/CPImageView.j>
@import <AppKit/CPPanel.j>
@import <AppKit/CPTextField.j>
/*
@global
@group CPAlertStyle
*/
CPWarningAlertStyle = 0;
CPWarningAlertStyle = 0;
/*
@global
@group CPAlertStyle
*/
CPInformationalAlertStyle = 1;
CPInformationalAlertStyle = 1;
/*
@global
@group CPAlertStyle
*/
CPCriticalAlertStyle = 2;
CPCriticalAlertStyle = 2;
var CPAlertWarningImage,
CPAlertInformationImage,
CPAlertErrorImage;
/*!
@ingroup appkit
CPAlert is an alert panel that can be displayed modally to present the
user with a message and one or more options.
@@ -69,51 +74,41 @@ CPCriticalAlertStyle = 2;
@delegate -(void)alertDidEnd:(CPAlert)theAlert returnCode:(int)returnCode;
Called when the user dismisses the alert by clicking one of the buttons.
@param theAlert the alert panel that the user dismissed
@param returnCode the index of the button that the user clicked (starting from 0,
@param returnCode the index of the button that the user clicked (starting from 0,
representing the first button added to the alert which appears on the
right, 1 representing the next button to the left and so on)
*/
@implementation CPAlert : CPView
@implementation CPAlert : CPObject
{
CPPanel _alertPanel;
CPTextField _messageLabel;
CPTextField _informativeLabel;
CPImageView _alertImageView;
CPAlertStyle _alertStyle;
CPString _windowTitle;
int _windowStyle;
int _buttonCount;
CPArray _buttons;
id _delegate;
SEL _didEndSelector;
id _modalDelegate;
}
+ (CPString)defaultThemeClass
+ (void)initialize
{
return @"alert";
}
if (self != CPAlert)
return;
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[CGSizeMake(400.0, 110.0), CGInsetMake(15, 15, 15, 50), 6, 10,
CPJustifiedTextAlignment, [CPColor blackColor], [CPFont boldSystemFontOfSize:13.0], [CPNull null], CGSizeMakeZero(),
CPJustifiedTextAlignment, [CPColor blackColor], [CPFont systemFontOfSize:12.0], [CPNull null], CGSizeMakeZero(),
CGPointMake(15, 12),
[CPNull null],
[CPNull null],
[CPNull null]
]
forKeys:[@"size", @"content-inset", @"informative-offset", @"button-offset",
@"message-text-alignment", @"message-text-color", @"message-text-font", @"message-text-shadow-color", @"message-text-shadow-offset",
@"informative-text-alignment", @"informative-text-color", @"informative-text-font", @"informative-text-shadow-color", @"informative-text-shadow-offset",
@"image-offset",
@"information-image",
@"warning-image",
@"error-image"
]];
var bundle = [CPBundle bundleForClass:[self class]];
CPAlertWarningImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPAlert/dialog-warning.png"]
size:CGSizeMake(32.0, 32.0)];
CPAlertInformationImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPAlert/dialog-information.png"]
size:CGSizeMake(32.0, 32.0)];
CPAlertErrorImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPAlert/dialog-error.png"]
size:CGSizeMake(32.0, 32.0)];
}
/*!
@@ -123,56 +118,57 @@ CPCriticalAlertStyle = 2;
{
if (self = [super init])
{
_buttonCount = 0;
_buttons = [CPArray array];
_alertStyle = CPWarningAlertStyle;
_alertPanel = nil;
_windowStyle = nil;
_didEndSelector = nil;
_messageLabel = [CPTextField labelWithTitle:@"Alert"];
_alertImageView = [[CPImageView alloc] initWithFrame:CGRectMakeZero()];
_informativeLabel = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[self setWindowStyle:nil];
}
return self;
}
/*!
Sets the window appearance. If CPHUDBackgroundWindowMask is set, the default HUD theme
will be activated.
Sets the window appearance.
@param styleMask - Either CPHUDBackgroundWindowMask or nil for standard.
*/
- (void)setWindowStyle:(int)styleMask
{
_windowStyle = styleMask;
_alertPanel = [[CPPanel alloc] initWithContentRect:CGRectMake(0.0, 0.0, 400.0, 110.0) styleMask:styleMask ? styleMask | CPTitledWindowMask : CPTitledWindowMask];
[_alertPanel setFloatingPanel:YES];
[_alertPanel center];
[self setTheme:(_windowStyle & CPHUDBackgroundWindowMask) ? [CPTheme defaultHudTheme] : [CPTheme defaultTheme]];
[_messageLabel setTextColor:(styleMask & CPHUDBackgroundWindowMask) ? [CPColor whiteColor] : [CPColor blackColor]];
// We'll need to recreate the panel to get the new window style.
_alertPanel = nil;
}
- (void)_createPanel
{
var frame = CGRectMakeZero();
frame.size = [self currentValueForThemeAttribute:@"size"];
_alertPanel = [[CPPanel alloc] initWithContentRect:frame styleMask:_windowStyle ? _windowStyle | CPTitledWindowMask : CPTitledWindowMask];
var contentView = [_alertPanel contentView],
count = [_buttons count];
if (count)
var count = [_buttons count];
for(var i=0; i < count; i++)
{
while (count--)
[contentView addSubview:_buttons[count]];
}
else
[self addButtonWithTitle:@"OK"];
var button = _buttons[i];
[button setFrameSize:CGSizeMake([button frame].size.width, (styleMask == CPHUDBackgroundWindowMask) ? 20.0 : 24.0)];
[button setTheme:(_windowStyle === CPHUDBackgroundWindowMask) ? [CPTheme themeNamed:"Aristo-HUD"] : [CPTheme defaultTheme]];
[contentView addSubview:_messageLabel];
[contentView addSubview:_alertImageView];
[contentView addSubview:_informativeLabel];
[[_alertPanel contentView] addSubview:button];
}
if (!_messageLabel)
{
var bounds = [[_alertPanel contentView] bounds];
_messageLabel = [[CPTextField alloc] initWithFrame:CGRectMake(57.0, 10.0, CGRectGetWidth(bounds) - 73.0, 62.0)];
[_messageLabel setFont:[CPFont boldSystemFontOfSize:13.0]];
[_messageLabel setLineBreakMode:CPLineBreakByWordWrapping];
[_messageLabel setAlignment:CPJustifiedTextAlignment];
[_messageLabel setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
_alertImageView = [[CPImageView alloc] initWithFrame:CGRectMake(15.0, 12.0, 32.0, 32.0)];
}
[[_alertPanel contentView] addSubview:_messageLabel];
[[_alertPanel contentView] addSubview:_alertImageView];
}
/*!
@@ -235,7 +231,7 @@ CPCriticalAlertStyle = 2;
}
/*!
Sets the receivers message text, or title, to a given text.
Sets the receivers message text, or title, to a given text.
@param messageText - Message text for the alert.
*/
- (void)setMessageText:(CPString)messageText
@@ -243,157 +239,41 @@ CPCriticalAlertStyle = 2;
[_messageLabel setStringValue:messageText];
}
/*!
Returns the receiver's message text body.
/*!
Return's the receiver's message text body.
*/
- (CPString)messageText
{
return [_messageLabel stringValue];
}
/*!
Sets the receiver's informative text, shown below the message text.
@param informativeText - The informative text.
*/
- (void)setInformativeText:(CPString)informativeText
{
[_informativeLabel setStringValue:informativeText];
}
/*!
Returns the receiver's informative text.
*/
- (CPString)informativeText
{
return [_informativeLabel stringValue];
}
/*!
Adds a button with a given title to the receiver.
Buttons will be added starting from the right hand side of the \c CPAlert panel.
The first button will have the index 0, the second button 1 and so on.
The first button will automatically be given a key equivalent of Return,
and any button titled "Cancel" will be given a key equivalent of Escape.
You really shouldn't need more than 3 buttons.
*/
- (void)addButtonWithTitle:(CPString)title
{
var bounds = [[_alertPanel contentView] bounds],
button = [[CPButton alloc] initWithFrame:CGRectMakeZero()],
_buttonCount = [_buttons count];
button = [[CPButton alloc] initWithFrame:CGRectMake(CGRectGetWidth(bounds) - ((_buttonCount + 1) * 90.0), CGRectGetHeight(bounds) - 34.0, 80.0, (_windowStyle == CPHUDBackgroundWindowMask) ? 20.0 : 24.0)];
[button setTitle:title];
[button setTarget:self];
[button setTag:_buttonCount];
[button setAction:@selector(_dismissAlert:)];
[button setAction:@selector(_notifyDelegate:)];
[button setTheme:(_windowStyle === CPHUDBackgroundWindowMask) ? [CPTheme themeNamed:"Aristo-HUD"] : [CPTheme defaultTheme]];
[button setAutoresizingMask:CPViewMinXMargin | CPViewMinYMargin];
[[_alertPanel contentView] addSubview:button];
if (_buttonCount == 0)
[button setKeyEquivalent:CPCarriageReturnCharacter];
else if ([title lowercaseString] === "cancel")
[button setKeyEquivalent:CPEscapeFunctionKey];
else
[button setKeyEquivalent:nil];
[_alertPanel setDefaultButton:button];
[_buttons insertObject:button atIndex:0];
}
- (void)layoutPanel
{
if (!_alertPanel)
[self _createPanel];
var inset = [self currentValueForThemeAttribute:@"content-inset"],
iconOffset = [self currentValueForThemeAttribute:@"image-offset"],
theTitle,
theImage;
switch (_alertStyle)
{
case CPWarningAlertStyle: theImage = [self currentValueForThemeAttribute:@"warning-image"];
theTitle = @"Warning";
break;
case CPInformationalAlertStyle: theImage = [self currentValueForThemeAttribute:@"information-image"];
theTitle = @"Information";
break;
case CPCriticalAlertStyle: theImage = [self currentValueForThemeAttribute:@"error-image"];
theTitle = @"Error";
break;
}
[_alertImageView setImage:theImage];
var imageSize = theImage ? [theImage size] : CGSizeMakeZero();
[_alertImageView setFrame:CGRectMake(iconOffset.x, iconOffset.y, imageSize.width, imageSize.height)];
[_alertPanel setTitle:_windowTitle ? _windowTitle : theTitle];
[_alertPanel setFloatingPanel:YES];
[_alertPanel center];
[_messageLabel setTextColor:[self currentValueForThemeAttribute:@"message-text-color"]];
[_messageLabel setFont:[self currentValueForThemeAttribute:@"message-text-font"]];
[_messageLabel setTextShadowColor:[self currentValueForThemeAttribute:@"message-text-shadow-color"]];
[_messageLabel setTextShadowOffset:[self currentValueForThemeAttribute:@"message-text-shadow-offset"]];
[_messageLabel setAlignment:[self currentValueForThemeAttribute:@"message-text-alignment"]];
[_messageLabel setLineBreakMode:CPLineBreakByWordWrapping];
[_informativeLabel setTextColor:[self currentValueForThemeAttribute:@"informative-text-color"]];
[_informativeLabel setFont:[self currentValueForThemeAttribute:@"informative-text-font"]];
[_informativeLabel setTextShadowColor:[self currentValueForThemeAttribute:@"informative-text-shadow-color"]];
[_informativeLabel setTextShadowOffset:[self currentValueForThemeAttribute:@"informative-text-shadow-offset"]];
[_informativeLabel setLineBreakMode:CPLineBreakByWordWrapping];
// FIXME sizeWithFontCorrection shouldn't be needed.
var bounds = [[_alertPanel contentView] bounds],
offsetX = CGRectGetWidth(bounds) - inset.right,
informativeOffset = [self currentValueForThemeAttribute:@"informative-offset"],
buttonOffset = [self currentValueForThemeAttribute:@"button-offset"],
textWidth = offsetX - inset.left,
messageSize = [([_messageLabel stringValue] || " ") sizeWithFont:[_messageLabel font] inWidth:textWidth],
informationString = [_informativeLabel stringValue],
informativeSize = [(informationString || " ") sizeWithFont:[_informativeLabel font] inWidth:textWidth],
sizeWithFontCorrection = 6.0;
[_messageLabel setFrame:CGRectMake(inset.left, inset.top, textWidth, messageSize.height + sizeWithFontCorrection)];
[_informativeLabel setFrame:CGRectMake(inset.left, CGRectGetMaxY([_messageLabel frame]) + informativeOffset, textWidth, informativeSize.height + sizeWithFontCorrection)];
// Don't let an empty informative label partially cover the buttons.
[_informativeLabel setHidden:!informationString];
var aRepresentativeButton = _buttons[0],
buttonY = MAX(CGRectGetMaxY([_alertImageView frame]), CGRectGetMaxY(informationString ? [_informativeLabel frame] : [_messageLabel frame])) + buttonOffset; // the lower of the bottom of the text and the bottom of the icon.
[aRepresentativeButton setTheme:[self theme]];
[aRepresentativeButton sizeToFit];
// Make the window just tall enough to fit everything. Bit of a hack really.
var minimumSize = [self currentValueForThemeAttribute:@"size"],
desiredHeight = MAX(minimumSize.height, buttonY + CGRectGetHeight([aRepresentativeButton bounds]) + inset.bottom),
deltaY = desiredHeight - CGRectGetHeight(bounds),
frameSize = CGSizeMakeCopy([_alertPanel frame].size);
frameSize.height += deltaY;
[_alertPanel setFrameSize:frameSize];
var count = [_buttons count];
while (count--)
{
var button = _buttons[count];
[button setTheme:[self theme]];
[button sizeToFit];
var buttonBounds = [button bounds],
width = MAX(80.0, CGRectGetWidth(buttonBounds)),
height = CGRectGetHeight(buttonBounds);
offsetX -= width;
[button setFrame:CGRectMake(offsetX, buttonY, width, height)];
offsetX -= 10;
}
_buttonCount++;
[_buttons addObject:button];
}
/*!
@@ -403,68 +283,34 @@ CPCriticalAlertStyle = 2;
*/
- (void)runModal
{
[self layoutPanel];
var theTitle;
switch (_alertStyle)
{
case CPWarningAlertStyle: [_alertImageView setImage:CPAlertWarningImage];
theTitle = @"Warning";
break;
case CPInformationalAlertStyle: [_alertImageView setImage:CPAlertInformationImage];
theTitle = @"Information";
break;
case CPCriticalAlertStyle: [_alertImageView setImage:CPAlertErrorImage];
theTitle = @"Error";
break;
}
[_alertPanel setTitle:_windowTitle ? _windowTitle : theTitle];
[CPApp runModalForWindow:_alertPanel];
}
/*!
Runs the receiver modally as an alert sheet attached to a specified window.
@param window The parent window for the sheet.
@param modalDelegate The delegate for the modal-dialog session.
@param alertDidEndSelector Message the alert sends to modalDelegate after the sheet is dismissed.
@param contextInfo Contextual data passed to modalDelegate in didEndSelector message.
*/
- (void)beginSheetModalForWindow:(CPWindow)window modalDelegate:(id)modalDelegate didEndSelector:(SEL)alertDidEndSelector contextInfo:(void)contextInfo
{
if (!(_windowStyle & CPDocModalWindowMask))
[self setWindowStyle:CPDocModalWindowMask];
[self layoutPanel];
_didEndSelector = alertDidEndSelector;
_modalDelegate = modalDelegate;
[CPApp beginSheet:_alertPanel modalForWindow:window modalDelegate:self didEndSelector:@selector(_alertDidEnd:returnCode:contextInfo:) contextInfo:contextInfo];
}
/*!
Runs the receiver modally as an alert sheet attached to a specified window.
@param window The parent window for the sheet.
*/
- (void)beginSheetModalForWindow:(CPWindow)window
{
if (!(_windowStyle & CPDocModalWindowMask))
[self setWindowStyle:CPDocModalWindowMask];
[self layoutPanel];
[CPApp beginSheet:_alertPanel modalForWindow:window modalDelegate:self didEndSelector:@selector(_alertDidEnd:returnCode:contextInfo:) contextInfo:nil];
}
- (void)_alertDidEnd:(CPWindow)aSheet returnCode:(CPInteger)returnCode contextInfo:(id)contextInfo
{
if ([_delegate respondsToSelector:@selector(alertDidEnd:returnCode:)])
[_delegate alertDidEnd:self returnCode:returnCode];
if (_didEndSelector)
objj_msgSend(_modalDelegate, _didEndSelector, self, returnCode, contextInfo);
_didEndSelector = nil;
_modalDelegate = nil;
}
/* @ignore */
- (void)_dismissAlert:(CPButton)button
- (void)_notifyDelegate:(id)button
{
if ([_alertPanel isSheet])
[CPApp endSheet:_alertPanel returnCode:[button tag]];
else
{
[CPApp abortModal];
[_alertPanel close];
[CPApp abortModal];
[_alertPanel close];
[self _alertDidEnd:nil returnCode:[button tag] contextInfo:nil];
}
if (_delegate && [_delegate respondsToSelector:@selector(alertDidEnd:returnCode:)])
[_delegate alertDidEnd:self returnCode:[button tag]];
}
@end
+27 -27
View File
@@ -48,14 +48,14 @@ CPAnimationLinear = 3;
ACTUAL_FRAME_RATE = 0;
/*!
/*!
@ingroup appkit
@class CPAnimation
Manages an animation. Contains timing and progress information.
@par Delegate Methods
@delegate -(BOOL)animationShouldStart:(CPAnimation)animation;
Called at the beginning of \c -startAnimation.
@param animation the animation that will start
@@ -81,13 +81,13 @@ ACTUAL_FRAME_RATE = 0;
{
CPTimeInterval _lastTime;
CPTimeInterval _duration;
CPAnimationCurve _animationCurve;
CAMediaTimingFunction _timingFunction;
float _frameRate;
float _progress;
id _delegate;
CPTimer _timer;
}
@@ -101,7 +101,7 @@ ACTUAL_FRAME_RATE = 0;
- (id)initWithDuration:(float)aDuration animationCurve:(CPAnimationCurve)anAnimationCurve
{
self = [super init];
if (self)
{
_progress = 0.0;
@@ -110,14 +110,14 @@ ACTUAL_FRAME_RATE = 0;
[self setAnimationCurve:anAnimationCurve];
}
return self;
}
/*!
Sets the animation's pace.
@param anAnimationCurve the animation's pace
@throws CPInvalidArgumentException if an invalid animation curve is specified
@throws CPInvalidArgumentException if an invalid animation curve is specified
*/
- (void)setAnimationCurve:(CPAnimationCurve)anAnimationCurve
{
@@ -125,13 +125,13 @@ ACTUAL_FRAME_RATE = 0;
{
case CPAnimationEaseInOut: timingFunctionName = kCAMediaTimingFunctionEaseInEaseOut;
break;
case CPAnimationEaseIn: timingFunctionName = kCAMediaTimingFunctionEaseIn;
break;
case CPAnimationEaseOut: timingFunctionName = kCAMediaTimingFunctionEaseOut;
break;
case CPAnimationLinear: timingFunctionName = kCAMediaTimingFunctionLinear;
break;
@@ -139,7 +139,7 @@ ACTUAL_FRAME_RATE = 0;
reason:"Invalid value provided for animation curve"];
break;
}
_animationCurve = anAnimationCurve;
_timingFunction = [CAMediaTimingFunction functionWithName:timingFunctionName];
}
@@ -161,7 +161,7 @@ ACTUAL_FRAME_RATE = 0;
{
if (aDuration < 0)
[CPException raise:CPInvalidArgumentException reason:"aDuration can't be negative"];
_duration = aDuration;
}
@@ -182,7 +182,7 @@ ACTUAL_FRAME_RATE = 0;
{
if (frameRate < 0)
[CPException raise:CPInvalidArgumentException reason:"frameRate can't be negative"];
_frameRate = frameRate;
}
@@ -221,13 +221,13 @@ ACTUAL_FRAME_RATE = 0;
// If we're already animating, or our delegate stops us, animate.
if (_timer || _delegate && [_delegate respondsToSelector:@selector(animationShouldStart:)] && ![_delegate animationShouldStart:self])
return;
if (_progress === 1.0)
_progress = 0.0;
ACTUAL_FRAME_RATE = 0;
_lastTime = new Date();
_timer = [CPTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(animationTimerDidFire:) userInfo:nil repeats:YES];
}
@@ -242,14 +242,14 @@ ACTUAL_FRAME_RATE = 0;
_lastTime = currentTime;
++ACTUAL_FRAME_RATE;
[self setCurrentProgress:progress];
if (progress === 1.0)
{
[_timer invalidate];
_timer = nil;
if ([_delegate respondsToSelector:@selector(animationDidEnd:)])
[_delegate animationDidEnd:self];
}
@@ -262,10 +262,10 @@ ACTUAL_FRAME_RATE = 0;
{
if (!_timer)
return;
[_timer invalidate];
_timer = nil;
if ([_delegate respondsToSelector:@selector(animationDidStop:)])
[_delegate animationDidStop:self];
}
@@ -302,16 +302,16 @@ ACTUAL_FRAME_RATE = 0;
- (float)currentValue
{
var t = [self currentProgress];
if ([_delegate respondsToSelector:@selector(animation:valueForProgress:)])
return [_delegate animation:self valueForProgress:t];
var c1 = [],
c2 = [];
[_timingFunction getControlPointAtIndex:1 values:c1];
[_timingFunction getControlPointAtIndex:2 values:c2];
return CubicBezierAtTime(t,c1[0],c1[1],c2[0],c2[1],_duration);
}
@@ -332,7 +332,7 @@ var CubicBezierAtTime = function CubicBezierAtTime(t,p1x,p1y,p2x,p2y,duration)
function solve(x,epsilon) {return sampleCurveY(solveCurveX(x,epsilon));};
// Given an x value, find a parametric value it came from.
function solveCurveX(x,epsilon) {var t0,t1,t2,x2,d2,i;
function fabs(n) {if(n>=0) {return n;}else {return 0-n;}};
function fabs(n) {if(n>=0) {return n;}else {return 0-n;}};
// First try a few iterations of Newton's method -- normally very fast.
for(t2=x, i=0; i<8; i++) {x2=sampleCurveX(t2)-x; if(fabs(x2)<epsilon) {return t2;} d2=sampleCurveDerivativeX(t2); if(fabs(d2)<1e-6) {break;} t2=t2-x2/d2;}
// Fall back to the bisection method for reliability.
+14 -31
View File
@@ -31,6 +31,7 @@
@import "CPCibLoading.j"
@import "CPPlatform.j"
#include "Platform/Platform.h"
var CPMainCibFile = @"CPMainCibFile",
CPMainCibFileHumanFriendly = @"Main cib file base name";
@@ -107,8 +108,6 @@ CPRunContinuesResponse = -1002;
CPImage _applicationIconImage;
CPPanel _aboutPanel;
CPThemeBlend _themeBlend @accessors(property=themeBlend);
}
/*!
@@ -326,9 +325,7 @@ CPRunContinuesResponse = -1002;
applicationVersion = [options objectForKey:@"ApplicationVersion"] || [mainInfo objectForKey:@"CPBundleShortVersionString"],
copyright = [options objectForKey:@"Copyright"] || [mainInfo objectForKey:@"CPHumanReadableCopyright"];
var aboutPanelPath = [[CPBundle bundleForClass:[CPWindowController class]] pathForResource:@"AboutPanel.cib"],
aboutPanelController = [CPWindowController alloc],
aboutPanelController = [aboutPanelController initWithWindowCibPath:aboutPanelPath owner:aboutPanelController],
var aboutPanelController = [[CPWindowController alloc] initWithWindowCibName:@"AboutPanel"],
aboutPanel = [aboutPanelController window],
contentView = [aboutPanel contentView],
imageView = [contentView viewWithTag:1],
@@ -506,8 +503,7 @@ CPRunContinuesResponse = -1002;
var theWindow = aModalSession._window;
[theWindow center];
[theWindow makeKeyWindow];
[theWindow orderFront:self];
[theWindow makeKeyAndOrderFront:self];
// [theWindow._bridge _obscureWindowsBelowModalWindow];
@@ -619,11 +615,7 @@ CPRunContinuesResponse = -1002;
*/
- (CPArray)orderedWindows
{
#if PLATFORM(DOM)
return CPWindowObjectList();
#else
return [];
#endif
}
- (void)hide:(id)aSender
@@ -683,7 +675,7 @@ CPRunContinuesResponse = -1002;
if ([super tryToPerform:anAction with:anObject])
return YES;
if ([_delegate respondsToSelector:anAction])
if([_delegate respondsToSelector:anAction])
{
[_delegate performSelector:anAction withObject:anObject];
@@ -863,7 +855,6 @@ CPRunContinuesResponse = -1002;
}
[aWindow orderFront:self];
[aSheet setPlatformWindow:[aWindow platformWindow]];
[aWindow _attachSheet:aSheet modalDelegate:aModalDelegate didEndSelector:aDidEndSelector contextInfo:aContextInfo];
}
@@ -873,8 +864,8 @@ CPRunContinuesResponse = -1002;
while (--count >= 0)
{
var aWindow = [_windows objectAtIndex:count],
context = aWindow._sheetContext;
var aWindow = [_windows objectAtIndex:count];
var context = aWindow._sheetContext;
if (context != nil && context["sheet"] === sheet)
{
@@ -892,7 +883,7 @@ CPRunContinuesResponse = -1002;
- (CPArray)arguments
{
if (_fullArgsString !== window.location.hash)
if(_fullArgsString !== window.location.hash)
[self _reloadArguments];
return _args;
@@ -900,7 +891,7 @@ CPRunContinuesResponse = -1002;
- (void)setArguments:(CPArray)args
{
if (!args || args.length == 0)
if(!args || args.length == 0)
{
_args = [];
window.location.hash = @"#";
@@ -908,13 +899,13 @@ CPRunContinuesResponse = -1002;
return;
}
if ([args class] != CPArray)
if([args class] != CPArray)
args = [CPArray arrayWithObject:args];
_args = args;
var toEncode = [_args copy];
for (var i = 0, count = toEncode.length; i < count; i++)
for(var i=0, count = toEncode.length; i<count; i++)
toEncode[i] = encodeURIComponent(toEncode[i]);
var hash = [toEncode componentsJoinedByString:@"/"];
@@ -1021,6 +1012,7 @@ CPRunContinuesResponse = -1002;
+ (CPString)defaultThemeName
{
// FIXME: don't hardcode
return ([[CPBundle mainBundle] objectForInfoDictionaryKey:"CPDefaultTheme"] || @"Aristo");
}
@@ -1036,8 +1028,7 @@ var _CPEventListenerMake = function(anEventMask, aCallback)
return { _mask:anEventMask, _callback:aCallback };
}
// Make this a global for use in CPPlatformWindow+DOM.j.
_CPRunModalLoop = function(anEvent)
var _CPRunModalLoop = function(anEvent)
{
[CPApp setCallback:_CPRunModalLoop forNextEventMatchingMask:CPAnyEventMask untilDate:nil inMode:0 dequeue:NO];
@@ -1115,15 +1106,8 @@ var _CPAppBootstrapperActions = nil;
+ (BOOL)loadDefaultTheme
{
var defaultThemeName = [CPApplication defaultThemeName],
themeURL = nil;
var blend = [[CPThemeBlend alloc] initWithContentsOfURL:[[CPBundle bundleForClass:[CPApplication class]] pathForResource:[CPApplication defaultThemeName] + ".blend"]];
if (defaultThemeName === @"Aristo")
themeURL = [[CPBundle bundleForClass:[CPApplication class]] pathForResource:defaultThemeName + @".blend"];
else
themeURL = [[CPBundle mainBundle] pathForResource:defaultThemeName + @".blend"];
var blend = [[CPThemeBlend alloc] initWithContentsOfURL:themeURL];
[blend loadWithDelegate:self];
return YES;
@@ -1131,7 +1115,6 @@ var _CPAppBootstrapperActions = nil;
+ (void)blendDidFinishLoading:(CPThemeBlend)aThemeBlend
{
[[CPApplication sharedApplication] setThemeBlend:aThemeBlend];
[CPTheme setDefaultTheme:[CPTheme themeNamed:[CPApplication defaultThemeName]]];
[self performActions];
@@ -1229,7 +1212,7 @@ var _CPAppBootstrapperActions = nil;
+ (void)reset
{
_CPAppBootstrapperActions = nil;
_CPAppBootstrapperActions = nil;
}
@end
-675
View File
@@ -1,675 +0,0 @@
/*
* CPArrayController.j
* AppKit
*
* Adapted from Cocotron, by Johannes Fortmann
*
* Created by Ross Boucher.
* Copyright 2009, 280 North, Inc.
*
* 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 <Foundation/CPIndexSet.j>
@import "CPObjectController.j"
@import "CPKeyValueBinding.j"
@implementation CPArrayController : CPObjectController
{
BOOL _avoidsEmptySelection;
BOOL _clearsFilterPredicateOnInsertion;
BOOL _filterRestrictsInsertion;
BOOL _preservesSelection;
BOOL _selectsInsertedObjects;
BOOL _alwaysUsesMultipleValuesMarker;
id _selectionIndexes;
id _sortDescriptors;
id _filterPredicate;
id _arrangedObjects;
}
+ (void)initialize
{
if (self !== [CPArrayController class])
return;
[self exposeBinding:@"contentArray"];
[self exposeBinding:@"contentSet"];
}
+ (CPSet)keyPathsForValuesAffectingContentArray
{
return [CPSet setWithObjects:"content"];
}
+ (CPSet)keyPathsForValuesAffectingArrangedObjects
{
return [CPSet setWithObjects:"content", "filterPredicate", "sortDescriptors"];
}
+ (CPSet)keyPathsForValuesAffectingSelection
{
return [CPSet setWithObjects:"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingSelectionIndex
{
return [CPSet setWithObjects:"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingSelectionIndexes
{
// When the arranged objects change, selection preservation may cause the indexes
// to change.
return [CPSet setWithObjects:"arrangedObjects"];
}
+ (CPSet)keyPathsForValuesAffectingSelectedObjects
{
// Don't need to depend on arrangedObjects here because selectionIndexes already does.
return [CPSet setWithObjects:"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingCanRemove
{
return [CPSet setWithObjects:"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingCanSelectNext
{
return [CPSet setWithObjects:"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingCanSelectPrevious
{
return [CPSet setWithObjects:"selectionIndexes"];
}
- (id)init
{
self = [super init];
if (self)
{
_selectionIndexes = [CPIndexSet indexSet];
}
return self;
}
- (void)prepareContent
{
[self _setContentArray:[[self newObject]]];
}
- (BOOL)preservesSelection
{
return _preservesSelection;
}
- (void)setPreservesSelection:(BOOL)value
{
_preservesSelection = value;
}
- (BOOL)selectsInsertedObjects
{
return _selectsInsertedObjects;
}
- (void)setSelectsInsertedObjects:(BOOL)value
{
_selectsInsertedObjects = value;
}
- (BOOL)avoidsEmptySelection
{
return _avoidsEmptySelection;
}
- (void)setAvoidsEmptySelection:(BOOL)value
{
_avoidsEmptySelection = value;
}
- (void)setContent:(id)value
{
if (value === nil)
value = [];
if (![value isKindOfClass:[CPArray class]])
value = [value];
var oldSelectedObjects = nil,
oldSelectionIndexes = nil;
if ([self preservesSelection])
oldSelectedObjects = [self selectedObjects];
else
oldSelectionIndexes = [self selectionIndexes];
/*
When the contents are changed, the selected indexes may no longer refer to the
same items. This would cause problems when setSelectedObjects is called below.
Any KVO observation would try to retrieve the 'before' value which could be
wrong or even throw an exception for no longer existing indexes.
To avoid that, use the internal __setSelectedObjects which fires no notifications.
The selectionIndexes notifications will fire later since they depend on the
content key. This pattern is also applied for many other methods throughout this
class.
*/
if (_clearsFilterPredicateOnInsertion)
[self willChangeValueForKey:@"filterPredicate"];
// Don't use [super setContent:] as that would fire the contentObject change.
// We need to be in control of when notifications fire.
_contentObject = value;
if (_clearsFilterPredicateOnInsertion)
[self __setFilterPredicate:nil]; // Causes a _rearrangeObjects.
else
[self _rearrangeObjects];
if ([self preservesSelection])
[self __setSelectedObjects:oldSelectedObjects];
else
[self __setSelectionIndexes:oldSelectionIndexes];
if (_clearsFilterPredicateOnInsertion)
[self didChangeValueForKey:@"filterPredicate"];
}
- (void)_setContentArray:(id)anArray
{
[self setContent:anArray];
}
- (void)_setContentSet:(id)aSet
{
[self setContent:aSet];
}
- (id)contentArray
{
return [self content];
}
- (id)contentSet
{
return [self content];
}
- (CPArray)arrangeObjects:(CPArray)objects
{
var filterPredicate = [self filterPredicate],
sortDescriptors = [self sortDescriptors];
if (filterPredicate && sortDescriptors)
{
var sortedObjects = [objects filteredArrayUsingPredicate:filterPredicate];
[sortedObjects sortUsingDescriptors:sortDescriptors];
return sortedObjects;
}
else if (filterPredicate)
return [objects filteredArrayUsingPredicate:filterPredicate];
else if (sortDescriptors)
return [objects sortedArrayUsingDescriptors:sortDescriptors];
return [objects copy];
}
- (void)rearrangeObjects
{
[self willChangeValueForKey:@"arrangedObjects"];
[self _rearrangeObjects];
[self didChangeValueForKey:@"arrangedObjects"];
}
/*
Like rearrangeObjects but don't fire any change notifications.
@ignore
*/
- (void)_rearrangeObjects
{
/*
Rearranging reapplies the selection criteria and may cause objects to disappear,
so take care of the selection.
*/
var oldSelectedObjects = nil,
oldSelectionIndexes = nil;
if ([self preservesSelection])
oldSelectedObjects = [self selectedObjects];
else
oldSelectionIndexes = [self selectionIndexes];
[self __setArrangedObjects:[self arrangeObjects:[self contentArray]]];
if ([self preservesSelection])
[self __setSelectedObjects:oldSelectedObjects];
else
[self __setSelectionIndexes:oldSelectionIndexes];
}
- (void)__setArrangedObjects:(id)value
{
if (_arrangedObjects === value)
return;
_arrangedObjects = [[_CPObservableArray alloc] initWithArray:value];
}
- (id)arrangedObjects
{
return _arrangedObjects;
}
- (CPArray)sortDescriptors
{
return _sortDescriptors;
}
- (void)setSortDescriptors:(CPArray)value
{
if (_sortDescriptors === value)
return;
_sortDescriptors = [value copy];
// Use the non-notification version since arrangedObjects already depends
// on sortDescriptors.
[self _rearrangeObjects];
}
- (CPPredicate)filterPredicate
{
return _filterPredicate;
}
- (void)setFilterPredicate:(CPPredicate)value
{
[self __setFilterPredicate:value];
}
/*
Like setFilterPredicate but don't fire any change notifications.
@ignore
*/
- (void)__setFilterPredicate:(CPPredicate)value
{
if (_filterPredicate === value)
return;
_filterPredicate = value;
// Use the non-notification version since arrangedObjects already depends
// on filterPredicate.
[self _rearrangeObjects];
}
- (BOOL)alwaysUsesMultipleValuesMarker
{
return _alwaysUsesMultipleValuesMarker;
}
//Selection
- (unsigned)selectionIndex
{
return [_selectionIndexes firstIndex];
}
- (BOOL)setSelectionIndex:(unsigned)index
{
return [self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
}
- (CPIndexSet)selectionIndexes
{
return _selectionIndexes;
}
- (BOOL)setSelectionIndexes:(CPIndexSet)indexes
{
[self _selectionWillChange]
[self __setSelectionIndexes:indexes];
[self _selectionDidChange];
}
/*
Like setSelectionIndex but don't fire any change notifications.
@ignore
*/
- (BOOL)__setSelectionIndex:(int)theIndex
{
[self __setSelectionIndexes:[CPIndexSet indexSetWithIndex:theIndex]];
}
/*
Like setSelectionIndexes but don't fire any change notifications.
@ignore
*/
- (BOOL)__setSelectionIndexes:(CPIndexSet)indexes
{
if (!indexes)
indexes = [CPIndexSet indexSet];
if (![indexes count])
{
if (_avoidsEmptySelection && [[self arrangedObjects] count])
indexes = [CPIndexSet indexSetWithIndex:0];
}
else
{
var objectsCount = [[self arrangedObjects] count];
// Remove out of bounds indexes.
[indexes removeIndexesInRange:CPMakeRange(objectsCount, [indexes lastIndex] + 1)];
// When avoiding empty selection and the deleted selection was at the bottom, select the last item.
if (![indexes count] && _avoidsEmptySelection && objectsCount)
indexes = [CPIndexSet indexSetWithIndex:objectsCount - 1];
}
if ([_selectionIndexes isEqualToIndexSet:indexes])
return NO;
_selectionIndexes = [indexes copy];
// Push back the new selection to the model for selectionIndexes if we have one.
// There won't be an infinite loop because of the equality check above.
[[CPKeyValueBinding getBinding:@"selectionIndexes" forObject:self] reverseSetValueFor:@"selectionIndexes"];
return YES;
}
- (CPArray)selectedObjects
{
var objects = [[self arrangedObjects] objectsAtIndexes:[self selectionIndexes]];
return [_CPObservableArray arrayWithArray:(objects || [])];
}
- (BOOL)setSelectedObjects:(CPArray)objects
{
[self willChangeValueForKey:@"selectionIndexes"];
[self _selectionWillChange];
[self __setSelectedObjects:objects];
[self didChangeValueForKey:@"selectionIndexes"];
[self _selectionDidChange];
}
/*
Like setSelectedObjects but don't fire any change notifications.
@ignore
*/
- (BOOL)__setSelectedObjects:(CPArray)objects
{
var set = [CPIndexSet indexSet],
count = [objects count],
arrangedObjects = [self arrangedObjects];
for (var i = 0; i < count; i++)
{
var index = [arrangedObjects indexOfObject:[objects objectAtIndex:i]];
if (index !== CPNotFound)
[set addIndex:index];
}
[self __setSelectionIndexes:set];
return YES;
}
//Moving selection
- (BOOL)canSelectPrevious
{
return [[self selectionIndexes] firstIndex] > 0
}
- (void)selectPrevious:(id)sender
{
var index = [[self selectionIndexes] firstIndex] - 1;
if (index >= 0)
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
}
- (BOOL)canSelectNext
{
return [[self selectionIndexes] firstIndex] < [[self arrangedObjects] count] - 1;
}
- (void)selectNext:(id)sender
{
var index = [[self selectionIndexes] firstIndex] + 1;
if (index < [[self arrangedObjects] count])
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
}
//Add/Remove
- (void)addObject:(id)object
{
if (![self canAdd])
return;
if (_clearsFilterPredicateOnInsertion)
[self willChangeValueForKey:@"filterPredicate"];
[self willChangeValueForKey:@"content"];
[_contentObject addObject:object];
if (_clearsFilterPredicateOnInsertion)
[self __setFilterPredicate:nil];
if (_filterPredicate === nil || [_filterPredicate evaluateWithObject:object])
{
var pos = [_arrangedObjects insertObject:object inArraySortedByDescriptors:_sortDescriptors];
// selectionIndexes change notification will be fired as a result of the
// content change. Don't fire manually.
if (_selectsInsertedObjects)
[self __setSelectionIndex:pos];
else
[_selectionIndexes shiftIndexesStartingAtIndex:pos by:1];
}
else
[self _rearrangeObjects];
[self didChangeValueForKey:@"content"];
if (_clearsFilterPredicateOnInsertion)
[self didChangeValueForKey:@"filterPredicate"];
}
- (void)insertObject:(id)anObject atArrangedObjectIndex:(int)anIndex
{
if (![self canAdd])
return;
if (_clearsFilterPredicateOnInsertion)
[self willChangeValueForKey:@"filterPredicate"];
[self willChangeValueForKey:@"content"];
[_contentObject insertObject:anObject atIndex:anIndex];
if (_clearsFilterPredicateOnInsertion)
[self __setFilterPredicate:nil];
[[self arrangedObjects] insertObject:anObject atIndex:anIndex];
// selectionIndexes change notification will be fired as a result of the
// content change. Don't fire manually.
if ([self selectsInsertedObjects])
[self __setSelectionIndex:anIndex];
else
[[self selectionIndexes] shiftIndexesStartingAtIndex:anIndex by:1];
if ([self avoidsEmptySelection] && [[self selectionIndexes] count] <= 0 && [_contentObject count] > 0)
[self __setSelectionIndexes:[CPIndexSet indexSetWithIndex:0]];
[self didChangeValueForKey:@"content"];
if (_clearsFilterPredicateOnInsertion)
[self didChangeValueForKey:@"filterPredicate"];
}
- (void)removeObject:(id)object
{
if (![self canRemove])
return;
[self willChangeValueForKey:@"content"];
[_contentObject removeObject:object];
if (_filterPredicate === nil || [_filterPredicate evaluateWithObject:object])
{
// selectionIndexes change notification will be fired as a result of the
// content change. Don't fire manually.
var pos = [_arrangedObjects indexOfObject:object];
[_arrangedObjects removeObjectAtIndex:pos];
[_selectionIndexes shiftIndexesStartingAtIndex:pos by:-1];
}
[self didChangeValueForKey:@"content"];
}
- (void)add:(id)sender
{
if (![self canAdd])
return;
[self insert:sender];
}
- (void)insert:(id)sender
{
if (![self canInsert])
return;
var newObject = [self automaticallyPreparesContent] ? [self newObject] : [self _defaultNewObject];
[self addObject:newObject];
}
- (void)remove:(id)sender
{
[self removeObjects:[[self arrangedObjects] objectsAtIndexes:[self selectionIndexes]]];
}
- (void)removeObjectsAtArrangedObjectIndexes:(CPIndexSet)indexes
{
[self _removeObjects:[[self arrangedObjects] objectsAtIndexes:indexes]];
}
- (void)addObjects:(CPArray)objects
{
if (![self canAdd])
return;
var contentArray = [self contentArray],
count = [objects count];
for (var i = 0; i < count; i++)
[contentArray addObject:[objects objectAtIndex:i]];
[self setContent:contentArray];
}
- (void)removeObjects:(CPArray)objects
{
if (![self canRemove])
return;
[self _removeObjects:objects];
}
- (void)_removeObjects:(CPArray)objects
{
[self willChangeValueForKey:@"content"];
[_contentObject removeObjectsInArray:objects];
var arrangedObjects = [self arrangedObjects],
position = [arrangedObjects indexOfObject:[objects objectAtIndex:0]];
[arrangedObjects removeObjectsInArray:objects];
var objectsCount = [arrangedObjects count],
selectionIndexes = [CPIndexSet indexSet];
if ([self preservesSelection] || [self avoidsEmptySelection])
{
selectionIndexes = [CPIndexSet indexSetWithIndex:position];
// Remove the selection if there are no objects
if (objectsCount <= 0)
selectionIndexes = [CPIndexSet indexSet];
// Shift selection to last object if position is out of bounds
else if (position >= objectsCount)
selectionIndexes = [CPIndexSet indexSetWithIndex:objectsCount - 1];
}
_selectionIndexes = selectionIndexes;
[self didChangeValueForKey:@"content"];
}
- (BOOL)canInsert
{
return [self isEditable];
}
@end
@implementation CPArrayController (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:coder];
if (self)
{
_avoidsEmptySelection = [coder decodeBoolForKey:@"CPArrayControllerAvoidsEmptySelection"];
_clearsFilterPredicateOnInsertion = [coder decodeBoolForKey:@"CPClearsFilterPredicateOnInsertion"];
_filterRestrictsInsertion = [coder decodeBoolForKey:@"CPArrayControllerFilterRestrictsInsertion"];
_preservesSelection = [coder decodeBoolForKey:@"CPArrayControllerPreservesSelection"];
_selectsInsertedObjects = [coder decodeBoolForKey:@"CPArrayControllerSelectsInsertedObjects"];
_alwaysUsesMultipleValuesMarker = [coder decodeBoolForKey:@"CPArrayControllerAlwaysUsesMultipleValuesMarker"];
if ([self automaticallyPreparesContent])
[self prepareContent];
else
[self _setContentArray:[]];
}
return self;
}
- (void)awakeFromCib
{
[self _selectionWillChange];
[self _selectionDidChange];
}
@end
+10 -11
View File
@@ -4,7 +4,7 @@
* Created by Ross Boucher.
* Copyright 2009, 280 North, Inc.
*
* Adapted from Kevin Wojniak, portions Copyright 2009 Kevin Wojniak.
* Adapted from Kevin Wojniak, portions Copyright 2009 Kevin Wojniak.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -20,27 +20,26 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright 2009 280 North, Inc.
*/
@import <AppKit/CPGraphicsContext.j>
@import <Foundation/CPObject.j>
@import "CPGraphicsContext.j"
// Class defaults
var DefaultLineWidth = 1.0;
/*!
/*!
@ingroup appkit
@class CPBezierPath
A CPBezierPath allows you to create paths for drawing to the screen using a simpler API than CoreGraphics.
Paths can form any shape, including regular polgyons like squares and triangles; circles, arcs; or complex
line segments.
line segments.
A path can be stroked and filled using the relevant method. The currently active fill and stroke color will
be used, which can be set by calling setFill: and setStroke: on any CPColor object (or set: for both).
*/
@@ -65,9 +64,9 @@ var DefaultLineWidth = 1.0;
+ (CPBezierPath)bezierPathWithOvalInRect:(CGRect)rect
{
var path = [self bezierPath];
[path appendBezierPathWithOvalInRect:rect];
return path;
}
@@ -77,9 +76,9 @@ var DefaultLineWidth = 1.0;
+ (CPBezierPath)bezierPathWithRect:(CGRect)rect
{
var path = [self bezierPath];
[path appendBezierPathWithRect:rect];
return path;
}
+53 -177
View File
@@ -19,33 +19,25 @@
* 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 "CPView.j"
// CPBoxType
CPBoxPrimary = 0;
CPBoxSecondary = 1;
CPBoxSeperator = 2;
CPBoxOldStyle = 3;
CPBoxCustom = 4;
// CPBorderType
CPNoBorder = 0;
CPLineBorder = 1;
CPLineBorder = 1;
CPBezelBorder = 2;
CPGrooveBorder = 3;
@implementation CPBox : CPView
{
CPBoxType _boxType;
CPBorderType _borderType;
CPColor _borderColor;
CPColor _fillColor;
float _cornerRadius;
float _borderWidth;
CPSize _contentMargin;
CPView _contentView;
}
@@ -58,19 +50,18 @@ CPGrooveBorder = 3;
[box setFrameFromContentFrame:[aView frame]];
[enclosingView replaceSubview:aView with:box];
[box setContentView:aView];
return box;
}
- (id)initWithFrame:(CPRect)frameRect
{
self = [super initWithFrame:frameRect];
if (self)
{
_borderType = CPBezelBorder;
_fillColor = [CPColor clearColor];
_borderColor = [CPColor blackColor];
@@ -78,9 +69,7 @@ CPGrooveBorder = 3;
_contentMargin = CGSizeMake(0.0, 0.0);
_contentView = [[CPView alloc] initWithFrame:[self bounds]];
[_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[self setAutoresizesSubviews:YES];
[self addSubview:_contentView];
}
@@ -99,26 +88,9 @@ CPGrooveBorder = 3;
return _borderType;
}
- (void)setBorderType:(CPBorderType)aBorderType
- (void)setBorderType:(CPBorderType)value
{
if (_borderType === aBorderType)
return;
_borderType = aBorderType;
[self setNeedsDisplay:YES];
}
- (CPBoxType)boxType
{
return _boxType;
}
- (void)setBoxType:(CPBoxType)aBoxType
{
if (_boxType === aBoxType)
return;
_boxType = aBoxType;
_borderType = value;
[self setNeedsDisplay:YES];
}
@@ -189,10 +161,9 @@ CPGrooveBorder = 3;
return;
[aView setFrame:CGRectInset([self bounds], _contentMargin.width + _borderWidth, _contentMargin.height + _borderWidth)];
[aView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[self replaceSubview:_contentView with:aView];
_contentView = aView;
_contentView = aView;
}
- (CPSize)contentViewMargins
@@ -202,9 +173,9 @@ CPGrooveBorder = 3;
- (void)setContentViewMargins:(CPSize)size
{
if (size.width < 0 || size.height < 0)
if(size.width < 0 || size.height < 0)
[CPException raise:CPGenericException reason:@"Margins must be positive"];
_contentMargin = CGSizeMakeCopy(size);
[self setNeedsDisplay:YES];
}
@@ -218,151 +189,56 @@ CPGrooveBorder = 3;
- (void)sizeToFit
{
var contentFrame = [_contentView frame];
[self setFrameSize:CGSizeMake(contentFrame.size.width + _contentMargin.width * 2,
[self setFrameSize:CGSizeMake(contentFrame.size.width + _contentMargin.width * 2,
contentFrame.size.height + _contentMargin.height * 2)];
[_contentView setFrameOrigin:CGPointMake(_contentMargin.width, _contentMargin.height)];
}
- (void)drawRect:(CPRect)rect
{
if (_borderType === CPNoBorder)
return;
var bounds = [self bounds],
aContext = [[CPGraphicsContext currentContext] graphicsPort],
border2 = _borderWidth/2,
var bounds = [self bounds];
strokeRect = CGRectMake(bounds.origin.x + border2,
bounds.origin.y + border2,
bounds.size.width - _borderWidth,
bounds.size.height - _borderWidth),
fillRect = CGRectMake(bounds.origin.x + border2,
bounds.origin.y + border2,
bounds.size.width - _borderWidth,
bounds.size.height - _borderWidth);
switch (_boxType)
CGContextSetFillColor(aContext, [self fillColor]);
CGContextSetStrokeColor(aContext, [self borderColor]);
CGContextSetLineWidth(aContext, _borderWidth);
switch(_borderType)
{
case CPBoxSeperator:
// NSBox does not include a horitontal flag for the seperator type. We have to determine
// the type of seperator to draw by the width and height of the frame.
if (CGRectGetWidth(bounds) === 5.0)
return [self _drawVerticalSeperatorInRect:bounds];
else if (CGRectGetHeight(bounds) === 5.0)
return [self _drawHorizontalSeperatorInRect:bounds];
case CPLineBorder: CGContextFillRoundedRectangleInRect(aContext, fillRect, _cornerRadius, YES, YES, YES, YES);
CGContextStrokeRoundedRectangleInRect(aContext, strokeRect, _cornerRadius, YES, YES, YES, YES);
break;
break;
case CPBezelBorder: CGContextFillRoundedRectangleInRect(aContext, fillRect, _cornerRadius, YES, YES, YES, YES);
CGContextSetStrokeColor(aContext, [CPColor colorWithWhite:190.0/255.0 alpha:1.0]);
CGContextBeginPath(aContext);
CGContextMoveToPoint(aContext, strokeRect.origin.x, strokeRect.origin.y);
CGContextAddLineToPoint(aContext, CGRectGetMinX(strokeRect), CGRectGetMaxY(strokeRect)),
CGContextAddLineToPoint(aContext, CGRectGetMaxX(strokeRect), CGRectGetMaxY(strokeRect)),
CGContextAddLineToPoint(aContext, CGRectGetMaxX(strokeRect), CGRectGetMinY(strokeRect)),
CGContextStrokePath(aContext);
CGContextSetStrokeColor(aContext, [CPColor colorWithWhite:142.0/255.0 alpha:1.0]);
CGContextBeginPath(aContext);
CGContextMoveToPoint(aContext, bounds.origin.x, strokeRect.origin.y);
CGContextAddLineToPoint(aContext, CGRectGetMaxX(bounds), CGRectGetMinY(strokeRect));
CGContextStrokePath(aContext);
break;
default: break;
}
switch (_borderType)
{
case CPBezelBorder:
[self _drawBezelBorderInRect:bounds];
break;
default:
case CPLineBorder:
[self _drawLineBorderInRect:bounds];
break;
}
}
- (void)_drawHorizontalSeperatorInRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSetStrokeColor(context, [self borderColor]);
CGContextSetLineWidth(context, 1.0);
CGContextMoveToPoint(context, CGRectGetMinX(aRect), CGRectGetMinY(aRect));
CGContextAddLineToPoint(context, CGRectGetWidth(aRect), CGRectGetMinY(aRect));
CGContextStrokePath(context);
}
- (void)_drawVerticalSeperatorInRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSetStrokeColor(context, [self borderColor]);
CGContextSetLineWidth(context, 1.0);
CGContextMoveToPoint(context, CGRectGetMinX(aRect), CGRectGetMinY(aRect));
CGContextAddLineToPoint(context, CGRectGetMinX(aRect), CGRectGetHeight(aRect));
CGContextStrokePath(context);
}
- (void)_drawBezelBorderInRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort],
sides = [CPMinYEdge, CPMaxXEdge, CPMaxYEdge, CPMinXEdge],
sideGray = 190.0 / 255.0,
grays = [142.0 / 255.0, sideGray, sideGray, sideGray],
borderWidth = _borderWidth;
while (borderWidth--)
aRect = CPDrawTiledRects(aRect, aRect, sides, grays);
CGContextSetFillColor(context, [self fillColor]);
CGContextFillRect(context, aRect);
}
- (void)_drawLineBorderInRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort];
aRect = CGRectInset(aRect, _borderWidth / 2.0, _borderWidth / 2.0);
CGContextSetFillColor(context, [self fillColor]);
CGContextSetStrokeColor(context, [self borderColor]);
CGContextSetLineWidth(context, _borderWidth);
CGContextFillRoundedRectangleInRect(context, aRect, _cornerRadius, YES, YES, YES, YES);
CGContextStrokeRoundedRectangleInRect(context, aRect, _cornerRadius, YES, YES, YES, YES);
}
@end
var CPBoxTypeKey = @"CPBoxTypeKey",
CPBoxBorderTypeKey = @"CPBoxBorderTypeKey",
CPBoxBorderColorKey = @"CPBoxBorderColorKey",
CPBoxFillColorKey = @"CPBoxFillColorKey",
CPBoxCornerRadiusKey = @"CPBoxCornerRadiusKey",
CPBoxBorderWidthKey = @"CPBoxBorderWidthKey",
CPBoxContentMarginKey = @"CPBoxContentMarginKey";
@implementation CPBox (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
_boxType = [aCoder decodeIntForKey:CPBoxTypeKey];
_borderType = [aCoder decodeIntForKey:CPBoxBorderTypeKey];
_borderColor = [aCoder decodeObjectForKey:CPBoxBorderColorKey];
_fillColor = [aCoder decodeObjectForKey:CPBoxFillColorKey];
_cornerRadius = [aCoder decodeFloatForKey:CPBoxCornerRadiusKey];
_borderWidth = [aCoder decodeFloatForKey:CPBoxBorderWidthKey];
_contentMargin = [aCoder decodeSizeForKey:CPBoxContentMarginKey];
_contentView = [self subviews][0];
[self setAutoresizesSubviews:YES];
[_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeInt:_boxType forKey:CPBoxTypeKey];
[aCoder encodeInt:_borderType forKey:CPBoxBorderTypeKey];
[aCoder encodeObject:_borderColor forKey:CPBoxBorderColorKey];
[aCoder encodeObject:_fillColor forKey:CPBoxFillColorKey];
[aCoder encodeFloat:_cornerRadius forKey:CPBoxCornerRadiusKey];
[aCoder encodeFloat:_borderWidth forKey:CPBoxBorderWidthKey];
[aCoder encodeSize:_contentMargin forKey:CPBoxContentMarginKey];
}
@end
+26 -29
View File
@@ -20,17 +20,14 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPIndexSet.j>
@import "CPControl.j"
@import "CPImage.j"
@import "CPTableView.j"
@import "CPTextField.j"
@import "CPScrollView.j"
/*!
/*!
@ingroup appkit
@class CPBrowser
@class CPBrowser
*/
@implementation CPBrowser : CPControl
@@ -67,14 +64,14 @@
+ (CPImage)branchImage
{
return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPBrowser class]]
return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPBrowser class]]
pathForResource:"browser-leaf.png"]
size:CGSizeMake(9,9)];
}
+ (CPImage)highlightedBranchImage
{
return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPBrowser class]]
return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPBrowser class]]
pathForResource:"browser-leaf-highlighted.png"]
size:CGSizeMake(9,9)];
}
@@ -99,18 +96,18 @@
_prototypeView = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[_prototypeView setVerticalAlignment:CPCenterVerticalTextAlignment];
[_prototypeView setValue:[CPColor whiteColor] forThemeAttribute:"text-color" inState:CPThemeStateSelectedDataView];
[_prototypeView setValue:[CPColor whiteColor] forThemeAttribute:"text-color" inState:CPThemeStateSelected];
[_prototypeView setLineBreakMode:CPLineBreakByTruncatingTail];
_horizontalScrollView = [[CPScrollView alloc] initWithFrame:[self bounds]];
[_horizontalScrollView setHasVerticalScroller:NO];
[_horizontalScrollView setAutohidesScrollers:YES];
[_horizontalScrollView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[_horizontalScrollView setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
_contentView = [[CPView alloc] initWithFrame:CGRectMake(0, 0, 0, CGRectGetHeight([self bounds]))];
[_contentView setAutoresizingMask:CPViewHeightSizable];
[_horizontalScrollView setDocumentView:_contentView];
[self addSubview:_horizontalScrollView];
@@ -132,7 +129,7 @@
}
- (void)setDelegate:(id)anObject
{
{
_delegate = anObject;
_delegateSupportsImages = [_delegate respondsToSelector:@selector(browser:imageValueForItem:)];
@@ -170,10 +167,12 @@
if (columnIndex >= _tableViews.length)
return;
var oldValue = _tableViews.length - 1,
indexPlusOne = columnIndex + 1; // unloads all later columns.
var oldValue = _tableViews.length - 1;
[[_tableViews.slice(indexPlusOne) valueForKey:"enclosingScrollView"]
// unloads all later columns.
var indexPlusOne = columnIndex + 1;
[[_tableViews.slice(indexPlusOne) valueForKey:"enclosingScrollView"]
makeObjectsPerformSelector:@selector(removeFromSuperview)];
_tableViews = _tableViews.slice(0, indexPlusOne);
@@ -197,10 +196,10 @@
selectionIndexes = [lastColumn selectedRowIndexes];
if (lastIndex >= 0 && [selectionIndexes count] > 1)
[CPException raise:CPInvalidArgumentException
[CPException raise:CPInvalidArgumentException
reason:"Can't add column, column "+lastIndex+" has invalid selection."];
var index = lastIndex + 1,
var index = lastIndex+1,
item = index === 0 ? _rootItem : [_tableDelegates[lastIndex] childAtIndex:[selectionIndexes firstIndex]];
if (index > 0 && item && [self isLeafItem:item])
@@ -232,7 +231,7 @@
[table setAction:@selector(_tableViewClicked:)];
[table setDoubleAction:@selector(_tableViewDoubleClicked:)];
[table setDraggingDestinationFeedbackStyle:CPTableViewDraggingDestinationFeedbackStyleRegular];
var scrollView = [[_CPBrowserScrollView alloc] initWithFrame:CGRectMakeZero()];
[scrollView _setBrowser:self];
[scrollView setDocumentView:table];
@@ -273,10 +272,10 @@
[view setBranchImage:[[self class] branchImage]];
[view setHighlightedBranchImage:[[self class] highlightedBranchImage]];
[column setDataView:view];
[column setResizingMask:CPTableColumnNoResizing];
[aTableView addTableColumn:column];
}
@@ -498,7 +497,7 @@
[_contentView scrollRectToVisible:[[[self tableViewInColumn:columnIndex] enclosingScrollView] frame]];
}
- (void)scrollRowToVisible:(unsigned)rowIndex inColumn:(unsigned)columnIndex
(void)scrollRowToVisible:(unsigned)rowIndex inColumn:(unsigned)columnIndex
{
[self scrollColumnToVisible:columnIndex];
[[self tableViewInColumn:columnIndex] scrollRowToVisible:rowIndex];
@@ -585,7 +584,7 @@
if ([_delegate respondsToSelector:@selector(browser:selectionIndexesForProposedSelection:inColumn:)])
indexSet = [_delegate browser:self selectionIndexesForProposedSelection:indexSet inColumn:column];
if ([_delegate respondsToSelector:@selector(browser:shouldSelectRowIndexes:inColumn:)] &&
if ([_delegate respondsToSelector:@selector(browser:shouldSelectRowIndexes:inColumn:)] &&
![_delegate browser:self shouldSelectRowIndexes:indexSet inColumn:column])
return;
@@ -797,7 +796,7 @@ var _CPBrowserResizeControlBackgroundImage = nil;
}
- (void)moveLeft:(id)sender
{
{
var previousColumn = [_browser selectedColumn] - 1,
selectedRow = [_browser selectedRowInColumn:previousColumn];
@@ -805,14 +804,12 @@ var _CPBrowserResizeControlBackgroundImage = nil;
}
- (void)moveRight:(id)sender
{
{
[_browser selectRow:0 inColumn:[_browser selectedColumn] + 1];
}
@end
@import <Foundation/CPObject.j>
@implementation _CPBrowserTableDelegate : CPObject
{
CPBrowser _browser @accessors;
@@ -863,7 +860,7 @@ var _CPBrowserResizeControlBackgroundImage = nil;
- (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id)info proposedRow:(int)row proposedDropOperation:(CPTableViewDropOperation)operation
{
if ([_delegate respondsToSelector:@selector(browser:validateDrop:proposedRow:column:dropOperation:)])
return [_delegate browser:_browser validateDrop:info proposedRow:row column:_index dropOperation:operation];
[_delegate browser:_browser validateDrop:info proposedRow:row column:_index dropOperation:operation];
else
return CPDragOperationNone;
}
@@ -924,9 +921,9 @@ var _CPBrowserResizeControlBackgroundImage = nil;
{
var imageView = [self layoutEphemeralSubviewNamed:@"image-view"
positioned:CPWindowAbove
relativeToEphemeralSubviewNamed:nil],
isHighlighted = [self themeState] & CPThemeStateSelectedDataView;
relativeToEphemeralSubviewNamed:nil];
var isHighlighted = [self themeState] & CPThemeStateSelected;
[imageView setImage: _isLeaf ? (isHighlighted ? _highlightedBranchImage : _branchImage) : nil];
[imageView setImageScaling:CPScaleNone];
}
+69 -173
View File
@@ -26,6 +26,8 @@
@import "CPControl.j"
@import "CPStringDrawing.j"
#include "CoreGraphics/CGGeometry.h"
/* @group CPBezelStyle */
@@ -72,10 +74,7 @@ CPChangeBackgroundCellMask = CPBackgroundButtonMask;
CPButtonStateMixed = CPThemeState("mixed");
CPButtonDefaultHeight = 24.0;
CPButtonImageOffset = 3.0;
/*!
/*!
@ingroup appkit
@class CPButton
@@ -86,9 +85,12 @@ CPButtonImageOffset = 3.0;
@implementation CPButton : CPControl
{
BOOL _allowsMixedState;
CPString _title;
CPString _alternateTitle;
CPImage _image;
CPImage _alternateImage;
CPInteger _showsStateBy;
CPInteger _highlightsBy;
@@ -97,9 +99,6 @@ CPButtonImageOffset = 3.0;
// NS-style Display Properties
CPBezelStyle _bezelStyle;
CPControlSize _controlSize;
CPString _keyEquivalent;
unsigned _keyEquivalentModifierMask;
}
+ (id)buttonWithTitle:(CPString)aTitle
@@ -118,21 +117,21 @@ CPButtonImageOffset = 3.0;
return button;
}
+ (CPString)defaultThemeClass
+ (CPString)themeClass
{
return @"button";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[[CPNull null], 0.0, _CGInsetMakeZero(), _CGInsetMakeZero(), [CPNull null]]
forKeys:[@"image", @"image-offset", @"bezel-inset", @"content-inset", @"bezel-color"]];
return [CPDictionary dictionaryWithObjects:[_CGInsetMakeZero(), _CGInsetMakeZero(), [CPNull null]]
forKeys:[@"bezel-inset", @"content-inset", @"bezel-color"]];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
// Should we instead override the defaults?
@@ -140,16 +139,13 @@ CPButtonImageOffset = 3.0;
[self setValue:CPCenterVerticalTextAlignment forThemeAttribute:@"vertical-alignment"];
[self setValue:CPImageLeft forThemeAttribute:@"image-position"];
[self setValue:CPScaleNone forThemeAttribute:@"image-scaling"];
_controlSize = CPRegularControlSize;
_keyEquivalent = @"";
_keyEquivalentModifierMask = 0;
// [self setBezelStyle:CPRoundRectBezelStyle];
[self setBordered:YES];
}
return self;
}
@@ -252,9 +248,9 @@ CPButtonImageOffset = 3.0;
{
if (_title === aTitle)
return;
_title = aTitle;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
@@ -268,7 +264,7 @@ CPButtonImageOffset = 3.0;
{
if (_alternateTitle === aTitle)
return;
_alternateTitle = aTitle;
[self setNeedsLayout];
@@ -282,12 +278,18 @@ CPButtonImageOffset = 3.0;
- (void)setImage:(CPImage)anImage
{
[self setValue:anImage forThemeAttribute:@"image"];
if (_image === anImage)
return;
_image = anImage;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
- (CPImage)image
{
return [self valueForThemeAttribute:@"image" inState:CPThemeStateNormal];
return _image;
}
/*!
@@ -296,7 +298,13 @@ CPButtonImageOffset = 3.0;
*/
- (void)setAlternateImage:(CPImage)anImage
{
[self setValue:anImage forThemeAttribute:@"image" inState:CPThemeStateHighlighted];
if (_alternateImage === anImage)
return;
_alternateImage = anImage;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
/*!
@@ -304,17 +312,7 @@ CPButtonImageOffset = 3.0;
*/
- (CPImage)alternateImage
{
return [self valueForThemeAttribute:@"image" inState:CPThemeStateHighlighted];
}
- (void)setImageOffset:(float)theImageOffset
{
[self setValue:theImageOffset forThemeAttribute:@"image-offset"];
}
- (float)imageOffset
{
return [self valueForThemeAttribute:@"image-offset"];
return _alternateImage;
}
- (void)setShowsStateBy:(CPInteger)aMask
@@ -375,13 +373,13 @@ CPButtonImageOffset = 3.0;
[self setShowsStateBy:CPContentsCellMask];
break;
case CPSwitchButton: [CPException raise:CPInvalidArgumentException
case CPSwitchButton: [CPException raise:CPInvalidArgumentException
reason:"The CPSwitchButton type is not supported in Cappuccino, use the CPCheckBox class instead."];
case CPRadioButton: [CPException raise:CPInvalidArgumentException
case CPRadioButton: [CPException raise:CPInvalidArgumentException
reason:"The CPRadioButton type is not supported in Cappuccino, use the CPRadio class instead."];
default: [CPException raise:CPInvalidArgumentException
default: [CPException raise:CPInvalidArgumentException
reason:"Unknown button type."];
}
@@ -397,7 +395,7 @@ CPButtonImageOffset = 3.0;
_imageDimsWhenDisabled = imageShouldDimWhenDisabled;
if ([self hasThemeState:CPThemeStateDisabled])
if (_imageDimsWhenDisabled)
{
[self setNeedsDisplay:YES];
[self setNeedsLayout];
@@ -412,7 +410,7 @@ CPButtonImageOffset = 3.0;
- (BOOL)startTrackingAt:(CGPoint)aPoint
{
[self highlight:YES];
return [super startTrackingAt:aPoint];
}
@@ -433,12 +431,11 @@ CPButtonImageOffset = 3.0;
if (_CGInsetIsEmpty(contentInset))
return bounds;
bounds = _CGRectMakeCopy(bounds);
bounds.origin.x += contentInset.left;
bounds.origin.y += contentInset.top;
bounds.size.width -= contentInset.left + contentInset.right;
bounds.size.height -= contentInset.top + contentInset.bottom;
return bounds;
}
@@ -452,7 +449,6 @@ CPButtonImageOffset = 3.0;
if (_CGInsetIsEmpty(bezelInset))
return bounds;
bounds = _CGRectMakeCopy(bounds);
bounds.origin.x += bezelInset.left;
bounds.origin.y += bezelInset.top;
bounds.size.width -= bezelInset.left + bezelInset.right;
@@ -466,20 +462,8 @@ CPButtonImageOffset = 3.0;
*/
- (void)sizeToFit
{
[self layoutSubviews];
var size,
contentView = [self ephemeralSubviewNamed:@"content-view"];
if (contentView)
{
[contentView sizeToFit];
size = [contentView frameSize];
}
else
size = [([self title] || " ") sizeWithFont:[self currentValueForThemeAttribute:@"font"]];
var contentInset = [self currentValueForThemeAttribute:@"content-inset"],
var size = [([self title] || " ") sizeWithFont:[self currentValueForThemeAttribute:@"font"]],
contentInset = [self currentValueForThemeAttribute:@"content-inset"],
minSize = [self currentValueForThemeAttribute:@"min-size"],
maxSize = [self currentValueForThemeAttribute:@"max-size"];
@@ -499,10 +483,10 @@ CPButtonImageOffset = 3.0;
{
if (aName === "bezel-view")
return [self bezelRectForBounds:[self bounds]];
else if (aName === "content-view")
return [self contentRectForBounds:[self bounds]];
return [super rectForEphemeralSubviewNamed:aName];
}
@@ -513,7 +497,7 @@ CPButtonImageOffset = 3.0;
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
[view setHitTests:NO];
return view;
}
else
@@ -535,8 +519,7 @@ CPButtonImageOffset = 3.0;
if (contentView)
{
[contentView setText:([self hasThemeState:CPThemeStateHighlighted] && _alternateTitle) ? _alternateTitle : _title];
[contentView setImage:[self currentValueForThemeAttribute:@"image"]];
[contentView setImageOffset:[self currentValueForThemeAttribute:@"image-offset"]];
[contentView setImage:([self hasThemeState:CPThemeStateHighlighted] && _alternateImage) ? _alternateImage : _image];
[contentView setFont:[self currentValueForThemeAttribute:@"font"]];
[contentView setTextColor:[self currentValueForThemeAttribute:@"text-color"]];
@@ -551,6 +534,14 @@ CPButtonImageOffset = 3.0;
}
}
- (void)setDefaultButton:(BOOL)shouldBeDefaultButton
{
if (shouldBeDefaultButton)
[self setThemeState:CPThemeStateDefault];
else
[self unsetThemeState:CPThemeStateDefault];
}
- (void)setBordered:(BOOL)shouldBeBordered
{
if (shouldBeBordered)
@@ -564,79 +555,6 @@ CPButtonImageOffset = 3.0;
return [self hasThemeState:CPThemeStateBordered];
}
/*!
Sets the keyboard shortcut for this button. For special keys see
CPEvent.j CP...FunctionKey and CPText.j CP...Character.
@param aString the keyboard shortcut as a string
*/
- (void)setKeyEquivalent:(CPString)aString
{
_keyEquivalent = aString || @"";
// Check if the key equivalent is the enter key
// Treat \r and \n as the same key equivalent. See issue #710.
if (aString === CPNewlineCharacter || aString === CPCarriageReturnCharacter)
[self setThemeState:CPThemeStateDefault];
else
[self unsetThemeState:CPThemeStateDefault];
}
- (void)viewWillMoveToWindow:(CPWindow)aWindow
{
var selfWindow = [self window];
if (selfWindow === aWindow || aWindow === nil)
return;
if ([selfWindow defaultButton] === self)
[selfWindow setDefaultButton:nil];
if ([self keyEquivalent] === CPNewlineCharacter || [self keyEquivalent] === CPCarriageReturnCharacter)
[aWindow setDefaultButton:self];
}
/*!
Returns the keyboard shortcut for this button.
*/
- (CPString)keyEquivalent
{
return _keyEquivalent;
}
/*!
Returns the mask used with this button's key equivalent.
*/
- (void)setKeyEquivalentModifierMask:(unsigned)aMask
{
_keyEquivalentModifierMask = aMask;
}
/*!
Sets the mask to be used with this button's key equivalent.
*/
- (unsigned)keyEquivalentModifierMask
{
return _keyEquivalentModifierMask;
}
/*!
Checks the button's key equivalent against that in the event, and if they
match simulates a button click.
*/
- (BOOL)performKeyEquivalent:(CPEvent)anEvent
{
// Don't handle the key equivalent for the default window because the window will handle it for us
if ([[self window] defaultButton] === self)
return NO;
if (![anEvent _triggersKeyEquivalent:[self keyEquivalent] withModifierMask:[self keyEquivalentModifierMask]])
return NO;
[self performClick:nil];
return YES;
}
@end
@implementation CPButton (NS)
@@ -652,16 +570,11 @@ CPButtonImageOffset = 3.0;
@end
var CPButtonImageKey = @"CPButtonImageKey",
CPButtonAlternateImageKey = @"CPButtonAlternateImageKey",
CPButtonTitleKey = @"CPButtonTitleKey",
CPButtonAlternateTitleKey = @"CPButtonAlternateTitleKey",
CPButtonIsBorderedKey = @"CPButtonIsBorderedKey",
CPButtonAllowsMixedStateKey = @"CPButtonAllowsMixedStateKey",
CPButtonImageDimsWhenDisabledKey = @"CPButtonImageDimsWhenDisabledKey",
CPButtonImagePositionKey = @"CPButtonImagePositionKey",
CPButtonKeyEquivalentKey = @"CPButtonKeyEquivalentKey",
CPButtonKeyEquivalentMaskKey = @"CPButtonKeyEquivalentMaskKey";
var CPButtonImageKey = @"CPButtonImageKey",
CPButtonAlternateImageKey = @"CPButtonAlternateImageKey",
CPButtonTitleKey = @"CPButtonTitleKey",
CPButtonAlternateTitleKey = @"CPButtonAlternateTitleKey",
CPButtonIsBorderedKey = @"CPButtonIsBorderedKey";
@implementation CPButton (CPCoding)
@@ -672,31 +585,21 @@ var CPButtonImageKey = @"CPButtonImageKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
_controlSize = CPRegularControlSize;
_title = [aCoder decodeObjectForKey:CPButtonTitleKey];
_alternateTitle = [aCoder decodeObjectForKey:CPButtonAlternateTitleKey];
if ([aCoder containsValueForKey:CPButtonAllowsMixedStateKey])
_allowsMixedState = [aCoder decodeBoolForKey:CPButtonAllowsMixedStateKey];
[self setImageDimsWhenDisabled:[aCoder decodeObjectForKey:CPButtonImageDimsWhenDisabledKey]];
if ([aCoder containsValueForKey:CPButtonImagePositionKey])
[self setImagePosition:[aCoder decodeIntForKey:CPButtonImagePositionKey]];
if ([aCoder containsValueForKey:CPButtonKeyEquivalentKey])
[self setKeyEquivalent:CFData.decodeBase64ToUtf16String([aCoder decodeObjectForKey:CPButtonKeyEquivalentKey])];
_keyEquivalentModifierMask = [aCoder decodeIntForKey:CPButtonKeyEquivalentMaskKey];
[self setImage:[aCoder decodeObjectForKey:CPButtonImageKey]];
[self setAlternateImage:[aCoder decodeObjectForKey:CPButtonAlternateImageKey]];
[self setTitle:[aCoder decodeObjectForKey:CPButtonTitleKey]];
[self setAlternateTitle:[aCoder decodeObjectForKey:CPButtonAlternateTitleKey]];
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
return self;
}
@@ -708,18 +611,11 @@ var CPButtonImageKey = @"CPButtonImageKey",
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_image forKey:CPButtonImageKey];
[aCoder encodeObject:_alternateImage forKey:CPButtonAlternateImageKey];
[aCoder encodeObject:_title forKey:CPButtonTitleKey];
[aCoder encodeObject:_alternateTitle forKey:CPButtonAlternateTitleKey];
[aCoder encodeBool:_allowsMixedState forKey:CPButtonAllowsMixedStateKey];
[aCoder encodeBool:[self imageDimsWhenDisabled] forKey:CPButtonImageDimsWhenDisabledKey];
[aCoder encodeInt:[self imagePosition] forKey:CPButtonImagePositionKey];
if (_keyEquivalent)
[aCoder encodeObject:CFData.encodeBase64Utf16String(_keyEquivalent) forKey:CPButtonKeyEquivalentKey];
[aCoder encodeInt:_keyEquivalentModifierMask forKey:CPButtonKeyEquivalentMaskKey];
}
@end
+13 -11
View File
@@ -1,5 +1,7 @@
@import "CPView.j"
@import <AppKit/CPView.j>
#include "CoreGraphics/CGGeometry.h"
@implementation CPButtonBar : CPView
@@ -48,7 +50,7 @@
return button;
}
+ (CPString)defaultThemeClass
+ (CPString)themeClass
{
return @"button-bar";
}
@@ -195,12 +197,12 @@
availableWidth = frameWidth - resizeWidth - 1;
for (var i = 0, count = [buttonsNotHidden count]; i < count; i++)
{
{
var button = buttonsNotHidden[i],
width = CGRectGetWidth([button frame]);
if (availableWidth > width)
availableWidth -= width;
availableWidth -=width;
else
break;
@@ -215,15 +217,15 @@
currentButtonOffset += width - 1;
}
[button setValue:normalColor forThemeAttribute:@"bezel-color" inState:CPThemeStateNormal | CPThemeStateBordered];
[button setValue:highlightedColor forThemeAttribute:@"bezel-color" inState:CPThemeStateHighlighted | CPThemeStateBordered];
[button setValue:disabledColor forThemeAttribute:@"bezel-color" inState:CPThemeStateDisabled | CPThemeStateBordered];
[button setValue:textColor forThemeAttribute:@"text-color" inState:CPThemeStateBordered];
[button setValue:normalColor forThemeAttribute:@"bezel-color" inState:CPThemeStateNormal|CPThemeStateBordered];
[button setValue:highlightedColor forThemeAttribute:@"bezel-color" inState:CPThemeStateHighlighted|CPThemeStateBordered];
[button setValue:disabledColor forThemeAttribute:@"bezel-color" inState:CPThemeStateDisabled|CPThemeStateBordered];
[button setValue:textColor forThemeAttribute:@"text-color" inState:CPThemeStateBordered];
// FIXME shouldn't need this
[button setValue:normalColor forThemeAttribute:@"bezel-color" inState:CPThemeStateNormal | CPThemeStateBordered | CPPopUpButtonStatePullsDown];
[button setValue:highlightedColor forThemeAttribute:@"bezel-color" inState:CPThemeStateHighlighted | CPThemeStateBordered | CPPopUpButtonStatePullsDown];
[button setValue:disabledColor forThemeAttribute:@"bezel-color" inState:CPThemeStateDisabled | CPThemeStateBordered | CPPopUpButtonStatePullsDown];
[button setValue:normalColor forThemeAttribute:@"bezel-color" inState:CPThemeStateNormal|CPThemeStateBordered|CPPopUpButtonStatePullsDown];
[button setValue:highlightedColor forThemeAttribute:@"bezel-color" inState:CPThemeStateHighlighted|CPThemeStateBordered|CPPopUpButtonStatePullsDown];
[button setValue:disabledColor forThemeAttribute:@"bezel-color" inState:CPThemeStateDisabled|CPThemeStateBordered|CPPopUpButtonStatePullsDown];
[self addSubview:button];
}
+2 -4
View File
@@ -23,8 +23,6 @@
@import "CPButton.j"
CPCheckBoxImageOffset = 4.0;
@implementation CPCheckBox : CPButton
{
}
@@ -39,7 +37,7 @@ CPCheckBoxImageOffset = 4.0;
return [self buttonWithTitle:aTitle];
}
+ (CPString)defaultThemeClass
+ (CPString)themeClass
{
return @"check-box";
}
@@ -57,7 +55,7 @@ CPCheckBoxImageOffset = 4.0;
[self setImagePosition:CPImageLeft];
[self setAlignment:CPLeftTextAlignment];
[self setBordered:NO];
[self setBordered:YES];
}
return self;
+26 -24
View File
@@ -22,12 +22,14 @@
@import "CPView.j"
#include "CoreGraphics/CGGeometry.h"
/*!
/*!
@ingroup appkit
@class CPClipView
CPClipView allows you to define a clip rect and display only that portion of its containing view.
CPClipView allows you to define a clip rect and display only that portion of its containing view.
It is used to hold the document view in a CPScrollView.
*/
@implementation CPClipView : CPView
@@ -45,7 +47,7 @@
return;
var defaultCenter = [CPNotificationCenter defaultCenter];
if (_documentView)
{
[defaultCenter
@@ -57,29 +59,29 @@
removeObserver:self
name:CPViewBoundsDidChangeNotification
object:_documentView];
[_documentView removeFromSuperview];
}
_documentView = aView;
if (_documentView)
{
[self addSubview:_documentView];
[_documentView setPostsFrameChangedNotifications:YES];
[_documentView setPostsBoundsChangedNotifications:YES];
[_documentView setPostsFrameChangedNotifications:YES];
[_documentView setPostsBoundsChangedNotifications:YES];
[defaultCenter
[defaultCenter
addObserver:self
selector:@selector(viewFrameChanged:)
name:CPViewFrameDidChangeNotification
name:CPViewFrameDidChangeNotification
object:_documentView];
[defaultCenter
[defaultCenter
addObserver:self
selector:@selector(viewBoundsChanged:)
name:CPViewBoundsDidChangeNotification
name:CPViewBoundsDidChangeNotification
object:_documentView];
}
}
@@ -104,7 +106,7 @@
return _CGPointMakeZero();
var documentFrame = [_documentView frame];
aPoint.x = MAX(0.0, MIN(aPoint.x, MAX(_CGRectGetWidth(documentFrame) - _CGRectGetWidth(_bounds), 0.0)));
aPoint.y = MAX(0.0, MIN(aPoint.y, MAX(_CGRectGetHeight(documentFrame) - _CGRectGetHeight(_bounds), 0.0)));
@@ -115,7 +117,7 @@
{
if (_CGPointEqualToPoint(_bounds.origin, aPoint))
return;
[super setBoundsOrigin:aPoint];
var superview = [self superview],
@@ -124,7 +126,7 @@
// FIXME: Should CPScrollView be finding out about this on its own somehow?
scrollViewClass = objj_getClass("CPScrollView");
if ([superview isKindOfClass:scrollViewClass])
if([superview isKindOfClass:scrollViewClass])
[superview reflectScrolledClipView:self];
}
@@ -164,12 +166,12 @@
- (void)_constrainScrollPoint
{
var oldScrollPoint = [self bounds].origin;
// Call scrollToPoint: because the current scroll point may no longer make
// Call scrollToPoint: because the current scroll point may no longer make
// sense given the new frame of the document view.
[self scrollToPoint:oldScrollPoint];
// scrollToPoint: takes care of reflectScrollClipView: for us, so bail if
// scrollToPoint: takes care of reflectScrollClipView: for us, so bail if
// the scroll points are not equal (meaning scrollToPoint: didn't early bail).
if (!CGPointEqualToPoint(oldScrollPoint, [self bounds].origin))
return;
@@ -185,7 +187,7 @@
[superview reflectScrolledClipView:self];
}
- (BOOL)autoscroll:(CPEvent)anEvent
- (BOOL)autoscroll:(CPEvent)anEvent
{
var bounds = [self bounds],
eventLocation = [self convertPoint:[anEvent locationInWindow] fromView:nil],
@@ -220,7 +222,7 @@
deltaX = bounds.size.width;
}
return [self scrollToPoint:CGPointMake(bounds.origin.x - deltaX, bounds.origin.y - deltaY)];
return [self scrollToPoint:CGPointMake(bounds.origin.x - deltaX, bounds.origin.y - deltaY)];
}
@end
@@ -234,14 +236,14 @@ var CPClipViewDocumentViewKey = @"CPScrollViewDocumentView";
{
if (self = [super initWithCoder:aCoder])
[self setDocumentView:[aCoder decodeObjectForKey:CPClipViewDocumentViewKey]];
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_documentView forKey:CPClipViewDocumentViewKey];
}
+24 -103
View File
@@ -297,7 +297,7 @@
*/
- (void)setSelectionIndexes:(CPIndexSet)anIndexSet
{
if ([_selectionIndexes isEqual:anIndexSet] || !_isSelectable)
if (_selectionIndexes == anIndexSet || !_isSelectable)
return;
var index = CPNotFound;
@@ -312,10 +312,8 @@
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
[_items[index] setSelected:YES];
[[CPKeyValueBinding getBinding:@"selectionIndexes" forObject:self] reverseSetValueFor:@"selectionIndexes"];
if ([_delegate respondsToSelector:@selector(collectionViewDidChangeSelection:)])
[_delegate collectionViewDidChangeSelection:self];
[_delegate collectionViewDidChangeSelection:self]
}
/*!
@@ -593,37 +591,8 @@
index = row * _numberOfColumns + column;
if (index >= 0 && index < _items.length)
{
if (_allowsMultipleSelection && ([anEvent modifierFlags] & CPCommandKeyMask || [anEvent modifierFlags] & CPShiftKeyMask))
{
if ([anEvent modifierFlags] & CPCommandKeyMask)
{
var indexes = [_selectionIndexes copy];
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
if ([indexes containsIndex:index])
[indexes removeIndex:index];
else
[indexes addIndex:index];
}
else if ([anEvent modifierFlags] & CPShiftKeyMask)
{
var firstSelectedIndex = [[self selectionIndexes] firstIndex],
newSelectedRange = nil;
if (index < firstSelectedIndex)
newSelectedRange = CPMakeRange(index, (firstSelectedIndex - index) + 1);
else
newSelectedRange = CPMakeRange(firstSelectedIndex, (index - firstSelectedIndex) + 1);
indexes = [[self selectionIndexes] copy];
[indexes addIndexesInRange:newSelectedRange];
}
}
else
indexes = [CPIndexSet indexSetWithIndex:index];
[self setSelectionIndexes:indexes];
}
else if (_allowsEmptySelection)
[self setSelectionIndexes:[CPIndexSet indexSet]];
}
@@ -654,6 +623,8 @@
[[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:dragTypes owner:self];
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
if (!_itemForDragging)
_itemForDragging = [self newItemForRepresentedObject:_content[[_selectionIndexes firstIndex]]];
else
@@ -756,29 +727,6 @@
@implementation CPCollectionView (KeyboardInteraction)
- (void)_modifySelectionWithNewIndex:(int)anIndex direction:(int)aDirection expand:(BOOL)shouldExpand
{
anIndex = MIN(MAX(anIndex, 0), [[self items] count] - 1);
if (_allowsMultipleSelection && shouldExpand)
{
var indexes = [_selectionIndexes copy],
bottomAnchor = [indexes firstIndex],
topAnchor = [indexes lastIndex];
// if the direction is backward (-1) check with the bottom anchor
if (aDirection === -1)
[indexes addIndexesInRange:CPMakeRange(anIndex, bottomAnchor - anIndex + 1)];
else
[indexes addIndexesInRange:CPMakeRange(topAnchor, anIndex - topAnchor + 1)];
}
else
indexes = [CPIndexSet indexSetWithIndex:anIndex];
[self setSelectionIndexes:indexes];
[self _scrollToSelection];
}
- (void)_scrollToSelection
{
var frame = [self frameForItemsAtIndexes:[self selectionIndexes]];
@@ -793,36 +741,26 @@
if (index === CPNotFound)
index = [[self items] count];
[self _modifySelectionWithNewIndex:index - 1 direction:-1 expand:NO];
}
index = MAX(index - 1, 0);
- (void)moveLeftAndModifySelection:(id)sender
{
var index = [[self selectionIndexes] firstIndex];
if (index === CPNotFound)
index = [[self items] count];
[self _modifySelectionWithNewIndex:index - 1 direction:-1 expand:YES];
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
[self _scrollToSelection];
}
- (void)moveRight:(id)sender
{
[self _modifySelectionWithNewIndex:[[self selectionIndexes] lastIndex] + 1 direction:1 expand:NO];
}
var index = MIN([[self selectionIndexes] firstIndex] + 1, [[self items] count]-1);
- (void)moveRightAndModifySelection:(id)sender
{
[self _modifySelectionWithNewIndex:[[self selectionIndexes] lastIndex] + 1 direction:1 expand:YES];
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
[self _scrollToSelection];
}
- (void)moveDown:(id)sender
{
[self _modifySelectionWithNewIndex:[[self selectionIndexes] lastIndex] + [self numberOfColumns] direction:1 expand:NO];
}
var index = MIN([[self selectionIndexes] firstIndex] + [self numberOfColumns], [[self items] count]-1);
- (void)moveDownAndModifySelection:(id)sender
{
[self _modifySelectionWithNewIndex:[[self selectionIndexes] lastIndex] + [self numberOfColumns] direction:1 expand:YES];
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
[self _scrollToSelection];
}
- (void)moveUp:(id)sender
@@ -831,16 +769,10 @@
if (index == CPNotFound)
index = [[self items] count];
[self _modifySelectionWithNewIndex:index - [self numberOfColumns] direction:-1 expand:NO];
}
index = MAX(0, index - [self numberOfColumns]);
- (void)moveUpAndModifySelection:(id)sender
{
var index = [[self selectionIndexes] firstIndex];
if (index == CPNotFound)
index = [[self items] count];
[self _modifySelectionWithNewIndex:index - [self numberOfColumns] direction:-1 expand:YES];
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
[self _scrollToSelection];
}
- (void)deleteBackward:(id)sender
@@ -850,8 +782,8 @@
[[self delegate] collectionView:self shouldDeleteItemsAtIndexes:[self selectionIndexes]];
var index = [[self selectionIndexes] firstIndex];
if (index > [[self content] count] - 1)
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:[[self content] count] - 1]];
if (index > [[self content] count]-1)
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:[[self content] count]-1]];
[self _scrollToSelection];
[self setNeedsDisplay:YES];
@@ -885,14 +817,11 @@
@end
var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeKey",
CPCollectionViewMaxItemSizeKey = @"CPCollectionViewMaxItemSizeKey",
CPCollectionViewVerticalMarginKey = @"CPCollectionViewVerticalMarginKey",
CPCollectionViewMaxNumberOfRowsKey = @"CPCollectionViewMaxNumberOfRowsKey",
CPCollectionViewMaxNumberOfColumnsKey = @"CPCollectionViewMaxNumberOfColumnsKey",
CPCollectionViewSelectableKey = @"CPCollectionViewSelectableKey",
CPCollectionViewAllowsMultipleSelectionKey = @"CPCollectionViewAllowsMultipleSelectionKey",
CPCollectionViewBackgroundColorsKey = @"CPCollectionViewBackgroundColorsKey";
var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeKey",
CPCollectionViewMaxItemSizeKey = @"CPCollectionViewMaxItemSizeKey",
CPCollectionViewVerticalMarginKey = @"CPCollectionViewVerticalMarginKey",
CPCollectionViewSelectableKey = @"CPCollectionViewSelectableKey",
CPCollectionViewBackgroundColorsKey = @"CPCollectionViewBackgroundColorsKey";
@implementation CPCollectionView (CPCoding)
@@ -913,13 +842,9 @@ var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeK
_minItemSize = [aCoder decodeSizeForKey:CPCollectionViewMinItemSizeKey] || CGSizeMakeZero();
_maxItemSize = [aCoder decodeSizeForKey:CPCollectionViewMaxItemSizeKey] || CGSizeMakeZero();
_maxNumberOfRows = [aCoder decodeIntForKey:CPCollectionViewMaxNumberOfRowsKey] || 0;
_maxNumberOfColumns = [aCoder decodeIntForKey:CPCollectionViewMaxNumberOfColumnsKey] || 0;
_verticalMargin = [aCoder decodeFloatForKey:CPCollectionViewVerticalMarginKey];
_isSelectable = [aCoder decodeBoolForKey:CPCollectionViewSelectableKey];
_allowsMultipleSelection = [aCoder decodeBoolForKey:CPCollectionViewAllowsMultipleSelectionKey];
[self setBackgroundColors:[aCoder decodeObjectForKey:CPCollectionViewBackgroundColorsKey]];
@@ -943,11 +868,7 @@ var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeK
if (!CGSizeEqualToSize(_maxItemSize, CGSizeMakeZero()))
[aCoder encodeSize:_maxItemSize forKey:CPCollectionViewMaxItemSizeKey];
[aCoder encodeInt:_maxNumberOfRows forKey:CPCollectionViewMaxNumberOfRowsKey];
[aCoder encodeInt:_maxNumberOfColumns forKey:CPCollectionViewMaxNumberOfColumnsKey];
[aCoder encodeBool:_isSelectable forKey:CPCollectionViewSelectableKey];
[aCoder encodeBool:_allowsMultipleSelection forKey:CPCollectionViewAllowsMultipleSelectionKey];
[aCoder encodeFloat:_verticalMargin forKey:CPCollectionViewVerticalMarginKey];
-1
View File
@@ -22,7 +22,6 @@
@import "CPViewController.j"
/*!
Represents an object inside a CPCollectionView.
*/
+91 -87
View File
@@ -32,7 +32,7 @@ var _redComponent = 0,
_greenComponent = 1,
_blueComponent = 2,
_alphaCompnent = 3;
var _hueComponent = 0,
_saturationComponent = 1,
_brightnessComponent = 2;
@@ -54,21 +54,27 @@ var cachedBlackColor,
cachedShadowColor,
cachedClearColor;
/*!
/*!
@ingroup appkit
@code CPColor
\c CPColor can be used to represent color
in an RGB or HSB model with an optional transparency value.</p>
<p>It also provides some class helper methods that
returns instances of commonly used colors.</p>
<p>The class does not have a \c -set: method
like NextStep based frameworks to change the color of
the current context. To change the color of the current
context, use CGContextSetFillColor().
*/
@implementation CPColor : CPObject
{
CPArray _components;
CPImage _patternImage;
CPString _cssString;
CPString _cssString;
}
/*!
@@ -76,12 +82,12 @@ var cachedBlackColor,
Each component should be between the range of 0.0 to 1.0. For
the alpha component, a value of 1.0 is opaque, and 0.0 means
completely transparent.
@param red the red component of the color
@param green the green component of the color
@param blue the blue component of the color
@param alpha the alpha component
@return a color initialized to the values specified
*/
+ (CPColor)colorWithRed:(float)red green:(float)green blue:(float)blue alpha:(float)alpha
@@ -91,17 +97,17 @@ var cachedBlackColor,
/*!
@deprecated in favor of colorWithRed:green:blue:alpha:
Creates a color in the RGB color space, with an alpha value.
Each component should be between the range of 0.0 to 1.0. For
the alpha component, a value of 1.0 is opaque, and 0.0 means
completely transparent.
@param red the red component of the color
@param green the green component of the color
@param blue the blue component of the color
@param alpha the alpha component
@return a color initialized to the values specified
*/
+ (CPColor)colorWithCalibratedRed:(float)red green:(float)green blue:(float)blue alpha:(float)alpha
@@ -113,10 +119,10 @@ var cachedBlackColor,
/*!
Creates a new color object with \c white for the RGB components.
For the alpha component, a value of 1.0 is opaque, and 0.0 means completely transparent.
@param white a float between 0.0 and 1.0
@param alpha the alpha component between 0.0 and 1.0
@return a color initialized to the values specified
*/
+ (CPColor)colorWithWhite:(float)white alpha:(float)alpha
@@ -126,13 +132,13 @@ var cachedBlackColor,
/*!
@deprecated in favor of colorWithWhite:apha:
Creates a new color object with \c white for the RGB components.
For the alpha component, a value of 1.0 is opaque, and 0.0 means completely transparent.
@param white a float between 0.0 and 1.0
@param alpha the alpha component between 0.0 and 1.0
@return a color initialized to the values specified
*/
+ (CPColor)colorWithCalibratedWhite:(float)white alpha:(float)alpha
@@ -142,11 +148,11 @@ var cachedBlackColor,
/*!
Creates a new color in HSB space.
@param hue the hue value
@param saturation the saturation value
@param brightness the brightness value
@return the initialized color
*/
+ (CPColor)colorWithHue:(float)hue saturation:(float)saturation brightness:(float)brightness
@@ -156,16 +162,16 @@ var cachedBlackColor,
+ (CPColor)colorWithHue:(float)hue saturation:(float)saturation brightness:(float)brightness alpha:(float)alpha
{
if (saturation === 0.0)
if(saturation === 0.0)
return [CPColor colorWithCalibratedWhite:brightness / 100.0 alpha:alpha];
var f = hue % 60,
p = (brightness * (100 - saturation)) / 10000,
q = (brightness * (6000 - saturation * f)) / 600000,
t = (brightness * (6000 - saturation * (60 -f))) / 600000,
b = brightness / 100.0;
switch (FLOOR(hue / 60))
switch(FLOOR(hue / 60))
{
case 0: return [CPColor colorWithCalibratedRed: b green: t blue: p alpha: alpha];
case 1: return [CPColor colorWithCalibratedRed: q green: b blue: p alpha: alpha];
@@ -180,7 +186,7 @@ var cachedBlackColor,
Creates an RGB color from a hexadecimal string. For example,
the a string of "FFFFFF" would return a white CPColor.
"FF0000" would return a pure red, "00FF00" would return a
pure blue, and "0000FF" would return a pure green.
pure blue, and "0000FF" would return a pure green.
@param hex a 6 character long string of hex
@@ -188,8 +194,7 @@ var cachedBlackColor,
*/
+ (CPColor)colorWithHexString:(string)hex
{
var rgba = hexToRGB(hex);
return rgba ? [[CPColor alloc] _initWithRGBA: rgba] : null;
return [[CPColor alloc] _initWithRGBA: hexToRGB(hex)];
}
/*!
@@ -392,7 +397,7 @@ var cachedBlackColor,
/*!
Creates a CPColor from a valid CSS RGB string. Example, "rgb(32,64,129)".
@param aString a CSS color string
@return a color initialized to the value in the css string
*/
@@ -404,23 +409,23 @@ var cachedBlackColor,
/* @ignore */
- (id)_initWithCSSString:(CPString)aString
{
if (aString.indexOf("rgb") == CPNotFound)
if(aString.indexOf("rgb") == CPNotFound)
return nil;
self = [super init];
var startingIndex = aString.indexOf("("),
parts = aString.substring(startingIndex + 1).split(',');
var startingIndex = aString.indexOf("(");
var parts = aString.substring(startingIndex+1).split(',');
_components = [
parseInt(parts[0], 10) / 255.0,
parseInt(parts[1], 10) / 255.0,
parseInt(parts[2], 10) / 255.0,
parts[3] ? parseInt(parts[3], 10) / 255.0 : 1.0
];
parts[3] ? parseInt(parts[3], 10) / 255.0 : 1.0
]
_cssString = aString;
return self;
}
@@ -428,7 +433,7 @@ var cachedBlackColor,
- (id)_initWithRGBA:(CPArray)components
{
self = [super init];
if (self)
{
_components = components;
@@ -449,14 +454,14 @@ var cachedBlackColor,
- (id)_initWithPatternImage:(CPImage)anImage
{
self = [super init];
if (self)
{
_patternImage = anImage;
_cssString = "url(\"" + [_patternImage filename] + "\")";
_components = [0.0, 0.0, 0.0, 1.0];
}
return self;
}
@@ -518,17 +523,17 @@ var cachedBlackColor,
/*!
Returns a new color with the same RGB as the receiver but a new alpha component.
@param anAlphaComponent the alpha component for the new color
@return a new color object
*/
- (CPColor)colorWithAlphaComponent:(float)anAlphaComponent
{
var components = _components.slice();
components[components.length - 1] = anAlphaComponent;
return [[[self class] alloc] _initWithRGBA:components];
}
@@ -547,40 +552,37 @@ var cachedBlackColor,
var red = ROUND(_components[_redComponent] * 255.0),
green = ROUND(_components[_greenComponent] * 255.0),
blue = ROUND(_components[_blueComponent] * 255.0);
var max = MAX(red, green, blue),
min = MIN(red, green, blue),
delta = max - min;
var brightness = max / 255.0,
saturation = (max != 0) ? delta / max : 0;
var hue;
if (saturation == 0)
{
if(saturation == 0)
hue = 0;
}
else
{
var rr = (max - red) / delta,
gr = (max - green) / delta,
br = (max - blue) / delta;
if (red == max)
var rr = (max - red) / delta;
var gr = (max - green) / delta;
var br = (max - blue) / delta;
if (red == max)
hue = br - gr;
else if (green == max)
else if (green == max)
hue = 2 + rr - br;
else
else
hue = 4 + gr - rr;
hue /= 6;
if (hue < 0)
if (hue < 0)
hue++;
}
return [
ROUND(hue * 360.0),
ROUND(hue * 360.0),
ROUND(saturation * 100.0),
ROUND(brightness * 100.0)
];
@@ -628,7 +630,7 @@ url("data:image/png;base64,BASE64ENCODEDDATA") // if there is a pattern image
@implementation CPColor (CoreGraphicsExtensions)
/*!
/*!
Set's the receiver to be the fill and stroke color in the current graphics context
*/
- (void)set
@@ -637,16 +639,16 @@ url("data:image/png;base64,BASE64ENCODEDDATA") // if there is a pattern image
[self setStroke];
}
/*!
/*!
Set's the receiver to be the fill color in the current graphics context
*/
- (void)setFill
{
var ctx = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSetFillColor(ctx, self);
CGContextSetFillColor(ctx, self);
}
/*!
/*!
Set's the receiver to be the stroke color in the current graphics context
*/
- (void)setStroke
@@ -679,7 +681,7 @@ var CPColorComponentsKey = @"CPColorComponentsKey",
{
if ([aCoder containsValueForKey:CPColorPatternImageKey])
return [self _initWithPatternImage:[aCoder decodeObjectForKey:CPColorPatternImageKey]];
return [self _initWithRGBA:[aCoder decodeObjectForKey:CPColorComponentsKey]];
}
@@ -697,48 +699,50 @@ var CPColorComponentsKey = @"CPColorComponentsKey",
@end
var hexCharacters = "0123456789ABCDEF";
// HACK: prevent these from becoming globals. workaround for obj-j "function foo(){}" behavior
var hexToRGB, rgbToHex, byteToHex;
/*!
Used for the CPColor \c +colorWithHexString: implementation
@ignore
@class CPColor
@return an array of rgb components
*/
var hexToRGB = function(hex)
function hexToRGB(hex)
{
if (hex.length == 3)
if ( hex.length == 3 )
hex = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2);
if (hex.length != 6)
if(hex.length != 6)
return null;
hex = hex.toUpperCase();
for (var i = 0; i < hex.length; i++)
if (hexCharacters.indexOf(hex.charAt(i)) == -1)
for(var i=0; i<hex.length; i++)
if(hexCharacters.indexOf(hex.charAt(i)) == -1)
return null;
var red = (hexCharacters.indexOf(hex.charAt(0)) * 16 + hexCharacters.indexOf(hex.charAt(1))) / 255.0,
green = (hexCharacters.indexOf(hex.charAt(2)) * 16 + hexCharacters.indexOf(hex.charAt(3))) / 255.0,
blue = (hexCharacters.indexOf(hex.charAt(4)) * 16 + hexCharacters.indexOf(hex.charAt(5))) / 255.0;
var red = (hexCharacters.indexOf(hex.charAt(0)) * 16 + hexCharacters.indexOf(hex.charAt(1))) / 255.0;
var green = (hexCharacters.indexOf(hex.charAt(2)) * 16 + hexCharacters.indexOf(hex.charAt(3))) / 255.0;
var blue = (hexCharacters.indexOf(hex.charAt(4)) * 16 + hexCharacters.indexOf(hex.charAt(5))) / 255.0;
return [red, green, blue, 1.0];
};
}
var rgbToHex = function(r,g,b)
{
function rgbToHex(r,g,b) {
return byteToHex(r) + byteToHex(g) + byteToHex(b);
};
}
var byteToHex = function(n)
{
if (!n || isNaN(n))
return "00";
function byteToHex(n) {
if (!n || isNaN(n)) return "00";
n = ROUND(MIN(255,MAX(0,256*n)));
return hexCharacters.charAt((n - n % 16) / 16) +
hexCharacters.charAt(n % 16);
}
n = FLOOR(MIN(255, MAX(0, 256 * n)));
// Toll-Free bridge CPColor to CGColor.
//CGColor.prototype.isa = CPColor;
//[CPColor initialize];
return hexCharacters.charAt((n - n % 16) / 16) +
hexCharacters.charAt(n % 16);
};
//http://dev.mootools.net/browser/trunk/Source/Utilities/Color.js?rev=1184
+80 -83
View File
@@ -20,13 +20,11 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPApplication.j"
@import "CPButton.j"
@import "CPCookie.j"
@import "CPPanel.j"
@import "CPView.j"
CPColorPanelColorDidChangeNotification = @"CPColorPanelColorDidChangeNotification";
var PREVIEW_HEIGHT = 20.0,
@@ -37,7 +35,7 @@ var PREVIEW_HEIGHT = 20.0,
var SharedColorPanel = nil,
ColorPickerClasses = [];
/*
A color wheel
@global
@@ -54,7 +52,7 @@ CPSliderColorPickerMode = 2;
CPColorPickerViewWidth = 265,
CPColorPickerViewHeight = 370;
/*!
/*!
@ingroup appkit
@class CPColorPanel
@@ -63,7 +61,7 @@ CPColorPickerViewHeight = 370;
obtain the panel, call the \c +sharedColorPanel method.
*/
@implementation CPColorPanel : CPPanel
{
{
_CPColorPanelToolbar _toolbar;
_CPColorPanelSwatches _swatchView;
_CPColorPanelPreview _previewView;
@@ -82,8 +80,8 @@ CPColorPickerViewHeight = 370;
int _mode;
}
/*!
A list of color pickers is collected here, and any color panel created will contain
/*!
A list of color pickers is collected here, and any color panel created will contain
any picker in this list up to this point. In other words, call before creating a color panel.
*/
+ (void)provideColorPickerClass:(Class)aColorPickerSubclass
@@ -98,7 +96,7 @@ CPColorPickerViewHeight = 370;
{
if (!SharedColorPanel)
SharedColorPanel = [[CPColorPanel alloc] init];
return SharedColorPanel;
}
@@ -109,7 +107,7 @@ CPColorPickerViewHeight = 370;
+ (void)setPickerMode:(CPColorPanelMode)mode
{
var panel = [CPColorPanel sharedColorPanel];
[panel setMode:mode];
[panel setMode: mode];
}
/*
@@ -118,7 +116,7 @@ CPColorPickerViewHeight = 370;
*/
- (id)init
{
self = [super initWithContentRect:CGRectMake(500.0, 50.0, 219.0, 370.0)
self = [super initWithContentRect:CGRectMake(500.0, 50.0, 219.0, 370.0)
styleMask:(CPTitledWindowMask | CPClosableWindowMask | CPResizableWindowMask)];
if (self)
@@ -127,14 +125,14 @@ CPColorPickerViewHeight = 370;
[self setTitle:@"Color Panel"];
[self setLevel:CPFloatingWindowLevel];
[self setFloatingPanel:YES];
[self setBecomesKeyOnlyIfNeeded:YES];
[self setMinSize:CGSizeMake(219.0, 342.0)];
[self setMaxSize:CGSizeMake(323.0, 537.0)];
}
return self;
}
@@ -145,12 +143,12 @@ CPColorPickerViewHeight = 370;
{
_color = aColor;
[_previewView setBackgroundColor: _color];
[CPApp sendAction:@selector(changeColor:) to:nil from:self];
if (_target && _action)
[CPApp sendAction:_action to:_target from:self];
[[CPNotificationCenter defaultCenter]
postNotificationName:CPColorPanelColorDidChangeNotification
object:self];
@@ -167,7 +165,7 @@ CPColorPickerViewHeight = 370;
- (void)setColor:(CPColor)aColor updatePicker:(BOOL)bool
{
[self setColor:aColor];
if (bool)
[_activePicker setColor:_color];
}
@@ -234,30 +232,30 @@ CPColorPickerViewHeight = 370;
{
var picker = _colorPickers[[sender tag]],
view = [picker provideNewView:NO];
if (!view)
view = [picker provideNewView:YES];
if (view == _currentView)
return;
if (_currentView)
[view setFrame:[_currentView frame]];
else
{
var height = (TOOLBAR_HEIGHT + 10 + PREVIEW_HEIGHT + 5 + SWATCH_HEIGHT + 32),
var height = (TOOLBAR_HEIGHT+10+PREVIEW_HEIGHT+5+SWATCH_HEIGHT+32),
bounds = [[self contentView] bounds];
[view setFrameSize:CPSizeMake(bounds.size.width - 10, bounds.size.height - height)];
[view setFrameOrigin:CPPointMake(5, height)];
[view setFrameSize: CPSizeMake(bounds.size.width - 10, bounds.size.height - height)];
[view setFrameOrigin: CPPointMake(5, height)];
}
[_currentView removeFromSuperview];
[[self contentView] addSubview:view];
_currentView = view;
_activePicker = picker;
[picker setColor:[self color]];
}
@@ -287,7 +285,7 @@ CPColorPickerViewHeight = 370;
_colorPickers = [];
var count = [ColorPickerClasses count];
for (var i = 0; i < count; i++)
for (var i=0; i<count; i++)
{
var currentPickerClass = ColorPickerClasses[i],
currentPicker = [[currentPickerClass alloc] initWithPickerMask:0 colorPanel:self];
@@ -299,29 +297,29 @@ CPColorPickerViewHeight = 370;
bounds = [contentView bounds];
_toolbar = [[CPView alloc] initWithFrame:CGRectMake(0, 6, CGRectGetWidth(bounds), TOOLBAR_HEIGHT)];
[_toolbar setAutoresizingMask: CPViewWidthSizable];
[_toolbar setAutoresizingMask: CPViewWidthSizable];
var totalToolbarWidth = count * ICON_WIDTH + (count - 1) * ICON_PADDING,
leftOffset = (CGRectGetWidth(bounds) - totalToolbarWidth) / 2.0,
buttonForLater = nil;
for (var i = 0; i < count; i++)
for (var i=0; i<count; i++)
{
var image = [_colorPickers[i] provideNewButtonImage],
highlightImage = [_colorPickers[i] provideNewAlternateButtonImage],
button = [[CPButton alloc] initWithFrame:CGRectMake(leftOffset + i * (ICON_WIDTH + ICON_PADDING), 0, ICON_WIDTH, ICON_WIDTH)];
button = [[CPButton alloc] initWithFrame:CGRectMake(leftOffset + i*(ICON_WIDTH+ICON_PADDING), 0, ICON_WIDTH, ICON_WIDTH)];
[button setTag:i];
[button setTarget:self];
[button setAction:@selector(_setPicker:)];
[button setBordered:NO];
[button setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin];
[button setAutoresizingMask:CPViewMinXMargin|CPViewMaxXMargin];
[button setImage:image];
[button setAlternateImage:highlightImage];
[_toolbar addSubview:button];
if (!buttonForLater)
buttonForLater = button;
}
@@ -332,7 +330,7 @@ CPColorPickerViewHeight = 370;
_previewView = [[_CPColorPanelPreview alloc] initWithFrame:CGRectInset([previewBox bounds], 2.0, 2.0)];
[_previewView setColorPanel:self];
[_previewView setAutoresizingMask:CPViewWidthSizable];
[_previewView setAutoresizingMask:CPViewWidthSizable];
[previewBox setBackgroundColor:[CPColor colorWithWhite:0.8 alpha:1.0]];
[previewBox setAutoresizingMask:CPViewWidthSizable];
@@ -340,7 +338,7 @@ CPColorPickerViewHeight = 370;
[previewBox addSubview:_previewView];
var _previewLabel = [[CPTextField alloc] initWithFrame: CPRectMake(10, TOOLBAR_HEIGHT + 10, 60, 15)];
[_previewLabel setStringValue:"Preview:"];
[_previewLabel setStringValue: "Preview:"];
[_previewLabel setTextColor:[CPColor blackColor]];
[_previewLabel setAlignment:CPRightTextAlignment];
@@ -352,8 +350,8 @@ CPColorPickerViewHeight = 370;
_swatchView = [[_CPColorPanelSwatches alloc] initWithFrame:CGRectInset([swatchBox bounds], 1.0, 1.0)];
[_swatchView setColorPanel:self];
[_swatchView setAutoresizingMask:CPViewWidthSizable];
[_swatchView setColorPanel: self];
[_swatchView setAutoresizingMask: CPViewWidthSizable];
[swatchBox addSubview:_swatchView];
@@ -369,7 +367,7 @@ CPColorPickerViewHeight = 370;
[opacityLabel setAlignment:CPRightTextAlignment];
_opacitySlider = [[CPSlider alloc] initWithFrame:CGRectMake(76, TOOLBAR_HEIGHT + PREVIEW_HEIGHT + 34, CGRectGetWidth(bounds) - 86, 20.0)];
[_opacitySlider setMinValue:0.0];
[_opacitySlider setMaxValue:1.0];
@@ -417,37 +415,37 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
CPCookie _swatchCookie;
}
- (id)initWithFrame:(CPRect)aFrame
-(id)initWithFrame:(CPRect)aFrame
{
self = [super initWithFrame:aFrame];
[self setBackgroundColor: [CPColor grayColor]];
[self registerForDraggedTypes:[CPArray arrayWithObjects:CPColorDragType]];
var whiteColor = [CPColor whiteColor];
_swatchCookie = [[CPCookie alloc] initWithName: CPColorPanelSwatchesCookie];
var colorList = [self startingColorList];
_swatches = [];
for (var i = 0; i < 50; i++)
for(var i=0; i < 50; i++)
{
// FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox
var view = [[CPView alloc] initWithFrame: CPRectMake(13 * i + 1, 1, 12, 12)],
var view = [[CPView alloc] initWithFrame: CPRectMake(13*i+1, 1, 12, 12)],
fillView = [[CPView alloc] initWithFrame:CGRectInset([view bounds], 1.0, 1.0)];
[view setBackgroundColor:whiteColor];
[fillView setBackgroundColor: (i < colorList.length) ? colorList[i] : whiteColor];
[view addSubview:fillView];
[self addSubview: view];
_swatches.push(view);
}
return self;
}
@@ -459,8 +457,7 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
- (CPArray)startingColorList
{
var cookieValue = [_swatchCookie value];
if (cookieValue == "")
if(cookieValue == "")
{
return [
[CPColor blackColor],
@@ -474,11 +471,11 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
[CPColor yellowColor]
];
}
var cookieValue = eval(cookieValue),
result = [];
for (var i = 0; i < cookieValue.length; i++)
var cookieValue = eval(cookieValue);
var result = [];
for(var i=0; i<cookieValue.length; i++)
result.push([CPColor colorWithHexString: cookieValue[i]]);
return result;
@@ -488,12 +485,12 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
{
var result = [];
// FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox
for (var i = 0; i < _swatches.length; i++)
for(var i=0; i<_swatches.length; i++)
result.push([[[_swatches[i] subviews][0] backgroundColor] hexString]);
var future = new Date();
future.setYear(2019);
[_swatchCookie setValue: JSON.stringify(result) expires:future domain: nil];
}
@@ -523,8 +520,8 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
{
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil],
bounds = [self bounds];
if (!CGRectContainsPoint(bounds, point) || point.x > [self bounds].size.width - 1 || point.x < 1)
if(!CGRectContainsPoint(bounds, point) || point.x > [self bounds].size.width - 1 || point.x < 1)
return NO;
[_colorPanel setColor: [self colorAtIndex:FLOOR(point.x / 13)] updatePicker: YES];
@@ -538,21 +535,21 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
return NO;
[[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:[CPArray arrayWithObject:CPColorDragType] owner:self];
var swatch = _swatches[FLOOR(point.x / 13)];
// FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox
_dragColor = [[swatch subviews][0] backgroundColor];
var bounds = CPRectCreateCopy([swatch bounds]);
// FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox
var dragView = [[CPView alloc] initWithFrame: bounds],
var dragView = [[CPView alloc] initWithFrame: bounds];
dragFillView = [[CPView alloc] initWithFrame:CGRectInset(bounds, 1.0, 1.0)];
[dragView setBackgroundColor:[CPColor blackColor]];
[dragFillView setBackgroundColor:_dragColor];
[dragView addSubview:dragFillView];
[self dragView: dragView
@@ -566,19 +563,19 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
- (void)pasteboard:(CPPasteboard)aPasteboard provideDataForType:(CPString)aType
{
if (aType == CPColorDragType)
if(aType == CPColorDragType)
[aPasteboard setData:[CPKeyedArchiver archivedDataWithRootObject:_dragColor] forType:aType];
}
- (void)performDragOperation:(id <CPDraggingInfo>)aSender
{
{
var location = [self convertPoint:[aSender draggingLocation] fromView:nil],
pasteboard = [aSender draggingPasteboard],
swatch = nil;
if (![pasteboard availableTypeFromArray:[CPColorDragType]] || location.x > [self bounds].size.width - 1 || location.x < 1)
if(![pasteboard availableTypeFromArray:[CPColorDragType]] || location.x > [self bounds].size.width - 1 || location.x < 1)
return NO;
[self setColor:[CPKeyedUnarchiver unarchiveObjectWithData:[pasteboard dataForType:CPColorDragType]] atIndex: FLOOR(location.x / 13)];
}
@@ -593,9 +590,9 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
- (id)initWithFrame:(CPRect)aFrame
{
self = [super initWithFrame:aFrame];
[self registerForDraggedTypes:[CPArray arrayWithObjects:CPColorDragType]];
return self;
}
@@ -613,9 +610,9 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
{
var pasteboard = [aSender draggingPasteboard];
if (![pasteboard availableTypeFromArray:[CPColorDragType]])
if(![pasteboard availableTypeFromArray:[CPColorDragType]])
return NO;
var color = [CPKeyedUnarchiver unarchiveObjectWithData:[pasteboard dataForType:CPColorDragType]];
[_colorPanel setColor:color updatePicker:YES];
}
@@ -629,19 +626,19 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
{
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
[[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:[CPColorDragType] owner:self];
[[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:[CPColorDragType] owner:self];
var bounds = CPRectMake(0, 0, 15, 15);
// FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox
var dragView = [[CPView alloc] initWithFrame: bounds],
var dragView = [[CPView alloc] initWithFrame: bounds];
dragFillView = [[CPView alloc] initWithFrame:CGRectInset(bounds, 1.0, 1.0)];
[dragView setBackgroundColor:[CPColor blackColor]];
[dragFillView setBackgroundColor:[self backgroundColor]];
[dragView addSubview:dragFillView];
[self dragView: dragView
at: CPPointMake(point.x - bounds.size.width / 2.0, point.y - bounds.size.height / 2.0)
offset: CPPointMake(0.0, 0.0)
@@ -653,7 +650,7 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
- (void)pasteboard:(CPPasteboard)aPasteboard provideDataForType:(CPString)aType
{
if (aType == CPColorDragType)
if(aType == CPColorDragType)
[aPasteboard setData:[CPKeyedArchiver archivedDataWithRootObject:[self backgroundColor]] forType:aType];
}
+39 -36
View File
@@ -21,11 +21,11 @@
*/
@import <Foundation/CPObject.j>
@import "CPColorPanel.j"
@import "CPView.j"
#include "Platform/Platform.h"
/*!
/*!
@ingroup appkit
@class CPColorPicker
@@ -102,18 +102,18 @@
CPColor _cachedColor;
}
- (id)initWithPickerMask:(int)mask colorPanel:(CPColorPanel)owningColorPanel
- (id)initWithPickerMask:(int)mask colorPanel:(CPColorPanel)owningColorPanel
{
return [super initWithPickerMask:mask colorPanel: owningColorPanel];
}
- (id)initView
-(id)initView
{
aFrame = CPRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight);
_pickerView = [[CPView alloc] initWithFrame:aFrame];
[_pickerView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[_pickerView setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
_brightnessSlider = [[CPSlider alloc] initWithFrame:CGRectMake(0, (aFrame.size.height - 34), aFrame.size.width, 15)];
@@ -136,17 +136,17 @@
[_pickerView addSubview:_brightnessSlider];
}
- (void)brightnessSliderDidChange:(id)sender
-(void)brightnessSliderDidChange:(id)sender
{
[self updateColor];
}
- (void)colorWheelDidChange:(id)sender
-(void)colorWheelDidChange:(id)sender
{
[self updateColor];
}
- (void)updateColor
-(void)updateColor
{
var hue = [_hueSaturationView angle],
saturation = [_hueSaturationView distance],
@@ -223,7 +223,7 @@
float _radius;
}
- (id)initWithFrame:(CPRect)aFrame
-(id)initWithFrame:(CPRect)aFrame
{
self = [super initWithFrame:aFrame];
@@ -261,19 +261,19 @@
return self;
}
- (void)setWheelBrightness:(float)brightness
-(void)setWheelBrightness:(float)brightness
{
_blackWheelImage.style.opacity = 1.0 - brightness;
_blackWheelImage.style.filter = "alpha(opacity=" + (1.0 - brightness) * 100 + ")"
_blackWheelImage.style.filter = "alpha(opacity=" + (1.0 - brightness)*100 + ")"
}
- (void)setFrameSize:(CPSize)aSize
-(void)setFrameSize:(CPSize)aSize
{
[super setFrameSize:aSize];
[self setWheelSize:aSize];
}
- (void)setWheelSize:(CPSize)aSize
-(void)setWheelSize:(CPSize)aSize
{
var min = MIN(aSize.width, aSize.height);
@@ -296,55 +296,57 @@
[self setAngle:[self degreesToRadians:_angle] distance:(_distance / 100.0) * _radius];
}
- (void)setDelegate:(id)aDelegate
-(void)setDelegate:(id)aDelegate
{
_delegate = aDelegate;
}
- (id)delegate
-(id)delegate
{
return _delegate;
}
- (float)angle
-(float)angle
{
return _angle;
}
- (float)distance
-(float)distance
{
return _distance;
}
- (void)mouseDown:(CPEvent)anEvent
-(void)mouseDown:(CPEvent)anEvent
{
[self reposition:anEvent];
}
- (void)mouseDragged:(CPEvent)anEvent
-(void)mouseDragged:(CPEvent)anEvent
{
[self reposition:anEvent];
}
- (void)reposition:(CPEvent)anEvent
-(void)reposition:(CPEvent)anEvent
{
var bounds = [self bounds],
location = [self convertPoint:[anEvent locationInWindow] fromView:nil],
midX = CGRectGetMidX(bounds),
midY = CGRectGetMidY(bounds),
distance = MIN(SQRT((location.x - midX) * (location.x - midX) + (location.y - midY) * (location.y - midY)), _radius),
angle = ATAN2(location.y - midY, location.x - midX);
location = [self convertPoint:[anEvent locationInWindow] fromView:nil];
var midX = CGRectGetMidX(bounds);
var midY = CGRectGetMidY(bounds);
var distance = MIN(SQRT((location.x - midX)*(location.x - midX) + (location.y - midY)*(location.y - midY)), _radius);
var angle = ATAN2(location.y - midY, location.x - midX);
[self setAngle:angle distance:distance];
[_delegate colorWheelDidChange:self];
}
- (void)setAngle:(int)angle distance:(float)distance
-(void)setAngle:(int)angle distance:(float)distance
{
var bounds = [self bounds],
midX = CGRectGetMidX(bounds),
midY = CGRectGetMidY(bounds);
var bounds = [self bounds];
var midX = CGRectGetMidX(bounds);
var midY = CGRectGetMidY(bounds);
_angle = [self radiansToDegrees:angle];
_distance = (distance / _radius) * 100.0;
@@ -352,22 +354,23 @@
[_crosshair setFrameOrigin:CPPointMake(COS(angle) * distance + midX - 2.0, SIN(angle) * distance + midY - 2.0)];
}
- (void)setPositionToColor:(CPColor)aColor
-(void)setPositionToColor:(CPColor)aColor
{
var hsb = [aColor hsbComponents],
bounds = [self bounds],
angle = [self degreesToRadians:hsb[0]],
bounds = [self bounds];
var angle = [self degreesToRadians:hsb[0]],
distance = (hsb[1] / 100.0) * _radius;
[self setAngle:angle distance:distance];
}
- (int)radiansToDegrees:(float)radians
-(int)radiansToDegrees:(float)radians
{
return ((-radians / PI) * 180 + 360) % 360;
}
- (float)degreesToRadians:(float)degrees
-(float)degreesToRadians:(float)degrees
{
return -(((degrees - 360) / 180) * PI);
}
+29 -29
View File
@@ -29,7 +29,7 @@
var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiveNotification";
/*!
/*!
@ingroup appkit
@class CPColorWell
@@ -41,7 +41,7 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
{
BOOL _active;
BOOL _bordered;
CPColor _color;
CPView _wellView;
}
@@ -49,19 +49,19 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_active = NO;
_bordered = YES;
_color = [CPColor whiteColor];
[self drawBezelWithHighlight:NO];
[self drawWellInside:CGRectInset([self bounds], 3.0, 3.0)];
[self _registerForNotifications];
}
return self;
}
@@ -97,9 +97,9 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
{
if (_bordered == bordered)
return;
_bordered = bordered;
[self drawWellInside:CGRectInset([self bounds], 3.0, 3.0)];
}
@@ -120,9 +120,9 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
{
if (_color == aColor)
return;
_color = aColor;
[self drawWellInside:CGRectInset([self bounds], 3.0, 3.0)];
}
@@ -137,7 +137,7 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
// Activating and Deactivating Color Wells
/*!
Activates the color well, displays the color panel, and makes the panel's current color the same as its own.
Activates the color well, displays the color panel, and makes the panel's current color the same as its own.
If exclusive is \c YES, deactivates any other CPColorWells. \c NO, keeps them active.
@param shouldBeExclusive whether other color wells should be deactivated.
*/
@@ -152,9 +152,9 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
if ([self isActive])
return;
_active = YES;
[[CPNotificationCenter defaultCenter]
addObserver:self
selector:@selector(colorPanelDidChangeColor:)
@@ -169,9 +169,9 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
{
if (![self isActive])
return;
_active = NO;
[[CPNotificationCenter defaultCenter]
removeObserver:self
name:CPColorPanelColorDidChangeNotification
@@ -202,19 +202,19 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
{
_wellView = [[CPView alloc] initWithFrame:aRect];
[_wellView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[self addSubview:_wellView];
}
else
[_wellView setFrame:aRect];
[_wellView setBackgroundColor:_color];
}
- (void)colorPanelDidChangeColor:(CPNotification)aNotification
{
[self takeColorFrom:[aNotification object]];
[self sendAction:[self action] to:[self target]];
}
@@ -245,17 +245,17 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
[self drawBezelWithHighlight:CGRectContainsPoint([self bounds], [self convertPoint:[anEvent locationInWindow] fromView:nil])];
}
- (void)mouseUp:(CPEvent)anEvent
-(void)mouseUp:(CPEvent)anEvent
{
[self drawBezelWithHighlight:NO];
if (!CGRectContainsPoint([self bounds], [self convertPoint:[anEvent locationInWindow] fromView:nil]) || ![self isEnabled])
return;
[self activate:YES];
var colorPanel = [CPColorPanel sharedColorPanel];
[colorPanel setColor:_color];
[colorPanel orderFront:self];
}
@@ -274,11 +274,11 @@ var CPColorWellColorKey = "CPColorWellColorKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
_active = NO;
_bordered = [aCoder decodeBoolForKey:CPColorWellBorderedKey];
_bordered = [aCoder decodeObjectForKey:CPColorWellBorderedKey];
_color = [aCoder decodeObjectForKey:CPColorWellColorKey];
[self drawBezelWithHighlight:NO];
@@ -286,7 +286,7 @@ var CPColorWellColorKey = "CPColorWellColorKey",
[self _registerForNotifications];
}
return self;
}
@@ -296,17 +296,17 @@ var CPColorWellColorKey = "CPColorWellColorKey",
*/
- (void)encodeWithCoder:(CPCoder)aCoder
{
// We do this in order to avoid encoding the _wellView, which
// We do this in order to avoid encoding the _wellView, which
// should just automatically be created programmatically as needed.
var actualSubviews = _subviews;
_subviews = [_subviews copy];
[_subviews removeObjectIdenticalTo:_wellView];
[super encodeWithCoder:aCoder];
_subviews = actualSubviews;
[aCoder encodeObject:_color forKey:CPColorWellColorKey];
[aCoder encodeObject:_bordered forKey:CPColorWellBorderedKey];
}
+15 -16
View File
@@ -23,7 +23,6 @@
@import "CPEvent.j"
@import "CPPlatform.j"
// Browser Engines
CPUnknownBrowserEngine = 0;
CPGeckoBrowserEngine = 1;
@@ -78,23 +77,23 @@ if (typeof window !== "undefined" && typeof window.navigator !== "undefined")
USER_AGENT = window.navigator.userAgent;
// Opera
if (typeof window !== "undefined" && window.opera)
if (window.opera)
{
PLATFORM_ENGINE = CPOperaBrowserEngine;
PLATFORM_FEATURES |= CPJavaScriptCanvasDrawFeature;
}
// Internet Explorer
else if (typeof window !== "undefined" && window.attachEvent) // Must follow Opera check.
else if (window.attachEvent) // Must follow Opera check.
{
PLATFORM_ENGINE = CPInternetExplorerBrowserEngine;
// Features we can only be sure of with IE (no known independent tests)
PLATFORM_FEATURES |= CPVMLFeature;
PLATFORM_FEATURES |= CPJavascriptRemedialKeySupport;
PLATFORM_FEATURES |= CPJavaScriptShadowFeature;
PLATFORM_FEATURES |= CPOpacityRequiresFilterFeature;
PLATFORM_FEATURES &= ~CPInputTypeCanBeChangedFeature;
@@ -104,7 +103,7 @@ else if (typeof window !== "undefined" && window.attachEvent) // Must follow Ope
else if (USER_AGENT.indexOf("AppleWebKit/") != -1)
{
PLATFORM_ENGINE = CPWebKitBrowserEngine;
// Features we can only be sure of with WebKit (no known independent tests)
PLATFORM_FEATURES |= CPCSSRGBAFeature;
PLATFORM_FEATURES |= CPHTMLContentEditableFeature;
@@ -115,7 +114,7 @@ else if (USER_AGENT.indexOf("AppleWebKit/") != -1)
PLATFORM_FEATURES |= CPJavascriptClipboardEventsFeature;
PLATFORM_FEATURES |= CPJavascriptClipboardAccessFeature;
PLATFORM_FEATURES |= CPJavaScriptShadowFeature;
var versionStart = USER_AGENT.indexOf("AppleWebKit/") + "AppleWebKit/".length,
versionEnd = USER_AGENT.indexOf(" ", versionStart),
versionString = USER_AGENT.substring(versionStart, versionEnd),
@@ -123,7 +122,7 @@ else if (USER_AGENT.indexOf("AppleWebKit/") != -1)
majorVersion = parseInt(versionString.substring(0, versionDivision)),
minorVersion = parseInt(versionString.substr(versionDivision + 1));
if ((USER_AGENT.indexOf("Safari") !== CPNotFound && (majorVersion > 525 || (majorVersion === 525 && minorVersion > 14))) || USER_AGENT.indexOf("Chrome") !== CPNotFound)
if((USER_AGENT.indexOf("Safari") !== CPNotFound && (majorVersion > 525 || (majorVersion === 525 && minorVersion > 14))) || USER_AGENT.indexOf("Chrome") !== CPNotFound)
PLATFORM_FEATURES |= CPJavascriptRemedialKeySupport;
// FIXME this is a terrible hack to get around this bug:
@@ -145,12 +144,12 @@ else if (USER_AGENT.indexOf("KHTML") != -1) // Must follow WebKit check.
else if (USER_AGENT.indexOf("Gecko") !== -1) // Must follow KHTML check.
{
PLATFORM_ENGINE = CPGeckoBrowserEngine;
PLATFORM_FEATURES |= CPJavaScriptCanvasDrawFeature;
var index = USER_AGENT.indexOf("Firefox"),
version = (index === -1) ? 2.0 : parseFloat(USER_AGENT.substring(index + "Firefox".length + 1));
if (version >= 3.0)
PLATFORM_FEATURES |= CPCSSRGBAFeature;
@@ -166,16 +165,16 @@ if (typeof document != "undefined")
if (canvasElement && canvasElement.getContext)
{
PLATFORM_FEATURES |= CPHTMLCanvasFeature;
// Detect Canvas setTransform/transform support
var context = document.createElement("canvas").getContext("2d");
if (context && context.setTransform && context.transform)
PLATFORM_FEATURES |= CPJavaScriptCanvasTransformFeature;
}
var DOMElement = document.createElement("div");
// Detect whether we have innerText or textContent (or neither)
if (DOMElement.innerText != undefined)
PLATFORM_FEATURES |= CPJavascriptInnerTextFeature;
+64 -176
View File
@@ -23,8 +23,9 @@
@import "CPFont.j"
@import "CPShadow.j"
@import "CPView.j"
@import "CPKeyValueBinding.j"
#include "CoreGraphics/CGGeometry.h"
#include "Platform/Platform.h"
CPLeftTextAlignment = 0;
CPRightTextAlignment = 1;
@@ -74,7 +75,7 @@ CPControlTextDidEndEditingNotification = "CPControlTextDidEndEditingNotific
var CPControlBlackColor = [CPColor blackColor];
/*!
/*!
@ingroup appkit
@class CPControl
@@ -83,7 +84,7 @@ var CPControlBlackColor = [CPColor blackColor];
@implementation CPControl : CPView
{
id _value;
// Target-Action Support
id _target;
SEL _action;
@@ -125,46 +126,16 @@ var CPControlBlackColor = [CPColor blackColor];
@"max-size"]];
}
+ (void)initialize
{
if (self === [CPControl class])
{
[self exposeBinding:@"value"];
[self exposeBinding:@"objectValue"];
[self exposeBinding:@"stringValue"];
[self exposeBinding:@"integerValue"];
[self exposeBinding:@"intValue"];
[self exposeBinding:@"doubleValue"];
[self exposeBinding:@"floatValue"];
[self exposeBinding:@"enabled"];
}
}
- (void)_reverseSetBinding
{
var theBinding = [CPKeyValueBinding getBinding:CPValueBinding forObject:self];
[theBinding reverseSetValueFor:@"objectValue"];
}
- (void)_replacementKeyPathForBinding:(CPString)aBinding
{
if (aBinding === @"value")
return @"objectValue";
return [super _replacementKeyPathForBinding:aBinding];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_sendActionOn = CPLeftMouseUpMask;
_trackingMouseDownFlags = 0;
}
return self;
}
@@ -209,16 +180,15 @@ var CPControlBlackColor = [CPColor blackColor];
*/
- (void)sendAction:(SEL)anAction to:(id)anObject
{
[self _reverseSetBinding];
[CPApp sendAction:anAction to:anObject from:self];
}
- (int)sendActionOn:(int)mask
{
var previousMask = _sendActionOn;
_sendActionOn = mask;
return previousMask;
}
@@ -231,7 +201,7 @@ var CPControlBlackColor = [CPColor blackColor];
{
if (_toolTip == aToolTip)
return;
_toolTip = aToolTip;
#if PLATFORM(DOM)
@@ -266,7 +236,7 @@ var CPControlBlackColor = [CPColor blackColor];
// Some subclasses should redefine this with CPLeftMouseDraggedMask
if (flag)
_sendActionOn |= CPPeriodicMask;
else
else
_sendActionOn &= ~CPPeriodicMask;
}
@@ -278,15 +248,16 @@ var CPControlBlackColor = [CPColor blackColor];
- (void)trackMouse:(CPEvent)anEvent
{
var type = [anEvent type],
currentLocation = [self convertPoint:[anEvent locationInWindow] fromView:nil],
currentLocation = [self convertPoint:[anEvent locationInWindow] fromView:nil];
isWithinFrame = [self tracksMouseOutsideOfFrame] || CGRectContainsPoint([self bounds], currentLocation);
if (type === CPLeftMouseUp)
{
[self stopTracking:_previousTrackingLocation at:currentLocation mouseIsUp:YES];
_trackingMouseDownFlags = 0;
}
else
{
if (type === CPLeftMouseDown)
@@ -300,20 +271,20 @@ var CPControlBlackColor = [CPColor blackColor];
{
if (!_trackingWasWithinFrame)
_continuousTracking = [self startTrackingAt:currentLocation];
else if (_continuousTracking)
_continuousTracking = [self continueTracking:_previousTrackingLocation at:currentLocation];
}
else
[self stopTracking:_previousTrackingLocation at:currentLocation mouseIsUp:NO];
}
[CPApp setTarget:self selector:@selector(trackMouse:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
}
if ((_sendActionOn & (1 << type)) && isWithinFrame)
[self sendAction:_action to:_target];
_trackingWasWithinFrame = isWithinFrame;
_previousTrackingLocation = currentLocation;
}
@@ -327,26 +298,13 @@ var CPControlBlackColor = [CPColor blackColor];
return 0;
}
- (void)performClick:(id)sender
- (void)performClick:(id)sender
{
if (![self isEnabled])
return;
[self highlight:YES];
[self setState:[self nextState]];
try
{
[self sendAction:[self action] to:[self target]];
}
catch (e)
{
throw e;
}
finally
{
[CPTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(unhighlightButtonTimerDidFinish:) userInfo:nil repeats:NO];
}
[self sendAction:[self action] to:[self target]];
[CPTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(unhighlightButtonTimerDidFinish:) userInfo:nil repeats:NO];
}
- (void)unhighlightButtonTimerDidFinish:(id)sender
@@ -362,7 +320,7 @@ var CPControlBlackColor = [CPColor blackColor];
- (BOOL)startTrackingAt:(CGPoint)aPoint
{
[self highlight:YES];
return (_sendActionOn & CPPeriodicMask) || (_sendActionOn & CPLeftMouseDraggedMask);
}
@@ -380,7 +338,7 @@ var CPControlBlackColor = [CPColor blackColor];
{
if (![self isEnabled])
return;
[self trackMouse:anEvent];
}
@@ -398,7 +356,7 @@ var CPControlBlackColor = [CPColor blackColor];
- (void)setObjectValue:(id)anObject
{
_value = anObject;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
@@ -472,7 +430,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Returns the receiver's string value
Returns the receiver's int value
*/
- (CPString)stringValue
{
@@ -480,7 +438,7 @@ var CPControlBlackColor = [CPColor blackColor];
}
/*!
Set's the receiver's string value
Set's the receiver's int value
*/
- (void)setStringValue:(CPString)anObject
{
@@ -527,124 +485,54 @@ var CPControlBlackColor = [CPColor blackColor];
[self setStringValue:[sender stringValue]];
}
- (void)textDidBeginEditing:(CPNotification)note
- (void)textDidBeginEditing:(CPNotification)note
{
//this looks to prevent false propagation of notifications for other objects
if ([note object] != self)
if([note object] != self)
return;
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidBeginEditingNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
}
- (void)textDidChange:(CPNotification)note
- (void)textDidChange:(CPNotification)note
{
//this looks to prevent false propagation of notifications for other objects
if ([note object] != self)
if([note object] != self)
return;
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidChangeNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
}
- (void)textDidEndEditing:(CPNotification)note
- (void)textDidEndEditing:(CPNotification)note
{
//this looks to prevent false propagation of notifications for other objects
if ([note object] != self)
if([note object] != self)
return;
[self _reverseSetBinding];
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidEndEditingNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
}
- (void)setAlignment:(CPTextAlignment)alignment
{
[self setValue:alignment forThemeAttribute:@"alignment"];
#define BRIDGE(UPPERCASE, LOWERCASE, ATTRIBUTENAME) \
/*! Sets the value for ATTRIBUTENAME */\
- (void)set##UPPERCASE:(id)aValue\
{\
[self setValue:aValue forThemeAttribute:ATTRIBUTENAME];\
}\
/*! Returns the current value for ATTRIBUTENAME */\
- (id)LOWERCASE\
{\
return [self valueForThemeAttribute:ATTRIBUTENAME];\
}
- (CPTextAlignment)alignment
{
return [self valueForThemeAttribute:@"alignment"];
}
- (void)setVerticalAlignment:(CPTextVerticalAlignment)alignment
{
[self setValue:alignment forThemeAttribute:@"vertical-alignment"];
}
- (CPTextVerticalAlignment)verticalAlignment
{
return [self valueForThemeAttribute:@"vertical-alignment"];
}
- (void)setLineBreakMode:(CPLineBreakMode)mode
{
[self setValue:mode forThemeAttribute:@"line-break-mode"];
}
- (CPLineBreakMode)lineBreakMode
{
return [self valueForThemeAttribute:@"line-break-mode"];
}
- (void)setTextColor:(CPColor)aColor
{
[self setValue:aColor forThemeAttribute:@"text-color"];
}
- (CPColor)textColor
{
return [self valueForThemeAttribute:@"text-color"];
}
- (void)setTextShadowColor:(CPColor)aColor
{
[self setValue:aColor forThemeAttribute:@"text-shadow-color"];
}
- (CPColor)textShadowColor
{
return [self valueForThemeAttribute:@"text-shadow-color"];
}
- (void)setTextShadowOffset:(float)offset
{
[self setValue:offset forThemeAttribute:@"text-shadow-offset"];
}
- (float)textShadowOffset
{
return [self valueForThemeAttribute:@"text-shadow-offset"];
}
- (void)setFont:(CPFont)aFont
{
[self setValue:aFont forThemeAttribute:@"font"];
}
- (CPFont)font
{
return [self valueForThemeAttribute:@"font"];
}
- (void)setImagePosition:(CPCellImagePosition)position
{
[self setValue:position forThemeAttribute:@"image-position"];
}
- (CPCellImagePosition)imagePosition
{
return [self valueForThemeAttribute:@"image-position"];
}
- (void)setImageScaling:(CPImageScaling)scaling
{
[self setValue:scaling forThemeAttribute:@"image-scaling"];
}
- (CPImageScaling)imageScaling
{
return [self valueForThemeAttribute:@"image-scaling"];
}
BRIDGE(Alignment, alignment, "alignment")
BRIDGE(VerticalAlignment, verticalAlignment, "vertical-alignment")
BRIDGE(LineBreakMode, lineBreakMode, "line-break-mode")
BRIDGE(TextColor, textColor, "text-color")
BRIDGE(Font, font, "font")
BRIDGE(TextShadowColor, textShadowColor, "text-shadow-color")
BRIDGE(TextShadowOffset, textShadowOffset, "text-shadow-offset")
BRIDGE(ImagePosition, imagePosition, "image-position")
BRIDGE(ImageScaling, imageScaling, "image-scaling")
- (void)setEnabled:(BOOL)isEnabled
{
@@ -682,7 +570,7 @@ var CPControlBlackColor = [CPColor blackColor];
var CPControlValueKey = "CPControlValueKey",
CPControlControlStateKey = @"CPControlControlStateKey",
CPControlIsEnabledKey = "CPControlIsEnabledKey",
CPControlTargetKey = "CPControlTargetKey",
CPControlActionKey = "CPControlActionKey",
CPControlSendActionOnKey = "CPControlSendActionOnKey",
@@ -712,7 +600,7 @@ var __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
[self sendActionOn:[aCoder decodeIntForKey:CPControlSendActionOnKey]];
[self setSendsActionOnEndEditing:[aCoder decodeBoolForKey:CPControlSendsActionOnEndEditingKey]];
}
return self;
}
@@ -748,7 +636,7 @@ var _CPControlSizeIdentifiers = [],
_CPControlSizeIdentifiers[CPRegularControlSize] = "Regular";
_CPControlSizeIdentifiers[CPSmallControlSize] = "Small";
_CPControlSizeIdentifiers[CPMiniControlSize] = "Mini";
function _CPControlIdentifierForControlSize(aControlSize)
{
return _CPControlSizeIdentifiers[aControlSize];
@@ -759,21 +647,21 @@ function _CPControlColorWithPatternImage(sizes, aClassName)
var index = 1,
count = arguments.length,
identifier = "";
for (; index < count; ++index)
identifier += arguments[index];
var color = _CPControlCachedColorWithPatternImages[identifier];
if (!color)
{
var bundle = [CPBundle bundleForClass:[CPControl class]];
color = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:aClassName + "/" + identifier + ".png"] size:sizes[identifier]]];
_CPControlCachedColorWithPatternImages[identifier] = color;
}
return color;
}
@@ -782,17 +670,17 @@ function _CPControlThreePartImagePattern(isVertical, sizes, aClassName)
var index = 2,
count = arguments.length,
identifier = "";
for (; index < count; ++index)
identifier += arguments[index];
var color = _CPControlCachedThreePartImagePattern[identifier];
if (!color)
{
var bundle = [CPBundle bundleForClass:[CPControl class]],
path = aClassName + "/" + identifier;
sizes = sizes[identifier];
color = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:[
@@ -800,9 +688,9 @@ function _CPControlThreePartImagePattern(isVertical, sizes, aClassName)
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + "1.png"] size:sizes[1]],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + "2.png"] size:sizes[2]]
] isVertical:isVertical]];
_CPControlCachedThreePartImagePattern[identifier] = color;
}
return color;
}
-88
View File
@@ -1,88 +0,0 @@
//
// CPController.j
// AppKit
//
// Created by Ross Boucher 1/15/09
// Copyright 280 North
//
// Adapted from GNUStep
// Copyright (C) 2007 Free Software Foundation, Inc
// Released under the LGPL.
//
@import <Foundation/CPObject.j>
var CPControllerDeclaredKeysKey = @"CPControllerDeclaredKeysKey";
@implementation CPController : CPObject
{
CPArray _editors;
CPArray _declaredKeys;
}
- (id)init
{
self = [super init];
if (self)
{
_editors = [];
_declaredKeys = [];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
if ([_declaredKeys count] > 0)
[aCoder encodeObject:_declaredKeys forKey:CPControllerDeclaredKeysKey];
}
- (id)initWithCoder:(CPCoder)aDecoder
{
self = [super init];
if (self)
{
_editors = [];
_declaredKeys = [aDecoder decodeObjectForKey:CPControllerDeclaredKeysKey] || [];
}
return nil;
}
- (BOOL)isEditing
{
return [_editors count] > 0;
}
- (BOOL)commitEditing
{
var index = 0,
count = _editors.length;
for (; index < count; ++index)
if (![[_editors objectAtIndex:i] commitEditing])
return NO;
return YES;
}
- (void)discardEditing
{
[_editors makeObjectsPerformSelector:@selector(discardEditing)];
}
- (void)objectDidBeginEditing:(id)anEditor
{
[_editors addObject:anEditor];
}
- (void)objectDidEndEditing:(id)anEditor
{
[_editors removeObject:anEditor];
}
@end
+20 -29
View File
@@ -24,7 +24,7 @@
@import <Foundation/CPString.j>
/*!
/*!
@ingroup appkit
@class CPCookie
CPCookie is the Cappuccino interface to a web browser cookie. You can set the name
@@ -33,7 +33,7 @@
{
CPString _cookieName;
CPString _cookieValue;
CPString _expires;
}
@@ -44,7 +44,7 @@
- (id)initWithName:(CPString)aName
{
self = [super init];
_cookieName = aName;
_cookieValue = [self _readCookieValue];
@@ -83,39 +83,30 @@
*/
- (void)setValue:(CPString)value expires:(CPDate)date domain:(CPString)domain
{
if (date)
var expires = "; expires=" + date.toGMTString();
else
if(date)
var expires = "; expires="+date.toGMTString();
else
var expires = "";
if (domain)
domain = "; domain=" + domain;
else
if(domain)
domain = "; domain="+domain;
else
domain = "";
#if PLATFORM(DOM)
document.cookie = _cookieName+"="+value+expires+"; path=/"+domain;
#else
_cookieValue = value;
_expires = expires;
#endif
document.cookie = _cookieName+"="+value+expires+"; path=/"+domain;
}
/* @ignore */
- (CPString)_readCookieValue
{
#if PLATFORM(DOM)
var nameEQ = _cookieName + "=",
ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++)
{
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
}
#endif
return "";
var nameEQ = _cookieName + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return "";
}
@end
+10 -15
View File
@@ -12,7 +12,7 @@ Implemented class methods:
Opera : All except resizeLeftRightCursor resizeUpDownCursor operationNotAllowedCursor dragCopyCursor dragLinkCursor contextualMenuCursor openHandCursor closedHandCursor disappearingItemCursor // Opera does not support url cursors so these won't work with images
*/
@import <Foundation/CPObject.j>
#include "Platform/Platform.h"
var currentCursor = nil,
cursorStack = [],
@@ -61,9 +61,9 @@ var currentCursor = nil,
if (CPBrowserIsEngine(CPGeckoBrowserEngine))
cursorURLFormat += ", default";
}
var url = [CPString stringWithFormat:cursorURLFormat, imageName];
return [[CPCursor alloc] initWithCSSString:url];
}
@@ -96,7 +96,7 @@ var currentCursor = nil,
{
if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
return [CPCursor cursorWithImageNamed:CPStringFromSelector(_cmd)];
return [CPCursor cursorWithCSSString:"s-resize"]; // WebKit | FF | opera
}
@@ -167,22 +167,18 @@ var currentCursor = nil,
{
if (CPBrowserIsEngine(CPWebKitBrowserEngine))
return [CPCursor cursorWithCSSString:@"-webkit-grab"];
else if (CPBrowserIsEngine(CPGeckoBrowserEngine))
return [CPCursor cursorWithCSSString:@"-moz-grab"];
else if (CPBrowserIsEngine(CPOperaBrowserEngine))
else if (CPBrowserIsEngine(CPGeckoBrowserEngine) || CPBrowserIsEngine(CPOperaBrowserEngine))
return [CPCursor cursorWithCSSString:@"move"];
return [CPCursor cursorWithImageNamed:CPStringFromSelector(_cmd)]; // WebKit only. move in FFMac|Opera
return [CPCursor cursorWithImageNamed:CPStringFromSelector(_cmd)]; // WebKit only. move in FFMac|Opera
}
+ (CPCursor)closedHandCursor
{
if (CPBrowserIsEngine(CPWebKitBrowserEngine))
return [CPCursor cursorWithCSSString:@"-webkit-grabbing"];
else if (CPBrowserIsEngine(CPGeckoBrowserEngine))
return [CPCursor cursorWithCSSString:@"-moz-grabbing"];
return [CPCursor cursorWithImageNamed:CPStringFromSelector(_cmd)]; // WebKit || FF
return [CPCursor cursorWithImageNamed:CPStringFromSelector(_cmd)]; // WebKit only
}
+ (CPCursor)disappearingItemCursor
@@ -197,7 +193,7 @@ var currentCursor = nil,
+ (void)unhide
{
[self _setCursorCSS:[currentCursor _cssString]];
[self _setCursorCSS:[currentCursor _cssString]]
}
+ (void)setHiddenUntilMouseMoves:(BOOL)flag
@@ -210,10 +206,9 @@ var currentCursor = nil,
- (id)initWithImage:(CPImage)image hotSpot:(CPPoint)hotSpot
{
return [self initWithCSSString:"url(" + [image filename] + "), auto"];
return [self initWithCSSString:"url(" + [image filename] + ")"];
}
- (void)mouseEntered:(CPEvent)event
{
}
@@ -224,7 +219,7 @@ var currentCursor = nil,
- (void)set
{
currentCursor = self;
currentCursor = self;
#if PLATFORM(DOM)
[[self class] _setCursorCSS:_cssString];
+50 -51
View File
@@ -23,7 +23,6 @@
@import <Foundation/CPString.j>
@import <Foundation/CPArray.j>
@import "CPApplication.j"
@import "CPResponder.j"
@import "CPSavePanel.j"
@import "CPViewController.j"
@@ -83,7 +82,7 @@ CPDocumentDidFailToSaveNotification = @"CPDocumentDidFailToSaveNotification";
var CPDocumentUntitledCount = 0;
/*!
/*!
@ingroup appkit
@class CPDocument
@@ -121,7 +120,7 @@ var CPDocumentUntitledCount = 0;
- (id)init
{
self = [super init];
if (self)
{
_windowControllers = [];
@@ -132,7 +131,7 @@ var CPDocumentUntitledCount = 0;
[self setNextResponder:CPApp];
}
return self;
}
@@ -145,10 +144,10 @@ var CPDocumentUntitledCount = 0;
- (id)initWithType:(CPString)aType error:({CPError})anError
{
self = [self init];
if (self)
[self setFileType:aType];
return self;
}
@@ -166,7 +165,7 @@ var CPDocumentUntitledCount = 0;
- (id)initWithContentsOfURL:(CPURL)anAbsoluteURL ofType:(CPString)aType delegate:(id)aDelegate didReadSelector:(SEL)aDidReadSelector contextInfo:(id)aContextInfo
{
self = [self init];
if (self)
{
[self setFileURL:anAbsoluteURL];
@@ -174,7 +173,7 @@ var CPDocumentUntitledCount = 0;
[self readFromURL:anAbsoluteURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo];
}
return self;
}
@@ -191,7 +190,7 @@ var CPDocumentUntitledCount = 0;
- (id)initForURL:(CPURL)anAbsoluteURL withContentsOfURL:(CPURL)absoluteContentsURL ofType:(CPString)aType delegate:(id)aDelegate didReadSelector:(SEL)aDidReadSelector contextInfo:(id)aContextInfo
{
self = [self init];
if (self)
{
[self setFileURL:anAbsoluteURL];
@@ -199,7 +198,7 @@ var CPDocumentUntitledCount = 0;
[self readFromURL:absoluteContentsURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo];
}
return self;
}
@@ -282,7 +281,7 @@ var CPDocumentUntitledCount = 0;
{
var view = [viewController view],
viewFrame = [view frame];
viewFrame.origin = CGPointMake(50, 50);
var theWindow = [[CPWindow alloc] initWithContentRect:viewFrame styleMask:CPTitledWindowMask | CPClosableWindowMask | CPMiniaturizableWindowMask | CPResizableWindowMask];
@@ -382,14 +381,14 @@ var CPDocumentUntitledCount = 0;
{
if (_fileURL)
return [_fileURL lastPathComponent];
if (!_untitledDocumentIndex)
_untitledDocumentIndex = ++CPDocumentUntitledCount;
if (_untitledDocumentIndex == 1)
return @"Untitled";
if (_untitledDocumentIndex == 1)
return @"Untitled";
return @"Untitled " + _untitledDocumentIndex;
return @"Untitled " + _untitledDocumentIndex;
}
- (CPString)viewCibName
@@ -458,7 +457,7 @@ var CPDocumentUntitledCount = 0;
return;
_fileURL = aFileURL;
[_windowControllers makeObjectsPerformSelector:@selector(synchronizeWindowTitleWithDocumentName)];
}
@@ -510,21 +509,21 @@ var CPDocumentUntitledCount = 0;
// If we got this far and it wasn't an HTTP request, then everything is fine.
if (![aResponse isKindOfClass:[CPHTTPURLResponse class]])
return;
var statusCode = [aResponse statusCode];
// Nothing to do if everything is hunky dory.
if (statusCode === 200)
return;
var session = aConnection.session;
if (aConnection == _readConnection)
{
[aConnection cancel];
alert("There was an error retrieving the document.");
objj_msgSend(session.delegate, session.didReadSelector, self, NO, session.contextInfo);
}
else
@@ -533,23 +532,23 @@ var CPDocumentUntitledCount = 0;
if (statusCode == 409)
{
[aConnection cancel];
if (confirm("There already exists a file with that name, would you like to overwrite it?"))
{
[_writeRequest setValue:@"true" forHTTPHeaderField:@"x-cappuccino-overwrite"];
[aConnection start];
}
else
else
{
if (session.saveOperation != CPSaveToOperation)
{
_changeCount += session.changeCount;
[_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[self isDocumentEdited]];
}
_writeRequest = nil;
objj_msgSend(session.delegate, session.didSaveSelector, self, NO, session.contextInfo);
[self _sendDocumentSavedNotification:NO];
}
@@ -564,7 +563,7 @@ var CPDocumentUntitledCount = 0;
- (void)connection:(CPURLConnection)aConnection didReceiveData:(CPString)aData
{
var session = aConnection.session;
// READ
if (aConnection == _readConnection)
{
@@ -576,9 +575,9 @@ var CPDocumentUntitledCount = 0;
{
if (session.saveOperation != CPSaveToOperation)
[self setFileURL:session.absoluteURL];
_writeRequest = nil;
objj_msgSend(session.delegate, session.didSaveSelector, self, YES, session.contextInfo);
[self _sendDocumentSavedNotification:YES];
}
@@ -591,17 +590,17 @@ var CPDocumentUntitledCount = 0;
- (void)connection:(CPURLConnection)aConnection didFailWithError:(CPError)anError
{
var session = aConnection.session;
if (_readConnection == aConnection)
objj_msgSend(session.delegate, session.didReadSelector, self, NO, session.contextInfo);
else
{
{
if (session.saveOperation != CPSaveToOperation)
{
_changeCount += session.changeCount;
[_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[self isDocumentEdited]];
}
}
_writeRequest = nil;
@@ -644,9 +643,9 @@ var CPDocumentUntitledCount = 0;
else if (aChangeType == CPChangeCleared)
_changeCount = 0;
/*else if (aChangeType == CPCHangeReadOtherContents)
else if (aChangeType == CPChangeAutosaved)*/
else if (aChangeType == CPChangeAutosaved)*/
[_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[self isDocumentEdited]];
}
@@ -686,9 +685,9 @@ var CPDocumentUntitledCount = 0;
{
if (_hasUndoManager == aFlag)
return;
_hasUndoManager = aFlag;
if (!_hasUndoManager)
[self setUndoManager:nil];
}
@@ -697,7 +696,7 @@ var CPDocumentUntitledCount = 0;
- (void)_undoManagerWillCloseGroup:(CPNotification)aNotification
{
var undoManager = [aNotification object];
if ([undoManager isUndoing] || [undoManager isRedoing])
return;
@@ -724,13 +723,13 @@ var CPDocumentUntitledCount = 0;
- (void)setUndoManager:(CPUndoManager)anUndoManager
{
var defaultCenter = [CPNotificationCenter defaultCenter];
if (_undoManager)
{
[defaultCenter removeObserver:self
name:CPUndoManagerDidUndoChangeNotification
object:_undoManager];
[defaultCenter removeObserver:self
name:CPUndoManagerDidRedoChangeNotification
object:_undoManager];
@@ -739,17 +738,17 @@ var CPDocumentUntitledCount = 0;
name:CPUndoManagerWillCloseUndoGroupNotification
object:_undoManager];
}
_undoManager = anUndoManager;
if (_undoManager)
{
[defaultCenter addObserver:self
selector:@selector(_undoManagerDidUndoChange:)
name:CPUndoManagerDidUndoChangeNotification
object:_undoManager];
[defaultCenter addObserver:self
selector:@selector(_undoManagerDidRedoChange:)
name:CPUndoManagerDidRedoChangeNotification
@@ -775,7 +774,7 @@ var CPDocumentUntitledCount = 0;
return _undoManager;
}
/*
Implemented as a delegate of a CPWindow
@ignore
@@ -804,7 +803,7 @@ var CPDocumentUntitledCount = 0;
[[CPNotificationCenter defaultCenter]
postNotificationName:CPDocumentWillSaveNotification
object:self];
[self saveToURL:_fileURL ofType:[self fileType] forSaveOperation:CPSaveOperation delegate:delegate didSaveSelector:didSaveSelector contextInfo:contextInfo];
}
else
@@ -862,7 +861,7 @@ var CPDocumentUntitledCount = 0;
[[CPDocumentController sharedDocumentController] removeDocument:self];
}
- (void)shouldCloseWindowController:(CPWindowController)controller delegate:(id)delegate shouldCloseSelector:(SEL)selector contextInfo:(Object)info
- (void)shouldCloseWindowController:(CPWindowController)controller delegate:(id)delegate shouldCloseSelector:(SEL)selector contextInfo:(Object)info
{
if ([controller shouldCloseDocument] || ([_windowControllers count] < 2 && [_windowControllers indexOfObject:controller] !== CPNotFound))
[self canCloseDocumentWithDelegate:self shouldCloseSelector:@selector(_document:shouldClose:context:) contextInfo:{delegate:delegate, selector:selector, context:info}];
@@ -879,7 +878,7 @@ var CPDocumentUntitledCount = 0;
objj_msgSend(context.delegate, context.selector, aDocument, shouldClose, context.context);
}
- (void)canCloseDocumentWithDelegate:(id)aDelegate shouldCloseSelector:(SEL)aSelector contextInfo:(Object)context
- (void)canCloseDocumentWithDelegate:(id)aDelegate shouldCloseSelector:(SEL)aSelector contextInfo:(Object)context
{
if (![self isDocumentEdited])
return [aDelegate respondsToSelector:aSelector] && objj_msgSend(aDelegate, aSelector, self, YES, context);
+22 -22
View File
@@ -29,7 +29,7 @@
var CPSharedDocumentController = nil;
/*!
/*!
@ingroup appkit
@class CPDocumentController
This class is responsible for managing an application's open documents.
@@ -41,7 +41,7 @@ var CPSharedDocumentController = nil;
}
/*!
Returns the singleton instance of the application's document controller. If it has not
Returns the singleton instance of the application's document controller. If it has not
been created yet, it will be created then returned.
@return a CPDocumentController
*/
@@ -49,7 +49,7 @@ var CPSharedDocumentController = nil;
{
if (!CPSharedDocumentController)
[[self alloc] init];
return CPSharedDocumentController;
}
@@ -59,11 +59,11 @@ var CPSharedDocumentController = nil;
- (id)init
{
self = [super init];
if (self)
{
_documents = [[CPArray alloc] init];
if (!CPSharedDocumentController)
CPSharedDocumentController = self;
@@ -85,16 +85,16 @@ var CPSharedDocumentController = nil;
{
var index = 0,
count = [_documents count];
for (; index < count; ++index)
for (; index < count; ++index)
{
var theDocument = _documents[index];
if ([[theDocument fileURL] isEqual:aURL])
return theDocument;
if ([[theDocument fileURL] isEqual:aURL])
return theDocument;
}
return nil;
return nil;
}
/*!
@@ -105,10 +105,10 @@ var CPSharedDocumentController = nil;
- (void)openUntitledDocumentOfType:(CPString)aType display:(BOOL)shouldDisplay
{
var theDocument = [self makeUntitledDocumentOfType:aType error:nil];
if (theDocument)
[self addDocument:theDocument];
if (shouldDisplay)
{
[theDocument makeWindowControllers];
@@ -210,7 +210,7 @@ var CPSharedDocumentController = nil;
return;
[aDocument makeWindowControllers];
if ([aContextInfo objectForKey:@"shouldDisplay"])
[aDocument showWindows];
}
@@ -224,7 +224,7 @@ var CPSharedDocumentController = nil;
[self openUntitledDocumentOfType:[[_documentTypes objectAtIndex:0] objectForKey:@"CPBundleTypeName"] display:YES];
}
- (void)openDocument:(id)aSender
-(void)openDocument:(id)aSender
{
var openPanel = [CPOpenPanel openPanel];
@@ -276,17 +276,17 @@ var CPSharedDocumentController = nil;
{
var index = 0,
count = _documentTypes.length,
extension = [[anAbsoluteURL pathExtension] lowercaseString],
starType = nil;
for (; index < count; ++index)
{
var documentType = _documentTypes[index],
extensions = [documentType objectForKey:@"CFBundleTypeExtensions"],
extensionIndex = 0,
extensionCount = extensions.length;
for (; extensionIndex < extensionCount; ++extensionIndex)
{
var thisExtension = [extensions[extensionIndex] lowercaseString];
@@ -312,11 +312,11 @@ var CPSharedDocumentController = nil;
for (;i < count; ++i)
{
var documentType = _documentTypes[i];
if ([documentType objectForKey:@"CPBundleTypeName"] == aType)
return documentType;
}
return nil;
}
@@ -336,7 +336,7 @@ var CPSharedDocumentController = nil;
@implementation CPDocumentController (Closing)
- (void)closeAllDocumentsWithDelegate:(id)aDelegate didCloseAllSelector:(SEL)didCloseSelector contextInfo:(Object)info
- (void)closeAllDocumentsWithDelegate:(id)aDelegate didCloseAllSelector:(SEL)didCloseSelector contextInfo:(Object)info
{
var context = {
delegate: aDelegate,
+11 -10
View File
@@ -20,12 +20,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPApplication.j"
@import "CPEvent.j"
@import "CPImageView.j"
@import "CPPasteboard.j"
@import "CPView.j"
@import "CPWindow.j"
@import <AppKit/CPView.j>
@import <AppKit/CPEvent.j>
@import <AppKit/CPPasteboard.j>
@import <AppKit/CPImageView.j>
#import "CoreGraphics/CGGeometry.h"
#import "Platform/Platform.h"
CPDragOperationNone = 0,
@@ -261,7 +262,7 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
{
var contentView = [scrollView contentView],
bounds = [contentView bounds],
insetBounds = CGRectInset(bounds, 10, 10),
insetBounds = CGRectInset(bounds, 10, 10)
eventLocation = [contentView convertPoint:_draggingLocation fromView:nil],
deltaX = 0,
deltaY = 0;
@@ -303,7 +304,7 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
- (void)_sendPeriodicDraggingUpdate:(CPTimer)aTimer
{
var userInfo = [aTimer userInfo];
_dragOperation = [self draggingUpdatedInPlatformWindow:[userInfo objectForKey:@"platformWindow"]
_dragOperation = [self draggingUpdatedInPlatformWindow:[userInfo objectForKey:@"platformWindow"]
location:[userInfo objectForKey:@"location"]];
}
@@ -327,8 +328,8 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
- (void)performDragOperationInPlatformWindow:(CPPlatformWindow)aPlatformWindow
{
if (_draggingDestination &&
(![_draggingDestination respondsToSelector:@selector(prepareForDragOperation:)] || [_draggingDestination prepareForDragOperation:CPDragServerDraggingInfo]) &&
if (_draggingDestination &&
(![_draggingDestination respondsToSelector:@selector(prepareForDragOperation:)] || [_draggingDestination prepareForDragOperation:CPDragServerDraggingInfo]) &&
(![_draggingDestination respondsToSelector:@selector(performDragOperation:)] || [_draggingDestination performDragOperation:CPDragServerDraggingInfo]) &&
[_draggingDestination respondsToSelector:@selector(concludeDragOperation:)])
[_draggingDestination concludeDragOperation:CPDragServerDraggingInfo];
+38 -165
View File
@@ -21,7 +21,8 @@
*/
@import <Foundation/CPObject.j>
@import "CPText.j"
#include "CoreGraphics/CGGeometry.h"
CPLeftMouseDown = 1;
@@ -40,7 +41,7 @@ CPAppKitDefined = 13;
CPSystemDefined = 14;
CPApplicationDefined = 15;
CPPeriodic = 16;
CPCursorUpdate = 17;
CPCursorUpdate = 17;
CPScrollWheel = 22;
CPOtherMouseDown = 25;
CPOtherMouseUp = 26;
@@ -51,7 +52,8 @@ CPTouchStart = 28;
CPTouchMove = 29;
CPTouchEnd = 30;
CPTouchCancel = 31;
CPAlphaShiftKeyMask = 1 << 16;
CPShiftKeyMask = 1 << 17;
CPControlKeyMask = 1 << 18;
@@ -85,102 +87,26 @@ CPPeriodicMask = 1 << CPPeriodic;
CPScrollWheelMask = 1 << CPScrollWheel;
CPAnyEventMask = 0xffffffff;
CPUpArrowFunctionKey = "\uF700";
CPDownArrowFunctionKey = "\uF701";
CPLeftArrowFunctionKey = "\uF702";
CPRightArrowFunctionKey = "\uF703";
CPF1FunctionKey = "\uF704";
CPF2FunctionKey = "\uF705";
CPF3FunctionKey = "\uF706";
CPF4FunctionKey = "\uF707";
CPF5FunctionKey = "\uF708";
CPF6FunctionKey = "\uF709";
CPF7FunctionKey = "\uF70A";
CPF8FunctionKey = "\uF70B";
CPF9FunctionKey = "\uF70C";
CPF10FunctionKey = "\uF70D";
CPF11FunctionKey = "\uF70E";
CPF12FunctionKey = "\uF70F";
CPF13FunctionKey = "\uF710";
CPF14FunctionKey = "\uF711";
CPF15FunctionKey = "\uF712";
CPF16FunctionKey = "\uF713";
CPF17FunctionKey = "\uF714";
CPF18FunctionKey = "\uF715";
CPF19FunctionKey = "\uF716";
CPF20FunctionKey = "\uF717";
CPF21FunctionKey = "\uF718";
CPF22FunctionKey = "\uF719";
CPF23FunctionKey = "\uF71A";
CPF24FunctionKey = "\uF71B";
CPF25FunctionKey = "\uF71C";
CPF26FunctionKey = "\uF71D";
CPF27FunctionKey = "\uF71E";
CPF28FunctionKey = "\uF71F";
CPF29FunctionKey = "\uF720";
CPF30FunctionKey = "\uF721";
CPF31FunctionKey = "\uF722";
CPF32FunctionKey = "\uF723";
CPF33FunctionKey = "\uF724";
CPF34FunctionKey = "\uF725";
CPF35FunctionKey = "\uF726";
CPInsertFunctionKey = "\uF727";
CPDeleteFunctionKey = "\uF728";
CPHomeFunctionKey = "\uF729";
CPBeginFunctionKey = "\uF72A";
CPEndFunctionKey = "\uF72B";
CPPageUpFunctionKey = "\uF72C";
CPPageDownFunctionKey = "\uF72D";
CPPrintScreenFunctionKey = "\uF72E";
CPScrollLockFunctionKey = "\uF72F";
CPPauseFunctionKey = "\uF730";
CPSysReqFunctionKey = "\uF731";
CPBreakFunctionKey = "\uF732";
CPResetFunctionKey = "\uF733";
CPStopFunctionKey = "\uF734";
CPMenuFunctionKey = "\uF735";
CPUserFunctionKey = "\uF736";
CPSystemFunctionKey = "\uF737";
CPPrintFunctionKey = "\uF738";
CPClearLineFunctionKey = "\uF739";
CPClearDisplayFunctionKey = "\uF73A";
CPInsertLineFunctionKey = "\uF73B";
CPDeleteLineFunctionKey = "\uF73C";
CPInsertCharFunctionKey = "\uF73D";
CPDeleteCharFunctionKey = "\uF73E";
CPPrevFunctionKey = "\uF73F";
CPNextFunctionKey = "\uF740";
CPSelectFunctionKey = "\uF741";
CPExecuteFunctionKey = "\uF742";
CPUndoFunctionKey = "\uF743";
CPRedoFunctionKey = "\uF744";
CPFindFunctionKey = "\uF745";
CPHelpFunctionKey = "\uF746";
CPModeSwitchFunctionKey = "\uF747";
CPEscapeFunctionKey = "\u001B";
CPDOMEventDoubleClick = "dblclick",
CPDOMEventMouseDown = "mousedown",
CPDOMEventMouseUp = "mouseup",
CPDOMEventMouseMoved = "mousemove",
CPDOMEventMouseDragged = "mousedrag",
CPDOMEventKeyUp = "keyup",
CPDOMEventKeyDown = "keydown",
CPDOMEventKeyPress = "keypress";
CPDOMEventCopy = "copy";
CPDOMEventPaste = "paste";
CPDOMEventScrollWheel = "mousewheel";
CPDOMEventTouchStart = "touchstart";
CPDOMEventTouchMove = "touchmove";
CPDOMEventTouchEnd = "touchend";
CPDOMEventTouchCancel = "touchcancel";
CPDOMEventDoubleClick = "dblclick",
CPDOMEventMouseDown = "mousedown",
CPDOMEventMouseUp = "mouseup",
CPDOMEventMouseMoved = "mousemove",
CPDOMEventMouseDragged = "mousedrag",
CPDOMEventKeyUp = "keyup",
CPDOMEventKeyDown = "keydown",
CPDOMEventKeyPress = "keypress";
CPDOMEventCopy = "copy";
CPDOMEventPaste = "paste";
CPDOMEventScrollWheel = "mousewheel";
CPDOMEventTouchStart = "touchstart";
CPDOMEventTouchMove = "touchmove";
CPDOMEventTouchEnd = "touchend";
CPDOMEventTouchCancel = "touchcancel";
var _CPEventPeriodicEventPeriod = 0,
_CPEventPeriodicEventTimer = nil,
_CPEventUpperCaseRegex = new RegExp("[A-Z]");
_CPEventPeriodicEventTimer = nil;
/*!
/*!
@ingroup appkit
@class CPEvent
CPEvent encapsulates the details of a Cappuccino keyboard or mouse event.
@@ -229,7 +155,7 @@ var _CPEventPeriodicEventPeriod = 0,
characters:(CPString)characters charactersIgnoringModifiers:(CPString)unmodCharacters isARepeat:(BOOL)repeatKey keyCode:(unsigned short)code
{
return [[self alloc] _initKeyEventWithType:anEventType location:aPoint modifierFlags:modifierFlags
timestamp:aTimestamp windowNumber:aWindowNumber context:aGraphicsContext
timestamp:aTimestamp windowNumber:aWindowNumber context:aGraphicsContext
characters:characters charactersIgnoringModifiers:unmodCharacters isARepeat:repeatKey keyCode:code];
}
@@ -247,7 +173,7 @@ var _CPEventPeriodicEventPeriod = 0,
@throws CPInternalInconsistencyException if an invalid event type is provided
@return the new mouse event
*/
+ (id)mouseEventWithType:(CPEventType)anEventType location:(CGPoint)aPoint modifierFlags:(unsigned)modifierFlags
+ (id)mouseEventWithType:(CPEventType)anEventType location:(CGPoint)aPoint modifierFlags:(unsigned)modifierFlags
timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext
eventNumber:(int)anEventNumber clickCount:(int)aClickCount pressure:(float)aPressure
{
@@ -278,12 +204,12 @@ var _CPEventPeriodicEventPeriod = 0,
}
/* @ignore */
- (id)_initMouseEventWithType:(CPEventType)anEventType location:(CPPoint)aPoint modifierFlags:(unsigned)modifierFlags
- (id)_initMouseEventWithType:(CPEventType)anEventType location:(CPPoint)aPoint modifierFlags:(unsigned)modifierFlags
timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext
eventNumber:(int)anEventNumber clickCount:(int)aClickCount pressure:(float)aPressure
{
self = [super init];
if (self)
{
_type = anEventType;
@@ -296,7 +222,7 @@ var _CPEventPeriodicEventPeriod = 0,
_pressure = aPressure;
_window = [CPApp windowWithWindowNumber:aWindowNumber];
}
return self;
}
@@ -306,7 +232,7 @@ var _CPEventPeriodicEventPeriod = 0,
characters:(CPString)characters charactersIgnoringModifiers:(CPString)unmodCharacters isARepeat:(BOOL)isARepeat keyCode:(unsigned short)code
{
self = [super init];
if (self)
{
_type = anEventType;
@@ -320,7 +246,7 @@ var _CPEventPeriodicEventPeriod = 0,
_keyCode = code;
_windowNumber = aWindowNumber;
}
return self;
}
@@ -330,7 +256,7 @@ var _CPEventPeriodicEventPeriod = 0,
subtype:(short)aSubtype data1:(int)aData1 data2:(int)aData2
{
self = [super init];
if (self)
{
_type = anEventType;
@@ -341,7 +267,7 @@ var _CPEventPeriodicEventPeriod = 0,
_subtype = aSubtype;
_data1 = aData1;
_data2 = aData2;
}
}
return self;
}
@@ -519,76 +445,23 @@ var _CPEventPeriodicEventPeriod = 0,
return _deltaZ;
}
- (BOOL)_triggersKeyEquivalent:(CPString)aKeyEquivalent withModifierMask:aKeyEquivalentModifierMask
{
if (!aKeyEquivalent)
return NO;
if (_CPEventUpperCaseRegex.test(aKeyEquivalent))
aKeyEquivalentModifierMask |= CPShiftKeyMask;
if (CPBrowserIsOperatingSystem(CPWindowsOperatingSystem) && (aKeyEquivalentModifierMask & CPCommandKeyMask))
{
aKeyEquivalentModifierMask |= CPControlKeyMask;
aKeyEquivalentModifierMask &= ~CPCommandKeyMask;
}
if ((_modifierFlags & (CPShiftKeyMask | CPAlternateKeyMask | CPCommandKeyMask | CPControlKeyMask)) !== aKeyEquivalentModifierMask)
return NO;
// Treat \r and \n as the same key equivalent. See issue #710.
if (_characters === CPNewlineCharacter || _characters === CPCarriageReturnCharacter)
return CPNewlineCharacter === aKeyEquivalent || CPCarriageReturnCharacter === aKeyEquivalent;
return [_characters caseInsensitiveCompare:aKeyEquivalent] === CPOrderedSame;
}
- (BOOL)_couldBeKeyEquivalent
{
if (_type !== CPKeyDown)
return NO;
var characterCount = _characters.length;
if (!characterCount)
return NO;
if (_modifierFlags & (CPCommandKeyMask | CPControlKeyMask))
return YES;
for(var i=0; i<characterCount; i++)
{
switch(_characters.charAt(i))
{
case CPBackspaceCharacter:
case CPDeleteCharacter:
case CPDeleteFunctionKey:
case CPTabCharacter:
case CPCarriageReturnCharacter:
case CPNewlineCharacter:
case CPEscapeFunctionKey:
case CPPageUpFunctionKey:
case CPPageDownFunctionKey:
case CPLeftArrowFunctionKey:
case CPUpArrowFunctionKey:
case CPRightArrowFunctionKey:
case CPDownArrowFunctionKey:
return YES;
}
}
// FIXME: More cases? Space?
return NO;
return _type === CPKeyDown &&
_modifierFlags & (CPCommandKeyMask | CPControlKeyMask) &&
[_characters length] > 0;
}
/*!
Gene rates periodic events every \c aPeriod seconds.
Generates periodic events every \c aPeriod seconds.
@param aDelay the number of seconds before the first event
@param aPeriod the length of time in seconds between successive events
*/
+ (void)startPeriodicEventsAfterDelay:(CPTimeInterval)aDelay withPeriod:(CPTimeInterval)aPeriod
{
_CPEventPeriodicEventPeriod = aPeriod;
// FIXME: OH TIMERS!!!
_CPEventPeriodicEventTimer = window.setTimeout(function() { _CPEventPeriodicEventTimer = window.setInterval(_CPEventFirePeriodEvent, aPeriod * 1000.0); }, aDelay * 1000.0);
}
@@ -600,9 +473,9 @@ var _CPEventPeriodicEventPeriod = 0,
{
if (_CPEventPeriodicEventTimer === nil)
return;
window.clearTimeout(_CPEventPeriodicEventTimer);
_CPEventPeriodicEventTimer = nil;
}
-1
View File
@@ -22,7 +22,6 @@
@import <Foundation/CPObject.j>
/*!
@ingroup appkit
@class CPFlashMovie
+1
View File
@@ -23,6 +23,7 @@
@import "CPFlashMovie.j"
@import "CPView.j"
#include "Platform/Platform.h"
var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
+8 -73
View File
@@ -20,12 +20,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPObject.j>
@import <Foundation/CPBundle.j>
@import "CPView.j"
var _CPFonts = {},
_CPFontSystemFontFace = @"Arial, sans-serif",
_CPWrapRegExp = new RegExp("\\s*,\\s*", "g");
@@ -34,7 +28,7 @@ var _CPFonts = {},
#define _CPCreateCSSString(aName, aSize, isBold) (isBold ? @"bold " : @"") + ROUND(aSize) + @"px " + ((aName === _CPFontSystemFontFace) ? aName : (@"\"" + aName.replace(_CPWrapRegExp, '", "') + @"\", " + _CPFontSystemFontFace))
#define _CPCachedFont(aName, aSize, isBold) _CPFonts[_CPCreateCSSString(aName, aSize, isBold)]
/*!
/*!
@ingroup appkit
@class CPFont
@@ -44,22 +38,11 @@ var _CPFonts = {},
{
CPString _name;
float _size;
float _ascender;
float _descender;
float _lineHeight;
BOOL _isBold;
CPString _cssString;
}
+ (void)initialize
{
var systemFont = [[CPBundle bundleForClass:[CPView class]] objectForInfoDictionaryKey:"CPSystemFontFace"];
if (systemFont)
_CPFontSystemFontFace = systemFont;
}
/*!
Returns a font with the specified name and size.
@param aName the name of the font
@@ -106,64 +89,25 @@ var _CPFonts = {},
@ignore
*/
- (id)_initWithName:(CPString)aName size:(float)aSize bold:(BOOL)isBold
{
{
self = [super init];
if (self)
{
_name = aName;
_size = aSize;
_ascender = 0;
_descender = 0;
_lineHeight = 0;
_isBold = isBold;
_cssString = _CPCreateCSSString(_name, _size, _isBold);
_CPFonts[_cssString] = self;
}
return self;
}
/*!
Returns the distance of the longest ascender's top y-coordinate from the baseline (in CSS px)
*/
- (float)ascender
{
if (!_ascender)
[self _getMetrics];
return _ascender;
}
/*!
Returns the bottom y coordinate (in CSS px), offset from the baseline, of the receiver's longest descender.
Thus, if the longest descender extends 2 points below the baseline, descender will return 2.
*/
- (float)descender
{
if (!_descender)
[self _getMetrics];
return _descender;
}
/*!
Returns the default line height.
NOTE: This was moved from NSFont to NSLayoutManager in Cocoa, but since there is no CPLayoutManager, it has been kept here.
*/
- (float)defaultLineHeightForFont
{
if (!_lineHeight)
[self _getMetrics];
return _lineHeight;
}
/*!
Returns the font size (in CSS px)
Returns the font size (in points)
*/
- (float)size
{
@@ -196,15 +140,6 @@ var _CPFonts = {},
return [CPString stringWithFormat:@"%@ %@ %f pt.", [super description], [self familyName], [self size]];
}
- (void)_getMetrics
{
var metrics = [CPString metricsOfFont:self];
_ascender = [metrics objectForKey:@"ascender"];
_descender = [metrics objectForKey:@"descender"];
_lineHeight = [metrics objectForKey:@"lineHeight"];
}
@end
var CPFontNameKey = @"CPFontNameKey",
+1 -1
View File
@@ -22,7 +22,7 @@
@import <Foundation/CPObject.j>
@import "CPFont.j"
@import <AppKit/CPFont.j>
var CPSharedFontManager = nil,
+15 -29
View File
@@ -70,7 +70,7 @@ function CPPointMake(x, y)
*/
function CPRectInset(aRect, dX, dY)
{
return CPRectMake( aRect.origin.x + dX, aRect.origin.y + dY,
return CPRectMake( aRect.origin.x + dX, aRect.origin.y + dY,
aRect.size.width - 2 * dX, aRect.size.height - 2*dY);
}
@@ -96,13 +96,13 @@ function CPRectIntegral(aRect)
function CPRectIntersection(lhsRect, rhsRect)
{
var intersection = CPRectMake(
Math.max(CPRectGetMinX(lhsRect), CPRectGetMinX(rhsRect)),
Math.max(CPRectGetMinY(lhsRect), CPRectGetMinY(rhsRect)),
Math.max(CPRectGetMinX(lhsRect), CPRectGetMinX(rhsRect)),
Math.max(CPRectGetMinY(lhsRect), CPRectGetMinY(rhsRect)),
0, 0);
intersection.size.width = Math.min(CPRectGetMaxX(lhsRect), CPRectGetMaxX(rhsRect)) - CPRectGetMinX(intersection);
intersection.size.height = Math.min(CPRectGetMaxY(lhsRect), CPRectGetMaxY(rhsRect)) - CPRectGetMinY(intersection);
return CPRectIsEmpty(intersection) ? CPRectMakeZero() : intersection;
}
@@ -160,13 +160,13 @@ function CPRectStandardize(aRect)
standardized.origin.x += width;
standardized.size.width = -width;
}
if (height < 0.0)
{
standardized.origin.y += height;
standardized.size.height = -height;
}
return standardized;
}
@@ -183,7 +183,7 @@ function CPRectUnion(lhsRect, rhsRect)
minY = Math.min(CPRectGetMinY(lhsRect), CPRectGetMinY(rhsRect)),
maxX = Math.max(CPRectGetMaxX(lhsRect), CPRectGetMaxX(rhsRect)),
maxY = Math.max(CPRectGetMaxY(lhsRect), CPRectGetMaxY(rhsRect));
return CPRectMake(minX, minY, maxX - minX, maxY - minY);
}
@@ -222,8 +222,8 @@ function CPRectContainsPoint(aRect, aPoint)
{
return aPoint.x >= CPRectGetMinX(aRect) &&
aPoint.y >= CPRectGetMinY(aRect) &&
aPoint.x < CPRectGetMaxX(aRect) &&
aPoint.y < CPRectGetMaxY(aRect);
aPoint.x < CPRectGetMaxX(aRect) &&
aPoint.y < CPRectGetMaxY(aRect);
}
/*!
@@ -261,7 +261,7 @@ function CPPointEqualToPoint(lhsPoint, rhsPoint)
*/
function CPRectEqualToRect(lhsRect, rhsRect)
{
return CPPointEqualToPoint(lhsRect.origin, rhsRect.origin) &&
return CPPointEqualToPoint(lhsRect.origin, rhsRect.origin) &&
CPSizeEqualToSize(lhsRect.size, rhsRect.size);
}
@@ -380,20 +380,6 @@ function CPRectIsNull(aRect)
return aRect.size.width <= 0.0 || aRect.size.height <= 0.0;
}
/*!
Creates two rectangles -- slice and rem -- from inRect, by dividing inRect
with a line that's parallel to the side of inRect specified by edge.
The size of slice is determined by amount, which specifies the distance from edge.
slice and rem must not be NULL.
@group CGRect
*/
function CPDivideRect(inRect, slice, rem, amount, edge)
{
CGRectDivide(inRect, slice, rem, amount, edge);
}
/*!
Returns \c YES if the two CGSizes are identical.
@group CGSize
@@ -448,7 +434,7 @@ function CPStringFromRect(aRect)
function CPPointFromString(aString)
{
var comma = aString.indexOf(',');
return { x:parseFloat(aString.substr(1, comma - 1), 10), y:parseFloat(aString.substring(comma + 1, aString.length), 10) };
}
@@ -461,7 +447,7 @@ function CPPointFromString(aString)
function CPSizeFromString(aString)
{
var comma = aString.indexOf(',');
return { width:parseFloat(aString.substr(1, comma - 1), 10), height:parseFloat(aString.substring(comma + 1, aString.length), 10) };
}
@@ -474,7 +460,7 @@ function CPSizeFromString(aString)
function CPRectFromString(aString)
{
var comma = aString.indexOf(',', aString.indexOf(',') + 1);
return { origin:CPPointFromString(aString.substr(1, comma - 1)), size:CPSizeFromString(aString.substring(comma + 2, aString.length)) };
}
@@ -518,6 +504,6 @@ function CPPointMakeZero()
return CPPointMake(0, 0, 0);
}
/*!
/*!
@}
*/
-108
View File
@@ -1,108 +0,0 @@
/*
* CPGraphics.j
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2010, 280 North, Inc.
*
* 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 "CPColor.j"
@import "CPGraphicsContext.j"
function CPDrawTiledRects(
/* CGRect */ boundsRect,
/* CGRect */ clipRect,
/* CPRectEdge[] */ sides,
/* float[] */ grays)
{
if (sides.length != grays.length)
[CPException raise:CPInvalidArgumentException reason:@"sides (length: " + sides.length + ") and grays (length: " + grays.length + ") must have the same length."];
var colors = [];
for (var i = 0; i < grays.length; ++i)
colors.push([CPColor colorWithCalibratedWhite:grays[i] alpha:1.0]);
return CPDrawColorTiledRects(boundsRect, clipRect, sides, colors);
}
function CPDrawColorTiledRects(
/* CGRect */ boundsRect,
/* CGRect */ clipRect,
/* CPRectEdge[] */ sides,
/* CPColor[] */ colors)
{
if (sides.length != colors.length)
[CPException raise:CPInvalidArgumentException reason:@"sides (length: " + sides.length + ") and colors (length: " + colors.length + ") must have the same length."];
var resultRect = _CGRectMakeCopy(boundsRect),
slice = _CGRectMakeZero(),
remainder = _CGRectMakeZero(),
context = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSaveGState(context);
CGContextSetLineWidth(context, 1.0);
for (var sideIndex = 0; sideIndex < sides.length; ++sideIndex)
{
var side = sides[sideIndex];
CGRectDivide(resultRect, slice, remainder, 1.0, side);
resultRect = remainder;
slice = CGRectIntersection(slice, clipRect);
// Cocoa docs say that only slices that are within the clipRect are actually drawn
if (_CGRectIsEmpty(slice))
continue;
var minX, maxX, minY, maxY;
if (side == CPMinXEdge || side == CPMaxXEdge)
{
// Make sure we have at least 1 pixel to draw a line
if (_CGRectGetWidth(slice) < 1.0)
continue;
minX = _CGRectGetMinX(slice) + 0.5;
maxX = minX;
minY = _CGRectGetMinY(slice);
maxY = _CGRectGetMaxY(slice);
}
else // CPMinYEdge || CPMaxYEdge
{
// Make sure we have at least 1 pixel to draw a line
if (_CGRectGetHeight(slice) < 1.0)
continue;
minX = _CGRectGetMinX(slice);
maxX = _CGRectGetMaxX(slice);
minY = _CGRectGetMinY(slice) + 0.5;
maxY = minY;
}
CGContextBeginPath(context);
CGContextMoveToPoint(context, minX, minY);
CGContextAddLineToPoint(context, maxX, maxY);
CGContextSetStrokeColor(context, colors[sideIndex]);
CGContextStrokePath(context);
}
CGContextRestoreGState(context);
return resultRect;
}
-5
View File
@@ -20,11 +20,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPObject.j>
@import "CGContext.j"
var CPGraphicsContextCurrent = nil;
/*!
+6 -9
View File
@@ -28,6 +28,8 @@
@import "CPGeometry.j"
#include "Platform/Platform.h"
CPImageLoadStatusInitialized = 0;
CPImageLoadStatusLoading = 1;
@@ -191,9 +193,6 @@ function CPAppKitImage(aFilename, aSize)
var imageOrSize = AppKitImageForNames[aName];
if (!imageOrSize)
return nil;
if (!imageOrSize.isa)
{
imageOrSize = CPAppKitImage("CPImage/" + aName + ".png", imageOrSize);
@@ -206,19 +205,17 @@ function CPAppKitImage(aFilename, aSize)
return imageOrSize;
}
- (BOOL)setName:(CPString)aName
- (void)setName:(CPString)aName
{
if (_name === aName)
return YES;
return;
if (imagesForNames[aName])
return NO;
if (imagesForNames[aName] === self)
imagesForNames[aName] = nil;
_name = aName;
imagesForNames[aName] = self;
return YES;
}
- (CPString)name
+17 -96
View File
@@ -26,23 +26,16 @@
@import "CPImage.j"
@import "CPShadowView.j"
#include "Platform/Platform.h"
#include "Platform/DOM/CPDOMDisplayServer.h"
#include "CoreGraphics/CGGeometry.h"
CPScaleProportionally = 0;
CPScaleToFit = 1;
CPScaleNone = 2;
CPImageAlignCenter = 0;
CPImageAlignTop = 1;
CPImageAlignTopLeft = 2;
CPImageAlignTopRight = 3;
CPImageAlignLeft = 4;
CPImageAlignBottom = 5;
CPImageAlignBottomLeft = 6;
CPImageAlignBottomRight = 7;
CPImageAlignRight = 8;
var CPImageViewShadowBackgroundColor = nil,
CPImageViewEmptyPlaceholderImage = nil;
var CPImageViewShadowBackgroundColor = nil;
var LEFT_SHADOW_INSET = 3.0,
RIGHT_SHADOW_INSET = 3.0,
@@ -59,22 +52,14 @@ var LEFT_SHADOW_INSET = 3.0,
*/
@implementation CPImageView : CPControl
{
DOMElement _DOMImageElement;
DOMElement _DOMImageElement;
BOOL _hasShadow;
CPView _shadowView;
BOOL _hasShadow;
CPView _shadowView;
BOOL _isEditable;
BOOL _isEditable;
CGRect _imageRect;
CPImageAlignment _imageAlignment;
}
+ (void)initialize
{
var bundle = [CPBundle bundleForClass:[CPView class]];
CPImageViewEmptyPlaceholderImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"empty.png"]];
CGRect _imageRect;
}
- (id)initWithFrame:(CGRect)aFrame
@@ -135,7 +120,7 @@ var LEFT_SHADOW_INSET = 3.0,
var newImage = [self objectValue];
#if PLATFORM(DOM)
_DOMImageElement.src = newImage ? [newImage filename] : [CPImageViewEmptyPlaceholderImage filename];
_DOMImageElement.src = newImage ? [newImage filename] : "";
#endif
var size = [newImage size];
@@ -206,30 +191,6 @@ var LEFT_SHADOW_INSET = 3.0,
[self hideOrDisplayContents];
}
/*!
Sets the type of image alignment that should be used to
render the image.
@param anImageAlignment the type of scaling to use
*/
- (void)setImageAlignment:(CPImageAlignment)anImageAlignment
{
if (_imageAlignment == anImageAlignment)
return;
_imageAlignment = anImageAlignment;
if (![self image])
return;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
- (unsigned)imageAlignment
{
return _imageAlignment;
}
/*!
Sets the type of image scaling that should be used to
render the image.
@@ -357,45 +318,8 @@ var LEFT_SHADOW_INSET = 3.0,
#endif
}
var x, y;
switch (_imageAlignment)
{
case CPImageAlignLeft:
case CPImageAlignTopLeft:
case CPImageAlignBottomLeft:
x = 0.0;
break;
case CPImageAlignRight:
case CPImageAlignTopRight:
case CPImageAlignBottomRight:
x = boundsWidth - width;
break;
default:
x = (boundsWidth - width) / 2.0;
break;
}
switch (_imageAlignment)
{
case CPImageAlignTop:
case CPImageAlignTopLeft:
case CPImageAlignTopRight:
y = 0.0;
break;
case CPImageAlignBottom:
case CPImageAlignBottomLeft:
case CPImageAlignBottomRight:
y = boundsHeight - height;
break;
default:
y = (boundsHeight - height) / 2.0;
break;
}
var x = (boundsWidth - width) / 2.0,
y = (boundsHeight - height) / 2.0;
#if PLATFORM(DOM)
CPDOMDisplayServerSetStyleLeftTop(_DOMImageElement, NULL, x, y);
@@ -456,11 +380,10 @@ var LEFT_SHADOW_INSET = 3.0,
@end
var CPImageViewImageKey = @"CPImageViewImageKey",
CPImageViewImageScalingKey = @"CPImageViewImageScalingKey",
CPImageViewImageAlignmentKey = @"CPImageViewImageAlignmentKey",
CPImageViewHasShadowKey = @"CPImageViewHasShadowKey",
CPImageViewIsEditableKey = @"CPImageViewIsEditableKey";
var CPImageViewImageKey = @"CPImageViewImageKey",
CPImageViewImageScalingKey = @"CPImageViewImageScalingKey",
CPImageViewHasShadowKey = @"CPImageViewHasShadowKey",
CPImageViewIsEditableKey = @"CPImageViewIsEditableKey";
@implementation CPImageView (CPCoding)
@@ -493,7 +416,6 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
#endif
[self setHasShadow:[aCoder decodeBoolForKey:CPImageViewHasShadowKey]];
[self setImageAlignment:[aCoder decodeIntForKey:CPImageViewImageAlignmentKey]];
if ([aCoder decodeBoolForKey:CPImageViewIsEditableKey] || NO)
[self setEditable:YES];
@@ -528,7 +450,6 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
_subviews = actualSubviews;
[aCoder encodeBool:_hasShadow forKey:CPImageViewHasShadowKey];
[aCoder encodeInt:_imageAlignment forKey:CPImageViewImageAlignmentKey];
if (_isEditable)
[aCoder encodeBool:_isEditable forKey:CPImageViewIsEditableKey];
-263
View File
@@ -1,263 +0,0 @@
/*
* CPKeyBinding.j
* AppKit
*
* Created by Nicholas Small.
* Copyright 2010, 280 North, Inc.
*
* 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 <Foundation/CPObject.j>
@import "CPEvent.j"
CPStandardKeyBindings = {
@"@.": @"cancelOperation:",
@"^a": @"moveToBeginningOfParagraph:",
@"^$a": @"moveToBeginningOfParagraphAndModifySelection:",
@"^b": @"moveBackward:",
@"^$b": @"moveBackwardAndModifySelection:",
@"^~b": @"moveWordBackward:",
@"^~$b": @"moveWordBackwardAndModifySelection:",
@"^d": @"deleteForward:",
@"^e": @"moveToEndOfParagraph:",
@"^$e": @"moveToEndOfParagraphAndModifySelection:",
@"^f": @"moveForward:",
@"^$f": @"moveForwardAndModifySelection:",
@"^~f": @"moveWordForward:",
@"^~$f": @"moveWordForwardAndModifySelection:",
@"^h": @"deleteBackward:",
@"^k": @"deleteToEndOfParagraph:",
@"^l": @"centerSelectionInVisibleArea:",
@"^n": @"moveDown:",
@"^$n": @"moveDownAndModifySelection:",
@"^o": [@"insertNewlineIgnoringFieldEditor:", @"moveBackward:"],
@"^p": @"moveUp:",
@"^$p": @"moveUpAndModifySelection:",
@"^t": @"transpose:",
@"^v": @"pageDown:",
@"^$v": @"pageDownAndModifySelection:",
@"^y": @"yank:"
};
CPStandardKeyBindings[CPNewlineCharacter] = @"insertNewline:";
CPStandardKeyBindings[CPCarriageReturnCharacter] = @"insertNewline:";
CPStandardKeyBindings[CPEnterCharacter] = @"insertNewline:";
CPStandardKeyBindings[@"~" + CPNewlineCharacter] = @"insertNewlineIgnoringFieldEditor:";
CPStandardKeyBindings[@"~" + CPCarriageReturnCharacter] = @"insertNewlineIgnoringFieldEditor:";
CPStandardKeyBindings[@"~" + CPEnterCharacter] = @"insertNewlineIgnoringFieldEditor:";
CPStandardKeyBindings[@"^" + CPNewlineCharacter] = @"insertLineBreak:";
CPStandardKeyBindings[@"^" + CPCarriageReturnCharacter] = @"insertLineBreak:";
CPStandardKeyBindings[@"^" + CPEnterCharacter] = @"insertLineBreak:";
CPStandardKeyBindings[CPBackspaceCharacter] = @"deleteBackward:";
CPStandardKeyBindings[@"~" + CPBackspaceCharacter] = @"deleteWordBackward:";
CPStandardKeyBindings[CPDeleteCharacter] = @"deleteBackward:";
CPStandardKeyBindings[@"@" + CPDeleteCharacter] = @"deleteToBeginningOfLine:";
CPStandardKeyBindings[@"~" + CPDeleteCharacter] = @"deleteWordBackward:";
CPStandardKeyBindings[@"^" + CPDeleteCharacter] = @"deleteBackwardByDecomposingPreviousCharacter:";
CPStandardKeyBindings[@"^~" + CPDeleteCharacter] = @"deleteWordBackward:";
CPStandardKeyBindings[CPDeleteFunctionKey] = @"deleteForward:";
CPStandardKeyBindings[@"~" + CPDeleteFunctionKey] = @"deleteWordForward:";
CPStandardKeyBindings[CPTabCharacter] = @"insertTab:";
CPStandardKeyBindings[@"~" + CPTabCharacter] = @"insertTabIgnoringFieldEditor:";
CPStandardKeyBindings[@"^" + CPTabCharacter] = @"selectNextKeyView:";
CPStandardKeyBindings[CPBackTabCharacter] = @"insertBacktab:";
CPStandardKeyBindings[@"^" + CPBackTabCharacter] = @"selectPreviousKeyView:";
CPStandardKeyBindings[CPEscapeFunctionKey] = @"cancelOperation:";
CPStandardKeyBindings[@"~" + CPEscapeFunctionKey] = @"complete:";
CPStandardKeyBindings[CPF5FunctionKey] = @"complete:";
CPStandardKeyBindings[CPLeftArrowFunctionKey] = @"moveLeft:";
CPStandardKeyBindings[@"~" + CPLeftArrowFunctionKey] = @"moveWordLeft:";
CPStandardKeyBindings[@"^" + CPLeftArrowFunctionKey] = @"moveToLeftEndOfLine:";
CPStandardKeyBindings[@"@" + CPLeftArrowFunctionKey] = @"moveToLeftEndOfLine:";
CPStandardKeyBindings[@"$" + CPLeftArrowFunctionKey] = @"moveLeftAndModifySelection:";
CPStandardKeyBindings[@"$~" + CPLeftArrowFunctionKey] = @"moveWordLeftAndModifySelection:";
CPStandardKeyBindings[@"$^" + CPLeftArrowFunctionKey] = @"moveToLeftEndOfLineAndModifySelection:";
CPStandardKeyBindings[@"$@" + CPLeftArrowFunctionKey] = @"moveToLeftEndOfLineAndModifySelection:";
CPStandardKeyBindings[@"@^" + CPLeftArrowFunctionKey] = @"makeBaseWritingDirectionRightToLeft:";
CPStandardKeyBindings[@"@^~" + CPLeftArrowFunctionKey] = @"makeTextWritingDirectionRightToLeft:";
CPStandardKeyBindings[CPRightArrowFunctionKey] = @"moveRight:";
CPStandardKeyBindings[@"~" + CPRightArrowFunctionKey] = @"moveWordRight:";
CPStandardKeyBindings[@"^" + CPRightArrowFunctionKey] = @"moveToRightEndOfLine:";
CPStandardKeyBindings[@"@" + CPRightArrowFunctionKey] = @"moveToRightEndOfLine:";
CPStandardKeyBindings[@"$" + CPRightArrowFunctionKey] = @"moveRightAndModifySelection:";
CPStandardKeyBindings[@"$~" + CPRightArrowFunctionKey] = @"moveWordRightAndModifySelection:";
CPStandardKeyBindings[@"$^" + CPRightArrowFunctionKey] = @"moveToRightEndOfLineAndModifySelection:";
CPStandardKeyBindings[@"$@" + CPRightArrowFunctionKey] = @"moveToRightEndOfLineAndModifySelection:";
CPStandardKeyBindings[@"@^" + CPRightArrowFunctionKey] = @"makeBaseWritingDirectionLeftToRight:";
CPStandardKeyBindings[@"@^~" + CPRightArrowFunctionKey] = @"makeTextWritingDirectionLeftToRight:";
CPStandardKeyBindings[CPUpArrowFunctionKey] = @"moveUp:";
CPStandardKeyBindings[@"~" + CPUpArrowFunctionKey] = [@"moveBackward:", @"moveToBeginningOfParagraph:"];
CPStandardKeyBindings[@"^" + CPUpArrowFunctionKey] = @"scrollPageUp:";
CPStandardKeyBindings[@"@" + CPUpArrowFunctionKey] = @"moveToBeginningOfDocument:";
CPStandardKeyBindings[@"$" + CPUpArrowFunctionKey] = @"moveUpAndModifySelection:";
CPStandardKeyBindings[@"$~" + CPUpArrowFunctionKey] = @"moveParagraphBackwardAndModifySelection:";
CPStandardKeyBindings[@"$@" + CPUpArrowFunctionKey] = @"moveToBeginningOfDocumentAndModifySelection:";
CPStandardKeyBindings[CPDownArrowFunctionKey] = @"moveDown:";
CPStandardKeyBindings[@"~" + CPDownArrowFunctionKey] = [@"moveForward:", @"moveToEndOfParagraph:"];
CPStandardKeyBindings[@"^" + CPDownArrowFunctionKey] = @"scrollPageDown:";
CPStandardKeyBindings[@"@" + CPDownArrowFunctionKey] = @"moveToEndOfDocument:";
CPStandardKeyBindings[@"$" + CPDownArrowFunctionKey] = @"moveDownAndModifySelection:";
CPStandardKeyBindings[@"$~" + CPDownArrowFunctionKey] = @"moveParagraphForwardAndModifySelection:";
CPStandardKeyBindings[@"$@" + CPDownArrowFunctionKey] = @"moveToEndOfDocumentAndModifySelection:";
CPStandardKeyBindings[@"@^" + CPDownArrowFunctionKey] = @"makeBaseWritingDirectionNatural:";
CPStandardKeyBindings[@"@^~" + CPDownArrowFunctionKey] = @"makeTextWritingDirectionNatural:";
CPStandardKeyBindings[CPHomeFunctionKey] = @"scrollToBeginningOfDocument:";
CPStandardKeyBindings[@"$" + CPHomeFunctionKey] = @"moveToBeginningOfDocumentAndModifySelection:";
CPStandardKeyBindings[CPEndFunctionKey] = @"scrollToEndOfDocument:";
CPStandardKeyBindings[@"$" + CPEndFunctionKey] = @"moveToEndOfDocumentAndModifySelection:";
CPStandardKeyBindings[CPPageUpFunctionKey] = @"scrollPageUp:";
CPStandardKeyBindings[@"~" + CPPageUpFunctionKey] = @"pageUp:";
CPStandardKeyBindings[@"$" + CPPageUpFunctionKey] = @"pageUpAndModifySelection:";
CPStandardKeyBindings[CPPageDownFunctionKey] = @"scrollPageDown:";
CPStandardKeyBindings[@"~" + CPPageDownFunctionKey] = @"pageDown:";
CPStandardKeyBindings[@"$" + CPPageDownFunctionKey] = @"pageDownAndModifySelection:";
var CPKeyBindingCache = {};
@implementation CPKeyBinding : CPObject
{
CPString _key;
unsigned _modifierFlags;
CPArray _selectors;
CPString _cacheName;
}
+ (void)initialize
{
if ([self class] !== CPKeyBinding)
return;
[self createKeyBindingsFromJSObject:CPStandardKeyBindings];
}
+ (void)createKeyBindingsFromJSObject:(JSObject)anObject
{
var binding;
for (binding in anObject)
[self cacheKeyBinding:[[CPKeyBinding alloc] initWithPhysicalKeyString:binding selectors:anObject[binding]]];
}
+ (void)cacheKeyBinding:(CPKeyBinding)aBinding
{
if (!aBinding)
return;
CPKeyBindingCache[[aBinding _cacheName]] = aBinding;
}
+ (CPKeyBinding)keyBindingForKey:(CPString)aKey modifierFlags:(unsigned)aFlag
{
var tempBinding = [[self alloc] initWithKey:aKey modifierFlags:aFlag selectors:nil];
return CPKeyBindingCache[[tempBinding _cacheName]];
}
+ (CPArray)selectorsForKey:(CPString)aKey modifierFlags:(unsigned)aFlag
{
return [[self keyBindingForKey:aKey modifierFlags:aFlag] selectors];
}
- (id)initWithPhysicalKeyString:(CPString)binding selectors:(CPArray)selectors
{
var components = binding.split(@""),
modifierFlags = ([components containsObject:@"$"] ? CPShiftKeyMask : 0) |
([components containsObject:@"^"] ? CPControlKeyMask : 0) |
([components containsObject:@"~"] ? CPAlternateKeyMask : 0) |
([components containsObject:@"@"] ? CPCommandKeyMask : 0);
if (![selectors isKindOfClass:CPArray])
selectors = [selectors];
return [self initWithKey:[components lastObject] modifierFlags:modifierFlags selectors:selectors];
}
- (id)initWithKey:(CPString)aKey modifierFlags:(unsigned)aFlag selectors:(CPArray)selectors
{
self = [super init];
if (self)
{
_key = aKey;
_modifierFlags = aFlag;
_selectors = selectors;
// We normalize our key binding string in order to properly cache it.
// We want to ensure the modifiers are always in the same order.
var cacheName = [];
if (_modifierFlags & CPCommandKeyMask)
cacheName.push(@"@");
if (_modifierFlags & CPControlKeyMask)
cacheName.push(@"^");
if (_modifierFlags & CPAlternateKeyMask)
cacheName.push(@"~");
if (_modifierFlags & CPShiftKeyMask)
cacheName.push(@"$");
cacheName.push(_key);
_cacheName = cacheName.join(@"");
}
return self;
}
- (CPString)key
{
return _key;
}
- (unsigned)modifierFlags
{
return _modifierFlags;
}
- (CPArray)selectors
{
return _selectors;
}
- (CPString)_cacheName
{
return _cacheName;
}
- (BOOL)isEqual:(CPKeyBinding)rhs
{
return _key === [rhs key] && _modifierFlags === [rhs modifierFlags];
}
- (CPString)description
{
return [CPString stringWithFormat:@"<KeyBinding string: '%@' modifierFlags: 0x%lx selectors: %@>", _key, _modifierFlags, _selectors];
}
@end
-472
View File
@@ -1,472 +0,0 @@
/*
* CPKeyValueBinding.j
* AppKit
*
* Created by Ross Boucher 1/13/09
* Copyright 280 North, Inc.
*
* Adapted from GNUStep
* Released under the LGPL.
*
* 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 <Foundation/CPObject.j>
@import <Foundation/CPArray.j>
@import <Foundation/CPDictionary.j>
@import <Foundation/CPValueTransformer.j>
var exposedBindingsMap = [CPDictionary new],
bindingsMap = [CPDictionary new];
var CPBindingOperationAnd = 0,
CPBindingOperationOr = 1;
@implementation CPKeyValueBinding : CPObject
{
CPDictionary _info;
id _source;
}
+ (void)exposeBinding:(CPString)aBinding forClass:(Class)aClass
{
var bindings = [exposedBindingsMap objectForKey:[aClass hash]];
if (!bindings)
{
bindings = [];
[exposedBindingsMap setObject:bindings forKey:[aClass hash]];
}
bindings.push(aBinding);
}
+ (CPArray)exposedBindingsForClass:(Class)aClass
{
return [[exposedBindingsMap objectForKey:[aClass hash]] copy];
}
+ (CPKeyValueBinding)getBinding:(CPString)aBinding forObject:(id)anObject
{
return [[bindingsMap objectForKey:[anObject hash]] objectForKey:aBinding];
}
+ (CPDictionary)infoForBinding:(CPString)aBinding forObject:(id)anObject
{
var theBinding = [self getBinding:aBinding forObject:anObject];
if (theBinding)
return theBinding._info;
return nil;
}
+ (CPDictionary)allBindingsForObject:(id)anObject
{
return [bindingsMap objectForKey:[anObject hash]];
}
+ (void)unbind:(CPString)aBinding forObject:(id)anObject
{
var bindings = [bindingsMap objectForKey:[anObject hash]];
if (!bindings)
return;
var theBinding = [bindings objectForKey:aBinding];
if (!theBinding)
return;
var infoDictionary = theBinding._info,
observedObject = [infoDictionary objectForKey:CPObservedObjectKey],
keyPath = [infoDictionary objectForKey:CPObservedKeyPathKey];
[observedObject removeObserver:theBinding forKeyPath:keyPath];
[bindings removeObjectForKey:aBinding];
}
+ (void)unbindAllForObject:(id)anObject
{
var bindings = [bindingsMap objectForKey:[anObject hash]];
if (!bindings)
return;
var allKeys = [bindings allKeys],
count = allKeys.length;
while (count--)
[anObject unbind:[bindings objectForKey:allKeys[count]]];
[bindingsMap removeObjectForKey:[anObject hash]];
}
- (id)initWithBinding:(CPString)aBinding name:(CPString)aName to:(id)aDestination keyPath:(CPString)aKeyPath options:(CPDictionary)options from:(id)aSource
{
self = [super init];
if (self)
{
_source = aSource;
_info = [CPDictionary dictionaryWithObjects:[aDestination, aKeyPath] forKeys:[CPObservedObjectKey, CPObservedKeyPathKey]];
if (options)
[_info setObject:options forKey:CPOptionsKey];
[aDestination addObserver:self forKeyPath:aKeyPath options:CPKeyValueObservingOptionNew context:aBinding];
var bindings = [bindingsMap objectForKey:[_source hash]];
if (!bindings)
{
bindings = [CPDictionary new];
[bindingsMap setObject:bindings forKey:[_source hash]];
}
[bindings setObject:self forKey:aName];
[self setValueFor:aBinding];
}
return self;
}
- (void)setValueFor:(CPString)aBinding
{
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey],
options = [_info objectForKey:CPOptionsKey],
newValue = [destination valueForKeyPath:keyPath],
isPlaceholder = CPIsControllerMarker(newValue);
if (isPlaceholder)
{
switch (newValue)
{
case CPMultipleValuesMarker:
newValue = [options objectForKey:CPMultipleValuesPlaceholderBindingOption] || @"Multiple Values";
break;
case CPNoSelectionMarker:
newValue = [options objectForKey:CPNoSelectionPlaceholderBindingOption] || @"No Selection";
break;
case CPNotApplicableMarker:
if ([options objectForKey:CPRaisesForNotApplicableKeysBindingOption])
[CPException raise:CPGenericException reason:@"can't transform non applicable key on: "+_source+" value: "+newValue];
newValue = [options objectForKey:CPNotApplicablePlaceholderBindingOption] || @"Not Applicable";
break;
}
}
else
{
// Only transform the value if the current value is not a placeholder
newValue = [self transformValue:newValue withOptions:options];
}
[_source setValue:newValue forKey:aBinding];
if ([_source respondsToSelector:@selector(_setCurrentValueIsPlaceholder:)])
[_source _setCurrentValueIsPlaceholder:isPlaceholder];
}
- (void)reverseSetValueFor:(CPString)aBinding
{
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey],
options = [_info objectForKey:CPOptionsKey],
newValue = [_source valueForKeyPath:aBinding];
newValue = [self reverseTransformValue:newValue withOptions:options];
[destination setValue:newValue forKeyPath:keyPath];
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)changes context:(id)context
{
if (!changes)
return;
[self setValueFor:context];
}
- (id)transformValue:(id)aValue withOptions:(CPDictionary)options
{
var valueTransformerName,
valueTransformer,
placeholder;
var valueTransformerName = [options objectForKey:CPValueTransformerNameBindingOption],
valueTransformer;
if (valueTransformerName)
{
valueTransformer = [CPValueTransformer valueTransformerForName:valueTransformerName];
if (!valueTransformer)
{
var valueTransformerClass = CPClassFromString(valueTransformerName);
if (valueTransformerClass)
{
valueTransformer = [[valueTransformerClass alloc] init];
[valueTransformerClass setValueTransformer:valueTransformer forName:valueTransformerName];
}
}
}
else
valueTransformer = [options objectForKey:CPValueTransformerBindingOption];
if (valueTransformer)
aValue = [valueTransformer transformedValue:aValue];
if (aValue === undefined || aValue === nil)
aValue = [options objectForKey:CPNullPlaceholderBindingOption] || nil;
return aValue;
}
- (id)reverseTransformValue:(id)aValue withOptions: (CPDictionary)options
{
var valueTransformerName = [options objectForKey:CPValueTransformerNameBindingOption],
valueTransformer;
if (valueTransformerName)
valueTransformer = [CPValueTransformer valueTransformerForName:valueTransformerName];
else
valueTransformer = [options objectForKey:CPValueTransformerBindingOption];
if (valueTransformer && [[valueTransformer class] allowsReverseTransformation])
aValue = [valueTransformer reverseTransformedValue:aValue];
return aValue;
}
@end
@implementation CPObject (KeyValueBindingCreation)
+ (void)exposeBinding:(CPString)aBinding
{
[CPKeyValueBinding exposeBinding:aBinding forClass:[self class]];
}
- (CPArray)exposedBindings
{
var exposedBindings = [],
theClass = [self class];
while (theClass)
{
var temp = [CPKeyValueBinding exposedBindingsForClass:theClass];
if (temp)
[exposedBindings addObjectsFromArray:temp];
theClass = [theClass superclass];
}
return exposedBindings;
}
- (Class)valueClassForBinding:(CPString)binding
{
return [CPString class];
}
- (void)bind:(CPString)aBinding toObject:(id)anObject withKeyPath:(CPString)aKeyPath options:(CPDictionary)options
{
if (!anObject || !aKeyPath)
return CPLog.error("Invalid object or path on "+self+" for "+aBinding);
//if (![[self exposedBindings] containsObject:aBinding])
// CPLog.warn("No binding exposed on "+self+" for "+aBinding);
[self unbind:aBinding];
[[CPKeyValueBinding alloc] initWithBinding:[self _replacementKeyPathForBinding:aBinding] name:aBinding to:anObject keyPath:aKeyPath options:options from:self];
}
- (CPDictionary)infoForBinding:(CPString)aBinding
{
return [CPKeyValueBinding infoForBinding:aBinding forObject:self];
}
- (void)unbind:(CPString)aBinding
{
[CPKeyValueBinding unbind:aBinding forObject:self];
}
- (id)_replacementKeyPathForBinding:(CPString)binding
{
return binding;
}
@end
@implementation _CPKeyValueOrBinding : CPKeyValueBinding
{
}
- (void)setValueFor:(CPString)aBinding
{
var bindings = [bindingsMap valueForKey:[_source hash]];
if (!bindings)
return;
[_source setValue:resolveMultipleValues(aBinding, bindings, CPBindingOperationOr) forKey:aBinding];
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)changes context:(id)context
{
[self setValueFor:context];
}
@end
@implementation _CPKeyValueAndBinding : CPKeyValueBinding
{
}
- (void)setValueFor:(CPString)aBinding
{
var bindings = [bindingsMap objectForKey:[_source hash]];
if (!bindings)
return;
[_source setValue:resolveMultipleValues(aBinding, bindings, CPBindingOperationAnd) forKey:aBinding];
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObejct change:(CPDictionary)changes context:(id)context
{
[self setValueFor:context];
}
@end
var resolveMultipleValues = function resolveMultipleValues(/*CPString*/key, /*CPDictionary*/bindings, /*GSBindingOperationKind*/operation)
{
var bindingName = key,
theBinding,
count = 1;
while (theBinding = [bindings objectForKey:bindingName])
{
var infoDictionary = theBinding._info,
object = [infoDictionary objectForKey:CPObservedObjectKey],
keyPath = [infoDictionary objectForKey:CPObservedKeyPathKey],
options = [infoDictionary objectForKey:CPOptionsKey];
var value = [theBinding transformValue:[object valueForKeyPath:keyPath] withOptions:options];
if (value == operation)
return operation;
bindingName = [CPString stringWithFormat:@"%@%i", key, ++count];
}
return !operation;
}
var invokeAction = function invokeAction(/*CPString*/targetKey, /*CPString*/argumentKey, /*CPDictionary*/bindings)
{
var theBinding = [bindings objectForKey:targetKey],
infoDictionary = theBinding._info,
object = [infoDictionary objectForKey:CPObservedObjectKey],
keyPath = [infoDictionary objectForKey:CPObservedKeyPathKey],
options = [infoDictionary objectForKey:CPOptionsKey],
target = [object valueForKeyPath:keyPath],
selector = [options objectForKey:CPSelectorNameBindingOption];
if (!target || !selector)
return;
var invocation = [CPInvocation invocationWithMethodSignature:[target methodSignatureForSelector:selector]];
[invocation setSelector:selector];
var bindingName = argumentKey,
count = 1;
while (theBinding = [bindings objectForKey:bindingName])
{
infoDictionary = theBinding._info;
keyPath = [infoDictionary objectForKey:CPObserverKeyPathKey];
object = [[infoDictionary objectForKey:CPObservedObjectKey] valueForKeyPath:keyPath];
if (object)
[invocation setArgument:object atIndex:++count];
bindingName = [CPString stringWithFormat:@"%@%i", argumentKey, count];
}
[invocation invoke];
}
// Keys in options dictionary
// Keys in dictionary returned by infoForBinding
CPObservedObjectKey = @"CPObservedObjectKey";
CPObservedKeyPathKey = @"CPObservedKeyPathKey";
CPOptionsKey = @"CPOptionsKey";
// special markers
CPMultipleValuesMarker = @"CPMultipleValuesMarker";
CPNoSelectionMarker = @"CPNoSelectionMarker";
CPNotApplicableMarker = @"CPNotApplicableMarker";
// Binding name constants
CPAlignmentBinding = @"CPAlignmentBinding";
CPEditableBinding = @"CPEditableBinding";
CPEnabledBinding = @"CPEnabledBinding";
CPFontBinding = @"CPFontBinding";
CPHiddenBinding = @"CPHiddenBinding";
CPSelectedIndexBinding = @"CPSelectedIndexBinding";
CPTextColorBinding = @"CPTextColorBinding";
CPToolTipBinding = @"CPToolTipBinding";
CPValueBinding = @"value";
//Binding options constants
CPAllowsEditingMultipleValuesSelectionBindingOption = @"CPAllowsEditingMultipleValuesSelectionBindingOption";
CPAllowsNullArgumentBindingOption = @"CPAllowsNullArgumentBindingOption";
CPConditionallySetsEditableBindingOption = @"CPConditionallySetsEditableBindingOption";
CPConditionallySetsEnabledBindingOption = @"CPConditionallySetsEnabledBindingOption";
CPConditionallySetsHiddenBindingOption = @"CPConditionallySetsHiddenBindingOption";
CPContinuouslyUpdatesValueBindingOption = @"CPContinuouslyUpdatesValueBindingOption";
CPCreatesSortDescriptorBindingOption = @"CPCreatesSortDescriptorBindingOption";
CPDeletesObjectsOnRemoveBindingsOption = @"CPDeletesObjectsOnRemoveBindingsOption";
CPDisplayNameBindingOption = @"CPDisplayNameBindingOption";
CPDisplayPatternBindingOption = @"CPDisplayPatternBindingOption";
CPHandlesContentAsCompoundValueBindingOption = @"CPHandlesContentAsCompoundValueBindingOption";
CPInsertsNullPlaceholderBindingOption = @"CPInsertsNullPlaceholderBindingOption";
CPInvokesSeparatelyWithArrayObjectsBindingOption = @"CPInvokesSeparatelyWithArrayObjectsBindingOption";
CPMultipleValuesPlaceholderBindingOption = @"CPMultipleValuesPlaceholderBindingOption";
CPNoSelectionPlaceholderBindingOption = @"CPNoSelectionPlaceholderBindingOption";
CPNotApplicablePlaceholderBindingOption = @"CPNotApplicablePlaceholderBindingOption";
CPNullPlaceholderBindingOption = @"CPNullPlaceholderBindingOption";
CPPredicateFormatBindingOption = @"CPPredicateFormatBindingOption";
CPRaisesForNotApplicableKeysBindingOption = @"CPRaisesForNotApplicableKeysBindingOption";
CPSelectorNameBindingOption = @"CPSelectorNameBindingOption";
CPSelectsAllWhenSettingContentBindingOption = @"CPSelectsAllWhenSettingContentBindingOption";
CPValidatesImmediatelyBindingOption = @"CPValidatesImmediatelyBindingOption";
CPValueTransformerNameBindingOption = @"CPValueTransformerNameBindingOption";
CPValueTransformerBindingOption = @"CPValueTransformerBindingOption";
CPIsControllerMarker = function(/*id*/anObject)
{
return anObject === CPMultipleValuesMarker || anObject === CPNoSelectionMarker || anObject === CPNotApplicableMarker;
}
+65 -52
View File
@@ -31,6 +31,9 @@
@import "CPMenuItem.j"
@import "CPPanel.j"
#include "../CoreGraphics/CGGeometry.h"
#include "../Platform/Platform.h"
CPMenuDidAddItemNotification = @"CPMenuDidAddItemNotification";
CPMenuDidChangeItemNotification = @"CPMenuDidChangeItemNotification";
@@ -47,11 +50,11 @@ var _CPMenuBarVisible = NO,
_CPMenuBarAttributes = nil,
_CPMenuBarSharedWindow = nil;
/*!
/*!
@ingroup appkit
@class CPMenu
Menus provide the user with a list of actions and/or submenus. Submenus themselves are full fledged menus
Menus provide the user with a list of actions and/or submenus. Submenus themselves are full fledged menus
and so a heirarchical structure appears.
*/
@implementation CPMenu : CPObject
@@ -66,13 +69,13 @@ var _CPMenuBarVisible = NO,
float _minimumWidth;
CPMutableArray _items;
BOOL _autoenablesItems;
BOOL _showsStateColumn;
id _delegate;
int _highlightedIndex;
CPMenuItem _highlightedIndex;
_CPMenuWindow _menuWindow;
}
@@ -92,7 +95,7 @@ var _CPMenuBarVisible = NO,
{
if (_CPMenuBarVisible === menuBarShouldBeVisible)
return;
_CPMenuBarVisible = menuBarShouldBeVisible;
if ([CPPlatform supportsNativeMainMenu])
@@ -102,13 +105,13 @@ var _CPMenuBarVisible = NO,
{
if (!_CPMenuBarSharedWindow)
_CPMenuBarSharedWindow = [[_CPMenuBarWindow alloc] init];
[_CPMenuBarSharedWindow setMenu:[CPApp mainMenu]];
[_CPMenuBarSharedWindow setTitle:_CPMenuBarTitle];
[_CPMenuBarSharedWindow setIconImage:_CPMenuBarIconImage];
[_CPMenuBarSharedWindow setIconImageAlphaValue:_CPMenuBarIconImageAlphaValue];
[_CPMenuBarSharedWindow setColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarBackgroundColor"]];
[_CPMenuBarSharedWindow setTextColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTextColor"]];
[_CPMenuBarSharedWindow setTitleColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTitleColor"]];
@@ -117,12 +120,12 @@ var _CPMenuBarVisible = NO,
[_CPMenuBarSharedWindow setHighlightColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightColor"]];
[_CPMenuBarSharedWindow setHighlightTextColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightTextColor"]];
[_CPMenuBarSharedWindow setHighlightTextShadowColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightTextShadowColor"]];
[_CPMenuBarSharedWindow orderFront:self];
}
else
[_CPMenuBarSharedWindow orderOut:self];
// FIXME: There must be a better way to do this.
#if PLATFORM(DOM)
[[CPPlatformWindow primaryPlatformWindow] resizeEvent:nil];
@@ -156,9 +159,9 @@ var _CPMenuBarVisible = NO,
{
if (_CPMenuBarAttributes == attributes)
return;
_CPMenuBarAttributes = [attributes copy];
var textColor = [attributes objectForKey:@"CPMenuBarTextColor"],
titleColor = [attributes objectForKey:@"CPMenuBarTitleColor"],
textShadowColor = [attributes objectForKey:@"CPMenuBarTextShadowColor"],
@@ -166,40 +169,40 @@ var _CPMenuBarVisible = NO,
highlightColor = [attributes objectForKey:@"CPMenuBarHighlightColor"],
highlightTextColor = [attributes objectForKey:@"CPMenuBarHighlightTextColor"],
highlightTextShadowColor = [attributes objectForKey:@"CPMenuBarHighlightTextShadowColor"];
if (!textColor && titleColor)
[_CPMenuBarAttributes setObject:titleColor forKey:@"CPMenuBarTextColor"];
else if (textColor && !titleColor)
[_CPMenuBarAttributes setObject:textColor forKey:@"CPMenuBarTitleColor"];
else if (!textColor && !titleColor)
{
[_CPMenuBarAttributes setObject:[CPColor colorWithRed:0.051 green:0.2 blue:0.275 alpha:1.0] forKey:@"CPMenuBarTextColor"];
[_CPMenuBarAttributes setObject:[CPColor colorWithRed:0.051 green:0.2 blue:0.275 alpha:1.0] forKey:@"CPMenuBarTitleColor"];
}
if (!textShadowColor && titleShadowColor)
[_CPMenuBarAttributes setObject:titleShadowColor forKey:@"CPMenuBarTextShadowColor"];
else if (textShadowColor && !titleShadowColor)
[_CPMenuBarAttributes setObject:textShadowColor forKey:@"CPMenuBarTitleShadowColor"];
else if (!textShadowColor && !titleShadowColor)
{
[_CPMenuBarAttributes setObject:[CPColor whiteColor] forKey:@"CPMenuBarTextShadowColor"];
[_CPMenuBarAttributes setObject:[CPColor whiteColor] forKey:@"CPMenuBarTitleShadowColor"];
}
if (!highlightColor)
[_CPMenuBarAttributes setObject:[CPColor colorWithCalibratedRed:94.0/255.0 green:130.0/255.0 blue:186.0/255.0 alpha:1.0] forKey:@"CPMenuBarHighlightColor"];
if (!highlightTextColor)
[_CPMenuBarAttributes setObject:[CPColor whiteColor] forKey:@"CPMenuBarHighlightTextColor"];
if (!highlightTextShadowColor)
[_CPMenuBarAttributes setObject:[CPColor blackColor] forKey:@"CPMenuBarHighlightTextShadowColor"];
if (_CPMenuBarSharedWindow)
{
[_CPMenuBarSharedWindow setColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarBackgroundColor"]];
@@ -228,7 +231,7 @@ var _CPMenuBarVisible = NO,
{
if (self === [CPApp mainMenu])
return MENUBAR_HEIGHT;
return 0.0;
}
@@ -246,18 +249,18 @@ var _CPMenuBarVisible = NO,
- (id)initWithTitle:(CPString)aTitle
{
self = [super init];
if (self)
{
_title = aTitle;
_items = [];
_autoenablesItems = YES;
_showsStateColumn = YES;
[self setMinimumWidth:0];
}
return self;
}
@@ -284,7 +287,7 @@ var _CPMenuBarVisible = NO,
[aMenuItem setMenu:self];
[_items insertObject:aMenuItem atIndex:anIndex];
[[CPNotificationCenter defaultCenter]
postNotificationName:CPMenuDidAddItemNotification
object:self
@@ -303,7 +306,7 @@ var _CPMenuBarVisible = NO,
- (CPMenuItem)insertItemWithTitle:(CPString)aTitle action:(SEL)anAction keyEquivalent:(CPString)aKeyEquivalent atIndex:(unsigned)anIndex
{
var item = [[CPMenuItem alloc] initWithTitle:aTitle action:anAction keyEquivalent:aKeyEquivalent];
[self insertItem:item atIndex:anIndex];
return item;
@@ -348,10 +351,10 @@ var _CPMenuBarVisible = NO,
{
if (anIndex < 0 || anIndex >= _items.length)
return;
[_items[anIndex] setMenu:nil];
[_items removeObjectAtIndex:anIndex];
[[CPNotificationCenter defaultCenter]
postNotificationName:CPMenuDidRemoveItemNotification
object:self
@@ -366,7 +369,7 @@ var _CPMenuBarVisible = NO,
{
if ([aMenuItem menu] != self)
return;
[[CPNotificationCenter defaultCenter]
postNotificationName:CPMenuDidChangeItemNotification
object:self
@@ -382,10 +385,10 @@ var _CPMenuBarVisible = NO,
- (CPMenuItem)itemWithTag:(int)aTag
{
var index = [self indexOfItemWithTag:aTag];
if (index == CPNotFound)
return nil;
return _items[index];
}
@@ -397,10 +400,10 @@ var _CPMenuBarVisible = NO,
- (CPMenuItem)itemWithTitle:(CPString)aTitle
{
var index = [self indexOfItemWithTitle:aTitle];
if (index == CPNotFound)
return nil;
return _items[index];
}
@@ -439,7 +442,7 @@ var _CPMenuBarVisible = NO,
{
if ([aMenuItem menu] !== self)
return CPNotFound;
return [_items indexOfObjectIdenticalTo:aMenuItem];
}
@@ -452,7 +455,7 @@ var _CPMenuBarVisible = NO,
{
var index = 0,
count = _items.length;
for (; index < count; ++index)
if ([_items[index] title] === aTitle)
return index;
@@ -469,7 +472,7 @@ var _CPMenuBarVisible = NO,
{
var index = 0,
count = _items.length;
for (; index < count; ++index)
if ([_items[index] tag] == aTag)
return index;
@@ -487,11 +490,11 @@ var _CPMenuBarVisible = NO,
{
var index = 0,
count = _items.length;
for (; index < count; ++index)
{
var item = _items[index];
if ([item target] == aTarget && (!anAction || [item action] == anAction))
return index;
}
@@ -508,7 +511,7 @@ var _CPMenuBarVisible = NO,
{
var index = 0,
count = _items.length;
for (; index < count; ++index)
if ([[_items[index] representedObject] isEqual:anObject])
return index;
@@ -525,7 +528,7 @@ var _CPMenuBarVisible = NO,
{
var index = 0,
count = _items.length;
for (; index < count; ++index)
if ([_items[index] submenu] == aMenu)
return index;
@@ -543,7 +546,7 @@ var _CPMenuBarVisible = NO,
{
[aMenuItem setTarget:aMenuItem];
[aMenuItem setAction:@selector(submenuAction:)];
[aMenuItem setSubmenu:aMenu];
}
@@ -680,7 +683,7 @@ var _CPMenuBarVisible = NO,
itemIndex = [self indexOfItem:anItem];
if (itemIndex === CPNotFound)
throw "In call to popUpMenuPositioningItem:atLocation:inView:callback:, menu item " +
throw "In call to popUpMenuPositioningItem:atLocation:inView:callback:, menu item " +
anItem + " is not present in menu " + self;
}
@@ -781,10 +784,10 @@ var _CPMenuBarVisible = NO,
+ (void)popUpContextMenu:(CPMenu)aMenu withEvent:(CPEvent)anEvent forView:(CPView)aView withFont:(CPFont)aFont
{
var delegate = [aMenu delegate];
if ([delegate respondsToSelector:@selector(menuWillOpen:)])
[delegate menuWillOpen:aMenu];
if (!aFont)
aFont = [CPFont systemFontOfSize:12.0];
@@ -935,7 +938,17 @@ var _CPMenuBarVisible = NO,
var item = _items[index],
modifierMask = [item keyEquivalentModifierMask];
if ([anEvent _triggersKeyEquivalent:[item keyEquivalent] withModifierMask:[item keyEquivalentModifierMask]])
if ([item keyEquivalent] === [[item keyEquivalent] uppercaseString])
modifierMask |= CPShiftKeyMask;
if (CPBrowserIsOperatingSystem(CPWindowsOperatingSystem) && (modifierMask & CPCommandKeyMask))
{
modifierMask |= CPControlKeyMask;
modifierMask &= ~CPCommandKeyMask;
}
if ((modifierFlags & (CPShiftKeyMask | CPAlternateKeyMask | CPCommandKeyMask | CPControlKeyMask)) == modifierMask &&
[characters caseInsensitiveCompare:[item keyEquivalent]] == CPOrderedSame)
{
if ([item isEnabled])
[self performActionForItemAtIndex:index];
@@ -943,7 +956,7 @@ var _CPMenuBarVisible = NO,
{
//beep?
}
return YES;
}
@@ -962,7 +975,7 @@ var _CPMenuBarVisible = NO,
- (void)performActionForItemAtIndex:(unsigned)anIndex
{
var item = _items[anIndex];
[CPApp sendAction:[item action] to:[item target] from:item];
}
@@ -1051,7 +1064,7 @@ var CPMenuTitleKey = @"CPMenuTitleKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
_title = [aCoder decodeObjectForKey:CPMenuTitleKey];
@@ -1063,7 +1076,7 @@ var CPMenuTitleKey = @"CPMenuTitleKey",
[self setMinimumWidth:0];
}
return self;
}
+4 -1
View File
@@ -1,4 +1,7 @@
@import "CPPanel.j"
#include "../CoreGraphics/CGGeometry.h"
#include "../Platform/Platform.h"
@import "_CPMenuWindow.j"
+4 -1
View File
@@ -1,3 +1,6 @@
#include "../CoreGraphics/CGGeometry.h"
@import <Foundation/CPObject.j>
@@ -93,7 +96,7 @@ var SharedMenuManager = nil;
// Close Menu Event.
if (type === CPAppKitDefined)
return [self completeTracking];
return [self completeTracking]
[CPApp setTarget:self selector:@selector(trackEvent:) forNextEventMatchingMask:CPPeriodicMask | CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPAppKitDefinedMask untilDate:nil inMode:nil dequeue:YES];
+2 -1
View File
@@ -1,4 +1,5 @@
@import "CPWindow.j"
#include "../CoreGraphics/CGGeometry.h"
var _CPMenuWindowPool = [],
+49 -91
View File
@@ -29,8 +29,7 @@
@import "CPView.j"
@import "_CPMenuItemView.j"
/*!
/*!
@ingroup appkit
@class CPMenuItem
@@ -44,39 +43,39 @@
CPString _title;
//CPAttributedString _attributedTitle;
CPFont _font;
id _target;
SEL _action;
BOOL _isEnabled;
BOOL _isHidden;
int _tag;
int _state;
CPImage _image;
CPImage _alternateImage;
CPImage _onStateImage;
CPImage _offStateImage;
CPImage _mixedStateImage;
CPMenu _submenu;
CPMenu _menu;
CPString _keyEquivalent;
unsigned _keyEquivalentModifierMask;
int _mnemonicLocation;
BOOL _isAlternate;
int _indentationLevel;
CPString _toolTip;
id _representedObject;
CPView _view;
_CPMenuItemView _menuItemView;
}
@@ -95,19 +94,19 @@
- (id)initWithTitle:(CPString)aTitle action:(SEL)anAction keyEquivalent:(CPString)aKeyEquivalent
{
self = [super init];
if (self)
{
_isSeparator = NO;
_title = aTitle;
_action = anAction;
_isEnabled = YES;
_tag = 0;
_state = CPOffState;
_keyEquivalent = aKeyEquivalent || @"";
_keyEquivalentModifierMask = CPPlatformActionKeyMask;
@@ -115,7 +114,7 @@
_mnemonicLocation = CPNotFound;
}
return self;
}
@@ -153,7 +152,7 @@
{
if (_isHidden == isHidden)
return;
_isHidden = isHidden;
[_menu itemChanged:self];
@@ -174,9 +173,9 @@
{
if (_isHidden)
return YES;
var supermenu = [_menu supermenu];
if ([[supermenu itemAtIndex:[supermenu indexOfItemWithSubmenu:_menu]] isHiddenOrHasHiddenAncestor])
return YES;
@@ -229,11 +228,11 @@
if (_title == aTitle)
return;
_title = aTitle;
[_menuItemView setDirty];
[_menu itemChanged:self];
}
@@ -261,11 +260,11 @@
{
if (_font == aFont)
return;
_font = aFont;
[_menu itemChanged:self];
[_menuItemView setDirty];
}
@@ -317,9 +316,9 @@ CPOffState
{
if (_state == aState)
return;
_state = aState;
[_menu itemChanged:self];
[_menuItemView setDirty];
@@ -347,11 +346,11 @@ CPOffState
{
if (_image == anImage)
return;
_image = anImage;
[_menuItemView setDirty];
[_menu itemChanged:self];
}
@@ -389,7 +388,7 @@ CPOffState
{
if (_onStateImage == anImage)
return;
_onStateImage = anImage;
[_menu itemChanged:self];
}
@@ -410,7 +409,7 @@ CPOffState
{
if (_offStateImage == anImage)
return;
_offStateImage = anImage;
[_menu itemChanged:self];
}
@@ -431,7 +430,7 @@ CPOffState
{
if (_mixedStateImage == anImage)
return;
_mixedStateImage = anImage;
[_menu itemChanged:self];
}
@@ -592,8 +591,7 @@ CPControlKeyMask
return @"";
var string = _keyEquivalent.toUpperCase(),
needsShift = _keyEquivalentModifierMask & CPShiftKeyMask ||
(string === _keyEquivalent && _keyEquivalent.toLowerCase() !== _keyEquivalent.toUpperCase());
needsShift = _keyEquivalentModifierMask & CPShiftKeyMask || string === _keyEquivalent;
if (CPBrowserIsOperatingSystem(CPMacOperatingSystem))
{
@@ -650,14 +648,14 @@ CPControlKeyMask
- (void)setTitleWithMnemonicLocation:(CPString)aTitle
{
var location = [aTitle rangeOfString:@"&"].location;
if (location == CPNotFound)
[self setTitle:aTitle];
else
{
[self setTitle:[aTitle substringToIndex:location] + [aTitle substringFromIndex:location + 1]];
[self setMnemonicLocation:location];
}
}
}
/*!
@@ -698,7 +696,7 @@ CPControlKeyMask
{
if (aLevel < 0)
[CPException raise:CPInvalidArgumentException reason:"setIndentationLevel: argument must be greater than or equal to 0."];
_indentationLevel = MIN(15, aLevel);
}
@@ -757,11 +755,11 @@ CPControlKeyMask
{
if (_view === aView)
return;
_view = aView;
[_menuItemView setDirty];
[_menu itemChanged:self];
}
@@ -783,48 +781,7 @@ CPControlKeyMask
return [[self menu] highlightedItem] == self;
}
#pragma mark CPObject Overrides
/*!
Returns a copy of the item. The copy does not belong If the item has a submenu, it is NOT copied.
*/
- (id)copy
{
var item = [[CPMenuItem alloc] init];
// No point in going through accessors and doing lots of unnecessary state checking/updating
item._isSeparator = _isSeparator;
[item setTitle:_title];
[item setFont:_font];
[item setTarget:_target];
[item setAction:_action];
[item setEnabled:_isEnabled];
[item setHidden:_isHidden]
[item setTag:_tag];
[item setState:_state];
[item setImage:_image];
[item setAlternateImage:_alternateImage];
[item setOnStateImage:_onStateImage];
[item setOffStateImage:_offStateImage];
[item setMixedStateImage:_mixedStateImage];
[item setKeyEquivalent:_keyEquivalent];
[item setKeyEquivalentModifierMask:_keyEquivalentModifierMask];
[item setMnemonicLocation:_mnemonicLocation];
[item setAlternate:_isAlternate];
[item setIndentationLevel:_indentationLevel];
[item setToolTip:_toolTip];
[item setRepresentedObject:_representedObject];
return item;
}
- (id)mutableCopy
{
return [self copy];
}
#pragma mark Internal
//
/*
@ignore
@@ -833,7 +790,7 @@ CPControlKeyMask
{
if (!_menuItemView)
_menuItemView = [[_CPMenuItemView alloc] initWithFrame:CGRectMakeZero() forMenuItem:self];
return _menuItemView;
}
@@ -887,15 +844,15 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
_isSeparator = [aCoder containsValueForKey:CPMenuItemIsSeparatorKey] && [aCoder decodeBoolForKey:CPMenuItemIsSeparatorKey];
_title = [aCoder decodeObjectForKey:CPMenuItemTitleKey];
// _font;
_target = [aCoder decodeObjectForKey:CPMenuItemTargetKey];
_action = [aCoder decodeObjectForKey:CPMenuItemActionKey];
@@ -903,6 +860,7 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
_isHidden = DEFAULT_VALUE(CPMenuItemIsHiddenKey, NO);
_tag = DEFAULT_VALUE(CPMenuItemTagKey, 0);
_state = DEFAULT_VALUE(CPMenuItemStateKey, CPOffState);
// int _state;
_image = DEFAULT_VALUE(CPMenuItemImageKey, nil);
_alternateImage = DEFAULT_VALUE(CPMenuItemAlternateImageKey, nil);
@@ -929,7 +887,7 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
_representedObject = DEFAULT_VALUE(CPMenuItemRepresentedObjectKey, nil);
_view = DEFAULT_VALUE(CPMenuItemViewKey, nil);
}
return self;
}
@@ -943,11 +901,11 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
[aCoder encodeBool:_isSeparator forKey:CPMenuItemIsSeparatorKey];
[aCoder encodeObject:_title forKey:CPMenuItemTitleKey];
[aCoder encodeObject:_target forKey:CPMenuItemTargetKey];
[aCoder encodeObject:_action forKey:CPMenuItemActionKey];
ENCODE_IFNOT(CPMenuItemIsEnabledKey, _isEnabled, YES);
ENCODE_IFNOT(CPMenuItemIsEnabledKey, _isEnabled, YES);
ENCODE_IFNOT(CPMenuItemIsHiddenKey, _isHidden, NO);
ENCODE_IFNOT(CPMenuItemTagKey, _tag, 0);
@@ -955,7 +913,7 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
ENCODE_IFNOT(CPMenuItemImageKey, _image, nil);
ENCODE_IFNOT(CPMenuItemAlternateImageKey, _alternateImage, nil);
ENCODE_IFNOT(CPMenuItemSubmenuKey, _submenu, nil);
ENCODE_IFNOT(CPMenuItemMenuKey, _menu, nil);
@@ -1,6 +1,3 @@
@import "CPView.j"
var HORIZONTAL_MARGIN = 8.0,
SUBMENU_INDICATOR_MARGIN = 3.0,
VERTICAL_MARGIN = 4.0;
@@ -65,7 +62,6 @@ var SelectionColor = nil,
_imageAndTextView = [[_CPImageAndTextView alloc] initWithFrame:CGRectMake(HORIZONTAL_MARGIN, 0.0, 0.0, 0.0)];
[_imageAndTextView setImagePosition:CPImageLeft];
[_imageAndTextView setImageOffset:3.0];
[_imageAndTextView setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_imageAndTextView setAutoresizingMask:CPViewMinYMargin | CPViewMaxYMargin];
+1 -1
View File
@@ -1,5 +1,5 @@
@import "CPView.j"
@import <AppKit/CPView.j>
@implementation _CPMenuItemSeparatorView : CPView
+5 -11
View File
@@ -1,6 +1,3 @@
@import "CPControl.j"
var LEFT_MARGIN = 3.0,
RIGHT_MARGIN = 14.0 + 3.0,
STATE_COLUMN_WIDTH = 14.0,
@@ -42,7 +39,7 @@ var SUBMENU_INDICATOR_COLOR = nil,
SUBMENU_INDICATOR_COLOR = [CPColor grayColor];
_CPMenuItemSelectionColor = [CPColor colorWithCalibratedRed:95.0 / 255.0 green:131.0 / 255.0 blue:185.0 / 255.0 alpha:1.0];
_CPMenuItemTextShadowColor = [CPColor colorWithCalibratedRed:26.0 / 255.0 green: 73.0 / 255.0 blue:109.0 / 255.0 alpha:1.0];
_CPMenuItemTextShadowColor = [CPColor colorWithCalibratedRed:26.0 / 255.0 green: 73.0 / 255.0 blue:109.0 / 255.0 alpha:1.0]
var bundle = [CPBundle bundleForClass:self];
@@ -260,13 +257,10 @@ var SUBMENU_INDICATOR_COLOR = nil,
[_keyEquivalentView setTextShadowColor:[self textShadowColor]];
}
if ([[_menuItem menu] showsStateColumn])
{
if (shouldHighlight)
[_stateView setImage:_CPMenuItemDefaultStateHighlightedImages[[_menuItem state]] || nil];
else
[_stateView setImage:_CPMenuItemDefaultStateImages[[_menuItem state]] || nil];
}
if (shouldHighlight)
[_stateView setImage:_CPMenuItemDefaultStateHighlightedImages[[_menuItem state]] || nil];
else
[_stateView setImage:_CPMenuItemDefaultStateImages[[_menuItem state]] || nil];
}
@end
+2 -4
View File
@@ -1,6 +1,4 @@
@import <AppKit/CPControl.j>
@import "_CPMenuItemSeparatorView.j"
@import "_CPMenuItemStandardView.j"
@import "_CPMenuItemMenuBarView.j"
@@ -45,7 +43,7 @@ var _CPMenuItemSelectionColor = nil,
return;
_CPMenuItemSelectionColor = [CPColor colorWithCalibratedRed:95.0 / 255.0 green:131.0 / 255.0 blue:185.0 / 255.0 alpha:1.0];
_CPMenuItemTextShadowColor = [CPColor colorWithCalibratedRed:26.0 / 255.0 green: 73.0 / 255.0 blue:109.0 / 255.0 alpha:1.0];
_CPMenuItemTextShadowColor = [CPColor colorWithCalibratedRed:26.0 / 255.0 green: 73.0 / 255.0 blue:109.0 / 255.0 alpha:1.0]
var bundle = [CPBundle bundleForClass:self];
@@ -254,4 +252,4 @@ var _CPMenuItemSelectionColor = nil,
CGContextFillPath(context);
}
@end
@end
-625
View File
@@ -1,625 +0,0 @@
@import <Foundation/CPDictionary.j>
@import <Foundation/CPCountedSet.j>
@import "CPController.j"
@implementation CPObjectController : CPController
{
id _contentObject;
id _selection;
Class _objectClass;
BOOL _isEditable;
BOOL _automaticallyPreparesContent;
CPCountedSet _observedKeys;
}
+ (id)initialize
{
[self exposeBinding:@"editable"];
[self exposeBinding:@"contentObject"];
}
+ (CPSet)keyPathsForValuesAffectingContentObject
{
return [CPSet setWithObjects:"content"];
}
+ (BOOL)automaticallyNotifiesObserversForKey:(CPString)aKey
{
if (aKey === @"contentObject")
return NO;
return YES;
}
+ (CPSet)keyPathsForValuesAffectingCanAdd
{
return [CPSet setWithObject:"editable"];
}
+ (CPSet)keyPathsForValuesAffectingCanInsert
{
return [CPSet setWithObject:"editable"];
}
+ (CPSet)keyPathsForValuesAffectingCanRemove
{
return [CPSet setWithObjects:"editable", "selection"];
}
- (id)init
{
return [self initWithContent:nil];
}
- (id)initWithContent:(id)aContent
{
if (self = [super init])
{
[self setContent:aContent];
[self setEditable:YES];
[self setObjectClass:[CPMutableDictionary class]];
_observedKeys = [[CPCountedSet alloc] init];
}
return self;
}
- (id)content
{
return _contentObject;
}
- (void)setContent:(id)aContent
{
[self willChangeValueForKey:@"contentObject"];
[self _selectionWillChange];
_contentObject = aContent;
[self didChangeValueForKey:@"contentObject"];
[self _selectionDidChange];
}
- (void)_setContentObject:(id)aContent
{
[self setContent:aContent];
}
- (id)_contentObject
{
return [self content];
}
- (void)setAutomaticallyPreparesContent:(BOOL)shouldAutomaticallyPrepareContent
{
_automaticallyPreparesContent = shouldAutomaticallyPrepareContent;
}
- (BOOL)automaticallyPreparesContent
{
return _automaticallyPreparesContent;
}
- (void)prepareContent
{
[self setContent:[self newObject]];
}
- (void)setObjectClass:(Class)aClass
{
_objectClass = aClass;
}
- (Class)objectClass
{
return _objectClass;
}
- (id)newObject
{
return [[[self objectClass] alloc] init];
}
- (void)addObject:(id)anObject
{
[self setContent:anObject];
[[CPKeyValueBinding getBinding:@"contentObject" forObject:self] reverseSetValueFor:@"contentObject"];
}
- (void)removeObject:(id)anObject
{
if ([self content] === anObject)
[self setContent:nil];
[[CPKeyValueBinding getBinding:@"contentObject" forObject:self] reverseSetValueFor:@"contentObject"];
}
- (void)add:(id)aSender
{
// FIXME: This should happen on the next run loop?
[self addObject:[self newObject]];
}
- (BOOL)canAdd
{
return [self isEditable];
}
- (void)remove:(id)aSender
{
// FIXME: This should happen on the next run loop?
[self removeObject:[self content]];
}
- (BOOL)canRemove
{
return [self isEditable] && [[self selectedObjects] count];
}
- (void)setEditable:(BOOL)shouldBeEditable
{
_isEditable = shouldBeEditable;
}
- (BOOL)isEditable
{
return _isEditable;
}
- (CPArray)selectedObjects
{
return [[_CPObservableArray alloc] initWithObjects:[_contentObject] count:1];
}
- (id)selection
{
return _selection;
}
- (void)_selectionWillChange
{
[_selection controllerWillChange];
[self willChangeValueForKey:@"selection"];
}
- (void)_selectionDidChange
{
if (_selection === undefined || _selection === nil)
_selection = [[CPControllerSelectionProxy alloc] initWithController:self];
[_selection controllerDidChange];
[self didChangeValueForKey:@"selection"];
}
- (id)observedKeys
{
return _observedKeys;
}
- (void)addObserver:(id)anObserver forKeyPath:(CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(id)context
{
[_observedKeys addObject:aKeyPath];
[super addObserver:anObserver forKeyPath:aKeyPath options:options context:context];
}
- (void)removeObserver:(id)anObserver forKeyPath:(CPString)aKeyPath
{
[_observedKeys removeObject:aKeyPath];
[super removeObserver:anObserver forKeyPath:aKeyPath];
}
@end
var CPObjectControllerObjectClassNameKey = @"CPObjectControllerObjectClassNameKey",
CPObjectControllerIsEditableKey = @"CPObjectControllerIsEditableKey",
CPObjectControllerAutomaticallyPreparesContentKey = @"CPObjectControllerAutomaticallyPreparesContentKey";
@implementation CPObjectController (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
var objectClassName = [aCoder decodeObjectForKey:CPObjectControllerObjectClassNameKey],
objectClass = CPClassFromString(objectClassName);
// FIXME: Error if objectClass === nil
[self setObjectClass:objectClass];
[self setEditable:[aCoder decodeBoolForKey:CPObjectControllerIsEditableKey]];
[self setAutomaticallyPreparesContent:[aCoder decodeBoolForKey:CPObjectControllerAutomaticallyPreparesContentKey] || NO];
_observedKeys = [[CPCountedSet alloc] init];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:CPStringFromClass(objectClass) forKey:CPObjectControllerObjectClassNameKey];
[aCoder encodeObject:[self isEditable] forKey:CPObjectControllerIsEditableKey];
if (![self automaticallyPreparesContent])
[aCoder encodeBOOL:YES forKey:CPObjectControllerAutomaticallyPreparesContentKey];
}
@end
@implementation _CPObservationProxy : CPObject
{
id _keyPath;
id _observer;
id _object;
BOOL _notifyObject;
id _context;
int _options;
}
- (id)initWithKeyPath:(id)aKeyPath observer:(id)anObserver object:(id)anObject
{
if (self=[super init])
{
_keyPath = aKeyPath;
_observer = anObserver;
_object = anObject;
}
return self;
}
- (id)observer
{
return _observer;
}
- (id)keyPath
{
return _keyPath;
}
- (id)context
{
return _context;
}
- (int)options
{
return _options;
}
- (void)setNotifyObject:(BOOL)notify
{
_notifyObject = notify;
}
- (BOOL)isEqual:(id)anObject
{
if ([anObject class] === [self class])
{
if (anObject._observer === _observer && [anObject._keyPath isEqual:_keyPath] && [anObject._object isEqual:_object])
return YES;
}
return NO;
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)change context:(id)context
{
if (_notifyObject)
[_object observeValueForKeyPath:_keyPath ofObject:_object change:change context:context];
[_observer observeValueForKeyPath:_keyPath ofObject:_object change:change context:context];
}
- (CPString)description
{
return [super description] + [CPString stringWithFormat:@"observation proxy for %@ on key path %@", _observer, _keyPath];
}
@end
@implementation _CPObservableArray : CPMutableArray
{
CPArray _observationProxies;
}
+ (id)alloc
{
var a = [];
a.isa = self;
var ivars = class_copyIvarList(self),
count = ivars.length;
while (count--)
a[ivar_getName(ivars[count])] = nil;
return a;
}
- (CPString)description
{
return "<_CPObservableArray: "+[super description]+" >";
}
- (id)initWithArray:(CPArray)anArray
{
if (self = [super initWithArray:anArray])
{
_observationProxies = [];
}
return self;
}
- (id)initWithObjects:(CPArray)objects count:(unsigned)count
{
if (self = [super initWithObjects:objects count:count])
{
_observationProxies = [];
}
return self;
}
-(void)addObserver:(id)anObserver forKeyPath:(CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(id)context
{
if (aKeyPath.indexOf("@") === 0)
{
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObserver object:self];
proxy._options = options;
proxy._context = context;
[_observationProxies addObject:proxy];
var dotIndex = aKeyPath.indexOf("."),
remaining = aKeyPath.substring(dotIndex+1),
indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self count])];
[self addObserver:proxy toObjectsAtIndexes:indexes forKeyPath:remaining options:options context:context];
}
else
{
var indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self count])];
[self addObserver:anObserver toObjectsAtIndexes:indexes forKeyPath:aKeyPath options:options context:context];
}
}
- (void)removeObserver:(id)anObserver forKeyPath:(CPString)aKeyPath
{
if (aKeyPath.indexOf("@") === 0)
{
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObserver object:self],
index = [_observationProxies indexOfObject:proxy];
proxy = [_observationProxies objectAtIndex:index];
var dotIndex = aKeyPath.indexOf("."),
remaining = aKeyPath.substring(dotIndex+1),
indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self count])];
[self removeObserver:proxy fromObjectsAtIndexes:indexes forKeyPath:remaining];
}
else
{
var indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self count])];
[self removeObserver:anObserver fromObjectsAtIndexes:indexes forKeyPath:aKeyPath];
}
}
- (void)insertObject:(id)anObject atIndex:(unsigned)anIndex
{
for (var i=0, count=[_observationProxies count]; i<count; i++)
{
var proxy = [_observationProxies objectAtIndex:i],
keyPath = [proxy keyPath],
operator = keyPath.indexOf(".") === 0;
if (operator)
[self willChangeValueForKey:keyPath];
[anObject addObserver:proxy forKeyPath:keyPath options:[proxy options] context:[proxy context]];
if (operator)
[self didChangeValueForKey:keyPath];
}
[super insertObject:anObject atIndex:anIndex];
}
- (void)removeObjectAtIndex:(unsigned)anIndex
{
for (var i=0, count=[_observationProxies count]; i<count; i++)
{
var proxy = [_observationProxies objectAtIndex:i],
keyPath = [proxy keyPath],
operator = keyPath.indexOf(".") === 0;
if (operator)
[self willChangeValueForKey:keyPath];
[anObject removeObserver:proxy forKeyPath:keyPath];
if (operator)
[self didChangeValueForKey:keyPath];
}
[super removeObjectAtIndex:anIndex];
}
- (_CPObservableArray)objectsAtIndexes:(CPIndexSet)theIndexes
{
return [_CPObservableArray arrayWithArray:[super objectsAtIndexes:theIndexes]];
}
- (void)addObject:(id)anObject
{
[self insertObject:anObject atIndex:[self count]];
}
- (void)removeLastObject
{
[self removeObjectAtIndex:[self count]];
}
- (void)replaceObjectAtIndex:(unsigned)anIndex withObject:(id)anObject
{
var currentObject = [self objectAtIndex:anIndex];
for (var i=0, count=[_observationProxies count]; i<count; i++)
{
var proxy = [_observationProxies objectAtIndex:i],
keyPath = [proxy keyPath],
operator = keyPath.indexOf(".") === 0;
if (operator)
[self willChangeValueForKey:keyPath];
[currentObject removeObserver:proxy forKeyPath:keyPath];
[anObject addObserver:proxy forKeyPath:keyPath options:[proxy options] context:[proxy context]];
if (operator)
[self didChangeValueForKey:keyPath];
}
[super replaceObjectAtIndex:anIndex withObject:anObject];
}
@end
@implementation CPControllerSelectionProxy : CPObject
{
id _controller;
id _keys;
CPDictionary _cachedValues;
CPArray _observationProxies;
}
- (id)initWithController:(id)aController
{
if (self = [super init])
{
_cachedValues = [CPDictionary dictionary];
_observationProxies = [CPArray array];
_controller = aController;
}
return self;
}
- (id)valueForKey:(CPString)aKey
{
var value = [_cachedValues objectForKey:aKey];
if (value !== undefined && value !== nil)
return value;
var allValues = [[_controller selectedObjects] valueForKeyPath:aKey],
count = [allValues count];
if (!count)
value = CPNoSelectionMarker;
else if (count === 1)
value = [allValues objectAtIndex:0];
else
{
if ([_controller alwaysUsesMultipleValuesMarker])
value = CPMultipleValuesMarker;
else
{
value = [allValues objectAtIndex:0];
for (var i=0, count=[allValues count]; i<count && value!=CPMultipleValuesMarker; i++)
{
if (![value isEqual:[allValues objectAtIndex:i]])
value = CPMultipleValuesMarker;
}
}
}
[_cachedValues setValue:value forKey:aKey];
return value;
}
- (unsigned)count
{
return [_cachedValues count];
}
- (id)keyEnumerator
{
return [_cachedValues keyEnumerator];
}
- (void)setValue:(id)aValue forKey:(CPString)aKey
{
[[_controller selectedObjects] setValue:aValue forKey:aKey];
}
-(void)controllerWillChange
{
_keys = [_cachedValues allKeys];
if (!_keys)
return;
for (var i=0, count=_keys.length; i<count; i++)
[self willChangeValueForKey:_keys[i]];
[_cachedValues removeAllObjects];
}
-(void)controllerDidChange
{
[_cachedValues removeAllObjects];
if (!_keys)
return;
for (var i=0, count=_keys.length; i<count; i++)
[self didChangeValueForKey:_keys[i]];
_keys = nil;
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)change context:(id)context
{
[_cachedValues removeObjectForKey:aKeyPath];
}
- (void)addObserver:(id)anObject forKeyPath:(CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(id)context
{
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObject object:self];
[proxy setNotifyObject:YES];
[_observationProxies addObject:proxy];
[[_controller selectedObjects] addObserver:proxy forKeyPath:aKeyPath options:options context:context];
}
- (void)removeObserver:(id)anObject forKeyPath:(CPString)aKeyPath
{
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObject object:self],
index = [_observationProxies indexOfObject:proxy];
[[_controller selectedObjects] removeObserver:[_observationProxies objectAtIndex:index] forKeyPath:aKeyPath];
[_observationProxies removeObjectAtIndex:index];
}
@end
+1 -1
View File
@@ -1,5 +1,5 @@
@import "CPPanel.j"
@import <AppKit/CPPanel.j>
@implementation CPOpenPanel : CPPanel
+94 -331
View File
@@ -23,6 +23,8 @@
@import "CPTableColumn.j"
@import "CPTableView.j"
#include "CoreGraphics/CGGeometry.h"
CPOutlineViewColumnDidMoveNotification = @"CPOutlineViewColumnDidMoveNotification";
CPOutlineViewColumnDidResizeNotification = @"CPOutlineViewColumnDidResizeNotification";
@@ -48,30 +50,12 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_
CPOutlineViewDataSource_outlineView_sortDescriptorsDidChange_ = 1 << 10;
var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ = 1 << 1,
CPOutlineViewDelegate_outlineView_didClickTableColumn_ = 1 << 2,
CPOutlineViewDelegate_outlineView_didDragTableColumn_ = 1 << 3,
CPOutlineViewDelegate_outlineView_heightOfRowByItem_ = 1 << 4,
CPOutlineViewDelegate_outlineView_isGroupItem_ = 1 << 5,
CPOutlineViewDelegate_outlineView_mouseDownInHeaderOfTableColumn_ = 1 << 6,
CPOutlineViewDelegate_outlineView_nextTypeSelectMatchFromItem_toItem_forString_ = 1 << 7,
CPOutlineViewDelegate_outlineView_selectionIndexesForProposedSelection_ = 1 << 8,
CPOutlineViewDelegate_outlineView_shouldCollapseItem_ = 1 << 9,
CPOutlineViewDelegate_outlineView_shouldEditTableColumn_item_ = 1 << 10,
CPOutlineViewDelegate_outlineView_shouldExpandItem_ = 1 << 11,
CPOutlineViewDelegate_outlineView_shouldReorderColumn_toColumn_ = 1 << 12,
CPOutlineViewDelegate_outlineView_shouldSelectItem_ = 1 << 13,
CPOutlineViewDelegate_outlineView_shouldSelectTableColumn_ = 1 << 14,
CPOutlineViewDelegate_outlineView_shouldShowOutlineViewForItem_ = 1 << 15,
CPOutlineViewDelegate_outlineView_shouldShowViewExpansionForTableColumn_item_ = 1 << 16,
CPOutlineViewDelegate_outlineView_shouldTrackView_forTableColumn_item_ = 1 << 17,
CPOutlineViewDelegate_outlineView_shouldTypeSelectForEvent_withCurrentSearchString_ = 1 << 18,
CPOutlineViewDelegate_outlineView_sizeToFitWidthOfColumn_ = 1 << 19,
CPOutlineViewDelegate_outlineView_toolTipForView_rect_tableColumn_item_mouseLocation_ = 1 << 20,
CPOutlineViewDelegate_outlineView_typeSelectStringForTableColumn_item_ = 1 << 21,
CPOutlineViewDelegate_outlineView_willDisplayOutlineView_forTableColumn_item_ = 1 << 22,
CPOutlineViewDelegate_outlineView_willDisplayView_forTableColumn_item_ = 1 << 23,
CPOutlineViewDelegate_selectionShouldChangeInOutlineView_ = 1 << 24;
CPOutlineViewDelegate_outlineView_shouldSelectItem_ = 1 << 2,
CPOutlineViewDelegate_outlineView_heightOfRowByItem_ = 1 << 3,
CPOutlineViewDelegate_outlineView_willDisplayView_forTableColumn_item_ = 1 << 4,
CPOutlineViewDelegate_outlineView_isGroupItem_ = 1 << 5;
CPOutlineViewDropOnItemIndex = -1;
@@ -95,10 +79,10 @@ CPOutlineViewDropOnItemIndex = -1;
CPArray _disclosureControlsForRows;
CPData _disclosureControlData;
CPArray _disclosureControlQueue;
BOOL _shouldRetargetItem;
id _retargetedItem;
BOOL _shouldRetargetChildIndex;
CPInteger _retargedChildIndex;
CPTimer _dragHoverTimer;
@@ -123,7 +107,7 @@ CPOutlineViewDropOnItemIndex = -1;
_retargetedItem = nil;
_shouldRetargetItem = NO;
_retargedChildIndex = nil;
_shouldRetargetChildIndex = NO;
_startHoverTime = nil;
@@ -232,7 +216,7 @@ CPOutlineViewDropOnItemIndex = -1;
- (void)expandItem:(id)anItem expandChildren:(BOOL)shouldExpandChildren
{
var itemInfo = null;
if (!anItem)
itemInfo = _rootItemInfo;
else
@@ -240,21 +224,15 @@ CPOutlineViewDropOnItemIndex = -1;
if (!itemInfo)
return;
// to prevent items which are already expanded from firing notifications
if (!itemInfo.isExpanded)
{
[self _noteItemWillExpand:anItem];
itemInfo.isExpanded = YES;
[self _noteItemDidExpand:anItem];
[self reloadItem:anItem reloadChildren:YES];
}
itemInfo.isExpanded = YES;
[self reloadItem:anItem reloadChildren:YES];
if (shouldExpandChildren)
{
var children = itemInfo.children,
childIndex = children.length;
while (childIndex--)
[self expandItem:children[childIndex] expandChildren:YES];
}
@@ -273,9 +251,7 @@ CPOutlineViewDropOnItemIndex = -1;
if (!itemInfo.isExpanded)
return;
[self _noteItemWillCollapse:anItem];
itemInfo.isExpanded = NO;
[self _noteItemDidCollapse:anItem];
[self reloadItem:anItem reloadChildren:YES];
}
@@ -390,7 +366,7 @@ CPOutlineViewDropOnItemIndex = -1;
return nil;
var parent = itemInfo.parent;
// Check if the parent is the root item because we never return the actual root item
if (itemInfo[[parent UID]] === _rootItemInfo)
parent = nil;
@@ -412,10 +388,10 @@ CPOutlineViewDropOnItemIndex = -1;
- (void)_performSelection:(BOOL)select forRow:(CPInteger)rowIndex context:(id)context
{
[super _performSelection:select forRow:rowIndex context:context];
var control = _disclosureControlsForRows[rowIndex],
selector = select ? @"setThemeState:" : @"unsetThemeState:";
[control performSelector:CPSelectorFromString(selector) withObject:CPThemeStateSelected];
}
@@ -451,76 +427,25 @@ CPOutlineViewDropOnItemIndex = -1;
removeObserver:_outlineViewDelegate
name:CPOutlineViewSelectionIsChangingNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewItemWillExpand:)])
[defaultCenter
removeObserver:_outlineViewDelegate
name:CPOutlineViewItemWillExpandNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewItemDidExpand:)])
[defaultCenter
removeObserver:_outlineViewDelegate
name:CPOutlineViewItemDidExpandNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewItemWillCollapse:)])
[defaultCenter
removeObserver:_outlineViewDelegate
name:CPOutlineViewItemWillCollapseNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewItemDidCollapse:)])
[defaultCenter
removeObserver:_outlineViewDelegate
name:CPOutlineViewItemDidCollapseNotification
object:self];
}
_outlineViewDelegate = aDelegate;
_implementedOutlineViewDelegateMethods = 0;
var delegateMethods = [
CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ , @selector(outlineView:dataViewForTableColumn:item:),
CPOutlineViewDelegate_outlineView_didClickTableColumn_ , @selector(outlineView:didClickTableColumn:),
CPOutlineViewDelegate_outlineView_didDragTableColumn_ , @selector(outlineView:didDragTableColumn:),
CPOutlineViewDelegate_outlineView_heightOfRowByItem_ , @selector(outlineView:heightOfRowByItem:),
CPOutlineViewDelegate_outlineView_isGroupItem_ , @selector(outlineView:isGroupItem:),
CPOutlineViewDelegate_outlineView_mouseDownInHeaderOfTableColumn_ , @selector(outlineView:mouseDownInHeaderOfTableColumn:),
CPOutlineViewDelegate_outlineView_nextTypeSelectMatchFromItem_toItem_forString_ , @selector(outlineView:nextTypeSelectMatchFromItem:toItem:forString:),
CPOutlineViewDelegate_outlineView_selectionIndexesForProposedSelection_ , @selector(outlineView:selectionIndexesForProposedSelection:),
CPOutlineViewDelegate_outlineView_shouldCollapseItem_ , @selector(outlineView:shouldCollapseItem:),
CPOutlineViewDelegate_outlineView_shouldEditTableColumn_item_ , @selector(outlineView:shouldEditTableColumn:item:),
CPOutlineViewDelegate_outlineView_shouldExpandItem_ , @selector(outlineView:shouldExpandItem:),
CPOutlineViewDelegate_outlineView_shouldReorderColumn_toColumn_ , @selector(outlineView:shouldReorderColumn:toColumn:),
CPOutlineViewDelegate_outlineView_shouldSelectItem_ , @selector(outlineView:shouldSelectItem:),
CPOutlineViewDelegate_outlineView_shouldSelectTableColumn_ , @selector(outlineView:shouldSelectTableColumn:),
CPOutlineViewDelegate_outlineView_shouldShowOutlineViewForItem_ , @selector(outlineView:shouldShowOutlineViewForItem:),
CPOutlineViewDelegate_outlineView_shouldShowViewExpansionForTableColumn_item_ , @selector(outlineView:shouldShowViewExpansionForTableColumn:item:),
CPOutlineViewDelegate_outlineView_shouldTrackView_forTableColumn_item_ , @selector(outlineView:shouldTrackView:forTableColumn:item:),
CPOutlineViewDelegate_outlineView_shouldTypeSelectForEvent_withCurrentSearchString_ , @selector(outlineView:shouldTypeSelectForEvent:withCurrentSearchString:),
CPOutlineViewDelegate_outlineView_sizeToFitWidthOfColumn_ , @selector(outlineView:sizeToFitWidthOfColumn:),
CPOutlineViewDelegate_outlineView_toolTipForView_rect_tableColumn_item_mouseLocation_, @selector(outlineView:toolTipForView:rect:tableColumn:item:mouseLocation:),
CPOutlineViewDelegate_outlineView_typeSelectStringForTableColumn_item_ , @selector(outlineView:typeSelectStringForTableColumn:item:),
CPOutlineViewDelegate_outlineView_willDisplayOutlineView_forTableColumn_item_ , @selector(outlineView:willDisplayOutlineView:forTableColumn:item:),
CPOutlineViewDelegate_outlineView_willDisplayView_forTableColumn_item_ , @selector(outlineView:willDisplayView:forTableColumn:item:),
CPOutlineViewDelegate_selectionShouldChangeInOutlineView_ , @selector(selectionShouldChangeInOutlineView:)
],
delegateCount = [delegateMethods count];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:dataViewForTableColumn:item:)])
_implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_;
if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:shouldSelectItem:)])
_implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_shouldSelectItem_;
if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:heightOfRowByItem:)])
_implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_heightOfRowByItem_;
for (var i=0; i < delegateCount; i += 2)
{
var bitMask = delegateMethods[i],
selector = delegateMethods[i+1];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:willDisplayView:forTableColumn:item:)])
_implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_willDisplayView_forTableColumn_item_;
if ([_outlineViewDelegate respondsToSelector:selector])
_implementedOutlineViewDelegateMethods |= bitMask;
}
if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:isGroupItem:)])
_implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_isGroupItem_;
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewColumnDidMove:)])
[defaultCenter
@@ -549,36 +474,6 @@ CPOutlineViewDropOnItemIndex = -1;
selector:@selector(outlineViewSelectionIsChanging:)
name:CPOutlineViewSelectionIsChangingNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewItemWillExpand:)])
[defaultCenter
addObserver:_outlineViewDelegate
selector:@selector(outlineViewItemWillExpand:)
name:CPOutlineViewItemWillExpandNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewItemDidExpand:)])
[defaultCenter
addObserver:_outlineViewDelegate
selector:@selector(outlineViewItemDidExpand:)
name:CPOutlineViewItemDidExpandNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewItemWillCollapse:)])
[defaultCenter
addObserver:_outlineViewDelegate
selector:@selector(outlineViewItemWillCollapse:)
name:CPOutlineViewItemWillCollapseNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewItemDidCollapse:)])
[defaultCenter
addObserver:_outlineViewDelegate
selector:@selector(outlineViewItemDidCollapse:)
name:CPOutlineViewItemDidCollapseNotification
object:self];
}
- (id)delegate
@@ -622,7 +517,7 @@ CPOutlineViewDropOnItemIndex = -1;
if (_dropItem)
{
[_dropOperationFeedbackView blink];
[CPTimer scheduledTimerWithTimeInterval:.3 callback:objj_msgSend(self, "expandItem:", _dropItem) repeats:NO];
[CPTimer scheduledTimerWithTimeInterval:.3 callback:objj_msgSend(self, "expandItem:", _dropItem) repeats:NO]; //[self expandItem:_dropItem];
}
}
@@ -638,23 +533,9 @@ CPOutlineViewDropOnItemIndex = -1;
_dropItem = theItem;
_retargetedItem = theItem;
_shouldRetargetItem = YES;
_retargedChildIndex = theIndex;
_shouldRetargetChildIndex = YES;
// set CPTableView's _retargetedDropRow based on retargetedItem and retargetedChildIndex
var retargetedItemInfo = (_retargetedItem !== nil) ? _itemInfosForItems[[_retargetedItem UID]] : _rootItemInfo;
if (_retargedChildIndex === [retargetedItemInfo.children count])
{
var retargetedChildItem = [retargetedItemInfo.children lastObject];
_retargetedDropRow = [self rowForItem:retargetedChildItem] + 1;
}
else
{
var retargetedChildItem = (_retargedChildIndex !== CPOutlineViewDropOnItemIndex) ? retargetedItemInfo.children[_retargedChildIndex] : _retargetedItem;
_retargetedDropRow = [self rowForItem:retargetedChildItem];
}
}
- (void)_draggingEnded
@@ -669,7 +550,7 @@ CPOutlineViewDropOnItemIndex = -1;
{
if (_shouldRetargetItem)
return _retargetedItem;
var lowerLevel = [self levelForRow:theLowerRowIndex]
upperItem = [self itemAtRow:theUpperRowIndex];
upperLevel = [self levelForItem:upperItem];
@@ -688,7 +569,7 @@ CPOutlineViewDropOnItemIndex = -1;
// Check the next parent
upperItem = [self parentForItem:upperItem];
}
return [self parentForItem:[self itemAtRow:theLowerRowIndex]];
}
@@ -698,10 +579,10 @@ CPOutlineViewDropOnItemIndex = -1;
var rect = [super _rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex offset:theOffset],
parentItem = [self _parentItemForUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex atMouseOffset:theOffset],
level = [self levelForItem:parentItem];
rect.origin.x = (level + 1) * [self indentationPerLevel];
rect.origin.x = (level + 1) * [self indentationPerLevel];
rect.size.width -= rect.origin.x; // This assumes that the x returned by super is zero
return rect;
}
@@ -835,41 +716,9 @@ CPOutlineViewDropOnItemIndex = -1;
userInfo:nil];
}
- (void)_noteItemWillExpand:(id)item
{
[[CPNotificationCenter defaultCenter]
postNotificationName:CPOutlineViewItemWillExpandNotification
object:self
userInfo:[CPDictionary dictionaryWithObject:item forKey:"CPObject"]];
}
- (void)_noteItemDidExpand:(id)item
{
[[CPNotificationCenter defaultCenter]
postNotificationName:CPOutlineViewItemDidExpandNotification
object:self
userInfo:[CPDictionary dictionaryWithObject:item forKey:"CPObject"]];
}
- (void)_noteItemWillCollapse:(id)item
{
[[CPNotificationCenter defaultCenter]
postNotificationName:CPOutlineViewItemWillCollapseNotification
object:self
userInfo:[CPDictionary dictionaryWithObject:item forKey:"CPObject"]];
}
- (void)_noteItemDidCollapse:(id)item
{
[[CPNotificationCenter defaultCenter]
postNotificationName:CPOutlineViewItemDidCollapseNotification
object:self
userInfo:[CPDictionary dictionaryWithObject:item forKey:"CPObject"]];
}
@end
// FIX ME: We're using with() here because Safari fails if we use anOutlineView._itemInfosForItems or whatever...
// FIX ME: We're using with() here because Safari fails if we use anOutlineView._itemInfosForItems or whatever...
var _reloadItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem)
{
if (!anItem)
@@ -882,55 +731,55 @@ var _reloadItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem)
dataSource = _outlineViewDataSource,
itemUID = [anItem UID],
itemInfo = itemInfosForItems[itemUID];
// If we're not in the tree, then just bail.
if (!itemInfo)
return [];
// See if the item itself can be swapped out.
var parent = itemInfo.parent,
parentItemInfo = parent ? itemInfosForItems[[parent UID]] : _rootItemInfo,
parentChildren = parentItemInfo.children,
index = [parentChildren indexOfObjectIdenticalTo:anItem],
newItem = [dataSource outlineView:anOutlineView child:index ofItem:parent];
if (anItem !== newItem)
{
itemInfosForItems[[anItem UID]] = nil;
itemInfosForItems[[newItem UID]] = itemInfo;
parentChildren[index] = newItem;
_itemsForRows[itemInfo.row] = newItem;
}
itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:newItem];
itemInfo.isExpanded = itemInfo.isExpandable && itemInfo.isExpanded;
}
}
// FIX ME: We're using with() here because Safari fails if we use anOutlineView._itemInfosForItems or whatever...
// FIX ME: We're using with() here because Safari fails if we use anOutlineView._itemInfosForItems or whatever...
var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem, /*BOOL*/ isIntermediate)
{
with(anOutlineView)
{
var itemInfosForItems = _itemInfosForItems,
dataSource = _outlineViewDataSource;
if (!anItem)
var itemInfo = _rootItemInfo;
else
{
// Get the existing info if it exists.
var itemUID = [anItem UID],
itemInfo = itemInfosForItems[itemUID];
// If we're not in the tree, then just bail.
if (!itemInfo)
return [];
itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:anItem];
// If we were previously expanded, but now no longer expandable, "de-expand".
// NOTE: we are *not* collapsing, thus no notification is posted.
if (!itemInfo.isExpandable && itemInfo.isExpanded)
@@ -939,72 +788,72 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
itemInfo.children = [];
}
}
// The root item does not count as a descendant.
var weight = itemInfo.weight,
descendants = anItem ? [anItem] : [];
if (itemInfo.isExpanded && (!(_implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_shouldDeferDisplayingChildrenOfItem_) ||
![dataSource outlineView:anOutlineView shouldDeferDisplayingChildrenOfItem:anItem]))
{
var index = 0,
count = [dataSource outlineView:anOutlineView numberOfChildrenOfItem:anItem],
level = itemInfo.level + 1;
itemInfo.children = [];
for (; index < count; ++index)
{
var childItem = [dataSource outlineView:anOutlineView child:index ofItem:anItem],
childItemInfo = itemInfosForItems[[childItem UID]];
if (!childItemInfo)
{
childItemInfo = { isExpanded:NO, isExpandable:NO, children:[], weight:1 };
itemInfosForItems[[childItem UID]] = childItemInfo;
}
itemInfo.children[index] = childItem;
var childDescendants = _loadItemInfoForItem(anOutlineView, childItem, YES);
childItemInfo.parent = anItem;
childItemInfo.level = level;
descendants = descendants.concat(childDescendants);
}
}
itemInfo.weight = descendants.length;
if (!isIntermediate)
{
// row = -1 is the root item, so just go to row 0 since it is ignored.
var index = MAX(itemInfo.row, 0),
itemsForRows = _itemsForRows;
descendants.unshift(index, weight);
itemsForRows.splice.apply(itemsForRows, descendants);
var count = itemsForRows.length;
for (; index < count; ++index)
itemInfosForItems[[itemsForRows[index] UID]].row = index;
var deltaWeight = itemInfo.weight - weight;
if (deltaWeight !== 0)
{
var parent = itemInfo.parent;
while (parent)
{
var parentItemInfo = itemInfosForItems[[parent UID]];
parentItemInfo.weight += deltaWeight;
parent = parentItemInfo.parent;
}
if (anItem)
_rootItemInfo.weight += deltaWeight;
}
@@ -1038,27 +887,20 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
return [_outlineView._outlineViewDataSource outlineView:_outlineView objectValueForTableColumn:aTableColumn byItem:_outlineView._itemsForRows[aRow]];
}
- (void)tableView:(CPTableView)aTableView setObjectValue:(id)aValue forTableColumn:(CPTableColumn)aColumn row:(CPInteger)aRow
{
if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_))
return;
[_outlineView._outlineViewDataSource outlineView:_outlineView setObjectValue:aValue forTableColumn:aColumn byItem:_outlineView._itemsForRows[aRow]];
}
- (BOOL)tableView:(CPTableView)aTableColumn writeRowsWithIndexes:(CPIndexSet)theIndexes toPasteboard:(CPPasteboard)thePasteboard
{
if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_writeItems_toPasteboard_))
return NO;
var rowIndexes = [];
[theIndexes getIndexes:rowIndexes maxCount:[theIndexes count] inIndexRange:nil];
var rowIndex = [rowIndexes count],
items = [];
while (rowIndex--)
[items addObject:[_outlineView itemAtRow:[rowIndexes objectAtIndex:rowIndex]]];
return [_outlineView._outlineViewDataSource outlineView:_outlineView writeItems:items toPasteboard:thePasteboard];
}
@@ -1066,15 +908,15 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
{
if (_outlineView._shouldRetargetChildIndex)
return _outlineView._retargedChildIndex;
var childIndex = CPNotFound;
if (theDropOperation === CPTableViewDropAbove)
{
var parentItem = [_outlineView _parentItemForUpperRow:theRow - 1 andLowerRow:theRow atMouseOffset:theOffset],
itemInfo = (parentItem !== nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo,
children = itemInfo.children;
childIndex = [children indexOfObject:[_outlineView itemAtRow:theRow]];
if (childIndex === CPNotFound)
@@ -1089,12 +931,12 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
- (void)_parentItemForDropOperation:(CPTableViewDropOperation)theDropOperation row:(int)theRow offset:(CPPoint)theOffset
{
if (theDropOperation === CPTableViewDropAbove)
return [_outlineView _parentItemForUpperRow:theRow - 1 andLowerRow:theRow atMouseOffset:theOffset]
return [_outlineView _parentItemForUpperRow:theRow - 1 andLowerRow:theRow atMouseOffset:theOffset]
return [_outlineView itemAtRow:theRow];
}
- (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id < CPDraggingInfo >)theInfo
- (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id < CPDraggingInfo >)theInfo
proposedRow:(int)theRow proposedDropOperation:(CPTableViewDropOperation)theOperation
{
if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_validateDrop_proposedItem_proposedChildIndex_))
@@ -1108,21 +950,21 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
_outlineView._shouldRetargetChildIndex = NO;
var location = [_outlineView convertPoint:[theInfo draggingLocation] fromView:nil],
parentItem = [self _parentItemForDropOperation:theOperation row:theRow offset:location],
parentItem = [self _parentItemForDropOperation:theOperation row:theRow offset:location];
childIndex = [self _childIndexForDropOperation:theOperation row:theRow offset:location];
return [_outlineView._outlineViewDataSource outlineView:_outlineView validateDrop:theInfo proposedItem:parentItem proposedChildIndex:childIndex];
}
- (BOOL)tableView:(CPTableView)aTableView acceptDrop:(id <CPDraggingInfo>)theInfo row:(int)theRow dropOperation:(CPTableViewDropOperation)theOperation
{
{
if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_acceptDrop_item_childIndex_))
return NO;
var location = [_outlineView convertPoint:[theInfo draggingLocation] fromView:nil],
parentItem = [self _parentItemForDropOperation:theOperation row:theRow offset:location];
childIndex = [self _childIndexForDropOperation:theOperation row:theRow offset:location];
_outlineView._retargetedItem = nil;
_outlineView._shouldRetargetItem = NO;
@@ -1152,15 +994,15 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
- (CPView)tableView:(CPTableView)theTableView dataViewForTableColumn:(CPTableColumn)theTableColumn row:(int)theRow
{
var dataView = nil;
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_))
dataView = [_outlineView._outlineViewDelegate outlineView:_outlineView
dataViewForTableColumn:theTableColumn
dataView = [_outlineView._outlineViewDelegate outlineView:_outlineView
dataViewForTableColumn:theTableColumn
item:[_outlineView itemAtRow:theRow]];
if (!dataView)
dataView = [theTableColumn dataViewForRow:theRow];
dataView = [theTableColumn dataViewForRow:theRow];
return dataView;
}
@@ -1168,18 +1010,10 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
{
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldSelectItem_))
return [_outlineView._outlineViewDelegate outlineView:_outlineView shouldSelectItem:[_outlineView itemAtRow:theRow]];
return YES;
}
- (BOOL)tableView:(CPTableView)aTableView shouldEditTableColumn:(CPTableColumn)aColumn row:(int)aRow
{
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldEditTableColumn_item_))
return [_outlineView._outlineViewDelegate outlineView:_outlineView shouldEditTableColumn:aColumn item:[_outlineView itemAtRow:aRow]];
return NO;
}
- (float)tableView:(CPTableView)theTableView heightOfRow:(int)theRow
{
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_heightOfRowByItem_))
@@ -1197,10 +1031,10 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
}
}
- (BOOL)tableView:(CPTableView)aTableView isGroupRow:(int)aRow
- (BOOL)tableView:(CPTableView)aTableView isGroupRow:(int)row
{
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_isGroupItem_))
return [_outlineView._outlineViewDelegate outlineView:_outlineView isGroupItem:[_outlineView itemAtRow:aRow]];
return [_outlineView._outlineViewDelegate outlineView:_outlineView isGroupItem:[_outlineView itemAtRow:theRow]];
return NO;
}
@@ -1253,82 +1087,11 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
CGContextAddLineToPoint(context, 0.0, 0.0);
CGContextClosePath(context);
CGContextSetFillColor(context,
colorForDisclosureTriangle([self hasThemeState:CPThemeStateSelected],
[self hasThemeState:CPThemeStateHighlighted]));
var isHighlighted = [self hasThemeState:CPThemeStateHighlighted];
var color = [self hasThemeState:CPThemeStateSelected] ? (isHighlighted ? [CPColor lightGrayColor] : [CPColor whiteColor]) : (isHighlighted ? [CPColor blackColor] : [CPColor grayColor]);
CGContextSetFillColor(context, color);
CGContextFillPath(context);
CGContextBeginPath(context);
CGContextMoveToPoint(context, 0.0, 0.0);
if(_angle === 0.0) {
CGContextAddLineToPoint(context, 4.5, 8.0);
CGContextAddLineToPoint(context, 9.0, 0.0);
} else {
CGContextAddLineToPoint(context, 4.5, 8.0);
}
CGContextSetStrokeColor(context, [CPColor colorWithCalibratedWhite:1.0 alpha: 0.8]);
CGContextStrokePath(context);
}
@end
var CPOutlineViewIndentationPerLevelKey = @"CPOutlineViewIndentationPerLevelKey",
CPOutlineViewOutlineTableColumnKey = @"CPOutlineViewOutlineTableColumnKey",
CPOutlineViewDataSourceKey = @"CPOutlineViewDataSourceKey",
CPOutlineViewDelegateKey = @"CPOutlineViewDelegateKey";
@implementation CPOutlineView (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
// The root item has weight "0", thus represents the weight solely of its descendants.
_rootItemInfo = { isExpanded:YES, isExpandable:NO, level:-1, row:-1, children:[], weight:0 };
_itemsForRows = [];
_itemInfosForItems = { };
_disclosureControlsForRows = [];
[self setIndentationMarkerFollowsDataView:YES];
[self setDisclosureControlPrototype:[[CPDisclosureButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 10.0, 10.0)]];
_outlineTableColumn = [aCoder decodeObjectForKey:CPOutlineViewOutlineTableColumnKey];
_indentationPerLevel = [aCoder decodeFloatForKey:CPOutlineViewIndentationPerLevelKey];
_outlineViewDataSource = [aCoder decodeObjectForKey:CPOutlineViewDataSourceKey];
_outlineViewDelegate = [aCoder decodeObjectForKey:CPOutlineViewDelegateKey];
[super setDataSource:[[_CPOutlineViewTableViewDataSource alloc] initWithOutlineView:self]];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_outlineTableColumn forKey:CPOutlineViewOutlineTableColumnKey];
[aCoder encodeFloat:_indentationPerLevel forKey:CPOutlineViewIndentationPerLevelKey];
[aCoder encodeObject:_outlineViewDataSource forKey:CPOutlineViewDataSourceKey];
[aCoder encodeObject:_outlineViewDelegate forKey:CPOutlineViewDelegateKey];
}
@end
var colorForDisclosureTriangle = function(isSelected, isHighlighted) {
return isSelected
? (isHighlighted
? [CPColor colorWithCalibratedWhite:0.9 alpha: 1.0]
: [CPColor colorWithCalibratedWhite:1.0 alpha: 1.0])
: (isHighlighted
? [CPColor colorWithCalibratedWhite:0.4 alpha: 1.0]
: [CPColor colorWithCalibratedWhite:0.5 alpha: 1.0]);
}
+2
View File
@@ -25,6 +25,8 @@
@import <Foundation/CPDictionary.j>
@import <Foundation/CPPropertyListSerialization.j>
#include "Platform/Platform.h"
CPGeneralPboard = @"CPGeneralPboard";
CPFontPboard = @"CPFontPboard";
+41 -48
View File
@@ -25,12 +25,14 @@
@import "CPMenu.j"
@import "CPMenuItem.j"
#include "CoreGraphics/CGGeometry.h"
var VISIBLE_MARGIN = 7.0;
CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
/*!
/*!
@ingroup appkit
@class CPPopUpButton
@@ -40,11 +42,11 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
{
int _selectedIndex;
CPRectEdge _preferredEdge;
CPMenu _menu;
}
+ (CPString)defaultThemeClass
+ (CPString)themeClass
{
return "popup-button";
}
@@ -58,21 +60,21 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
- (id)initWithFrame:(CGRect)aFrame pullsDown:(BOOL)shouldPullDown
{
self = [super initWithFrame:aFrame];
if (self)
{
_selectedIndex = CPNotFound;
_preferredEdge = CPMaxYEdge;
[self setValue:CPImageLeft forThemeAttribute:@"image-position"];
[self setValue:CPLeftTextAlignment forThemeAttribute:@"alignment"];
[self setValue:CPLineBreakByTruncatingTail forThemeAttribute:@"line-break-mode"];
[self setMenu:[[CPMenu alloc] initWithTitle:@""]];
[self setPullsDown:shouldPullDown];
}
return self;
}
@@ -143,7 +145,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
{
var index = 0,
count = [titles count];
for (; index < count; ++index)
[self addItemWithTitle:titles[index]];
}
@@ -157,11 +159,11 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
{
var items = [self itemArray],
count = [items count];
while (count--)
if ([items[count] title] == aTitle)
[self removeItemAtIndex:count];
[_menu insertItemWithTitle:aTitle action:NULL keyEquivalent:nil atIndex:anIndex];
}
@@ -171,7 +173,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
- (void)removeAllItems
{
var count = [_menu numberOfItems];
while (count--)
[_menu removeItemAtIndex:0];
}
@@ -204,7 +206,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
{
if (_selectedIndex < 0 || _selectedIndex > [self numberOfItems] - 1)
return nil;
return [_menu itemAtIndex:_selectedIndex];
}
@@ -251,15 +253,15 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
{
if (_selectedIndex == anIndex)
return;
if (_selectedIndex >= 0 && ![self pullsDown])
[[self selectedItem] setState:CPOffState];
_selectedIndex = anIndex;
if (_selectedIndex >= 0 && ![self pullsDown])
[[self selectedItem] setState:CPOnState];
[self synchronizeTitleAndSelectedItem];
}
@@ -308,7 +310,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
return;
var defaultCenter = [CPNotificationCenter defaultCenter];
if (_menu)
{
[defaultCenter
@@ -328,7 +330,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
}
_menu = aMenu;
if (_menu)
{
[defaultCenter
@@ -336,20 +338,20 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
selector:@selector(menuDidAddItem:)
name:CPMenuDidAddItemNotification
object:_menu];
[defaultCenter
addObserver:self
selector:@selector(menuDidChangeItem:)
name:CPMenuDidChangeItemNotification
object:_menu];
[defaultCenter
addObserver:self
selector:@selector(menuDidRemoveItem:)
name:CPMenuDidRemoveItemNotification
object:_menu];
}
[self synchronizeTitleAndSelectedItem];
}
@@ -394,13 +396,12 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
{
var titles = [],
items = [self itemArray],
index = 0,
count = [items count];
for (; index < count; ++index)
titles.push([items[index] title]);
return titles;
items.push([items[index] title]);
}
/*!
@@ -518,14 +519,14 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
else
{
var index = [self indexOfItemWithTitle:aTitle];
if (index < 0)
{
[self addItemWithTitle:aTitle];
index = [self numberOfItems] - 1;
}
[self selectItemAtIndex:index];
}
}
@@ -553,7 +554,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
if ([self pullsDown])
{
var items = [_menu itemArray];
if ([items count] > 0)
item = items[0];
}
@@ -572,22 +573,22 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
- (void)menuDidAddItem:(CPNotification)aNotification
{
var index = [[aNotification userInfo] objectForKey:@"CPMenuItemIndex"];
if (_selectedIndex < 0)
[self selectItemAtIndex:0];
else if (index == _selectedIndex)
[self synchronizeTitleAndSelectedItem];
else if (index < _selectedIndex)
++_selectedIndex;
if (index == 0 && [self pullsDown])
{
var items = [_menu itemArray];
[items[0] setHidden:YES];
if (items.length > 0)
[items[1] setHidden:NO];
}
@@ -612,10 +613,10 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
if ([self pullsDown] && index != 0)
return;
if (![self pullsDown] && index != _selectedIndex)
return;
[self synchronizeTitleAndSelectedItem];
}
@@ -626,7 +627,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
- (void)menuDidRemoveItem:(CPNotification)aNotification
{
var numberOfItems = [self numberOfItems];
if (numberOfItems <= _selectedIndex && numberOfItems > 0)
[self selectItemAtIndex:numberOfItems - 1];
else
@@ -660,9 +661,6 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
location = CGPointMake(CGRectGetMinX(contentRect) - standardLeftMargin, 0.0);
minimumWidth += standardLeftMargin;
// To ensure the selected item is highlighted correctly, unset the highlighted item
[menu _highlightItemAtIndex:CPNotFound];
}
[menu setMinimumWidth:minimumWidth];
@@ -700,11 +698,6 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
*/
}
- (void)rightMouseDown:(CPEvent)anEvent
{
// Disable standard CPView behaviour which incorrectly displays the menu as a 'context menu'.
}
- (void)_popUpItemAction:(id)aSender
{
[self sendAction:[self action] to:[self target]];
@@ -744,7 +737,7 @@ var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
// Nothing is currently selected
@@ -753,7 +746,7 @@ var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
[self setMenu:[aCoder decodeObjectForKey:CPPopUpButtonMenuKey]];
[self selectItemAtIndex:[aCoder decodeObjectForKey:CPPopUpButtonSelectedIndexKey]];
}
return self;
}
@@ -765,7 +758,7 @@ var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_menu forKey:CPPopUpButtonMenuKey];
[aCoder encodeInt:_selectedIndex forKey:CPPopUpButtonSelectedIndexKey];
}
+5 -3
View File
@@ -20,9 +20,11 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CGGeometry.j"
@import "CPImageView.j"
@import "CPView.j"
@import <AppKit/CGGeometry.j>
@import <AppKit/CPImageView.j>
@import <AppKit/CPView.j>
#include "CoreGraphics/CGGeometry.h"
/*
+15 -19
View File
@@ -25,29 +25,28 @@
@import "CPButton.j"
/*!
@ingroup appkit
from this mailing list thread:
http://groups.google.com/group/objectivej/browse_thread/thread/7c41cbd9cbee9ea3
http://groups.google.com/group/objectivej/browse_thread/thread/7c41cbd9cbee9ea3
-----------------------------------
Creating a checkbox is easy enough:
checkbox = [[CPCheckBox alloc] initWithFrame:aFrame];
That's basically all there is to it. Radio buttons are very similar,
the key difference is the introduction of a new class CPRadioGroup,
which defines which radio buttons are part of the same group:
[myRadioButton setRadioGroup:aRadioGroup];
Every radio button receives a unique radio group by default (so if you
do nothing further, they will all behave independently), but you can
use an existing radio button's group with other buttons as so:
button1 = [[CPRadio alloc] initWithFrame:aFrame];
...
button2 = [[CPRadio alloc] initWithFrame:aFrame radioGroup:[button1
@@ -56,16 +55,13 @@
button3 = [[CPRadio alloc] initWithFrame:aFrame radioGroup:[button1
radioGroup]];
...etc...
Here, all the radio buttons will act "together". [[button1 radioGroup]
allRadios] returns every button that's part of this group, and
[[button1 radioGroup] selectedRadio] returns the currently selected
option.
*/
CPRadioImageOffset = 4.0;
@implementation CPRadio : CPButton
{
CPRadioGroup _radioGroup;
@@ -90,7 +86,7 @@ CPRadioImageOffset = 4.0;
return button;
}
+ (CPString)defaultThemeClass
+ (CPString)themeClass
{
return @"radio";
}
@@ -99,7 +95,7 @@ CPRadioImageOffset = 4.0;
- (id)initWithFrame:(CGRect)aFrame radioGroup:(CPRadioGroup)aRadioGroup
{
self = [super initWithFrame:aFrame];
if (self)
{
[self setRadioGroup:aRadioGroup];
@@ -113,8 +109,8 @@ CPRadioImageOffset = 4.0;
[self setBordered:YES];
}
return self;
return self;
}
- (id)initWithFrame:(CGRect)aFrame
@@ -145,7 +141,7 @@ CPRadioImageOffset = 4.0;
- (void)setObjectValue:(id)aValue
{
[super setObjectValue:aValue];
if ([self state] === CPOnState)
[_radioGroup _setSelectedRadio:self];
}
+53 -47
View File
@@ -23,23 +23,22 @@
@import <Foundation/CPObject.j>
CPDeleteKeyCode = 8;
CPTabKeyCode = 9;
CPReturnKeyCode = 13;
CPEscapeKeyCode = 27;
CPSpaceKeyCode = 32;
CPPageUpKeyCode = 33;
CPPageDownKeyCode = 34;
CPLeftArrowKeyCode = 37;
CPUpArrowKeyCode = 38;
CPRightArrowKeyCode = 39;
CPDownArrowKeyCode = 40;
CPDeleteForwardKeyCode = 46;
CPDeleteKeyCode = 8;
CPTabKeyCode = 9;
CPReturnKeyCode = 13;
CPEscapeKeyCode = 27;
CPSpaceKeyCode = 32;
CPPageUpKeyCode = 33;
CPPageDownKeyCode = 34;
CPLeftArrowKeyCode = 37;
CPUpArrowKeyCode = 38;
CPRightArrowKeyCode = 39;
CPDownArrowKeyCode = 40;
/*!
@ingroup appkit
@class CPResponder
Subclasses of CPResonder can be part of the responder chain.
*/
@implementation CPResponder : CPObject
@@ -105,24 +104,42 @@ CPDeleteForwardKeyCode = 46;
for (; index < count; ++index)
{
var event = events[index],
modifierFlags = [event modifierFlags],
character = [event charactersIgnoringModifiers],
selectorNames = [CPKeyBinding selectorsForKey:character modifierFlags:modifierFlags];
var event = events[index];
if (selectorNames)
switch([event keyCode])
{
for (var s = 0, scount = selectorNames.length; s < scount; s++)
{
var selector = selectorNames[s];
if (!selector)
continue;
case CPPageUpKeyCode: [self doCommandBySelector:@selector(pageUp:)];
break;
case CPPageDownKeyCode: [self doCommandBySelector:@selector(pageDown:)];
break;
case CPLeftArrowKeyCode: [self doCommandBySelector:@selector(moveLeft:)];
break;
case CPRightArrowKeyCode: [self doCommandBySelector:@selector(moveRight:)];
break;
case CPUpArrowKeyCode: [self doCommandBySelector:@selector(moveUp:)];
break;
case CPDownArrowKeyCode: [self doCommandBySelector:@selector(moveDown:)];
break;
case CPDeleteKeyCode: [self doCommandBySelector:@selector(deleteBackward:)];
break;
case CPReturnKeyCode:
case 3: [self doCommandBySelector:@selector(insertLineBreak:)];
break;
case CPEscapeKeyCode: [self doCommandBySelector:@selector(cancel:)];
break;
[self doCommandBySelector:CPSelectorFromString(selector)];
}
case CPTabKeyCode: var shift = [event modifierFlags] & CPShiftKeyMask;
if (!shift)
[self doCommandBySelector:@selector(insertTab:)];
else
[self doCommandBySelector:@selector(insertBackTab:)];
break;
default: [self insertText:[event characters]];
}
else if (!(modifierFlags & (CPCommandKeyMask | CPControlKeyMask)) && [self respondsToSelector:@selector(insertText:)])
[self insertText:[event characters]];
}
}
@@ -222,15 +239,6 @@ CPDeleteForwardKeyCode = 46;
[_nextResponder performSelector:_cmd withObject:anEvent];
}
/*!
Notifies the receiver that the user has pressed or released a modifier key (Shift, Control, and so on).
@param anEvent information about the key press
*/
- (void)flagsChanged:(CPEvent)anEvent
{
[_nextResponder performSelector:_cmd withObject:anEvent];
}
/*
FIXME This description is bad.
Based on \c anEvent, the receiver should simulate the event.
@@ -261,6 +269,10 @@ CPDeleteForwardKeyCode = 46;
[[self nextResponder] insertNewline:aSender];
}
- (void)cancel:(id)sender
{
}
- (void)insertTab:(id)sender
{
}
@@ -300,10 +312,10 @@ CPDeleteForwardKeyCode = 46;
*/
- (BOOL)tryToPerform:(SEL)aSelector with:(id)anObject
{
if ([self respondsToSelector:aSelector])
if([self respondsToSelector:aSelector])
{
[self performSelector:aSelector withObject:anObject];
return YES;
}
@@ -342,8 +354,7 @@ CPDeleteForwardKeyCode = 46;
@end
var CPResponderNextResponderKey = @"CPResponderNextResponderKey",
CPResponderMenuKey = @"CPResponderMenuKey";
var CPResponderNextResponderKey = @"CPResponderNextResponderKey";
@implementation CPResponder (CPCoding)
@@ -355,13 +366,10 @@ var CPResponderNextResponderKey = @"CPResponderNextResponderKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
_nextResponder = [aCoder decodeObjectForKey:CPResponderNextResponderKey];
_menu = [aCoder decodeObjectForKey:CPResponderMenuKey];
}
return self;
}
@@ -374,8 +382,6 @@ var CPResponderNextResponderKey = @"CPResponderNextResponderKey",
// This will come out nil on the other side with decodeObjectForKey:
if (_nextResponder !== nil)
[aCoder encodeConditionalObject:_nextResponder forKey:CPResponderNextResponderKey];
[aCoder encodeObject:_menu forKey:CPResponderMenuKey];
}
@end
+1 -1
View File
@@ -1,5 +1,5 @@
@import "CPPanel.j"
@import <AppKit/CPPanel.j>
@implementation CPSavePanel : CPPanel
+2
View File
@@ -1,6 +1,8 @@
@import <Foundation/CPObject.j>
#import "CoreGraphics/CGGeometry.h"
#import "Platform/Platform.h"
@implementation CPScreen : CPObject
{
+94 -363
View File
@@ -20,13 +20,14 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPBox.j"
@import "CPView.j"
@import "CPClipView.j"
@import "CPScroller.j"
@import "CPView.j"
#include "CoreGraphics/CGGeometry.h"
/*!
/*!
@ingroup appkit
@class CPScrollView
@@ -36,39 +37,23 @@
*/
@implementation CPScrollView : CPView
{
CPClipView _contentView;
CPClipView _headerClipView;
CPView _cornerView;
CPView _bottomCornerView;
CPClipView _contentView;
CPClipView _headerClipView;
CPView _cornerView;
BOOL _hasVerticalScroller;
BOOL _hasHorizontalScroller;
BOOL _autohidesScrollers;
CPScroller _verticalScroller;
CPScroller _horizontalScroller;
int _recursionCount;
float _verticalLineScroll;
float _verticalPageScroll;
float _horizontalLineScroll;
float _horizontalPageScroll;
CPBorderType _borderType;
}
+ (CPString)defaultThemeClass
{
return @"scrollview"
}
+ (CPDictionary)themeAttributes
{
return [CPDictionary dictionaryWithJSObject:{
@"bottom-corner-color": [CPColor whiteColor],
@"border-color": [CPColor blackColor]
}];
BOOL _hasVerticalScroller;
BOOL _hasHorizontalScroller;
BOOL _autohidesScrollers;
CPScroller _verticalScroller;
CPScroller _horizontalScroller;
int _recursionCount;
float _verticalLineScroll;
float _verticalPageScroll;
float _horizontalLineScroll;
float _horizontalPageScroll;
}
- (id)initWithFrame:(CGRect)aFrame
@@ -83,17 +68,13 @@
_horizontalLineScroll = 10.0;
_horizontalPageScroll = 10.0;
_borderType = CPNoBorder;
_contentView = [[CPClipView alloc] initWithFrame:[self _insetBounds]];
_contentView = [[CPClipView alloc] initWithFrame:[self bounds]];
[self addSubview:_contentView];
_headerClipView = [[CPClipView alloc] init];
[self addSubview:_headerClipView];
_bottomCornerView = [[CPView alloc] init];
[self addSubview:_bottomCornerView];
[self addSubview:_headerClipView];
[self setHasVerticalScroller:YES];
[self setHasHorizontalScroller:YES];
@@ -102,70 +83,11 @@
return self;
}
// Calculating Layout
+ (CGSize)contentSizeForFrameSize:(CGSize)frameSize hasHorizontalScroller:(BOOL)hFlag hasVerticalScroller:(BOOL)vFlag borderType:(CPBorderType)borderType
{
var bounds = [self _insetBounds:_CGRectMake(0.0, 0.0, frameSize.width, frameSize.height) borderType:borderType],
scrollerWidth = [CPScroller scrollerWidth];
if (hFlag)
bounds.size.height -= scrollerWidth;
if (vFlag)
bounds.size.width -= scrollerWidth;
return bounds.size;
}
+ (CGSize)frameSizeForContentSize:(CGSize)contentSize hasHorizontalScroller:(BOOL)hFlag hasVerticalScroller:(BOOL)vFlag borderType:(CPBorderType)borderType
{
var bounds = [self _insetBounds:_CGRectMake(0.0, 0.0, contentSize.width, contentSize.height) borderType:borderType],
widthInset = contentSize.width - bounds.size.width,
heightInset = contentSize.height - bounds.size.height,
frameSize = _CGSizeMake(contentSize.width + widthInset, contentSize.height + heightInset),
scrollerWidth = [CPScroller scrollerWidth];
if (hFlag)
frameSize.height -= scrollerWidth;
if (vFlag)
frameSize.width -= scrollerWidth;
return frameSize;
}
+ (CGRect)_insetBounds:(CGRect)bounds borderType:(CPBorderType)borderType
{
switch (borderType)
{
case CPLineBorder:
case CPBezelBorder:
return _CGRectInset(bounds, 1.0, 1.0);
case CPGrooveBorder:
bounds = _CGRectInset(bounds, 2.0, 2.0);
++bounds.origin.y;
--bounds.size.height;
return bounds;
case CPNoBorder:
default:
return bounds;
}
}
- (CGRect)_insetBounds
{
return [[self class] _insetBounds:[self bounds] borderType:_borderType];
}
// Determining component sizes
/*!
Returns the size of the scroll view's content view.
*/
- (CGSize)contentSize
- (CGRect)contentSize
{
return [_contentView frame].size;
}
@@ -184,7 +106,7 @@
*/
- (void)setContentView:(CPClipView)aContentView
{
if (_contentView === aContentView || !aContentView)
if (_contentView !== aContentView || !aContentView)
return;
var documentView = [aContentView documentView];
@@ -231,16 +153,16 @@
*/
- (void)reflectScrolledClipView:(CPClipView)aClipView
{
if (_contentView !== aClipView)
if(_contentView !== aClipView)
return;
if (_recursionCount > 5)
return;
++_recursionCount;
var documentView = [self documentView];
if (!documentView)
{
if (_autohidesScrollers)
@@ -254,7 +176,7 @@
// [_horizontalScroller setEnabled:NO];
}
[_contentView setFrame:[self _insetBounds]];
[_contentView setFrame:[self bounds]];
[_headerClipView setFrame:_CGRectMakeZero()];
--_recursionCount;
@@ -263,7 +185,7 @@
}
var documentFrame = [documentView frame], // the size of the whole document
contentFrame = [self _insetBounds], // assume it takes up the entire size of the scrollview (no scrollers)
contentFrame = [self bounds], // assume it takes up the entire size of the scrollview (no scrollers)
headerClipViewFrame = [self _headerClipViewFrame],
headerClipViewHeight = _CGRectGetHeight(headerClipViewFrame);
@@ -313,10 +235,11 @@
if (shouldShowVerticalScroller)
{
var verticalScrollerY =
MAX(_CGRectGetMinY(contentFrame), MAX(_CGRectGetMaxY([self _cornerViewFrame]), _CGRectGetMaxY(headerClipViewFrame)));
var verticalScrollerY = MAX(_CGRectGetHeight([self _cornerViewFrame]), headerClipViewHeight),
verticalScrollerHeight = _CGRectGetHeight([self bounds]) - verticalScrollerY;
var verticalScrollerHeight = _CGRectGetMaxY(contentFrame) - verticalScrollerY;
if (shouldShowHorizontalScroller)
verticalScrollerHeight -= horizontalScrollerHeight;
[_verticalScroller setFloatValue:(difference.height <= 0.0) ? 0.0 : scrollPoint.y / difference.height];
[_verticalScroller setKnobProportion:_CGRectGetHeight(contentFrame) / _CGRectGetHeight(documentFrame)];
@@ -327,12 +250,12 @@
[_verticalScroller setFloatValue:0.0];
[_verticalScroller setKnobProportion:1.0];
}
if (shouldShowHorizontalScroller)
{
[_horizontalScroller setFloatValue:(difference.width <= 0.0) ? 0.0 : scrollPoint.x / difference.width];
[_horizontalScroller setKnobProportion:_CGRectGetWidth(contentFrame) / _CGRectGetWidth(documentFrame)];
[_horizontalScroller setFrame:_CGRectMake(_CGRectGetMinX(contentFrame), _CGRectGetMaxY(contentFrame), _CGRectGetWidth(contentFrame), horizontalScrollerHeight)];
[_horizontalScroller setFrame:_CGRectMake(0.0, _CGRectGetMaxY(contentFrame), _CGRectGetWidth(contentFrame), horizontalScrollerHeight)];
}
else if (wasShowingHorizontalScroller)
{
@@ -344,36 +267,9 @@
[_headerClipView setFrame:headerClipViewFrame];
[_cornerView setFrame:[self _cornerViewFrame]];
[[self bottomCornerView] setFrame:[self _bottomCornerViewFrame]];
[[self bottomCornerView] setBackgroundColor:[self currentValueForThemeAttribute:@"bottom-corner-color"]];
--_recursionCount;
}
// Managing Graphics Attributes
/*!
Sets the type of border to be drawn around the view.
*/
- (void)setBorderType:(CPBorderType)borderType
{
if (_borderType == borderType)
return;
_borderType = borderType;
[self reflectScrolledClipView:_contentView];
[self setNeedsDisplay:YES];
}
/*!
Returns the border type drawn around the view.
*/
- (CPBorderType)borderType
{
return _borderType;
}
// Managing Scrollers
/*!
Sets the scroll view's horizontal scroller.
@@ -383,13 +279,13 @@
{
if (_horizontalScroller === aScroller)
return;
[_horizontalScroller removeFromSuperview];
[_horizontalScroller setTarget:nil];
[_horizontalScroller setAction:nil];
_horizontalScroller = aScroller;
[_horizontalScroller setTarget:self];
[_horizontalScroller setAction:@selector(_horizontalScrollerDidScroll:)];
@@ -420,10 +316,8 @@
if (_hasHorizontalScroller && !_horizontalScroller)
{
var bounds = [self _insetBounds];
[self setHorizontalScroller:[[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, MAX(_CGRectGetWidth(bounds), [CPScroller scrollerWidth] + 1), [CPScroller scrollerWidth])]];
[[self horizontalScroller] setFrameSize:CGSizeMake(_CGRectGetWidth(bounds), [CPScroller scrollerWidth])];
[self setHorizontalScroller:[[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, MAX(_CGRectGetWidth([self bounds]), [CPScroller scrollerWidth]+1), [CPScroller scrollerWidth])]];
[[self horizontalScroller] setFrameSize:CGSizeMake(_CGRectGetWidth([self bounds]), [CPScroller scrollerWidth])];
}
[self reflectScrolledClipView:_contentView];
@@ -445,13 +339,13 @@
{
if (_verticalScroller === aScroller)
return;
[_verticalScroller removeFromSuperview];
[_verticalScroller setTarget:nil];
[_verticalScroller setAction:nil];
_verticalScroller = aScroller;
[_verticalScroller setTarget:self];
[_verticalScroller setAction:@selector(_verticalScrollerDidScroll:)];
@@ -483,10 +377,8 @@
if (_hasVerticalScroller && !_verticalScroller)
{
var bounds = [self _insetBounds];
[self setVerticalScroller:[[CPScroller alloc] initWithFrame:_CGRectMake(0.0, 0.0, [CPScroller scrollerWidth], MAX(_CGRectGetHeight(bounds), [CPScroller scrollerWidth] + 1))]];
[[self verticalScroller] setFrameSize:CGSizeMake([CPScroller scrollerWidth], _CGRectGetHeight(bounds))];
[self setVerticalScroller:[[CPScroller alloc] initWithFrame:_CGRectMake(0.0, 0.0, [CPScroller scrollerWidth], MAX(_CGRectGetHeight([self bounds]), [CPScroller scrollerWidth]+1))]];
[[self verticalScroller] setFrameSize:CGSizeMake([CPScroller scrollerWidth], _CGRectGetHeight([self bounds]))];
}
[self reflectScrolledClipView:_contentView];
@@ -511,7 +403,7 @@
return;
_autohidesScrollers = autohidesScrollers;
[self reflectScrolledClipView:_contentView];
}
@@ -561,11 +453,11 @@
if (!_cornerView)
return _CGRectMakeZero();
var bounds = [self _insetBounds],
var bounds = [self bounds],
frame = [_cornerView frame];
frame.origin.x = _CGRectGetMaxX(bounds) - _CGRectGetWidth(frame);
frame.origin.y = _CGRectGetMinY(bounds);
frame.origin.y = 0;
return frame;
}
@@ -577,7 +469,7 @@
if (!headerView)
return _CGRectMakeZero();
var frame = [self _insetBounds];
var frame = [self bounds];
frame.size.height = _CGRectGetHeight([headerView frame]);
frame.size.width -= _CGRectGetWidth([self _cornerViewFrame]);
@@ -585,69 +477,33 @@
return frame;
}
- (CGRect)_bottomCornerViewFrame
{
if ([[self horizontalScroller] isHidden] || [[self verticalScroller] isHidden])
return CGRectMakeZero();
var verticalFrame = [[self verticalScroller] frame],
bottomCornerFrame = CGRectMakeZero();
bottomCornerFrame.origin.x = CGRectGetMinX(verticalFrame);
bottomCornerFrame.origin.y = CGRectGetMaxY(verticalFrame);
bottomCornerFrame.size.width = [CPScroller scrollerWidth];
bottomCornerFrame.size.height = [CPScroller scrollerWidth];
return bottomCornerFrame;
}
- (void)setBottomCornerView:(CPView)aBottomCornerView
{
if (_bottomCornerView === aBottomCornerView)
return;
[_bottomCornerView removeFromSuperview];
[aBottomCornerView setFrame:[self _bottomCornerViewFrame]];
[self addSubview:aBottomCornerView];
_bottomCornerView = aBottomCornerView;
[self _updateCornerAndHeaderView];
}
- (CPView)bottomCornerView
{
return _bottomCornerView;
}
/* @ignore */
- (void)_verticalScrollerDidScroll:(CPScroller)aScroller
{
var value = [aScroller floatValue],
documentFrame = [[_contentView documentView] frame],
var value = [aScroller floatValue],
documentFrame = [[_contentView documentView] frame];
contentBounds = [_contentView bounds];
switch ([_verticalScroller hitPart])
{
case CPScrollerDecrementLine: contentBounds.origin.y -= _verticalLineScroll;
break;
case CPScrollerIncrementLine: contentBounds.origin.y += _verticalLineScroll;
break;
case CPScrollerDecrementPage: contentBounds.origin.y -= _CGRectGetHeight(contentBounds) - _verticalPageScroll;
break;
case CPScrollerIncrementPage: contentBounds.origin.y += _CGRectGetHeight(contentBounds) - _verticalPageScroll;
break;
case CPScrollerKnobSlot:
case CPScrollerKnob:
// We want integral bounds!
default: contentBounds.origin.y = ROUND(value * (_CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentBounds)));
}
[_contentView scrollToPoint:contentBounds.origin];
}
@@ -657,21 +513,21 @@
var value = [aScroller floatValue],
documentFrame = [[self documentView] frame],
contentBounds = [_contentView bounds];
switch ([_horizontalScroller hitPart])
{
case CPScrollerDecrementLine: contentBounds.origin.x -= _horizontalLineScroll;
break;
case CPScrollerIncrementLine: contentBounds.origin.x += _horizontalLineScroll;
break;
case CPScrollerDecrementPage: contentBounds.origin.x -= _CGRectGetWidth(contentBounds) - _horizontalPageScroll;
break;
case CPScrollerIncrementPage: contentBounds.origin.x += _CGRectGetWidth(contentBounds) - _horizontalPageScroll;
break;
case CPScrollerKnobSlot:
case CPScrollerKnob:
// We want integral bounds!
@@ -696,7 +552,7 @@
/*
@ignore
*/
- (void)resizeSubviewsWithOldSize:(CGSize)aSize
-(void)resizeSubviewsWithOldSize:(CGSize)aSize
{
[self reflectScrolledClipView:_contentView];
}
@@ -806,138 +662,14 @@
return _verticalPageScroll;
}
// CPView Overrides
- (void)drawRect:(CPRect)aRect
{
[super drawRect:aRect];
if (_borderType == CPNoBorder)
return;
var strokeRect = [self bounds],
context = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSetLineWidth(context, 1);
switch (_borderType)
{
case CPLineBorder:
CGContextSetStrokeColor(context, [self currentValueForThemeAttribute:@"border-color"]);
CGContextStrokeRect(context, _CGRectInset(strokeRect, 0.5, 0.5));
break;
case CPBezelBorder:
[self _drawGrayBezelInContext:context bounds:strokeRect];
break;
case CPGrooveBorder:
[self _drawGrooveInContext:context bounds:strokeRect];
break;
default:
break;
}
}
- (void)_drawGrayBezelInContext:(CGContext)context bounds:(CGRect)aRect
{
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:142.0 / 255.0 alpha:1.0]);
var y = _CGRectGetMinY(aRect) + 0.5;
CGContextMoveToPoint(context, _CGRectGetMinX(aRect), y);
CGContextAddLineToPoint(context, _CGRectGetMinX(aRect) + 1.0, y);
CGContextStrokePath(context);
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:192.0 / 255.0 alpha:1.0]);
CGContextMoveToPoint(context, _CGRectGetMinX(aRect) + 1.0, y);
CGContextAddLineToPoint(context, _CGRectGetMaxX(aRect) - 1.0, y);
CGContextStrokePath(context);
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:142.0 / 255.0 alpha:1.0]);
CGContextMoveToPoint(context, _CGRectGetMaxX(aRect) - 1.0, y);
CGContextAddLineToPoint(context, _CGRectGetMaxX(aRect), y);
CGContextStrokePath(context);
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:190.0 / 255.0 alpha:1.0]);
var x = _CGRectGetMaxX(aRect) - 0.5;
CGContextMoveToPoint(context, x, _CGRectGetMinY(aRect) + 1.0);
CGContextAddLineToPoint(context, x, _CGRectGetMaxY(aRect));
CGContextMoveToPoint(context, x - 0.5, _CGRectGetMaxY(aRect) - 0.5);
CGContextAddLineToPoint(context, _CGRectGetMinX(aRect), _CGRectGetMaxY(aRect) - 0.5);
x = _CGRectGetMinX(aRect) + 0.5;
CGContextMoveToPoint(context, x, _CGRectGetMaxY(aRect));
CGContextAddLineToPoint(context, x, _CGRectGetMinY(aRect) + 1.0);
CGContextStrokePath(context);
}
- (void)_drawGrooveInContext:(CGContext)context bounds:(CGRect)aRect
{
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:159.0 / 255.0 alpha:1.0]);
var y = _CGRectGetMinY(aRect) + 0.5;
CGContextMoveToPoint(context, _CGRectGetMinX(aRect), y);
CGContextAddLineToPoint(context, _CGRectGetMaxX(aRect), y);
var x = _CGRectGetMaxX(aRect) - 1.5;
CGContextMoveToPoint(context, x, _CGRectGetMinY(aRect) + 2.0);
CGContextAddLineToPoint(context, x, _CGRectGetMaxY(aRect) - 1.0);
y = _CGRectGetMaxY(aRect) - 1.5;
CGContextMoveToPoint(context, _CGRectGetMaxX(aRect) - 1.0, y);
CGContextAddLineToPoint(context, _CGRectGetMinX(aRect) + 2.0, y);
x = _CGRectGetMinX(aRect) + 0.5;
CGContextMoveToPoint(context, x, _CGRectGetMaxY(aRect));
CGContextAddLineToPoint(context, x, _CGRectGetMinY(aRect));
CGContextStrokePath(context);
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor whiteColor]);
var rect = _CGRectOffset(aRect, 1.0, 1.0);
rect.size.width -= 1.0;
rect.size.height -= 1.0;
CGContextStrokeRect(context, _CGRectInset(rect, 0.5, 0.5));
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:192.0 / 255.0 alpha:1.0]);
y = _CGRectGetMinY(aRect) + 2.5;
CGContextMoveToPoint(context, _CGRectGetMinX(aRect) + 2.0, y);
CGContextAddLineToPoint(context, _CGRectGetMaxX(aRect) - 2.0, y);
CGContextStrokePath(context);
}
// CPResponder Overrides
/*!
Handles a scroll wheel event from the user.
@param anEvent the scroll wheel event
*/
- (void)scrollWheel:(CPEvent)anEvent
{
[self _respondToScrollWheelEventWithDeltaX:[anEvent deltaX] deltaY:[anEvent deltaY]];
[self _respondToScrollWheelEventWithDeltaX:[anEvent deltaX] * _horizontalLineScroll
deltaY:[anEvent deltaY] * _verticalLineScroll];
}
- (void)_respondToScrollWheelEventWithDeltaX:(float)deltaX deltaY:(float)deltaY
@@ -945,15 +677,17 @@
var documentFrame = [[self documentView] frame],
contentBounds = [_contentView bounds],
contentFrame = [_contentView frame],
enclosingScrollView = [self enclosingScrollView];
enclosingScrollView = [self enclosingScrollView],
extraX = 0,
extraY = 0;
// We want integral bounds!
contentBounds.origin.x = ROUND(contentBounds.origin.x + deltaX);
contentBounds.origin.y = ROUND(contentBounds.origin.y + deltaY);
var constrainedOrigin = [_contentView constrainScrollPoint:CGPointCreateCopy(contentBounds.origin)],
extraX = contentBounds.origin.x - constrainedOrigin.x,
extraY = contentBounds.origin.y - constrainedOrigin.y;
var constrainedOrigin = [_contentView constrainScrollPoint:CGPointCreateCopy(contentBounds.origin)];
extraX = ((contentBounds.origin.x - constrainedOrigin.x) / _horizontalLineScroll) * [enclosingScrollView horizontalLineScroll];
extraY = ((contentBounds.origin.y - constrainedOrigin.y) / _verticalLineScroll) * [enclosingScrollView verticalLineScroll];
[_contentView scrollToPoint:constrainedOrigin];
[_headerClipView scrollToPoint:CGPointMake(constrainedOrigin.x, 0.0)];
@@ -962,13 +696,18 @@
[enclosingScrollView _respondToScrollWheelEventWithDeltaX:extraX deltaY:extraY];
}
- (void)scrollPageUp:(id)sender
- (void)keyDown:(CPEvent)anEvent
{
[self interpretKeyEvents:[anEvent]];
}
- (void)pageUp:(id)sender
{
var contentBounds = [_contentView bounds];
[self moveByOffset:CGSizeMake(0.0, -(_CGRectGetHeight(contentBounds) - _verticalPageScroll))];
}
- (void)scrollPageDown:(id)sender
- (void)pageDown:(id)sender
{
var contentBounds = [_contentView bounds];
[self moveByOffset:CGSizeMake(0.0, _CGRectGetHeight(contentBounds) - _verticalPageScroll)];
@@ -1008,20 +747,18 @@
@end
var CPScrollViewContentViewKey = @"CPScrollViewContentView",
CPScrollViewHeaderClipViewKey = @"CPScrollViewHeaderClipViewKey",
CPScrollViewVLineScrollKey = @"CPScrollViewVLineScroll",
CPScrollViewHLineScrollKey = @"CPScrollViewHLineScroll",
CPScrollViewVPageScrollKey = @"CPScrollViewVPageScroll",
CPScrollViewHPageScrollKey = @"CPScrollViewHPageScroll",
CPScrollViewHasVScrollerKey = @"CPScrollViewHasVScroller",
CPScrollViewHasHScrollerKey = @"CPScrollViewHasHScroller",
CPScrollViewVScrollerKey = @"CPScrollViewVScroller",
CPScrollViewHScrollerKey = @"CPScrollViewHScroller",
CPScrollViewAutohidesScrollerKey = @"CPScrollViewAutohidesScroller",
CPScrollViewCornerViewKey = @"CPScrollViewCornerViewKey",
CPScrollViewBottomCornerViewKey = @"CPScrollViewBottomCornerViewKey",
CPScrollViewBorderTypeKey = @"CPScrollViewBorderTypeKey";
var CPScrollViewContentViewKey = "CPScrollViewContentView",
CPScrollViewHeaderClipViewKey = "CPScrollViewHeaderClipViewKey",
CPScrollViewVLineScrollKey = "CPScrollViewVLineScroll",
CPScrollViewHLineScrollKey = "CPScrollViewHLineScroll",
CPScrollViewVPageScrollKey = "CPScrollViewVPageScroll",
CPScrollViewHPageScrollKey = "CPScrollViewHPageScroll",
CPScrollViewHasVScrollerKey = "CPScrollViewHasVScroller",
CPScrollViewHasHScrollerKey = "CPScrollViewHasHScroller",
CPScrollViewVScrollerKey = "CPScrollViewVScroller",
CPScrollViewHScrollerKey = "CPScrollViewHScroller",
CPScrollViewAutohidesScrollerKey = "CPScrollViewAutohidesScroller",
CPScrollViewCornerViewKey = "CPScrollViewCornerViewKey";
@implementation CPScrollView (CPCoding)
@@ -1034,7 +771,7 @@ var CPScrollViewContentViewKey = @"CPScrollViewContentView",
_horizontalLineScroll = [aCoder decodeFloatForKey:CPScrollViewHLineScrollKey];
_horizontalPageScroll = [aCoder decodeFloatForKey:CPScrollViewHPageScrollKey];
_contentView = [aCoder decodeObjectForKey:CPScrollViewContentViewKey];
_headerClipView = [aCoder decodeObjectForKey:CPScrollViewHeaderClipViewKey];
@@ -1051,41 +788,35 @@ var CPScrollViewContentViewKey = @"CPScrollViewContentView",
_hasHorizontalScroller = [aCoder decodeBoolForKey:CPScrollViewHasHScrollerKey];
_autohidesScrollers = [aCoder decodeBoolForKey:CPScrollViewAutohidesScrollerKey];
_borderType = [aCoder decodeIntForKey:CPScrollViewBorderTypeKey];
_cornerView = [aCoder decodeObjectForKey:CPScrollViewCornerViewKey];
_bottomCornerView = [aCoder decodeObjectForKey:CPScrollViewBottomCornerViewKey];
// Do to the anything goes nature of decoding, our subviews may not exist yet, so layout at the end of the run loop when we're sure everything is in a correct state.
[[CPRunLoop currentRunLoop] performSelector:@selector(reflectScrolledClipView:) target:self argument:_contentView order:0 modes:[CPDefaultRunLoopMode]];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_contentView forKey:CPScrollViewContentViewKey];
[aCoder encodeObject:_headerClipView forKey:CPScrollViewHeaderClipViewKey];
[aCoder encodeObject:_verticalScroller forKey:CPScrollViewVScrollerKey];
[aCoder encodeObject:_horizontalScroller forKey:CPScrollViewHScrollerKey];
[aCoder encodeFloat:_verticalLineScroll forKey:CPScrollViewVLineScrollKey];
[aCoder encodeFloat:_verticalPageScroll forKey:CPScrollViewVPageScrollKey];
[aCoder encodeFloat:_horizontalLineScroll forKey:CPScrollViewHLineScrollKey];
[aCoder encodeFloat:_horizontalPageScroll forKey:CPScrollViewHPageScrollKey];
[aCoder encodeBool:_hasVerticalScroller forKey:CPScrollViewHasVScrollerKey];
[aCoder encodeBool:_hasHorizontalScroller forKey:CPScrollViewHasHScrollerKey];
[aCoder encodeBool:_autohidesScrollers forKey:CPScrollViewAutohidesScrollerKey];
[aCoder encodeObject:_cornerView forKey:CPScrollViewCornerViewKey];
[aCoder encodeObject:_bottomCornerView forKey:CPScrollViewBottomCornerViewKey];
[aCoder encodeInt:_borderType forKey:CPScrollViewBorderTypeKey];
}
@end
+81 -93
View File
@@ -22,6 +22,8 @@
@import "CPControl.j"
#include "CoreGraphics/CGGeometry.h"
// CPScroller Constants
CPScrollerNoPart = 0;
@@ -39,9 +41,9 @@ CPNoScrollerParts = 0;
CPOnlyScrollerArrows = 1;
CPAllScrollerParts = 2;
/*!
/*!
@ingroup appkit
@class CPScroller
@class CPScroller
*/
var PARTS_ARRANGEMENT = [CPScrollerKnobSlot, CPScrollerDecrementLine, CPScrollerIncrementLine, CPScrollerKnob],
@@ -70,25 +72,24 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
CGPoint _trackingStartPoint;
}
+ (CPString)defaultThemeClass
+ (CPString)themeClass
{
return "scroller";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithJSObject:{
@"scroller-width": 15.0,
@"knob-slot-color": [CPColor lightGrayColor],
@"decrement-line-color": [CPNull null],
@"increment-line-color": [CPNull null],
@"knob-color": [CPColor grayColor],
@"decrement-line-size":_CGSizeMakeZero(),
@"increment-line-size":_CGSizeMakeZero(),
@"track-inset":_CGInsetMakeZero(),
@"knob-inset": _CGInsetMakeZero(),
@"minimum-knob-length":21.0
}]
return [CPDictionary dictionaryWithObjects:[ [CPNull null], [CPNull null], [CPNull null], [CPNull null],
_CGSizeMakeZero(), _CGSizeMakeZero(), _CGInsetMakeZero(), _CGInsetMakeZero(), _CGSizeMakeZero()]
forKeys:[ @"knob-slot-color",
@"decrement-line-color",
@"increment-line-color",
@"knob-color",
@"decrement-line-size",
@"increment-line-size",
@"track-inset",
@"knob-inset",
@"minimum-knob-length"]];
}
@@ -97,7 +98,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_controlSize = CPRegularControlSize;
@@ -105,7 +106,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
[self setFloatValue:0.0];
[self setKnobProportion:1.0];
_hitPart = CPScrollerNoPart;
[self _calculateIsVertical];
@@ -120,7 +121,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
*/
+ (float)scrollerWidth
{
return [[[CPScroller alloc] init] currentValueForThemeAttribute:@"scroller-width"];
return 15.0;//[self scrollerWidthForControlSize:CPRegularControlSize];
}
/*!
@@ -129,7 +130,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
*/
+ (float)scrollerWidthForControlSize:(CPControlSize)aControlSize
{
return [self scrollerWidth];
return 15.0;//_CPScrollerWidths[aControlSize];
}
/*!
@@ -179,10 +180,10 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
- (id)currentValueForThemeAttribute:(CPString)anAttributeName
{
var themeState = _themeState;
if (NAMES_FOR_PARTS[_hitPart] + "-color" !== anAttributeName)
themeState &= ~CPThemeStateHighlighted;
return [self valueForThemeAttribute:anAttributeName inState:themeState];
}
@@ -204,25 +205,25 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
- (CPScrollerPart)testPart:(CGPoint)aPoint
{
aPoint = [self convertPoint:aPoint fromView:nil];
// The ordering of these tests is important. We check the knob and
// The ordering of these tests is important. We check the knob and
// page rects first since they may overlap with the arrows.
if (CGRectContainsPoint([self rectForPart:CPScrollerKnob], aPoint))
return CPScrollerKnob;
if (CGRectContainsPoint([self rectForPart:CPScrollerDecrementPage], aPoint))
return CPScrollerDecrementPage;
if (CGRectContainsPoint([self rectForPart:CPScrollerIncrementPage], aPoint))
return CPScrollerIncrementPage;
if (CGRectContainsPoint([self rectForPart:CPScrollerDecrementLine], aPoint))
return CPScrollerDecrementLine;
if (CGRectContainsPoint([self rectForPart:CPScrollerIncrementLine], aPoint))
return CPScrollerIncrementLine;
if (CGRectContainsPoint([self rectForPart:CPScrollerKnobSlot], aPoint))
return CPScrollerKnobSlot;
@@ -240,7 +241,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
if (_knobProportion === 1.0)
{
_usableParts = CPNoScrollerParts;
_partRects[CPScrollerDecrementPage] = CGRectMakeZero();
_partRects[CPScrollerKnob] = CGRectMakeZero();
_partRects[CPScrollerIncrementPage] = CGRectMakeZero();
@@ -249,7 +250,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
// In this case, the slot is the entirety of the scroller.
_partRects[CPScrollerKnobSlot] = CGRectMakeCopy(bounds);
return;
}
@@ -259,8 +260,8 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
var knobInset = [self currentValueForThemeAttribute:@"knob-inset"],
trackInset = [self currentValueForThemeAttribute:@"track-inset"],
width = _CGRectGetWidth(bounds),
height = _CGRectGetHeight(bounds);
height = _CGRectGetHeight(bounds);
if ([self isVertical])
{
var decrementLineSize = [self currentValueForThemeAttribute:"decrement-line-size"],
@@ -279,11 +280,11 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
_partRects[CPScrollerKnobSlot] = _CGRectMake(trackInset.left, effectiveDecrementLineHeight, width - trackInset.left - trackInset.right, slotHeight);
_partRects[CPScrollerDecrementLine] = _CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height);
_partRects[CPScrollerIncrementLine] = _CGRectMake(0.0, height - incrementLineSize.height, incrementLineSize.width, incrementLineSize.height);
if (height < knobHeight + decrementLineSize.height + incrementLineSize.height + trackInset.top + trackInset.bottom)
if(height < knobHeight + decrementLineSize.height + incrementLineSize.height + trackInset.top + trackInset.bottom)
_partRects[CPScrollerKnob] = _CGRectMakeZero();
if (height < decrementLineSize.height + incrementLineSize.height - 2)
if(height < decrementLineSize.height + incrementLineSize.height - 2)
{
_partRects[CPScrollerIncrementLine] = _CGRectMakeZero();
_partRects[CPScrollerDecrementLine] = _CGRectMakeZero();
@@ -295,7 +296,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
var decrementLineSize = [self currentValueForThemeAttribute:"decrement-line-size"],
incrementLineSize = [self currentValueForThemeAttribute:"increment-line-size"],
effectiveDecrementLineWidth = decrementLineSize.width + trackInset.left,
effectiveIncrementLineWidth = incrementLineSize.width + trackInset.right,
effectiveIncrementLineWidth = incrementLineSize.width + trackInset.right;
slotWidth = width - effectiveDecrementLineWidth - effectiveIncrementLineWidth,
minimumKnobLength = [self currentValueForThemeAttribute:"minimum-knob-length"],
knobWidth = MAX(minimumKnobLength, (slotWidth * _knobProportion)),
@@ -308,11 +309,11 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
_partRects[CPScrollerKnobSlot] = _CGRectMake(effectiveDecrementLineWidth, trackInset.top, slotWidth, height - trackInset.top - trackInset.bottom);
_partRects[CPScrollerDecrementLine] = _CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height);
_partRects[CPScrollerIncrementLine] = _CGRectMake(width - incrementLineSize.width, 0.0, incrementLineSize.width, incrementLineSize.height);
if (width < knobWidth + decrementLineSize.width + incrementLineSize.width + trackInset.left + trackInset.right)
if(width < knobWidth + decrementLineSize.width + incrementLineSize.width + trackInset.left + trackInset.right)
_partRects[CPScrollerKnob] = _CGRectMakeZero();
if (width < decrementLineSize.width + incrementLineSize.width - 2)
if(width < decrementLineSize.width + incrementLineSize.width - 2)
{
_partRects[CPScrollerIncrementLine] = _CGRectMakeZero();
_partRects[CPScrollerDecrementLine] = _CGRectMakeZero();
@@ -357,9 +358,9 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
- (CPView)createViewForPart:(CPScrollerPart)aPart
{
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
[view setHitTests:NO];
return view;
}
@@ -373,7 +374,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
[view setHitTests:NO];
return view;
}
@@ -387,12 +388,12 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
for (; index < count; ++index)
{
var part = PARTS_ARRANGEMENT[index];
if (index === 0)
view = [self layoutEphemeralSubviewNamed:part positioned:CPWindowBelow relativeToEphemeralSubviewNamed:PARTS_ARRANGEMENT[index + 1]];
else
view = [self layoutEphemeralSubviewNamed:part positioned:CPWindowAbove relativeToEphemeralSubviewNamed:PARTS_ARRANGEMENT[index - 1]];
if (view)
[view setBackgroundColor:[self currentValueForThemeAttribute:NAMES_FOR_PARTS[part] + "-color"]];
}
@@ -402,7 +403,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
Caches images for the scroll arrow and knob.
*/
- (void)drawParts
{
{
[self drawKnobSlot];
[self drawKnob];
[self drawArrow:CPScrollerDecrementArrow highlight:NO];
@@ -425,37 +426,37 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
- (void)trackKnob:(CPEvent)anEvent
{
var type = [anEvent type];
if (type === CPLeftMouseUp)
{
_hitPart = CPScrollerNoPart;
return;
}
if (type === CPLeftMouseDown)
{
_trackingFloatValue = [self floatValue];
_trackingStartPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil];
}
else if (type === CPLeftMouseDragged)
{
var knobRect = [self rectForPart:CPScrollerKnob],
knobSlotRect = [self rectForPart:CPScrollerKnobSlot],
remainder = ![self isVertical] ? (_CGRectGetWidth(knobSlotRect) - _CGRectGetWidth(knobRect)) : (_CGRectGetHeight(knobSlotRect) - _CGRectGetHeight(knobRect));
if (remainder <= 0)
[self setFloatValue:0.0];
else
{
var location = [self convertPoint:[anEvent locationInWindow] fromView:nil],
var location = [self convertPoint:[anEvent locationInWindow] fromView:nil];
delta = ![self isVertical] ? location.x - _trackingStartPoint.x : location.y - _trackingStartPoint.y;
[self setFloatValue:_trackingFloatValue + delta / remainder];
}
}
[CPApp setTarget:self selector:@selector(trackKnob:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
[self sendAction:[self action] to:[self target]];
@@ -473,26 +474,26 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
{
[self highlight:NO];
[CPEvent stopPeriodicEvents];
_hitPart = CPScrollerNoPart;
return;
}
if (type === CPLeftMouseDown)
{
_trackingPart = [self hitPart];
_trackingStartPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil];
if ([anEvent modifierFlags] & CPAlternateKeyMask)
{
if (_trackingPart == CPScrollerDecrementLine)
_hitPart = CPScrollerDecrementPage;
else if (_trackingPart == CPScrollerIncrementLine)
_hitPart = CPScrollerIncrementPage;
else if (_trackingPart == CPScrollerDecrementPage || _trackingPart == CPScrollerIncrementPage)
{
var knobRect = [self rectForPart:CPScrollerKnob],
@@ -501,42 +502,42 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
remainder = (![self isVertical] ? _CGRectGetWidth(knobSlotRect) : _CGRectGetHeight(knobSlotRect)) - knobWidth;
[self setFloatValue:((![self isVertical] ? _trackingStartPoint.x - _CGRectGetMinX(knobSlotRect) : _trackingStartPoint.y - _CGRectGetMinY(knobSlotRect)) - knobWidth / 2.0) / remainder];
_hitPart = CPScrollerKnob;
[self sendAction:[self action] to:[self target]];
[self sendAction:[self action] to:[self target]];
// Now just track the knob.
return [self trackKnob:anEvent];
}
}
[self highlight:YES];
[self sendAction:[self action] to:[self target]];
[CPEvent startPeriodicEventsAfterDelay:0.5 withPeriod:0.04];
}
else if (type === CPLeftMouseDragged)
{
_trackingStartPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil];
if (_trackingPart == CPScrollerDecrementPage || _trackingPart == CPScrollerIncrementPage)
{
var hitPart = [self testPart:[anEvent locationInWindow]];
if (hitPart == CPScrollerDecrementPage || hitPart == CPScrollerIncrementPage)
{
_trackingPart = hitPart;
_hitPart = hitPart;
}
}
[self highlight:CGRectContainsPoint([self rectForPart:_trackingPart], _trackingStartPoint)];
}
else if (type == CPPeriodic && CGRectContainsPoint([self rectForPart:_trackingPart], _trackingStartPoint))
[self sendAction:[self action] to:[self target]];
[CPApp setTarget:self selector:@selector(trackScrollButtons:) forNextEventMatchingMask:CPPeriodicMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
}
@@ -568,15 +569,15 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
{
if (![self isEnabled])
return;
_hitPart = [self testPart:[anEvent locationInWindow]];
switch (_hitPart)
{
case CPScrollerKnob: return [self trackKnob:anEvent];
case CPScrollerDecrementLine:
case CPScrollerIncrementLine:
case CPScrollerDecrementLine:
case CPScrollerIncrementLine:
case CPScrollerDecrementPage:
case CPScrollerIncrementPage: return [self trackScrollButtons:anEvent];
}
@@ -602,32 +603,19 @@ var CPScrollerControlSizeKey = "CPScrollerControlSize",
_knobProportion = [aCoder decodeFloatForKey:CPScrollerKnobProportionKey];
_partRects = [];
_hitPart = CPScrollerNoPart;
[self _calculateIsVertical];
// Adjust the size of the scroller if the size from cib
// isn't equal to the scrollerWidth
var frame = [self frame],
scrollerWidth = [CPScroller scrollerWidth];
if ([self isVertical] && CGRectGetWidth(frame) !== scrollerWidth)
frame.size.width = scrollerWidth;
if (![self isVertical] && CGRectGetHeight(frame) !== scrollerWidth)
frame.size.height = scrollerWidth;
[self setFrame:frame];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeInt:_controlSize forKey:CPScrollerControlSizeKey];
[aCoder encodeFloat:_knobProportion forKey:CPScrollerKnobProportionKey];
}
+135 -238
View File
@@ -20,28 +20,20 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPButton.j"
@import "CPTextField.j"
#include "Platform/Platform.h"
CPSearchFieldRecentsTitleMenuItemTag = 1000;
CPSearchFieldRecentsMenuItemTag = 1001;
CPSearchFieldClearRecentsMenuItemTag = 1002;
CPSearchFieldNoRecentsMenuItemTag = 1003;
CPSearchFieldSeparatorMenuItemTag = 1004;
var CPSearchFieldSearchImage = nil,
CPSearchFieldFindImage = nil,
CPSearchFieldCancelImage = nil,
CPSearchFieldCancelPressedImage = nil;
var SEARCH_BUTTON_DEFAULT_WIDTH = 25.0,
CANCEL_BUTTON_DEFAULT_WIDTH = 22.0,
BUTTON_DEFAULT_HEIGHT = 22.0;
var RECENT_SEARCH_PREFIX = @" ";
/*!
@ingroup appkit
@class CPSearchField
@@ -62,37 +54,32 @@ var RECENT_SEARCH_PREFIX = @" ";
int _maximumRecents;
BOOL _sendsWholeSearchString;
BOOL _sendsSearchStringImmediately;
BOOL _canResignFirstResponder;
CPTimer _partialStringTimer;
}
+ (CPString)defaultThemeClass
{
return @"searchfield"
}
+ (void)initialize
{
if (self != [CPSearchField class])
return;
var bundle = [CPBundle bundleForClass:self];
CPSearchFieldSearchImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldSearch.png"] size:_CGSizeMake(SEARCH_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT)];
CPSearchFieldFindImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldFind.png"] size:_CGSizeMake(SEARCH_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT)];
CPSearchFieldCancelImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldCancel.png"] size:_CGSizeMake(CANCEL_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT)];
CPSearchFieldCancelPressedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldCancelPressed.png"] size:_CGSizeMake(CANCEL_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT)];
CPSearchFieldSearchImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldSearch.png"] size:CGSizeMake(25, 22)];
CPSearchFieldFindImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldFind.png"] size:CGSizeMake(25, 22)];
CPSearchFieldCancelImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldCancel.png"] size:CGSizeMake(22, 22)];
CPSearchFieldCancelPressedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldCancelPressed.png"] size:CGSizeMake(22, 22)];
}
- (id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
_recentSearches = [CPArray array];
_maximumRecents = 10;
_sendsWholeSearchString = NO;
_sendsSearchStringImmediately = NO;
_recentsAutosaveName = nil;
[self _init];
[self _initWithFrame:frame];
#if PLATFORM(DOM)
_cancelButton._DOMElement.style.cursor = "default";
_searchButton._DOMElement.style.cursor = "default";
@@ -102,28 +89,23 @@ var RECENT_SEARCH_PREFIX = @" ";
return self;
}
- (void)_init
- (void)_initWithFrame:(CGRect)frame
{
_recentSearches = [CPArray array];
[self setBezeled:YES];
[self setBezelStyle:CPTextFieldRoundedBezel];
[self setBordered:YES];
[self setEditable:YES];
[self setDelegate:self];
[self setContinuous:YES];
var bounds = [self bounds],
cancelButton = [[CPButton alloc] initWithFrame:[self cancelButtonRectForBounds:bounds]],
searchButton = [[CPButton alloc] initWithFrame:[self searchButtonRectForBounds:bounds]];
[self setCancelButton:cancelButton];
_cancelButton = [[CPButton alloc] initWithFrame:CGRectMake(frame.size.width - 27,(frame.size.height-22)/2,22,22)];
[self resetCancelButton];
[_cancelButton setHidden:YES];
[_cancelButton setAutoresizingMask:CPViewMinXMargin];
[self addSubview:_cancelButton];
[self setSearchButton:searchButton];
_searchButton = [[CPButton alloc] initWithFrame:CGRectMake(5,(frame.size.height-25)/2,25,25)];
[self resetSearchButton];
_canResignFirstResponder = YES;
[self addSubview:_searchButton];
}
// Managing Buttons
@@ -133,15 +115,7 @@ var RECENT_SEARCH_PREFIX = @" ";
*/
- (void)setSearchButton:(CPButton)button
{
if (button != _searchButton)
{
[_searchButton removeFromSuperview];
_searchButton = button;
[_searchButton setFrame:[self searchButtonRectForBounds:[self bounds]]];
[_searchButton setAutoresizingMask:CPViewMaxXMargin];
[self addSubview:_searchButton];
}
_searchButton = button;
}
/*!
@@ -159,13 +133,30 @@ var RECENT_SEARCH_PREFIX = @" ";
*/
- (void)resetSearchButton
{
var button = [self searchButton],
searchButtonImage = (_searchMenuTemplate === nil) ? CPSearchFieldSearchImage : CPSearchFieldFindImage;
var searchButtonImage,
action,
target,
button = [self searchButton];
if (_searchMenuTemplate === nil)
{
searchButtonImage = CPSearchFieldSearchImage;
action = @selector(_sendAction:);
target = self;
}
else
{
searchButtonImage = CPSearchFieldFindImage;
action = @selector(_showMenu:);
target = self;
}
[button setBordered:NO];
[button setImageScaling:CPScaleToFit];
[button setImage:searchButtonImage];
[button setAutoresizingMask:CPViewMaxXMargin];
[button setTarget:target];
[button setAction:action];
}
/*!
@@ -174,18 +165,7 @@ var RECENT_SEARCH_PREFIX = @" ";
*/
- (void)setCancelButton:(CPButton)button
{
if (button != _cancelButton)
{
[_cancelButton removeFromSuperview];
_cancelButton = button;
[_cancelButton setFrame:[self cancelButtonRectForBounds:[self bounds]]];
[_cancelButton setAutoresizingMask:CPViewMinXMargin];
[_cancelButton setTarget:self];
[_cancelButton setAction:@selector(_searchFieldCancel:)];
[self _updateCancelButtonVisibility];
[self addSubview:_cancelButton];
}
_cancelButton = button;
}
/*!
@@ -220,25 +200,23 @@ var RECENT_SEARCH_PREFIX = @" ";
@return The updated bounding rectangle to use for the search text field. The default value is the value passed into the rect parameter.
Subclasses can override this method to return a new bounding rectangle for the text-field object. You might use this method to provide a custom layout for the search field control.
*/
- (CGRect)searchTextRectForBounds:(CGRect)rect
- (CPRect)searchTextRectForBounds:(CPRect)rect
{
var leftOffset = 0,
width = _CGRectGetWidth(rect),
bounds = [self bounds];
var leftOffset = 0, width = rect.size.width;
if (_searchButton)
{
var searchBounds = [self searchButtonRectForBounds:bounds];
leftOffset = _CGRectGetMaxX(searchBounds) + 2;
var searchRect = [_searchButton frame];
leftOffset = searchRect.origin.x + searchRect.size.width;
}
if (_cancelButton)
{
var cancelRect = [self cancelButtonRectForBounds:bounds];
width = _CGRectGetMinX(cancelRect) - leftOffset;
var cancelRect = [_cancelButton frame];
width = cancelRect.origin.x - leftOffset;
}
return _CGRectMake(leftOffset, _CGRectGetMinY(rect), width, _CGRectGetHeight(rect));
return CPMakeRect(leftOffset,rect.origin.y,width,rect.size.height);
}
/*!
@@ -246,9 +224,9 @@ var RECENT_SEARCH_PREFIX = @" ";
@param rect The current bounding rectangle for the search button.
Subclasses can override this method to return a new bounding rectangle for the search button. You might use this method to provide a custom layout for the search field control.
*/
- (CGRect)searchButtonRectForBounds:(CGRect)rect
- (CPRect)searchButtonRectForBounds:(CPRect)rect
{
return _CGRectMake(5, (_CGRectGetHeight(rect) - BUTTON_DEFAULT_HEIGHT) / 2, SEARCH_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT);
return [_searchButton frame];
}
/*!
@@ -256,9 +234,9 @@ var RECENT_SEARCH_PREFIX = @" ";
@param rect The updated bounding rectangle to use for the cancel button. The default value is the value passed into the rect parameter.
Subclasses can override this method to return a new bounding rectangle for the cancel button. You might use this method to provide a custom layout for the search field control.
*/
- (CGRect)cancelButtonRectForBounds:(CGRect)rect
{
return _CGRectMake(_CGRectGetWidth(rect) - CANCEL_BUTTON_DEFAULT_WIDTH - 5, (_CGRectGetHeight(rect) - CANCEL_BUTTON_DEFAULT_WIDTH) / 2, BUTTON_DEFAULT_HEIGHT, BUTTON_DEFAULT_HEIGHT);
- (CPRect)cancelButtonRectForBounds:(CPRect)rect
{
return [_cancelButton frame];
}
// Managing Menu Templates
@@ -276,9 +254,9 @@ var RECENT_SEARCH_PREFIX = @" ";
@param menu The menu template to use.
The receiver looks for the tag constants described in ŇMenu tagsÓ to determine how to populate the menu with items related to recent searches. See ŇConfiguring a Search MenuÓ for a sample of how you might set up the search menu template.
*/
- (void)setSearchMenuTemplate:(CPMenu)aMenu
- (void)setSearchMenuTemplate:(CPMenu)menu
{
_searchMenuTemplate = aMenu;
_searchMenuTemplate = menu;
[self resetSearchButton];
[self _loadRecentSearchList];
@@ -395,7 +373,7 @@ var RECENT_SEARCH_PREFIX = @" ";
// Private methods and subclassing
- (CGRect)contentRectForBounds:(CGRect)bounds
- (CPRect)contentRectForBounds:(CPRect)bounds
{
var superbounds = [super contentRectForBounds:bounds];
return [self searchTextRectForBounds:superbounds];
@@ -469,78 +447,37 @@ var RECENT_SEARCH_PREFIX = @" ";
[self _updateSearchMenu];
}
- (CPView)hitTest:(CGPoint)aPoint
- (BOOL)trackMouse:(CPEvent)event
{
// Make sure a hit anywhere within the search field returns the search field itself
if (_CGRectContainsPoint([self frame], aPoint))
return self;
else
return nil;
}
- (BOOL)resignFirstResponder
{
return _canResignFirstResponder && [super resignFirstResponder];
}
- (void)mouseDown:(CPEvent)anEvent
{
var location = [anEvent locationInWindow],
point = [self convertPoint:location fromView:nil];
if (_CGRectContainsPoint([self searchButtonRectForBounds:[self bounds]], point))
var rect,
point,
location = [event locationInWindow];
point = [self convertPoint:location fromView:nil];
rect = [self searchButtonRectForBounds:[self frame]];
if (CPRectContainsPoint(rect,point))
{
if (_searchMenuTemplate == nil)
[self _sendAction:self];
else
[self _showMenu];
}
else if (_CGRectContainsPoint([self cancelButtonRectForBounds:[self bounds]], point))
[_cancelButton mouseDown:anEvent];
else
[super mouseDown:anEvent];
return [[self searchButton] trackMouse:event];
}
rect = [self cancelButtonRectForBounds:[self frame]];
if (CPRectContainsPoint(rect,point))
{
return [[self cancelButton] trackMouse:event];
}
return [super trackMouse:event];
}
/*!
Provides the common case items for a recent searches menu. If there are not recent searches,
displays a single disabled item:
No Recent Searches
If there are 1 more recent searches, it displays:
Recent Searches
recent search 1
recent search 2
etc.
---------------------
Clear Recent Searches
If you wish to add items before or after the template, you can. If you put items
before, a separator will automatically be placed before the default template item.
If you add items after the default template, it is your responsibility to add a separator.
To add a custom item:
item = [[CPMenuItem alloc] initWithTitle:@"google"
action:@selector(google:)
keyEquivalent:@""];
[item setTag:700];
[item setTarget:self];
[template addItem:item];
Be sure that your custom items do not use tags in the range 1000-1004 inclusive.
If you wish to maintain state in custom menu items that you add, you will need to maintain
the item state yourself, then in the action method of the custom items, modify the items
in the search menu template and send [searchField setSearchMenuTemplate:template] to update the menu.
*/
- (CPMenu)defaultSearchMenuTemplate
- (CPMenu)_defaultSearchMenuTemplate
{
var template = [[CPMenu alloc] init],
item;
item = [[CPMenuItem alloc] initWithTitle:@"Recent Searches"
action:nil
var template, item;
template = [[CPMenu alloc] init];
item = [[CPMenuItem alloc] initWithTitle:@"Recent searches"
action:NULL
keyEquivalent:@""];
[item setTag:CPSearchFieldRecentsTitleMenuItemTag];
[item setEnabled:NO];
@@ -553,15 +490,15 @@ var RECENT_SEARCH_PREFIX = @" ";
[item setTarget:self];
[template addItem:item];
item = [[CPMenuItem alloc] initWithTitle:@"Clear Recent Searches"
item = [[CPMenuItem alloc] initWithTitle:@"Clear recent searches"
action:@selector(_searchFieldClearRecents:)
keyEquivalent:@""];
[item setTag:CPSearchFieldClearRecentsMenuItemTag];
[item setTarget:self];
[template addItem:item];
item = [[CPMenuItem alloc] initWithTitle:@"No Recent Searches"
action:nil
item = [[CPMenuItem alloc] initWithTitle:@"No recent searches"
action:NULL
keyEquivalent:@""];
[item setTag:CPSearchFieldNoRecentsMenuItemTag];
[item setEnabled:NO];
@@ -575,96 +512,61 @@ var RECENT_SEARCH_PREFIX = @" ";
if (_searchMenuTemplate === nil)
return;
var menu = [[CPMenu alloc] init],
var i, menu = [[CPMenu alloc] init],
countOfRecents = [_recentSearches count],
numberOfItems = [_searchMenuTemplate numberOfItems];
for (var i = 0; i < numberOfItems; i++)
for (i = 0; i < numberOfItems; i++)
{
var item = [[_searchMenuTemplate itemAtIndex:i] copy];
switch ([item tag])
{
case CPSearchFieldRecentsTitleMenuItemTag:
if (countOfRecents === 0)
continue;
if ([menu numberOfItems] > 0)
[self _addSeparatorToMenu:menu];
break;
case CPSearchFieldRecentsMenuItemTag:
{
var itemAction = @selector(_searchFieldSearch:);
for (var recentIndex = 0; recentIndex < countOfRecents; ++recentIndex)
{
// RECENT_SEARCH_PREFIX is a hack until CPMenuItem -setIndentationLevel works
var recentItem = [[CPMenuItem alloc] initWithTitle:RECENT_SEARCH_PREFIX + [_recentSearches objectAtIndex:recentIndex]
action:itemAction
keyEquivalent:[item keyEquivalent]];
[item setTarget:self];
[menu addItem:recentItem];
}
continue;
}
case CPSearchFieldClearRecentsMenuItemTag:
if (countOfRecents === 0)
continue;
if ([menu numberOfItems] > 0)
[self _addSeparatorToMenu:menu];
[item setAction:@selector(_searchFieldClearRecents:)];
[item setTarget:self];
break;
case CPSearchFieldNoRecentsMenuItemTag:
if (countOfRecents !== 0)
continue;
if ([menu numberOfItems] > 0)
[self _addSeparatorToMenu:menu];
break;
case CPSearchFieldSeparatorMenuItemTag:
item = [CPMenuItem separatorItem];
[item setEnabled:NO];
[menu addItem:item];
continue;
}
var item = [_searchMenuTemplate itemAtIndex:i],
tag = [item tag];
[item setEnabled:([item isEnabled] && [item action] != nil && [item target] != nil)];
[menu addItem:item];
}
[menu setDelegate:self];
if (!(tag === CPSearchFieldRecentsTitleMenuItemTag && countOfRecents === 0) &&
!(tag === CPSearchFieldClearRecentsMenuItemTag && countOfRecents === 0) &&
!(tag === CPSearchFieldNoRecentsMenuItemTag && countOfRecents != 0) &&
!(tag === CPSearchFieldRecentsMenuItemTag))
{
var itemAction, itemTarget;
switch (tag)
{
case CPSearchFieldRecentsTitleMenuItemTag : itemAction = NULL; itemTarget = NULL; break;
case CPSearchFieldClearRecentsMenuItemTag : itemAction = @selector(_searchFieldClearRecents:); itemTarget = self; break;
case CPSearchFieldNoRecentsMenuItemTag : itemAction = NULL; itemTarget = NULL; break;
default: itemAction = [item action]; itemTarget = [item target]; break;
}
if (tag === CPSearchFieldClearRecentsMenuItemTag || tag === CPSearchFieldRecentsTitleMenuItemTag)
{
var separator = [CPMenuItem separatorItem];
[separator setEnabled:NO];
[menu addItem:separator];
}
var templateItem = [[CPMenuItem alloc] initWithTitle:[item title]
action:itemAction
keyEquivalent:[item keyEquivalent]];
[templateItem setTarget:itemTarget];
[templateItem setEnabled:([item isEnabled] && itemAction != NULL)];
[templateItem setTag:tag];
[menu addItem:templateItem];
}
else if (tag === CPSearchFieldRecentsMenuItemTag)
{
var j;
for (j = 0; j < countOfRecents; j++)
{
var rencentItem = [[CPMenuItem alloc] initWithTitle:[_recentSearches objectAtIndex:j]
action:@selector(_searchFieldSearch:)
keyEquivalent:[item keyEquivalent]];
[rencentItem setTarget:self];
[menu addItem:rencentItem];
}
}
}
_searchMenu = menu;
}
- (void)_addSeparatorToMenu:(CPMenu)aMenu
{
var separator = [CPMenuItem separatorItem];
[separator setEnabled:NO];
[aMenu addItem:separator];
}
- (void)menuWillOpen:(CPMenu)menu
{
_canResignFirstResponder = NO;
}
- (void)menuDidClose:(CPMenu)menu
{
_canResignFirstResponder = YES;
[self becomeFirstResponder];
}
- (void)_showMenu
- (void)_showMenu:(id)sender
{
if (_searchMenu === nil || [_searchMenu numberOfItems] === 0 || ![self isEnabled])
return;
@@ -674,14 +576,12 @@ var RECENT_SEARCH_PREFIX = @" ";
var anEvent = [CPEvent mouseEventWithType:CPRightMouseDown location:location modifierFlags:0 timestamp:[[CPApp currentEvent] timestamp] windowNumber:[[self window] windowNumber] context:nil eventNumber:1 clickCount:1 pressure:0];
[self selectAll:nil];
[CPMenu popUpContextMenu:_searchMenu withEvent:anEvent forView:self];
[CPMenu popUpContextMenu:_searchMenu withEvent:anEvent forView:sender];
}
- (void)_sendPartialString
{
[super sendAction:[self action] to:[self target]];
[_partialStringTimer invalidate];
[[self target] performSelector:[self action] withObject:self];
}
- (void)_searchFieldCancel:(id)sender
@@ -693,15 +593,14 @@ var RECENT_SEARCH_PREFIX = @" ";
- (void)_searchFieldSearch:(id)sender
{
var searchString = [[sender title] substringFromIndex:[RECENT_SEARCH_PREFIX length]];
var searchString = [sender title];
if ([sender tag] != CPSearchFieldRecentsMenuItemTag)
[self _addStringToRecentSearches:searchString];
[self setObjectValue:searchString];
[self _sendPartialString];
[self selectAll:nil];
[self _updateCancelButtonVisibility];
}
@@ -709,8 +608,6 @@ var RECENT_SEARCH_PREFIX = @" ";
{
[self setRecentSearches:[CPArray array]];
[self _updateSearchMenu];
[self setStringValue:@""];
[self _updateCancelButtonVisibility];
}
- (void)_registerForAutosaveNotification
@@ -771,7 +668,7 @@ var CPRecentsAutosaveNameKey = @"CPRecentsAutosaveNameKey",
CPSendsWholeSearchStringKey = @"CPSendsWholeSearchStringKey",
CPSendsSearchStringImmediatelyKey = @"CPSendsSearchStringImmediatelyKey",
CPMaximumRecentsKey = @"CPMaximumRecentsKey",
CPSearchMenuTemplateKey = @"CPSearchMenuTemplateKey";
CPSearchMenuTemplateKey = @"CPSearchMenuTemplateKey";
@implementation CPSearchField (CPCoding)
@@ -793,7 +690,6 @@ var CPRecentsAutosaveNameKey = @"CPRecentsAutosaveNameKey",
if (_recentsAutosaveName)
[coder encodeObject:_recentsAutosaveName forKey:CPRecentsAutosaveNameKey];
if (_searchMenuTemplate)
[coder encodeObject:_searchMenuTemplate forKey:CPSearchMenuTemplateKey];
}
@@ -802,17 +698,18 @@ var CPRecentsAutosaveNameKey = @"CPRecentsAutosaveNameKey",
{
if (self = [super initWithCoder:coder])
{
[self _initWithFrame:[self frame]];
_recentsAutosaveName = [coder decodeObjectForKey:CPRecentsAutosaveNameKey];
_sendsWholeSearchString = [coder decodeBoolForKey:CPSendsWholeSearchStringKey];
_sendsSearchStringImmediately = [coder decodeBoolForKey:CPSendsSearchStringImmediatelyKey];
_maximumRecents = [coder decodeIntForKey:CPMaximumRecentsKey];
var template = [coder decodeObjectForKey:CPSearchMenuTemplateKey];
if (template)
[self setSearchMenuTemplate:template];
[self _init];
[self setDelegate:self];
}
return self;
-1
View File
@@ -1,7 +1,6 @@
@import "CPTextField.j"
/*!
@ingroup appkit
*/
+133 -132
View File
@@ -24,12 +24,13 @@
@import "CPControl.j"
#include "CoreGraphics/CGGeometry.h"
CPSegmentSwitchTrackingSelectOne = 0;
CPSegmentSwitchTrackingSelectAny = 1;
CPSegmentSwitchTrackingMomentary = 2;
/*!
/*!
@ingroup appkit
@class CPSegmentedControl
@@ -48,7 +49,7 @@ CPSegmentSwitchTrackingMomentary = 2;
BOOL _trackingHighlighted;
}
+ (CPString)defaultThemeClass
+ (CPString)themeClass
{
return "segmented-control";
}
@@ -63,16 +64,16 @@ CPSegmentSwitchTrackingMomentary = 2;
{
_segments = [];
_themeStates = [];
self = [super initWithFrame:aRect];
if (self)
{
_selectedSegment = -1;
_trackingMode = CPSegmentSwitchTrackingSelectOne;
}
return self;
}
@@ -81,7 +82,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (int)selectedTag
{
return [_segments[_selectedSegment] tag];
return _segments[_selectedSegment].tag;
}
// Specifying the number of segments
@@ -93,11 +94,11 @@ CPSegmentSwitchTrackingMomentary = 2;
{
if (_segments.length == aCount)
return;
var height = CGRectGetHeight([self bounds]);
if (_segments.length < aCount)
{
{
for (var index = _segments.length; index < aCount; ++index)
{
_segments[index] = [[_CPSegmentItem alloc] init];
@@ -150,15 +151,15 @@ CPSegmentSwitchTrackingMomentary = 2;
- (BOOL)selectSegmentWithTag:(int)aTag
{
var index = 0;
for (; index < _segments.length; ++index)
if (_segments[index].tag == aTag)
{
[self setSelectedSegment:index];
return YES;
}
return NO;
}
@@ -173,28 +174,28 @@ CPSegmentSwitchTrackingMomentary = 2;
{
if (_trackingMode == aTrackingMode)
return;
_trackingMode = aTrackingMode;
if (_trackingMode == CPSegmentSwitchTrackingSelectOne)
{
var index = 0,
selected = NO;
for (; index < _segments.length; ++index)
if ([_segments[index] selected])
if (_segments[index].selected)
if (selected)
[self setSelected:NO forSegment:index];
else
selected = YES;
}
else if (_trackingMode == CPSegmentSwitchTrackingMomentary)
{
var index = 0;
for (; index < _segments.length; ++index)
if ([_segments[index] selected])
if (_segments[index].selected)
[self setSelected:NO forSegment:index];
}
}
@@ -216,8 +217,8 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (void)setWidth:(float)aWidth forSegment:(unsigned)aSegment
{
[_segments[aSegment] setWidth:aWidth];
_segments[aSegment].width = aWidth;
[self tileWithChangedSegment:aSegment];
}
@@ -228,7 +229,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (float)widthForSegment:(unsigned)aSegment
{
return [_segments[aSegment] width];
return _segments[aSegment].width;
}
/*!
@@ -239,7 +240,9 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (void)setImage:(CPImage)anImage forSegment:(unsigned)aSegment
{
[_segments[aSegment] setImage:anImage];
var segment = _segments[aSegment];
segment.image = anImage;
[self tileWithChangedSegment:aSegment];
}
@@ -251,7 +254,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (CPImage)imageForSegment:(unsigned)aSegment
{
return [_segments[aSegment] image];
return _segments[aSegment].image;
}
/*!
@@ -262,8 +265,10 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (void)setLabel:(CPString)aLabel forSegment:(unsigned)aSegment
{
[_segments[aSegment] setLabel:aLabel];
var segment = _segments[aSegment];
_segments[aSegment].label = aLabel;
[self tileWithChangedSegment:aSegment];
}
@@ -274,7 +279,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (CPString)labelForSegment:(unsigned)aSegment
{
return [_segments[aSegment] label];
return _segments[aSegment].label;
}
/*!
@@ -285,7 +290,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (void)setMenu:(CPMenu)aMenu forSegment:(unsigned)aSegment
{
[_segments[aSegment] setMenu:aMenu];
_segments[aSegment].menu = aMenu;
}
/*!
@@ -295,7 +300,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (CPMenu)menuForSegment:(unsigned)aSegment
{
return [_segments[aSegment] menu];
return _segments[aSegment].menu;
}
/*!
@@ -308,12 +313,12 @@ CPSegmentSwitchTrackingMomentary = 2;
- (void)setSelected:(BOOL)isSelected forSegment:(unsigned)aSegment
{
var segment = _segments[aSegment];
// If we're already in this state, bail.
if ([segment selected] == isSelected)
if (segment.selected == isSelected)
return;
[segment setSelected:isSelected];
segment.selected = isSelected;
_themeStates[aSegment] = isSelected ? CPThemeStateSelected : CPThemeStateNormal;
@@ -321,18 +326,18 @@ CPSegmentSwitchTrackingMomentary = 2;
if (isSelected)
{
var oldSelectedSegment = _selectedSegment;
_selectedSegment = aSegment;
if (_trackingMode == CPSegmentSwitchTrackingSelectOne && oldSelectedSegment != aSegment && oldSelectedSegment != -1)
{
[_segments[oldSelectedSegment] setSelected:NO];
_segments[oldSelectedSegment].selected = NO;
_themeStates[oldSelectedSegment] = CPThemeStateNormal;
[self drawSegmentBezel:oldSelectedSegment highlight:NO];
}
}
if (_trackingMode != CPSegmentSwitchTrackingMomentary)
[self drawSegmentBezel:aSegment highlight:NO];
@@ -347,7 +352,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (BOOL)isSelectedForSegment:(unsigned)aSegment
{
return [_segments[aSegment] selected];
return _segments[aSegment].selected;
}
/*!
@@ -358,8 +363,6 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (void)setEnabled:(BOOL)isEnabled forSegment:(unsigned)aSegment
{
[_segments[aSegment] setEnabled:isEnabled];
if (isEnabled)
_themeStates[aSegment] &= ~CPThemeStateDisabled;
else
@@ -376,7 +379,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (BOOL)isEnabledForSegment:(unsigned)aSegment
{
return [_segments[aSegment] enabled];
return !(_themeStates[aSegment] & CPThemeStateDisabled)
}
/*!
@@ -386,7 +389,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (void)setTag:(int)aTag forSegment:(unsigned)aSegment
{
[_segments[aSegment] setTag:aTag];
_segments[aSegment].tag = aTag;
}
/*!
@@ -395,7 +398,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (int)tagForSegment:(unsigned)aSegment
{
return [_segments[aSegment] tag];
return _segments[aSegment].tag;
}
// Drawings
@@ -458,7 +461,7 @@ CPSegmentSwitchTrackingMomentary = 2;
else if (aName.indexOf("segment-bezel") === 0)
{
var segment = parseInt(aName.substring("segment-bezel-".length), 10),
frame = CGRectCreateCopy([_segments[segment] frame]);
frame = CGRectCreateCopy(_segments[segment].frame);
if (segment === 0)
{
@@ -492,7 +495,7 @@ CPSegmentSwitchTrackingMomentary = 2;
- (CPView)createEphemeralSubviewNamed:(CPString)aName
{
if ([aName hasPrefix:@"segment-content"])
if (aName.substring(0, "segment-content".length) == "segment-content")
return [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
return [[CPView alloc] initWithFrame:_CGRectMakeZero()];
@@ -507,10 +510,10 @@ CPSegmentSwitchTrackingMomentary = 2;
themeState |= _themeState & CPThemeStateDisabled;
var leftCapColor = [self valueForThemeAttribute:@"left-segment-bezel-color"
inState:themeState],
var leftCapColor = [self valueForThemeAttribute:@"left-segment-bezel-color"
inState:themeState];
leftBezelView = [self layoutEphemeralSubviewNamed:@"left-segment-bezel"
var leftBezelView = [self layoutEphemeralSubviewNamed:@"left-segment-bezel"
positioned:CPWindowBelow
relativeToEphemeralSubviewNamed:nil];
@@ -520,39 +523,41 @@ CPSegmentSwitchTrackingMomentary = 2;
themeState |= _themeState & CPThemeStateDisabled;
var rightCapColor = [self valueForThemeAttribute:@"right-segment-bezel-color"
inState:themeState],
var rightCapColor = [self valueForThemeAttribute:@"right-segment-bezel-color"
inState:themeState];
rightBezelView = [self layoutEphemeralSubviewNamed:@"right-segment-bezel"
var rightBezelView = [self layoutEphemeralSubviewNamed:@"right-segment-bezel"
positioned:CPWindowBelow
relativeToEphemeralSubviewNamed:nil];
[rightBezelView setBackgroundColor:rightCapColor];
for (var i = 0, count = _themeStates.length; i < count; i++)
for (var i=0, count = _themeStates.length; i<count; i++)
{
var themeState = _themeStates[i];
themeState |= _themeState & CPThemeStateDisabled;
var bezelColor = [self valueForThemeAttribute:@"center-segment-bezel-color"
inState:themeState],
var bezelColor = [self valueForThemeAttribute:@"center-segment-bezel-color"
inState:themeState];
bezelView = [self layoutEphemeralSubviewNamed:"segment-bezel-" + i
positioned:CPWindowBelow
var bezelView = [self layoutEphemeralSubviewNamed:"segment-bezel-"+i
positioned:CPWindowBelow
relativeToEphemeralSubviewNamed:nil];
[bezelView setBackgroundColor:bezelColor];
// layout image/title views
var segment = _segments[i],
contentView = [self layoutEphemeralSubviewNamed:@"segment-content-" + i
positioned:CPWindowAbove
relativeToEphemeralSubviewNamed:@"segment-bezel-" + i];
//layout image/title views
var segment = _segments[i];
[contentView setText:[segment label]];
[contentView setImage:[segment image]];
var contentView = [self layoutEphemeralSubviewNamed:@"segment-content-"+i
positioned:CPWindowAbove
relativeToEphemeralSubviewNamed:@"segment-bezel-"+i];
[contentView setText:segment.label];
[contentView setImage:segment.image];
[contentView setFont:[self valueForThemeAttribute:@"font" inState:themeState]];
[contentView setTextColor:[self valueForThemeAttribute:@"text-color" inState:themeState]];
@@ -561,27 +566,27 @@ CPSegmentSwitchTrackingMomentary = 2;
[contentView setLineBreakMode:[self valueForThemeAttribute:@"line-break-mode" inState:themeState]];
[contentView setTextShadowColor:[self valueForThemeAttribute:@"text-shadow-color" inState:themeState]];
[contentView setTextShadowOffset:[self valueForThemeAttribute:@"text-shadow-offset" inState:themeState]];
[contentView setImageScaling:[self valueForThemeAttribute:@"image-scaling" inState:themeState]];
if ([segment image] && [segment label])
[contentView setImageScaling:[self valueForThemeAttribute:@"image-scaling" inState:themeState]];
if (segment.image && segment.label)
[contentView setImagePosition:[self valueForThemeAttribute:@"image-position" inState:themeState]];
else if ([segment image])
else if (segment.image)
[contentView setImagePosition:CPImageOnly];
if (i == count - 1)
continue;
var borderState = _themeStates[i] | _themeStates[i + 1];
var borderState = _themeStates[i] | _themeStates[i+1];
borderState = (borderState & CPThemeStateSelected & ~CPThemeStateHighlighted) ? CPThemeStateSelected : CPThemeStateNormal;
borderState |= _themeState & CPThemeStateDisabled;
var borderColor = [self valueForThemeAttribute:@"divider-bezel-color"
inState:borderState],
inState:borderState];
borderView = [self layoutEphemeralSubviewNamed:"divider-bezel-" + i
positioned:CPWindowBelow
var borderView = [self layoutEphemeralSubviewNamed:"divider-bezel-"+i
positioned:CPWindowBelow
relativeToEphemeralSubviewNamed:nil];
[borderView setBackgroundColor:borderColor];
@@ -604,53 +609,48 @@ CPSegmentSwitchTrackingMomentary = 2;
return;
var segment = _segments[aSegment],
segmentWidth = [segment width],
segmentWidth = segment.width,
themeState = _themeStates[aSegment] | (_themeState & CPThemeStateDisabled),
contentInset = [self valueForThemeAttribute:@"content-inset" inState:themeState],
font = [self valueForThemeAttribute:@"font" inState:themeState];
if (!segmentWidth)
{
if ([segment image] && [segment label])
segmentWidth = [[segment label] sizeWithFont:font].width + [[segment image] size].width + contentInset.left + contentInset.right;
if (segment.image && segment.label)
segmentWidth = [segment.label sizeWithFont:font].width + [segment.image size].width + contentInset.left + contentInset.right;
else if (segment.image)
segmentWidth = [[segment image] size].width + contentInset.left + contentInset.right;
segmentWidth = [segment.image size].width + contentInset.left + contentInset.right;
else if (segment.label)
segmentWidth = [[segment label] sizeWithFont:font].width + contentInset.left + contentInset.right;
segmentWidth = [segment.label sizeWithFont:font].width + contentInset.left + contentInset.right;
else
segmentWidth = 0.0;
}
var delta = segmentWidth - CGRectGetWidth([segment frame]);
var delta = segmentWidth - CGRectGetWidth(segment.frame);
if (!delta)
{
[self setNeedsLayout];
[self setNeedsDisplay:YES];
return;
}
// Update control size
// Update Contorl Size
var frame = [self frame];
[self setFrameSize:CGSizeMake(CGRectGetWidth(frame) + delta, CGRectGetHeight(frame))];
// Update segment width
[segment setWidth:segmentWidth];
[segment setFrame:[self frameForSegment:aSegment]];
// Update Segment Width
segment.width = segmentWidth;
segment.frame = [self frameForSegment:aSegment];;
// Update following segments widths
// Update Following Segments Widths
var index = aSegment + 1;
for (; index < _segments.length; ++index)
{
[_segments[index] frame].origin.x += delta;
_segments[index].frame.origin.x += delta;
[self drawSegmentBezel:index highlight:NO];
[self drawSegment:index highlight:NO];
}
[self drawSegmentBezel:aSegment highlight:NO];
[self drawSegment:aSegment highlight:NO];
@@ -696,14 +696,14 @@ CPSegmentSwitchTrackingMomentary = 2;
{
var location = [self convertPoint:aPoint fromView:nil],
count = _segments.length;
while (count--)
if (CGRectContainsPoint([_segments[count] frame], aPoint))
if (CGRectContainsPoint(_segments[count].frame, aPoint))
return count;
if (_segments.length)
{
var adjustedLastFrame = CGRectCreateCopy([_segments[_segments.length - 1] frame]);
var adjustedLastFrame = CGRectCreateCopy(_segments[_segments.length - 1].frame);
adjustedLastFrame.size.width = CGRectGetWidth([self bounds]) - adjustedLastFrame.origin.x;
if (CGRectContainsPoint(adjustedLastFrame, aPoint))
@@ -717,7 +717,7 @@ CPSegmentSwitchTrackingMomentary = 2;
{
if (![self isEnabled])
return;
[self trackSegment:anEvent];
}
@@ -731,10 +731,10 @@ CPSegmentSwitchTrackingMomentary = 2;
@param anEvent the event to handle
*/
- (void)trackSegment:(CPEvent)anEvent
{
{
var type = [anEvent type],
location = [self convertPoint:[anEvent locationInWindow] fromView:nil];
if (type == CPLeftMouseUp)
{
if (_trackingSegment == -1)
@@ -745,30 +745,30 @@ CPSegmentSwitchTrackingMomentary = 2;
if (_trackingMode == CPSegmentSwitchTrackingSelectAny)
{
[self setSelected:![self isSelectedForSegment:_trackingSegment] forSegment:_trackingSegment];
// With ANY, _selectedSegment means last pressed.
_selectedSegment = _trackingSegment;
}
else
[self setSelected:YES forSegment:_trackingSegment];
[self sendAction:[self action] to:[self target]];
if (_trackingMode == CPSegmentSwitchTrackingMomentary)
{
[self setSelected:NO forSegment:_trackingSegment];
_selectedSegment = -1;
}
}
[self drawSegmentBezel:_trackingSegment highlight:NO];
_trackingSegment = -1;
return;
}
if (type == CPLeftMouseDown)
{
var trackingSegment = [self testSegment:location];
@@ -779,7 +779,7 @@ CPSegmentSwitchTrackingMomentary = 2;
[self drawSegmentBezel:_trackingSegment highlight:YES];
}
}
else if (type == CPLeftMouseDragged)
{
if (_trackingSegment == -1)
@@ -793,14 +793,14 @@ CPSegmentSwitchTrackingMomentary = 2;
[self drawSegmentBezel:_trackingSegment highlight:_trackingHighlighted];
}
}
[CPApp setTarget:self selector:@selector(trackSegment:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
}
- (void)setFont:(CPFont)aFont
{
[super setFont:aFont];
[self tileWithChangedSegment:0];
}
@@ -816,12 +816,12 @@ var CPSegmentedControlSegmentsKey = "CPSegmentedControlSegmentsKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
var frame = [self frame],
originalWidth = frame.size.width;
frame.size.width = 0;
[self setFrame:frame];
@@ -832,38 +832,38 @@ var CPSegmentedControlSegmentsKey = "CPSegmentedControlSegmentsKey",
if ([aCoder containsValueForKey:CPSegmentedControlSelectedKey])
_selectedSegment = [aCoder decodeIntForKey:CPSegmentedControlSelectedKey];
else
else
_selectedSegment = -1;
if ([aCoder containsValueForKey:CPSegmentedControlTrackingModeKey])
_trackingMode = [aCoder decodeIntForKey:CPSegmentedControlTrackingModeKey];
else
_trackingMode = CPSegmentSwitchTrackingSelectOne;
// HACK
for (var i = 0; i < _segments.length; i++)
{
_themeStates[i] = [_segments[i] selected] ? CPThemeStateSelected : CPThemeStateNormal;
_themeStates[i] = _segments[i].selected ? CPThemeStateSelected : CPThemeStateNormal;
[self tileWithChangedSegment:i];
}
var difference = MAX(originalWidth - [self frame].size.width, 0.0),
remainingWidth = FLOOR(difference / _segments.length);
for (var i = 0; i < _segments.length; i++)
[self setWidth:[_segments[i] width] + remainingWidth forSegment:i];
for (var i=0; i < _segments.length; i++)
[self setWidth:_segments[i].width + remainingWidth forSegment:i];
[self tileWithChangedSegment:0];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_segments forKey:CPSegmentedControlSegmentsKey];
[aCoder encodeInt:_selectedSegment forKey:CPSegmentedControlSelectedKey];
[aCoder encodeInt:_segmentStyle forKey:CPSegmentedControlSegmentStyleKey];
@@ -875,15 +875,15 @@ var CPSegmentedControlSegmentsKey = "CPSegmentedControlSegmentsKey",
@implementation _CPSegmentItem : CPObject
{
CPImage image @accessors;
CPString label @accessors;
CPMenu menu @accessors;
BOOL selected @accessors;
BOOL enabled @accessors;
int tag @accessors;
int width @accessors;
CPImage image;
CPString label;
CPMenu menu;
BOOL selected;
BOOL enabled;
int tag;
int width;
CGRect frame @accessors;
CGRect frame;
}
- (id)init
@@ -894,8 +894,8 @@ var CPSegmentedControlSegmentsKey = "CPSegmentedControlSegmentsKey",
label = @"";
menu = nil;
selected = NO;
enabled = YES;
tag = -1;
enabled = NO;
tag = 0;
width = 0;
frame = CGRectMakeZero();
@@ -918,7 +918,7 @@ var CPSegmentItemImageKey = "CPSegmentItemImageKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
image = [aCoder decodeObjectForKey:CPSegmentItemImageKey];
@@ -931,7 +931,7 @@ var CPSegmentItemImageKey = "CPSegmentItemImageKey",
frame = CGRectMakeZero();
}
return self;
}
@@ -947,3 +947,4 @@ var CPSegmentItemImageKey = "CPSegmentItemImageKey",
}
@end
+18 -41
View File
@@ -28,17 +28,19 @@
@import "CPView.j"
#include "CoreGraphics/CGGeometry.h"
CPLightShadow = 0;
CPHeavyShadow = 1;
var CPShadowViewLightBackgroundColor = nil,
CPShadowViewHeavyBackgroundColor = nil;
var LIGHT_LEFT_INSET = 3.0,
LIGHT_RIGHT_INSET = 3.0,
LIGHT_TOP_INSET = 3.0,
LIGHT_BOTTOM_INSET = 5.0,
HEAVY_LEFT_INSET = 7.0,
HEAVY_RIGHT_INSET = 7.0,
HEAVY_TOP_INSET = 5.0,
@@ -59,76 +61,51 @@ var LIGHT_LEFT_INSET = 3.0,
return;
var bundle = [CPBundle bundleForClass:[self class]];
CPShadowViewLightBackgroundColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightTopLeft.png"] size:CGSizeMake(9.0, 9.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightTop.png"] size:CGSizeMake(1.0, 9.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightTopRight.png"] size:CGSizeMake(9.0, 9.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightLeft.png"] size:CGSizeMake(9.0, 1.0)],
nil,
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightRight.png"] size:CGSizeMake(9.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightBottomLeft.png"] size:CGSizeMake(9.0, 9.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightBottom.png"] size:CGSizeMake(1.0, 9.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightBottomRight.png"] size:CGSizeMake(9.0, 9.0)]
]]];
CPShadowViewHeavyBackgroundColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyTopLeft.png"] size:CGSizeMake(17.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyTop.png"] size:CGSizeMake(1.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyTopRight.png"] size:CGSizeMake(17.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyLeft.png"] size:CGSizeMake(17.0, 1.0)],
nil,
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyRight.png"] size:CGSizeMake(17.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyBottomLeft.png"] size:CGSizeMake(17.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyBottom.png"] size:CGSizeMake(1.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyBottomRight.png"] size:CGSizeMake(17.0, 17.0)]
]]];
}
+ (id)shadowViewEnclosingView:(CPView)aView
{
return [self shadowViewEnclosingView:aView withWeight:CPLightShadow];
}
+ (id)shadowViewEnclosingView:(CPView)aView withWeight:(CPShadowWeight)aWeight
{
var shadowView = [[CPShadowView alloc] initWithFrame:[aView frame]];
[shadowView setWeight:aWeight];
var size = [shadowView frame].size,
width = size.width - [shadowView leftInset] - [shadowView rightInset],
height = size.height - [shadowView topInset] - [shadowView bottomInset],
enclosingView = [aView superview];
[shadowView setHitTests:[aView hitTests]];
[shadowView setAutoresizingMask:[aView autoresizingMask]];
[aView removeFromSuperview];
[shadowView addSubview:aView];
[aView setFrame:CGRectMake([shadowView leftInset], [shadowView topInset], width, height)]
[enclosingView addSubview:shadowView];
return shadowView;
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_weight = CPLightShadow;
[self setBackgroundColor:CPShadowViewLightBackgroundColor];
[self setHitTests:NO];
}
return self;
}
@@ -136,9 +113,9 @@ var LIGHT_LEFT_INSET = 3.0,
{
if (_weight == aWeight)
return;
_weight = aWeight;
if (_weight == CPLightShadow)
[self setBackgroundColor:CPShadowViewLightBackgroundColor];
@@ -170,7 +147,7 @@ var LIGHT_LEFT_INSET = 3.0,
{
if (_weight == CPLightShadow)
return LIGHT_LEFT_INSET + LIGHT_RIGHT_INSET;
return HEAVY_LEFT_INSET + HEAVY_RIGHT_INSET;
}
@@ -178,7 +155,7 @@ var LIGHT_LEFT_INSET = 3.0,
{
if (_weight == CPLightShadow)
return LIGHT_TOP_INSET + LIGHT_BOTTOM_INSET;
return HEAVY_TOP_INSET + HEAVY_BOTTOM_INSET;
}
+40 -38
View File
@@ -22,6 +22,7 @@
@import "CPControl.j"
#include "CoreGraphics/CGGeometry.h"
/*! SLIDER STATES */
@@ -41,7 +42,7 @@ CPCircularSlider = 1;
BOOL _isVertical;
}
+ (CPString)defaultThemeClass
+ (CPString)themeClass
{
return "slider";
}
@@ -60,14 +61,14 @@ CPCircularSlider = 1;
{
_minValue = 0.0;
_maxValue = 100.0;
[self setObjectValue:50.0];
[self setContinuous:YES];
[self _recalculateIsVertical];
}
return self;
}
@@ -75,11 +76,11 @@ CPCircularSlider = 1;
{
if (_minValue === aMinimumValue)
return;
_minValue = aMinimumValue;
var doubleValue = [self doubleValue];
if (doubleValue < _minValue)
[self setDoubleValue:_minValue];
@@ -97,11 +98,11 @@ CPCircularSlider = 1;
{
if (_maxValue === aMaximumValue)
return;
_maxValue = aMaximumValue;
var doubleValue = [self doubleValue];
if (doubleValue > _maxValue)
[self setDoubleValue:_maxValue];
@@ -168,27 +169,27 @@ CPCircularSlider = 1;
bounds.size.height = trackWidth;
}
}
return bounds;
}
- (CGRect)knobRectForBounds:(CGRect)bounds
{
var knobSize = [self currentValueForThemeAttribute:@"knob-size"];
if (knobSize.width <= 0 || knobSize.height <= 0)
return _CGRectMakeZero();
var knobRect = _CGRectMake(0.0, 0.0, knobSize.width, knobSize.height),
trackRect = [self trackRectForBounds:bounds];
// No track, do our best to approximate a place for this thing.
if (!trackRect || _CGRectIsEmpty(trackRect))
trackRect = bounds;
if ([self hasThemeState:CPThemeStateCircular])
{
var angle = 3 * PI_2 - (1.0 - [self doubleValue] - _minValue) / (_maxValue - _minValue) * PI2,
var angle = 3*PI_2 - (1.0 - [self doubleValue] - _minValue) / (_maxValue - _minValue) * PI2,
radius = CGRectGetWidth(trackRect) / 2.0 - 8.0;
knobRect.origin.x = radius * COS(angle) + CGRectGetMidX(trackRect) - 3.0;
@@ -197,7 +198,7 @@ CPCircularSlider = 1;
else if ([self isVertical])
{
knobRect.origin.x = _CGRectGetMidX(trackRect) - knobSize.width / 2.0;
knobRect.origin.y = ((_maxValue - [self doubleValue]) / (_maxValue - _minValue)) * (_CGRectGetHeight(trackRect) - knobSize.height);
knobRect.origin.y = (([self doubleValue] - _minValue) / (_maxValue - _minValue)) * (_CGRectGetHeight(trackRect) - knobSize.height);
}
else
{
@@ -212,10 +213,10 @@ CPCircularSlider = 1;
{
if (aName === "track-view")
return [self trackRectForBounds:[self bounds]];
else if (aName === "knob-view")
return [self knobRectForBounds:[self bounds]];
return [super rectForEphemeralSubviewNamed:aName];
}
@@ -224,12 +225,12 @@ CPCircularSlider = 1;
if (aName === "track-view" || aName === "knob-view")
{
var view = [[CPView alloc] init];
[view setHitTests:NO];
return view;
}
return [super createEphemeralSubviewNamed:aName];
}
@@ -255,7 +256,7 @@ CPCircularSlider = 1;
var bounds = [self bounds],
width = _CGRectGetWidth(bounds),
height = _CGRectGetHeight(bounds);
_isVertical = width < height ? 1 : (width > height ? 0 : -1);
if (_isVertical === 1)
@@ -281,7 +282,7 @@ CPCircularSlider = 1;
var knobView = [self layoutEphemeralSubviewNamed:@"knob-view"
positioned:CPWindowAbove
relativeToEphemeralSubviewNamed:@"track-view"];
if (knobView)
[knobView setBackgroundColor:[self currentValueForThemeAttribute:"knob-color"]];
}
@@ -319,7 +320,7 @@ CPCircularSlider = 1;
var minValue = [self minValue];
return MAX(0.0, MIN(1.0, (_CGRectGetMaxY(trackRect) - aPoint.y) / _CGRectGetHeight(trackRect))) * ([self maxValue] - minValue) + minValue;
return MAX(0.0, MIN(1.0, (aPoint.y - _CGRectGetMinY(trackRect)) / _CGRectGetHeight(trackRect))) * ([self maxValue] - minValue) + minValue;
}
else
{
@@ -338,43 +339,44 @@ CPCircularSlider = 1;
{
var bounds = [self bounds],
knobRect = [self knobRectForBounds:_CGRectMakeCopy(bounds)];
if (_CGRectContainsPoint(knobRect, aPoint))
_dragOffset = _CGSizeMake(_CGRectGetMidX(knobRect) - aPoint.x, _CGRectGetMidY(knobRect) - aPoint.y);
else
else
{
var trackRect = [self trackRectForBounds:bounds];
if (trackRect && _CGRectContainsPoint(trackRect, aPoint))
{
_dragOffset = _CGSizeMakeZero();
[self setObjectValue:[self _valueAtPoint:aPoint]];
}
else
return NO;
}
[self setHighlighted:YES];
[self setNeedsLayout];
[self setNeedsDisplay:YES];
return YES;
return YES;
}
- (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint
{
[self setObjectValue:[self _valueAtPoint:_CGPointMake(aPoint.x + _dragOffset.width, aPoint.y + _dragOffset.height)]];
return YES;
}
- (void)stopTracking:(CGPoint)lastPoint at:(CGPoint)aPoint mouseIsUp:(BOOL)mouseIsUp
{
[self setHighlighted:NO];
if ([_target respondsToSelector:@selector(sliderDidFinish:)])
[_target sliderDidFinish:self];
@@ -390,7 +392,7 @@ CPCircularSlider = 1;
{
if (flag)
_sendActionOn |= CPLeftMouseDraggedMask;
else
else
_sendActionOn &= ~CPLeftMouseDraggedMask;
}
@@ -452,14 +454,14 @@ var CPSliderMinValueKey = "CPSliderMinValueKey",
- (id)value
{
CPLog.warn("[CPSlider value] is deprecated, use doubleValue or objectValue instead.");
return [self doubleValue];
return [self doubleValue];
}
- (void)setValue:(id)aValue
{
CPLog.warn("[CPSlider setValue:] is deprecated, use setDoubleValue: or setObjectValue: instead.");
[self setObjectValue:aValue];
}
+167 -103
View File
@@ -20,10 +20,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPView.j"
@import "CPColorPicker.j"
/*
@ignore
*/
@@ -47,15 +45,16 @@
CPTextField _saturationLabel;
CPTextField _brightnessLabel;
CPTextField _hexLabel;
CPTextField _hexValue;
CPTextField _hexValue;
CPTextField _redValue;
CPTextField _greenValue;
CPTextField _blueValue;
CPTextField _hueValue;
CPTextField _saturationValue;
CPTextField _brightnessValue;
#if PLATFORM(DOM)
DOMElement _redValue;
DOMElement _greenValue;
DOMElement _blueValue;
DOMElement _hueValue;
DOMElement _saturationValue;
DOMElement _brightnessValue;
DOMElement _hexValue;
#endif
}
- (id)initWithPickerMask:(int)mask colorPanel:(CPColorPanel)owningColorPanel
@@ -85,13 +84,73 @@
[_redSlider setAction: @selector(sliderChanged:)];
[_redSlider setAutoresizingMask: CPViewWidthSizable];
// red value input box
_redValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 30, 45, 29)];
[_redValue setAutoresizingMask: CPViewMinXMargin];
[_redValue setEditable: YES];
[_redValue setBezeled: YES];
[_redValue setDelegate: self];
[_contentView addSubview: _redValue];
#if PLATFORM(DOM)
var updateFunction = function(aDOMEvent)
{
if(isNaN(this.value))
return;
switch(this)
{
case _redValue: [_redSlider setFloatValue:MAX(MIN(ROUND(this.value), 255) / 255.0, 0)];
//[self sliderChanged: _redSlider];
break;
case _greenValue: [_greenSlider setFloatValue:MAX(MIN(ROUND(this.value), 255) / 255.0, 0)];
//[self sliderChanged: _greenSlider];
break;
case _blueValue: [_blueSlider setFloatValue:MAX(MIN(ROUND(this.value), 255) / 255.0, 0)];
//[self sliderChanged: _blueSlider];
break;
case _hueValue: [_hueSlider setFloatValue:MAX(MIN(ROUND(this.value), 360), 0)];
//[self sliderChanged: _hueSlider];
break;
case _saturationValue: [_saturationSlider setFloatValue:MAX(MIN(ROUND(this.value), 100), 0)];
//[self sliderChanged: _saturationSlider];
break;
case _brightnessValue: [_brightnessSlider setFloatValue:MAX(MIN(ROUND(this.value), 100), 0)];
//[self sliderChanged: _brightnessSlider];
break;
}
this.blur();
};
var keypressFunction = function(aDOMEvent)
{
aDOMEvent = aDOMEvent || window.event;
if (aDOMEvent.keyCode == 13)
{
updateFunction(aDOMEvent);
if(aDOMEvent.preventDefault)
aDOMEvent.preventDefault();
else if(aDOMEvent.stopPropagation)
aDOMEvent.stopPropagation();
}
}
//red value input box
var redValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 35, 45, 20)];
[redValue setAutoresizingMask: CPViewMinXMargin];
_redValue = document.createElement("input");
_redValue.style.width = "40px";
_redValue.style.backgroundColor = "transparent";
_redValue.style.border = "1px solid black";
_redValue.style.color = "black";
_redValue.style.position = "absolute";
_redValue.style.top = "0px";
_redValue.style.left = "0px";
_redValue.onchange = updateFunction;
redValue._DOMElement.appendChild(_redValue);
[_contentView addSubview: redValue];
#endif
_greenLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 58, 15, 20)];
[_greenLabel setStringValue: "G"];
@@ -104,13 +163,17 @@
[_greenSlider setAction: @selector(sliderChanged:)];
[_greenSlider setAutoresizingMask: CPViewWidthSizable];
// green value input box
_greenValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 53, 45, 29)];
[_greenValue setAutoresizingMask: CPViewMinXMargin];
[_greenValue setEditable: YES];
[_greenValue setBezeled: YES];
[_greenValue setDelegate: self];
[_contentView addSubview: _greenValue];
#if PLATFORM(DOM)
//green value input box
var greenValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 58, 45, 20)];
[greenValue setAutoresizingMask: CPViewMinXMargin];
_greenValue = _redValue.cloneNode(false);
_greenValue.onchange = updateFunction;
greenValue._DOMElement.appendChild(_greenValue);
[_contentView addSubview: greenValue];
#endif
_blueLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 81, 15, 20)];
[_blueLabel setStringValue: "B"];
@@ -123,14 +186,17 @@
[_blueSlider setAction: @selector(sliderChanged:)];
[_blueSlider setAutoresizingMask: CPViewWidthSizable];
// blue value input box
_blueValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 76, 45, 29)];
[_blueValue setAutoresizingMask: CPViewMinXMargin];
[_blueValue setEditable: YES];
[_blueValue setBezeled: YES];
[_blueValue setDelegate: self];
[_contentView addSubview: _blueValue];
#if PLATFORM(DOM)
//blue value input box
var blueValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 81, 45, 20)];
[blueValue setAutoresizingMask: CPViewMinXMargin];
_blueValue = _redValue.cloneNode(false);
_blueValue.onchange = updateFunction;
blueValue._DOMElement.appendChild(_blueValue);
[_contentView addSubview: blueValue];
#endif
_hsbLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 120, 190, 20)];
[_hsbLabel setStringValue: "Hue, Saturation, Brightness"];
[_hsbLabel setTextColor:[CPColor blackColor]];
@@ -146,14 +212,17 @@
[_hueSlider setAction: @selector(sliderChanged:)];
[_hueSlider setAutoresizingMask: CPViewWidthSizable];
// hue value input box
_hueValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 140, 45, 29)];
[_hueValue setAutoresizingMask: CPViewMinXMargin];
[_hueValue setEditable: YES];
[_hueValue setBezeled: YES];
[_hueValue setDelegate: self];
[_contentView addSubview: _hueValue];
#if PLATFORM(DOM)
//red value input box
var hueValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 145, 45, 20)];
[hueValue setAutoresizingMask: CPViewMinXMargin];
_hueValue = _redValue.cloneNode(false);
_hueValue.onchange = updateFunction;
hueValue._DOMElement.appendChild(_hueValue);
[_contentView addSubview: hueValue];
#endif
_saturationLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 168, 15, 20)];
[_saturationLabel setStringValue: "S"];
[_saturationLabel setTextColor:[CPColor blackColor]];
@@ -165,14 +234,17 @@
[_saturationSlider setAction: @selector(sliderChanged:)];
[_saturationSlider setAutoresizingMask: CPViewWidthSizable];
// saturation value input box
_saturationValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 163, 45, 29)];
[_saturationValue setAutoresizingMask: CPViewMinXMargin];
[_saturationValue setEditable: YES];
[_saturationValue setBezeled: YES];
[_saturationValue setDelegate: self];
[_contentView addSubview: _saturationValue];
#if PLATFORM(DOM)
//green value input box
var saturationValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 168, 45, 20)];
[saturationValue setAutoresizingMask: CPViewMinXMargin];
_saturationValue = _redValue.cloneNode(false);
_saturationValue.onchange = updateFunction;
saturationValue._DOMElement.appendChild(_saturationValue);
[_contentView addSubview: saturationValue];
#endif
_brightnessLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 191, 15, 20)];
[_brightnessLabel setStringValue: "B"];
[_brightnessLabel setTextColor:[CPColor blackColor]];
@@ -184,24 +256,51 @@
[_brightnessSlider setAction: @selector(sliderChanged:)];
[_brightnessSlider setAutoresizingMask: CPViewWidthSizable];
// brightness value input box
_brightnessValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 186, 45, 29)];
[_brightnessValue setAutoresizingMask: CPViewMinXMargin];
[_brightnessValue setEditable: YES];
[_brightnessValue setBezeled: YES];
[_brightnessValue setDelegate: self];
[_contentView addSubview: _brightnessValue];
#if PLATFORM(DOM)
//blue value input box
var brightnessValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 191, 45, 20)];
[brightnessValue setAutoresizingMask: CPViewMinXMargin];
_brightnessValue = _redValue.cloneNode(false);
_brightnessValue.onchange = updateFunction;
brightnessValue._DOMElement.appendChild(_brightnessValue);
[_contentView addSubview: brightnessValue];
#endif
_hexLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 230, 30, 20)];
[_hexLabel setStringValue: "Hex"];
[_hexLabel setTextColor:[CPColor blackColor]];
#if PLATFORM(DOM)
//hex input box
_hexValue = [[CPTextField alloc] initWithFrame: CGRectMake(32, 225, 80, 29)];
[_hexValue setEditable: YES];
[_hexValue setBezeled: YES];
[_hexValue setDelegate: self];
[_contentView addSubview: _hexValue];
_hexValue = _redValue.cloneNode(false);
_hexValue.style.top = "228px";
_hexValue.style.width = "80px";
_hexValue.style.left = "35px";
_hexValue.onkeypress = function(aDOMEvent)
{
aDOMEvent = aDOMEvent || window.event;
if (aDOMEvent.keyCode == 13)
{
var newColor = [CPColor colorWithHexString: this.value];
if(newColor)
{
[self setColor: newColor];
[[self colorPanel] setColor: newColor];
}
if(aDOMEvent.preventDefault)
aDOMEvent.preventDefault();
else if(aDOMEvent.stopPropagation)
aDOMEvent.stopPropagation();
this.blur();
}
};
_contentView._DOMElement.appendChild(_hexValue);
#endif
[_contentView addSubview: _rgbLabel];
[_contentView addSubview: _redLabel];
@@ -293,7 +392,9 @@
- (void)updateHex:(CPColor)aColor
{
[_hexValue setStringValue:[aColor hexString]];
#if PLATFORM(DOM)
_hexValue.value = [aColor hexString];
#endif
}
- (void)updateRGBSliders:(CPColor)aColor
@@ -307,13 +408,15 @@
- (void)updateLabels
{
[_hueValue setStringValue: ROUND([_hueSlider floatValue])];
[_saturationValue setStringValue: ROUND([_saturationSlider floatValue])];
[_brightnessValue setStringValue: ROUND([_brightnessSlider floatValue])];
#if PLATFORM(DOM)
_hueValue.value = ROUND([_hueSlider floatValue]);
_saturationValue.value = ROUND([_saturationSlider floatValue]);
_brightnessValue.value = ROUND([_brightnessSlider floatValue]);
[_redValue setStringValue: ROUND([_redSlider floatValue] * 255)];
[_greenValue setStringValue: ROUND([_greenSlider floatValue] * 255)];
[_blueValue setStringValue: ROUND([_blueSlider floatValue] * 255)];
_redValue.value = ROUND([_redSlider floatValue] * 255);
_greenValue.value = ROUND([_greenSlider floatValue] * 255);
_blueValue.value = ROUND([_blueSlider floatValue] * 255);
#endif
}
- (CPImage)provideNewButtonImage
@@ -326,43 +429,4 @@
return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:CPColorPicker] pathForResource:"slider_button_h.png"] size:CGSizeMake(32, 32)];
}
- (void)controlTextDidEndEditing:(CPNotification)aNotification
{
var field = [aNotification object],
value = [[field stringValue] stringByTrimmingWhitespace];
if (field === _hexValue) {
var newColor = [CPColor colorWithHexString: value];
if (newColor) {
[self setColor: newColor];
[[self colorPanel] setColor: newColor];
}
} else {
switch(field) {
case _redValue: [_redSlider setFloatValue:MAX(MIN(ROUND(value), 255) / 255.0, 0)];
[self sliderChanged: _redSlider];
break;
case _greenValue: [_greenSlider setFloatValue:MAX(MIN(ROUND(value), 255) / 255.0, 0)];
[self sliderChanged: _greenSlider];
break;
case _blueValue: [_blueSlider setFloatValue:MAX(MIN(ROUND(value), 255) / 255.0, 0)];
[self sliderChanged: _blueSlider];
break;
case _hueValue: [_hueSlider setFloatValue:MAX(MIN(ROUND(value), 360), 0)];
[self sliderChanged: _hueSlider];
break;
case _saturationValue: [_saturationSlider setFloatValue:MAX(MIN(ROUND(value), 100), 0)];
[self sliderChanged: _saturationSlider];
break;
case _brightnessValue: [_brightnessSlider setFloatValue:MAX(MIN(ROUND(value), 100), 0)];
[self sliderChanged: _brightnessSlider];
break;
}
}
}
@end
+30 -53
View File
@@ -24,6 +24,10 @@
@import "CPImage.j"
@import "CPView.j"
#include "CoreGraphics/CGGeometry.h"
#include "Platform/Platform.h"
#include "Platform/DOM/CPDOMDisplayServer.h"
CPSplitViewDidResizeSubviewsNotification = @"CPSplitViewDidResizeSubviewsNotification";
CPSplitViewWillResizeSubviewsNotification = @"CPSplitViewWillResizeSubviewsNotification";
@@ -43,7 +47,6 @@ var CPSplitViewHorizontalImage = nil,
int _currentDivider;
float _initialOffset;
float _preCollapsePosition;
CPString _originComponent;
CPString _sizeComponent;
@@ -57,17 +60,6 @@ var CPSplitViewHorizontalImage = nil,
CPArray _buttonBars;
}
+ (CPString)defaultThemeClass
{
return @"splitview";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[10.0, 1.0, [CPColor grayColor]]
forKeys:[@"divider-thickness", @"pane-divider-thickness", @"pane-divider-color"]];
}
/*
@ignore
*/
@@ -98,7 +90,7 @@ var CPSplitViewHorizontalImage = nil,
- (float)dividerThickness
{
return [self currentValueForThemeAttribute:[self isPaneSplitter] ? @"pane-divider-thickness" : @"divider-thickness"];
return _isPaneSplitter ? 1.0 : 10.0;
}
- (BOOL)isVertical
@@ -159,8 +151,8 @@ var CPSplitViewHorizontalImage = nil,
_isPaneSplitter = shouldBePaneSplitter;
if (_DOMDividerElements[_drawingDivider])
[self _setupDOMDivider];
if(_DOMDividerElements[_drawingDivider])
[self _setupDOMDivider]
// The divider changes size when pane splitter mode is toggled, so the
// subviews need to change size too.
@@ -193,8 +185,9 @@ var CPSplitViewHorizontalImage = nil,
- (CGRect)effectiveRectOfDividerAtIndex:(int)aDivider
{
var realRect = [self rectOfDividerAtIndex:aDivider],
padding = 2;
var realRect = [self rectOfDividerAtIndex:aDivider];
var padding = 2;
realRect.size[_sizeComponent] += padding * 2;
realRect.origin[_originComponent] -= padding;
@@ -236,7 +229,7 @@ var CPSplitViewHorizontalImage = nil,
{
if (_isPaneSplitter)
{
_DOMDividerElements[_drawingDivider].style.backgroundColor = [[self currentValueForThemeAttribute:@"pane-divider-color"] cssString];
_DOMDividerElements[_drawingDivider].style.backgroundColor = "#A5A5A5";
_DOMDividerElements[_drawingDivider].style.backgroundImage = "";
}
else
@@ -300,7 +293,7 @@ var CPSplitViewHorizontalImage = nil,
if ([_delegate respondsToSelector:@selector(splitView:additionalEffectiveRectOfDividerAtIndex:)])
additionalRect = [_delegate splitView:self additionalEffectiveRectOfDividerAtIndex:anIndex];
return CGRectContainsPoint(effectiveRect, aPoint) ||
return CGRectContainsPoint(effectiveRect, aPoint) ||
(additionalRect && CGRectContainsPoint(additionalRect, aPoint)) ||
(buttonBarRect && CGRectContainsPoint(buttonBarRect, aPoint));
}
@@ -310,9 +303,9 @@ var CPSplitViewHorizontalImage = nil,
if ([self isHidden] || ![self hitTests] || !CGRectContainsPoint([self frame], aPoint))
return nil;
var point = [self convertPoint:aPoint fromView:[self superview]],
count = [_subviews count] - 1;
var point = [self convertPoint:aPoint fromView:[self superview]];
var count = [_subviews count] - 1;
for (var i = 0; i < count; i++)
{
if ([self cursorAtPoint:point hitDividerAtIndex:i])
@@ -365,14 +358,14 @@ var CPSplitViewHorizontalImage = nil,
if ([_delegate splitView:self canCollapseSubview:_subviews[i]] && [_delegate splitView:self shouldCollapseSubview:_subviews[i] forDoubleClickOnDividerAtIndex:i])
{
if ([self isSubviewCollapsed:_subviews[i]])
[self setPosition:_preCollapsePosition ? _preCollapsePosition : (minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i];
[self setPosition:(minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i];
else
[self setPosition:minPosition ofDividerAtIndex:i];
}
else if ([_delegate splitView:self canCollapseSubview:_subviews[i + 1]] && [_delegate splitView:self shouldCollapseSubview:_subviews[i + 1] forDoubleClickOnDividerAtIndex:i])
else if ([_delegate splitView:self canCollapseSubview:_subviews[i+1]] && [_delegate splitView:self shouldCollapseSubview:_subviews[i+1] forDoubleClickOnDividerAtIndex:i])
{
if ([self isSubviewCollapsed:_subviews[i + 1]])
[self setPosition:_preCollapsePosition ? _preCollapsePosition : (minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i];
if ([self isSubviewCollapsed:_subviews[i+1]])
[self setPosition:(minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i];
else
[self setPosition:maxPosition ofDividerAtIndex:i];
}
@@ -451,19 +444,11 @@ var CPSplitViewHorizontalImage = nil,
if (_currentDivider === i || (_currentDivider == CPNotFound && [self cursorAtPoint:point hitDividerAtIndex:i]))
{
var frame = [_subviews[i] frame],
size = frame.size[_sizeComponent],
startPosition = frame.origin[_originComponent] + size,
canShrink = [self _realPositionForPosition:startPosition - 1 ofDividerAtIndex:i] < startPosition,
canGrow = [self _realPositionForPosition:startPosition + 1 ofDividerAtIndex:i] > startPosition,
startPosition = frame.origin[_originComponent] + frame.size[_sizeComponent],
canShrink = [self _realPositionForPosition:startPosition-1 ofDividerAtIndex:i] < startPosition,
canGrow = [self _realPositionForPosition:startPosition+1 ofDividerAtIndex:i] > startPosition,
cursor = [CPCursor arrowCursor];
if (size === 0)
canGrow = YES; // Subview is collapsed.
else if (!canShrink &&
[_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] &&
[_delegate splitView:self canCollapseSubview:_subviews[i]])
canShrink = YES; // Subview is collapsible.
if (_isVertical && canShrink && canGrow)
cursor = [CPCursor resizeLeftRightCursor];
else if (_isVertical && canShrink)
@@ -518,10 +503,10 @@ var CPSplitViewHorizontalImage = nil,
actualMax = proposedMax,
actualMin = proposedMin;
if ([_delegate respondsToSelector:@selector(splitView:constrainMinCoordinate:ofSubviewAt:)])
if([_delegate respondsToSelector:@selector(splitView:constrainMinCoordinate:ofSubviewAt:)])
actualMin = [_delegate splitView:self constrainMinCoordinate:proposedMin ofSubviewAt:dividerIndex];
if ([_delegate respondsToSelector:@selector(splitView:constrainMaxCoordinate:ofSubviewAt:)])
if([_delegate respondsToSelector:@selector(splitView:constrainMaxCoordinate:ofSubviewAt:)])
actualMax = [_delegate splitView:self constrainMaxCoordinate:proposedMax ofSubviewAt:dividerIndex];
var viewA = _subviews[dividerIndex],
@@ -546,18 +531,10 @@ var CPSplitViewHorizontalImage = nil,
viewB = _subviews[dividerIndex + 1],
frameB = [viewB frame];
_preCollapsePosition = 0;
var preSize = frameA.size[_sizeComponent];
frameA.size[_sizeComponent] = realPosition - frameA.origin[_originComponent];
if (preSize !== 0 && frameA.size[_sizeComponent] === 0)
_preCollapsePosition = preSize;
[_subviews[dividerIndex] setFrame:frameA];
preSize = frameB.size[_sizeComponent];
frameB.size[_sizeComponent] = frameB.origin[_originComponent] + frameB.size[_sizeComponent] - realPosition - [self dividerThickness];
if (preSize !== 0 && frameB.size[_sizeComponent] === 0)
_preCollapsePosition = preSize;
frameB.origin[_originComponent] = realPosition + [self dividerThickness];
[_subviews[dividerIndex + 1] setFrame:frameB];
@@ -612,8 +589,8 @@ var CPSplitViewHorizontalImage = nil,
var nonSizableSpace = totalSizableSpace ? bounds.size[_sizeComponent] - totalSizableSpace : 0,
remainingFlexibleSpace = bounds.size[_sizeComponent] - oldSize[_sizeComponent],
oldDimension = (oldSize[_sizeComponent] - totalDividers * dividerThickness - nonSizableSpace),
ratio = oldDimension <= 0 ? 0 : (bounds.size[_sizeComponent] - totalDividers * dividerThickness - nonSizableSpace) / oldDimension;
oldDimension = (oldSize[_sizeComponent]- totalDividers*dividerThickness - nonSizableSpace),
ratio = oldDimension <= 0 ? 0 : (bounds.size[_sizeComponent] - totalDividers*dividerThickness - nonSizableSpace) / oldDimension;
for (index = 0; index < count; ++index)
{
@@ -664,14 +641,14 @@ var CPSplitViewHorizontalImage = nil,
/*!
Set the button bar who's resize control should act as a control for this splitview.
Each divider can have at most one button bar assigned to it, and that button bar must be
Each divider can have at most one button bar assigned to it, and that button bar must be
a subview of one of the split view's subviews.
Calling this method with nil as the button bar will remove any currently assigned button bar
for the divider at that index. Indexes will not be adjusted as new subviews are added, so you
should usually call this method after adding all the desired subviews to the split view.
This method will automatically configure the hasResizeControl and resizeControlIsLeftAligned
This method will automatically configure the hasResizeControl and resizeControlIsLeftAligned
parameters of the button bar, and will override any currently set values.
*/
- (void)setButtonBar:(CPButtonBar)aButtonBar forDividerAtIndex:(unsigned)dividerIndex
@@ -692,7 +669,7 @@ var CPSplitViewHorizontalImage = nil,
}
if (view !== self)
[CPException raise:CPInvalidArgumentException
[CPException raise:CPInvalidArgumentException
reason:@"CPSplitView button bar must be a subview of the split view."];
var viewIndex = [[self subviews] indexOfObject:subview];
@@ -700,7 +677,7 @@ var CPSplitViewHorizontalImage = nil,
[aButtonBar setHasResizeControl:YES];
[aButtonBar setResizeControlIsLeftAligned:dividerIndex < viewIndex];
_buttonBars[dividerIndex] = aButtonBar;
_buttonBars[dividerIndex] = aButtonBar;
}
- (void)_postNotificationWillResize
@@ -737,7 +714,7 @@ var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
_DOMDividerElements = [];
_buttonBars = [aCoder decodeObjectForKey:CPSplitViewButtonBarsKey] || [];
_delegate = [aCoder decodeObjectForKey:CPSplitViewDelegateKey];
_isPaneSplitter = [aCoder decodeBoolForKey:CPSplitViewIsPaneSplitterKey];
+1 -25
View File
@@ -25,20 +25,8 @@
@import "CPPlatformString.j"
var CPStringSizeWithFontInWidthCache = {};
CPStringSizeCachingEnabled = YES;
@implementation CPString (CPStringDrawing)
/*!
Returns a dictionary with the items "ascender", "descender", "lineHeight"
*/
+ (CPDictionary)metricsOfFont:(CPFont)aFont
{
return [CPPlatformString metricsOfFont:aFont];
}
/*!
Returns the string
*/
@@ -54,19 +42,7 @@ CPStringSizeCachingEnabled = YES;
- (CGSize)sizeWithFont:(CPFont)aFont inWidth:(float)aWidth
{
if (!CPStringSizeCachingEnabled)
return [CPPlatformString sizeOfString:self withFont:aFont forWidth:aWidth];
var cacheKey = self + [aFont cssString] + aWidth,
size = CPStringSizeWithFontInWidthCache[cacheKey];
if (size === undefined)
{
size = [CPPlatformString sizeOfString:self withFont:aFont forWidth:aWidth];
CPStringSizeWithFontInWidthCache[cacheKey] = size;
}
return CGSizeMakeCopy(size);
return [CPPlatformString sizeOfString:self withFont:aFont forWidth:aWidth];
}
@end
+553 -202
View File
@@ -1,8 +1,32 @@
@import "CPBox.j"
@import "CPSegmentedControl.j"
/*
* CPTabView.j
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2008, 280 North, Inc.
*
* 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 "CPImageView.j"
@import "CPTabViewItem.j"
@import "CPView.j"
#include "CoreGraphics/CGGeometry.h"
/*
Places tabs on top with a bezeled border.
@global
@@ -10,7 +34,7 @@
*/
CPTopTabsBezelBorder = 0;
//CPLeftTabsBezelBorder = 1;
CPBottomTabsBezelBorder = 2;
//CPBottomTabsBezelBorder = 2;
//CPRightTabsBezelBorder = 3;
/*
Displays no tabs and has a bezeled border.
@@ -31,55 +55,173 @@ CPNoTabsLineBorder = 5;
*/
CPNoTabsNoBorder = 6;
var CPTabViewBezelBorderLeftImage = nil,
CPTabViewBackgroundCenterImage = nil,
CPTabViewBezelBorderRightImage = nil,
CPTabViewBezelBorderColor = nil,
CPTabViewBezelBorderBackgroundColor = nil;
var LEFT_INSET = 7.0,
RIGHT_INSET = 7.0;
var CPTabViewDidSelectTabViewItemSelector = 1,
CPTabViewShouldSelectTabViewItemSelector = 2,
CPTabViewWillSelectTabViewItemSelector = 4,
CPTabViewDidChangeNumberOfTabViewItemsSelector = 8;
var HEIGHT_OF_SEGMENTED_CONTROL = 24;
/*!
@ingroup appkit
@class CPTabView
This class represents a view that has multiple subviews (CPTabViewItem) presented as individual tabs.
Only one CPTabViewItem is shown at a time, and other CPTabViewItems can be made visible
(one at a time) by clicking on the CPTabViewItem's tab at the top of the tab view.
THe currently selected CPTabViewItem is the view that is displayed.
*/
@implementation CPTabView : CPView
{
CPArray items;
CPView _labelsView;
CPView _backgroundView;
CPView _separatorView;
CPView _auxiliaryView;
CPView _contentView;
CPArray _tabViewItems;
CPTabViewItem _selectedTabViewItem;
CPSegmentedControl tabs;
CPBox box;
CPTabViewType _tabViewType;
id _delegate;
unsigned _delegateSelectors;
}
CPNumber selectedIndex;
/*
@ignore
*/
+ (void)initialize
{
if (self != CPTabView)
return;
var bundle = [CPBundle bundleForClass:self],
emptyImage = [[CPImage alloc] initByReferencingFile:@"" size:CGSizeMake(7.0, 0.0)],
backgroundImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/CPTabViewBezelBackgroundCenter.png"] size:CGSizeMake(1.0, 1.0)],
bezelBorderLeftImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/CPTabViewBezelBorderLeft.png"] size:CGSizeMake(7.0, 1.0)],
bezerBorderImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/CPTabViewBezelBorder.png"] size:CGSizeMake(1.0, 1.0)],
bezelBorderRightImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/CPTabViewBezelBorderRight.png"] size:CGSizeMake(7.0, 1.0)];
CPTabViewBezelBorderBackgroundColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:
[
emptyImage,
emptyImage,
emptyImage,
CPTabViewType type;
bezelBorderLeftImage,
backgroundImage,
bezelBorderRightImage,
id delegate;
unsigned delegateSelectors;
bezelBorderLeftImage,
bezerBorderImage,
bezelBorderRightImage
]]];
CPTabViewBezelBorderColor = [CPColor colorWithPatternImage:bezerBorderImage];
}
/*
@ignore
*/
+ (CPColor)bezelBorderColor
{
return CPTabViewBezelBorderColor;
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
items = [CPArray array];
tabs = [[CPSegmentedControl alloc] initWithFrame:CGRectMake(0, 0, 0, HEIGHT_OF_SEGMENTED_CONTROL)];
[tabs setHitTests:NO];
box = [[CPBox alloc] initWithFrame:CGRectMake(0, HEIGHT_OF_SEGMENTED_CONTROL / 2, CGRectGetWidth(aFrame),
CGRectGetHeight(aFrame) - HEIGHT_OF_SEGMENTED_CONTROL)];
selectedIndex = CPNotFound;
[self setTabViewType:CPTopTabsBezelBorder];
[self setBackgroundColor:[CPColor colorWithCalibratedWhite:0.95 alpha:1.0]];
[self addSubview:box];
[self addSubview:tabs];
[box setAutoresizingMask:CPViewWidthSizable];
[tabs setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin];
_tabViewType = CPTopTabsBezelBorder;
_tabViewItems = [];
}
return self;
}
- (void)viewDidMoveToWindow
{
if (_tabViewType != CPTopTabsBezelBorder || _labelsView)
return;
[self _createBezelBorder];
[self layoutSubviews];
}
/* @ignore */
- (void)_createBezelBorder
{
var bounds = [self bounds];
_labelsView = [[_CPTabLabelsView alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(bounds), 0.0)];
[_labelsView setTabView:self];
[_labelsView setAutoresizingMask:CPViewWidthSizable];
[self addSubview:_labelsView];
_backgroundView = [[CPView alloc] initWithFrame:CGRectMakeZero()];
[_backgroundView setBackgroundColor:CPTabViewBezelBorderBackgroundColor];
[_backgroundView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[self addSubview:_backgroundView];
_separatorView = [[CPView alloc] initWithFrame:CGRectMakeZero()];
[_separatorView setBackgroundColor:[[self class] bezelBorderColor]];
[_separatorView setAutoresizingMask:CPViewWidthSizable | CPViewMaxYMargin];
[self addSubview:_separatorView];
}
/*
Lays out the subviews
@ignore
*/
- (void)layoutSubviews
{
if (_tabViewType == CPTopTabsBezelBorder)
{
var backgroundRect = [self bounds],
labelsViewHeight = [_CPTabLabelsView height];
backgroundRect.origin.y += labelsViewHeight;
backgroundRect.size.height -= labelsViewHeight;
[_backgroundView setFrame:backgroundRect];
var auxiliaryViewHeight = 5.0;
if (_auxiliaryView)
{
auxiliaryViewHeight = CGRectGetHeight([_auxiliaryView frame]);
[_auxiliaryView setFrame:CGRectMake(LEFT_INSET, labelsViewHeight, CGRectGetWidth(backgroundRect) - LEFT_INSET - RIGHT_INSET, auxiliaryViewHeight)];
}
[_separatorView setFrame:CGRectMake(LEFT_INSET, labelsViewHeight + auxiliaryViewHeight, CGRectGetWidth(backgroundRect) - LEFT_INSET - RIGHT_INSET, 1.0)];
}
// CPNoTabsNoBorder
[_contentView setFrame:[self contentRect]];
}
// Adding and Removing Tabs
/*!
Adds a CPTabViewItem to the tab view.
@@ -87,7 +229,7 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (void)addTabViewItem:(CPTabViewItem)aTabViewItem
{
[self insertTabViewItem:aTabViewItem atIndex:[items count]];
[self insertTabViewItem:aTabViewItem atIndex:[_tabViewItems count]];
}
/*!
@@ -98,13 +240,20 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (void)insertTabViewItem:(CPTabViewItem)aTabViewItem atIndex:(unsigned)anIndex
{
[items insertObject:aTabViewItem atIndex:anIndex];
if (!_labelsView && _tabViewType == CPTopTabsBezelBorder)
[self _createBezelBorder];
[_tabViewItems insertObject:aTabViewItem atIndex:anIndex];
[_labelsView tabView:self didAddTabViewItem:aTabViewItem];
[aTabViewItem _setTabView:self];
if ([_tabViewItems count] == 1)
[self selectFirstTabViewItem:self];
[self _updateItems];
[self _repositionTabs];
if (delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
[delegate tabViewDidChangeNumberOfTabViewItems:self];
if (_delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
[_delegate tabViewDidChangeNumberOfTabViewItems:self];
}
/*!
@@ -113,19 +262,16 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (void)removeTabViewItem:(CPTabViewItem)aTabViewItem
{
for (var i = 0; i < [items count]; i++)
{
if ([items objectAtIndex:i] === aTabViewItem)
{
[items removeObjectAtIndex:i];
}
}
var index = [self indexOfTabViewItem:aTabViewItem];
[self _updateItems];
[self _repositionTabs];
if (delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
[delegate tabViewDidChangeNumberOfTabViewItems:self];
[_tabViewItems removeObjectIdenticalTo:aTabViewItem];
[_labelsView tabView:self didRemoveTabViewItemAtIndex:index];
[aTabViewItem _setTabView:nil];
if (_delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
[_delegate tabViewDidChangeNumberOfTabViewItems:self];
}
// Accessing Tabs
@@ -135,7 +281,7 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (int)indexOfTabViewItem:(CPTabViewItem)aTabViewItem
{
return [items indexOfObjectIdenticalTo:aTabViewItem];
return [_tabViewItems indexOfObjectIdenticalTo:aTabViewItem];
}
/*!
@@ -144,11 +290,14 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (int)indexOfTabViewItemWithIdentifier:(CPString)anIdentifier
{
for (var index = [items count]; index >= 0; index--)
if ([[items[index] identifier] isEqual:anIdentifier])
var index = 0,
count = [_tabViewItems count];
for (; index < count; ++index)
if ([[_tabViewItems[index] identifier] isEqual:anIdentifier])
return index;
return CPNotFound;
return index;
}
/*!
@@ -156,7 +305,7 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (unsigned)numberOfTabViewItems
{
return [items count];
return [_tabViewItems count];
}
/*!
@@ -164,7 +313,7 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (CPTabViewItem)tabViewItemAtIndex:(unsigned)anIndex
{
return [items objectAtIndex:anIndex];
return _tabViewItems[anIndex];
}
/*!
@@ -172,7 +321,7 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (CPArray)tabViewItems
{
return [items copy]; // Copy?
return _tabViewItems;
}
// Selecting a Tab
@@ -182,10 +331,10 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (void)selectFirstTabViewItem:(id)aSender
{
if ([items count] === 0)
return; // throw?
[self selectTabViewItemAtIndex:0];
var count = [_tabViewItems count];
if (count)
[self selectTabViewItemAtIndex:0];
}
/*!
@@ -194,10 +343,10 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (void)selectLastTabViewItem:(id)aSender
{
if ([items count] === 0)
return; // throw?
[self selectTabViewItemAtIndex:[items count] - 1];
var count = [_tabViewItems count];
if (count)
[self selectTabViewItemAtIndex:count - 1];
}
/*!
@@ -206,16 +355,13 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (void)selectNextTabViewItem:(id)aSender
{
if (selectedIndex === CPNotFound)
if (!_selectedTabViewItem)
return;
var nextIndex = selectedIndex + 1;
if (nextIndex === [items count])
// does nothing. According to spec at (http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Reference/ApplicationKit/Classes/NSTabView_Class/Reference/Reference.html#//apple_ref/occ/instm/NSTabView/selectNextTabViewItem:)
return;
[self selectTabViewItemAtIndex:nextIndex];
var index = [self indexOfTabViewItem:_selectedTabViewItem],
count = [_tabViewItems count];
[self selectTabViewItemAtIndex:index + 1 % count];
}
/*!
@@ -224,15 +370,13 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (void)selectPreviousTabViewItem:(id)aSender
{
if (selectedIndex === CPNotFound)
if (!_selectedTabViewItem)
return;
var previousIndex = selectedIndex - 1;
if (previousIndex < 0)
return; // does nothing. See above.
[self selectTabViewItemAtIndex:previousIndex];
var index = [self indexOfTabViewItem:_selectedTabViewItem],
count = [_tabViewItems count];
[self selectTabViewItemAtIndex:index == 0 ? count : index - 1];
}
/*!
@@ -241,7 +385,41 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (void)selectTabViewItem:(CPTabViewItem)aTabViewItem
{
[self selectTabViewItemAtIndex:[self indexOfTabViewItem:aTabViewItem]];
if ((_delegateSelectors & CPTabViewShouldSelectTabViewItemSelector) && ![_delegate tabView:self shouldSelectTabViewItem:aTabViewItem])
return;
if (_delegateSelectors & CPTabViewWillSelectTabViewItemSelector)
[_delegate tabView:self willSelectTabViewItem:aTabViewItem];
if (_selectedTabViewItem)
{
_selectedTabViewItem._tabState = CPBackgroundTab;
[_labelsView tabView:self didChangeStateOfTabViewItem:_selectedTabViewItem];
[_contentView removeFromSuperview];
[_auxiliaryView removeFromSuperview];
}
_selectedTabViewItem = aTabViewItem;
_selectedTabViewItem._tabState = CPSelectedTab;
_contentView = [_selectedTabViewItem view];
[_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
_auxiliaryView = [_selectedTabViewItem auxiliaryView];
[_auxiliaryView setAutoresizingMask:CPViewWidthSizable];
[self addSubview:_contentView];
if (_auxiliaryView)
[self addSubview:_auxiliaryView];
[_labelsView tabView:self didChangeStateOfTabViewItem:_selectedTabViewItem];
[self layoutSubviews];
if (_delegateSelectors & CPTabViewDidSelectTabViewItemSelector)
[_delegate tabView:self didSelectTabViewItem:aTabViewItem];
}
/*!
@@ -250,24 +428,7 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (void)selectTabViewItemAtIndex:(unsigned)anIndex
{
var aTabViewItem = [items objectAtIndex:anIndex];
if (anIndex === selectedIndex)
return;
var aTabViewItem = [self tabViewItemAtIndex:anIndex];
if ((delegateSelectors & CPTabViewShouldSelectTabViewItemSelector) && ![delegate tabView:self shouldSelectTabViewItem:aTabViewItem])
return;
if (delegateSelectors & CPTabViewWillSelectTabViewItemSelector)
[delegate tabView:self willSelectTabViewItem:aTabViewItem];
[tabs selectSegmentWithTag:anIndex];
[self _setSelectedIndex:anIndex];
if (delegateSelectors & CPTabViewDidSelectTabViewItemSelector)
[delegate tabView:self didSelectTabViewItem:aTabViewItem];
[self selectTabViewItem:_tabViewItems[anIndex]];
}
/*!
@@ -275,43 +436,32 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (CPTabViewItem)selectedTabViewItem
{
return [items objectAtIndex:selectedIndex];
return _selectedTabViewItem;
}
//
//
/*!
Sets the tab view type.
@param aTabViewType the view type
*/
- (void)setTabViewType:(CPTabViewType)aTabViewType
{
if (type === aTabViewType)
if (_tabViewType == aTabViewType)
return;
if ((type === CPTopTabsBezelBorder || type === CPBottomTabsBezelBorder)
&& (aTabViewType !== CPTopTabsBezelBorder && aTabViewType !== CPBottomTabsBezelBorder))
[tabs removeFromSuperview];
if ((type === CPNoTabsBezelBorder || type === CPNoTabsLineBorder || type === CPNoTabsNoBorder)
&& (aTabViewType !== CPNoTabsBezelBorder && aTabViewType !== CPNoTabsBezelBorder && aTabViewType !== CPNoTabsNoBorder))
[self addSubview:tabs];
type = aTabViewType;
switch (type)
{
case CPTopTabsBezelBorder:
case CPBottomTabsBezelBorder:
case CPNoTabsBezelBorder:
[box setBorderType:CPBezelBorder];
break;
case CPNoTabsLineBorder:
[box setBorderType:CPLineBorder];
break;
case CPNoTabsNoBorder:
[box setBorderType:CPNoBorder];
break;
}
_tabViewType = aTabViewType;
if (_tabViewType == CPNoTabsBezelBorder || _tabViewType == CPNoTabsLineBorder || _tabViewType == CPNoTabsNoBorder)
[_labelsView removeFromSuperview];
else if (![_labelsView superview])
[self addSubview:_labelsView];
if (_tabViewType == CPNoTabsLineBorder || _tabViewType == CPNoTabsNoBorder)
[_backgroundView removeFromSuperview];
else if (![_backgroundView superview])
[self addSubview:_backgroundView];
[self layoutSubviews];
}
/*!
@@ -319,7 +469,31 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (CPTabViewType)tabViewType
{
return type;
return _tabViewType;
}
// Determining the Size
/*!
Returns the content rectangle.
*/
- (CGRect)contentRect
{
var contentRect = CGRectMakeCopy([self bounds]);
if (_tabViewType == CPTopTabsBezelBorder)
{
var labelsViewHeight = [_CPTabLabelsView height],
auxiliaryViewHeight = _auxiliaryView ? CGRectGetHeight([_auxiliaryView frame]) : 5.0,
separatorViewHeight = 1.0;
contentRect.origin.y += labelsViewHeight + auxiliaryViewHeight + separatorViewHeight;
contentRect.size.height -= labelsViewHeight + auxiliaryViewHeight + separatorViewHeight * 2.0; // 2 for the bottom border as well.
contentRect.origin.x += LEFT_INSET;
contentRect.size.width -= LEFT_INSET + RIGHT_INSET;
}
return contentRect;
}
/*!
@@ -327,7 +501,7 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (id)delegate
{
return delegate;
return _delegate;
}
/*!
@@ -336,74 +510,35 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/
- (void)setDelegate:(id)aDelegate
{
if (delegate == aDelegate)
if (_delegate == aDelegate)
return;
_delegate = aDelegate;
_delegateSelectors = 0;
delegate = aDelegate;
if ([_delegate respondsToSelector:@selector(tabView:shouldSelectTabViewItem:)])
_delegateSelectors |= CPTabViewShouldSelectTabViewItemSelector;
delegateSelectors = 0;
if ([_delegate respondsToSelector:@selector(tabView:willSelectTabViewItem:)])
_delegateSelectors |= CPTabViewWillSelectTabViewItemSelector;
if ([delegate respondsToSelector:@selector(tabView:shouldSelectTabViewItem:)])
delegateSelectors |= CPTabViewShouldSelectTabViewItemSelector;
if ([_delegate respondsToSelector:@selector(tabView:didSelectTabViewItem:)])
_delegateSelectors |= CPTabViewDidSelectTabViewItemSelector;
if ([delegate respondsToSelector:@selector(tabView:willSelectTabViewItem:)])
delegateSelectors |= CPTabViewWillSelectTabViewItemSelector;
if ([delegate respondsToSelector:@selector(tabView:didSelectTabViewItem:)])
delegateSelectors |= CPTabViewDidSelectTabViewItemSelector;
if ([delegate respondsToSelector:@selector(tabViewDidChangeNumberOfTabViewItems:)])
delegateSelectors |= CPTabViewDidChangeNumberOfTabViewItemsSelector;
if ([_delegate respondsToSelector:@selector(tabViewDidChangeNumberOfTabViewItems:)])
_delegateSelectors |= CPTabViewDidChangeNumberOfTabViewItemsSelector;
}
- (void)setBackgroundColor:(CPColor)aColor
{
[box setBackgroundColor:aColor];
}
//
- (void)mouseDown:(CPEvent)anEvent
{
var segmentIndex = [tabs testSegment:[tabs convertPoint:[anEvent locationInWindow] fromView:nil]];
if (segmentIndex != CPNotFound)
{
[self selectTabViewItemAtIndex:segmentIndex];
[tabs trackSegment:anEvent];
}
}
- (void)_repositionTabs
{
var horizontalCenterOfSelf = CGRectGetWidth([self bounds]) / 2,
verticalCenterOfTabs = CGRectGetHeight([tabs bounds]) / 2;
if (type === CPBottomTabsBezelBorder)
[tabs setCenter:CGPointMake(horizontalCenterOfSelf, CGRectGetHeight([self bounds]) - verticalCenterOfTabs)];
else
[tabs setCenter:CGPointMake(horizontalCenterOfSelf, verticalCenterOfTabs)];
}
- (void)_setSelectedIndex:(CPNumber)index
{
selectedIndex = index;
[box setContentView:[[items objectAtIndex:selectedIndex] view]];
}
- (void)_updateItems
{
[tabs setSegmentCount:[items count]];
for (var i = 0; i < [items count]; i++)
{
[tabs setLabel:[[items objectAtIndex:i] label] forSegment:i];
[tabs setTag:i forSegment:i];
}
if (selectedIndex === CPNotFound)
{
[self selectFirstTabViewItem:self];
}
var location = [_labelsView convertPoint:[anEvent locationInWindow] fromView:nil],
tabViewItem = [_labelsView representedTabViewItemAtPoint:location];
if (tabViewItem)
[self selectTabViewItem:tabViewItem];
}
@end
@@ -419,17 +554,20 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
{
if (self = [super initWithCoder:aCoder])
{
type = [aCoder decodeIntForKey:CPTabViewTypeKey];
items = [];
var encodedItems = [aCoder decodeObjectForKey:CPTabViewItemsKey];
for (var i = 0; encodedItems && i < encodedItems.length; i++)
[self insertTabViewItem:encodedItems[i] atIndex:i];
_tabViewType = [aCoder decodeIntForKey:CPTabViewTypeKey];
_tabViewItems = [];
// FIXME: this is somewhat hacky
[self _createBezelBorder];
var items = [aCoder decodeObjectForKey:CPTabViewItemsKey];
for (var i = 0; items && i < items.length; i++)
[self insertTabViewItem:items[i] atIndex:i];
var selected = [aCoder decodeObjectForKey:CPTabViewSelectedItemKey];
if (selected)
[self selectTabViewItem:selected];
[self setDelegate:[aCoder decodeObjectForKey:CPTabViewDelegateKey]];
}
@@ -438,14 +576,227 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
- (void)encodeWithCoder:(CPCoder)aCoder
{
var actualSubviews = _subviews;
_subviews = [];
[super encodeWithCoder:aCoder];
[aCoder encodeObject:items forKey:CPTabViewItemsKey];;
[aCoder encodeObject:[self selectedTabViewItem] forKey:CPTabViewSelectedItemKey];
[aCoder encodeInt:type forKey:CPTabViewTypeKey];
[aCoder encodeConditionalObject:delegate forKey:CPTabViewDelegateKey];
_subviews = actualSubviews;
[aCoder encodeObject:_tabViewItems forKey:CPTabViewItemsKey];;
[aCoder encodeObject:_selectedTabViewItem forKey:CPTabViewSelectedItemKey];
[aCoder encodeInt:_tabViewType forKey:CPTabViewTypeKey];
[aCoder encodeConditionalObject:_delegate forKey:CPTabViewDelegateKey];
}
@end
var _CPTabLabelsViewBackgroundColor = nil,
_CPTabLabelsViewInsideMargin = 10.0,
_CPTabLabelsViewOutsideMargin = 15.0;
/* @ignore */
@implementation _CPTabLabelsView : CPView
{
CPTabView _tabView;
CPDictionary _tabLabels;
}
+ (void)initialize
{
if (self != [_CPTabLabelsView class])
return;
var bundle = [CPBundle bundleForClass:self];
_CPTabLabelsViewBackgroundColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelsViewLeft.png"] size:CGSizeMake(12.0, 26.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelsViewCenter.png"] size:CGSizeMake(1.0, 26.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelsViewRight.png"] size:CGSizeMake(12.0, 26.0)]
] isVertical:NO]];
}
+ (float)height
{
return 26.0;
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_tabLabels = [];
[self setBackgroundColor:_CPTabLabelsViewBackgroundColor];
[self setFrameSize:CGSizeMake(CGRectGetWidth(aFrame), 26.0)];
}
return self;
}
- (void)setTabView:(CPTabView)aTabView
{
_tabView = aTabView;
}
- (CPTabView)tabView
{
return _tabView;
}
- (void)tabView:(CPTabView)aTabView didAddTabViewItem:(CPTabViewItem)aTabViewItem
{
var label = [[_CPTabLabel alloc] initWithFrame:CGRectMakeZero()];
[label setTabViewItem:aTabViewItem];
_tabLabels.push(label);
[self addSubview:label];
[self layoutSubviews];
}
- (void)tabView:(CPTabView)aTabView didRemoveTabViewItemAtIndex:(unsigned)index
{
var label = _tabLabels[index];
[_tabLabels removeObjectAtIndex:index];
[label removeFromSuperview];
[self layoutSubviews];
}
-(void)tabView:(CPTabView)aTabView didChangeStateOfTabViewItem:(CPTabViewItem)aTabViewItem
{
[_tabLabels[[aTabView indexOfTabViewItem:aTabViewItem]] setTabState:[aTabViewItem tabState]];
}
- (CPTabViewItem)representedTabViewItemAtPoint:(CGPoint)aPoint
{
var index = 0,
count = _tabLabels.length;
for (; index < count; ++index)
{
var label = _tabLabels[index];
if (CGRectContainsPoint([label frame], aPoint))
return [label tabViewItem];
}
return nil;
}
- (void)layoutSubviews
{
var index = 0,
count = _tabLabels.length,
width = (_CGRectGetWidth([self bounds]) - (count - 1) * _CPTabLabelsViewInsideMargin - 2 * _CPTabLabelsViewOutsideMargin) / count,
x = _CPTabLabelsViewOutsideMargin;
for (; index < count; ++index)
{
var label = _tabLabels[index],
frame = _CGRectMake(x, 8.0, width, 18.0);
[label setFrame:frame];
x = _CGRectGetMaxX(frame) + _CPTabLabelsViewInsideMargin;
}
}
- (void)setFrameSize:(CGSize)aSize
{
if (CGSizeEqualToSize([self frame].size, aSize))
return;
[super setFrameSize:aSize];
[self layoutSubviews];
}
@end
var _CPTabLabelBackgroundColor = nil,
_CPTabLabelSelectedBackgroundColor = nil;
/* @ignore */
@implementation _CPTabLabel : CPView
{
CPTabViewItem _tabViewItem;
CPTextField _labelField;
}
+ (void)initialize
{
if (self != [_CPTabLabel class])
return;
var bundle = [CPBundle bundleForClass:self];
_CPTabLabelBackgroundColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelBackgroundLeft.png"] size:CGSizeMake(6.0, 18.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelBackgroundCenter.png"] size:CGSizeMake(1.0, 18.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelBackgroundRight.png"] size:CGSizeMake(6.0, 18.0)]
] isVertical:NO]];
_CPTabLabelSelectedBackgroundColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelSelectedLeft.png"] size:CGSizeMake(3.0, 18.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelSelectedCenter.png"] size:CGSizeMake(1.0, 18.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelSelectedRight.png"] size:CGSizeMake(3.0, 18.0)]
] isVertical:NO]];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self)
{
_labelField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[_labelField setAlignment:CPCenterTextAlignment];
[_labelField setFrame:CGRectMake(5.0, 0.0, CGRectGetWidth(aFrame) - 10.0, 20.0)];
[_labelField setAutoresizingMask:CPViewWidthSizable];
[_labelField setFont:[CPFont boldSystemFontOfSize:11.0]];
[self addSubview:_labelField];
[self setTabState:CPBackgroundTab];
}
return self;
}
- (void)setTabState:(CPTabState)aTabState
{
[self setBackgroundColor:aTabState == CPSelectedTab ? _CPTabLabelSelectedBackgroundColor : _CPTabLabelBackgroundColor];
}
- (void)setTabViewItem:(CPTabViewItem)aTabViewItem
{
_tabViewItem = aTabViewItem;
[self update];
}
- (CPTabViewItem)tabViewItem
{
return _tabViewItem;
}
- (void)update
{
[_labelField setStringValue:[_tabViewItem label]];
}
@end
+1 -1
View File
@@ -22,7 +22,7 @@
@import <Foundation/CPObject.j>
@import "CPView.j"
@import <AppKit/CPView.j>
/*
+30 -107
View File
@@ -22,12 +22,12 @@
@import <Foundation/CPDictionary.j>
@import <Foundation/CPObject.j>
@import <Foundation/CPIndexSet.j>
@import <Foundation/CPSortDescriptor.j>
@import <Foundation/CPString.j>
@import "CPTableHeaderView.j"
#include "CoreGraphics/CGGeometry.h"
CPTableColumnNoResizing = 0;
CPTableColumnAutoresizingMask = 1 << 0;
@@ -50,7 +50,7 @@ CPTableColumnUserResizingMask = 1 << 1;
CPSortDescriptor _sortDescriptorPrototype;
BOOL _isHidden;
CPString _headerToolTip;
BOOL _disableResizingPosting @accessors(property=disableResizingPosting);
}
@@ -72,13 +72,19 @@ CPTableColumnUserResizingMask = 1 << 1;
_maxWidth = 1000000.0;
_resizingMask = CPTableColumnAutoresizingMask | CPTableColumnUserResizingMask;
_disableResizingPosting = NO;
[self setIdentifier:anIdentifier];
var header = [[_CPTableColumnHeaderView alloc] initWithFrame:CGRectMakeZero()];
[self setHeaderView:header];
[self setDataView:[CPTextField new]];
var textDataView = [CPTextField new];
[textDataView setLineBreakMode:CPLineBreakByTruncatingTail];
[textDataView setValue:[CPColor colorWithHexString:@"333333"] forThemeAttribute:@"text-color"];
[textDataView setValue:[CPColor whiteColor] forThemeAttribute:@"text-color" inState:CPThemeStateSelected];
[textDataView setValue:[CPFont boldSystemFontOfSize:12] forThemeAttribute:@"font" inState:CPThemeStateSelected];
[textDataView setValue:CPCenterVerticalTextAlignment forThemeAttribute:@"vertical-alignment"];
[self setDataView:textDataView];
}
return self;
@@ -117,19 +123,19 @@ CPTableColumnUserResizingMask = 1 << 1;
{
var index = [[tableView tableColumns] indexOfObjectIdenticalTo:self],
dirtyTableColumnRangeIndex = tableView._dirtyTableColumnRangeIndex;
if (dirtyTableColumnRangeIndex < 0)
tableView._dirtyTableColumnRangeIndex = index;
else
tableView._dirtyTableColumnRangeIndex = MIN(index, tableView._dirtyTableColumnRangeIndex);
var rows = tableView._exposedRows,
columns = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(index, [tableView._exposedColumns lastIndex] - index + 1)];
columns = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(index, [tableView._exposedColumns lastIndex] - index + 1)];
// FIXME: Would be faster with some sort of -setNeedsDisplayInColumns: that updates a dirtyTableColumnForDisplay cache; then marked columns would relayout their data views at display time.
[tableView _layoutDataViewsInRows:rows columns:columns];
[tableView tile];
if (!_disableResizingPosting)
[self _postDidResizeNotificationWithOldWidth:oldWidth];
}
@@ -226,12 +232,12 @@ CPTableColumnUserResizingMask = 1 << 1;
/*!
This method set's the "prototype" view which will be used to create all table cells in this column.
It creates a snapshot of aView, using keyed archiving, which is then copied over and over for each
It creates a snapshot of aView, using keyed archiving, which is then copied over and over for each
individual cell that is shown. As a result, changes made after calling this method won't be reflected.
Example:
[tableColumn setDataView:someView]; // snapshot taken
[[tableColumn dataView] setSomething:x]; //won't work
@@ -242,11 +248,12 @@ CPTableColumnUserResizingMask = 1 << 1;
*/
- (void)setDataView:(CPView)aView
{
if (_dataView === aView)
return;
if (_dataView)
_dataViewData[[_dataView UID]] = nil;
[aView setThemeState:CPThemeStateTableDataView];
_dataView = aView;
_dataViewData[[aView UID]] = [CPKeyedArchiver archivedDataWithRootObject:aView];
}
@@ -285,10 +292,7 @@ CPTableColumnUserResizingMask = 1 << 1;
// unarchive the data view cache
var newDataView = [CPKeyedUnarchiver unarchiveObjectWithData:_dataViewData[dataViewUID]];
newDataView.identifier = dataViewUID;
// make sure only we have control over the size and placement
[newDataView setAutoresizingMask:CPViewNotSizable];
return newDataView;
}
@@ -321,7 +325,7 @@ CPTableColumnUserResizingMask = 1 << 1;
}
/*
Returns YES if the user can edit cells associated with the receiver by double-clicking the
Returns YES if the user can edit cells associated with the receiver by double-clicking the
column in the NSTableView, NO otherwise.
*/
- (BOOL)isEditable
@@ -347,9 +351,9 @@ CPTableColumnUserResizingMask = 1 << 1;
shouldBeHidden = !!shouldBeHidden
if (_isHidden === shouldBeHidden)
return;
_isHidden = shouldBeHidden;
[[self headerView] setHidden:shouldBeHidden];
[[self tableView] _tableColumnVisibilityDidChange:self];
}
@@ -362,7 +366,7 @@ CPTableColumnUserResizingMask = 1 << 1;
//Setting Tool Tips
/*
Sets the tooltip string that is displayed when the cursor pauses over the
Sets the tooltip string that is displayed when the cursor pauses over the
header cell of the receiver.
*/
- (void)setHeaderToolTip:(CPString)aToolTip
@@ -385,86 +389,13 @@ CPTableColumnUserResizingMask = 1 << 1;
@end
@implementation CPTableColumn (Bindings)
- (void)bind:(CPString)aBinding toObject:(id)anObject withKeyPath:(CPString)aKeyPath options:(CPDictionary)options
{
[super bind:aBinding toObject:anObject withKeyPath:aKeyPath options:options];
if (![aBinding isEqual:@"someListOfExceptedBindings(notAcceptedBindings)"])
[[self tableView] _establishBindingsIfUnbound:anObject];
}
- (void)prepareDataView:(CPView)aDataView forRow:(unsigned)aRow
{
var bindingsDictionary = [CPKeyValueBinding allBindingsForObject:self],
keys = [bindingsDictionary allKeys];
for (var i = 0, count = [keys count]; i < count; i++)
{
var bindingName = keys[i],
bindingPath = [aDataView _replacementKeyPathForBinding:bindingName],
binding = [bindingsDictionary objectForKey:bindingName],
bindingInfo = binding._info,
destination = [bindingInfo objectForKey:CPObservedObjectKey],
keyPath = [bindingInfo objectForKey:CPObservedKeyPathKey],
dotIndex = keyPath.lastIndexOf("."),
value;
if (dotIndex === CPNotFound)
value = [[destination valueForKeyPath:keyPath] objectAtIndex:aRow];
else
{
/*
Optimize the prototypical use case where the key path describes a value
in an array. Without this optimization, we call CPArray's valueForKey
which generates as many values as objects in the array, of which we then
pick one and throw away the rest.
The optimization is to get the array and access the value directly. This
turns the operation into a single access regardless of how long the model
array is.
*/
var firstPart = keyPath.substring(0, dotIndex),
secondPart = keyPath.substring(dotIndex + 1),
firstValue = [destination valueForKeyPath:firstPart];
if ([firstValue isKindOfClass:CPArray])
value = [[firstValue objectAtIndex:aRow] valueForKeyPath:secondPart];
else
value = [[firstValue valueForKeyPath:secondPart] objectAtIndex:aRow];
}
value = [binding transformValue:value withOptions:[bindingInfo objectForKey:CPOptionsKey]];
// console.log(bindingName+" : "+keyPath+" : "+aRow+" : "+[[destination valueForKeyPath:keyPath] objectAtIndex:aRow]);
[aDataView setValue:value forKey:bindingPath];
}
}
//- (void)objectValue
//{
// return nil;
//}
- (void)setValue:(CPArray)content
{
[[self tableView] reloadData];
}
@end
var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
CPTableColumnHeaderViewKey = @"CPTableColumnHeaderViewKey",
CPTableColumnDataViewKey = @"CPTableColumnDataViewKey",
CPTableColumnWidthKey = @"CPTableColumnWidthKey",
CPTableColumnMinWidthKey = @"CPTableColumnMinWidthKey",
CPTableColumnMaxWidthKey = @"CPTableColumnMaxWidthKey",
CPTableColumnResizingMaskKey = @"CPTableColumnResizingMaskKey",
CPTableColumnIsHiddenKey = @"CPTableColumnIsHiddenKey",
CPSortDescriptorPrototypeKey = @"CPSortDescriptorPrototypeKey",
CPTableColumnIsEditableKey = @"CPTableColumnIsEditableKey";
CPTableColumnResizingMaskKey = @"CPTableColumnResizingMaskKey";
@implementation CPTableColumn (CPCoding)
@@ -485,11 +416,7 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
[self setDataView:[aCoder decodeObjectForKey:CPTableColumnDataViewKey]];
[self setHeaderView:[aCoder decodeObjectForKey:CPTableColumnHeaderViewKey]];
_resizingMask = [aCoder decodeIntForKey:CPTableColumnResizingMaskKey];
_isHidden = [aCoder decodeBoolForKey:CPTableColumnIsHiddenKey];
_isEditable = [aCoder decodeBoolForKey:CPTableColumnIsEditableKey];
_sortDescriptorPrototype = [aCoder decodeObjectForKey:CPSortDescriptorPrototypeKey];
_resizingMask = [aCoder decodeBoolForKey:CPTableColumnResizingMaskKey];
}
return self;
@@ -507,10 +434,6 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
[aCoder encodeObject:_dataView forKey:CPTableColumnDataViewKey];
[aCoder encodeObject:_resizingMask forKey:CPTableColumnResizingMaskKey];
[aCoder encodeBool:_isHidden forKey:CPTableColumnIsHiddenKey];
[aCoder encodeBool:_isEditable forKey:CPTableColumnIsEditableKey];
[aCoder encodeObject:_sortDescriptorPrototype forKey:CPSortDescriptorPrototypeKey];
}
@end
@@ -547,4 +470,4 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
reason:@"dataCellForRow: is not supported. Use -dataViewForRow:row instead."];
}
@end
@end
+83 -116
View File
@@ -20,64 +20,54 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPIndexSet.j>
@import "CPTableColumn.j"
@import "CPTableView.j"
@import "CPView.j"
@implementation _CPTableColumnHeaderView : CPView
{
_CPImageAndTextView _textField;
}
+ (CPString)defaultThemeClass
{
return @"columnHeader";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[[CPNull null], [CPNull null], CGInsetMakeZero(), [CPNull null], [CPNull null], [CPNull null], CGSizeMakeZero()]
forKeys:[@"background-color", @"text-alignment", @"text-inset", @"text-color", @"text-font", @"text-shadow-color", @"text-shadow-offset"]];
}
- (void)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
[self _init];
}
return self;
}
- (void)_init
{
_textField = [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
_textField = [[_CPImageAndTextView alloc] initWithFrame:CGRectMake(5, 1, CGRectGetWidth([self bounds]) - 10, CGRectGetHeight([self bounds]) - 1)];
[_textField setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
[_textField setLineBreakMode:CPLineBreakByTruncatingTail];
[_textField setTextColor: [CPColor colorWithHexString: @"333333"]];
[_textField setFont:[CPFont boldSystemFontOfSize:12.0]];
[_textField setAlignment:CPLeftTextAlignment];
[_textField setVerticalAlignment:CPCenterVerticalTextAlignment];
[_textField setTextShadowColor:[CPColor whiteColor]];
[_textField setTextShadowOffset:CGSizeMake(0,1)];
[self addSubview:_textField];
}
- (void)layoutSubviews
{
[self setBackgroundColor:[self currentValueForThemeAttribute:@"background-color"]];
var themeState = [self themeState];
var inset = [self currentValueForThemeAttribute:@"text-inset"],
bounds = [self bounds];
[_textField setFrame:_CGRectMake(inset.right, inset.top, bounds.size.width - inset.right - inset.left, bounds.size.height - inset.top - inset.bottom)];
[_textField setTextColor:[self currentValueForThemeAttribute:@"text-color"]];
[_textField setFont:[self currentValueForThemeAttribute:@"text-font"]];
[_textField setTextShadowColor:[self currentValueForThemeAttribute:@"text-shadow-color"]];
[_textField setTextShadowOffset:[self currentValueForThemeAttribute:@"text-shadow-offset"]];
[_textField setAlignment:[self currentValueForThemeAttribute:@"text-alignment"]];
if(themeState & CPThemeStateSelected && themeState & CPThemeStateHighlighted)
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-highlighted-pressed.png", CGSizeMake(1.0, 22.0))]];
else if (themeState & CPThemeStateSelected)
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-highlighted.png", CGSizeMake(1.0, 22.0))]];
else if (themeState & CPThemeStateHighlighted)
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-pressed.png", CGSizeMake(1.0, 22.0))]];
else
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 22.0))]];
}
- (void)setStringValue:(CPString)string
@@ -105,6 +95,11 @@
[_textField setFont:aFont];
}
- (void)setValue:(id)aValue forThemeAttribute:(id)aKey
{
[_textField setValue:aValue forThemeAttribute:aKey];
}
- (void)_setIndicatorImage:(CPImage)anImage
{
if (anImage)
@@ -152,47 +147,34 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
@implementation CPTableHeaderView : CPView
{
CGPoint _mouseDownLocation;
CGPoint _previousTrackingLocation;
CPPoint _mouseDownLocation;
CPPoint _previousTrackingLocation;
int _activeColumn;
int _pressedColumn;
BOOL _isResizing;
BOOL _isDragging;
BOOL _isTrackingColumn;
BOOL _drawsColumnLines;
float _columnOldWidth;
CPTableView _tableView @accessors(property=tableView);
}
+ (CPString)defaultThemeClass
{
return @"tableHeaderRow";
}
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[[CPNull null], [CPColor grayColor]]
forKeys:[@"background-color", @"divider-color"]];
}
- (void)_init
{
_mouseDownLocation = _CGPointMakeZero();
_previousTrackingLocation = _CGPointMakeZero();
_mouseDownLocation = CPPointMakeZero();
_previousTrackingLocation = CPPointMakeZero();
_activeColumn = -1;
_pressedColumn = -1;
_isResizing = NO;
_isDragging = NO;
_isTrackingColumn = NO;
_drawsColumnLines = YES;
_columnOldWidth = 0.0;
[self setBackgroundColor:[self currentValueForThemeAttribute:@"background-color"]];
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 22.0))]];
}
- (id)initWithFrame:(CGRect)aFrame
@@ -215,33 +197,23 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
var headerRect = [self bounds],
columnRect = [_tableView rectOfColumn:aColumnIndex];
headerRect.origin.x = _CGRectGetMinX(columnRect);
headerRect.size.width = _CGRectGetWidth(columnRect);
headerRect.origin.x = CPRectGetMinX(columnRect);
headerRect.size.width = CPRectGetWidth(columnRect);
return headerRect;
}
- (void)setDrawsColumnLines:(BOOL)aFlag
{
_drawsColumnLines = aFlag;
}
- (BOOL)drawsColumnLines
{
return _drawsColumnLines;
}
- (CGRect)_cursorRectForColumn:(int)column
{
if (column == -1 || !([_tableView._tableColumns[column] resizingMask] & CPTableColumnUserResizingMask))
return _CGRectMakeZero();
return CGRectMakeZero();
var rect = [self headerRectOfColumn:column];
rect.origin.x = _CGRectGetMaxX(rect) - 5;
rect.origin.x = CGRectGetMaxX(rect) - 5;
rect.size.width = 20;
return rect;
return rect;
}
- (void)_setPressedColumn:(CPInteger)column
@@ -250,7 +222,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
{
var headerView = [_tableView._tableColumns[_pressedColumn] headerView];
[headerView unsetThemeState:CPThemeStateHighlighted];
}
}
if (column != -1)
{
@@ -275,7 +247,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
currentLocation.x -= 5.0;
var columnIndex = [self columnAtPoint:currentLocation],
shouldResize = [self shouldResizeTableColumn:columnIndex at:_CGPointMake(currentLocation.x + 5.0, currentLocation.y)];
shouldResize = [self shouldResizeTableColumn:columnIndex at:CPPointMake(currentLocation.x + 5.0, currentLocation.y)];
if (type === CPLeftMouseUp)
{
@@ -319,7 +291,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
[self continueResizingTableColumn:_activeColumn at:currentLocation];
else
{
if (_activeColumn === columnIndex && _CGRectContainsPoint([self headerRectOfColumn:columnIndex], currentLocation))
if (_activeColumn === columnIndex && CPRectContainsPoint([self headerRectOfColumn:columnIndex], currentLocation))
{
if (_isTrackingColumn && _pressedColumn !== -1)
{
@@ -337,24 +309,24 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
[CPApp setTarget:self selector:@selector(trackMouse:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
}
- (void)startTrackingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
- (void)startTrackingTableColumn:(int)aColumnIndex at:(CPPoint)aPoint
{
[self _setPressedColumn:aColumnIndex];
}
- (BOOL)continueTrackingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
- (BOOL)continueTrackingTableColumn:(int)aColumnIndex at:(CPPoint)aPoint
{
if ([self _shouldDragTableColumn:aColumnIndex at:aPoint])
{
var columnRect = [self headerRectOfColumn:aColumnIndex],
offset = _CGPointMakeZero(),
offset = CPPointMakeZero(),
view = [_tableView _dragViewForColumn:aColumnIndex event:[CPApp currentEvent] offset:offset],
viewLocation = _CGPointMakeZero();
viewLocation = CPPointMakeZero();
viewLocation.x = ( _CGRectGetMinX(columnRect) + offset.x ) + ( aPoint.x - _mouseDownLocation.x );
viewLocation.y = _CGRectGetMinY(columnRect) + offset.y;
viewLocation.x = ( CPRectGetMinX(columnRect) + offset.x ) + ( aPoint.x - _mouseDownLocation.x );
viewLocation.y = CPRectGetMinY(columnRect) + offset.y;
[self dragView:view at:viewLocation offset:_CGSizeMakeZero() event:[CPApp currentEvent]
[self dragView:view at:viewLocation offset:CPSizeMakeZero() event:[CPApp currentEvent]
pasteboard:[CPPasteboard pasteboardWithName:CPDragPboard] source:self slideBack:YES];
return NO;
@@ -363,24 +335,24 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
return YES;
}
- (BOOL)_shouldStopTrackingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
- (BOOL)_shouldStopTrackingTableColumn:(int)aColumnIndex at:(CPPoint)aPoint
{
return _isTrackingColumn && _activeColumn === aColumnIndex &&
_CGRectContainsPoint([self headerRectOfColumn:aColumnIndex], aPoint);
return _isTrackingColumn && _activeColumn === aColumnIndex &&
CPRectContainsPoint([self headerRectOfColumn:aColumnIndex], aPoint);
}
- (void)stopTrackingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
- (void)stopTrackingTableColumn:(int)aColumnIndex at:(CPPoint)aPoint
{
[self _setPressedColumn:CPNotFound];
[self _updateResizeCursor:[CPApp currentEvent]];
}
- (BOOL)_shouldDragTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
- (BOOL)_shouldDragTableColumn:(int)aColumnIndex at:(CPPoint)aPoint
{
return [_tableView allowsColumnReordering] && ABS(aPoint.x - _mouseDownLocation.x) >= 10.0;
}
- (CGRect)_headerRectOfLastVisibleColumn
- (CPRect)_headerRectOfLastVisibleColumn
{
var tableColumns = [_tableView tableColumns],
columnIndex = [tableColumns count];
@@ -396,11 +368,11 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
return nil;
}
- (void)_constrainDragView:(CPView)theDragView at:(CGPoint)aPoint
- (void)_constrainDragView:(CPView)theDragView at:(CPPoint)aPoint
{
var tableColumns = [_tableView tableColumns],
lastColumnRect = [self _headerRectOfLastVisibleColumn],
activeColumnRect = [self headerRectOfColumn:_activeColumn],
lastColumnRect = [self _headerRectOfLastVisibleColumn];
activeColumnRect = [self headerRectOfColumn:_activeColumn];
dragWindow = [theDragView window],
frame = [dragWindow frame];
@@ -410,10 +382,10 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
frame.origin = [self convertPoint:frame.origin fromView:nil];
// This effectively clamps the value between the minimum and maximum
frame.origin.x = MAX(0.0, MIN(_CGRectGetMinX(frame), _CGRectGetMaxX(lastColumnRect) - _CGRectGetWidth(activeColumnRect)));
frame.origin.x = MAX(0.0, MIN(CGRectGetMinX(frame), CGRectGetMaxX(lastColumnRect) - CGRectGetWidth(activeColumnRect)));
// Make sure the column cannot move vertically
frame.origin.y = _CGRectGetMinY(lastColumnRect);
frame.origin.y = CPRectGetMinY(lastColumnRect);
// Convert the calculated origin back to the window coordinate system
frame.origin = [self convertPoint:frame.origin toView:nil];
@@ -428,21 +400,21 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
[_tableView moveColumn:aFromIndex toColumn:aToIndex];
_activeColumn = aToIndex;
_pressedColumn = _activeColumn;
[_tableView _setDraggedColumn:_activeColumn];
}
- (void)draggedView:(CPView)aView beganAt:(CGPoint)aPoint
- (void)draggedView:(CPView)aView beganAt:(CPPoint)aPoint
{
_isDragging = YES;
var column = [[_tableView tableColumns] objectAtIndex:_activeColumn];
[[column headerView] setHidden:YES];
[_tableView _setDraggedColumn:column];
[[[[_tableView tableColumns] objectAtIndex:_activeColumn] headerView] setHidden:YES];
[_tableView _setDraggedColumn:_activeColumn];
[self setNeedsDisplay:YES];
}
- (void)draggedView:(CPView)aView movedTo:(CGPoint)aPoint
- (void)draggedView:(CPView)aView movedTo:(CPPoint)aPoint
{
[self _constrainDragView:aView at:aPoint];
@@ -452,9 +424,9 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
var hoverPoint = CGPointCreateCopy(aPoint);
if (aPoint.x < _previousTrackingLocation.x)
hoverPoint = _CGPointMake(_CGRectGetMinX(dragWindowFrame), _CGRectGetMinY(dragWindowFrame));
hoverPoint = CGPointMake(CGRectGetMinX(dragWindowFrame), CGRectGetMinY(dragWindowFrame));
else if (aPoint.x > _previousTrackingLocation.x)
hoverPoint = _CGPointMake(_CGRectGetMaxX(dragWindowFrame), _CGRectGetMinY(dragWindowFrame));
hoverPoint = CGPointMake(CGRectGetMaxX(dragWindowFrame), CGRectGetMinY(dragWindowFrame));
// Convert the hover point from the global coordinate system to windows' coordinate system
hoverPoint = [[self window] convertGlobalToBase:hoverPoint];
@@ -466,7 +438,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
if (hoveredColumn !== -1)
{
var columnRect = [self headerRectOfColumn:hoveredColumn],
columnCenterPoint = [self convertPoint:CGPointMake(_CGRectGetMidX(columnRect), _CGRectGetMidY(columnRect)) fromView:self];
columnCenterPoint = [self convertPoint:CGPointMake(CGRectGetMidX(columnRect), CGRectGetMidY(columnRect)) fromView:self];
if (hoveredColumn < _activeColumn && hoverPoint.x < columnCenterPoint.x)
[self _moveColumn:_activeColumn toColumn:hoveredColumn];
else if (hoveredColumn > _activeColumn && hoverPoint.x > columnCenterPoint.x)
@@ -481,14 +453,14 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
_isDragging = NO;
_isTrackingColumn = NO; // We need to do this explicitly because the mouse up section of trackMouse is never reached
[_tableView _setDraggedColumn:nil];
[_tableView _setDraggedColumn:-1];
[[[[_tableView tableColumns] objectAtIndex:_activeColumn] headerView] setHidden:NO];
[self stopTrackingTableColumn:_activeColumn at:aLocation];
[self setNeedsDisplay:YES];
}
- (BOOL)shouldResizeTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
- (BOOL)shouldResizeTableColumn:(int)aColumnIndex at:(CPPoint)aPoint
{
if (_isResizing)
return YES;
@@ -496,10 +468,10 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
if (_isTrackingColumn)
return NO;
return [_tableView allowsColumnResizing] && _CGRectContainsPoint([self _cursorRectForColumn:aColumnIndex], aPoint);
return [_tableView allowsColumnResizing] && CPRectContainsPoint([self _cursorRectForColumn:aColumnIndex], aPoint);
}
- (void)startResizingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
- (void)startResizingTableColumn:(int)aColumnIndex at:(CPPoint)aPoint
{
_isResizing = YES;
@@ -509,7 +481,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
[_tableView setDisableAutomaticResizing:YES];
}
- (void)continueResizingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
- (void)continueResizingTableColumn:(int)aColumnIndex at:(CPPoint)aPoint
{
var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex],
newWidth = [tableColumn width] + aPoint.x - _previousTrackingLocation.x;
@@ -529,7 +501,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
}
}
- (void)stopResizingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
- (void)stopResizingTableColumn:(int)aColumnIndex at:(CPPoint)aPoint
{
var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex];
[tableColumn _postDidResizeNotificationWithOldWidth:_columnOldWidth];
@@ -548,11 +520,11 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
return;
}
var mouseLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil],
var mouseLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil],
mouseOverLocation = CGPointMake(mouseLocation.x - 5, mouseLocation.y),
overColumn = [self columnAtPoint:mouseOverLocation];
if (overColumn >= 0 && _CGRectContainsPoint([self _cursorRectForColumn:overColumn], mouseLocation))
if (overColumn >= 0 && CGRectContainsPoint([self _cursorRectForColumn:overColumn], mouseLocation))
{
var tableColumn = [[_tableView tableColumns] objectAtIndex:overColumn],
width = [tableColumn width];
@@ -569,7 +541,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
}
- (void)mouseEntered:(CPEvent)theEvent
{
{
[self _updateResizeCursor:theEvent];
}
@@ -587,16 +559,16 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
- (void)layoutSubviews
{
var tableColumns = [_tableView tableColumns],
count = [tableColumns count];
count = [tableColumns count];
for (var i = 0; i < count; i++)
for (var i = 0; i < count; i++)
{
var column = [tableColumns objectAtIndex:i],
headerView = [column headerView];
var frame = [self headerRectOfColumn:i];
frame.size.height -= 0.5;
if (i > 0)
if (i > 0)
{
frame.origin.x += 0.5;
frame.size.width -= 1;
@@ -607,13 +579,11 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
if([headerView superview] != self)
[self addSubview:headerView];
}
[self setBackgroundColor:[self currentValueForThemeAttribute:@"background-color"]];
}
- (void)drawRect:(CGRect)aRect
{
if (!_tableView || ![self drawsColumnLines])
if (!_tableView)
return;
var context = [[CPGraphicsContext currentContext] graphicsPort],
@@ -625,7 +595,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
exposedRange = CPMakeRange(firstIndex, [exposedTableColumns lastIndex] - firstIndex + 1);
CGContextSetLineWidth(context, 1);
CGContextSetStrokeColor(context, [self currentValueForThemeAttribute:@"divider-color"]);
CGContextSetStrokeColor(context, [_tableView gridColor]);
[exposedColumnIndexes getIndexes:columnsArray maxCount:-1 inIndexRange:exposedRange];
@@ -640,26 +610,25 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
var columnIndex = columnsArray[columnArrayIndex],
columnToStroke = [self headerRectOfColumn:columnIndex];
columnMaxX = _CGRectGetMaxX(columnToStroke);
columnMaxX = CGRectGetMaxX(columnToStroke);
CGContextMoveToPoint(context, ROUND(columnMaxX) + 0.5, ROUND(_CGRectGetMinY(columnToStroke)));
CGContextAddLineToPoint(context, ROUND(columnMaxX) + 0.5, ROUND(_CGRectGetMaxY(columnToStroke)));
CGContextMoveToPoint(context, ROUND(columnMaxX) + 0.5, ROUND(CGRectGetMinY(columnToStroke)));
CGContextAddLineToPoint(context, ROUND(columnMaxX) + 0.5, ROUND(CGRectGetMaxY(columnToStroke)));
}
CGContextClosePath(context);
CGContextStrokePath(context);
/*if (_isDragging)
if (_isDragging)
{
CGContextSetFillColor(context, [CPColor grayColor]);
CGContextFillRect(context, [self headerRectOfColumn:_activeColumn])
}*/
}
}
@end
var CPTableHeaderViewTableViewKey = @"CPTableHeaderViewTableViewKey",
CPTableHeaderViewDrawsColumnLines = @"CPTableHeaderViewDrawsColumnLines";
var CPTableHeaderViewTableViewKey = @"CPTableHeaderViewTableViewKey";
@implementation CPTableHeaderView (CPCoding)
@@ -669,7 +638,6 @@ var CPTableHeaderViewTableViewKey = @"CPTableHeaderViewTableViewKey",
{
[self _init];
_tableView = [aCoder decodeObjectForKey:CPTableHeaderViewTableViewKey];
_drawsColumnLines = [aCoder decodeBoolForKey:CPTableHeaderViewDrawsColumnLines];
}
return self;
@@ -679,7 +647,6 @@ var CPTableHeaderViewTableViewKey = @"CPTableHeaderViewTableViewKey",
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_tableView forKey:CPTableHeaderViewTableViewKey];
[aCoder encodeBool:_drawsColumnLines forKey:CPTableHeaderViewDrawsColumnLines];
}
@end
@end
+492 -894
View File
File diff suppressed because it is too large Load Diff
-30
View File
@@ -1,30 +0,0 @@
/*
* CPText.j
* AppKit
*
* Created by Alexander Ljungberg.
* Copyright 2010, WireLoad, LLC.
*
* 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
*/
CPEnterCharacter = "\u0003";
CPBackspaceCharacter = "\u0008";
CPTabCharacter = "\u0009";
CPNewlineCharacter = "\u000a";
CPFormFeedCharacter = "\u000c";
CPCarriageReturnCharacter = "\u000d";
CPBackTabCharacter = "\u0019";
CPDeleteCharacter = "\u007f";
+118 -249
View File
@@ -26,6 +26,9 @@
@import "CPCompatibility.j"
@import "_CPImageAndTextView.j"
#include "CoreGraphics/CGGeometry.h"
#include "Platform/Platform.h"
#include "Platform/DOM/CPDOMDisplayServer.h"
CPTextFieldSquareBezel = 0; /*! A textfield bezel with a squared corners. */
CPTextFieldRoundedBezel = 1; /*! A textfield bezel with rounded corners. */
@@ -46,7 +49,7 @@ var CPTextFieldDOMInputElement = nil,
CPTextFieldCachedSelectStartFunction = nil,
CPTextFieldCachedDragFunction = nil,
CPTextFieldBlurFunction = nil;
#endif
var CPSecureTextFieldCharacter = "\u2022";
@@ -77,18 +80,15 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
BOOL _isEditable;
BOOL _isSelectable;
BOOL _isSecure;
BOOL _willBecomeFirstResponderByClick;
BOOL _drawsBackground;
CPColor _textFieldBackgroundColor;
id _placeholderString;
id _originalPlaceholderString;
BOOL _currentValueIsPlaceholder;
id _delegate;
CPString _textDidChangeValue;
// NS-style Display Properties
@@ -155,7 +155,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
return textField;
}
+ (CPString)defaultThemeClass
+ (CPString)themeClass
{
return "textfield";
}
@@ -199,7 +199,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
}
CPTextFieldHandleBlur = function(anEvent)
{
{
CPTextFieldInputOwner = nil;
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
@@ -207,10 +207,10 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
//FIXME make this not onblur
CPTextFieldDOMInputElement.onblur = CPTextFieldBlurFunction;
CPTextFieldDOMStandardInputElement = CPTextFieldDOMInputElement;
}
if (CPFeatureIsCompatible(CPInputTypeCanBeChangedFeature))
{
if ([self isSecure])
@@ -237,14 +237,14 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
CPTextFieldDOMPasswordInputElement.onblur = CPTextFieldBlurFunction;
}
CPTextFieldDOMInputElement = CPTextFieldDOMPasswordInputElement;
}
else
{
CPTextFieldDOMInputElement = CPTextFieldDOMStandardInputElement;
}
return CPTextFieldDOMInputElement;
}
#endif
@@ -262,29 +262,18 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
[self setValue:CPLeftTextAlignment forThemeAttribute:@"alignment"];
}
return self;
}
#pragma mark Controlling Editability and Selectability
/*!
Sets whether or not the receiver text field can be edited. If NO, any
ongoing edit is ended.
/*!
Sets whether or not the receiver text field can be edited
*/
- (void)setEditable:(BOOL)shouldBeEditable
{
if (_isEditable === shouldBeEditable)
return;
_isEditable = shouldBeEditable;
if (shouldBeEditable)
_isSelectable = YES;
// We only allow first responder status if the field is editable and enabled.
if (!shouldBeEditable && [[self window] firstResponder] === self)
[[self window] makeFirstResponder:nil];
}
/*!
@@ -295,19 +284,6 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
return _isEditable;
}
/*!
Sets whether the field reacts to events. If NO, any ongoing edit is
ended.
*/
- (void)setEnabled:(BOOL)shouldBeEnabled
{
[super setEnabled:shouldBeEnabled];
// We only allow first responder status if the field is editable and enabled.
if (!shouldBeEnabled && [[self window] firstResponder] === self)
[[self window] makeFirstResponder:nil];
}
/*!
Sets whether the field's text is selectable by the user.
@param aFlag \c YES makes the text selectable
@@ -370,7 +346,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
- (void)setBezelStyle:(CPTextFieldBezelStyle)aBezelStyle
{
var shouldBeRounded = aBezelStyle === CPTextFieldRoundedBezel;
if (shouldBeRounded)
[self setThemeState:CPTextFieldStateRounded];
else
@@ -416,9 +392,9 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
{
if (_drawsBackground == shouldDrawBackground)
return;
_drawsBackground = shouldDrawBackground;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
@@ -439,9 +415,9 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
{
if (_textFieldBackgroundColor == aColor)
return;
_textFieldBackgroundColor = aColor;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
@@ -504,31 +480,24 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
_DOMElement.appendChild(element);
window.setTimeout(function()
{
window.setTimeout(function()
{
element.focus();
// Select the text if the textfield became first responder through keyboard interaction
if (!_willBecomeFirstResponderByClick)
[self selectText:self];
_willBecomeFirstResponderByClick = NO;
[self textDidFocus:[CPNotification notificationWithName:CPTextFieldDidFocusNotification object:self userInfo:nil]];
CPTextFieldInputOwner = self;
}, 0.0);
element.value = [self stringValue];
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
CPTextFieldInputIsActive = YES;
if (document.attachEvent)
{
CPTextFieldCachedSelectStartFunction = [[self window] platformWindow]._DOMBodyElement.onselectstart;
CPTextFieldCachedDragFunction = [[self window] platformWindow]._DOMBodyElement.ondrag;
[[self window] platformWindow]._DOMBodyElement.ondrag = function () {};
[[self window] platformWindow]._DOMBodyElement.onselectstart = function () {};
}
@@ -550,15 +519,14 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
var element = [self _inputElement];
if ([self stringValue] !== element.value)
[self _setStringValue:element.value];
[self setObjectValue:element.value];
CPTextFieldInputResigning = YES;
element.blur();
if (!CPTextFieldInputDidBlur)
CPTextFieldBlurFunction();
CPTextFieldInputDidBlur = NO;
CPTextFieldInputResigning = NO;
@@ -569,13 +537,13 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
if (document.attachEvent)
{
[[self window] platformWindow]._DOMBodyElement.ondrag = CPTextFieldCachedDragFunction;
[[self window] platformWindow]._DOMBodyElement.onselectstart = CPTextFieldCachedSelectStartFunction;
CPTextFieldCachedSelectStartFunction = nil;
CPTextFieldCachedDragFunction = nil;
[[self window] platformWindow]._DOMBodyElement.ondrag = CPTextFieldCachedDragFunction;
[[self window] platformWindow]._DOMBodyElement.onselectstart = CPTextFieldCachedSelectStartFunction;
}
#endif
//post CPControlTextDidEndEditingNotification
@@ -605,50 +573,21 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
{
// Don't track! (ever?)
if ([self isEditable] && [self isEnabled])
{
_willBecomeFirstResponderByClick = YES;
[[self window] makeFirstResponder:self];
}
else if ([self isSelectable])
{
if (document.attachEvent)
{
CPTextFieldCachedSelectStartFunction = [[self window] platformWindow]._DOMBodyElement.onselectstart;
CPTextFieldCachedDragFunction = [[self window] platformWindow]._DOMBodyElement.ondrag;
[[self window] platformWindow]._DOMBodyElement.ondrag = function () {};
[[self window] platformWindow]._DOMBodyElement.onselectstart = function () {};
}
return [[[anEvent window] platformWindow] _propagateCurrentDOMEvent:YES];
}
return [[self window] makeFirstResponder:self];
else
return [[self nextResponder] mouseDown:anEvent];
}
- (void)mouseUp:(CPEvent)anEvent
{
if (![self isSelectable] && (![self isEditable] || ![self isEnabled]))
if (![self isEditable] || ![self isEnabled])
[[self nextResponder] mouseUp:anEvent];
else if ([self isSelectable])
{
if (document.attachEvent)
{
[[self window] platformWindow]._DOMBodyElement.ondrag = CPTextFieldCachedDragFunction;
[[self window] platformWindow]._DOMBodyElement.onselectstart = CPTextFieldCachedSelectStartFunction;
CPTextFieldCachedSelectStartFunction = nil
CPTextFieldCachedDragFunction = nil;
}
return [[[anEvent window] platformWindow] _propagateCurrentDOMEvent:YES];
}
}
- (void)mouseDragged:(CPEvent)anEvent
{
if (![self isSelectable] && (![self isEditable] || ![self isEnabled]))
if (![self isEditable] || ![self isEnabled])
[[self nextResponder] mouseDragged:anEvent];
else if ([self isSelectable])
return [[[anEvent window] platformWindow] _propagateCurrentDOMEvent:YES];
}
- (void)keyUp:(CPEvent)anEvent
@@ -685,16 +624,29 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
[[[self window] platformWindow] _propagateCurrentDOMEvent:NO];
}
else if ([anEvent keyCode] === CPTabKeyCode)
{
if ([anEvent modifierFlags] & CPShiftKeyMask)
[[self window] selectPreviousKeyView:self];
else
[[self window] selectNextKeyView:self];
if ([[[self window] firstResponder] respondsToSelector:@selector(selectText:)])
[[[self window] firstResponder] selectText:self];
[[[self window] platformWindow] _propagateCurrentDOMEvent:NO];
}
else
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
}
- (void)textDidBlur:(CPNotification)note
{
// this looks to prevent false propagation of notifications for other objects
if ([note object] != self)
//this looks to prevent false propagation of notifications for other objects
if([note object] != self)
return;
[[CPNotificationCenter defaultCenter] postNotification:note];
@@ -702,22 +654,13 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
- (void)textDidFocus:(CPNotification)note
{
// this looks to prevent false propagation of notifications for other objects
if ([note object] != self)
//this looks to prevent false propagation of notifications for other objects
if([note object] != self)
return;
[[CPNotificationCenter defaultCenter] postNotification:note];
}
- (void)sendAction:(SEL)anAction to:(id)anObject
{
// Don't reverse set our empty value
if (!_currentValueIsPlaceholder)
[self _reverseSetBinding];
[CPApp sendAction:anAction to:anObject from:self];
}
/*!
Returns the string the text field.
*/
@@ -740,7 +683,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
- (void)setObjectValue:(id)aValue
{
[super setObjectValue:aValue];
#if PLATFORM(DOM)
if (CPTextFieldInputOwner === self || [[self window] firstResponder] === self)
@@ -764,11 +707,11 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
Sets a placeholder string for the receiver. The placeholder is displayed until editing begins,
and after editing ends, if the text field has an empty string value
*/
- (void)setPlaceholderString:(CPString)aStringValue
-(void)setPlaceholderString:(CPString)aStringValue
{
if (_placeholderString === aStringValue)
return;
_placeholderString = aStringValue;
// Only update things if we need to show the placeholder
@@ -787,101 +730,43 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
return _placeholderString;
}
- (void)_setCurrentValueIsPlaceholder:(BOOL)isPlaceholder
{
// The initial _currentValueIsPlaceholder is null so convert it to NO for comparison purposes.
if (!!_currentValueIsPlaceholder === isPlaceholder)
return;
if (isPlaceholder)
{
// Save the original placeholder value so we can restore it later
// Only do this if the placeholder is not already overridden because the bindings logic might call this method
// several times and we don't want the bindings placeholder to ever become the original placeholder
if (!_currentValueIsPlaceholder)
_originalPlaceholderString = [self placeholderString];
// Set the current string value as the current placeholder and clear the string value
[self setPlaceholderString:[self stringValue]];
[self setStringValue:@""];
}
else
{
// Restore the original placeholder, the actual textfield value is already correct
// because it was set using setValue:forKey:
[self setPlaceholderString:_originalPlaceholderString];
}
_currentValueIsPlaceholder = isPlaceholder;
}
/*!
For non-bezeled text fields (typically a label), sizeToFit has two behaviors, depending
on the line break mode of the receiver.
For non-bezeled receivers with a non-wrapping line break mode, sizeToFit will change the frame of the
receiver to perfectly fit the current text in stringValue in the current font, respecting
the current theme value for content-inset. For receivers with a wrapping line break mode,
sizeToFit will wrap the text within the current width (respecting the current content-inset),
so it will ONLY change the HEIGHT.
For bezeled text fields (typically editable fields), sizeToFit will ONLY change the HEIGHT
of the text field. It will not change the width of the text field. sizeToFit will attempt to
change the height to fit a single line of text, respecting the current theme values for min-size,
max-size and content-inset.
Size to fit has two behavior, depending on if the receiver is an editable text field or not.
For non-editable text fields (typically, a label), sizeToFit will change the frame of the
receiver to perfectly fit the current text in stringValue in the current font, and respecting
the current theme values for content-inset, min-size, and max-size.
For editable text fields, sizeToFit will ONLY change the HEIGHT of the text field. It will not
change the width of the text field. You can use setFrameSize: with the current height to set the
width, and you can get the size of a string with [CPString sizeWithFont:].
The logic behind this decision is that most of the time you do not know what content will be placed
in a bezeled text field, so you want to just choose a fixed width and leave it at that size.
in an editable text field, so you want to just choose a fixed width and leave it at that size.
However, since you don't know how tall it needs to be if you change the font, sizeToFit will still be
useful for making the textfield an appropriate height.
*/
- (void)sizeToFit
{
[self setFrameSize:[self _minimumFrameSize]];
}
- (CGSize)_minimumFrameSize
{
var frameSize = [self frameSize],
var size = [([self stringValue] || " ") sizeWithFont:[self currentValueForThemeAttribute:@"font"]],
contentInset = [self currentValueForThemeAttribute:@"content-inset"],
minSize = [self currentValueForThemeAttribute:@"min-size"],
maxSize = [self currentValueForThemeAttribute:@"max-size"],
lineBreakMode = [self lineBreakMode],
text = ([self stringValue] || @" "),
textSize = _CGSizeMakeCopy(frameSize),
font = [self currentValueForThemeAttribute:@"font"];
maxSize = [self currentValueForThemeAttribute:@"max-size"];
textSize.width -= contentInset.left + contentInset.right;
textSize.height -= contentInset.top + contentInset.bottom;
size.width = MAX(size.width + contentInset.left + contentInset.right, minSize.width);
size.height = MAX(size.height + contentInset.top + contentInset.bottom, minSize.height);
if (frameSize.width !== 0 &&
![self isBezeled] &&
(lineBreakMode === CPLineBreakByWordWrapping || lineBreakMode === CPLineBreakByCharWrapping))
{
textSize = [text sizeWithFont:font inWidth:textSize.width];
}
else
textSize = [text sizeWithFont:font];
if (maxSize.width >= 0.0)
size.width = MIN(size.width, maxSize.width);
frameSize.height = textSize.height + contentInset.top + contentInset.bottom;
if (maxSize.height >= 0.0)
size.height = MIN(size.height, maxSize.height);
if ([self isBezeled])
{
frameSize.height = MAX(frameSize.height, minSize.height);
if ([self isEditable])
size.width = CGRectGetWidth([self frame]);
if (maxSize.width > 0.0)
frameSize.width = MIN(frameSize.width, maxSize.width);
if (maxSize.height > 0.0)
frameSize.height = MIN(frameSize.height, maxSize.height);
}
else
frameSize.width = textSize.width + contentInset.left + contentInset.right;
frameSize.width = MAX(frameSize.width, minSize.width);
return frameSize;
[self setFrameSize:size];
}
/*!
@@ -891,13 +776,16 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
{
#if PLATFORM(DOM)
var element = [self _inputElement];
if (([self isEditable] || [self isSelectable]))
{
if ([[self window] firstResponder] === self)
window.setTimeout(function() { element.select(); }, 0);
else if ([self window] !== nil && [[self window] makeFirstResponder:self])
else
{
[[self window] makeFirstResponder:self];
window.setTimeout(function() {[self selectText:sender];}, 0);
}
}
#endif
}
@@ -946,7 +834,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
newValue = [stringValue stringByReplacingCharactersInRange:selectedRange withString:pasteString];
[self setStringValue:newValue];
[self setSelectedRange:CPMakeRange(selectedRange.location + pasteString.length, 0)];
[self setSelectedRange:CPMakeRange(selectedRange.location+pasteString.length, 0)];
}
}
@@ -956,14 +844,14 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
return CPMakeRange(0, 0);
// we wrap this in try catch because firefox will throw an exception in certain instances
try
try
{
var inputElement = [self _inputElement],
selectionStart = inputElement.selectionStart,
selectionEnd = inputElement.selectionEnd;
if ([selectionStart isKindOfClass:CPNumber])
return CPMakeRange(selectionStart, selectionEnd - selectionStart);
return CPMakeRange(selectionStart, selectionEnd - selectionStart);
// browsers which don't support selectionStart/selectionEnd (aka IE).
var theDocument = inputElement.ownerDocument || inputElement.document,
@@ -975,8 +863,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
range.setEndPoint('EndToStart', selectionRange);
return CPMakeRange(range.text.length, selectionRange.text.length);
}
}
catch (e)
}
catch (e)
{
// fall through to the return
}
@@ -991,7 +879,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
var inputElement = [self _inputElement];
try
try
{
if ([inputElement.selectionStart isKindOfClass:CPNumber])
{
@@ -1004,7 +892,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
var theDocument = inputElement.ownerDocument || inputElement.document,
existingRange = theDocument.selection.createRange(),
range = inputElement.createTextRange();
if (range.inRange(existingRange))
{
range.collapse(true);
@@ -1039,7 +927,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
- (void)setDelegate:(id)aDelegate
{
var defaultCenter = [CPNotificationCenter defaultCenter];
//unsubscribe the existing delegate if it exists
if (_delegate)
{
@@ -1049,24 +937,24 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
[defaultCenter removeObserver:_delegate name:CPTextFieldDidFocusNotification object:self];
[defaultCenter removeObserver:_delegate name:CPTextFieldDidBlurNotification object:self];
}
_delegate = aDelegate;
if ([_delegate respondsToSelector:@selector(controlTextDidBeginEditing:)])
[defaultCenter
addObserver:_delegate
selector:@selector(controlTextDidBeginEditing:)
name:CPControlTextDidBeginEditingNotification
object:self];
if ([_delegate respondsToSelector:@selector(controlTextDidChange:)])
[defaultCenter
addObserver:_delegate
selector:@selector(controlTextDidChange:)
name:CPControlTextDidChangeNotification
object:self];
if ([_delegate respondsToSelector:@selector(controlTextDidEndEditing:)])
[defaultCenter
addObserver:_delegate
@@ -1097,15 +985,15 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
- (CGRect)contentRectForBounds:(CGRect)bounds
{
var contentInset = [self currentValueForThemeAttribute:@"content-inset"];
if (!contentInset)
return bounds;
bounds.origin.x += contentInset.left;
bounds.origin.y += contentInset.top;
bounds.size.width -= contentInset.left + contentInset.right;
bounds.size.height -= contentInset.top + contentInset.bottom;
return bounds;
}
@@ -1115,12 +1003,12 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
if (_CGInsetIsEmpty(bezelInset))
return bounds;
bounds.origin.x += bezelInset.left;
bounds.origin.y += bezelInset.top;
bounds.size.width -= bezelInset.left + bezelInset.right;
bounds.size.height -= bezelInset.top + bezelInset.bottom;
return bounds;
}
@@ -1128,10 +1016,10 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
{
if (aName === "bezel-view")
return [self bezelRectForBounds:[self bounds]];
else if (aName === "content-view")
return [self contentRectForBounds:[self bounds]];
return [super rectForEphemeralSubviewNamed:aName];
}
@@ -1142,19 +1030,19 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
[view setHitTests:NO];
return view;
}
else
{
var view = [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
//[view setImagePosition:CPNoImage];
[view setHitTests:NO];
return view;
}
return [super createEphemeralSubviewNamed:aName];
}
@@ -1163,10 +1051,10 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
var bezelView = [self layoutEphemeralSubviewNamed:@"bezel-view"
positioned:CPWindowBelow
relativeToEphemeralSubviewNamed:@"content-view"];
if (bezelView)
[bezelView setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]];
var contentView = [self layoutEphemeralSubviewNamed:@"content-view"
positioned:CPWindowAbove
relativeToEphemeralSubviewNamed:@"bezel-view"];
@@ -1176,7 +1064,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
[contentView setHidden:[self hasThemeState:CPThemeStateEditing]];
var string = "";
if ([self hasThemeState:CPTextFieldStatePlaceholder])
string = [self placeholderString];
else
@@ -1223,7 +1111,7 @@ var secureStringForString = function(aString)
if (!aString)
return "";
return Array(aString.length + 1).join(CPSecureTextFieldCharacter);
return Array(aString.length+1).join(CPSecureTextFieldCharacter);
}
@@ -1234,7 +1122,6 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
CPTextFieldBezelStyleKey = "CPTextFieldBezelStyleKey",
CPTextFieldDrawsBackgroundKey = "CPTextFieldDrawsBackgroundKey",
CPTextFieldLineBreakModeKey = "CPTextFieldLineBreakModeKey",
CPTextFieldAlignmentKey = "CPTextFieldAlignmentKey",
CPTextFieldBackgroundColorKey = "CPTextFieldBackgroundColorKey",
CPTextFieldPlaceholderStringKey = "CPTextFieldPlaceholderStringKey";
@@ -1248,7 +1135,7 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
[self setEditable:[aCoder decodeBoolForKey:CPTextFieldIsEditableKey]];
@@ -1258,24 +1145,9 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
[self setTextFieldBackgroundColor:[aCoder decodeObjectForKey:CPTextFieldBackgroundColorKey]];
[self setLineBreakMode:[aCoder decodeIntForKey:CPTextFieldLineBreakModeKey]];
[self setAlignment:[aCoder decodeIntForKey:CPTextFieldAlignmentKey]];
[self setPlaceholderString:[aCoder decodeObjectForKey:CPTextFieldPlaceholderStringKey]];
// Make sure the frame is big enough
var minSize = [self _minimumFrameSize];
minSize.width = MAX(CGRectGetWidth([self frame]), minSize.width);
minSize.height = MAX(CGRectGetHeight([self frame]), minSize.height);
// Only size multiline bezeled textfields if it's to small to fit the content
if ([self isBezeled])
if ([self lineBreakMode] === CPLineBreakByCharWrapping || [self lineBreakMode] == CPLineBreakByWordWrapping)
minSize.height = MAX(CGRectGetHeight([self frame]), minSize.height);
[self setFrameSize:minSize];
}
return self;
}
@@ -1286,17 +1158,14 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeBool:_isEditable forKey:CPTextFieldIsEditableKey];
[aCoder encodeBool:_isSelectable forKey:CPTextFieldIsSelectableKey];
[aCoder encodeBool:_drawsBackground forKey:CPTextFieldDrawsBackgroundKey];
[aCoder encodeObject:_textFieldBackgroundColor forKey:CPTextFieldBackgroundColorKey];
[aCoder encodeInt:[self lineBreakMode] forKey:CPTextFieldLineBreakModeKey];
[aCoder encodeInt:[self alignment] forKey:CPTextFieldAlignmentKey];
[aCoder encodeObject:_placeholderString forKey:CPTextFieldPlaceholderStringKey];
}
+20 -188
View File
@@ -24,10 +24,8 @@
@import <Foundation/CPString.j>
@import <Foundation/CPKeyedUnarchiver.j>
var CPThemesByName = { },
CPThemeDefaultTheme = nil,
CPThemeDefaultHudTheme = nil;
var CPThemesByName = { },
CPThemeDefaultTheme = nil;
/*!
@@ -50,27 +48,6 @@ var CPThemesByName = { },
return CPThemeDefaultTheme;
}
/*!
Set the default HUD theme. If set to nil, the default described in defaultHudTheme
will be used.
*/
+ (void)setDefaultHudTheme:(CPTheme)aTheme
{
CPThemeDefaultHudTheme = aTheme;
}
/*!
The default HUD theme is (sometimes) used for windows with the CPHUDBackgroundWindowMask
style mask. The default is theme with the name of the default theme with -HUD appended
at the end.
*/
+ (CPTheme)defaultHudTheme
{
if (!CPThemeDefaultHudTheme)
CPThemeDefaultHudTheme = [CPTheme themeNamed:[[self defaultTheme] name] + "-HUD"];
return CPThemeDefaultHudTheme;
}
+ (CPTheme)themeNamed:(CPString)aName
{
return CPThemesByName[aName];
@@ -96,110 +73,9 @@ var CPThemesByName = { },
return _name;
}
/*!
Returns an array of names of themed classes defined in this theme, as found in its
ThemeDescriptors.j file.
NOTE: The names are not class names (such as "CPButton"), but the names returned
by the class' +defaultThemeClass method. For example, the name for CPCheckBox is "check-box",
as defined in CPCheckBox::themeClass.
*/
- (CPArray)classNames
- (_CPThemeAttribute)_attributeWithName:(CPString)aName forClass:(CPString)aClass
{
return [_attributes allKeys];
}
/*!
Returns a dictionary of all theme attributes defined for the given class, as found in the
theme's ThemeDescriptors.j file. The keys of the dictionary are attribute names, and the values
are instances of _CPThemeAttribute.
For a description of valid values for \c aClass, see \ref attributeNamesForClass:.
@param aClass The themed class whose attributes you want to retrieve
@return A dictionary of attributes or nil
*/
- (CPDictionary)attributesForClass:(id)aClass
{
if (!aClass)
return nil;
var className = nil;
if ([aClass isKindOfClass:[CPString class]])
{
// See if it is a class name
var theClass = CPClassFromString(aClass);
if (theClass)
aClass = theClass;
else
className = aClass;
}
if (!className)
{
if ([aClass isKindOfClass:[CPView class]])
{
if ([aClass respondsToSelector:@selector(defaultThemeClass)])
className = [aClass defaultThemeClass];
else if ([aClass respondsToSelector:@selector(themeClass)])
{
CPLog.warn(@"%@ themeClass is deprecated in favor of defaultThemeClass",CPStringFromClass([anObject class]));
className = [aClass themeClass];
}
else
return nil;
}
else
[CPException raise:CPInvalidArgumentException reason:@"aClass must be a class object or a string."];
}
return [_attributes objectForKey:className];
}
/*!
Returns an array of names of all theme attributes defined for the given class, as found in the
theme's ThemeDescriptors.j file.
The \c aClass parameter can be one of the following:
- A class instance, for example the result of [CPCheckBox class]. The class must be a subclass
of CPView.
- A class name, for example "CPCheckBox".
- A themed class name, for example "check-box".
If \c aClass does not refer to a themed class in this theme, nil is returned.
@param aClass The themed class whose attributes you want to retrieve
@return An array of attribute names or nil
*/
- (CPDictionary)attributeNamesForClass:(id)aClass
{
var attributes = [self attributesForClass:aClass];
if (attributes)
return [attributes allKeys];
else
return [CPArray array];
}
/*!
Returns a theme attribute defined for the given class, as found in the
theme's ThemeDescriptors.j file.
\c aName should be the attribute name as you would pass to the method
CPView::valueForThemeAttribute:.
For a description of valid values for \c aClass, see \ref attributeNamesForClass:.
@param aName The name of the attribute you want to retrieve
@param aClass The themed class in which to look for the attribute
@return An instance of _CPThemeAttribute or nil
*/
- (_CPThemeAttribute)attributeWithName:(CPString)aName forClass:(id)aClass
{
var attributes = [self attributesForClass:aClass];
var attributes = [_attributes objectForKey:aClass];
if (!attributes)
return nil;
@@ -207,53 +83,12 @@ var CPThemesByName = { },
return [attributes objectForKey:aName];
}
/*!
Returns the value for a theme attribute in its normal state, as defined for the given class
in the theme's ThemeDescriptors.j file.
\c aName should be the attribute name as you would pass to the method
CPView::valueForThemeAttribute:.
For a description of valid values for \c aClass, see \ref attributeNamesForClass:.
@param aName The name of the attribute whose value you want to retrieve
@param aClass The themed class in which to look for the attribute
@return A value or nil
*/
- (id)valueForAttributeWithName:(CPString)aName forClass:(id)aClass
{
return [self valueForAttributeWithName:aName inState:CPThemeStateNormal forClass:aClass];
}
/*!
Returns the value for a theme attribute in a given state, as defined for the given class
in the theme's ThemeDescriptors.j file. This is the equivalent of the method
CPView::valueForThemeAttribute:inState:, but retrieves the value from the theme definition as
opposed to a single view's current theme state.
For a description of valid values for \c aClass, see \ref attributeNamesForClass:.
@param aName The name of the attribute whose value you want to retrieve
@param aState The state qualifier for the attribute
@param aClass The themed class in which to look for the attribute
@return A value or nil
*/
- (id)valueForAttributeWithName:(CPString)aName inState:(CPThemeState)aState forClass:(id)aClass
{
var attribute = [self attributeWithName:aName forClass:aClass];
if (!attribute)
return nil;
return [attribute valueForState:aState];
}
- (void)takeThemeFromObject:(id)anObject
{
var attributes = [anObject _themeAttributeDictionary],
attributeName = nil,
attributeNames = [attributes keyEnumerator],
objectThemeClass = [anObject themeClass];
objectThemeClass = [[anObject class] themeClass];
while (attributeName = [attributeNames nextObject])
[self _recordAttribute:[attributes objectForKey:attributeName] forClass:objectThemeClass];
@@ -407,9 +242,6 @@ CPThemeStateNormal = CPThemeStates["normal"] = 0;
CPThemeStateDisabled = CPThemeState("disabled");
CPThemeStateHighlighted = CPThemeState("highlighted");
CPThemeStateSelected = CPThemeState("selected");
CPThemeStateTableDataView = CPThemeState("tableDataView");
CPThemeStateSelectedDataView = CPThemeStateSelectedTableDataView = CPThemeState("selectedTableDataView");
CPThemeStateGroupRow = CPThemeState("CPThemeStateGroupRow");
CPThemeStateBezeled = CPThemeState("bezeled");
CPThemeStateBordered = CPThemeState("bordered");
CPThemeStateEditable = CPThemeState("editable");
@@ -422,10 +254,10 @@ CPThemeStateCircular = CPThemeState("circular");
{
CPString _name;
id _defaultValue;
CPDictionary _values @accessors(readonly, getter=values);
CPDictionary _values;
JSObject _cache;
_CPThemeAttribute _parentAttribute;
CPThemeAttribute _parentAttribute;
}
- (id)initWithName:(CPString)aName defaultValue:(id)aDefaultValue
@@ -546,7 +378,7 @@ CPThemeStateCircular = CPThemeState("circular");
return value;
}
- (void)setParentAttribute:(_CPThemeAttribute)anAttribute
- (void)setParentAttribute:(CPThemeAttribute)anAttribute
{
if (_parentAttribute === anAttribute)
return;
@@ -555,7 +387,7 @@ CPThemeStateCircular = CPThemeState("circular");
_parentAttribute = anAttribute;
}
- (_CPThemeAttribute)attributeMergedWithAttribute:(_CPThemeAttribute)anAttribute
- (CPThemeAttribute)attributeMergedWithAttribute:(_CPThemeAttribute)anAttribute
{
var mergedAttribute = [[_CPThemeAttribute alloc] initWithName:_name defaultValue:_defaultValue];
@@ -640,15 +472,15 @@ CPThemeStateCircular = CPThemeState("circular");
@end
var cachedNumberOfOnes = [ 0 /*000000*/, 1 /*000001*/, 1 /*000010*/, 2 /*000011*/, 1 /*000100*/, 2 /*000101*/, 2 /*000110*/,
3 /*000111*/, 1 /*001000*/, 2 /*001001*/, 2 /*001010*/, 3 /*001011*/, 2 /*001100*/, 3 /*001101*/,
3 /*001110*/, 4 /*001111*/, 1 /*010000*/, 2 /*010001*/, 2 /*010010*/, 3 /*010011*/, 2 /*010100*/,
3 /*010101*/, 3 /*010110*/, 4 /*010111*/, 2 /*011000*/, 3 /*011001*/, 3 /*011010*/, 4 /*011011*/,
3 /*011100*/, 4 /*011101*/, 4 /*011110*/, 5 /*011111*/, 1 /*100000*/, 2 /*100001*/, 2 /*100010*/,
3 /*100011*/, 2 /*100100*/, 3 /*100101*/, 3 /*100110*/, 4 /*100111*/, 2 /*101000*/, 3 /*101001*/,
3 /*101010*/, 4 /*101011*/, 3 /*101100*/, 4 /*101101*/, 4 /*101110*/, 5 /*101111*/, 2 /*110000*/,
3 /*110001*/, 3 /*110010*/, 4 /*110011*/, 3 /*110100*/, 4 /*110101*/, 4 /*110110*/, 5 /*110111*/,
3 /*111000*/, 4 /*111001*/, 4 /*111010*/, 5 /*111011*/, 4 /*111100*/, 5 /*111101*/, 5 /*111110*/,
var cachedNumberOfOnes = [ 0 /*000000*/, 1 /*000001*/, 1 /*000010*/, 2 /*000011*/, 1 /*000100*/, 2 /*000101*/, 2 /*000110*/,
3 /*000111*/, 1 /*001000*/, 2 /*001001*/, 2 /*001010*/, 3 /*001011*/, 2 /*001100*/, 3 /*001101*/,
3 /*001110*/, 4 /*001111*/, 1 /*010000*/, 2 /*010001*/, 2 /*010010*/, 3 /*010011*/, 2 /*010100*/,
3 /*010101*/, 3 /*010110*/, 4 /*010111*/, 2 /*011000*/, 3 /*011001*/, 3 /*011010*/, 4 /*011011*/,
3 /*011100*/, 4 /*011101*/, 4 /*011110*/, 5 /*011111*/, 1 /*100000*/, 2 /*100001*/, 2 /*100010*/,
3 /*100011*/, 2 /*100100*/, 3 /*100101*/, 3 /*100110*/, 4 /*100111*/, 2 /*101000*/, 3 /*101001*/,
3 /*101010*/, 4 /*101011*/, 3 /*101100*/, 4 /*101101*/, 4 /*101110*/, 5 /*101111*/, 2 /*110000*/,
3 /*110001*/, 3 /*110010*/, 4 /*110011*/, 3 /*110100*/, 4 /*110101*/, 4 /*110110*/, 5 /*110111*/,
3 /*111000*/, 4 /*111001*/, 4 /*111010*/, 5 /*111011*/, 4 /*111100*/, 5 /*111101*/, 5 /*111110*/,
6 /*111111*/ ];
var numberOfOnes = function(aNumber)
@@ -719,7 +551,7 @@ function CPThemeAttributeDecode(aCoder, anAttributeName, aDefaultValue, aTheme,
}
if (aTheme && aClass)
[attribute setParentAttribute:[aTheme attributeWithName:anAttributeName forClass:aClass]];
[attribute setParentAttribute:[aTheme _attributeWithName:anAttributeName forClass:aClass]];
return attribute;
}
@@ -753,4 +585,4 @@ for (i = 0;i < Math.pow(2,6);++i)
}
print(str+']');
*/
*/
+10 -34
View File
@@ -22,10 +22,9 @@
@import <Foundation/CPObject.j>
@import "CPTheme.j"
@import "_CPCibCustomResource.j"
@import "_CPCibKeyedUnarchiver.j"
@import <AppKit/CPTheme.j>
@import <AppKit/_CPCibCustomResource.j>
@import <AppKit/_CPCibKeyedUnarchiver.j>
/*!
@ingroup appkit
@@ -34,60 +33,37 @@
@implementation CPThemeBlend : CPObject
{
CPBundle _bundle;
CPArray _themes;
CPArray _themes @accessors(readonly, getter=themes);
id _loadDelegate;
}
- (id)initWithContentsOfURL:(CPURL)aURL
{
self = [super init];
if (self)
{
_bundle = [[CPBundle alloc] initWithPath:aURL];
}
return self;
}
/*!
Returns an array of names of the keyed theme archives that make up this blend.
Each item in the array will have the extension ".keyedtheme".
*/
- (CPArray)themes
{
return _themes;
}
/*!
Returns an array of names of the themes that make up this blend.
*/
- (CPArray)themeNames
{
var names = [];
for (var i = 0; i < _themes.length; ++i)
names.push(_themes[i].substring(0, _themes[i].indexOf(".keyedtheme")));
return names;
}
- (void)loadWithDelegate:(id)aDelegate
{
_loadDelegate = aDelegate;
[_bundle loadWithDelegate:self];
}
- (void)bundleDidFinishLoading:(CPBundle)aBundle
{
_themes = [_bundle objectForInfoDictionaryKey:@"CPKeyedThemes"];
var count = _themes.length;
var themes = [_bundle objectForInfoDictionaryKey:@"CPKeyedThemes"],
count = themes.length;
while (count--)
{
var path = [aBundle pathForResource:_themes[count]],
var path = [aBundle pathForResource:themes[count]],
unarchiver = [[_CPThemeKeyedUnarchiver alloc]
initForReadingWithData:[[CPURL URLWithString:path] staticResourceData]
bundle:_bundle];
File diff suppressed because it is too large Load Diff
+10 -21
View File
@@ -28,6 +28,8 @@
@import "CPPopUpButton.j"
@import "CPToolbarItem.j"
#include "CoreGraphics/CGGeometry.h"
/*
@global
@@ -327,11 +329,7 @@ var CPToolbarConfigurationsByIdentifier = nil;
return _itemsSortedByVisibilityPriority;
}
/*!
Validates the visible toolbar items by sending a validate message to
each visible toolbar item.
*/
- (void)validateVisibleItems
- (void)validateVisibleToolbarItems
{
var toolbarItems = [self visibleItems],
count = [toolbarItems count];
@@ -468,14 +466,7 @@ var CPToolbarIdentifierKey = @"CPToolbarIdentifierKey",
// specified, it will be read later and the resulting call to -setDelegate:
// will cause -_reloadToolbarItems] to run again :-(
// FIXME: Can we make this better?
// Do this at the end of the run loop to allow all the cib-stuff to
// finish (establishing connections, etc.).
[[CPRunLoop currentRunLoop]
performSelector:@selector(_reloadToolbarItems)
target:self
argument:nil
order:0 modes:[CPDefaultRunLoopMode]];
[self _reloadToolbarItems];
}
return self;
@@ -568,7 +559,6 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
[_additionalItemsButton setImagePosition:CPImageOnly];
[[_additionalItemsButton menu] setShowsStateColumn:NO];
[[_additionalItemsButton menu] setAutoenablesItems:NO];
[_additionalItemsButton setAlternateImage:_CPToolbarViewExtraItemsAlternateImage];
}
@@ -799,13 +789,14 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
hasNonSeparatorItem = YES;
var menuItem = [[CPMenuItem alloc] initWithTitle:[item label] action:[item action] keyEquivalent:nil];
[_additionalItemsButton addItemWithTitle:[item label]];
var menuItem = [_additionalItemsButton itemArray][index + 1];
[menuItem setImage:[item image]];
[menuItem setTarget:[item target]];
[menuItem setEnabled:[item isEnabled]];
[_additionalItemsButton addItem:menuItem];
[menuItem setTarget:[item target]];
[menuItem setAction:[item action]];
}
}
else
@@ -979,7 +970,7 @@ var TOP_MARGIN = 5.0,
{
_imageView = [[CPImageView alloc] initWithFrame:[self bounds]];
[_imageView setImageScaling:CPScaleProportionally];
[_imageView setImageScaling:CPScaleNone];
[self addSubview:_imageView];
}
@@ -1060,8 +1051,6 @@ var TOP_MARGIN = 5.0,
[_imageView setAlphaValue:0.5];
[_labelField setAlphaValue:0.5];
}
[_toolbar tile];
}
- (CPColor)FIXME_labelColor
+2 -3
View File
@@ -23,9 +23,8 @@
@import <Foundation/CPObject.j>
@import <Foundation/CPString.j>
@import "CPImage.j"
@import "CPView.j"
@import <AppKit/CPImage.j>
@import <AppKit/CPView.j>
CPToolbarItemVisibilityPriorityStandard = 0;
CPToolbarItemVisibilityPriorityLow = -1000;
-197
View File
@@ -87,40 +87,6 @@
[_childNodes[count] sortWithSortDescriptors:sortDescriptors recursively:YES];
}
- (CPEnumerator)preOrder
{
return [_CPTreeNodeEnumerator enumeratorWithTreeNode:self order:_CPTreeNodeEnumeratorPreOrder];
}
- (CPEnumerator)inOrder
{
return [_CPTreeNodeEnumerator enumeratorWithTreeNode:self order:_CPTreeNodeEnumeratorInOrder];
}
- (CPEnumerator)postOrder
{
return [_CPTreeNodeEnumerator enumeratorWithTreeNode:self order:_CPTreeNodeEnumeratorPostOrder];
}
- (CPEnumerator)levelOrder
{
return [_CPTreeNodeEnumerator enumeratorWithTreeNode:self order:_CPTreeNodeEnumeratorLevelOrder];
}
- (int)countByEnumeratingWithState:(id)aState objects:(id)objects count:(id)aCount
{
if (aState.state !== 0)
return 0;
// FIXME: Change this to inorder when implemented?
var count = [[self preOrder] countByEnumeratingWithState:aState objects:objects count:aCount];
// Dangerous?
aState.state = YES;
return count;
}
@end
var CPTreeNodeRepresentedObjectKey = @"CPTreeNodeRepresentedObjectKey",
@@ -151,166 +117,3 @@ var CPTreeNodeRepresentedObjectKey = @"CPTreeNodeRepresentedObjectKey",
}
@end
var _CPTreeNodeEnumeratorPreOrder = 0,
_CPTreeNodeEnumeratorInOrder = 1,
_CPTreeNodeEnumeratorPostOrder = 2,
_CPTreeNodeEnumeratorLevelOrder = 3;
@implementation _CPTreeNodeEnumerator : CPEnumerator
{
int _order;
Object _state;
CPTreeNode _treeNode;
}
+ (_CPTreeNodeEnumerator)enumeratorWithTreeNode:(CPTreeNode)aTreeNode order:(int)anOrder
{
return [[self alloc] initWithTreeNode:aTreeNode order:anOrder];
}
- (id)initWithTreeNode:(CPTreeNode)aTreeNode order:(int)anOrder
{
self = [super init];
if (self)
{
_order = anOrder
_state = [self _newState];
_treeNode = aTreeNode;
}
return self;
}
- (id)_newState
{
return { stack:[_treeNode], visited:[CPSet set] };
}
- (id)_preOrderFromState:(Object)state allObjects:(BOOL)shouldReturnAllObjects
{
var stack = state.stack;
if (stack.length <= 0)
return nil;
if (shouldReturnAllObjects)
var allObjects = [];
while (stack.length)
{
var currentNode = stack.pop(),
childNodes = currentNode._childNodes,
count = childNodes.length;
while (count--)
stack.push(childNodes[count]);
if (shouldReturnAllObjects)
allObjects.push(currentNode);
else
return currentNode;
}
return allObjects;
}
- (id)_inOrderFromState:(Object)state allObjects:(BOOL)shouldReturnAllObjects
{
// Implement.
}
- (id)_postOrderFromState:(Object)state allObjects:(BOOL)shouldReturnAllObjects
{
var stack = state.stack;
if (stack.length <= 0)
return nil;
var visited = state.visited;
if (shouldReturnAllObjects)
var allObjects = [];
while (stack.length)
{
var currentNode = [stack lastObject],
childNodes = currentNode._childNodes,
originalCount = stack.length,
count = childNodes.length;
while (count--)
{
var treeNode = childNodes[count];
if ([visited containsObject:treeNode])
continue;
else
stack.push(treeNode);
}
if (originalCount === stack.length)
{
[visited addObject:currentNode];
if (shouldReturnAllObjects)
allObjects.push(stack.pop());
else
return stack.pop();
}
}
return allObjects;
}
- (id)_levelOrderFromState:(Object)state allObjects:(BOOL)shouldReturnAllObjects
{
// Implement.
}
- (id)nextObject
{
if (_order === _CPTreeNodeEnumeratorPreOrder)
return [self _preOrderFromState:[self _newState] allObjects:NO];
else if (_order === _CPTreeNodeEnumeratorInOrder)
return [self _inOrderFromState:[self _newState] allObjects:NO];
else if (_order === _CPTreeNodeEnumeratorPostOrder)
return [self _postOrderFromState:[self _newState] allObjects:NO];
//else if (_order === _CPTreeNodeEnumeratorLevelOrder)
return [self _levelOrderFromState:[self _newState] allObjects:NO];
}
- (CPArray)allObjects
{
if (_order === _CPTreeNodeEnumeratorPreOrder)
return [self _preOrderFromState:[self _newState] allObjects:YES];
else if (_order === _CPTreeNodeEnumeratorInOrder)
return [self _inOrderFromState:[self _newState] allObjects:YES];
else if (_order === _CPTreeNodeEnumeratorPostOrder)
return [self _postOrderFromState:[self _newState] allObjects:YES];
//else if (_order === _CPTreeNodeEnumeratorLevelOrder)
return [self _levelOrderFromState:[self _newState] allObjects:NO];
}
- (int)countByEnumeratingWithState:(id)aState objects:(id)objects count:(id)aCount
{
if (aState.state !== 0)
return 0;
var count = [[self allObjects] countByEnumeratingWithState:aState objects:objects count:aCount];
// Dangerous?
aState.state = YES;
return count;
}
@end
+195 -281
View File
File diff suppressed because it is too large Load Diff
+12 -13
View File
@@ -1,5 +1,5 @@
/*
* CPViewAnimation.j
* CPFlashView.j
* AppKit
*
* Created by Klaas Pieter Annema on September 3, 2009.
@@ -20,8 +20,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPAnimation.j"
@import <AppKit/CPAnimation.j>
CPViewAnimationTargetKey = @"CPViewAnimationTarget";
CPViewAnimationStartFrameKey = @"CPViewAnimationStartFrame";
@@ -70,7 +69,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOut";
[super startAnimation];
}
- (void)setCurrentProgress:(CPAnimationProgress)progress
- (void)setCurrentProgress:(NSAnimationProgress)progress
{
[super setCurrentProgress:progress];
@@ -78,17 +77,17 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOut";
while (animationIndex--)
{
var dictionary = [_viewAnimations objectAtIndex:animationIndex],
view = [self _targetView:dictionary],
startFrame = [self _startFrame:dictionary],
endFrame = [self _endFrame:dictionary],
differenceFrame = _CGRectMakeZero();
view = [self _targetView:dictionary]
startFrame = [self _startFrame:dictionary]
endFrame = [self _endFrame:dictionary]
differenceFrame = CPRectMakeZero();
differenceFrame.origin.x = endFrame.origin.x - startFrame.origin.x;
differenceFrame.origin.y = endFrame.origin.y - startFrame.origin.y;
differenceFrame.size.width = endFrame.size.width - startFrame.size.width;
differenceFrame.size.height = endFrame.size.height - startFrame.size.height;
var intermediateFrame = _CGRectMakeZero();
var intermediateFrame = CPRectMakeZero();
intermediateFrame.origin.x = startFrame.origin.x + differenceFrame.origin.x * progress;
intermediateFrame.origin.y = startFrame.origin.y + differenceFrame.origin.y * progress;
intermediateFrame.size.width = startFrame.size.width + differenceFrame.size.width * progress;
@@ -104,7 +103,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOut";
[view setAlphaValue:1.0 + ( 0.0 - 1.0 ) * progress];
if (progress === 1.0)
[view setHidden:_CGRectIsNull(endFrame) || [view alphaValue] === 0.0];
[view setHidden:CPRectIsNull(endFrame) || [view alphaValue] === 0.0];
}
}
@@ -125,7 +124,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOut";
else if (effect === CPViewAnimationFadeOutEffect)
[view setAlphaValue:0.0];
[view setHidden:_CGRectIsNull(endFrame) || [view alphaValue] === 0.0];
[view setHidden:CPRectIsNull(endFrame) || [view alphaValue] === 0.0];
}
[super stopAnimation];
@@ -140,7 +139,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOut";
return targetView;
}
- (CGRect)_startFrame:(CPDictionary)dictionary
- (CPRect)_startFrame:(CPDictionary)dictionary
{
var startFrame = [dictionary valueForKey:CPViewAnimationStartFrameKey];
if (!startFrame)
@@ -149,7 +148,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOut";
return startFrame;
}
- (CGRect)_endFrame:(CPDictionary)dictionary
- (CPRect)_endFrame:(CPDictionary)dictionary
{
var endFrame = [dictionary valueForKey:CPViewAnimationEndFrameKey];
if (!endFrame)
+7 -24
View File
@@ -20,12 +20,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPArray.j>
@import "CPApplication.j"
@import "CPCib.j"
@import "CPResponder.j"
@import <AppKit/CPResponder.j>
var CPViewControllerCachedCibs;
@@ -52,8 +47,7 @@ var CPViewControllerCachedCibs;
*/
@implementation CPViewController : CPResponder
{
CPView _view @accessors(property=view);
BOOL _isLoading;
CPView _view;
id _representedObject @accessors(property=representedObject);
CPString _title @accessors(property=title);
@@ -105,8 +99,6 @@ var CPViewControllerCachedCibs;
_cibName = aCibNameOrNil;
_cibBundle = aCibBundleOrNil || [CPBundle mainBundle];
_cibExternalNameTable = anExternalNameTable || [CPDictionary dictionaryWithObject:self forKey:CPCibOwner];
_isLoading = NO;
}
return self;
@@ -119,16 +111,16 @@ var CPViewControllerCachedCibs;
If you create your views manually, you must override this method and use it to create your view and assign it to the view property.
The default implementation for programmatic views is to create a plain view. You can invoke super to utilize this view.
If you use Interface Builder to create your views, you initialize the view using the
initWithCibName:bundle: method then you must not override this method. The consequences risk shattering the space-time continuum.
If you use Interface Builder to create your views and initialize the view controllerŃthat is, you initialize the view using the
initWithCibName:bundle: methodŃthen you must not override this method. The consequences risk shattering the space-time continuum.
Note: The cib loading system is currently synchronous.
Note: The cib loading system is currently asynchronous.
*/
- (void)loadView
{
if (_view)
return;
// check if a cib is already cached for the current _cibName
var cib = [CPViewControllerCachedCibs objectForKey:_cibName];
@@ -151,8 +143,6 @@ var CPViewControllerCachedCibs;
{
if (!_view)
{
_isLoading = YES;
var cibOwner = [_cibExternalNameTable objectForKey:CPCibOwner];
if ([cibOwner respondsToSelector:@selector(viewControllerWillLoadCib:)])
@@ -173,7 +163,6 @@ var CPViewControllerCachedCibs;
if ([cibOwner respondsToSelector:@selector(viewControllerDidLoadCib:)])
[cibOwner viewControllerDidLoadCib:self];
_isLoading = NO;
[self viewDidLoad];
}
@@ -184,7 +173,7 @@ var CPViewControllerCachedCibs;
/*!
This method is called after the view controller has loaded its associated views into memory.
This method is called regardless of whether the views were stored in a nib file or created programmatically in the loadView method.
This method is most commonly used to perform additional initialization steps on views that are loaded from cib files.
This method is most commonly used to perform additional initialization steps on views that are loaded from nib files.
*/
- (void)viewDidLoad
{
@@ -200,13 +189,7 @@ var CPViewControllerCachedCibs;
*/
- (void)setView:(CPView)aView
{
var viewWasLoaded = !_view;
_view = aView;
// Make sure the viewDidLoad method is called if the view is set directly
if (!_isLoading && viewWasLoaded)
[self viewDidLoad];
}
@end
+48 -48
View File
@@ -20,8 +20,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPView.j"
@import "CPScrollView.j"
@import <AppKit/CPView.j>
#include "Platform/Platform.h"
// FIXME: implement these where possible:
@@ -49,23 +50,23 @@ CPWebViewScrollNative = 2;
{
CPScrollView _scrollView;
CPView _frameView;
IFrame _iframe;
CPString _mainFrameURL;
CPArray _backwardStack;
CPArray _forwardStack;
BOOL _ignoreLoadStart;
BOOL _ignoreLoadEnd;
id _downloadDelegate;
id _frameLoadDelegate;
id _policyDelegate;
id _resourceLoadDelegate;
id _UIDelegate;
CPWebScriptObject _wso;
CPString _url;
CPString _html;
@@ -94,10 +95,10 @@ CPWebViewScrollNative = 2;
_backwardStack = [];
_forwardStack = [];
_scrollMode = CPWebViewScrollNative;
[self _initDOMWithFrame:aFrame];
}
return self;
}
@@ -105,52 +106,52 @@ CPWebViewScrollNative = 2;
{
_ignoreLoadStart = YES;
_ignoreLoadEnd = YES;
_iframe = document.createElement("iframe");
_iframe.name = "iframe_" + Math.floor(Math.random()*10000);
_iframe.style.width = "100%";
_iframe.style.height = "100%";
_iframe.style.borderWidth = "0px";
_iframe.frameBorder = "0";
[self setDrawsBackground:YES];
_loadCallback = function() {
// HACK: this block handles the case where we don't know about loads initiated by the user clicking a link
if (!_ignoreLoadStart)
{
// post the start load notification
[self _startedLoading];
if (_mainFrameURL)
[_backwardStack addObject:_mainFrameURL];
// FIXME: this doesn't actually get the right URL for different domains. Not possible due to browser security restrictions.
_mainFrameURL = _iframe.src;
_mainFrameURL = _iframe.src;
// clear the forward
[_forwardStack removeAllObjects];
}
else
_ignoreLoadStart = NO;
if (!_ignoreLoadEnd)
{
[self _finishedLoading];
}
else
_ignoreLoadEnd = NO;
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
}
if (_iframe.addEventListener)
_iframe.addEventListener("load", _loadCallback, false);
else if (_iframe.attachEvent)
_iframe.attachEvent("onload", _loadCallback);
_frameView = [[CPView alloc] initWithFrame:[self bounds]];
[_frameView setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
@@ -158,9 +159,9 @@ CPWebViewScrollNative = 2;
[_scrollView setAutohidesScrollers:YES];
[_scrollView setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
[_scrollView setDocumentView:_frameView];
_frameView._DOMElement.appendChild(_iframe);
[self _setScrollMode:_scrollMode];
[self addSubview:_scrollView];
@@ -168,7 +169,7 @@ CPWebViewScrollNative = 2;
- (void)setFrameSize:(CPSize)aSize
{
{
[super setFrameSize:aSize];
[self _resizeWebFrame];
}
@@ -210,7 +211,7 @@ CPWebViewScrollNative = 2;
{
var visibleRect = [_frameView visibleRect];
[_frameView setFrameSize:CGSizeMake(CGRectGetMaxX(visibleRect), CGRectGetMaxY(visibleRect))];
// try to get the document size so we can correctly set the frame
var win = null;
try { win = [self DOMWindow]; } catch (e) {}
@@ -228,7 +229,7 @@ CPWebViewScrollNative = 2;
else
{
CPLog.warn("using default size 800*1600");
[_frameView setFrameSize:CGSizeMake(800, 1600)];
}
@@ -241,7 +242,7 @@ CPWebViewScrollNative = 2;
{
if (_scrollMode == aScrollMode)
return;
[self _setScrollMode:aScrollMode];
}
@@ -251,7 +252,7 @@ CPWebViewScrollNative = 2;
_scrollMode = CPWebViewScrollNative;
else
_scrollMode = aScrollMode;
_ignoreLoadStart = YES;
_ignoreLoadEnd = YES;
@@ -262,16 +263,16 @@ CPWebViewScrollNative = 2;
{
[_scrollView setHasHorizontalScroller:YES];
[_scrollView setHasVerticalScroller:YES];
_iframe.setAttribute("scrolling", "no");
}
else
{
[_scrollView setHasHorizontalScroller:NO];
[_scrollView setHasVerticalScroller:NO];
_iframe.setAttribute("scrolling", "auto");
[_frameView setFrameSize:[_scrollView bounds].size];
}
@@ -292,13 +293,13 @@ CPWebViewScrollNative = 2;
[_frameView setFrameSize:[_scrollView contentSize]];
[self _startedLoading];
_ignoreLoadStart = YES;
_ignoreLoadEnd = NO;
_url = null;
_html = aString;
[self _load];
}
@@ -307,13 +308,13 @@ CPWebViewScrollNative = 2;
[self _setScrollMode:CPWebViewScrollNative];
[self _startedLoading];
_ignoreLoadStart = YES;
_ignoreLoadEnd = NO;
_url = _mainFrameURL;
_html = null;
[self _load];
}
@@ -334,13 +335,12 @@ CPWebViewScrollNative = 2;
_loadHTMLStringTimer = nil;
}
// need to give the browser a chance to reset iframe, otherwise we'll be document.write()-ing the previous document
// need to give the browser a chance to reset iframe, otherwise we'll be document.write()-ing the previous document
_loadHTMLStringTimer = window.setTimeout(function()
{
var win = [self DOMWindow];
if (win)
win.document.write(_html);
win.document.write(_html);
window.setTimeout(_loadCallback, 1);
}, 0);
@@ -372,7 +372,7 @@ CPWebViewScrollNative = 2;
}
- (void)setMainFrameURL:(CPString)URLString
{
{
if (_mainFrameURL)
[_backwardStack addObject:_mainFrameURL];
_mainFrameURL = URLString;
@@ -389,9 +389,9 @@ CPWebViewScrollNative = 2;
[_forwardStack addObject:_mainFrameURL];
_mainFrameURL = [_backwardStack lastObject];
[_backwardStack removeLastObject];
[self _loadMainFrameURL];
return YES;
}
return NO;
@@ -405,9 +405,9 @@ CPWebViewScrollNative = 2;
[_backwardStack addObject:_mainFrameURL];
_mainFrameURL = [_forwardStack lastObject];
[_forwardStack removeLastObject];
[self _loadMainFrameURL];
return YES;
}
return NO;
@@ -630,7 +630,7 @@ CPWebViewScrollNative = 2;
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
// FIXME: encode/decode these?
@@ -638,14 +638,14 @@ CPWebViewScrollNative = 2;
_backwardStack = [];
_forwardStack = [];
_scrollMode = CPWebViewScrollNative;
#if PLATFORM(DOM)
[self _initDOMWithFrame:[self frame]];
#endif
[self setBackgroundColor:[CPColor whiteColor]];
}
return self;
}
+130 -276
View File
@@ -26,9 +26,14 @@
@import "CGGeometry.j"
@import "CPAnimation.j"
@import "CPPlatformWindow.j"
@import "CPResponder.j"
@import "CPScreen.j"
@import "CPPlatformWindow.j"
#include "../Platform/Platform.h"
#include "../Platform/DOM/CPDOMDisplayServer.h"
#include "../CoreGraphics/CGGeometry.h"
/*
@@ -189,15 +194,13 @@ var SHADOW_MARGIN_LEFT = 20.0,
SHADOW_MARGIN_TOP = 10.0,
SHADOW_MARGIN_BOTTOM = 10.0,
SHADOW_DISTANCE = 5.0,
_CPWindowShadowColor = nil;
var CPWindowSaveImage = nil,
CPWindowSavingImage = nil;
var CPWindowResizeTime = 0.2;
/*!
/*!
@ingroup appkit
@class CPWindow
@@ -210,33 +213,33 @@ var CPWindowResizeTime = 0.2;
<p>A window always contains a content view which is the highest level view available for public (application) use. This view fills the area of the window inside any decoration/border. This is the only part of the window that application programmers are allowed to draw in directly.</p>
<p>You can convert between view coordinates and window base coordinates using the [CPView -convertPoint:fromView:], [CPView -convertPoint:toView:], [CPView -convertRect:fromView:], and [CPView -convertRect:toView:] methods with a nil view argument.
@par Delegate Methods
@delegate -(void)windowDidResize:(CPNotification)notification;
Sent from the notification center when the window has been resized.
@param notification contains information about the resize event
@delegate -(CPUndoManager)windowWillReturnUndoManager:(CPWindow)window;
Called to obtain the undo manager for a window
@param window the window for which to return the undo manager
@return the window's undo manager
@delegate -(void)windowDidBecomeMain:(CPNotification)notification;
Sent from the notification center when the delegate's window becomes
the main window.
@param notification contains information about the event
@delegate -(void)windowDidResignMain:(CPNotification)notification;
Sent from the notification center when the delegate's window has
resigned main window status.
@param notification contains information about the event
@delegate -(void)windowDidResignKey:(CPNotification)notification;
Sent from the notification center when the delegate's window has
resigned key window status.
@param notification contains information about the event
@delegate -(BOOL)windowShouldClose:(id)window;
Called when the user tries to close the window.
@param window the window to close
@@ -308,17 +311,15 @@ var CPWindowResizeTime = 0.2;
#endif
unsigned _autoresizingMask;
BOOL _delegateRespondsToWindowWillReturnUndoManagerSelector;
BOOL _isFullPlatformWindow;
_CPWindowFullPlatformWindowSession _fullPlatformWindowSession;
CPDictionary _sheetContext;
CPWindow _parentView;
BOOL _isSheet;
_CPWindowFrameAnimation _frameAnimation;
}
/*
@@ -329,9 +330,9 @@ var CPWindowResizeTime = 0.2;
{
if (self != [CPWindow class])
return;
var bundle = [CPBundle bundleForClass:[CPWindow class]];
CPWindowSavingImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPProgressIndicator/CPProgressIndicatorSpinningStyleRegular.gif"] size:CGSizeMake(16.0, 16.0)]
}
@@ -358,7 +359,7 @@ CPTexturedBackgroundWindowMask
- (id)initWithContentRect:(CGRect)aContentRect styleMask:(unsigned int)aStyleMask
{
self = [super init];
if (self)
{
var windowViewClass = [[self class] _windowViewClassForStyleMask:aStyleMask];
@@ -392,7 +393,7 @@ CPTexturedBackgroundWindowMask
// Set up our window number.
_windowNumber = [CPApp._windows count];
CPApp._windows[_windowNumber] = self;
_styleMask = aStyleMask;
[self setLevel:CPNormalWindowLevel];
@@ -407,15 +408,15 @@ CPTexturedBackgroundWindowMask
[_windowView setNextResponder:self];
[self setMovableByWindowBackground:aStyleMask & CPHUDBackgroundWindowMask];
// Create a generic content view.
[self setContentView:[[CPView alloc] initWithFrame:CGRectMakeZero()]];
_firstResponder = self;
#if PLATFORM(DOM)
_DOMElement = document.createElement("div");
_DOMElement.style.position = "absolute";
_DOMElement.style.visibility = "visible";
_DOMElement.style.zIndex = 0;
@@ -441,7 +442,7 @@ CPTexturedBackgroundWindowMask
[self setShowsResizeIndicator:_styleMask & CPResizableWindowMask];
}
return self;
}
@@ -658,10 +659,9 @@ CPTexturedBackgroundWindowMask
if (shouldAnimate)
{
[_frameAnimation stopAnimation];
_frameAnimation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:aFrame];
[_frameAnimation startAnimation];
var animation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:aFrame];
[animation startAnimation];
}
else
{
@@ -742,10 +742,8 @@ CPTexturedBackgroundWindowMask
*/
- (void)orderFront:(id)aSender
{
#if PLATFORM(DOM)
[_platformWindow orderFront:self];
[_platformWindow order:CPWindowAbove window:self relativeTo:nil];
#endif
if (_firstResponder === self || !_firstResponder)
[self makeFirstResponder:[self initialFirstResponder]];
@@ -773,17 +771,13 @@ CPTexturedBackgroundWindowMask
*/
- (void)orderOut:(id)aSender
{
#if PLATFORM(DOM)
if ([self _sharesChromeWithPlatformWindow])
[_platformWindow orderOut:self];
#endif
if ([_delegate respondsToSelector:@selector(windowWillClose:)])
[_delegate windowWillClose:self];
#if PLATFORM(DOM)
[_platformWindow order:CPWindowOut window:self relativeTo:nil];
#endif
[self _updateMainAndKeyWindows];
}
@@ -795,9 +789,7 @@ CPTexturedBackgroundWindowMask
*/
- (void)orderWindow:(CPWindowOrderingMode)aPlace relativeTo:(int)otherWindowNumber
{
#if PLATFORM(DOM)
[_platformWindow order:aPlace window:self relativeTo:CPApp._windows[otherWindowNumber]];
#endif
}
/*!
@@ -882,12 +874,12 @@ CPTexturedBackgroundWindowMask
{
if (_contentView)
[_contentView removeFromSuperview];
var bounds = CGRectMake(0.0, 0.0, CGRectGetWidth(_frame), CGRectGetHeight(_frame));
_contentView = aView;
[_contentView setFrame:[self contentRectForFrameRect:bounds]];
[_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[_windowView addSubview:_contentView];
}
@@ -943,24 +935,24 @@ CPTexturedBackgroundWindowMask
{
if (CGSizeEqualToSize(_minSize, aSize))
return;
_minSize = CGSizeCreateCopy(aSize);
var size = CGSizeMakeCopy([self frame].size),
needsFrameChange = NO;
if (size.width < _minSize.width)
{
size.width = _minSize.width;
needsFrameChange = YES;
}
if (size.height < _minSize.height)
{
size.height = _minSize.height;
needsFrameChange = YES;
}
if (needsFrameChange)
[self setFrameSize:size];
}
@@ -983,24 +975,24 @@ CPTexturedBackgroundWindowMask
{
if (CGSizeEqualToSize(_maxSize, aSize))
return;
_maxSize = CGSizeCreateCopy(aSize);
var size = CGSizeMakeCopy([self frame].size),
needsFrameChange = NO;
if (size.width > _maxSize.width)
{
size.width = _maxSize.width;
needsFrameChange = YES;
}
if (size.height > _maxSize.height)
{
size.height = _maxSize.height;
needsFrameChange = YES;
}
if (needsFrameChange)
[self setFrameSize:size];
}
@@ -1041,10 +1033,10 @@ CPTexturedBackgroundWindowMask
if (_hasShadow && !_shadowView)
{
var bounds = [_windowView bounds];
_shadowView = [[CPView alloc] initWithFrame:CGRectMake(-SHADOW_MARGIN_LEFT, -SHADOW_MARGIN_TOP + SHADOW_DISTANCE,
_shadowView = [[CPView alloc] initWithFrame:CGRectMake(-SHADOW_MARGIN_LEFT, -SHADOW_MARGIN_TOP + SHADOW_DISTANCE,
SHADOW_MARGIN_LEFT + CGRectGetWidth(bounds) + SHADOW_MARGIN_RIGHT, SHADOW_MARGIN_TOP + CGRectGetHeight(bounds) + SHADOW_MARGIN_BOTTOM)];
if (!_CPWindowShadowColor)
{
var bundle = [CPBundle bundleForClass:[CPWindow class]];
@@ -1067,7 +1059,7 @@ CPTexturedBackgroundWindowMask
[_shadowView setBackgroundColor:_CPWindowShadowColor];
[_shadowView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
#if PLATFORM(DOM)
CPDOMDisplayServerInsertBefore(_DOMElement, _shadowView._DOMElement, _windowView._DOMElement);
#endif
@@ -1133,7 +1125,7 @@ CPTexturedBackgroundWindowMask
selector:@selector(windowDidBecomeKey:)
name:CPWindowDidBecomeKeyNotification
object:self];
if ([_delegate respondsToSelector:@selector(windowDidBecomeMain:)])
[defaultCenter
addObserver:_delegate
@@ -1229,7 +1221,7 @@ CPTexturedBackgroundWindowMask
if(!aResponder || ![aResponder acceptsFirstResponder] || ![aResponder becomeFirstResponder])
{
_firstResponder = self;
return NO;
}
@@ -1282,9 +1274,9 @@ CPTexturedBackgroundWindowMask
- (void)setTitle:(CPString)aTitle
{
_title = aTitle;
[_windowView setTitle:aTitle];
[self _synchronizeMenuBarTitleWithWindowTitle];
}
@@ -1359,21 +1351,10 @@ CPTexturedBackgroundWindowMask
*/
- (void)center
{
if (_isFullPlatformWindow)
return;
var size = [self frame].size,
containerSize = [CPPlatform isBrowser] ? [_platformWindow contentBounds].size : [[self screen] visibleFrame].size;
var origin = CGPointMake((containerSize.width - size.width) / 2.0, (containerSize.height - size.height) / 2.0);
if (origin.x < 0.0)
origin.x = 0.0;
if (origin.y < 0.0)
origin.y = 0.0;
[self setFrameOrigin:origin];
[self setFrameOrigin:CGPointMake((containerSize.width - size.width) / 2.0, (containerSize.height - size.height) / 2.0)];
}
/*!
@@ -1387,37 +1368,8 @@ CPTexturedBackgroundWindowMask
switch (type)
{
case CPFlagsChanged: return [[self firstResponder] flagsChanged:anEvent];
case CPKeyUp: return [[self firstResponder] keyUp:anEvent];
case CPKeyDown: if ([anEvent charactersIgnoringModifiers] === CPTabCharacter)
{
if ([anEvent modifierFlags] & CPShiftKeyMask)
[self selectPreviousKeyView:self];
else
[self selectNextKeyView:self];
return;
}
else if ([anEvent charactersIgnoringModifiers] === CPBackTabCharacter)
return [self selectPreviousKeyView:self];
[[self firstResponder] keyDown:anEvent];
// Trigger the default button if needed
// FIXME: Is this only applicable in a sheet? See isse: #722.
if (![self disableKeyEquivalentForDefaultButton])
{
var defaultButton = [self defaultButton],
keyEquivalent = [defaultButton keyEquivalent],
modifierMask = [defaultButton keyEquivalentModifierMask];
if ([anEvent _triggersKeyEquivalent:keyEquivalent withModifierMask:modifierMask])
[[self defaultButton] performClick:self];
}
return;
case CPKeyDown: return [[self firstResponder] keyDown:anEvent];
case CPScrollWheel: return [[_windowView hitTest:point] scrollWheel:anEvent];
@@ -1576,7 +1528,7 @@ CPTexturedBackgroundWindowMask
- (void)makeKeyAndOrderFront:(id)aSender
{
[self orderFront:self];
[self makeKeyWindow];
[self makeMainWindow];
}
@@ -1640,7 +1592,7 @@ CPTexturedBackgroundWindowMask
if (!pasteboardTypes)
return;
[_inclusiveRegisteredDraggedTypes minusSet:pasteboardTypes];
[_inclusiveRegisteredDraggedTypes minusSet:pasteboardTypes]
if ([_inclusiveRegisteredDraggedTypes count] === 0)
_inclusiveRegisteredDraggedTypes = nil;
@@ -1671,7 +1623,7 @@ CPTexturedBackgroundWindowMask
return;
[self _noteUnregisteredDraggedTypes:_registeredDraggedTypes];
[_registeredDraggedTypes addObjectsFromArray:pasteboardTypes];
[_registeredDraggedTypes addObjectsFromArray:pasteboardTypes]
[self _noteRegisteredDraggedTypes:_registeredDraggedTypes];
_registeredDraggedTypesArray = nil;
@@ -1684,7 +1636,7 @@ CPTexturedBackgroundWindowMask
- (CPArray)registeredDraggedTypes
{
if (!_registeredDraggedTypesArray)
_registeredDraggedTypesArray = [_registeredDraggedTypes allObjects];
_registeredDraggedTypesArray = [_registeredDraggedTypes allObjects]
return _registeredDraggedTypesArray;
}
@@ -1710,9 +1662,9 @@ CPTexturedBackgroundWindowMask
{
if (_isDocumentEdited == isDocumentEdited)
return;
_isDocumentEdited = isDocumentEdited;
[CPMenu _setMenuBarIconImageAlphaValue:_isDocumentEdited ? 0.5 : 1.0];
[_windowView setDocumentEdited:isDocumentEdited];
@@ -1730,11 +1682,11 @@ CPTexturedBackgroundWindowMask
{
if (_isDocumentSaving == isDocumentSaving)
return;
_isDocumentSaving = isDocumentSaving;
[self _synchronizeSaveMenuWithDocumentSaving];
[_windowView windowDidChangeDocumentSaving];
}
@@ -1751,16 +1703,16 @@ CPTexturedBackgroundWindowMask
var mainMenu = [CPApp mainMenu],
index = [mainMenu indexOfItemWithTitle:_isDocumentSaving ? @"Save" : @"Saving..."];
if (index == CPNotFound)
return;
var item = [mainMenu itemAtIndex:index];
if (_isDocumentSaving)
{
CPWindowSaveImage = [item image];
[item setTitle:@"Saving..."];
[item setImage:CPWindowSavingImage];
[item setEnabled:NO];
@@ -1850,7 +1802,7 @@ CPTexturedBackgroundWindowMask
if (![_delegate windowShouldClose:self])
return;
}
// Only check self is delegate does NOT implement this. This also ensures this when delegate == self (returns true).
else if ([self respondsToSelector:@selector(windowShouldClose:)] && ![self windowShouldClose:self])
return;
@@ -1860,8 +1812,8 @@ CPTexturedBackgroundWindowMask
{
var index = [documents indexOfObject:[_windowController document]];
[documents[index] shouldCloseWindowController:_windowController
delegate:self
[documents[index] shouldCloseWindowController:_windowController
delegate:self
shouldCloseSelector:@selector(_windowControllerContainingDocument:shouldClose:contextInfo:)
contextInfo:{documents:[documents copy], visited:0, index:index}];
}
@@ -1885,8 +1837,8 @@ CPTexturedBackgroundWindowMask
{
[windowController setDocument:documents[index]];
[documents[index] shouldCloseWindowController:_windowController
delegate:self
[documents[index] shouldCloseWindowController:_windowController
delegate:self
shouldCloseSelector:@selector(_windowControllerContainingDocument:shouldClose:contextInfo:)
contextInfo:context];
}
@@ -1923,7 +1875,7 @@ CPTexturedBackgroundWindowMask
// FIXME: Also check if we can resize and titlebar.
if ([self isVisible])
return YES;
return NO;
}
@@ -1982,16 +1934,10 @@ CPTexturedBackgroundWindowMask
else
{
var mainMenu = [CPApp mainMenu],
menuBarClass = objj_getClass("_CPMenuBarWindow"),
menuWindow;
menuWindow = mainMenu ? mainMenu._menuWindow : nil;
for (var i = 0; i < windowCount; i++)
{
var currentWindow = allWindows[i];
if ([currentWindow isKindOfClass:menuBarClass])
menuWindow = currentWindow;
if (currentWindow === self || currentWindow === menuWindow)
continue;
@@ -2017,16 +1963,10 @@ CPTexturedBackgroundWindowMask
else
{
var mainMenu = [CPApp mainMenu],
menuBarClass = objj_getClass("_CPMenuBarWindow"),
menuWindow;
menuWindow = mainMenu ? mainMenu._menuWindow : nil;
for (var i = 0; i < windowCount; i++)
{
var currentWindow = allWindows[i];
if ([currentWindow isKindOfClass:menuBarClass])
menuWindow = currentWindow;
if (currentWindow === self || currentWindow === menuWindow)
continue;
@@ -2057,25 +1997,25 @@ CPTexturedBackgroundWindowMask
{
if (_toolbar === aToolbar)
return;
// If this has an owner, dump it!
[[aToolbar _window] setToolbar:nil];
// This is no longer out toolbar.
[_toolbar _setWindow:nil];
_toolbar = aToolbar;
// THIS is our toolbar.
[_toolbar _setWindow:self];
[self _noteToolbarChanged];
}
- (void)toggleToolbarShown:(id)aSender
{
var toolbar = [self toolbar];
[toolbar setVisible:![toolbar isVisible]];
}
@@ -2091,10 +2031,10 @@ CPTexturedBackgroundWindowMask
else
{
newFrame = CGRectMakeCopy([self frame]);
newFrame.origin = frame.origin;
}
[self setFrame:newFrame];
/*
[_windowView setAnimatingToolbar:YES];
@@ -2106,17 +2046,11 @@ CPTexturedBackgroundWindowMask
- (void)_setFrame:(CGRect)aFrame delegate:(id)delegate duration:(int)duration curve:(CPAnimationCurve)curve
{
[_frameAnimation stopAnimation];
_frameAnimation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:aFrame];
[_frameAnimation setDelegate:delegate];
[_frameAnimation setAnimationCurve:curve];
[_frameAnimation setDuration:duration];
[_frameAnimation startAnimation];
}
- (CPTimeInterval)animationResizeTime:(CGRect)newWindowFrame
{
return CPWindowResizeTime;
var animation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:aFrame];
[animation setDelegate:delegate];
[animation setAnimationCurve:curve];
[animation setDuration:duration];
[animation startAnimation];
}
/* @ignore */
@@ -2126,7 +2060,7 @@ CPTexturedBackgroundWindowMask
var attachedSheet = [self attachedSheet];
var contentRect = [[self contentView] frame],
sheetFrame = CGRectMakeCopy([attachedSheet frame]);
sheetFrame.origin.y = CGRectGetMinY(_frame) + CGRectGetMinY(contentRect);
sheetFrame.origin.x = CGRectGetMinX(_frame) + FLOOR((CGRectGetWidth(_frame) - CGRectGetWidth(sheetFrame)) / 2.0);
@@ -2138,8 +2072,8 @@ CPTexturedBackgroundWindowMask
{
var sheetFrame = [aSheet frame];
_sheetContext = {"sheet":aSheet, "modalDelegate":aModalDelegate, "endSelector":aDidEndSelector, "contextInfo":aContextInfo, "frame":CGRectMakeCopy(sheetFrame), "returnCode":-1, "opened": NO};
_sheetContext = {"sheet":aSheet, "modalDelegate":aModalDelegate, "endSelector":aDidEndSelector, "contextInfo":aContextInfo, "frame":CGRectMakeCopy(sheetFrame), "returnCode":-1, "opened": NO};
[self _attachSheetWindow:aSheet];
}
@@ -2149,12 +2083,12 @@ CPTexturedBackgroundWindowMask
var sheetFrame = [aSheet frame],
frame = [self frame],
sheetContent = [aSheet contentView];
[self _setUpMasksForView:sheetContent];
aSheet._isSheet = YES;
aSheet._parentView = self;
var originx = frame.origin.x + FLOOR((frame.size.width - sheetFrame.size.width)/2),
originy = frame.origin.y + [[self contentView] frame].origin.y,
startFrame = CGRectMake(originx, originy, sheetFrame.size.width, 0),
@@ -2162,15 +2096,15 @@ CPTexturedBackgroundWindowMask
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowWillBeginSheetNotification object:self];
[CPApp runModalForWindow:aSheet];
[aSheet orderFront:self];
[aSheet setFrame:startFrame display:YES animate:NO];
_sheetContext["opened"] = YES;
[aSheet _setFrame:endFrame delegate:self duration:[self animationResizeTime:endFrame] curve:CPAnimationEaseOut];
[aSheet _setFrame:endFrame delegate:self duration:0.2 curve:CPAnimationEaseOut];
// Should run the main loop here until _isAnimating = FALSE
[aSheet becomeKeyWindow];
[aSheet becomeKeyWindow];
}
/* @ignore */
@@ -2181,14 +2115,14 @@ CPTexturedBackgroundWindowMask
endFrame = CGRectMakeCopy(startFrame);
endFrame.size.height = 0;
_sheetContext["frame"] = startFrame;
var sheetContent = [sheet contentView];
[self _setUpMasksForView:sheetContent];
_sheetContext["opened"] = NO;
[sheet _setFrame:endFrame delegate:self duration:[self animationResizeTime:endFrame] curve:CPAnimationEaseIn];
[sheet _setFrame:endFrame delegate:self duration:0.2 curve:CPAnimationEaseIn];
}
/* @ignore */
@@ -2199,33 +2133,31 @@ CPTexturedBackgroundWindowMask
return;
var sheetContent = [sheet contentView];
if (_sheetContext["opened"] === YES)
{
[self _restoreMasksForView:sheetContent];
return;
}
[CPApp stopModal];
[CPApp stopModal];
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidEndSheetNotification object:self];
[sheet orderOut:self];
var lastFrame = _sheetContext["frame"];
[sheet setFrame:lastFrame];
[self _restoreMasksForView:sheetContent];
var delegate = _sheetContext["modalDelegate"],
endSelector = _sheetContext["endSelector"],
returnCode = _sheetContext["returnCode"],
contextInfo = _sheetContext["contextInfo"];
endSelector = _sheetContext["endSelector"];
if (delegate != nil && endSelector != nil)
objj_msgSend(delegate, endSelector, sheet, _sheetContext["returnCode"], _sheetContext["contextInfo"]);
_sheetContext = nil;
sheet._parentView = nil;
if (delegate != nil && endSelector != nil)
objj_msgSend(delegate, endSelector, sheet, returnCode, contextInfo);
}
- (void)_setUpMasksForView:(CPView)aView
@@ -2233,7 +2165,7 @@ CPTexturedBackgroundWindowMask
var views = [aView subviews];
[views addObject:aView];
for (var i = 0, count = [views count]; i < count; i++)
{
var view = [views objectAtIndex:i],
@@ -2249,7 +2181,7 @@ CPTexturedBackgroundWindowMask
var views = [aView subviews];
[views addObject:aView];
for (var i = 0, count = [views count]; i < count; i++)
{
var view = [views objectAtIndex:i],
@@ -2267,7 +2199,7 @@ CPTexturedBackgroundWindowMask
{
if (_sheetContext === nil)
return nil;
return _sheetContext["sheet"];
}
@@ -2298,7 +2230,7 @@ CPTexturedBackgroundWindowMask
return NO;
}
- (BOOL)performKeyEquivalent:(CPEvent)anEvent
- (void)performKeyEquivalent:(CPEvent)anEvent
{
// FIXME: should we be starting at the root, in other words _windowView?
// The evidence seems to point to no...
@@ -2309,92 +2241,19 @@ CPTexturedBackgroundWindowMask
{
// It's not clear why we do performKeyEquivalent again here...
// Perhaps to allow something to happen between sendEvent: and keyDown:?
if ([anEvent _couldBeKeyEquivalent] && [self performKeyEquivalent:anEvent])
return;
// Apple's documentation is inconsistent with their behavior here. According to the docs
// an event going of the responder chain is passed to the input system as a last resort.
// However, the only methods I could get Cocoa to call automatically are
// moveUp: moveDown: moveLeft: moveRight: pageUp: pageDown: and complete:
[self _processKeyboardUIKey:anEvent];
if (![anEvent _couldBeKeyEquivalent] || ![self performKeyEquivalent:anEvent])
[self interpretKeyEvents:[anEvent]];
}
/*
@ignore
Interprets the key event for action messages and sends the action message down the responder chain
Cocoa only sends moveDown:, moveUp:, moveLeft:, moveRight:, pageUp:, pageDown: and complete: messages.
We deviate from this by sending (the default) scrollPageUp: scrollPageDown: for pageUp and pageDown keys.
@param anEvent the event to handle.
@return YES if the key event was handled, NO if no responder handled the key event
*/
- (BOOL)_processKeyboardUIKey:(CPEvent)anEvent
- (void)insertNewline:(id)sender
{
var character = [anEvent charactersIgnoringModifiers],
uiKeys = [CPLeftArrowFunctionKey, CPRightArrowFunctionKey, CPUpArrowFunctionKey, CPDownArrowFunctionKey, CPPageUpFunctionKey, CPPageDownFunctionKey, CPEscapeFunctionKey];
if (![uiKeys containsObject:character])
return NO;
var selectors = [CPKeyBinding selectorsForKey:character modifierFlags:0];
if ([selectors count] <= 0)
return NO;
if (character !== CPEscapeFunctionKey)
{
var selector = [selectors objectAtIndex:0];
return [[self firstResponder] tryToPerform:selector with:self];
}
else
{
// Cocoa sends complete: for the escape key (in stead of the default cancelOperation:)
// This is also the only action that is not sent directly to the first responder, but through doCommandBySelector.
// The difference is that doCommandBySelector: will also send the action to the window and application delegates.
[[self firstResponder] doCommandBySelector:@selector(complete:)];
}
if (_defaultButton && _defaultButtonEnabled)
[_defaultButton performClick:nil];
}
/*
@ignore
Interprets the key event for action messages and sends the action message down the responder chain
Cocoa only sends moveDown:, moveUp:, moveLeft:, moveRight:, pageUp:, pageDown: and complete: messages.
We deviate from this by sending (the default) scrollPageUp: scrollPageDown: for pageUp and pageDown keys.
@param anEvent the event to handle.
@return YES if the key event was handled, NO if no responder handled the key event
*/
- (BOOL)_processKeyboardUIKey:(CPEvent)anEvent
- (void)insertTab:(id)sender
{
var character = [anEvent charactersIgnoringModifiers],
uiKeys = [
CPLeftArrowFunctionKey,
CPRightArrowFunctionKey,
CPUpArrowFunctionKey,
CPDownArrowFunctionKey,
CPPageUpFunctionKey,
CPPageDownFunctionKey,
CPEscapeFunctionKey
];
if (![uiKeys containsObject:character])
return NO;
var selectors = [CPKeyBinding selectorsForKey:character modifierFlags:0];
if ([selectors count] <= 0)
return NO;
if (character !== CPEscapeFunctionKey)
{
var selector = [selectors objectAtIndex:0];
return [[self firstResponder] tryToPerform:selector with:self];
}
else
{
// Cocoa sends complete: for the escape key (in stead of the default cancelOperation:)
// This is also the only action that is not sent directly to the first responder, but through doCommandBySelector.
// The difference is that doCommandBySelector: will also send the action to the window and application delegates.
[[self firstResponder] doCommandBySelector:@selector(complete:)];
}
[self selectNextKeyView:nil];
}
- (void)_dirtyKeyViewLoop
@@ -2421,7 +2280,7 @@ CPTexturedBackgroundWindowMask
- (void)recalculateKeyViewLoop
{
var subviews = [];
[self _appendSubviewsOf:_contentView toArray:subviews];
var keyViewOrder = [subviews sortedArrayUsingFunction:keyViewComparator context:_contentView],
@@ -2429,7 +2288,7 @@ CPTexturedBackgroundWindowMask
for (var i=0; i<count; i++)
[keyViewOrder[i] setNextKeyView:keyViewOrder[(i+1)%count]];
_keyViewLoopIsDirty = NO;
}
@@ -2450,7 +2309,7 @@ CPTexturedBackgroundWindowMask
return;
_autorecalculatesKeyViewLoop = shouldRecalculate;
if (_keyViewLoopIsDirty)
[self recalculateKeyViewLoop];
else if (_autorecalculatesKeyViewLoop)
@@ -2502,16 +2361,11 @@ CPTexturedBackgroundWindowMask
- (void)setDefaultButton:(CPButton)aButton
{
if (_defaultButton === aButton)
return;
if ([_defaultButton keyEquivalent] === CPCarriageReturnCharacter)
[_defaultButton setKeyEquivalent:nil];
[_defaultButton setDefaultButton:NO];
_defaultButton = aButton;
if ([_defaultButton keyEquivalent] !== CPCarriageReturnCharacter)
[_defaultButton setKeyEquivalent:CPCarriageReturnCharacter];
[_defaultButton setDefaultButton:YES];
}
- (CPButton)defaultButton
@@ -2578,7 +2432,7 @@ var keyViewComparator = function(a, b, context)
{
if ([self isFullPlatformWindow])
return [self setFrame:[_platformWindow visibleFrame]];
if (_autoresizingMask == CPWindowNotSizable)
return;
@@ -2593,7 +2447,7 @@ var keyViewComparator = function(a, b, context)
newFrame.origin.x += dX;
if (_autoresizingMask & CPWindowWidthSizable)
newFrame.size.width += dX;
if (_autoresizingMask & CPWindowMinYMargin)
newFrame.origin.y += dY;
if (_autoresizingMask & CPWindowHeightSizable)
@@ -2765,39 +2619,39 @@ var interpolate = function(fromValue, toValue, progress)
@implementation _CPWindowFrameAnimation : CPAnimation
{
CPWindow _window;
CGRect _startFrame;
CGRect _targetFrame;
}
- (id)initWithWindow:(CPWindow)aWindow targetFrame:(CGRect)aTargetFrame
{
self = [super initWithDuration:[aWindow animationResizeTime:aTargetFrame] animationCurve:CPAnimationLinear];
self = [super initWithDuration:0.2 animationCurve:CPAnimationLinear];
if (self)
{
_window = aWindow;
_targetFrame = CGRectMakeCopy(aTargetFrame);
_startFrame = CGRectMakeCopy([_window frame]);
}
return self;
}
- (void)startAnimation
{
[super startAnimation];
_window._isAnimating = YES;
}
- (void)setCurrentProgress:(float)aProgress
{
[super setCurrentProgress:aProgress];
var value = [self currentValue];
if (value == 1.0)
_window._isAnimating = NO;
+12 -12
View File
@@ -43,21 +43,21 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
_CPHUDWindowViewBackgroundColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground0.png"] size:CPSizeMake(7.0, 37.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground1.png"] size:CPSizeMake(1.0, 37.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground2.png"] size:CPSizeMake(7.0, 37.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground0.png"] size:CPSizeMake(6.0, 78.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground1.png"] size:CPSizeMake(1.0, 78.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground2.png"] size:CPSizeMake(6.0, 78.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground3.png"] size:CPSizeMake(7.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground4.png"] size:CPSizeMake(2.0, 2.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground5.png"] size:CPSizeMake(7.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground3.png"] size:CPSizeMake(6.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground4.png"] size:CPSizeMake(5.0, 5.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground5.png"] size:CPSizeMake(6.0, 1.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground6.png"] size:CPSizeMake(7.0, 3.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground7.png"] size:CPSizeMake(1.0, 3.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground8.png"] size:CPSizeMake(7.0, 3.0)]
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground6.png"] size:CPSizeMake(6.0, 6.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground7.png"] size:CPSizeMake(6.0, 6.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground8.png"] size:CPSizeMake(6.0, 6.0)]
]]];
_CPHUDWindowViewCloseImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/WindowClose.png"] size:CPSizeMake(18.0, 18.0)];
_CPHUDWindowViewCloseActiveImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/WindowCloseActive.png"] size:CPSizeMake(18.0, 18.0)];
_CPHUDWindowViewCloseImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/WindowClose.png"] size:CPSizeMake(20.0, 20.0)];
_CPHUDWindowViewCloseActiveImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/WindowCloseActive.png"] size:CPSizeMake(20.0, 20.0)];
}
+ (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
@@ -148,7 +148,7 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
{
var closeSize = [_CPHUDWindowViewCloseImage size];
_closeButton = [[CPButton alloc] initWithFrame:CGRectMake(8.0, 5.0, closeSize.width, closeSize.height)];
_closeButton = [[CPButton alloc] initWithFrame:CGRectMake(4.0, 4.0, closeSize.width, closeSize.height)];
[_closeButton setBordered:NO];
-1
View File
@@ -22,7 +22,6 @@
@import "_CPWindowView.j"
var GRADIENT_HEIGHT = 41.0;
var _CPTexturedWindowHeadGradientColor = nil,
+3 -1
View File
@@ -20,8 +20,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPImageView.j"
@import "CPView.j"
@import "CPImageView.j"
#include "../CoreGraphics/CGGeometry.h"
var _CPWindowViewResizeIndicatorImage = nil;
+4 -2
View File
@@ -27,6 +27,8 @@
@import "CPWindow.j"
@import "CPDocument.j"
#include "Platform/Platform.h"
/*!
@ingroup appkit
@@ -131,7 +133,7 @@
if (_window)
return;
[[CPBundle mainBundle] loadCibFile:[self windowCibPath] externalNameTable:[CPDictionary dictionaryWithObject:_cibOwner forKey:CPCibOwner]];
[[CPBundle bundleForClass:[_cibOwner class]] loadCibFile:[self windowCibPath] externalNameTable:[CPDictionary dictionaryWithObject:_cibOwner forKey:CPCibOwner]];
}
/*!
@@ -422,7 +424,7 @@
if (_windowCibPath)
return _windowCibPath;
return [[CPBundle mainBundle] pathForResource:_windowCibName + @".cib"];
return [[CPBundle bundleForClass:[_cibOwner class]] pathForResource:_windowCibName + @".cib"];
}
// Setting and Getting Window Attributes
+1 -1
View File
@@ -150,7 +150,7 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey";
var topLevelObjects = [anExternalNameTable objectForKey:CPCibTopLevelObjects];
[objectData instantiateWithOwner:owner topLevelObjects:topLevelObjects];
[objectData instantiateWithOwner:owner topLevelObjects:topLevelObjects]
[objectData establishConnectionsWithOwner:owner topLevelObjects:topLevelObjects];
[objectData awakeWithOwner:owner topLevelObjects:topLevelObjects];
+3 -9
View File
@@ -39,11 +39,9 @@
// Not having a selector is a fatal error.
if (!selector)
{
[CPException
raise:CPInvalidArgumentException
reason:@"-[" + [self className] + ' ' + _cmd + @"] selector " + selectorName + @" does not exist."];
}
// If the destination doesn't respond to this selector, warn but don't die.
if (_destination && ![_destination respondsToSelector:selector])
@@ -60,7 +58,7 @@
else
[CPException
raise:CPInvalidArgumentException
reason:@"-[" + [self className] + ' ' + _cmd + @"] " + [_source description] + @" does not respond to setAction:"];
reason:@"-[" + [self className] + ' ' + _cmd + @"] " + [_source description] + " does not respond to setAction:"];
// Not being able to set the target is a fatal error.
if ([_source respondsToSelector:@selector(setTarget:)])
@@ -69,14 +67,10 @@
else
[CPException
raise:CPInvalidArgumentException
reason:@"-[" + [self className] + ' ' + _cmd + @"] " + [_source description] + @" does not respond to setTarget:"];
reason:@"-[" + [self className] + ' ' + _cmd + @"] " + [_source description] + " does not respond to setTarget:"];
}
@end
@implementation _CPCibControlConnector : CPCibControlConnector
{
}
@end
@implementation _CPCibControlConnector : CPCibControlConnector { } @end
+5 -15
View File
@@ -46,28 +46,28 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
- (id)initWithClassName:(CPString)aClassName resourceName:(CPString)aResourceName properties:(CPDictionary)properties
{
self = [super init];
if (self)
{
_className = aClassName;
_resourceName = aResourceName;
_properties = properties;
}
return self;
}
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
_className = [aCoder decodeObjectForKey:_CPCibCustomResourceClassNameKey];
_resourceName = [aCoder decodeObjectForKey:_CPCibCustomResourceResourceNameKey];
_properties = [aCoder decodeObjectForKey:_CPCibCustomResourcePropertiesKey];
}
return self;
}
@@ -80,7 +80,7 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
- (id)awakeAfterUsingCoder:(CPCoder)aCoder
{
if ([aCoder respondsToSelector:@selector(bundle)] &&
if ([aCoder respondsToSelector:@selector(bundle)] &&
(![aCoder respondsToSelector:@selector(awakenCustomResources)] || [aCoder awakenCustomResources]))
if (_className === @"CPImage")
return [[CPImage alloc] initWithContentsOfFile:[[aCoder bundle] pathForResource:_resourceName] size:_properties.valueForKey(@"size")];
@@ -112,14 +112,4 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
return NO;
}
- (unsigned)loadStatus
{
return CPImageLoadStatusCompleted;
}
- (id)delegate
{
return nil;
}
@end
-3
View File
@@ -1,9 +1,6 @@
@import <Foundation/CPObject.j>
@import "CGGeometry.j"
@import "CPWindow.j"
var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinSizeKey",
_CPCibWindowTemplateMaxSizeKey = @"_CPCibWindowTemplateMaxSizeKey",
+6 -3
View File
@@ -22,10 +22,13 @@
@import <Foundation/CPObject.j>
@import "CABackingStore.j"
@import <AppKit/CABackingStore.j>
@import "CGContext.j"
@import "CGGeometry.j"
@import <AppKit/CGContext.j>
@import <AppKit/CGGeometry.j>
#include "../CoreGraphics/CGGeometry.h"
#include "../CoreGraphics/CGAffineTransform.j"
#define DOM(aLayer) aLayer._DOMElement
+5 -2
View File
@@ -20,11 +20,14 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CGGeometry.j"
#include "CGGeometry.h"
#include "CGAffineTransform.h"
#define _function(inline) function inline { return _##inline; }
@import "CGGeometry.j"
_function(CGAffineTransformMake(a, b, c, d, tx, ty))
_function(CGAffineTransformMakeIdentity())
_function(CGAffineTransformMakeCopy(anAffineTransform))
+5 -4
View File
@@ -20,11 +20,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CGAffineTransform.j"
@import "CPCompatibility.j"
@import "CGGeometry.j"
@import "CGPath.j"
#include "CGGeometry.h"
#include "CGAffineTransform.h"
@import "CGGeometry.j"
@import "CGAffineTransform.j"
@import "CGPath.j"
kCGLineCapButt = 0;
kCGLineCapRound = 1;
-1
View File
@@ -63,7 +63,6 @@
#define _CGInsetMakeCopy(anInset) _CGInsetMake(anInset.top, anInset.right, anInset.bottom, anInset.left)
#define _CGInsetMakeZero() _CGInsetMake(0, 0, 0, 0)
#define _CGInsetIsEmpty(anInset) ((anInset).top === 0 && (anInset).right === 0 && (anInset).bottom === 0 && (anInset).left === 0)
#define _CGInsetEqualToInset(lhsInset, rhsInset) ((lhsInset).top === (rhsInset).top && (lhsInset).right === (rhsInset).right && (lhsInset).bottom === (rhsInset).bottom && (lhsInset).left === (rhsInset).left)
// DEPRECATED
#define _CGPointCreateCopy(aPoint) _CGPointMake(aPoint.x, aPoint.y)
+17 -65
View File
@@ -20,6 +20,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "CGGeometry.h"
#define _function(inline) function inline { return _##inline; }
_function(CGPointMake(x, y))
@@ -67,12 +69,6 @@ _function(CGInsetMake(top, right, bottom, left))
_function(CGInsetMakeZero())
_function(CGInsetMakeCopy(anInset))
_function(CGInsetIsEmpty(anInset))
_function(CGInsetEqualToInset(lhsInset, rhsInset))
CGMinXEdge = 0;
CGMinYEdge = 1;
CGMaxXEdge = 2;
CGMaxYEdge = 3;
CGRectNull = _CGRectMake(Infinity, Infinity, 0.0, 0.0);
@@ -81,50 +77,6 @@ CGRectNull = _CGRectMake(Infinity, Infinity, 0.0, 0.0);
@{
*/
/*!
Creates two rectangles -- slice and rem -- from inRect, by dividing inRect
with a line that's parallel to the side of inRect specified by edge.
The size of slice is determined by amount, which specifies the distance from edge.
slice and rem must not be NULL, must not be the same object, and must not be the
same object as inRect.
@group CGRect
*/
function CGRectDivide(inRect, slice, rem, amount, edge)
{
slice.origin = _CGPointMakeCopy(inRect.origin);
slice.size = _CGSizeMakeCopy(inRect.size);
rem.origin = _CGPointMakeCopy(inRect.origin);
rem.size = _CGSizeMakeCopy(inRect.size);
switch (edge)
{
case CGMinXEdge:
slice.size.width = amount;
rem.origin.x += amount;
rem.size.width -= amount;
break;
case CGMaxXEdge:
slice.origin.x = _CGRectGetMaxX(slice) - amount;
slice.size.width = amount;
rem.size.width -= amount;
break;
case CGMinYEdge:
slice.size.height = amount;
rem.origin.y += amount;
rem.size.height -= amount;
break;
case CGMaxYEdge:
slice.origin.y = _CGRectGetMaxY(slice) - amount;
slice.size.height = amount;
rem.size.height -= amount;
}
}
/*!
Returns a \c BOOL indicating whether CGRect \c lhsRect
contains CGRect \c rhsRect.
@@ -136,7 +88,7 @@ function CGRectDivide(inRect, slice, rem, amount, edge)
function CGRectContainsRect(lhsRect, rhsRect)
{
var union = CGRectUnion(lhsRect, rhsRect);
return _CGRectEqualToRect(union, lhsRect);
}
@@ -150,12 +102,12 @@ function CGRectContainsRect(lhsRect, rhsRect)
function CGRectIntersectsRect(lhsRect, rhsRect)
{
var intersection = CGRectIntersection(lhsRect, rhsRect);
return !_CGRectIsEmpty(intersection);
}
/*!
Makes the origin and size of a CGRect all integers. Specifically, by making
Makes the origin and size of a CGRect all integers. Specifically, by making
the southwest corner the origin (rounded down), and the northeast corner a CGSize (rounded up).
@param aRect the rectangle to operate on
@return CGRect the modified rectangle (same as the input)
@@ -168,7 +120,7 @@ function CGRectIntegral(aRect)
// Store these out separately, if not the GetMaxes will return incorrect values.
var x = FLOOR(_CGRectGetMinX(aRect)),
y = FLOOR(_CGRectGetMinY(aRect));
aRect.size.width = CEIL(_CGRectGetMaxX(aRect)) - x;
aRect.size.height = CEIL(_CGRectGetMaxY(aRect)) - y;
@@ -188,18 +140,18 @@ function CGRectIntegral(aRect)
function CGRectIntersection(lhsRect, rhsRect)
{
var intersection = _CGRectMake(
MAX(_CGRectGetMinX(lhsRect), _CGRectGetMinX(rhsRect)),
MAX(_CGRectGetMinY(lhsRect), _CGRectGetMinY(rhsRect)),
MAX(_CGRectGetMinX(lhsRect), _CGRectGetMinX(rhsRect)),
MAX(_CGRectGetMinY(lhsRect), _CGRectGetMinY(rhsRect)),
0, 0);
intersection.size.width = MIN(_CGRectGetMaxX(lhsRect), _CGRectGetMaxX(rhsRect)) - _CGRectGetMinX(intersection);
intersection.size.height = MIN(_CGRectGetMaxY(lhsRect), _CGRectGetMaxY(rhsRect)) - _CGRectGetMinY(intersection);
return _CGRectIsEmpty(intersection) ? _CGRectMakeZero() : intersection;
}
/*
*/
function CGRectStandardize(aRect)
{
@@ -237,28 +189,28 @@ function CGRectUnion(lhsRect, rhsRect)
minY = MIN(_CGRectGetMinY(lhsRect), _CGRectGetMinY(rhsRect)),
maxX = MAX(_CGRectGetMaxX(lhsRect), _CGRectGetMaxX(rhsRect)),
maxY = MAX(_CGRectGetMaxY(lhsRect), _CGRectGetMaxY(rhsRect));
return _CGRectMake(minX, minY, maxX - minX, maxY - minY);
}
function CGPointFromString(aString)
{
var comma = aString.indexOf(',');
return { x:parseInt(aString.substr(1, comma - 1)), y:parseInt(aString.substring(comma + 1, aString.length)) };
}
function CGSizeFromString(aString)
{
var comma = aString.indexOf(',');
return { width:parseInt(aString.substr(1, comma - 1)), height:parseInt(aString.substring(comma + 1, aString.length)) };
}
function CGRectFromString(aString)
{
var comma = aString.indexOf(',', aString.indexOf(',') + 1);
return { origin:CGPointFromString(aString.substr(1, comma - 1)), size:CGSizeFromString(aString.substring(comma + 2, aString.length)) };
}
@@ -281,6 +233,6 @@ function CPStringFromCGInset(anInset)
return '{' + anInset.top + ", " + anInset.left + ", " + anInset.bottom + ", " + anInset.right + '}';
}
/*!
@}
/*!
@}
*/
+2 -5
View File
@@ -29,20 +29,17 @@ kCGGradientDrawsAfterEndLocation = 1 << 1;
function CGGradientCreateWithColorComponents(aColorSpace, components, locations, count)
{
if (arguments["locations"] == NULL)
var locations = [0.0, 1.0];
if (arguments["count"] == NULL)
var count = locations.length;
var colors = [];
while (count--)
{
var offset = count * 4;
colors[count] = CGColorCreate(aColorSpace, components.slice(offset, offset + 4));
}
return CGGradientCreateWithColors(aColorSpace, colors, locations);
}

Some files were not shown because too many files have changed in this diff Show More