1 /******************************************************************************* 2 * Copyright 2011 See AUTHORS file. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 ******************************************************************************/ 16 17 package com.badlogic.gdx.backends.lwjgl; 18 19 import java.awt.Dimension; 20 import java.awt.EventQueue; 21 import java.awt.Point; 22 23 import javax.swing.JFrame; 24 25 import com.badlogic.gdx.ApplicationListener; 26 27 /** Wraps an {@link LwjglCanvas} in a resizable {@link JFrame}. */ 28 public class LwjglFrame extends JFrame { 29 LwjglCanvas lwjglCanvas; 30 private Thread shutdownHook; 31 LwjglFrame(ApplicationListener listener, String title, int width, int height)32 public LwjglFrame (ApplicationListener listener, String title, int width, int height) { 33 super(title); 34 LwjglApplicationConfiguration config = new LwjglApplicationConfiguration(); 35 config.title = title; 36 config.width = width; 37 config.height = height; 38 construct(listener, config); 39 } 40 LwjglFrame(ApplicationListener listener, LwjglApplicationConfiguration config)41 public LwjglFrame (ApplicationListener listener, LwjglApplicationConfiguration config) { 42 super(config.title); 43 construct(listener, config); 44 } 45 construct(ApplicationListener listener, LwjglApplicationConfiguration config)46 private void construct (ApplicationListener listener, LwjglApplicationConfiguration config) { 47 lwjglCanvas = new LwjglCanvas(listener, config) { 48 protected void stopped () { 49 LwjglFrame.this.dispose(); 50 } 51 52 protected void setTitle (String title) { 53 LwjglFrame.this.setTitle(title); 54 } 55 56 protected void setDisplayMode (int width, int height) { 57 LwjglFrame.this.getContentPane().setPreferredSize(new Dimension(width, height)); 58 LwjglFrame.this.getContentPane().invalidate(); 59 LwjglFrame.this.pack(); 60 LwjglFrame.this.setLocationRelativeTo(null); 61 updateSize(width, height); 62 } 63 64 protected void resize (int width, int height) { 65 updateSize(width, height); 66 } 67 68 protected void start () { 69 LwjglFrame.this.start(); 70 } 71 72 protected void exception (Throwable t) { 73 LwjglFrame.this.exception(t); 74 } 75 76 protected int getFrameRate () { 77 int frameRate = LwjglFrame.this.getFrameRate(); 78 return frameRate == 0 ? super.getFrameRate() : frameRate; 79 } 80 }; 81 82 setHaltOnShutdown(true); 83 84 setDefaultCloseOperation(EXIT_ON_CLOSE); 85 getContentPane().setPreferredSize(new Dimension(config.width, config.height)); 86 87 initialize(); 88 pack(); 89 Point location = getLocation(); 90 if (location.x == 0 && location.y == 0) setLocationRelativeTo(null); 91 lwjglCanvas.getCanvas().setSize(getSize()); 92 93 // Finish with invokeLater so any LwjglFrame super constructor has a chance to initialize. 94 EventQueue.invokeLater(new Runnable() { 95 public void run () { 96 addCanvas(); 97 setVisible(true); 98 lwjglCanvas.getCanvas().requestFocus(); 99 } 100 }); 101 } 102 103 /** When true, <code>Runtime.getRuntime().halt(0);</code> is used when the JVM shuts down. This prevents Swing shutdown hooks 104 * from causing a deadlock and keeping the JVM alive indefinitely. Default is true. */ setHaltOnShutdown(boolean halt)105 public void setHaltOnShutdown (boolean halt) { 106 if (halt) { 107 if (shutdownHook != null) return; 108 shutdownHook = new Thread() { 109 public void run () { 110 Runtime.getRuntime().halt(0); // Because fuck you, deadlock causing Swing shutdown hooks. 111 } 112 }; 113 Runtime.getRuntime().addShutdownHook(shutdownHook); 114 } else if (shutdownHook != null) { 115 Runtime.getRuntime().removeShutdownHook(shutdownHook); 116 shutdownHook = null; 117 } 118 } 119 getFrameRate()120 protected int getFrameRate () { 121 return 0; 122 } 123 exception(Throwable ex)124 protected void exception (Throwable ex) { 125 ex.printStackTrace(); 126 lwjglCanvas.stop(); 127 } 128 129 /** Called before the JFrame is made displayable. */ initialize()130 protected void initialize () { 131 } 132 133 /** Adds the canvas to the content pane. This triggers addNotify and starts the canvas' game loop. */ addCanvas()134 protected void addCanvas () { 135 getContentPane().add(lwjglCanvas.getCanvas()); 136 } 137 138 /** Called after {@link ApplicationListener} create and resize, but before the game loop iteration. */ start()139 protected void start () { 140 } 141 142 /** Called when the canvas size changes. */ updateSize(int width, int height)143 public void updateSize (int width, int height) { 144 } 145 getLwjglCanvas()146 public LwjglCanvas getLwjglCanvas () { 147 return lwjglCanvas; 148 } 149 } 150