mxGraphModel.js 62 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755
  1. /**
  2. * Copyright (c) 2006-2018, JGraph Ltd
  3. * Copyright (c) 2006-2018, Gaudenz Alder
  4. */
  5. /**
  6. * Class: mxGraphModel
  7. *
  8. * Extends <mxEventSource> to implement a graph model. The graph model acts as
  9. * a wrapper around the cells which are in charge of storing the actual graph
  10. * datastructure. The model acts as a transactional wrapper with event
  11. * notification for all changes, whereas the cells contain the atomic
  12. * operations for updating the actual datastructure.
  13. *
  14. * Layers:
  15. *
  16. * The cell hierarchy in the model must have a top-level root cell which
  17. * contains the layers (typically one default layer), which in turn contain the
  18. * top-level cells of the layers. This means each cell is contained in a layer.
  19. * If no layers are required, then all new cells should be added to the default
  20. * layer.
  21. *
  22. * Layers are useful for hiding and showing groups of cells, or for placing
  23. * groups of cells on top of other cells in the display. To identify a layer,
  24. * the <isLayer> function is used. It returns true if the parent of the given
  25. * cell is the root of the model.
  26. *
  27. * Events:
  28. *
  29. * See events section for more details. There is a new set of events for
  30. * tracking transactional changes as they happen. The events are called
  31. * startEdit for the initial beginUpdate, executed for each executed change
  32. * and endEdit for the terminal endUpdate. The executed event contains a
  33. * property called change which represents the change after execution.
  34. *
  35. * Encoding the model:
  36. *
  37. * To encode a graph model, use the following code:
  38. *
  39. * (code)
  40. * var enc = new mxCodec();
  41. * var node = enc.encode(graph.getModel());
  42. * (end)
  43. *
  44. * This will create an XML node that contains all the model information.
  45. *
  46. * Encoding and decoding changes:
  47. *
  48. * For the encoding of changes, a graph model listener is required that encodes
  49. * each change from the given array of changes.
  50. *
  51. * (code)
  52. * model.addListener(mxEvent.CHANGE, function(sender, evt)
  53. * {
  54. * var changes = evt.getProperty('edit').changes;
  55. * var nodes = [];
  56. * var codec = new mxCodec();
  57. *
  58. * for (var i = 0; i < changes.length; i++)
  59. * {
  60. * nodes.push(codec.encode(changes[i]));
  61. * }
  62. * // do something with the nodes
  63. * });
  64. * (end)
  65. *
  66. * For the decoding and execution of changes, the codec needs a lookup function
  67. * that allows it to resolve cell IDs as follows:
  68. *
  69. * (code)
  70. * var codec = new mxCodec();
  71. * codec.lookup = function(id)
  72. * {
  73. * return model.getCell(id);
  74. * }
  75. * (end)
  76. *
  77. * For each encoded change (represented by a node), the following code can be
  78. * used to carry out the decoding and create a change object.
  79. *
  80. * (code)
  81. * var changes = [];
  82. * var change = codec.decode(node);
  83. * change.model = model;
  84. * change.execute();
  85. * changes.push(change);
  86. * (end)
  87. *
  88. * The changes can then be dispatched using the model as follows.
  89. *
  90. * (code)
  91. * var edit = new mxUndoableEdit(model, false);
  92. * edit.changes = changes;
  93. *
  94. * edit.notify = function()
  95. * {
  96. * edit.source.fireEvent(new mxEventObject(mxEvent.CHANGE,
  97. * 'edit', edit, 'changes', edit.changes));
  98. * edit.source.fireEvent(new mxEventObject(mxEvent.NOTIFY,
  99. * 'edit', edit, 'changes', edit.changes));
  100. * }
  101. *
  102. * model.fireEvent(new mxEventObject(mxEvent.UNDO, 'edit', edit));
  103. * model.fireEvent(new mxEventObject(mxEvent.CHANGE,
  104. * 'edit', edit, 'changes', changes));
  105. * (end)
  106. *
  107. * Event: mxEvent.CHANGE
  108. *
  109. * Fires when an undoable edit is dispatched. The <code>edit</code> property
  110. * contains the <mxUndoableEdit>. The <code>changes</code> property contains
  111. * the array of atomic changes inside the undoable edit. The changes property
  112. * is <strong>deprecated</strong>, please use edit.changes instead.
  113. *
  114. * Example:
  115. *
  116. * For finding newly inserted cells, the following code can be used:
  117. *
  118. * (code)
  119. * graph.model.addListener(mxEvent.CHANGE, function(sender, evt)
  120. * {
  121. * var changes = evt.getProperty('edit').changes;
  122. *
  123. * for (var i = 0; i < changes.length; i++)
  124. * {
  125. * var change = changes[i];
  126. *
  127. * if (change instanceof mxChildChange &&
  128. * change.change.previous == null)
  129. * {
  130. * graph.startEditingAtCell(change.child);
  131. * break;
  132. * }
  133. * }
  134. * });
  135. * (end)
  136. *
  137. *
  138. * Event: mxEvent.NOTIFY
  139. *
  140. * Same as <mxEvent.CHANGE>, this event can be used for classes that need to
  141. * implement a sync mechanism between this model and, say, a remote model. In
  142. * such a setup, only local changes should trigger a notify event and all
  143. * changes should trigger a change event.
  144. *
  145. * Event: mxEvent.EXECUTE
  146. *
  147. * Fires between begin- and endUpdate and after an atomic change was executed
  148. * in the model. The <code>change</code> property contains the atomic change
  149. * that was executed.
  150. *
  151. * Event: mxEvent.EXECUTED
  152. *
  153. * Fires between START_EDIT and END_EDIT after an atomic change was executed.
  154. * The <code>change</code> property contains the change that was executed.
  155. *
  156. * Event: mxEvent.BEGIN_UPDATE
  157. *
  158. * Fires after the <updateLevel> was incremented in <beginUpdate>. This event
  159. * contains no properties.
  160. *
  161. * Event: mxEvent.START_EDIT
  162. *
  163. * Fires after the <updateLevel> was changed from 0 to 1. This event
  164. * contains no properties.
  165. *
  166. * Event: mxEvent.END_UPDATE
  167. *
  168. * Fires after the <updateLevel> was decreased in <endUpdate> but before any
  169. * notification or change dispatching. The <code>edit</code> property contains
  170. * the <currentEdit>.
  171. *
  172. * Event: mxEvent.END_EDIT
  173. *
  174. * Fires after the <updateLevel> was changed from 1 to 0. This event
  175. * contains no properties.
  176. *
  177. * Event: mxEvent.BEFORE_UNDO
  178. *
  179. * Fires before the change is dispatched after the update level has reached 0
  180. * in <endUpdate>. The <code>edit</code> property contains the <curreneEdit>.
  181. *
  182. * Event: mxEvent.UNDO
  183. *
  184. * Fires after the change was dispatched in <endUpdate>. The <code>edit</code>
  185. * property contains the <currentEdit>.
  186. *
  187. * Constructor: mxGraphModel
  188. *
  189. * Constructs a new graph model. If no root is specified then a new root
  190. * <mxCell> with a default layer is created.
  191. *
  192. * Parameters:
  193. *
  194. * root - <mxCell> that represents the root cell.
  195. */
  196. function mxGraphModel(root)
  197. {
  198. this.currentEdit = this.createUndoableEdit();
  199. if (root != null)
  200. {
  201. this.setRoot(root);
  202. }
  203. else
  204. {
  205. this.clear();
  206. }
  207. };
  208. /**
  209. * Extends mxEventSource.
  210. */
  211. mxGraphModel.prototype = new mxEventSource();
  212. mxGraphModel.prototype.constructor = mxGraphModel;
  213. /**
  214. * Variable: root
  215. *
  216. * Holds the root cell, which in turn contains the cells that represent the
  217. * layers of the diagram as child cells. That is, the actual elements of the
  218. * diagram are supposed to live in the third generation of cells and below.
  219. */
  220. mxGraphModel.prototype.root = null;
  221. /**
  222. * Variable: cells
  223. *
  224. * Maps from Ids to cells.
  225. */
  226. mxGraphModel.prototype.cells = null;
  227. /**
  228. * Variable: maintainEdgeParent
  229. *
  230. * Specifies if edges should automatically be moved into the nearest common
  231. * ancestor of their terminals. Default is true.
  232. */
  233. mxGraphModel.prototype.maintainEdgeParent = true;
  234. /**
  235. * Variable: ignoreRelativeEdgeParent
  236. *
  237. * Specifies if relative edge parents should be ignored for finding the nearest
  238. * common ancestors of an edge's terminals. Default is true.
  239. */
  240. mxGraphModel.prototype.ignoreRelativeEdgeParent = true;
  241. /**
  242. * Variable: createIds
  243. *
  244. * Specifies if the model should automatically create Ids for new cells.
  245. * Default is true.
  246. */
  247. mxGraphModel.prototype.createIds = true;
  248. /**
  249. * Variable: prefix
  250. *
  251. * Defines the prefix of new Ids. Default is an empty string.
  252. */
  253. mxGraphModel.prototype.prefix = '';
  254. /**
  255. * Variable: postfix
  256. *
  257. * Defines the postfix of new Ids. Default is an empty string.
  258. */
  259. mxGraphModel.prototype.postfix = '';
  260. /**
  261. * Variable: nextId
  262. *
  263. * Specifies the next Id to be created. Initial value is 0.
  264. */
  265. mxGraphModel.prototype.nextId = 0;
  266. /**
  267. * Variable: currentEdit
  268. *
  269. * Holds the changes for the current transaction. If the transaction is
  270. * closed then a new object is created for this variable using
  271. * <createUndoableEdit>.
  272. */
  273. mxGraphModel.prototype.currentEdit = null;
  274. /**
  275. * Variable: updateLevel
  276. *
  277. * Counter for the depth of nested transactions. Each call to <beginUpdate>
  278. * will increment this number and each call to <endUpdate> will decrement
  279. * it. When the counter reaches 0, the transaction is closed and the
  280. * respective events are fired. Initial value is 0.
  281. */
  282. mxGraphModel.prototype.updateLevel = 0;
  283. /**
  284. * Variable: endingUpdate
  285. *
  286. * True if the program flow is currently inside endUpdate.
  287. */
  288. mxGraphModel.prototype.endingUpdate = false;
  289. /**
  290. * Function: clear
  291. *
  292. * Sets a new root using <createRoot>.
  293. */
  294. mxGraphModel.prototype.clear = function()
  295. {
  296. this.setRoot(this.createRoot());
  297. };
  298. /**
  299. * Function: isCreateIds
  300. *
  301. * Returns <createIds>.
  302. */
  303. mxGraphModel.prototype.isCreateIds = function()
  304. {
  305. return this.createIds;
  306. };
  307. /**
  308. * Function: setCreateIds
  309. *
  310. * Sets <createIds>.
  311. */
  312. mxGraphModel.prototype.setCreateIds = function(value)
  313. {
  314. this.createIds = value;
  315. };
  316. /**
  317. * Function: createRoot
  318. *
  319. * Creates a new root cell with a default layer (child 0).
  320. */
  321. mxGraphModel.prototype.createRoot = function()
  322. {
  323. var cell = new mxCell();
  324. cell.insert(new mxCell());
  325. return cell;
  326. };
  327. /**
  328. * Function: getCells
  329. *
  330. * Returns the cells in this model.
  331. */
  332. mxGraphModel.prototype.getCells = function()
  333. {
  334. var result = [];
  335. if (this.cells != null)
  336. {
  337. for (var key in this.cells)
  338. {
  339. result.push(this.cells[key]);
  340. }
  341. }
  342. return result;
  343. };
  344. /**
  345. * Function: getCellCount
  346. *
  347. * Returns the number of cells in the model.
  348. */
  349. mxGraphModel.prototype.getCellCount = function()
  350. {
  351. var count = 0;
  352. if (this.cells != null)
  353. {
  354. for (var key in this.cells)
  355. {
  356. count++;
  357. }
  358. }
  359. return count;
  360. };
  361. /**
  362. * Function: getCell
  363. *
  364. * Returns the <mxCell> for the specified Id or null if no cell can be
  365. * found for the given Id.
  366. *
  367. * Parameters:
  368. *
  369. * id - A string representing the Id of the cell.
  370. */
  371. mxGraphModel.prototype.getCell = function(id)
  372. {
  373. return (this.cells != null) ? this.cells[id] : null;
  374. };
  375. /**
  376. * Function: filterCells
  377. *
  378. * Returns the cells from the given array where the given filter function
  379. * returns true.
  380. */
  381. mxGraphModel.prototype.filterCells = function(cells, filter)
  382. {
  383. var result = null;
  384. if (cells != null)
  385. {
  386. result = [];
  387. for (var i = 0; i < cells.length; i++)
  388. {
  389. if (filter(cells[i]))
  390. {
  391. result.push(cells[i]);
  392. }
  393. }
  394. }
  395. return result;
  396. };
  397. /**
  398. * Function: getDescendants
  399. *
  400. * Returns all descendants of the given cell and the cell itself in an array.
  401. *
  402. * Parameters:
  403. *
  404. * parent - <mxCell> whose descendants should be returned.
  405. */
  406. mxGraphModel.prototype.getDescendants = function(parent)
  407. {
  408. return this.filterDescendants(null, parent);
  409. };
  410. /**
  411. * Function: filterDescendants
  412. *
  413. * Visits all cells recursively and applies the specified filter function
  414. * to each cell. If the function returns true then the cell is added
  415. * to the resulting array. The parent and result paramters are optional.
  416. * If parent is not specified then the recursion starts at <root>.
  417. *
  418. * Example:
  419. * The following example extracts all vertices from a given model:
  420. * (code)
  421. * var filter = function(cell)
  422. * {
  423. * return model.isVertex(cell);
  424. * }
  425. * var vertices = model.filterDescendants(filter);
  426. * (end)
  427. *
  428. * Parameters:
  429. *
  430. * filter - JavaScript function that takes an <mxCell> as an argument
  431. * and returns a boolean.
  432. * parent - Optional <mxCell> that is used as the root of the recursion.
  433. */
  434. mxGraphModel.prototype.filterDescendants = function(filter, parent)
  435. {
  436. // Creates a new array for storing the result
  437. var result = [];
  438. // Recursion starts at the root of the model
  439. parent = parent || this.getRoot();
  440. // Checks if the filter returns true for the cell
  441. // and adds it to the result array
  442. if (filter == null || filter(parent))
  443. {
  444. result.push(parent);
  445. }
  446. // Visits the children of the cell
  447. var childCount = this.getChildCount(parent);
  448. for (var i = 0; i < childCount; i++)
  449. {
  450. var child = this.getChildAt(parent, i);
  451. result = result.concat(this.filterDescendants(filter, child));
  452. }
  453. return result;
  454. };
  455. /**
  456. * Function: getRoot
  457. *
  458. * Returns the root of the model or the topmost parent of the given cell.
  459. *
  460. * Parameters:
  461. *
  462. * cell - Optional <mxCell> that specifies the child.
  463. */
  464. mxGraphModel.prototype.getRoot = function(cell)
  465. {
  466. var root = cell || this.root;
  467. if (cell != null)
  468. {
  469. while (cell != null)
  470. {
  471. root = cell;
  472. cell = this.getParent(cell);
  473. }
  474. }
  475. return root;
  476. };
  477. /**
  478. * Function: setRoot
  479. *
  480. * Sets the <root> of the model using <mxRootChange> and adds the change to
  481. * the current transaction. This resets all datastructures in the model and
  482. * is the preferred way of clearing an existing model. Returns the new
  483. * root.
  484. *
  485. * Example:
  486. *
  487. * (code)
  488. * var root = new mxCell();
  489. * root.insert(new mxCell());
  490. * model.setRoot(root);
  491. * (end)
  492. *
  493. * Parameters:
  494. *
  495. * root - <mxCell> that specifies the new root.
  496. */
  497. mxGraphModel.prototype.setRoot = function(root)
  498. {
  499. this.execute(new mxRootChange(this, root));
  500. return root;
  501. };
  502. /**
  503. * Function: rootChanged
  504. *
  505. * Inner callback to change the root of the model and update the internal
  506. * datastructures, such as <cells> and <nextId>. Returns the previous root.
  507. *
  508. * Parameters:
  509. *
  510. * root - <mxCell> that specifies the new root.
  511. */
  512. mxGraphModel.prototype.rootChanged = function(root)
  513. {
  514. var oldRoot = this.root;
  515. this.root = root;
  516. // Resets counters and datastructures
  517. this.nextId = 0;
  518. this.cells = null;
  519. this.cellAdded(root);
  520. return oldRoot;
  521. };
  522. /**
  523. * Function: isRoot
  524. *
  525. * Returns true if the given cell is the root of the model and a non-null
  526. * value.
  527. *
  528. * Parameters:
  529. *
  530. * cell - <mxCell> that represents the possible root.
  531. */
  532. mxGraphModel.prototype.isRoot = function(cell)
  533. {
  534. return cell != null && this.root == cell;
  535. };
  536. /**
  537. * Function: isLayer
  538. *
  539. * Returns true if <isRoot> returns true for the parent of the given cell.
  540. *
  541. * Parameters:
  542. *
  543. * cell - <mxCell> that represents the possible layer.
  544. */
  545. mxGraphModel.prototype.isLayer = function(cell)
  546. {
  547. return this.isRoot(this.getParent(cell));
  548. };
  549. /**
  550. * Function: isAncestor
  551. *
  552. * Returns true if the given parent is an ancestor of the given child. Note
  553. * returns true if child == parent.
  554. *
  555. * Parameters:
  556. *
  557. * parent - <mxCell> that specifies the parent.
  558. * child - <mxCell> that specifies the child.
  559. */
  560. mxGraphModel.prototype.isAncestor = function(parent, child)
  561. {
  562. while (child != null && child != parent)
  563. {
  564. child = this.getParent(child);
  565. }
  566. return child == parent;
  567. };
  568. /**
  569. * Function: contains
  570. *
  571. * Returns true if the model contains the given <mxCell>.
  572. *
  573. * Parameters:
  574. *
  575. * cell - <mxCell> that specifies the cell.
  576. */
  577. mxGraphModel.prototype.contains = function(cell)
  578. {
  579. return this.isAncestor(this.root, cell);
  580. };
  581. /**
  582. * Function: getParent
  583. *
  584. * Returns the parent of the given cell.
  585. *
  586. * Parameters:
  587. *
  588. * cell - <mxCell> whose parent should be returned.
  589. */
  590. mxGraphModel.prototype.getParent = function(cell)
  591. {
  592. return (cell != null) ? cell.getParent() : null;
  593. };
  594. /**
  595. * Function: add
  596. *
  597. * Adds the specified child to the parent at the given index using
  598. * <mxChildChange> and adds the change to the current transaction. If no
  599. * index is specified then the child is appended to the parent's array of
  600. * children. Returns the inserted child.
  601. *
  602. * Parameters:
  603. *
  604. * parent - <mxCell> that specifies the parent to contain the child.
  605. * child - <mxCell> that specifies the child to be inserted.
  606. * index - Optional integer that specifies the index of the child.
  607. */
  608. mxGraphModel.prototype.add = function(parent, child, index)
  609. {
  610. if (child != parent && parent != null && child != null)
  611. {
  612. // Appends the child if no index was specified
  613. if (index == null)
  614. {
  615. index = this.getChildCount(parent);
  616. }
  617. var parentChanged = parent != this.getParent(child);
  618. this.execute(new mxChildChange(this, parent, child, index));
  619. // Maintains the edges parents by moving the edges
  620. // into the nearest common ancestor of its terminals
  621. if (this.maintainEdgeParent && parentChanged)
  622. {
  623. this.updateEdgeParents(child);
  624. }
  625. }
  626. return child;
  627. };
  628. /**
  629. * Function: cellAdded
  630. *
  631. * Inner callback to update <cells> when a cell has been added. This
  632. * implementation resolves collisions by creating new Ids. To change the
  633. * ID of a cell after it was inserted into the model, use the following
  634. * code:
  635. *
  636. * (code
  637. * delete model.cells[cell.getId()];
  638. * cell.setId(newId);
  639. * model.cells[cell.getId()] = cell;
  640. * (end)
  641. *
  642. * If the change of the ID should be part of the command history, then the
  643. * cell should be removed from the model and a clone with the new ID should
  644. * be reinserted into the model instead.
  645. *
  646. * Parameters:
  647. *
  648. * cell - <mxCell> that specifies the cell that has been added.
  649. */
  650. mxGraphModel.prototype.cellAdded = function(cell)
  651. {
  652. if (cell != null)
  653. {
  654. // Creates an Id for the cell if not Id exists
  655. if (cell.getId() == null && this.createIds)
  656. {
  657. cell.setId(this.createId(cell));
  658. }
  659. if (cell.getId() != null)
  660. {
  661. var collision = this.getCell(cell.getId());
  662. if (collision != cell)
  663. {
  664. // Creates new Id for the cell
  665. // as long as there is a collision
  666. while (collision != null)
  667. {
  668. cell.setId(this.createId(cell));
  669. collision = this.getCell(cell.getId());
  670. }
  671. // Lazily creates the cells dictionary
  672. if (this.cells == null)
  673. {
  674. this.cells = new Object();
  675. }
  676. this.cells[cell.getId()] = cell;
  677. }
  678. }
  679. // Makes sure IDs of deleted cells are not reused
  680. if (mxUtils.isNumeric(cell.getId()))
  681. {
  682. this.nextId = Math.max(this.nextId, cell.getId());
  683. }
  684. // Recursively processes child cells
  685. var childCount = this.getChildCount(cell);
  686. for (var i=0; i<childCount; i++)
  687. {
  688. this.cellAdded(this.getChildAt(cell, i));
  689. }
  690. }
  691. };
  692. /**
  693. * Function: createId
  694. *
  695. * Hook method to create an Id for the specified cell. This implementation
  696. * concatenates <prefix>, id and <postfix> to create the Id and increments
  697. * <nextId>. The cell is ignored by this implementation, but can be used in
  698. * overridden methods to prefix the Ids with eg. the cell type.
  699. *
  700. * Parameters:
  701. *
  702. * cell - <mxCell> to create the Id for.
  703. */
  704. mxGraphModel.prototype.createId = function(cell)
  705. {
  706. var id = this.nextId;
  707. this.nextId++;
  708. return this.prefix + id + this.postfix;
  709. };
  710. /**
  711. * Function: updateEdgeParents
  712. *
  713. * Updates the parent for all edges that are connected to cell or one of
  714. * its descendants using <updateEdgeParent>.
  715. */
  716. mxGraphModel.prototype.updateEdgeParents = function(cell, root)
  717. {
  718. // Gets the topmost node of the hierarchy
  719. root = root || this.getRoot(cell);
  720. // Updates edges on children first
  721. var childCount = this.getChildCount(cell);
  722. for (var i = 0; i < childCount; i++)
  723. {
  724. var child = this.getChildAt(cell, i);
  725. this.updateEdgeParents(child, root);
  726. }
  727. // Updates the parents of all connected edges
  728. var edgeCount = this.getEdgeCount(cell);
  729. var edges = [];
  730. for (var i = 0; i < edgeCount; i++)
  731. {
  732. edges.push(this.getEdgeAt(cell, i));
  733. }
  734. for (var i = 0; i < edges.length; i++)
  735. {
  736. var edge = edges[i];
  737. // Updates edge parent if edge and child have
  738. // a common root node (does not need to be the
  739. // model root node)
  740. if (this.isAncestor(root, edge))
  741. {
  742. this.updateEdgeParent(edge, root);
  743. }
  744. }
  745. };
  746. /**
  747. * Function: updateEdgeParent
  748. *
  749. * Inner callback to update the parent of the specified <mxCell> to the
  750. * nearest-common-ancestor of its two terminals.
  751. *
  752. * Parameters:
  753. *
  754. * edge - <mxCell> that specifies the edge.
  755. * root - <mxCell> that represents the current root of the model.
  756. */
  757. mxGraphModel.prototype.updateEdgeParent = function(edge, root)
  758. {
  759. var source = this.getTerminal(edge, true);
  760. var target = this.getTerminal(edge, false);
  761. var cell = null;
  762. // Uses the first non-relative descendants of the source terminal
  763. while (source != null && !this.isEdge(source) &&
  764. source.geometry != null && source.geometry.relative)
  765. {
  766. source = this.getParent(source);
  767. }
  768. // Uses the first non-relative descendants of the target terminal
  769. while (target != null && this.ignoreRelativeEdgeParent &&
  770. !this.isEdge(target) && target.geometry != null &&
  771. target.geometry.relative)
  772. {
  773. target = this.getParent(target);
  774. }
  775. if (this.isAncestor(root, source) && this.isAncestor(root, target))
  776. {
  777. if (source == target)
  778. {
  779. cell = this.getParent(source);
  780. }
  781. else
  782. {
  783. cell = this.getNearestCommonAncestor(source, target);
  784. }
  785. if (cell != null && (this.getParent(cell) != this.root ||
  786. this.isAncestor(cell, edge)) && this.getParent(edge) != cell)
  787. {
  788. var geo = this.getGeometry(edge);
  789. if (geo != null)
  790. {
  791. var origin1 = this.getOrigin(this.getParent(edge));
  792. var origin2 = this.getOrigin(cell);
  793. var dx = origin2.x - origin1.x;
  794. var dy = origin2.y - origin1.y;
  795. geo = geo.clone();
  796. geo.translate(-dx, -dy);
  797. this.setGeometry(edge, geo);
  798. }
  799. this.add(cell, edge, this.getChildCount(cell));
  800. }
  801. }
  802. };
  803. /**
  804. * Function: getOrigin
  805. *
  806. * Returns the absolute, accumulated origin for the children inside the
  807. * given parent as an <mxPoint>.
  808. */
  809. mxGraphModel.prototype.getOrigin = function(cell)
  810. {
  811. var result = null;
  812. if (cell != null)
  813. {
  814. result = this.getOrigin(this.getParent(cell));
  815. if (!this.isEdge(cell))
  816. {
  817. var geo = this.getGeometry(cell);
  818. if (geo != null)
  819. {
  820. result.x += geo.x;
  821. result.y += geo.y;
  822. }
  823. }
  824. }
  825. else
  826. {
  827. result = new mxPoint();
  828. }
  829. return result;
  830. };
  831. /**
  832. * Function: getNearestCommonAncestor
  833. *
  834. * Returns the nearest common ancestor for the specified cells.
  835. *
  836. * Parameters:
  837. *
  838. * cell1 - <mxCell> that specifies the first cell in the tree.
  839. * cell2 - <mxCell> that specifies the second cell in the tree.
  840. */
  841. mxGraphModel.prototype.getNearestCommonAncestor = function(cell1, cell2)
  842. {
  843. if (cell1 != null && cell2 != null)
  844. {
  845. // Creates the cell path for the second cell
  846. var path = mxCellPath.create(cell2);
  847. if (path != null && path.length > 0)
  848. {
  849. // Bubbles through the ancestors of the first
  850. // cell to find the nearest common ancestor.
  851. var cell = cell1;
  852. var current = mxCellPath.create(cell);
  853. // Inverts arguments
  854. if (path.length < current.length)
  855. {
  856. cell = cell2;
  857. var tmp = current;
  858. current = path;
  859. path = tmp;
  860. }
  861. while (cell != null)
  862. {
  863. var parent = this.getParent(cell);
  864. // Checks if the cell path is equal to the beginning of the given cell path
  865. if (path.indexOf(current + mxCellPath.PATH_SEPARATOR) == 0 && parent != null)
  866. {
  867. return cell;
  868. }
  869. current = mxCellPath.getParentPath(current);
  870. cell = parent;
  871. }
  872. }
  873. }
  874. return null;
  875. };
  876. /**
  877. * Function: remove
  878. *
  879. * Removes the specified cell from the model using <mxChildChange> and adds
  880. * the change to the current transaction. This operation will remove the
  881. * cell and all of its children from the model. Returns the removed cell.
  882. *
  883. * Parameters:
  884. *
  885. * cell - <mxCell> that should be removed.
  886. */
  887. mxGraphModel.prototype.remove = function(cell)
  888. {
  889. if (cell == this.root)
  890. {
  891. this.setRoot(null);
  892. }
  893. else if (this.getParent(cell) != null)
  894. {
  895. this.execute(new mxChildChange(this, null, cell));
  896. }
  897. return cell;
  898. };
  899. /**
  900. * Function: cellRemoved
  901. *
  902. * Inner callback to update <cells> when a cell has been removed.
  903. *
  904. * Parameters:
  905. *
  906. * cell - <mxCell> that specifies the cell that has been removed.
  907. */
  908. mxGraphModel.prototype.cellRemoved = function(cell)
  909. {
  910. if (cell != null && this.cells != null)
  911. {
  912. // Recursively processes child cells
  913. var childCount = this.getChildCount(cell);
  914. for (var i = childCount - 1; i >= 0; i--)
  915. {
  916. this.cellRemoved(this.getChildAt(cell, i));
  917. }
  918. // Removes the dictionary entry for the cell
  919. if (this.cells != null && cell.getId() != null)
  920. {
  921. delete this.cells[cell.getId()];
  922. }
  923. }
  924. };
  925. /**
  926. * Function: parentForCellChanged
  927. *
  928. * Inner callback to update the parent of a cell using <mxCell.insert>
  929. * on the parent and return the previous parent.
  930. *
  931. * Parameters:
  932. *
  933. * cell - <mxCell> to update the parent for.
  934. * parent - <mxCell> that specifies the new parent of the cell.
  935. * index - Optional integer that defines the index of the child
  936. * in the parent's child array.
  937. */
  938. mxGraphModel.prototype.parentForCellChanged = function(cell, parent, index)
  939. {
  940. var previous = this.getParent(cell);
  941. if (parent != null)
  942. {
  943. if (parent != previous || previous.getIndex(cell) != index)
  944. {
  945. parent.insert(cell, index);
  946. }
  947. }
  948. else if (previous != null)
  949. {
  950. var oldIndex = previous.getIndex(cell);
  951. previous.remove(oldIndex);
  952. }
  953. // Adds or removes the cell from the model
  954. var par = this.contains(parent);
  955. var pre = this.contains(previous);
  956. if (par && !pre)
  957. {
  958. this.cellAdded(cell);
  959. }
  960. else if (pre && !par)
  961. {
  962. this.cellRemoved(cell);
  963. }
  964. return previous;
  965. };
  966. /**
  967. * Function: getChildCount
  968. *
  969. * Returns the number of children in the given cell.
  970. *
  971. * Parameters:
  972. *
  973. * cell - <mxCell> whose number of children should be returned.
  974. */
  975. mxGraphModel.prototype.getChildCount = function(cell)
  976. {
  977. return (cell != null) ? cell.getChildCount() : 0;
  978. };
  979. /**
  980. * Function: getChildAt
  981. *
  982. * Returns the child of the given <mxCell> at the given index.
  983. *
  984. * Parameters:
  985. *
  986. * cell - <mxCell> that represents the parent.
  987. * index - Integer that specifies the index of the child to be returned.
  988. */
  989. mxGraphModel.prototype.getChildAt = function(cell, index)
  990. {
  991. return (cell != null) ? cell.getChildAt(index) : null;
  992. };
  993. /**
  994. * Function: getChildren
  995. *
  996. * Returns all children of the given <mxCell> as an array of <mxCells>. The
  997. * return value should be only be read.
  998. *
  999. * Parameters:
  1000. *
  1001. * cell - <mxCell> the represents the parent.
  1002. */
  1003. mxGraphModel.prototype.getChildren = function(cell)
  1004. {
  1005. return (cell != null) ? cell.children : null;
  1006. };
  1007. /**
  1008. * Function: getChildVertices
  1009. *
  1010. * Returns the child vertices of the given parent.
  1011. *
  1012. * Parameters:
  1013. *
  1014. * cell - <mxCell> whose child vertices should be returned.
  1015. */
  1016. mxGraphModel.prototype.getChildVertices = function(parent)
  1017. {
  1018. return this.getChildCells(parent, true, false);
  1019. };
  1020. /**
  1021. * Function: getChildEdges
  1022. *
  1023. * Returns the child edges of the given parent.
  1024. *
  1025. * Parameters:
  1026. *
  1027. * cell - <mxCell> whose child edges should be returned.
  1028. */
  1029. mxGraphModel.prototype.getChildEdges = function(parent)
  1030. {
  1031. return this.getChildCells(parent, false, true);
  1032. };
  1033. /**
  1034. * Function: getChildCells
  1035. *
  1036. * Returns the children of the given cell that are vertices and/or edges
  1037. * depending on the arguments.
  1038. *
  1039. * Parameters:
  1040. *
  1041. * cell - <mxCell> the represents the parent.
  1042. * vertices - Boolean indicating if child vertices should be returned.
  1043. * Default is false.
  1044. * edges - Boolean indicating if child edges should be returned.
  1045. * Default is false.
  1046. */
  1047. mxGraphModel.prototype.getChildCells = function(parent, vertices, edges)
  1048. {
  1049. vertices = (vertices != null) ? vertices : false;
  1050. edges = (edges != null) ? edges : false;
  1051. var childCount = this.getChildCount(parent);
  1052. var result = [];
  1053. for (var i = 0; i < childCount; i++)
  1054. {
  1055. var child = this.getChildAt(parent, i);
  1056. if ((!edges && !vertices) || (edges && this.isEdge(child)) ||
  1057. (vertices && this.isVertex(child)))
  1058. {
  1059. result.push(child);
  1060. }
  1061. }
  1062. return result;
  1063. };
  1064. /**
  1065. * Function: getTerminal
  1066. *
  1067. * Returns the source or target <mxCell> of the given edge depending on the
  1068. * value of the boolean parameter.
  1069. *
  1070. * Parameters:
  1071. *
  1072. * edge - <mxCell> that specifies the edge.
  1073. * isSource - Boolean indicating which end of the edge should be returned.
  1074. */
  1075. mxGraphModel.prototype.getTerminal = function(edge, isSource)
  1076. {
  1077. return (edge != null) ? edge.getTerminal(isSource) : null;
  1078. };
  1079. /**
  1080. * Function: setTerminal
  1081. *
  1082. * Sets the source or target terminal of the given <mxCell> using
  1083. * <mxTerminalChange> and adds the change to the current transaction.
  1084. * This implementation updates the parent of the edge using <updateEdgeParent>
  1085. * if required.
  1086. *
  1087. * Parameters:
  1088. *
  1089. * edge - <mxCell> that specifies the edge.
  1090. * terminal - <mxCell> that specifies the new terminal.
  1091. * isSource - Boolean indicating if the terminal is the new source or
  1092. * target terminal of the edge.
  1093. */
  1094. mxGraphModel.prototype.setTerminal = function(edge, terminal, isSource)
  1095. {
  1096. var terminalChanged = terminal != this.getTerminal(edge, isSource);
  1097. this.execute(new mxTerminalChange(this, edge, terminal, isSource));
  1098. if (this.maintainEdgeParent && terminalChanged)
  1099. {
  1100. this.updateEdgeParent(edge, this.getRoot());
  1101. }
  1102. return terminal;
  1103. };
  1104. /**
  1105. * Function: setTerminals
  1106. *
  1107. * Sets the source and target <mxCell> of the given <mxCell> in a single
  1108. * transaction using <setTerminal> for each end of the edge.
  1109. *
  1110. * Parameters:
  1111. *
  1112. * edge - <mxCell> that specifies the edge.
  1113. * source - <mxCell> that specifies the new source terminal.
  1114. * target - <mxCell> that specifies the new target terminal.
  1115. */
  1116. mxGraphModel.prototype.setTerminals = function(edge, source, target)
  1117. {
  1118. this.beginUpdate();
  1119. try
  1120. {
  1121. this.setTerminal(edge, source, true);
  1122. this.setTerminal(edge, target, false);
  1123. }
  1124. finally
  1125. {
  1126. this.endUpdate();
  1127. }
  1128. };
  1129. /**
  1130. * Function: terminalForCellChanged
  1131. *
  1132. * Inner helper function to update the terminal of the edge using
  1133. * <mxCell.insertEdge> and return the previous terminal.
  1134. *
  1135. * Parameters:
  1136. *
  1137. * edge - <mxCell> that specifies the edge to be updated.
  1138. * terminal - <mxCell> that specifies the new terminal.
  1139. * isSource - Boolean indicating if the terminal is the new source or
  1140. * target terminal of the edge.
  1141. */
  1142. mxGraphModel.prototype.terminalForCellChanged = function(edge, terminal, isSource)
  1143. {
  1144. var previous = this.getTerminal(edge, isSource);
  1145. if (terminal != null)
  1146. {
  1147. terminal.insertEdge(edge, isSource);
  1148. }
  1149. else if (previous != null)
  1150. {
  1151. previous.removeEdge(edge, isSource);
  1152. }
  1153. return previous;
  1154. };
  1155. /**
  1156. * Function: getEdgeCount
  1157. *
  1158. * Returns the number of distinct edges connected to the given cell.
  1159. *
  1160. * Parameters:
  1161. *
  1162. * cell - <mxCell> that represents the vertex.
  1163. */
  1164. mxGraphModel.prototype.getEdgeCount = function(cell)
  1165. {
  1166. return (cell != null) ? cell.getEdgeCount() : 0;
  1167. };
  1168. /**
  1169. * Function: getEdgeAt
  1170. *
  1171. * Returns the edge of cell at the given index.
  1172. *
  1173. * Parameters:
  1174. *
  1175. * cell - <mxCell> that specifies the vertex.
  1176. * index - Integer that specifies the index of the edge
  1177. * to return.
  1178. */
  1179. mxGraphModel.prototype.getEdgeAt = function(cell, index)
  1180. {
  1181. return (cell != null) ? cell.getEdgeAt(index) : null;
  1182. };
  1183. /**
  1184. * Function: getDirectedEdgeCount
  1185. *
  1186. * Returns the number of incoming or outgoing edges, ignoring the given
  1187. * edge.
  1188. *
  1189. * Parameters:
  1190. *
  1191. * cell - <mxCell> whose edge count should be returned.
  1192. * outgoing - Boolean that specifies if the number of outgoing or
  1193. * incoming edges should be returned.
  1194. * ignoredEdge - <mxCell> that represents an edge to be ignored.
  1195. */
  1196. mxGraphModel.prototype.getDirectedEdgeCount = function(cell, outgoing, ignoredEdge)
  1197. {
  1198. var count = 0;
  1199. var edgeCount = this.getEdgeCount(cell);
  1200. for (var i = 0; i < edgeCount; i++)
  1201. {
  1202. var edge = this.getEdgeAt(cell, i);
  1203. if (edge != ignoredEdge && this.getTerminal(edge, outgoing) == cell)
  1204. {
  1205. count++;
  1206. }
  1207. }
  1208. return count;
  1209. };
  1210. /**
  1211. * Function: getConnections
  1212. *
  1213. * Returns all edges of the given cell without loops.
  1214. *
  1215. * Parameters:
  1216. *
  1217. * cell - <mxCell> whose edges should be returned.
  1218. *
  1219. */
  1220. mxGraphModel.prototype.getConnections = function(cell)
  1221. {
  1222. return this.getEdges(cell, true, true, false);
  1223. };
  1224. /**
  1225. * Function: getIncomingEdges
  1226. *
  1227. * Returns the incoming edges of the given cell without loops.
  1228. *
  1229. * Parameters:
  1230. *
  1231. * cell - <mxCell> whose incoming edges should be returned.
  1232. *
  1233. */
  1234. mxGraphModel.prototype.getIncomingEdges = function(cell)
  1235. {
  1236. return this.getEdges(cell, true, false, false);
  1237. };
  1238. /**
  1239. * Function: getOutgoingEdges
  1240. *
  1241. * Returns the outgoing edges of the given cell without loops.
  1242. *
  1243. * Parameters:
  1244. *
  1245. * cell - <mxCell> whose outgoing edges should be returned.
  1246. *
  1247. */
  1248. mxGraphModel.prototype.getOutgoingEdges = function(cell)
  1249. {
  1250. return this.getEdges(cell, false, true, false);
  1251. };
  1252. /**
  1253. * Function: getEdges
  1254. *
  1255. * Returns all distinct edges connected to this cell as a new array of
  1256. * <mxCells>. If at least one of incoming or outgoing is true, then loops
  1257. * are ignored, otherwise if both are false, then all edges connected to
  1258. * the given cell are returned including loops.
  1259. *
  1260. * Parameters:
  1261. *
  1262. * cell - <mxCell> that specifies the cell.
  1263. * incoming - Optional boolean that specifies if incoming edges should be
  1264. * returned. Default is true.
  1265. * outgoing - Optional boolean that specifies if outgoing edges should be
  1266. * returned. Default is true.
  1267. * includeLoops - Optional boolean that specifies if loops should be returned.
  1268. * Default is true.
  1269. */
  1270. mxGraphModel.prototype.getEdges = function(cell, incoming, outgoing, includeLoops)
  1271. {
  1272. incoming = (incoming != null) ? incoming : true;
  1273. outgoing = (outgoing != null) ? outgoing : true;
  1274. includeLoops = (includeLoops != null) ? includeLoops : true;
  1275. var edgeCount = this.getEdgeCount(cell);
  1276. var result = [];
  1277. for (var i = 0; i < edgeCount; i++)
  1278. {
  1279. var edge = this.getEdgeAt(cell, i);
  1280. var source = this.getTerminal(edge, true);
  1281. var target = this.getTerminal(edge, false);
  1282. if ((includeLoops && source == target) || ((source != target) && ((incoming && target == cell) ||
  1283. (outgoing && source == cell))))
  1284. {
  1285. result.push(edge);
  1286. }
  1287. }
  1288. return result;
  1289. };
  1290. /**
  1291. * Function: getEdgesBetween
  1292. *
  1293. * Returns all edges between the given source and target pair. If directed
  1294. * is true, then only edges from the source to the target are returned,
  1295. * otherwise, all edges between the two cells are returned.
  1296. *
  1297. * Parameters:
  1298. *
  1299. * source - <mxCell> that defines the source terminal of the edge to be
  1300. * returned.
  1301. * target - <mxCell> that defines the target terminal of the edge to be
  1302. * returned.
  1303. * directed - Optional boolean that specifies if the direction of the
  1304. * edge should be taken into account. Default is false.
  1305. */
  1306. mxGraphModel.prototype.getEdgesBetween = function(source, target, directed)
  1307. {
  1308. directed = (directed != null) ? directed : false;
  1309. var tmp1 = this.getEdgeCount(source);
  1310. var tmp2 = this.getEdgeCount(target);
  1311. // Assumes the source has less connected edges
  1312. var terminal = source;
  1313. var edgeCount = tmp1;
  1314. // Uses the smaller array of connected edges
  1315. // for searching the edge
  1316. if (tmp2 < tmp1)
  1317. {
  1318. edgeCount = tmp2;
  1319. terminal = target;
  1320. }
  1321. var result = [];
  1322. // Checks if the edge is connected to the correct
  1323. // cell and returns the first match
  1324. for (var i = 0; i < edgeCount; i++)
  1325. {
  1326. var edge = this.getEdgeAt(terminal, i);
  1327. var src = this.getTerminal(edge, true);
  1328. var trg = this.getTerminal(edge, false);
  1329. var directedMatch = (src == source) && (trg == target);
  1330. var oppositeMatch = (trg == source) && (src == target);
  1331. if (directedMatch || (!directed && oppositeMatch))
  1332. {
  1333. result.push(edge);
  1334. }
  1335. }
  1336. return result;
  1337. };
  1338. /**
  1339. * Function: getOpposites
  1340. *
  1341. * Returns all opposite vertices wrt terminal for the given edges, only
  1342. * returning sources and/or targets as specified. The result is returned
  1343. * as an array of <mxCells>.
  1344. *
  1345. * Parameters:
  1346. *
  1347. * edges - Array of <mxCells> that contain the edges to be examined.
  1348. * terminal - <mxCell> that specifies the known end of the edges.
  1349. * sources - Boolean that specifies if source terminals should be contained
  1350. * in the result. Default is true.
  1351. * targets - Boolean that specifies if target terminals should be contained
  1352. * in the result. Default is true.
  1353. */
  1354. mxGraphModel.prototype.getOpposites = function(edges, terminal, sources, targets)
  1355. {
  1356. sources = (sources != null) ? sources : true;
  1357. targets = (targets != null) ? targets : true;
  1358. var terminals = [];
  1359. if (edges != null)
  1360. {
  1361. for (var i = 0; i < edges.length; i++)
  1362. {
  1363. var source = this.getTerminal(edges[i], true);
  1364. var target = this.getTerminal(edges[i], false);
  1365. // Checks if the terminal is the source of
  1366. // the edge and if the target should be
  1367. // stored in the result
  1368. if (source == terminal && target != null && target != terminal && targets)
  1369. {
  1370. terminals.push(target);
  1371. }
  1372. // Checks if the terminal is the taget of
  1373. // the edge and if the source should be
  1374. // stored in the result
  1375. else if (target == terminal && source != null && source != terminal && sources)
  1376. {
  1377. terminals.push(source);
  1378. }
  1379. }
  1380. }
  1381. return terminals;
  1382. };
  1383. /**
  1384. * Function: getTopmostCells
  1385. *
  1386. * Returns the topmost cells of the hierarchy in an array that contains no
  1387. * descendants for each <mxCell> that it contains. Duplicates should be
  1388. * removed in the cells array to improve performance.
  1389. *
  1390. * Parameters:
  1391. *
  1392. * cells - Array of <mxCells> whose topmost ancestors should be returned.
  1393. */
  1394. mxGraphModel.prototype.getTopmostCells = function(cells)
  1395. {
  1396. var dict = new mxDictionary();
  1397. var tmp = [];
  1398. for (var i = 0; i < cells.length; i++)
  1399. {
  1400. dict.put(cells[i], true);
  1401. }
  1402. for (var i = 0; i < cells.length; i++)
  1403. {
  1404. var cell = cells[i];
  1405. var topmost = true;
  1406. var parent = this.getParent(cell);
  1407. while (parent != null)
  1408. {
  1409. if (dict.get(parent))
  1410. {
  1411. topmost = false;
  1412. break;
  1413. }
  1414. parent = this.getParent(parent);
  1415. }
  1416. if (topmost)
  1417. {
  1418. tmp.push(cell);
  1419. }
  1420. }
  1421. return tmp;
  1422. };
  1423. /**
  1424. * Function: isVertex
  1425. *
  1426. * Returns true if the given cell is a vertex.
  1427. *
  1428. * Parameters:
  1429. *
  1430. * cell - <mxCell> that represents the possible vertex.
  1431. */
  1432. mxGraphModel.prototype.isVertex = function(cell)
  1433. {
  1434. return (cell != null) ? cell.isVertex() : false;
  1435. };
  1436. /**
  1437. * Function: isEdge
  1438. *
  1439. * Returns true if the given cell is an edge.
  1440. *
  1441. * Parameters:
  1442. *
  1443. * cell - <mxCell> that represents the possible edge.
  1444. */
  1445. mxGraphModel.prototype.isEdge = function(cell)
  1446. {
  1447. return (cell != null) ? cell.isEdge() : false;
  1448. };
  1449. /**
  1450. * Function: isConnectable
  1451. *
  1452. * Returns true if the given <mxCell> is connectable. If <edgesConnectable>
  1453. * is false, then this function returns false for all edges else it returns
  1454. * the return value of <mxCell.isConnectable>.
  1455. *
  1456. * Parameters:
  1457. *
  1458. * cell - <mxCell> whose connectable state should be returned.
  1459. */
  1460. mxGraphModel.prototype.isConnectable = function(cell)
  1461. {
  1462. return (cell != null) ? cell.isConnectable() : false;
  1463. };
  1464. /**
  1465. * Function: getValue
  1466. *
  1467. * Returns the user object of the given <mxCell> using <mxCell.getValue>.
  1468. *
  1469. * Parameters:
  1470. *
  1471. * cell - <mxCell> whose user object should be returned.
  1472. */
  1473. mxGraphModel.prototype.getValue = function(cell)
  1474. {
  1475. return (cell != null) ? cell.getValue() : null;
  1476. };
  1477. /**
  1478. * Function: setValue
  1479. *
  1480. * Sets the user object of then given <mxCell> using <mxValueChange>
  1481. * and adds the change to the current transaction.
  1482. *
  1483. * Parameters:
  1484. *
  1485. * cell - <mxCell> whose user object should be changed.
  1486. * value - Object that defines the new user object.
  1487. */
  1488. mxGraphModel.prototype.setValue = function(cell, value)
  1489. {
  1490. this.execute(new mxValueChange(this, cell, value));
  1491. return value;
  1492. };
  1493. /**
  1494. * Function: valueForCellChanged
  1495. *
  1496. * Inner callback to update the user object of the given <mxCell>
  1497. * using <mxCell.valueChanged> and return the previous value,
  1498. * that is, the return value of <mxCell.valueChanged>.
  1499. *
  1500. * To change a specific attribute in an XML node, the following code can be
  1501. * used.
  1502. *
  1503. * (code)
  1504. * graph.getModel().valueForCellChanged = function(cell, value)
  1505. * {
  1506. * var previous = cell.value.getAttribute('label');
  1507. * cell.value.setAttribute('label', value);
  1508. *
  1509. * return previous;
  1510. * };
  1511. * (end)
  1512. */
  1513. mxGraphModel.prototype.valueForCellChanged = function(cell, value)
  1514. {
  1515. return cell.valueChanged(value);
  1516. };
  1517. /**
  1518. * Function: getGeometry
  1519. *
  1520. * Returns the <mxGeometry> of the given <mxCell>.
  1521. *
  1522. * Parameters:
  1523. *
  1524. * cell - <mxCell> whose geometry should be returned.
  1525. */
  1526. mxGraphModel.prototype.getGeometry = function(cell)
  1527. {
  1528. return (cell != null) ? cell.getGeometry() : null;
  1529. };
  1530. /**
  1531. * Function: setGeometry
  1532. *
  1533. * Sets the <mxGeometry> of the given <mxCell>. The actual update
  1534. * of the cell is carried out in <geometryForCellChanged>. The
  1535. * <mxGeometryChange> action is used to encapsulate the change.
  1536. *
  1537. * Parameters:
  1538. *
  1539. * cell - <mxCell> whose geometry should be changed.
  1540. * geometry - <mxGeometry> that defines the new geometry.
  1541. */
  1542. mxGraphModel.prototype.setGeometry = function(cell, geometry)
  1543. {
  1544. if (geometry != this.getGeometry(cell))
  1545. {
  1546. this.execute(new mxGeometryChange(this, cell, geometry));
  1547. }
  1548. return geometry;
  1549. };
  1550. /**
  1551. * Function: geometryForCellChanged
  1552. *
  1553. * Inner callback to update the <mxGeometry> of the given <mxCell> using
  1554. * <mxCell.setGeometry> and return the previous <mxGeometry>.
  1555. */
  1556. mxGraphModel.prototype.geometryForCellChanged = function(cell, geometry)
  1557. {
  1558. var previous = this.getGeometry(cell);
  1559. cell.setGeometry(geometry);
  1560. return previous;
  1561. };
  1562. /**
  1563. * Function: getStyle
  1564. *
  1565. * Returns the style of the given <mxCell>.
  1566. *
  1567. * Parameters:
  1568. *
  1569. * cell - <mxCell> whose style should be returned.
  1570. */
  1571. mxGraphModel.prototype.getStyle = function(cell)
  1572. {
  1573. return (cell != null) ? cell.getStyle() : null;
  1574. };
  1575. /**
  1576. * Function: setStyle
  1577. *
  1578. * Sets the style of the given <mxCell> using <mxStyleChange> and
  1579. * adds the change to the current transaction.
  1580. *
  1581. * Parameters:
  1582. *
  1583. * cell - <mxCell> whose style should be changed.
  1584. * style - String of the form [stylename;|key=value;] to specify
  1585. * the new cell style.
  1586. */
  1587. mxGraphModel.prototype.setStyle = function(cell, style)
  1588. {
  1589. if (style != this.getStyle(cell))
  1590. {
  1591. this.execute(new mxStyleChange(this, cell, style));
  1592. }
  1593. return style;
  1594. };
  1595. /**
  1596. * Function: styleForCellChanged
  1597. *
  1598. * Inner callback to update the style of the given <mxCell>
  1599. * using <mxCell.setStyle> and return the previous style.
  1600. *
  1601. * Parameters:
  1602. *
  1603. * cell - <mxCell> that specifies the cell to be updated.
  1604. * style - String of the form [stylename;|key=value;] to specify
  1605. * the new cell style.
  1606. */
  1607. mxGraphModel.prototype.styleForCellChanged = function(cell, style)
  1608. {
  1609. var previous = this.getStyle(cell);
  1610. cell.setStyle(style);
  1611. return previous;
  1612. };
  1613. /**
  1614. * Function: isCollapsed
  1615. *
  1616. * Returns true if the given <mxCell> is collapsed.
  1617. *
  1618. * Parameters:
  1619. *
  1620. * cell - <mxCell> whose collapsed state should be returned.
  1621. */
  1622. mxGraphModel.prototype.isCollapsed = function(cell)
  1623. {
  1624. return (cell != null) ? cell.isCollapsed() : false;
  1625. };
  1626. /**
  1627. * Function: setCollapsed
  1628. *
  1629. * Sets the collapsed state of the given <mxCell> using <mxCollapseChange>
  1630. * and adds the change to the current transaction.
  1631. *
  1632. * Parameters:
  1633. *
  1634. * cell - <mxCell> whose collapsed state should be changed.
  1635. * collapsed - Boolean that specifies the new collpased state.
  1636. */
  1637. mxGraphModel.prototype.setCollapsed = function(cell, collapsed)
  1638. {
  1639. if (collapsed != this.isCollapsed(cell))
  1640. {
  1641. this.execute(new mxCollapseChange(this, cell, collapsed));
  1642. }
  1643. return collapsed;
  1644. };
  1645. /**
  1646. * Function: collapsedStateForCellChanged
  1647. *
  1648. * Inner callback to update the collapsed state of the
  1649. * given <mxCell> using <mxCell.setCollapsed> and return
  1650. * the previous collapsed state.
  1651. *
  1652. * Parameters:
  1653. *
  1654. * cell - <mxCell> that specifies the cell to be updated.
  1655. * collapsed - Boolean that specifies the new collpased state.
  1656. */
  1657. mxGraphModel.prototype.collapsedStateForCellChanged = function(cell, collapsed)
  1658. {
  1659. var previous = this.isCollapsed(cell);
  1660. cell.setCollapsed(collapsed);
  1661. return previous;
  1662. };
  1663. /**
  1664. * Function: isVisible
  1665. *
  1666. * Returns true if the given <mxCell> is visible.
  1667. *
  1668. * Parameters:
  1669. *
  1670. * cell - <mxCell> whose visible state should be returned.
  1671. */
  1672. mxGraphModel.prototype.isVisible = function(cell)
  1673. {
  1674. return (cell != null) ? cell.isVisible() : false;
  1675. };
  1676. /**
  1677. * Function: setVisible
  1678. *
  1679. * Sets the visible state of the given <mxCell> using <mxVisibleChange> and
  1680. * adds the change to the current transaction.
  1681. *
  1682. * Parameters:
  1683. *
  1684. * cell - <mxCell> whose visible state should be changed.
  1685. * visible - Boolean that specifies the new visible state.
  1686. */
  1687. mxGraphModel.prototype.setVisible = function(cell, visible)
  1688. {
  1689. if (visible != this.isVisible(cell))
  1690. {
  1691. this.execute(new mxVisibleChange(this, cell, visible));
  1692. }
  1693. return visible;
  1694. };
  1695. /**
  1696. * Function: visibleStateForCellChanged
  1697. *
  1698. * Inner callback to update the visible state of the
  1699. * given <mxCell> using <mxCell.setCollapsed> and return
  1700. * the previous visible state.
  1701. *
  1702. * Parameters:
  1703. *
  1704. * cell - <mxCell> that specifies the cell to be updated.
  1705. * visible - Boolean that specifies the new visible state.
  1706. */
  1707. mxGraphModel.prototype.visibleStateForCellChanged = function(cell, visible)
  1708. {
  1709. var previous = this.isVisible(cell);
  1710. cell.setVisible(visible);
  1711. return previous;
  1712. };
  1713. /**
  1714. * Function: execute
  1715. *
  1716. * Executes the given edit and fires events if required. The edit object
  1717. * requires an execute function which is invoked. The edit is added to the
  1718. * <currentEdit> between <beginUpdate> and <endUpdate> calls, so that
  1719. * events will be fired if this execute is an individual transaction, that
  1720. * is, if no previous <beginUpdate> calls have been made without calling
  1721. * <endUpdate>. This implementation fires an <execute> event before
  1722. * executing the given change.
  1723. *
  1724. * Parameters:
  1725. *
  1726. * change - Object that described the change.
  1727. */
  1728. mxGraphModel.prototype.execute = function(change)
  1729. {
  1730. change.execute();
  1731. this.beginUpdate();
  1732. this.currentEdit.add(change);
  1733. this.fireEvent(new mxEventObject(mxEvent.EXECUTE, 'change', change));
  1734. // New global executed event
  1735. this.fireEvent(new mxEventObject(mxEvent.EXECUTED, 'change', change));
  1736. this.endUpdate();
  1737. };
  1738. /**
  1739. * Function: beginUpdate
  1740. *
  1741. * Increments the <updateLevel> by one. The event notification
  1742. * is queued until <updateLevel> reaches 0 by use of
  1743. * <endUpdate>.
  1744. *
  1745. * All changes on <mxGraphModel> are transactional,
  1746. * that is, they are executed in a single undoable change
  1747. * on the model (without transaction isolation).
  1748. * Therefore, if you want to combine any
  1749. * number of changes into a single undoable change,
  1750. * you should group any two or more API calls that
  1751. * modify the graph model between <beginUpdate>
  1752. * and <endUpdate> calls as shown here:
  1753. *
  1754. * (code)
  1755. * var model = graph.getModel();
  1756. * var parent = graph.getDefaultParent();
  1757. * var index = model.getChildCount(parent);
  1758. * model.beginUpdate();
  1759. * try
  1760. * {
  1761. * model.add(parent, v1, index);
  1762. * model.add(parent, v2, index+1);
  1763. * }
  1764. * finally
  1765. * {
  1766. * model.endUpdate();
  1767. * }
  1768. * (end)
  1769. *
  1770. * Of course there is a shortcut for appending a
  1771. * sequence of cells into the default parent:
  1772. *
  1773. * (code)
  1774. * graph.addCells([v1, v2]).
  1775. * (end)
  1776. */
  1777. mxGraphModel.prototype.beginUpdate = function()
  1778. {
  1779. this.updateLevel++;
  1780. this.fireEvent(new mxEventObject(mxEvent.BEGIN_UPDATE));
  1781. if (this.updateLevel == 1)
  1782. {
  1783. this.fireEvent(new mxEventObject(mxEvent.START_EDIT));
  1784. }
  1785. };
  1786. /**
  1787. * Function: endUpdate
  1788. *
  1789. * Decrements the <updateLevel> by one and fires an <undo>
  1790. * event if the <updateLevel> reaches 0. This function
  1791. * indirectly fires a <change> event by invoking the notify
  1792. * function on the <currentEdit> und then creates a new
  1793. * <currentEdit> using <createUndoableEdit>.
  1794. *
  1795. * The <undo> event is fired only once per edit, whereas
  1796. * the <change> event is fired whenever the notify
  1797. * function is invoked, that is, on undo and redo of
  1798. * the edit.
  1799. */
  1800. mxGraphModel.prototype.endUpdate = function()
  1801. {
  1802. this.updateLevel--;
  1803. if (this.updateLevel == 0)
  1804. {
  1805. this.fireEvent(new mxEventObject(mxEvent.END_EDIT));
  1806. }
  1807. if (!this.endingUpdate)
  1808. {
  1809. this.endingUpdate = this.updateLevel == 0;
  1810. this.fireEvent(new mxEventObject(mxEvent.END_UPDATE, 'edit', this.currentEdit));
  1811. try
  1812. {
  1813. if (this.endingUpdate && !this.currentEdit.isEmpty())
  1814. {
  1815. this.fireEvent(new mxEventObject(mxEvent.BEFORE_UNDO, 'edit', this.currentEdit));
  1816. var tmp = this.currentEdit;
  1817. this.currentEdit = this.createUndoableEdit();
  1818. tmp.notify();
  1819. this.fireEvent(new mxEventObject(mxEvent.UNDO, 'edit', tmp));
  1820. }
  1821. }
  1822. finally
  1823. {
  1824. this.endingUpdate = false;
  1825. }
  1826. }
  1827. };
  1828. /**
  1829. * Function: createUndoableEdit
  1830. *
  1831. * Creates a new <mxUndoableEdit> that implements the
  1832. * notify function to fire a <change> and <notify> event
  1833. * through the <mxUndoableEdit>'s source.
  1834. *
  1835. * Parameters:
  1836. *
  1837. * significant - Optional boolean that specifies if the edit to be created is
  1838. * significant. Default is true.
  1839. */
  1840. mxGraphModel.prototype.createUndoableEdit = function(significant)
  1841. {
  1842. var edit = new mxUndoableEdit(this, (significant != null) ? significant : true);
  1843. edit.notify = function()
  1844. {
  1845. // LATER: Remove changes property (deprecated)
  1846. edit.source.fireEvent(new mxEventObject(mxEvent.CHANGE,
  1847. 'edit', edit, 'changes', edit.changes));
  1848. edit.source.fireEvent(new mxEventObject(mxEvent.NOTIFY,
  1849. 'edit', edit, 'changes', edit.changes));
  1850. };
  1851. return edit;
  1852. };
  1853. /**
  1854. * Function: mergeChildren
  1855. *
  1856. * Merges the children of the given cell into the given target cell inside
  1857. * this model. All cells are cloned unless there is a corresponding cell in
  1858. * the model with the same id, in which case the source cell is ignored and
  1859. * all edges are connected to the corresponding cell in this model. Edges
  1860. * are considered to have no identity and are always cloned unless the
  1861. * cloneAllEdges flag is set to false, in which case edges with the same
  1862. * id in the target model are reconnected to reflect the terminals of the
  1863. * source edges.
  1864. */
  1865. mxGraphModel.prototype.mergeChildren = function(from, to, cloneAllEdges)
  1866. {
  1867. cloneAllEdges = (cloneAllEdges != null) ? cloneAllEdges : true;
  1868. this.beginUpdate();
  1869. try
  1870. {
  1871. var mapping = new Object();
  1872. this.mergeChildrenImpl(from, to, cloneAllEdges, mapping);
  1873. // Post-processes all edges in the mapping and
  1874. // reconnects the terminals to the corresponding
  1875. // cells in the target model
  1876. for (var key in mapping)
  1877. {
  1878. var cell = mapping[key];
  1879. var terminal = this.getTerminal(cell, true);
  1880. if (terminal != null)
  1881. {
  1882. terminal = mapping[mxCellPath.create(terminal)];
  1883. this.setTerminal(cell, terminal, true);
  1884. }
  1885. terminal = this.getTerminal(cell, false);
  1886. if (terminal != null)
  1887. {
  1888. terminal = mapping[mxCellPath.create(terminal)];
  1889. this.setTerminal(cell, terminal, false);
  1890. }
  1891. }
  1892. }
  1893. finally
  1894. {
  1895. this.endUpdate();
  1896. }
  1897. };
  1898. /**
  1899. * Function: mergeChildren
  1900. *
  1901. * Clones the children of the source cell into the given target cell in
  1902. * this model and adds an entry to the mapping that maps from the source
  1903. * cell to the target cell with the same id or the clone of the source cell
  1904. * that was inserted into this model.
  1905. */
  1906. mxGraphModel.prototype.mergeChildrenImpl = function(from, to, cloneAllEdges, mapping)
  1907. {
  1908. this.beginUpdate();
  1909. try
  1910. {
  1911. var childCount = from.getChildCount();
  1912. for (var i = 0; i < childCount; i++)
  1913. {
  1914. var cell = from.getChildAt(i);
  1915. if (typeof(cell.getId) == 'function')
  1916. {
  1917. var id = cell.getId();
  1918. var target = (id != null && (!this.isEdge(cell) || !cloneAllEdges)) ?
  1919. this.getCell(id) : null;
  1920. // Clones and adds the child if no cell exists for the id
  1921. if (target == null)
  1922. {
  1923. var clone = cell.clone();
  1924. clone.setId(id);
  1925. // Sets the terminals from the original cell to the clone
  1926. // because the lookup uses strings not cells in JS
  1927. clone.setTerminal(cell.getTerminal(true), true);
  1928. clone.setTerminal(cell.getTerminal(false), false);
  1929. // Do *NOT* use model.add as this will move the edge away
  1930. // from the parent in updateEdgeParent if maintainEdgeParent
  1931. // is enabled in the target model
  1932. target = to.insert(clone);
  1933. this.cellAdded(target);
  1934. }
  1935. // Stores the mapping for later reconnecting edges
  1936. mapping[mxCellPath.create(cell)] = target;
  1937. // Recurses
  1938. this.mergeChildrenImpl(cell, target, cloneAllEdges, mapping);
  1939. }
  1940. }
  1941. }
  1942. finally
  1943. {
  1944. this.endUpdate();
  1945. }
  1946. };
  1947. /**
  1948. * Function: getParents
  1949. *
  1950. * Returns an array that represents the set (no duplicates) of all parents
  1951. * for the given array of cells.
  1952. *
  1953. * Parameters:
  1954. *
  1955. * cells - Array of cells whose parents should be returned.
  1956. */
  1957. mxGraphModel.prototype.getParents = function(cells)
  1958. {
  1959. var parents = [];
  1960. if (cells != null)
  1961. {
  1962. var dict = new mxDictionary();
  1963. for (var i = 0; i < cells.length; i++)
  1964. {
  1965. var parent = this.getParent(cells[i]);
  1966. if (parent != null && !dict.get(parent))
  1967. {
  1968. dict.put(parent, true);
  1969. parents.push(parent);
  1970. }
  1971. }
  1972. }
  1973. return parents;
  1974. };
  1975. //
  1976. // Cell Cloning
  1977. //
  1978. /**
  1979. * Function: cloneCell
  1980. *
  1981. * Returns a deep clone of the given <mxCell> (including
  1982. * the children) which is created using <cloneCells>.
  1983. *
  1984. * Parameters:
  1985. *
  1986. * cell - <mxCell> to be cloned.
  1987. * includeChildren - Optional boolean indicating if the cells should be cloned
  1988. * with all descendants. Default is true.
  1989. * identical - Optional boolean to keep the identity of cloned cells.
  1990. * Default is false.
  1991. */
  1992. mxGraphModel.prototype.cloneCell = function(cell, includeChildren, identical)
  1993. {
  1994. if (cell != null)
  1995. {
  1996. return this.cloneCells([cell], includeChildren, null, identical)[0];
  1997. }
  1998. return null;
  1999. };
  2000. /**
  2001. * Function: cloneCells
  2002. *
  2003. * Returns an array of clones for the given array of <mxCells>.
  2004. * Depending on the value of includeChildren, a deep clone is created for
  2005. * each cell. Connections are restored based if the corresponding
  2006. * cell is contained in the passed in array.
  2007. *
  2008. * Parameters:
  2009. *
  2010. * cells - Array of <mxCell> to be cloned.
  2011. * includeChildren - Optional boolean indicating if the cells should be cloned
  2012. * with all descendants. Default is true.
  2013. * mapping - Optional mapping for existing clones.
  2014. * identical - Optional boolean to keep the cell IDs. Default is false.
  2015. */
  2016. mxGraphModel.prototype.cloneCells = function(cells, includeChildren, mapping, identical)
  2017. {
  2018. includeChildren = (includeChildren != null) ? includeChildren : true;
  2019. mapping = (mapping != null) ? mapping : new Object();
  2020. identical = (identical != null) ? identical : false;
  2021. var clones = [];
  2022. for (var i = 0; i < cells.length; i++)
  2023. {
  2024. if (cells[i] != null)
  2025. {
  2026. clones.push(this.cloneCellImpl(cells[i], mapping, includeChildren, identical));
  2027. }
  2028. else
  2029. {
  2030. clones.push(null);
  2031. }
  2032. }
  2033. for (var i = 0; i < clones.length; i++)
  2034. {
  2035. if (clones[i] != null)
  2036. {
  2037. this.restoreClone(clones[i], cells[i], mapping);
  2038. }
  2039. }
  2040. return clones;
  2041. };
  2042. /**
  2043. * Function: cloneCellImpl
  2044. *
  2045. * Inner helper method for cloning cells recursively.
  2046. */
  2047. mxGraphModel.prototype.cloneCellImpl = function(cell, mapping, includeChildren, identical)
  2048. {
  2049. var ident = mxObjectIdentity.get(cell);
  2050. var clone = mapping[ident];
  2051. if (clone == null)
  2052. {
  2053. clone = this.cellCloned(cell);
  2054. mapping[ident] = clone;
  2055. if (identical)
  2056. {
  2057. clone.id = cell.id;
  2058. }
  2059. if (includeChildren)
  2060. {
  2061. var childCount = this.getChildCount(cell);
  2062. for (var i = 0; i < childCount; i++)
  2063. {
  2064. var cloneChild = this.cloneCellImpl(
  2065. this.getChildAt(cell, i),
  2066. mapping, true, identical);
  2067. clone.insert(cloneChild);
  2068. }
  2069. }
  2070. }
  2071. return clone;
  2072. };
  2073. /**
  2074. * Function: cellCloned
  2075. *
  2076. * Hook for cloning the cell. This returns cell.clone() or
  2077. * any possible exceptions.
  2078. */
  2079. mxGraphModel.prototype.cellCloned = function(cell)
  2080. {
  2081. return cell.clone();
  2082. };
  2083. /**
  2084. * Function: restoreClone
  2085. *
  2086. * Inner helper method for restoring the connections in
  2087. * a network of cloned cells.
  2088. */
  2089. mxGraphModel.prototype.restoreClone = function(clone, cell, mapping)
  2090. {
  2091. var source = this.getTerminal(cell, true);
  2092. if (source != null)
  2093. {
  2094. var tmp = mapping[mxObjectIdentity.get(source)];
  2095. if (tmp != null)
  2096. {
  2097. tmp.insertEdge(clone, true);
  2098. }
  2099. }
  2100. var target = this.getTerminal(cell, false);
  2101. if (target != null)
  2102. {
  2103. var tmp = mapping[mxObjectIdentity.get(target)];
  2104. if (tmp != null)
  2105. {
  2106. tmp.insertEdge(clone, false);
  2107. }
  2108. }
  2109. var childCount = this.getChildCount(clone);
  2110. for (var i = 0; i < childCount; i++)
  2111. {
  2112. this.restoreClone(this.getChildAt(clone, i),
  2113. this.getChildAt(cell, i), mapping);
  2114. }
  2115. };
  2116. //
  2117. // Atomic changes
  2118. //
  2119. /**
  2120. * Class: mxRootChange
  2121. *
  2122. * Action to change the root in a model.
  2123. *
  2124. * Constructor: mxRootChange
  2125. *
  2126. * Constructs a change of the root in the
  2127. * specified model.
  2128. */
  2129. function mxRootChange(model, root)
  2130. {
  2131. this.model = model;
  2132. this.root = root;
  2133. this.previous = root;
  2134. };
  2135. /**
  2136. * Function: execute
  2137. *
  2138. * Carries out a change of the root using
  2139. * <mxGraphModel.rootChanged>.
  2140. */
  2141. mxRootChange.prototype.execute = function()
  2142. {
  2143. this.root = this.previous;
  2144. this.previous = this.model.rootChanged(this.previous);
  2145. };
  2146. /**
  2147. * Class: mxChildChange
  2148. *
  2149. * Action to add or remove a child in a model.
  2150. *
  2151. * Constructor: mxChildChange
  2152. *
  2153. * Constructs a change of a child in the
  2154. * specified model.
  2155. */
  2156. function mxChildChange(model, parent, child, index)
  2157. {
  2158. this.model = model;
  2159. this.parent = parent;
  2160. this.previous = parent;
  2161. this.child = child;
  2162. this.index = index;
  2163. this.previousIndex = index;
  2164. };
  2165. /**
  2166. * Function: execute
  2167. *
  2168. * Changes the parent of <child> using
  2169. * <mxGraphModel.parentForCellChanged> and
  2170. * removes or restores the cell's
  2171. * connections.
  2172. */
  2173. mxChildChange.prototype.execute = function()
  2174. {
  2175. if (this.child != null)
  2176. {
  2177. var tmp = this.model.getParent(this.child);
  2178. var tmp2 = (tmp != null) ? tmp.getIndex(this.child) : 0;
  2179. if (this.previous == null)
  2180. {
  2181. this.connect(this.child, false);
  2182. }
  2183. tmp = this.model.parentForCellChanged(
  2184. this.child, this.previous, this.previousIndex);
  2185. if (this.previous != null)
  2186. {
  2187. this.connect(this.child, true);
  2188. }
  2189. this.parent = this.previous;
  2190. this.previous = tmp;
  2191. this.index = this.previousIndex;
  2192. this.previousIndex = tmp2;
  2193. }
  2194. };
  2195. /**
  2196. * Function: disconnect
  2197. *
  2198. * Disconnects the given cell recursively from its
  2199. * terminals and stores the previous terminal in the
  2200. * cell's terminals.
  2201. */
  2202. mxChildChange.prototype.connect = function(cell, isConnect)
  2203. {
  2204. isConnect = (isConnect != null) ? isConnect : true;
  2205. var source = cell.getTerminal(true);
  2206. var target = cell.getTerminal(false);
  2207. if (source != null)
  2208. {
  2209. if (isConnect)
  2210. {
  2211. this.model.terminalForCellChanged(cell, source, true);
  2212. }
  2213. else
  2214. {
  2215. this.model.terminalForCellChanged(cell, null, true);
  2216. }
  2217. }
  2218. if (target != null)
  2219. {
  2220. if (isConnect)
  2221. {
  2222. this.model.terminalForCellChanged(cell, target, false);
  2223. }
  2224. else
  2225. {
  2226. this.model.terminalForCellChanged(cell, null, false);
  2227. }
  2228. }
  2229. cell.setTerminal(source, true);
  2230. cell.setTerminal(target, false);
  2231. var childCount = this.model.getChildCount(cell);
  2232. for (var i=0; i<childCount; i++)
  2233. {
  2234. this.connect(this.model.getChildAt(cell, i), isConnect);
  2235. }
  2236. };
  2237. /**
  2238. * Class: mxTerminalChange
  2239. *
  2240. * Action to change a terminal in a model.
  2241. *
  2242. * Constructor: mxTerminalChange
  2243. *
  2244. * Constructs a change of a terminal in the
  2245. * specified model.
  2246. */
  2247. function mxTerminalChange(model, cell, terminal, source)
  2248. {
  2249. this.model = model;
  2250. this.cell = cell;
  2251. this.terminal = terminal;
  2252. this.previous = terminal;
  2253. this.source = source;
  2254. };
  2255. /**
  2256. * Function: execute
  2257. *
  2258. * Changes the terminal of <cell> to <previous> using
  2259. * <mxGraphModel.terminalForCellChanged>.
  2260. */
  2261. mxTerminalChange.prototype.execute = function()
  2262. {
  2263. if (this.cell != null)
  2264. {
  2265. this.terminal = this.previous;
  2266. this.previous = this.model.terminalForCellChanged(
  2267. this.cell, this.previous, this.source);
  2268. }
  2269. };
  2270. /**
  2271. * Class: mxValueChange
  2272. *
  2273. * Action to change a user object in a model.
  2274. *
  2275. * Constructor: mxValueChange
  2276. *
  2277. * Constructs a change of a user object in the
  2278. * specified model.
  2279. */
  2280. function mxValueChange(model, cell, value)
  2281. {
  2282. this.model = model;
  2283. this.cell = cell;
  2284. this.value = value;
  2285. this.previous = value;
  2286. };
  2287. /**
  2288. * Function: execute
  2289. *
  2290. * Changes the value of <cell> to <previous> using
  2291. * <mxGraphModel.valueForCellChanged>.
  2292. */
  2293. mxValueChange.prototype.execute = function()
  2294. {
  2295. if (this.cell != null)
  2296. {
  2297. this.value = this.previous;
  2298. this.previous = this.model.valueForCellChanged(
  2299. this.cell, this.previous);
  2300. }
  2301. };
  2302. /**
  2303. * Class: mxStyleChange
  2304. *
  2305. * Action to change a cell's style in a model.
  2306. *
  2307. * Constructor: mxStyleChange
  2308. *
  2309. * Constructs a change of a style in the
  2310. * specified model.
  2311. */
  2312. function mxStyleChange(model, cell, style)
  2313. {
  2314. this.model = model;
  2315. this.cell = cell;
  2316. this.style = style;
  2317. this.previous = style;
  2318. };
  2319. /**
  2320. * Function: execute
  2321. *
  2322. * Changes the style of <cell> to <previous> using
  2323. * <mxGraphModel.styleForCellChanged>.
  2324. */
  2325. mxStyleChange.prototype.execute = function()
  2326. {
  2327. if (this.cell != null)
  2328. {
  2329. this.style = this.previous;
  2330. this.previous = this.model.styleForCellChanged(
  2331. this.cell, this.previous);
  2332. }
  2333. };
  2334. /**
  2335. * Class: mxGeometryChange
  2336. *
  2337. * Action to change a cell's geometry in a model.
  2338. *
  2339. * Constructor: mxGeometryChange
  2340. *
  2341. * Constructs a change of a geometry in the
  2342. * specified model.
  2343. */
  2344. function mxGeometryChange(model, cell, geometry)
  2345. {
  2346. this.model = model;
  2347. this.cell = cell;
  2348. this.geometry = geometry;
  2349. this.previous = geometry;
  2350. };
  2351. /**
  2352. * Function: execute
  2353. *
  2354. * Changes the geometry of <cell> ro <previous> using
  2355. * <mxGraphModel.geometryForCellChanged>.
  2356. */
  2357. mxGeometryChange.prototype.execute = function()
  2358. {
  2359. if (this.cell != null)
  2360. {
  2361. this.geometry = this.previous;
  2362. this.previous = this.model.geometryForCellChanged(
  2363. this.cell, this.previous);
  2364. }
  2365. };
  2366. /**
  2367. * Class: mxCollapseChange
  2368. *
  2369. * Action to change a cell's collapsed state in a model.
  2370. *
  2371. * Constructor: mxCollapseChange
  2372. *
  2373. * Constructs a change of a collapsed state in the
  2374. * specified model.
  2375. */
  2376. function mxCollapseChange(model, cell, collapsed)
  2377. {
  2378. this.model = model;
  2379. this.cell = cell;
  2380. this.collapsed = collapsed;
  2381. this.previous = collapsed;
  2382. };
  2383. /**
  2384. * Function: execute
  2385. *
  2386. * Changes the collapsed state of <cell> to <previous> using
  2387. * <mxGraphModel.collapsedStateForCellChanged>.
  2388. */
  2389. mxCollapseChange.prototype.execute = function()
  2390. {
  2391. if (this.cell != null)
  2392. {
  2393. this.collapsed = this.previous;
  2394. this.previous = this.model.collapsedStateForCellChanged(
  2395. this.cell, this.previous);
  2396. }
  2397. };
  2398. /**
  2399. * Class: mxVisibleChange
  2400. *
  2401. * Action to change a cell's visible state in a model.
  2402. *
  2403. * Constructor: mxVisibleChange
  2404. *
  2405. * Constructs a change of a visible state in the
  2406. * specified model.
  2407. */
  2408. function mxVisibleChange(model, cell, visible)
  2409. {
  2410. this.model = model;
  2411. this.cell = cell;
  2412. this.visible = visible;
  2413. this.previous = visible;
  2414. };
  2415. /**
  2416. * Function: execute
  2417. *
  2418. * Changes the visible state of <cell> to <previous> using
  2419. * <mxGraphModel.visibleStateForCellChanged>.
  2420. */
  2421. mxVisibleChange.prototype.execute = function()
  2422. {
  2423. if (this.cell != null)
  2424. {
  2425. this.visible = this.previous;
  2426. this.previous = this.model.visibleStateForCellChanged(
  2427. this.cell, this.previous);
  2428. }
  2429. };
  2430. /**
  2431. * Class: mxCellAttributeChange
  2432. *
  2433. * Action to change the attribute of a cell's user object.
  2434. * There is no method on the graph model that uses this
  2435. * action. To use the action, you can use the code shown
  2436. * in the example below.
  2437. *
  2438. * Example:
  2439. *
  2440. * To change the attributeName in the cell's user object
  2441. * to attributeValue, use the following code:
  2442. *
  2443. * (code)
  2444. * model.beginUpdate();
  2445. * try
  2446. * {
  2447. * var edit = new mxCellAttributeChange(
  2448. * cell, attributeName, attributeValue);
  2449. * model.execute(edit);
  2450. * }
  2451. * finally
  2452. * {
  2453. * model.endUpdate();
  2454. * }
  2455. * (end)
  2456. *
  2457. * Constructor: mxCellAttributeChange
  2458. *
  2459. * Constructs a change of a attribute of the DOM node
  2460. * stored as the value of the given <mxCell>.
  2461. */
  2462. function mxCellAttributeChange(cell, attribute, value)
  2463. {
  2464. this.cell = cell;
  2465. this.attribute = attribute;
  2466. this.value = value;
  2467. this.previous = value;
  2468. };
  2469. /**
  2470. * Function: execute
  2471. *
  2472. * Changes the attribute of the cell's user object by
  2473. * using <mxCell.setAttribute>.
  2474. */
  2475. mxCellAttributeChange.prototype.execute = function()
  2476. {
  2477. if (this.cell != null)
  2478. {
  2479. var tmp = this.cell.getAttribute(this.attribute);
  2480. if (this.previous == null)
  2481. {
  2482. this.cell.value.removeAttribute(this.attribute);
  2483. }
  2484. else
  2485. {
  2486. this.cell.setAttribute(this.attribute, this.previous);
  2487. }
  2488. this.previous = tmp;
  2489. }
  2490. };