/*****************************************************************************
 *                     Yumetech, Inc Copyright (c) 2005
 *                               Java Source
 *
 * This source is licensed under the BSD-style License
 * Please read http://www.opensource.org/licenses/bsd-license.php for more
 * information or docs/BSD.txt in the downloaded code.
 *
 * This software comes with the standard NO WARRANTY disclaimer for any
 * purpose. Use it at your own risk. If there's a problem you get to fix it.
 *
 ****************************************************************************/

package org.j3d.opengl.swt;

// External imports
import java.security.AccessController;
import java.security.PrivilegedAction;

import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLDrawableFactory;

import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;

// Local imports
// None

/**
 * A widget that represents a surface that OpenGL draws into.
 * <p>
 *
 * The canvas automatically creates a GLDrawable object to correspond to this
 * canvas, and an accompanying GLContext instance. The GLContext instance, by
 * default is not synchronized.
 *
 * @author Justin Couch
 * @version $Revision: 1.3 $
 */
public class GLCanvas extends Canvas
{
    // Internal implementation notes
    //
    // There is no need to override the SWT setSize() methods to call the
    // same methods on GLDrawable. Our onscreen GLDrawable just delegates
    // the calls straight back to this component without doing anything itself
    // internally. The size of the component has no effect on the rendered
    // output. That is purely controlled by the glViewport() function call.
    // The size information is only kept by this canvas and the base classes.
    // OpenGL does nothing with it.
    //

    /** The drawable we render to */
    private GLDrawable drawable;

    /** The GL context object */
    private GLContext context;

    /**
     * Static constructor to make sure that the right system property is set
     * for our SWT-specific factory.
     */
    static
    {
        AccessController.doPrivileged(
            new PrivilegedAction ()
            {
                public Object run()
                {
                    System.setProperty("opengl.factory.class.name",
                                       "org.j3d.opengl.swt.SWTRIDrawableFactory");
                    return null;
                }
            }
        );
    }

    /**
     * Create a new isntance of this widget using the default GL capabilities.
     *
     * @param parent The parent component this widget exists in
     * @param style SWT style bits
     */
    public GLCanvas(Composite parent, int style)
    {
        this(parent, style, null, null, null);
    }

    /**
     * Create a new isntance of this widget
     *
     * @param parent The parent component this widget exists in
     * @param style SWT style bits
     * @param sharedWith The GL context to share resources with. May be null
     */
    public GLCanvas(Composite parent, int style, GLContext shareWith)
    {
        this(parent, style, null, null, shareWith);
    }

    /**
     * Create a new instance of this widget. The capabilities are defined from
     * the list of prefered options in the chooser. If no chooser is given, a
     * default implementation is used that picks the best option.
     *
     * @param parent The parent component this widget exists in
     * @param style SWT style bits
     * @param capabilities A selection of the requested capabilities
     * @param chooser A chooser to help decide between requested and available
     *    screen and device capabilities
     * @param sharedWith The GL context to share resources with. May be null
     */
    public GLCanvas(Composite parent,
                    int style,
                    GLCapabilities capabilities,
                    GLCapabilitiesChooser chooser,
                    GLContext sharedWith)
    {
        super(parent, style);

        GLDrawableFactory fac = GLDrawableFactory.getFactory();
        drawable = fac.getGLDrawable(this, capabilities, chooser);
        drawable.setRealized(true);

        context = drawable.createContext(sharedWith);
    }

    //----------------------------------------------------------
    // Local methods
    //----------------------------------------------------------

    /**
     * Get the GLContext instance that was created for this canvas instance.
     *
     * @return The current context
     */
    public GLContext getGLContext()
    {
        return context;
    }

    /**
     * Get the GLContext instance that was created for this canvas instance.
     *
     * @return The current context
     */
    public GLDrawable getGLDrawable()
    {
        return drawable;
    }
}
