layout.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /**
  2. * DevExtreme (viz/vector_map/layout.js)
  3. * Version: 19.1.16
  4. * Build date: Tue Oct 18 2022
  5. *
  6. * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
  7. * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
  8. */
  9. "use strict";
  10. var inArray = require("../../core/utils/array").inArray;
  11. var each = require("../../core/utils/iterator").each;
  12. var _round = Math.round;
  13. var _min = Math.min;
  14. var _max = Math.max;
  15. var _each = each;
  16. var _inArray = inArray;
  17. var horizontalAlignmentMap = {
  18. left: 0,
  19. center: 1,
  20. right: 2
  21. };
  22. var verticalAlignmentMap = {
  23. top: 0,
  24. bottom: 1
  25. };
  26. function getCellIndex(options) {
  27. return 3 * verticalAlignmentMap[options.verticalAlignment] + horizontalAlignmentMap[options.horizontalAlignment]
  28. }
  29. function createCells(canvas, items) {
  30. var hStep = (canvas.right - canvas.left) / 3;
  31. var vStep = (canvas.bottom - canvas.top) / 2;
  32. var h1 = canvas.left;
  33. var h2 = _round(h1 + hStep);
  34. var h3 = _round(h1 + hStep + hStep);
  35. var h4 = canvas.right;
  36. var v1 = canvas.top;
  37. var v2 = _round(v1 + vStep);
  38. var v3 = canvas.bottom;
  39. var cells = [{
  40. rect: [h1, v1, h2, v2]
  41. }, {
  42. rect: [h2, v1, h3, v2],
  43. center: true
  44. }, {
  45. rect: [h3, v1, h4, v2],
  46. horInversion: true
  47. }, {
  48. rect: [h1, v2, h2, v3],
  49. verInversion: true
  50. }, {
  51. rect: [h2, v2, h3, v3],
  52. center: true,
  53. verInversion: true
  54. }, {
  55. rect: [h3, v2, h4, v3],
  56. horInversion: true,
  57. verInversion: true
  58. }];
  59. var itemsList = [
  60. [],
  61. [],
  62. [],
  63. [],
  64. [],
  65. []
  66. ];
  67. _each(items, function(_, item) {
  68. var options = item.getLayoutOptions();
  69. if (options) {
  70. itemsList[getCellIndex(options)].push({
  71. item: item,
  72. width: options.width,
  73. height: options.height
  74. })
  75. }
  76. });
  77. _each(cells, function(i, cell) {
  78. if (itemsList[i].length) {
  79. cell.items = itemsList[i]
  80. } else {
  81. if (cell.center) {
  82. cell.rect[0] = cell.rect[2] = (cell.rect[0] + cell.rect[2]) / 2
  83. } else {
  84. cell.rect[cell.horInversion ? 0 : 2] = cell.rect[cell.horInversion ? 2 : 0]
  85. }
  86. cell.rect[cell.verInversion ? 1 : 3] = cell.rect[cell.verInversion ? 3 : 1]
  87. }
  88. });
  89. return cells
  90. }
  91. function adjustCellSizes(cells) {
  92. _each([0, 1, 2, 3, 4, 5], function(_, index) {
  93. var cell = cells[index];
  94. var otherCell = cells[(index + 3) % 6];
  95. if (cell.items) {
  96. if (!otherCell.items) {
  97. cell.rect[1] = _min(cell.rect[1], otherCell.rect[3]);
  98. cell.rect[3] = _max(cell.rect[3], otherCell.rect[1])
  99. }
  100. }
  101. });
  102. _each([1, 4], function(_, index) {
  103. var cell = cells[index];
  104. var otherCell1 = cells[index - 1];
  105. var otherCell2 = cells[index + 1];
  106. var size1;
  107. var size2;
  108. if (cell.items) {
  109. if (!otherCell1.items && !otherCell2.items) {
  110. size1 = cell.rect[0] - otherCell1.rect[2];
  111. size2 = otherCell2.rect[0] - cell.rect[2];
  112. if (size1 > size2) {
  113. if (size1 / size2 >= 2) {
  114. cell.rect[0] -= size1;
  115. cell.right = true
  116. } else {
  117. cell.rect[0] -= size2;
  118. cell.rect[2] += size2
  119. }
  120. } else {
  121. if (size2 / size1 >= 2) {
  122. cell.rect[2] += size2;
  123. cell.center = null
  124. } else {
  125. cell.rect[0] -= size1;
  126. cell.rect[2] += size1
  127. }
  128. }
  129. }
  130. } else {
  131. if (otherCell1.items) {
  132. otherCell1.rect[2] = (cell.rect[0] + cell.rect[2]) / 2
  133. }
  134. if (otherCell2.items) {
  135. otherCell2.rect[0] = (cell.rect[0] + cell.rect[2]) / 2
  136. }
  137. }
  138. })
  139. }
  140. function adjustCellsAndApplyLayout(cells, forceMode) {
  141. var hasHiddenItems = false;
  142. adjustCellSizes(cells);
  143. _each(cells, function(_, cell) {
  144. if (cell.items) {
  145. hasHiddenItems = applyCellLayout(cell, forceMode) || hasHiddenItems
  146. }
  147. });
  148. return hasHiddenItems
  149. }
  150. function applyCellLayout(cell, forceMode) {
  151. var cellRect = cell.rect;
  152. var cellWidth = cellRect[2] - cellRect[0];
  153. var cellHeight = cellRect[3] - cellRect[1];
  154. var xOffset = 0;
  155. var yOffset = 0;
  156. var currentHeight = 0;
  157. var totalL = cellRect[2];
  158. var totalT = cellRect[3];
  159. var totalR = cellRect[0];
  160. var totalB = cellRect[1];
  161. var moves = [];
  162. var hasHiddenItems = false;
  163. _each(cell.items, function(_, item) {
  164. if (item.width > cellWidth || item.height > cellHeight) {
  165. moves.push(null);
  166. hasHiddenItems = true;
  167. return forceMode || false
  168. }
  169. if (xOffset + item.width > cellWidth) {
  170. yOffset += currentHeight;
  171. xOffset = currentHeight = 0
  172. }
  173. if (yOffset + item.height > cellHeight) {
  174. moves.push(null);
  175. hasHiddenItems = true;
  176. return forceMode || false
  177. }
  178. currentHeight = _max(currentHeight, item.height);
  179. var dx = cell.horInversion ? cellRect[2] - item.width - xOffset : cellRect[0] + xOffset;
  180. var dy = cell.verInversion ? cellRect[3] - item.height - yOffset : cellRect[1] + yOffset;
  181. xOffset += item.width;
  182. totalL = _min(totalL, dx);
  183. totalT = _min(totalT, dy);
  184. totalR = _max(totalR, dx + item.width);
  185. totalB = _max(totalB, dy + item.height);
  186. moves.push([dx, dy])
  187. });
  188. if (forceMode || !hasHiddenItems) {
  189. xOffset = 0;
  190. if (cell.right) {
  191. xOffset = cellRect[2] - cellRect[0] - totalR + totalL
  192. } else {
  193. if (cell.center) {
  194. xOffset = _round((cellRect[2] - cellRect[0] - totalR + totalL) / 2)
  195. }
  196. }
  197. _each(cell.items, function(i, item) {
  198. var move = moves[i];
  199. if (move) {
  200. item.item.locate(move[0] + xOffset, move[1])
  201. } else {
  202. item.item.resize(null)
  203. }
  204. });
  205. cell.rect = [totalL, totalT, totalR, totalB];
  206. cell.items = null
  207. }
  208. return hasHiddenItems
  209. }
  210. function applyLayout(canvas, items) {
  211. var cells = createCells(canvas, items);
  212. if (adjustCellsAndApplyLayout(cells)) {
  213. adjustCellsAndApplyLayout(cells, true)
  214. }
  215. }
  216. function LayoutControl() {
  217. var that = this;
  218. that._items = [];
  219. that._suspended = 0;
  220. that._updateLayout = function() {
  221. that._update()
  222. }
  223. }
  224. LayoutControl.prototype = {
  225. constructor: LayoutControl,
  226. dispose: function() {
  227. this._items = this._updateLayout = null
  228. },
  229. setSize: function(canvas) {
  230. this._canvas = canvas;
  231. this._update()
  232. },
  233. suspend: function() {
  234. ++this._suspended
  235. },
  236. resume: function() {
  237. if (0 === --this._suspended) {
  238. this._update()
  239. }
  240. },
  241. addItem: function(item) {
  242. this._items.push(item);
  243. item.updateLayout = this._updateLayout
  244. },
  245. removeItem: function(item) {
  246. this._items.splice(_inArray(item, this._items), 1);
  247. item.updateLayout = null
  248. },
  249. _update: function() {
  250. var canvas;
  251. if (0 === this._suspended) {
  252. canvas = this._canvas;
  253. _each(this._items, function(_, item) {
  254. item.resize(canvas)
  255. });
  256. applyLayout({
  257. left: canvas.left,
  258. top: canvas.top,
  259. right: canvas.width + canvas.left,
  260. bottom: canvas.height + canvas.top
  261. }, this._items)
  262. }
  263. }
  264. };
  265. exports.LayoutControl = LayoutControl;