merge from main

This commit is contained in:
daboe01 committed 2026-04-03 16:26:59 +02:00
commit fb348ed4f7
11 files changed
+923 -12

No files matched your search

+77 -9
View File
@@ -69,6 +69,7 @@ var CPButtonBarPopulateButtonBarSelector = 1 << 1;
@implementation CPButtonBar : CPView
{
CPArray _buttons;
CPArray _rightButtons;
CPMutableArray _dividers;
CPMutableArray _flexibles;
CPButtonBarStyle _style;
@@ -98,6 +99,8 @@ var CPButtonBarPopulateButtonBarSelector = 1 << 1;
id <CPButtonBarDelegate> _delegate;
unsigned _delegateSelectors;
BOOL _hasResizeControl;
BOOL _resizeControlIsLeftAligned;
}
#pragma mark -
@@ -288,6 +291,7 @@ var CPButtonBarPopulateButtonBarSelector = 1 << 1;
if (self)
{
_buttons = @[];
_rightButtons = @[];
_dividers = @[];
_flexibles = @[];
_flexibleSpacesCount = 0;
@@ -302,7 +306,7 @@ var CPButtonBarPopulateButtonBarSelector = 1 << 1;
[self setButtonsAreBordered: [self currentValueForThemeAttribute:@"bordered-buttons"]];
[self setDrawsSeparator: [self currentValueForThemeAttribute:@"draws-separator"]];
[self setIsTransparent: [self currentValueForThemeAttribute:@"is-transparent"]];
[self setAutomaticResizeControl:[self currentValueForThemeAttribute:@"auto-resize-control"]]
[self setAutomaticResizeControl:[self currentValueForThemeAttribute:@"auto-resize-control"]];
// Adapt the height of the button bar if needed
var minSize = [self currentValueForThemeAttribute:@"min-size"],
@@ -323,7 +327,7 @@ var CPButtonBarPopulateButtonBarSelector = 1 << 1;
// This is needed when compiling themes
[self _loadThemeValues];
[self setNeedsLayout:YES];
[self setNeedsLayout];
}
return self;
@@ -544,6 +548,30 @@ var CPButtonBarPopulateButtonBarSelector = 1 << 1;
return [CPArray arrayWithArray:_buttons];
}
- (void)setRightButtons:(CPArray)buttons
{
for (var i = [_rightButtons count] - 1; i >= 0; i--)
{
[_rightButtons[i] removeFromSuperview];
[_rightButtons[i] removeObserver:self forKeyPath:@"hidden"];
}
_rightButtons = [CPArray arrayWithArray:buttons];
for (var i = [_rightButtons count] - 1; i >= 0; i--)
{
[_rightButtons[i] addObserver:self forKeyPath:@"hidden" options:CPKeyValueObservingOptionNew | CPKeyValueObservingOptionOld context:nil];
[_rightButtons[i] setBordered:YES];
}
[self setNeedsLayout];
}
- (CPArray)rightButtons
{
return [CPArray arrayWithArray:_rightButtons];
}
- (void)setButtonsAreBordered:(BOOL)shouldBeBordered
{
if (_buttonsAreBordered === shouldBeBordered)
@@ -881,6 +909,7 @@ var CPButtonBarPopulateButtonBarSelector = 1 << 1;
flexibleSpaceWidth = (remainingSpace > 0) ? remainingSpace / _flexibleSpacesCount : 0;
}
// --- 1. LINKE/NORMALE BUTTONS PLATZIEREN ---
for (var i = 0, count = _buttons.length, button, width, extraSpace, buttonHeight; i < count; i++)
{
button = _buttons[i];
@@ -917,10 +946,41 @@ var CPButtonBarPopulateButtonBarSelector = 1 << 1;
}
}
// --- 2. RECHTE BUTTONS (aus Upstream) PLATZIEREN ---
var rightButtonsNotHidden = [CPArray arrayWithArray:_rightButtons],
rightCount = [rightButtonsNotHidden count];
while (rightCount--)
{
var button = rightButtonsNotHidden[rightCount];
if ([button isHidden])
{
[button removeFromSuperview];
[rightButtonsNotHidden removeObject:button];
}
}
var currentRightOffset = _hasRightResizeControl ? CGRectGetMaxX(bounds) - rightResizeWidth + 1 : CGRectGetMaxX(bounds) + 1;
for (var i = 0, count = [rightButtonsNotHidden count]; i < count; i++)
{
var rightButton = rightButtonsNotHidden[i],
btnWidth = CGRectGetWidth([rightButton frame]),
btnHeight = CGRectGetHeight([rightButton frame]);
[rightButton setFrame:CGRectMake(currentRightOffset - btnWidth, _buttonVerticalOffset + (height - btnHeight)/2, btnWidth, btnHeight)];
currentRightOffset -= btnWidth - 1;
if (![rightButton superview])
[self addSubview:rightButton];
}
// --- 3. RESIZE CONTROLS ---
if (_hasLeftResizeControl)
{
var resizeControlView = [self layoutEphemeralSubviewNamed:@"left-resize-control-view"
positioned:CPWindowAbove
positioned:CPWindowAbove
relativeToEphemeralSubviewNamed:nil];
[resizeControlView setAutoresizingMask:CPViewMaxXMargin];
@@ -993,7 +1053,10 @@ var CPButtonBarHasLeftResizeControlKey = @"CPButtonBarHasLeftResizeControl
CPButtonBarDividersKey = @"CPButtonBarDividersKey",
CPButtonBarFlexiblesKey = @"CPButtonBarFlexiblesKey",
CPButtonBarFlexibleSpacesCountKey = @"CPButtonBarFlexibleSpacesCountKey",
CPButtonBarDelegateKey = @"CPButtonBarDelegateKey";
CPButtonBarDelegateKey = @"CPButtonBarDelegateKey",
CPButtonBarHasResizeControlKey = @"CPButtonBarHasResizeControlKey",
CPButtonBarResizeControlIsLeftAlignedKey = @"CPButtonBarResizeControlIsLeftAlignedKey",
CPButtonBarRightButtonsKey = @"CPButtonBarRightButtonsKey";
@implementation CPButtonBar (CPCoding)
@@ -1011,27 +1074,32 @@ var CPButtonBarHasLeftResizeControlKey = @"CPButtonBarHasLeftResizeControl
[aCoder encodeObject:_dividers forKey:CPButtonBarDividersKey];
[aCoder encodeObject:_flexibles forKey:CPButtonBarFlexiblesKey];
[aCoder encodeInt: _flexibleSpacesCount forKey:CPButtonBarFlexibleSpacesCountKey];
[aCoder encodeConditionalObject:_delegate forKey:CPButtonBarDelegateKey];
[aCoder encodeBool:_hasResizeControl forKey:CPButtonBarHasResizeControlKey];
[aCoder encodeBool:_resizeControlIsLeftAligned forKey:CPButtonBarResizeControlIsLeftAlignedKey];
[aCoder encodeObject:_rightButtons forKey:CPButtonBarRightButtonsKey];
}
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super initWithCoder:aCoder])
{
_hasLeftResizeControl = [aCoder decodeBoolForKey:CPButtonBarHasLeftResizeControlKey];
_hasRightResizeControl = [aCoder decodeBoolForKey:CPButtonBarHasRightResizeControlKey];
_automaticResizeControl = [aCoder decodeBoolForKey:CPButtonBarAutomaticResizeControlKey];
_hasLeftResizeControl = [aCoder decodeBoolForKey:CPButtonBarHasLeftResizeControlKey];
_hasRightResizeControl = [aCoder decodeBoolForKey:CPButtonBarHasRightResizeControlKey];
_automaticResizeControl = [aCoder decodeBoolForKey:CPButtonBarAutomaticResizeControlKey];
_hasResizeControl = [aCoder decodeBoolForKey:CPButtonBarHasResizeControlKey];
_resizeControlIsLeftAligned = [aCoder decodeBoolForKey:CPButtonBarResizeControlIsLeftAlignedKey];
[self setButtonsAreBordered:!![aCoder decodeBoolForKey:CPButtonBarButtonsAreBorderedKey]];
[self setDrawsSeparator: !![aCoder decodeBoolForKey:CPButtonBarDrawsSeparatorKey]];
[self setIsTransparent: !![aCoder decodeBoolForKey:CPButtonBarIsTransparentKey]];
_buttons = [aCoder decodeObjectForKey:CPButtonBarButtonsKey] || @[];
_rightButtons = [aCoder decodeObjectForKey:CPButtonBarRightButtonsKey] || [];
_dividers = [aCoder decodeObjectForKey:CPButtonBarDividersKey] || @[];
_flexibles = [aCoder decodeObjectForKey:CPButtonBarFlexiblesKey] || @[];
_flexibleSpacesCount = [aCoder decodeIntForKey:CPButtonBarFlexibleSpacesCountKey];
[self setNeedsRelayout:YES];
}
+6 -1
View File
@@ -269,6 +269,8 @@
_currentAnimation = nil;
_sendAction = NO;
var rows = [];
if (predicate != nil)
{
if ((_nestingMode == CPRuleEditorNestingModeSimple || _nestingMode == CPRuleEditorNestingModeCompound)
@@ -276,10 +278,13 @@
predicate = [[CPCompoundPredicate alloc] initWithType:[self _compoundPredicateTypeForRootRows] subpredicates:[CPArray arrayWithObject:predicate]];
var row = [self _rowObjectFromPredicate:predicate];
if (row != nil)
[_boundArrayOwner setValue:[CPArray arrayWithObject:row] forKey:_boundArrayKeyPath];
[rows addObject:row];
}
[_boundArrayOwner setValue:rows forKey:_boundArrayKeyPath];
[self setAnimation:animation];
}
+192 -2
View File
@@ -763,9 +763,12 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew | CPKeyValueObservingOpti
if (!anObserver)
return;
var forwarder = nil;
var forwarder = nil,
collectionOperatorMatch = aPath.match(/^(.*)\.(@\w+)(?:\.(.*))?$/);
if (aPath.indexOf('.') !== CPNotFound && aPath.charAt(0) !== '@')
if (collectionOperatorMatch)
forwarder = [[_CPKVOCollectionOperatorObserver alloc] initWithTarget:_targetObject observer:anObserver keyPath:aPath options:options context:aContext];
else if (aPath.indexOf('.') !== CPNotFound && aPath.charAt(0) !== '@')
forwarder = [[_CPKVOForwardingObserver alloc] initWithKeyPath:aPath object:_targetObject observer:anObserver options:options context:aContext];
else
[self _replaceModifiersForKey:aPath];
@@ -1265,6 +1268,193 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew | CPKeyValueObservingOpti
@end
@implementation _CPKVOCollectionOperatorObserver : CPObject
{
id _target;
id _originalObserver;
CPString _fullKeyPath;
unsigned _options;
id _context;
CPString _collectionKeyPath;
CPString _operator;
CPString _valueKeyPath;
CPArray _observedItems;
id _cachedValue;
}
- (id)initWithTarget:(id)aTarget observer:(id)anObserver keyPath:(CPString)aKeyPath options:(unsigned)options context:(id)aContext
{
self = [super init];
if (self)
{
_target = aTarget;
_originalObserver = anObserver;
_fullKeyPath = aKeyPath;
_options = options;
_context = aContext;
_observedItems = [CPArray array];
var match = aKeyPath.match(/^(.*)\.(@\w+)(?:\.(.*))?$/);
if (match)
{
_collectionKeyPath = match[1];
_operator = match[2];
_valueKeyPath = match[3];
}
_cachedValue = [_target valueForKeyPath:_fullKeyPath];
[_target addObserver:self forKeyPath:_collectionKeyPath options:_options context:nil];
[self _setupItemObservers];
}
return self;
}
- (void)_setupItemObservers
{
var collection = [_target valueForKeyPath:_collectionKeyPath];
if (collection && [collection respondsToSelector:@selector(objectEnumerator)])
{
var enumerator = [collection objectEnumerator],
item;
while ((item = [enumerator nextObject]) !== nil)
{
if (_valueKeyPath && [item respondsToSelector:@selector(addObserver:forKeyPath:options:context:)])
[item addObserver:self forKeyPath:_valueKeyPath options:_options context:nil];
[_observedItems addObject:item];
}
}
}
- (void)_tearDownItemObservers
{
if (_valueKeyPath)
{
var count = [_observedItems count];
while (count--)
{
var item = [_observedItems objectAtIndex:count];
if ([item respondsToSelector:@selector(removeObserver:forKeyPath:context:)])
[item removeObserver:self forKeyPath:_valueKeyPath context:nil];
}
}
[_observedItems removeAllObjects];
}
- (void)observeValueForKeyPath:(CPString)keyPath ofObject:(id)object change:(CPDictionary)change context:(id)context
{
var isPrior = [[change objectForKey:CPKeyValueChangeNotificationIsPriorKey] boolValue];
if (object === _target && [keyPath isEqualToString:_collectionKeyPath])
{
// Only tear down/rebuild observers when the actual change happens, not during the "Prior" notification
if (!isPrior)
{
var kind = [change objectForKey:CPKeyValueChangeKindKey];
if (kind === CPKeyValueChangeSetting)
{
[self _tearDownItemObservers];
[self _setupItemObservers];
}
else if (kind === CPKeyValueChangeInsertion || kind === CPKeyValueChangeReplacement)
{
if (kind === CPKeyValueChangeReplacement)
{
var oldItems = [change objectForKey:CPKeyValueChangeOldKey];
if (oldItems)
{
for (var i = 0, len = oldItems.length; i < len; i++)
{
var item = oldItems[i];
if (_valueKeyPath && [item respondsToSelector:@selector(removeObserver:forKeyPath:context:)])
[item removeObserver:self forKeyPath:_valueKeyPath context:nil];
[_observedItems removeObject:item];
}
}
}
var newItems = [change objectForKey:CPKeyValueChangeNewKey];
if (newItems)
{
for (var i = 0, len = newItems.length; i < len; i++)
{
var item = newItems[i];
if (_valueKeyPath && [item respondsToSelector:@selector(addObserver:forKeyPath:options:context:)])
[item addObserver:self forKeyPath:_valueKeyPath options:_options context:nil];
[_observedItems addObject:item];
}
}
}
else if (kind === CPKeyValueChangeRemoval)
{
var oldItems = [change objectForKey:CPKeyValueChangeOldKey];
if (oldItems)
{
for (var i = 0, len = oldItems.length; i < len; i++)
{
var item = oldItems[i];
if (_valueKeyPath && [item respondsToSelector:@selector(removeObserver:forKeyPath:context:)])
[item removeObserver:self forKeyPath:_valueKeyPath context:nil];
[_observedItems removeObject:item];
}
}
}
}
[self _notifyOriginalObserverIsPrior:isPrior];
}
else if (_valueKeyPath && [keyPath isEqualToString:_valueKeyPath] && [_observedItems containsObject:object])
{
[self _notifyOriginalObserverIsPrior:isPrior];
}
}
- (void)_notifyOriginalObserverIsPrior:(BOOL)isPrior
{
var change = [CPMutableDictionary dictionaryWithObject:CPKeyValueChangeSetting forKey:CPKeyValueChangeKindKey];
if (isPrior)
[change setObject:YES forKey:CPKeyValueChangeNotificationIsPriorKey];
if (_options & CPKeyValueObservingOptionOld)
[change setObject:(_cachedValue !== nil ? _cachedValue : [CPNull null]) forKey:CPKeyValueChangeOldKey];
if (!isPrior)
{
var newValue = [_target valueForKeyPath:_fullKeyPath];
if (_options & CPKeyValueObservingOptionNew)
[change setObject:(newValue !== nil ? newValue : [CPNull null]) forKey:CPKeyValueChangeNewKey];
[_originalObserver observeValueForKeyPath:_fullKeyPath ofObject:_target change:change context:_context];
// Update the cache for the next notification
_cachedValue = newValue;
}
else
{
[_originalObserver observeValueForKeyPath:_fullKeyPath ofObject:_target change:change context:_context];
}
}
- (void)finalize
{
[_target removeObserver:self forKeyPath:_collectionKeyPath];
[self _tearDownItemObservers];
}
@end
@implementation _CPKVOForwardingObserver : CPObject
{
id _object;
+63
View File
@@ -3,6 +3,8 @@
@class CarTester
@class ToManyTester
@class AccountTester
@class TransactionTester
@implementation CPKVOTest : OJTestCase
{
@@ -436,6 +438,35 @@
[self assertTrue:_sawObservation message:@"Never recieved an observation"];
}
- (void)testCollectionOperatorKeyPath
{
var account = [[AccountTester alloc] init],
t1 = [[TransactionTester alloc] initWithAmount:10.0],
t2 = [[TransactionTester alloc] initWithAmount:20.0];
[account setTransactions:[t1, t2]];
// 1. Test updating a child property triggers an aggregate update
[account addObserver:self forKeyPath:@"transactions.@sum.amount" options:CPKeyValueObservingOptionNew | CPKeyValueObservingOptionOld context:@"testCollectionOperatorKeyPath_ItemChange"];
_sawObservation = NO;
[t1 setAmount:15.0]; // KVC sum goes from 30.0 -> 35.0
[self assertTrue:_sawObservation message:@"Never received an observation when child item's property changed"];
[account removeObserver:self forKeyPath:@"transactions.@sum.amount"];
// 2. Test replacing the whole array triggers an aggregate update
[account addObserver:self forKeyPath:@"transactions.@sum.amount" options:CPKeyValueObservingOptionNew | CPKeyValueObservingOptionOld context:@"testCollectionOperatorKeyPath_ArrayReplace"];
var t3 = [[TransactionTester alloc] initWithAmount:5.0];
_sawObservation = NO;
[account setTransactions:[t1, t2, t3]]; // KVC sum goes from 35.0 -> 40.0
[self assertTrue:_sawObservation message:@"Never received an observation when collection was replaced"];
[account removeObserver:self forKeyPath:@"transactions.@sum.amount"];
}
- (void)testPerformance
{
bob = [PersonTester new];
@@ -777,6 +808,16 @@
testNestedNotificationsBobCount += 1;
break;
case "testCollectionOperatorKeyPath_ItemChange":
[self assert:newValue equals:35.0];
[self assert:oldValue equals:30.0];
break;
case "testCollectionOperatorKeyPath_ArrayReplace":
[self assert:newValue equals:40.0];
[self assert:oldValue equals:35.0];
break;
default:
[self assertFalse:YES message:@"unhandled observation, must be an error"];
return;
@@ -955,3 +996,25 @@
}
@end
@implementation TransactionTester : CPObject
{
float amount @accessors;
}
- (id)initWithAmount:(float)anAmount
{
self = [super init];
if (self) {
amount = anAmount;
}
return self;
}
@end
@implementation AccountTester : CPObject
{
CPArray transactions @accessors;
}
@end
@@ -0,0 +1,104 @@
/*
* AppController.j
* CPButtonBar Right Buttons Manual Test
*/
@import <Foundation/CPObject.j>
@import <Foundation/CPKeyedArchiver.j>
@import <Foundation/CPKeyedUnarchiver.j>
@import <AppKit/AppKit.j>
@implementation AppController : CPObject
{
CPButtonBar buttonBar;
}
- (void)applicationDidFinishLaunching:(CPNotification)aNotification
{
var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask],
contentView = [theWindow contentView];
var bounds = [contentView bounds];
// 1. Create the ButtonBar
buttonBar = [[CPButtonBar alloc] initWithFrame:CGRectMake(0, CGRectGetHeight(bounds) - 28, CGRectGetWidth(bounds), 28)];
[buttonBar setAutoresizingMask:CPViewWidthSizable | CPViewMinYMargin];
// Add resize control to ensure bounds calculations are correct
[buttonBar setHasResizeControl:YES];
// 2. Setup standard Left Buttons
var plusButton = [CPButtonBar plusButton],
minusButton = [CPButtonBar minusButton];
[buttonBar setButtons:[plusButton, minusButton]];
// 3. Setup the new Right Buttons (PR #745)
var actionButton = [CPButtonBar actionPopupButton],
customRightBtn = [[CPButton alloc] initWithFrame:CGRectMake(0, 0, 70, 24)];
[customRightBtn setTitle:@"Settings"];
[buttonBar setRightButtons:[customRightBtn, actionButton]];
[contentView addSubview:buttonBar];
// --- Testing Controls ---
// Button to test resizing alignment layout
var toggleAlignmentBtn = [CPButton buttonWithTitle:@"Toggle Resize Control Alignment"];
[toggleAlignmentBtn setFrameOrigin:CGPointMake(20, 20)];
[toggleAlignmentBtn sizeToFit];
[toggleAlignmentBtn setTarget:self];
[toggleAlignmentBtn setAction:@selector(toggleResizeAlignment:)];
[contentView addSubview:toggleAlignmentBtn];
// Button to test the KVO "hidden" observer on rightButtons
var toggleVisibilityBtn = [CPButton buttonWithTitle:@"Toggle Right Button Visibility"];
[toggleVisibilityBtn setFrameOrigin:CGPointMake(20, 60)];
[toggleVisibilityBtn sizeToFit];
[toggleVisibilityBtn setTarget:self];
[toggleVisibilityBtn setAction:@selector(toggleRightVisibility:)];
[contentView addSubview:toggleVisibilityBtn];
// Button to test CPCoding archiving/unarchiving of rightButtons
var testArchivingBtn = [CPButton buttonWithTitle:@"Test Archiving (CPCoding)"];
[testArchivingBtn setFrameOrigin:CGPointMake(20, 100)];
[testArchivingBtn sizeToFit];
[testArchivingBtn setTarget:self];
[testArchivingBtn setAction:@selector(testArchiving:)];
[contentView addSubview:testArchivingBtn];
[theWindow orderFront:self];
}
- (void)toggleResizeAlignment:(id)sender
{
// Flipping the resize control to the left shouldn't break the right-aligned buttons
[buttonBar setResizeControlIsLeftAligned:![buttonBar resizeControlIsLeftAligned]];
}
- (void)toggleRightVisibility:(id)sender
{
var rightBtns = [buttonBar rightButtons];
if ([rightBtns count] > 0)
{
var btn = rightBtns[0];
[btn setHidden:![btn isHidden]];
}
}
- (void)testArchiving:(id)sender
{
// Test the new CPButtonBarRightButtonsKey in CPCoding
var data = [CPKeyedArchiver archivedDataWithRootObject:buttonBar];
var unarchivedBar = [CPKeyedUnarchiver unarchiveObjectWithData:data];
var bounds = [[buttonBar superview] bounds];
// Place the cloned bar directly above the original one
[unarchivedBar setFrame:CGRectMake(0, CGRectGetHeight(bounds) - 56, CGRectGetWidth(bounds), 28)];
[[buttonBar superview] addSubview:unarchivedBar];
}
@end
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CPApplicationDelegateClass</key>
<string>AppController</string>
<key>CPBundleName</key>
<string>CPButtonBarTest</string>
<key>CPPrincipalClass</key>
<string>CPApplication</string>
</dict>
</plist>
+81
View File
@@ -0,0 +1,81 @@
/*
* Jakefile
* CPBrowserTest
*
* Created by Ross Boucher on March 23, 2010.
* Copyright 2010, Your Company All rights reserved.
*/
var ENV = require("system").env,
FILE = require("file"),
JAKE = require("jake"),
task = JAKE.task,
FileList = JAKE.FileList,
app = require("cappuccino/jake").app,
configuration = ENV["CONFIG"] || ENV["CONFIGURATION"] || ENV["c"] || "Debug",
OS = require("os");
app ("CPBrowserTest", function(task)
{
task.setBuildIntermediatesPath(FILE.join("Build", "CPBrowserTest.build", configuration));
task.setBuildPath(FILE.join("Build", configuration));
task.setProductName("CPBrowserTest");
task.setIdentifier("com.yourcompany.CPBrowserTest");
task.setVersion("1.0");
task.setAuthor("Your Company");
task.setEmail("feedback @nospam@ yourcompany.com");
task.setSummary("CPBrowserTest");
task.setSources((new FileList("**/*.j")).exclude(FILE.join("Build", "**")));
task.setResources(new FileList("Resources/*"));
task.setIndexFilePath("index.html");
task.setInfoPlistPath("Info.plist");
if (configuration === "Debug")
task.setCompilerFlags("-DDEBUG -g");
else
task.setCompilerFlags("-O");
});
function printResults(configuration)
{
print("----------------------------");
print(configuration+" app built at path: "+FILE.join("Build", configuration, "CPBrowserTest"));
print("----------------------------");
}
task ("default", ["CPBrowserTest"], function()
{
printResults(configuration);
});
task ("build", ["default"]);
task ("debug", function()
{
ENV["CONFIGURATION"] = "Debug";
JAKE.subjake(["."], "build", ENV);
});
task ("release", function()
{
ENV["CONFIGURATION"] = "Release";
JAKE.subjake(["."], "build", ENV);
});
task ("run", ["debug"], function()
{
OS.system(["open", FILE.join("Build", "Debug", "CPBrowserTest", "index.html")]);
});
task ("run-release", ["release"], function()
{
OS.system(["open", FILE.join("Build", "Release", "CPBrowserTest", "index.html")]);
});
task ("deploy", ["release"], function()
{
FILE.mkdirs(FILE.join("Build", "Deployment", "CPBrowserTest"));
OS.system(["press", "-f", FILE.join("Build", "Release", "CPBrowserTest"), FILE.join("Build", "Deployment", "CPBrowserTest")]);
printResults("Deployment")
});
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -0,0 +1,204 @@
<!DOCTYPE html>
<html lang="en">
<!--
index-debug.html
__project.name__
Created by __user.name__ on __project.date__.
Copyright __project.year__, __organization.name__ All rights reserved.
-->
<head>
<meta charset="utf-8">
<!--[if lte IE 8]>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7, chrome=1">
<![endif]-->
<!--[if gte IE 9]>
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
<![endif]-->
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="apple-touch-icon" href="Resources/icon.png">
<link rel="apple-touch-startup-image" href="Resources/default.png">
<title>__project.name__</title>
<!-- Custom javascript goes here -->
<!-- End custom javascript -->
<script type="text/javascript">
OBJJ_MAIN_FILE = "main.j";
OBJJ_INCLUDE_PATHS = ["Frameworks/Debug", "Frameworks"];
// The below will tell the compiler to generate debug symbols, type signatures and not inline objj_msgSend functions.
// This will affect only Objective-J code that is compiled when loading the application. It will not affect precompiled
// code like the Cappuccino frameworks.
//
// Debug symbols will give each Objective-J method a Javascript function name. Without a name it will be very hard to find
// the methods in the debugger.
// Type Signatures will give type information to the Objective-J runtime for instance variables and methods.
// Inline objj_msgSend will give a speed increase but decorators will not work. Check below on debug options for
// more information on decorators.
//
// Uncomment or comment on the line below to change the flags
OBJJ_COMPILER_FLAGS = ["IncludeDebugSymbols", "IncludeTypeSignatures", "SourceMap", "InlineMsgSend"];
var progressBar = null;
OBJJ_PROGRESS_CALLBACK = function(percent, appSize, path)
{
percent = percent * 100;
if (!progressBar)
progressBar = document.getElementById("progress-bar");
if (progressBar)
progressBar.style.width = Math.min(percent, 100) + "%";
}
var loadingHTML =
'<div id="loading">' +
' <div id="loading-text">Loading...</div>' +
' <div id="progress-indicator">' +
' <span id="progress-bar" style="width:0%"></span>' +
' </div>' +
'</div>';
</script>
<script type="text/javascript" src="Frameworks/Debug/Objective-J/Objective-J.js" charset="UTF-8"></script>
<script type="text/javascript">
objj_msgSend_reset();
// DEBUG OPTIONS:
// Decorators will only work when the code is compiled without the compiler option 'InlineMsgSend'. Check above.
// Uncomment to enable printing of backtraces on exceptions:
//objj_msgSend_decorate(objj_backtrace_decorator);
// Uncomment to supress exceptions that take place inside a message
//objj_msgSend_decorate(objj_supress_exceptions_decorator)
// Uncomment to enable runtime type checking:
//objj_msgSend_decorate(objj_typecheck_decorator);
// Uncomment (along with both above) to print backtraces on type check errors:
//objj_typecheck_prints_backtrace = true;
// Uncomment to disable the default logger (CPLogConsole if window.console exists, CPLogPopup otherwise):
//CPLogUnregister(CPLogDefault);
// Uncomment to enable a specific logger:
//CPLogRegister(CPLogConsole);
//CPLogRegister(CPLogPopup);
// Tag view DOM elements with a "data-cappuccino-view" attribute that contains
// the class name of the view that created them. Comment this or set to false to disable.
appkit_tag_dom_elements = true;
</script>
<style type="text/css">
html, body, h1, p {
margin: 0;
padding: 0;
}
/* We need a body wrapper because Cappuccino is unhappy if we change the body element */
#cappuccino-body {
/* Position it absolutely so it will fill the height without content */
position: absolute;
top: 0;
bottom: 0;
width: 100%;
/* Put it at the bottom of the stack so it doesn't interfere with UI */
z-index: 0;
}
#cappuccino-body .container {
display: table;
margin: 0 auto;
height: 100%;
}
#cappuccino-body .content {
display: table-cell;
height: 100%;
vertical-align: top;
}
#loading {
position: relative;
top: 35%;
}
#loading-text {
height: 1.5em;
color: #555;
font: normal bold 36px/36px Arial, sans-serif;
}
#progress-indicator {
padding: 0px;
height: 16px;
border: 5px solid #555;
border-radius: 18px;
background-color: white;
}
#progress-bar {
position: relative;
top: -1px;
left: -1px;
display: block;
height: 18px;
/* Compensate for moving the bar left 1px to overlap the indicator border */
border-right: 1px solid #555;
background-color: #555;
}
#noscript {
position: relative;
top: 35%;
padding: 1em 1.5em;
border: 5px solid #555;
border-radius: 16px;
background-color: white;
color: #555;
text-align: center;
font: bold 24px Arial, sans-serif;
}
#noscript a {
color: #98c0ff;
text-decoration: none;
}
</style>
</head>
<body>
<div id="cappuccino-body">
<div class="container">
<div class="content">
<script type="text/javascript">
document.write(loadingHTML);
</script>
</div>
</div>
<noscript style="position:absolute; top:0; left:0; width:100%; height:100%">
<div class="container">
<div class="content">
<div id="noscript">
<p style="font-size:120%; margin-bottom:.75em">JavaScript is required for this application.</p>
<p><a href="http://www.enable-javascript.com" target="_blank">Enable JavaScript</a></p>
</div>
</div>
</div>
</noscript>
</div>
</body>
</html>
+166
View File
@@ -0,0 +1,166 @@
<!DOCTYPE html>
<html lang="en">
<!--
index.html
__project.name__
Created by __user.name__ on __project.date__.
Copyright __project.year__, __organization.name__ All rights reserved.
-->
<head>
<meta charset="utf-8">
<!--[if lte IE 8]>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7, chrome=1">
<![endif]-->
<!--[if gte IE 9]>
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
<![endif]-->
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="apple-touch-icon" href="Resources/icon.png">
<link rel="apple-touch-startup-image" href="Resources/default.png">
<title>__project.name__</title>
<!-- Custom javascript goes here -->
<!-- End custom javascript -->
<script type="text/javascript">
OBJJ_MAIN_FILE = "main.j";
// The below will tell the compiler to not generate debug symbols but will generate type signatures and inline objj_msgSend functions.
// This will affect only Objective-J code that is compiled when loading the application. It will not affect precompiled
// code like the Cappuccino frameworks.
// Uncomment or comment on the line below to change the flags
OBJJ_COMPILER_FLAGS = [/*"IncludeDebugSymbols"*/, "IncludeTypeSignatures"/*, "SourceMap"*/, "InlineMsgSend"];
var progressBar = null;
OBJJ_PROGRESS_CALLBACK = function(percent, appSize, path)
{
percent = percent * 100;
if (!progressBar)
progressBar = document.getElementById("progress-bar");
if (progressBar)
progressBar.style.width = Math.min(percent, 100) + "%";
}
var loadingHTML =
'<div id="loading">' +
' <div id="loading-text">Loading...</div>' +
' <div id="progress-indicator">' +
' <span id="progress-bar" style="width:0%"></span>' +
' </div>' +
'</div>';
</script>
<script type="text/javascript" src="Frameworks/Objective-J/Objective-J.js" charset="UTF-8"></script>
<style type="text/css">
html, body, h1, p {
margin: 0;
padding: 0;
}
/* We need a body wrapper because Cappuccino is unhappy if we change the body element */
#cappuccino-body {
/* Position it absolutely so it will fill the height without content */
position: absolute;
top: 0;
bottom: 0;
width: 100%;
/* Put it at the bottom of the stack so it doesn't interfere with UI */
z-index: 0;
}
#cappuccino-body .container {
display: table;
margin: 0 auto;
height: 100%;
}
#cappuccino-body .content {
display: table-cell;
height: 100%;
vertical-align: top;
}
#loading {
position: relative;
top: 35%;
}
#loading-text {
height: 1.5em;
color: #555;
font: normal bold 36px/36px Arial, sans-serif;
}
#progress-indicator {
padding: 0px;
height: 16px;
border: 5px solid #555;
border-radius: 18px;
background-color: white;
}
#progress-bar {
position: relative;
top: -1px;
left: -1px;
display: block;
height: 18px;
/* Compensate for moving the bar left 1px to overlap the indicator border */
border-right: 1px solid #555;
background-color: #555;
}
#noscript {
position: relative;
top: 35%;
padding: 1em 1.5em;
border: 5px solid #555;
border-radius: 16px;
background-color: white;
color: #555;
text-align: center;
font: bold 24px Arial, sans-serif;
}
#noscript a {
color: #98c0ff;
text-decoration: none;
}
</style>
</head>
<body>
<div id="cappuccino-body">
<div class="container">
<div class="content">
<script type="text/javascript">
document.write(loadingHTML);
</script>
</div>
</div>
<noscript style="position:absolute; top:0; left:0; width:100%; height:100%">
<div class="container">
<div class="content">
<div id="noscript">
<p style="font-size:120%; margin-bottom:.75em">JavaScript is required for this application.</p>
<p><a href="http://www.enable-javascript.com" target="_blank">Enable JavaScript</a></p>
</div>
</div>
</div>
</noscript>
</div>
</body>
</html>
+18
View File
@@ -0,0 +1,18 @@
/*
* AppController.j
* CPButtonBarTest
*
* Created by Ross Boucher on March 23, 2010.
* Copyright 2010, Your Company All rights reserved.
*/
@import <Foundation/Foundation.j>
@import <AppKit/AppKit.j>
@import "AppController.j"
function main(args, namedArgs)
{
CPApplicationMain(args, namedArgs);
}