ソースを参照

Internal: [WIP] delegating resizer strategy into a dedicated type.

Marek Lewandowski 6 年 前
コミット
2fd47afb4b

+ 11 - 57
packages/ckeditor5-widget/src/resizecontext.js

@@ -1,6 +1,8 @@
 import IconView from '@ckeditor/ckeditor5-ui/src/icon/iconview';
 import View from '@ckeditor/ckeditor5-ui/src/view';
 import dragHandlerIcon from '../theme/icons/drag-handler.svg';
+import ResizerCentral from './resizercentral';
+import { getAbsoluteBoundaryPoint } from './utils';
 
 import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
 import mix from '@ckeditor/ckeditor5-utils/src/mix';
@@ -11,29 +13,6 @@ import mix from '@ckeditor/ckeditor5-utils/src/mix';
 
 const HEIGHT_ATTRIBUTE_NAME = 'height';
 
-/**
- * Returns coordinates of top-left corner of a element, relative to the document's top-left corner.
- *
- * @param {HTMLElement} element
- * @param {String} resizerPosition Position of the resize handler, e.g. `"top-left"`, `"bottom-right"`.
- * @returns {Object} return
- * @returns {Number} return.x
- * @returns {Number} return.y
- */
-function getAbsoluteBoundaryPoint( element, resizerPosition ) {
-	const nativeRectangle = element.getBoundingClientRect();
-	const positionParts = resizerPosition.split( '-' );
-	const ret = {
-		x: positionParts[ 1 ] == 'right' ? nativeRectangle.right : nativeRectangle.left,
-		y: positionParts[ 0 ] == 'bottom' ? nativeRectangle.bottom : nativeRectangle.top
-	};
-
-	ret.x += element.ownerDocument.defaultView.scrollX;
-	ret.y += element.ownerDocument.defaultView.scrollY;
-
-	return ret;
-}
-
 function getAspectRatio( element ) {
 	const nativeRectangle = element.getBoundingClientRect();
 
@@ -54,6 +33,8 @@ export default class ResizeContext {
 		// view/Element
 		this.widgetWrapperElement = null;
 
+		this.resizeStrategy = new ResizerCentral( this, options );
+
 		/**
 		 * Container of entire resize UI.
 		 *
@@ -139,6 +120,8 @@ export default class ResizeContext {
 		if ( resizeHost ) {
 			this.aspectRatio = getAspectRatio( resizeHost, this.referenceHandlerPosition );
 		}
+
+		this.resizeStrategy.begin( domResizeHandler );
 	}
 
 	commit( editor ) {
@@ -156,12 +139,16 @@ export default class ResizeContext {
 		// Again, render will most likely change image size, so resizers needs a redraw.
 		editor.editing.view.once( 'render', () => this.redraw() );
 
+		this.resizeStrategy.commit( editor );
+
 		this._cleanupContext();
 	}
 
 	cancel() {
 		this._dismissShadow();
 
+		this.resizeStrategy.cancel();
+
 		this._cleanupContext();
 	}
 
@@ -183,45 +170,12 @@ export default class ResizeContext {
 	}
 
 	updateSize( domEventData ) {
-		const currentCoordinates = this._extractCoordinates( domEventData );
-
-		const proposedSize = {
-			x: Math.abs( currentCoordinates.x - this.referenceCoordinates.x ),
-			y: Math.abs( currentCoordinates.y - this.referenceCoordinates.y )
-		};
-
-		// Dominant determination must take the ratio into account.
-		proposedSize.dominant = proposedSize.x / this.aspectRatio > proposedSize.y ? 'x' : 'y';
-		proposedSize.max = proposedSize[ proposedSize.dominant ];
-
-		const drawnSize = {
-			x: proposedSize.x,
-			y: proposedSize.y
-		};
+		const proposedSize = this.resizeStrategy.updateSize( domEventData );
 
 		this.set( {
 			proposedX: proposedSize.x,
 			proposedY: proposedSize.y
 		} );
-
-		if ( proposedSize.dominant == 'x' ) {
-			drawnSize.y = drawnSize.x / this.aspectRatio;
-		} else {
-			drawnSize.x = drawnSize.y * this.aspectRatio;
-		}
-
-		// Reset shadow bounding.
-		this.domResizeShadow.style.top = 0;
-		this.domResizeShadow.style.left = 0;
-		this.domResizeShadow.style.bottom = 0;
-		this.domResizeShadow.style.right = 0;
-
-		this.domResizeShadow.style[ this.referenceHandlerPosition.split( '-' )[ 0 ] ] = 'auto';
-		this.domResizeShadow.style[ this.referenceHandlerPosition.split( '-' )[ 1 ] ] = 'auto';
-
-		// Apply the actual shadow dimensions.
-		this.domResizeShadow.style.width = `${ drawnSize.x }px`;
-		this.domResizeShadow.style.height = `${ drawnSize.y }px`;
 	}
 
 	redraw() {

+ 100 - 0
packages/ckeditor5-widget/src/resizercentral.js

@@ -0,0 +1,100 @@
+import {
+	getAbsoluteBoundaryPoint
+} from './utils';
+
+import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
+import mix from '@ckeditor/ckeditor5-utils/src/mix';
+
+/**
+ * Implements a resizer that enlarges/shrinks in all directions.
+ *
+ * @class ResizerCentral
+ */
+export default class ResizerCentral {
+	constructor( context, options ) {
+		this.context = context;
+		this.options = options || {};
+	}
+
+	attach() {}
+
+	begin() {
+		const resizeHost = this.context._getResizeHost();
+		this.closestReferencePoint = getAbsoluteBoundaryPoint( resizeHost, this.context.referenceHandlerPosition );
+	}
+
+	commit() {}
+
+	cancel() {}
+
+	destroy() {}
+
+	updateSize( domEventData ) {
+		const context = this.context;
+		const currentCoordinates = context._extractCoordinates( domEventData );
+
+		const enlargement = {
+			x: ( currentCoordinates.x - this.closestReferencePoint.x ) * 2,
+			y: ( currentCoordinates.y - this.closestReferencePoint.y ) * 2
+		};
+
+		// const resizeHost = this.context._getResizeHost();
+
+		// const initialSize = {
+		// 	x: resizeHost.width,
+		// 	y: resizeHost.height
+		// };
+
+		const proposedSize = {
+			// x: Math.abs( currentCoordinates.x - context.referenceCoordinates.x ),
+			// y: Math.abs( currentCoordinates.y - context.referenceCoordinates.y )
+			x: Math.abs( this.closestReferencePoint.x - context.referenceCoordinates.x + enlargement.x ),
+			y: Math.abs( this.closestReferencePoint.y - context.referenceCoordinates.y + enlargement.y )
+		};
+
+		// Dominant determination must take the ratio into account.
+		proposedSize.dominant = proposedSize.x / context.aspectRatio > proposedSize.y ? 'x' : 'y';
+		proposedSize.max = proposedSize[ proposedSize.dominant ];
+
+		const drawnSize = {
+			x: proposedSize.x,
+			y: proposedSize.y
+		};
+
+		if ( proposedSize.dominant == 'x' ) {
+			drawnSize.y = drawnSize.x / context.aspectRatio;
+		} else {
+			drawnSize.x = drawnSize.y * context.aspectRatio;
+		}
+
+		// console.log( 'initial', initialSize, 'drawn', drawnSize );
+
+		// Reset shadow bounding.
+		context.domResizeShadow.style.top = 'auto';
+		context.domResizeShadow.style.left = 'auto';
+		context.domResizeShadow.style.bottom = 'auto';
+		context.domResizeShadow.style.right = 'auto';
+
+		// context.domResizeShadow.style[ context.referenceHandlerPosition.split( '-' )[ 0 ] ] = 'auto';
+		// context.domResizeShadow.style[ context.referenceHandlerPosition.split( '-' )[ 1 ] ] = 'auto';
+
+		// const invertedPosition = this.context._invertPosition( context.referenceHandlerPosition );
+
+		// context.domResizeShadow.style[ invertedPosition.split( '-' )[ 0 ] ] = `${ ( drawnSize.x - initialSize.x ) / 2 * -1 }px`;
+		// context.domResizeShadow.style[ invertedPosition.split( '-' )[ 1 ] ] = `${ ( drawnSize.y - initialSize.y ) / 2 * -1 }px`;
+		// context.domResizeShadow.style[ invertedPosition.split( '-' )[ 0 ] ] = `${ enlargement.x / 2 * -1 }px`;
+		// context.domResizeShadow.style[ invertedPosition.split( '-' )[ 1 ] ] = `${ enlargement.y / 2 * -1 }px`;
+
+		// Apply the actual shadow dimensions.
+		context.domResizeShadow.style.width = `${ drawnSize.x }px`;
+		context.domResizeShadow.style.height = `${ drawnSize.y }px`;
+
+		return proposedSize;
+	}
+
+	redraw() {}
+
+	_getResizeHost() {}
+}
+
+mix( ResizerCentral, ObservableMixin );

+ 74 - 0
packages/ckeditor5-widget/src/resizerside.js

@@ -0,0 +1,74 @@
+import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
+import mix from '@ckeditor/ckeditor5-utils/src/mix';
+
+/**
+ * @module widget/resizecontext
+ */
+
+/**
+ * Implements a resizer that enlarges to the dragged side.
+ *
+ * @class ResizerSide
+ */
+export default class ResizerSide {
+	constructor( context, options ) {
+		this.context = context;
+		this.options = options || {};
+	}
+
+	attach() {}
+
+	begin() {}
+
+	commit() {}
+
+	cancel() {}
+
+	destroy() {}
+
+	updateSize( domEventData ) {
+		const context = this.context;
+		const currentCoordinates = context._extractCoordinates( domEventData );
+
+		const proposedSize = {
+			x: Math.abs( currentCoordinates.x - context.referenceCoordinates.x ),
+			y: Math.abs( currentCoordinates.y - context.referenceCoordinates.y )
+		};
+
+		// Dominant determination must take the ratio into account.
+		proposedSize.dominant = proposedSize.x / context.aspectRatio > proposedSize.y ? 'x' : 'y';
+		proposedSize.max = proposedSize[ proposedSize.dominant ];
+
+		const drawnSize = {
+			x: proposedSize.x,
+			y: proposedSize.y
+		};
+
+		if ( proposedSize.dominant == 'x' ) {
+			drawnSize.y = drawnSize.x / context.aspectRatio;
+		} else {
+			drawnSize.x = drawnSize.y * context.aspectRatio;
+		}
+
+		// Reset shadow bounding.
+		context.domResizeShadow.style.top = 0;
+		context.domResizeShadow.style.left = 0;
+		context.domResizeShadow.style.bottom = 0;
+		context.domResizeShadow.style.right = 0;
+
+		context.domResizeShadow.style[ context.referenceHandlerPosition.split( '-' )[ 0 ] ] = 'auto';
+		context.domResizeShadow.style[ context.referenceHandlerPosition.split( '-' )[ 1 ] ] = 'auto';
+
+		// Apply the actual shadow dimensions.
+		context.domResizeShadow.style.width = `${ drawnSize.x }px`;
+		context.domResizeShadow.style.height = `${ drawnSize.y }px`;
+
+		return proposedSize;
+	}
+
+	redraw() {}
+
+	_getResizeHost() {}
+}
+
+mix( ResizerSide, ObservableMixin );

+ 23 - 0
packages/ckeditor5-widget/src/utils.js

@@ -352,6 +352,29 @@ export function viewToModelPositionOutsideModelElement( model, viewElementMatche
 	};
 }
 
+/**
+ * Returns coordinates of top-left corner of a element, relative to the document's top-left corner.
+ *
+ * @param {HTMLElement} element
+ * @param {String} resizerPosition Position of the resize handler, e.g. `"top-left"`, `"bottom-right"`.
+ * @returns {Object} return
+ * @returns {Number} return.x
+ * @returns {Number} return.y
+ */
+export function getAbsoluteBoundaryPoint( element, resizerPosition ) {
+	const nativeRectangle = element.getBoundingClientRect();
+	const positionParts = resizerPosition.split( '-' );
+	const ret = {
+		x: positionParts[ 1 ] == 'right' ? nativeRectangle.right : nativeRectangle.left,
+		y: positionParts[ 0 ] == 'bottom' ? nativeRectangle.bottom : nativeRectangle.top
+	};
+
+	ret.x += element.ownerDocument.defaultView.scrollX;
+	ret.y += element.ownerDocument.defaultView.scrollY;
+
+	return ret;
+}
+
 // Default filler offset function applied to all widget elements.
 //
 // @returns {null}