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