From 492f4b648080c73c223d3caf64ac1330404224ef Mon Sep 17 00:00:00 2001 From: Francisco Ryan Tolmasky I Date: Sun, 1 Feb 2009 00:19:50 -0800 Subject: [PATCH] First pass at themes in Cappuccino. Reviewed by me. --- AppKit/AppKit.steam | 2 + AppKit/CPColor.j | 2 +- AppKit/CPControl.j | 2 +- AppKit/CPImage.j | 10 + AppKit/CPSlider.j | 746 +++++++++--------- AppKit/CPTheme.j | 286 +++++++ AppKit/CPView.j | 38 +- AppKit/Cib/_CPCibCustomResource.j | 57 +- AppKit/Info.plist | 4 + AppKit/Themes/Default/AppController.j | 169 ++++ AppKit/Themes/Default/Default.steam | 32 + AppKit/Themes/Default/Frameworks/AppKit | 1 + AppKit/Themes/Default/Frameworks/Debug/AppKit | 1 + .../Default/Frameworks/Debug/Foundation | 1 + .../Default/Frameworks/Debug/Objective-J | 1 + AppKit/Themes/Default/Frameworks/Foundation | 1 + AppKit/Themes/Default/Frameworks/Objective-J | 1 + AppKit/Themes/Default/Info.plist | 12 + .../Resources/horizontal-track-center.png} | Bin .../Resources/horizontal-track-left.png} | Bin .../Resources/horizontal-track-right.png} | Bin .../Default/Resources/knob-highlighted.png | Bin 0 -> 3161 bytes AppKit/Themes/Default/Resources/knob.png | Bin 0 -> 3210 bytes .../Resources/vertical-track-bottom.png} | Bin 3064 -> 2816 bytes .../Resources/vertical-track-center.png} | Bin 3093 -> 2804 bytes .../Default/Resources/vertical-track-top.png | Bin 0 -> 2818 bytes AppKit/Themes/Default/index-debug.html | 35 + AppKit/Themes/Default/index.html | 36 + AppKit/Themes/Default/main.j | 17 + AppKit/build.xml | 12 + Objective-J/evaluate.js | 6 + Objective-J/file.js | 28 +- Tools/Utilities/bundle.js | 131 +++ Tools/Utilities/file.js | 99 +++ Tools/steam/Project.js | 447 +++++++++++ Tools/steam/build.js | 102 +++ Tools/steam/build.xml | 10 +- Tools/steam/create-frameworks.js | 4 + Tools/steam/create.js | 77 ++ Tools/steam/inline-bundle.js | 156 ++++ Tools/steam/main.js | 201 +++++ Tools/steam/steam.js | 732 ----------------- Tools/steam/steam.xml | 19 + Tools/steam/usage.js | 22 + Tools/steam/version.js | 5 + 45 files changed, 2401 insertions(+), 1104 deletions(-) create mode 100644 AppKit/CPTheme.j create mode 100644 AppKit/Themes/Default/AppController.j create mode 100644 AppKit/Themes/Default/Default.steam create mode 120000 AppKit/Themes/Default/Frameworks/AppKit create mode 120000 AppKit/Themes/Default/Frameworks/Debug/AppKit create mode 120000 AppKit/Themes/Default/Frameworks/Debug/Foundation create mode 120000 AppKit/Themes/Default/Frameworks/Debug/Objective-J create mode 120000 AppKit/Themes/Default/Frameworks/Foundation create mode 120000 AppKit/Themes/Default/Frameworks/Objective-J create mode 100644 AppKit/Themes/Default/Info.plist rename AppKit/{Resources/CPSlider/CPSliderTrackHorizontalCenter.png => Themes/Default/Resources/horizontal-track-center.png} (100%) rename AppKit/{Resources/CPSlider/CPSliderTrackHorizontalLeft.png => Themes/Default/Resources/horizontal-track-left.png} (100%) rename AppKit/{Resources/CPSlider/CPSliderTrackHorizontalRight.png => Themes/Default/Resources/horizontal-track-right.png} (100%) create mode 100644 AppKit/Themes/Default/Resources/knob-highlighted.png create mode 100644 AppKit/Themes/Default/Resources/knob.png rename AppKit/{Resources/CPSlider/CPSliderKnobRegularPushed.png => Themes/Default/Resources/vertical-track-bottom.png} (87%) rename AppKit/{Resources/CPSlider/CPSliderKnobRegular.png => Themes/Default/Resources/vertical-track-center.png} (86%) create mode 100644 AppKit/Themes/Default/Resources/vertical-track-top.png create mode 100644 AppKit/Themes/Default/index-debug.html create mode 100644 AppKit/Themes/Default/index.html create mode 100644 AppKit/Themes/Default/main.j create mode 100644 Tools/Utilities/bundle.js create mode 100644 Tools/Utilities/file.js create mode 100644 Tools/steam/Project.js create mode 100644 Tools/steam/build.js create mode 100644 Tools/steam/create-frameworks.js create mode 100644 Tools/steam/create.js create mode 100644 Tools/steam/inline-bundle.js create mode 100644 Tools/steam/main.js delete mode 100644 Tools/steam/steam.js create mode 100644 Tools/steam/usage.js create mode 100644 Tools/steam/version.js diff --git a/AppKit/AppKit.steam b/AppKit/AppKit.steam index 134c9b59f..58d524005 100644 --- a/AppKit/AppKit.steam +++ b/AppKit/AppKit.steam @@ -15,6 +15,7 @@ CPTableColumn.j CPTableView.j + Themes CoreGraphics/CGContextCanvas.j CoreGraphics/CGContextVML.j @@ -29,6 +30,7 @@ CPOutlineView.j CPTableColumn.j CPTableView.j + Themes CoreGraphics/CGContextCanvas.j CoreGraphics/CGContextVML.j diff --git a/AppKit/CPColor.j b/AppKit/CPColor.j index 97cb4364b..c26071173 100644 --- a/AppKit/CPColor.j +++ b/AppKit/CPColor.j @@ -324,7 +324,7 @@ var _hueComponent = 0, if (self) { _patternImage = anImage; - _cssString = "url(\"" + _patternImage._filename + "\")"; + _cssString = "url(\"" + [_patternImage filename] + "\")"; } return self; diff --git a/AppKit/CPControl.j b/AppKit/CPControl.j index 23fbf5b1e..87c1c0fb6 100644 --- a/AppKit/CPControl.j +++ b/AppKit/CPControl.j @@ -393,7 +393,7 @@ var CPControlBlackColor = [CPColor blackColor]; if ((_sendActionOn & (1 << type)) && isWithinFrame) [self sendAction:_action to:_target]; - _trackingWasInFrame = isWithinFrame; + _trackingWasWithinFrame = isWithinFrame; _previousTrackingLocation = currentLocation; } diff --git a/AppKit/CPImage.j b/AppKit/CPImage.j index 34ff42ee7..5bf02cfd6 100644 --- a/AppKit/CPImage.j +++ b/AppKit/CPImage.j @@ -338,6 +338,11 @@ function CPImageInBundle(aFilename, aSize, aBundle) return self; } +- (CPString)filename +{ + return @""; +} + - (CPArray)imageSlices { return _imageSlices; @@ -402,6 +407,11 @@ var CPThreePartImageImageSlicesKey = @"CPThreePartImageImageSlicesKey", return self; } +- (CPString)filename +{ + return @""; +} + - (CPArray)imageSlices { return _imageSlices; diff --git a/AppKit/CPSlider.j b/AppKit/CPSlider.j index 22e64bbec..1d05b0f17 100644 --- a/AppKit/CPSlider.j +++ b/AppKit/CPSlider.j @@ -1,67 +1,28 @@ -/* - * CPSlider.j - * AppKit - * - * Created by Francisco Tolmasky. - * Copyright 2008, 280 North, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -@import "CPControl.j" +@import + +#include "CoreGraphics/CGGeometry.h" -var CPSliderHorizontalKnobImage = nil, - CPSliderHorizontalBarLeftImage = nil, - CPSliderHorizontalBarRightImage = nil, - CPSliderHorizontalBarCenterImage = nil; - -/*! @class CPSlider - - An CPSlider displays, and allows control of, some value in the application. It represents a continuous stream of values of type float, which can be retrieved by the method floatValue and set by the method setFloatValue:. -*/ @implementation CPSlider : CPControl { - double _minValue; - double _maxValue; - double _altIncrementValue; - BOOL _isVertical; + double _minValue; + double _maxValue; + double _altIncrementValue; - CPView _bar; - CPView _knob; - - CPImageView _standardKnob; - CPView _standardVerticalBar; - CPView _standardHorizontalBar; -} - -/* - @ignore -*/ -+ (void)initialize -{ - if (self != [CPSlider class]) - return; - - var bundle = [CPBundle bundleForClass:self]; + CPColor _verticalTrackColor; // vertical-track-color + CPColor _horizontalTrackColor; // horizontal-track-color - CPSliderKnobImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:"CPSlider/CPSliderKnobRegular.png"] size:CPSizeMake(11.0, 11.0)], - CPSliderKnobPushedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:"CPSlider/CPSliderKnobRegularPushed.png"] size:CPSizeMake(11.0, 11.0)], - CPSliderHorizontalBarLeftImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:"CPSlider/CPSliderTrackHorizontalLeft.png"] size:CPSizeMake(2.0, 4.0)], - CPSliderHorizontalBarRightImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:"CPSlider/CPSliderTrackHorizontalRight.png"] size:CPSizeMake(2.0, 4.0)], - CPSliderHorizontalBarCenterImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:"CPSlider/CPSliderTrackHorizontalCenter.png"] size:CPSizeMake(1.0, 4.0)]; + CPColor _knobColor; // knob-color + CPColor _highlightedKnobColor; // knob-color-highlighted + + float _trackWidth; // track-width + CGSize _knobSize; // knob-size + + BOOL _isHighlighted; + + CPView _trackView; + CPView _knobView; } - (id)initWithFrame:(CGRect)aFrame @@ -70,83 +31,353 @@ var CPSliderHorizontalKnobImage = nil, if (self) { - _value = 50.0; _minValue = 0.0; _maxValue = 100.0; - - _bar = [self bar]; - _knob = [self knob]; - _knobSize = [[self knobImage] size]; - _isVertical = [self isVertical]; + + [self setObjectValue:50.0]; [self setContinuous:YES]; - - [_knob setFrameOrigin:[self knobPosition]]; - - [self addSubview:_bar]; - [self addSubview:_knob]; } return self; } - -- (void)setFrameSize:(CGSize)aSize + +- (void)setMinValue:(float)aMinimumValue { - if (aSize.height > 21.0) - aSize.height = 21.0; + if (_minValue === aMinimumValue) + return; - if (_isVertical != [self isVertical]) + _minValue = aMinimumValue; + + var doubleValue = [self doubleValue]; + + if (doubleValue < _minValue) + [self setdoubleValue:_minValue]; +} + +- (float)minValue +{ + return _minValue; +} + +- (void)setMaxValue:(float)aMaximumValue +{ + if (_maxValue === aMaximumValue) + return; + + _maxValue = aMaximumValue; + + var doubleValue = [self doubleValue]; + + if (doubleValue > _maxValue) + [self setdoubleValue:_maxValue]; +} + +- (float)maxValue +{ + return _maxValue; +} + +- (void)setValue:(id)aValue +{ + CPLog.warn("[CPSlider setValue:] is deprecated, use setDoubleValue: instead."); + + [self setObjectValue:aValue]; +} + +- (void)setObjectValue:(id)aValue +{ + [super setObjectValue:aValue]; + + [self setNeedsDisplay:YES]; +} + +- (void)setHorizontalTrackColor:(CPColor)aColor +{ + if (_horizontalTrackColor === aColor) + return; + + _horizontalTrackColor = aColor; + + [self setNeedsDisplay:YES]; +} + +- (CPColor)horizontalTrackColor +{ + return _horizontalTrackColor; +} + +- (void)setVerticalTrackColor:(CPColor)aColor +{ + if (_verticalTrackColor === aColor) + return; + + _verticalTrackColor = aColor; + + [self setNeedsDisplay:YES]; +} + +- (CPColor)verticalTrackColor +{ + return _verticalTrackColor; +} + +- (void)setTrackWidth:(float)aTrackWidth +{ + if (_trackWidth === aTrackWidth) + return; + + _trackWidth = aTrackWidth; + + [self setNeedsDisplay:YES]; +} + +- (float)trackWidth +{ + return _trackWidth; +} + +- (CGRect)trackRectForBounds:(CGRect)bounds +{ + var trackWidth = [self trackWidth]; + + if (!trackWidth) + return _CGRectMakeZero(); + + if ([self isVertical]) { - _isVertical = [self isVertical]; - - var bar = [self bar], - knob = [self knob]; - - if (_bar != bar) - [self replaceSubview:_bar = bar withView:_bar]; - - if (_knob != knob) - { - [self replaceSubview:knob withView:_knob]; - - _knob = knob; - [_knob setFrameOrigin:[self knobPosition]]; - } + bounds.origin.x = (_CGRectGetWidth(bounds) - trackWidth) / 2.0; + bounds.size.width = _trackWidth; + } + else + { + bounds.origin.y = (_CGRectGetHeight(bounds) - trackWidth) / 2.0; + bounds.size.height = _trackWidth; } - [super setFrameSize:aSize]; + return bounds; +} + +- (void)setHighlightedKnobColor:(CPColor)aColor +{ + if (_highlightedKnobColor === aColor) + _highlightedKnobColor = aColor; - [_knob setFrameOrigin:[self knobPosition]]; + _highlightedKnobColor = aColor; } -/*! - Returns the value by which the slider will be - incremented if the user holds down the ALTs key. -*/ -- (double)altIncrementValue +- (CPColor)highlightedKnobColor { - return _altIncrementValue; + return _highlightedKnobColor; } -/*! - Sets the value the slider will be incremented if the user holds the ALT key. -*/ -- (void)setAltIncrementValue:(double)anIncrementValue +- (void)setKnobSize:(CGSize)aKnobSize { - _altIncrementValue = anIncrementValue; + if (_knobSize && (!aKnobSize || _CGSizeEqualToSize(_knobSize, aKnobSize))) + return; + + _knobSize = aKnobSize ? _CGSizeMakeCopy(aKnobSize) : nil; + + [self setNeedsDisplay:YES]; } -/*! - Returns whether the control can continuously send its action messages. -*/ -- (BOOL)isContinuous +- (void)setKnobColor:(CPColor)aColor { - return (_sendActionOn & CPLeftMouseDraggedMask) != 0; + if (_knobColor === aColor) + return; + + _knobColor = aColor; + + [self setNeedsDisplay:YES]; +} + +- (CPColor)knobColor +{ + return _knobColor; +} + +- (CGRect)knobRectForBounds:(CGRect)bounds +{ + if (!_knobSize || _knobSize.width <= 0 || _knobSize.height <= 0) + return _CGRectMakeZero(); + + var knobRect = _CGRectMake(0.0, 0.0, _knobSize.width, _knobSize.height), + trackRect = [self trackRectForBounds:bounds]; + + // No track, do our best to approximate a place for this thing. + if (!trackRect || _CGRectIsEmpty(trackRect)) + trackRect = bounds; + + if ([self isVertical]) + { + knobRect.origin.x = _CGRectGetMidX(trackRect) - _knobSize.width / 2.0; + knobRect.origin.y = (([self doubleValue] - _minValue) / (_maxValue - _minValue)) * (_CGRectGetHeight(trackRect) - _knobSize.height); + } + else + { + knobRect.origin.x = (([self doubleValue] - _minValue) / (_maxValue - _minValue)) * (_CGRectGetWidth(trackRect) - _knobSize.width); + knobRect.origin.y = _CGRectGetMidY(trackRect) - _knobSize.height / 2.0; + } + + return knobRect; +} + +- (int)isVertical +{ + var bounds = [self bounds], + width = CGRectGetWidth(bounds), + height = CGRectGetHeight(bounds); + + return width < height ? 1 : (width > height ? 0 : -1); +} + +- (void)drawRect:(CGRect)aRect +{ + var bounds = [self bounds], + isVertical = [self isVertical], + trackRect = nil; + + if ((isVertical && _verticalTrackColor || !isVertical && _horizontalTrackColor) && + (trackRect = [self trackRectForBounds:_CGRectMakeCopy(bounds)]) && !_CGRectIsEmpty(trackRect)) + { + if (!_trackView) + { + _trackView = [[CPView alloc] initWithFrame:trackRect]; + + [_trackView setHitTests:NO]; + + [self addSubview:_trackView positioned:CPWindowBelow relativeTo:_knobView]; + } + else + [_trackView setFrame:trackRect]; + + if ([self isVertical]) + [_trackView setBackgroundColor:_verticalTrackColor]; + else + [_trackView setBackgroundColor:_horizontalTrackColor]; + } + else if (_trackView) + { + [_trackView removeFromSuperview]; + + _trackView = nil; + } + + var knobRect = nil; + + if (_knobColor && (knobRect = [self knobRectForBounds:bounds]) && !_CGRectIsEmpty(knobRect)) + { + if (!_knobView) + { + _knobView = [[CPView alloc] initWithFrame:knobRect]; + + [_knobView setHitTests:NO]; + + [self addSubview:_knobView positioned:CPWindowAbove relativeTo:_trackView]; + } + else + [_knobView setFrame:knobRect]; + + if (_isHighlighted) + { + if (_highlightedKnobColor) + [_knobView setBackgroundColor:_highlightedKnobColor]; + } + else + [_knobView setBackgroundColor:_knobColor]; + } + else if (_knobView) + { + [_knobView removeFromSuperview]; + + _knobView = nil; + } +} + +- (BOOL)tracksMouseOutsideOfFrame +{ + return YES; +} + +- (float)_valueAtPoint:(CGPoint)aPoint +{ + var bounds = [self bounds], + knobRect = [self knobRectForBounds:bounds], + trackRect = [self trackRectForBounds:bounds]; + + if ([self isVertical]) + { + var knobHeight = _CGRectGetHeight(knobRect); + + trackRect.origin.y += knobHeight / 2; + trackRect.size.height -= knobHeight; + + var minValue = [self minValue]; + + return MAX(0.0, MIN(1.0, (aPoint.y - _CGRectGetMinY(trackRect)) / _CGRectGetHeight(trackRect))) * ([self maxValue] - minValue) + minValue; + } + else + + var knobWidth = _CGRectGetWidth(knobRect); + + trackRect.origin.x += knobWidth / 2; + trackRect.size.width -= knobWidth; + + var minValue = [self minValue]; + + return MAX(0.0, MIN(1.0, (aPoint.x - _CGRectGetMinX(trackRect)) / _CGRectGetWidth(trackRect))) * ([self maxValue] - minValue) + minValue; +} + +- (BOOL)startTrackingAt:(CGPoint)aPoint +{ + var bounds = [self bounds], + knobRect = [self knobRectForBounds:_CGRectMakeCopy(bounds)]; + + if (_CGRectContainsPoint(knobRect, aPoint)) + _dragOffset = _CGSizeMake(_CGRectGetMidX(knobRect) - aPoint.x, _CGRectGetMidY(knobRect) - aPoint.y); + + else + { + var trackRect = [self trackRectForBounds:bounds]; + + if (trackRect && _CGRectContainsPoint(trackRect, aPoint)) + { + _dragOffset = _CGSizeMakeZero(); + + [self setObjectValue:[self _valueAtPoint:aPoint]]; + } + + else + return NO; + } + + _isHighlighted = YES; + [self setNeedsDisplay:YES]; + + return YES; +} + +- (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint +{ + [self setObjectValue:[self _valueAtPoint:_CGPointMake(aPoint.x + _dragOffset.width, aPoint.y + _dragOffset.height)]]; + + return YES; +} + +- (void)stopTracking:(CGPoint)lastPoint at:(CGPoint)aPoint mouseIsUp:(BOOL)mouseIsUp +{ + _isHighlighted = NO; + + if ([_target respondsToSelector:@selector(sliderDidFinish:)]) + [_target sliderDidFinish:self]; + + [self setNeedsDisplay:YES]; } /*! - Sets whether the cell can continuously send its action messages. - */ + @ignore + shoudl we have _continuous? +*/ - (void)setContinuous:(BOOL)flag { if (flag) @@ -155,255 +386,52 @@ var CPSliderHorizontalKnobImage = nil, _sendActionOn &= ~CPLeftMouseDraggedMask; } -/*! - Returns the thickness of the slider's knob. This value is in pixels, - and is the size of the knob along the slider's track. -*/ -- (float)knobThickness -{ - return CPRectGetWidth([_knob frame]); -} +@end -/* - @ignore -*/ -- (CPImage)leftTrackImage -{ - return CPSliderHorizontalBarLeftImage; -} +@implementation CPSlider (Theming) -/* - @ignore -*/ -- (CPImage)rightTrackImage +- (void)viewDidChangeTheme { - return CPSliderHorizontalBarRightImage; -} - -/* - @ignore -*/ -- (CPImage)centerTrackImage -{ - return CPSliderHorizontalBarCenterImage -} - -/* - @ignore -*/ -- (CPImage)knobImage -{ - return CPSliderKnobImage; -} - -/* - @ignore -*/ -- (CPImage)pushedKnobImage -{ - return CPSliderKnobPushedImage; -} - -/*! - Returns the slider's knob. -*/ -- (CPView)knob -{ - if (!_standardKnob) - { - var knobImage = [self knobImage], - knobSize = [knobImage size]; - - _standardKnob = [[CPImageView alloc] initWithFrame:CPRectMake(0.0, 0.0, knobSize.width, knobSize.height)]; - - [_standardKnob setHitTests:NO]; - [_standardKnob setImage:knobImage]; - } + [super viewDidChangeTheme]; - return _standardKnob; -} - -/*! - Returns the slider's bar. -*/ -- (CPView)bar -{ - // FIXME: veritcal. - if ([self isVertical]) - return nil; - else - { - if (!_standardHorizontalBar) - { - var frame = [self frame], - barFrame = CPRectMake(0.0, 0.0, CPRectGetWidth(frame), 4.0); - - _standardHorizontalBar = [[CPView alloc] initWithFrame:barFrame]; - - [_standardHorizontalBar setBackgroundColor:[CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices: - [[self leftTrackImage], [self centerTrackImage], [self rightTrackImage]] isVertical:NO]]]; - - [_standardHorizontalBar setFrame:CPRectMake(0.0, (CPRectGetHeight(frame) - CPRectGetHeight(barFrame)) / 2.0, CPRectGetWidth(_isVertical ? barFrame : frame), CPRectGetHeight(_isVertical ? frame : barFrame))]; - [_standardHorizontalBar setAutoresizingMask:_isVertical ? CPViewHeightSizable : CPViewWidthSizable]; - } - - return _standardHorizontalBar; - } -} - -/*! - Returns YES if the slider is vertical. -*/ -- (BOOL)isVertical -{ - var frame = [self frame]; + var theme = [self theme]; - if (CPRectGetWidth(frame) == CPRectGetHeight(frame)) - return -1; + if (!theme) + return; + + [self setKnobSize:[theme valueForKey:@"knob-size"]]; + [self setKnobColor:[theme valueForKey:@"knob-color"]]; + [self setHighlightedKnobColor:[theme valueForKey:@"knob-color-highlighted"]]; - return CPRectGetWidth(frame) < CPRectGetHeight(frame); -} - -/*! - Returns the slider's maximum value -*/ -- (double)maxValue -{ - return _maxValue; -} - -/*! - Returns the slider's minimum value -*/ -- (double)minValue -{ - return _minValue; -} - -/*! - Sets the slider's maximum value - @param aMaxValue the new maximum value -*/ -- (void)setMaxValue:(double)aMaxValue -{ - _maxValue = aMaxValue; -} - -/*! - Sets the slider's minimum value - @param aMinValue the new minimum value -*/ -- (void)setMinValue:(double)aMinValue -{ - _minValue = aMinValue; -} - -/*! - Sets the slider's value - @param aValue the new slider value - @deprecated Use setFloatValue, setObjectValue, etc -*/ -- (void)setValue:(double)aValue -{ - [self setObjectValue:aValue]; -} - -/*! - Returns the slider's value - @deprecated Use floatValue, objectValue, etc -*/ -- (double)value -{ - return [self floatValue]; -} - -- (void)setObjectValue:(id)anObject -{ - [super setObjectValue:anObject]; + [self setTrackWidth:[theme valueForKey:@"track-width"]]; + [self setHorizontalTrackColor:[theme valueForKey:@"horizontal-track-color"]]; + [self setVerticalTrackColor:[theme valueForKey:@"vertical-track-color"]]; - if (_knob) - [_knob setFrameOrigin:[self knobPosition]]; + [self setNeedsDisplay:YES]; } -/* - Returns the knob's position - @ignore -*/ -- (CGPoint)knobPosition +- (CPDictionary)themedValues { - if ([self isVertical]) - return CPPointMake(0.0, 0.0); - else - return CPPointMake( - (([self floatValue] - _minValue) / (_maxValue - _minValue)) * (CPRectGetWidth([self frame]) - CPRectGetWidth([_knob frame])), - (CPRectGetHeight([self frame]) - CPRectGetHeight([_knob frame])) / 2.0); -} - -/* - @ignore -*/ -- (float)valueForKnobPosition:(CGPoint)aPoint -{ - if ([self isVertical]) - return 0.0; - else - return MAX(MIN((aPoint.x) * (_maxValue - _minValue) / ( CPRectGetWidth([self frame]) - CPRectGetWidth([_knob frame]) ) + _minValue, _maxValue), _minValue); -} - -- (CGPoint)constrainKnobPosition:(CGPoint)aPoint -{ - //FIXME - aPoint.x -= _knobSize.width / 2.0; - return CPPointMake(MAX(MIN(CPRectGetWidth([self bounds]) - _knobSize.width, aPoint.x), 0.0), (CPRectGetHeight([self bounds]) - CPRectGetHeight([_knob frame])) / 2.0); -} - -- (BOOL)tracksMouseOutsideOfFrame -{ - return YES; -} - -- (BOOL)startTrackingAt:(CGPoint)aPoint -{ - [[self knob] setImage:[self pushedKnobImage]]; + var values = [super themedValues]; - [_knob setFrameOrigin:[self constrainKnobPosition:aPoint]]; + [values setObject:_knobSize forKey:@"knob-size"]; + [values setObject:_knobColor forKey:@"knob-color"]; + [values setObject:_highlightedKnobColor forKey:@"knob-color-highlighted"]; + [values setObject:_trackWidth forKey:@"track-width"]; + [values setObject:_verticalTrackColor forKey:@"vertical-track-color"]; + [values setObject:_horizontalTrackColor forKey:@"horizontal-track-color"]; - [super setObjectValue:[self valueForKnobPosition:[_knob frame].origin]]; - - return YES; -} - -- (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint -{ - [_knob setFrameOrigin:[self constrainKnobPosition:aPoint]]; - - [super setObjectValue:[self valueForKnobPosition:[_knob frame].origin]]; - - return YES; -} - -- (void)stopTracking:(CGPoint)lastPoint at:(CGPoint)aPoint mouseIsUp:(BOOL)mouseIsUp -{ - [[self knob] setImage:[self knobImage]]; - - if ([_target respondsToSelector:@selector(sliderDidFinish:)]) - [_target sliderDidFinish:self]; + return values; } @end var CPSliderMinValueKey = "CPSliderMinValueKey", CPSliderMaxValueKey = "CPSliderMaxValueKey", - CPSliderAltIncrValueKey = "CPSliderAltIncrValueKey", - CPSliderIsVerticalKey = "CPSliderIsVerticalKey"; + CPSliderAltIncrValueKey = "CPSliderAltIncrValueKey"; @implementation CPSlider (CPCoding) -/*! - Initializes the slider from the data in a coder. - @param aCoder the coder from which to read the data - @return the initialized slider -*/ - (id)initWithCoder:(CPCoder)aCoder { self = [super initWithCoder:aCoder]; @@ -413,32 +441,37 @@ var CPSliderMinValueKey = "CPSliderMinValueKey", _minValue = [aCoder decodeDoubleForKey:CPSliderMinValueKey]; _maxValue = [aCoder decodeDoubleForKey:CPSliderMaxValueKey]; _altIncrementValue = [aCoder decodeDoubleForKey:CPSliderAltIncrValueKey]; - _isVertical = [aCoder decodeDoubleForKey:CPSliderIsVerticalKey]; - _bar = [self bar]; - _knob = [self knob]; - _knobSize = [[self knobImage] size]; - _isVertical = [self isVertical]; - - [_knob setFrameOrigin:[self knobPosition]]; - - [self addSubview:_bar]; - [self addSubview:_knob]; + [self setContinuous:YES]; + + [self setNeedsDisplay:YES]; } return self; } -/*! - Writes out the slider's instance information to a coder. - @param aCoder the coder to which to write the data -*/ - (void)encodeWithCoder:(CPCoder)aCoder { - var subviews = _subviews; + [super encodeWithCoder:aCoder]; + + var count = [_subviews count], + subviews = nil; + + if (count) + { + subviews = _subviews; + + if (count === 2 && _trackView && _knobView) + _subviews = []; + else + { + if (_trackView) + [_subviews removeObjectIdenticalTo:_trackView]; + if (_knobView) + [_subviews removeObjectIdenticalTo:_knobView]; + } + } - _subviews = []; - [super encodeWithCoder:aCoder]; _subviews = subviews; @@ -446,7 +479,12 @@ var CPSliderMinValueKey = "CPSliderMinValueKey", [aCoder encodeDouble:_minValue forKey:CPSliderMinValueKey]; [aCoder encodeDouble:_maxValue forKey:CPSliderMaxValueKey]; [aCoder encodeDouble:_altIncrementValue forKey:CPSliderAltIncrValueKey]; - [aCoder encodeBool:_isVertical forKey:CPSliderIsVerticalKey]; + + // NO! +/* [aCoder encodeObject:_verticalTrackColor forKey:"1"]; + [aCoder encodeObject:_horizontalTrackColor forKey:"2"]; + [aCoder encodeObject:_knobColor forKey:"3"]; + [aCoder encodeObject:_highlightedKnobColor forKey:"4"];*/ } @end diff --git a/AppKit/CPTheme.j b/AppKit/CPTheme.j new file mode 100644 index 000000000..89c85aa3c --- /dev/null +++ b/AppKit/CPTheme.j @@ -0,0 +1,286 @@ + +@import +@import +@import + + +var CPThemesByName = nil, + CPThemeDefaultTheme = nil, + + CPThemeViewClass = Nil, + CPThemeWindowClass = Nil; + +@implementation CPTheme : CPObject +{ + CPString _name; + Class _activeClass; + JSObject _classTable; +} + ++ (void)initialize +{ + if (self !== [CPTheme class]) + return; + + CPThemesByName = {}; + + CPThemeViewClass = [CPView class]; + CPThemeWindowClass = [CPWindow class]; + + var bundle = [CPBundle bundleForClass:self]; + defaultThemePath = [bundle objectForInfoDictionaryKey:@"Default Themes Path"], + defaultThemeName = [bundle objectForInfoDictionaryKey:@"Default Theme Name"]; + + if (!defaultThemePath) + return; + + defaultThemePath = [bundle pathForResource:defaultThemePath]; + + var file = objj_files[defaultThemePath + "/Info.plist"]; + + if (!file) + return; + + // Oh boy are we tricky. + var infoDictionary = CPPropertyListCreateFromData([CPData dataWithString:objj_files[defaultThemePath + "/Info.plist"].contents]); + + themes = [infoDictionary objectForKey:@"CPBundleReplacedFiles"], + + themeIndex = 0, + themeCount = [themes count]; + + for (; themeIndex < themeCount; ++themeIndex) + { + var unarchiver = [[_CPThemeKeyedUnarchiver alloc] + initForReadingWithData:[CPData dataWithString:objj_files[defaultThemePath + '/' + themes[themeIndex]].contents] + bundle:file.bundle]; + + [unarchiver decodeObjectForKey:@"root"]; + + [unarchiver finishDecoding]; + } + + [self setDefaultTheme:[CPTheme themeNamed:defaultThemeName]]; +} + ++ (void)setDefaultTheme:(CPTheme)aTheme +{ + CPThemeDefaultTheme = aTheme; +} + ++ (CPTheme)defaultTheme +{ + return CPThemeDefaultTheme; +} + ++ (CPTheme)themeNamed:(CPString)aName +{ + return CPThemesByName[aName]; +} + ++ (void)loadThemesAtURL:(CPURL)aURL delegate:(id)aLoadDelegate +{ + +} + +- (id)initWithName:(CPString)aName +{ + self = [super init]; + + if (self) + { + _name = aName; + _classTable = {}; + _classTable[[[self class] className]] = {}; + + CPThemesByName[_name] = aName; + } + + return self; +} + +- (CPString)name +{ + return _name; +} + +- (void)setActiveClass:(Class)aClass +{ + _activeClass = aClass; +} + +- (Class)activeClass +{ + return _activeClass; +} + +- (id)valueForKey:(CPString)aKey +{ + return [self valueForKey:aKey inClass:_activeClass]; +} + +- (id)valueForKey:(CPString)aKey inClass:(CPClass)aClass +{ + if (!aClass) + throw "no!"; + + var className = [aClass className], + table = _classTable[className]; + + if (!table) + return nil; + + var value = table[aKey]; + + if (!value) + return nil; + + return value; +} + +- (void)takeThemeFromObject:(id)anObject +{ + var values = [anObject themedValues], + key = nil, + keys = [values keyEnumerator], + objectClass = [anObject class]; + + while (key = [keys nextObject]) + [self addValue:[values objectForKey:key] forKey:key inClass:objectClass]; +} + +- (void)setDefaultValue:(id)aValue forKey:(CPString)aKey +{ + [self addValue:aValue forKey:aKey inClass:[self class]]; +} + +- (void)addValue:(id)aValue forKey:(CPString)aKey inClass:(Class)aClass +{ + if (!aValue) + return; + + var className = [aClass className], + table = _classTable[className]; + + if (!table) + { + var classNames = []; + + while (!table && (aClass !== CPThemeViewClass) && (aClass !== CPThemeWindowClass)) + { + classNames.push(className); + + aClass = [aClass superclass]; + className = [aClass className]; + table = _classTable[className]; + } + + if (!table) + table = _classTable[[[self class] className]]; + + var count = [classNames count]; + + while (count--) + { + className = classNames[count]; + + _classTable[className] = {}; + _classTable[className].prototype = table; + + table = _classTable[className]; + } + } + + if (table[aKey] !== aValue) + table[aKey] = aValue; +} + +@end + +var CPThemeNameKey = @"CPThemeNameKey", + CPThemeClassNamesArrayKey = @"CPThemeClassNamesArrayKey"; + +@implementation CPTheme (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super init]; + + _name = [aCoder decodeObjectForKey:CPThemeNameKey]; + _classTable = {}; + + CPThemesByName[_name] = self; + + if (self) + { + var classNamesArray = [aCoder decodeObjectForKey:CPThemeClassNamesArrayKey], + count = classNamesArray.length; + + while (count--) + { + var className = classNamesArray[count], + theClass = objj_getClass(className), + values = [aCoder decodeObjectForKey:className], + keys = [values allKeys], + keyCount = keys.length; + + while (keyCount--) + { + var key = keys[keyCount]; + + [self addValue:[values objectForKey:key] forKey:key inClass:theClass]; + } + } + } + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + var classNamesArray = []; + + for (var className in _classTable) + { + if (_classTable.hasOwnProperty(className)) + { + var values = _classTable[className], + valuesDictionary = [CPDictionary dictionary]; + + for (var key in values) + if (key !== "prototype" && values.hasOwnProperty(key)) + [valuesDictionary setObject:values[key] forKey:key]; + + [aCoder encodeObject:valuesDictionary forKey:className]; + + classNamesArray.push(className); + } + } + + [aCoder encodeObject:_name forKey:CPThemeNameKey]; + [aCoder encodeObject:classNamesArray forKey:CPThemeClassNamesArrayKey]; +} + +@end + +@implementation _CPThemeKeyedUnarchiver : CPKeyedUnarchiver +{ + CPBundle _bundle; +} + +- (id)initForReadingWithData:(CPData)data bundle:(CPBundle)aBundle +{ + self = [super initForReadingWithData:data]; + + if (self) + _bundle = aBundle; + + return self; +} + +- (CPBundle)bundle +{ + return _bundle; +} + +@end diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 86257d3fc..d8a672bba 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -29,8 +29,9 @@ @import "CPColor.j" @import "CPDOMDisplayServer.j" @import "CPGeometry.j" -@import "CPResponder.j" @import "CPGraphicsContext.j" +@import "CPResponder.j" +@import "CPTheme.j" #include "Platform/Platform.h" @@ -167,6 +168,9 @@ var DOMElementPrototype = nil, BOOL _isInFullScreenMode; _CPViewFullScreenModeState _fullScreenModeState; + + // Theming Support + CPTheme _theme; } /* @@ -237,6 +241,8 @@ var DOMElementPrototype = nil, _DOMImageParts = []; _DOMImageSizes = []; #endif + + [self setTheme:[CPTheme defaultTheme]]; } return self; @@ -1731,6 +1737,36 @@ setBoundsOrigin: @end +@implementation CPView (Theming) + +- (void)setTheme:(CPTheme)aTheme +{ + if (_theme === aTheme) + return; + + _theme = aTheme; + + [_theme setActiveClass:[self class]]; + [self viewDidChangeTheme]; + [_theme setActiveClass:Nil]; +} + +- (CPTheme)theme +{ + return _theme; +} + +- (void)viewDidChangeTheme +{ +} + +- (CPDictionary)themedValues +{ + return [CPDictionary dictionary]; +} + +@end + var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask", CPViewAutoresizesSubviewsKey = @"CPViewAutoresizesSubviews", CPViewBackgroundColorKey = @"CPViewBackgroundColor", diff --git a/AppKit/Cib/_CPCibCustomResource.j b/AppKit/Cib/_CPCibCustomResource.j index db87d1660..ec34cc349 100644 --- a/AppKit/Cib/_CPCibCustomResource.j +++ b/AppKit/Cib/_CPCibCustomResource.j @@ -28,22 +28,33 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey", - _CPCibCustomResourceResourceNameKey = @"_CPCibCustomResourceResourceNameKey"; + _CPCibCustomResourceResourceNameKey = @"_CPCibCustomResourceResourceNameKey", + _CPCibCustomResourcePropertiesKey = @"_CPCibCustomResourcePropertiesKey"; @implementation _CPCibCustomResource : CPObject { - CPString _className; - CPString _resourceName; + CPString _className; + CPString _resourceName; + CPDictionary _properties; } -- (CPString)filename ++ (id)imageResourceWithName:(CPString)aResourceName size:(CGSize)aSize { - return ""; + return [[self alloc] initWithClassName:@"CPImage" resourceName:aResourceName properties:[CPDictionary dictionaryWithObject:aSize forKey:@"size"]]; } -- (CGSize)size +- (id)initWithClassName:(CPString)aClassName resourceName:(CPString)aResourceName properties:(CPDictionary)properties { - return CGSizeMakeZero(); + self = [super init]; + + if (self) + { + _className = aClassName; + _resourceName = aResourceName; + _properties = properties; + } + + return self; } - (id)initWithCoder:(CPCoder)aCoder @@ -54,6 +65,7 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey", { _className = [aCoder decodeObjectForKey:_CPCibCustomResourceClassNameKey]; _resourceName = [aCoder decodeObjectForKey:_CPCibCustomResourceResourceNameKey]; + _properties = [aCoder decodeObjectForKey:_CPCibCustomResourcePropertiesKey]; } return self; @@ -63,15 +75,40 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey", { [aCoder encodeObject:_className forKey:_CPCibCustomResourceClassNameKey]; [aCoder encodeObject:_resourceName forKey:_CPCibCustomResourceResourceNameKey]; + [aCoder encodeObject:_properties forKey:_CPCibCustomResourcePropertiesKey]; } - (id)awakeAfterUsingCoder:(CPCoder)aCoder { - if ([aCoder isKindOfClass:[_CPCibKeyedUnarchiver class]]) + if ([aCoder respondsToSelector:@selector(bundle)]) if (_className === @"CPImage") - return [[CPImage alloc] initWithContentsOfFile:[[aCoder bundle] pathForResource:_resourceName]]; - + return [[CPImage alloc] initWithContentsOfFile:[[aCoder bundle] pathForResource:_resourceName] size:[_properties objectForKey:@"size"]]; + return self; } @end + +@implementation _CPCibCustomResource (CPImage) + +- (CPString)filename +{ + return [[CPBundle mainBundle] pathForResource:_resourceName]; +} + +- (CGSize)size +{ + return [_properties objectForKey:@"size"]; +} + +- (BOOL)isThreePartImage +{ + return NO; +} + +- (BOOL)isNinePartImage +{ + return NO; +} + +@end diff --git a/AppKit/Info.plist b/AppKit/Info.plist index ed261efba..c06c96b61 100644 --- a/AppKit/Info.plist +++ b/AppKit/Info.plist @@ -4,6 +4,10 @@ CPBundleIdentifier com.280n.AppKit + Default Themes Path + Default.cptheme + Default Theme Name + Default CPBundleInfoDictionaryVersion 6.0 CPBundleName diff --git a/AppKit/Themes/Default/AppController.j b/AppKit/Themes/Default/AppController.j new file mode 100644 index 000000000..518cc25e4 --- /dev/null +++ b/AppKit/Themes/Default/AppController.j @@ -0,0 +1,169 @@ +/* + * AppController.j + * + * Created by __Me__ on __Date__. + * Copyright 2008 __MyCompanyName__. All rights reserved. + */ + +@import +@import + + +@implementation AppController : CPObject +{ +} + +- (CPArray)themeNames +{ + return ["Default"]; +} + +- (void)viewsForDefaultTheme +{ + var views = [], + bundle = [CPBundle mainBundle]; + + // Horizontal Slider + + var horizontalTrackColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices: + [ + [_CPCibCustomResource imageResourceWithName:"horizontal-track-left.png" size:CPSizeMake(2.0, 4.0)], + [_CPCibCustomResource imageResourceWithName:"horizontal-track-center.png" size:CPSizeMake(1.0, 4.0)], + [_CPCibCustomResource imageResourceWithName:"horizontal-track-right.png" size:CPSizeMake(2.0, 4.0)] + ] + isVertical:NO]]; + + var horizontalSlider = [[CPSlider alloc] initWithFrame:CGRectMake(0.0, 0.0, 50.0, 24.0)]; + + [horizontalSlider setTrackWidth:4.0]; + [horizontalSlider setHorizontalTrackColor:horizontalTrackColor]; + + var knobColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"knob.png" size:CPSizeMake(11.0, 11.0)]]; + knobHighlightedColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"knob-highlighted.png" size:CPSizeMake(12.0, 12.0)]]; + + [horizontalSlider setKnobSize:CGSizeMake(12.0, 12.0)]; + [horizontalSlider setKnobColor:knobColor]; + [horizontalSlider setHighlightedKnobColor:knobHighlightedColor]; + + views.push(horizontalSlider); + + // Vertical Slider + + var verticalTrackColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices: + [ + [_CPCibCustomResource imageResourceWithName:"vertical-track-top.png" size:CPSizeMake(4.0, 2.0)], + [_CPCibCustomResource imageResourceWithName:"vertical-track-center.png" size:CPSizeMake(4.0, 1.0)], + [_CPCibCustomResource imageResourceWithName:"vertical-track-bottom.png" size:CPSizeMake(4.0, 2.0)] + ] + isVertical:YES]]; + + var verticalSlider = [[CPSlider alloc] initWithFrame:CGRectMake(0.0, 0.0, 24.0, 50.0)]; + + [verticalSlider setTrackWidth:4]; + [verticalSlider setVerticalTrackColor:verticalTrackColor]; + + [verticalSlider setKnobSize:CGSizeMake(12.0, 12.0)]; + [verticalSlider setKnobColor:knobColor]; + [verticalSlider setHighlightedKnobColor:knobHighlightedColor]; + + views.push(verticalSlider); + + return views; +} + +- (void)applicationDidFinishLaunching:(CPNotification)aNotification +{ + var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask], + contentView = [theWindow contentView], + bounds = [contentView bounds], + themeNames = [self themeNames], + index = 0, + count = themeNames.length; + + var tabView = [[CPTabView alloc] initWithFrame:bounds]; + + [tabView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; + + [contentView addSubview:tabView]; + + for (; index < count; ++index) + { + var item = [[CPTabViewItem alloc] initWithIdentifier:themeNames[index]], + selectorName = "viewsFor" + themeNames[index] + "Theme", + views = [self performSelector:selectorName], + viewsCount = [views count], + itemSize = CGSizeMake(0.0, 0.0); + + while (viewsCount--) + { + var size = [views[viewsCount] frame].size; + + if (size.width > itemSize.width) + itemSize.width = size.width; + + if (size.height > itemSize.height) + itemSize.height = size.height; + } + + itemSize.height += 30; + itemSize.width += 40; + + var collectionView = [[CPCollectionView alloc] initWithFrame:CGRectMakeZero()], + collectionViewItem = [[CPCollectionViewItem alloc] init]; + + [collectionViewItem setView:[[ThemedView alloc] init]]; + + [collectionView setItemPrototype:collectionViewItem]; + [collectionView setMinItemSize:itemSize]; + [collectionView setMaxItemSize:itemSize]; + [collectionView setVerticalMargin:5.0]; + [collectionView setContent:views]; + + [item setLabel:themeNames[index]]; + [item setView:collectionView]; + + [tabView addTabViewItem:item]; + } + + [theWindow orderFront:self]; +} + +@end + +@implementation ThemedView : CPView +{ + CPView _view; + CPTextField _label; +} + +- (void)setRepresentedObject:(id)anObject +{ + if (!_label) + { + _label = [[CPTextField alloc] initWithFrame:CGRectMakeZero()]; + + [_label setAlignment:CPCenterTextAlignment]; + [_label setAutoresizingMask:CPViewMinYMargin | CPViewWidthSizable]; + [_label setFont:[CPFont boldSystemFontOfSize:12.0]]; + + [self addSubview:_label]; + } + + [_label setStringValue:[anObject className]]; + [_label sizeToFit]; + + [_label setFrame:CGRectMake(0.0, CGRectGetHeight([self bounds]) - CGRectGetHeight([_label frame]), + CGRectGetWidth([self bounds]), CGRectGetHeight([_label frame]))]; + + if (_view) + [_view removeFromSuperview]; + + _view = anObject; + + [_view setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin | CPViewMinYMargin | CPViewMaxYMargin]; + [_view setFrameOrigin:CGPointMake((CGRectGetWidth([self bounds]) - CGRectGetWidth([_view frame])) / 2.0, (CGRectGetMinY([_label frame]) - CGRectGetHeight([_view frame])) / 2.0)]; + + [self addSubview:_view]; +} + +@end diff --git a/AppKit/Themes/Default/Default.steam b/AppKit/Themes/Default/Default.steam new file mode 100644 index 000000000..367779c42 --- /dev/null +++ b/AppKit/Themes/Default/Default.steam @@ -0,0 +1,32 @@ + + + + + Name + Default + Targets + + + Name + Default.cptheme + Type + 280N.theme + + + Configurations + + + Name + Debug + Flags + -DDEBUG -g + + + Name + Release + Flags + -O + + + + diff --git a/AppKit/Themes/Default/Frameworks/AppKit b/AppKit/Themes/Default/Frameworks/AppKit new file mode 120000 index 000000000..6f3e209f0 --- /dev/null +++ b/AppKit/Themes/Default/Frameworks/AppKit @@ -0,0 +1 @@ +/Users/tolmasky/Development/Build/Release/AppKit \ No newline at end of file diff --git a/AppKit/Themes/Default/Frameworks/Debug/AppKit b/AppKit/Themes/Default/Frameworks/Debug/AppKit new file mode 120000 index 000000000..e1a0507cb --- /dev/null +++ b/AppKit/Themes/Default/Frameworks/Debug/AppKit @@ -0,0 +1 @@ +/Users/tolmasky/Development/Build/Debug/AppKit \ No newline at end of file diff --git a/AppKit/Themes/Default/Frameworks/Debug/Foundation b/AppKit/Themes/Default/Frameworks/Debug/Foundation new file mode 120000 index 000000000..cba870cf2 --- /dev/null +++ b/AppKit/Themes/Default/Frameworks/Debug/Foundation @@ -0,0 +1 @@ +/Users/tolmasky/Development/Build/Debug/Foundation \ No newline at end of file diff --git a/AppKit/Themes/Default/Frameworks/Debug/Objective-J b/AppKit/Themes/Default/Frameworks/Debug/Objective-J new file mode 120000 index 000000000..99c1e032c --- /dev/null +++ b/AppKit/Themes/Default/Frameworks/Debug/Objective-J @@ -0,0 +1 @@ +/Users/tolmasky/Development/Build/Debug/Objective-J \ No newline at end of file diff --git a/AppKit/Themes/Default/Frameworks/Foundation b/AppKit/Themes/Default/Frameworks/Foundation new file mode 120000 index 000000000..b73c674fc --- /dev/null +++ b/AppKit/Themes/Default/Frameworks/Foundation @@ -0,0 +1 @@ +/Users/tolmasky/Development/Build/Release/Foundation \ No newline at end of file diff --git a/AppKit/Themes/Default/Frameworks/Objective-J b/AppKit/Themes/Default/Frameworks/Objective-J new file mode 120000 index 000000000..8674fc325 --- /dev/null +++ b/AppKit/Themes/Default/Frameworks/Objective-J @@ -0,0 +1 @@ +/Users/tolmasky/Development/Build/Release/Objective-J \ No newline at end of file diff --git a/AppKit/Themes/Default/Info.plist b/AppKit/Themes/Default/Info.plist new file mode 100644 index 000000000..92ab8b53d --- /dev/null +++ b/AppKit/Themes/Default/Info.plist @@ -0,0 +1,12 @@ + + + + + CPApplicationDelegateClass + AppController + CPBundleName + Hello World + CPPrincipalClass + CPApplication + + diff --git a/AppKit/Resources/CPSlider/CPSliderTrackHorizontalCenter.png b/AppKit/Themes/Default/Resources/horizontal-track-center.png similarity index 100% rename from AppKit/Resources/CPSlider/CPSliderTrackHorizontalCenter.png rename to AppKit/Themes/Default/Resources/horizontal-track-center.png diff --git a/AppKit/Resources/CPSlider/CPSliderTrackHorizontalLeft.png b/AppKit/Themes/Default/Resources/horizontal-track-left.png similarity index 100% rename from AppKit/Resources/CPSlider/CPSliderTrackHorizontalLeft.png rename to AppKit/Themes/Default/Resources/horizontal-track-left.png diff --git a/AppKit/Resources/CPSlider/CPSliderTrackHorizontalRight.png b/AppKit/Themes/Default/Resources/horizontal-track-right.png similarity index 100% rename from AppKit/Resources/CPSlider/CPSliderTrackHorizontalRight.png rename to AppKit/Themes/Default/Resources/horizontal-track-right.png diff --git a/AppKit/Themes/Default/Resources/knob-highlighted.png b/AppKit/Themes/Default/Resources/knob-highlighted.png new file mode 100644 index 0000000000000000000000000000000000000000..ea566de80604333c8ffb3ff6168f1f0194b0271e GIT binary patch literal 3161 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 literal 0 HcmV?d00001 diff --git a/AppKit/Themes/Default/Resources/knob.png b/AppKit/Themes/Default/Resources/knob.png new file mode 100644 index 0000000000000000000000000000000000000000..3591e46e319f645c82435ce109195c241a290921 GIT binary patch literal 3210 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 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPSlider/CPSliderKnobRegularPushed.png b/AppKit/Themes/Default/Resources/vertical-track-bottom.png similarity index 87% rename from AppKit/Resources/CPSlider/CPSliderKnobRegularPushed.png rename to AppKit/Themes/Default/Resources/vertical-track-bottom.png index b6612ec3a250d35656074e2d65da7f889d3ddeb5..573fe87dd8af6dea910c3c34c62423776a6cd941 100644 GIT binary patch delta 108 zcmew%-XNyf8Q|y6%O%Cdz`(%k>ERLtq*;KNiGvMD)~~2d-l#Z_%aK9b)5S5Q;#Lw5 z2gi@~3c6<(tXp$tLSV#<^G6OGxNz#onJ=+^j*05b%!efpFm#x(U!7<nK0YgQu&X J%Q~loCIE=nBS!!L delta 358 zcmV-s0h#`Q7Wfw-iBL{Q4GJ0x0000DNk~Le0000B0000B2nGNE0I95ZCb1!&3V#73 zNkl#>N$55d2`OneQ+DF{(;Mx7!_BYcGQ!I4R5WqbQ1(>2x}*_C{4n z)AV$=+l?BH#=u%jtyW{d-%}I?d4Hb2T5In_5cRA_V%*Ig%v77=x-FNUDl+j`e!o4*{YmB1w{i#7YF% zY&HOdz&Oh?n$0GEk!2acxF#YK@BPDSwIYt=qggJOc<&!XWDhQI092}d(f?eFZU6uP07*qoM6N<$ Ef^$BbU;qFB diff --git a/AppKit/Resources/CPSlider/CPSliderKnobRegular.png b/AppKit/Themes/Default/Resources/vertical-track-center.png similarity index 86% rename from AppKit/Resources/CPSlider/CPSliderKnobRegular.png rename to AppKit/Themes/Default/Resources/vertical-track-center.png index f2c3923d4291ccf816cf0c43a067bee95f2d2b2b..05441be1a0cb9cec6343febcf0fbaea0620e56a3 100644 GIT binary patch delta 96 zcmbO#@kLazGr-TCmrII^fq{Y7)59eQNV5PjBL^Fh{At5~cBA4vE>i}1PZ!6Kid#uM vJUoB&^;M59ShwcPgusXy{6JOz|1&eFX|v>pbxPa@av3~b{an^LB{Ts5XhRwj delta 387 zcmV-}0et@S6_pqviBL{Q4GJ0x0000DNk~Le0000B0000B2nGNE0I95ZCb1!&3V#7W zNkl5CXqIpxAt) zQ_bfPIoux<1d;QGQ~wR2=n(Y4JH5~IzRyqCQ=`$i7LgmE415AFy@@1GcB z?mf@DtyZhJu8Y>XG8_&oz_~Hzsej+^e`NqlrP4#Q*}SXOYAB^xtyUDz-r7lLJ zQ6>z-ckz9{?7HqptJOk8FvcJvyK2T5y4@~X>r)G;JC4I_Hrubi3j#QfLli}I%NRo( z$4n-ZKQG5|{0k@|f!3OQK7U}^H*2jCksuR>p)M2(M`@a#Z8jU0%jLmDQCP%uI_(Sw zgJ%oCw(ZC9c${A>7MIy<7R$0&uh%3=!hAk|%jI&900)0P&uc5Cu58;rPSf-|Ns`wf h2--X7E%AT!GXQNTme_m#WU>GN002ovPDHLkV1nP?srCQ> diff --git a/AppKit/Themes/Default/Resources/vertical-track-top.png b/AppKit/Themes/Default/Resources/vertical-track-top.png new file mode 100644 index 0000000000000000000000000000000000000000..a1878ed98b10ea3d2d74be35e290ea0cd2aaf2eb GIT binary patch literal 2818 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 USKBMM=l}o!07*qoM6N<$g5<(Gz5oCK literal 0 HcmV?d00001 diff --git a/AppKit/Themes/Default/index-debug.html b/AppKit/Themes/Default/index-debug.html new file mode 100644 index 000000000..392b37a8f --- /dev/null +++ b/AppKit/Themes/Default/index-debug.html @@ -0,0 +1,35 @@ + + + + + + + Hello World + + + + + + + + +
+
+ +
+
+ + + diff --git a/AppKit/Themes/Default/index.html b/AppKit/Themes/Default/index.html new file mode 100644 index 000000000..fbcf5a9bc --- /dev/null +++ b/AppKit/Themes/Default/index.html @@ -0,0 +1,36 @@ + + + + + + + Hello World + + + + + + + + + +
+
+ +
+
+ + + + diff --git a/AppKit/Themes/Default/main.j b/AppKit/Themes/Default/main.j new file mode 100644 index 000000000..b82bd4e3c --- /dev/null +++ b/AppKit/Themes/Default/main.j @@ -0,0 +1,17 @@ +/* + * main.j + * + * Created by __Me__ on __Date__. + * Copyright 2008 __MyCompanyName__. All rights reserved. + */ + +@import +@import + +@import "AppController.j" + + +function main(args, namedArgs) +{ + CPApplicationMain(args, namedArgs); +} diff --git a/AppKit/build.xml b/AppKit/build.xml index 1ae3709ad..327bc4b87 100644 --- a/AppKit/build.xml +++ b/AppKit/build.xml @@ -3,6 +3,8 @@ + + @@ -26,6 +28,16 @@ + + + + + + + + + + diff --git a/Objective-J/evaluate.js b/Objective-J/evaluate.js index 1886003be..72fd1ddf1 100644 --- a/Objective-J/evaluate.js +++ b/Objective-J/evaluate.js @@ -66,6 +66,12 @@ function objj_context() #define IS_FILE(aFragment) (aFragment.type & FRAGMENT_FILE) #define IS_LOCAL(aFragment) (aFragment.type & FRAGMENT_LOCAL) +objj_fragment.prototype.toMarkedString = function() +{ + return IS_FILE(this) ? (IS_LOCAL(this) ? MARKER_IMPORT_LOCAL : MARKER_IMPORT_STD) + ';' + GET_PATH(this).length + ';' + GET_PATH(this) : + MARKER_CODE + ';' + GET_CODE(this).length + ';' + GET_CODE(this); +} + function fragment_create_code(aCode, aBundle, aFile) { var fragment = new objj_fragment(); diff --git a/Objective-J/file.js b/Objective-J/file.js index 4d72810be..8c2e2d6cb 100644 --- a/Objective-J/file.js +++ b/Objective-J/file.js @@ -545,6 +545,8 @@ OBJJUnrecognizedFormatException = "OBJJUnrecognizedFormatException"; var STATIC_MAGIC_NUMBER = "@STATIC", MARKER_PATH = "p", MARKER_CODE = "c", + MARKER_BUNDLE = "b", + MARKER_TEXT = "t", MARKER_IMPORT_STD = 'I', MARKER_IMPORT_LOCAL = 'i'; @@ -569,7 +571,10 @@ function objj_decompile(aString, bundle) switch (marker) { - case MARKER_PATH: file = new objj_file(); + case MARKER_PATH: if (file && file.contents && file.path === file.bundle.path) + file.bundle.info = CPPropertyListCreateWithData({string:file.contents}); + + file = new objj_file(); file.path = DIRECTORY(bundle.path) + text; file.bundle = bundle; file.fragments = []; @@ -579,6 +584,24 @@ function objj_decompile(aString, bundle) objj_files[file.path] = file; break; + + case MARKER_BUNDLE: var bundlePath = DIRECTORY(bundle.path) + '/' + text; + + file.bundle = objj_getBundleWithPath(bundlePath); + + if (!file.bundle) + { + file.bundle = new objj_bundle(); + file.bundle.path = bundlePath; + + objj_setBundleForPath(file.bundle, bundlePath); + } + + break; + + case MARKER_TEXT: file.contents = text; + break; + case MARKER_CODE: file.fragments.push(fragment_create_code(text, bundle, file)); break; case MARKER_IMPORT_STD: file.fragments.push(fragment_create_file(text, bundle, NO, file)); @@ -588,5 +611,8 @@ function objj_decompile(aString, bundle) } } + if (file && file.contents && file.path === file.bundle.path) + file.bundle.info = CPPropertyListCreateWithData({string:file.contents}); + return files; } diff --git a/Tools/Utilities/bundle.js b/Tools/Utilities/bundle.js new file mode 100644 index 000000000..2e3a3d3ec --- /dev/null +++ b/Tools/Utilities/bundle.js @@ -0,0 +1,131 @@ + +function readContentsOfFile(/*File*/ aFile) +{ + var reader = new BufferedReader(new FileReader(aFile)), + fileContents = ""; + + // Get contents of the file + while (reader.ready()) + fileContents += reader.readLine() + '\n'; + + reader.close(); + + return fileContents; +} + +function writeContentsToFile(/*String*/ contents, /*File*/ aFile) +{ + var writer = new BufferedWriter(new FileWriter(aFile)); + + writer.write(contents); + + writer.close(); +} + +function readPlist(/*File*/ aFile) +{ + var fileContents = readFile(aFile); + + var data = new objj_data(); + data.string = fileContents; + + return new CPPropertyListCreateFromData(data); +} + +function readBundle(/*File*/ aFile, /*Boolean*/ shouldDecompile) +{ + var bundlePath = typeof aFile === "string" ? new File(aFile).getCanonicalPath() : aFile.getCanonicalPath(), + infoPath = bundlePath + "/Info.plist"; + + //err + var bundle = new objj_bundle(); + + bundle.path = infoPath; + bundle.info = readPlist(infoPath); + bundle._staticFilePaths = dictionary_getValue(bundle.info, "CPBundleReplacedFiles"); + + if (bundle._staticFilePaths.length) + { + bundle._staticContentPath = staticContentPath = bundlePath + '/' + dictionary_getValue(bundle.info, "CPBundleExecutable"); + + //err + + bundle._staticContent = readFile(staticContentPath); + + if (shouldDecompile) + bundle.files = objj_decompile(bundle._staticContent, bundle); + } + else + bundle._staticContent = ""; + + return bundle; +} + +function importFiles(files, aCallback) +{ + + if (files.length === 0) + aCallback(); + else + { + var file = files.shift(); + + if (typeof file === "string") + file = new File(file); + + objj_import(file.getCanonicalPath(), YES, function() { importFiles(files, aCallback) }); + } + return; + + var context = new objj_context(); + + if (aCallback) + context.didCompleteCallback = aCallback; + + var count = files.length; + + while (count--) + { + var file = files[count]; + + if (typeof file === "string") + file = new File(file); + + context.pushFragment(fragment_create_file(file, new objj_bundle(""), YES, NULL)); + } + + context.evaluate(); +} + +function loadFrameworks(frameworkPaths, aCallback) +{ + if (frameworkPaths.length === 0) + return aCallback(); + + var frameworkPath = frameworkPaths.shift(), + + infoPlist = new File(frameworkPath + "/Info.plist"); + + if (!infoPlist.exists()) + { + java.lang.System.out.println("'" + frameworkPath + "' is not a framework or could not be found."); + java.lang.System.exit(1); + } + + var infoDictionary = readPlist(new File(frameworkPath + "/Info.plist")); + + if (dictionary_getValue(infoDictionary, "CPBundlePackageType") !== "FMWK") + { + java.lang.System.out.println("'" + frameworkPath + "' is not a framework ."); + java.lang.System.exit(1); + } + + var files = dictionary_getValue(infoDictionary, "CPBundleReplacedFiles"), + index = 0, + count = files.length; + + for (; index < count; ++index) + files[index] = String(frameworkPath + '/' + files[index]); + + importFiles(files, function() { loadFrameworks(frameworkPaths, aCallback) }); +} diff --git a/Tools/Utilities/file.js b/Tools/Utilities/file.js new file mode 100644 index 000000000..c8461a7ab --- /dev/null +++ b/Tools/Utilities/file.js @@ -0,0 +1,99 @@ + + +function readFile(/*File*/ aFile) +{ + var reader = new BufferedReader(new FileReader(aFile)), + fileContents = ""; + + // Get contents of the file + while (reader.ready()) + fileContents += reader.readLine() + '\n'; + + reader.close(); + + return fileContents; +} + +function writeContentsToFile(/*String*/ contents, /*File*/ aFile) +{ + +} + +function readPlist(/*File*/ aFile) +{ + var fileContents = readFile(aFile); + + var data = new objj_data(); + data.string = fileContents; + + return new CPPropertyListCreateFromData(data); +} + +function importFiles(files, aCallback) +{ + + if (files.length === 0) + aCallback(); + else + { + var file = files.shift(); + + if (typeof file === "string") + file = new File(file); + + objj_import(file.getCanonicalPath(), YES, function() { importFiles(files, aCallback) }); + } + return; + + var context = new objj_context(); + + if (aCallback) + context.didCompleteCallback = aCallback; + + var count = files.length; + + while (count--) + { + var file = files[count]; + + if (typeof file === "string") + file = new File(file); + + context.pushFragment(fragment_create_file(file, new objj_bundle(""), YES, NULL)); + } + + context.evaluate(); +} + +function loadFrameworks(frameworkPaths, aCallback) +{ + if (frameworkPaths.length === 0) + return aCallback(); + + var frameworkPath = frameworkPaths.shift(), + + infoPlist = new File(frameworkPath + "/Info.plist"); + + if (!infoPlist.exists()) + { + java.lang.System.out.println("'" + frameworkPath + "' is not a framework or could not be found."); + java.lang.System.exit(1); + } + + var infoDictionary = readPlist(new File(frameworkPath + "/Info.plist")); + + if (dictionary_getValue(infoDictionary, "CPBundlePackageType") !== "FMWK") + { + java.lang.System.out.println("'" + frameworkPath + "' is not a framework ."); + java.lang.System.exit(1); + } + + var files = dictionary_getValue(infoDictionary, "CPBundleReplacedFiles"), + index = 0, + count = files.length; + + for (; index < count; ++index) + files[index] = String(frameworkPath + '/' + files[index]); + + importFiles(files, function() { loadFrameworks(frameworkPaths, aCallback) }); +} diff --git a/Tools/steam/Project.js b/Tools/steam/Project.js new file mode 100644 index 000000000..2543ce460 --- /dev/null +++ b/Tools/steam/Project.js @@ -0,0 +1,447 @@ + +importClass(java.io.FileOutputStream); +importClass(java.io.BufferedWriter); +importClass(java.io.OutputStreamWriter); + +function Target(dictionary) +{ + this._name = dictionary_getValue(dictionary, "Name"); + + var flagsString = dictionary_getValue(dictionary, "Flags"); + + this._flags = flagsString ? flagsString.split(/\s+/) : []; + + this._type = dictionary_getValue(dictionary, "Type"); + + if (!this._type) + this._type = "280N.application"; + + this._exclusions = []; + + var exclusions = dictionary_getValue(dictionary, "Excluded"); + + if (exclusions) + { + var index = 0, + count = exclusions.length; + + for (; index < count; ++index) + { + var file = new File(exclusions[index]).getCanonicalFile(); + + if (file.isDirectory()) + { + var files = getFiles(file); + + if (files.length) + this._exclusions = this._exclusions.concat(files); + } + else + this._exclusions.push(file); + } + } + + return this; +} + +Target.prototype.name = function() +{ + return this._name; +} + +Target.prototype.exclusions = function() +{ + return this._exclusions; +} + +Target.prototype.flags = function() +{ + return this._flags; +} + +Target.prototype.type = function() +{ + return this._type; +} + +function Configuration(dictionary) +{ + this._name = dictionary_getValue(dictionary, "Name"); + + var flagsString = dictionary_getValue(dictionary, "Flags"); + + this._flags = flagsString ? flagsString.split(/\s+/) : []; + + return this; +} + +Configuration.prototype.name = function() +{ + return this._name; +} + +Configuration.prototype.flags = function() +{ + return this._flags; +} + +function Project(/*String*/ aFilePath, /*String*/ aBuildPath) +{ + this._file = new File(aFilePath).getCanonicalFile(); + this._root = this._file.getParentFile(); + + // Read the project file (its just a plist). + this._properties = readPlist(this._file); + + this._name = dictionary_getValue(this._properties, "Name"); + + // Read existing Info.plist if it exists. + var infoPlist = new File(this._root.getAbsolutePath() + "/Info.plist"); + + if (infoPlist.exists()) + this._infoDictionary = readPlist(new File(this._root.getAbsolutePath() + "/Info.plist")); + else + this._infoDictionary = new objj_dictionary(); + + this.buildPath = aBuildPath; + + // Covert target dictionaries to target objects. + var targetDictionaries = dictionary_getValue(this._properties, "Targets"); + + this._targets = []; + + for (index = 0, count = targetDictionaries.length; index < count; ++index) + this._targets.push(new Target(targetDictionaries[index])); + + this.setActiveTarget(this._targets[0]); + + // Covert target dictionaries to target objects. + var configurationDictionaries = dictionary_getValue(this._properties, "Configurations"); + + this._configurations = []; + + for (index = 0, count = configurationDictionaries.length; index < count; ++index) + this._configurations.push(new Configuration(configurationDictionaries[index])); + + this.setActiveConfiguration(this._configurations[0]); + + // Grab the Resources Directory (if it exists) + this._resources = new File(this._root.getAbsolutePath() + "/Resources/").getCanonicalFile(); + + return this; +} + +Project.prototype.name = function() +{ + return this._name; +} + +Project.prototype.targetWithName = function(/*String*/ aName) +{ + var targets = this._targets, + index = 0, + count = targets.length; + + for (; index < count; ++index) + { + var target = targets[index]; + + if (target.name() == aName) + return target; + } + + return null; +} + +Project.prototype.configurationWithName = function(/*String*/ aName) +{ + var configurations = this._configurations, + index = 0, + count = configurations.length; + + for (; index < count; ++index) + { + var configuration = configurations[index]; + + if (configuration.name() == aName) + return configuration; + } + + return null; +} + +Project.prototype.setActiveTarget = function(/*Target*/ aTarget) +{ + this._activeTarget = aTarget; + + this._buildProducts = null; + this._buildIntermediates = null; + this._buildObjects = null; +} + +Project.prototype.activeTarget = function() +{ + return this._activeTarget; +} + +Project.prototype.setActiveConfiguration = function(/*Configuration*/ aConfiguration) +{ + this._activeConfiguration = aConfiguration; + + this._buildProducts = null; + this._buildIntermediates = null; + this._buildObjects = null; +} + +Project.prototype.activeConfiguration = function() +{ + return this._activeConfiguration; +} + +Project.prototype.buildProducts = function() +{ + if (!this._buildProducts) + { + this._buildProducts = new File(this.buildPath + '/' + this._activeConfiguration.name() + '/' + this._activeTarget.name()).getCanonicalFile(); + this._buildProducts.mkdirs(); + } + + return this._buildProducts; +} + +Project.prototype.buildIntermediates = function() +{ + if (!this._buildIntermediates) + { + this._buildIntermediates = new File(this.buildPath + '/' + this._activeTarget.name() + ".build/" + this._activeConfiguration.name()).getCanonicalFile(); + this._buildIntermediates.mkdirs(); + } + + return this._buildIntermediates; +} + +Project.prototype.buildObjects = function() +{ + if (!this._buildObjects) + { + this._buildObjects = new File(this.buildIntermediates().getAbsolutePath() + '/' + this._activeTarget.name()).getCanonicalFile(); + this._buildObjects.mkdirs(); + } + + return this._buildObjects; +} + +Project.prototype.activeFlags = function() +{ + return this.activeTarget().flags().concat(this.activeConfiguration().flags()); +} + +Project.prototype.buildTheme = function() +{ + var project = this; + + // FIXME: This should be stubbed out. It is also in objj.js + var OBJJ_LIB = OBJJ_HOME + "/lib/"; + + var defaultFrameworks = OBJJ_LIB + "/Frameworks-Rhino"; + + OBJJ_INCLUDE_PATHS = [defaultFrameworks]; + + var OBJJ_INCLUDE_PATHS_STRING = getenv("OBJJ_INCLUDE_PATHS"); + + if (OBJJ_INCLUDE_PATHS_STRING) + { + OBJJ_INCLUDE_PATHS = OBJJ_INCLUDE_PATHS_STRING.split(":"); + OBJJ_INCLUDE_PATHS.push(defaultFrameworks); + } + + // Load ALL of Foundation and AppKit, be nice to people. + loadFrameworks([OBJJ_LIB + "/Frameworks-Rhino/Foundation", OBJJ_LIB + "/Frameworks-Rhino/AppKit"], function() + { + // Get .j files + var jFiles = getFiles(project._root, "j", project.activeTarget().exclusions().concat("Frameworks/")); + + // Load 'em + importFiles(jFiles, function() + { + // Grab the application delegate. + var applicationDelegateClassName = dictionary_getValue(project._infoDictionary, "CPApplicationDelegateClass"), + applicationDelegate = objj_msgSend(objj_msgSend(objj_getClass(applicationDelegateClassName), "alloc"), "init"), + + // Grab all the themes we plan to make. + themeNames = objj_msgSend(applicationDelegate, "themeNames"), + + themeIndex = 0, + themeCount = themeNames.length, + + replacedFiles = [], + + staticContent = ""; + + for (; themeIndex < themeCount; ++themeIndex) + { + themeName = themeNames[themeIndex]; + + java.lang.System.out.println("Building " + themeName + " Theme."); + + var views = objj_msgSend(applicationDelegate, "viewsFor" + themeName + "Theme"), + viewIndex = 0, + viewCount = views.length, + theme = objj_msgSend(objj_msgSend(CPTheme, "alloc"), "initWithName:", themeName); + + if (!viewCount) + java.lang.System.out.println("There are no themed views in the " + themeName + " Theme."); + + // Loop through each "themed" view, and take it's themed properties. + for (; viewIndex < viewCount; ++viewIndex) + { + var view = views[viewIndex]; + + java.lang.System.out.println(" Recording theme for " + objj_msgSend(views[viewIndex], "className") + "."); + + objj_msgSend(theme, "takeThemeFromObject:", view); + } + + // Archive our theme. + var filePath = themeName + ".keyedtheme"; + fileContents = objj_msgSend(objj_msgSend(CPKeyedArchiver, "archivedDataWithRootObject:", theme), "string"); + + replacedFiles.push(filePath); + + staticContent += MARKER_PATH + ';' + filePath.length + ';' + filePath + MARKER_TEXT + ';' + fileContents.length + ';' + fileContents; + } + + staticContent = "@STATIC;1.0;" + staticContent; + + var staticContentName = getFileNameWithoutExtension(project.activeTarget().name()); + + dictionary_setValue(project._infoDictionary, "CPBundleReplacedFiles", replacedFiles); + dictionary_setValue(project._infoDictionary, "CPBundleExecutable", staticContentName); + + var writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(project.buildProducts().getCanonicalPath() + "/Info.plist"), "UTF-8")); + + writer.write(CPPropertyListCreate280NorthData(project._infoDictionary).string); + + writer.close(); + + writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(project.buildProducts().getCanonicalPath() + "/" + staticContentName), "UTF-8")); + + writer.write(staticContent); + + writer.close(); + }); + }); + + serviceTimeouts(); + + this.copyResources(); +} + +Project.prototype.build = function() +{ + java.lang.System.out.println("Building Target \"" + this.activeTarget().name() + + "\" of Project \"" + this.name() + + "\" with Configuration \"" + this.activeConfiguration().name() + "\"."); + + if (this.activeTarget().type() === "280N.theme") + return this.buildTheme(); + + var jFiles = getFiles(this._root, "j", this._activeTarget.exclusions()), + replacedFiles = []; + hasModifiedJFiles = false; + shouldObjjPreprocess = true, + shouldGzip = this._gzip, + objjcComponents = ["sh", OBJJ_HOME + "/bin/objjc"]; + + objjcComponents = objjcComponents.concat(this.activeFlags()); + + if (!shouldObjjPreprocess) + objjcComponents.push("-E"); + + var buildObjects = this.buildObjects(), + buildProducts = this.buildProducts(); + + for (index = 0, count = jFiles.length; index < count; ++index) + { + var file = jFiles[index], + builtFile = new File(buildObjects.getAbsolutePath() + '/' + getFileNameWithoutExtension(file) + '.o'); + + replacedFiles.push(file.getName() + ""); + + if (builtFile.exists() && file.lastModified() < builtFile.lastModified()) + continue; + else + hasModifiedJFiles = true; + + objjcComponents.push(file.getAbsolutePath()); + + objjcComponents.push("-o"); + objjcComponents.push(buildObjects.getAbsolutePath() + '/' + getFileNameWithoutExtension(file) + '.o'); + } + + exec(objjcComponents, true); + + var oFiles = getFiles(buildObjects, 'o'), + sjFile = new File(buildProducts.getCanonicalPath() + '/' + this._activeTarget.name() + ".sj"); + + if (hasModifiedJFiles) + { + // concatenate sjheader.txt and individual .o + exec(["sh", "-c", "cat '" + OBJJ_HOME + "/lib/sjheader.txt' '" + oFiles.join("' '") + "' > '" + sjFile.getCanonicalPath() + "'"], true); + } + + if (shouldGzip) + { + // gzip and copy .htaccess file + exec(["sh", "-c", "gzip -c '" + sjFile.getCanonicalPath() + "' > '" + sjFile.getCanonicalPath() + ".gz'"], true); + exec(["cp", OBJJ_HOME + "/lib/htaccess", sjFile.getParentFile().getCanonicalPath() + "/.htaccess"], true); + } + else + { + // remove gzip and .htaccess file if present + exec(["rm", "-f", sjFile.getParentFile().getCanonicalPath() + "/.htaccess", sjFile.getCanonicalPath() + ".gz"], true); + } + + dictionary_setValue(this._infoDictionary, "CPBundleExecutable", this._activeTarget.name() + ".sj"); + dictionary_setValue(this._infoDictionary, "CPBundleReplacedFiles", replacedFiles); + + this.writeInfoPlist(); + + this.copyResources(); + + // FIXME: This should be, if this is an app... + if (dictionary_getValue(this._infoDictionary, "CPBundlePackageType") == "280N") + this.copyIndexFile(); + +} + +Project.prototype.clean = function() +{ + java.lang.System.out.println("Cleaning Target \"" + this.activeTarget().name() + + "\" of Project \"" + this.name() + + "\" with Configuration \"" + this.activeConfiguration().name() + "\"."); + + exec(["rm", "-rf", this.buildIntermediates().getAbsolutePath()], true); + exec(["rm", "-rf", this.buildProducts().getAbsolutePath()], true); +} + +Project.prototype.copyIndexFile = function() +{ + var indexFile = new File(this._root.getAbsolutePath() + "/index.html").getCanonicalFile(); + + rsync(indexFile, this.buildProducts()); +} + +Project.prototype.writeInfoPlist = function() +{ + var writer = new BufferedWriter(new FileWriter(this.buildProducts().getAbsolutePath() + '/' + "Info.plist")); + + writer.write(CPPropertyListCreateXMLData(this._infoDictionary).string); + + writer.close(); +} + +Project.prototype.copyResources = function() +{ + rsync(this._resources, this.buildProducts()); +} diff --git a/Tools/steam/build.js b/Tools/steam/build.js new file mode 100644 index 000000000..959d22a0b --- /dev/null +++ b/Tools/steam/build.js @@ -0,0 +1,102 @@ +function build() +{ + var index = 0, + count = arguments.length, + + actions = [], + + targetName = null, + configurationName = null, + + buildPath = null, + projectFilePath = null, + + gzip = false; + + for (; index < count; ++index) + { + switch (arguments[index]) + { + case "-f": if (index + 1 == count) + throw "-f needs project file."; + + projectFilePath = arguments[++index]; + break; + + case "-t": if (index + 1 == count) + throw "-t needs a target"; + + targetName = arguments[++index]; + break; + + case "-c": if (index + 1 == count) + throw "-c needs configuration"; + + configurationName = arguments[++index]; + break; + + case "-b": if (index + 1 == count) + throw "-b needs a build location"; + + buildPath = arguments[++index]; + break; + + case "--gzip": gzip = true; + break; + + case "clean": + case "build": actions.push(arguments[index]); + break; + } + } + + // If no project file was specified, look for one. + if (!projectFilePath) + { + var candidates = getFiles(new File('.'), "steam"); + + if (candidates.length < 1) + throw "No project file specified or found."; + + projectFilePath = candidates[0]; + } + + // Construct the Build Directory + if (!buildPath) + { + buildPath = System.getenv("STEAM_BUILD"); + + if (!buildPath) + buildPath = "Build"; + } + + var project = new Project(projectFilePath, buildPath); + + project._gzip = gzip; + + if (targetName) + { + var target = project.targetWithName(targetName); + + if (!target) + throw "Target \"" + targetName + "\" not found in project."; + + project.setActiveTarget(target); + } + + if (configurationName) + { + var configuration = project.configurationWithName(configurationName); + + if (!configuration) + throw "Configuration \"" + configurationName + "\" not found in project."; + + project.setActiveConfiguration(configuration); + } + + if (!actions.length) + actions.push("build"); + + for (index = 0, count = actions.length; index < count; ++index) + project[actions[index]](); +} diff --git a/Tools/steam/build.xml b/Tools/steam/build.xml index 65da0fe1a..40493bd64 100644 --- a/Tools/steam/build.xml +++ b/Tools/steam/build.xml @@ -24,20 +24,22 @@ - + + + - + - + - + diff --git a/Tools/steam/create-frameworks.js b/Tools/steam/create-frameworks.js new file mode 100644 index 000000000..3d91f1b04 --- /dev/null +++ b/Tools/steam/create-frameworks.js @@ -0,0 +1,4 @@ +function createFrameworks() +{ + return create(Array.concat.apply(arguments, ["-f"])); +} \ No newline at end of file diff --git a/Tools/steam/create.js b/Tools/steam/create.js new file mode 100644 index 000000000..d95fc069a --- /dev/null +++ b/Tools/steam/create.js @@ -0,0 +1,77 @@ +function create() +{ + if (arguments.length < 1) + printUsage("create"); + + var link = false, + index = 0, + count = arguments.length, + + destination = NULL, + justFrameworks = false; + + for (; index < count; ++index) + { + var argument = arguments[index]; + + switch (arguments[index]) + { + case "-l": link = true; + break; + case "-f": justFrameworks = true; + break; + default: destination = argument; + } + } + + var sourceNewApplication = new File(OBJJ_HOME + "/lib/NewApplication"), + destinationNewApplication = new File(destination), + sourceFrameworks = new File(OBJJ_HOME + "/lib/Frameworks"), + sourceDebugFrameworks = new File(OBJJ_HOME + "/lib/Frameworks-Debug"), + destinationFrameworks = new File(destination + "/Frameworks"), + destinationDebugFrameworks = new File(destination + "/Frameworks/Debug"); + + System.out.println(sourceNewApplication.getCanonicalPath() + "," + destinationNewApplication.getCanonicalPath() + "," + sourceFrameworks.getCanonicalPath() + "," + destinationFrameworks.getCanonicalPath()); + + if (justFrameworks || !destinationNewApplication.exists()) + { + if (!justFrameworks) + exec(["cp", "-vR", sourceNewApplication.getCanonicalPath(), destinationNewApplication.getCanonicalPath()], true); + + if (!link) + { + exec(["cp", "-vR", sourceFrameworks.getCanonicalPath(), destinationFrameworks.getCanonicalPath()], true); + exec(["cp", "-vR", sourceDebugFrameworks.getCanonicalPath(), destinationDebugFrameworks.getCanonicalPath()], true); + } + else + { + var STEAM_BUILD = System.getenv("STEAM_BUILD"); + + // Release Frameworks + new File(destinationFrameworks).mkdir(); + + exec(["ln", "-s", new File(STEAM_BUILD + "/Release/Objective-J").getCanonicalPath(), + new File(destination + "/Frameworks/Objective-J").getCanonicalPath()], true); + + exec(["ln", "-s", new File(STEAM_BUILD + "/Release/Foundation").getCanonicalPath(), + new File(destination + "/Frameworks/Foundation").getCanonicalPath()], true); + + exec(["ln", "-s", new File(STEAM_BUILD + "/Release/AppKit").getCanonicalPath(), + new File(destination + "/Frameworks/AppKit").getCanonicalPath()], true); + + // Debug Frameworks + new File(destinationDebugFrameworks).mkdir(); + + exec(["ln", "-s", new File(STEAM_BUILD + "/Debug/Objective-J").getCanonicalPath(), + new File(destination + "/Frameworks/Debug/Objective-J").getCanonicalPath()], true); + + exec(["ln", "-s", new File(STEAM_BUILD + "/Debug/Foundation").getCanonicalPath(), + new File(destination + "/Frameworks/Debug/Foundation").getCanonicalPath()], true); + + exec(["ln", "-s", new File(STEAM_BUILD + "/Debug/AppKit").getCanonicalPath(), + new File(destination + "/Frameworks/Debug/AppKit").getCanonicalPath()], true); + } + } + else + System.out.println("Directory already exists"); +} diff --git a/Tools/steam/inline-bundle.js b/Tools/steam/inline-bundle.js new file mode 100644 index 000000000..2e2dc8643 --- /dev/null +++ b/Tools/steam/inline-bundle.js @@ -0,0 +1,156 @@ +function inlineBundle() +{ + var index = 0, + count = arguments.length, + bundlePath = NULL; + + for (; index < count; ++index) + { + var argument = arguments[index]; + + switch (arguments[index]) + { + case "-d": directoryPath = arguments[++index]; + break; + + default: bundlePath = argument; + } + } + + var bundleFile = new File(bundlePath).getCanonicalFile(), + bundlePath = String(bundleFile.getCanonicalPath()), + inlinedBundle = readBundle(bundleFile, true), + inlinedFiles = [], + replacedFiles = [], + staticContent = ""; + + // Find all internal bundles. + var bundleCandidates = getFiles(bundleFile, "plist"), + bundleCandidatesCount = bundleCandidates.length; + + while (bundleCandidatesCount--) + { + var bundleCandidate = bundleCandidates[bundleCandidatesCount]; + + // We only care about Info.plists, specifically the ones that aren't us. + if (String(bundleCandidate.getName()) !== "Info.plist" || String(bundleCandidate.getCanonicalPath()) === inlinedBundle.path) + continue; + + var infoDictionary = readPlist(bundleCandidate); + + // At least one of these two has to be present for this to be a real deal bundle. + if (!dictionary_getValue(infoDictionary, "CPBundleIdentifier") && !dictionary_getValue(infoDictionary, "CPBundleName")) + continue; + + java.lang.System.out.println(" Examining " + pathRelativeTo(bundleCandidate.getCanonicalPath(), bundlePath)); + + dictionary_removeValue(infoDictionary, "CPBundleExecutable"); + + var bundle = readBundle(bundleCandidate.getParentFile(), true); + + bundle.path = pathRelativeTo(bundle.path, bundlePath); + + // We want to inline the info plist too. + var inlinedFiles = [makeOBJJPlistFile(infoDictionary, bundleCandidate, bundle)].concat(bundle.files), + index = 0, + count = inlinedFiles.length; + + for (; index < count; ++index) + { + var file = inlinedFiles[index]; + + file.path = pathRelativeTo(String(file.path), bundlePath); + + java.lang.System.out.println(" Inlining " + file.path); + + replacedFiles.push(file.path); + staticContent += fileToMarkedString(inlinedFiles[index], true); + } + } + + var index = 0, + existingStaticFiles = inlinedBundle.files, + count = existingStaticFiles.length, + topLevelContent = "@STATIC;1.0;"; + + for (; index < count; ++index) + { + var file = existingStaticFiles[index]; + + // If this isn't actually part of our bundle, drop it! + if (file.bundle !== inlinedBundle) + continue; + + file.path = pathRelativeTo(String(file.path), bundlePath); + + replacedFiles.push(file.path); + topLevelContent += fileToMarkedString(file, false); + } + + dictionary_setValue(inlinedBundle.info, "CPBundleReplacedFiles", replacedFiles); + + writeContentsToFile(CPPropertyListCreateXMLData(inlinedBundle.info).string, inlinedBundle.path); + writeContentsToFile(topLevelContent + staticContent, inlinedBundle._staticContentPath); +} + +function fileToMarkedString(anOBJJFile, encodeBundle) +{ + var markedString = ""; + + markedString += MARKER_PATH + ';' + anOBJJFile.path.length + ';' + anOBJJFile.path; + + if (encodeBundle) + markedString += MARKER_BUNDLE + ';' + anOBJJFile.bundle.path.length + ';' + anOBJJFile.bundle.path; + + var fragments = anOBJJFile.fragments; + + if (fragments && fragments.length > 0) + { + var fragmentIndex = 0, + fragmentCount = fragments.length; + + for (; fragmentIndex < fragmentCount; ++fragmentIndex) + markedString += fragments[fragmentIndex].toMarkedString(); + } + + else + markedString += MARKER_TEXT + ';' + anOBJJFile.contents.length + ';' + anOBJJFile.contents; + + return markedString; +} + +function makeOBJJPlistFile(aDictionary, aFile, aBundle) +{ + var file = new objj_file(); + + file.path = typeof aFile === "string" ? aFile : aFile.getCanonicalPath(); + file.bundle = aBundle; + file.contents = CPPropertyListCreate280NorthData(aDictionary).string; + + return file; +} + +function pathRelativeTo(target, relativeTo) +{ + var components = [], + targetParts = target.split("/"), + relativeParts = relativeTo ? relativeTo.split("/") : []; + + var i = 0; + while (i < targetParts.length) + { + if (targetParts[i] != relativeParts[i]) + break; + i++; + } + + for (var j = i; j < relativeParts.length; j++) + components.push(".."); + + for (var j = i; j < targetParts.length; j++) + components.push(targetParts[j]); + + var result = components.join("/"); + + return result; +} \ No newline at end of file diff --git a/Tools/steam/main.js b/Tools/steam/main.js new file mode 100644 index 000000000..211989dc8 --- /dev/null +++ b/Tools/steam/main.js @@ -0,0 +1,201 @@ + +importPackage(java.lang); +importPackage(java.util); + +importClass(java.io.File); +importClass(java.io.BufferedReader); +importClass(java.io.FileReader); +importClass(java.io.BufferedWriter); +importClass(java.io.FileWriter); +importClass(java.io.SequenceInputStream); + +#include "../Utilities/bundle.js" + +#include "Project.js" + +function main() +{ + if (arguments.length < 1) + printUsage(); + + var command = Array.prototype.shift.apply(arguments); + + switch (command) + { + case "create": create.apply(create, arguments); + break; + + case "create-frameworks": createFrameworks.apply(createFrameworks, arguments); + break; + + + case "inline-bundle": inlineBundle.apply(inlineBundle, arguments); + break; + + case "build": build.apply(build, arguments); + break; + + case "help": printUsage(arguments[1]); + break; + + case "version": + case "--version": printVersion(); + break; + + default : printUsage(command); + } + +} + +function fileArrayContainsFile(/*Array*/ files, /*File*/ aFile) +{ + var index = 0, + count = files.length; + + for (; index < count; ++index) + if (files[index].equals(aFile)) + return true; + + return false; +} + +function getFiles(/*File*/ sourceDirectory, /*nil|String|Array*/ extensions, /*Array*/ exclusions) +{ + var matches = [], + files = sourceDirectory.listFiles(), + hasMultipleExtensions = typeof extensions !== "string"; + + if (files) + { + var index = 0, + count = files.length; + + for (; index < count; ++index) + { + var file = files[index].getCanonicalFile(), + name = String(file.getName()), + isValidExtension = !extensions; + + if (exclusions && fileArrayContainsFile(exclusions, file)) + continue; + + if (!isValidExtension) + if (hasMultipleExtensions) + { + var extensionCount = extensions.length; + + while (extensionCount-- && !isValidExtension) + { + var extension = extensions[extensionCount]; + + if (name.substring(name.length - extension.length - 1) === ("." + extension)) + isValidExtension = true; + } + } + else if (name.substring(name.length - extensions.length - 1) === ("." + extensions)) + isValidExtension = true; + + if (isValidExtension) + matches.push(file); + + if (file.isDirectory()) + matches = matches.concat(getFiles(file, extensions, exclusions)); + } + } + + return matches; +} + +function exec(/*Array*/ command, /*Boolean*/ showOutput) +{ + var line = "", + output = "", + + process = Packages.java.lang.Runtime.getRuntime().exec(command),//jsArrayToJavaArray(command)); + reader = new Packages.java.io.BufferedReader(new Packages.java.io.InputStreamReader(process.getInputStream())); + + while (line = reader.readLine()) + { + if (showOutput) + System.out.println(line); + + output += line + '\n'; + } + + reader = new Packages.java.io.BufferedReader(new Packages.java.io.InputStreamReader(process.getErrorStream())); + + while (line = reader.readLine()) + System.out.println(line); + + try + { + if (process.waitFor() != 0) + System.err.println("exit value = " + process.exitValue()); + } + catch (anException) + { + System.err.println(anException); + } + + return output; +} + +function rsync(srcFile, dstFile) +{ + var src, dst; + + if (String(java.lang.System.getenv("OS")).indexOf("Windows") < 0) + { + src = srcFile.getAbsolutePath(); + dst = dstFile.getAbsolutePath(); + } + else + { + src = exec(["cygpath", "-u", srcFile.getAbsolutePath() + '/']); + dst = exec(["cygpath", "-u", dstFile.getAbsolutePath() + "/Resources"]); + } + + if (srcFile.exists()) + exec(["rsync", "-avz", src, dst]); +} + +function getFileName(aPath) +{ + var index = aPath.lastIndexOf('/'); + + if (index == -1) + return aPath; + + return aPath.substr(index + 1); +} + +function getFileNameWithoutExtension(aFileOrFileName) +{ + var name = typeof aFileOrFileName === "string" ? aFileOrFileName : aFileOrFileName.getName(), + index = name.lastIndexOf('.'); + + if (index == -1 || index == 0) + return name; + + return name.substr(0, index); +} + +function getFileExtension(aPath) +{ + var slash = aPath.lastIndexOf('/'), + period = aPath.lastIndexOf('.'); + + if (period < slash || (period == slash + 1)) + return ""; + + return aPath.substr(period + 1); +} + +main.apply(main, arguments); + +#include "build.js" +#include "create.js" +#include "create-frameworks.js" +#include "inline-bundle.js" +#include "usage.js" +#include "version.js" diff --git a/Tools/steam/steam.js b/Tools/steam/steam.js deleted file mode 100644 index bcbbd352d..000000000 --- a/Tools/steam/steam.js +++ /dev/null @@ -1,732 +0,0 @@ - -importPackage(java.lang); -importPackage(java.util); - -importClass(java.io.File); -importClass(java.io.BufferedReader); -importClass(java.io.FileReader); -importClass(java.io.BufferedWriter); -importClass(java.io.FileWriter); -importClass(java.io.SequenceInputStream); - -function Target(dictionary) -{ - this._name = dictionary_getValue(dictionary, "Name"); - - var flagsString = dictionary_getValue(dictionary, "Flags"); - - this._flags = flagsString ? flagsString.split(/\s+/) : []; - - this._exclusions = []; - - var exclusions = dictionary_getValue(dictionary, "Excluded"); - - if (exclusions) - { - var index = 0, - count = exclusions.length; - - for (; index < count; ++index) - { - var file = new File(exclusions[index]).getCanonicalFile(); - - if (file.isDirectory()) - { - var files = getFiles(file); - - if (files.length) - this._exclusions = this._exclusions.concat(files); - } - else - this._exclusions.push(file); - } - } - - return this; -} - -Target.prototype.name = function() -{ - return this._name; -} - -Target.prototype.exclusions = function() -{ - return this._exclusions; -} - -Target.prototype.flags = function() -{ - return this._flags; -} - -function Configuration(dictionary) -{ - this._name = dictionary_getValue(dictionary, "Name"); - - var flagsString = dictionary_getValue(dictionary, "Flags"); - - this._flags = flagsString ? flagsString.split(/\s+/) : []; - - return this; -} - -Configuration.prototype.name = function() -{ - return this._name; -} - -Configuration.prototype.flags = function() -{ - return this._flags; -} - -function Project(/*String*/ aFilePath, /*String*/ aBuildPath) -{ - this._file = new File(aFilePath).getCanonicalFile(); - this._root = this._file.getParentFile(); - - // Read the project file (its just a plist). - this._properties = readPlist(this._file); - - this._name = dictionary_getValue(this._properties, "Name"); - - // Read existing Info.plist if it exists. - var infoPlist = new File(this._root.getAbsolutePath() + "/Info.plist"); - - if (infoPlist.exists()) - this._infoDictionary = readPlist(new File(this._root.getAbsolutePath() + "/Info.plist")); - else - this._infoDictionary = new objj_dictionary(); - - this.buildPath = aBuildPath; - - // Covert target dictionaries to target objects. - var targetDictionaries = dictionary_getValue(this._properties, "Targets"); - - this._targets = []; - - for (index = 0, count = targetDictionaries.length; index < count; ++index) - this._targets.push(new Target(targetDictionaries[index])); - - this.setActiveTarget(this._targets[0]); - - // Covert target dictionaries to target objects. - var configurationDictionaries = dictionary_getValue(this._properties, "Configurations"); - - this._configurations = []; - - for (index = 0, count = configurationDictionaries.length; index < count; ++index) - this._configurations.push(new Configuration(configurationDictionaries[index])); - - this.setActiveConfiguration(this._configurations[0]); - - // Grab the Resources Directory (if it exists) - this._resources = new File(this._root.getAbsolutePath() + "/Resources/").getCanonicalFile(); - - return this; -} - -Project.prototype.name = function() -{ - return this._name; -} - -Project.prototype.targetWithName = function(/*String*/ aName) -{ - var targets = this._targets, - index = 0, - count = targets.length; - - for (; index < count; ++index) - { - var target = targets[index]; - - if (target.name() == aName) - return target; - } - - return null; -} - -Project.prototype.configurationWithName = function(/*String*/ aName) -{ - var configurations = this._configurations, - index = 0, - count = configurations.length; - - for (; index < count; ++index) - { - var configuration = configurations[index]; - - if (configuration.name() == aName) - return configuration; - } - - return null; -} - -Project.prototype.setActiveTarget = function(/*Target*/ aTarget) -{ - this._activeTarget = aTarget; - - this._buildProducts = null; - this._buildIntermediates = null; - this._buildObjects = null; -} - -Project.prototype.activeTarget = function() -{ - return this._activeTarget; -} - -Project.prototype.setActiveConfiguration = function(/*Configuration*/ aConfiguration) -{ - this._activeConfiguration = aConfiguration; - - this._buildProducts = null; - this._buildIntermediates = null; - this._buildObjects = null; -} - -Project.prototype.activeConfiguration = function() -{ - return this._activeConfiguration; -} - -Project.prototype.buildProducts = function() -{ - if (!this._buildProducts) - { - this._buildProducts = new File(this.buildPath + '/' + this._activeConfiguration.name() + '/' + this._activeTarget.name()).getCanonicalFile(); - this._buildProducts.mkdirs(); - } - - return this._buildProducts; -} - -Project.prototype.buildIntermediates = function() -{ - if (!this._buildIntermediates) - { - this._buildIntermediates = new File(this.buildPath + '/' + this._activeTarget.name() + ".build/" + this._activeConfiguration.name()).getCanonicalFile(); - this._buildIntermediates.mkdirs(); - } - - return this._buildIntermediates; -} - -Project.prototype.buildObjects = function() -{ - if (!this._buildObjects) - { - this._buildObjects = new File(this.buildIntermediates().getAbsolutePath() + '/' + this._activeTarget.name()).getCanonicalFile(); - this._buildObjects.mkdirs(); - } - - return this._buildObjects; -} - -Project.prototype.activeFlags = function() -{ - return this.activeTarget().flags().concat(this.activeConfiguration().flags()); -} - -Project.prototype.build = function() -{ - java.lang.System.out.println("Building Target \"" + this.activeTarget().name() + - "\" of Project \"" + this.name() + - "\" with Configuration \"" + this.activeConfiguration().name() + "\"."); - - var jFiles = getFiles(this._root, "j", this._activeTarget.exclusions()), - replacedFiles = []; - hasModifiedJFiles = false; - shouldObjjPreprocess = true, - shouldGzip = this._gzip, - objjcComponents = ["sh", OBJJ_HOME + "/bin/objjc"]; - - objjcComponents = objjcComponents.concat(this.activeFlags()); - - if (!shouldObjjPreprocess) - objjcComponents.push("-E"); - - var buildObjects = this.buildObjects(), - buildProducts = this.buildProducts(); - - for (index = 0, count = jFiles.length; index < count; ++index) - { - var file = jFiles[index], - builtFile = new File(buildObjects.getAbsolutePath() + '/' + getFileNameWithoutExtension(file) + '.o'); - - replacedFiles.push(file.getName() + ""); - - if (builtFile.exists() && file.lastModified() < builtFile.lastModified()) - continue; - else - hasModifiedJFiles = true; - - objjcComponents.push(file.getAbsolutePath()); - - objjcComponents.push("-o"); - objjcComponents.push(buildObjects.getAbsolutePath() + '/' + getFileNameWithoutExtension(file) + '.o'); - } - - exec(objjcComponents, true); - - var oFiles = getFiles(buildObjects, 'o'), - sjFile = new File(buildProducts.getCanonicalPath() + '/' + this._activeTarget.name() + ".sj"); - - if (hasModifiedJFiles) - { - // concatenate sjheader.txt and individual .o - exec(["sh", "-c", "cat '" + OBJJ_HOME + "/lib/sjheader.txt' '" + oFiles.join("' '") + "' > '" + sjFile.getCanonicalPath() + "'"], true); - } - - if (shouldGzip) - { - // gzip and copy .htaccess file - exec(["sh", "-c", "gzip -c '" + sjFile.getCanonicalPath() + "' > '" + sjFile.getCanonicalPath() + ".gz'"], true); - exec(["cp", OBJJ_HOME + "/lib/htaccess", sjFile.getParentFile().getCanonicalPath() + "/.htaccess"], true); - } - else - { - // remove gzip and .htaccess file if present - exec(["rm", "-f", sjFile.getParentFile().getCanonicalPath() + "/.htaccess", sjFile.getCanonicalPath() + ".gz"], true); - } - - dictionary_setValue(this._infoDictionary, "CPBundleExecutable", this._activeTarget.name() + ".sj"); - dictionary_setValue(this._infoDictionary, "CPBundleReplacedFiles", replacedFiles); - - this.writeInfoPlist(); - - this.copyResources(); - - // FIXME: This should be, if this is an app... - if (dictionary_getValue(this._infoDictionary, "CPBundlePackageType") == "280N") - this.copyIndexFile(); - -} - -Project.prototype.clean = function() -{ - java.lang.System.out.println("Cleaning Target \"" + this.activeTarget().name() + - "\" of Project \"" + this.name() + - "\" with Configuration \"" + this.activeConfiguration().name() + "\"."); - - exec(["rm", "-rf", this.buildIntermediates().getAbsolutePath()], true); - exec(["rm", "-rf", this.buildProducts().getAbsolutePath()], true); -} - -Project.prototype.copyIndexFile = function() -{ - var indexFile = new File(this._root.getAbsolutePath() + "/index.html").getCanonicalFile(); - - rsync(indexFile, this.buildProducts()); -} - -Project.prototype.writeInfoPlist = function() -{ - var writer = new BufferedWriter(new FileWriter(this.buildProducts().getAbsolutePath() + '/' + "Info.plist")); - - writer.write(CPPropertyListCreateXMLData(this._infoDictionary).string); - - writer.close(); -} - -Project.prototype.copyResources = function() -{ - rsync(this._resources, this.buildProducts()); -} - -function printUsage(command) -{ - var usage = "usage: steam COMMAND [ARGS]\n\n"+ -"The most commonly used steam commands are:\n"+ -"\tbuild Build a project\n"+ -"\tcreate Create a new project\n\n"+ -"See 'steam help COMMAND' for more information on a specific command."; - - switch (command) - { - case "--help": - case undefined: java.lang.System.out.println(usage); - break; - - case "create": java.lang.System.out.println("Creates a new Cappuccino project.\n\nusage: steam create PROJECT_NAME [-l]\n\n"+ - "\t-l Link Frameworks to $STEAM_BUILD/Release, instead of installing default Frameworks"); - break; - - default: java.lang.System.out.println("steam: '" + command + "' is not a steam command. See 'steam --help'."); - } - java.lang.System.exit(1); -} - -function main() -{ - if (arguments.length < 1) - printUsage(); - - var command = Array.prototype.shift.apply(arguments); - switch (command) - { - case "create": mainCreate.apply(mainCreate, arguments); - break; - case "build": - mainBuild.apply(mainBuild, arguments); - break; - - case "help": printUsage(arguments[1]); - break; - - case "version": - case "--version": printVersion(); - break; - - default : printUsage(command); - } - -} - -function printVersion() -{ - java.lang.System.out.println("steam version 0.6"); - java.lang.System.exit(1); -} - -function mainCreate() -{ - if (arguments.length < 1) - printUsage("create"); - - var link = false, - index = 0, - count = arguments.length; - - for (; index < count; ++index) - { - var argument = arguments[index]; - - switch (arguments[index]) - { - case "-l": link = true; - break; - default: destination = argument; - } - } - - var sourceNewApplication = new File(OBJJ_HOME + "/lib/NewApplication"), - destinationNewApplication = new File(destination), - sourceFrameworks = new File(OBJJ_HOME + "/lib/Frameworks"), - sourceDebugFrameworks = new File(OBJJ_HOME + "/lib/Frameworks-Debug"), - destinationFrameworks = new File(destination + "/Frameworks"), - destinationDebugFrameworks = new File(destination + "/Frameworks/Debug"); - - System.out.println(sourceNewApplication.getCanonicalPath() + "," + destinationNewApplication.getCanonicalPath() + "," + sourceFrameworks.getCanonicalPath() + "," + destinationFrameworks.getCanonicalPath()); - - if (!destinationNewApplication.exists()) - { - exec(["cp", "-vR", sourceNewApplication.getCanonicalPath(), destinationNewApplication.getCanonicalPath()], true); - - if (!link) - { - exec(["cp", "-vR", sourceFrameworks.getCanonicalPath(), destinationFrameworks.getCanonicalPath()], true); - exec(["cp", "-vR", sourceDebugFrameworks.getCanonicalPath(), destinationDebugFrameworks.getCanonicalPath()], true); - } - else - { - var STEAM_BUILD = System.getenv("STEAM_BUILD"); - - // Release Frameworks - new File(destinationFrameworks).mkdir(); - - exec(["ln", "-s", new File(STEAM_BUILD + "/Release/Objective-J").getCanonicalPath(), - new File(destination + "/Frameworks/Objective-J").getCanonicalPath()], true); - - exec(["ln", "-s", new File(STEAM_BUILD + "/Release/Foundation").getCanonicalPath(), - new File(destination + "/Frameworks/Foundation").getCanonicalPath()], true); - - exec(["ln", "-s", new File(STEAM_BUILD + "/Release/AppKit").getCanonicalPath(), - new File(destination + "/Frameworks/AppKit").getCanonicalPath()], true); - - // Debug Frameworks - new File(destinationDebugFrameworks).mkdir(); - - exec(["ln", "-s", new File(STEAM_BUILD + "/Debug/Objective-J").getCanonicalPath(), - new File(destination + "/Frameworks/Debug/Objective-J").getCanonicalPath()], true); - - exec(["ln", "-s", new File(STEAM_BUILD + "/Debug/Foundation").getCanonicalPath(), - new File(destination + "/Frameworks/Debug/Foundation").getCanonicalPath()], true); - - exec(["ln", "-s", new File(STEAM_BUILD + "/Debug/AppKit").getCanonicalPath(), - new File(destination + "/Frameworks/Debug/AppKit").getCanonicalPath()], true); - } - } - else - System.out.println("Directory already exists"); -} - -function mainBuild() -{ - var index = 0, - count = arguments.length, - - actions = [], - - targetName = null, - configurationName = null, - - buildPath = null, - projectFilePath = null, - - gzip = false; - - for (; index < count; ++index) - { - switch (arguments[index]) - { - case "-f": if (index + 1 == count) - throw "-f needs project file."; - - projectFilePath = arguments[++index]; - break; - - case "-t": if (index + 1 == count) - throw "-t needs a target"; - - targetName = arguments[++index]; - break; - - case "-c": if (index + 1 == count) - throw "-c needs configuration"; - - configurationName = arguments[++index]; - break; - - case "-b": if (index + 1 == count) - throw "-b needs a build location"; - - buildPath = arguments[++index]; - break; - - case "--gzip": gzip = true; - break; - - case "clean": - case "build": actions.push(arguments[index]); - break; - } - } - - // If no project file was specified, look for one. - if (!projectFilePath) - { - var candidates = getFiles(new File('.'), "steam"); - - if (candidates.length < 1) - throw "No project file specified or found."; - - projectFilePath = candidates[0]; - } - - // Construct the Build Directory - if (!buildPath) - { - buildPath = System.getenv("STEAM_BUILD"); - - if (!buildPath) - buildPath = "Build"; - } - - var project = new Project(projectFilePath, buildPath); - - project._gzip = gzip; - - if (targetName) - { - var target = project.targetWithName(targetName); - - if (!target) - throw "Target \"" + targetName + "\" not found in project."; - - project.setActiveTarget(target); - } - - if (configurationName) - { - var configuration = project.configurationWithName(configurationName); - - if (!configuration) - throw "Configuration \"" + configurationName + "\" not found in project."; - - project.setActiveConfiguration(configuration); - } - - if (!actions.length) - actions.push("build"); - - for (index = 0, count = actions.length; index < count; ++index) - project[actions[index]](); -} - -function fileArrayContainsFile(/*Array*/ files, /*File*/ aFile) -{ - var index = 0, - count = files.length; - - for (; index < count; ++index) - if (files[index].equals(aFile)) - return true; - - return false; -} - -function getFiles(/*File*/ sourceDirectory, /*nil|String|Array*/ extensions, /*Array*/ exclusions) -{ - var matches = [], - files = sourceDirectory.listFiles(), - hasMultipleExtensions = typeof extensions !== "string"; - - if (files) - { - var index = 0, - count = files.length; - - for (; index < count; ++index) - { - var file = files[index].getCanonicalFile(), - name = String(file.getName()), - isValidExtension = !extensions; - - if (exclusions && fileArrayContainsFile(exclusions, file)) - continue; - - if (!isValidExtension) - if (hasMultipleExtensions) - { - var extensionCount = extensions.length; - - while (extensionCount-- && !isValidExtension) - { - var extension = extensions[extensionCount]; - - if (name.substring(name.length - extension.length - 1) === ("." + extension)) - isValidExtension = true; - } - } - else if (name.substring(name.length - extensions.length - 1) === ("." + extensions)) - isValidExtension = true; - - if (isValidExtension) - matches.push(file); - - if (file.isDirectory()) - matches = matches.concat(getFiles(file, extensions, exclusions)); - } - } - - return matches; -} - -function readPlist(/*File*/ aFile) -{ - var reader = new BufferedReader(new FileReader(aFile)), - fileContents = ""; - - // Get contents of the file - while (reader.ready()) - fileContents += reader.readLine() + '\n'; - - reader.close(); - - var data = new objj_data(); - data.string = fileContents; - - return new CPPropertyListCreateFromData(data); -} - -function exec(/*Array*/ command, /*Boolean*/ showOutput) -{ - var line = "", - output = "", - - process = Packages.java.lang.Runtime.getRuntime().exec(command),//jsArrayToJavaArray(command)); - reader = new Packages.java.io.BufferedReader(new Packages.java.io.InputStreamReader(process.getInputStream())); - - while (line = reader.readLine()) - { - if (showOutput) - System.out.println(line); - - output += line + '\n'; - } - - reader = new Packages.java.io.BufferedReader(new Packages.java.io.InputStreamReader(process.getErrorStream())); - - while (line = reader.readLine()) - System.out.println(line); - - try - { - if (process.waitFor() != 0) - System.err.println("exit value = " + process.exitValue()); - } - catch (anException) - { - System.err.println(anException); - } - - return output; -} - -function rsync(srcFile, dstFile) -{ - var src, dst; - - if (String(java.lang.System.getenv("OS")).indexOf("Windows") < 0) - { - src = srcFile.getAbsolutePath(); - dst = dstFile.getAbsolutePath(); - } - else - { - src = exec(["cygpath", "-u", srcFile.getAbsolutePath() + '/']); - dst = exec(["cygpath", "-u", dstFile.getAbsolutePath() + "/Resources"]); - } - - if (srcFile.exists()) - exec(["rsync", "-avz", src, dst]); -} - -function getFileName(aPath) -{ - var index = aPath.lastIndexOf('/'); - - if (index == -1) - return aPath; - - return aPath.substr(index + 1); -} - -function getFileNameWithoutExtension(aFile) -{ - var name = aFile.getName(), - index = name.lastIndexOf('.'); - - if (index == -1 || index == 0) - return name; - - return name.substr(0, index); -} - -function getFileExtension(aPath) -{ - var slash = aPath.lastIndexOf('/'), - period = aPath.lastIndexOf('.'); - - if (period < slash || (period == slash + 1)) - return ""; - - return aPath.substr(period + 1); -} - -main.apply(main, arguments); diff --git a/Tools/steam/steam.xml b/Tools/steam/steam.xml index 9db95a440..8b5e0a9f6 100644 --- a/Tools/steam/steam.xml +++ b/Tools/steam/steam.xml @@ -15,4 +15,23 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Tools/steam/usage.js b/Tools/steam/usage.js new file mode 100644 index 000000000..389fadc53 --- /dev/null +++ b/Tools/steam/usage.js @@ -0,0 +1,22 @@ +function printUsage(command) +{ + var usage = "usage: steam COMMAND [ARGS]\n\n"+ +"The most commonly used steam commands are:\n"+ +"\tbuild Build a project\n"+ +"\tcreate Create a new project\n\n"+ +"See 'steam help COMMAND' for more information on a specific command."; + + switch (command) + { + case "--help": + case undefined: java.lang.System.out.println(usage); + break; + + case "create": java.lang.System.out.println("Creates a new Cappuccino project.\n\nusage: steam create PROJECT_NAME [-l]\n\n"+ + "\t-l Link Frameworks to $STEAM_BUILD/Release, instead of installing default Frameworks"); + break; + + default: java.lang.System.out.println("steam: '" + command + "' is not a steam command. See 'steam --help'."); + } + java.lang.System.exit(1); +} diff --git a/Tools/steam/version.js b/Tools/steam/version.js new file mode 100644 index 000000000..c22171a3f --- /dev/null +++ b/Tools/steam/version.js @@ -0,0 +1,5 @@ +function printVersion() +{ + java.lang.System.out.println("steam version 0.6"); + java.lang.System.exit(1); +} \ No newline at end of file