package games.strategy.triplea.ui.menubar;
import java.awt.FileDialog;
import java.awt.Frame;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Vector;
import javax.swing.JFileChooser;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.plaf.metal.MetalLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceAutumnLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceBusinessBlackSteelLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceBusinessBlueSteelLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceBusinessLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceCeruleanLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceChallengerDeepLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceCremeCoffeeLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceCremeLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceDustCoffeeLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceDustLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceEmeraldDuskLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceGeminiLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceGraphiteAquaLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceGraphiteGlassLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceGraphiteLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceMagellanLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceMarinerLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceMistAquaLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceMistSilverLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceModerateLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceNebulaBrickWallLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceNebulaLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceOfficeBlack2007LookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceOfficeBlue2007LookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceOfficeSilver2007LookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceRavenLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceSaharaLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceTwilightLookAndFeel;
import games.strategy.debug.ClientLogger;
import games.strategy.engine.ClientContext;
import games.strategy.engine.framework.startup.ui.InGameLobbyWatcherWrapper;
import games.strategy.engine.framework.system.SystemProperties;
import games.strategy.engine.framework.ui.SaveGameFileChooser;
import games.strategy.engine.lobby.client.ui.action.EditGameCommentAction;
import games.strategy.engine.lobby.client.ui.action.RemoveGameFromLobbyAction;
import games.strategy.net.HeadlessServerMessenger;
import games.strategy.triplea.ui.TripleAFrame;
import games.strategy.util.Triple;
public class TripleAMenuBar extends JMenuBar {
private static final long serialVersionUID = -1447295944297939539L;
protected final TripleAFrame frame;
public TripleAMenuBar(final TripleAFrame frame) {
this.frame = frame;
new FileMenu(this, frame);
new ViewMenu(this, frame);
new GameMenu(this, frame);
new ExportMenu(this, frame);
final Optional<InGameLobbyWatcherWrapper> watcher = frame.getInGameLobbyWatcher();
if (watcher.isPresent() && watcher.get().isActive()) {
createLobbyMenu(this, watcher.get());
}
if (!(frame.getGame().getMessenger() instanceof HeadlessServerMessenger)) {
new NetworkMenu(this, watcher, frame);
}
new WebHelpMenu(this);
new DebugMenu(this, frame);
new HelpMenu(this, frame.getUIContext(), frame.getGame().getData(), getBackground());
}
private void createLobbyMenu(final JMenuBar menuBar, final InGameLobbyWatcherWrapper watcher) {
final JMenu lobby = new JMenu("Lobby");
lobby.setMnemonic(KeyEvent.VK_L);
menuBar.add(lobby);
lobby.add(new EditGameCommentAction(watcher, frame));
lobby.add(new RemoveGameFromLobbyAction(watcher));
}
public static File getSaveGameLocationDialog(final Frame frame) {
// For some strange reason,
// the only way to get a Mac OS X native-style file dialog
// is to use an AWT FileDialog instead of a Swing JDialog
if (SystemProperties.isMac()) {
final FileDialog fileDialog = new FileDialog(frame);
fileDialog.setMode(FileDialog.SAVE);
fileDialog.setDirectory(ClientContext.folderSettings().getSaveGamePath());
fileDialog.setFilenameFilter((dir, name) -> {
// the extension should be .tsvg, but find svg extensions as well
return name.endsWith(".tsvg") || name.endsWith(".svg");
});
fileDialog.setVisible(true);
String fileName = fileDialog.getFile();
final String dirName = fileDialog.getDirectory();
if (fileName == null) {
return null;
} else {
if (!fileName.endsWith(".tsvg")) {
fileName += ".tsvg";
}
// If the user selects a filename that already exists,
// the AWT Dialog on Mac OS X will ask the user for confirmation
final File f = new File(dirName, fileName);
return f;
}
} else { // Non-Mac platforms should use the normal Swing JFileChooser
final JFileChooser fileChooser = SaveGameFileChooser.getInstance();
final int rVal = fileChooser.showSaveDialog(frame);
if (rVal != JFileChooser.APPROVE_OPTION) {
return null;
}
File f = fileChooser.getSelectedFile();
// disallow sub directories to be entered (in the form directory/name) for Windows boxes
if (SystemProperties.isWindows()) {
final int slashIndex = Math.min(f.getPath().lastIndexOf("\\"), f.getPath().length());
final String filePath = f.getPath().substring(0, slashIndex);
if (!fileChooser.getCurrentDirectory().toString().equals(filePath)) {
JOptionPane.showConfirmDialog(frame, "Sub directories are not allowed in the file name. Please rename it.",
"Cancel?", JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE);
return null;
}
}
if (!f.getName().toLowerCase().endsWith(".tsvg")) {
f = new File(f.getParent(), f.getName() + ".tsvg");
}
// A small warning so users will not over-write a file
if (f.exists()) {
final int choice =
JOptionPane.showConfirmDialog(frame, "A file by that name already exists. Do you wish to over write it?",
"Over-write?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
if (choice != JOptionPane.OK_OPTION) {
return null;
}
}
return f;
}
}
public static List<String> getLookAndFeelAvailableList() {
final List<String> substanceLooks = new ArrayList<>();
for (final LookAndFeelInfo look : UIManager.getInstalledLookAndFeels()) {
substanceLooks.add(look.getClassName());
}
substanceLooks.addAll(Arrays.asList(SubstanceAutumnLookAndFeel.class.getName(),
SubstanceBusinessBlackSteelLookAndFeel.class.getName(), SubstanceBusinessBlueSteelLookAndFeel.class.getName(),
SubstanceBusinessLookAndFeel.class.getName(), SubstanceCeruleanLookAndFeel.class.getName(),
SubstanceChallengerDeepLookAndFeel.class.getName(), SubstanceCremeCoffeeLookAndFeel.class.getName(),
SubstanceCremeLookAndFeel.class.getName(), SubstanceDustCoffeeLookAndFeel.class.getName(),
SubstanceDustLookAndFeel.class.getName(), SubstanceEmeraldDuskLookAndFeel.class.getName(),
SubstanceGeminiLookAndFeel.class.getName(), SubstanceGraphiteAquaLookAndFeel.class.getName(),
SubstanceGraphiteGlassLookAndFeel.class.getName(), SubstanceGraphiteLookAndFeel.class.getName(),
SubstanceMagellanLookAndFeel.class.getName(), SubstanceMarinerLookAndFeel.class.getName(),
SubstanceMistAquaLookAndFeel.class.getName(), SubstanceMistSilverLookAndFeel.class.getName(),
SubstanceModerateLookAndFeel.class.getName(), SubstanceNebulaBrickWallLookAndFeel.class.getName(),
SubstanceNebulaLookAndFeel.class.getName(), SubstanceOfficeBlack2007LookAndFeel.class.getName(),
SubstanceOfficeBlue2007LookAndFeel.class.getName(), SubstanceOfficeSilver2007LookAndFeel.class.getName(),
SubstanceRavenLookAndFeel.class.getName(), SubstanceSaharaLookAndFeel.class.getName(),
SubstanceTwilightLookAndFeel.class.getName()));
return substanceLooks;
}
/**
* First is our JList, second is our LookAndFeels string -> class map, third is our 'current' look and feel.
*/
public static Triple<JList<String>, Map<String, String>, String> getLookAndFeelList() {
final Map<String, String> lookAndFeels = new LinkedHashMap<>();
try {
final List<String> substanceLooks = getLookAndFeelAvailableList();
for (final String s : substanceLooks) {
final Class<?> c = Class.forName(s);
final LookAndFeel lf = (LookAndFeel) c.newInstance();
lookAndFeels.put(lf.getName(), s);
}
} catch (final Exception e) {
ClientLogger.logError("An Error occured while getting LookAndFeels", e);
// we know all machines have these 3, so use them
lookAndFeels.clear();
lookAndFeels.put("Original", UIManager.getSystemLookAndFeelClassName());
lookAndFeels.put("Metal", MetalLookAndFeel.class.getName());
lookAndFeels.put("Platform Independent", UIManager.getCrossPlatformLookAndFeelClassName());
}
final JList<String> list = new JList<>(new Vector<>(lookAndFeels.keySet()));
String currentKey = null;
for (final String s : lookAndFeels.keySet()) {
final String currentName = UIManager.getLookAndFeel().getClass().getName();
if (lookAndFeels.get(s).equals(currentName)) {
currentKey = s;
break;
}
}
list.setSelectedValue(currentKey, false);
return Triple.of(list, lookAndFeels, currentKey);
}
}