1 /*
2 * JScroll - the scrollable desktop pane for Java.
3 * Copyright (C) 2003 Tom Tessier
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 *
19 */
20
21 package org.jscroll.widgets;
22
23 import javax.swing.*;
24
25 import java.awt.*;
26
27
28 /***
29 * This class provides internal frame positioning methods for use by
30 * {@link org.jscroll.widgets.DesktopScrollPane DesktopScrollPane}.
31 *
32 * @author <a href="mailto:tessier@gabinternet.com">Tom Tessier</a>
33 * @version 1.0 11-Aug-2001
34 */
35 public class FramePositioning implements DesktopConstants {
36 private DesktopScrollPane desktopScrollpane;
37 private boolean autoTile; // determines whether to cascade or tile windows
38
39 /***
40 * creates the FramePositioning object
41 *
42 * @param desktopScrollpane a reference to the DesktopScrollpane object
43 */
44 public FramePositioning(DesktopScrollPane desktopScrollpane) {
45 this.desktopScrollpane = desktopScrollpane;
46 }
47
48 /***
49 * turns autoTile on or off
50 *
51 * @param autoTile <code>boolean</code> representing autoTile mode.
52 * If <code>true</code>, then all new frames are tiled automatically.
53 * If <code>false</code>, then all new frames are cascaded automatically.
54 */
55 public void setAutoTile(boolean autoTile) {
56 this.autoTile = autoTile;
57
58 if (autoTile) {
59 tileInternalFrames();
60 } else {
61 cascadeInternalFrames();
62 }
63 }
64
65 /***
66 * returns the autoTile mode
67 *
68 * @return <code>boolean</code> representing current autoTile mode
69 */
70 public boolean getAutoTile() {
71 return autoTile;
72 }
73
74 /***
75 * cycles through and cascades all internal frames
76 */
77 public void cascadeInternalFrames() {
78 JInternalFrame[] frames = desktopScrollpane.getAllFrames();
79 JScrollInternalFrame f;
80
81 int frameCounter = 0;
82
83 for (int i = frames.length - 1; i >= 0; i--) {
84 f = (JScrollInternalFrame) frames[i];
85
86 // don't include iconified frames in the cascade
87 if (!f.isIcon()) {
88 f.setSize(f.getInitialDimensions());
89 f.setLocation(cascadeInternalFrame(f, frameCounter++));
90 }
91 }
92 }
93
94 /***
95 * cascades the given internal frame based upon the current number
96 * of internal frames
97 *
98 * @param f the internal frame to cascade
99 *
100 * @return a Point object representing the location
101 * assigned to the internal frame upon the virtual desktop
102 */
103 public Point cascadeInternalFrame(JInternalFrame f) {
104 return cascadeInternalFrame(f, desktopScrollpane.getNumberOfFrames());
105 }
106
107 /***
108 * cascades the given internal frame based upon supplied count
109 *
110 * @param f the internal frame to cascade
111 * @count the count to use in cascading the internal frame
112 *
113 * @return a Point object representing the location
114 * assigned to the internal frame upon the virtual desktop
115 */
116 private Point cascadeInternalFrame(JInternalFrame f, int count) {
117 int windowWidth = f.getWidth();
118 int windowHeight = f.getHeight();
119
120 Rectangle viewP = desktopScrollpane.getViewport().getViewRect();
121
122 // get # of windows that fit horizontally
123 int numFramesWide = (viewP.width - windowWidth) / X_OFFSET;
124
125 if (numFramesWide < 1) {
126 numFramesWide = 1;
127 }
128
129 // get # of windows that fit vertically
130 int numFramesHigh = (viewP.height - windowHeight) / Y_OFFSET;
131
132 if (numFramesHigh < 1) {
133 numFramesHigh = 1;
134 }
135
136 // position relative to the current viewport (viewP.x/viewP.y)
137 // (so new windows appear onscreen)
138 int xLoc = viewP.x +
139 (X_OFFSET * ((count + 1) -
140 ((numFramesWide - 1) * (int) (count / numFramesWide))));
141 int yLoc = viewP.y +
142 (Y_OFFSET * ((count + 1) -
143 (numFramesHigh * (int) (count / numFramesHigh))));
144
145 return new Point(xLoc, yLoc);
146 }
147
148 /***
149 * tiles internal frames upon the desktop.
150 * <BR><BR>
151 * Based upon the following tiling algorithm:
152 * <BR><BR>
153 * - take the sqroot of the total frames rounded down, that gives
154 * the number of columns.
155 * <BR><BR>
156 * - divide the total frames by the # of columns to get the #
157 * of rows in each column, and any remainder is distributed
158 * amongst the remaining rows from right to left)
159 * <BR><BR>
160 * eg) <BR>
161 * 1 frame, remainder 0, 1 row<BR>
162 * 2 frames, remainder 0, 2 rows<BR>
163 * 3 frames, remainder 0, 3 rows<BR>
164 * 4 frames, remainder 0, 2 rows x 2 columns <BR>
165 * 5 frames, remainder 1, 2 rows in column I, 3 rows in column II<BR>
166 * 10 frames, remainder 1, 3 rows in column I, 3 rows in column II,
167 * 4 rows in column III <BR>
168 * 16 frames, 4 rows x 4 columns <BR>
169 * <BR><BR>
170 * Pseudocode:
171 * <BR><BR><code>
172 * while (frames) { <BR>
173 * numCols = (int)sqrt(totalFrames); <BR>
174 * numRows = totalFrames / numCols; <BR>
175 * remainder = totalFrames % numCols <BR>
176 * if ((numCols-curCol) <= remainder) { <BR>
177 * numRows++; // add an extra row for this column <BR>
178 * } <BR>
179 * } </code><BR>
180 */
181 public void tileInternalFrames() {
182 Rectangle viewP = desktopScrollpane.getViewport().getViewRect();
183
184 int totalNonIconFrames = 0;
185
186 JInternalFrame[] frames = desktopScrollpane.getAllFrames();
187
188 for (int i = 0; i < frames.length; i++) {
189 if (!frames[i].isIcon()) { // don't include iconified frames...
190 totalNonIconFrames++;
191 }
192 }
193
194 int curCol = 0;
195 int curRow = 0;
196 int i = 0;
197
198 if (totalNonIconFrames > 0) {
199 // compute number of columns and rows then tile the frames
200 int numCols = (int) Math.sqrt(totalNonIconFrames);
201
202 int frameWidth = viewP.width / numCols;
203
204 for (curCol = 0; curCol < numCols; curCol++) {
205 int numRows = totalNonIconFrames / numCols;
206 int remainder = totalNonIconFrames % numCols;
207
208 if ((numCols - curCol) <= remainder) {
209 numRows++; // add an extra row for this guy
210 }
211
212 int frameHeight = viewP.height / numRows;
213
214 for (curRow = 0; curRow < numRows; curRow++) {
215 while (frames[i].isIcon()) { // find the next visible frame
216 i++;
217 }
218
219 frames[i].setBounds(curCol * frameWidth,
220 curRow * frameHeight, frameWidth, frameHeight);
221
222 i++;
223 }
224 }
225 }
226 }
227 }
This page was automatically generated by Maven