package org.gbcpainter.view.menu;
import org.gbcpainter.env.GameSettings;
import org.gbcpainter.env.GraphicsEnv;
import org.gbcpainter.env.LanguageDictionary;
import org.gbcpainter.view.ErrorDialog;
import org.gbcpainter.view.ViewManager;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
/**
* The settings menu
* <p/>
* This menu allows the player to modify the controls, the pause key, opengl and
* antialias settings
* <p/>
* Settings are read from {@link org.gbcpainter.env.GameSettings#getInstance()}
* and saved using {@link org.gbcpainter.env.GameSettings#storeSettings()}.
*
* @author Lorenzo Pellegrini
*/
public class SettingsMenu extends Panel {
private static final Color KEY_CONFLICT_COLOR = Color.MAGENTA;
private static final int CONTROLS_NUMBER = 5;
@NonNls
private static final String SETTINGS_SEPARATOR = " : ";
private final MenuElement controlUpLabel
= new FixedSizeMenuElement( LanguageDictionary.UP_STRING + SETTINGS_SEPARATOR,
Color.RED,
Color.RED,
Color.BLACK );
private final MenuElement controlDownLabel
= new FixedSizeMenuElement( LanguageDictionary.DOWN_STRING + SETTINGS_SEPARATOR,
Color.RED,
Color.RED,
Color.BLACK );
private final MenuElement controlLeftLabel
= new FixedSizeMenuElement( LanguageDictionary.LEFT_STRING + SETTINGS_SEPARATOR,
Color.RED,
Color.RED,
Color.BLACK );
private final MenuElement controlRightLabel
= new FixedSizeMenuElement( LanguageDictionary.RIGHT_STRING + SETTINGS_SEPARATOR,
Color.RED,
Color.RED,
Color.BLACK );
private final MenuElement controlPauseLabel
= new FixedSizeMenuElement( LanguageDictionary.PAUSE_STRING + SETTINGS_SEPARATOR,
Color.RED,
Color.RED,
Color.BLACK );
private final MenuElement controlOpenGLLabel
= new FixedSizeMenuElement( LanguageDictionary.OPENGL_STRING + SETTINGS_SEPARATOR,
Color.RED,
Color.RED,
Color.BLACK );
private final MenuElement controlAntialiasLabel
= new FixedSizeMenuElement( LanguageDictionary.ANTIALIAS_STRING + SETTINGS_SEPARATOR,
Color.RED,
Color.RED,
Color.BLACK );
private final MenuElement backButton =
new FixedSizeMenuElement( LanguageDictionary.BACK_TO_MENU_STRING,
Color.RED,
Color.GREEN,
Color.BLACK );
private final MenuElement saveButton =
new FixedSizeMenuElement( LanguageDictionary.SAVE_SETTINGS,
Color.RED,
Color.GREEN,
Color.BLACK );
private final MenuElement controlUp;
private final MenuElement controlDown;
private final MenuElement controlLeft;
private final MenuElement controlRight;
private final MenuElement controlPause;
private final MenuElement controlOpenGL;
private final MenuElement controlAntialias;
private int selectedControlUp = GameSettings.getInstance()
.getValue( GameSettings.INTEGER_SETTINGS_TYPE.KEY_UP );
private int selectedControlDown = GameSettings.getInstance()
.getValue( GameSettings.INTEGER_SETTINGS_TYPE.KEY_DOWN );
private int selectedControlLeft = GameSettings.getInstance()
.getValue( GameSettings.INTEGER_SETTINGS_TYPE.KEY_LEFT );
private int selectedControlRight = GameSettings.getInstance()
.getValue( GameSettings.INTEGER_SETTINGS_TYPE.KEY_RIGHT );
private int selectedControlPause = GameSettings.getInstance()
.getValue( GameSettings.INTEGER_SETTINGS_TYPE.KEY_PAUSE );
private boolean selectedOpenGL = GameSettings.getInstance()
.getNextRunValue( GameSettings.INTEGER_SETTINGS_TYPE.OPENGL ) != 0;
private boolean selectedAntialias = GameSettings.getInstance()
.getNextRunValue(
GameSettings.INTEGER_SETTINGS_TYPE.ANTIALIAS ) != 0;
@Nullable
private CONTROLS_SETTING modifyingSetting = null;
/**
* Creates the settings menu.
* <p/>
* Settings are read from {@link org.gbcpainter.env.GameSettings#getInstance()}
* and saved using {@link org.gbcpainter.env.GameSettings#storeSettings()}.
*/
public SettingsMenu() {
super( new GridBagLayout() );
this.setBackground( Color.RED );
controlUp = new FixedSizeMenuElement( "",
Color.RED,
Color.GREEN,
Color.BLACK );
controlDown = new FixedSizeMenuElement( "",
Color.RED,
Color.GREEN,
Color.BLACK );
controlLeft = new FixedSizeMenuElement( "",
Color.RED,
Color.GREEN,
Color.BLACK );
controlRight = new FixedSizeMenuElement( "",
Color.RED,
Color.GREEN,
Color.BLACK );
controlPause = new FixedSizeMenuElement( "",
Color.RED,
Color.GREEN,
Color.BLACK );
controlOpenGL = new FixedSizeMenuElement( "",
Color.RED,
Color.GREEN,
Color.BLACK );
controlAntialias = new FixedSizeMenuElement( "",
Color.RED,
Color.GREEN,
Color.BLACK );
changeControlsText();
controlUp
.addMouseListener( new SimpleEditor( CONTROLS_SETTING.CONTROL_UP ) );
controlDown
.addMouseListener( new SimpleEditor( CONTROLS_SETTING.CONTROL_DOWN ) );
controlLeft
.addMouseListener( new SimpleEditor( CONTROLS_SETTING.CONTROL_LEFT ) );
controlRight
.addMouseListener( new SimpleEditor( CONTROLS_SETTING.CONTROL_RIGHT ) );
controlPause
.addMouseListener( new SimpleEditor( CONTROLS_SETTING.CONTROL_PAUSE ) );
controlOpenGL
.addMouseListener( new SimpleSwitcher( SWITCH_SETTING.OPENGL ) );
controlAntialias
.addMouseListener( new SimpleSwitcher( SWITCH_SETTING.ANTIALIAS ) );
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.BOTH;
constraints.weighty = 1.0;
constraints.weightx = 1.0;
constraints.gridx = 0;
constraints.gridy = 0;
this.add( controlUpLabel, constraints );
constraints.gridy++;
this.add( controlDownLabel, constraints );
constraints.gridy++;
this.add( controlLeftLabel, constraints );
constraints.gridy++;
this.add( controlRightLabel, constraints );
constraints.gridy++;
this.add( controlPauseLabel, constraints );
constraints.gridy++;
this.add( controlOpenGLLabel, constraints );
constraints.gridy++;
this.add( controlAntialiasLabel, constraints );
constraints.gridx = 1;
constraints.gridy = 0;
this.add( controlUp, constraints );
constraints.gridy++;
this.add( controlDown, constraints );
constraints.gridy++;
this.add( controlLeft, constraints );
constraints.gridy++;
this.add( controlRight, constraints );
constraints.gridy++;
this.add( controlPause, constraints );
constraints.gridy++;
this.add( controlOpenGL, constraints );
constraints.gridy++;
this.add( controlAntialias, constraints );
backButton.addMouseListener( new MouseAdapter() {
@Override
public void mouseReleased( final MouseEvent e ) {
ViewManager.getMainView().swap( new MainMenu() );
}
} );
saveButton.addMouseListener( new MouseAdapter() {
@Override
public void mouseReleased( final MouseEvent e ) {
Map<Integer, Collection<CONTROLS_SETTING>> keyToSetting = new HashMap<>(
CONTROLS_NUMBER );
keyToSetting.put( selectedControlUp,
new LinkedList<CONTROLS_SETTING>() );
keyToSetting.put( selectedControlDown,
new LinkedList<CONTROLS_SETTING>() );
keyToSetting.put( selectedControlLeft,
new LinkedList<CONTROLS_SETTING>() );
keyToSetting.put( selectedControlRight,
new LinkedList<CONTROLS_SETTING>() );
keyToSetting.put( selectedControlPause,
new LinkedList<CONTROLS_SETTING>() );
keyToSetting.get( selectedControlUp )
.add( CONTROLS_SETTING.CONTROL_UP );
keyToSetting.get( selectedControlDown )
.add( CONTROLS_SETTING.CONTROL_DOWN );
keyToSetting.get( selectedControlLeft )
.add( CONTROLS_SETTING.CONTROL_LEFT );
keyToSetting.get( selectedControlRight )
.add( CONTROLS_SETTING.CONTROL_RIGHT );
keyToSetting.get( selectedControlPause )
.add( CONTROLS_SETTING.CONTROL_PAUSE );
for (Collection<CONTROLS_SETTING> editableSettings : keyToSetting
.values()) {
if ( editableSettings.size() != 1 ) {
for (CONTROLS_SETTING editableSetting : editableSettings) {
enumToMenuElement( editableSetting )
.setMouseLeftColor( KEY_CONFLICT_COLOR );
}
} else {
enumToMenuElement( editableSettings.iterator().next() )
.setMouseLeftColor( Color.RED );
}
}
if ( keyToSetting.size() == CONTROLS_NUMBER ) {
GameSettings.getInstance()
.updateData( GameSettings.INTEGER_SETTINGS_TYPE.KEY_UP,
selectedControlUp );
GameSettings.getInstance()
.updateData( GameSettings.INTEGER_SETTINGS_TYPE.KEY_DOWN,
selectedControlDown );
GameSettings.getInstance()
.updateData( GameSettings.INTEGER_SETTINGS_TYPE.KEY_LEFT,
selectedControlLeft );
GameSettings.getInstance()
.updateData( GameSettings.INTEGER_SETTINGS_TYPE.KEY_RIGHT,
selectedControlRight );
GameSettings.getInstance()
.updateData( GameSettings.INTEGER_SETTINGS_TYPE.KEY_PAUSE,
selectedControlPause );
GameSettings.getInstance()
.updateNextRunData( GameSettings.INTEGER_SETTINGS_TYPE.OPENGL,
selectedOpenGL ? 1 : 0 );
GameSettings.getInstance()
.updateNextRunData( GameSettings.INTEGER_SETTINGS_TYPE.ANTIALIAS,
selectedAntialias ? 1 : 0 );
new Thread( new Runnable() {
@Override
public void run() {
try {
GameSettings.getInstance().storeSettings();
} catch ( IOException e1 ) {
new ErrorDialog( ViewManager.getMainView()
.getFrame(),
LanguageDictionary.ERROR_STRING,
LanguageDictionary.ERROR_SAVE_SETTINGS,
e1 );
}
}
} ).start();
ViewManager.getMainView().swap( new MainMenu() );
}
}
} );
constraints.gridx = 0;
constraints.gridy++;
constraints.insets = new Insets( 1, 0, 0, 0 );
this.add( backButton, constraints );
constraints.gridx++;
this.add( saveButton, constraints );
this.addComponentListener( GraphicsEnv.getInstance()
.utilGetSmallElementsResizeHandler(
controlUpLabel,
controlDownLabel,
controlLeftLabel,
controlRightLabel,
controlPauseLabel,
controlUp,
controlDown,
controlLeft,
controlRight,
controlPause ) );
this.addComponentListener( GraphicsEnv.getInstance()
.utilGetSmallElementsResizeHandler(
controlOpenGLLabel,
controlAntialiasLabel,
controlOpenGL,
controlAntialias,
backButton,
saveButton ) );
this.addKeyListener( new SimpleKeyEditor() );
this.setFocusable( true );
}
@Override
public void addNotify() {
super.addNotify();
this.requestFocus();
}
private void changeControlsText() {
controlUp.setText( KeyEvent.getKeyText( selectedControlUp ) );
controlDown.setText( KeyEvent.getKeyText( selectedControlDown ) );
controlLeft.setText( KeyEvent.getKeyText( selectedControlLeft ) );
controlRight.setText( KeyEvent.getKeyText( selectedControlRight ) );
controlPause.setText( KeyEvent.getKeyText( selectedControlPause ) );
controlOpenGL.setText( ( selectedOpenGL )
? LanguageDictionary.YES_STRING
: LanguageDictionary.NO_STRING );
controlAntialias.setText( ( selectedAntialias )
? LanguageDictionary.YES_STRING
: LanguageDictionary.NO_STRING );
}
@NotNull
private MenuElement enumToMenuElement( @NotNull CONTROLS_SETTING setting ) {
switch ( setting ) {
case CONTROL_UP:
return controlUp;
case CONTROL_DOWN:
return controlDown;
case CONTROL_LEFT:
return controlLeft;
case CONTROL_RIGHT:
return controlRight;
case CONTROL_PAUSE:
return controlPause;
}
throw new AssertionError( "Invalid enum constant " + setting );
}
@NotNull
private MenuElement enumToMenuElement( @NotNull SWITCH_SETTING setting ) {
switch ( setting ) {
case OPENGL:
return controlOpenGL;
case ANTIALIAS:
return controlAntialias;
}
throw new AssertionError( "Invalid enum constant " + setting );
}
private static enum CONTROLS_SETTING {
CONTROL_UP, CONTROL_DOWN, CONTROL_LEFT, CONTROL_RIGHT, CONTROL_PAUSE
}
private static enum SWITCH_SETTING {
OPENGL, ANTIALIAS
}
private class SimpleSwitcher extends MouseAdapter {
@NotNull
private final SWITCH_SETTING setting;
public SimpleSwitcher( @NotNull SWITCH_SETTING setting ) {
this.setting = setting;
}
@Override
public void mouseReleased( final MouseEvent e ) {
super.mouseReleased( e );
switch ( setting ) {
case OPENGL:
selectedOpenGL = ! selectedOpenGL;
break;
case ANTIALIAS:
selectedAntialias = ! selectedAntialias;
break;
default:
throw new AssertionError( "Invalid enum constant " + setting );
}
changeControlsText();
}
}
private class SimpleEditor extends MouseAdapter {
@NotNull
private final CONTROLS_SETTING setting;
public SimpleEditor( @NotNull CONTROLS_SETTING setting ) {
this.setting = setting;
}
@Override
public void mouseReleased( final MouseEvent e ) {
super.mouseReleased( e );
if ( modifyingSetting != null ) {
/* User aborted editing */
enumToMenuElement( modifyingSetting )
.setMouseLeftColor( Color.RED );
modifyingSetting = null;
} else {
modifyingSetting = setting;
enumToMenuElement( modifyingSetting )
.setMouseLeftColor( Color.ORANGE );
requestFocusInWindow();
}
}
}
private class SimpleKeyEditor extends KeyAdapter {
@Override
public void keyReleased( final KeyEvent e ) {
final int key = e.getKeyCode();
//LOGGER.finer( "Pressed key: " + key + " while modifying " + modifyingSetting );
if ( modifyingSetting != null ) {
switch ( modifyingSetting ) {
case CONTROL_UP:
selectedControlUp = key;
break;
case CONTROL_DOWN:
selectedControlDown = key;
break;
case CONTROL_LEFT:
selectedControlLeft = key;
break;
case CONTROL_RIGHT:
selectedControlRight = key;
break;
case CONTROL_PAUSE:
selectedControlPause = key;
break;
default:
throw new AssertionError( "Unknown key setting: " + modifyingSetting );
}
changeControlsText();
enumToMenuElement( modifyingSetting )
.setMouseLeftColor( Color.RED );
modifyingSetting = null;
}
}
}
}