diff --git a/src/core/BaseApplication.coffee b/src/core/BaseApplication.coffee index ba288e5..11f7f9e 100644 --- a/src/core/BaseApplication.coffee +++ b/src/core/BaseApplication.coffee @@ -84,7 +84,8 @@ class BaseApplication extends this.OS.GUI.BaseModel toggle: () -> @trigger "toggle" - + + onexit: (evt) -> @cleanup(evt) if not evt.prevent diff --git a/src/core/BaseDialog.coffee b/src/core/BaseDialog.coffee index 5981ca4..a381a48 100644 --- a/src/core/BaseDialog.coffee +++ b/src/core/BaseDialog.coffee @@ -307,10 +307,11 @@ class FileDiaLog extends BaseDialog if me.data and me.data.mimes #verify the mime m = false - for v in me.data.mimes - if f.mime.match (new RegExp v, "g") - m = true - break + if f.mime + for v in me.data.mimes + if f.mime.match (new RegExp v, "g") + m = true + break return me.notify __("Only {0} could be selected", me.data.mimes.join(",")) unless m d = f.path d = f.path.asFileHandler().parent() if f.type is "file" diff --git a/src/core/BaseModel.coffee b/src/core/BaseModel.coffee index f20e5cc..89e63b0 100644 --- a/src/core/BaseModel.coffee +++ b/src/core/BaseModel.coffee @@ -77,6 +77,11 @@ class BaseModel @dialog.title = title @dialog.init() + ask: (t, m, f) -> + @._gui.openDialog "YesNoDialog", (d) -> + f() if d + , t, { text: m } + publish: (t, m, e) -> mt = @meta() _courrier.trigger t, { id: @pid, name: @name, data: { m: m, icon: mt.icon, iconclass: mt.iconclass }, error: e } diff --git a/src/packages/AntOSDK/main.coffee b/src/packages/AntOSDK/main.coffee index 66278ad..a649408 100644 --- a/src/packages/AntOSDK/main.coffee +++ b/src/packages/AntOSDK/main.coffee @@ -19,19 +19,21 @@ class AntOSDK extends this.OS.GUI.BaseApplication constructor: ( args ) -> super "AntOSDK", args - @currfile = if @args and @args.length > 0 then @args[0].asFileHandler() else null + @prjfile = if @args and @args.length > 0 then @args[0].asFileHandler() else null loadScheme: () -> - path = "#{@meta().path}/" + if @currfile then "scheme.html" else "welcome.html" + path = "#{@meta().path}/" + if @prjfile then "scheme.html" else "welcome.html" @render path main: () -> me = @ @scheme.set "apptitle", "AntOSDK" - @statbar = @find "editorstat" - if not @currfile + @output = @find "output" + if not @prjfile (@find "btnnewprj").set "onbtclick", () -> me.newProject (path) -> - me.currfile = "#{path}/project.apj".asFileHandler() + me.prjfile = "#{path}/project.apj".asFileHandler() me.loadScheme() + (@find "btnopenprj").set "onbtclick", () -> + me.actionProject "#{me.name}-Open" return @initWorkspace() @@ -39,9 +41,10 @@ class AntOSDK extends this.OS.GUI.BaseApplication me = @ @fileview = @find "fileview" div = @find "datarea" - + @currfile = "Untitled".asFileHandler() ace.require "ace/ext/language_tools" + @prjfile.dirty = false @.editor = ace.edit div @.editor.setOptions { enableBasicAutocompletion: true, @@ -85,12 +88,12 @@ class AntOSDK extends this.OS.GUI.BaseApplication me.editor.setTheme e.data.mode themelist.set "items", ldata - stat = @find "editorstat" + statbar = @find "editorstat" #status stup = (e) -> c = me.editor.session.selection.getCursor() l = me.editor.session.getLength() - stat.set "text", __("Row {0}, col {1}, lines: {2}", c.row, c.column, l) + statbar.set "text", __("Row {0}, col {1}, lines: {2}", c.row, c.column, l) stup(0) @.editor.getSession().selection.on "changeCursor", (e) -> stup(e) @editormux = false @@ -104,6 +107,7 @@ class AntOSDK extends this.OS.GUI.BaseApplication me.tabarea.update() @on "resize", () -> me.editor.resize() + @on "vboxchange", () -> me.editor.resize() @on "focus", () -> me.editor.focus() @fileview.set "fetch", (e, f) -> @@ -125,20 +129,28 @@ class AntOSDK extends this.OS.GUI.BaseApplication @tabarea.set "onitemclose", (e) -> it = e.item.item return false unless it + me.fileview.set "preventUpdate", true return me.closeTab it unless it.dirty me.openDialog "YesNoDialog", (d) -> return me.closeTab it if d me.editor.focus() , __("Close tab"), { text: __("Close without saving ?") } return false + (@find "log-clear").set "onbtclick", (e) -> + ($ me.output).empty() #@tabarea.set "closable", true @bindKey "ALT-N", () -> me.actionFile "#{me.name}-New" @bindKey "ALT-O", () -> me.actionFile "#{me.name}-Open" @bindKey "CTRL-S", () -> me.actionFile "#{me.name}-Save" @bindKey "ALT-W", () -> me.actionFile "#{me.name}-Saveas" - @openProject @currfile if @currfile + @bindKey "CTRL-R", () -> me.bnR() + @bindKey "CTRL-B", () -> me.actionBuild "#{me.name}-Build" + @openProject @prjfile if @prjfile @trigger "calibrate" - + + @log "ERROR", "This is an error" + @log "WARNING", "This is a warning" + newProject: (f) -> me = @ @openDialog "FileDiaLog", (d, n, p) -> @@ -150,6 +162,7 @@ class AntOSDK extends this.OS.GUI.BaseApplication # create asset dir dirs = [ rpath, + "#{rpath}/build", "#{rpath}/javascripts", "#{rpath}/css", "#{rpath}/coffees", @@ -162,7 +175,7 @@ class AntOSDK extends this.OS.GUI.BaseApplication dir = dir.parent().asFileHandler() dir.mk name, (r) -> return me.error __("Error when create directory: {0}", r.error) if r.error - me.statbar.set "text", __("Created directory: {0}", dir.path + "/" + name) + me.log "INFO", __("Created directory: {0}", dir.path + "/" + name) #console.log "created", dir.path + "/" + name fn list, f1 @@ -198,11 +211,12 @@ class AntOSDK extends this.OS.GUI.BaseApplication path: "#{rpath}/project.apj", content: """ { + "name": "#{n}", "root": "#{d}/#{n}", "css": [], "javascripts": [], "coffees": ["coffees/main.coffee"], - "copies": ["assets/scheme.htm", "package.json"] + "copies": ["assets/scheme.html", "package.json"] } """ }, @@ -234,18 +248,28 @@ class AntOSDK extends this.OS.GUI.BaseApplication file.cache = entry.content file.write "text/plain", (res) -> return me.error __("Cannot create file: {0}", res.error) if res.error - me.statbar.set "text", __("Created file: {0}", file.path) + me.log "INFO", __("Created file: {0}", file.path) fn1 list, f2 fn1 files, f , "__(New Project at)", { file: { basename: __("ProjectName") } } openProject: (file) -> me = @ - file.read (d) -> - me.chdir d.root if d.root - me.pinfo = d - me.open "#{d.root}/coffees/main.coffee".asFileHandler() - ,"json" + me.prjfile = file + if(me.tabarea) + file.read (d) -> + me.log "INFO", __("Opening {0}", me.prjfile.path) + me.tabarea.set "selected", -1 + me.tabarea.set "items", [] + me.currfile = "#{d.root}/coffees/main.coffee".asFileHandler() + me.currfile.dirty = false + me.chdir d.root if d.root + me.prjfile.cache = d + me.log "INFO", __("Opening {0}", me.currfile.path) + me.open me.currfile + ,"json" + else + me.loadScheme() open: (file) -> #find table @@ -344,7 +368,6 @@ class AntOSDK extends this.OS.GUI.BaseApplication @currfile.cache = @editor.getValue() @currfile.cursor = @editor.selection.getCursor() @currfile = file - m = "ace/mode/text" m = (@modes.getModeForPath file.path) if file.path.toString() isnt "Untitled" @mlist.set "selected", m.idx @@ -378,16 +401,37 @@ class AntOSDK extends this.OS.GUI.BaseApplication menu: () -> me = @ - menu = [{ + menu = [ + { text: "__(Project)", child: [ - { text: "__(New)", dataid: "#{@name}-New", shortcut: "A-N" }, - { text: "__(Open)", dataid: "#{@name}-Open", shortcut: "A-O" }, + { text: "__(New)", dataid: "#{@name}-New", }, + { text: "__(Open)", dataid: "#{@name}-Open" }, + { text: "__(Save)", dataid: "#{@name}-Save" } + ], + onmenuselect: (e) -> me.actionProject e.item.data.dataid + }, + { + text: "__(File)", + child: [ + { text: "__(New)", dataid: "#{@name}-New", shortcut: "A-N" }, + { text: "__(Open)", dataid: "#{@name}-Open", shortcut: "A-O" }, { text: "__(Save)", dataid: "#{@name}-Save", shortcut: "C-S" }, { text: "__(Save as)", dataid: "#{@name}-Saveas", shortcut: "A-W" } ], onmenuselect: (e) -> me.actionFile e.item.data.dataid - }] + }, + { + text: "__(Build)", + child: [ + { text: "__(Build and Run)", dataid: "#{@name}-Run", shortcut: "C-R" }, + { text: "__(Build release)", dataid: "#{@name}-Release", shortcut: "C-P" }, + { text: "__(Build)", dataid: "#{@name}-Build", shortcut: "C-B" }, + { text: "__(Build Options)", dataid: "#{@name}-Options", shortcut: "A-P" } + ], + onmenuselect: (e) -> me.actionBuild e.item.data.dataid + } + ] menu actionFile: (e) -> @@ -420,18 +464,191 @@ class AntOSDK extends this.OS.GUI.BaseApplication when "#{@name}-New" @open "Untitled".asFileHandler() + actionProject: (e) -> + me = @ + switch e + when "#{@name}-Open" + fn = () -> + me.openDialog "FileDiaLog", (d, f, p) -> + me.prjfile = "#{d}/#{f}".asFileHandler() + me.log "clean" + me.openProject me.prjfile + , "__(Open Project)", { mimes: me.meta().mimes } + return fn() unless @isDirty() + @ask "__(Unsaved project)", "__(Ignore unsaved project ?)", () -> + fn() + when "#{@name}-New" + fn = () -> + me.log "clean" + me.newProject (p) -> + me.openProject "#{p}/project.apj".asFileHandler() + return fn() unless @isDirty() + @ask "__(Unsaved project)", "__(Ignore unsaved project ?)", () -> + fn() + + + actionBuild: (e) -> + me = @ + switch e + when "#{@name}-Run" then me.bnR() + when "#{@name}-Build" + me.build().then(() ->).catch (ex) -> + me.log "ERROR", ex.toString() + + + isDirty: () -> + return false unless @tabarea + dirties = ( v for v in @tabarea.get "items" when v.dirty ) + return true if dirties.length > 0 or @prjfile.dirty + return false + cleanup: (evt) -> return unless @currfile - dirties = ( v for v in @tabarea.get "items" when v.dirty ) - return if dirties.length is 0 + return unless @isDirty() me = @ evt.preventDefault() - @.openDialog "YesNoDialog", (d) -> - if d - v.dirty = false for v in dirties - me.quit() - , "__(Quit)", { text: __("Ignore all {0} unsaved files ?", dirties.length) } + dirties = ( v for v in @tabarea.get "items" when v.dirty ) + @ask "__(Quit)", __("Ignore all {0} unsaved files ?", dirties.length), () -> + v.dirty = false for v in dirties + @prjfile.dirty = false + me.quit() + log: (t, m) -> + return $(@output).empty() if t is "clean" + p = ($ "
").attr("class", t.toLowerCase())[0]
+ $(p).html "#{t}: #{m.__()}"
+ ($ @output).append p
+ ($ @output).scrollTop @output.scrollHeight
+
+ verify: () ->
+ me = @
+ return new Promise (r, e) ->
+ return e me._api.throwe "Project not found" unless me.prjfile.cache
+ # perform the verification on each coffee file
+ list = ("#{me.prjfile.cache.root}/#{v}" for v in me.prjfile.cache.coffees)
+ return r() if list.length is 0
+ fn = (l) ->
+ return r() if l.length is 0
+ f = (l.splice 0, 1)[0].asFileHandler()
+ me.log "INFO", __("Verifying {0}", f.path)
+ f.read (d) ->
+ try
+ CoffeeScript.nodes d
+ fn l
+ catch ex
+ e ex
+ return fn list
+
+ cat: (files, t) ->
+ me = @
+ return new Promise (r, e) ->
+ fn = (l) ->
+ return r(t) if l.length is 0
+ f = (l.splice 0, 1)[0].asFileHandler()
+ f.read (d) ->
+ t = t + "\n" + d
+ fn l
+
+ return fn files
+
+ copy: (files, to) ->
+ me = @
+ return new Promise (r, e) ->
+ fn = (l) ->
+ return r() if l.length is 0
+ f = (l.splice 0, 1)[0].asFileHandler()
+ tof = "#{to}/#{f.basename}".asFileHandler()
+ f.read (d) ->
+ tof.cache = new Blob [d], { type: f.info.mime }
+ tof.write f.info.mime, (res) ->
+ return e res.error if res.error
+ fn(l)
+ , "binary"
+
+ return fn files
+
+ compile: () ->
+ me = @
+ list = ("#{me.prjfile.cache.root}/#{v}" for v in me.prjfile.cache.coffees)
+ t = ""
+ @verify().then () ->
+ me.cat(list, t)
+ .then (code) ->
+ return new Promise (r, e) ->
+ try
+ jsrc = CoffeeScript.compile code
+ me.log "SUCCESS", __("Compiled successful")
+ r jsrc
+ catch ex
+ e ex
+
+ build: () ->
+ me = @
+ @log "clean"
+ @compile().then (r) ->
+ # cat to the javascript
+ list = ("#{me.prjfile.cache.root}/#{v}" for v in me.prjfile.cache.javascripts)
+ me.cat(list, r).then (jsrc) ->
+ return new Promise (r, e) ->
+ r jsrc
+ .then (jsrc) ->
+ # write javascript src to file
+ return new Promise (r, e) ->
+ fp = "#{me.prjfile.cache.root}/build/main.js".asFileHandler()
+ fp.cache = jsrc
+ fp.write "text/plain", (res) ->
+ return e res.error if res.error
+ me.log "SUCCESS", __("Generated {0}", fp.path)
+ r()
+ .then () ->
+ # cat the css file
+ csslist = ("#{me.prjfile.cache.root}/#{v}" for v in me.prjfile.cache.css)
+ csstxt = ""
+ me.cat(csslist, csstxt).then (txt) ->
+ return new Promise (r, e) ->
+ return r() if txt is ""
+ fp = "#{me.prjfile.cache.root}/build/main.css".asFileHandler()
+ fp.cache = txt
+ fp.write "text/plain", (d) ->
+ return e d.error if d.error
+ me.log "SUCCESS", __("Generated {0}", fp.path)
+ r()
+ .then () ->
+ # copy the remain files
+ copylist = ("#{me.prjfile.cache.root}/#{v}" for v in me.prjfile.cache.copies)
+ me.copy copylist, "#{me.prjfile.cache.root}/build"
+ .then () ->
+ me.log "INFO", __("Build done")
+ return new Promise (r, e) -> r()
+
+ run: () ->
+ me = @
+ fp = "#{me.prjfile.cache.root}/build/package.json".asFileHandler()
+ fp.read (v) ->
+ me.log "INFO", __("Metadata found...")
+ v.text = v.name
+ v.path = "#{me.prjfile.cache.root}/build"
+ v.filename = me.prjfile.cache.name
+ v.type = "app"
+ v.mime = "antos/app"
+ v.icon = "#{v.path}/#{v.icon}" if v.icon
+ v.iconclass = "fa fa-adn" unless v.iconclass or v.icon
+ me.log "INFO", __("Installing...")
+ me.systemsetting.system.packages[me.prjfile.cache.name] = v
+ # todo: auto matic refresh menu
+ me._gui.refreshSystemMenu()
+ me._gui.buildSystemMenu()
+ me.log "INFO", __("Running {0}...", me.prjfile.cache.name)
+ me._gui.forceLaunch me.prjfile.cache.name
+ , "json"
+
+ bnR: () ->
+ me = @
+ @build().then () ->
+ me.run()
+ .catch (ex) ->
+ me.log "ERROR", ex.toString()
+
AntOSDK.singleton = false
AntOSDK.dependencies = [
"ace/ace",
diff --git a/src/packages/AntOSDK/main.css b/src/packages/AntOSDK/main.css
index 403ad69..81b84c8 100644
--- a/src/packages/AntOSDK/main.css
+++ b/src/packages/AntOSDK/main.css
@@ -13,6 +13,8 @@ afx-app-window[data-id="antOSDK"] afx-resizer{
}
afx-app-window[data-id="antOSDK"] afx-resizer[data-id="botrz"]
{
+ z-index: 9;
+ border-top: 1px solid #a6a6a6;
background-color: #2f3129;
}
@@ -33,30 +35,59 @@ afx-app-window[data-id="antOSDK"] div.welcome-cnt p{
width: 100%;
}
afx-app-window[data-id="antOSDK"] afx-label[data-id="editorstat"]{
- padding:5px;
+ padding-right:5px;
+ text-align: right;
display: inline-block;
}
-afx-app-window[data-id="antOSDK"] afx-vbox[data-id="bottom-vbox"]{
- background-color: #dfdfdf;
-}
afx-app-window[data-id="antOSDK"] .afx-window-content {
background-color: #f6F6F6;
}
afx-app-window[data-id="antOSDK"] div[data-id= "output"] {
background-color: #2f3129;
+ padding: 10px;
+ padding-left: 40px;
color:white;
+ overflow: auto;
+}
+afx-app-window[data-id="antOSDK"] div[data-id= "output"] p{
+ margin:0;
+ padding:0;
+ font-family: "HermitLight";
+ text-align: left;
+}
+afx-app-window[data-id="antOSDK"] div[data-id= "output"] p.error{
+ color: red;
+}
+afx-app-window[data-id="antOSDK"] div[data-id= "output"] p.warning{
+ color: orange;
+}
+afx-app-window[data-id="antOSDK"] div[data-id= "output"] p.success {
+ color: green;
}
afx-app-window[data-id="antOSDK"] afx-label.outputheader {
background-color: #2f3129;
font-weight: bold;
padding-left: 10px;
- border-bottom: 1px solid #a6a6a6;;
color:white;
}
afx-app-window[data-id="antOSDK"] afx-hbox[data-id="bottom-vbox"] {
- border-top: 1px solid #a6a6a6;
- border-bottom: 1px solid #a6a6a6;
+ background-color:#2f3129;
+}
+afx-app-window[data-id="antOSDK"] afx-hbox[data-id="bottom-vbox"] afx-button button{
+ background-color:#2f3129;
+ color:white;
+ border:0;
+ border-radius: 0;
+}
+afx-app-window[data-id="antOSDK"] afx-hbox[data-id="bottom-vbox"] afx-list-view > div.list-container > div {
+ background-color: #3c3c3c;
+ color:white;
+ border:0;
+ border-radius: 0;
+}
+afx-app-window[data-id="antOSDK"] afx-hbox[data-id="bottom-vbox"] afx-list-view > div.list-container > div::before{
+ color: white;
}
afx-tab-bar[data-id="tabarea"] afx-list-view > div.list-container > ul > li {
diff --git a/src/packages/AntOSDK/scheme.html b/src/packages/AntOSDK/scheme.html
index 655e1ed..9cdb4c1 100644
--- a/src/packages/AntOSDK/scheme.html
+++ b/src/packages/AntOSDK/scheme.html
@@ -6,13 +6,14 @@
-
+