core for app development

This commit is contained in:
Xuan Sang LE 2017-08-14 00:20:19 +02:00
parent f4c54c712d
commit 2985689217
43 changed files with 1414 additions and 172 deletions

View File

@ -1,14 +1,16 @@
BUILDDIR = build/htdocs
BLUE=\033[0;34m
BLUE=\033[1;34m
NC=\033[0m
coffees= src/define.coffee\
src/core/apis/api.coffee\
src/core/apis/handlers/InBrowserHandler.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/BaseEvent.coffee\
src/antos.coffee
tags= src/core/gui/tags/afx-button.js\
@ -18,7 +20,9 @@ tags= src/core/gui/tags/afx-button.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-list-view.js\
src/core/gui/tags/afx-tree-view.js \
src/core/gui/tags/afx-grid-view.js
antos_themes = src/core/gui/themes/antos/font-awesome.css\
src/core/gui/themes/antos/ubuntu-regular.css\
@ -28,19 +32,23 @@ antos_themes = src/core/gui/themes/antos/font-awesome.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-app-window.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
packages = NotePad
main: build_coffee build_tag build_theme schemes libs packages_builds
packages = NotePad Terminal ActivityMonitor
main: clean build_coffee build_tag build_theme schemes libs build_packages
- cp src/index.html $(BUILDDIR)/
#%.js: %.coffee
# coffee --compile $<
build_coffee:
- echo "$(BLUE)=======Building coffee files=======$(NC)"
@echo "$(BLUE)=======Building coffee files=======$(NC)"
- mkdir $(BUILDDIR)/scripts
- rm $(BUILDDIR)/scripts/antos.js
for f in $(coffees); do (cat "$${f}"; echo) >> $(BUILDDIR)/scripts/antos.coffee; done
@ -49,36 +57,37 @@ build_coffee:
libs:
- echo "$(BLUE)=======Copy lib files=======$(NC)
- cp -rf src/libs/* $(BUILDDIR)/scripts
@echo "$(BLUE)=======Copy lib files=======$(NC)"
cp -rf src/libs/* $(BUILDDIR)/scripts/
schemes:
- echo "$(BLUE)=======Copy schemes files======= $(NC)"
@echo "$(BLUE)=======Copy schemes files======= $(NC)"
- mkdir -p $(BUILDDIR)/resources/schemes
- cp src/core/gui/schemes/* $(BUILDDIR)/resources/schemes
cp src/core/gui/schemes/* $(BUILDDIR)/resources/schemes/
build_tag:
- echo "=======$(BLUE)Building tag files=======$(NC)"
@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
for f in $(tags); do (cat "$${f}"; echo) >> $(BUILDDIR)/resources/antos_tags.js; done
build_theme: antos_themes_build
antos_themes_build:
- echo "=======$(BLUE)Building themes name: antos=======$(NC)"
@echo "=======$(BLUE)Building themes name: antos=======$(NC)"
-rm -rf $(BUILDDIR)/resources/themes/antos/*
-mkdir -p $(BUILDDIR)/resources/themes/antos
- for f in $(antos_themes); do (cat "$${f}"; echo) >> $(BUILDDIR)/resources/themes/antos/antos.css; done
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/core/gui/themes/antos/fonts/* $(BUILDDIR)/resources/themes/antos/fonts
cp src/core/gui/themes/antos/wallpaper.jpg $(BUILDDIR)/resources/themes/antos/
packages_builds:
build_packages:
- mkdir $(BUILDDIR)/packages
- 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 src/packages/$$d/build && rm -r src/packages/$$d/build ); 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 src/packages/$$d/build && rm -r src/packages/$$d/build ); done
clean:
rm -rf $(BUILDDIR)/*

View File

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

View File

@ -13,13 +13,12 @@ self.OS.API =
_API.request 'config', (result) ->
console.log result
get:(p,c)=>
get:(p,c,f)->
$.get p
.done (data) ->
c(data)
.fail ->
alert "cannot get data"
c(null)
f()
resource: (resource,callback) ->
path = "resources/#{resource}"
_API.get path,callback

View File

@ -1,21 +1,88 @@
self = this
_PM = self.OS.PM
_APP = self.OS.APP
class BaseApplication
constructor: (@name) ->
@observable = riot.observable()
@pid = 0
@_api = self.OS.API
init: ->
#first load the scheme
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
me.appmenu.set "items", (me.baseMenu() || [])
me.appmenu.set "onmenuselect", (d)->
me.trigger("menuselect",d)
@on "hide", ()->
me.sysdock.set "selectedApp", null
me.appmenu.set "items",[]
@on "menuselect", (item) ->
switch 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"
@scheme = _GUI.loadScheme path,@observable
#if(!scheme) bug repporter go here
@event()
event: ->
#implement by subclasses
_GUI.loadScheme path ,this
on: (e,f) -> @observable.on e,f
trigger:(e,d) -> @observable.trigger e,d
show: () ->
@observable.trigger "focus"
blur: () ->
@.appmenu.set "items",[] if @.appmenu and @.pid == @.appmenu.pid
@observable.trigger "blur"
hide: () ->
@observable.trigger "hide"
toggle:() ->
@observable.trigger "toggle"
quit: () ->
evt = new _GUI.BaseEvent("exit")
@exit(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 =
[{
text:_APP[@name].meta.name,
child:[
{text:"About", dataid:"#{@name}-about"},
{text:"Exit", dataid:"#{@name}-exit"}
]
}]
menu = menu.concat @menu() || []
menu
main: ->
#main program
# implement by subclasses
menu: ->
# implement by subclasses
# to add menu to application
[]
open:->
#implement by subclasses
data:->
#implement by subclasses
# to return app data
update:->
#implement by subclasses
this.OS.GUI.BaseApplication = BaseApplication
exit: (e) ->
#implement by subclasses
# to handle the exit event
# use e.preventDefault() to
# discard the quit command
this.OS.GUI.BaseApplication = BaseApplication

View File

@ -0,0 +1,7 @@
class BaseEvent
constructor: (@name) ->
@prevent = false
preventDefault:()->
@prevent = true
this.OS.GUI.BaseEvent = BaseEvent

View File

@ -1,82 +1,109 @@
self.OS.GUI =
tagPath: "resources/tags/"
init: () ->
query =
path: 'VFS/get'
data: "#{_GUI.tagPath}/tags.json"
self.OS.API.request query, ()->
loadScheme: (path, obs) ->
_API.get path, (x) ->
loadScheme: (path,app) ->
_API.get path,
(x) ->
return null unless x
scheme = $.parseHTML x
scheme = $.parseHTML x
($ "#desktop").append scheme
riot.mount ($ scheme), {observable:obs}
scheme
riot.mount ($ scheme), {observable:app.observable}
app.scheme = scheme[0]
app.show()
app.main()
, (f) ->
alert "cannot load scheme"
loadTheme: (name) ->
path = "resources/themes/#{name}/#{name}.css"
$ "head link#ostheme"
.attr "href", path
launch: (app) ->
if not _APP[app]
# first load it
path = "packages/#{app}/main.js"
$.getScript path
path = "packages/#{app}/"
$.getScript path + "main.js"
.done (e,s) ->
#load css file
$.get "#{path}main.css", () ->
$ '<link>', {rel:'stylesheet', type:'text/css', 'href':"#{path}main.css"}
.appendTo 'head'
#launch
_app = new _APP[app]
_app.init()
console.log "Fist time loading "+app
if _APP[app]
# load app meta data
_API.get "#{path}package.json",
(data) ->
_APP[app].meta = data
_PM.createProcess app, _APP[app]
console.log "Fist time loading "+app
,(e,s)->
alert "cannot read application, meta-data"
.fail (e,s) ->
#BUG report here
console.log "bug report"
else
# now launch it
_app = new _APP[app]
_app.init()
# now launch it
if _APP[app]
_PM.createProcess app, _APP[app]
dock: (app,meta) ->
# dock an application to a dock
# create a data object
data =
icon:null
iconclass:meta.iconclass||""
app:app
onbtclick:() ->
app.toggle()
data.icon = "packages/#{meta.app}/#{meta.icon}" if meta.icon
data.iconclass = "fa fa-cogs" if (not meta.icon) and (not meta.iconclass)
dock = $ "#sysdock"
dock.get(0).newapp data
app.sysdock = dock.get(0)
app.appmenu = ($ "[data-id = 'appmenu']","#syspanel")[0]
app.init()
#app.show() -- notwork, sice the scheme is not loaded yet
undock: (app) ->
($ "#sysdock").get(0).removeapp app
initDM: ->
_API.resource "schemes/dm.html", (x) ->
return null unless x
scheme = $.parseHTML x
($ "#wrapper").append scheme
#riot.mount $ "#button", $ "#wrapper"
($ "#desktop").on "click", (e)->
return if e.target isnt ($ "#desktop").get(0)
($ "#sysdock").get(0).set "selectedApp",null
osmenu = {child:[
{text:"",icon:"fa fa-circle", child:[
{text:"",iconclass:"fa fa-eercast", child:[
{text:"About"},
{text:"System Preferences", icon:"fa fa-commenting"},
{text:"Applications",child:[{text:"Terminal"},{text:"Text edit"}]},
{text:"System Preferences", iconclass:"fa fa-commenting"},
{text:"Applications",child:[
{text:"Terminal",type:"app"},
{text:"NotePad",type:"app", icon:"packages/NotePad/icon.png"},
{text:"ActivityMonitor",type:"app"}
]},
{text:"Logout"}
]}
],
onmenuselect: (item)->
console.log item
_GUI.launch "NotePad"
],onmenuselect: (item)->
switch item.data.type
when "app" then _GUI.launch item.data.text
}
appmenu = {child:[
{text:"Text edit", child:[
{text:"About"},
{text:"Preferences"},
{text:"Exit"}
]},
{text:"File",child:[
{text:"Open"},{text:"Save"}]}
],
onmenuselect: (item)-> console.log item}
appmenu = {child:[]}
systray = {child:[
{text:"Sun 22:57 6 August 2017"},
{text:"",icon:"fa fa-search"},
{text:"",icon:"fa fa-commenting"}
{text:"",iconclass:"fa fa-search"},
{text:"",iconclass:"fa fa-commenting"}
],
onmenuselect: (item)->
console.log item
],onmenuselect: (item)->
console.log item
}
riot.mount ($ "#syspanel", $ "#wrapper"),{osmenu:osmenu,appmenu:appmenu,systray:systray}
docks = {items:[
{icon:"fa fa-cogs"},
{icon:"fa fa-life-ring"},
{icon:"fa fa-cubes"}
]}
riot.mount ($ "#sysdock", $ "#wrapper"), docks
riot.mount ($ "#sysdock", $ "#wrapper"), {items:[]}

View File

@ -1,8 +1,8 @@
<afx-app-window ref = "window">
<div class = "afx-window-wrapper" >
<ul class= "afx-window-top">
<li class = "afx-window-close"></li>
<li class = "afx-window-minimize"></li>
<afx-app-window ref = "window" >
<div class = "afx-window-wrapper">
<ul class= "afx-window-top" >
<li class = "afx-window-close" onclick = {close}></li>
<li class = "afx-window-minimize" onclick = {minimize}></li>
<li class = "afx-window-maximize" onclick={maximize}></li>
<li ref = "dragger" class = "afx-window-title">{ apptitle }</li>
</ul>
@ -25,6 +25,32 @@
var height = opts.height || 300
this.root.observable = opts.observable || riot.observable()
if(!window._zidex) window._zidex = 10
this.shown = false
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()
}
minimize()
{
this.root.observable.trigger("hide")
}
close()
{
this.root.observable.trigger("exit")
}
this.on('mount', function() {
var left,top
left = 20 + Math.floor(Math.random() * width)
@ -37,8 +63,13 @@
.css("height", height + "px")
.css("z-index",window._zidex++)
$(self.refs.window).on("mousedown", function(e){
window._zidex++
$(self.refs.window).css("z-index",window._zidex)
if(self.shown == false)
self.root.observable.trigger("focus")
})
$(self.refs.window).click(function(e) {
//e.stopPropagation()
//e.windowactive = true
//self.root.observable.trigger("windowselect")
})
enable_dragging()
if(isResize)
@ -49,6 +80,34 @@
$(self.refs.content).children().each(function(e){
this.observable = self.root.observable
})
self.root.observable.on("focus",function(){
window._zidex++
$(self.refs.window)
.show()
.css("z-index",window._zidex)
.removeClass("unactive")
self.shown = true
})
self.root.observable.on("blur", function(){
self.shown = false
$(self.refs.window)
.addClass("unactive")
// add css to blur app :)
})
self.root.observable.on("hide", function()
{
$(self.refs.window).hide()
self.shown = false
})
self.root.observable.on("toggle", function(){
if(self.shown)
self.root.observable.trigger("hide")
else
self.root.observable.trigger("focus")
})
})
var enable_dragging = function()
{
@ -112,7 +171,8 @@
.css("width", w +"px")
.css("height",h + "px")
isMaxi = false
self.root.observable.trigger('resize',w,h)
self.root.observable.trigger('resize',
{id:$(self.root).attr("data-id"),w:w,h:h})
})
$(window).on("mouseup", function(e){
$(window).unbind("mousemove", null)
@ -137,7 +197,8 @@
.css("width", w + "px")
.css("height", h + "px")
.css("top","0").css("left","0")
self.root.observable.trigger('resize',w,h)
self.root.observable.trigger('resize',
{id:$(self.root).attr("data-id"),w:w,h:h})
isMaxi = true
}
else
@ -147,7 +208,8 @@
.css("width",history.width)
.css("height",history.height)
.css("top",history.top).css("left",history.left)
self.root.observable.trigger('resize',history.width, history.height)
self.root.observable.trigger('resize',
{id:$(self.root).attr("data-id"),w:history.width,h:history.height} )
}
}

View File

@ -1,7 +1,60 @@
<afx-apps-dock>
<afx-button each={ items } icon = {icon} text = {text}>
<afx-button class = {selected: parent.selectedApp && app.pid == parent.selectedApp.pid} each={ items } icon = {icon} text = {text} onbtclick = {onbtclick}>
</afx-button>
<script>
this.items = opts.items
this.items = opts.items || []
var self = this
self.selectedApp = null
self.root.set = function(k,v)
{
if(k == "*")
for(var i in v)
self[i] = v[i]
else
{
self[k] = v
if(k == "selectedApp")
{
for(var i in self.items)
self.items[i].app.blur()
//v.show()
}
}
self.update()
}
self.root.newapp = function(i)
{
self.items.push(i)
self.selectedApp = i.app
self.update()
for(var i in self.items)
self.items[i].app.blur()
}
self.root.removeapp = function(a)
{
var i = -1;
for(var k in self.items)
if(self.items[k].app.pid == a.pid)
{
i = k; break;
}
if(i != -1)
{
delete self.items[i].app
self.items.splice(i,1)
self.update()
}
}
self.root.get = function(k)
{
return self[k]
}
self.root.update = function()
{
self.update()
}
</script>
</afx-apps-dock>

View File

@ -1,20 +1,41 @@
<afx-button>
<button disabled={ enable == "false" } onclick="{ _onbtclick }" >
<i class = { icon } ></i>
<i if={iconclass} class = {iconclass} ></i>
<i if={icon} class="icon-style" style = { "background: url("+icon+");background-size: 100% 100%;background-repeat: no-repeat;" }></i>
{ opts.text }
</button>
<script>
this.enable = opts.enable
this.icon = opts.icon
this.iconclass = opts.iconclass
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._onbtclick = function(e)
{
if(opts.onbtclick)
eval(opts.onbtclick)
if(typeof opts.onbtclick == 'string')
eval(opts.onbtclick())
else if(opts.onbtclick)
opts.onbtclick()
if(self.root.observable)
{
console.log("btclick")
self.root.observable.trigger("btclick",this)
self.root.observable.trigger("btclick",{id:$(self.root).attr("data-id"),data:self.root})
}
}
</script>

View File

@ -0,0 +1,162 @@
<afx-grid-view>
<afx-grid-row ref="gridhead" rootid = {rid} observable = {root.observable} header="true" class = {grid_row_header:header} if = {header} cols = {header}> </afx-grid-row>
<div ref = "scroller" style="width:100%; overflow:auto;">
<div ref = "container">
<afx-grid-row each={ child, i in rows } class = {selected: child.selected} rootid = {parent.rid} observable = {parent.root.observable} cols = {child} onclick = {parent._select}></afx-grid-row>
</div>
</div>
<script>
this.rows= []
if(opts.data)
{
this.header = opts.data.header
this.rows = opts.data.data
}
var self = this
this.rid = $(self.root).attr("data-id")
self.selidx = -1
self.nrow = 0
self.root.set = function(k,v)
{
if(k == "selected")
self._select({item:self.rows[v], preventDefault:function(){}})
else if(k == "*")
for(var i in v)
self[i] = v[i]
else
self[k] = v
self.update()
}
var calibrate_size = function()
{
if(self.header)
{
$(self.refs.scroller).css("height",
$(self.root).height() - $(self.refs.gridhead.root).height()
+ "px")
}
else
$(self.refs.scroller).css("height","100%")
}
self.root.get = function(k)
{
if(k == "selected")
return (self.selidx == -1?null:self.rows[self.selidx])
return self[k]
}
if(opts.observable)
this.root.observable = opts.observable
else
{
this.root.observable = riot.observable()
}
this.on("mount", function(){
$(self.refs.container)
.css("display","flex")
.css("flex-direction","column")
.css("width","100%")
calibrate_size()
this.root.observable.on("resize",function(){
calibrate_size()
if(self.refs.gridhead)
self.refs.gridhead.calibrate_size()
})
})
this.on("updated",function(){
if(self.selidx >= self.rows.length)
self.selidx = -1
if(self.nrow == self.rows.length) return
self.nrow = self.rows.length
calibrate_size()
if(self.refs.gridhead)
self.refs.gridhead.calibrate_size()
})
_select(event)
{
var data = {
id:self.rid,
data:event.item}
if(opts.onlistselect)
opts.onlistselect(data)
console.log(data)
if(self.selidx != -1)
self.rows[self.selidx].selected =false
self.selidx = event.item.i
self.rows[self.selidx].selected = true
this.root.observable.trigger('gridselect',data)
event.preventUpdate = true
self.update()
event.preventDefault()
}
</script>
</afx-grid-view>
<afx-grid-row>
<div style = "flex-grow:1;" each = { child,i in cols } class = {string:typeof child.value == "string", number: typeof child.value == "number"} >
<i if={child.iconclass} class = {child.iconclass} ></i>
<i if={child.icon} class="icon-style" style = { "background: url("+child.icon+");background-size: 100% 100%;background-repeat: no-repeat;" }></i>
{child.value}
</div>
<script>
this.cols = opts.cols || []
var self = this
this.rid = opts.rootid
this.observable = opts.observable
this.header = opts.header||false
this.calibrate_size = function()
{
if(!self.cols || self.cols.length == 0 || !self.observable) return
var totalw = $(self.root).parent().width()
var ocw = 0
var nauto = 0
var dist = []
$.each(self.cols, function(i,e){
if(e.width)
{
dist.push(e.width)
ocw += e.width
}
else
{
dist.push(-1)
nauto++
}
})
if(nauto > 0)
{
var cellw = (totalw - ocw)/ nauto
$.each(dist,function(i,e){
if(e == -1) dist[i] = cellw
})
}
self.observable.trigger("cellresize",{id:self.rid,data:dist})
}
self.observable.on("cellresize",function(d){
if(d.id && d.id == self.rid)
{
var i = 0
$(self.root)
.children()
.each(function(){
$(this).css("width", d.data[i]+"px")
i++
})
}
})
this.on("mount", function(){
$(self.root)
.css("display","flex")
.css("flex-direction","row")
.css("width","100%")
if(self.header)
self.calibrate_size()
})
</script>
</afx-grid-row>

View File

@ -4,14 +4,30 @@
</div>
<script>
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(){
$(self.refs.container)
.css("display","flex")
.css("flex-direction","column")
.css("width","100%")
.css("background-color","red")
.css("table-layout","fixed")
.css("overflow", "hidden")
//.css("background-color","red")
//.css("overflow", "hidden")
calibrate_size()
@ -36,7 +52,7 @@
this.observable = self.root.observable
$(this)
.css("flex-grow","1")
.css("border","1px solid black")
//.css("border","1px solid black")
var dw = $(this).attr("data-height")
if(dw)
{

View File

@ -1,29 +1,101 @@
<afx-list-view>
<ul>
<li each={ items } class = {child != null ? "afx-sublist":""} onclick = {parent.onselect}>
<afx-list-view if={child != null} child={child} observable = {parent.observable} ></afx-list-view>
<afx-list-view class = {dropdown: opts.dropdown == "true"}>
<div class = "list-container" ref = "container">
<div if = {opts.dropdown == "true"} ref = "current" style = {opts.width?"min-width:" + opts.width + "px;":"min-width:150px;"} onclick = {show_list}>
{selectedText}
</div>
<ul ref = "mlist">
<li each={ items } class={selected: selected} onclick = {parent._select}>
<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 }
</li>
</ul>
</div>
<script>
this.items = opts.child
var self = this
self.selidx = -1
self.selectedText = ""
self.onlistselect = opts.onlistselect
self.root.set = function(k,v)
{
if(k == "selected")
self._select({item:self.items[v], preventDefault:function(){}})
else if(k == "*")
for(var i in v)
self[i] = v[i]
else
self[k] = v
self.update()
}
self.root.update = function()
{
self.update()
}
self.root.get = function(k)
{
if(k == "selected")
return self.items[self.selidx]
return self[k]
}
if(opts.observable)
this.observable = opts.observable
else if(this.root.observable)
this.observable = this.root.observable
this.root.observable = opts.observable
else
{
this.observable = riot.observable()
this.observable.on('listselect',function(data){
if(opts.listselect)
opts.listselect(data)
})
this.root.observable = riot.observable()
}
onselect(event)
this.on("mount", function(){
if(opts.dropdown == "true")
{
$(document).click(function(event) {
if(!$(event.target).closest(self.refs.container).length) {
$(self.refs.mlist).hide()
}
})
//$(self.root).css("position","relative")
$(self.refs.container)
.css("position","absolute")
.css("display","inline-block")
$(self.refs.mlist)
.css("position","absolute")
.css("display","none")
.css("top","100%")
.css("left","0")
}
})
show_list()
{
this.observable.trigger('listselect',event.item)
event.preventDefault()
var desktoph = $("#desktop").height()
var off = $(self.root).offset().top + $(self.refs.mlist).height()
console.log(desktoph,off)
if( off > desktoph )
$(self.refs.mlist)
.css("top","-" + $(self.refs.mlist).outerHeight() + "px")
else
$(self.refs.mlist).css("top","100%")
$(self.refs.mlist).show()
}
_select(event)
{
var data = {
id:$(self.root).attr("data-id"),
data:event.item,
idx:self.items.indexOf(event.item)}
if(self.selidx != -1)
self.items[self.selidx].selected =false
self.selidx = data.idx
self.items[self.selidx].selected = true
if(opts.dropdown == "true")
{
$(self.refs.mlist).hide()
self.selectedText = self.items[self.selidx].text
}
if(self.onlistselect)
self.onlistselect(data)
this.root.observable.trigger('listselect',data)
event.preventDefault()
}
</script>
</afx-list-view>

View File

@ -1,17 +1,42 @@
<afx-menu>
<ul>
<li class="afx-corner-fix"></li>
<li each={ items } class = {child != null ? "afx-submenu":""}>
<li each={ items } class = {afx_submenu:child != null, fix_padding:icon}>
<a href="#" onclick = {parent.onselect}>
<i class = {icon} ></i>{ text }
<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 }
</a>
<afx-menu if={child != null} child={child} observable = {parent.root.observable} ></afx-menu>
<afx-menu if={child != null} child={child} onmenuselect={onmenuselect} observable = {parent.root.observable} rootid = {parent.rid}></afx-menu>
</li>
<li class="afx-corner-fix"></li>
</ul>
<script>
this.items = opts.child
if(opts.rootid)
this.rid = opts.rootid
else
this.rid = $(this.root).attr("data-id")
var self = this
this.onmenuselect = opts.onmenuselect
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()
}
if(opts.observable)
{
this.root.observable = opts.observable
@ -20,17 +45,24 @@
{
this.root.observable = riot.observable()
this.root.observable.on('menuselect',function(data){
if(opts.onmenuselect)
//console.log("From root",self.root)
if(self.onmenuselect)
{
opts.onmenuselect(data)
self.onmenuselect(data)
}
})
}
onselect(event)
{
this.root.observable.trigger('menuselect',event.item)
var data = {id:self.rid, data:event.item}
/*if(self.onmenuselect)
{
self.onmenuselect(data)
} else*/
this.root.observable.trigger('menuselect',data)
event.preventDefault()
}

View File

@ -1,8 +1,8 @@
<afx-sys-panel>
<div>
<afx-menu ref = "aOsmenu" child={osmenu.child} onmenuselect = {osmenu.onmenuselect} class="afx-panel-os-menu"></afx-menu>
<afx-menu ref = "aAppmenu" child={appmenu.child} onmenuselect = {appmenu.onmenuselect} class = "afx-panel-os-app"></afx-menu>
<afx-menu ref = "aTray" child={systray.child} onmenuselect = {systray.onmenuselect} class = "afx-panel-os-stray"></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 = "sys_tray" ref = "aTray" child={systray.child} onmenuselect = {systray.onmenuselect} class = "afx-panel-os-stray"></afx-menu>
</div>
<script>
@ -10,6 +10,24 @@
this.appmenu = opts.appmenu
this.systray = opts.systray
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() {
//console.log(self.refs.aOsmenu.root)
$(self.refs.aOsmenu.root).css("z-index",1000000)

View File

@ -0,0 +1,103 @@
<afx-tree-view>
<div ref = namediv class={afx_tree_item_selected:treeroot.selectedItem && treeroot.selectedItem.path == path, afx_folder_item: isFolder(), afx_tree_item_odd: index%2 != 0 } click={select}>
<i if={ !isFolder() && iconclass} class = {iconclass} ></i>
<i if={!isFolder() && icon} class="icon-style" style = { "background: url("+icon+");background-size: 100% 100%;background-repeat: no-repeat;" }></i>
<span onclick={ toggle } if={ isFolder() } class={open ? 'afx-tree-view-folder-open' : 'afx-tree-view-folder-close'}></span>
{ name }
</div>
<ul if={ isFolder() } show={ isFolder() && open }>
<li each={ child, i in nodes }>
<afx-tree-view data={child} indent={indent+1} observable = {parent.root.observable} path = {parent.path + ">" + i} treeroot= {parent.treeroot}></afx-tree-view>
</li>
</ul>
<script>
var self = this
if(opts.data)
{
self.name = opts.data.name
self.nodes = opts.data.nodes
self.icon = opts.data.icon
}
self.indent = opts.indent || 1
self.open = true
var istoggle = false
if(opts.treeroot)
{
this.treeroot = opts.treeroot
this.treeroot.counter++
}
else
{
this.treeroot = self
this.treeroot.counter = 0
}
self.path = opts.path || 0
self.selected = false
self.selectedItem = null
self.index = this.treeroot.counter
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.update = function()
{
self.update()
}
self.root.get = function(k)
{
return self[k]
}
if(opts.observable)
this.root.observable = opts.observable
else
{
this.root.observable = riot.observable()
}
this.on("mount", function(){
$(self.refs.namediv).css("padding-left", self.indent*15 + "px" )
})
isFolder() {
return self.nodes && self.nodes.length
}
toggle(e) {
self.open = !self.open
e.preventDefault()
istoggle = true
}
select(event)
{
if(istoggle)
{
istoggle = false
return
}
var data = {
id:$(self.treeroot.root).attr("data-id"),
data:event.item,
path:self.path
}
if(opts.ontreeselect)
opts.ontreeselect(data)
self.treeroot.selectedItem = data
this.root.observable.trigger('treeselect',data)
event.preventUpdate = true
self.treeroot.update()
event.preventDefault()
}
</script>
</afx-tree-view>

View File

@ -4,6 +4,23 @@
</div>
<script>
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(){
$(self.refs.container)
.css("display","flex")

View File

@ -3,16 +3,15 @@ afx-app-window div.afx-window-wrapper{
/*box-shadow: 1px 1px 1px #cbcbcb;*/
box-shadow: 1px 1px 1px #9f9F9F;
border-radius: 5px;
background-color:#e7e7e7;
background-color:#dfdfdf;
padding:0;
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
afx-app-window{
/*width: 600px;
height: 400px;*/
afx-app-window.unactive > div.afx-window-wrapper{
background-color: #f6f6f6;
}
afx-app-window ul.afx-window-top{

View File

@ -12,7 +12,12 @@ afx-button button{
afx-button button[disabled]{
color: #a6a6a6;
}
afx-button i.icon-style {
width: 16px;
height: 16px;
display: inline-block;
float:left;
}
afx-button button:active {
background-color: #2786F3;
color: white;

View File

@ -17,8 +17,20 @@ afx-apps-dock afx-button button{
width: 32px;
height: 32px;
font-size: 19px;
margin-bottom: 3px;
padding:0px;
background-color: transparent;
border:0;
}
afx-apps-dock afx-button .icon-style{
width: 24px;
height: 24px;
margin-bottom: 0px;
border:0;
background-color: transparent;
}
afx-apps-dock afx-button.selected > button {
background-color: #2786F3;
color: white;
border: 1px solid #dedede;
}

View File

@ -0,0 +1,33 @@
afx-grid-view{
overflow: hidden;
padding:5px;
}
afx-grid-view afx-grid-row div{
padding:3px;
padding-left: 5px;
padding-right: 5px;
}
afx-grid-view afx-grid-row:nth-child(even){
background-color: #f5F5F5;
}
afx-grid-view afx-grid-row.grid_row_header div{
border-right: 2px solid #e5e5e5;
}
afx-grid-view afx-grid-row i.icon-style {
width: 16px;
height: 16px;
display: inline-block;
float:left;
}
afx-grid-view afx-grid-row.selected {
background-color: #116cd6;
color:white;
}
afx-grid-view afx-grid-row.grid_row_header {
font-weight: bold;
border: 1px solid #e5e5e5;
border-right:0;
}

View File

@ -0,0 +1,104 @@
afx-list-view{
overflow:auto;
padding: 5px;
}
/*
afx-list-view div.list-container{
width: 100%;
height: 100%;
display: inline-block;
position: relative;
background-color: red;
}*/
afx-list-view ul{
margin:0;
padding: 0;
}
afx-list-view li{
margin:0;
padding:0;
list-style: none;
padding: 5px;
padding-top:3px;
padding-bottom: 3px;
color: #414339;
background-color: white;
}
afx-list-view li:nth-child(odd){
background-color: #f5F5F5;
}
afx-list-view i.icon-style {
width: 16px;
height: 16px;
display: inline-block;
float:left;
}
afx-list-view li > i {
margin-right: 3px;
}
afx-list-view li.selected {
background-color: #116cd6;
color:white;
}
/*
afx-list-view.dropdown div.list-container{
position: relative;
display: inline-block;
}
afx-list-view.dropdown div.list-container ul{
position:absolute;
top:100%;
left:0;
display: none;
border:1px solid red;
}*/
afx-list-view.dropdown {
padding:0;
margin: 0;
}
afx-list-view.dropdown div.list-container ul{
max-height: 150px;
overflow-y: auto;
overflow-x: hidden;
background-color: white;
}
afx-list-view.dropdown div.list-container ul{
border:1px solid #a6a6a6;
box-shadow: 1px 1px 1px #9f9F9F;
border-radius: 3px;
padding:2px;
border-top-left-radius: 0px;
}
afx-list-view.dropdown div.list-container ul li{
display: inline-block;
width:100%;
}
afx-list-view.dropdown div.list-container div{
padding:3px;
border:1px solid #a6a6a6;
border-radius: 3px;
padding-right:15px;
background-color: white;
height: 17px;
}
afx-list-view.dropdown div.list-container div:before {
content: "\f107";
font-family: "FontAwesome";
font-size: 11px;
font-style: normal;
color: #414339;
position: absolute;
top:25%;
right: 5px;
}
afx-list-view.dropdown div.list-container ul li:hover{
background-color: #dcdcdc;
color: #414339;
}

View File

@ -6,8 +6,6 @@ afx-menu {
}
afx-menu a{
text-decoration: none;
width: 100%;
height: 100%;
color: #414339;
display: inline-block;
width: 100%;
@ -17,6 +15,14 @@ afx-menu ul{
padding:0;
margin: 0;
}
afx-menu i.icon-style {
width: 16px;
height: 16px;
display: inline-block;
float:left;
}
afx-menu afx-menu ul {
padding: 0;
border:1px solid #a6a6a6;
@ -35,6 +41,18 @@ afx-menu ul > li{
padding-left: 5px;
padding-right: 5px;
}
afx-menu ul > li.fix_padding{
padding-top:1px;
padding-bottom: 0;
padding-left: 5px;
padding-right: 5px;
}
afx-menu afx-menu ul > li.fix_padding{
padding:3px;
padding-left: 5px;
padding-right: 5px;
}
afx-menu afx-menu {
top:100%;
left:0;
@ -46,7 +64,7 @@ afx-menu afx-menu i{
}
afx-menu afx-menu li{
float:none;
width: 150px;
min-width: 150px;
}
afx-menu afx-menu afx-menu{
top:-4px;
@ -74,11 +92,11 @@ afx-menu li.afx-corner-fix:hover{
background-color: transparent;
}
afx-menu afx-menu .afx-submenu:before {
afx-menu afx-menu .afx_submenu:before {
content: "\f054";
font-family: "FontAwesome";
font-size: 10px;
left:93%;
right:5px;
color: #414339;
position:absolute;
top:25%;

View File

@ -1,4 +1,8 @@
afx-sys-panel{
padding:0;
margin: 0;
}
afx-sys-panel div{
width: 100%;
height: 23px;
@ -7,13 +11,18 @@ afx-sys-panel div{
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;
left: -100%;
right:0;
}

View File

@ -0,0 +1,59 @@
afx-tree-view{
color: #414339;
padding:3px;
overflow: auto;
}
afx-tree-view afx-tree-view{
padding:0;
overflow: hidden;
}
afx-tree-view ul{
margin:0;
padding:0;
}
afx-tree-view li{
list-style: none;
margin:0;
padding: 0;
}
afx-tree-view div{
padding:3px;
background-color: white;
}
afx-tree-view i.icon-style {
width: 16px;
height: 16px;
display: inline-block;
float:left;
margin-right: 3px;
}
afx-tree-view div.afx_tree_item_selected{
background-color: #116cd6;
color:white;
}
afx-tree-view div.afx_tree_item_selected:hover{
background-color: #116cd6;
color:white;
}
/*
afx-tree-view div:hover{
background-color: #f5F5F5;
color: #414339;
}*/
afx-tree-view .afx_folder_item{
font-weight: bold;
}
afx-tree-view .afx-tree-view-folder-open:before{
content: "\f147";
font-family: "FontAwesome";
font-size: 13px;
}
afx-tree-view .afx-tree-view-folder-close:before{
content: "\f196";
font-family: "FontAwesome";
font-size: 13px;
}
afx-tree-view .afx_tree_item_odd{
background-color: #f5F5F5;
}

35
src/core/processes.coffee Normal file
View File

@ -0,0 +1,35 @@
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
_GUI.dock obj,cls.meta
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
_GUI.undock _PM.processes[app.name][i]
delete _PM.processes[app.name][i]
_PM.processes[app.name].splice i,1

View File

@ -4,11 +4,15 @@ self.OS or=
API: new Object()
GUI: new Object()
APP: new Object()
register: (name,x)-> self.OS.APP[name] = x
PM: new Object()
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()
_GUI.loadScheme "resources/schemes/test.html",null
#_GUI.loadScheme "resources/schemes/test.html",null

View File

@ -10,6 +10,8 @@
<script src="resources/antos_tags.js" type="riot/tag"></script>
<script src="scripts/riot.compiler.min.js"> </script>
<script src="scripts/ace/ace.js"></script>
<script src="scripts/ace/ext-language_tools.js"></script>
<script src="scripts/ace/ext-modelist.js"></script>
<script src="scripts/antos.js"></script>
</head>
<body>

View File

@ -0,0 +1,33 @@
coffee_files = main.coffee
jsfiles =
cssfiles = main.css
copyfiles = scheme.html package.json
BLUE=\033[1;34m
NC=\033[0m
main: title clean js css copy
title:
@echo "$(BLUE)======= Package ActivityMonitor =======$(NC)"
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,56 @@
_PM = this.OS.PM
_APP = this.OS.APP
class ActivityMonitor extends this.OS.GUI.BaseApplication
constructor: () ->
super "ActivityMonitor"
main: () ->
me = @
@scheme.set "apptitle", "Activity Monitor"
@grid = @find "mygrid"
@on "btclick", (e)->
return unless e.id == "btkill"
item = me.grid.get "selected"
return unless item
app = _PM.appByPid item[0].value
app.quit() if app
header = [{width:50,value:"Pid"},{value:"Name"},{width:100,value:"Alive (ms)"}]
@gdata =
processes:{}
alive:[]
@grid.set "header",header
@monitor()
monitor: () ->
me = @
#get all current running process
me.gdata.alive = []
now = (new Date).getTime()
$.each _PM.processes, (i,d)->
$.each d , (j,a)->
if me.gdata.processes[a.pid] #update it
me.gdata.processes[a.pid][2].value = now - a.birth
else #add it
me.gdata.processes[a.pid] = [
{value:a.pid},
{icon:_APP[a.name].meta.icon,iconclass:_APP[a.name].meta.iconclass,value:a.name},
{value: now - a.birth}
]
me.gdata.alive.push a.pid
@refreshGrid()
@timer = setTimeout (()-> me.monitor()),500#one second
refreshGrid: ()->
activeList = []
me = @
$.each @gdata.processes, (i,e) ->
if ($.inArray (Number i),me.gdata.alive) >= 0
activeList.push e
else
me.gdata.processes[i] = undefined
@grid.set "rows",activeList
exit: (e) ->
clearTimeout @timer if @timer
ActivityMonitor.singleton = true
this.OS.register "ActivityMonitor",ActivityMonitor

View File

@ -0,0 +1,8 @@
afx-app-window[data-id="am-window"] afx-button{
margin: 3px;
}
afx-app-window[data-id="am-window"] afx-grid-view{
padding-left:10px;
padding-right: 10px;
}

View File

@ -0,0 +1,12 @@
{
"app":"ActivityMonitor",
"name":"Activity monitor",
"description":"Processes monitor and manager",
"author":{
"name": "Xuan Sang LE",
"email": "xsang.le@gmail.com"
},
"category":"System",
"iconclass":"fa fa-heartbeat",
"mimes":["*"]
}

View File

@ -0,0 +1,7 @@
<afx-app-window data-id = "am-window" apptitle="" width="400" height="300">
<afx-vbox>
<afx-hbox>
<afx-grid-view data-id = "mygrid"></afx-grid-view>
<afx-button data-height="30" data-id = "btkill" text = "Kill process" iconclass="fa fa-times"></afx-button>
</afx-hbox>
</afx-app-window>

View File

@ -7,27 +7,27 @@ cssfiles = main.css
copyfiles = scheme.html package.json
BLUE=\033[0;34m
BLUE=\033[1;34m
NC=\033[0m
main: title clean js css copy
title:
- echo "$(BLUE)======= Package NotePad =======$(NC)"
@echo "$(BLUE)======= Package NotePad =======$(NC)"
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
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
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
for f in $(cssfiles); do (cat "$${f}"; echo) >> build/main.css; done
copy:
- cp -rf $(copyfiles) build/
cp -rf $(copyfiles) build/
clean:
- rm -rf build/*

View File

@ -1,10 +1,53 @@
class NotePad extends this.OS.GUI.BaseApplication
constructor: () ->
super "NotePad"
event: () ->
console.log @scheme
@on "btclick", (e)->
alert "Happy pola"
@on "resize", (w,h)->
console.log "resize"
main: () ->
me = @
@scheme.set "apptitle", "NotePad"
div = @find "datarea"
ace.require "ace/ext/language_tools"
@.editor = ace.edit div
@.editor.setTheme "ace/theme/monokai"
@.editor.getSession().setMode 'ace/mode/text'
@.editor.setOptions {
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: true,
fontSize: "10pt"
}
@.editor.completers.push {getCompletions:(editor, session, pos, prefix, callback)->}
@.editor.getSession().setUseWrapMode true
list = @find "modelist"
@modes = ace.require "ace/ext/modelist"
ldata = []
ldata.push {text:m.name, mode:m.mode} for m in @modes.modes
list.set "items",ldata
list.set "onlistselect", (e)->
me.editor.session.setMode e.data.mode
stat = @find "editorstat"
#status
stup = (e)->
c = me.editor.session.selection.getCursor()
l = me.editor.session.getLength()
$(stat).html "Row #{c.row}, col #{c.column}, lines: #{l}"
stup(0)
@.editor.getSession().selection.on "changeCursor", (e)->
stup(e)
@on "resize", ()-> me.editor.resize()
@on "focus", ()->me.editor.focus()
menu: ()->
menu = [{
text:"File",
child:[
{text:"Open", dataid:"#{@name}-Open"},
{text:"Close", dataid:"#{@name}-Close"}
]
}]
menu
NotePad.singleton = false
this.OS.register "NotePad",NotePad

View File

@ -1,3 +1,9 @@
fut{
background-color: black
afx-app-window[data-id="notepad"] afx-list-view[data-id="modelist"]{
margin:2px;
}
afx-app-window[data-id="notepad"] span[data-id="editorstat"]{
padding:5px;
display: inline-block;
}

View File

@ -7,6 +7,6 @@
"email": "xsang.le@gmail.com"
},
"category":"System",
"icon":"",
"iconclass":"fa fa-pencil-square-o",
"mimes":["*"]
}

View File

@ -1,16 +1,24 @@
<afx-app-window apptitle="Preview" width="600" height="400">
<afx-vbox>
<afx-app-window apptitle="" width="600" height="400" data-id="notepad">
<afx-hbox>
<afx-list-view data-width = "250"> </afx-list-view>
<!--afx-list-view data-id = "flist" data-width = "150" > </afx-list-view>
<afx-hbox>
<afx-button data-height="50" onbtclick="alert('im clicked')" text="Read more" icon="fa fa-camera-retro fa-lg" id="button">
<afx-button data-height="50" text="Read more" iconclass="fa fa-camera-retro fa-lg" id="button">
</afx-button>
<div style=" vertical-align: top; width:100%;height:100%;">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
<div>
big text here
</div>
<div data-height="100" style=" vertical-align: top; width:100%;height:100%;">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
<div data-width="100">Test</div>
</afx-hbox>
</afx-vbox>
</afx-hbox-->
<div data-id="datarea"></div>
<afx-vbox data-height="30">
<div ><span data-id = "editorstat"></span></div>
<afx-list-view data-width="170" data-id = "modelist" dropdown = "true" width="150"></afx-list-view>
</afx-vbox>
</afx-hbox>
</afx-app-window>

View File

@ -0,0 +1,33 @@
coffee_files = main.coffee
jsfiles =
cssfiles = main.css
copyfiles = scheme.html package.json
BLUE=\033[1;34m
NC=\033[0m
main: title clean js css copy
title:
@echo "$(BLUE)======= Package Terminal =======$(NC)"
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,80 @@
class Terminal extends this.OS.GUI.BaseApplication
constructor: () ->
super "Terminal"
main: () ->
self = @
@on "btclick", (e)->
alert "#{self.name}: Happy pola"
@on "resize", (w,h)->
console.log "#{self.name}: resize"
#@on "listselect", (i)->
# console.log self.name, i
@on "treeselect", (i) ->
console.log self.name,i
@on "focus", ()->
console.log self.name, "is focused"
tree = @find "mytree"
@scheme.set "apptitle", "Terminal"
tdata = {
name: 'My Tree',
nodes: [
{ name: 'hello', icon:'packages/NotePad/icon.png'},
{ name: 'wat' },
{
name: 'child folder',
nodes: [
{
name: 'child folder',
nodes: [
{ name: 'hello' },
{ name: 'wat' }
]
},
{ name: 'hello' },
{ name: 'wat' },
{
name: 'child folder',
nodes: [
{ name: 'hello' },
{ name: 'wat' }
]
}
]
}
]
}
tree.set "*",tdata
list = @find "mylist"
ldata = [
{text:"some thing with avery long text"},
{text:"some thing"},
{text:"some thing"},
{text:"some thing"},
{text:"some thing"},
{text:"some thing"},
{text:"some thing"},
{text:"some thing"},
{text:"some thing"},
{text:"some thing"},
{text:"some thing"},
{text:"some thing"},
{text:"some thing"},
{text:"some thing"},
{text:"some thing"},
{text:"some thing"},
{text:"some thing"},
{text:"some thing"},
{text:"some thing"},
{text:"some thing"},
{text:"some thing"},
{text:"some thing"},
{text:"some thing"}
]
list.set "items",ldata
list.set "onlistselect", (e)->
console.log e
Terminal.singleton = false
this.OS.register "Terminal",Terminal

View File

View File

@ -0,0 +1,12 @@
{
"app":"Terminal",
"name":"Unix terminal like",
"description":"Access Unix terminal from web",
"author":{
"name": "Xuan Sang LE",
"email": "xsang.le@gmail.com"
},
"category":"System",
"iconclass":"fa fa-terminal",
"mimes":["*"]
}

View File

@ -1,16 +1,14 @@
<afx-app-window apptitle="Preview" width="600" height="400">
<afx-vbox>
<afx-list-view data-width = "250"> </afx-list-view>
<afx-tree-view data-id="mytree"> </afx-tree-view>
<afx-hbox>
<afx-button data-height="50" onbtclick="alert('im clicked')" text="Read more" icon="fa fa-camera-retro fa-lg" id="button">
<afx-button data-height="50" text="Read more" iconclass="fa fa-camera-retro fa-lg" id="button">
</afx-button>
<div style=" vertical-align: top; width:100%;height:100%;">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
<afx-list-view data-id = "mylist" dropdown = "true" width="200"></afx-list-view>
<div data-height="100" style=" vertical-align: top; width:100%;height:100%;">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
<div data-width="100">Test</div>
</afx-hbox>
</afx-vbox>
</afx-app-window>