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 the scrollpane that contains the virtual desktop.
30 *
31 * @author <a href="mailto:tessier@gabinternet.com">Tom Tessier</a>
32 * @version 1.0 11-Aug-2001
33 */
34 public class DesktopScrollPane extends JScrollPane {
35 private DesktopMediator desktopMediator;
36 private RootDesktopPane desktopPane;
37 private FramePositioning positioning;
38
39 /***
40 * creates the DesktopScrollPane object
41 *
42 * @param desktopMediator a reference to the DesktopMediator object
43 */
44 public DesktopScrollPane(DesktopMediator desktopMediator) {
45 this.desktopMediator = desktopMediator;
46
47 desktopPane = new RootDesktopPane(this);
48 setViewportView(desktopPane);
49
50 positioning = new FramePositioning(this);
51
52 // set some defaults
53 setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
54 setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
55
56 // set scrollbars to scroll by 5 pixels each...
57 getHorizontalScrollBar().setUnitIncrement(5);
58 getVerticalScrollBar().setUnitIncrement(5);
59 }
60
61 /***
62 * creates a JScrollInternalFrame and adds it to the virtual desktop
63 *
64 * @param dListener a reference to the DesktopListener
65 * @param title the title displayed in the title bar of the internal frame
66 * @param icon the icon displayed in the title bar of the internal frame
67 * @param frameContents the contents of the internal frame
68 * @param isClosable <code>boolean</code> indicating whether internal frame
69 * is closable
70 * @param x x coordinates of internal frame within the scrollable desktop.
71 * <code>-1</code> indicates the virtual desktop is to determine the position
72 * @param y y coordinates of internal frame within the scrollable desktop
73 * <code>-1</code> indicates the virtual desktop is to determine the position
74 *
75 * @return the JScrollInternalFrame that was created
76 */
77 public JScrollInternalFrame add(DesktopListener dListener, String title,
78 ImageIcon icon, JPanel frameContents, boolean isClosable, int x, int y) {
79 JScrollInternalFrame f = new JScrollInternalFrame(title, icon,
80 frameContents, isClosable);
81 f.addComponentListener(dListener);
82
83 initAndAddFrame(f, x, y);
84
85 return f;
86 }
87
88 /***
89 * adds an internal frame to the virtual desktop
90 *
91 * @param dListener a reference to the DesktopListener
92 * @param f the internal frame to add
93 * @param x x coordinates of internal frame within the scrollable desktop.
94 * <code>-1</code> indicates the virtual desktop is to determine the position
95 * @param y y coordinates of internal frame within the scrollable desktop
96 * <code>-1</code> indicates the virtual desktop is to determine the position
97 */
98 public void add(DesktopListener dListener, JInternalFrame f, int x, int y) {
99 f.addComponentListener(dListener);
100 initAndAddFrame(f, x, y);
101 }
102
103 /***
104 * initializes the frame for display and adds it to the desktop
105 *
106 * @param f the internal frame to add
107 * @param x x coordinates of internal frame within the scrollable desktop.
108 * <code>-1</code> indicates the virtual desktop is to determine the position
109 * @param y y coordinates of internal frame within the scrollable desktop
110 * <code>-1</code> indicates the virtual desktop is to determine the position
111 */
112 private void initAndAddFrame(JInternalFrame f, int x, int y) {
113 // override the position of this window?
114 if ((x != -1) && (y != -1)) {
115 f.setLocation(x, y);
116 } else {
117 if (!getAutoTile()) {
118 f.setLocation(cascadeInternalFrame(f));
119 }
120 }
121
122 desktopPane.add(f);
123
124 // select the newly added frame (note that must select it AFTER it
125 // has been added to the desktopPane)
126 try {
127 f.setSelected(true);
128 } catch (java.beans.PropertyVetoException e) {
129 // swallow property veto exceptions here..!!
130 }
131
132 // resize desktop when add a frame in case any frames off screen
133 resizeDesktop();
134 }
135
136 /***
137 * returns all internal frames placed upon the virtual desktop
138 *
139 * @return a JInternalFrame array containing references to the internal frames
140 */
141 public JInternalFrame[] getAllFrames() {
142 return desktopPane.getAllFrames();
143 }
144
145 /***
146 * returns the internal frame currently selected upon the
147 * virtual desktop
148 *
149 * @return a reference to the active JInternalFrame
150 */
151 public JInternalFrame getSelectedFrame() {
152 return desktopPane.getSelectedFrame();
153 }
154
155 /***
156 * closes the internal frame currently selected upon the
157 * virtual desktop
158 */
159 public void closeSelectedFrame() {
160 JInternalFrame f = getSelectedFrame();
161
162 if (f != null) {
163 f.doDefaultCloseAction();
164 }
165 }
166
167 /***
168 * selects the specified internal frame upon the virtual desktop
169 *
170 * @param f the internal frame to select
171 */
172 public void setSelectedFrame(JInternalFrame f) {
173 try {
174 JInternalFrame currentFrame = desktopPane.getSelectedFrame();
175
176 if (currentFrame != null) {
177 currentFrame.setSelected(false);
178 }
179
180 f.setSelected(true);
181 f.setIcon(false); // de-iconify it (if iconified)
182 } catch (java.beans.PropertyVetoException pve) {
183 System.out.println(pve.getMessage());
184 }
185 }
186
187 /***
188 * flags the specified internal frame as "contents changed." Used to
189 * notify the user when the contents of an inactive internal frame
190 * have changed.
191 *
192 * @param f the internal frame to flag as "contents changed"
193 */
194 public void flagContentsChanged(JInternalFrame f) {
195 if (desktopPane.getSelectedFrame() != f) {
196 RootToggleButton button = (RootToggleButton) ((JScrollInternalFrame) f).getAssociatedButton();
197 button.flagContentsChanged(true);
198 }
199 }
200
201 /***
202 * selects the next available frame upon the virtual desktop
203 */
204 public void selectNextFrame() {
205 JInternalFrame[] frames = getAllFrames();
206
207 if (frames.length > 0) {
208 try {
209 frames[0].setSelected(true);
210 } catch (java.beans.PropertyVetoException pve) {
211 System.out.println("Bean veto: " + pve.getMessage());
212 }
213 }
214 }
215
216 /***
217 * returns the number of internal frames upon the virtual desktop
218 *
219 * @return an <code>int</code> representing the number of internal frames
220 */
221 public int getNumberOfFrames() {
222 return desktopPane.getComponentCount();
223 }
224
225 /***
226 * sets the preferred size of the virtual desktop
227 *
228 * @param dim a Dimension object representing the desired preferred size
229 */
230 public void setDesktopSize(Dimension dim) {
231 desktopPane.setPreferredSize(dim);
232 desktopPane.revalidate();
233 }
234
235 /***
236 * returns the preferred size of the virtual desktop
237 *
238 * @return a Dimension object representing the current preferred size
239 */
240 public Dimension getDesktopSize() {
241 return desktopPane.getPreferredSize();
242 }
243
244 /////
245 // positioning methods
246 /////
247
248 /***
249 * propogates setAutoTile to FramePositioning
250 *
251 * @param autoTile <code>boolean</code> representing autoTile mode.
252 * If <code>true</code>, then all new frames are tiled automatically.
253 * If <code>false</code>, then all new frames are cascaded automatically.
254 */
255 public void setAutoTile(boolean autoTile) {
256 positioning.setAutoTile(autoTile);
257 }
258
259 /***
260 * propogates getAutoTile to FramePositioning
261 *
262 * @return <code>boolean</code> representing current autoTile mode
263 */
264 public boolean getAutoTile() {
265 return positioning.getAutoTile();
266 }
267
268 /***
269 * propogates cascadeInternalFrame to FramePositioning
270 *
271 * @param f the internal frame to cascade
272 *
273 * @return a Point object representing the position of the internal frame
274 */
275 public Point cascadeInternalFrame(JInternalFrame f) {
276 return positioning.cascadeInternalFrame(f);
277 }
278
279 /***
280 * propogates cascadeInternalFrames to FramePositioning
281 */
282 public void cascadeInternalFrames() {
283 positioning.cascadeInternalFrames();
284 }
285
286 /***
287 * propogates tileInternalFrames to FramePositioning
288 */
289 public void tileInternalFrames() {
290 positioning.tileInternalFrames();
291 }
292
293 /***
294 * centers the viewport of the virtual desktop around the
295 * provided internal frame
296 *
297 * @param f the internal frame to center the viewport about
298 */
299 public void centerView(JScrollInternalFrame f) {
300 // set the view centered around this item
301 Rectangle viewP = getViewport().getViewRect();
302 int xCoords = (f.getX() + (f.getWidth() / 2)) - (viewP.width / 2);
303 int yCoords = (f.getY() + (f.getHeight() / 2)) - (viewP.height / 2);
304
305 Dimension desktopSize = getDesktopSize();
306
307 if ((xCoords + viewP.width) > desktopSize.width) {
308 xCoords = desktopSize.width - viewP.width;
309 } else if (xCoords < 0) {
310 xCoords = 0;
311 }
312
313 if ((yCoords + viewP.height) > desktopSize.height) {
314 yCoords = desktopSize.height - viewP.height;
315 } else if (yCoords < 0) {
316 yCoords = 0;
317 }
318
319 getViewport().setViewPosition(new Point(xCoords, yCoords));
320 }
321
322 /***
323 * resizes the virtual desktop based upon the locations of its
324 * internal frames. This updates the desktop scrollbars in real-time.
325 * Executes as an "invoked later" thread for a slight perceived
326 * performance boost.
327 */
328 public void resizeDesktop() {
329 SwingUtilities.invokeLater(new Runnable() {
330 public void run() {
331 // has to go through all the internal frames now and make sure none
332 // off screen, and if so, add those scroll bars!
333 Rectangle viewP = getViewport().getViewRect();
334
335 int maxX = viewP.width + viewP.x;
336 int maxY = viewP.height + viewP.y;
337 int minX = viewP.x;
338 int minY = viewP.y;
339
340 // determine the min/max extents of all internal frames
341 JInternalFrame f = null;
342 JInternalFrame[] frames = getAllFrames();
343
344 for (int i = 0; i < frames.length; i++) {
345 f = frames[i];
346
347 if (f.getX() < minX) { // get minimum X
348 minX = f.getX();
349 }
350
351 if ((f.getX() + f.getWidth()) > maxX) {
352 maxX = f.getX() + f.getWidth();
353 }
354
355 if (f.getY() < minY) { // get minimum Y
356 minY = f.getY();
357 }
358
359 if ((f.getY() + f.getHeight()) > maxY) {
360 maxY = f.getY() + f.getHeight();
361 }
362 }
363
364 setVisible(false); // don't update the viewport while we move
365
366 // everything (otherwise desktop looks 'bouncy')
367 if ((minX != 0) || (minY != 0)) {
368 // have to scroll it to the right or up the amount that it's off screen...
369 // before scroll, move every component to the right / down by that amount
370 for (int i = 0; i < frames.length; i++) {
371 f = frames[i];
372 f.setLocation(f.getX() - minX, f.getY() - minY);
373 }
374
375 // have to scroll (set the viewport) to the right or up the amount
376 // that it's off screen...
377 JViewport view = getViewport();
378 view.setViewSize(new Dimension((maxX - minX),
379 (maxY - minY)));
380 view.setViewPosition(new Point((viewP.x - minX),
381 (viewP.y - minY)));
382 setViewport(view);
383 }
384
385 // resize the desktop
386 setDesktopSize(new Dimension(maxX - minX, maxY - minY));
387
388 setVisible(true); // update the viewport again
389 }
390 });
391 }
392
393 /***
394 * propogates removeAssociatedComponents to DesktopMediator
395 *
396 * @param f the internal frame whose associated components are
397 * to be removed
398 */
399 public void removeAssociatedComponents(JScrollInternalFrame f) {
400 desktopMediator.removeAssociatedComponents(f);
401 }
402 }
This page was automatically generated by Maven