Build and run app directly from antOSDK

This commit is contained in:
Xuan Sang LE 2018-03-19 19:11:38 +01:00
parent cd3bba7cf8
commit e8d4815e93
7 changed files with 317 additions and 59 deletions

View File

@ -84,7 +84,8 @@ class BaseApplication extends this.OS.GUI.BaseModel
toggle: () ->
@trigger "toggle"
onexit: (evt) ->
@cleanup(evt)
if not evt.prevent

View File

@ -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"

View File

@ -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 }

View File

@ -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 = ($ "<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",

View File

@ -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 {

View File

@ -6,13 +6,14 @@
<afx-tab-bar data-id="tabarea" data-height="23" closable = true></afx-tab-bar>
<div data-id="datarea" data-height="80%"></div>
<afx-resizer data-height="3" data-id="botrz"></afx-resizer>
<afx-label data-height="20" class="outputheader" iconclass= "fa fa-wpforms" text = "__(Output)"></afx-label>
<div data-id= "output" ></div>
<afx-hbox data-height="30" data-id="bottom-vbox">
<afx-label data-id="editorstat"></afx-label>
<afx-list-view data-width="160" data-id = "themelist" dropdown = "true" width="135"></afx-list-view>
<afx-list-view data-width="125" data-id = "modelist" dropdown = "true" width="100"></afx-list-view>
</afx-hbox>
<afx-label class="outputheader" iconclass= "fa fa-wpforms" text = "__(Output)"></afx-label>
<afx-list-view data-width="160" data-id = "themelist" dropdown = "true" width="135"></afx-list-view>
<afx-list-view data-width="125" data-id = "modelist" dropdown = "true" width="100"></afx-list-view>
<afx-button data-id = "log-clear" data-width="25" iconclass="fa fa-trash"></afx-button>
</afx-hbox>
<div data-id= "output" ></div>
<afx-label data-id="editorstat" data-height="20"></afx-label>
</afx-vbox>
</afx-hbox>
</afx-app-window>

View File

@ -1,13 +1,15 @@
<afx-app-window apptitle="" width="600" height="500" data-id="antOSDK">
<afx-hbox >
<div class = "welcome-cnt">
<afx-label text="__(Wecome to AntOSDK)" class="wmsg"></afx-label>
<p>
<afx-button data-id="btnnewprj" iconclass= "fa fa-plus-circle" text = "__(New project)"></afx-button>
<afx-button data-id="btnopenprj" iconclass = "fa fa-folder-open" text = "__(Open project)"></afx-button>
</p>
<afx-label data-id="editorstat" ></afx-label>
</div>
</afx-hbox>
<afx-vbox>
<afx-hbox >
<div class = "welcome-cnt">
<afx-label text="__(Wecome to AntOSDK)" class="wmsg"></afx-label>
<p>
<afx-button data-id="btnnewprj" iconclass= "fa fa-plus-circle" text = "__(New project)"></afx-button>
<afx-button data-id="btnopenprj" iconclass = "fa fa-folder-open" text = "__(Open project)"></afx-button>
</p>
</div>
</afx-hbox>
<div data-id= "output" ></div>
</afx-vbox>
</afx-app-window>