mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-09-08 19:57:14 +00:00
Merge remote branch 'cappuccino/jake' into jake
Conflicts: AppKit/CPTableView.j AppKit/CPViewAnimation.j
This commit is contained in:
+4
-3
@@ -148,7 +148,8 @@ var CPAlertWarningImage,
|
||||
var button = _buttons[i];
|
||||
|
||||
[button setFrameSize:CGSizeMake([button frame].size.width, (styleMask == CPHUDBackgroundWindowMask) ? 20.0 : 24.0)];
|
||||
[button setTheme:[CPTheme themeNamed: _windowStyle === CPHUDBackgroundWindowMask ? "Aristo-HUD" : "Aristo"]];
|
||||
|
||||
[button setTheme:(_windowStyle === CPHUDBackgroundWindowMask) ? [CPTheme themeNamed:"Aristo-HUD"] : [CPTheme defaultTheme]];
|
||||
|
||||
[[_alertPanel contentView] addSubview:button];
|
||||
}
|
||||
@@ -263,8 +264,8 @@ var CPAlertWarningImage,
|
||||
[button setTag:_buttonCount];
|
||||
[button setAction:@selector(_notifyDelegate:)];
|
||||
|
||||
[button setTheme:[CPTheme themeNamed: _windowStyle === CPHUDBackgroundWindowMask ? "Aristo-HUD" : "Aristo"]];
|
||||
[button setAutoresizingMask:CPViewMinXMargin|CPViewMinYMargin];
|
||||
[button setTheme:(_windowStyle === CPHUDBackgroundWindowMask) ? [CPTheme themeNamed:"Aristo-HUD"] : [CPTheme defaultTheme]];
|
||||
[button setAutoresizingMask:CPViewMinXMargin | CPViewMinYMargin];
|
||||
|
||||
[[_alertPanel contentView] addSubview:button];
|
||||
|
||||
|
||||
@@ -962,7 +962,7 @@ CPRunContinuesResponse = -1002;
|
||||
+ (CPString)defaultThemeName
|
||||
{
|
||||
// FIXME: don't hardcode
|
||||
return @"Aristo.blend";
|
||||
return ([[CPBundle mainBundle] objectForInfoDictionaryKey:"CPDefaultTheme"] || @"Aristo");
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1069,7 +1069,7 @@ var _CPAppBootstrapperActions = nil;
|
||||
|
||||
+ (BOOL)loadDefaultTheme
|
||||
{
|
||||
var blend = [[CPThemeBlend alloc] initWithContentsOfURL:[[CPBundle bundleForClass:[CPApplication class]] pathForResource:[CPApplication defaultThemeName]]];
|
||||
var blend = [[CPThemeBlend alloc] initWithContentsOfURL:[[CPBundle bundleForClass:[CPApplication class]] pathForResource:[CPApplication defaultThemeName] + ".blend"]];
|
||||
|
||||
[blend loadWithDelegate:self];
|
||||
|
||||
@@ -1078,7 +1078,7 @@ var _CPAppBootstrapperActions = nil;
|
||||
|
||||
+ (void)blendDidFinishLoading:(CPBundle)aBundle
|
||||
{
|
||||
[CPTheme setDefaultTheme:[CPTheme themeNamed:@"Aristo"]];
|
||||
[CPTheme setDefaultTheme:[CPTheme themeNamed:[CPApplication defaultThemeName]]];
|
||||
|
||||
[self performActions];
|
||||
}
|
||||
|
||||
@@ -359,21 +359,29 @@
|
||||
- (void)tile
|
||||
{
|
||||
var width = CGRectGetWidth([self bounds]);
|
||||
|
||||
|
||||
if (![_content count] || width == _tileWidth)
|
||||
return;
|
||||
|
||||
|
||||
// We try to fit as many views per row as possible. Any remaining space is then
|
||||
// either proportioned out to the views (if their minSize != maxSize) or used as
|
||||
// margin
|
||||
var itemSize = CGSizeMakeCopy(_minItemSize);
|
||||
|
||||
|
||||
_numberOfColumns = MAX(1.0, FLOOR(width / itemSize.width));
|
||||
|
||||
|
||||
if (_maxNumberOfColumns > 0)
|
||||
_numberOfColumns = MIN(_maxNumberOfColumns, _numberOfColumns);
|
||||
|
||||
var remaining = width - _numberOfColumns * itemSize.width,
|
||||
|
||||
var nbItems = [_items count];
|
||||
if (_numberOfColumns > nbItems)
|
||||
_numberOfColumns = nbItems;
|
||||
|
||||
var maxItemSize = CGSizeMakeCopy(_maxItemSize);
|
||||
if (maxItemSize.width==0)
|
||||
maxItemSize.width = FLOOR(width / _numberOfColumns);
|
||||
|
||||
var remaining = width - _numberOfColumns * itemSize.width,
|
||||
itemsNeedSizeUpdate = NO;
|
||||
|
||||
if (remaining > 0 && itemSize.width < _maxItemSize.width)
|
||||
@@ -406,7 +414,7 @@
|
||||
{
|
||||
if (index % _numberOfColumns == 0)
|
||||
{
|
||||
x = _horizontalMargin;
|
||||
x = 0;
|
||||
y += _verticalMargin + itemSize.height;
|
||||
}
|
||||
|
||||
@@ -417,7 +425,7 @@
|
||||
if (itemsNeedSizeUpdate)
|
||||
[view setFrameSize:_itemSize];
|
||||
|
||||
x += itemSize.width + _horizontalMargin;
|
||||
x += itemSize.width;
|
||||
}
|
||||
|
||||
_tileWidth = width;
|
||||
|
||||
@@ -735,6 +735,9 @@ var CPColorComponentsKey = @"CPColorComponentsKey",
|
||||
|
||||
var hexCharacters = "0123456789ABCDEF";
|
||||
|
||||
// HACK: prevent these from becoming globals. workaround for obj-j "function foo(){}" behavior
|
||||
var hexToRGB, integerToBytes, rgbToHex, byteToHex;
|
||||
|
||||
/*!
|
||||
Used for the CPColor \c +colorWithHexString: implementation
|
||||
@ignore
|
||||
|
||||
+28
-5
@@ -30,7 +30,7 @@
|
||||
*/
|
||||
@implementation CPFlashMovie : CPObject
|
||||
{
|
||||
CPString _fileName;
|
||||
CPString _filename;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -38,9 +38,9 @@
|
||||
@param aFilename the swf to load
|
||||
@return the initialized CPFlashMovie
|
||||
*/
|
||||
+ (id)flashMovieWithFile:(CPString)aFileName
|
||||
+ (id)flashMovieWithFile:(CPString)aFilename
|
||||
{
|
||||
return [[self alloc] initWithFile:aFileName];
|
||||
return [[self alloc] initWithFile:aFilename];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -48,14 +48,37 @@
|
||||
@param aFilename the swf to load
|
||||
@return the initialized CPFlashMovie
|
||||
*/
|
||||
- (id)initWithFile:(CPString)aFileName
|
||||
- (id)initWithFile:(CPString)aFilename
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self)
|
||||
_fileName = aFileName;
|
||||
_filename = aFilename;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (CPString)filename
|
||||
{
|
||||
return _filename;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPFlashMovieFilenameKey = "CPFlashMovieFilenameKey";
|
||||
|
||||
@implementation CPFlashMovie (CPCoding)
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
_filename = [aCoder decodeObjectForKey:CPFlashMovieFilenameKey];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
[aCoder encodeObject:_filename forKey:CPFlashMovieFilenameKey];
|
||||
}
|
||||
|
||||
@end
|
||||
+78
-59
@@ -24,20 +24,21 @@
|
||||
@import "CPView.j"
|
||||
|
||||
|
||||
var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
*/
|
||||
@implementation CPFlashView : CPView
|
||||
{
|
||||
CPFlashMovie _flashMovie;
|
||||
CPDictionary _flashVars;
|
||||
|
||||
CPDictionary _params;
|
||||
CPDictionary _paramElements;
|
||||
|
||||
DOMElement _DOMEmbedElement;
|
||||
DOMElement _DOMMParamElement;
|
||||
DOMElement _DOMParamElement;
|
||||
DOMElement _DOMObjectElement;
|
||||
DOMElement _DOMInnerObjectElement;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
@@ -46,35 +47,30 @@
|
||||
|
||||
if (self)
|
||||
{
|
||||
_DOMObjectElement = document.createElement("object");
|
||||
_DOMObjectElement.width = "100%";
|
||||
_DOMObjectElement.height = "100%";
|
||||
_DOMObjectElement.style.top = "0px";
|
||||
_DOMObjectElement.style.left = "0px";
|
||||
|
||||
_DOMParamElement = document.createElement("param");
|
||||
_DOMParamElement.name = "movie";
|
||||
|
||||
_DOMObjectElement.appendChild(_DOMParamElement);
|
||||
|
||||
var param = document.createElement("param");
|
||||
|
||||
param.name = "wmode";
|
||||
param.value = "transparent";
|
||||
|
||||
_DOMObjectElement.appendChild(param);
|
||||
|
||||
_DOMEmbedElement = document.createElement("embed");
|
||||
|
||||
_DOMEmbedElement.type = "application/x-shockwave-flash";
|
||||
_DOMEmbedElement.setAttribute("wmode", "transparent");
|
||||
_DOMEmbedElement.width = "100%";
|
||||
_DOMEmbedElement.height = "100%";
|
||||
|
||||
// IE requires this thing to be in the _DOMElement and not the _DOMObjectElement.
|
||||
_DOMElement.appendChild(_DOMEmbedElement);
|
||||
|
||||
_DOMElement.appendChild(_DOMObjectElement);
|
||||
if (!CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
|
||||
{
|
||||
_DOMObjectElement = document.createElement(@"object");
|
||||
_DOMObjectElement.width = @"100%";
|
||||
_DOMObjectElement.height = @"100%";
|
||||
_DOMObjectElement.style.top = @"0px";
|
||||
_DOMObjectElement.style.left = @"0px";
|
||||
_DOMObjectElement.type = @"application/x-shockwave-flash";
|
||||
_DOMObjectElement.setAttribute(@"classid", IEFlashCLSID);
|
||||
|
||||
_DOMParamElement = document.createElement(@"param");
|
||||
_DOMParamElement.name = @"movie";
|
||||
|
||||
_DOMInnerObjectElement = document.createElement(@"object");
|
||||
_DOMInnerObjectElement.width = @"100%";
|
||||
_DOMInnerObjectElement.height = @"100%";
|
||||
|
||||
_DOMObjectElement.appendChild(_DOMParamElement);
|
||||
_DOMObjectElement.appendChild(_DOMInnerObjectElement);
|
||||
|
||||
_DOMElement.appendChild(_DOMObjectElement);
|
||||
}
|
||||
else
|
||||
[self _rebuildIEObjects];
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -87,10 +83,13 @@
|
||||
|
||||
_flashMovie = aFlashMovie;
|
||||
|
||||
_DOMParamElement.value = aFlashMovie._fileName;
|
||||
|
||||
if (_DOMEmbedElement)
|
||||
_DOMEmbedElement.src = aFlashMovie._fileName;
|
||||
if (!CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
|
||||
{
|
||||
_DOMParamElement.value = [aFlashMovie filename];
|
||||
_DOMInnerObjectElement.data = [aFlashMovie filename];
|
||||
}
|
||||
else
|
||||
[self _rebuildIEObjects];
|
||||
}
|
||||
|
||||
- (CPFlashMovie)flashMovie
|
||||
@@ -100,33 +99,28 @@
|
||||
|
||||
- (void)setFlashVars:(CPDictionary)aDictionary
|
||||
{
|
||||
_flashVars = aDictionary;
|
||||
|
||||
var varString = @"",
|
||||
enumerator = [_flashVars keyEnumerator];
|
||||
enumerator = [aDictionary keyEnumerator];
|
||||
|
||||
var key;
|
||||
while (key = [enumerator nextObject])
|
||||
varString = [varString stringByAppendingFormat:@"&%@=%@", key, [_flashVars objectForKey:key]];
|
||||
varString = [varString stringByAppendingFormat:@"&%@=%@", key, [aDictionary objectForKey:key]];
|
||||
|
||||
var param = document.createElement(@"param");
|
||||
param.name = @"flashvars";
|
||||
param.value = varString;
|
||||
if (!_params)
|
||||
_params = [CPDictionary dictionary];
|
||||
|
||||
_DOMObjectElement.appendChild(param);
|
||||
|
||||
if (_DOMEmbedElement)
|
||||
_DOMEmbedElement.setAttribute(@"flashvars", varString);
|
||||
[_params setObject:varString forKey:@"flashvars"];
|
||||
[self setParameters:_params];
|
||||
}
|
||||
|
||||
- (CPDictionary)flashVars
|
||||
{
|
||||
return _flashVars;
|
||||
return [_params objectForKey:@"flashvars"];
|
||||
}
|
||||
|
||||
- (void)setParameters:(CPDictionary)aDictionary
|
||||
{
|
||||
if (_paramElements)
|
||||
if (_paramElements && !CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
|
||||
{
|
||||
var elements = [_paramElements allValues],
|
||||
count = [elements count];
|
||||
@@ -136,21 +130,27 @@
|
||||
}
|
||||
|
||||
_params = aDictionary;
|
||||
_paramElements = [CPDictionary dictionary];
|
||||
|
||||
var enumerator = [_params keyEnumerator],
|
||||
key;
|
||||
|
||||
while (key = [enumerator nextObject])
|
||||
if (!CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
|
||||
{
|
||||
var param = document.createElement(@"param");
|
||||
param.name = key;
|
||||
param.value = [_params objectForKey:key];
|
||||
_paramElements = [CPDictionary dictionary];
|
||||
|
||||
_DOMObjectElement.appendChild(param);
|
||||
var enumerator = [_params keyEnumerator],
|
||||
key;
|
||||
|
||||
[_paramElements setObject:param forKey:key];
|
||||
while (key = [enumerator nextObject] && _DOMObjectElement)
|
||||
{
|
||||
var param = document.createElement(@"param");
|
||||
param.name = key;
|
||||
param.value = [_params objectForKey:key];
|
||||
|
||||
_DOMObjectElement.appendChild(param);
|
||||
|
||||
[_paramElements setObject:param forKey:key];
|
||||
}
|
||||
}
|
||||
else
|
||||
[self _rebuildIEObjects];
|
||||
}
|
||||
|
||||
- (CPDictionary)parameters
|
||||
@@ -158,6 +158,25 @@
|
||||
return _params;
|
||||
}
|
||||
|
||||
- (void)_rebuildIEObjects
|
||||
{
|
||||
_DOMElement.innerHTML = @"";
|
||||
if (![_flashMovie filename])
|
||||
return;
|
||||
|
||||
var paramString = [CPString stringWithFormat:@"<param name='movie' value='%@' />", [_flashMovie filename]],
|
||||
paramEnumerator = [_params keyEnumerator],
|
||||
key;
|
||||
|
||||
while (key = [paramEnumerator nextObject])
|
||||
paramString = [paramString stringByAppendingFormat:@"<param name='%@' value='%@' />", key, [_params objectForKey:key]];
|
||||
|
||||
_DOMObjectElement = document.createElement(@"object");
|
||||
_DOMElement.appendChild(_DOMObjectElement);
|
||||
|
||||
_DOMObjectElement.outerHTML = [CPString stringWithFormat:@"<object classid=%@ width=%@ height=%@>%@</object>", IEFlashCLSID, CGRectGetWidth([self bounds]), CGRectGetHeight([self bounds]), paramString];
|
||||
}
|
||||
|
||||
- (void)mouseDragged:(CPEvent)anEvent
|
||||
{
|
||||
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
#include "../CoreGraphics/CGGeometry.h"
|
||||
#include "../Platform/Platform.h"
|
||||
|
||||
@import "_CPMenuWindow.j"
|
||||
|
||||
|
||||
+18
-17
@@ -144,12 +144,11 @@ var CPSplitViewHorizontalImage = nil,
|
||||
{
|
||||
if (_isPaneSplitter == shouldBePaneSplitter)
|
||||
return;
|
||||
|
||||
|
||||
_isPaneSplitter = shouldBePaneSplitter;
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
_DOMDividerElements = [];
|
||||
#endif
|
||||
if(_DOMDividerElements[_drawingDivider])
|
||||
[self _setupDOMDivider]
|
||||
|
||||
// The divider changes size when pane splitter mode is toggled, so the
|
||||
// subviews need to change size too.
|
||||
@@ -160,7 +159,6 @@ var CPSplitViewHorizontalImage = nil,
|
||||
- (void)didAddSubview:(CPView)aSubview
|
||||
{
|
||||
_needsResizeSubviews = YES;
|
||||
// [self adjustSubviews];
|
||||
}
|
||||
|
||||
- (BOOL)isSubviewCollapsed:(CPView)subview
|
||||
@@ -216,16 +214,7 @@ var CPSplitViewHorizontalImage = nil,
|
||||
|
||||
CPDOMDisplayServerAppendChild(_DOMElement, _DOMDividerElements[_drawingDivider]);
|
||||
|
||||
if (_isPaneSplitter)
|
||||
{
|
||||
_DOMDividerElements[_drawingDivider].style.backgroundColor = "#A5A5A5";
|
||||
_DOMDividerElements[_drawingDivider].style.backgroundImage = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
_DOMDividerElements[_drawingDivider].style.backgroundColor = "";
|
||||
_DOMDividerElements[_drawingDivider].style.backgroundImage = "url('"+_dividerImagePath+"')";
|
||||
}
|
||||
[self _setupDOMDivider];
|
||||
}
|
||||
|
||||
CPDOMDisplayServerSetStyleLeftTop(_DOMDividerElements[_drawingDivider], NULL, _CGRectGetMinX(aRect), _CGRectGetMinY(aRect));
|
||||
@@ -233,6 +222,20 @@ var CPSplitViewHorizontalImage = nil,
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)_setupDOMDivider
|
||||
{
|
||||
if (_isPaneSplitter)
|
||||
{
|
||||
_DOMDividerElements[_drawingDivider].style.backgroundColor = "#A5A5A5";
|
||||
_DOMDividerElements[_drawingDivider].style.backgroundImage = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
_DOMDividerElements[_drawingDivider].style.backgroundColor = "";
|
||||
_DOMDividerElements[_drawingDivider].style.backgroundImage = "url('"+_dividerImagePath+"')";
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewWillDraw
|
||||
{
|
||||
[self _adjustSubviewsWithCalculatedSize];
|
||||
@@ -515,8 +518,6 @@ var CPSplitViewHorizontalImage = nil,
|
||||
}
|
||||
else if (totalSizableSpace && !isSizable)
|
||||
viewFrame.size[_sizeComponent] = [view frame].size[_sizeComponent];
|
||||
else
|
||||
alert("SHOULD NEVER GET HERE");
|
||||
|
||||
bounds.origin[_originComponent] += viewFrame.size[_sizeComponent] + dividerThickness;
|
||||
|
||||
|
||||
+182
-188
@@ -481,10 +481,10 @@ window.setTimeout(function(){
|
||||
[self setSelectionHightlightColor:[CPColor selectionColorSourceView]];
|
||||
_destinationDragStyle = CPTableViewDraggingDestinationFeedbackStyleSourceList;
|
||||
}
|
||||
else
|
||||
{
|
||||
[self setSelectionHightlightColor:[CPColor selectionColor]];
|
||||
_destinationDragStyle = CPTableViewDraggingDestinationFeedbackStyleRegular;
|
||||
else
|
||||
{
|
||||
[self setSelectionHightlightColor:[CPColor selectionColor]];
|
||||
_destinationDragStyle = CPTableViewDraggingDestinationFeedbackStyleRegular;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -656,7 +656,7 @@ window.setTimeout(function(){
|
||||
|
||||
- (void)selectRowIndexes:(CPIndexSet)rows byExtendingSelection:(BOOL)shouldExtendSelection
|
||||
{
|
||||
if (([rows firstIndex] != CPNotFound && [rows firstIndex] < 0) || [rows lastIndex] >= [self numberOfRows])
|
||||
if ([rows isEqualToIndexSet:_selectedRowIndexes] || (([rows firstIndex] != CPNotFound && [rows firstIndex] < 0) || [rows lastIndex] >= [self numberOfRows]))
|
||||
return;
|
||||
|
||||
// We deselect all columns when selecting rows.
|
||||
@@ -1433,55 +1433,63 @@ window.setTimeout(function(){
|
||||
}
|
||||
|
||||
- (CPImage)dragImageForRowsWithIndexes:(CPIndexSet)dragRows
|
||||
tableColumns:(CPArray)theTableColumns
|
||||
event:(CPEvent)dragEvent
|
||||
offset:(CPPointPointer)dragImageOffset
|
||||
tableColumns:(CPArray)theTableColumns
|
||||
event:(CPEvent)dragEvent
|
||||
offset:(CPPointPointer)dragImageOffset
|
||||
{
|
||||
return [[CPImage alloc] initWithContentsOfFile:@"Frameworks/AppKit/Resources/GenericFile.png" size:CGSizeMake(32,32)];
|
||||
}
|
||||
|
||||
- (CPView)dragViewForRowsWithIndexes:(CPIndexSet)theDraggedRows
|
||||
tableColumns:(CPArray)theTableColumns
|
||||
event:(CPEvent)theDragEvent
|
||||
offset:(CPPoint)dragViewOffset
|
||||
tableColumns:(CPArray)theTableColumns
|
||||
event:(CPEvent)theDragEvent
|
||||
offset:(CPPoint)dragViewOffset
|
||||
{
|
||||
var size = [self bounds].size,
|
||||
view = [[CPView alloc] initWithFrame:CPMakeRect(dragViewOffset.x, dragViewOffset.y, size.width, size.height)];
|
||||
|
||||
[view setBackgroundColor:[CPColor clearColor]];
|
||||
[view setAlphaValue:0.7];
|
||||
|
||||
// We have to fetch all the data views for the selected rows and columns
|
||||
// After that we can copy these add them to a transparent drag view and use that drag view
|
||||
// to make it appear we are dragging images of those rows (as you would do in regular Cocoa)
|
||||
var firstExposedColumn = [_exposedColumns firstIndex],
|
||||
exposedLength = [_exposedColumns lastIndex] - firstExposedColumn + 1,
|
||||
columns = [];
|
||||
|
||||
[_exposedColumns getIndexes:columns maxCount:-1 inIndexRange:CPMakeRange(firstExposedColumn, exposedLength)];
|
||||
|
||||
var columnIndex = [columns count],
|
||||
draggedDataViews = [],
|
||||
dragViewHeight = 0.0;
|
||||
|
||||
while (columnIndex--) {
|
||||
var column = [_tableColumns objectAtIndex:columnIndex],
|
||||
yOffset = 0,
|
||||
rowIndex = CPNotFound;
|
||||
|
||||
while ((rowIndex = [_selectedRowIndexes indexGreaterThanIndex:rowIndex]) !== CPNotFound)
|
||||
{
|
||||
var dataView = [self _newDataViewForRow:rowIndex tableColumn:column];
|
||||
|
||||
[dataView setBackgroundColor:[CPColor clearColor]];
|
||||
[dataView setFrame:[self frameOfDataViewAtColumn:columnIndex row:rowIndex]];
|
||||
[dataView setObjectValue:[self _objectValueForTableColumn:column row:rowIndex]];
|
||||
|
||||
[view addSubview:dataView];
|
||||
}
|
||||
}
|
||||
|
||||
return view;
|
||||
var bounds = [self bounds],
|
||||
view = [[CPView alloc] initWithFrame:bounds];
|
||||
|
||||
[view setBackgroundColor:[CPColor clearColor]];
|
||||
[view setAlphaValue:0.7];
|
||||
|
||||
// We have to fetch all the data views for the selected rows and columns
|
||||
// After that we can copy these add them to a transparent drag view and use that drag view
|
||||
// to make it appear we are dragging images of those rows (as you would do in regular Cocoa)
|
||||
var firstExposedColumn = [_exposedColumns firstIndex],
|
||||
firstExposedRow = [_exposedRows firstIndex],
|
||||
exposedColumnsLength = [_exposedColumns lastIndex] - firstExposedColumn + 1,
|
||||
exposedRowsLength = [_exposedRows lastIndex] - firstExposedRow + 1,
|
||||
columns = [],
|
||||
rows = [];
|
||||
|
||||
[_exposedColumns getIndexes:columns maxCount:-1 inIndexRange:CPMakeRange(firstExposedColumn, exposedColumnsLength)];
|
||||
[theDraggedRows getIndexes:rows maxCount:-1 inIndexRange:CPMakeRange(firstExposedRow, exposedRowsLength)];
|
||||
|
||||
var columnIndex = [columns count];
|
||||
|
||||
while (columnIndex--)
|
||||
{
|
||||
var column = columns[columnIndex],
|
||||
tableColumn = [_tableColumns objectAtIndex:column],
|
||||
rowIndex = [rows count];
|
||||
|
||||
while (rowIndex--)
|
||||
{
|
||||
var row = rows[rowIndex];
|
||||
var dataView = [self _newDataViewForRow:row tableColumn:tableColumn];
|
||||
|
||||
[dataView setBackgroundColor:[CPColor clearColor]];
|
||||
[dataView setFrame:[self frameOfDataViewAtColumn:column row:row]];
|
||||
[dataView setObjectValue:[self _objectValueForTableColumn:tableColumn row:row]];
|
||||
|
||||
[view addSubview:dataView];
|
||||
}
|
||||
}
|
||||
|
||||
var dragPoint = [self convertPoint:[theDragEvent locationInWindow] fromView:nil];
|
||||
dragViewOffset.x = CGRectGetWidth(bounds)/2 - dragPoint.x;
|
||||
dragViewOffset.y = CGRectGetHeight(bounds)/2 - dragPoint.y;
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
- (void)setDraggingSourceOperationMask:(CPDragOperation)mask forLocal:(BOOL)isLocal
|
||||
@@ -1554,7 +1562,6 @@ window.setTimeout(function(){
|
||||
|
||||
- (id)_objectValueForTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRowIndex
|
||||
{
|
||||
CPLog.debug(@"_objectValueForTableColumn:%@ row: %@", aTableColumn, aRowIndex);
|
||||
var tableColumnUID = [aTableColumn UID],
|
||||
tableColumnObjectValues = _objectValues[tableColumnUID];
|
||||
|
||||
@@ -1572,7 +1579,6 @@ window.setTimeout(function(){
|
||||
tableColumnObjectValues[aRowIndex] = objectValue;
|
||||
}
|
||||
|
||||
CPLog.debug(@"return %@", objectValue);
|
||||
return objectValue;
|
||||
}
|
||||
|
||||
@@ -1976,7 +1982,7 @@ window.setTimeout(function(){
|
||||
indexes = [],
|
||||
rectSelector = @selector(rectOfRow:);
|
||||
|
||||
[_selectionHightlightColor setFill];
|
||||
[_selectionHightlightColor setFill];
|
||||
|
||||
|
||||
if ([_selectedRowIndexes count] >= 1)
|
||||
@@ -2148,10 +2154,7 @@ window.setTimeout(function(){
|
||||
// if the table has drag support then we use mouseUp to select a single row.
|
||||
// otherwise it uses mouse down.
|
||||
if(!(_implementedDataSourceMethods & CPTableViewDataSource_tableView_writeRowsWithIndexes_toPasteboard_))
|
||||
{
|
||||
_previouslySelectedRowIndexes = nil;
|
||||
[self _updateSelectionWithMouseAtRow:row];
|
||||
}
|
||||
|
||||
[[self window] makeFirstResponder:self];
|
||||
return YES;
|
||||
@@ -2160,10 +2163,8 @@ window.setTimeout(function(){
|
||||
/* ignore */
|
||||
- (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint
|
||||
{
|
||||
|
||||
var row = [self rowAtPoint:aPoint];
|
||||
|
||||
|
||||
// begin the drag is the datasource lets us, we've move at least +-3px vertical or horizontal, or we're dragging from selected rows and we haven't begun a drag session
|
||||
if
|
||||
(
|
||||
@@ -2175,7 +2176,7 @@ window.setTimeout(function(){
|
||||
)
|
||||
)
|
||||
{
|
||||
if([_selectedRowIndexes containsIndex:row])
|
||||
if ([_selectedRowIndexes containsIndex:row])
|
||||
_draggedRowIndexes = [[CPIndexSet alloc] initWithIndexSet:_selectedRowIndexes];
|
||||
else
|
||||
_draggedRowIndexes = [CPIndexSet indexSetWithIndex:row];
|
||||
@@ -2184,33 +2185,34 @@ window.setTimeout(function(){
|
||||
//ask the datasource for the data
|
||||
var pboard = [CPPasteboard pasteboardWithName:CPDragPboard];
|
||||
|
||||
if([self canDragRowsWithIndexes:_draggedRowIndexes atPoint:aPoint] && [_dataSource tableView:self writeRowsWithIndexes:_draggedRowIndexes toPasteboard:pboard])
|
||||
if ([self canDragRowsWithIndexes:_draggedRowIndexes atPoint:aPoint] && [_dataSource tableView:self writeRowsWithIndexes:_draggedRowIndexes toPasteboard:pboard])
|
||||
{
|
||||
var currentEvent = [CPApp currentEvent],
|
||||
offset = CPPointMakeZero();
|
||||
|
||||
// We deviate from the default Cocoa implementation here by asking for a view in stead of an image
|
||||
// We support both, but the view prefered over the image because we can mimic the rows we are dragging
|
||||
// by re-creating the data views for the dragged rows
|
||||
var view = [self dragViewForRowsWithIndexes:_draggedRowIndexes
|
||||
tableColumns:_exposedColumns
|
||||
event:currentEvent
|
||||
offset:CPPointMakeZero()];
|
||||
|
||||
if (!view) {
|
||||
var image = [self dragImageForRowsWithIndexes:_draggedRowIndexes
|
||||
tableColumns:_exposedColumns
|
||||
event:currentEvent
|
||||
offset:CPPointMakeZero()];
|
||||
|
||||
view = [[CPImageView alloc] initWithFrame:CPMakeRect(aPoint.x, aPoint.y, [image size].width, [image size].height)];
|
||||
[view setImage:image];
|
||||
|
||||
offset = aPoint;
|
||||
}
|
||||
|
||||
[self dragView:view at:offset offset:CPPointMakeZero() event:[CPApp currentEvent] pasteboard:pboard source:self slideBack:YES];
|
||||
|
||||
var currentEvent = [CPApp currentEvent],
|
||||
offset = CPPointMakeZero(),
|
||||
tableColumns = [_tableColumns objectsAtIndexes:_exposedColumns];
|
||||
|
||||
// We deviate from the default Cocoa implementation here by asking for a view in stead of an image
|
||||
// We support both, but the view prefered over the image because we can mimic the rows we are dragging
|
||||
// by re-creating the data views for the dragged rows
|
||||
var view = [self dragViewForRowsWithIndexes:_draggedRowIndexes
|
||||
tableColumns:tableColumns
|
||||
event:currentEvent
|
||||
offset:offset];
|
||||
|
||||
if (!view)
|
||||
{
|
||||
var image = [self dragImageForRowsWithIndexes:_draggedRowIndexes
|
||||
tableColumns:tableColumns
|
||||
event:currentEvent
|
||||
offset:offset];
|
||||
view = [[CPImageView alloc] initWithFrame:CPMakeRect(0, 0, [image size].width, [image size].height)];
|
||||
[view setImage:image];
|
||||
}
|
||||
|
||||
var bounds = [view bounds];
|
||||
var viewLocation = CPPointMake(aPoint.x - CGRectGetWidth(bounds)/2 + offset.x, aPoint.y - CGRectGetHeight(bounds)/2 + offset.y);
|
||||
[self dragView:view at:viewLocation offset:CPPointMakeZero() event:[CPApp currentEvent] pasteboard:pboard source:self slideBack:YES];
|
||||
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
@@ -2254,15 +2256,11 @@ window.setTimeout(function(){
|
||||
return;
|
||||
}
|
||||
// if the table has drag support then we use mouseUp to select a single row.
|
||||
_previouslySelectedRowIndexes = nil;
|
||||
_previouslySelectedRowIndexes = [_selectedRowIndexes copy];
|
||||
[self _updateSelectionWithMouseAtRow:rowIndex];
|
||||
}
|
||||
}
|
||||
|
||||
if (![_previouslySelectedRowIndexes isEqualToIndexSet:_selectedRowIndexes])
|
||||
[self _noteSelectionDidChange];
|
||||
|
||||
|
||||
if (mouseIsUp
|
||||
&& (_implementedDataSourceMethods & CPTableViewDataSource_tableView_setObjectValue_forTableColumn_row_)
|
||||
&& !_trackingPointMovedOutOfClickSlop
|
||||
@@ -2574,13 +2572,9 @@ window.setTimeout(function(){
|
||||
if ([newSelection isEqualToIndexSet:_selectedRowIndexes])
|
||||
return;
|
||||
|
||||
if (!_previouslySelectedRowIndexes)
|
||||
_previouslySelectedRowIndexes = [_selectedRowIndexes copy];
|
||||
|
||||
[self selectRowIndexes:newSelection byExtendingSelection:NO];
|
||||
|
||||
[self _noteSelectionIsChanging];
|
||||
|
||||
}
|
||||
|
||||
- (void)_noteSelectionIsChanging
|
||||
@@ -2614,108 +2608,108 @@ window.setTimeout(function(){
|
||||
[self interpretKeyEvents:[CPArray arrayWithObject:anEvent]];
|
||||
}
|
||||
|
||||
- (void)interpretKeyEvents:(CPArray)events
|
||||
- (void)moveDown:(id)sender
|
||||
{
|
||||
[super interpretKeyEvents:events];
|
||||
if (_implementedDelegateMethods & CPTableViewDelegate_selectionShouldChangeInTableView_ &&
|
||||
![_delegate selectionShouldChangeInTableView:self])
|
||||
return;
|
||||
|
||||
for(var i = 0; i < [events count]; i++)
|
||||
var anEvent = [CPApp currentEvent];
|
||||
if([[self selectedRowIndexes] count] > 0)
|
||||
{
|
||||
var anEvent = [events objectAtIndex:i],
|
||||
key = [anEvent keyCode];
|
||||
var extend = NO;
|
||||
|
||||
if(key === CPDeleteKeyCode && [_delegate respondsToSelector: @selector(tableViewDeleteKeyPressed:)])
|
||||
[_delegate tableViewDeleteKeyPressed:self];
|
||||
if(([anEvent modifierFlags] & CPShiftKeyMask) && _allowsMultipleSelection)
|
||||
extend = YES;
|
||||
|
||||
if(key === CPUpArrowKeyCode)
|
||||
{
|
||||
if([[self selectedRowIndexes] count] > 0)
|
||||
{
|
||||
var extend = NO;
|
||||
|
||||
if(([anEvent modifierFlags] & CPShiftKeyMask) && _allowsMultipleSelection)
|
||||
extend = YES;
|
||||
|
||||
var i = [[self selectedRowIndexes] firstIndex];
|
||||
if(i > 0)
|
||||
i--; //set index to the prev row before the first row selected
|
||||
}
|
||||
else
|
||||
{
|
||||
var extend = NO;
|
||||
//no rows are currently selected
|
||||
if([self numberOfRows] > 0)
|
||||
var i = [self numberOfRows] - 1; //select the first row
|
||||
}
|
||||
|
||||
|
||||
if(_implementedDelegateMethods & CPTableViewDelegate_tableView_shouldSelectRow_)
|
||||
{
|
||||
|
||||
while((![_delegate tableView:self shouldSelectRow:i]) && i > 0)
|
||||
{
|
||||
//check to see if the row can be selected if it can't be then see if the prev row can be selected
|
||||
i--;
|
||||
}
|
||||
|
||||
//if the index still can be selected after the loop then just return
|
||||
if(![_delegate tableView:self shouldSelectRow:i])
|
||||
return;
|
||||
}
|
||||
|
||||
[self selectRowIndexes:[CPIndexSet indexSetWithIndex:i] byExtendingSelection:extend];
|
||||
|
||||
if(i)
|
||||
{
|
||||
[self scrollRowToVisible:i];
|
||||
[self _noteSelectionDidChange];
|
||||
}
|
||||
}
|
||||
|
||||
if(key == CPDownArrowKeyCode)
|
||||
{
|
||||
if([[self selectedRowIndexes] count] > 0)
|
||||
{
|
||||
var extend = NO;
|
||||
|
||||
if(([anEvent modifierFlags] & CPShiftKeyMask) && _allowsMultipleSelection)
|
||||
extend = YES;
|
||||
|
||||
var i = [[self selectedRowIndexes] lastIndex];
|
||||
if(i<[self numberOfRows] - 1)
|
||||
i++; //set index to the next row after the last row selected
|
||||
}
|
||||
else
|
||||
{
|
||||
var extend = NO;
|
||||
//no rows are currently selected
|
||||
if([self numberOfRows] > 0)
|
||||
var i = 0; //select the first row
|
||||
}
|
||||
|
||||
|
||||
if(_implementedDelegateMethods & CPTableViewDelegate_tableView_shouldSelectRow_)
|
||||
{
|
||||
|
||||
while((![_delegate tableView:self shouldSelectRow:i]) && i<[self numberOfRows])
|
||||
{
|
||||
//check to see if the row can be selected if it can't be then see if the next row can be selected
|
||||
i++;
|
||||
}
|
||||
|
||||
//if the index still can be selected after the loop then just return
|
||||
if(![_delegate tableView:self shouldSelectRow:i])
|
||||
return;
|
||||
}
|
||||
|
||||
[self selectRowIndexes:[CPIndexSet indexSetWithIndex:i] byExtendingSelection:extend];
|
||||
|
||||
if(i)
|
||||
{
|
||||
[self scrollRowToVisible:i];
|
||||
[self _noteSelectionDidChange];
|
||||
}
|
||||
}
|
||||
var i = [[self selectedRowIndexes] lastIndex];
|
||||
if(i<[self numberOfRows] - 1)
|
||||
i++; //set index to the next row after the last row selected
|
||||
}
|
||||
else
|
||||
{
|
||||
var extend = NO;
|
||||
//no rows are currently selected
|
||||
if([self numberOfRows] > 0)
|
||||
var i = 0; //select the first row
|
||||
}
|
||||
|
||||
|
||||
if(_implementedDelegateMethods & CPTableViewDelegate_tableView_shouldSelectRow_)
|
||||
{
|
||||
|
||||
while((![_delegate tableView:self shouldSelectRow:i]) && i<[self numberOfRows])
|
||||
{
|
||||
//check to see if the row can be selected if it can't be then see if the next row can be selected
|
||||
i++;
|
||||
}
|
||||
|
||||
//if the index still can be selected after the loop then just return
|
||||
if(![_delegate tableView:self shouldSelectRow:i])
|
||||
return;
|
||||
}
|
||||
|
||||
[self selectRowIndexes:[CPIndexSet indexSetWithIndex:i] byExtendingSelection:extend];
|
||||
|
||||
if(i)
|
||||
{
|
||||
[self scrollRowToVisible:i];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)moveUp:(id)sender
|
||||
{
|
||||
if (_implementedDelegateMethods & CPTableViewDelegate_selectionShouldChangeInTableView_ &&
|
||||
![_delegate selectionShouldChangeInTableView:self])
|
||||
return;
|
||||
|
||||
var anEvent = [CPApp currentEvent];
|
||||
if([[self selectedRowIndexes] count] > 0)
|
||||
{
|
||||
var extend = NO;
|
||||
|
||||
if(([anEvent modifierFlags] & CPShiftKeyMask) && _allowsMultipleSelection)
|
||||
extend = YES;
|
||||
|
||||
var i = [[self selectedRowIndexes] firstIndex];
|
||||
if(i > 0)
|
||||
i--; //set index to the prev row before the first row selected
|
||||
}
|
||||
else
|
||||
{
|
||||
var extend = NO;
|
||||
//no rows are currently selected
|
||||
if([self numberOfRows] > 0)
|
||||
var i = [self numberOfRows] - 1; //select the first row
|
||||
}
|
||||
|
||||
|
||||
if(_implementedDelegateMethods & CPTableViewDelegate_tableView_shouldSelectRow_)
|
||||
{
|
||||
|
||||
while((![_delegate tableView:self shouldSelectRow:i]) && i > 0)
|
||||
{
|
||||
//check to see if the row can be selected if it can't be then see if the prev row can be selected
|
||||
i--;
|
||||
}
|
||||
|
||||
//if the index still can be selected after the loop then just return
|
||||
if(![_delegate tableView:self shouldSelectRow:i])
|
||||
return;
|
||||
}
|
||||
|
||||
[self selectRowIndexes:[CPIndexSet indexSetWithIndex:i] byExtendingSelection:extend];
|
||||
|
||||
if(i)
|
||||
{
|
||||
[self scrollRowToVisible:i];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)deleteBackward:(id)sender
|
||||
{
|
||||
if([_delegate respondsToSelector: @selector(tableViewDeleteKeyPressed:)])
|
||||
[_delegate tableViewDeleteKeyPressed:self];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
+30
-21
@@ -799,41 +799,50 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
- (void)copy:(id)sender
|
||||
{
|
||||
var selectedRange = [self selectedRange];
|
||||
if (![CPPlatform isBrowser])
|
||||
{
|
||||
var selectedRange = [self selectedRange];
|
||||
|
||||
if (selectedRange.length < 1)
|
||||
return;
|
||||
if (selectedRange.length < 1)
|
||||
return;
|
||||
|
||||
var pasteboard = [CPPasteboard generalPasteboard],
|
||||
stringValue = [self stringValue],
|
||||
stringForPasting = [stringValue substringWithRange:selectedRange];
|
||||
var pasteboard = [CPPasteboard generalPasteboard],
|
||||
stringValue = [self stringValue],
|
||||
stringForPasting = [stringValue substringWithRange:selectedRange];
|
||||
|
||||
[pasteboard declareTypes:[CPStringPboardType] owner:nil];
|
||||
[pasteboard setString:stringForPasting forType:CPStringPboardType];
|
||||
[pasteboard declareTypes:[CPStringPboardType] owner:nil];
|
||||
[pasteboard setString:stringForPasting forType:CPStringPboardType];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)cut:(id)sender
|
||||
{
|
||||
[self copy:sender];
|
||||
[self deleteBackwards:sender];
|
||||
if (![CPPlatform isBrowser])
|
||||
{
|
||||
[self copy:sender];
|
||||
[self deleteBackwards:sender];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)paste:(id)sender
|
||||
{
|
||||
var pasteboard = [CPPasteboard generalPasteboard];
|
||||
|
||||
if (![[pasteboard types] containsObject:CPStringPboardType])
|
||||
return;
|
||||
if (![CPPlatform isBrowser])
|
||||
{
|
||||
var pasteboard = [CPPasteboard generalPasteboard];
|
||||
|
||||
[self deleteBackwards:sender];
|
||||
if (![[pasteboard types] containsObject:CPStringPboardType])
|
||||
return;
|
||||
|
||||
var selectedRange = [self selectedRange],
|
||||
stringValue = [self stringValue],
|
||||
pasteString = [pasteboard stringForType:CPStringPboardType],
|
||||
newValue = [stringValue stringByReplacingCharactersInRange:selectedRange withString:pasteString];
|
||||
[self deleteBackwards:sender];
|
||||
|
||||
[self setStringValue:newValue];
|
||||
[self setSelectedRange:CPMakeRange(selectedRange.location+pasteString.length, 0)];
|
||||
var selectedRange = [self selectedRange],
|
||||
stringValue = [self stringValue],
|
||||
pasteString = [pasteboard stringForType:CPStringPboardType],
|
||||
newValue = [stringValue stringByReplacingCharactersInRange:selectedRange withString:pasteString];
|
||||
|
||||
[self setStringValue:newValue];
|
||||
[self setSelectedRange:CPMakeRange(selectedRange.location+pasteString.length, 0)];
|
||||
}
|
||||
}
|
||||
|
||||
- (CPRange)selectedRange
|
||||
|
||||
+118
-123
@@ -1,11 +1,25 @@
|
||||
/*
|
||||
* CPViewAnimation.j
|
||||
* CPFlashView.j
|
||||
* AppKit
|
||||
*
|
||||
* Created by Klaas Pieter Annema on September 3, 2009.
|
||||
* Copyright 2009, Sofa BV
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
@import <AppKit/CPAnimation.j>
|
||||
|
||||
CPViewAnimationTargetKey = @"CPViewAnimationTarget";
|
||||
@@ -18,167 +32,148 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOut";
|
||||
|
||||
@implementation CPViewAnimation : CPAnimation
|
||||
{
|
||||
CPArray _viewAnimations;
|
||||
CPArray _viewAnimations;
|
||||
}
|
||||
|
||||
- (id)initWithViewAnimations:(CPArray)viewAnimations
|
||||
{
|
||||
if(self = [super initWithDuration:0.5 animationCurve:CPAnimationLinear])
|
||||
{
|
||||
[self setViewAnimations:viewAnimations];
|
||||
}
|
||||
return self;
|
||||
if (self = [super initWithDuration:0.5 animationCurve:CPAnimationLinear])
|
||||
{
|
||||
[self setViewAnimations:viewAnimations];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
// =============
|
||||
// = ANIMATION =
|
||||
// =============
|
||||
- (void)startAnimation
|
||||
{
|
||||
var animationIndex = [_viewAnimations count];
|
||||
|
||||
while (animationIndex--)
|
||||
{
|
||||
var dictionary = [_viewAnimations objectAtIndex:animationIndex];
|
||||
|
||||
var view = [self _targetView:dictionary],
|
||||
startFrame = [self _startFrame:dictionary];
|
||||
|
||||
[view setFrame:startFrame];
|
||||
|
||||
var effect = [self _effect:dictionary];
|
||||
|
||||
if (effect === CPViewAnimationFadeInEffect)
|
||||
{
|
||||
[view setAlphaValue:0.0];
|
||||
[view setHidden:NO];
|
||||
}
|
||||
else if (effect === CPViewAnimationFadeOutEffect)
|
||||
[view setAlphaValue:1.0];
|
||||
}
|
||||
|
||||
[super startAnimation];
|
||||
var animationIndex = [_viewAnimations count];
|
||||
while (animationIndex--)
|
||||
{
|
||||
var dictionary = [_viewAnimations objectAtIndex:animationIndex],
|
||||
view = [self _targetView:dictionary],
|
||||
startFrame = [self _startFrame:dictionary];
|
||||
|
||||
[view setFrame:startFrame];
|
||||
|
||||
var effect = [self _effect:dictionary];
|
||||
if (effect === CPViewAnimationFadeInEffect)
|
||||
{
|
||||
[view setAlphaValue:0.0];
|
||||
[view setHidden:NO];
|
||||
}
|
||||
else if (effect === CPViewAnimationFadeOutEffect)
|
||||
[view setAlphaValue:1.0];
|
||||
}
|
||||
|
||||
[super startAnimation];
|
||||
}
|
||||
|
||||
- (void)setCurrentProgress:(NSAnimationProgress)progress
|
||||
{
|
||||
[super setCurrentProgress:progress];
|
||||
|
||||
var animationIndex = [_viewAnimations count];
|
||||
while (animationIndex--)
|
||||
{
|
||||
var dictionary = [_viewAnimations objectAtIndex:animationIndex];
|
||||
|
||||
// Update the view's frame
|
||||
var view = [self _targetView:dictionary]
|
||||
startFrame = [self _startFrame:dictionary]
|
||||
endFrame = [self _endFrame:dictionary]
|
||||
differenceFrame = CPRectMakeZero();
|
||||
|
||||
differenceFrame.origin.x = endFrame.origin.x - startFrame.origin.x;
|
||||
differenceFrame.origin.y = endFrame.origin.y - startFrame.origin.y;
|
||||
differenceFrame.size.width = endFrame.size.width - startFrame.size.width;
|
||||
differenceFrame.size.height = endFrame.size.height - startFrame.size.height;
|
||||
|
||||
var intermediateFrame = CPRectMakeZero();
|
||||
intermediateFrame.origin.x = startFrame.origin.x + differenceFrame.origin.x * progress;
|
||||
intermediateFrame.origin.y = startFrame.origin.y + differenceFrame.origin.y * progress;
|
||||
intermediateFrame.size.width = startFrame.size.width + differenceFrame.size.width * progress;
|
||||
intermediateFrame.size.height = startFrame.size.height + differenceFrame.size.height * progress;
|
||||
|
||||
[view setFrame:intermediateFrame];
|
||||
|
||||
// Update the view's alpha value
|
||||
var effect = [self _effect:dictionary];
|
||||
|
||||
if (effect === CPViewAnimationFadeInEffect)
|
||||
[view setAlphaValue:1.0 * progress];
|
||||
else if (effect === CPViewAnimationFadeOutEffect)
|
||||
[view setAlphaValue:1.0 + ( 0.0 - 1.0 ) * progress];
|
||||
|
||||
if (progress === 1.0)
|
||||
[view setHidden:CPRectIsNull(endFrame) || [view alphaValue] === 0.0];
|
||||
}
|
||||
[super setCurrentProgress:progress];
|
||||
|
||||
var animationIndex = [_viewAnimations count];
|
||||
while (animationIndex--)
|
||||
{
|
||||
var dictionary = [_viewAnimations objectAtIndex:animationIndex],
|
||||
view = [self _targetView:dictionary]
|
||||
startFrame = [self _startFrame:dictionary]
|
||||
endFrame = [self _endFrame:dictionary]
|
||||
differenceFrame = CPRectMakeZero();
|
||||
|
||||
differenceFrame.origin.x = endFrame.origin.x - startFrame.origin.x;
|
||||
differenceFrame.origin.y = endFrame.origin.y - startFrame.origin.y;
|
||||
differenceFrame.size.width = endFrame.size.width - startFrame.size.width;
|
||||
differenceFrame.size.height = endFrame.size.height - startFrame.size.height;
|
||||
|
||||
var intermediateFrame = CPRectMakeZero();
|
||||
intermediateFrame.origin.x = startFrame.origin.x + differenceFrame.origin.x * progress;
|
||||
intermediateFrame.origin.y = startFrame.origin.y + differenceFrame.origin.y * progress;
|
||||
intermediateFrame.size.width = startFrame.size.width + differenceFrame.size.width * progress;
|
||||
intermediateFrame.size.height = startFrame.size.height + differenceFrame.size.height * progress;
|
||||
|
||||
[view setFrame:intermediateFrame];
|
||||
|
||||
// Update the view's alpha value
|
||||
var effect = [self _effect:dictionary];
|
||||
if (effect === CPViewAnimationFadeInEffect)
|
||||
[view setAlphaValue:1.0 * progress];
|
||||
else if (effect === CPViewAnimationFadeOutEffect)
|
||||
[view setAlphaValue:1.0 + ( 0.0 - 1.0 ) * progress];
|
||||
|
||||
if (progress === 1.0)
|
||||
[view setHidden:CPRectIsNull(endFrame) || [view alphaValue] === 0.0];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stopAnimation
|
||||
{
|
||||
var animationIndex = [_viewAnimations count];
|
||||
while (animationIndex--)
|
||||
{
|
||||
var dictionary = [_viewAnimations objectAtIndex:animationIndex];
|
||||
|
||||
var view = [self _targetView:dictionary],
|
||||
endFrame = [self _endFrame:dictionary];
|
||||
|
||||
[view setFrame:endFrame];
|
||||
|
||||
var effect = [self _effect:dictionary];
|
||||
|
||||
if (effect === CPViewAnimationFadeInEffect)
|
||||
[view setAlphaValue:1.0];
|
||||
else if (effect === CPViewAnimationFadeOutEffect)
|
||||
[view setAlphaValue:0.0];
|
||||
|
||||
[view setHidden:CPRectIsNull(endFrame) || [view alphaValue] === 0.0];
|
||||
}
|
||||
|
||||
[super stopAnimation];
|
||||
var animationIndex = [_viewAnimations count];
|
||||
while (animationIndex--)
|
||||
{
|
||||
var dictionary = [_viewAnimations objectAtIndex:animationIndex],
|
||||
view = [self _targetView:dictionary],
|
||||
endFrame = [self _endFrame:dictionary];
|
||||
|
||||
[view setFrame:endFrame];
|
||||
|
||||
var effect = [self _effect:dictionary];
|
||||
if (effect === CPViewAnimationFadeInEffect)
|
||||
[view setAlphaValue:1.0];
|
||||
else if (effect === CPViewAnimationFadeOutEffect)
|
||||
[view setAlphaValue:0.0];
|
||||
|
||||
[view setHidden:CPRectIsNull(endFrame) || [view alphaValue] === 0.0];
|
||||
}
|
||||
|
||||
[super stopAnimation];
|
||||
}
|
||||
|
||||
// ===============
|
||||
// = CONVENIENCE =
|
||||
// ===============
|
||||
- (id)_targetView:(CPDictionary)dictionary
|
||||
{
|
||||
var targetView = [dictionary valueForKey:CPViewAnimationTargetKey];
|
||||
|
||||
if (!targetView)
|
||||
[CPException raise:CPInternalInconsistencyException reason:[CPString stringWithFormat:@"view animation: %@ does not have a target view", [dictionary description]]];
|
||||
|
||||
return targetView;
|
||||
var targetView = [dictionary valueForKey:CPViewAnimationTargetKey];
|
||||
if (!targetView)
|
||||
[CPException raise:CPInternalInconsistencyException reason:[CPString stringWithFormat:@"view animation: %@ does not have a target view", [dictionary description]]];
|
||||
|
||||
return targetView;
|
||||
}
|
||||
|
||||
- (CPRect)_startFrame:(CPDictionary)dictionary
|
||||
{
|
||||
var startFrame = [dictionary valueForKey:CPViewAnimationStartFrameKey];
|
||||
|
||||
if (!startFrame)
|
||||
return [[self _targetView:dictionary] frame];
|
||||
|
||||
return startFrame;
|
||||
var startFrame = [dictionary valueForKey:CPViewAnimationStartFrameKey];
|
||||
if (!startFrame)
|
||||
return [[self _targetView:dictionary] frame];
|
||||
|
||||
return startFrame;
|
||||
}
|
||||
|
||||
- (CPRect)_endFrame:(CPDictionary)dictionary
|
||||
{
|
||||
var endFrame = [dictionary valueForKey:CPViewAnimationEndFrameKey];
|
||||
|
||||
if (!endFrame)
|
||||
return [[self _targetView:dictionary] frame];
|
||||
|
||||
return endFrame;
|
||||
var endFrame = [dictionary valueForKey:CPViewAnimationEndFrameKey];
|
||||
if (!endFrame)
|
||||
return [[self _targetView:dictionary] frame];
|
||||
|
||||
return endFrame;
|
||||
}
|
||||
|
||||
- (CPString)_effect:(CPDictionary)dictionary
|
||||
{
|
||||
return [dictionary valueForKey:CPViewAnimationEffectKey];
|
||||
return [dictionary valueForKey:CPViewAnimationEffectKey];
|
||||
}
|
||||
|
||||
// =============
|
||||
// = ACCESSORS =
|
||||
// =============
|
||||
- (CPArray)viewAnimations
|
||||
{
|
||||
return _viewAnimations;
|
||||
return _viewAnimations;
|
||||
}
|
||||
|
||||
- (void)setViewAnimations:(CPArray)viewAnimations
|
||||
{
|
||||
if (viewAnimations != _viewAnimations)
|
||||
{
|
||||
[self stopAnimation];
|
||||
_viewAnimations = [viewAnimations copy];
|
||||
}
|
||||
if (viewAnimations != _viewAnimations)
|
||||
{
|
||||
[self stopAnimation];
|
||||
_viewAnimations = [viewAnimations copy];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -44,7 +44,7 @@ var screenNeedsInitialization = NO,
|
||||
|
||||
+ (BOOL)supportsDragAndDrop
|
||||
{
|
||||
return CPFeatureIsCompatible(CPHTMLDragAndDropFeature);
|
||||
return CPFeatureIsCompatible(CPHTMLDragAndDropFeature) && ![self isBrowser];
|
||||
}
|
||||
|
||||
+ (BOOL)supportsNativeMainMenu
|
||||
|
||||
@@ -462,9 +462,9 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
_DOMWindow.cpSetShadowStyle(_shadowStyle);
|
||||
}
|
||||
|
||||
_DOMBodyElement.style.cursor = [[CPCursor currentCursor] _cssString];
|
||||
|
||||
[self registerDOMWindow];
|
||||
|
||||
_DOMBodyElement.style.cursor = [[CPCursor currentCursor] _cssString];
|
||||
}
|
||||
|
||||
- (void)orderOut:(id)aSender
|
||||
|
||||
|
Before Width: | Height: | Size: 137 B After Width: | Height: | Size: 137 B |
|
Before Width: | Height: | Size: 164 B After Width: | Height: | Size: 164 B |
@@ -403,6 +403,9 @@
|
||||
|
||||
var kvoOperators = [];
|
||||
|
||||
// HACK: prevent these from becoming globals. workaround for obj-j "function foo(){}" behavior
|
||||
var avgOperator, maxOperator, minOperator, countOperator, sumOperator;
|
||||
|
||||
kvoOperators["avg"] = function avgOperator(self, _cmd, param)
|
||||
{
|
||||
var objects = [self valueForKeyPath:param],
|
||||
|
||||
@@ -168,7 +168,7 @@ CPOperationQueuePriorityVeryHigh = 8;
|
||||
The JS function that should be run after the main method
|
||||
@return JS function
|
||||
*/
|
||||
– (JSObject)completionFunction
|
||||
- (JSObject)completionFunction
|
||||
{
|
||||
return _completionFunction;
|
||||
}
|
||||
@@ -290,4 +290,4 @@ CPOperationQueuePriorityVeryHigh = 8;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@end
|
||||
|
||||
@@ -176,41 +176,55 @@ task("test-only", function()
|
||||
{
|
||||
var tests = new FileList('Tests/**/*Test.j');
|
||||
var cmd = ["ojtest"].concat(tests.items());
|
||||
|
||||
|
||||
var code = OS.system(cmd);
|
||||
if (code !== 0)
|
||||
OS.exit(code);
|
||||
});
|
||||
|
||||
task("push-packages", ["CommonJS"], function()
|
||||
{
|
||||
task("push-packages", ["CommonJS", "push-cappuccino", "push-objective-j"]);
|
||||
|
||||
task("push-cappuccino", function() {
|
||||
pushPackage(
|
||||
BUILD_CJS_CAPPUCCINO,
|
||||
$BUILD_CJS_CAPPUCCINO,
|
||||
"git@github.com:280north/cappuccino-package.git"
|
||||
);
|
||||
});
|
||||
|
||||
task("push-objective-j", function() {
|
||||
pushPackage(
|
||||
BUILD_CJS_OBJECTIVE_J,
|
||||
$BUILD_CJS_OBJECTIVE_J,
|
||||
"git@github.com:280north/objective-j-package.git"
|
||||
);
|
||||
});
|
||||
|
||||
function pushPackage(path, remote)
|
||||
{
|
||||
// FIXME: this will probably fail next time...
|
||||
var cmds =
|
||||
[
|
||||
["cd", path],
|
||||
//["rm", "-rf", ".git*"],
|
||||
["git", "init"],
|
||||
stream.print("Pushing \0blue(" + path + "\0) to \0blue(" + remote + "\0)");
|
||||
|
||||
FILE.mkdirs("push-package");
|
||||
|
||||
var pushPackageDir = FILE.join("push-package", remote.replace(/[^\w]/g, "_"));
|
||||
|
||||
if (FILE.exists(pushPackageDir))
|
||||
OS.system(buildCommandString([["cd", pushPackageDir], ["git", "pull"]]));
|
||||
else
|
||||
OS.system(["git", "clone", remote, pushPackageDir]);
|
||||
|
||||
OS.system("cd "+OS.enquote(pushPackageDir)+" && git rm --ignore-unmatch -r * && rm -rf *");
|
||||
OS.system("cp -R "+OS.enquote(path)+"/* "+OS.enquote(pushPackageDir)+"/.");
|
||||
|
||||
OS.system(buildCommandString([
|
||||
["cd", pushPackageDir],
|
||||
["git", "add", "."],
|
||||
["git", "commit", "-m", "Pushed on " + new Date()],
|
||||
["git", "remote", "add", "origin", remote],
|
||||
["git", "push", "origin", "master"]
|
||||
];
|
||||
|
||||
var cmdString = cmds.map(function(cmd) {
|
||||
]));
|
||||
}
|
||||
|
||||
function buildCommandString(arrayOfCommands)
|
||||
{
|
||||
return arrayOfCommands.map(function(cmd) {
|
||||
return cmd.map(OS.enquote).join(" ");
|
||||
}).join(" && ");
|
||||
|
||||
OS.system(cmdString);
|
||||
}
|
||||
|
||||
@@ -1,79 +1,91 @@
|
||||
#!/usr/bin/env narwhal
|
||||
|
||||
var FILE = require("file");
|
||||
var SYSTEM = require("system");
|
||||
var OS = require("os");
|
||||
var OBJJ = require("objective-j");
|
||||
|
||||
var parser = new (require("args").Parser)();
|
||||
|
||||
function printUsage()
|
||||
{
|
||||
print("this is where you say the usage");
|
||||
}
|
||||
parser.usage("file...");
|
||||
parser.help("Cappuccino plist converter.");
|
||||
|
||||
parser.option("-c", "--convert", "format")
|
||||
.help("rewrite property list files in format")
|
||||
.choices({
|
||||
"280north1" : OBJJ.kCFPropertyList280NorthFormat_v1_0,
|
||||
"xml1": OBJJ.kCFPropertyListXMLFormat_v1_0
|
||||
});
|
||||
|
||||
parser.option("-l", "--lint", "lint")
|
||||
.help("check the property list files for syntax errors")
|
||||
.set(true);
|
||||
|
||||
parser.option("-h", "--help")
|
||||
.action(parser.printHelp);
|
||||
|
||||
parser.option("-o", "outPath")
|
||||
.help("specify alternate file path name for result;\n\
|
||||
the -o option is used with -convert, and is only\n\
|
||||
useful with one file argument (last file overwrites);\n\
|
||||
the path '-' means stdout.")
|
||||
.set();
|
||||
|
||||
parser.option("-e", "outExtension")
|
||||
.help("specify alternate extension for converted files")
|
||||
.set();
|
||||
|
||||
parser.option("-s", "silent")
|
||||
.help("be silent on success")
|
||||
.set(true);
|
||||
|
||||
exports.main = function(args)
|
||||
{
|
||||
// TODO: args parser
|
||||
args.shift();
|
||||
// HACK: add extra "-" to "-convert", etc, for plutil compatibility
|
||||
var args = args.map(function(arg) { return arg.replace(/^(-[^-].+)$/, "-$1"); });
|
||||
var options = parser.parse(args);
|
||||
|
||||
if (args.length < 1)
|
||||
return printUsage();
|
||||
|
||||
var allFiles = NO,
|
||||
format = nil,
|
||||
filePaths = [],
|
||||
outPath = nil,
|
||||
outExtension = nil;
|
||||
|
||||
index = 0,
|
||||
count = args.length;
|
||||
|
||||
for (; index < count; ++index)
|
||||
var ok = false;
|
||||
|
||||
if (typeof options.format !== "undefined" || options.lint)
|
||||
{
|
||||
var argument = args[index];
|
||||
|
||||
if (argument.charAt(0) === '-' && !allFiles)
|
||||
{
|
||||
if (filePaths.length > 0)
|
||||
return printUsage();
|
||||
|
||||
else if (argument === "-convert")
|
||||
format = args[++index];
|
||||
|
||||
else if (argument === "-o")
|
||||
outPath = args[++index];
|
||||
|
||||
else if (argument === "-e")
|
||||
outExtension = args[++index];
|
||||
|
||||
else if (argument === "--")
|
||||
allFiles = YES;
|
||||
|
||||
else if (argument === "-help")
|
||||
return printUsage();
|
||||
}
|
||||
else
|
||||
filePaths.push(args[index]);
|
||||
ok = true;
|
||||
options.args.forEach(function(filePath) {
|
||||
var data = new OBJJ.objj_data();
|
||||
data.string = FILE.read(filePath, { charset:"UTF-8" });
|
||||
|
||||
var plistObject = OBJJ.CPPropertyListCreateFromData(data);
|
||||
if (!plistObject)
|
||||
{
|
||||
// FIXME: more useful error messages
|
||||
SYSTEM.stderr.print(filePath + ": parse error");
|
||||
ok = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.lint)
|
||||
{
|
||||
if (!options.silent)
|
||||
SYSTEM.stderr.print(filePath + ": OK");
|
||||
}
|
||||
else
|
||||
{
|
||||
data = OBJJ.CPPropertyListCreateData(plistObject, options.format);
|
||||
|
||||
// outextension?
|
||||
if (options.outPath === "-")
|
||||
SYSTEM.stdout.write(data.string);
|
||||
else
|
||||
FILE.write(options.outPath || filePath, data.string, { charset:"UTF-8" });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
index = 0;
|
||||
count = filePaths.length;
|
||||
|
||||
for (; index < count; ++index)
|
||||
else
|
||||
{
|
||||
var filePath = filePaths[index],
|
||||
data = new objj_data();
|
||||
|
||||
data.string = FILE.read(filePaths[index], { charset:"UTF-8" });
|
||||
|
||||
var plistObject = new CPPropertyListCreateFromData(data);
|
||||
|
||||
if (format === "280north1")
|
||||
data = CPPropertyListCreate280NorthData(plistObject);
|
||||
|
||||
else if (format === "xml1")
|
||||
data = CPPropertyListCreateXMLData(plistObject);
|
||||
|
||||
// outextension?
|
||||
FILE.write(outPath || filePath, data.string, { charset:"UTF-8" });
|
||||
parser.printHelp(options);
|
||||
}
|
||||
|
||||
OS.exit(ok ? 0 : 1);
|
||||
}
|
||||
|
||||
if (require.main == module.id)
|
||||
|
||||
@@ -52,8 +52,8 @@ for (var name in catalog)
|
||||
}
|
||||
|
||||
// push to the front of the array lowest priority first.
|
||||
OBJJ_INCLUDE_PATHS.unshift.apply(OBJJ_INCLUDE_PATHS, exports.objj_debug_frameworks);
|
||||
OBJJ_INCLUDE_PATHS.unshift.apply(OBJJ_INCLUDE_PATHS, exports.objj_frameworks);
|
||||
OBJJ_INCLUDE_PATHS.unshift.apply(OBJJ_INCLUDE_PATHS, exports.objj_debug_frameworks);
|
||||
|
||||
if (system.env["OBJJ_INCLUDE_PATHS"])
|
||||
OBJJ_INCLUDE_PATHS.unshift.apply(OBJJ_INCLUDE_PATHS, system.env["OBJJ_INCLUDE_PATHS"].split(":"));
|
||||
@@ -112,6 +112,13 @@ exports.run = function(args)
|
||||
{
|
||||
if (args && args.length > 1)
|
||||
{
|
||||
// we expect args to be in the format:
|
||||
// 1) "objj" path
|
||||
// 2) optional "-I" args
|
||||
// 3) real or "virtual" main.j
|
||||
// 4) optional program arguments
|
||||
|
||||
// copy the args since we're going to modify them
|
||||
var argv = args.slice(1);
|
||||
|
||||
while (argv.length && argv[0].indexOf('-I') === 0)
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
#!/usr/bin/env narwhal
|
||||
|
||||
var FILE = require("file");
|
||||
var execPath = require("file").path(module.path);
|
||||
var mainPath = execPath.dirname().dirname().join("lib", execPath.basename(), "main.j");
|
||||
|
||||
var cappuccinoPackage = FILE.path(module.path).dirname().dirname();
|
||||
var mainPath = cappuccinoPackage.join("lib", FILE.basename(module.path), "main.j");
|
||||
var frameworksPath = cappuccinoPackage.join("Frameworks");
|
||||
|
||||
// TODO: is specifying the Frameworks necessary?
|
||||
system.args.splice(1, 0, "-I"+frameworksPath, String(mainPath));
|
||||
|
||||
// HACK: remove use of SELF_HOME from capp gen
|
||||
system.env["SELF_HOME"] = cappuccinoPackage;
|
||||
|
||||
require("objective-j").run(system.args);
|
||||
var args = ["objj", String(mainPath)].concat(system.args.slice(1));
|
||||
require("objective-j").run(args);
|
||||
|
||||
@@ -87,7 +87,7 @@ CPLogRegister(CPLogConsole);
|
||||
|
||||
[tableView setColumnAutoresizingStyle:CPTableViewUniformColumnAutoresizingStyle];
|
||||
|
||||
var scrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(100, 100, CGRectGetWidth([view bounds]), CGRectGetHeight([view bounds]))];
|
||||
var scrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth([view bounds]), CGRectGetHeight([view bounds]))];
|
||||
[tableView setRowHeight:22.0];
|
||||
[scrollView setDocumentView:tableView];
|
||||
[scrollView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
||||
|
||||
@@ -6,6 +6,8 @@ var OS = require("os"),
|
||||
FILE = require("file"),
|
||||
OBJJ = require("objective-j");
|
||||
|
||||
// FIXME: better way to do this:
|
||||
var CAPP_HOME = require("packages").catalog["cappuccino"].directory;
|
||||
|
||||
function gen(/*va_args*/)
|
||||
{
|
||||
@@ -56,7 +58,7 @@ function gen(/*va_args*/)
|
||||
if (FILE.isAbsolute(template))
|
||||
sourceTemplate = FILE.join(template);
|
||||
else
|
||||
sourceTemplate = FILE.join(SYSTEM.env["SELF_HOME"], "lib", "capp", "Resources", "Templates", template);
|
||||
sourceTemplate = FILE.join(CAPP_HOME, "lib", "capp", "Resources", "Templates", template);
|
||||
|
||||
var configFile = FILE.join(sourceTemplate, "template.config"),
|
||||
config = {};
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
@import <Foundation/Foundation.j>
|
||||
@import <AppKit/AppKit.j>
|
||||
|
||||
function findCibClassDependencies(cibPath) {
|
||||
var cib = [[CPCib alloc] initWithContentsOfURL:cibPath];
|
||||
|
||||
var dependencies = {};
|
||||
|
||||
var CPClassFromStringOriginal = CPClassFromString;
|
||||
CPClassFromString = function(aClassName) {
|
||||
var result = CPClassFromStringOriginal(aClassName);
|
||||
|
||||
// print("CPClassFromString: " + Array.prototype.slice.call(arguments) + " => " + result);
|
||||
dependencies[aClassName] = true;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// make sure CPApp is init'd
|
||||
[CPApplication sharedApplication]
|
||||
|
||||
try {
|
||||
var x = [cib pressInstantiate];
|
||||
} catch (e) {
|
||||
CPLog.warn("Exception thrown when instantiating " + cibPath + ": " + e);
|
||||
} finally {
|
||||
CPClassFromString = CPClassFromStringOriginal;
|
||||
}
|
||||
|
||||
return Object.keys(dependencies);
|
||||
}
|
||||
// this is copied from CPCib's "instantiateCibWithExternalNameTable:"
|
||||
@implementation CPCib (Press)
|
||||
|
||||
- (BOOL)pressInstantiate
|
||||
{
|
||||
var bundle = _bundle,
|
||||
owner = nil;//[anExternalNameTable objectForKey:CPCibOwner];
|
||||
|
||||
if (!bundle && owner)
|
||||
bundle = [CPBundle bundleForClass:[owner class]];
|
||||
|
||||
var unarchiver = [[_CPCibKeyedUnarchiver alloc] initForReadingWithData:_data bundle:bundle awakenCustomResources:_awakenCustomResources],
|
||||
replacementClasses = nil;//[anExternalNameTable objectForKey:CPCibReplacementClasses];
|
||||
|
||||
if (replacementClasses)
|
||||
{
|
||||
var key = nil,
|
||||
keyEnumerator = [replacementClasses keyEnumerator];
|
||||
|
||||
while (key = [keyEnumerator nextObject])
|
||||
[unarchiver setClass:[replacementClasses objectForKey:key] forClassName:key];
|
||||
}
|
||||
|
||||
[unarchiver setExternalObjectsForProxyIdentifiers:nil/*[anExternalNameTable objectForKey:CPCibExternalObjects]*/];
|
||||
|
||||
var objectData = [unarchiver decodeObjectForKey:"CPCibObjectDataKey"];
|
||||
|
||||
if (!objectData || ![objectData isKindOfClass:[_CPCibObjectData class]])
|
||||
return NO;
|
||||
|
||||
var topLevelObjects = nil;//[anExternalNameTable objectForKey:CPCibTopLevelObjects];
|
||||
|
||||
[objectData instantiateWithOwner:owner topLevelObjects:topLevelObjects]
|
||||
// [objectData establishConnectionsWithOwner:owner topLevelObjects:topLevelObjects];
|
||||
// [objectData awakeWithOwner:owner topLevelObjects:topLevelObjects];
|
||||
|
||||
// Display Visible Windows.
|
||||
// [objectData displayVisibleWindows];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env objj
|
||||
|
||||
@import <Foundation/Foundation.j>
|
||||
@import "cib-analysis-tools.j"
|
||||
|
||||
var FILE = require("file");
|
||||
|
||||
CPLogRegister(CPLogPrint);
|
||||
|
||||
function main(args)
|
||||
{
|
||||
args.slice(1).forEach(function(path) {
|
||||
var classes = findCibClassDependencies(FILE.absolute(path));
|
||||
|
||||
print(path+":");
|
||||
classes.sort().forEach(function(className) { print(" + " + className) });
|
||||
});
|
||||
}
|
||||
+79
-74
@@ -1,18 +1,16 @@
|
||||
var OS = require("os");
|
||||
if (system.engine !== "rhino") {
|
||||
system.args.splice(1,2); // remove library path and main.j
|
||||
var cmd = "NARWHAL_ENGINE_HOME='' NARWHAL_ENGINE='rhino' " + system.args.map(OS.enquote).join(" ");
|
||||
OS.exit(OS.system(cmd));
|
||||
}
|
||||
require("narwhal").ensureEngine("rhino");
|
||||
|
||||
@import <Foundation/Foundation.j>
|
||||
@import <AppKit/AppKit.j>
|
||||
|
||||
@import "objj-analysis-tools.j"
|
||||
@import "cib-analysis-tools.j"
|
||||
|
||||
var ARGS = require("args");
|
||||
var FILE = require("file");
|
||||
var OS = require("os");
|
||||
var DOM = require("browser/dom");
|
||||
var UTIL = require("util");
|
||||
var INTERPRETER = require("interpreter");
|
||||
|
||||
var serializer = new DOM.XMLSerializer();
|
||||
@@ -52,7 +50,7 @@ parser.option("-n", "--nostrip", "strip")
|
||||
.set(false)
|
||||
.help("Do not strip any files");
|
||||
|
||||
parser.option("-p", "--pngcrush", "png")
|
||||
parser.option("-p", "--pngcrush", "png")
|
||||
.def(false)
|
||||
.set(true)
|
||||
.help("Run pngcrush on all PNGs (pngcrush must be installed!)");
|
||||
@@ -67,12 +65,12 @@ parser.helpful();
|
||||
function main(args)
|
||||
{
|
||||
var options = parser.parse(args);
|
||||
|
||||
|
||||
if (options.args.length < 2) {
|
||||
parser.printUsage(options);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//if (options.verbose)
|
||||
CPLogRegister(CPLogPrint);
|
||||
//else
|
||||
@@ -98,63 +96,67 @@ function press(rootPath, outputPath, options) {
|
||||
CPLog.info("===========================================");
|
||||
CPLog.info("Application root: " + rootPath);
|
||||
CPLog.info("Output directory: " + outputPath);
|
||||
|
||||
|
||||
var outputFiles = {};
|
||||
|
||||
|
||||
// analyze and gather files for each environment:
|
||||
options.environments.forEach(function(environment) {
|
||||
pressEnvironment(rootPath, outputFiles, environment, options);
|
||||
});
|
||||
|
||||
|
||||
// phase 4: copy everything and write out the new files
|
||||
CPLog.error("PHASE 4: copy to output ("+rootPath+" to "+outputPath+")");
|
||||
|
||||
|
||||
FILE.copyTree(rootPath, outputPath);
|
||||
|
||||
|
||||
for (var path in outputFiles) {
|
||||
var file = outputPath.join(rootPath.relative(path));
|
||||
|
||||
|
||||
var parent = file.dirname();
|
||||
if (!parent.exists()) {
|
||||
CPLog.warn(parent + " doesn't exist, creating directories.");
|
||||
parent.mkdirs();
|
||||
}
|
||||
|
||||
|
||||
if (typeof outputFiles[path] !== "string")
|
||||
outputFiles[path] = outputFiles[path].join("");
|
||||
|
||||
|
||||
CPLog.info((file.exists() ? "Overwriting: " : "Writing: ") + file);
|
||||
FILE.write(file, outputFiles[path], { charset : "UTF-8" });
|
||||
}
|
||||
|
||||
|
||||
// strip known unnecessary files
|
||||
// outputPath.glob("**/Frameworks/Debug").forEach(function(debugFramework) {
|
||||
// outputPath.join(debugFramework).rmtree();
|
||||
// });
|
||||
// outputPath.join("index-debug.html").remove();
|
||||
|
||||
|
||||
if (options.png) {
|
||||
pngcrushDirectory(outputPath);
|
||||
}
|
||||
}
|
||||
|
||||
function pressEnvironment(rootPath, outputFiles, environment, options) {
|
||||
|
||||
|
||||
var mainPath = String(rootPath.join(options.main));
|
||||
var frameworks = options.frameworks.map(function(framework) { return rootPath.join(framework); });
|
||||
|
||||
|
||||
CPLog.info("===========================================");
|
||||
CPLog.info("Main file: " + mainPath)
|
||||
CPLog.info("Frameworks: " + frameworks);
|
||||
CPLog.info("Environment: " + environment);
|
||||
|
||||
|
||||
// get a Rhino context
|
||||
var context = new INTERPRETER.Context();
|
||||
var scope = setupObjectiveJ(context);
|
||||
|
||||
|
||||
scope.OBJJ_INCLUDE_PATHS = frameworks;
|
||||
scope.OBJJ_ENVIRONMENTS = [environment, "ObjJ"];
|
||||
|
||||
|
||||
// build list of cibs to inspect for dependent classes
|
||||
// FIXME: what's the best way to determine which cibs to look in?
|
||||
var cibs = FILE.glob(rootPath.join("**", "*.cib")).filter(function(path) { return !(/Frameworks/).test(path); });
|
||||
|
||||
// flattening bookkeeping. keep track of the bundles and evaled code (in the correct order!)
|
||||
var bundleArchiveResponses = [];
|
||||
var exectuableResponses = [];
|
||||
@@ -166,42 +168,42 @@ function pressEnvironment(rootPath, outputFiles, environment, options) {
|
||||
success : aResponse.success,
|
||||
filePath : rootPath.relative(aResponse.filePath).toString()
|
||||
};
|
||||
|
||||
|
||||
if (aResponse.success) {
|
||||
var xmlString = serializer.serializeToString(aResponse.xml);
|
||||
response.text = CPPropertyListCreate280NorthData(CPPropertyListCreateFromXMLData({ string: xmlString })).string;
|
||||
}
|
||||
|
||||
|
||||
bundleArchiveResponses.push(response);
|
||||
});
|
||||
|
||||
|
||||
functionHookBefore(scope.objj_search.prototype, "didReceiveExecutableResponse", function(aResponse) {
|
||||
exectuableResponses.push(aResponse);
|
||||
});
|
||||
|
||||
|
||||
// lets just use the Context object as our con
|
||||
context.rootPath = rootPath;
|
||||
context.scope = scope;
|
||||
|
||||
|
||||
// phase 1: get global defines
|
||||
CPLog.error("PHASE 1: Loading application...");
|
||||
|
||||
|
||||
var globals = findGlobalDefines(context, mainPath, evaledFragments);
|
||||
|
||||
|
||||
// coalesce the results
|
||||
var dependencies = coalesceGlobalDefines(globals);
|
||||
|
||||
// Log
|
||||
|
||||
// log identifer => files defining
|
||||
CPLog.trace("Global defines:");
|
||||
Object.keys(dependencies).sort().forEach(function(identifier) {
|
||||
CPLog.trace(" " + identifier + " => " + rootPath.relative(dependencies[identifier]));
|
||||
});
|
||||
|
||||
|
||||
// phase 2: walk the dependency tree (both imports and references) to determine exactly which files need to be included
|
||||
CPLog.error("PHASE 2: Walk dependency tree...");
|
||||
|
||||
|
||||
var requiredFiles = {};
|
||||
|
||||
|
||||
if (options.nostrip)
|
||||
{
|
||||
// all files are required. no need for analysis
|
||||
@@ -214,18 +216,31 @@ function pressEnvironment(rootPath, outputFiles, environment, options) {
|
||||
CPLog.error("Root file not loaded!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
CPLog.warn("Analyzing dependencies...");
|
||||
|
||||
|
||||
context.dependencies = dependencies;
|
||||
context.ignoreFrameworkImports = true; // ignores "XXX/XXX.j" imports
|
||||
context.importCallback = function(importing, imported) { requiredFiles[imported] = true; };
|
||||
context.referenceCallback = function(referencing, referenced) { requiredFiles[referenced] = true; }
|
||||
|
||||
|
||||
requiredFiles[mainPath] = true;
|
||||
|
||||
|
||||
// check the code
|
||||
traverseDependencies(context, scope.objj_files[mainPath]);
|
||||
|
||||
|
||||
// check the cibs
|
||||
cibs.forEach(function(cibPath) {
|
||||
var cibClasses = findCibClassDependencies(cibPath);
|
||||
CPLog.debug(cibPath + " => " + cibClasses);
|
||||
|
||||
var referencedFiles = {};
|
||||
markFilesReferencedByTokens(cibClasses, context.dependencies, referencedFiles);
|
||||
checkReferenced(context, null, referencedFiles);
|
||||
|
||||
print(UTIL.repr(referencedFiles));
|
||||
});
|
||||
|
||||
var count = 0,
|
||||
total = 0;
|
||||
for (var path in scope.objj_files)
|
||||
@@ -233,7 +248,7 @@ function pressEnvironment(rootPath, outputFiles, environment, options) {
|
||||
// mark all ".keytheme"s as required
|
||||
if (/\.keyedtheme$/.test(path))
|
||||
requiredFiles[path] = true;
|
||||
|
||||
|
||||
if (requiredFiles[path])
|
||||
{
|
||||
CPLog.debug("Included: " + rootPath.relative(path));
|
||||
@@ -242,30 +257,20 @@ function pressEnvironment(rootPath, outputFiles, environment, options) {
|
||||
else
|
||||
{
|
||||
CPLog.info("Excluded: " + rootPath.relative(path));
|
||||
}
|
||||
}
|
||||
total++;
|
||||
}
|
||||
CPLog.warn("Total required files: " + count + " out of " + total);
|
||||
|
||||
// FIXME: sprite images
|
||||
//for (var i in context.bundleImages)
|
||||
//{
|
||||
// var images = context.bundleImages[i];
|
||||
//
|
||||
// CPLog.debug("Bundle images for " + i);
|
||||
// for (var j in images)
|
||||
// CPLog.trace(j + " = " + images[j]);
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
if (options.flatten)
|
||||
{
|
||||
// phase 3a: build single Application.js file (and modified index.html)
|
||||
CPLog.error("PHASE 3a: Flattening...");
|
||||
|
||||
|
||||
var applicationScriptName = "Application-"+environment+".js";
|
||||
var indexHTMLName = "index-"+environment+".html";
|
||||
|
||||
|
||||
// Shim for faking bundle responses.
|
||||
// We're just defining it here so we can serialize the function. It's not used within press.
|
||||
// **************************************************
|
||||
@@ -303,9 +308,9 @@ function pressEnvironment(rootPath, outputFiles, environment, options) {
|
||||
}
|
||||
}
|
||||
// **************************************************
|
||||
|
||||
|
||||
var applicationScript = [];
|
||||
|
||||
|
||||
var URIMaps = {};
|
||||
Object.keys(scope.objj_bundles).forEach(function(bundleName) {
|
||||
var bundle = scope.objj_bundles[bundleName];
|
||||
@@ -332,7 +337,7 @@ function pressEnvironment(rootPath, outputFiles, environment, options) {
|
||||
applicationScript.push(" var URIMaps = " + JSON.stringify(URIMaps) + ";");
|
||||
applicationScript.push(" setupURIMaps(URIMaps);");
|
||||
applicationScript.push("})();");
|
||||
|
||||
|
||||
// add each fragment, wrapped in a function, along with OBJJ_CURRENT_BUNDLE bookkeeping
|
||||
evaledFragments.forEach(function(fragment) {
|
||||
if (requiredFiles[fragment.file.path])
|
||||
@@ -346,13 +351,13 @@ function pressEnvironment(rootPath, outputFiles, environment, options) {
|
||||
CPLog.info("Stripping " + rootPath.relative(fragment.file.path));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// call main once the page has loaded. FIXME: assumes synchronous script loading?
|
||||
applicationScript.push("if (window.addEventListener)");
|
||||
applicationScript.push(" window.addEventListener('load', main, false);")
|
||||
applicationScript.push("else if (window.attachEvent)")
|
||||
applicationScript.push(" window.attachEvent('onload', main);");
|
||||
|
||||
|
||||
// MHTML
|
||||
// TODO: combine multiple MHTMLs
|
||||
exectuableResponses.forEach(function(aResponse) {
|
||||
@@ -362,15 +367,15 @@ function pressEnvironment(rootPath, outputFiles, environment, options) {
|
||||
applicationScript.push(aResponse.text.slice(mhtmlStart, mhtmlEnd+2));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
var indexHTML = FILE.read(FILE.join(rootPath, "index.html"), { charset : "UTF-8" });
|
||||
|
||||
|
||||
// comment out any OBJJ_MAIN_FILE defintions or objj_import() calls
|
||||
indexHTML = indexHTML.replace(/(\bOBJJ_MAIN_FILE\s*=|\bobjj_import\s*\()/g, '//$&');
|
||||
|
||||
|
||||
// add a script tag for Application.js at the very end of the <head> block
|
||||
indexHTML = indexHTML.replace(/([ \t]*)(<\/head>)/, '$1 <script src = "'+applicationScriptName+'" type = "text/javascript"></script>\n$1$2');
|
||||
|
||||
|
||||
// output Application.js and index.html
|
||||
outputFiles[rootPath.join(applicationScriptName)] = applicationScript.join("\n");
|
||||
outputFiles[rootPath.join(indexHTMLName)] = indexHTML;
|
||||
@@ -423,7 +428,7 @@ function pressEnvironment(rootPath, outputFiles, environment, options) {
|
||||
outputFiles[staticPath].push("p;");
|
||||
outputFiles[staticPath].push(filename.length+";");
|
||||
outputFiles[staticPath].push(filename);
|
||||
|
||||
|
||||
for (var i = 0; i < file.fragments.length; i++)
|
||||
{
|
||||
if (file.fragments[i].type & FRAGMENT_CODE)
|
||||
@@ -443,13 +448,13 @@ function pressEnvironment(rootPath, outputFiles, environment, options) {
|
||||
ignoreFragment = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!ignoreFragment)
|
||||
{
|
||||
if (file.fragments[i].type & FRAGMENT_LOCAL)
|
||||
{
|
||||
var relativePath = pathRelativeTo(file.fragments[i].info, directory)
|
||||
|
||||
|
||||
outputFiles[staticPath].push("i;");
|
||||
outputFiles[staticPath].push(relativePath.length+";");
|
||||
outputFiles[staticPath].push(relativePath);
|
||||
@@ -480,20 +485,20 @@ function pressEnvironment(rootPath, outputFiles, environment, options) {
|
||||
|
||||
// phase 3.5: fix bundle plists
|
||||
CPLog.error("PHASE 3.5: fix bundle plists");
|
||||
|
||||
|
||||
for (var path in bundles)
|
||||
{
|
||||
var directory = FILE.dirname(path),
|
||||
dict = bundles[path].info,
|
||||
replacedFiles = [dict objectForKey:"CPBundleReplacedFiles"];
|
||||
|
||||
|
||||
CPLog.info("Modifying .sj: " + rootPath.relative(path));
|
||||
|
||||
|
||||
if (replacedFiles)
|
||||
{
|
||||
var newReplacedFiles = [];
|
||||
[dict setObject:newReplacedFiles forKey:"CPBundleReplacedFiles"];
|
||||
|
||||
|
||||
for (var i = 0; i < replacedFiles.length; i++)
|
||||
{
|
||||
var replacedFilePath = directory + "/" + replacedFiles[i]
|
||||
@@ -516,12 +521,12 @@ function pressEnvironment(rootPath, outputFiles, environment, options) {
|
||||
function pngcrushDirectory(directory) {
|
||||
var directoryPath = FILE.path(directory);
|
||||
var pngs = directoryPath.glob("**/*.png");
|
||||
|
||||
|
||||
system.stderr.print("Running pngcrush on " + pngs.length + " pngs:");
|
||||
pngs.forEach(function(dst) {
|
||||
var dstPath = directoryPath.join(dst);
|
||||
var tmpPath = FILE.path(dstPath+".tmp");
|
||||
|
||||
|
||||
var p = OS.popen(["pngcrush", "-rem", "alla", "-reduce", /*"-brute",*/ dstPath, tmpPath]);
|
||||
if (p.wait()) {
|
||||
CPLog.warn("pngcrush failed. Ensure it's installed and on your PATH.");
|
||||
|
||||
@@ -48,28 +48,6 @@ function traverseDependencies(context, file)
|
||||
file.fragments = objj_preprocess(file.contents, file.bundle, file);
|
||||
}
|
||||
|
||||
// sprite: look for pngs in the Resources directory
|
||||
if (!context.bundleImages)
|
||||
context.bundleImages = {};
|
||||
|
||||
if (!context.bundleImages[file.bundle.path])
|
||||
{
|
||||
var resourcesPath = FILE.path(file.bundle.path).dirname().join("/Resources");
|
||||
if (resourcesPath.exists())
|
||||
{
|
||||
context.bundleImages[file.bundle.path] = {};
|
||||
|
||||
resourcesPath.glob("**/*.png").forEach(function(png) {
|
||||
var pngPath = resourcesPath.join(png);
|
||||
var relativePath = pathRelativeTo(pngPath.absolute(), resourcesPath.absolute());
|
||||
|
||||
// this is used as a bit mask, not a boolean
|
||||
context.bundleImages[file.bundle.path][relativePath] = 1;
|
||||
});
|
||||
}
|
||||
}
|
||||
var images = context.bundleImages[file.bundle.path];
|
||||
|
||||
var referencedFiles = {},
|
||||
importedFiles = {};
|
||||
|
||||
@@ -80,31 +58,9 @@ function traverseDependencies(context, file)
|
||||
|
||||
if (fragment.type & FRAGMENT_CODE)
|
||||
{
|
||||
var lexer = new objj_lexer(fragment.info, NULL);
|
||||
|
||||
var token;
|
||||
while (token = lexer.skip_whitespace())
|
||||
{
|
||||
if (context.dependencies.hasOwnProperty(token))
|
||||
{
|
||||
var files = context.dependencies[token];
|
||||
for (var j = 0; j < files.length; j++)
|
||||
{
|
||||
// don't record references to self
|
||||
if (files[j] != file.path)
|
||||
{
|
||||
if (!referencedFiles[files[j]])
|
||||
referencedFiles[files[j]] = {};
|
||||
|
||||
referencedFiles[files[j]][token] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var matches = token.match(new RegExp("^['\"](.*)['\"]$"));
|
||||
if (matches && images && images[matches[1]])
|
||||
images[matches[1]] = (images[matches[1]] | 2);
|
||||
}
|
||||
var referencedTokens = uniqueTokens(fragment.info);
|
||||
|
||||
markFilesReferencedByTokens(referencedTokens, context.dependencies, referencedFiles);
|
||||
}
|
||||
else if (fragment.type & FRAGMENT_FILE)
|
||||
{
|
||||
@@ -130,12 +86,25 @@ function traverseDependencies(context, file)
|
||||
}
|
||||
|
||||
// check each imported file
|
||||
checkImported(context, file.path, importedFiles);
|
||||
|
||||
if (context.importedFiles)
|
||||
context.importedFiles[file.path] = importedFiles;
|
||||
|
||||
// check each referenced file
|
||||
checkReferenced(context, file.path, referencedFiles);
|
||||
|
||||
if (context.referencedFiles)
|
||||
context.referencedFiles[file.path] = referencedFiles;
|
||||
}
|
||||
|
||||
function checkImported(context, path, importedFiles) {
|
||||
for (var importedFile in importedFiles)
|
||||
{
|
||||
if (importedFile != file.path)
|
||||
if (importedFile != path)
|
||||
{
|
||||
if (context.importCallback)
|
||||
context.importCallback(file.path, importedFile);
|
||||
context.importCallback(path, importedFile);
|
||||
|
||||
if (context.scope.objj_files[importedFile])
|
||||
traverseDependencies(context, context.scope.objj_files[importedFile]);
|
||||
@@ -143,17 +112,15 @@ function traverseDependencies(context, file)
|
||||
CPLog.error("Missing imported file: " + importedFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (context.importedFiles)
|
||||
context.importedFiles[file.path] = importedFiles;
|
||||
|
||||
// check each referenced file
|
||||
function checkReferenced(context, path, referencedFiles) {
|
||||
for (var referencedFile in referencedFiles)
|
||||
{
|
||||
if (referencedFile != file.path)
|
||||
if (referencedFile != path)
|
||||
{
|
||||
if (context.referenceCallback)
|
||||
context.referenceCallback(file.path, referencedFile, referencedFiles[referencedFile]);
|
||||
context.referenceCallback(path, referencedFile, referencedFiles[referencedFile]);
|
||||
|
||||
if (context.scope.objj_files.hasOwnProperty(referencedFile))
|
||||
traverseDependencies(context, context.scope.objj_files[referencedFile]);
|
||||
@@ -161,9 +128,46 @@ function traverseDependencies(context, file)
|
||||
CPLog.error("Missing referenced file: " + referencedFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (context.referencedFiles)
|
||||
context.referencedFiles[file.path] = referencedFiles;
|
||||
// returns a unique list of tokens for a piece of code.
|
||||
// ideally this should return identifiers only
|
||||
function uniqueTokens(code) {
|
||||
// FIXME: this breaks for indentifiers containing "$" since it's considered a distinct token by the parser
|
||||
var lexer = new objj_lexer(code, null);
|
||||
|
||||
var token, tokens = {};
|
||||
while (token = lexer.skip_whitespace()) {
|
||||
tokens[token] = true;
|
||||
}
|
||||
|
||||
return Object.keys(tokens);
|
||||
}
|
||||
|
||||
/*
|
||||
params:
|
||||
tokens (in): list of tokens to mark as required
|
||||
tokenDependenciesMap (in): map from tokens to files which define those tokens
|
||||
referencedFiles (out): map of required files (to map of tokens defined in that file)
|
||||
*/
|
||||
function markFilesReferencedByTokens(tokens, tokenDependenciesMap, referencedFiles) {
|
||||
tokens.forEach(function(token) {
|
||||
if (tokenDependenciesMap.hasOwnProperty(token))
|
||||
{
|
||||
var files = tokenDependenciesMap[token];
|
||||
for (var j = 0; j < files.length; j++)
|
||||
{
|
||||
// don't record references to self
|
||||
if (files[j] != file.path)
|
||||
{
|
||||
if (!referencedFiles[files[j]])
|
||||
referencedFiles[files[j]] = {};
|
||||
|
||||
referencedFiles[files[j]][token] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function findImportInObjjFiles(scope, fragment)
|
||||
@@ -272,9 +276,9 @@ function findGlobalDefines(context, mainPath, evaledFragments, bundleCallback)
|
||||
bundlePaths = bundlePaths || [];
|
||||
|
||||
// load default theme bundle
|
||||
var themePath = [[CPBundle bundleForClass:[CPApplication class]] pathForResource:[CPApplication defaultThemeName]];
|
||||
var themeBundle = [[CPBundle alloc] initWithPath:themePath + "/Info.plist"];
|
||||
[themeBundle loadWithDelegate:bundleDelegate];
|
||||
// var themePath = [[CPBundle bundleForClass:[CPApplication class]] pathForResource:[CPApplication defaultThemeName]];
|
||||
// var themeBundle = [[CPBundle alloc] initWithPath:themePath + "/Info.plist"];
|
||||
// [themeBundle loadWithDelegate:bundleDelegate];
|
||||
|
||||
// load additional bundles
|
||||
bundlePaths.forEach(function(bundlePath) {
|
||||
|
||||
+46
-12
@@ -24,7 +24,8 @@ function ask_remove_dir () {
|
||||
if [ -d "$dir" ]; then
|
||||
echo "================================================================================"
|
||||
echo "Found an existing Narwhal/Cappuccino installation, $dir. Remove it automatically now?"
|
||||
echo "WARNING: custom modifications and installed packages in this installation WILL BE DELETED."
|
||||
echo "WARNING: the ENTIRE directory, $dir, will be removed (i.e. 'rm -rf $dir')."
|
||||
echo "Be sure this is correct. Custom modifications and installed packages WILL BE DELETED."
|
||||
if prompt; then
|
||||
rm -rf "$dir"
|
||||
fi
|
||||
@@ -33,7 +34,7 @@ function ask_remove_dir () {
|
||||
|
||||
function ask_append_shell_config () {
|
||||
config_string="$1"
|
||||
|
||||
|
||||
shell_config_file=""
|
||||
# use order outlined by http://hayne.net/MacDev/Notes/unixFAQ.html#shellStartup
|
||||
if [ -f "$HOME/.bash_profile" ]; then
|
||||
@@ -60,6 +61,13 @@ function ask_append_shell_config () {
|
||||
return 1
|
||||
}
|
||||
|
||||
function check_and_exit () {
|
||||
if [ ! "$?" = "0" ]; then
|
||||
echo "Error: problem running boostrap.sh. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "--clone" = "$1" ]; then
|
||||
tusk_install_command="clone"
|
||||
git_clone=1
|
||||
@@ -72,6 +80,8 @@ github_path=$(echo "$github_project" | tr '-' '/')
|
||||
install_directory="/usr/local/narwhal"
|
||||
tmp_zip="/tmp/narwhal.zip"
|
||||
|
||||
unset NARWHAL_ENGINE
|
||||
|
||||
PATH_SAVED="$PATH"
|
||||
|
||||
ask_remove_dir "/usr/local/share/objj"
|
||||
@@ -109,22 +119,37 @@ if [ "$install_narwhal" ]; then
|
||||
install_directory="`cd \`dirname $input\`; pwd`/`basename $input`"
|
||||
fi
|
||||
|
||||
if [ -d "$install_directory" ]; then
|
||||
echo "================================================================================"
|
||||
echo "Directory exists at $install_directory. Delete it?"
|
||||
if prompt; then
|
||||
rm -rf "$install_directory"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$git_clone" ]; then
|
||||
git_repo="git://github.com/$github_path.git"
|
||||
echo "Cloning Narwhal from \"$git_repo\"..."
|
||||
git clone "$git_repo" "$install_directory"
|
||||
else
|
||||
zip_ball="http://github.com/$github_path/zipball/master"
|
||||
|
||||
echo "Downloading Narwhal from \"$zip_ball\"..."
|
||||
curl -L -o "$tmp_zip" "$zip_ball"
|
||||
check_and_exit
|
||||
|
||||
echo "Installing Narwhal..."
|
||||
unzip "$tmp_zip" -d "$install_directory"
|
||||
check_and_exit
|
||||
rm "$tmp_zip"
|
||||
check_and_exit
|
||||
|
||||
mv $install_directory/$github_project-*/* $install_directory/.
|
||||
rm -rf $install_directory/$github_project-*
|
||||
mv "$install_directory/$github_project-"*/* "$install_directory/."
|
||||
check_and_exit
|
||||
rm -rf "$install_directory/$github_project-"*
|
||||
check_and_exit
|
||||
fi
|
||||
|
||||
|
||||
export PATH="$install_directory/bin:$PATH"
|
||||
fi
|
||||
|
||||
@@ -141,6 +166,14 @@ if ! prompt; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "================================================================================"
|
||||
echo "Would you like to install the pre-built Objective-J and Cappuccino packages?"
|
||||
echo "If you intend to build Cappuccino yourself this is not neccessary."
|
||||
extra_packages=""
|
||||
if prompt; then
|
||||
extra_packages="objective-j cappuccino"
|
||||
fi
|
||||
|
||||
echo "Installing necessary packages..."
|
||||
|
||||
if ! tusk update; then
|
||||
@@ -148,7 +181,7 @@ if ! tusk update; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tusk $tusk_install_command browserjs jake
|
||||
tusk $tusk_install_command browserjs jake $extra_packages
|
||||
|
||||
if [ `uname` = "Darwin" ]; then
|
||||
echo "================================================================================"
|
||||
@@ -156,7 +189,7 @@ if [ `uname` = "Darwin" ]; then
|
||||
echo "This is optional but will make building and running Objective-J much faster."
|
||||
if prompt; then
|
||||
tusk $tusk_install_command narwhal-jsc
|
||||
|
||||
|
||||
if ! (cd "$install_directory/packages/narwhal-jsc" && make webkit); then
|
||||
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
||||
echo "WARNING: building narwhal-jsc failed. Hit enter to continue."
|
||||
@@ -175,9 +208,9 @@ export PATH="$PATH_SAVED"
|
||||
if ! which "narwhal" > /dev/null; then
|
||||
echo "================================================================================"
|
||||
echo "You must add Narwhal's \"bin\" directory to your PATH environment variable. Do this automatically now?"
|
||||
|
||||
|
||||
export_path_string="export PATH=\"$install_directory/bin:\$PATH\""
|
||||
|
||||
|
||||
if ! ask_append_shell_config "$export_path_string"; then
|
||||
echo "Add \"$install_directory/bin\" to your PATH environment variable in your shell configuration file (e.x. .profile, .bashrc, .bash_profile)."
|
||||
echo "For example:"
|
||||
@@ -193,11 +226,12 @@ if [ "$CAPP_BUILD" ]; then
|
||||
rm -rf "$CAPP_BUILD"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
else
|
||||
echo "================================================================================"
|
||||
echo "Before building Cappuccino we recommend you set the \$CAPP_BUILD environment variable to a path where you wish to build Cappuccino."
|
||||
echo "If you have previously set \$CAPP_BUILD and built Cappuccino you may want to delete the directory before rebuilding."
|
||||
echo "NOTE: If you have previously set \$CAPP_BUILD and built Cappuccino you may want to delete the directory before rebuilding."
|
||||
fi
|
||||
|
||||
echo "================================================================================"
|
||||
echo "Bootstrapping of Narwhal and other required tools is complete. You can now build Cappuccino."
|
||||
echo "Bootstrapping of Narwhal and other required tools is complete."
|
||||
echo "NOTE: any changes made to the shell configuration files won't take place until you restart the shell."
|
||||
|
||||
Reference in New Issue
Block a user