diff --git a/Makefile b/Makefile index f495990..432423f 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ coffees= src/core/core.coffee\ -packages = CoreServices NotePad wTerm ActivityMonitor DummyApp Files MarkOn +packages = CoreServices NotePad wTerm ActivityMonitor DummyApp Files MarkOn MarketPlace main: build_coffees build_tags build_themes schemes libs build_packages - cp src/index.html $(BUILDDIR)/ diff --git a/src/core/BaseApplication.coffee b/src/core/BaseApplication.coffee index f00fbd2..d1a39a6 100644 --- a/src/core/BaseApplication.coffee +++ b/src/core/BaseApplication.coffee @@ -26,7 +26,7 @@ class BaseApplication extends this.OS.GUI.BaseModel when "#{me.name}-about" then me.openDialog "AboutDialog", ()-> when "#{me.name}-exit" then me.trigger "exit" #now load the scheme - path = "packages/#{@name}/scheme.html" + path = "#{@meta().path}/scheme.html" @.render path applySetting: (k) -> diff --git a/src/core/BaseDialog.coffee b/src/core/BaseDialog.coffee index 693738f..d49a16c 100644 --- a/src/core/BaseDialog.coffee +++ b/src/core/BaseDialog.coffee @@ -1,15 +1,14 @@ -class BaseDialog extends this.OS.GUI.BaseModel +class SubWindow extends this.OS.GUI.BaseModel constructor: (name) -> super name, null @parent = undefined @modal = false - @handler = undefined + quit: () -> evt = new _GUI.BaseEvent("exit") @onexit(evt) if not evt.prevent delete @.observable - @parent.dialog = undefined if @parent ($ @scheme).remove() if @scheme @dialog.quit() if @dialog init: () -> @@ -22,7 +21,17 @@ class BaseDialog extends this.OS.GUI.BaseModel hide: () -> @trigger 'hide' -BaseDialog.type = 3 +SubWindow.type = 3 +this.OS.GUI.SubWindow = SubWindow + +class BaseDialog extends SubWindow + constructor: (name) -> + super name + @handler = undefined + + onexit: (e) -> + @parent.dialog = undefined if @parent + this.OS.GUI.BaseDialog = BaseDialog ### this dialog rende a tag as main content @@ -47,8 +56,8 @@ class BasicDialog extends BaseDialog @title = @name if not @title html = " " - html += "<#{@conf.tag} #{@conf.att} data-id = 'content'>" - html += "
" + html += "<#{v.tag} #{v.att} data-id = 'content#{k}'>" for k,v of @conf.tags + html += "
" html += "" for k,v of @conf.buttons html += "
" #render the html @@ -69,16 +78,18 @@ this.OS.GUI.BasicDialog = BasicDialog class PromptDialog extends BasicDialog constructor: () -> super "PromptDialog", { - tag: "input", + tags: [ + { tag: "afx-label", att: "data-height = '20'" }, + { tag: "input", att: "type = 'text'" } + ], width: 200, - height: 90, - att: "type = 'text'" + height: 100, resizable: false, buttons: [ { label: "0k", onclick: (d) -> - txt = (d.find "content").value + txt = (d.find "content1").value return d.quit() if txt is "" d.handler txt if d.handler d.quit() @@ -90,9 +101,10 @@ class PromptDialog extends BasicDialog ], filldata: (d) -> return unless d.data - (d.find "content").value = d.data + (d.find "content0").set "text", d.data.label + (d.find "content1").value = d.data.value if d.data.value xtra: (d) -> - $( d.find "content" ).keyup (e) -> + $( d.find "content0" ).keyup (e) -> (d.find "bt0").trigger() if e.which is 13 } @@ -101,7 +113,7 @@ this.OS.register "PromptDialog", PromptDialog class CalendarDialog extends BasicDialog constructor: () -> super "CalendarDialog", { - tag: 'afx-calendar-view', + tags: [{ tag: 'afx-calendar-view' }], width: 300, height: 220, resizable: false, @@ -109,7 +121,7 @@ class CalendarDialog extends BasicDialog { label: 'Ok', onclick: (d) -> - date = (d.find "content").get "selectedDate" + date = (d.find "content0").get "selectedDate" if date d.handler date if d.handler d.quit() @@ -127,7 +139,7 @@ this.OS.register "CalendarDialog", CalendarDialog class ColorPickerDialog extends BasicDialog constructor: () -> super "ColorPickerDialog", { - tag: 'afx-color-picker', + tags: [{ tag: 'afx-color-picker' }], width: 313, height: 220, resizable: false, @@ -135,7 +147,7 @@ class ColorPickerDialog extends BasicDialog { label: 'Ok', onclick: (d) -> - c = (d.find "content").get "selectedColor" + c = (d.find "content0").get "selectedColor" if c d.handler c if d.handler d.quit() @@ -153,7 +165,7 @@ this.OS.register "ColorPickerDialog", ColorPickerDialog class InfoDialog extends BasicDialog constructor: () -> super "InfoDialog", { - tag: 'afx-grid-view', + tags: [{ tag: 'afx-grid-view' }], width: 250, height: 300, resizable: true, @@ -161,8 +173,8 @@ class InfoDialog extends BasicDialog filldata: (d) -> return unless d.data rows = [] - rows.push [ { value: k }, { value: v } ] for v, k in d.data - (d.find "content").set "rows", rows + rows.push [ { value: k }, { value: v } ] for k, v of d.data + (d.find "content0").set "rows", rows } this.OS.register "InfoDialog", InfoDialog @@ -170,10 +182,9 @@ this.OS.register "InfoDialog", InfoDialog class YesNoDialog extends BasicDialog constructor: () -> super "YesNoDialog", { - tag: "afx-label", + tags: [{ tag: "afx-label", att: "style = 'padding:10px;'" }], width: 300, height: 100, - att:"style = 'padding:10px;'" resizable: true, buttons: [ { @@ -189,7 +200,7 @@ class YesNoDialog extends BasicDialog ], filldata: (d) -> return unless d.data - l = d.find "content" + l = d.find "content0" for k, v of d.data l.set k, v } @@ -198,15 +209,14 @@ this.OS.register "YesNoDialog", YesNoDialog class SelectionDialog extends BasicDialog constructor: () -> super "SelectionDialog", { - tag: "afx-list-view", - att: "", + tags: [{ tag: "afx-list-view" }], width: 250, height: 300, resizable: false, buttons: [ { label: "Ok", onclick: (d) -> - el = d.find "content" + el = d.find "content0" it = el.get "selected" return unless it d.handler it if d.handler @@ -216,9 +226,9 @@ class SelectionDialog extends BasicDialog ], filldata: (d) -> return unless d.data - (d.find "content").set "items", d.data + (d.find "content0").set "items", d.data xtra: (d) -> - ( d.find "content" ).set "onlistdbclick", (e) -> + ( d.find "content0" ).set "onlistdbclick", (e) -> (d.find "bt0").trigger() } @@ -229,7 +239,7 @@ class AboutDialog extends BaseDialog super "AboutDialog" init: () -> - @render "resources/schemes/about.html" + @render "os:///resources/schemes/about.html" main: () -> mt = @meta() @@ -249,7 +259,7 @@ class FileDiaLog extends BaseDialog super "FileDiaLog" init: () -> - @render "resources/schemes/filedialog.html" + @render "os:///resources/schemes/filedialog.html" main: () -> fileview = @find "fileview" diff --git a/src/core/BaseModel.coffee b/src/core/BaseModel.coffee index f07a4d6..c99d135 100644 --- a/src/core/BaseModel.coffee +++ b/src/core/BaseModel.coffee @@ -37,10 +37,10 @@ class BaseModel if @dialog @dialog.show() return - if not _GUI.dialogs[d] + if not _GUI.subwindows[d] @error "Dialog #{d} not found" return - @dialog = new _GUI.dialogs[d]() + @dialog = new _GUI.subwindows[d]() @dialog.parent = @ @dialog.handler = f @dialog.pid = @pid diff --git a/src/core/BaseService.coffee b/src/core/BaseService.coffee index fbee401..98aaa1a 100644 --- a/src/core/BaseService.coffee +++ b/src/core/BaseService.coffee @@ -12,7 +12,7 @@ class BaseService extends this.OS.GUI.BaseModel # event registe, etc # scheme loader meta: () -> - @ + _OS.APP[@name].meta attach: (h) -> @holder = h diff --git a/src/core/api.coffee b/src/core/api.coffee index b96ddb7..5cf8417 100644 --- a/src/core/api.coffee +++ b/src/core/api.coffee @@ -120,6 +120,10 @@ self.OS.API = _API.handler.packages { command: "list", args: { paths: _OS.setting.system.pkgpaths } }, f + cache: (f) -> + _API.handler.packages { + command: "cache", args: { paths: _OS.setting.system.pkgpaths } + }, f throwe: (n) -> err = undefined diff --git a/src/core/core.coffee b/src/core/core.coffee index 4b5995d..e93ebac 100644 --- a/src/core/core.coffee +++ b/src/core/core.coffee @@ -38,7 +38,7 @@ self.OS or= _courrier.quota += 1 _courrier.quota register: (name, x) -> - if x.type is 3 then self.OS.GUI.dialogs[name] = x else _OS.APP[name] = x + if x.type is 3 then self.OS.GUI.subwindows[name] = x else _OS.APP[name] = x PM: pidalloc: 0 diff --git a/src/core/gui.coffee b/src/core/gui.coffee index 8910ebe..51dc638 100644 --- a/src/core/gui.coffee +++ b/src/core/gui.coffee @@ -1,5 +1,5 @@ self.OS.GUI = - dialogs: new Object() + subwindows: new Object() dialog: undefined htmlToScheme: (html, app, parent) -> scheme = $.parseHTML html @@ -9,12 +9,11 @@ self.OS.GUI = app.main() app.show() loadScheme: (path, app, parent) -> - _API.get path, - (x) -> + 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 + #, (e, s) -> + # _courrier.osfail "Cannot load scheme file: #{path} for #{app.name} (#{app.pid})", e, s clearTheme: () -> $ "head link#ostheme" @@ -37,10 +36,10 @@ self.OS.GUI = if _GUI.dialog _GUI.dialog.show() return - if not _GUI.dialogs[d] + if not _GUI.subwindows[d] ex = _API.throwe "Dialog" return _courrier.oserror "Dialog #{d} not found", ex, null - _GUI.dialog = new _GUI.dialogs[d]() + _GUI.dialog = new _GUI.subwindows[d]() _GUI.dialog.parent = _GUI _GUI.dialog.handler = f _GUI.dialog.pid = -1 @@ -105,6 +104,7 @@ self.OS.GUI = 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 css file css = "#{path}/main.css" @@ -113,15 +113,14 @@ self.OS.GUI = .appendTo 'head' , () -> #launch - if _OS.APP[app] - # load app meta data - "#{path}/package.json".asFileHandler().read (data) -> - data.path = path - _OS.APP[app].meta = data - ok app - , "json" - else + # 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 ok app + , "json" + #ok app , "script" launch: (app, args) -> if not _OS.APP[app] @@ -340,7 +339,7 @@ self.OS.GUI = "os:///packages" ] unless _OS.setting.system.pkgpaths _OS.setting.system.menu = {} unless _OS.setting.system.menu - + _OS.setting.system.repositories = [] unless _OS.setting.system.repositories _OS.setting.appearance.theme = "antos" unless _OS.setting.appearance.theme # load theme _GUI.loadTheme _OS.setting.appearance.theme @@ -348,23 +347,25 @@ self.OS.GUI = _GUI.initDM() _courrier.observable.one "syspanelloaded", () -> # TODO load packages list then build system menu - _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 [ - "CoreServices/PushNotification", - "CoreServices/Spotlight", - "CoreServices/Calendar" - ] + _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 [ + "CoreServices/PushNotification", + "CoreServices/Spotlight", + "CoreServices/Calendar" + ] #_GUI.launch "DummyApp" # startup application here diff --git a/src/core/tags/afx-hbox.js b/src/core/tags/afx-hbox.js index 1247bde..97d2a8f 100644 --- a/src/core/tags/afx-hbox.js +++ b/src/core/tags/afx-hbox.js @@ -4,6 +4,7 @@
\ 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 68b5d99..3e5aeea 100644 --- a/src/core/tags/afx-list-view.js +++ b/src/core/tags/afx-list-view.js @@ -98,6 +98,11 @@ .css("display","none") .css("top","100%") .css("left","0") + + self.root.observable.on("vboxchange", function(e){ + if(e.id == self.parent.rid) + $(self.refs.container).css("width", $(self.root).parent().innerWidth() + "px" ) + }) } }) show_list(event) diff --git a/src/core/tags/afx-resizer.js b/src/core/tags/afx-resizer.js index e007ee7..9dba6d3 100644 --- a/src/core/tags/afx-resizer.js +++ b/src/core/tags/afx-resizer.js @@ -64,7 +64,7 @@ w = Math.round(e.clientX - offset.left) if(w < self.minsize) w = self.minsize $(self.resizable).attr("data-width", w.toString()) - self.parent.root.observable.trigger("calibrate") + self.parent.root.observable.trigger("calibrate", self.resizable) } var verticalResize = function(e) @@ -77,7 +77,7 @@ h = Math.round(e.clientY - offset.top) if(h < self.minsize) h = minsize $(self.resizable).attr("data-height", h.toString()) - self.parent.root.observable.trigger("calibrate") + self.parent.root.observable.trigger("calibrate", self.resizable) } diff --git a/src/core/tags/afx-vbox.js b/src/core/tags/afx-vbox.js index 91c829e..e6ce1c9 100644 --- a/src/core/tags/afx-vbox.js +++ b/src/core/tags/afx-vbox.js @@ -4,6 +4,7 @@
\ No newline at end of file diff --git a/src/packages/CoreServices/PushNotification.coffee b/src/packages/CoreServices/PushNotification.coffee index 763d1b5..f4f79ba 100644 --- a/src/packages/CoreServices/PushNotification.coffee +++ b/src/packages/CoreServices/PushNotification.coffee @@ -7,7 +7,7 @@ class PushNotification extends this.OS.GUI.BaseService @pending = [] init: -> @view = false - path = path = "packages/CoreServices/notifications.html" + path = path = "#{@meta().path}/notifications.html" @render path spin: (b) -> diff --git a/src/packages/CoreServices/package.json b/src/packages/CoreServices/package.json index 7691707..65e8fd1 100644 --- a/src/packages/CoreServices/package.json +++ b/src/packages/CoreServices/package.json @@ -1,6 +1,6 @@ { "app":null, - "services": [ "Calendar", "PushNotification", "Spotlight" ] + "services": [ "Calendar", "PushNotification", "Spotlight" ], "name":"CoreServices", "description":"This is the core services", "info":{ diff --git a/src/packages/Files/main.coffee b/src/packages/Files/main.coffee index e2854cc..b1d4497 100644 --- a/src/packages/Files/main.coffee +++ b/src/packages/Files/main.coffee @@ -181,7 +181,7 @@ class Files extends this.OS.GUI.BaseApplication file.path.asFileHandler() .move "#{me.currdir.path}/#{d}", (r) -> me.error "Fail to rename to #{d}: #{r.error}" if r.error - , "Rename", file.filename + , "Rename", { label: "File name:", value: file.filename } when "#{@name}-rm" return unless file @@ -232,7 +232,7 @@ class Files extends this.OS.GUI.BaseApplication (d) -> me.currdir.mk d, (r) -> me.error "Fail to create #{d}: #{r.error}" if r.error - , "New folder" + , "New folder", { label: "Folder name:" } when "#{@name}-mkf" @openDialog "PromptDialog", @@ -240,7 +240,7 @@ class Files extends this.OS.GUI.BaseApplication fp = "#{me.currdir.path}/#{d}".asFileHandler() fp.write "", (r) -> me.error "Fail to create #{d}: #{r.error}" if r.error - , "New file" + , "New file", { label: "File name:" } when "#{@name}-info" return unless file diff --git a/src/packages/MarketPlace/Makefile b/src/packages/MarketPlace/Makefile new file mode 100644 index 0000000..fd8eec2 --- /dev/null +++ b/src/packages/MarketPlace/Makefile @@ -0,0 +1,11 @@ +coffee_files = dialog.coffee main.coffee + +jsfiles = + +cssfiles = main.css + +copyfiles = repositorydia.html scheme.html package.json + + +PKG_NAME=MarketPlace +include ../pkg.mk \ No newline at end of file diff --git a/src/packages/MarketPlace/dialog.coffee b/src/packages/MarketPlace/dialog.coffee new file mode 100644 index 0000000..77044d6 --- /dev/null +++ b/src/packages/MarketPlace/dialog.coffee @@ -0,0 +1,18 @@ +class RepositoryDialog extends this.OS.GUI.BaseDialog + constructor: () -> + super "RepositoryDialog" + + init: () -> + @render "#{@meta().path}/repositorydia.html" + + main: () -> + me = @ + @list = @find "repo-list" + ls = ({ text: v.name, iconclass: "fa fa-link", url: v.url + } for v in @systemsetting.system.repositories) + @url = @find "repo-url" + @list.set "onlistselect", (e) -> + ($ me.url).html e.data.url + @list.set "items", ls + +this.OS.register "RepositoryDialog", RepositoryDialog \ No newline at end of file diff --git a/src/packages/MarketPlace/main.coffee b/src/packages/MarketPlace/main.coffee new file mode 100644 index 0000000..89b2776 --- /dev/null +++ b/src/packages/MarketPlace/main.coffee @@ -0,0 +1,66 @@ +class MarketPlace extends this.OS.GUI.BaseApplication + constructor: (args) -> + super "MarketPlace", args + + main: () -> + me = @ + # test repository + @systemsetting.system.repositories.push { + text: "Antos repository" + url: "http://127.0.0.1:9191/repo/packages.json" + name: "Antos repository" + selected:true + } if @systemsetting.system.repositories.length is 0 + @repo = @find "repo" + @repo.set "onlistselect", (e) -> + return unless e.data + me.fetchApps e.data.url + @repo.set "items", @systemsetting.system.repositories + + @applist = @find "applist" + @applist.set "onlistselect", (e) -> + return unless e.data + me.appDetail e.data + @container = @find "container" + @appname = @find "appname" + @appdesc = @find "app-desc" + @appdetail = @find "app-detail" + @btinstall = @find "bt-install" + @btremove = @find "bt-remove" + @btexec = @find "bt-exec" + ($ @container ).css "visibility", "hidden" + @btexec.set "onbtclick", (e) -> + app = me.applist.get "selected" + return unless app + me._gui.launch app.className if app.className + @btinstall.set "onbtclick", (e) -> + me.openDialog "RepositoryDialog" + fetchApps: (url) -> + me = @ + @_api.get url, ( d ) -> + for v in d + v.text = v.name + v.iconclass = "fa fa-adn" + me.applist.set "items", d + , (e, s) -> + me.error "Fail to fetch packages list from: #{url}" + + appDetail: (d) -> + ($ @container).css "visibility", "visible" + ( $ @appname ).html d.name + ($ @appdesc).html d.description if d.description + + if @systemsetting.system.packages[d.className] + ($ @btinstall).hide() + ($ @btremove).show() + ($ @btexec).show() + else + ($ @btinstall).show() + ($ @btremove).hide() + ($ @btexec).hide() + + ($ @appdetail).empty() + for k, v of d when k isnt "name" and k isnt "description" + ($ @appdetail).append $("
  • ").append(($ "").html k).append $("").html v + +this.OS.register "MarketPlace", MarketPlace \ No newline at end of file diff --git a/src/packages/MarketPlace/main.css b/src/packages/MarketPlace/main.css new file mode 100644 index 0000000..b617cb9 --- /dev/null +++ b/src/packages/MarketPlace/main.css @@ -0,0 +1,59 @@ +afx-app-window[data-id ='marketplace-win'] afx-resizer{ + background-color: transparent; + border-left: 1px solid #cbcbcb; +} +afx-app-window[data-id ='marketplace-win'] afx-list-view[data-id='applist']{ + background-color: #f6F6F6; + padding:0; +} +afx-app-window[data-id="marketplace-win"] afx-list-view[data-id='repo'] div.list-container{ + z-index: 10; +} + +afx-app-window[data-id="marketplace-win"] afx-vbox[data-id='container'] { + color: #414339; + overflow-y: auto; +} +afx-app-window[data-id="marketplace-win"] afx-vbox[data-id='container'] afx-hbox { + padding-left: 10px; +} +afx-app-window[data-id="marketplace-win"] div[data-id='appname'] { + font-weight: bold; + font-size: 20px; + padding: 10px; + color: #414339; +} + +afx-app-window[data-id="marketplace-win"] div[data-id='appname']:before { + content: "\f085"; + font-family: "FontAwesome"; + font-size: 25px; + font-style: normal; + margin-right: 10px; + color: #414339; +} +afx-app-window[data-id="marketplace-win"] p[data-id='app-desc'] { + text-align: justify; + padding:10px; + padding-top: 0; +} +afx-app-window[data-id="marketplace-win"] ul[data-id='app-detail'] { + padding:0; + padding-left:10px; + display: table; + margin: 0; +} +afx-app-window[data-id="marketplace-win"] ul[data-id='app-detail'] li{ + padding:0; + margin: 0; + display: table-row; +} +afx-app-window[data-id="marketplace-win"] ul[data-id='app-detail'] span{ + display: table-cell; + padding: 5px; + padding-bottom: 2px; + padding-top: 2px; +} +afx-app-window[data-id="marketplace-win"] span.info-header{ + font-weight: bold; +} \ No newline at end of file diff --git a/src/packages/MarketPlace/package.json b/src/packages/MarketPlace/package.json new file mode 100644 index 0000000..7954bf5 --- /dev/null +++ b/src/packages/MarketPlace/package.json @@ -0,0 +1,13 @@ +{ + "app":"MarketPlace", + "name":"Application store", + "description":"Application store and repository management", + "info":{ + "author": "Xuan Sang LE", + "email": "xsang.le@gmail.com" + }, + "version":"0.1a", + "category":"System", + "iconclass":"fa fa-adn", + "mimes":["none"] +} \ No newline at end of file diff --git a/src/packages/MarketPlace/repositorydia.html b/src/packages/MarketPlace/repositorydia.html new file mode 100644 index 0000000..bf35226 --- /dev/null +++ b/src/packages/MarketPlace/repositorydia.html @@ -0,0 +1,12 @@ + + + +
    + + + +
    + +
    +
    +
    \ No newline at end of file diff --git a/src/packages/MarketPlace/scheme.html b/src/packages/MarketPlace/scheme.html new file mode 100644 index 0000000..d059468 --- /dev/null +++ b/src/packages/MarketPlace/scheme.html @@ -0,0 +1,23 @@ + + + + + + + + +
    + + + + +
    +
    +
    +

    +
      +
      +
      + +
      +
      \ No newline at end of file