package it.albertus.cycles.gui;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.window.IShellProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import it.albertus.cycles.data.DefaultBikes;
import it.albertus.cycles.engine.CyclesModEngine;
import it.albertus.cycles.engine.InvalidPropertyException;
import it.albertus.cycles.engine.NumeralSystem;
import it.albertus.cycles.gui.listener.CloseListener;
import it.albertus.cycles.model.BikesCfg;
import it.albertus.cycles.model.BikesInf;
import it.albertus.cycles.resources.Messages;
import it.albertus.cycles.resources.Messages.Language;
import it.albertus.jface.EnhancedErrorDialog;
import it.albertus.util.ExceptionUtils;
import it.albertus.util.IOUtils;
import it.albertus.util.StringUtils;
import it.albertus.util.Version;
import it.albertus.util.logging.LoggerFactory;
public class CyclesModGui extends CyclesModEngine implements IShellProvider {
private static final Logger logger = LoggerFactory.getLogger(CyclesModGui.class);
private static final String MSG_KEY_WARNING = "msg.warning";
private static final String MSG_KEY_COMPLETED = "msg.completed";
private static final String MSG_KEY_WIN_TITLE = "win.title";
private final Map<String, Integer> defaultProperties = new HashMap<String, Integer>();
private final Map<String, Integer> lastPersistedProperties = new HashMap<String, Integer>();
private final Shell shell;
private final MenuBar menuBar;
private final Tabs tabs;
private CyclesModGui(final Display display, final String fileName) throws IOException {
// Loading default properties...
InputStream is = null;
try {
is = new DefaultBikes().getInputStream();
setBikesInf(new BikesInf(is));
}
finally {
IOUtils.closeQuietly(is);
}
defaultProperties.putAll(new BikesCfg(getBikesInf()).getMap());
// Shell creation...
shell = new Shell(display);
shell.setImages(Images.MAIN_ICONS);
shell.setText(Messages.get(MSG_KEY_WIN_TITLE));
shell.setLayout(new FillLayout());
shell.addShellListener(new CloseListener(this));
menuBar = new MenuBar(this);
tabs = new Tabs(this);
// Size...
shell.pack();
tabs.updateFormValues();
// Loading custom properties...
if (StringUtils.isNotBlank(fileName)) {
load(fileName, false);
}
else {
setLastPersistedProperties(defaultProperties);
}
}
/* GUI entry point. */
public static void start(final String fileName) {
Display.setAppName(Messages.get(MSG_KEY_WIN_TITLE));
Display.setAppVersion(Version.getInstance().getNumber());
final Display display = Display.getDefault();
Shell shell = null;
try {
final CyclesModGui gui = new CyclesModGui(display, fileName);
shell = gui.getShell();
shell.open();
while (!shell.isDisposed()) {
if (!display.isDisposed() && !display.readAndDispatch()) {
display.sleep();
}
}
}
catch (final Exception e) {
final String message = e.toString();
logger.log(Level.SEVERE, message, e);
EnhancedErrorDialog.openError(shell != null ? shell : null, Messages.get(MSG_KEY_WARNING), message, IStatus.ERROR, e, Images.MAIN_ICONS);
}
finally {
display.dispose();
}
}
public void setLanguage(final Language language) {
Messages.setLanguage(language);
shell.setRedraw(false);
menuBar.updateTexts();
tabs.updateTexts();
shell.setRedraw(true);
}
public void updateModelValues(boolean lenient) {
for (final String key : tabs.getFormProperties().keySet()) {
applyProperty(key, tabs.getFormProperties().get(key).getValue(), lenient);
}
}
public void load(final String fileName, final boolean successMessage) {
try {
if (fileName.toLowerCase().endsWith(".inf")) {
final File bikesInfFile = new File(fileName);
setBikesInf(new BikesInf(bikesInfFile));
tabs.updateFormValues();
setLastPersistedProperties(new BikesCfg(getBikesInf()).getMap());
shell.setText(Messages.get(MSG_KEY_WIN_TITLE) + " - " + bikesInfFile.getCanonicalPath());
if (successMessage) {
final MessageBox messageBox = new MessageBox(shell, SWT.ICON_INFORMATION);
messageBox.setText(Messages.get(MSG_KEY_COMPLETED));
messageBox.setMessage(Messages.get("msg.file.loaded", fileName));
messageBox.open();
}
}
else if (fileName.toLowerCase().endsWith(".cfg")) {
InputStream is = null;
try {
is = new DefaultBikes().getInputStream();
setBikesInf(new BikesInf(is));
}
finally {
IOUtils.closeQuietly(is);
}
final BikesCfg bikesCfg = new BikesCfg(fileName);
short changesCount = 0;
for (final String key : bikesCfg.getProperties().stringPropertyNames()) {
if (applyProperty(key, bikesCfg.getProperties().getProperty(key), false)) {
changesCount++;
}
}
tabs.updateFormValues();
setLastPersistedProperties(new BikesCfg(getBikesInf()).getMap());
if (successMessage) {
final MessageBox messageBox = new MessageBox(shell, SWT.ICON_INFORMATION);
messageBox.setText(Messages.get(MSG_KEY_COMPLETED));
messageBox.setMessage(Messages.get("msg.customizations.applied", changesCount));
messageBox.open();
}
}
else {
final MessageBox messageBox = new MessageBox(shell, SWT.ICON_ERROR);
messageBox.setText(Messages.get(MSG_KEY_WARNING));
messageBox.setMessage(Messages.get("err.file.invalid"));
messageBox.open();
}
}
catch (final Exception e) {
logger.log(Level.WARNING, e.toString(), e);
EnhancedErrorDialog.openError(shell, Messages.get(MSG_KEY_WARNING), Messages.get("err.file.load"), IStatus.WARNING, e, Images.MAIN_ICONS);
}
}
public boolean save(final boolean successMessage) {
try {
updateModelValues(false);
}
catch (final InvalidPropertyException e) {
logger.log(Level.WARNING, e.toString(), e);
EnhancedErrorDialog.openError(shell, Messages.get(MSG_KEY_WARNING), ExceptionUtils.getUIMessage(e), IStatus.WARNING, e, Images.MAIN_ICONS);
return false;
}
final FileDialog saveDialog = new FileDialog(getShell(), SWT.SAVE);
saveDialog.setFilterExtensions(new String[] { "*.INF;*.inf" });
saveDialog.setFileName(BikesInf.FILE_NAME);
saveDialog.setOverwrite(true);
final String fileName = saveDialog.open();
if (StringUtils.isNotBlank(fileName)) {
try {
getBikesInf().write(fileName);
}
catch (final Exception e) {
logger.log(Level.WARNING, e.toString(), e);
EnhancedErrorDialog.openError(shell, Messages.get(MSG_KEY_WARNING), Messages.get("err.file.save"), IStatus.WARNING, e, Images.MAIN_ICONS);
return false;
}
shell.setText(Messages.get(MSG_KEY_WIN_TITLE) + " - " + fileName);
setLastPersistedProperties(new BikesCfg(getBikesInf()).getMap());
if (successMessage) {
final MessageBox messageBox = new MessageBox(getShell(), SWT.ICON_INFORMATION);
messageBox.setText(Messages.get(MSG_KEY_COMPLETED));
messageBox.setMessage(Messages.get("msg.file.saved", fileName));
messageBox.open();
}
return true;
}
else {
return false;
}
}
@Override
public void setNumeralSystem(final NumeralSystem numeralSystem) {
updateModelValues(true);
super.setNumeralSystem(numeralSystem);
tabs.updateFormValues();
}
public Map<String, Integer> getLastPersistedProperties() {
return Collections.unmodifiableMap(lastPersistedProperties);
}
private void setLastPersistedProperties(final Map<String, Integer> lastPersistedProperties) {
this.lastPersistedProperties.clear();
this.lastPersistedProperties.putAll(lastPersistedProperties);
}
@Override
public Shell getShell() {
return shell;
}
public MenuBar getMenuBar() {
return menuBar;
}
public Tabs getTabs() {
return tabs;
}
public Map<String, Integer> getDefaultProperties() {
return Collections.unmodifiableMap(defaultProperties);
}
}