001 /* 002 * Created on Jul 10, 2008 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 005 * in compliance with the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the License 010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 011 * or implied. See the License for the specific language governing permissions and limitations under 012 * the License. 013 * 014 * Copyright @2008-2010 the original author or authors. 015 */ 016 package org.fest.swing.applet; 017 018 import static java.awt.BorderLayout.CENTER; 019 import static java.awt.BorderLayout.SOUTH; 020 import static javax.swing.BorderFactory.*; 021 import static javax.swing.SwingUtilities.invokeLater; 022 import static javax.swing.SwingUtilities.isEventDispatchThread; 023 import static javax.swing.border.BevelBorder.LOWERED; 024 import static org.fest.swing.edt.GuiActionRunner.execute; 025 import static org.fest.util.Strings.concat; 026 027 import java.applet.Applet; 028 import java.applet.AppletStub; 029 import java.awt.BorderLayout; 030 import java.awt.Dimension; 031 import java.util.Map; 032 033 import javax.swing.JFrame; 034 import javax.swing.JLabel; 035 036 import org.fest.swing.annotation.RunsInCurrentThread; 037 import org.fest.swing.annotation.RunsInEDT; 038 import org.fest.swing.edt.GuiQuery; 039 040 /** 041 * Understands a window that displays an <code>{@link Applet}</code>. 042 * <p> 043 * Typical usage: 044 * <pre> 045 * AppletViewer viewer = AppletViewer.newViewer(new MyApplet()); 046 * 047 * // test the applet, viewer can be wrapped with a FrameFixture. 048 * FrameFixture viewerFixture = new FrameFixture(viewer); 049 * 050 * viewer.unloadApplet() // stops and destroys the applet 051 * viewerFixture.cleanUp(); 052 * </pre> 053 * <p> 054 * <b>Note:</b> In version 1.2, due to bug <a href="http://jira.codehaus.org/browse/FEST-219" target="_blank">FEST-219</a> 055 * constructors in this class have been replaced with the static factory methods <code>newViewer</code>. It was not 056 * possible to just deprecate them. To ensure correct behavior of the applet viewer, they had to be made unaccessible to 057 * client code. 058 * </p> 059 * </p> 060 * 061 * @author Alex Ruiz 062 * @author Yvonne Wang 063 */ 064 public class AppletViewer extends JFrame implements StatusDisplay { 065 066 private static final long serialVersionUID = 1L; 067 068 private static final String APPLET_VIEWER_TITLE = "Applet Viewer: "; 069 private static final String APPLET_LOADED_MESSAGE = "Applet loaded"; 070 private static final Dimension DEFAULT_SIZE = new Dimension(100, 100); 071 072 private final JLabel statusLabel = new JLabel(); 073 074 private final Applet applet; 075 private transient AppletStub stub; 076 private boolean loaded; 077 078 /** 079 * Creates a new </code>{@link AppletViewer}</code>. This factory method creates new instances of 080 * <code>{@link BasicAppletStub}</code> and <code>{@link BasicAppletContext}</code>. 081 * <p> 082 * <b>Note:</b> This method is executed in the event dispatch thread (EDT.) 083 * </p> 084 * @param applet the applet to view. 085 * @return the created <code>AppletViewer</code>. 086 * @throws NullPointerException if <code>applet</code> is <code>null</code>. 087 * @since 1.2 088 */ 089 @RunsInEDT 090 public static AppletViewer newViewer(Applet applet) { 091 AppletViewer viewer = createInEDT(applet); 092 viewer.appletStub(new BasicAppletStub(viewer, new BasicAppletContext(viewer))); 093 return viewer; 094 } 095 096 /** 097 * Creates a new </code>{@link AppletViewer}</code>. This factory method creates new instances of 098 * <code>{@link BasicAppletStub}</code> and <code>{@link BasicAppletContext}</code>. 099 * <p> 100 * <b>Note:</b> This method is executed in the event dispatch thread (EDT.) 101 * </p> 102 * @param applet the applet to view. 103 * @param parameters the parameters included in an applet HTML tag. 104 * @return the created <code>AppletViewer</code>. 105 * @throws NullPointerException if <code>applet</code> is <code>null</code>. 106 * @throws NullPointerException if <code>parameters</code> is <code>null</code>. 107 * @since 1.2 108 */ 109 @RunsInEDT 110 public static AppletViewer newViewer(Applet applet, Map<String, String> parameters) { 111 AppletViewer viewer = createInEDT(applet); 112 viewer.appletStub(new BasicAppletStub(viewer, new BasicAppletContext(viewer), parameters)); 113 return viewer; 114 } 115 116 117 /** 118 * Creates a new </code>{@link AppletViewer}</code>. 119 * <p> 120 * <b>Note:</b> This method is executed in the event dispatch thread (EDT.) 121 * </p> 122 * @param applet the applet to view. 123 * @param stub the applet's stub. 124 * @return the created <code>AppletViewer</code>. 125 * @throws NullPointerException if <code>applet</code> is <code>null</code>. 126 * @throws NullPointerException if <code>stub</code> is <code>null</code>. 127 * @since 1.2 128 */ 129 @RunsInEDT 130 public static AppletViewer newViewer(Applet applet, AppletStub stub) { 131 AppletViewer viewer = createInEDT(applet); 132 viewer.appletStub(stub); 133 return viewer; 134 } 135 136 @RunsInEDT 137 private static AppletViewer createInEDT(final Applet applet) { 138 return execute(new GuiQuery<AppletViewer>() { 139 protected AppletViewer executeInEDT() { 140 return new AppletViewer(applet); 141 } 142 }); 143 } 144 145 private AppletViewer(Applet applet) { 146 if (applet == null) throw new NullPointerException("The applet to load should not be null"); 147 this.applet = applet; 148 setUpFrame(); 149 addContent(); 150 } 151 152 private void setUpFrame() { 153 setTitle(concat(APPLET_VIEWER_TITLE, applet.getClass().getName())); 154 setSize(DEFAULT_SIZE); 155 setLayout(new BorderLayout()); 156 } 157 158 private void addContent() { 159 add(applet, CENTER); 160 statusLabel.setBorder(createCompoundBorder(createBevelBorder(LOWERED), createEmptyBorder(2, 5, 2, 5))); 161 statusLabel.setName("status"); 162 add(statusLabel, SOUTH); 163 } 164 165 private void appletStub(AppletStub newAppletStub) { 166 if (newAppletStub == null) throw new NullPointerException("The AppletStub should not be null"); 167 stub = newAppletStub; 168 applet.setStub(stub); 169 setUpApplet(); 170 } 171 172 private void setUpApplet() { 173 loadApplet(); 174 showStatus(APPLET_LOADED_MESSAGE); 175 } 176 177 /** 178 * Initializes and starts the applet in this viewer. 179 */ 180 public void reloadApplet() { 181 if (loaded) unloadApplet(); 182 loadApplet(); 183 } 184 185 private void loadApplet() { 186 applet.init(); 187 applet.start(); 188 loaded = true; 189 } 190 191 /** 192 * Stops and destroys the applet loaded in this viewer. This method should be called before closing or disposing this 193 * viewer. 194 */ 195 public void unloadApplet() { 196 applet.stop(); 197 applet.destroy(); 198 loaded = false; 199 } 200 201 /** 202 * Indicates whether the applet in this viewer is loaded or not. 203 * @return <code>true</code> if this applet is loaded, <code>false</code> otherwise. 204 */ 205 public boolean appletLoaded() { return loaded; } 206 207 /** 208 * Displays the given status message. This method is executed in the event dispatch thread (EDT.) 209 * @param status the status to display. 210 */ 211 @RunsInEDT 212 public void showStatus(final String status) { 213 if (isEventDispatchThread()) { 214 setStatus(status); 215 return; 216 } 217 invokeLater(new Runnable() { 218 public void run() { 219 setStatus(status); 220 } 221 }); 222 } 223 224 @RunsInCurrentThread 225 private void setStatus(String status) { 226 statusLabel.setText(status); 227 } 228 229 /** 230 * Returns the applet displayed in this viewer. 231 * @return the applet displayed in this viewer. 232 */ 233 public Applet applet() { 234 return applet; 235 } 236 237 /** 238 * Returns the <code>{@link AppletStub}</code> in this viewer. 239 * @return the <code>AppletStub</code> in this viewer. 240 */ 241 public AppletStub stub() { 242 return stub; 243 } 244 }