From f91d90c201006ecb06faee82af4865f13b37d7f9 Mon Sep 17 00:00:00 2001 From: Lance Ewing Date: Sun, 28 Apr 2024 23:41:02 +0100 Subject: [PATCH] Added title page to the home screen, with info icon to show About message dialog. --- .../java/com/agifans/agile/HomeScreen.java | 210 ++++++++++++++---- .../com/agifans/agile/ui/DialogHandler.java | 10 +- .../com/agifans/agile/ui/PagedScrollPane.java | 4 +- .../agifans/agile/gwt/GwtDialogHandler.java | 59 ++++- .../agile/lwjgl3/DesktopDialogHandler.java | 150 +++++++++++++ 5 files changed, 377 insertions(+), 56 deletions(-) diff --git a/core/src/main/java/com/agifans/agile/HomeScreen.java b/core/src/main/java/com/agifans/agile/HomeScreen.java index 770a0e7..364f5b0 100644 --- a/core/src/main/java/com/agifans/agile/HomeScreen.java +++ b/core/src/main/java/com/agifans/agile/HomeScreen.java @@ -77,6 +77,7 @@ public class HomeScreen extends InputAdapter implements Screen { private PaginationWidget portraitPaginationWidget; private PaginationWidget landscapePaginationWidget; private Texture whitePixelTexture; + private Texture titleTexture; /** * Invoked by AGILE whenever it would like to show a dialog, such as when it needs @@ -123,6 +124,11 @@ public class HomeScreen extends InputAdapter implements Screen { SIERRA_GAMES.add("bc"); } + /** + * Holds a reference to the AppConfigItem for the last game that was launched. + */ + private AppConfigItem lastGameLaunched; + /** * Constructor for HomeScreen. * @@ -147,6 +153,7 @@ public HomeScreen(Agile agile, DialogHandler dialogHandler) { skin.add("top", skin.newDrawable("default-round", new Color(0, 0, 0, 0)), Drawable.class); skin.add("empty", skin.newDrawable("default-round", new Color(1f, 1f, 1f, 0.1f)), Drawable.class); + titleTexture = new Texture("png/agile_title.png"); backgroundLandscape = new Texture("jpg/landscape_back.jpg"); backgroundLandscape.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear); backgroundPortrait = new Texture("jpg/portrait_back.jpg"); @@ -233,6 +240,9 @@ private void addAppButtonsToStage(Stage stage, PaginationWidget paginationWidget stage.addActor(container); container.setFillParent(true); + Table currentPage = new Table().pad(0, 0, 0, 0); + Image title = new Image(titleTexture); + float viewportWidth = viewportManager.getWidth(); float viewportHeight = viewportManager.getHeight(); @@ -245,18 +255,28 @@ private void addAppButtonsToStage(Stage stage, PaginationWidget paginationWidget int totalHorizPadding = 0; int horizPaddingUnit = 0; + Button infoButton = buildButton("INFO", null, "png/info.png", 96, 96, null, null); + currentPage.add().expandX(); + currentPage.add(infoButton).pad(16, 0, 0, 16).align(Align.right).expandX(); + currentPage.row(); + currentPage.add().expandX(); + if (viewportManager.isLandscape()) { // Landscape. - //sidePadding = 85; // 100 leaves 24 (i.e. 12 * 2) between. 85 leaves 30. container.setBackground(new Image(backgroundLandscape).getDrawable()); totalHorizPadding = 1920 - (ICON_IMAGE_WIDTH * columns) - (sidePadding * 2); horizPaddingUnit = totalHorizPadding / (columns * 2); + int titleWidth = 428; + float titlePadding = ((1920 - titleWidth) / 2); + currentPage.add(title).width(titleWidth).height(197).pad(0, titlePadding, 112 - 26, titlePadding).expand(); } else { // Portrait. - //sidePadding = 15; // 24 leaves 24 between. 15 leaves 30. container.setBackground(new Image(backgroundPortrait).getDrawable()); totalHorizPadding = 1080 - (ICON_IMAGE_WIDTH * columns) - (sidePadding * 2); horizPaddingUnit = totalHorizPadding / (columns * 2); + int titleWidth = 428; + float titlePadding = ((1080 - titleWidth) / 2); + currentPage.add(title).width(titleWidth).height(197).pad(0, titlePadding, 112 - 26, titlePadding).expand(); } PagedScrollPane pagedScrollPane = new PagedScrollPane(); @@ -265,7 +285,10 @@ private void addAppButtonsToStage(Stage stage, PaginationWidget paginationWidget int itemsPerPage = columns * rows; int pageItemCount = 0; - Table currentPage = new Table().pad(0, sidePadding, 0, sidePadding); + // Set up first page, which is mainly empty. + pagedScrollPane.addPage(currentPage); + + currentPage = new Table().pad(0, sidePadding, 0, sidePadding); currentPage.defaults().pad(0, horizPaddingUnit, 0, horizPaddingUnit); // Add empty slot at the start that will always be present for adding a new game. @@ -360,6 +383,13 @@ public void resize(int width, int height) { Gdx.input.setInputProcessor(landscapeInputProcessor); } updateHomeScreenButtonStages(); + + // Screen is resized after returning from GameScreen, so we need to scroll + // back to the page that the game that was running was on. + if (lastGameLaunched != null) { + showGamePage(lastGameLaunched, true); + lastGameLaunched = null; + } } @Override @@ -386,7 +416,7 @@ public void dispose() { whitePixelTexture.dispose(); landscapePaginationWidget.dispose(); portraitPaginationWidget.dispose(); - + titleTexture.dispose(); saveAppConfigMap(); } @@ -512,23 +542,44 @@ public Texture drawEmptyIcon(int iconWidth, int iconHeight) { private static final int ICON_IMAGE_HEIGHT = 240; private static final int ICON_LABEL_HEIGHT = 90; private static final int PAGINATION_HEIGHT = 60; - + /** * Creates a button to represent the given AppConfigItem. * - * @param appConfigItem AppConfigItem containing details about the app to build a Button to represent. + * @param appConfigItem * - * @return The button to use for running the given AppConfigItem. + * @return */ - public Button buildAppButton(AppConfigItem appConfigItem) { + private Button buildAppButton(AppConfigItem appConfigItem) { + String iconPath = appConfigItem.getGameId() != null? + StringUtils.format("screenshots/{0}.png", appConfigItem.getGameId().toUpperCase()) : ""; + return buildButton( + appConfigItem.getName(), + appConfigItem.getDisplayName() != null? appConfigItem.getDisplayName() : "", + iconPath, + ICON_IMAGE_WIDTH, ICON_IMAGE_HEIGHT, + appConfigItem.getFileType(), + appConfigItem.getGameId()); + } + + /** + * Creates a button using the given parameters. + * + * @param name + * @param displayName + * @param iconPath + * @param type + * @param gameId + * + * @return The created Button. + */ + private Button buildButton(String name, String labelText, String iconPath, int width, int height, String type, String gameId) { Button button = new Button(skin); ButtonStyle style = button.getStyle(); style.up = style.down = null; // An app button can contain an optional icon. Image icon = null; - String iconPath = appConfigItem.getGameId() != null? - StringUtils.format("screenshots/{0}.png", appConfigItem.getGameId().toUpperCase()) : ""; Texture iconTexture = buttonTextureMap.get(iconPath); if (iconTexture == null) { @@ -536,13 +587,13 @@ public Button buildAppButton(AppConfigItem appConfigItem) { try { // See if there is screenshot icon in the assets folder. Pixmap iconPixmap = new Pixmap(Gdx.files.internal(iconPath)); - if ("UNK".equals(appConfigItem.getFileType())) { + if ("UNK".equals(type)) { iconPixmap.setColor(0.0f, 0.0f, 0.0f, 0.5f); iconPixmap.fillRectangle(0, 0, iconPixmap.getWidth(), iconPixmap.getHeight()); } // If there is, then it's expected to be 320x200, so we scale it to right aspect ratio. - Pixmap iconStretchedPixmap = new Pixmap(ICON_IMAGE_WIDTH, ICON_IMAGE_HEIGHT, iconPixmap.getFormat()); + Pixmap iconStretchedPixmap = new Pixmap(width, height, iconPixmap.getFormat()); iconStretchedPixmap.drawPixmap(iconPixmap, 0, 0, iconPixmap.getWidth(), iconPixmap.getHeight(), 0, 0, iconStretchedPixmap.getWidth(), iconStretchedPixmap.getHeight() @@ -556,10 +607,10 @@ public Button buildAppButton(AppConfigItem appConfigItem) { icon = new Image(iconTexture); icon.setAlign(Align.center); } catch (Exception e) { - icon = new Image(drawEmptyIcon(ICON_IMAGE_WIDTH, ICON_IMAGE_HEIGHT)); + icon = new Image(drawEmptyIcon(width, height)); } } else { - icon = new Image(drawEmptyIcon(ICON_IMAGE_WIDTH, ICON_IMAGE_HEIGHT)); + icon = new Image(drawEmptyIcon(width, height)); } } else { icon = new Image(iconTexture); @@ -570,31 +621,33 @@ public Button buildAppButton(AppConfigItem appConfigItem) { Container iconContainer = new Container(); iconContainer.setActor(icon); iconContainer.align(Align.center); - button.stack(new Image(skin.getDrawable("top")), iconContainer).width(ICON_IMAGE_WIDTH) - .height(ICON_IMAGE_HEIGHT); + button.stack(new Image(skin.getDrawable("top")), iconContainer).width(width) + .height(height); } - button.row(); - - Label label = null; - if ((appConfigItem.getDisplayName() == null) || appConfigItem.getDisplayName().trim().isEmpty()) { - if ("ADD_GAME".equals(appConfigItem.getGameId())) { - label = new Label("Add Game", skin); - } else { - label = new Label("[empty]", skin); - } - label.setColor(new Color(1f, 1f, 1f, 0.6f)); - } else { - label = new Label(appConfigItem.getDisplayName(), skin); - if ("UNK".equals(appConfigItem.getFileType())) { + + if (labelText != null) { + button.row(); + Label label = null; + if (labelText.trim().isEmpty()) { + if ((gameId != null) && "ADD_GAME".equals(gameId)) { + label = new Label("Add Game", skin); + } else { + label = new Label("[empty]", skin); + } label.setColor(new Color(1f, 1f, 1f, 0.6f)); + } else { + label = new Label(labelText, skin); + if ("UNK".equals(type)) { + label.setColor(new Color(1f, 1f, 1f, 0.6f)); + } } + label.setFontScale(2f); + label.setAlignment(Align.top); + label.setWrap(false); + button.add(label).width(150).height(90).padTop(10); } - label.setFontScale(2f); - label.setAlignment(Align.top); - label.setWrap(false); - button.add(label).width(150).height(90).padTop(10); - - button.setName(appConfigItem.getName()); + + button.setName(name); button.addListener(appClickListener); button.addListener(appGestureListener); return button; @@ -727,7 +780,7 @@ public void clicked(InputEvent event, float x, float y) { final AppConfigItem appConfigItem = appConfigMap.get(appName); if (appConfigItem != null) { if (!menu.isOpen()) { - menu.open(appConfigItem, actor.getX(Align.center), actor.getY(Align.center) + 35); + menu.open(appConfigItem, actor.getX(Align.center), actor.getY(Align.center) + 70); } } } @@ -745,10 +798,13 @@ public void clicked(InputEvent event, float x, float y) { // Known game but hasn't yet been imported. importGame(appConfigItem); } else { + lastGameLaunched = appConfigItem; GameScreen gameScreen = agile.getGameScreen(); gameScreen.initGame(appConfigItem, true); agile.setScreen(gameScreen); } + } else if (appName.equals("INFO")) { + showAboutAgileDialog(); } } else { // Add miscellaneous game option (i.e. the plus icon). @@ -759,6 +815,59 @@ public void clicked(InputEvent event, float x, float y) { } }; + private void showAboutAgileDialog() { + dialogHandler.showAboutDialog( + "AGILE v1.0.0\n\n" + + "Celebrating the 40th anniversary of King's Quest!\n\n" + + "To start, simply swipe or click to the right.\n\n" + + "For legal reasons, you must import your own copy of the original Sierra games.\n" + + "Most AGI Sierra games are still available for purchase online.\n" + + "Check out gog.com and Steam.\n\n" + + "Over 100 fan made AGI games and demos are included by default.\n\n" + + "GitHub repo: https://github.com/lanceewing/agile-gdx\n\n", + new TextInputResponseHandler() { + @Override + public void inputTextResult(boolean success, String button) { + if (success && !button.equals("OK")) { + // State management. + switch (button) { + case "EXPORT": + exportState(); + break; + case "IMPORT": + importState(); + break; + case "CLEAR": + clearState(); + break; + case "RESET": + resetState(); + break; + default: + // Nothing to do. + break; + } + } + } + }); + } + + private void exportState() { + + } + + private void importState() { + + } + + private void clearState() { + + } + + private void resetState() { + + } + private void importGame(AppConfigItem appConfigItem) { Gdx.app.postRunnable(new Runnable() { @Override @@ -810,7 +919,7 @@ public void inputTextResult(boolean success, String text) { appConfigMap.put(appConfigItem.getName(), appConfigItem); disposeCachedIcon(appConfigItem); updateHomeScreenButtonStages(); - showGamePage(appConfigItem); + showGamePage(appConfigItem, false); } } }; @@ -877,8 +986,8 @@ private int getGameIndex(AppConfigItem game) { return 0; } - private void showGamePage(AppConfigItem appConfigItem) { - showGamePage(getGameIndex(appConfigItem), false); + private void showGamePage(AppConfigItem appConfigItem, boolean skipScroll) { + showGamePage(getGameIndex(appConfigItem), skipScroll); } private void showGamePage(int gameIndex, boolean skipScroll) { @@ -891,7 +1000,7 @@ private void showGamePage(int gameIndex, boolean skipScroll) { // Work out how far to move from far left to get to game's page. int gamesPerPage = pagedScrollPane.getGamesPerPage(); float pageWidth = viewportManager.isPortrait()? 1130.0f : 1970.0f; - float newScrollX = pageWidth * (gameIndex / gamesPerPage); + float newScrollX = pageWidth * (gameIndex / gamesPerPage) + pageWidth; pagedScrollPane.setScrollX(newScrollX); pagedScrollPane.setLastScrollX(newScrollX); @@ -969,11 +1078,18 @@ public void changed(ChangeEvent event, Actor actor) { private void runGame() { AppConfigItem gameToRun = appConfigItem; + lastGameLaunched = gameToRun; + closeImmediately(); - GameScreen gameScreen = agile.getGameScreen(); - gameScreen.initGame(gameToRun, true); - agile.setScreen(gameScreen); + Gdx.app.postRunnable(new Runnable(){ + @Override + public void run() { + GameScreen gameScreen = agile.getGameScreen(); + gameScreen.initGame(gameToRun, true); + agile.setScreen(gameScreen); + } + }); } private void deleteGame() { @@ -985,7 +1101,13 @@ private void deleteGame() { @Override public void yes() { int gameIndexBeforeClose = getGameIndex(gameToDelete); - appConfigMap.remove(gameToDelete.getName()); + if (SIERRA_GAMES.contains(gameToDelete.getGameId().toLowerCase())) { + gameToDelete.setFileType("UNK"); + gameToDelete.setFilePath(""); + disposeCachedIcon(gameToDelete); + } else { + appConfigMap.remove(gameToDelete.getName()); + } // TODO: GWT needs to remove data from OPFS. Gdx.app.postRunnable(new Runnable(){ @Override diff --git a/core/src/main/java/com/agifans/agile/ui/DialogHandler.java b/core/src/main/java/com/agifans/agile/ui/DialogHandler.java index ad7e35f..21cf05a 100644 --- a/core/src/main/java/com/agifans/agile/ui/DialogHandler.java +++ b/core/src/main/java/com/agifans/agile/ui/DialogHandler.java @@ -51,7 +51,15 @@ public interface DialogHandler { * @param importTypeResponseHandler The handler to be invoked with the user's response. */ public void promptForImportType(AppConfigItem appConfigItem, ImportTypeResponseHandler importTypeResponseHandler); - + + /** + * Shows the About AGILE message dialog. + * + * @param aboutMessage The About message to display. + * @param textInputResponseHandler Optional state management button response. + */ + public void showAboutDialog(String aboutMessage, TextInputResponseHandler textInputResponseHandler); + /** * Returns true if a dialog is currently open. * diff --git a/core/src/main/java/com/agifans/agile/ui/PagedScrollPane.java b/core/src/main/java/com/agifans/agile/ui/PagedScrollPane.java index fe2acea..6fae5b1 100644 --- a/core/src/main/java/com/agifans/agile/ui/PagedScrollPane.java +++ b/core/src/main/java/com/agifans/agile/ui/PagedScrollPane.java @@ -107,8 +107,8 @@ public void reset() { public int getGamesPerPage() { int gamesPerPage = 0; if (content.getChildren().notEmpty()) { - Table firstPage = (Table)content.getChild(0); - gamesPerPage = firstPage.getColumns() * firstPage.getRows(); + Table secondPage = (Table)content.getChild(1); + gamesPerPage = secondPage.getColumns() * secondPage.getRows(); } return gamesPerPage; } diff --git a/html/src/main/java/com/agifans/agile/gwt/GwtDialogHandler.java b/html/src/main/java/com/agifans/agile/gwt/GwtDialogHandler.java index 68a3a3a..7538547 100644 --- a/html/src/main/java/com/agifans/agile/gwt/GwtDialogHandler.java +++ b/html/src/main/java/com/agifans/agile/gwt/GwtDialogHandler.java @@ -42,10 +42,16 @@ public GwtDialogHandler() { gameFileMapEncoder = new GameFileMapEncoder(); opfsGameFiles = new OPFSGameFiles(); + initDialog(); + // The same worker script is used for importing game data as is used for // the interpreter but they are run in two different running web workers. worker = Worker.create("worker/worker.nocache.js"); } + + private final native void initDialog()/*-{ + this.dialog = new $wnd.Dialog(); + }-*/; @Override public void confirm(String message, ConfirmResponseHandler confirmResponseHandler) { @@ -60,8 +66,7 @@ public void run() { private final native void showHtmlConfirmBox(String message, ConfirmResponseHandler confirmResponseHandler)/*-{ var that = this; - var dialog = new $wnd.Dialog(); - dialog.confirm(message).then(function (res) { + this.dialog.confirm(message).then(function (res) { if (res) { confirmResponseHandler.@com.agifans.agile.ui.ConfirmResponseHandler::yes()(); } else { @@ -99,8 +104,7 @@ public void selectedOptionResult(boolean success, String optionText) { } private final native void showHtmlPromptForImportType(String title, String message, String[] options, PromptForOptionsResponseHandler promptForOptionsResponseHandler)/*-{ - var dialog = new $wnd.Dialog(); - dialog.promptForOption(title, message, options).then(function (res) { + this.dialog.promptForOption(title, message, options).then(function (res) { if (res) { promptForOptionsResponseHandler.@com.agifans.agile.gwt.GwtDialogHandler.PromptForOptionsResponseHandler::selectedOptionResult(ZLjava/lang/String;)(true, res.option); } else { @@ -346,8 +350,7 @@ public void run() { private final native void showHtmlPromptBox(String message, String initialValue, TextInputResponseHandler textInputResponseHandler)/*-{ var that = this; - var dialog = new $wnd.Dialog(); - dialog.prompt(message, initialValue).then(function (res) { + this.dialog.prompt(message, initialValue).then(function (res) { if (res) { textInputResponseHandler.@com.agifans.agile.ui.TextInputResponseHandler::inputTextResult(ZLjava/lang/String;)(true, res.prompt); } else { @@ -369,9 +372,47 @@ public void run() { } private final native void showHtmlMessageBox(String message)/*-{ - var dialog = new $wnd.Dialog(); - dialog.alert(message); - this.@com.agifans.agile.gwt.GwtDialogHandler::dialogOpen = false; + var that = this; + this.dialog.alert(message).then(function (res) { + that.@com.agifans.agile.gwt.GwtDialogHandler::dialogOpen = false; + }); + }-*/; + + @Override + public void showAboutDialog(String aboutMessage, TextInputResponseHandler textInputResponseHandler) { + Gdx.app.postRunnable(new Runnable() { + @Override + public void run() { + dialogOpen = true; + showHtmlAboutDialog(aboutMessage, textInputResponseHandler); + } + }); + } + + private final native void showHtmlAboutDialog(String message, TextInputResponseHandler textInputResponseHandler)/*-{ + var that = this; + message = message.replace(/(?:\r\n|\r|\n)/g, "
"); + message = message.replace(/gog.com/g, "gog.com"); + message = message.replace(/Steam/g, "Steam"); + message = message.replace(/https:\/\/github.com\/lanceewing\/agile-gdx/g, "https://github.com/lanceewing/agile-gdx"); + this.dialog.alert('', { + showStateButtons: false, + template: '' + message + '' + }).then(function (res) { + if (res) { + if (res === true) { + // OK button. + textInputResponseHandler.@com.agifans.agile.ui.TextInputResponseHandler::inputTextResult(ZLjava/lang/String;)(true, "OK"); + } + else { + textInputResponseHandler.@com.agifans.agile.ui.TextInputResponseHandler::inputTextResult(ZLjava/lang/String;)(true, res); + } + } + else { + textInputResponseHandler.@com.agifans.agile.ui.TextInputResponseHandler::inputTextResult(ZLjava/lang/String;)(false, null); + } + that.@com.agifans.agile.gwt.GwtDialogHandler::dialogOpen = false; + }); }-*/; @Override diff --git a/lwjgl3/src/main/java/com/agifans/agile/lwjgl3/DesktopDialogHandler.java b/lwjgl3/src/main/java/com/agifans/agile/lwjgl3/DesktopDialogHandler.java index 64c7414..5d856ba 100644 --- a/lwjgl3/src/main/java/com/agifans/agile/lwjgl3/DesktopDialogHandler.java +++ b/lwjgl3/src/main/java/com/agifans/agile/lwjgl3/DesktopDialogHandler.java @@ -1,9 +1,22 @@ package com.agifans.agile.lwjgl3; +import java.awt.Image; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.ByteArrayInputStream; import java.io.File; +import java.io.IOException; import java.util.HashMap; import java.util.Map; +import java.util.zip.Deflater; +import javax.imageio.ImageIO; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JOptionPane; import javax.swing.filechooser.FileNameExtensionFilter; @@ -20,6 +33,8 @@ import com.agifans.agile.ui.TextInputResponseHandler; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.files.FileHandle; +import com.badlogic.gdx.graphics.Pixmap; +import com.badlogic.gdx.graphics.PixmapIO; /** * Desktop implementation of the DialogHandler interface. @@ -27,7 +42,77 @@ public class DesktopDialogHandler implements DialogHandler { private boolean dialogOpen; + + private Icon importIcon; + private Icon exportIcon; + private Icon clearIcon; + private Icon resetIcon; + + private BufferedImage toBufferedImage(Pixmap pixmap) throws IOException { + try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + PixmapIO.PNG writer = new PixmapIO.PNG(pixmap.getWidth() * pixmap.getHeight() * 4); + try { + writer.setFlipY(false); + writer.setCompression(Deflater.NO_COMPRESSION); + writer.write(baos, pixmap); + } finally { + writer.dispose(); + } + + return ImageIO.read(new ByteArrayInputStream(baos.toByteArray())); + } + } + + private Image loadImage(String imagePath) { + try { + Pixmap iconPixmap = new Pixmap(Gdx.files.internal(imagePath)); + BufferedImage image = toBufferedImage(iconPixmap); + iconPixmap.dispose(); + return image; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + private Icon loadIcon(String iconPath) { + Image image = loadImage(iconPath); + if (image != null) { + return new ImageIcon(image); + } else { + return null; + } + } + + private Icon getImportIcon() { + if (importIcon == null) { + importIcon = loadIcon("png/import.png"); + } + return importIcon; + } + + private Icon getExportIcon() { + if (exportIcon == null) { + exportIcon = loadIcon("png/export.png"); + } + return exportIcon; + } + + private Icon getClearIcon() { + if (clearIcon == null) { + clearIcon = loadIcon("png/clear.png"); + } + return clearIcon; + } + + private Icon getResetIcon() { + if (resetIcon == null) { + resetIcon = loadIcon("png/reset.png"); + } + return resetIcon; + } + @Override public void confirm(final String message, final ConfirmResponseHandler responseHandler) { Gdx.app.postRunnable(new Runnable() { @@ -195,6 +280,71 @@ public void showMessageDialog(String message) { dialogOpen = false; } + @Override + public void showAboutDialog(String aboutMessage, TextInputResponseHandler textInputResponseHandler) { + dialogOpen = true; + + JButton spacerButton = new JButton( + " "); + spacerButton.setVisible(false); + JButton exportButton = new JButton(getExportIcon()); + JButton importButton = new JButton(getImportIcon()); + JButton resetButton = new JButton(getResetIcon()); + JButton clearButton = new JButton(getClearIcon()); + JButton okButton = new JButton("OK"); + //Object[] options = { exportButton, importButton, resetButton, clearButton, spacerButton, okButton }; + Object[] options = { okButton }; + + final JOptionPane pane = new JOptionPane( + aboutMessage, + JOptionPane.INFORMATION_MESSAGE, + JOptionPane.DEFAULT_OPTION, + loadIcon("png/agile-64x64.png"), + options, okButton); + + MouseAdapter mouseListener = new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + JButton button = (JButton)e.getComponent(); + if (button == exportButton) { + pane.setValue("EXPORT"); + } + else if (button == importButton) { + pane.setValue("IMPORT"); + } + else if (button == resetButton) { + pane.setValue("RESET"); + } + else if (button == clearButton) { + pane.setValue("CLEAR"); + } + else { + pane.setValue("OK"); + } + } + }; + + exportButton.addMouseListener(mouseListener); + importButton.addMouseListener(mouseListener); + resetButton.addMouseListener(mouseListener); + clearButton.addMouseListener(mouseListener); + okButton.addMouseListener(mouseListener); + + pane.setComponentOrientation(JOptionPane.getRootFrame().getComponentOrientation()); + JDialog dialog = pane.createDialog("About AGILE"); + dialog.setIconImage(loadImage("png/agile-32x32.png")); + dialog.show(); + dialog.dispose(); + + if (pane.getValue() != null) { + textInputResponseHandler.inputTextResult(true, (String)pane.getValue()); + } else { + textInputResponseHandler.inputTextResult(false, null); + } + + dialogOpen = false; + } + @Override public boolean isDialogOpen() { return dialogOpen;