adapt the system with the new api

This commit is contained in:
lxsang 2020-05-10 21:39:42 +02:00
parent ae54c9a10c
commit f5e5d8501b
24 changed files with 1120 additions and 952 deletions

View File

@ -44,7 +44,7 @@ class BaseApplication extends this.OS.GUI.BaseModel
me.appmenu.set "items", []
me.dialog.hide() if me.dialog
@on "menuselect", (d) ->
switch d.e.item.data.dataid
switch d.data.item.get("data").dataid
when "#{me.name}-about" then me.openDialog "AboutDialog", ()->
when "#{me.name}-exit" then me.trigger "exit"
@on "apptitlechange", () -> me.sysdock.update()

View File

@ -50,227 +50,297 @@ class BaseDialog extends SubWindow
@parent.dialog = undefined if @parent
this.OS.GUI.BaseDialog = BaseDialog
###
this dialog rende a tag as main content
and a list of buttons, the behaviour of
the button is specified by user. The conf
object is in the follow form
{
tag: <tag_name>,
buttons:[
{
label: 'buton label',
onclick: function(d){...}
}, ...
]
}
###
class BasicDialog extends BaseDialog
constructor: ( name, @conf, @title) ->
constructor: ( name, target) ->
super name
if typeof target is "string"
Ant.OS.GUI.htmlToScheme target, @, @host
else # a file handle
@render target.path
init: () ->
@title = @name if not @title
html = "<afx-app-window data-id = '#{@name}' width='#{@conf.width}' height='#{@conf.height}'>"
html += "<afx-hbox><div data-width='7'></div><afx-vbox><div data-height='5'></div>"
html += "<#{v.tag} #{v.att} data-id = 'content#{k}'></#{v.tag}>" for k,v of @conf.tags
html += "<div data-height = '35' style=' text-align:right;padding-top:3px;'>"
html += "<afx-button data-id = 'bt#{k}' text = '#{v.label}' style='margin-left:5px;'></afx-button>" for k,v of @conf.buttons
html += "</div><div data-height='5'></div></afx-vbox><div data-width='7'></div></afx-hbox></afx-app-window>"
#render the html
Ant.OS.GUI.htmlToScheme html, @, @host
main: () ->
@scheme.set "apptitle", @title
@scheme.set "minimizable", false
@scheme.set "resizable", @conf.resizable if @conf.resizable isnt undefined
me = @
f = (_v) -> () -> _v.onclick me
# bind action to button
( (me.find "bt#{k}").set "onbtclick", f(v) ) for k, v of @conf.buttons
@conf.filldata @ if @conf.filldata
@conf.xtra @ if @conf.xtra
@scheme.set "apptitle", @data.title if @data and @data.title
this.OS.GUI.BasicDialog = BasicDialog
class PromptDialog extends BasicDialog
constructor: () ->
super "PromptDialog", {
tags: [
{ tag: "afx-label" },
{ tag: "input", att: "type = 'text' data-height='25'" }
],
width: 200,
height: 120,
resizable: false,
buttons: [
{
label: "__(Ok)",
onclick: (d) ->
txt = (d.find "content1").value
return d.quit() if txt is ""
d.handle txt if d.handle
d.quit()
},
{
label: "__(Cancel)",
onclick: (d) -> d.quit()
}
],
filldata: (d) ->
return unless d.data
(d.find "content0").set "text", d.data.label
(d.find "content1").value = d.data.value if d.data.value
$(d.find "content1").attr("type", d.data.type) if d.data.type
xtra: (d) ->
$( d.find "content1" ).keyup (e) ->
(d.find "bt0").trigger() if e.which is 13
}
super "PromptDialog", PromptDialog.scheme
init: () ->
super.init()
me = @
@find("lbl").set "text", @data.label if @data and @data.label
$(@find "txtInput").val @data.value if @data and @data.value
(@find "btnOk").set "onbtclick", (e) ->
me.handle($(me.find "txtInput").val()) if me.handle
me.quit()
(@find "btnCancel").set "onbtclick", (e) ->
me.quit()
PromptDialog.scheme = """
<afx-app-window width='200' height='150' apptitle = "Prompt">
<afx-vbox>
<afx-hbox>
<div data-width = "10" />
<afx-vbox>
<div data-height="10" />
<afx-label data-id = "lbl" />
<input type = "text" data-id= "txtInput" />
<div data-height="10" />
<afx-hbox data-height="30">
<div />
<afx-button data-id = "btnOk" text = "__(Ok)" data-width = "40" />
<afx-button data-id = "btnCancel" text = "__(Cancel)" data-width = "50" />
</afx-hbox>
</afx-vbox>
<div data-width = "10" />
</afx-hbox>
</afx-vbox>
</afx-app-window>
"""
this.OS.register "PromptDialog", PromptDialog
class CalendarDialog extends BasicDialog
constructor: () ->
super "CalendarDialog", {
tags: [{ tag: 'afx-calendar-view' }],
width: 300,
height: 230,
resizable: false,
buttons: [
{
label: "__(Ok)",
onclick: (d) ->
date = (d.find "content0").get "selectedDate"
if date
d.handle date if d.handle
d.quit()
else
d.notify __("Please select a date")
},
{
label: "__(Cancel)",
onclick: (d) -> d.quit()
}
]
}
super "CalendarDialog", CalendarDialog.scheme
init: () ->
super.init()
me = @
(@find "btnOk").set "onbtclick", (e) ->
date = (me.find "cal").get "selectedDate"
return me.notify __("Please select a day") unless date
me.handle(date) if me.handle
me.quit()
(@find "btnCancel").set "onbtclick", (e) ->
me.quit()
CalendarDialog.scheme = """
<afx-app-window width='300' height='230' apptitle = "Calendar" >
<afx-vbox>
<afx-hbox>
<div data-width = "10" />
<afx-vbox>
<div data-height="10" />
<afx-calendar-view data-id = "cal" />
<div data-height="10" />
<afx-hbox data-height="30">
<div />
<afx-button data-id = "btnOk" text = "__(Ok)" data-width = "40" />
<afx-button data-id = "btnCancel" text = "__(Cancel)" data-width = "50" />
</afx-hbox>
<div data-height="10" />
</afx-vbox>
<div data-width = "10" />
</afx-hbox>
</afx-vbox>
</afx-app-window>
"""
this.OS.register "CalendarDialog", CalendarDialog
class ColorPickerDialog extends BasicDialog
constructor: () ->
super "ColorPickerDialog", {
tags: [{ tag: 'afx-color-picker' }, {tag:'div', att: 'data-height="5"' }],
width: 313,
height: 250,
resizable: false,
buttons: [
{
label: "__(Ok)",
onclick: (d) ->
c = (d.find "content0").get "selectedColor"
if c
d.handle c if d.handle
d.quit()
else
d.notify "Please select a color"
},
{
label: "__(Cancel)",
onclick: (d) -> d.quit()
}
]
}
super "ColorPickerDialog", ColorPickerDialog.scheme
init: () ->
super.init()
me = @
(@find "btnOk").set "onbtclick", (e) ->
color = (me.find "cpicker").get "selectedColor"
return me.notify __("Please select color") unless color
me.handle(color) if me.handle
me.quit()
(@find "btnCancel").set "onbtclick", (e) ->
me.quit()
ColorPickerDialog.scheme = """
<afx-app-window width='320' height='250' apptitle = "Color picker" >
<afx-vbox>
<afx-hbox>
<div data-width = "10" />
<afx-vbox>
<div data-height="10" />
<afx-color-picker data-id = "cpicker" />
<div data-height="10" />
<afx-hbox data-height="30">
<div />
<afx-button data-id = "btnOk" text = "__(Ok)" data-width = "40" />
<afx-button data-id = "btnCancel" text = "__(Cancel)" data-width = "50" />
</afx-hbox>
<div data-height="10" />
</afx-vbox>
<div data-width = "10" />
</afx-hbox>
</afx-vbox>
</afx-app-window>
"""
this.OS.register "ColorPickerDialog", ColorPickerDialog
class InfoDialog extends BasicDialog
constructor: () ->
super "InfoDialog", {
tags: [{ tag: 'afx-grid-view' }],
width: 250,
height: 300,
resizable: true,
buttons: [ { label: "__(Cancel)", onclick: (d) -> d.quit() } ],
filldata: (d) ->
return unless d.data
super "InfoDialog", InfoDialog.scheme
init: () ->
super.init()
me = @
rows = []
rows.push [ { value: k }, { value: v } ] for k, v of d.data
(d.find "content0").set "rows", rows
}
delete @data.title if @data and @data.title
rows.push [ { text: k }, { text: v } ] for k, v of @data
(@find "grid").set "header", [ { text: __("Name"), width: 70 }, { text: __("Value") } ]
(@find "grid").set "rows", rows
(@find "btnCancel").set "onbtclick", (e) ->
me.quit()
InfoDialog.scheme = """
<afx-app-window width='250' height='300' apptitle = "Info" >
<afx-vbox>
<afx-hbox>
<div data-width = "10" />
<afx-vbox>
<div data-height="10" />
<afx-grid-view data-id = "grid" />
<div data-height="10" />
<afx-hbox data-height="30">
<div />
<afx-button data-id = "btnCancel" text = "__(Cancel)" data-width = "50" />
</afx-hbox>
<div data-height="10" />
</afx-vbox>
<div data-width = "10" />
</afx-hbox>
</afx-vbox>
</afx-app-window>
"""
this.OS.register "InfoDialog", InfoDialog
class YesNoDialog extends BasicDialog
constructor: () ->
super "YesNoDialog", {
tags: [{ tag: "afx-label" }],
width: 300,
height: 100,
resizable: true,
buttons: [
{
label: "__(Yes)", onclick: (d) ->
d.handle true if d.handle
d.quit()
},
{
label: "__(No)", onclick: (d) ->
d.handle false if d.handle
d.quit()
}
],
filldata: (d) ->
return unless d.data
l = d.find "content0"
for k, v of d.data
l.set k, v
}
super "YesNoDialog", YesNoDialog.scheme
init: () ->
super.init()
me = @
@find("lbl").set "text", @data.label if @data and @data.label
(@find "btnYes").set "onbtclick", (e) ->
me.handle(true) if me.handle
me.quit()
(@find "btnNo").set "onbtclick", (e) ->
me.handle(false) if me.handle
me.quit()
YesNoDialog.scheme = """
<afx-app-window width='200' height='150' apptitle = "Prompt">
<afx-vbox>
<afx-hbox>
<div data-width = "10" />
<afx-vbox>
<div data-height="10" />
<afx-label data-id = "lbl" />
<div data-height="10" />
<afx-hbox data-height="30">
<div />
<afx-button data-id = "btnYes" text = "__(Yes)" data-width = "40" />
<afx-button data-id = "btnNo" text = "__(No)" data-width = "40" />
</afx-hbox>
</afx-vbox>
<div data-width = "10" />
</afx-hbox>
</afx-vbox>
</afx-app-window>
"""
this.OS.register "YesNoDialog", YesNoDialog
class SelectionDialog extends BasicDialog
constructor: () ->
super "SelectionDialog", {
tags: [{ tag: "afx-list-view" }],
width: 250,
height: 300,
resizable: false,
buttons: [
{
label: "__(Ok)", onclick: (d) ->
el = d.find "content0"
it = el.get "selected"
return unless it
d.handle it if d.handle
d.quit()
},
{ label: "__(Cancel)", onclick: (d) -> d.quit() }
],
filldata: (d) ->
return unless d.data
(d.find "content0").set "items", d.data
xtra: (d) ->
( d.find "content0" ).set "onlistdbclick", (e) ->
(d.find "bt0").trigger()
}
this.OS.register "SelectionDialog", SelectionDialog
class AboutDialog extends BaseDialog
constructor: () ->
super "AboutDialog"
super "SelectionDialog", SelectionDialog.scheme
init: () ->
@render "os://resources/schemes/about.html"
super.init()
me = @
(@find "list").set "data", @data.data if @data and @data.data
(@find "btnOk").set "onbtclick", (e) ->
data = (me.find "list").get "selectedItem"
return me.notify __("Please select an item") unless data
me.handle(data) if me.handle
me.quit()
main: () ->
(@find "btnCancel").set "onbtclick", (e) ->
me.quit()
SelectionDialog.scheme = """
<afx-app-window width='250' height='300' apptitle = "Selection">
<afx-vbox>
<afx-hbox>
<div data-width = "10" />
<afx-vbox>
<div data-height="10" />
<afx-list-view data-id = "list" />
<div data-height="10" />
<afx-hbox data-height="30">
<div />
<afx-button data-id = "btnOk" text = "__(Ok)" data-width = "40" />
<afx-button data-id = "btnCancel" text = "__(Cancels)" data-width = "50" />
</afx-hbox>
</afx-vbox>
<div data-width = "10" />
</afx-hbox>
</afx-vbox>
</afx-app-window>
"""
this.OS.register "SelectionDialog", SelectionDialog
class AboutDialog extends BasicDialog
constructor: () ->
super "AboutDialog", AboutDialog.scheme
init: () ->
mt = @meta()
me = @
@scheme.set "apptitle", __("About: {0}", mt.name)
(@find "mylabel").set "*", {icon:mt.icon, iconclass:mt.iconclass, text:"#{mt.name}(v#{mt.version})"}
(@find "mylabel").set "*", {
icon: mt.icon,
iconclass: mt.iconclass,
text: "#{mt.name}(v#{mt.version})"
}
($ @find "mydesc").html mt.description
# grid data for author info
return unless mt.info
rows = []
rows.push [ { value: k }, { value: v } ] for k, v of mt.info
rows.push [ { text: k }, { text: v } ] for k, v of mt.info
(@find "mygrid").set "header", [ { text: "", width: 100 }, { text: "" } ]
(@find "mygrid").set "rows", rows
(@find "btnCancel").set "onbtclick", (e) ->
me.quit()
AboutDialog.scheme = """
<afx-app-window data-id = 'about-window' width='300' height='200'>
<afx-vbox>
<div style="text-align:center; margin-top:10px;" data-height="50">
<h3 style = "margin:0;padding:0;">
<afx-label data-id = 'mylabel'></afx-label>
</h3>
<i><p style = "margin:0; padding:0" data-id = 'mydesc'></p></i>
</div>
<afx-grid-view data-id = 'mygrid'></afx-grid-view>
<afx-hbox data-height="30">
<div />
<afx-button data-id = "btnCancel" text = "__(Cancel)" data-width = "60" />
</afx-hbox>
<div data-height = "10"/>
</afx-vbox>
</afx-app-window>
"""
this.OS.register "AboutDialog", AboutDialog
class FileDiaLog extends BaseDialog

View File

@ -67,24 +67,27 @@ class BaseModel
subscribe: (e, f) ->
Ant.OS.announcer.on e, f, @
openDialog: (d, f, title, data) ->
if @dialog
@dialog.show()
openDialog: (d, data) ->
me = @
new Promise (resolve, reject) ->
if me.dialog
me.dialog.show()
return
if typeof d is "string"
if not Ant.OS.GUI.subwindows[d]
@error __("Dialog {0} not found", d)
me.error __("Dialog {0} not found", d)
return
@dialog = new Ant.OS.GUI.subwindows[d]()
me.dialog = new Ant.OS.GUI.subwindows[d]()
else
@dialog = d
me.dialog = d
#@dialog.observable = riot.observable() unless @dialog
@dialog.parent = @
@dialog.handle = f
@dialog.pid = @pid
@dialog.data = data
@dialog.title = title
@dialog.init()
me.dialog.parent = me
me.dialog.handle = resolve
me.dialog.reject = reject
me.dialog.pid = me.pid
me.dialog.data = data
me.dialog.title = data.title if data and data.title
me.dialog.init()
ask: (t, m, f) ->
@._gui.openDialog "YesNoDialog", (d) ->

View File

@ -32,6 +32,10 @@ class BaseService extends this.OS.GUI.BaseModel
#implement by user
# event registe, etc
# scheme loader
update: () ->
@domel.set "data", @
meta: () ->
Ant.OS.APP[@name].meta
attach: (h) ->

View File

@ -172,10 +172,10 @@ Ant.OS.API =
#request a user data
mid: () ->
return Ant.OS.announcer.getMID()
post: (p, d, c, f) ->
post: (p, d) ->
new Promise (resolve, reject) ->
q = Ant.OS.announcer.getMID()
Ant.OS.API.loading q, p
$.ajax {
type: 'POST',
url: p,
@ -184,32 +184,31 @@ Ant.OS.API =
dataType: 'json',
success: null
}
#$.getJSON p, d
.done (data) ->
Ant.OS.API.loaded q, p, "OK"
c(data)
resolve(data)
.fail (e, s) ->
Ant.OS.API.loaded q, p, "FAIL"
f(e, s)
reject(e, s)
blob: (p, c, f) ->
blob: (p) ->
new Promise (resolve, reject) ->
q = Ant.OS.announcer.getMID()
r = new XMLHttpRequest()
r.open "GET", p, true
r.responseType = "arraybuffer"
r.onload = (e) ->
if @status is 200 and @readyState is 4
c @response
resolve @response
Ant.OS.API.loaded q, p, "OK"
else
f e, @
reject e, @
Ant.OS.API.loaded q, p, "FAIL"
Ant.OS.API.loading q, p
r.send()
upload: (p, d, c, f) ->
upload: (p, d) ->
new Promise (resolve, reject) ->
q = Ant.OS.announcer.getMID()
#insert a temporal file selector
o = ($ '<input>').attr('type', 'file').css("display", "none")
@ -229,13 +228,12 @@ Ant.OS.API =
}
.done (data) ->
Ant.OS.API.loaded q, p, "OK"
c(data)
resolve(data)
o.remove()
.fail (e, s) ->
Ant.OS.API.loaded q, p, "FAIL"
f(e, s)
reject(e, s)
o.remove()
o.click()
saveblob: (name, b) ->
@ -249,41 +247,44 @@ Ant.OS.API =
window.URL.revokeObjectURL(url)
o.remove()
systemConfig: ->
Ant.OS.API.request 'config', (result) ->
console.log result
loading: (q, p) ->
Ant.OS.announcer.trigger "loading", { id: q, data: { m: "#{p}", s: true }, name: "OS" }
loaded: (q, p, m ) ->
Ant.OS.announcer.trigger "loaded", { id: q, data: { m: "#{m}: #{p}", s: false }, name: "OS" }
get: (p, c, f, t) ->
Ant.OS.announcer.trigger "loaded", {
id: q, data: { m: "#{m}: #{p}", s: false }, name: "OS" }
get: (p, t) ->
new Promise (resolve, reject) ->
conf =
type: 'GET',
url: p,
url: p
conf.dataType = t if t
q = Ant.OS.announcer.getMID()
Ant.OS.API.loading q, p
$.ajax conf
.done (data) ->
Ant.OS.API.loaded q, p, "OK"
c(data)
resolve(data)
.fail (e, s) ->
Ant.OS.API.loaded q, p, "FAIL"
f(e, s)
script: (p, c, f) ->
reject(e, s)
script: (p) ->
new Promise (resolve, reject) ->
q = Ant.OS.announcer.getMID()
Ant.OS.API.loading q, p
$.getScript p
.done (data) ->
Ant.OS.API.loaded q, p, "OK"
c(data)
resolve(data)
.fail (e, s) ->
Ant.OS.API.loaded q, p, "FAIL"
f(e, s)
resource: (r, c, f) ->
reject(e, s)
resource: (r) ->
path = "resources/#{r}"
Ant.OS.API.get path, c, f
Ant.OS.API.get path
libready: (l) ->
return Ant.OS.API.shared[l] || false
@ -324,19 +325,24 @@ Ant.OS.API =
libs.splice 0, 1
Ant.OS.API.requires libs, f
Ant.OS.API.require libs[0], null
packages:
fetch: (f) ->
fetch: () ->
Ant.OS.API.handle.packages {
command: "list", args: { paths: (v for k, v of Ant.OS.setting.system.pkgpaths) }
}, f
cache: (f) ->
}
cache: () ->
Ant.OS.API.handle.packages {
command: "cache", args: { paths: (v for k, v of Ant.OS.setting.system.pkgpaths) }
}, f
}
setting: (f) ->
Ant.OS.API.handle.setting f
apigateway: (d, ws, c) ->
return Ant.OS.API.handle.apigateway d, ws, c
search: (text) ->
r = []
@ -350,17 +356,17 @@ Ant.OS.API =
onsearch: (name, fn) ->
Ant.OS.API.searchHandle[name] = fn unless Ant.OS.API.searchHandle[name]
setLocale: (name, f) ->
setLocale: (name) ->
new Promise (resolve, reject) ->
path = "resources/languages/#{name}.json"
Ant.OS.API.get path, (d) ->
Ant.OS.API.get(path, "json")
.then (d) ->
Ant.OS.setting.system.locale = name
Ant.OS.API.lang = d
if f then f() else Ant.OS.announcer.trigger "systemlocalechange", name
, (e, s) ->
#Ant.OS.setting.system.locale = "en_GB"
Ant.OS.announcer.oserror __("Language file {0} not found", path), e, s
f() if f
, "json"
Ant.OS.announcer.trigger "systemlocalechange", name
resolve d
.catch (e) ->
reject e
throwe: (n) ->
err = undefined

View File

@ -107,7 +107,8 @@ Ant.OS or=
boot: ->
#first login
console.log "Booting sytem"
Ant.OS.API.handle.auth (d) ->
Ant.OS.API.handle.auth()
.then (d) ->
# in case someone call it more than once :)
if d.error
# show login screen
@ -115,13 +116,20 @@ Ant.OS or=
else
# startX :)
Ant.OS.GUI.startAntOS d.result
.catch (e) ->
console.error e
cleanupHandles: {}
exit: ->
#do clean up first
f() for n, f of Ant.OS.cleanupHandles
Ant.OS.API.handle.setting (r) ->
Ant.OS.API.handle.setting()
.then (r) ->
Ant.OS.cleanup()
Ant.OS.API.handle.logout()
.catch (e) ->
console.error e
onexit: (n, f) ->
Ant.OS.cleanupHandles[n] = f unless Ant.OS.cleanupHandles[n]

View File

@ -19,20 +19,23 @@
class DB
constructor: (@table) ->
save: (d, f) ->
Ant.OS.API.handle.dbquery "save", { table: @table, data: d }, f
delete: (c, f) ->
save: (d) ->
Ant.OS.API.handle.dbquery "save", { table: @table, data: d }
delete: (c) ->
rq = { table: @table }
return ( Ant.OS.announcer.oserror __("VDB Unknown condition for delete command"),
(Ant.OS.API.throwe "OS.DB"), c ) unless c and c isnt ""
return new Promise (resolve, reject) ->
reject(Ant.OS.API.throwe("OS.DB: unkown condition")) unless c and c isnt ""
if isNaN c
rq.cond = c
else
rq.id = c
Ant.OS.API.handle.dbquery "delete", rq, f
get: (id, f) ->
Ant.OS.API.handle.dbquery "get", { table: @table, id: id }, f
find: (cond, f) ->
Ant.OS.API.handle.dbquery "select", { table: @table, cond: cond }, f
Ant.OS.API.handle.dbquery "delete", rq
get: (id) ->
Ant.OS.API.handle.dbquery "get", { table: @table, id: id }
find: (cond) ->
Ant.OS.API.handle.dbquery "select", { table: @table, cond: cond }
Ant.OS.API.DB = DB

View File

@ -37,14 +37,14 @@ Ant.OS.GUI =
children: [],
dataid: "sys-apps"
iconclass: "fa fa-adn",
onmenuselect: (d) ->
Ant.OS.GUI.launch d.item.data.app
onchildselect: (d) ->
Ant.OS.GUI.launch d.data.item.get("data").name
}
],
onmenuselect: (d) ->
return Ant.OS.exit() if d.item.data.dataid is "sys-logout"
return Ant.OS.GUI.toggleFullscreen() if d.item.data.dataid is "os-fullsize"
Ant.OS.GUI.launch d.item.data.app unless d.item.data.dataid
onchildselect: (d) ->
id = d.data.item.get("data").dataid
return Ant.OS.exit() if id is "sys-logout"
return Ant.OS.GUI.toggleFullscreen() if id is "os-fullsize"
}
]
htmlToScheme: (html, app, parent) ->
@ -57,7 +57,7 @@ Ant.OS.GUI =
app.main()
app.show()
loadScheme: (path, app, parent) ->
path.asFileHandle().read (x) ->
path.asFileHandle().read().then (x) ->
return null unless x
Ant.OS.GUI.htmlToScheme x, app, parent
#, (e, s) ->
@ -100,10 +100,10 @@ Ant.OS.GUI =
srv = arr[1]
app = arr[0]
return Ant.OS.PM.createProcess srv, Ant.OS.APP[srv] if Ant.OS.APP[srv]
Ant.OS.GUI.loadApp app,
(a) ->
Ant.OS.GUI.loadApp app
.then (a) ->
return Ant.OS.PM.createProcess srv, Ant.OS.APP[srv] if Ant.OS.APP[srv]
(e, s) ->
.catch (e, s) ->
Ant.OS.announcer.trigger "srvroutineready", srv
Ant.OS.announcer.osfail __("Cannot read service script: {0}", srv), e, s
@ -153,38 +153,37 @@ Ant.OS.GUI =
($ Ant.OS.APP[app].style).remove() if Ant.OS.APP[app] and Ant.OS.APP[app].style
delete Ant.OS.APP[app]
loadApp: (app, ok, err) ->
path = "os://packages/#{app}"
loadApp: (app) ->
new Promise (resolve, reject) ->
path = Ant.OS.setting.system.packages[app].path if Ant.OS.setting.system.packages[app].path
js = path + "/main.js"
js.asFileHandle().read (d) ->
js.asFileHandle().read("script")
.then (d) ->
# load app meta data
"#{path}/package.json".asFileHandle().read (data) ->
"#{path}/package.json".asFileHandle().read("json")
.then (data) ->
data.path = path
Ant.OS.APP[app].meta = data if Ant.OS.APP[app]
Ant.OS.APP[v].meta = data for v in data.services if data.services
#load css file
css = "#{path}/main.css"
css.asFileHandle().onready (d) ->
css.asFileHandle().onready()
.then (d) ->
stamp = (new Date).timestamp()
el = $ '<link>', { rel: 'stylesheet', type: 'text/css', 'href': "#{Ant.OS.API.handle.get}/#{css}?stamp=#{stamp}" }
.appendTo 'head'
Ant.OS.APP[app].style = el[0] if Ant.OS.APP[app]
ok app
, () ->
#launch
ok app
, "json"
resolve app
.catch (e) -> resolve app
.catch (e) -> reject e
#ok app
, "script"
.catch (e) -> reject e
launch: (app, args) ->
if not Ant.OS.APP[app]
# first load it
Ant.OS.GUI.loadApp app,
(a)->
Ant.OS.GUI.loadApp(app).then (a) ->
Ant.OS.PM.createProcess a, Ant.OS.APP[a], args
, (e, s) ->
else
# now launch it
if Ant.OS.APP[app]
@ -289,7 +288,8 @@ Ant.OS.GUI =
initDM: ->
# check login first
Ant.OS.API.resource "schemes/dm.html", (x) ->
Ant.OS.API.resource("schemes/dm.html")
.then (x) ->
return null unless x
scheme = $.parseHTML x
($ "#wrapper").append scheme
@ -337,11 +337,10 @@ Ant.OS.GUI =
# desktop default file manager
desktop = $ Ant.OS.GUI.workspace
fp = Ant.OS.setting.desktop.path.asFileHandle()
desktop[0].fetch = () ->
fn = () ->
fp = Ant.OS.setting.desktop.path.asFileHandle()
fp.read (d) ->
fn = () ->
fp.read().then (d) ->
return Ant.OS.announcer.osfail d.error, (Ant.OS.API.throwe "OS.VFS"), d.error if d.error
items = []
$.each d.result, (i, v) ->
@ -350,15 +349,15 @@ Ant.OS.GUI =
#v.text = v.text.substring(0,9) + "..." ifv.text.length > 10
v.iconclass = v.type
items.push(v)
desktop[0].set "items", items
desktop[0].set "data", items
desktop[0].refresh()
fp.onready () ->
fn()
, ( e ) -> # try to create the path
fp.onready()
.then () -> fn()
.catch ( e ) -> # try to create the path
console.log "#{fp.path} not found"
name = fp.basename
fp.parent().asFileHandle().mk name, (r) ->
fp.parent().asFileHandle().mk(name).then (r) ->
ex = Ant.OS.API.throwe "OS.VFS"
if r.error then Ant.OS.announcer.osfail d.error, ex, d.error else fn()
@ -373,20 +372,19 @@ Ant.OS.GUI =
desktop[0].set "onlistdbclick", ( d ) ->
($ "#sysdock").get(0).set "selectedApp", null
it = desktop[0].get "selected"
Ant.OS.GUI.openWith it
it = desktop[0].get "selectedItem"
Ant.OS.GUI.openWith it.get("data")
#($ "#workingenv").on "click", (e) ->
# desktop[0].set "selected", -1
desktop.on "click", (e) ->
return unless e.target is desktop[0]
desktop[0].set "selected", -1
return unless e.target.tagName.toUpperCase() is "UL"
desktop[0].unselect()
($ "#sysdock").get(0).set "selectedApp", null
#console.log "desktop clicked"
desktop[0].contextmenuHandle = (e, m) ->
desktop[0].set "selected", -1 if e.target is desktop[0]
desktop[0].unselect() if e.target.tagName.toUpperCase() is "UL"
($ "#sysdock").get(0).set "selectedApp", null
menu = [
{ text: __("Open"), dataid: "desktop-open" },
@ -395,17 +393,18 @@ Ant.OS.GUI =
menu = menu.concat ( v for k, v of Ant.OS.setting.desktop.menu)
m.set "items", menu
m.set "onmenuselect", (evt) ->
switch evt.item.data.dataid
item = evt.data.item.get("data")
switch item.dataid
when "desktop-open"
it = desktop[0].get "selected"
return Ant.OS.GUI.openWith it if it
it = desktop[0].get "selectedItem"
return Ant.OS.GUI.openWith it.get("data") if it
it = Ant.OS.setting.desktop.path.asFileHandle()
it.mime = "dir"
Ant.OS.GUI.openWith it
when "desktop-refresh"
desktop[0].fetch()
else
Ant.OS.GUI.launch evt.item.data.app, evt.item.data.args if evt.item.data.app
Ant.OS.GUI.launch item.app, item.args if item.app
m.show(e)
desktop[0].fetch()
@ -415,9 +414,10 @@ Ant.OS.GUI =
# mount it
desktop[0].uify()
# riot.mount desktop
, (e, s) ->
.catch (e) ->
console.log e
alert __("System fail: Cannot init desktop manager")
console.log s, e
refreshDesktop: () ->
($ Ant.OS.GUI.workspace)[0].fetch()
@ -444,7 +444,8 @@ Ant.OS.GUI =
return new Ant.OS.GUI.BasicDialog conf.name, conf.layout
login: () ->
Ant.OS.API.resource "schemes/login.html", (x) ->
Ant.OS.API.resource "schemes/login.html"
.then (x) ->
return null unless x
scheme = $.parseHTML x
($ "#wrapper").append scheme
@ -452,11 +453,14 @@ Ant.OS.GUI =
data =
username: ($ "#txtuser").val(),
password: ($ "#txtpass").val()
Ant.OS.API.handle.login data, (d) ->
Ant.OS.API.handle.login data
.then (d) ->
if d.error then ($ "#login_error").html d.error else Ant.OS.GUI.startAntOS d.result
.catch (e) ->
($ "#login_error").html "Login: server error"
($ "#txtpass").keyup (e) ->
($ "#btlogin").click() if e.which is 13
, (e, s) ->
.catch (e) ->
alert __("System fail: Cannot init login screen")
startAntOS: (conf) ->
@ -473,9 +477,9 @@ Ant.OS.GUI =
Ant.OS.announcer.observable.on "systemlocalechange", (name) ->
($ "#syspanel")[0].update()
Ant.OS.API.packages.cache (ret) ->
Ant.OS.API.packages.cache().then (ret) ->
if ret.result
Ant.OS.API.packages.fetch (r) ->
Ant.OS.API.packages.fetch().then (r) ->
if r.result
for k, v of r.result
v.text = v.name
@ -493,5 +497,6 @@ Ant.OS.GUI =
(Ant.OS.GUI.launch a) for a in Ant.OS.setting.system.startup.apps
#Ant.OS.GUI.launch "DummyApp"
# initDM
Ant.OS.API.setLocale Ant.OS.setting.system.locale, () ->
Ant.OS.API.setLocale Ant.OS.setting.system.locale
.then () ->
Ant.OS.GUI.initDM()

View File

@ -23,101 +23,80 @@ Ant.OS.API.handle =
get: "#{Ant.OS.API.REST}/VFS/get"
# get shared file with publish
shared: "#{Ant.OS.API.REST}/VFS/shared"
scandir: (p, c ) ->
scandir: (p) ->
path = "#{Ant.OS.API.REST}/VFS/scandir"
Ant.OS.API.post path, { path: p }, c, (e, s) ->
Ant.OS.announcer.osfail __("Fail to scan directory: {0}", p), e, s
mkdir: (p, c ) ->
Ant.OS.API.post path, { path: p }
mkdir: (p) ->
path = "#{Ant.OS.API.REST}/VFS/mkdir"
Ant.OS.API.post path, { path: p }, c, (e, s) ->
Ant.OS.announcer.osfail __("Fail to create directory: {0}", p), e, s
sharefile: (p, pub , c) ->
Ant.OS.API.post path, { path: p }
sharefile: (p, pub) ->
path = "#{Ant.OS.API.REST}/VFS/publish"
Ant.OS.API.post path, { path: p , publish: pub }, c, (e, s) ->
Ant.OS.announcer.osfail __("Fail to publish file: {0}", p), e, s
Ant.OS.API.post path, { path: p , publish: pub }
fileinfo: (p, c) ->
fileinfo: (p) ->
path = "#{Ant.OS.API.REST}/VFS/fileinfo"
Ant.OS.API.post path, { path: p }, c, (e, s) ->
Ant.OS.announcer.osfail __("Fail to get file meta data: {0}", p), e, s
Ant.OS.API.post path, { path: p }
readfile: (p, c, t) ->
readfile: (p, t) ->
path = "#{Ant.OS.API.REST}/VFS/get/"
Ant.OS.API.get path + p, c, (e, s) ->
Ant.OS.announcer.osfail __("Fail to read file: {0}", p), e, s
, t
Ant.OS.API.get path + p, t
move: (s, d, c) ->
move: (s, d) ->
path = "#{Ant.OS.API.REST}/VFS/move"
Ant.OS.API.post path, { src: s, dest: d }, c, (e, s) ->
Ant.OS.announcer.osfail __("Fail to move file: {0} -> {1}", s, d), e, s
Ant.OS.API.post path, { src: s, dest: d }
delete: (p , c) ->
delete: (p) ->
path = "#{Ant.OS.API.REST}/VFS/delete"
Ant.OS.API.post path, { path: p }, c, (e, s) ->
Ant.OS.announcer.osfail __("Fail to delete: {0}", p), e, s
Ant.OS.API.post path, { path: p }
fileblob: (p, c) ->
fileblob: (p) ->
path = "#{Ant.OS.API.REST}/VFS/get/"
Ant.OS.API.blob path + p, c, (e, s) ->
Ant.OS.announcer.osfail "Fail to read file: #{p}", e, s
Ant.OS.API.blob path + p
packages: (d, c) ->
packages: (d) ->
path = "#{Ant.OS.API.REST}/system/packages"
Ant.OS.API.post path, d, c, (e, s) ->
Ant.OS.announcer.osfail __("Fail to {0} package", d.command), e, s
Ant.OS.API.post path, d
upload: (d, c) ->
upload: (d) ->
path = "#{Ant.OS.API.REST}/VFS/upload"
Ant.OS.API.upload path, d, c, (e, s) ->
Ant.OS.announcer.osfail __("Fail to upload file to: {0}", d), e, s
Ant.OS.API.upload path, d
write: (p, d , c) ->
write: (p, d) ->
path = "#{Ant.OS.API.REST}/VFS/write"
Ant.OS.API.post path, { path: p, data: d }, c, (e, s) ->
Ant.OS.announcer.osfail __("Fail to write to file: {0}", p), e, s
Ant.OS.API.post path, { path: p, data: d }
scanapp: (p, c ) ->
path = "#{Ant.OS.API.REST}/system/application"
apigateway: (d, ws, c) ->
apigateway: (d, ws) ->
if ws
new Promise (resolve, reject) ->
path = "#{Ant.OS.API.HOST}/system/apigateway?ws=1"
proto = if window.location.protocol is "https:" then "wss://" else "ws://"
socket = new WebSocket proto + path
if c then c(socket)
return socket
resolve(socket)
else
path = "#{Ant.OS.API.REST}/system/apigateway?ws=0"
Ant.OS.API.post path, d, c, (e, s) ->
Ant.OS.announcer.osfail __("Fail to invoke gateway api"), e, s
Ant.OS.API.post path, d
auth: (c) ->
auth: () ->
p = "#{Ant.OS.API.REST}/user/auth"
Ant.OS.API.post p, {}, c, (e, s) ->
console.log e, s
alert __("Resource not found: {0}", p)
login: (d, c) ->
Ant.OS.API.post p, {}
login: (d) ->
p = "#{Ant.OS.API.REST}/user/login"
Ant.OS.API.post p, d, c, () ->
alert __("Resource not found: {0}", p)
Ant.OS.API.post p, d
logout: () ->
p = "#{Ant.OS.API.REST}/user/logout"
Ant.OS.API.post p, {}, (d) ->
Ant.OS.boot()
, () ->
alert __("Resource not found: {0}", p)
setting: (f) ->
p = "#{Ant.OS.API.REST}/system/settings"
Ant.OS.API.post p, Ant.OS.setting, (d) ->
Ant.OS.announcer.oserror __("Cannot save system setting"), d.error if d.error
f(d) if f
, (e, s) ->
m = __("Fail to make request: {0}", p)
Ant.OS.announcer.osfail m , e, s
f({ error: m }) if f
Ant.OS.API.post p, {}
dbquery: (cmd, d, c) ->
setting: () ->
p = "#{Ant.OS.API.REST}/system/settings"
Ant.OS.API.post p, Ant.OS.setting
dbquery: (cmd, d) ->
path = "#{Ant.OS.API.REST}/VDB/#{cmd}"
Ant.OS.API.post path, d, c, (e, s) ->
Ant.OS.announcer.osfail __("Fail to query data from database: {0}", path), e, s
Ant.OS.API.post path, d

View File

@ -3,7 +3,7 @@
<!--div class = "afx-clear"></div-->
<div id = "workspace">
<afx-apps-dock id="sysdock"></afx-apps-dock>
<afx-float-list id = "desktop" ></afx-float-list>
<afx-float-list id = "desktop" dir="vertical" ></afx-float-list>
<!--div id = "workingenv"></div-->
</div>
<afx-menu id="contextmenu" data-id="contextmenu" context="true" style="display:none;"></afx-menu>

View File

@ -1,60 +1,67 @@
class AppDockTag extends Ant.OS.GUI.BaseTag
constructor: (r, o) ->
super r, o
@setopt "selectedApp"
@setopt "onappselect", (e) ->
@setopt "items", []
@setopt "selectedApp", undefined
me = @
@root.newapp = (a) -> me.addApp a
@root.removeapp = (a) -> me.removeApp a
__selectedApp__: (v) ->
el = undefined
for it in @get("items")
it.app.blur()
$(it.domel).removeClass()
el = it.domel if v and v is it.app
return unless el
$(el).addClass "selected"
$(Ant.OS.GUI.workspace)[0].unselect()
addApp: (item) ->
@items.push item
@set "selectedApp", item.app
@get("items").push item
el = $("<afx-button>")
el.appendTo @root
el[0].uify @observable
el[0].set "*", item
el.attr "tooltip", "cr:#{item.app.title()}"
item.domel = el[0]
me = @
el[0].set "onbtclick", (e) ->
e.id = me.aid()
e.data.app = item
me.get("onappselect") e
for v in @items
v.app.blur()
item.app.show()
@set "selectedApp", item.app
removeApp: (a) ->
i = -1
for v, k in self.items
for v, k in @get "items"
if v.app.pid == a.pid
i = k
break
if i != -1
delete @items[i].app
@items.splice(i, 1)
items = @get("items")
delete items[i].app
items.splice(i, 1)
$($(@root).children()[i]).remove()
mount: () ->
Ant.OS.announcer.trigger "sysdockloaded"
me = @
@root.contextmenuHandle = (e, m) ->
return if e.target is me.root
bt = $(e.target).closest "afx-button"
appidx = $(@root).children().indexOf bt
app = self.items[appidx].app
app = bt[0].get "app"
m.set "items", [
{ text: "__(Show)", dataid: "show" },
{ text: "__(Hide)", dataid: "hide" },
{ text: "__(Close)", dataid: "quit" }
]
m.set "onmenuselect", (evt) ->
console.log evt
### if(app[evt.item.data.dataid])
app[evt.item.data.dataid]() ###
item = evt.data.item.get("data")
if(app[item.dataid])
app[item.dataid]()
m.show(e)
Ant.OS.announcer.trigger "sysdockloaded"
Ant.OS.GUI.define "afx-apps-dock", AppDockTag

View File

@ -12,7 +12,6 @@ class ButtonTag extends Ant.OS.GUI.BaseTag
__color__: (v) ->
console.log @refs
@refs.label.set "color", v
__icon__: (v) ->

View File

@ -18,6 +18,7 @@ class FloatListTag extends ListViewTag
@calibrate()
__dir__: (v) ->
@calibrate()
mount: () ->
me = @
$(@refs.container)
@ -28,6 +29,8 @@ class FloatListTag extends ListViewTag
.css "display", "block"
.css "width", "100%"
@observable.on "resize", (e) -> me.calibrate()
@root.ready(@root) if @root.ready
push: (v) ->
el = super.push(v)
@enable_drag el

View File

@ -83,6 +83,7 @@ class ListViewTag extends Ant.OS.GUI.BaseTag
@root.push = (e) -> me.push e
@root.remove = (e) -> me.remove e
@root.unshift = (e) -> me.unshift e
@root.unselect = () -> me.unselect()
multiselect: () ->
return false if @get "dropdown"
@ -137,6 +138,12 @@ class ListViewTag extends Ant.OS.GUI.BaseTag
for item in data
@push item, false
unselect: () ->
v.set "selected", false for v in @get("selectedItems")
@set "selectedItems", []
@set "selectedItem", undefined
iclick: (e, flag) ->
return if not e.item
list = @get("selectedItems")

View File

@ -28,6 +28,6 @@ class OverlayTag extends Ant.OS.GUI.BaseTag
}
layout: () ->
@refs.yield = @root
@refs.yield = @roots
[]
Ant.OS.GUI.define "afx-overlay", OverlayTag

View File

@ -68,91 +68,148 @@ class BaseFileHandle
return -1 unless @path
return @path.hash()
sendB64: (p, f) ->
b64: (t) ->
# t is object or mime type
me = @
m = if p is "object" then "text/plain" else p
return f "" unless @cache
if p is "object" or typeof @cache is "string"
b64 = if p is "object" then (JSON.stringify @cache).asBase64() else @cache.asBase64()
new Promise (resolve, reject) ->
m = if t is "object" then "text/plain" else t
return resolve "" unless me.cache
if t is "object" or typeof me.cache is "string"
if t is "object"
b64 = (JSON.stringify me.cache).asBase64()
else
b64 = me.cache.asBase64()
b64 = "data:#{m};base64,#{b64}"
f(b64)
resolve(b64)
else
reader = new FileReader()
reader.readAsDataURL(@cache)
reader.readAsDataURL(me.cache)
reader.onload = () ->
f reader.result
resolve reader.result
reader.onerror = (e) ->
return Ant.OS.announcer.osfail __("VFS Cannot encode file: {0}", me.path), (Ant.OS.API.throwe "OS.VFS"), e
reject e
parent: () ->
return @ if @isRoot()
return (@protocol + "://" + (@genealogy.slice 0 , @genealogy.length - 1).join "/")
onready: (f, err) ->
onready: () ->
# read meta data
return f() if @ready
me = @
me.meta (d) ->
if d.error
return if err then err d else Ant.OS.announcer.osfail "#{me.path}: #{d.error}", (Ant.OS.API.throwe "OS.VFS"), d.error
new Promise (resolve, reject) ->
return resolve(me.info) if me.ready
me.meta()
.then (d) ->
return reject d if d.errors
me.info = d.result
me.ready = true
f()
resolve(d.result)
.catch (e) -> resolve e
read: (f, t) ->
read: (t) ->
me = @
@onready (() -> me.action "read", t, f)
new Promise (resolve, reject) ->
me.onready()
.then (r) ->
me._rd(t)
.then (d) -> resolve d
.catch (e) -> reject e
.catch (e) -> reject e
write: (d, f) ->
write: (d, t) ->
me = @
@action "write", d, (r) ->
Ant.OS.announcer.ostrigger "VFS", { m: "write", file: me } if r.result
f r
new Promise (resolve, reject) ->
me._wr(d, t)
.then (r) -> resolve r
.catch (e) -> reject e
mk: (d, f) ->
mk: (d) ->
me = @
@onready (() -> me.action "mk", d, (r) ->
Ant.OS.announcer.ostrigger "VFS", { m: "mk", file: me } if r.result
f r)
new Promise (resolve, reject) ->
me.onready()
.then (r) ->
me._mk(d)
.then (d) -> resolve d
.catch (e) -> reject e
.catch (e) -> reject e
remove: (f) ->
remove: () ->
me = @
@onready (() -> me.action "remove", null, (r) ->
Ant.OS.announcer.ostrigger "VFS", { m: "remove", file: me } if r.result
f r)
new Promise (resolve, reject) ->
me.onready()
.then (r) ->
me._rm()
.then (d) -> resolve d
.catch (e) -> reject e
.catch (e) -> reject e
upload: (f) ->
upload: () ->
me = @
@onready (() -> me.action "upload", null, (r) ->
Ant.OS.announcer.ostrigger "VFS", { m: "upload", file: me } if r.result
f r)
publish: (f) ->
me = @
@onready (() -> me.action "publish", null, (r) ->
Ant.OS.announcer.ostrigger "VFS", { m: "publish", file: me } if r.result
f r)
download: (f) ->
me = @
@onready (() -> me.action "download", null, f)
new Promise (resolve, reject) ->
me.onready()
.then (r) ->
me._up()
.then (d) -> resolve d
.catch (e) -> reject e
.catch (e) -> reject e
move: (d, f) ->
publish: () ->
me = @
@onready (() -> me.action "move", d, (r) ->
Ant.OS.announcer.ostrigger "VFS", { m: "move", file: d.asFileHandle() } if r.result
f r)
new Promise (resolve, reject) ->
me.onready()
.then (r) ->
me._pub()
.then (d) -> resolve d
.catch (e) -> reject e
.catch (e) -> reject e
execute: (f) ->
download: () ->
me = @
@onready (() -> me.action "execute", null, f)
new Promise (resolve, reject) ->
me.onready()
.then (r) ->
me._down()
.then (d) -> resolve d
.catch (e) -> reject e
.catch (e) -> reject e
#mk: (f) ->
move: (d) ->
me = @
new Promise (resolve, reject) ->
me.onready()
.then (r) ->
me._mv()
.then (d) -> resolve d
.catch (e) -> reject e
.catch (e) -> reject e
meta: (f) ->
execute: () ->
me = @
new Promise (resolve, reject) ->
me.onready()
.then (r) ->
me._exec()
.then (d) -> resolve d
.catch (e) -> reject e
.catch (e) -> reject e
getlink: () -> @path
# for main action read, write, remove, execute
# must be implemented by subclasses
action: (n, p, f) ->
return Ant.OS.announcer.osfail __("VFS unknown action: {0}", n), (Ant.OS.API.throwe "OS.VFS"), n
unsupported: (t) ->
me = @
new Promise (resolve, reject) ->
reject { error: __("Action {0} is unsupported on: {1}", t, me.path) }
# actions must be implemented by subclasses
_rd: (t) -> @unsupported "read"
_wr: (d, t) -> @unsupported "write"
_mk: (d) -> @unsupported "mk"
_rm: () -> @unsupported "remove"
_mv: (d) -> @unsupported "move"
_up: () -> @unsupported "upload"
_down: () -> @unsupported "download"
_exec: () -> @unsupported "execute"
_pub: () -> @unsupported "publish"
# now export the class
Ant.OS.API.VFS.BaseFileHandle = BaseFileHandle
@ -162,43 +219,66 @@ class RemoteFileHandle extends Ant.OS.API.VFS.BaseFileHandle
constructor: (path) ->
super path
meta: (f) ->
Ant.OS.API.handle.fileinfo @path, f
meta: () ->
Ant.OS.API.handle.fileinfo @path
getlink: () ->
Ant.OS.API.handle.get + "/" + @path
action: (n, p, f) ->
me = @
switch n
when "read"
return Ant.OS.API.handle.scandir @path, f if @info.type is "dir"
_rd: (t) ->
# t: binary, text, any type
return Ant.OS.API.handle.scandir @path if @info.type is "dir"
#read the file
return Ant.OS.API.handle.fileblob @path, f if p is "binary"
Ant.OS.API.handle.readfile @path, f, if p then p else "text"
when "mk"
return f { error: __("{0} is not a directory", @path) } if @info.type is "file"
Ant.OS.API.handle.mkdir "#{@path}/#{p}", f
when "write"
return Ant.OS.API.handle.write me.path, me.cache, f if p is "base64"
@sendB64 p, (data) ->
Ant.OS.API.handle.write me.path, data, f
when "upload"
return if @info.type is "file"
Ant.OS.API.handle.upload @path, f
when "remove"
Ant.OS.API.handle.delete @path, f
when "publish"
Ant.OS.API.handle.sharefile @path, true , f
when "download"
return if @info.type is "dir"
Ant.OS.API.handle.fileblob @path, (d) ->
return Ant.OS.API.handle.fileblob @path if t is "binary"
Ant.OS.API.handle.readfile @path, if t then t else "text"
_wr: (d, t) ->
# t is base64 or undefined
return Ant.OS.API.handle.write me.path, me.cache if p is "base64"
me = @
new Promise (resolve, reject) ->
me.b64(t)
.then (r) ->
Ant.OS.API.handle.write me.path, d
resolve r
.catch (e) -> reject e
_mk: (d) ->
me = @
if @info.type is "file"
return new Promise (resolve, reject) ->
reject { error: __("{0} is not a directory", me.path) }
Ant.OS.API.handle.mkdir "#{@path}/#{d}"
_rm: () ->
Ant.OS.API.handle.delete @path
_mv: (d) ->
Ant.OS.API.handle.move @path, d
_up: () ->
me = @
if @info.type isnt "file"
return new Promise (resolve, reject) ->
reject { error: __("{0} is not a file", me.path) }
Ant.OS.API.handle.upload @path
_down: () ->
me = @
new Promise (resolve, reject) ->
if me.info.type is "dir"
return reject { error: __("{0} is not a file", me.path) }
Ant.OS.API.handle.fileblob(@path)
.then (d) ->
blob = new Blob [d], { type: "octet/stream" }
Ant.OS.API.saveblob me.basename, blob
when "move"
Ant.OS.API.handle.move @path, p, f
else
return Ant.OS.announcer.osfail __("VFS unknown action: {0}", n), (Ant.OS.API.throwe "OS.VFS"), n
resolve()
.catch (e) ->
reject e
_pub: () ->
Ant.OS.API.handle.sharefile @path, true
Ant.OS.API.VFS.register "^(home|desktop|os|Untitled)$", RemoteFileHandle
@ -209,39 +289,13 @@ class ApplicationHandle extends Ant.OS.API.VFS.BaseFileHandle
@info = Ant.OS.setting.system.packages[@basename] if @basename
@ready = true
meta: (f) ->
f()
action: (n, p, f) ->
_rd: (t) ->
me = @
switch n
when "read"
return f { result: @info } if @info
return unless @isRoot()
f { result: ( v for k, v of Ant.OS.setting.system.packages ) }
new Promise (resolve, reject) ->
return resolve { result: me.info } if me.info
return reject { error: __("Application meta data isnt found") } unless me.isRoot()
resolve { result: ( v for k, v of Ant.OS.setting.system.packages ) }
when "mk"
return
when "write"
return
when "upload"
# install
return
when "remove"
#uninstall
return
when "publish"
return
when "download"
return
when "move"
return
else
return Ant.OS.announcer.osfail __("VFS unknown action: {0}", n), (Ant.OS.API.throwe "OS.VFS"), n
Ant.OS.API.VFS.register "^app$", ApplicationHandle
@ -255,103 +309,73 @@ class BufferFileHandle extends Ant.OS.API.VFS.BaseFileHandle
size: if data then data.length else 0
name: @basename
type: "file"
meta: (f) ->
f()
_rd: (t) ->
me = @
new Promise (resolve, reject) ->
resolve { result: me.cache }
_wr: (d, t) ->
@cache = d
@onchange @ if @onchange
new Promise (resolve, reject) ->
resolve { result: true }
_down: () ->
me = @
new Promise (resolve, reject) ->
blob = new Blob [me.cache], { type: "octet/stream" }
Ant.OS.API.saveblob me.basename, blob
resolve()
onchange: (f) ->
@onchange = f
action: (n, p, f) ->
me = @
switch n
when "read"
return f { result: @cache }
when "mk"
return
when "write"
@cache = p
@onchange @ if @onchange
f { result: true }
when "upload"
# install
return
when "remove"
#uninstall
return
when "publish"
return
when "download"
blob = new Blob [@cache], { type: "octet/stream" }
Ant.OS.API.saveblob me.basename, blob
when "move"
return
else
return Ant.OS.announcer.osfail __("VFS unknown action: {0}", n), (Ant.OS.API.throwe "OS.VFS"), n
Ant.OS.API.VFS.register "^mem$", BufferFileHandle
class URLFileHandle extends Ant.OS.API.VFS.BaseFileHandle
constructor: (path) ->
super path
@ready = true
meta: (f) ->
f { result: true }
action: (n, p, f) ->
me = @
switch n
when "read"
Ant.OS.API.get @path, (d) ->
f(d)
, (e, s) ->
Ant.OS.announcer.oserror __("VFS cannot read : {0}", me.path), e, s
, if p then p else "text"
else
return Ant.OS.announcer.oserror __("VFS unknown action: {0}", n), (Ant.OS.API.throwe "OS.VFS"), n
_rd: (t) ->
Ant.OS.API.get @path, if t then t else "text"
Ant.OS.API.VFS.register "^(http|https)$", URLFileHandle
class SharedFileHandle extends Ant.OS.API.VFS.BaseFileHandle
constructor: (path) ->
super path
@ready = true if @isRoot()
meta: (f) ->
Ant.OS.API.handle.fileinfo @path, f
action: (n, p, f) ->
me = @
switch n
when "read"
return Ant.OS.API.get "#{Ant.OS.API.handle.shared}/all", f, ((e, s)->) if @isRoot()
meta: () ->
Ant.OS.API.handle.fileinfo @path
_rd: (t) ->
return Ant.OS.API.get "#{Ant.OS.API.handle.shared}/all", t if @isRoot()
#read the file
return Ant.OS.API.handle.fileblob @path, f if p is "binary"
Ant.OS.API.handle.readfile @path, f, if p then p else "text"
when "mk"
return
return Ant.OS.API.handle.fileblob @path if t is "binary"
Ant.OS.API.handle.readfile @path, if t then t else "text"
when "write"
Ant.OS.API.handle.write @path, p, f
_wr: (d, t) ->
Ant.OS.API.handle.write @path, d
when "remove"
Ant.OS.API.handle.sharefile @basename, false, f
_rm: () ->
Ant.OS.API.handle.sharefile @basename, false
when "upload"
return
when "publish"
return f { result: @basename }
when "download"
return if @info.type is "dir"
Ant.OS.API.handle.fileblob @path, (d) ->
_down: () ->
me = @
new Promise (resolve, reject) ->
if me.info.type is "dir"
return reject { error: __("{0} is not a file", me.path) }
Ant.OS.API.handle.fileblob me.path, (d) ->
blob = new Blob [d], { type: "octet/stream" }
Ant.OS.API.saveblob me.basename, blob
when "move"
return
else
return Ant.OS.announcer.osfail __("VFS unknown action: {0}", n), (Ant.OS.API.throwe "OS.VFS"), n
resolve()
_pub: () ->
me = @
return new Promise (resolve, reject) -> resolve { result: me.basename }
Ant.OS.API.VFS.register "^shared$", SharedFileHandle

View File

@ -31,9 +31,9 @@ class Calendar extends this.OS.GUI.BaseService
awake: (e) ->
@.openDialog "CalendarDialog", (d) ->
@.openDialog("CalendarDialog" )
.then (d) ->
console.log d
, "Calendar"
# do nothing
cleanup: (evt) ->
console.log "cleanup for quit"

View File

@ -1,5 +1,55 @@
<afx-app-window apptitle="Preview" width="100" height="100">
<afx-hbox>
<afx-button data-height="30" toggle = "true" text="__(Read more)" iconclass="fa fa-camera-retro fa-lg" id="button"></afx-button>
<afx-app-window data-id="example-show-case" apptitle="AntOS GUI widgets" width="650" height="500">
<afx-vbox>
<afx-menu data-height="30" data-id="menu" />
<afx-tab-container data-id="tabctn" tabbarheight= "30">
<afx-hbox tabname="Widgets">
<afx-vbox data-width="150">
<afx-tree-view data-id="tree" />
<afx-slider data-id="slider" data-height="30" value="50"/>
</afx-vbox>
<afx-resizer data-width="5" />
<afx-vbox data-width="grow">
<afx-hbox min-height="50">
<afx-switch data-id="switch" />
<afx-button text="__(This is the label)"
data-id="bttest"
iconclass="fa fa-camera-retro fa-lg"
icon="os://packages/DummyApp/icon.png"/>
<afx-nspinner data-id="spin" value="10" step="2" />
</afx-hbox>
<afx-resizer data-height="5" />
<afx-hbox>
<afx-list-view data-id="list" dropdown="false" multiselect="true" />
</afx-hbox>
<afx-hbox data-height="150">
<afx-grid-view data-id="grid" multiselect="false" />
</afx-hbox>
</afx-vbox>
</afx-hbox>
<afx-hbox tabname="Virtual desktop">
<afx-float-list data-id = "flist"/>
</afx-hbox>
<afx-hbox tabname="Calendar">
<afx-calendar-view data-id = "cal"/>
</afx-hbox>
<afx-hbox tabname="Color picker">
<afx-color-picker data-id = "cpk"/>
</afx-hbox>
<afx-hbox tabname="File view">
<afx-vbox>
<afx-file-view data-id = "fileview"/>
<afx-list-view data-id = "viewoption" data-height="30" dropdown="true" />
</afx-vbox>
</afx-hbox>
<afx-hbox tabname="Dialogs">
<afx-vbox>
<afx-list-view data-id = "dialoglist"/>
<afx-button data-id = "btrundia" text="Run dialog" data-height="30"/>
</afx-vbox>
</afx-hbox>
</afx-tab-container>
</afx-vbox>
</afx-app-window>

View File

@ -5,107 +5,20 @@ class ShowCase extends this.OS.GUI.BaseApplication
main: () ->
me = @
@announcer = new Ant.OS.API.Announcer()
@announcer.on "evt1", (data) ->
console.log "evt1", data
@announcer.on "evt1", (data) ->
console.log "evt1 fn1: ", data
fn = (data) ->
console.log "evt1 fn2: ", data
@announcer.on "evt1", fn
@announcer.on "evt2", (data) ->
console.log "evt2", data
@announcer.one "evt1", (data) ->
console.log "evt1 only one", data
@announcer.one "*", (data) ->
console.log "evt1 only one*", data
@announcer.on "*", fn
console.log me.announcer
@on "btclick", (e) ->
me.openwin()
###
me.announcer.trigger("evt1", "Hello 1")
me.announcer.off("*")
me.announcer.trigger("evt2", "Hello 2")
console.log me.announcer
me.notify "Hello"
console.log tag
###
openwin: () ->
me = @
scheme = $.parseHTML """
<afx-app-window data-id="example-show-case" apptitle="Preview" width="650" height="500">
<afx-vbox>
<afx-menu data-height="30" data-id="menu" />
<afx-tab-container data-id="tabctn" tabbarheight= "30">
<afx-hbox tabname="Widgets">
<afx-vbox data-width="150">
<afx-tree-view data-id="tree" />
<afx-slider data-id="slider" data-height="30" value="50"/>
</afx-vbox>
<afx-resizer data-width="5" />
<afx-vbox data-width="grow">
<afx-hbox min-height="50">
<afx-switch data-id="switch" />
<afx-button text="__(This is the label)"
data-id="bttest"
iconclass="fa fa-camera-retro fa-lg"
icon="os://packages/DummyApp/icon.png"/>
<afx-nspinner data-id="spin" value="10" step="2" />
</afx-hbox>
<afx-resizer data-height="5" />
<afx-hbox>
<afx-list-view data-id="list" dropdown="false" multiselect="true" />
</afx-hbox>
<afx-hbox data-height="150">
<afx-grid-view data-id="grid" multiselect="false" />
</afx-hbox>
</afx-vbox>
</afx-hbox>
<afx-hbox tabname="Virtual desktop">
<afx-float-list data-id = "flist"/>
</afx-hbox>
<afx-hbox tabname="Calendar">
<afx-calendar-view data-id = "cal"/>
</afx-hbox>
<afx-hbox tabname="Color picker">
<afx-color-picker data-id = "cpk"/>
</afx-hbox>
<afx-hbox tabname="File view">
<afx-vbox>
<afx-file-view data-id = "fileview"/>
<afx-list-view data-id = "viewoption" data-height="30" dropdown="true" />
</afx-vbox>
</afx-hbox>
</afx-tab-container>
</afx-vbox>
</afx-app-window>
"""
ctmenu = $.parseHTML """<afx-menu data-id="mn-context" context="true" style="display:none;" /></div>"""
($ "#desktop").append scheme[0]
($ "#wrapper").append ctmenu[0]
me.subwin = scheme[0].uify()
bt = $ "[data-id='bttest']", scheme[0]
bt[0].set "onbtclick", (e) ->
bt = @find 'bttest'
bt.set "onbtclick", (e) ->
console.log "btclicked"
me.subwin.set "resizable", true
me.subwin.set "minimizable", false
me.subwin.observable.on "exit", () ->
me.subwin.observable.off "*"
$(me.subwin).remove()
me.quit()
me.subwin.observable.on "btclick", (e) ->
@observable.on "btclick", (e) ->
console.log "button clicked"
me.subwin.observable.on "menuselect", (e) ->
@observable.on "menuselect", (e) ->
console.log e.id
list = $ "[data-id='list']", scheme[0]
list = @find 'list'
list[0].set "data", [
list.set "data", [
{ text: "some thing with avery long text" },
{ text: "some thing 1", closable: true },
{ text: "some thing 2", iconclass: "fa fa-camera-retro fa-lg" },
@ -113,42 +26,39 @@ class ShowCase extends this.OS.GUI.BaseApplication
{ text: "some thing 4" },
{ text: "some thing 5" }
]
list[0].unshift { text: "shifted el" }
console.log "after shift", list[0].get("data")
list[0].set "onlistselect", (e) ->
console.log(e.data.items)
me.subwin.observable.on "itemclose", (e) ->
console.log "remove", list[0].get("data")
list.unshift { text: "shifted el" }
list.set "onlistselect", (e) -> console.log(e.data.items)
@observable.on "itemclose", (e) ->
console.log "remove", list.get("data")
console.log list[0].get "selectedItem"
console.log list[0].get "selectedItems"
sw = $ "[data-id='switch']", scheme[0]
sw[0].set "onchange", (e) ->
sw = @find 'switch'
sw.set "onchange", (e) ->
console.log e.data
spin = $ "[data-id='spin']", scheme[0]
spin[0].set "onchange", (e) ->
spin = @find 'spin'
spin.set "onchange", (e) ->
console.log e.data
menu = $ "[data-id='menu']", scheme[0]
menu[0].set "items", @menu()
ctmenu = ctmenu[0].uify(me.subwin.observable)
ctmenu.set "items", @menu()
ctmenu.set "onmenuselect", (e) ->
console.log "root event", e
list[0].contextmenuHandle = (e) ->
console.log e
ctmenu.show e
menu = @find 'menu'
menu.set "items", @menu()
grid = $ "[data-id='grid']", scheme[0]
grid[0].set "oncelldbclick", (e) ->
list.contextmenuHandle = (e, m) ->
m.set "items", me.menu()
m.show e
grid = @find 'grid'
grid.set "oncelldbclick", (e) ->
console.log "on dbclick", e
grid[0].set "onrowselect", (e) ->
grid.set "onrowselect", (e) ->
console.log "on rowselect", e.data.items
me.subwin.observable.on "cellselect", (e) ->
@observable.on "cellselect", (e) ->
console.log "observable", e
grid[0].set "header", [{ text: "header1", width: 80 }, { text: "header2" }, { text: "header3" }]
grid[0].set "rows", [
grid.set "header", [{ text: "header1", width: 80 }, { text: "header2" }, { text: "header3" }]
grid.set "rows", [
[{ text: "text 1" }, { text: "text 2" }, { text: "text 3" }],
[{ text: "text 4" }, { text: "text 5" }, { text: "text 6" }],
[{ text: "text 7" }, { text: "text 8" }, { text: "text 9" }],
@ -191,42 +101,42 @@ class ShowCase extends this.OS.GUI.BaseApplication
]
}
tree = $ "[data-id='tree']", scheme[0]
tree[0].set "data", tdata
tree[0].set "ontreeselect", (e) ->
tree = @find 'tree'
tree.set "data", tdata
tree.set "ontreeselect", (e) ->
console.log e.data.item.get "treepath"
tree[0].set "ontreedbclick", (e) ->
tree.set "ontreedbclick", (e) ->
console.log "treedbclick", e
me.subwin.observable.on "treedbclick", (e) ->
@observable.on "treedbclick", (e) ->
console.log "observable treedbclick", e
slider = $ "[data-id='slider']", scheme[0]
slider[0].set "onchanging", (v) ->
slider = @find 'slider'
slider.set "onchanging", (v) ->
console.log v
list = $ "[data-id='flist']", scheme[0]
list[0].set "data", [
flist = @find 'flist'
flist.set "data", [
{ text: "File.txt" },
{ text: "FileB.doc" },
{ text: "Data.doc", iconclass: "fa fa-camera-retro fa-lg" }
]
cal = $ "[data-id='cal']", scheme[0]
cal[0].set "ondateselect", (e) ->
cal = @find 'cal'
cal.set "ondateselect", (e) ->
console.log e
pk = $ "[data-id='cpk']", scheme[0]
pk[0].set "oncolorselect", (e) ->
pk = @find 'cpk'
pk.set "oncolorselect", (e) ->
console.log e
pk[0].set "oncolorselect", (e) ->
pk.set "oncolorselect", (e) ->
console.log e
fileview = $("[data-id='fileview']", scheme[0])[0]
fileview = @find 'fileview'
fileview.set "fetch", (path) ->
new Promise (resolve, reject) ->
dir = path.asFileHandle()
dir.read (d) ->
dir.read().then (d) ->
p = dir.parent().asFileHandle()
p.filename = "[..]"
p.type = "dir"
@ -235,7 +145,7 @@ class ShowCase extends this.OS.GUI.BaseApplication
resolve d.result
fileview.set "path", "home:///"
viewoption = $("[data-id='viewoption']", scheme[0])[0]
viewoption = @find 'viewoption'
viewoption.set "data", [
{ text: "icon" },
{ text: "list" },
@ -245,6 +155,74 @@ class ShowCase extends this.OS.GUI.BaseApplication
console.log e.data.item.get("data").text
fileview.set "view", e.data.item.get("data").text
dllist = @find "dialoglist"
btrun = @find "btrundia"
dllist.set "data", [
{ text: "Prompt dialog", id: "prompt" },
{ text: "Calendar dialog", id: "calendar" },
{ text: "Color picker dialog", id: "colorpicker" },
{ text: "Info dialog", id: "info" },
{ text: "YesNo dialog", id: "yesno" },
{ text: "Selection dialog", id: "selection" },
{ text: "About dialog", id: "about" },
{ text: "File dialog", id: "file" }
]
btrun.set "onbtclick", (e) ->
item = dllist.get "selectedItem"
return unless item
switch item.get("data").id
when "prompt"
me.openDialog("PromptDialog", {
title: "Prompt review",
value: "txt data",
label: "enter value"
})
.then (d) ->
console.log d
when "calendar"
me.openDialog("CalendarDialog", {
title: "Calendar"
})
.then (d) ->
console.log d
when "colorpicker"
me.openDialog("ColorPickerDialog")
.then (d) ->
console.log d
when "info"
me.openDialog("InfoDialog", {
title: "Info application",
name: "Show case",
date: "10/12/2014",
description: "the brown fox jumps over the lazy dog"
})
.then (d) ->
when "yesno"
me.openDialog("YesNoDialog", {
title: "Question ?",
label: "Do you realy want to delete file ?"
})
.then (d) ->
console.log d
when "selection"
me.openDialog("SelectionDialog", {
title: "Select data ?",
data: [
{ text: "Option 1" },
{ text: "Option 2" },
{ text: "Option 3", iconclass: "fa fa-camera-retro fa-lg" }
]
})
.then (d) ->
console.log d
when "about"
me.openDialog("AboutDialog" )
.then (d) ->
else return
mnFile: () ->
#console.log file
@ -274,9 +252,7 @@ class ShowCase extends this.OS.GUI.BaseApplication
{ text: "__(Paste)", dataid: "#{@name}-paste", shortcut: 'C-P' }
], onchildselect: (e) -> console.log "child", e
}
cleanup: () ->
return unless @subwin
$(@subwin).remove()
menu: () ->
me = @
menu = [

View File

@ -41,12 +41,19 @@ afx-calendar-view i.nextmonth:before{
right:5px;*/
}
/*
afx-calendar-view afx-grid-view afx-grid-row.selected{
background-color: white;
color:#414339;
}
}*/
afx-calendar-view afx-grid-view afx-grid-row .cellselected{
afx-calendar-view afx-grid-view div.afx-grid-row-selected .afx-grid-cell
{
background-color: transparent;
color:black;
}
afx-calendar-view afx-grid-view div.afx-grid-row-selected .afx-grid-cell-selected
{
background-color: #116cd6;
color:white;
border-radius: 6px;

View File

@ -7,21 +7,28 @@ afx-grid-view afx-grid-row div{
cursor:default;
}
afx-grid-view afx-grid-row:nth-child(even){
afx-grid-view div.afx-grid-row:nth-child(even) .afx-grid-cell
{
background-color: #f5F5F5;
}
afx-grid-view afx-grid-row.grid_row_header div{
afx-grid-view div.afx-grid-row-selected .afx-grid-cell
{
background-color: #116cd6;
color:white;
}
afx-grid-view div.afx-grid-row-selected .afx-grid-cell-selected
{
font-weight: bold;
}
afx-grid-view div.grid_row_header{
border-right: 2px solid #e5e5e5;
user-select:none;
-webkit-user-select:none;
cursor:default;
}
afx-grid-view afx-grid-row.selected {
background-color: #116cd6;
color:white;
}
afx-grid-view afx-grid-row.grid_row_header {
font-weight: bold;
border: 1px solid #e5e5e5;
border-right:0;

View File

@ -37,8 +37,7 @@ afx-list-view > div.list-container > ul li{
-webkit-user-select:none;
cursor:default;
}
afx-list-view > div.list-container > ul afx-list-item:nth-child(even) li,
afx-list-view > div.list-container > ul li:nth-child(even){
afx-list-view > div.list-container > ul afx-list-item:nth-child(even) li{
background-color:#f5F5F5;
}
afx-list-view i.closable{
@ -63,8 +62,7 @@ afx-list-view > div.list-container > ul li > i {
margin-right: 3px;
}
afx-list-view > div.list-container > ul > afx-list-item > li.selected,
afx-list-view > div.list-container > ul li.selected {
afx-list-view > div.list-container > ul > afx-list-item > li.selected{
background-color: #116cd6;
color:white;
}

View File

@ -7,6 +7,17 @@ afx-tab-bar afx-list-view {
padding:0;
margin:0;
}
afx-tab-bar afx-list-view > div.list-container > ul afx-list-item:nth-child(even) li
{
background-color: transparent;
}
afx-tab-bar afx-list-view > div.list-container > ul > afx-list-item > li.selected
{
background-color: #116cd6;
color:white;
}
afx-tab-bar afx-list-view > div.list-container > ul li{
float:left;
border-top-left-radius: 5px;

View File

@ -39,7 +39,7 @@ html,body{
cursor: default;
padding:0px;
}
#desktop > div > .float_list_item {
#desktop > div > ul afx-list-item {
display:block;
background-color:transparent;
text-align: center;
@ -48,7 +48,7 @@ html,body{
padding:3px;
}
#desktop > div > div.float_list_item_selected {
#desktop > div > ul afx-list-item li.selected {
display:block;
background-color: #116cd6;
color:white;
@ -59,7 +59,7 @@ html,body{
padding:3px;
}
#desktop > div > div.float_list_item i.file:before{
#desktop > div > ul afx-list-item i.file:before{
content: "\f15b\a";
font-family: "FontAwesome";
font-size: 32px;
@ -68,11 +68,11 @@ html,body{
font-style: normal;
font-weight: normal;
}
#desktop > div > div.float_list_item span{
#desktop > div > ul afx-list-item span{
width: 100%;
word-wrap: break-word;
}
#desktop > div > div.float_list_item i.dir:before{
#desktop > div > ul afx-list-item i.dir:before{
display: block;
content: "\f07b\a";
font-family: "FontAwesome";
@ -81,6 +81,7 @@ html,body{
font-weight: normal;
font-style: normal;
}
#systooltip {
border:1px solid #a6a6a6;
border-radius: 3px;