mirror of
https://github.com/lxsang/antos-frontend.git
synced 2024-12-26 01:18:21 +01:00
use services to communicate between apps
This commit is contained in:
parent
16074ac3f8
commit
8fbd0b4a98
74
Makefile
74
Makefile
@ -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:
|
||||
|
@ -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
50
src/core/BaseModel.coffee
Normal 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
|
@ -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
|
@ -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
69
src/core/core.coffee
Normal 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"]
|
@ -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
|
@ -1,3 +0,0 @@
|
||||
<afx-service>
|
||||
<yield/>
|
||||
</afx-service>
|
@ -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;
|
||||
}
|
@ -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
|
36
src/core/schemes/notifications.html
Normal file
36
src/core/schemes/notifications.html
Normal 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>
|
@ -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()
|
||||
{
|
3
src/core/tags/afx-dummy.js
Normal file
3
src/core/tags/afx-dummy.js
Normal file
@ -0,0 +1,3 @@
|
||||
<afx-dummy>
|
||||
<yield/>
|
||||
</afx-dummy>
|
35
src/core/tags/afx-feed.js
Normal file
35
src/core/tags/afx-feed.js
Normal 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>
|
@ -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>
|
@ -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
|
45
src/core/tags/afx-overlay.js
Normal file
45
src/core/tags/afx-overlay.js
Normal 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>
|
@ -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)
|
||||
{
|
@ -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"
|
||||
|
@ -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:[]
|
||||
|
@ -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)->
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
@ -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
|
44
src/themes/antos/afx-feed.css
Normal file
44
src/themes/antos/afx-feed.css
Normal 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;
|
||||
}
|
@ -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;
|
59
src/themes/antos/afx-sys-panel.css
Normal file
59
src/themes/antos/afx-sys-panel.css
Normal 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;
|
||||
}
|
Before Width: | Height: | Size: 434 KiB After Width: | Height: | Size: 434 KiB |
Before Width: | Height: | Size: 1.7 MiB After Width: | Height: | Size: 1.7 MiB |
Loading…
Reference in New Issue
Block a user