self.OS.GUI = subwindows: new Object() dialog: undefined fullscreen: false shortcut: ALT: {} CTRL: {} SHIFT: {} META: {} htmlToScheme: (html, app, parent) -> scheme = $.parseHTML html ($ parent).append scheme riot.mount ($ scheme), { observable: app.observable } app.scheme = scheme[0] app.main() app.show() loadScheme: (path, app, parent) -> path.asFileHandler().read (x) -> return null unless x _GUI.htmlToScheme x, app, parent #, (e, s) -> # _courrier.osfail "Cannot load scheme file: #{path} for #{app.name} (#{app.pid})", e, s clearTheme: () -> $ "head link#ostheme" .attr "href", "" loadTheme: (name, force) -> _GUI.clearTheme() if force path = "resources/themes/#{name}/#{name}.css" $ "head link#ostheme" .attr "href", path pushServices: (srvs) -> return unless srvs.length > 0 _courrier.observable.one "srvroutineready", () -> srvs.splice 0, 1 _GUI.pushServices srvs _GUI.pushService srvs[0] openDialog: (d, f, title, data) -> if _GUI.dialog _GUI.dialog.show() return if not _GUI.subwindows[d] ex = _API.throwe "Dialog" return _courrier.oserror "Dialog #{d} not found", ex, null _GUI.dialog = new _GUI.subwindows[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] app = arr[0] return _PM.createProcess srv, _OS.APP[srv] if _OS.APP[srv] _GUI.loadApp app, (a) -> return _PM.createProcess srv, _OS.APP[srv] if _OS.APP[srv] (e, s) -> _courrier.trigger "srvroutineready", srv _courrier.osfail "Cannot read service script: #{srv} ", e, s appsByMime: (mime) -> metas = ( v for k, v of _OS.setting.system.packages when v.app ) mimes = ( m.mimes for m in metas when m) apps = [] # search app by mimes f = ( arr, idx ) -> try arr.filter (m, i) -> if mime.match (new RegExp m, "g") apps.push metas[idx] return false return false catch e _courrier.osfail "Find app by mimes #{mime}", e, mime ( f m, i if m ) for m, i in mimes return apps appsWithServices: () -> o = {} o[k] = v for k, v of _OS.setting.system.packages when v.services and v.services.length > 0 o openWith: (it) -> return unless it return _GUI.launch it.app if it.type is "app" and it.app return _courrier.osinfo "Application#{it.text} is not executable" if it.type is "app" apps = _GUI.appsByMime ( if it.type is "dir" then "dir" else it.mime ) return _courrier.osinfo "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 ($ _OS.APP[app].style).remove() if _OS.APP[app] and _OS.APP[app].style _OS.APP[app] = undefined _GUI.launch app, args loadApp: (app, ok, err) -> path = "os:///packages/#{app}" path = _OS.setting.system.packages[app].path if _OS.setting.system.packages[app].path js = path + "/main.js" js.asFileHandler().read (d) -> # load app meta data "#{path}/package.json".asFileHandler().read (data) -> data.path = path _OS.APP[app].meta = data if _OS.APP[app] _OS.APP[v].meta = data for v in data.services if data.services #load css file css = "#{path}/main.css" css.asFileHandler().onready (d) -> el = $ '', { rel: 'stylesheet', type: 'text/css', 'href': "#{_API.handler.get}/#{css}" } .appendTo 'head' _OS.APP[app].style = el[0] if _OS.APP[app] ok app , () -> #launch ok app , "json" #ok app , "script" launch: (app, args) -> if not _OS.APP[app] # first load it _GUI.loadApp app, (a)-> _PM.createProcess a, _OS.APP[a], args , (e, s) -> else # now launch it if _OS.APP[app] _PM.createProcess app, _OS.APP[app], args dock: (app, meta) -> # dock an application to a dock # create a data object data = icon: null iconclass: meta.iconclass || "" app: app onbtclick: () -> app.toggle() # TODO: this path is not good, need to create a blob of it data.icon = "#{_API.handler.get}/#{meta.path}/#{meta.icon}" if meta.icon # TODO: add default app icon class in system setting # so that it can be themed data.iconclass = "fa fa-cogs" if (not meta.icon) and (not meta.iconclass) dock = $ "#sysdock" app.one "rendered", () -> dock.get(0).newapp data app.sysdock = dock.get(0) app.appmenu = ($ "[data-id = 'appmenu']", "#syspanel")[0] app.init() toggleFullscreen: () -> el = ($ "body")[0] if _GUI.fullscreen return document.exitFullscreen() if document.exitFullscreen return document.mozCancelFullScreen() if document.mozCancelFullScreen return document.webkitExitFullscreen() if document.webkitExitFullscreen return document.cancelFullScreen() if document.cancelFullScreen else return el.requestFullscreen() if el.requestFullscreen return el.mozRequestFullScreen() if el.mozRequestFullScreen return el.webkitRequestFullscreen() if el.webkitRequestFullscreen return el.msRequestFullscreen() if el.msRequestFullscreen undock: (app) -> ($ "#sysdock").get(0).removeapp app attachservice: (srv) -> ($ "#syspanel")[0].attachservice srv srv.init() detachservice: (srv) -> ($ "#syspanel")[0].detachservice srv bindContextMenu: (event) -> handler = (e) -> if e.contextmenuHandler e.contextmenuHandler event, ($ "#contextmenu")[0] else p = $(e).parent().get(0) handler p if p isnt ($ "#workspace").get(0) handler event.target event.preventDefault() bindKey: (k, f) -> arr = k.split "-" return unless arr.length is 2 fnk = arr[0].toUpperCase() c = arr[1].toUpperCase() return unless _GUI.shortcut[fnk] _GUI.shortcut[fnk][c] = f initDM: -> ($ document).on 'webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange', ()-> _GUI.fullscreen = not _GUI.fullscreen # check login first _API.resource "schemes/dm.html", (x) -> return null unless x scheme = $.parseHTML x ($ "#wrapper").append scheme _courrier.observable.one "sysdockloaded", () -> ($ window).bind 'keydown', (event) -> dock = ($ "#sysdock")[0] return unless dock app = dock.get "selectedApp" #return true unless app c = String.fromCharCode(event.which).toUpperCase() fnk = undefined if event.ctrlKey fnk = "CTRL" else if event.metaKey fnk = "META" else if event.shiftKey fnk = "SHIFT" else if event.altKey fnk = "ALT" return unless fnk r = if app then app.shortcut fnk, c, event else true return event.preventDefault() if not r return unless _GUI.shortcut[fnk] return unless _GUI.shortcut[fnk][c] _GUI.shortcut[fnk][c](event) event.preventDefault() # 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 default file manager desktop = $ "#desktop" fp = _OS.setting.desktop.path.asFileHandler() desktop[0].fetch = () -> 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) -> return unless e.target is desktop[0] desktop[0].set "selected", -1 ($ "#sysdock").get(0).set "selectedApp", null #console.log "desktop clicked" desktop[0].contextmenuHandler = (e, m) -> desktop[0].set "selected", -1 if e.target is desktop[0] ($ "#sysdock").get(0).set "selectedApp", null menu = [ { text: "Open", dataid: "desktop-open" }, { text: "Refresh", dataid: "desktop-refresh" } ] menu = menu.concat ( v for k, v of _OS.setting.desktop.menu) m.set "items", menu m.set "onmenuselect", (evt) -> switch evt.item.data.dataid when "desktop-open" it = desktop[0].get "selected" return _GUI.openWith it if it it = _OS.setting.desktop.path.asFileHandler() it.mime = "dir" _GUI.openWith it when "desktop-refresh" desktop[0].fetch() else _GUI.launch evt.item.data.app, evt.item.data.args if evt.item.data.app m.show(e) desktop[0].fetch() _courrier.observable.on "VFS", (d) -> desktop[0].fetch() if d.data.file.hash() is fp.hash() or d.data.file.parent().hash() is fp.hash() _courrier.ostrigger "desktoploaded" # mount it riot.mount desktop , (e, s) -> alert "System fall: Cannot init desktop manager" console.log s, e buildSystemMenu: () -> menu = text: "" iconclass: "fa fa-eercast" dataid: "sys-menu-root" child: [ { text: "Application", child: ( v for k, v of _OS.setting.system.packages when v.app ), dataid: "sys-apps" iconclass: "fa fa-adn", onmenuselect: (d) -> _GUI.launch d.item.data.app } ] menu.child = menu.child.concat (v for k, v of _OS.setting.system.menu) menu.child.push text: "Toggle Full screen", dataid: "os-fullsize", iconclass: "fa fa-tv" menu.child.push text: "Log out", dataid: "sys-logout", iconclass: "fa fa-user-times" menu.onmenuselect = (d) -> return _OS.exit() if d.item.data.dataid is "sys-logout" return _GUI.toggleFullscreen() if d.item.data.dataid is "os-fullsize" _GUI.launch d.item.data.app unless d.item.data.dataid ($ "[data-id = 'os_menu']", "#syspanel")[0].set "items", [menu] #console.log menu login: () -> _OS.cleanup() _API.resource "schemes/login.html", (x) -> return null unless x scheme = $.parseHTML x ($ "#wrapper").append scheme ($ "#btlogin").click () -> data = username: ($ "#txtuser").val(), password: ($ "#txtpass").val() _API.handler.login data, (d) -> if d.error then ($ "#login_error").html d.error else _GUI.startAntOS d.result ($ "#txtpass").keyup (e) -> ($ "#btlogin").click() if e.which is 13 , (e, s) -> alert "System fall: Cannot init login screen" startAntOS: (conf) -> # clean up things _OS.cleanup() # get setting from conf _OS.systemSetting(conf) #console.log _OS.setting # load theme _GUI.loadTheme _OS.setting.appearance.theme # initDM _GUI.initDM() _courrier.observable.one "syspanelloaded", () -> # TODO load packages list then build system menu _API.packages.cache (ret) -> if ret.result _API.packages.fetch (r) -> if r.result for k, v of r.result v.text = v.name v.filename = k v.type = "app" v.mime = "antos/app" v.iconclass = "fa fa-adn" unless v.iconclass or v.icon _OS.setting.system.packages = if r.result then r.result else _GUI.buildSystemMenu() # push startup services # TODO: get services list from user setting _GUI.pushServices (v for v in _OS.setting.system.startup.services) (_GUI.launch a) for a in _OS.setting.system.startup.apps #_GUI.launch "DummyApp"