diff options
Diffstat (limited to 'src/js/view/mxMultiplicity.js')
-rw-r--r-- | src/js/view/mxMultiplicity.js | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/src/js/view/mxMultiplicity.js b/src/js/view/mxMultiplicity.js new file mode 100644 index 0000000..c927d3f --- /dev/null +++ b/src/js/view/mxMultiplicity.js @@ -0,0 +1,257 @@ +/** + * $Id: mxMultiplicity.js,v 1.24 2010-11-03 14:52:40 gaudenz Exp $ + * Copyright (c) 2006-2010, JGraph Ltd + */ +/** + * Class: mxMultiplicity + * + * Defines invalid connections along with the error messages that they produce. + * To add or remove rules on a graph, you must add/remove instances of this + * class to <mxGraph.multiplicities>. + * + * Example: + * + * (code) + * graph.multiplicities.push(new mxMultiplicity( + * true, 'rectangle', null, null, 0, 2, ['circle'], + * 'Only 2 targets allowed', + * 'Only circle targets allowed')); + * (end) + * + * Defines a rule where each rectangle must be connected to no more than 2 + * circles and no other types of targets are allowed. + * + * Constructor: mxMultiplicity + * + * Instantiate class mxMultiplicity in order to describe allowed + * connections in a graph. Not all constraints can be enforced while + * editing, some must be checked at validation time. The <countError> and + * <typeError> are treated as resource keys in <mxResources>. + * + * Parameters: + * + * source - Boolean indicating if this rule applies to the source or target + * terminal. + * type - Type of the source or target terminal that this rule applies to. + * See <type> for more information. + * attr - Optional attribute name to match the source or target terminal. + * value - Optional attribute value to match the source or target terminal. + * min - Minimum number of edges for this rule. Default is 1. + * max - Maximum number of edges for this rule. n means infinite. Default + * is n. + * validNeighbors - Array of types of the opposite terminal for which this + * rule applies. + * countError - Error to be displayed for invalid number of edges. + * typeError - Error to be displayed for invalid opposite terminals. + * validNeighborsAllowed - Optional boolean indicating if the array of + * opposite types should be valid or invalid. + */ +function mxMultiplicity(source, type, attr, value, min, max, + validNeighbors, countError, typeError, validNeighborsAllowed) +{ + this.source = source; + this.type = type; + this.attr = attr; + this.value = value; + this.min = (min != null) ? min : 0; + this.max = (max != null) ? max : 'n'; + this.validNeighbors = validNeighbors; + this.countError = mxResources.get(countError) || countError; + this.typeError = mxResources.get(typeError) || typeError; + this.validNeighborsAllowed = (validNeighborsAllowed != null) ? + validNeighborsAllowed : true; +}; + +/** + * Variable: type + * + * Defines the type of the source or target terminal. The type is a string + * passed to <mxUtils.isNode> together with the source or target vertex + * value as the first argument. + */ +mxMultiplicity.prototype.type = null; + +/** + * Variable: attr + * + * Optional string that specifies the attributename to be passed to + * <mxUtils.isNode> to check if the rule applies to a cell. + */ +mxMultiplicity.prototype.attr = null; + +/** + * Variable: value + * + * Optional string that specifies the value of the attribute to be passed + * to <mxUtils.isNode> to check if the rule applies to a cell. + */ +mxMultiplicity.prototype.value = null; + +/** + * Variable: source + * + * Boolean that specifies if the rule is applied to the source or target + * terminal of an edge. + */ +mxMultiplicity.prototype.source = null; + +/** + * Variable: min + * + * Defines the minimum number of connections for which this rule applies. + * Default is 0. + */ +mxMultiplicity.prototype.min = null; + +/** + * Variable: max + * + * Defines the maximum number of connections for which this rule applies. + * A value of 'n' means unlimited times. Default is 'n'. + */ +mxMultiplicity.prototype.max = null; + +/** + * Variable: validNeighbors + * + * Holds an array of strings that specify the type of neighbor for which + * this rule applies. The strings are used in <mxCell.is> on the opposite + * terminal to check if the rule applies to the connection. + */ +mxMultiplicity.prototype.validNeighbors = null; + +/** + * Variable: validNeighborsAllowed + * + * Boolean indicating if the list of validNeighbors are those that are allowed + * for this rule or those that are not allowed for this rule. + */ +mxMultiplicity.prototype.validNeighborsAllowed = true; + +/** + * Variable: countError + * + * Holds the localized error message to be displayed if the number of + * connections for which the rule applies is smaller than <min> or greater + * than <max>. + */ +mxMultiplicity.prototype.countError = null; + +/** + * Variable: typeError + * + * Holds the localized error message to be displayed if the type of the + * neighbor for a connection does not match the rule. + */ +mxMultiplicity.prototype.typeError = null; + +/** + * Function: check + * + * Checks the multiplicity for the given arguments and returns the error + * for the given connection or null if the multiplicity does not apply. + * + * Parameters: + * + * graph - Reference to the enclosing <mxGraph> instance. + * edge - <mxCell> that represents the edge to validate. + * source - <mxCell> that represents the source terminal. + * target - <mxCell> that represents the target terminal. + * sourceOut - Number of outgoing edges from the source terminal. + * targetIn - Number of incoming edges for the target terminal. + */ +mxMultiplicity.prototype.check = function(graph, edge, source, target, sourceOut, targetIn) +{ + var error = ''; + + if ((this.source && this.checkTerminal(graph, source, edge)) || + (!this.source && this.checkTerminal(graph, target, edge))) + { + if (this.countError != null && + ((this.source && (this.max == 0 || (sourceOut >= this.max))) || + (!this.source && (this.max == 0 || (targetIn >= this.max))))) + { + error += this.countError + '\n'; + } + + if (this.validNeighbors != null && this.typeError != null && this.validNeighbors.length > 0) + { + var isValid = this.checkNeighbors(graph, edge, source, target); + + if (!isValid) + { + error += this.typeError + '\n'; + } + } + } + + return (error.length > 0) ? error : null; +}; + +/** + * Function: checkNeighbors + * + * Checks if there are any valid neighbours in <validNeighbors>. This is only + * called if <validNeighbors> is a non-empty array. + */ +mxMultiplicity.prototype.checkNeighbors = function(graph, edge, source, target) +{ + var sourceValue = graph.model.getValue(source); + var targetValue = graph.model.getValue(target); + var isValid = !this.validNeighborsAllowed; + var valid = this.validNeighbors; + + for (var j = 0; j < valid.length; j++) + { + if (this.source && + this.checkType(graph, targetValue, valid[j])) + { + isValid = this.validNeighborsAllowed; + break; + } + else if (!this.source && + this.checkType(graph, sourceValue, valid[j])) + { + isValid = this.validNeighborsAllowed; + break; + } + } + + return isValid; +}; + +/** + * Function: checkTerminal + * + * Checks the given terminal cell and returns true if this rule applies. The + * given cell is the source or target of the given edge, depending on + * <source>. This implementation uses <checkType> on the terminal's value. + */ +mxMultiplicity.prototype.checkTerminal = function(graph, terminal, edge) +{ + var value = graph.model.getValue(terminal); + + return this.checkType(graph, value, this.type, this.attr, this.value); +}; + +/** + * Function: checkType + * + * Checks the type of the given value. + */ +mxMultiplicity.prototype.checkType = function(graph, value, type, attr, attrValue) +{ + if (value != null) + { + if (!isNaN(value.nodeType)) // Checks if value is a DOM node + { + return mxUtils.isNode(value, type, attr, attrValue); + } + else + { + return value == type; + } + } + + return false; +}; |