src/pyams_skin/resources/js/ext/tinymce/dev/classes/ui/FlexLayout.js
changeset 566 a1707c607eec
parent 565 318533413200
child 567 bca1726b1d85
equal deleted inserted replaced
565:318533413200 566:a1707c607eec
     1 /**
       
     2  * FlexLayout.js
       
     3  *
       
     4  * Copyright, Moxiecode Systems AB
       
     5  * Released under LGPL License.
       
     6  *
       
     7  * License: http://www.tinymce.com/license
       
     8  * Contributing: http://www.tinymce.com/contributing
       
     9  */
       
    10 
       
    11 /**
       
    12  * This layout manager works similar to the CSS flex box.
       
    13  *
       
    14  * @setting {String} direction row|row-reverse|column|column-reverse
       
    15  * @setting {Number} flex A positive-number to flex by.
       
    16  * @setting {String} align start|end|center|stretch
       
    17  * @setting {String} pack start|end|justify
       
    18  *
       
    19  * @class tinymce.ui.FlexLayout
       
    20  * @extends tinymce.ui.AbsoluteLayout
       
    21  */
       
    22 define("tinymce/ui/FlexLayout", [
       
    23 	"tinymce/ui/AbsoluteLayout"
       
    24 ], function(AbsoluteLayout) {
       
    25 	"use strict";
       
    26 
       
    27 	return AbsoluteLayout.extend({
       
    28 		/**
       
    29 		 * Recalculates the positions of the controls in the specified container.
       
    30 		 *
       
    31 		 * @method recalc
       
    32 		 * @param {tinymce.ui.Container} container Container instance to recalc.
       
    33 		 */
       
    34 		recalc: function(container) {
       
    35 			// A ton of variables, needs to be in the same scope for performance
       
    36 			var i, l, items, contLayoutRect, contPaddingBox, contSettings, align, pack, spacing, totalFlex, availableSpace, direction;
       
    37 			var ctrl, ctrlLayoutRect, ctrlSettings, flex, maxSizeItems = [], size, maxSize, ratio, rect, pos, maxAlignEndPos;
       
    38 			var sizeName, minSizeName, posName, maxSizeName, beforeName, innerSizeName, deltaSizeName, contentSizeName;
       
    39 			var alignAxisName, alignInnerSizeName, alignSizeName, alignMinSizeName, alignBeforeName, alignAfterName;
       
    40 			var alignDeltaSizeName, alignContentSizeName;
       
    41 			var max = Math.max, min = Math.min;
       
    42 
       
    43 			// Get container items, properties and settings
       
    44 			items = container.items().filter(':visible');
       
    45 			contLayoutRect = container.layoutRect();
       
    46 			contPaddingBox = container._paddingBox;
       
    47 			contSettings = container.settings;
       
    48 			direction = container.isRtl() ? (contSettings.direction || 'row-reversed') : contSettings.direction;
       
    49 			align = contSettings.align;
       
    50 			pack = container.isRtl() ? (contSettings.pack || 'end') : contSettings.pack;
       
    51 			spacing = contSettings.spacing || 0;
       
    52 
       
    53 			if (direction == "row-reversed" || direction == "column-reverse") {
       
    54 				items = items.set(items.toArray().reverse());
       
    55 				direction = direction.split('-')[0];
       
    56 			}
       
    57 
       
    58 			// Setup axis variable name for row/column direction since the calculations is the same
       
    59 			if (direction == "column") {
       
    60 				posName = "y";
       
    61 				sizeName = "h";
       
    62 				minSizeName = "minH";
       
    63 				maxSizeName = "maxH";
       
    64 				innerSizeName = "innerH";
       
    65 				beforeName = 'top';
       
    66 				deltaSizeName = "deltaH";
       
    67 				contentSizeName = "contentH";
       
    68 
       
    69 				alignBeforeName = "left";
       
    70 				alignSizeName = "w";
       
    71 				alignAxisName = "x";
       
    72 				alignInnerSizeName = "innerW";
       
    73 				alignMinSizeName = "minW";
       
    74 				alignAfterName = "right";
       
    75 				alignDeltaSizeName = "deltaW";
       
    76 				alignContentSizeName = "contentW";
       
    77 			} else {
       
    78 				posName = "x";
       
    79 				sizeName = "w";
       
    80 				minSizeName = "minW";
       
    81 				maxSizeName = "maxW";
       
    82 				innerSizeName = "innerW";
       
    83 				beforeName = 'left';
       
    84 				deltaSizeName = "deltaW";
       
    85 				contentSizeName = "contentW";
       
    86 
       
    87 				alignBeforeName = "top";
       
    88 				alignSizeName = "h";
       
    89 				alignAxisName = "y";
       
    90 				alignInnerSizeName = "innerH";
       
    91 				alignMinSizeName = "minH";
       
    92 				alignAfterName = "bottom";
       
    93 				alignDeltaSizeName = "deltaH";
       
    94 				alignContentSizeName = "contentH";
       
    95 			}
       
    96 
       
    97 			// Figure out total flex, availableSpace and collect any max size elements
       
    98 			availableSpace = contLayoutRect[innerSizeName] - contPaddingBox[beforeName] - contPaddingBox[beforeName];
       
    99 			maxAlignEndPos = totalFlex = 0;
       
   100 			for (i = 0, l = items.length; i < l; i++) {
       
   101 				ctrl = items[i];
       
   102 				ctrlLayoutRect = ctrl.layoutRect();
       
   103 				ctrlSettings = ctrl.settings;
       
   104 				flex = ctrlSettings.flex;
       
   105 				availableSpace -= (i < l - 1 ? spacing : 0);
       
   106 
       
   107 				if (flex > 0) {
       
   108 					totalFlex += flex;
       
   109 
       
   110 					// Flexed item has a max size then we need to check if we will hit that size
       
   111 					if (ctrlLayoutRect[maxSizeName]) {
       
   112 						maxSizeItems.push(ctrl);
       
   113 					}
       
   114 
       
   115 					ctrlLayoutRect.flex = flex;
       
   116 				}
       
   117 
       
   118 				availableSpace -= ctrlLayoutRect[minSizeName];
       
   119 
       
   120 				// Calculate the align end position to be used to check for overflow/underflow
       
   121 				size = contPaddingBox[alignBeforeName] + ctrlLayoutRect[alignMinSizeName] + contPaddingBox[alignAfterName];
       
   122 				if (size > maxAlignEndPos) {
       
   123 					maxAlignEndPos = size;
       
   124 				}
       
   125 			}
       
   126 
       
   127 			// Calculate minW/minH
       
   128 			rect = {};
       
   129 			if (availableSpace < 0) {
       
   130 				rect[minSizeName] = contLayoutRect[minSizeName] - availableSpace + contLayoutRect[deltaSizeName];
       
   131 			} else {
       
   132 				rect[minSizeName] = contLayoutRect[innerSizeName] - availableSpace + contLayoutRect[deltaSizeName];
       
   133 			}
       
   134 
       
   135 			rect[alignMinSizeName] = maxAlignEndPos + contLayoutRect[alignDeltaSizeName];
       
   136 
       
   137 			rect[contentSizeName] = contLayoutRect[innerSizeName] - availableSpace;
       
   138 			rect[alignContentSizeName] = maxAlignEndPos;
       
   139 			rect.minW = min(rect.minW, contLayoutRect.maxW);
       
   140 			rect.minH = min(rect.minH, contLayoutRect.maxH);
       
   141 			rect.minW = max(rect.minW, contLayoutRect.startMinWidth);
       
   142 			rect.minH = max(rect.minH, contLayoutRect.startMinHeight);
       
   143 
       
   144 			// Resize container container if minSize was changed
       
   145 			if (contLayoutRect.autoResize && (rect.minW != contLayoutRect.minW || rect.minH != contLayoutRect.minH)) {
       
   146 				rect.w = rect.minW;
       
   147 				rect.h = rect.minH;
       
   148 
       
   149 				container.layoutRect(rect);
       
   150 				this.recalc(container);
       
   151 
       
   152 				// Forced recalc for example if items are hidden/shown
       
   153 				if (container._lastRect === null) {
       
   154 					var parentCtrl = container.parent();
       
   155 					if (parentCtrl) {
       
   156 						parentCtrl._lastRect = null;
       
   157 						parentCtrl.recalc();
       
   158 					}
       
   159 				}
       
   160 
       
   161 				return;
       
   162 			}
       
   163 
       
   164 			// Handle max size elements, check if they will become to wide with current options
       
   165 			ratio = availableSpace / totalFlex;
       
   166 			for (i = 0, l = maxSizeItems.length; i < l; i++) {
       
   167 				ctrl = maxSizeItems[i];
       
   168 				ctrlLayoutRect = ctrl.layoutRect();
       
   169 				maxSize = ctrlLayoutRect[maxSizeName];
       
   170 				size = ctrlLayoutRect[minSizeName] + ctrlLayoutRect.flex * ratio;
       
   171 
       
   172 				if (size > maxSize) {
       
   173 					availableSpace -= (ctrlLayoutRect[maxSizeName] - ctrlLayoutRect[minSizeName]);
       
   174 					totalFlex -= ctrlLayoutRect.flex;
       
   175 					ctrlLayoutRect.flex = 0;
       
   176 					ctrlLayoutRect.maxFlexSize = maxSize;
       
   177 				} else {
       
   178 					ctrlLayoutRect.maxFlexSize = 0;
       
   179 				}
       
   180 			}
       
   181 
       
   182 			// Setup new ratio, target layout rect, start position
       
   183 			ratio = availableSpace / totalFlex;
       
   184 			pos = contPaddingBox[beforeName];
       
   185 			rect = {};
       
   186 
       
   187 			// Handle pack setting moves the start position to end, center
       
   188 			if (totalFlex === 0) {
       
   189 				if (pack == "end") {
       
   190 					pos = availableSpace + contPaddingBox[beforeName];
       
   191 				} else if (pack == "center") {
       
   192 					pos = Math.round(
       
   193 						(contLayoutRect[innerSizeName] / 2) - ((contLayoutRect[innerSizeName] - availableSpace) / 2)
       
   194 					) + contPaddingBox[beforeName];
       
   195 
       
   196 					if (pos < 0) {
       
   197 						pos = contPaddingBox[beforeName];
       
   198 					}
       
   199 				} else if (pack == "justify") {
       
   200 					pos = contPaddingBox[beforeName];
       
   201 					spacing = Math.floor(availableSpace / (items.length - 1));
       
   202 				}
       
   203 			}
       
   204 
       
   205 			// Default aligning (start) the other ones needs to be calculated while doing the layout
       
   206 			rect[alignAxisName] = contPaddingBox[alignBeforeName];
       
   207 
       
   208 			// Start laying out controls
       
   209 			for (i = 0, l = items.length; i < l; i++) {
       
   210 				ctrl = items[i];
       
   211 				ctrlLayoutRect = ctrl.layoutRect();
       
   212 				size = ctrlLayoutRect.maxFlexSize || ctrlLayoutRect[minSizeName];
       
   213 
       
   214 				// Align the control on the other axis
       
   215 				if (align === "center") {
       
   216 					rect[alignAxisName] = Math.round((contLayoutRect[alignInnerSizeName] / 2) - (ctrlLayoutRect[alignSizeName] / 2));
       
   217 				} else if (align === "stretch") {
       
   218 					rect[alignSizeName] = max(
       
   219 						ctrlLayoutRect[alignMinSizeName] || 0,
       
   220 						contLayoutRect[alignInnerSizeName] - contPaddingBox[alignBeforeName] - contPaddingBox[alignAfterName]
       
   221 					);
       
   222 					rect[alignAxisName] = contPaddingBox[alignBeforeName];
       
   223 				} else if (align === "end") {
       
   224 					rect[alignAxisName] = contLayoutRect[alignInnerSizeName] - ctrlLayoutRect[alignSizeName] - contPaddingBox.top;
       
   225 				}
       
   226 
       
   227 				// Calculate new size based on flex
       
   228 				if (ctrlLayoutRect.flex > 0) {
       
   229 					size += ctrlLayoutRect.flex * ratio;
       
   230 				}
       
   231 
       
   232 				rect[sizeName] = size;
       
   233 				rect[posName] = pos;
       
   234 				ctrl.layoutRect(rect);
       
   235 
       
   236 				// Recalculate containers
       
   237 				if (ctrl.recalc) {
       
   238 					ctrl.recalc();
       
   239 				}
       
   240 
       
   241 				// Move x/y position
       
   242 				pos += size + spacing;
       
   243 			}
       
   244 		}
       
   245 	});
       
   246 });