Commit 1449da57 authored by Vincent van Beveren's avatar Vincent van Beveren

added locking and error handler for uncaught exceptions

parent 6907b580
......@@ -20,8 +20,11 @@ package nl.nikhef.safaripark;
import java.util.HashSet;
import java.util.Set;
import nl.nikhef.safaripark.extra.BaseMessage;
import nl.nikhef.safaripark.extra.Message;
import nl.nikhef.safaripark.extra.MessagePane;
import nl.nikhef.safaripark.extra.Module;
import nl.nikhef.safaripark.extra.StatefulTask;
import nl.nikhef.sfp.SFPManager;
import nl.nikhef.sfp.ddmi.DDMILoader;
......@@ -31,6 +34,7 @@ public class AppContext {
public final DDMILoader ddmiLdr;
public final OverlayManager ovlMgr;
public final ContextCache ctxCache;
private SaFariPark _sfp;
private final Set<Module> _locks = new HashSet();
private MessagePane _msgPane;
......@@ -43,6 +47,14 @@ public class AppContext {
}
public void setSaFariPark(SaFariPark sfp) {
_sfp = sfp;
}
public SaFariPark getSaFariPark() {
return _sfp;
}
public boolean isLocked(Module m)
{
......@@ -58,7 +70,9 @@ public class AppContext {
public void unlock(Module m)
{
if (!_locks.contains(m)) throw new RuntimeException("Module unlocked w/o being locked");
if (!_locks.contains(m)) {
throw new RuntimeException("Module unlocked w/o being locked");
}
_locks.remove(m);
}
......@@ -73,6 +87,15 @@ public class AppContext {
public MessagePane getMessagePane() {
return _msgPane;
}
private Message _lockedMessage = new BaseMessage("One or more modules is currently in use by another operation");
public void showLockedMessage() {
getMessagePane().addMessage(_lockedMessage);
}
}
......@@ -45,6 +45,7 @@ import javax.swing.JRadioButton;
import nl.nikhef.safaripark.devmgr.BaySelectionListener;
import nl.nikhef.safaripark.extra.BaseMessage;
import nl.nikhef.safaripark.extra.Message;
import nl.nikhef.safaripark.extra.Module;
import nl.nikhef.sfp.SFPDevice;
import nl.nikhef.sfp.ddmi.DDMI;
import nl.nikhef.sfp.ddmi.DDMIContext;
......@@ -67,6 +68,7 @@ public class ModuleManager implements BaySelectionListener
private String _moduleName;
private DateFormat _fileDateFormat = new SimpleDateFormat("yyMMdd_HHmmss");
private AppContext _appCtx;
private Module _selectedMod;
public ModuleManager(Action binExport, AppContext appCtx)
{
......@@ -109,6 +111,7 @@ public class ModuleManager implements BaySelectionListener
{
_ctx = _appCtx.ctxCache.getContextFor(dev, bay);
_selectedMod = new Module(dev, bay);
_moduleName = dev.getModuleName(bay);
_binExport.setEnabled(true);
widthdrawChecksum();
......@@ -116,6 +119,7 @@ public class ModuleManager implements BaySelectionListener
} else {
_ctx = null;
_binExport.setEnabled(false);
_selectedMod = null;
widthdrawChecksum();
}
} catch (IOException e) {
......@@ -136,6 +140,11 @@ public class ModuleManager implements BaySelectionListener
@Override
public void runOperation() {
if (_appCtx.isLocked(_selectedMod)) {
_appCtx.showLockedMessage();
return;
}
_ctx.updateChecksums();
}
......
......@@ -18,9 +18,18 @@
package nl.nikhef.safaripark;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.SplashScreen;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
......@@ -29,6 +38,8 @@ import java.awt.event.WindowListener;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Locale;
import java.util.Map.Entry;
import java.util.Properties;
......@@ -43,8 +54,10 @@ import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
......@@ -165,16 +178,18 @@ public class SaFariPark extends JFrame implements BaySelectionListener, WindowLi
_devMgr = new DeviceManager(appCtx.sfpMgr);
_devMgr.addDeviceSelectedListener(this);
_tabEdit = new EditPane(appCtx.ctxCache);
_tabEdit = new EditPane(appCtx);
_logOut = new ActiveLogArea();
_monitor = new Monitor(appCtx);
_status = new StatusBar();
_modMgr = new ModuleManager(_saveBinary, appCtx);
_devMgr.addDeviceSelectedListener(_modMgr);
_appCtx.setMessagePane(_messagePane);
DollyModel dm = new DollyModel(appCtx.ctxCache);
_appCtx.setSaFariPark(this);
DollyModel dm = new DollyModel(appCtx);
appCtx.sfpMgr.addSFPProviderListener(dm);
_dp = new DollyPanel(appCtx.ddmiLdr, dm, this);
_dp = new DollyPanel(dm, appCtx);
makeToolbar();
_topSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
_topSplit.setDividerLocation(300);
......@@ -292,6 +307,20 @@ public class SaFariPark extends JFrame implements BaySelectionListener, WindowLi
SwingUtilities.invokeLater(_taskRunner);
}
public static void updateSplash(String str)
{
SplashScreen ss = SplashScreen.getSplashScreen();
int height = ss.getBounds().height;
int width = ss.getBounds().width;
Graphics2D g2d = ss.createGraphics();
g2d.setColor(Color.BLACK);
g2d.fillRect(0, height - 20, width, 20);
g2d.setColor(Color.WHITE);
g2d.drawString(str, 10, ss.getBounds().height - 10);
g2d.dispose();
ss.update();
}
public static void main(String[] args)
{
System.out.printf("Starting SaFariPark on %s Java %s (%s bit) and %s (OS=%s, %s)\n",
......@@ -313,6 +342,13 @@ public class SaFariPark extends JFrame implements BaySelectionListener, WindowLi
} catch (UnsupportedLookAndFeelException e) {
}
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
SaFariPark.showFatalError(e, null);
}
});
LogManager.getLogManager().getLogger("").setLevel(Level.INFO);
Logger globalLogger = Logger.getLogger("");
......@@ -332,11 +368,16 @@ public class SaFariPark extends JFrame implements BaySelectionListener, WindowLi
}
}
SaFariPark sfpE;
try {
updateSplash("Initializing SFP drivers");
SFPManager sfpMgr = new SFPManager();
updateSplash("Loading XML definitions");
DDMILoader ddmiLdr = new DDMILoader();
OverlayManager ovlMgr = new OverlayManager();
ovlMgr.scanDirectory(new File("overlays"));
ddmiLdr.loadOverlays(ovlMgr.getOverlays());
......@@ -346,16 +387,39 @@ public class SaFariPark extends JFrame implements BaySelectionListener, WindowLi
sfpE.setVisible(true);
sfpE.init();
} catch (IOException e) {
e.printStackTrace();
showFatalError(e, null);
} catch (XMLStreamException e) {
e.printStackTrace();
showFatalError(e, null);
} catch (SAXException e) {
e.printStackTrace();
showFatalError(e, null);
}
}
private static void showFatalError(Throwable e, Component parent) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
JTextArea jte = new JTextArea(sw.toString());
JScrollPane jsp = new JScrollPane(jte);
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
int width = gd.getDisplayMode().getWidth();
int height = gd.getDisplayMode().getHeight();
Dimension dm = new Dimension(width / 2, height / 2);
jsp.setPreferredSize(dm);
JOptionPane.showMessageDialog(parent, jsp, "Fatal error", JOptionPane.ERROR_MESSAGE);
}
public static void setDpi(int dpi) {
......@@ -516,6 +580,5 @@ public class SaFariPark extends JFrame implements BaySelectionListener, WindowLi
}
......@@ -30,7 +30,9 @@ import javax.swing.DefaultListModel;
import javax.swing.ListModel;
import javax.swing.SwingUtilities;
import nl.nikhef.safaripark.AppContext;
import nl.nikhef.safaripark.ContextCache;
import nl.nikhef.safaripark.extra.BaseMessage;
import nl.nikhef.safaripark.extra.Module;
import nl.nikhef.safaripark.extra.StatefulTask;
import nl.nikhef.sfp.SFPDevice;
......@@ -52,11 +54,11 @@ public class DollyModel implements SFPDeviceListener, SFPProviderListener {
private Collection<Module> _targetModules;
private String _errorMessage;
private List<DDMIValue> _selectedValues;
private ContextCache _cc;
private AppContext _appCtx;
public DollyModel(ContextCache cc)
public DollyModel(AppContext appCtx)
{
_cc = cc;
_appCtx = appCtx;
}
......@@ -208,6 +210,9 @@ public class DollyModel implements SFPDeviceListener, SFPProviderListener {
switch (_state)
{
case PREPARE:
if (_sourceFile != null) {
try {
_vg = new FileValueGetter(_sourceFile);
......@@ -216,12 +221,29 @@ public class DollyModel implements SFPDeviceListener, SFPProviderListener {
return true;
}
} else {
_vg = new ModuleValueGetter(_cc, _sourceModule);
if (_appCtx.isLocked(_sourceModule)) {
_appCtx.showLockedMessage();
return true;
}
_vg = new ModuleValueGetter(_appCtx.ctxCache, _sourceModule);
}
for (Module m : _targetModules) {
_vs.add(new ModuleValueSetter(_cc, m));
if (_appCtx.isLocked(m)) {
_appCtx.showLockedMessage();
return true;
}
_vs.add(new ModuleValueSetter(_appCtx.ctxCache, m));
}
// at this point all locks should be tested, so if this fails, it asserts false
if (_sourceModule != null) if (!_appCtx.lock(_sourceModule)) assert(false);
for (Module m : _targetModules) if (!_appCtx.lock(m)) assert(false);
if (_targetFile != null) {
_vs.add(new FileValueSetter(_targetFile));
}
......@@ -263,6 +285,8 @@ public class DollyModel implements SFPDeviceListener, SFPProviderListener {
}
}
if (_sourceModule != null) _appCtx.unlock(_sourceModule);
for (Module m : _targetModules) _appCtx.unlock(m);
LOG.info(String.format("Cloned %d value(s) to %d output(s)", _selectedValues.size(), _vs.size()));
return true;
......@@ -275,6 +299,8 @@ public class DollyModel implements SFPDeviceListener, SFPProviderListener {
public StatefulTask getCloneTask()
{
return new CloneTask();
}
......@@ -290,14 +316,14 @@ public class DollyModel implements SFPDeviceListener, SFPProviderListener {
return;
}
} else {
vg = new ModuleValueGetter(_cc, _sourceModule);
vg = new ModuleValueGetter(_appCtx.ctxCache, _sourceModule);
}
List<ValueSetter> vs = new ArrayList<ValueSetter>();
for (Module m : _targetModules) {
vs.add(new ModuleValueSetter(_cc, m));
vs.add(new ModuleValueSetter(_appCtx.ctxCache, m));
}
if (_targetFile != null) {
vs.add(new FileValueSetter(_targetFile));
......
......@@ -40,6 +40,7 @@ import javax.swing.JTextField;
import javax.swing.filechooser.FileNameExtensionFilter;
import net.miginfocom.swing.MigLayout;
import nl.nikhef.safaripark.AppContext;
import nl.nikhef.safaripark.SaFariPark;
import nl.nikhef.safaripark.Title;
import nl.nikhef.safaripark.extra.CheckableList;
......@@ -76,17 +77,17 @@ public class DollyPanel extends JPanel implements ActionListener, ItemListener {
private DollyModel _model;
private JFileChooser _fileChooser;
private SaFariPark _sfp;
private AppContext _app;
public DollyPanel(DDMILoader loader, DollyModel model, SaFariPark sfp) {
public DollyPanel(DollyModel model, AppContext app) {
_model = model;
_sfp = sfp;
_app = app;
setLayout(new BorderLayout());
add(new Title("Clone Tool", Resources.getIcon("emblem-documents")), BorderLayout.NORTH);
_vsp = new ValueSelectionPane(loader);
_vsp = new ValueSelectionPane(_app.ddmiLdr);
JPanel core = new JPanel();
core.setLayout(new BorderLayout());
......@@ -122,7 +123,7 @@ public class DollyPanel extends JPanel implements ActionListener, ItemListener {
JScrollPane jsp = new JScrollPane(_targetModuleSelects);
target.add(new JScrollPane(_targetModuleSelects),"growx, span 2, wrap, height :100:");
target.add(jsp,"growx, span 2, wrap, height :100:");
target.add(_targetFileOption);
target.add(_targetFileName, "growx");
_targetFileName.setEditable(false);
......@@ -199,7 +200,7 @@ public class DollyPanel extends JPanel implements ActionListener, ItemListener {
@Override
public void actionPerformed(ActionEvent e) {
_sfp.executeTask(_model.getCloneTask());
_app.getSaFariPark().executeTask(_model.getCloneTask());
}
});
......
......@@ -34,8 +34,10 @@ import javax.swing.JTabbedPane;
import javax.swing.JToolBar;
import javax.swing.SwingConstants;
import nl.nikhef.safaripark.AppContext;
import nl.nikhef.safaripark.ContextCache;
import nl.nikhef.safaripark.extra.GuiUtils;
import nl.nikhef.safaripark.extra.Module;
import nl.nikhef.safaripark.res.Resources;
import nl.nikhef.sfp.SFPDevice;
import nl.nikhef.sfp.ddmi.DDMI;
......@@ -51,9 +53,8 @@ public class EditPane extends JPanel {
private JTabbedPane _tab;
private JToolBar _tbar;
private EditorContext _ctx;
private ContextCache _ctxCache;
private SFPDevice _dev;
private int _bay;
private AppContext _appCtx;
private Module _module;
private Action _apply = new AbstractAction("Apply", Resources.getIcon("dialog-apply")) {
......@@ -61,7 +62,8 @@ public class EditPane extends JPanel {
public void actionPerformed(ActionEvent e) {
_ctx.commit();
_ctx.getContext().updateChecksums();
_dev.refreshInfo(_bay);
//_dev.refreshInfo(_bay);
_module.dev.refreshInfo(_module.bay);
}
};
......@@ -88,15 +90,15 @@ public class EditPane extends JPanel {
};
public EditPane(ContextCache ctxCache) {
public EditPane(AppContext appCtx) {
setLayout(new BorderLayout());
_ctxCache = ctxCache;
_ctx = new EditorContext(_apply, _revert, _reload);
_appCtx = appCtx;
_ctx = new EditorContext(_appCtx, _apply, _revert, _reload);
_tbar = new JToolBar("Form Editor");
......@@ -137,19 +139,18 @@ public class EditPane extends JPanel {
{
_apply.setEnabled(false);
_revert.setEnabled(false);
// TODO Remove checksum test from this location. Should be generic
_dev = dev;
_bay = bay;
if (dev.isModulePresent(bay)) {
DDMIContext ctx = _ctxCache.getContextFor(dev, bay);
_ctx.setContext(ctx);
DDMIContext ctx = _appCtx.ctxCache.getContextFor(dev, bay);
_module = new Module(dev, bay);
_ctx.setContext(ctx, _module);
_reload.setEnabled(true);
} else {
_ctx.setContext(null);
_module = null;
_ctx.setContext(null, null);
_reload.setEnabled(false);
}
}
......
......@@ -23,7 +23,10 @@ import java.util.List;
import java.util.Set;
import javax.swing.Action;
import javax.swing.SwingUtilities;
import nl.nikhef.safaripark.AppContext;
import nl.nikhef.safaripark.extra.Module;
import nl.nikhef.sfp.ddmi.DDMIContext;
import nl.nikhef.sfp.ddmi.DataSource;
......@@ -44,11 +47,15 @@ public class EditorContext
private Action _apply;
private Action _revert;
private Action _reload;
private AppContext _appCtx;
private boolean _hasLock = false;
private Module _selected;
public EditorContext(Action apply, Action revert, Action reload) {
public EditorContext(AppContext appCtx, Action apply, Action revert, Action reload) {
_apply = apply;
_revert = revert;
_reload = reload;
_appCtx = appCtx;
}
void addEditor(ValueEditor editor)
......@@ -62,10 +69,15 @@ public class EditorContext
*
* @param ctx The Link.
*/
public void setContext(DDMIContext ctx)
public void setContext(DDMIContext ctx, Module mod)
{
_ctx = ctx;
freeLock();
_selected = mod;
_dirty.clear();
for (ValueEditor ve : _editor)
......@@ -75,6 +87,13 @@ public class EditorContext
}
private void freeLock() {
if (!_hasLock) return;
_appCtx.unlock(_selected);
_hasLock = false;
}
/**
* Returns whether or not some components are dirty.
*
......@@ -115,6 +134,7 @@ public class EditorContext
}
_dirty.clear();
_batchProc = false;
freeLock();
updateButtons();
}
......@@ -127,6 +147,7 @@ public class EditorContext
}
_dirty.clear();
_batchProc = false;
freeLock();
updateButtons();
}
......@@ -154,8 +175,26 @@ public class EditorContext
public void changeDirtyState(ValueEditor valueEditor) {
if (_batchProc) return;
if (valueEditor.dirty)
{
if (!_hasLock) {
if (_appCtx.isLocked(_selected)) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
revert();
}
});
_appCtx.showLockedMessage();
return;
}
_appCtx.lock(_selected);
_hasLock = true;
}
if (!_dirty.contains(valueEditor)) _dirty.add(valueEditor);
}
else
......
......@@ -20,6 +20,7 @@ package nl.nikhef.safaripark.extra;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;
......@@ -40,7 +41,7 @@ public class MessagePane extends JPanel implements ActionListener {
private JButton _close;
private Queue<Message> _messages = new LinkedList<Message>();
private LinkedList<Message> _messages = new LinkedList<Message>();
public MessagePane() {
Border outside = BorderFactory.createMatteBorder(1, 1, 1, 1, Color.BLACK);
......@@ -83,8 +84,11 @@ public class MessagePane extends JPanel implements ActionListener {
public void addMessage(Message m)
{
if (_messages.contains(m)) return;
_messages.add(m);
_messages.addFirst(m);
updateQueue();
/*Runnable sound2 =
(Runnable)Toolkit.getDefaultToolkit().getDesktopProperty("win.sound.default");
if(sound2 != null) sound2.run();*/
}
public void widthdrawMessage(Message m)
......
......@@ -77,9 +77,13 @@ public class Module {
return false;
return true;
}
public void refresh() {
dev.refreshInfo(bay);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment