Compare commits

..
2 Commits
644 changed files with 8168 additions and 46576 deletions
+4 -9
View File
@@ -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"
+5 -40
View File
@@ -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];
+95 -249
View File
@@ -26,30 +26,35 @@
@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
@@ -73,47 +78,37 @@ CPCriticalAlertStyle = 2;
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;
[self setTheme:(_windowStyle & CPHUDBackgroundWindowMask) ? [CPTheme defaultHudTheme] : [CPTheme defaultTheme]]; _alertPanel = [[CPPanel alloc] initWithContentRect:CGRectMake(0.0, 0.0, 400.0, 110.0) styleMask:styleMask ? styleMask | CPTitledWindowMask : CPTitledWindowMask];
[_alertPanel setFloatingPanel:YES];
[_alertPanel center];
// We'll need to recreate the panel to get the new window style. [_messageLabel setTextColor:(styleMask & CPHUDBackgroundWindowMask) ? [CPColor whiteColor] : [CPColor blackColor]];
_alertPanel = nil;
}
- (void)_createPanel var count = [_buttons count];
{ for(var i=0; i < count; i++)
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]];
}
else
[self addButtonWithTitle:@"OK"];
[contentView addSubview:_messageLabel]; [button setFrameSize:CGSizeMake([button frame].size.width, (styleMask == CPHUDBackgroundWindowMask) ? 20.0 : 24.0)];
[contentView addSubview:_alertImageView];
[contentView addSubview:_informativeLabel]; [button setTheme:(_windowStyle === CPHUDBackgroundWindowMask) ? [CPTheme themeNamed:"Aristo-HUD"] : [CPTheme defaultTheme]];
[[_alertPanel contentView] addSubview:button];
}
if (!_messageLabel)
{
var bounds = [[_alertPanel contentView] bounds];
_messageLabel = [[CPTextField alloc] initWithFrame:CGRectMake(57.0, 10.0, CGRectGetWidth(bounds) - 73.0, 62.0)];
[_messageLabel setFont:[CPFont boldSystemFontOfSize:13.0]];
[_messageLabel setLineBreakMode:CPLineBreakByWordWrapping];
[_messageLabel setAlignment:CPJustifiedTextAlignment];
[_messageLabel setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
_alertImageView = [[CPImageView alloc] initWithFrame:CGRectMake(15.0, 12.0, 32.0, 32.0)];
}
[[_alertPanel contentView] addSubview:_messageLabel];
[[_alertPanel contentView] addSubview:_alertImageView];
} }
/*! /*!
@@ -235,7 +231,7 @@ CPCriticalAlertStyle = 2;
} }
/*! /*!
Sets the receivers message text, or title, to a given text. Sets the receivers message text, or title, to a given text.
@param messageText - Message text for the alert. @param messageText - Message text for the alert.
*/ */
- (void)setMessageText:(CPString)messageText - (void)setMessageText:(CPString)messageText
@@ -244,156 +240,40 @@ CPCriticalAlertStyle = 2;
} }
/*! /*!
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
+71 -96
View File
@@ -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";
@@ -107,8 +108,6 @@ CPRunContinuesResponse = -1002;
CPImage _applicationIconImage; CPImage _applicationIconImage;
CPPanel _aboutPanel; CPPanel _aboutPanel;
CPThemeBlend _themeBlend @accessors(property=themeBlend);
} }
/*! /*!
@@ -133,8 +132,6 @@ CPRunContinuesResponse = -1002;
{ {
self = [super init]; self = [super init];
CPApp = self;
if (self) if (self)
{ {
_eventListeners = []; _eventListeners = [];
@@ -142,6 +139,63 @@ CPRunContinuesResponse = -1002;
_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;
@@ -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],
@@ -506,8 +558,7 @@ CPRunContinuesResponse = -1002;
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];
@@ -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
@@ -683,7 +730,7 @@ 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];
@@ -863,7 +910,6 @@ CPRunContinuesResponse = -1002;
} }
[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];
} }
@@ -873,8 +919,8 @@ CPRunContinuesResponse = -1002;
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)
{ {
@@ -892,7 +938,7 @@ CPRunContinuesResponse = -1002;
- (CPArray)arguments - (CPArray)arguments
{ {
if (_fullArgsString !== window.location.hash) if(_fullArgsString !== window.location.hash)
[self _reloadArguments]; [self _reloadArguments];
return _args; return _args;
@@ -900,7 +946,7 @@ CPRunContinuesResponse = -1002;
- (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 = @"#";
@@ -908,13 +954,13 @@ CPRunContinuesResponse = -1002;
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:@"/"];
@@ -1021,6 +1067,7 @@ CPRunContinuesResponse = -1002;
+ (CPString)defaultThemeName + (CPString)defaultThemeName
{ {
// FIXME: don't hardcode
return ([[CPBundle mainBundle] objectForInfoDictionaryKey:"CPDefaultTheme"] || @"Aristo"); return ([[CPBundle mainBundle] objectForInfoDictionaryKey:"CPDefaultTheme"] || @"Aristo");
} }
@@ -1036,8 +1083,7 @@ 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];
@@ -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
-675
View File
@@ -1,675 +0,0 @@
/*
* CPArrayController.j
* AppKit
*
* Adapted from Cocotron, by Johannes Fortmann
*
* Created by Ross Boucher.
* Copyright 2009, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPIndexSet.j>
@import "CPObjectController.j"
@import "CPKeyValueBinding.j"
@implementation CPArrayController : CPObjectController
{
BOOL _avoidsEmptySelection;
BOOL _clearsFilterPredicateOnInsertion;
BOOL _filterRestrictsInsertion;
BOOL _preservesSelection;
BOOL _selectsInsertedObjects;
BOOL _alwaysUsesMultipleValuesMarker;
id _selectionIndexes;
id _sortDescriptors;
id _filterPredicate;
id _arrangedObjects;
}
+ (void)initialize
{
if (self !== [CPArrayController class])
return;
[self exposeBinding:@"contentArray"];
[self exposeBinding:@"contentSet"];
}
+ (CPSet)keyPathsForValuesAffectingContentArray
{
return [CPSet setWithObjects:"content"];
}
+ (CPSet)keyPathsForValuesAffectingArrangedObjects
{
return [CPSet setWithObjects:"content", "filterPredicate", "sortDescriptors"];
}
+ (CPSet)keyPathsForValuesAffectingSelection
{
return [CPSet setWithObjects:"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingSelectionIndex
{
return [CPSet setWithObjects:"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingSelectionIndexes
{
// When the arranged objects change, selection preservation may cause the indexes
// to change.
return [CPSet setWithObjects:"arrangedObjects"];
}
+ (CPSet)keyPathsForValuesAffectingSelectedObjects
{
// Don't need to depend on arrangedObjects here because selectionIndexes already does.
return [CPSet setWithObjects:"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingCanRemove
{
return [CPSet setWithObjects:"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingCanSelectNext
{
return [CPSet setWithObjects:"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingCanSelectPrevious
{
return [CPSet setWithObjects:"selectionIndexes"];
}
- (id)init
{
self = [super init];
if (self)
{
_selectionIndexes = [CPIndexSet indexSet];
}
return self;
}
- (void)prepareContent
{
[self _setContentArray:[[self newObject]]];
}
- (BOOL)preservesSelection
{
return _preservesSelection;
}
- (void)setPreservesSelection:(BOOL)value
{
_preservesSelection = value;
}
- (BOOL)selectsInsertedObjects
{
return _selectsInsertedObjects;
}
- (void)setSelectsInsertedObjects:(BOOL)value
{
_selectsInsertedObjects = value;
}
- (BOOL)avoidsEmptySelection
{
return _avoidsEmptySelection;
}
- (void)setAvoidsEmptySelection:(BOOL)value
{
_avoidsEmptySelection = value;
}
- (void)setContent:(id)value
{
if (value === nil)
value = [];
if (![value isKindOfClass:[CPArray class]])
value = [value];
var oldSelectedObjects = nil,
oldSelectionIndexes = nil;
if ([self preservesSelection])
oldSelectedObjects = [self selectedObjects];
else
oldSelectionIndexes = [self selectionIndexes];
/*
When the contents are changed, the selected indexes may no longer refer to the
same items. This would cause problems when setSelectedObjects is called below.
Any KVO observation would try to retrieve the 'before' value which could be
wrong or even throw an exception for no longer existing indexes.
To avoid that, use the internal __setSelectedObjects which fires no notifications.
The selectionIndexes notifications will fire later since they depend on the
content key. This pattern is also applied for many other methods throughout this
class.
*/
if (_clearsFilterPredicateOnInsertion)
[self willChangeValueForKey:@"filterPredicate"];
// Don't use [super setContent:] as that would fire the contentObject change.
// We need to be in control of when notifications fire.
_contentObject = value;
if (_clearsFilterPredicateOnInsertion)
[self __setFilterPredicate:nil]; // Causes a _rearrangeObjects.
else
[self _rearrangeObjects];
if ([self preservesSelection])
[self __setSelectedObjects:oldSelectedObjects];
else
[self __setSelectionIndexes:oldSelectionIndexes];
if (_clearsFilterPredicateOnInsertion)
[self didChangeValueForKey:@"filterPredicate"];
}
- (void)_setContentArray:(id)anArray
{
[self setContent:anArray];
}
- (void)_setContentSet:(id)aSet
{
[self setContent:aSet];
}
- (id)contentArray
{
return [self content];
}
- (id)contentSet
{
return [self content];
}
- (CPArray)arrangeObjects:(CPArray)objects
{
var filterPredicate = [self filterPredicate],
sortDescriptors = [self sortDescriptors];
if (filterPredicate && sortDescriptors)
{
var sortedObjects = [objects filteredArrayUsingPredicate:filterPredicate];
[sortedObjects sortUsingDescriptors:sortDescriptors];
return sortedObjects;
}
else if (filterPredicate)
return [objects filteredArrayUsingPredicate:filterPredicate];
else if (sortDescriptors)
return [objects sortedArrayUsingDescriptors:sortDescriptors];
return [objects copy];
}
- (void)rearrangeObjects
{
[self willChangeValueForKey:@"arrangedObjects"];
[self _rearrangeObjects];
[self didChangeValueForKey:@"arrangedObjects"];
}
/*
Like rearrangeObjects but don't fire any change notifications.
@ignore
*/
- (void)_rearrangeObjects
{
/*
Rearranging reapplies the selection criteria and may cause objects to disappear,
so take care of the selection.
*/
var oldSelectedObjects = nil,
oldSelectionIndexes = nil;
if ([self preservesSelection])
oldSelectedObjects = [self selectedObjects];
else
oldSelectionIndexes = [self selectionIndexes];
[self __setArrangedObjects:[self arrangeObjects:[self contentArray]]];
if ([self preservesSelection])
[self __setSelectedObjects:oldSelectedObjects];
else
[self __setSelectionIndexes:oldSelectionIndexes];
}
- (void)__setArrangedObjects:(id)value
{
if (_arrangedObjects === value)
return;
_arrangedObjects = [[_CPObservableArray alloc] initWithArray:value];
}
- (id)arrangedObjects
{
return _arrangedObjects;
}
- (CPArray)sortDescriptors
{
return _sortDescriptors;
}
- (void)setSortDescriptors:(CPArray)value
{
if (_sortDescriptors === value)
return;
_sortDescriptors = [value copy];
// Use the non-notification version since arrangedObjects already depends
// on sortDescriptors.
[self _rearrangeObjects];
}
- (CPPredicate)filterPredicate
{
return _filterPredicate;
}
- (void)setFilterPredicate:(CPPredicate)value
{
[self __setFilterPredicate:value];
}
/*
Like setFilterPredicate but don't fire any change notifications.
@ignore
*/
- (void)__setFilterPredicate:(CPPredicate)value
{
if (_filterPredicate === value)
return;
_filterPredicate = value;
// Use the non-notification version since arrangedObjects already depends
// on filterPredicate.
[self _rearrangeObjects];
}
- (BOOL)alwaysUsesMultipleValuesMarker
{
return _alwaysUsesMultipleValuesMarker;
}
//Selection
- (unsigned)selectionIndex
{
return [_selectionIndexes firstIndex];
}
- (BOOL)setSelectionIndex:(unsigned)index
{
return [self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
}
- (CPIndexSet)selectionIndexes
{
return _selectionIndexes;
}
- (BOOL)setSelectionIndexes:(CPIndexSet)indexes
{
[self _selectionWillChange]
[self __setSelectionIndexes:indexes];
[self _selectionDidChange];
}
/*
Like setSelectionIndex but don't fire any change notifications.
@ignore
*/
- (BOOL)__setSelectionIndex:(int)theIndex
{
[self __setSelectionIndexes:[CPIndexSet indexSetWithIndex:theIndex]];
}
/*
Like setSelectionIndexes but don't fire any change notifications.
@ignore
*/
- (BOOL)__setSelectionIndexes:(CPIndexSet)indexes
{
if (!indexes)
indexes = [CPIndexSet indexSet];
if (![indexes count])
{
if (_avoidsEmptySelection && [[self arrangedObjects] count])
indexes = [CPIndexSet indexSetWithIndex:0];
}
else
{
var objectsCount = [[self arrangedObjects] count];
// Remove out of bounds indexes.
[indexes removeIndexesInRange:CPMakeRange(objectsCount, [indexes lastIndex] + 1)];
// When avoiding empty selection and the deleted selection was at the bottom, select the last item.
if (![indexes count] && _avoidsEmptySelection && objectsCount)
indexes = [CPIndexSet indexSetWithIndex:objectsCount - 1];
}
if ([_selectionIndexes isEqualToIndexSet:indexes])
return NO;
_selectionIndexes = [indexes copy];
// Push back the new selection to the model for selectionIndexes if we have one.
// There won't be an infinite loop because of the equality check above.
[[CPKeyValueBinding getBinding:@"selectionIndexes" forObject:self] reverseSetValueFor:@"selectionIndexes"];
return YES;
}
- (CPArray)selectedObjects
{
var objects = [[self arrangedObjects] objectsAtIndexes:[self selectionIndexes]];
return [_CPObservableArray arrayWithArray:(objects || [])];
}
- (BOOL)setSelectedObjects:(CPArray)objects
{
[self willChangeValueForKey:@"selectionIndexes"];
[self _selectionWillChange];
[self __setSelectedObjects:objects];
[self didChangeValueForKey:@"selectionIndexes"];
[self _selectionDidChange];
}
/*
Like setSelectedObjects but don't fire any change notifications.
@ignore
*/
- (BOOL)__setSelectedObjects:(CPArray)objects
{
var set = [CPIndexSet indexSet],
count = [objects count],
arrangedObjects = [self arrangedObjects];
for (var i = 0; i < count; i++)
{
var index = [arrangedObjects indexOfObject:[objects objectAtIndex:i]];
if (index !== CPNotFound)
[set addIndex:index];
}
[self __setSelectionIndexes:set];
return YES;
}
//Moving selection
- (BOOL)canSelectPrevious
{
return [[self selectionIndexes] firstIndex] > 0
}
- (void)selectPrevious:(id)sender
{
var index = [[self selectionIndexes] firstIndex] - 1;
if (index >= 0)
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
}
- (BOOL)canSelectNext
{
return [[self selectionIndexes] firstIndex] < [[self arrangedObjects] count] - 1;
}
- (void)selectNext:(id)sender
{
var index = [[self selectionIndexes] firstIndex] + 1;
if (index < [[self arrangedObjects] count])
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
}
//Add/Remove
- (void)addObject:(id)object
{
if (![self canAdd])
return;
if (_clearsFilterPredicateOnInsertion)
[self willChangeValueForKey:@"filterPredicate"];
[self willChangeValueForKey:@"content"];
[_contentObject addObject:object];
if (_clearsFilterPredicateOnInsertion)
[self __setFilterPredicate:nil];
if (_filterPredicate === nil || [_filterPredicate evaluateWithObject:object])
{
var pos = [_arrangedObjects insertObject:object inArraySortedByDescriptors:_sortDescriptors];
// selectionIndexes change notification will be fired as a result of the
// content change. Don't fire manually.
if (_selectsInsertedObjects)
[self __setSelectionIndex:pos];
else
[_selectionIndexes shiftIndexesStartingAtIndex:pos by:1];
}
else
[self _rearrangeObjects];
[self didChangeValueForKey:@"content"];
if (_clearsFilterPredicateOnInsertion)
[self didChangeValueForKey:@"filterPredicate"];
}
- (void)insertObject:(id)anObject atArrangedObjectIndex:(int)anIndex
{
if (![self canAdd])
return;
if (_clearsFilterPredicateOnInsertion)
[self willChangeValueForKey:@"filterPredicate"];
[self willChangeValueForKey:@"content"];
[_contentObject insertObject:anObject atIndex:anIndex];
if (_clearsFilterPredicateOnInsertion)
[self __setFilterPredicate:nil];
[[self arrangedObjects] insertObject:anObject atIndex:anIndex];
// selectionIndexes change notification will be fired as a result of the
// content change. Don't fire manually.
if ([self selectsInsertedObjects])
[self __setSelectionIndex:anIndex];
else
[[self selectionIndexes] shiftIndexesStartingAtIndex:anIndex by:1];
if ([self avoidsEmptySelection] && [[self selectionIndexes] count] <= 0 && [_contentObject count] > 0)
[self __setSelectionIndexes:[CPIndexSet indexSetWithIndex:0]];
[self didChangeValueForKey:@"content"];
if (_clearsFilterPredicateOnInsertion)
[self didChangeValueForKey:@"filterPredicate"];
}
- (void)removeObject:(id)object
{
if (![self canRemove])
return;
[self willChangeValueForKey:@"content"];
[_contentObject removeObject:object];
if (_filterPredicate === nil || [_filterPredicate evaluateWithObject:object])
{
// selectionIndexes change notification will be fired as a result of the
// content change. Don't fire manually.
var pos = [_arrangedObjects indexOfObject:object];
[_arrangedObjects removeObjectAtIndex:pos];
[_selectionIndexes shiftIndexesStartingAtIndex:pos by:-1];
}
[self didChangeValueForKey:@"content"];
}
- (void)add:(id)sender
{
if (![self canAdd])
return;
[self insert:sender];
}
- (void)insert:(id)sender
{
if (![self canInsert])
return;
var newObject = [self automaticallyPreparesContent] ? [self newObject] : [self _defaultNewObject];
[self addObject:newObject];
}
- (void)remove:(id)sender
{
[self removeObjects:[[self arrangedObjects] objectsAtIndexes:[self selectionIndexes]]];
}
- (void)removeObjectsAtArrangedObjectIndexes:(CPIndexSet)indexes
{
[self _removeObjects:[[self arrangedObjects] objectsAtIndexes:indexes]];
}
- (void)addObjects:(CPArray)objects
{
if (![self canAdd])
return;
var contentArray = [self contentArray],
count = [objects count];
for (var i = 0; i < count; i++)
[contentArray addObject:[objects objectAtIndex:i]];
[self setContent:contentArray];
}
- (void)removeObjects:(CPArray)objects
{
if (![self canRemove])
return;
[self _removeObjects:objects];
}
- (void)_removeObjects:(CPArray)objects
{
[self willChangeValueForKey:@"content"];
[_contentObject removeObjectsInArray:objects];
var arrangedObjects = [self arrangedObjects],
position = [arrangedObjects indexOfObject:[objects objectAtIndex:0]];
[arrangedObjects removeObjectsInArray:objects];
var objectsCount = [arrangedObjects count],
selectionIndexes = [CPIndexSet indexSet];
if ([self preservesSelection] || [self avoidsEmptySelection])
{
selectionIndexes = [CPIndexSet indexSetWithIndex:position];
// Remove the selection if there are no objects
if (objectsCount <= 0)
selectionIndexes = [CPIndexSet indexSet];
// Shift selection to last object if position is out of bounds
else if (position >= objectsCount)
selectionIndexes = [CPIndexSet indexSetWithIndex:objectsCount - 1];
}
_selectionIndexes = selectionIndexes;
[self didChangeValueForKey:@"content"];
}
- (BOOL)canInsert
{
return [self isEditable];
}
@end
@implementation CPArrayController (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:coder];
if (self)
{
_avoidsEmptySelection = [coder decodeBoolForKey:@"CPArrayControllerAvoidsEmptySelection"];
_clearsFilterPredicateOnInsertion = [coder decodeBoolForKey:@"CPClearsFilterPredicateOnInsertion"];
_filterRestrictsInsertion = [coder decodeBoolForKey:@"CPArrayControllerFilterRestrictsInsertion"];
_preservesSelection = [coder decodeBoolForKey:@"CPArrayControllerPreservesSelection"];
_selectsInsertedObjects = [coder decodeBoolForKey:@"CPArrayControllerSelectsInsertedObjects"];
_alwaysUsesMultipleValuesMarker = [coder decodeBoolForKey:@"CPArrayControllerAlwaysUsesMultipleValuesMarker"];
if ([self automaticallyPreparesContent])
[self prepareContent];
else
[self _setContentArray:[]];
}
return self;
}
- (void)awakeFromCib
{
[self _selectionWillChange];
[self _selectionDidChange];
}
@end
+1 -2
View File
@@ -23,10 +23,9 @@
*/ */
@import <AppKit/CPGraphicsContext.j>
@import <Foundation/CPObject.j> @import <Foundation/CPObject.j>
@import "CPGraphicsContext.j"
// Class defaults // Class defaults
+39 -163
View File
@@ -22,13 +22,6 @@
@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;
@@ -37,7 +30,6 @@ CPGrooveBorder = 3;
@implementation CPBox : CPView @implementation CPBox : CPView
{ {
CPBoxType _boxType;
CPBorderType _borderType; CPBorderType _borderType;
CPColor _borderColor; CPColor _borderColor;
@@ -70,7 +62,6 @@ CPGrooveBorder = 3;
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,7 +161,6 @@ 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;
@@ -202,7 +173,7 @@ 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);
@@ -227,142 +198,47 @@ CPGrooveBorder = 3;
- (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),
switch (_boxType) fillRect = CGRectMake(bounds.origin.x + border2,
bounds.origin.y + border2,
bounds.size.width - _borderWidth,
bounds.size.height - _borderWidth);
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
+32 -91
View File
@@ -20,12 +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 <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"
/*! /*!
@@ -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,14 +96,14 @@
_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];
@@ -170,8 +167,10 @@
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.
// unloads all later columns.
var indexPlusOne = columnIndex + 1;
[[_tableViews.slice(indexPlusOne) valueForKey:"enclosingScrollView"] [[_tableViews.slice(indexPlusOne) valueForKey:"enclosingScrollView"]
makeObjectsPerformSelector:@selector(removeFromSuperview)]; makeObjectsPerformSelector:@selector(removeFromSuperview)];
@@ -200,7 +199,7 @@
[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];
@@ -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];
} }
@@ -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];
} }
@@ -811,8 +754,6 @@ var _CPBrowserResizeControlBackgroundImage = nil;
@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];
} }
+48 -153
View File
@@ -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,9 +74,6 @@ CPChangeBackgroundCellMask = CPBackgroundButtonMask;
CPButtonStateMixed = CPThemeState("mixed"); CPButtonStateMixed = CPThemeState("mixed");
CPButtonDefaultHeight = 24.0;
CPButtonImageOffset = 3.0;
/*! /*!
@ingroup appkit @ingroup appkit
@class CPButton @class CPButton
@@ -90,6 +89,9 @@ CPButtonImageOffset = 3.0;
CPString _title; CPString _title;
CPString _alternateTitle; CPString _alternateTitle;
CPImage _image;
CPImage _alternateImage;
CPInteger _showsStateBy; CPInteger _showsStateBy;
CPInteger _highlightsBy; CPInteger _highlightsBy;
BOOL _imageDimsWhenDisabled; BOOL _imageDimsWhenDisabled;
@@ -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,15 +117,15 @@ 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
@@ -143,9 +142,6 @@ CPButtonImageOffset = 3.0;
_controlSize = CPRegularControlSize; _controlSize = CPRegularControlSize;
_keyEquivalent = @"";
_keyEquivalentModifierMask = 0;
// [self setBezelStyle:CPRoundRectBezelStyle]; // [self setBezelStyle:CPRoundRectBezelStyle];
[self setBordered:YES]; [self setBordered:YES];
} }
@@ -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
@@ -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];
@@ -433,7 +431,6 @@ 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;
@@ -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"];
@@ -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)
@@ -677,21 +589,11 @@ var CPButtonImageKey = @"CPButtonImageKey",
{ {
_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];
@@ -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
+28 -56
View File
@@ -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,7 +82,24 @@
_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
View File
@@ -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
+13 -33
View File
@@ -22,6 +22,8 @@
@import "CPView.j" @import "CPView.j"
#include "CoreGraphics/CGGeometry.h"
/*! /*!
@ingroup appkit @ingroup appkit
@@ -67,16 +69,16 @@
{ {
[self addSubview:_documentView]; [self addSubview:_documentView];
[_documentView setPostsFrameChangedNotifications:YES]; [_documentView setPostsFrameChangedNotifications:YES];
[_documentView setPostsBoundsChangedNotifications:YES]; [_documentView setPostsBoundsChangedNotifications:YES];
[defaultCenter [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
@@ -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];
} }
@@ -188,39 +190,17 @@
- (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
+26 -122
View File
@@ -297,7 +297,7 @@
*/ */
- (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;
@@ -312,10 +312,8 @@
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]
} }
/*! /*!
@@ -428,17 +426,8 @@
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;
} }
@@ -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
@@ -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]];
@@ -793,36 +724,26 @@
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
@@ -831,16 +752,10 @@
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)
@@ -913,13 +825,9 @@ var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeK
_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]];
@@ -943,11 +851,7 @@ var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeK
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];
-1
View File
@@ -22,7 +22,6 @@
@import "CPViewController.j" @import "CPViewController.j"
/*! /*!
Represents an object inside a CPCollectionView. Represents an object inside a CPCollectionView.
*/ */
+41 -37
View File
@@ -56,12 +56,18 @@ var cachedBlackColor,
/*! /*!
@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
{ {
@@ -156,7 +162,7 @@ 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,
@@ -165,7 +171,7 @@ var cachedBlackColor,
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];
@@ -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;
} }
/*! /*!
@@ -404,20 +409,20 @@ 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;
@@ -556,16 +561,13 @@ var cachedBlackColor,
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;
@@ -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);
};
+26 -29
View File
@@ -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,
@@ -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];
} }
/* /*
@@ -245,11 +243,11 @@ CPColorPickerViewHeight = 370;
[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];
@@ -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];
@@ -305,17 +303,17 @@ CPColorPickerViewHeight = 370;
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];
@@ -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];
@@ -417,7 +415,7 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
CPCookie _swatchCookie; CPCookie _swatchCookie;
} }
- (id)initWithFrame:(CPRect)aFrame -(id)initWithFrame:(CPRect)aFrame
{ {
self = [super initWithFrame:aFrame]; self = [super initWithFrame:aFrame];
@@ -432,10 +430,10 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
_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];
@@ -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],
@@ -475,10 +472,10 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
]; ];
} }
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,7 +485,7 @@ 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();
@@ -524,7 +521,7 @@ 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];
@@ -547,7 +544,7 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
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]];
@@ -566,7 +563,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:_dragColor] forType:aType]; [aPasteboard setData:[CPKeyedArchiver archivedDataWithRootObject:_dragColor] forType:aType];
} }
@@ -576,7 +573,7 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
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)];
@@ -613,7 +610,7 @@ 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]];
@@ -634,7 +631,7 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
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]];
@@ -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];
} }
+36 -33
View File
@@ -21,9 +21,9 @@
*/ */
@import <Foundation/CPObject.j> @import <Foundation/CPObject.j>
@import "CPColorPanel.j"
@import "CPView.j" #include "Platform/Platform.h"
/*! /*!
@ingroup appkit @ingroup appkit
@@ -108,12 +108,12 @@
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);
} }
+3 -9
View File
@@ -231,25 +231,19 @@ 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];
@@ -278,7 +272,7 @@ var CPColorWellColorKey = "CPColorWellColorKey",
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];
+3 -4
View File
@@ -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,7 +77,7 @@ 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;
@@ -86,7 +85,7 @@ if (typeof window !== "undefined" && window.opera)
} }
// 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;
@@ -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:
+30 -142
View File
@@ -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;
@@ -125,36 +126,6 @@ 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];
@@ -209,7 +180,6 @@ 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];
} }
@@ -278,7 +248,7 @@ 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)
@@ -287,6 +257,7 @@ var CPControlBlackColor = [CPColor blackColor];
_trackingMouseDownFlags = 0; _trackingMouseDownFlags = 0;
} }
else else
{ {
if (type === CPLeftMouseDown) if (type === CPLeftMouseDown)
@@ -329,24 +300,11 @@ var CPControlBlackColor = [CPColor blackColor];
- (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
@@ -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
{ {
@@ -530,7 +488,7 @@ var CPControlBlackColor = [CPColor blackColor];
- (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"]];
@@ -539,7 +497,7 @@ var CPControlBlackColor = [CPColor blackColor];
- (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"]];
@@ -548,103 +506,33 @@ var CPControlBlackColor = [CPColor blackColor];
- (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
{ {
-88
View File
@@ -1,88 +0,0 @@
//
// CPController.j
// AppKit
//
// Created by Ross Boucher 1/15/09
// Copyright 280 North
//
// Adapted from GNUStep
// Copyright (C) 2007 Free Software Foundation, Inc
// Released under the LGPL.
//
@import <Foundation/CPObject.j>
var CPControllerDeclaredKeysKey = @"CPControllerDeclaredKeysKey";
@implementation CPController : CPObject
{
CPArray _editors;
CPArray _declaredKeys;
}
- (id)init
{
self = [super init];
if (self)
{
_editors = [];
_declaredKeys = [];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
if ([_declaredKeys count] > 0)
[aCoder encodeObject:_declaredKeys forKey:CPControllerDeclaredKeysKey];
}
- (id)initWithCoder:(CPCoder)aDecoder
{
self = [super init];
if (self)
{
_editors = [];
_declaredKeys = [aDecoder decodeObjectForKey:CPControllerDeclaredKeysKey] || [];
}
return nil;
}
- (BOOL)isEditing
{
return [_editors count] > 0;
}
- (BOOL)commitEditing
{
var index = 0,
count = _editors.length;
for (; index < count; ++index)
if (![[_editors objectAtIndex:i] commitEditing])
return NO;
return YES;
}
- (void)discardEditing
{
[_editors makeObjectsPerformSelector:@selector(discardEditing)];
}
- (void)objectDidBeginEditing:(id)anEditor
{
[_editors addObject:anEditor];
}
- (void)objectDidEndEditing:(id)anEditor
{
[_editors removeObject:anEditor];
}
@end
+13 -22
View File
@@ -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
+5 -10
View File
@@ -12,7 +12,7 @@ Implemented class methods:
Opera : All except resizeLeftRightCursor resizeUpDownCursor operationNotAllowedCursor dragCopyCursor dragLinkCursor contextualMenuCursor openHandCursor closedHandCursor disappearingItemCursor // Opera does not support url cursors so these won't work with images 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 = [],
@@ -167,9 +167,7 @@ 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
@@ -179,10 +177,8 @@ var currentCursor = nil,
{ {
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
{ {
} }
+20 -8
View File
@@ -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"
@@ -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."];
} }
/*! /*!
@@ -386,10 +385,10 @@ var CPDocumentUntitledCount = 0;
if (!_untitledDocumentIndex) if (!_untitledDocumentIndex)
_untitledDocumentIndex = ++CPDocumentUntitledCount; _untitledDocumentIndex = ++CPDocumentUntitledCount;
if (_untitledDocumentIndex == 1) if (_untitledDocumentIndex == 1)
return @"Untitled"; return @"Untitled";
return @"Untitled " + _untitledDocumentIndex; return @"Untitled " + _untitledDocumentIndex;
} }
- (CPString)viewCibName - (CPString)viewCibName
@@ -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];
+63 -8
View File
@@ -38,6 +38,7 @@ var CPSharedDocumentController = nil;
{ {
CPArray _documents; CPArray _documents;
CPArray _documentTypes; CPArray _documentTypes;
CPArray _localDocumentURLs;
} }
/*! /*!
@@ -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;
@@ -86,15 +103,15 @@ 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;
} }
/*! /*!
@@ -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];
@@ -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
+36 -98
View File
@@ -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])
@@ -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];
} }
+23 -150
View File
@@ -21,7 +21,8 @@
*/ */
@import <Foundation/CPObject.j> @import <Foundation/CPObject.j>
@import "CPText.j"
#include "CoreGraphics/CGGeometry.h"
CPLeftMouseDown = 1; CPLeftMouseDown = 1;
@@ -52,6 +53,7 @@ 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,100 +87,24 @@ 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
@@ -519,69 +445,16 @@ 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
*/ */
-1
View File
@@ -22,7 +22,6 @@
@import <Foundation/CPObject.j> @import <Foundation/CPObject.j>
/*! /*!
@ingroup appkit @ingroup appkit
@class CPFlashMovie @class CPFlashMovie
+1
View File
@@ -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";
+1 -66
View File
@@ -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");
@@ -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
@@ -113,9 +96,6 @@ var _CPFonts = {},
{ {
_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);
@@ -127,43 +107,7 @@ var _CPFonts = {},
} }
/*! /*!
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",
+1 -1
View File
@@ -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,
+2 -16
View File
@@ -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);
} }
/*! /*!
@@ -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
-108
View File
@@ -1,108 +0,0 @@
/*
* CPGraphics.j
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2010, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPColor.j"
@import "CPGraphicsContext.j"
function CPDrawTiledRects(
/* CGRect */ boundsRect,
/* CGRect */ clipRect,
/* CPRectEdge[] */ sides,
/* float[] */ grays)
{
if (sides.length != grays.length)
[CPException raise:CPInvalidArgumentException reason:@"sides (length: " + sides.length + ") and grays (length: " + grays.length + ") must have the same length."];
var colors = [];
for (var i = 0; i < grays.length; ++i)
colors.push([CPColor colorWithCalibratedWhite:grays[i] alpha:1.0]);
return CPDrawColorTiledRects(boundsRect, clipRect, sides, colors);
}
function CPDrawColorTiledRects(
/* CGRect */ boundsRect,
/* CGRect */ clipRect,
/* CPRectEdge[] */ sides,
/* CPColor[] */ colors)
{
if (sides.length != colors.length)
[CPException raise:CPInvalidArgumentException reason:@"sides (length: " + sides.length + ") and colors (length: " + colors.length + ") must have the same length."];
var resultRect = _CGRectMakeCopy(boundsRect),
slice = _CGRectMakeZero(),
remainder = _CGRectMakeZero(),
context = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSaveGState(context);
CGContextSetLineWidth(context, 1.0);
for (var sideIndex = 0; sideIndex < sides.length; ++sideIndex)
{
var side = sides[sideIndex];
CGRectDivide(resultRect, slice, remainder, 1.0, side);
resultRect = remainder;
slice = CGRectIntersection(slice, clipRect);
// Cocoa docs say that only slices that are within the clipRect are actually drawn
if (_CGRectIsEmpty(slice))
continue;
var minX, maxX, minY, maxY;
if (side == CPMinXEdge || side == CPMaxXEdge)
{
// Make sure we have at least 1 pixel to draw a line
if (_CGRectGetWidth(slice) < 1.0)
continue;
minX = _CGRectGetMinX(slice) + 0.5;
maxX = minX;
minY = _CGRectGetMinY(slice);
maxY = _CGRectGetMaxY(slice);
}
else // CPMinYEdge || CPMaxYEdge
{
// Make sure we have at least 1 pixel to draw a line
if (_CGRectGetHeight(slice) < 1.0)
continue;
minX = _CGRectGetMinX(slice);
maxX = _CGRectGetMaxX(slice);
minY = _CGRectGetMinY(slice) + 0.5;
maxY = minY;
}
CGContextBeginPath(context);
CGContextMoveToPoint(context, minX, minY);
CGContextAddLineToPoint(context, maxX, maxY);
CGContextSetStrokeColor(context, colors[sideIndex]);
CGContextStrokePath(context);
}
CGContextRestoreGState(context);
return resultRect;
}
-5
View File
@@ -20,11 +20,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 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
View File
@@ -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
View File
@@ -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];
-263
View File
@@ -1,263 +0,0 @@
/*
* CPKeyBinding.j
* AppKit
*
* Created by Nicholas Small.
* Copyright 2010, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPObject.j>
@import "CPEvent.j"
CPStandardKeyBindings = {
@"@.": @"cancelOperation:",
@"^a": @"moveToBeginningOfParagraph:",
@"^$a": @"moveToBeginningOfParagraphAndModifySelection:",
@"^b": @"moveBackward:",
@"^$b": @"moveBackwardAndModifySelection:",
@"^~b": @"moveWordBackward:",
@"^~$b": @"moveWordBackwardAndModifySelection:",
@"^d": @"deleteForward:",
@"^e": @"moveToEndOfParagraph:",
@"^$e": @"moveToEndOfParagraphAndModifySelection:",
@"^f": @"moveForward:",
@"^$f": @"moveForwardAndModifySelection:",
@"^~f": @"moveWordForward:",
@"^~$f": @"moveWordForwardAndModifySelection:",
@"^h": @"deleteBackward:",
@"^k": @"deleteToEndOfParagraph:",
@"^l": @"centerSelectionInVisibleArea:",
@"^n": @"moveDown:",
@"^$n": @"moveDownAndModifySelection:",
@"^o": [@"insertNewlineIgnoringFieldEditor:", @"moveBackward:"],
@"^p": @"moveUp:",
@"^$p": @"moveUpAndModifySelection:",
@"^t": @"transpose:",
@"^v": @"pageDown:",
@"^$v": @"pageDownAndModifySelection:",
@"^y": @"yank:"
};
CPStandardKeyBindings[CPNewlineCharacter] = @"insertNewline:";
CPStandardKeyBindings[CPCarriageReturnCharacter] = @"insertNewline:";
CPStandardKeyBindings[CPEnterCharacter] = @"insertNewline:";
CPStandardKeyBindings[@"~" + CPNewlineCharacter] = @"insertNewlineIgnoringFieldEditor:";
CPStandardKeyBindings[@"~" + CPCarriageReturnCharacter] = @"insertNewlineIgnoringFieldEditor:";
CPStandardKeyBindings[@"~" + CPEnterCharacter] = @"insertNewlineIgnoringFieldEditor:";
CPStandardKeyBindings[@"^" + CPNewlineCharacter] = @"insertLineBreak:";
CPStandardKeyBindings[@"^" + CPCarriageReturnCharacter] = @"insertLineBreak:";
CPStandardKeyBindings[@"^" + CPEnterCharacter] = @"insertLineBreak:";
CPStandardKeyBindings[CPBackspaceCharacter] = @"deleteBackward:";
CPStandardKeyBindings[@"~" + CPBackspaceCharacter] = @"deleteWordBackward:";
CPStandardKeyBindings[CPDeleteCharacter] = @"deleteBackward:";
CPStandardKeyBindings[@"@" + CPDeleteCharacter] = @"deleteToBeginningOfLine:";
CPStandardKeyBindings[@"~" + CPDeleteCharacter] = @"deleteWordBackward:";
CPStandardKeyBindings[@"^" + CPDeleteCharacter] = @"deleteBackwardByDecomposingPreviousCharacter:";
CPStandardKeyBindings[@"^~" + CPDeleteCharacter] = @"deleteWordBackward:";
CPStandardKeyBindings[CPDeleteFunctionKey] = @"deleteForward:";
CPStandardKeyBindings[@"~" + CPDeleteFunctionKey] = @"deleteWordForward:";
CPStandardKeyBindings[CPTabCharacter] = @"insertTab:";
CPStandardKeyBindings[@"~" + CPTabCharacter] = @"insertTabIgnoringFieldEditor:";
CPStandardKeyBindings[@"^" + CPTabCharacter] = @"selectNextKeyView:";
CPStandardKeyBindings[CPBackTabCharacter] = @"insertBacktab:";
CPStandardKeyBindings[@"^" + CPBackTabCharacter] = @"selectPreviousKeyView:";
CPStandardKeyBindings[CPEscapeFunctionKey] = @"cancelOperation:";
CPStandardKeyBindings[@"~" + CPEscapeFunctionKey] = @"complete:";
CPStandardKeyBindings[CPF5FunctionKey] = @"complete:";
CPStandardKeyBindings[CPLeftArrowFunctionKey] = @"moveLeft:";
CPStandardKeyBindings[@"~" + CPLeftArrowFunctionKey] = @"moveWordLeft:";
CPStandardKeyBindings[@"^" + CPLeftArrowFunctionKey] = @"moveToLeftEndOfLine:";
CPStandardKeyBindings[@"@" + CPLeftArrowFunctionKey] = @"moveToLeftEndOfLine:";
CPStandardKeyBindings[@"$" + CPLeftArrowFunctionKey] = @"moveLeftAndModifySelection:";
CPStandardKeyBindings[@"$~" + CPLeftArrowFunctionKey] = @"moveWordLeftAndModifySelection:";
CPStandardKeyBindings[@"$^" + CPLeftArrowFunctionKey] = @"moveToLeftEndOfLineAndModifySelection:";
CPStandardKeyBindings[@"$@" + CPLeftArrowFunctionKey] = @"moveToLeftEndOfLineAndModifySelection:";
CPStandardKeyBindings[@"@^" + CPLeftArrowFunctionKey] = @"makeBaseWritingDirectionRightToLeft:";
CPStandardKeyBindings[@"@^~" + CPLeftArrowFunctionKey] = @"makeTextWritingDirectionRightToLeft:";
CPStandardKeyBindings[CPRightArrowFunctionKey] = @"moveRight:";
CPStandardKeyBindings[@"~" + CPRightArrowFunctionKey] = @"moveWordRight:";
CPStandardKeyBindings[@"^" + CPRightArrowFunctionKey] = @"moveToRightEndOfLine:";
CPStandardKeyBindings[@"@" + CPRightArrowFunctionKey] = @"moveToRightEndOfLine:";
CPStandardKeyBindings[@"$" + CPRightArrowFunctionKey] = @"moveRightAndModifySelection:";
CPStandardKeyBindings[@"$~" + CPRightArrowFunctionKey] = @"moveWordRightAndModifySelection:";
CPStandardKeyBindings[@"$^" + CPRightArrowFunctionKey] = @"moveToRightEndOfLineAndModifySelection:";
CPStandardKeyBindings[@"$@" + CPRightArrowFunctionKey] = @"moveToRightEndOfLineAndModifySelection:";
CPStandardKeyBindings[@"@^" + CPRightArrowFunctionKey] = @"makeBaseWritingDirectionLeftToRight:";
CPStandardKeyBindings[@"@^~" + CPRightArrowFunctionKey] = @"makeTextWritingDirectionLeftToRight:";
CPStandardKeyBindings[CPUpArrowFunctionKey] = @"moveUp:";
CPStandardKeyBindings[@"~" + CPUpArrowFunctionKey] = [@"moveBackward:", @"moveToBeginningOfParagraph:"];
CPStandardKeyBindings[@"^" + CPUpArrowFunctionKey] = @"scrollPageUp:";
CPStandardKeyBindings[@"@" + CPUpArrowFunctionKey] = @"moveToBeginningOfDocument:";
CPStandardKeyBindings[@"$" + CPUpArrowFunctionKey] = @"moveUpAndModifySelection:";
CPStandardKeyBindings[@"$~" + CPUpArrowFunctionKey] = @"moveParagraphBackwardAndModifySelection:";
CPStandardKeyBindings[@"$@" + CPUpArrowFunctionKey] = @"moveToBeginningOfDocumentAndModifySelection:";
CPStandardKeyBindings[CPDownArrowFunctionKey] = @"moveDown:";
CPStandardKeyBindings[@"~" + CPDownArrowFunctionKey] = [@"moveForward:", @"moveToEndOfParagraph:"];
CPStandardKeyBindings[@"^" + CPDownArrowFunctionKey] = @"scrollPageDown:";
CPStandardKeyBindings[@"@" + CPDownArrowFunctionKey] = @"moveToEndOfDocument:";
CPStandardKeyBindings[@"$" + CPDownArrowFunctionKey] = @"moveDownAndModifySelection:";
CPStandardKeyBindings[@"$~" + CPDownArrowFunctionKey] = @"moveParagraphForwardAndModifySelection:";
CPStandardKeyBindings[@"$@" + CPDownArrowFunctionKey] = @"moveToEndOfDocumentAndModifySelection:";
CPStandardKeyBindings[@"@^" + CPDownArrowFunctionKey] = @"makeBaseWritingDirectionNatural:";
CPStandardKeyBindings[@"@^~" + CPDownArrowFunctionKey] = @"makeTextWritingDirectionNatural:";
CPStandardKeyBindings[CPHomeFunctionKey] = @"scrollToBeginningOfDocument:";
CPStandardKeyBindings[@"$" + CPHomeFunctionKey] = @"moveToBeginningOfDocumentAndModifySelection:";
CPStandardKeyBindings[CPEndFunctionKey] = @"scrollToEndOfDocument:";
CPStandardKeyBindings[@"$" + CPEndFunctionKey] = @"moveToEndOfDocumentAndModifySelection:";
CPStandardKeyBindings[CPPageUpFunctionKey] = @"scrollPageUp:";
CPStandardKeyBindings[@"~" + CPPageUpFunctionKey] = @"pageUp:";
CPStandardKeyBindings[@"$" + CPPageUpFunctionKey] = @"pageUpAndModifySelection:";
CPStandardKeyBindings[CPPageDownFunctionKey] = @"scrollPageDown:";
CPStandardKeyBindings[@"~" + CPPageDownFunctionKey] = @"pageDown:";
CPStandardKeyBindings[@"$" + CPPageDownFunctionKey] = @"pageDownAndModifySelection:";
var CPKeyBindingCache = {};
@implementation CPKeyBinding : CPObject
{
CPString _key;
unsigned _modifierFlags;
CPArray _selectors;
CPString _cacheName;
}
+ (void)initialize
{
if ([self class] !== CPKeyBinding)
return;
[self createKeyBindingsFromJSObject:CPStandardKeyBindings];
}
+ (void)createKeyBindingsFromJSObject:(JSObject)anObject
{
var binding;
for (binding in anObject)
[self cacheKeyBinding:[[CPKeyBinding alloc] initWithPhysicalKeyString:binding selectors:anObject[binding]]];
}
+ (void)cacheKeyBinding:(CPKeyBinding)aBinding
{
if (!aBinding)
return;
CPKeyBindingCache[[aBinding _cacheName]] = aBinding;
}
+ (CPKeyBinding)keyBindingForKey:(CPString)aKey modifierFlags:(unsigned)aFlag
{
var tempBinding = [[self alloc] initWithKey:aKey modifierFlags:aFlag selectors:nil];
return CPKeyBindingCache[[tempBinding _cacheName]];
}
+ (CPArray)selectorsForKey:(CPString)aKey modifierFlags:(unsigned)aFlag
{
return [[self keyBindingForKey:aKey modifierFlags:aFlag] selectors];
}
- (id)initWithPhysicalKeyString:(CPString)binding selectors:(CPArray)selectors
{
var components = binding.split(@""),
modifierFlags = ([components containsObject:@"$"] ? CPShiftKeyMask : 0) |
([components containsObject:@"^"] ? CPControlKeyMask : 0) |
([components containsObject:@"~"] ? CPAlternateKeyMask : 0) |
([components containsObject:@"@"] ? CPCommandKeyMask : 0);
if (![selectors isKindOfClass:CPArray])
selectors = [selectors];
return [self initWithKey:[components lastObject] modifierFlags:modifierFlags selectors:selectors];
}
- (id)initWithKey:(CPString)aKey modifierFlags:(unsigned)aFlag selectors:(CPArray)selectors
{
self = [super init];
if (self)
{
_key = aKey;
_modifierFlags = aFlag;
_selectors = selectors;
// We normalize our key binding string in order to properly cache it.
// We want to ensure the modifiers are always in the same order.
var cacheName = [];
if (_modifierFlags & CPCommandKeyMask)
cacheName.push(@"@");
if (_modifierFlags & CPControlKeyMask)
cacheName.push(@"^");
if (_modifierFlags & CPAlternateKeyMask)
cacheName.push(@"~");
if (_modifierFlags & CPShiftKeyMask)
cacheName.push(@"$");
cacheName.push(_key);
_cacheName = cacheName.join(@"");
}
return self;
}
- (CPString)key
{
return _key;
}
- (unsigned)modifierFlags
{
return _modifierFlags;
}
- (CPArray)selectors
{
return _selectors;
}
- (CPString)_cacheName
{
return _cacheName;
}
- (BOOL)isEqual:(CPKeyBinding)rhs
{
return _key === [rhs key] && _modifierFlags === [rhs modifierFlags];
}
- (CPString)description
{
return [CPString stringWithFormat:@"<KeyBinding string: '%@' modifierFlags: 0x%lx selectors: %@>", _key, _modifierFlags, _selectors];
}
@end
-472
View File
@@ -1,472 +0,0 @@
/*
* CPKeyValueBinding.j
* AppKit
*
* Created by Ross Boucher 1/13/09
* Copyright 280 North, Inc.
*
* Adapted from GNUStep
* Released under the LGPL.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPObject.j>
@import <Foundation/CPArray.j>
@import <Foundation/CPDictionary.j>
@import <Foundation/CPValueTransformer.j>
var exposedBindingsMap = [CPDictionary new],
bindingsMap = [CPDictionary new];
var CPBindingOperationAnd = 0,
CPBindingOperationOr = 1;
@implementation CPKeyValueBinding : CPObject
{
CPDictionary _info;
id _source;
}
+ (void)exposeBinding:(CPString)aBinding forClass:(Class)aClass
{
var bindings = [exposedBindingsMap objectForKey:[aClass hash]];
if (!bindings)
{
bindings = [];
[exposedBindingsMap setObject:bindings forKey:[aClass hash]];
}
bindings.push(aBinding);
}
+ (CPArray)exposedBindingsForClass:(Class)aClass
{
return [[exposedBindingsMap objectForKey:[aClass hash]] copy];
}
+ (CPKeyValueBinding)getBinding:(CPString)aBinding forObject:(id)anObject
{
return [[bindingsMap objectForKey:[anObject hash]] objectForKey:aBinding];
}
+ (CPDictionary)infoForBinding:(CPString)aBinding forObject:(id)anObject
{
var theBinding = [self getBinding:aBinding forObject:anObject];
if (theBinding)
return theBinding._info;
return nil;
}
+ (CPDictionary)allBindingsForObject:(id)anObject
{
return [bindingsMap objectForKey:[anObject hash]];
}
+ (void)unbind:(CPString)aBinding forObject:(id)anObject
{
var bindings = [bindingsMap objectForKey:[anObject hash]];
if (!bindings)
return;
var theBinding = [bindings objectForKey:aBinding];
if (!theBinding)
return;
var infoDictionary = theBinding._info,
observedObject = [infoDictionary objectForKey:CPObservedObjectKey],
keyPath = [infoDictionary objectForKey:CPObservedKeyPathKey];
[observedObject removeObserver:theBinding forKeyPath:keyPath];
[bindings removeObjectForKey:aBinding];
}
+ (void)unbindAllForObject:(id)anObject
{
var bindings = [bindingsMap objectForKey:[anObject hash]];
if (!bindings)
return;
var allKeys = [bindings allKeys],
count = allKeys.length;
while (count--)
[anObject unbind:[bindings objectForKey:allKeys[count]]];
[bindingsMap removeObjectForKey:[anObject hash]];
}
- (id)initWithBinding:(CPString)aBinding name:(CPString)aName to:(id)aDestination keyPath:(CPString)aKeyPath options:(CPDictionary)options from:(id)aSource
{
self = [super init];
if (self)
{
_source = aSource;
_info = [CPDictionary dictionaryWithObjects:[aDestination, aKeyPath] forKeys:[CPObservedObjectKey, CPObservedKeyPathKey]];
if (options)
[_info setObject:options forKey:CPOptionsKey];
[aDestination addObserver:self forKeyPath:aKeyPath options:CPKeyValueObservingOptionNew context:aBinding];
var bindings = [bindingsMap objectForKey:[_source hash]];
if (!bindings)
{
bindings = [CPDictionary new];
[bindingsMap setObject:bindings forKey:[_source hash]];
}
[bindings setObject:self forKey:aName];
[self setValueFor:aBinding];
}
return self;
}
- (void)setValueFor:(CPString)aBinding
{
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey],
options = [_info objectForKey:CPOptionsKey],
newValue = [destination valueForKeyPath:keyPath],
isPlaceholder = CPIsControllerMarker(newValue);
if (isPlaceholder)
{
switch (newValue)
{
case CPMultipleValuesMarker:
newValue = [options objectForKey:CPMultipleValuesPlaceholderBindingOption] || @"Multiple Values";
break;
case CPNoSelectionMarker:
newValue = [options objectForKey:CPNoSelectionPlaceholderBindingOption] || @"No Selection";
break;
case CPNotApplicableMarker:
if ([options objectForKey:CPRaisesForNotApplicableKeysBindingOption])
[CPException raise:CPGenericException reason:@"can't transform non applicable key on: "+_source+" value: "+newValue];
newValue = [options objectForKey:CPNotApplicablePlaceholderBindingOption] || @"Not Applicable";
break;
}
}
else
{
// Only transform the value if the current value is not a placeholder
newValue = [self transformValue:newValue withOptions:options];
}
[_source setValue:newValue forKey:aBinding];
if ([_source respondsToSelector:@selector(_setCurrentValueIsPlaceholder:)])
[_source _setCurrentValueIsPlaceholder:isPlaceholder];
}
- (void)reverseSetValueFor:(CPString)aBinding
{
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey],
options = [_info objectForKey:CPOptionsKey],
newValue = [_source valueForKeyPath:aBinding];
newValue = [self reverseTransformValue:newValue withOptions:options];
[destination setValue:newValue forKeyPath:keyPath];
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)changes context:(id)context
{
if (!changes)
return;
[self setValueFor:context];
}
- (id)transformValue:(id)aValue withOptions:(CPDictionary)options
{
var valueTransformerName,
valueTransformer,
placeholder;
var valueTransformerName = [options objectForKey:CPValueTransformerNameBindingOption],
valueTransformer;
if (valueTransformerName)
{
valueTransformer = [CPValueTransformer valueTransformerForName:valueTransformerName];
if (!valueTransformer)
{
var valueTransformerClass = CPClassFromString(valueTransformerName);
if (valueTransformerClass)
{
valueTransformer = [[valueTransformerClass alloc] init];
[valueTransformerClass setValueTransformer:valueTransformer forName:valueTransformerName];
}
}
}
else
valueTransformer = [options objectForKey:CPValueTransformerBindingOption];
if (valueTransformer)
aValue = [valueTransformer transformedValue:aValue];
if (aValue === undefined || aValue === nil)
aValue = [options objectForKey:CPNullPlaceholderBindingOption] || nil;
return aValue;
}
- (id)reverseTransformValue:(id)aValue withOptions: (CPDictionary)options
{
var valueTransformerName = [options objectForKey:CPValueTransformerNameBindingOption],
valueTransformer;
if (valueTransformerName)
valueTransformer = [CPValueTransformer valueTransformerForName:valueTransformerName];
else
valueTransformer = [options objectForKey:CPValueTransformerBindingOption];
if (valueTransformer && [[valueTransformer class] allowsReverseTransformation])
aValue = [valueTransformer reverseTransformedValue:aValue];
return aValue;
}
@end
@implementation CPObject (KeyValueBindingCreation)
+ (void)exposeBinding:(CPString)aBinding
{
[CPKeyValueBinding exposeBinding:aBinding forClass:[self class]];
}
- (CPArray)exposedBindings
{
var exposedBindings = [],
theClass = [self class];
while (theClass)
{
var temp = [CPKeyValueBinding exposedBindingsForClass:theClass];
if (temp)
[exposedBindings addObjectsFromArray:temp];
theClass = [theClass superclass];
}
return exposedBindings;
}
- (Class)valueClassForBinding:(CPString)binding
{
return [CPString class];
}
- (void)bind:(CPString)aBinding toObject:(id)anObject withKeyPath:(CPString)aKeyPath options:(CPDictionary)options
{
if (!anObject || !aKeyPath)
return CPLog.error("Invalid object or path on "+self+" for "+aBinding);
//if (![[self exposedBindings] containsObject:aBinding])
// CPLog.warn("No binding exposed on "+self+" for "+aBinding);
[self unbind:aBinding];
[[CPKeyValueBinding alloc] initWithBinding:[self _replacementKeyPathForBinding:aBinding] name:aBinding to:anObject keyPath:aKeyPath options:options from:self];
}
- (CPDictionary)infoForBinding:(CPString)aBinding
{
return [CPKeyValueBinding infoForBinding:aBinding forObject:self];
}
- (void)unbind:(CPString)aBinding
{
[CPKeyValueBinding unbind:aBinding forObject:self];
}
- (id)_replacementKeyPathForBinding:(CPString)binding
{
return binding;
}
@end
@implementation _CPKeyValueOrBinding : CPKeyValueBinding
{
}
- (void)setValueFor:(CPString)aBinding
{
var bindings = [bindingsMap valueForKey:[_source hash]];
if (!bindings)
return;
[_source setValue:resolveMultipleValues(aBinding, bindings, CPBindingOperationOr) forKey:aBinding];
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)changes context:(id)context
{
[self setValueFor:context];
}
@end
@implementation _CPKeyValueAndBinding : CPKeyValueBinding
{
}
- (void)setValueFor:(CPString)aBinding
{
var bindings = [bindingsMap objectForKey:[_source hash]];
if (!bindings)
return;
[_source setValue:resolveMultipleValues(aBinding, bindings, CPBindingOperationAnd) forKey:aBinding];
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObejct change:(CPDictionary)changes context:(id)context
{
[self setValueFor:context];
}
@end
var resolveMultipleValues = function resolveMultipleValues(/*CPString*/key, /*CPDictionary*/bindings, /*GSBindingOperationKind*/operation)
{
var bindingName = key,
theBinding,
count = 1;
while (theBinding = [bindings objectForKey:bindingName])
{
var infoDictionary = theBinding._info,
object = [infoDictionary objectForKey:CPObservedObjectKey],
keyPath = [infoDictionary objectForKey:CPObservedKeyPathKey],
options = [infoDictionary objectForKey:CPOptionsKey];
var value = [theBinding transformValue:[object valueForKeyPath:keyPath] withOptions:options];
if (value == operation)
return operation;
bindingName = [CPString stringWithFormat:@"%@%i", key, ++count];
}
return !operation;
}
var invokeAction = function invokeAction(/*CPString*/targetKey, /*CPString*/argumentKey, /*CPDictionary*/bindings)
{
var theBinding = [bindings objectForKey:targetKey],
infoDictionary = theBinding._info,
object = [infoDictionary objectForKey:CPObservedObjectKey],
keyPath = [infoDictionary objectForKey:CPObservedKeyPathKey],
options = [infoDictionary objectForKey:CPOptionsKey],
target = [object valueForKeyPath:keyPath],
selector = [options objectForKey:CPSelectorNameBindingOption];
if (!target || !selector)
return;
var invocation = [CPInvocation invocationWithMethodSignature:[target methodSignatureForSelector:selector]];
[invocation setSelector:selector];
var bindingName = argumentKey,
count = 1;
while (theBinding = [bindings objectForKey:bindingName])
{
infoDictionary = theBinding._info;
keyPath = [infoDictionary objectForKey:CPObserverKeyPathKey];
object = [[infoDictionary objectForKey:CPObservedObjectKey] valueForKeyPath:keyPath];
if (object)
[invocation setArgument:object atIndex:++count];
bindingName = [CPString stringWithFormat:@"%@%i", argumentKey, count];
}
[invocation invoke];
}
// Keys in options dictionary
// Keys in dictionary returned by infoForBinding
CPObservedObjectKey = @"CPObservedObjectKey";
CPObservedKeyPathKey = @"CPObservedKeyPathKey";
CPOptionsKey = @"CPOptionsKey";
// special markers
CPMultipleValuesMarker = @"CPMultipleValuesMarker";
CPNoSelectionMarker = @"CPNoSelectionMarker";
CPNotApplicableMarker = @"CPNotApplicableMarker";
// Binding name constants
CPAlignmentBinding = @"CPAlignmentBinding";
CPEditableBinding = @"CPEditableBinding";
CPEnabledBinding = @"CPEnabledBinding";
CPFontBinding = @"CPFontBinding";
CPHiddenBinding = @"CPHiddenBinding";
CPSelectedIndexBinding = @"CPSelectedIndexBinding";
CPTextColorBinding = @"CPTextColorBinding";
CPToolTipBinding = @"CPToolTipBinding";
CPValueBinding = @"value";
//Binding options constants
CPAllowsEditingMultipleValuesSelectionBindingOption = @"CPAllowsEditingMultipleValuesSelectionBindingOption";
CPAllowsNullArgumentBindingOption = @"CPAllowsNullArgumentBindingOption";
CPConditionallySetsEditableBindingOption = @"CPConditionallySetsEditableBindingOption";
CPConditionallySetsEnabledBindingOption = @"CPConditionallySetsEnabledBindingOption";
CPConditionallySetsHiddenBindingOption = @"CPConditionallySetsHiddenBindingOption";
CPContinuouslyUpdatesValueBindingOption = @"CPContinuouslyUpdatesValueBindingOption";
CPCreatesSortDescriptorBindingOption = @"CPCreatesSortDescriptorBindingOption";
CPDeletesObjectsOnRemoveBindingsOption = @"CPDeletesObjectsOnRemoveBindingsOption";
CPDisplayNameBindingOption = @"CPDisplayNameBindingOption";
CPDisplayPatternBindingOption = @"CPDisplayPatternBindingOption";
CPHandlesContentAsCompoundValueBindingOption = @"CPHandlesContentAsCompoundValueBindingOption";
CPInsertsNullPlaceholderBindingOption = @"CPInsertsNullPlaceholderBindingOption";
CPInvokesSeparatelyWithArrayObjectsBindingOption = @"CPInvokesSeparatelyWithArrayObjectsBindingOption";
CPMultipleValuesPlaceholderBindingOption = @"CPMultipleValuesPlaceholderBindingOption";
CPNoSelectionPlaceholderBindingOption = @"CPNoSelectionPlaceholderBindingOption";
CPNotApplicablePlaceholderBindingOption = @"CPNotApplicablePlaceholderBindingOption";
CPNullPlaceholderBindingOption = @"CPNullPlaceholderBindingOption";
CPPredicateFormatBindingOption = @"CPPredicateFormatBindingOption";
CPRaisesForNotApplicableKeysBindingOption = @"CPRaisesForNotApplicableKeysBindingOption";
CPSelectorNameBindingOption = @"CPSelectorNameBindingOption";
CPSelectsAllWhenSettingContentBindingOption = @"CPSelectsAllWhenSettingContentBindingOption";
CPValidatesImmediatelyBindingOption = @"CPValidatesImmediatelyBindingOption";
CPValueTransformerNameBindingOption = @"CPValueTransformerNameBindingOption";
CPValueTransformerBindingOption = @"CPValueTransformerBindingOption";
CPIsControllerMarker = function(/*id*/anObject)
{
return anObject === CPMultipleValuesMarker || anObject === CPNoSelectionMarker || anObject === CPNotApplicableMarker;
}
+15 -8
View File
@@ -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";
@@ -72,7 +75,7 @@ var _CPMenuBarVisible = NO,
id _delegate; id _delegate;
int _highlightedIndex; CPMenuItem _highlightedIndex;
_CPMenuWindow _menuWindow; _CPMenuWindow _menuWindow;
} }
@@ -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.
@@ -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];
+4 -1
View File
@@ -1,4 +1,7 @@
@import "CPPanel.j"
#include "../CoreGraphics/CGGeometry.h"
#include "../Platform/Platform.h"
@import "_CPMenuWindow.j" @import "_CPMenuWindow.j"
+4 -1
View File
@@ -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];
+2 -1
View File
@@ -1,4 +1,5 @@
@import "CPWindow.j"
#include "../CoreGraphics/CGGeometry.h"
var _CPMenuWindowPool = [], var _CPMenuWindowPool = [],
+3 -45
View File
@@ -29,7 +29,6 @@
@import "CPView.j" @import "CPView.j"
@import "_CPMenuItemView.j" @import "_CPMenuItemView.j"
/*! /*!
@ingroup appkit @ingroup appkit
@class CPMenuItem @class CPMenuItem
@@ -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))
{ {
@@ -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
@@ -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);
@@ -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 -1
View File
@@ -1,5 +1,5 @@
@import "CPView.j" @import <AppKit/CPView.j>
@implementation _CPMenuItemSeparatorView : CPView @implementation _CPMenuItemSeparatorView : CPView
+5 -11
View File
@@ -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 -3
View File
@@ -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];
-625
View File
@@ -1,625 +0,0 @@
@import <Foundation/CPDictionary.j>
@import <Foundation/CPCountedSet.j>
@import "CPController.j"
@implementation CPObjectController : CPController
{
id _contentObject;
id _selection;
Class _objectClass;
BOOL _isEditable;
BOOL _automaticallyPreparesContent;
CPCountedSet _observedKeys;
}
+ (id)initialize
{
[self exposeBinding:@"editable"];
[self exposeBinding:@"contentObject"];
}
+ (CPSet)keyPathsForValuesAffectingContentObject
{
return [CPSet setWithObjects:"content"];
}
+ (BOOL)automaticallyNotifiesObserversForKey:(CPString)aKey
{
if (aKey === @"contentObject")
return NO;
return YES;
}
+ (CPSet)keyPathsForValuesAffectingCanAdd
{
return [CPSet setWithObject:"editable"];
}
+ (CPSet)keyPathsForValuesAffectingCanInsert
{
return [CPSet setWithObject:"editable"];
}
+ (CPSet)keyPathsForValuesAffectingCanRemove
{
return [CPSet setWithObjects:"editable", "selection"];
}
- (id)init
{
return [self initWithContent:nil];
}
- (id)initWithContent:(id)aContent
{
if (self = [super init])
{
[self setContent:aContent];
[self setEditable:YES];
[self setObjectClass:[CPMutableDictionary class]];
_observedKeys = [[CPCountedSet alloc] init];
}
return self;
}
- (id)content
{
return _contentObject;
}
- (void)setContent:(id)aContent
{
[self willChangeValueForKey:@"contentObject"];
[self _selectionWillChange];
_contentObject = aContent;
[self didChangeValueForKey:@"contentObject"];
[self _selectionDidChange];
}
- (void)_setContentObject:(id)aContent
{
[self setContent:aContent];
}
- (id)_contentObject
{
return [self content];
}
- (void)setAutomaticallyPreparesContent:(BOOL)shouldAutomaticallyPrepareContent
{
_automaticallyPreparesContent = shouldAutomaticallyPrepareContent;
}
- (BOOL)automaticallyPreparesContent
{
return _automaticallyPreparesContent;
}
- (void)prepareContent
{
[self setContent:[self newObject]];
}
- (void)setObjectClass:(Class)aClass
{
_objectClass = aClass;
}
- (Class)objectClass
{
return _objectClass;
}
- (id)newObject
{
return [[[self objectClass] alloc] init];
}
- (void)addObject:(id)anObject
{
[self setContent:anObject];
[[CPKeyValueBinding getBinding:@"contentObject" forObject:self] reverseSetValueFor:@"contentObject"];
}
- (void)removeObject:(id)anObject
{
if ([self content] === anObject)
[self setContent:nil];
[[CPKeyValueBinding getBinding:@"contentObject" forObject:self] reverseSetValueFor:@"contentObject"];
}
- (void)add:(id)aSender
{
// FIXME: This should happen on the next run loop?
[self addObject:[self newObject]];
}
- (BOOL)canAdd
{
return [self isEditable];
}
- (void)remove:(id)aSender
{
// FIXME: This should happen on the next run loop?
[self removeObject:[self content]];
}
- (BOOL)canRemove
{
return [self isEditable] && [[self selectedObjects] count];
}
- (void)setEditable:(BOOL)shouldBeEditable
{
_isEditable = shouldBeEditable;
}
- (BOOL)isEditable
{
return _isEditable;
}
- (CPArray)selectedObjects
{
return [[_CPObservableArray alloc] initWithObjects:[_contentObject] count:1];
}
- (id)selection
{
return _selection;
}
- (void)_selectionWillChange
{
[_selection controllerWillChange];
[self willChangeValueForKey:@"selection"];
}
- (void)_selectionDidChange
{
if (_selection === undefined || _selection === nil)
_selection = [[CPControllerSelectionProxy alloc] initWithController:self];
[_selection controllerDidChange];
[self didChangeValueForKey:@"selection"];
}
- (id)observedKeys
{
return _observedKeys;
}
- (void)addObserver:(id)anObserver forKeyPath:(CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(id)context
{
[_observedKeys addObject:aKeyPath];
[super addObserver:anObserver forKeyPath:aKeyPath options:options context:context];
}
- (void)removeObserver:(id)anObserver forKeyPath:(CPString)aKeyPath
{
[_observedKeys removeObject:aKeyPath];
[super removeObserver:anObserver forKeyPath:aKeyPath];
}
@end
var CPObjectControllerObjectClassNameKey = @"CPObjectControllerObjectClassNameKey",
CPObjectControllerIsEditableKey = @"CPObjectControllerIsEditableKey",
CPObjectControllerAutomaticallyPreparesContentKey = @"CPObjectControllerAutomaticallyPreparesContentKey";
@implementation CPObjectController (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
var objectClassName = [aCoder decodeObjectForKey:CPObjectControllerObjectClassNameKey],
objectClass = CPClassFromString(objectClassName);
// FIXME: Error if objectClass === nil
[self setObjectClass:objectClass];
[self setEditable:[aCoder decodeBoolForKey:CPObjectControllerIsEditableKey]];
[self setAutomaticallyPreparesContent:[aCoder decodeBoolForKey:CPObjectControllerAutomaticallyPreparesContentKey] || NO];
_observedKeys = [[CPCountedSet alloc] init];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:CPStringFromClass(objectClass) forKey:CPObjectControllerObjectClassNameKey];
[aCoder encodeObject:[self isEditable] forKey:CPObjectControllerIsEditableKey];
if (![self automaticallyPreparesContent])
[aCoder encodeBOOL:YES forKey:CPObjectControllerAutomaticallyPreparesContentKey];
}
@end
@implementation _CPObservationProxy : CPObject
{
id _keyPath;
id _observer;
id _object;
BOOL _notifyObject;
id _context;
int _options;
}
- (id)initWithKeyPath:(id)aKeyPath observer:(id)anObserver object:(id)anObject
{
if (self=[super init])
{
_keyPath = aKeyPath;
_observer = anObserver;
_object = anObject;
}
return self;
}
- (id)observer
{
return _observer;
}
- (id)keyPath
{
return _keyPath;
}
- (id)context
{
return _context;
}
- (int)options
{
return _options;
}
- (void)setNotifyObject:(BOOL)notify
{
_notifyObject = notify;
}
- (BOOL)isEqual:(id)anObject
{
if ([anObject class] === [self class])
{
if (anObject._observer === _observer && [anObject._keyPath isEqual:_keyPath] && [anObject._object isEqual:_object])
return YES;
}
return NO;
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)change context:(id)context
{
if (_notifyObject)
[_object observeValueForKeyPath:_keyPath ofObject:_object change:change context:context];
[_observer observeValueForKeyPath:_keyPath ofObject:_object change:change context:context];
}
- (CPString)description
{
return [super description] + [CPString stringWithFormat:@"observation proxy for %@ on key path %@", _observer, _keyPath];
}
@end
@implementation _CPObservableArray : CPMutableArray
{
CPArray _observationProxies;
}
+ (id)alloc
{
var a = [];
a.isa = self;
var ivars = class_copyIvarList(self),
count = ivars.length;
while (count--)
a[ivar_getName(ivars[count])] = nil;
return a;
}
- (CPString)description
{
return "<_CPObservableArray: "+[super description]+" >";
}
- (id)initWithArray:(CPArray)anArray
{
if (self = [super initWithArray:anArray])
{
_observationProxies = [];
}
return self;
}
- (id)initWithObjects:(CPArray)objects count:(unsigned)count
{
if (self = [super initWithObjects:objects count:count])
{
_observationProxies = [];
}
return self;
}
-(void)addObserver:(id)anObserver forKeyPath:(CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(id)context
{
if (aKeyPath.indexOf("@") === 0)
{
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObserver object:self];
proxy._options = options;
proxy._context = context;
[_observationProxies addObject:proxy];
var dotIndex = aKeyPath.indexOf("."),
remaining = aKeyPath.substring(dotIndex+1),
indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self count])];
[self addObserver:proxy toObjectsAtIndexes:indexes forKeyPath:remaining options:options context:context];
}
else
{
var indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self count])];
[self addObserver:anObserver toObjectsAtIndexes:indexes forKeyPath:aKeyPath options:options context:context];
}
}
- (void)removeObserver:(id)anObserver forKeyPath:(CPString)aKeyPath
{
if (aKeyPath.indexOf("@") === 0)
{
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObserver object:self],
index = [_observationProxies indexOfObject:proxy];
proxy = [_observationProxies objectAtIndex:index];
var dotIndex = aKeyPath.indexOf("."),
remaining = aKeyPath.substring(dotIndex+1),
indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self count])];
[self removeObserver:proxy fromObjectsAtIndexes:indexes forKeyPath:remaining];
}
else
{
var indexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self count])];
[self removeObserver:anObserver fromObjectsAtIndexes:indexes forKeyPath:aKeyPath];
}
}
- (void)insertObject:(id)anObject atIndex:(unsigned)anIndex
{
for (var i=0, count=[_observationProxies count]; i<count; i++)
{
var proxy = [_observationProxies objectAtIndex:i],
keyPath = [proxy keyPath],
operator = keyPath.indexOf(".") === 0;
if (operator)
[self willChangeValueForKey:keyPath];
[anObject addObserver:proxy forKeyPath:keyPath options:[proxy options] context:[proxy context]];
if (operator)
[self didChangeValueForKey:keyPath];
}
[super insertObject:anObject atIndex:anIndex];
}
- (void)removeObjectAtIndex:(unsigned)anIndex
{
for (var i=0, count=[_observationProxies count]; i<count; i++)
{
var proxy = [_observationProxies objectAtIndex:i],
keyPath = [proxy keyPath],
operator = keyPath.indexOf(".") === 0;
if (operator)
[self willChangeValueForKey:keyPath];
[anObject removeObserver:proxy forKeyPath:keyPath];
if (operator)
[self didChangeValueForKey:keyPath];
}
[super removeObjectAtIndex:anIndex];
}
- (_CPObservableArray)objectsAtIndexes:(CPIndexSet)theIndexes
{
return [_CPObservableArray arrayWithArray:[super objectsAtIndexes:theIndexes]];
}
- (void)addObject:(id)anObject
{
[self insertObject:anObject atIndex:[self count]];
}
- (void)removeLastObject
{
[self removeObjectAtIndex:[self count]];
}
- (void)replaceObjectAtIndex:(unsigned)anIndex withObject:(id)anObject
{
var currentObject = [self objectAtIndex:anIndex];
for (var i=0, count=[_observationProxies count]; i<count; i++)
{
var proxy = [_observationProxies objectAtIndex:i],
keyPath = [proxy keyPath],
operator = keyPath.indexOf(".") === 0;
if (operator)
[self willChangeValueForKey:keyPath];
[currentObject removeObserver:proxy forKeyPath:keyPath];
[anObject addObserver:proxy forKeyPath:keyPath options:[proxy options] context:[proxy context]];
if (operator)
[self didChangeValueForKey:keyPath];
}
[super replaceObjectAtIndex:anIndex withObject:anObject];
}
@end
@implementation CPControllerSelectionProxy : CPObject
{
id _controller;
id _keys;
CPDictionary _cachedValues;
CPArray _observationProxies;
}
- (id)initWithController:(id)aController
{
if (self = [super init])
{
_cachedValues = [CPDictionary dictionary];
_observationProxies = [CPArray array];
_controller = aController;
}
return self;
}
- (id)valueForKey:(CPString)aKey
{
var value = [_cachedValues objectForKey:aKey];
if (value !== undefined && value !== nil)
return value;
var allValues = [[_controller selectedObjects] valueForKeyPath:aKey],
count = [allValues count];
if (!count)
value = CPNoSelectionMarker;
else if (count === 1)
value = [allValues objectAtIndex:0];
else
{
if ([_controller alwaysUsesMultipleValuesMarker])
value = CPMultipleValuesMarker;
else
{
value = [allValues objectAtIndex:0];
for (var i=0, count=[allValues count]; i<count && value!=CPMultipleValuesMarker; i++)
{
if (![value isEqual:[allValues objectAtIndex:i]])
value = CPMultipleValuesMarker;
}
}
}
[_cachedValues setValue:value forKey:aKey];
return value;
}
- (unsigned)count
{
return [_cachedValues count];
}
- (id)keyEnumerator
{
return [_cachedValues keyEnumerator];
}
- (void)setValue:(id)aValue forKey:(CPString)aKey
{
[[_controller selectedObjects] setValue:aValue forKey:aKey];
}
-(void)controllerWillChange
{
_keys = [_cachedValues allKeys];
if (!_keys)
return;
for (var i=0, count=_keys.length; i<count; i++)
[self willChangeValueForKey:_keys[i]];
[_cachedValues removeAllObjects];
}
-(void)controllerDidChange
{
[_cachedValues removeAllObjects];
if (!_keys)
return;
for (var i=0, count=_keys.length; i<count; i++)
[self didChangeValueForKey:_keys[i]];
_keys = nil;
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)change context:(id)context
{
[_cachedValues removeObjectForKey:aKeyPath];
}
- (void)addObserver:(id)anObject forKeyPath:(CPString)aKeyPath options:(CPKeyValueObservingOptions)options context:(id)context
{
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObject object:self];
[proxy setNotifyObject:YES];
[_observationProxies addObject:proxy];
[[_controller selectedObjects] addObserver:proxy forKeyPath:aKeyPath options:options context:context];
}
- (void)removeObserver:(id)anObject forKeyPath:(CPString)aKeyPath
{
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObject object:self],
index = [_observationProxies indexOfObject:proxy];
[[_controller selectedObjects] removeObserver:[_observationProxies objectAtIndex:index] forKeyPath:aKeyPath];
[_observationProxies removeObjectAtIndex:index];
}
@end
+1 -1
View File
@@ -1,5 +1,5 @@
@import "CPPanel.j" @import <AppKit/CPPanel.j>
@implementation CPOpenPanel : CPPanel @implementation CPOpenPanel : CPPanel
+60 -306
View File
@@ -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;
@@ -101,8 +85,6 @@ CPOutlineViewDropOnItemIndex = -1;
BOOL _shouldRetargetChildIndex; BOOL _shouldRetargetChildIndex;
CPInteger _retargedChildIndex; CPInteger _retargedChildIndex;
CPTimer _dragHoverTimer;
id _dropItem;
} }
- (id)initWithFrame:(CGRect)aFrame - (id)initWithFrame:(CGRect)aFrame
@@ -126,7 +108,6 @@ CPOutlineViewDropOnItemIndex = -1;
_retargedChildIndex = nil; _retargedChildIndex = nil;
_shouldRetargetChildIndex = NO; _shouldRetargetChildIndex = NO;
_startHoverTime = nil;
[self setIndentationPerLevel:16.0]; [self setIndentationPerLevel:16.0];
[self setIndentationMarkerFollowsDataView:YES]; [self setIndentationMarkerFollowsDataView:YES];
@@ -241,14 +222,8 @@ 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)
{ {
@@ -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];
} }
@@ -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 = [];
[[self selectedRowIndexes] getIndexes:previousSelectedRows maxCount:-1 inIndexRange:nil];
var control = _disclosureControlsForRows[rowIndex], var index = [previousSelectedRows count];
selector = select ? @"setThemeState:" : @"unsetThemeState:"; while (index--)
{
var rowIndex = previousSelectedRows[index],
item = [self itemAtRow:rowIndex];
[control performSelector:CPSelectorFromString(selector) withObject:CPThemeStateSelected]; 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:),
CPOutlineViewDelegate_outlineView_heightOfRowByItem_ , @selector(outlineView:heightOfRowByItem:),
CPOutlineViewDelegate_outlineView_isGroupItem_ , @selector(outlineView:isGroupItem:),
CPOutlineViewDelegate_outlineView_mouseDownInHeaderOfTableColumn_ , @selector(outlineView:mouseDownInHeaderOfTableColumn:),
CPOutlineViewDelegate_outlineView_nextTypeSelectMatchFromItem_toItem_forString_ , @selector(outlineView:nextTypeSelectMatchFromItem:toItem:forString:),
CPOutlineViewDelegate_outlineView_selectionIndexesForProposedSelection_ , @selector(outlineView:selectionIndexesForProposedSelection:),
CPOutlineViewDelegate_outlineView_shouldCollapseItem_ , @selector(outlineView:shouldCollapseItem:),
CPOutlineViewDelegate_outlineView_shouldEditTableColumn_item_ , @selector(outlineView:shouldEditTableColumn:item:),
CPOutlineViewDelegate_outlineView_shouldExpandItem_ , @selector(outlineView:shouldExpandItem:),
CPOutlineViewDelegate_outlineView_shouldReorderColumn_toColumn_ , @selector(outlineView:shouldReorderColumn:toColumn:),
CPOutlineViewDelegate_outlineView_shouldSelectItem_ , @selector(outlineView:shouldSelectItem:),
CPOutlineViewDelegate_outlineView_shouldSelectTableColumn_ , @selector(outlineView:shouldSelectTableColumn:),
CPOutlineViewDelegate_outlineView_shouldShowOutlineViewForItem_ , @selector(outlineView:shouldShowOutlineViewForItem:),
CPOutlineViewDelegate_outlineView_shouldShowViewExpansionForTableColumn_item_ , @selector(outlineView:shouldShowViewExpansionForTableColumn:item:),
CPOutlineViewDelegate_outlineView_shouldTrackView_forTableColumn_item_ , @selector(outlineView:shouldTrackView:forTableColumn:item:),
CPOutlineViewDelegate_outlineView_shouldTypeSelectForEvent_withCurrentSearchString_ , @selector(outlineView:shouldTypeSelectForEvent:withCurrentSearchString:),
CPOutlineViewDelegate_outlineView_sizeToFitWidthOfColumn_ , @selector(outlineView:sizeToFitWidthOfColumn:),
CPOutlineViewDelegate_outlineView_toolTipForView_rect_tableColumn_item_mouseLocation_, @selector(outlineView:toolTipForView:rect:tableColumn:item:mouseLocation:),
CPOutlineViewDelegate_outlineView_typeSelectStringForTableColumn_item_ , @selector(outlineView:typeSelectStringForTableColumn:item:),
CPOutlineViewDelegate_outlineView_willDisplayOutlineView_forTableColumn_item_ , @selector(outlineView:willDisplayOutlineView:forTableColumn:item:),
CPOutlineViewDelegate_outlineView_willDisplayView_forTableColumn_item_ , @selector(outlineView:willDisplayView:forTableColumn:item:),
CPOutlineViewDelegate_selectionShouldChangeInOutlineView_ , @selector(selectionShouldChangeInOutlineView:)
],
delegateCount = [delegateMethods count];
for (var i=0; i < delegateCount; i += 2) if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:shouldSelectItem:)])
{ _implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_shouldSelectItem_;
var bitMask = delegateMethods[i],
selector = delegateMethods[i+1];
if ([_outlineViewDelegate respondsToSelector:selector]) if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:heightOfRowByItem:)])
_implementedOutlineViewDelegateMethods |= bitMask; _implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_heightOfRowByItem_;
}
if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:willDisplayView:forTableColumn:item:)])
_implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_willDisplayView_forTableColumn_item_;
if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:isGroupItem:)])
_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,56 +534,11 @@ 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
@@ -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,38 +709,6 @@ 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...
@@ -1038,13 +880,6 @@ 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_))
@@ -1108,7 +943,7 @@ 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];
@@ -1172,14 +1007,6 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
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]);
}
+2
View File
@@ -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";
+5 -29
View File
@@ -25,6 +25,8 @@
@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;
@@ -44,7 +46,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
CPMenu _menu; CPMenu _menu;
} }
+ (CPString)defaultThemeClass + (CPString)themeClass
{ {
return "popup-button"; return "popup-button";
} }
@@ -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;
} }
/*! /*!
@@ -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",
+5 -3
View File
@@ -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"
/* /*
+1 -5
View File
@@ -25,7 +25,6 @@
@import "CPButton.j" @import "CPButton.j"
/*! /*!
@ingroup appkit @ingroup appkit
@@ -63,9 +62,6 @@
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";
} }
+49 -43
View File
@@ -23,18 +23,17 @@
@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
@@ -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;
[self doCommandBySelector:CPSelectorFromString(selector)]; case CPEscapeKeyCode: [self doCommandBySelector:@selector(cancel:)];
} break;
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,7 +312,7 @@ 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];
@@ -342,8 +354,7 @@ CPDeleteForwardKeyCode = 46;
@end @end
var CPResponderNextResponderKey = @"CPResponderNextResponderKey", var CPResponderNextResponderKey = @"CPResponderNextResponderKey";
CPResponderMenuKey = @"CPResponderMenuKey";
@implementation CPResponder (CPCoding) @implementation CPResponder (CPCoding)
@@ -357,10 +368,7 @@ var CPResponderNextResponderKey = @"CPResponderNextResponderKey",
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 -1
View File
@@ -1,5 +1,5 @@
@import "CPPanel.j" @import <AppKit/CPPanel.j>
@implementation CPSavePanel : CPPanel @implementation CPSavePanel : CPPanel
+2
View File
@@ -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
{ {
+66 -356
View File
@@ -20,10 +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 "CPBox.j" @import "CPView.j"
@import "CPClipView.j" @import "CPClipView.j"
@import "CPScroller.j" @import "CPScroller.j"
@import "CPView.j"
#include "CoreGraphics/CGGeometry.h"
/*! /*!
@@ -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,7 +153,7 @@
*/ */
- (void)reflectScrolledClipView:(CPClipView)aClipView - (void)reflectScrolledClipView:(CPClipView)aClipView
{ {
if (_contentView !== aClipView) if(_contentView !== aClipView)
return; return;
if (_recursionCount > 5) if (_recursionCount > 5)
@@ -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)];
@@ -332,7 +255,7 @@
{ {
[_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.
@@ -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];
@@ -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];
@@ -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,47 +479,11 @@
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])
@@ -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)
@@ -1038,12 +760,6 @@ var CPScrollViewContentViewKey = @"CPScrollViewContentView",
_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,10 +767,7 @@ 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]];
@@ -1083,9 +796,6 @@ var CPScrollViewContentViewKey = @"CPScrollViewContentView",
[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
+22 -34
View File
@@ -22,6 +22,8 @@
@import "CPControl.j" @import "CPControl.j"
#include "CoreGraphics/CGGeometry.h"
// CPScroller Constants // CPScroller Constants
CPScrollerNoPart = 0; CPScrollerNoPart = 0;
@@ -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"]];
}]
} }
@@ -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];
} }
/*! /*!
@@ -280,10 +281,10 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
_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)),
@@ -309,10 +310,10 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
_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();
@@ -449,7 +450,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
[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];
@@ -606,19 +607,6 @@ var CPScrollerControlSizeKey = "CPScrollerControlSize",
_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;
+120 -223
View File
@@ -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;
}
- (BOOL)resignFirstResponder point = [self convertPoint:location fromView:nil];
{
return _canResignFirstResponder && [super resignFirstResponder];
}
- (void)mouseDown:(CPEvent)anEvent rect = [self searchButtonRectForBounds:[self frame]];
{ if (CPRectContainsPoint(rect,point))
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];
} }
else if (_CGRectContainsPoint([self cancelButtonRectForBounds:[self bounds]], point))
[_cancelButton mouseDown:anEvent]; rect = [self cancelButtonRectForBounds:[self frame]];
else if (CPRectContainsPoint(rect,point))
[super mouseDown:anEvent]; {
return [[self cancelButton] trackMouse:event];
}
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;
item = [[CPMenuItem alloc] initWithTitle:@"Recent Searches" template = [[CPMenu alloc] init];
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]) if (!(tag === CPSearchFieldRecentsTitleMenuItemTag && countOfRecents === 0) &&
!(tag === CPSearchFieldClearRecentsMenuItemTag && countOfRecents === 0) &&
!(tag === CPSearchFieldNoRecentsMenuItemTag && countOfRecents != 0) &&
!(tag === CPSearchFieldRecentsMenuItemTag))
{ {
case CPSearchFieldRecentsTitleMenuItemTag: var itemAction, itemTarget;
if (countOfRecents === 0) switch (tag)
continue;
if ([menu numberOfItems] > 0)
[self _addSeparatorToMenu:menu];
break;
case CPSearchFieldRecentsMenuItemTag:
{ {
var itemAction = @selector(_searchFieldSearch:); case CPSearchFieldRecentsTitleMenuItemTag : itemAction = NULL; itemTarget = NULL; break;
case CPSearchFieldClearRecentsMenuItemTag : itemAction = @selector(_searchFieldClearRecents:); itemTarget = self; break;
for (var recentIndex = 0; recentIndex < countOfRecents; ++recentIndex) case CPSearchFieldNoRecentsMenuItemTag : itemAction = NULL; itemTarget = NULL; break;
{ default: itemAction = [item action]; itemTarget = [item target]; break;
// 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 (tag === CPSearchFieldClearRecentsMenuItemTag || tag === CPSearchFieldRecentsTitleMenuItemTag)
if (countOfRecents === 0) {
continue; var separator = [CPMenuItem separatorItem];
[separator setEnabled:NO];
[menu addItem:separator];
}
if ([menu numberOfItems] > 0) var templateItem = [[CPMenuItem alloc] initWithTitle:[item title]
[self _addSeparatorToMenu:menu]; action:itemAction
keyEquivalent:[item keyEquivalent]];
[item setAction:@selector(_searchFieldClearRecents:)]; [templateItem setTarget:itemTarget];
[item setTarget:self]; [templateItem setEnabled:([item isEnabled] && itemAction != NULL)];
break; [templateItem setTag:tag];
[menu addItem:templateItem];
case CPSearchFieldNoRecentsMenuItemTag: }
if (countOfRecents !== 0) else if (tag === CPSearchFieldRecentsMenuItemTag)
continue; {
var j;
if ([menu numberOfItems] > 0) for (j = 0; j < countOfRecents; j++)
[self _addSeparatorToMenu:menu]; {
break; var rencentItem = [[CPMenuItem alloc] initWithTitle:[_recentSearches objectAtIndex:j]
action:@selector(_searchFieldSearch:)
case CPSearchFieldSeparatorMenuItemTag: keyEquivalent:[item keyEquivalent]];
item = [CPMenuItem separatorItem]; [rencentItem setTarget:self];
[item setEnabled:NO]; [menu addItem:rencentItem];
[menu addItem:item]; }
continue;
} }
[item setEnabled:([item isEnabled] && [item action] != nil && [item target] != nil)];
[menu addItem:item];
} }
[menu setDelegate:self];
_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,14 +593,13 @@ 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
@@ -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
View File
@@ -1,7 +1,6 @@
@import "CPTextField.j" @import "CPTextField.j"
/*! /*!
@ingroup appkit @ingroup appkit
*/ */
+75 -74
View File
@@ -24,6 +24,7 @@
@import "CPControl.j" @import "CPControl.j"
#include "CoreGraphics/CGGeometry.h"
CPSegmentSwitchTrackingSelectOne = 0; CPSegmentSwitchTrackingSelectOne = 0;
CPSegmentSwitchTrackingSelectAny = 1; CPSegmentSwitchTrackingSelectAny = 1;
@@ -48,7 +49,7 @@ CPSegmentSwitchTrackingMomentary = 2;
BOOL _trackingHighlighted; BOOL _trackingHighlighted;
} }
+ (CPString)defaultThemeClass + (CPString)themeClass
{ {
return "segmented-control"; return "segmented-control";
} }
@@ -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
@@ -182,7 +183,7 @@ CPSegmentSwitchTrackingMomentary = 2;
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
@@ -194,7 +195,7 @@ CPSegmentSwitchTrackingMomentary = 2;
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,7 +217,7 @@ 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,7 +265,9 @@ 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;
} }
/*! /*!
@@ -310,10 +315,10 @@ CPSegmentSwitchTrackingMomentary = 2;
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;
@@ -326,7 +331,7 @@ CPSegmentSwitchTrackingMomentary = 2;
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];
@@ -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()];
@@ -508,9 +511,9 @@ 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];
@@ -521,38 +524,40 @@ 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]];
@@ -563,24 +568,24 @@ CPSegmentSwitchTrackingMomentary = 2;
[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];
@@ -604,48 +609,43 @@ 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];
@@ -698,12 +698,12 @@ CPSegmentSwitchTrackingMomentary = 2;
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))
@@ -844,15 +844,15 @@ var CPSegmentedControlSegmentsKey = "CPSegmentedControlSegmentsKey",
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];
} }
@@ -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();
@@ -947,3 +947,4 @@ var CPSegmentItemImageKey = "CPSegmentItemImageKey",
} }
@end @end
+2 -25
View File
@@ -28,6 +28,8 @@
@import "CPView.j" @import "CPView.j"
#include "CoreGraphics/CGGeometry.h"
CPLightShadow = 0; CPLightShadow = 0;
CPHeavyShadow = 1; CPHeavyShadow = 1;
@@ -91,31 +93,6 @@ var LIGHT_LEFT_INSET = 3.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];
+6 -16
View File
@@ -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";
} }
@@ -188,7 +189,7 @@ CPCircularSlider = 1;
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
{ {
@@ -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
{ {
@@ -341,6 +342,7 @@ CPCircularSlider = 1;
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];
@@ -394,18 +396,6 @@ CPCircularSlider = 1;
_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",
+167 -103
View File
@@ -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
+26 -48
View File
@@ -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
@@ -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)
{ {
+1 -25
View File
@@ -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
+531 -180
View File
@@ -1,8 +1,32 @@
@import "CPBox.j" /*
@import "CPSegmentedControl.j" * CPTabView.j
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2008, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPImageView.j"
@import "CPTabViewItem.j" @import "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;
CPSegmentedControl tabs; CPView _auxiliaryView;
CPBox box; CPView _contentView;
CPNumber selectedIndex; CPArray _tabViewItems;
CPTabViewItem _selectedTabViewItem;
CPTabViewType type; CPTabViewType _tabViewType;
id delegate; id _delegate;
unsigned delegateSelectors; unsigned _delegateSelectors;
}
/*
@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,
bezelBorderLeftImage,
backgroundImage,
bezelBorderRightImage,
bezelBorderLeftImage,
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];
[self _updateItems]; [_tabViewItems insertObject:aTabViewItem atIndex:anIndex];
[self _repositionTabs];
if (delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector) [_labelsView tabView:self didAddTabViewItem:aTabViewItem];
[delegate tabViewDidChangeNumberOfTabViewItems:self];
[aTabViewItem _setTabView:self];
if ([_tabViewItems count] == 1)
[self selectFirstTabViewItem: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];
if (delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector) [_labelsView tabView:self didRemoveTabViewItemAtIndex:index];
[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?
[self selectTabViewItemAtIndex:0]; if (count)
[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?
[self selectTabViewItemAtIndex:[items count] - 1]; if (count)
[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]) [self selectTabViewItemAtIndex:index + 1 % count];
// does nothing. According to spec at (http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Reference/ApplicationKit/Classes/NSTabView_Class/Reference/Reference.html#//apple_ref/occ/instm/NSTabView/selectNextTabViewItem:)
return;
[self selectTabViewItemAtIndex:nextIndex];
} }
/*! /*!
@@ -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) [self selectTabViewItemAtIndex:index == 0 ? count : index - 1];
return; // does nothing. See above.
[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,7 +436,7 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/ */
- (CPTabViewItem)selectedTabViewItem - (CPTabViewItem)selectedTabViewItem
{ {
return [items objectAtIndex:selectedIndex]; return _selectedTabViewItem;
} }
// //
@@ -285,33 +446,22 @@ var HEIGHT_OF_SEGMENTED_CONTROL = 24;
*/ */
- (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 ((type === CPNoTabsBezelBorder || type === CPNoTabsLineBorder || type === CPNoTabsNoBorder) if (_tabViewType == CPNoTabsBezelBorder || _tabViewType == CPNoTabsLineBorder || _tabViewType == CPNoTabsNoBorder)
&& (aTabViewType !== CPNoTabsBezelBorder && aTabViewType !== CPNoTabsBezelBorder && aTabViewType !== CPNoTabsNoBorder)) [_labelsView removeFromSuperview];
[self addSubview:tabs]; else if (![_labelsView superview])
[self addSubview:_labelsView];
type = aTabViewType; if (_tabViewType == CPNoTabsLineBorder || _tabViewType == CPNoTabsNoBorder)
[_backgroundView removeFromSuperview];
else if (![_backgroundView superview])
[self addSubview:_backgroundView];
switch (type) [self layoutSubviews];
{
case CPTopTabsBezelBorder:
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; _delegate = aDelegate;
delegateSelectors = 0; _delegateSelectors = 0;
if ([delegate respondsToSelector:@selector(tabView:shouldSelectTabViewItem:)]) if ([_delegate respondsToSelector:@selector(tabView:shouldSelectTabViewItem:)])
delegateSelectors |= CPTabViewShouldSelectTabViewItemSelector; _delegateSelectors |= CPTabViewShouldSelectTabViewItemSelector;
if ([delegate respondsToSelector:@selector(tabView:willSelectTabViewItem:)]) if ([_delegate respondsToSelector:@selector(tabView:willSelectTabViewItem:)])
delegateSelectors |= CPTabViewWillSelectTabViewItemSelector; _delegateSelectors |= CPTabViewWillSelectTabViewItemSelector;
if ([delegate respondsToSelector:@selector(tabView:didSelectTabViewItem:)]) if ([_delegate respondsToSelector:@selector(tabView:didSelectTabViewItem:)])
delegateSelectors |= CPTabViewDidSelectTabViewItemSelector; _delegateSelectors |= CPTabViewDidSelectTabViewItemSelector;
if ([delegate respondsToSelector:@selector(tabViewDidChangeNumberOfTabViewItems:)]) if ([_delegate respondsToSelector:@selector(tabViewDidChangeNumberOfTabViewItems:)])
delegateSelectors |= CPTabViewDidChangeNumberOfTabViewItemsSelector; _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 selectTabViewItem:tabViewItem];
[self selectTabViewItemAtIndex:segmentIndex];
[tabs trackSegment:anEvent];
}
}
- (void)_repositionTabs
{
var horizontalCenterOfSelf = CGRectGetWidth([self bounds]) / 2,
verticalCenterOfTabs = CGRectGetHeight([tabs bounds]) / 2;
if (type === CPBottomTabsBezelBorder)
[tabs setCenter:CGPointMake(horizontalCenterOfSelf, CGRectGetHeight([self bounds]) - verticalCenterOfTabs)];
else
[tabs setCenter:CGPointMake(horizontalCenterOfSelf, verticalCenterOfTabs)];
}
- (void)_setSelectedIndex:(CPNumber)index
{
selectedIndex = index;
[box setContentView:[[items objectAtIndex:selectedIndex] view]];
}
- (void)_updateItems
{
[tabs setSegmentCount:[items count]];
for (var i = 0; i < [items count]; i++)
{
[tabs setLabel:[[items objectAtIndex:i] label] forSegment:i];
[tabs setTag:i forSegment:i];
}
if (selectedIndex === CPNotFound)
{
[self selectFirstTabViewItem:self];
}
} }
@end @end
@@ -419,12 +554,15 @@ 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)
@@ -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:_tabViewItems forKey:CPTabViewItemsKey];;
[aCoder encodeObject:[self selectedTabViewItem] forKey:CPTabViewSelectedItemKey]; [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
+1 -1
View File
@@ -22,7 +22,7 @@
@import <Foundation/CPObject.j> @import <Foundation/CPObject.j>
@import "CPView.j" @import <AppKit/CPView.j>
/* /*
+13 -97
View File
@@ -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;
@@ -78,7 +78,13 @@ CPTableColumnUserResizingMask = 1 << 1;
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;
@@ -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];
} }
@@ -286,9 +293,6 @@ CPTableColumnUserResizingMask = 1 << 1;
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;
} }
@@ -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
@@ -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
+156 -342
View File
@@ -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)
@@ -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;
BOOL _isResizing; float _draggedDistance @accessors(readonly, property=draggedDistance);
BOOL _isDragging; float _lastLocation;
BOOL _isTrackingColumn; float _columnOldWidth;
BOOL _drawsColumnLines;
float _columnOldWidth; CPTableView _tableView @accessors(property=tableView);
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,38 +182,36 @@ 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 ?
}
- (void)setDrawsColumnLines:(BOOL)aFlag var tableRange = _tableView._tableColumnRanges[aColumnIndex],
{ bounds = [self bounds];
_drawsColumnLines = aFlag;
}
- (BOOL)drawsColumnLines var rMinX = ROUND(tableRange.location);
{ bounds.origin.x = rMinX;
return _drawsColumnLines; bounds.size.width = FLOOR(tableRange.length + tableRange.location - rMinX);
return bounds;
} }
- (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;
@@ -263,280 +236,104 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
- (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];
// Take the right columns resize tracking area into account if (type == CPLeftMouseUp)
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];
}
[self _updateResizeCursor:[CPApp currentEvent]]; if (clickedColumn != -1)
[_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];
}
- (void)trackResizeWithEvent:(CPEvent)anEvent
{
var location = [self convertPoint:[anEvent locationInWindow] fromView:nil],
tableColumn = [[_tableView tableColumns] objectAtIndex:_resizedColumn],
type = [anEvent type];
if (_lastLocation == nil)
_lastLocation = location;
if (_columnOldWidth == nil)
_columnOldWidth = [tableColumn width];
if (type === CPLeftMouseUp)
{ {
if (columnIndex === -1) [self _updateResizeCursor:anEvent];
return;
_mouseDownLocation = currentLocation; [tableColumn _postDidResizeNotificationWithOldWidth:_columnOldWidth];
_activeColumn = columnIndex; [tableColumn setDisableResizingPosting:NO];
[_tableView setDisableAutomaticResizing:NO];
[_tableView _sendDelegateDidMouseDownInHeader:columnIndex]; _resizedColumn = -1;
_lastLocation = nil;
_columnOldWidth = nil;
if (shouldResize) return;
[self startResizingTableColumn:columnIndex at:currentLocation];
else
{
[self startTrackingTableColumn:columnIndex at:currentLocation];
_isTrackingColumn = YES;
}
} }
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
@@ -552,7 +349,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
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];
@@ -568,6 +365,12 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
[[CPCursor arrowCursor] set]; [[CPCursor arrowCursor] set];
} }
- (void)viewDidMoveToWindow
{
//if ([_tableView allowsColumnResizing])
// [[self window] setAcceptsMouseMovedEvents:YES];
}
- (void)mouseEntered:(CPEvent)theEvent - (void)mouseEntered:(CPEvent)theEvent
{ {
[self _updateResizeCursor:theEvent]; [self _updateResizeCursor:theEvent];
@@ -607,13 +410,11 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
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,7 +426,7 @@ 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];
@@ -640,26 +441,40 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
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
+408 -921
View File
File diff suppressed because it is too large Load Diff
-30
View File
@@ -1,30 +0,0 @@
/*
* CPText.j
* AppKit
*
* Created by Alexander Ljungberg.
* Copyright 2010, WireLoad, LLC.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
CPEnterCharacter = "\u0003";
CPBackspaceCharacter = "\u0008";
CPTabCharacter = "\u0009";
CPNewlineCharacter = "\u000a";
CPFormFeedCharacter = "\u000c";
CPCarriageReturnCharacter = "\u000d";
CPBackTabCharacter = "\u0019";
CPDeleteCharacter = "\u007f";
+56 -203
View File
@@ -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. */
@@ -77,15 +80,12 @@ 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;
@@ -155,7 +155,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
return textField; return textField;
} }
+ (CPString)defaultThemeClass + (CPString)themeClass
{ {
return "textfield"; return "textfield";
} }
@@ -269,22 +269,11 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
#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
@@ -507,13 +483,6 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
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);
@@ -550,8 +519,7 @@ 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();
@@ -569,11 +537,11 @@ 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
@@ -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.
*/ */
@@ -764,7 +707,7 @@ 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;
@@ -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-bezeled receivers with a non-wrapping line break mode, sizeToFit will change the frame of the For non-editable text fields (typically, a label), sizeToFit will change the frame of the
receiver to perfectly fit the current text in stringValue in the current font, respecting receiver to perfectly fit the current text in stringValue in the current font, and respecting
the current theme value for content-inset. For receivers with a wrapping line break mode, the current theme values for content-inset, min-size, and max-size.
sizeToFit will wrap the text within the current width (respecting the current content-inset),
so it will ONLY change the HEIGHT.
For bezeled text fields (typically editable fields), sizeToFit will ONLY change the HEIGHT For editable text fields, sizeToFit will ONLY change the HEIGHT of the text field. It will not
of the text field. It will not change the width of the text field. sizeToFit will attempt to change the width of the text field. You can use setFrameSize: with the current height to set the
change the height to fit a single line of text, respecting the current theme values for min-size, width, and you can get the size of a string with [CPString sizeWithFont:].
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;
} }
/*! /*!
@@ -896,8 +781,11 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
{ {
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)];
} }
} }
@@ -1109,7 +997,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
return bounds; return bounds;
} }
- (CGRect)bezelRectForBounds:(CGRect)bounds - (CGRect)bezelRectForBounds:(CFRect)bounds
{ {
var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"]; var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"];
@@ -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";
@@ -1258,22 +1129,7 @@ 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;
@@ -1294,9 +1150,6 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
[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];
} }
+10 -178
View File
@@ -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];
@@ -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;
} }
+7 -31
View File
@@ -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,7 +33,7 @@
@implementation CPThemeBlend : CPObject @implementation CPThemeBlend : CPObject
{ {
CPBundle _bundle; CPBundle _bundle;
CPArray _themes; CPArray _themes @accessors(readonly, getter=themes);
id _loadDelegate; id _loadDelegate;
} }
@@ -50,28 +49,6 @@
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;
@@ -81,13 +58,12 @@
- (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
View File
@@ -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
+6 -6
View File
@@ -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];
-197
View File
@@ -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
+37 -148
View File
@@ -22,7 +22,6 @@
@import <Foundation/CPArray.j> @import <Foundation/CPArray.j>
@import <Foundation/CPObjJRuntime.j> @import <Foundation/CPObjJRuntime.j>
@import <Foundation/CPSet.j>
@import "CGAffineTransform.j" @import "CGAffineTransform.j"
@import "CGGeometry.j" @import "CGGeometry.j"
@@ -35,6 +34,11 @@
@import "_CPDisplayServer.j" @import "_CPDisplayServer.j"
#include "Platform/Platform.h"
#include "CoreGraphics/CGAffineTransform.h"
#include "CoreGraphics/CGGeometry.h"
#include "Platform/DOM/CPDOMDisplayServer.h"
/* /*
@global @global
@group CPViewAutoresizingMasks @group CPViewAutoresizingMasks
@@ -90,8 +94,7 @@ var DOMElementPrototype = nil,
BackgroundTrivialColor = 0, BackgroundTrivialColor = 0,
BackgroundVerticalThreePartImage = 1, BackgroundVerticalThreePartImage = 1,
BackgroundHorizontalThreePartImage = 2, BackgroundHorizontalThreePartImage = 2,
BackgroundNinePartImage = 3, BackgroundNinePartImage = 3;
BackgroundTransparentColor = 4;
#endif #endif
var CPViewFlags = { }, var CPViewFlags = { },
@@ -136,7 +139,6 @@ var CPViewFlags = { },
BOOL _isHidden; BOOL _isHidden;
BOOL _hitTests; BOOL _hitTests;
BOOL _clipsToBounds;
BOOL _postsFrameChangedNotifications; BOOL _postsFrameChangedNotifications;
BOOL _postsBoundsChangedNotifications; BOOL _postsBoundsChangedNotifications;
@@ -174,7 +176,6 @@ var CPViewFlags = { },
// Theming Support // Theming Support
CPTheme _theme; CPTheme _theme;
CPString _themeClass;
JSObject _themeAttributes; JSObject _themeAttributes;
unsigned _themeState; unsigned _themeState;
@@ -276,7 +277,6 @@ var CPViewFlags = { },
_autoresizingMask = CPViewNotSizable; _autoresizingMask = CPViewNotSizable;
_autoresizesSubviews = YES; _autoresizesSubviews = YES;
_clipsToBounds = YES;
_opacity = 1.0; _opacity = 1.0;
_isHidden = NO; _isHidden = NO;
@@ -835,33 +835,28 @@ var CPViewFlags = { },
if (_backgroundType !== BackgroundTrivialColor) if (_backgroundType !== BackgroundTrivialColor)
{ {
if (_backgroundType === BackgroundTransparentColor) var images = [[_backgroundColor patternImage] imageSlices];
if (_backgroundType === BackgroundVerticalThreePartImage)
{ {
CPDOMDisplayServerSetStyleSize(_DOMImageParts[0], size.width, size.height); CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], size.width, size.height - _DOMImageSizes[0].height - _DOMImageSizes[2].height);
} }
else
else if (_backgroundType === BackgroundHorizontalThreePartImage)
{ {
var images = [[_backgroundColor patternImage] imageSlices]; CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], size.width - _DOMImageSizes[0].width - _DOMImageSizes[2].width, size.height);
}
if (_backgroundType === BackgroundVerticalThreePartImage) else if (_backgroundType === BackgroundNinePartImage)
{ {
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], size.width, size.height - _DOMImageSizes[0].height - _DOMImageSizes[2].height); var width = size.width - _DOMImageSizes[0].width - _DOMImageSizes[2].width,
} height = size.height - _DOMImageSizes[0].height - _DOMImageSizes[6].height;
else if (_backgroundType === BackgroundHorizontalThreePartImage)
{
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], size.width - _DOMImageSizes[0].width - _DOMImageSizes[2].width, size.height);
}
else if (_backgroundType === BackgroundNinePartImage)
{
var width = size.width - _DOMImageSizes[0].width - _DOMImageSizes[2].width,
height = size.height - _DOMImageSizes[0].height - _DOMImageSizes[6].height;
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], width, _DOMImageSizes[0].height); CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], width, _DOMImageSizes[0].height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[3], _DOMImageSizes[3].width, height); CPDOMDisplayServerSetStyleSize(_DOMImageParts[3], _DOMImageSizes[3].width, height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[4], width, height); CPDOMDisplayServerSetStyleSize(_DOMImageParts[4], width, height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[5], _DOMImageSizes[5].width, height); CPDOMDisplayServerSetStyleSize(_DOMImageParts[5], _DOMImageSizes[5].width, height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[7], width, _DOMImageSizes[7].height); CPDOMDisplayServerSetStyleSize(_DOMImageParts[7], width, _DOMImageSizes[7].height);
}
} }
} }
#endif #endif
@@ -1000,7 +995,7 @@ var CPViewFlags = { },
{ {
var mask = [self autoresizingMask]; var mask = [self autoresizingMask];
if (mask == CPViewNotSizable) if(mask == CPViewNotSizable)
return; return;
var frame = _superview._frame, var frame = _superview._frame,
@@ -1156,7 +1151,7 @@ var CPViewFlags = { },
{ {
aFlag = !!aFlag; aFlag = !!aFlag;
if (_isHidden === aFlag) if(_isHidden === aFlag)
return; return;
// FIXME: Should we return to visibility? This breaks in FireFox, Opera, and IE. // FIXME: Should we return to visibility? This breaks in FireFox, Opera, and IE.
@@ -1182,31 +1177,7 @@ var CPViewFlags = { },
} }
while (view = [view superview]); while (view = [view superview]);
} }
[self _notifyViewDidHide];
} }
else
{
[self _notifyViewDidUnhide];
}
}
- (void)_notifyViewDidHide
{
[self viewDidHide];
var count = [_subviews count];
while (count--)
[_subviews[count] _notifyViewDidHide];
}
- (void)_notifyViewDidUnhide
{
[self viewDidUnhide];
var count = [_subviews count];
while (count--)
[_subviews[count] _notifyViewDidUnhide];
} }
/*! /*!
@@ -1217,23 +1188,6 @@ var CPViewFlags = { },
return _isHidden; return _isHidden;
} }
- (void)setClipsToBounds:(BOOL)shouldClip
{
if (_clipsToBounds === shouldClip)
return;
_clipsToBounds = shouldClip;
#if PLATFORM(DOM)
_DOMElement.style.overflow = _clipsToBounds ? "hidden" : "visible";
#endif
}
- (BOOL)clipsToBounds
{
return _clipsToBounds;
}
/*! /*!
Sets the opacity of the receiver. The value must be in the range of 0.0 to 1.0, where 0.0 is Sets the opacity of the receiver. The value must be in the range of 0.0 to 1.0, where 0.0 is
completely transparent and 1.0 is completely opaque. completely transparent and 1.0 is completely opaque.
@@ -1284,34 +1238,6 @@ var CPViewFlags = { },
return view !== nil; return view !== nil;
} }
/*!
Called when the return value of isHiddenOrHasHiddenAncestor becomes YES,
e.g. when this view becomes hidden due to a setHidden:YES message to
itself or to one of its superviews.
Note: in the current implementation, viewDidHide may be called multiple
times if additional superviews are hidden, even if
isHiddenOrHasHiddenAncestor was already YES.
*/
- (void)viewDidHide
{
}
/*!
Called when the return value of isHiddenOrHasHiddenAncestor becomes NO,
e.g. when this view stops being hidden due to a setHidden:NO message to
itself or to one of its superviews.
Note: in the current implementation, viewDidUnhide may be called multiple
times if additional superviews are unhidden, even if
isHiddenOrHasHiddenAncestor was already NO.
*/
- (void)viewDidUnhide
{
}
/*! /*!
Returns whether the receiver should be sent a \c -mouseDown: message for \c anEvent.<br/> Returns whether the receiver should be sent a \c -mouseDown: message for \c anEvent.<br/>
Returns \c YES by default. Returns \c YES by default.
@@ -1348,7 +1274,7 @@ var CPViewFlags = { },
*/ */
- (CPView)hitTest:(CPPoint)aPoint - (CPView)hitTest:(CPPoint)aPoint
{ {
if (_isHidden || !_hitTests || !CPRectContainsPoint(_frame, aPoint)) if(_isHidden || !_hitTests || !CPRectContainsPoint(_frame, aPoint))
return nil; return nil;
var view = nil, var view = nil,
@@ -1413,9 +1339,6 @@ var CPViewFlags = { },
if (_backgroundColor == aColor) if (_backgroundColor == aColor)
return; return;
if (aColor == [CPNull null])
aColor = nil;
_backgroundColor = aColor; _backgroundColor = aColor;
#if PLATFORM(DOM) #if PLATFORM(DOM)
@@ -1438,7 +1361,7 @@ var CPViewFlags = { },
} }
else else
{ {
_backgroundType = colorNeedsDOMElement ? BackgroundTransparentColor : BackgroundTrivialColor; _backgroundType = BackgroundTrivialColor;
amount = (colorNeedsDOMElement ? 1 : 0) - _DOMImageParts.length; amount = (colorNeedsDOMElement ? 1 : 0) - _DOMImageParts.length;
} }
@@ -1461,7 +1384,7 @@ var CPViewFlags = { },
_DOMElement.removeChild(_DOMImageParts.pop()); _DOMElement.removeChild(_DOMImageParts.pop());
} }
if (_backgroundType === BackgroundTrivialColor || _backgroundType === BackgroundTransparentColor) if (_backgroundType === BackgroundTrivialColor)
{ {
var colorCSS = colorExists ? [_backgroundColor cssString] : ""; var colorCSS = colorExists ? [_backgroundColor cssString] : "";
@@ -1731,7 +1654,7 @@ setBoundsOrigin:
var theWindow = [self window]; var theWindow = [self window];
[theWindow _noteUnregisteredDraggedTypes:_registeredDraggedTypes]; [theWindow _noteUnregisteredDraggedTypes:_registeredDraggedTypes];
[_registeredDraggedTypes addObjectsFromArray:pasteboardTypes]; [_registeredDraggedTypes addObjectsFromArray:pasteboardTypes]
[theWindow _noteRegisteredDraggedTypes:_registeredDraggedTypes]; [theWindow _noteRegisteredDraggedTypes:_registeredDraggedTypes];
_registeredDraggedTypesArray = nil; _registeredDraggedTypesArray = nil;
@@ -1843,17 +1766,12 @@ setBoundsOrigin:
- (void)displayRectIgnoringOpacity:(CGRect)aRect inContext:(CPGraphicsContext)aGraphicsContext - (void)displayRectIgnoringOpacity:(CGRect)aRect inContext:(CPGraphicsContext)aGraphicsContext
{ {
if ([self isHidden])
return;
#if PLATFORM(DOM)
[self lockFocus]; [self lockFocus];
CGContextClearRect([[CPGraphicsContext currentContext] graphicsPort], aRect); CGContextClearRect([[CPGraphicsContext currentContext] graphicsPort], aRect);
[self drawRect:aRect]; [self drawRect:aRect];
[self unlockFocus]; [self unlockFocus];
#endif
} }
- (void)viewWillDraw - (void)viewWillDraw
@@ -1956,7 +1874,7 @@ setBoundsOrigin:
var superview = _superview, var superview = _superview,
clipViewClass = [CPClipView class]; clipViewClass = [CPClipView class];
while (superview && ![superview isKindOfClass:clipViewClass]) while(superview && ![superview isKindOfClass:clipViewClass])
superview = superview._superview; superview = superview._superview;
return superview; return superview;
@@ -2052,7 +1970,7 @@ setBoundsOrigin:
var superview = _superview, var superview = _superview,
scrollViewClass = [CPScrollView class]; scrollViewClass = [CPScrollView class];
while (superview && ![superview isKindOfClass:scrollViewClass]) while(superview && ![superview isKindOfClass:scrollViewClass])
superview = superview._superview; superview = superview._superview;
return superview; return superview;
@@ -2248,29 +2166,11 @@ setBoundsOrigin:
#pragma mark Theme Attributes #pragma mark Theme Attributes
+ (CPString)defaultThemeClass + (CPString)themeClass
{ {
return nil; return nil;
} }
- (CPString)themeClass
{
if (_themeClass)
return _themeClass;
return [[self class] defaultThemeClass];
}
- (void)setThemeClass:(CPString)theClass
{
_themeClass = theClass;
[self _loadThemeAttributes];
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
+ (CPDictionary)themeAttributes + (CPDictionary)themeAttributes
{ {
return nil; return nil;
@@ -2329,7 +2229,7 @@ setBoundsOrigin:
return; return;
var theme = [self theme], var theme = [self theme],
themeClass = [self themeClass]; themeClass = [theClass themeClass];
_themeAttributes = {}; _themeAttributes = {};
@@ -2338,7 +2238,7 @@ setBoundsOrigin:
var attributeName = attributes[count--], var attributeName = attributes[count--],
attribute = [[_CPThemeAttribute alloc] initWithName:attributeName defaultValue:attributes[count]]; attribute = [[_CPThemeAttribute alloc] initWithName:attributeName defaultValue:attributes[count]];
[attribute setParentAttribute:[theme attributeWithName:attributeName forClass:themeClass]]; [attribute setParentAttribute:[theme _attributeWithName:attributeName forClass:themeClass]];
_themeAttributes[attributeName] = attribute; _themeAttributes[attributeName] = attribute;
} }
@@ -2365,11 +2265,11 @@ setBoundsOrigin:
return; return;
var theme = [self theme], var theme = [self theme],
themeClass = [self themeClass]; themeClass = [[self class] themeClass];
for (var attributeName in _themeAttributes) for (var attributeName in _themeAttributes)
if (_themeAttributes.hasOwnProperty(attributeName)) if (_themeAttributes.hasOwnProperty(attributeName))
[_themeAttributes[attributeName] setParentAttribute:[theme attributeWithName:attributeName forClass:themeClass]]; [_themeAttributes[attributeName] setParentAttribute:[theme _attributeWithName:attributeName forClass:themeClass]];
[self setNeedsLayout]; [self setNeedsLayout];
[self setNeedsDisplay:YES]; [self setNeedsDisplay:YES];
@@ -2495,14 +2395,6 @@ setBoundsOrigin:
return _ephemeralSubviewsForNames[aViewName]; return _ephemeralSubviewsForNames[aViewName];
} }
- (CPView)ephemeralSubviewNamed:(CPString)aViewName
{
if (!_ephemeralSubviewsForNames)
return nil;
return (_ephemeralSubviewsForNames[aViewName] || nil);
}
@end @end
var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask", var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
@@ -2516,7 +2408,6 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
CPViewSubviewsKey = @"CPViewSubviewsKey", CPViewSubviewsKey = @"CPViewSubviewsKey",
CPViewSuperviewKey = @"CPViewSuperviewKey", CPViewSuperviewKey = @"CPViewSuperviewKey",
CPViewTagKey = @"CPViewTagKey", CPViewTagKey = @"CPViewTagKey",
CPViewThemeClassKey = @"CPViewThemeClassKey",
CPViewThemeStateKey = @"CPViewThemeStateKey", CPViewThemeStateKey = @"CPViewThemeStateKey",
CPViewWindowKey = @"CPViewWindowKey", CPViewWindowKey = @"CPViewWindowKey",
CPViewNextKeyViewKey = @"CPViewNextKeyViewKey", CPViewNextKeyViewKey = @"CPViewNextKeyViewKey",
@@ -2596,12 +2487,11 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
[self setupViewFlags]; [self setupViewFlags];
_theme = [CPTheme defaultTheme]; _theme = [CPTheme defaultTheme];
_themeClass = [aCoder decodeObjectForKey:CPViewThemeClassKey];
_themeState = CPThemeState([aCoder decodeIntForKey:CPViewThemeStateKey]); _themeState = CPThemeState([aCoder decodeIntForKey:CPViewThemeStateKey]);
_themeAttributes = {}; _themeAttributes = {};
var theClass = [self class], var theClass = [self class],
themeClass = [self themeClass], themeClass = [theClass themeClass],
attributes = [theClass _themeAttributes], attributes = [theClass _themeAttributes],
count = attributes.length; count = attributes.length;
@@ -2684,7 +2574,6 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
if (previousKeyView !== nil) if (previousKeyView !== nil)
[aCoder encodeConditionalObject:previousKeyView forKey:CPViewPreviousKeyViewKey]; [aCoder encodeConditionalObject:previousKeyView forKey:CPViewPreviousKeyViewKey];
[aCoder encodeObject:[self themeClass] forKey:CPViewThemeClassKey];
[aCoder encodeInt:CPThemeStateName(_themeState) forKey:CPViewThemeStateKey]; [aCoder encodeInt:CPThemeStateName(_themeState) forKey:CPViewThemeStateKey];
for (var attributeName in _themeAttributes) for (var attributeName in _themeAttributes)
+12 -13
View File
@@ -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)
+60 -26
View File
@@ -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,10 +134,10 @@ 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
{ {
@@ -132,9 +147,9 @@ var CPViewControllerCachedCibs;
// 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
+9 -53
View File
@@ -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:
@@ -73,8 +74,6 @@ CPWebViewScrollNative = 2;
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
@@ -111,7 +110,6 @@ CPWebViewScrollNative = 2;
_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];
@@ -173,32 +171,7 @@ CPWebViewScrollNative = 2;
[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;
@@ -231,8 +203,6 @@ CPWebViewScrollNative = 2;
[_frameView setFrameSize:CGSizeMake(800, 1600)]; [_frameView setFrameSize:CGSizeMake(800, 1600)];
} }
[_frameView scrollRectToVisible:visibleRect];
} }
} }
} }
@@ -247,10 +217,7 @@ CPWebViewScrollNative = 2;
- (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;
@@ -289,8 +256,6 @@ CPWebViewScrollNative = 2;
[self _setScrollMode:CPWebViewScrollAppKit]; [self _setScrollMode:CPWebViewScrollAppKit];
[_frameView setFrameSize:[_scrollView contentSize]];
[self _startedLoading]; [self _startedLoading];
_ignoreLoadStart = YES; _ignoreLoadStart = YES;
@@ -328,19 +293,11 @@ CPWebViewScrollNative = 2;
// clear the iframe // clear the iframe
_iframe.src = ""; _iframe.src = "";
if (_loadHTMLStringTimer !== nil)
{
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 // need to give the browser a chance to reset iframe, otherwise we'll be document.write()-ing the previous document
_loadHTMLStringTimer = window.setTimeout(function() 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,7 +315,6 @@ CPWebViewScrollNative = 2;
- (void)_finishedLoading - (void)_finishedLoading
{ {
[self _resizeWebFrame]; [self _resizeWebFrame];
[self _attachScrollEventIfNecessary];
[[CPNotificationCenter defaultCenter] postNotificationName:CPWebViewProgressFinishedNotification object:self]; [[CPNotificationCenter defaultCenter] postNotificationName:CPWebViewProgressFinishedNotification object:self];
+37 -211
View File
@@ -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"
/* /*
@@ -195,8 +200,6 @@ var SHADOW_MARGIN_LEFT = 20.0,
var CPWindowSaveImage = nil, var CPWindowSaveImage = nil,
CPWindowSavingImage = nil; CPWindowSavingImage = nil;
var CPWindowResizeTime = 0.2;
/*! /*!
@ingroup appkit @ingroup appkit
@class CPWindow @class CPWindow
@@ -317,8 +320,6 @@ var CPWindowResizeTime = 0.2;
CPDictionary _sheetContext; CPDictionary _sheetContext;
CPWindow _parentView; CPWindow _parentView;
BOOL _isSheet; BOOL _isSheet;
_CPWindowFrameAnimation _frameAnimation;
} }
/* /*
@@ -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;
} }
@@ -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];
[_frameAnimation startAnimation]; [animation 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
} }
/*! /*!
@@ -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
@@ -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];
@@ -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;
} }
@@ -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;
@@ -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 */
@@ -2167,7 +2073,7 @@ CPTexturedBackgroundWindowMask
[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];
@@ -2188,7 +2094,7 @@ CPTexturedBackgroundWindowMask
[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 */
@@ -2217,15 +2123,13 @@ CPTexturedBackgroundWindowMask
[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
@@ -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
@@ -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
@@ -2772,7 +2598,7 @@ var interpolate = function(fromValue, toValue, progress)
- (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)
{ {
+12 -12
View File
@@ -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];
-1
View File
@@ -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,
+3 -1
View File
@@ -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;
+4 -2
View File
@@ -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
View File
@@ -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];
+3 -9
View File
@@ -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
View File
@@ -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
-10
View File
@@ -112,14 +112,4 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
return NO; return NO;
} }
- (unsigned)loadStatus
{
return CPImageLoadStatusCompleted;
}
- (id)delegate
{
return nil;
}
@end @end
-3
View File
@@ -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",
+6 -3
View File
@@ -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
+5 -2
View File
@@ -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))
+5 -4
View File
@@ -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;
-1
View File
@@ -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)
+2 -50
View File
@@ -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.
-3
View File
@@ -29,9 +29,6 @@ kCGGradientDrawsAfterEndLocation = 1 << 1;
function CGGradientCreateWithColorComponents(aColorSpace, components, locations, count) function CGGradientCreateWithColorComponents(aColorSpace, components, locations, count)
{ {
if (arguments["locations"] == NULL)
var locations = [0.0, 1.0];
if (arguments["count"] == NULL) if (arguments["count"] == NULL)
var count = locations.length; var count = locations.length;

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