/** * Copyright (c) 2003-2009, Xith3D Project Group all rights reserved. * * Portions based on the Java3D interface, Copyright by Sun Microsystems. * Many thanks to the developers of Java3D and Sun Microsystems for their * innovation and design. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the 'Xith3D Project Group' nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) A * RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE */ package org.xith3d.utility.launching; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.image.BufferedImage; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.Vector; import java.net.URL; import javax.imageio.ImageIO; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.DefaultComboBoxModel; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.WindowConstants; import javax.swing.border.EmptyBorder; import javax.swing.border.LineBorder; import javax.swing.border.TitledBorder; import org.xith3d.render.config.DisplayMode; import org.xith3d.render.config.DisplayModeSelector; import org.xith3d.render.config.FSAA; import org.xith3d.render.config.OpenGLLayer; import org.xith3d.render.config.DisplayMode.FullscreenMode; import org.xith3d.utility.awt.WindowHelper; /** * This class can be used to select resolution, fullscreen and OpenGLLayer * and then run an application. * * Extend this class and fill the EAST panel with additional information * to customize the dialog. * * @author Marvin Froehlich (aka Qudus) * @author jeepndesert */ public abstract class DisplayOptions extends JFrame implements ActionListener { private static final long serialVersionUID = 1493957380741174538L; protected OpenGLLayer currentOGLLayer; protected String currentDisplayMode; protected FullscreenMode currentFullscreenMode; protected boolean currentVSync; protected FSAA currentFSAA; private JComboBox oglSelector; private Map< OpenGLLayer, Integer > oglCBIndices; private JComboBox dspModeSelector; private JCheckBox fsCheck; private JCheckBox vsyncCheck; private JComboBox fsaaSelector; private Map< FSAA, Integer > fsaaCBIndices; private JButton startButton; private boolean isStartRequested = false; /** * @return a File reference to the folder, where the properties file is to * be stored. */ protected File getPropertiesFileFolder() { final File userHomeDir = new File( (String)System.getProperties().get( "user.home" ) ); return ( new File( userHomeDir, ".xith3d" ) ); } /** * @return the name of the file, where the properties are to be stored. */ protected String getPropertiesFilename() { return ( "displayoptions_selection.properties" ); } /** * @return the comment to write to the properties file */ protected String getPropertiesComment() { return ( "Last selected items in the DisplayOptions" ); } /** * @return the File reference to the properties file. * * @param forcePathExistance if true, the path is created, if it doesn't exist */ protected File findPropertiesFile( boolean forcePathExistance ) { try { File xithTLPropsFile = null; File xithPropsDir = getPropertiesFileFolder(); if ( !xithPropsDir.exists() ) { if ( forcePathExistance ) xithPropsDir.mkdir(); } if ( xithPropsDir.exists() ) { xithTLPropsFile = new File( xithPropsDir, getPropertiesFilename() ); } return ( xithTLPropsFile ); } catch ( Throwable t ) { //t.printStackTrace(); return ( null ); } } /** * Creates (and fills) the Properties object to save the current selections. * * @return the created (and filled) Properties instance */ protected Properties createProperties() { final Properties props = new Properties(); props.setProperty( "displayoptions.openGLLayer", String.valueOf( getCurrentOGLLayer() ) ); props.setProperty( "displayoptions.displayMode", getCurrentDisplayMode().toLightString() ); props.setProperty( "displayoptions.fullscreen", String.valueOf( getCurrentFullscreenMode() ) ); props.setProperty( "displayoptions.vsync", String.valueOf( getCurrentVSync() ) ); props.setProperty( "displayoptions.fsaa", String.valueOf( getCurrentFSAA() ) ); return ( props ); } private void saveSelections() { try { final File propertiesFile = findPropertiesFile( true ); if ( propertiesFile != null ) { Properties props = createProperties(); props.store( new BufferedOutputStream( new FileOutputStream( propertiesFile ) ), getPropertiesComment() ); } } catch ( Throwable t ) { //t.printStackTrace(); } } /** * Loads the selection Properties from the given File. * * @param propertiesFile the File to load the Properties from * * @return the Properties instance with the last stored selections. * * @throws IOException */ private Properties loadProperties( File propertiesFile ) throws IOException { Properties props = new Properties(); if ( ( propertiesFile != null ) && ( propertiesFile.exists() ) ) { props.load( new BufferedInputStream( new FileInputStream( propertiesFile ) ) ); } return ( props ); } protected void restoreSelections( Properties props ) throws Throwable { setCurrentOGLLayer( OpenGLLayer.valueOf( props.getProperty( "displayoptions.openGLLayer", "LWJGL" ) ) ); setCurrentDisplayMode( org.xith3d.render.config.DisplayMode.parseDisplayMode( getCurrentOGLLayer(), props.getProperty( "displayoptions.displayMode", "800X600x24x75" ) ) ); setCurrentFullscreenMode( FullscreenMode.valueOf( props.getProperty( "displayoptions.fullscreen", "WINDOWED" ) ) ); setCurrentVSync( Boolean.valueOf( props.getProperty( "displayoptions.vsync", "true" ) ) ); setCurrentFSAA( FSAA.valueOf( props.getProperty( "displayoptions.fsaa", "OFF" ) ) ); } private void restoreSelections() { try { final File propertiesFile = findPropertiesFile( false ); if ( ( propertiesFile != null ) && ( propertiesFile.exists() ) ) { final Properties props = loadProperties( propertiesFile ); restoreSelections( props ); } } catch ( Throwable t ) { //t.printStackTrace(); } } /** * This event method is executed, when the "Start"-Button is was clicked. * * @return true, to indicate success. * false to indicate an error (the DisplayOptions frame is re-shown) */ protected abstract boolean onStartButtonClicked(); /** * Defines, if the Start-Button is enabled or not. * * @param enabled */ protected void setStartButtonEnabled( boolean enabled ) { startButton.setEnabled( enabled ); } public void requestStart() { saveSelections(); //isStartRequested = true; setVisible( false ); onStartButtonClicked(); } /** * aggretation of all resolution- and fullscreen- selections * and cancel- and start-button actions. */ public void actionPerformed( ActionEvent e ) { if ( e.getSource() instanceof JCheckBox ) { if ( e.getActionCommand().startsWith( "FULLSCREEN::" ) ) { // TODO: Add support for windowed mode! currentFullscreenMode = ( (JCheckBox)e.getSource() ).isSelected() ? FullscreenMode.FULLSCREEN : FullscreenMode.WINDOWED; } else if ( e.getActionCommand().startsWith( "VSYNC::" ) ) { currentVSync = ( (JCheckBox)e.getSource() ).isSelected(); } } else if ( e.getSource() instanceof JComboBox ) { if ( e.getActionCommand().startsWith( "OPENGL_LAYER::" ) ) { final JComboBox cb = (JComboBox)e.getSource(); final Object selItem = cb.getSelectedItem(); currentOGLLayer = OpenGLLayer.valueOf( (String)selItem ); refillDisplayModeSelector(); } if ( e.getActionCommand().startsWith( "DISPLAY_MODE::" ) ) { final JComboBox cb = (JComboBox)e.getSource(); final Object selItem = cb.getSelectedItem(); currentDisplayMode = (String)selItem; } if ( e.getActionCommand().startsWith( "FSAA::" ) ) { final JComboBox cb = (JComboBox)e.getSource(); final Object selItem = cb.getSelectedItem(); currentFSAA = FSAA.valueOf( ( (String)selItem ).substring( 6 ) ); } } else if ( e.getSource() instanceof JButton ) { if ( e.getActionCommand().equals( "CANCEL" ) ) { this.setVisible( false ); System.exit( 0 ); } else if ( e.getActionCommand().equals( "START" ) ) { requestStart(); } } } private static final String[] getValidOpenGLLayersAsString() { int n = OpenGLLayer.values().length; String[] tmpItems = new String[ n ]; int j = 0; for ( int i = 0; i < n; i++ ) { OpenGLLayer ogl = OpenGLLayer.values()[i]; //if ( ogl.isStandaloneCapable() ) if ( ogl != OpenGLLayer.JOGL_SWT ) tmpItems[j++] = ogl.name(); } String[] items = new String[ j ]; System.arraycopy( tmpItems, 0, items, 0, j ); return ( items ); } /** * Creates a new JComponent with two RadioButtons to select the OpenGLLayer. * * @return the new JComponent */ protected JComponent createOpenGLLayerSelector() { JPanel panel = new JPanel( new GridLayout( 1, 1 ) ); panel.setMinimumSize( new Dimension( 1, 20 ) ); panel.setPreferredSize( new Dimension( 1, 20 ) ); panel.setMaximumSize( new Dimension( Integer.MAX_VALUE, 20 ) ); String[] items = getValidOpenGLLayersAsString(); this.oglSelector = new JComboBox( items ); oglSelector.setSelectedIndex( 0 ); oglSelector.setActionCommand( "OPENGL_LAYER::" ); oglSelector.addActionListener( this ); oglCBIndices = new HashMap< OpenGLLayer, Integer >(); for ( int i = 0; i < items.length; i++ ) { oglCBIndices.put( OpenGLLayer.valueOf( items[i] ), i ); } panel.add( oglSelector ); return ( panel ); } /** * Sets the current selected OpenGLLayer. * * @param oglLayer */ public void setCurrentOGLLayer( OpenGLLayer oglLayer ) { int index = oglCBIndices.get( oglLayer ); oglSelector.setSelectedIndex( index ); currentOGLLayer = oglLayer; } /** * @return the current selected OpenGLLayer. */ public OpenGLLayer getCurrentOGLLayer() { return ( currentOGLLayer ); } protected void refillDisplayModeSelector() { final DisplayMode currDspMode = getCurrentDisplayMode(); org.xith3d.render.config.DisplayMode[] displayModes = DisplayModeSelector.getImplementation( getCurrentOGLLayer() ).getAvailableModes(); Vector< String > modeStrings = new Vector< String >(); for ( org.xith3d.render.config.DisplayMode displayMode: displayModes ) { modeStrings.add( displayMode.toLightString() ); } dspModeSelector.setModel( new DefaultComboBoxModel( modeStrings ) ); setCurrentDisplayMode( currDspMode ); } /** * Creates a new JComponent with the DisplayMode selection controls. * * @return the created JPanel */ protected final JComponent createDisplayModeSelector() { this.dspModeSelector = new JComboBox( new String[] {} ); dspModeSelector.setMinimumSize( new Dimension( 1, 20 ) ); dspModeSelector.setPreferredSize( new Dimension( 1, 20 ) ); dspModeSelector.setMaximumSize( new Dimension( Integer.MAX_VALUE, 20 ) ); dspModeSelector.setActionCommand( "DISPLAY_MODE::" ); dspModeSelector.addActionListener( this ); refillDisplayModeSelector(); return ( dspModeSelector ); } /** * Sets the currently selected DisplayMode. * * @param displayMode */ public void setCurrentDisplayMode( DisplayMode displayMode ) { int found = 0; int selIndex = 0; for ( int i = 0; i < dspModeSelector.getItemCount(); i++ ) { final String[] modeParts = ( (String)dspModeSelector.getItemAt( i ) ).split( "x" ); final int width = Integer.parseInt( modeParts[ 0 ] ); final int height = Integer.parseInt( modeParts[ 1 ] ); final int bpp; if ( modeParts[ 2 ].equals( "?" ) ) bpp = 24; else bpp = Integer.parseInt( modeParts[ 2 ] ); final int freq; if ( modeParts[ 3 ].equals( "?" ) ) freq = 75; else freq = Integer.parseInt( modeParts[ 3 ] ); switch ( found ) { case 0: { final DisplayMode dm0 = DisplayModeSelector.getImplementation( getCurrentOGLLayer() ).getBestMode( width, height ); if ( dm0.getWidth() == displayMode.getWidth() && dm0.getHeight() == displayMode.getHeight() ) { selIndex = i; found = 1; } break; } case 1: { final DisplayMode dm1 = DisplayModeSelector.getImplementation( getCurrentOGLLayer() ).getBestMode( width, height, bpp ); if ( dm1.getWidth() == displayMode.getWidth() && dm1.getHeight() == displayMode.getHeight() && dm1.getBPP() == displayMode.getBPP() ) { selIndex = i; found = 2; } break; } case 2: { final DisplayMode dm2 = DisplayModeSelector.getImplementation( getCurrentOGLLayer() ).getBestMode( width, height, bpp, freq ); if ( dm2.getWidth() == displayMode.getWidth() && dm2.getHeight() == displayMode.getHeight() && dm2.getBPP() == displayMode.getBPP() && dm2.getFrequency() == displayMode.getFrequency() ) { selIndex = i; } break; } } } if ( dspModeSelector.getItemCount() > 0 ) dspModeSelector.setSelectedIndex( selIndex ); currentDisplayMode = displayMode.toLightString(); } /** * @return the currently selected resolution. */ public DisplayMode getCurrentDisplayMode() { final String[] modeParts = currentDisplayMode.split( "x" ); final int width = Integer.parseInt( modeParts[ 0 ] ); final int height = Integer.parseInt( modeParts[ 1 ] ); final int bpp; if ( modeParts[ 2 ].equals( "?" ) ) bpp = 24; else bpp = Integer.parseInt( modeParts[ 2 ] ); final int freq; if ( modeParts[ 3 ].equals( "?" ) ) freq = 75; else freq = Integer.parseInt( modeParts[ 3 ] ); return ( DisplayModeSelector.getImplementation( getCurrentOGLLayer() ).getBestMode( width, height, bpp, freq ) ); } /** * Creates a new JComponent with a JCheckBox to select fullscreen. * * @return the new JComponent */ protected JComponent createFullscreenSelector() { JPanel panel = new JPanel( new GridLayout( 1, 1 ) ); panel.setMinimumSize( new Dimension( 1, 20 ) ); panel.setPreferredSize( new Dimension( 1, 20 ) ); panel.setMaximumSize( new Dimension( Integer.MAX_VALUE, 20 ) ); // TODO: Add support for windowed mode! fsCheck = new JCheckBox( "Fullscreen", currentFullscreenMode.isFullscreen() ); fsCheck.setActionCommand( "FULLSCREEN::" ); fsCheck.addActionListener( this ); panel.add( fsCheck ); return ( panel ); } /** * Creates a new JComponent with a JCheckBox to select vsync. * * @return the new JComponent */ protected JComponent createVSyncSelector() { JPanel panel = new JPanel( new GridLayout( 1, 1 ) ); panel.setMinimumSize( new Dimension( 1, 20 ) ); panel.setPreferredSize( new Dimension( 1, 20 ) ); panel.setMaximumSize( new Dimension( Integer.MAX_VALUE, 20 ) ); vsyncCheck = new JCheckBox( "V-Sync", currentVSync ); vsyncCheck.setActionCommand( "VSYNC::" ); vsyncCheck.addActionListener( this ); panel.add( vsyncCheck ); return ( panel ); } /** * Changes the current state of the fullscreen selector checkbox. */ public void setCurrentFullscreenMode( FullscreenMode fs ) { fsCheck.setSelected( fs.isFullscreen() ); currentFullscreenMode = fs; } /** * @return the current state of the fullscreen selector checkbox. */ public FullscreenMode getCurrentFullscreenMode() { return ( currentFullscreenMode ); } /** * Changes the current state of the fullscreen selector checkbox. */ public void setCurrentVSync( boolean vsync ) { vsyncCheck.setSelected( vsync ); currentVSync = vsync; } /** * @return the current state of the vsync selector checkbox. */ public boolean getCurrentVSync() { return ( currentVSync ); } /** * Creates a new JComponent with a JCheckBox to select FSAA. * * @return the new JComponent */ protected JComponent createFSAASelector() { String[] items = new String[ FSAA.values().length ]; for ( int i = 0; i < FSAA.values().length; i++ ) { items[ i ] = "FSAA: " + FSAA.values()[ i ]; } this.fsaaSelector = new JComboBox( items ); fsaaSelector.setMinimumSize( new Dimension( 1, 20 ) ); fsaaSelector.setPreferredSize( new Dimension( 1, 20 ) ); fsaaSelector.setMaximumSize( new Dimension( Integer.MAX_VALUE, 20 ) ); fsaaSelector.setActionCommand( "FSAA::" ); fsaaSelector.addActionListener( this ); fsaaCBIndices = new HashMap< FSAA, Integer >(); int i = 0; for ( FSAA fsaa: FSAA.values() ) { fsaaCBIndices.put( fsaa, i++ ); } return ( fsaaSelector ); } /** * Changes the current state of the FSAA selector checkbox. */ public void setCurrentFSAA( FSAA fsaa ) { int index = fsaaCBIndices.get( fsaa ); fsaaSelector.setSelectedIndex( index ); currentFSAA = fsaa; } /** * @return the current state of the FSAA selector checkbox. */ public FSAA getCurrentFSAA() { return ( currentFSAA ); } /** * Creates a new JComponent with the content for the NORTH (header). * * @return the created JComponent */ protected JComponent createNorthComponent() { return ( null ); } /** * Creates a new JComponent with the content for the WEST-Panel. * * @return the created JComponent */ protected JComponent createCenterComponent() { return ( null ); } /** * Creates a JComponent, that will be displayed in the WEST-Panel of the * DisplayOptions Frame. Return <i>null</i> to not display a component at * this place. * * @return the created WEST-Component (or null for no component at this place) */ protected JComponent createWestComponent() { return ( null ); } /** * Creates a JComponent, that will be displayed in the NORTH-WEST of the * DisplayOptions Frame.<br> * By default this returns <i>null</i>. * * @return the created NORTH-WEST-Component (or <i>null</i> for no Component) */ protected JComponent createNorthWestComponent() { JPanel p = new JPanel(); p.setLayout( new BoxLayout( p, BoxLayout.Y_AXIS ) ); p.setBorder( new TitledBorder( new LineBorder( Color.BLACK, 2 ), "Configuration" ) ); p.add( createOpenGLLayerSelector() ); p.add( Box.createVerticalStrut( 5 ) ); p.add( createDisplayModeSelector() ); p.add( Box.createVerticalStrut( 5 ) ); p.add( createFullscreenSelector() ); p.add( Box.createVerticalStrut( 5 ) ); p.add( createVSyncSelector() ); p.add( Box.createVerticalStrut( 5 ) ); p.add( createFSAASelector() ); /* int height = 50; for ( Component comp: p.getComponents() ) { height += comp.getPreferredSize().getHeight(); } p.setMinimumSize( new Dimension( 150, height ) ); p.setPreferredSize( new Dimension( 150, height ) ); p.setMaximumSize( new Dimension( 150, height ) ); */ return ( p ); } /** * Creates a JComponent, that will be displayed in the SOUTH-WEST of the * DisplayOptions Frame. Normally it displays a logo. Return <i>null</i> * to not display a component at this place. * * @return the created SOUTH-WEST-Component (or <i>null</i> for no Component) */ @SuppressWarnings( "serial" ) protected JComponent createSouthWestComponent() { final URL location = this.getClass().getClassLoader().getResource( "resources/org/xith3d/pictures/Xith3D-Logo.png" ); if ( location == null ) return ( null ); final ImageIcon icon = new ImageIcon( location ); final double q = ( ( (double)( icon.getIconWidth() ) ) / ( (double)( icon.getIconHeight() ) ) ); JComponent logo = new JComponent() { @Override public void paintComponent( Graphics g ) { super.paintComponent( g ); final int w = getWidth() - 6; final int h = (int)( w / q ); g.drawImage( icon.getImage(), 3, getHeight() - 3 - h, w, h, this ); } }; logo.setMinimumSize( new Dimension( 0, 0 ) ); logo.setPreferredSize( new Dimension( 150, 150 / (int)q ) ); logo.setMaximumSize( new Dimension( Integer.MAX_VALUE, Integer.MAX_VALUE ) ); return ( logo ); } /** * Creates a JComponent, that will be displayed in the EAST-Panel of the * DisplayOptions Frame. Return <i>null</i> to not display a component at * this place. * * @return the created EAST-Component (or null for no component at this place) */ protected JComponent createEastComponent() { return ( null ); } /** * Creates a JComponent, that will be displayed in the EAST-Panel of the * DisplayOptions Frame. Return <i>null</i> to not display a component at * this place. * * @return the created EAST-Component (or null for no component at this place) */ protected JComponent createNorthEastComponent() { return ( null ); } /** * Creates a JComponent, that will be displayed in the EAST-Panel of the * DisplayOptions Frame. Return <i>null</i> to not display a component at * this place. * * @return the created EAST-Component (or null for no component at this place) */ protected JComponent createSouthEastComponent() { return ( null ); } /** * Creates a JComponent, that will be displayed in the SOUTH-Panel of the * DisplayOptions Frame. Return <i>null</i> to not display a component at * this place. * * @return the created SOUTH-Component (or null for no component at this place) */ protected JComponent createSouthComponent() { return ( null ); } /** * Creates a JComponent containing all the bottom-Buttons * (like Start and Cancel). * * @return the JComponent with the bottom-Buttons */ protected JComponent createFooterComponent() { final int height = 41; FlowLayout fl = new FlowLayout(); fl.setAlignment( FlowLayout.RIGHT ); JPanel comp = new JPanel( fl ); comp.setMinimumSize( new Dimension( 0, height ) ); comp.setPreferredSize( new Dimension( Integer.MAX_VALUE, height ) ); comp.setMaximumSize( new Dimension( Integer.MAX_VALUE, height ) ); comp.setBorder( new EmptyBorder( 3, 3, 3, 3 ) ); startButton = new JButton( "Start" ); startButton.setActionCommand( "START" ); startButton.addActionListener( this ); setStartButtonEnabled( true ); comp.add( startButton, null ); JButton cancelButton = new JButton( "Close" ); cancelButton.setActionCommand( "CANCEL" ); cancelButton.addActionListener( this ); comp.add( cancelButton, null ); return ( comp ); } /** * Sets the icon of this JFrame. */ protected void setIcon() { try { BufferedImage icon = ImageIO.read( this.getClass().getClassLoader().getResource( "resources/org/xith3d/pictures/Xith3D-Icon.png" ) ); this.setIconImage( icon ); } catch ( Exception e ) { //e.printStackTrace(); } } /** * Builds the whole GUI of the DisplayOptions Frame. * * @return the GUI's size */ protected Dimension buildGUI() { Dimension minSize = new Dimension( 100, 100 ); Dimension prefSize = new Dimension( 100, 200 ); Dimension maxSize = new Dimension( Integer.MAX_VALUE, Integer.MAX_VALUE ); this.setLayout( new BorderLayout() ); GridBagLayout gbl = new GridBagLayout(); GridBagLayout westGbl = new GridBagLayout(); GridBagLayout eastGbl = new GridBagLayout(); GridBagConstraints gbc; final JComponent north = createNorthComponent(); final JComponent center = createCenterComponent(); final JComponent west = createWestComponent(); final JComponent east = createEastComponent(); final JComponent south = createSouthComponent(); final JComponent footer = createFooterComponent(); final JPanel p0 = new JPanel( new BorderLayout() ); final JPanel p1 = new JPanel( gbl ); this.getContentPane().add( p0, BorderLayout.CENTER ); p0.add( p1, BorderLayout.CENTER ); if ( north != null ) { p0.add( north, BorderLayout.NORTH ); minSize.height += north.getMinimumSize().height; prefSize.height += north.getPreferredSize().height; } if ( center != null ) { //p0.add( center, BorderLayout.CENTER ); gbc = new GridBagConstraints(); gbc.gridx = 1; gbc.gridy = 0; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.fill = GridBagConstraints.BOTH; gbl.setConstraints( center, gbc ); p1.add( center ); if ( center.isMinimumSizeSet() ) { minSize.width += -100 + center.getMinimumSize().width; minSize.height += -100 + center.getMinimumSize().height; } if ( center.isPreferredSizeSet() ) { prefSize.width += -100 + center.getPreferredSize().width; prefSize.height += -200 + center.getPreferredSize().height; } } if ( west != null ) { //p0.add( west, BorderLayout.WEST ); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.WEST; gbl.setConstraints( west, gbc ); p1.add( west ); minSize.width += west.getMinimumSize().width; prefSize.width += west.getPreferredSize().width; } else { final JComponent northWest = createNorthWestComponent(); final JComponent southWest = createSouthWestComponent(); int mw1 = 0, mw2 = 0; int pw1 = 0, pw2 = 0; JPanel westPanel = null; if ( ( northWest != null ) || ( southWest != null ) ) { westPanel = new JPanel(); //westPanel.setLayout( new BoxLayout( westPanel, BoxLayout.Y_AXIS ) ); //p1.add( westPanel, BorderLayout.WEST ); westGbl = new GridBagLayout(); westPanel.setLayout( westGbl ); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.NORTHWEST; gbl.setConstraints( westPanel, gbc ); p1.add( westPanel ); } if ( northWest != null ) { //westPanel.add( northWest ); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.anchor = GridBagConstraints.NORTHWEST; westGbl.setConstraints( northWest, gbc ); westPanel.add( northWest ); mw1 = northWest.getMinimumSize().width; pw1 = northWest.getPreferredSize().width; } if ( westPanel != null ) { //westPanel.add( Box.createVerticalGlue() ); } if ( southWest != null ) { //westPanel.add( southWest ); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 1; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.anchor = GridBagConstraints.SOUTHWEST; westGbl.setConstraints( southWest, gbc ); westPanel.add( southWest ); mw2 = southWest.getMinimumSize().width; pw2 = southWest.getPreferredSize().width; } minSize.width += Math.max( mw1, mw2 ); prefSize.width += Math.max( pw1, pw2 ); } if ( east != null ) { //p0.add( east, BorderLayout.EAST ); gbc = new GridBagConstraints(); gbc.gridx = 2; gbc.gridy = 0; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.EAST; gbl.setConstraints( east, gbc ); p1.add( east ); minSize.width += east.getMinimumSize().width; prefSize.width += east.getPreferredSize().width; } else { final JComponent northEast = createNorthEastComponent(); final JComponent southEast = createSouthEastComponent(); int mw1 = 0, mw2 = 0; int pw1 = 0, pw2 = 0; JPanel eastPanel = null; if ( ( northEast != null ) || ( southEast != null ) ) { eastPanel = new JPanel(); //eastPanel.setLayout( new BoxLayout( eastPanel, BoxLayout.Y_AXIS ) ); //p0.add( eastPanel, BorderLayout.EAST ); eastGbl = new GridBagLayout(); eastPanel.setLayout( eastGbl ); gbc = new GridBagConstraints(); gbc.gridx = 2; gbc.gridy = 0; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.NORTHEAST; gbl.setConstraints( eastPanel, gbc ); p1.add( eastPanel ); } if ( northEast != null ) { //eastPanel.add( northEast ); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.anchor = GridBagConstraints.NORTHEAST; eastGbl.setConstraints( northEast, gbc ); eastPanel.add( northEast ); mw1 = northEast.getMinimumSize().width; pw1 = northEast.getPreferredSize().width; } if ( eastPanel != null ) { //eastPanel.add( Box.createVerticalGlue() ); } if ( southEast != null ) { //eastPanel.add( southEast ); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 1; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.anchor = GridBagConstraints.SOUTHEAST; eastGbl.setConstraints( southEast, gbc ); eastPanel.add( southEast ); mw2 = southEast.getMinimumSize().width; pw2 = southEast.getPreferredSize().width; } minSize.width += Math.max( mw1, mw2 ); prefSize.width += Math.max( pw1, pw2 ); } if ( south != null ) { p0.add( south, BorderLayout.SOUTH ); minSize.height += south.getMinimumSize().height; prefSize.height += south.getPreferredSize().height; } if ( footer != null ) { this.getContentPane().add( footer, BorderLayout.SOUTH ); minSize.height += footer.getMinimumSize().height; prefSize.height += footer.getPreferredSize().height; } this.setMinimumSize( minSize ); this.setPreferredSize( prefSize ); this.setMaximumSize( maxSize ); return ( prefSize ); } /** * Waits for the start Button to be clicked in this Thread. */ protected void waitForStart() { isStartRequested = false; setVisible( true ); this.setAlwaysOnTop( true ); this.toFront(); this.requestFocus(); while ( !isStartRequested ) { try { Thread.sleep( 50L ); } catch ( InterruptedException e ) { e.printStackTrace(); } } this.setVisible( false ); if ( !onStartButtonClicked() ) { waitForStart(); } } protected DisplayOptions( String title, OpenGLLayer oglLayer, DisplayMode displayMode, FullscreenMode fullscreen, boolean vsync, FSAA fsaa ) { super( title ); this.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE ); this.addWindowListener( new WindowAdapter() { @Override public void windowClosing( WindowEvent e ) { System.exit( 0 ); } } ); currentOGLLayer = oglLayer; currentDisplayMode = displayMode.toLightString(); currentFullscreenMode = fullscreen; currentVSync = vsync; currentFSAA = fsaa; setIcon(); this.setSize( buildGUI() ); WindowHelper.center( this ); restoreSelections(); waitForStart(); } protected DisplayOptions( String title, OpenGLLayer oglLayer, DisplayMode displayMode, FullscreenMode fullscreen, FSAA fsaa ) { this( title, oglLayer, displayMode, fullscreen, DisplayMode.VSYNC_ENABLED, fsaa ); } protected DisplayOptions( String title, DisplayMode displayMode, FullscreenMode fullscreen, boolean vsync, FSAA fsaa ) { this( title, OpenGLLayer.getDefault(), displayMode, fullscreen, vsync, fsaa ); } protected DisplayOptions( String title, DisplayMode displayMode, FullscreenMode fullscreen, FSAA fsaa ) { this( title, OpenGLLayer.getDefault(), displayMode, fullscreen, fsaa ); } protected DisplayOptions( String title, DisplayMode displayMode, FullscreenMode fullscreen, boolean vsync ) { this( title, displayMode, fullscreen, vsync, FSAA.OFF ); } protected DisplayOptions( String title, DisplayMode displayMode, FullscreenMode fullscreen ) { this( title, displayMode, fullscreen, FSAA.OFF ); } protected DisplayOptions( String title, DisplayMode displayMode ) { this( title, displayMode, FullscreenMode.WINDOWED ); } protected DisplayOptions( String title, boolean vsync ) { this( title, DisplayModeSelector.getImplementation( OpenGLLayer.JOGL_AWT ).getBestMode( 800, 600 ), FullscreenMode.WINDOWED, vsync ); } protected DisplayOptions( String title ) { this( title, DisplayModeSelector.getImplementation( OpenGLLayer.JOGL_AWT ).getBestMode( 800, 600 ) ); } protected DisplayOptions( boolean vsync ) { this( "Xith3DApplicationLauncher", vsync ); } protected DisplayOptions() { this( "Xith3DApplicationLauncher" ); } }