UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

225 lines (211 loc) • 7.49 kB
/** * DevExtreme (viz/core/layout.js) * Version: 18.1.3 * Build date: Tue May 15 2018 * * Copyright (c) 2012 - 2018 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ "use strict"; var _normalizeEnum = require("./utils").normalizeEnum, _min = Math.min, _max = Math.max, ALIGN_START = 0, ALIGN_MIDDLE = 1, ALIGN_END = 2, horizontalAlignmentMap = { left: ALIGN_START, center: ALIGN_MIDDLE, right: ALIGN_END }, verticalAlignmentMap = { top: ALIGN_START, center: ALIGN_MIDDLE, bottom: ALIGN_END }, sideMap = { horizontal: 0, vertical: 1 }, slicersMap = {}; slicersMap[ALIGN_START] = function(a, b, size) { return [a, _min(b, a + size)] }; slicersMap[ALIGN_MIDDLE] = function(a, b, size) { return [_max(a, (a + b - size) / 2), _min(b, (a + b + size) / 2)] }; slicersMap[ALIGN_END] = function(a, b, size) { return [_max(a, b - size), b] }; function pickValue(value, map, defaultValue) { var val = _normalizeEnum(value); return val in map ? map[val] : defaultValue } function normalizeLayoutOptions(options) { var side = pickValue(options.side, sideMap, 1), alignment = [pickValue(options.horizontalAlignment, horizontalAlignmentMap, ALIGN_MIDDLE), pickValue(options.verticalAlignment, verticalAlignmentMap, ALIGN_START)]; return { side: side, primary: bringToEdge(alignment[side]), secondary: alignment[1 - side], weak: options.weak, priority: options.priority || 0, header: options.header } } function bringToEdge(primary) { return primary < 2 ? 0 : 2 } function getConjugateSide(side) { return 1 - side } function getSlice(alignment, a, b, size) { return slicersMap[alignment](a, b, size) } function getShrink(alignment, size) { return (alignment > 0 ? -1 : 1) * size } function processForward(item, rect, minSize) { var side = item.side, size = item.element.measure([rect[2] - rect[0], rect[3] - rect[1]]), isValid = size[side] < rect[2 + side] - rect[side] - minSize[side]; if (isValid) { rect[item.primary + side] += getShrink(item.primary, size[side]); item.size = size } return isValid } function processRectBackward(item, rect, alignmentRect) { var primarySide = item.side, secondarySide = getConjugateSide(primarySide), itemRect = [], secondary = getSlice(item.secondary, alignmentRect[secondarySide], alignmentRect[2 + secondarySide], item.size[secondarySide]); itemRect[primarySide] = itemRect[2 + primarySide] = rect[item.primary + primarySide]; itemRect[item.primary + primarySide] = rect[item.primary + primarySide] -= getShrink(item.primary, item.size[primarySide]); itemRect[secondarySide] = secondary[0]; itemRect[2 + secondarySide] = secondary[1]; return itemRect } function processBackward(item, rect, alignmentRect) { var rectCopy = rect.slice(), itemRect = processRectBackward(item, rect, alignmentRect); item.element.move(itemRect, rectCopy) } function Layout() { this._targets = [] } Layout.prototype = { constructor: Layout, dispose: function() { this._targets = null }, add: function(target) { this._targets.push(target) }, forward: function(targetRect, minSize) { var i, rect = targetRect.slice(), targets = createTargets(this._targets), ii = targets.length, cache = []; for (i = 0; i < ii; ++i) { if (processForward(targets[i], rect, minSize)) { cache.push(targets[i]) } else { targets[i].element.freeSpace() } } this._cache = cache.reverse(); return rect }, backward: function(targetRect, alignmentRect) { var target, i, backwardRect = targetRect.slice(), targets = this._cache, targetSide = 0, ii = targets.length; for (i = 0; i < ii; ++i) { target = targets[i]; if (target.side !== targetSide) { backwardRect = targetRect.slice() } processBackward(target, backwardRect, alignmentRect); targetSide = target.side } this._cache = null } }; function createTargets(targets) { var i, layout, ii = targets.length, collection = []; for (i = 0; i < ii; ++i) { layout = targets[i].layoutOptions(); if (layout) { layout = normalizeLayoutOptions(layout); layout.element = targets[i]; collection.push(layout) } } collection.sort(function(a, b) { return a.side - b.side || a.priority - b.priority }); collection = processWeakItems(collection); return collection } function processWeakItems(collection) { var headerItem, weakItem = collection.filter(function(item) { return true === item.weak })[0]; if (weakItem) { headerItem = collection.filter(function(item) { return weakItem.primary === item.primary && item.side === weakItem.side && item !== weakItem })[0] } if (weakItem && headerItem) { return [makeHeader(headerItem, weakItem)].concat(collection.filter(function(item) { return !(item === headerItem || item === weakItem) })) } return collection } function makeHeader(header, weakElement) { var side = header.side, primary = header.primary, secondary = header.secondary, secondarySide = getConjugateSide(side); return { side: side, primary: primary, secondary: secondary, priority: 0, element: { measure: function(targetSize) { var headerSize = header.element.measure(targetSize.slice()), weakSize = weakElement.element.measure(targetSize.slice()), size = headerSize.slice(); size[side] = Math.max(headerSize[side], weakSize[side]); weakSize[side] += (size[side] - weakSize[side]) / 2; headerSize[side] += (size[side] - weakSize[side]) / 2; weakElement.size = weakSize; header.size = headerSize; return size }, move: function(alignRect, rect) { var weakRect = processRectBackward(weakElement, rect, rect), intersection = alignRect[secondarySide + 2] - weakRect[secondarySide]; if (intersection > 0) { alignRect[secondarySide] -= intersection; alignRect[secondarySide + 2] -= intersection; if (alignRect[secondarySide] < 0) { alignRect[secondarySide] = 0 } } weakElement.element.move(weakRect); header.element.move(alignRect) }, freeSpace: function() { header.element.freeSpace(); weakElement.element.freeSpace() } } } } module.exports = Layout;