mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-09-10 04:37:11 +00:00
Merge remote-tracking branch 'Slevenbits/master' into slevenbits-master
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.8
|
||||
before_install:
|
||||
- jdk_switcher use openjdk6
|
||||
install: ./bootstrap.sh --quiet --noprompt --directory ./narwhal
|
||||
script: jake test
|
||||
env: PATH=/home/travis/builds/cappuccino/cappuccino/narwhal/bin:$PATH CAPP_BUILD=/home/travis/builds/cappuccino/cappuccino/Build NARWHAL_ENGINE=rhino
|
||||
+80
-60
@@ -75,32 +75,33 @@ CPCriticalAlertStyle = 2;
|
||||
representing the first button added to the alert which appears on the
|
||||
right, 1 representing the next button to the left and so on)
|
||||
*/
|
||||
@implementation CPAlert : CPView
|
||||
@implementation CPAlert : CPObject
|
||||
{
|
||||
BOOL _showHelp @accessors(property=showsHelp);
|
||||
BOOL _showSuppressionButton @accessors(property=showsSuppressionButton);
|
||||
BOOL _showHelp @accessors(property=showsHelp);
|
||||
BOOL _showSuppressionButton @accessors(property=showsSuppressionButton);
|
||||
|
||||
CPAlertStyle _alertStyle @accessors(property=alertStyle);
|
||||
CPString _title @accessors(property=title);
|
||||
CPView _accessoryView @accessors(property=accessoryView);
|
||||
CPImage _icon @accessors(property=icon);
|
||||
CPAlertStyle _alertStyle @accessors(property=alertStyle);
|
||||
CPString _title @accessors(property=title);
|
||||
CPView _accessoryView @accessors(property=accessoryView);
|
||||
CPImage _icon @accessors(property=icon);
|
||||
|
||||
CPArray _buttons @accessors(property=buttons,readonly);
|
||||
CPCheckBox _suppressionButton @accessors(property=suppressionButton,readonly);
|
||||
CPArray _buttons @accessors(property=buttons,readonly);
|
||||
CPCheckBox _suppressionButton @accessors(property=suppressionButton,readonly);
|
||||
|
||||
id _delegate @accessors(property=delegate);
|
||||
id _modalDelegate;
|
||||
SEL _didEndSelector;
|
||||
id _delegate @accessors(property=delegate);
|
||||
id _modalDelegate;
|
||||
SEL _didEndSelector;
|
||||
|
||||
CPWindow _window @accessors(property=window,readonly);
|
||||
int _defaultWindowStyle;
|
||||
_CPAlertThemeView _themeView @accessors(property=themeView, readonly);
|
||||
CPWindow _window @accessors(property=window,readonly);
|
||||
int _defaultWindowStyle;
|
||||
|
||||
CPImageView _alertImageView;
|
||||
CPTextField _informativeLabel;
|
||||
CPTextField _messageLabel;
|
||||
CPButton _alertHelpButton;
|
||||
CPImageView _alertImageView;
|
||||
CPTextField _informativeLabel;
|
||||
CPTextField _messageLabel;
|
||||
CPButton _alertHelpButton;
|
||||
|
||||
BOOL _needsLayout;
|
||||
BOOL _needsLayout;
|
||||
}
|
||||
|
||||
#pragma mark Creating Alerts
|
||||
@@ -164,6 +165,7 @@ CPCriticalAlertStyle = 2;
|
||||
_showHelp = NO;
|
||||
_needsLayout = YES;
|
||||
_defaultWindowStyle = CPTitledWindowMask;
|
||||
_themeView = [_CPAlertThemeView new];
|
||||
|
||||
_messageLabel = [CPTextField labelWithTitle:@"Alert"];
|
||||
_alertImageView = [[CPImageView alloc] init];
|
||||
@@ -180,6 +182,11 @@ CPCriticalAlertStyle = 2;
|
||||
|
||||
#pragma mark Accessors
|
||||
|
||||
- (CPTheme)theme
|
||||
{
|
||||
return [_themeView theme];
|
||||
}
|
||||
|
||||
/*!
|
||||
set the theme to use
|
||||
|
||||
@@ -197,9 +204,20 @@ CPCriticalAlertStyle = 2;
|
||||
|
||||
_window = nil; // will be regenerated at next layout
|
||||
_needsLayout = YES;
|
||||
[super setTheme:aTheme];
|
||||
[_themeView setTheme:aTheme];
|
||||
}
|
||||
|
||||
- (void)setValue:(id)aValue forThemeAttribute:(CPString)aName
|
||||
{
|
||||
[_themeView setValue:aValue forThemeAttribute:aName];
|
||||
}
|
||||
|
||||
- (void)setValue:(id)aValue forThemeAttribute:(CPString)aName inState:(CPThemeState)aState
|
||||
{
|
||||
[_themeView setValue:aValue forThemeAttribute:aName inState:aState];
|
||||
}
|
||||
|
||||
|
||||
/*! @deprecated
|
||||
*/
|
||||
- (void)setWindowStyle:(int)aStyle
|
||||
@@ -334,16 +352,16 @@ CPCriticalAlertStyle = 2;
|
||||
*/
|
||||
- (void)_layoutMessageView
|
||||
{
|
||||
var inset = [self currentValueForThemeAttribute:@"content-inset"],
|
||||
var inset = [_themeView currentValueForThemeAttribute:@"content-inset"],
|
||||
sizeWithFontCorrection = 6.0,
|
||||
messageLabelWidth,
|
||||
messageLabelTextSize;
|
||||
|
||||
[_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 setTextColor:[_themeView currentValueForThemeAttribute:@"message-text-color"]];
|
||||
[_messageLabel setFont:[_themeView currentValueForThemeAttribute:@"message-text-font"]];
|
||||
[_messageLabel setTextShadowColor:[_themeView currentValueForThemeAttribute:@"message-text-shadow-color"]];
|
||||
[_messageLabel setTextShadowOffset:[_themeView currentValueForThemeAttribute:@"message-text-shadow-offset"]];
|
||||
[_messageLabel setAlignment:[_themeView currentValueForThemeAttribute:@"message-text-alignment"]];
|
||||
[_messageLabel setLineBreakMode:CPLineBreakByWordWrapping];
|
||||
|
||||
messageLabelWidth = CGRectGetWidth([[_window contentView] frame]) - inset.left - inset.right;
|
||||
@@ -357,18 +375,18 @@ CPCriticalAlertStyle = 2;
|
||||
*/
|
||||
- (void)_layoutInformativeView
|
||||
{
|
||||
var inset = [self currentValueForThemeAttribute:@"content-inset"],
|
||||
defaultElementsMargin = [self currentValueForThemeAttribute:@"default-elements-margin"],
|
||||
var inset = [_themeView currentValueForThemeAttribute:@"content-inset"],
|
||||
defaultElementsMargin = [_themeView currentValueForThemeAttribute:@"default-elements-margin"],
|
||||
sizeWithFontCorrection = 6.0,
|
||||
informativeLabelWidth,
|
||||
informativeLabelOriginY,
|
||||
informativeLabelTextSize;
|
||||
|
||||
[_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 setAlignment:[self currentValueForThemeAttribute:@"informative-text-alignment"]];
|
||||
[_informativeLabel setTextColor:[_themeView currentValueForThemeAttribute:@"informative-text-color"]];
|
||||
[_informativeLabel setFont:[_themeView currentValueForThemeAttribute:@"informative-text-font"]];
|
||||
[_informativeLabel setTextShadowColor:[_themeView currentValueForThemeAttribute:@"informative-text-shadow-color"]];
|
||||
[_informativeLabel setTextShadowOffset:[_themeView currentValueForThemeAttribute:@"informative-text-shadow-offset"]];
|
||||
[_informativeLabel setAlignment:[_themeView currentValueForThemeAttribute:@"informative-text-alignment"]];
|
||||
[_informativeLabel setLineBreakMode:CPLineBreakByWordWrapping];
|
||||
|
||||
informativeLabelWidth = CGRectGetWidth([[_window contentView] frame]) - inset.left - inset.right;
|
||||
@@ -386,8 +404,8 @@ CPCriticalAlertStyle = 2;
|
||||
if (!_accessoryView)
|
||||
return;
|
||||
|
||||
var inset = [self currentValueForThemeAttribute:@"content-inset"],
|
||||
defaultElementsMargin = [self currentValueForThemeAttribute:@"default-elements-margin"],
|
||||
var inset = [_themeView currentValueForThemeAttribute:@"content-inset"],
|
||||
defaultElementsMargin = [_themeView currentValueForThemeAttribute:@"default-elements-margin"],
|
||||
accessoryViewWidth = CGRectGetWidth([[_window contentView] frame]) - inset.left - inset.right,
|
||||
accessoryViewOriginY = CGRectGetMaxY([_informativeLabel frame]) + defaultElementsMargin;
|
||||
|
||||
@@ -403,16 +421,16 @@ CPCriticalAlertStyle = 2;
|
||||
if (!_showSuppressionButton)
|
||||
return;
|
||||
|
||||
var inset = [self currentValueForThemeAttribute:@"content-inset"],
|
||||
suppressionViewXOffset = [self currentValueForThemeAttribute:@"suppression-button-x-offset"],
|
||||
suppressionViewYOffset = [self currentValueForThemeAttribute:@"suppression-button-y-offset"],
|
||||
defaultElementsMargin = [self currentValueForThemeAttribute:@"default-elements-margin"],
|
||||
var inset = [_themeView currentValueForThemeAttribute:@"content-inset"],
|
||||
suppressionViewXOffset = [_themeView currentValueForThemeAttribute:@"suppression-button-x-offset"],
|
||||
suppressionViewYOffset = [_themeView currentValueForThemeAttribute:@"suppression-button-y-offset"],
|
||||
defaultElementsMargin = [_themeView currentValueForThemeAttribute:@"default-elements-margin"],
|
||||
suppressionButtonViewOriginY = CGRectGetMaxY([(_accessoryView || _informativeLabel) frame]) + defaultElementsMargin + suppressionViewYOffset;
|
||||
|
||||
[_suppressionButton setTextColor:[self currentValueForThemeAttribute:@"suppression-button-text-color"]];
|
||||
[_suppressionButton setFont:[self currentValueForThemeAttribute:@"suppression-button-text-font"]];
|
||||
[_suppressionButton setTextShadowColor:[self currentValueForThemeAttribute:@"suppression-button-text-shadow-color"]];
|
||||
[_suppressionButton setTextShadowOffset:[self currentValueForThemeAttribute:@"suppression-button-text-shadow-offset"]];
|
||||
[_suppressionButton setTextColor:[_themeView currentValueForThemeAttribute:@"suppression-button-text-color"]];
|
||||
[_suppressionButton setFont:[_themeView currentValueForThemeAttribute:@"suppression-button-text-font"]];
|
||||
[_suppressionButton setTextShadowColor:[_themeView currentValueForThemeAttribute:@"suppression-button-text-shadow-color"]];
|
||||
[_suppressionButton setTextShadowOffset:[_themeView currentValueForThemeAttribute:@"suppression-button-text-shadow-offset"]];
|
||||
[_suppressionButton sizeToFit];
|
||||
|
||||
[_suppressionButton setFrameOrigin:CGPointMake(inset.left + suppressionViewXOffset, suppressionButtonViewOriginY)];
|
||||
@@ -424,12 +442,12 @@ CPCriticalAlertStyle = 2;
|
||||
*/
|
||||
- (CGSize)_layoutButtonsFromView:(CPView)lastView
|
||||
{
|
||||
var inset = [self currentValueForThemeAttribute:@"content-inset"],
|
||||
minimumSize = [self currentValueForThemeAttribute:@"size"],
|
||||
buttonOffset = [self currentValueForThemeAttribute:@"button-offset"],
|
||||
helpLeftOffset = [self currentValueForThemeAttribute:@"help-image-left-offset"],
|
||||
var inset = [_themeView currentValueForThemeAttribute:@"content-inset"],
|
||||
minimumSize = [_themeView currentValueForThemeAttribute:@"size"],
|
||||
buttonOffset = [_themeView currentValueForThemeAttribute:@"button-offset"],
|
||||
helpLeftOffset = [_themeView currentValueForThemeAttribute:@"help-image-left-offset"],
|
||||
aRepresentativeButton = [_buttons objectAtIndex:0],
|
||||
defaultElementsMargin = [self currentValueForThemeAttribute:@"default-elements-margin"],
|
||||
defaultElementsMargin = [_themeView currentValueForThemeAttribute:@"default-elements-margin"],
|
||||
panelSize = [[_window contentView] frame].size,
|
||||
buttonsOriginY,
|
||||
offsetX;
|
||||
@@ -461,8 +479,8 @@ CPCriticalAlertStyle = 2;
|
||||
|
||||
if (_showHelp)
|
||||
{
|
||||
var helpImage = [self currentValueForThemeAttribute:@"help-image"],
|
||||
helpImagePressed = [self currentValueForThemeAttribute:@"help-image-pressed"],
|
||||
var helpImage = [_themeView currentValueForThemeAttribute:@"help-image"],
|
||||
helpImagePressed = [_themeView currentValueForThemeAttribute:@"help-image-pressed"],
|
||||
helpImageSize = helpImage ? [helpImage size] : CGSizeMakeZero(),
|
||||
helpFrame = CGRectMake(helpLeftOffset, buttonsOriginY, helpImageSize.width, helpImageSize.height);
|
||||
|
||||
@@ -487,7 +505,7 @@ CPCriticalAlertStyle = 2;
|
||||
if (!_window)
|
||||
[self _createWindowWithStyle:nil];
|
||||
|
||||
var iconOffset = [self currentValueForThemeAttribute:@"image-offset"],
|
||||
var iconOffset = [_themeView currentValueForThemeAttribute:@"image-offset"],
|
||||
theImage = _icon,
|
||||
finalSize;
|
||||
|
||||
@@ -495,13 +513,13 @@ CPCriticalAlertStyle = 2;
|
||||
switch (_alertStyle)
|
||||
{
|
||||
case CPWarningAlertStyle:
|
||||
theImage = [self currentValueForThemeAttribute:@"warning-image"];
|
||||
theImage = [_themeView currentValueForThemeAttribute:@"warning-image"];
|
||||
break;
|
||||
case CPInformationalAlertStyle:
|
||||
theImage = [self currentValueForThemeAttribute:@"information-image"];
|
||||
theImage = [_themeView currentValueForThemeAttribute:@"information-image"];
|
||||
break;
|
||||
case CPCriticalAlertStyle:
|
||||
theImage = [self currentValueForThemeAttribute:@"error-image"];
|
||||
theImage = [_themeView currentValueForThemeAttribute:@"error-image"];
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -592,7 +610,7 @@ CPCriticalAlertStyle = 2;
|
||||
- (void)_createWindowWithStyle:(int)forceStyle
|
||||
{
|
||||
var frame = CGRectMakeZero();
|
||||
frame.size = [self currentValueForThemeAttribute:@"size"];
|
||||
frame.size = [_themeView currentValueForThemeAttribute:@"size"];
|
||||
|
||||
_window = [[CPWindow alloc] initWithContentRect:frame styleMask:forceStyle || _defaultWindowStyle];
|
||||
[_window setLevel:CPStatusWindowLevel];
|
||||
@@ -633,8 +651,8 @@ CPCriticalAlertStyle = 2;
|
||||
{
|
||||
if ([_window isSheet])
|
||||
{
|
||||
[CPApp endSheet:_window returnCode:[aSender tag]];
|
||||
[_window orderOut:nil];
|
||||
[CPApp endSheet:_window returnCode:[aSender tag]];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -650,17 +668,19 @@ CPCriticalAlertStyle = 2;
|
||||
*/
|
||||
- (void)_alertDidEnd:(CPWindow)aWindow returnCode:(int)returnCode contextInfo:(id)contextInfo
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(alertDidEnd:returnCode:)])
|
||||
[_delegate alertDidEnd:self returnCode:returnCode];
|
||||
|
||||
if (_didEndSelector)
|
||||
objj_msgSend(_modalDelegate, _didEndSelector, self, returnCode, contextInfo);
|
||||
|
||||
_modalDelegate = nil;
|
||||
_didEndSelector = nil;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(alertDidEnd:returnCode:)])
|
||||
[_delegate alertDidEnd:self returnCode:returnCode];
|
||||
}
|
||||
|
||||
#pragma mark Theme Attributes
|
||||
@end
|
||||
|
||||
@implementation _CPAlertThemeView : CPView
|
||||
|
||||
+ (CPString)defaultThemeClass
|
||||
{
|
||||
|
||||
+15
-10
@@ -20,6 +20,8 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#import "../Foundation/CPRange.h"
|
||||
|
||||
@import <Foundation/CPBundle.j>
|
||||
|
||||
@import "CPCompatibility.j"
|
||||
@@ -139,9 +141,7 @@ CPRunContinuesResponse = -1002;
|
||||
{
|
||||
_eventListeners = [];
|
||||
|
||||
_windows = [];
|
||||
|
||||
[_windows addObject:nil];
|
||||
_windows = [[CPNull null]];
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -655,6 +655,10 @@ CPRunContinuesResponse = -1002;
|
||||
*/
|
||||
- (CPWindow)windowWithWindowNumber:(int)aWindowNumber
|
||||
{
|
||||
// Never allow _windows[0] to be returned - it's an internal CPNull placeholder.
|
||||
if (!aWindowNumber)
|
||||
return nil;
|
||||
|
||||
return _windows[aWindowNumber];
|
||||
}
|
||||
|
||||
@@ -663,7 +667,8 @@ CPRunContinuesResponse = -1002;
|
||||
*/
|
||||
- (CPArray)windows
|
||||
{
|
||||
return _windows;
|
||||
// Return all windows, but not the CPNull placeholder in _windows[0].
|
||||
return [_windows subarrayWithRange:_CPMakeRange(1, [_windows count] - 1)];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1042,9 +1047,9 @@ CPRunContinuesResponse = -1002;
|
||||
if (!args || args.length == 0)
|
||||
{
|
||||
_args = [];
|
||||
#if PLATFORM(DOM)
|
||||
window.location.hash = @"#";
|
||||
#endif
|
||||
// Don't use if PLATFORM(DOM) here - the unit test fakes window.location so we should play along.
|
||||
if (window && window.location)
|
||||
window.location.hash = @"#";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1059,9 +1064,9 @@ CPRunContinuesResponse = -1002;
|
||||
|
||||
var hash = [toEncode componentsJoinedByString:@"/"];
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
window.location.hash = @"#" + hash;
|
||||
#endif
|
||||
// Don't use if PLATFORM(DOM) here - the unit test fakes window.location so we should play along.
|
||||
if (window && window.location)
|
||||
window.location.hash = @"#" + hash;
|
||||
}
|
||||
|
||||
- (void)_reloadArguments
|
||||
|
||||
@@ -706,7 +706,11 @@ var CPScrollDestinationNone = 0,
|
||||
{
|
||||
if (![self hasThemeState:CPThemeStateEditing])
|
||||
return @"";
|
||||
#if PLATFORM(DOM)
|
||||
return [self _inputElement].value;
|
||||
#else
|
||||
return @"";
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)moveUp:(id)sender
|
||||
|
||||
@@ -651,6 +651,9 @@ var CPViewFlags = { },
|
||||
if (_window === aWindow)
|
||||
return;
|
||||
|
||||
// Unlike in Cocoa you can observe the window of a view.
|
||||
[self willChangeValueForKey:@"window"];
|
||||
|
||||
[[self window] _dirtyKeyViewLoop];
|
||||
|
||||
// Clear out first responder if we're the first responder and leaving.
|
||||
@@ -678,6 +681,8 @@ var CPViewFlags = { },
|
||||
[self viewDidMoveToWindow];
|
||||
|
||||
[[self window] _dirtyKeyViewLoop];
|
||||
|
||||
[self didChangeValueForKey:@"window"];
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -901,6 +901,8 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
[_platformWindow orderFront:self];
|
||||
[_platformWindow order:CPWindowAbove window:self relativeTo:nil];
|
||||
#else
|
||||
_isVisible = YES;
|
||||
#endif
|
||||
|
||||
if (!CPApp._keyWindow)
|
||||
@@ -946,6 +948,8 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
[_platformWindow order:CPWindowOut window:self relativeTo:nil];
|
||||
#else
|
||||
_isVisible = NO;
|
||||
#endif
|
||||
|
||||
[self _updateMainAndKeyWindows];
|
||||
|
||||
@@ -1832,7 +1832,7 @@ var themedButtonValues = nil,
|
||||
|
||||
[self registerThemeValues:themedAlertValues forView:alert];
|
||||
|
||||
return alert;
|
||||
return [alert themeView];
|
||||
}
|
||||
|
||||
+ (CPStepper)themedStepper
|
||||
@@ -2095,7 +2095,7 @@ var themedButtonValues = nil,
|
||||
|
||||
[self registerThemeValues:hudSpecificValues forView:alert inherit:themedAlertValues];
|
||||
|
||||
return alert;
|
||||
return [alert themeView];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -38,6 +38,7 @@ var _CPAutocompleteMenuMaximumHeight = 307;
|
||||
float widestItemWidth;
|
||||
|
||||
CPWindow _menuWindow;
|
||||
CPWindow _parentWindow @accessors(property=parentWindow);
|
||||
CPScrollView scrollView;
|
||||
CPTableView tableView;
|
||||
|
||||
@@ -48,7 +49,8 @@ var _CPAutocompleteMenuMaximumHeight = 307;
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
textField = aTextField;
|
||||
[self bind:@"parentWindow" toObject:self withKeyPath:@"textField.window" options:nil];
|
||||
[self setTextField:aTextField];
|
||||
|
||||
_menuWindow = [[CPWindow alloc] initWithContentRect:CGRectMake(0, 0, 100, 100) styleMask:CPBorderlessWindowMask];
|
||||
|
||||
@@ -185,7 +187,7 @@ var _CPAutocompleteMenuMaximumHeight = 307;
|
||||
{
|
||||
var indexOfSelectedItem = [self indexOfSelectedItem];
|
||||
|
||||
[self setContentArray:[textField _completionsForSubstring:[textField _inputElement].value indexOfToken:0 indexOfSelectedItem:indexOfSelectedItem]];
|
||||
[self setContentArray:[textField _completionsForSubstring:[textField _editorValue] indexOfToken:0 indexOfSelectedItem:indexOfSelectedItem]];
|
||||
|
||||
if (![contentArray count])
|
||||
return;
|
||||
@@ -258,6 +260,25 @@ var _CPAutocompleteMenuMaximumHeight = 307;
|
||||
[textField _complete:self];
|
||||
}
|
||||
|
||||
- (void)setParentWindow:(CPWindow)aWindow
|
||||
{
|
||||
if (aWindow === _parentWindow)
|
||||
return;
|
||||
|
||||
if (_parentWindow)
|
||||
[[CPNotificationCenter defaultCenter] removeObserver:self];
|
||||
|
||||
_parentWindow = aWindow;
|
||||
|
||||
if (_parentWindow)
|
||||
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(parentWindowWillClose:) name:CPWindowWillCloseNotification object:_parentWindow];
|
||||
}
|
||||
|
||||
- (void)parentWindowWillClose:(CPNotification)aNotification
|
||||
{
|
||||
[self _hideCompletions];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@@ -29,6 +29,48 @@ Now you can go to GitHub and [make a pull request](https://help.github.com/artic
|
||||
|
||||
Some things are difficult to unit test in a way that's worthwhile. For instance a change to the mouse interaction of a `CPButton`. In this case a manual test is fine instead. Find the closest related manual test in `Tests/Manual` and add whatever it takes to easily reproduce the patched behavior, ideally with some labels describing how someone running the manual test should exercise it.
|
||||
|
||||
## Commit Messages
|
||||
|
||||
The style and format of your commit messages are very important to the health of the project. A good commit message helps not only users reading the release notes, but also your fellow Cappuccino developers as they review `git log` or `git blame` to figure out what you were doing.
|
||||
|
||||
This is the preferred format of commit messages for complex changes:
|
||||
|
||||
[New:] <what's new.>
|
||||
|
||||
[OPTIONAL DESCRIPTION ABOUT WHAT THIS THING DOES.]
|
||||
|
||||
Or for fixes:
|
||||
|
||||
Fixed: <what was fixed.>
|
||||
|
||||
BEFORE
|
||||
|
||||
AFTER
|
||||
|
||||
**Example:**
|
||||
|
||||
nib2cib support for table view background colour.
|
||||
|
||||
**Example:**
|
||||
|
||||
Fixed: CPAlert was a CPView.
|
||||
|
||||
Before this fix, CPAlert subclassed CPView, causing an API mismatch with Cocoa and exposing unexpected methods in the public API which made no sense for a CPAlert such as autoresizing masks. It also lead to CPAlert mistakingly shadowing _window from its CPView superclass.
|
||||
|
||||
This fix makes CPAlert inherit from CPObject as it should. The theming, which needs to be applied to a view, was moved to an internal view.
|
||||
|
||||
The summary line concisely says what was fixed or improved by the commit. If it's an improvement or something new it optionally starts with "New:". If it's a bug fix it starts with "Fixed:".
|
||||
|
||||
For a 'new' change, the rest of the summary line answers the question *"What is new and where?"*. Optionally the summary can be followed with more detail about what's new and why it's great.
|
||||
|
||||
If the summary starts with "Fixed:" the rest of the summary line answers the question *"What was fixed?"*. E.g. "Fixed: the blargh had too many blurghs."
|
||||
|
||||
(Note it does NOT answer the question *"what was done to fix it?"* E.g. **WRONG:** "Fixed: removed 2 blurghs from the blargh." That would imply that your very change was what was fixed by itself, causing an infinite loop in the universe and ending the world as we know it.)
|
||||
|
||||
The rest of the fix message is in a before / after form. The first part describes what the situation was before the fix and says why the fix was needed. The after part describes what change was made to rectify the situation and any implementation notes that might be useful to know for people reviewing it in the future.
|
||||
|
||||
Naturally small or unimportant commits have less rigid requirements. If you can comfortably and easily describe the whole change in the summary only, go ahead. Maybe you fixed a tiny typo or did a minor refactoring.
|
||||
|
||||
## Cappuccino Coding Style Guidelines
|
||||
|
||||
### Trailing whitespace
|
||||
|
||||
@@ -263,8 +263,8 @@ task ("demos", function()
|
||||
rm_rf(demosDir);
|
||||
FILE.mkdirs(demosDir);
|
||||
|
||||
OS.system("curl -L http://github.com/280north/cappuccino-demos/zipball/master > "+zipQuoted);
|
||||
OS.system("(cd "+demosQuoted+" && unzip "+zipQuoted+" -d demos)");
|
||||
OS.system("curl -L http://github.com/280north/cappuccino-demos/zipball/master > " + zipQuoted);
|
||||
OS.system("(cd " + demosQuoted + " && unzip " + zipQuoted + " -d demos)");
|
||||
|
||||
require("objective-j");
|
||||
|
||||
@@ -311,8 +311,8 @@ task ("demos", function()
|
||||
cp_r(FILE.join($STARTER_DOWNLOAD_APPLICATION, "Frameworks"), FILE.join(demo.path(), "Frameworks"));
|
||||
rm_rf(FILE.join(demo.path(), "Frameworks", "Debug"));
|
||||
|
||||
var outputPath = demo.name().replace(/\s/g, "-")+".zip";
|
||||
OS.system("cd "+OS.enquote(FILE.dirname(demo.path()))+" && zip -ry -8 "+OS.enquote(outputPath)+" "+OS.enquote(FILE.basename(demo.path())));
|
||||
var outputPath = demo.name().replace(/\s/g, "-") + ".zip";
|
||||
OS.system("cd " + OS.enquote(FILE.dirname(demo.path()))+" && zip -ry -8 " + OS.enquote(outputPath) + " " + OS.enquote(FILE.basename(demo.path())));
|
||||
|
||||
// remove the frameworks
|
||||
rm_rf(FILE.join(demo.path(), "Frameworks"));
|
||||
@@ -321,7 +321,7 @@ task ("demos", function()
|
||||
|
||||
// Testing
|
||||
|
||||
task("test", ["CommonJS", "test-only", "check-missing-imports"]);
|
||||
task("test", ["CommonJS", "test-only"]);
|
||||
|
||||
task("test-only", function()
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@import <AppKit/CPApplication.j>
|
||||
@import <AppKit/CPWindow.j>
|
||||
|
||||
globalResults = [];
|
||||
var globalResults = [];
|
||||
|
||||
@implementation MyAppDelegate : CPObject
|
||||
{
|
||||
@@ -77,6 +77,12 @@ globalResults = [];
|
||||
globalResults = []
|
||||
}
|
||||
|
||||
- (void)tearDown
|
||||
{
|
||||
// This is the only way to clear the global window list between tests. You'd normally never do this.
|
||||
CPApp = nil;
|
||||
}
|
||||
|
||||
- (void)receiveNotification:(CPNotification)aNote
|
||||
{
|
||||
globalResults.push(aNote);
|
||||
@@ -182,12 +188,12 @@ globalResults = [];
|
||||
|
||||
- (void)testWindows
|
||||
{
|
||||
[self assert:@"My Great Window" equals:[[[app windows] objectAtIndex:1] title]];
|
||||
[self assert:[[aWindow title]] equals:[[app windows] valueForKey:@"title"]];
|
||||
}
|
||||
|
||||
- (void)testWindowWithWindowNumber
|
||||
{
|
||||
[self assert:@"My Great Window" equals:[[app windowWithWindowNumber:1] title]];
|
||||
[self assert:@"My Great Window" equals:[[app windowWithWindowNumber:[aWindow windowNumber]] title]];
|
||||
}
|
||||
|
||||
- (void)testReplyToApplicationShouldTerminate
|
||||
|
||||
@@ -28,15 +28,15 @@
|
||||
- (void)setUp
|
||||
{
|
||||
_tabView = [[CPTabView alloc] initWithFrame:CGRectMake(0, 0, 800, 600)];
|
||||
|
||||
_tabItem1 = [[CPTabViewItem alloc] initWithIdentifier:@"id1"];
|
||||
|
||||
_tabItem1 = [[CPTabViewItem alloc] initWithIdentifier:@"id1"];
|
||||
[_tabItem1 setLabel:@"Item A"];
|
||||
[_tabItem1 setView:[[CPView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]]
|
||||
|
||||
_tabItem2 = [[CPTabViewItem alloc] initWithIdentifier:@"id2"];
|
||||
[_tabItem2 setLabel:@"Item B"];
|
||||
[_tabItem2 setView:[[CPView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]]
|
||||
|
||||
|
||||
[_tabView addTabViewItem:_tabItem1];
|
||||
[_tabView addTabViewItem:_tabItem2];
|
||||
}
|
||||
@@ -44,35 +44,41 @@
|
||||
- (void)testCreate
|
||||
{
|
||||
[self assertNotNull:_tabView];
|
||||
|
||||
|
||||
}
|
||||
|
||||
- (void)testMiddle
|
||||
{
|
||||
var tabs = [_tabView tabs];
|
||||
[self assert:([_tabView frameSize].width / 2) equals:CPRectGetMidX([tabs frame])];
|
||||
[self assert:([_tabView frameSize].width / 2) equals:CGRectGetMidX([tabs frame])];
|
||||
}
|
||||
|
||||
- (void)testMiddleAfterMoveFrame
|
||||
{
|
||||
var tabs = [_tabView tabs];
|
||||
[_tabView setFrame:CPRectMake(10, 100, 1000, 200)];
|
||||
[self assert:([_tabView frameSize].width / 2) equals:CPRectGetMidX([tabs frame])];
|
||||
[_tabView setFrame:CGRectMake(10, 100, 1000, 200)];
|
||||
// Perform this manually for the sake of the unit test.
|
||||
[_tabView layoutIfNeeded];
|
||||
[self assert:([_tabView frameSize].width / 2) equals:CGRectGetMidX([tabs frame])];
|
||||
}
|
||||
|
||||
- (void)testMiddleAfterMoveBound
|
||||
{
|
||||
var tabs = [_tabView tabs];
|
||||
[_tabView setBounds:CPRectMake(100, 100, 20, 300)];
|
||||
[self assert:([tabs boundsSize].width / 2) equals:CPRectGetMidX([tabs bounds])];
|
||||
[_tabView setBounds:CGRectMake(100, 100, 20, 300)];
|
||||
// Perform this manually for the sake of the unit test.
|
||||
[_tabView layoutIfNeeded];
|
||||
[self assert:([tabs boundsSize].width / 2) equals:CGRectGetMidX([tabs bounds])];
|
||||
}
|
||||
|
||||
- (void)testBoxHeight
|
||||
{
|
||||
var box = [_tabView box],
|
||||
tabs = [_tabView tabs];
|
||||
|
||||
[_tabView setFrame:CPRectMake(0, 0, 800, 800)];
|
||||
|
||||
[_tabView setFrame:CGRectMake(0, 0, 800, 800)];
|
||||
// Perform this manually for the sake of the unit test.
|
||||
[_tabView layoutIfNeeded];
|
||||
[self assert:[box frameSize].height equals:800 - [tabs frameSize].height / 2];
|
||||
}
|
||||
|
||||
@@ -87,4 +93,4 @@
|
||||
[self assertNull:[_tabItem1 tabView]];
|
||||
}
|
||||
|
||||
@end
|
||||
@end
|
||||
|
||||
@@ -28,4 +28,53 @@
|
||||
[[aWindow contentView] addSubview:tokenField];
|
||||
}
|
||||
|
||||
- (void)testCloseParentWindow
|
||||
{
|
||||
var aWindow = [[CPWindow alloc] initWithContentRect:CGRectMake(0.0, 0.0, 1024.0, 768.0) styleMask:CPTitledWindowMask],
|
||||
tokenField = [[CPTokenField alloc] initWithFrame:CGRectMake(10, 10, 100, 28)];
|
||||
|
||||
[[aWindow contentView] addSubview:tokenField];
|
||||
[tokenField setEnabled:YES];
|
||||
[tokenField setEditable:YES];
|
||||
|
||||
[aWindow makeKeyAndOrderFront:nil];
|
||||
|
||||
// Start autocomplete.
|
||||
var tokenDelegate = [TokenFieldDelegate new];
|
||||
[tokenDelegate setCompletions:[@"Tokyo", @"Toronto", @"Gothenburg", @"London"]];
|
||||
[tokenField setDelegate:tokenDelegate];
|
||||
|
||||
[tokenField setStringValue:@"To"];
|
||||
// Start autocomplete programmatically.
|
||||
[aWindow makeFirstResponder:tokenField];
|
||||
[[tokenField _autocompleteMenu] _showCompletions:nil];
|
||||
|
||||
// Verify we're now autocompleting.
|
||||
[self assertTrue:[[tokenField _autocompleteMenu]._menuWindow isVisible] message:@"autocomplete visible"];
|
||||
|
||||
[aWindow close];
|
||||
[self assertFalse:[[tokenField _autocompleteMenu]._menuWindow isVisible] message:@"autocomplete not visible when token field window closes"];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation TokenFieldDelegate : CPObject
|
||||
{
|
||||
CPArray completions @accessors;
|
||||
}
|
||||
|
||||
- (CPArray)tokenField:(CPTokenField)aTokenField completionsForSubstring:(CPString)substring indexOfToken:(int)tokenIndex indexOfSelectedItem:(int)selectedIndex
|
||||
{
|
||||
var r = [];
|
||||
|
||||
if (!substring)
|
||||
return completions;
|
||||
|
||||
for (var i = 0; i < completions.length; i++)
|
||||
if (completions[i].toLowerCase().indexOf(completions.toLowerCase()) == 0)
|
||||
r.push(completions[i]);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
+18
-4
@@ -144,6 +144,7 @@ github_ref="v0.9.6-RC2"
|
||||
noprompt=""
|
||||
install_capp=""
|
||||
install_method="zip"
|
||||
verbosity=1
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
@@ -153,6 +154,8 @@ while [ $# -gt 0 ]; do
|
||||
--clone-http) install_method="clone --http";;
|
||||
--github-user) github_user="$2"; shift;;
|
||||
--github-ref) github_ref="$2"; shift;;
|
||||
-q|--quiet) verbosity=$[verbosity - 1];;
|
||||
-v|--verbose) verbosity=$[verbosity + 1];;
|
||||
*) cat >&2 <<-EOT
|
||||
usage: ./bootstrap.sh [OPTIONS]
|
||||
|
||||
@@ -162,6 +165,8 @@ usage: ./bootstrap.sh [OPTIONS]
|
||||
--clone-http: Do "git clone http://" instead of downloading zips.
|
||||
--github-user [USER]: Github user (default: $github_user).
|
||||
--github-ref [REF]: Use another git ref (default: $github_ref).
|
||||
-q | --quiet: Output less logging.
|
||||
-v | --verbose: Output more logging.
|
||||
EOT
|
||||
exit 1;;
|
||||
esac
|
||||
@@ -174,7 +179,8 @@ github_path="$github_user/cappuccino-base"
|
||||
# The purpose of bootstrap is to install Cappuccino.
|
||||
install_cappuccino="yes"
|
||||
|
||||
sed "s/\[\[ CAPPUCCINO_VERSION \]\]/$github_ref/" <<EOT
|
||||
if (( $verbosity > 0 )); then
|
||||
sed "s/\[\[ CAPPUCCINO_VERSION \]\]/$github_ref/" <<EOT
|
||||
|
||||
_______ ____ ___ __ __________(_)__ ___
|
||||
/ __/ _ \`/ _ \/ _ \/ // / __/ __/ / _ \/ _ \\
|
||||
@@ -192,8 +198,10 @@ sed "s/\[\[ CAPPUCCINO_VERSION \]\]/$github_ref/" <<EOT
|
||||
http://github.com/cappuccino/cappuccino
|
||||
irc://irc.freenode.org#cappuccino
|
||||
|
||||
This script will install the Cappuccino environment for you. Continue?
|
||||
EOT
|
||||
fi
|
||||
|
||||
echo "This script will install the Cappuccino environment for you. Continue?"
|
||||
|
||||
if ! prompt "yes"; then
|
||||
install_cappuccino="no"
|
||||
@@ -274,11 +282,17 @@ if [ "$install_cappuccino" ]; then
|
||||
zip_ball="http://github.com/$github_path/zipball/$github_ref"
|
||||
|
||||
echo "Downloading Cappuccino base from \"$zip_ball\"..."
|
||||
$(which curl &> /dev/null && echo curl -L -o || echo wget --no-check-certificate -O) "$tmp_zip" "$zip_ball"
|
||||
curl_quiet_arg=""
|
||||
wget_quiet_arg=""
|
||||
if (( $verbosity < 1 )); then curl_quiet_arg="--silent"; wget_quiet_arg="--no-verbose"; fi
|
||||
$(which curl &> /dev/null && echo curl $curl_quiet_arg -L -o || echo $wget_quiet_arg --no-check-certificate -O) "$tmp_zip" "$zip_ball"
|
||||
check_and_exit
|
||||
|
||||
echo "Installing Cappuccino base..."
|
||||
unzip "$tmp_zip" -d "$install_directory"
|
||||
|
||||
quiet_arg=""
|
||||
if (( $verbosity < 2 )); then quiet_arg="-q"; fi
|
||||
unzip $quiet_arg "$tmp_zip" -d "$install_directory"
|
||||
check_and_exit
|
||||
rm "$tmp_zip"
|
||||
check_and_exit
|
||||
|
||||
Reference in New Issue
Block a user