package com.momega.spacesimulator.opengl; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Image; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLProfile; import javax.media.opengl.awt.GLCanvas; import javax.swing.JFrame; import javax.swing.JMenuBar; import javax.swing.JPopupMenu; import javax.swing.JToolBar; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.jogamp.opengl.util.AnimatorBase; import com.jogamp.opengl.util.FPSAnimator; import com.momega.spacesimulator.controller.Controller; /** * This abstract class provides basic OPENGL window, with the animator. It also registered the {@link AbstractGLRenderer} * and {@link com.momega.spacesimulator.controller.Controller} * Created by martin on 4/19/14. */ public abstract class DefaultWindow extends WindowAdapter { private static final int WINDOW_WIDTH = 1280; // width of the drawable private static final int WINDOW_HEIGHT = 640; // height of the drawable private static final int FPS = 50; // animator's target frames per second private static final Logger logger = LoggerFactory.getLogger(DefaultWindow.class); private GLCanvas canvas; private AnimatorBase animator; private String title; private JFrame frame; protected DefaultWindow(String title) { this.title = title; } public void openWindow(final AbstractGLRenderer renderer, final Controller controller) { // Run the GUI codes in the event-dispatching thread for thread safety try { EventQueue.invokeAndWait(new Runnable() { @Override public void run() { // Get the default OpenGL profile, reflecting the best for your running platform GLProfile glp = GLProfile.getDefault(); // Specifies a set of OpenGL capabilities, based on your profile. GLCapabilities caps = new GLCapabilities(glp); caps.setAlphaBits(8); caps.setStencilBits(8); // Create the OpenGL rendering canvas logger.info("GL {}", caps.toString()); canvas = new GLCanvas(caps); canvas.setPreferredSize(new Dimension(WINDOW_WIDTH, WINDOW_HEIGHT)); logger.info("Window created"); // Create a animator that drives canvas' display() at the specified FPS. animator = new FPSAnimator(canvas, FPS, true); animator.setUpdateFPSFrames(100, null); frame = new JFrame(title); JMenuBar menuBar = createMenuBar(controller); if (menuBar != null) { frame.setJMenuBar(menuBar); } Image icon = getIcon(); if (icon != null) { frame.setIconImage(icon); } JToolBar toolBar = createToolBar(controller); frame.setLayout(new java.awt.BorderLayout()); if (toolBar != null) { frame.add(toolBar, BorderLayout.PAGE_START); } frame.add(canvas, BorderLayout.CENTER); frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); createStatusBar(controller, frame); canvas.addGLEventListener(renderer); logger.info("Render set to window"); frame.setSize(WINDOW_WIDTH, WINDOW_HEIGHT); frame.setVisible(true); animator.start(); logger.info("Animator started"); canvas.requestFocus(); frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { DefaultWindow.this.windowClosing(controller); } }); canvas.addMouseListener(controller); canvas.addKeyListener(controller); canvas.addMouseMotionListener(controller); canvas.addMouseWheelListener(controller); canvas.addComponentListener(controller); JPopupMenu.setDefaultLightWeightPopupEnabled(false); } }); } catch (Exception e1) { throw new IllegalStateException(e1); } sleep(500); logger.info("main method finished"); } public GLCanvas getCanvas() { return canvas; } protected void createStatusBar(Controller controller, JFrame frame) { // do nothing } public void windowClosing(Controller controller) { logger.info("Closing window"); stopAnimator(); } protected abstract JMenuBar createMenuBar(Controller controller); protected abstract JToolBar createToolBar(Controller controller); protected Image getIcon() { return null; } public void pauseAnimator() { animator.pause(); } public void resumeAnimator() { animator.resume(); } public JFrame getFrame() { return frame; } public String getTitle() { return title; } public void stopAnimator() { logger.info("Stopping animator thread"); // Use a dedicate thread to run the stop() to ensure that the // animator stops before program exits. new Thread() { @Override public void run() { frame.dispose(); if (animator.isStarted()) { animator.stop(); } logger.info("animator stopped"); System.exit(0); } }.start(); } public void sleep(int timeout) { try { Thread.sleep(timeout); } catch (InterruptedException e) { // do nothing } } }