aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaphael Moll <ralf@android.com>2010-09-15 19:25:54 -0700
committerRaphael Moll <ralf@android.com>2010-09-15 19:34:18 -0700
commitaa80eb0797889e53c43ef91bb8e63d8d9d5f1d24 (patch)
tree58d3c1edabdcd33e1492a23a97b6bf3e74ed7f22
parent2bbc18d53dd0e845677081be94ff57450d4e91fc (diff)
downloadsdk-aa80eb0797889e53c43ef91bb8e63d8d9d5f1d24.zip
sdk-aa80eb0797889e53c43ef91bb8e63d8d9d5f1d24.tar.gz
sdk-aa80eb0797889e53c43ef91bb8e63d8d9d5f1d24.tar.bz2
GLE2: fix layout editor not properly closed when dirty.
The symptom was that once the layout editor had a modification and was in the "dirty" mode, closing it would keep the model around and re-opening would show the previous state. That was a red herring. The actual issue is that the undo begin/end wrapper methods were calling getModelForEdit() without doing a proper releaseFromEdit() call after the fact. Somewhere down in the overly complex code that disposes the EditorPart there is a test that would not purge the model if it is still locked. The fix is thus in the begin/endUndoRecording of the base AndroidXmlEditor. This CL also cleans up some IFile usage; when fixing the code above I noticed we can now get the model without first getting an SSE internal document, instead we can use the editor's IFile. However I doubt SSE for 3.3 would have the API, I need to check that in another CL. Later, it's a P3. Change-Id: I2437475dfeee9d6689b7b604782ae140d7aff1c3
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidTextEditor.java14
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidXmlEditor.java115
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/MatchingStrategy.java6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestEditor.java39
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/PasteAction.java103
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiElementDetail.java72
6 files changed, 184 insertions, 165 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidTextEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidTextEditor.java
index d180b5e..e524826 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidTextEditor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidTextEditor.java
@@ -318,6 +318,20 @@ public abstract class AndroidTextEditor extends FormEditor implements IResourceC
}
/**
+ * Returns the {@link IFile} matching the editor's input or null.
+ * <p/>
+ * By construction, the editor input has to be an {@link IFileEditorInput} so it must
+ * have an associated {@link IFile}. Null can only be returned if this editor has no
+ * input somehow.
+ */
+ public IFile getFile() {
+ if (getEditorInput() instanceof IFileEditorInput) {
+ return ((IFileEditorInput) getEditorInput()).getFile();
+ }
+ return null;
+ }
+
+ /**
* Removes attached listeners.
*
* @see WorkbenchPart
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidXmlEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidXmlEditor.java
index ed5e79d..c3970d3 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidXmlEditor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidXmlEditor.java
@@ -56,7 +56,6 @@ import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.events.IHyperlinkListener;
import org.eclipse.ui.forms.widgets.FormText;
import org.eclipse.ui.internal.browser.WorkbenchBrowserSupport;
-import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.part.MultiPageEditorPart;
import org.eclipse.ui.part.WorkbenchPart;
import org.eclipse.wst.sse.core.StructuredModelManager;
@@ -249,9 +248,8 @@ public abstract class AndroidXmlEditor extends FormEditor implements IResourceCh
*/
protected void selectDefaultPage(String defaultPageId) {
if (defaultPageId == null) {
- if (getEditorInput() instanceof IFileEditorInput) {
- IFile file = ((IFileEditorInput) getEditorInput()).getFile();
-
+ IFile file = getInputFile();
+ if (file != null) {
QualifiedName qname = new QualifiedName(AdtPlugin.PLUGIN_ID,
getClass().getSimpleName() + PREF_CURRENT_PAGE);
String pageId;
@@ -323,9 +321,8 @@ public abstract class AndroidXmlEditor extends FormEditor implements IResourceCh
return;
}
- if (getEditorInput() instanceof IFileEditorInput) {
- IFile file = ((IFileEditorInput) getEditorInput()).getFile();
-
+ IFile file = getInputFile();
+ if (file != null) {
QualifiedName qname = new QualifiedName(AdtPlugin.PLUGIN_ID,
getClass().getSimpleName() + PREF_CURRENT_PAGE);
try {
@@ -345,21 +342,19 @@ public abstract class AndroidXmlEditor extends FormEditor implements IResourceCh
*/
public void resourceChanged(final IResourceChangeEvent event) {
if (event.getType() == IResourceChangeEvent.PRE_CLOSE) {
- Display.getDefault().asyncExec(new Runnable() {
- public void run() {
- IWorkbenchPage[] pages = getSite().getWorkbenchWindow()
- .getPages();
- for (int i = 0; i < pages.length; i++) {
- if (((FileEditorInput)mTextEditor.getEditorInput())
- .getFile().getProject().equals(
- event.getResource())) {
- IEditorPart editorPart = pages[i].findEditor(mTextEditor
- .getEditorInput());
+ IFile file = getInputFile();
+ if (file != null && file.getProject().equals(event.getResource())) {
+ final IEditorInput input = getEditorInput();
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ IWorkbenchPage[] pages = getSite().getWorkbenchWindow().getPages();
+ for (int i = 0; i < pages.length; i++) {
+ IEditorPart editorPart = pages[i].findEditor(input);
pages[i].closeEditor(editorPart, true);
}
}
- }
- });
+ });
+ }
}
}
@@ -378,6 +373,21 @@ public abstract class AndroidXmlEditor extends FormEditor implements IResourceCh
}
/**
+ * Returns the {@link IFile} matching the editor's input or null.
+ * <p/>
+ * By construction, the editor input has to be an {@link IFileEditorInput} so it must
+ * have an associated {@link IFile}. Null can only be returned if this editor has no
+ * input somehow.
+ */
+ public IFile getInputFile() {
+ IEditorInput input = getEditorInput();
+ if (input instanceof IFileEditorInput) {
+ return ((IFileEditorInput) input).getFile();
+ }
+ return null;
+ }
+
+ /**
* Removes attached listeners.
*
* @see WorkbenchPart
@@ -626,6 +636,11 @@ public abstract class AndroidXmlEditor extends FormEditor implements IResourceCh
if (document != null) {
IModelManager mm = StructuredModelManager.getModelManager();
if (mm != null) {
+ // TODO simplify this by not using the internal IStructuredDocument.
+ // Instead we can now use mm.getModelForRead(getFile()).
+ // However we must first check that SSE for Eclipse 3.3 or 3.4 has this
+ // method. IIRC 3.3 didn't have it.
+
return mm.getModelForRead(document);
}
}
@@ -636,18 +651,25 @@ public abstract class AndroidXmlEditor extends FormEditor implements IResourceCh
* Returns a version of the model that has been shared for edit.
* <p/>
* Callers <em>must</em> call model.releaseFromEdit() when done, typically
- * in a try..finally clause. Because of this, it is highly recommended
- * to <b>NOT</b> use this method directly and instead use the wrapper
+ * in a try..finally clause.
+ * <p/>
+ * Because of this, it is mandatory to use the wrapper
* {@link #wrapEditXmlModel(Runnable)} which executes a runnable into a
* properly configured model and then performs whatever cleanup is necessary.
*
* @return The model for the XML document or null if cannot be obtained from the editor
*/
- public final IStructuredModel getModelForEdit() {
+ private IStructuredModel getModelForEdit() {
+
IStructuredDocument document = getStructuredDocument();
if (document != null) {
IModelManager mm = StructuredModelManager.getModelManager();
if (mm != null) {
+ // TODO simplify this by not using the internal IStructuredDocument.
+ // Instead we can now use mm.getModelForRead(getFile()).
+ // However we must first check that SSE for Eclipse 3.3 or 3.4 has this
+ // method. IIRC 3.3 didn't have it.
+
return mm.getModelForEdit(document);
}
}
@@ -700,7 +722,7 @@ public abstract class AndroidXmlEditor extends FormEditor implements IResourceCh
if (mIsEditXmlModelPending < 0) {
AdtPlugin.log(IStatus.ERROR,
- "wrapEditXmlModel finished with invalid nested counter==%d", //$NON-NLS-1$
+ "wrapEditXmlModel finished with invalid nested counter==%1$d", //$NON-NLS-1$
mIsEditXmlModelPending);
mIsEditXmlModelPending = 0;
}
@@ -770,16 +792,14 @@ public abstract class AndroidXmlEditor extends FormEditor implements IResourceCh
* @return True if the undo recording actually started, false if any kind of error occured.
* {@link #endUndoRecording()} should only be called if True is returned.
*/
- private final boolean beginUndoRecording(String label) {
- IStructuredDocument document = getStructuredDocument();
- if (document != null) {
- IModelManager mm = StructuredModelManager.getModelManager();
- if (mm != null) {
- IStructuredModel model = mm.getModelForEdit(document);
- if (model != null) {
- model.beginRecording(this, label);
- return true;
- }
+ private boolean beginUndoRecording(String label) {
+ IStructuredModel model = getModelForEdit();
+ if (model != null) {
+ try {
+ model.beginRecording(this, label);
+ return true;
+ } finally {
+ model.releaseFromEdit();
}
}
return false;
@@ -792,15 +812,13 @@ public abstract class AndroidXmlEditor extends FormEditor implements IResourceCh
* used if the initial call returned true.
* To guarantee that, only access this via {@link #wrapUndoEditXmlModel(String, Runnable)}.
*/
- private final void endUndoRecording() {
- IStructuredDocument document = getStructuredDocument();
- if (document != null) {
- IModelManager mm = StructuredModelManager.getModelManager();
- if (mm != null) {
- IStructuredModel model = mm.getModelForEdit(document);
- if (model != null) {
- model.endRecording(this);
- }
+ private void endUndoRecording() {
+ IStructuredModel model = getModelForEdit();
+ if (model != null) {
+ try {
+ model.endRecording(this);
+ } finally {
+ model.releaseFromEdit();
}
}
}
@@ -825,16 +843,9 @@ public abstract class AndroidXmlEditor extends FormEditor implements IResourceCh
* Returns the {@link IProject} for the edited file.
*/
public IProject getProject() {
- if (mTextEditor != null) {
- IEditorInput input = mTextEditor.getEditorInput();
- if (input instanceof FileEditorInput) {
- FileEditorInput fileInput = (FileEditorInput)input;
- IFile inputFile = fileInput.getFile();
-
- if (inputFile != null) {
- return inputFile.getProject();
- }
- }
+ IFile file = getInputFile();
+ if (file != null) {
+ return file.getProject();
}
return null;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/MatchingStrategy.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/MatchingStrategy.java
index a6a19a6..c6c5261 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/MatchingStrategy.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/MatchingStrategy.java
@@ -37,11 +37,11 @@ public class MatchingStrategy implements IEditorMatchingStrategy {
// first check that the file being opened is a layout file.
if (input instanceof FileEditorInput) {
FileEditorInput fileInput = (FileEditorInput)input;
-
+
// get the IFile object and check it's in one of the layout folders.
IFile iFile = fileInput.getFile();
ResourceFolder resFolder = ResourceManager.getInstance().getResourceFolder(iFile);
-
+
// if it's a layout, we know check the name of the fileInput against the name of the
// file being currently edited by the editor since those are independent of the config.
if (resFolder != null && resFolder.getType() == ResourceFolderType.LAYOUT) {
@@ -50,7 +50,7 @@ public class MatchingStrategy implements IEditorMatchingStrategy {
if (editorInput instanceof FileEditorInput) {
FileEditorInput editorFileInput = (FileEditorInput)editorInput;
IFile editorIFile = editorFileInput.getFile();
-
+
return editorIFile.getProject().equals(iFile.getProject())
&& editorIFile.getName().equals(iFile.getName());
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestEditor.java
index edf0103..6e0936b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestEditor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestEditor.java
@@ -41,7 +41,7 @@ import org.eclipse.core.runtime.CoreException;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PartInitException;
-import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
@@ -198,8 +198,15 @@ public final class ManifestEditor extends AndroidXmlEditor {
}
private void onDescriptorsChanged() {
- Node node = getManifestXmlNode(getXmlDocument(getModelForRead()));
- mUiManifestNode.reloadFromXmlNode(node);
+ IStructuredModel model = getModelForRead();
+ if (model != null) {
+ try {
+ Node node = getManifestXmlNode(getXmlDocument(model));
+ mUiManifestNode.reloadFromXmlNode(node);
+ } finally {
+ model.releaseFromRead();
+ }
+ }
if (mOverviewPage != null) {
mOverviewPage.refreshUiApplicationNode();
@@ -234,7 +241,8 @@ public final class ManifestEditor extends AndroidXmlEditor {
}
};
- GlobalProjectMonitor.getMonitor().addFileListener(mMarkerMonitor, IResourceDelta.CHANGED);
+ GlobalProjectMonitor.getMonitor().addFileListener(
+ mMarkerMonitor, IResourceDelta.CHANGED);
}
}
@@ -246,17 +254,17 @@ public final class ManifestEditor extends AndroidXmlEditor {
private void updateFromExistingMarkers(IFile inputFile) {
try {
// get the markers for the file
- IMarker[] markers = inputFile.findMarkers(AndroidConstants.MARKER_ANDROID, true,
- IResource.DEPTH_ZERO);
+ IMarker[] markers = inputFile.findMarkers(
+ AndroidConstants.MARKER_ANDROID, true, IResource.DEPTH_ZERO);
AndroidManifestDescriptors desc = getManifestDescriptors();
if (desc != null) {
ElementDescriptor appElement = desc.getApplicationElement();
- if (appElement != null) {
- UiElementNode app_ui_node = mUiManifestNode.findUiChildNode(
+ if (appElement != null && mUiManifestNode != null) {
+ UiElementNode appUiNode = mUiManifestNode.findUiChildNode(
appElement.getXmlName());
- List<UiElementNode> children = app_ui_node.getUiChildren();
+ List<UiElementNode> children = appUiNode.getUiChildren();
for (IMarker marker : markers) {
processMarker(marker, children, IResourceDelta.ADDED);
@@ -378,17 +386,4 @@ public final class ManifestEditor extends AndroidXmlEditor {
mUiManifestNode.setEditor(this);
}
}
-
- /**
- * Returns the {@link IFile} being edited, or <code>null</code> if it couldn't be computed.
- */
- private IFile getInputFile() {
- IEditorInput input = getEditorInput();
- if (input instanceof FileEditorInput) {
- FileEditorInput fileInput = (FileEditorInput) input;
- return fileInput.getFile();
- }
-
- return null;
- }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/PasteAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/PasteAction.java
index d649af7..9cd7412 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/PasteAction.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/PasteAction.java
@@ -27,7 +27,6 @@ import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
-import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
@@ -63,61 +62,65 @@ public class PasteAction extends Action {
@Override
public void run() {
super.run();
-
+
final String data = (String) mClipboard.getContents(TextTransfer.getInstance());
if (data != null) {
- IStructuredModel model = mEditor.getModelForEdit();
- try {
- IStructuredDocument sse_doc = mEditor.getStructuredDocument();
- if (sse_doc != null) {
- if (mUiNode.getDescriptor().hasChildren()) {
- // This UI Node can have children. The new XML is
- // inserted as the first child.
-
- if (mUiNode.getUiChildren().size() > 0) {
- // There's already at least one child, so insert right before it.
- Node xml_node = mUiNode.getUiChildren().get(0).getXmlNode();
- if (xml_node instanceof IndexedRegion) { // implies xml_node != null
- IndexedRegion region = (IndexedRegion) xml_node;
- sse_doc.replace(region.getStartOffset(), 0, data);
- return; // we're done, no need to try the other cases
- }
- }
-
- // If there's no first XML node child. Create one by
- // inserting at the end of the *start* tag.
- Node xml_node = mUiNode.getXmlNode();
- if (xml_node instanceof NodeContainer) {
- NodeContainer container = (NodeContainer) xml_node;
- IStructuredDocumentRegion start_tag =
- container.getStartStructuredDocumentRegion();
- if (start_tag != null) {
- sse_doc.replace(start_tag.getEndOffset(), 0, data);
- return; // we're done, no need to try the other case
+ mEditor.wrapEditXmlModel(new Runnable() {
+ public void run() {
+ try {
+ IStructuredDocument sse_doc = mEditor.getStructuredDocument();
+ if (sse_doc != null) {
+ if (mUiNode.getDescriptor().hasChildren()) {
+ // This UI Node can have children. The new XML is
+ // inserted as the first child.
+
+ if (mUiNode.getUiChildren().size() > 0) {
+ // There's already at least one child,
+ // so insert right before it.
+ Node xml_node = mUiNode.getUiChildren().get(0).getXmlNode();
+
+ if (xml_node instanceof IndexedRegion) {
+ IndexedRegion region = (IndexedRegion) xml_node;
+ sse_doc.replace(region.getStartOffset(), 0, data);
+ return; // we're done, no need to try the other cases
+ }
+ }
+
+ // If there's no first XML node child. Create one by
+ // inserting at the end of the *start* tag.
+ Node xml_node = mUiNode.getXmlNode();
+ if (xml_node instanceof NodeContainer) {
+ NodeContainer container = (NodeContainer) xml_node;
+ IStructuredDocumentRegion start_tag =
+ container.getStartStructuredDocumentRegion();
+ if (start_tag != null) {
+ sse_doc.replace(start_tag.getEndOffset(), 0, data);
+ return; // we're done, no need to try the other case
+ }
+ }
+ }
+
+ // This UI Node doesn't accept children. The new XML is inserted as the
+ // next sibling. This also serves as a fallback if all the previous
+ // attempts failed. However, this is not possible if the current node
+ // has for parent a document -- an XML document can only have one root,
+ // with no siblings.
+ if (!(mUiNode.getUiParent() instanceof UiDocumentNode)) {
+ Node xml_node = mUiNode.getXmlNode();
+ if (xml_node instanceof IndexedRegion) {
+ IndexedRegion region = (IndexedRegion) xml_node;
+ sse_doc.replace(region.getEndOffset(), 0, data);
+ }
}
}
- }
-
- // This UI Node doesn't accept children. The new XML is inserted as the
- // next sibling. This also serves as a fallback if all the previous
- // attempts failed. However, this is not possible if the current node
- // has for parent a document -- an XML document can only have one root,
- // with no siblings.
- if (!(mUiNode.getUiParent() instanceof UiDocumentNode)) {
- Node xml_node = mUiNode.getXmlNode();
- if (xml_node instanceof IndexedRegion) {
- IndexedRegion region = (IndexedRegion) xml_node;
- sse_doc.replace(region.getEndOffset(), 0, data);
- }
+
+ } catch (BadLocationException e) {
+ AdtPlugin.log(e,
+ "ParseAction failed for UI Node %2$s, content '%1$s'", //$NON-NLS-1$
+ mUiNode.getBreadcrumbTrailDescription(true), data);
}
}
-
- } catch (BadLocationException e) {
- AdtPlugin.log(e, "ParseAction failed for UI Node %2$s, content '%1$s'", //$NON-NLS-1$
- mUiNode.getBreadcrumbTrailDescription(true), data);
- } finally {
- model.releaseFromEdit();
- }
+ });
}
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiElementDetail.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiElementDetail.java
index 0e160b9..b0cd84a 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiElementDetail.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiElementDetail.java
@@ -73,13 +73,13 @@ class UiElementDetail implements IDetailsPage {
private IManagedForm mManagedForm;
private final UiTreeBlock mTree;
-
+
public UiElementDetail(UiTreeBlock tree) {
mTree = tree;
mMasterPart = mTree.getMasterPart();
mManagedForm = mMasterPart.getManagedForm();
}
-
+
/* (non-java doc)
* Initializes the part.
*/
@@ -117,25 +117,21 @@ class UiElementDetail implements IDetailsPage {
* Instructs it to commit the new (modified) data back into the model.
*/
public void commit(boolean onSave) {
-
- IStructuredModel model = mTree.getEditor().getModelForEdit();
- try {
- // Notify the model we're about to change data...
- model.aboutToChangeModel();
-
- if (mCurrentUiElementNode != null) {
- mCurrentUiElementNode.commit();
+
+ mTree.getEditor().wrapEditXmlModel(new Runnable() {
+ public void run() {
+ try {
+ if (mCurrentUiElementNode != null) {
+ mCurrentUiElementNode.commit();
+ }
+
+ // Finally reset the dirty flag if everything was saved properly
+ mIsDirty = false;
+ } catch (Exception e) {
+ AdtPlugin.log(e, "Detail node failed to commit XML attribute!"); //$NON-NLS-1$
+ }
}
-
- // Finally reset the dirty flag if everything was saved properly
- mIsDirty = false;
- } catch (Exception e) {
- AdtPlugin.log(e, "Detail node failed to commit XML attribute!"); //$NON-NLS-1$
- } finally {
- // Notify the model we're done modifying it. This must *always* be executed.
- model.changedModel();
- model.releaseFromEdit();
- }
+ });
}
public void dispose() {
@@ -183,7 +179,7 @@ class UiElementDetail implements IDetailsPage {
/**
* Creates a TableWrapLayout in the DetailsPage, which in turns contains a Section.
- *
+ *
* All the UI should be created in a layout which parent is the mSection itself.
* The hierarchy is:
* <pre>
@@ -194,7 +190,7 @@ class UiElementDetail implements IDetailsPage {
* + Labels/Forms/etc... [*]
* </pre>
* Both items marked with [*] are created by the derived classes to fit their needs.
- *
+ *
* @param parent Parent of the mSection (from createContents)
* @return The new Section
*/
@@ -215,7 +211,7 @@ class UiElementDetail implements IDetailsPage {
* <p/>
* This is called by the constructor.
* Derived classes can override this if necessary.
- *
+ *
* @param managedForm The managed form
*/
private void createUiAttributeControls(
@@ -258,7 +254,7 @@ class UiElementDetail implements IDetailsPage {
mCurrentTable = masterTable;
mCurrentUiElementNode = ui_node;
-
+
if (elem_desc.getTooltip() != null) {
String tooltip;
if (Sdk.getCurrent() != null &&
@@ -285,7 +281,7 @@ class UiElementDetail implements IDetailsPage {
"Malformed javadoc, rejected by FormText for node %1$s: '%2$s'", //$NON-NLS-1$
ui_node.getDescriptor().getXmlName(),
tooltip);
-
+
// Fallback to a pure text tooltip, no fancy HTML
tooltip = DescriptorsUtils.formatTooltip(elem_desc.getTooltip());
Label label = SectionHelper.createLabel(masterTable, toolkit,
@@ -294,7 +290,7 @@ class UiElementDetail implements IDetailsPage {
}
Composite table = useSubsections ? null : masterTable;
-
+
for (AttributeDescriptor attr_desc : attr_desc_list) {
if (attr_desc instanceof XmlnsAttributeDescriptor) {
// Do not show hidden attributes
@@ -318,7 +314,7 @@ class UiElementDetail implements IDetailsPage {
if (ui_attr != null) {
ui_attr.createUiControl(table, managedForm);
-
+
if (ui_attr.getCurrentValue() != null &&
ui_attr.getCurrentValue().length() > 0) {
((Section) table.getParent()).setExpanded(true);
@@ -339,7 +335,7 @@ class UiElementDetail implements IDetailsPage {
"Unknown XML Attributes");
unknownTable.getParent().setVisible(false); // set section to not visible
final HashSet<UiAttributeNode> reference = new HashSet<UiAttributeNode>();
-
+
final IUiUpdateListener updateListener = new IUiUpdateListener() {
public void uiElementNodeUpdated(UiElementNode ui_node, UiUpdateState state) {
if (state == UiUpdateState.ATTR_UPDATED) {
@@ -349,16 +345,16 @@ class UiElementDetail implements IDetailsPage {
}
};
ui_node.addUpdateListener(updateListener);
-
+
// remove the listener when the UI is disposed
unknownTable.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
ui_node.removeUpdateListener(updateListener);
}
});
-
+
updateUnknownAttributesSection(ui_node, unknownTable, managedForm, reference);
-
+
mMasterSection.getParent().pack(true /* changed */);
}
}
@@ -369,7 +365,7 @@ class UiElementDetail implements IDetailsPage {
*/
private Composite createSubSectionTable(FormToolkit toolkit,
Composite masterTable, String title) {
-
+
// The Section composite seems to ignore colspan when assigned a TableWrapData so
// if the parent is a table with more than one column an extra table with one column
// is inserted to respect colspan.
@@ -381,7 +377,7 @@ class UiElementDetail implements IDetailsPage {
twd.colspan = parentNumCol;
masterTable.setLayoutData(twd);
}
-
+
Composite table;
Section section = toolkit.createSection(masterTable,
Section.TITLE_BAR | Section.TWISTIE);
@@ -449,28 +445,28 @@ class UiElementDetail implements IDetailsPage {
if (has_differences) {
needs_reflow = true;
reference.clear();
-
+
// Remove all children of the table
for (Control c : unknownTable.getChildren()) {
c.dispose();
}
-
+
// Recreate all attributes UI
for (UiAttributeNode ui_attr : ui_attrs) {
reference.add(ui_attr);
ui_attr.createUiControl(unknownTable, managedForm);
-
+
if (ui_attr.getCurrentValue() != null && ui_attr.getCurrentValue().length() > 0) {
section.setExpanded(true);
}
}
}
-
+
if (needs_reflow) {
reflowMasterSection();
}
}
-
+
/**
* Marks the part dirty. Called as a result of user interaction with the widgets in the
* section.