Browse Source

extracted the logic that instantiates resource editors into separate ResourceEditorBuilders so that it's easier to register and add new editors

Shaddock Heath 9 years ago
parent
commit
b23ec556c1

+ 2 - 0
Script/AtomicEditor/editor/EditorEvents.ts

@@ -159,3 +159,5 @@ export interface RemoveCurrentAssetAssignedEvent {
 }
 
 export const UserPreferencesChangedNotification  = "UserPreferencesChangedNotification";
+export const WebViewLoadEnd = "WebViewLoadEnd";
+export const WebMessage = "WebMessage";

+ 95 - 0
Script/AtomicEditor/ui/ResourceEditorProvider.ts

@@ -0,0 +1,95 @@
+//
+// Copyright (c) 2014-2016 THUNDERBEAST GAMES LLC
+//
+// 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 JavascriptResourceEditorBuilder from "./resourceEditors/JavascriptResourceEditorBuilder";
+import JsonResourceEditorBuilder from "./resourceEditors/JsonResourceEditorBuilder";
+import Scene3dResourceEditorBuilder from "./resourceEditors/Scene3dResourceEditorBuilder";
+import TextFileResourceEditorBuilder from "./resourceEditors/TextFileResourceEditorBuilder";
+import TurboBadgerResourceEditorBuilder from "./resourceEditors/TurboBadgerResourceEditorBuilder";
+import TypescriptResourceEditorBuilder from "./resourceEditors/TypescriptResourceEditorBuilder";
+
+export default class ResourceEditorProvider {
+    private standardEditorRegistry: Editor.Extensions.ResourceEditorBuilder[] = [];
+    private customEditorRegistry: Editor.Extensions.ResourceEditorBuilder[] = [];
+    private resourceFrame: Atomic.UIWidget;
+
+    constructor(resourceFrame: Atomic.UIWidget) {
+        this.resourceFrame = resourceFrame;
+    }
+
+    /**
+     * Register an internal core editor.
+     */
+    registerStandardEditor(editorBuilder: Editor.Extensions.ResourceEditorBuilder) {
+        this.standardEditorRegistry.push(editorBuilder);
+    }
+
+    /**
+     * Register a custom editor.  These editors will override editors in the standard editor list if
+     * they both resolve the ```canHandleResource``` call.
+     */
+    registerCustomEditor(editorBuilder) {
+        this.customEditorRegistry.push(editorBuilder);
+    }
+
+    /**
+     * Returns an editor for the provided resource type or null
+     */
+    getEditor(resourcePath: string, tabContainer) {
+        let editorBuilder: Editor.Extensions.ResourceEditorBuilder;
+        this.customEditorRegistry.forEach((builder) => {
+            if (builder.canHandleResource(resourcePath)) {
+                editorBuilder = builder;
+                return;
+            }
+        });
+
+        if (!editorBuilder) {
+            this.standardEditorRegistry.forEach((builder) => {
+                if (builder.canHandleResource(resourcePath)) {
+                    editorBuilder = builder;
+                    return;
+                }
+            });
+        }
+
+        if (editorBuilder) {
+            return editorBuilder.getEditor(this.resourceFrame, resourcePath, tabContainer);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Loads the built-in standard editors
+     */
+    loadStandardEditors() {
+        this.registerStandardEditor(new TextFileResourceEditorBuilder());
+        this.registerStandardEditor(new JavascriptResourceEditorBuilder());
+        this.registerStandardEditor(new JsonResourceEditorBuilder());
+        this.registerStandardEditor(new TypescriptResourceEditorBuilder());
+        this.registerStandardEditor(new Scene3dResourceEditorBuilder());
+
+        // this overrides the test resource editor so need to put it in the custom bucket
+        this.registerCustomEditor(new TurboBadgerResourceEditorBuilder());
+    }
+}

+ 6 - 42
Script/AtomicEditor/ui/frames/ResourceFrame.ts

@@ -23,6 +23,7 @@
 import ScriptWidget = require("ui/ScriptWidget");
 import EditorEvents = require("editor/EditorEvents");
 import UIEvents = require("ui/UIEvents");
+import ResourceEditorProvider from "../ResourceEditorProvider";
 
 // the root content of editor widgets (rootContentWidget property) are extended with an editor field
 // so we can access the editor they belong to from the widget itself
@@ -37,6 +38,7 @@ class ResourceFrame extends ScriptWidget {
     resourceViewContainer: Atomic.UILayout;
     currentResourceEditor: Editor.ResourceEditor;
     wasClosed: boolean;
+    resourceEditorProvider: ResourceEditorProvider;
 
     // editors have a rootCotentWidget which is what is a child of the tab container
 
@@ -94,29 +96,7 @@ class ResourceFrame extends ScriptWidget {
 
         }
 
-        var ext = Atomic.getExtension(path);
-
-        var editor: Editor.ResourceEditor = null;
-
-        if (ext == ".js" || ext == ".txt" || ext == ".json" || ext == ".ts") {
-
-            editor = new Editor.JSResourceEditor(path, this.tabcontainer);
-
-            // one time subscriptions waiting for the web view to finish loading
-            this.subscribeToEvent("WebViewLoadEnd", (data) => {
-                this.unsubscribeFromEvent("WebViewLoadEnd");
-                let webClient = <WebView.WebClient> data.client;
-                webClient.executeJavaScript(`HOST_loadCode("atomic://${path}");`);
-            });
-
-        } else if (ext == ".scene") {
-
-            var sceneEditor3D = new Editor.SceneEditor3D(path, this.tabcontainer);
-            editor = sceneEditor3D;
-            this.sendEvent(EditorEvents.ActiveSceneEditorChange, { sceneEditor: sceneEditor3D });
-
-        }
-
+        var editor = this.resourceEditorProvider.getEditor(ev.path, this.tabcontainer);
         if (editor) {
 
             // cast and add editor lookup on widget itself
@@ -233,23 +213,6 @@ class ResourceFrame extends ScriptWidget {
         }
     }
 
-    handleUserPreferencesChanged() {
-        let prefsPath = ToolCore.toolSystem.project.userPrefsFullPath;
-        if (Atomic.fileSystem.fileExists(prefsPath)) {
-            for (let editorKey in this.editors) {
-                let editor = this.editors[editorKey];
-                if (editor.typeName == "JSResourceEditor") {
-                    let jsEditor = <Editor.JSResourceEditor>editor;
-
-                    // Get a reference to the web client so we can call the load preferences method
-                    let webClient = jsEditor.webView.webClient;
-
-                    webClient.executeJavaScript(`HOST_loadPreferences("atomic://${prefsPath}");`);
-                }
-            }
-        }
-    }
-
     handleWidgetEvent(ev: Atomic.UIWidgetEvent) {
 
         if (ev.type == Atomic.UI_EVENT_TYPE_TAB_CHANGED && ev.target == this.tabcontainer) {
@@ -296,7 +259,7 @@ class ResourceFrame extends ScriptWidget {
     handleProjectUnloaded(data) {
 
       for (var i in this.editors) {
-          this.editors[i].close();
+           this.sendEvent(EditorEvents.EditorResourceClose, { editor: this.editors[i], navigateToAvailableResource: false });
       }
 
     }
@@ -314,6 +277,8 @@ class ResourceFrame extends ScriptWidget {
         this.resourceLayout = <Atomic.UILayout> this.getWidget("resourcelayout");
 
         this.resourceViewContainer.addChild(this);
+        this.resourceEditorProvider = new ResourceEditorProvider(this);
+        this.resourceEditorProvider.loadStandardEditors();
 
         this.subscribeToEvent(EditorEvents.ProjectUnloadedNotification, (data) => this.handleProjectUnloaded(data));
         this.subscribeToEvent(EditorEvents.EditResource, (data) => this.handleEditResource(data));
@@ -322,7 +287,6 @@ class ResourceFrame extends ScriptWidget {
         this.subscribeToEvent(EditorEvents.EditorResourceClose, (ev: EditorEvents.EditorCloseResourceEvent) => this.handleCloseResource(ev));
         this.subscribeToEvent(EditorEvents.RenameResourceNotification, (ev: EditorEvents.RenameResourceEvent) => this.handleRenameResource(ev));
         this.subscribeToEvent(EditorEvents.DeleteResourceNotification, (data) => this.handleDeleteResource(data));
-        this.subscribeToEvent(EditorEvents.UserPreferencesChangedNotification, (data) => this.handleUserPreferencesChanged());
 
         this.subscribeToEvent(UIEvents.ResourceEditorChanged, (data) => this.handleResourceEditorChanged(data));
 

+ 100 - 0
Script/AtomicEditor/ui/resourceEditors/AbstractTextResourceEditorBuilder.ts

@@ -0,0 +1,100 @@
+//
+// Copyright (c) 2014-2016 THUNDERBEAST GAMES LLC
+//
+// 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 EditorEvents = require("../../editor/EditorEvents");
+export abstract class AbstractTextResourceEditorBuilder implements Editor.Extensions.ResourceEditorBuilder {
+
+    abstract canHandleResource(resourcePath: string): boolean;
+
+    /**
+     * Full path is the fully qualified path from the root of the filesystem.  In order to take advantage
+     * of the resource caching system, let's trim it down to just the path inside the resources directory
+     * including the Resources directory so that the casing is correct
+     */
+    private getNormalizedPath(path: string) {
+        const RESOURCES_MARKER = "resources/";
+        return path.substring(path.toLowerCase().indexOf(RESOURCES_MARKER));
+    }
+
+    getEditor(resourceFrame: Atomic.UIWidget, resourcePath: string, tabContainer: Atomic.UITabContainer): Editor.ResourceEditor {
+
+        const editor = new Editor.JSResourceEditor(resourcePath, tabContainer);
+
+        // one time subscriptions waiting for the web view to finish loading.  This event
+        // actually hits the editor instance before we can hook it, so listen to it on the
+        // frame and then unhook it
+        editor.subscribeToEvent(EditorEvents.WebViewLoadEnd, (data) => {
+            editor.unsubscribeFromEvent(EditorEvents.WebViewLoadEnd);
+            this.loadCode(<Editor.JSResourceEditor>editor, resourcePath);
+        });
+
+        // Cannot subscribe to WebMessage until the .ts side can return a Handler.Success() message
+        // editor.subscribeToEvent(EditorEvents.WebMessage, (data) => {
+        //     console.log("editor Got a web message: " + data.request);
+        //     for (let x in data) {
+        //         console.log(x + ":" + data[x]);
+        //     }
+        //     const request = JSON.parse(data.request);
+        //     switch (request.message) {
+        //         case "editorGetUserPrefs":
+        //             this.getUserPrefs(editor);
+        //             return true;
+        //     }
+        // });
+
+        editor.subscribeToEvent(EditorEvents.ProjectUnloadedNotification, (data) => {
+            const webClient = editor.webView.webClient;
+            webClient.executeJavaScript("HOST_projectUnloaded();");
+        });
+
+        editor.subscribeToEvent(EditorEvents.DeleteResourceNotification, (data) => {
+            const webClient = editor.webView.webClient;
+            webClient.executeJavaScript(`HOST_resourceDeleted("atomic://${this.getNormalizedPath(editor.fullPath)}");`);
+        });
+
+        editor.subscribeToEvent(EditorEvents.UserPreferencesChangedNotification, (data) => {
+            this.getUserPrefs(editor);
+        });
+
+        return editor;
+    }
+
+    /**
+     * Send the url of the user prefs to the web view so that it can request it
+     */
+    getUserPrefs(editor: Editor.JSResourceEditor) {
+        let prefsPath = ToolCore.toolSystem.project.userPrefsFullPath;
+        if (Atomic.fileSystem.fileExists(prefsPath)) {
+            // Get a reference to the web client so we can call the load preferences method
+            const webClient = editor.webView.webClient;
+            webClient.executeJavaScript(`HOST_loadPreferences("atomic://${prefsPath}");`);
+        }
+    }
+
+    /**
+     * Send the url of the code to the web view so that it can request it
+     */
+    loadCode(editor: Editor.JSResourceEditor, resourcePath: string) {
+        const webClient = editor.webView.webClient;
+        webClient.executeJavaScript(`HOST_loadCode("atomic://${this.getNormalizedPath(editor.fullPath)}");`);
+    }
+}

+ 35 - 0
Script/AtomicEditor/ui/resourceEditors/JavascriptResourceEditorBuilder.ts

@@ -0,0 +1,35 @@
+//
+// Copyright (c) 2014-2016 THUNDERBEAST GAMES LLC
+//
+// 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 {AbstractTextResourceEditorBuilder} from "./AbstractTextResourceEditorBuilder";
+
+export default class JavascriptResourceEditorBuilder extends AbstractTextResourceEditorBuilder {
+
+    constructor() {
+        super();
+    }
+
+    canHandleResource(resourcePath: string) : boolean {
+        var ext = Atomic.getExtension(resourcePath).toLowerCase();
+        return ext == ".js";
+    }
+}

+ 35 - 0
Script/AtomicEditor/ui/resourceEditors/JsonResourceEditorBuilder.ts

@@ -0,0 +1,35 @@
+//
+// Copyright (c) 2014-2016 THUNDERBEAST GAMES LLC
+//
+// 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 {AbstractTextResourceEditorBuilder} from "./AbstractTextResourceEditorBuilder";
+
+export default class JsonResourceEditorBuilder extends AbstractTextResourceEditorBuilder {
+
+    constructor() {
+        super();
+    }
+
+    canHandleResource(resourcePath: string) : boolean {
+        var ext = Atomic.getExtension(resourcePath).toLowerCase();
+        return ext == ".json";
+    }
+}

+ 38 - 0
Script/AtomicEditor/ui/resourceEditors/Scene3dResourceEditorBuilder.ts

@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2014-2016 THUNDERBEAST GAMES LLC
+//
+// 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 EditorEvents = require("../../editor/EditorEvents");
+
+export default class Scene3dResourceEditorBuilder implements Editor.Extensions.ResourceEditorBuilder {
+
+    canHandleResource(resourcePath: string) : boolean {
+        var ext = Atomic.getExtension(resourcePath);
+        return ext == ".scene";
+    }
+
+    getEditor(resourceFram: Atomic.UIWidget, resourcePath: string, tabContainer: Atomic.UITabContainer) : Editor.ResourceEditor {
+
+        const editor = new Editor.SceneEditor3D(resourcePath, tabContainer);
+        editor.sendEvent(EditorEvents.ActiveSceneEditorChange, { sceneEditor: editor });
+
+        return editor;
+    }
+}

+ 35 - 0
Script/AtomicEditor/ui/resourceEditors/TextFileResourceEditorBuilder.ts

@@ -0,0 +1,35 @@
+//
+// Copyright (c) 2014-2016 THUNDERBEAST GAMES LLC
+//
+// 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 {AbstractTextResourceEditorBuilder} from "./AbstractTextResourceEditorBuilder";
+
+export default class TextResourceEditorBuilder extends AbstractTextResourceEditorBuilder {
+
+    constructor() {
+        super();
+    }
+
+    canHandleResource(resourcePath: string) : boolean {
+        var ext = Atomic.getExtension(resourcePath).toLowerCase();
+        return ext == ".txt";
+    }
+}

+ 35 - 0
Script/AtomicEditor/ui/resourceEditors/TurboBadgerResourceEditorBuilder.ts

@@ -0,0 +1,35 @@
+//
+// Copyright (c) 2014-2016 THUNDERBEAST GAMES LLC
+//
+// 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 {AbstractTextResourceEditorBuilder} from "./AbstractTextResourceEditorBuilder";
+
+export default class TurboBadgerResourceEditorBuilder extends AbstractTextResourceEditorBuilder {
+
+    constructor() {
+        super();
+    }
+
+    canHandleResource(resourcePath: string) : boolean {
+        var ext = Atomic.getExtension(resourcePath).toLowerCase();
+        return ext == ".tb" || ext == "txt.tb";
+    }
+}

+ 35 - 0
Script/AtomicEditor/ui/resourceEditors/TypescriptResourceEditorBuilder.ts

@@ -0,0 +1,35 @@
+//
+// Copyright (c) 2014-2016 THUNDERBEAST GAMES LLC
+//
+// 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 {AbstractTextResourceEditorBuilder} from "./AbstractTextResourceEditorBuilder";
+
+export default class TypescriptResourceEditorBuilder extends AbstractTextResourceEditorBuilder {
+
+    constructor() {
+        super();
+    }
+
+    canHandleResource(resourcePath: string) : boolean {
+        var ext = Atomic.getExtension(resourcePath).toLowerCase();
+        return ext == ".ts";
+    }
+}

+ 16 - 0
Script/TypeScript/EditorWork.d.ts

@@ -219,6 +219,22 @@ declare module Editor.Extensions {
          */
         unregister(service: T);
     }
+
+    /**
+     * Interface that describes a Resource Editor Factory that will build out the editor for the relevant resource type
+     */
+    export interface ResourceEditorBuilder {
+        /**
+         * Returns true if this builder can generate an editor for this resource type
+         */
+        canHandleResource(resourcePath: string) : boolean;
+        /**
+         * Generates a resource editor for the provided resource type
+         * @param  resourcePath
+         * @param  tabContainer
+         */
+        getEditor(resourceFrame: Atomic.UIWidget, resourcePath: string, tabContainer: Atomic.UITabContainer) : Editor.ResourceEditor;
+    }
 }
 
 declare module Editor.Modal {

+ 8 - 0
Script/tsconfig.json

@@ -94,6 +94,14 @@
         "./AtomicEditor/ui/modal/UIResourceOps.ts",
         "./AtomicEditor/ui/playmode/PlayerOutput.ts",
         "./AtomicEditor/ui/playmode/PlayMode.ts",
+        "./AtomicEditor/ui/ResourceEditorProvider.ts",
+        "./AtomicEditor/ui/resourceEditors/AbstractTextResourceEditorBuilder.ts",
+        "./AtomicEditor/ui/resourceEditors/JavascriptResourceEditorBuilder.ts",
+        "./AtomicEditor/ui/resourceEditors/JsonResourceEditorBuilder.ts",
+        "./AtomicEditor/ui/resourceEditors/Scene3dResourceEditorBuilder.ts",
+        "./AtomicEditor/ui/resourceEditors/TextFileResourceEditorBuilder.ts",
+        "./AtomicEditor/ui/resourceEditors/TurboBadgerResourceEditorBuilder.ts",
+        "./AtomicEditor/ui/resourceEditors/TypescriptResourceEditorBuilder.ts",
         "./AtomicEditor/ui/ScriptWidget.ts",
         "./AtomicEditor/ui/Shortcuts.ts",
         "./AtomicEditor/ui/UIEvents.ts",