8
0
Эх сурвалжийг харах

Tree model classes structure.

Piotr Jasiun 10 жил өмнө
parent
commit
864c61077e

+ 49 - 0
packages/ckeditor5-engine/src/treeview/observer/mutationobserver.js

@@ -0,0 +1,49 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+CKEDITOR.define( [ 'treeview/observer/observer' ], ( Observer ) => {
+	class MutationObserver extends Observer {
+		constructor() {
+			super();
+
+			this.config = {
+				childList: true,
+				characterData: true,
+				characterDataOldValue: true,
+				subtree: true
+			};
+		}
+
+		/**
+		 * @method init
+		 * @param {treeView.TreeView}
+		 */
+		init( treeView ) {
+			this.dom = treeView.dom;
+
+			this._mutationObserver = new window.MutationObserver( this._onMutations.bind( this ) );
+		}
+
+		/**
+		 * @method attach
+		 */
+		attach() {
+			this._mutationObserver.observe( this.dom, this.config );
+		}
+
+		/**
+		 * @method detach
+		 */
+		detach() {
+			this._mutationObserver.disconnect();
+		}
+
+		_onMutations( mutations ) {
+
+		}
+	}
+} );

+ 23 - 0
packages/ckeditor5-engine/src/treeview/observer/observer.js

@@ -0,0 +1,23 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+CKEDITOR.define( [], () => {
+	class Observer {
+		/**
+		 * @method init
+		 * @param {treeView.TreeView}
+		 */
+
+		/**
+		 * @method attach
+		 */
+
+		/**
+		 * @method detach
+		 */
+	}
+} );

+ 59 - 0
packages/ckeditor5-engine/src/treeview/renderer.js

@@ -0,0 +1,59 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+CKEDITOR.define( [], () => {
+	ATTRIBUTES_NEED_UPDATE = 0;
+	CHILDREN_NEED_UPDATE = 1;
+	TEXT_NEEDS_UPDATE = 2;
+
+	class Renderer {
+		constructor( treeView ) {
+			this.view = treeView.view;
+
+			this.dom = treeView.dom;
+
+			this.markedTexts = new Set();
+			this.markedAttrs = new Set();
+			this.markedChildren = new Set();
+		}
+
+		markNode( node, type ) {
+			if ( type === ATTRIBUTES_NEED_UPDATE ) {
+				this.markedAttrs.push( node );
+			} else if ( type === CHILDREN_NEED_UPDATE ) {
+				this.markedChildren.push( element );
+			} else if ( type === TEXT_NEEDS_UPDATE ) {
+				this.markedTexts.push( element );
+			}
+		}
+
+		render() {
+			this._updateTexts();
+			this._updateAttrs();
+			this._updateChildren();
+		}
+
+		_updateTexts() {
+
+		}
+
+		_updateAttrs() {
+		}
+
+		_updateChildren() {
+			//diff
+		}
+	}
+
+	Renderer.ATTRIBUTES_NEED_UPDATE = ATTRIBUTES_NEED_UPDATE;
+	Renderer.CHILDREN_NEED_UPDATE = CHILDREN_NEED_UPDATE;
+	Renderer.TEXT_NEEDS_UPDATE = TEXT_NEEDS_UPDATE;
+
+	utils.extend( Document.prototype, EmitterMixin );
+
+	return Renderer;
+} );

+ 78 - 0
packages/ckeditor5-engine/src/treeview/treeview.js

@@ -0,0 +1,78 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+CKEDITOR.define( [ 'treeview/renderer' ], ( Renderer ) => {
+	class TreeView {
+		constructor( domElement ) {
+			/**
+			 * Root of the view
+			 */
+			this.view = domElement.clone();
+
+			/**
+			 * Root of the DOM.
+			 */
+			this.dom = domElement;
+
+			this.elementsMapping = new WeakMap();
+
+			this.observers = new Set();
+
+			this.renderer = new Renderer( this );
+		}
+
+		addObserver( observer ) {
+			this.observers.push( observer );
+			observer.init( this );
+			observer.attach();
+		}
+
+		render() {
+			for ( let observer of this.observers ) {
+				observer.detach();
+			}
+
+			this.renderer.render();
+
+			for ( let observer of this.observers ) {
+				observer.attach();
+			}
+		}
+
+		insertBefore( parent, newNode, referenceNode ) {
+			parent.insertBefore( newNode, referenceNode );
+			this.render.markNode( element, Renderer.CHILDREN_NEED_UPDATE );
+		}
+
+		appendChild( parent, node ) {
+			parent.appendChild( node );
+			this.render.markNode( parent, Renderer.CHILDREN_NEED_UPDATE );
+		}
+
+		removeChild( parent, child ) {
+			parent.removeChild( child );
+			this.render.markNode( parent, Renderer.CHILDREN_NEED_UPDATE );
+		}
+
+		setAttr( element, key, value ) {
+			element.setAttribute( key, value );
+			this.render.markNode( element, Renderer.ATTRIBUTES_NEED_UPDATE );
+		}
+
+		removeAttr( element, key ) {
+			element.removeAttribute( key );
+			this.render.markNode( element, Renderer.ATTRIBUTES_NEED_UPDATE );
+		}
+
+		setText( textNode, text ) {
+			textNode.data = text;
+			this.render.markNode( textNode, Renderer.TEXT_NEEDS_UPDATE );
+		}
+	}
+
+	utils.extend( Document.prototype, EmitterMixin );
+} );

+ 130 - 0
packages/ckeditor5-engine/src/utils-diff.js

@@ -0,0 +1,130 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+// the following code is based on the "O(NP) Sequence Comparison Algorithm" by Sun Wu, Udi Manber, Gene Myers, Webb Miller
+
+CKEDITOR.define( [ 'utils' ], ( utils ) => {
+	// operation types
+	var INSERT = 1,
+		DELETE = -1,
+		EQUAL = 0;
+
+	/**
+	 * Calculates the difference between two arrays producing an object containing a list of operations
+	 * necessary to transform one array into another.
+	 *
+	 *		diff( 'aba', 'acca' ); // [ EQUAL, INSERT, INSERT, DELETE, EQUAL ]
+	 *
+	 * @param {Array} a Input array
+	 * @param {Array} b Output array
+	 * @param {Function} [cmp] Optional function used to compare array values, by default === is used
+	 * @return {Array}
+	 */
+	function diff( a, b, cmp ) {
+		// Set the comparator function.
+		cmp = cmp || function( a, b ) {
+				return a === b;
+			};
+
+		// Temporary operation type statics.
+		var _INSERT, _DELETE;
+
+		// Swapped the arrays to use the shorter one as the first one.
+		if ( b.length < a.length ) {
+			var tmp = a;
+
+			a = b;
+			b = tmp;
+
+			// We swap the operation types as well.
+			_INSERT = DELETE;
+			_DELETE = INSERT;
+		} else {
+			_INSERT = INSERT;
+			_DELETE = DELETE;
+		}
+
+		var m = a.length,
+			n = b.length,
+			delta = n - m;
+
+		// Edit scripts, for each diagonal.
+		var es = {};
+		// Furthest points, the furthest y we can get on each diagonal.
+		var fp = {};
+
+		function snake( k ) {
+			// We use -1 as an alternative below to handle initial values ( instead of filling the fp with -1 first ).
+			// Furthest points (y) on the diagonal below k.
+			var y1 = ( fp[ k - 1 ] !== undefined ? fp[ k - 1 ] : -1 ) + 1;
+			// Furthest points (y) on the diagonal above k.
+			var y2 = fp[ k + 1 ] !== undefined ? fp[ k + 1 ] : -1;
+			// The way we should go to get further.
+			var dir = y1 > y2 ? -1 : 1;
+
+			// Clone previous operations array (if any).
+			if ( es[ k + dir ] ) {
+				es[ k ] = es[ k + dir ].slice( 0 );
+			}
+
+			// Create operations array.
+			if ( !es[ k ] ) {
+				es[ k ] = [];
+			}
+
+			// Push the operation.
+			es[ k ].push( y1 > y2 ? _INSERT : _DELETE );
+
+			// Set the beginning coordinates.
+			var y = Math.max( y1, y2 ),
+				x = y - k;
+
+			// Traverse the diagonal as long as the values match.
+			while ( x < m && y < n && cmp( a[ x ], b[ y ] ) ) {
+				x++;
+				y++;
+				// Push no change operation.
+				es[ k ].push( EQUAL );
+			}
+
+			return y;
+		}
+
+		var p = 0,
+			k;
+
+		// Traverse the graph until we reach the end of the longer string.
+		do {
+			// Updates furthest points and edit scripts for diagonals below delta.
+			for ( k = -p; k < delta; k++ ) {
+				fp[ k ] = snake( k );
+			}
+
+			// Updates furthest points and edit scripts for diagonals above delta.
+			for ( k = delta + p; k > delta; k-- ) {
+				fp[ k ] = snake( k );
+			}
+
+			// Updates furthest point and edit script for the delta diagonal.
+			// note that the delta diagonal is the one which goes through the sink (m, n).
+			fp[ delta ] = snake( delta );
+
+			p++;
+		} while ( fp[ delta ] !== n );
+
+		// Return the final list of edit operations.
+		// We remove the first item that represents the operation for the injected nulls.
+		return es[ delta ].slice( 1 );
+	}
+
+	// Expose operation types.
+	utils.INSERT = INSERT;
+	utils.DELETE = DELETE;
+	utils.EQUAL = EQUAL;
+
+	return utils;
+} );