mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-09-14 22:51:28 +00:00
Merge pull request #2448 from cacaodev/CPViewController-async
Fixed: CPViewController isViewLoaded property in async mode
This commit is contained in:
@@ -150,7 +150,7 @@ var CPViewControllerCachedCibs;
|
||||
If you use Interface Builder to create your views, and you initialize the
|
||||
controller using the initWithCibName:bundle: methods, then you MUST NOT override
|
||||
this method.
|
||||
|
||||
|
||||
@note When using this method, the cib loading system is synchronous.
|
||||
See the loadViewWithCompletionHandler: method for an asynchronous loading.
|
||||
*/
|
||||
@@ -179,11 +179,11 @@ var CPViewControllerCachedCibs;
|
||||
|
||||
/*!
|
||||
Loads asynchronously the cib and creates the view that the controller manages.
|
||||
|
||||
|
||||
@param aHandler A function passing the loaded view as the first argument
|
||||
and a network error or nil as the second argument: function(view, error).
|
||||
|
||||
@note If the view has already been loaded, the completion handler is run immediatly
|
||||
|
||||
@note If the view has already been loaded, the completion handler is run immediatly
|
||||
and the process is synchronous.
|
||||
*/
|
||||
- (void)loadViewWithCompletionHandler:(Function/*(view, error)*/)aHandler
|
||||
@@ -217,7 +217,7 @@ var CPViewControllerCachedCibs;
|
||||
|
||||
[CPViewControllerCachedCibs setObject:aCib forKey:_cibName];
|
||||
[aCib instantiateCibWithExternalNameTable:_cibExternalNameTable];
|
||||
aHandler(_view, nil);
|
||||
[self _viewDidLoadWithCompletionHandler:aHandler];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -228,13 +228,13 @@ var CPViewControllerCachedCibs;
|
||||
else
|
||||
{
|
||||
[cib instantiateCibWithExternalNameTable:_cibExternalNameTable];
|
||||
aHandler(_view, nil);
|
||||
[self _viewDidLoadWithCompletionHandler:aHandler];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_view = [CPView new];
|
||||
aHandler(_view, nil);
|
||||
[self _viewDidLoadWithCompletionHandler:aHandler];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,9 +285,16 @@ var CPViewControllerCachedCibs;
|
||||
}
|
||||
|
||||
- (void)_viewDidLoad
|
||||
{
|
||||
[self _viewDidLoadWithCompletionHandler:function() {
|
||||
[self viewDidLoad];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)_viewDidLoadWithCompletionHandler:(Function)aHandler
|
||||
{
|
||||
[self willChangeValueForKey:"isViewLoaded"];
|
||||
[self viewDidLoad];
|
||||
aHandler(_view, nil);
|
||||
_isViewLoaded = YES;
|
||||
[self didChangeValueForKey:"isViewLoaded"];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* AppController.j
|
||||
* CPViewControllerTest
|
||||
*
|
||||
* Created by You on May 9, 2016.
|
||||
* Copyright 2016, Your Company All rights reserved.
|
||||
*/
|
||||
|
||||
@import <Foundation/Foundation.j>
|
||||
@import <AppKit/AppKit.j>
|
||||
|
||||
|
||||
@implementation AppController : CPObject
|
||||
{
|
||||
@outlet CPWindow theWindow;
|
||||
@outlet CPViewController viewController;
|
||||
BOOL isViewLoaded;
|
||||
}
|
||||
|
||||
- (void)applicationDidFinishLaunching:(CPNotification)aNotification
|
||||
{
|
||||
// This is called when the application is done loading.
|
||||
}
|
||||
|
||||
- (void)awakeFromCib
|
||||
{
|
||||
// This is called when the cib is done loading.
|
||||
// You can implement this method on any object instantiated from a Cib.
|
||||
// It's a useful hook for setting up current UI values, and other things.
|
||||
|
||||
isViewLoaded = NO;
|
||||
// In this case, we want the window from Cib to become our full browser window
|
||||
[theWindow setFullPlatformWindow:YES];
|
||||
}
|
||||
|
||||
- (IBAction)load:(id)sender
|
||||
{
|
||||
[viewController loadViewWithCompletionHandler:function(view, error)
|
||||
{
|
||||
[view setBackgroundColor:[CPColor redColor]];
|
||||
[view setFrameOrigin:CGPointMake(100,100)];
|
||||
[[theWindow contentView] addSubview:view];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Nuage Networks
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
// Import this Categories from your application
|
||||
// You can now user -(void)setCucappIdentifier: and -(CPString)cucappIdentifier
|
||||
// to set and get your cucapp IDs.
|
||||
// Then from a test, you can use it as a selector like //CPView[cucappIdentifier="my-button"]
|
||||
|
||||
@import <AppKit/CPResponder.j>
|
||||
@import <AppKit/CPMenuItem.j>
|
||||
|
||||
@implementation CPResponder (cucappAdditions)
|
||||
|
||||
- (void)setCucappIdentifier:(CPString)anIdentifier
|
||||
{
|
||||
self.__cucappIdentifier = anIdentifier;
|
||||
}
|
||||
|
||||
- (CPString)cucappIdentifier
|
||||
{
|
||||
return self.__cucappIdentifier;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPMenuItem (cucappAdditionsMenu)
|
||||
|
||||
- (void)setCucappIdentifier:(CPString)anIdentifier
|
||||
{
|
||||
[[self _menuItemView] setCucappIdentifier:anIdentifier];
|
||||
}
|
||||
|
||||
- (CPString)cucappIdentifier
|
||||
{
|
||||
[[self _menuItemView] cucappIdentifier];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
function load_cucapp_CLI(path)
|
||||
{
|
||||
if (!path)
|
||||
path = "Cucapp/lib/Cucumber.j"
|
||||
|
||||
try {
|
||||
objj_importFile(path, true, function() {
|
||||
[Cucumber stopCucumber];
|
||||
CPLog.debug("Cucapp CLI has been well loaded");
|
||||
_addition_cpapplication_send_event_method();
|
||||
});
|
||||
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
[CPException raise:CPInvalidArgumentException reason:@"Invalid path for the lib Cucumber"];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function load_cucapp_record(path)
|
||||
{
|
||||
if (!path)
|
||||
path = "CuCapp+Record.j"
|
||||
|
||||
try {
|
||||
objj_importFile(path, true, function() {
|
||||
CPLog.debug("Cucapp record has been well loaded");
|
||||
});
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
[CPException raise:CPInvalidArgumentException reason:@"Invalid path for the lib Cucapp+Record.j"];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,591 @@
|
||||
@import <AppKit/CPApplication.j>
|
||||
|
||||
function start_record(path)
|
||||
{
|
||||
[CPWindow start_record];
|
||||
}
|
||||
|
||||
function stop_record()
|
||||
{
|
||||
[CPWindow stop_record];
|
||||
}
|
||||
|
||||
function save_record(fileName)
|
||||
{
|
||||
if (!fileName)
|
||||
fileName = @"record"
|
||||
|
||||
var eventRecords = [CPWindow eventRecords],
|
||||
JSONEvents = [];
|
||||
|
||||
for (var i = 0; i < [eventRecords count]; i++)
|
||||
{
|
||||
var eventRecord = eventRecords[i];
|
||||
[JSONEvents addObject:[eventRecord objectToJSON]];
|
||||
}
|
||||
|
||||
var pom = document.createElement('a');
|
||||
pom.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(JSON.stringify(JSONEvents, null, 4)));
|
||||
pom.setAttribute('download', fileName + ".json");
|
||||
pom.click();
|
||||
}
|
||||
|
||||
function play_record(file_name, cucumber_path)
|
||||
{
|
||||
if (!cucumber_path)
|
||||
cucumber_path = path = "../../Cucapp/lib/Cucumber.j";
|
||||
|
||||
load_cucapp_CLI(cucumber_path);
|
||||
|
||||
setTimeout(function(){
|
||||
_load_javascript_file(file_name)
|
||||
},1000);
|
||||
}
|
||||
|
||||
function _load_javascript_file(file_name)
|
||||
{
|
||||
var AJAX_req = new XMLHttpRequest();
|
||||
AJAX_req.open( "GET", file_name, true );
|
||||
AJAX_req.setRequestHeader("Content-type", "application/json");
|
||||
|
||||
AJAX_req.onreadystatechange = function()
|
||||
{
|
||||
if (AJAX_req.readyState == 4)
|
||||
{
|
||||
var recordingEvents = JSON.parse(AJAX_req.responseText);
|
||||
|
||||
for (var i = 0; i < [recordingEvents count]; i++)
|
||||
{
|
||||
var recordingEvent = JSON.parse(recordingEvents[i]),
|
||||
type = recordingEvent["event"]["type"];
|
||||
|
||||
if (type == CPLeftMouseDown && i < [recordingEvents count] - 1)
|
||||
{
|
||||
var nextRecordingEvent = JSON.parse(recordingEvents[i + 1]),
|
||||
nextType = nextRecordingEvent["event"]["type"];
|
||||
|
||||
if (nextType == CPMouseMoved)
|
||||
{
|
||||
for (var j = i; j < [recordingEvents count]; j++)
|
||||
{
|
||||
var tmpRecordingEvent = JSON.parse(recordingEvents[j]),
|
||||
tmpType = tmpRecordingEvent["event"]["type"];
|
||||
|
||||
if (tmpType == CPLeftMouseUp)
|
||||
{
|
||||
setTimeout(_simulate_drag_event, recordingEvent["event"]["timestamp"] * 1000, recordingEvent, tmpRecordingEvent);
|
||||
i = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(_simulate_event, recordingEvent["event"]["timestamp"] * 1000, recordingEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AJAX_req.send();
|
||||
}
|
||||
|
||||
function _simulate_drag_event(event1, event2)
|
||||
{
|
||||
var keyView1 = event1["keyView"],
|
||||
valueView1 = event1["valueView"],
|
||||
keyView2 = event2["keyView"],
|
||||
valueView2 = event2["valueView"],
|
||||
locationInWindow1 = CGPointMake(event1["event"]["locationInWindow"]["x"], event1["event"]["locationInWindow"]["y"]);
|
||||
locationInWindow2 = CGPointMake(event2["event"]["locationInWindow"]["x"], event2["event"]["locationInWindow"]["y"]);
|
||||
|
||||
if (keyView1 && valueView1 && keyView2 && valueView2)
|
||||
simulate_dragged_click_view_to_view(keyView1, valueView1, keyView2, valueView2);
|
||||
else if (keyView1 && valueView1)
|
||||
simulate_dragged_click_view_to_point(keyView1, valueView1, locationInWindow1.x, locationInWindow1.y);
|
||||
else
|
||||
simulate_dragged_click_point_to_point(locationInWindow1.x, locationInWindow1.y, locationInWindow2.x, locationInWindow2.y);
|
||||
}
|
||||
|
||||
function _simulate_event(event)
|
||||
{
|
||||
var type = event["event"]["type"],
|
||||
keyView = event["keyView"],
|
||||
valueView = event["valueView"],
|
||||
characters = event["event"]["characters"],
|
||||
deltaX = event["event"]["deltaX"],
|
||||
deltaY = event["event"]["deltaY"],
|
||||
deltaZ = event["event"]["deltaZ"],
|
||||
deltaZ = event["event"]["deltaZ"],
|
||||
locationInWindow = CGPointMake(event["event"]["locationInWindow"]["x"], event["event"]["locationInWindow"]["y"]);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case CPScrollWheel:
|
||||
|
||||
if (keyView && valueView)
|
||||
simulate_scroll_wheel_on_view(keyView, valueView, deltaX, deltaY)
|
||||
|
||||
break;
|
||||
|
||||
case CPLeftMouseDown:
|
||||
|
||||
if (keyView && valueView)
|
||||
simulate_left_click_on_view(keyView, valueView);
|
||||
else
|
||||
simulate_left_click_on_point(locationInWindow.x, locationInWindow.y)
|
||||
|
||||
break;
|
||||
|
||||
case CPRightMouseDown:
|
||||
|
||||
if (keyView && valueView)
|
||||
simulate_right_click_on_view(keyView, valueView);
|
||||
else
|
||||
simulate_right_click_on_point(locationInWindow.x, locationInWindow.y)
|
||||
|
||||
break;
|
||||
|
||||
case CPKeyDown:
|
||||
simulate_keyboard_event(characters);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var eventRecords,
|
||||
recording = NO;
|
||||
|
||||
@implementation CPWindow (cucappRecord)
|
||||
|
||||
+ (CPArray)eventRecords
|
||||
{
|
||||
return eventRecords;
|
||||
}
|
||||
|
||||
+ (void)start_record
|
||||
{
|
||||
eventRecords = [];
|
||||
recording = YES;
|
||||
}
|
||||
|
||||
+ (void)stop_record
|
||||
{
|
||||
recording = NO;
|
||||
}
|
||||
|
||||
/*!
|
||||
Dispatches events that are sent to it from CPApplication.
|
||||
@param anEvent the event to be dispatched
|
||||
*/
|
||||
- (void)sendEvent:(CPEvent)anEvent
|
||||
{
|
||||
var type = [anEvent type],
|
||||
sheet = [self attachedSheet],
|
||||
recordingEvent = [[RecordingEvent alloc] initWithEvent:anEvent];
|
||||
|
||||
if (recordingEvent && type != CPFlagsChanged && type != CPMouseMoved)
|
||||
[eventRecords addObject:recordingEvent];
|
||||
|
||||
// If a sheet is attached events get filtered here.
|
||||
// It is not clear what events should be passed to the view, perhaps all?
|
||||
// CPLeftMouseDown is needed for window moving and resizing to work.
|
||||
// CPMouseMoved is needed for rollover effects on title bar buttons.
|
||||
|
||||
if (sheet)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case CPLeftMouseDown:
|
||||
|
||||
// This is needed when a doubleClick occurs when the sheet is closing or opening
|
||||
if (!_parentWindow)
|
||||
return;
|
||||
|
||||
[recordingEvent setView:_windowView];
|
||||
|
||||
[_windowView mouseDown:anEvent];
|
||||
|
||||
// -dw- if the window is clicked, the sheet should come to front, and become key,
|
||||
// and the window should be immediately behind
|
||||
[sheet makeKeyAndOrderFront:self];
|
||||
|
||||
return;
|
||||
|
||||
case CPMouseMoved:
|
||||
// Allow these through to the parent
|
||||
break;
|
||||
|
||||
default:
|
||||
// Everything else is filtered
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var point = [anEvent locationInWindow];
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case CPFlagsChanged:
|
||||
return [[self firstResponder] flagsChanged:anEvent];
|
||||
|
||||
case CPKeyUp:
|
||||
return [[self firstResponder] keyUp:anEvent];
|
||||
|
||||
case CPKeyDown:
|
||||
if ([anEvent charactersIgnoringModifiers] === CPTabCharacter)
|
||||
{
|
||||
if ([anEvent modifierFlags] & CPShiftKeyMask)
|
||||
[self selectPreviousKeyView:self];
|
||||
else
|
||||
[self selectNextKeyView:self];
|
||||
|
||||
// Make sure the browser doesn't try to do its own tab handling.
|
||||
// This is important or the browser might blur the shared text field or token field input field,
|
||||
// even that we just moved it to a new first responder.
|
||||
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO]
|
||||
return;
|
||||
}
|
||||
else if ([anEvent charactersIgnoringModifiers] === CPBackTabCharacter)
|
||||
{
|
||||
var didTabBack = [self selectPreviousKeyView:self];
|
||||
|
||||
if (didTabBack)
|
||||
{
|
||||
// Make sure the browser doesn't try to do its own tab handling.
|
||||
// This is important or the browser might blur the shared text field or token field input field,
|
||||
// even that we just moved it to a new first responder.
|
||||
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO]
|
||||
}
|
||||
return didTabBack;
|
||||
}
|
||||
else if ([anEvent charactersIgnoringModifiers] == CPEscapeFunctionKey && [self _processKeyboardUIKey:anEvent])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
[[self firstResponder] keyDown:anEvent];
|
||||
|
||||
// Trigger the default button if needed
|
||||
// FIXME: Is this only applicable in a sheet? See isse: #722.
|
||||
if (![self disableKeyEquivalentForDefaultButton])
|
||||
{
|
||||
var defaultButton = [self defaultButton],
|
||||
keyEquivalent = [defaultButton keyEquivalent],
|
||||
modifierMask = [defaultButton keyEquivalentModifierMask];
|
||||
|
||||
if ([anEvent _triggersKeyEquivalent:keyEquivalent withModifierMask:modifierMask])
|
||||
[[self defaultButton] performClick:self];
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
case CPScrollWheel:
|
||||
[recordingEvent setView:[_windowView hitTest:point]];
|
||||
|
||||
return [[_windowView hitTest:point] scrollWheel:anEvent];
|
||||
|
||||
case CPLeftMouseUp:
|
||||
case CPRightMouseUp:
|
||||
var hitTestedView = _leftMouseDownView,
|
||||
selector = type == CPRightMouseUp ? @selector(rightMouseUp:) : @selector(mouseUp:);
|
||||
|
||||
if (!hitTestedView)
|
||||
hitTestedView = [_windowView hitTest:point];
|
||||
|
||||
[recordingEvent setView:hitTestedView];
|
||||
|
||||
[hitTestedView performSelector:selector withObject:anEvent];
|
||||
|
||||
_leftMouseDownView = nil;
|
||||
|
||||
return;
|
||||
|
||||
case CPLeftMouseDown:
|
||||
case CPRightMouseDown:
|
||||
// This will return _windowView if it is within a resize region
|
||||
_leftMouseDownView = [_windowView hitTest:point];
|
||||
|
||||
[recordingEvent setView:_leftMouseDownView];
|
||||
|
||||
if (_leftMouseDownView !== _firstResponder && [_leftMouseDownView acceptsFirstResponder])
|
||||
[self makeFirstResponder:_leftMouseDownView];
|
||||
|
||||
[CPApp activateIgnoringOtherApps:YES];
|
||||
|
||||
var theWindow = [anEvent window],
|
||||
selector = type == CPRightMouseDown ? @selector(rightMouseDown:) : @selector(mouseDown:);
|
||||
|
||||
if ([theWindow isKeyWindow] || ([theWindow becomesKeyOnlyIfNeeded] && ![_leftMouseDownView needsPanelToBecomeKey]))
|
||||
return [_leftMouseDownView performSelector:selector withObject:anEvent];
|
||||
else
|
||||
{
|
||||
// FIXME: delayed ordering?
|
||||
[self makeKeyAndOrderFront:self];
|
||||
|
||||
if ([_leftMouseDownView acceptsFirstMouse:anEvent])
|
||||
return [_leftMouseDownView performSelector:selector withObject:anEvent];
|
||||
}
|
||||
break;
|
||||
|
||||
case CPLeftMouseDragged:
|
||||
case CPRightMouseDragged:
|
||||
if (!_leftMouseDownView)
|
||||
{
|
||||
[recordingEvent setView:[_windowView hitTest:point]];
|
||||
return [[_windowView hitTest:point] mouseDragged:anEvent];
|
||||
}
|
||||
|
||||
[recordingEvent setView:_leftMouseDownView];
|
||||
|
||||
var selector;
|
||||
|
||||
if (type == CPRightMouseDragged)
|
||||
{
|
||||
selector = @selector(rightMouseDragged:)
|
||||
if (![_leftMouseDownView respondsToSelector:selector])
|
||||
selector = nil;
|
||||
}
|
||||
|
||||
if (!selector)
|
||||
selector = @selector(mouseDragged:)
|
||||
|
||||
return [_leftMouseDownView performSelector:selector withObject:anEvent];
|
||||
|
||||
case CPMouseMoved:
|
||||
[_windowView setCursorForLocation:point resizing:NO];
|
||||
|
||||
// Ignore mouse moves for parents of sheets
|
||||
if (!_acceptsMouseMovedEvents || sheet)
|
||||
return;
|
||||
|
||||
if (!_mouseEnteredStack)
|
||||
_mouseEnteredStack = [];
|
||||
|
||||
var hitTestView = [_windowView hitTest:point];
|
||||
|
||||
if ([_mouseEnteredStack count] && [_mouseEnteredStack lastObject] === hitTestView)
|
||||
return [hitTestView mouseMoved:anEvent];
|
||||
|
||||
var view = hitTestView,
|
||||
mouseEnteredStack = [];
|
||||
|
||||
while (view)
|
||||
{
|
||||
mouseEnteredStack.unshift(view);
|
||||
|
||||
view = [view superview];
|
||||
}
|
||||
|
||||
var deviation = MIN(_mouseEnteredStack.length, mouseEnteredStack.length);
|
||||
|
||||
while (deviation--)
|
||||
if (_mouseEnteredStack[deviation] === mouseEnteredStack[deviation])
|
||||
break;
|
||||
|
||||
var index = deviation + 1,
|
||||
count = _mouseEnteredStack.length;
|
||||
|
||||
if (index < count)
|
||||
{
|
||||
var event = [CPEvent mouseEventWithType:CPMouseExited location:point modifierFlags:[anEvent modifierFlags] timestamp:[anEvent timestamp] windowNumber:_windowNumber context:nil eventNumber:-1 clickCount:1 pressure:0];
|
||||
|
||||
for (; index < count; ++index)
|
||||
[_mouseEnteredStack[index] mouseExited:event];
|
||||
}
|
||||
|
||||
index = deviation + 1;
|
||||
count = mouseEnteredStack.length;
|
||||
|
||||
if (index < count)
|
||||
{
|
||||
var event = [CPEvent mouseEventWithType:CPMouseEntered location:point modifierFlags:[anEvent modifierFlags] timestamp:[anEvent timestamp] windowNumber:_windowNumber context:nil eventNumber:-1 clickCount:1 pressure:0];
|
||||
|
||||
for (; index < count; ++index)
|
||||
[mouseEnteredStack[index] mouseEntered:event];
|
||||
}
|
||||
|
||||
_mouseEnteredStack = mouseEnteredStack;
|
||||
|
||||
[hitTestView mouseMoved:anEvent];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation RecordingEvent : CPObject
|
||||
{
|
||||
CPEvent _event @accessors(property=event);
|
||||
CPString _keyView @accessors(property=keyView);
|
||||
CPString _valueView @accessors(property=valueView);
|
||||
CGPoint _offsetView @accessors(property=offsetView);
|
||||
int _offsetXPercentage @accessors(property=offsetXPercentage);
|
||||
int _offsetYPercentage @accessors(property=offsetYPercentage);
|
||||
}
|
||||
|
||||
- (id)initWithEvent:(CPEvent)anEvent
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
_event = anEvent;
|
||||
_offsetView = CGPointMakeZero();
|
||||
_keyView = @"";
|
||||
_valueView = @"";
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setView:(CPView)aView
|
||||
{
|
||||
if ([aView respondsToSelector:@selector(cucappIdentifier)])
|
||||
{
|
||||
_keyView = @"cucappIdentifier";
|
||||
_valueView = [aView cucappIdentifier];
|
||||
}
|
||||
else if ([aView respondsToSelector:@selector(identifier)])
|
||||
{
|
||||
_keyView = @"identifier";
|
||||
_valueView = [aView identifier];
|
||||
}
|
||||
else if ([aView respondsToSelector:@selector(title)])
|
||||
{
|
||||
_keyView = @"title";
|
||||
_valueView = [aView title];
|
||||
}
|
||||
else if ([aView respondsToSelector:@selector(placeholderString)])
|
||||
{
|
||||
_keyView = @"placeholderString";
|
||||
_valueView = [aView placeholderString];
|
||||
}
|
||||
else if ([aView respondsToSelector:@selector(text)])
|
||||
{
|
||||
_keyView = @"text";
|
||||
_valueView = [aView text];
|
||||
}
|
||||
else if ([aView respondsToSelector:@selector(tag)])
|
||||
{
|
||||
_keyView = @"tag";
|
||||
_valueView = [aView tag];
|
||||
}
|
||||
else if ([aView respondsToSelector:@selector(label)])
|
||||
{
|
||||
_keyView = @"label";
|
||||
_valueView = [aView label];
|
||||
}
|
||||
else if ([aView respondsToSelector:@selector(objectValue)])
|
||||
{
|
||||
_keyView = @"objectValue";
|
||||
_valueView = [aView objectValue];
|
||||
}
|
||||
|
||||
var globalPoint = [[aView superview] convertPointToBase:[aView frameOrigin]],
|
||||
globalEventPoint = [_event locationInWindow];
|
||||
|
||||
_offsetView = CGPointMake(globalEventPoint.x - globalPoint.x, globalEventPoint.y - globalPoint.y);
|
||||
|
||||
_offsetXPercentage = _offsetView.x * 100 / [aView frameSize].width;
|
||||
_offsetYPercentage = _offsetView.y * 100 / [aView frameSize].height;
|
||||
}
|
||||
|
||||
- (CPString)objectToJSON
|
||||
{
|
||||
var json = {};
|
||||
|
||||
json["keyView"] = _keyView;
|
||||
json["valueView"] = _valueView;
|
||||
json["offsetXPercentage"] = _offsetXPercentage;
|
||||
json["offsetYPercentage"] = _offsetYPercentage;
|
||||
json["offsetView"] = {"x" : _offsetView.x, "y" : _offsetView.y};
|
||||
|
||||
var event = {};
|
||||
event["type"] = [_event type];
|
||||
event["deltaX"] = [_event deltaX];
|
||||
event["deltaY"] = [_event deltaY];
|
||||
event["deltaZ"] = [_event deltaZ];
|
||||
event["characters"] = [_event characters];
|
||||
event["charactersIgnoringModifiers"] = [_event charactersIgnoringModifiers];
|
||||
event["clickCount"] = [_event clickCount];
|
||||
event["modifierFlags"] = [_event modifierFlags];
|
||||
event["locationInWindow"] = {"x" : [_event locationInWindow].x, "y" : [_event locationInWindow].y};
|
||||
event["keyCode"] = [_event keyCode];
|
||||
event["timestamp"] = [_event timestamp];
|
||||
|
||||
json["event"] = event;
|
||||
|
||||
return JSON.stringify(json, null, 4);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation CPApplication (cucappRecord)
|
||||
|
||||
/*!
|
||||
Dispatches events to other objects.
|
||||
@param anEvent the event to dispatch
|
||||
*/
|
||||
- (void)sendEvent:(CPEvent)anEvent
|
||||
{
|
||||
_currentEvent = anEvent;
|
||||
CPEventModifierFlags = [anEvent modifierFlags];
|
||||
|
||||
var theWindow = [anEvent window];
|
||||
|
||||
// Check if this is a candidate for key equivalent...
|
||||
if ([anEvent _couldBeKeyEquivalent] && [self _handleKeyEquivalent:anEvent])
|
||||
// The key equivalent was handled.
|
||||
return;
|
||||
|
||||
if ([anEvent type] == CPMouseMoved)
|
||||
{
|
||||
if (theWindow !== _lastMouseMoveWindow)
|
||||
[_lastMouseMoveWindow _mouseExitedResizeRect];
|
||||
|
||||
_lastMouseMoveWindow = theWindow;
|
||||
}
|
||||
|
||||
/*
|
||||
Event listeners are processed from back to front so that newer event listeners normally take
|
||||
precedence. If during the execution of a callback a new event listener is added, it should
|
||||
be inserted after the current callback but before any higher priority callbacks. This makes
|
||||
repeating event listeners (those that reinsert themselves) stable relative to each other.
|
||||
*/
|
||||
for (var i = _eventListeners.length - 1; i >= 0; i--)
|
||||
{
|
||||
var listener = _eventListeners[i];
|
||||
|
||||
if (listener._mask & (1 << [anEvent type]))
|
||||
{
|
||||
_eventListeners.splice(i, 1);
|
||||
// In case the callback wants to add more listeners.
|
||||
_eventListenerInsertionIndex = i;
|
||||
listener._callback(anEvent);
|
||||
|
||||
var type = [anEvent type],
|
||||
recordingEvent = [[RecordingEvent alloc] initWithEvent:anEvent];
|
||||
|
||||
if (recordingEvent && type != CPFlagsChanged && type != CPMouseMoved)
|
||||
[eventRecords addObject:recordingEvent];
|
||||
|
||||
if (theWindow)
|
||||
[recordingEvent setView:[theWindow._windowView hitTest:[anEvent locationInWindow]]];
|
||||
|
||||
if (listener._dequeue)
|
||||
{
|
||||
// Don't process the event normally and don't send it to any other listener.
|
||||
_eventListenerInsertionIndex = _eventListeners.length;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_eventListenerInsertionIndex = _eventListeners.length;
|
||||
|
||||
if (theWindow)
|
||||
[theWindow sendEvent:anEvent];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,14 @@
|
||||
<?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>Main cib file base name</key>
|
||||
<string>MainMenu.cib</string>
|
||||
<key>CPBundleName</key>
|
||||
<string>CPViewControllerTest</string>
|
||||
<key>CPBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>CPHumanReadableCopyright</key>
|
||||
<string>Copyright © 2016, Your Company All rights reserved.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Jakefile
|
||||
* CPViewControllerTest
|
||||
*
|
||||
* Created by You on May 9, 2016.
|
||||
* Copyright 2016, 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"),
|
||||
projectName = "CPViewControllerTest";
|
||||
|
||||
app (projectName, function(task)
|
||||
{
|
||||
ENV["OBJJ_INCLUDE_PATHS"] = "Frameworks";
|
||||
|
||||
if (configuration === "Debug")
|
||||
ENV["OBJJ_INCLUDE_PATHS"] = FILE.join(ENV["OBJJ_INCLUDE_PATHS"], configuration);
|
||||
|
||||
task.setBuildIntermediatesPath(FILE.join("Build", "CPViewControllerTest.build", configuration));
|
||||
task.setBuildPath(FILE.join("Build", configuration));
|
||||
|
||||
task.setProductName("CPViewControllerTest");
|
||||
task.setIdentifier("com.yourcompany.CPViewControllerTest");
|
||||
task.setVersion("1.0");
|
||||
task.setAuthor("Your Company");
|
||||
task.setEmail("feedback @nospam@ yourcompany.com");
|
||||
task.setSummary("CPViewControllerTest");
|
||||
task.setSources(new FileList("**/*.j").exclude(FILE.join("Build", "**")).exclude(FILE.join("Frameworks", "Source", "**")));
|
||||
task.setResources(new FileList("Resources/**"));
|
||||
task.setIndexFilePath("index.html");
|
||||
task.setInfoPlistPath("Info.plist");
|
||||
|
||||
if (configuration === "Debug")
|
||||
task.setCompilerFlags("-DDEBUG -g");
|
||||
else
|
||||
task.setCompilerFlags("-O2");
|
||||
});
|
||||
|
||||
task ("default", [projectName], function()
|
||||
{
|
||||
printResults(configuration);
|
||||
});
|
||||
|
||||
task ("build", ["default"], function()
|
||||
{
|
||||
updateApplicationSize();
|
||||
});
|
||||
|
||||
task ("debug", function()
|
||||
{
|
||||
configuration = ENV["CONFIGURATION"] = "Debug";
|
||||
JAKE.subjake(["."], "build", ENV);
|
||||
});
|
||||
|
||||
task ("release", function()
|
||||
{
|
||||
configuration = ENV["CONFIGURATION"] = "Release";
|
||||
JAKE.subjake(["."], "build", ENV);
|
||||
});
|
||||
|
||||
task ("run", ["debug"], function()
|
||||
{
|
||||
OS.system(["open", FILE.join("Build", "Debug", projectName, "index.html")]);
|
||||
});
|
||||
|
||||
task ("run-release", ["release"], function()
|
||||
{
|
||||
OS.system(["open", FILE.join("Build", "Release", projectName, "index.html")]);
|
||||
});
|
||||
|
||||
task ("deploy", ["release"], function()
|
||||
{
|
||||
FILE.mkdirs(FILE.join("Build", "Deployment", projectName));
|
||||
OS.system(["press", "-f", FILE.join("Build", "Release", projectName), FILE.join("Build", "Deployment", projectName)]);
|
||||
printResults("Deployment")
|
||||
});
|
||||
|
||||
task ("desktop", ["release"], function()
|
||||
{
|
||||
FILE.mkdirs(FILE.join("Build", "Desktop", projectName));
|
||||
require("cappuccino/nativehost").buildNativeHost(FILE.join("Build", "Release", projectName), FILE.join("Build", "Desktop", projectName, "CPViewControllerTest.app"));
|
||||
printResults("Desktop")
|
||||
});
|
||||
|
||||
task ("run-desktop", ["desktop"], function()
|
||||
{
|
||||
OS.system([FILE.join("Build", "Desktop", projectName, "CPViewControllerTest.app", "Contents", "MacOS", "NativeHost"), "-i"]);
|
||||
});
|
||||
|
||||
function printResults(configuration)
|
||||
{
|
||||
print("----------------------------");
|
||||
print(configuration+" app built at path: "+FILE.join("Build", configuration, projectName));
|
||||
print("----------------------------");
|
||||
}
|
||||
|
||||
function updateApplicationSize()
|
||||
{
|
||||
print("Calculating application file sizes...");
|
||||
|
||||
var contents = FILE.read(FILE.join("Build", configuration, projectName, "Info.plist"), { charset:"UTF-8" }),
|
||||
format = CFPropertyList.sniffedFormatOfString(contents),
|
||||
plist = CFPropertyList.propertyListFromString(contents),
|
||||
totalBytes = {executable:0, data:0, mhtml:0};
|
||||
|
||||
// Get the size of all framework executables and sprite data
|
||||
var frameworksDir = "Frameworks";
|
||||
|
||||
if (configuration === "Debug")
|
||||
frameworksDir = FILE.join(frameworksDir, "Debug");
|
||||
|
||||
var frameworks = FILE.list(frameworksDir);
|
||||
|
||||
frameworks.forEach(function(framework)
|
||||
{
|
||||
if (framework !== "Source")
|
||||
addBundleFileSizes(FILE.join(frameworksDir, framework), totalBytes);
|
||||
});
|
||||
|
||||
// Read in the default theme name, and attempt to get its size
|
||||
var themeName = plist.valueForKey("CPDefaultTheme") || "Aristo2",
|
||||
themePath = nil;
|
||||
|
||||
if (themeName === "Aristo" || themeName === "Aristo2")
|
||||
themePath = FILE.join(frameworksDir, "AppKit", "Resources", themeName + ".blend");
|
||||
else
|
||||
themePath = FILE.join("Frameworks", "Resources", themeName + ".blend");
|
||||
|
||||
if (FILE.isDirectory(themePath))
|
||||
addBundleFileSizes(themePath, totalBytes);
|
||||
|
||||
// Add sizes for the app
|
||||
addBundleFileSizes(FILE.join("Build", configuration, projectName), totalBytes);
|
||||
|
||||
print("Executables: " + totalBytes.executable + ", sprite data: " + totalBytes.data + ", total: " + (totalBytes.executable + totalBytes.data));
|
||||
|
||||
var dict = new CFMutableDictionary();
|
||||
|
||||
dict.setValueForKey("executable", totalBytes.executable);
|
||||
dict.setValueForKey("data", totalBytes.data);
|
||||
dict.setValueForKey("mhtml", totalBytes.mhtml);
|
||||
|
||||
plist.setValueForKey("CPApplicationSize", dict);
|
||||
|
||||
FILE.write(FILE.join("Build", configuration, projectName, "Info.plist"), CFPropertyList.stringFromPropertyList(plist, format), { charset:"UTF-8" });
|
||||
}
|
||||
|
||||
function addBundleFileSizes(bundlePath, totalBytes)
|
||||
{
|
||||
var bundleName = FILE.basename(bundlePath),
|
||||
environment = bundleName === "Foundation" ? "Objj" : "Browser",
|
||||
bundlePath = FILE.join(bundlePath, environment + ".environment");
|
||||
|
||||
if (FILE.isDirectory(bundlePath))
|
||||
{
|
||||
var filename = bundleName + ".sj",
|
||||
filePath = new FILE.Path(FILE.join(bundlePath, filename));
|
||||
|
||||
if (filePath.exists())
|
||||
totalBytes.executable += filePath.size();
|
||||
|
||||
filePath = new FILE.Path(FILE.join(bundlePath, "dataURLs.txt"));
|
||||
|
||||
if (filePath.exists())
|
||||
totalBytes.data += filePath.size();
|
||||
|
||||
filePath = new FILE.Path(FILE.join(bundlePath, "MHTMLData.txt"));
|
||||
|
||||
if (filePath.exists())
|
||||
totalBytes.mhtml += filePath.size();
|
||||
|
||||
filePath = new FILE.Path(FILE.join(bundlePath, "MHTMLPaths.txt"));
|
||||
|
||||
if (filePath.exists())
|
||||
totalBytes.mhtml += filePath.size();
|
||||
}
|
||||
}
|
||||
|
||||
task ("cucumber-test", function()
|
||||
{
|
||||
var SYSTEM = require("system");
|
||||
|
||||
OS.system("ln -s " + SYSTEM.prefix + "/packages/cucapp/Cucapp Cucapp")
|
||||
var code = OS.system("cucumber");
|
||||
OS.system("rm -f Cucapp; rm -f cucumber.html")
|
||||
OS.exit(code);
|
||||
});
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="15E65" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
|
||||
<dependencies>
|
||||
<deployment version="1050" identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||
<connections>
|
||||
<outlet property="delegate" destination="450" id="451"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="371">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="335" y="390" width="480" height="360"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="878"/>
|
||||
<view key="contentView" id="372">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<button identifier="load" verticalHuggingPriority="750" id="B4t-mW-jyS">
|
||||
<rect key="frame" x="20" y="312" width="70" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Load" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="L4T-tk-zIe">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="load:" target="450" id="B2z-4h-JJK"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField identifier="result" horizontalHuggingPriority="251" verticalHuggingPriority="750" id="EwI-DV-COg">
|
||||
<rect key="frame" x="99" y="319" width="163" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="isViewLoaded=" id="w5e-oN-M00">
|
||||
<font key="font" metaFont="system" size="17"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="EPv-VX-kzA" name="displayPatternValue1" keyPath="selection.isViewLoaded" id="BIN-61-0Im">
|
||||
<dictionary key="options">
|
||||
<string key="NSDisplayPattern">isViewLoaded=%{value1}@</string>
|
||||
<string key="NSNoSelectionPlaceholder">NO</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
</subviews>
|
||||
</view>
|
||||
</window>
|
||||
<customObject id="450" customClass="AppController">
|
||||
<connections>
|
||||
<outlet property="theWindow" destination="371" id="459"/>
|
||||
<outlet property="viewController" destination="rLc-A4-CBZ" id="H6z-uM-FBg"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<viewController nibName="ViewController" id="rLc-A4-CBZ"/>
|
||||
<objectController id="EPv-VX-kzA">
|
||||
<connections>
|
||||
<outlet property="content" destination="rLc-A4-CBZ" id="Xfw-zG-Ryt"/>
|
||||
</connections>
|
||||
</objectController>
|
||||
</objects>
|
||||
</document>
|
||||
@@ -0,0 +1 @@
|
||||
280NPLIST;1.0;D;K;4;$topD;K;18;CPCibObjectDataKeyD;K;6;CP$UIDd;1;2E;E;K;8;$objectsA;S;5;$nullD;K;10;$classnameS;16;_CPCibObjectDataK;8;$classesA;S;16;_CPCibObjectDataS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;1;1E;K;28;_CPCibObjectDataNamesKeysKeyD;K;6;CP$UIDd;1;0E;K;30;_CPCibObjectDataNamesValuesKeyD;K;6;CP$UIDd;1;0E;K;30;_CPCibObjectDataClassesKeysKeyD;K;6;CP$UIDd;1;0E;K;32;_CPCibObjectDataClassesValuesKeyD;K;6;CP$UIDd;1;0E;K;30;_CPCibObjectDataConnectionsKeyD;K;6;CP$UIDd;1;4E;K;28;_CPCibObjectDataFrameworkKeyD;K;6;CP$UIDd;1;0E;K;26;_CPCibObjectDataNextOidKeyD;K;6;CP$UIDd;1;5E;K;30;_CPCibObjectDataObjectsKeysKeyD;K;6;CP$UIDd;1;6E;K;32;_CPCibObjectDataObjectsValuesKeyD;K;6;CP$UIDd;1;7E;K;26;_CPCibObjectDataOidKeysKeyD;K;6;CP$UIDd;1;8E;K;28;_CPCibObjectDataOidValuesKeyD;K;6;CP$UIDd;1;9E;K;28;_CPCibObjectDataFileOwnerKeyD;K;6;CP$UIDd;2;11E;K;33;_CPCibObjectDataVisibleWindowsKeyD;K;6;CP$UIDd;2;13E;E;D;K;10;$classnameS;7;CPArrayK;8;$classesA;S;7;CPArrayS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;15E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;16E;D;K;6;CP$UIDd;2;18E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;11E;D;K;6;CP$UIDd;2;11E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;10;$classnameS;18;_CPCibCustomObjectK;8;$classesA;S;18;_CPCibCustomObjectS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;10E;K;27;_CPCibCustomObjectClassNameD;K;6;CP$UIDd;2;19E;E;D;K;10;$classnameS;5;CPSetK;8;$classesA;S;5;CPSetS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;12E;K;15;CPSetObjectsKeyD;K;6;CP$UIDd;2;20E;E;D;K;10;$classnameS;20;CPCibOutletConnectorK;8;$classesA;S;20;CPCibOutletConnectorS;14;CPCibConnectorS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;14E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;11E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;18E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;2;21E;E;D;K;6;$classD;K;6;CP$UIDd;2;10E;K;27;_CPCibCustomObjectClassNameD;K;6;CP$UIDd;2;22E;E;D;K;10;$classnameS;18;_CPCibClassSwapperK;8;$classesA;S;18;_CPCibClassSwapperS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;17E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;12;CPViewTagKeyD;K;6;CP$UIDd;2;23E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;2;24E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;2;24E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;2;25E;K;19;CPViewThemeClassKeyD;K;6;CP$UIDd;1;0E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;26E;K;14;CPViewScaleKeyD;K;6;CP$UIDd;2;27E;K;18;CPViewSizeScaleKeyD;K;6;CP$UIDd;2;27E;K;17;CPViewIsScaledKeyD;K;6;CP$UIDd;2;28E;K;19;CPViewAppearanceKeyD;K;6;CP$UIDd;1;0E;K;22;CPViewTrackingAreasKeyD;K;6;CP$UIDd;2;29E;K;30;_CPCibClassSwapperClassNameKeyD;K;6;CP$UIDd;2;30E;K;38;_CPCibClassSwapperOriginalClassNameKeyD;K;6;CP$UIDd;2;31E;E;S;16;CPViewControllerD;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;S;4;viewS;13;CPApplicationd;1;0S;20;{{0, 0}, {480, 272}}d;2;12S;6;normalS;6;{1, 1}F;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;S;6;NSViewS;6;CPViewE;K;9;$archiverS;15;CPKeyedArchiverK;8;$versionS;6;100000E;
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="15E65" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSViewController">
|
||||
<connections>
|
||||
<outlet property="view" destination="c22-O7-iKe" id="jmy-2J-skS"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<customView id="c22-O7-iKe">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
</objects>
|
||||
</document>
|
||||
@@ -0,0 +1,173 @@
|
||||
# Given the application is lauched
|
||||
Given /^the application is launched$/ do
|
||||
launched = app.gui.command "launched"
|
||||
|
||||
if !launched
|
||||
raise "The application was not launched"
|
||||
end
|
||||
end
|
||||
|
||||
# Given I wait for n seconds
|
||||
Given /^I wait for (\d+) seconds?$/ do |n|
|
||||
sleep(eval("#{n.to_i}"))
|
||||
end
|
||||
|
||||
# When I close the popover
|
||||
When /^I close the popover$/ do
|
||||
step "I hit the key escape"
|
||||
end
|
||||
|
||||
|
||||
# When I hit the key c
|
||||
When /^I hit the key (.*)$/ do |key|
|
||||
step "I hit the mask none and the key #{key}"
|
||||
end
|
||||
|
||||
|
||||
# When I hit the mask shif and the key c
|
||||
When /^I hit the mask (.*) and the key (.*)$/ do |mask, key|
|
||||
simulate_keyboard_event(key, mask)
|
||||
end
|
||||
|
||||
|
||||
# When the keys cucapp
|
||||
When /^I hit the keys (.*)$/ do |keys|
|
||||
step "I hit the mask none and keys #{keys}"
|
||||
end
|
||||
|
||||
|
||||
# When I hit the mask shif and the keys cucapp
|
||||
When /^I hit the mask (.*) and keys (.*)$/ do |mask, keys|
|
||||
simulate_keyboard_event(keys, mask)
|
||||
end
|
||||
|
||||
|
||||
# When I select all
|
||||
When /^I select all$/ do
|
||||
app.gui.simulate_keyboard_event "a", [$CPCommandKeyMask]
|
||||
end
|
||||
|
||||
|
||||
# When I save the document
|
||||
When /^I save the document$/ do
|
||||
app.gui.simulate_keyboard_event "s", [$CPCommandKeyMask]
|
||||
end
|
||||
|
||||
|
||||
# When I (click|right click|double click) on the field with the value cucapp
|
||||
When /^I (click|right click|double click) on the (\w*\-*\w*) with the value (.*)$/ do |click_type, element, value|
|
||||
step "I #{click_type} on the #{element} with the property object-value set to #{value}"
|
||||
end
|
||||
|
||||
|
||||
# When I click on the field with the property cucapp-identifier set to cucapp-identifier-button-add
|
||||
When /^I (click|right click|double click) on the (\w*\-*\w*) with the property (\w*\-*\w*) set to (.*)$/ do |click_type, element, property, property_value|
|
||||
step "I #{click_type} with the key mask none on the #{element} with the property #{property} set to #{property_value}"
|
||||
end
|
||||
|
||||
|
||||
# When I click with the mask shift on the field with the property cucapp-identifier set to cucapp-identifier-button-add
|
||||
When /^I (click|right click|double click) with the key mask (.*) on the (\w*\-*\w*) with the property (\w*\-*\w*) set to (.*)$/ do |click_type, mask, element, property, property_value|
|
||||
|
||||
type = $mouse_left_click
|
||||
|
||||
if click_type == "right click"
|
||||
type = $mouse_right_click
|
||||
end
|
||||
|
||||
if click_type == "double click"
|
||||
type = $mouse_double_click
|
||||
end
|
||||
|
||||
simulate_click(type, element, property, property_value, mask)
|
||||
end
|
||||
|
||||
|
||||
# When I do a drag and drop from the field with the value cucapp to the field with the value cappuccino
|
||||
When /^I do a drag and drop from the (\w*\-*\w*) with the value (.*) to the (\w*\-*\w*) with the value (.*)$/ do |element, value, second_element, second_value|
|
||||
step "I do a drag and drop from the #{element} with the property object-value set to #{value} to the #{second_element} with the property object-value set to #{second_value}"
|
||||
end
|
||||
|
||||
|
||||
# When I do a drag and drop from the field with the property title set to cucapp to the field with the property title set to cappuccino
|
||||
When /^I do a drag and drop from the (\w*\-*\w*) with the property (\w*\-*\w*) set to (.*) to the (\w*\-*\w*) with the property (\w*\-*\w*) set to (.*)$/ do |element, property, property_value, second_element, second_property, second_property_value|
|
||||
step "I do a drag and drop with the key mask none from the #{element} with the property #{property} set to #{property_value} to the #{second_element} with the property #{second_property} set to #{second_property_value}"
|
||||
end
|
||||
|
||||
|
||||
# When I do a drag and drop with the key mask shift from the field with the property title set to cucapp to the field with the property title set to cappuccino
|
||||
When /^I do a drag and drop with the key mask (.*) from the (\w*\-*\w*) with the property (\w*\-*\w*) set to (.*) to the (\w*\-*\w*) with the property (\w*\-*\w*) set to (.*)$/ do |mask, element, property, property_value, second_element, second_property, second_property_value|
|
||||
simulate_drag_and_drop(element, property, property_value, second_element, second_property, second_property_value, mask)
|
||||
end
|
||||
|
||||
|
||||
# When I vertically|horizontally scroll on the field with the value cappuccino
|
||||
When /^I (vertically|horizontally) scroll on the (\w*\-*\w*) with the value (.*)$/ do |direction, element, value|
|
||||
step "When I #{direction} scroll 10 times on the #{element} with the value #{value}"
|
||||
end
|
||||
|
||||
|
||||
# When I vertically|horizontally scroll 10 times on the field with the value cappuccino
|
||||
When /^I (vertically|horizontally) scroll ([0-9]*) times on the (\w*\-*\w*) with the value (.*)$/ do |direction, times, element, value|
|
||||
step "I #{direction} scroll #{times} times on the #{element} with the property object-value set to #{value}"
|
||||
end
|
||||
|
||||
|
||||
# When I vertically|horizontally scroll 10 times on the field with the property title set to cappuccino
|
||||
When /^I (vertically|horizontally) scroll ([0-9]*) times on the (\w*\-*\w*) with the property (\w*\-*\w*) set to (.*)$/ do |direction, times, element, property, property_value|
|
||||
step "I #{direction} scroll #{times} times with the key mask none on the #{element} with the property #{property} set to #{property_value}"
|
||||
end
|
||||
|
||||
|
||||
# When I vertically|horizontally scroll 10 times on the field with the property title set to cappuccino
|
||||
When /^I (vertically|horizontally) scroll ([0-9]*) times with the key mask (.*) on the (\w*\-*\w*) with the property (\w*\-*\w*) set to (.*)$/ do |direction, times, mask, element, property, property_value|
|
||||
|
||||
vertically = false
|
||||
horizontally = false
|
||||
|
||||
if direction == "vertically"
|
||||
vertically = true
|
||||
end
|
||||
|
||||
if direction == "horizontally"
|
||||
horizontally = true
|
||||
end
|
||||
|
||||
simulate_scroll(element, property, property_value, times, mask, horizontally, vertically)
|
||||
end
|
||||
|
||||
|
||||
# When I select the item name of the pop-up-button with the property cucapp-identifier set to cucappIdentifierPopUpButton
|
||||
When /^I select the item (.*) of the pop-up-button with the property (\w*\-*\w*) set to (.*)$/ do |item_name, property, property_value|
|
||||
select_pop_up_button_item(item_name, property, property_value)
|
||||
end
|
||||
|
||||
|
||||
# Then the field with the property title set to name should be focused
|
||||
Then /^the (\w*\-*\w*) with the property (\w*\-*\w*) set to (.*) should be focused$/ do |element, property, property_value|
|
||||
app.gui.is_control_focused(create_xpath(element, property, property_value))
|
||||
end
|
||||
|
||||
|
||||
# Then the field should not have a value
|
||||
Then /^the (\w*\-*\w*) should not have a value$/ do |element|
|
||||
step "the #{element} with the property object-value set to #{value} should have the value #{value}"
|
||||
end
|
||||
|
||||
|
||||
# Then the field with the property cucapp-identifier set to cucapp-identifier-textfield-description should not have a value
|
||||
Then /^the (\w*\-*\w*) with the property (\w*\-*\w*) set to (.*) should not have a value$/ do |element, property, property_value|
|
||||
check_value_control(element, property, property_value, nil)
|
||||
end
|
||||
|
||||
|
||||
# Then the field should have the value cucapp
|
||||
Then /^the (\w*\-*\w*) should have the value (.*)$/ do |element, value|
|
||||
step "the #{element} with the property object-value set to #{value} should have the value #{value}"
|
||||
end
|
||||
|
||||
|
||||
# Then the field with the property cucapp-identifier set to cucapp-identifier-textfield-description should have the value cucapp
|
||||
Then /^the (\w*\-*\w*) with the property (\w*\-*\w*) set to (.*) should have the value (.*)$/ do |element, property, property_value, value|
|
||||
check_value_control(element, property, property_value, value)
|
||||
end
|
||||
@@ -0,0 +1,19 @@
|
||||
@import <Foundation/Foundation.j>
|
||||
|
||||
@implementation Cucumber (CuCapp)
|
||||
|
||||
- (CPString)valueIsEqual:(CPArray)params
|
||||
{
|
||||
var obj = cucumber_objects[params[0]],
|
||||
value = params[1];
|
||||
|
||||
if (!obj)
|
||||
return '{"result" : "__CUKE_ERROR__"}';
|
||||
|
||||
if ([obj respondsToSelector:@selector(stringValue)] && value === [obj stringValue])
|
||||
return '{"result" : "OK"}';
|
||||
|
||||
return '{"result" : "__CUKE_ERROR__"}';
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,62 @@
|
||||
$cappuccino_control_mappings = {
|
||||
"image-view-text" => "_CPImageAndTextView",
|
||||
"menu-item" => "_CPMenuItemView",
|
||||
"tool-bar-item" => "_CPToolbarItemView",
|
||||
"box" => "CPBox",
|
||||
"button" => "CPButton",
|
||||
"button-bar" => "CPButtonBar",
|
||||
"collection-view" => "CPCollectionView",
|
||||
"combo-box" => "CPComboBox",
|
||||
"control" => "CPControl",
|
||||
"check-box" => "CPCheckBox",
|
||||
"date-picker" => "CPDatePicker",
|
||||
"image-view" => "CPImageView",
|
||||
"level-indicator" => "CPLevelIndicator",
|
||||
"outline-view" => "CPOutlineView",
|
||||
"pop-up-button" => "CPPopUpButton",
|
||||
"predicate-editor" => "CPPredicateEditor",
|
||||
"radio-button" => "CPRadio",
|
||||
"rule-editor" => "CPRuleEditor",
|
||||
"scroller" => "CPScroller",
|
||||
"scroll-view" => "CPScrollView",
|
||||
"search-field" => "CPSearchField",
|
||||
"secure-field" => "CPSecureTextField",
|
||||
"segemented-control" => "CPSegmentedControl",
|
||||
"slider" => "CPSlider",
|
||||
"stepper" => "CPStepper",
|
||||
"tab-view" => "CPTabView",
|
||||
"table" => "CPTableView",
|
||||
"field" => "CPTextField",
|
||||
"token-field" => "CPTokenField",
|
||||
"view" => "CPView",
|
||||
"none" => nil
|
||||
}
|
||||
|
||||
$property_mappings = {
|
||||
"cucapp-identifier" => "cucappIdentifier",
|
||||
"id" => "id",
|
||||
"identifier" => "identifier",
|
||||
"label" => "label",
|
||||
"object-value" => "objectValue",
|
||||
"placeholder" => "placeholderString",
|
||||
"tag" => "tag",
|
||||
"title" => "title",
|
||||
"text" => "text",
|
||||
"none" => nil
|
||||
}
|
||||
|
||||
$key_mappings = {
|
||||
"command" => $CPCommandKeyMask,
|
||||
"shift" => $CPShiftKeyMask,
|
||||
"option" => $CPAlternateKeyMask,
|
||||
"control" => $CPControlKeyMask,
|
||||
"delete" => $CPDeleteCharacter,
|
||||
"escape" => $CPEscapeFunctionKey,
|
||||
"enter" => $CPNewlineCharacter,
|
||||
"left-arrow" => $CPLeftArrowFunctionKey,
|
||||
"right-arrow" => $CPRightArrowFunctionKey,
|
||||
"top-arrow" => $CPTopArrowFunctionKey,
|
||||
"down-arrow" => $CPDownArrowFunctionKey,
|
||||
"tab" => $CPTabCharacter,
|
||||
"none" => nil
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
module Encumber
|
||||
|
||||
class GUI
|
||||
def value_is_equal(xpath, value)
|
||||
|
||||
if !value
|
||||
value = ""
|
||||
end
|
||||
|
||||
result = command 'valueIsEqual', id_for_element(xpath), value
|
||||
raise "Value #{value} not found" if result["result"] != "OK"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,20 @@
|
||||
$: << File.join(File.dirname(__FILE__), '..', '..', 'Cucapp')
|
||||
|
||||
require 'cucapp.rb'
|
||||
require 'logger'
|
||||
|
||||
module AppHelper
|
||||
|
||||
def app
|
||||
@app ||= Cucapp.new
|
||||
end
|
||||
|
||||
def log
|
||||
@log ||= ENV['log']
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
World(
|
||||
AppHelper
|
||||
)
|
||||
@@ -0,0 +1,7 @@
|
||||
Before do
|
||||
app.reset()
|
||||
end
|
||||
|
||||
After do
|
||||
app.quit()
|
||||
end
|
||||
@@ -0,0 +1,92 @@
|
||||
def check_value_control(element, property, property_value, value)
|
||||
xpath = create_xpath(element, property, property_value)
|
||||
|
||||
app.gui.wait_for xpath
|
||||
app.gui.value_is_equal xpath, value
|
||||
end
|
||||
|
||||
def simulate_keyboard_event(keys, mask)
|
||||
app.gui.simulate_keyboard_events cappuccino_key(keys), [cappuccino_key(mask)]
|
||||
end
|
||||
|
||||
def simulate_click(type, element, property, property_value, mask)
|
||||
xpath = create_xpath(element, property, property_value)
|
||||
|
||||
app.gui.wait_for xpath
|
||||
|
||||
if type == $mouse_double_click
|
||||
app.gui.simulate_double_click xpath, [cappuccino_key(mask)]
|
||||
elsif type == $mouse_right_click
|
||||
app.gui.simulate_right_click xpath, [cappuccino_key(mask)]
|
||||
else
|
||||
app.gui.simulate_left_click xpath, [cappuccino_key(mask)]
|
||||
end
|
||||
end
|
||||
|
||||
def simulate_drag_and_drop(element, property, property_value, second_element, second_property, second_property_value, mask)
|
||||
|
||||
xpath1 = create_xpath(element, property, property_value)
|
||||
xpath2 = create_xpath(second_element, second_property, second_property_value)
|
||||
|
||||
app.gui.simulate_dragged_click_view_to_view xpath1, xpath2, [cappuccino_key(mask)]
|
||||
end
|
||||
|
||||
def simulate_scroll(element, property, property_value, times, mask, horizontal, vertical)
|
||||
xpath = create_xpath(element, property, property_value)
|
||||
delta_x = 0
|
||||
delta_y = 0
|
||||
|
||||
if horizontal
|
||||
delta_x = 1
|
||||
end
|
||||
|
||||
if vertical
|
||||
delta_y = 1
|
||||
end
|
||||
|
||||
for i in 0..times.to_i
|
||||
app.gui.simulate_scroll_wheel xpath, delta_x, delta_y, [cappuccino_key(mask)]
|
||||
end
|
||||
end
|
||||
|
||||
def select_pop_up_button_item(item_name, property, property_value)
|
||||
simulate_click($mouse_left_click, "pop-up-button", property, property_value, [])
|
||||
|
||||
pop_up_button_xpath = create_xpath("pop-up-button", property, property_value)
|
||||
|
||||
pop_up_button_item_xpath = create_xpath("image-view-text", "text", item_name)
|
||||
|
||||
while !app.gui.wait_for_element(pop_up_button_item_xpath, 0.05) && app.gui.pop_up_button_can_scroll_up(pop_up_button_xpath)
|
||||
simulate_keyboard_event("up-arrow", [])
|
||||
end
|
||||
|
||||
while !app.gui.wait_for_element(pop_up_button_item_xpath, 0.05) && app.gui.pop_up_button_can_scroll_down(pop_up_button_xpath)
|
||||
simulate_keyboard_event("down-arrow", [])
|
||||
end
|
||||
|
||||
if not app.gui.wait_for(pop_up_button_item_xpath)
|
||||
raise "Menu item #{item_name} not found !"
|
||||
end
|
||||
|
||||
simulate_click($mouse_left_click, "image-view-text", "text", item_name, [])
|
||||
end
|
||||
|
||||
def cappuccino_key(key)
|
||||
if $key_mappings.has_key?(key)
|
||||
key = $key_mappings[key]
|
||||
end
|
||||
|
||||
return key
|
||||
end
|
||||
|
||||
def create_xpath(element, property, property_value)
|
||||
if !$cappuccino_control_mappings.has_key?(element)
|
||||
raise "Element #{element} not found in the hash cappuccino_control_mappings. You should complete the hash $cappuccino_control_mappings in env.rb"
|
||||
end
|
||||
|
||||
if !$property_mappings.has_key?(property)
|
||||
raise "Property #{property} not found in the hash $property_mappings. You should complete the hash $property_mappings in env.rb"
|
||||
end
|
||||
|
||||
return "//" + $cappuccino_control_mappings[element] + "["+ $property_mappings[property] +"='#{property_value}']"
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
Feature: Test the CPViewController asynchronous loading
|
||||
This test is used to make sure that the isViewLoaded property is true when the loading has ended.
|
||||
|
||||
Scenario: Check if the application is launched
|
||||
Given the application is launched
|
||||
When I click on the button with the property identifier set to load
|
||||
Given I wait for 1 second
|
||||
Then the field with the property identifier set to result should have the value isViewLoaded=true
|
||||
@@ -0,0 +1,204 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!--
|
||||
index-debug.html
|
||||
CPViewControllerTest
|
||||
|
||||
Created by You on May 9, 2016.
|
||||
Copyright 2016, Your Company 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>CPViewControllerTest</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"/*, "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 site.</p>
|
||||
<p><a href="http://www.enable-javascript.com" target="_blank">Enable JavaScript</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</noscript>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,166 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!--
|
||||
index.html
|
||||
CPViewControllerTest
|
||||
|
||||
Created by You on May 9, 2016.
|
||||
Copyright 2016, Your Company 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>CPViewControllerTest</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", "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 site.</p>
|
||||
<p><a href="http://www.enable-javascript.com" target="_blank">Enable JavaScript</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</noscript>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* AppController.j
|
||||
* CPViewControllerTest
|
||||
*
|
||||
* Created by You on May 9, 2016.
|
||||
* Copyright 2016, Your Company All rights reserved.
|
||||
*/
|
||||
|
||||
@import <Foundation/Foundation.j>
|
||||
@import <AppKit/AppKit.j>
|
||||
|
||||
@import "AppController.j"
|
||||
|
||||
|
||||
function main(args, namedArgs)
|
||||
{
|
||||
CPApplicationMain(args, namedArgs);
|
||||
}
|
||||
Reference in New Issue
Block a user