Browse Source

staging the webview extension code so that it will be ready to receive a project unloaded event message, a delete resource event message, and a rename resource event message. Also did some cleanup to reduce duplicate code

Shaddock Heath 9 years ago
parent
commit
b77f5ab2de

+ 18 - 0
Script/AtomicWebViewEditor/clientExtensions/ClientExtensionEventNames.ts

@@ -0,0 +1,18 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// LICENSE: Atomic Game Engine Editor and Tools EULA
+// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
+// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
+//
+
+/**
+ * All of the publicly available events that client extensions listen to
+ */
+export default class ClientExtensionEventNames {
+    static CodeLoadedEvent = "CodeLoadedEvent";
+    static ConfigureEditorEvent = "ConfigureEditorEvent";
+    static ResourceSavedEvent = "ResourceSavedEvent";
+    static ResourceRenamedEvent = "ResourceRenamedEvent";
+    static ResourceDeletedEvent = "ResourceDeletedEvent";
+    static ProjectUnloadedEvent = "ProjectUnloadedEvent";
+}

+ 76 - 3
Script/AtomicWebViewEditor/clientExtensions/ClientExtensionServices.ts

@@ -5,8 +5,9 @@
 // license information: https://github.com/AtomicGameEngine/AtomicGameEngine
 //
 
-// Entry point for web view extensions -- extensions that live inside the web view
+import ClientExtensionEventNames from "./ClientExtensionEventNames";
 
+// Entry point for web view extensions -- extensions that live inside the web view
 interface EventSubscription {
     eventName: string;
     callback: (data: any) => any;
@@ -34,6 +35,7 @@ export class EventDispatcher implements Editor.Extensions.EventDispatcher {
     }
 }
 
+
 /**
  * Generic registry for storing Editor Extension Services
  */
@@ -56,8 +58,11 @@ export class ExtensionServiceRegistry extends ServiceRegistry<Editor.ClientExten
      * @param  {EventDispatcher} eventDispatcher The global event dispatcher
      */
     subscribeToEvents(eventDispatcher: Editor.Extensions.EventDispatcher) {
-        eventDispatcher.subscribeToEvent("CodeLoadedNotification", (ev) => this.codeLoaded(ev));
-        eventDispatcher.subscribeToEvent("ConfigureEditor", (ev) => this.configureEditor(ev));
+        eventDispatcher.subscribeToEvent(ClientExtensionEventNames.CodeLoadedEvent, (ev) => this.codeLoaded(ev));
+        eventDispatcher.subscribeToEvent(ClientExtensionEventNames.ConfigureEditorEvent, (ev) => this.configureEditor(ev));
+        eventDispatcher.subscribeToEvent(ClientExtensionEventNames.ResourceRenamedEvent, (ev) => this.renameResource(ev));
+        eventDispatcher.subscribeToEvent(ClientExtensionEventNames.ProjectUnloadedEvent, (ev) => this.projectUnloaded());
+        eventDispatcher.subscribeToEvent(ClientExtensionEventNames.ResourceDeletedEvent, (ev) => this.deleteResource(ev));
     }
 
     /**
@@ -77,6 +82,57 @@ export class ExtensionServiceRegistry extends ServiceRegistry<Editor.ClientExten
         });
     }
 
+    /**
+     * Called after a resource has been saved
+     * @param  {Editor.EditorEvents.SaveResourceEvent} ev
+     */
+    saveResource(ev: Editor.EditorEvents.SaveResourceEvent) {
+        // run through and find any services that can handle this.
+        this.registeredServices.forEach((service) => {
+            try {
+                // Verify that the service contains the appropriate methods and that it can save
+                if (service.save) {
+                    service.save(ev);
+                }
+            } catch (e) {
+                alert(`Error detected in extension ${service.name}\n \n ${e.stack}`);
+            }
+        });
+    }
+
+    /**
+     * Called when a resource has been deleted
+     */
+    deleteResource(ev: Editor.EditorEvents.DeleteResourceEvent) {
+        this.registeredServices.forEach((service) => {
+            try {
+                // Verify that the service contains the appropriate methods and that it can delete
+                if (service.delete) {
+                    service.delete(ev);
+                }
+            } catch (e) {
+                alert(`Error detected in extension ${service.name}\n \n ${e.stack}`);
+            }
+        });
+    }
+
+    /**
+     * Called when a resource has been renamed
+     * @param  {Editor.EditorEvents.RenameResourceEvent} ev
+     */
+    renameResource(ev: Editor.EditorEvents.RenameResourceEvent) {
+        this.registeredServices.forEach((service) => {
+            try {
+                // Verify that the service contains the appropriate methods and that it can handle the rename
+                if (service.rename) {
+                    service.rename(ev);
+                }
+            } catch (e) {
+                alert(`Error detected in extension ${service.name}\n \n ${e.stack}`);
+            }
+        });
+    }
+
     /**
      * Called when the editor is requesting to be configured for a particular file
      * @param  {Editor.EditorEvents.EditorFileEvent} ev
@@ -93,4 +149,21 @@ export class ExtensionServiceRegistry extends ServiceRegistry<Editor.ClientExten
             }
         });
     }
+
+
+    /**
+     * Called when the project is unloaded
+     */
+    projectUnloaded() {
+        this.registeredServices.forEach((service) => {
+            // Notify services that the project has been unloaded
+            try {
+                if (service.projectUnloaded) {
+                    service.projectUnloaded();
+                }
+            } catch (e) {
+                alert(`Extension Error:\n Error detected in extension ${service.name}\n \n ${e.stack}`);
+            }
+        });
+    }
 }

+ 5 - 0
Script/AtomicWebViewEditor/clientExtensions/languageExtensions/javascript/JavascriptLanguageExtension.ts

@@ -40,6 +40,11 @@ export default class JavascriptLanguageExtension implements Editor.ClientExtensi
         if (this.isValidFiletype(ev.filename)) {
             let editor = <AceAjax.Editor>ev.editor;
             editor.session.setMode("ace/mode/javascript");
+
+            editor.setOptions({
+                enableBasicAutocompletion: true,
+                enableLiveAutocompletion: true
+            });
         }
     }
 }

+ 83 - 57
Script/AtomicWebViewEditor/clientExtensions/languageExtensions/typescript/TypescriptLanguageExtension.ts

@@ -7,7 +7,8 @@
 // Based upon the TypeScript language services example at https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#incremental-build-support-using-the-language-services
 
 import * as ts from "../../../modules/typescript";
-import * as WorkerProcessCommands from "./workerprocess/workerProcessCommands";
+import * as WorkerProcessTypes from "./workerprocess/workerProcessTypes";
+import ClientExtensionEventNames from "../../ClientExtensionEventNames";
 
 /**
  * Resource extension that handles compiling or transpling typescript on file save.
@@ -65,7 +66,7 @@ export default class TypescriptLanguageExtension implements Editor.ClientExtensi
         let worker = this.worker;
 
         return new Promise((resolve, reject) => {
-            const responseCallback = function(e: WorkerProcessCommands.WorkerProcessMessage<any>) {
+            const responseCallback = function(e: WorkerProcessTypes.WorkerProcessMessage<any>) {
                 if (e.data.command == responseChannel) {
                     worker.port.removeEventListener("message", responseCallback);
                     resolve(e.data);
@@ -82,8 +83,15 @@ export default class TypescriptLanguageExtension implements Editor.ClientExtensi
      */
     configureEditor(ev: Editor.EditorEvents.EditorFileEvent) {
         if (this.isValidFiletype(ev.filename)) {
-            this.editor = <AceAjax.Editor>ev.editor;
-            this.editor.session.setMode("ace/mode/typescript");
+            let editor = <AceAjax.Editor>ev.editor;
+            editor.session.setMode("ace/mode/typescript");
+
+            editor.setOptions({
+                enableBasicAutocompletion: true,
+                enableLiveAutocompletion: true
+            });
+
+            this.editor = editor; // cache this so that we can reference it later
         }
     }
 
@@ -105,21 +113,20 @@ export default class TypescriptLanguageExtension implements Editor.ClientExtensi
             this.buildWorker();
 
             // post a message to the shared web worker
-            this.worker.port.postMessage({ command: WorkerProcessCommands.Connect, sender: "Typescript Language Extension", filename: ev.filename });
+            this.worker.port.postMessage({ command: WorkerProcessTypes.Connect, sender: "Typescript Language Extension", filename: ev.filename });
         }
     }
 
     /**
      * Handler for any messages initiated by the worker process
-     * @param  {any} e
-     * @return {[type]}
+     * @param  {WorkerProcessTypes.WorkerProcessMessage} e
      */
-    handleWorkerMessage(e: WorkerProcessCommands.WorkerProcessMessage<any>) {
+    handleWorkerMessage(e: WorkerProcessTypes.WorkerProcessMessage<any>) {
         switch (e.data.command) {
-            case WorkerProcessCommands.Message:
+            case WorkerProcessTypes.Message:
                 console.log(e.data.message);
                 break;
-            case WorkerProcessCommands.Alert:
+            case WorkerProcessTypes.Alert:
                 alert(e.data.message);
                 break;
         }
@@ -137,7 +144,7 @@ export default class TypescriptLanguageExtension implements Editor.ClientExtensi
 
         // Tell the SharedWorker we're closing
         addEventListener("beforeunload", () => {
-            this.worker.port.postMessage({ command: WorkerProcessCommands.Disconnect });
+            this.worker.port.postMessage({ command: WorkerProcessTypes.Disconnect });
         });
 
         this.worker.port.start();
@@ -146,19 +153,17 @@ export default class TypescriptLanguageExtension implements Editor.ClientExtensi
     /**
      * Builds the word completer for the Ace Editor.  This will handle determining which items to display in the popup and in which order
      * @param  {string} filename the filename of the current file
-     * @param  {TypescriptLanguageService} langService The language service that handles compilation, completion resolution, etc.
-     * @param  {FileSystemInterface} fs the interface into the file system
      * @return {[type]} returns a completer
      */
     private buildWordCompleter(filename: string): {
-        getDocTooltip?: (selected: WorkerProcessCommands.WordCompletion) => void,
+        getDocTooltip?: (selected: WorkerProcessTypes.WordCompletion) => void,
         getCompletions: (editor, session, pos, prefix, callback) => void
     } {
         let extension = this;
         let wordCompleter = {
-            getDocTooltip: function(selected: WorkerProcessCommands.WordCompletion) {
-                const message: WorkerProcessCommands.GetDocTooltipMessageData = {
-                    command: WorkerProcessCommands.GetDocTooltip,
+            getDocTooltip: function(selected: WorkerProcessTypes.WordCompletion) {
+                const message: WorkerProcessTypes.GetDocTooltipMessageData = {
+                    command: WorkerProcessTypes.GetDocTooltip,
                     filename: extension.filename,
                     completionItem: selected,
                     pos: selected.pos
@@ -167,23 +172,23 @@ export default class TypescriptLanguageExtension implements Editor.ClientExtensi
                 // Since the doc tooltip built in function of Ace doesn't support async calls to retrieve the tootip,
                 // we need to go ahead and call the worker and then force the display of the tooltip when we get
                 // a result back
-                extension.workerRequest(WorkerProcessCommands.DocTooltipResponse, message)
-                    .then((e: WorkerProcessCommands.GetDocTooltipResponseMessageData) => {
+                extension.workerRequest(WorkerProcessTypes.DocTooltipResponse, message)
+                    .then((e: WorkerProcessTypes.GetDocTooltipResponseMessageData) => {
                     extension.editor.completer.showDocTooltip(e);
                 });
             },
 
             getCompletions: function(editor, session, pos, prefix, callback) {
-                const message: WorkerProcessCommands.GetCompletionsMessageData = {
-                    command: WorkerProcessCommands.GetCompletions,
+                const message: WorkerProcessTypes.GetCompletionsMessageData = {
+                    command: WorkerProcessTypes.GetCompletions,
                     filename: extension.filename,
                     pos: pos,
                     sourceText: editor.session.getValue(),
                     prefix: prefix
                 };
 
-                extension.workerRequest(WorkerProcessCommands.CompletionResponse, message)
-                    .then((e: WorkerProcessCommands.GetCompletionsResponseMessageData) => {
+                extension.workerRequest(WorkerProcessTypes.CompletionResponse, message)
+                    .then((e: WorkerProcessTypes.GetCompletionsResponseMessageData) => {
                     callback(null, e.completions);
                 });
             }
@@ -191,52 +196,73 @@ export default class TypescriptLanguageExtension implements Editor.ClientExtensi
         return wordCompleter;
     }
 
-    /*** ResourceService implementation ****/
-
     /**
      * Called once a resource has been saved
      * @param  {Editor.EditorEvents.SaveResourceEvent} ev
      */
-    // save(ev: Editor.EditorEvents.SaveResourceEvent) {
-    //     if (this.isValidFiletype(ev.path)) {
-    //         console.log(`${this.name}: received a save resource event for ${ev.path}`);
-    //         this.worker.port.postMessage({
-    //             command: WorkerProcessCommands.Save,
-    //             path: ev.path
-    //         });
-    //     }
-    // }
+    save(ev: Editor.EditorEvents.SaveResourceEvent) {
+        if (this.isValidFiletype(ev.path)) {
+            console.log(`${this.name}: received a save resource event for ${ev.path}`);
+
+            const message: WorkerProcessTypes.SaveMessageData = {
+                command: ClientExtensionEventNames.ResourceSavedEvent,
+                path: ev.path
+            };
+
+            this.worker.port.postMessage(message);
+        }
+    }
 
     /**
      * Handle the delete.  This should delete the corresponding javascript file
      * @param  {Editor.EditorEvents.DeleteResourceEvent} ev
      */
-    // delete(ev: Editor.EditorEvents.DeleteResourceEvent) {
-    //     if (this.isValidFiletype(ev.path)) {
-    //         console.log(`${this.name}: received a delete resource event`);
-    //
-    //         // notify the typescript language service that the file has been deleted
-    //         this.worker.port.postMessage({
-    //             command: WorkerProcessCommands.Delete,
-    //             path: ev.path
-    //         });
-    //     }
-    // }
+    delete(ev: Editor.EditorEvents.DeleteResourceEvent) {
+        if (this.isValidFiletype(ev.path)) {
+            console.log(`${this.name}: received a delete resource event`);
+
+            // notify the typescript language service that the file has been deleted
+            const message: WorkerProcessTypes.DeleteMessageData = {
+                command: ClientExtensionEventNames.ResourceDeletedEvent,
+                path: ev.path
+            };
+
+            this.worker.port.postMessage(message);
+        }
+    }
 
     /**
      * Handle the rename.  Should rename the corresponding .js file
      * @param  {Editor.EditorEvents.RenameResourceEvent} ev
      */
-    // rename(ev: Editor.EditorEvents.RenameResourceEvent) {
-    //     if (this.isValidFiletype(ev.path)) {
-    //         console.log(`${this.name}: received a rename resource event`);
-    //
-    //         // notify the typescript language service that the file has been renamed
-    //         this.worker.port.postMessage({
-    //             command: WorkerProcessCommands.Rename,
-    //             path: ev.path,
-    //             newPath: ev.newPath
-    //         });
-    //     }
-    // }
+    rename(ev: Editor.EditorEvents.RenameResourceEvent) {
+        if (this.isValidFiletype(ev.path)) {
+            console.log(`${this.name}: received a rename resource event`);
+
+            // notify the typescript language service that the file has been renamed
+            const message: WorkerProcessTypes.RenameMessageData = {
+                command: ClientExtensionEventNames.ResourceRenamedEvent,
+                path: ev.path,
+                newPath: ev.newPath
+            };
+
+            this.worker.port.postMessage(message);
+        }
+    }
+
+    /**
+     * Handle when the project is unloaded so that resources can be freed
+     */
+    projectUnloaded() {
+        if (this.worker) {
+
+            console.log(`${this.name}: received a project unloaded event`);
+
+            const message: WorkerProcessTypes.WorkerProcessMessageData = {
+                command: ClientExtensionEventNames.ProjectUnloadedEvent
+            };
+
+            this.worker.port.postMessage(message);
+        }
+    }
 }

+ 65 - 14
Script/AtomicWebViewEditor/clientExtensions/languageExtensions/typescript/workerprocess/TypescriptLanguageServiceWebWorker.ts

@@ -11,7 +11,8 @@
  */
 import * as ts from "../../../../modules/typescript";
 import {TypescriptLanguageService, FileSystemInterface} from "./TypescriptLanguageService";
-import * as WorkerProcessCommands from "./workerProcessCommands";
+import * as WorkerProcessTypes from "./workerProcessTypes";
+import ClientExtensionEventNames from "../../../ClientExtensionEventNames";
 
 interface TSConfigFile {
     compilerOptions?: ts.CompilerOptions;
@@ -137,20 +138,32 @@ export default class TypescriptLanguageServiceWebWorker {
         let port: MessagePort = e.ports[0];
         this.connections++;
 
-        port.addEventListener("message", (e:WorkerProcessCommands.WorkerProcessMessage<any>) => {
+        port.addEventListener("message", (e: WorkerProcessTypes.WorkerProcessMessage<any>) => {
             switch (e.data.command) {
-                case WorkerProcessCommands.Connect:
+                case WorkerProcessTypes.Connect:
                     this.handleHELO(port, e.data);
                     break;
-                case WorkerProcessCommands.Disconnect:
+                case WorkerProcessTypes.Disconnect:
                     this.handleCLOSE(port, e.data);
                     break;
-                case WorkerProcessCommands.GetCompletions:
+                case WorkerProcessTypes.GetCompletions:
                     this.handleGetCompletions(port, e.data);
                     break;
-                case WorkerProcessCommands.GetDocTooltip:
+                case WorkerProcessTypes.GetDocTooltip:
                     this.handleGetDocTooltip(port, e.data);
                     break;
+                case ClientExtensionEventNames.ResourceSavedEvent:
+                    this.handleSave(port, e.data);
+                    break;
+                case ClientExtensionEventNames.ResourceRenamedEvent:
+                    this.handleRename(port, e.data);
+                    break;
+                case ClientExtensionEventNames.ResourceDeletedEvent:
+                    this.handleDelete(port, e.data);
+                    break;
+                case ClientExtensionEventNames.ProjectUnloadedEvent:
+                    this.handleProjectUnloaded(port);
+                    break;
             }
 
         }, false);
@@ -207,7 +220,7 @@ export default class TypescriptLanguageServiceWebWorker {
         sender: string,
         filename: string
     }) {
-        port.postMessage({ command: WorkerProcessCommands.Message, message: "Hello " + eventData.sender + " (port #" + this.connections + ")" });
+        port.postMessage({ command: WorkerProcessTypes.Message, message: "Hello " + eventData.sender + " (port #" + this.connections + ")" });
         this.loadProjectFiles().then(() => {
             this.languageService.compile([eventData.filename]);
         });
@@ -231,14 +244,14 @@ export default class TypescriptLanguageServiceWebWorker {
      * @param  {MessagePort} port
      * @param  {WorkerProcessCommands.GetCompletionsMessage} eventData
      */
-    handleGetCompletions(port: MessagePort, eventData: WorkerProcessCommands.GetCompletionsMessageData) {
+    handleGetCompletions(port: MessagePort, eventData: WorkerProcessTypes.GetCompletionsMessageData) {
         let sourceFile = this.languageService.updateProjectFile(eventData.filename, eventData.sourceText);
 
         let newpos = this.languageService.getPositionOfLineAndCharacter(sourceFile, eventData.pos.row, eventData.pos.column);
         let completions = this.languageService.getCompletions(eventData.filename, newpos);
 
-        let message: WorkerProcessCommands.GetCompletionsResponseMessageData = {
-            command: WorkerProcessCommands.CompletionResponse,
+        let message: WorkerProcessTypes.GetCompletionsResponseMessageData = {
+            command: WorkerProcessTypes.CompletionResponse,
             completions: []
         };
         let langService = this.languageService;
@@ -246,7 +259,7 @@ export default class TypescriptLanguageServiceWebWorker {
         if (completions) {
             message.completions = completions.entries.map((completion: ts.CompletionEntry) => {
                 let value = completion.name;
-                let completionItem: WorkerProcessCommands.WordCompletion = {
+                let completionItem: WorkerProcessTypes.WordCompletion = {
                     caption: completion.name,
                     value: value,
                     score: 100 - parseInt(completion.sortText, 0),
@@ -268,9 +281,9 @@ export default class TypescriptLanguageServiceWebWorker {
      * @param  {WorkerProcessCommands.GetDocTooltipMessageData} eventData
      * @return {[type]}
      */
-    handleGetDocTooltip(port: MessagePort, eventData: WorkerProcessCommands.GetDocTooltipMessageData) {
-        let message: WorkerProcessCommands.GetDocTooltipResponseMessageData = {
-            command: WorkerProcessCommands.DocTooltipResponse
+    handleGetDocTooltip(port: MessagePort, eventData: WorkerProcessTypes.GetDocTooltipMessageData) {
+        let message: WorkerProcessTypes.GetDocTooltipResponseMessageData = {
+            command: WorkerProcessTypes.DocTooltipResponse
         };
         const details = this.languageService.getCompletionEntryDetails(eventData.filename, eventData.pos, eventData.completionItem.caption);
         if (details) {
@@ -284,4 +297,42 @@ export default class TypescriptLanguageServiceWebWorker {
 
         port.postMessage(message);
     }
+
+    /**
+     * Called when the file has been saved.
+     * @param  {MessagePort} port
+     * @param  {WorkerProcessCommands.SaveMessageData} eventData
+     */
+    handleSave(port: MessagePort, eventData: WorkerProcessTypes.SaveMessageData) {
+        // let's reload the file
+        getFileResource(eventData.path).then((code: string) => {
+            this.languageService.updateProjectFile(eventData.path, code);
+        });
+    }
+
+    /**
+     * Called when a file has been deleted
+     * @param  {MessagePort} port
+     * @param  {WorkerProcessCommands.DeleteMessageData} eventData
+     */
+    handleDelete(port: MessagePort, eventData: WorkerProcessTypes.DeleteMessageData) {
+        this.languageService.deleteProjectFile(eventData.path);
+    }
+
+    /**
+     * Called when a file has been renamed
+     * @param  {MessagePort} port
+     * @param  {WorkerProcessCommands.RenameMessageData} eventData
+     */
+    handleRename(port: MessagePort, eventData: WorkerProcessTypes.RenameMessageData) {
+        this.languageService.renameProjectFile(eventData.path, eventData.newPath);
+    }
+
+    /**
+     * Called when the project has been closed
+     * @param  {MessagePort} port
+     */
+    handleProjectUnloaded(port: MessagePort) {
+        this.reset();
+    }
 }

+ 4 - 0
Script/AtomicWebViewEditor/clientExtensions/languageExtensions/typescript/workerprocess/workerProcessCommands.ts → Script/AtomicWebViewEditor/clientExtensions/languageExtensions/typescript/workerprocess/workerProcessTypes.ts

@@ -54,3 +54,7 @@ export const Connect = "HELO";
 export const Disconnect = "CLOSE";
 export const Message = "MESSAGE";
 export const Alert = "ALERT";
+
+export interface SaveMessageData extends WorkerProcessMessageData, Editor.EditorEvents.SaveResourceEvent { }
+export interface DeleteMessageData extends WorkerProcessMessageData, Editor.EditorEvents.DeleteResourceEvent {}
+export interface RenameMessageData extends WorkerProcessMessageData, Editor.EditorEvents.RenameResourceEvent {}

+ 43 - 4
Script/AtomicWebViewEditor/editor/editorConfig.ts → Script/AtomicWebViewEditor/editor/editorCommands.ts

@@ -8,9 +8,9 @@
 import editor from "./editor";
 import serviceLocator from "../clientExtensions/ServiceLocator";
 import HostInterop from "../interop";
+import ClientExtensionEventNames from "../clientExtensions/ClientExtensionEventNames";
+
 
-const CONFIGURE_EDITOR_EVENT = "ConfigureEditor";
-const CODE_LOADED_NOTIFICATION = "CodeLoadedNotification";
 /**
  * Set the editor theme and configuration based upon the file extension
  * @param  {string} fileExt
@@ -24,13 +24,21 @@ export function configure(fileExt: string, filename: string) {
     editor.session.setMode("ace/mode/javascript");
 
     // give the language extensions the opportunity to configure the editor based upon the file type
-    serviceLocator.sendEvent(CONFIGURE_EDITOR_EVENT, {
+    serviceLocator.sendEvent(ClientExtensionEventNames.ConfigureEditorEvent, {
         fileExt: fileExt,
         filename: filename,
         editor: editor
     });
 }
 
+/**
+ * Returns the text in the editor instance
+ * @return {string}
+ */
+export function getSourceText() : string {
+    return editor.session.getValue();
+}
+
 /**
  * Loads a file of code into the editor and wires up the change events
  * @param  {string} code
@@ -45,7 +53,7 @@ export function loadCodeIntoEditor(code: string, filename: string, fileExt: stri
         HostInterop.getInstance().notifyEditorChange();
     });
 
-    serviceLocator.sendEvent(CODE_LOADED_NOTIFICATION, {
+    serviceLocator.sendEvent(ClientExtensionEventNames.CodeLoadedEvent, {
         code: code,
         filename: filename,
         fileExt: fileExt,
@@ -53,3 +61,34 @@ export function loadCodeIntoEditor(code: string, filename: string, fileExt: stri
     });
 
 }
+
+/**
+ * Called when the project is getting unloaded
+ */
+export function projectUnloaded() {
+    serviceLocator.sendEvent(ClientExtensionEventNames.ProjectUnloadedEvent, null);
+}
+
+/**
+ * Called when a resource is getting renamed
+ * @param  {string} path
+ * @param  {string} newPath
+ */
+export function resourceRenamed(path: string, newPath: string) {
+    let data:Editor.EditorEvents.RenameResourceEvent = {
+        path: path,
+        newPath: newPath
+    };
+    serviceLocator.sendEvent(ClientExtensionEventNames.ResourceRenamedEvent, data);
+}
+
+/**
+ * Called when a resource is getting deleted
+ * @param  {string} path
+ */
+export function resourceDeleted(path: string) {
+    let data:Editor.EditorEvents.DeleteResourceEvent = {
+        path: path
+    };
+    serviceLocator.sendEvent(ClientExtensionEventNames.ResourceDeletedEvent, data);
+}

+ 38 - 9
Script/AtomicWebViewEditor/interop.ts

@@ -6,8 +6,7 @@
 //
 
 // This is the interop file, exposing functions that can be called by the host game engine
-import editor from "./editor/editor";
-import * as editorConfig from "./editor/editorConfig";
+import * as editorCommands from "./editor/editorCommands";
 
 /**
  * Port to attach Chrome Dev Tools to
@@ -46,10 +45,6 @@ function atomicQueryPromise(message: any): Promise<{}> {
 }
 
 export default class HostInteropType {
-    static EDITOR_SAVE_CODE = "editorSaveCode";
-    static EDITOR_SAVE_FILE = "editorSaveFile";
-    static EDITOR_LOAD_COMPLETE = "editorLoadComplete";
-    static EDITOR_CHANGE = "editorChange";
 
     private static _inst: HostInteropType = null;
     static getInstance(): HostInteropType {
@@ -59,10 +54,19 @@ export default class HostInteropType {
         return HostInteropType._inst;
     }
 
+    static EDITOR_SAVE_CODE = "editorSaveCode";
+    static EDITOR_SAVE_FILE = "editorSaveFile";
+    static EDITOR_LOAD_COMPLETE = "editorLoadComplete";
+    static EDITOR_CHANGE = "editorChange";
+
     constructor() {
         // Set up the window object so the host can call into it
         window.HOST_loadCode = this.loadCode.bind(this);
         window.HOST_saveCode = this.saveCode.bind(this);
+
+        window.HOST_projectUnloaded = this.projectUnloaded.bind(this);
+        window.HOST_resourceRenamed = this.resourceRenamed.bind(this);
+        window.HOST_resourceDeleted = this.resourceDeleted.bind(this);
     }
 
     /**
@@ -75,11 +79,11 @@ export default class HostInteropType {
         const filename = codeUrl.replace("atomic://", "");
 
         // go ahead and set the theme prior to pulling the file across
-        editorConfig.configure(fileExt, filename);
+        editorCommands.configure(fileExt, filename);
 
         // get the code
         this.getResource(codeUrl).then((src: string) => {
-            editorConfig.loadCodeIntoEditor(src, filename, fileExt);
+            editorCommands.loadCodeIntoEditor(src, filename, fileExt);
         }).catch((e: Editor.ClientExtensions.AtomicErrorMessage) => {
             console.log("Error loading code: " + e.error_message);
         });
@@ -92,7 +96,7 @@ export default class HostInteropType {
     saveCode(): Promise<{}> {
         return atomicQueryPromise({
             message: HostInteropType.EDITOR_SAVE_CODE,
-            payload: editor.session.getValue()
+            payload: editorCommands.getSourceText()
         });
     }
 
@@ -156,6 +160,31 @@ export default class HostInteropType {
             console.log("Error on change: " + e.error_message);
         });
     }
+
+    /**
+     * Notify that the project has been unloaded
+     */
+    projectUnloaded() {
+        editorCommands.projectUnloaded();
+    }
+
+    /**
+     * Notify that a resource has been renamed
+     * @param  {string} path
+     * @param  {string} newPath
+     */
+    resourceRenamed(path: string, newPath: string) {
+        editorCommands.resourceRenamed(path, newPath);
+
+    }
+
+    /**
+     * Notify that a resource has been deleted
+     * @param  {string} path
+     */
+    resourceDeleted(path: string) {
+        editorCommands.resourceDeleted(path);
+    }
 }
 
 HostInteropType.getInstance().editorLoaded();

+ 3 - 2
Script/AtomicWebViewEditor/tsconfig.json

@@ -17,16 +17,17 @@
         "rewriteTsconfig": true
     },
     "files": [
+        "./clientExtensions/ClientExtensionEventNames.ts",
         "./clientExtensions/ClientExtensionServices.ts",
         "./clientExtensions/languageExtensions/javascript/JavascriptLanguageExtension.ts",
         "./clientExtensions/languageExtensions/typescript/TypescriptLanguageExtension.ts",
         "./clientExtensions/languageExtensions/typescript/workerprocess/TypescriptLanguageService.ts",
         "./clientExtensions/languageExtensions/typescript/workerprocess/TypescriptLanguageServiceWebWorker.ts",
         "./clientExtensions/languageExtensions/typescript/workerprocess/workerLoader.ts",
-        "./clientExtensions/languageExtensions/typescript/workerprocess/workerProcessCommands.ts",
+        "./clientExtensions/languageExtensions/typescript/workerprocess/workerProcessTypes.ts",
         "./clientExtensions/ServiceLocator.ts",
         "./editor/editor.ts",
-        "./editor/editorConfig.ts",
+        "./editor/editorCommands.ts",
         "./interop.ts",
         "./modules/typescript.d.ts",
         "./typings/ace.d.ts",

+ 4 - 0
Script/AtomicWebViewEditor/typings/WindowExt.d.ts

@@ -12,4 +12,8 @@ interface Window {
     atomicQuery: any;
     HOST_loadCode: (codeUrl) => void;
     HOST_saveCode: () => void;
+
+    HOST_projectUnloaded: () => void;
+    HOST_resourceRenamed: (path:string, newPath:string) => void;
+    HOST_resourceDeleted: (path: string) => void;
 }

+ 4 - 3
Script/TypeScript/EditorWork.d.ts

@@ -110,9 +110,6 @@ declare module Editor.EditorEvents {
         // The full path to the resource to edit
         path: string;
         newPath: string;
-
-        // the asset to delete
-        asset: ToolCore.Asset;
     }
 
     export interface SceneEditStateChangeEvent {
@@ -238,6 +235,10 @@ declare module Editor.ClientExtensions {
     export interface WebViewService extends Editor.Extensions.EditorService {
         configureEditor?(ev: EditorEvents.EditorFileEvent);
         codeLoaded?(ev: EditorEvents.CodeLoadedEvent);
+        save?(ev: EditorEvents.SaveResourceEvent);
+        delete?(ev: EditorEvents.DeleteResourceEvent);
+        rename?(ev: EditorEvents.RenameResourceEvent);
+        projectUnloaded?();
     }
 
     export interface AtomicErrorMessage {