use services to communicate between apps

This commit is contained in:
Xuan Sang LE 2017-08-16 00:27:32 +02:00
parent 16074ac3f8
commit 8fbd0b4a98
62 changed files with 590 additions and 211 deletions

View File

@ -4,53 +4,57 @@ BUILDDIR = build/htdocs
BLUE=\033[1;34m
NC=\033[0m
coffees= src/define.coffee\
coffees= src/core/core.coffee\
src/core/api.coffee\
src/core/processes.coffee\
src/core/handlers/InBrowserHandler.coffee\
src/core/gui/gui.coffee\
src/core/gui/BaseApplication.coffee\
src/core/gui/BaseService.coffee\
src/core/gui/BaseEvent.coffee\
src/core/gui.coffee\
src/core/BaseModel.coffee\
src/core/BaseApplication.coffee\
src/core/BaseService.coffee\
src/core/BaseEvent.coffee\
src/antos.coffee
tags= src/core/gui/tags/afx-button.js\
src/core/gui/tags/afx-menu.js\
src/core/gui/tags/afx-sys-panel.js\
src/core/gui/tags/afx-apps-dock.js\
src/core/gui/tags/afx-app-window.js\
src/core/gui/tags/afx-vbox.js\
src/core/gui/tags/afx-hbox.js\
src/core/gui/tags/afx-list-view.js\
src/core/gui/tags/afx-tree-view.js \
src/core/gui/tags/afx-grid-view.js
tags= src/core/tags/afx-button.js\
src/core/tags/afx-menu.js\
src/core/tags/afx-sys-panel.js\
src/core/tags/afx-apps-dock.js\
src/core/tags/afx-app-window.js\
src/core/tags/afx-vbox.js\
src/core/tags/afx-hbox.js\
src/core/tags/afx-list-view.js\
src/core/tags/afx-tree-view.js \
src/core/tags/afx-overlay.js\
src/core/tags/afx-dummy.js\
src/core/tags/afx-feed.js\
src/core/tags/afx-grid-view.js
antos_themes = src/core/gui/themes/antos/font-awesome.css\
src/core/gui/themes/antos/ubuntu-regular.css\
src/core/gui/themes/antos/hermit-light.css\
src/core/gui/themes/antos/antos.css\
src/core/gui/themes/antos/afx-button.css\
src/core/gui/themes/antos/afx-menu.css\
src/core/gui/themes/antos/afx-sys-panel.css\
src/core/gui/themes/antos/afx-dock.css\
src/core/gui/themes/antos/afx-list-view.css\
src/core/gui/themes/antos/afx-tree-view.css\
src/core/gui/themes/antos/afx-grid-view.css\
src/core/gui/themes/antos/afx-app-window.css
antos_themes = src/themes/antos/font-awesome.css\
src/themes/antos/ubuntu-regular.css\
src/themes/antos/hermit-light.css\
src/themes/antos/antos.css\
src/themes/antos/afx-button.css\
src/themes/antos/afx-menu.css\
src/themes/antos/afx-sys-panel.css\
src/themes/antos/afx-dock.css\
src/themes/antos/afx-list-view.css\
src/themes/antos/afx-tree-view.css\
src/themes/antos/afx-grid-view.css\
src/themes/antos/afx-feed.css\
src/themes/antos/afx-app-window.css
packages = NotePad wTerm ActivityMonitor DummyApp
services = PushNotification Spotlight Calendar
main: clean build_coffee build_tag build_theme schemes libs build_services build_packages
main: clean build_coffees build_tags build_themes schemes libs build_services build_packages
- cp src/index.html $(BUILDDIR)/
lite: build_coffee build_tag build_theme schemes build_services build_packages
#%.js: %.coffee
# coffee --compile $<
build_coffee:
build_coffees:
@echo "$(BLUE)=======Building coffee files=======$(NC)"
- mkdir $(BUILDDIR)/scripts
- rm $(BUILDDIR)/scripts/antos.js
@ -66,15 +70,15 @@ libs:
schemes:
@echo "$(BLUE)=======Copy schemes files======= $(NC)"
- mkdir -p $(BUILDDIR)/resources/schemes
cp src/core/gui/schemes/* $(BUILDDIR)/resources/schemes/
cp src/core/schemes/* $(BUILDDIR)/resources/schemes/
build_tag:
build_tags:
@echo "=======$(BLUE)Building tag files=======$(NC)"
-mkdir $(BUILDDIR)/resources
-rm $(BUILDDIR)/resources/antos_tags.js
for f in $(tags); do (cat "$${f}"; echo) >> $(BUILDDIR)/resources/antos_tags.js; done
build_theme: antos_themes_build
build_themes: antos_themes_build
antos_themes_build:
@ -83,8 +87,8 @@ antos_themes_build:
-mkdir -p $(BUILDDIR)/resources/themes/antos
for f in $(antos_themes); do (cat "$${f}"; echo) >> $(BUILDDIR)/resources/themes/antos/antos.css; done
-mkdir -p $(BUILDDIR)/resources/themes/antos/fonts
cp -rf src/core/gui/themes/antos/fonts/* $(BUILDDIR)/resources/themes/antos/fonts
cp src/core/gui/themes/antos/wallpaper.jpg $(BUILDDIR)/resources/themes/antos/
cp -rf src/themes/antos/fonts/* $(BUILDDIR)/resources/themes/antos/fonts
cp src/themes/antos/wallpaper.jpg $(BUILDDIR)/resources/themes/antos/
build_services:

View File

@ -1,16 +1,15 @@
self = this
_PM = self.OS.PM
_APP = self.OS.APP
class BaseApplication
constructor: (@name) ->
@observable = riot.observable()
@pid = 0
@_api = self.OS.API
_MAIL = self.OS.courrier
class BaseApplication extends this.OS.GUI.BaseModel
constructor: (name) ->
super name
init: ->
me = @
# first register some base event to the app
@on "exit", () -> me.quit()
@on "focus", () ->
me.sysdock.set "selectedApp", me
me.appmenu.pid = me.pid
@ -20,41 +19,33 @@ class BaseApplication
@on "hide", () ->
me.sysdock.set "selectedApp", null
me.appmenu.set "items", []
@on "menuselect", (item) ->
switch item.data.dataid
@on "menuselect", (d) ->
switch d.e.item.data.dataid
when "#{me.name}-about" then alert "About " + me.pid + me.name
when "#{me.name}-exit" then me.trigger "exit"
#now load the scheme
path = "packages/#{@name}/scheme.html"
_GUI.loadScheme path , @
@.render path
on: (e, f) -> @observable.on e, f
trigger: (e, d) -> @observable.trigger e, d
show: () ->
@observable.trigger "focus"
@trigger "focus"
blur: () ->
@.appmenu.set "items", [] if @.appmenu and @.pid == @.appmenu.pid
@observable.trigger "blur"
@trigger "blur"
hide: () ->
@observable.trigger "hide"
@trigger "hide"
toggle: () ->
@observable.trigger "toggle"
@trigger "toggle"
quit: () ->
evt = new _GUI.BaseEvent("exit")
@exit(evt)
onexit: (evt) ->
@cleanup(evt)
if not evt.prevent
@.appmenu.set "items", [] if @.pid == @.appmenu.pid
_PM.kill @
($ @scheme).remove()
find: (id) -> ($ "[data-id='#{id}']", @scheme)[0]
baseMenu: ->
menu =
[{
@ -81,7 +72,7 @@ class BaseApplication
# to return app data
update:->
#implement by subclasses
exit: (e) ->
cleanup: (e) ->
#implement by subclasses
# to handle the exit event
# use e.preventDefault() to

50
src/core/BaseModel.coffee Normal file
View File

@ -0,0 +1,50 @@
self = this
_PM = self.OS.PM
_APP = self.OS.APP
_MAIL = self.OS.courrier
_GUI = self.OS.GUI
class BaseModel
constructor: (@name) ->
@observable = riot.observable()
@pid = 0
@_api = self.OS.API
me = @
@on "exit", () -> me.quit()
@parent = "#desktop"
render: (p) ->
_GUI.loadScheme p, @, @parent
quit: () ->
evt = new _GUI.BaseEvent("exit")
@onexit(evt)
if not evt.prevent
delete @.observable
_PM.kill @
init: ->
#implement by sub class
onexit: (e) ->
#implement by subclass
on: (e, f) -> @observable.on e, f
trigger: (e, d) -> @observable.trigger e, d
subscribe: (e, f) -> _MAIL.on e, f, @
meta: () -> _APP[@name].meta
publish: (t, m) ->
mt = @meta()
_MAIL.trigger t, { id: @pid, name: @name, data: { m: m, icon: mt.icon, iconclass: mt.iconclass } }
notify: (m) ->
@publish "notification", m
warn: (m) ->
@publish "warning", m
error: (m) ->
@publish "error", m
fail: (m) ->
@publish "fail", m
find: (id) -> ($ "[data-id='#{id}']", @scheme)[0] if @scheme
this.OS.GUI.BaseModel = BaseModel

View File

@ -1,12 +1,11 @@
MAIL = this.OS.courrier
_API = this.OS.API
_PM = this.OS.PM
class BaseService
constructor: (@name) ->
class BaseService extends this.OS.GUI.BaseModel
constructor: (name) ->
super name
@icon = undefined
@iconclass = "fa-paper-plane-o"
@text = ""
@_api = _API
@timer = undefined
@holder = undefined
@ -15,26 +14,29 @@ class BaseService
# event registe, etc
# scheme loader
attach: (h) -> @holder = h
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: ()->
onexit: (evt) ->
console.log "clean timer" if @timer
clearTimeout @timer if @timer
@cleanup()
_PM.kill @
@cleanup(evt)
($ @scheme).remove() if @scheme
main: () ->
show: () ->
awake: () ->
awake: (e) ->
#implement by user to tart the service
cleanup:() ->
cleanup: (evt) ->
#implemeted by user
BaseService.type = 2
BaseService.singleton = true
this.OS.GUI.BaseService = BaseService

View File

@ -5,21 +5,19 @@ self.OS.API =
handler: new Object()
#request a user data
request: (query,callback) ->
request: (query, callback) ->
# definition here
handle.request query,callback
handle.request query, callback
systemConfig: ->
_API.request 'config', (result) ->
console.log result
get:(p,c,f)->
$.get p
.done (data) ->
c(data)
.fail ->
f()
resource: (resource,callback) ->
get: (p, c, f) ->
$.get p
.done (data) -> c(data)
.fail -> f()
resource: (resource, callback) ->
path = "resources/#{resource}"
_API.get path,callback
_API.get path, callback

69
src/core/core.coffee Normal file
View File

@ -0,0 +1,69 @@
#define the OS object
self = this
self.OS or=
API: new Object()
GUI: new Object()
APP: new Object()
courrier:
observable: riot.observable()
listeners: new Object
on: (e, f, a) ->
_courrier.listeners[a.pid] = [] unless _courrier.listeners[a.pid]
_courrier.listeners[a.pid].push { e: e, f: f }
_courrier.observable.on e, f
trigger: (e, d) -> _courrier.observable.trigger e, d
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]
delete _courrier.listeners[app.pid]
_courrier.listeners[app.pid] = []
register: (name, x) -> _APP[name] = x
PM:
pidalloc: 0
processes: new Object
createProcess: (app, cls) ->
#if it is single ton
# and a process is existing
# just return it
if cls.singleton and _PM.processes[app] and _PM.processes[app].length == 1
_PM.processes[app][0].show()
else
_PM.processes[app] = [] if not _PM.processes[app]
obj = new cls
obj.birth = (new Date).getTime()
_PM.pidalloc++
obj.pid = _PM.pidalloc
_PM.processes[app].push obj
if cls.type is 1 then _GUI.dock obj, cls.meta else _GUI.attachservice obj
if cls.type is 2
_courrier.trigger "srvroutineready", app
appByPid: (pid) ->
app = undefined
find = (l) ->
return a for a in l when a.pid is pid
for k, v of _PM.processes
app = find v
break if app
app
kill: (app) ->
return if 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
_courrier.unregister app
delete _PM.processes[app.name][i]
_PM.processes[app.name].splice i, 1
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"]

View File

@ -5,17 +5,22 @@ self.OS.GUI =
data: "#{_GUI.tagPath}/tags.json"
self.OS.API.request query, ()->
loadScheme: (path, app) ->
loadScheme: (path, app, parent) ->
_API.get path,
(x) ->
return null unless x
scheme = $.parseHTML x
($ "#desktop").append scheme
($ parent).append scheme
riot.mount ($ scheme), { observable: app.observable }
app.scheme = scheme[0]
app.main()
app.show()
, (f) ->
_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) ->
@ -23,6 +28,13 @@ self.OS.GUI =
$ "head link#ostheme"
.attr "href", path
pushServices: (srvs) ->
f = (v) ->
_courrier.observable.one "srvroutineready", () -> _GUI.pushService v
_GUI.pushService srvs[0]
srvs.splice 0, 1
f i for i in srvs
pushService: (srv) ->
return _PM.createProcess srv, _APP[srv] if _APP[srv]
path = "services/#{srv}.js"
@ -30,9 +42,10 @@ self.OS.GUI =
.done (e, s) ->
_PM.createProcess srv, _APP[srv]
.fail (e, s) ->
_courrier.trigger "srvroutineready", srv
_courrier.trigger "fail",
{ m: "Cannot read service script: #{srv} ",
e: e, s: s }
{ id:0,data:{m: "Cannot read service script: #{srv} ", e: e, s: s },
name:"0S"}
launch: (app) ->
if not _APP[app]
@ -54,14 +67,13 @@ self.OS.GUI =
console.log "Fist time loading " + app
, (e, s) ->
_courrier.trigger "fail",
{ m: "Cannot read application metadata: #{app} ",
e: e, s: s }
{id:0, data:{ m: "Cannot read application metadata: #{app} ",e: e, s: s }, name:"OS"}
alert "cannot read application, meta-data"
.fail (e,s) ->
#BUG report here
_courrier.trigger "fail",
{ m: "Cannot load application script: #{app}",
e: e, s:s }
{id :0, data:{m: "Cannot load application script: #{app}",
e: e, s:s }, name:"OS"}
console.log "bug report", e, s, path
else
# now launch it

View File

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

View File

@ -1,28 +0,0 @@
afx-sys-panel{
padding:0;
margin: 0;
}
afx-sys-panel div{
width: 100%;
height: 23px;
margin:0;
padding: 0;
background-color: #e7e7e7;
border-bottom: 1px solid #9c9C9C;
box-shadow: 1px 1px 1px #9F9F9F;
position:absolute;
}
afx-sys-panel .afx-panel-os-menu{
padding:0;
margin: 0;
float:left;
}
afx-sys-panel .afx-panel-os-stray{
float:right;
}
afx-sys-panel .afx-panel-os-stray afx-menu afx-menu{
top:-4px;
right:0;
}

View File

@ -1,36 +0,0 @@
self.OS.PM =
pidalloc: 0
processes: new Object
createProcess: (app, cls) ->
#if it is single ton
# and a process is existing
# just return it
if cls.singleton and _PM.processes[app] and _PM.processes[app].length == 1
_PM.processes[app][0].show()
return _PM.processes[app][0]
else
_PM.processes[app] = [] if not _PM.processes[app]
obj = new cls
obj.birth = (new Date).getTime()
_PM.pidalloc++
obj.pid = _PM.pidalloc
_PM.processes[app].push obj
if cls.type is 1 then _GUI.dock obj, cls.meta else _GUI.attachservice obj
appByPid:(pid)->
app = undefined
find = (l) ->
return a for a in l when a.pid is pid
for k, v of _PM.processes
app = find v
break if app
app
kill: (app) ->
return if not _PM.processes[app.name]
i = _PM.processes[app.name].indexOf app
if i >= 0
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]
_PM.processes[app.name].splice i, 1

View File

@ -0,0 +1,36 @@
<afx-dummy>
<afx-overlay data-id = "notifyzone" width = "250">
<afx-list-view data-id="notifylist"></afx-list-view>
<style>
afx-overlay[data-id = "notifyzone"]{
background-color: rgba(215,215,215,0.7);
overflow-y: auto;
overflow-x: hidden;
padding:3px;
margin: 0;
}
afx-list-view[data-id = "notifylist"]
{
padding:0;
}
afx-list-view[data-id = "notifylist"] li{
border:1px solid #a6a6a6;
border-radius: 6px;
margin-bottom: 2px;
}
</style>
</afx-overlay>
<afx-feed data-id = "notifeed" style = "display: none;" closable="true">
<!--afx-button text = "click me"></afx-button-->
<style>
afx-feed[data-id = "notifeed"]{
position: absolute;
width: 250px;
}
afx-feed[data-id = "notifeed"] > div{
box-shadow: 1px 1px 1px #9f9F9F;
}
</style>
</afx-feed>
</afx-dummy>

View File

@ -104,7 +104,7 @@
else
self.root.observable.trigger("focus")
})
self.root.observable.trigger("loaded", self.root)
self.root.observable.trigger("rendered", self.root)
})
var enable_dragging = function()
{

View File

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

35
src/core/tags/afx-feed.js Normal file
View File

@ -0,0 +1,35 @@
<afx-feed>
<div>
<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
this.icon = opts.icon
this.iconclass = opts.iconclass
this.closable = opts.closable
this.header = opts.header||""
this.text = opts.text || ""
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]
}
</script>
</afx-feed>

View File

@ -8,11 +8,12 @@
<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 }
<i if = {closable} class = "closable" click = {parent._remove}></i>
</li>
</ul>
</div>
<script>
this.items = opts.child
this.items = opts.child || []
var self = this
self.selidx = -1
self.selectedText = ""
@ -34,7 +35,16 @@
return self.items[self.selidx]
return self[k]
}
self.root.push = function(e,u)
{
self.items.push(e)
if(u) self.update()
}
self.root.unshift = function(e,u)
{
self.items.unshift(e)
if(u) self.update()
}
if(opts.observable)
this.root.observable = opts.observable
else
@ -72,6 +82,17 @@
$(self.refs.mlist).css("top","100%")
$(self.refs.mlist).show()
}
_remove(event)
{
if(self.selidx != -1)
{
self.items[self.selidx].selected =false
self.selidx = -1
}
self.items.splice(self.items.indexOf(event.item),1)
event.target = self.root
self.update()
}
_select(event)
{
var data = {
@ -81,7 +102,10 @@
if(self.selidx != -1)
self.items[self.selidx].selected =false
self.selidx = data.idx
self.items[self.selidx].selected = true
if(!self.items[self.selidx])
return
self.items[self.selidx].selected = true
if(opts.dropdown == "true")
{
$(self.refs.mlist).hide()
@ -90,7 +114,7 @@
if(self.onlistselect)
self.onlistselect(data)
this.root.observable.trigger('listselect',data)
event.preventDefault()
//event.preventDefault()
}
</script>
</afx-list-view>

View File

@ -1,14 +1,14 @@
<afx-menu >
<ul class={context: opts.context == "true"}>
<li class="afx-corner-fix"></li>
<li ref = "container" each={ item,i in items } class = {afx_submenu:item.child != null, fix_padding:item.icon} no-reorder>
<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={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 }
<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 }
</a>
<afx-menu if={item.child != null} child={item.child} observable = {parent.root.observable} rootid = {parent.rid}></afx-menu>
<afx-menu if={data.child != null} child={data.child} onmenuselect = {data.onmenuselect} observable = {parent.root.observable} rootid = {parent.rid}></afx-menu>
</li>
<li class="afx-corner-fix"></li>
</ul>
@ -126,8 +126,9 @@
onselect(event)
{
var data = {id:self.rid, data:event.item.item, root:isRoot}
var data = {id:self.rid, root:isRoot, e:event}
this.root.observable.trigger('menuselect',data)
if( this.onmenuselect && !isRoot) this.onmenuselect(data)
event.preventDefault()
$(document).unbind("click",mnhide)
if(opts.context == "true") return

View File

@ -0,0 +1,45 @@
<afx-overlay>
<yield/>
<script>
this.width = opts.width || 200
this.height = opts.height || 400
var self = this;
self.commander = null
this.root.observable = opts.observable || riot.observable()
var id = $(self.root).attr("data-id")
var calibre_size = function()
{
$(self.root)
.css("width", self.width + "px")
.css("height", self.height + "px")
self.root.observable.trigger("resize", {id:id,w:self.width,h:self.height})
}
self.root.set = function(k,v)
{
if(k == "*")
for(var i in v)
self[i] = v[i]
else
self[k] = v
if( k == "width" || k == "height")
calibre_size()
self.update()
}
self.root.get = function(k)
{
return self[k]
}
self.on("mount", function(){
$(self.root)
.css("position", "absolute")
//.css("z-index",1000000)
$(self.root).children().each(function(e){
this.observalbe = self.root.observalbe
})
calibre_size()
self.root.observable.trigger("rendered", self.root)
})
</script>
</afx-overlay>

View File

@ -15,23 +15,31 @@
{text:"NotePad",type:"app", iconclass:"fa fa-commenting"},
{text:"ActivityMonitor",type:"app"},
{text:"DummyApp",type:"app"}
]},
],
onmenuselect: function(d)
{
if(d.e.item.data.type == "app")
window.OS.GUI.launch(d.e.item.data.text)
}
},
{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()}}
this.systray = {
child: [],
onmenuselect: function(d){
if(d.root)
d.e.item.data.awake(d.e)
}
}
var self = this
self.root.attachservice = function(s)
{
s.attach(self.refs.aTray)
self.refs.aTray.root.unshift(s,true)
s.attach(self.refs.aTray)
}
self.root.detachservice = function(s)
{

View File

@ -1,23 +0,0 @@
#define the OS object
self = this
self.OS or=
API: new Object()
GUI: new Object()
APP: new Object()
PM: new Object()
courrier: riot.observable()
register: (name,x)->
# load the metadata first
_APP[name] = x
boot: ->
#first load the configuration
#then load the theme
_GUI = self.OS.GUI
_GUI.loadTheme "antos"
_GUI.initDM()
_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.quit() if app
header = [{width:50,value:"Pid"},{value:"Name"}, {value:"Type", width:75},{width:70,value:"Alive (ms)"}]
header = [{width:50,value:"Pid"},{value:"Name"}, {value:"Type", width:80},{width:75,value:"Alive (ms)"}]
@gdata =
processes:{}
alive:[]

View File

@ -1,10 +1,12 @@
_GUI = this.OS.GUI
class DummyApp extends this.OS.GUI.BaseApplication
constructor: () ->
super "DummyApp"
main: () ->
self = @
@on "btclick", (e)->
alert "#{self.name}: Happy pola"
self.notify "this is a dummy notify"
_GUI.pushService "Budgy"
@on "resize", (w,h)->
console.log "#{self.name}: resize"
#@on "listselect", (i)->

View File

@ -13,10 +13,10 @@ class Calendar extends this.OS.GUI.BaseService
"#{now.getHours()}:#{now.getMinutes()}:#{now.getSeconds()}"
me.update()
awake: ->
awake: (e) ->
console.log @name,@pid
# do nothing
cleanup: ->
cleanup: (evt) ->
console.log "cleanup for quit"
# do nothing

View File

@ -2,12 +2,74 @@ class PushNotification extends this.OS.GUI.BaseService
constructor: () ->
super "PushNotification"
@iconclass = "fa fa-commenting"
@onmenuselect = (e) -> console.log e
@cb = undefined
init: ->
# do nothing
awake: ->
console.log @name,@pid
cleanup: ->
@view = false
path = "resources/schemes/notifications.html"
@render path
main: ->
me = @
mfeed = @find "notifeed"
@scheme = @find "notifyzone"
mlist = @find "notifylist"
@subscribe "notification", (o) ->
d = {
header: "#{o.name} (#{o.id})"
text: "INFO: #{o.name} (#{o.id}): #{o.data.m}",
lite: o.data.m
icon: o.data.icon,
iconclass: o.data.iconclass,
closable: true }
mlist.push d, true
me.notifeed d, mfeed
@subscribe "fail", (o) ->
d = {
header: "#{o.name} (#{o.id})"
text: "FAIL: #{o.name} (#{o.id}): #{o.data.m}",
lite: o.data.m
icon: o.data.icon,
iconclass: o.data.iconclass,
closable: true }
mlist.push d, true
me.notifeed d, mfeed
($ @scheme).css "right", 0
.css "top", "-3px"
.css "height", ""
.css "bottom", "0"
.hide()
($ mfeed).css "right", "5px"
.css "top", "0"
notifeed: (d, mfeed) ->
mfeed.set "*", d
($ mfeed).show()
timer = setTimeout () ->
($ mfeed).hide()
clearTimeout timer
, 3000
awake: (e) ->
if @view then ($ @scheme).hide() else ($ @scheme).show()
@view = not @view
me = @
if not @cb
@cb = (e) ->
return if e.originalEvent.item and e.originalEvent.item.closable
if not ($ e.target).closest($ me.scheme).length and not ($ e.target).closest($ me.holder.root).length
($ me.scheme).hide()
$(document).unbind "click", me.cb
me.view = not me.view
if @view
$(document).on "click", @cb
else
$(document).unbind "click", @cb
cleanup: (evt) ->
# do nothing
this.OS.register "PushNotification",PushNotification

View File

@ -2,12 +2,19 @@ class Spotlight extends this.OS.GUI.BaseService
constructor: () ->
super "Spotlight"
@iconclass = "fa fa-search"
init: ->
@child = [
{
text: "#{@.name} (#{@.pid}): dummy notif",
child: [ { text: "submenu" } ]
}
]
# do nothing
awake: ->
console.log @name,@pid
cleanup: ->
main: ->
awake: (e) ->
console.log @name ,@pid
cleanup: (evt) ->
# do nothing
this.OS.register "Spotlight",Spotlight

View File

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

@ -24,6 +24,7 @@ afx-list-view li{
padding-bottom: 3px;
color: #414339;
background-color: white;
position: relative;
}
afx-list-view li:nth-child(odd){
background-color: #f5F5F5;
@ -34,6 +35,22 @@ afx-list-view i.icon-style {
display: inline-block;
float:left;
}
afx-list-view i.closable{
width: 16px;
height: 16px;
display: inline-block;
cursor: pointer;
}
afx-list-view i.closable:before{
content: "\f00d";
font-family: "FontAwesome";
font-size: 10px;
right:5px;
color: #414339;
position:absolute;
font-style: normal;
top:5px;
}
afx-list-view li > i {
margin-right: 3px;

View File

@ -0,0 +1,59 @@
afx-sys-panel{
padding:0;
margin: 0;
}
afx-sys-panel div{
width: 100%;
height: 23px;
margin:0;
padding: 0;
background-color: #e7e7e7;
border-bottom: 1px solid #9c9C9C;
box-shadow: 1px 1px 1px #9F9F9F;
position:absolute;
}
afx-sys-panel .afx-panel-os-menu{
padding:0;
margin: 0;
float:left;
}
afx-sys-panel .afx-panel-os-stray{
float:right;
position: relative;
}
afx-sys-panel afx-menu.afx-panel-os-stray afx-menu {
right: 0;
left: calc(100% - 170px);
position: absolute;
}
afx-sys-panel afx-menu.afx-panel-os-stray afx-menu li.afx_submenu a{
margin-left: 10px;
}
afx-sys-panel afx-menu.afx-panel-os-stray afx-menu li.afx_submenu:before {
content: "\f054";
font-family: "FontAwesome";
font-size: 10px;
color: #414339;
position:absolute;
text-align: left;
left:5px;
top:25%;
}
afx-sys-panel afx-menu.afx-panel-os-stray afx-menu afx-menu{
left: -100%;
right: 100%;
top:-4px;
}
afx-sys-panel afx-menu.afx-panel-os-stray afx-menu ul{
border:1px solid #a6a6a6;
border-radius: 5px;
border-top-right-radius: 0px;
}
afx-sys-panel afx-menu.afx-panel-os-stray afx-menu li{
min-width: 150px;
}

View File

Before

Width:  |  Height:  |  Size: 434 KiB

After

Width:  |  Height:  |  Size: 434 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB