| [ Web Proxy ] |
| Viewing: https://raw.githubusercontent.com/h2oop/processing/master/core/src/processing/core/PApplet.java | [Back] [Original] |
* public class ExampleFrame extends Frame {
*
* public ExampleFrame() {
* super("Embedded PApplet");
*
* setLayout(new BorderLayout());
* PApplet embed = new Embedded();
* add(embed, BorderLayout.CENTER);
*
* // important to call this whenever embedding a PApplet.
* // It ensures that the animation thread is started and
* // that other internal variables are properly set.
* embed.init();
* }
* }
*
* public class Embedded extends PApplet {
*
* public void setup() {
* // original setup code here ...
* size(400, 400);
*
* // prevent thread from starving everything else
* noLoop();
* }
*
* public void draw() {
* // drawing code goes here
* }
*
* public void mousePressed() {
* // do something based on mouse movement
*
* // update the screen (run draw once)
* redraw();
* }
* }
*
* @usage Web & Application
*/
public class PApplet extends Applet
implements PConstants, Runnable,
MouseListener, MouseWheelListener, MouseMotionListener, KeyListener, FocusListener
{
/**
* Full name of the Java version (i.e. 1.5.0_11).
* Prior to 0125, this was only the first three digits.
*/
public static final String javaVersionName =
System.getProperty("java.version");
/**
* Version of Java that's in use, whether 1.1 or 1.3 or whatever,
* stored as a float.
* * Note that because this is stored as a float, the values may * not be exactly 1.3 or 1.4. Instead, make sure you're * comparing against 1.3f or 1.4f, which will have the same amount * of error (i.e. 1.40000001). This could just be a double, but * since Processing only uses floats, it's safer for this to be a float * because there's no good way to specify a double with the preproc. */ public static final float javaVersion = new Float(javaVersionName.substring(0, 3)).floatValue(); /** * Current platform in use. *
* Equivalent to System.getProperty("os.name"), just used internally. */ /** * Current platform in use, one of the * PConstants WINDOWS, MACOSX, MACOS9, LINUX or OTHER. */ static public int platform; /** * Name associated with the current 'platform' (see PConstants.platformNames) */ //static public String platformName; static { String osname = System.getProperty("os.name"); if (osname.indexOf("Mac") != -1) { platform = MACOSX; } else if (osname.indexOf("Windows") != -1) { platform = WINDOWS; } else if (osname.equals("Linux")) { // true for the ibm vm platform = LINUX; } else { platform = OTHER; } } /** * Setting for whether to use the Quartz renderer on OS X. The Quartz * renderer is on its way out for OS X, but Processing uses it by default * because it's much faster than the Sun renderer. In some cases, however, * the Quartz renderer is preferred. For instance, fonts are less thick * when using the Sun renderer, so to improve how fonts look, * change this setting before you call PApplet.main(). *
* static public void main(String[] args) {
* PApplet.useQuartz = false;
* PApplet.main(new String[] { "YourSketch" });
* }
*
* This setting must be called before any AWT work happens, so that's why
* it's such a terrible hack in how it's employed here. Calling setProperty()
* inside setup() is a joke, since it's long since the AWT has been invoked.
*
* On OS X with a retina display, this option is ignored, because Apple's
* Java implementation takes over and forces the Quartz renderer.
*/
// static public boolean useQuartz = true;
static public boolean useQuartz = false;
/**
* Whether to use native (AWT) dialogs for selectInput and selectOutput.
* The native dialogs on Linux tend to be pretty awful. With selectFolder()
* this is ignored, because there is no native folder selector, except on
* Mac OS X. On OS X, the native folder selector will be used unless
* useNativeSelect is set to false.
*/
static public boolean useNativeSelect = (platform != LINUX);
// /**
// * Modifier flags for the shortcut key used to trigger menus.
// * (Cmd on Mac OS X, Ctrl on Linux and Windows)
// */
// static public final int MENU_SHORTCUT =
// Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
/** The PGraphics renderer associated with this PApplet */
public PGraphics g;
/** The frame containing this applet (if any) */
public Frame frame;
// disabled on retina inside init()
boolean useActive = true;
// boolean useActive = false;
// boolean useStrategy = true;
boolean useStrategy = false;
Canvas canvas;
Method revalidateMethod;
// /**
// * Usually just 0, but with multiple displays, the X and Y coordinates of
// * the screen will depend on the current screen's position relative to
// * the other displays.
// */
// public int displayX;
// public int displayY;
/**
* ( begin auto-generated from screenWidth.xml )
*
* System variable which stores the width of the computer screen. For
* example, if the current screen resolution is 1024x768,
* displayWidth is 1024 and displayHeight is 768. These
* dimensions are useful when exporting full-screen applications.
* * This does not include the arguments passed in to PApplet itself. */ public String[] args; /** Path to sketch folder */ public String sketchPath; static final boolean DEBUG = false; // static final boolean DEBUG = true; /** Default width and height for applet when not specified */ static public final int DEFAULT_WIDTH = 100; static public final int DEFAULT_HEIGHT = 100; /** * Minimum dimensions for the window holding an applet. This varies between * platforms, Mac OS X 10.3 (confirmed with 10.7 and Java 6) can do any * height but requires at least 128 pixels width. Windows XP has another * set of limitations. And for all I know, Linux probably lets you make * windows with negative sizes. */ static public final int MIN_WINDOW_WIDTH = 128; static public final int MIN_WINDOW_HEIGHT = 128; /** * Gets set by main() if --present (old) or --full-screen (newer) are used, * and is returned by sketchFullscreen() when initializing in main(). */ // protected boolean fullScreen = false; /** * Exception thrown when size() is called the first time. *
* This is used internally so that setup() is forced to run twice
* when the renderer is changed. This is the only way for us to handle
* invoking the new renderer while also in the midst of rendering.
*/
static public class RendererChangeException extends RuntimeException { }
/**
* true if no size() command has been executed. This is used to wait until
* a size has been set before placing in the window and showing it.
*/
public boolean defaultSize;
/** Storage for the current renderer size to avoid re-allocation. */
Dimension currentSize = new Dimension();
// volatile boolean resizeRequest;
// volatile int resizeWidth;
// volatile int resizeHeight;
/**
* ( begin auto-generated from pixels.xml )
*
* Array containing the values for all the pixels in the display window.
* These values are of the color datatype. This array is the size of the
* display window. For example, if the image is 100x100 pixels, there will
* be 10000 values and if the window is 200x300 pixels, there will be 60000
* values. The index value defines the position of a value within
* the array. For example, the statement color b = pixels[230] will
* set the variable b to be equal to the value at that location in
* the array.
*
* Before accessing this array, the data must loaded with the
* loadPixels() function. After the array data has been modified,
* the updatePixels() function must be run to update the changes.
* Without loadPixels(), running the code may (or will in future
* releases) result in a NullPointerException.
*
* ( end auto-generated )
*
* @webref image:pixels
* @see PApplet#loadPixels()
* @see PApplet#updatePixels()
* @see PApplet#get(int, int, int, int)
* @see PApplet#set(int, int, int)
* @see PImage
*/
public int pixels[];
/**
* ( begin auto-generated from width.xml )
*
* System variable which stores the width of the display window. This value
* is set by the first parameter of the size() function. For
* example, the function call size(320, 240) sets the width
* variable to the value 320. The value of width is zero until
* size() is called.
*
* ( end auto-generated )
* @webref environment
* @see PApplet#height
* @see PApplet#size(int, int)
*/
public int width;
/**
* ( begin auto-generated from height.xml )
*
* System variable which stores the height of the display window. This
* value is set by the second parameter of the size() function. For
* example, the function call size(320, 240) sets the height
* variable to the value 240. The value of height is zero until
* size() is called.
*
* ( end auto-generated )
* @webref environment
* @see PApplet#width
* @see PApplet#size(int, int)
*/
public int height;
/**
* ( begin auto-generated from mouseX.xml )
*
* The system variable mouseX always contains the current horizontal
* coordinate of the mouse.
*
* ( end auto-generated )
* @webref input:mouse
* @see PApplet#mouseY
* @see PApplet#pmouseX
* @see PApplet#pmouseY
* @see PApplet#mousePressed
* @see PApplet#mousePressed()
* @see PApplet#mouseReleased()
* @see PApplet#mouseClicked()
* @see PApplet#mouseMoved()
* @see PApplet#mouseDragged()
* @see PApplet#mouseButton
* @see PApplet#mouseWheel(MouseEvent)
*
*
*/
public int mouseX;
/**
* ( begin auto-generated from mouseY.xml )
*
* The system variable mouseY always contains the current vertical
* coordinate of the mouse.
*
* ( end auto-generated )
* @webref input:mouse
* @see PApplet#mouseX
* @see PApplet#pmouseX
* @see PApplet#pmouseY
* @see PApplet#mousePressed
* @see PApplet#mousePressed()
* @see PApplet#mouseReleased()
* @see PApplet#mouseClicked()
* @see PApplet#mouseMoved()
* @see PApplet#mouseDragged()
* @see PApplet#mouseButton
* @see PApplet#mouseWheel(MouseEvent)
*
*/
public int mouseY;
/**
* ( begin auto-generated from pmouseX.xml )
*
* The system variable pmouseX always contains the horizontal
* position of the mouse in the frame previous to the current frame.
*
* You may find that pmouseX and pmouseY have different
* values inside draw() and inside events like mousePressed()
* and mouseMoved(). This is because they're used for different
* roles, so don't mix them. Inside draw(), pmouseX and
* pmouseY update only once per frame (once per trip through your
* draw()). But, inside mouse events, they update each time the
* event is called. If they weren't separated, then the mouse would be read
* only once per frame, making response choppy. If the mouse variables were
* always updated multiple times per frame, using line(pmouseX,
* pmouseY, mouseX, mouseY) inside draw() would have lots
* of gaps, because pmouseX may have changed several times in
* between the calls to line(). Use pmouseX and
* pmouseY inside draw() if you want values relative to the
* previous frame. Use pmouseX and pmouseY inside the mouse
* functions if you want continuous response.
*
* ( end auto-generated )
* @webref input:mouse
* @see PApplet#mouseX
* @see PApplet#mouseY
* @see PApplet#pmouseY
* @see PApplet#mousePressed
* @see PApplet#mousePressed()
* @see PApplet#mouseReleased()
* @see PApplet#mouseClicked()
* @see PApplet#mouseMoved()
* @see PApplet#mouseDragged()
* @see PApplet#mouseButton
* @see PApplet#mouseWheel(MouseEvent)
*/
public int pmouseX;
/**
* ( begin auto-generated from pmouseY.xml )
*
* The system variable pmouseY always contains the vertical position
* of the mouse in the frame previous to the current frame. More detailed
* information about how pmouseY is updated inside of draw()
* and mouse events is explained in the reference for pmouseX.
*
* ( end auto-generated )
* @webref input:mouse
* @see PApplet#mouseX
* @see PApplet#mouseY
* @see PApplet#pmouseX
* @see PApplet#mousePressed
* @see PApplet#mousePressed()
* @see PApplet#mouseReleased()
* @see PApplet#mouseClicked()
* @see PApplet#mouseMoved()
* @see PApplet#mouseDragged()
* @see PApplet#mouseButton
* @see PApplet#mouseWheel(MouseEvent)
*/
public int pmouseY;
/**
* previous mouseX/Y for the draw loop, separated out because this is
* separate from the pmouseX/Y when inside the mouse event handlers.
*/
protected int dmouseX, dmouseY;
/**
* pmouseX/Y for the event handlers (mousePressed(), mouseDragged() etc)
* these are different because mouse events are queued to the end of
* draw, so the previous position has to be updated on each event,
* as opposed to the pmouseX/Y that's used inside draw, which is expected
* to be updated once per trip through draw().
*/
protected int emouseX, emouseY;
/**
* Used to set pmouseX/Y to mouseX/Y the first time mouseX/Y are used,
* otherwise pmouseX/Y are always zero, causing a nasty jump.
*
* Just using (frameCount == 0) won't work since mouseXxxxx() * may not be called until a couple frames into things. *
* @deprecated Please refrain from using this variable, it will be removed * from future releases of Processing because it cannot be used consistently * across platforms and input methods. */ @Deprecated public boolean firstMouse; /** * ( begin auto-generated from mouseButton.xml ) * * Processing automatically tracks if the mouse button is pressed and which * button is pressed. The value of the system variable mouseButton * is either LEFT, RIGHT, or CENTER depending on which * button is pressed. * * ( end auto-generated ) * *
* If it's a coded key, i.e. UP/DOWN/CTRL/SHIFT/ALT,
* this will be set to CODED (0xffff or 65535).
*
* @webref input:keyboard
* @see PApplet#keyCode
* @see PApplet#keyPressed
* @see PApplet#keyPressed()
* @see PApplet#keyReleased()
*/
public char key;
/**
* ( begin auto-generated from keyCode.xml )
*
* The variable keyCode is used to detect special keys such as the
* UP, DOWN, LEFT, RIGHT arrow keys and ALT, CONTROL, SHIFT. When checking
* for these keys, it's first necessary to check and see if the key is
* coded. This is done with the conditional "if (key == CODED)" as shown in
* the example.
*
* The keys included in the ASCII specification (BACKSPACE, TAB, ENTER,
* RETURN, ESC, and DELETE) do not require checking to see if they key is
* coded, and you should simply use the key variable instead of
* keyCode If you're making cross-platform projects, note that the
* ENTER key is commonly used on PCs and Unix and the RETURN key is used
* instead on Macintosh. Check for both ENTER and RETURN to make sure your
* program will work for all platforms.
*
* For users familiar with Java, the values for UP and DOWN are simply
* shorter versions of Java's KeyEvent.VK_UP and KeyEvent.VK_DOWN. Other
* keyCode values can be found in the Java KeyEvent reference.
*
* ( end auto-generated )
*
*
* For the arrow keys, keyCode will be one of UP, DOWN, LEFT and RIGHT. * Also available are ALT, CONTROL and SHIFT. A full set of constants * can be obtained from java.awt.event.KeyEvent, from the VK_XXXX variables. * * @webref input:keyboard * @see PApplet#key * @see PApplet#keyPressed * @see PApplet#keyPressed() * @see PApplet#keyReleased() */ public int keyCode; /** * ( begin auto-generated from keyPressed_var.xml ) * * The boolean system variable keyPressed is true if any key * is pressed and false if no keys are pressed. * * ( end auto-generated ) * @webref input:keyboard * @see PApplet#key * @see PApplet#keyCode * @see PApplet#keyPressed() * @see PApplet#keyReleased() */ public boolean keyPressed; /** * The last KeyEvent object passed into a mouse function. * @deprecated Use a key event handler that passes an event instead. */ @Deprecated public KeyEvent keyEvent; /** * ( begin auto-generated from focused.xml ) * * Confirms if a Processing program is "focused", meaning that it is active * and will accept input from mouse or keyboard. This variable is "true" if * it is focused and "false" if not. This variable is often used when you * want to warn people they need to click on or roll over an applet before * it will work. * * ( end auto-generated ) * @webref environment */ public boolean focused = false; /** * Confirms if a Processing program is running inside a web browser. This * variable is "true" if the program is online and "false" if not. */ @Deprecated public boolean online = false; // This is deprecated because it's poorly named (and even more poorly // understood). Further, we'll probably be removing applets soon, in which // case this won't work at all. If you want this feature, you can check // whether getAppletContext() returns null. /** * Time in milliseconds when the applet was started. *
* Used by the millis() function. */ long millisOffset = System.currentTimeMillis(); /** * ( begin auto-generated from frameRate_var.xml ) * * The system variable frameRate contains the approximate frame rate * of the software as it executes. The initial value is 10 fps and is * updated with each frame. The value is averaged (integrated) over several * frames. As such, this value won't be valid until after 5-10 frames. * * ( end auto-generated ) * @webref environment * @see PApplet#frameRate(float) * @see PApplet#frameCount */ public float frameRate = 10; /** Last time in nanoseconds that frameRate was checked */ protected long frameRateLastNanos = 0; /** As of release 0116, frameRate(60) is called as a default */ protected float frameRateTarget = 60; protected long frameRatePeriod = 1000000000L / 60L; protected boolean looping; /** flag set to true when a redraw is asked for by the user */ protected boolean redraw; /** * ( begin auto-generated from frameCount.xml ) * * The system variable frameCount contains the number of frames * displayed since the program started. Inside setup() the value is * 0 and and after the first iteration of draw it is 1, etc. * * ( end auto-generated ) * @webref environment * @see PApplet#frameRate(float) * @see PApplet#frameRate */ public int frameCount; /** true if the sketch has stopped permanently. */ public volatile boolean finished; /** * true if the animation thread is paused. */ public volatile boolean paused; /** * true if exit() has been called so that things shut down * once the main thread kicks off. */ protected boolean exitCalled; Object pauseObject = new Object(); Thread thread; // Background default needs to be different from the default value in // PGraphics.backgroundColor, otherwise size(100, 100) bg spills over. // https://github.com/processing/processing/issues/2297 static final Color WINDOW_BGCOLOR = new Color(0xDD, 0xDD, 0xDD); // messages to send if attached as an external vm /** * Position of the upper-lefthand corner of the editor window * that launched this applet. */ static public final String ARGS_EDITOR_LOCATION = "--editor-location"; static public final String ARGS_EXTERNAL = "--external"; /** * Location for where to position the applet window on screen. *
* This is used by the editor to when saving the previous applet * location, or could be used by other classes to launch at a * specific position on-screen. */ static public final String ARGS_LOCATION = "--location"; static public final String ARGS_DISPLAY = "--display"; static public final String ARGS_BGCOLOR = "--bgcolor"; /** @deprecated use --full-screen instead. */ static public final String ARGS_PRESENT = "--present"; static public final String ARGS_FULL_SCREEN = "--full-screen"; // static public final String ARGS_EXCLUSIVE = "--exclusive"; static public final String ARGS_STOP_COLOR = "--stop-color"; static public final String ARGS_HIDE_STOP = "--hide-stop"; /** * Allows the user or PdeEditor to set a specific sketch folder path. *
* Used by PdeEditor to pass in the location where saveFrame() * and all that stuff should write things. */ static public final String ARGS_SKETCH_FOLDER = "--sketch-path"; /** * When run externally to a PdeEditor, * this is sent by the applet when it quits. */ //static public final String EXTERNAL_QUIT = "__QUIT__"; static public final String EXTERNAL_STOP = "__STOP__"; /** * When run externally to a PDE Editor, this is sent by the applet * whenever the window is moved. *
* This is used so that the editor can re-open the sketch window * in the same position as the user last left it. */ static public final String EXTERNAL_MOVE = "__MOVE__"; /** true if this sketch is being run by the PDE */ boolean external = false; /** * Not official API, using internally because of the tweaks required. */ boolean retina; static final String ERROR_MIN_MAX = "Cannot use min() or max() on an empty array."; // during rev 0100 dev cycle, working on new threading model, // but need to disable and go conservative with changes in order // to get pdf and audio working properly first. // for 0116, the CRUSTY_THREADS are being disabled to fix lots of bugs. //static final boolean CRUSTY_THREADS = false; //true; /** * Applet initialization. This can do GUI work because the components have * not been 'realized' yet: things aren't visible, displayed, etc. */ @Override public void init() { // println("init() called " + Integer.toHexString(hashCode())); // using a local version here since the class variable is deprecated // Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); // screenWidth = screen.width; // screenHeight = screen.height; if (checkRetina()) { // The active-mode rendering seems to be 2x slower, so disable it // with retina. On a non-retina machine, however, useActive seems // the only (or best) way to handle the rendering. useActive = false; } if (javaVersion >= 1.7f) { try { revalidateMethod = getClass().getMethod("revalidate", new Class[] {}); } catch (Exception e) { } } // send tab keys through to the PApplet setFocusTraversalKeysEnabled(false); //millisOffset = System.currentTimeMillis(); // moved to the variable declaration finished = false; // just for clarity // this will be cleared by draw() if it is not overridden looping = true; redraw = true; // draw this guy once firstMouse = true; // these need to be inited before setup // sizeMethods = new RegisteredMethods(); // pauseMethods = new RegisteredMethods(); // resumeMethods = new RegisteredMethods(); // preMethods = new RegisteredMethods(); // drawMethods = new RegisteredMethods(); // postMethods = new RegisteredMethods(); // mouseEventMethods = new RegisteredMethods(); // keyEventMethods = new RegisteredMethods(); // disposeMethods = new RegisteredMethods(); try { getAppletContext(); online = true; } catch (NullPointerException e) { online = false; } // Removed in 2.1.2, brought back for 2.1.3. Usually sketchPath is set // inside runSketch(), but if this sketch takes care of calls to init() // and setup() itself (i.e. it's in a larger Java application), it'll // still need to be set here so that fonts, etc can be retrieved. if (sketchPath == null) { sketchPath = calcSketchPath(); } // Figure out the available display width and height. // No major problem if this fails, we have to try again anyway in // handleDraw() on the first (== 0) frame. checkDisplaySize(); Dimension size = getSize(); if ((size.width != 0) && (size.height != 0)) { // When this PApplet is embedded inside a Java application with other // Component objects, its size() may already be set externally (perhaps // by a LayoutManager). In this case, honor that size as the default. // Size of the component is set, just create a renderer. g = makeGraphics(size.width, size.height, sketchRenderer(), null, true); // This doesn't call setSize() or setPreferredSize() because the fact // that a size was already set means that someone is already doing it. } else { // Set the default size, until the user specifies otherwise this.defaultSize = true; int w = sketchWidth(); int h = sketchHeight(); g = makeGraphics(w, h, sketchRenderer(), null, true); // Fire component resize event setSize(w, h); setPreferredSize(new Dimension(w, h)); } width = g.width; height = g.height; // addListeners(); // 2.0a6 // moved out of addListeners() in 2.0a6 addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { // Component c = e.getComponent(); // //System.out.println("componentResized() " + c); // Rectangle bounds = c.getBounds(); // resizeRequest = true; // resizeWidth = bounds.width; // resizeHeight = bounds.height; if (!looping) { redraw(); } } }); // if (thread == null) { // paused = true; thread = new Thread(this, "Animation Thread"); thread.start(); // } // this is automatically called in applets // though it's here for applications anyway // start(); } private void checkDisplaySize() { if (getGraphicsConfiguration() != null) { GraphicsDevice displayDevice = getGraphicsConfiguration().getDevice(); if (displayDevice != null) { Rectangle screenRect = displayDevice.getDefaultConfiguration().getBounds(); displayWidth = screenRect.width; displayHeight = screenRect.height; } } } private boolean checkRetina() { if (platform == MACOSX) { // This should probably be reset each time there's a display change. // A 5-minute search didn't turn up any such event in the Java API. // Also, should we use the Toolkit associated with the editor window? final String javaVendor = System.getProperty("java.vendor"); if (javaVendor.contains("Apple")) { Float prop = (Float) getToolkit().getDesktopProperty("apple.awt.contentScaleFactor"); if (prop != null) { return prop == 2; } } else if (javaVendor.contains("Oracle")) { String version = System.getProperty("java.version"); // 1.7.0_40 String[] m = match(version, "1.(\\d).*_(\\d+)"); // Make sure this is Oracle Java 7u40 or later if (m != null && PApplet.parseInt(m[1]) >= 7 && PApplet.parseInt(m[1]) >= 40) { GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice device = env.getDefaultScreenDevice(); try { Field field = device.getClass().getDeclaredField("scale"); if (field != null) { field.setAccessible(true); Object scale = field.get(device); if (scale instanceof Integer && ((Integer)scale).intValue() == 2) { return true; } } } catch (Exception ignore) { } } } } return false; } public int sketchQuality() { return 2; } public int sketchWidth() { return DEFAULT_WIDTH; } public int sketchHeight() { return DEFAULT_HEIGHT; } public String sketchRenderer() { return JAVA2D; } public boolean sketchFullScreen() { // return fullScreen; return false; } public void orientation(int which) { // ignore calls to the orientation command } /** * Called by the browser or applet viewer to inform this applet that it * should start its execution. It is called after the init method and * each time the applet is revisited in a Web page. *
* Called explicitly via the first call to PApplet.paint(), because * PAppletGL needs to have a usable screen before getting things rolling. */ @Override public void start() { debug("start() called"); // new Exception().printStackTrace(System.out); paused = false; // unpause the thread resume(); // resumeMethods.handle(); handleMethods("resume"); debug("un-pausing thread"); synchronized (pauseObject) { debug("start() calling pauseObject.notifyAll()"); // try { pauseObject.notifyAll(); // wake up the animation thread debug("un-pausing thread 3"); // } catch (InterruptedException e) { } } } /** * Called by the browser or applet viewer to inform * this applet that it should stop its execution. * * Unfortunately, there are no guarantees from the Java spec * when or if stop() will be called (i.e. on browser quit, * or when moving between web pages), and it's not always called. */ @Override public void stop() { // this used to shut down the sketch, but that code has // been moved to destroy/dispose() // if (paused) { // synchronized (pauseObject) { // try { // pauseObject.wait(); // } catch (InterruptedException e) { // // waiting for this interrupt on a start() (resume) call // } // } // } // on the next trip through the animation thread, things will go sleepy-by paused = true; // causes animation thread to sleep pause(); handleMethods("pause"); // actual pause will happen in the run() method // synchronized (pauseObject) { // debug("stop() calling pauseObject.wait()"); // try { // pauseObject.wait(); // } catch (InterruptedException e) { // // waiting for this interrupt on a start() (resume) call // } // } } /** * Sketch has been paused. Called when switching tabs in a browser or * swapping to a different application on Android. Also called just before * quitting. Use to safely disable things like serial, sound, or sensors. */ public void pause() { } /** * Sketch has resumed. Called when switching tabs in a browser or * swapping to this application on Android. Also called on startup. * Use this to safely disable things like serial, sound, or sensors. */ public void resume() { } /** * Called by the browser or applet viewer to inform this applet * that it is being reclaimed and that it should destroy * any resources that it has allocated. * * destroy() supposedly gets called as the applet viewer * is shutting down the applet. stop() is called * first, and then destroy() to really get rid of things. * no guarantees on when they're run (on browser quit, or * when moving between pages), though. */ @Override public void destroy() { this.dispose(); } ////////////////////////////////////////////////////////////// /** Map of registered methods, stored by name. */ HashMap registerMap = new HashMap(); class RegisteredMethods { int count; Object[] objects; // Because the Method comes from the class being called, // it will be unique for most, if not all, objects. Method[] methods; Object[] emptyArgs = new Object[] { }; void handle() { handle(emptyArgs); } void handle(Object[] args) { for (int i = 0; i < count; i++) { try { methods[i].invoke(objects[i], args); } catch (Exception e) { // check for wrapped exception, get root exception Throwable t; if (e instanceof InvocationTargetException) { InvocationTargetException ite = (InvocationTargetException) e; t = ite.getCause(); } else { t = e; } // check for RuntimeException, and allow to bubble up if (t instanceof RuntimeException) { // re-throw exception throw (RuntimeException) t; } else { // trap and print as usual t.printStackTrace(); } } } } void add(Object object, Method method) { if (findIndex(object) == -1) { if (objects == null) { objects = new Object[5]; methods = new Method[5]; } else if (count == objects.length) { objects = (Object[]) PApplet.expand(objects); methods = (Method[]) PApplet.expand(methods); } objects[count] = object; methods[count] = method; count++; } else { die(method.getName() + "() already added for this instance of " + object.getClass().getName()); } } /** * Removes first object/method pair matched (and only the first, * must be called multiple times if object is registered multiple times). * Does not shrink array afterwards, silently returns if method not found. */ // public void remove(Object object, Method method) { // int index = findIndex(object, method); public void remove(Object object) { int index = findIndex(object); if (index != -1) { // shift remaining methods by one to preserve ordering count--; for (int i = index; i < count; i++) { objects[i] = objects[i+1]; methods[i] = methods[i+1]; } // clean things out for the gc's sake objects[count] = null; methods[count] = null; } } // protected int findIndex(Object object, Method method) { protected int findIndex(Object object) { for (int i = 0; i < count; i++) { if (objects[i] == object) { // if (objects[i] == object && methods[i].equals(method)) { //objects[i].equals() might be overridden, so use == for safety // since here we do care about actual object identity //methods[i]==method is never true even for same method, so must use // equals(), this should be safe because of object identity return i; } } return -1; } } /** * Register a built-in event so that it can be fired for libraries, etc. * Supported events include: *
* If called once a renderer has already been set, this will
* use the previous renderer and simply resize it.
*
* @webref environment
* @param w width of the display window in units of pixels
* @param h height of the display window in units of pixels
* @see PApplet#width
* @see PApplet#height
*/
public void size(int w, int h) {
size(w, h, JAVA2D, null);
}
/**
* @param renderer Either P2D, P3D, or PDF
*/
public void size(int w, int h, String renderer) {
size(w, h, renderer, null);
}
/**
* @nowebref
*/
public void size(final int w, final int h,
String renderer, String path) {
// Run this from the EDT, just cuz it's AWT stuff (or maybe later Swing)
EventQueue.invokeLater(new Runnable() {
public void run() {
// Set the preferred size so that the layout managers can handle it
setPreferredSize(new Dimension(w, h));
setSize(w, h);
}
});
// ensure that this is an absolute path
if (path != null) path = savePath(path);
String currentRenderer = g.getClass().getName();
if (currentRenderer.equals(renderer)) {
// Avoid infinite loop of throwing exception to reset renderer
resizeRenderer(w, h);
//redraw(); // will only be called insize draw()
} else { // renderer is being changed
// otherwise ok to fall through and create renderer below
// the renderer is changing, so need to create a new object
g = makeGraphics(w, h, renderer, path, true);
this.width = w;
this.height = h;
// fire resize event to make sure the applet is the proper size
// setSize(iwidth, iheight);
// this is the function that will run if the user does their own
// size() command inside setup, so set defaultSize to false.
defaultSize = false;
// throw an exception so that setup() is called again
// but with a properly sized render
// this is for opengl, which needs a valid, properly sized
// display before calling anything inside setup().
throw new RendererChangeException();
}
}
public PGraphics createGraphics(int w, int h) {
return createGraphics(w, h, JAVA2D);
}
/**
* ( begin auto-generated from createGraphics.xml )
*
* Creates and returns a new PGraphics object of the types P2D or
* P3D. Use this class if you need to draw into an off-screen graphics
* buffer. The PDF renderer requires the filename parameter. The DXF
* renderer should not be used with createGraphics(), it's only
* built for use with beginRaw() and endRaw().
*
* It's important to call any drawing functions between beginDraw()
* and endDraw() statements. This is also true for any functions
* that affect drawing, such as smooth() or colorMode().
*
the main drawing surface which is completely opaque, surfaces
* created with createGraphics() can have transparency. This makes
* it possible to draw into a graphics and maintain the alpha channel. By
* using save() to write a PNG or TGA file, the transparency of the
* graphics object will be honored. Note that transparency levels are
* binary: pixels are either complete opaque or transparent. For the time
* being, this means that text characters will be opaque blocks. This will
* be fixed in a future release (Issue 80).
*
* ( end auto-generated )
*
*
* PGraphics big;
*
* void setup() {
* big = createGraphics(3000, 3000);
*
* big.beginDraw();
* big.background(128);
* big.line(20, 1800, 1800, 900);
* // etc..
* big.endDraw();
*
* // make sure the file is written to the sketch folder
* big.save("big.tif");
* }
*
*
* | Web Proxy Viewer | New URL | Original Page |