add afx-label and afx-switch

This commit is contained in:
Xuan Sang LE 2017-08-26 16:50:13 +02:00
parent 2284f50523
commit 4cf1d694f9
39 changed files with 898 additions and 239 deletions

View File

@ -6,7 +6,7 @@ NC=\033[0m
coffees= src/core/core.coffee\
src/core/api.coffee\
src/core/handlers/InBrowserHandler.coffee\
src/core/handlers/TestHandler.coffee\
src/core/gui.coffee\
src/core/BaseModel.coffee\
src/core/BaseApplication.coffee\
@ -30,7 +30,7 @@ lite: build_coffee build_tag build_theme schemes build_services build_packages
# coffee --compile $<
build_coffees:
@echo "$(BLUE)=======Building coffee files=======$(NC)"
@echo "$(BLUE)Building coffee files$(NC)"
- mkdir $(BUILDDIR)/scripts
- rm $(BUILDDIR)/scripts/antos.js
for f in $(coffees); do (cat "$${f}"; echo) >> $(BUILDDIR)/scripts/antos.coffee; done
@ -39,16 +39,20 @@ build_coffees:
libs:
@echo "$(BLUE)=======Copy lib files=======$(NC)"
@echo "$(BLUE)Copy lib files$(NC)"
cp -rf src/libs/* $(BUILDDIR)/scripts/
schemes:
@echo "$(BLUE)=======Copy schemes files======= $(NC)"
@echo "$(BLUE)Copy schemes files$(NC)"
- mkdir -p $(BUILDDIR)/resources/schemes
cp src/core/schemes/* $(BUILDDIR)/resources/schemes/
testdata:
@echo "$(BLUE)Copy JSON test files$(NC)"
- mkdir -p $(BUILDDIR)/resources/jsons
cp src/core/handlers/jsons/* $(BUILDDIR)/resources/jsons
build_tags:
@echo "=======$(BLUE)Building tag files=======$(NC)"
@echo "$(BLUE)Building tag files$(NC)"
-mkdir $(BUILDDIR)/resources
-rm $(BUILDDIR)/resources/antos_tags.js
for f in src/core/tags/*; do (cat "$${f}"; echo) >> $(BUILDDIR)/resources/antos_tags.js; done
@ -57,7 +61,7 @@ build_themes: antos_themes_build
antos_themes_build:
@echo "=======$(BLUE)Building themes name: antos=======$(NC)"
@echo "$(BLUE)Building themes name: antos$(NC)"
-rm -rf $(BUILDDIR)/resources/themes/antos/*
-mkdir -p $(BUILDDIR)/resources/themes/antos
for f in src/themes/antos/*.css; do (cat "$${f}"; echo) >> $(BUILDDIR)/resources/themes/antos/antos.css;done
@ -67,7 +71,7 @@ antos_themes_build:
build_services:
@echo "=======$(BLUE)Building services=======$(NC)"
@echo "$(BLUE)Building services$(NC)"
-mkdir -p $(BUILDDIR)/services
-rm -rf $(BUILDDIR)/services/*
for f in $(services); do (coffee -cs < "src/services/$$f.coffee" >$(BUILDDIR)/services/"$$f.js");done

View File

@ -20,7 +20,7 @@ class BaseApplication extends this.OS.GUI.BaseModel
me.dialog.hide() if me.dialog
@on "menuselect", (d) ->
switch d.e.item.data.dataid
when "#{me.name}-about" then alert "About " + me.pid + me.name
when "#{me.name}-about" then me.openDialog "AboutDialog", ()->
when "#{me.name}-exit" then me.trigger "exit"
#now load the scheme
path = "packages/#{@name}/scheme.html"

View File

@ -12,6 +12,8 @@ class BaseDialog extends this.OS.GUI.BaseModel
@parent.dialog = undefined if @parent
($ @scheme).remove() if @scheme
@dialog.quit() if @dialog
init: () ->
main: () ->
meta: () ->
@parent.meta()
show: () ->
@ -40,7 +42,9 @@ this.OS.GUI.BaseDialog = BaseDialog
class BasicDialog extends BaseDialog
constructor: ( name, @conf ) ->
super name
html = "<afx-app-window data-id = 'dia-window' apptitle='#{name}' width='#{@conf.width}' height='#{@conf.height}'>
init: () ->
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;'>"
@ -109,4 +113,24 @@ class ColorPickerDialog extends BasicDialog
}
]
}
this.OS.register "ColorPickerDialog", ColorPickerDialog
this.OS.register "ColorPickerDialog", ColorPickerDialog
class AboutDialog extends BaseDialog
constructor: () ->
super "AboutDialog"
init: () ->
@render "resources/schemes/about.html"
main: () ->
mt = @meta()
@scheme.set "apptitle", "About: #{mt.name}"
(@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
(@find "mygrid").set "rows", rows
this.OS.register "AboutDialog", AboutDialog

View File

@ -22,6 +22,7 @@ class BaseModel
#implement by sub class
onexit: (e) ->
#implement by subclass
one: (e, f) -> @observable.one e, f
on: (e, f) -> @observable.on e, f
trigger: (e, d) -> @observable.trigger e, d
@ -39,6 +40,7 @@ class BaseModel
@dialog.parent = @
@dialog.handler = f
@dialog.pid = @pid
@dialog.init()
publish: (t, m) ->
mt = @meta()

View File

@ -1,22 +1,56 @@
self.OS.API =
self.OS.API =
# the handler object could be a any remote or local handle to
# fetch user data, used by the API to make requests
# handlers are defined in /src/handlers
handler: new Object()
handler: {}
VFS:
scandir: (p, c, f) ->
_API.handler.request "scandir", { path: p }, c, f
#request a user data
request: (query, callback) ->
# definition here
handle.request query, callback
post: (p, d, c, f) ->
q = _courrier.getMID()
_API.loading q, p
$.ajax {
type: "POST",
url: p,
data: d,
success: null,
dataType: 'json'
}
.done (data) ->
_API.loaded q, p, "OK"
c(data)
.fail (e, s) ->
_API.loaded q, p, "FAIL"
f(e, s)
systemConfig: ->
_API.request 'config', (result) ->
console.log result
loading: (q, p) ->
_courrier.trigger "loading", { id: q, data: { m: "#{p}", s: true }, name: "OS" }
loaded: (q, p, m ) ->
_courrier.trigger "loaded", { id: q, data: { m: "#{m}: #{p}", s: false }, name: "OS" }
get: (p, c, f) ->
q = _courrier.getMID()
_API.loading q, p
$.get p
.done (data) -> c(data)
.fail -> f()
.done (data) ->
_API.loaded q, p, "OK"
c(data)
.fail (e, s) ->
_API.loaded q, p, "FAIL"
f(e, s)
script: (p, c, f) ->
q = _courrier.getMID()
_API.loading q, p
$.getScript p
.done (data) ->
_API.loaded q, p, "OK"
c(data)
.fail (e, s) ->
_API.loaded q, p, "FAIL"
f(e, s)
resource: (resource, callback) ->
path = "resources/#{resource}"
_API.get path, callback

View File

@ -8,6 +8,7 @@ self.OS or=
courrier:
observable: riot.observable()
quota: 0
listeners: new Object
on: (e, f, a) ->
_courrier.listeners[a.pid] = [] unless _courrier.listeners[a.pid]
@ -19,6 +20,9 @@ self.OS or=
_courrier.observable.off i.e, i.f for i in _courrier.listeners[app.pid]
delete _courrier.listeners[app.pid]
_courrier.listeners[app.pid] = []
getMID: () ->
_courrier.quota += 1
_courrier.quota
register: (name, x) ->
if x.type is 3 then self.OS.GUI.dialog[name] = x else _APP[name] = x

View File

@ -17,13 +17,12 @@ self.OS.GUI =
(x) ->
return null unless x
_GUI.htmlToScheme x, app, parent
, (f) ->
, (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"
}
alert "cannot load scheme"
loadTheme: (name) ->
path = "resources/themes/#{name}/#{name}.css"
@ -40,10 +39,10 @@ self.OS.GUI =
pushService: (srv) ->
return _PM.createProcess srv, _APP[srv] if _APP[srv]
path = "services/#{srv}.js"
$.getScript path
.done (e, s) ->
_API.script path,
(d) ->
_PM.createProcess srv, _APP[srv]
.fail (e, s) ->
, (e, s) ->
_courrier.trigger "srvroutineready", srv
_courrier.trigger "fail",
{ id:0,data:{m: "Cannot read service script: #{srv} ", e: e, s: s },
@ -53,12 +52,14 @@ self.OS.GUI =
if not _APP[app]
# first load it
path = "packages/#{app}/"
$.getScript path + "main.js"
.done (e, s) ->
_API.script path + "main.js",
(d) ->
#load css file
$.get "#{path}main.css", () ->
$ '<link>', { rel: 'stylesheet', type: 'text/css', 'href': "#{path}main.css" }
.appendTo 'head'
_API.get "#{path}main.css",
() ->
$ '<link>', { rel: 'stylesheet', type: 'text/css', 'href': "#{path}main.css" }
.appendTo 'head'
, () ->
#launch
if _APP[app]
# load app meta data
@ -66,12 +67,11 @@ self.OS.GUI =
(data) ->
_APP[app].meta = data
_PM.createProcess app, _APP[app]
console.log "Fist time loading " + app
, (e, s) ->
_courrier.trigger "fail",
{id:0, data:{ m: "Cannot read application metadata: #{app} ",e: e, s: s }, name:"OS"}
alert "cannot read application, meta-data"
.fail (e,s) ->
, (e, s) ->
#BUG report here
_courrier.trigger "fail",
{id :0, data:{m: "Cannot load application script: #{app}",
@ -81,23 +81,24 @@ self.OS.GUI =
# now launch it
if _APP[app]
_PM.createProcess app, _APP[app]
dock: (app,meta) ->
dock: (app, meta) ->
# dock an application to a dock
# create a data object
data =
icon: null
iconclass: meta.iconclass || ""
app:app
onbtclick: () ->
app.toggle()
app: app
onbtclick: () -> app.toggle()
data.icon = "packages/#{meta.app}/#{meta.icon}" if meta.icon
# TODO: add default app icon class in system setting
# so that it can be themed
data.iconclass = "fa fa-cogs" if (not meta.icon) and (not meta.iconclass)
dock = $ "#sysdock"
dock.get(0).newapp data
app.sysdock = dock.get(0)
app.appmenu = ($ "[data-id = 'appmenu']", "#syspanel")[0]
app.one "rendered", () ->
dock.get(0).newapp data
app.sysdock = dock.get(0)
app.appmenu = ($ "[data-id = 'appmenu']", "#syspanel")[0]
app.init()
#app.show() -- notwork, sice the scheme is not loaded yet
undock: (app) ->
($ "#sysdock").get(0).removeapp app
@ -112,7 +113,6 @@ self.OS.GUI =
if e.contextmenuHandler
e.contextmenuHandler event, ($ "#contextmenu")[0]
else
#console.log ($ "#workspace").get(0), ($ e).parent().get(0)
p = $(e).parent().get(0)
handler p if p isnt ($ "#workspace").get(0)
handler event.target

View File

@ -1,3 +0,0 @@
self.OS.API.handler =
request: ( query ) ->
$.ajax {}

View File

@ -0,0 +1,8 @@
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

View File

@ -0,0 +1,324 @@
{
"result": [
{
"permissions": " (755)",
"type": "dir",
"mtime": "2017-07-23T22:53:10",
"size": 102,
"path": "home:////.desktop",
"ctime": "2017-07-23T22:53:10",
"filename": ".desktop",
"perm": {
"owner": {
"write": true,
"read": true,
"exec": true
},
"group": {
"write": false,
"read": true,
"exec": true
},
"other": {
"write": false,
"read": true,
"exec": true
}
},
"mime": "",
"uid": 501,
"gid": 20
},
{
"permissions": " (644)",
"type": "file",
"mtime": "2017-07-23T22:51:57",
"size": 6148,
"path": "home:////.DS_Store",
"ctime": "2017-07-23T22:51:57",
"filename": ".DS_Store",
"perm": {
"owner": {
"write": true,
"read": true,
"exec": false
},
"group": {
"write": false,
"read": true,
"exec": false
},
"other": {
"write": false,
"read": true,
"exec": false
}
},
"mime": "application/octet-stream",
"uid": 501,
"gid": 20
},
{
"permissions": " (755)",
"type": "dir",
"mtime": "2017-07-23T21:45:59",
"size": 68,
"path": "home:////.packages",
"ctime": "2017-07-23T21:45:59",
"filename": ".packages",
"perm": {
"owner": {
"write": true,
"read": true,
"exec": true
},
"group": {
"write": false,
"read": true,
"exec": true
},
"other": {
"write": false,
"read": true,
"exec": true
}
},
"mime": "",
"uid": 501,
"gid": 20
},
{
"permissions": " (644)",
"type": "file",
"mtime": "2017-07-30T00:55:34",
"size": 2821,
"path": "home:////.settings.json",
"ctime": "2017-07-30T00:55:34",
"filename": ".settings.json",
"perm": {
"owner": {
"write": true,
"read": true,
"exec": false
},
"group": {
"write": false,
"read": true,
"exec": false
},
"other": {
"write": false,
"read": true,
"exec": false
}
},
"mime": "application/json",
"uid": 501,
"gid": 20
},
{
"permissions": " (644)",
"type": "file",
"mtime": "2017-07-11T20:30:51",
"size": 575,
"path": "home:////helloworld.xml",
"ctime": "2017-07-11T20:30:51",
"filename": "helloworld.xml",
"perm": {
"owner": {
"write": true,
"read": true,
"exec": false
},
"group": {
"write": false,
"read": true,
"exec": false
},
"other": {
"write": false,
"read": true,
"exec": false
}
},
"mime": "application/xml",
"uid": 501,
"gid": 20
},
{
"permissions": " (644)",
"type": "file",
"mtime": "2017-05-15T14:47:59",
"size": 4420074,
"path": "home:////Last Reunion - Peter Roe.mp3",
"ctime": "2017-07-11T21:27:28",
"filename": "Last Reunion - Peter Roe.mp3",
"perm": {
"owner": {
"write": true,
"read": true,
"exec": false
},
"group": {
"write": false,
"read": true,
"exec": false
},
"other": {
"write": false,
"read": true,
"exec": false
}
},
"mime": "audio/mpeg",
"uid": 501,
"gid": 20
},
{
"permissions": " (644)",
"type": "file",
"mtime": "2016-05-07T15:45:47",
"size": 3409596,
"path": "home:////Nobody Home.mp3",
"ctime": "2017-07-11T21:33:26",
"filename": "Nobody Home.mp3",
"perm": {
"owner": {
"write": true,
"read": true,
"exec": false
},
"group": {
"write": false,
"read": true,
"exec": false
},
"other": {
"write": false,
"read": true,
"exec": false
}
},
"mime": "audio/mpeg",
"uid": 501,
"gid": 20
},
{
"permissions": " (644)",
"type": "file",
"mtime": "2014-03-28T18:15:53",
"size": 1953,
"path": "home:////opencvcurl.cpp",
"ctime": "2017-07-23T13:39:31",
"filename": "opencvcurl.cpp",
"perm": {
"owner": {
"write": true,
"read": true,
"exec": false
},
"group": {
"write": false,
"read": true,
"exec": false
},
"other": {
"write": false,
"read": true,
"exec": false
}
},
"mime": "text/cpp",
"uid": 501,
"gid": 20
},
{
"permissions": " (755)",
"type": "dir",
"mtime": "2017-07-11T20:27:40",
"size": 68,
"path": "home:////Public",
"ctime": "2017-07-11T20:27:40",
"filename": "Public",
"perm": {
"owner": {
"write": true,
"read": true,
"exec": true
},
"group": {
"write": false,
"read": true,
"exec": true
},
"other": {
"write": false,
"read": true,
"exec": true
}
},
"mime": "",
"uid": 501,
"gid": 20
},
{
"permissions": " (644)",
"type": "file",
"mtime": "2017-07-11T20:31:04",
"size": 69,
"path": "home:////test.lua",
"ctime": "2017-07-11T20:31:04",
"filename": "test.lua",
"perm": {
"owner": {
"write": true,
"read": true,
"exec": false
},
"group": {
"write": false,
"read": true,
"exec": false
},
"other": {
"write": false,
"read": true,
"exec": false
}
},
"mime": "text/lua",
"uid": 501,
"gid": 20
},
{
"permissions": " (644)",
"type": "file",
"mtime": "2016-08-01T14:54:34",
"size": 3974373,
"path": "home:////The sound of silence.mp3",
"ctime": "2017-07-11T20:29:04",
"filename": "The sound of silence.mp3",
"perm": {
"owner": {
"write": true,
"read": true,
"exec": false
},
"group": {
"write": false,
"read": true,
"exec": false
},
"other": {
"write": false,
"read": true,
"exec": false
}
},
"mime": "audio/mpeg",
"uid": 501,
"gid": 20
}
],
"error": false
}

View File

@ -0,0 +1,11 @@
<afx-app-window data-id = 'about-window' width='300' height='200'>
<afx-hbox>
<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>
</afx-app-window>

View File

@ -29,16 +29,30 @@
}
</style>
</afx-overlay>
<afx-feed data-id = "notifeed" style = "display: none;">
<!--afx-button text = "click me"></afx-button-->
<afx-overlay data-id = "feedzone" width = "250">
<afx-list-view data-id = "notifeed">
</afx-list-view>
<style>
afx-feed[data-id = "notifeed"]{
position: absolute;
width: 250px;
afx-overlay[data-id = "feedzone"]{
overflow: hidden;
background-color:transparent;
right:5px;
margin: 0;
padding:0;
top:0;
}
afx-feed[data-id = "notifeed"] > div{
afx-list-view[data-id = "notifeed"]
{
padding:0;
margin:0;
}
afx-list-view[data-id = "notifeed"] li{
box-shadow: 1px 1px 1px #9f9F9F;
border:1px solid #a6a6a6;
border-radius: 6px;
margin-bottom: 2px;
z-index: 99999;
}
</style>
</afx-feed>
</afx-overlay>
</afx-dummy>

View File

@ -1,13 +1,12 @@
<afx-button>
<button disabled={ enable == "false" } onclick="{ _onbtclick }" >
<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>
{ opts.text }
<afx-label icon={icon} iconclass = {iconclass} text = {text} ></afx-label>
</button>
<script>
this.enable = opts.enable
this.icon = opts.icon
this.iconclass = opts.iconclass
this.text = opts.text || ""
var self = this
this.onbtclick = opts.onbtclick
self.root.set = function(k,v)

View File

@ -1,6 +1,6 @@
<afx-calendar-view>
<div><i class ="prevmonth" onclick={prevmonth}></i>{text}<i onclick={nextmonth} class="nextmonth"></i></div>
<afx-grid-view data-id ={"grid_" + rid} style = "height:100%;" ref = "grid" header = {header} observable = {root.observable}> </afx-grid-view>
<afx-grid-view data-id ={"grid_" + rid} style = "height:100%;" ref = "grid" header = {header}> </afx-grid-view>
<script >
this.header = [{value:"Sun"},{value:"Mon"},{value:"Tue"},{value:"Wed"},{value:"Thu"},{value:"Fri"},{value:"Sat"}]

View File

@ -1,49 +0,0 @@
<afx-feed>
<div each = {items}>
<p>
<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>
{header}
<i if={closable} class = "closable"></i>
</p>
<div>
<p>{text}</p>
<yield/>
</div>
</div>
<script>
var self = this
self.items = opts.items || []
self.root.set = function(k,v)
{
if(k == "*")
for(var i in v)
self[i] = v[i]
else
self[k] = v
self.update()
}
self.root.push = function(i,u)
{
self.items.push(i)
if(u) self.update()
}
self.root.remove = function(e,u)
{
var i = self.items.indexOf(e)
if(i >= 0)
self.items.splice(i, 1)
if(u)
self.update()
}
self.root.unshift = function(i,u)
{
self.items.unshift(i)
if(u) self.update()
}
self.root.get = function(k)
{
return self[k]
}
</script>
</afx-feed>

View File

@ -1,13 +1,18 @@
<afx-file-view>
<afx-list-view if = {view == 'icon'} child = {data.items}></afx-list-view>
<afx-grid-view if = {view == 'list'} header = {data.header} rows = {data.items}></afx-grid-view>
<afx-tree-view if = {view == 'tree'}></afx-tree-view>
<afx-list-view if = {view == 'icon'} ref="listview" observable = {root.observable}></afx-list-view>
<afx-grid-view if = {view == 'list'} ref = "gridview" header = {header} observable = {root.observable}></afx-grid-view>
<afx-tree-view if = {view == 'tree'} ref = "treeview" observable = {root.observable}></afx-tree-view>
<div if = {status == true} class = "status" ref = "stbar"></div>
<script>
var self = this
self.root.observable = opts.observable
self.view = opts.view || 'icon'
self.data = opts.data
self.root.observable = opts.observable || riot.observable()
self.view = opts.view || 'list'
self.data = opts.data || []
self.onfileselect
this.status = opts.status == undefined?true:opts.status
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}]
self.root.set = function(k,v)
{
if(k == "*")
@ -21,5 +26,80 @@
{
return self[k]
}
var sortByType = function(a,b)
{
return a.type < b.type ? -1 : ( a.type > b.type ? 1: 0 )
}
var calibre_size = function()
{
var h = $(self.root).height()
if(self.refs.stbar)
h -= $(self.refs.stbar).height()
if(self.refs.listview)
$(self.refs.listview.root).css("height", h + "px")
else if(self.refs.gridview)
$(self.refs.gridview.root).css("height", h + "px")
else if(self.refs.treeview)
$(self.refs.treeview.root).css("height", h + "px")
}
var refreshList = function(){
$.each(self.data, function(i, v){
v.text = v.filename
if(v.text.length > 10)
v.text = v.text.substring(0,9) + "..."
if(v.type == 'file')
v.iconclass = 'afx-file'
else
v.iconclass = 'afx-dir'
})
self.refs.listview.root.set("items", self.data)
}
var refreshGrid = function(){
var rows = []
$.each(self.data, function(i,v){
var row = [{value:v.filename, iconclass: v.type == "dir"?"afx-dir":"afx-file" },{value:v.mime},{value:v.size}]
rows.push(row)
})
self.refs.gridview.root.set("rows",rows)
}
var refreshData = function(){
self.data.sort(sortByType)
if(self.refs.listview)
refreshList()
else if(self.refs.gridview)
refreshGrid()
}
self.on("updated", function(){
refreshData()
calibre_size()
})
self.on("mount", function(){
if(self.refs.listview)
{
self.refs.listview.onlistselect = function(data)
{
data.id = self.rid
self.root.observable.trigger("fileselect",data)
}
}
if(self.refs.gridview)
{
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.root.observable.on("fileselect", function(e){
if(e.id != self.rid) return
$(self.refs.stbar).html("Selected: " + e.data.filename + " (" + e.data.size + " bytes)")
})
calibre_size()
self.root.observable.on("resize", function(e){
calibre_size()
})
})
</script>
</afx-file-view>

View File

@ -1,5 +1,5 @@
<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>
<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>
@ -12,6 +12,8 @@
this.rid = $(self.root).attr("data-id") || Math.floor(Math.random() * 100000) + 1
self.selidx = -1
self.nrow = 0
self.ongridselect = opts.ongridselect
self.root.observable = opts.observable
self.root.set = function(k,v)
{
if(k == "selected")
@ -43,16 +45,16 @@
return self[k]
}
this.root.observable = opts.observable || riot.observable()
this.on("mount", function(){
if(self.refs.gridhead)
self.refs.gridhead.observable = self.root.observable
$(self.refs.container)
.css("display","table")
//.css("flex-direction","column")
.css("width","100%")
self.calibrate_size()
this.root.observable.on("resize",function(){
self.root.observable.on("resize",function(){
self.calibrate_size()
})
})
@ -68,13 +70,13 @@
var data = {
id:self.rid,
data:event.item}
if(opts.onlistselect)
opts.onlistselect(data)
if(self.ongridselect)
self.ongridselect(data)
if(self.selidx != -1)
self.rows[self.selidx].selected =false
self.selidx = event.item.i
self.rows[self.selidx].selected = true
this.root.observable.trigger('gridselect',data)
self.root.observable.trigger('gridselect',data)
event.preventUpdate = true
self.update()
//event.preventDefault()
@ -85,18 +87,16 @@
<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)} >
<i if={child.iconclass} class = {child.iconclass} ></i>
<i if={child.icon} class="icon-style" style = { "background: url("+child.icon+");background-size: 100% 100%;background-repeat: no-repeat;" }></i>
{child.value}
<afx-label icon = {child.icon} iconclass = {child.iconclass} text = {child.value} ></afx-label>
</div>
<script>
this.cols = opts.cols || []
var self = this
this.rid = opts.rootid
this.index = opts.index
this.header = opts.header||false
this.header = eval(opts.header)||false
this.head = opts.head
this.selidx = -1;
this.selidx = -1
self.observable = opts.observable
this.colssize = []
var update_header_size = function()
@ -174,6 +174,9 @@
self.selidx = -1
}
})
self.observable.on("resize",function(){
self.update()
})
})
_cell_select(event)
{

View File

@ -0,0 +1,31 @@
<afx-label>
<span>
<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 }
</span>
<script>
this.iconclass = opts.iconclass
this.icon = opts.icon
this.text = opts.text
var self = this
this.on("update",function(){
self.iconclass = opts.iconclass
self.icon = opts.icon
self.text = opts.text
})
self.root.set = function(k,v)
{
if(k == "*")
for(var i in v)
opts[i] = v[i]
else
opts[k] = v
self.update()
}
self.root.get = function(k)
{
return self[k]
}
</script>
</afx-label>

View File

@ -4,19 +4,18 @@
</div>
<ul ref = "mlist">
<li each={item,i in items } class={selected: parent._autoselect(item,i)} onclick = {parent._select}>
<i if={item.iconclass} class = {item.iconclass} ></i>
<i if={item.icon} class="icon-style" style = { "background: url("+item.icon+");background-size: 100% 100%;background-repeat: no-repeat;" }></i>
{ item.text }
<afx-label iconclass = {item.iconclass} icon = {item.icon} text = {item.text}></afx-label>
<i if = {item.closable} class = "closable" click = {parent._remove}></i>
</li>
</ul>
</div>
<script>
this.items = opts.child || []
this.items = opts.items || []
var self = this
self.selidx = -1
self.onlistselect = opts.onlistselect
var onclose = false
this.rid = $(self.root).attr("data-id") || Math.floor(Math.random() * 100000) + 1
self.root.set = function(k,v)
{
if(k == "selected")
@ -48,6 +47,22 @@
self.items.unshift(e)
if(u) self.update()
}
self.root.remove = function(e,u)
{
var i = self.items.indexOf(e)
if(i >= 0)
{
if(self.selidx != -1)
{
self.items[self.selidx].selected =false
self.selidx = -1
}
self.items.splice(i, 1)
if(u)
self.update()
onclose = true
}
}
if(opts.observable)
this.root.observable = opts.observable
else
@ -89,20 +104,13 @@
}
_remove(event)
{
if(self.selidx != -1)
{
self.items[self.selidx].selected =false
self.selidx = -1
}
self.items.splice(self.items.indexOf(event.item),1)
self.update()
onclose = true
self.root.remove(event.item.item, true)
}
_autoselect(it,i)
{
if(!it.selected || it.selected == false) return false
var data = {
id:$(self.root).attr("data-id"),
id:self.rid,
data:it,
idx:i}
//if(self.selidx != -1)

View File

@ -3,9 +3,7 @@
<li class="afx-corner-fix"></li>
<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}>
<i if={data.iconclass} class = {data.iconclass} ></i>
<i if={data.icon} class="icon-style" style = { "background: url("+data.icon+");background-size: 100% 100%;background-repeat: no-repeat;" }></i>
{ data.text }
<afx-label 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>
@ -126,7 +124,7 @@
onselect(event)
{
var data = {id:self.rid, root:isRoot, e:event}
var data = {id:self.rid, root:isRoot, e:event, item:event.item}
this.root.observable.trigger('menuselect',data)
if( this.onmenuselect && !isRoot) this.onmenuselect(data)
event.preventDefault()

View File

@ -0,0 +1,43 @@
<afx-switch>
<span class = {swon: swon} onclick = {toggle}></span>
<script>
this.swon = opts.swon || false
var self = this
this.root.observable = opts.observable
this.onchange = opts.onchange
this.rid = $(self.root).attr("data-id") || Math.floor(Math.random() * 100000) + 1
console.log(this.swon)
self.root.set = function(k,v)
{
if(k == "*")
for(var i in v)
self[i] = v[i]
else
self[k] = v
self.update()
}
self.root.get = function(k)
{
return self[k]
}
this.root.toggle = function()
{
self.swon = !self.swon
self.update()
}
toggle(e)
{
self.swon = !self.swon
var data = {
id: self.rid,
data: self.swon
}
if(self.onchange)
self.onchange(data)
if(self.root.observable)
self.root.observable.trigger("switch", data)
}
</script>
</afx-switch>

View File

@ -14,7 +14,8 @@
{text:"wTerm",type:"app"},
{text:"NotePad",type:"app", iconclass:"fa fa-commenting"},
{text:"ActivityMonitor",type:"app"},
{text:"DummyApp",type:"app"}
{text:"DummyApp",type:"app"},
{text:"Files",type:"app"}
],
onmenuselect: function(d)
{

View File

@ -2,10 +2,11 @@
"app":"ActivityMonitor",
"name":"Activity monitor",
"description":"Processes monitor and manager",
"author":{
"name": "Xuan Sang LE",
"info":{
"author": "Xuan Sang LE",
"email": "xsang.le@gmail.com"
},
"version":"0.1a",
"category":"System",
"iconclass":"fa fa-heartbeat",
"mimes":["*"]

View File

@ -2,10 +2,13 @@
"app":"DummyApp",
"name":"DummyApp",
"description":"App for test",
"author":{
"name": "Xuan Sang LE",
"email": "xsang.le@gmail.com"
"info":{
"author": "Xuan Sang LE",
"email": "xsang.le@gmail.com",
"credit": "dedicated to some one here",
"licences": "MIT"
},
"version":"0.1a",
"category":"System",
"iconclass":"fa fa-user-circle-o",
"mimes":["*"]

View File

@ -2,8 +2,8 @@
<afx-vbox>
<afx-tree-view data-id="mytree"> </afx-tree-view>
<afx-hbox>
<afx-button data-height="40" text="Read more" iconclass="fa fa-camera-retro fa-lg" id="button">
</afx-button>
<afx-button data-height="30" text="Read more" iconclass="fa fa-camera-retro fa-lg" id="button"></afx-button>
<afx-switch data-height="30"></afx-switch>
<afx-calendar-view></afx-calendar-view>
<afx-color-picker></afx-color-picker>
<afx-list-view data-id = "mylist" dropdown = "true" width="200" data-height = "40"></afx-list-view>

View File

@ -1,4 +1,3 @@
_GUI = this.OS.GUI
class Files extends this.OS.GUI.BaseApplication
constructor: () ->
super "Files"
@ -10,8 +9,52 @@ class Files extends this.OS.GUI.BaseApplication
mdata = [ { text: " Child 1" }, { text: "child2", child: [{text: "sub child", child:[{text:"sub sub child"}] }]}]
m.set "items", mdata
m.show(e)
@on "fileselect", (d) -> console.log d
#load home directory
@_api.VFS.scandir 'home:///',
(d) ->
me.view.set "data", d.result
, (e, s) ->
alert "cannot open dir"
samples: () ->
menu: () ->
me = @
menu = [
{
text: "File",
child: [
{ text: "New file", dataid: "#{@name}-mkf" },
{ text: "New folder", dataid: "#{@name}-mkdir" },
{ text: "Upload", dataid: "#{@name}-upload" }
]
},
{
text: "Edit",
child: [
{ text: "Rename", dataid: "#{@name}-mv" },
{ text: "Delete", dataid: "#{@name}-rm" },
{ text: "Information", dataid: "#{@name}-info" },
{ text: "Open with", dataid: "#{@name}-open" },
{ text: "Download", dataid: "#{@name}-download" },
]
},
{
text: "View",
child: [
{ text: "Refresh", dataid: "#{@name}-refresh" },
{ text: "Sidebar", dataid: "#{@name}-side" },
{ text: "Navigation bar", dataid: "#{@name}-nav" },
{ text: "Hidden files", dataid: "#{@name}-hidden" },
{ text: "Type", child: [
{ text: "Icon view", dataid: "#{@name}-icon", type: 'icon' },
{ text: "List view", dataid: "#{@name}-list", type: 'list' },
{ text: "Tree view", dataid: "#{@name}-tree", type: 'tree' }
], onmenuselect: (e) ->
me.view.set 'view', e.item.data.type
},
]
},
]
menu
this.OS.register "Files",Files

View File

@ -2,11 +2,12 @@
"app":"Files",
"name":"Files manager",
"description":"System files manager",
"author":{
"name": "Xuan Sang LE",
"info":{
"author": "Xuan Sang LE",
"email": "xsang.le@gmail.com"
},
"version":"0.1a",
"category":"System",
"iconclass":"fa fa-archive",
"iconclass":"fa fa-hdd-o",
"mimes":["*"]
}

View File

@ -1,4 +1,4 @@
<afx-app-window apptitle="Preview" width="600" height="400">
<afx-app-window apptitle="Files" width="600" height="400">
<afx-vbox>
<afx-file-view data-id = "fileview"></afx-file-view>
</afx-vbox>

View File

@ -2,10 +2,11 @@
"app":"NotePad",
"name":"NotePad editor",
"description":"Basic application for text editing",
"author":{
"name": "Xuan Sang LE",
"info":{
"author": "Xuan Sang LE",
"email": "xsang.le@gmail.com"
},
"version":"0.1a",
"category":"System",
"iconclass":"fa fa-pencil-square-o",
"mimes":["*"]

View File

@ -2,10 +2,11 @@
"app":"wTerm",
"name":"Unix terminal like",
"description":"Access Unix terminal from web",
"author":{
"name": "Xuan Sang LE",
"info":{
"author": "Xuan Sang LE",
"email": "xsang.le@gmail.com"
},
"version":"0.1a",
"category":"System",
"iconclass":"fa fa-terminal",
"mimes":["*"]

View File

@ -12,9 +12,9 @@ class Calendar extends this.OS.GUI.BaseService
me.text = "#{now.getDate()}/#{(now.getMonth()+1)}/#{now.getFullYear()} " +
"#{now.getHours()}:#{now.getMinutes()}:#{now.getSeconds()}"
me.update()
awake: (e) ->
@.openDialog "CalendarDialog", (d) ->
@.openDialog "CalendarDialog", (d) -> console.log d
# do nothing
cleanup: (evt) ->
console.log "cleanup for quit"

View File

@ -1,33 +1,55 @@
class PushNotification extends this.OS.GUI.BaseService
constructor: () ->
super "PushNotification"
@iconclass = "fa fa-commenting"
@iconclass = "fa fa-bars"
@onmenuselect = (e) -> console.log e
@cb = undefined
@pending = []
init: ->
@view = false
path = "resources/schemes/notifications.html"
@render path
spin: (b) ->
if b and @iconclass is "fa fa-bars"
@iconclass = "fa fa-spinner fa-spin"
@update()
else if not b and @iconclass is "fa fa-spinner fa-spin"
@iconclass = "fa fa-bars"
@update()
main: ->
me = @
@mlist = @find "notifylist"
@mfeed = @find "notifeed"
@nzone = @find "notifyzone"
@fzone = @find "feedzone"
(@find "btclear").set "onbtclick", (e) -> me.mlist.set "items", []
#mlist.set "onlistselect", (e) -> console.log e
@subscribe "notification", (o) -> me.pushout 'INFO', o
@subscribe "fail", (o) -> me.pushout 'FAIL', o
@subscribe "error", (o) -> me.pushout 'ERROR', o
@subscribe "loading", (o) ->
me.pending.push o.id
me.spin true
@subscribe "loaded", (o) ->
i = me.pending.indexOf o.id
me.pending.splice i, 1 if i >= 0
me.spin false if me.pending.length is 0
($ @nzone).css "right", 0
.css "top", "-3px"
.css "height", ""
.css "bottom", "0"
.css "z-index", 1000000
.hide()
($ @fzone)
#.css("z-index", 99999)
.css("bottom", "0")
.css("height", "")
.hide()
($ @mfeed).css "right", "5px"
.css "top", "0"
pushout: (s, o, mfeed) ->
d = {
@ -35,19 +57,13 @@ class PushNotification extends this.OS.GUI.BaseService
icon: o.data.icon,
iconclass: o.data.iconclass,
closable: true }
d1 = {
header: "#{o.name} (#{o.id})"
text: "#{s}: #{o.data.m}",
icon: o.data.icon,
iconclass: o.data.iconclass,
closable: true }
@mlist.push d, true
@notifeed d1
@mlist.unshift d, true
@notifeed d
notifeed: (d) ->
me = @
@mfeed.push d, true
($ @mfeed).show()
@mfeed.unshift d, true
($ @fzone).show()
timer = setTimeout () ->
me.mfeed.remove d, true
clearTimeout timer
@ -59,7 +75,7 @@ class PushNotification extends this.OS.GUI.BaseService
me = @
if not @cb
@cb = (e) ->
return if e.originalEvent.item and e.originalEvent.item.closable
return if e.originalEvent.item and e.originalEvent.item.i isnt undefined
if not ($ e.target).closest($ me.nzone).length and not ($ e.target).closest($ me.holder.root).length
($ me.nzone).hide()
$(document).unbind "click", me.cb

View File

@ -1,44 +0,0 @@
afx-feed {
width: 100%;
}
afx-feed > div{
border:1px solid #a6a6a6;
border-radius: 6px;
background-color: #e9e9e9;
}
afx-feed > div > p{
padding:2px;
padding-top: 0;
padding-left: 5px;
margin: 0;
font-weight: bold;
border-bottom: 1px solid #a6a6a6;
position: relative;
}
afx-feed i.closable{
width: 16px;
height: 16px;
display: inline-block;
cursor: pointer;
}
afx-feed i.closable:before{
content: "\f00d";
font-family: "FontAwesome";
font-size: 10px;
right:5px;
color: #414339;
position:absolute;
font-style: normal;
top:5px;
}
afx-feed > div > div{
background-color: white;
padding:5px;
border-radius: 6px;
}
afx-feed > div > div > p{
padding:0;
margin: 0;
}

View File

@ -0,0 +1,87 @@
afx-file-view {
position: relative;
}
afx-file-view div.status{
position: absolute;
bottom: 0px;
left:0px;
padding:3px;
right: 0px;
height: 15px;
background-color: #dfdfdf;
border-top: 1px solid #a6A6a6;
}
afx-file-view afx-list-view li{
float:left;
display: block;
width:70px;
height: 60px;
background-color: transparent;
text-align: center;
padding:3px;
margin-right: 5px;
margin-bottom: 5px;
}
afx-file-view afx-list-view li:nth-child(odd){
background-color: transparent;
}
afx-file-view afx-list-view i.afx-dir:before{
content: "\f07b";
font-family: "FontAwesome";
font-size: 32px;
color: #414339;
font-weight: normal;
font-style: normal;
}
afx-file-view afx-list-view i{
width: 32px;
height: 32px;
display: block;
margin-left: 19px;
}
afx-file-view afx-list-view i.afx-file:before{
content: "\f016";
font-family: "FontAwesome";
font-size: 28px;
color: #414339;
font-style: normal;
font-weight: normal;
}
afx-file-view afx-list-view li.selected, afx-file-view afx-list-view li.selected i:before {
background-color: #116cd6;
color:white;
border-radius: 6px;
}
afx-file-view afx-grid-view i.afx-file:before{
content: "\f016";
font-family: "FontAwesome";
font-size: 16px;
color: #414339;
font-style: normal;
font-weight: normal;
}
afx-file-view afx-grid-view i.afx-dir:before{
content: "\f07b";
font-family: "FontAwesome";
font-size: 16px;
color: #414339;
font-style: normal;
font-weight: normal;
}
afx-file-view afx-grid-view i{
display: inline-block;
margin-right: 5px;
}
afx-file-view afx-grid-view afx-grid-row.selected i:before{
color:white;
}
afx-file-view afx-grid-view afx-grid-row.grid_row_header{
background-color: #dfdfdf;
}
afx-file-view afx-grid-view afx-grid-row.grid_row_header div{
border: 1px solid #a6a6a6;
}

View File

@ -7,6 +7,9 @@ afx-grid-view afx-grid-row div{
padding:3px;
padding-left: 5px;
padding-right: 5px;
user-select:none;
-webkit-user-select:none;
cursor:default;
}
afx-grid-view afx-grid-row:nth-child(even){
@ -15,13 +18,9 @@ afx-grid-view afx-grid-row:nth-child(even){
afx-grid-view afx-grid-row.grid_row_header div{
border-right: 2px solid #e5e5e5;
}
afx-grid-view afx-grid-row i.icon-style {
width: 16px;
height: 16px;
display: inline-block;
float:left;
user-select:none;
-webkit-user-select:none;
cursor:default;
}
afx-grid-view afx-grid-row.selected {
background-color: #116cd6;

View File

@ -0,0 +1,6 @@
afx-label i.icon-style {
width: 16px;
height: 16px;
display: inline-block;
float:left;
}

View File

@ -1,6 +1,7 @@
afx-list-view{
overflow:auto;
padding: 5px;
display: block;
}
/*
afx-list-view div.list-container{
@ -29,12 +30,6 @@ afx-list-view li{
afx-list-view li:nth-child(odd){
background-color: #f5F5F5;
}
afx-list-view i.icon-style {
width: 16px;
height: 16px;
display: inline-block;
float:left;
}
afx-list-view i.closable{
width: 16px;
height: 16px;

View File

@ -15,12 +15,6 @@ afx-menu ul{
padding:0;
margin: 0;
}
afx-menu i.icon-style {
width: 16px;
height: 16px;
display: inline-block;
float:left;
}
afx-menu afx-menu ul {

View File

@ -0,0 +1,20 @@
afx-switch span{
display: inline-block;
width: 30px;
height:24px;
cursor: pointer;
font-size: 24px;
font-family: "FontAwesome";
}
afx-switch span:before{
content: "\f204";
color: #414339;
font-style: normal;
font-weight: normal;
}
afx-switch span.swon:before{
content: "\f205";
color: #116cd6;
font-style: normal;
font-weight: normal;
}