From 2664e30a8b60af05330009d6005dff3edcd1b7ef Mon Sep 17 00:00:00 2001 From: Francisco Tolmasky Date: Sun, 8 Mar 2009 20:40:11 -0700 Subject: [PATCH] A number of changes. Reviewed by me. --- AppKit/CPPopUpButton.j | 10 +- AppKit/CPScroller.j | 191 +++++------ AppKit/CPThemedAttribute.j | 97 +++--- AppKit/Cib/CPCib.j | 48 --- AppKit/Cib/_CPCibObjectData.j | 59 +++- Foundation/CPKeyedArchiver.j | 4 +- Objective-J/evaluate.js | 19 +- Tools/blend/BlendKit/BKShowcaseController.j | 120 +++++++ Tools/blend/BlendKit/BKUtilities.j | 145 +++++++++ Tools/blend/BlendKit/BlendKit.j | 3 + Tools/blend/BlendKit/BlendKit.steam | 42 +++ Tools/blend/BlendKit/Info.plist | 14 + Tools/blend/BlendKit/build.xml | 33 ++ Tools/blend/Tool/blend | 57 ++++ Tools/blend/Tool/blend.steam | 46 +++ Tools/blend/Tool/build.xml | 23 ++ Tools/blend/Tool/main.j | 301 ++++++++++++++++++ Tools/blend/build.xml | 28 ++ Tools/steam/Project.js | 124 -------- .../Templates/ThemeDescriptor/Info.plist | 12 + .../ThemeDescriptor/ThemeDescriptors.j | 33 ++ .../ThemeDescriptor/index-debug.html | 36 +++ .../Templates/ThemeDescriptor/index.html | 37 +++ Tools/steam/Templates/ThemeDescriptor/main.j | 19 ++ 24 files changed, 1143 insertions(+), 358 deletions(-) create mode 100644 Tools/blend/BlendKit/BKShowcaseController.j create mode 100644 Tools/blend/BlendKit/BKUtilities.j create mode 100644 Tools/blend/BlendKit/BlendKit.j create mode 100644 Tools/blend/BlendKit/BlendKit.steam create mode 100644 Tools/blend/BlendKit/Info.plist create mode 100644 Tools/blend/BlendKit/build.xml create mode 100755 Tools/blend/Tool/blend create mode 100644 Tools/blend/Tool/blend.steam create mode 100644 Tools/blend/Tool/build.xml create mode 100644 Tools/blend/Tool/main.j create mode 100644 Tools/blend/build.xml create mode 100644 Tools/steam/Templates/ThemeDescriptor/Info.plist create mode 100644 Tools/steam/Templates/ThemeDescriptor/ThemeDescriptors.j create mode 100644 Tools/steam/Templates/ThemeDescriptor/index-debug.html create mode 100644 Tools/steam/Templates/ThemeDescriptor/index.html create mode 100755 Tools/steam/Templates/ThemeDescriptor/main.j diff --git a/AppKit/CPPopUpButton.j b/AppKit/CPPopUpButton.j index a2049230b..80d463868 100644 --- a/AppKit/CPPopUpButton.j +++ b/AppKit/CPPopUpButton.j @@ -95,7 +95,7 @@ CPPopUpButtonStatePullsDown = 1 << 12; var items = [_menu itemArray]; - if (items.length <= 0) + if ([items count] <= 0) return; [items[0] setHidden:[self pullsDown]]; @@ -493,14 +493,14 @@ CPPopUpButtonStatePullsDown = 1 << 12; */ - (void)setTitle:(CPString)aTitle { - if ([self title] == aTitle) + if ([self title] === aTitle) return; if ([self pullsDown]) { var items = [_menu itemArray]; - if (items.length <= 0) + if ([items count] <= 0) [self addItemWithTitle:aTitle]; else @@ -548,7 +548,7 @@ CPPopUpButtonStatePullsDown = 1 << 12; { var items = [_menu itemArray]; - if (items.length > 0) + if ([items count] > 0) item = items[0]; } else @@ -717,7 +717,7 @@ var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey", { // Nothing is currently selected _selectedIndex = -1; - + [self setMenu:[aCoder decodeObjectForKey:CPPopUpButtonMenuKey]]; [self selectItemAtIndex:[aCoder decodeObjectForKey:CPPopUpButtonSelectedIndexKey]]; } diff --git a/AppKit/CPScroller.j b/AppKit/CPScroller.j index 8ac1a42ce..cecfec70d 100644 --- a/AppKit/CPScroller.j +++ b/AppKit/CPScroller.j @@ -45,7 +45,15 @@ CPAllScrollerParts = 2; */ -var PARTS_ARRANGEMENT = [CPScrollerKnobSlot, CPScrollerDecrementLine, CPScrollerIncrementLine, CPScrollerKnob]; +var PARTS_ARRANGEMENT = [CPScrollerKnobSlot, CPScrollerDecrementLine, CPScrollerIncrementLine, CPScrollerKnob], + NAMES_FOR_PARTS = {}, + PARTS_FOR_NAMES = {}; + +NAMES_FOR_PARTS[CPScrollerDecrementLine] = @"decrement-line"; +NAMES_FOR_PARTS[CPScrollerIncrementLine] = @"increment-line"; +NAMES_FOR_PARTS[CPScrollerKnobSlot] = @"knob-slot"; +NAMES_FOR_PARTS[CPScrollerKnob] = @"knob"; + @implementation CPScroller : CPControl { @@ -53,7 +61,7 @@ var PARTS_ARRANGEMENT = [CPScrollerKnobSlot, CPScrollerDecrementLine, CPScroller CPUsableScrollerParts _usableParts; CPArray _partRects; - BOOL _isVertical; + BOOL _isVertical @accessors(readonly, getter=isVertical); float _knobProportion; CPScrollerPart _hitPart; @@ -61,32 +69,21 @@ var PARTS_ARRANGEMENT = [CPScrollerKnobSlot, CPScrollerDecrementLine, CPScroller CPScrollerPart _trackingPart; float _trackingFloatValue; CGPoint _trackingStartPoint; - - CPView _knobView; - CPView _knobSlotView; - - CPView _decrementArrowView; - CPView _incrementArrowView; } + (id)themedAttributes { return [CPDictionary dictionaryWithObjects:[ _CGInsetMakeZero(), - nil, nil, nil, nil, - nil, nil, nil, nil, - _CGSizeMakeZero(), _CGSizeMakeZero(), _CGSizeMakeZero(), + nil, nil, nil, nil, _CGSizeMakeZero(), _CGSizeMakeZero(), _CGSizeMakeZero()] forKeys:[ @"track-overlap-inset", - @"horizontal-" + CPScrollerKnobSlot + "-color", - @"horizontal-" + CPScrollerDecrementLine + "-color", - @"horizontal-" + CPScrollerIncrementLine + "-color", - @"horizontal-" + CPScrollerKnob + "-color", - @"vertical-" + CPScrollerKnobSlot + "-color", - @"vertical-" + CPScrollerDecrementLine + "-color", - @"vertical-" + CPScrollerIncrementLine + "-color", - @"vertical-" + CPScrollerKnob + "-color", - @"horizontal-decrement-line-size", @"horizontal-increment-line-size", @"horizontal-minimum-knob-size", - @"vertical-decrement-line-size", @"vertical-increment-line-size", @"vertical-minimum-knob-size"]]; + @"knob-slot-color", + @"decrement-line-color", + @"increment-line-color", + @"knob-color", + @"decrement-line-size", + @"increment-line-size", + @"minimum-knob-size"]]; } @@ -104,24 +101,13 @@ var PARTS_ARRANGEMENT = [CPScrollerKnobSlot, CPScrollerDecrementLine, CPScroller [self setFloatValue:0.0 knobProportion:1.0]; _hitPart = CPScrollerNoPart; + + [self _recalculateIsVertical]; } return self; } -- (BOOL)isVertical -{ - if (_isVertical === nil) - { - var bounds = [self bounds], - width = _CGRectGetWidth(bounds), - height = _CGRectGetHeight(bounds); - - _isVertical = width < height ? 1 : (width > height ? 0 : -1); - } - - return _isVertical; -} // Determining CPScroller Size /*! Returns the CPScroller's width for a CPRegularControlSize. @@ -195,64 +181,14 @@ var PARTS_ARRANGEMENT = [CPScrollerKnobSlot, CPScrollerDecrementLine, CPScroller return _knobProportion; } -- (void)setColor:(CPColor)aColor forHorizontalPart:(CPScrollerPart)aScrollerPart inControlState:(CPControlState)aControlState -{ - [self setValue:aColor forThemedAttributeName:"horizontal-" + aScrollerPart + "-color" inControlState:aControlState]; -} - -- (CPColor)colorForHorizontalPart:(CPScrollerPart)aScrollerPart inControlState:(CPControlState)aControlState -{ - return [self valueForThemedAttributeName:"horizontal-" + aScrollerPart + "-color" inControlState:aControlState]; -} - -- (void)setColor:(CPColor)aColor forHorizontalPart:(CPScrollerPart)aScrollerPart -{ - [self setValue:aColor forThemedAttributeName:"horizontal-" + aScrollerPart + "-color"]; -} - -- (id)colorForHorizontalPart:(CPScrollerPart)aScrollerPart -{ - return [self valueForThemedAttributeName:"horizontal-" + aScrollerPart + "-color" inControlState:aControlState]; -} - -- (id)currentColorForHorizontalPart:(CPScrollerPart)aScrollerPart +- (id)currentValueForThemedAttributeName:(CPString)anAttributeName { var controlState = _controlState; - if (_hitPart !== aScrollerPart) + if (NAMES_FOR_PARTS[_hitPart] + "-color" !== anAttributeName) controlState &= ~CPControlStateHighlighted; - return [self valueForThemedAttributeName:"horizontal-" + aScrollerPart + "-color" inControlState:controlState]; -} - -- (void)setColor:(CPColor)aColor forVerticalPart:(CPScrollerPart)aScrollerPart inControlState:(CPControlState)aControlState -{ - [self setValue:aColor forThemedAttributeName:"vertical-" + aScrollerPart + "-color" inControlState:aControlState]; -} - -- (CPColor)colorForVerticalPart:(CPScrollerPart)aScrollerPart inControlState:(CPControlState)aControlState -{ - return [self valueForThemedAttributeName:"vertical-" + aScrollerPart + "-color" inControlState:aControlState]; -} - -- (void)setColor:(CPColor)aColor forVerticalPart:(CPScrollerPart)aScrollerPart -{ - [self setValue:aColor forThemedAttributeName:"vertical-" + aScrollerPart + "-color"]; -} - -- (id)colorForVerticalPart:(CPScrollerPart)aScrollerPart -{ - return [self valueForThemedAttributeName:"vertical-" + aScrollerPart + "-color" inControlState:aControlState]; -} - -- (id)currentColorForVerticalPart:(CPScrollerPart)aScrollerPart -{ - var controlState = _controlState; - - if (_hitPart !== aScrollerPart) - controlState &= ~CPControlStateHighlighted; - - return [self valueForThemedAttributeName:"vertical-" + aScrollerPart + "-color" inControlState:controlState]; + return [self valueForThemedAttributeName:anAttributeName inControlState:controlState]; } // Calculating Layout @@ -325,40 +261,21 @@ var PARTS_ARRANGEMENT = [CPScrollerKnobSlot, CPScrollerDecrementLine, CPScroller // At this point we know we're going to need arrows. _usableParts = CPAllScrollerParts; - var isHorizontal = ![self isVertical], - trackOverlapInset = [self currentValueForThemedAttributeName:@"track-overlap-inset"], + var trackOverlapInset = [self currentValueForThemedAttributeName:@"track-overlap-inset"], width = _CGRectGetWidth(bounds), height = _CGRectGetHeight(bounds); - if (isHorizontal) + if ([self isVertical]) { - var decrementLineSize = [self currentValueForThemedAttributeName:"horizontal-decrement-line-size"], - incrementLineSize = [self currentValueForThemedAttributeName:"horizontal-increment-line-size"], - effectiveDecrementLineWidth = decrementLineSize.width - trackOverlapInset.left, - effectiveIncrementLineWidth = incrementLineSize.width - trackOverlapInset.right; - slotWidth = width - effectiveDecrementLineWidth - effectiveIncrementLineWidth, - minimumKnobSize = [self currentValueForThemedAttributeName:"horizontal-minimum-knob-size"], - knobWidth = MAX(minimumKnobSize.width, (slotWidth * _knobProportion)), - knobLocation = effectiveDecrementLineWidth + (slotWidth - knobWidth) * [self floatValue]; - - _partRects[CPScrollerDecrementPage] = _CGRectMake(effectiveDecrementLineWidth, 0.0, knobLocation - effectiveDecrementLineWidth, height); - _partRects[CPScrollerKnob] = _CGRectMake(knobLocation, 0.0, knobWidth, minimumKnobSize.height); - _partRects[CPScrollerIncrementPage] = _CGRectMake(knobLocation + knobWidth, 0.0, width - (knobLocation + knobWidth) - effectiveIncrementLineWidth, height); - _partRects[CPScrollerKnobSlot] = _CGRectMake(effectiveDecrementLineWidth, 0.0, slotWidth, height); - _partRects[CPScrollerDecrementLine] = _CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height); - _partRects[CPScrollerIncrementLine] = _CGRectMake(width - incrementLineSize.width, 0.0, incrementLineSize.width, incrementLineSize.height); - } - else - { - var decrementLineSize = [self currentValueForThemedAttributeName:"vertical-decrement-line-size"], - incrementLineSize = [self currentValueForThemedAttributeName:"vertical-decrement-line-size"], + var decrementLineSize = [self currentValueForThemedAttributeName:"decrement-line-size"], + incrementLineSize = [self currentValueForThemedAttributeName:"increment-line-size"], effectiveDecrementLineHeight = decrementLineSize.height - trackOverlapInset.top, effectiveIncrementLineHeight = incrementLineSize.height - trackOverlapInset.bottom, slotHeight = height - effectiveDecrementLineHeight - effectiveIncrementLineHeight, - minimumKnobSize = [self currentValueForThemedAttributeName:"vertical-minimum-knob-size"], + minimumKnobSize = [self currentValueForThemedAttributeName:"minimum-knob-size"], knobHeight = MAX(minimumKnobSize.height, (slotHeight * _knobProportion)), knobLocation = effectiveDecrementLineHeight + (slotHeight - knobHeight) * [self floatValue]; - + _partRects[CPScrollerDecrementPage] = _CGRectMake(0.0, effectiveDecrementLineHeight, width, knobLocation - effectiveDecrementLineHeight); _partRects[CPScrollerKnob] = _CGRectMake((width - minimumKnobSize.width) / 2.0, knobLocation, minimumKnobSize.width, knobHeight); _partRects[CPScrollerIncrementPage] = _CGRectMake(0.0, knobLocation + knobHeight, width, height - (knobLocation + knobHeight) - effectiveIncrementLineHeight); @@ -366,6 +283,25 @@ var PARTS_ARRANGEMENT = [CPScrollerKnobSlot, CPScrollerDecrementLine, CPScroller _partRects[CPScrollerDecrementLine] = _CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height); _partRects[CPScrollerIncrementLine] = _CGRectMake(0.0, height - incrementLineSize.height, incrementLineSize.width, incrementLineSize.height); } + + else + { + var decrementLineSize = [self currentValueForThemedAttributeName:"decrement-line-size"], + incrementLineSize = [self currentValueForThemedAttributeName:"increment-line-size"], + effectiveDecrementLineWidth = decrementLineSize.width - trackOverlapInset.left, + effectiveIncrementLineWidth = incrementLineSize.width - trackOverlapInset.right; + slotWidth = width - effectiveDecrementLineWidth - effectiveIncrementLineWidth, + minimumKnobSize = [self currentValueForThemedAttributeName:"minimum-knob-size"], + knobWidth = MAX(minimumKnobSize.width, (slotWidth * _knobProportion)), + knobLocation = effectiveDecrementLineWidth + (slotWidth - knobWidth) * [self floatValue]; + + _partRects[CPScrollerDecrementPage] = _CGRectMake(effectiveDecrementLineWidth, 0.0, knobLocation - effectiveDecrementLineWidth, height); + _partRects[CPScrollerKnob] = _CGRectMake(knobLocation, 0.0, knobWidth, minimumKnobSize.height); + _partRects[CPScrollerIncrementPage] = _CGRectMake(knobLocation + knobWidth, 0.0, width - (knobLocation + knobWidth) - effectiveIncrementLineWidth, height); + _partRects[CPScrollerKnobSlot] = _CGRectMake(effectiveDecrementLineWidth, 0.0, slotWidth, height); + _partRects[CPScrollerDecrementLine] = _CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height); + _partRects[CPScrollerIncrementLine] = _CGRectMake(width - incrementLineSize.width, 0.0, incrementLineSize.width, incrementLineSize.height); + } } /*! @@ -429,9 +365,8 @@ var PARTS_ARRANGEMENT = [CPScrollerKnobSlot, CPScrollerDecrementLine, CPScroller [self checkSpaceForParts]; var index = 0, - count = PARTS_ARRANGEMENT.length, - selector = [self isVertical] ? @selector(currentColorForVerticalPart:) : @selector(currentColorForHorizontalPart:); - + count = PARTS_ARRANGEMENT.length; + for (; index < count; ++index) { var part = PARTS_ARRANGEMENT[index]; @@ -442,7 +377,7 @@ var PARTS_ARRANGEMENT = [CPScrollerKnobSlot, CPScrollerDecrementLine, CPScroller view = [self layoutEphemeralSubviewNamed:part positioned:CPWindowAbove relativeToEphemeralSubviewNamed:PARTS_ARRANGEMENT[index - 1]]; if (view) - [view setBackgroundColor:objj_msgSend(self, selector, part)]; + [view setBackgroundColor:[self currentValueForThemedAttributeName:NAMES_FOR_PARTS[part] + "-color"]]; } } @@ -589,12 +524,27 @@ var PARTS_ARRANGEMENT = [CPScrollerKnobSlot, CPScrollerDecrementLine, CPScroller } +- (void)_recalculateIsVertical +{ + // Recalculate isVertical. + var bounds = [self bounds], + width = _CGRectGetWidth(bounds), + height = _CGRectGetHeight(bounds); + + _isVertical = width < height ? 1 : (width > height ? 0 : -1); + + if (_isVertical === 1) + _controlState |= CPControlStateVertical; + else if (_isVertical === 0) + _controlState &= ~CPControlStateVertical; +} + - (void)setFrameSize:(CGSize)aSize { [super setFrameSize:aSize]; - - _isVertical = nil; - + + [self _recalculateIsVertical]; + [self checkSpaceForParts]; [self setNeedsLayout]; } @@ -639,7 +589,8 @@ var CPScrollerControlSizeKey = "CPScrollerControlSize", _partRects = []; _hitPart = CPScrollerNoPart; - + + [self _recalculateIsVertical]; // [self checkSpaceForParts]; // [self setNeedsLayout]; } diff --git a/AppKit/CPThemedAttribute.j b/AppKit/CPThemedAttribute.j index 24d2bf9d8..9ab810f76 100644 --- a/AppKit/CPThemedAttribute.j +++ b/AppKit/CPThemedAttribute.j @@ -32,6 +32,8 @@ var BIT_COUNT = [ 0 /*00000*/, 1 /*00001*/, 1 /*00010*/, 2 /*00011*/, 1 /*0010 { BOOL _isSingularObject; + JSObject _cache; + CPString _name; id _defaultValue; @@ -45,21 +47,23 @@ var BIT_COUNT = [ 0 /*00000*/, 1 /*00001*/, 1 /*00010*/, 2 /*00011*/, 1 /*0010 - (id)initWithName:(CPString)aName defaultValue:(id)aDefaultValue theme:(CPTheme)aTheme class:(Class)aClass { self = [super init]; - + if (self) { + _cache = {}; + _name = aName; - + _defaultValue = aDefaultValue; - + _theme = aTheme; _themedClass = aClass; - + _isSingularObject = YES; _values = nil; _valueFromTheme = [_theme valueForAttributeName:_name inClass:_themedClass]; } - + return self; } @@ -75,6 +79,7 @@ var BIT_COUNT = [ 0 /*00000*/, 1 /*00001*/, 1 /*00010*/, 2 /*00011*/, 1 /*0010 - (void)setDefaultValue:(id)aValue { + _cache = {}; _defaultValue = aValue; } @@ -83,6 +88,7 @@ var BIT_COUNT = [ 0 /*00000*/, 1 /*00001*/, 1 /*00010*/, 2 /*00011*/, 1 /*0010 if (_theme === aTheme) return; + _cache = {}; _theme = aTheme; _valueFromTheme = [_theme valueForAttributeName:_name inClass:_themedClass]; } @@ -98,6 +104,7 @@ var BIT_COUNT = [ 0 /*00000*/, 1 /*00001*/, 1 /*00010*/, 2 /*00011*/, 1 /*0010 - (void)setValue:(id)aValue { + _cache = {}; _isSingularObject = YES; _values = aValue; } @@ -109,6 +116,8 @@ var BIT_COUNT = [ 0 /*00000*/, 1 /*00001*/, 1 /*00010*/, 2 /*00011*/, 1 /*0010 - (void)setValue:(id)aValue forControlState:(CPControlState)aState { + _cache = {}; + if (aState !== CPControlStateNormal) { if (_isSingularObject) @@ -135,54 +144,52 @@ var BIT_COUNT = [ 0 /*00000*/, 1 /*00001*/, 1 /*00010*/, 2 /*00011*/, 1 /*0010 - (id)valueForControlState:(CPControlState)aState { + var value = _cache[aState]; + + if (value !== undefined && value !== nil) + return value; + if (_isSingularObject) - { var value = _values; - if (value === undefined || value === nil) - value = [_valueFromTheme valueForControlState:aState]; - - if (value === undefined || value === nil) - value = _defaultValue; - - return value; - } - - var value = _values[aState]; - - // If we don't have a value, and we have a non-normal state... - if ((value === undefined || value === nil) && aState > 0) + else { - // If this is a composite state, find the closest partial subset match. - if (aState & (aState - 1)) + var value = _values[aState]; + + // If we don't have a value, and we have a non-normal state... + if ((value === undefined || value === nil) && aState > 0) { - var highestBitCount = 0; - - for (state in _values) - { - if (!_values.hasOwnProperty(state)) - continue; - - // state is a string! - state = Number(state); - - // A & B = A iff A < B - if ((state & aState) === state) + // If this is a composite state, find the closest partial subset match. + if (aState & (aState - 1)) + { + var highestBitCount = 0; + + for (state in _values) { - var bitCount = (state < BIT_COUNT.length) ? BIT_COUNT[state] : bit_count(state); - - if (bitCount > highestBitCount) + if (!_values.hasOwnProperty(state)) + continue; + + // state is a string! + state = Number(state); + + // A & B = A iff A < B + if ((state & aState) === state) { - highestBitCount = bitCount; - value = _values[state]; + var bitCount = (state < BIT_COUNT.length) ? BIT_COUNT[state] : bit_count(state); + + if (bitCount > highestBitCount) + { + highestBitCount = bitCount; + value = _values[state]; + } } } } - } - // Still don't have a value? OK, let's use the normal value. - if (value === undefined || value === nil) - value = _values[CPControlStateNormal]; + // Still don't have a value? OK, let's use the normal value. + if (value === undefined || value === nil) + value = _values[CPControlStateNormal]; + } } if (value === undefined || value === nil) @@ -191,6 +198,8 @@ var BIT_COUNT = [ 0 /*00000*/, 1 /*00001*/, 1 /*00010*/, 2 /*00011*/, 1 /*0010 if (value === undefined || value === nil) value = _defaultValue; + _cache[aState] = value; + return value; } @@ -234,6 +243,7 @@ var BIT_COUNT = [ 0 /*00000*/, 1 /*00001*/, 1 /*00010*/, 2 /*00011*/, 1 /*0010 if (self) { + _cache = {}; _isSingularObject = [aCoder containsValueForKey:@"value"]; if (_isSingularObject) @@ -311,7 +321,7 @@ function CPThemedAttributeDecode(aCoder, anAttributeName, aDefaultValue, aTheme, var attribute = [aCoder decodeObjectForKey:key]; - if (![attribute isKindOfClass:[CPThemedAttribute class]]) + if (!attribute.isa || ![attribute isKindOfClass:[CPThemedAttribute class]]) { var themedAttribute = CPThemedAttributeMake(anAttributeName, aDefaultValue, aTheme, aClass); @@ -319,6 +329,7 @@ function CPThemedAttributeDecode(aCoder, anAttributeName, aDefaultValue, aTheme, attribute = themedAttribute; } + else { [attribute setName:anAttributeName]; diff --git a/AppKit/Cib/CPCib.j b/AppKit/Cib/CPCib.j index 995bcac14..cae1ced63 100644 --- a/AppKit/Cib/CPCib.j +++ b/AppKit/Cib/CPCib.j @@ -103,54 +103,6 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey"; // Display Visible Windows. [objectData displayVisibleWindows]; - /* -// [objectData establishConnectionsWithOwner:owner topLevelObjects:topLevelObjects]; -// [objectData cibInstantiateWithOwner:owner topLevelObjects:topLevelObjects]; -// alert([objectData description]); -// alert([unarchiver._archive description]); - - NSMutableArray *t; - NSEnumerator *e; - id o; - id owner; - id rootObject; -#if 0 - NSLog(@"instantiateCibWithExternalNameTable=%@", table); -#endif - if(![decoded isKindOfClass:[NSIBObjectData class]]) - return NO; - owner=[table objectForKey:NSCibOwner]; - rootObject=[decoded rootObject]; -#if 0 - NSLog(@"establishConnections"); -#endif - [decoded establishConnectionsWithExternalNameTable:table]; -#if 0 - NSLog(@"awakeFromCib %d objects", [decodedObjects count]); -#endif -#if 0 - NSLog(@"objects 2=%@", decodedObjects); -#endif - - // FIXME: shouldn't be accessing private variables. - var objects = unarchiver._objects, - count = [objects count]; - - // The order in which objects receive the awakeFromCib message is not guaranteed. - while (count--) - { - var object = objects[count]; - - if ([object respondsToSelector:@selector(awakeFromCib)]) - [object awakeFromCib]; - } - -// if ([owner respondsToSelector:@selector(awakeFromCib)]) -// [owner awakeFromCib]; - // Display visible windows. - - return YES;*/ - return YES; } diff --git a/AppKit/Cib/_CPCibObjectData.j b/AppKit/Cib/_CPCibObjectData.j index 9fc5620c2..b56a33527 100644 --- a/AppKit/Cib/_CPCibObjectData.j +++ b/AppKit/Cib/_CPCibObjectData.j @@ -61,6 +61,43 @@ JSObject _replacementObjects; } +- (id)init +{ + self = [super init]; + + if (self) + { + _namesKeys = []; + _namesValues = []; + + //CPArray _accessibilityConnectors; + //CPArray _accessibilityOidsKeys; + //CPArray _accessibilityOidsValues; + + _classesKeys = []; + _classesValues = []; + + _connections = []; + //id _fontManager; + + _framework = @""; + + _nextOid = []; + + _objectsKeys = []; + _objectsValues = []; + + _oidKeys = []; + _oidValues = []; + + _fileOwner = nil; + + _visibleWindows = [CPSet set]; + } + + return self; +} + - (CPMenu)mainMenu { var index = [_namesValues indexOfObjectIdenticalTo:"MainMenu"]; @@ -114,7 +151,7 @@ var _CPCibObjectDataNamesKeysKey = @"_CPCibObjectDataNamesKeysKey - (id)initWithCoder:(CPCoder)aCoder { self = [super init]; - + if (self) { _replacementObjects = {}; @@ -131,22 +168,22 @@ var _CPCibObjectDataNamesKeysKey = @"_CPCibObjectDataNamesKeysKey _connections = [aCoder decodeObjectForKey:_CPCibObjectDataConnectionsKey]; //id _fontManager; - + _framework = [aCoder decodeObjectForKey:_CPCibObjectDataFrameworkKey]; - + _nextOid = [aCoder decodeIntForKey:_CPCibObjectDataNextOidKey]; - + _objectsKeys = [aCoder decodeObjectForKey:_CPCibObjectDataObjectsKeysKey]; _objectsValues = [aCoder decodeObjectForKey:_CPCibObjectDataObjectsValuesKey]; - + _oidKeys = [aCoder decodeObjectForKey:_CPCibObjectDataOidKeysKey]; _oidValues = [aCoder decodeObjectForKey:_CPCibObjectDataOidValuesKey]; _fileOwner = [aCoder decodeObjectForKey:_CPCibObjectDataFileOwnerKey]; - + _visibleWindows = [aCoder decodeObjectForKey:_CPCibObjectDataVisibleWindowsKey]; } - + return self; } @@ -154,16 +191,16 @@ var _CPCibObjectDataNamesKeysKey = @"_CPCibObjectDataNamesKeysKey { [aCoder encodeObject:_namesKeys forKey:_CPCibObjectDataNamesKeysKey]; [aCoder encodeObject:_namesValues forKey:_CPCibObjectDataNamesValuesKey]; - + //CPArray _accessibilityConnectors; //CPArray _accessibilityOidsKeys; //CPArray _accessibilityOidsValues; - + [aCoder encodeObject:_classesKeys forKey:_CPCibObjectDataClassesKeysKey]; [aCoder encodeObject:_classesValues forKey:_CPCibObjectDataClassesValuesKey]; - + [aCoder encodeObject:_connections forKey:_CPCibObjectDataConnectionsKey]; - + //id _fontManager; [aCoder encodeObject:_framework forKey:_CPCibObjectDataFrameworkKey]; diff --git a/Foundation/CPKeyedArchiver.j b/Foundation/CPKeyedArchiver.j index 28b7db48f..f95df0d2d 100644 --- a/Foundation/CPKeyedArchiver.j +++ b/Foundation/CPKeyedArchiver.j @@ -205,8 +205,8 @@ var _CPKeyedArchiverStringClass = Nil, // We call willEncodeObject previously. _plistObject = _plistObjects[[_UIDs objectForKey:[object hash]]]; - [object encodeWithCoder:self]; - + [object encodeWithCoder:self]; + if (_delegate && _delegateSelectors & _CPKeyedArchiverDidEncodeObjectSelector) [_delegate archiver:self didEncodeObject:object]; } diff --git a/Objective-J/evaluate.js b/Objective-J/evaluate.js index 72fd1ddf1..a6ed69846 100644 --- a/Objective-J/evaluate.js +++ b/Objective-J/evaluate.js @@ -239,12 +239,21 @@ function fragment_evaluate_file(aFragment) return requiresSleep; } -function objj_import(aPath, isLocal, didCompleteCallback) +function objj_import(/*String | Array*/ pathOrPaths, /*BOOL*/ isLocal, /*Function*/ didCompleteCallback) { - var context = new objj_context(); - + var context = new objj_context(), + paths = pathOrPaths; + + if (typeof paths === "string") + paths = [paths]; + + var index = 0, + count = paths.length; + + for (; index < count; ++index) + context.pushFragment(fragment_create_file(paths[index], new objj_bundle(""), isLocal, NULL)); + context.didCompleteCallback = didCompleteCallback; - context.pushFragment(fragment_create_file(aPath, new objj_bundle(""), isLocal, NULL)); - + context.evaluate(); } diff --git a/Tools/blend/BlendKit/BKShowcaseController.j b/Tools/blend/BlendKit/BKShowcaseController.j new file mode 100644 index 000000000..885417f3e --- /dev/null +++ b/Tools/blend/BlendKit/BKShowcaseController.j @@ -0,0 +1,120 @@ + +@import +@import + +@import "BKUtilities.j" + + +@implementation BKShowcaseController : CPObject +{ +} + +- (void)applicationDidFinishLaunching:(CPNotification)aNotification +{ + var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask], + contentView = [theWindow contentView], + bounds = [contentView bounds], + themeDescriptorClasses = BKThemeDescriptorClasses(); + + var tabView = [[CPTabView alloc] initWithFrame:bounds]; + + [tabView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; + + [contentView addSubview:tabView]; + + var count = [themeDescriptorClasses count]; + + while (count--) + { + var theClass = themeDescriptorClasses[count], + item = [[CPTabViewItem alloc] initWithIdentifier:[theClass themeName]], + templates = BKThemeObjectTemplatesForClass(theClass), + templatesCount = [templates count], + viewTemplates = [], + itemSize = CGSizeMake(0.0, 0.0); + + while (templatesCount--) + { + var template = templates[templatesCount], + object = [template valueForKey:@"themedObject"]; + + if ([object isKindOfClass:[CPView class]]) + { + var size = [object frame].size, + labelWidth = [[template valueForKey:@"label"] sizeWithFont:[CPFont boldSystemFontOfSize:12.0]].width + 20.0; + + if (size.width > itemSize.width) + itemSize.width = size.width; + + if (labelWidth > itemSize.width) + itemSize.width = labelWidth; + + if (size.height > itemSize.height) + itemSize.height = size.height; + + [viewTemplates addObject:template]; + } + } + + itemSize.height += 30; + + var collectionView = [[CPCollectionView alloc] initWithFrame:CGRectMakeZero()], + collectionViewItem = [[CPCollectionViewItem alloc] init]; + + [collectionViewItem setView:[[BKShowcaseCell alloc] init]]; + + [collectionView setItemPrototype:collectionViewItem]; + [collectionView setMinItemSize:itemSize]; + [collectionView setMaxItemSize:itemSize]; + [collectionView setVerticalMargin:5.0]; + [collectionView setContent:viewTemplates]; + + [item setLabel:[theClass themeName]]; + [item setView:collectionView]; + + [tabView addTabViewItem:item]; + } + + [theWindow orderFront:self]; +} + +@end + + +@implementation BKShowcaseCell : 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 valueForKey:@"label"]]; + [_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 valueForKey:@"themedObject"]; + + [_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/Tools/blend/BlendKit/BKUtilities.j b/Tools/blend/BlendKit/BKUtilities.j new file mode 100644 index 000000000..bda6e696a --- /dev/null +++ b/Tools/blend/BlendKit/BKUtilities.j @@ -0,0 +1,145 @@ + +@implementation AKThemeTemplate : CPObject +{ + CPString _name; + CPString _description; +} + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super init]; + + if (self) + { + _name = [aCoder decodeObjectForKey:@"AKThemeTemplateName"]; + _description = [aCoder decodeObjectForKey:@"AKThemeTemplateDescription"]; + } + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [aCoder encodeObject:_name forKey:@"AKThemeTemplateName"]; + [aCoder encodeObject:_description forKey:@"AKThemeTemplateDescription"]; +} + +@end + +@implementation AKThemeObjectTemplate : CPView +{ + CPString _label; + id _themedObject; +} + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super init]; + + if (self) + { + _label = [aCoder decodeObjectForKey:@"AKThemeObjectTemplateLabel"]; + _themedObject = [aCoder decodeObjectForKey:@"AKThemeObjectTemplateThemedObject"]; + } + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [aCoder encodeObject:_label forKey:@"AKThemeObjectTemplateLabel"]; + [aCoder encodeObject:_themedObject forKey:@"AKThemeObjectTemplateThemedObject"]; +} + +@end + +function BKThemeDescriptorClasses() +{ + // Grab Theme Descriptor Classes. + var themeDescriptorClasses = []; + + for (candidate in window) + { + var theClass = objj_getClass(candidate), + theClassName = class_getName(theClass), + index = theClassName.indexOf("ThemeDescriptor"); + + if ((index >= 0) && (index === theClassName.length - "ThemeDescriptor".length)) + themeDescriptorClasses.push(theClass); + } + + return themeDescriptorClasses; +} + +function BKThemeObjectTemplatesForClass(aClass) +{ + var templates = [], + methods = class_copyMethodList(aClass.isa), + count = [methods count]; + + while (count--) + { + var method = methods[count], + selector = method_getName(method); + + if (selector.indexOf("themed") === 0) + { + var impl = method_getImplementation(method), + object = impl(aClass, selector); + + if (object) + { + var template = [[AKThemeObjectTemplate alloc] init]; + + [template setValue:object forKey:@"themedObject"]; + [template setValue:BKLabelFromIdentifier(selector) forKey:@"label"]; + + [templates addObject:template]; + } + } + } + + return templates; +} + +function BKLabelFromIdentifier(anIdentifier) +{ + var string = anIdentifier.substr("themed".length); + index = 0, + count = string.length, + label = "", + lastCapital = null, + isLeadingCapital = YES; + + for (; index < count; ++index) + { + var character = string.charAt(index), + isCapital = /^[A-Z]/.test(character); + + if (isCapital) + { + if (!isLeadingCapital) + { + if (lastCapital === null) + label += ' ' + character.toLowerCase(); + else + label += character; + } + + lastCapital = character; + } + else + { + if (isLeadingCapital && lastCapital !== null) + label += lastCapital; + + label += character; + + lastCapital = null; + isLeadingCapital = NO; + } + } + + return label; +} + diff --git a/Tools/blend/BlendKit/BlendKit.j b/Tools/blend/BlendKit/BlendKit.j new file mode 100644 index 000000000..09821ddd7 --- /dev/null +++ b/Tools/blend/BlendKit/BlendKit.j @@ -0,0 +1,3 @@ + +@import "BKShowcaseController.j" +@import "BKUtilities.j" diff --git a/Tools/blend/BlendKit/BlendKit.steam b/Tools/blend/BlendKit/BlendKit.steam new file mode 100644 index 000000000..75d93232e --- /dev/null +++ b/Tools/blend/BlendKit/BlendKit.steam @@ -0,0 +1,42 @@ + + + + + Name + BlendKit + Targets + + + Name + BlendKit + + + Configurations + + + Name + Debug + Flags + -DDEBUG -DPLATFORM_DOM -g + + + Name + Release + Flags + -DPLATFORM_DOM -O + + + Name + Debug-Rhino + Flags + -DDEBUG -g + + + Name + Release-Rhino + Flags + -O + + + + diff --git a/Tools/blend/BlendKit/Info.plist b/Tools/blend/BlendKit/Info.plist new file mode 100644 index 000000000..898e2e6c0 --- /dev/null +++ b/Tools/blend/BlendKit/Info.plist @@ -0,0 +1,14 @@ + + + + + CPBundleIdentifier + com.280n.BlendKit + CPBundleInfoDictionaryVersion + 6.0 + CPBundleName + BlendKit + CPBundlePackageType + FMWK + + diff --git a/Tools/blend/BlendKit/build.xml b/Tools/blend/BlendKit/build.xml new file mode 100644 index 000000000..67c5ff641 --- /dev/null +++ b/Tools/blend/BlendKit/build.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/blend/Tool/blend b/Tools/blend/Tool/blend new file mode 100755 index 000000000..7d3ae9cac --- /dev/null +++ b/Tools/blend/Tool/blend @@ -0,0 +1,57 @@ +#!/bin/sh +# +# blend +# blend +# +# 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 +# + +# if OBJJ_HOME isn't set, try to determine it +if [ -z $OBJJ_HOME ]; then + # get path of the executable + SELF_PATH=$(cd -P -- "$(dirname -- "$0")" && pwd -P) && SELF_PATH=$SELF_PATH/$(basename -- "$0") + + # resolve symlinks + if [ -h $SELF_PATH ]; then + SELF_PATH=`readlink $SELF_PATH` + fi + + # get second ancestor directory + SELF_DIR=`dirname $SELF_PATH` + export OBJJ_HOME=`dirname $SELF_DIR` + + # check to ensure it exists, print message + if [ -d $OBJJ_HOME ]; then + echo "OBJJ_HOME not set, defaulting to $OBJJ_HOME" 1>&2 + else + echo "OBJJ_HOME not set, default at $OBJJ_HOME doesn't exist, exiting" 1>&2 + exit 2 + fi +fi + +OBJJ_LIB="$OBJJ_HOME/lib" + +BLEND="$OBJJ_LIB/blend/main.j" + +# convert paths for Cygwin +if [[ `uname` == CYGWIN* ]]; then + OBJJ_HOME=`cygpath -w "$OBJJ_HOME"` + BAKE=`cygpath -w "$BLEND"` +fi + +objj $BLEND $@ diff --git a/Tools/blend/Tool/blend.steam b/Tools/blend/Tool/blend.steam new file mode 100644 index 000000000..b4287d226 --- /dev/null +++ b/Tools/blend/Tool/blend.steam @@ -0,0 +1,46 @@ + + + + + Name + blend + Targets + + + Name + blend + Excluded + + BlendKit + + + + Configurations + + + Name + Debug + Flags + -DDEBUG -DPLATFORM_DOM -g + + + Name + Release + Flags + -DPLATFORM_DOM -O + + + Name + Debug-Rhino + Flags + -DDEBUG -g + + + Name + Release-Rhino + Flags + -O + + + + diff --git a/Tools/blend/Tool/build.xml b/Tools/blend/Tool/build.xml new file mode 100644 index 000000000..a3773f38b --- /dev/null +++ b/Tools/blend/Tool/build.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/blend/Tool/main.j b/Tools/blend/Tool/main.j new file mode 100644 index 000000000..e59d6eb7a --- /dev/null +++ b/Tools/blend/Tool/main.j @@ -0,0 +1,301 @@ + +@import +@import +@import +@import +@import + +importClass(java.io.File); +importClass(java.io.FileOutputStream); +importClass(java.io.BufferedWriter); +importClass(java.io.OutputStreamWriter); + + +function main() +{ + var index = 0, + count = arguments.length, + + outputFilePath = "", + descriptorFiles = [], + resourcesPath = nil, + cibFiles = []; + + for (; index < count; ++index) + { + var argument = String(arguments[index]); + + switch (argument) + { + case "-c": + case "--cib": cibFiles.push(String(arguments[++index])); + break; + + case "-d": + case "-descriptor": descriptorFiles.push(String(arguments[++index])); + break; + + case "-o": outputFilePath = String(arguments[++index]); + break; + + case "-R": resourcesPath = String(arguments[++index]); + break; + + default: jExtensionIndex = argument.indexOf(".j"); + + if ((jExtensionIndex > 0) && (jExtensionIndex === argument.length - ".j".length)) + descriptorFiles.push(argument); + else + cibFiles.push(argument); + } + } + + if (descriptorFiles.length === 0) + return buildBlendFromCibFiles(cibFiles); + + objj_import(descriptorFiles, YES, function() + { + var themeDescriptorClasses = BKThemeDescriptorClasses(), + count = [themeDescriptorClasses count]; + + while (count--) + { + var theClass = themeDescriptorClasses[count], + themeTemplate = [[AKThemeTemplate alloc] init]; + + [themeTemplate setValue:[theClass themeName] forKey:@"name"]; + + var objectTemplates = BKThemeObjectTemplatesForClass(theClass); + data = cibDataFromTopLevelObjects(objectTemplates.concat([themeTemplate])), + temporaryCibFile = File.createTempFile("temp", ".cib"), + temporaryCibFilePath = temporaryCibFile.getAbsolutePath(), + writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(temporaryCibFilePath), "UTF-8")); + + writer.write([data string]); + writer.close(); + + cibFiles.push(temporaryCibFilePath); + } + + buildBlendFromCibFiles(cibFiles, outputFilePath, resourcesPath); + }); +} + +function cibDataFromTopLevelObjects(objects) +{ + var data = [CPData data], + archiver = [[CPKeyedArchiver alloc] initForWritingWithMutableData:data], + objectData = [[_CPCibObjectData alloc] init]; + + objectData._fileOwner = [_CPCibCustomObject new]; + objectData._fileOwner._className = @"CPObject"; + + var index = 0, + count = objects.length; + + for (; index < count; ++index) + { + objectData._objectsValues[index] = objectData._fileOwner; + objectData._objectsKeys[index] = objects[index]; + } + + [archiver encodeObject:objectData forKey:@"CPCibObjectDataKey"]; + + [archiver finishEncoding]; + + return data; +} + +function getDirectory(aPath) +{ + return (aPath).substr(0, (aPath).lastIndexOf('/') + 1) +} + +function buildBlendFromCibFiles(cibFiles, outputFilePath, resourcesPath) +{ + var resourcesFile = nil, + resourcesBundle = new objj_bundle(); + + if (resourcesPath) + { + resourcesFile = new File(resourcesPath); + resourcesBundle.path = getDirectory(resourcesFile.getCanonicalPath()) + "/Info.plist"; + } + + var count = cibFiles.length, + replacedFiles = [], + staticContent = @""; + + while (count--) + { + var theme = themeFromCibFile(new File(cibFiles[count]), resourcesBundle), + + // Archive our theme. + filePath = [theme name] + ".keyedtheme", + fileContents = [[CPKeyedArchiver archivedDataWithRootObject:theme] string]; + + replacedFiles.push(filePath); + + staticContent += MARKER_PATH + ';' + filePath.length + ';' + filePath + MARKER_TEXT + ';' + fileContents.length + ';' + fileContents; + } + + staticContent = "@STATIC;1.0;" + staticContent; + + var infoDictionary = [CPDictionary dictionary]; + staticContentName = "Aristo";//getFileNameWithoutExtension(project.activeTarget().name()); + + [infoDictionary setObject:@"Yikes." forKey:@"CPBundleName"]; + [infoDictionary setObject:@"Yikes." forKey:@"CPBundleIdentifier"]; + [infoDictionary setObject:replacedFiles forKey:@"CPBundleReplacedFiles"]; + [infoDictionary setObject:staticContentName forKey:@"CPBundleExecutable"]; + + var outputFile = new File(outputFilePath).getCanonicalFile(); + + outputFile.mkdirs(); + + var writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFilePath + "/Info.plist"), "UTF-8")); + + writer.write(CPPropertyListCreate280NorthData(infoDictionary).string); + + writer.close(); + + writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFilePath + '/' + staticContentName), "UTF-8")); + + writer.write(staticContent); + + writer.close(); + + if (resourcesPath) + rsync(new File(resourcesPath), new File(outputFilePath)); +} + +function themeFromCibFile(aFile, resourcesBundle) +{ + var cib = [[CPCib alloc] initWithCibNamed:aFile.getCanonicalPath() bundle:resourcesBundle],//WithContentsOfURL:aFile.getCanonicalPath()], + topLevelObjects = []; + + [cib instantiateCibWithExternalNameTable:[CPDictionary dictionaryWithObject:topLevelObjects forKey:CPCibTopLevelObjects]]; + + var count = topLevelObjects.length, + theme = nil, + templates = []; + + while (count--) + { + var object = topLevelObjects[count]; + + templates = templates.concat([object blendThemeObjectTemplates]); + + if ([object isKindOfClass:[AKThemeTemplate class]]) + theme = [[CPTheme alloc] initWithName:[object valueForKey:@"name"]]; + } + + [templates makeObjectsPerformSelector:@selector(blendAddThemedObjectAttributesToTheme:) withObject:theme]; + + return theme; +} + +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 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; +} + +@implementation CPObject (BlendAdditions) + +- (CPArray)blendThemeObjectTemplates +{ + var theClass = [self class]; + + if ([theClass isKindOfClass:[AKThemeObjectTemplate class]]) + return [self]; + + if ([theClass isKindOfClass:[CPView class]]) + { + var templates = [], + subviews = [self subviews], + count = [subviews count]; + + while (count--) + templates = templates.concat([subviews[count] blendThemeObjectTemplates]); + + return templates; + } + + return []; +} + +@end + +@implementation AKThemeObjectTemplate (BlendAdditions) + +- (void)blendAddThemedObjectAttributesToTheme:(CPTheme)aTheme +{ + var themedObject = [self valueForKey:@"themedObject"]; + + if (!themedObject) + { + var subviews = [self subviews]; + + if ([subviews count] > 0) + themedObject = subviews[0]; + } + + if (themedObject) + { + print(" Recording theme for " + [themedObject className] + "."); + + [aTheme takeThemeFromObject:themedObject]; + } +} + +@end + +main.apply(main, args); diff --git a/Tools/blend/build.xml b/Tools/blend/build.xml new file mode 100644 index 000000000..903d5a94a --- /dev/null +++ b/Tools/blend/build.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/steam/Project.js b/Tools/steam/Project.js index 718d69835..3e48b401c 100644 --- a/Tools/steam/Project.js +++ b/Tools/steam/Project.js @@ -224,136 +224,12 @@ Project.prototype.activeFlags = function() return this.activeTarget().flags().concat(this.activeConfiguration().flags()); } -Project.prototype.buildTheme = function() -{ - var project = this/*, - frameworks = NULL; - - // FIXME: OBJJ_INCLUDE_PATHS ENV VAR? - if (true) - { - OBJJ_INCLUDE_PATHS = [System.getenv("STEAM_BUILD") + "/Release-Rhino/", System.getenv("STEAM_BUILD") + "/Release/"]; - frameworks = [System.getenv("STEAM_BUILD") + "/Release/Foundation", System.getenv("STEAM_BUILD") + "/Release-Rhino/AppKit"]; - } - else - { - OBJJ_INCLUDE_PATHS = [OBJJ_HOME + "/lib/Frameworks-Rhino"]; - frameworks = [OBJJ_HOME + "/lib/Frameworks-Rhino/Foundation", OBJJ_HOME + "/lib/Frameworks-Rhino/AppKit"]; - } - - // Load ALL of Foundation and AppKit, be nice to people. - loadFrameworks(frameworks, function()*/ - - // 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); - } - - var activeConfigurationName = this.activeConfiguration().name(); - - OBJJ_INCLUDE_PATHS = [System.getenv("STEAM_BUILD") + "/" + activeConfigurationName + "-Rhino/", System.getenv("STEAM_BUILD") + "/" + activeConfigurationName + "/"]; - - // Load ALL of Foundation and AppKit, be nice to people. - loadFrameworks([System.getenv("STEAM_BUILD") + "/" + activeConfigurationName + "/Foundation", System.getenv("STEAM_BUILD") + "/" + activeConfigurationName + "-Rhino/AppKit"], function() - { - // Get .j files - var jFiles = getFiles(project._root, "j", project.activeTarget().exclusions().concat([new File("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; diff --git a/Tools/steam/Templates/ThemeDescriptor/Info.plist b/Tools/steam/Templates/ThemeDescriptor/Info.plist new file mode 100644 index 000000000..f09701c61 --- /dev/null +++ b/Tools/steam/Templates/ThemeDescriptor/Info.plist @@ -0,0 +1,12 @@ + + + + + CPApplicationDelegateClass + BKShowcaseController + CPBundleName + __Product__ + CPPrincipalClass + CPApplication + + diff --git a/Tools/steam/Templates/ThemeDescriptor/ThemeDescriptors.j b/Tools/steam/Templates/ThemeDescriptor/ThemeDescriptors.j new file mode 100644 index 000000000..aab4c6581 --- /dev/null +++ b/Tools/steam/Templates/ThemeDescriptor/ThemeDescriptors.j @@ -0,0 +1,33 @@ +/* + * ThemeDescriptors.j + * __Product__ + * + * Created by __Me__ on __Date__. + * Copyright 2008 __MyCompanyName__. All rights reserved. + */ + +@import + + +@implementation __Product__ThemeDescriptor : CPObject +{ +} + ++ (CPString)themeName +{ + return @"__Product__"; +} + ++ (CPTextField)themedTextField +{ + var textField = [[CPTextField alloc] initWithFrame:CGRectMake(0.0, 0.0, 200.0, 20.0)]; + + [textField setValue:[CPColor blueColor] forThemedAttributeName:@"bezel-color"]; + [textField setValue:[CPColor redColor] forThemedAttributeName:@"text-color"]; + + [textField setStringValue:@"Yikes!"]; + + return textField; +} + +@end diff --git a/Tools/steam/Templates/ThemeDescriptor/index-debug.html b/Tools/steam/Templates/ThemeDescriptor/index-debug.html new file mode 100644 index 000000000..d941b006a --- /dev/null +++ b/Tools/steam/Templates/ThemeDescriptor/index-debug.html @@ -0,0 +1,36 @@ + + + + + + + Hello World + + + + + + + + +
+
+ +
+
+ + + diff --git a/Tools/steam/Templates/ThemeDescriptor/index.html b/Tools/steam/Templates/ThemeDescriptor/index.html new file mode 100644 index 000000000..bea6f5f36 --- /dev/null +++ b/Tools/steam/Templates/ThemeDescriptor/index.html @@ -0,0 +1,37 @@ + + + + + + + Hello World + + + + + + + + + +
+
+ +
+
+ + + + diff --git a/Tools/steam/Templates/ThemeDescriptor/main.j b/Tools/steam/Templates/ThemeDescriptor/main.j new file mode 100755 index 000000000..cb02f4859 --- /dev/null +++ b/Tools/steam/Templates/ThemeDescriptor/main.j @@ -0,0 +1,19 @@ +/* + * main.j + * __Product__ + * + * Created by __Me__ on __Date__. + * Copyright 2008 __MyCompanyName__. All rights reserved. + */ + +@import +@import +@import + +@import "ThemeDescriptors.j" + + +function main(args, namedArgs) +{ + CPApplicationMain(args, namedArgs); +}