diff --git a/Atom/Classes/AtomApp.m b/Atom/Classes/AtomApp.m index a8754b25d..414c28e1b 100644 --- a/Atom/Classes/AtomApp.m +++ b/Atom/Classes/AtomApp.m @@ -4,6 +4,8 @@ #import +#define ATOM_USER_PATH @"~/.atomicity/" + @implementation AtomApp @synthesize controllers; @@ -11,6 +13,7 @@ - (AtomController *)createController:(NSString *)path { AtomController *controller = [[AtomController alloc] initWithPath:path]; [controllers addObject:controller]; + [controller.window makeKeyAndOrderFront:self]; return controller; } @@ -18,15 +21,43 @@ [controllers removeObject:controller]; } +- (void)open:(NSString *)path { + if (!path) { + NSOpenPanel *panel =[NSOpenPanel openPanel]; + panel.canChooseDirectories = YES; + if (panel.runModal != NSFileHandlingPanelOKButton) return; + + path = [[[panel URLs] lastObject] path]; + } + + for (AtomController *controller in controllers) { + JSValueRef value = [controller.jscocoa callJSFunctionNamed:@"canOpen" withArguments:path , nil]; + if ([controller.jscocoa toBool:value]) { + [controller.jscocoa callJSFunctionNamed:@"open" withArguments:path, nil]; + return; + } + } + + [self createController:path]; +} + +// Events in the "app:*" namespace get sent to all controllers +- (void)triggerGlobalEvent:(NSString *)name data:(id)data { + for (AtomController *controller in controllers) { + [controller.jscocoa callJSFunctionNamed:@"triggerEvent" withArguments:name, data, false, nil]; + } +} + // Overridden - (void)sendEvent:(NSEvent *)event { if ([event type] == NSKeyDown) { BOOL handeled = NO; - id controller = [[self keyWindow] windowController]; + AtomController *controller = [[self keyWindow] windowController]; // The keyWindow could be a Cocoa Dialog or something, ignore that. if ([controller isKindOfClass:[AtomController class]]) { - handeled = [controller handleKeyEvent:event]; + JSValueRef value = [controller.jscocoa callJSFunctionNamed:@"handleKeyEvent" withArguments:event, nil]; + handeled = [controller.jscocoa toBool:value]; } if (!handeled) [super sendEvent:event]; @@ -38,9 +69,11 @@ // AppDelegate - (void)applicationWillFinishLaunching:(NSNotification *)aNotification { + self.controllers = [NSMutableArray array]; + // Hack to make localStorage work WebPreferences* prefs = [WebPreferences standardPreferences]; - [prefs _setLocalStorageDatabasePath:@"~/.atomicity/storage"]; + [prefs _setLocalStorageDatabasePath:ATOM_USER_PATH @"storage"]; [prefs setLocalStorageEnabled:YES]; NSDictionary *defaults = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], @"WebKitDeveloperExtras", nil]; @@ -48,8 +81,7 @@ } - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { - AtomController *controller = [self createController:NULL]; - [controller window]; + [self createController:NULL]; } @end diff --git a/Atom/Classes/AtomController.h b/Atom/Classes/AtomController.h index 2317c1a1b..01350b5e6 100644 --- a/Atom/Classes/AtomController.h +++ b/Atom/Classes/AtomController.h @@ -4,15 +4,12 @@ @class WebView; @interface AtomController : NSWindowController { - IBOutlet WebView *webView; - NSString *path; - JSCocoa* jscocoa; } -@property (retain) IBOutlet WebView *webView; +@property (retain) WebView *webView; @property (retain) NSString *path; +@property (retain) JSCocoa *jscocoa; - (AtomController *)initWithPath:(NSString *)aPath; -- (BOOL)handleKeyEvent:(NSEvent *)event; @end diff --git a/Atom/Classes/AtomController.m b/Atom/Classes/AtomController.m index bff481682..03f2d3859 100644 --- a/Atom/Classes/AtomController.m +++ b/Atom/Classes/AtomController.m @@ -6,7 +6,7 @@ @implementation AtomController -@synthesize webView, path; +@synthesize webView, path, jscocoa; - (void)dealloc { [jscocoa unlinkAllReferences]; @@ -21,7 +21,7 @@ - (id)initWithPath:(NSString *)aPath { self = [super initWithWindowNibName:@"AtomWindow"]; - [self setPath:aPath]; + [self setPath:[aPath stringByStandardizingPath]]; return self; } @@ -34,7 +34,7 @@ [self setShouldCascadeWindows:YES]; [self setWindowFrameAutosaveName:@"atomController"]; - jscocoa = [[JSCocoa alloc] initWithGlobalContext:[[webView mainFrame] globalContext]]; + jscocoa = [[JSCocoa alloc] initWithGlobalContext:[[webView mainFrame] globalContext]]; [jscocoa setObject:self withName:@"atomController"]; NSURL *resourceURL = [[NSBundle mainBundle] resourceURL]; @@ -48,16 +48,9 @@ [super close]; } -- (BOOL)handleKeyEvent:(NSEvent *)event { - // ICKY: Using a global function defined in App.js to deal with key events - JSValueRef returnValue = [jscocoa callJSFunctionNamed:@"handleKeyEvent" withArguments:event, nil]; - return [jscocoa toBool:returnValue]; -} - // WebUIDelegate Protocol - (NSArray *)webView:(WebView *)sender contextMenuItemsForElement:(NSDictionary *)element defaultMenuItems:(NSArray *)defaultMenuItems { return defaultMenuItems; } - @end diff --git a/src/app.coffee b/src/app.coffee index ada16169d..860bf00ea 100644 --- a/src/app.coffee +++ b/src/app.coffee @@ -1,4 +1,5 @@ KeyBinder = require 'key-binder' +fs = require 'fs' require 'window' module.exports = @@ -7,5 +8,8 @@ class App KeyBinder.register "app", @ window.startup() + @open: (path) -> + OSX.NSApp.open path + @quit: -> OSX.NSApp.terminate null diff --git a/src/event.coffee b/src/event.coffee index dcfe60155..7220c548c 100644 --- a/src/event.coffee +++ b/src/event.coffee @@ -12,7 +12,11 @@ class Event @off: (name, callback) -> window.document.removeEventListener name, callback - @trigger: (name, data) -> + @trigger: (name, data, bubbleToApp=true) -> + if bubbleToApp and name.match /^app:/ + OSX.NSApp.triggerGlobalEvent_data name, data + return + event = @events[name] if not event event = window.document.createEvent "CustomEvent" diff --git a/src/window.coffee b/src/window.coffee index e2eba8565..4160884d3 100644 --- a/src/window.coffee +++ b/src/window.coffee @@ -5,7 +5,7 @@ Native = require 'native' fs = require 'fs' -# This file is a weirdo. We don't create a Window class, we just add stuff to +# This a weirdo file. We don't create a Window class, we just add stuff to # the DOM window. windowAdditions = editor: null @@ -14,14 +14,18 @@ windowAdditions = appRoot: OSX.NSBundle.mainBundle.resourcePath - path: null - startup: () -> - @path = atomController.path ? @recentPath() + if atomController.path + @setRecentPath atomController.path + else + atomController.path = @recentPath() KeyBinder.register "window", window - @editor = new Editor @path + @editor = if fs.isFile atomController.path + new Editor atomController.path + else + new Editor @tmpFile() @loadExtensions() @@ -50,31 +54,49 @@ windowAdditions = console.warn error recentPath: -> - localStorage.lastOpenedPath ? "/tmp/atom" + localStorage.lastOpenedPath ? @tmpFile() setRecentPath: (path) -> localStorage.lastOpenedPath = path - handleKeyEvent: -> - KeyBinder.handleEvent.apply KeyBinder, arguments + tmpFile: -> + "/tmp/atom" showConsole: -> atomController.webView.inspector.showConsole true reload: -> @close() - Native.newWindow @path + Native.newWindow atomController.path open: (path) -> - path = Native.openPanel() if not path - if path - @path = path - @setRecentPath path + atomController.window.makeKeyAndOrderFront atomController + + if fs.isFile path Event.trigger 'window:open', path close: -> atomController.close + # Global methods that are used by the cocoa side of things + handleKeyEvent: -> + KeyBinder.handleEvent.apply KeyBinder, arguments + + triggerEvent: -> + Event.trigger.apply Event, arguments + + canOpen: (path) -> + parent = atomController.path.replace(/([^\/])$/, "$1/") + child = path.replace(/([^\/])$/, "$1/") + + console.log parent + console.log child + window.x = parent + window.y = child + + # If the child is contained by the parent, it can be opened by this window + return child.match "^" + parent + for key, value of windowAdditions console.warn "DOMWindow already has a key named `#{key}`" if window[key] window[key] = value diff --git a/static/key-bindings.coffee b/static/key-bindings.coffee index d21df22df..5f39681f1 100644 --- a/static/key-bindings.coffee +++ b/static/key-bindings.coffee @@ -1,11 +1,10 @@ app: 'cmd-q': (app) -> app.quit() - 'cmd-j': (app) -> console.log "OMG YOU TOUCHED THE LETTER J!" + 'cmd-o': (app) -> app.open() window: 'cmd-shift-i': (window) -> window.showConsole() 'cmd-w': (window) -> window.close() - 'cmd-o': (window) -> window.open() 'cmd-r': (window) -> window.reload() editor: