package org.simantics.ui.workbench.handler.e4; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.contexts.IContextActivation; import org.eclipse.ui.contexts.IContextService; import org.simantics.DatabaseJob; import org.simantics.Simantics; import org.simantics.db.Session; import org.simantics.db.UndoContext; import org.simantics.db.exception.DatabaseException; import org.simantics.db.management.ISessionContext; import org.simantics.db.service.UndoRedoSupport; import org.simantics.ui.SimanticsUI; import org.simantics.utils.ui.ErrorLogger; import org.simantics.utils.ui.SWTUtils; public class UndoRedoTester { private static final boolean DEBUG = false; private static final String SIMANTICS_UNDO_CONTEXT = "org.simantics.ui.undoContext"; public static final String UNDO_ENABLED = "org.simantics.undo.enabled"; private static UndoRedoSupport undoSupport = null; private static UndoChangeListener changeListener = new UndoChangeListener(); private static IContextActivation activation = null; private static class UndoChangeListener implements UndoRedoSupport.ChangeListener { private int oldUndo = 0; private int oldRedo = 0; @Override public void onChanged() { if (DEBUG) System.out.println("UndoPropertyTester: on change."); Display display = PlatformUI.getWorkbench().getDisplay(); SWTUtils.asyncExec(display, new Runnable() { @Override public void run() { handleChange(); } }); } private void handleChange() { int newUndo = oldUndo; int newRedo = oldRedo; try { ISessionContext ctx = Simantics.getSessionContext(); if (DEBUG) System.out.println("UndoPropertyTester: handle change, ctx=" + ctx); if (ctx == null) return; Session session = ctx.peekSession(); if (DEBUG) System.out.println("UndoPropertyTester: handle change, session=" + session); if (session == null) return; UndoContext uc = undoSupport.getUndoContext(session); if (uc == null) return; newUndo = uc.getAll().size(); newRedo = uc.getRedoList().size(); if (DEBUG) { System.out.println("on undo change: " + oldUndo + "->" + newUndo); System.out.println("on redo change: " + oldRedo + "->" + newRedo); } boolean undoOn = oldUndo == 0 && newUndo == 1; boolean undoOff = oldUndo > 0 && newUndo == 0; boolean redoOn = oldRedo == 0 && newRedo == 1; boolean redoOff = oldRedo > 0 && newRedo == 0; if (undoOn || undoOff || redoOn || redoOff) toggleContext(); } catch (DatabaseException e) { ErrorLogger.getDefault().logError("Undo/Redo support failed.", e); } oldUndo = newUndo; oldRedo = newRedo; } private void toggleContext() { IContextService contextService = (IContextService)PlatformUI.getWorkbench().getService(IContextService.class); if (null != activation) { if (DEBUG) System.out.println("UndoPropertyTester: deactivate."); try { contextService.deactivateContext(activation); } catch (Throwable t) { ErrorLogger.getDefault().logError("Undo/Redo support failed.", t); } activation = null; if (DEBUG) System.out.println("UndoPropertyTester: deactivated."); } else { if (DEBUG) System.out.println("UndoPropertyTester: activate."); try { activation = contextService.activateContext(SIMANTICS_UNDO_CONTEXT); } catch (Throwable t) { ErrorLogger.getDefault().logError("Undo/Redo support failed.", t); activation = null; } if (DEBUG) System.out.println("UndoPropertyTester: activated=" + activation); } } } private UndoRedoTester() { } public static boolean canUndo() { String undoEnabled = System.getProperty(UNDO_ENABLED); if(undoEnabled != null && "false".equals(undoEnabled)) return false; ISessionContext ctx = Simantics.getSessionContext(); if (ctx == null) { if (DEBUG) System.out.println("UndoPropertyTester: no can do undo."); return false; } try { Session s = ctx.peekSession(); if (null == s) { if (DEBUG) System.out.println("UndoPropertyTester: session is null, no can do undo."); return false; } if (DatabaseJob.inProgress()) return true; if (null == undoSupport) { undoSupport = s.getService(UndoRedoSupport.class); undoSupport.subscribe(changeListener); } UndoContext uc = undoSupport.getUndoContext(s); if (uc == null) return false; boolean ret = !uc.getAll().isEmpty(); if (DEBUG) System.out.println("UndoPropertyTester: " + (ret ? "" : "no ")+ "can do undo."); return ret; } catch (Exception e) { ErrorLogger.getDefault().logError("Undo/Redo support failed.", e); if (DEBUG) System.out.println("UndoPropertyTester: no can do undo"); return false; } } public static boolean canRedo() { ISessionContext ctx = Simantics.getSessionContext(); if (ctx == null) { if (DEBUG) System.out.println("UndoPropertyTester: no can do redo."); return false; } try { Session s = ctx.peekSession(); if (null == s) { if (DEBUG) System.out.println("UndoPropertyTester: session is null, no can do redo."); return false; } if (DatabaseJob.inProgress()) return true; if (null == undoSupport) { undoSupport = s.getService(UndoRedoSupport.class); undoSupport.subscribe(changeListener); } UndoContext uc = undoSupport.getUndoContext(s); if (uc == null) return false; boolean ret = !uc.getRedoList().isEmpty(); if (DEBUG) System.out.println("UndoPropertyTester: " + (ret ? "" : "no ")+ "can do redo."); return ret; } catch (Exception e) { ErrorLogger.getDefault().logError("Undo/Redo support failed.", e); if (DEBUG) System.out.println("UndoPropertyTester: no can do redo."); return false; } } }