mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-06 04:42:15 -05:00
Implement 'row' type component, for multiple components per row in palettes.
This commit is contained in:
parent
09a4defb73
commit
54de02149b
5 changed files with 120 additions and 67 deletions
|
@ -836,7 +836,6 @@ var Rectangle = Base.extend(/** @lends Rectangle# */{
|
||||||
* @class An internal version of Rectangle that notifies its owner of each
|
* @class An internal version of Rectangle that notifies its owner of each
|
||||||
* change through setting itself again on the setter that corresponds to the
|
* change through setting itself again on the setter that corresponds to the
|
||||||
* getter that produced this LinkedRectangle.
|
* getter that produced this LinkedRectangle.
|
||||||
* See uses of LinkedRectangle.create()
|
|
||||||
* Note: This prototype is not exported.
|
* Note: This prototype is not exported.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
|
|
|
@ -159,6 +159,11 @@ var DomElement = new function() {
|
||||||
el.parentNode.removeChild(el);
|
el.parentNode.removeChild(el);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
addChildren: function(el, children) {
|
||||||
|
// We can use the create() function for this too!
|
||||||
|
return create(children, el);
|
||||||
|
},
|
||||||
|
|
||||||
removeChildren: function(el) {
|
removeChildren: function(el) {
|
||||||
while (el.firstChild)
|
while (el.firstChild)
|
||||||
el.removeChild(el.firstChild);
|
el.removeChild(el.firstChild);
|
||||||
|
|
|
@ -78,60 +78,91 @@ var Component = Base.extend(Callback, /** @lends Component# */{
|
||||||
return new Color(value).toCSS(
|
return new Color(value).toCSS(
|
||||||
DomElement.get(this._input, 'type') === 'color');
|
DomElement.get(this._input, 'type') === 'color');
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
|
row: {}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Default values for internals
|
// Default values for internals
|
||||||
|
_visible: true,
|
||||||
_enabled: true,
|
_enabled: true,
|
||||||
|
|
||||||
initialize: function Component(obj) {
|
initialize: function Component(pane, name, props, value, row, parent) {
|
||||||
|
if (value === undefined)
|
||||||
|
value = props.value;
|
||||||
|
if (!name)
|
||||||
|
name = 'component-' + this._id,
|
||||||
this._id = Component._id = (Component._id || 0) + 1;
|
this._id = Component._id = (Component._id || 0) + 1;
|
||||||
var type = this._type = obj.type in this._types
|
this._pane = pane;
|
||||||
? obj.type
|
this._name = name;
|
||||||
: 'options' in obj
|
this._row = row;
|
||||||
? 'list'
|
this._parent = parent; // The parent component, if any.
|
||||||
: 'onClick' in obj
|
var type = this._type = props.type in this._types
|
||||||
? 'button'
|
? props.type
|
||||||
: typeof obj.value,
|
: 'options' in props
|
||||||
|
? 'list'
|
||||||
|
: 'onClick' in props
|
||||||
|
? 'button'
|
||||||
|
: typeof value,
|
||||||
meta = this._meta = this._types[type] || { type: type },
|
meta = this._meta = this._types[type] || { type: type },
|
||||||
name = this._name = obj.name || 'component-' + this._id,
|
that = this,
|
||||||
that = this;
|
create = DomElement.create;
|
||||||
this._input = DomElement.create(meta.tag || 'input', {
|
if (type === 'row') {
|
||||||
id: 'palettejs-input-' + name,
|
var components = this._components = [];
|
||||||
type: meta.type,
|
for (var key in props) {
|
||||||
events: {
|
var entry = props[key];
|
||||||
change: function() {
|
if (Base.isPlainObject(entry))
|
||||||
that.setValue(
|
components.push(new Component(pane, key, entry,
|
||||||
DomElement.get(this, meta.value || 'value'));
|
pane._values[key], row, this));
|
||||||
},
|
|
||||||
click: function() {
|
|
||||||
that.fire('click');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
pane._maxComponents = Math.max(components.length,
|
||||||
|
pane._maxComponents || 0);
|
||||||
|
} else {
|
||||||
|
DomElement.addChildren(row, [
|
||||||
|
this._labelCell = create('td', {
|
||||||
|
class: 'palettejs-label',
|
||||||
|
id: 'palettejs-label-' + name
|
||||||
|
}),
|
||||||
|
this._inputCell = create('td', {
|
||||||
|
class: 'palettejs-input',
|
||||||
|
id: 'palettejs-input-' + name
|
||||||
|
}, [
|
||||||
|
this._input = create(meta.tag || 'input', {
|
||||||
|
type: meta.type,
|
||||||
|
events: {
|
||||||
|
change: function() {
|
||||||
|
that.setValue(DomElement.get(this,
|
||||||
|
meta.value || 'value'));
|
||||||
|
},
|
||||||
|
click: function() {
|
||||||
|
that.fire('click');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
}
|
||||||
// Attach default 'change' even that delegates to palette
|
// Attach default 'change' even that delegates to palette
|
||||||
this.attach('change', function(value) {
|
this.attach('change', function(value) {
|
||||||
if (!this._dontFire)
|
if (!this._dontFire)
|
||||||
this._palette.fire('change', this, this._name, value);
|
pane.fire('change', this, this._name, value);
|
||||||
});
|
});
|
||||||
this._element = DomElement.create('tr',
|
|
||||||
{ class: 'palettejs-row', id: 'palettejs-row-' + name }, [
|
|
||||||
this._labelCell = DomElement.create('td',
|
|
||||||
{ class: 'palettejs-label' }),
|
|
||||||
'td', { class: 'palettejs-input' }, [this._input]
|
|
||||||
]);
|
|
||||||
this._dontFire = true;
|
this._dontFire = true;
|
||||||
// Now that everything is set up, copy over values fro obj.
|
// Now that everything is set up, copy over values fro, props.
|
||||||
// NOTE: This triggers setters, which is why we set _dontFire = true,
|
// NOTE: This triggers setters, which is why we set _dontFire = true,
|
||||||
// and why we can only call this after everything else is set up (e.g.
|
// and why we can only call this after everything else is set up (e.g.
|
||||||
// setLabel() requires this._labelCell).
|
// setLabel() requires this._labelCell).
|
||||||
// Exclude name because it's already set, and value since we want to set
|
// Exclude name because it's already set, and value since we want to set
|
||||||
// it after range.
|
// it after range.
|
||||||
Base.set(this, obj, { name: true, value: true });
|
Base.set(this, props, { name: true, value: true });
|
||||||
this.setValue(obj.value);
|
this.setValue(value);
|
||||||
this._defaultValue = this._value;
|
|
||||||
// Start firing change events after we have initialized.
|
// Start firing change events after we have initialized.
|
||||||
this._dontFire = false;
|
this._dontFire = false;
|
||||||
|
// Store link to component in the pane's components object.
|
||||||
|
pane._components[name] = this;
|
||||||
|
// Make sure each component has an entry in values also, so observers
|
||||||
|
// get installed correctly in the Pane constructor.
|
||||||
|
pane._values[name] = this._defaultValue = this._value;
|
||||||
},
|
},
|
||||||
|
|
||||||
getType: function() {
|
getType: function() {
|
||||||
|
@ -161,7 +192,7 @@ var Component = Base.extend(Callback, /** @lends Component# */{
|
||||||
setSuffix: function(suffix) {
|
setSuffix: function(suffix) {
|
||||||
this._suffix = suffix;
|
this._suffix = suffix;
|
||||||
DomElement.set(this._suffixNode = this._suffixNode
|
DomElement.set(this._suffixNode = this._suffixNode
|
||||||
|| this._input.parentNode.appendChild(DomElement.create('label',
|
|| this._inputCell.appendChild(DomElement.create('label',
|
||||||
{ 'for': 'palettejs-input-' + this._name })),
|
{ 'for': 'palettejs-input-' + this._name })),
|
||||||
'text', suffix);
|
'text', suffix);
|
||||||
},
|
},
|
||||||
|
@ -202,11 +233,15 @@ var Component = Base.extend(Callback, /** @lends Component# */{
|
||||||
},
|
},
|
||||||
|
|
||||||
getVisible: function() {
|
getVisible: function() {
|
||||||
return !DomElement.hasClass(this._element, 'hidden');
|
return this._visible;
|
||||||
},
|
},
|
||||||
|
|
||||||
setVisible: function(visible) {
|
setVisible: function(visible) {
|
||||||
DomElement.toggleClass(this._element, 'hidden', !visible);
|
// NOTE: Only set the visibility of the whole row if this is a row item,
|
||||||
|
// in which case this._input is not defined.
|
||||||
|
DomElement.toggleClass(this._inputCell || this._row, 'hidden', !visible);
|
||||||
|
DomElement.toggleClass(this._labelCell, 'hidden', !visible);
|
||||||
|
this._visible = !!visible;
|
||||||
},
|
},
|
||||||
|
|
||||||
getEnabled: function() {
|
getEnabled: function() {
|
||||||
|
@ -223,7 +258,7 @@ var Component = Base.extend(Callback, /** @lends Component# */{
|
||||||
enabled = enabled && prev;
|
enabled = enabled && prev;
|
||||||
}
|
}
|
||||||
DomElement.set(this._input, 'disabled', !enabled);
|
DomElement.set(this._input, 'disabled', !enabled);
|
||||||
this._enabled = enabled;
|
this._enabled = !!enabled;
|
||||||
},
|
},
|
||||||
|
|
||||||
getRange: function() {
|
getRange: function() {
|
||||||
|
|
|
@ -25,11 +25,13 @@
|
||||||
// DOCS: Palette#remove()
|
// DOCS: Palette#remove()
|
||||||
|
|
||||||
initialize: function Palette(title, components, values) {
|
initialize: function Palette(title, components, values) {
|
||||||
Pane.call(this, title, components, values, 'palettejs-palette');
|
Pane.call(this, title, components, values);
|
||||||
var parent = DomElement.find('.palettejs-panel')
|
var parent = DomElement.find('.palettejs-panel')
|
||||||
|| DomElement.find('body').appendChild(
|
|| DomElement.find('body').appendChild(
|
||||||
DomElement.create('div', { class: 'palettejs-panel' }));
|
DomElement.create('div', { class: 'palettejs-panel' }));
|
||||||
parent.appendChild(this._element);
|
this._element = parent.appendChild(
|
||||||
|
DomElement.create('div', { class: 'palettejs-palette' },
|
||||||
|
[this._table]));
|
||||||
// Link to the current scope's palettes list.
|
// Link to the current scope's palettes list.
|
||||||
// TODO: This is the only paper dependency in Palette.js
|
// TODO: This is the only paper dependency in Palette.js
|
||||||
// Find a way to make it independent.
|
// Find a way to make it independent.
|
||||||
|
|
|
@ -20,7 +20,7 @@ var Pane = Base.extend(Callback, /** @lends Pane# */{
|
||||||
// Defaults for internals
|
// Defaults for internals
|
||||||
_enabled: true,
|
_enabled: true,
|
||||||
|
|
||||||
initialize: function Pane(title, components, values, className) {
|
initialize: function Pane(title, components, values) {
|
||||||
// Support object literal constructor
|
// Support object literal constructor
|
||||||
var props = Base.isPlainObject(title) && title;
|
var props = Base.isPlainObject(title) && title;
|
||||||
if (props) {
|
if (props) {
|
||||||
|
@ -28,38 +28,42 @@ var Pane = Base.extend(Callback, /** @lends Pane# */{
|
||||||
components = props.components;
|
components = props.components;
|
||||||
values = props.values;
|
values = props.values;
|
||||||
}
|
}
|
||||||
this._element = DomElement.create('table', {
|
|
||||||
class: 'palettejs-pane' + (className ? ' ' + className : '')
|
|
||||||
});
|
|
||||||
this._title = title;
|
|
||||||
if (!values)
|
if (!values)
|
||||||
values = {};
|
values = {};
|
||||||
for (var name in (this.components = components)) {
|
this._table = DomElement.create('table', { class: 'palettejs-pane' });
|
||||||
var component = components[name];
|
this._title = title;
|
||||||
if (!(component instanceof Component)) {
|
// NOTE: We modify the actual passed components and values objects so
|
||||||
component = components[name] = new Component(
|
// the newly created components and their values can easily be
|
||||||
new Base(component, {
|
// referenced from outside.
|
||||||
value: Base.pick(component.value, values[name]),
|
this._components = components;
|
||||||
name: name
|
this._values = values;
|
||||||
}));
|
this._maxComponents = 1; // 1 component per row is the default.
|
||||||
|
for (var name in components) {
|
||||||
|
var row = DomElement.create('tr', { class: 'palettejs-row' }),
|
||||||
|
component = new Component(this, name, components[name],
|
||||||
|
values[name], row);
|
||||||
|
DomElement.set(row, 'id', 'palettejs-row-' + component._name);
|
||||||
|
this._table.appendChild(row);
|
||||||
|
}
|
||||||
|
if (this._maxComponents > 1) {
|
||||||
|
for (name in components) {
|
||||||
|
var component = components[name];
|
||||||
|
if (component._inputCell && !component._parent) {
|
||||||
|
DomElement.set(component._inputCell, 'colspan',
|
||||||
|
this._maxComponents * 2 - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this._element.appendChild(component._element);
|
|
||||||
component._palette = this;
|
|
||||||
// Make sure each component has an entry in values, so observers get
|
|
||||||
// installed further down.
|
|
||||||
if (values[name] === undefined)
|
|
||||||
values[name] = component._value;
|
|
||||||
}
|
}
|
||||||
// Now replace each entry in values with a getter / setters so we can
|
// Now replace each entry in values with a getter / setters so we can
|
||||||
// directly link the value to the component and observe change.
|
// directly link the value to the component and observe change.
|
||||||
this.values = Base.each(values, function(value, name) {
|
Base.each(values, function(value, name) {
|
||||||
var component = components[name];
|
var component = components && components[name];
|
||||||
if (component) {
|
if (component) {
|
||||||
Base.define(values, name, {
|
Base.define(values, name, {
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
configurable: true,
|
configurable: true,
|
||||||
get: function() {
|
get: function() {
|
||||||
return component._value;
|
return component.getValue();
|
||||||
},
|
},
|
||||||
set: function(val) {
|
set: function(val) {
|
||||||
component.setValue(val);
|
component.setValue(val);
|
||||||
|
@ -73,14 +77,22 @@ var Pane = Base.extend(Callback, /** @lends Pane# */{
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getComponents: function() {
|
||||||
|
return this._components;
|
||||||
|
},
|
||||||
|
|
||||||
|
getValues: function() {
|
||||||
|
return this._values;
|
||||||
|
},
|
||||||
|
|
||||||
getEnabled: function() {
|
getEnabled: function() {
|
||||||
return this._enabled;
|
return this._enabled;
|
||||||
},
|
},
|
||||||
|
|
||||||
setEnabled: function(enabled) {
|
setEnabled: function(enabled) {
|
||||||
this._enabled = enabled;
|
this._enabled = enabled;
|
||||||
for (var i in this.components)
|
for (var i in this._components)
|
||||||
this.components[i].setEnabled(enabled, true);
|
this._components[i].setEnabled(enabled, true);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,7 +100,7 @@ var Pane = Base.extend(Callback, /** @lends Pane# */{
|
||||||
* {@link Component#defaultValue}.
|
* {@link Component#defaultValue}.
|
||||||
*/
|
*/
|
||||||
reset: function() {
|
reset: function() {
|
||||||
for (var i in this.components)
|
for (var i in this._components)
|
||||||
this.components[i].reset();
|
this._components[i].reset();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue