Browse Source

ProjectFrame ts work

Josh Engebretson 10 years ago
parent
commit
886b353b97
31 changed files with 792 additions and 87 deletions
  1. 6 1
      Data/AtomicEditor/Resources/EditorData/AtomicEditor/typescript/AtomicWork.d.ts
  2. 34 13
      Data/AtomicEditor/Resources/EditorData/AtomicEditor/typescript/editor/Editor.ts
  3. 1 4
      Data/AtomicEditor/Resources/EditorData/AtomicEditor/typescript/main.ts
  4. 8 5
      Data/AtomicEditor/Resources/EditorData/AtomicEditor/typescript/ui/MainFrame.ts
  5. 268 43
      Data/AtomicEditor/Resources/EditorData/AtomicEditor/typescript/ui/ProjectFrame.ts
  6. 3 1
      Data/AtomicEditor/Resources/EditorData/AtomicEditor/typescript/ui/ScriptWidget.ts
  7. 1 2
      Data/AtomicEditor/Resources/EditorData/AtomicEditor/typescript/ui/modal/MessageModal.ts
  8. 9 0
      Source/Atomic/UI/UI.cpp
  9. 34 0
      Source/Atomic/UI/UIFontDescription.cpp
  10. 31 0
      Source/Atomic/UI/UIFontDescription.h
  11. 9 0
      Source/Atomic/UI/UILayout.cpp
  12. 19 0
      Source/Atomic/UI/UILayout.h
  13. 46 5
      Source/Atomic/UI/UIListView.cpp
  14. 10 2
      Source/Atomic/UI/UIListView.h
  15. 41 0
      Source/Atomic/UI/UISelectList.cpp
  16. 6 0
      Source/Atomic/UI/UISelectList.h
  17. 39 0
      Source/Atomic/UI/UISkinImage.cpp
  18. 26 0
      Source/Atomic/UI/UISkinImage.h
  19. 37 0
      Source/Atomic/UI/UIWidget.cpp
  20. 10 1
      Source/Atomic/UI/UIWidget.h
  21. 2 0
      Source/AtomicJS/Javascript/JSAtomic.cpp
  22. 25 2
      Source/AtomicJS/Javascript/JSCore.cpp
  23. 76 0
      Source/AtomicJS/Javascript/JSFileSystem.cpp
  24. 16 0
      Source/AtomicJS/Javascript/JSFileSystem.h
  25. 2 2
      Source/AtomicJS/Javascript/JSScriptObject.cpp
  26. 4 4
      Source/AtomicJS/Javascript/JSScriptObject.h
  27. 2 0
      Source/AtomicJS/Javascript/JSUI.cpp
  28. 1 1
      Source/AtomicJS/Packages/Atomic/Javascript.json
  29. 2 1
      Source/AtomicJS/Packages/Atomic/UI.json
  30. 8 0
      Source/ToolCore/Project/Project.cpp
  31. 16 0
      Source/ToolCore/ToolEvents.h

+ 6 - 1
Data/AtomicEditor/Resources/EditorData/AtomicEditor/typescript/AtomicWork.d.ts

@@ -4,9 +4,14 @@
 
 declare module Atomic
 {
+	export function getArguments() : Array<string>;
+
 	export function getInput() : Input;
 	export function getGraphics() : Graphics;
-	export function getFileSystem(); FileSystem;
+	export function getFileSystem(): FileSystem;
+
+
+
 }
 
 declare module ToolCore

+ 34 - 13
Data/AtomicEditor/Resources/EditorData/AtomicEditor/typescript/editor/Editor.ts

@@ -2,21 +2,16 @@
 import MainFrame = require("../ui/MainFrame");
 import UIEvents = require("../ui/UIEvents");
 
-
-export function getEditor():Editor {
-  return TheEditor;
-}
-
-var TheEditor:Editor;
-
-export class Editor extends Atomic.JSScriptObject
+class Editor extends Atomic.ScriptObject
 {
 
   project: ToolCore.Project;
   view: Atomic.UIView;
-  mainframe: MainFrame.MainFrame;
+  mainframe: MainFrame;
+
+  static instance:Editor;
 
-  loadProject(projectPath:string) {
+  loadProject(projectPath:string):boolean {
 
     var system = ToolCore.getToolSystem();
 
@@ -25,9 +20,31 @@ export class Editor extends Atomic.JSScriptObject
       this.sendEvent(UIEvents.MessageModalEvent,
         { type:"error", title:"Project already loaded", message:"Project already loaded"} );
 
+        return false;
+
     }
 
-    system.loadProject(projectPath);
+    return system.loadProject(projectPath);
+
+  }
+
+  parseArguments() {
+
+    var args = Atomic.getArguments();
+
+    var idx = 0;
+
+    while (idx < args.length) {
+
+      if (args[idx] == "--project") {
+
+        this.loadProject(args[idx + 1]);
+
+      }
+
+      idx++;
+
+    }
 
   }
 
@@ -35,19 +52,23 @@ export class Editor extends Atomic.JSScriptObject
 
     super();
 
-    TheEditor = this;
+    Editor.instance = this;
 
     var graphics = Atomic.getGraphics();
 
     this.view = new Atomic.UIView();
 
-    this.mainframe = new MainFrame.MainFrame();
+    this.mainframe = new MainFrame();
 
     this.view.addChild(this.mainframe);
 
     // set initial size
     this.mainframe.setSize(graphics.width, graphics.height);
 
+    this.parseArguments();
+
   }
 
 }
+
+export = Editor;

+ 1 - 4
Data/AtomicEditor/Resources/EditorData/AtomicEditor/typescript/main.ts

@@ -6,7 +6,4 @@
 
 import Editor = require("./editor/Editor");
 
-var TheEditor = new Editor.Editor();
-
-TheEditor.loadProject("/Users/josh/Dev/atomic/AtomicExamples/NewSpaceGame");
-TheEditor.loadProject("/Users/josh/Dev/atomic/AtomicExamples/NewSpaceGame");
+var TheEditor = new Editor();

+ 8 - 5
Data/AtomicEditor/Resources/EditorData/AtomicEditor/typescript/ui/MainFrame.ts

@@ -1,12 +1,13 @@
 import menubar = require("./MainFrameMenu");
-import scriptwidget = require("./ScriptWidget");
-import projectframe = require("./ProjectFrame");
+import ProjectFrame = require("./ProjectFrame");
 import MessageModal = require("./modal/MessageModal");
 import UIEvents = require("./UIEvents");
 
-export class MainFrame extends scriptwidget.ScriptWidget {
+import ScriptWidget = require("./ScriptWidget");
 
-	projectframe:projectframe.ProjectFrame;
+class MainFrame extends ScriptWidget {
+
+	projectframe:ProjectFrame;	
 	private messagemodal:MessageModal.MessageModal = new MessageModal.MessageModal();
 
 	constructor() {
@@ -15,7 +16,7 @@ export class MainFrame extends scriptwidget.ScriptWidget {
 
 		this.load("AtomicEditor/editor/ui/mainframe.tb.txt");
 
-		this.projectframe = new projectframe.ProjectFrame(this);
+		this.projectframe = new ProjectFrame(this);
 
 	}
 
@@ -63,3 +64,5 @@ export class MainFrame extends scriptwidget.ScriptWidget {
 	}
 
 }
+
+export = MainFrame;

+ 268 - 43
Data/AtomicEditor/Resources/EditorData/AtomicEditor/typescript/ui/ProjectFrame.ts

@@ -1,84 +1,309 @@
 
 
-import scriptwidget = require("./ScriptWidget");
+import ScriptWidget = require("./ScriptWidget");
 
-export class ProjectFrame extends scriptwidget.ScriptWidget {
+var UI = Atomic.UI;
 
-  folderList:Atomic.UIListView;
+class ProjectFrame extends ScriptWidget {
 
-	constructor(parent: Atomic.UIWidget) {
+    folderList: Atomic.UIListView;
 
-		super();
+    constructor(parent: Atomic.UIWidget) {
 
-		this.load("AtomicEditor/editor/ui/projectframe.tb.txt");
+        super();
 
-    this.gravity = Atomic.UI.GRAVITY_TOP_BOTTOM;
+        this.load("AtomicEditor/editor/ui/projectframe.tb.txt");
 
-    var projectviewcontainer = parent.getWidget("projectviewcontainer");
+        this.gravity = UI.GRAVITY_TOP_BOTTOM;
 
-    projectviewcontainer.addChild(this);
+        var projectviewcontainer = parent.getWidget("projectviewcontainer");
 
-    var foldercontainer = this.getWidget("foldercontainer");
+        projectviewcontainer.addChild(this);
 
-    var folderList = this.folderList = new Atomic.UIListView();
+        var foldercontainer = this.getWidget("foldercontainer");
 
-    folderList.id = "folderList";
+        var folderList = this.folderList = new Atomic.UIListView();
 
-    foldercontainer.addChild(folderList);
+        folderList.rootList.id = "folderList_";
 
-    folderList.addItem("Resources", "Folder.icon", "myid")
+        foldercontainer.addChild(folderList);
 
-    var fileSystem = Atomic.getFileSystem();
+        // events
+        this.subscribeToEvent("ProjectLoaded", (data) => this.handleProjectLoaded(data));
 
-    var folders = fileSystem.scanDir("/", "", Atomic.SCAN_DIRS, false);
+    }
 
-    print(folders);
 
+    handleProjectLoaded(data) {
 
+        this.refresh();
 
-	}
+    }
 
-	onEventClick(target: Atomic.UIWidget, refid: string): boolean {
+    handleWidgetEvent(data): boolean {
 
-      return false;
+        if (data.type == Atomic.UI.EVENT_TYPE_CLICK) {
 
-	}
+            var fs = Atomic.getFileSystem();
 
+            if (data.target && data.target.id.length) {
 
-}
+                var id = data.target.id;
 
+                if (id == "folderList_") {
 
+                    var list = <Atomic.UISelectList> data.target;
 
-/*
-var UI = Atomic.UI;
-var UIWidget = Atomic.UIWidget;
-var UIListView = Atomic.UIListView;
-var fileSystem = Atomic.getFileSystem();
+                    var selectedId = list.selectedItemID;
+
+                    if (fs.dirExists(selectedId)) {
+                        this.selectCurrentContentFolder(selectedId);
+                    }
+
+                    return true;
+
+                }
+
+                if (id == "..") {
+                    var parentPath = Atomic.getParentPath(this.currentContentFolder);
+                    this.selectCurrentContentFolder(parentPath);
+                    return true;
+                }
+
+                if (fs.dirExists(id)) {
+                    this.selectCurrentContentFolder(id);
+                }
+
+            }
+
+        }
+
+        return false;
+
+    }
+
+
+    refresh() {
+
+        var cfolder = this.currentContentFolder;
+        this.currentContentFolder = "";
+        this.refreshFolders();
+        
+    }
+
+    private refreshContent(fullpath: string) {
+
+        var system = ToolCore.getToolSystem();
+        var project = system.project;
+
+        this.currentContentFolder = fullpath;
+
+        var folders = new Array<string>();
+        var content = new Array<string>();
+
+        this.scanContentDirForContent(folders, content, fullpath);
+
+        var container: Atomic.UILayout = <Atomic.UILayout> this.getWidget("contentcontainer");
+
+        container.deleteAllChildren();
+
+        if (fullpath != project.resourcePath) {
+
+            var lp = new Atomic.UILayoutParams();
+            lp.height = 20;
+
+            var fd = new Atomic.UIFontDescription();
+            fd.id = "Vera";
+            fd.size = 11;
+
+            var button = new Atomic.UIButton();
+            button.gravity = UI.GRAVITY_LEFT;
+            button.text = "..                     ";
+            button.id = "..";
+            button.skinBg = "TBButton.flat";
+            button.layoutParams = lp;
+            button.fontDescription = fd;
+
+            container.addChild(button);
+
+        }
+
+        for (var folder of folders) {
+
+            var contentID = Atomic.addTrailingSlash(fullpath + folder);
+            container.addChild(this.createButtonLayout(contentID, folder));
+        }
+
+        for (var c of content) {
+
+            var contentID = Atomic.addTrailingSlash(fullpath) + c;
+            container.addChild(this.createButtonLayout(contentID, c));
+        }
+
+
+    }
+
+    private recursiveAddFolder(parentItemID: number, fullpath: string, folderName: string) {
+
+        var folderList = this.folderList;
+
+        var childItemID = folderList.addChildItem(parentItemID, folderName, "Folder.icon", fullpath);
+
+        var dirs = new Array<string>();
+
+        this.scanDirForFolders(dirs, fullpath);
+
+        for (var folder of dirs) {
+            this.recursiveAddFolder(childItemID, fullpath + folder + "/", folder);
+        }
+
+    }
+
+    private refreshFolders() {
+
+        var system = ToolCore.getToolSystem();
+        var project = system.project;
+
+        var folderList = this.folderList;
 
-var mainframe = require("./mainframe").mainframe;
+        folderList.deleteAllItems();
 
-var projectframe = exports.projectframe = new UIWidget();
+        var resourcesID = folderList.addRootItem("Resources", "Folder.icon", project.resourcePath);
 
-projectframe.gravity = UI.GRAVITY_TOP_BOTTOM;
+        var dirs = new Array<string>();
 
-// load the UI
-projectframe.load("AtomicEditor/editor/ui/projectframe.tb.txt");
+        this.scanDirForFolders(dirs, project.resourcePath);
 
-// snap the project frame into place
-var projectviewcontainer = mainframe.getWidget("projectviewcontainer");
-projectviewcontainer.addChild(projectframe);
+        for (var folder of dirs) {
+            this.recursiveAddFolder(resourcesID, project.resourcePath + folder + "/", folder);
+        }
 
-var foldercontainer = projectframe.getWidget("foldercontainer");
+        folderList.setExpanded(resourcesID, true);
+        this.refreshContent(project.resourcePath);
+        folderList.rootList.value = 0;
 
-var folderList = new UIListView();
 
-folderList.id = "folderList";
+    }
 
-foldercontainer.addChild(folderList);
+    private selectCurrentContentFolder(folder: string) {
 
-//folderList.addItem("Resources", "Folder.icon", "myid")
+        this.folderList.selectItemByID(folder);
+        if (this.currentContentFolder != folder)
+            this.refreshContent(folder);
+    }
 
-var folders = fileSystem.scanDir("/", "", Atomic.SCAN_DIRS, false);
+    private endsWith(str: string, suffix: string): boolean {
+        return str && str.indexOf(suffix, str.length - suffix.length) !== -1;
+    }
+
+    private scanDirForFolders(dirs: Array<string>, fullpath: string) {
+
+        var fileSystem = Atomic.getFileSystem();
+
+        dirs.length = 0;
+
+        var folders = fileSystem.scanDir(fullpath, "", Atomic.SCAN_DIRS, false);
+
+        for (var folder of folders) {
+
+            if (folder == "." || folder == ".." || this.endsWith(folder, "/..") || this.endsWith(folder, "/."))
+                continue;
+
+            dirs.push(folder);
+
+        }
+
+    }
+
+
+    private scanContentDirForContent(folders: Array<string>, content: Array<string>, fullPath: string) {
+
+        var fileSystem = Atomic.getFileSystem();
+
+        folders.length = content.length = 0;
+
+        var _folders = fileSystem.scanDir(fullPath, "", Atomic.SCAN_DIRS, false);
+
+        for (var folder of _folders) {
+
+            if (folder == "." || folder == ".." || this.endsWith(folder, "/..") || this.endsWith(folder, "/."))
+                continue;
+
+            folders.push(folder);
+
+        }
+
+        var _content = fileSystem.scanDir(fullPath, "", Atomic.SCAN_FILES, false);
+
+        for (var c of _content) {
+
+            content.push(c);
+
+        }
+
+    }
+
+    private createButtonLayout(fullpath: string, text: string): Atomic.UILayout {
+
+        var system = ToolCore.getToolSystem();
+        var project = system.project;
+        var fs = Atomic.getFileSystem();
+
+        var pathinfo = Atomic.splitPath(fullpath);
+
+        var bitmapID = "Folder.icon";
+
+        if (fs.fileExists(fullpath)) {
+            bitmapID = "FileBitmap";
+        }
+
+        if (pathinfo.ext == ".js") {
+            if (project.isComponentsDirOrFile(fullpath)) {
+                bitmapID = "ComponentBitmap";
+            }
+            else {
+                bitmapID = "JavascriptBitmap";
+            }
+        }
+
+        var blayout = new Atomic.UILayout();
+
+        blayout.gravity = UI.GRAVITY_LEFT;
+
+        var spacer = new Atomic.UIWidget();
+        spacer.rect = [0, 0, 8, 8];
+        blayout.addChild(spacer);
+
+        var button = new Atomic.UIButton();
+
+        var lp = new Atomic.UILayoutParams;
+        lp.height = 20;
+
+        var fd = new Atomic.UIFontDescription();
+        fd.id = "Vera";
+        fd.size = 11;
+
+        button.gravity = UI.GRAVITY_LEFT;
+
+        var image = new Atomic.UISkinImage(bitmapID);
+        image.rect = [0, 0, 12, 12];
+        image.gravity = UI.GRAVITY_RIGHT;
+        blayout.addChild(image);
+
+        button.id = fullpath;
+        button.layoutParams = lp;
+        button.fontDescription = fd;
+        button.text = text;
+        button.skinBg = "TBButton.flat";
+        blayout.addChild(button);
+
+        return blayout;
+    }
+
+
+    private currentContentFolder: string;
+
+
+}
 
-print(folders);
-*/
+export = ProjectFrame;

+ 3 - 1
Data/AtomicEditor/Resources/EditorData/AtomicEditor/typescript/ui/ScriptWidget.ts

@@ -1,6 +1,6 @@
 
 
-export class ScriptWidget extends Atomic.UIWidget {
+class ScriptWidget extends Atomic.UIWidget {
 
 	constructor() {
 
@@ -34,3 +34,5 @@ export class ScriptWidget extends Atomic.UIWidget {
 	}
 
 }
+
+export = ScriptWidget;

+ 1 - 2
Data/AtomicEditor/Resources/EditorData/AtomicEditor/typescript/ui/modal/MessageModal.ts

@@ -2,7 +2,7 @@
 import UIEvents = require("../UIEvents");
 import Editor = require("../../editor/Editor");
 
-export class MessageModal extends Atomic.JSScriptObject
+export class MessageModal extends Atomic.ScriptObject
 {
 
   showErrorWindow(title:string, message:string):void {
@@ -13,7 +13,6 @@ export class MessageModal extends Atomic.JSScriptObject
 
   }
 
-
   constructor() {
 
     super();

+ 9 - 0
Source/Atomic/UI/UI.cpp

@@ -40,6 +40,7 @@ using namespace tb;
 #include "UICheckBox.h"
 #include "UISelectList.h"
 #include "UIMessageWindow.h"
+#include "UISkinImage.h"
 
 namespace tb
 {
@@ -487,6 +488,14 @@ UIWidget* UI::WrapWidget(tb::TBWidget* widget)
         return editfield;
     }
 
+    if (widget->IsOfType<TBSkinImage>())
+    {
+        UISkinImage* skinimage = new UISkinImage(context_, "", false);
+        skinimage->SetWidget(widget);
+        widgetWrap_[widget] = skinimage;
+        return skinimage;
+    }
+
     if (widget->IsOfType<TBImageWidget>())
     {
         UIImageWidget* imagewidget = new UIImageWidget(context_, false);

+ 34 - 0
Source/Atomic/UI/UIFontDescription.cpp

@@ -0,0 +1,34 @@
+#include <TurboBadger/tb_widgets.h>
+#include <TurboBadger/tb_widgets_common.h>
+#include <TurboBadger/tb_layout.h>
+
+#include "UI.h"
+#include "UIEvents.h"
+#include "UIWidget.h"
+#include "UIFontDescription.h"
+
+using namespace tb;
+
+namespace Atomic
+{
+
+UIFontDescription::UIFontDescription(Context* context) : Object(context)
+{
+}
+
+UIFontDescription::~UIFontDescription()
+{
+
+}
+
+void UIFontDescription::SetId(const String& id)
+{
+    desc_.SetID(TBIDC(id.CString()));
+}
+
+void UIFontDescription::SetSize(int size)
+{
+    desc_.SetSize(size);
+}
+
+}

+ 31 - 0
Source/Atomic/UI/UIFontDescription.h

@@ -0,0 +1,31 @@
+
+
+#pragma once
+
+#include "UIWidget.h"
+
+namespace Atomic
+{
+
+class UIFontDescription : public Object
+{
+    OBJECT(UIFontDescription)
+
+public:
+
+    UIFontDescription(Context* context);
+    virtual ~UIFontDescription();
+
+    void SetId(const String& id);
+    void SetSize(int size);
+
+    tb::TBFontDescription* GetTBFontDescription() { return &desc_; }
+
+private:
+
+    tb::TBFontDescription desc_;
+
+};
+
+
+}

+ 9 - 0
Source/Atomic/UI/UILayout.cpp

@@ -13,6 +13,15 @@ using namespace tb;
 namespace Atomic
 {
 
+UILayoutParams::UILayoutParams(Context* context) : Object(context)
+{
+}
+
+UILayoutParams::~UILayoutParams()
+{
+}
+
+
 UILayout::UILayout(Context* context, bool createWidget) : UIWidget(context, false)
 {
     if (createWidget)

+ 19 - 0
Source/Atomic/UI/UILayout.h

@@ -6,6 +6,25 @@
 namespace Atomic
 {
 
+class UILayoutParams : public Object
+{
+    OBJECT(UILayoutParams)
+
+public:
+
+    UILayoutParams(Context* context);
+    virtual ~UILayoutParams();
+
+    void SetHeight(int height) { params_.SetHeight(height); }
+
+    tb::LayoutParams* GetTBLayoutParams() { return &params_; }
+
+private:
+
+    tb::LayoutParams params_;
+
+};
+
 
 class UILayout : public UIWidget
 {

+ 46 - 5
Source/Atomic/UI/UIListView.cpp

@@ -21,6 +21,7 @@ public:
         : TBGenericStringItem(str, id), source_(source), parent_(0),
           depth_(0), widget_(0), expanded_(false), icon_(icon)
     {
+
     }
 
     ListViewItem* AddChild(const char* text, const char* icon, const TBID &id);
@@ -179,11 +180,9 @@ TBWidget *ListViewItemSource::CreateItemWidget(int index, TBSelectItemViewer *vi
     return nullptr;
 }
 
-//-----------------------------------------------------------------------------------
-
 UIListView::UIListView(Context* context, bool createWidget) :
     UIWidget(context, createWidget),
-    source_(0)
+    source_(0), itemLookupId_(0)
 {
     rootList_ = new UISelectList(context);
 
@@ -205,21 +204,63 @@ UIListView::~UIListView()
 
 }
 
-void UIListView::AddItem(const String& text, const String& icon, const String& id)
+unsigned UIListView::AddRootItem(const String& text, const String& icon, const String& id)
 {
     ListViewItem* item = new ListViewItem(text.CString(), TBID(id.CString()), icon.CString(), source_);
     source_->AddItem(item);
+
+    itemLookup_[itemLookupId_++] = item;
+    return itemLookupId_ - 1;
 }
 
-void UIListView::DeleteAllItems()
+unsigned UIListView::AddChildItem(unsigned parentItemID, const String& text, const String& icon, const String& id)
+{
+    if (!itemLookup_.Contains(parentItemID))
+        return -1;
+
+    ListViewItem* item = itemLookup_[parentItemID];
+
+    ListViewItem* child = item->AddChild(text.CString(), icon.CString(), TBID(id.CString()));
+
+    itemLookup_[itemLookupId_++] = child;
+    return itemLookupId_ - 1;
+
+}
+
+void UIListView::SetExpanded(unsigned itemID, bool value)
 {
+    if (!itemLookup_.Contains(itemID))
+        return;
+
+    itemLookup_[itemID]->SetExpanded(value);
 
 }
 
 
+void UIListView::DeleteAllItems()
+{
+    itemLookup_.Clear();
+    source_->DeleteAllItems();
+}
+
+
 void UIListView::SelectItemByID(const String& id)
 {
+    TBID tid = TBIDC(id.CString());
 
+    for (int i = 0; i < source_->GetNumItems(); i++)
+    {
+        ListViewItem* item = source_->GetItem(i);
+
+        if (tid == item->id)
+        {
+            item->SetExpanded(true);
+            rootList_->SetValue(i);
+            rootList_->InvalidateList();
+            return;
+        }
+
+    }
 }
 
 

+ 10 - 2
Source/Atomic/UI/UIListView.h

@@ -8,6 +8,7 @@ namespace Atomic
 {
 
 class ListViewItemSource;
+class ListViewItem;
 
 class UIListView : public UIWidget
 {
@@ -20,7 +21,11 @@ public:
     /// Destruct.
     virtual ~UIListView();
 
-    void AddItem(const String& text, const String& icon, const String& id);
+    unsigned AddRootItem(const String& text, const String& icon, const String& id);
+    unsigned AddChildItem(unsigned parentItemID, const String& text, const String& icon, const String& id);
+
+    void SetExpanded(unsigned itemID, bool value);
+
     void DeleteAllItems();
     void SelectItemByID(const String& id);
 
@@ -29,9 +34,12 @@ public:
 private:
 
     SharedPtr<UISelectList> rootList_;
-
     ListViewItemSource* source_;
 
+    HashMap<unsigned,ListViewItem*> itemLookup_;
+
+    unsigned itemLookupId_;
+
 };
 
 }

+ 41 - 0
Source/Atomic/UI/UISelectList.cpp

@@ -38,6 +38,47 @@ void UISelectList::SetFilter(const String& filter)
     ((TBSelectList*)widget_)->SetFilter(filter.CString());
 }
 
+void UISelectList::SetValue(int value)
+{
+    if (!widget_)
+        return;
+
+    ((TBSelectList*)widget_)->SetValue(value);
+
+}
+
+int UISelectList::GetValue()
+{
+    if (!widget_)
+        return 0;
+
+    return ((TBSelectList*)widget_)->GetValue();
+
+}
+
+void UISelectList::InvalidateList()
+{
+    if (!widget_)
+        return;
+
+    return ((TBSelectList*)widget_)->InvalidateList();
+}
+
+String UISelectList::GetSelectedItemID()
+{
+    if (!widget_)
+        return "";
+
+    String id_;
+
+    TBID id = ((TBSelectList*)widget_)->GetSelectedItemID();
+
+    GetSubsystem<UI>()->GetTBIDString(id, id_);
+
+    return id_;
+
+}
+
 void UISelectList::SetSource(UISelectItemSource* source)
 {
     if (!widget_)

+ 6 - 0
Source/Atomic/UI/UISelectList.h

@@ -24,6 +24,12 @@ public:
     void SetFilter(const String& filter);
 
     void SetSource(UISelectItemSource* source);
+    void InvalidateList();
+
+    void SetValue(int value);
+    int GetValue();
+
+    String GetSelectedItemID();
 
     tb::TBSelectList* GetTBSelectList();
 

+ 39 - 0
Source/Atomic/UI/UISkinImage.cpp

@@ -0,0 +1,39 @@
+
+#include <TurboBadger/tb_widgets.h>
+#include <TurboBadger/tb_widgets_common.h>
+#include <TurboBadger/tb_editfield.h>
+
+#include "UI.h"
+#include "UIEvents.h"
+#include "UISkinImage.h"
+
+using namespace tb;
+
+namespace Atomic
+{
+
+UISkinImage::UISkinImage(Context* context, const String& bitmapID, bool createWidget) : UIWidget(context, false)
+{
+    if (createWidget)
+    {
+        if (bitmapID.Length())
+            widget_ = new TBSkinImage(TBIDC(bitmapID.CString()));
+        else
+            widget_ = new TBSkinImage();
+
+        widget_->SetDelegate(this);
+        GetSubsystem<UI>()->WrapWidget(this, widget_);
+    }
+}
+
+UISkinImage::~UISkinImage()
+{
+
+}
+
+bool UISkinImage::OnEvent(const tb::TBWidgetEvent &ev)
+{
+    return false;
+}
+
+}

+ 26 - 0
Source/Atomic/UI/UISkinImage.h

@@ -0,0 +1,26 @@
+
+#pragma once
+
+#include "UIWidget.h"
+
+namespace Atomic
+{
+
+class UISkinImage : public UIWidget
+{
+    OBJECT(UISkinImage)
+
+public:
+
+    UISkinImage(Context* context, const String& bitmapID, bool createWidget = true);
+    virtual ~UISkinImage();
+
+protected:
+
+    virtual bool OnEvent(const tb::TBWidgetEvent &ev);
+
+private:
+
+};
+
+}

+ 37 - 0
Source/Atomic/UI/UIWidget.cpp

@@ -6,6 +6,8 @@
 #include "UIEvents.h"
 #include "UI.h"
 #include "UIWidget.h"
+#include "UILayout.h"
+#include "UIFontDescription.h"
 
 using namespace tb;
 
@@ -249,6 +251,41 @@ void UIWidget::Die()
 
 }
 
+void UIWidget::SetLayoutParams(UILayoutParams* params)
+{
+    if (!widget_)
+        return;
+
+    widget_->SetLayoutParams(*(params->GetTBLayoutParams()));
+
+}
+
+void UIWidget::SetFontDescription(UIFontDescription* fd)
+{
+    if (!widget_)
+        return;
+
+    widget_->SetFontDescription(*(fd->GetTBFontDescription()));
+
+}
+
+void UIWidget::DeleteAllChildren()
+{
+    if (!widget_)
+        return;
+
+    widget_->DeleteAllChildren();
+}
+
+void UIWidget::SetSkinBg(const String& id)
+{
+    if (!widget_)
+        return;
+
+    widget_->SetSkinBg(TBIDC(id.CString()));
+
+}
+
 void UIWidget::RemoveChild(UIWidget* child, bool cleanup)
 {
     if (!widget_ || !child)

+ 10 - 1
Source/Atomic/UI/UIWidget.h

@@ -13,6 +13,9 @@ class TBWidget;
 namespace Atomic
 {
 
+class UILayoutParams;
+class UIFontDescription;
+
 /// Wraps a TurboBadger widget in our Object model
 class UIWidget : public Object, public tb::TBWidgetDelegate
 {
@@ -34,14 +37,20 @@ public:
     void SetPosition(int x, int y);
     void SetText(const String& text);
 
+    void SetSkinBg(const String& id);
+    void SetLayoutParams(UILayoutParams* params);
+    void SetFontDescription(UIFontDescription* fd);
+
     UIWidget* GetParent();
     UIWidget* GetContentRoot();
 
     void RemoveChild(UIWidget* child, bool cleanup = true);
 
+    void DeleteAllChildren();
+
     // String ID
     const String& GetId();
-    void SetId(const String& id);
+    virtual void SetId(const String& id);
 
     void Center();
     void SetGravity(/*WIDGET_GRAVITY*/ unsigned gravity);

+ 2 - 0
Source/AtomicJS/Javascript/JSAtomic.cpp

@@ -15,6 +15,7 @@
 #include "JSVM.h"
 #include "JSComponent.h"
 #include "JSCore.h"
+#include "JSFileSystem.h"
 #include "JSGraphics.h"
 #include "JSIO.h"
 #include "JSUIAPI.h"
@@ -256,6 +257,7 @@ void jsapi_init_atomic(JSVM* vm)
 
     // extensions
     jsapi_init_core(vm);
+    jsapi_init_filesystem(vm);
     jsapi_init_io(vm);
     jsapi_init_graphics(vm);
     jsapi_init_ui(vm);

+ 25 - 2
Source/AtomicJS/Javascript/JSCore.cpp

@@ -2,6 +2,8 @@
 // Please see LICENSE.md in repository root for license information
 // https://github.com/AtomicGameEngine/AtomicGameEngine
 
+#include <Atomic/Core/ProcessUtils.h>
+
 #include "JSCore.h"
 #include "JSEventHelper.h"
 #include "JSVM.h"
@@ -151,16 +153,37 @@ static int Object_SendEvent(duk_context* ctx)
 
 }
 
+static int Atomic_GetArguments(duk_context* ctx)
+{
+    duk_push_array(ctx);
+
+    for (unsigned i = 0; i < GetArguments().Size(); i++)
+    {
+        duk_push_string(ctx, GetArguments()[i].CString());
+        duk_put_prop_index(ctx, -2, i);
+    }
+
+    return 1;
+
+}
+
 void jsapi_init_core(JSVM* vm)
 {
     duk_context* ctx = vm->GetJSContext();
 
+    duk_get_global_string(ctx, "Atomic");
+
+    duk_push_c_function(ctx, Atomic_GetArguments, 0);
+    duk_put_prop_string(ctx, -2, "getArguments");
+
+    duk_pop(ctx); // pop Atomic object
+
     js_class_get_prototype(ctx, "Atomic", "AObject");
     duk_push_c_function(ctx, Object_SubscribeToEvent, DUK_VARARGS);
     duk_put_prop_string(ctx, -2, "subscribeToEvent");
     duk_push_c_function(ctx, Object_SendEvent, DUK_VARARGS);
-    duk_put_prop_string(ctx, -2, "sendEvent");
-    duk_pop(ctx);
+    duk_put_prop_string(ctx, -2, "sendEvent");    
+    duk_pop(ctx); // pop AObject prototype
 }
 
 }

+ 76 - 0
Source/AtomicJS/Javascript/JSFileSystem.cpp

@@ -0,0 +1,76 @@
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// Please see LICENSE.md in repository root for license information
+// https://github.com/AtomicGameEngine/AtomicGameEngine
+
+#include <Atomic/Core/ProcessUtils.h>
+
+#include "JSCore.h"
+#include "JSEventHelper.h"
+#include "JSVM.h"
+
+namespace Atomic
+{
+
+static int Atomic_SplitPath(duk_context* ctx)
+{
+    String path = duk_require_string(ctx, 0);
+
+    String pathName;
+    String fileName;
+    String ext;
+
+    duk_push_object(ctx);
+
+    SplitPath(path, pathName, fileName, ext);
+
+    duk_push_string(ctx, pathName.CString());
+    duk_put_prop_string(ctx, -2, "pathName");
+
+    duk_push_string(ctx, fileName.CString());
+    duk_put_prop_string(ctx, -2, "fileName");
+
+    duk_push_string(ctx, ext.CString());
+    duk_put_prop_string(ctx, -2, "ext");
+
+    return 1;
+
+}
+
+static int Atomic_AddTrailingSlash(duk_context* ctx)
+{
+    String path = duk_require_string(ctx, 0);
+
+    duk_push_string(ctx, AddTrailingSlash(path).CString());
+
+    return 1;
+}
+
+static int Atomic_GetParentPath(duk_context* ctx)
+{
+    String path = duk_require_string(ctx, 0);
+
+    duk_push_string(ctx, GetParentPath(path).CString());
+
+    return 1;
+}
+
+
+void jsapi_init_filesystem(JSVM* vm)
+{
+    duk_context* ctx = vm->GetJSContext();
+
+    duk_get_global_string(ctx, "Atomic");
+
+    duk_push_c_function(ctx, Atomic_SplitPath, 1);
+    duk_put_prop_string(ctx, -2, "splitPath");
+
+    duk_push_c_function(ctx, Atomic_AddTrailingSlash, 1);
+    duk_put_prop_string(ctx, -2, "addTrailingSlash");
+
+    duk_push_c_function(ctx, Atomic_GetParentPath, 1);
+    duk_put_prop_string(ctx, -2, "getParentPath");
+
+    duk_pop(ctx); // pop Atomic object
+}
+
+}

+ 16 - 0
Source/AtomicJS/Javascript/JSFileSystem.h

@@ -0,0 +1,16 @@
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// Please see LICENSE.md in repository root for license information
+// https://github.com/AtomicGameEngine/AtomicGameEngine
+
+#pragma once
+
+#include "JSAPI.h"
+
+namespace Atomic
+{
+
+class JSVM;
+
+void jsapi_init_filesystem(JSVM* vm);
+
+}

+ 2 - 2
Source/AtomicJS/Javascript/JSScriptObject.cpp

@@ -4,12 +4,12 @@
 namespace Atomic
 {
 
-JSScriptObject::JSScriptObject(Context* context) : Object(context)
+ScriptObject::ScriptObject(Context* context) : Object(context)
 {
 
 }
 
-JSScriptObject::~JSScriptObject()
+ScriptObject::~ScriptObject()
 {
 
 }

+ 4 - 4
Source/AtomicJS/Javascript/JSScriptObject.h

@@ -8,16 +8,16 @@ namespace Atomic
 
 /// ScriptObject makes it possible for script classes to inherit "directly" from
 /// Object (which is abstract) and use the event system, etc
-class JSScriptObject : public Object
+class ScriptObject : public Object
 {
 
-    OBJECT(JSScriptObject);
+    OBJECT(ScriptObject);
 
 public:
     /// Construct.
-    JSScriptObject(Context* context);
+    ScriptObject(Context* context);
     /// Destruct.
-    virtual ~JSScriptObject();
+    virtual ~ScriptObject();
 
 };
 

+ 2 - 0
Source/AtomicJS/Javascript/JSUI.cpp

@@ -49,6 +49,8 @@ JSUI::JSUI(Context* context) : Object(context),
     uiTypes_["UISelectLost"] = true;
     uiTypes_["UIListView"] = true;
     uiTypes_["UIMessageWindow"] = true;
+    uiTypes_["UISkinImage"] = true;
+
 }
 
 JSUI::~JSUI()

+ 1 - 1
Source/AtomicJS/Packages/Atomic/Javascript.json

@@ -1,5 +1,5 @@
 {
 	"name" : "Javascript",
 	"sources" : ["Source/AtomicJS/Javascript"],
-	"classes" : ["JSVM", "JSComponent", "JSMetrics", "JSEventHelper", "JSScriptObject"]
+	"classes" : ["JSVM", "JSComponent", "JSMetrics", "JSEventHelper", "ScriptObject"]
 }

+ 2 - 1
Source/AtomicJS/Packages/Atomic/UI.json

@@ -6,7 +6,8 @@
 	"classes" : ["UIWidget", "UILayout", "UIView", "UIWindow", "UIButton", "UITextField",
 								"UISelectItem", "UISelectItemSource", "UIMenuWindow", "UIEditField",
 								"UIImageWidget", "UIClickLabel", "UICheckBox", "UIMenuItem", "UIMenuItemSource",
-								"UISelectList", "UIListView", "UIMessageWindow"],
+								"UISelectList", "UIListView", "UIMessageWindow", "UILayoutParams", "UIFontDescription",
+								"UISkinImage"],
 	"overloads" : {
 	}
 }

+ 8 - 0
Source/ToolCore/Project/Project.cpp

@@ -13,6 +13,7 @@
 #include <Atomic/Resource/JSONFile.h>
 
 #include "../ToolSystem.h"
+#include "../ToolEvents.h"
 #include "../Platform/Platform.h"
 
 #include "ProjectFile.h"
@@ -105,6 +106,7 @@ bool Project::Load(const String& fullpath)
 
     projectPath_ = GetPath(fullpath);
     projectFilePath_ = fullpath;
+
     SharedPtr<ProjectFile> pfile(new ProjectFile(context_));
     bool result = pfile->Load(this);
 
@@ -113,6 +115,12 @@ bool Project::Load(const String& fullpath)
     LoadBuildSettings();
     LoadUserPrefs();
 
+    if ( true /*result*/) {
+        VariantMap data;
+        data[ProjectLoaded::P_PROJECTPATH] = projectPath_;
+        SendEvent(E_PROJECTLOADED, data);
+    }
+
     return result;
 }
 

+ 16 - 0
Source/ToolCore/ToolEvents.h

@@ -0,0 +1,16 @@
+
+#pragma once
+
+#include <Atomic/Core/Object.h>
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+EVENT(E_PROJECTLOADED, ProjectLoaded)
+{
+    PARAM(P_PROJECTPATH, ProjectPath);    // string
+}
+
+}