Merge remote-tracking branch 'origin/master' into upstream_master

This commit is contained in:
Stefan Eilers
2012-10-23 17:24:58 +02:00
79 changed files with 4293 additions and 2833 deletions
+35
View File
@@ -165,6 +165,19 @@ var DefaultLineWidth = 1.0;
CGPathAddCurveToPoint(_path, nil, controlPoint1.x, controlPoint1.y, controlPoint2.x, controlPoint2.y, endPoint.x, endPoint.y);
}
- (CGRect)bounds
{
// TODO: this should return this. The controlPointBounds is not a tight fit.
// return CGPathGetPathBoundingBox(_path);
return [self controlPointBounds];
}
- (CGRect)controlPointBounds
{
return CGPathGetBoundingBox(_path);
}
/*!
Create a line segment between the first and last points in the subpath, closing it.
*/
@@ -272,6 +285,11 @@ var DefaultLineWidth = 1.0;
CGPathAddPath(_path, nil, CGPathWithRoundedRectangleInRect(rect, xRadius, yRadius, YES, YES, YES, YES));
}
- (void)appendBezierPathWithArcFromPoint:(CGPoint)fromPoint toPoint:(CGPoint)toPoint radius:(float)radius
{
CGPathAddArcToPoint(_path, null, fromPoint.x, fromPoint.y, toPoint.x, toPoint.y, radius);
}
/*!
Append the contents of a CPBezierPath object.
*/
@@ -288,4 +306,21 @@ var DefaultLineWidth = 1.0;
_path = CGPathCreateMutable();
}
- (void)addClip
{
var ctx = [[CPGraphicsContext currentContext] graphicsPort];
CGContextAddPath(ctx, _path);
CGContextClip(ctx);
}
- (void)setClip
{
var ctx = [[CPGraphicsContext currentContext] graphicsPort];
CGContextBeginPath(ctx);
CGContextAddPath(ctx, _path);
CGContextClip(ctx);
}
@end
+10
View File
@@ -322,6 +322,16 @@ CPBelowBottom = 6;
[self _manageTitlePositioning];
}
- (CPFont)titleFont
{
return [_titleView font];
}
- (void)setTitleFont:(CPFont)aFont
{
[_titleView setFont:aFont];
}
- (void)_manageTitlePositioning
{
if (_titlePosition == CPNoTitle)
+7 -3
View File
@@ -28,7 +28,7 @@
@import "CPView.j"
@import "CPCollectionViewItem.j"
@import "CPCompatibility.j"
/*!
@ingroup appkit
@@ -647,9 +647,9 @@
if (index >= 0 && index < _items.length)
{
if (_allowsMultipleSelection && ([anEvent modifierFlags] & CPCommandKeyMask || [anEvent modifierFlags] & CPShiftKeyMask))
if (_allowsMultipleSelection && ([anEvent modifierFlags] & CPPlatformActionKeyMask || [anEvent modifierFlags] & CPShiftKeyMask))
{
if ([anEvent modifierFlags] & CPCommandKeyMask)
if ([anEvent modifierFlags] & CPPlatformActionKeyMask)
{
var indexes = [_selectionIndexes copy];
@@ -690,6 +690,10 @@
- (void)mouseDragged:(CPEvent)anEvent
{
// Don't crash if we never registered the intial click.
if (!_mouseDownEvent)
return;
var locationInWindow = [anEvent locationInWindow],
mouseDownLocationInWindow = [_mouseDownEvent locationInWindow];
+8
View File
@@ -611,6 +611,14 @@ function CPColorWithImages()
return [[[self class] alloc] _initWithRGBA:components];
}
/*!
Returns the receiver. This method is a placeholder that does nothing but may be implemented in the future.
*/
- (CPColor)colorUsingColorSpaceName:(id)aColorSpaceName
{
return self;
}
/*!
Returns an array with the HSB values for this color.
The index values are ordered as:
+15
View File
@@ -174,6 +174,21 @@ following:
return _CPFontSystemFontSize;
}
+ (float)systemFontSizeForControlSize:(CPControlSize)aSize
{
// TODO These sizes should be themable or made less arbitrary in some other way.
switch (aSize)
{
case CPSmallControlSize:
return _CPFontSystemFontSize - 1;
case CPMiniControlSize:
return _CPFontSystemFontSize - 2;
case CPRegularControlSize:
default:
return _CPFontSystemFontSize;
}
}
/*!
Sets the default system font size.
*/
+10
View File
@@ -23,6 +23,16 @@
@import "CPColor.j"
@import "CPGraphicsContext.j"
CPCalibratedWhiteColorSpace = @"CalibratedWhiteColorSpace";
CPCalibratedBlackColorSpace = @"CalibratedBlackColorSpace";
CPCalibratedRGBColorSpace = @"CalibratedRGBColorSpace";
CPDeviceWhiteColorSpace = @"DeviceWhiteColorSpace";
CPDeviceBlackColorSpace = @"DeviceBlackColorSpace";
CPDeviceRGBColorSpace = @"DeviceRGBColorSpace";
CPDeviceCMYKColorSpace = @"DeviceCMYKColorSpace";
CPNamedColorSpace = @"NamedColorSpace";
CPPatternColorSpace = @"PatternColorSpace";
CPCustomColorSpace = @"CustomColorSpace";
function CPDrawTiledRects(
/* CGRect */ boundsRect,
+34 -1
View File
@@ -25,7 +25,8 @@
@import "CGContext.j"
var CPGraphicsContextCurrent = nil;
var CPGraphicsContextCurrent = nil,
CPGraphicsContextThreadStack = nil;
/*!
@ingroup appkit
@@ -52,6 +53,28 @@ var CPGraphicsContextCurrent = nil;
CPGraphicsContextCurrent = aGraphicsContext;
}
+ (void)saveGraphicsState
{
if (!CPGraphicsContextCurrent)
return;
if (!CPGraphicsContextThreadStack)
CPGraphicsContextThreadStack = [CPMutableArray array];
[CPGraphicsContextThreadStack addObject:CPGraphicsContextCurrent];
[CPGraphicsContextCurrent saveGraphicsState];
}
+ (void)restoreGraphicsState
{
var lastContext = [CPGraphicsContextThreadStack lastObject];
if (lastContext)
{
[lastContext restoreGraphicsState];
[CPGraphicsContextThreadStack removeLastObject];
}
}
/*!
Creates a graphics context with a provided port.
@param aContext the context to initialize with
@@ -99,4 +122,14 @@ var CPGraphicsContextCurrent = nil;
return YES;
}
- (void)saveGraphicsState
{
CGContextSaveGState(_graphicsPort);
}
- (void)restoreGraphicsState
{
CGContextRestoreGState(_graphicsPort);
}
@end
+1 -2
View File
@@ -976,8 +976,7 @@ var _CPMenuBarVisible = NO,
for (; index < count; ++index)
{
var item = _items[index],
modifierMask = [item keyEquivalentModifierMask];
var item = _items[index];
if ([anEvent _triggersKeyEquivalent:[item keyEquivalent] withModifierMask:[item keyEquivalentModifierMask]])
{
+2 -4
View File
@@ -376,9 +376,8 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
var previousRowCount = [self numberOfRows];
itemInfo.isExpanded = YES;
// XXX Shouldn't the items reload before the notification is sent?
[self _noteItemDidExpand:anItem];
[self reloadItem:anItem reloadChildren:YES];
[self _noteItemDidExpand:anItem];
// Shift selection indexes below so that the same items remain selected.
var rowCountDelta = [self numberOfRows] - previousRowCount;
@@ -469,9 +468,8 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
}
itemInfo.isExpanded = NO;
// XXX Shouldn't the items reload before the notification is sent?
[self _noteItemDidCollapse:anItem];
[self reloadItem:anItem reloadChildren:YES];
[self _noteItemDidCollapse:anItem];
// Send selection notifications only after the items have loaded so that
// the new selection is consistent with the actual rows for any observers.
+5 -5
View File
@@ -45,7 +45,7 @@
{
var context = [[CPGraphicsContext currentContext] graphicsPort],
bounds = [self bounds],
maxX = CGRectGetWidth(bounds) - 2,
maxX = CGRectGetWidth(bounds),
maxY = CGRectGetHeight(bounds);
// Draw background
@@ -63,7 +63,7 @@
// Draw Top Border
CGContextBeginPath(context);
CGContextMoveToPoint(context, 1, 0);
CGContextMoveToPoint(context, 0, 0);
CGContextAddLineToPoint(context, maxX, 0);
CGContextClosePath(context);
CGContextSetStrokeColor(context, [_ruleEditor _sliceTopBorderColor]);
@@ -71,8 +71,8 @@
// Draw Bottom Border
CGContextBeginPath(context);
CGContextMoveToPoint(context, 1, maxY - 0.5);
CGContextAddLineToPoint(context, maxX, maxY - 0.5);
CGContextMoveToPoint(context, 0, maxY);
CGContextAddLineToPoint(context, maxX, maxY);
CGContextClosePath(context);
var bottomColor = (_rowIndex == [_ruleEditor _lastRow]) ? [_ruleEditor _sliceLastBottomBorderColor] : [_ruleEditor _sliceBottomBorderColor];
CGContextSetStrokeColor(context, bottomColor);
@@ -106,4 +106,4 @@
return [CPString stringWithFormat:@"<%@ %p index:%d indentation:%d>",[self className],self,[self rowIndex],[self indentation]];
}
@end
@end
@@ -121,7 +121,7 @@ var CONTROL_HEIGHT = 16.,
return [CPMenuItem separatorItem];
}
- (_CPRuleEditorTextField)_createStaticTextFieldWithStringValue:(CPString )text
- (_CPRuleEditorTextField)_createStaticTextFieldWithStringValue:(CPString)text
{
var textField = [[_CPRuleEditorTextField alloc] initWithFrame:CPMakeRect(0, 0, 200, CONTROL_HEIGHT)],
refont = [_ruleEditor font],
@@ -352,6 +352,15 @@ var CONTROL_HEIGHT = 16.,
optionFrame = _ruleOptionFrames[i];
optionFrame.origin.y = (rowHeight - CGRectGetHeight(optionFrame)) / 2 - 2;
// small positioning fix
if ([ruleOptionView isKindOfClass:CPTextField])
{
optionFrame.origin.y += 2;
[_ruleOptionViews[i] setValue:CGInsetMake(7, 7, 7, 8) forThemeAttribute:@"content-inset"];
}
if (widthChanged)
{
optionFrame.origin.x = optionViewOriginX;
+2 -2
View File
@@ -172,10 +172,10 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
scrollerWidth = [CPScroller scrollerWidth];
if (hFlag)
frameSize.height -= scrollerWidth;
frameSize.height += scrollerWidth;
if (vFlag)
frameSize.width -= scrollerWidth;
frameSize.width += scrollerWidth;
return frameSize;
}
+6 -1
View File
@@ -501,7 +501,12 @@ var RECENT_SEARCH_PREFIX = @" ";
if (_CGRectContainsPoint([self searchButtonRectForBounds:[self bounds]], point))
{
if (_searchMenuTemplate == nil)
[self _sendAction:self];
{
if ([_searchButton target] && [_searchButton action])
[_searchButton mouseDown:anEvent];
else
[self _sendAction:self];
}
else
[self _showMenu];
}
+6 -3
View File
@@ -366,11 +366,14 @@ CPSegmentSwitchTrackingMomentary = 2;
@param aSegment the segment to enable/disable
@throws CPRangeException if \c aSegment is out of bounds
*/
- (void)setEnabled:(BOOL)isEnabled forSegment:(unsigned)aSegment
- (void)setEnabled:(BOOL)shouldBeEnabled forSegment:(unsigned)aSegment
{
[_segments[aSegment] setEnabled:isEnabled];
if ([_segments[aSegment] enabled] === shouldBeEnabled)
return;
if (isEnabled)
[_segments[aSegment] setEnabled:shouldBeEnabled];
if (shouldBeEnabled)
_themeStates[aSegment] &= ~CPThemeStateDisabled;
else
_themeStates[aSegment] |= CPThemeStateDisabled;
+31 -1
View File
@@ -494,7 +494,13 @@ CPTableColumnUserResizingMask = 1 << 1;
*/
- (CPSortDescriptor)sortDescriptorPrototype
{
return _sortDescriptorPrototype;
if (_sortDescriptorPrototype)
return _sortDescriptorPrototype;
var binderClass = [[self class] _binderClassForBinding:CPValueBinding],
binding = [binderClass getBinding:CPValueBinding forObject:self];
return [binding _defaultSortDescriptorPrototype];
}
/*!
@@ -570,6 +576,30 @@ CPTableColumnUserResizingMask = 1 << 1;
[tableView reloadDataForRowIndexes:rowIndexes columnIndexes:columnIndexes];
}
- (CPSortDescriptor)_defaultSortDescriptorPrototype
{
if (![self createsSortDescriptor])
return nil;
var keyPath = [_info objectForKey:CPObservedKeyPathKey],
dotIndex = keyPath.indexOf(".");
if (dotIndex === CPNotFound)
return nil;
var firstPart = keyPath.substring(0, dotIndex),
key = keyPath.substring(dotIndex + 1);
return [CPSortDescriptor sortDescriptorWithKey:key ascending:YES];
}
- (BOOL)createsSortDescriptor
{
var options = [_info objectForKey:CPOptionsKey],
optionValue = [options objectForKey:CPCreatesSortDescriptorBindingOption];
return optionValue === nil ? YES : [optionValue boolValue];
}
@end
@implementation CPTableColumn (Bindings)
+62 -4
View File
@@ -39,8 +39,8 @@
+ (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", @"font", @"text-shadow-color", @"text-shadow-offset"]];
return [CPDictionary dictionaryWithObjects:[[CPNull null], CPLeftTextAlignment, CPLineBreakByTruncatingTail, CGInsetMakeZero(), [CPNull null], [CPNull null], [CPNull null], CGSizeMakeZero()]
forKeys:[@"background-color", @"text-alignment", @"line-break-mode", @"text-inset", @"text-color", @"font", @"text-shadow-color", @"text-shadow-offset"]];
}
- (void)initWithFrame:(CGRect)frame
@@ -78,6 +78,7 @@
[_textField setTextShadowColor:[self currentValueForThemeAttribute:@"text-shadow-color"]];
[_textField setTextShadowOffset:[self currentValueForThemeAttribute:@"text-shadow-offset"]];
[_textField setAlignment:[self currentValueForThemeAttribute:@"text-alignment"]];
[_textField setLineBreakMode:[self currentValueForThemeAttribute:@"line-break-mode"]];
}
- (void)setStringValue:(CPString)string
@@ -102,7 +103,52 @@
- (void)setFont:(CPFont)aFont
{
[self setValue:aFont forThemeAttribute:"font"];
[self setValue:aFont forThemeAttribute:@"font"];
}
- (CPFont)font
{
return [self currentValueForThemeAttribute:@"font"]
}
- (void)setAlignment:(CPTextAlignment)alignment
{
[self setValue:alignment forThemeAttribute:@"text-alignment"];
}
- (CPTextAlignment)alignment
{
return [self currentValueForThemeAttribute:@"text-alignment"]
}
- (void)setLineBreakMode:(CPLineBreakMode)mode
{
[self setValue:mode forThemeAttribute:@"line-break-mode"];
}
- (CPLineBreakMode)lineBreakMode
{
return [self currentValueForThemeAttribute:@"line-break-mode"]
}
- (void)setTextColor:(CPColor)aColor
{
[self setValue:aColor forThemeAttribute:@"text-color"];
}
- (CPColor)textColor
{
return [self currentValueForThemeAttribute:@"text-color"]
}
- (void)setTextShadowColor:(CPColor)aColor
{
[self setValue:aColor forThemeAttribute:@"text-shadow-color"];
}
- (CPColor)textShadowColor
{
return [self currentValueForThemeAttribute:@"text-shadow-color"]
}
- (void)_setIndicatorImage:(CPImage)anImage
@@ -122,6 +168,10 @@
var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringValueKey",
_CPTableColumnHeaderViewFontKey = @"_CPTableColumnHeaderViewFontKey",
_CPTableColumnHeaderViewTextColorKey = @"_CPTableColumnHeaderViewTextColorKey",
_CPTableColumnHeaderViewTextShadowColorKey = @"_CPTableColumnHeaderViewTextShadowColorKey",
_CPTableColumnHeaderViewAlignmentKey = @"_CPTableColumnHeaderViewAlignmentKey",
_CPTableColumnHeaderViewLineBreakModeKey = @"_CPTableColumnHeaderViewLineBreakModeKey",
_CPTableColumnHeaderViewImageKey = @"_CPTableColumnHeaderViewImageKey";
@implementation _CPTableColumnHeaderView (CPCoding)
@@ -134,6 +184,10 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
[self _setIndicatorImage:[aCoder decodeObjectForKey:_CPTableColumnHeaderViewImageKey]];
[self setStringValue:[aCoder decodeObjectForKey:_CPTableColumnHeaderViewStringValueKey]];
[self setFont:[aCoder decodeObjectForKey:_CPTableColumnHeaderViewFontKey]];
[self setTextColor:[aCoder decodeObjectForKey:_CPTableColumnHeaderViewTextColorKey]];
[self setTextShadowColor:[aCoder decodeObjectForKey:_CPTableColumnHeaderViewTextShadowColorKey]];
[self setAlignment:[aCoder decodeIntForKey:_CPTableColumnHeaderViewAlignmentKey]];
[self setLineBreakMode:[aCoder decodeIntForKey:_CPTableColumnHeaderViewLineBreakModeKey]];
}
return self;
@@ -145,7 +199,11 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
[aCoder encodeObject:[_textField text] forKey:_CPTableColumnHeaderViewStringValueKey];
[aCoder encodeObject:[_textField image] forKey:_CPTableColumnHeaderViewImageKey];
[aCoder encodeObject:[_textField font] forKey:_CPTableColumnHeaderViewFontKey];
[aCoder encodeObject:[self font] forKey:_CPTableColumnHeaderViewFontKey];
[aCoder encodeObject:[self textColor] forKey:_CPTableColumnHeaderViewTextColorKey];
[aCoder encodeObject:[self textShadowColor] forKey:_CPTableColumnHeaderViewTextShadowColorKey];
[aCoder encodeInt:[self alignment] forKey:_CPTableColumnHeaderViewAlignmentKey];
[aCoder encodeInt:[self lineBreakMode] forKey:_CPTableColumnHeaderViewLineBreakModeKey];
}
@end
+32 -18
View File
@@ -29,6 +29,7 @@
@import "CPTableColumn.j"
@import "_CPCornerView.j"
@import "CPScroller.j"
@import "CPCompatibility.j"
CPTableViewColumnDidMoveNotification = @"CPTableViewColumnDidMoveNotification";
@@ -221,6 +222,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
SEL _doubleAction;
CPInteger _clickedRow;
CPInteger _clickedColumn;
unsigned _columnAutoResizingStyle;
int _lastTrackedRowIndex;
@@ -323,7 +325,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
*/
- (void)_init
{
_lastSelectedRow = -1;
_lastSelectedRow = _clickedColumn = _clickedRow = -1;
_selectedColumnIndexes = [CPIndexSet indexSet];
_selectedRowIndexes = [CPIndexSet indexSet];
@@ -541,8 +543,12 @@ NOT YET IMPLEMENTED
}
/*
* - clickedColumn
Returns the index of the the column the user clicked to trigger an action, or -1 if no column was clicked.
*/
- (CPInteger)clickedColumn
{
return _clickedColumn;
}
/*!
Returns the index of the the row the user clicked to trigger an action, or -1 if no row was clicked.
@@ -2644,7 +2650,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
if (_allowsColumnSelection)
{
[self _noteSelectionIsChanging];
if (modifierFlags & CPCommandKeyMask)
if (modifierFlags & CPPlatformActionKeyMask)
{
if ([self isColumnSelected:clickedColumn])
[self deselectColumn:clickedColumn];
@@ -2881,13 +2887,8 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
row = [_exposedRows indexGreaterThanIndex:row];
}
// Add the column header view
var headerFrame = [headerView frame];
headerFrame.origin = _CGPointMakeZero();
var columnHeaderView = [[_CPTableColumnHeaderView alloc] initWithFrame:headerFrame];
[columnHeaderView setStringValue:[headerView stringValue]];
[columnHeaderView setThemeState:[headerView themeState]];
// Add a copy of the header view.
var columnHeaderView = [CPKeyedUnarchiver unarchiveObjectWithData:[CPKeyedArchiver archivedDataWithRootObject:headerView]];
[dragView addSubview:columnHeaderView];
[dragView setBackgroundColor:[CPColor whiteColor]];
@@ -3380,12 +3381,15 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
rowIndex = 0,
rowsCount = rowArray.length;
for (; rowIndex < rowsCount; ++rowIndex)
if (dataViewsForTableColumn)
{
var row = rowArray[rowIndex],
dataView = dataViewsForTableColumn[row];
for (; rowIndex < rowsCount; ++rowIndex)
{
var row = rowArray[rowIndex],
dataView = dataViewsForTableColumn[row];
[dataView setFrame:[self frameOfDataViewAtColumn:column row:row]];
[dataView setFrame:[self frameOfDataViewAtColumn:column row:row]];
}
}
}
}
@@ -4192,7 +4196,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
_isSelectingSession = NO;
var CLICK_TIME_DELTA = 1000,
columnIndex,
columnIndex = -1,
column,
rowIndex,
shouldEdit = YES;
@@ -4200,6 +4204,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
if (_implementedDataSourceMethods & CPTableViewDataSource_tableView_writeRowsWithIndexes_toPasteboard_)
{
rowIndex = [self rowAtPoint:aPoint];
if (rowIndex !== -1)
{
if ([_draggedRowIndexes count] > 0)
@@ -4221,12 +4226,15 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|| [self infoForBinding:@"content"]))
{
columnIndex = [self columnAtPoint:lastPoint];
if (columnIndex !== -1)
{
column = _tableColumns[columnIndex];
if ([column isEditable])
{
rowIndex = [self rowAtPoint:aPoint];
if (rowIndex !== -1)
{
if (_implementedDelegateMethods & CPTableViewDelegate_tableView_shouldEditTableColumn_row_)
@@ -4246,6 +4254,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
if ([[CPApp currentEvent] clickCount] === 2 && _doubleAction)
{
_clickedRow = [self rowAtPoint:aPoint];
_clickedColumn = [self columnAtPoint:lastPoint];
[self sendAction:_doubleAction to:_target];
}
}
@@ -4785,10 +4794,15 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
_contentBindingExpicitelySet = NO;
}
if ([[self infoForBinding:@"selectionIndexes"] objectForKey:CPObservedObjectKey] !== destination)
[self bind:@"selectionIndexes" toObject:destination withKeyPath:@"selectionIndexes" options:nil];
// If the content binding was set manually assume the user is taking manual control of establishing bindings.
if (!_contentBindingExpicitelySet)
{
if ([[self infoForBinding:@"selectionIndexes"] objectForKey:CPObservedObjectKey] !== destination)
[self bind:@"selectionIndexes" toObject:destination withKeyPath:@"selectionIndexes" options:nil];
//[self bind:@"sortDescriptors" toObject:destination withKeyPath:@"sortDescriptors" options:nil];
if ([[self infoForBinding:@"sortDescriptors"] objectForKey:CPObservedObjectKey] !== destination)
[self bind:@"sortDescriptors" toObject:destination withKeyPath:@"sortDescriptors" options:nil];
}
}
- (void)bind:(CPString)aBinding toObject:(id)anObject withKeyPath:(CPString)aKeyPath options:(CPDictionary)options
+4
View File
@@ -1174,6 +1174,10 @@ var LABEL_MARGIN = 2.0;
- (void)setEnabled:(BOOL)shouldBeEnabled
{
// Tiling is very expensive so try to avoid it. The CPToolbarItem should already be careful to not notifying about its enabled state needlessly.
if ([self isEnabled] === shouldBeEnabled)
return;
[super setEnabled:shouldBeEnabled];
if (shouldBeEnabled)
+32 -6
View File
@@ -275,6 +275,9 @@ CPToolbarPrintItemIdentifier = @"CPToolbarPrintItem";
*/
- (void)setEnabled:(BOOL)shouldBeEnabled
{
if (_isEnabled === shouldBeEnabled)
return;
if ([_view respondsToSelector:@selector(setEnabled:)])
[_view setEnabled:shouldBeEnabled];
@@ -457,26 +460,49 @@ CPToolbarItemVisibilityPriorityUser
if (_view)
{
if ([target respondsToSelector:@selector(validateToolbarItem:)])
[self setEnabled:[target validateToolbarItem:self]];
{
var shouldBeEnabled = [target validateToolbarItem:self];
if (_isEnabled !== shouldBeEnabled)
[self setEnabled:shouldBeEnabled];
}
return;
}
if (!action)
return [self setEnabled:NO];
{
if (_isEnabled)
return [self setEnabled:NO];
return;
}
if (target && ![target respondsToSelector:action])
return [self setEnabled:NO];
{
if (_isEnabled)
return [self setEnabled:NO];
return;
}
target = [CPApp targetForAction:action to:target from:self];
if (!target)
return [self setEnabled:NO];
{
if (_isEnabled)
return [self setEnabled:NO];
return;
}
if ([target respondsToSelector:@selector(validateToolbarItem:)])
[self setEnabled:[target validateToolbarItem:self]];
{
var shouldBeEnabled = [target validateToolbarItem:self];
if (_isEnabled !== shouldBeEnabled)
[self setEnabled:shouldBeEnabled];
}
else
[self setEnabled:YES];
{
if (!_isEnabled)
[self setEnabled:YES];
}
}
- (BOOL)autovalidates
+229 -113
View File
@@ -98,9 +98,6 @@ var CPViewFlags = { },
CPViewHasCustomDrawRect = 1 << 0,
CPViewHasCustomLayoutSubviews = 1 << 1;
var CPCurrentToolTip,
CPCurrentToolTipTimer,
CPToolTipDelay = 1.0;
/*!
@ingroup appkit
@@ -246,8 +243,8 @@ var CPCurrentToolTip,
- (void)_setupToolTipHandlers
{
_toolTipInstalled = NO;
_toolTipFunctionIn = function(e) { [self _fireToolTip]; }
_toolTipFunctionOut = function(e) { [self _invalidateToolTip]; };
_toolTipFunctionIn = function(e) { [_CPToolTip scheduleToolTipForView:self]; }
_toolTipFunctionOut = function(e) { [_CPToolTip invalidateCurrentToolTipIfNeeded]; };
}
+ (CPSet)keyPathsForValuesAffectingFrame
@@ -336,6 +333,9 @@ var CPCurrentToolTip,
if (_toolTip == aToolTip)
return;
if (aToolTip && ![aToolTip isKindOfClass:CPString])
aToolTip = [aToolTip description];
_toolTip = aToolTip;
if (_toolTip)
@@ -398,54 +398,6 @@ var CPCurrentToolTip,
_toolTipInstalled = NO;
}
/*! @ignore
Starts the tooltip timer.
*/
- (void)_fireToolTip
{
if (CPCurrentToolTipTimer)
{
[CPCurrentToolTipTimer invalidate];
if (CPCurrentToolTip)
[CPCurrentToolTip close];
CPCurrentToolTip = nil;
}
if (_toolTip)
CPCurrentToolTipTimer = [CPTimer scheduledTimerWithTimeInterval:CPToolTipDelay target:self selector:@selector(_showToolTip:) userInfo:nil repeats:NO];
}
/*! @ignore
Stop the tooltip timer if any
*/
- (void)_invalidateToolTip
{
if (CPCurrentToolTipTimer)
{
[CPCurrentToolTipTimer invalidate];
CPCurrentToolTipTimer = nil;
}
if (CPCurrentToolTip)
{
[CPCurrentToolTip close];
CPCurrentToolTip = nil;
}
}
/*! @ignore
Actually shows the tooltip if any
*/
- (void)_showToolTip:(CPTimer)aTimer
{
if (CPCurrentToolTip)
[CPCurrentToolTip close];
CPCurrentToolTip = [_CPToolTip toolTipWithString:_toolTip];
}
/*!
Returns the container view of the receiver
@return the receiver's containing view
@@ -987,32 +939,90 @@ var CPCurrentToolTip,
}
else
{
var images = [[_backgroundColor patternImage] imageSlices];
var images = [[_backgroundColor patternImage] imageSlices],
partIndex = 0;
if (_backgroundType === BackgroundVerticalThreePartImage)
{
var top = _DOMImageSizes[0] ? _DOMImageSizes[0].height : 0,
bottom = _DOMImageSizes[2] ? _DOMImageSizes[2].height : 0;
// Make sure to repeat the top and bottom pieces horizontally if they're not the exact width needed.
CPDOMDisplayServerSetStyleSize(_DOMImageParts[0], size.width, _DOMImageSizes[0].height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], size.width, size.height - _DOMImageSizes[0].height - _DOMImageSizes[2].height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[2], size.width, _DOMImageSizes[2].height);
if (top)
{
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], size.width, top);
partIndex++;
}
if (_DOMImageSizes[1])
{
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], size.width, size.height - top - bottom);
partIndex++;
}
if (bottom)
{
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], size.width, bottom);
}
}
else if (_backgroundType === BackgroundHorizontalThreePartImage)
{
var left = _DOMImageSizes[0] ? _DOMImageSizes[0].width : 0,
right = _DOMImageSizes[2] ? _DOMImageSizes[2].width : 0;
// Make sure to repeat the left and right pieces vertically if they're not the exact height needed.
CPDOMDisplayServerSetStyleSize(_DOMImageParts[0], _DOMImageSizes[0].width, size.height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], size.width - _DOMImageSizes[0].width - _DOMImageSizes[2].width, size.height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[2], _DOMImageSizes[2].width, size.height);
if (left)
{
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], left, size.height);
partIndex++;
}
if (_DOMImageSizes[1])
{
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], size.width - left - right, size.height);
partIndex++;
}
if (right)
{
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], right, 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;
var left = _DOMImageSizes[0] ? _DOMImageSizes[0].width : 0,
right = _DOMImageSizes[2] ? _DOMImageSizes[2].width : 0,
top = _DOMImageSizes[0] ? _DOMImageSizes[0].height : 0,
bottom = _DOMImageSizes[6] ? _DOMImageSizes[6].height : 0,
width = size.width - left - right,
height = size.height - top - bottom;
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], width, _DOMImageSizes[0].height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[3], _DOMImageSizes[3].width, height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[4], width, height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[5], _DOMImageSizes[5].width, height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[7], width, _DOMImageSizes[7].height);
if (_DOMImageSizes[0])
partIndex++;
if (_DOMImageSizes[1])
{
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], width, top);
partIndex++;
}
if (_DOMImageSizes[2])
partIndex++;
if (_DOMImageSizes[3])
{
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], _DOMImageSizes[3].width, height);
partIndex++;
}
if (_DOMImageSizes[4])
{
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], width, height);
partIndex++;
}
if (_DOMImageSizes[5])
{
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], _DOMImageSizes[5].width, height);
partIndex++;
}
if (_DOMImageSizes[6])
partIndex++;
if (_DOMImageSizes[7])
{
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], width, _DOMImageSizes[7].height);
}
}
}
}
@@ -1508,7 +1518,7 @@ var CPCurrentToolTip,
*/
- (CPView)hitTest:(CPPoint)aPoint
{
if (_isHidden || !_hitTests || !CPRectContainsPoint(_frame, aPoint))
if (_isHidden || !_hitTests || !_CGRectContainsPoint(_frame, aPoint))
return nil;
var view = nil,
@@ -1584,17 +1594,18 @@ var CPCurrentToolTip,
colorHasAlpha = colorExists && [_backgroundColor alphaComponent] < 1.0,
supportsRGBA = CPFeatureIsCompatible(CPCSSRGBAFeature),
colorNeedsDOMElement = colorHasAlpha && !supportsRGBA,
amount = 0;
amount = 0,
slices;
if ([patternImage isThreePartImage])
{
_backgroundType = [patternImage isVertical] ? BackgroundVerticalThreePartImage : BackgroundHorizontalThreePartImage;
amount = 3 - _DOMImageParts.length;
amount = 3;
}
else if ([patternImage isNinePartImage])
{
_backgroundType = BackgroundNinePartImage;
amount = 9 - _DOMImageParts.length;
amount = 9;
}
else
{
@@ -1602,6 +1613,34 @@ var CPCurrentToolTip,
amount = (colorNeedsDOMElement ? 1 : 0) - _DOMImageParts.length;
}
// Prepare multipart image data and reduce number of required DOM parts by number of empty slices in the multipart image to save needless DOM elements.
if (_backgroundType === BackgroundVerticalThreePartImage || _backgroundType === BackgroundHorizontalThreePartImage || _backgroundType === BackgroundNinePartImage)
{
slices = [patternImage imageSlices];
// We won't need more divs than there are slices.
amount = MIN(amount, slices.length);
for (var i = 0, count = slices.length; i < count; i++)
{
var image = slices[i],
size = [image size];
if (!size || (size.width == 0 && size.height == 0))
size = nil;
_DOMImageSizes[i] = size;
// If there's a nil slice or a slice with no size, it won't need a div.
if (!size)
amount--;
}
// Now that we know how many divs we really need, compare that to number we actually have.
amount -= _DOMImageParts.length;
}
// Make sure the number of divs we have match our needs.
if (amount > 0)
{
while (amount--)
@@ -1643,70 +1682,148 @@ var CPCurrentToolTip,
}
else
{
var slices = [patternImage imageSlices],
count = MIN(_DOMImageParts.length, slices.length),
frameSize = _frame.size;
var frameSize = _frame.size,
partIndex = 0;
while (count--)
for (var i = 0; i < slices.length; i++)
{
var image = slices[count],
size = _DOMImageSizes[count] = image ? [image size] : _CGSizeMakeZero();
var size = _DOMImageSizes[i];
CPDOMDisplayServerSetStyleSize(_DOMImageParts[count], size.width, size.height);
if (!size)
continue;
_DOMImageParts[count].style.background = image ? "url(\"" + [image filename] + "\")" : "";
var image = slices[i];
// // If image was nil, size should have been nil too.
// assert(image != nil);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], size.width, size.height);
_DOMImageParts[partIndex].style.background = "url(\"" + [image filename] + "\")";
if (!supportsRGBA)
{
if (CPFeatureIsCompatible(CPOpacityRequiresFilterFeature))
try { _DOMImageParts[count].style.removeAttribute("filter") } catch (anException) { }
try { _DOMImageParts[partIndex].style.removeAttribute("filter") } catch (anException) { }
else
_DOMImageParts[count].style.opacity = 1.0;
_DOMImageParts[partIndex].style.opacity = 1.0;
}
partIndex++;
}
if (_backgroundType == BackgroundNinePartImage)
{
var width = frameSize.width - _DOMImageSizes[0].width - _DOMImageSizes[2].width,
height = frameSize.height - _DOMImageSizes[0].height - _DOMImageSizes[6].height;
var left = _DOMImageSizes[0] ? _DOMImageSizes[0].width : 0,
right = _DOMImageSizes[2] ? _DOMImageSizes[2].width : 0,
top = _DOMImageSizes[0] ? _DOMImageSizes[0].height : 0,
bottom = _DOMImageSizes[6] ? _DOMImageSizes[6].height : 0,
width = frameSize.width - left - right,
height = frameSize.height - top - bottom;
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], width, _DOMImageSizes[0].height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[3], _DOMImageSizes[3].width, height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[4], width, height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[5], _DOMImageSizes[5].width, height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[7], width, _DOMImageSizes[7].height);
partIndex = 0;
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[0], NULL, 0.0, 0.0);
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[1], NULL, _DOMImageSizes[0].width, 0.0);
CPDOMDisplayServerSetStyleRightTop(_DOMImageParts[2], NULL, 0.0, 0.0);
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[3], NULL, 0.0, _DOMImageSizes[1].height);
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[4], NULL, _DOMImageSizes[0].width, _DOMImageSizes[0].height);
CPDOMDisplayServerSetStyleRightTop(_DOMImageParts[5], NULL, 0.0, _DOMImageSizes[1].height);
CPDOMDisplayServerSetStyleLeftBottom(_DOMImageParts[6], NULL, 0.0, 0.0);
CPDOMDisplayServerSetStyleLeftBottom(_DOMImageParts[7], NULL, _DOMImageSizes[6].width, 0.0);
CPDOMDisplayServerSetStyleRightBottom(_DOMImageParts[8], NULL, 0.0, 0.0);
if (_DOMImageSizes[0])
{
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
partIndex++;
}
if (_DOMImageSizes[1])
{
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, left, 0.0);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], width, _DOMImageSizes[1].height);
partIndex++;
}
if (_DOMImageSizes[2])
{
CPDOMDisplayServerSetStyleRightTop(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
partIndex++;
}
if (_DOMImageSizes[3])
{
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, 0.0, top);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], _DOMImageSizes[3].width, height);
partIndex++;
}
if (_DOMImageSizes[4])
{
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, left, top);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], width, height);
partIndex++;
}
if (_DOMImageSizes[5])
{
CPDOMDisplayServerSetStyleRightTop(_DOMImageParts[partIndex], NULL, 0.0, top);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], _DOMImageSizes[5].width, height);
partIndex++;
}
if (_DOMImageSizes[6])
{
CPDOMDisplayServerSetStyleLeftBottom(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
partIndex++;
}
if (_DOMImageSizes[7])
{
CPDOMDisplayServerSetStyleLeftBottom(_DOMImageParts[partIndex], NULL, left, 0.0);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], width, _DOMImageSizes[7].height);
partIndex++;
}
if (_DOMImageSizes[8])
{
CPDOMDisplayServerSetStyleRightBottom(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
}
}
else if (_backgroundType == BackgroundVerticalThreePartImage)
{
// Make sure to repeat the top and bottom pieces horizontally if they're not the exact width needed.
CPDOMDisplayServerSetStyleSize(_DOMImageParts[0], frameSize.width, _DOMImageSizes[0].height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], frameSize.width, frameSize.height - _DOMImageSizes[0].height - _DOMImageSizes[2].height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[2], frameSize.width, _DOMImageSizes[2].height);
var top = _DOMImageSizes[0] ? _DOMImageSizes[0].height : 0,
bottom = _DOMImageSizes[2] ? _DOMImageSizes[2].height : 0;
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[0], NULL, 0.0, 0.0);
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[1], NULL, 0.0, _DOMImageSizes[0].height);
CPDOMDisplayServerSetStyleLeftBottom(_DOMImageParts[2], NULL, 0.0, 0.0);
partIndex = 0;
// Make sure to repeat the top and bottom pieces horizontally if they're not the exact width needed.
if (top)
{
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], frameSize.width, top);
partIndex++;
}
if (_DOMImageSizes[1])
{
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, 0.0, top);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], frameSize.width, frameSize.height - top - bottom);
partIndex++;
}
if (bottom)
{
CPDOMDisplayServerSetStyleLeftBottom(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], frameSize.width, bottom);
}
}
else if (_backgroundType == BackgroundHorizontalThreePartImage)
{
// Make sure to repeat the left and right pieces vertically if they're not the exact height needed.
CPDOMDisplayServerSetStyleSize(_DOMImageParts[0], _DOMImageSizes[0].width, frameSize.height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], frameSize.width - _DOMImageSizes[0].width - _DOMImageSizes[2].width, frameSize.height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[2], _DOMImageSizes[2].width, frameSize.height);
var left = _DOMImageSizes[0] ? _DOMImageSizes[0].width : 0,
right = _DOMImageSizes[2] ? _DOMImageSizes[2].width : 0;
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[0], NULL, 0.0, 0.0);
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[1], NULL, _DOMImageSizes[0].width, 0.0);
CPDOMDisplayServerSetStyleRightTop(_DOMImageParts[2], NULL, 0.0, 0.0);
partIndex = 0;
// Make sure to repeat the left and right pieces vertically if they're not the exact height needed.
if (left)
{
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], left, frameSize.height);
partIndex++;
}
if (_DOMImageSizes[1])
{
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, left, 0.0);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], frameSize.width - left - right, frameSize.height);
partIndex++;
}
if (right)
{
CPDOMDisplayServerSetStyleRightTop(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], right, frameSize.height);
}
}
}
#endif
@@ -2907,6 +3024,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
[self _setupToolTipHandlers];
_toolTip = [aCoder decodeObjectForKey:CPViewToolTipKey];
if (_toolTip)
[self _installToolTipEventHandlers];
@@ -3143,5 +3261,3 @@ var _CPViewGetTransform = function(/*CPView*/ fromView, /*CPView */ toView)
return transform;
};
+5
View File
@@ -1032,6 +1032,11 @@ CPWebViewAppKitScrollMaxPollCount = 3;
var documentURL = [CPURL URLWithString:window.location.href];
if ([documentURL isFileURL] && CPFeatureIsCompatible(CPSOPDisabledFromFileURLs))
return YES;
// Relative URLs always pass the SOP.
if (![self scheme] && ![self host] && ![self port])
return YES;
return ([documentURL scheme] == [self scheme] && [documentURL host] == [self host] && [documentURL port] == [self port]);
}
+46
View File
@@ -287,6 +287,9 @@ var CPWindowActionMessageKeys = [
unsigned _shadowStyle;
BOOL _showsResizeIndicator;
int _positioningMask;
CGRect _positioningScreenRect;
BOOL _isDocumentEdited;
BOOL _isDocumentSaving;
@@ -535,6 +538,49 @@ CPTexturedBackgroundWindowMask
// set up a default key view loop.
if (_keyViewLoopIsDirty && ![self autorecalculatesKeyViewLoop])
[self recalculateKeyViewLoop];
// At this time we know the final screen (or browser) size and can apply the positioning mask, if any, from the nib.
if (_positioningScreenRect)
{
var actualScreenRect = [CPPlatform isBrowser] ? [_platformWindow contentBounds] : [[self screen] visibleFrame],
frame = [self frame],
origin = frame.origin;
if (actualScreenRect)
{
if ((_positioningMask & CPWindowPositionFlexibleLeft) && (_positioningMask & CPWindowPositionFlexibleRight))
{
// Proportional Horizontal.
origin.x *= (actualScreenRect.size.width / _positioningScreenRect.size.width);
}
else if (_positioningMask & CPWindowPositionFlexibleLeft)
{
// Fixed from Right
origin.x += actualScreenRect.size.width - _positioningScreenRect.size.width;
}
else if (_positioningMask & CPWindowPositionFlexibleRight)
{
// Fixed from Left
}
if ((_positioningMask & CPWindowPositionFlexibleTop) && (_positioningMask & CPWindowPositionFlexibleBottom))
{
// Proportional Vertical.
origin.y *= (actualScreenRect.size.height / _positioningScreenRect.size.height);
}
else if (_positioningMask & CPWindowPositionFlexibleTop)
{
// Fixed from Bottom
origin.y += actualScreenRect.size.height - _positioningScreenRect.size.height;
}
else if (_positioningMask & CPWindowPositionFlexibleBottom)
{
// Fixed from Top
}
[self setFrameOrigin:origin];
}
}
}
- (void)_setWindowView:(CPView)aWindowView
+86 -66
View File
@@ -4,29 +4,20 @@
@import "CGGeometry.j"
@import "CPWindow.j"
CPWindowPositionFlexibleRight = 1 << 19;
CPWindowPositionFlexibleLeft = 1 << 20;
CPWindowPositionFlexibleBottom = 1 << 21;
CPWindowPositionFlexibleTop = 1 << 22;
var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinSizeKey",
_CPCibWindowTemplateMaxSizeKey = @"_CPCibWindowTemplateMaxSizeKey",
_CPCibWindowTemplateViewClassKey = @"_CPCibWindowTemplateViewClassKey",
_CPCibWindowTemplateWindowClassKey = @"_CPCibWindowTemplateWindowClassKey",
_CPCibWindowTemplateWindowRectKey = @"_CPCibWindowTemplateWindowRectKey",
_CPCibWindowTemplateWindowStyleMaskKey = @"_CPCibWindowTempatStyleMaskKey",
_CPCibWindowTemplateWindowTitleKey = @"_CPCibWindowTemplateWindowTitleKey",
_CPCibWindowTemplateWindowViewKey = @"_CPCibWindowTemplateWindowViewKey",
_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop = @"_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop",
_CPCibWindowTemplateWindowIsFullPlatformWindowKey = @"_CPCibWindowTemplateWindowIsFullPlatformWindowKey";
@implementation _CPCibWindowTemplate : CPObject
{
CGSize _minSize;
CGSize _maxSize;
//CGSize _screenRect;
CGRect _screenRect;
id _viewClass;
//unsigned _wtFlags;
unsigned _wtFlags;
CPString _windowClass;
CGRect _windowRect;
unsigned _windowStyleMask;
@@ -52,67 +43,18 @@ var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemp
_windowView = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, 400.0, 200.0)];
_windowIsFullPlatformWindow = NO;
_wtFlags = CPPositionProportionalHorizontal | CPPositionProportionalVertical;
}
return self;
}
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
if ([aCoder containsValueForKey:_CPCibWindowTemplateMinSizeKey])
_minSize = [aCoder decodeSizeForKey:_CPCibWindowTemplateMinSizeKey];
if ([aCoder containsValueForKey:_CPCibWindowTemplateMaxSizeKey])
_maxSize = [aCoder decodeSizeForKey:_CPCibWindowTemplateMaxSizeKey];
_viewClass = [aCoder decodeObjectForKey:_CPCibWindowTemplateViewClassKey];
_windowClass = [aCoder decodeObjectForKey:_CPCibWindowTemplateWindowClassKey];
_windowRect = [aCoder decodeRectForKey:_CPCibWindowTemplateWindowRectKey];
_windowStyleMask = [aCoder decodeIntForKey:_CPCibWindowTemplateWindowStyleMaskKey];
_windowTitle = [aCoder decodeObjectForKey:_CPCibWindowTemplateWindowTitleKey];
_windowView = [aCoder decodeObjectForKey:_CPCibWindowTemplateWindowViewKey];
_windowAutorecalculatesKeyViewLoop = [aCoder decodeBoolForKey:_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop];
_windowIsFullPlatformWindow = [aCoder decodeBoolForKey:_CPCibWindowTemplateWindowIsFullPlatformWindowKey];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
if (_minSize)
[aCoder encodeSize:_minSize forKey:_CPCibWindowTemplateMinSizeKey];
if (_maxSize)
[aCoder encodeSize:_maxSize forKey:_CPCibWindowTemplateMaxSizeKey];
[aCoder encodeObject:_viewClass forKey:_CPCibWindowTemplateViewClassKey];
[aCoder encodeObject:_windowClass forKey:_CPCibWindowTemplateWindowClassKey];
[aCoder encodeRect:_windowRect forKey:_CPCibWindowTemplateWindowRectKey];
[aCoder encodeInt:_windowStyleMask forKey:_CPCibWindowTemplateWindowStyleMaskKey];
[aCoder encodeObject:_windowTitle forKey:_CPCibWindowTemplateWindowTitleKey];
[aCoder encodeObject:_windowView forKey:_CPCibWindowTemplateWindowViewKey];
if (_windowAutorecalculatesKeyViewLoop)
[aCoder encodeObject:_windowAutorecalculatesKeyViewLoop forKey:_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop];
if (_windowIsFullPlatformWindow)
[aCoder encodeObject:_windowIsFullPlatformWindow forKey:_CPCibWindowTemplateWindowIsFullPlatformWindowKey];
}
- (CPString)customClassName
{
return _windowClass;
}
- (void)setCustomClassName:(CPString)aClassName
{
_windowClass = aClassName;
@@ -155,7 +97,85 @@ var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemp
[theWindow setAutorecalculatesKeyViewLoop:_windowAutorecalculatesKeyViewLoop];
[theWindow setFullBridge:_windowIsFullPlatformWindow];
theWindow._positioningMask = _wtFlags;
theWindow._positioningScreenRect = _screenRect;
return theWindow;
}
@end
var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinSizeKey",
_CPCibWindowTemplateMaxSizeKey = @"_CPCibWindowTemplateMaxSizeKey",
_CPCibWindowTemplateViewClassKey = @"_CPCibWindowTemplateViewClassKey",
_CPCibWindowTemplateWTFlagsKey = @"_CPCibWindowTemplateWTFlagsKey",
_CPCibWindowTemplateWindowClassKey = @"_CPCibWindowTemplateWindowClassKey",
_CPCibWindowTemplateWindowRectKey = @"_CPCibWindowTemplateWindowRectKey",
_CPCibWindowTemplateScreenRectKey = @"_CPCibWindowTemplateScreenRectKey",
_CPCibWindowTemplateWindowStyleMaskKey = @"_CPCibWindowTempatStyleMaskKey",
_CPCibWindowTemplateWindowTitleKey = @"_CPCibWindowTemplateWindowTitleKey",
_CPCibWindowTemplateWindowViewKey = @"_CPCibWindowTemplateWindowViewKey",
_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop = @"_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop",
_CPCibWindowTemplateWindowIsFullPlatformWindowKey = @"_CPCibWindowTemplateWindowIsFullPlatformWindowKey";
@implementation _CPCibWindowTemplate (Coding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super init];
if (self)
{
if ([aCoder containsValueForKey:_CPCibWindowTemplateMinSizeKey])
_minSize = [aCoder decodeSizeForKey:_CPCibWindowTemplateMinSizeKey];
if ([aCoder containsValueForKey:_CPCibWindowTemplateMaxSizeKey])
_maxSize = [aCoder decodeSizeForKey:_CPCibWindowTemplateMaxSizeKey];
_viewClass = [aCoder decodeObjectForKey:_CPCibWindowTemplateViewClassKey];
_windowClass = [aCoder decodeObjectForKey:_CPCibWindowTemplateWindowClassKey];
_wtFlags = [aCoder decodeIntForKey:_CPCibWindowTemplateWTFlagsKey];
_windowRect = [aCoder decodeRectForKey:_CPCibWindowTemplateWindowRectKey];
_screenRect = [aCoder decodeRectForKey:_CPCibWindowTemplateScreenRectKey];
_windowStyleMask = [aCoder decodeIntForKey:_CPCibWindowTemplateWindowStyleMaskKey];
_windowTitle = [aCoder decodeObjectForKey:_CPCibWindowTemplateWindowTitleKey];
_windowView = [aCoder decodeObjectForKey:_CPCibWindowTemplateWindowViewKey];
_windowAutorecalculatesKeyViewLoop = [aCoder decodeBoolForKey:_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop];
_windowIsFullPlatformWindow = [aCoder decodeBoolForKey:_CPCibWindowTemplateWindowIsFullPlatformWindowKey];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
if (_minSize)
[aCoder encodeSize:_minSize forKey:_CPCibWindowTemplateMinSizeKey];
if (_maxSize)
[aCoder encodeSize:_maxSize forKey:_CPCibWindowTemplateMaxSizeKey];
[aCoder encodeObject:_viewClass forKey:_CPCibWindowTemplateViewClassKey];
[aCoder encodeObject:_windowClass forKey:_CPCibWindowTemplateWindowClassKey];
[aCoder encodeInt:_wtFlags forKey:_CPCibWindowTemplateWTFlagsKey];
[aCoder encodeRect:_windowRect forKey:_CPCibWindowTemplateWindowRectKey];
[aCoder encodeRect:_screenRect forKey:_CPCibWindowTemplateScreenRectKey];
[aCoder encodeInt:_windowStyleMask forKey:_CPCibWindowTemplateWindowStyleMaskKey];
[aCoder encodeObject:_windowTitle forKey:_CPCibWindowTemplateWindowTitleKey];
[aCoder encodeObject:_windowView forKey:_CPCibWindowTemplateWindowViewKey];
if (_windowAutorecalculatesKeyViewLoop)
[aCoder encodeObject:_windowAutorecalculatesKeyViewLoop forKey:_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop];
if (_windowIsFullPlatformWindow)
[aCoder encodeObject:_windowIsFullPlatformWindow forKey:_CPCibWindowTemplateWindowIsFullPlatformWindowKey];
}
@end
+10
View File
@@ -321,6 +321,16 @@ function CGContextClosePath(aContext)
CGPathCloseSubpath(aContext.path);
}
/*!
Return YES if the current path in the given context is empty.
@param aContext the CGContext to examine
@return BOOL
*/
function CGContextIsPathEmpty(aContext)
{
return (!aContext.path || CGPathIsEmpty(aContext.path));
}
/*!
Moves the current location of aContext to the given x and y coordinates
@param aContext the CGContext to move
+1 -1
View File
@@ -129,7 +129,7 @@ function CGContextAddPath(aContext, aPath)
break;
case kCGPathElementAddArc: _CGContextAddArcCanvas(aContext, element.x, element.y, element.radius, element.startAngle, element.endAngle, element.clockwise);
break;
case kCGPathElementAddArcTo: //_CGContextAddArcToPointCanvas(aContext, element.cp1x, element.cp1.y, element.cp2.x, element.cp2y, element.radius);
case kCGPathElementAddArcToPoint: _CGContextAddArcToPointCanvas(aContext, element.p1x, element.p1y, element.p2x, element.p2y, element.radius);
break;
}
}
+2 -2
View File
@@ -215,7 +215,7 @@ function CGContextDrawPath(aContext, aMode)
COORD(start.x), ',', COORD(start.y), " ",
COORD(end.x), ',', COORD(end.y));
break;
case kCGPathElementAddArcTo: break;
case kCGPathElementAddArcToPoint: break;
}
// TODO: Following is broken for curves due to
@@ -332,4 +332,4 @@ function CGContextDrawLinearGradient(aContext, aGradient, aStartPoint, anEndPoin
// aContext.buffer += vml.join("");
// else
// aContext.DOMElement.innerHTML = vml.join("");
}
}
+119
View File
@@ -118,6 +118,17 @@ function CGPathAddArc(aPath, aTransform, x, y, aRadius, aStartAngle, anEndAngle,
function CGPathAddArcToPoint(aPath, aTransform, x1, y1, x2, y2, aRadius)
{
var p1 = _CGPointMake(x1, y1),
p2 = _CGPointMake(x2, y2);
if (aTransform)
{
p1 = _CGPointApplyAffineTransform(p1, aTransform);
p2 = _CGPointApplyAffineTransform(p2, aTransform);
}
aPath.current = p2;
aPath.elements[aPath.count++] = { type:kCGPathElementAddArcToPoint, p1x:p1.x, p1y:p1.y, p2x:p2.x, p2y:p2.y, radius:aRadius };
}
function CGPathAddCurveToPoint(aPath, aTransform, cp1x, cp1y, cp2x, cp2y, x, y)
@@ -186,6 +197,12 @@ function CGPathAddPath(aPath, aTransform, anotherPath)
element.endAngle, element.isClockwise);
break;
case kCGPathElementAddArcToPoint: CGPathAddArcToPoint(aPath, aTransform,
element.p1x, element.p1y,
element.p2x, element.p2y,
element.radius);
break;
case kCGPathElementAddQuadCurveToPoint: CGPathAddQuadCurveToPoint(aPath, aTransform,
element.cpx, element.cpy,
element.x, element.y);
@@ -389,6 +406,108 @@ function CGPathIsEmpty(aPath)
return !aPath || aPath.count == 0;
}
/*!
Calculate the smallest rectangle to contain both the path of the receiver and all control points.
*/
function CGPathGetBoundingBox(aPath)
{
if (!aPath || !aPath.count)
return _CGRectMakeZero();
var ox = 0,
oy = 0,
rx = 0,
ry = 0,
movePoint = nil;
function addPoint(x, y)
{
ox = MIN(ox, x);
oy = MIN(oy, y);
rx = MAX(rx, x);
ry = MAX(ry, y);
}
for (var i = 0, count = aPath.count; i < count; ++i)
{
var element = aPath.elements[i];
// Just enclose all the control points. The curves must be inside of the control points.
// This won't work for CGPathGetPathBoundingBox.
switch (element.type)
{
case kCGPathElementAddLineToPoint:
if (movePoint)
{
addPoint(movePoint.x, movePoint.y);
movePoint = nil;
}
addPoint(element.x, element.y);
break;
case kCGPathElementAddCurveToPoint:
if (movePoint)
{
addPoint(movePoint.x, movePoint.y);
movePoint = nil;
}
addPoint(element.cp1x, element.cp1y);
addPoint(element.cp2x, element.cp2y);
addPoint(element.x, element.y);
break;
case kCGPathElementAddArc:
if (movePoint)
{
addPoint(movePoint.x, movePoint.y);
movePoint = nil;
}
addPoint(element.x, element.y);
break;
case kCGPathElementAddArcToPoint:
if (movePoint)
{
addPoint(movePoint.x, movePoint.y);
movePoint = nil;
}
addPoint(element.p1x, element.p1y);
addPoint(element.p2x, element.p2y);
break;
case kCGPathElementAddQuadCurveToPoint:
if (movePoint)
{
addPoint(movePoint.x, movePoint.y);
movePoint = nil;
}
addPoint(element.cpx, element.cpy);
addPoint(element.x, element.y);
break;
case kCGPathElementMoveToPoint:
movePoint = _CGPointMake(element.x, element.y);
break;
case kCGPathElementCloseSubpath:
if (movePoint)
{
addPoint(movePoint.x, movePoint.y);
movePoint = nil;
}
break;
}
}
return _CGRectMake(ox, oy, rx - ox, ry - oy);
}
/*!
@}
*/
+5 -3
View File
@@ -113,14 +113,12 @@
@import "CPEvent.j"
@import "CPText.j"
@import "CPCompatibility.j"
@import "CPDOMWindowLayer.j"
@import "CPPlatform.j"
@import "CPPlatformWindow.j"
@import "CPPlatformWindow+DOMKeys.j"
// List of all open native windows
var PlatformWindows = [CPSet set];
@@ -1242,6 +1240,10 @@ var resizeTimer = nil;
else if (type === "mousedown")
{
// If we receive a click event, then we invalidate any scheduled
// or visible tooltips
[_CPToolTip invalidateCurrentToolTipIfNeeded];
var button = aDOMEvent.button;
_mouseDownIsRightClick = button == 2 || (CPBrowserIsOperatingSystem(CPMacOperatingSystem) && button == 0 && modifierFlags & CPControlKeyMask);
@@ -1601,7 +1603,7 @@ var _CPEventFromNativeMouseEvent = function(aNativeEvent, anEventType, aPoint, m
};
var CLICK_SPACE_DELTA = 5.0,
CLICK_TIME_DELTA = (typeof document != "undefined" && document.addEventListener) ? 350.0 : 1000.0;
CLICK_TIME_DELTA = (typeof document != "undefined" && document.addEventListener) ? 0.55 : 1.0;
var CPDOMEventGetClickCount = function(aComparisonEvent, aTimestamp, aLocation)
{
Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 B

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 B

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 B

After

Width:  |  Height:  |  Size: 169 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 B

After

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 B

After

Width:  |  Height:  |  Size: 169 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 B

After

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 183 B

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 B

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 B

After

Width:  |  Height:  |  Size: 169 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 B

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 B

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 B

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 190 B

After

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 B

After

Width:  |  Height:  |  Size: 181 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 B

After

Width:  |  Height:  |  Size: 184 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 190 B

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 B

After

Width:  |  Height:  |  Size: 180 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 B

After

Width:  |  Height:  |  Size: 180 B

+1
View File
@@ -1678,6 +1678,7 @@ var themedButtonValues = nil,
[@"text-shadow-color", [CPColor whiteColor]],
[@"text-shadow-offset", CGSizeMake(0.0, 1.0)],
[@"text-alignment", CPLeftTextAlignment],
[@"line-break-mode", CPLineBreakByTruncatingTail],
[@"background-color", pressed, CPThemeStateHighlighted],
[@"background-color", highlighted, CPThemeStateSelected],
+44 -1
View File
@@ -27,7 +27,10 @@
_CPToolTipWindowMask = 1 << 27;
var _CPToolTipHeight = 24.0,
_CPToolTipFontSize = 11.0;
_CPToolTipFontSize = 11.0,
_CPToolTipDelay = 1.0,
_CPToolTipCurrentToolTip,
_CPToolTipCurrentToolTipTimer;
/*! @ingroup appkit
This is a basic tooltip that behaves mostly like Cocoa ones.
@@ -41,6 +44,46 @@ var _CPToolTipHeight = 24.0,
#pragma mark -
#pragma mark Class Methods
/*! @ignore
Invalidate any scheduled tooltips, or hide any visible one
*/
+ (void)invalidateCurrentToolTipIfNeeded
{
if (_CPToolTipCurrentToolTipTimer)
{
[_CPToolTipCurrentToolTipTimer invalidate];
_CPToolTipCurrentToolTipTimer = nil;
}
if (_CPToolTipCurrentToolTip)
{
[_CPToolTipCurrentToolTip close];
_CPToolTipCurrentToolTip = nil;
}
}
/*! @ignore
Schedule a tooltip for the given view
@param aView the view that might display the tooltip
*/
+ (void)scheduleToolTipForView:(CPView)aView
{
if (![aView toolTip] || ![[aView toolTip] length])
return;
[_CPToolTip invalidateCurrentToolTipIfNeeded];
var callbackFunction = function() {
[_CPToolTip invalidateCurrentToolTipIfNeeded];
_CPToolTipCurrentToolTip = [_CPToolTip toolTipWithString:[aView toolTip]];
};
_CPToolTipCurrentToolTipTimer = [CPTimer scheduledTimerWithTimeInterval:_CPToolTipDelay
callback:callbackFunction
repeats:NO];
}
/*! Returns an initialized _CPToolTip with the given text and attach it to given view.
@param aString the content of the tooltip
*/
+480
View File
@@ -0,0 +1,480 @@
Contributing
------------
As an open source project, your contributions are important to the future of Cappuccino. Whether you're looking to write code, add new documentation, or just report a bug, you'll be helping everyone who uses Cappuccino in the future.
## Reporting Bugs
We use [GitHub to track issues](https://github.com/cappuccino/cappuccino/issues). You might be interested in our [issue life cycle](http://www.cappuccino-project.org/community/contribute/the-issue-lifecycle/) which explains the process of how an issue is taken from new to resolved.
## Patches
To contribute a patch or a fix, fork Cappuccino and then clone your fork and make the changes to a branch of your fork:
git clone https://github.com/<your username>/cappuccino.git
git checkout -b descriptive-branch-name master
# Check that the unit tests work.
jake test
# Make changes. Make sure you follow the coding style guidelines and write unit tests.
# Check that everything is still working, then commit.
jake test
git commit
git push origin descriptive-branch-name
Now you can go to GitHub and [make a pull request](https://help.github.com/articles/using-pull-requests).
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.
## Cappuccino Coding Style Guidelines
### Trailing whitespace
Leave no trailing spaces or tabs at the end of a line (`trailing whitespace`), even if the line is empty and in an otherwise indented block.
### Indentation
Use spaces, not tabs. Tabs should only appear in files that require them for semantic meaning, like Makefiles (which there are currently none of). The indent size is 4 spaces.
##### Right:
function main()
{
return 0;
}
##### Wrong:
function main()
{
return 0;
}
---
A case label should be indented once from its switch statement. The case statement is indented out from the longest label.
##### Right:
switch (condition)
{
case fooCondition:
case barCondition: i++;
break;
default: i--;
}
##### Wrong:
switch (condition) {
case fooCondition:
case barCondition:
i++;
break;
default:
i--;
}
### Spacing
Do not place spaces around unary operators.
##### Right:
i++
##### Wrong:
i ++
---
Do place spaces around binary and ternary operators.
##### Right:
y = m * x + b;
f(a, b);
c = a | b;
return condition ? 1 : 0;
##### Wrong:
y=m*x+b;
f(a,b);
c = a|b;
return condition ? 1:0;
---
Place spaces between control statements and their parentheses.
##### Right:
if (condition)
doIt();
##### Wrong:
if(condition)
doIt();
---
Do not place spaces between a function and its parentheses, or between a parenthesis and its content.
##### Right:
f(a, b);
##### Wrong:
f (a, b);
f( a, b );
---
Do not place spaces between the return type of an Objective-J method and the selector name. DO place spaces between the method type and the method return type.
##### Right:
- (void)method;
##### Wrong:
- (void) method;
-(void)method;
---
Do not place spaces between Objective-J selectors and arguments.
##### Right:
[myNumber addNumber:5]
##### Wrong:
[myNumber addNumber: 5]
### Line breaking
Each statement should get its own line.
##### Right:
var x,
y;
x++;
y++;
if (condition)
doIt();
##### Wrong:
var x, y;
x++; y++;
if (condition) doIt();
### Braces
Every brace gets its own line, very simple to remember:
##### Right:
int main()
{
//...
}
if (condition)
{
//...
}
else if (condition)
{
//...
}
@implementation MyObject : CPObject
{
}
@end
##### Wrong:
int main() {
...
}
if (condition) {
...
} else if (condition) {
...
}
@implementation MyObject : CPObject {}
@end
### Null, false and 0
In JavaScript, the null object value should be written as null. In Objective-J, it should be written as `nil` when the variable refers to an object, and `Nil` when it refers to a `Class`. Objective-J `BOOL` values should be written as `YES` and `NO`.
Tests for `true/false`, `null/non-null`, and zero/non-zero should all be done without equality comparisons, except for cases when a value could be both 0 or `null` (or another "falsey" value). In this case, the comparison should be preceded by a comment explaining the distinction.
##### Right:
if (condition)
doIt();
if (!ptr)
return;
if (!count)
return;
// object is an ID number, so 0 is OK, but null is not.
if (object === null)
return;
##### Wrong:
if (condition == true)
doIt();
if (ptr == NULL)
return;
if (count == 0)
return;
if (object == null)
return;
---
In Objective-J, instance variables are initialized to `nil` automatically. Don't add explicit initializations to `nil` or `NO` in an init method.
### Names
Use CamelCase. Capitalize the first letter of a class. Lower-case the first letter of a variable or function name. Fully capitalize acronyms.
##### Right:
@implementation Data : //...
@implementation HTMLDocument : //...
##### Wrong:
@implementation data : //...
@implementation HtmlDocument : //...
---
Multiple var declarations should be collapsed with commas.
##### Right:
var index = 0,
count = 5;
##### Wrong:
var index = 0;
var count = 5;
---
Variable declarations should be created as needed, rather than up front ("hoisted").
##### Right:
- (BOOL)doSomething:(id)aFoo
{
var importantVariable = [aFoo message];
if (!importantVariable)
return;
var index = [aFoo count];
while (index--)
{
var innerVariable = [aFoo objectAtIndex:index];
//do something;
}
}
##### Wrong:
- (BOOL)doSomething:(id)aFoo
{
var importantVariable = [aFoo message],
index = [aFoo count],
innerVariable;
if (!importantVariable)
return;
while (index--)
{
innerVariable = [aFoo objectAtIndex:index];
//do something;
}
}
---
Use full words, except in the rare case where an abbreviation would be more canonical and easier to understand.
##### Right:
var characterSize,
length,
tabIndex; // more canonical
##### Wrong:
var charSize,
len,
tabulationIndex; // bizarre
---
Prefix Objective-J instance variables with `_`, but only when writing code for the Cappuccino frameworks. User level (application) code should not prefix variables with `_`. This prevents conflicts between the two scopes.
##### Right:
@implementation CPString
{
unsigned _length;
}
@end
##### Wrong:
@implementation CPString
{
unsigned length;
}
@end
---
Precede boolean values with words like "is" and "did".
##### Right:
var isValid;
var didSendData;
- (BOOL)isEditable;
- (BOOL)didReceiveResponse;
##### Wrong:
var valid;
var sentData;
- (BOOL)editable;
- (BOOL)receivedResponse;
---
Precede setters with the word "set". Use bare words for getters. Setter and getter names should match the names of the variables being set/gotten.
##### Right:
- (void)setCount:(unsigned)aCount; // sets _count
- (unsigned)count; // returns _count
##### Wrong:
- (unsigned)getCount;
---
Use descriptive verbs in function names, and place desired types in comments.
##### Right:
function convertToASCII(/*String*/ aString)
##### Wrong:
function toASCII(str)
---
Use descriptive parameter names that are not abbreviated.
##### Right:
- (void)convertString:(CPString)aString toFormat:(Format)aFormat;
- (void)appendSubviews:(CPArray)subviews inOrder:(BOOL)shouldBeInOrder;
##### Wrong:
- (void)convertString:(CPString)str toFormat:(Format)f;
- (void)appendSubviews:(CPArray)s inOrder:(BOOL)flag;
---
Use descriptive parameter types, despite not being fully supported in JavaScript. At some point we will be adding optional static typing, and even until then this serves as a much better indicator of what the method expects. Of course, if the method can truly take any input or return any output, it is perfectly acceptable to use `id`, `CPObject`, or `var`.
##### Right:
- (char)characterAtIndex:(unsigned)anIndex;
- (void)insertObject:(id)anObject;
##### Wrong:
- (String)characterAtIndex:(var)index;
---
Objective-J method names should follow the Cocoa naming guidelines — they should read like a phrase and each piece of the selector should start with a lowercase letter and use intercaps.
Enum members should user InterCaps with an initial capital letter.
`#defined` constants should use all uppercase names with words separated by underscores.
Macros that expand to function calls or other non-constant computation: these should be named like functions, and should have parentheses at the end, even if they take no arguments (with the exception of some special macros like ASSERT).
##### Right:
#define StopButtonTitle() \
CPLocalizedString(@"Stop", @"Stop button title")
##### Wrong:
#define STOP_BUTTON_TITLE \
CPLocalizedString(@"Stop", @"Stop button title")
#define StopButtontitle \
CPLocalizedString(@"Stop", @"Stop button title")
### import Statements
1. Include external frameworks first.
2. Include Foundation classes before AppKit classes.
3. Include files in alphabetical order.
4. Use local imports whenever possible.
##### Right:
// (Within AppKit)
import <Foundation/CPObject.j>
import <Foundation/CPArray.j>
import "CPTabViewItem.j"
import "CPTabView.j"
##### Wrong:
// (Within AppKit)
import "CPTabView.j"
import <AppKit/CPTabViewItem.j>
import <Foundation/CPArray.j>
import <Foundation/CPObject.j>
-2
View File
@@ -176,8 +176,6 @@ var _CPKeyedArchiverStringClass = Nil,
_replacementObjects = [CPDictionary dictionary];
_data = data;
_plistObject = [CPDictionary dictionary];
_plistObjects = [CPArray arrayWithObject:_CPKeyedArchiverNullString];
}
+11
View File
@@ -90,6 +90,11 @@ CPNumberFormatterRoundHalfUp = CPRoundPlain;
- (CPString)stringFromNumber:(CPNumber)number
{
if (_numberStyle == CPNumberFormatterPercentStyle)
{
number *= 100.0;
}
var dcmn = [number isKindOfClass:CPDecimalNumber] ? number : [[CPDecimalNumber alloc] _initWithJSNumber:number];
// TODO Add locale support.
@@ -97,6 +102,7 @@ CPNumberFormatterRoundHalfUp = CPRoundPlain;
{
case CPNumberFormatterCurrencyStyle:
case CPNumberFormatterDecimalStyle:
case CPNumberFormatterPercentStyle:
UPDATE_NUMBER_HANDLER_IF_NECESSARY();
dcmn = [dcmn decimalNumberByRoundingAccordingToBehavior:_numberHandler];
@@ -134,6 +140,11 @@ CPNumberFormatterRoundHalfUp = CPRoundPlain;
string = _currencyCode + string;
}
if (_numberStyle == CPNumberFormatterPercentStyle)
{
string += "%";
}
return string;
default:
return [number description];
+58
View File
@@ -161,6 +161,17 @@
[self assert:2 equals:[[outlineView selectedRowIndexes] count] message:"selections should remain"];
}
- (void)testExpandCollapseItemVisibility
{
var delegate = [TestExpandCollapseVisibilityDelegate new];
[delegate setTester:self];
[outlineView setDelegate:delegate];
[outlineView collapseItem:".1"];
[outlineView expandItem:".1"];
}
/*!
Test that the outline view archives properly.
*/
@@ -270,3 +281,50 @@
}
@end
@implementation TestExpandCollapseVisibilityDelegate : CPObject
{
id tester @accessors;
}
- (void)outlineViewItemWillCollapse:(CPNotification)aNotification
{
var anOutlineView = [aNotification object],
visibleRows = [anOutlineView rowsInRect:[anOutlineView visibleRect]];
[tester assertTrue:[anOutlineView isItemExpanded:".1"]];
[tester assert:0 equals:visibleRows.location];
[tester assert:8 equals:visibleRows.length];
}
- (void)outlineViewItemDidCollapse:(CPNotification)aNotification
{
var anOutlineView = [aNotification object],
visibleRows = [anOutlineView rowsInRect:[anOutlineView visibleRect]];
[tester assertFalse:[anOutlineView isItemExpanded:".1"]];
[tester assert:0 equals:visibleRows.location];
[tester assert:4 equals:visibleRows.length];
}
- (void)outlineViewItemWillExpand:(CPNotification)aNotification
{
var anOutlineView = [aNotification object],
visibleRows = [anOutlineView rowsInRect:[anOutlineView visibleRect]];
[tester assertFalse:[anOutlineView isItemExpanded:".1"]];
[tester assert:0 equals:visibleRows.location];
[tester assert:4 equals:visibleRows.length];
}
- (void)outlineViewItemDidExpand:(CPNotification)aNotification
{
var anOutlineView = [aNotification object],
visibleRows = [anOutlineView rowsInRect:[anOutlineView visibleRect]];
[tester assertTrue:[anOutlineView isItemExpanded:".1"]];
[tester assert:0 equals:visibleRows.location];
[tester assert:8 equals:visibleRows.length];
}
@end
+35
View File
@@ -267,6 +267,41 @@
[contentBindingTable reloadData];
}
- (void)testInitiallyHiddenColumns
{
var table = [[CPTableView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)],
tableColumn1 = [[CPTableColumn alloc] initWithIdentifier:@"A"],
tableColumn2 = [[CPTableColumn alloc] initWithIdentifier:@"B"],
delegate = [ContentBindingTableDelegate new];
[delegate setTester:self];
[table setDelegate:delegate];
[delegate setTableEntries:[[@"A1", @"B1"], [@"A2", @"B2"], [@"A3", @"B3"]]];
[table bind:@"content" toObject:delegate withKeyPath:@"tableEntries" options:nil];
[[theWindow contentView] addSubview:table];
[tableColumn1 setHidden:YES];
[tableColumn1 setWidth:50.0];
[tableColumn2 setWidth:100.0];
[table addTableColumn:tableColumn1];
[table addTableColumn:tableColumn2];
[table reloadData];
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
[self assertTrue:[table bounds].size.width > 100 && [table bounds].size.width < 200];
[tableColumn1 setHidden:NO];
[tableColumn1 setWidth:100.0];
[self assertTrue:[table bounds].size.width >= 200];
}
@end
@implementation FirstResponderConfigurableTableView : CPTableView
+4 -5
View File
@@ -71,10 +71,10 @@
var rawString = "cappuccino",
bytes = [99, 97, 112, 112, 117, 99, 99, 105, 110, 111],
base64 = "Y2FwcHVjY2lubw==";
var data = [CPData dataWithBase64:base64];
[self assert:rawString equals:[data rawString]];
data = [CPData dataWithBase64:base64];
[self assert:bytes equals:[data bytes]];
@@ -84,17 +84,16 @@
data = [CPData dataWithRawString:rawString];
[self assert:rawString equals:[data rawString]];
data = [CPData dataWithRawString:rawString];
[self assert:bytes equals:[data bytes]];
data = [CPData dataWithRawString:rawString];
[self assert:base64 equals:[data base64]];
data = [CPData dataWithBytes:bytes];
[self assert:rawString equals:[data rawString]];
data = [CPData dataWithBytes:bytes];
[self assert:bytes equals:[data bytes]];
+17
View File
@@ -143,6 +143,23 @@
[self assert:@"SEK0.02" equals:[numberFormatter stringFromNumber:[CPDecimalNumber decimalNumberWithString:@"0.015"]]];
}
- (void)testPercentStyle
{
var numberFormatter = [CPNumberFormatter new];
[numberFormatter setNumberStyle:CPNumberFormatterPercentStyle];
[self assert:@"1%" equals:[numberFormatter stringFromNumber:[CPDecimalNumber decimalNumberWithString:@"0.01"]]];
[self assert:@"100%" equals:[numberFormatter stringFromNumber:[CPDecimalNumber decimalNumberWithString:@"1.0"]]];
[self assert:@"150%" equals:[numberFormatter stringFromNumber:[CPDecimalNumber decimalNumberWithString:@"1.5"]]];
[numberFormatter setMinimumFractionDigits:1];
[numberFormatter setMaximumFractionDigits:1];
[self assert:@"1.0%" equals:[numberFormatter stringFromNumber:[CPDecimalNumber decimalNumberWithString:@"0.01"]]];
[self assert:@"100.2%" equals:[numberFormatter stringFromNumber:[CPDecimalNumber decimalNumberWithString:@"1.002"]]];
[self assert:@"150.7%" equals:[numberFormatter stringFromNumber:[CPDecimalNumber decimalNumberWithString:@"1.507"]]];
}
- (void)testSetGeneratesDecimalNumbers_
{
var numberFormatter = [CPNumberFormatter new];
+11 -13
View File
@@ -26,11 +26,9 @@ CPLogRegister(CPLogConsole);
- (void)awakeFromCib
{
var contentView = [theWindow contentView];
var contentView = [theWindow contentView],
notWrongItem = [Item new];
//create our non ui objects
var notWrongItem = [Item new];
[notWrongItem setRightOrWrong:"also right"];
itemsArray = [[Item new], notWrongItem];
@@ -104,8 +102,7 @@ CPLogRegister(CPLogConsole);
{
// bind array controller to self's itemsArray
[arrayController bind:@"contentArray" toObject:self
withKeyPath:@"itemsArray" options:nil];
[arrayController bind:@"contentArray" toObject:self withKeyPath:@"itemsArray" options:nil];
// bind the total field -- no options on this one
[totalCountField bind:CPValueBinding toObject:arrayController
@@ -113,13 +110,14 @@ CPLogRegister(CPLogConsole);
var bindingOptions = [CPDictionary dictionary];
//[bindingOptions setObject:@"No Name" forKey:@"NSNullPlaceholder"];
[selectedNameField bind: @"value" toObject:arrayController
withKeyPath:@"selection.name" options:bindingOptions];
[selectedNameField bind:CPValueBinding toObject:arrayController
withKeyPath:@"selection.name" options:bindingOptions];
// binding for "name" column
var tableColumn = [tableView tableColumnWithIdentifier:@"name"],
bindingOptions = [CPDictionary dictionary];
[tableColumn bind:@"value" toObject: arrayController
bindingOptions = [CPDictionary dictionary];
[tableColumn bind:CPValueBinding toObject:arrayController
withKeyPath:@"arrangedObjects.name" options:bindingOptions];
@@ -129,13 +127,13 @@ CPLogRegister(CPLogConsole);
//[bindingOptions removeObjectForKey:@"NSNullPlaceholder"];
//[bindingOptions setObject:YES
// forKey:CPValidatesImmediatelyBindingOption];
[selectedPriceField bind:@"value" toObject: arrayController
[selectedPriceField bind:CPValueBinding toObject: arrayController
withKeyPath:@"selection.price" options:bindingOptions];
// binding for "price" column
tableColumn = [tableView tableColumnWithIdentifier:@"price"];
bindingOptions = [CPDictionary dictionary];
[tableColumn bind:@"value" toObject: arrayController
[tableColumn bind:CPValueBinding toObject:arrayController
withKeyPath:@"arrangedObjects.price" options:bindingOptions];
tableColumn = [tableView tableColumnWithIdentifier:@"all right"];
@@ -215,4 +213,4 @@ CPLogRegister(CPLogConsole);
return aValue == "wrong" ? "right" : aValue;
}
@end
@end
@@ -69,11 +69,6 @@ CPLogRegister(CPLogConsole);
[[radio1 radioGroup] setAction:@selector(radioGroupClicked:)];
[multiCheckbox setState:CPMixedState];
[pushInButton setButtonType:CPMomentaryLightButton];
[pushOnOffButton setButtonType:CPPushOnPushOffButton];
[toggleButton setButtonType:CPToggleButton];
[momentaryChangeButton setButtonType:CPMomentaryChangeButton];
[pushInButton setAlternateTitle:@"Should Not See Me"];
[toggleButton setAlternateTitle:@"Alternate Title For Toggle"];
[momentaryChangeButton setAlternateTitle:@"Changed!"];
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
@@ -34,7 +34,7 @@
var data = [[CPData alloc] initWithRawString:dataString],
theRows = [CPPropertyListSerialization propertyListFromData:data format:CPPropertyListXMLFormat_v1_0];
// Add a CPImage to the model to test CPValueBinding.
// Add a CPImage to the model to test CPValueBinding.
var path = [[CPBundle mainBundle] pathForResource:@"value.jpg"],
image = [[CPImage alloc] initWithContentsOfFile:path],
dict = [CPDictionary dictionaryWithObject:image forKey:@"image"];
File diff suppressed because one or more lines are too long
@@ -2,39 +2,36 @@
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
<data>
<int key="IBDocument.SystemTarget">1050</int>
<string key="IBDocument.SystemVersion">10J3210</string>
<string key="IBDocument.InterfaceBuilderVersion">1306</string>
<string key="IBDocument.AppKitVersion">1038.35</string>
<string key="IBDocument.HIToolboxVersion">461.00</string>
<string key="IBDocument.SystemVersion">12C60</string>
<string key="IBDocument.InterfaceBuilderVersion">2843</string>
<string key="IBDocument.AppKitVersion">1187.34</string>
<string key="IBDocument.HIToolboxVersion">625.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="NS.object.0">1306</string>
<string key="NS.object.0">2843</string>
</object>
<object class="NSArray" key="IBDocument.IntegratedClassDependencies">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>NSScroller</string>
<string>NSTableHeaderView</string>
<string>NSScrollView</string>
<string>NSTextFieldCell</string>
<string>NSButtonCell</string>
<string>NSImageCell</string>
<string>NSTableView</string>
<string>NSCustomObject</string>
<string>NSImageCell</string>
<string>NSLevelIndicatorCell</string>
<string>NSScrollView</string>
<string>NSScroller</string>
<string>NSTableColumn</string>
<string>NSTableHeaderView</string>
<string>NSTableView</string>
<string>NSTextFieldCell</string>
<string>NSView</string>
<string>NSWindowTemplate</string>
<string>NSLevelIndicatorCell</string>
<string>NSTableColumn</string>
</object>
<object class="NSArray" key="IBDocument.PluginDependencies">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
</object>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys" id="0">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<reference key="dict.values" ref="0"/>
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
<integer value="1" key="NS.object.0"/>
</object>
<object class="NSMutableArray" key="IBDocument.RootObjects" id="1048">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -55,6 +52,7 @@
<string key="NSWindowTitle">Window</string>
<string key="NSWindowClass">NSWindow</string>
<nil key="NSViewClass"/>
<nil key="NSUserInterfaceItemIdentifier"/>
<object class="NSView" key="NSWindowView" id="439893737">
<reference key="NSNextResponder"/>
<int key="NSvFlags">256</int>
@@ -78,21 +76,21 @@
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="347610108"/>
<bool key="NSEnabled">YES</bool>
<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
<bool key="NSControlAllowsExpansionToolTips">YES</bool>
<object class="NSTableHeaderView" key="NSHeaderView" id="393525317">
<reference key="NSNextResponder" ref="471528550"/>
<int key="NSvFlags">256</int>
<string key="NSFrameSize">{644, 17}</string>
<reference key="NSSuperview" ref="471528550"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="167646100"/>
<reference key="NSNextKeyView" ref="331394667"/>
<reference key="NSTableView" ref="86489736"/>
</object>
<object class="_NSCornerView" key="NSCornerView" id="167646100">
<reference key="NSNextResponder" ref="1048514227"/>
<object class="_NSCornerView" key="NSCornerView">
<nil key="NSNextResponder"/>
<int key="NSvFlags">-2147483392</int>
<string key="NSFrame">{{502, 0}, {16, 17}}</string>
<reference key="NSSuperview" ref="1048514227"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="331394667"/>
</object>
<object class="NSMutableArray" key="NSTableColumns">
@@ -103,13 +101,13 @@
<double key="NSMinWidth">10</double>
<double key="NSMaxWidth">3.0282346638528862e+53</double>
<object class="NSTableHeaderCell" key="NSHeaderCell">
<int key="NSCellFlags">75628096</int>
<int key="NSCellFlags2">2048</int>
<string key="NSContents">ImageView</string>
<object class="NSFont" key="NSSupport" id="26">
<string key="NSName">LucidaGrande</string>
<int key="NSCellFlags">75497536</int>
<int key="NSCellFlags2">134219776</int>
<string key="NSContents">Image</string>
<object class="NSFont" key="NSSupport">
<string key="NSName">Georgia</string>
<double key="NSSize">11</double>
<int key="NSfFlags">3100</int>
<int key="NSfFlags">16</int>
</object>
<object class="NSColor" key="NSBackgroundColor" id="676350359">
<int key="NSColorSpace">6</int>
@@ -131,13 +129,8 @@
</object>
</object>
<object class="NSImageCell" key="NSDataCell" id="1016771331">
<int key="NSCellFlags">67239424</int>
<int key="NSCellFlags">134217728</int>
<int key="NSCellFlags2">33554432</int>
<object class="NSFont" key="NSSupport" id="390959245">
<string key="NSName">LucidaGrande</string>
<double key="NSSize">13</double>
<int key="NSfFlags">1044</int>
</object>
<int key="NSAlign">0</int>
<int key="NSScale">0</int>
<int key="NSStyle">0</int>
@@ -154,10 +147,14 @@
<double key="NSMinWidth">40</double>
<double key="NSMaxWidth">1000</double>
<object class="NSTableHeaderCell" key="NSHeaderCell">
<int key="NSCellFlags">75628096</int>
<int key="NSCellFlags">75497536</int>
<int key="NSCellFlags2">2048</int>
<string key="NSContents">Column 1</string>
<reference key="NSSupport" ref="26"/>
<object class="NSFont" key="NSSupport" id="26">
<string key="NSName">LucidaGrande</string>
<double key="NSSize">11</double>
<int key="NSfFlags">3100</int>
</object>
<object class="NSColor" key="NSBackgroundColor" id="1073356944">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MC4zMzMzMzI5ODU2AA</bytes>
@@ -165,10 +162,14 @@
<reference key="NSTextColor" ref="678139720"/>
</object>
<object class="NSTextFieldCell" key="NSDataCell" id="279840144">
<int key="NSCellFlags">337772096</int>
<int key="NSCellFlags">337641536</int>
<int key="NSCellFlags2">2048</int>
<string key="NSContents">Text Cell</string>
<reference key="NSSupport" ref="390959245"/>
<object class="NSFont" key="NSSupport" id="390959245">
<string key="NSName">LucidaGrande</string>
<double key="NSSize">13</double>
<int key="NSfFlags">1044</int>
</object>
<reference key="NSControlView" ref="86489736"/>
<object class="NSColor" key="NSBackgroundColor" id="979654510">
<int key="NSColorSpace">6</int>
@@ -195,19 +196,23 @@
<double key="NSMinWidth">40</double>
<double key="NSMaxWidth">1000</double>
<object class="NSTableHeaderCell" key="NSHeaderCell">
<int key="NSCellFlags">75628096</int>
<int key="NSCellFlags2">2048</int>
<int key="NSCellFlags">75497536</int>
<int key="NSCellFlags2">67110912</int>
<string key="NSContents">Two</string>
<reference key="NSSupport" ref="26"/>
<object class="NSFont" key="NSSupport">
<string key="NSName">LucidaGrande-Bold</string>
<double key="NSSize">20</double>
<int key="NSfFlags">16</int>
</object>
<reference key="NSBackgroundColor" ref="1073356944"/>
<reference key="NSTextColor" ref="678139720"/>
</object>
<object class="NSTextFieldCell" key="NSDataCell" id="642682655">
<int key="NSCellFlags">337772096</int>
<int key="NSCellFlags2">2048</int>
<int key="NSCellFlags">337641536</int>
<int key="NSCellFlags2">67110912</int>
<string key="NSContents">Text Cell</string>
<object class="NSFont" key="NSSupport">
<string key="NSName">LucidaGrande</string>
<string key="NSName">TimesNewRomanPSMT</string>
<double key="NSSize">20</double>
<int key="NSfFlags">16</int>
</object>
@@ -226,24 +231,24 @@
<reference key="NSTableView" ref="86489736"/>
</object>
<object class="NSTableColumn" id="467346610">
<double key="NSWidth">81</double>
<double key="NSWidth">94.078125</double>
<double key="NSMinWidth">10</double>
<double key="NSMaxWidth">3.4028234663852885e+54</double>
<object class="NSTableHeaderCell" key="NSHeaderCell">
<int key="NSCellFlags">75628096</int>
<int key="NSCellFlags">75497536</int>
<int key="NSCellFlags2">2048</int>
<string key="NSContents">Checkbox</string>
<string key="NSContents">Checkbox really long</string>
<reference key="NSSupport" ref="26"/>
<reference key="NSBackgroundColor" ref="676350359"/>
<reference key="NSTextColor" ref="678139720"/>
</object>
<object class="NSButtonCell" key="NSDataCell" id="271362548">
<int key="NSCellFlags">67239424</int>
<int key="NSCellFlags">67108864</int>
<int key="NSCellFlags2">134217728</int>
<string key="NSContents">Check</string>
<reference key="NSSupport" ref="390959245"/>
<reference key="NSControlView" ref="86489736"/>
<int key="NSButtonFlags">1211912703</int>
<int key="NSButtonFlags">1211912448</int>
<int key="NSButtonFlags2">2</int>
<object class="NSCustomResource" key="NSNormalImage">
<string key="NSClassName">NSImage</string>
@@ -263,11 +268,11 @@
<reference key="NSTableView" ref="86489736"/>
</object>
<object class="NSTableColumn" id="991776537">
<double key="NSWidth">105</double>
<double key="NSWidth">92</double>
<double key="NSMinWidth">10</double>
<double key="NSMaxWidth">3.4028234663852885e+54</double>
<object class="NSTableHeaderCell" key="NSHeaderCell">
<int key="NSCellFlags">75628096</int>
<int key="NSCellFlags">75497536</int>
<int key="NSCellFlags2">2048</int>
<string key="NSContents">Level Indicator</string>
<reference key="NSSupport" ref="26"/>
@@ -275,7 +280,7 @@
<reference key="NSTextColor" ref="678139720"/>
</object>
<object class="NSLevelIndicatorCell" key="NSDataCell" id="801202458">
<int key="NSCellFlags">-2080244224</int>
<int key="NSCellFlags">-2080374784</int>
<int key="NSCellFlags2">0</int>
<reference key="NSSupport" ref="390959245"/>
<reference key="NSControlView" ref="86489736"/>
@@ -313,6 +318,7 @@
<int key="NSDraggingSourceMaskForNonLocal">0</int>
<bool key="NSAllowsTypeSelect">YES</bool>
<int key="NSTableViewDraggingDestinationStyle">0</int>
<int key="NSTableViewGroupRowStyle">1</int>
</object>
</object>
<string key="NSFrame">{{1, 17}, {644, 290}}</string>
@@ -330,6 +336,7 @@
<reference key="NSSuperview" ref="1048514227"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="480583225"/>
<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
<reference key="NSTarget" ref="1048514227"/>
<string key="NSAction">_doScroller:</string>
<double key="NSPercent">0.94827586206896552</double>
@@ -337,14 +344,15 @@
<object class="NSScroller" id="480583225">
<reference key="NSNextResponder" ref="1048514227"/>
<int key="NSvFlags">-2147483392</int>
<string key="NSFrame">{{1, 292}, {516, 15}}</string>
<string key="NSFrame">{{1, 291}, {644, 16}}</string>
<reference key="NSSuperview" ref="1048514227"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
<int key="NSsFlags">1</int>
<reference key="NSTarget" ref="1048514227"/>
<string key="NSAction">_doScroller:</string>
<double key="NSPercent">0.99382716049382713</double>
<double key="NSPercent">0.94152046783625731</double>
</object>
<object class="NSClipView" id="471528550">
<reference key="NSNextResponder" ref="1048514227"/>
@@ -361,28 +369,30 @@
<reference key="NSBGColor" ref="979654510"/>
<int key="NScvFlags">4</int>
</object>
<reference ref="167646100"/>
</object>
<string key="NSFrame">{{20, 20}, {646, 308}}</string>
<reference key="NSSuperview" ref="439893737"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="471528550"/>
<int key="NSsFlags">562</int>
<int key="NSsFlags">133682</int>
<reference key="NSVScroller" ref="347610108"/>
<reference key="NSHScroller" ref="480583225"/>
<reference key="NSContentView" ref="331394667"/>
<reference key="NSHeaderClipView" ref="471528550"/>
<reference key="NSCornerView" ref="167646100"/>
<bytes key="NSScrollAmts">QSAAAEEgAABCNAAAQjQAAA</bytes>
<double key="NSMinMagnification">0.25</double>
<double key="NSMaxMagnification">4</double>
<double key="NSMagnification">1</double>
</object>
</object>
<string key="NSFrame">{{7, 11}, {686, 348}}</string>
<string key="NSFrameSize">{686, 348}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="1048514227"/>
</object>
<string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string>
<string key="NSMaxSize">{1e+13, 1e+13}</string>
<string key="NSScreenRect">{{0, 0}, {1440, 878}}</string>
<string key="NSMaxSize">{10000000000000, 10000000000000}</string>
<bool key="NSWindowIsRestorable">YES</bool>
</object>
<object class="NSCustomObject" id="635946545">
<string key="NSClassName">AppController</string>
@@ -421,7 +431,9 @@
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBObjectRecord">
<int key="objectID">0</int>
<reference key="object" ref="0"/>
<object class="NSArray" key="object" id="0">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<reference key="children" ref="1048"/>
<nil key="parent"/>
</object>
@@ -582,13 +594,14 @@
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>-1.IBPluginDependency</string>
<string>-2.IBPluginDependency</string>
<string>-3.IBPluginDependency</string>
<string>371.IBEditorWindowLastContentRect</string>
<string>371.IBPluginDependency</string>
<string>371.IBWindowTemplateEditedContentRect</string>
<string>371.NSWindowTemplate.visibleAtLaunch</string>
<string>371.editorWindowContentRectSynchronizationRect</string>
<string>372.IBPluginDependency</string>
<string>450.IBPluginDependency</string>
<string>489.IBPluginDependency</string>
<string>490.IBPluginDependency</string>
<string>491.IBPluginDependency</string>
@@ -598,18 +611,25 @@
<string>495.IBPluginDependency</string>
<string>496.IBPluginDependency</string>
<string>497.IBPluginDependency</string>
<string>501.IBPluginDependency</string>
<string>503.IBPluginDependency</string>
<string>504.IBPluginDependency</string>
<string>506.IBPluginDependency</string>
<string>508.IBPluginDependency</string>
<string>510.IBPluginDependency</string>
</object>
<object class="NSMutableArray" key="dict.values">
<object class="NSArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{{370, 244}, {558, 348}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{{370, 244}, {558, 348}}</string>
<integer value="1"/>
<string>{{33, 99}, {480, 360}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+42 -7
View File
@@ -188,9 +188,24 @@ dl.el {
margin-left: -1cm;
}
.fragment {
font-family: Courier, monospace, fixed;
font-size: 105%;
.fragment .line {
font-family: Consolas, Courier, monospace, fixed;
white-space: pre-wrap; /* css-3 */
white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
font-size: 11px;
margin-bottom: 3px;
}
.fragment .lineno {
color: #d4d4d4;
margin-right: 10px;
}
.fragment .lineno a {
color: #d4d4d4;
}
pre.fragment {
@@ -443,7 +458,7 @@ table.memberdecls {
}
.memItemLeft, .memItemRight, .memTemplParams {
border-top: 1px solid #ccc;
border-top: 1px solid #f3f3f3;
}
.memItemLeft, .memTemplItemLeft {
@@ -813,7 +828,7 @@ table.fieldtable {
float:left;
padding-left:10px;
padding-right: 15px;
background-image:url('bc_s.png');
padding-top: 0px;
background-repeat:no-repeat;
background-position:right;
color:#374E7C;
@@ -1079,7 +1094,7 @@ dl.citelist dd {
/* ADDITIONS */
.tabs, .tabs2, .tabs3 {
background: -moz-linear-gradient(-90deg, #fff, #eee);
background: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#eee));
background: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#eee));
border-bottom: 1px solid #ccc;
width: 100%;
z-index: 101;
@@ -1150,7 +1165,7 @@ dl.citelist dd {
.tablist li.current a {
background: -moz-linear-gradient(-90deg, #eee, #fff);
background: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#fff));
background: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#fff));
color: #444;
text-shadow: 0px 1px 1px #f2f2f2;
}
@@ -1283,3 +1298,23 @@ dl.citelist dd {
#nav-tree-contents {
margin: 6px 0px 0px 0px;
}
.memSeparator {
display: none;
}
.inherit_header td {
padding-top: 30px;
padding-bottom: 10px;
font: 13px normal "Lucida Grande", Helvetica, Arial, Geneva, sans-serif;
font-size: 14px;
}
#nav-sync {
right: 5px;
}
#nav-sync img {
width: 16px;
}
}
+3 -1
View File
@@ -73,7 +73,9 @@ extern NSString * const XCCListeningStartNotification;
- (BOOL)isXIBFile:(NSString *)path;
- (BOOL)isXCCIgnoreFile:(NSString *)path;
- (BOOL)prepareXCodeSupportProject;
- (NSURL*)shadowURLForSourceURL:(NSURL*)aSourceURL;
- (NSURL*)shadowHeaderURLForSourceURL:(NSURL*)aSourceURL;
- (void)cleanUpShadowsRelatedToSourceURL:(NSURL*)aSourceURL;
- (NSURL*)shadowImplementationURLForSourceURL:(NSURL*)aSourceURL;
- (NSURL*)sourceURLForShadowName:(NSString *)aString;
- (void)handleFileModification:(NSString*)fullPath notify:(BOOL)shouldNotify;
- (void)handleFileRemoval:(NSString*)fullPath;
+292 -257
View File
@@ -19,6 +19,7 @@
#import "TNXCodeCapp.h"
#include "macros.h"
NSString * const XCCUnderscoreReplacement = @"DoNotPutThisStringInFileNameOrWorldWillDie";
NSString * const XCCDidPopulateProjectNotification = @"XCCDidPopulateProjectNotification";
NSString * const XCCConversionStartNotification = @"XCCConversionStartNotification";
NSString * const XCCConversionStopNotification = @"XCCConversionStopNotification";
@@ -39,8 +40,8 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
@synthesize supportFileLevelAPI;
@synthesize isUsingFileLevelAPI;
#pragma mark -
#pragma mark Initialization
#pragma mark - Initialization
/*!
Initialize the AppController
@@ -48,7 +49,7 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
- (id)init
{
self = [super init];
if (self)
{
errorList = [NSMutableArray arrayWithCapacity:10];
@@ -57,7 +58,7 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
parserPath = [[NSBundle mainBundle] pathForResource:@"parser" ofType:@"j"];
lastEventId = [[NSUserDefaults standardUserDefaults] objectForKey:@"lastEventId"];
appStartedTimestamp = [NSDate date];
[self setIsListening:NO];
[self setIsUsingFileLevelAPI:NO];
@@ -65,11 +66,11 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
SInt32 versionMinor = 0;
Gestalt(gestaltSystemVersionMajor, &versionMajor);
Gestalt(gestaltSystemVersionMinor, &versionMinor);
[self setSupportFileLevelAPI:versionMajor >= 10 && versionMinor >= 7];
// Uncomment to simulate 10.6 mode
// [self setSupportFileLevelAPI:NO];
[self configure];
if([fm fileExistsAtPath:[@"~/.bash_profile" stringByExpandingTildeInPath]])
@@ -91,21 +92,21 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
profilePath = @"";
}
}
return self;
}
- (void)start
{
{
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"XCCReopenLastProject"])
return;
NSString *lastOpenedPath = [[NSUserDefaults standardUserDefaults] objectForKey:@"LastOpenedPath"];
if (lastOpenedPath)
{
if ([fm fileExistsAtPath:lastOpenedPath])
{
{
[self listenProjectAtPath:[NSString stringWithFormat:@"%@/", lastOpenedPath]];
}
else
@@ -115,6 +116,135 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
}
}
#pragma mark - Project Management
/*!
Check if .XcodeSupport needs to be initialized.
If not needed, check that all J files are mirrored. If no,
then launch conversion for missing mirrored h files
@return YES or NO
*/
- (BOOL)prepareXCodeSupportProject
{
XCodeSupportProjectName = [NSString stringWithFormat:@"%@.xcodeproj/", currentProjectName];
XCodeTemplatePBXPath = [[NSBundle mainBundle] pathForResource:@"project.pbxproj" ofType:@"sample"];
XCodeSupportProject = [NSURL URLWithString:XCodeSupportProjectName relativeToURL:currentProjectURL];
XCodeSupportProjectSources = [NSURL URLWithString:@".XcodeSupport/" relativeToURL:currentProjectURL];
XCodeSupportPBXPath = [NSString stringWithFormat:@"%@/project.pbxproj", [XCodeSupportProject path]];
PBXModifierScriptPath = [[NSBundle mainBundle] pathForResource:@"pbxprojModifier" ofType:@"py"];
//[fm removeItemAtURL:XCodeSupportProjectSources error:nil];
//[fm removeItemAtURL:XCodeSupportProject error:nil];
// create the template project if it doesn't exist
if (![fm fileExistsAtPath:[XCodeSupportProjectSources path]])
{
NSLog(@"prepareXCodeSupportProject: Xcode support folder created at: %@", [XCodeSupportProject path]);
[fm createDirectoryAtPath:[XCodeSupportProject path] withIntermediateDirectories:YES attributes:nil error:nil];
DLog(@"prepareXCodeSupportProject: Copying project.pbxproj from %@ to %@", XCodeTemplatePBXPath, [XCodeSupportProject path]);
[fm copyItemAtPath:XCodeTemplatePBXPath toPath:XCodeSupportPBXPath error:nil];
DLog(@"prepareXCodeSupportProject: Reading the content of the project.pbxproj");
NSMutableString *PBXContent = [NSMutableString stringWithContentsOfFile:XCodeSupportPBXPath encoding:NSUTF8StringEncoding error:nil];
[PBXContent writeToFile:XCodeSupportPBXPath atomically:YES encoding:NSUTF8StringEncoding error:nil];
DLog(@"prepareXCodeSupportProject: PBX file adapted to the project");
[self createXcodeSupportProjectSourcesDirIfNecessary];
return NO;
}
[self createXcodeSupportProjectSourcesDirIfNecessary];
return YES;
}
/*!
Create the .XcodeSupport/Sources folder if necessary.
*/
- (void)createXcodeSupportProjectSourcesDirIfNecessary
{
if ([fm fileExistsAtPath:[XCodeSupportProjectSources path]])
return;
DLog(@"createXcodeSupportProjectSourcesDirIfNecessary: Creating source folder %@", [XCodeSupportProjectSources path]);
[fm createDirectoryAtPath:[XCodeSupportProjectSources path] withIntermediateDirectories:YES attributes:nil error:nil];
}
/*!
Initialize the creation of the .XcodeSupport project. This
Operation is threaded
@param arguments Thread arguments (not used)
@param shouldNotify is YES, XCCDidPopulateProjectNotification will be send
*/
- (void)populateXCodeProject:(NSNumber *)shouldNotify
{
if ([shouldNotify boolValue])
[delegate performSelector:@selector(growlWithTitle:message:) withObject:@"Loading project" withObject:[currentProjectURL path]];
NSArray *subdpaths = [fm subpathsAtPath:[currentProjectURL path]];
for (NSString *p in subdpaths)
{
NSString *filePath = [NSString stringWithFormat:@"%@/%@", [currentProjectURL path], p];
BOOL isDir = NO;
[fm fileExistsAtPath:filePath isDirectory:&isDir];
if (isDir || ![self isObjJFile:filePath] || [self isPathMatchingIgnoredPaths:filePath])
continue;
NSURL *eventualShadow = [self shadowHeaderURLForSourceURL:[NSURL fileURLWithPath:filePath]];
if (![fm fileExistsAtPath:[eventualShadow path]])
{
DLog(@"populateXCodeProject: Computing missing shadow file for %@", filePath);
[self handleFileModification:filePath notify:NO];
}
}
if ([shouldNotify boolValue])
{
NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:currentProjectURL, @"URL", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:XCCDidPopulateProjectNotification object:self userInfo:info];
}
}
/*!
Start all needed processes for listening to a given path
@param path The folder path to listen to
*/
- (void)listenProjectAtPath:(NSString *)path
{
NSMutableString *tempName = [NSMutableString stringWithString:[path lastPathComponent]];
currentProjectURL = [NSURL fileURLWithPath:path];
[tempName replaceOccurrencesOfString:@" "
withString:@"_"
options:NSCaseInsensitiveSearch
range:NSMakeRange(0, [tempName length])];
currentProjectName = [NSString stringWithString:tempName];
[self computeIgnoredPaths];
BOOL isProjectReady = [self prepareXCodeSupportProject];
[NSThread detachNewThreadSelector:@selector(populateXCodeProject:) toTarget:self withObject:[NSNumber numberWithBool:!isProjectReady]];
[self initializeEventStreamWithPath:[currentProjectURL path]];
NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:path, @"path", [NSNumber numberWithInt:(isProjectReady) ? 1 : 0], @"ready", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:XCCListeningStartNotification object:self userInfo:info];
[[NSUserDefaults standardUserDefaults] setObject:[currentProjectURL path] forKey:@"LastOpenedPath"];
}
#pragma mark - Event Stream
/*!
Initializes the FSEvent stream
@param aPath the path of the folder to listen
@@ -123,18 +253,18 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
{
if ([self isListening])
return;
[self stopEventStream];
NSMutableArray *pathsToWatch = [NSMutableArray arrayWithObject:aPath];
void *appPointer = (void *)self;
FSEventStreamContext context = {0, appPointer, NULL, NULL, NULL};
CFTimeInterval latency = 2.0;
FSEventStreamCreateFlags flags = 0;
if (supportsFileBasedListening)
{
DLog(@"Initializing the FSEventStream at file level (clean)");
DLog(@"initializeEventStreamWithPath: Initializing the FSEventStream at file level (clean)");
flags = kFSEventStreamCreateFlagUseCFTypes | kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents;
}
else
@@ -142,10 +272,10 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
NSLog(@"Initializing the FSEventStream at folder level (dirty)");
flags = kFSEventStreamCreateFlagUseCFTypes;
}
// add symlinked directories
NSArray *fileList = [fm contentsOfDirectoryAtPath:aPath error:nil];
for (NSString *node in fileList)
{
NSDictionary *attributes = [fm attributesOfItemAtPath:aPath error:nil];
@@ -160,19 +290,15 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
}
}
}
stream = FSEventStreamCreate(NULL, &fsevents_callback, &context, (CFArrayRef) pathsToWatch,
[lastEventId unsignedLongLongValue], latency, flags);
FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
FSEventStreamStart(stream);
[self setIsListening:YES];
}
#pragma mark -
#pragma mark Utilities
/*!
Stop listening the FSEvent stream if active
*/
@@ -210,7 +336,7 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
{
if (![self supportFileLevelAPI])
{
DLog(@"System doesn't support file level API");
DLog(@"configure: System doesn't support file level API");
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:2] forKey:@"XCCAPIMode"];
}
@@ -229,7 +355,7 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
if (supportsFileBasedListening)
{
DLog(@"using 10.7+ mode listening (clean)");
DLog(@"configure: using 10.7+ mode listening (clean)");
[self setCurrentAPIMode:@"File level (Lion)"];
[self setIsUsingFileLevelAPI:YES];
@@ -237,7 +363,7 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
}
else
{
DLog(@"using 10.6 mode listening (dirty)");
DLog(@"configure: using 10.6 mode listening (dirty)");
reactToInodeModification = NO;
[self setCurrentAPIMode:@"Folder level (Snow Leopard)"];
[self setIsUsingFileLevelAPI:NO];
@@ -273,6 +399,9 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
[[NSUserDefaults standardUserDefaults] synchronize];
}
#pragma mark - Shell Helpers
/*!
Run a NSTask with the given arguments
@param arguments NSArray containing the NSTask arguments
@@ -284,22 +413,25 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
NSData *stdOut;
NSString *response;
NSNumber *status;
task = [[NSTask alloc] init];
[task setLaunchPath: @"/bin/bash"];
[task setArguments: arguments];
[task setStandardOutput:[NSPipe pipe]];
[task launch];
[task waitUntilExit];
stdOut = [[[task standardOutput] fileHandleForReading] availableData];
response = [[NSString alloc] initWithData:stdOut encoding:NSUTF8StringEncoding];
status = [NSNumber numberWithInt:[task terminationStatus]];
return [NSArray arrayWithObjects:status, response, nil];
}
#pragma mark - Event Handlers
/*!
Handle a file modification. If it's a .J or XIB or NIB, it will
perform the according conversion. If it's .xcodecapp-ignore, it will
@@ -315,7 +447,7 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
if ([self isPathMatchingIgnoredPaths:fullPath] || ![fm fileExistsAtPath:fullPath])
return;
DLog(@"Parsing modified file: %@", fullPath);
DLog(@"handleFileModification:notify: Parsing modified file: %@", fullPath);
NSArray *arguments = nil;
NSArray *PBXArguments = nil;
@@ -324,16 +456,19 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
NSString *response = nil;
NSNumber *status = [NSNumber numberWithInt:0];
NSString *splitPath = [fullPath substringFromIndex:[[currentProjectURL path] length] + 1];
NSString *shadowPath = [[self shadowURLForSourceURL:[NSURL URLWithString:[fullPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]] path];
DLog(@"Shadow path: %@", shadowPath);
NSURL *encodedURL = [NSURL URLWithString:[fullPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURL *shadowHeaderURL = [self shadowHeaderURLForSourceURL:encodedURL];
NSURL *shadowImplementationURL = [self shadowImplementationURLForSourceURL:encodedURL];
DLog(@"handleFileModification:notify: Shadow header path: %@", shadowHeaderURL);
DLog(@"handleFileModification:notify: Shadow implementation path: %@", shadowImplementationURL);
[[NSNotificationCenter defaultCenter] postNotificationName:XCCConversionStartNotification object:self];
if ([self isXIBFile:fullPath])
{
arguments = [NSArray arrayWithObjects: @"-c",
[NSString stringWithFormat:@"(%@; nib2cib '%@';) 2>&1", profilePath, fullPath],@"",nil];
[NSString stringWithFormat:@"(%@; nib2cib '%@';) 2>&1", profilePath, fullPath],@"",nil];
successTitle = @"XIB converted";
successMsg = splitPath;
@@ -341,19 +476,20 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
else if ([self isObjJFile:fullPath])
{
arguments = [NSArray arrayWithObjects: @"-c",
[NSString stringWithFormat:@"(%@; objj '%@' '%@' '%@';) 2>&1",
profilePath,
parserPath,
fullPath,
shadowPath],
@"",nil];
[NSString stringWithFormat:@"(%@; objj '%@' '%@' '%@' '%@';) 2>&1",
profilePath,
parserPath,
fullPath,
[shadowHeaderURL path],
[shadowImplementationURL path]],nil];
PBXArguments = [NSArray arrayWithObjects: @"-c",
[NSString stringWithFormat:@"(%@; python %@ add '%@' '%@' '%@' '%@') 2>&1",
[NSString stringWithFormat:@"(%@; python %@ add '%@' '%@' '%@' '%@' '%@') 2>&1",
profilePath,
PBXModifierScriptPath,
XCodeSupportPBXPath,
shadowPath,
[shadowHeaderURL path],
[shadowImplementationURL path],
fullPath,
[currentProjectURL path]],nil];
@@ -371,22 +507,22 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
// Run the task and get the response if needed
if (arguments)
{
DLog(@"Running conversion task...");
DLog(@"handleFileModification:notify: Running conversion task...");
NSArray *statusInfo = [self runTask:arguments];
status = [statusInfo objectAtIndex:0];
response = [statusInfo objectAtIndex:1];
DLog(@"Conversion task result/response: %@/%@", status, response);
DLog(@"handleFileModification:notify: Conversion task result/response: %@/%@", status, response);
}
if (PBXArguments)
{
DLog(@"Running update PBX task...");
DLog(@"handleFileModification:notify: Running update PBX task...");
NSArray *statusInfo = [self runTask:PBXArguments];
status = [statusInfo objectAtIndex:0];
response = [statusInfo objectAtIndex:1];
DLog(@"Update PBX Task result/response: %@/%@", status, response);
DLog(@"handleFileModification:notify: Update PBX Task result/response: %@/%@", status, response);
}
if ([status intValue] == 0 && shouldNotify)
@@ -397,12 +533,12 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
{
if (response)
[errorList addObject:response];
[delegate performSelector:@selector(growlWithTitle:message:) withObject:@"Error processing file" withObject:splitPath];
}
[[NSNotificationCenter defaultCenter] postNotificationName:XCCConversionStopNotification object:self];
DLog(@"Processed: %@", fullPath);
DLog(@"handleFileModification:notify: Processed: %@", fullPath);
}
/*!
@@ -416,37 +552,18 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
{
if ([self isPathMatchingIgnoredPaths:fullPath] || [fm fileExistsAtPath:fullPath])
return;
NSString *encodedPath = [fullPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
if ([self isObjJFile:fullPath])
{
NSString *shadowPath = [[self shadowURLForSourceURL:[NSURL URLWithString:[fullPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]] path];
DLog(@"Removing shadow file: %@", shadowPath);
[fm removeItemAtPath:shadowPath error:nil];
DLog(@"Removing PBX reference task...");
#if DEBUG
NSArray *PBXArguments = [NSArray arrayWithObjects: @"-c",
[NSString stringWithFormat:@"(%@; python %@ remove '%@' '%@' '%@' '%@') 2>&1",
profilePath,
PBXModifierScriptPath,
XCodeSupportPBXPath,
shadowPath,
fullPath,
[currentProjectURL path]],nil];
NSArray *statusInfo = [self runTask:PBXArguments];
NSNumber *status = [statusInfo objectAtIndex:0];
NSString *response = [statusInfo objectAtIndex:1];
#endif
DLog(@"PBX Reference removal status/response: %@/%@", status, response);
}
[self cleanUpShadowsRelatedToSourceURL:[NSURL URLWithString:encodedPath]];
else if ([self isXCCIgnoreFile:fullPath])
{
[self computeIgnoredPaths];
}
}
#pragma mark - Source Files Management
/*!
Check if given full path is Objective-J file
@param path the path to check
@@ -480,114 +597,23 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
}
/*!
Check if .XcodeSupport needs to be initialized.
If not needed, check that all J files are mirrored. If no,
then launch conversion for missing mirrored h files
@return YES or NO
*/
- (BOOL)prepareXCodeSupportProject
{
XCodeSupportProjectName = [NSString stringWithFormat:@"%@.xcodeproj/", currentProjectName];
XCodeTemplatePBXPath = [[NSBundle mainBundle] pathForResource:@"project.pbxproj" ofType:@"sample"];
XCodeSupportProject = [NSURL URLWithString:XCodeSupportProjectName relativeToURL:currentProjectURL];
XCodeSupportProjectSources = [NSURL URLWithString:@".XcodeSupport/" relativeToURL:currentProjectURL];
XCodeSupportPBXPath = [NSString stringWithFormat:@"%@/project.pbxproj", [XCodeSupportProject path]];
PBXModifierScriptPath = [[NSBundle mainBundle] pathForResource:@"pbxprojModifier" ofType:@"py"];
//[fm removeItemAtURL:XCodeSupportProjectSources error:nil];
//[fm removeItemAtURL:XCodeSupportProject error:nil];
// create the template project if it doesn't exist
if (![fm fileExistsAtPath:[XCodeSupportProjectSources path]])
{
NSLog(@"Xcode support folder created at: %@", [XCodeSupportProject path]);
[fm createDirectoryAtPath:[XCodeSupportProject path] withIntermediateDirectories:YES attributes:nil error:nil];
DLog(@"Copying project.pbxproj from %@ to %@", XCodeTemplatePBXPath, [XCodeSupportProject path]);
[fm copyItemAtPath:XCodeTemplatePBXPath toPath:XCodeSupportPBXPath error:nil];
DLog(@"Reading the content of the project.pbxproj");
NSMutableString *PBXContent = [NSMutableString stringWithContentsOfFile:XCodeSupportPBXPath encoding:NSUTF8StringEncoding error:nil];
[PBXContent writeToFile:XCodeSupportPBXPath atomically:YES encoding:NSUTF8StringEncoding error:nil];
DLog(@"PBX file adapted to the project");
[self createXcodeSupportProjectSourcesDirIfNecessary];
return NO;
}
[self createXcodeSupportProjectSourcesDirIfNecessary];
return YES;
}
#pragma mark - Shadow Files Management
/*!
Create the .XcodeSupport/Sources folder if necessary.
*/
- (void)createXcodeSupportProjectSourcesDirIfNecessary
{
if ([fm fileExistsAtPath:[XCodeSupportProjectSources path]])
return;
DLog(@"Creating source folder %@", [XCodeSupportProjectSources path]);
[fm createDirectoryAtPath:[XCodeSupportProjectSources path] withIntermediateDirectories:YES attributes:nil error:nil];
}
/*!
Initialize the creation of the .XcodeSupport project. This
Operation is threaded
@param arguments Thread arguments (not used)
@param shouldNotify is YES, XCCDidPopulateProjectNotification will be send
*/
- (void)populateXCodeProject:(NSNumber *)shouldNotify
{
if ([shouldNotify boolValue])
[delegate performSelector:@selector(growlWithTitle:message:) withObject:@"Loading project" withObject:[currentProjectURL path]];
NSArray *subdpaths = [fm subpathsAtPath:[currentProjectURL path]];
for (NSString *p in subdpaths)
{
NSString *filePath = [NSString stringWithFormat:@"%@/%@", [currentProjectURL path], p];
BOOL isDir = NO;
[fm fileExistsAtPath:filePath isDirectory:&isDir];
if (isDir || ![self isObjJFile:filePath] || [self isPathMatchingIgnoredPaths:filePath])
continue;
NSURL *eventualShadow = [self shadowURLForSourceURL:[NSURL fileURLWithPath:filePath]];
if (![fm fileExistsAtPath:[eventualShadow path]])
{
DLog(@"Computing missing shadow file for %@", filePath);
[self handleFileModification:filePath notify:NO];
}
}
if ([shouldNotify boolValue])
{
NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:currentProjectURL, @"URL", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:XCCDidPopulateProjectNotification object:self userInfo:info];
}
}
/*!
Compute the mirorred (shadow) name for a given path
Compute the mirorred (shadow) header file name for a given path
@param aSourceURL the origin path
@return NSURL representing the shadow path
@return NSURL representing the shadow URL for the header file
*/
- (NSURL *)shadowURLForSourceURL:(NSURL*)aSourceURL
- (NSURL *)shadowHeaderURLForSourceURL:(NSURL*)aSourceURL
{
if (!aSourceURL)
[NSException raise:NSInvalidArgumentException format:@"shadowURLForSourceURL: aSource URL must not be null"];
[NSException raise:NSInvalidArgumentException format:@"shadowHeaderURLForSourceURL: aSource URL must not be null"];
NSMutableString *flattenedPath = [NSMutableString stringWithString:[aSourceURL path]];
// Replace "_" with a substring that is unlikely to be in a filename
[flattenedPath replaceOccurrencesOfString:@"_"
withString:@"≤‹°∞°›≥"
withString:XCCUnderscoreReplacement
options:0
range:NSMakeRange(0, [flattenedPath length])];
@@ -596,12 +622,33 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
options:0
range:NSMakeRange(0, [flattenedPath length])];
DLog(@"Flattened path: %@", flattenedPath);
NSString *basename = [NSString stringWithFormat:@"%@.m", [[flattenedPath stringByDeletingPathExtension] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
DLog(@"shadowHeaderURLForSourceURL: Flattened path: %@", flattenedPath);
NSString *basename = [NSString stringWithFormat:@"%@.h", [[flattenedPath stringByDeletingPathExtension] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
return [NSURL URLWithString:basename relativeToURL:XCodeSupportProjectSources];
}
/*!
Compute the mirorred (shadow) implementation file name for a given path
@param aSourceURL the origin path
@return NSURL representing the shadow URL for the implementation file
*/
- (NSURL *)shadowImplementationURLForSourceURL:(NSURL*)aSourceURL
{
if (!aSourceURL)
[NSException raise:NSInvalidArgumentException format:@"shadowImplementationURLForSourceURL: aSource URL must not be null"];
NSURL *shadowHeaderURL = [self shadowHeaderURLForSourceURL:aSourceURL];
NSURL *shadowImplPath = [[shadowHeaderURL URLByDeletingPathExtension] URLByAppendingPathExtension:@"m"];
return shadowImplPath;
}
/*!
Compute the Cappuccino source file that is related to the given shadow header file URL
@param aString the origin path
@return NSURL representing the URL for the related Cappuccino source file
*/
- (NSURL *)sourceURLForShadowName:(NSString *)aString
{
NSMutableString * unshadowedPath = [NSMutableString stringWithString:aString];
@@ -611,12 +658,12 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
options:0
range:NSMakeRange(0, [unshadowedPath length])];
[unshadowedPath replaceOccurrencesOfString:@"≤‹°∞°›≥"
withString:@"_"
options:0
range:NSMakeRange(0, [unshadowedPath length])];
[unshadowedPath replaceOccurrencesOfString:XCCUnderscoreReplacement
withString:@"_"
options:0
range:NSMakeRange(0, [unshadowedPath length])];
[unshadowedPath replaceOccurrencesOfString:@".m"
[unshadowedPath replaceOccurrencesOfString:@".h"
withString:@".j"
options:0
range:NSMakeRange(0, [unshadowedPath length])];
@@ -624,6 +671,64 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
return [NSURL fileURLWithPath:[NSString stringWithString:unshadowedPath]];
}
/*!
Clean up any shadow files and PBX entries related to given the Cappuccino source file URL
@param anURL the Cappuccino source file URL
*/
- (void)cleanUpShadowsRelatedToSourceURL:(NSURL *)anURL
{
NSURL *shadowHeaderURL = [self shadowHeaderURLForSourceURL:anURL];
NSURL *shadowImplementationURL = [self shadowImplementationURLForSourceURL:anURL];
DLog(@"cleanUpShadowsRelatedToSourceURL: Removing shadow header file: %@", shadowHeaderURL);
[fm removeItemAtURL:shadowHeaderURL error:nil];
DLog(@"cleanUpShadowsRelatedToSourceURL: Removing shadow implementation file: %@", shadowImplementationURL);
[fm removeItemAtURL:shadowImplementationURL error:nil];
DLog(@"cleanUpShadowsRelatedToSourceURL:Removing PBX reference task...");
NSArray *PBXArguments = [NSArray arrayWithObjects: @"-c",
[NSString stringWithFormat:@"(%@; python %@ remove '%@' '%@' '%@' '%@' '%@') 2>&1",
profilePath,
PBXModifierScriptPath,
XCodeSupportPBXPath,
[shadowHeaderURL path],
[shadowImplementationURL path],
[anURL path],
[currentProjectURL path]],nil];
NSArray *statusInfo = [self runTask:PBXArguments];
NSNumber *status = [statusInfo objectAtIndex:0];
NSString *response = [statusInfo objectAtIndex:1];
DLog(@"cleanUpShadowsRelatedToSourceURL: PBX Reference removal status/response: %@/%@", status, response);
}
/*!
Clean the support folder according to files present in given path
*/
- (void)tidyShadowedFiles
{
NSArray *subpaths = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[XCodeSupportProjectSources path] error:NULL];
for (NSString *subpath in subpaths)
{
if ([subpath pathExtension] != @".h" || [subpath lastPathComponent] == @"xcc_general_include.h")
continue;
NSURL *unshadowed = [self sourceURLForShadowName:subpath];
if (![fm fileExistsAtPath:[unshadowed path]])
{
[self cleanUpShadowsRelatedToSourceURL:unshadowed];
if (![self supportFileLevelAPI] && [self respondsToSelector:@selector(updateLastModificationDate:forPath:)])
[self performSelector:@selector(updateLastModificationDate:forPath:) withObject:nil withObject:unshadowed];
}
}
}
#pragma mark - XCC Ignore management
/*!
Compute the ignored paths according to any existing
@@ -645,7 +750,7 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
[ignoredFilePaths addObject:pattern];
}
}
[ignoredFilePaths addObject:@"*/.git/*"];
[ignoredFilePaths addObject:@"*/.svn/*"];
[ignoredFilePaths addObject:@"*/.hg/*"];
@@ -656,7 +761,7 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
[ignoredFilePaths addObject:@"*main.j"];
[ignoredFilePaths addObject:@"*.xcodeproj/*"];
[ignoredFilePaths addObject:@"*.DS_Store"];
NSLog(@"Ignoring file paths: %@", ignoredFilePaths);
}
@@ -706,76 +811,6 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
return NO;
}
/*!
Start all needed processes for listening to a given path
@param path The folder path to listen to
*/
- (void)listenProjectAtPath:(NSString *)path
{
NSMutableString *tempName = [NSMutableString stringWithString:[path lastPathComponent]];
currentProjectURL = [NSURL fileURLWithPath:path];
[tempName replaceOccurrencesOfString:@" "
withString:@"_"
options:NSCaseInsensitiveSearch
range:NSMakeRange(0, [tempName length])];
currentProjectName = [NSString stringWithString:tempName];
[self computeIgnoredPaths];
BOOL isProjectReady = [self prepareXCodeSupportProject];
[NSThread detachNewThreadSelector:@selector(populateXCodeProject:) toTarget:self withObject:[NSNumber numberWithBool:!isProjectReady]];
[self initializeEventStreamWithPath:[currentProjectURL path]];
NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:path, @"path", [NSNumber numberWithInt:(isProjectReady) ? 1 : 0], @"ready", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:XCCListeningStartNotification object:self userInfo:info];
[[NSUserDefaults standardUserDefaults] setObject:[currentProjectURL path] forKey:@"LastOpenedPath"];
}
/*!
Clean the support folder according to files present in given path
*/
- (void)tidyShadowedFiles
{
NSArray *subpaths = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[XCodeSupportProjectSources path] error:NULL];
for (NSString *subpath in subpaths)
{
NSString *unshadowed = [[self sourceURLForShadowName:subpath] path];
NSString *shadowFullPath = [NSString stringWithFormat:@"%@/%@", [XCodeSupportProjectSources path], subpath];
if (![fm fileExistsAtPath:unshadowed])
{
DLog(@"cleaning shadow file: %@", subpath);
[fm removeItemAtPath:shadowFullPath error:nil];
#if DEBUG
NSArray *PBXArguments = [NSArray arrayWithObjects: @"-c",
[NSString stringWithFormat:@"(%@; python %@ remove '%@' '%@' '%@' '%@') 2>&1",
profilePath,
PBXModifierScriptPath,
XCodeSupportPBXPath,
shadowFullPath,
unshadowed,
[currentProjectURL path]],nil];
DLog(@"Cleaning PBX reference task...");
NSArray *statusInfo = [self runTask:PBXArguments];
NSNumber *status = [statusInfo objectAtIndex:0];
NSString *response = [statusInfo objectAtIndex:1];
#endif
DLog(@"PBX Reference cleaning status/response: %@/%@", status, response);
if (![self supportFileLevelAPI] && [self respondsToSelector:@selector(updateLastModificationDate:forPath:)])
[self performSelector:@selector(updateLastModificationDate:forPath:) withObject:nil withObject:unshadowed];
}
}
}
@end
@@ -786,7 +821,7 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
if (!pathModificationDates)
{
pathModificationDates = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"pathModificationDates"] mutableCopy];
if (!pathModificationDates)
pathModificationDates = [NSMutableDictionary new];
}
@@ -804,7 +839,7 @@ NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification
if (!pathModificationDates)
{
pathModificationDates = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"pathModificationDates"] mutableCopy];
if (!pathModificationDates)
pathModificationDates = [NSMutableDictionary new];
}
@@ -194,6 +194,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 027D99A313696A7000D3DB13 /* Build configuration list for PBXNativeTarget "XcodeCapp" */;
buildPhases = (
024699001602C04A00F0AE43 /* ShellScript */,
027D999A13696A7000D3DB13 /* Resources */,
027D999D13696A7000D3DB13 /* Sources */,
02998CF81369C383006C73DB /* CopyFiles */,
@@ -255,6 +256,25 @@
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
024699001602C04A00F0AE43 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"$(SRCROOT)/*.m",
"$(SRCROOT)/*.h",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /usr/bin/perl;
shellScript = "#!/usr/bin/perl\n\nwhile (<>) {\n s/\\s+$//;\n print \"$_\\n\";\n}";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
027D999D13696A7000D3DB13 /* Sources */ = {
isa = PBXSourcesBuildPhase;
+24 -8
View File
@@ -26,7 +26,8 @@ var FILE = require("file");
function main(args)
{
var fileURL = new CFURL(args[1]),
outputURL = new CFURL(args[2]),
outputHeaderURL = new CFURL(args[2]),
outputSourceURL = new CFURL(args[3]),
source = FILE.read(fileURL, { charset: "UTF-8" }),
flags = ObjectiveJ.Preprocessor.Flags.IncludeDebugSymbols |
ObjectiveJ.Preprocessor.Flags.IncludeTypeSignatures,
@@ -65,7 +66,8 @@ function main(args)
eval(source);
var ObjectiveCSource = "";
var ObjectiveCSource = "",
ObjectiveCHeader = "";
classes.forEach(function(aClass)
{
@@ -104,22 +106,29 @@ function main(args)
var className = class_getName(aClass),
superClassName = superClasses[className];
ObjectiveCSource +=
ObjectiveCHeader +=
"#import <Foundation/Foundation.h>\n" +
"#import <Cocoa/Cocoa.h>\n" +
"#import \"xcc_general_include.h\"\n" +
"\n@interface " + class_getName(aClass) +
(superClassName === "Nil" ? "" : (" : " + NSCompatibleClassName(superClassName))) +
"\n\n" +
outlets.join("\n") +
"\n" +
actions.join("\n") +
"\n@end\n\n"+
"\n@end\n";
ObjectiveCSource +=
"#import \"" + outputHeaderURL.absoluteString().replace(/\\/g,'/').replace( /.*\//, '' ) + "\"" +
"\n@implementation " + class_getName(aClass) +
"\n@end\n";
});
if (ObjectiveCSource.length)
FILE.write(outputURL, ObjectiveCSource, { charset:"UTF-8" });
FILE.write(outputSourceURL, ObjectiveCSource, { charset:"UTF-8" });
if (ObjectiveCHeader.length)
FILE.write(outputHeaderURL, ObjectiveCHeader, { charset:"UTF-8" });
}
function NSCompatibleClassName(aClassName, asPointer)
@@ -127,10 +136,10 @@ function NSCompatibleClassName(aClassName, asPointer)
if (aClassName === "var" || aClassName === "id")
return "id";
var suffix = aClassName.substr(0, 2),
var prefix = aClassName.substr(0, 2),
asterisk = asPointer ? "*" : "";
if (suffix !== "CP")
if (prefix !== "CP")
return aClassName + asterisk;
var NSClassName = "NS" + aClassName.substr(2);
@@ -138,9 +147,16 @@ function NSCompatibleClassName(aClassName, asPointer)
if (NSClasses[NSClassName])
return NSClassName + asterisk;
if (ReplacementClasses[aClassName])
return ReplacementClasses[aClassName] + asterisk;
return aClassName + asterisk;
}
var ReplacementClasses = {
"CPWebView": "WebView"
};
var NSClasses = {
"NSAffineTransform" : YES,
"NSAppleEventDescriptor" : YES,
@@ -486,4 +502,4 @@ var NSClasses = {
"NSWindowController" : YES,
"NSWorkspace" : YES,
"NSPopover": YES
};
};
+41 -32
View File
@@ -3,49 +3,58 @@ from mod_pbxproj import XcodeProject
XCODESUPPORTFOLDER = ".XcodeSupport"
def add_file(project, shadowGroup, sourceGroup, shadowPath, sourcePath, projectBaseURL):
project.add_file(shadowPath, parent=shadowGroup)
project.add_file(sourcePath, parent=sourceGroup)
project.save()
def update_general_include(project, projectBaseURL):
xcc_general_include_file = "%s/%s/xcc_general_include.h" % (projectBaseURL, XCODESUPPORTFOLDER)
content = ""
def remove_file(project, shadowGroup, sourceGroup, shadowPath, sourcePath, projectBaseURL):
project.remove_file("%s/%s" % (XCODESUPPORTFOLDER, os.path.basename(shadowPath)), parent=shadowGroup)
for file in os.listdir("%s/%s" % (projectBaseURL, XCODESUPPORTFOLDER)):
if file.endswith(".h"):
content += "#include \"%s\"\n" % file
f = open(xcc_general_include_file, "w")
f.write(content)
f.close()
if len(project.get_files_by_os_path("%s/%s" % (XCODESUPPORTFOLDER, os.path.basename(xcc_general_include_file)))) == 0:
project.add_file(xcc_general_include_file, parent=shadowGroup)
def add_file(project, shadowGroup, sourceGroup, shadowHeaderPath, shadowImplementationFilePath, sourcePath, projectBaseURL):
project.add_file(shadowHeaderPath, parent=shadowGroup)
project.add_file(shadowImplementationFilePath, parent=shadowGroup)
project.add_file(sourcePath, parent=sourceGroup)
def remove_file(project, shadowGroup, sourceGroup, shadowHeaderPath, shadowImplementationFilePath, sourcePath, projectBaseURL):
project.remove_file("%s/%s" % (XCODESUPPORTFOLDER, os.path.basename(shadowHeaderPath)), parent=shadowGroup)
project.remove_file("%s/%s" % (XCODESUPPORTFOLDER, os.path.basename(shadowImplementationFilePath)), parent=shadowGroup)
project.remove_file(os.path.relpath(sourcePath, projectBaseURL), parent=sourceGroup)
project.save()
if __name__ == '__main__':
action = sys.argv[1]
PBXProjectFilePath = sys.argv[2]
shadowFilePath = sys.argv[3]
sourceFilePath = sys.argv[4]
projectBaseURL = sys.argv[5]
action = sys.argv[1]
PBXProjectFilePath = sys.argv[2]
shadowHeaderFilePath = sys.argv[3]
shadowImplementationFilePath = sys.argv[4]
sourceFilePath = sys.argv[5]
projectBaseURL = sys.argv[6]
project = XcodeProject.Load(PBXProjectFilePath)
shadowGroup = project.get_or_create_group('Classes')
sourceGroup = project.get_or_create_group('Sources')
if "main.m" in shadowFilePath:
if "main.j" in sourceFilePath:
sys.exit(0)
files = project.get_files_by_os_path("%s/%s" % (XCODESUPPORTFOLDER, os.path.basename(shadowFilePath)))
files = project.get_files_by_os_path("%s/%s" % (XCODESUPPORTFOLDER, os.path.basename(shadowHeaderFilePath)))
if action == "add" and len(files) == 0:
add_file(project, shadowGroup, sourceGroup, shadowFilePath, sourceFilePath, projectBaseURL)
update_general_include(project, projectBaseURL)
add_file(project, shadowGroup, sourceGroup, shadowHeaderFilePath, shadowImplementationFilePath, sourceFilePath, projectBaseURL)
project.save()
elif action == "remove" and len(files) == 1:
remove_file(project, shadowGroup, sourceGroup, shadowFilePath, sourceFilePath, projectBaseURL)
update_general_include(project, projectBaseURL)
remove_file(project, shadowGroup, sourceGroup, shadowHeaderFilePath, shadowImplementationFilePath, sourceFilePath, projectBaseURL)
project.save()
-2
View File
@@ -269,8 +269,6 @@ var NSButtonIsBorderedMask = 0x00800000,
_highlightsBy = [cell highlightsBy];
_showsStateBy = [cell showsStateBy];
[self setTag:[cell tag]];
return self;
}
+3
View File
@@ -45,6 +45,9 @@
CPLog.debug("NSColorWell: adjusting height from %d to %d", frameSize.height, 24.0);
frameSize.height = 24.0;
[self setFrameSize:frameSize];
// Adjust for differences between Cocoa and Cappuccino widget framing.
_frame.origin.x -= 3;
}
}
+3
View File
@@ -48,6 +48,9 @@
size = [self frameSize];
[self setFrameSize:CGSizeMake(size.width, MIN(size.height, maxSize.height))];
// Adjust for differences between Cocoa and Cappuccino widget framing.
_frame.origin.x += 1;
}
return self;
+5
View File
@@ -56,6 +56,11 @@
[self setLineBreakMode:[cell lineBreakMode]];
[self setFormatter:[cell formatter]];
// In IB, both cells and controls can have tags.
// If the control has a tag, that takes precedence.
if ([aCoder containsValueForKey:@"NSTag"])
[self setTag:[aCoder decodeIntForKey:@"NSTag"]];
}
return self;
+1
View File
@@ -82,6 +82,7 @@ var NSMatrixRadioModeMask = 0x40000000,
[self setBackgroundColor:backgroundColor];
self.isa = [CPView class];
NIB_CONNECTION_EQUIVALENCY_TABLE[[self UID]] = radioGroup;
}
else
{
+3 -3
View File
@@ -36,10 +36,10 @@
_menu = [cell menu];
// adjust the frame
_frame.origin.x -= 3;
_frame.origin.x -= 4;
_frame.origin.y -= 4;
_frame.size.width += 6;
_bounds.size.width += 6;
_frame.size.width += 7;
_bounds.size.width += 7;
[self setPullsDown:[cell pullsDown]];
_preferredEdge = [cell preferredEdge];
+2
View File
@@ -57,6 +57,8 @@
[self tileWithChangedSegment:i];
}
// Adjust for differences between Cocoa and Cappuccino widget framing.
frame.origin.x += 4;
frame.size.width = originalWidth;
[self setFrame:frame];
}
+5
View File
@@ -38,6 +38,11 @@
_valueWraps = [cell valueWraps];
_autorepeat = [cell autorepeat];
_objectValue = [cell objectValue];
// Convert Cocoa normal size to Cappuccino normal size.
_frame.origin.y += 2;
_frame.size.height -= 2;
_bounds.size.height -= 2;
}
return self;
+2 -1
View File
@@ -90,7 +90,8 @@
headerView = [[_CPTableColumnHeaderView alloc] initWithFrame:CPRectMakeZero()];
[headerView setStringValue:[headerCell objectValue]];
[headerView setValue:[dataViewCell alignment] forThemeAttribute:@"text-alignment"];
[headerView setFont:[headerCell font]];
[headerView setAlignment:[headerCell alignment]];
[self setHeaderView:headerView];
+14 -9
View File
@@ -23,15 +23,20 @@
@import <AppKit/_CPCibWindowTemplate.j>
var NSBorderlessWindowMask = 0x00,
NSTitledWindowMask = 0x01,
NSClosableWindowMask = 0x02,
NSMiniaturizableWindowMask = 0x04,
NSResizableWindowMask = 0x08,
NSUtilityWindowMask = 0x10,
NSDocModalWindowMask = 0x40,
NSTexturedBackgroundWindowMask = 0x100,
NSHUDBackgroundWindowMask = 0x2000,
var NSBorderlessWindowMask = 0x00,
NSTitledWindowMask = 0x01,
NSClosableWindowMask = 0x02,
NSMiniaturizableWindowMask = 0x04,
NSResizableWindowMask = 0x08,
NSUtilityWindowMask = 0x10,
NSDocModalWindowMask = 0x40,
NSTexturedBackgroundWindowMask = 0x100,
NSHUDBackgroundWindowMask = 0x2000,
NSPositionFlexibleRight = 1 << 19,
NSPositionFlexibleLeft = 1 << 20,
NSPositionFlexibleBottom = 1 << 21,
NSPositionFlexibleTop = 1 << 22,
NSAutorecalculatesKeyViewLoopWTFlag = 0x800;
+11 -1
View File
@@ -466,8 +466,18 @@ global.sudo = function(/*Array or String*/ command)
// First try without sudo
command = normalizeCommand(command);
if (OS.system(command + " >/dev/null 2>&1"))
var returnCode = OS.system(command + " >/dev/null 2>&1")
if (returnCode)
{
// if this is set, then disable the use of sudo.
// This is very usefull for CI scripts and stuff like that
if (SYSTEM.env["CAPP_NOSUDO"] == 1)
return returnCode;
return OS.system("sudo -p '\nEnter your admin password: ' " + command);
}
return 0;
};