summaryrefslogtreecommitdiff
path: root/src/js/io/mxGraphViewCodec.js
blob: 110b212cde504460d783f29be9128dc4e7bb6ad9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/**
 * $Id: mxGraphViewCodec.js,v 1.18 2010-12-03 11:05:52 gaudenz Exp $
 * Copyright (c) 2006-2010, JGraph Ltd
 */
mxCodecRegistry.register(function()
{
	/**
	 * Class: mxGraphViewCodec
	 *
	 * Custom encoder for <mxGraphView>s. This class is created
	 * and registered dynamically at load time and used implicitely via
	 * <mxCodec> and the <mxCodecRegistry>. This codec only writes views
	 * into a XML format that can be used to create an image for
	 * the graph, that is, it contains absolute coordinates with
	 * computed perimeters, edge styles and cell styles.
	 */
	var codec = new mxObjectCodec(new mxGraphView());

	/**
	 * Function: encode
	 *
	 * Encodes the given <mxGraphView> using <encodeCell>
	 * starting at the model's root. This returns the
	 * top-level graph node of the recursive encoding.
	 */
	codec.encode = function(enc, view)
	{
		return this.encodeCell(enc, view,
			view.graph.getModel().getRoot());
	};

	/**
	 * Function: encodeCell
	 *
	 * Recursively encodes the specifed cell. Uses layer
	 * as the default nodename. If the cell's parent is
	 * null, then graph is used for the nodename. If
	 * <mxGraphModel.isEdge> returns true for the cell,
	 * then edge is used for the nodename, else if
	 * <mxGraphModel.isVertex> returns true for the cell,
	 * then vertex is used for the nodename.
	 *
	 * <mxGraph.getLabel> is used to create the label
	 * attribute for the cell. For graph nodes and vertices
	 * the bounds are encoded into x, y, width and height.
	 * For edges the points are encoded into a points
	 * attribute as a space-separated list of comma-separated
	 * coordinate pairs (eg. x0,y0 x1,y1 ... xn,yn). All
	 * values from the cell style are added as attribute
	 * values to the node. 
	 */
	codec.encodeCell = function(enc, view, cell)
	{
		var model = view.graph.getModel();
		var state = view.getState(cell);
		var parent = model.getParent(cell);
		
		if (parent == null || state != null)
		{
			var childCount = model.getChildCount(cell);
			var geo = view.graph.getCellGeometry(cell);
			var name = null;
			
			if (parent == model.getRoot())
			{
				name = 'layer';
			}
			else if (parent == null)
			{
				name = 'graph';
			}
			else if (model.isEdge(cell))
			{
				name = 'edge';
			}
			else if (childCount > 0 && geo != null)
			{
				name = 'group';
			}
			else if (model.isVertex(cell))
			{
				name = 'vertex';
			}
			
			if (name != null)
			{
				var node = enc.document.createElement(name);
				var lab = view.graph.getLabel(cell);
				
				if (lab != null)
				{
					node.setAttribute('label', view.graph.getLabel(cell));
					
					if (view.graph.isHtmlLabel(cell))
					{
						node.setAttribute('html', true);
					}
				}
		
				if (parent == null)
				{
					var bounds = view.getGraphBounds();
					
					if (bounds != null)
					{
						node.setAttribute('x', Math.round(bounds.x));
						node.setAttribute('y', Math.round(bounds.y));
						node.setAttribute('width', Math.round(bounds.width));
						node.setAttribute('height', Math.round(bounds.height));
					}
					
					node.setAttribute('scale', view.scale);
				}
				else if (state != null && geo != null)
				{
					// Writes each key, value in the style pair to an attribute
				    for (var i in state.style)
				    {
				    	var value = state.style[i];
		
				    	// Tries to turn objects and functions into strings
					    if (typeof(value) == 'function' &&
							typeof(value) == 'object')
						{
					    	value = mxStyleRegistry.getName(value);
				        }
				    	
				    	if (value != null &&
				    		typeof(value) != 'function' &&
							typeof(value) != 'object')
						{
							node.setAttribute(i, value);
				        }
				    }
				    
					var abs = state.absolutePoints;
					
					// Writes the list of points into one attribute
					if (abs != null && abs.length > 0)
					{
						var pts = Math.round(abs[0].x) + ',' + Math.round(abs[0].y);
		
						for (var i=1; i<abs.length; i++)
						{
							pts += ' ' + Math.round(abs[i].x) + ',' +
								Math.round(abs[i].y);
						}
		
						node.setAttribute('points', pts);
					}
					
					// Writes the bounds into 4 attributes
					else
					{
						node.setAttribute('x', Math.round(state.x));
						node.setAttribute('y', Math.round(state.y));
						node.setAttribute('width', Math.round(state.width));
						node.setAttribute('height', Math.round(state.height));				
					}
		
					var offset = state.absoluteOffset;
					
					// Writes the offset into 2 attributes
					if (offset != null)
					{
						if (offset.x != 0)
						{
							node.setAttribute('dx', Math.round(offset.x));
						}
						
						if (offset.y != 0)
						{
							node.setAttribute('dy', Math.round(offset.y));
						}
					}
				}
		
				for (var i=0; i<childCount; i++)
				{
					var childNode = this.encodeCell(enc,
							view, model.getChildAt(cell, i));
					
					if (childNode != null)
					{
						node.appendChild(childNode);
					}
				}
			}
		}
		
		return node;
	};

	// Returns the codec into the registry
	return codec;

}());