changeset 98:c3002fd38e27

Fix dirty state handling for edit pages
author Omair Majid <omajid@redhat.com>
date Fri, 07 Feb 2014 12:57:54 -0500
parents 1c835942f3c2
children 7484f4e4f587
files TODO.md com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/editor/CommandEditPage.java com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/editor/DataBindingChangeSupport.java com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/editor/ExtensionEditPage.java com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/editor/MultiPageEditor.java
diffstat 5 files changed, 92 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/TODO.md	Thu Feb 06 17:03:49 2014 -0500
+++ b/TODO.md	Fri Feb 07 12:57:54 2014 -0500
@@ -6,7 +6,7 @@
 
 - Add validators for all fields where it makes sense
 
-- Fix up dirty/stale states
+- Fix up stale states
 
 - Implement support for options/arguments
 
--- a/com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/editor/CommandEditPage.java	Thu Feb 06 17:03:49 2014 -0500
+++ b/com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/editor/CommandEditPage.java	Fri Feb 07 12:57:54 2014 -0500
@@ -4,6 +4,8 @@
 import org.eclipse.core.databinding.DataBindingContext;
 import org.eclipse.core.databinding.UpdateValueStrategy;
 import org.eclipse.core.databinding.beans.BeanProperties;
+import org.eclipse.core.databinding.observable.ChangeEvent;
+import org.eclipse.core.databinding.observable.IChangeListener;
 import org.eclipse.core.databinding.observable.list.IObservableList;
 import org.eclipse.core.databinding.observable.value.IObservableValue;
 import org.eclipse.jface.databinding.fieldassist.ControlDecorationSupport;
@@ -46,10 +48,12 @@
  * <p>
  * The details area of the master-details block.
  */
-class CommandEditPage implements IDetailsPage {
+class CommandEditPage implements IDetailsPage, IChangeListener {
 
     private FormToolkit toolkit;
     private Plugin model;
+
+    private boolean isDirty = false;
     private boolean isStale = false;
 
     private Command commandModel;
@@ -83,28 +87,23 @@
     @Override
     public void dispose() {
         if (bindingContext != null) {
+            DataBindingChangeSupport.removeChangeListener(bindingContext, this);
             bindingContext.dispose();
         }
     }
 
     @Override
     public boolean isDirty() {
-        if (commandModel == null) {
-            return false;
-        }
-
-        Command latestCommandInModel = model.getCommand(commandModel.getName());
-        if (latestCommandInModel == null) {
-            return false;
-        }
-
-        // TODO convert is-command-different into is-command-dirty operation
-        return !latestCommandInModel.equals(commandModel);
+        return isDirty;
     }
 
     @Override
     public void commit(boolean onSave) {
-        // no op
+        // model is always kept in sync
+
+        if (onSave) {
+            isDirty = false;
+        }
     }
 
     @Override
@@ -126,12 +125,13 @@
 
     @Override
     public void refresh() {
-        // no-op
+        // no-op: model is always kept in sync
     }
 
     @Override
     public void selectionChanged(IFormPart part, ISelection selection) {
         if (bindingContext != null) {
+            DataBindingChangeSupport.removeChangeListener(bindingContext, this);
             bindingContext.dispose();
         }
 
@@ -142,6 +142,7 @@
         }
 
         bindingContext = initDataBindings();
+        DataBindingChangeSupport.addChangeListener(bindingContext, this);
     }
 
     @Override
@@ -285,4 +286,11 @@
 
         return bindingContext;
     }
+
+    @Override
+    public void handleChange(ChangeEvent event) {
+        isDirty = true;
+
+        form.getEditor().editorDirtyStateChanged();
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/editor/DataBindingChangeSupport.java	Fri Feb 07 12:57:54 2014 -0500
@@ -0,0 +1,27 @@
+package com.redhat.thermostat.tools.eclipse.plugin.editor;
+
+import org.eclipse.core.databinding.Binding;
+import org.eclipse.core.databinding.DataBindingContext;
+import org.eclipse.core.databinding.observable.IChangeListener;
+import org.eclipse.core.databinding.observable.list.IObservableList;
+
+public class DataBindingChangeSupport {
+
+    public static void addChangeListener(DataBindingContext bindingContext, IChangeListener listener) {
+
+        IObservableList providers = bindingContext.getValidationStatusProviders();
+        for (Object o : providers) {
+            Binding b = (Binding) o;
+            b.getTarget().addChangeListener(listener);
+        }
+    }
+
+    public static void removeChangeListener(DataBindingContext bindingContext, IChangeListener listener) {
+        IObservableList providers = bindingContext.getValidationStatusProviders();
+        for (Object o : providers) {
+            Binding b = (Binding) o;
+            b.getTarget().removeChangeListener(listener);
+        }
+    }
+
+}
--- a/com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/editor/ExtensionEditPage.java	Thu Feb 06 17:03:49 2014 -0500
+++ b/com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/editor/ExtensionEditPage.java	Fri Feb 07 12:57:54 2014 -0500
@@ -1,9 +1,9 @@
 package com.redhat.thermostat.tools.eclipse.plugin.editor;
 
-import java.util.Objects;
-
 import org.eclipse.core.databinding.DataBindingContext;
 import org.eclipse.core.databinding.beans.BeanProperties;
+import org.eclipse.core.databinding.observable.ChangeEvent;
+import org.eclipse.core.databinding.observable.IChangeListener;
 import org.eclipse.core.databinding.observable.list.IObservableList;
 import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
 import org.eclipse.jface.viewers.ISelection;
@@ -36,7 +36,7 @@
 /**
  * Edits aspects of a single extension.
  */
-public class ExtensionEditPage implements IDetailsPage {
+public class ExtensionEditPage implements IDetailsPage, IChangeListener {
 
     private FormToolkit toolkit;
     private Plugin model;
@@ -48,6 +48,8 @@
 
     private FormPage formPage;
 
+    private boolean isDirty = false;
+
     public ExtensionEditPage(FormPage parent) {
         this.formPage = parent;
     }
@@ -64,28 +66,23 @@
     @Override
     public void dispose() {
         if (bindingContext != null) {
+            DataBindingChangeSupport.removeChangeListener(bindingContext, this);
             bindingContext.dispose();
         }
     }
 
     @Override
     public boolean isDirty() {
-        if (extensionModel == null) {
-            return false;
-        }
-
-        Extension extensionInMasterModel = model.getExtension(extensionModel.getName());
-        if (extensionInMasterModel == null) {
-            return false;
-        }
-
-        // TODO change this is-content-different into is-content-dirty
-        return !extensionInMasterModel.equals(extensionModel);
+        return isDirty;
     }
 
     @Override
     public void commit(boolean onSave) {
-        // nothing to do
+        // model is always kept in sync
+
+        if (onSave) {
+            isDirty = false;
+        }
     }
 
     @Override
@@ -114,6 +111,7 @@
     @Override
     public void selectionChanged(IFormPart part, ISelection selection) {
         if (bindingContext != null) {
+            DataBindingChangeSupport.removeChangeListener(bindingContext, this);
             bindingContext.dispose();
         }
 
@@ -121,6 +119,7 @@
         extensionModel = model.getExtension(extensionName);
 
         bindingContext = initDataBindings();
+        DataBindingChangeSupport.addChangeListener(bindingContext, this);
     }
 
     @Override
@@ -204,4 +203,12 @@
 
         return bindingContext;
     }
+
+    @Override
+    public void handleChange(ChangeEvent event) {
+        isDirty = true;
+
+        formPage.getEditor().editorDirtyStateChanged();
+    }
+
 }
--- a/com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/editor/MultiPageEditor.java	Thu Feb 06 17:03:49 2014 -0500
+++ b/com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/editor/MultiPageEditor.java	Fri Feb 07 12:57:54 2014 -0500
@@ -2,6 +2,7 @@
 
 import java.io.ByteArrayOutputStream;
 import java.nio.charset.StandardCharsets;
+import java.util.Iterator;
 import java.util.Objects;
 
 import org.eclipse.core.resources.IFile;
@@ -21,6 +22,7 @@
 import org.eclipse.ui.IWorkbenchPage;
 import org.eclipse.ui.PartInitException;
 import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.IFormPage;
 import org.eclipse.ui.part.FileEditorInput;
 import org.eclipse.wst.sse.ui.StructuredTextEditor;
 
@@ -32,6 +34,11 @@
     private static final int INDEX_SOURCE = 3;
 
     private StructuredTextEditor editor;
+
+    /**
+     * Helps synchronizing changes between editor and model. Not related to
+     * {@code isDirty()}.
+     */
     private boolean editorIsDirty = false;
 
     private PluginModelReaderWriter modelHelper;
@@ -128,6 +135,19 @@
             updateSourceFromModel();
         }
 
+        // save all the pages. this doesn't really do the saving, but tells each
+        // page that it is being saved, so they can get a chance to update the
+        // model and deal with changes
+        Iterator iter = pages.iterator();
+        while (iter.hasNext()) {
+            Object obj = iter.next();
+
+            if (obj instanceof IFormPage) {
+                ((IFormPage) obj).doSave(monitor);
+            }
+        }
+
+        // actually save the model
         editor.doSave(monitor);
     }