001: /*
002: * $RCSfile: MainFrame.java,v $
003: *
004: * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * - Redistribution of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * - Redistribution in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * Neither the name of Sun Microsystems, Inc. or the names of
019: * contributors may be used to endorse or promote products derived
020: * from this software without specific prior written permission.
021: *
022: * This software is provided "AS IS," without a warranty of any
023: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
024: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
025: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
026: * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
027: * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
028: * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
029: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
030: * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
031: * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
032: * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
033: * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
034: * POSSIBILITY OF SUCH DAMAGES.
035: *
036: * You acknowledge that this software is not designed, licensed or
037: * intended for use in the design, construction, operation or
038: * maintenance of any nuclear facility.
039: *
040: * $Revision: 1.4 $
041: * $Date: 2007/02/09 17:20:10 $
042: * $State: Exp $
043: */
044:
045: // MainFrame - run an Applet as an application
046: //
047: // Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. All rights reserved.
048: //
049: // Redistribution and use in source and binary forms, with or without
050: // modification, are permitted provided that the following conditions
051: // are met:
052: // 1. Redistributions of source code must retain the above copyright
053: // notice, this list of conditions and the following disclaimer.
054: // 2. Redistributions in binary form must reproduce the above copyright
055: // notice, this list of conditions and the following disclaimer in the
056: // documentation and/or other materials provided with the distribution.
057: //
058: // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
059: // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
060: // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
061: // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
062: // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
063: // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
064: // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
065: // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
066: // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
067: // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
068: // SUCH DAMAGE.
069: //
070: // Visit the ACME Labs Java page for up-to-date versions of this and other
071: // fine Java utilities: http://www.acme.com/java/
072: // ---------------------------------------------------------------------
073: package com.sun.j3d.utils.applet;
074:
075: import java.applet.*;
076: import java.awt.*;
077: import java.awt.event.*;
078: import java.awt.image.*;
079: import java.net.*;
080: import java.io.*;
081: import java.util.*;
082:
083: /// Run an Applet as an application.
084: // <P>
085: // Using this class you can add a trivial main program to any Applet
086: // and run it directly, as well as from a browser or the appletviewer.
087: // And unlike some versions of this concept, MainFrame implements both
088: // images and sound.
089: // <P>
090: // Sample main program:
091: // <BLOCKQUOTE><PRE>
092: // public static void main( String[] args )
093: // {
094: // new Acme.MainFrame( new ThisApplet(), args, 400, 400 );
095: // }
096: // </PRE></BLOCKQUOTE>
097: // The only methods you need to know about are the constructors.
098: // <P>
099: // You can specify Applet parameters on the command line, as name=value.
100: // For instance, the equivalent of:
101: // <BLOCKQUOTE><PRE>
102: // <PARAM NAME="pause" VALUE="200">
103: // </PRE></BLOCKQUOTE>
104: // would just be:
105: // <BLOCKQUOTE><PRE>
106: // pause=200
107: // </PRE></BLOCKQUOTE>
108: // You can also specify three special parameters:
109: // <BLOCKQUOTE><PRE>
110: // width=N Width of the Applet.
111: // height=N Height of the Applet.
112: // barebones=true Leave off the menu bar and status area.
113: // </PRE></BLOCKQUOTE>
114: // <P>
115: // <A HREF="/resources/classes/Acme/MainFrame.java">Fetch the software.</A><BR>
116: // <A HREF="/resources/classes/Acme.tar.Z">Fetch the entire Acme package.</A>
117:
118: public class MainFrame extends Frame implements Runnable, AppletStub,
119: AppletContext {
120:
121: private String[] args = null;
122: private static int instances = 0;
123: private String name;
124: private boolean barebones = true;
125: private Applet applet;
126: private Label label = null;
127: private Dimension appletSize;
128:
129: private static final String PARAM_PROP_PREFIX = "parameter.";
130:
131: /// Constructor with everything specified.
132: public MainFrame(Applet applet, String[] args, int width, int height) {
133: build(applet, args, width, height);
134: }
135:
136: /// Constructor with no default width/height.
137: public MainFrame(Applet applet, String[] args) {
138: build(applet, args, -1, -1);
139: }
140:
141: /// Constructor with no arg parsing.
142: public MainFrame(Applet applet, int width, int height) {
143: build(applet, null, width, height);
144: }
145:
146: // Internal constructor routine.
147: private void build(Applet applet, String[] args, int width,
148: int height) {
149: ++instances;
150: this .applet = applet;
151: this .args = args;
152: applet.setStub(this );
153: name = applet.getClass().getName();
154: setTitle(name);
155:
156: // Set up properties.
157: Properties props = System.getProperties();
158: props.put("browser", "Acme.MainFrame");
159: props.put("browser.version", "11jul96");
160: props.put("browser.vendor", "Acme Laboratories");
161: props.put("browser.vendor.url", "http://www.acme.com/");
162:
163: // Turn args into parameters by way of the properties list.
164: if (args != null)
165: parseArgs(args, props);
166:
167: // If width and height are specified in the parameters, override
168: // the compiled-in values.
169: String widthStr = getParameter("width");
170: if (widthStr != null) {
171: width = Integer.parseInt(widthStr);
172: }
173:
174: String heightStr = getParameter("height");
175: if (heightStr != null) {
176: height = Integer.parseInt(heightStr);
177: }
178:
179: // Were width and height specified somewhere?
180: if ((width == -1) || (height == -1)) {
181: System.err.println("Width and height must be specified.");
182: return;
183: }
184:
185: // Do we want to run bare-bones?
186: String bonesStr = getParameter("barebones");
187: if ((bonesStr != null) && bonesStr.equals("true")) {
188: barebones = true;
189: }
190:
191: // Lay out components.
192: setLayout(new BorderLayout());
193: add("Center", applet);
194:
195: // Set up size.
196: pack();
197: validate();
198: appletSize = applet.getSize();
199: applet.setSize(width, height);
200: setVisible(true);
201:
202: /*
203: Added WindowListener inner class to detect close events.
204: */
205: SecurityManager sm = System.getSecurityManager();
206: boolean doExit = true;
207:
208: if (sm != null) {
209: try {
210: sm.checkExit(0);
211: } catch (SecurityException e) {
212: doExit = false;
213: }
214: }
215:
216: final boolean _doExit = doExit;
217:
218: addWindowListener(new WindowAdapter() {
219: public void windowClosing(WindowEvent winEvent) {
220: if (MainFrame.this .applet != null) {
221: MainFrame.this .applet.destroy();
222: }
223: Window w = winEvent.getWindow();
224: w.hide();
225: try {
226: w.dispose();
227: } catch (IllegalStateException e) {
228: }
229:
230: if (_doExit) {
231: System.exit(0);
232: }
233: }
234: });
235:
236: // Start a separate thread to call the applet's init() and start()
237: // methods, in case they take a long time.
238: (new Thread(this )).start();
239: }
240:
241: // Turn command-line arguments into Applet parameters, by way of the
242: // properties list.
243: private static void parseArgs(String[] args, Properties props) {
244: String arg;
245:
246: for (int i = 0; i < args.length; ++i) {
247: arg = args[i];
248: int ind = arg.indexOf('=');
249: if (ind == -1) {
250: props.put(PARAM_PROP_PREFIX + arg.toLowerCase(), "");
251: } else {
252: props.put(PARAM_PROP_PREFIX
253: + arg.substring(0, ind).toLowerCase(), arg
254: .substring(ind + 1));
255: }
256: }
257: }
258:
259: // Methods from Runnable.
260:
261: /// Separate thread to call the applet's init() and start() methods.
262: public void run() {
263: showStatus(name + " initializing...");
264: applet.init();
265: validate();
266: showStatus(name + " starting...");
267: applet.start();
268: validate();
269: showStatus(name + " running...");
270: }
271:
272: // Methods from AppletStub.
273: public boolean isActive() {
274: return true;
275: }
276:
277: public URL getDocumentBase() {
278: // Returns the current directory.
279: String dir = System.getProperty("user.dir");
280: String urlDir = dir.replace(File.separatorChar, '/');
281: try {
282: return new URL("file:" + urlDir + "/");
283: } catch (MalformedURLException e) {
284: return null;
285: }
286: }
287:
288: public URL getCodeBase() {
289: // Hack: loop through each item in CLASSPATH, checking if
290: // the appropriately named .class file exists there. But
291: // this doesn't account for .zip files.
292: String path = System.getProperty("java.class.path");
293: Enumeration st = new StringTokenizer(path, ":");
294: while (st.hasMoreElements()) {
295: String dir = (String) st.nextElement();
296: String filename = dir + File.separatorChar + name
297: + ".class";
298: File file = new File(filename);
299: if (file.exists()) {
300: String urlDir = dir.replace(File.separatorChar, '/');
301: try {
302: return new URL("file:" + urlDir + "/");
303: } catch (MalformedURLException e) {
304: return null;
305: }
306: }
307: }
308: return null;
309: }
310:
311: public String getParameter(String name) {
312: // Return a parameter via the munged names in the properties list.
313: return System.getProperty(PARAM_PROP_PREFIX
314: + name.toLowerCase());
315: }
316:
317: public void appletResize(int width, int height) {
318: // Change the frame's size by the same amount that the applet's
319: // size is changing.
320: Dimension frameSize = getSize();
321: frameSize.width += width - appletSize.width;
322: frameSize.height += height - appletSize.height;
323: setSize(frameSize);
324: appletSize = applet.getSize();
325: }
326:
327: public AppletContext getAppletContext() {
328: return this ;
329: }
330:
331: // Methods from AppletContext.
332: public AudioClip getAudioClip(URL url) {
333: // This is an internal undocumented routine. However, it
334: // also provides needed functionality not otherwise available.
335: // I suspect that in a future release, JavaSoft will add an
336: // audio content handler which encapsulates this, and then
337: // we can just do a getContent just like for images.
338: return new sun.applet.AppletAudioClip(url);
339: }
340:
341: public Image getImage(URL url) {
342: Toolkit tk = Toolkit.getDefaultToolkit();
343: try {
344: ImageProducer prod = (ImageProducer) url.getContent();
345: return tk.createImage(prod);
346: } catch (IOException e) {
347: return null;
348: }
349: }
350:
351: public Applet getApplet(String name) {
352: // Returns this Applet or nothing.
353: if (name.equals(this .name)) {
354: return applet;
355: }
356: return null;
357: }
358:
359: public Enumeration getApplets() {
360: // Just yields this applet.
361: Vector v = new Vector();
362: v.addElement(applet);
363: return v.elements();
364: }
365:
366: public void showDocument(URL url) {
367: // Ignore.
368: }
369:
370: public void showDocument(URL url, String target) {
371: // Ignore.
372: }
373:
374: public void showStatus(String status) {
375: if (label != null) {
376: label.setText(status);
377: }
378: }
379:
380: public void setStream(String key, java.io.InputStream stream) {
381: throw new RuntimeException("Not Implemented");
382: // TODO implement setStream method
383: }
384:
385: public java.io.InputStream getStream(String key) {
386: throw new RuntimeException("Not Implemented");
387: // TODO implement getStream method
388: }
389:
390: public java.util.Iterator getStreamKeys() {
391: throw new RuntimeException("Not Implemented");
392: // TODO implement getStreamKeys method
393: }
394: }
|