001: /* ========================================================================
002: * JCommon : a free general purpose class library for the Java(tm) platform
003: * ========================================================================
004: *
005: * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
006: *
007: * Project Info: http://www.jfree.org/jcommon/index.html
008: *
009: * This library is free software; you can redistribute it and/or modify it
010: * under the terms of the GNU Lesser General Public License as published by
011: * the Free Software Foundation; either version 2.1 of the License, or
012: * (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful, but
015: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017: * License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
022: * USA.
023: *
024: * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025: * in the United States and other countries.]
026: *
027: * -----------------
028: * RadialLayout.java
029: * -----------------
030: * (C) Copyright 2003, 2004, by Bryan Scott (for Australian Antarctic Division).
031: *
032: * Original Author: Bryan Scott (for Australian Antarctic Division);
033: * Contributor(s): David Gilbert (for Object Refinery Limited);
034: *
035: *
036: * Changes:
037: * --------
038: * 30-Jun-2003 : Version 1 (BS);
039: * 24-Jul-2003 : Completed missing Javadocs (DG);
040: *
041: */
042:
043: package org.jfree.layout;
044:
045: import java.awt.Checkbox;
046: import java.awt.Component;
047: import java.awt.Container;
048: import java.awt.Dimension;
049: import java.awt.Frame;
050: import java.awt.Insets;
051: import java.awt.LayoutManager;
052: import java.awt.Panel;
053: import java.io.Serializable;
054:
055: /**
056: * RadialLayout is a component layout manager. Compents are laid out in a
057: * circle. If only one component is contained in the layout it is positioned
058: * centrally, otherwise components are evenly spaced around the centre with
059: * the first component placed to the North.
060: *<P>
061: * This code was developed to display CTD rosette firing control
062: *
063: * WARNING: Not thoughly tested, use at own risk.
064: *
065: * @author Bryan Scott (for Australian Antarctic Division)
066: */
067:
068: public class RadialLayout implements LayoutManager, Serializable {
069:
070: /** For serialization. */
071: private static final long serialVersionUID = -7582156799248315534L;
072:
073: /** The minimum width. */
074: private int minWidth = 0;
075:
076: /** The minimum height. */
077: private int minHeight = 0;
078:
079: /** The maximum component width. */
080: private int maxCompWidth = 0;
081:
082: /** The maximum component height. */
083: private int maxCompHeight = 0;
084:
085: /** The preferred width. */
086: private int preferredWidth = 0;
087:
088: /** The preferred height. */
089: private int preferredHeight = 0;
090:
091: /** Size unknown flag. */
092: private boolean sizeUnknown = true;
093:
094: /**
095: * Constructs this layout manager with default properties.
096: */
097: public RadialLayout() {
098: super ();
099: }
100:
101: /**
102: * Not used.
103: *
104: * @param comp the component.
105: */
106: public void addLayoutComponent(final Component comp) {
107: // not used
108: }
109:
110: /**
111: * Not used.
112: *
113: * @param comp the component.
114: */
115: public void removeLayoutComponent(final Component comp) {
116: // not used
117: }
118:
119: /**
120: * Not used.
121: *
122: * @param name the component name.
123: * @param comp the component.
124: */
125: public void addLayoutComponent(final String name,
126: final Component comp) {
127: // not used
128: }
129:
130: /**
131: * Not used.
132: *
133: * @param name the component name.
134: * @param comp the component.
135: */
136: public void removeLayoutComponent(final String name,
137: final Component comp) {
138: // not used
139: }
140:
141: /**
142: * Sets the sizes attribute of the RadialLayout object.
143: *
144: * @param parent the parent.
145: *
146: * @see LayoutManager
147: */
148: private void setSizes(final Container parent) {
149: final int nComps = parent.getComponentCount();
150: //Reset preferred/minimum width and height.
151: this .preferredWidth = 0;
152: this .preferredHeight = 0;
153: this .minWidth = 0;
154: this .minHeight = 0;
155: for (int i = 0; i < nComps; i++) {
156: final Component c = parent.getComponent(i);
157: if (c.isVisible()) {
158: final Dimension d = c.getPreferredSize();
159: if (this .maxCompWidth < d.width) {
160: this .maxCompWidth = d.width;
161: }
162: if (this .maxCompHeight < d.height) {
163: this .maxCompHeight = d.height;
164: }
165: this .preferredWidth += d.width;
166: this .preferredHeight += d.height;
167: }
168: }
169: this .preferredWidth = this .preferredWidth / 2;
170: this .preferredHeight = this .preferredHeight / 2;
171: this .minWidth = this .preferredWidth;
172: this .minHeight = this .preferredHeight;
173: }
174:
175: /**
176: * Returns the preferred size.
177: *
178: * @param parent the parent.
179: *
180: * @return The preferred size.
181: * @see LayoutManager
182: */
183: public Dimension preferredLayoutSize(final Container parent) {
184: final Dimension dim = new Dimension(0, 0);
185: setSizes(parent);
186:
187: //Always add the container's insets!
188: final Insets insets = parent.getInsets();
189: dim.width = this .preferredWidth + insets.left + insets.right;
190: dim.height = this .preferredHeight + insets.top + insets.bottom;
191:
192: this .sizeUnknown = false;
193: return dim;
194: }
195:
196: /**
197: * Returns the minimum size.
198: *
199: * @param parent the parent.
200: *
201: * @return The minimum size.
202: * @see LayoutManager
203: */
204: public Dimension minimumLayoutSize(final Container parent) {
205: final Dimension dim = new Dimension(0, 0);
206:
207: //Always add the container's insets!
208: final Insets insets = parent.getInsets();
209: dim.width = this .minWidth + insets.left + insets.right;
210: dim.height = this .minHeight + insets.top + insets.bottom;
211:
212: this .sizeUnknown = false;
213: return dim;
214: }
215:
216: /**
217: * This is called when the panel is first displayed, and every time its size
218: * changes.
219: * Note: You CAN'T assume preferredLayoutSize or minimumLayoutSize will be
220: * called -- in the case of applets, at least, they probably won't be.
221: *
222: * @param parent the parent.
223: * @see LayoutManager
224: */
225: public void layoutContainer(final Container parent) {
226: final Insets insets = parent.getInsets();
227: final int maxWidth = parent.getSize().width
228: - (insets.left + insets.right);
229: final int maxHeight = parent.getSize().height
230: - (insets.top + insets.bottom);
231: final int nComps = parent.getComponentCount();
232: int x = 0;
233: int y = 0;
234:
235: // Go through the components' sizes, if neither preferredLayoutSize nor
236: // minimumLayoutSize has been called.
237: if (this .sizeUnknown) {
238: setSizes(parent);
239: }
240:
241: if (nComps < 2) {
242: final Component c = parent.getComponent(0);
243: if (c.isVisible()) {
244: final Dimension d = c.getPreferredSize();
245: c.setBounds(x, y, d.width, d.height);
246: }
247: } else {
248: double radialCurrent = Math.toRadians(90);
249: final double radialIncrement = 2 * Math.PI / nComps;
250: final int midX = maxWidth / 2;
251: final int midY = maxHeight / 2;
252: final int a = midX - this .maxCompWidth;
253: final int b = midY - this .maxCompHeight;
254: for (int i = 0; i < nComps; i++) {
255: final Component c = parent.getComponent(i);
256: if (c.isVisible()) {
257: final Dimension d = c.getPreferredSize();
258: x = (int) (midX - (a * Math.cos(radialCurrent))
259: - (d.getWidth() / 2) + insets.left);
260: y = (int) (midY - (b * Math.sin(radialCurrent))
261: - (d.getHeight() / 2) + insets.top);
262:
263: // Set the component's size and position.
264: c.setBounds(x, y, d.width, d.height);
265: }
266: radialCurrent += radialIncrement;
267: }
268: }
269: }
270:
271: /**
272: * Returns the class name.
273: *
274: * @return The class name.
275: */
276: public String toString() {
277: return getClass().getName();
278: }
279:
280: /**
281: * Run a demonstration.
282: *
283: * @param args ignored.
284: *
285: * @throws Exception when an error occurs.
286: */
287: public static void main(final String[] args) throws Exception {
288: final Frame frame = new Frame();
289: final Panel panel = new Panel();
290: panel.setLayout(new RadialLayout());
291:
292: panel.add(new Checkbox("One"));
293: panel.add(new Checkbox("Two"));
294: panel.add(new Checkbox("Three"));
295: panel.add(new Checkbox("Four"));
296: panel.add(new Checkbox("Five"));
297: panel.add(new Checkbox("One"));
298: panel.add(new Checkbox("Two"));
299: panel.add(new Checkbox("Three"));
300: panel.add(new Checkbox("Four"));
301: panel.add(new Checkbox("Five"));
302:
303: frame.add(panel);
304: frame.setSize(300, 500);
305: frame.setVisible(true);
306: }
307:
308: }
|