Project

General

Profile

Download (7.6 KB) Statistics
| Branch: | Tag: | Revision:
1
/*******************************************************************************
2
 * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
3
 * All rights reserved. This program and the accompanying materials are made
4
 * available under the terms of the Eclipse Public License v1.0 which
5
 * accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors: The Chisel Group, University of Victoria
9
 *******************************************************************************/
10
package org.eclipse.zest.layouts.algorithms;
11

    
12
import java.util.Arrays;
13

    
14
import org.eclipse.zest.layouts.LayoutStyles;
15
import org.eclipse.zest.layouts.dataStructures.InternalNode;
16
import org.eclipse.zest.layouts.dataStructures.InternalRelationship;
17

    
18
/**
19
 * @version 2.0
20
 * @author Ian Bull
21
 * @author Casey Best and Rob Lintern
22
 */
23
public class GridLayoutAlgorithm extends AbstractLayoutAlgorithm {
24

    
25
	private static final double PADDING_PERCENTAGE = 0.95;
26

    
27
	protected int rowPadding = 0;
28

    
29
	public void setLayoutArea(double x, double y, double width, double height) {
30
		throw new RuntimeException("Operation not implemented");
31
	}
32

    
33
	int rows, cols, numChildren;
34
	double colWidth, rowHeight, offsetX, offsetY;
35
	int totalProgress;
36
	double h, w;
37

    
38
	/**
39
	 * Initializes the grid layout.
40
	 * @param styles
41
	 * @see LayoutStyles
42
	 */
43
	public GridLayoutAlgorithm(int styles) {
44
		super(styles);
45
	}
46

    
47
	/**
48
	 * Inititalizes the grid layout with no style.
49
	 */
50
	public GridLayoutAlgorithm() {
51
		this(LayoutStyles.NONE);
52
	}
53

    
54
	protected int getCurrentLayoutStep() {
55
		// TODO: This isn't right
56
		return 0;
57
	}
58

    
59
	protected int getTotalNumberOfLayoutSteps() {
60
		return totalProgress;
61
	}
62

    
63
	/**
64
	 * 
65
	 */
66
	protected void preLayoutAlgorithm(InternalNode[] entitiesToLayout, InternalRelationship[] relationshipsToConsider, double x, double y, double width, double height) {
67

    
68
		// TODO: Filter unwanted entities and relationships
69
		//super.applyLayout (entitiesToLayout, relationshipsToConsider, boundsX, boundsY, boundsWidth, boundsHeight);
70
		// now begin
71
		numChildren = entitiesToLayout.length;
72
		if (numChildren < 1)
73
			return;
74

    
75
		int[] colsAndRows = calculateNumberOfRowsAndCols(numChildren, x, y, width, height);
76
		cols = colsAndRows[0];
77
		rows = colsAndRows[1];
78

    
79
		totalProgress = rows + 2;
80
		fireProgressEvent(1, totalProgress);
81

    
82
		// sort the entities
83
		if (comparator != null) {
84
			Arrays.sort(entitiesToLayout, comparator);
85
		} else {
86
			Arrays.sort(entitiesToLayout);
87
		}
88
		fireProgressEvent(2, totalProgress);
89

    
90
		// Calculate row height and column width
91
		colWidth = width / cols;
92
		rowHeight = height / rows;
93

    
94
		// Calculate amount to scale children
95
		double[] nodeSize = calculateNodeSize(colWidth, rowHeight);
96
		w = nodeSize[0];
97
		h = nodeSize[1];
98
		offsetX = (colWidth - w) / 2.0; // half of the space between columns
99
		offsetY = (rowHeight - h) / 2.0; // half of the space between rows
100
	}
101

    
102
	/**
103
	 * Use this algorithm to layout the given entities, using the given relationships and bounds.
104
	 * The entities will be placed in the same order as they are passed in, unless a comparator
105
	 * is supplied.  
106
	 * 
107
	 * @param entitiesToLayout Apply the algorithm to these entities
108
	 * @param relationshipsToConsider Only consider these relationships when applying the algorithm.
109
	 * @param boundsX The left side of the bounds in which the layout can place the entities.
110
	 * @param boundsY The top side of the bounds in which the layout can place the entities.
111
	 * @param boundsWidth The width of the bounds in which the layout can place the entities.
112
	 * @param boundsHeight The height of the bounds in which the layout can place the entities.
113
	 * @throws RuntimeException Thrown if entitiesToLayout doesn't contain all of the endpoints for each relationship in relationshipsToConsider
114
	 */
115
	protected synchronized void applyLayoutInternal(InternalNode[] entitiesToLayout, InternalRelationship[] relationshipsToConsider, double boundsX, double boundsY, double boundsWidth, double boundsHeight) {
116

    
117
		int index = 0;
118
		for (int i = 0; i < rows; i++) {
119
			for (int j = 0; j < cols; j++) {
120
				if ((i * cols + j) < numChildren) {
121
					// find new position for child
122
					double xmove = boundsX + j * colWidth + offsetX;
123
					double ymove = boundsY + i * rowHeight + offsetY;
124
					InternalNode sn = entitiesToLayout[index++];
125
					sn.setInternalLocation(xmove, ymove);
126
					sn.setInternalSize(Math.max(w, MIN_ENTITY_SIZE), Math.max(h, MIN_ENTITY_SIZE));
127
				}
128
			}
129
			fireProgressEvent(2 + i, totalProgress);
130
		}
131
		updateLayoutLocations(entitiesToLayout);
132
		fireProgressEvent(totalProgress, totalProgress);
133
	}
134

    
135
	protected void postLayoutAlgorithm(InternalNode[] entitiesToLayout, InternalRelationship[] relationshipsToConsider) {
136

    
137
	}
138

    
139
	/**
140
	 * Calculates and returns an array containing the number of columns, followed by the number of rows
141
	 */
142
	protected int[] calculateNumberOfRowsAndCols(int numChildren, double boundX, double boundY, double boundWidth, double boundHeight) {
143
		if (getEntityAspectRatio() == 1.0) {
144
			return calculateNumberOfRowsAndCols_square(numChildren, boundX, boundY, boundWidth, boundHeight);
145
		} else {
146
			return calculateNumberOfRowsAndCols_rectangular(numChildren);
147
		}
148
	}
149

    
150
	protected int[] calculateNumberOfRowsAndCols_square(int numChildren, double boundX, double boundY, double boundWidth, double boundHeight) {
151
		int rows = Math.max(1, (int) Math.sqrt(numChildren * boundHeight / boundWidth));
152
		int cols = Math.max(1, (int) Math.sqrt(numChildren * boundWidth / boundHeight));
153

    
154
		// if space is taller than wide, adjust rows first
155
		if (boundWidth <= boundHeight) {
156
			//decrease number of rows and columns until just enough or not enough
157
			while (rows * cols > numChildren) {
158
				if (rows > 1)
159
					rows--;
160
				if (rows * cols > numChildren)
161
					if (cols > 1)
162
						cols--;
163
			}
164
			//increase number of rows and columns until just enough
165
			while (rows * cols < numChildren) {
166
				rows++;
167
				if (rows * cols < numChildren)
168
					cols++;
169
			}
170
		} else {
171
			//decrease number of rows and columns until just enough or not enough
172
			while (rows * cols > numChildren) {
173
				if (cols > 1)
174
					cols--;
175
				if (rows * cols > numChildren)
176
					if (rows > 1)
177
						rows--;
178
			}
179
			//increase number of rows and columns until just enough
180
			while (rows * cols < numChildren) {
181
				cols++;
182
				if (rows * cols < numChildren)
183
					rows++;
184
			}
185
		}
186
		int[] result = { cols, rows };
187
		return result;
188
	}
189

    
190
	protected int[] calculateNumberOfRowsAndCols_rectangular(int numChildren) {
191
		int rows = Math.max(1, (int) Math.ceil(Math.sqrt(numChildren)));
192
		int cols = Math.max(1, (int) Math.ceil(Math.sqrt(numChildren)));
193
		int[] result = { cols, rows };
194
		return result;
195
	}
196

    
197
	protected double[] calculateNodeSize(double colWidth, double rowHeight) {
198
		double childW = Math.max(MIN_ENTITY_SIZE, PADDING_PERCENTAGE * colWidth);
199
		double childH = Math.max(MIN_ENTITY_SIZE, PADDING_PERCENTAGE * (rowHeight - rowPadding));
200
		double whRatio = colWidth / rowHeight;
201
		if (whRatio < getEntityAspectRatio()) {
202
			childH = childW / getEntityAspectRatio();
203
		} else {
204
			childW = childH * getEntityAspectRatio();
205
		}
206
		double[] result = { childW, childH };
207
		return result;
208
	}
209

    
210
	/**
211
	 * Increases the padding between rows in the grid
212
	 * @param rowPadding Value will not be set if less than 0.
213
	 */
214
	public void setRowPadding(int rowPadding) {
215
		if (rowPadding < 0) {
216
			return;
217
		}
218
		this.rowPadding = rowPadding;
219
	}
220

    
221
	protected boolean isValidConfiguration(boolean asynchronous, boolean continueous) {
222
		if (asynchronous && continueous)
223
			return false;
224
		else if (asynchronous && !continueous)
225
			return true;
226
		else if (!asynchronous && continueous)
227
			return false;
228
		else if (!asynchronous && !continueous)
229
			return true;
230

    
231
		return false;
232
	}
233

    
234
}
(5-5/12)