diff --git a/AppKit/CPAlert.j b/AppKit/CPAlert.j
index 14bf6ccd5..97a2f1518 100644
--- a/AppKit/CPAlert.j
+++ b/AppKit/CPAlert.j
@@ -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];
diff --git a/AppKit/CPApplication.j b/AppKit/CPApplication.j
index ee53c6643..c8debf421 100644
--- a/AppKit/CPApplication.j
+++ b/AppKit/CPApplication.j
@@ -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];
}
diff --git a/AppKit/CPCollectionView.j b/AppKit/CPCollectionView.j
index 40413eb5b..4a9ddecba 100644
--- a/AppKit/CPCollectionView.j
+++ b/AppKit/CPCollectionView.j
@@ -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;
diff --git a/AppKit/CPColor.j b/AppKit/CPColor.j
index 636f96a3f..cdc3af3a7 100644
--- a/AppKit/CPColor.j
+++ b/AppKit/CPColor.j
@@ -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
diff --git a/AppKit/CPFlashMovie.j b/AppKit/CPFlashMovie.j
index b666c2391..22cd0c520 100644
--- a/AppKit/CPFlashMovie.j
+++ b/AppKit/CPFlashMovie.j
@@ -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
\ No newline at end of file
diff --git a/AppKit/CPFlashView.j b/AppKit/CPFlashView.j
index d1c0a9ba0..8f1d99fa8 100644
--- a/AppKit/CPFlashView.j
+++ b/AppKit/CPFlashView.j
@@ -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:@"", [_flashMovie filename]],
+ paramEnumerator = [_params keyEnumerator],
+ key;
+
+ while (key = [paramEnumerator nextObject])
+ paramString = [paramString stringByAppendingFormat:@"", key, [_params objectForKey:key]];
+
+ _DOMObjectElement = document.createElement(@"object");
+ _DOMElement.appendChild(_DOMObjectElement);
+
+ _DOMObjectElement.outerHTML = [CPString stringWithFormat:@"", IEFlashCLSID, CGRectGetWidth([self bounds]), CGRectGetHeight([self bounds]), paramString];
+}
+
- (void)mouseDragged:(CPEvent)anEvent
{
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
diff --git a/AppKit/CPMenu/_CPMenuBarWindow.j b/AppKit/CPMenu/_CPMenuBarWindow.j
index 1898e7252..da829d047 100644
--- a/AppKit/CPMenu/_CPMenuBarWindow.j
+++ b/AppKit/CPMenu/_CPMenuBarWindow.j
@@ -1,5 +1,6 @@
#include "../CoreGraphics/CGGeometry.h"
+#include "../Platform/Platform.h"
@import "_CPMenuWindow.j"
diff --git a/AppKit/CPSplitView.j b/AppKit/CPSplitView.j
index 8022dad0e..33d243f22 100644
--- a/AppKit/CPSplitView.j
+++ b/AppKit/CPSplitView.j
@@ -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;
diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j
index 3a2b505e8..ff105e47a 100644
--- a/AppKit/CPTableView.j
+++ b/AppKit/CPTableView.j
@@ -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
diff --git a/AppKit/CPTextField.j b/AppKit/CPTextField.j
index e647e542f..c906e80ca 100644
--- a/AppKit/CPTextField.j
+++ b/AppKit/CPTextField.j
@@ -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
diff --git a/AppKit/CPViewAnimation.j b/AppKit/CPViewAnimation.j
index 5950d9609..692523584 100644
--- a/AppKit/CPViewAnimation.j
+++ b/AppKit/CPViewAnimation.j
@@ -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
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
diff --git a/AppKit/Platform/DOM/CPPlatform.j b/AppKit/Platform/DOM/CPPlatform.j
index 535644ea2..47af4b175 100644
--- a/AppKit/Platform/DOM/CPPlatform.j
+++ b/AppKit/Platform/DOM/CPPlatform.j
@@ -44,7 +44,7 @@ var screenNeedsInitialization = NO,
+ (BOOL)supportsDragAndDrop
{
- return CPFeatureIsCompatible(CPHTMLDragAndDropFeature);
+ return CPFeatureIsCompatible(CPHTMLDragAndDropFeature) && ![self isBrowser];
}
+ (BOOL)supportsNativeMainMenu
diff --git a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j
index 152373698..5c73c69cc 100644
--- a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j
+++ b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j
@@ -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
diff --git a/AppKit/Themes/Aristo/Resources/tableview-headerview-highlighted.png b/AppKit/Resources/tableview-headerview-highlighted.png
similarity index 100%
rename from AppKit/Themes/Aristo/Resources/tableview-headerview-highlighted.png
rename to AppKit/Resources/tableview-headerview-highlighted.png
diff --git a/AppKit/Themes/Aristo/Resources/tableview-headerview.png b/AppKit/Resources/tableview-headerview.png
similarity index 100%
rename from AppKit/Themes/Aristo/Resources/tableview-headerview.png
rename to AppKit/Resources/tableview-headerview.png
diff --git a/Foundation/CPArray+KVO.j b/Foundation/CPArray+KVO.j
index 1388f8a6e..4c56931a3 100644
--- a/Foundation/CPArray+KVO.j
+++ b/Foundation/CPArray+KVO.j
@@ -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],
diff --git a/Foundation/CPOperation.j b/Foundation/CPOperation.j
index a4503f41a..e24617ae7 100644
--- a/Foundation/CPOperation.j
+++ b/Foundation/CPOperation.j
@@ -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
\ No newline at end of file
+@end
diff --git a/Jakefile b/Jakefile
index 54161d8b7..1a53ee621 100644
--- a/Jakefile
+++ b/Jakefile
@@ -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);
}
diff --git a/Objective-J/CommonJS/bin/cplutil b/Objective-J/CommonJS/bin/cplutil
index 194095d2b..000e7d1be 100755
--- a/Objective-J/CommonJS/bin/cplutil
+++ b/Objective-J/CommonJS/bin/cplutil
@@ -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)
diff --git a/Objective-J/CommonJS/lib/objective-j.js b/Objective-J/CommonJS/lib/objective-j.js
index f0bf6b0a9..cc2fb248c 100644
--- a/Objective-J/CommonJS/lib/objective-j.js
+++ b/Objective-J/CommonJS/lib/objective-j.js
@@ -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)
diff --git a/Objective-J/CommonJS/objj-executable b/Objective-J/CommonJS/objj-executable
index 36a954d58..919302c11 100755
--- a/Objective-J/CommonJS/objj-executable
+++ b/Objective-J/CommonJS/objj-executable
@@ -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);
diff --git a/Tests/Manual/TableTest/AppController.j b/Tests/Manual/TableTest/AppController.j
index e4f58c534..f9fbb76bd 100644
--- a/Tests/Manual/TableTest/AppController.j
+++ b/Tests/Manual/TableTest/AppController.j
@@ -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];
diff --git a/Tools/capp/Generate.j b/Tools/capp/Generate.j
index ba10684f7..5e3e7b8e1 100644
--- a/Tools/capp/Generate.j
+++ b/Tools/capp/Generate.j
@@ -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 = {};
diff --git a/Tools/press/cib-analysis-tools.j b/Tools/press/cib-analysis-tools.j
new file mode 100644
index 000000000..cab6a919a
--- /dev/null
+++ b/Tools/press/cib-analysis-tools.j
@@ -0,0 +1,74 @@
+@import
+@import
+
+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
diff --git a/Tools/press/cib-dump b/Tools/press/cib-dump
new file mode 100755
index 000000000..87fff35a5
--- /dev/null
+++ b/Tools/press/cib-dump
@@ -0,0 +1,18 @@
+#!/usr/bin/env objj
+
+@import
+@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) });
+ });
+}
diff --git a/Tools/press/main.j b/Tools/press/main.j
index f92270a50..f8f497823 100644
--- a/Tools/press/main.j
+++ b/Tools/press/main.j
@@ -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
+@import
@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 block
indexHTML = indexHTML.replace(/([ \t]*)(<\/head>)/, '$1 \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.");
diff --git a/Tools/press/objj-analysis-tools.j b/Tools/press/objj-analysis-tools.j
index 344148bc8..c45a7601b 100644
--- a/Tools/press/objj-analysis-tools.j
+++ b/Tools/press/objj-analysis-tools.j
@@ -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) {
diff --git a/bootstrap.sh b/bootstrap.sh
index df2c06bb9..8d03401f5 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -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."