mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-20 22:39:50 -05:00
Merge Pane functionality into Component.
Work in progress.
This commit is contained in:
parent
e46a1d24da
commit
73529f0170
5 changed files with 123 additions and 149 deletions
|
@ -96,7 +96,7 @@ var DomElement = new function() {
|
||||||
for (var name in key)
|
for (var name in key)
|
||||||
if (key.hasOwnProperty(name))
|
if (key.hasOwnProperty(name))
|
||||||
DomElement.set(el, name, key[name]);
|
DomElement.set(el, name, key[name]);
|
||||||
} else if (!el || value === undefined) {
|
} else if (!el || value == null) {
|
||||||
return el;
|
return el;
|
||||||
} else if (special.test(key)) {
|
} else if (special.test(key)) {
|
||||||
el[key] = value;
|
el[key] = value;
|
||||||
|
|
|
@ -118,9 +118,8 @@ var paper = new function(undefined) {
|
||||||
/*#*/ include('ui/MouseEvent.js');
|
/*#*/ include('ui/MouseEvent.js');
|
||||||
|
|
||||||
/*#*/ if (__options.palette) {
|
/*#*/ if (__options.palette) {
|
||||||
/*#*/ include('ui/Pane.js');
|
|
||||||
/*#*/ include('ui/Palette.js');
|
|
||||||
/*#*/ include('ui/Component.js');
|
/*#*/ include('ui/Component.js');
|
||||||
|
/*#*/ include('ui/Palette.js');
|
||||||
/*#*/ }
|
/*#*/ }
|
||||||
|
|
||||||
/*#*/ include('tool/ToolEvent.js');
|
/*#*/ include('tool/ToolEvent.js');
|
||||||
|
|
|
@ -78,53 +78,98 @@ 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: {},
|
|
||||||
column: {}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Default values for internals
|
// Default values for internals
|
||||||
_visible: true,
|
_visible: true,
|
||||||
_enabled: true,
|
_enabled: true,
|
||||||
|
|
||||||
initialize: function Component(pane, name, props, values, row, parent) {
|
initialize: function Component(parent, name, props, values, row) {
|
||||||
if (!name)
|
if (!name)
|
||||||
name = 'component-' + this._id;
|
name = 'component-' + this._id;
|
||||||
var value = Base.pick(values[name], props.value);
|
var value = Base.pick(values[name], props.value);
|
||||||
this._id = Component._id = (Component._id || 0) + 1;
|
this._id = Component._id = (Component._id || 0) + 1;
|
||||||
this._pane = pane;
|
this._parent = parent;
|
||||||
this._name = name;
|
this._name = name;
|
||||||
this._row = row;
|
this._row = row;
|
||||||
this._parent = parent; // The parent component, if any.
|
|
||||||
if (!parent || parent._type !== 'row')
|
|
||||||
DomElement.set(row, 'id', 'palettejs-row-' + name);
|
|
||||||
var type = this._type = props.type in this._types
|
var type = this._type = props.type in this._types
|
||||||
? props.type
|
? props.type
|
||||||
: 'options' in props
|
: 'options' in props
|
||||||
? 'list'
|
? 'list'
|
||||||
: 'onClick' in props
|
: 'onClick' in props
|
||||||
? 'button'
|
? 'button'
|
||||||
: typeof value,
|
: value !== undefined
|
||||||
|
? typeof value
|
||||||
|
: undefined,
|
||||||
meta = this._meta = this._types[type] || { type: type },
|
meta = this._meta = this._types[type] || { type: type },
|
||||||
that = this,
|
|
||||||
create = DomElement.create,
|
create = DomElement.create,
|
||||||
element = null,
|
element = null;
|
||||||
isRow = type === 'row',
|
if (!type) {
|
||||||
isColumn = type === 'column';
|
var horizontal = props.horizontal,
|
||||||
if (isRow || isColumn) {
|
// On the root element, we need to create the table and row even
|
||||||
var childPane = this._childPane = new Pane(props, values, this,
|
// if it's a horizontal layout.
|
||||||
isRow && row);
|
table = this._table = !(horizontal && row) && DomElement.create(
|
||||||
if (isRow) {
|
'table', {
|
||||||
pane._numCells = childPane._numCells;
|
class: 'palettejs-pane' // XXX
|
||||||
} else { // isColumn
|
}),
|
||||||
element = childPane._table;
|
components = this._components = {},
|
||||||
|
currentRow = row,
|
||||||
|
numCells = 0;
|
||||||
|
this._numCells = 0;
|
||||||
|
for (var key in props) {
|
||||||
|
var component = props[key];
|
||||||
|
if (Base.isPlainObject(component)) {
|
||||||
|
// Create the rows for vertical elements, as well as
|
||||||
|
// horizontal root elements.
|
||||||
|
if (table && !(horizontal && currentRow)) {
|
||||||
|
currentRow = DomElement.addChildren(table, ['tr', {
|
||||||
|
class: 'palettejs-row',
|
||||||
|
id: horizontal ? null : 'palettejs-row-' + key
|
||||||
|
}])[0];
|
||||||
|
// Set _row for the horizontal root element.
|
||||||
|
if (horizontal)
|
||||||
|
this._row = currentRow;
|
||||||
|
}
|
||||||
|
components[key] = new Component(this, key, component,
|
||||||
|
values, currentRow);
|
||||||
|
numCells = Math.max(numCells, this._numCells);
|
||||||
|
// Do not reset cell counter if all components go to the
|
||||||
|
// same parent row.
|
||||||
|
if (!horizontal)
|
||||||
|
this._numCells = 0;
|
||||||
|
// Remove the entry now from the object that was provided to
|
||||||
|
// create the component since the leftovers will be injected
|
||||||
|
// into the created component through #_set() below.
|
||||||
|
delete props[key];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
this._numCells = numCells;
|
||||||
|
if (horizontal && parent)
|
||||||
|
parent._numCells = numCells;
|
||||||
|
Base.each(components, function(component, key) {
|
||||||
|
if (numCells > 2 && component._cell && !horizontal)
|
||||||
|
DomElement.set(component._cell, 'colspan', numCells - 1);
|
||||||
|
// Replace each entry in values with getters/setters so we can
|
||||||
|
// directly link the value to the component and observe change.
|
||||||
|
Base.define(values, key, {
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
get: function() {
|
||||||
|
return component.getValue();
|
||||||
|
},
|
||||||
|
set: function(val) {
|
||||||
|
component.setValue(val);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
// Add child components directly to this component, so we can access
|
// Add child components directly to this component, so we can access
|
||||||
// it through the same path as in the components object literal that
|
// it through the same path as in the components object literal that
|
||||||
// was passed.
|
// was passed.
|
||||||
Base.set(this, childPane._components);
|
Base.set(this, components);
|
||||||
|
element = row && table;
|
||||||
} else {
|
} else {
|
||||||
|
var that = this;
|
||||||
element = this._input = create(meta.tag || 'input', {
|
element = this._input = create(meta.tag || 'input', {
|
||||||
class: 'palettejs-input',
|
class: 'palettejs-input',
|
||||||
id: 'palettejs-input-' + name,
|
id: 'palettejs-input-' + name,
|
||||||
|
@ -152,13 +197,14 @@ var Component = Base.extend(Callback, /** @lends Component# */{
|
||||||
}, [ element ])
|
}, [ element ])
|
||||||
]);
|
]);
|
||||||
// We just added two cells to the row:
|
// We just added two cells to the row:
|
||||||
pane._numCells += 2;
|
if (parent)
|
||||||
|
parent._numCells += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attach default 'change' even that delegates to palette
|
// Attach default 'change' even that delegates to parent component.
|
||||||
this.attach('change', function(value) {
|
this.attach('change', function(value) {
|
||||||
if (!this._dontFire)
|
if (!this._dontFire && parent)
|
||||||
pane.fire('change', this, this._name, value);
|
parent.fire('change', this, this._name, value);
|
||||||
});
|
});
|
||||||
this._dontFire = true;
|
this._dontFire = true;
|
||||||
// Now that everything is set up, copy over values fro, props.
|
// Now that everything is set up, copy over values fro, props.
|
||||||
|
@ -171,8 +217,6 @@ var Component = Base.extend(Callback, /** @lends Component# */{
|
||||||
this.setValue(value);
|
this.setValue(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;
|
|
||||||
values[name] = this._defaultValue = this._value;
|
values[name] = this._defaultValue = this._value;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -229,7 +273,7 @@ var Component = Base.extend(Callback, /** @lends Component# */{
|
||||||
},
|
},
|
||||||
|
|
||||||
setValue: function(value) {
|
setValue: function(value) {
|
||||||
if (this._childPane)
|
if (this._components)
|
||||||
return;
|
return;
|
||||||
var meta = this._meta,
|
var meta = this._meta,
|
||||||
key = meta.value || 'value',
|
key = meta.value || 'value',
|
||||||
|
@ -264,19 +308,20 @@ var Component = Base.extend(Callback, /** @lends Component# */{
|
||||||
return this._enabled;
|
return this._enabled;
|
||||||
},
|
},
|
||||||
|
|
||||||
setEnabled: function(enabled, _fromPalette) {
|
setEnabled: function(enabled, _fromParent) {
|
||||||
if (_fromPalette) {
|
if (_fromParent) {
|
||||||
// When called from Palette#setEnabled, we have to remember the
|
// When called from the parent component, we have to remember the
|
||||||
// component's previous enabled state when disabling the palette,
|
// component's previous enabled state when disabling the palette,
|
||||||
// so we can restore it when enabling the palette again.
|
// so we can restore it when enabling the palette again.
|
||||||
var prev = Base.pick(this._previousEnabled, this._enabled);
|
var prev = Base.pick(this._previousEnabled, this._enabled);
|
||||||
this._previousEnabled = enabled ? undefined : prev; // clear
|
this._previousEnabled = enabled ? undefined : prev; // clear
|
||||||
enabled = enabled && prev;
|
enabled = enabled && prev;
|
||||||
}
|
}
|
||||||
if (this._input) {
|
if (this._components) {
|
||||||
|
for (var i in this._components)
|
||||||
|
this._components[i].setEnabled(enabled, true);
|
||||||
|
} else {
|
||||||
DomElement.set(this._input, 'disabled', !enabled);
|
DomElement.set(this._input, 'disabled', !enabled);
|
||||||
} else if (this._childPane) {
|
|
||||||
this._childPane.setEnabled(enabled);
|
|
||||||
}
|
}
|
||||||
this._enabled = !!enabled;
|
this._enabled = !!enabled;
|
||||||
},
|
},
|
||||||
|
@ -316,8 +361,9 @@ var Component = Base.extend(Callback, /** @lends Component# */{
|
||||||
},
|
},
|
||||||
|
|
||||||
reset: function() {
|
reset: function() {
|
||||||
if (this._childPane) {
|
if (this._components) {
|
||||||
this._childPane.reset();
|
for (var i in this._components)
|
||||||
|
this._components[i].reset();
|
||||||
} else {
|
} else {
|
||||||
this.setValue(this._defaultValue);
|
this.setValue(this._defaultValue);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,8 @@
|
||||||
/**
|
/**
|
||||||
* @name Palette
|
* @name Palette
|
||||||
* @class
|
* @class
|
||||||
* @extends Pane
|
|
||||||
*/
|
*/
|
||||||
/* var Palette = */ Pane.extend(/** @lends Palette# */{
|
/* var Palette = */ Base.extend(/** @lends Palette# */{
|
||||||
_class: 'Palette',
|
_class: 'Palette',
|
||||||
|
|
||||||
// DOCS: Palette#initialize(props)
|
// DOCS: Palette#initialize(props)
|
||||||
|
@ -33,13 +32,24 @@
|
||||||
values = props.values;
|
values = props.values;
|
||||||
}
|
}
|
||||||
this._title = title;
|
this._title = title;
|
||||||
Pane.call(this, components, values);
|
this._values = values;
|
||||||
|
this._components = components;
|
||||||
|
// Create one root component that handles the layout and contains all
|
||||||
|
// the components.
|
||||||
|
var root = this._root = new Component(null, 'root', components, values),
|
||||||
|
that = this;
|
||||||
|
root.attach('change', function(value) {
|
||||||
|
that.fire('change', this, this._name, value);
|
||||||
|
});
|
||||||
|
// Write the created components back into the passed components object,
|
||||||
|
// so they are exposed and can easily be accessed from the outside.
|
||||||
|
Base.set(components, root._components);
|
||||||
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' }));
|
||||||
this._element = parent.appendChild(
|
this._element = parent.appendChild(
|
||||||
DomElement.create('div', { class: 'palettejs-palette' },
|
DomElement.create('div', { class: 'palettejs-palette' },
|
||||||
[this._table]));
|
[root._table]));
|
||||||
if (props)
|
if (props)
|
||||||
this._set(props, { title: true, components: true, values: true });
|
this._set(props, { title: true, components: true, values: true });
|
||||||
// Link to the current scope's palettes list.
|
// Link to the current scope's palettes list.
|
||||||
|
@ -48,6 +58,30 @@
|
||||||
(this._palettes = paper.palettes).push(this);
|
(this._palettes = paper.palettes).push(this);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getComponents: function() {
|
||||||
|
return this._components;
|
||||||
|
},
|
||||||
|
|
||||||
|
getValues: function() {
|
||||||
|
return this._values;
|
||||||
|
},
|
||||||
|
|
||||||
|
getEnabled: function() {
|
||||||
|
return this._root.getEnabled();
|
||||||
|
},
|
||||||
|
|
||||||
|
setEnabled: function(enabled) {
|
||||||
|
return this._root.setEnabled(enabled);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the values of the components to their
|
||||||
|
* {@link Component#defaultValue}.
|
||||||
|
*/
|
||||||
|
reset: function() {
|
||||||
|
this._root.reset();
|
||||||
|
},
|
||||||
|
|
||||||
remove: function() {
|
remove: function() {
|
||||||
DomElement.remove(this._element);
|
DomElement.remove(this._element);
|
||||||
var palettes = this._palettes;
|
var palettes = this._palettes;
|
||||||
|
|
105
src/ui/Pane.js
105
src/ui/Pane.js
|
@ -1,105 +0,0 @@
|
||||||
/*
|
|
||||||
* Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
|
|
||||||
* http://paperjs.org/
|
|
||||||
*
|
|
||||||
* Copyright (c) 2011 - 2014, Juerg Lehni & Jonathan Puckey
|
|
||||||
* http://scratchdisk.com/ & http://jonathanpuckey.com/
|
|
||||||
*
|
|
||||||
* Distributed under the MIT license. See LICENSE file for details.
|
|
||||||
*
|
|
||||||
* All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @name Pane
|
|
||||||
* @class
|
|
||||||
*/
|
|
||||||
var Pane = Base.extend(Callback, /** @lends Pane# */{
|
|
||||||
_class: 'Pane',
|
|
||||||
_events: [ 'onChange' ],
|
|
||||||
// Defaults for internals
|
|
||||||
_enabled: true,
|
|
||||||
|
|
||||||
initialize: function Pane(components, values, parent, parentRow) {
|
|
||||||
if (!values)
|
|
||||||
values = {};
|
|
||||||
this._table = !parentRow && DomElement.create('table', {
|
|
||||||
class: 'palettejs-pane'
|
|
||||||
});
|
|
||||||
// NOTE: We modify the actual passed components in the root pane, and
|
|
||||||
// also the values objects, so the newly created components and their
|
|
||||||
// values can easily be referenced from outside.
|
|
||||||
var comps = this._components = parent ? {} : components;
|
|
||||||
this._values = values;
|
|
||||||
var numCells = 0;
|
|
||||||
this._numCells = 0;
|
|
||||||
for (var name in components) {
|
|
||||||
var component = components[name];
|
|
||||||
if (Base.isPlainObject(component)) {
|
|
||||||
var row = parentRow || DomElement.addChildren(this._table,
|
|
||||||
['tr', { class: 'palettejs-row' }])[0];
|
|
||||||
new Component(this, name, component, values, row, parent);
|
|
||||||
numCells = Math.max(numCells, this._numCells);
|
|
||||||
// Do not reset cell counter if all components go to the same
|
|
||||||
// parent row.
|
|
||||||
if (!parentRow)
|
|
||||||
this._numCells = 0;
|
|
||||||
if (parent) {
|
|
||||||
// If this is a child pane, remove the entry now from the
|
|
||||||
// object that was provided to create it, since the left
|
|
||||||
// overs will be injected into the parent component through
|
|
||||||
// #_set()
|
|
||||||
delete components[name];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this._numCells = numCells;
|
|
||||||
Base.each(comps, function(component, name) {
|
|
||||||
// Update colspan in all components that are not nested in another
|
|
||||||
// component.
|
|
||||||
if (numCells > 2 && component._cell
|
|
||||||
&& (!parent || parent._type === 'column')) {
|
|
||||||
DomElement.set(component._cell, 'colspan', numCells - 1);
|
|
||||||
}
|
|
||||||
// Now replace each entry in values with a getter / setters so we
|
|
||||||
// can directly link the value to the component and observe change.
|
|
||||||
Base.define(values, name, {
|
|
||||||
enumerable: true,
|
|
||||||
configurable: true,
|
|
||||||
get: function() {
|
|
||||||
return component.getValue();
|
|
||||||
},
|
|
||||||
set: function(val) {
|
|
||||||
component.setValue(val);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
getComponents: function() {
|
|
||||||
return this._components;
|
|
||||||
},
|
|
||||||
|
|
||||||
getValues: function() {
|
|
||||||
return this._values;
|
|
||||||
},
|
|
||||||
|
|
||||||
getEnabled: function() {
|
|
||||||
return this._enabled;
|
|
||||||
},
|
|
||||||
|
|
||||||
setEnabled: function(enabled) {
|
|
||||||
this._enabled = enabled;
|
|
||||||
for (var i in this._components)
|
|
||||||
this._components[i].setEnabled(enabled, true);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets the values of the components to their
|
|
||||||
* {@link Component#defaultValue}.
|
|
||||||
*/
|
|
||||||
reset: function() {
|
|
||||||
for (var i in this._components)
|
|
||||||
this._components[i].reset();
|
|
||||||
}
|
|
||||||
});
|
|
Loading…
Reference in a new issue