Browse Source

Update undo manager for components

pull/3411/head
Artur Arseniev 6 years ago
parent
commit
1b3790bc91
  1. 19
      src/canvas/model/Frame.js
  2. 64
      src/dom_components/index.js
  3. 32
      src/dom_components/model/Component.js
  4. 2
      src/dom_components/model/Components.js
  5. 4
      src/editor/model/Editor.js
  6. 10
      src/undo_manager/index.js

19
src/canvas/model/Frame.js

@ -1,5 +1,5 @@
import { Model } from 'backbone';
import { result, forEach, isEmpty } from 'underscore';
import { result, forEach, isEmpty, debounce } from 'underscore';
import { isComponent, isObject } from 'utils/mixins';
const keyAutoW = '__aw';
@ -9,6 +9,7 @@ export default Model.extend({
defaults: () => ({
x: 0,
y: 0,
changesCount: 0,
attributes: {},
width: null,
height: null,
@ -44,16 +45,15 @@ export default Model.extend({
!props.width && this.set(keyAutoW, 1);
!props.height && this.set(keyAutoH, 1);
// this._initUm();
this.getComponent()._initUm();
},
_initUm() {
const um = this.em.get('UndoManager');
const component = this.getComponent();
if (!um) return;
um.add(component);
console.log({ component, um });
},
changesUp: debounce(function(opt = {}) {
if (opt.temporary || opt.noCount || opt.avoidStore) {
return;
}
this.set('changesCount', this.get('changesCount') + 1);
}),
getComponent() {
return this.get('component');
@ -146,6 +146,7 @@ export default Model.extend({
const defaults = result(this, 'defaults');
delete obj.styles;
delete obj.changesCount;
obj[keyAutoW] && delete obj.width;
obj[keyAutoH] && delete obj.height;

64
src/dom_components/index.js

@ -304,70 +304,6 @@ export default () => {
c.components && this.setComponents(c.components);
},
/**
* Do stuff after load
* @param {Editor} em
* @private
*/
postLoad(em) {
this.handleChanges(this.getWrapper(), null, { avoidStore: 1 });
},
/**
* Handle component changes
* @private
*/
handleChanges(model, value, opts = {}) {
const comps = model.components();
const um = em.get('UndoManager');
const handleUpdates = em.handleUpdates.bind(em);
const handleChanges = this.handleChanges.bind(this);
const handleChangesColl = this.handleChangesColl.bind(this);
const handleRemoves = this.handleRemoves.bind(this);
um && um.add(model);
um && comps && um.add(comps);
const evn = 'change:style change:content change:attributes change:src';
[
[model, evn, handleUpdates],
[model, 'change:components', handleChangesColl],
[comps, 'add', handleChanges],
[comps, 'remove reset', handleRemoves],
[model.get('classes'), 'add remove', handleUpdates]
].forEach(els => {
em.stopListening(els[0], els[1], els[2]);
em.listenTo(els[0], els[1], els[2]);
});
!opts.avoidStore && handleUpdates('', '', opts);
comps.each(model => this.handleChanges(model, value, opts));
},
handleChangesColl(model, coll) {
const um = em.get('UndoManager');
if (um && coll instanceof Backbone.Collection) {
const handleChanges = this.handleChanges.bind(this);
const handleRemoves = this.handleRemoves.bind(this);
um.add(coll);
[
[coll, 'add', handleChanges],
[coll, 'remove reset', handleRemoves]
].forEach(els => {
em.stopListening(els[0], els[1], els[2]);
em.listenTo(els[0], els[1], els[2]);
});
}
},
/**
* Triggered when some component is removed
* @private
* */
handleRemoves(m, value, opt) {
const opts = opt || value; // in case of reset
em.handleUpdates(m, value, opts);
},
/**
* Load components from the passed object, if the object is empty will try to fetch them
* autonomously from the selected storage

32
src/dom_components/model/Component.js

@ -122,7 +122,9 @@ const Component = Backbone.Model.extend(Styleable).extend(
traits: ['id', 'title'],
propagate: '',
dmode: '',
toolbar: null
toolbar: null,
_undo: true,
_undoexc: ['status', 'open']
},
/**
@ -193,6 +195,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
this.listenTo(this, 'change:attributes', this.attrUpdated);
this.listenTo(this, 'change:attributes:id', this._idUpdated);
this.on('change:toolbar', this.__emitUpdateTlb);
this.on('change', this.__onChange);
this.set('status', '');
this.views = [];
@ -211,6 +214,27 @@ const Component = Backbone.Model.extend(Styleable).extend(
}
},
_initUm() {
const um = this.em.get('UndoManager');
if (!um) return;
um.add(this);
um.add(this.components());
},
__onChange(m, opts) {
const changed = this.changedAttributes();
['status', 'open', 'toolbar', 'traits'].forEach(
name => delete changed[name]
);
// Propagate component prop changes
!isEmptyObj(changed) && this.__changesUp(opts);
},
__changesUp(opts) {
const { em, frame } = this;
[frame, em].forEach(md => md && md.changesUp(opts));
},
__emitUpdateTlb() {
this.emitUpdate('toolbar');
},
@ -720,10 +744,12 @@ const Component = Backbone.Model.extend(Styleable).extend(
// This will propagate the change up to __upSymbProps
child.set('classes', this.get('classes'), { fromInstance: this });
});
this.__changesUp(opts);
},
__upSymbComps(m, c, o) {
const { fromInstance } = o || c || {};
const optUp = o || c || {};
const { fromInstance } = optUp;
const toUpOpts = { fromInstance };
const isTemp = m.opt.temporary;
@ -791,6 +817,8 @@ const Component = Backbone.Model.extend(Styleable).extend(
});
}
}
this.__changesUp(optUp);
},
initClasses(m, c, opts = {}) {

2
src/dom_components/model/Components.js

@ -252,7 +252,7 @@ export default Backbone.Collection.extend({
model.setStyle({});
model.addClass(name);
}
model._initUm();
this.__onAddEnd();
},

4
src/editor/model/Editor.js

@ -271,6 +271,10 @@ export default Backbone.Model.extend({
}, 0);
},
changesUp(opts) {
this.handleUpdates(0, 0, opts);
},
/**
* Callback on component hover
* @param {Object} Model

10
src/undo_manager/index.js

@ -36,6 +36,7 @@ export default () => {
maximumStackLength: 500
};
const hasSkip = opts => opts.avoidStore || opts.noUndo;
const getChanged = obj => Object.keys(obj.changedAttributes());
return {
name: 'UndoManager',
@ -54,14 +55,17 @@ export default () => {
condition: object => {
const hasUndo = object.get('_undo');
if (hasUndo) {
const undoExc = object.get('_undoexc');
if (isArray(undoExc)) {
if (getChanged(object).some(chn => undoExc.indexOf(chn) >= 0))
return false;
}
if (isBoolean(hasUndo)) return true;
if (isArray(hasUndo)) {
const changed = Object.keys(object.changedAttributes());
if (changed.some(chn => hasUndo.indexOf(hasUndo) >= 0))
if (getChanged(object).some(chn => hasUndo.indexOf(chn) >= 0))
return true;
}
}
// console.log('UndoType change', object.attributes, object.changedAttributes());
return false;
},
on(object, v, opt = {}) {

Loading…
Cancel
Save