/* * $Id$ * * Copyright (c) 2004 by Rodney Kinney * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License (LGPL) as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, copies are available * at http://www.opensource.org. */ package VASSAL.build.module.documentation; import java.awt.event.ActionEvent; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.ExecutionException; import javax.swing.AbstractAction; import javax.swing.Action; import org.jdesktop.swingworker.SwingWorker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import VASSAL.build.AbstractConfigurable; import VASSAL.build.Buildable; import VASSAL.build.GameModule; import VASSAL.command.Command; import VASSAL.configure.BooleanConfigurer; import VASSAL.configure.VisibilityCondition; import VASSAL.i18n.Resources; import VASSAL.tools.ErrorDialog; import VASSAL.tools.menu.MenuItemProxy; import VASSAL.tools.menu.MenuManager; /** * Provides tutorial functionality by reading in a logfile */ public class Tutorial extends AbstractConfigurable { private static final Logger logger = LoggerFactory.getLogger(Tutorial.class); public static final String FILE_NAME = "logfile"; //$NON-NLS-1$ public static final String NAME = "name"; //$NON-NLS-1$ public static final String LAUNCH_ON_STARTUP = "launchOnStartup"; //$NON-NLS-1$ public static final String PROMPT_MESSAGE = "promptMessage"; //$NON-NLS-1$ public static final String WELCOME_MESSAGE = "welcomeMessage"; //$NON-NLS-1$ private String fileName; private Action launch; private boolean launchOnFirstStartup; private String welcomeMessage = Resources.getString("Tutorial.instructions"); //$NON-NLS-1$ private String promptMessage = Resources.getString("Tutorial.load_tutorial"); //$NON-NLS-1$ protected BooleanConfigurer hasViewedTutorial; public Tutorial() { launch = new AbstractAction(Resources.getString("Tutorial.tutorial")) { //$NON-NLS-1$ private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { launch(); }; }; } public void launch() { GameModule.getGameModule().warn(Resources.getString("Tutorial.Tutorial.loading")); //$NON-NLS-1$ new SwingWorker<Command,Void>() { @Override public Command doInBackground() throws Exception { return getTutorialCommand(); } @Override protected void done() { Command saveCommand = null; String error = null; try { saveCommand = get(); } catch (InterruptedException e) { ErrorDialog.bug(e); } // FIXME: review error message catch (ExecutionException e) { logger.error("", e); String msg = Resources.getString("Tutorial.unable_to_launch", name); //$NON-NLS-1$ if (e.getMessage() != null) { msg += ": " + e.getMessage(); //$NON-NLS-1$ } error = msg; } if (saveCommand != null) { saveCommand.execute(); if (welcomeMessage != null && welcomeMessage.length() > 0) { GameModule.getGameModule().warn(welcomeMessage); } } else { GameModule.getGameModule().warn(error); } } }.execute(); } public String[] getAttributeDescriptions() { return new String[] { "Menu Text", //$NON-NLS-1$ "Logfile", //$NON-NLS-1$ "Launch automatically on first startup", //$NON-NLS-1$ "Auto-launch confirm message", //$NON-NLS-1$ "Welcome message" //$NON-NLS-1$ }; } public Class<?>[] getAttributeTypes() { return new Class<?>[]{ String.class, File.class, Boolean.class, String.class, String.class }; } public String[] getAttributeNames() { return new String[]{ NAME, FILE_NAME, LAUNCH_ON_STARTUP, PROMPT_MESSAGE, WELCOME_MESSAGE }; } public VisibilityCondition getAttributeVisibility(String name) { if (name.equals(PROMPT_MESSAGE)) { return new VisibilityCondition() { public boolean shouldBeVisible() { return launchOnFirstStartup; } }; } return null; } public String getAttributeValueString(String key) { if (FILE_NAME.equals(key)) { return fileName; } else if (NAME.equals(key)) { return getConfigureName(); } else if (LAUNCH_ON_STARTUP.equals(key)) { return String.valueOf(launchOnFirstStartup); } else if (PROMPT_MESSAGE.equals(key)) { return promptMessage; } else if (WELCOME_MESSAGE.equals(key)) { return welcomeMessage; } else { return null; } } public void setAttribute(String key, Object value) { if (FILE_NAME.equals(key)) { if (value instanceof File) { value = ((File) value).getName(); } fileName = (String) value; } else if (NAME.equals(key)) { launch.putValue(Action.NAME, value); setConfigureName((String) value); } else if (LAUNCH_ON_STARTUP.equals(key)) { if (value instanceof String) { value = Boolean.valueOf((String) value); } launchOnFirstStartup = ((Boolean) value).booleanValue(); } else if (PROMPT_MESSAGE.equals(key)) { promptMessage = (String) value; } else if (WELCOME_MESSAGE.equals(key)) { welcomeMessage = (String) value; } } protected MenuItemProxy launchItem; public void addTo(Buildable parent) { launchItem = new MenuItemProxy(launch); MenuManager.getInstance().addToSection("Documentation.Module", launchItem); final String key = "viewedTutorial" + getConfigureName(); //$NON-NLS-1$ hasViewedTutorial = new BooleanConfigurer(key, null, Boolean.FALSE); GameModule.getGameModule().getPrefs().addOption(null, hasViewedTutorial); GameModule.getGameModule().getWizardSupport().setTutorial(this); } public void removeFrom(Buildable parent) { MenuManager.getInstance() .removeFromSection("Documentation.Module", launchItem); } public Class<?>[] getAllowableConfigureComponents() { return new Class<?>[0]; } public HelpFile getHelpFile() { return HelpFile.getReferenceManualPage("HelpMenu.htm", "Tutorial"); //$NON-NLS-1$ //$NON-NLS-2$ } /** * Get the Command representing this tutorial logfile. Executing the command loads the tutorial * @return * @throws IOException */ public Command getTutorialCommand() throws IOException { return GameModule.getGameModule().getGameState().decodeSavedGame(getTutorialContents()); } public InputStream getTutorialContents() throws IOException { if (fileName == null) { throw new FileNotFoundException("Tutorial has null filename"); } return GameModule.getGameModule().getDataArchive().getInputStream(fileName); } public boolean isFirstRun() { return launchOnFirstStartup && !hasViewedTutorial.booleanValue(); } /** * Mark this tutorial as having been viewed */ public void markAsViewed() { hasViewedTutorial.setValue(Boolean.TRUE); } public String getWelcomeMessage() { return welcomeMessage; } }