aboutsummaryrefslogtreecommitdiffstats
path: root/gl4java/swing
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2000-11-18 06:43:49 +0000
committerSven Gothel <[email protected]>2000-11-18 06:43:49 +0000
commit880653d31a8f1ff8384fdbc75b84934bceecfdb8 (patch)
treebdafb71416f176d2a4b73bf716c9dc3f13685a8b /gl4java/swing
Initial revision
Diffstat (limited to 'gl4java/swing')
-rw-r--r--gl4java/swing/GLAnimJPanel.java720
-rw-r--r--gl4java/swing/GLJPanel.java865
-rw-r--r--gl4java/swing/GLJPanel.java,v959
-rw-r--r--gl4java/swing/SimpleGLJApplet1.java292
4 files changed, 2836 insertions, 0 deletions
diff --git a/gl4java/swing/GLAnimJPanel.java b/gl4java/swing/GLAnimJPanel.java
new file mode 100644
index 0000000..e9bdbdf
--- /dev/null
+++ b/gl4java/swing/GLAnimJPanel.java
@@ -0,0 +1,720 @@
+/**
+ * @(#) GLAnimJPanel.java
+ */
+
+package gl4java.swing;
+
+import gl4java.GLContext;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.lang.Math;
+
+
+/**
+ * This is meant as an base class writing
+ * Animations. A clean usage of multi-threading compatible
+ * with JAVA2 is implemented here !
+ *
+ * <p>
+ *
+ * If you are interessting in further Documentation and/or
+ * the history of GL4Java follow the following link.
+ *
+ * <pre>
+ <a href="../../GL4Java.html">The GL4Java Documentation</a>
+ * </pre>
+ * <p>
+ *
+ * This code uses repaint() to fire a sDisplay call by the AWT-Event thread !
+ * and sleep to suspend for a given Frames per secounds value as default !!
+ *
+ * To switch this behavior for a better performance, and responsiveness
+ * so that sDisplay is called by the animation thread itself
+ * call:
+ *
+ * <pre>
+ <a href="GLAnimJPanel.html#setUseRepaint(boolean)">setUseRepaint(false)</a>
+ * </pre>
+ * <p>
+ *
+ * This code sleep's for a given Frames per secounds after each frame
+ * as default !!
+ *
+ * To switch this behavior for a better performance,
+ * so that much frames are rendered as the machine can do !
+ * call:
+ *
+ * <pre>
+ <a href="GLAnimJPanel.html#setUseFpsSleep(boolean)">setUseFpsSleep(false)</a>
+ * </pre>
+ * <p>
+ * But be sure, that the other threads may not have enough time or i
+ * may not get the cpu power ...
+ *
+ * The following settings for setUseRepaint and setUseFpsSleep looks fine:
+ *
+ * <pre>
+ <p>
+ A JVM with operating system threads has: <b>native-threads</b>
+ <p>
+ A JVM where all JVM threads runs in one operating-system-thread
+ has: <b>green-threads</b>
+
+ <a name="table">
+ <table border>
+ <tr>
+ <th><th>green-threads<th>native-threads
+ <tr>
+ <td align=center><a href="GLAnimJPanel.html#setUseRepaint(boolean)"><code>setUseRepaint</code></a>
+ <td align=center><code>true</code>
+ <td align=center><code> true & false </code>
+ <tr>
+ <td align=center><a href="GLAnimJPanel.html#setUseFpsSleep(boolean)"><code>setUseFpsSleep</code></a>
+ <td align=center><code>true</code>
+ <td align=center><code> true & false </code>
+
+ </table>
+ </a>
+ * </pre>
+ *
+ * If you play with setUseRepaint or setUseFpsSleep,
+ * be shure to have a Java VM with native-thread support,
+ * because a GL-Context can be shared by many threads,
+ * but one thread can have just one GL-Context !
+ *
+ * (comments welcome)
+ *
+ * <p>
+ * To use real fps settings, the following functions provides you to do so:
+ * <pre>
+ <a href="GLAnimJPanel.html#setAnimateFps(double, int)">setAnimateFps</a>
+ <a href="GLAnimJPanel.html#getMaxFps()">getMaxFps</a>
+ * </pre>
+ * Like the first animation run, this class renders a view frames (default 10)
+ * to subtract the render time from the sleep time !
+ * <p>
+ * You should overwrite the following methods for your needs:
+ * <pre>
+ <a href="GLAnimJPanel.html#init()">init - 1st initialisation</a>
+ <a href="GLAnimJPanel.html#display()">display - render one frame</a>
+ <a href="GLCanvas.html#reshape(int, int)">reshape - to reshape (window resize)</a>
+ <a href="GLAnimJPanel.html#ReInit()">ReInit - ReInitialisation after stop for setSuspended(false)</a>
+ * </pre>
+ *
+ * @see GLCanvas
+ * @version 2.0, 21. April 1999
+ * @author Sven Goethel
+ *
+ */
+public class GLAnimJPanel extends GLJPanel
+ implements Runnable
+{
+ /**
+ * To support frames per scounds,
+ * instead of killing the machine :-)
+ *
+ * A little GUI is supported !
+ *
+ * @see GLAnimJPanel#run
+ */
+ protected double FramesPerSec=20;
+ protected long mSecPerFrame=0;
+
+ /**
+ * the delays ..
+ */
+ protected long dFpsMilli = 0;
+
+ /**
+ * The thread for referencing Thread (Animation)
+ *
+ * @see GLAnimJPanel#stop
+ * @see GLAnimJPanel#start
+ * @see GLAnimJPanel#run
+ */
+ protected Thread killme = null;
+
+ /**
+ * Instead of using suspend (JAVA2)
+ *
+ * @see GLAnimJPanel#run
+ */
+ protected boolean threadSuspended = false;
+
+ static {
+ if(GLContext.loadNativeLibraries(null, null, null)==false)
+ System.out.println("GLAnimJPanel could not load def. native libs.");
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * @param gl_Name The name of the GLFunc implementation
+ * If gl_Name==null, the default class will be used !
+ *
+ * @param glu_Name The name of the GLUFunc implementation
+ * If gl_LibName==null, the default class will be used !
+ *
+ * @param layout the layout manager
+ * @param isDoubleBuffered the flag indicates,
+ * if double buffer should be used
+ *
+ */
+ public GLAnimJPanel( String gl_Name,
+ String glu_Name,
+ LayoutManager layout, boolean isDoubleBuffered
+ )
+ {
+ super( gl_Name, glu_Name, layout, isDoubleBuffered );
+ setAnimateFps(FramesPerSec);
+
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * @param layout the layout manager
+ * @param isDoubleBuffered the flag indicates,
+ * if double buffer should be used
+ *
+ */
+ public GLAnimJPanel( LayoutManager layout, boolean isDoubleBuffered )
+ {
+ super(layout, isDoubleBuffered);
+ setAnimateFps(FramesPerSec);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * Uses the default GLFunc and GLUFunc implementation !
+ *
+ * @param isDoubleBuffered the flag indicates,
+ * if double buffer should be used
+ */
+ public GLAnimJPanel( boolean isDoubleBuffered )
+ {
+ super(isDoubleBuffered);
+ setAnimateFps(FramesPerSec);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * Uses the default GLFunc and GLUFunc implementation !
+ *
+ * @param layout the layout manager
+ */
+ public GLAnimJPanel(LayoutManager layout)
+ {
+ super(layout);
+ setAnimateFps(FramesPerSec);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * Uses the default GLFunc and GLUFunc implementation !
+ *
+ * @see GLCanvas#GLCanvas
+ *
+ */
+ public GLAnimJPanel( )
+ {
+ super();
+ setAnimateFps(FramesPerSec);
+ }
+
+ /**
+ * init should be overwritten by you,
+ * to enter your initialisation code
+ *
+ */
+ public void init()
+ {
+ /* here we should add and initialize our JAVA components */
+
+ /* ... and furthet OpenGL init's - like you want to */
+
+ glj.gljCheckGL();
+
+ ReInit();
+
+ /* and start our working thread ... */
+ start();
+ }
+
+ /**
+ *
+ * This is the rendering-method called by sDisplay
+ * (and sDisplay is called by paint, or by the thread directly !).
+ * The derived-class (Your Subclass) will redefine this,
+ * to draw it's own animation !
+ *
+ * <p>
+ *
+ * You should set shallWeRender here,
+ * to signalize the animation-loop 'run' to supsend
+ * <p>
+ * To restart the thread, just call setSuspended(false)
+ *
+ * @see GLAnimJPanel#shallWeRender
+ * @see GLAnimJPanel#run
+ * @see GLAnimJPanel#setSuspended
+ * @see GLCanvas#sDisplay
+ * @see GLCanvas#paint
+ */
+ public void display()
+ {
+ int i;
+
+ // ... just render it
+
+ }
+
+ /**
+ * ReInit should be overwritten by you,
+ * to enter your re-initialisation within setSuspended(false)
+ *
+ * @see GLAnimJPanel#setSuspended
+ */
+ public void ReInit()
+ {
+ }
+
+ protected boolean useRepaint = true;
+
+ protected boolean useFpsSleep = true;
+
+ /**
+ * The normal behavior is to use 'repaint'
+ * within the AWT-Event Thread to render.
+ * <p>
+ * If you have serious reasons, e.g. measuring performance,
+ * you can change it while invoke this function with 'false'.
+ * In this case, the thread itself calls the sDisplay method !
+ *
+ * On fast good multi-threading machines (native-thread-JVM),
+ * this should increase the performance and the responsiveness !
+ * <p>
+ *
+ * @param b if true, uses repaint (default), otherwise directly sDisplay
+ * @see GLCanvas#sDisplay
+ * @see GLAnimJPanel#setUseFpsSleep
+ */
+ public void setUseRepaint(boolean b)
+ {
+ useRepaint = b;
+ }
+
+ /**
+ * The normal behavior is to use FpsSleep
+ *
+ * But you can overwrite this behavior and
+ * drop the Frame Per Secound sleeps -
+ * so that much frames are rendered as the machine can do !
+ * <p>
+ *
+ * @param b if true, uses Fps sleeping, else not !
+ * @see GLCanvas#sDisplay
+ * @see GLAnimJPanel#setUseRepaint
+ */
+ public void setUseFpsSleep(boolean b)
+ {
+ useFpsSleep = b;
+ }
+
+ public boolean getUseRepaint()
+ {
+ return useRepaint;
+ }
+
+ public boolean getUseFpsSleep()
+ {
+ return useFpsSleep;
+ }
+
+ /**
+ * HERE WE DO HAVE OUR RUNNING THREAD !
+ * WE NEED STUFF LIKE THAT FOR ANIMATION ;-)
+ */
+ public void start()
+ {
+ if(killme == null)
+ {
+ killme = new Thread(this);
+ killme.start();
+
+ resetFpsCounter();
+ }
+ }
+
+ public synchronized void stop()
+ {
+ killme = null;
+ threadSuspended=false;
+ notify();
+ }
+
+ /**
+ * Should be set in display,
+ * whether to render or not while the animation loop
+ * <p>
+ * If shallWeRender is false,
+ * this thread will suspend !
+ *
+ * @see GLAnimJPanel#display
+ * @see GLAnimJPanel#run
+ */
+ protected boolean shallWeRender = true;
+
+ private long _fDelay = 0;
+ private long _fDelay_Frames = 10;
+ private boolean _fDelaySync=true;
+ private boolean _fDelayRun=false;
+
+ /**
+ * The running loop for animations
+ * which initiates the call of display
+ *
+ * @see GLAnimJPanel#shallWeRender
+ * @see GLAnimJPanel#display
+ * @see GLAnimJPanel#diplay
+ */
+ public void run()
+ {
+ Thread thisThread = Thread.currentThread();
+
+
+ while (killme==thisThread)
+ {
+ if(cvsIsInit())
+ {
+ /* DRAW THE TINGS .. */
+ if (shallWeRender)
+ {
+ if(useRepaint)
+ repaint();
+ else
+ sDisplay();
+ } else {
+ // lets sleep ...
+ synchronized (this) {
+ threadSuspended=true;
+ }
+ }
+
+ if(fps_isCounting)
+ fps_frames++;
+
+ }
+
+ try {
+ if(useFpsSleep)
+ {
+ if(useRepaint)
+ {
+ if(mSecPerFrame<_f_dur_total)
+ dFpsMilli=_f_dur_total;
+ else
+ dFpsMilli=mSecPerFrame;
+ }
+ else
+ {
+ dFpsMilli= mSecPerFrame - _f_dur_total;
+ if (dFpsMilli<=0)
+ dFpsMilli= 1;
+ }
+
+ Thread.currentThread().sleep(dFpsMilli, 0 );
+ }
+
+ if (threadSuspended) {
+ stopFpsCounter();
+ synchronized (this) {
+ while (threadSuspended)
+ wait();
+ }
+ }
+ } catch (InterruptedException e)
+ {}
+ }
+ }
+
+ /**
+ * Here we can (re)start or suspend animation ...
+ *
+ * If the thread should be (re)started and is not alive -> killed,
+ * or never be started, it will be started !
+ *
+ * @param suspend if true the thread will be suspended,
+ * if false, the thread will be (re)started
+ *
+ * @see GLAnimJPanel#isAlive
+ * @see GLAnimJPanel#start
+ */
+ public void setSuspended(boolean suspend)
+ {
+ setSuspended(suspend, false);
+ }
+
+ /**
+ * Here we can (re)start or suspend animation ...
+ *
+ * If the thread should be (re)started and is not alive -> killed,
+ * or never be started, it will be started !
+ *
+ * @param suspend if true the thread will be suspended,
+ * if false, the thread will be (re)started
+ *
+ * @param reInit if true the ReInit will be called additionally,
+ * where the user can set additional initialisations
+ *
+ * @see GLAnimJPanel#isAlive
+ * @see GLAnimJPanel#start
+ */
+ public synchronized void setSuspended(boolean suspend, boolean reInit)
+ {
+ if(suspend) {
+ shallWeRender=false;
+ } else if(isAlive()==false) {
+ start();
+ } else {
+ // the thread is alive, but suspended and should be
+ // re-started
+ shallWeRender=true;
+ resetFpsCounter();
+
+ if(reInit)
+ ReInit();
+
+ threadSuspended=false;
+ notify();
+ }
+ }
+
+ /**
+ * is the thread alive, means is started and not died ?
+ *
+ * @see GLAnimJPanel#run
+ * @see GLAnimJPanel#setSuspended
+ * @see GLAnimJPanel#start
+ * @see GLAnimJPanel#stop
+ */
+ public boolean isAlive()
+ {
+ if(killme==null) return false;
+ return killme.isAlive();
+ }
+
+ /**
+ * is the thread suspended, means is started but waiting,
+ * or not alive (ok :-| - but it is practical)
+ *
+ * @see GLAnimJPanel#run
+ * @see GLAnimJPanel#setSuspended
+ * @see GLAnimJPanel#start
+ * @see GLAnimJPanel#stop
+ */
+ public boolean isSuspended()
+ {
+ if(killme==null) return true;
+ return threadSuspended;
+ }
+
+ private double fps=0; // frame-per-sec
+ private long fps_duration =0; // milli-secs
+ private long fps_start=0; // milli-secs
+ private long fps_frames =0; // number of frames
+ private boolean fps_isCounting =true; // shall i count
+ private boolean verboseFps =true; // shall i be verbose
+
+ /**
+ * resets the Fps Counter
+ * <p>
+ * this function is called automatically by
+ * start and setSuspended
+ *
+ * @see GLAnimJPanel#start
+ * @see GLAnimJPanel#setSuspended
+ * @see GLAnimJPanel#resetFpsCounter
+ * @see GLAnimJPanel#stopFpsCounter
+ * @see GLAnimJPanel#getFps
+ * @see GLAnimJPanel#getFpsDuration
+ * @see GLAnimJPanel#getFpsFrames
+ * @see GLAnimJPanel#setVerboseFps
+ */
+ public void resetFpsCounter()
+ {
+ fps=0; // frame-per-sec
+ fps_duration =0; // milli-secs
+ fps_frames =0; // number of frames
+ fps_isCounting =true; // shall i count
+ fps_start=System.currentTimeMillis();
+ }
+
+ /**
+ * stops the Fps Counter and sets all values
+ * fot the getFps* methods
+ * <p>
+ * this function is called automatically by
+ * run, if the thread is suspended via shallWeRender
+ * <p>
+ * All data's are print out on System.out
+ * if verboseFps is set !
+ *
+ * @see GLAnimJPanel#run
+ * @see GLAnimJPanel#shallWeRender
+ * @see GLAnimJPanel#resetFpsCounter
+ * @see GLAnimJPanel#stopFpsCounter
+ * @see GLAnimJPanel#getFps
+ * @see GLAnimJPanel#getFpsDuration
+ * @see GLAnimJPanel#getFpsFrames
+ * @see GLAnimJPanel#setVerboseFps
+ */
+ public void stopFpsCounter()
+ {
+ if(fps_isCounting==true)
+ {
+ long fps_end=System.currentTimeMillis();
+ fps_duration = fps_end-fps_start;
+ double timed= ((double)fps_duration)/1000.0;
+ if(timed==0) timed=1.0;
+ fps = ((double)fps_frames)/timed ;
+ fps_isCounting=false;
+ }
+ if(verboseFps)
+ {
+ System.out.println("\nfps = "+String.valueOf(fps));
+ System.out.println("time = "+String.valueOf(fps_duration)+" ms");
+ System.out.println("frames = "+String.valueOf(fps_frames));
+ if(fps_frames==0) fps_frames=1;
+ System.out.println("time/f = "+String.valueOf(fps_duration/fps_frames)+" ms");
+ }
+ }
+
+ /**
+ * sets if the Fps data shall be printed to System.out
+ * while stopFpsCounter is called !
+ * <p>
+ * verboseFps is set to true by default !
+ *
+ * @see GLAnimJPanel#run
+ * @see GLAnimJPanel#shallWeRender
+ * @see GLAnimJPanel#resetFpsCounter
+ * @see GLAnimJPanel#stopFpsCounter
+ * @see GLAnimJPanel#getFps
+ * @see GLAnimJPanel#getFpsDuration
+ * @see GLAnimJPanel#getFpsFrames
+ * @see GLAnimJPanel#setVerboseFps
+ */
+ public void setVerboseFps(boolean v)
+ {
+ verboseFps=v;
+ }
+
+ /**
+ * returns the calculated frames per secounds
+ * <p>
+ * this data is avaiable after calling stopFpsCounter
+ *
+ * @see GLAnimJPanel#resetFpsCounter
+ * @see GLAnimJPanel#stopFpsCounter
+ * @see GLAnimJPanel#getFps
+ * @see GLAnimJPanel#getFpsDuration
+ * @see GLAnimJPanel#getFpsFrames
+ * @see GLAnimJPanel#setVerboseFps
+ */
+ public double getFps()
+ {
+ return fps;
+ }
+
+ /**
+ * returns the calculated duration in millisecs
+ * <p>
+ * this data is avaiable after calling stopFpsCounter
+ *
+ * @see GLAnimJPanel#resetFpsCounter
+ * @see GLAnimJPanel#stopFpsCounter
+ * @see GLAnimJPanel#getFps
+ * @see GLAnimJPanel#getFpsDuration
+ * @see GLAnimJPanel#getFpsFrames
+ * @see GLAnimJPanel#setVerboseFps
+ */
+ public long getFpsDuration()
+ {
+ return fps_duration;
+ }
+
+ /**
+ * returns the calculated frames number
+ * <p>
+ * this data is avaiable after calling stopFpsCounter
+ *
+ * @see GLAnimJPanel#resetFpsCounter
+ * @see GLAnimJPanel#stopFpsCounter
+ * @see GLAnimJPanel#getFps
+ * @see GLAnimJPanel#getFpsDuration
+ * @see GLAnimJPanel#getFpsFrames
+ * @see GLAnimJPanel#setVerboseFps
+ */
+ public long getFpsFrames()
+ {
+ return fps_frames;
+ }
+
+ /**
+ * Just set the FramePerSecounds for Animation
+ *
+ * @deprecated Now the frames per seconds are allways
+ * calculated, no pre-sync needed.
+ * @see #setAnimateFps(double)
+ */
+ public void setAnimateFps(double fps, int synFrames)
+ {
+ setAnimateFps(fps);
+ }
+
+ /**
+ * Just set the FramePerSecounds for Animation
+ *
+ * @see GLAnimJPanel#getMaxFps
+ */
+ public void setAnimateFps(double fps)
+ {
+ FramesPerSec=fps;
+ mSecPerFrame = (long) ( (1.0/FramesPerSec) * 1000.0 ) ;
+ if(verboseFps)
+ {
+ System.out.println("\nset fps := "+
+ String.valueOf(fps)+
+ " -> "+String.valueOf(mSecPerFrame)+
+ " [ms/frame]"
+ );
+ }
+ resetFpsCounter();
+ }
+
+ /**
+ * Just get the maximum number of Frames per secounds,
+ * which is calculated with the time, one frame needs to render !
+ *
+ * this value is avaiable after the thread is started
+ * and the first frames are rendered !
+ *
+ * @see GLAnimJPanel#setAnimateFps
+ */
+ public double getMaxFps()
+ {
+ return (1.0/(double)_f_dur_total)*1000.0;
+ }
+
+}
+
diff --git a/gl4java/swing/GLJPanel.java b/gl4java/swing/GLJPanel.java
new file mode 100644
index 0000000..21beb39
--- /dev/null
+++ b/gl4java/swing/GLJPanel.java
@@ -0,0 +1,865 @@
+package gl4java.swing;
+
+import gl4java.*;
+
+import java.awt.*;
+import java.awt.image.*;
+import java.awt.event.*;
+import javax.swing.*;
+
+/**
+ * This is meant as an base class writing
+ * easy render functions. A clean usage of multi-threading compatible
+ * with JAVA2 is implemented in GLAnimJPanel !
+ *
+ * <p>
+ *
+ * If you are interessting in further Documentation and/or
+ * the history of GL4Java follow the following link.
+ *
+ * <pre>
+ <a href="../../GL4Java.html">The GL4Java Documentation</a>
+ * </pre>
+ * <p>
+ *
+ * You should overwrite the following methods for your needs:
+ * <pre>
+ <a href="GLJPanel.html#init()">preInit - initialisation before creating GLContext</a>
+ <a href="GLJPanel.html#init()">init - 1st initialisation after creating GLContext</a>
+ <a href="GLJPanel.html#doCleanup()">doCleanup - OGL cleanup prior to context deletion</a>
+ <a href="GLJPanel.html#display()">display - render your frame</a>
+ <a href="GLJPanel.html#reshape(int, int)">reshape - to reshape (window resize), gljResize() is allready invoked !</a>
+ * </pre>
+ *
+ * To check if you can use the GLContext and GL and GLU methods,
+ * use the function
+ * <pre>
+ <a href="GLJPanel.html#cvsIsInit()">cvsIsInit</a>
+ * </pre>
+ * <p>
+ * IF you remove/release a GLJPanel,
+ * e.g. you want to close/dispose it�s Window (which contains this GLJPanel),
+ * you HAVE TO call:
+ *
+ * <pre>
+ <a href="GLJPanel.html#cvsDispose()">cvsDispose</a>
+ * </pre>
+ * You should call this before releasing/dispose this Window !
+ * Also you can overwrite this class,
+ * to dispose your own elements, e.g. a Frame etc. -
+ * but be shure that you call
+ * cvsDispose implementation call this one !
+ *
+ * <p>
+ * We do override the following Canvas methods.
+ *
+ * <pre>
+ <a href="GLJPanel.html#update(java.awt.Graphics)">update</a>
+ <a href="GLJPanel.html#paint(java.awt.Graphics)">paint</a>
+ * </pre>
+ * <p>
+ *
+ * @see GLAnimJPanel
+ * @version 2.0, 21. April 1999
+ * @author Sven Goethel
+ *
+ */
+public class GLJPanel extends JPanel
+ implements GLEnum, GLUEnum,
+ ComponentListener, WindowListener, MouseListener
+{
+ protected GLContext glj = null;
+ public GLFunc gl = null;
+ public GLUFunc glu = null;
+
+ protected boolean mustResize = false;
+
+ protected boolean cvsInitialized=false;
+
+ protected boolean needCvsDispose = false;
+
+ /**
+ * Visual pre-set for stencil-bit number, default: 0
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * @see GLJPanel#preInit
+ * @see GLJPanel#paint
+ */
+ protected int stencilBits = 0;
+
+ /**
+ * Visual pre-set for accumulator buffer size, default: 0
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * @see GLJPanel#preInit
+ * @see GLJPanel#paint
+ */
+ protected int accumSize = 0;
+
+ /**
+ * Visual pre-set for stereoView, default: false
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * @see GLJPanel#preInit
+ * @see GLJPanel#paint
+ */
+ protected boolean stereoView = false;
+
+ /**
+ * Visual pre-set for RGBA usage, default: true - of course ;-)
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * @see GLJPanel#preInit
+ * @see GLJPanel#paint
+ */
+ protected boolean rgba = true;
+
+ /**
+ * The context with witch display lists and textures will be shared.
+ *
+ * @see GLJPanel#preInit
+ * @see GLJPanel#paint
+ */
+ protected GLContext sharedGLContext;
+
+ /**
+ * The data to hold the offscreen pixels on the java side !
+ *
+ * @see GLJPanel#offImagePixels
+ * @see GLJPanel#paint
+ */
+ protected BufferedImage offImage = null;
+
+ /**
+ * The data to hold the offscreen pixels on the GL side !
+ *
+ * @see GLJPanel#offImage
+ * @see GLJPanel#paint
+ */
+ protected byte[] offImagePixels = null;
+
+ /**
+ * The custom set offscreen Size
+ *
+ * If this is set to != null,
+ * the offscreen pixmap is used in this size,
+ * not in the components-size (-> faster if smaller)
+ *
+ * @see GLJPanel#paint
+ * @see GLJPanel#setOffScreenSize
+ * @see GLJPanel#getOffScreenSize
+ */
+ protected Dimension offScrnSize = null;
+ protected boolean customOffScrnSize=false;
+ protected boolean offScrnSizeChanged=false;
+
+ static {
+ if(GLContext.loadNativeLibraries(null, null, null)==false)
+ System.out.println("GLJPanel could not load def. native libs.");
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * @param gl_Name The name of the GLFunc implementation
+ * If gl_Name==null, the default class will be used !
+ *
+ * @param glu_Name The name of the GLUFunc implementation
+ * If gl_LibName==null, the default class will be used !
+ *
+ * @param layout the layout manager
+ * @param isDoubleBuffered the flag indicates,
+ * if double buffer should be used
+ *
+ */
+ public GLJPanel( String gl_Name,
+ String glu_Name,
+ LayoutManager layout, boolean isDoubleBuffered
+ )
+ {
+ super( layout, isDoubleBuffered );
+
+ if( (gl=GLContext.createGLFunc(gl_Name)) ==null)
+ {
+ System.out.println("GLFunc implementation "+gl_Name+" not created");
+ }
+ if( (glu=GLContext.createGLUFunc(glu_Name)) ==null)
+ {
+ System.out.println("GLUFunc implementation "+glu_Name+" not created");
+ }
+
+ /* to be able for RESIZE event's */
+ addComponentListener(this);
+
+ setOpaque(false);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * @param layout the layout manager
+ * @param isDoubleBuffered the flag indicates,
+ * if double buffer should be used
+ *
+ */
+ public GLJPanel( LayoutManager layout, boolean isDoubleBuffered )
+ {
+ this(null, null, layout, isDoubleBuffered);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * Uses the default GLFunc and GLUFunc implementation !
+ *
+ * @param isDoubleBuffered the flag indicates,
+ * if double buffer should be used
+ */
+ public GLJPanel( boolean isDoubleBuffered )
+ {
+ this(null, null, new FlowLayout(), isDoubleBuffered);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * Uses the default GLFunc and GLUFunc implementation !
+ *
+ * @param layout the layout manager
+ */
+ public GLJPanel(LayoutManager layout)
+ {
+ this(null, null, layout, true);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * Uses the default GLFunc and GLUFunc implementation !
+ *
+ */
+ public GLJPanel( )
+ {
+ this(null, null, new FlowLayout(), true);
+ }
+
+ /**
+ * Used to return the created GLContext
+ */
+ public final GLContext getGLContext() { return glj; }
+
+ /**
+ * Safe the toplevel window
+ */
+ protected Window topLevelWindow = null;
+
+ /**
+ *
+ * This function returns the found TopLevelWindow,
+ * which contains this Canvas ..
+ *
+ * @return void
+ *
+ * @see GLJPanel#paint
+ */
+ public final Window getTopLevelWindow()
+ { return topLevelWindow; }
+
+ /**
+ * The customers offscreen Size
+ *
+ * If this is set,
+ * the offscreen pixmap is used in this size,
+ * not in the components-size (-> faster if smaller)
+ *
+ * @see GLJPanel#offScrnSize
+ * @see GLJPanel#setOffScreenSize
+ */
+ public Dimension getOffScreenSize()
+ { return offScrnSize; }
+
+ /**
+ * The customers offscreen Size
+ *
+ * If this is set,
+ * the offscreen pixmap is used in this size,
+ * not in the components-size (-> faster if smaller)
+ *
+ * @see GLJPanel#offScrnSize
+ * @see GLJPanel#getOffScreenSize
+ */
+ public void setOffScreenSize(Dimension size)
+ {
+ if((size!=null && size.equals(offScrnSize)==false) ||
+ size!=offScrnSize
+ )
+ {
+ offScrnSizeChanged=true;
+ offScrnSize=size;
+ customOffScrnSize=offScrnSize!=null;
+ }
+ }
+
+ /**
+ * this function overrides the Canvas paint method !
+ *
+ * For the first paint,
+ * the user function preInit is called, a GLContext is created
+ * and the user function init is called !
+ *
+ * Also, if a GL Context exist, GLJPanel's sDisplay-method will be called
+ * to do OpenGL-rendering.
+ *
+ * The sDisplay method itself calls the display-method !
+ * sDisplay is needed to be thread-safe, to manage
+ * the resize functionality and to safe the time per frame.
+ *
+ * To define your rendering, you should overwrite the display-method
+ * in your derivation.
+ *
+ * @see gl4java.GLContext#GLContext
+ * @see GLJPanel#cvsIsInit
+ * @see GLJPanel#sDisplay
+ * @see GLJPanel#display
+ * @see GLJPanel#preInit
+ * @see GLJPanel#init
+ */
+ public synchronized final void paintComponent(Graphics g)
+ {
+ if(glj == null ||
+ (mustResize && !customOffScrnSize) || offScrnSizeChanged )
+ {
+ if(mustResize)
+ {
+ cvsDispose();
+ mustResize=false;
+ }
+ preInit();
+ glj = GLContext.createOffScreenCtx ( this, gl, glu,
+ stereoView,
+ rgba, stencilBits, accumSize,
+ sharedGLContext,
+ offScrnSize
+ );
+
+ if(glj!=null)
+ {
+ /*
+ createOwnWindow = glj.isOwnWindowCreated();
+ doubleBuffer = glj.isDoubleBuffer();
+ */
+ stencilBits = glj.getStencilBitNumber();
+ accumSize = glj.getAccumSize();
+ stereoView = glj.isStereoView();
+ rgba = glj.isRGBA();
+ }
+ if(offImage!=null)
+ offImage.flush();
+ offImage=null;
+ offScrnSizeChanged=false;
+
+ init();
+
+ // fetch the top-level window ,
+ // to add us as the windowListener
+ //
+ Container _c = getParent();
+ Container c = null;
+
+ while(_c!=null)
+ {
+ c = _c;
+ _c = _c.getParent();
+ }
+
+ if(c instanceof Window) {
+ topLevelWindow = (Window)c;
+ topLevelWindow.addComponentListener(this);
+ topLevelWindow.addMouseListener(this);
+ } else {
+ topLevelWindow = null;
+ System.out.println("toplevel is not a Window: "+c);
+ }
+
+ if(topLevelWindow!=null)
+ {
+ topLevelWindow.addWindowListener(this);
+ } else {
+ System.out.println("no parent found for "+getName());
+ System.out.flush();
+ }
+ if(glj!=null && glj.gljIsInit())
+ cvsInitialized=true;
+ }
+ /*
+ if( mustResize ) size = getSize();
+ g.setClip(0, 0, size.width, size.height );
+ */
+ //super.paintComponent(g);
+
+ gr = g;
+ sDisplay();
+ }
+
+ Graphics gr = null;
+ DataBufferInt dbInt = null;
+
+ /**
+ *
+ * This is the thread save rendering-method called by paint.
+ * The actual thread will be set to highes priority befor calling
+ * 'display'. After 'display' the priority will be reset !
+ *
+ * 'gljFree' will be NOT called after 'display'.
+ *
+ * We tested the above to use multi-threading and
+ * for the demonstration 'glDemos' it works ;-)) !
+ *
+ * BE SURE, if you want to call 'display' by yourself
+ * (e.g. in the run method for animation)
+ * YOU HAVE TO CALL sDisplay -- OR YOU MUST KNOW WHAT YOU ARE DOING THEN !
+ *
+ * @return void
+ *
+ * @see GLJPanel#paint
+ * @see GLJPanel#display
+ */
+ public synchronized final void sDisplay()
+ {
+ boolean ok = true;
+
+ long _s = System.currentTimeMillis();
+
+ if(!cvsIsInit())
+ return;
+
+ if( glj.gljMakeCurrent() == false ) {
+ System.out.println("GLJPanel: problem in use() method");
+ return;
+ }
+
+ if(ok)
+ {
+ display();
+ _f_dur_self = System.currentTimeMillis()-_s;
+ if(GLContext.gljClassDebug)
+ {
+ _f_dur_self_sum+=_f_dur_self;
+ glj.gljCheckGL();
+ }
+
+ int glFormat;
+ int glComps;
+ int awtFormat;
+
+ glFormat = (rgba == true)?GL_RGBA:GL_RGB;
+ glComps = (rgba == true)?4:3;
+ awtFormat = (rgba == true)?BufferedImage.TYPE_INT_ARGB:
+ BufferedImage.TYPE_INT_RGB;
+
+ Dimension size = null;
+ if(customOffScrnSize)
+ size=offScrnSize;
+ else
+ size=getSize();
+ int w=size.width;
+ int h=size.height;
+
+ long _s_tst = System.currentTimeMillis();
+
+ if(offImage==null ||
+ offImage.getHeight()!=h || offImage.getWidth()!=w)
+ {
+ if(offImage!=null)
+ offImage.flush();
+ offImage = new BufferedImage(w,h,awtFormat);
+ offImagePixels=new byte[w*h*glComps];
+ dbInt = (DataBufferInt)
+ offImage.getRaster().getDataBuffer();
+
+ if(GLContext.gljClassDebug)
+ {
+ System.out.print("set offImage to size: "+size+
+ "(hw size: "+w+"x"+h+"), type: ");
+ switch(glFormat) {
+ case GL_RGB: System.out.println("RGB"); break;
+ case GL_RGBA: System.out.println("RGBA"); break;
+ case GL_BGR_EXT: System.out.println("BGR"); break;
+ case GL_BGRA_EXT: System.out.println("BGRA"); break;
+ }
+ }
+ }
+
+ glj.gljReadPixelGL2AWT(0,0,w,h,glFormat,GL_UNSIGNED_BYTE,
+ glj.isDoubleBuffer()?GL_BACK:GL_FRONT,
+ offImagePixels, dbInt.getData());
+
+ //glj.gljSwap(); // no true swapping with offscreen buffers ..
+
+ if(GLContext.gljClassDebug)
+ _f_dur_tst_sum+=System.currentTimeMillis()-_s_tst;
+
+ if(GLContext.gljClassDebug)
+ glj.gljCheckGL();
+ glj.gljFree(); // enable ctx for threads ...
+
+ if(!customOffScrnSize)
+ gr.drawImage(offImage, 0, 0, this);
+ else {
+ size=super.getSize();
+ gr.drawImage(offImage, 0, 0, size.width, size.height, this);
+ }
+
+ _f_dur_total = System.currentTimeMillis()-_s;
+ if(GLContext.gljClassDebug)
+ {
+ _f_dur_total_sum+=_f_dur_total;
+ if(++_f_dur_times==100)
+ {
+ System.out.println("self p 100: "+
+ (double)(_f_dur_self_sum/100)/1000.0+" s");
+
+ System.out.println("tst p 100: "+
+ (double)(_f_dur_tst_sum/100)/1000.0+" s");
+
+ System.out.println("gl-bitblit p 100: "+
+ (double)((_f_dur_total_sum-_f_dur_self_sum)/100)/1000.0+" s");
+ System.out.println("total p 100: "+
+ (double)(_f_dur_total_sum/100)/1000.0+" s");
+
+ _f_dur_self_sum=0;
+ _f_dur_tst_sum=0;
+ _f_dur_total_sum=0;
+ _f_dur_times=0;
+ }
+ }
+
+ }
+
+ }
+
+ /**
+ *
+ * This is the rendering-method called by sDisplay
+ * (and sDisplay is called by paint !).
+ * The derived-class (Your Subclass) will redefine this, to draw it's own...
+ *
+ * BE SURE, if you want to call 'display' by yourself
+ * (e.g. in the run method for animation)
+ * YOU HAVE TO CALL sDisplay !
+ *
+ * 'sDisplay' manages a semaphore to avoid reentrance of
+ * the display function !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ *
+ * @return void
+ *
+ * @see GLJPanel#sDisplay
+ * @see GLJPanel#paint
+ */
+ public void display()
+ {
+ }
+
+ /**
+ *
+ * This is your pre-init method.
+ * preInit is called just BEFORE the GL-Context is created.
+ * You should override preInit, to initialize your visual-stuff,
+ * like the protected vars: doubleBuffer and stereoView
+ *
+ * @return void
+ *
+ * @see GLJPanel#paint
+ * @see GLJPanel#doubleBuffer
+ * @see GLJPanel#stereoView
+ * @see GLJPanel#rgba
+ * @see GLJPanel#stencilBits
+ * @see GLJPanel#accumSize
+ */
+ public void preInit()
+ {
+ }
+
+ /**
+ *
+ * This is your init method.
+ * init is called right after the GL-Context is initialized.
+ * You should override init, to initialize your stuff needed
+ * by OpenGL an Java !
+ *
+ * @return void
+ *
+ * @see GLJPanel#paint
+ */
+ public void init()
+ {
+ }
+
+ /**
+ * This method is used to clean up any OpenGL stuff (delete textures
+ * or whatever) prior to actually deleting the OpenGL context.
+ * You should override this with your own version, if you need to do
+ * any cleanup work at this phase.
+ * This functions is called within cvsDispose
+ *
+ * @return void
+ *
+ * @see GLJPanel#cvsDispose
+ */
+ public void doCleanup()
+ {
+ }
+
+ /**
+ * This function returns, if everything is init: the GLContext,
+ * the and the users init function
+ * This value is set in the paint method!
+ *
+ * @return boolean
+ *
+ * @see GLJPanel#paint
+ * @see GLJPanel#init
+ */
+ public boolean cvsIsInit()
+ {
+ return cvsInitialized;
+ }
+
+ protected long _f_dur_self = 0;
+ protected long _f_dur_self_sum = 0;
+ protected long _f_dur_tst_sum = 0;
+ protected long _f_dur_total = 0;
+ protected long _f_dur_total_sum = 0;
+ protected int _f_dur_times = 0;
+
+ /**
+ *
+ * This is the reshape-method called by paint.
+ * The derived-class (Your Subclass) will redefine this,
+ * to manage your individual reshape ...
+ *
+ * This �reshape� method will be invoked after the first paint command
+ * after GLJPanel.componentResize is called AND only if �gljUse� was
+ * succesfull (so a call of gljUse is redundant).
+ * �reshape� is not an overloading of java.awt.Component.reshape,
+ * �reshape� is more like �glut�-reshape.
+ *
+ * GLJPanel.reshape allready has a simple default implementation,
+ * which calls �gljResize� and �glViewport� - so you may be can
+ * left this one as it is (no need to overload).
+ * The needed call to �gljResize� is done by hte invoker paint !
+ *
+ * @param width the new width
+ * @param height the new height
+ * @return void
+ *
+ * @see GLJPanel#paint
+ * @see GLJPanel#sDisplay
+ */
+ public void reshape( int width, int height )
+ {
+ if(GLContext.gljClassDebug)
+ System.out.println("GLJPanel::reshape bounds("+getBounds()+")");
+ gl.glViewport(0,0, width, height);
+ }
+
+ /**
+ *
+ * �componentResized� is the componentListeners event handler.
+ *
+ * This method sets the variable �mustResize� to true,
+ * so the upcoming �paint� method-call will invoke �reshape� !
+ *
+ * This little look-alike complicating thing is done,
+ * to avoid an Exception by using the glContext from more than
+ * one concurrent thread�s !
+ *
+ * You cannot override this implementation, it is final
+ * - override �reshape' instead !
+ *
+ * @param e the element, which is resized
+ * @return void
+ *
+ * @see GLJPanel#paint
+ * @see GLJPanel#reshape
+ */
+ public void componentResized(ComponentEvent e)
+ {
+ if(GLContext.gljClassDebug)
+ System.out.println("GLJPanel::componentResized("+e.getComponent()+")");
+ if(glj!=null && glj.gljIsInit() && e.getComponent()==this )
+ {
+ mustResize = true;
+ //repaint();
+ }
+ }
+
+ public void componentMoved(ComponentEvent e)
+ {
+ /*
+ if(GLContext.gljClassDebug)
+ System.out.print("GLJPanel::componentMoved("+e.getComponent()+")");
+ if(e.getComponent().equals(topLevelWindow))
+ {
+ repaint();
+ }
+ */
+ }
+
+ public void componentShown(ComponentEvent e)
+ {
+ }
+
+ public void componentHidden(ComponentEvent e)
+ {
+ }
+
+ public void mouseClicked(MouseEvent e)
+ {
+ }
+ public void mouseEntered(MouseEvent e)
+ {
+ /*
+ if(GLContext.gljClassDebug)
+ System.out.print("GLJPanel::mouseEntered("+e.getComponent()+")");
+ if(e.getComponent().equals(topLevelWindow))
+ {
+ repaint();
+ }
+ */
+ }
+ public void mouseExited(MouseEvent e)
+ {}
+ public void mousePressed(MouseEvent e)
+ {
+ }
+ public void mouseReleased(MouseEvent e)
+ {
+ }
+
+ public void windowOpened(WindowEvent e)
+ {
+ }
+
+ /**
+ *
+ * �windowClosing� is the windowListeners event handler
+ * for the topLevelWindow of this Canvas !
+ *
+ * This methods free�s AND destroy�s
+ * the GL Context with �glj.gljDestroy� !
+ *
+ * @return void
+ *
+ */
+ public void windowClosing(WindowEvent e)
+ {
+ if(e.getComponent().equals(topLevelWindow))
+ {
+ cvsDispose();
+ }
+ }
+
+ /**
+ *
+ * �windowClosed� is the windowListeners event handler.
+ *
+ * @return void
+ *
+ */
+ public void windowClosed(WindowEvent e)
+ {
+ if (needCvsDispose) cvsDispose();
+ }
+
+ public void windowIconified(WindowEvent e)
+ {
+ }
+
+ public void windowDeiconified(WindowEvent e)
+ {
+ }
+
+ public void windowActivated(WindowEvent e)
+ {
+ }
+
+ public void windowDeactivated(WindowEvent e)
+ {
+ }
+
+ /**
+ * You should call this before releasing/dispose this Window !
+ * Also you can overwrite this class,
+ * to dispose your own elements, e.g. a Frame etc. -
+ * but be shure that you call
+ * cvsDispose implementation call this one !
+ *
+ * This function calls gljDestroy of GLContext !
+ *
+ * @see gl4java.GLContext#gljDestroy
+ * @see GLJPanel#doCleanup
+ */
+ public void cvsDispose()
+ {
+ cvsInitialized = false;
+ if (glj != null)
+ {
+ if (glj.gljIsInit())
+ {
+ /* Sometimes the Microsoft VM calls the
+ Applet.stop() method but doesn't have
+ permissions to do J/Direct calls, so
+ this whole block of code will throw a
+ security exception. If this happens,
+ however, windowClosing() will still
+ call us again later and we will have
+ another opportunity to shut down the
+ context, so it all works out fine. */
+ try
+ {
+ glj.gljFree();
+ doCleanup();
+ //locks and free's GLContext
+ glj.setEnabled(false);
+ glj.gljDestroy();
+ needCvsDispose = false;
+ }
+ catch (Exception ex)
+ {
+ needCvsDispose = true;
+ }
+ }
+ }
+
+ // Setting glj to null will simply cause paint() to re-initialize.
+ // We don't want that to happen, so we will leave glj non-null.
+ }
+
+ public Dimension getSize()
+ {
+ if(customOffScrnSize)
+ return offScrnSize;
+ return super.getSize();
+ }
+
+ /**
+ * get methods
+ */
+ public final int cvsGetWidth() {
+ return getSize().width;
+ }
+ public final int cvsGetHeight() {
+ return getSize().height;
+ }
+}
+
diff --git a/gl4java/swing/GLJPanel.java,v b/gl4java/swing/GLJPanel.java,v
new file mode 100644
index 0000000..2d89e6c
--- /dev/null
+++ b/gl4java/swing/GLJPanel.java,v
@@ -0,0 +1,959 @@
+head 1.2;
+access;
+symbols;
+locks; strict;
+comment @# @;
+
+
+1.2
+date 2000.07.19.12.08.58; author sven; state Exp;
+branches;
+next 1.1;
+
+1.1
+date 2000.07.19.12.01.31; author sven; state Exp;
+branches;
+next ;
+
+
+desc
+@the first - with experimental code
+@
+
+
+1.2
+log
+@stabile
+@
+text
+@package gl4java.swing;
+
+import gl4java.*;
+
+import java.awt.*;
+import java.awt.image.*;
+import java.awt.event.*;
+import javax.swing.*;
+
+/**
+ * This is meant as an base class writing
+ * easy render functions. A clean usage of multi-threading compatible
+ * with JAVA2 is implemented in GLAnimJPanel !
+ *
+ * <p>
+ *
+ * If you are interessting in further Documentation and/or
+ * the history of GL4Java follow the following link.
+ *
+ * <pre>
+ <a href="../../GL4Java.html">The GL4Java Documentation</a>
+ * </pre>
+ * <p>
+ *
+ * You should overwrite the following methods for your needs:
+ * <pre>
+ <a href="GLJPanel.html#init()">preInit - initialisation before creating GLContext</a>
+ <a href="GLJPanel.html#init()">init - 1st initialisation after creating GLContext</a>
+ <a href="GLJPanel.html#doCleanup()">doCleanup - OGL cleanup prior to context deletion</a>
+ <a href="GLJPanel.html#display()">display - render your frame</a>
+ <a href="GLJPanel.html#reshape(int, int)">reshape - to reshape (window resize), gljResize() is allready invoked !</a>
+ * </pre>
+ *
+ * To check if you can use the GLContext and GL and GLU methods,
+ * use the function
+ * <pre>
+ <a href="GLJPanel.html#cvsIsInit()">cvsIsInit</a>
+ * </pre>
+ * <p>
+ * IF you remove/release a GLJPanel,
+ * e.g. you want to close/dispose it�s Window (which contains this GLJPanel),
+ * you HAVE TO call:
+ *
+ * <pre>
+ <a href="GLJPanel.html#cvsDispose()">cvsDispose</a>
+ * </pre>
+ * You should call this before releasing/dispose this Window !
+ * Also you can overwrite this class,
+ * to dispose your own elements, e.g. a Frame etc. -
+ * but be shure that you call
+ * cvsDispose implementation call this one !
+ *
+ * <p>
+ * We do override the following Canvas methods.
+ *
+ * <pre>
+ <a href="GLJPanel.html#update(java.awt.Graphics)">update</a>
+ <a href="GLJPanel.html#paint(java.awt.Graphics)">paint</a>
+ * </pre>
+ * <p>
+ *
+ * @@see GLAnimJPanel
+ * @@version 2.0, 21. April 1999
+ * @@author Sven Goethel
+ *
+ */
+public class GLJPanel extends JPanel
+ implements GLEnum, GLUEnum,
+ ComponentListener, WindowListener, MouseListener
+{
+ protected GLContext glj = null;
+ public GLFunc gl = null;
+ public GLUFunc glu = null;
+
+ protected boolean mustResize = false;
+
+ protected boolean cvsInitialized=false;
+
+ protected boolean needCvsDispose = false;
+
+ /**
+ * Visual pre-set for stencil-bit number, default: 0
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * @@see GLJPanel#preInit
+ * @@see GLJPanel#paint
+ */
+ protected int stencilBits = 0;
+
+ /**
+ * Visual pre-set for accumulator buffer size, default: 0
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * @@see GLJPanel#preInit
+ * @@see GLJPanel#paint
+ */
+ protected int accumSize = 0;
+
+ /**
+ * Visual pre-set for stereoView, default: false
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * @@see GLJPanel#preInit
+ * @@see GLJPanel#paint
+ */
+ protected boolean stereoView = false;
+
+ /**
+ * Visual pre-set for RGBA usage, default: true - of course ;-)
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * @@see GLJPanel#preInit
+ * @@see GLJPanel#paint
+ */
+ protected boolean rgba = true;
+
+ /**
+ * The context with witch display lists and textures will be shared.
+ *
+ * @@see GLJPanel#preInit
+ * @@see GLJPanel#paint
+ */
+ protected GLContext sharedGLContext;
+
+ /**
+ * The data to hold the offscreen pixels on the java side !
+ *
+ * @@see GLJPanel#offImagePixels
+ * @@see GLJPanel#paint
+ */
+ protected BufferedImage offImage = null;
+
+ /**
+ * The data to hold the offscreen pixels on the GL side !
+ *
+ * @@see GLJPanel#offImage
+ * @@see GLJPanel#paint
+ */
+ protected byte[] offImagePixels = null;
+
+ /**
+ * The custom set offscreen Size
+ *
+ * If this is set to != null,
+ * the offscreen pixmap is used in this size,
+ * not in the components-size (-> faster if smaller)
+ *
+ * @@see GLJPanel#paint
+ * @@see GLJPanel#setOffScreenSize
+ * @@see GLJPanel#getOffScreenSize
+ */
+ protected Dimension offScrnSize = null;
+ protected boolean customOffScrnSize=false;
+ protected boolean offScrnSizeChanged=false;
+
+ static {
+ if(GLContext.loadNativeLibraries(null, null, null)==false)
+ System.out.println("GLJPanel could not load def. native libs.");
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * @@param gl_Name The name of the GLFunc implementation
+ * If gl_Name==null, the default class will be used !
+ *
+ * @@param glu_Name The name of the GLUFunc implementation
+ * If gl_LibName==null, the default class will be used !
+ *
+ * @@param layout the layout manager
+ * @@param isDoubleBuffered the flag indicates,
+ * if double buffer should be used
+ *
+ */
+ public GLJPanel( String gl_Name,
+ String glu_Name,
+ LayoutManager layout, boolean isDoubleBuffered
+ )
+ {
+ super( layout, isDoubleBuffered );
+
+ if( (gl=GLContext.createGLFunc(gl_Name)) ==null)
+ {
+ System.out.println("GLFunc implementation "+gl_Name+" not created");
+ }
+ if( (glu=GLContext.createGLUFunc(glu_Name)) ==null)
+ {
+ System.out.println("GLUFunc implementation "+glu_Name+" not created");
+ }
+
+ /* to be able for RESIZE event's */
+ addComponentListener(this);
+
+ setOpaque(false);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * @@param layout the layout manager
+ * @@param isDoubleBuffered the flag indicates,
+ * if double buffer should be used
+ *
+ */
+ public GLJPanel( LayoutManager layout, boolean isDoubleBuffered )
+ {
+ this(null, null, layout, isDoubleBuffered);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * Uses the default GLFunc and GLUFunc implementation !
+ *
+ * @@param isDoubleBuffered the flag indicates,
+ * if double buffer should be used
+ */
+ public GLJPanel( boolean isDoubleBuffered )
+ {
+ this(null, null, new FlowLayout(), isDoubleBuffered);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * Uses the default GLFunc and GLUFunc implementation !
+ *
+ * @@param layout the layout manager
+ */
+ public GLJPanel(LayoutManager layout)
+ {
+ this(null, null, layout, true);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * Uses the default GLFunc and GLUFunc implementation !
+ *
+ */
+ public GLJPanel( )
+ {
+ this(null, null, new FlowLayout(), true);
+ }
+
+ /**
+ * Used to return the created GLContext
+ */
+ public final GLContext getGLContext() { return glj; }
+
+ /**
+ * Safe the toplevel window
+ */
+ protected Window topLevelWindow = null;
+
+ /**
+ *
+ * This function returns the found TopLevelWindow,
+ * which contains this Canvas ..
+ *
+ * @@return void
+ *
+ * @@see GLJPanel#paint
+ */
+ public final Window getTopLevelWindow()
+ { return topLevelWindow; }
+
+ /**
+ * The customers offscreen Size
+ *
+ * If this is set,
+ * the offscreen pixmap is used in this size,
+ * not in the components-size (-> faster if smaller)
+ *
+ * @@see GLJPanel#offScrnSize
+ * @@see GLJPanel#setOffScreenSize
+ */
+ public Dimension getOffScreenSize()
+ { return offScrnSize; }
+
+ /**
+ * The customers offscreen Size
+ *
+ * If this is set,
+ * the offscreen pixmap is used in this size,
+ * not in the components-size (-> faster if smaller)
+ *
+ * @@see GLJPanel#offScrnSize
+ * @@see GLJPanel#getOffScreenSize
+ */
+ public void setOffScreenSize(Dimension size)
+ {
+ if((size!=null && size.equals(offScrnSize)==false) ||
+ size!=offScrnSize
+ )
+ {
+ offScrnSizeChanged=true;
+ offScrnSize=size;
+ customOffScrnSize=offScrnSize!=null;
+ }
+ }
+
+ /**
+ * this function overrides the Canvas paint method !
+ *
+ * For the first paint,
+ * the user function preInit is called, a GLContext is created
+ * and the user function init is called !
+ *
+ * Also, if a GL Context exist, GLJPanel's sDisplay-method will be called
+ * to do OpenGL-rendering.
+ *
+ * The sDisplay method itself calls the display-method !
+ * sDisplay is needed to be thread-safe, to manage
+ * the resize functionality and to safe the time per frame.
+ *
+ * To define your rendering, you should overwrite the display-method
+ * in your derivation.
+ *
+ * @@see gl4java.GLContext#GLContext
+ * @@see GLJPanel#cvsIsInit
+ * @@see GLJPanel#sDisplay
+ * @@see GLJPanel#display
+ * @@see GLJPanel#preInit
+ * @@see GLJPanel#init
+ */
+ public synchronized final void paintComponent(Graphics g)
+ {
+ if(glj == null ||
+ (mustResize && !customOffScrnSize) || offScrnSizeChanged )
+ {
+ if(mustResize)
+ {
+ cvsDispose();
+ mustResize=false;
+ }
+ preInit();
+ glj = GLContext.createOffScreenCtx ( this, gl, glu,
+ stereoView,
+ rgba, stencilBits, accumSize,
+ sharedGLContext,
+ offScrnSize
+ );
+
+ if(glj!=null)
+ {
+ /*
+ createOwnWindow = glj.isOwnWindowCreated();
+ doubleBuffer = glj.isDoubleBuffer();
+ */
+ stencilBits = glj.getStencilBitNumber();
+ accumSize = glj.getAccumSize();
+ stereoView = glj.isStereoView();
+ rgba = glj.isRGBA();
+ }
+ if(offImage!=null)
+ offImage.flush();
+ offImage=null;
+ offScrnSizeChanged=false;
+
+ init();
+
+ // fetch the top-level window ,
+ // to add us as the windowListener
+ //
+ Container _c = getParent();
+ Container c = null;
+
+ while(_c!=null)
+ {
+ c = _c;
+ _c = _c.getParent();
+ }
+
+ if(c instanceof Window) {
+ topLevelWindow = (Window)c;
+ topLevelWindow.addComponentListener(this);
+ topLevelWindow.addMouseListener(this);
+ } else {
+ topLevelWindow = null;
+ System.out.println("toplevel is not a Window: "+c);
+ }
+
+ if(topLevelWindow!=null)
+ {
+ topLevelWindow.addWindowListener(this);
+ } else {
+ System.out.println("no parent found for "+getName());
+ System.out.flush();
+ }
+ if(glj!=null && glj.gljIsInit())
+ cvsInitialized=true;
+ }
+ /*
+ if( mustResize ) size = getSize();
+ g.setClip(0, 0, size.width, size.height );
+ */
+ //super.paintComponent(g);
+
+ gr = g;
+ sDisplay();
+ }
+
+ Graphics gr = null;
+ DataBufferInt dbInt = null;
+
+ /**
+ *
+ * This is the thread save rendering-method called by paint.
+ * The actual thread will be set to highes priority befor calling
+ * 'display'. After 'display' the priority will be reset !
+ *
+ * 'gljFree' will be NOT called after 'display'.
+ *
+ * We tested the above to use multi-threading and
+ * for the demonstration 'glDemos' it works ;-)) !
+ *
+ * BE SURE, if you want to call 'display' by yourself
+ * (e.g. in the run method for animation)
+ * YOU HAVE TO CALL sDisplay -- OR YOU MUST KNOW WHAT YOU ARE DOING THEN !
+ *
+ * @@return void
+ *
+ * @@see GLJPanel#paint
+ * @@see GLJPanel#display
+ */
+ public synchronized final void sDisplay()
+ {
+ boolean ok = true;
+
+ long _s = System.currentTimeMillis();
+
+ if(!cvsIsInit())
+ return;
+
+ if( glj.gljMakeCurrent() == false ) {
+ System.out.println("GLJPanel: problem in use() method");
+ return;
+ }
+
+ if(ok)
+ {
+ display();
+ _f_dur_self = System.currentTimeMillis()-_s;
+ if(GLContext.gljClassDebug)
+ {
+ _f_dur_self_sum+=_f_dur_self;
+ glj.gljCheckGL();
+ }
+
+ int glFormat;
+ int glComps;
+ int awtFormat;
+
+ glFormat = (rgba == true)?GL_RGBA:GL_RGB;
+ glComps = (rgba == true)?4:3;
+ awtFormat = (rgba == true)?BufferedImage.TYPE_INT_ARGB:
+ BufferedImage.TYPE_INT_RGB;
+
+ Dimension size = null;
+ if(customOffScrnSize)
+ size=offScrnSize;
+ else
+ size=getSize();
+ int w=size.width;
+ int h=size.height;
+
+ long _s_tst = System.currentTimeMillis();
+
+ if(offImage==null ||
+ offImage.getHeight()!=h || offImage.getWidth()!=w)
+ {
+ if(offImage!=null)
+ offImage.flush();
+ offImage = new BufferedImage(w,h,awtFormat);
+ offImagePixels=new byte[w*h*glComps];
+ dbInt = (DataBufferInt)
+ offImage.getRaster().getDataBuffer();
+
+ if(GLContext.gljClassDebug)
+ {
+ System.out.print("set offImage to size: "+size+
+ "(hw size: "+w+"x"+h+"), type: ");
+ switch(glFormat) {
+ case GL_RGB: System.out.println("RGB"); break;
+ case GL_RGBA: System.out.println("RGBA"); break;
+ case GL_BGR_EXT: System.out.println("BGR"); break;
+ case GL_BGRA_EXT: System.out.println("BGRA"); break;
+ }
+ }
+ }
+
+ glj.gljReadPixelGL2AWT(0,0,w,h,glFormat,GL_UNSIGNED_BYTE,
+ glj.isDoubleBuffer()?GL_BACK:GL_FRONT,
+ offImagePixels, dbInt.getData());
+
+ //glj.gljSwap(); // no true swapping with offscreen buffers ..
+
+ if(GLContext.gljClassDebug)
+ _f_dur_tst_sum+=System.currentTimeMillis()-_s_tst;
+
+ if(GLContext.gljClassDebug)
+ glj.gljCheckGL();
+ glj.gljFree(); // enable ctx for threads ...
+
+ if(!customOffScrnSize)
+ gr.drawImage(offImage, 0, 0, this);
+ else {
+ size=super.getSize();
+ gr.drawImage(offImage, 0, 0, size.width, size.height, this);
+ }
+
+ _f_dur_total = System.currentTimeMillis()-_s;
+ if(GLContext.gljClassDebug)
+ {
+ _f_dur_total_sum+=_f_dur_total;
+ if(++_f_dur_times==100)
+ {
+ System.out.println("self p 100: "+
+ (double)(_f_dur_self_sum/100)/1000.0+" s");
+
+ System.out.println("tst p 100: "+
+ (double)(_f_dur_tst_sum/100)/1000.0+" s");
+
+ System.out.println("gl-bitblit p 100: "+
+ (double)((_f_dur_total_sum-_f_dur_self_sum)/100)/1000.0+" s");
+ System.out.println("total p 100: "+
+ (double)(_f_dur_total_sum/100)/1000.0+" s");
+
+ _f_dur_self_sum=0;
+ _f_dur_tst_sum=0;
+ _f_dur_total_sum=0;
+ _f_dur_times=0;
+ }
+ }
+
+ }
+
+ }
+
+ /**
+ *
+ * This is the rendering-method called by sDisplay
+ * (and sDisplay is called by paint !).
+ * The derived-class (Your Subclass) will redefine this, to draw it's own...
+ *
+ * BE SURE, if you want to call 'display' by yourself
+ * (e.g. in the run method for animation)
+ * YOU HAVE TO CALL sDisplay !
+ *
+ * 'sDisplay' manages a semaphore to avoid reentrance of
+ * the display function !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ *
+ * @@return void
+ *
+ * @@see GLJPanel#sDisplay
+ * @@see GLJPanel#paint
+ */
+ public void display()
+ {
+ }
+
+ /**
+ *
+ * This is your pre-init method.
+ * preInit is called just BEFORE the GL-Context is created.
+ * You should override preInit, to initialize your visual-stuff,
+ * like the protected vars: doubleBuffer and stereoView
+ *
+ * @@return void
+ *
+ * @@see GLJPanel#paint
+ * @@see GLJPanel#doubleBuffer
+ * @@see GLJPanel#stereoView
+ * @@see GLJPanel#rgba
+ * @@see GLJPanel#stencilBits
+ * @@see GLJPanel#accumSize
+ */
+ public void preInit()
+ {
+ }
+
+ /**
+ *
+ * This is your init method.
+ * init is called right after the GL-Context is initialized.
+ * You should override init, to initialize your stuff needed
+ * by OpenGL an Java !
+ *
+ * @@return void
+ *
+ * @@see GLJPanel#paint
+ */
+ public void init()
+ {
+ }
+
+ /**
+ * This method is used to clean up any OpenGL stuff (delete textures
+ * or whatever) prior to actually deleting the OpenGL context.
+ * You should override this with your own version, if you need to do
+ * any cleanup work at this phase.
+ * This functions is called within cvsDispose
+ *
+ * @@return void
+ *
+ * @@see GLJPanel#cvsDispose
+ */
+ public void doCleanup()
+ {
+ }
+
+ /**
+ * This function returns, if everything is init: the GLContext,
+ * the and the users init function
+ * This value is set in the paint method!
+ *
+ * @@return boolean
+ *
+ * @@see GLJPanel#paint
+ * @@see GLJPanel#init
+ */
+ public boolean cvsIsInit()
+ {
+ return cvsInitialized;
+ }
+
+ protected long _f_dur_self = 0;
+ protected long _f_dur_self_sum = 0;
+ protected long _f_dur_tst_sum = 0;
+ protected long _f_dur_total = 0;
+ protected long _f_dur_total_sum = 0;
+ protected int _f_dur_times = 0;
+
+ /**
+ *
+ * This is the reshape-method called by paint.
+ * The derived-class (Your Subclass) will redefine this,
+ * to manage your individual reshape ...
+ *
+ * This �reshape� method will be invoked after the first paint command
+ * after GLJPanel.componentResize is called AND only if �gljUse� was
+ * succesfull (so a call of gljUse is redundant).
+ * �reshape� is not an overloading of java.awt.Component.reshape,
+ * �reshape� is more like �glut�-reshape.
+ *
+ * GLJPanel.reshape allready has a simple default implementation,
+ * which calls �gljResize� and �glViewport� - so you may be can
+ * left this one as it is (no need to overload).
+ * The needed call to �gljResize� is done by hte invoker paint !
+ *
+ * @@param width the new width
+ * @@param height the new height
+ * @@return void
+ *
+ * @@see GLJPanel#paint
+ * @@see GLJPanel#sDisplay
+ */
+ public void reshape( int width, int height )
+ {
+ if(GLContext.gljClassDebug)
+ System.out.println("GLJPanel::reshape bounds("+getBounds()+")");
+ gl.glViewport(0,0, width, height);
+ }
+
+ /**
+ *
+ * �componentResized� is the componentListeners event handler.
+ *
+ * This method sets the variable �mustResize� to true,
+ * so the upcoming �paint� method-call will invoke �reshape� !
+ *
+ * This little look-alike complicating thing is done,
+ * to avoid an Exception by using the glContext from more than
+ * one concurrent thread�s !
+ *
+ * You cannot override this implementation, it is final
+ * - override �reshape' instead !
+ *
+ * @@param e the element, which is resized
+ * @@return void
+ *
+ * @@see GLJPanel#paint
+ * @@see GLJPanel#reshape
+ */
+ public void componentResized(ComponentEvent e)
+ {
+ if(GLContext.gljClassDebug)
+ System.out.println("GLJPanel::componentResized("+e.getComponent()+")");
+ if(glj!=null && glj.gljIsInit() && e.getComponent()==this )
+ {
+ mustResize = true;
+ //repaint();
+ }
+ }
+
+ public void componentMoved(ComponentEvent e)
+ {
+ /*
+ if(GLContext.gljClassDebug)
+ System.out.print("GLJPanel::componentMoved("+e.getComponent()+")");
+ if(e.getComponent().equals(topLevelWindow))
+ {
+ repaint();
+ }
+ */
+ }
+
+ public void componentShown(ComponentEvent e)
+ {
+ }
+
+ public void componentHidden(ComponentEvent e)
+ {
+ }
+
+ public void mouseClicked(MouseEvent e)
+ {
+ }
+ public void mouseEntered(MouseEvent e)
+ {
+ /*
+ if(GLContext.gljClassDebug)
+ System.out.print("GLJPanel::mouseEntered("+e.getComponent()+")");
+ if(e.getComponent().equals(topLevelWindow))
+ {
+ repaint();
+ }
+ */
+ }
+ public void mouseExited(MouseEvent e)
+ {}
+ public void mousePressed(MouseEvent e)
+ {
+ }
+ public void mouseReleased(MouseEvent e)
+ {
+ }
+
+ public void windowOpened(WindowEvent e)
+ {
+ }
+
+ /**
+ *
+ * �windowClosing� is the windowListeners event handler
+ * for the topLevelWindow of this Canvas !
+ *
+ * This methods free�s AND destroy�s
+ * the GL Context with �glj.gljDestroy� !
+ *
+ * @@return void
+ *
+ */
+ public void windowClosing(WindowEvent e)
+ {
+ if(e.getComponent().equals(topLevelWindow))
+ {
+ cvsDispose();
+ }
+ }
+
+ /**
+ *
+ * �windowClosed� is the windowListeners event handler.
+ *
+ * @@return void
+ *
+ */
+ public void windowClosed(WindowEvent e)
+ {
+ if (needCvsDispose) cvsDispose();
+ }
+
+ public void windowIconified(WindowEvent e)
+ {
+ }
+
+ public void windowDeiconified(WindowEvent e)
+ {
+ }
+
+ public void windowActivated(WindowEvent e)
+ {
+ }
+
+ public void windowDeactivated(WindowEvent e)
+ {
+ }
+
+ /**
+ * You should call this before releasing/dispose this Window !
+ * Also you can overwrite this class,
+ * to dispose your own elements, e.g. a Frame etc. -
+ * but be shure that you call
+ * cvsDispose implementation call this one !
+ *
+ * This function calls gljDestroy of GLContext !
+ *
+ * @@see gl4java.GLContext#gljDestroy
+ * @@see GLJPanel#doCleanup
+ */
+ public void cvsDispose()
+ {
+ cvsInitialized = false;
+ if (glj != null)
+ {
+ if (glj.gljIsInit())
+ {
+ /* Sometimes the Microsoft VM calls the
+ Applet.stop() method but doesn't have
+ permissions to do J/Direct calls, so
+ this whole block of code will throw a
+ security exception. If this happens,
+ however, windowClosing() will still
+ call us again later and we will have
+ another opportunity to shut down the
+ context, so it all works out fine. */
+ try
+ {
+ glj.gljFree();
+ doCleanup();
+ //locks and free's GLContext
+ glj.setEnabled(false);
+ glj.gljDestroy();
+ needCvsDispose = false;
+ }
+ catch (Exception ex)
+ {
+ needCvsDispose = true;
+ }
+ }
+ }
+
+ // Setting glj to null will simply cause paint() to re-initialize.
+ // We don't want that to happen, so we will leave glj non-null.
+ }
+
+ public Dimension getSize()
+ {
+ if(customOffScrnSize)
+ return offScrnSize;
+ return super.getSize();
+ }
+
+ /**
+ * get methods
+ */
+ public final int cvsGetWidth() {
+ return getSize().width;
+ }
+ public final int cvsGetHeight() {
+ return getSize().height;
+ }
+}
+
+@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@a414 1
+ DataBufferByte dbByte = null;
+a438 9
+ boolean useBGR = false;
+ boolean useNativeCpy = false;
+
+ /*
+ if(glj.getNativeOSType()==GLContext.OsWindoof)
+ useBGR=true;
+ if(glj.getNativeOSType()==GLContext.OsX11)
+ useNativeCpy=true;
+ */
+d464 3
+a466 10
+ if(useBGR)
+ {
+ glFormat = (rgba == true)?GL_BGRA_EXT:GL_BGR_EXT;
+ glComps = (rgba == true)?4:3;
+ awtFormat = (rgba == true)?BufferedImage.TYPE_4BYTE_ABGR:
+ BufferedImage.TYPE_3BYTE_BGR;
+ } else {
+ glFormat = (rgba == true)?GL_RGBA:GL_RGB;
+ glComps = (rgba == true)?4:3;
+ awtFormat = (rgba == true)?BufferedImage.TYPE_INT_ARGB:
+a467 1
+ }
+d485 4
+a488 15
+ if(useBGR)
+ {
+ offImagePixels=null;
+ dbByte = (DataBufferByte)
+ offImage.getRaster().getDataBuffer();
+ dbInt = null;
+ } else {
+ if(!useNativeCpy)
+ offImagePixels=new byte[w*h*glComps];
+ else
+ offImagePixels=null;
+ dbInt = (DataBufferInt)
+ offImage.getRaster().getDataBuffer();
+ dbByte = null;
+ }
+d502 3
+a504 12
+ if(useBGR)
+ glj.gljReadPixelGL2AWT(0,0,w,h,glFormat,GL_UNSIGNED_BYTE,
+ glj.isDoubleBuffer()?GL_BACK:GL_FRONT,
+ dbByte.getData());
+ else if(useNativeCpy)
+ {
+ glj.gljCpyOffScrnImg2Buffer(w, h, glFormat, dbInt.getData());
+ glj.gljSwap();
+ } else
+ glj.gljReadPixelGL2AWT(0,0,w,h,glFormat,GL_UNSIGNED_BYTE,
+ glj.isDoubleBuffer()?GL_BACK:GL_FRONT,
+ offImagePixels, dbInt.getData());
+@
diff --git a/gl4java/swing/SimpleGLJApplet1.java b/gl4java/swing/SimpleGLJApplet1.java
new file mode 100644
index 0000000..0dc21f4
--- /dev/null
+++ b/gl4java/swing/SimpleGLJApplet1.java
@@ -0,0 +1,292 @@
+/**
+ * @(#) SimpleGLJApplet1.java
+ * @(#) author: Sven Goethel
+ */
+
+package gl4java.swing;
+
+/* This program is licensed under the LGPL */
+
+import java.applet.*;
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.lang.*;
+import gl4java.GLContext;
+import gl4java.GLFunc;
+import gl4java.GLUFunc;
+import gl4java.awt.GLAnimCanvas;
+
+public class SimpleGLJApplet1 extends JApplet
+ implements MouseListener, WindowListener, ActionListener, ItemListener
+{
+ public GLJPanel canvas = null;
+
+ public Button buttonInfo = null;
+ public Button buttonFps = null;
+ public TextField textFps = null;
+ public Checkbox checkUseRepaint = null;
+ public Checkbox checkUseFpsSleep = null;
+ public Button buttonReStart = null;
+
+
+ Frame fInfo = null;
+
+ /* Initialize the applet */
+
+ public void init()
+ {
+ JPanel master = new JPanel (new BorderLayout());
+ setContentPane(master);
+
+ JPanel pan = new JPanel();
+ pan.setLayout(new GridLayout(2,3));
+
+ buttonInfo = new Button("GL4Java");
+ buttonInfo.addMouseListener(this);
+ pan.add(buttonInfo);
+
+ checkUseRepaint = new Checkbox("repaint", true);
+ checkUseRepaint.addItemListener(this);
+ pan.add(checkUseRepaint);
+
+ checkUseFpsSleep = new Checkbox("fps-sleep", true);
+ checkUseFpsSleep.addItemListener(this);
+ pan.add(checkUseFpsSleep);
+
+ buttonReStart = new Button("start/stop");
+ buttonReStart.addMouseListener(this);
+ pan.add(buttonReStart);
+
+ buttonFps = new Button("fps: ");
+ buttonFps.addMouseListener(this);
+ pan.add(buttonFps);
+
+ textFps=new TextField("0000000000");
+ textFps.addActionListener(this);
+ pan.add(textFps);
+
+ master.add("South",pan);
+ }
+
+
+ public void start()
+ {
+ if(canvas instanceof GLAnimJPanel)
+ ((GLAnimJPanel)canvas).start();
+ }
+
+
+ public void stop()
+ {
+ if(canvas instanceof GLAnimJPanel)
+ ((GLAnimJPanel)canvas).stop();
+ }
+
+
+ public void destroy()
+ {
+ if(fInfo!=null)
+ {
+ fInfo.dispose();
+ fInfo=null;
+ }
+ if(canvas instanceof GLAnimJPanel)
+ {
+ ((GLAnimJPanel)canvas).stop();
+ ((GLAnimJPanel)canvas).cvsDispose();
+ }
+ }
+
+
+ // Methods required for the implementation of MouseListener
+ public void mouseEntered( MouseEvent evt )
+ {
+ }
+
+ public void mouseExited( MouseEvent evt )
+ {
+ }
+
+ public void mousePressed( MouseEvent evt )
+ {
+ }
+
+ public void mouseReleased( MouseEvent evt )
+ {
+ }
+
+ public void mouseClicked( MouseEvent evt )
+ {
+ Component comp = evt.getComponent();
+
+ if((canvas instanceof GLAnimJPanel)==false)
+ return;
+
+ GLAnimJPanel canvasAnim = (GLAnimJPanel)canvas;
+
+ if( canvasAnim!=null && comp.equals(buttonFps) )
+ {
+ double fps = 0;
+ int a1;
+
+ canvasAnim.stopFpsCounter();
+ fps=canvasAnim.getFps();
+ a1=(int)(fps*100.0);
+ fps=(double)a1/100.0;
+ textFps.setText(String.valueOf(fps));
+ canvasAnim.resetFpsCounter();
+ } else if( comp.equals(buttonInfo) )
+ {
+ if(fInfo==null && canvasAnim!=null && canvasAnim.getGLContext()!=null)
+ fInfo = showGLInfo();
+ }
+ else if( comp.equals(buttonReStart) )
+ {
+ canvasAnim.setSuspended(!canvasAnim.isSuspended(),
+ evt.getClickCount()>1 // -> ReInit
+ );
+ }
+ }
+
+ public void itemStateChanged( ItemEvent evt )
+ {
+ ItemSelectable comp = evt.getItemSelectable();
+
+ if((canvas instanceof GLAnimJPanel)==false)
+ return;
+
+ GLAnimJPanel canvasAnim = (GLAnimJPanel)canvas;
+
+ if( comp.equals(checkUseRepaint ) )
+ {
+ if(canvasAnim!=null)
+ {
+ canvasAnim.setUseRepaint(checkUseRepaint.getState());
+ System.out.println("canvas uses repaint: "+
+ checkUseRepaint.getState());
+ }
+ }
+ if( comp.equals(checkUseFpsSleep ) )
+ {
+ if(canvasAnim!=null)
+ {
+ canvasAnim.setUseFpsSleep(checkUseFpsSleep.getState());
+ System.out.println("canvas uses fps-sleep: "+
+ checkUseFpsSleep.getState());
+ }
+ }
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ Object source = event.getSource();
+
+ if((canvas instanceof GLAnimJPanel)==false)
+ return;
+
+ GLAnimJPanel canvasAnim = (GLAnimJPanel)canvas;
+
+ if ( source == textFps)
+ {
+ try {
+ double FramesPerSec=
+ Double.valueOf(textFps.getText()).doubleValue();
+ if(canvasAnim!=null)
+ {
+ canvasAnim.setAnimateFps(FramesPerSec);
+ canvasAnim.setSuspended(false, true);
+ }
+ } catch (NumberFormatException s) {
+ System.out.println("wrong fps format, use float ..");
+ }
+
+ }
+ }
+
+ public void windowOpened(WindowEvent e)
+ {
+ }
+
+ public void windowClosing(WindowEvent e)
+ {
+ Window w = e.getWindow();
+ if(w == fInfo && fInfo!=null)
+ {
+ fInfo.dispose();
+ fInfo=null;
+ }
+ }
+
+ public void windowClosed(WindowEvent e)
+ {
+ Window w = e.getWindow();
+ if(w == fInfo && fInfo!=null)
+ {
+ fInfo.dispose();
+ fInfo=null;
+ }
+ }
+
+ public void windowIconified(WindowEvent e)
+ {
+ }
+
+ public void windowDeiconified(WindowEvent e)
+ {
+ }
+
+ public void windowActivated(WindowEvent e)
+ {
+ }
+
+ public void windowDeactivated(WindowEvent e)
+ {
+ }
+
+ public Frame showGLInfo()
+ {
+ if(canvas==null) return null;
+
+ GLContext glc = canvas.getGLContext();
+ if(glc==null) return null;
+
+ GLFunc gl = glc.getGLFunc();
+ if(gl==null) return null;
+
+ GLUFunc glu = glc.getGLUFunc();
+ if(gl==null) return null;
+
+ if((canvas instanceof GLAnimJPanel)==false)
+ ((GLAnimJPanel)canvas).setSuspended(true, false);
+
+ Frame f = new Frame("GL4Java Version");
+ TextArea info= new TextArea(25, 80);
+ info.setEditable(false);
+ f.add(info);
+ f.setSize(600, 400);
+
+ String str = "null string";
+ if( glc.gljMakeCurrent() == false )
+ {
+ str="problem in use() method\n";
+ } else {
+ str=canvas.getGLContext().gljGetVersions();
+ if(str==null)
+ str="could not get versions";
+ System.out.println(str);
+ glc.gljFree();
+ }
+ info.append(str);
+
+ f.addWindowListener(this);
+
+ if((canvas instanceof GLAnimJPanel)==false)
+ ((GLAnimJPanel)canvas).setSuspended(false, false);
+
+ f.pack();
+ f.setVisible(true);
+
+ return f;
+ }
+}