/* GeoGebra - Dynamic Mathematics for Everyone http://www.geogebra.org This file is part of GeoGebra. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. */ package geogebra; import java.awt.Color; import java.awt.Graphics; import javax.swing.JApplet; import javax.swing.RepaintManager; import javax.swing.SwingUtilities; import org.geogebra.common.plugin.JavaScriptAPI; import org.geogebra.common.util.debug.Log; import org.geogebra.desktop.AppletImplementationInterface; import org.geogebra.desktop.AppletSplashScreen; import org.geogebra.desktop.main.AppletImplementation; /** * GeoGebra applet * * @see org.geogebra.desktop.main.AppletImplementation for the actual * implementation * @author Markus Hohenwarter * @date 2008-10-24 */ public class GeoGebraApplet extends JApplet implements JavaScriptAPI { private static final long serialVersionUID = -350682076336303151L; // applet member variables /** Implamentation of applet's methods */ AppletImplementationInterface appletImplementation = null; private boolean animationRunningAtLastStop = false; /** Splash screen */ AppletSplashScreen splashScreen = null; private boolean appletIsIniting = true; /** * Loads necessary jar files and initializes applet. During the loading of * jar files, a splash screen is shown. */ @Override public void init() { Log.debug("init"); try { SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { // init splash screen splashScreen = new AppletSplashScreen(GeoGebraApplet.this); repaint(); // init APPLET in background task initAppletInBackground(); } }); } catch (Throwable e) { e.printStackTrace(); } } /** * Initializes applet in separate thread */ void initAppletInBackground() { Thread runner = new Thread() { @Override public void run() { Log.debug("initAppletInBackground"); // init applet getGgbApi(); // init CAS, GUI dialogs, and download jar files in background SwingUtilities.invokeLater(new Runnable() { @Override public void run() { // update GUI if (GeoGebraApplet.this.isShowing()) { SwingUtilities .updateComponentTreeUI(GeoGebraApplet.this); } // dispose splash screen splashScreen.dispose(); splashScreen = null; // init some things in background (like CAS, more GUI // components) appletImplementation.initInBackground(); } }); } }; runner.start(); } @Override public void start() { // restart animation if necessary if (animationRunningAtLastStop) { getGgbApi().startAnimation(); } // request focus // important for accessibility (ie where the mouse can't be used) // as the browser may not provide a keyboard shortcut requestFocus(); requestFocusInWindow(); requestFocus(); repaint(); } @Override public void stop() { // stop animation and remember that it needs to be restarted later if (appletImplementation != null) { animationRunningAtLastStop = getGgbApi().isAnimationRunning(); if (animationRunningAtLastStop) { getGgbApi().stopAnimation(); } } repaint(); } @Override public void destroy() { // stop animation if (appletImplementation != null) { getGgbApi().stopAnimation(); appletImplementation.dispose(); appletImplementation = null; } if (splashScreen != null) { splashScreen.dispose(); splashScreen = null; } // free up memory on reload, see Java bug // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6550586 RepaintManager.setCurrentManager(null); } /** * Returns the appletImplementation object. * * @return the applet implementation */ public synchronized AppletImplementationInterface getAppletImplementation() { if (appletIsIniting) { initAppletImplementation(); } return appletImplementation; } /** * @param appImp * applet implementation */ public void setAppletImplementation(AppletImplementationInterface appImp) { appletImplementation = appImp; appletIsIniting = false; } /** * Initializes the appletImplementation object. Loads geogebra_main.jar file * and initializes applet if necessary. */ protected synchronized void initAppletImplementation() { if (isAppletFullyLoaded()) { return; } // create delegate object that implements our applet's methods AppletImplementation applImpl = new AppletImplementation(this); // initialize applet's user interface, this changes the content pane applImpl.initGUI(); // remember the applet implementation setAppletImplementation(applImpl); } /** * Paints the applet or a loading screen while the applet is being * initialized. */ @Override final public void paint(Graphics g) { // INITING applet if (appletIsIniting) { // show splash screen if (splashScreen != null && splashScreen.isReady()) { g.drawImage(splashScreen.getImage(), 0, 0, null); } else { // OUT OF MEMORY // Draw GeoGebra text until splash screen is ready. // This is only shown when we ran out of memory and // couldn't even load the splash screen. int width = getWidth(); int height = getHeight(); g.setColor(Color.white); g.fillRect(0, 0, width, height); g.setColor(Color.darkGray); g.drawString("GeoGebra", width / 2 - 10, height / 2); // less then about 2MB free memory: we may have run out of // memory: // tell user to restart browser if (Runtime.getRuntime().freeMemory() < 2000000) { g.drawString( "Out of Memory Error: Please restart your browser. ", width / 2 - 120, height / 2 + 30); } } } // STANDARD CASE else { super.paint(g); } } /** * @return true once the GUI is fully initialized */ final boolean isAppletFullyLoaded() { return !appletIsIniting; } /* * JAVASCRIPT interface * * To add a new JavaScript method, do the following: 1) add the method stub * to the interface geogebra.JavaScriptAPI 2) implement the method in * geogebra.main.AppletImplementation 3) implement the method here in * org.geogebra.desktop.GeoGebraApplet by delegating it to * geogebra.main.AppletImplementation */ @Override public synchronized void deleteObject(String objName) { getGgbApi().deleteObject(objName); } @Override public synchronized boolean evalCommand(final String cmdString) { return evalCommand(cmdString, true); } @Override public synchronized String evalCommandCAS(final String cmdString) { return getGgbApi().evalCommandCAS(cmdString); } @Override public synchronized String evalGeoGebraCAS(final String cmdString) { return getAppletImplementation().evalGeoGebraCAS(cmdString); } /** * @param cmdString * command * @param waitForResult * whether to wait * @return true when successful (or not waiting) */ public synchronized boolean evalCommand(final String cmdString, boolean waitForResult) { if (waitForResult) { return getGgbApi().evalCommand(cmdString); } // see #106 // (redraw error if evalCommand() is called again before it's finished) try { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { getGgbApi().evalCommand(cmdString); } }); } catch (Exception e) { e.printStackTrace(); } return true; } @Override public synchronized void evalXML(String xmlString) { getAppletImplementation().evalXML(xmlString); } @Override public synchronized void debug(String string) { getGgbApi().debug(string); } @Override public synchronized boolean exists(String objName) { return getGgbApi().exists(objName); } @Override public synchronized String[] getAllObjectNames() { return getGgbApi().getAllObjectNames(); } @Override public synchronized String getColor(String objName) { return getGgbApi().getColor(objName); } @Override public synchronized double getFilling(String objName) { return getGgbApi().getFilling(objName); } @Override public synchronized int getPointStyle(String objName) { return getGgbApi().getPointStyle(objName); } @Override public synchronized int getPointSize(String objName) { return getGgbApi().getPointSize(objName); } @Override public synchronized int getLineStyle(String objName) { return getGgbApi().getLineStyle(objName); } @Override public synchronized int getLineThickness(String objName) { return getGgbApi().getLineThickness(objName); } @Override public synchronized String getCommandString(String objName) { return getGgbApi().getCommandString(objName); } @Override public synchronized String getDefinitionString(String objName) { return getGgbApi().getDefinitionString(objName); } @Override public synchronized String getLaTeXString(String objName) { return getGgbApi().getLaTeXString(objName); } @Override public synchronized byte[] getGGBfile() { return getGgbApi().getGGBfile(); } @Override public synchronized int getLayer(String objName) { return getGgbApi().getLayer(objName); } @Override public synchronized String getObjectName(int i) { return getGgbApi().getObjectName(i); } @Override public synchronized String getPNGBase64(double exportScale, boolean transparent, double DPI, boolean copyToClipboard) { return getAppletImplementation().getPNGBase64(exportScale, transparent, DPI, copyToClipboard); } @Override public synchronized boolean writePNGtoFile(String filename, double exportScale, boolean transparent, double DPI) { return getAppletImplementation().writePNGtoFile(filename, exportScale, transparent, DPI); } @Override public synchronized int getObjectNumber() { return getGgbApi().getObjectNumber(); } @Override public synchronized String getObjectType(String objName) { return getGgbApi().getObjectType(objName); } @Override public synchronized double getValue(String objName) { return getGgbApi().getValue(objName); } @Override public synchronized String getValueString(String objName) { return getGgbApi().getValueString(objName); } @Override public synchronized String getXML() { return getGgbApi().getXML(); } @Override public synchronized String getBase64() { return getGgbApi().getBase64(false); } @Override public synchronized String getBase64(boolean includeThumbnail) { return getGgbApi().getBase64(includeThumbnail); } @Override public synchronized String getXML(String objName) { return getGgbApi().getXML(objName); } @Override public synchronized String getAlgorithmXML(String objName) { return getGgbApi().getAlgorithmXML(objName); } @Override public synchronized double getXcoord(String objName) { return getGgbApi().getXcoord(objName); } @Override public synchronized double getYcoord(String objName) { return getGgbApi().getYcoord(objName); } @Override public synchronized double getZcoord(String objName) { return getGgbApi().getYcoord(objName); } @Override public synchronized boolean isDefined(String objName) { return getGgbApi().isDefined(objName); } @Override public synchronized boolean isIndependent(String objName) { return getGgbApi().isIndependent(objName); } @Override public synchronized void openFile(String strURL) { getAppletImplementation().openFile(strURL); } @Override public synchronized void refreshViews() { getGgbApi().refreshViews(); } @Override public synchronized void registerAddListener(String JSFunctionName) { getGgbApi().registerAddListener(JSFunctionName); } @Override public synchronized void registerClearListener(String JSFunctionName) { getGgbApi().registerClearListener(JSFunctionName); } @Override public synchronized void registerObjectUpdateListener(String objName, String JSFunctionName) { getGgbApi().registerObjectUpdateListener(objName, JSFunctionName); } @Override public synchronized void registerObjectClickListener(String objName, String JSFunctionName) { getGgbApi().registerObjectClickListener(objName, JSFunctionName); } @Override public synchronized void registerRemoveListener(String JSFunctionName) { getGgbApi().registerRemoveListener(JSFunctionName); } @Override public synchronized void registerRenameListener(String JSFunctionName) { getGgbApi().registerRenameListener(JSFunctionName); } @Override public synchronized void registerUpdateListener(String JSFunctionName) { getGgbApi().registerUpdateListener(JSFunctionName); } @Override public synchronized void registerClickListener(String JSFunctionName) { getGgbApi().registerClickListener(JSFunctionName); } @Override public synchronized boolean renameObject(String oldObjName, String newObjName) { return getGgbApi().renameObject(oldObjName, newObjName); } @Override public synchronized boolean renameObject(String oldObjName, String newObjName, boolean force) { return getGgbApi().renameObject(oldObjName, newObjName, force); } @Override public synchronized void setAnimating(String objName, boolean animate) { getGgbApi().setAnimating(objName, animate); } @Override public synchronized void setAnimationSpeed(String objName, double speed) { getGgbApi().setAnimationSpeed(objName, speed); } @Override public synchronized void startAnimation() { getGgbApi().startAnimation(); } @Override public synchronized void stopAnimation() { getGgbApi().stopAnimation(); } @Override public void hideCursorWhenDragging(boolean hideCursorWhenDragging) { getGgbApi().hideCursorWhenDragging(hideCursorWhenDragging); } @Override public synchronized boolean isAnimationRunning() { return getGgbApi().isAnimationRunning(); } @Override public synchronized void reset() { getAppletImplementation().reset(); } @Override public synchronized void setAxesVisible(boolean xVisible, boolean yVisible) { getGgbApi().setAxesVisible(xVisible, yVisible); } @Override public synchronized void setAxesVisible(int view, boolean xVisible, boolean yVisible, boolean zVisible) { getGgbApi().setAxesVisible(view, xVisible, yVisible, zVisible); } @Override public synchronized void setColor(String objName, int red, int green, int blue) { getGgbApi().setColor(objName, red, green, blue); } @Override public synchronized void setCorner(String objName, double x, double y, int index) { getGgbApi().setCorner(objName, x, y, index); } @Override public synchronized void setCorner(String objName, double x, double y) { getGgbApi().setCorner(objName, x, y); } @Override public synchronized void setLineThickness(String objName, int thickness) { getGgbApi().setLineThickness(objName, thickness); } @Override public synchronized void setLineStyle(String objName, int style) { getGgbApi().setLineStyle(objName, style); } @Override public synchronized void setFilling(String objName, double filling) { getGgbApi().setFilling(objName, filling); } @Override public synchronized void setPointStyle(String objName, int style) { getGgbApi().setPointStyle(objName, style); } @Override public void setOnTheFlyPointCreationActive(boolean flag) { getGgbApi().setOnTheFlyPointCreationActive(flag); } @Override public void setUndoPoint() { getGgbApi().setUndoPoint(); } @Override public synchronized void setPointSize(String objName, int style) { getGgbApi().setPointSize(objName, style); } @Override public synchronized void setCoordSystem(double xmin, double xmax, double ymin, double ymax) { getGgbApi().setCoordSystem(xmin, xmax, ymin, ymax); } @Override public synchronized void setCoords(String objName, double x, double y) { getGgbApi().setCoords(objName, x, y); } @Override public synchronized void setCoords(String objName, double x, double y, double z) { getGgbApi().setCoords(objName, x, y, z); } @Override public synchronized void setErrorDialogsActive(boolean flag) { getGgbApi().setErrorDialogsActive(flag); } @Override public synchronized void setFixed(String objName, boolean flag) { getGgbApi().setFixed(objName, flag); } @Override public synchronized void setGridVisible(boolean flag) { getGgbApi().setGridVisible(flag); } @Override public synchronized void setGridVisible(int view, boolean flag) { getGgbApi().setGridVisible(flag); } @Override public synchronized void setLabelStyle(String objName, int style) { getGgbApi().setLabelStyle(objName, style); } @Override public synchronized void setLabelVisible(String objName, boolean visible) { getGgbApi().setLabelVisible(objName, visible); } @Override public synchronized boolean getLabelVisible(String objName) { return getGgbApi().getLabelVisible(objName); } @Override public synchronized void setLayer(String objName, int layer) { getGgbApi().setLayer(objName, layer); } @Override public synchronized void setLayerVisible(int layer, boolean visible) { getGgbApi().setLayerVisible(layer, visible); } @Override public synchronized void setMode(int mode) { getGgbApi().setMode(mode); } @Override public synchronized void setRepaintingActive(boolean flag) { getGgbApi().setRepaintingActive(flag); } @Override public synchronized void setTrace(String objName, boolean flag) { getGgbApi().setTrace(objName, flag); } @Override public synchronized void setValue(String objName, double x) { getGgbApi().setValue(objName, x); } @Override public synchronized void setTextValue(String objName, String x) { getGgbApi().setTextValue(objName, x); } @Override public synchronized void setListValue(String objName, double x, double y) { getGgbApi().setListValue(objName, x, y); } @Override public synchronized void setVisible(String objName, boolean visible) { getGgbApi().setVisible(objName, visible); } @Override public synchronized boolean getVisible(String objName) { return getGgbApi().getVisible(objName); } @Override public synchronized void setXML(String xml) { getAppletImplementation().setXML(xml); } @Override public synchronized void setBase64(String base64) { getGgbApi().setBase64(base64); } @Override public synchronized void unregisterAddListener(String JSFunctionName) { getGgbApi().unregisterAddListener(JSFunctionName); } @Override public synchronized void unregisterClearListener(String JSFunctionName) { getGgbApi().unregisterClearListener(JSFunctionName); } @Override public synchronized void unregisterObjectUpdateListener(String objName) { getGgbApi().unregisterObjectUpdateListener(objName); } @Override public synchronized void unregisterObjectClickListener(String objName) { getGgbApi().unregisterObjectClickListener(objName); } @Override public synchronized void registerStoreUndoListener(String objName) { getGgbApi().registerStoreUndoListener(objName); } @Override public synchronized void unregisterRemoveListener(String JSFunctionName) { getGgbApi().unregisterRemoveListener(JSFunctionName); } @Override public synchronized void unregisterRenameListener(String JSFunctionName) { getGgbApi().unregisterRenameListener(JSFunctionName); } @Override public synchronized void unregisterUpdateListener(String JSFunctionName) { getGgbApi().unregisterUpdateListener(JSFunctionName); } @Override public synchronized void unregisterClickListener(String JSFunctionName) { getGgbApi().unregisterClickListener(JSFunctionName); } @Override public boolean isMoveable(String objName) { return getGgbApi().isMoveable(objName); } @Override public void uploadToGeoGebraTube() { getGgbApi().uploadToGeoGebraTube(); } @Override public void setPenColor(int red, int green, int blue) { getGgbApi().setPenColor(red, green, blue); } @Override public void setPenSize(int size) { getGgbApi().setPenSize(size); } @Override public int getPenSize() { return getGgbApi().getPenSize(); } @Override public String getPenColor() { return getGgbApi().getPenColor(); } @Override public synchronized double getListValue(String objName, int index) { return getGgbApi().getListValue(objName, index); } @Override public void registerClientListener(String JSFunctionName) { getGgbApi().registerClientListener(JSFunctionName); } @Override public void unregisterClientListener(String JSFunctionName) { getGgbApi().unregisterClientListener(JSFunctionName); } @Override public void setPerspective(String code) { getGgbApi().setPerspective(code); } @Override public synchronized boolean getVisible(String objName, int view) { return getGgbApi().getVisible(objName, view); } @Override public int getCASObjectNumber() { return getGgbApi().getCASObjectNumber(); } @Override public synchronized int getMode() { return getGgbApi().getMode(); } @Override public double getExerciseFraction() { return getGgbApi().getExerciseFraction(); } @Override public String getCommandString(String objName, boolean localize) { return getGgbApi().getCommandString(objName, localize); } @Override public synchronized boolean getGridVisible(int view) { return getGgbApi().getGridVisible(view); } @Override public synchronized boolean getGridVisible() { return getGgbApi().getGridVisible(); } @Override public synchronized int getLabelStyle(String objName) { return getGgbApi().getLabelStyle(objName); } @Override public String getCaption(String objName, boolean subst) { return getGgbApi().getCaption(objName, subst); } @Override public void setCaption(String objName, String caption) { getGgbApi().setCaption(objName, caption); } @Override public String getPerspectiveXML() { return getGgbApi().getPerspectiveXML(); } @Override public String getVersion() { return getGgbApi().getVersion(); } @Override public double getFrameRate() { return getGgbApi().getFrameRate(); } @Override public String getDefinitionString(String objName, boolean localize) { return getGgbApi().getDefinitionString(objName, localize); } @Override public void enableCAS(boolean enable) { getGgbApi().enableCAS(enable); } @Override public void enable3D(boolean enable) { getGgbApi().enable3D(enable); } /** * The API instance * * @return the API */ JavaScriptAPI getGgbApi() { return getAppletImplementation().getGgbApi(); } @Override public void enableRightClick(boolean enable) { getGgbApi().enableRightClick(enable); } @Override public void enableLabelDrags(boolean enable) { getGgbApi().enableLabelDrags(enable); } @Override public void enableShiftDragZoom(boolean enable) { getGgbApi().enableShiftDragZoom(enable); } @Override public void setAxisSteps(int view, String xStep, String yStep, String zStep) { getGgbApi().setAxisSteps(view, xStep, yStep, zStep); } @Override public void setAxisLabels(int view, String xLabel, String yLabel, String zLabel) { getGgbApi().setAxisLabels(view, xLabel, yLabel, zLabel); } @Override public void setAxisUnits(int view, String xLabel, String yLabel, String zLabel) { getGgbApi().setAxisUnits(view, xLabel, yLabel, zLabel); } @Override public void setAuxiliary(String objName, boolean flag) { getGgbApi().setAuxiliary(objName, flag); } @Override public void setPointCapture(int view, int capture) { getGgbApi().setPointCapture(view, capture); } @Override public void setFont(String label, int size, boolean italic, boolean bold, boolean serif) { getGgbApi().setFont(label, size, italic, bold, serif); } @Override public void setRounding(String format) { getGgbApi().setRounding(format); } @Override public void newConstruction() { getGgbApi().newConstruction(); } @Override public boolean isExercise() { // TODO Auto-generated method stub return getGgbApi().isExercise(); } @Override public void undo(boolean repaint) { getGgbApi().undo(repaint); } @Override public void redo(boolean repaint) { getGgbApi().redo(repaint); } @Override public String getViewProperties(int viewID) { return getGgbApi().getViewProperties(viewID); } @Override public void logout() { getGgbApi().logout(); } @Override public void login(String token) { getGgbApi().login(token); } @Override public String[] getAllObjectNames(String type) { return getGgbApi().getAllObjectNames(type); } @Override public String getToolName(int mode) { return getGgbApi().getToolName(mode); } public boolean isTracing(String objName) { return getGgbApi().isTracing(objName); } public void evalLaTeX(String input, int mode) { getGgbApi().evalLaTeX(input, mode); } }