diff --git a/src/core/BaseDialog.coffee b/src/core/BaseDialog.coffee
index 9ee7357..3e8f121 100644
--- a/src/core/BaseDialog.coffee
+++ b/src/core/BaseDialog.coffee
@@ -191,6 +191,31 @@ class YesNoDialog extends BasicDialog
}
this.OS.register "YesNoDialog", YesNoDialog
+class SelectionDialog extends BasicDialog
+ constructor: () ->
+ super "SelectionDialog", {
+ tag: "afx-list-view",
+ att: "",
+ width: 250,
+ height: 300,
+ resizable: false,
+ buttons: [
+ {
+ label: "Ok", onclick: (d) ->
+ el = d.find "content"
+ it = el.get "selected"
+ return unless it
+ d.handler it if d.handler
+ d.quit()
+ },
+ { label: "Cancel", onclick: (d) -> d.quit() }
+ ],
+ filldata: (d) ->
+ return unless d.data
+ (d.find "content").set "items", d.data
+ }
+this.OS.register "SelectionDialog", SelectionDialog
+
class AboutDialog extends BaseDialog
constructor: () ->
super "AboutDialog"
diff --git a/src/core/BaseModel.coffee b/src/core/BaseModel.coffee
index 0682858..391b426 100644
--- a/src/core/BaseModel.coffee
+++ b/src/core/BaseModel.coffee
@@ -2,9 +2,10 @@ class BaseModel
constructor: (@name, @args) ->
@observable = riot.observable()
@_api = self.OS.API
+ @_gui = self.OS.GUI
me = @
@on "exit", () -> me.quit()
- @host = "#desktop"
+ @host = "#workingenv"
@dialog = undefined
render: (p) ->
@@ -35,10 +36,10 @@ class BaseModel
if @dialog
@dialog.show()
return
- if not _GUI.dialog[d]
+ if not _GUI.dialogs[d]
@error "Dialog #{d} not found"
return
- @dialog = new _GUI.dialog[d]()
+ @dialog = new _GUI.dialogs[d]()
@dialog.parent = @
@dialog.handler = f
@dialog.pid = @pid
diff --git a/src/core/api.coffee b/src/core/api.coffee
index 9897c89..4900ee4 100644
--- a/src/core/api.coffee
+++ b/src/core/api.coffee
@@ -117,5 +117,5 @@ self.OS.API =
catch e
err = e
return "" if not err
- return err.stack
+ return err
diff --git a/src/core/core.coffee b/src/core/core.coffee
index 9109249..ea7aa4e 100644
--- a/src/core/core.coffee
+++ b/src/core/core.coffee
@@ -8,6 +8,7 @@ self.OS or=
setting:
user: {}
applications: {}
+ desktop: {}
appearance: {}
courrier:
observable: riot.observable()
@@ -22,6 +23,8 @@ self.OS or=
_courrier.ostrigger "fail", { m: m, e: e, s: s }
oserror: (m, e, s) ->
_courrier.ostrigger "error", { m: m, e: e, s: s }
+ osinfo: (m) ->
+ _courrier.ostrigger "info", { m: m, e: null, s: null }
ostrigger: (e, d) ->
_courrier.trigger e, { id: 0, data: d, name: "OS" }
unregister: (app) ->
@@ -33,7 +36,7 @@ self.OS or=
_courrier.quota += 1
_courrier.quota
register: (name, x) ->
- if x.type is 3 then self.OS.GUI.dialog[name] = x else _OS.APP[name] = x
+ if x.type is 3 then self.OS.GUI.dialogs[name] = x else _OS.APP[name] = x
PM:
pidalloc: 0
diff --git a/src/core/gui.coffee b/src/core/gui.coffee
index cf267db..3bfacf9 100644
--- a/src/core/gui.coffee
+++ b/src/core/gui.coffee
@@ -1,5 +1,6 @@
self.OS.GUI =
- dialog: new Object()
+ dialogs: new Object()
+ dialog: undefined
htmlToScheme: (html, app, parent) ->
scheme = $.parseHTML html
($ parent).append scheme
@@ -19,7 +20,8 @@ self.OS.GUI =
$ "head link#ostheme"
.attr "href", ""
- loadTheme: (name) ->
+ loadTheme: (name, force) ->
+ _GUI.clearTheme() if force
path = "resources/themes/#{name}/#{name}.css"
$ "head link#ostheme"
.attr "href", path
@@ -31,6 +33,21 @@ self.OS.GUI =
srvs.splice 0, 1
f i for i in srvs
+ openDialog: (d, f, title, data) ->
+ if _GUI.dialog
+ _GUI.dialog.show()
+ return
+ if not _GUI.dialogs[d]
+ ex = _API.throwe "Dialog"
+ return _courrier.oserror "Dialog #{d} not found", ex, null
+ _GUI.dialog = new _GUI.dialogs[d]()
+ _GUI.dialog.parent = _GUI
+ _GUI.dialog.handler = f
+ _GUI.dialog.pid = -1
+ _GUI.dialog.data = data
+ _GUI.dialog.title = title
+ _GUI.dialog.init()
+
pushService: (ph) ->
arr = ph.split "/"
srv = arr[1]
@@ -43,6 +60,32 @@ self.OS.GUI =
_courrier.trigger "srvroutineready", srv
_courrier.osfail "Cannot read service script: #{srv} ", e, s
+ appsByMime: (mime) ->
+ metas = ( a.meta for k, a of _OS.APP when a.type is 1)
+ mimes = ( m.mimes for m in metas )
+ apps = []
+ # search app by mimes
+ f = ( arr, idx ) ->
+ arr.filter (m, i) ->
+ if mime.match (new RegExp m, "g")
+ apps.push metas[idx]
+ return false
+ return false
+
+ f m, i for m, i in mimes
+ return apps
+
+ openWith: (it) ->
+ return unless it
+ console.log "open #{it.path}"
+ apps = _GUI.appsByMime ( if it.type is "dir" then "dir" else it.mime )
+ return OS.info "No application available to open #{it.filename}" if apps.length is 0
+ return _GUI.launch apps[0].app, [it.path] if apps.length is 1
+ list = ( { text: e.app, icon: e.icon, iconclass: e.iconclass } for e in apps )
+ _GUI.openDialog "SelectionDialog", ( d ) ->
+ _GUI.launch d.text, [it.path]
+ , "Open width", list
+
forceLaunch: (app, args) ->
console.log "This method is used for developing only, please use the launch method instead"
_PM.killAll app
@@ -129,19 +172,71 @@ self.OS.GUI =
return null unless x
scheme = $.parseHTML x
($ "#wrapper").append scheme
+
+ # system menu and dock
+ riot.mount ($ "#syspanel", $ "#wrapper")
+ riot.mount ($ "#sysdock", $ "#wrapper"), { items: [] }
+
# context menu
riot.mount ($ "#contextmenu")
($ "#workspace").contextmenu (e) -> _GUI.bindContextMenu e
- #desktop
- desktop = ($ "#desktop")
- desktop.on "click", (e) ->
- return if e.target isnt desktop.get(0)
- ($ "#sysdock").get(0).set "selectedApp", null
- desktop.get(0).contextmenuHandler = (e, m) ->
- console.log "context menu handler for desktop"
- # system menu
- riot.mount ($ "#syspanel", $ "#wrapper")
- riot.mount ($ "#sysdock", $ "#wrapper"), { items: [] }
+
+ # desktop default file manager
+ desktop = $ "#desktop"
+ desktop[0].fetch = () ->
+ fp = _OS.setting.desktop.path.asFileHandler()
+ fn = () ->
+ fp.read (d) ->
+ return _courrier.osfail d.error, (_API.throwe "OS.VFS"), d.error if d.error
+ items = []
+ $.each d.result, (i, v) ->
+ return if v.filename[0] is '.' and not _OS.setting.desktop.showhidden
+ v.text = v.filename
+ #v.text = v.text.substring(0,9) + "..." ifv.text.length > 10
+ v.iconclass = v.type
+ items.push(v)
+ desktop[0].set "items", items
+ desktop[0].refresh()
+
+ fp.onready () ->
+ fn()
+ , ( e ) -> # try to create the path
+ console.log "#{fp.path} not found"
+ name = fp.basename
+ fp.parent().asFileHandler().mk name, (r) ->
+ ex = _API.throwe "OS.VFS"
+ if r.error then _courrier.osfail d.error, ex, d.error else fn()
+
+ desktop[0].ready = (e) ->
+ e.observable = _courrier
+ window.onresize = () ->
+ _courrier.trigger "desktopresize"
+ e.refresh()
+
+ desktop[0].set "onlistselect", (d) ->
+ ($ "#sysdock").get(0).set "selectedApp", null
+
+ desktop[0].set "onlistdbclick", ( d ) ->
+ ($ "#sysdock").get(0).set "selectedApp", null
+ it = desktop[0].get "selected"
+ _GUI.openWith it
+
+ ($ "#workingenv").on "click", (e) ->
+ desktop[0].set "selected", -1
+
+ desktop.on "click", (e) ->
+ ($ "#sysdock").get(0).set "selectedApp", null
+ desktop[0].set "selected", -1 if e.target is desktop[0]
+ console.log "desktop clicked"
+
+ desktop[0].contextmenuHandler = (e, m) ->
+ desktop[0].set "selected", -1 if e.target is desktop[0]
+ console.log "context menu handler for desktop"
+
+ desktop[0].fetch()
+ _courrier.trigger "desktoploaded"
+ # mount it
+ riot.mount desktop
, (e, s) ->
alert "System fall: Cannot init desktop manager"
@@ -161,16 +256,25 @@ self.OS.GUI =
alert "System fall: Cannot init login screen"
startAntOS: (conf) ->
+ # clean up things
_OS.cleanup()
+ # get setting from conf
+ _OS.setting.desktop = conf.desktop if conf.desktop
_OS.setting.applications = conf.applications if conf.applications
_OS.setting.appearance = conf.appearance if conf.appearance
_OS.setting.user = conf.user
- # get setting from conf
- # load packages list
+ _OS.setting.desktop.path = "home:///.desktop" unless _OS.setting.desktop.path
# load theme
- # initDM
_GUI.loadTheme "antos"
+ # initDM
_GUI.initDM()
_courrier.observable.one "syspanelloaded", () ->
- #_GUI.loadApp "CoreServices", (a) ->
- _GUI.pushServices ["CoreServices/PushNotification", "CoreServices/Spotlight", "CoreServices/Calendar"]
\ No newline at end of file
+ # TODO load packages list then build system menu
+ # push startup services
+ # TODO: get services list from user setting
+ _GUI.pushServices ["CoreServices/PushNotification", "CoreServices/Spotlight", "CoreServices/Calendar"]
+
+ # startup application here
+ _courrier.observable.one "desktoploaded", () ->
+ _GUI.launch "Files"
+ _GUI.launch "NotePad"
\ No newline at end of file
diff --git a/src/core/schemes/dm.html b/src/core/schemes/dm.html
index 3a1f1bb..bf2c643 100644
--- a/src/core/schemes/dm.html
+++ b/src/core/schemes/dm.html
@@ -3,7 +3,7 @@
diff --git a/src/core/tags/afx-app-window.js b/src/core/tags/afx-app-window.js
index ddef264..642de97 100644
--- a/src/core/tags/afx-app-window.js
+++ b/src/core/tags/afx-app-window.js
@@ -50,8 +50,10 @@
}
this.on('mount', function() {
var left,top
- left = 20 + Math.floor(Math.random() * ($("#desktop").width() - width))
- top = 20 + Math.floor(Math.random() * ($("#desktop").height() - height))
+ //left = 20 + Math.floor(Math.random() * ($("#desktop").width() - width))
+ //top = 20 + Math.floor(Math.random() * ($("#desktop").height() - height))
+ left = ($("#desktop").width() - width)/2
+ top = ($("#desktop").height() - height)/2
$(self.refs.window)
.css("position",'absolute')
.css("left",left + "px")
diff --git a/src/core/tags/afx-float-list.js b/src/core/tags/afx-float-list.js
index cfbd587..f828a39 100644
--- a/src/core/tags/afx-float-list.js
+++ b/src/core/tags/afx-float-list.js
@@ -1,8 +1,176 @@
-
-
-
+
+
-
\ No newline at end of file
diff --git a/src/core/tags/afx-list-view.js b/src/core/tags/afx-list-view.js
index 2fed093..0be3e7c 100644
--- a/src/core/tags/afx-list-view.js
+++ b/src/core/tags/afx-list-view.js
@@ -35,7 +35,10 @@
self.root.get = function(k)
{
if(k == "selected")
- return self.items[self.selidx]
+ if(self.selidx != -1)
+ return self.items[self.selidx]
+ else
+ return undefined
return self[k]
}
self.root.push = function(e,u)
diff --git a/src/core/vfs.coffee b/src/core/vfs.coffee
index cf71497..1edf00b 100644
--- a/src/core/vfs.coffee
+++ b/src/core/vfs.coffee
@@ -39,12 +39,13 @@ class BasicFileHandler
return @ if @isRoot()
return (@protocol + ":///" + (@genealogy.slice 0 , @genealogy.length - 1).join "/")
- onready: (f) ->
+ onready: (f, err) ->
# read meta data
return f() if @ready
me = @
me.meta (d) ->
- return _courrier.osfail d.error, (_API.throwe "OS.VFS"), d.error if d.error
+ if d.error
+ return if err then err d else _courrier.osfail d.error, (_API.throwe "OS.VFS"), d.error
me.meta = d.result
me.ready = true
f()
diff --git a/src/packages/CoreServices/PushNotification.coffee b/src/packages/CoreServices/PushNotification.coffee
index 547b7bf..802104f 100644
--- a/src/packages/CoreServices/PushNotification.coffee
+++ b/src/packages/CoreServices/PushNotification.coffee
@@ -27,11 +27,12 @@ class PushNotification extends this.OS.GUI.BaseService
@nzone = @find "notifyzone"
@fzone = @find "feedzone"
(@find "btclear").set "onbtclick", (e) -> me.mlist.set "items", []
- #mlist.set "onlistselect", (e) -> console.log e
+ @subscribe "fail", (e) -> console.log e
@subscribe "notification", (o) -> me.pushout 'INFO', o
@subscribe "fail", (o) -> me.pushout 'FAIL', o
@subscribe "error", (o) -> me.pushout 'ERROR', o
-
+ @subscribe "info", (o) -> me.pushout 'INFO', o
+
@subscribe "loading", (o) ->
me.pending.push o.id
me.spin true
@@ -59,6 +60,8 @@ class PushNotification extends this.OS.GUI.BaseService
icon: o.data.icon,
iconclass: o.data.iconclass,
closable: true }
+ console.log o.data.s
+ console.log o.data.e
@mlist.unshift d, true
@notifeed d
diff --git a/src/packages/Files/main.coffee b/src/packages/Files/main.coffee
index 263bb4a..7e6dc86 100644
--- a/src/packages/Files/main.coffee
+++ b/src/packages/Files/main.coffee
@@ -8,7 +8,7 @@ class Files extends this.OS.GUI.BaseApplication
@view = @find "fileview"
@navinput = @find "navinput"
@navbar = @find "nav-bar"
- @currdir = undefined
+ @currdir = if @args and @args.length > 0 then @args[0].asFileHandler() else "home:///".asFileHandler()
@favo = @find "favouri"
@clipboard = undefined
@@ -17,7 +17,9 @@ class Files extends this.OS.GUI.BaseApplication
m.show(e)
#@on "fileselect", (d) -> console.log d
@on "filedbclick", (e) ->
- #if e.data.type is 'dir' then me.chdir e.data.path, true
+ return unless e.data
+ return if e.data.type is "dir"
+ me._gui.openWith e.data
@favo.set "onlistselect", (e) -> me.chdir e.data.path
($ @find "btback").click () ->
@@ -38,15 +40,17 @@ class Files extends this.OS.GUI.BaseApplication
@setting.favorite = [
{ text: "Applications", path: 'app:///', iconclass: "fa fa-adn" },
- { text: "Home", path: 'home:///', iconclass: "fa fa-home", selected: true },
+ { text: "Home", path: 'home:///', iconclass: "fa fa-home" },
{ text: "OS", path: 'os:///', iconclass: "fa fa-inbox" },
{ text: "Desktop", path: 'home:///.desktop', iconclass: "fa fa-desktop" },
] if not @setting.favorite
@setting.sidebar = true if @setting.sidebar is undefined
@setting.nav = true if @setting.nav is undefined
@setting.showhidden = false if @setting.showhidden is undefined
- @favo.set "items", @setting.favorite
+
+ @favo.set "items", $.extend true, {}, @setting.favorite
@applySetting()
+ @chdir null
applySetting: (k) ->
# view setting
diff --git a/src/packages/Files/package.json b/src/packages/Files/package.json
index 03a28d5..0f6511f 100644
--- a/src/packages/Files/package.json
+++ b/src/packages/Files/package.json
@@ -9,5 +9,5 @@
"version":"0.1a",
"category":"System",
"iconclass":"fa fa-hdd-o",
- "mimes":["*"]
+ "mimes":["dir"]
}
\ No newline at end of file
diff --git a/src/packages/NotePad/main.coffee b/src/packages/NotePad/main.coffee
index 711cba7..0938f33 100644
--- a/src/packages/NotePad/main.coffee
+++ b/src/packages/NotePad/main.coffee
@@ -1,5 +1,5 @@
class NotePad extends this.OS.GUI.BaseApplication
- constructor: (args) ->
+ constructor: ( args ) ->
super "NotePad", args
main: () ->
me = @
@@ -9,6 +9,7 @@ class NotePad extends this.OS.GUI.BaseApplication
@fileview = @find "fileview"
div = @find "datarea"
ace.require "ace/ext/language_tools"
+ @currfile = if @args and @args.length > 0 then @args[0].asFileHandler() else undefined
@.editor = ace.edit div
@.editor.setOptions {
enableBasicAutocompletion: true,
@@ -16,7 +17,7 @@ class NotePad extends this.OS.GUI.BaseApplication
enableLiveAutocompletion: true,
fontSize: "9pt"
}
- @.editor.completers.push {getCompletions:(editor, session, pos, prefix, callback)->}
+ @.editor.completers.push { getCompletions: ( editor, session, pos, prefix, callback ) -> }
@.editor.getSession().setUseWrapMode true
list = @find "modelist"
@@ -64,11 +65,20 @@ class NotePad extends this.OS.GUI.BaseApplication
@location.set "onlistselect", (e) -> me.chdir e.data.path
@location.set "items", [
- { text: "Home", path: 'home:///', iconclass:"fa fa-home", selected:true},
- { text: "OS", path: 'os:///', iconclass:"fa fa-inbox" },
+ { text: "Home", path: 'home:///', iconclass: "fa fa-home", selected: true },
+ { text: "OS", path: 'os:///', iconclass: "fa fa-inbox" },
{ text: "Desktop", path: 'home:///.desktop', iconclass: "fa fa-desktop" },
]
+ @open @currfile if @currfile
+
+ open: (file) ->
+ me = @
+ file.read (d) ->
+ return unless d
+ me.scheme.set "apptitle", file.basename
+ me.editor.setValue d, -1
+
chdir: (p) ->
me = @
me._api.handler.scandir p,
@@ -82,10 +92,10 @@ class NotePad extends this.OS.GUI.BaseApplication
menu: ()->
menu = [{
- text:"File",
- child:[
- {text:"Open", dataid:"#{@name}-Open"},
- {text:"Close", dataid:"#{@name}-Close"}
+ text: "File",
+ child: [
+ { text: "Open", dataid: "#{@name}-Open" },
+ { text: "Close", dataid: "#{@name}-Close" }
]
}]
menu
diff --git a/src/packages/NotePad/package.json b/src/packages/NotePad/package.json
index 8119eaa..775719a 100644
--- a/src/packages/NotePad/package.json
+++ b/src/packages/NotePad/package.json
@@ -9,5 +9,5 @@
"version":"0.1a",
"category":"System",
"iconclass":"fa fa-pencil-square-o",
- "mimes":["*"]
+ "mimes":[".*"]
}
\ No newline at end of file
diff --git a/src/packages/wTerm/main.coffee b/src/packages/wTerm/main.coffee
index 5e21ac1..11cab14 100644
--- a/src/packages/wTerm/main.coffee
+++ b/src/packages/wTerm/main.coffee
@@ -64,6 +64,7 @@ class wTerm extends this.OS.GUI.BaseApplication
@socket.onmessage = (e) -> me.term.write e.data if me.term and e.data
@socket.onclose = () ->
me.socket = null
+ me.quit()
console.log "socket closed"
#el.style.display = "block"
cleanup: (e)->
diff --git a/src/themes/antos/antos.css b/src/themes/antos/antos.css
index b93c2e2..e3b75f8 100644
--- a/src/themes/antos/antos.css
+++ b/src/themes/antos/antos.css
@@ -42,6 +42,48 @@ html,body{
cursor: default;
padding:0px;
}
+#desktop > div.float_list_item {
+ display:block;
+ background-color:transparent;
+ text-align: center;
+ width: 70px;
+ color: white;
+ padding:3px;
+}
+
+#desktop > div.float_list_item_selected {
+ display:block;
+ background-color: #116cd6;
+ color:white;
+ border-radius: 6px;
+ text-align: center;
+ width: 70px;
+ color: white;
+ padding:3px;
+}
+
+#desktop > div.float_list_item i.file:before{
+ content: "\f15b\a";
+ font-family: "FontAwesome";
+ font-size: 32px;
+ display: block;
+ color: white;
+ font-style: normal;
+ font-weight: normal;
+}
+#desktop > div.float_list_item span{
+ width: 100%;
+ word-wrap: break-word;
+}
+#desktop > div.float_list_item i.dir:before{
+ display: block;
+ content: "\f07b\a";
+ font-family: "FontAwesome";
+ font-size: 32px;
+ color: #76D2F9;
+ font-weight: normal;
+ font-style: normal;
+}
input {
outline: none;
padding: 2px;