mxGraphSelectionModel.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. /**
  2. * Copyright (c) 2006-2015, JGraph Ltd
  3. * Copyright (c) 2006-2015, Gaudenz Alder
  4. */
  5. /**
  6. * Class: mxGraphSelectionModel
  7. *
  8. * Implements the selection model for a graph. Here is a listener that handles
  9. * all removed selection cells.
  10. *
  11. * (code)
  12. * graph.getSelectionModel().addListener(mxEvent.CHANGE, function(sender, evt)
  13. * {
  14. * var cells = evt.getProperty('added');
  15. *
  16. * for (var i = 0; i < cells.length; i++)
  17. * {
  18. * // Handle cells[i]...
  19. * }
  20. * });
  21. * (end)
  22. *
  23. * Event: mxEvent.UNDO
  24. *
  25. * Fires after the selection was changed in <changeSelection>. The
  26. * <code>edit</code> property contains the <mxUndoableEdit> which contains the
  27. * <mxSelectionChange>.
  28. *
  29. * Event: mxEvent.CHANGE
  30. *
  31. * Fires after the selection changes by executing an <mxSelectionChange>. The
  32. * <code>added</code> and <code>removed</code> properties contain arrays of
  33. * cells that have been added to or removed from the selection, respectively.
  34. * The names are inverted due to historic reasons. This cannot be changed.
  35. *
  36. * Constructor: mxGraphSelectionModel
  37. *
  38. * Constructs a new graph selection model for the given <mxGraph>.
  39. *
  40. * Parameters:
  41. *
  42. * graph - Reference to the enclosing <mxGraph>.
  43. */
  44. function mxGraphSelectionModel(graph)
  45. {
  46. this.graph = graph;
  47. this.cells = [];
  48. };
  49. /**
  50. * Extends mxEventSource.
  51. */
  52. mxGraphSelectionModel.prototype = new mxEventSource();
  53. mxGraphSelectionModel.prototype.constructor = mxGraphSelectionModel;
  54. /**
  55. * Variable: doneResource
  56. *
  57. * Specifies the resource key for the status message after a long operation.
  58. * If the resource for this key does not exist then the value is used as
  59. * the status message. Default is 'done'.
  60. */
  61. mxGraphSelectionModel.prototype.doneResource = (mxClient.language != 'none') ? 'done' : '';
  62. /**
  63. * Variable: updatingSelectionResource
  64. *
  65. * Specifies the resource key for the status message while the selection is
  66. * being updated. If the resource for this key does not exist then the
  67. * value is used as the status message. Default is 'updatingSelection'.
  68. */
  69. mxGraphSelectionModel.prototype.updatingSelectionResource = (mxClient.language != 'none') ? 'updatingSelection' : '';
  70. /**
  71. * Variable: graph
  72. *
  73. * Reference to the enclosing <mxGraph>.
  74. */
  75. mxGraphSelectionModel.prototype.graph = null;
  76. /**
  77. * Variable: singleSelection
  78. *
  79. * Specifies if only one selected item at a time is allowed.
  80. * Default is false.
  81. */
  82. mxGraphSelectionModel.prototype.singleSelection = false;
  83. /**
  84. * Function: isSingleSelection
  85. *
  86. * Returns <singleSelection> as a boolean.
  87. */
  88. mxGraphSelectionModel.prototype.isSingleSelection = function()
  89. {
  90. return this.singleSelection;
  91. };
  92. /**
  93. * Function: setSingleSelection
  94. *
  95. * Sets the <singleSelection> flag.
  96. *
  97. * Parameters:
  98. *
  99. * singleSelection - Boolean that specifies the new value for
  100. * <singleSelection>.
  101. */
  102. mxGraphSelectionModel.prototype.setSingleSelection = function(singleSelection)
  103. {
  104. this.singleSelection = singleSelection;
  105. };
  106. /**
  107. * Function: isSelected
  108. *
  109. * Returns true if the given <mxCell> is selected.
  110. */
  111. mxGraphSelectionModel.prototype.isSelected = function(cell)
  112. {
  113. if (cell != null)
  114. {
  115. return mxUtils.indexOf(this.cells, cell) >= 0;
  116. }
  117. return false;
  118. };
  119. /**
  120. * Function: isEmpty
  121. *
  122. * Returns true if no cells are currently selected.
  123. */
  124. mxGraphSelectionModel.prototype.isEmpty = function()
  125. {
  126. return this.cells.length == 0;
  127. };
  128. /**
  129. * Function: clear
  130. *
  131. * Clears the selection and fires a <change> event if the selection was not
  132. * empty.
  133. */
  134. mxGraphSelectionModel.prototype.clear = function()
  135. {
  136. this.changeSelection(null, this.cells);
  137. };
  138. /**
  139. * Function: setCell
  140. *
  141. * Selects the specified <mxCell> using <setCells>.
  142. *
  143. * Parameters:
  144. *
  145. * cell - <mxCell> to be selected.
  146. */
  147. mxGraphSelectionModel.prototype.setCell = function(cell)
  148. {
  149. if (cell != null)
  150. {
  151. this.setCells([cell]);
  152. }
  153. };
  154. /**
  155. * Function: setCells
  156. *
  157. * Selects the given array of <mxCells> and fires a <change> event.
  158. *
  159. * Parameters:
  160. *
  161. * cells - Array of <mxCells> to be selected.
  162. */
  163. mxGraphSelectionModel.prototype.setCells = function(cells)
  164. {
  165. if (cells != null)
  166. {
  167. if (this.singleSelection)
  168. {
  169. cells = [this.getFirstSelectableCell(cells)];
  170. }
  171. var tmp = [];
  172. for (var i = 0; i < cells.length; i++)
  173. {
  174. if (this.graph.isCellSelectable(cells[i]))
  175. {
  176. tmp.push(cells[i]);
  177. }
  178. }
  179. this.changeSelection(tmp, this.cells);
  180. }
  181. };
  182. /**
  183. * Function: getFirstSelectableCell
  184. *
  185. * Returns the first selectable cell in the given array of cells.
  186. */
  187. mxGraphSelectionModel.prototype.getFirstSelectableCell = function(cells)
  188. {
  189. if (cells != null)
  190. {
  191. for (var i = 0; i < cells.length; i++)
  192. {
  193. if (this.graph.isCellSelectable(cells[i]))
  194. {
  195. return cells[i];
  196. }
  197. }
  198. }
  199. return null;
  200. };
  201. /**
  202. * Function: addCell
  203. *
  204. * Adds the given <mxCell> to the selection and fires a <select> event.
  205. *
  206. * Parameters:
  207. *
  208. * cell - <mxCell> to add to the selection.
  209. */
  210. mxGraphSelectionModel.prototype.addCell = function(cell)
  211. {
  212. if (cell != null)
  213. {
  214. this.addCells([cell]);
  215. }
  216. };
  217. /**
  218. * Function: addCells
  219. *
  220. * Adds the given array of <mxCells> to the selection and fires a <select>
  221. * event.
  222. *
  223. * Parameters:
  224. *
  225. * cells - Array of <mxCells> to add to the selection.
  226. */
  227. mxGraphSelectionModel.prototype.addCells = function(cells)
  228. {
  229. if (cells != null)
  230. {
  231. var remove = null;
  232. if (this.singleSelection)
  233. {
  234. remove = this.cells;
  235. cells = [this.getFirstSelectableCell(cells)];
  236. }
  237. var tmp = [];
  238. for (var i = 0; i < cells.length; i++)
  239. {
  240. if (!this.isSelected(cells[i]) &&
  241. this.graph.isCellSelectable(cells[i]))
  242. {
  243. tmp.push(cells[i]);
  244. }
  245. }
  246. this.changeSelection(tmp, remove);
  247. }
  248. };
  249. /**
  250. * Function: removeCell
  251. *
  252. * Removes the specified <mxCell> from the selection and fires a <select>
  253. * event for the remaining cells.
  254. *
  255. * Parameters:
  256. *
  257. * cell - <mxCell> to remove from the selection.
  258. */
  259. mxGraphSelectionModel.prototype.removeCell = function(cell)
  260. {
  261. if (cell != null)
  262. {
  263. this.removeCells([cell]);
  264. }
  265. };
  266. /**
  267. * Function: removeCells
  268. */
  269. mxGraphSelectionModel.prototype.removeCells = function(cells)
  270. {
  271. if (cells != null)
  272. {
  273. var tmp = [];
  274. for (var i = 0; i < cells.length; i++)
  275. {
  276. if (this.isSelected(cells[i]))
  277. {
  278. tmp.push(cells[i]);
  279. }
  280. }
  281. this.changeSelection(null, tmp);
  282. }
  283. };
  284. /**
  285. * Function: changeSelection
  286. *
  287. * Adds/removes the specified arrays of <mxCell> to/from the selection.
  288. *
  289. * Parameters:
  290. *
  291. * added - Array of <mxCell> to add to the selection.
  292. * remove - Array of <mxCell> to remove from the selection.
  293. */
  294. mxGraphSelectionModel.prototype.changeSelection = function(added, removed)
  295. {
  296. if ((added != null &&
  297. added.length > 0 &&
  298. added[0] != null) ||
  299. (removed != null &&
  300. removed.length > 0 &&
  301. removed[0] != null))
  302. {
  303. var change = new mxSelectionChange(this, added, removed);
  304. change.execute();
  305. var edit = new mxUndoableEdit(this, false);
  306. edit.add(change);
  307. this.fireEvent(new mxEventObject(mxEvent.UNDO, 'edit', edit));
  308. }
  309. };
  310. /**
  311. * Function: cellAdded
  312. *
  313. * Inner callback to add the specified <mxCell> to the selection. No event
  314. * is fired in this implementation.
  315. *
  316. * Paramters:
  317. *
  318. * cell - <mxCell> to add to the selection.
  319. */
  320. mxGraphSelectionModel.prototype.cellAdded = function(cell)
  321. {
  322. if (cell != null &&
  323. !this.isSelected(cell))
  324. {
  325. this.cells.push(cell);
  326. }
  327. };
  328. /**
  329. * Function: cellRemoved
  330. *
  331. * Inner callback to remove the specified <mxCell> from the selection. No
  332. * event is fired in this implementation.
  333. *
  334. * Parameters:
  335. *
  336. * cell - <mxCell> to remove from the selection.
  337. */
  338. mxGraphSelectionModel.prototype.cellRemoved = function(cell)
  339. {
  340. if (cell != null)
  341. {
  342. var index = mxUtils.indexOf(this.cells, cell);
  343. if (index >= 0)
  344. {
  345. this.cells.splice(index, 1);
  346. }
  347. }
  348. };
  349. /**
  350. * Class: mxSelectionChange
  351. *
  352. * Action to change the current root in a view.
  353. *
  354. * Constructor: mxCurrentRootChange
  355. *
  356. * Constructs a change of the current root in the given view.
  357. */
  358. function mxSelectionChange(selectionModel, added, removed)
  359. {
  360. this.selectionModel = selectionModel;
  361. this.added = (added != null) ? added.slice() : null;
  362. this.removed = (removed != null) ? removed.slice() : null;
  363. };
  364. /**
  365. * Function: execute
  366. *
  367. * Changes the current root of the view.
  368. */
  369. mxSelectionChange.prototype.execute = function()
  370. {
  371. var t0 = mxLog.enter('mxSelectionChange.execute');
  372. window.status = mxResources.get(
  373. this.selectionModel.updatingSelectionResource) ||
  374. this.selectionModel.updatingSelectionResource;
  375. if (this.removed != null)
  376. {
  377. for (var i = 0; i < this.removed.length; i++)
  378. {
  379. this.selectionModel.cellRemoved(this.removed[i]);
  380. }
  381. }
  382. if (this.added != null)
  383. {
  384. for (var i = 0; i < this.added.length; i++)
  385. {
  386. this.selectionModel.cellAdded(this.added[i]);
  387. }
  388. }
  389. var tmp = this.added;
  390. this.added = this.removed;
  391. this.removed = tmp;
  392. window.status = mxResources.get(this.selectionModel.doneResource) ||
  393. this.selectionModel.doneResource;
  394. mxLog.leave('mxSelectionChange.execute', t0);
  395. this.selectionModel.fireEvent(new mxEventObject(mxEvent.CHANGE,
  396. 'added', this.added, 'removed', this.removed));
  397. };