package org.gbcpainter.view.menu;
import org.gbcpainter.env.GraphicsEnv;
import org.gbcpainter.env.LanguageDictionary;
import org.gbcpainter.game.GameElementFactory;
import org.gbcpainter.loaders.level.LOADING_STATUS;
import org.gbcpainter.loaders.level.LevelLoadObserver;
import org.gbcpainter.loaders.level.LevelLoader;
import org.gbcpainter.loaders.level.SimpleLevelLoader;
import org.gbcpainter.view.ErrorDialog;
import org.gbcpainter.view.GameHolder;
import org.gbcpainter.view.ViewManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.awt.event.*;
/**
* The level loading screen
* <p/>
* This menu starts a background thread when it's added to a view
*
* @author Lorenzo Pellegrini
*/
public class LevelLoadingScreen extends Panel implements LevelLoadObserver {
@NotNull
private final MenuElement failBackButton;
@NotNull
private final MenuElement loadingLabel;
@NotNull
private final String levelName;
@Nullable
private final LevelLoader loader = new SimpleLevelLoader<>( new GameElementFactory() );
private volatile boolean loadingDone = false;
@Nullable
private GameHolder holder = null;
@Nullable
private Thread holderCreator = null;
public LevelLoadingScreen( @NotNull String levelName ) {
this.levelName = levelName;
this.failBackButton = new VariableSizeMenuElement( LanguageDictionary.FAILED_LEVEL_LOADING,
Color.RED,
Color.GREEN,
Color.BLACK );
this.loadingLabel = new VariableSizeMenuElement( LanguageDictionary.LEVEL_LOADING,
Color.RED,
Color.RED,
Color.BLACK );
this.setBackground( Color.BLACK );
this.setLayout( null );
this.add( this.loadingLabel );
this.setFont( GraphicsEnv.getInstance().getBigElementsFont() );
resizeElements();
this.addComponentListener( new ComponentAdapter() {
@Override
public void componentResized( final ComponentEvent e ) {
super.componentResized( e );
resizeElements();
}
} );
}
@NotNull
private static String getLoadingDescription(
@NotNull LOADING_STATUS status ) {
switch ( status ) {
case NOT_STARTED:
return LanguageDictionary.NOT_STARTED_LOADING;
case SEARCH_FILE:
return LanguageDictionary.SEARCHING_LEVEL;
case LOAD_FILE:
return LanguageDictionary.LOADING_LEVEL_FILE;
case PARSE_DATA:
return LanguageDictionary.PARSING_LEVEL_FILE;
case DEFINE_LEVEL:
return LanguageDictionary.CREATING_LEVEL_DATA;
case INIT_LEVEL:
return LanguageDictionary.INITIALIZING_LEVEL;
case SUCCESS:
return LanguageDictionary.LEVEL_LOADED;
case FAIL:
return LanguageDictionary.LEVEL_LOAD_FAIL;
default:
throw new AssertionError( "Invalid level loading status: " + status );
}
}
@Override
public void paint( Graphics g ) {
super.paint( g );
}
@Override
public void removeNotify() {
super.removeNotify();
loadingDone = true;
}
@Override
public void addNotify() {
super.addNotify();
if ( loadingDone ) {
return;
}
this.loader.startLoading( this.levelName, this );
}
private void resizeElements() {
final Insets frameInsets = getInsets();
final Dimension realDimension = getSize();
final int viewHeight = realDimension.height - ( frameInsets.bottom + frameInsets.top );
final int viewWidth = realDimension.width - ( frameInsets.left + frameInsets.right );
failBackButton.setBounds( frameInsets.left, frameInsets.top, viewWidth, viewHeight );
loadingLabel.setBounds( frameInsets.left, frameInsets.top, viewWidth, viewHeight );
this.repaint();
}
@Override
public void loadStatusUpdated( @NotNull final LevelLoader loader ) {
final LOADING_STATUS status = this.loader.getLoadStatus();
if ( ! status.hasFinished() ) {
EventQueue.invokeLater( new Runnable() {
@Override
public void run() {
if ( ! loadingDone ) {
loadingLabel.setText( getLoadingDescription( status ) );
resizeElements();
}
}
} );
} else {
loadingDone = true;
if ( status.hasFailed() ) {
switchToFailMenu();
} else {
holderCreator = new Thread( new Runnable() {
@Override
public void run() {
try {
holder = new GameHolder( loader.getResult() );
} catch ( Exception e ) {
switchToFailMenu();
}
if( holder != null) {
EventQueue.invokeLater( new Runnable() {
@Override
public void run() {
MouseListener startLevelListener = new MouseAdapter() {
@Override
public void mouseReleased( final MouseEvent e ) {
if(holder != null) {
//If there was no errors...
ViewManager.getMainView().swapToFullView( holder );
}
}
};
loadingLabel.setText( LanguageDictionary.START_GAME_STRING );
LevelLoadingScreen.this.addMouseListener( startLevelListener );
loadingLabel.addMouseListener( startLevelListener );
resizeElements();
}
} );
}
}
});
holderCreator.start();
}
}
}
private void switchToFailMenu() {
EventQueue.invokeLater( new Runnable() {
@Override
public void run() {
MouseListener backListener = new MouseAdapter() {
@Override
public void mouseReleased( final MouseEvent e ) {
ViewManager.getMainView().swap( new MainMenu() );
}
};
LevelLoadingScreen.this.remove( loadingLabel );
LevelLoadingScreen.this.add( failBackButton );
LevelLoadingScreen.this.addMouseListener( backListener );
failBackButton.addMouseListener( backListener );
resizeElements();
}
} );
new ErrorDialog( ViewManager.getMainView().getFrame(), LanguageDictionary.ERROR_STRING,
LanguageDictionary.LEVEL_LOAD_FAIL, loader.getLoadingException() );
}
}