Permalink
Browse files

[feature] stdlib: added an experimental UI library

Rescued this interesting proposal for an UI library. Although it is very
experimental, I think it's worth of being on master, as a proposal towards a
better UI library. Note: most of the work due to David.
  • Loading branch information...
1 parent 7409d79 commit c252d10c3dcbe000dc5ab82741120e42222095ee François-Régis Sinot committed Oct 12, 2011
View
@@ -0,0 +1,133 @@
+/*
+ Copyright © 2011 MLstate
+
+ This file is part of OPA.
+
+ OPA is free software: you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License, version 3, as published by
+ the Free Software Foundation.
+
+ OPA is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
+ more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with OPA. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * Elvis Buttons
+ *
+ * @category UI
+ * @author David Rajchenbach-Teller, 2011
+ * @destination PUBLIC
+ * @stability EXPERIMENTAL
+ */
+
+/**
+ * {1 Simple clickable}
+ *
+ * Native button.
+ */
+
+/**
+ * {1 Theming}
+ *
+ * The button always has classes "mlstate" "elvis" "button"
+ * During a click, it also has class "down", otherwise it has class "up"
+ * When enabled, it has class "enabled", otherwise it has class "disabled"
+ */
+
+type EButton.options = {
+ content: xhtml
+ is_enabled: bool
+}
+
+type EButton.sources = {
+ chosen: Event.source(void)
+}
+@abstract type EButton.implementation = {
+ dom: dom
+ state_enabled: Client.reference(bool)
+}
+
+type EButton.elvis = Elvis.elvis(EButton.sources, EButton.implementation)
+
+EButton =
+{{
+/**
+ * {1 Constructors}
+ */
+ simple(content:xhtml): EButton.elvis =
+ make({is_enabled = true
+ content = content})
+
+ make(options:EButton.options): EButton.elvis =
+ (
+ id = "ebutton_{Random.string(32)}"
+ dom = Dom.select_id(id)
+ chosen_net = Network.empty()
+ state_enabled = Client_reference.create(options.is_enabled)
+ display(theme) =
+ (
+ mouse_changed(up) =
+ (
+ if Client_reference.get(state_enabled) then
+ dom = Dom.resolve(dom)
+ if up then
+ do Dom.remove_class(dom, class_down)
+ do Dom.add_class(dom, class_up)
+ void
+ else
+ do Dom.remove_class(dom, class_up)
+ do Dom.add_class(dom, class_down)
+ void
+ )
+ theme_classes = Elvis.Theme.get_classes(theme)
+ xhtml = <button id={id}
+ class="{theme_classes} elvis mlstate button {class_up} {if Client_reference.get(state_enabled) then class_enabled else class_disabled}"
+ onclick={_ -> if Client_reference.get(state_enabled) then Network.broadcast({}, chosen_net) else void}
+ onmouseup={_ -> mouse_changed({true})}
+ onmousedown={_ -> mouse_changed({false})}
+ >{
+ options.content
+ }</button>
+ dom = Dom.of_xhtml(xhtml)
+ ~{xhtml dom}
+ )
+ implem = ({
+ ~dom
+ ~state_enabled
+ })
+ sources = {
+ chosen = (chosen_net)
+ }
+ Elvis.make(sources, implem, display)
+ )
+
+/**
+ * {1 Accessors}
+ */
+ set_enabled(button: EButton.elvis, enabled: bool): void =
+ (
+ implem = (Elvis.implem(button))
+ dom = Dom.resolve(implem.dom)
+ state_enabled = implem.state_enabled
+ do if enabled != Client_reference.get(state_enabled) then
+ if enabled then
+ do Dom.remove_class(dom, class_disabled)
+ do Dom.add_class(dom, class_enabled)
+ void
+ else
+ do Dom.remove_class(dom, class_enabled)
+ do Dom.add_class(dom, class_disabled)
+ void
+ Client_reference.set(state_enabled, enabled)
+ )
+
+ @private class_enabled = "enabled"
+ @private class_disabled= "disabled"
+ @private class_up = "up"
+ @private class_down = "down"
+}}
View
@@ -0,0 +1,147 @@
+/*
+ Copyright © 2011 MLstate
+
+ This file is part of OPA.
+
+ OPA is free software: you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License, version 3, as published by
+ the Free Software Foundation.
+
+ OPA is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
+ more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with OPA. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * Elvis Clickables
+ *
+ * @category UI
+ * @author David Rajchenbach-Teller, 2011
+ * @destination PUBLIC
+ * @stability EXPERIMENTAL
+ */
+
+/**
+ * {1 Simple clickable}
+ *
+ * Wrap an elvis as something clickable.
+ */
+
+/**
+ * {1 Theming}
+ *
+ * The clickable always has classes "mlstate" "elvis" "clickable"
+ * During a click, it also has class "down", otherwise it has class "up"
+ * When enabled, it has class "enabled", otherwise it has class "disabled"
+ */
+
+type EClickable.options = {
+ content: Elvis.elvis(Elvis.masked, Elvis.masked)
+ is_enabled: bool
+}
+
+type EClickable.sources = {
+ chosen: Event.source(void)
+ //unfocused:Event.source(void)
+ dbclick: Event.source(void)
+}
+@abstract type EClickable.implementation = {
+ dom: dom
+ state_enabled: Client.reference(bool)
+}
+
+type EClickable.elvis = Elvis.elvis(EClickable.sources, EClickable.implementation)
+
+EClickable =
+{{
+/**
+ * {1 Constructors}
+ */
+ simple(content:xhtml): EClickable.elvis =
+ make({is_enabled = true
+ content = Elvis.pack(ELabel.simple(content))})
+
+ make(options:EClickable.options): EClickable.elvis =
+ (
+ id = "eclickable_{Random.string(32)}"
+ dom = Dom.select_id(id)
+ chosen_net = Network.empty()
+ dbclick_net = Network.empty()
+ //unfocused_net = Network.empty()
+ state_enabled = Client_reference.create(options.is_enabled)
+ display(theme) =
+ (
+ mouse_changed(up) =
+ (
+ if Client_reference.get(state_enabled) then
+ dom = Dom.resolve(dom)
+ if up then
+ do Dom.remove_class(dom, class_down)
+ do Dom.add_class(dom, class_up)
+ void
+ else
+ do Dom.remove_class(dom, class_up)
+ do Dom.add_class(dom, class_down)
+ void
+ )
+ theme_classes = Elvis.Theme.get_classes(theme)
+ xhtml = <div id={id}
+ class="{theme_classes} elvis mlstate clickable {class_up} {if Client_reference.get(state_enabled) then class_enabled else class_disabled}"
+ onclick={_ -> if Client_reference.get(state_enabled) then Network.broadcast({}, chosen_net) else void}
+ ondblclick={_ -> if Client_reference.get(state_enabled) then Network.broadcast({}, dbclick_net) else void}
+ //onfocusout={_ -> Network.broadcast({}, unfocused_net)}
+ onmouseup={_ -> mouse_changed({true})}
+ onmousedown={_ -> mouse_changed({false})}>
+ <div class="{theme_classes} elvis mlstate clickable_content">{
+ Elvis.for_display_in_theme(options.content, theme)
+ }</div></div>
+ dom = Dom.of_xhtml(xhtml)
+ ~{xhtml dom}
+ )
+ implem = ({
+ ~dom
+ ~state_enabled
+ })
+ sources = {
+ chosen = (chosen_net)
+ dbclick = (dbclick_net)
+ //unfocused = (unfocused_net)
+ }
+ Elvis.make(sources, implem, display)
+ )
+
+ default_options =
+ {
+ content = ELabel.simple(<>Nothing to see</>)
+ is_enabled = {true}
+ }
+/**
+ * {1 Accessors}
+ */
+ set_enabled(clickable: EClickable.elvis, enabled: bool): void =
+ (
+ implem = (Elvis.implem(clickable))
+ dom = Dom.resolve(implem.dom)
+ state_enabled = implem.state_enabled
+ do if enabled != Client_reference.get(state_enabled) then
+ if enabled then
+ do Dom.remove_class(dom, class_disabled)
+ do Dom.add_class(dom, class_enabled)
+ void
+ else
+ do Dom.remove_class(dom, class_enabled)
+ do Dom.add_class(dom, class_disabled)
+ void
+ Client_reference.set(state_enabled, enabled)
+ )
+
+ @private class_enabled = "enabled"
+ @private class_disabled= "disabled"
+ @private class_up = "up"
+ @private class_down = "down"
+}}
+
Oops, something went wrong.

0 comments on commit c252d10

Please sign in to comment.