add services

This commit is contained in:
Xuan Sang LE 2017-08-15 02:56:04 +02:00
parent 2985689217
commit 16074ac3f8
39 changed files with 7912 additions and 188 deletions

View File

@ -10,6 +10,7 @@ coffees= src/define.coffee\
src/core/handlers/InBrowserHandler.coffee\ src/core/handlers/InBrowserHandler.coffee\
src/core/gui/gui.coffee\ src/core/gui/gui.coffee\
src/core/gui/BaseApplication.coffee\ src/core/gui/BaseApplication.coffee\
src/core/gui/BaseService.coffee\
src/core/gui/BaseEvent.coffee\ src/core/gui/BaseEvent.coffee\
src/antos.coffee src/antos.coffee
@ -39,11 +40,13 @@ antos_themes = src/core/gui/themes/antos/font-awesome.css\
packages = NotePad Terminal ActivityMonitor packages = NotePad wTerm ActivityMonitor DummyApp
services = PushNotification Spotlight Calendar
main: clean build_coffee build_tag build_theme schemes libs build_packages main: clean build_coffee build_tag build_theme schemes libs build_services build_packages
- cp src/index.html $(BUILDDIR)/ - cp src/index.html $(BUILDDIR)/
lite: build_coffee build_tag build_theme schemes build_services build_packages
#%.js: %.coffee #%.js: %.coffee
# coffee --compile $< # coffee --compile $<
@ -84,8 +87,14 @@ antos_themes_build:
cp src/core/gui/themes/antos/wallpaper.jpg $(BUILDDIR)/resources/themes/antos/ cp src/core/gui/themes/antos/wallpaper.jpg $(BUILDDIR)/resources/themes/antos/
build_services:
@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
build_packages: build_packages:
- mkdir $(BUILDDIR)/packages - mkdir $(BUILDDIR)/packages
- for d in $(packages); do ( test -d $(BUILDDIR)/packages/$$d && rm -rf $(BUILDDIR)/packages/$$d/* ); done
for d in $(packages); do (cd src/packages/$$d; make);done for d in $(packages); do (cd src/packages/$$d; make);done
for d in $(packages); do ( test -d $(BUILDDIR)/packages/$$d || mkdir -p $(BUILDDIR)/packages/$$d && cp -rf src/packages/$$d/build/* $(BUILDDIR)/packages/$$d/);done for d in $(packages); do ( test -d $(BUILDDIR)/packages/$$d || mkdir -p $(BUILDDIR)/packages/$$d && cp -rf src/packages/$$d/build/* $(BUILDDIR)/packages/$$d/);done
for d in $(packages); do ( test -d src/packages/$$d/build && rm -r src/packages/$$d/build ); done for d in $(packages); do ( test -d src/packages/$$d/build && rm -r src/packages/$$d/build ); done

View File

@ -2,6 +2,7 @@ _GUI = self.OS.GUI
_API = self.OS.API _API = self.OS.API
_APP = self.OS.APP _APP = self.OS.APP
_PM = self.OS.PM _PM = self.OS.PM
_courrier = self.OS.courrier
this.onload = () -> this.onload = () ->
console.log "Booting the os" console.log "Booting the os"
self.OS.boot() self.OS.boot()

View File

@ -6,61 +6,62 @@ class BaseApplication
@observable = riot.observable() @observable = riot.observable()
@pid = 0 @pid = 0
@_api = self.OS.API @_api = self.OS.API
init: -> init: ->
me = @ me = @
# first register some base event to the app # first register some base event to the app
@on "exit", ()-> me.quit() @on "exit", () -> me.quit()
@on "focus", () -> @on "focus", () ->
me.sysdock.set "selectedApp", me me.sysdock.set "selectedApp", me
me.appmenu.pid = me.pid me.appmenu.pid = me.pid
me.appmenu.set "items", (me.baseMenu() || []) me.appmenu.set "items", (me.baseMenu() || [])
me.appmenu.set "onmenuselect", (d)-> me.appmenu.set "onmenuselect", (d) ->
me.trigger("menuselect",d) me.trigger("menuselect", d)
@on "hide", ()-> @on "hide", () ->
me.sysdock.set "selectedApp", null me.sysdock.set "selectedApp", null
me.appmenu.set "items",[] me.appmenu.set "items", []
@on "menuselect", (item) -> @on "menuselect", (item) ->
switch item.data.dataid switch item.data.dataid
when "#{me.name}-about" then alert "About " + me.pid + me.name when "#{me.name}-about" then alert "About " + me.pid + me.name
when "#{me.name}-exit" then me.trigger "exit" when "#{me.name}-exit" then me.trigger "exit"
#now load the scheme #now load the scheme
path = "packages/#{@name}/scheme.html" path = "packages/#{@name}/scheme.html"
_GUI.loadScheme path ,this _GUI.loadScheme path , @
on: (e,f) -> @observable.on e,f on: (e, f) -> @observable.on e, f
trigger:(e,d) -> @observable.trigger e,d trigger: (e, d) -> @observable.trigger e, d
show: () -> show: () ->
@observable.trigger "focus" @observable.trigger "focus"
blur: () -> blur: () ->
@.appmenu.set "items",[] if @.appmenu and @.pid == @.appmenu.pid @.appmenu.set "items", [] if @.appmenu and @.pid == @.appmenu.pid
@observable.trigger "blur" @observable.trigger "blur"
hide: () -> hide: () ->
@observable.trigger "hide" @observable.trigger "hide"
toggle:() -> toggle: () ->
@observable.trigger "toggle" @observable.trigger "toggle"
quit: () -> quit: () ->
evt = new _GUI.BaseEvent("exit") evt = new _GUI.BaseEvent("exit")
@exit(evt) @exit(evt)
if not evt.prevent if not evt.prevent
@.appmenu.set "items",[] if @.pid == @.appmenu.pid @.appmenu.set "items", [] if @.pid == @.appmenu.pid
_PM.kill(@) _PM.kill @
($ @scheme).remove() ($ @scheme).remove()
find: (id) -> ($ "[data-id='#{id}']",@scheme)[0] find: (id) -> ($ "[data-id='#{id}']", @scheme)[0]
baseMenu:-> baseMenu: ->
menu = menu =
[{ [{
text:_APP[@name].meta.name, text: _APP[@name].meta.name,
child:[ child: [
{text:"About", dataid:"#{@name}-about"}, { text: "About", dataid: "#{@name}-about" },
{text:"Exit", dataid:"#{@name}-exit"} { text: "Exit", dataid: "#{@name}-exit" }
] ]
}] }]
menu = menu.concat @menu() || [] menu = menu.concat @menu() || []
@ -85,4 +86,5 @@ class BaseApplication
# to handle the exit event # to handle the exit event
# use e.preventDefault() to # use e.preventDefault() to
# discard the quit command # discard the quit command
BaseApplication.type = 1
this.OS.GUI.BaseApplication = BaseApplication this.OS.GUI.BaseApplication = BaseApplication

View File

@ -0,0 +1,40 @@
MAIL = this.OS.courrier
_API = this.OS.API
_PM = this.OS.PM
class BaseService
constructor: (@name) ->
@icon = undefined
@iconclass = "fa-paper-plane-o"
@text = ""
@_api = _API
@timer = undefined
@holder = undefined
init: ()->
#implement by user
# event registe, etc
# scheme loader
attach: (h) -> @holder = h
update: () -> @holder.update() if @holder
on: (e, f) -> MAIL.on e, f
trigger: (e, d) -> MAIL.trigger e, d
watch: ( t, f) ->
me = @
func = () ->
f()
me.timer = setTimeout (() -> func()), t
func()
quit: ()->
console.log "clean timer" if @timer
clearTimeout @timer if @timer
@cleanup()
_PM.kill @
main: () ->
show: () ->
awake: () ->
#implement by user to tart the service
cleanup:() ->
#implemeted by user
BaseService.type = 2
this.OS.GUI.BaseService = BaseService

View File

@ -5,16 +5,16 @@ self.OS.GUI =
data: "#{_GUI.tagPath}/tags.json" data: "#{_GUI.tagPath}/tags.json"
self.OS.API.request query, ()-> self.OS.API.request query, ()->
loadScheme: (path,app) -> loadScheme: (path, app) ->
_API.get path, _API.get path,
(x) -> (x) ->
return null unless x return null unless x
scheme = $.parseHTML x scheme = $.parseHTML x
($ "#desktop").append scheme ($ "#desktop").append scheme
riot.mount ($ scheme), {observable:app.observable} riot.mount ($ scheme), { observable: app.observable }
app.scheme = scheme[0] app.scheme = scheme[0]
app.show()
app.main() app.main()
app.show()
, (f) -> , (f) ->
alert "cannot load scheme" alert "cannot load scheme"
@ -23,15 +23,26 @@ self.OS.GUI =
$ "head link#ostheme" $ "head link#ostheme"
.attr "href", path .attr "href", path
pushService: (srv) ->
return _PM.createProcess srv, _APP[srv] if _APP[srv]
path = "services/#{srv}.js"
$.getScript path
.done (e, s) ->
_PM.createProcess srv, _APP[srv]
.fail (e, s) ->
_courrier.trigger "fail",
{ m: "Cannot read service script: #{srv} ",
e: e, s: s }
launch: (app) -> launch: (app) ->
if not _APP[app] if not _APP[app]
# first load it # first load it
path = "packages/#{app}/" path = "packages/#{app}/"
$.getScript path + "main.js" $.getScript path + "main.js"
.done (e,s) -> .done (e, s) ->
#load css file #load css file
$.get "#{path}main.css", () -> $.get "#{path}main.css", () ->
$ '<link>', {rel:'stylesheet', type:'text/css', 'href':"#{path}main.css"} $ '<link>', { rel: 'stylesheet', type: 'text/css', 'href': "#{path}main.css" }
.appendTo 'head' .appendTo 'head'
#launch #launch
if _APP[app] if _APP[app]
@ -40,12 +51,18 @@ self.OS.GUI =
(data) -> (data) ->
_APP[app].meta = data _APP[app].meta = data
_PM.createProcess app, _APP[app] _PM.createProcess app, _APP[app]
console.log "Fist time loading "+app console.log "Fist time loading " + app
,(e,s)-> , (e, s) ->
_courrier.trigger "fail",
{ m: "Cannot read application metadata: #{app} ",
e: e, s: s }
alert "cannot read application, meta-data" alert "cannot read application, meta-data"
.fail (e,s) -> .fail (e,s) ->
#BUG report here #BUG report here
console.log "bug report" _courrier.trigger "fail",
{ m: "Cannot load application script: #{app}",
e: e, s:s }
console.log "bug report", e, s, path
else else
# now launch it # now launch it
if _APP[app] if _APP[app]
@ -54,56 +71,53 @@ self.OS.GUI =
# dock an application to a dock # dock an application to a dock
# create a data object # create a data object
data = data =
icon:null icon: null
iconclass:meta.iconclass||"" iconclass: meta.iconclass || ""
app:app app:app
onbtclick:() -> onbtclick: () ->
app.toggle() app.toggle()
data.icon = "packages/#{meta.app}/#{meta.icon}" if meta.icon data.icon = "packages/#{meta.app}/#{meta.icon}" if meta.icon
data.iconclass = "fa fa-cogs" if (not meta.icon) and (not meta.iconclass) data.iconclass = "fa fa-cogs" if (not meta.icon) and (not meta.iconclass)
dock = $ "#sysdock" dock = $ "#sysdock"
dock.get(0).newapp data dock.get(0).newapp data
app.sysdock = dock.get(0) app.sysdock = dock.get(0)
app.appmenu = ($ "[data-id = 'appmenu']","#syspanel")[0] app.appmenu = ($ "[data-id = 'appmenu']", "#syspanel")[0]
app.init() app.init()
#app.show() -- notwork, sice the scheme is not loaded yet #app.show() -- notwork, sice the scheme is not loaded yet
undock: (app) -> undock: (app) ->
($ "#sysdock").get(0).removeapp app ($ "#sysdock").get(0).removeapp app
attachservice: (srv) ->
($ "#syspanel")[0].attachservice srv
srv.init()
detachservice: (srv) ->
($ "#syspanel")[0].detachservice srv
bindContextMenu: (event) ->
handler = (e) ->
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
event.preventDefault()
initDM: -> initDM: ->
_API.resource "schemes/dm.html", (x) -> _API.resource "schemes/dm.html", (x) ->
return null unless x return null unless x
scheme = $.parseHTML x scheme = $.parseHTML x
($ "#wrapper").append scheme ($ "#wrapper").append scheme
($ "#desktop").on "click", (e)-> # context menu
return if e.target isnt ($ "#desktop").get(0) riot.mount ($ "#contextmenu")
($ "#sysdock").get(0).set "selectedApp",null ($ "#workspace").contextmenu (e) -> _GUI.bindContextMenu e
#desktop
osmenu = {child:[ desktop = ($ "#desktop")
{text:"",iconclass:"fa fa-eercast", child:[ desktop.on "click", (e) ->
{text:"About"}, return if e.target isnt desktop.get(0)
{text:"System Preferences", iconclass:"fa fa-commenting"}, ($ "#sysdock").get(0).set "selectedApp", null
{text:"Applications",child:[ desktop.get(0).contextmenuHandler = (e, m) ->
{text:"Terminal",type:"app"}, console.log "context menu handler for desktop"
{text:"NotePad",type:"app", icon:"packages/NotePad/icon.png"}, # system menu
{text:"ActivityMonitor",type:"app"} riot.mount ($ "#syspanel", $ "#wrapper")
]}, riot.mount ($ "#sysdock", $ "#wrapper"), { items: [] }
{text:"Logout"}
]}
],onmenuselect: (item)->
switch item.data.type
when "app" then _GUI.launch item.data.text
}
appmenu = {child:[]}
systray = {child:[
{text:"Sun 22:57 6 August 2017"},
{text:"",iconclass:"fa fa-search"},
{text:"",iconclass:"fa fa-commenting"}
],onmenuselect: (item)->
console.log item
}
riot.mount ($ "#syspanel", $ "#wrapper"),{osmenu:osmenu,appmenu:appmenu,systray:systray}
riot.mount ($ "#sysdock", $ "#wrapper"), {items:[]}

View File

@ -6,3 +6,4 @@
<div id = "desktop"> <div id = "desktop">
</div> </div>
</div> </div>
<afx-menu id="contextmenu" context="true" style="display:none;"></afx-menu>

View File

@ -39,10 +39,6 @@
{ {
return self[k] return self[k]
} }
self.root.update = function()
{
self.update()
}
minimize() minimize()
{ {
this.root.observable.trigger("hide") this.root.observable.trigger("hide")
@ -108,6 +104,7 @@
else else
self.root.observable.trigger("focus") self.root.observable.trigger("focus")
}) })
self.root.observable.trigger("loaded", self.root)
}) })
var enable_dragging = function() var enable_dragging = function()
{ {

View File

@ -51,10 +51,9 @@
{ {
return self[k] return self[k]
} }
self.root.update = function() this.on("mount", function(){
{ window.OS.courrier.trigger("sysdockloaded")
self.update() })
}
</script> </script>
</afx-apps-dock> </afx-apps-dock>

View File

@ -23,10 +23,6 @@
{ {
return self[k] return self[k]
} }
self.root.update = function()
{
self.update()
}
this._onbtclick = function(e) this._onbtclick = function(e)
{ {
if(typeof opts.onbtclick == 'string') if(typeof opts.onbtclick == 'string')

View File

@ -82,7 +82,6 @@
data:event.item} data:event.item}
if(opts.onlistselect) if(opts.onlistselect)
opts.onlistselect(data) opts.onlistselect(data)
console.log(data)
if(self.selidx != -1) if(self.selidx != -1)
self.rows[self.selidx].selected =false self.rows[self.selidx].selected =false
self.selidx = event.item.i self.selidx = event.item.i

View File

@ -4,23 +4,6 @@
</div> </div>
<script> <script>
var self = this var self = this
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]
}
self.root.update = function()
{
self.update()
}
this.on('mount', function(){ this.on('mount', function(){
$(self.refs.container) $(self.refs.container)
.css("display","flex") .css("display","flex")
@ -44,6 +27,7 @@
var auto_height = [] var auto_height = []
var csize, ocheight = 0, avaiheight; var csize, ocheight = 0, avaiheight;
avaiheight = $(self.root).parent().height() avaiheight = $(self.root).parent().height()
avaiwidth = $(self.root).parent().width()
$(self.refs.container).css("height",avaiheight + "px") $(self.refs.container).css("height",avaiheight + "px")
$(self.refs.container) $(self.refs.container)
.children() .children()
@ -69,6 +53,8 @@
{ {
$(v).css("height", csize + "px") $(v).css("height", csize + "px")
}) })
self.root.observable.trigger("hboxchange",
{id:$(self.root).attr("data-id"), w:avaiwidth, h:csize})
} }
</script> </script>
</afx-hbox> </afx-hbox>

View File

@ -28,10 +28,6 @@
self[k] = v self[k] = v
self.update() self.update()
} }
self.root.update = function()
{
self.update()
}
self.root.get = function(k) self.root.get = function(k)
{ {
if(k == "selected") if(k == "selected")
@ -69,7 +65,6 @@
{ {
var desktoph = $("#desktop").height() var desktoph = $("#desktop").height()
var off = $(self.root).offset().top + $(self.refs.mlist).height() var off = $(self.root).offset().top + $(self.refs.mlist).height()
console.log(desktoph,off)
if( off > desktoph ) if( off > desktoph )
$(self.refs.mlist) $(self.refs.mlist)
.css("top","-" + $(self.refs.mlist).outerHeight() + "px") .css("top","-" + $(self.refs.mlist).outerHeight() + "px")

View File

@ -1,23 +1,30 @@
<afx-menu> <afx-menu >
<ul> <ul class={context: opts.context == "true"}>
<li class="afx-corner-fix"></li> <li class="afx-corner-fix"></li>
<li each={ items } class = {afx_submenu:child != null, fix_padding:icon}> <li ref = "container" each={ item,i in items } class = {afx_submenu:item.child != null, fix_padding:item.icon} no-reorder>
<a href="#" onclick = {parent.onselect}> <a href="#" onclick = {parent.onselect}>
<i if={iconclass} class = {iconclass} ></i> <i if={item.iconclass} class = {item.iconclass} ></i>
<i if={icon} class="icon-style" style = { "background: url("+icon+");background-size: 100% 100%;background-repeat: no-repeat;" }></i> <i if={item.icon} class="icon-style" style = { "background: url("+item.icon+");background-size: 100% 100%;background-repeat: no-repeat;" }></i>
{ text } { item.text }
</a> </a>
<afx-menu if={child != null} child={child} onmenuselect={onmenuselect} observable = {parent.root.observable} rootid = {parent.rid}></afx-menu> <afx-menu if={item.child != null} child={item.child} observable = {parent.root.observable} rootid = {parent.rid}></afx-menu>
</li> </li>
<li class="afx-corner-fix"></li> <li class="afx-corner-fix"></li>
</ul> </ul>
<script> <script>
this.items = opts.child this.items = opts.child || []
var isRoot
if(opts.rootid) if(opts.rootid)
{
this.rid = opts.rootid this.rid = opts.rootid
isRoot = false
}
else else
{
this.rid = $(this.root).attr("data-id") this.rid = $(this.root).attr("data-id")
isRoot = true
}
var self = this var self = this
this.onmenuselect = opts.onmenuselect this.onmenuselect = opts.onmenuselect
self.root.set = function(k,v) self.root.set = function(k,v)
@ -29,14 +36,45 @@
self[k] = v self[k] = v
self.update() self.update()
} }
self.root.get = function(k) self.root.push = function(e,u)
{ {
return self[k] self.items.push(e)
if(u)
self.update()
}
self.root.unshift = function(e,u)
{
self.items.unshift(e)
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.update = function() self.root.update = function()
{ {
self.update() self.update()
} }
self.root.get = function(k)
{
return self[k]
}
self.root.show = function(e)
{
//only for menucontext
if(opts.context != "true") return;
$(self.root)
.css("top", e.clientY - 15 + "px")
.css("left",e.clientX -5 + "px")
.show()
$(document).on("click",mnhide)
}
if(opts.observable) if(opts.observable)
{ {
this.root.observable = opts.observable this.root.observable = opts.observable
@ -47,23 +85,61 @@
this.root.observable.on('menuselect',function(data){ this.root.observable.on('menuselect',function(data){
//console.log("From root",self.root) //console.log("From root",self.root)
if(self.onmenuselect) if(self.onmenuselect)
{
self.onmenuselect(data) self.onmenuselect(data)
if(opts.context == "true")
$(self.root).hide()
else if(!data.root && self.refs.container)
{
var arr = self.refs.container.length?self.refs.container:[self.refs.container]
for( var i in arr)
$("afx-menu",arr[i]).first().hide()
} }
}) })
} }
var mnhide = function(event)
{
if(opts.context == "true")
{
if(!$(event.target).closest(self.root).length) {
$(self.root).hide()
$(document).unbind("click",mnhide)
}
return;
}
if(!$(event.target).closest(self.refs.container).length && self.refs.container) {
var arr = self.refs.container.length?self.refs.container:[self.refs.container]
for( var i in arr)
$("afx-menu",arr[i]).first().hide()
$(document).unbind("click",mnhide)
}
else
{
if(self.refs.container && self.refs.container.length)
for(var i in self.refs.container)
if(!$(event.target).closest(self.refs.container[i]).length) {
$("afx-menu",self.refs.container[i]).first().hide()
}
}
}
onselect(event) onselect(event)
{ {
var data = {id:self.rid, data:event.item} var data = {id:self.rid, data:event.item.item, root:isRoot}
/*if(self.onmenuselect)
{
self.onmenuselect(data)
} else*/
this.root.observable.trigger('menuselect',data) this.root.observable.trigger('menuselect',data)
event.preventDefault() event.preventDefault()
$(document).unbind("click",mnhide)
if(opts.context == "true") return
if(isRoot && self.refs.container)
{
if(self.refs.container.length)
$("afx-menu",self.refs.container[event.item.i]).first().show()
else
$("afx-menu",self.refs.container).first().show()
$(document).on("click",mnhide)
return
}
} }
</script> </script>

View File

@ -0,0 +1,3 @@
<afx-service>
<yield/>
</afx-service>

View File

@ -1,16 +1,42 @@
<afx-sys-panel> <afx-sys-panel>
<div> <div>
<afx-menu data-id = "os_menu" ref = "aOsmenu" child={osmenu.child} onmenuselect = {osmenu.onmenuselect} class="afx-panel-os-menu"></afx-menu> <afx-menu data-id = "os_menu" ref = "aOsmenu" child={osmenu.child} onmenuselect = {osmenu.onmenuselect} class="afx-panel-os-menu"></afx-menu>
<afx-menu data-id = "appmenu" ref = "aAppmenu" child={appmenu.child} onmenuselect = {appmenu.onmenuselect} class = "afx-panel-os-app"></afx-menu> <afx-menu data-id = "appmenu" ref = "aAppmenu" child={appmenu.child} class = "afx-panel-os-app"></afx-menu>
<afx-menu data-id = "sys_tray" ref = "aTray" child={systray.child} onmenuselect = {systray.onmenuselect} class = "afx-panel-os-stray"></afx-menu> <afx-menu data-id = "sys_tray" ref = "aTray" child={systray.child} onmenuselect = {systray.onmenuselect} class = "afx-panel-os-stray"></afx-menu>
</div> </div>
<script> <script>
this.osmenu = opts.osmenu this.osmenu = {child:[
this.appmenu = opts.appmenu {text:"",iconclass:"fa fa-eercast", child:[
this.systray = opts.systray {text:"About"},
var self = this {text:"System Preferences", iconclass:"fa fa-commenting"},
{text:"Applications",child:[
{text:"wTerm",type:"app"},
{text:"NotePad",type:"app", iconclass:"fa fa-commenting"},
{text:"ActivityMonitor",type:"app"},
{text:"DummyApp",type:"app"}
]},
{text:"Logout"}
]}
],onmenuselect: function(item)
{
if(item.data.type == "app")
window.OS.GUI.launch(item.data.text)
}
}
this.appmenu = { child: [] }
this.systray = { child: [], onmenuselect: function(item){item.data.awake()}}
var self = this
self.root.attachservice = function(s)
{
s.attach(self.refs.aTray)
self.refs.aTray.root.unshift(s,true)
}
self.root.detachservice = function(s)
{
self.refs.aTray.root.remove(s, true)
}
self.root.set = function(k,v) self.root.set = function(k,v)
{ {
if(k == "*") if(k == "*")
@ -24,15 +50,12 @@
{ {
return self[k] return self[k]
} }
self.root.update = function()
{
self.update()
}
this.on('mount', function() { this.on('mount', function() {
//console.log(self.refs.aOsmenu.root) //console.log(self.refs.aOsmenu.root)
$(self.refs.aOsmenu.root).css("z-index",1000000) $(self.refs.aOsmenu.root).css("z-index",1000000)
$(self.refs.aAppmenu.root).css("z-index",1000000) $(self.refs.aAppmenu.root).css("z-index",1000000)
$(self.refs.aTray.root).css("z-index",1000000) $(self.refs.aTray.root).css("z-index",1000000)
window.OS.courrier.trigger("syspanelloaded")
}) })
</script> </script>
</afx-sys-panel> </afx-sys-panel>

View File

@ -49,10 +49,6 @@
self[k] = v self[k] = v
self.update() self.update()
} }
self.root.update = function()
{
self.update()
}
self.root.get = function(k) self.root.get = function(k)
{ {
return self[k] return self[k]

View File

@ -4,23 +4,6 @@
</div> </div>
<script> <script>
var self = this var self = this
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]
}
self.root.update = function()
{
self.update()
}
this.on('mount', function(){ this.on('mount', function(){
$(self.refs.container) $(self.refs.container)
.css("display","flex") .css("display","flex")
@ -36,7 +19,6 @@
}) })
} }
}) })
var calibrate_size = function() var calibrate_size = function()
{ {
var auto_width = [] var auto_width = []
@ -51,6 +33,7 @@
this.observable = self.root.observable this.observable = self.root.observable
$(this) $(this)
.css("flex-grow","1") .css("flex-grow","1")
//.css("height",avaiheight + "px")
var dw = $(this).attr("data-width") var dw = $(this).attr("data-width")
if(dw) if(dw)
{ {
@ -67,6 +50,8 @@
{ {
$(v).css("width", csize + "px") $(v).css("width", csize + "px")
}) })
self.root.observable.trigger("vboxchange",
{id:$(self.root).attr("data-id"), w:csize, h:avaiheight})
} }
</script> </script>
</afx-vbox> </afx-vbox>

View File

@ -66,7 +66,7 @@ afx-menu afx-menu li{
float:none; float:none;
min-width: 150px; min-width: 150px;
} }
afx-menu afx-menu afx-menu{ afx-menu afx-menu afx-menu, afx-menu ul.context afx-menu{
top:-4px; top:-4px;
left: 100%; left: 100%;
} }
@ -78,7 +78,7 @@ afx-menu li:hover > a {
color: white; color: white;
} }
afx-menu li:hover > afx-menu afx-menu afx-menu li:hover > afx-menu, ul.context li:hover > afx-menu
{ {
display: block; display: block;
} }
@ -92,7 +92,7 @@ afx-menu li.afx-corner-fix:hover{
background-color: transparent; background-color: transparent;
} }
afx-menu afx-menu .afx_submenu:before { afx-menu afx-menu .afx_submenu:before, afx-menu ul.context .afx_submenu:before{
content: "\f054"; content: "\f054";
font-family: "FontAwesome"; font-family: "FontAwesome";
font-size: 10px; font-size: 10px;
@ -101,3 +101,19 @@ afx-menu afx-menu .afx_submenu:before {
position:absolute; position:absolute;
top:25%; top:25%;
} }
afx-menu ul.context{
position: absolute;
z-index: 1000000;
padding: 0;
border:1px solid #a6a6a6;
border-radius: 5px;
border-top-left-radius: 0px;
/*box-shadow: 2px 2px 2px #cbcbcb;*/
box-shadow: 1px 1px 1px #9f9F9F;
background-color: #e7e7e7;
}
afx-menu ul.context li{
clear:float;
min-width: 150px;
}

View File

@ -1,7 +1,7 @@
self.OS.PM = self.OS.PM =
pidalloc:0 pidalloc: 0
processes: new Object processes: new Object
createProcess: (app,cls) -> createProcess: (app, cls) ->
#if it is single ton #if it is single ton
# and a process is existing # and a process is existing
# just return it # just return it
@ -15,12 +15,12 @@ self.OS.PM =
_PM.pidalloc++ _PM.pidalloc++
obj.pid = _PM.pidalloc obj.pid = _PM.pidalloc
_PM.processes[app].push obj _PM.processes[app].push obj
_GUI.dock obj,cls.meta if cls.type is 1 then _GUI.dock obj, cls.meta else _GUI.attachservice obj
appByPid:(pid)-> appByPid:(pid)->
app = undefined app = undefined
find = (l) -> find = (l) ->
return a for a in l when a.pid is pid return a for a in l when a.pid is pid
for k,v of _PM.processes for k, v of _PM.processes
app = find v app = find v
break if app break if app
app app
@ -30,6 +30,7 @@ self.OS.PM =
i = _PM.processes[app.name].indexOf app i = _PM.processes[app.name].indexOf app
if i >= 0 if i >= 0
_GUI.undock _PM.processes[app.name][i] p = _PM.processes[app.name][i]
if _APP[app.name].type == 1 then _GUI.undock p else _GUI.detachservice p
delete _PM.processes[app.name][i] delete _PM.processes[app.name][i]
_PM.processes[app.name].splice i,1 _PM.processes[app.name].splice i, 1

View File

@ -5,6 +5,7 @@ self.OS or=
GUI: new Object() GUI: new Object()
APP: new Object() APP: new Object()
PM: new Object() PM: new Object()
courrier: riot.observable()
register: (name,x)-> register: (name,x)->
# load the metadata first # load the metadata first
_APP[name] = x _APP[name] = x
@ -15,4 +16,8 @@ self.OS or=
_GUI = self.OS.GUI _GUI = self.OS.GUI
_GUI.loadTheme "antos" _GUI.loadTheme "antos"
_GUI.initDM() _GUI.initDM()
#_GUI.loadScheme "resources/schemes/test.html",null _courrier.on "syspanelloaded", () ->
_GUI.pushService "PushNotification"
_GUI.pushService "Spotlight"
_GUI.pushService "Calendar"

View File

@ -14,7 +14,7 @@ class ActivityMonitor extends this.OS.GUI.BaseApplication
app = _PM.appByPid item[0].value app = _PM.appByPid item[0].value
app.quit() if app app.quit() if app
header = [{width:50,value:"Pid"},{value:"Name"},{width:100,value:"Alive (ms)"}] header = [{width:50,value:"Pid"},{value:"Name"}, {value:"Type", width:75},{width:70,value:"Alive (ms)"}]
@gdata = @gdata =
processes:{} processes:{}
alive:[] alive:[]
@ -29,11 +29,14 @@ class ActivityMonitor extends this.OS.GUI.BaseApplication
$.each _PM.processes, (i,d)-> $.each _PM.processes, (i,d)->
$.each d , (j,a)-> $.each d , (j,a)->
if me.gdata.processes[a.pid] #update it if me.gdata.processes[a.pid] #update it
me.gdata.processes[a.pid][2].value = now - a.birth me.gdata.processes[a.pid][3].value = now - a.birth
else #add it else #add it
me.gdata.processes[a.pid] = [ me.gdata.processes[a.pid] = [
{value:a.pid}, {value:a.pid},
{icon:_APP[a.name].meta.icon,iconclass:_APP[a.name].meta.iconclass,value:a.name}, {icon:if _APP[a.name].type == 1 then _APP[a.name].meta.icon else a.icon,
iconclass:if _APP[a.name].type == 1 then _APP[a.name].meta.iconclass else a.iconclass,
value:a.name},
{value: if _APP[a.name].type == 1 then "Application" else "Service"}
{value: now - a.birth} {value: now - a.birth}
] ]
me.gdata.alive.push a.pid me.gdata.alive.push a.pid

View File

@ -13,7 +13,7 @@ NC=\033[0m
main: title clean js css copy main: title clean js css copy
title: title:
@echo "$(BLUE)======= Package Terminal =======$(NC)" @echo "$(BLUE)======= Package DummyApp =======$(NC)"
coffee: coffee:
- mkdir build - mkdir build

View File

@ -1,6 +1,6 @@
class Terminal extends this.OS.GUI.BaseApplication class DummyApp extends this.OS.GUI.BaseApplication
constructor: () -> constructor: () ->
super "Terminal" super "DummyApp"
main: () -> main: () ->
self = @ self = @
@on "btclick", (e)-> @on "btclick", (e)->
@ -19,7 +19,7 @@ class Terminal extends this.OS.GUI.BaseApplication
tdata = { tdata = {
name: 'My Tree', name: 'My Tree',
nodes: [ nodes: [
{ name: 'hello', icon:'packages/NotePad/icon.png'}, { name: 'hello', icon:'fa fa-car'},
{ name: 'wat' }, { name: 'wat' },
{ {
name: 'child folder', name: 'child folder',
@ -76,5 +76,12 @@ class Terminal extends this.OS.GUI.BaseApplication
list.set "onlistselect", (e)-> list.set "onlistselect", (e)->
console.log e console.log e
Terminal.singleton = false @scheme.set "apptitle", "AntOS feature showcase"
this.OS.register "Terminal",Terminal
@scheme.contextmenuHandler = (e, m) ->
mdata = [ { text: " Child 1" }, { text: "child2", child: [{text: "sub child", child:[{text:"sub sub child"}] }]}]
m.set "items", mdata
m.show(e)
DummyApp.singleton = false
this.OS.register "DummyApp",DummyApp

View File

@ -0,0 +1,12 @@
{
"app":"DummyApp",
"name":"DummyApp",
"description":"App for test",
"author":{
"name": "Xuan Sang LE",
"email": "xsang.le@gmail.com"
},
"category":"System",
"iconclass":"fa fa-user-circle-o",
"mimes":["*"]
}

View File

@ -14,7 +14,7 @@ class NotePad extends this.OS.GUI.BaseApplication
enableBasicAutocompletion: true, enableBasicAutocompletion: true,
enableSnippets: true, enableSnippets: true,
enableLiveAutocompletion: true, enableLiveAutocompletion: true,
fontSize: "10pt" fontSize: "9pt"
} }
@.editor.completers.push {getCompletions:(editor, session, pos, prefix, callback)->} @.editor.completers.push {getCompletions:(editor, session, pos, prefix, callback)->}
@.editor.getSession().setUseWrapMode true @.editor.getSession().setUseWrapMode true
@ -34,8 +34,7 @@ class NotePad extends this.OS.GUI.BaseApplication
l = me.editor.session.getLength() l = me.editor.session.getLength()
$(stat).html "Row #{c.row}, col #{c.column}, lines: #{l}" $(stat).html "Row #{c.row}, col #{c.column}, lines: #{l}"
stup(0) stup(0)
@.editor.getSession().selection.on "changeCursor", (e)-> @.editor.getSession().selection.on "changeCursor", (e)->stup(e)
stup(e)
@on "resize", ()-> me.editor.resize() @on "resize", ()-> me.editor.resize()
@on "focus", ()->me.editor.focus() @on "focus", ()->me.editor.focus()

View File

@ -1,9 +1,16 @@
afx-app-window[data-id="notepad"] afx-list-view[data-id="modelist"] {
margin: 2px;
margin-right: 5px;
}
afx-app-window[data-id="notepad"] afx-list-view[data-id="modelist"]{ afx-app-window[data-id="notepad"] afx-list-view[data-id="modelist"] div.list-container{
margin:2px; z-index: 10;
} }
afx-app-window[data-id="notepad"] span[data-id="editorstat"]{ afx-app-window[data-id="notepad"] span[data-id="editorstat"]{
padding:5px; padding:5px;
display: inline-block; display: inline-block;
} }
afx-app-window[data-id="notepad"] afx-vbox[data-id="bottom-vbox"]{
background-color: #dfdfdf;
}

View File

@ -15,7 +15,7 @@
</afx-hbox--> </afx-hbox-->
<div data-id="datarea"></div> <div data-id="datarea"></div>
<afx-vbox data-height="30"> <afx-vbox data-height="30" data-id="bottom-vbox">
<div ><span data-id = "editorstat"></span></div> <div ><span data-id = "editorstat"></span></div>
<afx-list-view data-width="170" data-id = "modelist" dropdown = "true" width="150"></afx-list-view> <afx-list-view data-width="170" data-id = "modelist" dropdown = "true" width="150"></afx-list-view>

View File

@ -0,0 +1,34 @@
coffee_files = main.coffee
jsfiles = xterm.js
cssfiles = xterm.css main.css
copyfiles = scheme.html package.json
BLUE=\033[1;34m
NC=\033[0m
main: title clean js css copy
title:
@echo "$(BLUE)======= Package wTerm =======$(NC)"
- rm -rf build/*
coffee:
- mkdir build
for f in $(coffee_files); do (coffee -cs < $$f >build/"$$f.js");done
for f in build/*.coffee.js; do (cat "$${f}"; echo) >> build/main.js; done
- rm build/*.coffee.js
js: coffee
for f in $(jsfiles); do (cat "$${f}"; echo) >> build/main.js; done
css:
for f in $(cssfiles); do (cat "$${f}"; echo) >> build/main.css; done
copy:
cp -rf $(copyfiles) build/
clean:
- rm -rf build/*

View File

@ -0,0 +1,71 @@
class wTerm extends this.OS.GUI.BaseApplication
constructor: () ->
super "wTerm"
main: () ->
me = @
@scheme.set "apptitle", "Terminal"
@mterm = @find "myterm"
@term = new Terminal { cursorBlink: true }
@term.on "key", (d, e) ->
me.socket.send "i#{d}" if me.socket
@term.on 'title', () -> console.log "title change"
@term.open @mterm
@socket = null
#@on "resize", () -> me.resizeContent()
@on "focus", () -> me.term.focus()
# handle the paste event
area = ($ ".xterm-helper-textarea", @mterm)[0]
area.onpaste = (e) ->
#ifreturn false unless @socket
pastedText = undefined
if window.clipboardData and window.clipboardData.getData #IE
pastedText = window.clipboardData.getData 'Text'
else if e.clipboardData and e.clipboardData.getData
pastedText = e.clipboardData.getData 'text/plain'
return false unless pastedText
# send by chunk, to ease the handle on server side
len = pastedText.length
chunklen = len / 1000 + if (len % 1000 == 0) then 0 else 1
for i in [0..(len - 1)]
end = if (i + 1) * 1000 > len then len else (i + 1) * 1000
me.term.write pastedText.substring i * 1000, end
#self.socket.send("i"+ substr.replace(/\n/g,"\r\n"))
@openSession()
@on "vboxchange", (e) -> me.resizeContent e.w, e.h
resizeContent: (w, h) ->
ex = @term.rowContainer.firstElementChild
oldhtml = ($ ex).html()
($ ex).css "display", "inline"
($ ex).html "W"
ncol = parseInt (w / ($ ex).width())
nrow = parseInt (h / ($ ex).height())
($ ex).css "display", ""
($ ex).html oldhtml
@term.resize ncol, nrow
return if not @socket or (@socket.readyState isnt @socket.OPEN)
#initialGeometry = @.term.proposeGeometry()
#cols = initialGeometry.cols
#rows = initialGeometry.rows
#console.log "send", "s#{ncol}:#{nrow}"
@socket.send "s#{ncol}:#{nrow}"
openSession: () ->
me = @
@term.clear()
@term.focus()
@socket = new WebSocket "ws://" + window.location.host + "/wterm"
@socket.onopen = () ->
#el.style.display = "none"
me.resizeContent (($ me.mterm).width()) , (($ me.mterm).height())
me.term.focus()
@socket.onmessage = (e) -> me.term.write e.data if me.term and e.data
@socket.onclose = () ->
me.socket = null
console.log "socket closed"
#el.style.display = "block"
exit: (e)->
@socket.close() if @socket
this.OS.register "wTerm",wTerm

View File

View File

@ -1,5 +1,5 @@
{ {
"app":"Terminal", "app":"wTerm",
"name":"Unix terminal like", "name":"Unix terminal like",
"description":"Access Unix terminal from web", "description":"Access Unix terminal from web",
"author":{ "author":{

View File

@ -0,0 +1,5 @@
<afx-app-window apptitle="Preview" width="600" height="400">
<afx-vbox data-id = "mybox">
<div data-id="myterm" ></div>
</afx-vbox>
</afx-app-window>

2261
src/packages/wTerm/xterm.css Executable file

File diff suppressed because it is too large Load Diff

5132
src/packages/wTerm/xterm.js Executable file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,23 @@
class Calendar extends this.OS.GUI.BaseService
constructor: () ->
super "Calendar"
#@iconclass = "fa fa-commenting"
@text = ""
@iconclass = "fa fa-calendar"
init: ->
#update time each second
me = @
@watch 1000, () ->
now = new Date
me.text = "#{now.getDate()}/#{(now.getMonth()+1)}/#{now.getFullYear()} " +
"#{now.getHours()}:#{now.getMinutes()}:#{now.getSeconds()}"
me.update()
awake: ->
console.log @name,@pid
# do nothing
cleanup: ->
console.log "cleanup for quit"
# do nothing
this.OS.register "Calendar",Calendar

View File

@ -0,0 +1,13 @@
class PushNotification extends this.OS.GUI.BaseService
constructor: () ->
super "PushNotification"
@iconclass = "fa fa-commenting"
init: ->
# do nothing
awake: ->
console.log @name,@pid
cleanup: ->
# do nothing
this.OS.register "PushNotification",PushNotification

View File

@ -0,0 +1,13 @@
class Spotlight extends this.OS.GUI.BaseService
constructor: () ->
super "Spotlight"
@iconclass = "fa fa-search"
init: ->
# do nothing
awake: ->
console.log @name,@pid
cleanup: ->
# do nothing
this.OS.register "Spotlight",Spotlight