From 550d43ae0b37eb600299b7f85b818c3e2d34e30b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Wed, 14 Nov 2012 01:35:34 -0800 Subject: [PATCH] Check in first version of Scriptographer-style Palette / Component GUI code, including a basic example. It kinda works already! --- examples/Interface/Palette.html | 71 ++++++++++++++ src/paper.js | 3 + src/ui/Component.js | 165 ++++++++++++++++++++++++++++++++ src/ui/Palette.js | 70 ++++++++++++++ 4 files changed, 309 insertions(+) create mode 100644 examples/Interface/Palette.html create mode 100644 src/ui/Component.js create mode 100644 src/ui/Palette.js diff --git a/examples/Interface/Palette.html b/examples/Interface/Palette.html new file mode 100644 index 00000000..34d14f88 --- /dev/null +++ b/examples/Interface/Palette.html @@ -0,0 +1,71 @@ + + + + + Paelette + + + + + + + + \ No newline at end of file diff --git a/src/paper.js b/src/paper.js index cccc226d..f745adb9 100644 --- a/src/paper.js +++ b/src/paper.js @@ -123,6 +123,9 @@ var paper = new function() { /*#*/ include('ui/Key.js'); /*#*/ include('ui/MouseEvent.js'); +/*#*/ include('ui/Palette.js'); +/*#*/ include('ui/Component.js'); + /*#*/ include('tool/ToolEvent.js'); /*#*/ include('tool/Tool.js'); /*#*/ } // options.browser diff --git a/src/ui/Component.js b/src/ui/Component.js new file mode 100644 index 00000000..49c314a1 --- /dev/null +++ b/src/ui/Component.js @@ -0,0 +1,165 @@ +/* + * Paper.js + * + * This file is part of Paper.js, a JavaScript Vector Graphics Library, + * based on Scriptographer.org and designed to be largely API compatible. + * http://paperjs.org/ + * http://scriptographer.org/ + * + * Copyright (c) 2011, Juerg Lehni & Jonathan Puckey + * http://lehni.org/ & http://jonathanpuckey.com/ + * + * Distributed under the MIT license. See LICENSE file for details. + * + * All rights reserved. + */ + +var Component = this.Component = Base.extend(Callback, /** @lends Component# */{ + _events: [ 'onChange', 'onClick' ], + + _types: { + 'boolean': { + type: 'checkbox', + value: 'checked' + }, + + string: { + type: 'text' + }, + + number: { + type: 'number' + }, + + button: { + type: 'button' + }, + + text: { + tag: 'div', + value: 'text' + }, + + slider: { + type: 'range' + }, + + list: { + tag: 'select', + options: function() { + DomElement.removeChildren(this.element); + DomElement.create(Base.each(this._options, function(option) { + this.push('option', { value: option, text: option }); + }, []), this.element); + }, + + value: function(value) { + DomElement.set( + DomElement.find('option[value="' + value + '"]', this.element), + 'selected', true); + } + } + }, + + initialize: function(obj) { + this._type = obj.type + || ('options' in obj + ? 'list' + : 'onClick' in obj + ? 'button' + : typeof value); + this._info = this._types[this._type] || { type: this._type }; + var that = this, + fireChange = false; + this.element = DomElement.create(this._info.tag || 'input', { + type: this._info.type, + events: { + change: function() { + var key = that._info.value; + if (typeof key === 'function') + key = null; + var value = DomElement.get(that.element, key || 'value'); + if (fireChange) { + that.palette.fire('change', that, that.name, value); + that.fire('change', value); + } + }, + click: function() { + that.fire('click'); + } + } + }); + Base.each(obj, function(value, key) { + this[key] = value; + }, this); + this._defaultValue = this._value; + // Only fire change events after we have initalized + fireChange = true; + }, + + getType: function() { + return this._type; + }, + + getOptions: function() { + return this._options; + }, + + setOptions: function(options) { + this._options = options; + if (this._info.options) + this._info.options.call(this); + }, + + getValue: function() { + return this._value; + }, + + setValue: function(value) { + var key = this._info.value; + if (typeof key === 'function') + key.call(this, value); + else + DomElement.set(this.element, key || 'value', value); + this._value = value; + }, + + getRange: function() { + return [toFloat(DomElement.get(this.element, 'min')), + toFloat(DomElement.get(this.element, 'max'))]; + }, + + setRange: function(arg0, arg1) { + if (!Array.isArray(arg0)) + arg0 = [arg0, arg1]; + DomElement.set(this.element, { min: arg0[0], max: arg0[1] }); + }, + + getMin: function() { + return getRange()[0]; + }, + + setMin: function(min) { + this.setRange(min, getMax()); + }, + + getMax: function() { + return getRange()[1]; + }, + + setMax: function(max) { + this.setRange(getMin(), max); + }, + + getStep: function() { + return toFloat(DomElement.get(this.element, 'step')); + }, + + setStep: function(step) { + DomElement.set(this.element, 'step', step); + }, + + reset: function() { + this.setValue(this._defaultValue); + } +}); \ No newline at end of file diff --git a/src/ui/Palette.js b/src/ui/Palette.js new file mode 100644 index 00000000..4c3fde64 --- /dev/null +++ b/src/ui/Palette.js @@ -0,0 +1,70 @@ +/* + * Paper.js + * + * This file is part of Paper.js, a JavaScript Vector Graphics Library, + * based on Scriptographer.org and designed to be largely API compatible. + * http://paperjs.org/ + * http://scriptographer.org/ + * + * Copyright (c) 2011, Juerg Lehni & Jonathan Puckey + * http://lehni.org/ & http://jonathanpuckey.com/ + * + * Distributed under the MIT license. See LICENSE file for details. + * + * All rights reserved. + */ + +var Palette = this.Palette = Base.extend(Callback, /** @lends Palette# */{ + _events: [ 'onChange' ], + + initialize: function(title, components, values) { + var parent = DomElement.find('.paperjs-palettes') + || DomElement.find('body').appendChild( + DomElement.create('div', { 'class': 'paperjs-palettes' })); + var table = parent.appendChild( + DomElement.create('table', { 'class': 'paperjs-palette' })); + this._title = title; + if (!values) + values = {}; + this._components = Base.each(components, function(component, name) { + if (!(component instanceof Component)) { + if (component.value == null) + component.value = values[name]; + component.name = name; + component = components[name] = new Component(component); + } + component.palette = this; + // Make sure each component has an entry in values, so observers get + // installed further down. + if (values[name] === undefined) + values[name] = null; + var row = table.appendChild( + DomElement.create('tr', [ + 'td', { text: (component.label || name) + ':' }, + 'td', component.element + ]) + ); + }, this); + this._values = Base.each(values, function(value, name) { + // Replace each entry with an getter / setters so we can observe + // change. + Base.define(values, name, { + enumerable: true, + configurable: true, + writable: true, + get: function() { + return value; + }, + set: function(val) { + value = val; + components[name].setValue(val); + } + }); + }); + }, + + reset: function() { + for (var i in this._components) + this._components[i].reset(); + } +});