mxMultiplicity.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /**
  2. * Copyright (c) 2006-2015, JGraph Ltd
  3. * Copyright (c) 2006-2015, Gaudenz Alder
  4. */
  5. /**
  6. * Class: mxMultiplicity
  7. *
  8. * Defines invalid connections along with the error messages that they produce.
  9. * To add or remove rules on a graph, you must add/remove instances of this
  10. * class to <mxGraph.multiplicities>.
  11. *
  12. * Example:
  13. *
  14. * (code)
  15. * graph.multiplicities.push(new mxMultiplicity(
  16. * true, 'rectangle', null, null, 0, 2, ['circle'],
  17. * 'Only 2 targets allowed',
  18. * 'Only circle targets allowed'));
  19. * (end)
  20. *
  21. * Defines a rule where each rectangle must be connected to no more than 2
  22. * circles and no other types of targets are allowed.
  23. *
  24. * Constructor: mxMultiplicity
  25. *
  26. * Instantiate class mxMultiplicity in order to describe allowed
  27. * connections in a graph. Not all constraints can be enforced while
  28. * editing, some must be checked at validation time. The <countError> and
  29. * <typeError> are treated as resource keys in <mxResources>.
  30. *
  31. * Parameters:
  32. *
  33. * source - Boolean indicating if this rule applies to the source or target
  34. * terminal.
  35. * type - Type of the source or target terminal that this rule applies to.
  36. * See <type> for more information.
  37. * attr - Optional attribute name to match the source or target terminal.
  38. * value - Optional attribute value to match the source or target terminal.
  39. * min - Minimum number of edges for this rule. Default is 1.
  40. * max - Maximum number of edges for this rule. n means infinite. Default
  41. * is n.
  42. * validNeighbors - Array of types of the opposite terminal for which this
  43. * rule applies.
  44. * countError - Error to be displayed for invalid number of edges.
  45. * typeError - Error to be displayed for invalid opposite terminals.
  46. * validNeighborsAllowed - Optional boolean indicating if the array of
  47. * opposite types should be valid or invalid.
  48. */
  49. function mxMultiplicity(source, type, attr, value, min, max,
  50. validNeighbors, countError, typeError, validNeighborsAllowed)
  51. {
  52. this.source = source;
  53. this.type = type;
  54. this.attr = attr;
  55. this.value = value;
  56. this.min = (min != null) ? min : 0;
  57. this.max = (max != null) ? max : 'n';
  58. this.validNeighbors = validNeighbors;
  59. this.countError = mxResources.get(countError) || countError;
  60. this.typeError = mxResources.get(typeError) || typeError;
  61. this.validNeighborsAllowed = (validNeighborsAllowed != null) ?
  62. validNeighborsAllowed : true;
  63. };
  64. /**
  65. * Variable: type
  66. *
  67. * Defines the type of the source or target terminal. The type is a string
  68. * passed to <mxUtils.isNode> together with the source or target vertex
  69. * value as the first argument.
  70. */
  71. mxMultiplicity.prototype.type = null;
  72. /**
  73. * Variable: attr
  74. *
  75. * Optional string that specifies the attributename to be passed to
  76. * <mxUtils.isNode> to check if the rule applies to a cell.
  77. */
  78. mxMultiplicity.prototype.attr = null;
  79. /**
  80. * Variable: value
  81. *
  82. * Optional string that specifies the value of the attribute to be passed
  83. * to <mxUtils.isNode> to check if the rule applies to a cell.
  84. */
  85. mxMultiplicity.prototype.value = null;
  86. /**
  87. * Variable: source
  88. *
  89. * Boolean that specifies if the rule is applied to the source or target
  90. * terminal of an edge.
  91. */
  92. mxMultiplicity.prototype.source = null;
  93. /**
  94. * Variable: min
  95. *
  96. * Defines the minimum number of connections for which this rule applies.
  97. * Default is 0.
  98. */
  99. mxMultiplicity.prototype.min = null;
  100. /**
  101. * Variable: max
  102. *
  103. * Defines the maximum number of connections for which this rule applies.
  104. * A value of 'n' means unlimited times. Default is 'n'.
  105. */
  106. mxMultiplicity.prototype.max = null;
  107. /**
  108. * Variable: validNeighbors
  109. *
  110. * Holds an array of strings that specify the type of neighbor for which
  111. * this rule applies. The strings are used in <mxCell.is> on the opposite
  112. * terminal to check if the rule applies to the connection.
  113. */
  114. mxMultiplicity.prototype.validNeighbors = null;
  115. /**
  116. * Variable: validNeighborsAllowed
  117. *
  118. * Boolean indicating if the list of validNeighbors are those that are allowed
  119. * for this rule or those that are not allowed for this rule.
  120. */
  121. mxMultiplicity.prototype.validNeighborsAllowed = true;
  122. /**
  123. * Variable: countError
  124. *
  125. * Holds the localized error message to be displayed if the number of
  126. * connections for which the rule applies is smaller than <min> or greater
  127. * than <max>.
  128. */
  129. mxMultiplicity.prototype.countError = null;
  130. /**
  131. * Variable: typeError
  132. *
  133. * Holds the localized error message to be displayed if the type of the
  134. * neighbor for a connection does not match the rule.
  135. */
  136. mxMultiplicity.prototype.typeError = null;
  137. /**
  138. * Function: check
  139. *
  140. * Checks the multiplicity for the given arguments and returns the error
  141. * for the given connection or null if the multiplicity does not apply.
  142. *
  143. * Parameters:
  144. *
  145. * graph - Reference to the enclosing <mxGraph> instance.
  146. * edge - <mxCell> that represents the edge to validate.
  147. * source - <mxCell> that represents the source terminal.
  148. * target - <mxCell> that represents the target terminal.
  149. * sourceOut - Number of outgoing edges from the source terminal.
  150. * targetIn - Number of incoming edges for the target terminal.
  151. */
  152. mxMultiplicity.prototype.check = function(graph, edge, source, target, sourceOut, targetIn)
  153. {
  154. var error = '';
  155. if ((this.source && this.checkTerminal(graph, source, edge)) ||
  156. (!this.source && this.checkTerminal(graph, target, edge)))
  157. {
  158. if (this.countError != null &&
  159. ((this.source && (this.max == 0 || (sourceOut >= this.max))) ||
  160. (!this.source && (this.max == 0 || (targetIn >= this.max)))))
  161. {
  162. error += this.countError + '\n';
  163. }
  164. if (this.validNeighbors != null && this.typeError != null && this.validNeighbors.length > 0)
  165. {
  166. var isValid = this.checkNeighbors(graph, edge, source, target);
  167. if (!isValid)
  168. {
  169. error += this.typeError + '\n';
  170. }
  171. }
  172. }
  173. return (error.length > 0) ? error : null;
  174. };
  175. /**
  176. * Function: checkNeighbors
  177. *
  178. * Checks if there are any valid neighbours in <validNeighbors>. This is only
  179. * called if <validNeighbors> is a non-empty array.
  180. */
  181. mxMultiplicity.prototype.checkNeighbors = function(graph, edge, source, target)
  182. {
  183. var sourceValue = graph.model.getValue(source);
  184. var targetValue = graph.model.getValue(target);
  185. var isValid = !this.validNeighborsAllowed;
  186. var valid = this.validNeighbors;
  187. for (var j = 0; j < valid.length; j++)
  188. {
  189. if (this.source &&
  190. this.checkType(graph, targetValue, valid[j]))
  191. {
  192. isValid = this.validNeighborsAllowed;
  193. break;
  194. }
  195. else if (!this.source &&
  196. this.checkType(graph, sourceValue, valid[j]))
  197. {
  198. isValid = this.validNeighborsAllowed;
  199. break;
  200. }
  201. }
  202. return isValid;
  203. };
  204. /**
  205. * Function: checkTerminal
  206. *
  207. * Checks the given terminal cell and returns true if this rule applies. The
  208. * given cell is the source or target of the given edge, depending on
  209. * <source>. This implementation uses <checkType> on the terminal's value.
  210. */
  211. mxMultiplicity.prototype.checkTerminal = function(graph, terminal, edge)
  212. {
  213. var value = graph.model.getValue(terminal);
  214. return this.checkType(graph, value, this.type, this.attr, this.value);
  215. };
  216. /**
  217. * Function: checkType
  218. *
  219. * Checks the type of the given value.
  220. */
  221. mxMultiplicity.prototype.checkType = function(graph, value, type, attr, attrValue)
  222. {
  223. if (value != null)
  224. {
  225. if (!isNaN(value.nodeType)) // Checks if value is a DOM node
  226. {
  227. return mxUtils.isNode(value, type, attr, attrValue);
  228. }
  229. else
  230. {
  231. return value == type;
  232. }
  233. }
  234. return false;
  235. };