diff --git a/Makefile b/Makefile index 26e664d..4d444b2 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,8 @@ coffees= src/core/core.coffee\ src/core/BaseService.coffee\ src/core/BaseEvent.coffee\ src/core/BaseDialog.coffee\ - src/core/tag.coffee\ + src/core/tags/tag.coffee\ + src/core/tags/WindowTag.coffee\ src/antos.coffee diff --git a/src/core/tags/TileLayoutTags.coffee b/src/core/tags/TileLayoutTags.coffee new file mode 100644 index 0000000..e9d2902 --- /dev/null +++ b/src/core/tags/TileLayoutTags.coffee @@ -0,0 +1,41 @@ +class TileLayoutTag extends Ant.OS.GUI.BaseTag + constructor: (r, o, @conf) -> + super r, o + @setopt @conf.opt, "grow" + @mount() + + mount: () -> + $(@refs.yield) + .css("display", "flex") + .css("flex-direction", @conf.dir) + .css("width", "100%") + me = @ + @observable.on "resize", (e) -> me.calibrate() + @observable.on "calibrate", (e) -> me.calibrate() + @calibrate() + + calibrate: () -> + + + layout: () -> + { + el: "div", class: "afx-#{@conf.name}-container", ref: "yield" + } + + +class HBoxTag extends TileLayoutTag + constructor: (r, o) -> + super r, o, { + name: "hbox", + dir: "row", + opt: "data-width" + } + + +class VBoxTag extends TileLayoutTag + constructor: (r, o) -> + super r, o, { + name: "vbox", + dir: "column", + opt: "data-height" + } \ No newline at end of file diff --git a/src/core/tags/WindowTag.coffee b/src/core/tags/WindowTag.coffee new file mode 100644 index 0000000..d748046 --- /dev/null +++ b/src/core/tags/WindowTag.coffee @@ -0,0 +1,200 @@ +class WindowTag extends Ant.OS.GUI.BaseTag + constructor: (r, o) -> + super r, o + @setopt "minimizable", true + @setopt "resizable", true + @setopt "apptitle", "Untitled" + @setopt "desktop", "#desktop" + @setopt "width", 400 + @setopt "height", 300 + @shown = false + @isMaxi = false + @history = {} + @desktop = $(@get "desktop") + @desktop_pos = @desktop.offset() + me = @ + @root.contextmenuHandle = (e) -> + $(@refs["minbt"]).click (e) -> + me.observable.trigger("hide") + + $(@refs["maxbt"]).click (e) -> + me.toggle_window() + + $(@refs["closebt"]).click (e) -> + me.observable.trigger("exit") + @mount() + + resize: () -> + ch = $(@refs["yield"]).height() / $(@refs["yield"]).children().length + $(@refs["yield"]).children().each (e) -> + $(this).css "height", "#{ch}px" + + mount: () -> + me = @ + left = ($(@desktop).width() - (@get "width")) / 2 + top = ($(@desktop).height() - (@get "height")) / 2 + $(@root) + .css("position", 'absolute') + .css("left", "#{left}px") + .css("top", "#{top}px") + .css("width", "#{(@get "width")}px") + .css("height", "#{(@get "height")}px") + .css("z-index", Ant.OS.GUI.zindex++) + $(@root).on "mousedown", (e) -> + return if me.shown + me.observable.trigger "focus" + + $(@refs["dragger"]).dblclick (e) -> + me.toggle_window() + + + @observable.on "resize", (e) -> me.resize() + + @observable.on "focus", () -> + Ant.OS.GUI.zindex++ + $(me.root) + .show() + .css("z-index", Ant.OS.GUI.zindex) + .removeClass("unactive") + me.shown = true + + @observable.on "blur", () -> + me.shown = false + $(me.root) + .addClass("unactive") + @observable.on "hide", () -> + $(me.root).hide() + me.shown = false + + @observable.on "toggle", () -> + if me.shown + me.observable.trigger "hide" + else + me.observable.trigger "focus" + @enable_dragging() + @enable_resize() + @resize() + @observable.trigger "rendered", @root + + on_minimizable_changed: (value) -> + if value then $(@refs["minbt"]).show() else $(@refs["minbt"]).hide() + + on_resizable_changed: (value) -> + if value + $(@refs["maxbt"]).show() + $(@refs["grip"]).show() + else + $(@refs["maxbt"]).hide() + $(@refs["grip"]).hide() + + on_apptitle_changed: (value) -> + $(@refs["dragger"]).text value.__() if value + + enable_dragging: () -> + me = @ + $(@refs["dragger"]) + .css("user-select", "none") + .css("cursor", "default") + $(@refs["dragger"]).on "mousedown", (e) -> + e.preventDefault() + offset = $(me.root).offset() + offset.top = e.clientY - offset.top + offset.left = e.clientX - offset.left + $(window).on "mousemove", (e) -> + if me.isMaxi + me.toggle_window() + top = 0 + letf = e.clientX - $(me.root).width() / 2 + offset.top = 10 + offset.left = $(me.root).width() / 2 + else + top = e.clientY - offset.top - me.desktop_pos.top + left = e.clientX - me.desktop_pos.top - offset.left + left = if left < 0 then 0 else left + top = if top < 0 then 0 else top + + $(me.root) + .css("top", "#{top}px") + .css("left", "#{left}px") + $(window).on "mouseup", (e) -> + $(window).unbind "mousemove", null + $(window).unbind "mouseup", null + + enable_resize: () -> + me = @ + $(@refs["grip"]) + .css("user-select", "none") + .css("cursor", "default") + .css("position", "absolute") + .css("bottom", "0") + .css("right", "0") + .css("cursor", "nwse-resize") + + $(@refs["grip"]).on "mousedown", (e) -> + e.preventDefault() + offset = { top: 0, left: 0 } + offset.top = e.clientY + offset.left = e.clientX + $(window).on "mousemove", (e) -> + w = $(me.root).width() + e.clientX - offset.left + h = $(me.root).height() + e.clientY - offset.top + w = if w < 100 then 100 else w + h = if h < 100 then 100 else h + offset.top = e.clientY + offset.left = e.clientX + $(me.root) + .css("width", "#{w}px") + .css("height", "#{h}px") + me.isMaxi = false + me.observable.trigger "resize", { id: me.id(), w: w, h: h } + + $(window).on "mouseup", (e) -> + $(window).unbind "mousemove", null + $(window).unbind "mouseup", null + + toggle_window: () -> + return unless @get "resizable" + me = @ + if @isMaxi is false + @history = { + top: $(@root).css("top"), + left: $(@root).css("left"), + width: $(@root).css("width"), + height: $(@root).css("height") + } + w = $(@desktop).width() - 5 + h = $(@desktop).height() - 10 + $(@root) + .css("width", "#{w}px") + .css("height", "#{h}px") + .css("top", "0") + .css("left", "0") + @observable.trigger 'resize', { id: @id(), w: w, h: h } + @isMaxi = true + else + @isMaxi = false + $(@root) + .css("width", @history.width) + .css("height", @history.height) + .css("top", @history.top) + .css("left", @history.left) + @observable.trigger 'resize', { id: @id(), w: history.width, h: history.height } + + layout: () -> + { + el: "div", class: "afx-window-wrapper", children: [ + { + el: "ul", class: "afx-window-top", children: [ + { el: "li", class: "afx-window-close", ref: "closebt" }, + { el: "li", class: "afx-window-minimize", ref: "minbt" }, + { el: "li", class: "afx-window-maximize", ref: "maxbt" }, + { el: "li", class: "afx-window-title", ref: "dragger" } + ] + }, + { el: "div", class: "afx-clear" }, + { el: "div", ref: "yield", class: "afx-window-content" }, + { el: "div", ref: "grip", class: "afx-window-grip" } + ] + } + +Ant.OS.GUI.define "afx-app-window", WindowTag \ No newline at end of file diff --git a/src/core/tags/tag.coffee b/src/core/tags/tag.coffee index ac159f6..0d14879 100644 --- a/src/core/tags/tag.coffee +++ b/src/core/tags/tag.coffee @@ -1,9 +1,67 @@ Ant.OS.GUI.tag = {} +Ant.OS.GUI.zindex = 10 +class Ant.OS.GUI.BaseTag + constructor: (@root, @observable) -> + @opts = {} + me = @ + @observable = new Ant.OS.API.Announcer() unless @observable + # export to rootnode + @root.observable = @observable + @root.set = (k, v) -> me.set k, v + @root.get = (k) -> me.get k + + @refs = {} + @setopt "data-id", Math.floor(Math.random() * 100000) + 1 + @wrapper = @mkui() + if @refs["yield"] + ($($(v).detach()[0].uify(@observable)).appendTo(@refs.yield)) for v in $(@root).children() + $(@wrapper).appendTo(@root) + else + $(@root).empty() + $(@wrapper).appendTo(@root) -Element.prototype.mount = () -> - Ant.OS.GUI.tag[@tagName](@) if RegExp('afx-*').test(@tagName) and Ant.OS.GUI.tag[@tagName] + setopt: (name, val) -> + value = val + if ($(@root).attr name) + v = $(@root).attr name + try + value = JSON.parse(v) + catch e + value = v + @set name, value + + set: (opt, value) -> + @opts[opt] = value + @["on_#{opt}_changed"](value) if @["on_#{opt}_changed"] + + id: () -> + @get "data-id" + -Ant.OS.GUI.tag.define = (name, fn) -> - Ant.OS.GUI.tag[name] = fn + get: (opt) -> + @opts[opt] + + layout: () -> + # should be defined by subclasses + + mkui: (obj) -> + tag = obj + tag = @layout() unless tag + dom = $("<#{tag.el}>") + $(dom).addClass tag.class if tag.class + if tag.children + $(@mkui(v)).appendTo(dom) for v in tag.children + if tag.ref + @refs[tag.ref] = dom + # dom.mount @observable + return dom + +Element.prototype.uify = (observable) -> + tag = @tagName.toLowerCase() + if RegExp('afx-*', "i" ).test(tag) and Ant.OS.GUI.tag[tag] + return new Ant.OS.GUI.tag[tag](@, observable).root + return @ + +Ant.OS.GUI.define = (name, cls) -> + Ant.OS.GUI.tag[name] = cls -Ant.OS.GUI.tag.mount = (obj) -> diff --git a/src/core/tags/window-tag.coffee b/src/core/tags/window-tag.coffee deleted file mode 100644 index 8ae4838..0000000 --- a/src/core/tags/window-tag.coffee +++ /dev/null @@ -1,8 +0,0 @@ - -Ant.OS.GUI.tag.define "afx-window", (tag) -> - childen = $(tag).childen() - @(tag).empty() - $(tag).append( - $("
") - .addClass("afx-window-wrapper") - .append()) \ No newline at end of file diff --git a/src/packages/ShowCase/coffees/main.coffee b/src/packages/ShowCase/coffees/main.coffee index 99ccccf..a053b38 100644 --- a/src/packages/ShowCase/coffees/main.coffee +++ b/src/packages/ShowCase/coffees/main.coffee @@ -23,14 +23,31 @@ class ShowCase extends this.OS.GUI.BaseApplication console.log me.announcer @on "btclick", (e) -> + me.openwin() + ### me.announcer.trigger("evt1", "Hello 1") me.announcer.off("*") me.announcer.trigger("evt2", "Hello 2") console.log me.announcer me.notify "Hello" - tag = new Ant.OS.GUI.tags["afx-window"]() console.log tag - + ### + openwin: () -> + scheme = $.parseHTML """ + +
+

hello

+
+
+ """ + obj = scheme[0].uify() + ($ "#desktop").append obj + obj.set "resizable", false + obj.set "minimizable", false + obj.observable.on "exit", () -> + console.log "exit" + obj.observable.off "*" + $(obj).remove() ShowCase.singleton = false this.OS.register "ShowCase", ShowCase \ No newline at end of file