mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-09-09 20:27:13 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4091acd0ec | ||
|
|
f8114b0760 |
+4
-9
@@ -36,8 +36,8 @@
|
|||||||
@import "CPCibLoading.j"
|
@import "CPCibLoading.j"
|
||||||
@import "CPCibOutletConnector.j"
|
@import "CPCibOutletConnector.j"
|
||||||
@import "CPClipView.j"
|
@import "CPClipView.j"
|
||||||
@import "CPCollectionView.j"
|
|
||||||
@import "CPCollectionViewItem.j"
|
@import "CPCollectionViewItem.j"
|
||||||
|
@import "CPCollectionView.j"
|
||||||
@import "CPColor.j"
|
@import "CPColor.j"
|
||||||
@import "CPColorPanel.j"
|
@import "CPColorPanel.j"
|
||||||
@import "CPColorWell.j"
|
@import "CPColorWell.j"
|
||||||
@@ -53,10 +53,8 @@
|
|||||||
@import "CPFont.j"
|
@import "CPFont.j"
|
||||||
@import "CPFontManager.j"
|
@import "CPFontManager.j"
|
||||||
@import "CPGeometry.j"
|
@import "CPGeometry.j"
|
||||||
@import "CPGraphics.j"
|
|
||||||
@import "CPImage.j"
|
@import "CPImage.j"
|
||||||
@import "CPImageView.j"
|
@import "CPImageView.j"
|
||||||
@import "CPKeyBinding.j"
|
|
||||||
@import "CPMenu.j"
|
@import "CPMenu.j"
|
||||||
@import "CPMenuItem.j"
|
@import "CPMenuItem.j"
|
||||||
@import "CPOpenPanel.j"
|
@import "CPOpenPanel.j"
|
||||||
@@ -67,22 +65,20 @@
|
|||||||
@import "CPProgressIndicator.j"
|
@import "CPProgressIndicator.j"
|
||||||
@import "CPRadio.j"
|
@import "CPRadio.j"
|
||||||
@import "CPResponder.j"
|
@import "CPResponder.j"
|
||||||
@import "CPScroller.j"
|
|
||||||
@import "CPScrollView.j"
|
|
||||||
@import "CPSearchField.j"
|
@import "CPSearchField.j"
|
||||||
|
@import "CPScrollView.j"
|
||||||
|
@import "CPScroller.j"
|
||||||
@import "CPSecureTextField.j"
|
@import "CPSecureTextField.j"
|
||||||
@import "CPSegmentedControl.j"
|
@import "CPSegmentedControl.j"
|
||||||
@import "CPShadow.j"
|
@import "CPShadow.j"
|
||||||
@import "CPSlider.j"
|
@import "CPSlider.j"
|
||||||
@import "CPSplitView.j"
|
@import "CPSplitView.j"
|
||||||
|
@import "CPTabView.j"
|
||||||
@import "CPTableColumn.j"
|
@import "CPTableColumn.j"
|
||||||
@import "CPTableView.j"
|
@import "CPTableView.j"
|
||||||
@import "CPTabView.j"
|
|
||||||
@import "CPText.j"
|
|
||||||
@import "CPTextField.j"
|
@import "CPTextField.j"
|
||||||
@import "CPToolbar.j"
|
@import "CPToolbar.j"
|
||||||
@import "CPToolbarItem.j"
|
@import "CPToolbarItem.j"
|
||||||
@import "CPTokenField.j"
|
|
||||||
@import "CPTreeNode.j"
|
@import "CPTreeNode.j"
|
||||||
@import "CPView.j"
|
@import "CPView.j"
|
||||||
@import "CPViewAnimation.j"
|
@import "CPViewAnimation.j"
|
||||||
@@ -90,4 +86,3 @@
|
|||||||
@import "CPWebView.j"
|
@import "CPWebView.j"
|
||||||
@import "CPWindow.j"
|
@import "CPWindow.j"
|
||||||
@import "CPWindowController.j"
|
@import "CPWindowController.j"
|
||||||
@import "CPArrayController.j"
|
|
||||||
|
|||||||
+11
-46
@@ -26,16 +26,11 @@
|
|||||||
@import <Foundation/CPIndexSet.j>
|
@import <Foundation/CPIndexSet.j>
|
||||||
@import <Foundation/CPString.j>
|
@import <Foundation/CPString.j>
|
||||||
|
|
||||||
@import "CPView.j"
|
@import <AppKit/CPView.j>
|
||||||
@import "CPButton.j"
|
|
||||||
|
#import "CoreGraphics/CGGeometry.h"
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@ingroup appkit
|
|
||||||
@class CPAccordionViewItem
|
|
||||||
|
|
||||||
<p>A CPAccordionViewItem represents a single section of a CPAccordionView.</p>
|
|
||||||
*/
|
|
||||||
@implementation CPAccordionViewItem : CPObject
|
@implementation CPAccordionViewItem : CPObject
|
||||||
{
|
{
|
||||||
CPString _identifier @accessors(property=identifier);
|
CPString _identifier @accessors(property=identifier);
|
||||||
@@ -48,10 +43,6 @@
|
|||||||
return [self initWithIdentifier:@""];
|
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
|
- (id)initWithIdentifier:(CPString)anIdentifier
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
@@ -64,25 +55,6 @@
|
|||||||
|
|
||||||
@end
|
@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
|
@implementation CPAccordionView : CPView
|
||||||
{
|
{
|
||||||
CPInteger _dirtyItemIndex;
|
CPInteger _dirtyItemIndex;
|
||||||
@@ -92,10 +64,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
|
|||||||
CPMutableArray _itemViews;
|
CPMutableArray _itemViews;
|
||||||
CPIndexSet _expandedItemIndexes;
|
CPIndexSet _expandedItemIndexes;
|
||||||
}
|
}
|
||||||
/*!
|
|
||||||
Initializes the receiver for usage with the specified bounding rectangle
|
|
||||||
@return the initialized view
|
|
||||||
*/
|
|
||||||
- (id)initWithFrame:(CGRect)aFrame
|
- (id)initWithFrame:(CGRect)aFrame
|
||||||
{
|
{
|
||||||
self = [super initWithFrame:aFrame];
|
self = [super initWithFrame:aFrame];
|
||||||
@@ -126,11 +95,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
|
|||||||
{
|
{
|
||||||
return _items;
|
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
|
- (void)addItem:(CPAccordionViewItem)anItem
|
||||||
{
|
{
|
||||||
[self insertItem:anItem atIndex:_items.length];
|
[self insertItem:anItem atIndex:_items.length];
|
||||||
@@ -213,7 +178,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
|
|||||||
|
|
||||||
if ([itemView isCollapsed])
|
if ([itemView isCollapsed])
|
||||||
[self expandItemAtIndex:anIndex];
|
[self expandItemAtIndex:anIndex];
|
||||||
|
|
||||||
else
|
else
|
||||||
[self collapseItemAtIndex:anIndex];
|
[self collapseItemAtIndex:anIndex];
|
||||||
}
|
}
|
||||||
@@ -237,12 +202,12 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
|
|||||||
var itemView = _itemViews[anIndex];
|
var itemView = _itemViews[anIndex];
|
||||||
if (!itemView)
|
if (!itemView)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!isEnabled)
|
if (!isEnabled)
|
||||||
[self collapseItemAtIndex:anIndex];
|
[self collapseItemAtIndex:anIndex];
|
||||||
else
|
else
|
||||||
[self expandItemAtIndex:anIndex];
|
[self expandItemAtIndex:anIndex];
|
||||||
|
|
||||||
[itemView setEnabled:isEnabled];
|
[itemView setEnabled:isEnabled];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,7 +235,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
|
|||||||
{
|
{
|
||||||
if (_items.length <= 0)
|
if (_items.length <= 0)
|
||||||
return [self setFrameSize:_CGSizeMake(_CGRectGetWidth([self frame]), 0.0)];
|
return [self setFrameSize:_CGSizeMake(_CGRectGetWidth([self frame]), 0.0)];
|
||||||
|
|
||||||
if (_dirtyItemIndex === CPNotFound)
|
if (_dirtyItemIndex === CPNotFound)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -391,7 +356,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
|
|||||||
|
|
||||||
[_contentView setFrameSize:_CGSizeMake(aWidth, contentHeight)];
|
[_contentView setFrameSize:_CGSizeMake(aWidth, contentHeight)];
|
||||||
[self setFrame:_CGRectMake(0.0, aY, aWidth, contentHeight + headerHeight)];
|
[self setFrame:_CGRectMake(0.0, aY, aWidth, contentHeight + headerHeight)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)resizeSubviewsWithOldSize:(CGSize)aSize
|
- (void)resizeSubviewsWithOldSize:(CGSize)aSize
|
||||||
@@ -408,7 +373,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
|
|||||||
/*
|
/*
|
||||||
else if (aKeyPath === "itemHeaderPrototype")
|
else if (aKeyPath === "itemHeaderPrototype")
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|||||||
+102
-256
@@ -26,34 +26,39 @@
|
|||||||
@import <Foundation/CPObject.j>
|
@import <Foundation/CPObject.j>
|
||||||
@import <Foundation/CPString.j>
|
@import <Foundation/CPString.j>
|
||||||
|
|
||||||
@import "CPApplication.j"
|
@import <AppKit/CPApplication.j>
|
||||||
@import "CPButton.j"
|
@import <AppKit/CPButton.j>
|
||||||
@import "CPColor.j"
|
@import <AppKit/CPColor.j>
|
||||||
@import "CPFont.j"
|
@import <AppKit/CPFont.j>
|
||||||
@import "CPImage.j"
|
@import <AppKit/CPImage.j>
|
||||||
@import "CPImageView.j"
|
@import <AppKit/CPImageView.j>
|
||||||
@import "CPPanel.j"
|
@import <AppKit/CPPanel.j>
|
||||||
@import "CPTextField.j"
|
@import <AppKit/CPTextField.j>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@global
|
@global
|
||||||
@group CPAlertStyle
|
@group CPAlertStyle
|
||||||
*/
|
*/
|
||||||
CPWarningAlertStyle = 0;
|
CPWarningAlertStyle = 0;
|
||||||
/*
|
/*
|
||||||
@global
|
@global
|
||||||
@group CPAlertStyle
|
@group CPAlertStyle
|
||||||
*/
|
*/
|
||||||
CPInformationalAlertStyle = 1;
|
CPInformationalAlertStyle = 1;
|
||||||
/*
|
/*
|
||||||
@global
|
@global
|
||||||
@group CPAlertStyle
|
@group CPAlertStyle
|
||||||
*/
|
*/
|
||||||
CPCriticalAlertStyle = 2;
|
CPCriticalAlertStyle = 2;
|
||||||
|
|
||||||
|
|
||||||
|
var CPAlertWarningImage,
|
||||||
|
CPAlertInformationImage,
|
||||||
|
CPAlertErrorImage;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
|
|
||||||
CPAlert is an alert panel that can be displayed modally to present the
|
CPAlert is an alert panel that can be displayed modally to present the
|
||||||
user with a message and one or more options.
|
user with a message and one or more options.
|
||||||
|
|
||||||
@@ -69,51 +74,41 @@ CPCriticalAlertStyle = 2;
|
|||||||
@delegate -(void)alertDidEnd:(CPAlert)theAlert returnCode:(int)returnCode;
|
@delegate -(void)alertDidEnd:(CPAlert)theAlert returnCode:(int)returnCode;
|
||||||
Called when the user dismisses the alert by clicking one of the buttons.
|
Called when the user dismisses the alert by clicking one of the buttons.
|
||||||
@param theAlert the alert panel that the user dismissed
|
@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
|
representing the first button added to the alert which appears on the
|
||||||
right, 1 representing the next button to the left and so on)
|
right, 1 representing the next button to the left and so on)
|
||||||
*/
|
*/
|
||||||
@implementation CPAlert : CPView
|
@implementation CPAlert : CPObject
|
||||||
{
|
{
|
||||||
CPPanel _alertPanel;
|
CPPanel _alertPanel;
|
||||||
|
|
||||||
CPTextField _messageLabel;
|
CPTextField _messageLabel;
|
||||||
CPTextField _informativeLabel;
|
|
||||||
CPImageView _alertImageView;
|
CPImageView _alertImageView;
|
||||||
|
|
||||||
CPAlertStyle _alertStyle;
|
CPAlertStyle _alertStyle;
|
||||||
CPString _windowTitle;
|
CPString _windowTitle;
|
||||||
int _windowStyle;
|
int _windowStyle;
|
||||||
|
int _buttonCount;
|
||||||
CPArray _buttons;
|
CPArray _buttons;
|
||||||
|
|
||||||
id _delegate;
|
id _delegate;
|
||||||
SEL _didEndSelector;
|
|
||||||
id _modalDelegate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (CPString)defaultThemeClass
|
+ (void)initialize
|
||||||
{
|
{
|
||||||
return @"alert";
|
if (self != CPAlert)
|
||||||
}
|
return;
|
||||||
|
|
||||||
+ (id)themeAttributes
|
var bundle = [CPBundle bundleForClass:[self class]];
|
||||||
{
|
|
||||||
return [CPDictionary dictionaryWithObjects:[CGSizeMake(400.0, 110.0), CGInsetMake(15, 15, 15, 50), 6, 10,
|
CPAlertWarningImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPAlert/dialog-warning.png"]
|
||||||
CPJustifiedTextAlignment, [CPColor blackColor], [CPFont boldSystemFontOfSize:13.0], [CPNull null], CGSizeMakeZero(),
|
size:CGSizeMake(32.0, 32.0)];
|
||||||
CPJustifiedTextAlignment, [CPColor blackColor], [CPFont systemFontOfSize:12.0], [CPNull null], CGSizeMakeZero(),
|
|
||||||
CGPointMake(15, 12),
|
CPAlertInformationImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPAlert/dialog-information.png"]
|
||||||
[CPNull null],
|
size:CGSizeMake(32.0, 32.0)];
|
||||||
[CPNull null],
|
|
||||||
[CPNull null]
|
CPAlertErrorImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPAlert/dialog-error.png"]
|
||||||
]
|
size:CGSizeMake(32.0, 32.0)];
|
||||||
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"
|
|
||||||
]];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -123,56 +118,57 @@ CPCriticalAlertStyle = 2;
|
|||||||
{
|
{
|
||||||
if (self = [super init])
|
if (self = [super init])
|
||||||
{
|
{
|
||||||
|
_buttonCount = 0;
|
||||||
_buttons = [CPArray array];
|
_buttons = [CPArray array];
|
||||||
_alertStyle = CPWarningAlertStyle;
|
_alertStyle = CPWarningAlertStyle;
|
||||||
_alertPanel = nil;
|
|
||||||
_windowStyle = nil;
|
|
||||||
_didEndSelector = nil;
|
|
||||||
|
|
||||||
_messageLabel = [CPTextField labelWithTitle:@"Alert"];
|
[self setWindowStyle:nil];
|
||||||
_alertImageView = [[CPImageView alloc] initWithFrame:CGRectMakeZero()];
|
|
||||||
_informativeLabel = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Sets the window appearance. If CPHUDBackgroundWindowMask is set, the default HUD theme
|
Sets the window appearance.
|
||||||
will be activated.
|
|
||||||
|
|
||||||
@param styleMask - Either CPHUDBackgroundWindowMask or nil for standard.
|
@param styleMask - Either CPHUDBackgroundWindowMask or nil for standard.
|
||||||
*/
|
*/
|
||||||
- (void)setWindowStyle:(int)styleMask
|
- (void)setWindowStyle:(int)styleMask
|
||||||
{
|
{
|
||||||
_windowStyle = 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.
|
var count = [_buttons count];
|
||||||
_alertPanel = nil;
|
for(var i=0; i < count; i++)
|
||||||
}
|
|
||||||
|
|
||||||
- (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)
|
|
||||||
{
|
{
|
||||||
while (count--)
|
var button = _buttons[i];
|
||||||
[contentView addSubview:_buttons[count]];
|
|
||||||
}
|
[button setFrameSize:CGSizeMake([button frame].size.width, (styleMask == CPHUDBackgroundWindowMask) ? 20.0 : 24.0)];
|
||||||
else
|
|
||||||
[self addButtonWithTitle:@"OK"];
|
[button setTheme:(_windowStyle === CPHUDBackgroundWindowMask) ? [CPTheme themeNamed:"Aristo-HUD"] : [CPTheme defaultTheme]];
|
||||||
|
|
||||||
[contentView addSubview:_messageLabel];
|
[[_alertPanel contentView] addSubview:button];
|
||||||
[contentView addSubview:_alertImageView];
|
}
|
||||||
[contentView addSubview:_informativeLabel];
|
|
||||||
|
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 receiver’s message text, or title, to a given text.
|
Set’s the receiver’s message text, or title, to a given text.
|
||||||
@param messageText - Message text for the alert.
|
@param messageText - Message text for the alert.
|
||||||
*/
|
*/
|
||||||
- (void)setMessageText:(CPString)messageText
|
- (void)setMessageText:(CPString)messageText
|
||||||
@@ -243,157 +239,41 @@ CPCriticalAlertStyle = 2;
|
|||||||
[_messageLabel setStringValue:messageText];
|
[_messageLabel setStringValue:messageText];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns the receiver's message text body.
|
Return's the receiver's message text body.
|
||||||
*/
|
*/
|
||||||
- (CPString)messageText
|
- (CPString)messageText
|
||||||
{
|
{
|
||||||
return [_messageLabel stringValue];
|
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.
|
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.
|
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 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.
|
You really shouldn't need more than 3 buttons.
|
||||||
*/
|
*/
|
||||||
- (void)addButtonWithTitle:(CPString)title
|
- (void)addButtonWithTitle:(CPString)title
|
||||||
{
|
{
|
||||||
var bounds = [[_alertPanel contentView] bounds],
|
var bounds = [[_alertPanel contentView] bounds],
|
||||||
button = [[CPButton alloc] initWithFrame:CGRectMakeZero()],
|
button = [[CPButton alloc] initWithFrame:CGRectMake(CGRectGetWidth(bounds) - ((_buttonCount + 1) * 90.0), CGRectGetHeight(bounds) - 34.0, 80.0, (_windowStyle == CPHUDBackgroundWindowMask) ? 20.0 : 24.0)];
|
||||||
_buttonCount = [_buttons count];
|
|
||||||
|
|
||||||
[button setTitle:title];
|
[button setTitle:title];
|
||||||
[button setTarget:self];
|
[button setTarget:self];
|
||||||
[button setTag:_buttonCount];
|
[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];
|
[[_alertPanel contentView] addSubview:button];
|
||||||
|
|
||||||
if (_buttonCount == 0)
|
if (_buttonCount == 0)
|
||||||
[button setKeyEquivalent:CPCarriageReturnCharacter];
|
[_alertPanel setDefaultButton:button];
|
||||||
else if ([title lowercaseString] === "cancel")
|
|
||||||
[button setKeyEquivalent:CPEscapeFunctionKey];
|
|
||||||
else
|
|
||||||
[button setKeyEquivalent:nil];
|
|
||||||
|
|
||||||
[_buttons insertObject:button atIndex:0];
|
_buttonCount++;
|
||||||
}
|
[_buttons addObject:button];
|
||||||
|
|
||||||
- (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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -403,68 +283,34 @@ CPCriticalAlertStyle = 2;
|
|||||||
*/
|
*/
|
||||||
- (void)runModal
|
- (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];
|
[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 */
|
/* @ignore */
|
||||||
- (void)_dismissAlert:(CPButton)button
|
- (void)_notifyDelegate:(id)button
|
||||||
{
|
{
|
||||||
if ([_alertPanel isSheet])
|
[CPApp abortModal];
|
||||||
[CPApp endSheet:_alertPanel returnCode:[button tag]];
|
[_alertPanel close];
|
||||||
else
|
|
||||||
{
|
|
||||||
[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
|
@end
|
||||||
|
|||||||
+27
-27
@@ -48,14 +48,14 @@ CPAnimationLinear = 3;
|
|||||||
|
|
||||||
ACTUAL_FRAME_RATE = 0;
|
ACTUAL_FRAME_RATE = 0;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPAnimation
|
@class CPAnimation
|
||||||
|
|
||||||
Manages an animation. Contains timing and progress information.
|
Manages an animation. Contains timing and progress information.
|
||||||
|
|
||||||
@par Delegate Methods
|
@par Delegate Methods
|
||||||
|
|
||||||
@delegate -(BOOL)animationShouldStart:(CPAnimation)animation;
|
@delegate -(BOOL)animationShouldStart:(CPAnimation)animation;
|
||||||
Called at the beginning of \c -startAnimation.
|
Called at the beginning of \c -startAnimation.
|
||||||
@param animation the animation that will start
|
@param animation the animation that will start
|
||||||
@@ -81,13 +81,13 @@ ACTUAL_FRAME_RATE = 0;
|
|||||||
{
|
{
|
||||||
CPTimeInterval _lastTime;
|
CPTimeInterval _lastTime;
|
||||||
CPTimeInterval _duration;
|
CPTimeInterval _duration;
|
||||||
|
|
||||||
CPAnimationCurve _animationCurve;
|
CPAnimationCurve _animationCurve;
|
||||||
CAMediaTimingFunction _timingFunction;
|
CAMediaTimingFunction _timingFunction;
|
||||||
|
|
||||||
float _frameRate;
|
float _frameRate;
|
||||||
float _progress;
|
float _progress;
|
||||||
|
|
||||||
id _delegate;
|
id _delegate;
|
||||||
CPTimer _timer;
|
CPTimer _timer;
|
||||||
}
|
}
|
||||||
@@ -101,7 +101,7 @@ ACTUAL_FRAME_RATE = 0;
|
|||||||
- (id)initWithDuration:(float)aDuration animationCurve:(CPAnimationCurve)anAnimationCurve
|
- (id)initWithDuration:(float)aDuration animationCurve:(CPAnimationCurve)anAnimationCurve
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_progress = 0.0;
|
_progress = 0.0;
|
||||||
@@ -110,14 +110,14 @@ ACTUAL_FRAME_RATE = 0;
|
|||||||
|
|
||||||
[self setAnimationCurve:anAnimationCurve];
|
[self setAnimationCurve:anAnimationCurve];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Sets the animation's pace.
|
Sets the animation's pace.
|
||||||
@param anAnimationCurve 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
|
- (void)setAnimationCurve:(CPAnimationCurve)anAnimationCurve
|
||||||
{
|
{
|
||||||
@@ -125,13 +125,13 @@ ACTUAL_FRAME_RATE = 0;
|
|||||||
{
|
{
|
||||||
case CPAnimationEaseInOut: timingFunctionName = kCAMediaTimingFunctionEaseInEaseOut;
|
case CPAnimationEaseInOut: timingFunctionName = kCAMediaTimingFunctionEaseInEaseOut;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CPAnimationEaseIn: timingFunctionName = kCAMediaTimingFunctionEaseIn;
|
case CPAnimationEaseIn: timingFunctionName = kCAMediaTimingFunctionEaseIn;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CPAnimationEaseOut: timingFunctionName = kCAMediaTimingFunctionEaseOut;
|
case CPAnimationEaseOut: timingFunctionName = kCAMediaTimingFunctionEaseOut;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CPAnimationLinear: timingFunctionName = kCAMediaTimingFunctionLinear;
|
case CPAnimationLinear: timingFunctionName = kCAMediaTimingFunctionLinear;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ ACTUAL_FRAME_RATE = 0;
|
|||||||
reason:"Invalid value provided for animation curve"];
|
reason:"Invalid value provided for animation curve"];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
_animationCurve = anAnimationCurve;
|
_animationCurve = anAnimationCurve;
|
||||||
_timingFunction = [CAMediaTimingFunction functionWithName:timingFunctionName];
|
_timingFunction = [CAMediaTimingFunction functionWithName:timingFunctionName];
|
||||||
}
|
}
|
||||||
@@ -161,7 +161,7 @@ ACTUAL_FRAME_RATE = 0;
|
|||||||
{
|
{
|
||||||
if (aDuration < 0)
|
if (aDuration < 0)
|
||||||
[CPException raise:CPInvalidArgumentException reason:"aDuration can't be negative"];
|
[CPException raise:CPInvalidArgumentException reason:"aDuration can't be negative"];
|
||||||
|
|
||||||
_duration = aDuration;
|
_duration = aDuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,7 +182,7 @@ ACTUAL_FRAME_RATE = 0;
|
|||||||
{
|
{
|
||||||
if (frameRate < 0)
|
if (frameRate < 0)
|
||||||
[CPException raise:CPInvalidArgumentException reason:"frameRate can't be negative"];
|
[CPException raise:CPInvalidArgumentException reason:"frameRate can't be negative"];
|
||||||
|
|
||||||
_frameRate = frameRate;
|
_frameRate = frameRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,13 +221,13 @@ ACTUAL_FRAME_RATE = 0;
|
|||||||
// If we're already animating, or our delegate stops us, animate.
|
// If we're already animating, or our delegate stops us, animate.
|
||||||
if (_timer || _delegate && [_delegate respondsToSelector:@selector(animationShouldStart:)] && ![_delegate animationShouldStart:self])
|
if (_timer || _delegate && [_delegate respondsToSelector:@selector(animationShouldStart:)] && ![_delegate animationShouldStart:self])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_progress === 1.0)
|
if (_progress === 1.0)
|
||||||
_progress = 0.0;
|
_progress = 0.0;
|
||||||
|
|
||||||
ACTUAL_FRAME_RATE = 0;
|
ACTUAL_FRAME_RATE = 0;
|
||||||
_lastTime = new Date();
|
_lastTime = new Date();
|
||||||
|
|
||||||
_timer = [CPTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(animationTimerDidFire:) userInfo:nil repeats:YES];
|
_timer = [CPTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(animationTimerDidFire:) userInfo:nil repeats:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,14 +242,14 @@ ACTUAL_FRAME_RATE = 0;
|
|||||||
_lastTime = currentTime;
|
_lastTime = currentTime;
|
||||||
|
|
||||||
++ACTUAL_FRAME_RATE;
|
++ACTUAL_FRAME_RATE;
|
||||||
|
|
||||||
[self setCurrentProgress:progress];
|
[self setCurrentProgress:progress];
|
||||||
|
|
||||||
if (progress === 1.0)
|
if (progress === 1.0)
|
||||||
{
|
{
|
||||||
[_timer invalidate];
|
[_timer invalidate];
|
||||||
_timer = nil;
|
_timer = nil;
|
||||||
|
|
||||||
if ([_delegate respondsToSelector:@selector(animationDidEnd:)])
|
if ([_delegate respondsToSelector:@selector(animationDidEnd:)])
|
||||||
[_delegate animationDidEnd:self];
|
[_delegate animationDidEnd:self];
|
||||||
}
|
}
|
||||||
@@ -262,10 +262,10 @@ ACTUAL_FRAME_RATE = 0;
|
|||||||
{
|
{
|
||||||
if (!_timer)
|
if (!_timer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[_timer invalidate];
|
[_timer invalidate];
|
||||||
_timer = nil;
|
_timer = nil;
|
||||||
|
|
||||||
if ([_delegate respondsToSelector:@selector(animationDidStop:)])
|
if ([_delegate respondsToSelector:@selector(animationDidStop:)])
|
||||||
[_delegate animationDidStop:self];
|
[_delegate animationDidStop:self];
|
||||||
}
|
}
|
||||||
@@ -302,16 +302,16 @@ ACTUAL_FRAME_RATE = 0;
|
|||||||
- (float)currentValue
|
- (float)currentValue
|
||||||
{
|
{
|
||||||
var t = [self currentProgress];
|
var t = [self currentProgress];
|
||||||
|
|
||||||
if ([_delegate respondsToSelector:@selector(animation:valueForProgress:)])
|
if ([_delegate respondsToSelector:@selector(animation:valueForProgress:)])
|
||||||
return [_delegate animation:self valueForProgress:t];
|
return [_delegate animation:self valueForProgress:t];
|
||||||
|
|
||||||
var c1 = [],
|
var c1 = [],
|
||||||
c2 = [];
|
c2 = [];
|
||||||
|
|
||||||
[_timingFunction getControlPointAtIndex:1 values:c1];
|
[_timingFunction getControlPointAtIndex:1 values:c1];
|
||||||
[_timingFunction getControlPointAtIndex:2 values:c2];
|
[_timingFunction getControlPointAtIndex:2 values:c2];
|
||||||
|
|
||||||
return CubicBezierAtTime(t,c1[0],c1[1],c2[0],c2[1],_duration);
|
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));};
|
function solve(x,epsilon) {return sampleCurveY(solveCurveX(x,epsilon));};
|
||||||
// Given an x value, find a parametric value it came from.
|
// Given an x value, find a parametric value it came from.
|
||||||
function solveCurveX(x,epsilon) {var t0,t1,t2,x2,d2,i;
|
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.
|
// 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;}
|
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.
|
// Fall back to the bisection method for reliability.
|
||||||
|
|||||||
+146
-171
@@ -31,6 +31,7 @@
|
|||||||
@import "CPCibLoading.j"
|
@import "CPCibLoading.j"
|
||||||
@import "CPPlatform.j"
|
@import "CPPlatform.j"
|
||||||
|
|
||||||
|
#include "Platform/Platform.h"
|
||||||
|
|
||||||
var CPMainCibFile = @"CPMainCibFile",
|
var CPMainCibFile = @"CPMainCibFile",
|
||||||
CPMainCibFileHumanFriendly = @"Main cib file base name";
|
CPMainCibFileHumanFriendly = @"Main cib file base name";
|
||||||
@@ -53,7 +54,7 @@ CPRunStoppedResponse = -1000;
|
|||||||
CPRunAbortedResponse = -1001;
|
CPRunAbortedResponse = -1001;
|
||||||
CPRunContinuesResponse = -1002;
|
CPRunContinuesResponse = -1002;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPApplication
|
@class CPApplication
|
||||||
|
|
||||||
@@ -61,7 +62,7 @@ CPRunContinuesResponse = -1002;
|
|||||||
Every GUI application has exactly one instance of CPApplication (or of a custom subclass of
|
Every GUI application has exactly one instance of CPApplication (or of a custom subclass of
|
||||||
CPApplication). Your program's main() function can create that instance by calling the
|
CPApplication). Your program's main() function can create that instance by calling the
|
||||||
\c CPApplicationMain function. A simple example looks like this:
|
\c CPApplicationMain function. A simple example looks like this:
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
function main(args, namedArgs)
|
function main(args, namedArgs)
|
||||||
{
|
{
|
||||||
@@ -81,25 +82,25 @@ CPRunContinuesResponse = -1002;
|
|||||||
@implementation CPApplication : CPResponder
|
@implementation CPApplication : CPResponder
|
||||||
{
|
{
|
||||||
CPArray _eventListeners;
|
CPArray _eventListeners;
|
||||||
|
|
||||||
CPEvent _currentEvent;
|
CPEvent _currentEvent;
|
||||||
|
|
||||||
CPArray _windows;
|
CPArray _windows;
|
||||||
CPWindow _keyWindow;
|
CPWindow _keyWindow;
|
||||||
CPWindow _mainWindow;
|
CPWindow _mainWindow;
|
||||||
CPWindow _previousKeyWindow;
|
CPWindow _previousKeyWindow;
|
||||||
CPWindow _previousMainWindow;
|
CPWindow _previousMainWindow;
|
||||||
|
|
||||||
CPMenu _mainMenu;
|
CPMenu _mainMenu;
|
||||||
CPDocumentController _documentController;
|
CPDocumentController _documentController;
|
||||||
|
|
||||||
CPModalSession _currentSession;
|
CPModalSession _currentSession;
|
||||||
|
|
||||||
//
|
//
|
||||||
id _delegate;
|
id _delegate;
|
||||||
BOOL _finishedLaunching;
|
BOOL _finishedLaunching;
|
||||||
BOOL _isActive;
|
BOOL _isActive;
|
||||||
|
|
||||||
CPDictionary _namedArgs;
|
CPDictionary _namedArgs;
|
||||||
CPArray _args;
|
CPArray _args;
|
||||||
CPString _fullArgsString;
|
CPString _fullArgsString;
|
||||||
@@ -107,8 +108,6 @@ CPRunContinuesResponse = -1002;
|
|||||||
CPImage _applicationIconImage;
|
CPImage _applicationIconImage;
|
||||||
|
|
||||||
CPPanel _aboutPanel;
|
CPPanel _aboutPanel;
|
||||||
|
|
||||||
CPThemeBlend _themeBlend @accessors(property=themeBlend);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -120,7 +119,7 @@ CPRunContinuesResponse = -1002;
|
|||||||
{
|
{
|
||||||
if (!CPApp)
|
if (!CPApp)
|
||||||
CPApp = [[CPApplication alloc] init];
|
CPApp = [[CPApplication alloc] init];
|
||||||
|
|
||||||
return CPApp;
|
return CPApp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,18 +131,73 @@ CPRunContinuesResponse = -1002;
|
|||||||
- (id)init
|
- (id)init
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
CPApp = self;
|
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_eventListeners = [];
|
_eventListeners = [];
|
||||||
|
|
||||||
_windows = [];
|
_windows = [];
|
||||||
|
|
||||||
[_windows addObject:nil];
|
[_windows addObject:nil];
|
||||||
}
|
|
||||||
|
// FIXME: This should be read from the cib.
|
||||||
|
_mainMenu = [[CPMenu alloc] initWithTitle:@"MainMenu"];
|
||||||
|
|
||||||
|
// FIXME: We should implement autoenabling.
|
||||||
|
[_mainMenu setAutoenablesItems:NO];
|
||||||
|
|
||||||
|
var bundle = [CPBundle bundleForClass:[CPApplication class]],
|
||||||
|
newMenuItem = [[CPMenuItem alloc] initWithTitle:@"New" action:@selector(newDocument:) keyEquivalent:@"n"];
|
||||||
|
|
||||||
|
[newMenuItem setImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/New.png"] size:CGSizeMake(16.0, 16.0)]];
|
||||||
|
[newMenuItem setAlternateImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/NewHighlighted.png"] size:CGSizeMake(16.0, 16.0)]];
|
||||||
|
|
||||||
|
[_mainMenu addItem:newMenuItem];
|
||||||
|
|
||||||
|
var openMenuItem = [[CPMenuItem alloc] initWithTitle:@"Open" action:@selector(openDocument:) keyEquivalent:@"o"];
|
||||||
|
|
||||||
|
[openMenuItem setImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/Open.png"] size:CGSizeMake(16.0, 16.0)]];
|
||||||
|
[openMenuItem setAlternateImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/OpenHighlighted.png"] size:CGSizeMake(16.0, 16.0)]];
|
||||||
|
|
||||||
|
[_mainMenu addItem:openMenuItem];
|
||||||
|
|
||||||
|
var saveMenu = [[CPMenu alloc] initWithTitle:@"Save"],
|
||||||
|
saveMenuItem = [[CPMenuItem alloc] initWithTitle:@"Save" action:@selector(saveDocument:) keyEquivalent:nil];
|
||||||
|
|
||||||
|
[saveMenuItem setImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/Save.png"] size:CGSizeMake(16.0, 16.0)]];
|
||||||
|
[saveMenuItem setAlternateImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/SaveHighlighted.png"] size:CGSizeMake(16.0, 16.0)]];
|
||||||
|
|
||||||
|
[saveMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Save" action:@selector(saveDocument:) keyEquivalent:@"s"]];
|
||||||
|
[saveMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Save As" action:@selector(saveDocumentAs:) keyEquivalent:nil]];
|
||||||
|
|
||||||
|
[saveMenuItem setSubmenu:saveMenu];
|
||||||
|
|
||||||
|
[_mainMenu addItem:saveMenuItem];
|
||||||
|
|
||||||
|
var editMenuItem = [[CPMenuItem alloc] initWithTitle:@"Edit" action:nil keyEquivalent:nil],
|
||||||
|
editMenu = [[CPMenu alloc] initWithTitle:@"Edit"],
|
||||||
|
|
||||||
|
undoMenuItem = [[CPMenuItem alloc] initWithTitle:@"Undo" action:@selector(undo:) keyEquivalent:CPUndoKeyEquivalent],
|
||||||
|
redoMenuItem = [[CPMenuItem alloc] initWithTitle:@"Redo" action:@selector(redo:) keyEquivalent:CPRedoKeyEquivalent];
|
||||||
|
|
||||||
|
[undoMenuItem setKeyEquivalentModifierMask:CPUndoKeyEquivalentModifierMask];
|
||||||
|
[redoMenuItem setKeyEquivalentModifierMask:CPRedoKeyEquivalentModifierMask];
|
||||||
|
|
||||||
|
[editMenu addItem:undoMenuItem];
|
||||||
|
[editMenu addItem:redoMenuItem];
|
||||||
|
|
||||||
|
[editMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Cut" action:@selector(cut:) keyEquivalent:@"x"]],
|
||||||
|
[editMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Copy" action:@selector(copy:) keyEquivalent:@"c"]],
|
||||||
|
[editMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Paste" action:@selector(paste:) keyEquivalent:@"v"]];
|
||||||
|
|
||||||
|
[editMenuItem setSubmenu:editMenu];
|
||||||
|
[editMenuItem setHidden:YES];
|
||||||
|
|
||||||
|
[_mainMenu addItem:editMenuItem];
|
||||||
|
|
||||||
|
[_mainMenu addItem:[CPMenuItem separatorItem]];
|
||||||
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,28 +278,28 @@ CPRunContinuesResponse = -1002;
|
|||||||
|
|
||||||
// We also want to set the default cursor on the body, so that buttons and things don't have an iBeam
|
// We also want to set the default cursor on the body, so that buttons and things don't have an iBeam
|
||||||
[[CPCursor arrowCursor] set];
|
[[CPCursor arrowCursor] set];
|
||||||
|
|
||||||
var bundle = [CPBundle mainBundle],
|
var bundle = [CPBundle mainBundle],
|
||||||
types = [bundle objectForInfoDictionaryKey:@"CPBundleDocumentTypes"];
|
types = [bundle objectForInfoDictionaryKey:@"CPBundleDocumentTypes"];
|
||||||
|
|
||||||
if ([types count] > 0)
|
if ([types count] > 0)
|
||||||
_documentController = [CPDocumentController sharedDocumentController];
|
_documentController = [CPDocumentController sharedDocumentController];
|
||||||
|
|
||||||
var delegateClassName = [bundle objectForInfoDictionaryKey:@"CPApplicationDelegateClass"];
|
var delegateClassName = [bundle objectForInfoDictionaryKey:@"CPApplicationDelegateClass"];
|
||||||
|
|
||||||
if (delegateClassName)
|
if (delegateClassName)
|
||||||
{
|
{
|
||||||
var delegateClass = objj_getClass(delegateClassName);
|
var delegateClass = objj_getClass(delegateClassName);
|
||||||
|
|
||||||
if (delegateClass)
|
if (delegateClass)
|
||||||
if ([_documentController class] == delegateClass)
|
if ([_documentController class] == delegateClass)
|
||||||
[self setDelegate:_documentController];
|
[self setDelegate:_documentController];
|
||||||
else
|
else
|
||||||
[self setDelegate:[[delegateClass alloc] init]];
|
[self setDelegate:[[delegateClass alloc] init]];
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaultCenter = [CPNotificationCenter defaultCenter];
|
var defaultCenter = [CPNotificationCenter defaultCenter];
|
||||||
|
|
||||||
[defaultCenter
|
[defaultCenter
|
||||||
postNotificationName:CPApplicationWillFinishLaunchingNotification
|
postNotificationName:CPApplicationWillFinishLaunchingNotification
|
||||||
object:self];
|
object:self];
|
||||||
@@ -326,9 +380,7 @@ CPRunContinuesResponse = -1002;
|
|||||||
applicationVersion = [options objectForKey:@"ApplicationVersion"] || [mainInfo objectForKey:@"CPBundleShortVersionString"],
|
applicationVersion = [options objectForKey:@"ApplicationVersion"] || [mainInfo objectForKey:@"CPBundleShortVersionString"],
|
||||||
copyright = [options objectForKey:@"Copyright"] || [mainInfo objectForKey:@"CPHumanReadableCopyright"];
|
copyright = [options objectForKey:@"Copyright"] || [mainInfo objectForKey:@"CPHumanReadableCopyright"];
|
||||||
|
|
||||||
var aboutPanelPath = [[CPBundle bundleForClass:[CPWindowController class]] pathForResource:@"AboutPanel.cib"],
|
var aboutPanelController = [[CPWindowController alloc] initWithWindowCibName:@"AboutPanel"],
|
||||||
aboutPanelController = [CPWindowController alloc],
|
|
||||||
aboutPanelController = [aboutPanelController initWithWindowCibPath:aboutPanelPath owner:aboutPanelController],
|
|
||||||
aboutPanel = [aboutPanelController window],
|
aboutPanel = [aboutPanelController window],
|
||||||
contentView = [aboutPanel contentView],
|
contentView = [aboutPanel contentView],
|
||||||
imageView = [contentView viewWithTag:1],
|
imageView = [contentView viewWithTag:1],
|
||||||
@@ -336,14 +388,14 @@ CPRunContinuesResponse = -1002;
|
|||||||
versionLabel = [contentView viewWithTag:3],
|
versionLabel = [contentView viewWithTag:3],
|
||||||
copyrightLabel = [contentView viewWithTag:4],
|
copyrightLabel = [contentView viewWithTag:4],
|
||||||
standardPath = [[CPBundle bundleForClass:[self class]] pathForResource:@"standardApplicationIcon.png"];
|
standardPath = [[CPBundle bundleForClass:[self class]] pathForResource:@"standardApplicationIcon.png"];
|
||||||
|
|
||||||
// FIXME move this into the CIB eventually
|
// FIXME move this into the CIB eventually
|
||||||
[applicationLabel setFont:[CPFont boldSystemFontOfSize:14.0]];
|
[applicationLabel setFont:[CPFont boldSystemFontOfSize:14.0]];
|
||||||
[applicationLabel setAlignment:CPCenterTextAlignment];
|
[applicationLabel setAlignment:CPCenterTextAlignment];
|
||||||
[versionLabel setAlignment:CPCenterTextAlignment];
|
[versionLabel setAlignment:CPCenterTextAlignment];
|
||||||
[copyrightLabel setAlignment:CPCenterTextAlignment];
|
[copyrightLabel setAlignment:CPCenterTextAlignment];
|
||||||
|
|
||||||
[imageView setImage:applicationIcon || [[CPImage alloc] initWithContentsOfFile:standardPath
|
[imageView setImage:applicationIcon || [[CPImage alloc] initWithContentsOfFile:standardPath
|
||||||
size:CGSizeMake(256, 256)]];
|
size:CGSizeMake(256, 256)]];
|
||||||
|
|
||||||
[applicationLabel setStringValue:applicationTitle || ""];
|
[applicationLabel setStringValue:applicationTitle || ""];
|
||||||
@@ -447,10 +499,10 @@ CPRunContinuesResponse = -1002;
|
|||||||
return;
|
return;
|
||||||
// raise exception;
|
// raise exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentSession._state = aCode;
|
_currentSession._state = aCode;
|
||||||
_currentSession = _currentSession._previous;
|
_currentSession = _currentSession._previous;
|
||||||
|
|
||||||
// if (aCode == CPRunAbortedResponse)
|
// if (aCode == CPRunAbortedResponse)
|
||||||
[self _removeRunModalLoop];
|
[self _removeRunModalLoop];
|
||||||
}
|
}
|
||||||
@@ -459,12 +511,12 @@ CPRunContinuesResponse = -1002;
|
|||||||
- (void)_removeRunModalLoop
|
- (void)_removeRunModalLoop
|
||||||
{
|
{
|
||||||
var count = _eventListeners.length;
|
var count = _eventListeners.length;
|
||||||
|
|
||||||
while (count--)
|
while (count--)
|
||||||
if (_eventListeners[count]._callback === _CPRunModalLoop)
|
if (_eventListeners[count]._callback === _CPRunModalLoop)
|
||||||
{
|
{
|
||||||
_eventListeners.splice(count, 1);
|
_eventListeners.splice(count, 1);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -502,13 +554,12 @@ CPRunContinuesResponse = -1002;
|
|||||||
{
|
{
|
||||||
aModalSession._previous = _currentSession;
|
aModalSession._previous = _currentSession;
|
||||||
_currentSession = aModalSession;
|
_currentSession = aModalSession;
|
||||||
|
|
||||||
var theWindow = aModalSession._window;
|
var theWindow = aModalSession._window;
|
||||||
|
|
||||||
[theWindow center];
|
[theWindow center];
|
||||||
[theWindow makeKeyWindow];
|
[theWindow makeKeyAndOrderFront:self];
|
||||||
[theWindow orderFront:self];
|
|
||||||
|
|
||||||
// [theWindow._bridge _obscureWindowsBelowModalWindow];
|
// [theWindow._bridge _obscureWindowsBelowModalWindow];
|
||||||
|
|
||||||
[CPApp setCallback:_CPRunModalLoop forNextEventMatchingMask:CPAnyEventMask untilDate:nil inMode:0 dequeue:NO];
|
[CPApp setCallback:_CPRunModalLoop forNextEventMatchingMask:CPAnyEventMask untilDate:nil inMode:0 dequeue:NO];
|
||||||
@@ -522,7 +573,7 @@ CPRunContinuesResponse = -1002;
|
|||||||
{
|
{
|
||||||
if (!_currentSession)
|
if (!_currentSession)
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
return _currentSession._window;
|
return _currentSession._window;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -567,7 +618,7 @@ CPRunContinuesResponse = -1002;
|
|||||||
{
|
{
|
||||||
if (_eventListeners[_eventListeners.length - 1]._mask & (1 << [anEvent type]))
|
if (_eventListeners[_eventListeners.length - 1]._mask & (1 << [anEvent type]))
|
||||||
_eventListeners.pop()._callback(anEvent);
|
_eventListeners.pop()._callback(anEvent);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -619,11 +670,7 @@ CPRunContinuesResponse = -1002;
|
|||||||
*/
|
*/
|
||||||
- (CPArray)orderedWindows
|
- (CPArray)orderedWindows
|
||||||
{
|
{
|
||||||
#if PLATFORM(DOM)
|
|
||||||
return CPWindowObjectList();
|
return CPWindowObjectList();
|
||||||
#else
|
|
||||||
return [];
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)hide:(id)aSender
|
- (void)hide:(id)aSender
|
||||||
@@ -682,11 +729,11 @@ CPRunContinuesResponse = -1002;
|
|||||||
|
|
||||||
if ([super tryToPerform:anAction with:anObject])
|
if ([super tryToPerform:anAction with:anObject])
|
||||||
return YES;
|
return YES;
|
||||||
|
|
||||||
if ([_delegate respondsToSelector:anAction])
|
if([_delegate respondsToSelector:anAction])
|
||||||
{
|
{
|
||||||
[_delegate performSelector:anAction withObject:anObject];
|
[_delegate performSelector:anAction withObject:anObject];
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -706,9 +753,9 @@ CPRunContinuesResponse = -1002;
|
|||||||
|
|
||||||
if (!target)
|
if (!target)
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
[target performSelector:anAction withObject:aSender];
|
[target performSelector:anAction withObject:aSender];
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -727,10 +774,10 @@ CPRunContinuesResponse = -1002;
|
|||||||
{
|
{
|
||||||
if (!anAction)
|
if (!anAction)
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
if (aTarget)
|
if (aTarget)
|
||||||
return aTarget;
|
return aTarget;
|
||||||
|
|
||||||
return [self targetForAction:anAction];
|
return [self targetForAction:anAction];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -755,28 +802,28 @@ CPRunContinuesResponse = -1002;
|
|||||||
{
|
{
|
||||||
var responder = [aWindow firstResponder],
|
var responder = [aWindow firstResponder],
|
||||||
checkWindow = YES;
|
checkWindow = YES;
|
||||||
|
|
||||||
while (responder)
|
while (responder)
|
||||||
{
|
{
|
||||||
if ([responder respondsToSelector:anAction])
|
if ([responder respondsToSelector:anAction])
|
||||||
return responder;
|
return responder;
|
||||||
|
|
||||||
if (responder == aWindow)
|
if (responder == aWindow)
|
||||||
checkWindow = NO;
|
checkWindow = NO;
|
||||||
|
|
||||||
responder = [responder nextResponder];
|
responder = [responder nextResponder];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkWindow && [aWindow respondsToSelector:anAction])
|
if (checkWindow && [aWindow respondsToSelector:anAction])
|
||||||
return aWindow;
|
return aWindow;
|
||||||
|
|
||||||
var delegate = [aWindow delegate];
|
var delegate = [aWindow delegate];
|
||||||
|
|
||||||
if ([delegate respondsToSelector:anAction])
|
if ([delegate respondsToSelector:anAction])
|
||||||
return delegate;
|
return delegate;
|
||||||
|
|
||||||
var windowController = [aWindow windowController];
|
var windowController = [aWindow windowController];
|
||||||
|
|
||||||
if ([windowController respondsToSelector:anAction])
|
if ([windowController respondsToSelector:anAction])
|
||||||
return windowController;
|
return windowController;
|
||||||
|
|
||||||
@@ -805,26 +852,26 @@ CPRunContinuesResponse = -1002;
|
|||||||
{
|
{
|
||||||
if (!anAction)
|
if (!anAction)
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
var target = [self _targetForWindow:[self keyWindow] action:anAction];
|
var target = [self _targetForWindow:[self keyWindow] action:anAction];
|
||||||
|
|
||||||
if (target)
|
if (target)
|
||||||
return target;
|
return target;
|
||||||
|
|
||||||
target = [self _targetForWindow:[self mainWindow] action:anAction];
|
target = [self _targetForWindow:[self mainWindow] action:anAction];
|
||||||
|
|
||||||
if (target)
|
if (target)
|
||||||
return target;
|
return target;
|
||||||
|
|
||||||
if ([self respondsToSelector:anAction])
|
if ([self respondsToSelector:anAction])
|
||||||
return self;
|
return self;
|
||||||
|
|
||||||
if ([_delegate respondsToSelector:anAction])
|
if ([_delegate respondsToSelector:anAction])
|
||||||
return _delegate;
|
return _delegate;
|
||||||
|
|
||||||
if ([_documentController respondsToSelector:anAction])
|
if ([_documentController respondsToSelector:anAction])
|
||||||
return _documentController;
|
return _documentController;
|
||||||
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -854,31 +901,30 @@ CPRunContinuesResponse = -1002;
|
|||||||
@param aContextInfo
|
@param aContextInfo
|
||||||
*/
|
*/
|
||||||
- (void)beginSheet:(CPWindow)aSheet modalForWindow:(CPWindow)aWindow modalDelegate:(id)aModalDelegate didEndSelector:(SEL)aDidEndSelector contextInfo:(id)aContextInfo
|
- (void)beginSheet:(CPWindow)aSheet modalForWindow:(CPWindow)aWindow modalDelegate:(id)aModalDelegate didEndSelector:(SEL)aDidEndSelector contextInfo:(id)aContextInfo
|
||||||
{
|
{
|
||||||
var styleMask = [aSheet styleMask];
|
var styleMask = [aSheet styleMask];
|
||||||
if (!(styleMask & CPDocModalWindowMask))
|
if (!(styleMask & CPDocModalWindowMask))
|
||||||
{
|
{
|
||||||
[CPException raise:CPInternalInconsistencyException reason:@"Currently only CPDocModalWindowMask style mask is supported for attached sheets"];
|
[CPException raise:CPInternalInconsistencyException reason:@"Currently only CPDocModalWindowMask style mask is supported for attached sheets"];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[aWindow orderFront:self];
|
[aWindow orderFront:self];
|
||||||
[aSheet setPlatformWindow:[aWindow platformWindow]];
|
|
||||||
[aWindow _attachSheet:aSheet modalDelegate:aModalDelegate didEndSelector:aDidEndSelector contextInfo:aContextInfo];
|
[aWindow _attachSheet:aSheet modalDelegate:aModalDelegate didEndSelector:aDidEndSelector contextInfo:aContextInfo];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)endSheet:(CPWindow)sheet returnCode:(int)returnCode
|
- (void)endSheet:(CPWindow)sheet returnCode:(int)returnCode
|
||||||
{
|
{
|
||||||
var count = [_windows count];
|
var count = [_windows count];
|
||||||
|
|
||||||
while (--count >= 0)
|
while (--count >= 0)
|
||||||
{
|
{
|
||||||
var aWindow = [_windows objectAtIndex:count],
|
var aWindow = [_windows objectAtIndex:count];
|
||||||
context = aWindow._sheetContext;
|
var context = aWindow._sheetContext;
|
||||||
|
|
||||||
if (context != nil && context["sheet"] === sheet)
|
if (context != nil && context["sheet"] === sheet)
|
||||||
{
|
{
|
||||||
context["returnCode"] = returnCode;
|
context["returnCode"] = returnCode;
|
||||||
[aWindow _detachSheetWindow];
|
[aWindow _detachSheetWindow];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -892,40 +938,40 @@ CPRunContinuesResponse = -1002;
|
|||||||
|
|
||||||
- (CPArray)arguments
|
- (CPArray)arguments
|
||||||
{
|
{
|
||||||
if (_fullArgsString !== window.location.hash)
|
if(_fullArgsString !== window.location.hash)
|
||||||
[self _reloadArguments];
|
[self _reloadArguments];
|
||||||
|
|
||||||
return _args;
|
return _args;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setArguments:(CPArray)args
|
- (void)setArguments:(CPArray)args
|
||||||
{
|
{
|
||||||
if (!args || args.length == 0)
|
if(!args || args.length == 0)
|
||||||
{
|
{
|
||||||
_args = [];
|
_args = [];
|
||||||
window.location.hash = @"#";
|
window.location.hash = @"#";
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([args class] != CPArray)
|
if([args class] != CPArray)
|
||||||
args = [CPArray arrayWithObject:args];
|
args = [CPArray arrayWithObject:args];
|
||||||
|
|
||||||
_args = args;
|
_args = args;
|
||||||
|
|
||||||
var toEncode = [_args copy];
|
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]);
|
toEncode[i] = encodeURIComponent(toEncode[i]);
|
||||||
|
|
||||||
var hash = [toEncode componentsJoinedByString:@"/"];
|
var hash = [toEncode componentsJoinedByString:@"/"];
|
||||||
|
|
||||||
window.location.hash = @"#" + hash;
|
window.location.hash = @"#" + hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_reloadArguments
|
- (void)_reloadArguments
|
||||||
{
|
{
|
||||||
_fullArgsString = window.location.hash;
|
_fullArgsString = window.location.hash;
|
||||||
|
|
||||||
if (_fullArgsString.length)
|
if (_fullArgsString.length)
|
||||||
{
|
{
|
||||||
var args = _fullArgsString.substring(1).split("/");
|
var args = _fullArgsString.substring(1).split("/");
|
||||||
@@ -960,18 +1006,18 @@ CPRunContinuesResponse = -1002;
|
|||||||
|
|
||||||
- (void)_willBecomeActive
|
- (void)_willBecomeActive
|
||||||
{
|
{
|
||||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationWillBecomeActiveNotification
|
[[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationWillBecomeActiveNotification
|
||||||
object:self
|
object:self
|
||||||
userInfo:nil];
|
userInfo:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_didBecomeActive
|
- (void)_didBecomeActive
|
||||||
{
|
{
|
||||||
if (![self keyWindow] && _previousKeyWindow &&
|
if (![self keyWindow] && _previousKeyWindow &&
|
||||||
[[self windows] indexOfObjectIdenticalTo:_previousKeyWindow] !== CPNotFound)
|
[[self windows] indexOfObjectIdenticalTo:_previousKeyWindow] !== CPNotFound)
|
||||||
[_previousKeyWindow makeKeyWindow];
|
[_previousKeyWindow makeKeyWindow];
|
||||||
|
|
||||||
if (![self mainWindow] && _previousMainWindow &&
|
if (![self mainWindow] && _previousMainWindow &&
|
||||||
[[self windows] indexOfObjectIdenticalTo:_previousMainWindow] !== CPNotFound)
|
[[self windows] indexOfObjectIdenticalTo:_previousMainWindow] !== CPNotFound)
|
||||||
[_previousMainWindow makeMainWindow];
|
[_previousMainWindow makeMainWindow];
|
||||||
|
|
||||||
@@ -985,15 +1031,15 @@ CPRunContinuesResponse = -1002;
|
|||||||
_previousKeyWindow = nil;
|
_previousKeyWindow = nil;
|
||||||
_previousMainWindow = nil;
|
_previousMainWindow = nil;
|
||||||
|
|
||||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationDidBecomeActiveNotification
|
[[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationDidBecomeActiveNotification
|
||||||
object:self
|
object:self
|
||||||
userInfo:nil];
|
userInfo:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_willResignActive
|
- (void)_willResignActive
|
||||||
{
|
{
|
||||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationWillResignActiveNotification
|
[[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationWillResignActiveNotification
|
||||||
object:self
|
object:self
|
||||||
userInfo:nil];
|
userInfo:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1014,13 +1060,14 @@ CPRunContinuesResponse = -1002;
|
|||||||
[_previousMainWindow resignMainWindow];
|
[_previousMainWindow resignMainWindow];
|
||||||
}
|
}
|
||||||
|
|
||||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationDidResignActiveNotification
|
[[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationDidResignActiveNotification
|
||||||
object:self
|
object:self
|
||||||
userInfo:nil];
|
userInfo:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (CPString)defaultThemeName
|
+ (CPString)defaultThemeName
|
||||||
{
|
{
|
||||||
|
// FIXME: don't hardcode
|
||||||
return ([[CPBundle mainBundle] objectForInfoDictionaryKey:"CPDefaultTheme"] || @"Aristo");
|
return ([[CPBundle mainBundle] objectForInfoDictionaryKey:"CPDefaultTheme"] || @"Aristo");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1036,14 +1083,13 @@ var _CPEventListenerMake = function(anEventMask, aCallback)
|
|||||||
return { _mask:anEventMask, _callback:aCallback };
|
return { _mask:anEventMask, _callback:aCallback };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make this a global for use in CPPlatformWindow+DOM.j.
|
var _CPRunModalLoop = function(anEvent)
|
||||||
_CPRunModalLoop = function(anEvent)
|
|
||||||
{
|
{
|
||||||
[CPApp setCallback:_CPRunModalLoop forNextEventMatchingMask:CPAnyEventMask untilDate:nil inMode:0 dequeue:NO];
|
[CPApp setCallback:_CPRunModalLoop forNextEventMatchingMask:CPAnyEventMask untilDate:nil inMode:0 dequeue:NO];
|
||||||
|
|
||||||
var theWindow = [anEvent window],
|
var theWindow = [anEvent window],
|
||||||
modalSession = CPApp._currentSession;
|
modalSession = CPApp._currentSession;
|
||||||
|
|
||||||
if (theWindow == modalSession._window || [theWindow worksWhenModal])
|
if (theWindow == modalSession._window || [theWindow worksWhenModal])
|
||||||
[theWindow sendEvent:anEvent];
|
[theWindow sendEvent:anEvent];
|
||||||
}
|
}
|
||||||
@@ -1115,15 +1161,8 @@ var _CPAppBootstrapperActions = nil;
|
|||||||
|
|
||||||
+ (BOOL)loadDefaultTheme
|
+ (BOOL)loadDefaultTheme
|
||||||
{
|
{
|
||||||
var defaultThemeName = [CPApplication defaultThemeName],
|
var blend = [[CPThemeBlend alloc] initWithContentsOfURL:[[CPBundle bundleForClass:[CPApplication class]] pathForResource:[CPApplication defaultThemeName] + ".blend"]];
|
||||||
themeURL = nil;
|
|
||||||
|
|
||||||
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];
|
[blend loadWithDelegate:self];
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
@@ -1131,7 +1170,6 @@ var _CPAppBootstrapperActions = nil;
|
|||||||
|
|
||||||
+ (void)blendDidFinishLoading:(CPThemeBlend)aThemeBlend
|
+ (void)blendDidFinishLoading:(CPThemeBlend)aThemeBlend
|
||||||
{
|
{
|
||||||
[[CPApplication sharedApplication] setThemeBlend:aThemeBlend];
|
|
||||||
[CPTheme setDefaultTheme:[CPTheme themeNamed:[CPApplication defaultThemeName]]];
|
[CPTheme setDefaultTheme:[CPTheme themeNamed:[CPApplication defaultThemeName]]];
|
||||||
|
|
||||||
[self performActions];
|
[self performActions];
|
||||||
@@ -1150,73 +1188,10 @@ var _CPAppBootstrapperActions = nil;
|
|||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
[self loadCiblessBrowserMainMenu];
|
|
||||||
|
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (void)loadCiblessBrowserMainMenu
|
|
||||||
{
|
|
||||||
var mainMenu = [[CPMenu alloc] initWithTitle:@"MainMenu"];
|
|
||||||
|
|
||||||
// FIXME: We should implement autoenabling.
|
|
||||||
[mainMenu setAutoenablesItems:NO];
|
|
||||||
|
|
||||||
var bundle = [CPBundle bundleForClass:[CPApplication class]],
|
|
||||||
newMenuItem = [[CPMenuItem alloc] initWithTitle:@"New" action:@selector(newDocument:) keyEquivalent:@"n"];
|
|
||||||
|
|
||||||
[newMenuItem setImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/New.png"] size:CGSizeMake(16.0, 16.0)]];
|
|
||||||
[newMenuItem setAlternateImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/NewHighlighted.png"] size:CGSizeMake(16.0, 16.0)]];
|
|
||||||
|
|
||||||
[mainMenu addItem:newMenuItem];
|
|
||||||
|
|
||||||
var openMenuItem = [[CPMenuItem alloc] initWithTitle:@"Open" action:@selector(openDocument:) keyEquivalent:@"o"];
|
|
||||||
|
|
||||||
[openMenuItem setImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/Open.png"] size:CGSizeMake(16.0, 16.0)]];
|
|
||||||
[openMenuItem setAlternateImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/OpenHighlighted.png"] size:CGSizeMake(16.0, 16.0)]];
|
|
||||||
|
|
||||||
[mainMenu addItem:openMenuItem];
|
|
||||||
|
|
||||||
var saveMenu = [[CPMenu alloc] initWithTitle:@"Save"],
|
|
||||||
saveMenuItem = [[CPMenuItem alloc] initWithTitle:@"Save" action:@selector(saveDocument:) keyEquivalent:nil];
|
|
||||||
|
|
||||||
[saveMenuItem setImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/Save.png"] size:CGSizeMake(16.0, 16.0)]];
|
|
||||||
[saveMenuItem setAlternateImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/SaveHighlighted.png"] size:CGSizeMake(16.0, 16.0)]];
|
|
||||||
|
|
||||||
[saveMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Save" action:@selector(saveDocument:) keyEquivalent:@"s"]];
|
|
||||||
[saveMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Save As" action:@selector(saveDocumentAs:) keyEquivalent:nil]];
|
|
||||||
|
|
||||||
[saveMenuItem setSubmenu:saveMenu];
|
|
||||||
|
|
||||||
[mainMenu addItem:saveMenuItem];
|
|
||||||
|
|
||||||
var editMenuItem = [[CPMenuItem alloc] initWithTitle:@"Edit" action:nil keyEquivalent:nil],
|
|
||||||
editMenu = [[CPMenu alloc] initWithTitle:@"Edit"],
|
|
||||||
|
|
||||||
undoMenuItem = [[CPMenuItem alloc] initWithTitle:@"Undo" action:@selector(undo:) keyEquivalent:CPUndoKeyEquivalent],
|
|
||||||
redoMenuItem = [[CPMenuItem alloc] initWithTitle:@"Redo" action:@selector(redo:) keyEquivalent:CPRedoKeyEquivalent];
|
|
||||||
|
|
||||||
[undoMenuItem setKeyEquivalentModifierMask:CPUndoKeyEquivalentModifierMask];
|
|
||||||
[redoMenuItem setKeyEquivalentModifierMask:CPRedoKeyEquivalentModifierMask];
|
|
||||||
|
|
||||||
[editMenu addItem:undoMenuItem];
|
|
||||||
[editMenu addItem:redoMenuItem];
|
|
||||||
|
|
||||||
[editMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Cut" action:@selector(cut:) keyEquivalent:@"x"]],
|
|
||||||
[editMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Copy" action:@selector(copy:) keyEquivalent:@"c"]],
|
|
||||||
[editMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Paste" action:@selector(paste:) keyEquivalent:@"v"]];
|
|
||||||
|
|
||||||
[editMenuItem setSubmenu:editMenu];
|
|
||||||
[editMenuItem setHidden:YES];
|
|
||||||
|
|
||||||
[mainMenu addItem:editMenuItem];
|
|
||||||
|
|
||||||
[mainMenu addItem:[CPMenuItem separatorItem]];
|
|
||||||
|
|
||||||
[CPApp setMainMenu:mainMenu];
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (void)cibDidFinishLoading:(CPCib)aCib
|
+ (void)cibDidFinishLoading:(CPCib)aCib
|
||||||
{
|
{
|
||||||
[self performActions];
|
[self performActions];
|
||||||
@@ -1229,7 +1204,7 @@ var _CPAppBootstrapperActions = nil;
|
|||||||
|
|
||||||
+ (void)reset
|
+ (void)reset
|
||||||
{
|
{
|
||||||
_CPAppBootstrapperActions = nil;
|
_CPAppBootstrapperActions = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -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
@@ -4,7 +4,7 @@
|
|||||||
* Created by Ross Boucher.
|
* Created by Ross Boucher.
|
||||||
* Copyright 2009, 280 North, Inc.
|
* 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
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* 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
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
* Copyright 2009 280 North, Inc.
|
* Copyright 2009 280 North, Inc.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@import <AppKit/CPGraphicsContext.j>
|
||||||
@import <Foundation/CPObject.j>
|
@import <Foundation/CPObject.j>
|
||||||
|
|
||||||
@import "CPGraphicsContext.j"
|
|
||||||
|
|
||||||
|
|
||||||
// Class defaults
|
// Class defaults
|
||||||
|
|
||||||
var DefaultLineWidth = 1.0;
|
var DefaultLineWidth = 1.0;
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPBezierPath
|
@class CPBezierPath
|
||||||
|
|
||||||
A CPBezierPath allows you to create paths for drawing to the screen using a simpler API than CoreGraphics.
|
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
|
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
|
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).
|
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
|
+ (CPBezierPath)bezierPathWithOvalInRect:(CGRect)rect
|
||||||
{
|
{
|
||||||
var path = [self bezierPath];
|
var path = [self bezierPath];
|
||||||
|
|
||||||
[path appendBezierPathWithOvalInRect:rect];
|
[path appendBezierPathWithOvalInRect:rect];
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,9 +76,9 @@ var DefaultLineWidth = 1.0;
|
|||||||
+ (CPBezierPath)bezierPathWithRect:(CGRect)rect
|
+ (CPBezierPath)bezierPathWithRect:(CGRect)rect
|
||||||
{
|
{
|
||||||
var path = [self bezierPath];
|
var path = [self bezierPath];
|
||||||
|
|
||||||
[path appendBezierPathWithRect:rect];
|
[path appendBezierPathWithRect:rect];
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+53
-177
@@ -19,33 +19,25 @@
|
|||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@import "CPView.j"
|
@import "CPView.j"
|
||||||
|
|
||||||
// CPBoxType
|
|
||||||
CPBoxPrimary = 0;
|
|
||||||
CPBoxSecondary = 1;
|
|
||||||
CPBoxSeperator = 2;
|
|
||||||
CPBoxOldStyle = 3;
|
|
||||||
CPBoxCustom = 4;
|
|
||||||
|
|
||||||
// CPBorderType
|
// CPBorderType
|
||||||
CPNoBorder = 0;
|
CPNoBorder = 0;
|
||||||
CPLineBorder = 1;
|
CPLineBorder = 1;
|
||||||
CPBezelBorder = 2;
|
CPBezelBorder = 2;
|
||||||
CPGrooveBorder = 3;
|
CPGrooveBorder = 3;
|
||||||
|
|
||||||
@implementation CPBox : CPView
|
@implementation CPBox : CPView
|
||||||
{
|
{
|
||||||
CPBoxType _boxType;
|
|
||||||
CPBorderType _borderType;
|
CPBorderType _borderType;
|
||||||
|
|
||||||
CPColor _borderColor;
|
CPColor _borderColor;
|
||||||
CPColor _fillColor;
|
CPColor _fillColor;
|
||||||
|
|
||||||
float _cornerRadius;
|
float _cornerRadius;
|
||||||
float _borderWidth;
|
float _borderWidth;
|
||||||
|
|
||||||
CPSize _contentMargin;
|
CPSize _contentMargin;
|
||||||
CPView _contentView;
|
CPView _contentView;
|
||||||
}
|
}
|
||||||
@@ -58,19 +50,18 @@ CPGrooveBorder = 3;
|
|||||||
[box setFrameFromContentFrame:[aView frame]];
|
[box setFrameFromContentFrame:[aView frame]];
|
||||||
|
|
||||||
[enclosingView replaceSubview:aView with:box];
|
[enclosingView replaceSubview:aView with:box];
|
||||||
|
|
||||||
[box setContentView:aView];
|
[box setContentView:aView];
|
||||||
|
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithFrame:(CPRect)frameRect
|
- (id)initWithFrame:(CPRect)frameRect
|
||||||
{
|
{
|
||||||
self = [super initWithFrame:frameRect];
|
self = [super initWithFrame:frameRect];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_borderType = CPBezelBorder;
|
|
||||||
_fillColor = [CPColor clearColor];
|
_fillColor = [CPColor clearColor];
|
||||||
_borderColor = [CPColor blackColor];
|
_borderColor = [CPColor blackColor];
|
||||||
|
|
||||||
@@ -78,9 +69,7 @@ CPGrooveBorder = 3;
|
|||||||
_contentMargin = CGSizeMake(0.0, 0.0);
|
_contentMargin = CGSizeMake(0.0, 0.0);
|
||||||
|
|
||||||
_contentView = [[CPView alloc] initWithFrame:[self bounds]];
|
_contentView = [[CPView alloc] initWithFrame:[self bounds]];
|
||||||
[_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
|
||||||
|
|
||||||
[self setAutoresizesSubviews:YES];
|
|
||||||
[self addSubview:_contentView];
|
[self addSubview:_contentView];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,26 +88,9 @@ CPGrooveBorder = 3;
|
|||||||
return _borderType;
|
return _borderType;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setBorderType:(CPBorderType)aBorderType
|
- (void)setBorderType:(CPBorderType)value
|
||||||
{
|
{
|
||||||
if (_borderType === aBorderType)
|
_borderType = value;
|
||||||
return;
|
|
||||||
|
|
||||||
_borderType = aBorderType;
|
|
||||||
[self setNeedsDisplay:YES];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (CPBoxType)boxType
|
|
||||||
{
|
|
||||||
return _boxType;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setBoxType:(CPBoxType)aBoxType
|
|
||||||
{
|
|
||||||
if (_boxType === aBoxType)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_boxType = aBoxType;
|
|
||||||
[self setNeedsDisplay:YES];
|
[self setNeedsDisplay:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,10 +161,9 @@ CPGrooveBorder = 3;
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
[aView setFrame:CGRectInset([self bounds], _contentMargin.width + _borderWidth, _contentMargin.height + _borderWidth)];
|
[aView setFrame:CGRectInset([self bounds], _contentMargin.width + _borderWidth, _contentMargin.height + _borderWidth)];
|
||||||
[aView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
|
||||||
[self replaceSubview:_contentView with:aView];
|
[self replaceSubview:_contentView with:aView];
|
||||||
|
|
||||||
_contentView = aView;
|
_contentView = aView;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CPSize)contentViewMargins
|
- (CPSize)contentViewMargins
|
||||||
@@ -202,9 +173,9 @@ CPGrooveBorder = 3;
|
|||||||
|
|
||||||
- (void)setContentViewMargins:(CPSize)size
|
- (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"];
|
[CPException raise:CPGenericException reason:@"Margins must be positive"];
|
||||||
|
|
||||||
_contentMargin = CGSizeMakeCopy(size);
|
_contentMargin = CGSizeMakeCopy(size);
|
||||||
[self setNeedsDisplay:YES];
|
[self setNeedsDisplay:YES];
|
||||||
}
|
}
|
||||||
@@ -218,151 +189,56 @@ CPGrooveBorder = 3;
|
|||||||
- (void)sizeToFit
|
- (void)sizeToFit
|
||||||
{
|
{
|
||||||
var contentFrame = [_contentView frame];
|
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)];
|
contentFrame.size.height + _contentMargin.height * 2)];
|
||||||
|
|
||||||
[_contentView setFrameOrigin:CGPointMake(_contentMargin.width, _contentMargin.height)];
|
[_contentView setFrameOrigin:CGPointMake(_contentMargin.width, _contentMargin.height)];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)drawRect:(CPRect)rect
|
- (void)drawRect:(CPRect)rect
|
||||||
{
|
{
|
||||||
if (_borderType === CPNoBorder)
|
var bounds = [self bounds],
|
||||||
return;
|
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:
|
case CPLineBorder: CGContextFillRoundedRectangleInRect(aContext, fillRect, _cornerRadius, YES, YES, YES, YES);
|
||||||
// NSBox does not include a horitontal flag for the seperator type. We have to determine
|
CGContextStrokeRoundedRectangleInRect(aContext, strokeRect, _cornerRadius, YES, YES, YES, YES);
|
||||||
// the type of seperator to draw by the width and height of the frame.
|
break;
|
||||||
if (CGRectGetWidth(bounds) === 5.0)
|
|
||||||
return [self _drawVerticalSeperatorInRect:bounds];
|
|
||||||
else if (CGRectGetHeight(bounds) === 5.0)
|
|
||||||
return [self _drawHorizontalSeperatorInRect:bounds];
|
|
||||||
|
|
||||||
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
|
@end
|
||||||
|
|||||||
+45
-104
@@ -20,17 +20,14 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@import <Foundation/CPIndexSet.j>
|
|
||||||
|
|
||||||
@import "CPControl.j"
|
@import "CPControl.j"
|
||||||
@import "CPImage.j"
|
@import "CPImage.j"
|
||||||
@import "CPTableView.j"
|
@import "CPTableView.j"
|
||||||
@import "CPTextField.j"
|
|
||||||
@import "CPScrollView.j"
|
@import "CPScrollView.j"
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPBrowser
|
@class CPBrowser
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@implementation CPBrowser : CPControl
|
@implementation CPBrowser : CPControl
|
||||||
@@ -67,14 +64,14 @@
|
|||||||
|
|
||||||
+ (CPImage)branchImage
|
+ (CPImage)branchImage
|
||||||
{
|
{
|
||||||
return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPBrowser class]]
|
return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[self class]]
|
||||||
pathForResource:"browser-leaf.png"]
|
pathForResource:"browser-leaf.png"]
|
||||||
size:CGSizeMake(9,9)];
|
size:CGSizeMake(9,9)];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (CPImage)highlightedBranchImage
|
+ (CPImage)highlightedBranchImage
|
||||||
{
|
{
|
||||||
return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPBrowser class]]
|
return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[self class]]
|
||||||
pathForResource:"browser-leaf-highlighted.png"]
|
pathForResource:"browser-leaf-highlighted.png"]
|
||||||
size:CGSizeMake(9,9)];
|
size:CGSizeMake(9,9)];
|
||||||
}
|
}
|
||||||
@@ -99,18 +96,18 @@
|
|||||||
|
|
||||||
_prototypeView = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
|
_prototypeView = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
|
||||||
[_prototypeView setVerticalAlignment:CPCenterVerticalTextAlignment];
|
[_prototypeView setVerticalAlignment:CPCenterVerticalTextAlignment];
|
||||||
[_prototypeView setValue:[CPColor whiteColor] forThemeAttribute:"text-color" inState:CPThemeStateSelectedDataView];
|
[_prototypeView setValue:[CPColor whiteColor] forThemeAttribute:"text-color" inState:CPThemeStateSelected];
|
||||||
[_prototypeView setLineBreakMode:CPLineBreakByTruncatingTail];
|
[_prototypeView setLineBreakMode:CPLineBreakByTruncatingTail];
|
||||||
|
|
||||||
_horizontalScrollView = [[CPScrollView alloc] initWithFrame:[self bounds]];
|
_horizontalScrollView = [[CPScrollView alloc] initWithFrame:[self bounds]];
|
||||||
|
|
||||||
[_horizontalScrollView setHasVerticalScroller:NO];
|
[_horizontalScrollView setHasVerticalScroller:NO];
|
||||||
[_horizontalScrollView setAutohidesScrollers:YES];
|
[_horizontalScrollView setAutohidesScrollers:YES];
|
||||||
[_horizontalScrollView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
[_horizontalScrollView setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
|
||||||
|
|
||||||
_contentView = [[CPView alloc] initWithFrame:CGRectMake(0, 0, 0, CGRectGetHeight([self bounds]))];
|
_contentView = [[CPView alloc] initWithFrame:CGRectMake(0, 0, 0, CGRectGetHeight([self bounds]))];
|
||||||
[_contentView setAutoresizingMask:CPViewHeightSizable];
|
[_contentView setAutoresizingMask:CPViewHeightSizable];
|
||||||
|
|
||||||
[_horizontalScrollView setDocumentView:_contentView];
|
[_horizontalScrollView setDocumentView:_contentView];
|
||||||
|
|
||||||
[self addSubview:_horizontalScrollView];
|
[self addSubview:_horizontalScrollView];
|
||||||
@@ -132,7 +129,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)setDelegate:(id)anObject
|
- (void)setDelegate:(id)anObject
|
||||||
{
|
{
|
||||||
_delegate = anObject;
|
_delegate = anObject;
|
||||||
_delegateSupportsImages = [_delegate respondsToSelector:@selector(browser:imageValueForItem:)];
|
_delegateSupportsImages = [_delegate respondsToSelector:@selector(browser:imageValueForItem:)];
|
||||||
|
|
||||||
@@ -170,10 +167,12 @@
|
|||||||
if (columnIndex >= _tableViews.length)
|
if (columnIndex >= _tableViews.length)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var oldValue = _tableViews.length - 1,
|
var oldValue = _tableViews.length - 1;
|
||||||
indexPlusOne = columnIndex + 1; // unloads all later columns.
|
|
||||||
|
|
||||||
[[_tableViews.slice(indexPlusOne) valueForKey:"enclosingScrollView"]
|
// unloads all later columns.
|
||||||
|
var indexPlusOne = columnIndex + 1;
|
||||||
|
|
||||||
|
[[_tableViews.slice(indexPlusOne) valueForKey:"enclosingScrollView"]
|
||||||
makeObjectsPerformSelector:@selector(removeFromSuperview)];
|
makeObjectsPerformSelector:@selector(removeFromSuperview)];
|
||||||
|
|
||||||
_tableViews = _tableViews.slice(0, indexPlusOne);
|
_tableViews = _tableViews.slice(0, indexPlusOne);
|
||||||
@@ -197,10 +196,10 @@
|
|||||||
selectionIndexes = [lastColumn selectedRowIndexes];
|
selectionIndexes = [lastColumn selectedRowIndexes];
|
||||||
|
|
||||||
if (lastIndex >= 0 && [selectionIndexes count] > 1)
|
if (lastIndex >= 0 && [selectionIndexes count] > 1)
|
||||||
[CPException raise:CPInvalidArgumentException
|
[CPException raise:CPInvalidArgumentException
|
||||||
reason:"Can't add column, column "+lastIndex+" has invalid selection."];
|
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]];
|
item = index === 0 ? _rootItem : [_tableDelegates[lastIndex] childAtIndex:[selectionIndexes firstIndex]];
|
||||||
|
|
||||||
if (index > 0 && item && [self isLeafItem:item])
|
if (index > 0 && item && [self isLeafItem:item])
|
||||||
@@ -214,6 +213,8 @@
|
|||||||
[table setAllowsEmptySelection:_allowsEmptySelection];
|
[table setAllowsEmptySelection:_allowsEmptySelection];
|
||||||
[table registerForDraggedTypes:[self registeredDraggedTypes]];
|
[table registerForDraggedTypes:[self registeredDraggedTypes]];
|
||||||
|
|
||||||
|
[self setNextResponder:table];
|
||||||
|
|
||||||
[self _addTableColumnsToTableView:table forColumnIndex:index];
|
[self _addTableColumnsToTableView:table forColumnIndex:index];
|
||||||
|
|
||||||
var delegate = [[_CPBrowserTableDelegate alloc] init];
|
var delegate = [[_CPBrowserTableDelegate alloc] init];
|
||||||
@@ -232,7 +233,7 @@
|
|||||||
[table setAction:@selector(_tableViewClicked:)];
|
[table setAction:@selector(_tableViewClicked:)];
|
||||||
[table setDoubleAction:@selector(_tableViewDoubleClicked:)];
|
[table setDoubleAction:@selector(_tableViewDoubleClicked:)];
|
||||||
[table setDraggingDestinationFeedbackStyle:CPTableViewDraggingDestinationFeedbackStyleRegular];
|
[table setDraggingDestinationFeedbackStyle:CPTableViewDraggingDestinationFeedbackStyleRegular];
|
||||||
|
|
||||||
var scrollView = [[_CPBrowserScrollView alloc] initWithFrame:CGRectMakeZero()];
|
var scrollView = [[_CPBrowserScrollView alloc] initWithFrame:CGRectMakeZero()];
|
||||||
[scrollView _setBrowser:self];
|
[scrollView _setBrowser:self];
|
||||||
[scrollView setDocumentView:table];
|
[scrollView setDocumentView:table];
|
||||||
@@ -273,10 +274,10 @@
|
|||||||
|
|
||||||
[view setBranchImage:[[self class] branchImage]];
|
[view setBranchImage:[[self class] branchImage]];
|
||||||
[view setHighlightedBranchImage:[[self class] highlightedBranchImage]];
|
[view setHighlightedBranchImage:[[self class] highlightedBranchImage]];
|
||||||
|
|
||||||
[column setDataView:view];
|
[column setDataView:view];
|
||||||
[column setResizingMask:CPTableColumnNoResizing];
|
[column setResizingMask:CPTableColumnNoResizing];
|
||||||
|
|
||||||
[aTableView addTableColumn:column];
|
[aTableView addTableColumn:column];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,39 +314,6 @@
|
|||||||
[_contentView setFrameSize:CGSizeMake(xOrigin, height)];
|
[_contentView setFrameSize:CGSizeMake(xOrigin, height)];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (unsigned)rowAtPoint:(CGPoint)aPoint
|
|
||||||
{
|
|
||||||
var column = [self columnAtPoint:aPoint];
|
|
||||||
if (column === -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
var tableView = _tableViews[column];
|
|
||||||
return [tableView rowAtPoint:[tableView convertPoint:aPoint fromView:self]];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (unsigned)columnAtPoint:(CGPoint)aPoint
|
|
||||||
{
|
|
||||||
var adjustedPoint = [_contentView convertPoint:aPoint fromView:self];
|
|
||||||
|
|
||||||
for (var i = 0, count = _tableViews.length; i < count; i++)
|
|
||||||
{
|
|
||||||
var frame = [[_tableViews[i] enclosingScrollView] frame];
|
|
||||||
if (CGRectContainsPoint(frame, adjustedPoint))
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (CGRect)rectOfRow:(unsigned)aRow inColumn:(unsigned)aColumn
|
|
||||||
{
|
|
||||||
var tableView = _tableViews[aColumn],
|
|
||||||
rect = [tableView rectOfRow:aRow];
|
|
||||||
|
|
||||||
rect.origin = [self convertPoint:rect.origin fromView:tableView];
|
|
||||||
return rect;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ITEMS
|
// ITEMS
|
||||||
|
|
||||||
- (id)itemAtRow:(int)row inColumn:(int)column
|
- (id)itemAtRow:(int)row inColumn:(int)column
|
||||||
@@ -389,10 +357,6 @@
|
|||||||
|
|
||||||
// CLICK EVENTS
|
// CLICK EVENTS
|
||||||
|
|
||||||
- (void)trackMouse:(CPEvent)anEvent
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)_column:(unsigned)columnIndex clickedRow:(unsigned)rowIndex
|
- (void)_column:(unsigned)columnIndex clickedRow:(unsigned)rowIndex
|
||||||
{
|
{
|
||||||
[self setLastColumn:columnIndex];
|
[self setLastColumn:columnIndex];
|
||||||
@@ -418,15 +382,6 @@
|
|||||||
[self sendAction:_doubleAction to:_target];
|
[self sendAction:_doubleAction to:_target];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)keyDown:(CPEvent)anEvent
|
|
||||||
{
|
|
||||||
var column = [self selectedColumn];
|
|
||||||
if (column === -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
[_tableViews[column] keyDown:anEvent];
|
|
||||||
}
|
|
||||||
|
|
||||||
// SIZING
|
// SIZING
|
||||||
|
|
||||||
- (float)columnContentWidthForColumnWidth:(float)aWidth
|
- (float)columnContentWidthForColumnWidth:(float)aWidth
|
||||||
@@ -498,7 +453,7 @@
|
|||||||
[_contentView scrollRectToVisible:[[[self tableViewInColumn:columnIndex] enclosingScrollView] frame]];
|
[_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 scrollColumnToVisible:columnIndex];
|
||||||
[[self tableViewInColumn:columnIndex] scrollRowToVisible:rowIndex];
|
[[self tableViewInColumn:columnIndex] scrollRowToVisible:rowIndex];
|
||||||
@@ -571,9 +526,6 @@
|
|||||||
|
|
||||||
- (CPIndexSet)selectedRowIndexesInColumn:(unsigned)column
|
- (CPIndexSet)selectedRowIndexesInColumn:(unsigned)column
|
||||||
{
|
{
|
||||||
if (column < 0 || column > [self lastColumn] +1)
|
|
||||||
return [CPIndexSet indexSet];
|
|
||||||
|
|
||||||
return [[self tableViewInColumn:column] selectedRowIndexes];
|
return [[self tableViewInColumn:column] selectedRowIndexes];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -585,7 +537,7 @@
|
|||||||
if ([_delegate respondsToSelector:@selector(browser:selectionIndexesForProposedSelection:inColumn:)])
|
if ([_delegate respondsToSelector:@selector(browser:selectionIndexesForProposedSelection:inColumn:)])
|
||||||
indexSet = [_delegate browser:self selectionIndexesForProposedSelection:indexSet inColumn:column];
|
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])
|
![_delegate browser:self shouldSelectRowIndexes:indexSet inColumn:column])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -599,6 +551,8 @@
|
|||||||
|
|
||||||
[[self tableViewInColumn:column] selectRowIndexes:indexSet byExtendingSelection:NO];
|
[[self tableViewInColumn:column] selectRowIndexes:indexSet byExtendingSelection:NO];
|
||||||
|
|
||||||
|
[self setNextResponder:[self tableViewInColumn:[self lastColumn]]];
|
||||||
|
|
||||||
[self scrollColumnToVisible:column];
|
[self scrollColumnToVisible:column];
|
||||||
|
|
||||||
if ([_delegate respondsToSelector:@selector(browserSelectionDidChange:)])
|
if ([_delegate respondsToSelector:@selector(browserSelectionDidChange:)])
|
||||||
@@ -650,8 +604,6 @@
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
var _CPBrowserResizeControlBackgroundImage = nil;
|
|
||||||
|
|
||||||
@implementation _CPBrowserResizeControl : CPView
|
@implementation _CPBrowserResizeControl : CPView
|
||||||
{
|
{
|
||||||
CGPoint _mouseDownX;
|
CGPoint _mouseDownX;
|
||||||
@@ -660,26 +612,6 @@ var _CPBrowserResizeControlBackgroundImage = nil;
|
|||||||
unsigned _width;
|
unsigned _width;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (CPImage)backgroundImage
|
|
||||||
{
|
|
||||||
if (!_CPBrowserResizeControlBackgroundImage)
|
|
||||||
{
|
|
||||||
var path = [[CPBundle bundleForClass:[self class]] pathForResource:"browser-resize-control.png"];
|
|
||||||
_CPBrowserResizeControlBackgroundImage = [[CPImage alloc] initWithContentsOfFile:path
|
|
||||||
size:CGSizeMake(15, 14)];
|
|
||||||
}
|
|
||||||
|
|
||||||
return _CPBrowserResizeControlBackgroundImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id)initWithFrame:(CGRect)aFrame
|
|
||||||
{
|
|
||||||
if (self = [super initWithFrame:aFrame])
|
|
||||||
[self setBackgroundColor:[CPColor colorWithPatternImage:[[self class] backgroundImage]]];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)mouseDown:(CPEvent)anEvent
|
- (void)mouseDown:(CPEvent)anEvent
|
||||||
{
|
{
|
||||||
_mouseDownX = [anEvent locationInWindow].x;
|
_mouseDownX = [anEvent locationInWindow].x;
|
||||||
@@ -694,23 +626,34 @@ var _CPBrowserResizeControlBackgroundImage = nil;
|
|||||||
[_browser setWidth:_width + deltaX ofColumn:_index];
|
[_browser setWidth:_width + deltaX ofColumn:_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)mouseUp:(CPEvent)anEvent
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
var _CPBrowserResizeControlBackgroundImage = nil;
|
||||||
|
|
||||||
@implementation _CPBrowserScrollView : CPScrollView
|
@implementation _CPBrowserScrollView : CPScrollView
|
||||||
{
|
{
|
||||||
_CPBrowserResizeControl _resizeControl;
|
_CPBrowserResizeControl _resizeControl;
|
||||||
CPBrowser _browser @accessors;
|
CPBrowser _browser @accessors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (CPImage)backgroundImage
|
||||||
|
{
|
||||||
|
if (!_CPBrowserResizeControlBackgroundImage)
|
||||||
|
{
|
||||||
|
var path = [[CPBundle bundleForClass:[self class]] pathForResource:"browser-resize-control.png"];
|
||||||
|
_CPBrowserResizeControlBackgroundImage = [[CPImage alloc] initWithContentsOfFile:path
|
||||||
|
size:CGSizeMake(15, 14)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return _CPBrowserResizeControlBackgroundImage;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)initWithFrame:(CGRect)aFrame
|
- (void)initWithFrame:(CGRect)aFrame
|
||||||
{
|
{
|
||||||
if (self = [super initWithFrame:aFrame])
|
if (self = [super initWithFrame:aFrame])
|
||||||
{
|
{
|
||||||
_resizeControl = [[_CPBrowserResizeControl alloc] initWithFrame:CGRectMakeZero()];
|
_resizeControl = [[_CPBrowserResizeControl alloc] initWithFrame:CGRectMakeZero()];
|
||||||
|
[_resizeControl setBackgroundColor:[CPColor colorWithPatternImage:[[self class] backgroundImage]]];
|
||||||
[self addSubview:_resizeControl];
|
[self addSubview:_resizeControl];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -797,7 +740,7 @@ var _CPBrowserResizeControlBackgroundImage = nil;
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)moveLeft:(id)sender
|
- (void)moveLeft:(id)sender
|
||||||
{
|
{
|
||||||
var previousColumn = [_browser selectedColumn] - 1,
|
var previousColumn = [_browser selectedColumn] - 1,
|
||||||
selectedRow = [_browser selectedRowInColumn:previousColumn];
|
selectedRow = [_browser selectedRowInColumn:previousColumn];
|
||||||
|
|
||||||
@@ -805,14 +748,12 @@ var _CPBrowserResizeControlBackgroundImage = nil;
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)moveRight:(id)sender
|
- (void)moveRight:(id)sender
|
||||||
{
|
{
|
||||||
[_browser selectRow:0 inColumn:[_browser selectedColumn] + 1];
|
[_browser selectRow:0 inColumn:[_browser selectedColumn] + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@import <Foundation/CPObject.j>
|
|
||||||
|
|
||||||
@implementation _CPBrowserTableDelegate : CPObject
|
@implementation _CPBrowserTableDelegate : CPObject
|
||||||
{
|
{
|
||||||
CPBrowser _browser @accessors;
|
CPBrowser _browser @accessors;
|
||||||
@@ -863,7 +804,7 @@ var _CPBrowserResizeControlBackgroundImage = nil;
|
|||||||
- (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id)info proposedRow:(int)row proposedDropOperation:(CPTableViewDropOperation)operation
|
- (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id)info proposedRow:(int)row proposedDropOperation:(CPTableViewDropOperation)operation
|
||||||
{
|
{
|
||||||
if ([_delegate respondsToSelector:@selector(browser:validateDrop:proposedRow:column:dropOperation:)])
|
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
|
else
|
||||||
return CPDragOperationNone;
|
return CPDragOperationNone;
|
||||||
}
|
}
|
||||||
@@ -924,9 +865,9 @@ var _CPBrowserResizeControlBackgroundImage = nil;
|
|||||||
{
|
{
|
||||||
var imageView = [self layoutEphemeralSubviewNamed:@"image-view"
|
var imageView = [self layoutEphemeralSubviewNamed:@"image-view"
|
||||||
positioned:CPWindowAbove
|
positioned:CPWindowAbove
|
||||||
relativeToEphemeralSubviewNamed:nil],
|
relativeToEphemeralSubviewNamed:nil];
|
||||||
isHighlighted = [self themeState] & CPThemeStateSelectedDataView;
|
|
||||||
|
|
||||||
|
var isHighlighted = [self themeState] & CPThemeStateSelected;
|
||||||
[imageView setImage: _isLeaf ? (isHighlighted ? _highlightedBranchImage : _branchImage) : nil];
|
[imageView setImage: _isLeaf ? (isHighlighted ? _highlightedBranchImage : _branchImage) : nil];
|
||||||
[imageView setImageScaling:CPScaleNone];
|
[imageView setImageScaling:CPScaleNone];
|
||||||
}
|
}
|
||||||
|
|||||||
+69
-174
@@ -26,6 +26,8 @@
|
|||||||
@import "CPControl.j"
|
@import "CPControl.j"
|
||||||
@import "CPStringDrawing.j"
|
@import "CPStringDrawing.j"
|
||||||
|
|
||||||
|
#include "CoreGraphics/CGGeometry.h"
|
||||||
|
|
||||||
|
|
||||||
/* @group CPBezelStyle */
|
/* @group CPBezelStyle */
|
||||||
|
|
||||||
@@ -72,10 +74,7 @@ CPChangeBackgroundCellMask = CPBackgroundButtonMask;
|
|||||||
|
|
||||||
CPButtonStateMixed = CPThemeState("mixed");
|
CPButtonStateMixed = CPThemeState("mixed");
|
||||||
|
|
||||||
CPButtonDefaultHeight = 24.0;
|
/*!
|
||||||
CPButtonImageOffset = 3.0;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPButton
|
@class CPButton
|
||||||
|
|
||||||
@@ -86,9 +85,12 @@ CPButtonImageOffset = 3.0;
|
|||||||
@implementation CPButton : CPControl
|
@implementation CPButton : CPControl
|
||||||
{
|
{
|
||||||
BOOL _allowsMixedState;
|
BOOL _allowsMixedState;
|
||||||
|
|
||||||
CPString _title;
|
CPString _title;
|
||||||
CPString _alternateTitle;
|
CPString _alternateTitle;
|
||||||
|
|
||||||
|
CPImage _image;
|
||||||
|
CPImage _alternateImage;
|
||||||
|
|
||||||
CPInteger _showsStateBy;
|
CPInteger _showsStateBy;
|
||||||
CPInteger _highlightsBy;
|
CPInteger _highlightsBy;
|
||||||
@@ -97,9 +99,6 @@ CPButtonImageOffset = 3.0;
|
|||||||
// NS-style Display Properties
|
// NS-style Display Properties
|
||||||
CPBezelStyle _bezelStyle;
|
CPBezelStyle _bezelStyle;
|
||||||
CPControlSize _controlSize;
|
CPControlSize _controlSize;
|
||||||
|
|
||||||
CPString _keyEquivalent;
|
|
||||||
unsigned _keyEquivalentModifierMask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (id)buttonWithTitle:(CPString)aTitle
|
+ (id)buttonWithTitle:(CPString)aTitle
|
||||||
@@ -118,21 +117,21 @@ CPButtonImageOffset = 3.0;
|
|||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (CPString)defaultThemeClass
|
+ (CPString)themeClass
|
||||||
{
|
{
|
||||||
return @"button";
|
return @"button";
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (id)themeAttributes
|
+ (id)themeAttributes
|
||||||
{
|
{
|
||||||
return [CPDictionary dictionaryWithObjects:[[CPNull null], 0.0, _CGInsetMakeZero(), _CGInsetMakeZero(), [CPNull null]]
|
return [CPDictionary dictionaryWithObjects:[_CGInsetMakeZero(), _CGInsetMakeZero(), [CPNull null]]
|
||||||
forKeys:[@"image", @"image-offset", @"bezel-inset", @"content-inset", @"bezel-color"]];
|
forKeys:[@"bezel-inset", @"content-inset", @"bezel-color"]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithFrame:(CGRect)aFrame
|
- (id)initWithFrame:(CGRect)aFrame
|
||||||
{
|
{
|
||||||
self = [super initWithFrame:aFrame];
|
self = [super initWithFrame:aFrame];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
// Should we instead override the defaults?
|
// Should we instead override the defaults?
|
||||||
@@ -140,16 +139,13 @@ CPButtonImageOffset = 3.0;
|
|||||||
[self setValue:CPCenterVerticalTextAlignment forThemeAttribute:@"vertical-alignment"];
|
[self setValue:CPCenterVerticalTextAlignment forThemeAttribute:@"vertical-alignment"];
|
||||||
[self setValue:CPImageLeft forThemeAttribute:@"image-position"];
|
[self setValue:CPImageLeft forThemeAttribute:@"image-position"];
|
||||||
[self setValue:CPScaleNone forThemeAttribute:@"image-scaling"];
|
[self setValue:CPScaleNone forThemeAttribute:@"image-scaling"];
|
||||||
|
|
||||||
_controlSize = CPRegularControlSize;
|
_controlSize = CPRegularControlSize;
|
||||||
|
|
||||||
_keyEquivalent = @"";
|
|
||||||
_keyEquivalentModifierMask = 0;
|
|
||||||
|
|
||||||
// [self setBezelStyle:CPRoundRectBezelStyle];
|
// [self setBezelStyle:CPRoundRectBezelStyle];
|
||||||
[self setBordered:YES];
|
[self setBordered:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,9 +248,9 @@ CPButtonImageOffset = 3.0;
|
|||||||
{
|
{
|
||||||
if (_title === aTitle)
|
if (_title === aTitle)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_title = aTitle;
|
_title = aTitle;
|
||||||
|
|
||||||
[self setNeedsLayout];
|
[self setNeedsLayout];
|
||||||
[self setNeedsDisplay:YES];
|
[self setNeedsDisplay:YES];
|
||||||
}
|
}
|
||||||
@@ -268,7 +264,7 @@ CPButtonImageOffset = 3.0;
|
|||||||
{
|
{
|
||||||
if (_alternateTitle === aTitle)
|
if (_alternateTitle === aTitle)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_alternateTitle = aTitle;
|
_alternateTitle = aTitle;
|
||||||
|
|
||||||
[self setNeedsLayout];
|
[self setNeedsLayout];
|
||||||
@@ -282,12 +278,18 @@ CPButtonImageOffset = 3.0;
|
|||||||
|
|
||||||
- (void)setImage:(CPImage)anImage
|
- (void)setImage:(CPImage)anImage
|
||||||
{
|
{
|
||||||
[self setValue:anImage forThemeAttribute:@"image"];
|
if (_image === anImage)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_image = anImage;
|
||||||
|
|
||||||
|
[self setNeedsLayout];
|
||||||
|
[self setNeedsDisplay:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CPImage)image
|
- (CPImage)image
|
||||||
{
|
{
|
||||||
return [self valueForThemeAttribute:@"image" inState:CPThemeStateNormal];
|
return _image;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -296,7 +298,13 @@ CPButtonImageOffset = 3.0;
|
|||||||
*/
|
*/
|
||||||
- (void)setAlternateImage:(CPImage)anImage
|
- (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
|
- (CPImage)alternateImage
|
||||||
{
|
{
|
||||||
return [self valueForThemeAttribute:@"image" inState:CPThemeStateHighlighted];
|
return _alternateImage;
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setImageOffset:(float)theImageOffset
|
|
||||||
{
|
|
||||||
[self setValue:theImageOffset forThemeAttribute:@"image-offset"];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (float)imageOffset
|
|
||||||
{
|
|
||||||
return [self valueForThemeAttribute:@"image-offset"];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setShowsStateBy:(CPInteger)aMask
|
- (void)setShowsStateBy:(CPInteger)aMask
|
||||||
@@ -375,13 +373,13 @@ CPButtonImageOffset = 3.0;
|
|||||||
[self setShowsStateBy:CPContentsCellMask];
|
[self setShowsStateBy:CPContentsCellMask];
|
||||||
break;
|
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."];
|
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."];
|
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."];
|
reason:"Unknown button type."];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,7 +395,7 @@ CPButtonImageOffset = 3.0;
|
|||||||
|
|
||||||
_imageDimsWhenDisabled = imageShouldDimWhenDisabled;
|
_imageDimsWhenDisabled = imageShouldDimWhenDisabled;
|
||||||
|
|
||||||
if ([self hasThemeState:CPThemeStateDisabled])
|
if (_imageDimsWhenDisabled)
|
||||||
{
|
{
|
||||||
[self setNeedsDisplay:YES];
|
[self setNeedsDisplay:YES];
|
||||||
[self setNeedsLayout];
|
[self setNeedsLayout];
|
||||||
@@ -412,7 +410,7 @@ CPButtonImageOffset = 3.0;
|
|||||||
- (BOOL)startTrackingAt:(CGPoint)aPoint
|
- (BOOL)startTrackingAt:(CGPoint)aPoint
|
||||||
{
|
{
|
||||||
[self highlight:YES];
|
[self highlight:YES];
|
||||||
|
|
||||||
return [super startTrackingAt:aPoint];
|
return [super startTrackingAt:aPoint];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -433,12 +431,11 @@ CPButtonImageOffset = 3.0;
|
|||||||
if (_CGInsetIsEmpty(contentInset))
|
if (_CGInsetIsEmpty(contentInset))
|
||||||
return bounds;
|
return bounds;
|
||||||
|
|
||||||
bounds = _CGRectMakeCopy(bounds);
|
|
||||||
bounds.origin.x += contentInset.left;
|
bounds.origin.x += contentInset.left;
|
||||||
bounds.origin.y += contentInset.top;
|
bounds.origin.y += contentInset.top;
|
||||||
bounds.size.width -= contentInset.left + contentInset.right;
|
bounds.size.width -= contentInset.left + contentInset.right;
|
||||||
bounds.size.height -= contentInset.top + contentInset.bottom;
|
bounds.size.height -= contentInset.top + contentInset.bottom;
|
||||||
|
|
||||||
return bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,7 +449,6 @@ CPButtonImageOffset = 3.0;
|
|||||||
if (_CGInsetIsEmpty(bezelInset))
|
if (_CGInsetIsEmpty(bezelInset))
|
||||||
return bounds;
|
return bounds;
|
||||||
|
|
||||||
bounds = _CGRectMakeCopy(bounds);
|
|
||||||
bounds.origin.x += bezelInset.left;
|
bounds.origin.x += bezelInset.left;
|
||||||
bounds.origin.y += bezelInset.top;
|
bounds.origin.y += bezelInset.top;
|
||||||
bounds.size.width -= bezelInset.left + bezelInset.right;
|
bounds.size.width -= bezelInset.left + bezelInset.right;
|
||||||
@@ -466,20 +462,8 @@ CPButtonImageOffset = 3.0;
|
|||||||
*/
|
*/
|
||||||
- (void)sizeToFit
|
- (void)sizeToFit
|
||||||
{
|
{
|
||||||
[self layoutSubviews];
|
var size = [([self title] || " ") sizeWithFont:[self currentValueForThemeAttribute:@"font"]],
|
||||||
|
contentInset = [self currentValueForThemeAttribute:@"content-inset"],
|
||||||
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"],
|
|
||||||
minSize = [self currentValueForThemeAttribute:@"min-size"],
|
minSize = [self currentValueForThemeAttribute:@"min-size"],
|
||||||
maxSize = [self currentValueForThemeAttribute:@"max-size"];
|
maxSize = [self currentValueForThemeAttribute:@"max-size"];
|
||||||
|
|
||||||
@@ -499,10 +483,10 @@ CPButtonImageOffset = 3.0;
|
|||||||
{
|
{
|
||||||
if (aName === "bezel-view")
|
if (aName === "bezel-view")
|
||||||
return [self bezelRectForBounds:[self bounds]];
|
return [self bezelRectForBounds:[self bounds]];
|
||||||
|
|
||||||
else if (aName === "content-view")
|
else if (aName === "content-view")
|
||||||
return [self contentRectForBounds:[self bounds]];
|
return [self contentRectForBounds:[self bounds]];
|
||||||
|
|
||||||
return [super rectForEphemeralSubviewNamed:aName];
|
return [super rectForEphemeralSubviewNamed:aName];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -513,7 +497,7 @@ CPButtonImageOffset = 3.0;
|
|||||||
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
|
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
|
||||||
|
|
||||||
[view setHitTests:NO];
|
[view setHitTests:NO];
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -535,8 +519,7 @@ CPButtonImageOffset = 3.0;
|
|||||||
if (contentView)
|
if (contentView)
|
||||||
{
|
{
|
||||||
[contentView setText:([self hasThemeState:CPThemeStateHighlighted] && _alternateTitle) ? _alternateTitle : _title];
|
[contentView setText:([self hasThemeState:CPThemeStateHighlighted] && _alternateTitle) ? _alternateTitle : _title];
|
||||||
[contentView setImage:[self currentValueForThemeAttribute:@"image"]];
|
[contentView setImage:([self hasThemeState:CPThemeStateHighlighted] && _alternateImage) ? _alternateImage : _image];
|
||||||
[contentView setImageOffset:[self currentValueForThemeAttribute:@"image-offset"]];
|
|
||||||
|
|
||||||
[contentView setFont:[self currentValueForThemeAttribute:@"font"]];
|
[contentView setFont:[self currentValueForThemeAttribute:@"font"]];
|
||||||
[contentView setTextColor:[self currentValueForThemeAttribute:@"text-color"]];
|
[contentView setTextColor:[self currentValueForThemeAttribute:@"text-color"]];
|
||||||
@@ -547,10 +530,17 @@ CPButtonImageOffset = 3.0;
|
|||||||
[contentView setTextShadowOffset:[self currentValueForThemeAttribute:@"text-shadow-offset"]];
|
[contentView setTextShadowOffset:[self currentValueForThemeAttribute:@"text-shadow-offset"]];
|
||||||
[contentView setImagePosition:[self currentValueForThemeAttribute:@"image-position"]];
|
[contentView setImagePosition:[self currentValueForThemeAttribute:@"image-position"]];
|
||||||
[contentView setImageScaling:[self currentValueForThemeAttribute:@"image-scaling"]];
|
[contentView setImageScaling:[self currentValueForThemeAttribute:@"image-scaling"]];
|
||||||
[contentView setDimsImage:[self hasThemeState:CPThemeStateDisabled] && _imageDimsWhenDisabled];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setDefaultButton:(BOOL)shouldBeDefaultButton
|
||||||
|
{
|
||||||
|
if (shouldBeDefaultButton)
|
||||||
|
[self setThemeState:CPThemeStateDefault];
|
||||||
|
else
|
||||||
|
[self unsetThemeState:CPThemeStateDefault];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setBordered:(BOOL)shouldBeBordered
|
- (void)setBordered:(BOOL)shouldBeBordered
|
||||||
{
|
{
|
||||||
if (shouldBeBordered)
|
if (shouldBeBordered)
|
||||||
@@ -564,79 +554,6 @@ CPButtonImageOffset = 3.0;
|
|||||||
return [self hasThemeState:CPThemeStateBordered];
|
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
|
@end
|
||||||
|
|
||||||
@implementation CPButton (NS)
|
@implementation CPButton (NS)
|
||||||
@@ -652,16 +569,11 @@ CPButtonImageOffset = 3.0;
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
var CPButtonImageKey = @"CPButtonImageKey",
|
var CPButtonImageKey = @"CPButtonImageKey",
|
||||||
CPButtonAlternateImageKey = @"CPButtonAlternateImageKey",
|
CPButtonAlternateImageKey = @"CPButtonAlternateImageKey",
|
||||||
CPButtonTitleKey = @"CPButtonTitleKey",
|
CPButtonTitleKey = @"CPButtonTitleKey",
|
||||||
CPButtonAlternateTitleKey = @"CPButtonAlternateTitleKey",
|
CPButtonAlternateTitleKey = @"CPButtonAlternateTitleKey",
|
||||||
CPButtonIsBorderedKey = @"CPButtonIsBorderedKey",
|
CPButtonIsBorderedKey = @"CPButtonIsBorderedKey";
|
||||||
CPButtonAllowsMixedStateKey = @"CPButtonAllowsMixedStateKey",
|
|
||||||
CPButtonImageDimsWhenDisabledKey = @"CPButtonImageDimsWhenDisabledKey",
|
|
||||||
CPButtonImagePositionKey = @"CPButtonImagePositionKey",
|
|
||||||
CPButtonKeyEquivalentKey = @"CPButtonKeyEquivalentKey",
|
|
||||||
CPButtonKeyEquivalentMaskKey = @"CPButtonKeyEquivalentMaskKey";
|
|
||||||
|
|
||||||
@implementation CPButton (CPCoding)
|
@implementation CPButton (CPCoding)
|
||||||
|
|
||||||
@@ -672,31 +584,21 @@ var CPButtonImageKey = @"CPButtonImageKey",
|
|||||||
- (id)initWithCoder:(CPCoder)aCoder
|
- (id)initWithCoder:(CPCoder)aCoder
|
||||||
{
|
{
|
||||||
self = [super initWithCoder:aCoder];
|
self = [super initWithCoder:aCoder];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_controlSize = CPRegularControlSize;
|
_controlSize = CPRegularControlSize;
|
||||||
|
|
||||||
_title = [aCoder decodeObjectForKey:CPButtonTitleKey];
|
[self setImage:[aCoder decodeObjectForKey:CPButtonImageKey]];
|
||||||
_alternateTitle = [aCoder decodeObjectForKey:CPButtonAlternateTitleKey];
|
[self setAlternateImage:[aCoder decodeObjectForKey:CPButtonAlternateImageKey]];
|
||||||
|
|
||||||
if ([aCoder containsValueForKey:CPButtonAllowsMixedStateKey])
|
[self setTitle:[aCoder decodeObjectForKey:CPButtonTitleKey]];
|
||||||
_allowsMixedState = [aCoder decodeBoolForKey:CPButtonAllowsMixedStateKey];
|
[self setAlternateTitle:[aCoder decodeObjectForKey:CPButtonAlternateTitleKey]];
|
||||||
|
|
||||||
[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 setNeedsLayout];
|
[self setNeedsLayout];
|
||||||
[self setNeedsDisplay:YES];
|
[self setNeedsDisplay:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -708,18 +610,11 @@ var CPButtonImageKey = @"CPButtonImageKey",
|
|||||||
{
|
{
|
||||||
[super encodeWithCoder:aCoder];
|
[super encodeWithCoder:aCoder];
|
||||||
|
|
||||||
|
[aCoder encodeObject:_image forKey:CPButtonImageKey];
|
||||||
|
[aCoder encodeObject:_alternateImage forKey:CPButtonAlternateImageKey];
|
||||||
|
|
||||||
[aCoder encodeObject:_title forKey:CPButtonTitleKey];
|
[aCoder encodeObject:_title forKey:CPButtonTitleKey];
|
||||||
[aCoder encodeObject:_alternateTitle forKey:CPButtonAlternateTitleKey];
|
[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
|
@end
|
||||||
|
|||||||
+29
-57
@@ -1,5 +1,7 @@
|
|||||||
|
|
||||||
@import "CPView.j"
|
@import <AppKit/CPView.j>
|
||||||
|
|
||||||
|
#include "CoreGraphics/CGGeometry.h"
|
||||||
|
|
||||||
|
|
||||||
@implementation CPButtonBar : CPView
|
@implementation CPButtonBar : CPView
|
||||||
@@ -12,9 +14,8 @@
|
|||||||
+ (id)plusButton
|
+ (id)plusButton
|
||||||
{
|
{
|
||||||
var button = [[CPButton alloc] initWithFrame:CGRectMake(0, 0, 35, 25)],
|
var button = [[CPButton alloc] initWithFrame:CGRectMake(0, 0, 35, 25)],
|
||||||
image = [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPButtonBar class]] pathForResource:@"plus_button.png"] size:CGSizeMake(11, 12)];
|
image = [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:self] pathForResource:@"plus_button.png"] size:CGSizeMake(11, 12)];
|
||||||
|
|
||||||
[button setBordered:NO];
|
|
||||||
[button setImage:image];
|
[button setImage:image];
|
||||||
[button setImagePosition:CPImageOnly];
|
[button setImagePosition:CPImageOnly];
|
||||||
|
|
||||||
@@ -24,39 +25,23 @@
|
|||||||
+ (id)minusButton
|
+ (id)minusButton
|
||||||
{
|
{
|
||||||
var button = [[CPButton alloc] initWithFrame:CGRectMake(0, 0, 35, 25)],
|
var button = [[CPButton alloc] initWithFrame:CGRectMake(0, 0, 35, 25)],
|
||||||
image = [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPButtonBar class]] pathForResource:@"minus_button.png"] size:CGSizeMake(11, 4)];
|
image = [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:self] pathForResource:@"minus_button.png"] size:CGSizeMake(11, 4)];
|
||||||
|
|
||||||
[button setBordered:NO];
|
|
||||||
[button setImage:image];
|
[button setImage:image];
|
||||||
[button setImagePosition:CPImageOnly];
|
[button setImagePosition:CPImageOnly];
|
||||||
|
|
||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (id)actionPopupButton
|
+ (CPString)themeClass
|
||||||
{
|
|
||||||
var button = [[CPPopUpButton alloc] initWithFrame:CGRectMake(0, 0, 35, 25)],
|
|
||||||
image = [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPButtonBar class]] pathForResource:@"action_button.png"] size:CGSizeMake(22, 14)];
|
|
||||||
|
|
||||||
[button addItemWithTitle:nil];
|
|
||||||
[[button lastItem] setImage:image];
|
|
||||||
[button setImagePosition:CPImageOnly];
|
|
||||||
[button setValue:CGInsetMake(0, 0, 0, 0) forThemeAttribute:"content-inset"];
|
|
||||||
|
|
||||||
[button setPullsDown:YES];
|
|
||||||
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (CPString)defaultThemeClass
|
|
||||||
{
|
{
|
||||||
return @"button-bar";
|
return @"button-bar";
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (id)themeAttributes
|
+ (id)themeAttributes
|
||||||
{
|
{
|
||||||
return [CPDictionary dictionaryWithObjects:[CGInsetMake(0.0, 0.0, 0.0, 0.0), CGSizeMakeZero(), [CPNull null], [CPNull null], [CPNull null], [CPNull null]]
|
return [CPDictionary dictionaryWithObjects:[CGInsetMake(0.0, 0.0, 0.0, 0.0), CGSizeMakeZero(), [CPNull null], [CPNull null], [CPNull null]]
|
||||||
forKeys:[@"resize-control-inset", @"resize-control-size", @"resize-control-color", @"bezel-color", @"button-bezel-color", @"button-text-color"]];
|
forKeys:[@"resize-control-inset", @"resize-control-size", @"resize-control-color", @"bezel-color", @"button-bezel-color"]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithFrame:(CGRect)aFrame
|
- (id)initWithFrame:(CGRect)aFrame
|
||||||
@@ -97,8 +82,25 @@
|
|||||||
_buttons = [CPArray arrayWithArray:buttons];
|
_buttons = [CPArray arrayWithArray:buttons];
|
||||||
|
|
||||||
for (var i = 0, count = [_buttons count]; i < count; i++)
|
for (var i = 0, count = [_buttons count]; i < count; i++)
|
||||||
[_buttons[i] setBordered:YES];
|
{
|
||||||
|
var button = _buttons[i];
|
||||||
|
|
||||||
|
var normalColor = [self valueForThemeAttribute:@"button-bezel-color" inState:CPThemeStateNormal],
|
||||||
|
highlightedColor = [self valueForThemeAttribute:@"button-bezel-color" inState:CPThemeStateHighlighted],
|
||||||
|
disabledColor = [self valueForThemeAttribute:@"button-bezel-color" inState:CPThemeStateDisabled];
|
||||||
|
|
||||||
|
[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];
|
||||||
|
|
||||||
|
// 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 setBordered:YES];
|
||||||
|
}
|
||||||
|
|
||||||
[self setNeedsLayout];
|
[self setNeedsLayout];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,11 +176,6 @@
|
|||||||
{
|
{
|
||||||
[self setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]];
|
[self setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]];
|
||||||
|
|
||||||
var normalColor = [self valueForThemeAttribute:@"button-bezel-color" inState:CPThemeStateNormal],
|
|
||||||
highlightedColor = [self valueForThemeAttribute:@"button-bezel-color" inState:CPThemeStateHighlighted],
|
|
||||||
disabledColor = [self valueForThemeAttribute:@"button-bezel-color" inState:CPThemeStateDisabled],
|
|
||||||
textColor = [self valueForThemeAttribute:@"button-text-color" inState:CPThemeStateNormal];
|
|
||||||
|
|
||||||
var buttonsNotHidden = [CPArray arrayWithArray:_buttons],
|
var buttonsNotHidden = [CPArray arrayWithArray:_buttons],
|
||||||
count = [buttonsNotHidden count];
|
count = [buttonsNotHidden count];
|
||||||
|
|
||||||
@@ -187,23 +184,13 @@
|
|||||||
[buttonsNotHidden removeObject:buttonsNotHidden[count]];
|
[buttonsNotHidden removeObject:buttonsNotHidden[count]];
|
||||||
|
|
||||||
var currentButtonOffset = _resizeControlIsLeftAligned ? CGRectGetMaxX([self bounds]) + 1 : -1,
|
var currentButtonOffset = _resizeControlIsLeftAligned ? CGRectGetMaxX([self bounds]) + 1 : -1,
|
||||||
bounds = [self bounds],
|
height = CGRectGetHeight([self bounds]) - 1;
|
||||||
height = CGRectGetHeight(bounds) - 1,
|
|
||||||
frameWidth = CGRectGetWidth(bounds),
|
|
||||||
resizeRect = _hasResizeControl ? [self rectForEphemeralSubviewNamed:"resize-control-view"] : CGRectMakeZero(),
|
|
||||||
resizeWidth = CGRectGetWidth(resizeRect),
|
|
||||||
availableWidth = frameWidth - resizeWidth - 1;
|
|
||||||
|
|
||||||
for (var i = 0, count = [buttonsNotHidden count]; i < count; i++)
|
for (var i = 0, count = [buttonsNotHidden count]; i < count; i++)
|
||||||
{
|
{
|
||||||
var button = buttonsNotHidden[i],
|
var button = buttonsNotHidden[i],
|
||||||
width = CGRectGetWidth([button frame]);
|
width = CGRectGetWidth([button frame]);
|
||||||
|
|
||||||
if (availableWidth > width)
|
|
||||||
availableWidth -= width;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (_resizeControlIsLeftAligned)
|
if (_resizeControlIsLeftAligned)
|
||||||
{
|
{
|
||||||
[button setFrame:CGRectMake(currentButtonOffset - width, 1, width, height)];
|
[button setFrame:CGRectMake(currentButtonOffset - width, 1, width, height)];
|
||||||
@@ -215,16 +202,6 @@
|
|||||||
currentButtonOffset += width - 1;
|
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];
|
|
||||||
|
|
||||||
// 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];
|
|
||||||
|
|
||||||
[self addSubview:button];
|
[self addSubview:button];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,12 +216,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setFrameSize:(CGSize)aSize
|
|
||||||
{
|
|
||||||
[super setFrameSize:aSize];
|
|
||||||
[self setNeedsLayout];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
var CPButtonBarHasResizeControlKey = @"CPButtonBarHasResizeControlKey",
|
var CPButtonBarHasResizeControlKey = @"CPButtonBarHasResizeControlKey",
|
||||||
@@ -275,3 +246,4 @@ var CPButtonBarHasResizeControlKey = @"CPButtonBarHasResizeControlKey",
|
|||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
+2
-27
@@ -23,8 +23,6 @@
|
|||||||
@import "CPButton.j"
|
@import "CPButton.j"
|
||||||
|
|
||||||
|
|
||||||
CPCheckBoxImageOffset = 4.0;
|
|
||||||
|
|
||||||
@implementation CPCheckBox : CPButton
|
@implementation CPCheckBox : CPButton
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -39,7 +37,7 @@ CPCheckBoxImageOffset = 4.0;
|
|||||||
return [self buttonWithTitle:aTitle];
|
return [self buttonWithTitle:aTitle];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (CPString)defaultThemeClass
|
+ (CPString)themeClass
|
||||||
{
|
{
|
||||||
return @"check-box";
|
return @"check-box";
|
||||||
}
|
}
|
||||||
@@ -57,33 +55,10 @@ CPCheckBoxImageOffset = 4.0;
|
|||||||
[self setImagePosition:CPImageLeft];
|
[self setImagePosition:CPImageLeft];
|
||||||
[self setAlignment:CPLeftTextAlignment];
|
[self setAlignment:CPLeftTextAlignment];
|
||||||
|
|
||||||
[self setBordered:NO];
|
[self setBordered:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)takeStateFromKeyPath:(CPString)aKeyPath ofObjects:(CPArray)objects
|
|
||||||
{
|
|
||||||
var count = objects.length,
|
|
||||||
value = [objects[0] valueForKeyPath:aKeyPath] ? CPOnState : CPOffState;
|
|
||||||
|
|
||||||
[self setAllowsMixedState:NO];
|
|
||||||
[self setState:value];
|
|
||||||
|
|
||||||
while (count-- > 1)
|
|
||||||
{
|
|
||||||
if (value !== ([objects[count] valueForKeyPath:aKeyPath] ? CPOnState : CPOffState))
|
|
||||||
{
|
|
||||||
[self setAllowsMixedState:YES];
|
|
||||||
[self setState:CPMixedState];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)takeValueFromKeyPath:(CPString)aKeyPath ofObjects:(CPArray)objects
|
|
||||||
{
|
|
||||||
[self takeStateFromKeyPath:aKeyPath ofObjects:objects];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
+31
-51
@@ -22,12 +22,14 @@
|
|||||||
|
|
||||||
@import "CPView.j"
|
@import "CPView.j"
|
||||||
|
|
||||||
|
#include "CoreGraphics/CGGeometry.h"
|
||||||
|
|
||||||
/*!
|
|
||||||
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPClipView
|
@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.
|
It is used to hold the document view in a CPScrollView.
|
||||||
*/
|
*/
|
||||||
@implementation CPClipView : CPView
|
@implementation CPClipView : CPView
|
||||||
@@ -45,7 +47,7 @@
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var defaultCenter = [CPNotificationCenter defaultCenter];
|
var defaultCenter = [CPNotificationCenter defaultCenter];
|
||||||
|
|
||||||
if (_documentView)
|
if (_documentView)
|
||||||
{
|
{
|
||||||
[defaultCenter
|
[defaultCenter
|
||||||
@@ -57,29 +59,29 @@
|
|||||||
removeObserver:self
|
removeObserver:self
|
||||||
name:CPViewBoundsDidChangeNotification
|
name:CPViewBoundsDidChangeNotification
|
||||||
object:_documentView];
|
object:_documentView];
|
||||||
|
|
||||||
[_documentView removeFromSuperview];
|
[_documentView removeFromSuperview];
|
||||||
}
|
}
|
||||||
|
|
||||||
_documentView = aView;
|
_documentView = aView;
|
||||||
|
|
||||||
if (_documentView)
|
if (_documentView)
|
||||||
{
|
{
|
||||||
[self addSubview:_documentView];
|
[self addSubview:_documentView];
|
||||||
|
|
||||||
|
[_documentView setPostsFrameChangedNotifications:YES];
|
||||||
|
[_documentView setPostsBoundsChangedNotifications:YES];
|
||||||
|
|
||||||
[_documentView setPostsFrameChangedNotifications:YES];
|
[defaultCenter
|
||||||
[_documentView setPostsBoundsChangedNotifications:YES];
|
|
||||||
|
|
||||||
[defaultCenter
|
|
||||||
addObserver:self
|
addObserver:self
|
||||||
selector:@selector(viewFrameChanged:)
|
selector:@selector(viewFrameChanged:)
|
||||||
name:CPViewFrameDidChangeNotification
|
name:CPViewFrameDidChangeNotification
|
||||||
object:_documentView];
|
object:_documentView];
|
||||||
|
|
||||||
[defaultCenter
|
[defaultCenter
|
||||||
addObserver:self
|
addObserver:self
|
||||||
selector:@selector(viewBoundsChanged:)
|
selector:@selector(viewBoundsChanged:)
|
||||||
name:CPViewBoundsDidChangeNotification
|
name:CPViewBoundsDidChangeNotification
|
||||||
object:_documentView];
|
object:_documentView];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,7 +106,7 @@
|
|||||||
return _CGPointMakeZero();
|
return _CGPointMakeZero();
|
||||||
|
|
||||||
var documentFrame = [_documentView frame];
|
var documentFrame = [_documentView frame];
|
||||||
|
|
||||||
aPoint.x = MAX(0.0, MIN(aPoint.x, MAX(_CGRectGetWidth(documentFrame) - _CGRectGetWidth(_bounds), 0.0)));
|
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)));
|
aPoint.y = MAX(0.0, MIN(aPoint.y, MAX(_CGRectGetHeight(documentFrame) - _CGRectGetHeight(_bounds), 0.0)));
|
||||||
|
|
||||||
@@ -115,7 +117,7 @@
|
|||||||
{
|
{
|
||||||
if (_CGPointEqualToPoint(_bounds.origin, aPoint))
|
if (_CGPointEqualToPoint(_bounds.origin, aPoint))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[super setBoundsOrigin:aPoint];
|
[super setBoundsOrigin:aPoint];
|
||||||
|
|
||||||
var superview = [self superview],
|
var superview = [self superview],
|
||||||
@@ -124,7 +126,7 @@
|
|||||||
// FIXME: Should CPScrollView be finding out about this on its own somehow?
|
// FIXME: Should CPScrollView be finding out about this on its own somehow?
|
||||||
scrollViewClass = objj_getClass("CPScrollView");
|
scrollViewClass = objj_getClass("CPScrollView");
|
||||||
|
|
||||||
if ([superview isKindOfClass:scrollViewClass])
|
if([superview isKindOfClass:scrollViewClass])
|
||||||
[superview reflectScrolledClipView:self];
|
[superview reflectScrolledClipView:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,12 +166,12 @@
|
|||||||
- (void)_constrainScrollPoint
|
- (void)_constrainScrollPoint
|
||||||
{
|
{
|
||||||
var oldScrollPoint = [self bounds].origin;
|
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.
|
// sense given the new frame of the document view.
|
||||||
[self scrollToPoint:oldScrollPoint];
|
[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).
|
// the scroll points are not equal (meaning scrollToPoint: didn't early bail).
|
||||||
if (!CGPointEqualToPoint(oldScrollPoint, [self bounds].origin))
|
if (!CGPointEqualToPoint(oldScrollPoint, [self bounds].origin))
|
||||||
return;
|
return;
|
||||||
@@ -185,42 +187,20 @@
|
|||||||
[superview reflectScrolledClipView:self];
|
[superview reflectScrolledClipView:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)autoscroll:(CPEvent)anEvent
|
- (BOOL)autoscroll:(CPEvent)anEvent
|
||||||
{
|
{
|
||||||
var bounds = [self bounds],
|
var bounds = [self bounds],
|
||||||
eventLocation = [self convertPoint:[anEvent locationInWindow] fromView:nil],
|
eventLocation = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
||||||
superview = [self superview],
|
|
||||||
deltaX = 0,
|
|
||||||
deltaY = 0;
|
|
||||||
|
|
||||||
if (CGRectContainsPoint(bounds, eventLocation))
|
if (CPRectContainsPoint(bounds, eventLocation))
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
if (![superview isKindOfClass:[CPScrollView class]] || [superview hasVerticalScroller])
|
var newRect = CGRectMakeZero();
|
||||||
{
|
|
||||||
if (eventLocation.y < CGRectGetMinY(bounds))
|
|
||||||
deltaY = CGRectGetMinY(bounds) - eventLocation.y;
|
|
||||||
else if (eventLocation.y > CGRectGetMaxY(bounds))
|
|
||||||
deltaY = CGRectGetMaxY(bounds) - eventLocation.y;
|
|
||||||
if (deltaY < -bounds.size.height)
|
|
||||||
deltaY = -bounds.size.height;
|
|
||||||
if (deltaY > bounds.size.height)
|
|
||||||
deltaY = bounds.size.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (![superview isKindOfClass:[CPScrollView class]] || [superview hasHorizontalScroller])
|
newRect.origin = eventLocation;
|
||||||
{
|
newRect.size = CPSizeMake(10, 10);
|
||||||
if (eventLocation.x < CGRectGetMinX(bounds))
|
|
||||||
deltaX = CGRectGetMinX(bounds) - eventLocation.x;
|
|
||||||
else if (eventLocation.x > CGRectGetMaxX(bounds))
|
|
||||||
deltaX = CGRectGetMaxX(bounds) - eventLocation.x;
|
|
||||||
if (deltaX < -bounds.size.width)
|
|
||||||
deltaX = -bounds.size.width;
|
|
||||||
if (deltaX > bounds.size.width)
|
|
||||||
deltaX = bounds.size.width;
|
|
||||||
}
|
|
||||||
|
|
||||||
return [self scrollToPoint:CGPointMake(bounds.origin.x - deltaX, bounds.origin.y - deltaY)];
|
return [_documentView scrollRectToVisible:newRect];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -234,14 +214,14 @@ var CPClipViewDocumentViewKey = @"CPScrollViewDocumentView";
|
|||||||
{
|
{
|
||||||
if (self = [super initWithCoder:aCoder])
|
if (self = [super initWithCoder:aCoder])
|
||||||
[self setDocumentView:[aCoder decodeObjectForKey:CPClipViewDocumentViewKey]];
|
[self setDocumentView:[aCoder decodeObjectForKey:CPClipViewDocumentViewKey]];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||||
{
|
{
|
||||||
[super encodeWithCoder:aCoder];
|
[super encodeWithCoder:aCoder];
|
||||||
|
|
||||||
[aCoder encodeObject:_documentView forKey:CPClipViewDocumentViewKey];
|
[aCoder encodeObject:_documentView forKey:CPClipViewDocumentViewKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+100
-196
@@ -30,16 +30,16 @@
|
|||||||
@import "CPCollectionViewItem.j"
|
@import "CPCollectionViewItem.j"
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPCollectionView
|
@class CPCollectionView
|
||||||
|
|
||||||
This class displays an array as a grid of objects, where each object is represented by a view.
|
This class displays an array as a grid of objects, where each object is represented by a view.
|
||||||
The view is controlled by creating a CPCollectionViewItem and specifying its view, then
|
The view is controlled by creating a CPCollectionViewItem and specifying its view, then
|
||||||
setting that item as the collection view prototype.
|
setting that item as the collection view prototype.
|
||||||
|
|
||||||
@par Delegate Methods
|
@par Delegate Methods
|
||||||
|
|
||||||
@delegate -(void)collectionViewDidChangeSelection:(CPCollectionView)collectionView;
|
@delegate -(void)collectionViewDidChangeSelection:(CPCollectionView)collectionView;
|
||||||
Called when the selection in the collection view has changed.
|
Called when the selection in the collection view has changed.
|
||||||
@param collectionView the collection view who's selection changed
|
@param collectionView the collection view who's selection changed
|
||||||
@@ -67,35 +67,35 @@
|
|||||||
{
|
{
|
||||||
CPArray _content;
|
CPArray _content;
|
||||||
CPArray _items;
|
CPArray _items;
|
||||||
|
|
||||||
CPData _itemData;
|
CPData _itemData;
|
||||||
CPCollectionViewItem _itemPrototype;
|
CPCollectionViewItem _itemPrototype;
|
||||||
CPCollectionViewItem _itemForDragging;
|
CPCollectionViewItem _itemForDragging;
|
||||||
CPMutableArray _cachedItems;
|
CPMutableArray _cachedItems;
|
||||||
|
|
||||||
unsigned _maxNumberOfRows;
|
unsigned _maxNumberOfRows;
|
||||||
unsigned _maxNumberOfColumns;
|
unsigned _maxNumberOfColumns;
|
||||||
|
|
||||||
CGSize _minItemSize;
|
CGSize _minItemSize;
|
||||||
CGSize _maxItemSize;
|
CGSize _maxItemSize;
|
||||||
|
|
||||||
CPArray _backgroundColors;
|
CPArray _backgroundColors;
|
||||||
|
|
||||||
float _tileWidth;
|
float _tileWidth;
|
||||||
|
|
||||||
BOOL _isSelectable;
|
BOOL _isSelectable;
|
||||||
BOOL _allowsMultipleSelection;
|
BOOL _allowsMultipleSelection;
|
||||||
BOOL _allowsEmptySelection;
|
BOOL _allowsEmptySelection;
|
||||||
CPIndexSet _selectionIndexes;
|
CPIndexSet _selectionIndexes;
|
||||||
|
|
||||||
CGSize _itemSize;
|
CGSize _itemSize;
|
||||||
|
|
||||||
float _horizontalMargin;
|
float _horizontalMargin;
|
||||||
float _verticalMargin;
|
float _verticalMargin;
|
||||||
|
|
||||||
unsigned _numberOfRows;
|
unsigned _numberOfRows;
|
||||||
unsigned _numberOfColumns;
|
unsigned _numberOfColumns;
|
||||||
|
|
||||||
id _delegate;
|
id _delegate;
|
||||||
|
|
||||||
CPEvent _mouseDownEvent;
|
CPEvent _mouseDownEvent;
|
||||||
@@ -104,14 +104,14 @@
|
|||||||
- (id)initWithFrame:(CGRect)aFrame
|
- (id)initWithFrame:(CGRect)aFrame
|
||||||
{
|
{
|
||||||
self = [super initWithFrame:aFrame];
|
self = [super initWithFrame:aFrame];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_items = [];
|
_items = [];
|
||||||
_content = [];
|
_content = [];
|
||||||
|
|
||||||
_cachedItems = [];
|
_cachedItems = [];
|
||||||
|
|
||||||
_itemSize = CGSizeMakeZero();
|
_itemSize = CGSizeMakeZero();
|
||||||
_minItemSize = CGSizeMakeZero();
|
_minItemSize = CGSizeMakeZero();
|
||||||
_maxItemSize = CGSizeMakeZero();
|
_maxItemSize = CGSizeMakeZero();
|
||||||
@@ -120,12 +120,12 @@
|
|||||||
|
|
||||||
_verticalMargin = 5.0;
|
_verticalMargin = 5.0;
|
||||||
_tileWidth = -1.0;
|
_tileWidth = -1.0;
|
||||||
|
|
||||||
_selectionIndexes = [CPIndexSet indexSet];
|
_selectionIndexes = [CPIndexSet indexSet];
|
||||||
_allowsEmptySelection = YES;
|
_allowsEmptySelection = YES;
|
||||||
_isSelectable = YES;
|
_isSelectable = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,8 +196,8 @@
|
|||||||
|
|
||||||
// Setting the Content
|
// Setting the Content
|
||||||
/*!
|
/*!
|
||||||
Sets the content of the collection view to the content in \c anArray.
|
Sets the content of the collection view to the content in \c anArray.
|
||||||
This array can be of any type, and each element will be passed to the \c -setRepresentedObject: method.
|
This array can be of any type, and each element will be passed to the \c -setRepresentedObject: method.
|
||||||
It's the responsibility of your custom collection view item to interpret the object.
|
It's the responsibility of your custom collection view item to interpret the object.
|
||||||
@param anArray the content array
|
@param anArray the content array
|
||||||
*/
|
*/
|
||||||
@@ -205,9 +205,9 @@
|
|||||||
{
|
{
|
||||||
if (_content == anArray)
|
if (_content == anArray)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_content = anArray;
|
_content = anArray;
|
||||||
|
|
||||||
[self reloadContent];
|
[self reloadContent];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,13 +236,13 @@
|
|||||||
{
|
{
|
||||||
if (_isSelectable == isSelectable)
|
if (_isSelectable == isSelectable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_isSelectable = isSelectable;
|
_isSelectable = isSelectable;
|
||||||
|
|
||||||
if (!_isSelectable)
|
if (!_isSelectable)
|
||||||
{
|
{
|
||||||
var index = CPNotFound;
|
var index = CPNotFound;
|
||||||
|
|
||||||
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
|
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
|
||||||
[_items[index] setSelected:NO];
|
[_items[index] setSelected:NO];
|
||||||
}
|
}
|
||||||
@@ -297,25 +297,23 @@
|
|||||||
*/
|
*/
|
||||||
- (void)setSelectionIndexes:(CPIndexSet)anIndexSet
|
- (void)setSelectionIndexes:(CPIndexSet)anIndexSet
|
||||||
{
|
{
|
||||||
if ([_selectionIndexes isEqual:anIndexSet] || !_isSelectable)
|
if (_selectionIndexes == anIndexSet || !_isSelectable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var index = CPNotFound;
|
var index = CPNotFound;
|
||||||
|
|
||||||
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
|
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
|
||||||
[_items[index] setSelected:NO];
|
[_items[index] setSelected:NO];
|
||||||
|
|
||||||
_selectionIndexes = anIndexSet;
|
_selectionIndexes = anIndexSet;
|
||||||
|
|
||||||
var index = CPNotFound;
|
var index = CPNotFound;
|
||||||
|
|
||||||
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
|
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
|
||||||
[_items[index] setSelected:YES];
|
[_items[index] setSelected:YES];
|
||||||
|
|
||||||
[[CPKeyValueBinding getBinding:@"selectionIndexes" forObject:self] reverseSetValueFor:@"selectionIndexes"];
|
|
||||||
|
|
||||||
if ([_delegate respondsToSelector:@selector(collectionViewDidChangeSelection:)])
|
if ([_delegate respondsToSelector:@selector(collectionViewDidChangeSelection:)])
|
||||||
[_delegate collectionViewDidChangeSelection:self];
|
[_delegate collectionViewDidChangeSelection:self]
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -328,10 +326,10 @@
|
|||||||
|
|
||||||
/* @ignore */
|
/* @ignore */
|
||||||
- (void)reloadContent
|
- (void)reloadContent
|
||||||
{
|
{
|
||||||
// Remove current views
|
// Remove current views
|
||||||
var count = _items.length;
|
var count = _items.length;
|
||||||
|
|
||||||
while (count--)
|
while (count--)
|
||||||
{
|
{
|
||||||
[[_items[count] view] removeFromSuperview];
|
[[_items[count] view] removeFromSuperview];
|
||||||
@@ -339,7 +337,7 @@
|
|||||||
|
|
||||||
_cachedItems.push(_items[count]);
|
_cachedItems.push(_items[count]);
|
||||||
}
|
}
|
||||||
|
|
||||||
_items = [];
|
_items = [];
|
||||||
|
|
||||||
if (!_itemPrototype || !_content)
|
if (!_itemPrototype || !_content)
|
||||||
@@ -352,7 +350,7 @@
|
|||||||
for (; index < count; ++index)
|
for (; index < count; ++index)
|
||||||
{
|
{
|
||||||
_items.push([self newItemForRepresentedObject:_content[index]]);
|
_items.push([self newItemForRepresentedObject:_content[index]]);
|
||||||
|
|
||||||
[self addSubview:[_items[index] view]];
|
[self addSubview:[_items[index] view]];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,49 +365,49 @@
|
|||||||
- (void)tile
|
- (void)tile
|
||||||
{
|
{
|
||||||
var width = CGRectGetWidth([self bounds]);
|
var width = CGRectGetWidth([self bounds]);
|
||||||
|
|
||||||
if (![_content count] || width == _tileWidth)
|
if (![_content count] || width == _tileWidth)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// We try to fit as many views per row as possible. Any remaining space is then
|
// We try to fit as many views per row as possible. Any remaining space is then
|
||||||
// either proportioned out to the views (if their minSize != maxSize) or used as
|
// either proportioned out to the views (if their minSize != maxSize) or used as
|
||||||
// margin
|
// margin
|
||||||
var itemSize = CGSizeMakeCopy(_minItemSize);
|
var itemSize = CGSizeMakeCopy(_minItemSize);
|
||||||
|
|
||||||
_numberOfColumns = MAX(1.0, FLOOR(width / itemSize.width));
|
_numberOfColumns = MAX(1.0, FLOOR(width / itemSize.width));
|
||||||
|
|
||||||
if (_maxNumberOfColumns > 0)
|
if (_maxNumberOfColumns > 0)
|
||||||
_numberOfColumns = MIN(_maxNumberOfColumns, _numberOfColumns);
|
_numberOfColumns = MIN(_maxNumberOfColumns, _numberOfColumns);
|
||||||
|
|
||||||
var remaining = width - _numberOfColumns * itemSize.width,
|
var remaining = width - _numberOfColumns * itemSize.width,
|
||||||
itemsNeedSizeUpdate = NO;
|
itemsNeedSizeUpdate = NO;
|
||||||
|
|
||||||
if (remaining > 0 && itemSize.width < _maxItemSize.width)
|
if (remaining > 0 && itemSize.width < _maxItemSize.width)
|
||||||
itemSize.width = MIN(_maxItemSize.width, itemSize.width + FLOOR(remaining / _numberOfColumns));
|
itemSize.width = MIN(_maxItemSize.width, itemSize.width + FLOOR(remaining / _numberOfColumns));
|
||||||
|
|
||||||
// When we ONE column and a non-integral width, the FLOORing above can cause the item width to be smaller than the total width.
|
// When we ONE column and a non-integral width, the FLOORing above can cause the item width to be smaller than the total width.
|
||||||
if (_maxNumberOfColumns == 1 && itemSize.width < _maxItemSize.width && itemSize.width < width)
|
if (_maxNumberOfColumns == 1 && itemSize.width < _maxItemSize.width && itemSize.width < width)
|
||||||
itemSize.width = MIN(_maxItemSize.width, width);
|
itemSize.width = MIN(_maxItemSize.width, width);
|
||||||
|
|
||||||
if (!CGSizeEqualToSize(_itemSize, itemSize))
|
if (!CGSizeEqualToSize(_itemSize, itemSize))
|
||||||
{
|
{
|
||||||
_itemSize = itemSize;
|
_itemSize = itemSize;
|
||||||
itemsNeedSizeUpdate = YES;
|
itemsNeedSizeUpdate = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
var index = 0,
|
var index = 0,
|
||||||
count = _items.length;
|
count = _items.length;
|
||||||
|
|
||||||
if (_maxNumberOfColumns > 0 && _maxNumberOfRows > 0)
|
if (_maxNumberOfColumns > 0 && _maxNumberOfRows > 0)
|
||||||
count = MIN(count, _maxNumberOfColumns * _maxNumberOfRows);
|
count = MIN(count, _maxNumberOfColumns * _maxNumberOfRows);
|
||||||
|
|
||||||
_numberOfRows = CEIL(count / _numberOfColumns);
|
_numberOfRows = CEIL(count / _numberOfColumns);
|
||||||
|
|
||||||
_horizontalMargin = FLOOR((width - _numberOfColumns * itemSize.width) / (_numberOfColumns + 1));
|
_horizontalMargin = FLOOR((width - _numberOfColumns * itemSize.width) / (_numberOfColumns + 1));
|
||||||
|
|
||||||
var x = _horizontalMargin,
|
var x = _horizontalMargin,
|
||||||
y = -itemSize.height;
|
y = -itemSize.height;
|
||||||
|
|
||||||
for (; index < count; ++index)
|
for (; index < count; ++index)
|
||||||
{
|
{
|
||||||
if (index % _numberOfColumns == 0)
|
if (index % _numberOfColumns == 0)
|
||||||
@@ -417,28 +415,19 @@
|
|||||||
x = _horizontalMargin;
|
x = _horizontalMargin;
|
||||||
y += _verticalMargin + itemSize.height;
|
y += _verticalMargin + itemSize.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
var view = [_items[index] view];
|
var view = [_items[index] view];
|
||||||
|
|
||||||
[view setFrameOrigin:CGPointMake(x, y)];
|
[view setFrameOrigin:CGPointMake(x, y)];
|
||||||
|
|
||||||
if (itemsNeedSizeUpdate)
|
if (itemsNeedSizeUpdate)
|
||||||
[view setFrameSize:_itemSize];
|
[view setFrameSize:_itemSize];
|
||||||
|
|
||||||
x += itemSize.width + _horizontalMargin;
|
x += itemSize.width + _horizontalMargin;
|
||||||
}
|
}
|
||||||
|
|
||||||
var superview = [self superview],
|
|
||||||
proposedHeight = y + itemSize.height + _verticalMargin;
|
|
||||||
|
|
||||||
if ([superview isKindOfClass:[CPClipView class]])
|
|
||||||
{
|
|
||||||
var superviewSize = [superview bounds].size;
|
|
||||||
proposedHeight = MAX(superviewSize.height, proposedHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
_tileWidth = width;
|
_tileWidth = width;
|
||||||
[self setFrameSize:CGSizeMake(width, proposedHeight)];
|
[self setFrameSize:CGSizeMake(width, y + itemSize.height + _verticalMargin)];
|
||||||
_tileWidth = -1.0;
|
_tileWidth = -1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,9 +445,9 @@
|
|||||||
{
|
{
|
||||||
if (_maxNumberOfRows == aMaxNumberOfRows)
|
if (_maxNumberOfRows == aMaxNumberOfRows)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_maxNumberOfRows = aMaxNumberOfRows;
|
_maxNumberOfRows = aMaxNumberOfRows;
|
||||||
|
|
||||||
[self tile];
|
[self tile];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,9 +467,9 @@
|
|||||||
{
|
{
|
||||||
if (_maxNumberOfColumns == aMaxNumberOfColumns)
|
if (_maxNumberOfColumns == aMaxNumberOfColumns)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_maxNumberOfColumns = aMaxNumberOfColumns;
|
_maxNumberOfColumns = aMaxNumberOfColumns;
|
||||||
|
|
||||||
[self tile];
|
[self tile];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -517,9 +506,9 @@
|
|||||||
{
|
{
|
||||||
if (CGSizeEqualToSize(_minItemSize, aSize))
|
if (CGSizeEqualToSize(_minItemSize, aSize))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_minItemSize = CGSizeMakeCopy(aSize);
|
_minItemSize = CGSizeMakeCopy(aSize);
|
||||||
|
|
||||||
[self tile];
|
[self tile];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -539,9 +528,9 @@
|
|||||||
{
|
{
|
||||||
if (CGSizeEqualToSize(_maxItemSize, aSize))
|
if (CGSizeEqualToSize(_maxItemSize, aSize))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_maxItemSize = CGSizeMakeCopy(aSize);
|
_maxItemSize = CGSizeMakeCopy(aSize);
|
||||||
|
|
||||||
[self tile];
|
[self tile];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -593,51 +582,14 @@
|
|||||||
index = row * _numberOfColumns + column;
|
index = row * _numberOfColumns + column;
|
||||||
|
|
||||||
if (index >= 0 && index < _items.length)
|
if (index >= 0 && index < _items.length)
|
||||||
{
|
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
|
||||||
if (_allowsMultipleSelection && ([anEvent modifierFlags] & CPCommandKeyMask || [anEvent modifierFlags] & CPShiftKeyMask))
|
|
||||||
{
|
|
||||||
if ([anEvent modifierFlags] & CPCommandKeyMask)
|
|
||||||
{
|
|
||||||
var indexes = [_selectionIndexes copy];
|
|
||||||
|
|
||||||
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)
|
else if (_allowsEmptySelection)
|
||||||
[self setSelectionIndexes:[CPIndexSet indexSet]];
|
[self setSelectionIndexes:[CPIndexSet indexSet]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)mouseDragged:(CPEvent)anEvent
|
- (void)mouseDragged:(CPEvent)anEvent
|
||||||
{
|
{
|
||||||
var locationInWindow = [anEvent locationInWindow],
|
|
||||||
mouseDownLocationInWindow = [_mouseDownEvent locationInWindow];
|
|
||||||
|
|
||||||
// FIXME: This is because Safari's drag hysteresis is 3px x 3px
|
|
||||||
if ((ABS(locationInWindow.x - mouseDownLocationInWindow.x) < 3) &&
|
|
||||||
(ABS(locationInWindow.y - mouseDownLocationInWindow.y) < 3))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (![_delegate respondsToSelector:@selector(collectionView:dragTypesForItemsAtIndexes:)])
|
if (![_delegate respondsToSelector:@selector(collectionView:dragTypesForItemsAtIndexes:)])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -654,6 +606,8 @@
|
|||||||
|
|
||||||
[[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:dragTypes owner:self];
|
[[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:dragTypes owner:self];
|
||||||
|
|
||||||
|
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
||||||
|
|
||||||
if (!_itemForDragging)
|
if (!_itemForDragging)
|
||||||
_itemForDragging = [self newItemForRepresentedObject:_content[[_selectionIndexes firstIndex]]];
|
_itemForDragging = [self newItemForRepresentedObject:_content[[_selectionIndexes firstIndex]]];
|
||||||
else
|
else
|
||||||
@@ -694,9 +648,9 @@
|
|||||||
{
|
{
|
||||||
if (_verticalMargin == aVerticalMargin)
|
if (_verticalMargin == aVerticalMargin)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_verticalMargin = aVerticalMargin;
|
_verticalMargin = aVerticalMargin;
|
||||||
|
|
||||||
[self tile];
|
[self tile];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -747,7 +701,7 @@
|
|||||||
count = [indexArray count];
|
count = [indexArray count];
|
||||||
|
|
||||||
for (; index < count; ++index)
|
for (; index < count; ++index)
|
||||||
frame = CGRectUnion(frame, [self frameForItemAtIndex:indexArray[index]]);
|
frame = CGRectUnion(frame, [self rectForItemAtIndex:indexArray[index]]);
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
@@ -756,29 +710,6 @@
|
|||||||
|
|
||||||
@implementation CPCollectionView (KeyboardInteraction)
|
@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
|
- (void)_scrollToSelection
|
||||||
{
|
{
|
||||||
var frame = [self frameForItemsAtIndexes:[self selectionIndexes]];
|
var frame = [self frameForItemsAtIndexes:[self selectionIndexes]];
|
||||||
@@ -790,57 +721,41 @@
|
|||||||
- (void)moveLeft:(id)sender
|
- (void)moveLeft:(id)sender
|
||||||
{
|
{
|
||||||
var index = [[self selectionIndexes] firstIndex];
|
var index = [[self selectionIndexes] firstIndex];
|
||||||
if (index === CPNotFound)
|
if (index === CPNotFound)
|
||||||
index = [[self items] count];
|
index = [[self items] count];
|
||||||
|
|
||||||
[self _modifySelectionWithNewIndex:index - 1 direction:-1 expand:NO];
|
index = MAX(index - 1, 0);
|
||||||
}
|
|
||||||
|
|
||||||
- (void)moveLeftAndModifySelection:(id)sender
|
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
|
||||||
{
|
[self _scrollToSelection];
|
||||||
var index = [[self selectionIndexes] firstIndex];
|
|
||||||
if (index === CPNotFound)
|
|
||||||
index = [[self items] count];
|
|
||||||
|
|
||||||
[self _modifySelectionWithNewIndex:index - 1 direction:-1 expand:YES];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)moveRight:(id)sender
|
- (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 setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
|
||||||
{
|
[self _scrollToSelection];
|
||||||
[self _modifySelectionWithNewIndex:[[self selectionIndexes] lastIndex] + 1 direction:1 expand:YES];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)moveDown:(id)sender
|
- (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 setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
|
||||||
{
|
[self _scrollToSelection];
|
||||||
[self _modifySelectionWithNewIndex:[[self selectionIndexes] lastIndex] + [self numberOfColumns] direction:1 expand:YES];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)moveUp:(id)sender
|
- (void)moveUp:(id)sender
|
||||||
{
|
{
|
||||||
var index = [[self selectionIndexes] firstIndex];
|
var index = [[self selectionIndexes] firstIndex];
|
||||||
if (index == CPNotFound)
|
if (index == CPNotFound)
|
||||||
index = [[self items] count];
|
index = [[self items] count];
|
||||||
|
|
||||||
[self _modifySelectionWithNewIndex:index - [self numberOfColumns] direction:-1 expand:NO];
|
index = MAX(0, index - [self numberOfColumns]);
|
||||||
}
|
|
||||||
|
|
||||||
- (void)moveUpAndModifySelection:(id)sender
|
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
|
||||||
{
|
[self _scrollToSelection];
|
||||||
var index = [[self selectionIndexes] firstIndex];
|
|
||||||
if (index == CPNotFound)
|
|
||||||
index = [[self items] count];
|
|
||||||
|
|
||||||
[self _modifySelectionWithNewIndex:index - [self numberOfColumns] direction:-1 expand:YES];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)deleteBackward:(id)sender
|
- (void)deleteBackward:(id)sender
|
||||||
@@ -850,8 +765,8 @@
|
|||||||
[[self delegate] collectionView:self shouldDeleteItemsAtIndexes:[self selectionIndexes]];
|
[[self delegate] collectionView:self shouldDeleteItemsAtIndexes:[self selectionIndexes]];
|
||||||
|
|
||||||
var index = [[self selectionIndexes] firstIndex];
|
var index = [[self selectionIndexes] firstIndex];
|
||||||
if (index > [[self content] count] - 1)
|
if (index > [[self content] count]-1)
|
||||||
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:[[self content] count] - 1]];
|
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:[[self content] count]-1]];
|
||||||
|
|
||||||
[self _scrollToSelection];
|
[self _scrollToSelection];
|
||||||
[self setNeedsDisplay:YES];
|
[self setNeedsDisplay:YES];
|
||||||
@@ -885,14 +800,11 @@
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeKey",
|
var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeKey",
|
||||||
CPCollectionViewMaxItemSizeKey = @"CPCollectionViewMaxItemSizeKey",
|
CPCollectionViewMaxItemSizeKey = @"CPCollectionViewMaxItemSizeKey",
|
||||||
CPCollectionViewVerticalMarginKey = @"CPCollectionViewVerticalMarginKey",
|
CPCollectionViewVerticalMarginKey = @"CPCollectionViewVerticalMarginKey",
|
||||||
CPCollectionViewMaxNumberOfRowsKey = @"CPCollectionViewMaxNumberOfRowsKey",
|
CPCollectionViewSelectableKey = @"CPCollectionViewSelectableKey",
|
||||||
CPCollectionViewMaxNumberOfColumnsKey = @"CPCollectionViewMaxNumberOfColumnsKey",
|
CPCollectionViewBackgroundColorsKey = @"CPCollectionViewBackgroundColorsKey";
|
||||||
CPCollectionViewSelectableKey = @"CPCollectionViewSelectableKey",
|
|
||||||
CPCollectionViewAllowsMultipleSelectionKey = @"CPCollectionViewAllowsMultipleSelectionKey",
|
|
||||||
CPCollectionViewBackgroundColorsKey = @"CPCollectionViewBackgroundColorsKey";
|
|
||||||
|
|
||||||
|
|
||||||
@implementation CPCollectionView (CPCoding)
|
@implementation CPCollectionView (CPCoding)
|
||||||
@@ -909,24 +821,20 @@ var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeK
|
|||||||
_cachedItems = [];
|
_cachedItems = [];
|
||||||
|
|
||||||
_itemSize = CGSizeMakeZero();
|
_itemSize = CGSizeMakeZero();
|
||||||
|
|
||||||
_minItemSize = [aCoder decodeSizeForKey:CPCollectionViewMinItemSizeKey] || CGSizeMakeZero();
|
_minItemSize = [aCoder decodeSizeForKey:CPCollectionViewMinItemSizeKey] || CGSizeMakeZero();
|
||||||
_maxItemSize = [aCoder decodeSizeForKey:CPCollectionViewMaxItemSizeKey] || CGSizeMakeZero();
|
_maxItemSize = [aCoder decodeSizeForKey:CPCollectionViewMaxItemSizeKey] || CGSizeMakeZero();
|
||||||
|
|
||||||
_maxNumberOfRows = [aCoder decodeIntForKey:CPCollectionViewMaxNumberOfRowsKey] || 0;
|
|
||||||
_maxNumberOfColumns = [aCoder decodeIntForKey:CPCollectionViewMaxNumberOfColumnsKey] || 0;
|
|
||||||
|
|
||||||
_verticalMargin = [aCoder decodeFloatForKey:CPCollectionViewVerticalMarginKey];
|
_verticalMargin = [aCoder decodeFloatForKey:CPCollectionViewVerticalMarginKey];
|
||||||
|
|
||||||
_isSelectable = [aCoder decodeBoolForKey:CPCollectionViewSelectableKey];
|
_isSelectable = [aCoder decodeBoolForKey:CPCollectionViewSelectableKey];
|
||||||
_allowsMultipleSelection = [aCoder decodeBoolForKey:CPCollectionViewAllowsMultipleSelectionKey];
|
|
||||||
|
|
||||||
[self setBackgroundColors:[aCoder decodeObjectForKey:CPCollectionViewBackgroundColorsKey]];
|
[self setBackgroundColors:[aCoder decodeObjectForKey:CPCollectionViewBackgroundColorsKey]];
|
||||||
|
|
||||||
_tileWidth = -1.0;
|
_tileWidth = -1.0;
|
||||||
|
|
||||||
_selectionIndexes = [CPIndexSet indexSet];
|
_selectionIndexes = [CPIndexSet indexSet];
|
||||||
|
|
||||||
_allowsEmptySelection = YES;
|
_allowsEmptySelection = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -939,16 +847,12 @@ var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeK
|
|||||||
|
|
||||||
if (!CGSizeEqualToSize(_minItemSize, CGSizeMakeZero()))
|
if (!CGSizeEqualToSize(_minItemSize, CGSizeMakeZero()))
|
||||||
[aCoder encodeSize:_minItemSize forKey:CPCollectionViewMinItemSizeKey];
|
[aCoder encodeSize:_minItemSize forKey:CPCollectionViewMinItemSizeKey];
|
||||||
|
|
||||||
if (!CGSizeEqualToSize(_maxItemSize, CGSizeMakeZero()))
|
if (!CGSizeEqualToSize(_maxItemSize, CGSizeMakeZero()))
|
||||||
[aCoder encodeSize:_maxItemSize forKey:CPCollectionViewMaxItemSizeKey];
|
[aCoder encodeSize:_maxItemSize forKey:CPCollectionViewMaxItemSizeKey];
|
||||||
|
|
||||||
[aCoder encodeInt:_maxNumberOfRows forKey:CPCollectionViewMaxNumberOfRowsKey];
|
|
||||||
[aCoder encodeInt:_maxNumberOfColumns forKey:CPCollectionViewMaxNumberOfColumnsKey];
|
|
||||||
|
|
||||||
[aCoder encodeBool:_isSelectable forKey:CPCollectionViewSelectableKey];
|
[aCoder encodeBool:_isSelectable forKey:CPCollectionViewSelectableKey];
|
||||||
[aCoder encodeBool:_allowsMultipleSelection forKey:CPCollectionViewAllowsMultipleSelectionKey];
|
|
||||||
|
|
||||||
[aCoder encodeFloat:_verticalMargin forKey:CPCollectionViewVerticalMarginKey];
|
[aCoder encodeFloat:_verticalMargin forKey:CPCollectionViewVerticalMarginKey];
|
||||||
|
|
||||||
[aCoder encodeObject:_backgroundColors forKey:CPCollectionViewBackgroundColorsKey];
|
[aCoder encodeObject:_backgroundColors forKey:CPCollectionViewBackgroundColorsKey];
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
@import "CPViewController.j"
|
@import "CPViewController.j"
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Represents an object inside a CPCollectionView.
|
Represents an object inside a CPCollectionView.
|
||||||
*/
|
*/
|
||||||
|
|||||||
+91
-87
@@ -32,7 +32,7 @@ var _redComponent = 0,
|
|||||||
_greenComponent = 1,
|
_greenComponent = 1,
|
||||||
_blueComponent = 2,
|
_blueComponent = 2,
|
||||||
_alphaCompnent = 3;
|
_alphaCompnent = 3;
|
||||||
|
|
||||||
var _hueComponent = 0,
|
var _hueComponent = 0,
|
||||||
_saturationComponent = 1,
|
_saturationComponent = 1,
|
||||||
_brightnessComponent = 2;
|
_brightnessComponent = 2;
|
||||||
@@ -54,21 +54,27 @@ var cachedBlackColor,
|
|||||||
cachedShadowColor,
|
cachedShadowColor,
|
||||||
cachedClearColor;
|
cachedClearColor;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
|
@code CPColor
|
||||||
|
|
||||||
\c CPColor can be used to represent color
|
\c CPColor can be used to represent color
|
||||||
in an RGB or HSB model with an optional transparency value.</p>
|
in an RGB or HSB model with an optional transparency value.</p>
|
||||||
|
|
||||||
<p>It also provides some class helper methods that
|
<p>It also provides some class helper methods that
|
||||||
returns instances of commonly used colors.</p>
|
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
|
@implementation CPColor : CPObject
|
||||||
{
|
{
|
||||||
CPArray _components;
|
CPArray _components;
|
||||||
|
|
||||||
CPImage _patternImage;
|
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
|
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
|
the alpha component, a value of 1.0 is opaque, and 0.0 means
|
||||||
completely transparent.
|
completely transparent.
|
||||||
|
|
||||||
@param red the red component of the color
|
@param red the red component of the color
|
||||||
@param green the green component of the color
|
@param green the green component of the color
|
||||||
@param blue the blue component of the color
|
@param blue the blue component of the color
|
||||||
@param alpha the alpha component
|
@param alpha the alpha component
|
||||||
|
|
||||||
@return a color initialized to the values specified
|
@return a color initialized to the values specified
|
||||||
*/
|
*/
|
||||||
+ (CPColor)colorWithRed:(float)red green:(float)green blue:(float)blue alpha:(float)alpha
|
+ (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:
|
@deprecated in favor of colorWithRed:green:blue:alpha:
|
||||||
|
|
||||||
Creates a color in the RGB color space, with an alpha value.
|
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
|
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
|
the alpha component, a value of 1.0 is opaque, and 0.0 means
|
||||||
completely transparent.
|
completely transparent.
|
||||||
|
|
||||||
@param red the red component of the color
|
@param red the red component of the color
|
||||||
@param green the green component of the color
|
@param green the green component of the color
|
||||||
@param blue the blue component of the color
|
@param blue the blue component of the color
|
||||||
@param alpha the alpha component
|
@param alpha the alpha component
|
||||||
|
|
||||||
@return a color initialized to the values specified
|
@return a color initialized to the values specified
|
||||||
*/
|
*/
|
||||||
+ (CPColor)colorWithCalibratedRed:(float)red green:(float)green blue:(float)blue alpha:(float)alpha
|
+ (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.
|
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.
|
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 white a float between 0.0 and 1.0
|
||||||
@param alpha the alpha component 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
|
@return a color initialized to the values specified
|
||||||
*/
|
*/
|
||||||
+ (CPColor)colorWithWhite:(float)white alpha:(float)alpha
|
+ (CPColor)colorWithWhite:(float)white alpha:(float)alpha
|
||||||
@@ -126,13 +132,13 @@ var cachedBlackColor,
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
@deprecated in favor of colorWithWhite:apha:
|
@deprecated in favor of colorWithWhite:apha:
|
||||||
|
|
||||||
Creates a new color object with \c white for the RGB components.
|
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.
|
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 white a float between 0.0 and 1.0
|
||||||
@param alpha the alpha component 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
|
@return a color initialized to the values specified
|
||||||
*/
|
*/
|
||||||
+ (CPColor)colorWithCalibratedWhite:(float)white alpha:(float)alpha
|
+ (CPColor)colorWithCalibratedWhite:(float)white alpha:(float)alpha
|
||||||
@@ -142,11 +148,11 @@ var cachedBlackColor,
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
Creates a new color in HSB space.
|
Creates a new color in HSB space.
|
||||||
|
|
||||||
@param hue the hue value
|
@param hue the hue value
|
||||||
@param saturation the saturation value
|
@param saturation the saturation value
|
||||||
@param brightness the brightness value
|
@param brightness the brightness value
|
||||||
|
|
||||||
@return the initialized color
|
@return the initialized color
|
||||||
*/
|
*/
|
||||||
+ (CPColor)colorWithHue:(float)hue saturation:(float)saturation brightness:(float)brightness
|
+ (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
|
+ (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];
|
return [CPColor colorWithCalibratedWhite:brightness / 100.0 alpha:alpha];
|
||||||
|
|
||||||
var f = hue % 60,
|
var f = hue % 60,
|
||||||
p = (brightness * (100 - saturation)) / 10000,
|
p = (brightness * (100 - saturation)) / 10000,
|
||||||
q = (brightness * (6000 - saturation * f)) / 600000,
|
q = (brightness * (6000 - saturation * f)) / 600000,
|
||||||
t = (brightness * (6000 - saturation * (60 -f))) / 600000,
|
t = (brightness * (6000 - saturation * (60 -f))) / 600000,
|
||||||
b = brightness / 100.0;
|
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 0: return [CPColor colorWithCalibratedRed: b green: t blue: p alpha: alpha];
|
||||||
case 1: return [CPColor colorWithCalibratedRed: q green: b 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,
|
Creates an RGB color from a hexadecimal string. For example,
|
||||||
the a string of "FFFFFF" would return a white CPColor.
|
the a string of "FFFFFF" would return a white CPColor.
|
||||||
"FF0000" would return a pure red, "00FF00" would return a
|
"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
|
@param hex a 6 character long string of hex
|
||||||
|
|
||||||
@@ -188,8 +194,7 @@ var cachedBlackColor,
|
|||||||
*/
|
*/
|
||||||
+ (CPColor)colorWithHexString:(string)hex
|
+ (CPColor)colorWithHexString:(string)hex
|
||||||
{
|
{
|
||||||
var rgba = hexToRGB(hex);
|
return [[CPColor alloc] _initWithRGBA: hexToRGB(hex)];
|
||||||
return rgba ? [[CPColor alloc] _initWithRGBA: rgba] : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -392,7 +397,7 @@ var cachedBlackColor,
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
Creates a CPColor from a valid CSS RGB string. Example, "rgb(32,64,129)".
|
Creates a CPColor from a valid CSS RGB string. Example, "rgb(32,64,129)".
|
||||||
|
|
||||||
@param aString a CSS color string
|
@param aString a CSS color string
|
||||||
@return a color initialized to the value in the css string
|
@return a color initialized to the value in the css string
|
||||||
*/
|
*/
|
||||||
@@ -404,23 +409,23 @@ var cachedBlackColor,
|
|||||||
/* @ignore */
|
/* @ignore */
|
||||||
- (id)_initWithCSSString:(CPString)aString
|
- (id)_initWithCSSString:(CPString)aString
|
||||||
{
|
{
|
||||||
if (aString.indexOf("rgb") == CPNotFound)
|
if(aString.indexOf("rgb") == CPNotFound)
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
var startingIndex = aString.indexOf("("),
|
var startingIndex = aString.indexOf("(");
|
||||||
parts = aString.substring(startingIndex + 1).split(',');
|
var parts = aString.substring(startingIndex+1).split(',');
|
||||||
|
|
||||||
_components = [
|
_components = [
|
||||||
parseInt(parts[0], 10) / 255.0,
|
parseInt(parts[0], 10) / 255.0,
|
||||||
parseInt(parts[1], 10) / 255.0,
|
parseInt(parts[1], 10) / 255.0,
|
||||||
parseInt(parts[2], 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;
|
_cssString = aString;
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,7 +433,7 @@ var cachedBlackColor,
|
|||||||
- (id)_initWithRGBA:(CPArray)components
|
- (id)_initWithRGBA:(CPArray)components
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_components = components;
|
_components = components;
|
||||||
@@ -449,14 +454,14 @@ var cachedBlackColor,
|
|||||||
- (id)_initWithPatternImage:(CPImage)anImage
|
- (id)_initWithPatternImage:(CPImage)anImage
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_patternImage = anImage;
|
_patternImage = anImage;
|
||||||
_cssString = "url(\"" + [_patternImage filename] + "\")";
|
_cssString = "url(\"" + [_patternImage filename] + "\")";
|
||||||
_components = [0.0, 0.0, 0.0, 1.0];
|
_components = [0.0, 0.0, 0.0, 1.0];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,17 +523,17 @@ var cachedBlackColor,
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns a new color with the same RGB as the receiver but a new alpha component.
|
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
|
@param anAlphaComponent the alpha component for the new color
|
||||||
|
|
||||||
@return a new color object
|
@return a new color object
|
||||||
*/
|
*/
|
||||||
- (CPColor)colorWithAlphaComponent:(float)anAlphaComponent
|
- (CPColor)colorWithAlphaComponent:(float)anAlphaComponent
|
||||||
{
|
{
|
||||||
var components = _components.slice();
|
var components = _components.slice();
|
||||||
|
|
||||||
components[components.length - 1] = anAlphaComponent;
|
components[components.length - 1] = anAlphaComponent;
|
||||||
|
|
||||||
return [[[self class] alloc] _initWithRGBA:components];
|
return [[[self class] alloc] _initWithRGBA:components];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -547,40 +552,37 @@ var cachedBlackColor,
|
|||||||
var red = ROUND(_components[_redComponent] * 255.0),
|
var red = ROUND(_components[_redComponent] * 255.0),
|
||||||
green = ROUND(_components[_greenComponent] * 255.0),
|
green = ROUND(_components[_greenComponent] * 255.0),
|
||||||
blue = ROUND(_components[_blueComponent] * 255.0);
|
blue = ROUND(_components[_blueComponent] * 255.0);
|
||||||
|
|
||||||
var max = MAX(red, green, blue),
|
var max = MAX(red, green, blue),
|
||||||
min = MIN(red, green, blue),
|
min = MIN(red, green, blue),
|
||||||
delta = max - min;
|
delta = max - min;
|
||||||
|
|
||||||
var brightness = max / 255.0,
|
var brightness = max / 255.0,
|
||||||
saturation = (max != 0) ? delta / max : 0;
|
saturation = (max != 0) ? delta / max : 0;
|
||||||
|
|
||||||
var hue;
|
var hue;
|
||||||
|
if(saturation == 0)
|
||||||
if (saturation == 0)
|
|
||||||
{
|
|
||||||
hue = 0;
|
hue = 0;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var rr = (max - red) / delta,
|
var rr = (max - red) / delta;
|
||||||
gr = (max - green) / delta,
|
var gr = (max - green) / delta;
|
||||||
br = (max - blue) / delta;
|
var br = (max - blue) / delta;
|
||||||
|
|
||||||
if (red == max)
|
if (red == max)
|
||||||
hue = br - gr;
|
hue = br - gr;
|
||||||
else if (green == max)
|
else if (green == max)
|
||||||
hue = 2 + rr - br;
|
hue = 2 + rr - br;
|
||||||
else
|
else
|
||||||
hue = 4 + gr - rr;
|
hue = 4 + gr - rr;
|
||||||
|
|
||||||
hue /= 6;
|
hue /= 6;
|
||||||
if (hue < 0)
|
if (hue < 0)
|
||||||
hue++;
|
hue++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
ROUND(hue * 360.0),
|
ROUND(hue * 360.0),
|
||||||
ROUND(saturation * 100.0),
|
ROUND(saturation * 100.0),
|
||||||
ROUND(brightness * 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)
|
@implementation CPColor (CoreGraphicsExtensions)
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Set's the receiver to be the fill and stroke color in the current graphics context
|
Set's the receiver to be the fill and stroke color in the current graphics context
|
||||||
*/
|
*/
|
||||||
- (void)set
|
- (void)set
|
||||||
@@ -637,16 +639,16 @@ url("data:image/png;base64,BASE64ENCODEDDATA") // if there is a pattern image
|
|||||||
[self setStroke];
|
[self setStroke];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Set's the receiver to be the fill color in the current graphics context
|
Set's the receiver to be the fill color in the current graphics context
|
||||||
*/
|
*/
|
||||||
- (void)setFill
|
- (void)setFill
|
||||||
{
|
{
|
||||||
var ctx = [[CPGraphicsContext currentContext] graphicsPort];
|
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
|
Set's the receiver to be the stroke color in the current graphics context
|
||||||
*/
|
*/
|
||||||
- (void)setStroke
|
- (void)setStroke
|
||||||
@@ -679,7 +681,7 @@ var CPColorComponentsKey = @"CPColorComponentsKey",
|
|||||||
{
|
{
|
||||||
if ([aCoder containsValueForKey:CPColorPatternImageKey])
|
if ([aCoder containsValueForKey:CPColorPatternImageKey])
|
||||||
return [self _initWithPatternImage:[aCoder decodeObjectForKey:CPColorPatternImageKey]];
|
return [self _initWithPatternImage:[aCoder decodeObjectForKey:CPColorPatternImageKey]];
|
||||||
|
|
||||||
return [self _initWithRGBA:[aCoder decodeObjectForKey:CPColorComponentsKey]];
|
return [self _initWithRGBA:[aCoder decodeObjectForKey:CPColorComponentsKey]];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -697,48 +699,50 @@ var CPColorComponentsKey = @"CPColorComponentsKey",
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
var hexCharacters = "0123456789ABCDEF";
|
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
|
Used for the CPColor \c +colorWithHexString: implementation
|
||||||
@ignore
|
@ignore
|
||||||
@class CPColor
|
@class CPColor
|
||||||
@return an array of rgb components
|
@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);
|
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;
|
return null;
|
||||||
|
|
||||||
hex = hex.toUpperCase();
|
hex = hex.toUpperCase();
|
||||||
|
|
||||||
for (var i = 0; i < hex.length; i++)
|
for(var i=0; i<hex.length; i++)
|
||||||
if (hexCharacters.indexOf(hex.charAt(i)) == -1)
|
if(hexCharacters.indexOf(hex.charAt(i)) == -1)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var red = (hexCharacters.indexOf(hex.charAt(0)) * 16 + hexCharacters.indexOf(hex.charAt(1))) / 255.0,
|
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,
|
var 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 blue = (hexCharacters.indexOf(hex.charAt(4)) * 16 + hexCharacters.indexOf(hex.charAt(5))) / 255.0;
|
||||||
|
|
||||||
return [red, green, blue, 1.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);
|
return byteToHex(r) + byteToHex(g) + byteToHex(b);
|
||||||
};
|
}
|
||||||
|
|
||||||
var byteToHex = function(n)
|
function byteToHex(n) {
|
||||||
{
|
if (!n || isNaN(n)) return "00";
|
||||||
if (!n || isNaN(n))
|
n = ROUND(MIN(255,MAX(0,256*n)));
|
||||||
return "00";
|
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) +
|
//http://dev.mootools.net/browser/trunk/Source/Utilities/Color.js?rev=1184
|
||||||
hexCharacters.charAt(n % 16);
|
|
||||||
};
|
|
||||||
|
|||||||
+80
-83
@@ -20,13 +20,11 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@import "CPApplication.j"
|
|
||||||
@import "CPButton.j"
|
@import "CPButton.j"
|
||||||
@import "CPCookie.j"
|
@import "CPCookie.j"
|
||||||
@import "CPPanel.j"
|
@import "CPPanel.j"
|
||||||
@import "CPView.j"
|
@import "CPView.j"
|
||||||
|
|
||||||
|
|
||||||
CPColorPanelColorDidChangeNotification = @"CPColorPanelColorDidChangeNotification";
|
CPColorPanelColorDidChangeNotification = @"CPColorPanelColorDidChangeNotification";
|
||||||
|
|
||||||
var PREVIEW_HEIGHT = 20.0,
|
var PREVIEW_HEIGHT = 20.0,
|
||||||
@@ -37,7 +35,7 @@ var PREVIEW_HEIGHT = 20.0,
|
|||||||
|
|
||||||
var SharedColorPanel = nil,
|
var SharedColorPanel = nil,
|
||||||
ColorPickerClasses = [];
|
ColorPickerClasses = [];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A color wheel
|
A color wheel
|
||||||
@global
|
@global
|
||||||
@@ -54,7 +52,7 @@ CPSliderColorPickerMode = 2;
|
|||||||
CPColorPickerViewWidth = 265,
|
CPColorPickerViewWidth = 265,
|
||||||
CPColorPickerViewHeight = 370;
|
CPColorPickerViewHeight = 370;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPColorPanel
|
@class CPColorPanel
|
||||||
|
|
||||||
@@ -63,7 +61,7 @@ CPColorPickerViewHeight = 370;
|
|||||||
obtain the panel, call the \c +sharedColorPanel method.
|
obtain the panel, call the \c +sharedColorPanel method.
|
||||||
*/
|
*/
|
||||||
@implementation CPColorPanel : CPPanel
|
@implementation CPColorPanel : CPPanel
|
||||||
{
|
{
|
||||||
_CPColorPanelToolbar _toolbar;
|
_CPColorPanelToolbar _toolbar;
|
||||||
_CPColorPanelSwatches _swatchView;
|
_CPColorPanelSwatches _swatchView;
|
||||||
_CPColorPanelPreview _previewView;
|
_CPColorPanelPreview _previewView;
|
||||||
@@ -82,8 +80,8 @@ CPColorPickerViewHeight = 370;
|
|||||||
int _mode;
|
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.
|
any picker in this list up to this point. In other words, call before creating a color panel.
|
||||||
*/
|
*/
|
||||||
+ (void)provideColorPickerClass:(Class)aColorPickerSubclass
|
+ (void)provideColorPickerClass:(Class)aColorPickerSubclass
|
||||||
@@ -98,7 +96,7 @@ CPColorPickerViewHeight = 370;
|
|||||||
{
|
{
|
||||||
if (!SharedColorPanel)
|
if (!SharedColorPanel)
|
||||||
SharedColorPanel = [[CPColorPanel alloc] init];
|
SharedColorPanel = [[CPColorPanel alloc] init];
|
||||||
|
|
||||||
return SharedColorPanel;
|
return SharedColorPanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +107,7 @@ CPColorPickerViewHeight = 370;
|
|||||||
+ (void)setPickerMode:(CPColorPanelMode)mode
|
+ (void)setPickerMode:(CPColorPanelMode)mode
|
||||||
{
|
{
|
||||||
var panel = [CPColorPanel sharedColorPanel];
|
var panel = [CPColorPanel sharedColorPanel];
|
||||||
[panel setMode:mode];
|
[panel setMode: mode];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -118,7 +116,7 @@ CPColorPickerViewHeight = 370;
|
|||||||
*/
|
*/
|
||||||
- (id)init
|
- (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)];
|
styleMask:(CPTitledWindowMask | CPClosableWindowMask | CPResizableWindowMask)];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
@@ -127,14 +125,14 @@ CPColorPickerViewHeight = 370;
|
|||||||
|
|
||||||
[self setTitle:@"Color Panel"];
|
[self setTitle:@"Color Panel"];
|
||||||
[self setLevel:CPFloatingWindowLevel];
|
[self setLevel:CPFloatingWindowLevel];
|
||||||
|
|
||||||
[self setFloatingPanel:YES];
|
[self setFloatingPanel:YES];
|
||||||
[self setBecomesKeyOnlyIfNeeded:YES];
|
[self setBecomesKeyOnlyIfNeeded:YES];
|
||||||
|
|
||||||
[self setMinSize:CGSizeMake(219.0, 342.0)];
|
[self setMinSize:CGSizeMake(219.0, 342.0)];
|
||||||
[self setMaxSize:CGSizeMake(323.0, 537.0)];
|
[self setMaxSize:CGSizeMake(323.0, 537.0)];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,12 +143,12 @@ CPColorPickerViewHeight = 370;
|
|||||||
{
|
{
|
||||||
_color = aColor;
|
_color = aColor;
|
||||||
[_previewView setBackgroundColor: _color];
|
[_previewView setBackgroundColor: _color];
|
||||||
|
|
||||||
[CPApp sendAction:@selector(changeColor:) to:nil from:self];
|
[CPApp sendAction:@selector(changeColor:) to:nil from:self];
|
||||||
|
|
||||||
if (_target && _action)
|
if (_target && _action)
|
||||||
[CPApp sendAction:_action to:_target from:self];
|
[CPApp sendAction:_action to:_target from:self];
|
||||||
|
|
||||||
[[CPNotificationCenter defaultCenter]
|
[[CPNotificationCenter defaultCenter]
|
||||||
postNotificationName:CPColorPanelColorDidChangeNotification
|
postNotificationName:CPColorPanelColorDidChangeNotification
|
||||||
object:self];
|
object:self];
|
||||||
@@ -167,7 +165,7 @@ CPColorPickerViewHeight = 370;
|
|||||||
- (void)setColor:(CPColor)aColor updatePicker:(BOOL)bool
|
- (void)setColor:(CPColor)aColor updatePicker:(BOOL)bool
|
||||||
{
|
{
|
||||||
[self setColor:aColor];
|
[self setColor:aColor];
|
||||||
|
|
||||||
if (bool)
|
if (bool)
|
||||||
[_activePicker setColor:_color];
|
[_activePicker setColor:_color];
|
||||||
}
|
}
|
||||||
@@ -234,30 +232,30 @@ CPColorPickerViewHeight = 370;
|
|||||||
{
|
{
|
||||||
var picker = _colorPickers[[sender tag]],
|
var picker = _colorPickers[[sender tag]],
|
||||||
view = [picker provideNewView:NO];
|
view = [picker provideNewView:NO];
|
||||||
|
|
||||||
if (!view)
|
if (!view)
|
||||||
view = [picker provideNewView:YES];
|
view = [picker provideNewView:YES];
|
||||||
|
|
||||||
if (view == _currentView)
|
if (view == _currentView)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_currentView)
|
if (_currentView)
|
||||||
[view setFrame:[_currentView frame]];
|
[view setFrame:[_currentView frame]];
|
||||||
else
|
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];
|
bounds = [[self contentView] bounds];
|
||||||
|
|
||||||
[view setFrameSize:CPSizeMake(bounds.size.width - 10, bounds.size.height - height)];
|
[view setFrameSize: CPSizeMake(bounds.size.width - 10, bounds.size.height - height)];
|
||||||
[view setFrameOrigin:CPPointMake(5, height)];
|
[view setFrameOrigin: CPPointMake(5, height)];
|
||||||
}
|
}
|
||||||
|
|
||||||
[_currentView removeFromSuperview];
|
[_currentView removeFromSuperview];
|
||||||
[[self contentView] addSubview:view];
|
[[self contentView] addSubview:view];
|
||||||
|
|
||||||
_currentView = view;
|
_currentView = view;
|
||||||
_activePicker = picker;
|
_activePicker = picker;
|
||||||
|
|
||||||
[picker setColor:[self color]];
|
[picker setColor:[self color]];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,7 +285,7 @@ CPColorPickerViewHeight = 370;
|
|||||||
_colorPickers = [];
|
_colorPickers = [];
|
||||||
|
|
||||||
var count = [ColorPickerClasses count];
|
var count = [ColorPickerClasses count];
|
||||||
for (var i = 0; i < count; i++)
|
for (var i=0; i<count; i++)
|
||||||
{
|
{
|
||||||
var currentPickerClass = ColorPickerClasses[i],
|
var currentPickerClass = ColorPickerClasses[i],
|
||||||
currentPicker = [[currentPickerClass alloc] initWithPickerMask:0 colorPanel:self];
|
currentPicker = [[currentPickerClass alloc] initWithPickerMask:0 colorPanel:self];
|
||||||
@@ -299,29 +297,29 @@ CPColorPickerViewHeight = 370;
|
|||||||
bounds = [contentView bounds];
|
bounds = [contentView bounds];
|
||||||
|
|
||||||
_toolbar = [[CPView alloc] initWithFrame:CGRectMake(0, 6, CGRectGetWidth(bounds), TOOLBAR_HEIGHT)];
|
_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,
|
var totalToolbarWidth = count * ICON_WIDTH + (count - 1) * ICON_PADDING,
|
||||||
leftOffset = (CGRectGetWidth(bounds) - totalToolbarWidth) / 2.0,
|
leftOffset = (CGRectGetWidth(bounds) - totalToolbarWidth) / 2.0,
|
||||||
buttonForLater = nil;
|
buttonForLater = nil;
|
||||||
|
|
||||||
for (var i = 0; i < count; i++)
|
for (var i=0; i<count; i++)
|
||||||
{
|
{
|
||||||
var image = [_colorPickers[i] provideNewButtonImage],
|
var image = [_colorPickers[i] provideNewButtonImage],
|
||||||
highlightImage = [_colorPickers[i] provideNewAlternateButtonImage],
|
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 setTag:i];
|
||||||
[button setTarget:self];
|
[button setTarget:self];
|
||||||
[button setAction:@selector(_setPicker:)];
|
[button setAction:@selector(_setPicker:)];
|
||||||
[button setBordered:NO];
|
[button setBordered:NO];
|
||||||
[button setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin];
|
[button setAutoresizingMask:CPViewMinXMargin|CPViewMaxXMargin];
|
||||||
|
|
||||||
[button setImage:image];
|
[button setImage:image];
|
||||||
[button setAlternateImage:highlightImage];
|
[button setAlternateImage:highlightImage];
|
||||||
|
|
||||||
[_toolbar addSubview:button];
|
[_toolbar addSubview:button];
|
||||||
|
|
||||||
if (!buttonForLater)
|
if (!buttonForLater)
|
||||||
buttonForLater = button;
|
buttonForLater = button;
|
||||||
}
|
}
|
||||||
@@ -332,7 +330,7 @@ CPColorPickerViewHeight = 370;
|
|||||||
_previewView = [[_CPColorPanelPreview alloc] initWithFrame:CGRectInset([previewBox bounds], 2.0, 2.0)];
|
_previewView = [[_CPColorPanelPreview alloc] initWithFrame:CGRectInset([previewBox bounds], 2.0, 2.0)];
|
||||||
|
|
||||||
[_previewView setColorPanel:self];
|
[_previewView setColorPanel:self];
|
||||||
[_previewView setAutoresizingMask:CPViewWidthSizable];
|
[_previewView setAutoresizingMask:CPViewWidthSizable];
|
||||||
|
|
||||||
[previewBox setBackgroundColor:[CPColor colorWithWhite:0.8 alpha:1.0]];
|
[previewBox setBackgroundColor:[CPColor colorWithWhite:0.8 alpha:1.0]];
|
||||||
[previewBox setAutoresizingMask:CPViewWidthSizable];
|
[previewBox setAutoresizingMask:CPViewWidthSizable];
|
||||||
@@ -340,7 +338,7 @@ CPColorPickerViewHeight = 370;
|
|||||||
[previewBox addSubview:_previewView];
|
[previewBox addSubview:_previewView];
|
||||||
|
|
||||||
var _previewLabel = [[CPTextField alloc] initWithFrame: CPRectMake(10, TOOLBAR_HEIGHT + 10, 60, 15)];
|
var _previewLabel = [[CPTextField alloc] initWithFrame: CPRectMake(10, TOOLBAR_HEIGHT + 10, 60, 15)];
|
||||||
[_previewLabel setStringValue:"Preview:"];
|
[_previewLabel setStringValue: "Preview:"];
|
||||||
[_previewLabel setTextColor:[CPColor blackColor]];
|
[_previewLabel setTextColor:[CPColor blackColor]];
|
||||||
[_previewLabel setAlignment:CPRightTextAlignment];
|
[_previewLabel setAlignment:CPRightTextAlignment];
|
||||||
|
|
||||||
@@ -352,8 +350,8 @@ CPColorPickerViewHeight = 370;
|
|||||||
|
|
||||||
_swatchView = [[_CPColorPanelSwatches alloc] initWithFrame:CGRectInset([swatchBox bounds], 1.0, 1.0)];
|
_swatchView = [[_CPColorPanelSwatches alloc] initWithFrame:CGRectInset([swatchBox bounds], 1.0, 1.0)];
|
||||||
|
|
||||||
[_swatchView setColorPanel:self];
|
[_swatchView setColorPanel: self];
|
||||||
[_swatchView setAutoresizingMask:CPViewWidthSizable];
|
[_swatchView setAutoresizingMask: CPViewWidthSizable];
|
||||||
|
|
||||||
[swatchBox addSubview:_swatchView];
|
[swatchBox addSubview:_swatchView];
|
||||||
|
|
||||||
@@ -369,7 +367,7 @@ CPColorPickerViewHeight = 370;
|
|||||||
[opacityLabel setAlignment:CPRightTextAlignment];
|
[opacityLabel setAlignment:CPRightTextAlignment];
|
||||||
|
|
||||||
_opacitySlider = [[CPSlider alloc] initWithFrame:CGRectMake(76, TOOLBAR_HEIGHT + PREVIEW_HEIGHT + 34, CGRectGetWidth(bounds) - 86, 20.0)];
|
_opacitySlider = [[CPSlider alloc] initWithFrame:CGRectMake(76, TOOLBAR_HEIGHT + PREVIEW_HEIGHT + 34, CGRectGetWidth(bounds) - 86, 20.0)];
|
||||||
|
|
||||||
[_opacitySlider setMinValue:0.0];
|
[_opacitySlider setMinValue:0.0];
|
||||||
[_opacitySlider setMaxValue:1.0];
|
[_opacitySlider setMaxValue:1.0];
|
||||||
|
|
||||||
@@ -417,37 +415,37 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
|
|||||||
CPCookie _swatchCookie;
|
CPCookie _swatchCookie;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithFrame:(CPRect)aFrame
|
-(id)initWithFrame:(CPRect)aFrame
|
||||||
{
|
{
|
||||||
self = [super initWithFrame:aFrame];
|
self = [super initWithFrame:aFrame];
|
||||||
|
|
||||||
[self setBackgroundColor: [CPColor grayColor]];
|
[self setBackgroundColor: [CPColor grayColor]];
|
||||||
|
|
||||||
[self registerForDraggedTypes:[CPArray arrayWithObjects:CPColorDragType]];
|
[self registerForDraggedTypes:[CPArray arrayWithObjects:CPColorDragType]];
|
||||||
|
|
||||||
var whiteColor = [CPColor whiteColor];
|
var whiteColor = [CPColor whiteColor];
|
||||||
|
|
||||||
_swatchCookie = [[CPCookie alloc] initWithName: CPColorPanelSwatchesCookie];
|
_swatchCookie = [[CPCookie alloc] initWithName: CPColorPanelSwatchesCookie];
|
||||||
var colorList = [self startingColorList];
|
var colorList = [self startingColorList];
|
||||||
|
|
||||||
_swatches = [];
|
_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
|
// 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)];
|
fillView = [[CPView alloc] initWithFrame:CGRectInset([view bounds], 1.0, 1.0)];
|
||||||
|
|
||||||
[view setBackgroundColor:whiteColor];
|
[view setBackgroundColor:whiteColor];
|
||||||
[fillView setBackgroundColor: (i < colorList.length) ? colorList[i] : whiteColor];
|
[fillView setBackgroundColor: (i < colorList.length) ? colorList[i] : whiteColor];
|
||||||
|
|
||||||
[view addSubview:fillView];
|
[view addSubview:fillView];
|
||||||
|
|
||||||
[self addSubview: view];
|
[self addSubview: view];
|
||||||
|
|
||||||
_swatches.push(view);
|
_swatches.push(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -459,8 +457,7 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
|
|||||||
- (CPArray)startingColorList
|
- (CPArray)startingColorList
|
||||||
{
|
{
|
||||||
var cookieValue = [_swatchCookie value];
|
var cookieValue = [_swatchCookie value];
|
||||||
|
if(cookieValue == "")
|
||||||
if (cookieValue == "")
|
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
[CPColor blackColor],
|
[CPColor blackColor],
|
||||||
@@ -474,11 +471,11 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
|
|||||||
[CPColor yellowColor]
|
[CPColor yellowColor]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
var cookieValue = eval(cookieValue),
|
var cookieValue = eval(cookieValue);
|
||||||
result = [];
|
var result = [];
|
||||||
|
|
||||||
for (var i = 0; i < cookieValue.length; i++)
|
for(var i=0; i<cookieValue.length; i++)
|
||||||
result.push([CPColor colorWithHexString: cookieValue[i]]);
|
result.push([CPColor colorWithHexString: cookieValue[i]]);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -488,12 +485,12 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
|
|||||||
{
|
{
|
||||||
var result = [];
|
var result = [];
|
||||||
// FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox
|
// 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]);
|
result.push([[[_swatches[i] subviews][0] backgroundColor] hexString]);
|
||||||
|
|
||||||
var future = new Date();
|
var future = new Date();
|
||||||
future.setYear(2019);
|
future.setYear(2019);
|
||||||
|
|
||||||
[_swatchCookie setValue: JSON.stringify(result) expires:future domain: nil];
|
[_swatchCookie setValue: JSON.stringify(result) expires:future domain: nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,8 +520,8 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
|
|||||||
{
|
{
|
||||||
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil],
|
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil],
|
||||||
bounds = [self bounds];
|
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;
|
return NO;
|
||||||
|
|
||||||
[_colorPanel setColor: [self colorAtIndex:FLOOR(point.x / 13)] updatePicker: YES];
|
[_colorPanel setColor: [self colorAtIndex:FLOOR(point.x / 13)] updatePicker: YES];
|
||||||
@@ -538,21 +535,21 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
|
|||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
[[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:[CPArray arrayWithObject:CPColorDragType] owner:self];
|
[[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:[CPArray arrayWithObject:CPColorDragType] owner:self];
|
||||||
|
|
||||||
var swatch = _swatches[FLOOR(point.x / 13)];
|
var swatch = _swatches[FLOOR(point.x / 13)];
|
||||||
|
|
||||||
// FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox
|
// FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox
|
||||||
_dragColor = [[swatch subviews][0] backgroundColor];
|
_dragColor = [[swatch subviews][0] backgroundColor];
|
||||||
|
|
||||||
var bounds = CPRectCreateCopy([swatch bounds]);
|
var bounds = CPRectCreateCopy([swatch bounds]);
|
||||||
|
|
||||||
// FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox
|
// 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)];
|
dragFillView = [[CPView alloc] initWithFrame:CGRectInset(bounds, 1.0, 1.0)];
|
||||||
|
|
||||||
[dragView setBackgroundColor:[CPColor blackColor]];
|
[dragView setBackgroundColor:[CPColor blackColor]];
|
||||||
[dragFillView setBackgroundColor:_dragColor];
|
[dragFillView setBackgroundColor:_dragColor];
|
||||||
|
|
||||||
[dragView addSubview:dragFillView];
|
[dragView addSubview:dragFillView];
|
||||||
|
|
||||||
[self dragView: dragView
|
[self dragView: dragView
|
||||||
@@ -566,19 +563,19 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
|
|||||||
|
|
||||||
- (void)pasteboard:(CPPasteboard)aPasteboard provideDataForType:(CPString)aType
|
- (void)pasteboard:(CPPasteboard)aPasteboard provideDataForType:(CPString)aType
|
||||||
{
|
{
|
||||||
if (aType == CPColorDragType)
|
if(aType == CPColorDragType)
|
||||||
[aPasteboard setData:[CPKeyedArchiver archivedDataWithRootObject:_dragColor] forType:aType];
|
[aPasteboard setData:[CPKeyedArchiver archivedDataWithRootObject:_dragColor] forType:aType];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)performDragOperation:(id <CPDraggingInfo>)aSender
|
- (void)performDragOperation:(id <CPDraggingInfo>)aSender
|
||||||
{
|
{
|
||||||
var location = [self convertPoint:[aSender draggingLocation] fromView:nil],
|
var location = [self convertPoint:[aSender draggingLocation] fromView:nil],
|
||||||
pasteboard = [aSender draggingPasteboard],
|
pasteboard = [aSender draggingPasteboard],
|
||||||
swatch = nil;
|
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;
|
return NO;
|
||||||
|
|
||||||
[self setColor:[CPKeyedUnarchiver unarchiveObjectWithData:[pasteboard dataForType:CPColorDragType]] atIndex: FLOOR(location.x / 13)];
|
[self setColor:[CPKeyedUnarchiver unarchiveObjectWithData:[pasteboard dataForType:CPColorDragType]] atIndex: FLOOR(location.x / 13)];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -593,9 +590,9 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
|
|||||||
- (id)initWithFrame:(CPRect)aFrame
|
- (id)initWithFrame:(CPRect)aFrame
|
||||||
{
|
{
|
||||||
self = [super initWithFrame:aFrame];
|
self = [super initWithFrame:aFrame];
|
||||||
|
|
||||||
[self registerForDraggedTypes:[CPArray arrayWithObjects:CPColorDragType]];
|
[self registerForDraggedTypes:[CPArray arrayWithObjects:CPColorDragType]];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,9 +610,9 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
|
|||||||
{
|
{
|
||||||
var pasteboard = [aSender draggingPasteboard];
|
var pasteboard = [aSender draggingPasteboard];
|
||||||
|
|
||||||
if (![pasteboard availableTypeFromArray:[CPColorDragType]])
|
if(![pasteboard availableTypeFromArray:[CPColorDragType]])
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
var color = [CPKeyedUnarchiver unarchiveObjectWithData:[pasteboard dataForType:CPColorDragType]];
|
var color = [CPKeyedUnarchiver unarchiveObjectWithData:[pasteboard dataForType:CPColorDragType]];
|
||||||
[_colorPanel setColor:color updatePicker:YES];
|
[_colorPanel setColor:color updatePicker:YES];
|
||||||
}
|
}
|
||||||
@@ -629,19 +626,19 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
|
|||||||
{
|
{
|
||||||
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
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);
|
var bounds = CPRectMake(0, 0, 15, 15);
|
||||||
|
|
||||||
// FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox
|
// 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)];
|
dragFillView = [[CPView alloc] initWithFrame:CGRectInset(bounds, 1.0, 1.0)];
|
||||||
|
|
||||||
[dragView setBackgroundColor:[CPColor blackColor]];
|
[dragView setBackgroundColor:[CPColor blackColor]];
|
||||||
[dragFillView setBackgroundColor:[self backgroundColor]];
|
[dragFillView setBackgroundColor:[self backgroundColor]];
|
||||||
|
|
||||||
[dragView addSubview:dragFillView];
|
[dragView addSubview:dragFillView];
|
||||||
|
|
||||||
[self dragView: dragView
|
[self dragView: dragView
|
||||||
at: CPPointMake(point.x - bounds.size.width / 2.0, point.y - bounds.size.height / 2.0)
|
at: CPPointMake(point.x - bounds.size.width / 2.0, point.y - bounds.size.height / 2.0)
|
||||||
offset: CPPointMake(0.0, 0.0)
|
offset: CPPointMake(0.0, 0.0)
|
||||||
@@ -653,7 +650,7 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
|
|||||||
|
|
||||||
- (void)pasteboard:(CPPasteboard)aPasteboard provideDataForType:(CPString)aType
|
- (void)pasteboard:(CPPasteboard)aPasteboard provideDataForType:(CPString)aType
|
||||||
{
|
{
|
||||||
if (aType == CPColorDragType)
|
if(aType == CPColorDragType)
|
||||||
[aPasteboard setData:[CPKeyedArchiver archivedDataWithRootObject:[self backgroundColor]] forType:aType];
|
[aPasteboard setData:[CPKeyedArchiver archivedDataWithRootObject:[self backgroundColor]] forType:aType];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+39
-36
@@ -21,11 +21,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
@import <Foundation/CPObject.j>
|
@import <Foundation/CPObject.j>
|
||||||
|
@import "CPColorPanel.j"
|
||||||
|
|
||||||
@import "CPView.j"
|
#include "Platform/Platform.h"
|
||||||
|
|
||||||
|
/*!
|
||||||
/*!
|
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPColorPicker
|
@class CPColorPicker
|
||||||
|
|
||||||
@@ -102,18 +102,18 @@
|
|||||||
|
|
||||||
CPColor _cachedColor;
|
CPColor _cachedColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithPickerMask:(int)mask colorPanel:(CPColorPanel)owningColorPanel
|
- (id)initWithPickerMask:(int)mask colorPanel:(CPColorPanel)owningColorPanel
|
||||||
{
|
{
|
||||||
return [super initWithPickerMask:mask colorPanel: owningColorPanel];
|
return [super initWithPickerMask:mask colorPanel: owningColorPanel];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initView
|
-(id)initView
|
||||||
{
|
{
|
||||||
aFrame = CPRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight);
|
aFrame = CPRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight);
|
||||||
|
|
||||||
_pickerView = [[CPView alloc] initWithFrame:aFrame];
|
_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)];
|
_brightnessSlider = [[CPSlider alloc] initWithFrame:CGRectMake(0, (aFrame.size.height - 34), aFrame.size.width, 15)];
|
||||||
|
|
||||||
@@ -136,17 +136,17 @@
|
|||||||
[_pickerView addSubview:_brightnessSlider];
|
[_pickerView addSubview:_brightnessSlider];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)brightnessSliderDidChange:(id)sender
|
-(void)brightnessSliderDidChange:(id)sender
|
||||||
{
|
{
|
||||||
[self updateColor];
|
[self updateColor];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)colorWheelDidChange:(id)sender
|
-(void)colorWheelDidChange:(id)sender
|
||||||
{
|
{
|
||||||
[self updateColor];
|
[self updateColor];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateColor
|
-(void)updateColor
|
||||||
{
|
{
|
||||||
var hue = [_hueSaturationView angle],
|
var hue = [_hueSaturationView angle],
|
||||||
saturation = [_hueSaturationView distance],
|
saturation = [_hueSaturationView distance],
|
||||||
@@ -223,7 +223,7 @@
|
|||||||
float _radius;
|
float _radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithFrame:(CPRect)aFrame
|
-(id)initWithFrame:(CPRect)aFrame
|
||||||
{
|
{
|
||||||
self = [super initWithFrame:aFrame];
|
self = [super initWithFrame:aFrame];
|
||||||
|
|
||||||
@@ -261,19 +261,19 @@
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setWheelBrightness:(float)brightness
|
-(void)setWheelBrightness:(float)brightness
|
||||||
{
|
{
|
||||||
_blackWheelImage.style.opacity = 1.0 - 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];
|
[super setFrameSize:aSize];
|
||||||
[self setWheelSize:aSize];
|
[self setWheelSize:aSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setWheelSize:(CPSize)aSize
|
-(void)setWheelSize:(CPSize)aSize
|
||||||
{
|
{
|
||||||
var min = MIN(aSize.width, aSize.height);
|
var min = MIN(aSize.width, aSize.height);
|
||||||
|
|
||||||
@@ -296,55 +296,57 @@
|
|||||||
[self setAngle:[self degreesToRadians:_angle] distance:(_distance / 100.0) * _radius];
|
[self setAngle:[self degreesToRadians:_angle] distance:(_distance / 100.0) * _radius];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setDelegate:(id)aDelegate
|
-(void)setDelegate:(id)aDelegate
|
||||||
{
|
{
|
||||||
_delegate = aDelegate;
|
_delegate = aDelegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)delegate
|
-(id)delegate
|
||||||
{
|
{
|
||||||
return _delegate;
|
return _delegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (float)angle
|
-(float)angle
|
||||||
{
|
{
|
||||||
return _angle;
|
return _angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (float)distance
|
-(float)distance
|
||||||
{
|
{
|
||||||
return _distance;
|
return _distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)mouseDown:(CPEvent)anEvent
|
-(void)mouseDown:(CPEvent)anEvent
|
||||||
{
|
{
|
||||||
[self reposition:anEvent];
|
[self reposition:anEvent];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)mouseDragged:(CPEvent)anEvent
|
-(void)mouseDragged:(CPEvent)anEvent
|
||||||
{
|
{
|
||||||
[self reposition:anEvent];
|
[self reposition:anEvent];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)reposition:(CPEvent)anEvent
|
-(void)reposition:(CPEvent)anEvent
|
||||||
{
|
{
|
||||||
var bounds = [self bounds],
|
var bounds = [self bounds],
|
||||||
location = [self convertPoint:[anEvent locationInWindow] fromView:nil],
|
location = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
||||||
midX = CGRectGetMidX(bounds),
|
|
||||||
midY = CGRectGetMidY(bounds),
|
var midX = CGRectGetMidX(bounds);
|
||||||
distance = MIN(SQRT((location.x - midX) * (location.x - midX) + (location.y - midY) * (location.y - midY)), _radius),
|
var midY = CGRectGetMidY(bounds);
|
||||||
angle = ATAN2(location.y - midY, location.x - midX);
|
|
||||||
|
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];
|
[self setAngle:angle distance:distance];
|
||||||
|
|
||||||
[_delegate colorWheelDidChange:self];
|
[_delegate colorWheelDidChange:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setAngle:(int)angle distance:(float)distance
|
-(void)setAngle:(int)angle distance:(float)distance
|
||||||
{
|
{
|
||||||
var bounds = [self bounds],
|
var bounds = [self bounds];
|
||||||
midX = CGRectGetMidX(bounds),
|
var midX = CGRectGetMidX(bounds);
|
||||||
midY = CGRectGetMidY(bounds);
|
var midY = CGRectGetMidY(bounds);
|
||||||
|
|
||||||
_angle = [self radiansToDegrees:angle];
|
_angle = [self radiansToDegrees:angle];
|
||||||
_distance = (distance / _radius) * 100.0;
|
_distance = (distance / _radius) * 100.0;
|
||||||
@@ -352,22 +354,23 @@
|
|||||||
[_crosshair setFrameOrigin:CPPointMake(COS(angle) * distance + midX - 2.0, SIN(angle) * distance + midY - 2.0)];
|
[_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],
|
var hsb = [aColor hsbComponents],
|
||||||
bounds = [self bounds],
|
bounds = [self bounds];
|
||||||
angle = [self degreesToRadians:hsb[0]],
|
|
||||||
|
var angle = [self degreesToRadians:hsb[0]],
|
||||||
distance = (hsb[1] / 100.0) * _radius;
|
distance = (hsb[1] / 100.0) * _radius;
|
||||||
|
|
||||||
[self setAngle:angle distance:distance];
|
[self setAngle:angle distance:distance];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int)radiansToDegrees:(float)radians
|
-(int)radiansToDegrees:(float)radians
|
||||||
{
|
{
|
||||||
return ((-radians / PI) * 180 + 360) % 360;
|
return ((-radians / PI) * 180 + 360) % 360;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (float)degreesToRadians:(float)degrees
|
-(float)degreesToRadians:(float)degrees
|
||||||
{
|
{
|
||||||
return -(((degrees - 360) / 180) * PI);
|
return -(((degrees - 360) / 180) * PI);
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-36
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiveNotification";
|
var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiveNotification";
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPColorWell
|
@class CPColorWell
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
|
|||||||
{
|
{
|
||||||
BOOL _active;
|
BOOL _active;
|
||||||
BOOL _bordered;
|
BOOL _bordered;
|
||||||
|
|
||||||
CPColor _color;
|
CPColor _color;
|
||||||
CPView _wellView;
|
CPView _wellView;
|
||||||
}
|
}
|
||||||
@@ -49,19 +49,19 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
|
|||||||
- (id)initWithFrame:(CGRect)aFrame
|
- (id)initWithFrame:(CGRect)aFrame
|
||||||
{
|
{
|
||||||
self = [super initWithFrame:aFrame];
|
self = [super initWithFrame:aFrame];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_active = NO;
|
_active = NO;
|
||||||
_bordered = YES;
|
_bordered = YES;
|
||||||
_color = [CPColor whiteColor];
|
_color = [CPColor whiteColor];
|
||||||
|
|
||||||
[self drawBezelWithHighlight:NO];
|
[self drawBezelWithHighlight:NO];
|
||||||
[self drawWellInside:CGRectInset([self bounds], 3.0, 3.0)];
|
[self drawWellInside:CGRectInset([self bounds], 3.0, 3.0)];
|
||||||
|
|
||||||
[self _registerForNotifications];
|
[self _registerForNotifications];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,9 +97,9 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
|
|||||||
{
|
{
|
||||||
if (_bordered == bordered)
|
if (_bordered == bordered)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_bordered = bordered;
|
_bordered = bordered;
|
||||||
|
|
||||||
[self drawWellInside:CGRectInset([self bounds], 3.0, 3.0)];
|
[self drawWellInside:CGRectInset([self bounds], 3.0, 3.0)];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,9 +120,9 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
|
|||||||
{
|
{
|
||||||
if (_color == aColor)
|
if (_color == aColor)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_color = aColor;
|
_color = aColor;
|
||||||
|
|
||||||
[self drawWellInside:CGRectInset([self bounds], 3.0, 3.0)];
|
[self drawWellInside:CGRectInset([self bounds], 3.0, 3.0)];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +137,7 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
|
|||||||
|
|
||||||
// Activating and Deactivating Color Wells
|
// 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.
|
If exclusive is \c YES, deactivates any other CPColorWells. \c NO, keeps them active.
|
||||||
@param shouldBeExclusive whether other color wells should be deactivated.
|
@param shouldBeExclusive whether other color wells should be deactivated.
|
||||||
*/
|
*/
|
||||||
@@ -152,9 +152,9 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
|
|||||||
|
|
||||||
if ([self isActive])
|
if ([self isActive])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_active = YES;
|
_active = YES;
|
||||||
|
|
||||||
[[CPNotificationCenter defaultCenter]
|
[[CPNotificationCenter defaultCenter]
|
||||||
addObserver:self
|
addObserver:self
|
||||||
selector:@selector(colorPanelDidChangeColor:)
|
selector:@selector(colorPanelDidChangeColor:)
|
||||||
@@ -169,9 +169,9 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
|
|||||||
{
|
{
|
||||||
if (![self isActive])
|
if (![self isActive])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_active = NO;
|
_active = NO;
|
||||||
|
|
||||||
[[CPNotificationCenter defaultCenter]
|
[[CPNotificationCenter defaultCenter]
|
||||||
removeObserver:self
|
removeObserver:self
|
||||||
name:CPColorPanelColorDidChangeNotification
|
name:CPColorPanelColorDidChangeNotification
|
||||||
@@ -202,19 +202,19 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
|
|||||||
{
|
{
|
||||||
_wellView = [[CPView alloc] initWithFrame:aRect];
|
_wellView = [[CPView alloc] initWithFrame:aRect];
|
||||||
[_wellView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
[_wellView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
||||||
|
|
||||||
[self addSubview:_wellView];
|
[self addSubview:_wellView];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
[_wellView setFrame:aRect];
|
[_wellView setFrame:aRect];
|
||||||
|
|
||||||
[_wellView setBackgroundColor:_color];
|
[_wellView setBackgroundColor:_color];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)colorPanelDidChangeColor:(CPNotification)aNotification
|
- (void)colorPanelDidChangeColor:(CPNotification)aNotification
|
||||||
{
|
{
|
||||||
[self takeColorFrom:[aNotification object]];
|
[self takeColorFrom:[aNotification object]];
|
||||||
|
|
||||||
[self sendAction:[self action] to:[self target]];
|
[self sendAction:[self action] to:[self target]];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,31 +231,25 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
|
|||||||
|
|
||||||
- (void)mouseDown:(CPEvent)anEvent
|
- (void)mouseDown:(CPEvent)anEvent
|
||||||
{
|
{
|
||||||
if (![self isEnabled])
|
|
||||||
return;
|
|
||||||
|
|
||||||
[self drawBezelWithHighlight:YES];
|
[self drawBezelWithHighlight:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)mouseDragged:(CPEvent)anEvent
|
- (void)mouseDragged:(CPEvent)anEvent
|
||||||
{
|
{
|
||||||
if (![self isEnabled])
|
|
||||||
return;
|
|
||||||
|
|
||||||
[self drawBezelWithHighlight:CGRectContainsPoint([self bounds], [self convertPoint:[anEvent locationInWindow] fromView:nil])];
|
[self drawBezelWithHighlight:CGRectContainsPoint([self bounds], [self convertPoint:[anEvent locationInWindow] fromView:nil])];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)mouseUp:(CPEvent)anEvent
|
-(void)mouseUp:(CPEvent)anEvent
|
||||||
{
|
{
|
||||||
[self drawBezelWithHighlight:NO];
|
[self drawBezelWithHighlight:NO];
|
||||||
|
|
||||||
if (!CGRectContainsPoint([self bounds], [self convertPoint:[anEvent locationInWindow] fromView:nil]) || ![self isEnabled])
|
if (!CGRectContainsPoint([self bounds], [self convertPoint:[anEvent locationInWindow] fromView:nil]))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[self activate:YES];
|
[self activate:YES];
|
||||||
|
|
||||||
var colorPanel = [CPColorPanel sharedColorPanel];
|
var colorPanel = [CPColorPanel sharedColorPanel];
|
||||||
|
|
||||||
[colorPanel setColor:_color];
|
[colorPanel setColor:_color];
|
||||||
[colorPanel orderFront:self];
|
[colorPanel orderFront:self];
|
||||||
}
|
}
|
||||||
@@ -274,11 +268,11 @@ var CPColorWellColorKey = "CPColorWellColorKey",
|
|||||||
- (id)initWithCoder:(CPCoder)aCoder
|
- (id)initWithCoder:(CPCoder)aCoder
|
||||||
{
|
{
|
||||||
self = [super initWithCoder:aCoder];
|
self = [super initWithCoder:aCoder];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_active = NO;
|
_active = NO;
|
||||||
_bordered = [aCoder decodeBoolForKey:CPColorWellBorderedKey];
|
_bordered = [aCoder decodeObjectForKey:CPColorWellBorderedKey];
|
||||||
_color = [aCoder decodeObjectForKey:CPColorWellColorKey];
|
_color = [aCoder decodeObjectForKey:CPColorWellColorKey];
|
||||||
|
|
||||||
[self drawBezelWithHighlight:NO];
|
[self drawBezelWithHighlight:NO];
|
||||||
@@ -286,7 +280,7 @@ var CPColorWellColorKey = "CPColorWellColorKey",
|
|||||||
|
|
||||||
[self _registerForNotifications];
|
[self _registerForNotifications];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,17 +290,17 @@ var CPColorWellColorKey = "CPColorWellColorKey",
|
|||||||
*/
|
*/
|
||||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
- (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.
|
// should just automatically be created programmatically as needed.
|
||||||
var actualSubviews = _subviews;
|
var actualSubviews = _subviews;
|
||||||
|
|
||||||
_subviews = [_subviews copy];
|
_subviews = [_subviews copy];
|
||||||
[_subviews removeObjectIdenticalTo:_wellView];
|
[_subviews removeObjectIdenticalTo:_wellView];
|
||||||
|
|
||||||
[super encodeWithCoder:aCoder];
|
[super encodeWithCoder:aCoder];
|
||||||
|
|
||||||
_subviews = actualSubviews;
|
_subviews = actualSubviews;
|
||||||
|
|
||||||
[aCoder encodeObject:_color forKey:CPColorWellColorKey];
|
[aCoder encodeObject:_color forKey:CPColorWellColorKey];
|
||||||
[aCoder encodeObject:_bordered forKey:CPColorWellBorderedKey];
|
[aCoder encodeObject:_bordered forKey:CPColorWellBorderedKey];
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-16
@@ -23,7 +23,6 @@
|
|||||||
@import "CPEvent.j"
|
@import "CPEvent.j"
|
||||||
@import "CPPlatform.j"
|
@import "CPPlatform.j"
|
||||||
|
|
||||||
|
|
||||||
// Browser Engines
|
// Browser Engines
|
||||||
CPUnknownBrowserEngine = 0;
|
CPUnknownBrowserEngine = 0;
|
||||||
CPGeckoBrowserEngine = 1;
|
CPGeckoBrowserEngine = 1;
|
||||||
@@ -78,23 +77,23 @@ if (typeof window !== "undefined" && typeof window.navigator !== "undefined")
|
|||||||
USER_AGENT = window.navigator.userAgent;
|
USER_AGENT = window.navigator.userAgent;
|
||||||
|
|
||||||
// Opera
|
// Opera
|
||||||
if (typeof window !== "undefined" && window.opera)
|
if (window.opera)
|
||||||
{
|
{
|
||||||
PLATFORM_ENGINE = CPOperaBrowserEngine;
|
PLATFORM_ENGINE = CPOperaBrowserEngine;
|
||||||
|
|
||||||
PLATFORM_FEATURES |= CPJavaScriptCanvasDrawFeature;
|
PLATFORM_FEATURES |= CPJavaScriptCanvasDrawFeature;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internet Explorer
|
// Internet Explorer
|
||||||
else if (typeof window !== "undefined" && window.attachEvent) // Must follow Opera check.
|
else if (window.attachEvent) // Must follow Opera check.
|
||||||
{
|
{
|
||||||
PLATFORM_ENGINE = CPInternetExplorerBrowserEngine;
|
PLATFORM_ENGINE = CPInternetExplorerBrowserEngine;
|
||||||
|
|
||||||
// Features we can only be sure of with IE (no known independent tests)
|
// Features we can only be sure of with IE (no known independent tests)
|
||||||
PLATFORM_FEATURES |= CPVMLFeature;
|
PLATFORM_FEATURES |= CPVMLFeature;
|
||||||
PLATFORM_FEATURES |= CPJavascriptRemedialKeySupport;
|
PLATFORM_FEATURES |= CPJavascriptRemedialKeySupport;
|
||||||
PLATFORM_FEATURES |= CPJavaScriptShadowFeature;
|
PLATFORM_FEATURES |= CPJavaScriptShadowFeature;
|
||||||
|
|
||||||
PLATFORM_FEATURES |= CPOpacityRequiresFilterFeature;
|
PLATFORM_FEATURES |= CPOpacityRequiresFilterFeature;
|
||||||
|
|
||||||
PLATFORM_FEATURES &= ~CPInputTypeCanBeChangedFeature;
|
PLATFORM_FEATURES &= ~CPInputTypeCanBeChangedFeature;
|
||||||
@@ -104,7 +103,7 @@ else if (typeof window !== "undefined" && window.attachEvent) // Must follow Ope
|
|||||||
else if (USER_AGENT.indexOf("AppleWebKit/") != -1)
|
else if (USER_AGENT.indexOf("AppleWebKit/") != -1)
|
||||||
{
|
{
|
||||||
PLATFORM_ENGINE = CPWebKitBrowserEngine;
|
PLATFORM_ENGINE = CPWebKitBrowserEngine;
|
||||||
|
|
||||||
// Features we can only be sure of with WebKit (no known independent tests)
|
// Features we can only be sure of with WebKit (no known independent tests)
|
||||||
PLATFORM_FEATURES |= CPCSSRGBAFeature;
|
PLATFORM_FEATURES |= CPCSSRGBAFeature;
|
||||||
PLATFORM_FEATURES |= CPHTMLContentEditableFeature;
|
PLATFORM_FEATURES |= CPHTMLContentEditableFeature;
|
||||||
@@ -115,7 +114,7 @@ else if (USER_AGENT.indexOf("AppleWebKit/") != -1)
|
|||||||
PLATFORM_FEATURES |= CPJavascriptClipboardEventsFeature;
|
PLATFORM_FEATURES |= CPJavascriptClipboardEventsFeature;
|
||||||
PLATFORM_FEATURES |= CPJavascriptClipboardAccessFeature;
|
PLATFORM_FEATURES |= CPJavascriptClipboardAccessFeature;
|
||||||
PLATFORM_FEATURES |= CPJavaScriptShadowFeature;
|
PLATFORM_FEATURES |= CPJavaScriptShadowFeature;
|
||||||
|
|
||||||
var versionStart = USER_AGENT.indexOf("AppleWebKit/") + "AppleWebKit/".length,
|
var versionStart = USER_AGENT.indexOf("AppleWebKit/") + "AppleWebKit/".length,
|
||||||
versionEnd = USER_AGENT.indexOf(" ", versionStart),
|
versionEnd = USER_AGENT.indexOf(" ", versionStart),
|
||||||
versionString = USER_AGENT.substring(versionStart, versionEnd),
|
versionString = USER_AGENT.substring(versionStart, versionEnd),
|
||||||
@@ -123,7 +122,7 @@ else if (USER_AGENT.indexOf("AppleWebKit/") != -1)
|
|||||||
majorVersion = parseInt(versionString.substring(0, versionDivision)),
|
majorVersion = parseInt(versionString.substring(0, versionDivision)),
|
||||||
minorVersion = parseInt(versionString.substr(versionDivision + 1));
|
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;
|
PLATFORM_FEATURES |= CPJavascriptRemedialKeySupport;
|
||||||
|
|
||||||
// FIXME this is a terrible hack to get around this bug:
|
// 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.
|
else if (USER_AGENT.indexOf("Gecko") !== -1) // Must follow KHTML check.
|
||||||
{
|
{
|
||||||
PLATFORM_ENGINE = CPGeckoBrowserEngine;
|
PLATFORM_ENGINE = CPGeckoBrowserEngine;
|
||||||
|
|
||||||
PLATFORM_FEATURES |= CPJavaScriptCanvasDrawFeature;
|
PLATFORM_FEATURES |= CPJavaScriptCanvasDrawFeature;
|
||||||
|
|
||||||
var index = USER_AGENT.indexOf("Firefox"),
|
var index = USER_AGENT.indexOf("Firefox"),
|
||||||
version = (index === -1) ? 2.0 : parseFloat(USER_AGENT.substring(index + "Firefox".length + 1));
|
version = (index === -1) ? 2.0 : parseFloat(USER_AGENT.substring(index + "Firefox".length + 1));
|
||||||
|
|
||||||
if (version >= 3.0)
|
if (version >= 3.0)
|
||||||
PLATFORM_FEATURES |= CPCSSRGBAFeature;
|
PLATFORM_FEATURES |= CPCSSRGBAFeature;
|
||||||
|
|
||||||
@@ -166,16 +165,16 @@ if (typeof document != "undefined")
|
|||||||
if (canvasElement && canvasElement.getContext)
|
if (canvasElement && canvasElement.getContext)
|
||||||
{
|
{
|
||||||
PLATFORM_FEATURES |= CPHTMLCanvasFeature;
|
PLATFORM_FEATURES |= CPHTMLCanvasFeature;
|
||||||
|
|
||||||
// Detect Canvas setTransform/transform support
|
// Detect Canvas setTransform/transform support
|
||||||
var context = document.createElement("canvas").getContext("2d");
|
var context = document.createElement("canvas").getContext("2d");
|
||||||
|
|
||||||
if (context && context.setTransform && context.transform)
|
if (context && context.setTransform && context.transform)
|
||||||
PLATFORM_FEATURES |= CPJavaScriptCanvasTransformFeature;
|
PLATFORM_FEATURES |= CPJavaScriptCanvasTransformFeature;
|
||||||
}
|
}
|
||||||
|
|
||||||
var DOMElement = document.createElement("div");
|
var DOMElement = document.createElement("div");
|
||||||
|
|
||||||
// Detect whether we have innerText or textContent (or neither)
|
// Detect whether we have innerText or textContent (or neither)
|
||||||
if (DOMElement.innerText != undefined)
|
if (DOMElement.innerText != undefined)
|
||||||
PLATFORM_FEATURES |= CPJavascriptInnerTextFeature;
|
PLATFORM_FEATURES |= CPJavascriptInnerTextFeature;
|
||||||
|
|||||||
+64
-176
@@ -23,8 +23,9 @@
|
|||||||
@import "CPFont.j"
|
@import "CPFont.j"
|
||||||
@import "CPShadow.j"
|
@import "CPShadow.j"
|
||||||
@import "CPView.j"
|
@import "CPView.j"
|
||||||
@import "CPKeyValueBinding.j"
|
|
||||||
|
|
||||||
|
#include "CoreGraphics/CGGeometry.h"
|
||||||
|
#include "Platform/Platform.h"
|
||||||
|
|
||||||
CPLeftTextAlignment = 0;
|
CPLeftTextAlignment = 0;
|
||||||
CPRightTextAlignment = 1;
|
CPRightTextAlignment = 1;
|
||||||
@@ -74,7 +75,7 @@ CPControlTextDidEndEditingNotification = "CPControlTextDidEndEditingNotific
|
|||||||
|
|
||||||
var CPControlBlackColor = [CPColor blackColor];
|
var CPControlBlackColor = [CPColor blackColor];
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPControl
|
@class CPControl
|
||||||
|
|
||||||
@@ -83,7 +84,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
|||||||
@implementation CPControl : CPView
|
@implementation CPControl : CPView
|
||||||
{
|
{
|
||||||
id _value;
|
id _value;
|
||||||
|
|
||||||
// Target-Action Support
|
// Target-Action Support
|
||||||
id _target;
|
id _target;
|
||||||
SEL _action;
|
SEL _action;
|
||||||
@@ -125,46 +126,16 @@ var CPControlBlackColor = [CPColor blackColor];
|
|||||||
@"max-size"]];
|
@"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
|
- (id)initWithFrame:(CGRect)aFrame
|
||||||
{
|
{
|
||||||
self = [super initWithFrame:aFrame];
|
self = [super initWithFrame:aFrame];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_sendActionOn = CPLeftMouseUpMask;
|
_sendActionOn = CPLeftMouseUpMask;
|
||||||
_trackingMouseDownFlags = 0;
|
_trackingMouseDownFlags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,16 +180,15 @@ var CPControlBlackColor = [CPColor blackColor];
|
|||||||
*/
|
*/
|
||||||
- (void)sendAction:(SEL)anAction to:(id)anObject
|
- (void)sendAction:(SEL)anAction to:(id)anObject
|
||||||
{
|
{
|
||||||
[self _reverseSetBinding];
|
|
||||||
[CPApp sendAction:anAction to:anObject from:self];
|
[CPApp sendAction:anAction to:anObject from:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int)sendActionOn:(int)mask
|
- (int)sendActionOn:(int)mask
|
||||||
{
|
{
|
||||||
var previousMask = _sendActionOn;
|
var previousMask = _sendActionOn;
|
||||||
|
|
||||||
_sendActionOn = mask;
|
_sendActionOn = mask;
|
||||||
|
|
||||||
return previousMask;
|
return previousMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,7 +201,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
|||||||
{
|
{
|
||||||
if (_toolTip == aToolTip)
|
if (_toolTip == aToolTip)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_toolTip = aToolTip;
|
_toolTip = aToolTip;
|
||||||
|
|
||||||
#if PLATFORM(DOM)
|
#if PLATFORM(DOM)
|
||||||
@@ -266,7 +236,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
|||||||
// Some subclasses should redefine this with CPLeftMouseDraggedMask
|
// Some subclasses should redefine this with CPLeftMouseDraggedMask
|
||||||
if (flag)
|
if (flag)
|
||||||
_sendActionOn |= CPPeriodicMask;
|
_sendActionOn |= CPPeriodicMask;
|
||||||
else
|
else
|
||||||
_sendActionOn &= ~CPPeriodicMask;
|
_sendActionOn &= ~CPPeriodicMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,15 +248,16 @@ var CPControlBlackColor = [CPColor blackColor];
|
|||||||
- (void)trackMouse:(CPEvent)anEvent
|
- (void)trackMouse:(CPEvent)anEvent
|
||||||
{
|
{
|
||||||
var type = [anEvent type],
|
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);
|
isWithinFrame = [self tracksMouseOutsideOfFrame] || CGRectContainsPoint([self bounds], currentLocation);
|
||||||
|
|
||||||
if (type === CPLeftMouseUp)
|
if (type === CPLeftMouseUp)
|
||||||
{
|
{
|
||||||
[self stopTracking:_previousTrackingLocation at:currentLocation mouseIsUp:YES];
|
[self stopTracking:_previousTrackingLocation at:currentLocation mouseIsUp:YES];
|
||||||
|
|
||||||
_trackingMouseDownFlags = 0;
|
_trackingMouseDownFlags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (type === CPLeftMouseDown)
|
if (type === CPLeftMouseDown)
|
||||||
@@ -300,20 +271,20 @@ var CPControlBlackColor = [CPColor blackColor];
|
|||||||
{
|
{
|
||||||
if (!_trackingWasWithinFrame)
|
if (!_trackingWasWithinFrame)
|
||||||
_continuousTracking = [self startTrackingAt:currentLocation];
|
_continuousTracking = [self startTrackingAt:currentLocation];
|
||||||
|
|
||||||
else if (_continuousTracking)
|
else if (_continuousTracking)
|
||||||
_continuousTracking = [self continueTracking:_previousTrackingLocation at:currentLocation];
|
_continuousTracking = [self continueTracking:_previousTrackingLocation at:currentLocation];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
[self stopTracking:_previousTrackingLocation at:currentLocation mouseIsUp:NO];
|
[self stopTracking:_previousTrackingLocation at:currentLocation mouseIsUp:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
[CPApp setTarget:self selector:@selector(trackMouse:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
|
[CPApp setTarget:self selector:@selector(trackMouse:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((_sendActionOn & (1 << type)) && isWithinFrame)
|
if ((_sendActionOn & (1 << type)) && isWithinFrame)
|
||||||
[self sendAction:_action to:_target];
|
[self sendAction:_action to:_target];
|
||||||
|
|
||||||
_trackingWasWithinFrame = isWithinFrame;
|
_trackingWasWithinFrame = isWithinFrame;
|
||||||
_previousTrackingLocation = currentLocation;
|
_previousTrackingLocation = currentLocation;
|
||||||
}
|
}
|
||||||
@@ -327,26 +298,13 @@ var CPControlBlackColor = [CPColor blackColor];
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)performClick:(id)sender
|
- (void)performClick:(id)sender
|
||||||
{
|
{
|
||||||
if (![self isEnabled])
|
|
||||||
return;
|
|
||||||
|
|
||||||
[self highlight:YES];
|
[self highlight:YES];
|
||||||
[self setState:[self nextState]];
|
[self setState:[self nextState]];
|
||||||
|
[self sendAction:[self action] to:[self target]];
|
||||||
try
|
|
||||||
{
|
[CPTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(unhighlightButtonTimerDidFinish:) userInfo:nil repeats:NO];
|
||||||
[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];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)unhighlightButtonTimerDidFinish:(id)sender
|
- (void)unhighlightButtonTimerDidFinish:(id)sender
|
||||||
@@ -362,7 +320,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
|||||||
- (BOOL)startTrackingAt:(CGPoint)aPoint
|
- (BOOL)startTrackingAt:(CGPoint)aPoint
|
||||||
{
|
{
|
||||||
[self highlight:YES];
|
[self highlight:YES];
|
||||||
|
|
||||||
return (_sendActionOn & CPPeriodicMask) || (_sendActionOn & CPLeftMouseDraggedMask);
|
return (_sendActionOn & CPPeriodicMask) || (_sendActionOn & CPLeftMouseDraggedMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,7 +338,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
|||||||
{
|
{
|
||||||
if (![self isEnabled])
|
if (![self isEnabled])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[self trackMouse:anEvent];
|
[self trackMouse:anEvent];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,7 +356,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
|||||||
- (void)setObjectValue:(id)anObject
|
- (void)setObjectValue:(id)anObject
|
||||||
{
|
{
|
||||||
_value = anObject;
|
_value = anObject;
|
||||||
|
|
||||||
[self setNeedsLayout];
|
[self setNeedsLayout];
|
||||||
[self setNeedsDisplay:YES];
|
[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
|
- (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
|
- (void)setStringValue:(CPString)anObject
|
||||||
{
|
{
|
||||||
@@ -527,124 +485,54 @@ var CPControlBlackColor = [CPColor blackColor];
|
|||||||
[self setStringValue:[sender stringValue]];
|
[self setStringValue:[sender stringValue]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)textDidBeginEditing:(CPNotification)note
|
- (void)textDidBeginEditing:(CPNotification)note
|
||||||
{
|
{
|
||||||
//this looks to prevent false propagation of notifications for other objects
|
//this looks to prevent false propagation of notifications for other objects
|
||||||
if ([note object] != self)
|
if([note object] != self)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidBeginEditingNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
|
[[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
|
//this looks to prevent false propagation of notifications for other objects
|
||||||
if ([note object] != self)
|
if([note object] != self)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidChangeNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
|
[[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
|
//this looks to prevent false propagation of notifications for other objects
|
||||||
if ([note object] != self)
|
if([note object] != self)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[self _reverseSetBinding];
|
|
||||||
|
|
||||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidEndEditingNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
|
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidEndEditingNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setAlignment:(CPTextAlignment)alignment
|
#define BRIDGE(UPPERCASE, LOWERCASE, ATTRIBUTENAME) \
|
||||||
{
|
/*! Sets the value for ATTRIBUTENAME */\
|
||||||
[self setValue:alignment forThemeAttribute:@"alignment"];
|
- (void)set##UPPERCASE:(id)aValue\
|
||||||
|
{\
|
||||||
|
[self setValue:aValue forThemeAttribute:ATTRIBUTENAME];\
|
||||||
|
}\
|
||||||
|
/*! Returns the current value for ATTRIBUTENAME */\
|
||||||
|
- (id)LOWERCASE\
|
||||||
|
{\
|
||||||
|
return [self valueForThemeAttribute:ATTRIBUTENAME];\
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CPTextAlignment)alignment
|
BRIDGE(Alignment, alignment, "alignment")
|
||||||
{
|
BRIDGE(VerticalAlignment, verticalAlignment, "vertical-alignment")
|
||||||
return [self valueForThemeAttribute:@"alignment"];
|
BRIDGE(LineBreakMode, lineBreakMode, "line-break-mode")
|
||||||
}
|
BRIDGE(TextColor, textColor, "text-color")
|
||||||
|
BRIDGE(Font, font, "font")
|
||||||
- (void)setVerticalAlignment:(CPTextVerticalAlignment)alignment
|
BRIDGE(TextShadowColor, textShadowColor, "text-shadow-color")
|
||||||
{
|
BRIDGE(TextShadowOffset, textShadowOffset, "text-shadow-offset")
|
||||||
[self setValue:alignment forThemeAttribute:@"vertical-alignment"];
|
BRIDGE(ImagePosition, imagePosition, "image-position")
|
||||||
}
|
BRIDGE(ImageScaling, imageScaling, "image-scaling")
|
||||||
|
|
||||||
- (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"];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setEnabled:(BOOL)isEnabled
|
- (void)setEnabled:(BOOL)isEnabled
|
||||||
{
|
{
|
||||||
@@ -682,7 +570,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
|||||||
var CPControlValueKey = "CPControlValueKey",
|
var CPControlValueKey = "CPControlValueKey",
|
||||||
CPControlControlStateKey = @"CPControlControlStateKey",
|
CPControlControlStateKey = @"CPControlControlStateKey",
|
||||||
CPControlIsEnabledKey = "CPControlIsEnabledKey",
|
CPControlIsEnabledKey = "CPControlIsEnabledKey",
|
||||||
|
|
||||||
CPControlTargetKey = "CPControlTargetKey",
|
CPControlTargetKey = "CPControlTargetKey",
|
||||||
CPControlActionKey = "CPControlActionKey",
|
CPControlActionKey = "CPControlActionKey",
|
||||||
CPControlSendActionOnKey = "CPControlSendActionOnKey",
|
CPControlSendActionOnKey = "CPControlSendActionOnKey",
|
||||||
@@ -712,7 +600,7 @@ var __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
|
|||||||
[self sendActionOn:[aCoder decodeIntForKey:CPControlSendActionOnKey]];
|
[self sendActionOn:[aCoder decodeIntForKey:CPControlSendActionOnKey]];
|
||||||
[self setSendsActionOnEndEditing:[aCoder decodeBoolForKey:CPControlSendsActionOnEndEditingKey]];
|
[self setSendsActionOnEndEditing:[aCoder decodeBoolForKey:CPControlSendsActionOnEndEditingKey]];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -748,7 +636,7 @@ var _CPControlSizeIdentifiers = [],
|
|||||||
_CPControlSizeIdentifiers[CPRegularControlSize] = "Regular";
|
_CPControlSizeIdentifiers[CPRegularControlSize] = "Regular";
|
||||||
_CPControlSizeIdentifiers[CPSmallControlSize] = "Small";
|
_CPControlSizeIdentifiers[CPSmallControlSize] = "Small";
|
||||||
_CPControlSizeIdentifiers[CPMiniControlSize] = "Mini";
|
_CPControlSizeIdentifiers[CPMiniControlSize] = "Mini";
|
||||||
|
|
||||||
function _CPControlIdentifierForControlSize(aControlSize)
|
function _CPControlIdentifierForControlSize(aControlSize)
|
||||||
{
|
{
|
||||||
return _CPControlSizeIdentifiers[aControlSize];
|
return _CPControlSizeIdentifiers[aControlSize];
|
||||||
@@ -759,21 +647,21 @@ function _CPControlColorWithPatternImage(sizes, aClassName)
|
|||||||
var index = 1,
|
var index = 1,
|
||||||
count = arguments.length,
|
count = arguments.length,
|
||||||
identifier = "";
|
identifier = "";
|
||||||
|
|
||||||
for (; index < count; ++index)
|
for (; index < count; ++index)
|
||||||
identifier += arguments[index];
|
identifier += arguments[index];
|
||||||
|
|
||||||
var color = _CPControlCachedColorWithPatternImages[identifier];
|
var color = _CPControlCachedColorWithPatternImages[identifier];
|
||||||
|
|
||||||
if (!color)
|
if (!color)
|
||||||
{
|
{
|
||||||
var bundle = [CPBundle bundleForClass:[CPControl class]];
|
var bundle = [CPBundle bundleForClass:[CPControl class]];
|
||||||
|
|
||||||
color = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:aClassName + "/" + identifier + ".png"] size:sizes[identifier]]];
|
color = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:aClassName + "/" + identifier + ".png"] size:sizes[identifier]]];
|
||||||
|
|
||||||
_CPControlCachedColorWithPatternImages[identifier] = color;
|
_CPControlCachedColorWithPatternImages[identifier] = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -782,17 +670,17 @@ function _CPControlThreePartImagePattern(isVertical, sizes, aClassName)
|
|||||||
var index = 2,
|
var index = 2,
|
||||||
count = arguments.length,
|
count = arguments.length,
|
||||||
identifier = "";
|
identifier = "";
|
||||||
|
|
||||||
for (; index < count; ++index)
|
for (; index < count; ++index)
|
||||||
identifier += arguments[index];
|
identifier += arguments[index];
|
||||||
|
|
||||||
var color = _CPControlCachedThreePartImagePattern[identifier];
|
var color = _CPControlCachedThreePartImagePattern[identifier];
|
||||||
|
|
||||||
if (!color)
|
if (!color)
|
||||||
{
|
{
|
||||||
var bundle = [CPBundle bundleForClass:[CPControl class]],
|
var bundle = [CPBundle bundleForClass:[CPControl class]],
|
||||||
path = aClassName + "/" + identifier;
|
path = aClassName + "/" + identifier;
|
||||||
|
|
||||||
sizes = sizes[identifier];
|
sizes = sizes[identifier];
|
||||||
|
|
||||||
color = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:[
|
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 + "1.png"] size:sizes[1]],
|
||||||
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + "2.png"] size:sizes[2]]
|
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + "2.png"] size:sizes[2]]
|
||||||
] isVertical:isVertical]];
|
] isVertical:isVertical]];
|
||||||
|
|
||||||
_CPControlCachedThreePartImagePattern[identifier] = color;
|
_CPControlCachedThreePartImagePattern[identifier] = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -24,7 +24,7 @@
|
|||||||
@import <Foundation/CPString.j>
|
@import <Foundation/CPString.j>
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPCookie
|
@class CPCookie
|
||||||
CPCookie is the Cappuccino interface to a web browser cookie. You can set the name
|
CPCookie is the Cappuccino interface to a web browser cookie. You can set the name
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
{
|
{
|
||||||
CPString _cookieName;
|
CPString _cookieName;
|
||||||
CPString _cookieValue;
|
CPString _cookieValue;
|
||||||
|
|
||||||
CPString _expires;
|
CPString _expires;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
- (id)initWithName:(CPString)aName
|
- (id)initWithName:(CPString)aName
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
_cookieName = aName;
|
_cookieName = aName;
|
||||||
_cookieValue = [self _readCookieValue];
|
_cookieValue = [self _readCookieValue];
|
||||||
|
|
||||||
@@ -83,39 +83,30 @@
|
|||||||
*/
|
*/
|
||||||
- (void)setValue:(CPString)value expires:(CPDate)date domain:(CPString)domain
|
- (void)setValue:(CPString)value expires:(CPDate)date domain:(CPString)domain
|
||||||
{
|
{
|
||||||
if (date)
|
if(date)
|
||||||
var expires = "; expires=" + date.toGMTString();
|
var expires = "; expires="+date.toGMTString();
|
||||||
else
|
else
|
||||||
var expires = "";
|
var expires = "";
|
||||||
|
|
||||||
if (domain)
|
if(domain)
|
||||||
domain = "; domain=" + domain;
|
domain = "; domain="+domain;
|
||||||
else
|
else
|
||||||
domain = "";
|
domain = "";
|
||||||
|
|
||||||
#if PLATFORM(DOM)
|
document.cookie = _cookieName+"="+value+expires+"; path=/"+domain;
|
||||||
document.cookie = _cookieName+"="+value+expires+"; path=/"+domain;
|
|
||||||
#else
|
|
||||||
_cookieValue = value;
|
|
||||||
_expires = expires;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* @ignore */
|
/* @ignore */
|
||||||
- (CPString)_readCookieValue
|
- (CPString)_readCookieValue
|
||||||
{
|
{
|
||||||
#if PLATFORM(DOM)
|
var nameEQ = _cookieName + "=";
|
||||||
var nameEQ = _cookieName + "=",
|
var ca = document.cookie.split(';');
|
||||||
ca = document.cookie.split(';');
|
for(var i=0;i < ca.length;i++) {
|
||||||
|
var c = ca[i];
|
||||||
for (var i = 0; i < ca.length; i++)
|
while (c.charAt(0)==' ') c = c.substring(1,c.length);
|
||||||
{
|
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
|
||||||
var c = ca[i];
|
}
|
||||||
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
|
return "";
|
||||||
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
+10
-15
@@ -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
|
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,
|
var currentCursor = nil,
|
||||||
cursorStack = [],
|
cursorStack = [],
|
||||||
@@ -61,9 +61,9 @@ var currentCursor = nil,
|
|||||||
if (CPBrowserIsEngine(CPGeckoBrowserEngine))
|
if (CPBrowserIsEngine(CPGeckoBrowserEngine))
|
||||||
cursorURLFormat += ", default";
|
cursorURLFormat += ", default";
|
||||||
}
|
}
|
||||||
|
|
||||||
var url = [CPString stringWithFormat:cursorURLFormat, imageName];
|
var url = [CPString stringWithFormat:cursorURLFormat, imageName];
|
||||||
|
|
||||||
return [[CPCursor alloc] initWithCSSString:url];
|
return [[CPCursor alloc] initWithCSSString:url];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ var currentCursor = nil,
|
|||||||
{
|
{
|
||||||
if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
|
if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
|
||||||
return [CPCursor cursorWithImageNamed:CPStringFromSelector(_cmd)];
|
return [CPCursor cursorWithImageNamed:CPStringFromSelector(_cmd)];
|
||||||
|
|
||||||
return [CPCursor cursorWithCSSString:"s-resize"]; // WebKit | FF | opera
|
return [CPCursor cursorWithCSSString:"s-resize"]; // WebKit | FF | opera
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,22 +167,18 @@ var currentCursor = nil,
|
|||||||
{
|
{
|
||||||
if (CPBrowserIsEngine(CPWebKitBrowserEngine))
|
if (CPBrowserIsEngine(CPWebKitBrowserEngine))
|
||||||
return [CPCursor cursorWithCSSString:@"-webkit-grab"];
|
return [CPCursor cursorWithCSSString:@"-webkit-grab"];
|
||||||
else if (CPBrowserIsEngine(CPGeckoBrowserEngine))
|
else if (CPBrowserIsEngine(CPGeckoBrowserEngine) || CPBrowserIsEngine(CPOperaBrowserEngine))
|
||||||
return [CPCursor cursorWithCSSString:@"-moz-grab"];
|
|
||||||
else if (CPBrowserIsEngine(CPOperaBrowserEngine))
|
|
||||||
return [CPCursor cursorWithCSSString:@"move"];
|
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
|
+ (CPCursor)closedHandCursor
|
||||||
{
|
{
|
||||||
if (CPBrowserIsEngine(CPWebKitBrowserEngine))
|
if (CPBrowserIsEngine(CPWebKitBrowserEngine))
|
||||||
return [CPCursor cursorWithCSSString:@"-webkit-grabbing"];
|
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
|
+ (CPCursor)disappearingItemCursor
|
||||||
@@ -197,7 +193,7 @@ var currentCursor = nil,
|
|||||||
|
|
||||||
+ (void)unhide
|
+ (void)unhide
|
||||||
{
|
{
|
||||||
[self _setCursorCSS:[currentCursor _cssString]];
|
[self _setCursorCSS:[currentCursor _cssString]]
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (void)setHiddenUntilMouseMoves:(BOOL)flag
|
+ (void)setHiddenUntilMouseMoves:(BOOL)flag
|
||||||
@@ -210,10 +206,9 @@ var currentCursor = nil,
|
|||||||
|
|
||||||
- (id)initWithImage:(CPImage)image hotSpot:(CPPoint)hotSpot
|
- (id)initWithImage:(CPImage)image hotSpot:(CPPoint)hotSpot
|
||||||
{
|
{
|
||||||
return [self initWithCSSString:"url(" + [image filename] + "), auto"];
|
return [self initWithCSSString:"url(" + [image filename] + ")"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (void)mouseEntered:(CPEvent)event
|
- (void)mouseEntered:(CPEvent)event
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -224,7 +219,7 @@ var currentCursor = nil,
|
|||||||
|
|
||||||
- (void)set
|
- (void)set
|
||||||
{
|
{
|
||||||
currentCursor = self;
|
currentCursor = self;
|
||||||
|
|
||||||
#if PLATFORM(DOM)
|
#if PLATFORM(DOM)
|
||||||
[[self class] _setCursorCSS:_cssString];
|
[[self class] _setCursorCSS:_cssString];
|
||||||
|
|||||||
+67
-55
@@ -23,7 +23,6 @@
|
|||||||
@import <Foundation/CPString.j>
|
@import <Foundation/CPString.j>
|
||||||
@import <Foundation/CPArray.j>
|
@import <Foundation/CPArray.j>
|
||||||
|
|
||||||
@import "CPApplication.j"
|
|
||||||
@import "CPResponder.j"
|
@import "CPResponder.j"
|
||||||
@import "CPSavePanel.j"
|
@import "CPSavePanel.j"
|
||||||
@import "CPViewController.j"
|
@import "CPViewController.j"
|
||||||
@@ -83,7 +82,7 @@ CPDocumentDidFailToSaveNotification = @"CPDocumentDidFailToSaveNotification";
|
|||||||
|
|
||||||
var CPDocumentUntitledCount = 0;
|
var CPDocumentUntitledCount = 0;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPDocument
|
@class CPDocument
|
||||||
|
|
||||||
@@ -121,7 +120,7 @@ var CPDocumentUntitledCount = 0;
|
|||||||
- (id)init
|
- (id)init
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_windowControllers = [];
|
_windowControllers = [];
|
||||||
@@ -132,7 +131,7 @@ var CPDocumentUntitledCount = 0;
|
|||||||
|
|
||||||
[self setNextResponder:CPApp];
|
[self setNextResponder:CPApp];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,10 +144,10 @@ var CPDocumentUntitledCount = 0;
|
|||||||
- (id)initWithType:(CPString)aType error:({CPError})anError
|
- (id)initWithType:(CPString)aType error:({CPError})anError
|
||||||
{
|
{
|
||||||
self = [self init];
|
self = [self init];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
[self setFileType:aType];
|
[self setFileType:aType];
|
||||||
|
|
||||||
return self;
|
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
|
- (id)initWithContentsOfURL:(CPURL)anAbsoluteURL ofType:(CPString)aType delegate:(id)aDelegate didReadSelector:(SEL)aDidReadSelector contextInfo:(id)aContextInfo
|
||||||
{
|
{
|
||||||
self = [self init];
|
self = [self init];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
[self setFileURL:anAbsoluteURL];
|
[self setFileURL:anAbsoluteURL];
|
||||||
@@ -174,7 +173,7 @@ var CPDocumentUntitledCount = 0;
|
|||||||
|
|
||||||
[self readFromURL:anAbsoluteURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo];
|
[self readFromURL:anAbsoluteURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
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
|
- (id)initForURL:(CPURL)anAbsoluteURL withContentsOfURL:(CPURL)absoluteContentsURL ofType:(CPString)aType delegate:(id)aDelegate didReadSelector:(SEL)aDidReadSelector contextInfo:(id)aContextInfo
|
||||||
{
|
{
|
||||||
self = [self init];
|
self = [self init];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
[self setFileURL:anAbsoluteURL];
|
[self setFileURL:anAbsoluteURL];
|
||||||
@@ -199,7 +198,7 @@ var CPDocumentUntitledCount = 0;
|
|||||||
|
|
||||||
[self readFromURL:absoluteContentsURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo];
|
[self readFromURL:absoluteContentsURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,10 +210,10 @@ var CPDocumentUntitledCount = 0;
|
|||||||
@throws CPUnsupportedMethodException if this method hasn't been overriden by the subclass
|
@throws CPUnsupportedMethodException if this method hasn't been overriden by the subclass
|
||||||
@return the document data
|
@return the document data
|
||||||
*/
|
*/
|
||||||
- (CPData)dataOfType:(CPString)aType error:({CPError})anError
|
- (CPData)dataOfType:(CPString)aType
|
||||||
{
|
{
|
||||||
[CPException raise:CPUnsupportedMethodException
|
[CPException raise:CPUnsupportedMethodException
|
||||||
reason:"dataOfType:error: must be overridden by the document subclass."];
|
reason:"dataOfType: must be overridden by the document subclass."];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -282,7 +281,7 @@ var CPDocumentUntitledCount = 0;
|
|||||||
{
|
{
|
||||||
var view = [viewController view],
|
var view = [viewController view],
|
||||||
viewFrame = [view frame];
|
viewFrame = [view frame];
|
||||||
|
|
||||||
viewFrame.origin = CGPointMake(50, 50);
|
viewFrame.origin = CGPointMake(50, 50);
|
||||||
|
|
||||||
var theWindow = [[CPWindow alloc] initWithContentRect:viewFrame styleMask:CPTitledWindowMask | CPClosableWindowMask | CPMiniaturizableWindowMask | CPResizableWindowMask];
|
var theWindow = [[CPWindow alloc] initWithContentRect:viewFrame styleMask:CPTitledWindowMask | CPClosableWindowMask | CPMiniaturizableWindowMask | CPResizableWindowMask];
|
||||||
@@ -382,14 +381,14 @@ var CPDocumentUntitledCount = 0;
|
|||||||
{
|
{
|
||||||
if (_fileURL)
|
if (_fileURL)
|
||||||
return [_fileURL lastPathComponent];
|
return [_fileURL lastPathComponent];
|
||||||
|
|
||||||
if (!_untitledDocumentIndex)
|
if (!_untitledDocumentIndex)
|
||||||
_untitledDocumentIndex = ++CPDocumentUntitledCount;
|
_untitledDocumentIndex = ++CPDocumentUntitledCount;
|
||||||
|
|
||||||
|
if (_untitledDocumentIndex == 1)
|
||||||
|
return @"Untitled";
|
||||||
|
|
||||||
if (_untitledDocumentIndex == 1)
|
return @"Untitled " + _untitledDocumentIndex;
|
||||||
return @"Untitled";
|
|
||||||
|
|
||||||
return @"Untitled " + _untitledDocumentIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CPString)viewCibName
|
- (CPString)viewCibName
|
||||||
@@ -458,7 +457,7 @@ var CPDocumentUntitledCount = 0;
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
_fileURL = aFileURL;
|
_fileURL = aFileURL;
|
||||||
|
|
||||||
[_windowControllers makeObjectsPerformSelector:@selector(synchronizeWindowTitleWithDocumentName)];
|
[_windowControllers makeObjectsPerformSelector:@selector(synchronizeWindowTitleWithDocumentName)];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,8 +473,21 @@ var CPDocumentUntitledCount = 0;
|
|||||||
*/
|
*/
|
||||||
- (void)saveToURL:(CPURL)anAbsoluteURL ofType:(CPString)aTypeName forSaveOperation:(CPSaveOperationType)aSaveOperation delegate:(id)aDelegate didSaveSelector:(SEL)aDidSaveSelector contextInfo:(id)aContextInfo
|
- (void)saveToURL:(CPURL)anAbsoluteURL ofType:(CPString)aTypeName forSaveOperation:(CPSaveOperationType)aSaveOperation delegate:(id)aDelegate didSaveSelector:(SEL)aDidSaveSelector contextInfo:(id)aContextInfo
|
||||||
{
|
{
|
||||||
var data = [self dataOfType:[self fileType] error:nil],
|
if (anAbsoluteURL.isLocalStorageURL())
|
||||||
oldChangeCount = _changeCount;
|
[[CPDocumentController sharedDocumentController] _addLocalDocumentURL:anAbsoluteURL];
|
||||||
|
|
||||||
|
var data = nil;
|
||||||
|
|
||||||
|
if ([self respondsToSelector:@selector(dataOfType:error:)])
|
||||||
|
{
|
||||||
|
CPLog.warn("[" + CPStringFromClass([self class]) + " " + CPStringFromSelector(@selector(dataOfType:error:)) + "] is deprecated, please implement " + CPStringFromSelector(@selector(dataOfType:)) + " instead and simply throw exceptions when necessary.");
|
||||||
|
|
||||||
|
data = [self dataOfType:[self fileType] error:nil];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
data = [self dataOfType:[self fileType]];
|
||||||
|
|
||||||
|
var oldChangeCount = _changeCount;
|
||||||
|
|
||||||
_writeRequest = [CPURLRequest requestWithURL:anAbsoluteURL];
|
_writeRequest = [CPURLRequest requestWithURL:anAbsoluteURL];
|
||||||
|
|
||||||
@@ -510,21 +522,21 @@ var CPDocumentUntitledCount = 0;
|
|||||||
// If we got this far and it wasn't an HTTP request, then everything is fine.
|
// If we got this far and it wasn't an HTTP request, then everything is fine.
|
||||||
if (![aResponse isKindOfClass:[CPHTTPURLResponse class]])
|
if (![aResponse isKindOfClass:[CPHTTPURLResponse class]])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var statusCode = [aResponse statusCode];
|
var statusCode = [aResponse statusCode];
|
||||||
|
|
||||||
// Nothing to do if everything is hunky dory.
|
// Nothing to do if everything is hunky dory.
|
||||||
if (statusCode === 200)
|
if (statusCode === 200)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var session = aConnection.session;
|
var session = aConnection.session;
|
||||||
|
|
||||||
if (aConnection == _readConnection)
|
if (aConnection == _readConnection)
|
||||||
{
|
{
|
||||||
[aConnection cancel];
|
[aConnection cancel];
|
||||||
|
|
||||||
alert("There was an error retrieving the document.");
|
alert("There was an error retrieving the document.");
|
||||||
|
|
||||||
objj_msgSend(session.delegate, session.didReadSelector, self, NO, session.contextInfo);
|
objj_msgSend(session.delegate, session.didReadSelector, self, NO, session.contextInfo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -533,23 +545,23 @@ var CPDocumentUntitledCount = 0;
|
|||||||
if (statusCode == 409)
|
if (statusCode == 409)
|
||||||
{
|
{
|
||||||
[aConnection cancel];
|
[aConnection cancel];
|
||||||
|
|
||||||
if (confirm("There already exists a file with that name, would you like to overwrite it?"))
|
if (confirm("There already exists a file with that name, would you like to overwrite it?"))
|
||||||
{
|
{
|
||||||
[_writeRequest setValue:@"true" forHTTPHeaderField:@"x-cappuccino-overwrite"];
|
[_writeRequest setValue:@"true" forHTTPHeaderField:@"x-cappuccino-overwrite"];
|
||||||
|
|
||||||
[aConnection start];
|
[aConnection start];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (session.saveOperation != CPSaveToOperation)
|
if (session.saveOperation != CPSaveToOperation)
|
||||||
{
|
{
|
||||||
_changeCount += session.changeCount;
|
_changeCount += session.changeCount;
|
||||||
[_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[self isDocumentEdited]];
|
[_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[self isDocumentEdited]];
|
||||||
}
|
}
|
||||||
|
|
||||||
_writeRequest = nil;
|
_writeRequest = nil;
|
||||||
|
|
||||||
objj_msgSend(session.delegate, session.didSaveSelector, self, NO, session.contextInfo);
|
objj_msgSend(session.delegate, session.didSaveSelector, self, NO, session.contextInfo);
|
||||||
[self _sendDocumentSavedNotification:NO];
|
[self _sendDocumentSavedNotification:NO];
|
||||||
}
|
}
|
||||||
@@ -564,7 +576,7 @@ var CPDocumentUntitledCount = 0;
|
|||||||
- (void)connection:(CPURLConnection)aConnection didReceiveData:(CPString)aData
|
- (void)connection:(CPURLConnection)aConnection didReceiveData:(CPString)aData
|
||||||
{
|
{
|
||||||
var session = aConnection.session;
|
var session = aConnection.session;
|
||||||
|
|
||||||
// READ
|
// READ
|
||||||
if (aConnection == _readConnection)
|
if (aConnection == _readConnection)
|
||||||
{
|
{
|
||||||
@@ -576,9 +588,9 @@ var CPDocumentUntitledCount = 0;
|
|||||||
{
|
{
|
||||||
if (session.saveOperation != CPSaveToOperation)
|
if (session.saveOperation != CPSaveToOperation)
|
||||||
[self setFileURL:session.absoluteURL];
|
[self setFileURL:session.absoluteURL];
|
||||||
|
|
||||||
_writeRequest = nil;
|
_writeRequest = nil;
|
||||||
|
|
||||||
objj_msgSend(session.delegate, session.didSaveSelector, self, YES, session.contextInfo);
|
objj_msgSend(session.delegate, session.didSaveSelector, self, YES, session.contextInfo);
|
||||||
[self _sendDocumentSavedNotification:YES];
|
[self _sendDocumentSavedNotification:YES];
|
||||||
}
|
}
|
||||||
@@ -591,17 +603,17 @@ var CPDocumentUntitledCount = 0;
|
|||||||
- (void)connection:(CPURLConnection)aConnection didFailWithError:(CPError)anError
|
- (void)connection:(CPURLConnection)aConnection didFailWithError:(CPError)anError
|
||||||
{
|
{
|
||||||
var session = aConnection.session;
|
var session = aConnection.session;
|
||||||
|
|
||||||
if (_readConnection == aConnection)
|
if (_readConnection == aConnection)
|
||||||
objj_msgSend(session.delegate, session.didReadSelector, self, NO, session.contextInfo);
|
objj_msgSend(session.delegate, session.didReadSelector, self, NO, session.contextInfo);
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (session.saveOperation != CPSaveToOperation)
|
if (session.saveOperation != CPSaveToOperation)
|
||||||
{
|
{
|
||||||
_changeCount += session.changeCount;
|
_changeCount += session.changeCount;
|
||||||
[_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[self isDocumentEdited]];
|
[_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[self isDocumentEdited]];
|
||||||
}
|
}
|
||||||
|
|
||||||
_writeRequest = nil;
|
_writeRequest = nil;
|
||||||
|
|
||||||
@@ -644,9 +656,9 @@ var CPDocumentUntitledCount = 0;
|
|||||||
else if (aChangeType == CPChangeCleared)
|
else if (aChangeType == CPChangeCleared)
|
||||||
_changeCount = 0;
|
_changeCount = 0;
|
||||||
/*else if (aChangeType == CPCHangeReadOtherContents)
|
/*else if (aChangeType == CPCHangeReadOtherContents)
|
||||||
|
|
||||||
else if (aChangeType == CPChangeAutosaved)*/
|
else if (aChangeType == CPChangeAutosaved)*/
|
||||||
|
|
||||||
[_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[self isDocumentEdited]];
|
[_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[self isDocumentEdited]];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -686,9 +698,9 @@ var CPDocumentUntitledCount = 0;
|
|||||||
{
|
{
|
||||||
if (_hasUndoManager == aFlag)
|
if (_hasUndoManager == aFlag)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_hasUndoManager = aFlag;
|
_hasUndoManager = aFlag;
|
||||||
|
|
||||||
if (!_hasUndoManager)
|
if (!_hasUndoManager)
|
||||||
[self setUndoManager:nil];
|
[self setUndoManager:nil];
|
||||||
}
|
}
|
||||||
@@ -697,7 +709,7 @@ var CPDocumentUntitledCount = 0;
|
|||||||
- (void)_undoManagerWillCloseGroup:(CPNotification)aNotification
|
- (void)_undoManagerWillCloseGroup:(CPNotification)aNotification
|
||||||
{
|
{
|
||||||
var undoManager = [aNotification object];
|
var undoManager = [aNotification object];
|
||||||
|
|
||||||
if ([undoManager isUndoing] || [undoManager isRedoing])
|
if ([undoManager isUndoing] || [undoManager isRedoing])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -724,13 +736,13 @@ var CPDocumentUntitledCount = 0;
|
|||||||
- (void)setUndoManager:(CPUndoManager)anUndoManager
|
- (void)setUndoManager:(CPUndoManager)anUndoManager
|
||||||
{
|
{
|
||||||
var defaultCenter = [CPNotificationCenter defaultCenter];
|
var defaultCenter = [CPNotificationCenter defaultCenter];
|
||||||
|
|
||||||
if (_undoManager)
|
if (_undoManager)
|
||||||
{
|
{
|
||||||
[defaultCenter removeObserver:self
|
[defaultCenter removeObserver:self
|
||||||
name:CPUndoManagerDidUndoChangeNotification
|
name:CPUndoManagerDidUndoChangeNotification
|
||||||
object:_undoManager];
|
object:_undoManager];
|
||||||
|
|
||||||
[defaultCenter removeObserver:self
|
[defaultCenter removeObserver:self
|
||||||
name:CPUndoManagerDidRedoChangeNotification
|
name:CPUndoManagerDidRedoChangeNotification
|
||||||
object:_undoManager];
|
object:_undoManager];
|
||||||
@@ -739,17 +751,17 @@ var CPDocumentUntitledCount = 0;
|
|||||||
name:CPUndoManagerWillCloseUndoGroupNotification
|
name:CPUndoManagerWillCloseUndoGroupNotification
|
||||||
object:_undoManager];
|
object:_undoManager];
|
||||||
}
|
}
|
||||||
|
|
||||||
_undoManager = anUndoManager;
|
_undoManager = anUndoManager;
|
||||||
|
|
||||||
if (_undoManager)
|
if (_undoManager)
|
||||||
{
|
{
|
||||||
|
|
||||||
[defaultCenter addObserver:self
|
[defaultCenter addObserver:self
|
||||||
selector:@selector(_undoManagerDidUndoChange:)
|
selector:@selector(_undoManagerDidUndoChange:)
|
||||||
name:CPUndoManagerDidUndoChangeNotification
|
name:CPUndoManagerDidUndoChangeNotification
|
||||||
object:_undoManager];
|
object:_undoManager];
|
||||||
|
|
||||||
[defaultCenter addObserver:self
|
[defaultCenter addObserver:self
|
||||||
selector:@selector(_undoManagerDidRedoChange:)
|
selector:@selector(_undoManagerDidRedoChange:)
|
||||||
name:CPUndoManagerDidRedoChangeNotification
|
name:CPUndoManagerDidRedoChangeNotification
|
||||||
@@ -775,7 +787,7 @@ var CPDocumentUntitledCount = 0;
|
|||||||
|
|
||||||
return _undoManager;
|
return _undoManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Implemented as a delegate of a CPWindow
|
Implemented as a delegate of a CPWindow
|
||||||
@ignore
|
@ignore
|
||||||
@@ -804,7 +816,7 @@ var CPDocumentUntitledCount = 0;
|
|||||||
[[CPNotificationCenter defaultCenter]
|
[[CPNotificationCenter defaultCenter]
|
||||||
postNotificationName:CPDocumentWillSaveNotification
|
postNotificationName:CPDocumentWillSaveNotification
|
||||||
object:self];
|
object:self];
|
||||||
|
|
||||||
[self saveToURL:_fileURL ofType:[self fileType] forSaveOperation:CPSaveOperation delegate:delegate didSaveSelector:didSaveSelector contextInfo:contextInfo];
|
[self saveToURL:_fileURL ofType:[self fileType] forSaveOperation:CPSaveOperation delegate:delegate didSaveSelector:didSaveSelector contextInfo:contextInfo];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -862,7 +874,7 @@ var CPDocumentUntitledCount = 0;
|
|||||||
[[CPDocumentController sharedDocumentController] removeDocument:self];
|
[[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))
|
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}];
|
[self canCloseDocumentWithDelegate:self shouldCloseSelector:@selector(_document:shouldClose:context:) contextInfo:{delegate:delegate, selector:selector, context:info}];
|
||||||
@@ -879,7 +891,7 @@ var CPDocumentUntitledCount = 0;
|
|||||||
objj_msgSend(context.delegate, context.selector, aDocument, shouldClose, context.context);
|
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])
|
if (![self isDocumentEdited])
|
||||||
return [aDelegate respondsToSelector:aSelector] && objj_msgSend(aDelegate, aSelector, self, YES, context);
|
return [aDelegate respondsToSelector:aSelector] && objj_msgSend(aDelegate, aSelector, self, YES, context);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
var CPSharedDocumentController = nil;
|
var CPSharedDocumentController = nil;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPDocumentController
|
@class CPDocumentController
|
||||||
This class is responsible for managing an application's open documents.
|
This class is responsible for managing an application's open documents.
|
||||||
@@ -38,10 +38,11 @@ var CPSharedDocumentController = nil;
|
|||||||
{
|
{
|
||||||
CPArray _documents;
|
CPArray _documents;
|
||||||
CPArray _documentTypes;
|
CPArray _documentTypes;
|
||||||
|
CPArray _localDocumentURLs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
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.
|
been created yet, it will be created then returned.
|
||||||
@return a CPDocumentController
|
@return a CPDocumentController
|
||||||
*/
|
*/
|
||||||
@@ -49,7 +50,7 @@ var CPSharedDocumentController = nil;
|
|||||||
{
|
{
|
||||||
if (!CPSharedDocumentController)
|
if (!CPSharedDocumentController)
|
||||||
[[self alloc] init];
|
[[self alloc] init];
|
||||||
|
|
||||||
return CPSharedDocumentController;
|
return CPSharedDocumentController;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,11 +63,27 @@ var CPSharedDocumentController = nil;
|
|||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_documents = [[CPArray alloc] init];
|
|
||||||
|
|
||||||
if (!CPSharedDocumentController)
|
if (!CPSharedDocumentController)
|
||||||
CPSharedDocumentController = self;
|
CPSharedDocumentController = self;
|
||||||
|
|
||||||
|
_localDocumentURLs = [CPSet set];
|
||||||
|
|
||||||
|
if (window.localStorage)
|
||||||
|
{
|
||||||
|
var localDocumentURLs = localStorage.getItem(CPDocumentControllerLocalDocumentURLsKey);
|
||||||
|
|
||||||
|
if (localDocumentURLs)
|
||||||
|
{
|
||||||
|
localDocumentURLs = JSON.parse(localDocumentURLs);
|
||||||
|
|
||||||
|
var count = [localDocumentURLs count];
|
||||||
|
|
||||||
|
while (count--)
|
||||||
|
[_localDocumentURLs addObject:new CFURL(localDocumentURLs[count])];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_documents = [];
|
||||||
_documentTypes = [[[CPBundle mainBundle] infoDictionary] objectForKey:@"CPBundleDocumentTypes"];
|
_documentTypes = [[[CPBundle mainBundle] infoDictionary] objectForKey:@"CPBundleDocumentTypes"];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
@@ -85,16 +102,16 @@ var CPSharedDocumentController = nil;
|
|||||||
{
|
{
|
||||||
var index = 0,
|
var index = 0,
|
||||||
count = [_documents count];
|
count = [_documents count];
|
||||||
|
|
||||||
for (; index < count; ++index)
|
for (; index < count; ++index)
|
||||||
{
|
{
|
||||||
var theDocument = _documents[index];
|
var theDocument = _documents[index];
|
||||||
|
|
||||||
if ([[theDocument fileURL] isEqual:aURL])
|
if ([[theDocument fileURL] isEqual:aURL])
|
||||||
return theDocument;
|
return theDocument;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -105,10 +122,10 @@ var CPSharedDocumentController = nil;
|
|||||||
- (void)openUntitledDocumentOfType:(CPString)aType display:(BOOL)shouldDisplay
|
- (void)openUntitledDocumentOfType:(CPString)aType display:(BOOL)shouldDisplay
|
||||||
{
|
{
|
||||||
var theDocument = [self makeUntitledDocumentOfType:aType error:nil];
|
var theDocument = [self makeUntitledDocumentOfType:aType error:nil];
|
||||||
|
|
||||||
if (theDocument)
|
if (theDocument)
|
||||||
[self addDocument:theDocument];
|
[self addDocument:theDocument];
|
||||||
|
|
||||||
if (shouldDisplay)
|
if (shouldDisplay)
|
||||||
{
|
{
|
||||||
[theDocument makeWindowControllers];
|
[theDocument makeWindowControllers];
|
||||||
@@ -210,7 +227,7 @@ var CPSharedDocumentController = nil;
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
[aDocument makeWindowControllers];
|
[aDocument makeWindowControllers];
|
||||||
|
|
||||||
if ([aContextInfo objectForKey:@"shouldDisplay"])
|
if ([aContextInfo objectForKey:@"shouldDisplay"])
|
||||||
[aDocument showWindows];
|
[aDocument showWindows];
|
||||||
}
|
}
|
||||||
@@ -219,12 +236,12 @@ var CPSharedDocumentController = nil;
|
|||||||
Opens a new document in the application.
|
Opens a new document in the application.
|
||||||
@param aSender the requesting object
|
@param aSender the requesting object
|
||||||
*/
|
*/
|
||||||
- (CFAction)newDocument:(id)aSender
|
- (@action)newDocument:(id)aSender
|
||||||
{
|
{
|
||||||
[self openUntitledDocumentOfType:[[_documentTypes objectAtIndex:0] objectForKey:@"CPBundleTypeName"] display:YES];
|
[self openUntitledDocumentOfType:[[_documentTypes objectAtIndex:0] objectForKey:@"CPBundleTypeName"] display:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)openDocument:(id)aSender
|
-(void)openDocument:(id)aSender
|
||||||
{
|
{
|
||||||
var openPanel = [CPOpenPanel openPanel];
|
var openPanel = [CPOpenPanel openPanel];
|
||||||
|
|
||||||
@@ -276,17 +293,17 @@ var CPSharedDocumentController = nil;
|
|||||||
{
|
{
|
||||||
var index = 0,
|
var index = 0,
|
||||||
count = _documentTypes.length,
|
count = _documentTypes.length,
|
||||||
|
|
||||||
extension = [[anAbsoluteURL pathExtension] lowercaseString],
|
extension = [[anAbsoluteURL pathExtension] lowercaseString],
|
||||||
starType = nil;
|
starType = nil;
|
||||||
|
|
||||||
for (; index < count; ++index)
|
for (; index < count; ++index)
|
||||||
{
|
{
|
||||||
var documentType = _documentTypes[index],
|
var documentType = _documentTypes[index],
|
||||||
extensions = [documentType objectForKey:@"CFBundleTypeExtensions"],
|
extensions = [documentType objectForKey:@"CFBundleTypeExtensions"],
|
||||||
extensionIndex = 0,
|
extensionIndex = 0,
|
||||||
extensionCount = extensions.length;
|
extensionCount = extensions.length;
|
||||||
|
|
||||||
for (; extensionIndex < extensionCount; ++extensionIndex)
|
for (; extensionIndex < extensionCount; ++extensionIndex)
|
||||||
{
|
{
|
||||||
var thisExtension = [extensions[extensionIndex] lowercaseString];
|
var thisExtension = [extensions[extensionIndex] lowercaseString];
|
||||||
@@ -312,11 +329,11 @@ var CPSharedDocumentController = nil;
|
|||||||
for (;i < count; ++i)
|
for (;i < count; ++i)
|
||||||
{
|
{
|
||||||
var documentType = _documentTypes[i];
|
var documentType = _documentTypes[i];
|
||||||
|
|
||||||
if ([documentType objectForKey:@"CPBundleTypeName"] == aType)
|
if ([documentType objectForKey:@"CPBundleTypeName"] == aType)
|
||||||
return documentType;
|
return documentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,7 +353,7 @@ var CPSharedDocumentController = nil;
|
|||||||
|
|
||||||
@implementation CPDocumentController (Closing)
|
@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 = {
|
var context = {
|
||||||
delegate: aDelegate,
|
delegate: aDelegate,
|
||||||
@@ -455,3 +472,41 @@ var CPSharedDocumentController = nil;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
var CPDocumentControllerLocalDocumentURLsKey = @"Cappuccino.CPDocumentController.documentURLs";
|
||||||
|
|
||||||
|
@implementation CPDocumentController (LocalStorage)
|
||||||
|
|
||||||
|
- (void)_addLocalDocumentURL:(CPURL)aURL
|
||||||
|
{
|
||||||
|
if (!window.localStorage)
|
||||||
|
return;
|
||||||
|
|
||||||
|
[_localDocumentURLs addObject:aURL];
|
||||||
|
|
||||||
|
var stringURLs = [],
|
||||||
|
URL = nil,
|
||||||
|
URLEnumerator = [_localDocumentURLs objectEnumerator];
|
||||||
|
|
||||||
|
while (URL = [URLEnumerator nextObject])
|
||||||
|
stringURLs.push(URL + "");
|
||||||
|
|
||||||
|
localStorage.setItem(CPDocumentControllerLocalDocumentURLsKey, JSON.stringify(stringURLs));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)_removeLocalDocumentURL:(CPURL)aURL
|
||||||
|
{
|
||||||
|
if (!window.localStorage)
|
||||||
|
return;
|
||||||
|
|
||||||
|
[_localDocumentURLs removeObject:aURL];
|
||||||
|
|
||||||
|
localStorage.setItem(CPDocumentControllerLocalDocumentURLsKey, JSON.stringify([self allObjects]));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CPSet)localDocumentURLs
|
||||||
|
{
|
||||||
|
return [_localDocumentURLs copy];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|||||||
+38
-100
@@ -20,12 +20,13 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@import "CPApplication.j"
|
@import <AppKit/CPView.j>
|
||||||
@import "CPEvent.j"
|
@import <AppKit/CPEvent.j>
|
||||||
@import "CPImageView.j"
|
@import <AppKit/CPPasteboard.j>
|
||||||
@import "CPPasteboard.j"
|
@import <AppKit/CPImageView.j>
|
||||||
@import "CPView.j"
|
|
||||||
@import "CPWindow.j"
|
#import "CoreGraphics/CGGeometry.h"
|
||||||
|
#import "Platform/Platform.h"
|
||||||
|
|
||||||
|
|
||||||
CPDragOperationNone = 0,
|
CPDragOperationNone = 0,
|
||||||
@@ -39,10 +40,29 @@ CPDragOperationEvery = -1;
|
|||||||
|
|
||||||
#define DRAGGING_WINDOW(anObject) ([anObject isKindOfClass:[CPWindow class]] ? anObject : [anObject window])
|
#define DRAGGING_WINDOW(anObject) ([anObject isKindOfClass:[CPWindow class]] ? anObject : [anObject window])
|
||||||
|
|
||||||
var CPDragServerPreviousEvent = nil,
|
var CPDragServerPreviousEvent = nil,
|
||||||
CPDragServerPeriodicUpdateInterval = 0.05;
|
CPDragServerAutoscrollInterval = nil;
|
||||||
|
/*
|
||||||
|
var CPDragServerAutoscroll = function()
|
||||||
|
{
|
||||||
|
[CPDragServerSource autoscroll:CPDragServerPreviousEvent];
|
||||||
|
}
|
||||||
|
|
||||||
var CPSharedDragServer = nil;
|
if (CPDragServerAutoscrollInterval === nil)
|
||||||
|
{
|
||||||
|
if ([CPDragServerSource respondsToSelector:@selector(autoscroll:)])
|
||||||
|
CPDragServerAutoscrollInterval = setInterval(CPDragServerAutoscroll, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
CPDragServerPreviousEvent = anEvent;
|
||||||
|
|
||||||
|
if (CPDragServerAutoscrollInterval !== nil)
|
||||||
|
clearInterval(CPDragServerAutoscrollInterval);
|
||||||
|
|
||||||
|
CPDragServerAutoscrollInterval = nil;
|
||||||
|
*/
|
||||||
|
|
||||||
|
var CPSharedDragServer = nil;
|
||||||
|
|
||||||
var CPDragServerSource = nil;
|
var CPDragServerSource = nil;
|
||||||
var CPDragServerDraggingInfo = nil;
|
var CPDragServerDraggingInfo = nil;
|
||||||
@@ -130,13 +150,10 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
|
|||||||
|
|
||||||
CGPoint _draggingLocation;
|
CGPoint _draggingLocation;
|
||||||
id _draggingDestination;
|
id _draggingDestination;
|
||||||
BOOL _draggingDestinationWantsPeriodicUpdates;
|
|
||||||
|
|
||||||
CGPoint _startDragLocation;
|
CGPoint _startDragLocation;
|
||||||
BOOL _shouldSlideBack;
|
BOOL _shouldSlideBack;
|
||||||
unsigned _dragOperation;
|
unsigned _dragOperation;
|
||||||
|
|
||||||
CPTimer _draggingUpdateTimer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -217,9 +234,6 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
|
|||||||
|
|
||||||
- (CPDragOperation)draggingUpdatedInPlatformWindow:(CPPlatformWindow)aPlatformWindow location:(CGPoint)aLocation
|
- (CPDragOperation)draggingUpdatedInPlatformWindow:(CPPlatformWindow)aPlatformWindow location:(CGPoint)aLocation
|
||||||
{
|
{
|
||||||
[_draggingUpdateTimer invalidate];
|
|
||||||
_draggingUpdateTimer = nil;
|
|
||||||
|
|
||||||
var dragOperation = CPDragOperationCopy;
|
var dragOperation = CPDragOperationCopy;
|
||||||
// We have to convert base to bridge since the drag event comes from the source window, not the drag window.
|
// We have to convert base to bridge since the drag event comes from the source window, not the drag window.
|
||||||
var draggingDestination = [aPlatformWindow _dragHitTest:aLocation pasteboard:[CPDragServerDraggingInfo draggingPasteboard]];
|
var draggingDestination = [aPlatformWindow _dragHitTest:aLocation pasteboard:[CPDragServerDraggingInfo draggingPasteboard]];
|
||||||
@@ -229,89 +243,25 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
|
|||||||
|
|
||||||
if(draggingDestination !== _draggingDestination)
|
if(draggingDestination !== _draggingDestination)
|
||||||
{
|
{
|
||||||
if ([_draggingDestination respondsToSelector:@selector(draggingExited:)])
|
if (_draggingDestination && [_draggingDestination respondsToSelector:@selector(draggingExited:)])
|
||||||
[_draggingDestination draggingExited:CPDragServerDraggingInfo];
|
[_draggingDestination draggingExited:CPDragServerDraggingInfo];
|
||||||
|
|
||||||
_draggingDestination = draggingDestination;
|
_draggingDestination = draggingDestination;
|
||||||
|
|
||||||
if ([_draggingDestination respondsToSelector:@selector(wantsPeriodicDraggingUpdates)])
|
if (_draggingDestination && [_draggingDestination respondsToSelector:@selector(draggingEntered:)])
|
||||||
_draggingDestinationWantsPeriodicUpdates = [_draggingDestination wantsPeriodicDraggingUpdates];
|
|
||||||
else
|
|
||||||
_draggingDestinationWantsPeriodicUpdates = YES;
|
|
||||||
|
|
||||||
if ([_draggingDestination respondsToSelector:@selector(draggingEntered:)])
|
|
||||||
dragOperation = [_draggingDestination draggingEntered:CPDragServerDraggingInfo];
|
dragOperation = [_draggingDestination draggingEntered:CPDragServerDraggingInfo];
|
||||||
}
|
}
|
||||||
else if ([_draggingDestination respondsToSelector:@selector(draggingUpdated:)])
|
else if (_draggingDestination && [_draggingDestination respondsToSelector:@selector(draggingUpdated:)])
|
||||||
dragOperation = [_draggingDestination draggingUpdated:CPDragServerDraggingInfo];
|
dragOperation = [_draggingDestination draggingUpdated:CPDragServerDraggingInfo];
|
||||||
|
|
||||||
if (!_draggingDestination)
|
if (!_draggingDestination)
|
||||||
dragOperation = CPDragOperationNone;
|
dragOperation = CPDragOperationNone;
|
||||||
else
|
|
||||||
{
|
|
||||||
if (_draggingDestinationWantsPeriodicUpdates)
|
|
||||||
_draggingUpdateTimer = [CPTimer scheduledTimerWithTimeInterval:CPDragServerPeriodicUpdateInterval
|
|
||||||
target:self
|
|
||||||
selector:@selector(_sendPeriodicDraggingUpdate:)
|
|
||||||
userInfo:[CPDictionary dictionaryWithJSObject:{platformWindow:aPlatformWindow, location:aLocation}]
|
|
||||||
repeats:NO];
|
|
||||||
|
|
||||||
var scrollView = [_draggingDestination isKindOfClass:[CPView class]] ? [_draggingDestination enclosingScrollView] : nil;
|
|
||||||
if (scrollView)
|
|
||||||
{
|
|
||||||
var contentView = [scrollView contentView],
|
|
||||||
bounds = [contentView bounds],
|
|
||||||
insetBounds = CGRectInset(bounds, 10, 10),
|
|
||||||
eventLocation = [contentView convertPoint:_draggingLocation fromView:nil],
|
|
||||||
deltaX = 0,
|
|
||||||
deltaY = 0;
|
|
||||||
|
|
||||||
if (!CGRectContainsPoint(insetBounds, eventLocation))
|
|
||||||
{
|
|
||||||
if ([scrollView hasVerticalScroller])
|
|
||||||
{
|
|
||||||
if (eventLocation.y < CGRectGetMinY(insetBounds))
|
|
||||||
deltaY = CGRectGetMinY(insetBounds) - eventLocation.y;
|
|
||||||
else if (eventLocation.y > CGRectGetMaxY(insetBounds))
|
|
||||||
deltaY = CGRectGetMaxY(insetBounds) - eventLocation.y;
|
|
||||||
if (deltaY < -insetBounds.size.height)
|
|
||||||
deltaY = -insetBounds.size.height;
|
|
||||||
if (deltaY > insetBounds.size.height)
|
|
||||||
deltaY = insetBounds.size.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ([scrollView hasHorizontalScroller])
|
|
||||||
{
|
|
||||||
if (eventLocation.x < CGRectGetMinX(insetBounds))
|
|
||||||
deltaX = CGRectGetMinX(insetBounds) - eventLocation.x;
|
|
||||||
else if (eventLocation.x > CGRectGetMaxX(insetBounds))
|
|
||||||
deltaX = CGRectGetMaxX(insetBounds) - eventLocation.x;
|
|
||||||
if (deltaX < -insetBounds.size.width)
|
|
||||||
deltaX = -insetBounds.size.width;
|
|
||||||
if (deltaX > insetBounds.size.width)
|
|
||||||
deltaX = insetBounds.size.width;
|
|
||||||
}
|
|
||||||
|
|
||||||
[contentView scrollToPoint:CGPointMake(bounds.origin.x - deltaX, bounds.origin.y - deltaY)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return dragOperation;
|
return dragOperation;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_sendPeriodicDraggingUpdate:(CPTimer)aTimer
|
|
||||||
{
|
|
||||||
var userInfo = [aTimer userInfo];
|
|
||||||
_dragOperation = [self draggingUpdatedInPlatformWindow:[userInfo objectForKey:@"platformWindow"]
|
|
||||||
location:[userInfo objectForKey:@"location"]];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)draggingEndedInPlatformWindow:(CPPlatformWindow)aPlatformWindow globalLocation:(CGPoint)aLocation operation:(CPDragOperation)anOperation
|
- (void)draggingEndedInPlatformWindow:(CPPlatformWindow)aPlatformWindow globalLocation:(CGPoint)aLocation operation:(CPDragOperation)anOperation
|
||||||
{
|
{
|
||||||
[_draggingUpdateTimer invalidate];
|
|
||||||
_draggingUpdateTimer = nil;
|
|
||||||
|
|
||||||
[_draggedView removeFromSuperview];
|
[_draggedView removeFromSuperview];
|
||||||
|
|
||||||
if (![CPPlatform supportsDragAndDrop])
|
if (![CPPlatform supportsDragAndDrop])
|
||||||
@@ -327,8 +277,8 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
|
|||||||
|
|
||||||
- (void)performDragOperationInPlatformWindow:(CPPlatformWindow)aPlatformWindow
|
- (void)performDragOperationInPlatformWindow:(CPPlatformWindow)aPlatformWindow
|
||||||
{
|
{
|
||||||
if (_draggingDestination &&
|
if (_draggingDestination &&
|
||||||
(![_draggingDestination respondsToSelector:@selector(prepareForDragOperation:)] || [_draggingDestination prepareForDragOperation:CPDragServerDraggingInfo]) &&
|
(![_draggingDestination respondsToSelector:@selector(prepareForDragOperation:)] || [_draggingDestination prepareForDragOperation:CPDragServerDraggingInfo]) &&
|
||||||
(![_draggingDestination respondsToSelector:@selector(performDragOperation:)] || [_draggingDestination performDragOperation:CPDragServerDraggingInfo]) &&
|
(![_draggingDestination respondsToSelector:@selector(performDragOperation:)] || [_draggingDestination performDragOperation:CPDragServerDraggingInfo]) &&
|
||||||
[_draggingDestination respondsToSelector:@selector(concludeDragOperation:)])
|
[_draggingDestination respondsToSelector:@selector(concludeDragOperation:)])
|
||||||
[_draggingDestination concludeDragOperation:CPDragServerDraggingInfo];
|
[_draggingDestination concludeDragOperation:CPDragServerDraggingInfo];
|
||||||
@@ -454,25 +404,13 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
|
|||||||
// Stop tracking events.
|
// Stop tracking events.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (type === CPKeyDown)
|
|
||||||
{
|
[self draggingSourceUpdatedWithGlobalLocation:platformWindowLocation];
|
||||||
var keyCode = [anEvent keyCode];
|
_dragOperation = [self draggingUpdatedInPlatformWindow:platformWindow location:platformWindowLocation];
|
||||||
if (keyCode === CPEscapeKeyCode)
|
|
||||||
{
|
|
||||||
_dragOperation = CPDragOperationNone;
|
|
||||||
[self draggingEndedInPlatformWindow:platformWindow globalLocation:CGPointMakeZero() operation:_dragOperation];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
[self draggingSourceUpdatedWithGlobalLocation:platformWindowLocation];
|
|
||||||
_dragOperation = [self draggingUpdatedInPlatformWindow:platformWindow location:platformWindowLocation];
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're not a mouse up, then we're going to want to grab the next event.
|
// If we're not a mouse up, then we're going to want to grab the next event.
|
||||||
[CPApp setTarget:self selector:@selector(trackDragging:)
|
[CPApp setTarget:self selector:@selector(trackDragging:)
|
||||||
forNextEventMatchingMask:CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPKeyDownMask
|
forNextEventMatchingMask:CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask
|
||||||
untilDate:nil inMode:0 dequeue:NO];
|
untilDate:nil inMode:0 dequeue:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+38
-165
@@ -21,7 +21,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
@import <Foundation/CPObject.j>
|
@import <Foundation/CPObject.j>
|
||||||
@import "CPText.j"
|
|
||||||
|
#include "CoreGraphics/CGGeometry.h"
|
||||||
|
|
||||||
|
|
||||||
CPLeftMouseDown = 1;
|
CPLeftMouseDown = 1;
|
||||||
@@ -40,7 +41,7 @@ CPAppKitDefined = 13;
|
|||||||
CPSystemDefined = 14;
|
CPSystemDefined = 14;
|
||||||
CPApplicationDefined = 15;
|
CPApplicationDefined = 15;
|
||||||
CPPeriodic = 16;
|
CPPeriodic = 16;
|
||||||
CPCursorUpdate = 17;
|
CPCursorUpdate = 17;
|
||||||
CPScrollWheel = 22;
|
CPScrollWheel = 22;
|
||||||
CPOtherMouseDown = 25;
|
CPOtherMouseDown = 25;
|
||||||
CPOtherMouseUp = 26;
|
CPOtherMouseUp = 26;
|
||||||
@@ -51,7 +52,8 @@ CPTouchStart = 28;
|
|||||||
CPTouchMove = 29;
|
CPTouchMove = 29;
|
||||||
CPTouchEnd = 30;
|
CPTouchEnd = 30;
|
||||||
CPTouchCancel = 31;
|
CPTouchCancel = 31;
|
||||||
|
|
||||||
|
|
||||||
CPAlphaShiftKeyMask = 1 << 16;
|
CPAlphaShiftKeyMask = 1 << 16;
|
||||||
CPShiftKeyMask = 1 << 17;
|
CPShiftKeyMask = 1 << 17;
|
||||||
CPControlKeyMask = 1 << 18;
|
CPControlKeyMask = 1 << 18;
|
||||||
@@ -85,102 +87,26 @@ CPPeriodicMask = 1 << CPPeriodic;
|
|||||||
CPScrollWheelMask = 1 << CPScrollWheel;
|
CPScrollWheelMask = 1 << CPScrollWheel;
|
||||||
CPAnyEventMask = 0xffffffff;
|
CPAnyEventMask = 0xffffffff;
|
||||||
|
|
||||||
CPUpArrowFunctionKey = "\uF700";
|
CPDOMEventDoubleClick = "dblclick",
|
||||||
CPDownArrowFunctionKey = "\uF701";
|
CPDOMEventMouseDown = "mousedown",
|
||||||
CPLeftArrowFunctionKey = "\uF702";
|
CPDOMEventMouseUp = "mouseup",
|
||||||
CPRightArrowFunctionKey = "\uF703";
|
CPDOMEventMouseMoved = "mousemove",
|
||||||
CPF1FunctionKey = "\uF704";
|
CPDOMEventMouseDragged = "mousedrag",
|
||||||
CPF2FunctionKey = "\uF705";
|
CPDOMEventKeyUp = "keyup",
|
||||||
CPF3FunctionKey = "\uF706";
|
CPDOMEventKeyDown = "keydown",
|
||||||
CPF4FunctionKey = "\uF707";
|
CPDOMEventKeyPress = "keypress";
|
||||||
CPF5FunctionKey = "\uF708";
|
CPDOMEventCopy = "copy";
|
||||||
CPF6FunctionKey = "\uF709";
|
CPDOMEventPaste = "paste";
|
||||||
CPF7FunctionKey = "\uF70A";
|
CPDOMEventScrollWheel = "mousewheel";
|
||||||
CPF8FunctionKey = "\uF70B";
|
CPDOMEventTouchStart = "touchstart";
|
||||||
CPF9FunctionKey = "\uF70C";
|
CPDOMEventTouchMove = "touchmove";
|
||||||
CPF10FunctionKey = "\uF70D";
|
CPDOMEventTouchEnd = "touchend";
|
||||||
CPF11FunctionKey = "\uF70E";
|
CPDOMEventTouchCancel = "touchcancel";
|
||||||
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";
|
|
||||||
|
|
||||||
var _CPEventPeriodicEventPeriod = 0,
|
var _CPEventPeriodicEventPeriod = 0,
|
||||||
_CPEventPeriodicEventTimer = nil,
|
_CPEventPeriodicEventTimer = nil;
|
||||||
_CPEventUpperCaseRegex = new RegExp("[A-Z]");
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPEvent
|
@class CPEvent
|
||||||
CPEvent encapsulates the details of a Cappuccino keyboard or mouse event.
|
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
|
characters:(CPString)characters charactersIgnoringModifiers:(CPString)unmodCharacters isARepeat:(BOOL)repeatKey keyCode:(unsigned short)code
|
||||||
{
|
{
|
||||||
return [[self alloc] _initKeyEventWithType:anEventType location:aPoint modifierFlags:modifierFlags
|
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];
|
characters:characters charactersIgnoringModifiers:unmodCharacters isARepeat:repeatKey keyCode:code];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +173,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
|||||||
@throws CPInternalInconsistencyException if an invalid event type is provided
|
@throws CPInternalInconsistencyException if an invalid event type is provided
|
||||||
@return the new mouse event
|
@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
|
timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext
|
||||||
eventNumber:(int)anEventNumber clickCount:(int)aClickCount pressure:(float)aPressure
|
eventNumber:(int)anEventNumber clickCount:(int)aClickCount pressure:(float)aPressure
|
||||||
{
|
{
|
||||||
@@ -278,12 +204,12 @@ var _CPEventPeriodicEventPeriod = 0,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* @ignore */
|
/* @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
|
timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext
|
||||||
eventNumber:(int)anEventNumber clickCount:(int)aClickCount pressure:(float)aPressure
|
eventNumber:(int)anEventNumber clickCount:(int)aClickCount pressure:(float)aPressure
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_type = anEventType;
|
_type = anEventType;
|
||||||
@@ -296,7 +222,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
|||||||
_pressure = aPressure;
|
_pressure = aPressure;
|
||||||
_window = [CPApp windowWithWindowNumber:aWindowNumber];
|
_window = [CPApp windowWithWindowNumber:aWindowNumber];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,7 +232,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
|||||||
characters:(CPString)characters charactersIgnoringModifiers:(CPString)unmodCharacters isARepeat:(BOOL)isARepeat keyCode:(unsigned short)code
|
characters:(CPString)characters charactersIgnoringModifiers:(CPString)unmodCharacters isARepeat:(BOOL)isARepeat keyCode:(unsigned short)code
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_type = anEventType;
|
_type = anEventType;
|
||||||
@@ -320,7 +246,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
|||||||
_keyCode = code;
|
_keyCode = code;
|
||||||
_windowNumber = aWindowNumber;
|
_windowNumber = aWindowNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,7 +256,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
|||||||
subtype:(short)aSubtype data1:(int)aData1 data2:(int)aData2
|
subtype:(short)aSubtype data1:(int)aData1 data2:(int)aData2
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_type = anEventType;
|
_type = anEventType;
|
||||||
@@ -341,7 +267,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
|||||||
_subtype = aSubtype;
|
_subtype = aSubtype;
|
||||||
_data1 = aData1;
|
_data1 = aData1;
|
||||||
_data2 = aData2;
|
_data2 = aData2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@@ -519,76 +445,23 @@ var _CPEventPeriodicEventPeriod = 0,
|
|||||||
return _deltaZ;
|
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
|
- (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?
|
// 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 aDelay the number of seconds before the first event
|
||||||
@param aPeriod the length of time in seconds between successive events
|
@param aPeriod the length of time in seconds between successive events
|
||||||
*/
|
*/
|
||||||
+ (void)startPeriodicEventsAfterDelay:(CPTimeInterval)aDelay withPeriod:(CPTimeInterval)aPeriod
|
+ (void)startPeriodicEventsAfterDelay:(CPTimeInterval)aDelay withPeriod:(CPTimeInterval)aPeriod
|
||||||
{
|
{
|
||||||
_CPEventPeriodicEventPeriod = aPeriod;
|
_CPEventPeriodicEventPeriod = aPeriod;
|
||||||
|
|
||||||
// FIXME: OH TIMERS!!!
|
// FIXME: OH TIMERS!!!
|
||||||
_CPEventPeriodicEventTimer = window.setTimeout(function() { _CPEventPeriodicEventTimer = window.setInterval(_CPEventFirePeriodEvent, aPeriod * 1000.0); }, aDelay * 1000.0);
|
_CPEventPeriodicEventTimer = window.setTimeout(function() { _CPEventPeriodicEventTimer = window.setInterval(_CPEventFirePeriodEvent, aPeriod * 1000.0); }, aDelay * 1000.0);
|
||||||
}
|
}
|
||||||
@@ -600,9 +473,9 @@ var _CPEventPeriodicEventPeriod = 0,
|
|||||||
{
|
{
|
||||||
if (_CPEventPeriodicEventTimer === nil)
|
if (_CPEventPeriodicEventTimer === nil)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
window.clearTimeout(_CPEventPeriodicEventTimer);
|
window.clearTimeout(_CPEventPeriodicEventTimer);
|
||||||
|
|
||||||
_CPEventPeriodicEventTimer = nil;
|
_CPEventPeriodicEventTimer = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
@import <Foundation/CPObject.j>
|
@import <Foundation/CPObject.j>
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPFlashMovie
|
@class CPFlashMovie
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
@import "CPFlashMovie.j"
|
@import "CPFlashMovie.j"
|
||||||
@import "CPView.j"
|
@import "CPView.j"
|
||||||
|
|
||||||
|
#include "Platform/Platform.h"
|
||||||
|
|
||||||
var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
|
var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
|
||||||
|
|
||||||
|
|||||||
+8
-73
@@ -20,12 +20,6 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* 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 = {},
|
var _CPFonts = {},
|
||||||
_CPFontSystemFontFace = @"Arial, sans-serif",
|
_CPFontSystemFontFace = @"Arial, sans-serif",
|
||||||
_CPWrapRegExp = new RegExp("\\s*,\\s*", "g");
|
_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 _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)]
|
#define _CPCachedFont(aName, aSize, isBold) _CPFonts[_CPCreateCSSString(aName, aSize, isBold)]
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPFont
|
@class CPFont
|
||||||
|
|
||||||
@@ -44,22 +38,11 @@ var _CPFonts = {},
|
|||||||
{
|
{
|
||||||
CPString _name;
|
CPString _name;
|
||||||
float _size;
|
float _size;
|
||||||
float _ascender;
|
|
||||||
float _descender;
|
|
||||||
float _lineHeight;
|
|
||||||
BOOL _isBold;
|
BOOL _isBold;
|
||||||
|
|
||||||
CPString _cssString;
|
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.
|
Returns a font with the specified name and size.
|
||||||
@param aName the name of the font
|
@param aName the name of the font
|
||||||
@@ -106,64 +89,25 @@ var _CPFonts = {},
|
|||||||
@ignore
|
@ignore
|
||||||
*/
|
*/
|
||||||
- (id)_initWithName:(CPString)aName size:(float)aSize bold:(BOOL)isBold
|
- (id)_initWithName:(CPString)aName size:(float)aSize bold:(BOOL)isBold
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_name = aName;
|
_name = aName;
|
||||||
_size = aSize;
|
_size = aSize;
|
||||||
_ascender = 0;
|
|
||||||
_descender = 0;
|
|
||||||
_lineHeight = 0;
|
|
||||||
_isBold = isBold;
|
_isBold = isBold;
|
||||||
|
|
||||||
_cssString = _CPCreateCSSString(_name, _size, _isBold);
|
_cssString = _CPCreateCSSString(_name, _size, _isBold);
|
||||||
|
|
||||||
_CPFonts[_cssString] = self;
|
_CPFonts[_cssString] = self;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns the distance of the longest ascender's top y-coordinate from the baseline (in CSS px)
|
Returns the font size (in points)
|
||||||
*/
|
|
||||||
- (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)
|
|
||||||
*/
|
*/
|
||||||
- (float)size
|
- (float)size
|
||||||
{
|
{
|
||||||
@@ -196,15 +140,6 @@ var _CPFonts = {},
|
|||||||
return [CPString stringWithFormat:@"%@ %@ %f pt.", [super description], [self familyName], [self size]];
|
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
|
@end
|
||||||
|
|
||||||
var CPFontNameKey = @"CPFontNameKey",
|
var CPFontNameKey = @"CPFontNameKey",
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
@import <Foundation/CPObject.j>
|
@import <Foundation/CPObject.j>
|
||||||
|
|
||||||
@import "CPFont.j"
|
@import <AppKit/CPFont.j>
|
||||||
|
|
||||||
|
|
||||||
var CPSharedFontManager = nil,
|
var CPSharedFontManager = nil,
|
||||||
|
|||||||
+15
-29
@@ -70,7 +70,7 @@ function CPPointMake(x, y)
|
|||||||
*/
|
*/
|
||||||
function CPRectInset(aRect, dX, dY)
|
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);
|
aRect.size.width - 2 * dX, aRect.size.height - 2*dY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,13 +96,13 @@ function CPRectIntegral(aRect)
|
|||||||
function CPRectIntersection(lhsRect, rhsRect)
|
function CPRectIntersection(lhsRect, rhsRect)
|
||||||
{
|
{
|
||||||
var intersection = CPRectMake(
|
var intersection = CPRectMake(
|
||||||
Math.max(CPRectGetMinX(lhsRect), CPRectGetMinX(rhsRect)),
|
Math.max(CPRectGetMinX(lhsRect), CPRectGetMinX(rhsRect)),
|
||||||
Math.max(CPRectGetMinY(lhsRect), CPRectGetMinY(rhsRect)),
|
Math.max(CPRectGetMinY(lhsRect), CPRectGetMinY(rhsRect)),
|
||||||
0, 0);
|
0, 0);
|
||||||
|
|
||||||
intersection.size.width = Math.min(CPRectGetMaxX(lhsRect), CPRectGetMaxX(rhsRect)) - CPRectGetMinX(intersection);
|
intersection.size.width = Math.min(CPRectGetMaxX(lhsRect), CPRectGetMaxX(rhsRect)) - CPRectGetMinX(intersection);
|
||||||
intersection.size.height = Math.min(CPRectGetMaxY(lhsRect), CPRectGetMaxY(rhsRect)) - CPRectGetMinY(intersection);
|
intersection.size.height = Math.min(CPRectGetMaxY(lhsRect), CPRectGetMaxY(rhsRect)) - CPRectGetMinY(intersection);
|
||||||
|
|
||||||
return CPRectIsEmpty(intersection) ? CPRectMakeZero() : intersection;
|
return CPRectIsEmpty(intersection) ? CPRectMakeZero() : intersection;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,13 +160,13 @@ function CPRectStandardize(aRect)
|
|||||||
standardized.origin.x += width;
|
standardized.origin.x += width;
|
||||||
standardized.size.width = -width;
|
standardized.size.width = -width;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (height < 0.0)
|
if (height < 0.0)
|
||||||
{
|
{
|
||||||
standardized.origin.y += height;
|
standardized.origin.y += height;
|
||||||
standardized.size.height = -height;
|
standardized.size.height = -height;
|
||||||
}
|
}
|
||||||
|
|
||||||
return standardized;
|
return standardized;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +183,7 @@ function CPRectUnion(lhsRect, rhsRect)
|
|||||||
minY = Math.min(CPRectGetMinY(lhsRect), CPRectGetMinY(rhsRect)),
|
minY = Math.min(CPRectGetMinY(lhsRect), CPRectGetMinY(rhsRect)),
|
||||||
maxX = Math.max(CPRectGetMaxX(lhsRect), CPRectGetMaxX(rhsRect)),
|
maxX = Math.max(CPRectGetMaxX(lhsRect), CPRectGetMaxX(rhsRect)),
|
||||||
maxY = Math.max(CPRectGetMaxY(lhsRect), CPRectGetMaxY(rhsRect));
|
maxY = Math.max(CPRectGetMaxY(lhsRect), CPRectGetMaxY(rhsRect));
|
||||||
|
|
||||||
return CPRectMake(minX, minY, maxX - minX, maxY - minY);
|
return CPRectMake(minX, minY, maxX - minX, maxY - minY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,8 +222,8 @@ function CPRectContainsPoint(aRect, aPoint)
|
|||||||
{
|
{
|
||||||
return aPoint.x >= CPRectGetMinX(aRect) &&
|
return aPoint.x >= CPRectGetMinX(aRect) &&
|
||||||
aPoint.y >= CPRectGetMinY(aRect) &&
|
aPoint.y >= CPRectGetMinY(aRect) &&
|
||||||
aPoint.x < CPRectGetMaxX(aRect) &&
|
aPoint.x < CPRectGetMaxX(aRect) &&
|
||||||
aPoint.y < CPRectGetMaxY(aRect);
|
aPoint.y < CPRectGetMaxY(aRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -261,7 +261,7 @@ function CPPointEqualToPoint(lhsPoint, rhsPoint)
|
|||||||
*/
|
*/
|
||||||
function CPRectEqualToRect(lhsRect, rhsRect)
|
function CPRectEqualToRect(lhsRect, rhsRect)
|
||||||
{
|
{
|
||||||
return CPPointEqualToPoint(lhsRect.origin, rhsRect.origin) &&
|
return CPPointEqualToPoint(lhsRect.origin, rhsRect.origin) &&
|
||||||
CPSizeEqualToSize(lhsRect.size, rhsRect.size);
|
CPSizeEqualToSize(lhsRect.size, rhsRect.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,20 +380,6 @@ function CPRectIsNull(aRect)
|
|||||||
return aRect.size.width <= 0.0 || aRect.size.height <= 0.0;
|
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.
|
Returns \c YES if the two CGSizes are identical.
|
||||||
@group CGSize
|
@group CGSize
|
||||||
@@ -448,7 +434,7 @@ function CPStringFromRect(aRect)
|
|||||||
function CPPointFromString(aString)
|
function CPPointFromString(aString)
|
||||||
{
|
{
|
||||||
var comma = aString.indexOf(',');
|
var comma = aString.indexOf(',');
|
||||||
|
|
||||||
return { x:parseFloat(aString.substr(1, comma - 1), 10), y:parseFloat(aString.substring(comma + 1, aString.length), 10) };
|
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)
|
function CPSizeFromString(aString)
|
||||||
{
|
{
|
||||||
var comma = aString.indexOf(',');
|
var comma = aString.indexOf(',');
|
||||||
|
|
||||||
return { width:parseFloat(aString.substr(1, comma - 1), 10), height:parseFloat(aString.substring(comma + 1, aString.length), 10) };
|
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)
|
function CPRectFromString(aString)
|
||||||
{
|
{
|
||||||
var comma = aString.indexOf(',', aString.indexOf(',') + 1);
|
var comma = aString.indexOf(',', aString.indexOf(',') + 1);
|
||||||
|
|
||||||
return { origin:CPPointFromString(aString.substr(1, comma - 1)), size:CPSizeFromString(aString.substring(comma + 2, aString.length)) };
|
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);
|
return CPPointMake(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@}
|
@}
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -20,11 +20,6 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@import <Foundation/CPObject.j>
|
|
||||||
|
|
||||||
@import "CGContext.j"
|
|
||||||
|
|
||||||
|
|
||||||
var CPGraphicsContextCurrent = nil;
|
var CPGraphicsContextCurrent = nil;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|||||||
+6
-9
@@ -28,6 +28,8 @@
|
|||||||
|
|
||||||
@import "CPGeometry.j"
|
@import "CPGeometry.j"
|
||||||
|
|
||||||
|
#include "Platform/Platform.h"
|
||||||
|
|
||||||
|
|
||||||
CPImageLoadStatusInitialized = 0;
|
CPImageLoadStatusInitialized = 0;
|
||||||
CPImageLoadStatusLoading = 1;
|
CPImageLoadStatusLoading = 1;
|
||||||
@@ -191,9 +193,6 @@ function CPAppKitImage(aFilename, aSize)
|
|||||||
|
|
||||||
var imageOrSize = AppKitImageForNames[aName];
|
var imageOrSize = AppKitImageForNames[aName];
|
||||||
|
|
||||||
if (!imageOrSize)
|
|
||||||
return nil;
|
|
||||||
|
|
||||||
if (!imageOrSize.isa)
|
if (!imageOrSize.isa)
|
||||||
{
|
{
|
||||||
imageOrSize = CPAppKitImage("CPImage/" + aName + ".png", imageOrSize);
|
imageOrSize = CPAppKitImage("CPImage/" + aName + ".png", imageOrSize);
|
||||||
@@ -206,19 +205,17 @@ function CPAppKitImage(aFilename, aSize)
|
|||||||
return imageOrSize;
|
return imageOrSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)setName:(CPString)aName
|
- (void)setName:(CPString)aName
|
||||||
{
|
{
|
||||||
if (_name === aName)
|
if (_name === aName)
|
||||||
return YES;
|
return;
|
||||||
|
|
||||||
if (imagesForNames[aName])
|
if (imagesForNames[aName] === self)
|
||||||
return NO;
|
imagesForNames[aName] = nil;
|
||||||
|
|
||||||
_name = aName;
|
_name = aName;
|
||||||
|
|
||||||
imagesForNames[aName] = self;
|
imagesForNames[aName] = self;
|
||||||
|
|
||||||
return YES;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CPString)name
|
- (CPString)name
|
||||||
|
|||||||
+18
-99
@@ -26,23 +26,16 @@
|
|||||||
@import "CPImage.j"
|
@import "CPImage.j"
|
||||||
@import "CPShadowView.j"
|
@import "CPShadowView.j"
|
||||||
|
|
||||||
|
#include "Platform/Platform.h"
|
||||||
|
#include "Platform/DOM/CPDOMDisplayServer.h"
|
||||||
|
|
||||||
|
#include "CoreGraphics/CGGeometry.h"
|
||||||
|
|
||||||
CPScaleProportionally = 0;
|
CPScaleProportionally = 0;
|
||||||
CPScaleToFit = 1;
|
CPScaleToFit = 1;
|
||||||
CPScaleNone = 2;
|
CPScaleNone = 2;
|
||||||
|
|
||||||
CPImageAlignCenter = 0;
|
var CPImageViewShadowBackgroundColor = nil;
|
||||||
CPImageAlignTop = 1;
|
|
||||||
CPImageAlignTopLeft = 2;
|
|
||||||
CPImageAlignTopRight = 3;
|
|
||||||
CPImageAlignLeft = 4;
|
|
||||||
CPImageAlignBottom = 5;
|
|
||||||
CPImageAlignBottomLeft = 6;
|
|
||||||
CPImageAlignBottomRight = 7;
|
|
||||||
CPImageAlignRight = 8;
|
|
||||||
|
|
||||||
var CPImageViewShadowBackgroundColor = nil,
|
|
||||||
CPImageViewEmptyPlaceholderImage = nil;
|
|
||||||
|
|
||||||
var LEFT_SHADOW_INSET = 3.0,
|
var LEFT_SHADOW_INSET = 3.0,
|
||||||
RIGHT_SHADOW_INSET = 3.0,
|
RIGHT_SHADOW_INSET = 3.0,
|
||||||
@@ -59,22 +52,14 @@ var LEFT_SHADOW_INSET = 3.0,
|
|||||||
*/
|
*/
|
||||||
@implementation CPImageView : CPControl
|
@implementation CPImageView : CPControl
|
||||||
{
|
{
|
||||||
DOMElement _DOMImageElement;
|
DOMElement _DOMImageElement;
|
||||||
|
|
||||||
BOOL _hasShadow;
|
BOOL _hasShadow;
|
||||||
CPView _shadowView;
|
CPView _shadowView;
|
||||||
|
|
||||||
BOOL _isEditable;
|
BOOL _isEditable;
|
||||||
|
|
||||||
CGRect _imageRect;
|
CGRect _imageRect;
|
||||||
CPImageAlignment _imageAlignment;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (void)initialize
|
|
||||||
{
|
|
||||||
var bundle = [CPBundle bundleForClass:[CPView class]];
|
|
||||||
|
|
||||||
CPImageViewEmptyPlaceholderImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"empty.png"]];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithFrame:(CGRect)aFrame
|
- (id)initWithFrame:(CGRect)aFrame
|
||||||
@@ -135,7 +120,7 @@ var LEFT_SHADOW_INSET = 3.0,
|
|||||||
var newImage = [self objectValue];
|
var newImage = [self objectValue];
|
||||||
|
|
||||||
#if PLATFORM(DOM)
|
#if PLATFORM(DOM)
|
||||||
_DOMImageElement.src = newImage ? [newImage filename] : [CPImageViewEmptyPlaceholderImage filename];
|
_DOMImageElement.src = newImage ? [newImage filename] : "";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var size = [newImage size];
|
var size = [newImage size];
|
||||||
@@ -206,30 +191,6 @@ var LEFT_SHADOW_INSET = 3.0,
|
|||||||
[self hideOrDisplayContents];
|
[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
|
Sets the type of image scaling that should be used to
|
||||||
render the image.
|
render the image.
|
||||||
@@ -357,45 +318,8 @@ var LEFT_SHADOW_INSET = 3.0,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
var x, y;
|
var x = (boundsWidth - width) / 2.0,
|
||||||
|
y = (boundsHeight - height) / 2.0;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if PLATFORM(DOM)
|
#if PLATFORM(DOM)
|
||||||
CPDOMDisplayServerSetStyleLeftTop(_DOMImageElement, NULL, x, y);
|
CPDOMDisplayServerSetStyleLeftTop(_DOMImageElement, NULL, x, y);
|
||||||
@@ -441,7 +365,7 @@ var LEFT_SHADOW_INSET = 3.0,
|
|||||||
return _isEditable;
|
return _isEditable;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)performDragOperation:(CPDraggingInfo)aSender
|
- (void)performDragOperation:(CPDraggingInfo)aSender
|
||||||
{
|
{
|
||||||
var images = [CPKeyedUnarchiver unarchiveObjectWithData:[[aSender draggingPasteboard] dataForType:CPImagesPboardType]];
|
var images = [CPKeyedUnarchiver unarchiveObjectWithData:[[aSender draggingPasteboard] dataForType:CPImagesPboardType]];
|
||||||
|
|
||||||
@@ -450,17 +374,14 @@ var LEFT_SHADOW_INSET = 3.0,
|
|||||||
[self setImage:images[0]];
|
[self setImage:images[0]];
|
||||||
[self sendAction:[self action] to:[self target]];
|
[self sendAction:[self action] to:[self target]];
|
||||||
}
|
}
|
||||||
|
|
||||||
return YES;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
var CPImageViewImageKey = @"CPImageViewImageKey",
|
var CPImageViewImageKey = @"CPImageViewImageKey",
|
||||||
CPImageViewImageScalingKey = @"CPImageViewImageScalingKey",
|
CPImageViewImageScalingKey = @"CPImageViewImageScalingKey",
|
||||||
CPImageViewImageAlignmentKey = @"CPImageViewImageAlignmentKey",
|
CPImageViewHasShadowKey = @"CPImageViewHasShadowKey",
|
||||||
CPImageViewHasShadowKey = @"CPImageViewHasShadowKey",
|
CPImageViewIsEditableKey = @"CPImageViewIsEditableKey";
|
||||||
CPImageViewIsEditableKey = @"CPImageViewIsEditableKey";
|
|
||||||
|
|
||||||
@implementation CPImageView (CPCoding)
|
@implementation CPImageView (CPCoding)
|
||||||
|
|
||||||
@@ -493,7 +414,6 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
[self setHasShadow:[aCoder decodeBoolForKey:CPImageViewHasShadowKey]];
|
[self setHasShadow:[aCoder decodeBoolForKey:CPImageViewHasShadowKey]];
|
||||||
[self setImageAlignment:[aCoder decodeIntForKey:CPImageViewImageAlignmentKey]];
|
|
||||||
|
|
||||||
if ([aCoder decodeBoolForKey:CPImageViewIsEditableKey] || NO)
|
if ([aCoder decodeBoolForKey:CPImageViewIsEditableKey] || NO)
|
||||||
[self setEditable:YES];
|
[self setEditable:YES];
|
||||||
@@ -528,7 +448,6 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
|
|||||||
_subviews = actualSubviews;
|
_subviews = actualSubviews;
|
||||||
|
|
||||||
[aCoder encodeBool:_hasShadow forKey:CPImageViewHasShadowKey];
|
[aCoder encodeBool:_hasShadow forKey:CPImageViewHasShadowKey];
|
||||||
[aCoder encodeInt:_imageAlignment forKey:CPImageViewImageAlignmentKey];
|
|
||||||
|
|
||||||
if (_isEditable)
|
if (_isEditable)
|
||||||
[aCoder encodeBool:_isEditable forKey:CPImageViewIsEditableKey];
|
[aCoder encodeBool:_isEditable forKey:CPImageViewIsEditableKey];
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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
-58
@@ -31,6 +31,9 @@
|
|||||||
@import "CPMenuItem.j"
|
@import "CPMenuItem.j"
|
||||||
@import "CPPanel.j"
|
@import "CPPanel.j"
|
||||||
|
|
||||||
|
#include "../CoreGraphics/CGGeometry.h"
|
||||||
|
#include "../Platform/Platform.h"
|
||||||
|
|
||||||
|
|
||||||
CPMenuDidAddItemNotification = @"CPMenuDidAddItemNotification";
|
CPMenuDidAddItemNotification = @"CPMenuDidAddItemNotification";
|
||||||
CPMenuDidChangeItemNotification = @"CPMenuDidChangeItemNotification";
|
CPMenuDidChangeItemNotification = @"CPMenuDidChangeItemNotification";
|
||||||
@@ -47,11 +50,11 @@ var _CPMenuBarVisible = NO,
|
|||||||
_CPMenuBarAttributes = nil,
|
_CPMenuBarAttributes = nil,
|
||||||
_CPMenuBarSharedWindow = nil;
|
_CPMenuBarSharedWindow = nil;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPMenu
|
@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.
|
and so a heirarchical structure appears.
|
||||||
*/
|
*/
|
||||||
@implementation CPMenu : CPObject
|
@implementation CPMenu : CPObject
|
||||||
@@ -66,13 +69,13 @@ var _CPMenuBarVisible = NO,
|
|||||||
float _minimumWidth;
|
float _minimumWidth;
|
||||||
|
|
||||||
CPMutableArray _items;
|
CPMutableArray _items;
|
||||||
|
|
||||||
BOOL _autoenablesItems;
|
BOOL _autoenablesItems;
|
||||||
BOOL _showsStateColumn;
|
BOOL _showsStateColumn;
|
||||||
|
|
||||||
id _delegate;
|
id _delegate;
|
||||||
|
|
||||||
int _highlightedIndex;
|
CPMenuItem _highlightedIndex;
|
||||||
_CPMenuWindow _menuWindow;
|
_CPMenuWindow _menuWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +95,7 @@ var _CPMenuBarVisible = NO,
|
|||||||
{
|
{
|
||||||
if (_CPMenuBarVisible === menuBarShouldBeVisible)
|
if (_CPMenuBarVisible === menuBarShouldBeVisible)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_CPMenuBarVisible = menuBarShouldBeVisible;
|
_CPMenuBarVisible = menuBarShouldBeVisible;
|
||||||
|
|
||||||
if ([CPPlatform supportsNativeMainMenu])
|
if ([CPPlatform supportsNativeMainMenu])
|
||||||
@@ -102,13 +105,13 @@ var _CPMenuBarVisible = NO,
|
|||||||
{
|
{
|
||||||
if (!_CPMenuBarSharedWindow)
|
if (!_CPMenuBarSharedWindow)
|
||||||
_CPMenuBarSharedWindow = [[_CPMenuBarWindow alloc] init];
|
_CPMenuBarSharedWindow = [[_CPMenuBarWindow alloc] init];
|
||||||
|
|
||||||
[_CPMenuBarSharedWindow setMenu:[CPApp mainMenu]];
|
[_CPMenuBarSharedWindow setMenu:[CPApp mainMenu]];
|
||||||
|
|
||||||
[_CPMenuBarSharedWindow setTitle:_CPMenuBarTitle];
|
[_CPMenuBarSharedWindow setTitle:_CPMenuBarTitle];
|
||||||
[_CPMenuBarSharedWindow setIconImage:_CPMenuBarIconImage];
|
[_CPMenuBarSharedWindow setIconImage:_CPMenuBarIconImage];
|
||||||
[_CPMenuBarSharedWindow setIconImageAlphaValue:_CPMenuBarIconImageAlphaValue];
|
[_CPMenuBarSharedWindow setIconImageAlphaValue:_CPMenuBarIconImageAlphaValue];
|
||||||
|
|
||||||
[_CPMenuBarSharedWindow setColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarBackgroundColor"]];
|
[_CPMenuBarSharedWindow setColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarBackgroundColor"]];
|
||||||
[_CPMenuBarSharedWindow setTextColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTextColor"]];
|
[_CPMenuBarSharedWindow setTextColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTextColor"]];
|
||||||
[_CPMenuBarSharedWindow setTitleColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTitleColor"]];
|
[_CPMenuBarSharedWindow setTitleColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarTitleColor"]];
|
||||||
@@ -117,12 +120,12 @@ var _CPMenuBarVisible = NO,
|
|||||||
[_CPMenuBarSharedWindow setHighlightColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightColor"]];
|
[_CPMenuBarSharedWindow setHighlightColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightColor"]];
|
||||||
[_CPMenuBarSharedWindow setHighlightTextColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightTextColor"]];
|
[_CPMenuBarSharedWindow setHighlightTextColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightTextColor"]];
|
||||||
[_CPMenuBarSharedWindow setHighlightTextShadowColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightTextShadowColor"]];
|
[_CPMenuBarSharedWindow setHighlightTextShadowColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarHighlightTextShadowColor"]];
|
||||||
|
|
||||||
[_CPMenuBarSharedWindow orderFront:self];
|
[_CPMenuBarSharedWindow orderFront:self];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
[_CPMenuBarSharedWindow orderOut:self];
|
[_CPMenuBarSharedWindow orderOut:self];
|
||||||
|
|
||||||
// FIXME: There must be a better way to do this.
|
// FIXME: There must be a better way to do this.
|
||||||
#if PLATFORM(DOM)
|
#if PLATFORM(DOM)
|
||||||
[[CPPlatformWindow primaryPlatformWindow] resizeEvent:nil];
|
[[CPPlatformWindow primaryPlatformWindow] resizeEvent:nil];
|
||||||
@@ -156,9 +159,9 @@ var _CPMenuBarVisible = NO,
|
|||||||
{
|
{
|
||||||
if (_CPMenuBarAttributes == attributes)
|
if (_CPMenuBarAttributes == attributes)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_CPMenuBarAttributes = [attributes copy];
|
_CPMenuBarAttributes = [attributes copy];
|
||||||
|
|
||||||
var textColor = [attributes objectForKey:@"CPMenuBarTextColor"],
|
var textColor = [attributes objectForKey:@"CPMenuBarTextColor"],
|
||||||
titleColor = [attributes objectForKey:@"CPMenuBarTitleColor"],
|
titleColor = [attributes objectForKey:@"CPMenuBarTitleColor"],
|
||||||
textShadowColor = [attributes objectForKey:@"CPMenuBarTextShadowColor"],
|
textShadowColor = [attributes objectForKey:@"CPMenuBarTextShadowColor"],
|
||||||
@@ -166,40 +169,40 @@ var _CPMenuBarVisible = NO,
|
|||||||
highlightColor = [attributes objectForKey:@"CPMenuBarHighlightColor"],
|
highlightColor = [attributes objectForKey:@"CPMenuBarHighlightColor"],
|
||||||
highlightTextColor = [attributes objectForKey:@"CPMenuBarHighlightTextColor"],
|
highlightTextColor = [attributes objectForKey:@"CPMenuBarHighlightTextColor"],
|
||||||
highlightTextShadowColor = [attributes objectForKey:@"CPMenuBarHighlightTextShadowColor"];
|
highlightTextShadowColor = [attributes objectForKey:@"CPMenuBarHighlightTextShadowColor"];
|
||||||
|
|
||||||
if (!textColor && titleColor)
|
if (!textColor && titleColor)
|
||||||
[_CPMenuBarAttributes setObject:titleColor forKey:@"CPMenuBarTextColor"];
|
[_CPMenuBarAttributes setObject:titleColor forKey:@"CPMenuBarTextColor"];
|
||||||
|
|
||||||
else if (textColor && !titleColor)
|
else if (textColor && !titleColor)
|
||||||
[_CPMenuBarAttributes setObject:textColor forKey:@"CPMenuBarTitleColor"];
|
[_CPMenuBarAttributes setObject:textColor forKey:@"CPMenuBarTitleColor"];
|
||||||
|
|
||||||
else if (!textColor && !titleColor)
|
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:@"CPMenuBarTextColor"];
|
||||||
[_CPMenuBarAttributes setObject:[CPColor colorWithRed:0.051 green:0.2 blue:0.275 alpha:1.0] forKey:@"CPMenuBarTitleColor"];
|
[_CPMenuBarAttributes setObject:[CPColor colorWithRed:0.051 green:0.2 blue:0.275 alpha:1.0] forKey:@"CPMenuBarTitleColor"];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!textShadowColor && titleShadowColor)
|
if (!textShadowColor && titleShadowColor)
|
||||||
[_CPMenuBarAttributes setObject:titleShadowColor forKey:@"CPMenuBarTextShadowColor"];
|
[_CPMenuBarAttributes setObject:titleShadowColor forKey:@"CPMenuBarTextShadowColor"];
|
||||||
|
|
||||||
else if (textShadowColor && !titleShadowColor)
|
else if (textShadowColor && !titleShadowColor)
|
||||||
[_CPMenuBarAttributes setObject:textShadowColor forKey:@"CPMenuBarTitleShadowColor"];
|
[_CPMenuBarAttributes setObject:textShadowColor forKey:@"CPMenuBarTitleShadowColor"];
|
||||||
|
|
||||||
else if (!textShadowColor && !titleShadowColor)
|
else if (!textShadowColor && !titleShadowColor)
|
||||||
{
|
{
|
||||||
[_CPMenuBarAttributes setObject:[CPColor whiteColor] forKey:@"CPMenuBarTextShadowColor"];
|
[_CPMenuBarAttributes setObject:[CPColor whiteColor] forKey:@"CPMenuBarTextShadowColor"];
|
||||||
[_CPMenuBarAttributes setObject:[CPColor whiteColor] forKey:@"CPMenuBarTitleShadowColor"];
|
[_CPMenuBarAttributes setObject:[CPColor whiteColor] forKey:@"CPMenuBarTitleShadowColor"];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!highlightColor)
|
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"];
|
[_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)
|
if (!highlightTextColor)
|
||||||
[_CPMenuBarAttributes setObject:[CPColor whiteColor] forKey:@"CPMenuBarHighlightTextColor"];
|
[_CPMenuBarAttributes setObject:[CPColor whiteColor] forKey:@"CPMenuBarHighlightTextColor"];
|
||||||
|
|
||||||
if (!highlightTextShadowColor)
|
if (!highlightTextShadowColor)
|
||||||
[_CPMenuBarAttributes setObject:[CPColor blackColor] forKey:@"CPMenuBarHighlightTextShadowColor"];
|
[_CPMenuBarAttributes setObject:[CPColor blackColor] forKey:@"CPMenuBarHighlightTextShadowColor"];
|
||||||
|
|
||||||
if (_CPMenuBarSharedWindow)
|
if (_CPMenuBarSharedWindow)
|
||||||
{
|
{
|
||||||
[_CPMenuBarSharedWindow setColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarBackgroundColor"]];
|
[_CPMenuBarSharedWindow setColor:[_CPMenuBarAttributes objectForKey:@"CPMenuBarBackgroundColor"]];
|
||||||
@@ -228,7 +231,7 @@ var _CPMenuBarVisible = NO,
|
|||||||
{
|
{
|
||||||
if (self === [CPApp mainMenu])
|
if (self === [CPApp mainMenu])
|
||||||
return MENUBAR_HEIGHT;
|
return MENUBAR_HEIGHT;
|
||||||
|
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,18 +249,18 @@ var _CPMenuBarVisible = NO,
|
|||||||
- (id)initWithTitle:(CPString)aTitle
|
- (id)initWithTitle:(CPString)aTitle
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_title = aTitle;
|
_title = aTitle;
|
||||||
_items = [];
|
_items = [];
|
||||||
|
|
||||||
_autoenablesItems = YES;
|
_autoenablesItems = YES;
|
||||||
_showsStateColumn = YES;
|
_showsStateColumn = YES;
|
||||||
|
|
||||||
[self setMinimumWidth:0];
|
[self setMinimumWidth:0];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,7 +287,7 @@ var _CPMenuBarVisible = NO,
|
|||||||
|
|
||||||
[aMenuItem setMenu:self];
|
[aMenuItem setMenu:self];
|
||||||
[_items insertObject:aMenuItem atIndex:anIndex];
|
[_items insertObject:aMenuItem atIndex:anIndex];
|
||||||
|
|
||||||
[[CPNotificationCenter defaultCenter]
|
[[CPNotificationCenter defaultCenter]
|
||||||
postNotificationName:CPMenuDidAddItemNotification
|
postNotificationName:CPMenuDidAddItemNotification
|
||||||
object:self
|
object:self
|
||||||
@@ -303,7 +306,7 @@ var _CPMenuBarVisible = NO,
|
|||||||
- (CPMenuItem)insertItemWithTitle:(CPString)aTitle action:(SEL)anAction keyEquivalent:(CPString)aKeyEquivalent atIndex:(unsigned)anIndex
|
- (CPMenuItem)insertItemWithTitle:(CPString)aTitle action:(SEL)anAction keyEquivalent:(CPString)aKeyEquivalent atIndex:(unsigned)anIndex
|
||||||
{
|
{
|
||||||
var item = [[CPMenuItem alloc] initWithTitle:aTitle action:anAction keyEquivalent:aKeyEquivalent];
|
var item = [[CPMenuItem alloc] initWithTitle:aTitle action:anAction keyEquivalent:aKeyEquivalent];
|
||||||
|
|
||||||
[self insertItem:item atIndex:anIndex];
|
[self insertItem:item atIndex:anIndex];
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
@@ -348,10 +351,10 @@ var _CPMenuBarVisible = NO,
|
|||||||
{
|
{
|
||||||
if (anIndex < 0 || anIndex >= _items.length)
|
if (anIndex < 0 || anIndex >= _items.length)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[_items[anIndex] setMenu:nil];
|
[_items[anIndex] setMenu:nil];
|
||||||
[_items removeObjectAtIndex:anIndex];
|
[_items removeObjectAtIndex:anIndex];
|
||||||
|
|
||||||
[[CPNotificationCenter defaultCenter]
|
[[CPNotificationCenter defaultCenter]
|
||||||
postNotificationName:CPMenuDidRemoveItemNotification
|
postNotificationName:CPMenuDidRemoveItemNotification
|
||||||
object:self
|
object:self
|
||||||
@@ -366,7 +369,7 @@ var _CPMenuBarVisible = NO,
|
|||||||
{
|
{
|
||||||
if ([aMenuItem menu] != self)
|
if ([aMenuItem menu] != self)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[[CPNotificationCenter defaultCenter]
|
[[CPNotificationCenter defaultCenter]
|
||||||
postNotificationName:CPMenuDidChangeItemNotification
|
postNotificationName:CPMenuDidChangeItemNotification
|
||||||
object:self
|
object:self
|
||||||
@@ -382,10 +385,10 @@ var _CPMenuBarVisible = NO,
|
|||||||
- (CPMenuItem)itemWithTag:(int)aTag
|
- (CPMenuItem)itemWithTag:(int)aTag
|
||||||
{
|
{
|
||||||
var index = [self indexOfItemWithTag:aTag];
|
var index = [self indexOfItemWithTag:aTag];
|
||||||
|
|
||||||
if (index == CPNotFound)
|
if (index == CPNotFound)
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
return _items[index];
|
return _items[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,10 +400,10 @@ var _CPMenuBarVisible = NO,
|
|||||||
- (CPMenuItem)itemWithTitle:(CPString)aTitle
|
- (CPMenuItem)itemWithTitle:(CPString)aTitle
|
||||||
{
|
{
|
||||||
var index = [self indexOfItemWithTitle:aTitle];
|
var index = [self indexOfItemWithTitle:aTitle];
|
||||||
|
|
||||||
if (index == CPNotFound)
|
if (index == CPNotFound)
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
return _items[index];
|
return _items[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,7 +442,7 @@ var _CPMenuBarVisible = NO,
|
|||||||
{
|
{
|
||||||
if ([aMenuItem menu] !== self)
|
if ([aMenuItem menu] !== self)
|
||||||
return CPNotFound;
|
return CPNotFound;
|
||||||
|
|
||||||
return [_items indexOfObjectIdenticalTo:aMenuItem];
|
return [_items indexOfObjectIdenticalTo:aMenuItem];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,7 +455,7 @@ var _CPMenuBarVisible = NO,
|
|||||||
{
|
{
|
||||||
var index = 0,
|
var index = 0,
|
||||||
count = _items.length;
|
count = _items.length;
|
||||||
|
|
||||||
for (; index < count; ++index)
|
for (; index < count; ++index)
|
||||||
if ([_items[index] title] === aTitle)
|
if ([_items[index] title] === aTitle)
|
||||||
return index;
|
return index;
|
||||||
@@ -469,7 +472,7 @@ var _CPMenuBarVisible = NO,
|
|||||||
{
|
{
|
||||||
var index = 0,
|
var index = 0,
|
||||||
count = _items.length;
|
count = _items.length;
|
||||||
|
|
||||||
for (; index < count; ++index)
|
for (; index < count; ++index)
|
||||||
if ([_items[index] tag] == aTag)
|
if ([_items[index] tag] == aTag)
|
||||||
return index;
|
return index;
|
||||||
@@ -487,11 +490,11 @@ var _CPMenuBarVisible = NO,
|
|||||||
{
|
{
|
||||||
var index = 0,
|
var index = 0,
|
||||||
count = _items.length;
|
count = _items.length;
|
||||||
|
|
||||||
for (; index < count; ++index)
|
for (; index < count; ++index)
|
||||||
{
|
{
|
||||||
var item = _items[index];
|
var item = _items[index];
|
||||||
|
|
||||||
if ([item target] == aTarget && (!anAction || [item action] == anAction))
|
if ([item target] == aTarget && (!anAction || [item action] == anAction))
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
@@ -508,7 +511,7 @@ var _CPMenuBarVisible = NO,
|
|||||||
{
|
{
|
||||||
var index = 0,
|
var index = 0,
|
||||||
count = _items.length;
|
count = _items.length;
|
||||||
|
|
||||||
for (; index < count; ++index)
|
for (; index < count; ++index)
|
||||||
if ([[_items[index] representedObject] isEqual:anObject])
|
if ([[_items[index] representedObject] isEqual:anObject])
|
||||||
return index;
|
return index;
|
||||||
@@ -525,7 +528,7 @@ var _CPMenuBarVisible = NO,
|
|||||||
{
|
{
|
||||||
var index = 0,
|
var index = 0,
|
||||||
count = _items.length;
|
count = _items.length;
|
||||||
|
|
||||||
for (; index < count; ++index)
|
for (; index < count; ++index)
|
||||||
if ([_items[index] submenu] == aMenu)
|
if ([_items[index] submenu] == aMenu)
|
||||||
return index;
|
return index;
|
||||||
@@ -543,7 +546,7 @@ var _CPMenuBarVisible = NO,
|
|||||||
{
|
{
|
||||||
[aMenuItem setTarget:aMenuItem];
|
[aMenuItem setTarget:aMenuItem];
|
||||||
[aMenuItem setAction:@selector(submenuAction:)];
|
[aMenuItem setAction:@selector(submenuAction:)];
|
||||||
|
|
||||||
[aMenuItem setSubmenu:aMenu];
|
[aMenuItem setSubmenu:aMenu];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -680,7 +683,7 @@ var _CPMenuBarVisible = NO,
|
|||||||
itemIndex = [self indexOfItem:anItem];
|
itemIndex = [self indexOfItem:anItem];
|
||||||
|
|
||||||
if (itemIndex === CPNotFound)
|
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;
|
anItem + " is not present in menu " + self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -744,9 +747,6 @@ var _CPMenuBarVisible = NO,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Show it.
|
// Show it.
|
||||||
if ([CPPlatform isBrowser])
|
|
||||||
[menuWindow setPlatformWindow:[[aView window] platformWindow]];
|
|
||||||
|
|
||||||
[menuWindow orderFront:self];
|
[menuWindow orderFront:self];
|
||||||
|
|
||||||
// Track it.
|
// Track it.
|
||||||
@@ -781,10 +781,10 @@ var _CPMenuBarVisible = NO,
|
|||||||
+ (void)popUpContextMenu:(CPMenu)aMenu withEvent:(CPEvent)anEvent forView:(CPView)aView withFont:(CPFont)aFont
|
+ (void)popUpContextMenu:(CPMenu)aMenu withEvent:(CPEvent)anEvent forView:(CPView)aView withFont:(CPFont)aFont
|
||||||
{
|
{
|
||||||
var delegate = [aMenu delegate];
|
var delegate = [aMenu delegate];
|
||||||
|
|
||||||
if ([delegate respondsToSelector:@selector(menuWillOpen:)])
|
if ([delegate respondsToSelector:@selector(menuWillOpen:)])
|
||||||
[delegate menuWillOpen:aMenu];
|
[delegate menuWillOpen:aMenu];
|
||||||
|
|
||||||
if (!aFont)
|
if (!aFont)
|
||||||
aFont = [CPFont systemFontOfSize:12.0];
|
aFont = [CPFont systemFontOfSize:12.0];
|
||||||
|
|
||||||
@@ -816,9 +816,6 @@ var _CPMenuBarVisible = NO,
|
|||||||
[menuWindow setFrameOrigin:CGRectIntersection(unconstrainedFrame, constraintRect).origin];
|
[menuWindow setFrameOrigin:CGRectIntersection(unconstrainedFrame, constraintRect).origin];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([CPPlatform isBrowser])
|
|
||||||
[menuWindow setPlatformWindow:[[aView window] platformWindow]];
|
|
||||||
|
|
||||||
[menuWindow orderFront:self];
|
[menuWindow orderFront:self];
|
||||||
|
|
||||||
[[_CPMenuManager sharedMenuManager]
|
[[_CPMenuManager sharedMenuManager]
|
||||||
@@ -935,7 +932,17 @@ var _CPMenuBarVisible = NO,
|
|||||||
var item = _items[index],
|
var item = _items[index],
|
||||||
modifierMask = [item keyEquivalentModifierMask];
|
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])
|
if ([item isEnabled])
|
||||||
[self performActionForItemAtIndex:index];
|
[self performActionForItemAtIndex:index];
|
||||||
@@ -943,7 +950,7 @@ var _CPMenuBarVisible = NO,
|
|||||||
{
|
{
|
||||||
//beep?
|
//beep?
|
||||||
}
|
}
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -962,7 +969,7 @@ var _CPMenuBarVisible = NO,
|
|||||||
- (void)performActionForItemAtIndex:(unsigned)anIndex
|
- (void)performActionForItemAtIndex:(unsigned)anIndex
|
||||||
{
|
{
|
||||||
var item = _items[anIndex];
|
var item = _items[anIndex];
|
||||||
|
|
||||||
[CPApp sendAction:[item action] to:[item target] from:item];
|
[CPApp sendAction:[item action] to:[item target] from:item];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1051,7 +1058,7 @@ var CPMenuTitleKey = @"CPMenuTitleKey",
|
|||||||
- (id)initWithCoder:(CPCoder)aCoder
|
- (id)initWithCoder:(CPCoder)aCoder
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_title = [aCoder decodeObjectForKey:CPMenuTitleKey];
|
_title = [aCoder decodeObjectForKey:CPMenuTitleKey];
|
||||||
@@ -1063,7 +1070,7 @@ var CPMenuTitleKey = @"CPMenuTitleKey",
|
|||||||
|
|
||||||
[self setMinimumWidth:0];
|
[self setMinimumWidth:0];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
@import "CPPanel.j"
|
|
||||||
|
#include "../CoreGraphics/CGGeometry.h"
|
||||||
|
#include "../Platform/Platform.h"
|
||||||
|
|
||||||
@import "_CPMenuWindow.j"
|
@import "_CPMenuWindow.j"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
|
||||||
|
#include "../CoreGraphics/CGGeometry.h"
|
||||||
|
|
||||||
@import <Foundation/CPObject.j>
|
@import <Foundation/CPObject.j>
|
||||||
|
|
||||||
|
|
||||||
@@ -93,7 +96,7 @@ var SharedMenuManager = nil;
|
|||||||
|
|
||||||
// Close Menu Event.
|
// Close Menu Event.
|
||||||
if (type === CPAppKitDefined)
|
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];
|
[CPApp setTarget:self selector:@selector(trackEvent:) forNextEventMatchingMask:CPPeriodicMask | CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPAppKitDefinedMask untilDate:nil inMode:nil dequeue:YES];
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
@import "CPWindow.j"
|
|
||||||
|
#include "../CoreGraphics/CGGeometry.h"
|
||||||
|
|
||||||
|
|
||||||
var _CPMenuWindowPool = [],
|
var _CPMenuWindowPool = [],
|
||||||
|
|||||||
@@ -29,8 +29,7 @@
|
|||||||
@import "CPView.j"
|
@import "CPView.j"
|
||||||
@import "_CPMenuItemView.j"
|
@import "_CPMenuItemView.j"
|
||||||
|
|
||||||
|
/*!
|
||||||
/*!
|
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPMenuItem
|
@class CPMenuItem
|
||||||
|
|
||||||
@@ -44,39 +43,39 @@
|
|||||||
|
|
||||||
CPString _title;
|
CPString _title;
|
||||||
//CPAttributedString _attributedTitle;
|
//CPAttributedString _attributedTitle;
|
||||||
|
|
||||||
CPFont _font;
|
CPFont _font;
|
||||||
|
|
||||||
id _target;
|
id _target;
|
||||||
SEL _action;
|
SEL _action;
|
||||||
|
|
||||||
BOOL _isEnabled;
|
BOOL _isEnabled;
|
||||||
BOOL _isHidden;
|
BOOL _isHidden;
|
||||||
|
|
||||||
int _tag;
|
int _tag;
|
||||||
int _state;
|
int _state;
|
||||||
|
|
||||||
CPImage _image;
|
CPImage _image;
|
||||||
CPImage _alternateImage;
|
CPImage _alternateImage;
|
||||||
CPImage _onStateImage;
|
CPImage _onStateImage;
|
||||||
CPImage _offStateImage;
|
CPImage _offStateImage;
|
||||||
CPImage _mixedStateImage;
|
CPImage _mixedStateImage;
|
||||||
|
|
||||||
CPMenu _submenu;
|
CPMenu _submenu;
|
||||||
CPMenu _menu;
|
CPMenu _menu;
|
||||||
|
|
||||||
CPString _keyEquivalent;
|
CPString _keyEquivalent;
|
||||||
unsigned _keyEquivalentModifierMask;
|
unsigned _keyEquivalentModifierMask;
|
||||||
|
|
||||||
int _mnemonicLocation;
|
int _mnemonicLocation;
|
||||||
|
|
||||||
BOOL _isAlternate;
|
BOOL _isAlternate;
|
||||||
int _indentationLevel;
|
int _indentationLevel;
|
||||||
|
|
||||||
CPString _toolTip;
|
CPString _toolTip;
|
||||||
id _representedObject;
|
id _representedObject;
|
||||||
CPView _view;
|
CPView _view;
|
||||||
|
|
||||||
_CPMenuItemView _menuItemView;
|
_CPMenuItemView _menuItemView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,19 +94,19 @@
|
|||||||
- (id)initWithTitle:(CPString)aTitle action:(SEL)anAction keyEquivalent:(CPString)aKeyEquivalent
|
- (id)initWithTitle:(CPString)aTitle action:(SEL)anAction keyEquivalent:(CPString)aKeyEquivalent
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_isSeparator = NO;
|
_isSeparator = NO;
|
||||||
|
|
||||||
_title = aTitle;
|
_title = aTitle;
|
||||||
_action = anAction;
|
_action = anAction;
|
||||||
|
|
||||||
_isEnabled = YES;
|
_isEnabled = YES;
|
||||||
|
|
||||||
_tag = 0;
|
_tag = 0;
|
||||||
_state = CPOffState;
|
_state = CPOffState;
|
||||||
|
|
||||||
_keyEquivalent = aKeyEquivalent || @"";
|
_keyEquivalent = aKeyEquivalent || @"";
|
||||||
_keyEquivalentModifierMask = CPPlatformActionKeyMask;
|
_keyEquivalentModifierMask = CPPlatformActionKeyMask;
|
||||||
|
|
||||||
@@ -115,7 +114,7 @@
|
|||||||
|
|
||||||
_mnemonicLocation = CPNotFound;
|
_mnemonicLocation = CPNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +152,7 @@
|
|||||||
{
|
{
|
||||||
if (_isHidden == isHidden)
|
if (_isHidden == isHidden)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_isHidden = isHidden;
|
_isHidden = isHidden;
|
||||||
|
|
||||||
[_menu itemChanged:self];
|
[_menu itemChanged:self];
|
||||||
@@ -174,9 +173,9 @@
|
|||||||
{
|
{
|
||||||
if (_isHidden)
|
if (_isHidden)
|
||||||
return YES;
|
return YES;
|
||||||
|
|
||||||
var supermenu = [_menu supermenu];
|
var supermenu = [_menu supermenu];
|
||||||
|
|
||||||
if ([[supermenu itemAtIndex:[supermenu indexOfItemWithSubmenu:_menu]] isHiddenOrHasHiddenAncestor])
|
if ([[supermenu itemAtIndex:[supermenu indexOfItemWithSubmenu:_menu]] isHiddenOrHasHiddenAncestor])
|
||||||
return YES;
|
return YES;
|
||||||
|
|
||||||
@@ -229,11 +228,11 @@
|
|||||||
|
|
||||||
if (_title == aTitle)
|
if (_title == aTitle)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_title = aTitle;
|
_title = aTitle;
|
||||||
|
|
||||||
[_menuItemView setDirty];
|
[_menuItemView setDirty];
|
||||||
|
|
||||||
[_menu itemChanged:self];
|
[_menu itemChanged:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,11 +260,11 @@
|
|||||||
{
|
{
|
||||||
if (_font == aFont)
|
if (_font == aFont)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_font = aFont;
|
_font = aFont;
|
||||||
|
|
||||||
[_menu itemChanged:self];
|
[_menu itemChanged:self];
|
||||||
|
|
||||||
[_menuItemView setDirty];
|
[_menuItemView setDirty];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,9 +316,9 @@ CPOffState
|
|||||||
{
|
{
|
||||||
if (_state == aState)
|
if (_state == aState)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_state = aState;
|
_state = aState;
|
||||||
|
|
||||||
[_menu itemChanged:self];
|
[_menu itemChanged:self];
|
||||||
|
|
||||||
[_menuItemView setDirty];
|
[_menuItemView setDirty];
|
||||||
@@ -347,11 +346,11 @@ CPOffState
|
|||||||
{
|
{
|
||||||
if (_image == anImage)
|
if (_image == anImage)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_image = anImage;
|
_image = anImage;
|
||||||
|
|
||||||
[_menuItemView setDirty];
|
[_menuItemView setDirty];
|
||||||
|
|
||||||
[_menu itemChanged:self];
|
[_menu itemChanged:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -389,7 +388,7 @@ CPOffState
|
|||||||
{
|
{
|
||||||
if (_onStateImage == anImage)
|
if (_onStateImage == anImage)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_onStateImage = anImage;
|
_onStateImage = anImage;
|
||||||
[_menu itemChanged:self];
|
[_menu itemChanged:self];
|
||||||
}
|
}
|
||||||
@@ -410,7 +409,7 @@ CPOffState
|
|||||||
{
|
{
|
||||||
if (_offStateImage == anImage)
|
if (_offStateImage == anImage)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_offStateImage = anImage;
|
_offStateImage = anImage;
|
||||||
[_menu itemChanged:self];
|
[_menu itemChanged:self];
|
||||||
}
|
}
|
||||||
@@ -431,7 +430,7 @@ CPOffState
|
|||||||
{
|
{
|
||||||
if (_mixedStateImage == anImage)
|
if (_mixedStateImage == anImage)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_mixedStateImage = anImage;
|
_mixedStateImage = anImage;
|
||||||
[_menu itemChanged:self];
|
[_menu itemChanged:self];
|
||||||
}
|
}
|
||||||
@@ -592,8 +591,7 @@ CPControlKeyMask
|
|||||||
return @"";
|
return @"";
|
||||||
|
|
||||||
var string = _keyEquivalent.toUpperCase(),
|
var string = _keyEquivalent.toUpperCase(),
|
||||||
needsShift = _keyEquivalentModifierMask & CPShiftKeyMask ||
|
needsShift = _keyEquivalentModifierMask & CPShiftKeyMask || string === _keyEquivalent;
|
||||||
(string === _keyEquivalent && _keyEquivalent.toLowerCase() !== _keyEquivalent.toUpperCase());
|
|
||||||
|
|
||||||
if (CPBrowserIsOperatingSystem(CPMacOperatingSystem))
|
if (CPBrowserIsOperatingSystem(CPMacOperatingSystem))
|
||||||
{
|
{
|
||||||
@@ -650,14 +648,14 @@ CPControlKeyMask
|
|||||||
- (void)setTitleWithMnemonicLocation:(CPString)aTitle
|
- (void)setTitleWithMnemonicLocation:(CPString)aTitle
|
||||||
{
|
{
|
||||||
var location = [aTitle rangeOfString:@"&"].location;
|
var location = [aTitle rangeOfString:@"&"].location;
|
||||||
|
|
||||||
if (location == CPNotFound)
|
if (location == CPNotFound)
|
||||||
[self setTitle:aTitle];
|
[self setTitle:aTitle];
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[self setTitle:[aTitle substringToIndex:location] + [aTitle substringFromIndex:location + 1]];
|
[self setTitle:[aTitle substringToIndex:location] + [aTitle substringFromIndex:location + 1]];
|
||||||
[self setMnemonicLocation:location];
|
[self setMnemonicLocation:location];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -698,7 +696,7 @@ CPControlKeyMask
|
|||||||
{
|
{
|
||||||
if (aLevel < 0)
|
if (aLevel < 0)
|
||||||
[CPException raise:CPInvalidArgumentException reason:"setIndentationLevel: argument must be greater than or equal to 0."];
|
[CPException raise:CPInvalidArgumentException reason:"setIndentationLevel: argument must be greater than or equal to 0."];
|
||||||
|
|
||||||
_indentationLevel = MIN(15, aLevel);
|
_indentationLevel = MIN(15, aLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -757,11 +755,11 @@ CPControlKeyMask
|
|||||||
{
|
{
|
||||||
if (_view === aView)
|
if (_view === aView)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_view = aView;
|
_view = aView;
|
||||||
|
|
||||||
[_menuItemView setDirty];
|
[_menuItemView setDirty];
|
||||||
|
|
||||||
[_menu itemChanged:self];
|
[_menu itemChanged:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -783,48 +781,7 @@ CPControlKeyMask
|
|||||||
return [[self menu] highlightedItem] == self;
|
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
|
@ignore
|
||||||
@@ -833,7 +790,7 @@ CPControlKeyMask
|
|||||||
{
|
{
|
||||||
if (!_menuItemView)
|
if (!_menuItemView)
|
||||||
_menuItemView = [[_CPMenuItemView alloc] initWithFrame:CGRectMakeZero() forMenuItem:self];
|
_menuItemView = [[_CPMenuItemView alloc] initWithFrame:CGRectMakeZero() forMenuItem:self];
|
||||||
|
|
||||||
return _menuItemView;
|
return _menuItemView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -887,15 +844,15 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
|
|||||||
- (id)initWithCoder:(CPCoder)aCoder
|
- (id)initWithCoder:(CPCoder)aCoder
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_isSeparator = [aCoder containsValueForKey:CPMenuItemIsSeparatorKey] && [aCoder decodeBoolForKey:CPMenuItemIsSeparatorKey];
|
_isSeparator = [aCoder containsValueForKey:CPMenuItemIsSeparatorKey] && [aCoder decodeBoolForKey:CPMenuItemIsSeparatorKey];
|
||||||
|
|
||||||
_title = [aCoder decodeObjectForKey:CPMenuItemTitleKey];
|
_title = [aCoder decodeObjectForKey:CPMenuItemTitleKey];
|
||||||
|
|
||||||
// _font;
|
// _font;
|
||||||
|
|
||||||
_target = [aCoder decodeObjectForKey:CPMenuItemTargetKey];
|
_target = [aCoder decodeObjectForKey:CPMenuItemTargetKey];
|
||||||
_action = [aCoder decodeObjectForKey:CPMenuItemActionKey];
|
_action = [aCoder decodeObjectForKey:CPMenuItemActionKey];
|
||||||
|
|
||||||
@@ -903,6 +860,7 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
|
|||||||
_isHidden = DEFAULT_VALUE(CPMenuItemIsHiddenKey, NO);
|
_isHidden = DEFAULT_VALUE(CPMenuItemIsHiddenKey, NO);
|
||||||
_tag = DEFAULT_VALUE(CPMenuItemTagKey, 0);
|
_tag = DEFAULT_VALUE(CPMenuItemTagKey, 0);
|
||||||
_state = DEFAULT_VALUE(CPMenuItemStateKey, CPOffState);
|
_state = DEFAULT_VALUE(CPMenuItemStateKey, CPOffState);
|
||||||
|
// int _state;
|
||||||
|
|
||||||
_image = DEFAULT_VALUE(CPMenuItemImageKey, nil);
|
_image = DEFAULT_VALUE(CPMenuItemImageKey, nil);
|
||||||
_alternateImage = DEFAULT_VALUE(CPMenuItemAlternateImageKey, nil);
|
_alternateImage = DEFAULT_VALUE(CPMenuItemAlternateImageKey, nil);
|
||||||
@@ -929,7 +887,7 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
|
|||||||
_representedObject = DEFAULT_VALUE(CPMenuItemRepresentedObjectKey, nil);
|
_representedObject = DEFAULT_VALUE(CPMenuItemRepresentedObjectKey, nil);
|
||||||
_view = DEFAULT_VALUE(CPMenuItemViewKey, nil);
|
_view = DEFAULT_VALUE(CPMenuItemViewKey, nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -943,11 +901,11 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
|
|||||||
[aCoder encodeBool:_isSeparator forKey:CPMenuItemIsSeparatorKey];
|
[aCoder encodeBool:_isSeparator forKey:CPMenuItemIsSeparatorKey];
|
||||||
|
|
||||||
[aCoder encodeObject:_title forKey:CPMenuItemTitleKey];
|
[aCoder encodeObject:_title forKey:CPMenuItemTitleKey];
|
||||||
|
|
||||||
[aCoder encodeObject:_target forKey:CPMenuItemTargetKey];
|
[aCoder encodeObject:_target forKey:CPMenuItemTargetKey];
|
||||||
[aCoder encodeObject:_action forKey:CPMenuItemActionKey];
|
[aCoder encodeObject:_action forKey:CPMenuItemActionKey];
|
||||||
|
|
||||||
ENCODE_IFNOT(CPMenuItemIsEnabledKey, _isEnabled, YES);
|
ENCODE_IFNOT(CPMenuItemIsEnabledKey, _isEnabled, YES);
|
||||||
ENCODE_IFNOT(CPMenuItemIsHiddenKey, _isHidden, NO);
|
ENCODE_IFNOT(CPMenuItemIsHiddenKey, _isHidden, NO);
|
||||||
|
|
||||||
ENCODE_IFNOT(CPMenuItemTagKey, _tag, 0);
|
ENCODE_IFNOT(CPMenuItemTagKey, _tag, 0);
|
||||||
@@ -955,7 +913,7 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
|
|||||||
|
|
||||||
ENCODE_IFNOT(CPMenuItemImageKey, _image, nil);
|
ENCODE_IFNOT(CPMenuItemImageKey, _image, nil);
|
||||||
ENCODE_IFNOT(CPMenuItemAlternateImageKey, _alternateImage, nil);
|
ENCODE_IFNOT(CPMenuItemAlternateImageKey, _alternateImage, nil);
|
||||||
|
|
||||||
ENCODE_IFNOT(CPMenuItemSubmenuKey, _submenu, nil);
|
ENCODE_IFNOT(CPMenuItemSubmenuKey, _submenu, nil);
|
||||||
ENCODE_IFNOT(CPMenuItemMenuKey, _menu, nil);
|
ENCODE_IFNOT(CPMenuItemMenuKey, _menu, nil);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
@import "CPView.j"
|
|
||||||
|
|
||||||
|
|
||||||
var HORIZONTAL_MARGIN = 8.0,
|
var HORIZONTAL_MARGIN = 8.0,
|
||||||
SUBMENU_INDICATOR_MARGIN = 3.0,
|
SUBMENU_INDICATOR_MARGIN = 3.0,
|
||||||
VERTICAL_MARGIN = 4.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 = [[_CPImageAndTextView alloc] initWithFrame:CGRectMake(HORIZONTAL_MARGIN, 0.0, 0.0, 0.0)];
|
||||||
|
|
||||||
[_imageAndTextView setImagePosition:CPImageLeft];
|
[_imageAndTextView setImagePosition:CPImageLeft];
|
||||||
[_imageAndTextView setImageOffset:3.0];
|
|
||||||
[_imageAndTextView setTextShadowOffset:CGSizeMake(0.0, 1.0)];
|
[_imageAndTextView setTextShadowOffset:CGSizeMake(0.0, 1.0)];
|
||||||
[_imageAndTextView setAutoresizingMask:CPViewMinYMargin | CPViewMaxYMargin];
|
[_imageAndTextView setAutoresizingMask:CPViewMinYMargin | CPViewMaxYMargin];
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
@import "CPView.j"
|
@import <AppKit/CPView.j>
|
||||||
|
|
||||||
|
|
||||||
@implementation _CPMenuItemSeparatorView : CPView
|
@implementation _CPMenuItemSeparatorView : CPView
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
@import "CPControl.j"
|
|
||||||
|
|
||||||
|
|
||||||
var LEFT_MARGIN = 3.0,
|
var LEFT_MARGIN = 3.0,
|
||||||
RIGHT_MARGIN = 14.0 + 3.0,
|
RIGHT_MARGIN = 14.0 + 3.0,
|
||||||
STATE_COLUMN_WIDTH = 14.0,
|
STATE_COLUMN_WIDTH = 14.0,
|
||||||
@@ -42,7 +39,7 @@ var SUBMENU_INDICATOR_COLOR = nil,
|
|||||||
SUBMENU_INDICATOR_COLOR = [CPColor grayColor];
|
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];
|
_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];
|
var bundle = [CPBundle bundleForClass:self];
|
||||||
|
|
||||||
@@ -260,13 +257,10 @@ var SUBMENU_INDICATOR_COLOR = nil,
|
|||||||
[_keyEquivalentView setTextShadowColor:[self textShadowColor]];
|
[_keyEquivalentView setTextShadowColor:[self textShadowColor]];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([[_menuItem menu] showsStateColumn])
|
if (shouldHighlight)
|
||||||
{
|
[_stateView setImage:_CPMenuItemDefaultStateHighlightedImages[[_menuItem state]] || nil];
|
||||||
if (shouldHighlight)
|
else
|
||||||
[_stateView setImage:_CPMenuItemDefaultStateHighlightedImages[[_menuItem state]] || nil];
|
[_stateView setImage:_CPMenuItemDefaultStateImages[[_menuItem state]] || nil];
|
||||||
else
|
|
||||||
[_stateView setImage:_CPMenuItemDefaultStateImages[[_menuItem state]] || nil];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
|
|
||||||
@import <AppKit/CPControl.j>
|
|
||||||
|
|
||||||
@import "_CPMenuItemSeparatorView.j"
|
@import "_CPMenuItemSeparatorView.j"
|
||||||
@import "_CPMenuItemStandardView.j"
|
@import "_CPMenuItemStandardView.j"
|
||||||
@import "_CPMenuItemMenuBarView.j"
|
@import "_CPMenuItemMenuBarView.j"
|
||||||
@@ -45,7 +43,7 @@ var _CPMenuItemSelectionColor = nil,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
_CPMenuItemSelectionColor = [CPColor colorWithCalibratedRed:95.0 / 255.0 green:131.0 / 255.0 blue:185.0 / 255.0 alpha:1.0];
|
_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];
|
var bundle = [CPBundle bundleForClass:self];
|
||||||
|
|
||||||
@@ -254,4 +252,4 @@ var _CPMenuItemSelectionColor = nil,
|
|||||||
CGContextFillPath(context);
|
CGContextFillPath(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -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,5 +1,5 @@
|
|||||||
|
|
||||||
@import "CPPanel.j"
|
@import <AppKit/CPPanel.j>
|
||||||
|
|
||||||
|
|
||||||
@implementation CPOpenPanel : CPPanel
|
@implementation CPOpenPanel : CPPanel
|
||||||
|
|||||||
+125
-371
@@ -23,6 +23,8 @@
|
|||||||
@import "CPTableColumn.j"
|
@import "CPTableColumn.j"
|
||||||
@import "CPTableView.j"
|
@import "CPTableView.j"
|
||||||
|
|
||||||
|
#include "CoreGraphics/CGGeometry.h"
|
||||||
|
|
||||||
|
|
||||||
CPOutlineViewColumnDidMoveNotification = @"CPOutlineViewColumnDidMoveNotification";
|
CPOutlineViewColumnDidMoveNotification = @"CPOutlineViewColumnDidMoveNotification";
|
||||||
CPOutlineViewColumnDidResizeNotification = @"CPOutlineViewColumnDidResizeNotification";
|
CPOutlineViewColumnDidResizeNotification = @"CPOutlineViewColumnDidResizeNotification";
|
||||||
@@ -48,30 +50,12 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_
|
|||||||
|
|
||||||
CPOutlineViewDataSource_outlineView_sortDescriptorsDidChange_ = 1 << 10;
|
CPOutlineViewDataSource_outlineView_sortDescriptorsDidChange_ = 1 << 10;
|
||||||
|
|
||||||
|
|
||||||
var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ = 1 << 1,
|
var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ = 1 << 1,
|
||||||
CPOutlineViewDelegate_outlineView_didClickTableColumn_ = 1 << 2,
|
CPOutlineViewDelegate_outlineView_shouldSelectItem_ = 1 << 2,
|
||||||
CPOutlineViewDelegate_outlineView_didDragTableColumn_ = 1 << 3,
|
CPOutlineViewDelegate_outlineView_heightOfRowByItem_ = 1 << 3,
|
||||||
CPOutlineViewDelegate_outlineView_heightOfRowByItem_ = 1 << 4,
|
CPOutlineViewDelegate_outlineView_willDisplayView_forTableColumn_item_ = 1 << 4,
|
||||||
CPOutlineViewDelegate_outlineView_isGroupItem_ = 1 << 5,
|
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;
|
|
||||||
|
|
||||||
CPOutlineViewDropOnItemIndex = -1;
|
CPOutlineViewDropOnItemIndex = -1;
|
||||||
|
|
||||||
@@ -95,14 +79,12 @@ CPOutlineViewDropOnItemIndex = -1;
|
|||||||
CPArray _disclosureControlsForRows;
|
CPArray _disclosureControlsForRows;
|
||||||
CPData _disclosureControlData;
|
CPData _disclosureControlData;
|
||||||
CPArray _disclosureControlQueue;
|
CPArray _disclosureControlQueue;
|
||||||
|
|
||||||
BOOL _shouldRetargetItem;
|
BOOL _shouldRetargetItem;
|
||||||
id _retargetedItem;
|
id _retargetedItem;
|
||||||
|
|
||||||
BOOL _shouldRetargetChildIndex;
|
BOOL _shouldRetargetChildIndex;
|
||||||
CPInteger _retargedChildIndex;
|
CPInteger _retargedChildIndex;
|
||||||
CPTimer _dragHoverTimer;
|
|
||||||
id _dropItem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithFrame:(CGRect)aFrame
|
- (id)initWithFrame:(CGRect)aFrame
|
||||||
@@ -123,10 +105,9 @@ CPOutlineViewDropOnItemIndex = -1;
|
|||||||
|
|
||||||
_retargetedItem = nil;
|
_retargetedItem = nil;
|
||||||
_shouldRetargetItem = NO;
|
_shouldRetargetItem = NO;
|
||||||
|
|
||||||
_retargedChildIndex = nil;
|
_retargedChildIndex = nil;
|
||||||
_shouldRetargetChildIndex = NO;
|
_shouldRetargetChildIndex = NO;
|
||||||
_startHoverTime = nil;
|
|
||||||
|
|
||||||
[self setIndentationPerLevel:16.0];
|
[self setIndentationPerLevel:16.0];
|
||||||
[self setIndentationMarkerFollowsDataView:YES];
|
[self setIndentationMarkerFollowsDataView:YES];
|
||||||
@@ -232,7 +213,7 @@ CPOutlineViewDropOnItemIndex = -1;
|
|||||||
- (void)expandItem:(id)anItem expandChildren:(BOOL)shouldExpandChildren
|
- (void)expandItem:(id)anItem expandChildren:(BOOL)shouldExpandChildren
|
||||||
{
|
{
|
||||||
var itemInfo = null;
|
var itemInfo = null;
|
||||||
|
|
||||||
if (!anItem)
|
if (!anItem)
|
||||||
itemInfo = _rootItemInfo;
|
itemInfo = _rootItemInfo;
|
||||||
else
|
else
|
||||||
@@ -240,21 +221,15 @@ CPOutlineViewDropOnItemIndex = -1;
|
|||||||
|
|
||||||
if (!itemInfo)
|
if (!itemInfo)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// to prevent items which are already expanded from firing notifications
|
itemInfo.isExpanded = YES;
|
||||||
if (!itemInfo.isExpanded)
|
[self reloadItem:anItem reloadChildren:YES];
|
||||||
{
|
|
||||||
[self _noteItemWillExpand:anItem];
|
|
||||||
itemInfo.isExpanded = YES;
|
|
||||||
[self _noteItemDidExpand:anItem];
|
|
||||||
[self reloadItem:anItem reloadChildren:YES];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldExpandChildren)
|
if (shouldExpandChildren)
|
||||||
{
|
{
|
||||||
var children = itemInfo.children,
|
var children = itemInfo.children,
|
||||||
childIndex = children.length;
|
childIndex = children.length;
|
||||||
|
|
||||||
while (childIndex--)
|
while (childIndex--)
|
||||||
[self expandItem:children[childIndex] expandChildren:YES];
|
[self expandItem:children[childIndex] expandChildren:YES];
|
||||||
}
|
}
|
||||||
@@ -273,9 +248,7 @@ CPOutlineViewDropOnItemIndex = -1;
|
|||||||
if (!itemInfo.isExpanded)
|
if (!itemInfo.isExpanded)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[self _noteItemWillCollapse:anItem];
|
|
||||||
itemInfo.isExpanded = NO;
|
itemInfo.isExpanded = NO;
|
||||||
[self _noteItemDidCollapse:anItem];
|
|
||||||
|
|
||||||
[self reloadItem:anItem reloadChildren:YES];
|
[self reloadItem:anItem reloadChildren:YES];
|
||||||
}
|
}
|
||||||
@@ -390,7 +363,7 @@ CPOutlineViewDropOnItemIndex = -1;
|
|||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
var parent = itemInfo.parent;
|
var parent = itemInfo.parent;
|
||||||
|
|
||||||
// Check if the parent is the root item because we never return the actual root item
|
// Check if the parent is the root item because we never return the actual root item
|
||||||
if (itemInfo[[parent UID]] === _rootItemInfo)
|
if (itemInfo[[parent UID]] === _rootItemInfo)
|
||||||
parent = nil;
|
parent = nil;
|
||||||
@@ -409,14 +382,43 @@ CPOutlineViewDropOnItemIndex = -1;
|
|||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_performSelection:(BOOL)select forRow:(CPInteger)rowIndex context:(id)context
|
- (void)selectRowIndexes:(CPIndexSet)rows byExtendingSelection:(BOOL)shouldExtendSelection
|
||||||
{
|
{
|
||||||
[super _performSelection:select forRow:rowIndex context:context];
|
// First un highlight the old disclosure controls
|
||||||
|
var previousSelectedRows = [];
|
||||||
var control = _disclosureControlsForRows[rowIndex],
|
[[self selectedRowIndexes] getIndexes:previousSelectedRows maxCount:-1 inIndexRange:nil];
|
||||||
selector = select ? @"setThemeState:" : @"unsetThemeState:";
|
|
||||||
|
var index = [previousSelectedRows count];
|
||||||
[control performSelector:CPSelectorFromString(selector) withObject:CPThemeStateSelected];
|
while (index--)
|
||||||
|
{
|
||||||
|
var rowIndex = previousSelectedRows[index],
|
||||||
|
item = [self itemAtRow:rowIndex];
|
||||||
|
|
||||||
|
if (![self isExpandable:item])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var control = _disclosureControlsForRows[rowIndex];
|
||||||
|
[control setHighlighted:NO];
|
||||||
|
}
|
||||||
|
|
||||||
|
[super selectRowIndexes:rows byExtendingSelection:shouldExtendSelection];
|
||||||
|
|
||||||
|
// Now highlight the new disclosure controls
|
||||||
|
var selectedRows = [];
|
||||||
|
[rows getIndexes:selectedRows maxCount:-1 inIndexRange:nil];
|
||||||
|
|
||||||
|
var index = [selectedRows count];
|
||||||
|
while (index--)
|
||||||
|
{
|
||||||
|
var rowIndex = selectedRows[index],
|
||||||
|
item = [self itemAtRow:rowIndex];
|
||||||
|
|
||||||
|
if (![self isExpandable:item])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var control = _disclosureControlsForRows[rowIndex];
|
||||||
|
[control setHighlighted:YES];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setDelegate:(id)aDelegate
|
- (void)setDelegate:(id)aDelegate
|
||||||
@@ -451,76 +453,25 @@ CPOutlineViewDropOnItemIndex = -1;
|
|||||||
removeObserver:_outlineViewDelegate
|
removeObserver:_outlineViewDelegate
|
||||||
name:CPOutlineViewSelectionIsChangingNotification
|
name:CPOutlineViewSelectionIsChangingNotification
|
||||||
object:self];
|
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;
|
_outlineViewDelegate = aDelegate;
|
||||||
_implementedOutlineViewDelegateMethods = 0;
|
_implementedOutlineViewDelegateMethods = 0;
|
||||||
|
|
||||||
var delegateMethods = [
|
if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:dataViewForTableColumn:item:)])
|
||||||
CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ , @selector(outlineView:dataViewForTableColumn:item:),
|
_implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_;
|
||||||
CPOutlineViewDelegate_outlineView_didClickTableColumn_ , @selector(outlineView:didClickTableColumn:),
|
|
||||||
CPOutlineViewDelegate_outlineView_didDragTableColumn_ , @selector(outlineView:didDragTableColumn:),
|
if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:shouldSelectItem:)])
|
||||||
CPOutlineViewDelegate_outlineView_heightOfRowByItem_ , @selector(outlineView:heightOfRowByItem:),
|
_implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_shouldSelectItem_;
|
||||||
CPOutlineViewDelegate_outlineView_isGroupItem_ , @selector(outlineView:isGroupItem:),
|
|
||||||
CPOutlineViewDelegate_outlineView_mouseDownInHeaderOfTableColumn_ , @selector(outlineView:mouseDownInHeaderOfTableColumn:),
|
if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:heightOfRowByItem:)])
|
||||||
CPOutlineViewDelegate_outlineView_nextTypeSelectMatchFromItem_toItem_forString_ , @selector(outlineView:nextTypeSelectMatchFromItem:toItem:forString:),
|
_implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_heightOfRowByItem_;
|
||||||
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];
|
|
||||||
|
|
||||||
for (var i=0; i < delegateCount; i += 2)
|
if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:willDisplayView:forTableColumn:item:)])
|
||||||
{
|
_implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_willDisplayView_forTableColumn_item_;
|
||||||
var bitMask = delegateMethods[i],
|
|
||||||
selector = delegateMethods[i+1];
|
|
||||||
|
|
||||||
if ([_outlineViewDelegate respondsToSelector:selector])
|
if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:isGroupItem:)])
|
||||||
_implementedOutlineViewDelegateMethods |= bitMask;
|
_implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_isGroupItem_;
|
||||||
}
|
|
||||||
|
|
||||||
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewColumnDidMove:)])
|
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewColumnDidMove:)])
|
||||||
[defaultCenter
|
[defaultCenter
|
||||||
@@ -549,36 +500,6 @@ CPOutlineViewDropOnItemIndex = -1;
|
|||||||
selector:@selector(outlineViewSelectionIsChanging:)
|
selector:@selector(outlineViewSelectionIsChanging:)
|
||||||
name:CPOutlineViewSelectionIsChangingNotification
|
name:CPOutlineViewSelectionIsChangingNotification
|
||||||
object:self];
|
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
|
- (id)delegate
|
||||||
@@ -613,63 +534,18 @@ CPOutlineViewDropOnItemIndex = -1;
|
|||||||
|
|
||||||
- (void)setDropItem:(id)theItem dropChildIndex:(int)theIndex
|
- (void)setDropItem:(id)theItem dropChildIndex:(int)theIndex
|
||||||
{
|
{
|
||||||
if (_dropItem !== theItem && theIndex < 0 && [self isExpandable:theItem] && ![self isItemExpanded:theItem])
|
|
||||||
{
|
|
||||||
if (_dragHoverTimer)
|
|
||||||
[_dragHoverTimer invalidate];
|
|
||||||
|
|
||||||
var autoExpandCallBack = function(){
|
|
||||||
if (_dropItem)
|
|
||||||
{
|
|
||||||
[_dropOperationFeedbackView blink];
|
|
||||||
[CPTimer scheduledTimerWithTimeInterval:.3 callback:objj_msgSend(self, "expandItem:", _dropItem) repeats:NO];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_dragHoverTimer = [CPTimer scheduledTimerWithTimeInterval:.8 callback:autoExpandCallBack repeats:NO];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (theIndex >= 0)
|
|
||||||
{
|
|
||||||
[_dragHoverTimer invalidate];
|
|
||||||
_dragHoverTimer = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
_dropItem = theItem;
|
|
||||||
_retargetedItem = theItem;
|
_retargetedItem = theItem;
|
||||||
_shouldRetargetItem = YES;
|
_shouldRetargetItem = YES;
|
||||||
|
|
||||||
_retargedChildIndex = theIndex;
|
_retargedChildIndex = theIndex;
|
||||||
_shouldRetargetChildIndex = YES;
|
_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
|
|
||||||
{
|
|
||||||
[super _draggingEnded];
|
|
||||||
_dropItem = nil;
|
|
||||||
[_dragHoverTimer invalidate];
|
|
||||||
_dragHoverTimer = nil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)_parentItemForUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex atMouseOffset:(CPPoint)theOffset
|
- (id)_parentItemForUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex atMouseOffset:(CPPoint)theOffset
|
||||||
{
|
{
|
||||||
if (_shouldRetargetItem)
|
if (_shouldRetargetItem)
|
||||||
return _retargetedItem;
|
return _retargetedItem;
|
||||||
|
|
||||||
var lowerLevel = [self levelForRow:theLowerRowIndex]
|
var lowerLevel = [self levelForRow:theLowerRowIndex]
|
||||||
upperItem = [self itemAtRow:theUpperRowIndex];
|
upperItem = [self itemAtRow:theUpperRowIndex];
|
||||||
upperLevel = [self levelForItem:upperItem];
|
upperLevel = [self levelForItem:upperItem];
|
||||||
@@ -688,7 +564,7 @@ CPOutlineViewDropOnItemIndex = -1;
|
|||||||
// Check the next parent
|
// Check the next parent
|
||||||
upperItem = [self parentForItem:upperItem];
|
upperItem = [self parentForItem:upperItem];
|
||||||
}
|
}
|
||||||
|
|
||||||
return [self parentForItem:[self itemAtRow:theLowerRowIndex]];
|
return [self parentForItem:[self itemAtRow:theLowerRowIndex]];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -698,10 +574,10 @@ CPOutlineViewDropOnItemIndex = -1;
|
|||||||
var rect = [super _rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex offset:theOffset],
|
var rect = [super _rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex offset:theOffset],
|
||||||
parentItem = [self _parentItemForUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex atMouseOffset:theOffset],
|
parentItem = [self _parentItemForUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex atMouseOffset:theOffset],
|
||||||
level = [self levelForItem:parentItem];
|
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
|
rect.size.width -= rect.origin.x; // This assumes that the x returned by super is zero
|
||||||
|
|
||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -743,8 +619,6 @@ CPOutlineViewDropOnItemIndex = -1;
|
|||||||
_disclosureControlsForRows[row] = control;
|
_disclosureControlsForRows[row] = control;
|
||||||
|
|
||||||
[control setState:[self isItemExpanded:item] ? CPOnState : CPOffState];
|
[control setState:[self isItemExpanded:item] ? CPOnState : CPOffState];
|
||||||
var selector = [self isRowSelected:row] ? @"setThemeState:" : @"unsetThemeState:";
|
|
||||||
[control performSelector:CPSelectorFromString(selector) withObject:CPThemeStateSelected];
|
|
||||||
[control setFrame:frame];
|
[control setFrame:frame];
|
||||||
|
|
||||||
[self addSubview:control];
|
[self addSubview:control];
|
||||||
@@ -835,41 +709,9 @@ CPOutlineViewDropOnItemIndex = -1;
|
|||||||
userInfo:nil];
|
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
|
@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)
|
var _reloadItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem)
|
||||||
{
|
{
|
||||||
if (!anItem)
|
if (!anItem)
|
||||||
@@ -882,55 +724,55 @@ var _reloadItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem)
|
|||||||
dataSource = _outlineViewDataSource,
|
dataSource = _outlineViewDataSource,
|
||||||
itemUID = [anItem UID],
|
itemUID = [anItem UID],
|
||||||
itemInfo = itemInfosForItems[itemUID];
|
itemInfo = itemInfosForItems[itemUID];
|
||||||
|
|
||||||
// If we're not in the tree, then just bail.
|
// If we're not in the tree, then just bail.
|
||||||
if (!itemInfo)
|
if (!itemInfo)
|
||||||
return [];
|
return [];
|
||||||
|
|
||||||
// See if the item itself can be swapped out.
|
// See if the item itself can be swapped out.
|
||||||
var parent = itemInfo.parent,
|
var parent = itemInfo.parent,
|
||||||
parentItemInfo = parent ? itemInfosForItems[[parent UID]] : _rootItemInfo,
|
parentItemInfo = parent ? itemInfosForItems[[parent UID]] : _rootItemInfo,
|
||||||
parentChildren = parentItemInfo.children,
|
parentChildren = parentItemInfo.children,
|
||||||
index = [parentChildren indexOfObjectIdenticalTo:anItem],
|
index = [parentChildren indexOfObjectIdenticalTo:anItem],
|
||||||
newItem = [dataSource outlineView:anOutlineView child:index ofItem:parent];
|
newItem = [dataSource outlineView:anOutlineView child:index ofItem:parent];
|
||||||
|
|
||||||
if (anItem !== newItem)
|
if (anItem !== newItem)
|
||||||
{
|
{
|
||||||
itemInfosForItems[[anItem UID]] = nil;
|
itemInfosForItems[[anItem UID]] = nil;
|
||||||
itemInfosForItems[[newItem UID]] = itemInfo;
|
itemInfosForItems[[newItem UID]] = itemInfo;
|
||||||
|
|
||||||
parentChildren[index] = newItem;
|
parentChildren[index] = newItem;
|
||||||
_itemsForRows[itemInfo.row] = newItem;
|
_itemsForRows[itemInfo.row] = newItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:newItem];
|
itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:newItem];
|
||||||
itemInfo.isExpanded = itemInfo.isExpandable && itemInfo.isExpanded;
|
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)
|
var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem, /*BOOL*/ isIntermediate)
|
||||||
{
|
{
|
||||||
with(anOutlineView)
|
with(anOutlineView)
|
||||||
{
|
{
|
||||||
var itemInfosForItems = _itemInfosForItems,
|
var itemInfosForItems = _itemInfosForItems,
|
||||||
dataSource = _outlineViewDataSource;
|
dataSource = _outlineViewDataSource;
|
||||||
|
|
||||||
if (!anItem)
|
if (!anItem)
|
||||||
var itemInfo = _rootItemInfo;
|
var itemInfo = _rootItemInfo;
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Get the existing info if it exists.
|
// Get the existing info if it exists.
|
||||||
var itemUID = [anItem UID],
|
var itemUID = [anItem UID],
|
||||||
itemInfo = itemInfosForItems[itemUID];
|
itemInfo = itemInfosForItems[itemUID];
|
||||||
|
|
||||||
// If we're not in the tree, then just bail.
|
// If we're not in the tree, then just bail.
|
||||||
if (!itemInfo)
|
if (!itemInfo)
|
||||||
return [];
|
return [];
|
||||||
|
|
||||||
itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:anItem];
|
itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:anItem];
|
||||||
|
|
||||||
// If we were previously expanded, but now no longer expandable, "de-expand".
|
// If we were previously expanded, but now no longer expandable, "de-expand".
|
||||||
// NOTE: we are *not* collapsing, thus no notification is posted.
|
// NOTE: we are *not* collapsing, thus no notification is posted.
|
||||||
if (!itemInfo.isExpandable && itemInfo.isExpanded)
|
if (!itemInfo.isExpandable && itemInfo.isExpanded)
|
||||||
@@ -939,72 +781,72 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
|
|||||||
itemInfo.children = [];
|
itemInfo.children = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The root item does not count as a descendant.
|
// The root item does not count as a descendant.
|
||||||
var weight = itemInfo.weight,
|
var weight = itemInfo.weight,
|
||||||
descendants = anItem ? [anItem] : [];
|
descendants = anItem ? [anItem] : [];
|
||||||
|
|
||||||
if (itemInfo.isExpanded && (!(_implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_shouldDeferDisplayingChildrenOfItem_) ||
|
if (itemInfo.isExpanded && (!(_implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_shouldDeferDisplayingChildrenOfItem_) ||
|
||||||
![dataSource outlineView:anOutlineView shouldDeferDisplayingChildrenOfItem:anItem]))
|
![dataSource outlineView:anOutlineView shouldDeferDisplayingChildrenOfItem:anItem]))
|
||||||
{
|
{
|
||||||
var index = 0,
|
var index = 0,
|
||||||
count = [dataSource outlineView:anOutlineView numberOfChildrenOfItem:anItem],
|
count = [dataSource outlineView:anOutlineView numberOfChildrenOfItem:anItem],
|
||||||
level = itemInfo.level + 1;
|
level = itemInfo.level + 1;
|
||||||
|
|
||||||
itemInfo.children = [];
|
itemInfo.children = [];
|
||||||
|
|
||||||
for (; index < count; ++index)
|
for (; index < count; ++index)
|
||||||
{
|
{
|
||||||
var childItem = [dataSource outlineView:anOutlineView child:index ofItem:anItem],
|
var childItem = [dataSource outlineView:anOutlineView child:index ofItem:anItem],
|
||||||
childItemInfo = itemInfosForItems[[childItem UID]];
|
childItemInfo = itemInfosForItems[[childItem UID]];
|
||||||
|
|
||||||
if (!childItemInfo)
|
if (!childItemInfo)
|
||||||
{
|
{
|
||||||
childItemInfo = { isExpanded:NO, isExpandable:NO, children:[], weight:1 };
|
childItemInfo = { isExpanded:NO, isExpandable:NO, children:[], weight:1 };
|
||||||
itemInfosForItems[[childItem UID]] = childItemInfo;
|
itemInfosForItems[[childItem UID]] = childItemInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
itemInfo.children[index] = childItem;
|
itemInfo.children[index] = childItem;
|
||||||
|
|
||||||
var childDescendants = _loadItemInfoForItem(anOutlineView, childItem, YES);
|
var childDescendants = _loadItemInfoForItem(anOutlineView, childItem, YES);
|
||||||
|
|
||||||
childItemInfo.parent = anItem;
|
childItemInfo.parent = anItem;
|
||||||
childItemInfo.level = level;
|
childItemInfo.level = level;
|
||||||
descendants = descendants.concat(childDescendants);
|
descendants = descendants.concat(childDescendants);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
itemInfo.weight = descendants.length;
|
itemInfo.weight = descendants.length;
|
||||||
|
|
||||||
if (!isIntermediate)
|
if (!isIntermediate)
|
||||||
{
|
{
|
||||||
// row = -1 is the root item, so just go to row 0 since it is ignored.
|
// row = -1 is the root item, so just go to row 0 since it is ignored.
|
||||||
var index = MAX(itemInfo.row, 0),
|
var index = MAX(itemInfo.row, 0),
|
||||||
itemsForRows = _itemsForRows;
|
itemsForRows = _itemsForRows;
|
||||||
|
|
||||||
descendants.unshift(index, weight);
|
descendants.unshift(index, weight);
|
||||||
|
|
||||||
itemsForRows.splice.apply(itemsForRows, descendants);
|
itemsForRows.splice.apply(itemsForRows, descendants);
|
||||||
|
|
||||||
var count = itemsForRows.length;
|
var count = itemsForRows.length;
|
||||||
|
|
||||||
for (; index < count; ++index)
|
for (; index < count; ++index)
|
||||||
itemInfosForItems[[itemsForRows[index] UID]].row = index;
|
itemInfosForItems[[itemsForRows[index] UID]].row = index;
|
||||||
|
|
||||||
var deltaWeight = itemInfo.weight - weight;
|
var deltaWeight = itemInfo.weight - weight;
|
||||||
|
|
||||||
if (deltaWeight !== 0)
|
if (deltaWeight !== 0)
|
||||||
{
|
{
|
||||||
var parent = itemInfo.parent;
|
var parent = itemInfo.parent;
|
||||||
|
|
||||||
while (parent)
|
while (parent)
|
||||||
{
|
{
|
||||||
var parentItemInfo = itemInfosForItems[[parent UID]];
|
var parentItemInfo = itemInfosForItems[[parent UID]];
|
||||||
|
|
||||||
parentItemInfo.weight += deltaWeight;
|
parentItemInfo.weight += deltaWeight;
|
||||||
parent = parentItemInfo.parent;
|
parent = parentItemInfo.parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (anItem)
|
if (anItem)
|
||||||
_rootItemInfo.weight += deltaWeight;
|
_rootItemInfo.weight += deltaWeight;
|
||||||
}
|
}
|
||||||
@@ -1038,27 +880,20 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
|
|||||||
return [_outlineView._outlineViewDataSource outlineView:_outlineView objectValueForTableColumn:aTableColumn byItem:_outlineView._itemsForRows[aRow]];
|
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
|
- (BOOL)tableView:(CPTableView)aTableColumn writeRowsWithIndexes:(CPIndexSet)theIndexes toPasteboard:(CPPasteboard)thePasteboard
|
||||||
{
|
{
|
||||||
if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_writeItems_toPasteboard_))
|
if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_writeItems_toPasteboard_))
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
var rowIndexes = [];
|
var rowIndexes = [];
|
||||||
[theIndexes getIndexes:rowIndexes maxCount:[theIndexes count] inIndexRange:nil];
|
[theIndexes getIndexes:rowIndexes maxCount:[theIndexes count] inIndexRange:nil];
|
||||||
|
|
||||||
var rowIndex = [rowIndexes count],
|
var rowIndex = [rowIndexes count],
|
||||||
items = [];
|
items = [];
|
||||||
|
|
||||||
while (rowIndex--)
|
while (rowIndex--)
|
||||||
[items addObject:[_outlineView itemAtRow:[rowIndexes objectAtIndex:rowIndex]]];
|
[items addObject:[_outlineView itemAtRow:[rowIndexes objectAtIndex:rowIndex]]];
|
||||||
|
|
||||||
return [_outlineView._outlineViewDataSource outlineView:_outlineView writeItems:items toPasteboard:thePasteboard];
|
return [_outlineView._outlineViewDataSource outlineView:_outlineView writeItems:items toPasteboard:thePasteboard];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1066,15 +901,15 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
|
|||||||
{
|
{
|
||||||
if (_outlineView._shouldRetargetChildIndex)
|
if (_outlineView._shouldRetargetChildIndex)
|
||||||
return _outlineView._retargedChildIndex;
|
return _outlineView._retargedChildIndex;
|
||||||
|
|
||||||
var childIndex = CPNotFound;
|
var childIndex = CPNotFound;
|
||||||
|
|
||||||
if (theDropOperation === CPTableViewDropAbove)
|
if (theDropOperation === CPTableViewDropAbove)
|
||||||
{
|
{
|
||||||
var parentItem = [_outlineView _parentItemForUpperRow:theRow - 1 andLowerRow:theRow atMouseOffset:theOffset],
|
var parentItem = [_outlineView _parentItemForUpperRow:theRow - 1 andLowerRow:theRow atMouseOffset:theOffset],
|
||||||
itemInfo = (parentItem !== nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo,
|
itemInfo = (parentItem !== nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo,
|
||||||
children = itemInfo.children;
|
children = itemInfo.children;
|
||||||
|
|
||||||
childIndex = [children indexOfObject:[_outlineView itemAtRow:theRow]];
|
childIndex = [children indexOfObject:[_outlineView itemAtRow:theRow]];
|
||||||
|
|
||||||
if (childIndex === CPNotFound)
|
if (childIndex === CPNotFound)
|
||||||
@@ -1089,12 +924,12 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
|
|||||||
- (void)_parentItemForDropOperation:(CPTableViewDropOperation)theDropOperation row:(int)theRow offset:(CPPoint)theOffset
|
- (void)_parentItemForDropOperation:(CPTableViewDropOperation)theDropOperation row:(int)theRow offset:(CPPoint)theOffset
|
||||||
{
|
{
|
||||||
if (theDropOperation === CPTableViewDropAbove)
|
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];
|
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
|
proposedRow:(int)theRow proposedDropOperation:(CPTableViewDropOperation)theOperation
|
||||||
{
|
{
|
||||||
if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_validateDrop_proposedItem_proposedChildIndex_))
|
if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_validateDrop_proposedItem_proposedChildIndex_))
|
||||||
@@ -1108,21 +943,21 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
|
|||||||
_outlineView._shouldRetargetChildIndex = NO;
|
_outlineView._shouldRetargetChildIndex = NO;
|
||||||
|
|
||||||
var location = [_outlineView convertPoint:[theInfo draggingLocation] fromView:nil],
|
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];
|
childIndex = [self _childIndexForDropOperation:theOperation row:theRow offset:location];
|
||||||
|
|
||||||
return [_outlineView._outlineViewDataSource outlineView:_outlineView validateDrop:theInfo proposedItem:parentItem proposedChildIndex:childIndex];
|
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
|
- (BOOL)tableView:(CPTableView)aTableView acceptDrop:(id <CPDraggingInfo>)theInfo row:(int)theRow dropOperation:(CPTableViewDropOperation)theOperation
|
||||||
{
|
{
|
||||||
if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_acceptDrop_item_childIndex_))
|
if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_acceptDrop_item_childIndex_))
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
var location = [_outlineView convertPoint:[theInfo draggingLocation] fromView:nil],
|
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];
|
childIndex = [self _childIndexForDropOperation:theOperation row:theRow offset:location];
|
||||||
|
|
||||||
_outlineView._retargetedItem = nil;
|
_outlineView._retargetedItem = nil;
|
||||||
_outlineView._shouldRetargetItem = NO;
|
_outlineView._shouldRetargetItem = NO;
|
||||||
|
|
||||||
@@ -1152,15 +987,15 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
|
|||||||
- (CPView)tableView:(CPTableView)theTableView dataViewForTableColumn:(CPTableColumn)theTableColumn row:(int)theRow
|
- (CPView)tableView:(CPTableView)theTableView dataViewForTableColumn:(CPTableColumn)theTableColumn row:(int)theRow
|
||||||
{
|
{
|
||||||
var dataView = nil;
|
var dataView = nil;
|
||||||
|
|
||||||
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_))
|
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_))
|
||||||
dataView = [_outlineView._outlineViewDelegate outlineView:_outlineView
|
dataView = [_outlineView._outlineViewDelegate outlineView:_outlineView
|
||||||
dataViewForTableColumn:theTableColumn
|
dataViewForTableColumn:theTableColumn
|
||||||
item:[_outlineView itemAtRow:theRow]];
|
item:[_outlineView itemAtRow:theRow]];
|
||||||
|
|
||||||
if (!dataView)
|
if (!dataView)
|
||||||
dataView = [theTableColumn dataViewForRow:theRow];
|
dataView = [theTableColumn dataViewForRow:theRow];
|
||||||
|
|
||||||
return dataView;
|
return dataView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1168,18 +1003,10 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
|
|||||||
{
|
{
|
||||||
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldSelectItem_))
|
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldSelectItem_))
|
||||||
return [_outlineView._outlineViewDelegate outlineView:_outlineView shouldSelectItem:[_outlineView itemAtRow:theRow]];
|
return [_outlineView._outlineViewDelegate outlineView:_outlineView shouldSelectItem:[_outlineView itemAtRow:theRow]];
|
||||||
|
|
||||||
return YES;
|
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
|
- (float)tableView:(CPTableView)theTableView heightOfRow:(int)theRow
|
||||||
{
|
{
|
||||||
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_heightOfRowByItem_))
|
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_heightOfRowByItem_))
|
||||||
@@ -1197,10 +1024,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_))
|
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;
|
return NO;
|
||||||
}
|
}
|
||||||
@@ -1253,82 +1080,9 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
|
|||||||
CGContextAddLineToPoint(context, 0.0, 0.0);
|
CGContextAddLineToPoint(context, 0.0, 0.0);
|
||||||
|
|
||||||
CGContextClosePath(context);
|
CGContextClosePath(context);
|
||||||
CGContextSetFillColor(context,
|
|
||||||
colorForDisclosureTriangle([self hasThemeState:CPThemeStateSelected],
|
CGContextSetFillColor(context, [self isHighlighted] ? [CPColor whiteColor] : [CPColor grayColor]);
|
||||||
[self hasThemeState:CPThemeStateHighlighted]));
|
|
||||||
CGContextFillPath(context);
|
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
|
@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]);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -25,6 +25,8 @@
|
|||||||
@import <Foundation/CPDictionary.j>
|
@import <Foundation/CPDictionary.j>
|
||||||
@import <Foundation/CPPropertyListSerialization.j>
|
@import <Foundation/CPPropertyListSerialization.j>
|
||||||
|
|
||||||
|
#include "Platform/Platform.h"
|
||||||
|
|
||||||
|
|
||||||
CPGeneralPboard = @"CPGeneralPboard";
|
CPGeneralPboard = @"CPGeneralPboard";
|
||||||
CPFontPboard = @"CPFontPboard";
|
CPFontPboard = @"CPFontPboard";
|
||||||
|
|||||||
+41
-65
@@ -25,12 +25,14 @@
|
|||||||
@import "CPMenu.j"
|
@import "CPMenu.j"
|
||||||
@import "CPMenuItem.j"
|
@import "CPMenuItem.j"
|
||||||
|
|
||||||
|
#include "CoreGraphics/CGGeometry.h"
|
||||||
|
|
||||||
|
|
||||||
var VISIBLE_MARGIN = 7.0;
|
var VISIBLE_MARGIN = 7.0;
|
||||||
|
|
||||||
CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPPopUpButton
|
@class CPPopUpButton
|
||||||
|
|
||||||
@@ -40,11 +42,11 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
|||||||
{
|
{
|
||||||
int _selectedIndex;
|
int _selectedIndex;
|
||||||
CPRectEdge _preferredEdge;
|
CPRectEdge _preferredEdge;
|
||||||
|
|
||||||
CPMenu _menu;
|
CPMenu _menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (CPString)defaultThemeClass
|
+ (CPString)themeClass
|
||||||
{
|
{
|
||||||
return "popup-button";
|
return "popup-button";
|
||||||
}
|
}
|
||||||
@@ -58,21 +60,21 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
|||||||
- (id)initWithFrame:(CGRect)aFrame pullsDown:(BOOL)shouldPullDown
|
- (id)initWithFrame:(CGRect)aFrame pullsDown:(BOOL)shouldPullDown
|
||||||
{
|
{
|
||||||
self = [super initWithFrame:aFrame];
|
self = [super initWithFrame:aFrame];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_selectedIndex = CPNotFound;
|
_selectedIndex = CPNotFound;
|
||||||
_preferredEdge = CPMaxYEdge;
|
_preferredEdge = CPMaxYEdge;
|
||||||
|
|
||||||
[self setValue:CPImageLeft forThemeAttribute:@"image-position"];
|
[self setValue:CPImageLeft forThemeAttribute:@"image-position"];
|
||||||
[self setValue:CPLeftTextAlignment forThemeAttribute:@"alignment"];
|
[self setValue:CPLeftTextAlignment forThemeAttribute:@"alignment"];
|
||||||
[self setValue:CPLineBreakByTruncatingTail forThemeAttribute:@"line-break-mode"];
|
[self setValue:CPLineBreakByTruncatingTail forThemeAttribute:@"line-break-mode"];
|
||||||
|
|
||||||
[self setMenu:[[CPMenu alloc] initWithTitle:@""]];
|
[self setMenu:[[CPMenu alloc] initWithTitle:@""]];
|
||||||
|
|
||||||
[self setPullsDown:shouldPullDown];
|
[self setPullsDown:shouldPullDown];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +145,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
|||||||
{
|
{
|
||||||
var index = 0,
|
var index = 0,
|
||||||
count = [titles count];
|
count = [titles count];
|
||||||
|
|
||||||
for (; index < count; ++index)
|
for (; index < count; ++index)
|
||||||
[self addItemWithTitle:titles[index]];
|
[self addItemWithTitle:titles[index]];
|
||||||
}
|
}
|
||||||
@@ -157,11 +159,11 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
|||||||
{
|
{
|
||||||
var items = [self itemArray],
|
var items = [self itemArray],
|
||||||
count = [items count];
|
count = [items count];
|
||||||
|
|
||||||
while (count--)
|
while (count--)
|
||||||
if ([items[count] title] == aTitle)
|
if ([items[count] title] == aTitle)
|
||||||
[self removeItemAtIndex:count];
|
[self removeItemAtIndex:count];
|
||||||
|
|
||||||
[_menu insertItemWithTitle:aTitle action:NULL keyEquivalent:nil atIndex:anIndex];
|
[_menu insertItemWithTitle:aTitle action:NULL keyEquivalent:nil atIndex:anIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +173,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
|||||||
- (void)removeAllItems
|
- (void)removeAllItems
|
||||||
{
|
{
|
||||||
var count = [_menu numberOfItems];
|
var count = [_menu numberOfItems];
|
||||||
|
|
||||||
while (count--)
|
while (count--)
|
||||||
[_menu removeItemAtIndex:0];
|
[_menu removeItemAtIndex:0];
|
||||||
}
|
}
|
||||||
@@ -204,7 +206,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
|||||||
{
|
{
|
||||||
if (_selectedIndex < 0 || _selectedIndex > [self numberOfItems] - 1)
|
if (_selectedIndex < 0 || _selectedIndex > [self numberOfItems] - 1)
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
return [_menu itemAtIndex:_selectedIndex];
|
return [_menu itemAtIndex:_selectedIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,15 +253,15 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
|||||||
{
|
{
|
||||||
if (_selectedIndex == anIndex)
|
if (_selectedIndex == anIndex)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_selectedIndex >= 0 && ![self pullsDown])
|
if (_selectedIndex >= 0 && ![self pullsDown])
|
||||||
[[self selectedItem] setState:CPOffState];
|
[[self selectedItem] setState:CPOffState];
|
||||||
|
|
||||||
_selectedIndex = anIndex;
|
_selectedIndex = anIndex;
|
||||||
|
|
||||||
if (_selectedIndex >= 0 && ![self pullsDown])
|
if (_selectedIndex >= 0 && ![self pullsDown])
|
||||||
[[self selectedItem] setState:CPOnState];
|
[[self selectedItem] setState:CPOnState];
|
||||||
|
|
||||||
[self synchronizeTitleAndSelectedItem];
|
[self synchronizeTitleAndSelectedItem];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,7 +310,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var defaultCenter = [CPNotificationCenter defaultCenter];
|
var defaultCenter = [CPNotificationCenter defaultCenter];
|
||||||
|
|
||||||
if (_menu)
|
if (_menu)
|
||||||
{
|
{
|
||||||
[defaultCenter
|
[defaultCenter
|
||||||
@@ -328,7 +330,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
|||||||
}
|
}
|
||||||
|
|
||||||
_menu = aMenu;
|
_menu = aMenu;
|
||||||
|
|
||||||
if (_menu)
|
if (_menu)
|
||||||
{
|
{
|
||||||
[defaultCenter
|
[defaultCenter
|
||||||
@@ -336,20 +338,20 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
|||||||
selector:@selector(menuDidAddItem:)
|
selector:@selector(menuDidAddItem:)
|
||||||
name:CPMenuDidAddItemNotification
|
name:CPMenuDidAddItemNotification
|
||||||
object:_menu];
|
object:_menu];
|
||||||
|
|
||||||
[defaultCenter
|
[defaultCenter
|
||||||
addObserver:self
|
addObserver:self
|
||||||
selector:@selector(menuDidChangeItem:)
|
selector:@selector(menuDidChangeItem:)
|
||||||
name:CPMenuDidChangeItemNotification
|
name:CPMenuDidChangeItemNotification
|
||||||
object:_menu];
|
object:_menu];
|
||||||
|
|
||||||
[defaultCenter
|
[defaultCenter
|
||||||
addObserver:self
|
addObserver:self
|
||||||
selector:@selector(menuDidRemoveItem:)
|
selector:@selector(menuDidRemoveItem:)
|
||||||
name:CPMenuDidRemoveItemNotification
|
name:CPMenuDidRemoveItemNotification
|
||||||
object:_menu];
|
object:_menu];
|
||||||
}
|
}
|
||||||
|
|
||||||
[self synchronizeTitleAndSelectedItem];
|
[self synchronizeTitleAndSelectedItem];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,13 +396,12 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
|||||||
{
|
{
|
||||||
var titles = [],
|
var titles = [],
|
||||||
items = [self itemArray],
|
items = [self itemArray],
|
||||||
|
|
||||||
index = 0,
|
index = 0,
|
||||||
count = [items count];
|
count = [items count];
|
||||||
|
|
||||||
for (; index < count; ++index)
|
for (; index < count; ++index)
|
||||||
titles.push([items[index] title]);
|
items.push([items[index] title]);
|
||||||
|
|
||||||
return titles;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -518,14 +519,14 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var index = [self indexOfItemWithTitle:aTitle];
|
var index = [self indexOfItemWithTitle:aTitle];
|
||||||
|
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
{
|
{
|
||||||
[self addItemWithTitle:aTitle];
|
[self addItemWithTitle:aTitle];
|
||||||
|
|
||||||
index = [self numberOfItems] - 1;
|
index = [self numberOfItems] - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
[self selectItemAtIndex:index];
|
[self selectItemAtIndex:index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -553,7 +554,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
|||||||
if ([self pullsDown])
|
if ([self pullsDown])
|
||||||
{
|
{
|
||||||
var items = [_menu itemArray];
|
var items = [_menu itemArray];
|
||||||
|
|
||||||
if ([items count] > 0)
|
if ([items count] > 0)
|
||||||
item = items[0];
|
item = items[0];
|
||||||
}
|
}
|
||||||
@@ -572,22 +573,22 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
|||||||
- (void)menuDidAddItem:(CPNotification)aNotification
|
- (void)menuDidAddItem:(CPNotification)aNotification
|
||||||
{
|
{
|
||||||
var index = [[aNotification userInfo] objectForKey:@"CPMenuItemIndex"];
|
var index = [[aNotification userInfo] objectForKey:@"CPMenuItemIndex"];
|
||||||
|
|
||||||
if (_selectedIndex < 0)
|
if (_selectedIndex < 0)
|
||||||
[self selectItemAtIndex:0];
|
[self selectItemAtIndex:0];
|
||||||
|
|
||||||
else if (index == _selectedIndex)
|
else if (index == _selectedIndex)
|
||||||
[self synchronizeTitleAndSelectedItem];
|
[self synchronizeTitleAndSelectedItem];
|
||||||
|
|
||||||
else if (index < _selectedIndex)
|
else if (index < _selectedIndex)
|
||||||
++_selectedIndex;
|
++_selectedIndex;
|
||||||
|
|
||||||
if (index == 0 && [self pullsDown])
|
if (index == 0 && [self pullsDown])
|
||||||
{
|
{
|
||||||
var items = [_menu itemArray];
|
var items = [_menu itemArray];
|
||||||
|
|
||||||
[items[0] setHidden:YES];
|
[items[0] setHidden:YES];
|
||||||
|
|
||||||
if (items.length > 0)
|
if (items.length > 0)
|
||||||
[items[1] setHidden:NO];
|
[items[1] setHidden:NO];
|
||||||
}
|
}
|
||||||
@@ -612,10 +613,10 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
|||||||
|
|
||||||
if ([self pullsDown] && index != 0)
|
if ([self pullsDown] && index != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (![self pullsDown] && index != _selectedIndex)
|
if (![self pullsDown] && index != _selectedIndex)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[self synchronizeTitleAndSelectedItem];
|
[self synchronizeTitleAndSelectedItem];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -626,7 +627,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
|||||||
- (void)menuDidRemoveItem:(CPNotification)aNotification
|
- (void)menuDidRemoveItem:(CPNotification)aNotification
|
||||||
{
|
{
|
||||||
var numberOfItems = [self numberOfItems];
|
var numberOfItems = [self numberOfItems];
|
||||||
|
|
||||||
if (numberOfItems <= _selectedIndex && numberOfItems > 0)
|
if (numberOfItems <= _selectedIndex && numberOfItems > 0)
|
||||||
[self selectItemAtIndex:numberOfItems - 1];
|
[self selectItemAtIndex:numberOfItems - 1];
|
||||||
else
|
else
|
||||||
@@ -660,9 +661,6 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
|||||||
location = CGPointMake(CGRectGetMinX(contentRect) - standardLeftMargin, 0.0);
|
location = CGPointMake(CGRectGetMinX(contentRect) - standardLeftMargin, 0.0);
|
||||||
|
|
||||||
minimumWidth += standardLeftMargin;
|
minimumWidth += standardLeftMargin;
|
||||||
|
|
||||||
// To ensure the selected item is highlighted correctly, unset the highlighted item
|
|
||||||
[menu _highlightItemAtIndex:CPNotFound];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[menu setMinimumWidth:minimumWidth];
|
[menu setMinimumWidth:minimumWidth];
|
||||||
@@ -700,33 +698,11 @@ 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
|
- (void)_popUpItemAction:(id)aSender
|
||||||
{
|
{
|
||||||
[self sendAction:[self action] to:[self target]];
|
[self sendAction:[self action] to:[self target]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)takeValueFromKeyPath:(CPString)aKeyPath ofObjects:(CPArray)objects
|
|
||||||
{
|
|
||||||
var count = objects.length,
|
|
||||||
value = [objects[0] valueForKeyPath:aKeyPath];
|
|
||||||
|
|
||||||
[self selectItemWithTag:value];
|
|
||||||
[self setEnabled:YES];
|
|
||||||
|
|
||||||
while (count-- > 1)
|
|
||||||
{
|
|
||||||
if (value !== [objects[count] valueForKeyPath:aKeyPath])
|
|
||||||
{
|
|
||||||
[[self selectedItem] setState:CPOffState];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
|
var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
|
||||||
@@ -744,7 +720,7 @@ var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
|
|||||||
- (id)initWithCoder:(CPCoder)aCoder
|
- (id)initWithCoder:(CPCoder)aCoder
|
||||||
{
|
{
|
||||||
self = [super initWithCoder:aCoder];
|
self = [super initWithCoder:aCoder];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
// Nothing is currently selected
|
// Nothing is currently selected
|
||||||
@@ -753,7 +729,7 @@ var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
|
|||||||
[self setMenu:[aCoder decodeObjectForKey:CPPopUpButtonMenuKey]];
|
[self setMenu:[aCoder decodeObjectForKey:CPPopUpButtonMenuKey]];
|
||||||
[self selectItemAtIndex:[aCoder decodeObjectForKey:CPPopUpButtonSelectedIndexKey]];
|
[self selectItemAtIndex:[aCoder decodeObjectForKey:CPPopUpButtonSelectedIndexKey]];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -765,7 +741,7 @@ var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
|
|||||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||||
{
|
{
|
||||||
[super encodeWithCoder:aCoder];
|
[super encodeWithCoder:aCoder];
|
||||||
|
|
||||||
[aCoder encodeObject:_menu forKey:CPPopUpButtonMenuKey];
|
[aCoder encodeObject:_menu forKey:CPPopUpButtonMenuKey];
|
||||||
[aCoder encodeInt:_selectedIndex forKey:CPPopUpButtonSelectedIndexKey];
|
[aCoder encodeInt:_selectedIndex forKey:CPPopUpButtonSelectedIndexKey];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,9 +20,11 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@import "CGGeometry.j"
|
@import <AppKit/CGGeometry.j>
|
||||||
@import "CPImageView.j"
|
@import <AppKit/CPImageView.j>
|
||||||
@import "CPView.j"
|
@import <AppKit/CPView.j>
|
||||||
|
|
||||||
|
#include "CoreGraphics/CGGeometry.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
+15
-19
@@ -25,29 +25,28 @@
|
|||||||
|
|
||||||
@import "CPButton.j"
|
@import "CPButton.j"
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
|
|
||||||
from this mailing list thread:
|
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:
|
Creating a checkbox is easy enough:
|
||||||
|
|
||||||
checkbox = [[CPCheckBox alloc] initWithFrame:aFrame];
|
checkbox = [[CPCheckBox alloc] initWithFrame:aFrame];
|
||||||
|
|
||||||
That's basically all there is to it. Radio buttons are very similar,
|
That's basically all there is to it. Radio buttons are very similar,
|
||||||
the key difference is the introduction of a new class CPRadioGroup,
|
the key difference is the introduction of a new class CPRadioGroup,
|
||||||
which defines which radio buttons are part of the same group:
|
which defines which radio buttons are part of the same group:
|
||||||
|
|
||||||
[myRadioButton setRadioGroup:aRadioGroup];
|
[myRadioButton setRadioGroup:aRadioGroup];
|
||||||
|
|
||||||
Every radio button receives a unique radio group by default (so if you
|
Every radio button receives a unique radio group by default (so if you
|
||||||
do nothing further, they will all behave independently), but you can
|
do nothing further, they will all behave independently), but you can
|
||||||
use an existing radio button's group with other buttons as so:
|
use an existing radio button's group with other buttons as so:
|
||||||
|
|
||||||
button1 = [[CPRadio alloc] initWithFrame:aFrame];
|
button1 = [[CPRadio alloc] initWithFrame:aFrame];
|
||||||
...
|
...
|
||||||
button2 = [[CPRadio alloc] initWithFrame:aFrame radioGroup:[button1
|
button2 = [[CPRadio alloc] initWithFrame:aFrame radioGroup:[button1
|
||||||
@@ -56,16 +55,13 @@
|
|||||||
button3 = [[CPRadio alloc] initWithFrame:aFrame radioGroup:[button1
|
button3 = [[CPRadio alloc] initWithFrame:aFrame radioGroup:[button1
|
||||||
radioGroup]];
|
radioGroup]];
|
||||||
...etc...
|
...etc...
|
||||||
|
|
||||||
Here, all the radio buttons will act "together". [[button1 radioGroup]
|
Here, all the radio buttons will act "together". [[button1 radioGroup]
|
||||||
allRadios] returns every button that's part of this group, and
|
allRadios] returns every button that's part of this group, and
|
||||||
[[button1 radioGroup] selectedRadio] returns the currently selected
|
[[button1 radioGroup] selectedRadio] returns the currently selected
|
||||||
option.
|
option.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CPRadioImageOffset = 4.0;
|
|
||||||
|
|
||||||
@implementation CPRadio : CPButton
|
@implementation CPRadio : CPButton
|
||||||
{
|
{
|
||||||
CPRadioGroup _radioGroup;
|
CPRadioGroup _radioGroup;
|
||||||
@@ -90,7 +86,7 @@ CPRadioImageOffset = 4.0;
|
|||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (CPString)defaultThemeClass
|
+ (CPString)themeClass
|
||||||
{
|
{
|
||||||
return @"radio";
|
return @"radio";
|
||||||
}
|
}
|
||||||
@@ -99,7 +95,7 @@ CPRadioImageOffset = 4.0;
|
|||||||
- (id)initWithFrame:(CGRect)aFrame radioGroup:(CPRadioGroup)aRadioGroup
|
- (id)initWithFrame:(CGRect)aFrame radioGroup:(CPRadioGroup)aRadioGroup
|
||||||
{
|
{
|
||||||
self = [super initWithFrame:aFrame];
|
self = [super initWithFrame:aFrame];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
[self setRadioGroup:aRadioGroup];
|
[self setRadioGroup:aRadioGroup];
|
||||||
@@ -113,8 +109,8 @@ CPRadioImageOffset = 4.0;
|
|||||||
|
|
||||||
[self setBordered:YES];
|
[self setBordered:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithFrame:(CGRect)aFrame
|
- (id)initWithFrame:(CGRect)aFrame
|
||||||
@@ -145,7 +141,7 @@ CPRadioImageOffset = 4.0;
|
|||||||
- (void)setObjectValue:(id)aValue
|
- (void)setObjectValue:(id)aValue
|
||||||
{
|
{
|
||||||
[super setObjectValue:aValue];
|
[super setObjectValue:aValue];
|
||||||
|
|
||||||
if ([self state] === CPOnState)
|
if ([self state] === CPOnState)
|
||||||
[_radioGroup _setSelectedRadio:self];
|
[_radioGroup _setSelectedRadio:self];
|
||||||
}
|
}
|
||||||
|
|||||||
+53
-47
@@ -23,23 +23,22 @@
|
|||||||
@import <Foundation/CPObject.j>
|
@import <Foundation/CPObject.j>
|
||||||
|
|
||||||
|
|
||||||
CPDeleteKeyCode = 8;
|
CPDeleteKeyCode = 8;
|
||||||
CPTabKeyCode = 9;
|
CPTabKeyCode = 9;
|
||||||
CPReturnKeyCode = 13;
|
CPReturnKeyCode = 13;
|
||||||
CPEscapeKeyCode = 27;
|
CPEscapeKeyCode = 27;
|
||||||
CPSpaceKeyCode = 32;
|
CPSpaceKeyCode = 32;
|
||||||
CPPageUpKeyCode = 33;
|
CPPageUpKeyCode = 33;
|
||||||
CPPageDownKeyCode = 34;
|
CPPageDownKeyCode = 34;
|
||||||
CPLeftArrowKeyCode = 37;
|
CPLeftArrowKeyCode = 37;
|
||||||
CPUpArrowKeyCode = 38;
|
CPUpArrowKeyCode = 38;
|
||||||
CPRightArrowKeyCode = 39;
|
CPRightArrowKeyCode = 39;
|
||||||
CPDownArrowKeyCode = 40;
|
CPDownArrowKeyCode = 40;
|
||||||
CPDeleteForwardKeyCode = 46;
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPResponder
|
@class CPResponder
|
||||||
|
|
||||||
Subclasses of CPResonder can be part of the responder chain.
|
Subclasses of CPResonder can be part of the responder chain.
|
||||||
*/
|
*/
|
||||||
@implementation CPResponder : CPObject
|
@implementation CPResponder : CPObject
|
||||||
@@ -105,24 +104,42 @@ CPDeleteForwardKeyCode = 46;
|
|||||||
|
|
||||||
for (; index < count; ++index)
|
for (; index < count; ++index)
|
||||||
{
|
{
|
||||||
var event = events[index],
|
var event = events[index];
|
||||||
modifierFlags = [event modifierFlags],
|
|
||||||
character = [event charactersIgnoringModifiers],
|
|
||||||
selectorNames = [CPKeyBinding selectorsForKey:character modifierFlags:modifierFlags];
|
|
||||||
|
|
||||||
if (selectorNames)
|
switch([event keyCode])
|
||||||
{
|
{
|
||||||
for (var s = 0, scount = selectorNames.length; s < scount; s++)
|
case CPPageUpKeyCode: [self doCommandBySelector:@selector(pageUp:)];
|
||||||
{
|
break;
|
||||||
var selector = selectorNames[s];
|
case CPPageDownKeyCode: [self doCommandBySelector:@selector(pageDown:)];
|
||||||
if (!selector)
|
break;
|
||||||
continue;
|
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];
|
[_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.
|
FIXME This description is bad.
|
||||||
Based on \c anEvent, the receiver should simulate the event.
|
Based on \c anEvent, the receiver should simulate the event.
|
||||||
@@ -261,6 +269,10 @@ CPDeleteForwardKeyCode = 46;
|
|||||||
[[self nextResponder] insertNewline:aSender];
|
[[self nextResponder] insertNewline:aSender];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)cancel:(id)sender
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
- (void)insertTab:(id)sender
|
- (void)insertTab:(id)sender
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -300,10 +312,10 @@ CPDeleteForwardKeyCode = 46;
|
|||||||
*/
|
*/
|
||||||
- (BOOL)tryToPerform:(SEL)aSelector with:(id)anObject
|
- (BOOL)tryToPerform:(SEL)aSelector with:(id)anObject
|
||||||
{
|
{
|
||||||
if ([self respondsToSelector:aSelector])
|
if([self respondsToSelector:aSelector])
|
||||||
{
|
{
|
||||||
[self performSelector:aSelector withObject:anObject];
|
[self performSelector:aSelector withObject:anObject];
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,8 +354,7 @@ CPDeleteForwardKeyCode = 46;
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
var CPResponderNextResponderKey = @"CPResponderNextResponderKey",
|
var CPResponderNextResponderKey = @"CPResponderNextResponderKey";
|
||||||
CPResponderMenuKey = @"CPResponderMenuKey";
|
|
||||||
|
|
||||||
@implementation CPResponder (CPCoding)
|
@implementation CPResponder (CPCoding)
|
||||||
|
|
||||||
@@ -355,13 +366,10 @@ var CPResponderNextResponderKey = @"CPResponderNextResponderKey",
|
|||||||
- (id)initWithCoder:(CPCoder)aCoder
|
- (id)initWithCoder:(CPCoder)aCoder
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
|
||||||
_nextResponder = [aCoder decodeObjectForKey:CPResponderNextResponderKey];
|
_nextResponder = [aCoder decodeObjectForKey:CPResponderNextResponderKey];
|
||||||
_menu = [aCoder decodeObjectForKey:CPResponderMenuKey];
|
|
||||||
}
|
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,8 +382,6 @@ var CPResponderNextResponderKey = @"CPResponderNextResponderKey",
|
|||||||
// This will come out nil on the other side with decodeObjectForKey:
|
// This will come out nil on the other side with decodeObjectForKey:
|
||||||
if (_nextResponder !== nil)
|
if (_nextResponder !== nil)
|
||||||
[aCoder encodeConditionalObject:_nextResponder forKey:CPResponderNextResponderKey];
|
[aCoder encodeConditionalObject:_nextResponder forKey:CPResponderNextResponderKey];
|
||||||
|
|
||||||
[aCoder encodeObject:_menu forKey:CPResponderMenuKey];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
@import "CPPanel.j"
|
@import <AppKit/CPPanel.j>
|
||||||
|
|
||||||
|
|
||||||
@implementation CPSavePanel : CPPanel
|
@implementation CPSavePanel : CPPanel
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
|
|
||||||
@import <Foundation/CPObject.j>
|
@import <Foundation/CPObject.j>
|
||||||
|
|
||||||
|
#import "CoreGraphics/CGGeometry.h"
|
||||||
|
#import "Platform/Platform.h"
|
||||||
|
|
||||||
@implementation CPScreen : CPObject
|
@implementation CPScreen : CPObject
|
||||||
{
|
{
|
||||||
|
|||||||
+96
-386
@@ -20,13 +20,14 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@import "CPBox.j"
|
@import "CPView.j"
|
||||||
@import "CPClipView.j"
|
@import "CPClipView.j"
|
||||||
@import "CPScroller.j"
|
@import "CPScroller.j"
|
||||||
@import "CPView.j"
|
|
||||||
|
#include "CoreGraphics/CGGeometry.h"
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPScrollView
|
@class CPScrollView
|
||||||
|
|
||||||
@@ -36,39 +37,23 @@
|
|||||||
*/
|
*/
|
||||||
@implementation CPScrollView : CPView
|
@implementation CPScrollView : CPView
|
||||||
{
|
{
|
||||||
CPClipView _contentView;
|
CPClipView _contentView;
|
||||||
CPClipView _headerClipView;
|
CPClipView _headerClipView;
|
||||||
CPView _cornerView;
|
CPView _cornerView;
|
||||||
CPView _bottomCornerView;
|
|
||||||
|
|
||||||
BOOL _hasVerticalScroller;
|
BOOL _hasVerticalScroller;
|
||||||
BOOL _hasHorizontalScroller;
|
BOOL _hasHorizontalScroller;
|
||||||
BOOL _autohidesScrollers;
|
BOOL _autohidesScrollers;
|
||||||
|
|
||||||
CPScroller _verticalScroller;
|
CPScroller _verticalScroller;
|
||||||
CPScroller _horizontalScroller;
|
CPScroller _horizontalScroller;
|
||||||
|
|
||||||
int _recursionCount;
|
int _recursionCount;
|
||||||
|
|
||||||
float _verticalLineScroll;
|
float _verticalLineScroll;
|
||||||
float _verticalPageScroll;
|
float _verticalPageScroll;
|
||||||
float _horizontalLineScroll;
|
float _horizontalLineScroll;
|
||||||
float _horizontalPageScroll;
|
float _horizontalPageScroll;
|
||||||
|
|
||||||
CPBorderType _borderType;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (CPString)defaultThemeClass
|
|
||||||
{
|
|
||||||
return @"scrollview"
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (CPDictionary)themeAttributes
|
|
||||||
{
|
|
||||||
return [CPDictionary dictionaryWithJSObject:{
|
|
||||||
@"bottom-corner-color": [CPColor whiteColor],
|
|
||||||
@"border-color": [CPColor blackColor]
|
|
||||||
}];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithFrame:(CGRect)aFrame
|
- (id)initWithFrame:(CGRect)aFrame
|
||||||
@@ -83,17 +68,13 @@
|
|||||||
_horizontalLineScroll = 10.0;
|
_horizontalLineScroll = 10.0;
|
||||||
_horizontalPageScroll = 10.0;
|
_horizontalPageScroll = 10.0;
|
||||||
|
|
||||||
_borderType = CPNoBorder;
|
_contentView = [[CPClipView alloc] initWithFrame:[self bounds]];
|
||||||
|
|
||||||
_contentView = [[CPClipView alloc] initWithFrame:[self _insetBounds]];
|
|
||||||
|
|
||||||
[self addSubview:_contentView];
|
[self addSubview:_contentView];
|
||||||
|
|
||||||
_headerClipView = [[CPClipView alloc] init];
|
_headerClipView = [[CPClipView alloc] init];
|
||||||
[self addSubview:_headerClipView];
|
|
||||||
|
|
||||||
_bottomCornerView = [[CPView alloc] init];
|
[self addSubview:_headerClipView];
|
||||||
[self addSubview:_bottomCornerView];
|
|
||||||
|
|
||||||
[self setHasVerticalScroller:YES];
|
[self setHasVerticalScroller:YES];
|
||||||
[self setHasHorizontalScroller:YES];
|
[self setHasHorizontalScroller:YES];
|
||||||
@@ -102,70 +83,11 @@
|
|||||||
return self;
|
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
|
// Determining component sizes
|
||||||
/*!
|
/*!
|
||||||
Returns the size of the scroll view's content view.
|
Returns the size of the scroll view's content view.
|
||||||
*/
|
*/
|
||||||
- (CGSize)contentSize
|
- (CGRect)contentSize
|
||||||
{
|
{
|
||||||
return [_contentView frame].size;
|
return [_contentView frame].size;
|
||||||
}
|
}
|
||||||
@@ -184,7 +106,7 @@
|
|||||||
*/
|
*/
|
||||||
- (void)setContentView:(CPClipView)aContentView
|
- (void)setContentView:(CPClipView)aContentView
|
||||||
{
|
{
|
||||||
if (_contentView === aContentView || !aContentView)
|
if (_contentView !== aContentView || !aContentView)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var documentView = [aContentView documentView];
|
var documentView = [aContentView documentView];
|
||||||
@@ -231,16 +153,16 @@
|
|||||||
*/
|
*/
|
||||||
- (void)reflectScrolledClipView:(CPClipView)aClipView
|
- (void)reflectScrolledClipView:(CPClipView)aClipView
|
||||||
{
|
{
|
||||||
if (_contentView !== aClipView)
|
if(_contentView !== aClipView)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_recursionCount > 5)
|
if (_recursionCount > 5)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
++_recursionCount;
|
++_recursionCount;
|
||||||
|
|
||||||
var documentView = [self documentView];
|
var documentView = [self documentView];
|
||||||
|
|
||||||
if (!documentView)
|
if (!documentView)
|
||||||
{
|
{
|
||||||
if (_autohidesScrollers)
|
if (_autohidesScrollers)
|
||||||
@@ -254,7 +176,7 @@
|
|||||||
// [_horizontalScroller setEnabled:NO];
|
// [_horizontalScroller setEnabled:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
[_contentView setFrame:[self _insetBounds]];
|
[_contentView setFrame:[self bounds]];
|
||||||
[_headerClipView setFrame:_CGRectMakeZero()];
|
[_headerClipView setFrame:_CGRectMakeZero()];
|
||||||
|
|
||||||
--_recursionCount;
|
--_recursionCount;
|
||||||
@@ -263,7 +185,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
var documentFrame = [documentView frame], // the size of the whole document
|
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],
|
headerClipViewFrame = [self _headerClipViewFrame],
|
||||||
headerClipViewHeight = _CGRectGetHeight(headerClipViewFrame);
|
headerClipViewHeight = _CGRectGetHeight(headerClipViewFrame);
|
||||||
|
|
||||||
@@ -313,10 +235,11 @@
|
|||||||
|
|
||||||
if (shouldShowVerticalScroller)
|
if (shouldShowVerticalScroller)
|
||||||
{
|
{
|
||||||
var verticalScrollerY =
|
var verticalScrollerY = MAX(_CGRectGetHeight([self _cornerViewFrame]), headerClipViewHeight),
|
||||||
MAX(_CGRectGetMinY(contentFrame), MAX(_CGRectGetMaxY([self _cornerViewFrame]), _CGRectGetMaxY(headerClipViewFrame)));
|
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 setFloatValue:(difference.height <= 0.0) ? 0.0 : scrollPoint.y / difference.height];
|
||||||
[_verticalScroller setKnobProportion:_CGRectGetHeight(contentFrame) / _CGRectGetHeight(documentFrame)];
|
[_verticalScroller setKnobProportion:_CGRectGetHeight(contentFrame) / _CGRectGetHeight(documentFrame)];
|
||||||
@@ -327,12 +250,12 @@
|
|||||||
[_verticalScroller setFloatValue:0.0];
|
[_verticalScroller setFloatValue:0.0];
|
||||||
[_verticalScroller setKnobProportion:1.0];
|
[_verticalScroller setKnobProportion:1.0];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldShowHorizontalScroller)
|
if (shouldShowHorizontalScroller)
|
||||||
{
|
{
|
||||||
[_horizontalScroller setFloatValue:(difference.width <= 0.0) ? 0.0 : scrollPoint.x / difference.width];
|
[_horizontalScroller setFloatValue:(difference.width <= 0.0) ? 0.0 : scrollPoint.x / difference.width];
|
||||||
[_horizontalScroller setKnobProportion:_CGRectGetWidth(contentFrame) / _CGRectGetWidth(documentFrame)];
|
[_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)
|
else if (wasShowingHorizontalScroller)
|
||||||
{
|
{
|
||||||
@@ -344,36 +267,9 @@
|
|||||||
[_headerClipView setFrame:headerClipViewFrame];
|
[_headerClipView setFrame:headerClipViewFrame];
|
||||||
[_cornerView setFrame:[self _cornerViewFrame]];
|
[_cornerView setFrame:[self _cornerViewFrame]];
|
||||||
|
|
||||||
[[self bottomCornerView] setFrame:[self _bottomCornerViewFrame]];
|
|
||||||
[[self bottomCornerView] setBackgroundColor:[self currentValueForThemeAttribute:@"bottom-corner-color"]];
|
|
||||||
|
|
||||||
--_recursionCount;
|
--_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
|
// Managing Scrollers
|
||||||
/*!
|
/*!
|
||||||
Sets the scroll view's horizontal scroller.
|
Sets the scroll view's horizontal scroller.
|
||||||
@@ -383,13 +279,13 @@
|
|||||||
{
|
{
|
||||||
if (_horizontalScroller === aScroller)
|
if (_horizontalScroller === aScroller)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[_horizontalScroller removeFromSuperview];
|
[_horizontalScroller removeFromSuperview];
|
||||||
[_horizontalScroller setTarget:nil];
|
[_horizontalScroller setTarget:nil];
|
||||||
[_horizontalScroller setAction:nil];
|
[_horizontalScroller setAction:nil];
|
||||||
|
|
||||||
_horizontalScroller = aScroller;
|
_horizontalScroller = aScroller;
|
||||||
|
|
||||||
[_horizontalScroller setTarget:self];
|
[_horizontalScroller setTarget:self];
|
||||||
[_horizontalScroller setAction:@selector(_horizontalScrollerDidScroll:)];
|
[_horizontalScroller setAction:@selector(_horizontalScrollerDidScroll:)];
|
||||||
|
|
||||||
@@ -420,10 +316,8 @@
|
|||||||
|
|
||||||
if (_hasHorizontalScroller && !_horizontalScroller)
|
if (_hasHorizontalScroller && !_horizontalScroller)
|
||||||
{
|
{
|
||||||
var bounds = [self _insetBounds];
|
[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 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 reflectScrolledClipView:_contentView];
|
[self reflectScrolledClipView:_contentView];
|
||||||
@@ -445,13 +339,13 @@
|
|||||||
{
|
{
|
||||||
if (_verticalScroller === aScroller)
|
if (_verticalScroller === aScroller)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[_verticalScroller removeFromSuperview];
|
[_verticalScroller removeFromSuperview];
|
||||||
[_verticalScroller setTarget:nil];
|
[_verticalScroller setTarget:nil];
|
||||||
[_verticalScroller setAction:nil];
|
[_verticalScroller setAction:nil];
|
||||||
|
|
||||||
_verticalScroller = aScroller;
|
_verticalScroller = aScroller;
|
||||||
|
|
||||||
[_verticalScroller setTarget:self];
|
[_verticalScroller setTarget:self];
|
||||||
[_verticalScroller setAction:@selector(_verticalScrollerDidScroll:)];
|
[_verticalScroller setAction:@selector(_verticalScrollerDidScroll:)];
|
||||||
|
|
||||||
@@ -483,10 +377,8 @@
|
|||||||
|
|
||||||
if (_hasVerticalScroller && !_verticalScroller)
|
if (_hasVerticalScroller && !_verticalScroller)
|
||||||
{
|
{
|
||||||
var bounds = [self _insetBounds];
|
[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 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 reflectScrolledClipView:_contentView];
|
[self reflectScrolledClipView:_contentView];
|
||||||
@@ -511,7 +403,7 @@
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
_autohidesScrollers = autohidesScrollers;
|
_autohidesScrollers = autohidesScrollers;
|
||||||
|
|
||||||
[self reflectScrolledClipView:_contentView];
|
[self reflectScrolledClipView:_contentView];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -553,7 +445,9 @@
|
|||||||
|
|
||||||
- (CPView)_headerView
|
- (CPView)_headerView
|
||||||
{
|
{
|
||||||
return [_headerClipView documentView];
|
var headerClipViewSubviews = [_headerClipView subviews];
|
||||||
|
|
||||||
|
return [headerClipViewSubviews count] ? headerClipViewSubviews[0] : nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGRect)_cornerViewFrame
|
- (CGRect)_cornerViewFrame
|
||||||
@@ -561,11 +455,11 @@
|
|||||||
if (!_cornerView)
|
if (!_cornerView)
|
||||||
return _CGRectMakeZero();
|
return _CGRectMakeZero();
|
||||||
|
|
||||||
var bounds = [self _insetBounds],
|
var bounds = [self bounds],
|
||||||
frame = [_cornerView frame];
|
frame = [_cornerView frame];
|
||||||
|
|
||||||
frame.origin.x = _CGRectGetMaxX(bounds) - _CGRectGetWidth(frame);
|
frame.origin.x = _CGRectGetMaxX(bounds) - _CGRectGetWidth(frame);
|
||||||
frame.origin.y = _CGRectGetMinY(bounds);
|
frame.origin.y = 0;
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
@@ -577,7 +471,7 @@
|
|||||||
if (!headerView)
|
if (!headerView)
|
||||||
return _CGRectMakeZero();
|
return _CGRectMakeZero();
|
||||||
|
|
||||||
var frame = [self _insetBounds];
|
var frame = [self bounds];
|
||||||
|
|
||||||
frame.size.height = _CGRectGetHeight([headerView frame]);
|
frame.size.height = _CGRectGetHeight([headerView frame]);
|
||||||
frame.size.width -= _CGRectGetWidth([self _cornerViewFrame]);
|
frame.size.width -= _CGRectGetWidth([self _cornerViewFrame]);
|
||||||
@@ -585,69 +479,33 @@
|
|||||||
return frame;
|
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 */
|
/* @ignore */
|
||||||
- (void)_verticalScrollerDidScroll:(CPScroller)aScroller
|
- (void)_verticalScrollerDidScroll:(CPScroller)aScroller
|
||||||
{
|
{
|
||||||
var value = [aScroller floatValue],
|
var value = [aScroller floatValue],
|
||||||
documentFrame = [[_contentView documentView] frame],
|
documentFrame = [[_contentView documentView] frame];
|
||||||
contentBounds = [_contentView bounds];
|
contentBounds = [_contentView bounds];
|
||||||
|
|
||||||
switch ([_verticalScroller hitPart])
|
switch ([_verticalScroller hitPart])
|
||||||
{
|
{
|
||||||
case CPScrollerDecrementLine: contentBounds.origin.y -= _verticalLineScroll;
|
case CPScrollerDecrementLine: contentBounds.origin.y -= _verticalLineScroll;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CPScrollerIncrementLine: contentBounds.origin.y += _verticalLineScroll;
|
case CPScrollerIncrementLine: contentBounds.origin.y += _verticalLineScroll;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CPScrollerDecrementPage: contentBounds.origin.y -= _CGRectGetHeight(contentBounds) - _verticalPageScroll;
|
case CPScrollerDecrementPage: contentBounds.origin.y -= _CGRectGetHeight(contentBounds) - _verticalPageScroll;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CPScrollerIncrementPage: contentBounds.origin.y += _CGRectGetHeight(contentBounds) - _verticalPageScroll;
|
case CPScrollerIncrementPage: contentBounds.origin.y += _CGRectGetHeight(contentBounds) - _verticalPageScroll;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CPScrollerKnobSlot:
|
case CPScrollerKnobSlot:
|
||||||
case CPScrollerKnob:
|
case CPScrollerKnob:
|
||||||
// We want integral bounds!
|
// We want integral bounds!
|
||||||
default: contentBounds.origin.y = ROUND(value * (_CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentBounds)));
|
default: contentBounds.origin.y = ROUND(value * (_CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentBounds)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[_contentView scrollToPoint:contentBounds.origin];
|
[_contentView scrollToPoint:contentBounds.origin];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -657,21 +515,21 @@
|
|||||||
var value = [aScroller floatValue],
|
var value = [aScroller floatValue],
|
||||||
documentFrame = [[self documentView] frame],
|
documentFrame = [[self documentView] frame],
|
||||||
contentBounds = [_contentView bounds];
|
contentBounds = [_contentView bounds];
|
||||||
|
|
||||||
switch ([_horizontalScroller hitPart])
|
switch ([_horizontalScroller hitPart])
|
||||||
{
|
{
|
||||||
case CPScrollerDecrementLine: contentBounds.origin.x -= _horizontalLineScroll;
|
case CPScrollerDecrementLine: contentBounds.origin.x -= _horizontalLineScroll;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CPScrollerIncrementLine: contentBounds.origin.x += _horizontalLineScroll;
|
case CPScrollerIncrementLine: contentBounds.origin.x += _horizontalLineScroll;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CPScrollerDecrementPage: contentBounds.origin.x -= _CGRectGetWidth(contentBounds) - _horizontalPageScroll;
|
case CPScrollerDecrementPage: contentBounds.origin.x -= _CGRectGetWidth(contentBounds) - _horizontalPageScroll;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CPScrollerIncrementPage: contentBounds.origin.x += _CGRectGetWidth(contentBounds) - _horizontalPageScroll;
|
case CPScrollerIncrementPage: contentBounds.origin.x += _CGRectGetWidth(contentBounds) - _horizontalPageScroll;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CPScrollerKnobSlot:
|
case CPScrollerKnobSlot:
|
||||||
case CPScrollerKnob:
|
case CPScrollerKnob:
|
||||||
// We want integral bounds!
|
// We want integral bounds!
|
||||||
@@ -696,7 +554,7 @@
|
|||||||
/*
|
/*
|
||||||
@ignore
|
@ignore
|
||||||
*/
|
*/
|
||||||
- (void)resizeSubviewsWithOldSize:(CGSize)aSize
|
-(void)resizeSubviewsWithOldSize:(CGSize)aSize
|
||||||
{
|
{
|
||||||
[self reflectScrolledClipView:_contentView];
|
[self reflectScrolledClipView:_contentView];
|
||||||
}
|
}
|
||||||
@@ -806,169 +664,35 @@
|
|||||||
return _verticalPageScroll;
|
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.
|
Handles a scroll wheel event from the user.
|
||||||
@param anEvent the scroll wheel event
|
@param anEvent the scroll wheel event
|
||||||
*/
|
*/
|
||||||
- (void)scrollWheel:(CPEvent)anEvent
|
- (void)scrollWheel:(CPEvent)anEvent
|
||||||
{
|
{
|
||||||
[self _respondToScrollWheelEventWithDeltaX:[anEvent deltaX] deltaY:[anEvent deltaY]];
|
var documentFrame = [[self documentView] frame],
|
||||||
}
|
contentBounds = [_contentView bounds];
|
||||||
|
|
||||||
- (void)_respondToScrollWheelEventWithDeltaX:(float)deltaX deltaY:(float)deltaY
|
|
||||||
{
|
|
||||||
var documentFrame = [[self documentView] frame],
|
|
||||||
contentBounds = [_contentView bounds],
|
|
||||||
contentFrame = [_contentView frame],
|
|
||||||
enclosingScrollView = [self enclosingScrollView];
|
|
||||||
|
|
||||||
// We want integral bounds!
|
// We want integral bounds!
|
||||||
contentBounds.origin.x = ROUND(contentBounds.origin.x + deltaX);
|
contentBounds.origin.x = ROUND(contentBounds.origin.x + [anEvent deltaX] * _horizontalLineScroll);
|
||||||
contentBounds.origin.y = ROUND(contentBounds.origin.y + deltaY);
|
contentBounds.origin.y = ROUND(contentBounds.origin.y + [anEvent deltaY] * _verticalLineScroll);
|
||||||
|
|
||||||
var constrainedOrigin = [_contentView constrainScrollPoint:CGPointCreateCopy(contentBounds.origin)],
|
[_contentView scrollToPoint:contentBounds.origin];
|
||||||
extraX = contentBounds.origin.x - constrainedOrigin.x,
|
[_headerClipView scrollToPoint:CGPointMake(contentBounds.origin.x, 0.0)];
|
||||||
extraY = contentBounds.origin.y - constrainedOrigin.y;
|
|
||||||
|
|
||||||
[_contentView scrollToPoint:constrainedOrigin];
|
|
||||||
[_headerClipView scrollToPoint:CGPointMake(constrainedOrigin.x, 0.0)];
|
|
||||||
|
|
||||||
if (extraX || extraY)
|
|
||||||
[enclosingScrollView _respondToScrollWheelEventWithDeltaX:extraX deltaY:extraY];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)scrollPageUp:(id)sender
|
- (void)keyDown:(CPEvent)anEvent
|
||||||
|
{
|
||||||
|
[self interpretKeyEvents:[anEvent]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)pageUp:(id)sender
|
||||||
{
|
{
|
||||||
var contentBounds = [_contentView bounds];
|
var contentBounds = [_contentView bounds];
|
||||||
[self moveByOffset:CGSizeMake(0.0, -(_CGRectGetHeight(contentBounds) - _verticalPageScroll))];
|
[self moveByOffset:CGSizeMake(0.0, -(_CGRectGetHeight(contentBounds) - _verticalPageScroll))];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)scrollPageDown:(id)sender
|
- (void)pageDown:(id)sender
|
||||||
{
|
{
|
||||||
var contentBounds = [_contentView bounds];
|
var contentBounds = [_contentView bounds];
|
||||||
[self moveByOffset:CGSizeMake(0.0, _CGRectGetHeight(contentBounds) - _verticalPageScroll)];
|
[self moveByOffset:CGSizeMake(0.0, _CGRectGetHeight(contentBounds) - _verticalPageScroll)];
|
||||||
@@ -1008,20 +732,18 @@
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
var CPScrollViewContentViewKey = @"CPScrollViewContentView",
|
var CPScrollViewContentViewKey = "CPScrollViewContentView",
|
||||||
CPScrollViewHeaderClipViewKey = @"CPScrollViewHeaderClipViewKey",
|
CPScrollViewHeaderClipViewKey = "CPScrollViewHeaderClipViewKey",
|
||||||
CPScrollViewVLineScrollKey = @"CPScrollViewVLineScroll",
|
CPScrollViewVLineScrollKey = "CPScrollViewVLineScroll",
|
||||||
CPScrollViewHLineScrollKey = @"CPScrollViewHLineScroll",
|
CPScrollViewHLineScrollKey = "CPScrollViewHLineScroll",
|
||||||
CPScrollViewVPageScrollKey = @"CPScrollViewVPageScroll",
|
CPScrollViewVPageScrollKey = "CPScrollViewVPageScroll",
|
||||||
CPScrollViewHPageScrollKey = @"CPScrollViewHPageScroll",
|
CPScrollViewHPageScrollKey = "CPScrollViewHPageScroll",
|
||||||
CPScrollViewHasVScrollerKey = @"CPScrollViewHasVScroller",
|
CPScrollViewHasVScrollerKey = "CPScrollViewHasVScroller",
|
||||||
CPScrollViewHasHScrollerKey = @"CPScrollViewHasHScroller",
|
CPScrollViewHasHScrollerKey = "CPScrollViewHasHScroller",
|
||||||
CPScrollViewVScrollerKey = @"CPScrollViewVScroller",
|
CPScrollViewVScrollerKey = "CPScrollViewVScroller",
|
||||||
CPScrollViewHScrollerKey = @"CPScrollViewHScroller",
|
CPScrollViewHScrollerKey = "CPScrollViewHScroller",
|
||||||
CPScrollViewAutohidesScrollerKey = @"CPScrollViewAutohidesScroller",
|
CPScrollViewAutohidesScrollerKey = "CPScrollViewAutohidesScroller",
|
||||||
CPScrollViewCornerViewKey = @"CPScrollViewCornerViewKey",
|
CPScrollViewCornerViewKey = "CPScrollViewCornerViewKey";
|
||||||
CPScrollViewBottomCornerViewKey = @"CPScrollViewBottomCornerViewKey",
|
|
||||||
CPScrollViewBorderTypeKey = @"CPScrollViewBorderTypeKey";
|
|
||||||
|
|
||||||
@implementation CPScrollView (CPCoding)
|
@implementation CPScrollView (CPCoding)
|
||||||
|
|
||||||
@@ -1034,16 +756,10 @@ var CPScrollViewContentViewKey = @"CPScrollViewContentView",
|
|||||||
|
|
||||||
_horizontalLineScroll = [aCoder decodeFloatForKey:CPScrollViewHLineScrollKey];
|
_horizontalLineScroll = [aCoder decodeFloatForKey:CPScrollViewHLineScrollKey];
|
||||||
_horizontalPageScroll = [aCoder decodeFloatForKey:CPScrollViewHPageScrollKey];
|
_horizontalPageScroll = [aCoder decodeFloatForKey:CPScrollViewHPageScrollKey];
|
||||||
|
|
||||||
_contentView = [aCoder decodeObjectForKey:CPScrollViewContentViewKey];
|
_contentView = [aCoder decodeObjectForKey:CPScrollViewContentViewKey];
|
||||||
_headerClipView = [aCoder decodeObjectForKey:CPScrollViewHeaderClipViewKey];
|
_headerClipView = [aCoder decodeObjectForKey:CPScrollViewHeaderClipViewKey];
|
||||||
|
|
||||||
if (!_headerClipView)
|
|
||||||
{
|
|
||||||
_headerClipView = [[CPClipView alloc] init];
|
|
||||||
[self addSubview:_headerClipView];
|
|
||||||
}
|
|
||||||
|
|
||||||
_verticalScroller = [aCoder decodeObjectForKey:CPScrollViewVScrollerKey];
|
_verticalScroller = [aCoder decodeObjectForKey:CPScrollViewVScrollerKey];
|
||||||
_horizontalScroller = [aCoder decodeObjectForKey:CPScrollViewHScrollerKey];
|
_horizontalScroller = [aCoder decodeObjectForKey:CPScrollViewHScrollerKey];
|
||||||
|
|
||||||
@@ -1051,41 +767,35 @@ var CPScrollViewContentViewKey = @"CPScrollViewContentView",
|
|||||||
_hasHorizontalScroller = [aCoder decodeBoolForKey:CPScrollViewHasHScrollerKey];
|
_hasHorizontalScroller = [aCoder decodeBoolForKey:CPScrollViewHasHScrollerKey];
|
||||||
_autohidesScrollers = [aCoder decodeBoolForKey:CPScrollViewAutohidesScrollerKey];
|
_autohidesScrollers = [aCoder decodeBoolForKey:CPScrollViewAutohidesScrollerKey];
|
||||||
|
|
||||||
_borderType = [aCoder decodeIntForKey:CPScrollViewBorderTypeKey];
|
|
||||||
|
|
||||||
_cornerView = [aCoder decodeObjectForKey:CPScrollViewCornerViewKey];
|
_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.
|
// 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]];
|
[[CPRunLoop currentRunLoop] performSelector:@selector(reflectScrolledClipView:) target:self argument:_contentView order:0 modes:[CPDefaultRunLoopMode]];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||||
{
|
{
|
||||||
[super encodeWithCoder:aCoder];
|
[super encodeWithCoder:aCoder];
|
||||||
|
|
||||||
[aCoder encodeObject:_contentView forKey:CPScrollViewContentViewKey];
|
[aCoder encodeObject:_contentView forKey:CPScrollViewContentViewKey];
|
||||||
[aCoder encodeObject:_headerClipView forKey:CPScrollViewHeaderClipViewKey];
|
[aCoder encodeObject:_headerClipView forKey:CPScrollViewHeaderClipViewKey];
|
||||||
|
|
||||||
[aCoder encodeObject:_verticalScroller forKey:CPScrollViewVScrollerKey];
|
[aCoder encodeObject:_verticalScroller forKey:CPScrollViewVScrollerKey];
|
||||||
[aCoder encodeObject:_horizontalScroller forKey:CPScrollViewHScrollerKey];
|
[aCoder encodeObject:_horizontalScroller forKey:CPScrollViewHScrollerKey];
|
||||||
|
|
||||||
[aCoder encodeFloat:_verticalLineScroll forKey:CPScrollViewVLineScrollKey];
|
[aCoder encodeFloat:_verticalLineScroll forKey:CPScrollViewVLineScrollKey];
|
||||||
[aCoder encodeFloat:_verticalPageScroll forKey:CPScrollViewVPageScrollKey];
|
[aCoder encodeFloat:_verticalPageScroll forKey:CPScrollViewVPageScrollKey];
|
||||||
[aCoder encodeFloat:_horizontalLineScroll forKey:CPScrollViewHLineScrollKey];
|
[aCoder encodeFloat:_horizontalLineScroll forKey:CPScrollViewHLineScrollKey];
|
||||||
[aCoder encodeFloat:_horizontalPageScroll forKey:CPScrollViewHPageScrollKey];
|
[aCoder encodeFloat:_horizontalPageScroll forKey:CPScrollViewHPageScrollKey];
|
||||||
|
|
||||||
[aCoder encodeBool:_hasVerticalScroller forKey:CPScrollViewHasVScrollerKey];
|
[aCoder encodeBool:_hasVerticalScroller forKey:CPScrollViewHasVScrollerKey];
|
||||||
[aCoder encodeBool:_hasHorizontalScroller forKey:CPScrollViewHasHScrollerKey];
|
[aCoder encodeBool:_hasHorizontalScroller forKey:CPScrollViewHasHScrollerKey];
|
||||||
[aCoder encodeBool:_autohidesScrollers forKey:CPScrollViewAutohidesScrollerKey];
|
[aCoder encodeBool:_autohidesScrollers forKey:CPScrollViewAutohidesScrollerKey];
|
||||||
|
|
||||||
[aCoder encodeObject:_cornerView forKey:CPScrollViewCornerViewKey];
|
[aCoder encodeObject:_cornerView forKey:CPScrollViewCornerViewKey];
|
||||||
[aCoder encodeObject:_bottomCornerView forKey:CPScrollViewBottomCornerViewKey];
|
|
||||||
|
|
||||||
[aCoder encodeInt:_borderType forKey:CPScrollViewBorderTypeKey];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
+81
-93
@@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
@import "CPControl.j"
|
@import "CPControl.j"
|
||||||
|
|
||||||
|
#include "CoreGraphics/CGGeometry.h"
|
||||||
|
|
||||||
|
|
||||||
// CPScroller Constants
|
// CPScroller Constants
|
||||||
CPScrollerNoPart = 0;
|
CPScrollerNoPart = 0;
|
||||||
@@ -39,9 +41,9 @@ CPNoScrollerParts = 0;
|
|||||||
CPOnlyScrollerArrows = 1;
|
CPOnlyScrollerArrows = 1;
|
||||||
CPAllScrollerParts = 2;
|
CPAllScrollerParts = 2;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPScroller
|
@class CPScroller
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var PARTS_ARRANGEMENT = [CPScrollerKnobSlot, CPScrollerDecrementLine, CPScrollerIncrementLine, CPScrollerKnob],
|
var PARTS_ARRANGEMENT = [CPScrollerKnobSlot, CPScrollerDecrementLine, CPScrollerIncrementLine, CPScrollerKnob],
|
||||||
@@ -70,25 +72,24 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
|||||||
CGPoint _trackingStartPoint;
|
CGPoint _trackingStartPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (CPString)defaultThemeClass
|
+ (CPString)themeClass
|
||||||
{
|
{
|
||||||
return "scroller";
|
return "scroller";
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (id)themeAttributes
|
+ (id)themeAttributes
|
||||||
{
|
{
|
||||||
return [CPDictionary dictionaryWithJSObject:{
|
return [CPDictionary dictionaryWithObjects:[ [CPNull null], [CPNull null], [CPNull null], [CPNull null],
|
||||||
@"scroller-width": 15.0,
|
_CGSizeMakeZero(), _CGSizeMakeZero(), _CGInsetMakeZero(), _CGInsetMakeZero(), _CGSizeMakeZero()]
|
||||||
@"knob-slot-color": [CPColor lightGrayColor],
|
forKeys:[ @"knob-slot-color",
|
||||||
@"decrement-line-color": [CPNull null],
|
@"decrement-line-color",
|
||||||
@"increment-line-color": [CPNull null],
|
@"increment-line-color",
|
||||||
@"knob-color": [CPColor grayColor],
|
@"knob-color",
|
||||||
@"decrement-line-size":_CGSizeMakeZero(),
|
@"decrement-line-size",
|
||||||
@"increment-line-size":_CGSizeMakeZero(),
|
@"increment-line-size",
|
||||||
@"track-inset":_CGInsetMakeZero(),
|
@"track-inset",
|
||||||
@"knob-inset": _CGInsetMakeZero(),
|
@"knob-inset",
|
||||||
@"minimum-knob-length":21.0
|
@"minimum-knob-length"]];
|
||||||
}]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -97,7 +98,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
|||||||
- (id)initWithFrame:(CGRect)aFrame
|
- (id)initWithFrame:(CGRect)aFrame
|
||||||
{
|
{
|
||||||
self = [super initWithFrame:aFrame];
|
self = [super initWithFrame:aFrame];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_controlSize = CPRegularControlSize;
|
_controlSize = CPRegularControlSize;
|
||||||
@@ -105,7 +106,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
|||||||
|
|
||||||
[self setFloatValue:0.0];
|
[self setFloatValue:0.0];
|
||||||
[self setKnobProportion:1.0];
|
[self setKnobProportion:1.0];
|
||||||
|
|
||||||
_hitPart = CPScrollerNoPart;
|
_hitPart = CPScrollerNoPart;
|
||||||
|
|
||||||
[self _calculateIsVertical];
|
[self _calculateIsVertical];
|
||||||
@@ -120,7 +121,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
|||||||
*/
|
*/
|
||||||
+ (float)scrollerWidth
|
+ (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
|
+ (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
|
- (id)currentValueForThemeAttribute:(CPString)anAttributeName
|
||||||
{
|
{
|
||||||
var themeState = _themeState;
|
var themeState = _themeState;
|
||||||
|
|
||||||
if (NAMES_FOR_PARTS[_hitPart] + "-color" !== anAttributeName)
|
if (NAMES_FOR_PARTS[_hitPart] + "-color" !== anAttributeName)
|
||||||
themeState &= ~CPThemeStateHighlighted;
|
themeState &= ~CPThemeStateHighlighted;
|
||||||
|
|
||||||
return [self valueForThemeAttribute:anAttributeName inState:themeState];
|
return [self valueForThemeAttribute:anAttributeName inState:themeState];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,25 +205,25 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
|||||||
- (CPScrollerPart)testPart:(CGPoint)aPoint
|
- (CPScrollerPart)testPart:(CGPoint)aPoint
|
||||||
{
|
{
|
||||||
aPoint = [self convertPoint:aPoint fromView:nil];
|
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.
|
// page rects first since they may overlap with the arrows.
|
||||||
|
|
||||||
if (CGRectContainsPoint([self rectForPart:CPScrollerKnob], aPoint))
|
if (CGRectContainsPoint([self rectForPart:CPScrollerKnob], aPoint))
|
||||||
return CPScrollerKnob;
|
return CPScrollerKnob;
|
||||||
|
|
||||||
if (CGRectContainsPoint([self rectForPart:CPScrollerDecrementPage], aPoint))
|
if (CGRectContainsPoint([self rectForPart:CPScrollerDecrementPage], aPoint))
|
||||||
return CPScrollerDecrementPage;
|
return CPScrollerDecrementPage;
|
||||||
|
|
||||||
if (CGRectContainsPoint([self rectForPart:CPScrollerIncrementPage], aPoint))
|
if (CGRectContainsPoint([self rectForPart:CPScrollerIncrementPage], aPoint))
|
||||||
return CPScrollerIncrementPage;
|
return CPScrollerIncrementPage;
|
||||||
|
|
||||||
if (CGRectContainsPoint([self rectForPart:CPScrollerDecrementLine], aPoint))
|
if (CGRectContainsPoint([self rectForPart:CPScrollerDecrementLine], aPoint))
|
||||||
return CPScrollerDecrementLine;
|
return CPScrollerDecrementLine;
|
||||||
|
|
||||||
if (CGRectContainsPoint([self rectForPart:CPScrollerIncrementLine], aPoint))
|
if (CGRectContainsPoint([self rectForPart:CPScrollerIncrementLine], aPoint))
|
||||||
return CPScrollerIncrementLine;
|
return CPScrollerIncrementLine;
|
||||||
|
|
||||||
if (CGRectContainsPoint([self rectForPart:CPScrollerKnobSlot], aPoint))
|
if (CGRectContainsPoint([self rectForPart:CPScrollerKnobSlot], aPoint))
|
||||||
return CPScrollerKnobSlot;
|
return CPScrollerKnobSlot;
|
||||||
|
|
||||||
@@ -240,7 +241,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
|||||||
if (_knobProportion === 1.0)
|
if (_knobProportion === 1.0)
|
||||||
{
|
{
|
||||||
_usableParts = CPNoScrollerParts;
|
_usableParts = CPNoScrollerParts;
|
||||||
|
|
||||||
_partRects[CPScrollerDecrementPage] = CGRectMakeZero();
|
_partRects[CPScrollerDecrementPage] = CGRectMakeZero();
|
||||||
_partRects[CPScrollerKnob] = CGRectMakeZero();
|
_partRects[CPScrollerKnob] = CGRectMakeZero();
|
||||||
_partRects[CPScrollerIncrementPage] = CGRectMakeZero();
|
_partRects[CPScrollerIncrementPage] = CGRectMakeZero();
|
||||||
@@ -249,7 +250,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
|||||||
|
|
||||||
// In this case, the slot is the entirety of the scroller.
|
// In this case, the slot is the entirety of the scroller.
|
||||||
_partRects[CPScrollerKnobSlot] = CGRectMakeCopy(bounds);
|
_partRects[CPScrollerKnobSlot] = CGRectMakeCopy(bounds);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,8 +260,8 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
|||||||
var knobInset = [self currentValueForThemeAttribute:@"knob-inset"],
|
var knobInset = [self currentValueForThemeAttribute:@"knob-inset"],
|
||||||
trackInset = [self currentValueForThemeAttribute:@"track-inset"],
|
trackInset = [self currentValueForThemeAttribute:@"track-inset"],
|
||||||
width = _CGRectGetWidth(bounds),
|
width = _CGRectGetWidth(bounds),
|
||||||
height = _CGRectGetHeight(bounds);
|
height = _CGRectGetHeight(bounds);
|
||||||
|
|
||||||
if ([self isVertical])
|
if ([self isVertical])
|
||||||
{
|
{
|
||||||
var decrementLineSize = [self currentValueForThemeAttribute:"decrement-line-size"],
|
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[CPScrollerKnobSlot] = _CGRectMake(trackInset.left, effectiveDecrementLineHeight, width - trackInset.left - trackInset.right, slotHeight);
|
||||||
_partRects[CPScrollerDecrementLine] = _CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height);
|
_partRects[CPScrollerDecrementLine] = _CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height);
|
||||||
_partRects[CPScrollerIncrementLine] = _CGRectMake(0.0, height - incrementLineSize.height, incrementLineSize.width, incrementLineSize.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();
|
_partRects[CPScrollerKnob] = _CGRectMakeZero();
|
||||||
|
|
||||||
if (height < decrementLineSize.height + incrementLineSize.height - 2)
|
if(height < decrementLineSize.height + incrementLineSize.height - 2)
|
||||||
{
|
{
|
||||||
_partRects[CPScrollerIncrementLine] = _CGRectMakeZero();
|
_partRects[CPScrollerIncrementLine] = _CGRectMakeZero();
|
||||||
_partRects[CPScrollerDecrementLine] = _CGRectMakeZero();
|
_partRects[CPScrollerDecrementLine] = _CGRectMakeZero();
|
||||||
@@ -295,7 +296,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
|||||||
var decrementLineSize = [self currentValueForThemeAttribute:"decrement-line-size"],
|
var decrementLineSize = [self currentValueForThemeAttribute:"decrement-line-size"],
|
||||||
incrementLineSize = [self currentValueForThemeAttribute:"increment-line-size"],
|
incrementLineSize = [self currentValueForThemeAttribute:"increment-line-size"],
|
||||||
effectiveDecrementLineWidth = decrementLineSize.width + trackInset.left,
|
effectiveDecrementLineWidth = decrementLineSize.width + trackInset.left,
|
||||||
effectiveIncrementLineWidth = incrementLineSize.width + trackInset.right,
|
effectiveIncrementLineWidth = incrementLineSize.width + trackInset.right;
|
||||||
slotWidth = width - effectiveDecrementLineWidth - effectiveIncrementLineWidth,
|
slotWidth = width - effectiveDecrementLineWidth - effectiveIncrementLineWidth,
|
||||||
minimumKnobLength = [self currentValueForThemeAttribute:"minimum-knob-length"],
|
minimumKnobLength = [self currentValueForThemeAttribute:"minimum-knob-length"],
|
||||||
knobWidth = MAX(minimumKnobLength, (slotWidth * _knobProportion)),
|
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[CPScrollerKnobSlot] = _CGRectMake(effectiveDecrementLineWidth, trackInset.top, slotWidth, height - trackInset.top - trackInset.bottom);
|
||||||
_partRects[CPScrollerDecrementLine] = _CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height);
|
_partRects[CPScrollerDecrementLine] = _CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height);
|
||||||
_partRects[CPScrollerIncrementLine] = _CGRectMake(width - incrementLineSize.width, 0.0, incrementLineSize.width, incrementLineSize.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();
|
_partRects[CPScrollerKnob] = _CGRectMakeZero();
|
||||||
|
|
||||||
if (width < decrementLineSize.width + incrementLineSize.width - 2)
|
if(width < decrementLineSize.width + incrementLineSize.width - 2)
|
||||||
{
|
{
|
||||||
_partRects[CPScrollerIncrementLine] = _CGRectMakeZero();
|
_partRects[CPScrollerIncrementLine] = _CGRectMakeZero();
|
||||||
_partRects[CPScrollerDecrementLine] = _CGRectMakeZero();
|
_partRects[CPScrollerDecrementLine] = _CGRectMakeZero();
|
||||||
@@ -357,9 +358,9 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
|||||||
- (CPView)createViewForPart:(CPScrollerPart)aPart
|
- (CPView)createViewForPart:(CPScrollerPart)aPart
|
||||||
{
|
{
|
||||||
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
|
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
|
||||||
|
|
||||||
[view setHitTests:NO];
|
[view setHitTests:NO];
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,7 +374,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
|||||||
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
|
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
|
||||||
|
|
||||||
[view setHitTests:NO];
|
[view setHitTests:NO];
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,12 +388,12 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
|||||||
for (; index < count; ++index)
|
for (; index < count; ++index)
|
||||||
{
|
{
|
||||||
var part = PARTS_ARRANGEMENT[index];
|
var part = PARTS_ARRANGEMENT[index];
|
||||||
|
|
||||||
if (index === 0)
|
if (index === 0)
|
||||||
view = [self layoutEphemeralSubviewNamed:part positioned:CPWindowBelow relativeToEphemeralSubviewNamed:PARTS_ARRANGEMENT[index + 1]];
|
view = [self layoutEphemeralSubviewNamed:part positioned:CPWindowBelow relativeToEphemeralSubviewNamed:PARTS_ARRANGEMENT[index + 1]];
|
||||||
else
|
else
|
||||||
view = [self layoutEphemeralSubviewNamed:part positioned:CPWindowAbove relativeToEphemeralSubviewNamed:PARTS_ARRANGEMENT[index - 1]];
|
view = [self layoutEphemeralSubviewNamed:part positioned:CPWindowAbove relativeToEphemeralSubviewNamed:PARTS_ARRANGEMENT[index - 1]];
|
||||||
|
|
||||||
if (view)
|
if (view)
|
||||||
[view setBackgroundColor:[self currentValueForThemeAttribute:NAMES_FOR_PARTS[part] + "-color"]];
|
[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.
|
Caches images for the scroll arrow and knob.
|
||||||
*/
|
*/
|
||||||
- (void)drawParts
|
- (void)drawParts
|
||||||
{
|
{
|
||||||
[self drawKnobSlot];
|
[self drawKnobSlot];
|
||||||
[self drawKnob];
|
[self drawKnob];
|
||||||
[self drawArrow:CPScrollerDecrementArrow highlight:NO];
|
[self drawArrow:CPScrollerDecrementArrow highlight:NO];
|
||||||
@@ -425,37 +426,37 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
|||||||
- (void)trackKnob:(CPEvent)anEvent
|
- (void)trackKnob:(CPEvent)anEvent
|
||||||
{
|
{
|
||||||
var type = [anEvent type];
|
var type = [anEvent type];
|
||||||
|
|
||||||
if (type === CPLeftMouseUp)
|
if (type === CPLeftMouseUp)
|
||||||
{
|
{
|
||||||
_hitPart = CPScrollerNoPart;
|
_hitPart = CPScrollerNoPart;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === CPLeftMouseDown)
|
if (type === CPLeftMouseDown)
|
||||||
{
|
{
|
||||||
_trackingFloatValue = [self floatValue];
|
_trackingFloatValue = [self floatValue];
|
||||||
_trackingStartPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
_trackingStartPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (type === CPLeftMouseDragged)
|
else if (type === CPLeftMouseDragged)
|
||||||
{
|
{
|
||||||
var knobRect = [self rectForPart:CPScrollerKnob],
|
var knobRect = [self rectForPart:CPScrollerKnob],
|
||||||
knobSlotRect = [self rectForPart:CPScrollerKnobSlot],
|
knobSlotRect = [self rectForPart:CPScrollerKnobSlot],
|
||||||
remainder = ![self isVertical] ? (_CGRectGetWidth(knobSlotRect) - _CGRectGetWidth(knobRect)) : (_CGRectGetHeight(knobSlotRect) - _CGRectGetHeight(knobRect));
|
remainder = ![self isVertical] ? (_CGRectGetWidth(knobSlotRect) - _CGRectGetWidth(knobRect)) : (_CGRectGetHeight(knobSlotRect) - _CGRectGetHeight(knobRect));
|
||||||
|
|
||||||
if (remainder <= 0)
|
if (remainder <= 0)
|
||||||
[self setFloatValue:0.0];
|
[self setFloatValue:0.0];
|
||||||
else
|
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;
|
delta = ![self isVertical] ? location.x - _trackingStartPoint.x : location.y - _trackingStartPoint.y;
|
||||||
|
|
||||||
[self setFloatValue:_trackingFloatValue + delta / remainder];
|
[self setFloatValue:_trackingFloatValue + delta / remainder];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[CPApp setTarget:self selector:@selector(trackKnob:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
|
[CPApp setTarget:self selector:@selector(trackKnob:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
|
||||||
|
|
||||||
[self sendAction:[self action] to:[self target]];
|
[self sendAction:[self action] to:[self target]];
|
||||||
@@ -473,26 +474,26 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
|||||||
{
|
{
|
||||||
[self highlight:NO];
|
[self highlight:NO];
|
||||||
[CPEvent stopPeriodicEvents];
|
[CPEvent stopPeriodicEvents];
|
||||||
|
|
||||||
_hitPart = CPScrollerNoPart;
|
_hitPart = CPScrollerNoPart;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === CPLeftMouseDown)
|
if (type === CPLeftMouseDown)
|
||||||
{
|
{
|
||||||
_trackingPart = [self hitPart];
|
_trackingPart = [self hitPart];
|
||||||
|
|
||||||
_trackingStartPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
_trackingStartPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
||||||
|
|
||||||
if ([anEvent modifierFlags] & CPAlternateKeyMask)
|
if ([anEvent modifierFlags] & CPAlternateKeyMask)
|
||||||
{
|
{
|
||||||
if (_trackingPart == CPScrollerDecrementLine)
|
if (_trackingPart == CPScrollerDecrementLine)
|
||||||
_hitPart = CPScrollerDecrementPage;
|
_hitPart = CPScrollerDecrementPage;
|
||||||
|
|
||||||
else if (_trackingPart == CPScrollerIncrementLine)
|
else if (_trackingPart == CPScrollerIncrementLine)
|
||||||
_hitPart = CPScrollerIncrementPage;
|
_hitPart = CPScrollerIncrementPage;
|
||||||
|
|
||||||
else if (_trackingPart == CPScrollerDecrementPage || _trackingPart == CPScrollerIncrementPage)
|
else if (_trackingPart == CPScrollerDecrementPage || _trackingPart == CPScrollerIncrementPage)
|
||||||
{
|
{
|
||||||
var knobRect = [self rectForPart:CPScrollerKnob],
|
var knobRect = [self rectForPart:CPScrollerKnob],
|
||||||
@@ -501,42 +502,42 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
|||||||
remainder = (![self isVertical] ? _CGRectGetWidth(knobSlotRect) : _CGRectGetHeight(knobSlotRect)) - knobWidth;
|
remainder = (![self isVertical] ? _CGRectGetWidth(knobSlotRect) : _CGRectGetHeight(knobSlotRect)) - knobWidth;
|
||||||
|
|
||||||
[self setFloatValue:((![self isVertical] ? _trackingStartPoint.x - _CGRectGetMinX(knobSlotRect) : _trackingStartPoint.y - _CGRectGetMinY(knobSlotRect)) - knobWidth / 2.0) / remainder];
|
[self setFloatValue:((![self isVertical] ? _trackingStartPoint.x - _CGRectGetMinX(knobSlotRect) : _trackingStartPoint.y - _CGRectGetMinY(knobSlotRect)) - knobWidth / 2.0) / remainder];
|
||||||
|
|
||||||
_hitPart = CPScrollerKnob;
|
_hitPart = CPScrollerKnob;
|
||||||
|
|
||||||
[self sendAction:[self action] to:[self target]];
|
[self sendAction:[self action] to:[self target]];
|
||||||
|
|
||||||
// Now just track the knob.
|
// Now just track the knob.
|
||||||
return [self trackKnob:anEvent];
|
return [self trackKnob:anEvent];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[self highlight:YES];
|
[self highlight:YES];
|
||||||
[self sendAction:[self action] to:[self target]];
|
[self sendAction:[self action] to:[self target]];
|
||||||
|
|
||||||
[CPEvent startPeriodicEventsAfterDelay:0.5 withPeriod:0.04];
|
[CPEvent startPeriodicEventsAfterDelay:0.5 withPeriod:0.04];
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (type === CPLeftMouseDragged)
|
else if (type === CPLeftMouseDragged)
|
||||||
{
|
{
|
||||||
_trackingStartPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
_trackingStartPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
||||||
|
|
||||||
if (_trackingPart == CPScrollerDecrementPage || _trackingPart == CPScrollerIncrementPage)
|
if (_trackingPart == CPScrollerDecrementPage || _trackingPart == CPScrollerIncrementPage)
|
||||||
{
|
{
|
||||||
var hitPart = [self testPart:[anEvent locationInWindow]];
|
var hitPart = [self testPart:[anEvent locationInWindow]];
|
||||||
|
|
||||||
if (hitPart == CPScrollerDecrementPage || hitPart == CPScrollerIncrementPage)
|
if (hitPart == CPScrollerDecrementPage || hitPart == CPScrollerIncrementPage)
|
||||||
{
|
{
|
||||||
_trackingPart = hitPart;
|
_trackingPart = hitPart;
|
||||||
_hitPart = hitPart;
|
_hitPart = hitPart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[self highlight:CGRectContainsPoint([self rectForPart:_trackingPart], _trackingStartPoint)];
|
[self highlight:CGRectContainsPoint([self rectForPart:_trackingPart], _trackingStartPoint)];
|
||||||
}
|
}
|
||||||
else if (type == CPPeriodic && CGRectContainsPoint([self rectForPart:_trackingPart], _trackingStartPoint))
|
else if (type == CPPeriodic && CGRectContainsPoint([self rectForPart:_trackingPart], _trackingStartPoint))
|
||||||
[self sendAction:[self action] to:[self target]];
|
[self sendAction:[self action] to:[self target]];
|
||||||
|
|
||||||
[CPApp setTarget:self selector:@selector(trackScrollButtons:) forNextEventMatchingMask:CPPeriodicMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
|
[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])
|
if (![self isEnabled])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_hitPart = [self testPart:[anEvent locationInWindow]];
|
_hitPart = [self testPart:[anEvent locationInWindow]];
|
||||||
|
|
||||||
switch (_hitPart)
|
switch (_hitPart)
|
||||||
{
|
{
|
||||||
case CPScrollerKnob: return [self trackKnob:anEvent];
|
case CPScrollerKnob: return [self trackKnob:anEvent];
|
||||||
|
|
||||||
case CPScrollerDecrementLine:
|
case CPScrollerDecrementLine:
|
||||||
case CPScrollerIncrementLine:
|
case CPScrollerIncrementLine:
|
||||||
case CPScrollerDecrementPage:
|
case CPScrollerDecrementPage:
|
||||||
case CPScrollerIncrementPage: return [self trackScrollButtons:anEvent];
|
case CPScrollerIncrementPage: return [self trackScrollButtons:anEvent];
|
||||||
}
|
}
|
||||||
@@ -602,32 +603,19 @@ var CPScrollerControlSizeKey = "CPScrollerControlSize",
|
|||||||
_knobProportion = [aCoder decodeFloatForKey:CPScrollerKnobProportionKey];
|
_knobProportion = [aCoder decodeFloatForKey:CPScrollerKnobProportionKey];
|
||||||
|
|
||||||
_partRects = [];
|
_partRects = [];
|
||||||
|
|
||||||
_hitPart = CPScrollerNoPart;
|
_hitPart = CPScrollerNoPart;
|
||||||
|
|
||||||
[self _calculateIsVertical];
|
[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;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||||
{
|
{
|
||||||
[super encodeWithCoder:aCoder];
|
[super encodeWithCoder:aCoder];
|
||||||
|
|
||||||
[aCoder encodeInt:_controlSize forKey:CPScrollerControlSizeKey];
|
[aCoder encodeInt:_controlSize forKey:CPScrollerControlSizeKey];
|
||||||
[aCoder encodeFloat:_knobProportion forKey:CPScrollerKnobProportionKey];
|
[aCoder encodeFloat:_knobProportion forKey:CPScrollerKnobProportionKey];
|
||||||
}
|
}
|
||||||
|
|||||||
+135
-238
@@ -20,28 +20,20 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@import "CPButton.j"
|
|
||||||
@import "CPTextField.j"
|
@import "CPTextField.j"
|
||||||
|
|
||||||
|
#include "Platform/Platform.h"
|
||||||
|
|
||||||
CPSearchFieldRecentsTitleMenuItemTag = 1000;
|
CPSearchFieldRecentsTitleMenuItemTag = 1000;
|
||||||
CPSearchFieldRecentsMenuItemTag = 1001;
|
CPSearchFieldRecentsMenuItemTag = 1001;
|
||||||
CPSearchFieldClearRecentsMenuItemTag = 1002;
|
CPSearchFieldClearRecentsMenuItemTag = 1002;
|
||||||
CPSearchFieldNoRecentsMenuItemTag = 1003;
|
CPSearchFieldNoRecentsMenuItemTag = 1003;
|
||||||
CPSearchFieldSeparatorMenuItemTag = 1004;
|
|
||||||
|
|
||||||
var CPSearchFieldSearchImage = nil,
|
var CPSearchFieldSearchImage = nil,
|
||||||
CPSearchFieldFindImage = nil,
|
CPSearchFieldFindImage = nil,
|
||||||
CPSearchFieldCancelImage = nil,
|
CPSearchFieldCancelImage = nil,
|
||||||
CPSearchFieldCancelPressedImage = 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
|
@ingroup appkit
|
||||||
@class CPSearchField
|
@class CPSearchField
|
||||||
@@ -62,37 +54,32 @@ var RECENT_SEARCH_PREFIX = @" ";
|
|||||||
int _maximumRecents;
|
int _maximumRecents;
|
||||||
BOOL _sendsWholeSearchString;
|
BOOL _sendsWholeSearchString;
|
||||||
BOOL _sendsSearchStringImmediately;
|
BOOL _sendsSearchStringImmediately;
|
||||||
BOOL _canResignFirstResponder;
|
|
||||||
CPTimer _partialStringTimer;
|
CPTimer _partialStringTimer;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (CPString)defaultThemeClass
|
|
||||||
{
|
|
||||||
return @"searchfield"
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (void)initialize
|
+ (void)initialize
|
||||||
{
|
{
|
||||||
if (self != [CPSearchField class])
|
if (self != [CPSearchField class])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var bundle = [CPBundle bundleForClass:self];
|
var bundle = [CPBundle bundleForClass:self];
|
||||||
CPSearchFieldSearchImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldSearch.png"] size:_CGSizeMake(SEARCH_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(SEARCH_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT)];
|
CPSearchFieldFindImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldFind.png"] size:CGSizeMake(25, 22)];
|
||||||
CPSearchFieldCancelImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldCancel.png"] size:_CGSizeMake(CANCEL_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT)];
|
CPSearchFieldCancelImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldCancel.png"] size:CGSizeMake(22, 22)];
|
||||||
CPSearchFieldCancelPressedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldCancelPressed.png"] size:_CGSizeMake(CANCEL_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT)];
|
CPSearchFieldCancelPressedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldCancelPressed.png"] size:CGSizeMake(22, 22)];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithFrame:(CGRect)frame
|
- (id)initWithFrame:(CGRect)frame
|
||||||
{
|
{
|
||||||
if (self = [super initWithFrame:frame])
|
if (self = [super initWithFrame:frame])
|
||||||
{
|
{
|
||||||
|
_recentSearches = [CPArray array];
|
||||||
_maximumRecents = 10;
|
_maximumRecents = 10;
|
||||||
_sendsWholeSearchString = NO;
|
_sendsWholeSearchString = NO;
|
||||||
_sendsSearchStringImmediately = NO;
|
_sendsSearchStringImmediately = NO;
|
||||||
_recentsAutosaveName = nil;
|
_recentsAutosaveName = nil;
|
||||||
|
|
||||||
[self _init];
|
[self _initWithFrame:frame];
|
||||||
#if PLATFORM(DOM)
|
#if PLATFORM(DOM)
|
||||||
_cancelButton._DOMElement.style.cursor = "default";
|
_cancelButton._DOMElement.style.cursor = "default";
|
||||||
_searchButton._DOMElement.style.cursor = "default";
|
_searchButton._DOMElement.style.cursor = "default";
|
||||||
@@ -102,28 +89,23 @@ var RECENT_SEARCH_PREFIX = @" ";
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_init
|
- (void)_initWithFrame:(CGRect)frame
|
||||||
{
|
{
|
||||||
_recentSearches = [CPArray array];
|
|
||||||
|
|
||||||
[self setBezeled:YES];
|
[self setBezeled:YES];
|
||||||
[self setBezelStyle:CPTextFieldRoundedBezel];
|
[self setBezelStyle:CPTextFieldRoundedBezel];
|
||||||
[self setBordered:YES];
|
[self setBordered:YES];
|
||||||
[self setEditable:YES];
|
[self setEditable:YES];
|
||||||
[self setDelegate:self];
|
[self setDelegate:self];
|
||||||
[self setContinuous:YES];
|
|
||||||
|
|
||||||
var bounds = [self bounds],
|
_cancelButton = [[CPButton alloc] initWithFrame:CGRectMake(frame.size.width - 27,(frame.size.height-22)/2,22,22)];
|
||||||
cancelButton = [[CPButton alloc] initWithFrame:[self cancelButtonRectForBounds:bounds]],
|
|
||||||
searchButton = [[CPButton alloc] initWithFrame:[self searchButtonRectForBounds:bounds]];
|
|
||||||
|
|
||||||
[self setCancelButton:cancelButton];
|
|
||||||
[self resetCancelButton];
|
[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];
|
[self resetSearchButton];
|
||||||
|
[self addSubview:_searchButton];
|
||||||
_canResignFirstResponder = YES;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Managing Buttons
|
// Managing Buttons
|
||||||
@@ -133,15 +115,7 @@ var RECENT_SEARCH_PREFIX = @" ";
|
|||||||
*/
|
*/
|
||||||
- (void)setSearchButton:(CPButton)button
|
- (void)setSearchButton:(CPButton)button
|
||||||
{
|
{
|
||||||
if (button != _searchButton)
|
_searchButton = button;
|
||||||
{
|
|
||||||
[_searchButton removeFromSuperview];
|
|
||||||
_searchButton = button;
|
|
||||||
|
|
||||||
[_searchButton setFrame:[self searchButtonRectForBounds:[self bounds]]];
|
|
||||||
[_searchButton setAutoresizingMask:CPViewMaxXMargin];
|
|
||||||
[self addSubview:_searchButton];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -159,13 +133,30 @@ var RECENT_SEARCH_PREFIX = @" ";
|
|||||||
*/
|
*/
|
||||||
- (void)resetSearchButton
|
- (void)resetSearchButton
|
||||||
{
|
{
|
||||||
var button = [self searchButton],
|
var searchButtonImage,
|
||||||
searchButtonImage = (_searchMenuTemplate === nil) ? CPSearchFieldSearchImage : CPSearchFieldFindImage;
|
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 setBordered:NO];
|
||||||
[button setImageScaling:CPScaleToFit];
|
[button setImageScaling:CPScaleToFit];
|
||||||
[button setImage:searchButtonImage];
|
[button setImage:searchButtonImage];
|
||||||
[button setAutoresizingMask:CPViewMaxXMargin];
|
[button setAutoresizingMask:CPViewMaxXMargin];
|
||||||
|
[button setTarget:target];
|
||||||
|
[button setAction:action];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -174,18 +165,7 @@ var RECENT_SEARCH_PREFIX = @" ";
|
|||||||
*/
|
*/
|
||||||
- (void)setCancelButton:(CPButton)button
|
- (void)setCancelButton:(CPButton)button
|
||||||
{
|
{
|
||||||
if (button != _cancelButton)
|
_cancelButton = button;
|
||||||
{
|
|
||||||
[_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];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -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.
|
@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.
|
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,
|
var leftOffset = 0, width = rect.size.width;
|
||||||
width = _CGRectGetWidth(rect),
|
|
||||||
bounds = [self bounds];
|
|
||||||
|
|
||||||
if (_searchButton)
|
if (_searchButton)
|
||||||
{
|
{
|
||||||
var searchBounds = [self searchButtonRectForBounds:bounds];
|
var searchRect = [_searchButton frame];
|
||||||
leftOffset = _CGRectGetMaxX(searchBounds) + 2;
|
leftOffset = searchRect.origin.x + searchRect.size.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_cancelButton)
|
if (_cancelButton)
|
||||||
{
|
{
|
||||||
var cancelRect = [self cancelButtonRectForBounds:bounds];
|
var cancelRect = [_cancelButton frame];
|
||||||
width = _CGRectGetMinX(cancelRect) - leftOffset;
|
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.
|
@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.
|
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.
|
@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.
|
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
|
- (CPRect)cancelButtonRectForBounds:(CPRect)rect
|
||||||
{
|
{
|
||||||
return _CGRectMake(_CGRectGetWidth(rect) - CANCEL_BUTTON_DEFAULT_WIDTH - 5, (_CGRectGetHeight(rect) - CANCEL_BUTTON_DEFAULT_WIDTH) / 2, BUTTON_DEFAULT_HEIGHT, BUTTON_DEFAULT_HEIGHT);
|
return [_cancelButton frame];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Managing Menu Templates
|
// Managing Menu Templates
|
||||||
@@ -276,9 +254,9 @@ var RECENT_SEARCH_PREFIX = @" ";
|
|||||||
@param menu The menu template to use.
|
@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.
|
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 resetSearchButton];
|
||||||
[self _loadRecentSearchList];
|
[self _loadRecentSearchList];
|
||||||
@@ -395,7 +373,7 @@ var RECENT_SEARCH_PREFIX = @" ";
|
|||||||
|
|
||||||
// Private methods and subclassing
|
// Private methods and subclassing
|
||||||
|
|
||||||
- (CGRect)contentRectForBounds:(CGRect)bounds
|
- (CPRect)contentRectForBounds:(CPRect)bounds
|
||||||
{
|
{
|
||||||
var superbounds = [super contentRectForBounds:bounds];
|
var superbounds = [super contentRectForBounds:bounds];
|
||||||
return [self searchTextRectForBounds:superbounds];
|
return [self searchTextRectForBounds:superbounds];
|
||||||
@@ -469,78 +447,37 @@ var RECENT_SEARCH_PREFIX = @" ";
|
|||||||
[self _updateSearchMenu];
|
[self _updateSearchMenu];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CPView)hitTest:(CGPoint)aPoint
|
- (BOOL)trackMouse:(CPEvent)event
|
||||||
{
|
{
|
||||||
// Make sure a hit anywhere within the search field returns the search field itself
|
var rect,
|
||||||
if (_CGRectContainsPoint([self frame], aPoint))
|
point,
|
||||||
return self;
|
location = [event locationInWindow];
|
||||||
else
|
|
||||||
return nil;
|
point = [self convertPoint:location fromView:nil];
|
||||||
}
|
|
||||||
|
rect = [self searchButtonRectForBounds:[self frame]];
|
||||||
- (BOOL)resignFirstResponder
|
if (CPRectContainsPoint(rect,point))
|
||||||
{
|
|
||||||
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))
|
|
||||||
{
|
{
|
||||||
if (_searchMenuTemplate == nil)
|
return [[self searchButton] trackMouse:event];
|
||||||
[self _sendAction:self];
|
}
|
||||||
else
|
|
||||||
[self _showMenu];
|
rect = [self cancelButtonRectForBounds:[self frame]];
|
||||||
}
|
if (CPRectContainsPoint(rect,point))
|
||||||
else if (_CGRectContainsPoint([self cancelButtonRectForBounds:[self bounds]], point))
|
{
|
||||||
[_cancelButton mouseDown:anEvent];
|
return [[self cancelButton] trackMouse:event];
|
||||||
else
|
}
|
||||||
[super mouseDown:anEvent];
|
|
||||||
|
return [super trackMouse:event];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
- (CPMenu)_defaultSearchMenuTemplate
|
||||||
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
|
|
||||||
{
|
{
|
||||||
var template = [[CPMenu alloc] init],
|
var template, item;
|
||||||
item;
|
|
||||||
|
template = [[CPMenu alloc] init];
|
||||||
item = [[CPMenuItem alloc] initWithTitle:@"Recent Searches"
|
|
||||||
action:nil
|
item = [[CPMenuItem alloc] initWithTitle:@"Recent searches"
|
||||||
|
action:NULL
|
||||||
keyEquivalent:@""];
|
keyEquivalent:@""];
|
||||||
[item setTag:CPSearchFieldRecentsTitleMenuItemTag];
|
[item setTag:CPSearchFieldRecentsTitleMenuItemTag];
|
||||||
[item setEnabled:NO];
|
[item setEnabled:NO];
|
||||||
@@ -553,15 +490,15 @@ var RECENT_SEARCH_PREFIX = @" ";
|
|||||||
[item setTarget:self];
|
[item setTarget:self];
|
||||||
[template addItem:item];
|
[template addItem:item];
|
||||||
|
|
||||||
item = [[CPMenuItem alloc] initWithTitle:@"Clear Recent Searches"
|
item = [[CPMenuItem alloc] initWithTitle:@"Clear recent searches"
|
||||||
action:@selector(_searchFieldClearRecents:)
|
action:@selector(_searchFieldClearRecents:)
|
||||||
keyEquivalent:@""];
|
keyEquivalent:@""];
|
||||||
[item setTag:CPSearchFieldClearRecentsMenuItemTag];
|
[item setTag:CPSearchFieldClearRecentsMenuItemTag];
|
||||||
[item setTarget:self];
|
[item setTarget:self];
|
||||||
[template addItem:item];
|
[template addItem:item];
|
||||||
|
|
||||||
item = [[CPMenuItem alloc] initWithTitle:@"No Recent Searches"
|
item = [[CPMenuItem alloc] initWithTitle:@"No recent searches"
|
||||||
action:nil
|
action:NULL
|
||||||
keyEquivalent:@""];
|
keyEquivalent:@""];
|
||||||
[item setTag:CPSearchFieldNoRecentsMenuItemTag];
|
[item setTag:CPSearchFieldNoRecentsMenuItemTag];
|
||||||
[item setEnabled:NO];
|
[item setEnabled:NO];
|
||||||
@@ -575,96 +512,61 @@ var RECENT_SEARCH_PREFIX = @" ";
|
|||||||
if (_searchMenuTemplate === nil)
|
if (_searchMenuTemplate === nil)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var menu = [[CPMenu alloc] init],
|
var i, menu = [[CPMenu alloc] init],
|
||||||
countOfRecents = [_recentSearches count],
|
countOfRecents = [_recentSearches count],
|
||||||
numberOfItems = [_searchMenuTemplate numberOfItems];
|
numberOfItems = [_searchMenuTemplate numberOfItems];
|
||||||
|
|
||||||
for (var i = 0; i < numberOfItems; i++)
|
for (i = 0; i < numberOfItems; i++)
|
||||||
{
|
{
|
||||||
var item = [[_searchMenuTemplate itemAtIndex:i] copy];
|
var item = [_searchMenuTemplate itemAtIndex:i],
|
||||||
|
tag = [item tag];
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
[item setEnabled:([item isEnabled] && [item action] != nil && [item target] != nil)];
|
if (!(tag === CPSearchFieldRecentsTitleMenuItemTag && countOfRecents === 0) &&
|
||||||
[menu addItem:item];
|
!(tag === CPSearchFieldClearRecentsMenuItemTag && countOfRecents === 0) &&
|
||||||
}
|
!(tag === CPSearchFieldNoRecentsMenuItemTag && countOfRecents != 0) &&
|
||||||
|
!(tag === CPSearchFieldRecentsMenuItemTag))
|
||||||
[menu setDelegate:self];
|
{
|
||||||
|
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;
|
_searchMenu = menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_addSeparatorToMenu:(CPMenu)aMenu
|
- (void)_showMenu:(id)sender
|
||||||
{
|
|
||||||
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
|
|
||||||
{
|
{
|
||||||
if (_searchMenu === nil || [_searchMenu numberOfItems] === 0 || ![self isEnabled])
|
if (_searchMenu === nil || [_searchMenu numberOfItems] === 0 || ![self isEnabled])
|
||||||
return;
|
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];
|
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:sender];
|
||||||
[CPMenu popUpContextMenu:_searchMenu withEvent:anEvent forView:self];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_sendPartialString
|
- (void)_sendPartialString
|
||||||
{
|
{
|
||||||
[super sendAction:[self action] to:[self target]];
|
[[self target] performSelector:[self action] withObject:self];
|
||||||
[_partialStringTimer invalidate];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_searchFieldCancel:(id)sender
|
- (void)_searchFieldCancel:(id)sender
|
||||||
@@ -693,15 +593,14 @@ var RECENT_SEARCH_PREFIX = @" ";
|
|||||||
|
|
||||||
- (void)_searchFieldSearch:(id)sender
|
- (void)_searchFieldSearch:(id)sender
|
||||||
{
|
{
|
||||||
var searchString = [[sender title] substringFromIndex:[RECENT_SEARCH_PREFIX length]];
|
var searchString = [sender title];
|
||||||
|
|
||||||
if ([sender tag] != CPSearchFieldRecentsMenuItemTag)
|
if ([sender tag] != CPSearchFieldRecentsMenuItemTag)
|
||||||
[self _addStringToRecentSearches:searchString];
|
[self _addStringToRecentSearches:searchString];
|
||||||
|
|
||||||
[self setObjectValue:searchString];
|
[self setObjectValue:searchString];
|
||||||
[self _sendPartialString];
|
[self _sendPartialString];
|
||||||
[self selectAll:nil];
|
|
||||||
|
|
||||||
[self _updateCancelButtonVisibility];
|
[self _updateCancelButtonVisibility];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -709,8 +608,6 @@ var RECENT_SEARCH_PREFIX = @" ";
|
|||||||
{
|
{
|
||||||
[self setRecentSearches:[CPArray array]];
|
[self setRecentSearches:[CPArray array]];
|
||||||
[self _updateSearchMenu];
|
[self _updateSearchMenu];
|
||||||
[self setStringValue:@""];
|
|
||||||
[self _updateCancelButtonVisibility];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_registerForAutosaveNotification
|
- (void)_registerForAutosaveNotification
|
||||||
@@ -771,7 +668,7 @@ var CPRecentsAutosaveNameKey = @"CPRecentsAutosaveNameKey",
|
|||||||
CPSendsWholeSearchStringKey = @"CPSendsWholeSearchStringKey",
|
CPSendsWholeSearchStringKey = @"CPSendsWholeSearchStringKey",
|
||||||
CPSendsSearchStringImmediatelyKey = @"CPSendsSearchStringImmediatelyKey",
|
CPSendsSearchStringImmediatelyKey = @"CPSendsSearchStringImmediatelyKey",
|
||||||
CPMaximumRecentsKey = @"CPMaximumRecentsKey",
|
CPMaximumRecentsKey = @"CPMaximumRecentsKey",
|
||||||
CPSearchMenuTemplateKey = @"CPSearchMenuTemplateKey";
|
CPSearchMenuTemplateKey = @"CPSearchMenuTemplateKey";
|
||||||
|
|
||||||
@implementation CPSearchField (CPCoding)
|
@implementation CPSearchField (CPCoding)
|
||||||
|
|
||||||
@@ -793,7 +690,6 @@ var CPRecentsAutosaveNameKey = @"CPRecentsAutosaveNameKey",
|
|||||||
|
|
||||||
if (_recentsAutosaveName)
|
if (_recentsAutosaveName)
|
||||||
[coder encodeObject:_recentsAutosaveName forKey:CPRecentsAutosaveNameKey];
|
[coder encodeObject:_recentsAutosaveName forKey:CPRecentsAutosaveNameKey];
|
||||||
|
|
||||||
if (_searchMenuTemplate)
|
if (_searchMenuTemplate)
|
||||||
[coder encodeObject:_searchMenuTemplate forKey:CPSearchMenuTemplateKey];
|
[coder encodeObject:_searchMenuTemplate forKey:CPSearchMenuTemplateKey];
|
||||||
}
|
}
|
||||||
@@ -802,17 +698,18 @@ var CPRecentsAutosaveNameKey = @"CPRecentsAutosaveNameKey",
|
|||||||
{
|
{
|
||||||
if (self = [super initWithCoder:coder])
|
if (self = [super initWithCoder:coder])
|
||||||
{
|
{
|
||||||
|
[self _initWithFrame:[self frame]];
|
||||||
|
|
||||||
_recentsAutosaveName = [coder decodeObjectForKey:CPRecentsAutosaveNameKey];
|
_recentsAutosaveName = [coder decodeObjectForKey:CPRecentsAutosaveNameKey];
|
||||||
_sendsWholeSearchString = [coder decodeBoolForKey:CPSendsWholeSearchStringKey];
|
_sendsWholeSearchString = [coder decodeBoolForKey:CPSendsWholeSearchStringKey];
|
||||||
_sendsSearchStringImmediately = [coder decodeBoolForKey:CPSendsSearchStringImmediatelyKey];
|
_sendsSearchStringImmediately = [coder decodeBoolForKey:CPSendsSearchStringImmediatelyKey];
|
||||||
_maximumRecents = [coder decodeIntForKey:CPMaximumRecentsKey];
|
_maximumRecents = [coder decodeIntForKey:CPMaximumRecentsKey];
|
||||||
|
|
||||||
var template = [coder decodeObjectForKey:CPSearchMenuTemplateKey];
|
var template = [coder decodeObjectForKey:CPSearchMenuTemplateKey];
|
||||||
|
|
||||||
if (template)
|
if (template)
|
||||||
[self setSearchMenuTemplate:template];
|
[self setSearchMenuTemplate:template];
|
||||||
|
|
||||||
[self _init];
|
[self setDelegate:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
@import "CPTextField.j"
|
@import "CPTextField.j"
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
*/
|
*/
|
||||||
|
|||||||
+133
-132
@@ -24,12 +24,13 @@
|
|||||||
|
|
||||||
@import "CPControl.j"
|
@import "CPControl.j"
|
||||||
|
|
||||||
|
#include "CoreGraphics/CGGeometry.h"
|
||||||
|
|
||||||
CPSegmentSwitchTrackingSelectOne = 0;
|
CPSegmentSwitchTrackingSelectOne = 0;
|
||||||
CPSegmentSwitchTrackingSelectAny = 1;
|
CPSegmentSwitchTrackingSelectAny = 1;
|
||||||
CPSegmentSwitchTrackingMomentary = 2;
|
CPSegmentSwitchTrackingMomentary = 2;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPSegmentedControl
|
@class CPSegmentedControl
|
||||||
|
|
||||||
@@ -48,7 +49,7 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
BOOL _trackingHighlighted;
|
BOOL _trackingHighlighted;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (CPString)defaultThemeClass
|
+ (CPString)themeClass
|
||||||
{
|
{
|
||||||
return "segmented-control";
|
return "segmented-control";
|
||||||
}
|
}
|
||||||
@@ -63,16 +64,16 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
{
|
{
|
||||||
_segments = [];
|
_segments = [];
|
||||||
_themeStates = [];
|
_themeStates = [];
|
||||||
|
|
||||||
self = [super initWithFrame:aRect];
|
self = [super initWithFrame:aRect];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_selectedSegment = -1;
|
_selectedSegment = -1;
|
||||||
|
|
||||||
_trackingMode = CPSegmentSwitchTrackingSelectOne;
|
_trackingMode = CPSegmentSwitchTrackingSelectOne;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +82,7 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
*/
|
*/
|
||||||
- (int)selectedTag
|
- (int)selectedTag
|
||||||
{
|
{
|
||||||
return [_segments[_selectedSegment] tag];
|
return _segments[_selectedSegment].tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Specifying the number of segments
|
// Specifying the number of segments
|
||||||
@@ -93,11 +94,11 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
{
|
{
|
||||||
if (_segments.length == aCount)
|
if (_segments.length == aCount)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var height = CGRectGetHeight([self bounds]);
|
var height = CGRectGetHeight([self bounds]);
|
||||||
|
|
||||||
if (_segments.length < aCount)
|
if (_segments.length < aCount)
|
||||||
{
|
{
|
||||||
for (var index = _segments.length; index < aCount; ++index)
|
for (var index = _segments.length; index < aCount; ++index)
|
||||||
{
|
{
|
||||||
_segments[index] = [[_CPSegmentItem alloc] init];
|
_segments[index] = [[_CPSegmentItem alloc] init];
|
||||||
@@ -150,15 +151,15 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
- (BOOL)selectSegmentWithTag:(int)aTag
|
- (BOOL)selectSegmentWithTag:(int)aTag
|
||||||
{
|
{
|
||||||
var index = 0;
|
var index = 0;
|
||||||
|
|
||||||
for (; index < _segments.length; ++index)
|
for (; index < _segments.length; ++index)
|
||||||
if (_segments[index].tag == aTag)
|
if (_segments[index].tag == aTag)
|
||||||
{
|
{
|
||||||
[self setSelectedSegment:index];
|
[self setSelectedSegment:index];
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,28 +174,28 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
{
|
{
|
||||||
if (_trackingMode == aTrackingMode)
|
if (_trackingMode == aTrackingMode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_trackingMode = aTrackingMode;
|
_trackingMode = aTrackingMode;
|
||||||
|
|
||||||
if (_trackingMode == CPSegmentSwitchTrackingSelectOne)
|
if (_trackingMode == CPSegmentSwitchTrackingSelectOne)
|
||||||
{
|
{
|
||||||
var index = 0,
|
var index = 0,
|
||||||
selected = NO;
|
selected = NO;
|
||||||
|
|
||||||
for (; index < _segments.length; ++index)
|
for (; index < _segments.length; ++index)
|
||||||
if ([_segments[index] selected])
|
if (_segments[index].selected)
|
||||||
if (selected)
|
if (selected)
|
||||||
[self setSelected:NO forSegment:index];
|
[self setSelected:NO forSegment:index];
|
||||||
else
|
else
|
||||||
selected = YES;
|
selected = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (_trackingMode == CPSegmentSwitchTrackingMomentary)
|
else if (_trackingMode == CPSegmentSwitchTrackingMomentary)
|
||||||
{
|
{
|
||||||
var index = 0;
|
var index = 0;
|
||||||
|
|
||||||
for (; index < _segments.length; ++index)
|
for (; index < _segments.length; ++index)
|
||||||
if ([_segments[index] selected])
|
if (_segments[index].selected)
|
||||||
[self setSelected:NO forSegment:index];
|
[self setSelected:NO forSegment:index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,8 +217,8 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
*/
|
*/
|
||||||
- (void)setWidth:(float)aWidth forSegment:(unsigned)aSegment
|
- (void)setWidth:(float)aWidth forSegment:(unsigned)aSegment
|
||||||
{
|
{
|
||||||
[_segments[aSegment] setWidth:aWidth];
|
_segments[aSegment].width = aWidth;
|
||||||
|
|
||||||
[self tileWithChangedSegment:aSegment];
|
[self tileWithChangedSegment:aSegment];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +229,7 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
*/
|
*/
|
||||||
- (float)widthForSegment:(unsigned)aSegment
|
- (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
|
- (void)setImage:(CPImage)anImage forSegment:(unsigned)aSegment
|
||||||
{
|
{
|
||||||
[_segments[aSegment] setImage:anImage];
|
var segment = _segments[aSegment];
|
||||||
|
|
||||||
|
segment.image = anImage;
|
||||||
|
|
||||||
[self tileWithChangedSegment:aSegment];
|
[self tileWithChangedSegment:aSegment];
|
||||||
}
|
}
|
||||||
@@ -251,7 +254,7 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
*/
|
*/
|
||||||
- (CPImage)imageForSegment:(unsigned)aSegment
|
- (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
|
- (void)setLabel:(CPString)aLabel forSegment:(unsigned)aSegment
|
||||||
{
|
{
|
||||||
[_segments[aSegment] setLabel:aLabel];
|
var segment = _segments[aSegment];
|
||||||
|
|
||||||
|
_segments[aSegment].label = aLabel;
|
||||||
|
|
||||||
[self tileWithChangedSegment:aSegment];
|
[self tileWithChangedSegment:aSegment];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,7 +279,7 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
*/
|
*/
|
||||||
- (CPString)labelForSegment:(unsigned)aSegment
|
- (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
|
- (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
|
- (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
|
- (void)setSelected:(BOOL)isSelected forSegment:(unsigned)aSegment
|
||||||
{
|
{
|
||||||
var segment = _segments[aSegment];
|
var segment = _segments[aSegment];
|
||||||
|
|
||||||
// If we're already in this state, bail.
|
// If we're already in this state, bail.
|
||||||
if ([segment selected] == isSelected)
|
if (segment.selected == isSelected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[segment setSelected:isSelected];
|
segment.selected = isSelected;
|
||||||
|
|
||||||
_themeStates[aSegment] = isSelected ? CPThemeStateSelected : CPThemeStateNormal;
|
_themeStates[aSegment] = isSelected ? CPThemeStateSelected : CPThemeStateNormal;
|
||||||
|
|
||||||
@@ -321,18 +326,18 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
if (isSelected)
|
if (isSelected)
|
||||||
{
|
{
|
||||||
var oldSelectedSegment = _selectedSegment;
|
var oldSelectedSegment = _selectedSegment;
|
||||||
|
|
||||||
_selectedSegment = aSegment;
|
_selectedSegment = aSegment;
|
||||||
|
|
||||||
if (_trackingMode == CPSegmentSwitchTrackingSelectOne && oldSelectedSegment != aSegment && oldSelectedSegment != -1)
|
if (_trackingMode == CPSegmentSwitchTrackingSelectOne && oldSelectedSegment != aSegment && oldSelectedSegment != -1)
|
||||||
{
|
{
|
||||||
[_segments[oldSelectedSegment] setSelected:NO];
|
_segments[oldSelectedSegment].selected = NO;
|
||||||
_themeStates[oldSelectedSegment] = CPThemeStateNormal;
|
_themeStates[oldSelectedSegment] = CPThemeStateNormal;
|
||||||
|
|
||||||
[self drawSegmentBezel:oldSelectedSegment highlight:NO];
|
[self drawSegmentBezel:oldSelectedSegment highlight:NO];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_trackingMode != CPSegmentSwitchTrackingMomentary)
|
if (_trackingMode != CPSegmentSwitchTrackingMomentary)
|
||||||
[self drawSegmentBezel:aSegment highlight:NO];
|
[self drawSegmentBezel:aSegment highlight:NO];
|
||||||
|
|
||||||
@@ -347,7 +352,7 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
*/
|
*/
|
||||||
- (BOOL)isSelectedForSegment:(unsigned)aSegment
|
- (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
|
- (void)setEnabled:(BOOL)isEnabled forSegment:(unsigned)aSegment
|
||||||
{
|
{
|
||||||
[_segments[aSegment] setEnabled:isEnabled];
|
|
||||||
|
|
||||||
if (isEnabled)
|
if (isEnabled)
|
||||||
_themeStates[aSegment] &= ~CPThemeStateDisabled;
|
_themeStates[aSegment] &= ~CPThemeStateDisabled;
|
||||||
else
|
else
|
||||||
@@ -376,7 +379,7 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
*/
|
*/
|
||||||
- (BOOL)isEnabledForSegment:(unsigned)aSegment
|
- (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
|
- (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
|
- (int)tagForSegment:(unsigned)aSegment
|
||||||
{
|
{
|
||||||
return [_segments[aSegment] tag];
|
return _segments[aSegment].tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drawings
|
// Drawings
|
||||||
@@ -458,7 +461,7 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
else if (aName.indexOf("segment-bezel") === 0)
|
else if (aName.indexOf("segment-bezel") === 0)
|
||||||
{
|
{
|
||||||
var segment = parseInt(aName.substring("segment-bezel-".length), 10),
|
var segment = parseInt(aName.substring("segment-bezel-".length), 10),
|
||||||
frame = CGRectCreateCopy([_segments[segment] frame]);
|
frame = CGRectCreateCopy(_segments[segment].frame);
|
||||||
|
|
||||||
if (segment === 0)
|
if (segment === 0)
|
||||||
{
|
{
|
||||||
@@ -492,7 +495,7 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
|
|
||||||
- (CPView)createEphemeralSubviewNamed:(CPString)aName
|
- (CPView)createEphemeralSubviewNamed:(CPString)aName
|
||||||
{
|
{
|
||||||
if ([aName hasPrefix:@"segment-content"])
|
if (aName.substring(0, "segment-content".length) == "segment-content")
|
||||||
return [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
|
return [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
|
||||||
|
|
||||||
return [[CPView alloc] initWithFrame:_CGRectMakeZero()];
|
return [[CPView alloc] initWithFrame:_CGRectMakeZero()];
|
||||||
@@ -507,10 +510,10 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
|
|
||||||
themeState |= _themeState & CPThemeStateDisabled;
|
themeState |= _themeState & CPThemeStateDisabled;
|
||||||
|
|
||||||
var leftCapColor = [self valueForThemeAttribute:@"left-segment-bezel-color"
|
var leftCapColor = [self valueForThemeAttribute:@"left-segment-bezel-color"
|
||||||
inState:themeState],
|
inState:themeState];
|
||||||
|
|
||||||
leftBezelView = [self layoutEphemeralSubviewNamed:@"left-segment-bezel"
|
var leftBezelView = [self layoutEphemeralSubviewNamed:@"left-segment-bezel"
|
||||||
positioned:CPWindowBelow
|
positioned:CPWindowBelow
|
||||||
relativeToEphemeralSubviewNamed:nil];
|
relativeToEphemeralSubviewNamed:nil];
|
||||||
|
|
||||||
@@ -520,39 +523,41 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
|
|
||||||
themeState |= _themeState & CPThemeStateDisabled;
|
themeState |= _themeState & CPThemeStateDisabled;
|
||||||
|
|
||||||
var rightCapColor = [self valueForThemeAttribute:@"right-segment-bezel-color"
|
var rightCapColor = [self valueForThemeAttribute:@"right-segment-bezel-color"
|
||||||
inState:themeState],
|
inState:themeState];
|
||||||
|
|
||||||
rightBezelView = [self layoutEphemeralSubviewNamed:@"right-segment-bezel"
|
var rightBezelView = [self layoutEphemeralSubviewNamed:@"right-segment-bezel"
|
||||||
positioned:CPWindowBelow
|
positioned:CPWindowBelow
|
||||||
relativeToEphemeralSubviewNamed:nil];
|
relativeToEphemeralSubviewNamed:nil];
|
||||||
|
|
||||||
[rightBezelView setBackgroundColor:rightCapColor];
|
[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];
|
var themeState = _themeStates[i];
|
||||||
|
|
||||||
themeState |= _themeState & CPThemeStateDisabled;
|
themeState |= _themeState & CPThemeStateDisabled;
|
||||||
|
|
||||||
var bezelColor = [self valueForThemeAttribute:@"center-segment-bezel-color"
|
var bezelColor = [self valueForThemeAttribute:@"center-segment-bezel-color"
|
||||||
inState:themeState],
|
inState:themeState];
|
||||||
|
|
||||||
bezelView = [self layoutEphemeralSubviewNamed:"segment-bezel-" + i
|
var bezelView = [self layoutEphemeralSubviewNamed:"segment-bezel-"+i
|
||||||
positioned:CPWindowBelow
|
positioned:CPWindowBelow
|
||||||
relativeToEphemeralSubviewNamed:nil];
|
relativeToEphemeralSubviewNamed:nil];
|
||||||
|
|
||||||
[bezelView setBackgroundColor:bezelColor];
|
[bezelView setBackgroundColor:bezelColor];
|
||||||
|
|
||||||
|
|
||||||
// layout image/title views
|
//layout image/title views
|
||||||
var segment = _segments[i],
|
var segment = _segments[i];
|
||||||
contentView = [self layoutEphemeralSubviewNamed:@"segment-content-" + i
|
|
||||||
positioned:CPWindowAbove
|
|
||||||
relativeToEphemeralSubviewNamed:@"segment-bezel-" + 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 setFont:[self valueForThemeAttribute:@"font" inState:themeState]];
|
||||||
[contentView setTextColor:[self valueForThemeAttribute:@"text-color" 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 setLineBreakMode:[self valueForThemeAttribute:@"line-break-mode" inState:themeState]];
|
||||||
[contentView setTextShadowColor:[self valueForThemeAttribute:@"text-shadow-color" inState:themeState]];
|
[contentView setTextShadowColor:[self valueForThemeAttribute:@"text-shadow-color" inState:themeState]];
|
||||||
[contentView setTextShadowOffset:[self valueForThemeAttribute:@"text-shadow-offset" inState:themeState]];
|
[contentView setTextShadowOffset:[self valueForThemeAttribute:@"text-shadow-offset" inState:themeState]];
|
||||||
[contentView setImageScaling:[self valueForThemeAttribute:@"image-scaling" inState:themeState]];
|
[contentView setImageScaling:[self valueForThemeAttribute:@"image-scaling" inState:themeState]];
|
||||||
|
|
||||||
if ([segment image] && [segment label])
|
if (segment.image && segment.label)
|
||||||
[contentView setImagePosition:[self valueForThemeAttribute:@"image-position" inState:themeState]];
|
[contentView setImagePosition:[self valueForThemeAttribute:@"image-position" inState:themeState]];
|
||||||
else if ([segment image])
|
else if (segment.image)
|
||||||
[contentView setImagePosition:CPImageOnly];
|
[contentView setImagePosition:CPImageOnly];
|
||||||
|
|
||||||
if (i == count - 1)
|
if (i == count - 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var borderState = _themeStates[i] | _themeStates[i + 1];
|
var borderState = _themeStates[i] | _themeStates[i+1];
|
||||||
|
|
||||||
borderState = (borderState & CPThemeStateSelected & ~CPThemeStateHighlighted) ? CPThemeStateSelected : CPThemeStateNormal;
|
borderState = (borderState & CPThemeStateSelected & ~CPThemeStateHighlighted) ? CPThemeStateSelected : CPThemeStateNormal;
|
||||||
|
|
||||||
borderState |= _themeState & CPThemeStateDisabled;
|
borderState |= _themeState & CPThemeStateDisabled;
|
||||||
|
|
||||||
var borderColor = [self valueForThemeAttribute:@"divider-bezel-color"
|
var borderColor = [self valueForThemeAttribute:@"divider-bezel-color"
|
||||||
inState:borderState],
|
inState:borderState];
|
||||||
|
|
||||||
borderView = [self layoutEphemeralSubviewNamed:"divider-bezel-" + i
|
var borderView = [self layoutEphemeralSubviewNamed:"divider-bezel-"+i
|
||||||
positioned:CPWindowBelow
|
positioned:CPWindowBelow
|
||||||
relativeToEphemeralSubviewNamed:nil];
|
relativeToEphemeralSubviewNamed:nil];
|
||||||
|
|
||||||
[borderView setBackgroundColor:borderColor];
|
[borderView setBackgroundColor:borderColor];
|
||||||
@@ -604,53 +609,48 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var segment = _segments[aSegment],
|
var segment = _segments[aSegment],
|
||||||
segmentWidth = [segment width],
|
segmentWidth = segment.width,
|
||||||
themeState = _themeStates[aSegment] | (_themeState & CPThemeStateDisabled),
|
themeState = _themeStates[aSegment] | (_themeState & CPThemeStateDisabled),
|
||||||
contentInset = [self valueForThemeAttribute:@"content-inset" inState:themeState],
|
contentInset = [self valueForThemeAttribute:@"content-inset" inState:themeState],
|
||||||
font = [self valueForThemeAttribute:@"font" inState:themeState];
|
font = [self valueForThemeAttribute:@"font" inState:themeState];
|
||||||
|
|
||||||
if (!segmentWidth)
|
if (!segmentWidth)
|
||||||
{
|
{
|
||||||
if ([segment image] && [segment label])
|
if (segment.image && segment.label)
|
||||||
segmentWidth = [[segment label] sizeWithFont:font].width + [[segment image] size].width + contentInset.left + contentInset.right;
|
segmentWidth = [segment.label sizeWithFont:font].width + [segment.image size].width + contentInset.left + contentInset.right;
|
||||||
else if (segment.image)
|
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)
|
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
|
else
|
||||||
segmentWidth = 0.0;
|
segmentWidth = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
var delta = segmentWidth - CGRectGetWidth([segment frame]);
|
var delta = segmentWidth - CGRectGetWidth(segment.frame);
|
||||||
|
|
||||||
if (!delta)
|
if (!delta)
|
||||||
{
|
|
||||||
[self setNeedsLayout];
|
|
||||||
[self setNeedsDisplay:YES];
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// Update control size
|
// Update Contorl Size
|
||||||
var frame = [self frame];
|
var frame = [self frame];
|
||||||
|
|
||||||
[self setFrameSize:CGSizeMake(CGRectGetWidth(frame) + delta, CGRectGetHeight(frame))];
|
[self setFrameSize:CGSizeMake(CGRectGetWidth(frame) + delta, CGRectGetHeight(frame))];
|
||||||
|
|
||||||
// Update segment width
|
// Update Segment Width
|
||||||
[segment setWidth:segmentWidth];
|
segment.width = segmentWidth;
|
||||||
[segment setFrame:[self frameForSegment:aSegment]];
|
segment.frame = [self frameForSegment:aSegment];;
|
||||||
|
|
||||||
// Update following segments widths
|
// Update Following Segments Widths
|
||||||
var index = aSegment + 1;
|
var index = aSegment + 1;
|
||||||
|
|
||||||
for (; index < _segments.length; ++index)
|
for (; index < _segments.length; ++index)
|
||||||
{
|
{
|
||||||
[_segments[index] frame].origin.x += delta;
|
_segments[index].frame.origin.x += delta;
|
||||||
|
|
||||||
[self drawSegmentBezel:index highlight:NO];
|
[self drawSegmentBezel:index highlight:NO];
|
||||||
[self drawSegment:index highlight:NO];
|
[self drawSegment:index highlight:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
[self drawSegmentBezel:aSegment highlight:NO];
|
[self drawSegmentBezel:aSegment highlight:NO];
|
||||||
[self drawSegment:aSegment highlight:NO];
|
[self drawSegment:aSegment highlight:NO];
|
||||||
|
|
||||||
@@ -696,14 +696,14 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
{
|
{
|
||||||
var location = [self convertPoint:aPoint fromView:nil],
|
var location = [self convertPoint:aPoint fromView:nil],
|
||||||
count = _segments.length;
|
count = _segments.length;
|
||||||
|
|
||||||
while (count--)
|
while (count--)
|
||||||
if (CGRectContainsPoint([_segments[count] frame], aPoint))
|
if (CGRectContainsPoint(_segments[count].frame, aPoint))
|
||||||
return count;
|
return count;
|
||||||
|
|
||||||
if (_segments.length)
|
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;
|
adjustedLastFrame.size.width = CGRectGetWidth([self bounds]) - adjustedLastFrame.origin.x;
|
||||||
|
|
||||||
if (CGRectContainsPoint(adjustedLastFrame, aPoint))
|
if (CGRectContainsPoint(adjustedLastFrame, aPoint))
|
||||||
@@ -717,7 +717,7 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
{
|
{
|
||||||
if (![self isEnabled])
|
if (![self isEnabled])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[self trackSegment:anEvent];
|
[self trackSegment:anEvent];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -731,10 +731,10 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
@param anEvent the event to handle
|
@param anEvent the event to handle
|
||||||
*/
|
*/
|
||||||
- (void)trackSegment:(CPEvent)anEvent
|
- (void)trackSegment:(CPEvent)anEvent
|
||||||
{
|
{
|
||||||
var type = [anEvent type],
|
var type = [anEvent type],
|
||||||
location = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
location = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
||||||
|
|
||||||
if (type == CPLeftMouseUp)
|
if (type == CPLeftMouseUp)
|
||||||
{
|
{
|
||||||
if (_trackingSegment == -1)
|
if (_trackingSegment == -1)
|
||||||
@@ -745,30 +745,30 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
if (_trackingMode == CPSegmentSwitchTrackingSelectAny)
|
if (_trackingMode == CPSegmentSwitchTrackingSelectAny)
|
||||||
{
|
{
|
||||||
[self setSelected:![self isSelectedForSegment:_trackingSegment] forSegment:_trackingSegment];
|
[self setSelected:![self isSelectedForSegment:_trackingSegment] forSegment:_trackingSegment];
|
||||||
|
|
||||||
// With ANY, _selectedSegment means last pressed.
|
// With ANY, _selectedSegment means last pressed.
|
||||||
_selectedSegment = _trackingSegment;
|
_selectedSegment = _trackingSegment;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
[self setSelected:YES forSegment:_trackingSegment];
|
[self setSelected:YES forSegment:_trackingSegment];
|
||||||
|
|
||||||
[self sendAction:[self action] to:[self target]];
|
[self sendAction:[self action] to:[self target]];
|
||||||
|
|
||||||
if (_trackingMode == CPSegmentSwitchTrackingMomentary)
|
if (_trackingMode == CPSegmentSwitchTrackingMomentary)
|
||||||
{
|
{
|
||||||
[self setSelected:NO forSegment:_trackingSegment];
|
[self setSelected:NO forSegment:_trackingSegment];
|
||||||
|
|
||||||
_selectedSegment = -1;
|
_selectedSegment = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[self drawSegmentBezel:_trackingSegment highlight:NO];
|
[self drawSegmentBezel:_trackingSegment highlight:NO];
|
||||||
|
|
||||||
_trackingSegment = -1;
|
_trackingSegment = -1;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == CPLeftMouseDown)
|
if (type == CPLeftMouseDown)
|
||||||
{
|
{
|
||||||
var trackingSegment = [self testSegment:location];
|
var trackingSegment = [self testSegment:location];
|
||||||
@@ -779,7 +779,7 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
[self drawSegmentBezel:_trackingSegment highlight:YES];
|
[self drawSegmentBezel:_trackingSegment highlight:YES];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (type == CPLeftMouseDragged)
|
else if (type == CPLeftMouseDragged)
|
||||||
{
|
{
|
||||||
if (_trackingSegment == -1)
|
if (_trackingSegment == -1)
|
||||||
@@ -793,14 +793,14 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
[self drawSegmentBezel:_trackingSegment highlight:_trackingHighlighted];
|
[self drawSegmentBezel:_trackingSegment highlight:_trackingHighlighted];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[CPApp setTarget:self selector:@selector(trackSegment:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
|
[CPApp setTarget:self selector:@selector(trackSegment:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setFont:(CPFont)aFont
|
- (void)setFont:(CPFont)aFont
|
||||||
{
|
{
|
||||||
[super setFont:aFont];
|
[super setFont:aFont];
|
||||||
|
|
||||||
[self tileWithChangedSegment:0];
|
[self tileWithChangedSegment:0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -816,12 +816,12 @@ var CPSegmentedControlSegmentsKey = "CPSegmentedControlSegmentsKey",
|
|||||||
- (id)initWithCoder:(CPCoder)aCoder
|
- (id)initWithCoder:(CPCoder)aCoder
|
||||||
{
|
{
|
||||||
self = [super initWithCoder:aCoder];
|
self = [super initWithCoder:aCoder];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
var frame = [self frame],
|
var frame = [self frame],
|
||||||
originalWidth = frame.size.width;
|
originalWidth = frame.size.width;
|
||||||
|
|
||||||
frame.size.width = 0;
|
frame.size.width = 0;
|
||||||
|
|
||||||
[self setFrame:frame];
|
[self setFrame:frame];
|
||||||
@@ -832,38 +832,38 @@ var CPSegmentedControlSegmentsKey = "CPSegmentedControlSegmentsKey",
|
|||||||
|
|
||||||
if ([aCoder containsValueForKey:CPSegmentedControlSelectedKey])
|
if ([aCoder containsValueForKey:CPSegmentedControlSelectedKey])
|
||||||
_selectedSegment = [aCoder decodeIntForKey:CPSegmentedControlSelectedKey];
|
_selectedSegment = [aCoder decodeIntForKey:CPSegmentedControlSelectedKey];
|
||||||
else
|
else
|
||||||
_selectedSegment = -1;
|
_selectedSegment = -1;
|
||||||
|
|
||||||
if ([aCoder containsValueForKey:CPSegmentedControlTrackingModeKey])
|
if ([aCoder containsValueForKey:CPSegmentedControlTrackingModeKey])
|
||||||
_trackingMode = [aCoder decodeIntForKey:CPSegmentedControlTrackingModeKey];
|
_trackingMode = [aCoder decodeIntForKey:CPSegmentedControlTrackingModeKey];
|
||||||
else
|
else
|
||||||
_trackingMode = CPSegmentSwitchTrackingSelectOne;
|
_trackingMode = CPSegmentSwitchTrackingSelectOne;
|
||||||
|
|
||||||
// HACK
|
// HACK
|
||||||
|
|
||||||
for (var i = 0; i < _segments.length; i++)
|
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];
|
[self tileWithChangedSegment:i];
|
||||||
}
|
}
|
||||||
|
|
||||||
var difference = MAX(originalWidth - [self frame].size.width, 0.0),
|
var difference = MAX(originalWidth - [self frame].size.width, 0.0),
|
||||||
remainingWidth = FLOOR(difference / _segments.length);
|
remainingWidth = FLOOR(difference / _segments.length);
|
||||||
|
|
||||||
for (var i = 0; i < _segments.length; i++)
|
for (var i=0; i < _segments.length; i++)
|
||||||
[self setWidth:[_segments[i] width] + remainingWidth forSegment:i];
|
[self setWidth:_segments[i].width + remainingWidth forSegment:i];
|
||||||
|
|
||||||
[self tileWithChangedSegment:0];
|
[self tileWithChangedSegment:0];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||||
{
|
{
|
||||||
[super encodeWithCoder:aCoder];
|
[super encodeWithCoder:aCoder];
|
||||||
|
|
||||||
[aCoder encodeObject:_segments forKey:CPSegmentedControlSegmentsKey];
|
[aCoder encodeObject:_segments forKey:CPSegmentedControlSegmentsKey];
|
||||||
[aCoder encodeInt:_selectedSegment forKey:CPSegmentedControlSelectedKey];
|
[aCoder encodeInt:_selectedSegment forKey:CPSegmentedControlSelectedKey];
|
||||||
[aCoder encodeInt:_segmentStyle forKey:CPSegmentedControlSegmentStyleKey];
|
[aCoder encodeInt:_segmentStyle forKey:CPSegmentedControlSegmentStyleKey];
|
||||||
@@ -875,15 +875,15 @@ var CPSegmentedControlSegmentsKey = "CPSegmentedControlSegmentsKey",
|
|||||||
|
|
||||||
@implementation _CPSegmentItem : CPObject
|
@implementation _CPSegmentItem : CPObject
|
||||||
{
|
{
|
||||||
CPImage image @accessors;
|
CPImage image;
|
||||||
CPString label @accessors;
|
CPString label;
|
||||||
CPMenu menu @accessors;
|
CPMenu menu;
|
||||||
BOOL selected @accessors;
|
BOOL selected;
|
||||||
BOOL enabled @accessors;
|
BOOL enabled;
|
||||||
int tag @accessors;
|
int tag;
|
||||||
int width @accessors;
|
int width;
|
||||||
|
|
||||||
CGRect frame @accessors;
|
CGRect frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)init
|
- (id)init
|
||||||
@@ -894,8 +894,8 @@ var CPSegmentedControlSegmentsKey = "CPSegmentedControlSegmentsKey",
|
|||||||
label = @"";
|
label = @"";
|
||||||
menu = nil;
|
menu = nil;
|
||||||
selected = NO;
|
selected = NO;
|
||||||
enabled = YES;
|
enabled = NO;
|
||||||
tag = -1;
|
tag = 0;
|
||||||
width = 0;
|
width = 0;
|
||||||
|
|
||||||
frame = CGRectMakeZero();
|
frame = CGRectMakeZero();
|
||||||
@@ -918,7 +918,7 @@ var CPSegmentItemImageKey = "CPSegmentItemImageKey",
|
|||||||
- (id)initWithCoder:(CPCoder)aCoder
|
- (id)initWithCoder:(CPCoder)aCoder
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
image = [aCoder decodeObjectForKey:CPSegmentItemImageKey];
|
image = [aCoder decodeObjectForKey:CPSegmentItemImageKey];
|
||||||
@@ -931,7 +931,7 @@ var CPSegmentItemImageKey = "CPSegmentItemImageKey",
|
|||||||
|
|
||||||
frame = CGRectMakeZero();
|
frame = CGRectMakeZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -947,3 +947,4 @@ var CPSegmentItemImageKey = "CPSegmentItemImageKey",
|
|||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
+18
-41
@@ -28,17 +28,19 @@
|
|||||||
@import "CPView.j"
|
@import "CPView.j"
|
||||||
|
|
||||||
|
|
||||||
|
#include "CoreGraphics/CGGeometry.h"
|
||||||
|
|
||||||
CPLightShadow = 0;
|
CPLightShadow = 0;
|
||||||
CPHeavyShadow = 1;
|
CPHeavyShadow = 1;
|
||||||
|
|
||||||
var CPShadowViewLightBackgroundColor = nil,
|
var CPShadowViewLightBackgroundColor = nil,
|
||||||
CPShadowViewHeavyBackgroundColor = nil;
|
CPShadowViewHeavyBackgroundColor = nil;
|
||||||
|
|
||||||
var LIGHT_LEFT_INSET = 3.0,
|
var LIGHT_LEFT_INSET = 3.0,
|
||||||
LIGHT_RIGHT_INSET = 3.0,
|
LIGHT_RIGHT_INSET = 3.0,
|
||||||
LIGHT_TOP_INSET = 3.0,
|
LIGHT_TOP_INSET = 3.0,
|
||||||
LIGHT_BOTTOM_INSET = 5.0,
|
LIGHT_BOTTOM_INSET = 5.0,
|
||||||
|
|
||||||
HEAVY_LEFT_INSET = 7.0,
|
HEAVY_LEFT_INSET = 7.0,
|
||||||
HEAVY_RIGHT_INSET = 7.0,
|
HEAVY_RIGHT_INSET = 7.0,
|
||||||
HEAVY_TOP_INSET = 5.0,
|
HEAVY_TOP_INSET = 5.0,
|
||||||
@@ -59,76 +61,51 @@ var LIGHT_LEFT_INSET = 3.0,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var bundle = [CPBundle bundleForClass:[self class]];
|
var bundle = [CPBundle bundleForClass:[self class]];
|
||||||
|
|
||||||
CPShadowViewLightBackgroundColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:
|
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/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/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/CPShadowViewLightTopRight.png"] size:CGSizeMake(9.0, 9.0)],
|
||||||
|
|
||||||
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightLeft.png"] size:CGSizeMake(9.0, 1.0)],
|
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightLeft.png"] size:CGSizeMake(9.0, 1.0)],
|
||||||
nil,
|
nil,
|
||||||
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightRight.png"] size:CGSizeMake(9.0, 1.0)],
|
[[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/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/CPShadowViewLightBottom.png"] size:CGSizeMake(1.0, 9.0)],
|
||||||
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightBottomRight.png"] size:CGSizeMake(9.0, 9.0)]
|
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightBottomRight.png"] size:CGSizeMake(9.0, 9.0)]
|
||||||
]]];
|
]]];
|
||||||
|
|
||||||
CPShadowViewHeavyBackgroundColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:
|
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/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/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/CPShadowViewHeavyTopRight.png"] size:CGSizeMake(17.0, 17.0)],
|
||||||
|
|
||||||
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyLeft.png"] size:CGSizeMake(17.0, 1.0)],
|
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyLeft.png"] size:CGSizeMake(17.0, 1.0)],
|
||||||
nil,
|
nil,
|
||||||
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyRight.png"] size:CGSizeMake(17.0, 1.0)],
|
[[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/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/CPShadowViewHeavyBottom.png"] size:CGSizeMake(1.0, 17.0)],
|
||||||
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyBottomRight.png"] size:CGSizeMake(17.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
|
- (id)initWithFrame:(CGRect)aFrame
|
||||||
{
|
{
|
||||||
self = [super initWithFrame:aFrame];
|
self = [super initWithFrame:aFrame];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_weight = CPLightShadow;
|
_weight = CPLightShadow;
|
||||||
|
|
||||||
[self setBackgroundColor:CPShadowViewLightBackgroundColor];
|
[self setBackgroundColor:CPShadowViewLightBackgroundColor];
|
||||||
|
|
||||||
[self setHitTests:NO];
|
[self setHitTests:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,9 +113,9 @@ var LIGHT_LEFT_INSET = 3.0,
|
|||||||
{
|
{
|
||||||
if (_weight == aWeight)
|
if (_weight == aWeight)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_weight = aWeight;
|
_weight = aWeight;
|
||||||
|
|
||||||
if (_weight == CPLightShadow)
|
if (_weight == CPLightShadow)
|
||||||
[self setBackgroundColor:CPShadowViewLightBackgroundColor];
|
[self setBackgroundColor:CPShadowViewLightBackgroundColor];
|
||||||
|
|
||||||
@@ -170,7 +147,7 @@ var LIGHT_LEFT_INSET = 3.0,
|
|||||||
{
|
{
|
||||||
if (_weight == CPLightShadow)
|
if (_weight == CPLightShadow)
|
||||||
return LIGHT_LEFT_INSET + LIGHT_RIGHT_INSET;
|
return LIGHT_LEFT_INSET + LIGHT_RIGHT_INSET;
|
||||||
|
|
||||||
return HEAVY_LEFT_INSET + HEAVY_RIGHT_INSET;
|
return HEAVY_LEFT_INSET + HEAVY_RIGHT_INSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,7 +155,7 @@ var LIGHT_LEFT_INSET = 3.0,
|
|||||||
{
|
{
|
||||||
if (_weight == CPLightShadow)
|
if (_weight == CPLightShadow)
|
||||||
return LIGHT_TOP_INSET + LIGHT_BOTTOM_INSET;
|
return LIGHT_TOP_INSET + LIGHT_BOTTOM_INSET;
|
||||||
|
|
||||||
return HEAVY_TOP_INSET + HEAVY_BOTTOM_INSET;
|
return HEAVY_TOP_INSET + HEAVY_BOTTOM_INSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+40
-50
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
@import "CPControl.j"
|
@import "CPControl.j"
|
||||||
|
|
||||||
|
#include "CoreGraphics/CGGeometry.h"
|
||||||
|
|
||||||
/*! SLIDER STATES */
|
/*! SLIDER STATES */
|
||||||
|
|
||||||
@@ -41,7 +42,7 @@ CPCircularSlider = 1;
|
|||||||
BOOL _isVertical;
|
BOOL _isVertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (CPString)defaultThemeClass
|
+ (CPString)themeClass
|
||||||
{
|
{
|
||||||
return "slider";
|
return "slider";
|
||||||
}
|
}
|
||||||
@@ -60,14 +61,14 @@ CPCircularSlider = 1;
|
|||||||
{
|
{
|
||||||
_minValue = 0.0;
|
_minValue = 0.0;
|
||||||
_maxValue = 100.0;
|
_maxValue = 100.0;
|
||||||
|
|
||||||
[self setObjectValue:50.0];
|
[self setObjectValue:50.0];
|
||||||
|
|
||||||
[self setContinuous:YES];
|
[self setContinuous:YES];
|
||||||
|
|
||||||
[self _recalculateIsVertical];
|
[self _recalculateIsVertical];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,11 +76,11 @@ CPCircularSlider = 1;
|
|||||||
{
|
{
|
||||||
if (_minValue === aMinimumValue)
|
if (_minValue === aMinimumValue)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_minValue = aMinimumValue;
|
_minValue = aMinimumValue;
|
||||||
|
|
||||||
var doubleValue = [self doubleValue];
|
var doubleValue = [self doubleValue];
|
||||||
|
|
||||||
if (doubleValue < _minValue)
|
if (doubleValue < _minValue)
|
||||||
[self setDoubleValue:_minValue];
|
[self setDoubleValue:_minValue];
|
||||||
|
|
||||||
@@ -97,11 +98,11 @@ CPCircularSlider = 1;
|
|||||||
{
|
{
|
||||||
if (_maxValue === aMaximumValue)
|
if (_maxValue === aMaximumValue)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_maxValue = aMaximumValue;
|
_maxValue = aMaximumValue;
|
||||||
|
|
||||||
var doubleValue = [self doubleValue];
|
var doubleValue = [self doubleValue];
|
||||||
|
|
||||||
if (doubleValue > _maxValue)
|
if (doubleValue > _maxValue)
|
||||||
[self setDoubleValue:_maxValue];
|
[self setDoubleValue:_maxValue];
|
||||||
|
|
||||||
@@ -168,27 +169,27 @@ CPCircularSlider = 1;
|
|||||||
bounds.size.height = trackWidth;
|
bounds.size.height = trackWidth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGRect)knobRectForBounds:(CGRect)bounds
|
- (CGRect)knobRectForBounds:(CGRect)bounds
|
||||||
{
|
{
|
||||||
var knobSize = [self currentValueForThemeAttribute:@"knob-size"];
|
var knobSize = [self currentValueForThemeAttribute:@"knob-size"];
|
||||||
|
|
||||||
if (knobSize.width <= 0 || knobSize.height <= 0)
|
if (knobSize.width <= 0 || knobSize.height <= 0)
|
||||||
return _CGRectMakeZero();
|
return _CGRectMakeZero();
|
||||||
|
|
||||||
var knobRect = _CGRectMake(0.0, 0.0, knobSize.width, knobSize.height),
|
var knobRect = _CGRectMake(0.0, 0.0, knobSize.width, knobSize.height),
|
||||||
trackRect = [self trackRectForBounds:bounds];
|
trackRect = [self trackRectForBounds:bounds];
|
||||||
|
|
||||||
// No track, do our best to approximate a place for this thing.
|
// No track, do our best to approximate a place for this thing.
|
||||||
if (!trackRect || _CGRectIsEmpty(trackRect))
|
if (!trackRect || _CGRectIsEmpty(trackRect))
|
||||||
trackRect = bounds;
|
trackRect = bounds;
|
||||||
|
|
||||||
if ([self hasThemeState:CPThemeStateCircular])
|
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;
|
radius = CGRectGetWidth(trackRect) / 2.0 - 8.0;
|
||||||
|
|
||||||
knobRect.origin.x = radius * COS(angle) + CGRectGetMidX(trackRect) - 3.0;
|
knobRect.origin.x = radius * COS(angle) + CGRectGetMidX(trackRect) - 3.0;
|
||||||
@@ -197,7 +198,7 @@ CPCircularSlider = 1;
|
|||||||
else if ([self isVertical])
|
else if ([self isVertical])
|
||||||
{
|
{
|
||||||
knobRect.origin.x = _CGRectGetMidX(trackRect) - knobSize.width / 2.0;
|
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
|
else
|
||||||
{
|
{
|
||||||
@@ -212,10 +213,10 @@ CPCircularSlider = 1;
|
|||||||
{
|
{
|
||||||
if (aName === "track-view")
|
if (aName === "track-view")
|
||||||
return [self trackRectForBounds:[self bounds]];
|
return [self trackRectForBounds:[self bounds]];
|
||||||
|
|
||||||
else if (aName === "knob-view")
|
else if (aName === "knob-view")
|
||||||
return [self knobRectForBounds:[self bounds]];
|
return [self knobRectForBounds:[self bounds]];
|
||||||
|
|
||||||
return [super rectForEphemeralSubviewNamed:aName];
|
return [super rectForEphemeralSubviewNamed:aName];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,12 +225,12 @@ CPCircularSlider = 1;
|
|||||||
if (aName === "track-view" || aName === "knob-view")
|
if (aName === "track-view" || aName === "knob-view")
|
||||||
{
|
{
|
||||||
var view = [[CPView alloc] init];
|
var view = [[CPView alloc] init];
|
||||||
|
|
||||||
[view setHitTests:NO];
|
[view setHitTests:NO];
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [super createEphemeralSubviewNamed:aName];
|
return [super createEphemeralSubviewNamed:aName];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,7 +256,7 @@ CPCircularSlider = 1;
|
|||||||
var bounds = [self bounds],
|
var bounds = [self bounds],
|
||||||
width = _CGRectGetWidth(bounds),
|
width = _CGRectGetWidth(bounds),
|
||||||
height = _CGRectGetHeight(bounds);
|
height = _CGRectGetHeight(bounds);
|
||||||
|
|
||||||
_isVertical = width < height ? 1 : (width > height ? 0 : -1);
|
_isVertical = width < height ? 1 : (width > height ? 0 : -1);
|
||||||
|
|
||||||
if (_isVertical === 1)
|
if (_isVertical === 1)
|
||||||
@@ -281,7 +282,7 @@ CPCircularSlider = 1;
|
|||||||
var knobView = [self layoutEphemeralSubviewNamed:@"knob-view"
|
var knobView = [self layoutEphemeralSubviewNamed:@"knob-view"
|
||||||
positioned:CPWindowAbove
|
positioned:CPWindowAbove
|
||||||
relativeToEphemeralSubviewNamed:@"track-view"];
|
relativeToEphemeralSubviewNamed:@"track-view"];
|
||||||
|
|
||||||
if (knobView)
|
if (knobView)
|
||||||
[knobView setBackgroundColor:[self currentValueForThemeAttribute:"knob-color"]];
|
[knobView setBackgroundColor:[self currentValueForThemeAttribute:"knob-color"]];
|
||||||
}
|
}
|
||||||
@@ -319,7 +320,7 @@ CPCircularSlider = 1;
|
|||||||
|
|
||||||
var minValue = [self minValue];
|
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
|
else
|
||||||
{
|
{
|
||||||
@@ -338,43 +339,44 @@ CPCircularSlider = 1;
|
|||||||
{
|
{
|
||||||
var bounds = [self bounds],
|
var bounds = [self bounds],
|
||||||
knobRect = [self knobRectForBounds:_CGRectMakeCopy(bounds)];
|
knobRect = [self knobRectForBounds:_CGRectMakeCopy(bounds)];
|
||||||
|
|
||||||
if (_CGRectContainsPoint(knobRect, aPoint))
|
if (_CGRectContainsPoint(knobRect, aPoint))
|
||||||
_dragOffset = _CGSizeMake(_CGRectGetMidX(knobRect) - aPoint.x, _CGRectGetMidY(knobRect) - aPoint.y);
|
_dragOffset = _CGSizeMake(_CGRectGetMidX(knobRect) - aPoint.x, _CGRectGetMidY(knobRect) - aPoint.y);
|
||||||
else
|
|
||||||
|
else
|
||||||
{
|
{
|
||||||
var trackRect = [self trackRectForBounds:bounds];
|
var trackRect = [self trackRectForBounds:bounds];
|
||||||
|
|
||||||
if (trackRect && _CGRectContainsPoint(trackRect, aPoint))
|
if (trackRect && _CGRectContainsPoint(trackRect, aPoint))
|
||||||
{
|
{
|
||||||
_dragOffset = _CGSizeMakeZero();
|
_dragOffset = _CGSizeMakeZero();
|
||||||
|
|
||||||
[self setObjectValue:[self _valueAtPoint:aPoint]];
|
[self setObjectValue:[self _valueAtPoint:aPoint]];
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
[self setHighlighted:YES];
|
[self setHighlighted:YES];
|
||||||
|
|
||||||
[self setNeedsLayout];
|
[self setNeedsLayout];
|
||||||
[self setNeedsDisplay:YES];
|
[self setNeedsDisplay:YES];
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint
|
- (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint
|
||||||
{
|
{
|
||||||
[self setObjectValue:[self _valueAtPoint:_CGPointMake(aPoint.x + _dragOffset.width, aPoint.y + _dragOffset.height)]];
|
[self setObjectValue:[self _valueAtPoint:_CGPointMake(aPoint.x + _dragOffset.width, aPoint.y + _dragOffset.height)]];
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)stopTracking:(CGPoint)lastPoint at:(CGPoint)aPoint mouseIsUp:(BOOL)mouseIsUp
|
- (void)stopTracking:(CGPoint)lastPoint at:(CGPoint)aPoint mouseIsUp:(BOOL)mouseIsUp
|
||||||
{
|
{
|
||||||
[self setHighlighted:NO];
|
[self setHighlighted:NO];
|
||||||
|
|
||||||
if ([_target respondsToSelector:@selector(sliderDidFinish:)])
|
if ([_target respondsToSelector:@selector(sliderDidFinish:)])
|
||||||
[_target sliderDidFinish:self];
|
[_target sliderDidFinish:self];
|
||||||
|
|
||||||
@@ -390,22 +392,10 @@ CPCircularSlider = 1;
|
|||||||
{
|
{
|
||||||
if (flag)
|
if (flag)
|
||||||
_sendActionOn |= CPLeftMouseDraggedMask;
|
_sendActionOn |= CPLeftMouseDraggedMask;
|
||||||
else
|
else
|
||||||
_sendActionOn &= ~CPLeftMouseDraggedMask;
|
_sendActionOn &= ~CPLeftMouseDraggedMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)takeValueFromKeyPath:(CPString)aKeyPath ofObjects:(CPArray)objects
|
|
||||||
{
|
|
||||||
var count = objects.length,
|
|
||||||
value = [objects[0] valueForKeyPath:aKeyPath];
|
|
||||||
|
|
||||||
[self setObjectValue:value];
|
|
||||||
|
|
||||||
while (count-- > 1)
|
|
||||||
if (value !== ([objects[count] valueForKeyPath:aKeyPath]))
|
|
||||||
return [self setFloatValue:1.0];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
var CPSliderMinValueKey = "CPSliderMinValueKey",
|
var CPSliderMinValueKey = "CPSliderMinValueKey",
|
||||||
@@ -452,14 +442,14 @@ var CPSliderMinValueKey = "CPSliderMinValueKey",
|
|||||||
- (id)value
|
- (id)value
|
||||||
{
|
{
|
||||||
CPLog.warn("[CPSlider value] is deprecated, use doubleValue or objectValue instead.");
|
CPLog.warn("[CPSlider value] is deprecated, use doubleValue or objectValue instead.");
|
||||||
|
|
||||||
return [self doubleValue];
|
return [self doubleValue];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setValue:(id)aValue
|
- (void)setValue:(id)aValue
|
||||||
{
|
{
|
||||||
CPLog.warn("[CPSlider setValue:] is deprecated, use setDoubleValue: or setObjectValue: instead.");
|
CPLog.warn("[CPSlider setValue:] is deprecated, use setDoubleValue: or setObjectValue: instead.");
|
||||||
|
|
||||||
[self setObjectValue:aValue];
|
[self setObjectValue:aValue];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+167
-103
@@ -20,10 +20,8 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@import "CPView.j"
|
|
||||||
@import "CPColorPicker.j"
|
@import "CPColorPicker.j"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ignore
|
@ignore
|
||||||
*/
|
*/
|
||||||
@@ -47,15 +45,16 @@
|
|||||||
CPTextField _saturationLabel;
|
CPTextField _saturationLabel;
|
||||||
CPTextField _brightnessLabel;
|
CPTextField _brightnessLabel;
|
||||||
CPTextField _hexLabel;
|
CPTextField _hexLabel;
|
||||||
CPTextField _hexValue;
|
|
||||||
|
|
||||||
CPTextField _hexValue;
|
#if PLATFORM(DOM)
|
||||||
CPTextField _redValue;
|
DOMElement _redValue;
|
||||||
CPTextField _greenValue;
|
DOMElement _greenValue;
|
||||||
CPTextField _blueValue;
|
DOMElement _blueValue;
|
||||||
CPTextField _hueValue;
|
DOMElement _hueValue;
|
||||||
CPTextField _saturationValue;
|
DOMElement _saturationValue;
|
||||||
CPTextField _brightnessValue;
|
DOMElement _brightnessValue;
|
||||||
|
DOMElement _hexValue;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithPickerMask:(int)mask colorPanel:(CPColorPanel)owningColorPanel
|
- (id)initWithPickerMask:(int)mask colorPanel:(CPColorPanel)owningColorPanel
|
||||||
@@ -85,13 +84,73 @@
|
|||||||
[_redSlider setAction: @selector(sliderChanged:)];
|
[_redSlider setAction: @selector(sliderChanged:)];
|
||||||
[_redSlider setAutoresizingMask: CPViewWidthSizable];
|
[_redSlider setAutoresizingMask: CPViewWidthSizable];
|
||||||
|
|
||||||
// red value input box
|
#if PLATFORM(DOM)
|
||||||
_redValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 30, 45, 29)];
|
var updateFunction = function(aDOMEvent)
|
||||||
[_redValue setAutoresizingMask: CPViewMinXMargin];
|
{
|
||||||
[_redValue setEditable: YES];
|
if(isNaN(this.value))
|
||||||
[_redValue setBezeled: YES];
|
return;
|
||||||
[_redValue setDelegate: self];
|
|
||||||
[_contentView addSubview: _redValue];
|
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 = [[CPTextField alloc] initWithFrame: CPRectMake(0, 58, 15, 20)];
|
||||||
[_greenLabel setStringValue: "G"];
|
[_greenLabel setStringValue: "G"];
|
||||||
@@ -104,13 +163,17 @@
|
|||||||
[_greenSlider setAction: @selector(sliderChanged:)];
|
[_greenSlider setAction: @selector(sliderChanged:)];
|
||||||
[_greenSlider setAutoresizingMask: CPViewWidthSizable];
|
[_greenSlider setAutoresizingMask: CPViewWidthSizable];
|
||||||
|
|
||||||
// green value input box
|
#if PLATFORM(DOM)
|
||||||
_greenValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 53, 45, 29)];
|
//green value input box
|
||||||
[_greenValue setAutoresizingMask: CPViewMinXMargin];
|
var greenValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 58, 45, 20)];
|
||||||
[_greenValue setEditable: YES];
|
[greenValue setAutoresizingMask: CPViewMinXMargin];
|
||||||
[_greenValue setBezeled: YES];
|
|
||||||
[_greenValue setDelegate: self];
|
_greenValue = _redValue.cloneNode(false);
|
||||||
[_contentView addSubview: _greenValue];
|
_greenValue.onchange = updateFunction;
|
||||||
|
|
||||||
|
greenValue._DOMElement.appendChild(_greenValue);
|
||||||
|
[_contentView addSubview: greenValue];
|
||||||
|
#endif
|
||||||
|
|
||||||
_blueLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 81, 15, 20)];
|
_blueLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 81, 15, 20)];
|
||||||
[_blueLabel setStringValue: "B"];
|
[_blueLabel setStringValue: "B"];
|
||||||
@@ -123,14 +186,17 @@
|
|||||||
[_blueSlider setAction: @selector(sliderChanged:)];
|
[_blueSlider setAction: @selector(sliderChanged:)];
|
||||||
[_blueSlider setAutoresizingMask: CPViewWidthSizable];
|
[_blueSlider setAutoresizingMask: CPViewWidthSizable];
|
||||||
|
|
||||||
// blue value input box
|
#if PLATFORM(DOM)
|
||||||
_blueValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 76, 45, 29)];
|
//blue value input box
|
||||||
[_blueValue setAutoresizingMask: CPViewMinXMargin];
|
var blueValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 81, 45, 20)];
|
||||||
[_blueValue setEditable: YES];
|
[blueValue setAutoresizingMask: CPViewMinXMargin];
|
||||||
[_blueValue setBezeled: YES];
|
|
||||||
[_blueValue setDelegate: self];
|
|
||||||
[_contentView addSubview: _blueValue];
|
|
||||||
|
|
||||||
|
_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 = [[CPTextField alloc] initWithFrame: CPRectMake(0, 120, 190, 20)];
|
||||||
[_hsbLabel setStringValue: "Hue, Saturation, Brightness"];
|
[_hsbLabel setStringValue: "Hue, Saturation, Brightness"];
|
||||||
[_hsbLabel setTextColor:[CPColor blackColor]];
|
[_hsbLabel setTextColor:[CPColor blackColor]];
|
||||||
@@ -146,14 +212,17 @@
|
|||||||
[_hueSlider setAction: @selector(sliderChanged:)];
|
[_hueSlider setAction: @selector(sliderChanged:)];
|
||||||
[_hueSlider setAutoresizingMask: CPViewWidthSizable];
|
[_hueSlider setAutoresizingMask: CPViewWidthSizable];
|
||||||
|
|
||||||
// hue value input box
|
#if PLATFORM(DOM)
|
||||||
_hueValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 140, 45, 29)];
|
//red value input box
|
||||||
[_hueValue setAutoresizingMask: CPViewMinXMargin];
|
var hueValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 145, 45, 20)];
|
||||||
[_hueValue setEditable: YES];
|
[hueValue setAutoresizingMask: CPViewMinXMargin];
|
||||||
[_hueValue setBezeled: YES];
|
|
||||||
[_hueValue setDelegate: self];
|
|
||||||
[_contentView addSubview: _hueValue];
|
|
||||||
|
|
||||||
|
_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 = [[CPTextField alloc] initWithFrame: CPRectMake(0, 168, 15, 20)];
|
||||||
[_saturationLabel setStringValue: "S"];
|
[_saturationLabel setStringValue: "S"];
|
||||||
[_saturationLabel setTextColor:[CPColor blackColor]];
|
[_saturationLabel setTextColor:[CPColor blackColor]];
|
||||||
@@ -165,14 +234,17 @@
|
|||||||
[_saturationSlider setAction: @selector(sliderChanged:)];
|
[_saturationSlider setAction: @selector(sliderChanged:)];
|
||||||
[_saturationSlider setAutoresizingMask: CPViewWidthSizable];
|
[_saturationSlider setAutoresizingMask: CPViewWidthSizable];
|
||||||
|
|
||||||
// saturation value input box
|
#if PLATFORM(DOM)
|
||||||
_saturationValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 163, 45, 29)];
|
//green value input box
|
||||||
[_saturationValue setAutoresizingMask: CPViewMinXMargin];
|
var saturationValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 168, 45, 20)];
|
||||||
[_saturationValue setEditable: YES];
|
[saturationValue setAutoresizingMask: CPViewMinXMargin];
|
||||||
[_saturationValue setBezeled: YES];
|
|
||||||
[_saturationValue setDelegate: self];
|
|
||||||
[_contentView addSubview: _saturationValue];
|
|
||||||
|
|
||||||
|
_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 = [[CPTextField alloc] initWithFrame: CPRectMake(0, 191, 15, 20)];
|
||||||
[_brightnessLabel setStringValue: "B"];
|
[_brightnessLabel setStringValue: "B"];
|
||||||
[_brightnessLabel setTextColor:[CPColor blackColor]];
|
[_brightnessLabel setTextColor:[CPColor blackColor]];
|
||||||
@@ -184,24 +256,51 @@
|
|||||||
[_brightnessSlider setAction: @selector(sliderChanged:)];
|
[_brightnessSlider setAction: @selector(sliderChanged:)];
|
||||||
[_brightnessSlider setAutoresizingMask: CPViewWidthSizable];
|
[_brightnessSlider setAutoresizingMask: CPViewWidthSizable];
|
||||||
|
|
||||||
// brightness value input box
|
#if PLATFORM(DOM)
|
||||||
_brightnessValue = [[CPTextField alloc] initWithFrame: CGRectMake(aFrame.size.width - 45, 186, 45, 29)];
|
//blue value input box
|
||||||
[_brightnessValue setAutoresizingMask: CPViewMinXMargin];
|
var brightnessValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 191, 45, 20)];
|
||||||
[_brightnessValue setEditable: YES];
|
[brightnessValue setAutoresizingMask: CPViewMinXMargin];
|
||||||
[_brightnessValue setBezeled: YES];
|
|
||||||
[_brightnessValue setDelegate: self];
|
|
||||||
[_contentView addSubview: _brightnessValue];
|
|
||||||
|
|
||||||
|
_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 = [[CPTextField alloc] initWithFrame: CPRectMake(0, 230, 30, 20)];
|
||||||
[_hexLabel setStringValue: "Hex"];
|
[_hexLabel setStringValue: "Hex"];
|
||||||
[_hexLabel setTextColor:[CPColor blackColor]];
|
[_hexLabel setTextColor:[CPColor blackColor]];
|
||||||
|
|
||||||
|
#if PLATFORM(DOM)
|
||||||
//hex input box
|
//hex input box
|
||||||
_hexValue = [[CPTextField alloc] initWithFrame: CGRectMake(32, 225, 80, 29)];
|
_hexValue = _redValue.cloneNode(false);
|
||||||
[_hexValue setEditable: YES];
|
_hexValue.style.top = "228px";
|
||||||
[_hexValue setBezeled: YES];
|
_hexValue.style.width = "80px";
|
||||||
[_hexValue setDelegate: self];
|
_hexValue.style.left = "35px";
|
||||||
[_contentView addSubview: _hexValue];
|
_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: _rgbLabel];
|
||||||
[_contentView addSubview: _redLabel];
|
[_contentView addSubview: _redLabel];
|
||||||
@@ -293,7 +392,9 @@
|
|||||||
|
|
||||||
- (void)updateHex:(CPColor)aColor
|
- (void)updateHex:(CPColor)aColor
|
||||||
{
|
{
|
||||||
[_hexValue setStringValue:[aColor hexString]];
|
#if PLATFORM(DOM)
|
||||||
|
_hexValue.value = [aColor hexString];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateRGBSliders:(CPColor)aColor
|
- (void)updateRGBSliders:(CPColor)aColor
|
||||||
@@ -307,13 +408,15 @@
|
|||||||
|
|
||||||
- (void)updateLabels
|
- (void)updateLabels
|
||||||
{
|
{
|
||||||
[_hueValue setStringValue: ROUND([_hueSlider floatValue])];
|
#if PLATFORM(DOM)
|
||||||
[_saturationValue setStringValue: ROUND([_saturationSlider floatValue])];
|
_hueValue.value = ROUND([_hueSlider floatValue]);
|
||||||
[_brightnessValue setStringValue: ROUND([_brightnessSlider floatValue])];
|
_saturationValue.value = ROUND([_saturationSlider floatValue]);
|
||||||
|
_brightnessValue.value = ROUND([_brightnessSlider floatValue]);
|
||||||
|
|
||||||
[_redValue setStringValue: ROUND([_redSlider floatValue] * 255)];
|
_redValue.value = ROUND([_redSlider floatValue] * 255);
|
||||||
[_greenValue setStringValue: ROUND([_greenSlider floatValue] * 255)];
|
_greenValue.value = ROUND([_greenSlider floatValue] * 255);
|
||||||
[_blueValue setStringValue: ROUND([_blueSlider floatValue] * 255)];
|
_blueValue.value = ROUND([_blueSlider floatValue] * 255);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CPImage)provideNewButtonImage
|
- (CPImage)provideNewButtonImage
|
||||||
@@ -326,43 +429,4 @@
|
|||||||
return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:CPColorPicker] pathForResource:"slider_button_h.png"] size:CGSizeMake(32, 32)];
|
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
|
@end
|
||||||
|
|||||||
+32
-54
@@ -24,6 +24,10 @@
|
|||||||
@import "CPImage.j"
|
@import "CPImage.j"
|
||||||
@import "CPView.j"
|
@import "CPView.j"
|
||||||
|
|
||||||
|
#include "CoreGraphics/CGGeometry.h"
|
||||||
|
#include "Platform/Platform.h"
|
||||||
|
#include "Platform/DOM/CPDOMDisplayServer.h"
|
||||||
|
|
||||||
|
|
||||||
CPSplitViewDidResizeSubviewsNotification = @"CPSplitViewDidResizeSubviewsNotification";
|
CPSplitViewDidResizeSubviewsNotification = @"CPSplitViewDidResizeSubviewsNotification";
|
||||||
CPSplitViewWillResizeSubviewsNotification = @"CPSplitViewWillResizeSubviewsNotification";
|
CPSplitViewWillResizeSubviewsNotification = @"CPSplitViewWillResizeSubviewsNotification";
|
||||||
@@ -43,7 +47,6 @@ var CPSplitViewHorizontalImage = nil,
|
|||||||
|
|
||||||
int _currentDivider;
|
int _currentDivider;
|
||||||
float _initialOffset;
|
float _initialOffset;
|
||||||
float _preCollapsePosition;
|
|
||||||
|
|
||||||
CPString _originComponent;
|
CPString _originComponent;
|
||||||
CPString _sizeComponent;
|
CPString _sizeComponent;
|
||||||
@@ -57,17 +60,6 @@ var CPSplitViewHorizontalImage = nil,
|
|||||||
CPArray _buttonBars;
|
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
|
@ignore
|
||||||
*/
|
*/
|
||||||
@@ -98,7 +90,7 @@ var CPSplitViewHorizontalImage = nil,
|
|||||||
|
|
||||||
- (float)dividerThickness
|
- (float)dividerThickness
|
||||||
{
|
{
|
||||||
return [self currentValueForThemeAttribute:[self isPaneSplitter] ? @"pane-divider-thickness" : @"divider-thickness"];
|
return _isPaneSplitter ? 1.0 : 10.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)isVertical
|
- (BOOL)isVertical
|
||||||
@@ -159,8 +151,8 @@ var CPSplitViewHorizontalImage = nil,
|
|||||||
|
|
||||||
_isPaneSplitter = shouldBePaneSplitter;
|
_isPaneSplitter = shouldBePaneSplitter;
|
||||||
|
|
||||||
if (_DOMDividerElements[_drawingDivider])
|
if(_DOMDividerElements[_drawingDivider])
|
||||||
[self _setupDOMDivider];
|
[self _setupDOMDivider]
|
||||||
|
|
||||||
// The divider changes size when pane splitter mode is toggled, so the
|
// The divider changes size when pane splitter mode is toggled, so the
|
||||||
// subviews need to change size too.
|
// subviews need to change size too.
|
||||||
@@ -193,8 +185,9 @@ var CPSplitViewHorizontalImage = nil,
|
|||||||
|
|
||||||
- (CGRect)effectiveRectOfDividerAtIndex:(int)aDivider
|
- (CGRect)effectiveRectOfDividerAtIndex:(int)aDivider
|
||||||
{
|
{
|
||||||
var realRect = [self rectOfDividerAtIndex:aDivider],
|
var realRect = [self rectOfDividerAtIndex:aDivider];
|
||||||
padding = 2;
|
|
||||||
|
var padding = 2;
|
||||||
|
|
||||||
realRect.size[_sizeComponent] += padding * 2;
|
realRect.size[_sizeComponent] += padding * 2;
|
||||||
realRect.origin[_originComponent] -= padding;
|
realRect.origin[_originComponent] -= padding;
|
||||||
@@ -224,9 +217,10 @@ var CPSplitViewHorizontalImage = nil,
|
|||||||
_DOMDividerElements[_drawingDivider].style.backgroundRepeat = "repeat";
|
_DOMDividerElements[_drawingDivider].style.backgroundRepeat = "repeat";
|
||||||
|
|
||||||
CPDOMDisplayServerAppendChild(_DOMElement, _DOMDividerElements[_drawingDivider]);
|
CPDOMDisplayServerAppendChild(_DOMElement, _DOMDividerElements[_drawingDivider]);
|
||||||
|
|
||||||
|
[self _setupDOMDivider];
|
||||||
}
|
}
|
||||||
|
|
||||||
[self _setupDOMDivider];
|
|
||||||
CPDOMDisplayServerSetStyleLeftTop(_DOMDividerElements[_drawingDivider], NULL, _CGRectGetMinX(aRect), _CGRectGetMinY(aRect));
|
CPDOMDisplayServerSetStyleLeftTop(_DOMDividerElements[_drawingDivider], NULL, _CGRectGetMinX(aRect), _CGRectGetMinY(aRect));
|
||||||
CPDOMDisplayServerSetStyleSize(_DOMDividerElements[_drawingDivider], _CGRectGetWidth(aRect), _CGRectGetHeight(aRect));
|
CPDOMDisplayServerSetStyleSize(_DOMDividerElements[_drawingDivider], _CGRectGetWidth(aRect), _CGRectGetHeight(aRect));
|
||||||
#endif
|
#endif
|
||||||
@@ -236,7 +230,7 @@ var CPSplitViewHorizontalImage = nil,
|
|||||||
{
|
{
|
||||||
if (_isPaneSplitter)
|
if (_isPaneSplitter)
|
||||||
{
|
{
|
||||||
_DOMDividerElements[_drawingDivider].style.backgroundColor = [[self currentValueForThemeAttribute:@"pane-divider-color"] cssString];
|
_DOMDividerElements[_drawingDivider].style.backgroundColor = "#A5A5A5";
|
||||||
_DOMDividerElements[_drawingDivider].style.backgroundImage = "";
|
_DOMDividerElements[_drawingDivider].style.backgroundImage = "";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -300,7 +294,7 @@ var CPSplitViewHorizontalImage = nil,
|
|||||||
if ([_delegate respondsToSelector:@selector(splitView:additionalEffectiveRectOfDividerAtIndex:)])
|
if ([_delegate respondsToSelector:@selector(splitView:additionalEffectiveRectOfDividerAtIndex:)])
|
||||||
additionalRect = [_delegate splitView:self additionalEffectiveRectOfDividerAtIndex:anIndex];
|
additionalRect = [_delegate splitView:self additionalEffectiveRectOfDividerAtIndex:anIndex];
|
||||||
|
|
||||||
return CGRectContainsPoint(effectiveRect, aPoint) ||
|
return CGRectContainsPoint(effectiveRect, aPoint) ||
|
||||||
(additionalRect && CGRectContainsPoint(additionalRect, aPoint)) ||
|
(additionalRect && CGRectContainsPoint(additionalRect, aPoint)) ||
|
||||||
(buttonBarRect && CGRectContainsPoint(buttonBarRect, aPoint));
|
(buttonBarRect && CGRectContainsPoint(buttonBarRect, aPoint));
|
||||||
}
|
}
|
||||||
@@ -310,9 +304,9 @@ var CPSplitViewHorizontalImage = nil,
|
|||||||
if ([self isHidden] || ![self hitTests] || !CGRectContainsPoint([self frame], aPoint))
|
if ([self isHidden] || ![self hitTests] || !CGRectContainsPoint([self frame], aPoint))
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
var point = [self convertPoint:aPoint fromView:[self superview]],
|
var point = [self convertPoint:aPoint fromView:[self superview]];
|
||||||
count = [_subviews count] - 1;
|
|
||||||
|
|
||||||
|
var count = [_subviews count] - 1;
|
||||||
for (var i = 0; i < count; i++)
|
for (var i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
if ([self cursorAtPoint:point hitDividerAtIndex:i])
|
if ([self cursorAtPoint:point hitDividerAtIndex:i])
|
||||||
@@ -365,14 +359,14 @@ var CPSplitViewHorizontalImage = nil,
|
|||||||
if ([_delegate splitView:self canCollapseSubview:_subviews[i]] && [_delegate splitView:self shouldCollapseSubview:_subviews[i] forDoubleClickOnDividerAtIndex:i])
|
if ([_delegate splitView:self canCollapseSubview:_subviews[i]] && [_delegate splitView:self shouldCollapseSubview:_subviews[i] forDoubleClickOnDividerAtIndex:i])
|
||||||
{
|
{
|
||||||
if ([self isSubviewCollapsed:_subviews[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
|
else
|
||||||
[self setPosition:minPosition ofDividerAtIndex:i];
|
[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]])
|
if ([self isSubviewCollapsed:_subviews[i+1]])
|
||||||
[self setPosition:_preCollapsePosition ? _preCollapsePosition : (minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i];
|
[self setPosition:(minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i];
|
||||||
else
|
else
|
||||||
[self setPosition:maxPosition ofDividerAtIndex:i];
|
[self setPosition:maxPosition ofDividerAtIndex:i];
|
||||||
}
|
}
|
||||||
@@ -451,19 +445,11 @@ var CPSplitViewHorizontalImage = nil,
|
|||||||
if (_currentDivider === i || (_currentDivider == CPNotFound && [self cursorAtPoint:point hitDividerAtIndex:i]))
|
if (_currentDivider === i || (_currentDivider == CPNotFound && [self cursorAtPoint:point hitDividerAtIndex:i]))
|
||||||
{
|
{
|
||||||
var frame = [_subviews[i] frame],
|
var frame = [_subviews[i] frame],
|
||||||
size = frame.size[_sizeComponent],
|
startPosition = frame.origin[_originComponent] + frame.size[_sizeComponent],
|
||||||
startPosition = frame.origin[_originComponent] + size,
|
canShrink = [self _realPositionForPosition:startPosition-1 ofDividerAtIndex:i] < startPosition,
|
||||||
canShrink = [self _realPositionForPosition:startPosition - 1 ofDividerAtIndex:i] < startPosition,
|
canGrow = [self _realPositionForPosition:startPosition+1 ofDividerAtIndex:i] > startPosition,
|
||||||
canGrow = [self _realPositionForPosition:startPosition + 1 ofDividerAtIndex:i] > startPosition,
|
|
||||||
cursor = [CPCursor arrowCursor];
|
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)
|
if (_isVertical && canShrink && canGrow)
|
||||||
cursor = [CPCursor resizeLeftRightCursor];
|
cursor = [CPCursor resizeLeftRightCursor];
|
||||||
else if (_isVertical && canShrink)
|
else if (_isVertical && canShrink)
|
||||||
@@ -518,10 +504,10 @@ var CPSplitViewHorizontalImage = nil,
|
|||||||
actualMax = proposedMax,
|
actualMax = proposedMax,
|
||||||
actualMin = proposedMin;
|
actualMin = proposedMin;
|
||||||
|
|
||||||
if ([_delegate respondsToSelector:@selector(splitView:constrainMinCoordinate:ofSubviewAt:)])
|
if([_delegate respondsToSelector:@selector(splitView:constrainMinCoordinate:ofSubviewAt:)])
|
||||||
actualMin = [_delegate splitView:self constrainMinCoordinate:proposedMin ofSubviewAt:dividerIndex];
|
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];
|
actualMax = [_delegate splitView:self constrainMaxCoordinate:proposedMax ofSubviewAt:dividerIndex];
|
||||||
|
|
||||||
var viewA = _subviews[dividerIndex],
|
var viewA = _subviews[dividerIndex],
|
||||||
@@ -546,18 +532,10 @@ var CPSplitViewHorizontalImage = nil,
|
|||||||
viewB = _subviews[dividerIndex + 1],
|
viewB = _subviews[dividerIndex + 1],
|
||||||
frameB = [viewB frame];
|
frameB = [viewB frame];
|
||||||
|
|
||||||
_preCollapsePosition = 0;
|
|
||||||
|
|
||||||
var preSize = frameA.size[_sizeComponent];
|
|
||||||
frameA.size[_sizeComponent] = realPosition - frameA.origin[_originComponent];
|
frameA.size[_sizeComponent] = realPosition - frameA.origin[_originComponent];
|
||||||
if (preSize !== 0 && frameA.size[_sizeComponent] === 0)
|
|
||||||
_preCollapsePosition = preSize;
|
|
||||||
[_subviews[dividerIndex] setFrame:frameA];
|
[_subviews[dividerIndex] setFrame:frameA];
|
||||||
|
|
||||||
preSize = frameB.size[_sizeComponent];
|
|
||||||
frameB.size[_sizeComponent] = frameB.origin[_originComponent] + frameB.size[_sizeComponent] - realPosition - [self dividerThickness];
|
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];
|
frameB.origin[_originComponent] = realPosition + [self dividerThickness];
|
||||||
[_subviews[dividerIndex + 1] setFrame:frameB];
|
[_subviews[dividerIndex + 1] setFrame:frameB];
|
||||||
|
|
||||||
@@ -612,8 +590,8 @@ var CPSplitViewHorizontalImage = nil,
|
|||||||
|
|
||||||
var nonSizableSpace = totalSizableSpace ? bounds.size[_sizeComponent] - totalSizableSpace : 0,
|
var nonSizableSpace = totalSizableSpace ? bounds.size[_sizeComponent] - totalSizableSpace : 0,
|
||||||
remainingFlexibleSpace = bounds.size[_sizeComponent] - oldSize[_sizeComponent],
|
remainingFlexibleSpace = bounds.size[_sizeComponent] - oldSize[_sizeComponent],
|
||||||
oldDimension = (oldSize[_sizeComponent] - totalDividers * dividerThickness - nonSizableSpace),
|
oldDimension = (oldSize[_sizeComponent]- totalDividers*dividerThickness - nonSizableSpace),
|
||||||
ratio = oldDimension <= 0 ? 0 : (bounds.size[_sizeComponent] - totalDividers * dividerThickness - nonSizableSpace) / oldDimension;
|
ratio = oldDimension <= 0 ? 0 : (bounds.size[_sizeComponent] - totalDividers*dividerThickness - nonSizableSpace) / oldDimension;
|
||||||
|
|
||||||
for (index = 0; index < count; ++index)
|
for (index = 0; index < count; ++index)
|
||||||
{
|
{
|
||||||
@@ -664,14 +642,14 @@ var CPSplitViewHorizontalImage = nil,
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
Set the button bar who's resize control should act as a control for this splitview.
|
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.
|
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
|
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
|
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.
|
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.
|
parameters of the button bar, and will override any currently set values.
|
||||||
*/
|
*/
|
||||||
- (void)setButtonBar:(CPButtonBar)aButtonBar forDividerAtIndex:(unsigned)dividerIndex
|
- (void)setButtonBar:(CPButtonBar)aButtonBar forDividerAtIndex:(unsigned)dividerIndex
|
||||||
@@ -692,7 +670,7 @@ var CPSplitViewHorizontalImage = nil,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (view !== self)
|
if (view !== self)
|
||||||
[CPException raise:CPInvalidArgumentException
|
[CPException raise:CPInvalidArgumentException
|
||||||
reason:@"CPSplitView button bar must be a subview of the split view."];
|
reason:@"CPSplitView button bar must be a subview of the split view."];
|
||||||
|
|
||||||
var viewIndex = [[self subviews] indexOfObject:subview];
|
var viewIndex = [[self subviews] indexOfObject:subview];
|
||||||
@@ -700,7 +678,7 @@ var CPSplitViewHorizontalImage = nil,
|
|||||||
[aButtonBar setHasResizeControl:YES];
|
[aButtonBar setHasResizeControl:YES];
|
||||||
[aButtonBar setResizeControlIsLeftAligned:dividerIndex < viewIndex];
|
[aButtonBar setResizeControlIsLeftAligned:dividerIndex < viewIndex];
|
||||||
|
|
||||||
_buttonBars[dividerIndex] = aButtonBar;
|
_buttonBars[dividerIndex] = aButtonBar;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_postNotificationWillResize
|
- (void)_postNotificationWillResize
|
||||||
@@ -737,7 +715,7 @@ var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
|
|||||||
_DOMDividerElements = [];
|
_DOMDividerElements = [];
|
||||||
|
|
||||||
_buttonBars = [aCoder decodeObjectForKey:CPSplitViewButtonBarsKey] || [];
|
_buttonBars = [aCoder decodeObjectForKey:CPSplitViewButtonBarsKey] || [];
|
||||||
|
|
||||||
_delegate = [aCoder decodeObjectForKey:CPSplitViewDelegateKey];
|
_delegate = [aCoder decodeObjectForKey:CPSplitViewDelegateKey];
|
||||||
|
|
||||||
_isPaneSplitter = [aCoder decodeBoolForKey:CPSplitViewIsPaneSplitterKey];
|
_isPaneSplitter = [aCoder decodeBoolForKey:CPSplitViewIsPaneSplitterKey];
|
||||||
|
|||||||
@@ -25,20 +25,8 @@
|
|||||||
@import "CPPlatformString.j"
|
@import "CPPlatformString.j"
|
||||||
|
|
||||||
|
|
||||||
var CPStringSizeWithFontInWidthCache = {};
|
|
||||||
|
|
||||||
CPStringSizeCachingEnabled = YES;
|
|
||||||
|
|
||||||
@implementation CPString (CPStringDrawing)
|
@implementation CPString (CPStringDrawing)
|
||||||
|
|
||||||
/*!
|
|
||||||
Returns a dictionary with the items "ascender", "descender", "lineHeight"
|
|
||||||
*/
|
|
||||||
+ (CPDictionary)metricsOfFont:(CPFont)aFont
|
|
||||||
{
|
|
||||||
return [CPPlatformString metricsOfFont:aFont];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns the string
|
Returns the string
|
||||||
*/
|
*/
|
||||||
@@ -54,19 +42,7 @@ CPStringSizeCachingEnabled = YES;
|
|||||||
|
|
||||||
- (CGSize)sizeWithFont:(CPFont)aFont inWidth:(float)aWidth
|
- (CGSize)sizeWithFont:(CPFont)aFont inWidth:(float)aWidth
|
||||||
{
|
{
|
||||||
if (!CPStringSizeCachingEnabled)
|
return [CPPlatformString sizeOfString:self withFont:aFont forWidth:aWidth];
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
+553
-202
@@ -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 "CPTabViewItem.j"
|
||||||
@import "CPView.j"
|
@import "CPView.j"
|
||||||
|
|
||||||
|
#include "CoreGraphics/CGGeometry.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Places tabs on top with a bezeled border.
|
Places tabs on top with a bezeled border.
|
||||||
@global
|
@global
|
||||||
@@ -10,7 +34,7 @@
|
|||||||
*/
|
*/
|
||||||
CPTopTabsBezelBorder = 0;
|
CPTopTabsBezelBorder = 0;
|
||||||
//CPLeftTabsBezelBorder = 1;
|
//CPLeftTabsBezelBorder = 1;
|
||||||
CPBottomTabsBezelBorder = 2;
|
//CPBottomTabsBezelBorder = 2;
|
||||||
//CPRightTabsBezelBorder = 3;
|
//CPRightTabsBezelBorder = 3;
|
||||||
/*
|
/*
|
||||||
Displays no tabs and has a bezeled border.
|
Displays no tabs and has a bezeled border.
|
||||||
@@ -31,55 +55,173 @@ CPNoTabsLineBorder = 5;
|
|||||||
*/
|
*/
|
||||||
CPNoTabsNoBorder = 6;
|
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,
|
var CPTabViewDidSelectTabViewItemSelector = 1,
|
||||||
CPTabViewShouldSelectTabViewItemSelector = 2,
|
CPTabViewShouldSelectTabViewItemSelector = 2,
|
||||||
CPTabViewWillSelectTabViewItemSelector = 4,
|
CPTabViewWillSelectTabViewItemSelector = 4,
|
||||||
CPTabViewDidChangeNumberOfTabViewItemsSelector = 8;
|
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
|
@implementation CPTabView : CPView
|
||||||
{
|
{
|
||||||
CPArray items;
|
CPView _labelsView;
|
||||||
|
CPView _backgroundView;
|
||||||
|
CPView _separatorView;
|
||||||
|
|
||||||
|
CPView _auxiliaryView;
|
||||||
|
CPView _contentView;
|
||||||
|
|
||||||
|
CPArray _tabViewItems;
|
||||||
|
CPTabViewItem _selectedTabViewItem;
|
||||||
|
|
||||||
CPSegmentedControl tabs;
|
CPTabViewType _tabViewType;
|
||||||
CPBox box;
|
|
||||||
|
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;
|
bezelBorderLeftImage,
|
||||||
unsigned delegateSelectors;
|
bezerBorderImage,
|
||||||
|
bezelBorderRightImage
|
||||||
|
]]];
|
||||||
|
|
||||||
|
CPTabViewBezelBorderColor = [CPColor colorWithPatternImage:bezerBorderImage];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@ignore
|
||||||
|
*/
|
||||||
|
+ (CPColor)bezelBorderColor
|
||||||
|
{
|
||||||
|
return CPTabViewBezelBorderColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithFrame:(CGRect)aFrame
|
- (id)initWithFrame:(CGRect)aFrame
|
||||||
{
|
{
|
||||||
self = [super initWithFrame:aFrame];
|
self = [super initWithFrame:aFrame];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
items = [CPArray array];
|
_tabViewType = CPTopTabsBezelBorder;
|
||||||
|
_tabViewItems = [];
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
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
|
// Adding and Removing Tabs
|
||||||
/*!
|
/*!
|
||||||
Adds a CPTabViewItem to the tab view.
|
Adds a CPTabViewItem to the tab view.
|
||||||
@@ -87,7 +229,7 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
|
|||||||
*/
|
*/
|
||||||
- (void)addTabViewItem:(CPTabViewItem)aTabViewItem
|
- (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
|
- (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];
|
if (_delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
|
||||||
[self _repositionTabs];
|
[_delegate tabViewDidChangeNumberOfTabViewItems:self];
|
||||||
|
|
||||||
if (delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
|
|
||||||
[delegate tabViewDidChangeNumberOfTabViewItems:self];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -113,19 +262,16 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
|
|||||||
*/
|
*/
|
||||||
- (void)removeTabViewItem:(CPTabViewItem)aTabViewItem
|
- (void)removeTabViewItem:(CPTabViewItem)aTabViewItem
|
||||||
{
|
{
|
||||||
for (var i = 0; i < [items count]; i++)
|
var index = [self indexOfTabViewItem:aTabViewItem];
|
||||||
{
|
|
||||||
if ([items objectAtIndex:i] === aTabViewItem)
|
|
||||||
{
|
|
||||||
[items removeObjectAtIndex:i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[self _updateItems];
|
[_tabViewItems removeObjectIdenticalTo:aTabViewItem];
|
||||||
[self _repositionTabs];
|
|
||||||
|
[_labelsView tabView:self didRemoveTabViewItemAtIndex:index];
|
||||||
if (delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
|
|
||||||
[delegate tabViewDidChangeNumberOfTabViewItems:self];
|
[aTabViewItem _setTabView:nil];
|
||||||
|
|
||||||
|
if (_delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
|
||||||
|
[_delegate tabViewDidChangeNumberOfTabViewItems:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accessing Tabs
|
// Accessing Tabs
|
||||||
@@ -135,7 +281,7 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
|
|||||||
*/
|
*/
|
||||||
- (int)indexOfTabViewItem:(CPTabViewItem)aTabViewItem
|
- (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
|
- (int)indexOfTabViewItemWithIdentifier:(CPString)anIdentifier
|
||||||
{
|
{
|
||||||
for (var index = [items count]; index >= 0; index--)
|
var index = 0,
|
||||||
if ([[items[index] identifier] isEqual:anIdentifier])
|
count = [_tabViewItems count];
|
||||||
|
|
||||||
|
for (; index < count; ++index)
|
||||||
|
if ([[_tabViewItems[index] identifier] isEqual:anIdentifier])
|
||||||
return index;
|
return index;
|
||||||
|
|
||||||
return CPNotFound;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -156,7 +305,7 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
|
|||||||
*/
|
*/
|
||||||
- (unsigned)numberOfTabViewItems
|
- (unsigned)numberOfTabViewItems
|
||||||
{
|
{
|
||||||
return [items count];
|
return [_tabViewItems count];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -164,7 +313,7 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
|
|||||||
*/
|
*/
|
||||||
- (CPTabViewItem)tabViewItemAtIndex:(unsigned)anIndex
|
- (CPTabViewItem)tabViewItemAtIndex:(unsigned)anIndex
|
||||||
{
|
{
|
||||||
return [items objectAtIndex:anIndex];
|
return _tabViewItems[anIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -172,7 +321,7 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
|
|||||||
*/
|
*/
|
||||||
- (CPArray)tabViewItems
|
- (CPArray)tabViewItems
|
||||||
{
|
{
|
||||||
return [items copy]; // Copy?
|
return _tabViewItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Selecting a Tab
|
// Selecting a Tab
|
||||||
@@ -182,10 +331,10 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
|
|||||||
*/
|
*/
|
||||||
- (void)selectFirstTabViewItem:(id)aSender
|
- (void)selectFirstTabViewItem:(id)aSender
|
||||||
{
|
{
|
||||||
if ([items count] === 0)
|
var count = [_tabViewItems count];
|
||||||
return; // throw?
|
|
||||||
|
if (count)
|
||||||
[self selectTabViewItemAtIndex:0];
|
[self selectTabViewItemAtIndex:0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -194,10 +343,10 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
|
|||||||
*/
|
*/
|
||||||
- (void)selectLastTabViewItem:(id)aSender
|
- (void)selectLastTabViewItem:(id)aSender
|
||||||
{
|
{
|
||||||
if ([items count] === 0)
|
var count = [_tabViewItems count];
|
||||||
return; // throw?
|
|
||||||
|
if (count)
|
||||||
[self selectTabViewItemAtIndex:[items count] - 1];
|
[self selectTabViewItemAtIndex:count - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -206,16 +355,13 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
|
|||||||
*/
|
*/
|
||||||
- (void)selectNextTabViewItem:(id)aSender
|
- (void)selectNextTabViewItem:(id)aSender
|
||||||
{
|
{
|
||||||
if (selectedIndex === CPNotFound)
|
if (!_selectedTabViewItem)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var nextIndex = selectedIndex + 1;
|
var index = [self indexOfTabViewItem:_selectedTabViewItem],
|
||||||
|
count = [_tabViewItems count];
|
||||||
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:)
|
[self selectTabViewItemAtIndex:index + 1 % count];
|
||||||
return;
|
|
||||||
|
|
||||||
[self selectTabViewItemAtIndex:nextIndex];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -224,15 +370,13 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
|
|||||||
*/
|
*/
|
||||||
- (void)selectPreviousTabViewItem:(id)aSender
|
- (void)selectPreviousTabViewItem:(id)aSender
|
||||||
{
|
{
|
||||||
if (selectedIndex === CPNotFound)
|
if (!_selectedTabViewItem)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var previousIndex = selectedIndex - 1;
|
var index = [self indexOfTabViewItem:_selectedTabViewItem],
|
||||||
|
count = [_tabViewItems count];
|
||||||
if (previousIndex < 0)
|
|
||||||
return; // does nothing. See above.
|
[self selectTabViewItemAtIndex:index == 0 ? count : index - 1];
|
||||||
|
|
||||||
[self selectTabViewItemAtIndex:previousIndex];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -241,7 +385,41 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
|
|||||||
*/
|
*/
|
||||||
- (void)selectTabViewItem:(CPTabViewItem)aTabViewItem
|
- (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
|
- (void)selectTabViewItemAtIndex:(unsigned)anIndex
|
||||||
{
|
{
|
||||||
var aTabViewItem = [items objectAtIndex:anIndex];
|
[self selectTabViewItem:_tabViewItems[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];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -275,43 +436,32 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
|
|||||||
*/
|
*/
|
||||||
- (CPTabViewItem)selectedTabViewItem
|
- (CPTabViewItem)selectedTabViewItem
|
||||||
{
|
{
|
||||||
return [items objectAtIndex:selectedIndex];
|
return _selectedTabViewItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
/*!
|
/*!
|
||||||
Sets the tab view type.
|
Sets the tab view type.
|
||||||
@param aTabViewType the view type
|
@param aTabViewType the view type
|
||||||
*/
|
*/
|
||||||
- (void)setTabViewType:(CPTabViewType)aTabViewType
|
- (void)setTabViewType:(CPTabViewType)aTabViewType
|
||||||
{
|
{
|
||||||
if (type === aTabViewType)
|
if (_tabViewType == aTabViewType)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((type === CPTopTabsBezelBorder || type === CPBottomTabsBezelBorder)
|
_tabViewType = aTabViewType;
|
||||||
&& (aTabViewType !== CPTopTabsBezelBorder && aTabViewType !== CPBottomTabsBezelBorder))
|
|
||||||
[tabs removeFromSuperview];
|
if (_tabViewType == CPNoTabsBezelBorder || _tabViewType == CPNoTabsLineBorder || _tabViewType == CPNoTabsNoBorder)
|
||||||
|
[_labelsView removeFromSuperview];
|
||||||
if ((type === CPNoTabsBezelBorder || type === CPNoTabsLineBorder || type === CPNoTabsNoBorder)
|
else if (![_labelsView superview])
|
||||||
&& (aTabViewType !== CPNoTabsBezelBorder && aTabViewType !== CPNoTabsBezelBorder && aTabViewType !== CPNoTabsNoBorder))
|
[self addSubview:_labelsView];
|
||||||
[self addSubview:tabs];
|
|
||||||
|
if (_tabViewType == CPNoTabsLineBorder || _tabViewType == CPNoTabsNoBorder)
|
||||||
type = aTabViewType;
|
[_backgroundView removeFromSuperview];
|
||||||
|
else if (![_backgroundView superview])
|
||||||
switch (type)
|
[self addSubview:_backgroundView];
|
||||||
{
|
|
||||||
case CPTopTabsBezelBorder:
|
[self layoutSubviews];
|
||||||
case CPBottomTabsBezelBorder:
|
|
||||||
case CPNoTabsBezelBorder:
|
|
||||||
[box setBorderType:CPBezelBorder];
|
|
||||||
break;
|
|
||||||
case CPNoTabsLineBorder:
|
|
||||||
[box setBorderType:CPLineBorder];
|
|
||||||
break;
|
|
||||||
case CPNoTabsNoBorder:
|
|
||||||
[box setBorderType:CPNoBorder];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -319,7 +469,31 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
|
|||||||
*/
|
*/
|
||||||
- (CPTabViewType)tabViewType
|
- (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
|
- (id)delegate
|
||||||
{
|
{
|
||||||
return delegate;
|
return _delegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -336,74 +510,35 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
|
|||||||
*/
|
*/
|
||||||
- (void)setDelegate:(id)aDelegate
|
- (void)setDelegate:(id)aDelegate
|
||||||
{
|
{
|
||||||
if (delegate == aDelegate)
|
if (_delegate == aDelegate)
|
||||||
return;
|
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:)])
|
if ([_delegate respondsToSelector:@selector(tabView:didSelectTabViewItem:)])
|
||||||
delegateSelectors |= CPTabViewShouldSelectTabViewItemSelector;
|
_delegateSelectors |= CPTabViewDidSelectTabViewItemSelector;
|
||||||
|
|
||||||
if ([delegate respondsToSelector:@selector(tabView:willSelectTabViewItem:)])
|
if ([_delegate respondsToSelector:@selector(tabViewDidChangeNumberOfTabViewItems:)])
|
||||||
delegateSelectors |= CPTabViewWillSelectTabViewItemSelector;
|
_delegateSelectors |= CPTabViewDidChangeNumberOfTabViewItemsSelector;
|
||||||
|
|
||||||
if ([delegate respondsToSelector:@selector(tabView:didSelectTabViewItem:)])
|
|
||||||
delegateSelectors |= CPTabViewDidSelectTabViewItemSelector;
|
|
||||||
|
|
||||||
if ([delegate respondsToSelector:@selector(tabViewDidChangeNumberOfTabViewItems:)])
|
|
||||||
delegateSelectors |= CPTabViewDidChangeNumberOfTabViewItemsSelector;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setBackgroundColor:(CPColor)aColor
|
//
|
||||||
{
|
|
||||||
[box setBackgroundColor:aColor];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)mouseDown:(CPEvent)anEvent
|
- (void)mouseDown:(CPEvent)anEvent
|
||||||
{
|
{
|
||||||
var segmentIndex = [tabs testSegment:[tabs convertPoint:[anEvent locationInWindow] fromView:nil]];
|
var location = [_labelsView convertPoint:[anEvent locationInWindow] fromView:nil],
|
||||||
|
tabViewItem = [_labelsView representedTabViewItemAtPoint:location];
|
||||||
if (segmentIndex != CPNotFound)
|
|
||||||
{
|
if (tabViewItem)
|
||||||
[self selectTabViewItemAtIndex:segmentIndex];
|
[self selectTabViewItem:tabViewItem];
|
||||||
[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];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -419,17 +554,20 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
|
|||||||
{
|
{
|
||||||
if (self = [super initWithCoder:aCoder])
|
if (self = [super initWithCoder:aCoder])
|
||||||
{
|
{
|
||||||
type = [aCoder decodeIntForKey:CPTabViewTypeKey];
|
_tabViewType = [aCoder decodeIntForKey:CPTabViewTypeKey];
|
||||||
items = [];
|
_tabViewItems = [];
|
||||||
|
|
||||||
var encodedItems = [aCoder decodeObjectForKey:CPTabViewItemsKey];
|
// FIXME: this is somewhat hacky
|
||||||
for (var i = 0; encodedItems && i < encodedItems.length; i++)
|
[self _createBezelBorder];
|
||||||
[self insertTabViewItem:encodedItems[i] atIndex:i];
|
|
||||||
|
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];
|
var selected = [aCoder decodeObjectForKey:CPTabViewSelectedItemKey];
|
||||||
if (selected)
|
if (selected)
|
||||||
[self selectTabViewItem:selected];
|
[self selectTabViewItem:selected];
|
||||||
|
|
||||||
[self setDelegate:[aCoder decodeObjectForKey:CPTabViewDelegateKey]];
|
[self setDelegate:[aCoder decodeObjectForKey:CPTabViewDelegateKey]];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -438,14 +576,227 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
|
|||||||
|
|
||||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||||
{
|
{
|
||||||
|
var actualSubviews = _subviews;
|
||||||
|
_subviews = [];
|
||||||
[super encodeWithCoder:aCoder];
|
[super encodeWithCoder:aCoder];
|
||||||
|
_subviews = actualSubviews;
|
||||||
[aCoder encodeObject:items forKey:CPTabViewItemsKey];;
|
|
||||||
[aCoder encodeObject:[self selectedTabViewItem] forKey:CPTabViewSelectedItemKey];
|
[aCoder encodeObject:_tabViewItems forKey:CPTabViewItemsKey];;
|
||||||
|
[aCoder encodeObject:_selectedTabViewItem forKey:CPTabViewSelectedItemKey];
|
||||||
[aCoder encodeInt:type forKey:CPTabViewTypeKey];
|
|
||||||
|
[aCoder encodeInt:_tabViewType forKey:CPTabViewTypeKey];
|
||||||
[aCoder encodeConditionalObject:delegate forKey:CPTabViewDelegateKey];
|
|
||||||
|
[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
|
@end
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
@import <Foundation/CPObject.j>
|
@import <Foundation/CPObject.j>
|
||||||
|
|
||||||
@import "CPView.j"
|
@import <AppKit/CPView.j>
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
+28
-112
@@ -22,12 +22,12 @@
|
|||||||
|
|
||||||
@import <Foundation/CPDictionary.j>
|
@import <Foundation/CPDictionary.j>
|
||||||
@import <Foundation/CPObject.j>
|
@import <Foundation/CPObject.j>
|
||||||
@import <Foundation/CPIndexSet.j>
|
|
||||||
@import <Foundation/CPSortDescriptor.j>
|
@import <Foundation/CPSortDescriptor.j>
|
||||||
@import <Foundation/CPString.j>
|
@import <Foundation/CPString.j>
|
||||||
|
|
||||||
@import "CPTableHeaderView.j"
|
@import "CPTableHeaderView.j"
|
||||||
|
|
||||||
|
#include "CoreGraphics/CGGeometry.h"
|
||||||
|
|
||||||
CPTableColumnNoResizing = 0;
|
CPTableColumnNoResizing = 0;
|
||||||
CPTableColumnAutoresizingMask = 1 << 0;
|
CPTableColumnAutoresizingMask = 1 << 0;
|
||||||
@@ -50,7 +50,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
|||||||
CPSortDescriptor _sortDescriptorPrototype;
|
CPSortDescriptor _sortDescriptorPrototype;
|
||||||
BOOL _isHidden;
|
BOOL _isHidden;
|
||||||
CPString _headerToolTip;
|
CPString _headerToolTip;
|
||||||
|
|
||||||
BOOL _disableResizingPosting @accessors(property=disableResizingPosting);
|
BOOL _disableResizingPosting @accessors(property=disableResizingPosting);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,13 +72,19 @@ CPTableColumnUserResizingMask = 1 << 1;
|
|||||||
_maxWidth = 1000000.0;
|
_maxWidth = 1000000.0;
|
||||||
_resizingMask = CPTableColumnAutoresizingMask | CPTableColumnUserResizingMask;
|
_resizingMask = CPTableColumnAutoresizingMask | CPTableColumnUserResizingMask;
|
||||||
_disableResizingPosting = NO;
|
_disableResizingPosting = NO;
|
||||||
|
|
||||||
[self setIdentifier:anIdentifier];
|
[self setIdentifier:anIdentifier];
|
||||||
|
|
||||||
var header = [[_CPTableColumnHeaderView alloc] initWithFrame:CGRectMakeZero()];
|
var header = [[_CPTableColumnHeaderView alloc] initWithFrame:CGRectMakeZero()];
|
||||||
[self setHeaderView:header];
|
[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;
|
return self;
|
||||||
@@ -117,19 +123,19 @@ CPTableColumnUserResizingMask = 1 << 1;
|
|||||||
{
|
{
|
||||||
var index = [[tableView tableColumns] indexOfObjectIdenticalTo:self],
|
var index = [[tableView tableColumns] indexOfObjectIdenticalTo:self],
|
||||||
dirtyTableColumnRangeIndex = tableView._dirtyTableColumnRangeIndex;
|
dirtyTableColumnRangeIndex = tableView._dirtyTableColumnRangeIndex;
|
||||||
|
|
||||||
if (dirtyTableColumnRangeIndex < 0)
|
if (dirtyTableColumnRangeIndex < 0)
|
||||||
tableView._dirtyTableColumnRangeIndex = index;
|
tableView._dirtyTableColumnRangeIndex = index;
|
||||||
else
|
else
|
||||||
tableView._dirtyTableColumnRangeIndex = MIN(index, tableView._dirtyTableColumnRangeIndex);
|
tableView._dirtyTableColumnRangeIndex = MIN(index, tableView._dirtyTableColumnRangeIndex);
|
||||||
|
|
||||||
var rows = tableView._exposedRows,
|
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.
|
// 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 _layoutDataViewsInRows:rows columns:columns];
|
||||||
[tableView tile];
|
[tableView tile];
|
||||||
|
|
||||||
if (!_disableResizingPosting)
|
if (!_disableResizingPosting)
|
||||||
[self _postDidResizeNotificationWithOldWidth:oldWidth];
|
[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.
|
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.
|
individual cell that is shown. As a result, changes made after calling this method won't be reflected.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
[tableColumn setDataView:someView]; // snapshot taken
|
[tableColumn setDataView:someView]; // snapshot taken
|
||||||
[[tableColumn dataView] setSomething:x]; //won't work
|
[[tableColumn dataView] setSomething:x]; //won't work
|
||||||
|
|
||||||
@@ -242,11 +248,12 @@ CPTableColumnUserResizingMask = 1 << 1;
|
|||||||
*/
|
*/
|
||||||
- (void)setDataView:(CPView)aView
|
- (void)setDataView:(CPView)aView
|
||||||
{
|
{
|
||||||
|
if (_dataView === aView)
|
||||||
|
return;
|
||||||
|
|
||||||
if (_dataView)
|
if (_dataView)
|
||||||
_dataViewData[[_dataView UID]] = nil;
|
_dataViewData[[_dataView UID]] = nil;
|
||||||
|
|
||||||
[aView setThemeState:CPThemeStateTableDataView];
|
|
||||||
|
|
||||||
_dataView = aView;
|
_dataView = aView;
|
||||||
_dataViewData[[aView UID]] = [CPKeyedArchiver archivedDataWithRootObject:aView];
|
_dataViewData[[aView UID]] = [CPKeyedArchiver archivedDataWithRootObject:aView];
|
||||||
}
|
}
|
||||||
@@ -285,10 +292,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
|||||||
// unarchive the data view cache
|
// unarchive the data view cache
|
||||||
var newDataView = [CPKeyedUnarchiver unarchiveObjectWithData:_dataViewData[dataViewUID]];
|
var newDataView = [CPKeyedUnarchiver unarchiveObjectWithData:_dataViewData[dataViewUID]];
|
||||||
newDataView.identifier = dataViewUID;
|
newDataView.identifier = dataViewUID;
|
||||||
|
|
||||||
// make sure only we have control over the size and placement
|
|
||||||
[newDataView setAutoresizingMask:CPViewNotSizable];
|
|
||||||
|
|
||||||
return newDataView;
|
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.
|
column in the NSTableView, NO otherwise.
|
||||||
*/
|
*/
|
||||||
- (BOOL)isEditable
|
- (BOOL)isEditable
|
||||||
@@ -344,14 +348,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
|||||||
|
|
||||||
- (void)setHidden:(BOOL)shouldBeHidden
|
- (void)setHidden:(BOOL)shouldBeHidden
|
||||||
{
|
{
|
||||||
shouldBeHidden = !!shouldBeHidden
|
|
||||||
if (_isHidden === shouldBeHidden)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_isHidden = shouldBeHidden;
|
_isHidden = shouldBeHidden;
|
||||||
|
|
||||||
[[self headerView] setHidden:shouldBeHidden];
|
|
||||||
[[self tableView] _tableColumnVisibilityDidChange:self];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)isHidden
|
- (BOOL)isHidden
|
||||||
@@ -362,7 +359,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
|||||||
//Setting Tool Tips
|
//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.
|
header cell of the receiver.
|
||||||
*/
|
*/
|
||||||
- (void)setHeaderToolTip:(CPString)aToolTip
|
- (void)setHeaderToolTip:(CPString)aToolTip
|
||||||
@@ -385,86 +382,13 @@ CPTableColumnUserResizingMask = 1 << 1;
|
|||||||
|
|
||||||
@end
|
@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",
|
var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
|
||||||
CPTableColumnHeaderViewKey = @"CPTableColumnHeaderViewKey",
|
CPTableColumnHeaderViewKey = @"CPTableColumnHeaderViewKey",
|
||||||
CPTableColumnDataViewKey = @"CPTableColumnDataViewKey",
|
CPTableColumnDataViewKey = @"CPTableColumnDataViewKey",
|
||||||
CPTableColumnWidthKey = @"CPTableColumnWidthKey",
|
CPTableColumnWidthKey = @"CPTableColumnWidthKey",
|
||||||
CPTableColumnMinWidthKey = @"CPTableColumnMinWidthKey",
|
CPTableColumnMinWidthKey = @"CPTableColumnMinWidthKey",
|
||||||
CPTableColumnMaxWidthKey = @"CPTableColumnMaxWidthKey",
|
CPTableColumnMaxWidthKey = @"CPTableColumnMaxWidthKey",
|
||||||
CPTableColumnResizingMaskKey = @"CPTableColumnResizingMaskKey",
|
CPTableColumnResizingMaskKey = @"CPTableColumnResizingMaskKey";
|
||||||
CPTableColumnIsHiddenKey = @"CPTableColumnIsHiddenKey",
|
|
||||||
CPSortDescriptorPrototypeKey = @"CPSortDescriptorPrototypeKey",
|
|
||||||
CPTableColumnIsEditableKey = @"CPTableColumnIsEditableKey";
|
|
||||||
|
|
||||||
@implementation CPTableColumn (CPCoding)
|
@implementation CPTableColumn (CPCoding)
|
||||||
|
|
||||||
@@ -485,11 +409,7 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
|
|||||||
[self setDataView:[aCoder decodeObjectForKey:CPTableColumnDataViewKey]];
|
[self setDataView:[aCoder decodeObjectForKey:CPTableColumnDataViewKey]];
|
||||||
[self setHeaderView:[aCoder decodeObjectForKey:CPTableColumnHeaderViewKey]];
|
[self setHeaderView:[aCoder decodeObjectForKey:CPTableColumnHeaderViewKey]];
|
||||||
|
|
||||||
_resizingMask = [aCoder decodeIntForKey:CPTableColumnResizingMaskKey];
|
_resizingMask = [aCoder decodeBoolForKey:CPTableColumnResizingMaskKey];
|
||||||
_isHidden = [aCoder decodeBoolForKey:CPTableColumnIsHiddenKey];
|
|
||||||
_isEditable = [aCoder decodeBoolForKey:CPTableColumnIsEditableKey];
|
|
||||||
|
|
||||||
_sortDescriptorPrototype = [aCoder decodeObjectForKey:CPSortDescriptorPrototypeKey];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
@@ -507,10 +427,6 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
|
|||||||
[aCoder encodeObject:_dataView forKey:CPTableColumnDataViewKey];
|
[aCoder encodeObject:_dataView forKey:CPTableColumnDataViewKey];
|
||||||
|
|
||||||
[aCoder encodeObject:_resizingMask forKey:CPTableColumnResizingMaskKey];
|
[aCoder encodeObject:_resizingMask forKey:CPTableColumnResizingMaskKey];
|
||||||
[aCoder encodeBool:_isHidden forKey:CPTableColumnIsHiddenKey];
|
|
||||||
[aCoder encodeBool:_isEditable forKey:CPTableColumnIsEditableKey];
|
|
||||||
|
|
||||||
[aCoder encodeObject:_sortDescriptorPrototype forKey:CPSortDescriptorPrototypeKey];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -547,4 +463,4 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
|
|||||||
reason:@"dataCellForRow: is not supported. Use -dataViewForRow:row instead."];
|
reason:@"dataCellForRow: is not supported. Use -dataViewForRow:row instead."];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
+188
-374
@@ -20,64 +20,54 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@import <Foundation/CPIndexSet.j>
|
|
||||||
|
|
||||||
@import "CPTableColumn.j"
|
@import "CPTableColumn.j"
|
||||||
@import "CPTableView.j"
|
@import "CPTableView.j"
|
||||||
@import "CPView.j"
|
@import "CPView.j"
|
||||||
|
|
||||||
|
|
||||||
@implementation _CPTableColumnHeaderView : CPView
|
@implementation _CPTableColumnHeaderView : CPView
|
||||||
{
|
{
|
||||||
_CPImageAndTextView _textField;
|
_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
|
- (void)initWithFrame:(CGRect)frame
|
||||||
{
|
{
|
||||||
self = [super initWithFrame:frame];
|
self = [super initWithFrame:frame];
|
||||||
if (self)
|
if (self)
|
||||||
|
{
|
||||||
[self _init];
|
[self _init];
|
||||||
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_init
|
- (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 setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
|
||||||
|
|
||||||
[_textField setLineBreakMode:CPLineBreakByTruncatingTail];
|
[_textField setLineBreakMode:CPLineBreakByTruncatingTail];
|
||||||
|
[_textField setTextColor: [CPColor colorWithHexString: @"333333"]];
|
||||||
|
[_textField setFont:[CPFont boldSystemFontOfSize:12.0]];
|
||||||
[_textField setAlignment:CPLeftTextAlignment];
|
[_textField setAlignment:CPLeftTextAlignment];
|
||||||
[_textField setVerticalAlignment:CPCenterVerticalTextAlignment];
|
[_textField setVerticalAlignment:CPCenterVerticalTextAlignment];
|
||||||
|
[_textField setTextShadowColor:[CPColor whiteColor]];
|
||||||
|
[_textField setTextShadowOffset:CGSizeMake(0,1)];
|
||||||
|
|
||||||
[self addSubview:_textField];
|
[self addSubview:_textField];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)layoutSubviews
|
- (void)layoutSubviews
|
||||||
{
|
{
|
||||||
[self setBackgroundColor:[self currentValueForThemeAttribute:@"background-color"]];
|
var themeState = [self themeState];
|
||||||
|
|
||||||
var inset = [self currentValueForThemeAttribute:@"text-inset"],
|
if(themeState & CPThemeStateSelected && themeState & CPThemeStateHighlighted)
|
||||||
bounds = [self bounds];
|
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-highlighted-pressed.png", CGSizeMake(1.0, 22.0))]];
|
||||||
|
else if (themeState & CPThemeStateSelected)
|
||||||
[_textField setFrame:_CGRectMake(inset.right, inset.top, bounds.size.width - inset.right - inset.left, bounds.size.height - inset.top - inset.bottom)];
|
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-highlighted.png", CGSizeMake(1.0, 22.0))]];
|
||||||
[_textField setTextColor:[self currentValueForThemeAttribute:@"text-color"]];
|
else if (themeState & CPThemeStateHighlighted)
|
||||||
[_textField setFont:[self currentValueForThemeAttribute:@"text-font"]];
|
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-pressed.png", CGSizeMake(1.0, 22.0))]];
|
||||||
[_textField setTextShadowColor:[self currentValueForThemeAttribute:@"text-shadow-color"]];
|
else
|
||||||
[_textField setTextShadowOffset:[self currentValueForThemeAttribute:@"text-shadow-offset"]];
|
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 22.0))]];
|
||||||
[_textField setAlignment:[self currentValueForThemeAttribute:@"text-alignment"]];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setStringValue:(CPString)string
|
- (void)setStringValue:(CPString)string
|
||||||
@@ -105,6 +95,11 @@
|
|||||||
[_textField setFont:aFont];
|
[_textField setFont:aFont];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setValue:(id)aValue forThemeAttribute:(id)aKey
|
||||||
|
{
|
||||||
|
[_textField setValue:aValue forThemeAttribute:aKey];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)_setIndicatorImage:(CPImage)anImage
|
- (void)_setIndicatorImage:(CPImage)anImage
|
||||||
{
|
{
|
||||||
if (anImage)
|
if (anImage)
|
||||||
@@ -142,7 +137,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
|
|||||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||||
{
|
{
|
||||||
[super encodeWithCoder:aCoder];
|
[super encodeWithCoder:aCoder];
|
||||||
|
|
||||||
[aCoder encodeObject:[_textField text] forKey:_CPTableColumnHeaderViewStringValueKey];
|
[aCoder encodeObject:[_textField text] forKey:_CPTableColumnHeaderViewStringValueKey];
|
||||||
[aCoder encodeObject:[_textField image] forKey:_CPTableColumnHeaderViewImageKey];
|
[aCoder encodeObject:[_textField image] forKey:_CPTableColumnHeaderViewImageKey];
|
||||||
[aCoder encodeObject:[_textField font] forKey:_CPTableColumnHeaderViewFontKey];
|
[aCoder encodeObject:[_textField font] forKey:_CPTableColumnHeaderViewFontKey];
|
||||||
@@ -152,47 +147,27 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
|
|||||||
|
|
||||||
@implementation CPTableHeaderView : CPView
|
@implementation CPTableHeaderView : CPView
|
||||||
{
|
{
|
||||||
CGPoint _mouseDownLocation;
|
int _resizedColumn @accessors(readonly, property=resizedColumn);
|
||||||
CGPoint _previousTrackingLocation;
|
int _draggedColumn @accessors(readonly, property=draggedColumn);
|
||||||
int _activeColumn;
|
int _pressedColumn @accessors(readonly, property=pressedColumn);
|
||||||
int _pressedColumn;
|
|
||||||
|
float _draggedDistance @accessors(readonly, property=draggedDistance);
|
||||||
BOOL _isResizing;
|
float _lastLocation;
|
||||||
BOOL _isDragging;
|
float _columnOldWidth;
|
||||||
BOOL _isTrackingColumn;
|
|
||||||
BOOL _drawsColumnLines;
|
CPTableView _tableView @accessors(property=tableView);
|
||||||
|
|
||||||
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
|
- (void)_init
|
||||||
{
|
{
|
||||||
_mouseDownLocation = _CGPointMakeZero();
|
_resizedColumn = -1;
|
||||||
_previousTrackingLocation = _CGPointMakeZero();
|
_draggedColumn = -1;
|
||||||
_activeColumn = -1;
|
|
||||||
_pressedColumn = -1;
|
_pressedColumn = -1;
|
||||||
|
_draggedDistance = 0.0;
|
||||||
|
_lastLocation = nil;
|
||||||
|
_columnOldWidth = nil;
|
||||||
|
|
||||||
_isResizing = NO;
|
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 22.0))]];
|
||||||
_isDragging = NO;
|
|
||||||
_isTrackingColumn = NO;
|
|
||||||
_drawsColumnLines = YES;
|
|
||||||
|
|
||||||
_columnOldWidth = 0.0;
|
|
||||||
|
|
||||||
[self setBackgroundColor:[self currentValueForThemeAttribute:@"background-color"]];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithFrame:(CGRect)aFrame
|
- (id)initWithFrame:(CGRect)aFrame
|
||||||
@@ -207,41 +182,39 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
|
|||||||
|
|
||||||
- (int)columnAtPoint:(CGPoint)aPoint
|
- (int)columnAtPoint:(CGPoint)aPoint
|
||||||
{
|
{
|
||||||
return [_tableView columnAtPoint:CGPointMake(aPoint.x, aPoint.y)];
|
return [_tableView columnAtPoint:CGPointMake(aPoint.x, 0)];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGRect)headerRectOfColumn:(int)aColumnIndex
|
- (CGRect)headerRectOfColumn:(int)aColumnIndex
|
||||||
{
|
{
|
||||||
var headerRect = [self bounds],
|
var tableColumns = [_tableView tableColumns];
|
||||||
columnRect = [_tableView rectOfColumn:aColumnIndex];
|
|
||||||
|
|
||||||
headerRect.origin.x = _CGRectGetMinX(columnRect);
|
if (aColumnIndex < 0 || aColumnIndex > [tableColumns count])
|
||||||
headerRect.size.width = _CGRectGetWidth(columnRect);
|
[CPException raise:"invalid" reason:"tried to get headerRectOfColumn: on invalid column"];
|
||||||
|
|
||||||
return headerRect;
|
// UPDATE COLUMN RANGES ?
|
||||||
}
|
|
||||||
|
var tableRange = _tableView._tableColumnRanges[aColumnIndex],
|
||||||
|
bounds = [self bounds];
|
||||||
|
|
||||||
- (void)setDrawsColumnLines:(BOOL)aFlag
|
var rMinX = ROUND(tableRange.location);
|
||||||
{
|
bounds.origin.x = rMinX;
|
||||||
_drawsColumnLines = aFlag;
|
bounds.size.width = FLOOR(tableRange.length + tableRange.location - rMinX);
|
||||||
}
|
|
||||||
|
return bounds;
|
||||||
- (BOOL)drawsColumnLines
|
|
||||||
{
|
|
||||||
return _drawsColumnLines;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGRect)_cursorRectForColumn:(int)column
|
- (CGRect)_cursorRectForColumn:(int)column
|
||||||
{
|
{
|
||||||
if (column == -1 || !([_tableView._tableColumns[column] resizingMask] & CPTableColumnUserResizingMask))
|
if (column == -1 || !([_tableView._tableColumns[column] resizingMask] & CPTableColumnUserResizingMask))
|
||||||
return _CGRectMakeZero();
|
return CGRectMakeZero();
|
||||||
|
|
||||||
var rect = [self headerRectOfColumn:column];
|
var rect = [self headerRectOfColumn:column];
|
||||||
|
|
||||||
rect.origin.x = _CGRectGetMaxX(rect) - 5;
|
rect.origin.x = CGRectGetMaxX(rect) - 5;
|
||||||
rect.size.width = 20;
|
rect.size.width = 20;
|
||||||
|
|
||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_setPressedColumn:(CPInteger)column
|
- (void)_setPressedColumn:(CPInteger)column
|
||||||
@@ -250,293 +223,117 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
|
|||||||
{
|
{
|
||||||
var headerView = [_tableView._tableColumns[_pressedColumn] headerView];
|
var headerView = [_tableView._tableColumns[_pressedColumn] headerView];
|
||||||
[headerView unsetThemeState:CPThemeStateHighlighted];
|
[headerView unsetThemeState:CPThemeStateHighlighted];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (column != -1)
|
if (column != -1)
|
||||||
{
|
{
|
||||||
var headerView = [_tableView._tableColumns[column] headerView];
|
var headerView = [_tableView._tableColumns[column] headerView];
|
||||||
[headerView setThemeState:CPThemeStateHighlighted];
|
[headerView setThemeState:CPThemeStateHighlighted];
|
||||||
}
|
}
|
||||||
|
|
||||||
_pressedColumn = column;
|
_pressedColumn = column;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)mouseDown:(CPEvent)theEvent
|
- (void)mouseDown:(CPEvent)theEvent
|
||||||
{
|
{
|
||||||
[self trackMouse:theEvent];
|
var mouseLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil],
|
||||||
|
clickedColumn = [self columnAtPoint:mouseLocation];
|
||||||
|
|
||||||
|
// should we send column -1 ?
|
||||||
|
[_tableView _sendDelegateDidMouseDownInHeader:clickedColumn];
|
||||||
|
|
||||||
|
var resizeLocation = CGPointMake(mouseLocation.x - 5, mouseLocation.y),
|
||||||
|
resizedColumn = [self columnAtPoint:resizeLocation];
|
||||||
|
|
||||||
|
if (resizedColumn == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 2 different tracking methods: one for resizing/stop-resizing, another one for selection/reordering
|
||||||
|
if ([_tableView allowsColumnResizing]
|
||||||
|
&& CGRectContainsPoint([self _cursorRectForColumn:resizedColumn], mouseLocation))
|
||||||
|
{
|
||||||
|
_resizedColumn = resizedColumn;
|
||||||
|
[_tableView._tableColumns[_resizedColumn] setDisableResizingPosting:YES];
|
||||||
|
[_tableView setDisableAutomaticResizing:YES];
|
||||||
|
[self trackResizeWithEvent:theEvent];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[self _setPressedColumn:clickedColumn];
|
||||||
|
[self trackMouseWithEvent:theEvent];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)trackMouse:(CPEvent)theEvent
|
- (void)trackMouseWithEvent:(CPEvent)theEvent
|
||||||
{
|
{
|
||||||
var type = [theEvent type],
|
var type = [theEvent type];
|
||||||
currentLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
|
||||||
|
if (type == CPLeftMouseUp)
|
||||||
// Take the right columns resize tracking area into account
|
|
||||||
currentLocation.x -= 5.0;
|
|
||||||
|
|
||||||
var columnIndex = [self columnAtPoint:currentLocation],
|
|
||||||
shouldResize = [self shouldResizeTableColumn:columnIndex at:_CGPointMake(currentLocation.x + 5.0, currentLocation.y)];
|
|
||||||
|
|
||||||
if (type === CPLeftMouseUp)
|
|
||||||
{
|
{
|
||||||
if (shouldResize)
|
var location = [self convertPoint:[theEvent locationInWindow] fromView:nil],
|
||||||
[self stopResizingTableColumn:_activeColumn at:currentLocation];
|
clickedColumn = [self columnAtPoint:location];
|
||||||
else if ([self _shouldStopTrackingTableColumn:columnIndex at:currentLocation])
|
|
||||||
{
|
|
||||||
[_tableView _didClickTableColumn:columnIndex modifierFlags:[theEvent modifierFlags]];
|
|
||||||
[self stopTrackingTableColumn:columnIndex at:currentLocation];
|
|
||||||
|
|
||||||
_isTrackingColumn = NO;
|
[self _setPressedColumn:-1];
|
||||||
}
|
|
||||||
|
if (clickedColumn != -1)
|
||||||
[self _updateResizeCursor:[CPApp currentEvent]];
|
[_tableView _didClickTableColumn:clickedColumn modifierFlags:[theEvent modifierFlags]];
|
||||||
|
|
||||||
_activeColumn = CPNotFound;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === CPLeftMouseDown)
|
[CPApp setTarget:self selector:@selector(trackMouseWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPLeftMouseDownMask untilDate:nil inMode:nil dequeue:YES];
|
||||||
{
|
}
|
||||||
if (columnIndex === -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_mouseDownLocation = currentLocation;
|
- (void)trackResizeWithEvent:(CPEvent)anEvent
|
||||||
_activeColumn = columnIndex;
|
{
|
||||||
|
var location = [self convertPoint:[anEvent locationInWindow] fromView:nil],
|
||||||
|
tableColumn = [[_tableView tableColumns] objectAtIndex:_resizedColumn],
|
||||||
|
type = [anEvent type];
|
||||||
|
|
||||||
[_tableView _sendDelegateDidMouseDownInHeader:columnIndex];
|
if (_lastLocation == nil)
|
||||||
|
_lastLocation = location;
|
||||||
|
|
||||||
if (shouldResize)
|
if (_columnOldWidth == nil)
|
||||||
[self startResizingTableColumn:columnIndex at:currentLocation];
|
_columnOldWidth = [tableColumn width];
|
||||||
else
|
|
||||||
{
|
if (type === CPLeftMouseUp)
|
||||||
[self startTrackingTableColumn:columnIndex at:currentLocation];
|
{
|
||||||
_isTrackingColumn = YES;
|
[self _updateResizeCursor:anEvent];
|
||||||
}
|
|
||||||
}
|
[tableColumn _postDidResizeNotificationWithOldWidth:_columnOldWidth];
|
||||||
|
[tableColumn setDisableResizingPosting:NO];
|
||||||
|
[_tableView setDisableAutomaticResizing:NO];
|
||||||
|
|
||||||
|
_resizedColumn = -1;
|
||||||
|
_lastLocation = nil;
|
||||||
|
_columnOldWidth = nil;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
else if (type === CPLeftMouseDragged)
|
else if (type === CPLeftMouseDragged)
|
||||||
{
|
{
|
||||||
if (shouldResize)
|
var newWidth = [tableColumn width] + location.x - _lastLocation.x;
|
||||||
[self continueResizingTableColumn:_activeColumn at:currentLocation];
|
|
||||||
|
if (newWidth < [tableColumn minWidth])
|
||||||
|
[[CPCursor resizeRightCursor] set];
|
||||||
|
else if (newWidth > [tableColumn maxWidth])
|
||||||
|
[[CPCursor resizeLeftCursor] set];
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (_activeColumn === columnIndex && _CGRectContainsPoint([self headerRectOfColumn:columnIndex], currentLocation))
|
_tableView._lastColumnShouldSnap = NO;
|
||||||
{
|
[tableColumn setWidth:newWidth];
|
||||||
if (_isTrackingColumn && _pressedColumn !== -1)
|
// FIXME: there has to be a better way to do this...
|
||||||
{
|
// We should refactor the auto resizing crap.
|
||||||
if (![self continueTrackingTableColumn:columnIndex at:currentLocation])
|
// We need to figure out the exact cocoa behavior here though.
|
||||||
return; // Stop tracking the column, because it's being dragged
|
_lastLocation = location;
|
||||||
} else
|
|
||||||
[self startTrackingTableColumn:columnIndex at:currentLocation];
|
|
||||||
|
|
||||||
} else if (_isTrackingColumn && _pressedColumn !== -1)
|
[[CPCursor resizeLeftRightCursor] set];
|
||||||
[self stopTrackingTableColumn:_activeColumn at:currentLocation];
|
[self setNeedsLayout];
|
||||||
|
[self setNeedsDisplay:YES];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_previousTrackingLocation = currentLocation;
|
[CPApp setTarget:self selector:@selector(trackResizeWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
|
||||||
[CPApp setTarget:self selector:@selector(trackMouse:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)startTrackingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
|
|
||||||
{
|
|
||||||
[self _setPressedColumn:aColumnIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)continueTrackingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
|
|
||||||
{
|
|
||||||
if ([self _shouldDragTableColumn:aColumnIndex at:aPoint])
|
|
||||||
{
|
|
||||||
var columnRect = [self headerRectOfColumn:aColumnIndex],
|
|
||||||
offset = _CGPointMakeZero(),
|
|
||||||
view = [_tableView _dragViewForColumn:aColumnIndex event:[CPApp currentEvent] offset:offset],
|
|
||||||
viewLocation = _CGPointMakeZero();
|
|
||||||
|
|
||||||
viewLocation.x = ( _CGRectGetMinX(columnRect) + offset.x ) + ( aPoint.x - _mouseDownLocation.x );
|
|
||||||
viewLocation.y = _CGRectGetMinY(columnRect) + offset.y;
|
|
||||||
|
|
||||||
[self dragView:view at:viewLocation offset:_CGSizeMakeZero() event:[CPApp currentEvent]
|
|
||||||
pasteboard:[CPPasteboard pasteboardWithName:CPDragPboard] source:self slideBack:YES];
|
|
||||||
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)_shouldStopTrackingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
|
|
||||||
{
|
|
||||||
return _isTrackingColumn && _activeColumn === aColumnIndex &&
|
|
||||||
_CGRectContainsPoint([self headerRectOfColumn:aColumnIndex], aPoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)stopTrackingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
|
|
||||||
{
|
|
||||||
[self _setPressedColumn:CPNotFound];
|
|
||||||
[self _updateResizeCursor:[CPApp currentEvent]];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)_shouldDragTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
|
|
||||||
{
|
|
||||||
return [_tableView allowsColumnReordering] && ABS(aPoint.x - _mouseDownLocation.x) >= 10.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (CGRect)_headerRectOfLastVisibleColumn
|
|
||||||
{
|
|
||||||
var tableColumns = [_tableView tableColumns],
|
|
||||||
columnIndex = [tableColumns count];
|
|
||||||
|
|
||||||
while (columnIndex--)
|
|
||||||
{
|
|
||||||
var tableColumn = [tableColumns objectAtIndex:columnIndex];
|
|
||||||
|
|
||||||
if (![tableColumn isHidden])
|
|
||||||
return [self headerRectOfColumn:columnIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)_constrainDragView:(CPView)theDragView at:(CGPoint)aPoint
|
|
||||||
{
|
|
||||||
var tableColumns = [_tableView tableColumns],
|
|
||||||
lastColumnRect = [self _headerRectOfLastVisibleColumn],
|
|
||||||
activeColumnRect = [self headerRectOfColumn:_activeColumn],
|
|
||||||
dragWindow = [theDragView window],
|
|
||||||
frame = [dragWindow frame];
|
|
||||||
|
|
||||||
// Convert the frame origin from the global coordinate system to the windows' coordinate system
|
|
||||||
frame.origin = [[self window] convertGlobalToBase:frame.origin];
|
|
||||||
// the from the window to the view
|
|
||||||
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)));
|
|
||||||
|
|
||||||
// Make sure the column cannot move vertically
|
|
||||||
frame.origin.y = _CGRectGetMinY(lastColumnRect);
|
|
||||||
|
|
||||||
// Convert the calculated origin back to the window coordinate system
|
|
||||||
frame.origin = [self convertPoint:frame.origin toView:nil];
|
|
||||||
// Then back to the global coordinate system
|
|
||||||
frame.origin = [[self window] convertBaseToGlobal:frame.origin];
|
|
||||||
|
|
||||||
[dragWindow setFrame:frame];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)_moveColumn:(int)aFromIndex toColumn:(int)aToIndex
|
|
||||||
{
|
|
||||||
[_tableView moveColumn:aFromIndex toColumn:aToIndex];
|
|
||||||
_activeColumn = aToIndex;
|
|
||||||
_pressedColumn = _activeColumn;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)draggedView:(CPView)aView beganAt:(CGPoint)aPoint
|
|
||||||
{
|
|
||||||
_isDragging = YES;
|
|
||||||
|
|
||||||
var column = [[_tableView tableColumns] objectAtIndex:_activeColumn];
|
|
||||||
|
|
||||||
[[column headerView] setHidden:YES];
|
|
||||||
[_tableView _setDraggedColumn:column];
|
|
||||||
|
|
||||||
[self setNeedsDisplay:YES];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)draggedView:(CPView)aView movedTo:(CGPoint)aPoint
|
|
||||||
{
|
|
||||||
[self _constrainDragView:aView at:aPoint];
|
|
||||||
|
|
||||||
var dragWindow = [aView window],
|
|
||||||
dragWindowFrame = [dragWindow frame];
|
|
||||||
|
|
||||||
var hoverPoint = CGPointCreateCopy(aPoint);
|
|
||||||
|
|
||||||
if (aPoint.x < _previousTrackingLocation.x)
|
|
||||||
hoverPoint = _CGPointMake(_CGRectGetMinX(dragWindowFrame), _CGRectGetMinY(dragWindowFrame));
|
|
||||||
else if (aPoint.x > _previousTrackingLocation.x)
|
|
||||||
hoverPoint = _CGPointMake(_CGRectGetMaxX(dragWindowFrame), _CGRectGetMinY(dragWindowFrame));
|
|
||||||
|
|
||||||
// Convert the hover point from the global coordinate system to windows' coordinate system
|
|
||||||
hoverPoint = [[self window] convertGlobalToBase:hoverPoint];
|
|
||||||
// then to the view
|
|
||||||
hoverPoint = [self convertPoint:hoverPoint fromView:nil];
|
|
||||||
|
|
||||||
var hoveredColumn = [self columnAtPoint:hoverPoint];
|
|
||||||
|
|
||||||
if (hoveredColumn !== -1)
|
|
||||||
{
|
|
||||||
var columnRect = [self headerRectOfColumn:hoveredColumn],
|
|
||||||
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)
|
|
||||||
[self _moveColumn:_activeColumn toColumn:hoveredColumn];
|
|
||||||
}
|
|
||||||
|
|
||||||
_previousTrackingLocation = aPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)draggedView:(CPImage)aView endedAt:(CGPoint)aLocation operation:(CPDragOperation)anOperation
|
|
||||||
{
|
|
||||||
_isDragging = NO;
|
|
||||||
_isTrackingColumn = NO; // We need to do this explicitly because the mouse up section of trackMouse is never reached
|
|
||||||
|
|
||||||
[_tableView _setDraggedColumn:nil];
|
|
||||||
[[[[_tableView tableColumns] objectAtIndex:_activeColumn] headerView] setHidden:NO];
|
|
||||||
[self stopTrackingTableColumn:_activeColumn at:aLocation];
|
|
||||||
|
|
||||||
[self setNeedsDisplay:YES];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)shouldResizeTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
|
|
||||||
{
|
|
||||||
if (_isResizing)
|
|
||||||
return YES;
|
|
||||||
|
|
||||||
if (_isTrackingColumn)
|
|
||||||
return NO;
|
|
||||||
|
|
||||||
return [_tableView allowsColumnResizing] && _CGRectContainsPoint([self _cursorRectForColumn:aColumnIndex], aPoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)startResizingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
|
|
||||||
{
|
|
||||||
_isResizing = YES;
|
|
||||||
|
|
||||||
var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex];
|
|
||||||
|
|
||||||
[tableColumn setDisableResizingPosting:YES];
|
|
||||||
[_tableView setDisableAutomaticResizing:YES];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)continueResizingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
|
|
||||||
{
|
|
||||||
var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex],
|
|
||||||
newWidth = [tableColumn width] + aPoint.x - _previousTrackingLocation.x;
|
|
||||||
|
|
||||||
if (newWidth < [tableColumn minWidth])
|
|
||||||
[[CPCursor resizeRightCursor] set];
|
|
||||||
else if (newWidth > [tableColumn maxWidth])
|
|
||||||
[[CPCursor resizeLeftCursor] set];
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_tableView._lastColumnShouldSnap = NO;
|
|
||||||
[tableColumn setWidth:newWidth];
|
|
||||||
|
|
||||||
[[CPCursor resizeLeftRightCursor] set];
|
|
||||||
[self setNeedsLayout];
|
|
||||||
[self setNeedsDisplay:YES];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)stopResizingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint
|
|
||||||
{
|
|
||||||
var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex];
|
|
||||||
[tableColumn _postDidResizeNotificationWithOldWidth:_columnOldWidth];
|
|
||||||
[tableColumn setDisableResizingPosting:NO];
|
|
||||||
[_tableView setDisableAutomaticResizing:NO];
|
|
||||||
|
|
||||||
_isResizing = NO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_updateResizeCursor:(CPEvent)theEvent
|
- (void)_updateResizeCursor:(CPEvent)theEvent
|
||||||
@@ -548,15 +345,15 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mouseLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil],
|
var mouseLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil],
|
||||||
mouseOverLocation = CGPointMake(mouseLocation.x - 5, mouseLocation.y),
|
mouseOverLocation = CGPointMake(mouseLocation.x - 5, mouseLocation.y),
|
||||||
overColumn = [self columnAtPoint:mouseOverLocation];
|
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],
|
var tableColumn = [[_tableView tableColumns] objectAtIndex:overColumn],
|
||||||
width = [tableColumn width];
|
width = [tableColumn width];
|
||||||
|
|
||||||
if (width == [tableColumn minWidth])
|
if (width == [tableColumn minWidth])
|
||||||
[[CPCursor resizeRightCursor] set];
|
[[CPCursor resizeRightCursor] set];
|
||||||
else if (width == [tableColumn maxWidth])
|
else if (width == [tableColumn maxWidth])
|
||||||
@@ -568,8 +365,14 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
|
|||||||
[[CPCursor arrowCursor] set];
|
[[CPCursor arrowCursor] set];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)mouseEntered:(CPEvent)theEvent
|
- (void)viewDidMoveToWindow
|
||||||
{
|
{
|
||||||
|
//if ([_tableView allowsColumnResizing])
|
||||||
|
// [[self window] setAcceptsMouseMovedEvents:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mouseEntered:(CPEvent)theEvent
|
||||||
|
{
|
||||||
[self _updateResizeCursor:theEvent];
|
[self _updateResizeCursor:theEvent];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -587,33 +390,31 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
|
|||||||
- (void)layoutSubviews
|
- (void)layoutSubviews
|
||||||
{
|
{
|
||||||
var tableColumns = [_tableView tableColumns],
|
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],
|
var column = [tableColumns objectAtIndex:i],
|
||||||
headerView = [column headerView];
|
headerView = [column headerView];
|
||||||
|
|
||||||
var frame = [self headerRectOfColumn:i];
|
var frame = [self headerRectOfColumn:i];
|
||||||
frame.size.height -= 0.5;
|
frame.size.height -= 0.5;
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
{
|
{
|
||||||
frame.origin.x += 0.5;
|
frame.origin.x += 0.5;
|
||||||
frame.size.width -= 1;
|
frame.size.width -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
[headerView setFrame:frame];
|
[headerView setFrame:frame];
|
||||||
|
|
||||||
if([headerView superview] != self)
|
if([headerView superview] != self)
|
||||||
[self addSubview:headerView];
|
[self addSubview:headerView];
|
||||||
}
|
}
|
||||||
|
|
||||||
[self setBackgroundColor:[self currentValueForThemeAttribute:@"background-color"]];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)drawRect:(CGRect)aRect
|
- (void)drawRect:(CGRect)aRect
|
||||||
{
|
{
|
||||||
if (!_tableView || ![self drawsColumnLines])
|
if (!_tableView)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var context = [[CPGraphicsContext currentContext] graphicsPort],
|
var context = [[CPGraphicsContext currentContext] graphicsPort],
|
||||||
@@ -625,41 +426,55 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
|
|||||||
exposedRange = CPMakeRange(firstIndex, [exposedTableColumns lastIndex] - firstIndex + 1);
|
exposedRange = CPMakeRange(firstIndex, [exposedTableColumns lastIndex] - firstIndex + 1);
|
||||||
|
|
||||||
CGContextSetLineWidth(context, 1);
|
CGContextSetLineWidth(context, 1);
|
||||||
CGContextSetStrokeColor(context, [self currentValueForThemeAttribute:@"divider-color"]);
|
CGContextSetStrokeColor(context, [_tableView gridColor]);
|
||||||
|
|
||||||
[exposedColumnIndexes getIndexes:columnsArray maxCount:-1 inIndexRange:exposedRange];
|
[exposedColumnIndexes getIndexes:columnsArray maxCount:-1 inIndexRange:exposedRange];
|
||||||
|
|
||||||
var columnArrayIndex = 0,
|
var columnArrayIndex = 0,
|
||||||
columnArrayCount = columnsArray.length,
|
columnArrayCount = columnsArray.length,
|
||||||
columnMaxX;
|
columnMaxX;
|
||||||
|
|
||||||
CGContextBeginPath(context);
|
CGContextBeginPath(context);
|
||||||
for(; columnArrayIndex < columnArrayCount; columnArrayIndex++)
|
for(; columnArrayIndex < columnArrayCount; columnArrayIndex++)
|
||||||
{
|
{
|
||||||
// grab each column rect and add vertical lines
|
// grab each column rect and add vertical lines
|
||||||
var columnIndex = columnsArray[columnArrayIndex],
|
var columnIndex = columnsArray[columnArrayIndex],
|
||||||
columnToStroke = [self headerRectOfColumn:columnIndex];
|
columnToStroke = [self headerRectOfColumn:columnIndex];
|
||||||
|
|
||||||
columnMaxX = _CGRectGetMaxX(columnToStroke);
|
columnMaxX = CGRectGetMaxX(columnToStroke);
|
||||||
|
|
||||||
CGContextMoveToPoint(context, ROUND(columnMaxX) + 0.5, ROUND(_CGRectGetMinY(columnToStroke)));
|
CGContextMoveToPoint(context, ROUND(columnMaxX) + 0.5, ROUND(CGRectGetMinY(columnToStroke)));
|
||||||
CGContextAddLineToPoint(context, ROUND(columnMaxX) + 0.5, ROUND(_CGRectGetMaxY(columnToStroke)));
|
CGContextAddLineToPoint(context, ROUND(columnMaxX) + 0.5, ROUND(CGRectGetMaxY(columnToStroke)));
|
||||||
}
|
}
|
||||||
|
|
||||||
CGContextClosePath(context);
|
CGContextClosePath(context);
|
||||||
CGContextStrokePath(context);
|
CGContextStrokePath(context);
|
||||||
|
|
||||||
/*if (_isDragging)
|
/*
|
||||||
|
var maxY = CGRectGetMaxY([self bounds]);
|
||||||
|
// draw normal gradient for remaining space
|
||||||
|
if (supportsCanvasGradient)
|
||||||
{
|
{
|
||||||
CGContextSetFillColor(context, [CPColor grayColor]);
|
aRect.origin.x = columnMaxX - 0.5;
|
||||||
CGContextFillRect(context, [self headerRectOfColumn:_activeColumn])
|
aRect.size.width -= columnMaxX;
|
||||||
}*/
|
CGContextBeginPath(context);
|
||||||
|
CGContextAddRect(context, CGRectMake(columnMaxX + 1, 0, CGRectGetMaxX([self bounds]) - columnMaxX, CGRectGetHeight([self bounds])));
|
||||||
|
CGContextClosePath(context);
|
||||||
|
CGContextDrawLinearGradient(context, [_CPTableColumnHeaderView headerGradient], CGPointMake(0,0), CGPointMake(0, maxY - 1),0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw bottom line
|
||||||
|
CGContextBeginPath(context);
|
||||||
|
CGContextMoveToPoint(context, 0, maxY - 0.5);
|
||||||
|
CGContextAddLineToPoint(context, CGRectGetMaxX([self bounds]), maxY - 0.5);
|
||||||
|
CGContextClosePath(context);
|
||||||
|
CGContextStrokePath(context);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
var CPTableHeaderViewTableViewKey = @"CPTableHeaderViewTableViewKey",
|
var CPTableHeaderViewTableViewKey = @"CPTableHeaderViewTableViewKey";
|
||||||
CPTableHeaderViewDrawsColumnLines = @"CPTableHeaderViewDrawsColumnLines";
|
|
||||||
|
|
||||||
@implementation CPTableHeaderView (CPCoding)
|
@implementation CPTableHeaderView (CPCoding)
|
||||||
|
|
||||||
@@ -669,7 +484,6 @@ var CPTableHeaderViewTableViewKey = @"CPTableHeaderViewTableViewKey",
|
|||||||
{
|
{
|
||||||
[self _init];
|
[self _init];
|
||||||
_tableView = [aCoder decodeObjectForKey:CPTableHeaderViewTableViewKey];
|
_tableView = [aCoder decodeObjectForKey:CPTableHeaderViewTableViewKey];
|
||||||
_drawsColumnLines = [aCoder decodeBoolForKey:CPTableHeaderViewDrawsColumnLines];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
@@ -679,7 +493,7 @@ var CPTableHeaderViewTableViewKey = @"CPTableHeaderViewTableViewKey",
|
|||||||
{
|
{
|
||||||
[super encodeWithCoder:aCoder];
|
[super encodeWithCoder:aCoder];
|
||||||
[aCoder encodeObject:_tableView forKey:CPTableHeaderViewTableViewKey];
|
[aCoder encodeObject:_tableView forKey:CPTableHeaderViewTableViewKey];
|
||||||
[aCoder encodeBool:_drawsColumnLines forKey:CPTableHeaderViewDrawsColumnLines];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
+530
-1043
File diff suppressed because it is too large
Load Diff
@@ -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";
|
|
||||||
+119
-266
@@ -26,6 +26,9 @@
|
|||||||
@import "CPCompatibility.j"
|
@import "CPCompatibility.j"
|
||||||
@import "_CPImageAndTextView.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. */
|
CPTextFieldSquareBezel = 0; /*! A textfield bezel with a squared corners. */
|
||||||
CPTextFieldRoundedBezel = 1; /*! A textfield bezel with rounded corners. */
|
CPTextFieldRoundedBezel = 1; /*! A textfield bezel with rounded corners. */
|
||||||
@@ -46,7 +49,7 @@ var CPTextFieldDOMInputElement = nil,
|
|||||||
CPTextFieldCachedSelectStartFunction = nil,
|
CPTextFieldCachedSelectStartFunction = nil,
|
||||||
CPTextFieldCachedDragFunction = nil,
|
CPTextFieldCachedDragFunction = nil,
|
||||||
CPTextFieldBlurFunction = nil;
|
CPTextFieldBlurFunction = nil;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var CPSecureTextFieldCharacter = "\u2022";
|
var CPSecureTextFieldCharacter = "\u2022";
|
||||||
@@ -77,18 +80,15 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
BOOL _isEditable;
|
BOOL _isEditable;
|
||||||
BOOL _isSelectable;
|
BOOL _isSelectable;
|
||||||
BOOL _isSecure;
|
BOOL _isSecure;
|
||||||
BOOL _willBecomeFirstResponderByClick;
|
|
||||||
|
|
||||||
BOOL _drawsBackground;
|
BOOL _drawsBackground;
|
||||||
|
|
||||||
CPColor _textFieldBackgroundColor;
|
CPColor _textFieldBackgroundColor;
|
||||||
|
|
||||||
id _placeholderString;
|
id _placeholderString;
|
||||||
id _originalPlaceholderString;
|
|
||||||
BOOL _currentValueIsPlaceholder;
|
|
||||||
|
|
||||||
id _delegate;
|
id _delegate;
|
||||||
|
|
||||||
CPString _textDidChangeValue;
|
CPString _textDidChangeValue;
|
||||||
|
|
||||||
// NS-style Display Properties
|
// NS-style Display Properties
|
||||||
@@ -155,7 +155,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
return textField;
|
return textField;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (CPString)defaultThemeClass
|
+ (CPString)themeClass
|
||||||
{
|
{
|
||||||
return "textfield";
|
return "textfield";
|
||||||
}
|
}
|
||||||
@@ -199,7 +199,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
}
|
}
|
||||||
|
|
||||||
CPTextFieldHandleBlur = function(anEvent)
|
CPTextFieldHandleBlur = function(anEvent)
|
||||||
{
|
{
|
||||||
CPTextFieldInputOwner = nil;
|
CPTextFieldInputOwner = nil;
|
||||||
|
|
||||||
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
||||||
@@ -207,10 +207,10 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
|
|
||||||
//FIXME make this not onblur
|
//FIXME make this not onblur
|
||||||
CPTextFieldDOMInputElement.onblur = CPTextFieldBlurFunction;
|
CPTextFieldDOMInputElement.onblur = CPTextFieldBlurFunction;
|
||||||
|
|
||||||
CPTextFieldDOMStandardInputElement = CPTextFieldDOMInputElement;
|
CPTextFieldDOMStandardInputElement = CPTextFieldDOMInputElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CPFeatureIsCompatible(CPInputTypeCanBeChangedFeature))
|
if (CPFeatureIsCompatible(CPInputTypeCanBeChangedFeature))
|
||||||
{
|
{
|
||||||
if ([self isSecure])
|
if ([self isSecure])
|
||||||
@@ -237,14 +237,14 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
|
|
||||||
CPTextFieldDOMPasswordInputElement.onblur = CPTextFieldBlurFunction;
|
CPTextFieldDOMPasswordInputElement.onblur = CPTextFieldBlurFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
CPTextFieldDOMInputElement = CPTextFieldDOMPasswordInputElement;
|
CPTextFieldDOMInputElement = CPTextFieldDOMPasswordInputElement;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CPTextFieldDOMInputElement = CPTextFieldDOMStandardInputElement;
|
CPTextFieldDOMInputElement = CPTextFieldDOMStandardInputElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CPTextFieldDOMInputElement;
|
return CPTextFieldDOMInputElement;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -262,29 +262,18 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
|
|
||||||
[self setValue:CPLeftTextAlignment forThemeAttribute:@"alignment"];
|
[self setValue:CPLeftTextAlignment forThemeAttribute:@"alignment"];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark Controlling Editability and Selectability
|
#pragma mark Controlling Editability and Selectability
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Sets whether or not the receiver text field can be edited. If NO, any
|
Sets whether or not the receiver text field can be edited
|
||||||
ongoing edit is ended.
|
|
||||||
*/
|
*/
|
||||||
- (void)setEditable:(BOOL)shouldBeEditable
|
- (void)setEditable:(BOOL)shouldBeEditable
|
||||||
{
|
{
|
||||||
if (_isEditable === shouldBeEditable)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_isEditable = shouldBeEditable;
|
_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;
|
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.
|
Sets whether the field's text is selectable by the user.
|
||||||
@param aFlag \c YES makes the text selectable
|
@param aFlag \c YES makes the text selectable
|
||||||
@@ -370,7 +346,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
- (void)setBezelStyle:(CPTextFieldBezelStyle)aBezelStyle
|
- (void)setBezelStyle:(CPTextFieldBezelStyle)aBezelStyle
|
||||||
{
|
{
|
||||||
var shouldBeRounded = aBezelStyle === CPTextFieldRoundedBezel;
|
var shouldBeRounded = aBezelStyle === CPTextFieldRoundedBezel;
|
||||||
|
|
||||||
if (shouldBeRounded)
|
if (shouldBeRounded)
|
||||||
[self setThemeState:CPTextFieldStateRounded];
|
[self setThemeState:CPTextFieldStateRounded];
|
||||||
else
|
else
|
||||||
@@ -416,9 +392,9 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
{
|
{
|
||||||
if (_drawsBackground == shouldDrawBackground)
|
if (_drawsBackground == shouldDrawBackground)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_drawsBackground = shouldDrawBackground;
|
_drawsBackground = shouldDrawBackground;
|
||||||
|
|
||||||
[self setNeedsLayout];
|
[self setNeedsLayout];
|
||||||
[self setNeedsDisplay:YES];
|
[self setNeedsDisplay:YES];
|
||||||
}
|
}
|
||||||
@@ -439,9 +415,9 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
{
|
{
|
||||||
if (_textFieldBackgroundColor == aColor)
|
if (_textFieldBackgroundColor == aColor)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_textFieldBackgroundColor = aColor;
|
_textFieldBackgroundColor = aColor;
|
||||||
|
|
||||||
[self setNeedsLayout];
|
[self setNeedsLayout];
|
||||||
[self setNeedsDisplay:YES];
|
[self setNeedsDisplay:YES];
|
||||||
}
|
}
|
||||||
@@ -504,31 +480,24 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
|
|
||||||
_DOMElement.appendChild(element);
|
_DOMElement.appendChild(element);
|
||||||
|
|
||||||
window.setTimeout(function()
|
window.setTimeout(function()
|
||||||
{
|
{
|
||||||
element.focus();
|
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]];
|
[self textDidFocus:[CPNotification notificationWithName:CPTextFieldDidFocusNotification object:self userInfo:nil]];
|
||||||
CPTextFieldInputOwner = self;
|
CPTextFieldInputOwner = self;
|
||||||
}, 0.0);
|
}, 0.0);
|
||||||
|
|
||||||
element.value = [self stringValue];
|
element.value = [self stringValue];
|
||||||
|
|
||||||
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
|
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
|
||||||
|
|
||||||
CPTextFieldInputIsActive = YES;
|
CPTextFieldInputIsActive = YES;
|
||||||
|
|
||||||
if (document.attachEvent)
|
if (document.attachEvent)
|
||||||
{
|
{
|
||||||
CPTextFieldCachedSelectStartFunction = [[self window] platformWindow]._DOMBodyElement.onselectstart;
|
CPTextFieldCachedSelectStartFunction = [[self window] platformWindow]._DOMBodyElement.onselectstart;
|
||||||
CPTextFieldCachedDragFunction = [[self window] platformWindow]._DOMBodyElement.ondrag;
|
CPTextFieldCachedDragFunction = [[self window] platformWindow]._DOMBodyElement.ondrag;
|
||||||
|
|
||||||
[[self window] platformWindow]._DOMBodyElement.ondrag = function () {};
|
[[self window] platformWindow]._DOMBodyElement.ondrag = function () {};
|
||||||
[[self window] platformWindow]._DOMBodyElement.onselectstart = function () {};
|
[[self window] platformWindow]._DOMBodyElement.onselectstart = function () {};
|
||||||
}
|
}
|
||||||
@@ -550,15 +519,14 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
|
|
||||||
var element = [self _inputElement];
|
var element = [self _inputElement];
|
||||||
|
|
||||||
if ([self stringValue] !== element.value)
|
[self setObjectValue:element.value];
|
||||||
[self _setStringValue:element.value];
|
|
||||||
|
|
||||||
CPTextFieldInputResigning = YES;
|
CPTextFieldInputResigning = YES;
|
||||||
element.blur();
|
element.blur();
|
||||||
|
|
||||||
if (!CPTextFieldInputDidBlur)
|
if (!CPTextFieldInputDidBlur)
|
||||||
CPTextFieldBlurFunction();
|
CPTextFieldBlurFunction();
|
||||||
|
|
||||||
CPTextFieldInputDidBlur = NO;
|
CPTextFieldInputDidBlur = NO;
|
||||||
CPTextFieldInputResigning = NO;
|
CPTextFieldInputResigning = NO;
|
||||||
|
|
||||||
@@ -569,13 +537,13 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
|
|
||||||
if (document.attachEvent)
|
if (document.attachEvent)
|
||||||
{
|
{
|
||||||
[[self window] platformWindow]._DOMBodyElement.ondrag = CPTextFieldCachedDragFunction;
|
|
||||||
[[self window] platformWindow]._DOMBodyElement.onselectstart = CPTextFieldCachedSelectStartFunction;
|
|
||||||
|
|
||||||
CPTextFieldCachedSelectStartFunction = nil;
|
CPTextFieldCachedSelectStartFunction = nil;
|
||||||
CPTextFieldCachedDragFunction = nil;
|
CPTextFieldCachedDragFunction = nil;
|
||||||
|
|
||||||
|
[[self window] platformWindow]._DOMBodyElement.ondrag = CPTextFieldCachedDragFunction;
|
||||||
|
[[self window] platformWindow]._DOMBodyElement.onselectstart = CPTextFieldCachedSelectStartFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//post CPControlTextDidEndEditingNotification
|
//post CPControlTextDidEndEditingNotification
|
||||||
@@ -605,50 +573,21 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
{
|
{
|
||||||
// Don't track! (ever?)
|
// Don't track! (ever?)
|
||||||
if ([self isEditable] && [self isEnabled])
|
if ([self isEditable] && [self isEnabled])
|
||||||
{
|
return [[self window] makeFirstResponder:self];
|
||||||
_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];
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
return [[self nextResponder] mouseDown:anEvent];
|
return [[self nextResponder] mouseDown:anEvent];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)mouseUp:(CPEvent)anEvent
|
- (void)mouseUp:(CPEvent)anEvent
|
||||||
{
|
{
|
||||||
if (![self isSelectable] && (![self isEditable] || ![self isEnabled]))
|
if (![self isEditable] || ![self isEnabled])
|
||||||
[[self nextResponder] mouseUp:anEvent];
|
[[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
|
- (void)mouseDragged:(CPEvent)anEvent
|
||||||
{
|
{
|
||||||
if (![self isSelectable] && (![self isEditable] || ![self isEnabled]))
|
if (![self isEditable] || ![self isEnabled])
|
||||||
[[self nextResponder] mouseDragged:anEvent];
|
[[self nextResponder] mouseDragged:anEvent];
|
||||||
else if ([self isSelectable])
|
|
||||||
return [[[anEvent window] platformWindow] _propagateCurrentDOMEvent:YES];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)keyUp:(CPEvent)anEvent
|
- (void)keyUp:(CPEvent)anEvent
|
||||||
@@ -685,16 +624,29 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
|
|
||||||
[[[self window] platformWindow] _propagateCurrentDOMEvent:NO];
|
[[[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
|
else
|
||||||
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
|
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
|
||||||
|
|
||||||
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (void)textDidBlur:(CPNotification)note
|
- (void)textDidBlur:(CPNotification)note
|
||||||
{
|
{
|
||||||
// this looks to prevent false propagation of notifications for other objects
|
//this looks to prevent false propagation of notifications for other objects
|
||||||
if ([note object] != self)
|
if([note object] != self)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[[CPNotificationCenter defaultCenter] postNotification:note];
|
[[CPNotificationCenter defaultCenter] postNotification:note];
|
||||||
@@ -702,22 +654,13 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
|
|
||||||
- (void)textDidFocus:(CPNotification)note
|
- (void)textDidFocus:(CPNotification)note
|
||||||
{
|
{
|
||||||
// this looks to prevent false propagation of notifications for other objects
|
//this looks to prevent false propagation of notifications for other objects
|
||||||
if ([note object] != self)
|
if([note object] != self)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[[CPNotificationCenter defaultCenter] postNotification:note];
|
[[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.
|
Returns the string the text field.
|
||||||
*/
|
*/
|
||||||
@@ -740,7 +683,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
- (void)setObjectValue:(id)aValue
|
- (void)setObjectValue:(id)aValue
|
||||||
{
|
{
|
||||||
[super setObjectValue:aValue];
|
[super setObjectValue:aValue];
|
||||||
|
|
||||||
#if PLATFORM(DOM)
|
#if PLATFORM(DOM)
|
||||||
|
|
||||||
if (CPTextFieldInputOwner === self || [[self window] firstResponder] === self)
|
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,
|
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
|
and after editing ends, if the text field has an empty string value
|
||||||
*/
|
*/
|
||||||
- (void)setPlaceholderString:(CPString)aStringValue
|
-(void)setPlaceholderString:(CPString)aStringValue
|
||||||
{
|
{
|
||||||
if (_placeholderString === aStringValue)
|
if (_placeholderString === aStringValue)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_placeholderString = aStringValue;
|
_placeholderString = aStringValue;
|
||||||
|
|
||||||
// Only update things if we need to show the placeholder
|
// Only update things if we need to show the placeholder
|
||||||
@@ -787,101 +730,43 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
return _placeholderString;
|
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
|
Size to fit has two behavior, depending on if the receiver is an editable text field or not.
|
||||||
on the line break mode of the receiver.
|
|
||||||
|
For non-editable text fields (typically, a label), sizeToFit will change the frame of the
|
||||||
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, and respecting
|
||||||
receiver to perfectly fit the current text in stringValue in the current font, respecting
|
the current theme values for content-inset, min-size, and max-size.
|
||||||
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),
|
For editable text fields, sizeToFit will ONLY change the HEIGHT of the text field. It will not
|
||||||
so it will ONLY change the HEIGHT.
|
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:].
|
||||||
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.
|
|
||||||
|
|
||||||
The logic behind this decision is that most of the time you do not know what content will be placed
|
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
|
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.
|
useful for making the textfield an appropriate height.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
- (void)sizeToFit
|
- (void)sizeToFit
|
||||||
{
|
{
|
||||||
[self setFrameSize:[self _minimumFrameSize]];
|
var size = [([self stringValue] || " ") sizeWithFont:[self currentValueForThemeAttribute:@"font"]],
|
||||||
}
|
|
||||||
|
|
||||||
- (CGSize)_minimumFrameSize
|
|
||||||
{
|
|
||||||
var frameSize = [self frameSize],
|
|
||||||
contentInset = [self currentValueForThemeAttribute:@"content-inset"],
|
contentInset = [self currentValueForThemeAttribute:@"content-inset"],
|
||||||
minSize = [self currentValueForThemeAttribute:@"min-size"],
|
minSize = [self currentValueForThemeAttribute:@"min-size"],
|
||||||
maxSize = [self currentValueForThemeAttribute:@"max-size"],
|
maxSize = [self currentValueForThemeAttribute:@"max-size"];
|
||||||
lineBreakMode = [self lineBreakMode],
|
|
||||||
text = ([self stringValue] || @" "),
|
|
||||||
textSize = _CGSizeMakeCopy(frameSize),
|
|
||||||
font = [self currentValueForThemeAttribute:@"font"];
|
|
||||||
|
|
||||||
textSize.width -= contentInset.left + contentInset.right;
|
size.width = MAX(size.width + contentInset.left + contentInset.right, minSize.width);
|
||||||
textSize.height -= contentInset.top + contentInset.bottom;
|
size.height = MAX(size.height + contentInset.top + contentInset.bottom, minSize.height);
|
||||||
|
|
||||||
if (frameSize.width !== 0 &&
|
if (maxSize.width >= 0.0)
|
||||||
![self isBezeled] &&
|
size.width = MIN(size.width, maxSize.width);
|
||||||
(lineBreakMode === CPLineBreakByWordWrapping || lineBreakMode === CPLineBreakByCharWrapping))
|
|
||||||
{
|
|
||||||
textSize = [text sizeWithFont:font inWidth:textSize.width];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
textSize = [text sizeWithFont:font];
|
|
||||||
|
|
||||||
frameSize.height = textSize.height + contentInset.top + contentInset.bottom;
|
if (maxSize.height >= 0.0)
|
||||||
|
size.height = MIN(size.height, maxSize.height);
|
||||||
|
|
||||||
if ([self isBezeled])
|
if ([self isEditable])
|
||||||
{
|
size.width = CGRectGetWidth([self frame]);
|
||||||
frameSize.height = MAX(frameSize.height, minSize.height);
|
|
||||||
|
|
||||||
if (maxSize.width > 0.0)
|
[self setFrameSize:size];
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -891,13 +776,16 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
{
|
{
|
||||||
#if PLATFORM(DOM)
|
#if PLATFORM(DOM)
|
||||||
var element = [self _inputElement];
|
var element = [self _inputElement];
|
||||||
|
|
||||||
if (([self isEditable] || [self isSelectable]))
|
if (([self isEditable] || [self isSelectable]))
|
||||||
{
|
{
|
||||||
if ([[self window] firstResponder] === self)
|
if ([[self window] firstResponder] === self)
|
||||||
window.setTimeout(function() { element.select(); }, 0);
|
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);
|
window.setTimeout(function() {[self selectText:sender];}, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -946,7 +834,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
newValue = [stringValue stringByReplacingCharactersInRange:selectedRange withString:pasteString];
|
newValue = [stringValue stringByReplacingCharactersInRange:selectedRange withString:pasteString];
|
||||||
|
|
||||||
[self setStringValue:newValue];
|
[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);
|
return CPMakeRange(0, 0);
|
||||||
|
|
||||||
// we wrap this in try catch because firefox will throw an exception in certain instances
|
// we wrap this in try catch because firefox will throw an exception in certain instances
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var inputElement = [self _inputElement],
|
var inputElement = [self _inputElement],
|
||||||
selectionStart = inputElement.selectionStart,
|
selectionStart = inputElement.selectionStart,
|
||||||
selectionEnd = inputElement.selectionEnd;
|
selectionEnd = inputElement.selectionEnd;
|
||||||
|
|
||||||
if ([selectionStart isKindOfClass:CPNumber])
|
if ([selectionStart isKindOfClass:CPNumber])
|
||||||
return CPMakeRange(selectionStart, selectionEnd - selectionStart);
|
return CPMakeRange(selectionStart, selectionEnd - selectionStart);
|
||||||
|
|
||||||
// browsers which don't support selectionStart/selectionEnd (aka IE).
|
// browsers which don't support selectionStart/selectionEnd (aka IE).
|
||||||
var theDocument = inputElement.ownerDocument || inputElement.document,
|
var theDocument = inputElement.ownerDocument || inputElement.document,
|
||||||
@@ -975,8 +863,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
range.setEndPoint('EndToStart', selectionRange);
|
range.setEndPoint('EndToStart', selectionRange);
|
||||||
return CPMakeRange(range.text.length, selectionRange.text.length);
|
return CPMakeRange(range.text.length, selectionRange.text.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e)
|
catch (e)
|
||||||
{
|
{
|
||||||
// fall through to the return
|
// fall through to the return
|
||||||
}
|
}
|
||||||
@@ -991,7 +879,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
|
|
||||||
var inputElement = [self _inputElement];
|
var inputElement = [self _inputElement];
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if ([inputElement.selectionStart isKindOfClass:CPNumber])
|
if ([inputElement.selectionStart isKindOfClass:CPNumber])
|
||||||
{
|
{
|
||||||
@@ -1004,7 +892,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
var theDocument = inputElement.ownerDocument || inputElement.document,
|
var theDocument = inputElement.ownerDocument || inputElement.document,
|
||||||
existingRange = theDocument.selection.createRange(),
|
existingRange = theDocument.selection.createRange(),
|
||||||
range = inputElement.createTextRange();
|
range = inputElement.createTextRange();
|
||||||
|
|
||||||
if (range.inRange(existingRange))
|
if (range.inRange(existingRange))
|
||||||
{
|
{
|
||||||
range.collapse(true);
|
range.collapse(true);
|
||||||
@@ -1039,7 +927,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
- (void)setDelegate:(id)aDelegate
|
- (void)setDelegate:(id)aDelegate
|
||||||
{
|
{
|
||||||
var defaultCenter = [CPNotificationCenter defaultCenter];
|
var defaultCenter = [CPNotificationCenter defaultCenter];
|
||||||
|
|
||||||
//unsubscribe the existing delegate if it exists
|
//unsubscribe the existing delegate if it exists
|
||||||
if (_delegate)
|
if (_delegate)
|
||||||
{
|
{
|
||||||
@@ -1049,24 +937,24 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
[defaultCenter removeObserver:_delegate name:CPTextFieldDidFocusNotification object:self];
|
[defaultCenter removeObserver:_delegate name:CPTextFieldDidFocusNotification object:self];
|
||||||
[defaultCenter removeObserver:_delegate name:CPTextFieldDidBlurNotification object:self];
|
[defaultCenter removeObserver:_delegate name:CPTextFieldDidBlurNotification object:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
_delegate = aDelegate;
|
_delegate = aDelegate;
|
||||||
|
|
||||||
if ([_delegate respondsToSelector:@selector(controlTextDidBeginEditing:)])
|
if ([_delegate respondsToSelector:@selector(controlTextDidBeginEditing:)])
|
||||||
[defaultCenter
|
[defaultCenter
|
||||||
addObserver:_delegate
|
addObserver:_delegate
|
||||||
selector:@selector(controlTextDidBeginEditing:)
|
selector:@selector(controlTextDidBeginEditing:)
|
||||||
name:CPControlTextDidBeginEditingNotification
|
name:CPControlTextDidBeginEditingNotification
|
||||||
object:self];
|
object:self];
|
||||||
|
|
||||||
if ([_delegate respondsToSelector:@selector(controlTextDidChange:)])
|
if ([_delegate respondsToSelector:@selector(controlTextDidChange:)])
|
||||||
[defaultCenter
|
[defaultCenter
|
||||||
addObserver:_delegate
|
addObserver:_delegate
|
||||||
selector:@selector(controlTextDidChange:)
|
selector:@selector(controlTextDidChange:)
|
||||||
name:CPControlTextDidChangeNotification
|
name:CPControlTextDidChangeNotification
|
||||||
object:self];
|
object:self];
|
||||||
|
|
||||||
|
|
||||||
if ([_delegate respondsToSelector:@selector(controlTextDidEndEditing:)])
|
if ([_delegate respondsToSelector:@selector(controlTextDidEndEditing:)])
|
||||||
[defaultCenter
|
[defaultCenter
|
||||||
addObserver:_delegate
|
addObserver:_delegate
|
||||||
@@ -1097,30 +985,30 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
- (CGRect)contentRectForBounds:(CGRect)bounds
|
- (CGRect)contentRectForBounds:(CGRect)bounds
|
||||||
{
|
{
|
||||||
var contentInset = [self currentValueForThemeAttribute:@"content-inset"];
|
var contentInset = [self currentValueForThemeAttribute:@"content-inset"];
|
||||||
|
|
||||||
if (!contentInset)
|
if (!contentInset)
|
||||||
return bounds;
|
return bounds;
|
||||||
|
|
||||||
bounds.origin.x += contentInset.left;
|
bounds.origin.x += contentInset.left;
|
||||||
bounds.origin.y += contentInset.top;
|
bounds.origin.y += contentInset.top;
|
||||||
bounds.size.width -= contentInset.left + contentInset.right;
|
bounds.size.width -= contentInset.left + contentInset.right;
|
||||||
bounds.size.height -= contentInset.top + contentInset.bottom;
|
bounds.size.height -= contentInset.top + contentInset.bottom;
|
||||||
|
|
||||||
return bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGRect)bezelRectForBounds:(CGRect)bounds
|
- (CGRect)bezelRectForBounds:(CFRect)bounds
|
||||||
{
|
{
|
||||||
var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"];
|
var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"];
|
||||||
|
|
||||||
if (_CGInsetIsEmpty(bezelInset))
|
if (_CGInsetIsEmpty(bezelInset))
|
||||||
return bounds;
|
return bounds;
|
||||||
|
|
||||||
bounds.origin.x += bezelInset.left;
|
bounds.origin.x += bezelInset.left;
|
||||||
bounds.origin.y += bezelInset.top;
|
bounds.origin.y += bezelInset.top;
|
||||||
bounds.size.width -= bezelInset.left + bezelInset.right;
|
bounds.size.width -= bezelInset.left + bezelInset.right;
|
||||||
bounds.size.height -= bezelInset.top + bezelInset.bottom;
|
bounds.size.height -= bezelInset.top + bezelInset.bottom;
|
||||||
|
|
||||||
return bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1128,10 +1016,10 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
{
|
{
|
||||||
if (aName === "bezel-view")
|
if (aName === "bezel-view")
|
||||||
return [self bezelRectForBounds:[self bounds]];
|
return [self bezelRectForBounds:[self bounds]];
|
||||||
|
|
||||||
else if (aName === "content-view")
|
else if (aName === "content-view")
|
||||||
return [self contentRectForBounds:[self bounds]];
|
return [self contentRectForBounds:[self bounds]];
|
||||||
|
|
||||||
return [super rectForEphemeralSubviewNamed:aName];
|
return [super rectForEphemeralSubviewNamed:aName];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1142,19 +1030,19 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
|
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
|
||||||
|
|
||||||
[view setHitTests:NO];
|
[view setHitTests:NO];
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var view = [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
|
var view = [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
|
||||||
//[view setImagePosition:CPNoImage];
|
//[view setImagePosition:CPNoImage];
|
||||||
|
|
||||||
[view setHitTests:NO];
|
[view setHitTests:NO];
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [super createEphemeralSubviewNamed:aName];
|
return [super createEphemeralSubviewNamed:aName];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1163,10 +1051,10 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
var bezelView = [self layoutEphemeralSubviewNamed:@"bezel-view"
|
var bezelView = [self layoutEphemeralSubviewNamed:@"bezel-view"
|
||||||
positioned:CPWindowBelow
|
positioned:CPWindowBelow
|
||||||
relativeToEphemeralSubviewNamed:@"content-view"];
|
relativeToEphemeralSubviewNamed:@"content-view"];
|
||||||
|
|
||||||
if (bezelView)
|
if (bezelView)
|
||||||
[bezelView setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]];
|
[bezelView setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]];
|
||||||
|
|
||||||
var contentView = [self layoutEphemeralSubviewNamed:@"content-view"
|
var contentView = [self layoutEphemeralSubviewNamed:@"content-view"
|
||||||
positioned:CPWindowAbove
|
positioned:CPWindowAbove
|
||||||
relativeToEphemeralSubviewNamed:@"bezel-view"];
|
relativeToEphemeralSubviewNamed:@"bezel-view"];
|
||||||
@@ -1176,7 +1064,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
[contentView setHidden:[self hasThemeState:CPThemeStateEditing]];
|
[contentView setHidden:[self hasThemeState:CPThemeStateEditing]];
|
||||||
|
|
||||||
var string = "";
|
var string = "";
|
||||||
|
|
||||||
if ([self hasThemeState:CPTextFieldStatePlaceholder])
|
if ([self hasThemeState:CPTextFieldStatePlaceholder])
|
||||||
string = [self placeholderString];
|
string = [self placeholderString];
|
||||||
else
|
else
|
||||||
@@ -1199,22 +1087,6 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)takeValueFromKeyPath:(CPString)aKeyPath ofObjects:(CPArray)objects
|
|
||||||
{
|
|
||||||
var count = objects.length,
|
|
||||||
value = [objects[0] valueForKeyPath:aKeyPath];
|
|
||||||
|
|
||||||
[self setStringValue:value];
|
|
||||||
[self setPlaceholderString:@""];
|
|
||||||
|
|
||||||
while (count-- > 1)
|
|
||||||
if (value !== [objects[count] valueForKeyPath:aKeyPath])
|
|
||||||
{
|
|
||||||
[self setPlaceholderString:@"Multiple Values"];
|
|
||||||
[self setStringValue:@""];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
var secureStringForString = function(aString)
|
var secureStringForString = function(aString)
|
||||||
@@ -1223,7 +1095,7 @@ var secureStringForString = function(aString)
|
|||||||
if (!aString)
|
if (!aString)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
return Array(aString.length + 1).join(CPSecureTextFieldCharacter);
|
return Array(aString.length+1).join(CPSecureTextFieldCharacter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1234,7 +1106,6 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
|
|||||||
CPTextFieldBezelStyleKey = "CPTextFieldBezelStyleKey",
|
CPTextFieldBezelStyleKey = "CPTextFieldBezelStyleKey",
|
||||||
CPTextFieldDrawsBackgroundKey = "CPTextFieldDrawsBackgroundKey",
|
CPTextFieldDrawsBackgroundKey = "CPTextFieldDrawsBackgroundKey",
|
||||||
CPTextFieldLineBreakModeKey = "CPTextFieldLineBreakModeKey",
|
CPTextFieldLineBreakModeKey = "CPTextFieldLineBreakModeKey",
|
||||||
CPTextFieldAlignmentKey = "CPTextFieldAlignmentKey",
|
|
||||||
CPTextFieldBackgroundColorKey = "CPTextFieldBackgroundColorKey",
|
CPTextFieldBackgroundColorKey = "CPTextFieldBackgroundColorKey",
|
||||||
CPTextFieldPlaceholderStringKey = "CPTextFieldPlaceholderStringKey";
|
CPTextFieldPlaceholderStringKey = "CPTextFieldPlaceholderStringKey";
|
||||||
|
|
||||||
@@ -1248,7 +1119,7 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
|
|||||||
- (id)initWithCoder:(CPCoder)aCoder
|
- (id)initWithCoder:(CPCoder)aCoder
|
||||||
{
|
{
|
||||||
self = [super initWithCoder:aCoder];
|
self = [super initWithCoder:aCoder];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
[self setEditable:[aCoder decodeBoolForKey:CPTextFieldIsEditableKey]];
|
[self setEditable:[aCoder decodeBoolForKey:CPTextFieldIsEditableKey]];
|
||||||
@@ -1258,24 +1129,9 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
|
|||||||
|
|
||||||
[self setTextFieldBackgroundColor:[aCoder decodeObjectForKey:CPTextFieldBackgroundColorKey]];
|
[self setTextFieldBackgroundColor:[aCoder decodeObjectForKey:CPTextFieldBackgroundColorKey]];
|
||||||
|
|
||||||
[self setLineBreakMode:[aCoder decodeIntForKey:CPTextFieldLineBreakModeKey]];
|
|
||||||
[self setAlignment:[aCoder decodeIntForKey:CPTextFieldAlignmentKey]];
|
|
||||||
|
|
||||||
[self setPlaceholderString:[aCoder decodeObjectForKey:CPTextFieldPlaceholderStringKey]];
|
[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;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1286,17 +1142,14 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
|
|||||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||||
{
|
{
|
||||||
[super encodeWithCoder:aCoder];
|
[super encodeWithCoder:aCoder];
|
||||||
|
|
||||||
[aCoder encodeBool:_isEditable forKey:CPTextFieldIsEditableKey];
|
[aCoder encodeBool:_isEditable forKey:CPTextFieldIsEditableKey];
|
||||||
[aCoder encodeBool:_isSelectable forKey:CPTextFieldIsSelectableKey];
|
[aCoder encodeBool:_isSelectable forKey:CPTextFieldIsSelectableKey];
|
||||||
|
|
||||||
[aCoder encodeBool:_drawsBackground forKey:CPTextFieldDrawsBackgroundKey];
|
[aCoder encodeBool:_drawsBackground forKey:CPTextFieldDrawsBackgroundKey];
|
||||||
|
|
||||||
[aCoder encodeObject:_textFieldBackgroundColor forKey:CPTextFieldBackgroundColorKey];
|
[aCoder encodeObject:_textFieldBackgroundColor forKey:CPTextFieldBackgroundColorKey];
|
||||||
|
|
||||||
[aCoder encodeInt:[self lineBreakMode] forKey:CPTextFieldLineBreakModeKey];
|
|
||||||
[aCoder encodeInt:[self alignment] forKey:CPTextFieldAlignmentKey];
|
|
||||||
|
|
||||||
[aCoder encodeObject:_placeholderString forKey:CPTextFieldPlaceholderStringKey];
|
[aCoder encodeObject:_placeholderString forKey:CPTextFieldPlaceholderStringKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+20
-188
@@ -24,10 +24,8 @@
|
|||||||
@import <Foundation/CPString.j>
|
@import <Foundation/CPString.j>
|
||||||
@import <Foundation/CPKeyedUnarchiver.j>
|
@import <Foundation/CPKeyedUnarchiver.j>
|
||||||
|
|
||||||
|
var CPThemesByName = { },
|
||||||
var CPThemesByName = { },
|
CPThemeDefaultTheme = nil;
|
||||||
CPThemeDefaultTheme = nil,
|
|
||||||
CPThemeDefaultHudTheme = nil;
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -50,27 +48,6 @@ var CPThemesByName = { },
|
|||||||
return CPThemeDefaultTheme;
|
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
|
+ (CPTheme)themeNamed:(CPString)aName
|
||||||
{
|
{
|
||||||
return CPThemesByName[aName];
|
return CPThemesByName[aName];
|
||||||
@@ -96,110 +73,9 @@ var CPThemesByName = { },
|
|||||||
return _name;
|
return _name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
- (_CPThemeAttribute)_attributeWithName:(CPString)aName forClass:(CPString)aClass
|
||||||
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
|
|
||||||
{
|
{
|
||||||
return [_attributes allKeys];
|
var attributes = [_attributes objectForKey:aClass];
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
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];
|
|
||||||
|
|
||||||
if (!attributes)
|
if (!attributes)
|
||||||
return nil;
|
return nil;
|
||||||
@@ -207,53 +83,12 @@ var CPThemesByName = { },
|
|||||||
return [attributes objectForKey:aName];
|
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
|
- (void)takeThemeFromObject:(id)anObject
|
||||||
{
|
{
|
||||||
var attributes = [anObject _themeAttributeDictionary],
|
var attributes = [anObject _themeAttributeDictionary],
|
||||||
attributeName = nil,
|
attributeName = nil,
|
||||||
attributeNames = [attributes keyEnumerator],
|
attributeNames = [attributes keyEnumerator],
|
||||||
objectThemeClass = [anObject themeClass];
|
objectThemeClass = [[anObject class] themeClass];
|
||||||
|
|
||||||
while (attributeName = [attributeNames nextObject])
|
while (attributeName = [attributeNames nextObject])
|
||||||
[self _recordAttribute:[attributes objectForKey:attributeName] forClass:objectThemeClass];
|
[self _recordAttribute:[attributes objectForKey:attributeName] forClass:objectThemeClass];
|
||||||
@@ -407,9 +242,6 @@ CPThemeStateNormal = CPThemeStates["normal"] = 0;
|
|||||||
CPThemeStateDisabled = CPThemeState("disabled");
|
CPThemeStateDisabled = CPThemeState("disabled");
|
||||||
CPThemeStateHighlighted = CPThemeState("highlighted");
|
CPThemeStateHighlighted = CPThemeState("highlighted");
|
||||||
CPThemeStateSelected = CPThemeState("selected");
|
CPThemeStateSelected = CPThemeState("selected");
|
||||||
CPThemeStateTableDataView = CPThemeState("tableDataView");
|
|
||||||
CPThemeStateSelectedDataView = CPThemeStateSelectedTableDataView = CPThemeState("selectedTableDataView");
|
|
||||||
CPThemeStateGroupRow = CPThemeState("CPThemeStateGroupRow");
|
|
||||||
CPThemeStateBezeled = CPThemeState("bezeled");
|
CPThemeStateBezeled = CPThemeState("bezeled");
|
||||||
CPThemeStateBordered = CPThemeState("bordered");
|
CPThemeStateBordered = CPThemeState("bordered");
|
||||||
CPThemeStateEditable = CPThemeState("editable");
|
CPThemeStateEditable = CPThemeState("editable");
|
||||||
@@ -422,10 +254,10 @@ CPThemeStateCircular = CPThemeState("circular");
|
|||||||
{
|
{
|
||||||
CPString _name;
|
CPString _name;
|
||||||
id _defaultValue;
|
id _defaultValue;
|
||||||
CPDictionary _values @accessors(readonly, getter=values);
|
CPDictionary _values;
|
||||||
|
|
||||||
JSObject _cache;
|
JSObject _cache;
|
||||||
_CPThemeAttribute _parentAttribute;
|
CPThemeAttribute _parentAttribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithName:(CPString)aName defaultValue:(id)aDefaultValue
|
- (id)initWithName:(CPString)aName defaultValue:(id)aDefaultValue
|
||||||
@@ -546,7 +378,7 @@ CPThemeStateCircular = CPThemeState("circular");
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setParentAttribute:(_CPThemeAttribute)anAttribute
|
- (void)setParentAttribute:(CPThemeAttribute)anAttribute
|
||||||
{
|
{
|
||||||
if (_parentAttribute === anAttribute)
|
if (_parentAttribute === anAttribute)
|
||||||
return;
|
return;
|
||||||
@@ -555,7 +387,7 @@ CPThemeStateCircular = CPThemeState("circular");
|
|||||||
_parentAttribute = anAttribute;
|
_parentAttribute = anAttribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (_CPThemeAttribute)attributeMergedWithAttribute:(_CPThemeAttribute)anAttribute
|
- (CPThemeAttribute)attributeMergedWithAttribute:(_CPThemeAttribute)anAttribute
|
||||||
{
|
{
|
||||||
var mergedAttribute = [[_CPThemeAttribute alloc] initWithName:_name defaultValue:_defaultValue];
|
var mergedAttribute = [[_CPThemeAttribute alloc] initWithName:_name defaultValue:_defaultValue];
|
||||||
|
|
||||||
@@ -640,15 +472,15 @@ CPThemeStateCircular = CPThemeState("circular");
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
var cachedNumberOfOnes = [ 0 /*000000*/, 1 /*000001*/, 1 /*000010*/, 2 /*000011*/, 1 /*000100*/, 2 /*000101*/, 2 /*000110*/,
|
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 /*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 /*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 /*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 /*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 /*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 /*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 /*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*/,
|
3 /*111000*/, 4 /*111001*/, 4 /*111010*/, 5 /*111011*/, 4 /*111100*/, 5 /*111101*/, 5 /*111110*/,
|
||||||
6 /*111111*/ ];
|
6 /*111111*/ ];
|
||||||
|
|
||||||
var numberOfOnes = function(aNumber)
|
var numberOfOnes = function(aNumber)
|
||||||
@@ -719,7 +551,7 @@ function CPThemeAttributeDecode(aCoder, anAttributeName, aDefaultValue, aTheme,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (aTheme && aClass)
|
if (aTheme && aClass)
|
||||||
[attribute setParentAttribute:[aTheme attributeWithName:anAttributeName forClass:aClass]];
|
[attribute setParentAttribute:[aTheme _attributeWithName:anAttributeName forClass:aClass]];
|
||||||
|
|
||||||
return attribute;
|
return attribute;
|
||||||
}
|
}
|
||||||
@@ -753,4 +585,4 @@ for (i = 0;i < Math.pow(2,6);++i)
|
|||||||
}
|
}
|
||||||
print(str+']');
|
print(str+']');
|
||||||
|
|
||||||
*/
|
*/
|
||||||
+10
-34
@@ -22,10 +22,9 @@
|
|||||||
|
|
||||||
@import <Foundation/CPObject.j>
|
@import <Foundation/CPObject.j>
|
||||||
|
|
||||||
@import "CPTheme.j"
|
@import <AppKit/CPTheme.j>
|
||||||
@import "_CPCibCustomResource.j"
|
@import <AppKit/_CPCibCustomResource.j>
|
||||||
@import "_CPCibKeyedUnarchiver.j"
|
@import <AppKit/_CPCibKeyedUnarchiver.j>
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@@ -34,60 +33,37 @@
|
|||||||
@implementation CPThemeBlend : CPObject
|
@implementation CPThemeBlend : CPObject
|
||||||
{
|
{
|
||||||
CPBundle _bundle;
|
CPBundle _bundle;
|
||||||
CPArray _themes;
|
CPArray _themes @accessors(readonly, getter=themes);
|
||||||
id _loadDelegate;
|
id _loadDelegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithContentsOfURL:(CPURL)aURL
|
- (id)initWithContentsOfURL:(CPURL)aURL
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_bundle = [[CPBundle alloc] initWithPath:aURL];
|
_bundle = [[CPBundle alloc] initWithPath:aURL];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
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
|
- (void)loadWithDelegate:(id)aDelegate
|
||||||
{
|
{
|
||||||
_loadDelegate = aDelegate;
|
_loadDelegate = aDelegate;
|
||||||
|
|
||||||
[_bundle loadWithDelegate:self];
|
[_bundle loadWithDelegate:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)bundleDidFinishLoading:(CPBundle)aBundle
|
- (void)bundleDidFinishLoading:(CPBundle)aBundle
|
||||||
{
|
{
|
||||||
_themes = [_bundle objectForInfoDictionaryKey:@"CPKeyedThemes"];
|
var themes = [_bundle objectForInfoDictionaryKey:@"CPKeyedThemes"],
|
||||||
|
count = themes.length;
|
||||||
var count = _themes.length;
|
|
||||||
|
|
||||||
while (count--)
|
while (count--)
|
||||||
{
|
{
|
||||||
var path = [aBundle pathForResource:_themes[count]],
|
var path = [aBundle pathForResource:themes[count]],
|
||||||
unarchiver = [[_CPThemeKeyedUnarchiver alloc]
|
unarchiver = [[_CPThemeKeyedUnarchiver alloc]
|
||||||
initForReadingWithData:[[CPURL URLWithString:path] staticResourceData]
|
initForReadingWithData:[[CPURL URLWithString:path] staticResourceData]
|
||||||
bundle:_bundle];
|
bundle:_bundle];
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+10
-21
@@ -28,6 +28,8 @@
|
|||||||
@import "CPPopUpButton.j"
|
@import "CPPopUpButton.j"
|
||||||
@import "CPToolbarItem.j"
|
@import "CPToolbarItem.j"
|
||||||
|
|
||||||
|
#include "CoreGraphics/CGGeometry.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@global
|
@global
|
||||||
@@ -327,11 +329,7 @@ var CPToolbarConfigurationsByIdentifier = nil;
|
|||||||
return _itemsSortedByVisibilityPriority;
|
return _itemsSortedByVisibilityPriority;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
- (void)validateVisibleToolbarItems
|
||||||
Validates the visible toolbar items by sending a validate message to
|
|
||||||
each visible toolbar item.
|
|
||||||
*/
|
|
||||||
- (void)validateVisibleItems
|
|
||||||
{
|
{
|
||||||
var toolbarItems = [self visibleItems],
|
var toolbarItems = [self visibleItems],
|
||||||
count = [toolbarItems count];
|
count = [toolbarItems count];
|
||||||
@@ -468,14 +466,7 @@ var CPToolbarIdentifierKey = @"CPToolbarIdentifierKey",
|
|||||||
// specified, it will be read later and the resulting call to -setDelegate:
|
// specified, it will be read later and the resulting call to -setDelegate:
|
||||||
// will cause -_reloadToolbarItems] to run again :-(
|
// will cause -_reloadToolbarItems] to run again :-(
|
||||||
// FIXME: Can we make this better?
|
// FIXME: Can we make this better?
|
||||||
|
[self _reloadToolbarItems];
|
||||||
// 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]];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
@@ -568,7 +559,6 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
|
|||||||
|
|
||||||
[_additionalItemsButton setImagePosition:CPImageOnly];
|
[_additionalItemsButton setImagePosition:CPImageOnly];
|
||||||
[[_additionalItemsButton menu] setShowsStateColumn:NO];
|
[[_additionalItemsButton menu] setShowsStateColumn:NO];
|
||||||
[[_additionalItemsButton menu] setAutoenablesItems:NO];
|
|
||||||
|
|
||||||
[_additionalItemsButton setAlternateImage:_CPToolbarViewExtraItemsAlternateImage];
|
[_additionalItemsButton setAlternateImage:_CPToolbarViewExtraItemsAlternateImage];
|
||||||
}
|
}
|
||||||
@@ -799,13 +789,14 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
|
|||||||
|
|
||||||
hasNonSeparatorItem = YES;
|
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 setImage:[item image]];
|
||||||
[menuItem setTarget:[item target]];
|
|
||||||
[menuItem setEnabled:[item isEnabled]];
|
|
||||||
|
|
||||||
[_additionalItemsButton addItem:menuItem];
|
[menuItem setTarget:[item target]];
|
||||||
|
[menuItem setAction:[item action]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -979,7 +970,7 @@ var TOP_MARGIN = 5.0,
|
|||||||
{
|
{
|
||||||
_imageView = [[CPImageView alloc] initWithFrame:[self bounds]];
|
_imageView = [[CPImageView alloc] initWithFrame:[self bounds]];
|
||||||
|
|
||||||
[_imageView setImageScaling:CPScaleProportionally];
|
[_imageView setImageScaling:CPScaleNone];
|
||||||
|
|
||||||
[self addSubview:_imageView];
|
[self addSubview:_imageView];
|
||||||
}
|
}
|
||||||
@@ -1060,8 +1051,6 @@ var TOP_MARGIN = 5.0,
|
|||||||
[_imageView setAlphaValue:0.5];
|
[_imageView setAlphaValue:0.5];
|
||||||
[_labelField setAlphaValue:0.5];
|
[_labelField setAlphaValue:0.5];
|
||||||
}
|
}
|
||||||
|
|
||||||
[_toolbar tile];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CPColor)FIXME_labelColor
|
- (CPColor)FIXME_labelColor
|
||||||
|
|||||||
@@ -23,9 +23,8 @@
|
|||||||
@import <Foundation/CPObject.j>
|
@import <Foundation/CPObject.j>
|
||||||
@import <Foundation/CPString.j>
|
@import <Foundation/CPString.j>
|
||||||
|
|
||||||
@import "CPImage.j"
|
@import <AppKit/CPImage.j>
|
||||||
@import "CPView.j"
|
@import <AppKit/CPView.j>
|
||||||
|
|
||||||
|
|
||||||
CPToolbarItemVisibilityPriorityStandard = 0;
|
CPToolbarItemVisibilityPriorityStandard = 0;
|
||||||
CPToolbarItemVisibilityPriorityLow = -1000;
|
CPToolbarItemVisibilityPriorityLow = -1000;
|
||||||
@@ -450,9 +449,6 @@ CPToolbarItemVisibilityPriorityUser
|
|||||||
|
|
||||||
- (void)validate
|
- (void)validate
|
||||||
{
|
{
|
||||||
var action = [self action],
|
|
||||||
target = [self target];
|
|
||||||
|
|
||||||
// View items do not do any target-action analysis.
|
// View items do not do any target-action analysis.
|
||||||
if (_view)
|
if (_view)
|
||||||
{
|
{
|
||||||
@@ -462,9 +458,13 @@ CPToolbarItemVisibilityPriorityUser
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var action = [self action];
|
||||||
|
|
||||||
if (!action)
|
if (!action)
|
||||||
return [self setEnabled:NO];
|
return [self setEnabled:NO];
|
||||||
|
|
||||||
|
var target = [self target];
|
||||||
|
|
||||||
if (target && ![target respondsToSelector:action])
|
if (target && ![target respondsToSelector:action])
|
||||||
return [self setEnabled:NO];
|
return [self setEnabled:NO];
|
||||||
|
|
||||||
|
|||||||
@@ -87,40 +87,6 @@
|
|||||||
[_childNodes[count] sortWithSortDescriptors:sortDescriptors recursively:YES];
|
[_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
|
@end
|
||||||
|
|
||||||
var CPTreeNodeRepresentedObjectKey = @"CPTreeNodeRepresentedObjectKey",
|
var CPTreeNodeRepresentedObjectKey = @"CPTreeNodeRepresentedObjectKey",
|
||||||
@@ -151,166 +117,3 @@ var CPTreeNodeRepresentedObjectKey = @"CPTreeNodeRepresentedObjectKey",
|
|||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@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
|
|
||||||
|
|||||||
+215
-326
File diff suppressed because it is too large
Load Diff
+12
-13
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* CPViewAnimation.j
|
* CPFlashView.j
|
||||||
* AppKit
|
* AppKit
|
||||||
*
|
*
|
||||||
* Created by Klaas Pieter Annema on September 3, 2009.
|
* 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
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@import "CPAnimation.j"
|
@import <AppKit/CPAnimation.j>
|
||||||
|
|
||||||
|
|
||||||
CPViewAnimationTargetKey = @"CPViewAnimationTarget";
|
CPViewAnimationTargetKey = @"CPViewAnimationTarget";
|
||||||
CPViewAnimationStartFrameKey = @"CPViewAnimationStartFrame";
|
CPViewAnimationStartFrameKey = @"CPViewAnimationStartFrame";
|
||||||
@@ -70,7 +69,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOut";
|
|||||||
[super startAnimation];
|
[super startAnimation];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setCurrentProgress:(CPAnimationProgress)progress
|
- (void)setCurrentProgress:(NSAnimationProgress)progress
|
||||||
{
|
{
|
||||||
[super setCurrentProgress:progress];
|
[super setCurrentProgress:progress];
|
||||||
|
|
||||||
@@ -78,17 +77,17 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOut";
|
|||||||
while (animationIndex--)
|
while (animationIndex--)
|
||||||
{
|
{
|
||||||
var dictionary = [_viewAnimations objectAtIndex:animationIndex],
|
var dictionary = [_viewAnimations objectAtIndex:animationIndex],
|
||||||
view = [self _targetView:dictionary],
|
view = [self _targetView:dictionary]
|
||||||
startFrame = [self _startFrame:dictionary],
|
startFrame = [self _startFrame:dictionary]
|
||||||
endFrame = [self _endFrame:dictionary],
|
endFrame = [self _endFrame:dictionary]
|
||||||
differenceFrame = _CGRectMakeZero();
|
differenceFrame = CPRectMakeZero();
|
||||||
|
|
||||||
differenceFrame.origin.x = endFrame.origin.x - startFrame.origin.x;
|
differenceFrame.origin.x = endFrame.origin.x - startFrame.origin.x;
|
||||||
differenceFrame.origin.y = endFrame.origin.y - startFrame.origin.y;
|
differenceFrame.origin.y = endFrame.origin.y - startFrame.origin.y;
|
||||||
differenceFrame.size.width = endFrame.size.width - startFrame.size.width;
|
differenceFrame.size.width = endFrame.size.width - startFrame.size.width;
|
||||||
differenceFrame.size.height = endFrame.size.height - startFrame.size.height;
|
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.x = startFrame.origin.x + differenceFrame.origin.x * progress;
|
||||||
intermediateFrame.origin.y = startFrame.origin.y + differenceFrame.origin.y * progress;
|
intermediateFrame.origin.y = startFrame.origin.y + differenceFrame.origin.y * progress;
|
||||||
intermediateFrame.size.width = startFrame.size.width + differenceFrame.size.width * 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];
|
[view setAlphaValue:1.0 + ( 0.0 - 1.0 ) * progress];
|
||||||
|
|
||||||
if (progress === 1.0)
|
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)
|
else if (effect === CPViewAnimationFadeOutEffect)
|
||||||
[view setAlphaValue:0.0];
|
[view setAlphaValue:0.0];
|
||||||
|
|
||||||
[view setHidden:_CGRectIsNull(endFrame) || [view alphaValue] === 0.0];
|
[view setHidden:CPRectIsNull(endFrame) || [view alphaValue] === 0.0];
|
||||||
}
|
}
|
||||||
|
|
||||||
[super stopAnimation];
|
[super stopAnimation];
|
||||||
@@ -140,7 +139,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOut";
|
|||||||
return targetView;
|
return targetView;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGRect)_startFrame:(CPDictionary)dictionary
|
- (CPRect)_startFrame:(CPDictionary)dictionary
|
||||||
{
|
{
|
||||||
var startFrame = [dictionary valueForKey:CPViewAnimationStartFrameKey];
|
var startFrame = [dictionary valueForKey:CPViewAnimationStartFrameKey];
|
||||||
if (!startFrame)
|
if (!startFrame)
|
||||||
@@ -149,7 +148,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOut";
|
|||||||
return startFrame;
|
return startFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGRect)_endFrame:(CPDictionary)dictionary
|
- (CPRect)_endFrame:(CPDictionary)dictionary
|
||||||
{
|
{
|
||||||
var endFrame = [dictionary valueForKey:CPViewAnimationEndFrameKey];
|
var endFrame = [dictionary valueForKey:CPViewAnimationEndFrameKey];
|
||||||
if (!endFrame)
|
if (!endFrame)
|
||||||
|
|||||||
+61
-27
@@ -20,12 +20,7 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@import <Foundation/CPArray.j>
|
@import <AppKit/CPResponder.j>
|
||||||
|
|
||||||
@import "CPApplication.j"
|
|
||||||
@import "CPCib.j"
|
|
||||||
@import "CPResponder.j"
|
|
||||||
|
|
||||||
|
|
||||||
var CPViewControllerCachedCibs;
|
var CPViewControllerCachedCibs;
|
||||||
|
|
||||||
@@ -52,11 +47,10 @@ var CPViewControllerCachedCibs;
|
|||||||
*/
|
*/
|
||||||
@implementation CPViewController : CPResponder
|
@implementation CPViewController : CPResponder
|
||||||
{
|
{
|
||||||
CPView _view @accessors(property=view);
|
CPView _view;
|
||||||
BOOL _isLoading;
|
|
||||||
|
|
||||||
id _representedObject @accessors(property=representedObject);
|
id _representedObject @accessors(property=representedObject);
|
||||||
CPString _title @accessors(property=title);
|
CPString _title;
|
||||||
|
|
||||||
CPString _cibName @accessors(property=cibName, readonly);
|
CPString _cibName @accessors(property=cibName, readonly);
|
||||||
CPBundle _cibBundle @accessors(property=cibBundle, readonly);
|
CPBundle _cibBundle @accessors(property=cibBundle, readonly);
|
||||||
@@ -84,7 +78,9 @@ var CPViewControllerCachedCibs;
|
|||||||
|
|
||||||
- (id)initWithCibName:(CPString)aCibNameOrNil bundle:(CPBundle)aCibBundleOrNil owner:(id)anOwner
|
- (id)initWithCibName:(CPString)aCibNameOrNil bundle:(CPBundle)aCibBundleOrNil owner:(id)anOwner
|
||||||
{
|
{
|
||||||
return [self initWithCibName:aCibNameOrNil bundle:aCibBundleOrNil externalNameTable:[CPDictionary dictionaryWithObject:anOwner forKey:CPCibOwner]];
|
return [self initWithCibName:aCibNameOrNil
|
||||||
|
bundle:aCibBundleOrNil
|
||||||
|
externalNameTable:[CPDictionary dictionaryWithObject:anOwner forKey:CPCibOwner]];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -103,15 +99,34 @@ var CPViewControllerCachedCibs;
|
|||||||
{
|
{
|
||||||
// Don't load the cib until someone actually requests the view. The user may just be intending to use setView:.
|
// Don't load the cib until someone actually requests the view. The user may just be intending to use setView:.
|
||||||
_cibName = aCibNameOrNil;
|
_cibName = aCibNameOrNil;
|
||||||
_cibBundle = aCibBundleOrNil || [CPBundle mainBundle];
|
_cibBundle = aCibBundleOrNil;
|
||||||
_cibExternalNameTable = anExternalNameTable || [CPDictionary dictionaryWithObject:self forKey:CPCibOwner];
|
|
||||||
|
|
||||||
_isLoading = NO;
|
if (!_cibBundle)
|
||||||
|
{
|
||||||
|
var owner = [anExternalNameTable objectForKey:CPCibOwner];
|
||||||
|
|
||||||
|
_cibBundle = owner ? [CPBundle bundleForClass:[owner class]] : [CPBundle mainBundle];
|
||||||
|
}
|
||||||
|
|
||||||
|
_cibExternalNameTable = anExternalNameTable || [CPDictionary dictionaryWithObject:self forKey:CPCibOwner];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setTitle:(CPString)aTitle
|
||||||
|
{
|
||||||
|
_title = aTitle;
|
||||||
|
|
||||||
|
if (self._navigationItem)
|
||||||
|
[_navigationItem setTitle:aTitle];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CPString)title
|
||||||
|
{
|
||||||
|
return _title;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Programmatically creates the view that the controller manages.
|
Programmatically creates the view that the controller manages.
|
||||||
You should never call this method directly. The view controller calls this method when the view property is requested but is nil.
|
You should never call this method directly. The view controller calls this method when the view property is requested but is nil.
|
||||||
@@ -119,22 +134,22 @@ 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.
|
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.
|
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
|
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.
|
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
|
- (void)loadView
|
||||||
{
|
{
|
||||||
if (_view)
|
if (_view)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// check if a cib is already cached for the current _cibName
|
// check if a cib is already cached for the current _cibName
|
||||||
var cib = [CPViewControllerCachedCibs objectForKey:_cibName];
|
var cib = [CPViewControllerCachedCibs objectForKey:_cibName];
|
||||||
|
|
||||||
|
// If the cib isn't cached yet : fetch it and cache it
|
||||||
if (!cib)
|
if (!cib)
|
||||||
{
|
{
|
||||||
// if the cib isn't cached yet : fetch it and cache it
|
|
||||||
cib = [[CPCib alloc] initWithContentsOfURL:[_cibBundle pathForResource:_cibName + @".cib"]];
|
cib = [[CPCib alloc] initWithContentsOfURL:[_cibBundle pathForResource:_cibName + @".cib"]];
|
||||||
[CPViewControllerCachedCibs setObject:cib forKey:_cibName];
|
[CPViewControllerCachedCibs setObject:cib forKey:_cibName];
|
||||||
}
|
}
|
||||||
@@ -151,8 +166,6 @@ var CPViewControllerCachedCibs;
|
|||||||
{
|
{
|
||||||
if (!_view)
|
if (!_view)
|
||||||
{
|
{
|
||||||
_isLoading = YES;
|
|
||||||
|
|
||||||
var cibOwner = [_cibExternalNameTable objectForKey:CPCibOwner];
|
var cibOwner = [_cibExternalNameTable objectForKey:CPCibOwner];
|
||||||
|
|
||||||
if ([cibOwner respondsToSelector:@selector(viewControllerWillLoadCib:)])
|
if ([cibOwner respondsToSelector:@selector(viewControllerWillLoadCib:)])
|
||||||
@@ -173,7 +186,6 @@ var CPViewControllerCachedCibs;
|
|||||||
if ([cibOwner respondsToSelector:@selector(viewControllerDidLoadCib:)])
|
if ([cibOwner respondsToSelector:@selector(viewControllerDidLoadCib:)])
|
||||||
[cibOwner viewControllerDidLoadCib:self];
|
[cibOwner viewControllerDidLoadCib:self];
|
||||||
|
|
||||||
_isLoading = NO;
|
|
||||||
[self viewDidLoad];
|
[self viewDidLoad];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +196,7 @@ var CPViewControllerCachedCibs;
|
|||||||
/*!
|
/*!
|
||||||
This method is called after the view controller has loaded its associated views into memory.
|
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 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
|
- (void)viewDidLoad
|
||||||
{
|
{
|
||||||
@@ -200,13 +212,35 @@ var CPViewControllerCachedCibs;
|
|||||||
*/
|
*/
|
||||||
- (void)setView:(CPView)aView
|
- (void)setView:(CPView)aView
|
||||||
{
|
{
|
||||||
var viewWasLoaded = !_view;
|
|
||||||
|
|
||||||
_view = aView;
|
_view = aView;
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure the viewDidLoad method is called if the view is set directly
|
- (CPNavigationItem)navigationItem
|
||||||
if (!_isLoading && viewWasLoaded)
|
{
|
||||||
[self viewDidLoad];
|
var navigationItem = self._navigationItem;
|
||||||
|
|
||||||
|
if (!navigationItem)
|
||||||
|
navigationItem = [[CPNavigationItem alloc] initWithTitle:[self title]];
|
||||||
|
|
||||||
|
self._navigationItem = navigationItem;
|
||||||
|
|
||||||
|
return navigationItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)viewWillAppear:(BOOL)isAnimated
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)viewDidAppear:(BOOL)isAnimated
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)viewWillDisappear:(BOOL)isAnimated
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)viewDidDisappear:(BOOL)isAnimated
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
+56
-100
@@ -20,8 +20,9 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@import "CPView.j"
|
@import <AppKit/CPView.j>
|
||||||
@import "CPScrollView.j"
|
|
||||||
|
#include "Platform/Platform.h"
|
||||||
|
|
||||||
|
|
||||||
// FIXME: implement these where possible:
|
// FIXME: implement these where possible:
|
||||||
@@ -49,32 +50,30 @@ CPWebViewScrollNative = 2;
|
|||||||
{
|
{
|
||||||
CPScrollView _scrollView;
|
CPScrollView _scrollView;
|
||||||
CPView _frameView;
|
CPView _frameView;
|
||||||
|
|
||||||
IFrame _iframe;
|
IFrame _iframe;
|
||||||
CPString _mainFrameURL;
|
CPString _mainFrameURL;
|
||||||
CPArray _backwardStack;
|
CPArray _backwardStack;
|
||||||
CPArray _forwardStack;
|
CPArray _forwardStack;
|
||||||
|
|
||||||
BOOL _ignoreLoadStart;
|
BOOL _ignoreLoadStart;
|
||||||
BOOL _ignoreLoadEnd;
|
BOOL _ignoreLoadEnd;
|
||||||
|
|
||||||
id _downloadDelegate;
|
id _downloadDelegate;
|
||||||
id _frameLoadDelegate;
|
id _frameLoadDelegate;
|
||||||
id _policyDelegate;
|
id _policyDelegate;
|
||||||
id _resourceLoadDelegate;
|
id _resourceLoadDelegate;
|
||||||
id _UIDelegate;
|
id _UIDelegate;
|
||||||
|
|
||||||
CPWebScriptObject _wso;
|
CPWebScriptObject _wso;
|
||||||
|
|
||||||
CPString _url;
|
CPString _url;
|
||||||
CPString _html;
|
CPString _html;
|
||||||
|
|
||||||
Function _loadCallback;
|
Function _loadCallback;
|
||||||
|
|
||||||
int _scrollMode;
|
int _scrollMode;
|
||||||
CGSize _scrollSize;
|
CGSize _scrollSize;
|
||||||
|
|
||||||
int _loadHTMLStringTimer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithFrame:(CPRect)frameRect frameName:(CPString)frameName groupName:(CPString)groupName
|
- (id)initWithFrame:(CPRect)frameRect frameName:(CPString)frameName groupName:(CPString)groupName
|
||||||
@@ -94,10 +93,10 @@ CPWebViewScrollNative = 2;
|
|||||||
_backwardStack = [];
|
_backwardStack = [];
|
||||||
_forwardStack = [];
|
_forwardStack = [];
|
||||||
_scrollMode = CPWebViewScrollNative;
|
_scrollMode = CPWebViewScrollNative;
|
||||||
|
|
||||||
[self _initDOMWithFrame:aFrame];
|
[self _initDOMWithFrame:aFrame];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,52 +104,51 @@ CPWebViewScrollNative = 2;
|
|||||||
{
|
{
|
||||||
_ignoreLoadStart = YES;
|
_ignoreLoadStart = YES;
|
||||||
_ignoreLoadEnd = YES;
|
_ignoreLoadEnd = YES;
|
||||||
|
|
||||||
_iframe = document.createElement("iframe");
|
_iframe = document.createElement("iframe");
|
||||||
_iframe.name = "iframe_" + Math.floor(Math.random()*10000);
|
_iframe.name = "iframe_" + Math.floor(Math.random()*10000);
|
||||||
_iframe.style.width = "100%";
|
_iframe.style.width = "100%";
|
||||||
_iframe.style.height = "100%";
|
_iframe.style.height = "100%";
|
||||||
_iframe.style.borderWidth = "0px";
|
_iframe.style.borderWidth = "0px";
|
||||||
_iframe.frameBorder = "0";
|
|
||||||
|
|
||||||
[self setDrawsBackground:YES];
|
[self setDrawsBackground:YES];
|
||||||
|
|
||||||
_loadCallback = function() {
|
_loadCallback = function() {
|
||||||
// HACK: this block handles the case where we don't know about loads initiated by the user clicking a link
|
// HACK: this block handles the case where we don't know about loads initiated by the user clicking a link
|
||||||
if (!_ignoreLoadStart)
|
if (!_ignoreLoadStart)
|
||||||
{
|
{
|
||||||
// post the start load notification
|
// post the start load notification
|
||||||
[self _startedLoading];
|
[self _startedLoading];
|
||||||
|
|
||||||
if (_mainFrameURL)
|
if (_mainFrameURL)
|
||||||
[_backwardStack addObject:_mainFrameURL];
|
[_backwardStack addObject:_mainFrameURL];
|
||||||
|
|
||||||
// FIXME: this doesn't actually get the right URL for different domains. Not possible due to browser security restrictions.
|
// 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;
|
||||||
_mainFrameURL = _iframe.src;
|
_mainFrameURL = _iframe.src;
|
||||||
|
|
||||||
// clear the forward
|
// clear the forward
|
||||||
[_forwardStack removeAllObjects];
|
[_forwardStack removeAllObjects];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_ignoreLoadStart = NO;
|
_ignoreLoadStart = NO;
|
||||||
|
|
||||||
if (!_ignoreLoadEnd)
|
if (!_ignoreLoadEnd)
|
||||||
{
|
{
|
||||||
[self _finishedLoading];
|
[self _finishedLoading];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_ignoreLoadEnd = NO;
|
_ignoreLoadEnd = NO;
|
||||||
|
|
||||||
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_iframe.addEventListener)
|
if (_iframe.addEventListener)
|
||||||
_iframe.addEventListener("load", _loadCallback, false);
|
_iframe.addEventListener("load", _loadCallback, false);
|
||||||
else if (_iframe.attachEvent)
|
else if (_iframe.attachEvent)
|
||||||
_iframe.attachEvent("onload", _loadCallback);
|
_iframe.attachEvent("onload", _loadCallback);
|
||||||
|
|
||||||
|
|
||||||
_frameView = [[CPView alloc] initWithFrame:[self bounds]];
|
_frameView = [[CPView alloc] initWithFrame:[self bounds]];
|
||||||
[_frameView setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
|
[_frameView setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
|
||||||
|
|
||||||
@@ -158,9 +156,9 @@ CPWebViewScrollNative = 2;
|
|||||||
[_scrollView setAutohidesScrollers:YES];
|
[_scrollView setAutohidesScrollers:YES];
|
||||||
[_scrollView setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
|
[_scrollView setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
|
||||||
[_scrollView setDocumentView:_frameView];
|
[_scrollView setDocumentView:_frameView];
|
||||||
|
|
||||||
_frameView._DOMElement.appendChild(_iframe);
|
_frameView._DOMElement.appendChild(_iframe);
|
||||||
|
|
||||||
[self _setScrollMode:_scrollMode];
|
[self _setScrollMode:_scrollMode];
|
||||||
|
|
||||||
[self addSubview:_scrollView];
|
[self addSubview:_scrollView];
|
||||||
@@ -168,37 +166,12 @@ CPWebViewScrollNative = 2;
|
|||||||
|
|
||||||
|
|
||||||
- (void)setFrameSize:(CPSize)aSize
|
- (void)setFrameSize:(CPSize)aSize
|
||||||
{
|
{
|
||||||
[super setFrameSize:aSize];
|
[super setFrameSize:aSize];
|
||||||
[self _resizeWebFrame];
|
[self _resizeWebFrame];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_attachScrollEventIfNecessary
|
- (BOOL)_resizeWebFrame
|
||||||
{
|
|
||||||
if (_scrollMode !== CPWebViewScrollAppKit)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var win = null;
|
|
||||||
try { win = [self DOMWindow]; } catch (e) {}
|
|
||||||
|
|
||||||
if (win && win.addEventListener)
|
|
||||||
{
|
|
||||||
var scrollEventHandler = function(anEvent)
|
|
||||||
{
|
|
||||||
var frameBounds = [self bounds],
|
|
||||||
frameCenter = CGPointMake(CGRectGetMidX(frameBounds), CGRectGetMidY(frameBounds)),
|
|
||||||
windowOrigin = [self convertPoint:frameCenter toView:nil],
|
|
||||||
globalOrigin = [[self window] convertBaseToBridge:windowOrigin];
|
|
||||||
|
|
||||||
anEvent._overrideLocation = globalOrigin;
|
|
||||||
[[[self window] platformWindow] scrollEvent:anEvent];
|
|
||||||
};
|
|
||||||
|
|
||||||
win.addEventListener("DOMMouseScroll", scrollEventHandler, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)_resizeWebFrame
|
|
||||||
{
|
{
|
||||||
if (_scrollMode === CPWebViewScrollAppKit)
|
if (_scrollMode === CPWebViewScrollAppKit)
|
||||||
{
|
{
|
||||||
@@ -208,14 +181,13 @@ CPWebViewScrollNative = 2;
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var visibleRect = [_frameView visibleRect];
|
[_frameView setFrameSize:[_scrollView contentSize]];
|
||||||
[_frameView setFrameSize:CGSizeMake(CGRectGetMaxX(visibleRect), CGRectGetMaxY(visibleRect))];
|
|
||||||
|
|
||||||
// try to get the document size so we can correctly set the frame
|
// try to get the document size so we can correctly set the frame
|
||||||
var win = null;
|
var win = null;
|
||||||
try { win = [self DOMWindow]; } catch (e) {}
|
try { win = [self DOMWindow]; } catch (e) {}
|
||||||
|
|
||||||
if (win && win.document && win.document.body)
|
if (win && win.document)
|
||||||
{
|
{
|
||||||
var width = win.document.body.scrollWidth,
|
var width = win.document.body.scrollWidth,
|
||||||
height = win.document.body.scrollHeight;
|
height = win.document.body.scrollHeight;
|
||||||
@@ -228,11 +200,9 @@ CPWebViewScrollNative = 2;
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
CPLog.warn("using default size 800*1600");
|
CPLog.warn("using default size 800*1600");
|
||||||
|
|
||||||
[_frameView setFrameSize:CGSizeMake(800, 1600)];
|
[_frameView setFrameSize:CGSizeMake(800, 1600)];
|
||||||
}
|
}
|
||||||
|
|
||||||
[_frameView scrollRectToVisible:visibleRect];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -241,17 +211,14 @@ CPWebViewScrollNative = 2;
|
|||||||
{
|
{
|
||||||
if (_scrollMode == aScrollMode)
|
if (_scrollMode == aScrollMode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[self _setScrollMode:aScrollMode];
|
[self _setScrollMode:aScrollMode];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_setScrollMode:(int)aScrollMode
|
- (void)_setScrollMode:(int)aScrollMode
|
||||||
{
|
{
|
||||||
if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
|
_scrollMode = aScrollMode;
|
||||||
_scrollMode = CPWebViewScrollNative;
|
|
||||||
else
|
|
||||||
_scrollMode = aScrollMode;
|
|
||||||
|
|
||||||
_ignoreLoadStart = YES;
|
_ignoreLoadStart = YES;
|
||||||
_ignoreLoadEnd = YES;
|
_ignoreLoadEnd = YES;
|
||||||
|
|
||||||
@@ -262,16 +229,16 @@ CPWebViewScrollNative = 2;
|
|||||||
{
|
{
|
||||||
[_scrollView setHasHorizontalScroller:YES];
|
[_scrollView setHasHorizontalScroller:YES];
|
||||||
[_scrollView setHasVerticalScroller:YES];
|
[_scrollView setHasVerticalScroller:YES];
|
||||||
|
|
||||||
_iframe.setAttribute("scrolling", "no");
|
_iframe.setAttribute("scrolling", "no");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[_scrollView setHasHorizontalScroller:NO];
|
[_scrollView setHasHorizontalScroller:NO];
|
||||||
[_scrollView setHasVerticalScroller:NO];
|
[_scrollView setHasVerticalScroller:NO];
|
||||||
|
|
||||||
_iframe.setAttribute("scrolling", "auto");
|
_iframe.setAttribute("scrolling", "auto");
|
||||||
|
|
||||||
[_frameView setFrameSize:[_scrollView bounds].size];
|
[_frameView setFrameSize:[_scrollView bounds].size];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,16 +256,14 @@ CPWebViewScrollNative = 2;
|
|||||||
|
|
||||||
[self _setScrollMode:CPWebViewScrollAppKit];
|
[self _setScrollMode:CPWebViewScrollAppKit];
|
||||||
|
|
||||||
[_frameView setFrameSize:[_scrollView contentSize]];
|
|
||||||
|
|
||||||
[self _startedLoading];
|
[self _startedLoading];
|
||||||
|
|
||||||
_ignoreLoadStart = YES;
|
_ignoreLoadStart = YES;
|
||||||
_ignoreLoadEnd = NO;
|
_ignoreLoadEnd = NO;
|
||||||
|
|
||||||
_url = null;
|
_url = null;
|
||||||
_html = aString;
|
_html = aString;
|
||||||
|
|
||||||
[self _load];
|
[self _load];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,13 +272,13 @@ CPWebViewScrollNative = 2;
|
|||||||
[self _setScrollMode:CPWebViewScrollNative];
|
[self _setScrollMode:CPWebViewScrollNative];
|
||||||
|
|
||||||
[self _startedLoading];
|
[self _startedLoading];
|
||||||
|
|
||||||
_ignoreLoadStart = YES;
|
_ignoreLoadStart = YES;
|
||||||
_ignoreLoadEnd = NO;
|
_ignoreLoadEnd = NO;
|
||||||
|
|
||||||
_url = _mainFrameURL;
|
_url = _mainFrameURL;
|
||||||
_html = null;
|
_html = null;
|
||||||
|
|
||||||
[self _load];
|
[self _load];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,19 +293,11 @@ CPWebViewScrollNative = 2;
|
|||||||
// clear the iframe
|
// clear the iframe
|
||||||
_iframe.src = "";
|
_iframe.src = "";
|
||||||
|
|
||||||
if (_loadHTMLStringTimer !== nil)
|
// need to give the browser a chance to reset iframe, otherwise we'll be document.write()-ing the previous document
|
||||||
{
|
window.setTimeout(function() {
|
||||||
window.clearTimeout(_loadHTMLStringTimer);
|
|
||||||
_loadHTMLStringTimer = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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];
|
var win = [self DOMWindow];
|
||||||
|
|
||||||
if (win)
|
win.document.write(_html);
|
||||||
win.document.write(_html);
|
|
||||||
|
|
||||||
window.setTimeout(_loadCallback, 1);
|
window.setTimeout(_loadCallback, 1);
|
||||||
}, 0);
|
}, 0);
|
||||||
@@ -358,8 +315,7 @@ CPWebViewScrollNative = 2;
|
|||||||
- (void)_finishedLoading
|
- (void)_finishedLoading
|
||||||
{
|
{
|
||||||
[self _resizeWebFrame];
|
[self _resizeWebFrame];
|
||||||
[self _attachScrollEventIfNecessary];
|
|
||||||
|
|
||||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPWebViewProgressFinishedNotification object:self];
|
[[CPNotificationCenter defaultCenter] postNotificationName:CPWebViewProgressFinishedNotification object:self];
|
||||||
|
|
||||||
if ([_frameLoadDelegate respondsToSelector:@selector(webView:didFinishLoadForFrame:)])
|
if ([_frameLoadDelegate respondsToSelector:@selector(webView:didFinishLoadForFrame:)])
|
||||||
@@ -372,7 +328,7 @@ CPWebViewScrollNative = 2;
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)setMainFrameURL:(CPString)URLString
|
- (void)setMainFrameURL:(CPString)URLString
|
||||||
{
|
{
|
||||||
if (_mainFrameURL)
|
if (_mainFrameURL)
|
||||||
[_backwardStack addObject:_mainFrameURL];
|
[_backwardStack addObject:_mainFrameURL];
|
||||||
_mainFrameURL = URLString;
|
_mainFrameURL = URLString;
|
||||||
@@ -389,9 +345,9 @@ CPWebViewScrollNative = 2;
|
|||||||
[_forwardStack addObject:_mainFrameURL];
|
[_forwardStack addObject:_mainFrameURL];
|
||||||
_mainFrameURL = [_backwardStack lastObject];
|
_mainFrameURL = [_backwardStack lastObject];
|
||||||
[_backwardStack removeLastObject];
|
[_backwardStack removeLastObject];
|
||||||
|
|
||||||
[self _loadMainFrameURL];
|
[self _loadMainFrameURL];
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
return NO;
|
return NO;
|
||||||
@@ -405,9 +361,9 @@ CPWebViewScrollNative = 2;
|
|||||||
[_backwardStack addObject:_mainFrameURL];
|
[_backwardStack addObject:_mainFrameURL];
|
||||||
_mainFrameURL = [_forwardStack lastObject];
|
_mainFrameURL = [_forwardStack lastObject];
|
||||||
[_forwardStack removeLastObject];
|
[_forwardStack removeLastObject];
|
||||||
|
|
||||||
[self _loadMainFrameURL];
|
[self _loadMainFrameURL];
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
return NO;
|
return NO;
|
||||||
@@ -630,7 +586,7 @@ CPWebViewScrollNative = 2;
|
|||||||
- (id)initWithCoder:(CPCoder)aCoder
|
- (id)initWithCoder:(CPCoder)aCoder
|
||||||
{
|
{
|
||||||
self = [super initWithCoder:aCoder];
|
self = [super initWithCoder:aCoder];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
// FIXME: encode/decode these?
|
// FIXME: encode/decode these?
|
||||||
@@ -638,14 +594,14 @@ CPWebViewScrollNative = 2;
|
|||||||
_backwardStack = [];
|
_backwardStack = [];
|
||||||
_forwardStack = [];
|
_forwardStack = [];
|
||||||
_scrollMode = CPWebViewScrollNative;
|
_scrollMode = CPWebViewScrollNative;
|
||||||
|
|
||||||
#if PLATFORM(DOM)
|
#if PLATFORM(DOM)
|
||||||
[self _initDOMWithFrame:[self frame]];
|
[self _initDOMWithFrame:[self frame]];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
[self setBackgroundColor:[CPColor whiteColor]];
|
[self setBackgroundColor:[CPColor whiteColor]];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+130
-304
@@ -26,9 +26,14 @@
|
|||||||
|
|
||||||
@import "CGGeometry.j"
|
@import "CGGeometry.j"
|
||||||
@import "CPAnimation.j"
|
@import "CPAnimation.j"
|
||||||
@import "CPPlatformWindow.j"
|
|
||||||
@import "CPResponder.j"
|
@import "CPResponder.j"
|
||||||
@import "CPScreen.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_TOP = 10.0,
|
||||||
SHADOW_MARGIN_BOTTOM = 10.0,
|
SHADOW_MARGIN_BOTTOM = 10.0,
|
||||||
SHADOW_DISTANCE = 5.0,
|
SHADOW_DISTANCE = 5.0,
|
||||||
|
|
||||||
_CPWindowShadowColor = nil;
|
_CPWindowShadowColor = nil;
|
||||||
|
|
||||||
var CPWindowSaveImage = nil,
|
var CPWindowSaveImage = nil,
|
||||||
CPWindowSavingImage = nil;
|
CPWindowSavingImage = nil;
|
||||||
|
|
||||||
var CPWindowResizeTime = 0.2;
|
/*!
|
||||||
|
|
||||||
/*!
|
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@class CPWindow
|
@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>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.
|
<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
|
@par Delegate Methods
|
||||||
|
|
||||||
@delegate -(void)windowDidResize:(CPNotification)notification;
|
@delegate -(void)windowDidResize:(CPNotification)notification;
|
||||||
Sent from the notification center when the window has been resized.
|
Sent from the notification center when the window has been resized.
|
||||||
@param notification contains information about the resize event
|
@param notification contains information about the resize event
|
||||||
|
|
||||||
@delegate -(CPUndoManager)windowWillReturnUndoManager:(CPWindow)window;
|
@delegate -(CPUndoManager)windowWillReturnUndoManager:(CPWindow)window;
|
||||||
Called to obtain the undo manager for a window
|
Called to obtain the undo manager for a window
|
||||||
@param window the window for which to return the undo manager
|
@param window the window for which to return the undo manager
|
||||||
@return the window's undo manager
|
@return the window's undo manager
|
||||||
|
|
||||||
@delegate -(void)windowDidBecomeMain:(CPNotification)notification;
|
@delegate -(void)windowDidBecomeMain:(CPNotification)notification;
|
||||||
Sent from the notification center when the delegate's window becomes
|
Sent from the notification center when the delegate's window becomes
|
||||||
the main window.
|
the main window.
|
||||||
@param notification contains information about the event
|
@param notification contains information about the event
|
||||||
|
|
||||||
@delegate -(void)windowDidResignMain:(CPNotification)notification;
|
@delegate -(void)windowDidResignMain:(CPNotification)notification;
|
||||||
Sent from the notification center when the delegate's window has
|
Sent from the notification center when the delegate's window has
|
||||||
resigned main window status.
|
resigned main window status.
|
||||||
@param notification contains information about the event
|
@param notification contains information about the event
|
||||||
|
|
||||||
@delegate -(void)windowDidResignKey:(CPNotification)notification;
|
@delegate -(void)windowDidResignKey:(CPNotification)notification;
|
||||||
Sent from the notification center when the delegate's window has
|
Sent from the notification center when the delegate's window has
|
||||||
resigned key window status.
|
resigned key window status.
|
||||||
@param notification contains information about the event
|
@param notification contains information about the event
|
||||||
|
|
||||||
@delegate -(BOOL)windowShouldClose:(id)window;
|
@delegate -(BOOL)windowShouldClose:(id)window;
|
||||||
Called when the user tries to close the window.
|
Called when the user tries to close the window.
|
||||||
@param window the window to close
|
@param window the window to close
|
||||||
@@ -308,17 +311,15 @@ var CPWindowResizeTime = 0.2;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned _autoresizingMask;
|
unsigned _autoresizingMask;
|
||||||
|
|
||||||
BOOL _delegateRespondsToWindowWillReturnUndoManagerSelector;
|
BOOL _delegateRespondsToWindowWillReturnUndoManagerSelector;
|
||||||
|
|
||||||
BOOL _isFullPlatformWindow;
|
BOOL _isFullPlatformWindow;
|
||||||
_CPWindowFullPlatformWindowSession _fullPlatformWindowSession;
|
_CPWindowFullPlatformWindowSession _fullPlatformWindowSession;
|
||||||
|
|
||||||
CPDictionary _sheetContext;
|
CPDictionary _sheetContext;
|
||||||
CPWindow _parentView;
|
CPWindow _parentView;
|
||||||
BOOL _isSheet;
|
BOOL _isSheet;
|
||||||
|
|
||||||
_CPWindowFrameAnimation _frameAnimation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -329,9 +330,9 @@ var CPWindowResizeTime = 0.2;
|
|||||||
{
|
{
|
||||||
if (self != [CPWindow class])
|
if (self != [CPWindow class])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var bundle = [CPBundle bundleForClass:[CPWindow class]];
|
var bundle = [CPBundle bundleForClass:[CPWindow class]];
|
||||||
|
|
||||||
CPWindowSavingImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPProgressIndicator/CPProgressIndicatorSpinningStyleRegular.gif"] size:CGSizeMake(16.0, 16.0)]
|
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
|
- (id)initWithContentRect:(CGRect)aContentRect styleMask:(unsigned int)aStyleMask
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
var windowViewClass = [[self class] _windowViewClassForStyleMask:aStyleMask];
|
var windowViewClass = [[self class] _windowViewClassForStyleMask:aStyleMask];
|
||||||
@@ -371,15 +372,6 @@ CPTexturedBackgroundWindowMask
|
|||||||
[self setPlatformWindow:[CPPlatformWindow primaryPlatformWindow]];
|
[self setPlatformWindow:[CPPlatformWindow primaryPlatformWindow]];
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// give zero sized borderless bridge windows a default size if we're not in the browser so they show up in NativeHost.
|
|
||||||
if ((aStyleMask & CPBorderlessBridgeWindowMask) && aContentRect.size.width === 0 && aContentRect.size.height === 0)
|
|
||||||
{
|
|
||||||
var visibleFrame = [[[CPScreen alloc] init] visibleFrame];
|
|
||||||
_frame.size.height = MIN(768.0, visibleFrame.size.height);
|
|
||||||
_frame.size.width = MIN(1024.0, visibleFrame.size.width);
|
|
||||||
_frame.origin.x = (visibleFrame.size.width - _frame.size.width) / 2;
|
|
||||||
_frame.origin.y = (visibleFrame.size.height - _frame.size.height) / 2;
|
|
||||||
}
|
|
||||||
[self setPlatformWindow:[[CPPlatformWindow alloc] initWithContentRect:_frame]];
|
[self setPlatformWindow:[[CPPlatformWindow alloc] initWithContentRect:_frame]];
|
||||||
[self platformWindow]._only = self;
|
[self platformWindow]._only = self;
|
||||||
}
|
}
|
||||||
@@ -392,7 +384,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
// Set up our window number.
|
// Set up our window number.
|
||||||
_windowNumber = [CPApp._windows count];
|
_windowNumber = [CPApp._windows count];
|
||||||
CPApp._windows[_windowNumber] = self;
|
CPApp._windows[_windowNumber] = self;
|
||||||
|
|
||||||
_styleMask = aStyleMask;
|
_styleMask = aStyleMask;
|
||||||
|
|
||||||
[self setLevel:CPNormalWindowLevel];
|
[self setLevel:CPNormalWindowLevel];
|
||||||
@@ -407,15 +399,15 @@ CPTexturedBackgroundWindowMask
|
|||||||
[_windowView setNextResponder:self];
|
[_windowView setNextResponder:self];
|
||||||
|
|
||||||
[self setMovableByWindowBackground:aStyleMask & CPHUDBackgroundWindowMask];
|
[self setMovableByWindowBackground:aStyleMask & CPHUDBackgroundWindowMask];
|
||||||
|
|
||||||
// Create a generic content view.
|
// Create a generic content view.
|
||||||
[self setContentView:[[CPView alloc] initWithFrame:CGRectMakeZero()]];
|
[self setContentView:[[CPView alloc] initWithFrame:CGRectMakeZero()]];
|
||||||
|
|
||||||
_firstResponder = self;
|
_firstResponder = self;
|
||||||
|
|
||||||
#if PLATFORM(DOM)
|
#if PLATFORM(DOM)
|
||||||
_DOMElement = document.createElement("div");
|
_DOMElement = document.createElement("div");
|
||||||
|
|
||||||
_DOMElement.style.position = "absolute";
|
_DOMElement.style.position = "absolute";
|
||||||
_DOMElement.style.visibility = "visible";
|
_DOMElement.style.visibility = "visible";
|
||||||
_DOMElement.style.zIndex = 0;
|
_DOMElement.style.zIndex = 0;
|
||||||
@@ -441,7 +433,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
|
|
||||||
[self setShowsResizeIndicator:_styleMask & CPResizableWindowMask];
|
[self setShowsResizeIndicator:_styleMask & CPResizableWindowMask];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -658,10 +650,9 @@ CPTexturedBackgroundWindowMask
|
|||||||
|
|
||||||
if (shouldAnimate)
|
if (shouldAnimate)
|
||||||
{
|
{
|
||||||
[_frameAnimation stopAnimation];
|
var animation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:aFrame];
|
||||||
_frameAnimation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:aFrame];
|
|
||||||
|
[animation startAnimation];
|
||||||
[_frameAnimation startAnimation];
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -742,10 +733,8 @@ CPTexturedBackgroundWindowMask
|
|||||||
*/
|
*/
|
||||||
- (void)orderFront:(id)aSender
|
- (void)orderFront:(id)aSender
|
||||||
{
|
{
|
||||||
#if PLATFORM(DOM)
|
|
||||||
[_platformWindow orderFront:self];
|
[_platformWindow orderFront:self];
|
||||||
[_platformWindow order:CPWindowAbove window:self relativeTo:nil];
|
[_platformWindow order:CPWindowAbove window:self relativeTo:nil];
|
||||||
#endif
|
|
||||||
|
|
||||||
if (_firstResponder === self || !_firstResponder)
|
if (_firstResponder === self || !_firstResponder)
|
||||||
[self makeFirstResponder:[self initialFirstResponder]];
|
[self makeFirstResponder:[self initialFirstResponder]];
|
||||||
@@ -773,17 +762,13 @@ CPTexturedBackgroundWindowMask
|
|||||||
*/
|
*/
|
||||||
- (void)orderOut:(id)aSender
|
- (void)orderOut:(id)aSender
|
||||||
{
|
{
|
||||||
#if PLATFORM(DOM)
|
|
||||||
if ([self _sharesChromeWithPlatformWindow])
|
if ([self _sharesChromeWithPlatformWindow])
|
||||||
[_platformWindow orderOut:self];
|
[_platformWindow orderOut:self];
|
||||||
#endif
|
|
||||||
|
|
||||||
if ([_delegate respondsToSelector:@selector(windowWillClose:)])
|
if ([_delegate respondsToSelector:@selector(windowWillClose:)])
|
||||||
[_delegate windowWillClose:self];
|
[_delegate windowWillClose:self];
|
||||||
|
|
||||||
#if PLATFORM(DOM)
|
|
||||||
[_platformWindow order:CPWindowOut window:self relativeTo:nil];
|
[_platformWindow order:CPWindowOut window:self relativeTo:nil];
|
||||||
#endif
|
|
||||||
|
|
||||||
[self _updateMainAndKeyWindows];
|
[self _updateMainAndKeyWindows];
|
||||||
}
|
}
|
||||||
@@ -795,9 +780,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
*/
|
*/
|
||||||
- (void)orderWindow:(CPWindowOrderingMode)aPlace relativeTo:(int)otherWindowNumber
|
- (void)orderWindow:(CPWindowOrderingMode)aPlace relativeTo:(int)otherWindowNumber
|
||||||
{
|
{
|
||||||
#if PLATFORM(DOM)
|
|
||||||
[_platformWindow order:aPlace window:self relativeTo:CPApp._windows[otherWindowNumber]];
|
[_platformWindow order:aPlace window:self relativeTo:CPApp._windows[otherWindowNumber]];
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -882,12 +865,12 @@ CPTexturedBackgroundWindowMask
|
|||||||
{
|
{
|
||||||
if (_contentView)
|
if (_contentView)
|
||||||
[_contentView removeFromSuperview];
|
[_contentView removeFromSuperview];
|
||||||
|
|
||||||
var bounds = CGRectMake(0.0, 0.0, CGRectGetWidth(_frame), CGRectGetHeight(_frame));
|
var bounds = CGRectMake(0.0, 0.0, CGRectGetWidth(_frame), CGRectGetHeight(_frame));
|
||||||
|
|
||||||
_contentView = aView;
|
_contentView = aView;
|
||||||
[_contentView setFrame:[self contentRectForFrameRect:bounds]];
|
[_contentView setFrame:[self contentRectForFrameRect:bounds]];
|
||||||
|
|
||||||
[_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
[_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
||||||
[_windowView addSubview:_contentView];
|
[_windowView addSubview:_contentView];
|
||||||
}
|
}
|
||||||
@@ -900,23 +883,6 @@ CPTexturedBackgroundWindowMask
|
|||||||
return _contentView;
|
return _contentView;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
Applies an alpha value to the window.
|
|
||||||
@param aValue the alpha value to apply
|
|
||||||
*/
|
|
||||||
- (void)setAlphaValue:(float)aValue
|
|
||||||
{
|
|
||||||
[_windowView setAlphaValue:aValue];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Returns the alpha value of the window.
|
|
||||||
*/
|
|
||||||
- (float)alphaValue
|
|
||||||
{
|
|
||||||
return [_windowView alphaValue];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Sets the window's background color.
|
Sets the window's background color.
|
||||||
@param aColor the new color for the background
|
@param aColor the new color for the background
|
||||||
@@ -943,24 +909,24 @@ CPTexturedBackgroundWindowMask
|
|||||||
{
|
{
|
||||||
if (CGSizeEqualToSize(_minSize, aSize))
|
if (CGSizeEqualToSize(_minSize, aSize))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_minSize = CGSizeCreateCopy(aSize);
|
_minSize = CGSizeCreateCopy(aSize);
|
||||||
|
|
||||||
var size = CGSizeMakeCopy([self frame].size),
|
var size = CGSizeMakeCopy([self frame].size),
|
||||||
needsFrameChange = NO;
|
needsFrameChange = NO;
|
||||||
|
|
||||||
if (size.width < _minSize.width)
|
if (size.width < _minSize.width)
|
||||||
{
|
{
|
||||||
size.width = _minSize.width;
|
size.width = _minSize.width;
|
||||||
needsFrameChange = YES;
|
needsFrameChange = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size.height < _minSize.height)
|
if (size.height < _minSize.height)
|
||||||
{
|
{
|
||||||
size.height = _minSize.height;
|
size.height = _minSize.height;
|
||||||
needsFrameChange = YES;
|
needsFrameChange = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needsFrameChange)
|
if (needsFrameChange)
|
||||||
[self setFrameSize:size];
|
[self setFrameSize:size];
|
||||||
}
|
}
|
||||||
@@ -983,24 +949,24 @@ CPTexturedBackgroundWindowMask
|
|||||||
{
|
{
|
||||||
if (CGSizeEqualToSize(_maxSize, aSize))
|
if (CGSizeEqualToSize(_maxSize, aSize))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_maxSize = CGSizeCreateCopy(aSize);
|
_maxSize = CGSizeCreateCopy(aSize);
|
||||||
|
|
||||||
var size = CGSizeMakeCopy([self frame].size),
|
var size = CGSizeMakeCopy([self frame].size),
|
||||||
needsFrameChange = NO;
|
needsFrameChange = NO;
|
||||||
|
|
||||||
if (size.width > _maxSize.width)
|
if (size.width > _maxSize.width)
|
||||||
{
|
{
|
||||||
size.width = _maxSize.width;
|
size.width = _maxSize.width;
|
||||||
needsFrameChange = YES;
|
needsFrameChange = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size.height > _maxSize.height)
|
if (size.height > _maxSize.height)
|
||||||
{
|
{
|
||||||
size.height = _maxSize.height;
|
size.height = _maxSize.height;
|
||||||
needsFrameChange = YES;
|
needsFrameChange = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needsFrameChange)
|
if (needsFrameChange)
|
||||||
[self setFrameSize:size];
|
[self setFrameSize:size];
|
||||||
}
|
}
|
||||||
@@ -1041,10 +1007,10 @@ CPTexturedBackgroundWindowMask
|
|||||||
if (_hasShadow && !_shadowView)
|
if (_hasShadow && !_shadowView)
|
||||||
{
|
{
|
||||||
var bounds = [_windowView bounds];
|
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)];
|
SHADOW_MARGIN_LEFT + CGRectGetWidth(bounds) + SHADOW_MARGIN_RIGHT, SHADOW_MARGIN_TOP + CGRectGetHeight(bounds) + SHADOW_MARGIN_BOTTOM)];
|
||||||
|
|
||||||
if (!_CPWindowShadowColor)
|
if (!_CPWindowShadowColor)
|
||||||
{
|
{
|
||||||
var bundle = [CPBundle bundleForClass:[CPWindow class]];
|
var bundle = [CPBundle bundleForClass:[CPWindow class]];
|
||||||
@@ -1067,7 +1033,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
|
|
||||||
[_shadowView setBackgroundColor:_CPWindowShadowColor];
|
[_shadowView setBackgroundColor:_CPWindowShadowColor];
|
||||||
[_shadowView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
[_shadowView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
||||||
|
|
||||||
#if PLATFORM(DOM)
|
#if PLATFORM(DOM)
|
||||||
CPDOMDisplayServerInsertBefore(_DOMElement, _shadowView._DOMElement, _windowView._DOMElement);
|
CPDOMDisplayServerInsertBefore(_DOMElement, _shadowView._DOMElement, _windowView._DOMElement);
|
||||||
#endif
|
#endif
|
||||||
@@ -1133,7 +1099,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
selector:@selector(windowDidBecomeKey:)
|
selector:@selector(windowDidBecomeKey:)
|
||||||
name:CPWindowDidBecomeKeyNotification
|
name:CPWindowDidBecomeKeyNotification
|
||||||
object:self];
|
object:self];
|
||||||
|
|
||||||
if ([_delegate respondsToSelector:@selector(windowDidBecomeMain:)])
|
if ([_delegate respondsToSelector:@selector(windowDidBecomeMain:)])
|
||||||
[defaultCenter
|
[defaultCenter
|
||||||
addObserver:_delegate
|
addObserver:_delegate
|
||||||
@@ -1229,7 +1195,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
if(!aResponder || ![aResponder acceptsFirstResponder] || ![aResponder becomeFirstResponder])
|
if(!aResponder || ![aResponder acceptsFirstResponder] || ![aResponder becomeFirstResponder])
|
||||||
{
|
{
|
||||||
_firstResponder = self;
|
_firstResponder = self;
|
||||||
|
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1282,9 +1248,9 @@ CPTexturedBackgroundWindowMask
|
|||||||
- (void)setTitle:(CPString)aTitle
|
- (void)setTitle:(CPString)aTitle
|
||||||
{
|
{
|
||||||
_title = aTitle;
|
_title = aTitle;
|
||||||
|
|
||||||
[_windowView setTitle:aTitle];
|
[_windowView setTitle:aTitle];
|
||||||
|
|
||||||
[self _synchronizeMenuBarTitleWithWindowTitle];
|
[self _synchronizeMenuBarTitleWithWindowTitle];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1359,21 +1325,10 @@ CPTexturedBackgroundWindowMask
|
|||||||
*/
|
*/
|
||||||
- (void)center
|
- (void)center
|
||||||
{
|
{
|
||||||
if (_isFullPlatformWindow)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var size = [self frame].size,
|
var size = [self frame].size,
|
||||||
containerSize = [CPPlatform isBrowser] ? [_platformWindow contentBounds].size : [[self screen] visibleFrame].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);
|
[self setFrameOrigin: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];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -1387,37 +1342,8 @@ CPTexturedBackgroundWindowMask
|
|||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case CPFlagsChanged: return [[self firstResponder] flagsChanged:anEvent];
|
|
||||||
|
|
||||||
case CPKeyUp: return [[self firstResponder] keyUp:anEvent];
|
case CPKeyUp: return [[self firstResponder] keyUp:anEvent];
|
||||||
|
case CPKeyDown: return [[self firstResponder] keyDown: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 CPScrollWheel: return [[_windowView hitTest:point] scrollWheel:anEvent];
|
case CPScrollWheel: return [[_windowView hitTest:point] scrollWheel:anEvent];
|
||||||
|
|
||||||
@@ -1576,7 +1502,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
- (void)makeKeyAndOrderFront:(id)aSender
|
- (void)makeKeyAndOrderFront:(id)aSender
|
||||||
{
|
{
|
||||||
[self orderFront:self];
|
[self orderFront:self];
|
||||||
|
|
||||||
[self makeKeyWindow];
|
[self makeKeyWindow];
|
||||||
[self makeMainWindow];
|
[self makeMainWindow];
|
||||||
}
|
}
|
||||||
@@ -1640,7 +1566,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
if (!pasteboardTypes)
|
if (!pasteboardTypes)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[_inclusiveRegisteredDraggedTypes minusSet:pasteboardTypes];
|
[_inclusiveRegisteredDraggedTypes minusSet:pasteboardTypes]
|
||||||
|
|
||||||
if ([_inclusiveRegisteredDraggedTypes count] === 0)
|
if ([_inclusiveRegisteredDraggedTypes count] === 0)
|
||||||
_inclusiveRegisteredDraggedTypes = nil;
|
_inclusiveRegisteredDraggedTypes = nil;
|
||||||
@@ -1671,7 +1597,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
[self _noteUnregisteredDraggedTypes:_registeredDraggedTypes];
|
[self _noteUnregisteredDraggedTypes:_registeredDraggedTypes];
|
||||||
[_registeredDraggedTypes addObjectsFromArray:pasteboardTypes];
|
[_registeredDraggedTypes addObjectsFromArray:pasteboardTypes]
|
||||||
[self _noteRegisteredDraggedTypes:_registeredDraggedTypes];
|
[self _noteRegisteredDraggedTypes:_registeredDraggedTypes];
|
||||||
|
|
||||||
_registeredDraggedTypesArray = nil;
|
_registeredDraggedTypesArray = nil;
|
||||||
@@ -1684,7 +1610,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
- (CPArray)registeredDraggedTypes
|
- (CPArray)registeredDraggedTypes
|
||||||
{
|
{
|
||||||
if (!_registeredDraggedTypesArray)
|
if (!_registeredDraggedTypesArray)
|
||||||
_registeredDraggedTypesArray = [_registeredDraggedTypes allObjects];
|
_registeredDraggedTypesArray = [_registeredDraggedTypes allObjects]
|
||||||
|
|
||||||
return _registeredDraggedTypesArray;
|
return _registeredDraggedTypesArray;
|
||||||
}
|
}
|
||||||
@@ -1710,9 +1636,9 @@ CPTexturedBackgroundWindowMask
|
|||||||
{
|
{
|
||||||
if (_isDocumentEdited == isDocumentEdited)
|
if (_isDocumentEdited == isDocumentEdited)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_isDocumentEdited = isDocumentEdited;
|
_isDocumentEdited = isDocumentEdited;
|
||||||
|
|
||||||
[CPMenu _setMenuBarIconImageAlphaValue:_isDocumentEdited ? 0.5 : 1.0];
|
[CPMenu _setMenuBarIconImageAlphaValue:_isDocumentEdited ? 0.5 : 1.0];
|
||||||
|
|
||||||
[_windowView setDocumentEdited:isDocumentEdited];
|
[_windowView setDocumentEdited:isDocumentEdited];
|
||||||
@@ -1730,11 +1656,11 @@ CPTexturedBackgroundWindowMask
|
|||||||
{
|
{
|
||||||
if (_isDocumentSaving == isDocumentSaving)
|
if (_isDocumentSaving == isDocumentSaving)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_isDocumentSaving = isDocumentSaving;
|
_isDocumentSaving = isDocumentSaving;
|
||||||
|
|
||||||
[self _synchronizeSaveMenuWithDocumentSaving];
|
[self _synchronizeSaveMenuWithDocumentSaving];
|
||||||
|
|
||||||
[_windowView windowDidChangeDocumentSaving];
|
[_windowView windowDidChangeDocumentSaving];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1751,16 +1677,16 @@ CPTexturedBackgroundWindowMask
|
|||||||
|
|
||||||
var mainMenu = [CPApp mainMenu],
|
var mainMenu = [CPApp mainMenu],
|
||||||
index = [mainMenu indexOfItemWithTitle:_isDocumentSaving ? @"Save" : @"Saving..."];
|
index = [mainMenu indexOfItemWithTitle:_isDocumentSaving ? @"Save" : @"Saving..."];
|
||||||
|
|
||||||
if (index == CPNotFound)
|
if (index == CPNotFound)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var item = [mainMenu itemAtIndex:index];
|
var item = [mainMenu itemAtIndex:index];
|
||||||
|
|
||||||
if (_isDocumentSaving)
|
if (_isDocumentSaving)
|
||||||
{
|
{
|
||||||
CPWindowSaveImage = [item image];
|
CPWindowSaveImage = [item image];
|
||||||
|
|
||||||
[item setTitle:@"Saving..."];
|
[item setTitle:@"Saving..."];
|
||||||
[item setImage:CPWindowSavingImage];
|
[item setImage:CPWindowSavingImage];
|
||||||
[item setEnabled:NO];
|
[item setEnabled:NO];
|
||||||
@@ -1850,7 +1776,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
if (![_delegate windowShouldClose:self])
|
if (![_delegate windowShouldClose:self])
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only check self is delegate does NOT implement this. This also ensures this when delegate == self (returns true).
|
// 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])
|
else if ([self respondsToSelector:@selector(windowShouldClose:)] && ![self windowShouldClose:self])
|
||||||
return;
|
return;
|
||||||
@@ -1860,8 +1786,8 @@ CPTexturedBackgroundWindowMask
|
|||||||
{
|
{
|
||||||
var index = [documents indexOfObject:[_windowController document]];
|
var index = [documents indexOfObject:[_windowController document]];
|
||||||
|
|
||||||
[documents[index] shouldCloseWindowController:_windowController
|
[documents[index] shouldCloseWindowController:_windowController
|
||||||
delegate:self
|
delegate:self
|
||||||
shouldCloseSelector:@selector(_windowControllerContainingDocument:shouldClose:contextInfo:)
|
shouldCloseSelector:@selector(_windowControllerContainingDocument:shouldClose:contextInfo:)
|
||||||
contextInfo:{documents:[documents copy], visited:0, index:index}];
|
contextInfo:{documents:[documents copy], visited:0, index:index}];
|
||||||
}
|
}
|
||||||
@@ -1885,8 +1811,8 @@ CPTexturedBackgroundWindowMask
|
|||||||
{
|
{
|
||||||
[windowController setDocument:documents[index]];
|
[windowController setDocument:documents[index]];
|
||||||
|
|
||||||
[documents[index] shouldCloseWindowController:_windowController
|
[documents[index] shouldCloseWindowController:_windowController
|
||||||
delegate:self
|
delegate:self
|
||||||
shouldCloseSelector:@selector(_windowControllerContainingDocument:shouldClose:contextInfo:)
|
shouldCloseSelector:@selector(_windowControllerContainingDocument:shouldClose:contextInfo:)
|
||||||
contextInfo:context];
|
contextInfo:context];
|
||||||
}
|
}
|
||||||
@@ -1923,7 +1849,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
// FIXME: Also check if we can resize and titlebar.
|
// FIXME: Also check if we can resize and titlebar.
|
||||||
if ([self isVisible])
|
if ([self isVisible])
|
||||||
return YES;
|
return YES;
|
||||||
|
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1981,17 +1907,10 @@ CPTexturedBackgroundWindowMask
|
|||||||
[keyWindow makeKeyWindow];
|
[keyWindow makeKeyWindow];
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var mainMenu = [CPApp mainMenu],
|
var menuWindow = [CPApp mainMenu]._menuWindow;
|
||||||
menuBarClass = objj_getClass("_CPMenuBarWindow"),
|
|
||||||
menuWindow;
|
|
||||||
|
|
||||||
for (var i = 0; i < windowCount; i++)
|
for (var i = 0; i < windowCount; i++)
|
||||||
{
|
{
|
||||||
var currentWindow = allWindows[i];
|
var currentWindow = allWindows[i];
|
||||||
|
|
||||||
if ([currentWindow isKindOfClass:menuBarClass])
|
|
||||||
menuWindow = currentWindow;
|
|
||||||
|
|
||||||
if (currentWindow === self || currentWindow === menuWindow)
|
if (currentWindow === self || currentWindow === menuWindow)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -2016,17 +1935,10 @@ CPTexturedBackgroundWindowMask
|
|||||||
[mainWindow makeMainWindow];
|
[mainWindow makeMainWindow];
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var mainMenu = [CPApp mainMenu],
|
var menuWindow = [CPApp mainMenu]._menuWindow;
|
||||||
menuBarClass = objj_getClass("_CPMenuBarWindow"),
|
|
||||||
menuWindow;
|
|
||||||
|
|
||||||
for (var i = 0; i < windowCount; i++)
|
for (var i = 0; i < windowCount; i++)
|
||||||
{
|
{
|
||||||
var currentWindow = allWindows[i];
|
var currentWindow = allWindows[i];
|
||||||
|
|
||||||
if ([currentWindow isKindOfClass:menuBarClass])
|
|
||||||
menuWindow = currentWindow;
|
|
||||||
|
|
||||||
if (currentWindow === self || currentWindow === menuWindow)
|
if (currentWindow === self || currentWindow === menuWindow)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -2057,25 +1969,25 @@ CPTexturedBackgroundWindowMask
|
|||||||
{
|
{
|
||||||
if (_toolbar === aToolbar)
|
if (_toolbar === aToolbar)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// If this has an owner, dump it!
|
// If this has an owner, dump it!
|
||||||
[[aToolbar _window] setToolbar:nil];
|
[[aToolbar _window] setToolbar:nil];
|
||||||
|
|
||||||
// This is no longer out toolbar.
|
// This is no longer out toolbar.
|
||||||
[_toolbar _setWindow:nil];
|
[_toolbar _setWindow:nil];
|
||||||
|
|
||||||
_toolbar = aToolbar;
|
_toolbar = aToolbar;
|
||||||
|
|
||||||
// THIS is our toolbar.
|
// THIS is our toolbar.
|
||||||
[_toolbar _setWindow:self];
|
[_toolbar _setWindow:self];
|
||||||
|
|
||||||
[self _noteToolbarChanged];
|
[self _noteToolbarChanged];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)toggleToolbarShown:(id)aSender
|
- (void)toggleToolbarShown:(id)aSender
|
||||||
{
|
{
|
||||||
var toolbar = [self toolbar];
|
var toolbar = [self toolbar];
|
||||||
|
|
||||||
[toolbar setVisible:![toolbar isVisible]];
|
[toolbar setVisible:![toolbar isVisible]];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2091,10 +2003,10 @@ CPTexturedBackgroundWindowMask
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
newFrame = CGRectMakeCopy([self frame]);
|
newFrame = CGRectMakeCopy([self frame]);
|
||||||
|
|
||||||
newFrame.origin = frame.origin;
|
newFrame.origin = frame.origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
[self setFrame:newFrame];
|
[self setFrame:newFrame];
|
||||||
/*
|
/*
|
||||||
[_windowView setAnimatingToolbar:YES];
|
[_windowView setAnimatingToolbar:YES];
|
||||||
@@ -2106,17 +2018,11 @@ CPTexturedBackgroundWindowMask
|
|||||||
|
|
||||||
- (void)_setFrame:(CGRect)aFrame delegate:(id)delegate duration:(int)duration curve:(CPAnimationCurve)curve
|
- (void)_setFrame:(CGRect)aFrame delegate:(id)delegate duration:(int)duration curve:(CPAnimationCurve)curve
|
||||||
{
|
{
|
||||||
[_frameAnimation stopAnimation];
|
var animation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:aFrame];
|
||||||
_frameAnimation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:aFrame];
|
[animation setDelegate:delegate];
|
||||||
[_frameAnimation setDelegate:delegate];
|
[animation setAnimationCurve:curve];
|
||||||
[_frameAnimation setAnimationCurve:curve];
|
[animation setDuration:duration];
|
||||||
[_frameAnimation setDuration:duration];
|
[animation startAnimation];
|
||||||
[_frameAnimation startAnimation];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (CPTimeInterval)animationResizeTime:(CGRect)newWindowFrame
|
|
||||||
{
|
|
||||||
return CPWindowResizeTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* @ignore */
|
/* @ignore */
|
||||||
@@ -2126,7 +2032,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
var attachedSheet = [self attachedSheet];
|
var attachedSheet = [self attachedSheet];
|
||||||
var contentRect = [[self contentView] frame],
|
var contentRect = [[self contentView] frame],
|
||||||
sheetFrame = CGRectMakeCopy([attachedSheet frame]);
|
sheetFrame = CGRectMakeCopy([attachedSheet frame]);
|
||||||
|
|
||||||
sheetFrame.origin.y = CGRectGetMinY(_frame) + CGRectGetMinY(contentRect);
|
sheetFrame.origin.y = CGRectGetMinY(_frame) + CGRectGetMinY(contentRect);
|
||||||
sheetFrame.origin.x = CGRectGetMinX(_frame) + FLOOR((CGRectGetWidth(_frame) - CGRectGetWidth(sheetFrame)) / 2.0);
|
sheetFrame.origin.x = CGRectGetMinX(_frame) + FLOOR((CGRectGetWidth(_frame) - CGRectGetWidth(sheetFrame)) / 2.0);
|
||||||
|
|
||||||
@@ -2138,8 +2044,8 @@ CPTexturedBackgroundWindowMask
|
|||||||
{
|
{
|
||||||
var sheetFrame = [aSheet frame];
|
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];
|
[self _attachSheetWindow:aSheet];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2149,12 +2055,12 @@ CPTexturedBackgroundWindowMask
|
|||||||
var sheetFrame = [aSheet frame],
|
var sheetFrame = [aSheet frame],
|
||||||
frame = [self frame],
|
frame = [self frame],
|
||||||
sheetContent = [aSheet contentView];
|
sheetContent = [aSheet contentView];
|
||||||
|
|
||||||
[self _setUpMasksForView:sheetContent];
|
[self _setUpMasksForView:sheetContent];
|
||||||
|
|
||||||
aSheet._isSheet = YES;
|
aSheet._isSheet = YES;
|
||||||
aSheet._parentView = self;
|
aSheet._parentView = self;
|
||||||
|
|
||||||
var originx = frame.origin.x + FLOOR((frame.size.width - sheetFrame.size.width)/2),
|
var originx = frame.origin.x + FLOOR((frame.size.width - sheetFrame.size.width)/2),
|
||||||
originy = frame.origin.y + [[self contentView] frame].origin.y,
|
originy = frame.origin.y + [[self contentView] frame].origin.y,
|
||||||
startFrame = CGRectMake(originx, originy, sheetFrame.size.width, 0),
|
startFrame = CGRectMake(originx, originy, sheetFrame.size.width, 0),
|
||||||
@@ -2162,15 +2068,15 @@ CPTexturedBackgroundWindowMask
|
|||||||
|
|
||||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowWillBeginSheetNotification object:self];
|
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowWillBeginSheetNotification object:self];
|
||||||
[CPApp runModalForWindow:aSheet];
|
[CPApp runModalForWindow:aSheet];
|
||||||
|
|
||||||
[aSheet orderFront:self];
|
[aSheet orderFront:self];
|
||||||
[aSheet setFrame:startFrame display:YES animate:NO];
|
[aSheet setFrame:startFrame display:YES animate:NO];
|
||||||
_sheetContext["opened"] = YES;
|
_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
|
// Should run the main loop here until _isAnimating = FALSE
|
||||||
[aSheet becomeKeyWindow];
|
[aSheet becomeKeyWindow];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* @ignore */
|
/* @ignore */
|
||||||
@@ -2181,14 +2087,14 @@ CPTexturedBackgroundWindowMask
|
|||||||
endFrame = CGRectMakeCopy(startFrame);
|
endFrame = CGRectMakeCopy(startFrame);
|
||||||
|
|
||||||
endFrame.size.height = 0;
|
endFrame.size.height = 0;
|
||||||
|
|
||||||
_sheetContext["frame"] = startFrame;
|
_sheetContext["frame"] = startFrame;
|
||||||
|
|
||||||
var sheetContent = [sheet contentView];
|
var sheetContent = [sheet contentView];
|
||||||
[self _setUpMasksForView:sheetContent];
|
[self _setUpMasksForView:sheetContent];
|
||||||
|
|
||||||
_sheetContext["opened"] = NO;
|
_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 */
|
/* @ignore */
|
||||||
@@ -2199,33 +2105,31 @@ CPTexturedBackgroundWindowMask
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var sheetContent = [sheet contentView];
|
var sheetContent = [sheet contentView];
|
||||||
|
|
||||||
if (_sheetContext["opened"] === YES)
|
if (_sheetContext["opened"] === YES)
|
||||||
{
|
{
|
||||||
[self _restoreMasksForView:sheetContent];
|
[self _restoreMasksForView:sheetContent];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[CPApp stopModal];
|
[CPApp stopModal];
|
||||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidEndSheetNotification object:self];
|
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidEndSheetNotification object:self];
|
||||||
|
|
||||||
[sheet orderOut:self];
|
[sheet orderOut:self];
|
||||||
|
|
||||||
var lastFrame = _sheetContext["frame"];
|
var lastFrame = _sheetContext["frame"];
|
||||||
[sheet setFrame:lastFrame];
|
[sheet setFrame:lastFrame];
|
||||||
|
|
||||||
[self _restoreMasksForView:sheetContent];
|
[self _restoreMasksForView:sheetContent];
|
||||||
|
|
||||||
var delegate = _sheetContext["modalDelegate"],
|
var delegate = _sheetContext["modalDelegate"],
|
||||||
endSelector = _sheetContext["endSelector"],
|
endSelector = _sheetContext["endSelector"];
|
||||||
returnCode = _sheetContext["returnCode"],
|
|
||||||
contextInfo = _sheetContext["contextInfo"];
|
if (delegate != nil && endSelector != nil)
|
||||||
|
objj_msgSend(delegate, endSelector, sheet, _sheetContext["returnCode"], _sheetContext["contextInfo"]);
|
||||||
|
|
||||||
_sheetContext = nil;
|
_sheetContext = nil;
|
||||||
sheet._parentView = nil;
|
sheet._parentView = nil;
|
||||||
|
|
||||||
if (delegate != nil && endSelector != nil)
|
|
||||||
objj_msgSend(delegate, endSelector, sheet, returnCode, contextInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_setUpMasksForView:(CPView)aView
|
- (void)_setUpMasksForView:(CPView)aView
|
||||||
@@ -2233,7 +2137,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
var views = [aView subviews];
|
var views = [aView subviews];
|
||||||
|
|
||||||
[views addObject:aView];
|
[views addObject:aView];
|
||||||
|
|
||||||
for (var i = 0, count = [views count]; i < count; i++)
|
for (var i = 0, count = [views count]; i < count; i++)
|
||||||
{
|
{
|
||||||
var view = [views objectAtIndex:i],
|
var view = [views objectAtIndex:i],
|
||||||
@@ -2249,7 +2153,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
var views = [aView subviews];
|
var views = [aView subviews];
|
||||||
|
|
||||||
[views addObject:aView];
|
[views addObject:aView];
|
||||||
|
|
||||||
for (var i = 0, count = [views count]; i < count; i++)
|
for (var i = 0, count = [views count]; i < count; i++)
|
||||||
{
|
{
|
||||||
var view = [views objectAtIndex:i],
|
var view = [views objectAtIndex:i],
|
||||||
@@ -2267,7 +2171,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
{
|
{
|
||||||
if (_sheetContext === nil)
|
if (_sheetContext === nil)
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
return _sheetContext["sheet"];
|
return _sheetContext["sheet"];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2298,7 +2202,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)performKeyEquivalent:(CPEvent)anEvent
|
- (void)performKeyEquivalent:(CPEvent)anEvent
|
||||||
{
|
{
|
||||||
// FIXME: should we be starting at the root, in other words _windowView?
|
// FIXME: should we be starting at the root, in other words _windowView?
|
||||||
// The evidence seems to point to no...
|
// The evidence seems to point to no...
|
||||||
@@ -2309,92 +2213,19 @@ CPTexturedBackgroundWindowMask
|
|||||||
{
|
{
|
||||||
// It's not clear why we do performKeyEquivalent again here...
|
// It's not clear why we do performKeyEquivalent again here...
|
||||||
// Perhaps to allow something to happen between sendEvent: and keyDown:?
|
// Perhaps to allow something to happen between sendEvent: and keyDown:?
|
||||||
if ([anEvent _couldBeKeyEquivalent] && [self performKeyEquivalent:anEvent])
|
if (![anEvent _couldBeKeyEquivalent] || ![self performKeyEquivalent:anEvent])
|
||||||
return;
|
[self interpretKeyEvents:[anEvent]];
|
||||||
|
|
||||||
// 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];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
- (void)insertNewline:(id)sender
|
||||||
@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
|
|
||||||
{
|
{
|
||||||
var character = [anEvent charactersIgnoringModifiers],
|
if (_defaultButton && _defaultButtonEnabled)
|
||||||
uiKeys = [CPLeftArrowFunctionKey, CPRightArrowFunctionKey, CPUpArrowFunctionKey, CPDownArrowFunctionKey, CPPageUpFunctionKey, CPPageDownFunctionKey, CPEscapeFunctionKey];
|
[_defaultButton performClick:nil];
|
||||||
|
|
||||||
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:)];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
- (void)insertTab:(id)sender
|
||||||
@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
|
|
||||||
{
|
{
|
||||||
var character = [anEvent charactersIgnoringModifiers],
|
[self selectNextKeyView:nil];
|
||||||
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:)];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_dirtyKeyViewLoop
|
- (void)_dirtyKeyViewLoop
|
||||||
@@ -2421,7 +2252,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
- (void)recalculateKeyViewLoop
|
- (void)recalculateKeyViewLoop
|
||||||
{
|
{
|
||||||
var subviews = [];
|
var subviews = [];
|
||||||
|
|
||||||
[self _appendSubviewsOf:_contentView toArray:subviews];
|
[self _appendSubviewsOf:_contentView toArray:subviews];
|
||||||
|
|
||||||
var keyViewOrder = [subviews sortedArrayUsingFunction:keyViewComparator context:_contentView],
|
var keyViewOrder = [subviews sortedArrayUsingFunction:keyViewComparator context:_contentView],
|
||||||
@@ -2429,7 +2260,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
|
|
||||||
for (var i=0; i<count; i++)
|
for (var i=0; i<count; i++)
|
||||||
[keyViewOrder[i] setNextKeyView:keyViewOrder[(i+1)%count]];
|
[keyViewOrder[i] setNextKeyView:keyViewOrder[(i+1)%count]];
|
||||||
|
|
||||||
_keyViewLoopIsDirty = NO;
|
_keyViewLoopIsDirty = NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2450,7 +2281,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
_autorecalculatesKeyViewLoop = shouldRecalculate;
|
_autorecalculatesKeyViewLoop = shouldRecalculate;
|
||||||
|
|
||||||
if (_keyViewLoopIsDirty)
|
if (_keyViewLoopIsDirty)
|
||||||
[self recalculateKeyViewLoop];
|
[self recalculateKeyViewLoop];
|
||||||
else if (_autorecalculatesKeyViewLoop)
|
else if (_autorecalculatesKeyViewLoop)
|
||||||
@@ -2502,16 +2333,11 @@ CPTexturedBackgroundWindowMask
|
|||||||
|
|
||||||
- (void)setDefaultButton:(CPButton)aButton
|
- (void)setDefaultButton:(CPButton)aButton
|
||||||
{
|
{
|
||||||
if (_defaultButton === aButton)
|
[_defaultButton setDefaultButton:NO];
|
||||||
return;
|
|
||||||
|
|
||||||
if ([_defaultButton keyEquivalent] === CPCarriageReturnCharacter)
|
|
||||||
[_defaultButton setKeyEquivalent:nil];
|
|
||||||
|
|
||||||
_defaultButton = aButton;
|
_defaultButton = aButton;
|
||||||
|
|
||||||
if ([_defaultButton keyEquivalent] !== CPCarriageReturnCharacter)
|
[_defaultButton setDefaultButton:YES];
|
||||||
[_defaultButton setKeyEquivalent:CPCarriageReturnCharacter];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CPButton)defaultButton
|
- (CPButton)defaultButton
|
||||||
@@ -2578,7 +2404,7 @@ var keyViewComparator = function(a, b, context)
|
|||||||
{
|
{
|
||||||
if ([self isFullPlatformWindow])
|
if ([self isFullPlatformWindow])
|
||||||
return [self setFrame:[_platformWindow visibleFrame]];
|
return [self setFrame:[_platformWindow visibleFrame]];
|
||||||
|
|
||||||
if (_autoresizingMask == CPWindowNotSizable)
|
if (_autoresizingMask == CPWindowNotSizable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -2593,7 +2419,7 @@ var keyViewComparator = function(a, b, context)
|
|||||||
newFrame.origin.x += dX;
|
newFrame.origin.x += dX;
|
||||||
if (_autoresizingMask & CPWindowWidthSizable)
|
if (_autoresizingMask & CPWindowWidthSizable)
|
||||||
newFrame.size.width += dX;
|
newFrame.size.width += dX;
|
||||||
|
|
||||||
if (_autoresizingMask & CPWindowMinYMargin)
|
if (_autoresizingMask & CPWindowMinYMargin)
|
||||||
newFrame.origin.y += dY;
|
newFrame.origin.y += dY;
|
||||||
if (_autoresizingMask & CPWindowHeightSizable)
|
if (_autoresizingMask & CPWindowHeightSizable)
|
||||||
@@ -2765,39 +2591,39 @@ var interpolate = function(fromValue, toValue, progress)
|
|||||||
@implementation _CPWindowFrameAnimation : CPAnimation
|
@implementation _CPWindowFrameAnimation : CPAnimation
|
||||||
{
|
{
|
||||||
CPWindow _window;
|
CPWindow _window;
|
||||||
|
|
||||||
CGRect _startFrame;
|
CGRect _startFrame;
|
||||||
CGRect _targetFrame;
|
CGRect _targetFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithWindow:(CPWindow)aWindow targetFrame:(CGRect)aTargetFrame
|
- (id)initWithWindow:(CPWindow)aWindow targetFrame:(CGRect)aTargetFrame
|
||||||
{
|
{
|
||||||
self = [super initWithDuration:[aWindow animationResizeTime:aTargetFrame] animationCurve:CPAnimationLinear];
|
self = [super initWithDuration:0.2 animationCurve:CPAnimationLinear];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_window = aWindow;
|
_window = aWindow;
|
||||||
|
|
||||||
_targetFrame = CGRectMakeCopy(aTargetFrame);
|
_targetFrame = CGRectMakeCopy(aTargetFrame);
|
||||||
_startFrame = CGRectMakeCopy([_window frame]);
|
_startFrame = CGRectMakeCopy([_window frame]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)startAnimation
|
- (void)startAnimation
|
||||||
{
|
{
|
||||||
[super startAnimation];
|
[super startAnimation];
|
||||||
|
|
||||||
_window._isAnimating = YES;
|
_window._isAnimating = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setCurrentProgress:(float)aProgress
|
- (void)setCurrentProgress:(float)aProgress
|
||||||
{
|
{
|
||||||
[super setCurrentProgress:aProgress];
|
[super setCurrentProgress:aProgress];
|
||||||
|
|
||||||
var value = [self currentValue];
|
var value = [self currentValue];
|
||||||
|
|
||||||
if (value == 1.0)
|
if (value == 1.0)
|
||||||
_window._isAnimating = NO;
|
_window._isAnimating = NO;
|
||||||
|
|
||||||
|
|||||||
@@ -43,21 +43,21 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
|
|||||||
|
|
||||||
_CPHUDWindowViewBackgroundColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:
|
_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/CPWindowHUDBackground0.png"] size:CPSizeMake(6.0, 78.0)],
|
||||||
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground1.png"] size:CPSizeMake(1.0, 37.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(7.0, 37.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/CPWindowHUDBackground3.png"] size:CPSizeMake(6.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/CPWindowHUDBackground4.png"] size:CPSizeMake(5.0, 5.0)],
|
||||||
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground5.png"] size:CPSizeMake(7.0, 1.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/CPWindowHUDBackground6.png"] size:CPSizeMake(6.0, 6.0)],
|
||||||
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/HUD/CPWindowHUDBackground7.png"] size:CPSizeMake(1.0, 3.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(7.0, 3.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)];
|
_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(18.0, 18.0)];
|
_CPHUDWindowViewCloseActiveImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/WindowCloseActive.png"] size:CPSizeMake(20.0, 20.0)];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
|
+ (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
|
||||||
@@ -148,7 +148,7 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
|
|||||||
{
|
{
|
||||||
var closeSize = [_CPHUDWindowViewCloseImage size];
|
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];
|
[_closeButton setBordered:NO];
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
@import "_CPWindowView.j"
|
@import "_CPWindowView.j"
|
||||||
|
|
||||||
|
|
||||||
var GRADIENT_HEIGHT = 41.0;
|
var GRADIENT_HEIGHT = 41.0;
|
||||||
|
|
||||||
var _CPTexturedWindowHeadGradientColor = nil,
|
var _CPTexturedWindowHeadGradientColor = nil,
|
||||||
|
|||||||
@@ -20,8 +20,10 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@import "CPImageView.j"
|
|
||||||
@import "CPView.j"
|
@import "CPView.j"
|
||||||
|
@import "CPImageView.j"
|
||||||
|
|
||||||
|
#include "../CoreGraphics/CGGeometry.h"
|
||||||
|
|
||||||
|
|
||||||
var _CPWindowViewResizeIndicatorImage = nil;
|
var _CPWindowViewResizeIndicatorImage = nil;
|
||||||
|
|||||||
@@ -27,6 +27,8 @@
|
|||||||
@import "CPWindow.j"
|
@import "CPWindow.j"
|
||||||
@import "CPDocument.j"
|
@import "CPDocument.j"
|
||||||
|
|
||||||
|
#include "Platform/Platform.h"
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ingroup appkit
|
@ingroup appkit
|
||||||
@@ -131,7 +133,7 @@
|
|||||||
if (_window)
|
if (_window)
|
||||||
return;
|
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)
|
if (_windowCibPath)
|
||||||
return _windowCibPath;
|
return _windowCibPath;
|
||||||
|
|
||||||
return [[CPBundle mainBundle] pathForResource:_windowCibName + @".cib"];
|
return [[CPBundle bundleForClass:[_cibOwner class]] pathForResource:_windowCibName + @".cib"];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setting and Getting Window Attributes
|
// Setting and Getting Window Attributes
|
||||||
|
|||||||
+1
-1
@@ -150,7 +150,7 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey";
|
|||||||
|
|
||||||
var topLevelObjects = [anExternalNameTable objectForKey:CPCibTopLevelObjects];
|
var topLevelObjects = [anExternalNameTable objectForKey:CPCibTopLevelObjects];
|
||||||
|
|
||||||
[objectData instantiateWithOwner:owner topLevelObjects:topLevelObjects];
|
[objectData instantiateWithOwner:owner topLevelObjects:topLevelObjects]
|
||||||
[objectData establishConnectionsWithOwner:owner topLevelObjects:topLevelObjects];
|
[objectData establishConnectionsWithOwner:owner topLevelObjects:topLevelObjects];
|
||||||
[objectData awakeWithOwner:owner topLevelObjects:topLevelObjects];
|
[objectData awakeWithOwner:owner topLevelObjects:topLevelObjects];
|
||||||
|
|
||||||
|
|||||||
@@ -39,11 +39,9 @@
|
|||||||
|
|
||||||
// Not having a selector is a fatal error.
|
// Not having a selector is a fatal error.
|
||||||
if (!selector)
|
if (!selector)
|
||||||
{
|
|
||||||
[CPException
|
[CPException
|
||||||
raise:CPInvalidArgumentException
|
raise:CPInvalidArgumentException
|
||||||
reason:@"-[" + [self className] + ' ' + _cmd + @"] selector " + selectorName + @" does not exist."];
|
reason:@"-[" + [self className] + ' ' + _cmd + @"] selector " + selectorName + @" does not exist."];
|
||||||
}
|
|
||||||
|
|
||||||
// If the destination doesn't respond to this selector, warn but don't die.
|
// If the destination doesn't respond to this selector, warn but don't die.
|
||||||
if (_destination && ![_destination respondsToSelector:selector])
|
if (_destination && ![_destination respondsToSelector:selector])
|
||||||
@@ -60,7 +58,7 @@
|
|||||||
else
|
else
|
||||||
[CPException
|
[CPException
|
||||||
raise:CPInvalidArgumentException
|
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.
|
// Not being able to set the target is a fatal error.
|
||||||
if ([_source respondsToSelector:@selector(setTarget:)])
|
if ([_source respondsToSelector:@selector(setTarget:)])
|
||||||
@@ -69,14 +67,10 @@
|
|||||||
else
|
else
|
||||||
[CPException
|
[CPException
|
||||||
raise:CPInvalidArgumentException
|
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
|
@end
|
||||||
|
|
||||||
@implementation _CPCibControlConnector : CPCibControlConnector
|
@implementation _CPCibControlConnector : CPCibControlConnector { } @end
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
|
|||||||
+14
-14
@@ -37,12 +37,12 @@ var CPCibOwner = @"CPCibOwner";
|
|||||||
|
|
||||||
@implementation CPBundle (CPCibLoading)
|
@implementation CPBundle (CPCibLoading)
|
||||||
|
|
||||||
+ (CPCib)loadCibFile:(CPString)anAbsolutePath externalNameTable:(CPDictionary)aNameTable
|
+ (void)loadCibFile:(CPString)anAbsolutePath externalNameTable:(CPDictionary)aNameTable
|
||||||
{
|
{
|
||||||
return [[[CPCib alloc] initWithContentsOfURL:anAbsolutePath] instantiateCibWithExternalNameTable:aNameTable];
|
[[[CPCib alloc] initWithContentsOfURL:anAbsolutePath] instantiateCibWithExternalNameTable:aNameTable];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (CPCib)loadCibNamed:(CPString)aName owner:(id)anOwner
|
+ (void)loadCibNamed:(CPString)aName owner:(id)anOwner
|
||||||
{
|
{
|
||||||
if (![aName hasSuffix:@".cib"])
|
if (![aName hasSuffix:@".cib"])
|
||||||
aName = [aName stringByAppendingString:@".cib"];
|
aName = [aName stringByAppendingString:@".cib"];
|
||||||
@@ -51,24 +51,24 @@ var CPCibOwner = @"CPCibOwner";
|
|||||||
var bundle = anOwner ? [CPBundle bundleForClass:[anOwner class]] : [CPBundle mainBundle],
|
var bundle = anOwner ? [CPBundle bundleForClass:[anOwner class]] : [CPBundle mainBundle],
|
||||||
path = [bundle pathForResource:aName];
|
path = [bundle pathForResource:aName];
|
||||||
|
|
||||||
return [self loadCibFile:path externalNameTable:[CPDictionary dictionaryWithObject:anOwner forKey:CPCibOwner]];
|
[self loadCibFile:path externalNameTable:[CPDictionary dictionaryWithObject:anOwner forKey:CPCibOwner]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CPCib)loadCibFile:(CPString)aFileName externalNameTable:(CPDictionary)aNameTable
|
- (void)loadCibFile:(CPString)aFileName externalNameTable:(CPDictionary)aNameTable
|
||||||
{
|
{
|
||||||
return [[[CPCib alloc] initWithContentsOfURL:aFileName] instantiateCibWithExternalNameTable:aNameTable];
|
[[[CPCib alloc] initWithContentsOfURL:aFileName] instantiateCibWithExternalNameTable:aNameTable];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (CPCib)loadCibFile:(CPString)anAbsolutePath externalNameTable:(CPDictionary)aNameTable loadDelegate:aDelegate
|
+ (void)loadCibFile:(CPString)anAbsolutePath externalNameTable:(CPDictionary)aNameTable loadDelegate:aDelegate
|
||||||
{
|
{
|
||||||
return ([[CPCib alloc]
|
[[CPCib alloc]
|
||||||
initWithContentsOfURL:anAbsolutePath
|
initWithContentsOfURL:anAbsolutePath
|
||||||
loadDelegate:[[_CPCibLoadDelegate alloc]
|
loadDelegate:[[_CPCibLoadDelegate alloc]
|
||||||
initWithLoadDelegate:aDelegate
|
initWithLoadDelegate:aDelegate
|
||||||
externalNameTable:aNameTable]]);
|
externalNameTable:aNameTable]];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (CPCib)loadCibNamed:(CPString)aName owner:(id)anOwner loadDelegate:(id)aDelegate
|
+ (void)loadCibNamed:(CPString)aName owner:(id)anOwner loadDelegate:(id)aDelegate
|
||||||
{
|
{
|
||||||
if (![aName hasSuffix:@".cib"])
|
if (![aName hasSuffix:@".cib"])
|
||||||
aName = [aName stringByAppendingString:@".cib"];
|
aName = [aName stringByAppendingString:@".cib"];
|
||||||
@@ -77,17 +77,17 @@ var CPCibOwner = @"CPCibOwner";
|
|||||||
var bundle = anOwner ? [CPBundle bundleForClass:[anOwner class]] : [CPBundle mainBundle],
|
var bundle = anOwner ? [CPBundle bundleForClass:[anOwner class]] : [CPBundle mainBundle],
|
||||||
path = [bundle pathForResource:aName];
|
path = [bundle pathForResource:aName];
|
||||||
|
|
||||||
return [self loadCibFile:path externalNameTable:[CPDictionary dictionaryWithObject:anOwner forKey:CPCibOwner] loadDelegate:aDelegate];
|
[self loadCibFile:path externalNameTable:[CPDictionary dictionaryWithObject:anOwner forKey:CPCibOwner] loadDelegate:aDelegate];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CPCib)loadCibFile:(CPString)aFileName externalNameTable:(CPDictionary)aNameTable loadDelegate:(id)aDelegate
|
- (void)loadCibFile:(CPString)aFileName externalNameTable:(CPDictionary)aNameTable loadDelegate:(id)aDelegate
|
||||||
{
|
{
|
||||||
return ([[CPCib alloc]
|
[[CPCib alloc]
|
||||||
initWithCibNamed:aFileName
|
initWithCibNamed:aFileName
|
||||||
bundle:self
|
bundle:self
|
||||||
loadDelegate:[[_CPCibLoadDelegate alloc]
|
loadDelegate:[[_CPCibLoadDelegate alloc]
|
||||||
initWithLoadDelegate:aDelegate
|
initWithLoadDelegate:aDelegate
|
||||||
externalNameTable:aNameTable]]);
|
externalNameTable:aNameTable]];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -46,28 +46,28 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
|
|||||||
- (id)initWithClassName:(CPString)aClassName resourceName:(CPString)aResourceName properties:(CPDictionary)properties
|
- (id)initWithClassName:(CPString)aClassName resourceName:(CPString)aResourceName properties:(CPDictionary)properties
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_className = aClassName;
|
_className = aClassName;
|
||||||
_resourceName = aResourceName;
|
_resourceName = aResourceName;
|
||||||
_properties = properties;
|
_properties = properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithCoder:(CPCoder)aCoder
|
- (id)initWithCoder:(CPCoder)aCoder
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_className = [aCoder decodeObjectForKey:_CPCibCustomResourceClassNameKey];
|
_className = [aCoder decodeObjectForKey:_CPCibCustomResourceClassNameKey];
|
||||||
_resourceName = [aCoder decodeObjectForKey:_CPCibCustomResourceResourceNameKey];
|
_resourceName = [aCoder decodeObjectForKey:_CPCibCustomResourceResourceNameKey];
|
||||||
_properties = [aCoder decodeObjectForKey:_CPCibCustomResourcePropertiesKey];
|
_properties = [aCoder decodeObjectForKey:_CPCibCustomResourcePropertiesKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
|
|||||||
|
|
||||||
- (id)awakeAfterUsingCoder:(CPCoder)aCoder
|
- (id)awakeAfterUsingCoder:(CPCoder)aCoder
|
||||||
{
|
{
|
||||||
if ([aCoder respondsToSelector:@selector(bundle)] &&
|
if ([aCoder respondsToSelector:@selector(bundle)] &&
|
||||||
(![aCoder respondsToSelector:@selector(awakenCustomResources)] || [aCoder awakenCustomResources]))
|
(![aCoder respondsToSelector:@selector(awakenCustomResources)] || [aCoder awakenCustomResources]))
|
||||||
if (_className === @"CPImage")
|
if (_className === @"CPImage")
|
||||||
return [[CPImage alloc] initWithContentsOfFile:[[aCoder bundle] pathForResource:_resourceName] size:_properties.valueForKey(@"size")];
|
return [[CPImage alloc] initWithContentsOfFile:[[aCoder bundle] pathForResource:_resourceName] size:_properties.valueForKey(@"size")];
|
||||||
@@ -112,14 +112,4 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
|
|||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (unsigned)loadStatus
|
|
||||||
{
|
|
||||||
return CPImageLoadStatusCompleted;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id)delegate
|
|
||||||
{
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
|
|
||||||
@import <Foundation/CPObject.j>
|
@import <Foundation/CPObject.j>
|
||||||
|
|
||||||
@import "CGGeometry.j"
|
|
||||||
@import "CPWindow.j"
|
|
||||||
|
|
||||||
|
|
||||||
var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinSizeKey",
|
var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinSizeKey",
|
||||||
_CPCibWindowTemplateMaxSizeKey = @"_CPCibWindowTemplateMaxSizeKey",
|
_CPCibWindowTemplateMaxSizeKey = @"_CPCibWindowTemplateMaxSizeKey",
|
||||||
|
|||||||
@@ -22,10 +22,13 @@
|
|||||||
|
|
||||||
@import <Foundation/CPObject.j>
|
@import <Foundation/CPObject.j>
|
||||||
|
|
||||||
@import "CABackingStore.j"
|
@import <AppKit/CABackingStore.j>
|
||||||
|
|
||||||
@import "CGContext.j"
|
@import <AppKit/CGContext.j>
|
||||||
@import "CGGeometry.j"
|
@import <AppKit/CGGeometry.j>
|
||||||
|
|
||||||
|
#include "../CoreGraphics/CGGeometry.h"
|
||||||
|
#include "../CoreGraphics/CGAffineTransform.j"
|
||||||
|
|
||||||
|
|
||||||
#define DOM(aLayer) aLayer._DOMElement
|
#define DOM(aLayer) aLayer._DOMElement
|
||||||
|
|||||||
@@ -20,11 +20,14 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* 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; }
|
#define _function(inline) function inline { return _##inline; }
|
||||||
|
|
||||||
|
@import "CGGeometry.j"
|
||||||
|
|
||||||
|
|
||||||
_function(CGAffineTransformMake(a, b, c, d, tx, ty))
|
_function(CGAffineTransformMake(a, b, c, d, tx, ty))
|
||||||
_function(CGAffineTransformMakeIdentity())
|
_function(CGAffineTransformMakeIdentity())
|
||||||
_function(CGAffineTransformMakeCopy(anAffineTransform))
|
_function(CGAffineTransformMakeCopy(anAffineTransform))
|
||||||
|
|||||||
@@ -20,11 +20,12 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@import "CGAffineTransform.j"
|
#include "CGGeometry.h"
|
||||||
@import "CPCompatibility.j"
|
#include "CGAffineTransform.h"
|
||||||
@import "CGGeometry.j"
|
|
||||||
@import "CGPath.j"
|
|
||||||
|
|
||||||
|
@import "CGGeometry.j"
|
||||||
|
@import "CGAffineTransform.j"
|
||||||
|
@import "CGPath.j"
|
||||||
|
|
||||||
kCGLineCapButt = 0;
|
kCGLineCapButt = 0;
|
||||||
kCGLineCapRound = 1;
|
kCGLineCapRound = 1;
|
||||||
|
|||||||
@@ -63,7 +63,6 @@
|
|||||||
#define _CGInsetMakeCopy(anInset) _CGInsetMake(anInset.top, anInset.right, anInset.bottom, anInset.left)
|
#define _CGInsetMakeCopy(anInset) _CGInsetMake(anInset.top, anInset.right, anInset.bottom, anInset.left)
|
||||||
#define _CGInsetMakeZero() _CGInsetMake(0, 0, 0, 0)
|
#define _CGInsetMakeZero() _CGInsetMake(0, 0, 0, 0)
|
||||||
#define _CGInsetIsEmpty(anInset) ((anInset).top === 0 && (anInset).right === 0 && (anInset).bottom === 0 && (anInset).left === 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
|
// DEPRECATED
|
||||||
#define _CGPointCreateCopy(aPoint) _CGPointMake(aPoint.x, aPoint.y)
|
#define _CGPointCreateCopy(aPoint) _CGPointMake(aPoint.x, aPoint.y)
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "CGGeometry.h"
|
||||||
|
|
||||||
#define _function(inline) function inline { return _##inline; }
|
#define _function(inline) function inline { return _##inline; }
|
||||||
|
|
||||||
_function(CGPointMake(x, y))
|
_function(CGPointMake(x, y))
|
||||||
@@ -67,12 +69,6 @@ _function(CGInsetMake(top, right, bottom, left))
|
|||||||
_function(CGInsetMakeZero())
|
_function(CGInsetMakeZero())
|
||||||
_function(CGInsetMakeCopy(anInset))
|
_function(CGInsetMakeCopy(anInset))
|
||||||
_function(CGInsetIsEmpty(anInset))
|
_function(CGInsetIsEmpty(anInset))
|
||||||
_function(CGInsetEqualToInset(lhsInset, rhsInset))
|
|
||||||
|
|
||||||
CGMinXEdge = 0;
|
|
||||||
CGMinYEdge = 1;
|
|
||||||
CGMaxXEdge = 2;
|
|
||||||
CGMaxYEdge = 3;
|
|
||||||
|
|
||||||
CGRectNull = _CGRectMake(Infinity, Infinity, 0.0, 0.0);
|
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
|
Returns a \c BOOL indicating whether CGRect \c lhsRect
|
||||||
contains CGRect \c rhsRect.
|
contains CGRect \c rhsRect.
|
||||||
@@ -136,7 +88,7 @@ function CGRectDivide(inRect, slice, rem, amount, edge)
|
|||||||
function CGRectContainsRect(lhsRect, rhsRect)
|
function CGRectContainsRect(lhsRect, rhsRect)
|
||||||
{
|
{
|
||||||
var union = CGRectUnion(lhsRect, rhsRect);
|
var union = CGRectUnion(lhsRect, rhsRect);
|
||||||
|
|
||||||
return _CGRectEqualToRect(union, lhsRect);
|
return _CGRectEqualToRect(union, lhsRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,12 +102,12 @@ function CGRectContainsRect(lhsRect, rhsRect)
|
|||||||
function CGRectIntersectsRect(lhsRect, rhsRect)
|
function CGRectIntersectsRect(lhsRect, rhsRect)
|
||||||
{
|
{
|
||||||
var intersection = CGRectIntersection(lhsRect, rhsRect);
|
var intersection = CGRectIntersection(lhsRect, rhsRect);
|
||||||
|
|
||||||
return !_CGRectIsEmpty(intersection);
|
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).
|
the southwest corner the origin (rounded down), and the northeast corner a CGSize (rounded up).
|
||||||
@param aRect the rectangle to operate on
|
@param aRect the rectangle to operate on
|
||||||
@return CGRect the modified rectangle (same as the input)
|
@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.
|
// Store these out separately, if not the GetMaxes will return incorrect values.
|
||||||
var x = FLOOR(_CGRectGetMinX(aRect)),
|
var x = FLOOR(_CGRectGetMinX(aRect)),
|
||||||
y = FLOOR(_CGRectGetMinY(aRect));
|
y = FLOOR(_CGRectGetMinY(aRect));
|
||||||
|
|
||||||
aRect.size.width = CEIL(_CGRectGetMaxX(aRect)) - x;
|
aRect.size.width = CEIL(_CGRectGetMaxX(aRect)) - x;
|
||||||
aRect.size.height = CEIL(_CGRectGetMaxY(aRect)) - y;
|
aRect.size.height = CEIL(_CGRectGetMaxY(aRect)) - y;
|
||||||
|
|
||||||
@@ -188,18 +140,18 @@ function CGRectIntegral(aRect)
|
|||||||
function CGRectIntersection(lhsRect, rhsRect)
|
function CGRectIntersection(lhsRect, rhsRect)
|
||||||
{
|
{
|
||||||
var intersection = _CGRectMake(
|
var intersection = _CGRectMake(
|
||||||
MAX(_CGRectGetMinX(lhsRect), _CGRectGetMinX(rhsRect)),
|
MAX(_CGRectGetMinX(lhsRect), _CGRectGetMinX(rhsRect)),
|
||||||
MAX(_CGRectGetMinY(lhsRect), _CGRectGetMinY(rhsRect)),
|
MAX(_CGRectGetMinY(lhsRect), _CGRectGetMinY(rhsRect)),
|
||||||
0, 0);
|
0, 0);
|
||||||
|
|
||||||
intersection.size.width = MIN(_CGRectGetMaxX(lhsRect), _CGRectGetMaxX(rhsRect)) - _CGRectGetMinX(intersection);
|
intersection.size.width = MIN(_CGRectGetMaxX(lhsRect), _CGRectGetMaxX(rhsRect)) - _CGRectGetMinX(intersection);
|
||||||
intersection.size.height = MIN(_CGRectGetMaxY(lhsRect), _CGRectGetMaxY(rhsRect)) - _CGRectGetMinY(intersection);
|
intersection.size.height = MIN(_CGRectGetMaxY(lhsRect), _CGRectGetMaxY(rhsRect)) - _CGRectGetMinY(intersection);
|
||||||
|
|
||||||
return _CGRectIsEmpty(intersection) ? _CGRectMakeZero() : intersection;
|
return _CGRectIsEmpty(intersection) ? _CGRectMakeZero() : intersection;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
*/
|
*/
|
||||||
function CGRectStandardize(aRect)
|
function CGRectStandardize(aRect)
|
||||||
{
|
{
|
||||||
@@ -237,28 +189,28 @@ function CGRectUnion(lhsRect, rhsRect)
|
|||||||
minY = MIN(_CGRectGetMinY(lhsRect), _CGRectGetMinY(rhsRect)),
|
minY = MIN(_CGRectGetMinY(lhsRect), _CGRectGetMinY(rhsRect)),
|
||||||
maxX = MAX(_CGRectGetMaxX(lhsRect), _CGRectGetMaxX(rhsRect)),
|
maxX = MAX(_CGRectGetMaxX(lhsRect), _CGRectGetMaxX(rhsRect)),
|
||||||
maxY = MAX(_CGRectGetMaxY(lhsRect), _CGRectGetMaxY(rhsRect));
|
maxY = MAX(_CGRectGetMaxY(lhsRect), _CGRectGetMaxY(rhsRect));
|
||||||
|
|
||||||
return _CGRectMake(minX, minY, maxX - minX, maxY - minY);
|
return _CGRectMake(minX, minY, maxX - minX, maxY - minY);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CGPointFromString(aString)
|
function CGPointFromString(aString)
|
||||||
{
|
{
|
||||||
var comma = aString.indexOf(',');
|
var comma = aString.indexOf(',');
|
||||||
|
|
||||||
return { x:parseInt(aString.substr(1, comma - 1)), y:parseInt(aString.substring(comma + 1, aString.length)) };
|
return { x:parseInt(aString.substr(1, comma - 1)), y:parseInt(aString.substring(comma + 1, aString.length)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
function CGSizeFromString(aString)
|
function CGSizeFromString(aString)
|
||||||
{
|
{
|
||||||
var comma = aString.indexOf(',');
|
var comma = aString.indexOf(',');
|
||||||
|
|
||||||
return { width:parseInt(aString.substr(1, comma - 1)), height:parseInt(aString.substring(comma + 1, aString.length)) };
|
return { width:parseInt(aString.substr(1, comma - 1)), height:parseInt(aString.substring(comma + 1, aString.length)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
function CGRectFromString(aString)
|
function CGRectFromString(aString)
|
||||||
{
|
{
|
||||||
var comma = aString.indexOf(',', aString.indexOf(',') + 1);
|
var comma = aString.indexOf(',', aString.indexOf(',') + 1);
|
||||||
|
|
||||||
return { origin:CGPointFromString(aString.substr(1, comma - 1)), size:CGSizeFromString(aString.substring(comma + 2, aString.length)) };
|
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 + '}';
|
return '{' + anInset.top + ", " + anInset.left + ", " + anInset.bottom + ", " + anInset.right + '}';
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@}
|
@}
|
||||||
*/
|
*/
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user