001: /* *************************************************************************
002:
003: Millstone(TM)
004: Open Sourced User Interface Library for
005: Internet Development with Java
006:
007: Millstone is a registered trademark of IT Mill Ltd
008: Copyright (C) 2000-2005 IT Mill Ltd
009:
010: *************************************************************************
011:
012: This library is free software; you can redistribute it and/or
013: modify it under the terms of the GNU Lesser General Public
014: license version 2.1 as published by the Free Software Foundation.
015:
016: This library is distributed in the hope that it will be useful,
017: but WITHOUT ANY WARRANTY; without even the implied warranty of
018: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: Lesser General Public License for more details.
020:
021: You should have received a copy of the GNU Lesser General Public
022: License along with this library; if not, write to the Free Software
023: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024:
025: *************************************************************************
026:
027: For more information, contact:
028:
029: IT Mill Ltd phone: +358 2 4802 7180
030: Ruukinkatu 2-4 fax: +358 2 4802 7181
031: 20540, Turku email: info@itmill.com
032: Finland company www: www.itmill.com
033:
034: Primary source for MillStone information and releases: www.millstone.org
035:
036: ********************************************************************** */
037:
038: package org.millstone.base.ui;
039:
040: import java.net.URL;
041: import java.util.Collections;
042: import java.util.Iterator;
043: import java.util.LinkedList;
044: import java.util.List;
045:
046: import org.millstone.base.Application;
047: import org.millstone.base.terminal.PaintException;
048: import org.millstone.base.terminal.PaintTarget;
049: import org.millstone.base.terminal.Resource;
050:
051: /** <p>An application frame window component. This component implements a
052: * window that contains a hierarchical set of frames. Each frame can contain
053: * a web-page, window or a set of frames that divides the space horizontally
054: * or vertically.</p>
055: *
056: * <p>A <code>FrameWindow</code> can't contain any components directly (as
057: * it contains only a set of frames) and thus the container interface
058: * methods do nothing.</p>
059: *
060: * @author IT Mill Ltd.
061: * @version 3.1.1
062: * @since 3.0
063: */
064: public class FrameWindow extends Window {
065:
066: private Frameset frameset = new Frameset();
067:
068: /** <p>Constructs a new frame window.
069: *
070: */
071: public FrameWindow() {
072: }
073:
074: /** <p>Constructs a new frame window.
075: *
076: * @param caption title of the window
077: */
078: public FrameWindow(String caption) {
079: super (caption);
080: }
081:
082: /** Gets the window's UIDL tag.
083: *
084: * @return window's UIDL tag as <code>String</code>
085: */
086: public String getTag() {
087: return "framewindow";
088: }
089:
090: /** Gets the main frameset of the window. This set contains all the
091: * top-level frames of the window. New contents are added by adding
092: * frames to this frameset.
093: *
094: * @return top-level frame set of this frame window
095: */
096: public Frameset getFrameset() {
097: return frameset;
098: }
099:
100: /** Paints the window contents.
101: *
102: * @param target A paint target event
103: * @throws PaintException if the paint operation fails
104: *
105: * @see org.millstone.base.ui.AbstractComponent#paintContent(PaintTarget)
106: */
107: public void paintContent(PaintTarget target) throws PaintException {
108:
109: super .paintContent(target);
110:
111: // Paint frameset
112: getFrameset().paint(target);
113: }
114:
115: /** An individual frame that contains either a window or the contents of the
116: * url set to frame.
117: *
118: * <p>The frames can be only created to framesets using the
119: * <code>newFrame()</code> functions of the frameset.</p>
120: */
121: public class Frame {
122:
123: /** URL of the frame contents */
124: private URL url;
125:
126: /** Name of the frame */
127: private String name;
128:
129: /** Window connected to frame or null */
130: private Window window;
131:
132: /** Window connected to frame or null */
133: private Resource resource;
134:
135: /** String representation of the width */
136: private String width = "*";
137:
138: /** Parent frameset */
139: protected Frameset parentFrameset;
140:
141: /** URL of the frame */
142: public URL getURL() {
143: return window == null ? url : window.getURL();
144: }
145:
146: /** Get the parent frameset */
147: public Frameset getParentFrameset() {
148: return parentFrameset;
149: }
150:
151: /** Name of the freame */
152: public String getName() {
153: return window == null ? name : window.getName();
154: }
155:
156: /** Window connected to frame */
157: public Window getWindow() {
158: return window;
159: }
160:
161: /** Resource connected to frame */
162: public Resource getResource() {
163: return resource;
164: }
165:
166: /** Absolute width/height of the frame in pixels */
167: public void setAbsoluteSize(int widthInPixels) {
168: width = String.valueOf(widthInPixels);
169: requestRepaint();
170: }
171:
172: /** Set the frame size to be freely specified by the terminal */
173: public void setFreeSize() {
174: width = "*";
175: requestRepaint();
176: }
177:
178: /** Set the frame width/height as a percentage of the containing
179: * frameset size */
180: public void setRelativeSize(int widthInPercents) {
181: if (widthInPercents < 0 || widthInPercents > 100)
182: throw new IllegalArgumentException(
183: "Relative width must "
184: + "be between 0% and 100%");
185: width = String.valueOf(widthInPercents) + "%";
186: requestRepaint();
187: }
188:
189: /** Paint the frame */
190: private void paint(PaintTarget target) throws PaintException {
191: target.startTag("frame");
192: if (getResource() != null)
193: target.addAttribute("src", getResource());
194: else
195: target.addAttribute("src", getURL().toString());
196: target.addAttribute("name", getName());
197: target.endTag("frame");
198: }
199: }
200:
201: /** Vertical or horizontal set of frames */
202: public class Frameset extends Frame {
203:
204: /** List of frames ordered from left to right or from top to bottom */
205: private LinkedList frames = new LinkedList();
206:
207: /** True iff the frames are on top of each other. If false the frames
208: * are side by side.
209: */
210: private boolean vertical = false;
211:
212: /** Get a list of frames.
213: *
214: * @return unmodifiable list of frames.
215: */
216: public List getFrames() {
217: return Collections.unmodifiableList(frames);
218: }
219:
220: /** Create new frame containing a window.
221: *
222: * <p>The new frame will be in the end of the frames list.</p>
223: */
224: public Frame newFrame(Window window) {
225: return newFrame(window, size());
226: }
227:
228: /** Create new frame containing a window.
229: *
230: * <p>The new frame will be put before the frame identified
231: * by the given index. The indexes of the frame previously in the
232: * given position and all the positions after it are incremented
233: * by one.</p>
234: */
235: public Frame newFrame(Window window, int index) {
236: Frame f = new Frame();
237: f.window = window;
238: f.parentFrameset = this ;
239: frames.add(index, f);
240: if (getApplication() != null)
241: getApplication().addWindow(window);
242: requestRepaint();
243: return f;
244: }
245:
246: /** Create new frame containing a url.
247: *
248: * <p>The new frame will be put in the end of the frames list..</p>
249: */
250: public Frame newFrame(URL url, String name) {
251: return newFrame(url, name, size());
252: }
253:
254: /** Create new frame containing a resource.
255: *
256: * <p>The new frame will be put in the end of the frames list..</p>
257: */
258: public Frame newFrame(Resource resource, String name) {
259: return newFrame(resource, name, size());
260: }
261:
262: /** Create new frame containing a url.
263: *
264: * <p>The new frame will be put before the frame identified
265: * by the given index. The indexes of the frame previously in the
266: * given position and all the positions after it are incremented
267: * by one.</p>
268: */
269: public Frame newFrame(URL url, String name, int index) {
270: Frame f = new Frame();
271: f.url = url;
272: f.name = name;
273: f.parentFrameset = this ;
274: frames.add(index, f);
275: requestRepaint();
276: return f;
277: }
278:
279: /** Create new frame containing a resource.
280: *
281: * <p>The new frame will be put before the frame identified
282: * by the given index. The indexes of the frame previously in the
283: * given position and all the positions after it are incremented
284: * by one.</p>
285: */
286: public Frame newFrame(Resource resource, String name, int index) {
287: Frame f = new Frame();
288: f.resource = resource;
289: f.name = name;
290: f.parentFrameset = this ;
291: frames.add(index, f);
292: requestRepaint();
293: return f;
294: }
295:
296: /** Create new frameset.
297: *
298: * <p>The new frame will be put before the frame identified
299: * by the given index. The indexes of the frame previously in the
300: * given position and all the positions after it are incremented
301: * by one.</p>
302: */
303: public Frameset newFrameset(boolean isVertical, int index) {
304: Frameset f = new Frameset();
305: f.setVertical(isVertical);
306: f.parentFrameset = this ;
307: frames.add(index, f);
308: requestRepaint();
309: return f;
310: }
311:
312: /** Remove a frame from this frameset */
313: public void removeFrame(Frame frame) {
314: frames.remove(frame);
315: frame.parentFrameset = null;
316: requestRepaint();
317: }
318:
319: /** Remove all frames from this frameset */
320: public void removeAllFrames() {
321: for (Iterator i = frames.iterator(); i.hasNext();)
322: ((Frame) i.next()).parentFrameset = null;
323: frames.clear();
324: requestRepaint();
325: }
326:
327: /** Number of frames in this frameset */
328: public int size() {
329: return frames.size();
330: }
331:
332: /** Set the framaset to be vertical.
333: *
334: * <p>By setting this true, the frames will be ordered on top
335: * of each other from top to bottom. Setting this false, the
336: * frames will be ordered side by side from left to right.</p>
337: */
338: public void setVertical(boolean isVertical) {
339: this .vertical = isVertical;
340: requestRepaint();
341: }
342:
343: /** Check if the frameset is vertical.
344: *
345: * <p>If this is true, the frames will be ordered on top
346: * of each other from top to bottom, otherwise the
347: * frames will be ordered side by side from left to right.</p>
348: */
349: public boolean isVertical() {
350: return vertical;
351: }
352:
353: /** Get frame by name.
354: * @return Frame having the given name or null if the frame is
355: * not found
356: */
357: public Frame getFrame(String name) {
358: if (name == null)
359: return null;
360: for (Iterator i = frames.iterator(); i.hasNext();) {
361: Frame f = (Frame) i.next();
362: if (name.equals(f.getName()))
363: return f;
364: }
365: return null;
366: }
367:
368: /** Get frame by index.
369: * @return Frame having the given index or null if the frame is
370: * not found
371: */
372: public Frame getFrame(int index) {
373: if (index >= 0 && index < frames.size())
374: return (Frame) frames.get(index);
375: return null;
376: }
377:
378: /** Paint the frameset */
379: private void paint(PaintTarget target) throws PaintException {
380: target.startTag("frameset");
381: if (!frames.isEmpty()) {
382: StringBuffer widths = null;
383: for (Iterator i = frames.iterator(); i.hasNext();) {
384: Frame f = (Frame) i.next();
385: if (widths == null)
386: widths = new StringBuffer();
387: else
388: widths.append(',');
389: widths.append(f.width);
390: }
391: if (vertical)
392: target.addAttribute("rows", widths.toString());
393: else
394: target.addAttribute("cols", widths.toString());
395: for (Iterator i = frames.iterator(); i.hasNext();) {
396: Frame f = (Frame) i.next();
397: if (Frameset.class.isAssignableFrom(f.getClass()))
398: ((Frameset) f).paint(target);
399: else
400: f.paint(target);
401: }
402: }
403: target.endTag("frameset");
404: }
405:
406: /** Set the application for all the frames in this frameset */
407: private void setApplication(Application fromApplication,
408: Application toApplication) {
409: for (Iterator i = frames.iterator(); i.hasNext();) {
410: Frame f = (Frame) i.next();
411: if (f instanceof Frameset)
412: ((Frameset) f).setApplication(fromApplication,
413: toApplication);
414: else if (f.window != null) {
415: if (toApplication == null) {
416: fromApplication.removeWindow(f.window);
417: } else
418: toApplication.addWindow(f.window);
419: }
420: }
421: }
422: }
423:
424: /** Setting the application for frame window also sets the application
425: * for all the frames.
426: * @see org.millstone.base.ui.Window#setApplication(Application)
427: */
428: public void setApplication(Application application) {
429: Application fromApplication = getApplication();
430: super .setApplication(application);
431: Frameset fs = getFrameset();
432: if (fs != null)
433: fs.setApplication(fromApplication, application);
434: }
435:
436: /** Frame windows does not support scrolling.
437: */
438: public boolean isScrollable() {
439: return false;
440: }
441:
442: /** Frame windows does not support scrolling.
443: *
444: * @see org.millstone.base.terminal.Scrollable#setScrollable(boolean)
445: */
446: public void setScrollable(boolean isScrollingEnabled) {
447: }
448:
449: /** Frame windows does not support scrolling.
450: *
451: * @see org.millstone.base.terminal.Scrollable#setScrollOffsetX(int)
452: */
453: public void setScrollOffsetX(int pixelsScrolledLeft) {
454: }
455:
456: /** Frame windows does not support scrolling.
457: *
458: * @see org.millstone.base.terminal.Scrollable#setScrollOffsetY(int)
459: */
460: public void setScrollOffsetY(int pixelsScrolledDown) {
461: }
462:
463: /** Frame window does not support adding components directly.
464: *
465: * <p>To add component to frame window, normal window must be
466: * first created and then attached to frame window as a frame.</p>
467: *
468: * @see org.millstone.base.ui.ComponentContainer#addComponent(Component)
469: * @throws UnsupportedOperationException if invoked.
470: */
471: public void addComponent(Component c)
472: throws UnsupportedOperationException {
473: throw new UnsupportedOperationException();
474: }
475:
476: }
|