remote handler

This commit is contained in:
Xuan Sang LE
2017-08-27 23:40:02 +02:00
parent fc406be924
commit 6f298fc52b
42 changed files with 714 additions and 205 deletions

View File

@ -1,7 +1,7 @@
self = this
class BaseApplication extends this.OS.GUI.BaseModel
constructor: (name) ->
super name
constructor: (name, args) ->
super name, args
init: ->
me = @
@ -44,11 +44,11 @@ class BaseApplication extends this.OS.GUI.BaseModel
if not evt.prevent
@.appmenu.set "items", [] if @.pid == @.appmenu.pid
($ @scheme).remove()
meta: () -> _APP[@name].meta
meta: () -> _OS.APP[@name].meta
baseMenu: ->
mn =
[{
text: _APP[@name].meta.name,
text: _OS.APP[@name].meta.name,
child: [
{ text: "About", dataid: "#{@name}-about" },
{ text: "Exit", dataid: "#{@name}-exit" }

View File

@ -1,6 +1,6 @@
class BaseDialog extends this.OS.GUI.BaseModel
constructor: (name) ->
super name
super name, null
@parent = undefined
@modal = false
@handler = undefined
@ -47,8 +47,8 @@ class BasicDialog extends BaseDialog
html = "<afx-app-window data-id = 'dia-window' apptitle='#{@name}' width='#{@conf.width}' height='#{@conf.height}'>
<afx-hbox>"
html += "<#{@conf.tag} data-id = 'content'></#{@conf.tag}>"
html += "<div data-height = '40' style='padding:5px; text-align:right;'>"
html += "<afx-button data-id = 'bt#{k}' text = '#{v.label}' style='margin-left:3px;'></afx-button>" for k,v of @conf.buttons
html += "<div data-height = '40' style=' text-align:right;padding-top:3px;'>"
html += "<afx-button data-id = 'bt#{k}' text = '#{v.label}' style='margin-right:5px;'></afx-button>" for k,v of @conf.buttons
html += "</div></afx-hbox></afx-app-window>"
#render the html
_GUI.htmlToScheme html, @, @host
@ -60,6 +60,7 @@ class BasicDialog extends BaseDialog
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
this.OS.GUI.BasicDialog = BasicDialog
@ -115,6 +116,22 @@ class ColorPickerDialog extends BasicDialog
}
this.OS.register "ColorPickerDialog", ColorPickerDialog
class InfoDialog extends BasicDialog
constructor: () ->
super "InfoDialog", {
tag: 'afx-grid-view',
width: 250,
height: 300,
resizable: true,
buttons: [ { label: 'Cancel', onclick: (d) -> d.quit() } ],
filldata: (d) ->
return unless d.data
rows = []
rows.push [ { value: k }, { value: v } ] for k, v of d.data
(d.find "content").set "rows", rows
}
this.OS.register "InfoDialog", InfoDialog
class AboutDialog extends BaseDialog
constructor: () ->
super "AboutDialog"

View File

@ -1,10 +1,12 @@
class BaseModel
constructor: (@name) ->
constructor: (@name, @args) ->
@observable = riot.observable()
@_api = self.OS.API
me = @
@on "exit", () -> me.quit()
@host = "#desktop"
_OS.setting.applications[@name] = {} if not _OS.setting.applications[@name]
@setting = _OS.setting.applications[@name]
@dialog = undefined
render: (p) ->
@ -29,7 +31,7 @@ class BaseModel
subscribe: (e, f) -> _courrier.on e, f, @
openDialog: (d, f) ->
openDialog: (d, f, data) ->
if @dialog
@dialog.show()
return
@ -40,6 +42,7 @@ class BaseModel
@dialog.parent = @
@dialog.handler = f
@dialog.pid = @pid
@dialog.data = data
@dialog.init()
publish: (t, m) ->

View File

@ -1,6 +1,6 @@
class BaseService extends this.OS.GUI.BaseModel
constructor: (name) ->
super name
constructor: (name, args) ->
super name, args
@icon = undefined
@iconclass = "fa-paper-plane-o"
@text = ""

View File

@ -3,20 +3,20 @@ self.OS.API =
# fetch user data, used by the API to make requests
# handlers are defined in /src/handlers
handler: {}
VFS:
scandir: (p, c, f) ->
_API.handler.request "scandir", { path: p }, c, f
#request a user data
post: (p, d, c, f) ->
q = _courrier.getMID()
_API.loading q, p
$.ajax {
type: "POST",
type: 'POST',
url: p,
data: d,
success: null,
dataType: 'json'
contentType: 'application/json',
data: JSON.stringify d,
dataType: 'json',
success: null
}
#$.getJSON p, d
.done (data) ->
_API.loaded q, p, "OK"
c(data)
@ -51,7 +51,7 @@ self.OS.API =
.fail (e, s) ->
_API.loaded q, p, "FAIL"
f(e, s)
resource: (resource, callback) ->
path = "resources/#{resource}"
_API.get path, callback
resource: (r, c, f) ->
path = "resources/#{r}"
_API.get path, c, f

View File

@ -2,10 +2,13 @@
self = this
self.OS or=
API: new Object()
GUI: new Object()
APP: new Object()
API: {}
GUI: {}
APP: {}
setting:
user: {}
applications: {}
appearance: {}
courrier:
observable: riot.observable()
quota: 0
@ -15,6 +18,12 @@ self.OS or=
_courrier.listeners[a.pid].push { e: e, f: f }
_courrier.observable.on e, f
trigger: (e, d) -> _courrier.observable.trigger e, d
osfail: (m, e, s) ->
_courrier.ostrigger "fail", { m: m, e: e, s: s }
oserror: (m, e, s) ->
_courrier.ostrigger "error", { m: m, e: e, s: s }
ostrigger: (e, d) ->
_courrier.trigger e, { id: 0, data: d, name: "OS" }
unregister: (app) ->
return unless _courrier.listeners[app.pid] and _courrier.listeners[app.pid].length > 0
_courrier.observable.off i.e, i.f for i in _courrier.listeners[app.pid]
@ -24,12 +33,12 @@ self.OS or=
_courrier.quota += 1
_courrier.quota
register: (name, x) ->
if x.type is 3 then self.OS.GUI.dialog[name] = x else _APP[name] = x
if x.type is 3 then self.OS.GUI.dialog[name] = x else _OS.APP[name] = x
PM:
pidalloc: 0
processes: new Object
createProcess: (app, cls) ->
processes: {}
createProcess: (app, cls, args) ->
#if it is single ton
# and a process is existing
# just return it
@ -37,7 +46,7 @@ self.OS or=
_PM.processes[app][0].show()
else
_PM.processes[app] = [] if not _PM.processes[app]
obj = new cls
obj = new cls(args)
obj.birth = (new Date).getTime()
_PM.pidalloc++
obj.pid = _PM.pidalloc
@ -55,20 +64,28 @@ self.OS or=
app
kill: (app) ->
return if not _PM.processes[app.name]
return if not app.name or not _PM.processes[app.name]
i = _PM.processes[app.name].indexOf app
if i >= 0
if _APP[app.name].type == 1 then _GUI.undock app else _GUI.detachservice app
if _OS.APP[app.name].type == 1 then _GUI.undock app else _GUI.detachservice app
_courrier.unregister app
delete _PM.processes[app.name][i]
_PM.processes[app.name].splice i, 1
killAll: (app) ->
return unless _PM.processes[app]
tmp = []
tmp.push a for a in _PM.processes[app]
a.quit() for a in tmp
boot: ->
#first load the configuration
#then load the theme
_GUI = self.OS.GUI
_GUI.loadTheme "antos"
_GUI.initDM()
_courrier.observable.one "syspanelloaded", () ->
_GUI.pushServices ["PushNotification", "Spotlight", "Calendar"]
#first login
_API.handler.auth (d) ->
# in case someone call it more than once :)
if d.error
# show login screen
_GUI.login()
else
# startX :)
_GUI.startAntOS d.result

View File

@ -18,11 +18,11 @@ self.OS.GUI =
return null unless x
_GUI.htmlToScheme x, app, parent
, (e, s) ->
_courrier.trigger "fail",
{id: 0, data: {
m: "Cannot load scheme file: #{path} for #{app.name} (#{app.pid})",e: e, s: s },
name:"OS"
}
_courrier.osfail "Cannot load scheme file: #{path} for #{app.name} (#{app.pid})",e,s
clearTheme: () ->
$ "head link#ostheme"
.attr "href", ""
loadTheme: (name) ->
path = "resources/themes/#{name}/#{name}.css"
@ -37,19 +37,23 @@ self.OS.GUI =
f i for i in srvs
pushService: (srv) ->
return _PM.createProcess srv, _APP[srv] if _APP[srv]
return _PM.createProcess srv, _OS.APP[srv] if _OS.APP[srv]
path = "services/#{srv}.js"
_API.script path,
(d) ->
_PM.createProcess srv, _APP[srv]
_PM.createProcess srv, _OS.APP[srv]
, (e, s) ->
_courrier.trigger "srvroutineready", srv
_courrier.trigger "fail",
{ id:0,data:{m: "Cannot read service script: #{srv} ", e: e, s: s },
name:"0S"}
_courrier.osfail "Cannot read service script: #{srv} ", e, s
launch: (app) ->
if not _APP[app]
forceLaunch: (app, args) ->
console.log "This method is used for developing only, please use the launch method instead"
_PM.killAll app
_OS.APP[app] = undefined
_GUI.launch app, args
launch: (app, args) ->
if not _OS.APP[app]
# first load it
path = "packages/#{app}/"
_API.script path + "main.js",
@ -61,26 +65,23 @@ self.OS.GUI =
.appendTo 'head'
, () ->
#launch
if _APP[app]
if _OS.APP[app]
# load app meta data
_API.get "#{path}package.json",
(data) ->
_APP[app].meta = data
_PM.createProcess app, _APP[app]
_OS.APP[app].meta = data
_PM.createProcess app, _OS.APP[app], args
, (e, s) ->
_courrier.trigger "fail",
{id:0, data:{ m: "Cannot read application metadata: #{app} ",e: e, s: s }, name:"OS"}
_courrier.osfail "Cannot read application metadata: #{app}", e, s
alert "cannot read application, meta-data"
, (e, s) ->
#BUG report here
_courrier.trigger "fail",
{id :0, data:{m: "Cannot load application script: #{app}",
e: e, s:s }, name:"OS"}
_courrier.osfail "Cannot load application script: #{app}", e, s
console.log "bug report", e, s, path
else
# now launch it
if _APP[app]
_PM.createProcess app, _APP[app]
if _OS.APP[app]
_PM.createProcess app, _OS.APP[app], args
dock: (app, meta) ->
# dock an application to a dock
# create a data object
@ -118,6 +119,7 @@ self.OS.GUI =
handler event.target
event.preventDefault()
initDM: ->
# check login first
_API.resource "schemes/dm.html", (x) ->
return null unless x
scheme = $.parseHTML x
@ -134,4 +136,42 @@ self.OS.GUI =
console.log "context menu handler for desktop"
# system menu
riot.mount ($ "#syspanel", $ "#wrapper")
riot.mount ($ "#sysdock", $ "#wrapper"), { items: [] }
riot.mount ($ "#sysdock", $ "#wrapper"), { items: [] }
, (e, s) ->
alert "System fall: Cannot init desktop manager"
login: () ->
($ "#wrapper").empty()
_GUI.clearTheme()
_API.resource "schemes/login.html", (x) ->
return null unless x
scheme = $.parseHTML x
($ "#wrapper").append scheme
($ "#btlogin").click () ->
data =
username: ($ "#txtuser").val(),
password: ($ "#txtpass").val()
_API.handler.login data, (d) ->
console.log d
if d.error then ($ "#login_error").html d.error else _GUI.startAntOS d.result
, (e, s) ->
alert "System fall: Cannot init login screen"
startAntOS: (conf) ->
($ "#wrapper").empty()
_GUI.clearTheme()
_courrier.observable = riot.observable()
_OS.APP = {}
_PM.processes = {}
_PM.pidalloc = 0
_OS.setting.applications = conf.applications if conf.applications
_OS.setting.appearance = conf.appearance if conf.appearance
_OS.setting.user = conf.user
# get setting from conf
# load packages list
# load theme
# initDM
_GUI.loadTheme "antos"
_GUI.initDM()
_courrier.observable.one "syspanelloaded", () ->
_GUI.pushServices ["PushNotification", "Spotlight", "Calendar"]

View File

@ -0,0 +1,26 @@
self.OS.API.handler =
scandir: (p, c ) ->
path = "lua-api/fs/scandir"
_API.post path, { path: p }, c, (e, s) ->
_courrier.osfail "Fail to make request: #{path}", e, s
auth: (c) ->
p = "lua-api/system/auth"
_API.post p, {}, c, () ->
alert "Resource not found: #{p}"
login: (d, c) ->
p = "lua-api/system/login"
_API.post p, d, c, () ->
alert "Resource not found: #{p}"
logout: () ->
p = "lua-api/system/logout"
_API.post p, {}, (d) ->
_OS.boot()
, () ->
alert "Resource not found #{p}"
setting: () ->
p = "lua-api/system/settings"
_API.post p, _OS.setting, (d) ->
_courrier.oserror "Cannot save system setting", d.error if d.error
, (e, s) ->
_courrier.osfail "Fail to make request: #{p}", e, s

View File

@ -1,8 +1,6 @@
self.OS.API.handler =
request: ( p, d, c, f) ->
path = switch p
when 'scandir' then 'resources/jsons/scandir.json'
else undefined
return unless path
_API.get path, c, f
scandir: (p, c ) ->
path = 'resources/jsons/scandir.json'
_API.get path , c, (e, s) ->
_courrier.osfail "System fall: Cannot read #{path}", e, s

View File

@ -0,0 +1,78 @@
<!--
Since nothing is loaded, the login form is a standalone element,
it deserves it own unique style
For now, it can not be themed !!!
-->
<style>
body, html{
background-color: rgba(215,215,215,0.7);
}
#login_form{
width:300px;
height: 200px;
display: block;
border:1px solid #a6a6a6;
border-radius: 6px;
box-shadow: 1px 1px 1px #9f9F9F;
position: absolute;
margin: auto;
top:0;
right: 0;
bottom: 0;
left: 0;
font-family:Verdana, Geneva, Tahoma, sans-serif;
font-size: 13px;
text-align: center;
background-color: white;
color: #414339;
}
#login_form p{
display: inline-block;
background-color:#dfdfdf;
border-bottom: 1px solid #a6a6a6;
padding:10px;
width: calc(100% - 20px);
border-top-left-radius: 6px;
border-top-right-radius: 6px;
font-weight: bold;
margin:0;
}
#login_form input {
width: 250px;
outline: none;
margin-top:10px;
border-radius: 6px;
box-sizing: border-box;
font-size: 13px;
padding: 5px;
border: 1px solid #a6a6a6;
background-color: white;
color: #414339;
}
#login_form button{
margin-top:10px;
width: 250px;
height: 30px;
background-color: #2786F3;
color: white;
border: 1px solid #dedede;
border-radius: 6px;
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: 13px;
padding:5px;
}
#login_error{
padding:3px;
color:red;
font-weight: normal;
}
</style>
<div id = "login_form">
<p>Welcome to AntOS, plese identify</p>
<input id = "txtuser" type = "text" value = "User name" />
<input id = "txtpass" type = "password" value = "password" />
<button id = "btlogin">Login</button>
<span id = "login_error"></span>
</div>

View File

@ -77,7 +77,15 @@
$(self.refs.content).children().each(function(e){
this.observable = self.root.observable
})
var fn = function()
{
var ch = $(self.refs.content).height()/ $(self.refs.content).children().length
$(self.refs.content).children().each(function(e){
$(this).css("height",ch+"px")
})
}
fn()
self.root.observable.on("resize", function(){ fn()})
self.root.observable.on("focus",function(){
window._zindex++
$(self.refs.window)

View File

@ -1,11 +1,12 @@
<afx-button>
<button disabled={ enable == "false" } onclick="{ _onbtclick }" >
<afx-label icon={icon} iconclass = {iconclass} text = {text} ></afx-label>
<afx-label color = {color} icon={icon} iconclass = {iconclass} text = {text} ></afx-label>
</button>
<script>
this.enable = opts.enable
this.icon = opts.icon
this.iconclass = opts.iconclass
this.color = opts.color
this.text = opts.text || ""
var self = this
this.onbtclick = opts.onbtclick

View File

@ -56,6 +56,12 @@
colorctx.fillRect(0, 0, colorctx.canvas.width, colorctx.canvas.height)
//$(self.refs.palette).css("position", "absolute")
// now add mouse move event
var getHex = function(c)
{
s = c.toString(16)
if(s.length == 1) s = "0" + s
return s
}
var pick_color = function(e)
{
$(self.refs.palette).css("cursor","crosshair")
@ -68,7 +74,7 @@
g:color.data[1],
b:color.data[2],
text:'rgb(' + color.data[0] + ', ' + color.data[1] + ', ' + color.data[2] + ')',
hex:'#' + color.data[0].toString(16) + color.data[1].toString(16) + color.data[2].toString(16)
hex:'#' + getHex(color.data[0]) + getHex(color.data[1]) + getHex(color.data[2])
}
return data
}

View File

@ -1,7 +1,9 @@
<afx-file-view>
<afx-list-view ref="listview" observable = {root.observable}></afx-list-view>
<afx-grid-view ref = "gridview" header = {header} observable = {root.observable}></afx-grid-view>
<afx-tree-view ref = "treeview" observable = {root.observable}></afx-tree-view>
<div class = "treecontainer" ref="treecontainer">
<afx-tree-view ref = "treeview" observable = {root.observable}></afx-tree-view>
</div>
<div if = {status == true} class = "status" ref = "stbar"></div>
<script>
var self = this
@ -12,8 +14,11 @@
self.onfileselect
this.status = opts.status == undefined?true:opts.status
this.selectedFile = undefined
this.showhidden = opts.showhidden
this.fetch = opts.fetch
this.chdir = opts.chdir
this.rid = $(self.root).attr("data-id") || Math.floor(Math.random() * 100000) + 1
this.header = [{value:"File name"},{value: "Type", width:100}, {value: "Size", width:70}]
this.header = [{value:"File name"},{value: "Type", width:150}, {value: "Size", width:70}]
self.root.set = function(k,v)
{
@ -36,35 +41,50 @@
}
var calibre_size = function()
{
var h = $(self.root).height()
var h = $(self.root).outerHeight()
var w = $(self.root).width()
if(self.refs.stbar)
h -= $(self.refs.stbar).height()
h -= ($(self.refs.stbar).height() + 10)
$(self.refs.listview.root).css("height", h + "px")
$(self.refs.gridview.root).css("height", h + "px")
$(self.refs.treeview.root).css("height", h + "px")
$(self.refs.treecontainer).css("height", h + "px")
$(self.refs.listview.root).css("width", w + "px")
$(self.refs.gridview.root).css("width", w + "px")
$(self.refs.treecontainer).css("width", w + "px")
}
var refreshList = function(){
var items = []
$.each(self.data, function(i, v){
if(v.filename[0] == '.' && !self.showhidden) return
v.text = v.filename
if(v.text.length > 10)
v.text = v.text.substring(0,9) + "..."
v.iconclass = v.type
items.push(v)
})
self.refs.listview.root.set("items", self.data)
self.refs.listview.root.set("items", items)
}
var refreshGrid = function(){
var rows = []
$.each(self.data, function(i,v){
if(v.filename[0] == '.' && !self.showhidden) return
var row = [{value:v.filename, iconclass: v.type},{value:v.mime},{value:v.size}]
rows.push(row)
})
self.refs.gridview.root.set("rows",rows)
}
var refreshTree = function(){
self.refs.treeview.root.set("selectedItem", null)
var tdata = {}
tdata.name = self.path
tdata.nodes = []
$.each(self.data, function(i,v){
tdata.nodes = getTreeData(self.data)
self.refs.treeview.root.set("*", tdata)
}
var getTreeData = function(data)
{
nodes = []
$.each(data, function(i,v){
if(v.filename[0] == '.' && !self.showhidden) return
v.name = v.filename
if(v.type == 'dir')
{
@ -72,9 +92,9 @@
v.open = false
}
v.iconclass = v.type
tdata.nodes.push(v)
nodes.push(v)
})
self.refs.treeview.root.set("*", tdata)
return nodes
}
var refreshData = function(){
self.data.sort(sortByType)
@ -89,10 +109,16 @@
{
$(self.refs.listview.root).hide()
$(self.refs.gridview.root).hide()
$(self.refs.treeview.root).hide()
$(self.refs.treecontainer).hide()
self.selectedFile = undefined
self.refs.listview.root.set("selected", -1)
self.refs.treeview.selectedItem = undefined
self.refs.treeview.root.set("fetch",function(e,f){
if(!self.fetch) return
self.fetch(e, function(d){
f(getTreeData(d))
})
})
$(self.refs.stbar).html("")
switch (self.view) {
case 'icon':
@ -102,7 +128,7 @@
$(self.refs.gridview.root).show()
break;
case 'tree':
$(self.refs.treeview.root).show()
$(self.refs.treecontainer).show()
break;
default:
break;
@ -120,22 +146,43 @@
data.id = self.rid
self.root.observable.trigger("fileselect",data)
}
self.refs.listview.onlistdbclick = function(data)
{
data.id = self.rid
self.root.observable.trigger("filedbclick",data)
}
self.refs.gridview.root.observable = self.root.observable
self.refs.gridview.ongridselect = function(d)
{
var data = {id:self.rid, data:self.data[d.data.i], idx:d.data.i}
self.root.observable.trigger("fileselect",data)
}
self.refs.gridview.ongriddbclick = function(d)
{
var data = {id:self.rid, data:self.data[d.data.i], idx:d.data.i}
self.root.observable.trigger("filedbclick",data)
}
self.refs.treeview.ontreeselect = function(d)
{
if(!d.data) return;
var data = {id:self.rid, data:d.data.child, idx:d.data.i}
self.root.observable.trigger("fileselect",data)
}
self.refs.treeview.ontreedbclick = function(d)
{
if(!d.data) return;
var data = {id:self.rid, data:d.data.child, idx:d.data.i}
self.root.observable.trigger("filedbclick",data)
}
self.root.observable.on("fileselect", function(e){
if(e.id != self.rid) return
self.selectedFile = e.data
$(self.refs.stbar).html("Selected: " + e.data.filename + " (" + e.data.size + " bytes)")
})
self.root.observable.on("filedbclick", function(e){
if(e.id != self.rid || e.data.type == 'file' || !self.chdir) return
self.chdir(e.data.path)
})
calibre_size()
self.root.observable.on("resize", function(e){
calibre_size()

View File

@ -1,8 +1,8 @@
<afx-grid-view>
<afx-grid-row ref="gridhead" rootid = {rid} observable = {root.observable} header="true" class = {grid_row_header:header} if = {header} cols = {header}> </afx-grid-row>
<div ref = "scroller" style="width:100%; overflow:auto;">
<div ref = "container">
<afx-grid-row each={ child, i in rows } class = {selected: child.selected} rootid = {parent.rid} observable = {parent.root.observable} index = {i} cols = {child} onclick = {parent._select} head = {parent.refs.gridhead} ></afx-grid-row>
<div ref = "container" style ="padding-bottom:10px">
<afx-grid-row each={ child, i in rows } class = {selected: child.selected} rootid = {parent.rid} observable = {parent.root.observable} index = {i} cols = {child} ondblclick = {parent._dbclick} onclick = {parent._select} oncontextmenu = {parent._select} head = {parent.refs.gridhead} ></afx-grid-row>
</div>
</div>
<script>
@ -13,6 +13,7 @@
self.selidx = -1
self.nrow = 0
self.ongridselect = opts.ongridselect
self.ongriddbclick = opts.ongriddbclick
self.root.observable = opts.observable
self.root.set = function(k,v)
{
@ -82,13 +83,22 @@
self.update()
//event.preventDefault()
}
_dbclick(event)
{
data = {
id:self.rid,
data:event.item}
if(self.ongriddbclick)
self.ongriddbclick(data)
self.root.observable.trigger('griddbclick', data)
}
</script>
</afx-grid-view>
<afx-grid-row>
<div style = {!header? "display: table-cell;" :""} onclick = {parent._cell_select} each = { child,i in cols } class = {string:typeof child.value == "string", number: typeof child.value == "number", cellselected: parent._auto_cell_select(child,i)} >
<afx-label icon = {child.icon} iconclass = {child.iconclass} text = {child.value} ></afx-label>
<afx-label color={child.color} icon = {child.icon} iconclass = {child.iconclass} text = {child.value} ></afx-label>
</div>
<script>
this.cols = opts.cols || []

View File

@ -1,4 +1,4 @@
<afx-hbox>
<afx-hbox style = "display:block;">
<div ref = "container" class="afx-hbox-container">
<yield/>
</div>
@ -26,8 +26,8 @@
{
var auto_height = []
var csize, ocheight = 0, avaiheight;
avaiheight = $(self.root).parent().height()
avaiwidth = $(self.root).parent().width()
avaiheight = $(self.root).height()
avaiwidth = $(self.root).width()
$(self.refs.container).css("height",avaiheight + "px")
$(self.refs.container)
.children()

View File

@ -1,5 +1,5 @@
<afx-label>
<span>
<span style = {color?"color:" + color:""} >
<i if={iconclass} class = {iconclass} ></i>
<i if={icon} class="icon-style" style = { "background: url("+icon+");background-size: 100% 100%;background-repeat: no-repeat;" }></i>
{ text }
@ -8,11 +8,13 @@
this.iconclass = opts.iconclass
this.icon = opts.icon
this.text = opts.text
this.color = opts.color
var self = this
this.on("update",function(){
self.iconclass = opts.iconclass
self.icon = opts.icon
self.text = opts.text
self.color = opts.color
})
self.root.set = function(k,v)
{

View File

@ -3,8 +3,8 @@
<div if = {opts.dropdown == "true"} ref = "current" style = {opts.width?"min-width:" + opts.width + "px;":"min-width:150px;"} onclick = {show_list}>
</div>
<ul ref = "mlist">
<li each={item,i in items } class={selected: parent._autoselect(item,i)} onclick = {parent._select}>
<afx-label iconclass = {item.iconclass} icon = {item.icon} text = {item.text}></afx-label>
<li each={item,i in items } class={selected: parent._autoselect(item,i)} ondblclick = {parent._dbclick} onclick = {parent._select} oncontextmenu = {parent._select}>
<afx-label color = {item.color} iconclass = {item.iconclass} icon = {item.icon} text = {item.text}></afx-label>
<i if = {item.closable} class = "closable" click = {parent._remove}></i>
</li>
</ul>
@ -14,6 +14,7 @@
var self = this
self.selidx = -1
self.onlistselect = opts.onlistselect
self.onlistdbclick = opts.onlistdbclick
var onclose = false
this.rid = $(self.root).attr("data-id") || Math.floor(Math.random() * 100000) + 1
self.root.set = function(k,v)
@ -138,5 +139,15 @@
self.items[self.selidx].selected =false
event.item.item.selected = true
}
_dbclick(event)
{
data = {
id:self.rid,
data:event.item.item,
idx: event.item.i}
if(self.onlistdbclick)
self.onlistdbclick(data)
self.root.observable.trigger('listdbclick', data)
}
</script>
</afx-list-view>

View File

@ -4,7 +4,7 @@
<li ref = "container" each={ data,i in items } class = {afx_submenu:data.child != null, fix_padding:data.icon} no-reorder>
<a href="#" onclick = {parent.onselect}>
<afx-switch if = {data.switch || data.radio} class = {checked:parent.checkItem(data)} enable = false swon = {data.checked} ></afx-switch>
<afx-label iconclass = {data.iconclass} icon = {data.icon} text = {data.text} ></afx-label>
<afx-label color = {data.color} iconclass = {data.iconclass} icon = {data.icon} text = {data.text} ></afx-label>
</a>
<afx-menu if={data.child != null} child={data.child} onmenuselect = {data.onmenuselect} observable = {parent.root.observable} rootid = {parent.rid}></afx-menu>
@ -22,7 +22,7 @@
}
else
{
this.rid = $(this.root).attr("data-id")
this.rid = $(this.root).attr("data-id") || Math.floor(Math.random() * 100000) + 1
isRoot = true
}
var self = this
@ -94,7 +94,6 @@
{
this.root.observable = riot.observable()
this.root.observable.on('menuselect',function(data){
//console.log("From root",self.root)
if(self.onmenuselect)
self.onmenuselect(data)

View File

@ -21,12 +21,17 @@
onmenuselect: function(d)
{
if(d.e.item.data.type == "app")
window.OS.GUI.launch(d.e.item.data.text)
window.OS.GUI.launch(d.e.item.data.text, null)
}
},
{text:"Logout"}
{text:"Logout", dataid: "sys-logout"}
]}
]
],
onmenuselect: function(d)
{
if(d.e.item.data.dataid == "sys-logout")
window.OS.API.handler.logout()
}
}
this.appmenu = { child: [] }
this.systray = {

View File

@ -1,17 +1,22 @@
<afx-tree-view>
<div ref = namediv class={afx_tree_item_selected:treeroot.selectedItem && treeroot.selectedItem.path == path, afx_folder_item: isFolder(), afx_tree_item_odd: index%2 != 0 } click={select}>
<i if={ !isFolder() && iconclass} class = {iconclass} ></i>
<i if={!isFolder() && icon} class="icon-style" style = { "background: url("+icon+");background-size: 100% 100%;background-repeat: no-repeat;" }></i>
<div class={afx_tree_item_selected:treeroot.selectedItem && treeroot.selectedItem.path == path, afx_folder_item: isFolder(), afx_tree_item_odd: index%2 != 0 } onclick={select} ondblclick = {_dbclick} oncontextmenu = {select}>
<ul style = "padding:0;margin:0;white-space: nowrap;">
<li ref = "padding" ></li>
<li class = "itemname" style="display:inline-block;" >
<i if={ !isFolder() && iconclass} class = {iconclass} ></i>
<i if={!isFolder() && icon} class="icon-style" style = { "background: url("+icon+");background-size: 100% 100%;background-repeat: no-repeat;" }></i>
<span onclick={ toggle } if={ isFolder() } class={open ? 'afx-tree-view-folder-open' : 'afx-tree-view-folder-close'}></span>
{ name }
<span onclick={ toggle } if={ isFolder() } class={open ? 'afx-tree-view-folder-open' : 'afx-tree-view-folder-close'}></span>
{ name }
</li>
</ul>
</div>
<ul if={ isFolder() } show={ isFolder() && open }>
<li each={ child, i in nodes }>
<afx-tree-view ontreeselect = {parent.ontreeselect} data={child} indent={indent+1} observable = {parent.root.observable} path = {parent.path + ">" + i} treeroot= {parent.treeroot}></afx-tree-view>
<afx-tree-view ontreeselect = {parent.ontreeselect} fetch = {parent.fetch} ontreedbclick = {parent.ontreedbclick} data={child} indent={indent+1} observable = {parent.root.observable} path = {parent.path + ">" + i} treeroot= {parent.treeroot}></afx-tree-view>
</li>
</ul>
@ -28,6 +33,8 @@
}
this.rid = $(self.root).attr("data-id") || Math.floor(Math.random() * 100000) + 1
self.ontreeselect = opts.ontreeselect
self.ontreedbclick = opts.ontreedbclick
self.fetch = opts.fetch
self.indent = opts.indent || 1
var istoggle = false
if(opts.treeroot)
@ -66,7 +73,13 @@
}
this.on("mount", function(){
$(self.refs.namediv).css("padding-left", self.indent*15 + "px" )
$(self.refs.padding)
.css("display", "inline-block")
.css("height","1px")
.css("padding",0)
.css("margin", 0)
.css("background-color","transparent")
.css("width", self.indent*15 + "px" )
})
isFolder() {
@ -77,6 +90,11 @@
self.open = !self.open
e.preventDefault()
istoggle = true
if(self.open && self.nodes.length == 0 && self.fetch)
self.fetch(e.item, function(d){
self.nodes = d
self.update()
})
}
select(event)
@ -99,5 +117,22 @@
self.treeroot.update()
event.preventDefault()
}
_dbclick(event)
{
if(istoggle)
{
istoggle = false
return
}
data = {
id:self.rid,
data:event.item,
path: self.path}
if(self.ontreedbclick)
{
self.ontreedbclick(data)
}
self.root.observable.trigger('treedbclick', data)
}
</script>
</afx-tree-view>

View File

@ -1,4 +1,4 @@
<afx-vbox>
<afx-vbox style = "display:block;">
<div ref = "container" class="afx-vbox-container">
<yield/>
</div>
@ -23,8 +23,8 @@
{
var auto_width = []
var csize, ocwidth = 0, avaiheight;
avaiheight = $(self.root).parent().height()
avaiWidth = $(self.root).parent().width()
avaiheight = $(self.root).height()
avaiWidth = $(self.root).width()
$(self.refs.container).css("height",avaiheight + "px")
$(self.refs.container)
.children()