package ch.rakudave.jnetmap.controller;
import java.awt.Component;
import java.io.File;
import java.io.FileInputStream;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import net.xeoh.plugins.base.PluginManager;
import net.xeoh.plugins.base.impl.PluginManagerFactory;
import net.xeoh.plugins.base.options.addpluginsfrom.OptionLazyActivation;
import ch.rakudave.jnetmap.model.Map;
import ch.rakudave.jnetmap.util.Crypto;
import ch.rakudave.jnetmap.util.IO;
import ch.rakudave.jnetmap.util.Icons;
import ch.rakudave.jnetmap.util.Lang;
import ch.rakudave.jnetmap.util.Settings;
import ch.rakudave.jnetmap.util.SwingHelper;
import ch.rakudave.jnetmap.util.XStreamHelper;
import ch.rakudave.jnetmap.util.logging.FileAppender;
import ch.rakudave.jnetmap.util.logging.Logger;
import ch.rakudave.jnetmap.util.logging.Logger.Level;
import ch.rakudave.jnetmap.view.IView;
import ch.rakudave.jnetmap.view.MapView;
import ch.rakudave.jnetmap.view.components.SplashScreen;
import ch.rakudave.jnetmap.view.preferences.Preferences;
/**
* @author rakudave
*/
public class Controller {
public static final String version = "0.5.1";
private static IView view;
protected static Preferences preferences;
private static List<Map> maps;
private static Map currentMap;
public static PluginManager pm;
public static void main(String[] args) {
try {
InstanceDetector.delegate(args);
try { // Set native look-and-feel
if (IO.isOSX) System.setProperty("apple.laf.useScreenMenuBar", "true");
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
Logger.warn("Unable to set 'System Look-And-Feel', falling back to Swing");
}
new Controller(args);
} catch (Throwable t) {
Logger.error("Unhandled exception", t);
}
}
private Controller(String[] args) {
SplashScreen.create();
SplashScreen.setProgress(0, "Initial setup...");
Scheduler.executor = new ScheduledThreadPoolExecutor(3);
maps = new LinkedList<Map>();
IO.installUserFiles();
SplashScreen.setProgress(15, "Loading preferences...");
Settings.load();
Logger.addAppender(new FileAppender(Level.valueOf(Settings.get("logger.FileAppender", "ERROR"))));
Logger.debug("Java "+System.getProperty("java.version")+" by "+System.getProperty("java.vendor"));
Logger.debug("OS: "+System.getProperty("os.name")+" "+System.getProperty("os.version")+" "+System.getProperty("os.arch"));
SplashScreen.setProgress(30, "Loading language...");
Lang.load();
SplashScreen.setProgress(45, "Loading icons...");
Icons.load();
SplashScreen.setProgress(60, "Loading plugins...");
pm = PluginManagerFactory.createPluginManager();
pm.addPluginsFrom(IO.pluginDir.toURI(), new OptionLazyActivation());
SplashScreen.setProgress(75, "Loading GUI...");
view = new MapView();
preferences = new Preferences(view);
SplashScreen.setProgress(90, "Opening files...");
open(args);
if (args.length == 0 && Settings.getBoolean("maps.restore", false)) {
int count = Settings.getInt("maps.count", 0);
if (count != 0) {
String[] maps = new String[count];
for (int i = 0; i < count; i++) {
maps[i] = Settings.get("maps."+i, "");
}
open(maps);
}
}
SplashScreen.dispose();
}
public static void open(String[] files) {
if (files.length == 0) return;
Logger.info("Opening files " + Arrays.toString(files));
for (String file : files) {
if (!file.isEmpty()) open(getMapFromFile(file, null));
}
view.toFront();
}
public static void open(Map map) {
if (map == null) return;
Logger.info("Opening '" + map.getFileName() + "'");
if (maps.contains(map)) {
Logger.warn("Map is already open: " + map.getFileName());
return;
}
try {
view.openMap(map);
setCurrentMap(map);
} catch (Exception e) {
Logger.error("Unable to open " + map.getFileName(), e);
JOptionPane.showMessageDialog((Component) Controller.view, Lang.get("map.fail.open"), map.getFileName(), JOptionPane.ERROR_MESSAGE);
}
}
public static Map getMapFromFile(String filePath, String password) {
try {
File mapFile = new File(filePath);
String xml = IO.getString(new FileInputStream(mapFile));
if (xml == null) return null;
if (!xml.startsWith("<Map>")) {
password = SwingHelper.passwordPrompt();
if (password == null) return null;
}
if (password != null && !password.isEmpty()) {
xml = Crypto.decrypt(xml, password);
}
Map m = (Map) XStreamHelper.getXStream().fromXML(xml);
m.setFile(mapFile);
m.setPassword(password);
return m;
} catch (Exception e) {
Logger.error("Could not open file '" + filePath + "'", e);
return null;
}
}
public static boolean close(Map map) {
if (map == null || !maps.contains(map)) return true;
Logger.trace("Closing map "+map);
if (!map.isSaved()){
String msg = Lang.get("message.unsaved").replaceAll("%name%", map.getFileName());
int i = JOptionPane.showConfirmDialog((Component) view, msg,
map.getFilePath(), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
switch (i) {
case 2: return false;
case 0:
setCurrentMap(map);
Actions.save().actionPerformed(null);
break;
default: break;
}
}
maps.remove(map);
return true;
}
public static void setCurrentMap(Map map) {
if (!maps.contains(currentMap)) {
maps.add(map);
StatusUpdater.addMap(map);
}
currentMap = map;
view.setWindowTitle(map.getFilePath());
}
public static Map getCurrentMap() {
return currentMap;
}
public static boolean closeAllMaps() {
List<Map> tempMaps = new LinkedList<Map>(maps);
int i = 0;
for (Map m : tempMaps) {
if (!close(m)) return false;
if (!m.getFileName().equals(Lang.getNoHTML("map.newmap")))
Settings.put("maps."+i++, m.getFilePath());
}
Settings.put("maps.count", i);
return true;
}
public static IView getView() {
return view;
}
}