mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-25 04:57:03 +00:00
346 lines
9.4 KiB
Objective-C
346 lines
9.4 KiB
Objective-C
//
|
|
// BridgedMethods.m
|
|
// NativeHost
|
|
//
|
|
// Created by Francisco Tolmasky on 10/16/09.
|
|
// Copyright 2009 280 North, Inc.. All rights reserved.
|
|
//
|
|
|
|
|
|
#import <objc/runtime.h>
|
|
#import "Application.h"
|
|
#import "AppController.h"
|
|
#import "BridgedMethods.h"
|
|
#import "NSObject+WebAdditions.h"
|
|
#import "NSURL+Additions.h"
|
|
#import "WebWindow.h"
|
|
#import "WebPasteboardProxy.h"
|
|
|
|
static NSMutableDictionary * MethodClasses;
|
|
|
|
@implementation GlobalMethods
|
|
|
|
- (id)isDesktop
|
|
{
|
|
return [NSNumber numberWithBool:YES];
|
|
}
|
|
|
|
- (id)openingURLStrings
|
|
{
|
|
return [(AppController *)[NSApp delegate] openingURLStrings];
|
|
}
|
|
|
|
- (id)setMainMenu:(id)arguments
|
|
{
|
|
[[NSApp delegate] setMainMenuObject:[arguments objectAtIndex:0]];
|
|
|
|
return [WebUndefined undefined];
|
|
}
|
|
|
|
- (id)terminate
|
|
{
|
|
[(Application *)NSApp _reallyTerminate:self];
|
|
|
|
return [WebUndefined undefined];
|
|
}
|
|
|
|
- (id)activateIgnoringOtherApps:(NSArray *)arguments
|
|
{
|
|
id argument = [arguments objectAtIndex:0];
|
|
|
|
[(NSApplication *)NSApp activateIgnoringOtherApps:[argument isKindOfClass:[NSNumber class]] && [(NSNumber *)argument boolValue]];
|
|
|
|
return [WebUndefined undefined];
|
|
}
|
|
|
|
- (id)deactivate
|
|
{
|
|
[(NSApplication *)NSApp deactivate];
|
|
return [WebUndefined undefined];
|
|
}
|
|
|
|
- (id)hide
|
|
{
|
|
[NSApp hide:self];
|
|
return [WebUndefined undefined];
|
|
}
|
|
|
|
- (id)hideOtherApplications
|
|
{
|
|
[NSApp hideOtherApplications:self];
|
|
return [WebUndefined undefined];
|
|
}
|
|
|
|
- (id)openPanel
|
|
{
|
|
NSOpenPanel * openPanel = [NSOpenPanel openPanel];
|
|
|
|
NSInteger result = [openPanel runModal];
|
|
|
|
NSMutableString * resultObject = [NSMutableString stringWithFormat:@"({ button:%d, URLs:", result];
|
|
|
|
NSMutableArray * fileSystemURLs = [NSMutableArray array];
|
|
|
|
for (NSURL * URL in [openPanel URLs])
|
|
[fileSystemURLs addObject:[URL HTTPFileSystemURL]];
|
|
|
|
if (result == NSFileHandlingPanelOKButton)
|
|
[resultObject appendString:[NSString stringWithFormat:@"[\"%@\"] })", [fileSystemURLs componentsJoinedByString:@"\", \""]]];
|
|
|
|
else
|
|
[resultObject appendString:@"[] })"];
|
|
|
|
return [[webView windowScriptObject] evaluateWebScript:resultObject];
|
|
}
|
|
|
|
- (id)savePanel:(NSArray *)arguments
|
|
{
|
|
NSSavePanel * savePanel = [NSSavePanel savePanel];
|
|
WebScriptObject *args = [arguments objectAtIndex:0];
|
|
|
|
[savePanel setAllowedFileTypes:[BridgedMethods arrayFromWebScriptObject:[args valueForKey:@"allowedFileTypes"]]];
|
|
|
|
id allowsOtherFileTypes = [args valueForKey:@"allowsOtherFileTypes"];
|
|
|
|
[savePanel setAllowsOtherFileTypes:allowsOtherFileTypes && [allowsOtherFileTypes webBoolValue]];
|
|
|
|
id isExtensionHidden = [args valueForKey:@"isExtensionHidden"];
|
|
|
|
[savePanel setExtensionHidden:isExtensionHidden && [isExtensionHidden webBoolValue]];
|
|
|
|
id canSelectHiddenExtension = [args valueForKey:@"canSelectHiddenExtension"];
|
|
|
|
[savePanel setCanSelectHiddenExtension:canSelectHiddenExtension && canSelectHiddenExtension];
|
|
|
|
id canCreateDirectories = [args valueForKey:@"canCreateDirectories"];
|
|
|
|
[savePanel setCanCreateDirectories:canCreateDirectories && [canCreateDirectories webBoolValue]];
|
|
|
|
NSInteger result = [savePanel runModal];
|
|
|
|
return [[webView windowScriptObject] evaluateWebScript:[NSString stringWithFormat:@"({ button:%d, URL:\"%@\" })", result, [[[savePanel URL] HTTPFileSystemURL] absoluteString]]];
|
|
}
|
|
|
|
- (id)clearRecentDocuments
|
|
{
|
|
[[NSDocumentController sharedDocumentController] clearRecentDocuments:self];
|
|
return [WebUndefined undefined];
|
|
}
|
|
|
|
- (id)noteNewRecentDocumentPath:(NSArray *)arguments
|
|
{
|
|
if (![arguments count])
|
|
return [WebUndefined undefined];
|
|
|
|
NSString *aURL = [arguments objectAtIndex:0];
|
|
NSURL *fileURL = [NSURL fileSystemURLFromHTTPFileSystemString:aURL];
|
|
|
|
[[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:fileURL];
|
|
|
|
return [WebUndefined undefined];
|
|
}
|
|
|
|
- (id)recentDocumentURLs
|
|
{
|
|
NSArray *existingURLs = [[NSDocumentController sharedDocumentController] recentDocumentURLs];
|
|
NSMutableArray *urlsAsStrings = [NSMutableArray array];
|
|
|
|
for (int i=0, count = [existingURLs count]; i < count; i++)
|
|
[urlsAsStrings addObject:[[existingURLs objectAtIndex:i] absoluteString]];
|
|
|
|
return urlsAsStrings;
|
|
}
|
|
|
|
- (id)pasteboardWithName:(NSArray *)arguments
|
|
{
|
|
if (![arguments count])
|
|
return [WebUndefined undefined];
|
|
|
|
return [WebPasteboardProxy pasteboardWithName:[arguments objectAtIndex:0]];
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation WindowMethods
|
|
|
|
- (id)miniaturize
|
|
{
|
|
[[webView window] miniaturize:nil];
|
|
return [WebUndefined undefined];
|
|
}
|
|
|
|
- (id)deminiaturize
|
|
{
|
|
[[webView window] deminiaturize:nil];
|
|
return [WebUndefined undefined];
|
|
}
|
|
|
|
- (id)level
|
|
{
|
|
return [NSNumber numberWithInt:[[webView window] level]];
|
|
}
|
|
|
|
- (id)setLevel:(NSArray *)arguments
|
|
{
|
|
[[webView window] setLevel:[[arguments objectAtIndex:0] intValue]];
|
|
|
|
return [WebUndefined undefined];
|
|
}
|
|
|
|
- (id)hasShadow
|
|
{
|
|
return [NSNumber numberWithBool:[[webView window] hasShadow]];
|
|
}
|
|
|
|
- (id)setHasShadow:(NSArray *)arguments
|
|
{
|
|
[[webView window] setHasShadow:[[arguments objectAtIndex:0] boolValue]];
|
|
|
|
return [WebUndefined undefined];
|
|
}
|
|
|
|
- (id)frame
|
|
{
|
|
NSRect frame = [[webView window] frame];
|
|
|
|
return [[webView windowScriptObject] evaluateWebScript:[NSString stringWithFormat:@"({ origin:{%f, %f}, size:{%f, %f}})", NSMinX(frame), NSMinY(frame), NSWidth(frame), NSHeight(frame)]];
|
|
}
|
|
|
|
- (id)setFrame:(NSArray *)arguments
|
|
{
|
|
id origin = [[arguments objectAtIndex:0] valueForKey:@"origin"],
|
|
size = [[arguments objectAtIndex:0] valueForKey:@"size"];
|
|
|
|
NSWindow * window = [webView window];
|
|
NSScreen * screen = [window screen];
|
|
|
|
if (!screen)
|
|
screen = [NSScreen mainScreen]; // Is this correct?
|
|
|
|
float height = [[size valueForKey:@"height"] floatValue];
|
|
|
|
[[webView window] setFrame:NSMakeRect([[origin valueForKey:@"x"] floatValue], NSMaxY([screen frame]) - [[origin valueForKey:@"y"] floatValue] - height, [[size valueForKey:@"width"] floatValue], height) display:YES];
|
|
/*
|
|
NSLog([webView description]);
|
|
NSLog(@"%@ %@", [window screen], NSStringFromRect([window frame]));
|
|
NSLog(@"%f - %f - %f = %f", NSMaxY([[window screen] frame]), [[origin valueForKey:@"y"] floatValue], height, NSMaxY([[window screen] frame]) - [[origin valueForKey:@"y"] floatValue] - height);
|
|
NSLog(@"FROM: %@", NSStringFromRect(NSMakeRect([[origin valueForKey:@"x"] floatValue], [[origin valueForKey:@"y"] floatValue], [[size valueForKey:@"width"] floatValue], height)));
|
|
NSLog(@" TO: %@", NSStringFromRect([[webView window] frame]));
|
|
*/
|
|
|
|
return [WebUndefined undefined];
|
|
}
|
|
|
|
- (id)shadowStyle
|
|
{
|
|
WebWindow * window = (WebWindow *)[webView window];
|
|
|
|
return [NSNumber numberWithInt:[window shadowStyle]];
|
|
}
|
|
|
|
- (id)setShadowStyle:(id)arguments
|
|
{
|
|
int type = [[arguments objectAtIndex:0] intValue];
|
|
|
|
WebWindow * window = (WebWindow *)[webView window];
|
|
|
|
[window setShadowStyle:type];
|
|
|
|
return [WebUndefined undefined];
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
@interface WindowScriptObjectMethod : NSObject
|
|
{
|
|
WebView * webView;
|
|
}
|
|
|
|
- (id)initWithWebView:(WebView *)aWebView;
|
|
|
|
@end
|
|
|
|
@implementation WindowScriptObjectMethod
|
|
|
|
- (id)initWithWebView:(WebView *)aWebView
|
|
{
|
|
self = [super init];
|
|
|
|
if (self)
|
|
webView = aWebView;
|
|
|
|
return self;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation BridgedMethods
|
|
|
|
+ (NSMutableArray *)arrayFromWebScriptObject:(WebScriptObject *)incomingObject
|
|
{
|
|
if (!incomingObject)
|
|
return nil;
|
|
|
|
NSMutableArray * newItems = [[NSMutableArray alloc] init];
|
|
|
|
for (int i=0; [incomingObject webScriptValueAtIndex:i]!=[WebUndefined undefined]; i++)
|
|
{
|
|
id oneItem =[incomingObject webScriptValueAtIndex:i];
|
|
[newItems addObject:oneItem];
|
|
}
|
|
|
|
return [newItems autorelease];
|
|
}
|
|
|
|
+ (void)enhanceWindowObject:(WebScriptObject *)aWindowObject ofWebView:(WebView *)aWebView
|
|
{
|
|
NSDictionary * classMethods = [MethodClasses objectForKey:[self className]];
|
|
NSString * key = nil;
|
|
NSEnumerator * keyEnumerator = [classMethods keyEnumerator];
|
|
|
|
while (key = [keyEnumerator nextObject])
|
|
[aWindowObject setValue:[(WindowScriptObjectMethod *)[[[classMethods objectForKey:key] alloc] initWithWebView:aWebView] autorelease] forKey:key];
|
|
}
|
|
|
|
+ (void)bridgeMethod:(Method)aMethod dictionary:(NSMutableDictionary *)aDictionary
|
|
{
|
|
NSString * methodName = NSStringFromSelector(method_getName(aMethod)),
|
|
* publicMethodName = [NSString stringWithFormat:@"cp%@", [[NSString stringWithFormat:@"%@%@", [[methodName substringToIndex:1] uppercaseString], [methodName substringFromIndex:1]] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@":"]]];
|
|
|
|
Class methodClass = objc_allocateClassPair([WindowScriptObjectMethod class], [[NSString stringWithFormat:@"WebScriptObjectMethod_%@", publicMethodName] cString], 0);
|
|
|
|
class_addMethod(methodClass, @selector(invokeDefaultMethodWithArguments:), method_getImplementation(aMethod), "@@:@");
|
|
|
|
objc_registerClassPair(methodClass);
|
|
|
|
[aDictionary setObject:methodClass forKey:publicMethodName];
|
|
}
|
|
|
|
+ (void)initialize
|
|
{
|
|
if (!MethodClasses)
|
|
MethodClasses = [[NSMutableDictionary alloc] init];
|
|
|
|
NSMutableDictionary * dictionary = [[NSMutableDictionary alloc] init];
|
|
|
|
[MethodClasses setObject:dictionary forKey:[self className]];
|
|
[dictionary release];
|
|
|
|
unsigned int methodCount = 0;
|
|
Method * methods = class_copyMethodList(self, &methodCount);
|
|
|
|
if (!methods)
|
|
return;
|
|
|
|
int index = 0;
|
|
|
|
for (; index < methodCount; ++index)
|
|
[self bridgeMethod:methods[index] dictionary:dictionary];
|
|
|
|
free(methods);
|
|
methods = NULL;
|
|
}
|
|
|
|
@end
|