RESOLVED - bug 287073: [modeling] Generic source page for EMF Forms Editor
https://bugs.eclipse.org/bugs/show_bug.cgi?id=287073
diff --git a/modeling/plugins/org.eclipse.pde.emfforms/META-INF/MANIFEST.MF b/modeling/plugins/org.eclipse.pde.emfforms/META-INF/MANIFEST.MF
index b91033a..64bc3ab 100644
--- a/modeling/plugins/org.eclipse.pde.emfforms/META-INF/MANIFEST.MF
+++ b/modeling/plugins/org.eclipse.pde.emfforms/META-INF/MANIFEST.MF
@@ -12,11 +12,12 @@
  org.eclipse.emf.edit.ui;bundle-version="2.4.0",
  org.eclipse.ui.ide;bundle-version="3.4.0",
  org.eclipse.jface.databinding;bundle-version="1.2.0",
-  org.eclipse.wst.sse.core;bundle-version="1.1.300";resolution:=optional,
+ org.eclipse.wst.sse.core;bundle-version="1.1.300";resolution:=optional,
  org.eclipse.wst.sse.ui;bundle-version="1.1.0";resolution:=optional,
  org.eclipse.wst.xml.core;bundle-version="1.1.300";resolution:=optional,
  org.eclipse.wst.xml.ui;bundle-version="1.0.400";resolution:=optional,
- org.eclipse.jface.text;bundle-version="3.4.0"
+ org.eclipse.jface.text;bundle-version="3.4.0",
+ org.eclipse.ui.editors;bundle-version="3.4.0"
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
 Bundle-Localization: plugin
 Bundle-ActivationPolicy: lazy
diff --git a/modeling/plugins/org.eclipse.pde.emfforms/src/org/eclipse/pde/emfforms/editor/DefaultEmfFormEditorConfig.java b/modeling/plugins/org.eclipse.pde.emfforms/src/org/eclipse/pde/emfforms/editor/DefaultEmfFormEditorConfig.java
index 4b01578..0e13d14 100644
--- a/modeling/plugins/org.eclipse.pde.emfforms/src/org/eclipse/pde/emfforms/editor/DefaultEmfFormEditorConfig.java
+++ b/modeling/plugins/org.eclipse.pde.emfforms/src/org/eclipse/pde/emfforms/editor/DefaultEmfFormEditorConfig.java
@@ -8,7 +8,7 @@
  * Contributors:
  *     Anyware Technologies - initial API and implementation
  *
- * $Id: DefaultEmfFormEditorConfig.java,v 1.1 2009/04/24 11:52:09 bcabe Exp $
+ * $Id: DefaultEmfFormEditorConfig.java,v 1.2 2009/07/05 20:22:09 bcabe Exp $
  */
 package org.eclipse.pde.emfforms.editor;
 
@@ -33,6 +33,10 @@
 		return true;
 	}
 
+	public boolean isShowSourcePage() {
+		return true;
+	}
+
 	public PDEFormToolkit createPDEFormToolkit(Display display) {
 		if (this.customizedToolkit != null) {
 			return this.customizedToolkit;
diff --git a/modeling/plugins/org.eclipse.pde.emfforms/src/org/eclipse/pde/emfforms/editor/EmfFormEditor.java b/modeling/plugins/org.eclipse.pde.emfforms/src/org/eclipse/pde/emfforms/editor/EmfFormEditor.java
index 4b54b11..156d361 100644
--- a/modeling/plugins/org.eclipse.pde.emfforms/src/org/eclipse/pde/emfforms/editor/EmfFormEditor.java
+++ b/modeling/plugins/org.eclipse.pde.emfforms/src/org/eclipse/pde/emfforms/editor/EmfFormEditor.java
@@ -8,7 +8,7 @@
  * Contributors:
  *     Anyware Technologies - initial API and implementation
  *
- * $Id: EmfFormEditor.java,v 1.17 2009/08/07 16:25:33 bcabe Exp $
+ * $Id: EmfFormEditor.java,v 1.18 2009/08/18 08:00:37 bcabe Exp $
  */
 package org.eclipse.pde.emfforms.editor;
 
@@ -50,7 +50,7 @@
 import org.eclipse.jface.window.Window;
 import org.eclipse.pde.emfforms.editor.IEmfFormEditorConfig.VALIDATE_ON_SAVE;
 import org.eclipse.pde.emfforms.internal.Activator;
-import org.eclipse.pde.emfforms.internal.editor.Messages;
+import org.eclipse.pde.emfforms.internal.editor.*;
 import org.eclipse.pde.emfforms.internal.validation.ValidatingEContentAdapter;
 import org.eclipse.swt.dnd.DND;
 import org.eclipse.swt.dnd.Transfer;
@@ -67,6 +67,8 @@
 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
 import org.eclipse.ui.views.properties.IPropertySheetPage;
 import org.eclipse.ui.views.properties.PropertySheetPage;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
 
 /**
  * A {@link FormEditor} allowing to edit an EMF {@link EObject} in a convenient
@@ -212,11 +214,32 @@
 			for (Image img : getPagesImages())
 				setPageImage(i++, img);
 
+			addSourcePage();
 		} catch (PartInitException e) {
 			Activator.logException(e, Messages.EmfFormEditor_InitError);
 		}
 	}
 
+	private void addSourcePage() throws PartInitException {
+		if (!_editorConfig.isShowSourcePage())
+			return;
+
+		boolean isXmlUiBundlePresent = false;
+		BundleContext bc = Activator.getDefault().getBundle().getBundleContext();
+		for (Bundle b : bc.getBundles()) {
+			if ("org.eclipse.wst.xml.ui".equals(b.getSymbolicName())) { //$NON-NLS-1$
+				isXmlUiBundlePresent = true;
+				break;
+			}
+		}
+
+		if (isXmlUiBundlePresent)
+			addPage(new XmlSourcePage(this));
+		else
+			addPage(new SimpleSourcePage(this));
+
+	}
+
 	/**
 	 * @throws PartInitException
 	 */
diff --git a/modeling/plugins/org.eclipse.pde.emfforms/src/org/eclipse/pde/emfforms/editor/IEmfFormEditorConfig.java b/modeling/plugins/org.eclipse.pde.emfforms/src/org/eclipse/pde/emfforms/editor/IEmfFormEditorConfig.java
index 5ae44b9..c50d71f 100644
--- a/modeling/plugins/org.eclipse.pde.emfforms/src/org/eclipse/pde/emfforms/editor/IEmfFormEditorConfig.java
+++ b/modeling/plugins/org.eclipse.pde.emfforms/src/org/eclipse/pde/emfforms/editor/IEmfFormEditorConfig.java
@@ -8,7 +8,7 @@
  * Contributors:
  *     Anyware Technologies - initial API and implementation
  *
- * $Id: IEmfFormEditorConfig.java,v 1.1 2009/04/24 11:52:09 bcabe Exp $
+ * $Id: IEmfFormEditorConfig.java,v 1.2 2009/07/05 20:22:09 bcabe Exp $
  */
 package org.eclipse.pde.emfforms.editor;
 
@@ -28,6 +28,8 @@
 
 	public abstract boolean isShowOutlinePage();
 
+	public abstract boolean isShowSourcePage();
+
 	/**
 	 * 
 	 * @param display
diff --git a/modeling/plugins/org.eclipse.pde.emfforms/src/org/eclipse/pde/emfforms/internal/editor/AbstractSourcePage.java b/modeling/plugins/org.eclipse.pde.emfforms/src/org/eclipse/pde/emfforms/internal/editor/AbstractSourcePage.java
new file mode 100644
index 0000000..22fde00
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.emfforms/src/org/eclipse/pde/emfforms/internal/editor/AbstractSourcePage.java
@@ -0,0 +1,118 @@
+/**
+ * Copyright (c) 2009 Anyware Technologies and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Anyware Technologies - initial API and implementation
+ *
+ * $Id: Messages.java,v 1.2 2009/02/13 10:24:39 bcabe Exp $
+ */
+package org.eclipse.pde.emfforms.internal.editor;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.Collections;
+import java.util.EventObject;
+import org.eclipse.core.databinding.DataBindingContext;
+import org.eclipse.core.databinding.observable.value.IObservableValue;
+import org.eclipse.emf.common.command.CommandStackListener;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.xmi.XMLResource;
+import org.eclipse.emf.edit.domain.EditingDomain;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.pde.emfforms.editor.AbstractEmfFormPage;
+import org.eclipse.pde.emfforms.editor.EmfFormEditor;
+import org.eclipse.pde.emfforms.internal.Activator;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+
+public abstract class AbstractSourcePage extends AbstractEmfFormPage {
+	private SourceViewer _sourceViewer;
+
+	public static final String ID = "emfforms.source"; //$NON-NLS-1$
+
+	protected static final int VERTICAL_RULER_WIDTH = 12;
+
+	private EditingDomain _editingDomain;
+	private CommandStackListener _commandStackListener;
+
+	/**
+	 * @param editor
+	 */
+	public AbstractSourcePage(EmfFormEditor<?> editor) {
+		super(editor);
+	}
+
+	public void bind(DataBindingContext bindingContext) {
+		_editingDomain = ((EmfFormEditor<?>) getEditor()).getEditingDomain();
+
+		_commandStackListener = new CommandStackListener() {
+			public void commandStackChanged(EventObject event) {
+				refreshSourceContent();
+			}
+		};
+		_editingDomain.getCommandStack().addCommandStackListener(_commandStackListener);
+
+		// initialize content
+		refreshSourceContent();
+	}
+
+	private void refreshSourceContent() {
+		EObject obj = (EObject) getObservedValue().getValue();
+
+		// Copies the root to avoid modifying it
+		final StringWriter writer = new StringWriter();
+		try {
+			((XMLResource) obj.eResource()).save(writer, Collections.EMPTY_MAP);
+		} catch (IOException e) {
+			Activator.log(e);
+		}
+		final String result = writer.toString();
+		writer.flush();
+		if (_sourceViewer != null)
+			_sourceViewer.getDocument().set(result);
+	}
+
+	public void createContents(Composite parent) {
+		GridLayout gl = new GridLayout(getNumColumns(), true);
+		gl.verticalSpacing = 0;
+		parent.setLayout(gl);
+
+		_sourceViewer = createSourceViewer(parent);
+
+		GridDataFactory.fillDefaults().grab(true, true).applyTo(_sourceViewer.getControl());
+	}
+
+	public abstract SourceViewer createSourceViewer(Composite parent);
+
+	@Override
+	public String getId() {
+		return ID;
+	}
+
+	@Override
+	public String getPartName() {
+		return "Source"; //$NON-NLS-1$
+	}
+
+	@Override
+	public Viewer getViewer() {
+		return null;
+	}
+
+	private IObservableValue getObservedValue() {
+		return ((EmfFormEditor<?>) getEditor()).getInputObservable();
+	}
+
+	@Override
+	public void dispose() {
+		_editingDomain.getCommandStack().removeCommandStackListener(_commandStackListener);
+
+		super.dispose();
+	}
+}
diff --git a/modeling/plugins/org.eclipse.pde.emfforms/src/org/eclipse/pde/emfforms/internal/editor/SimpleSourcePage.java b/modeling/plugins/org.eclipse.pde.emfforms/src/org/eclipse/pde/emfforms/internal/editor/SimpleSourcePage.java
new file mode 100644
index 0000000..5a15562
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.emfforms/src/org/eclipse/pde/emfforms/internal/editor/SimpleSourcePage.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2009 Anyware Technologies and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Anyware Technologies - initial API and implementation
+ *
+ * $Id: Messages.java,v 1.2 2009/02/13 10:24:39 bcabe Exp $
+ */
+package org.eclipse.pde.emfforms.internal.editor;
+
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.text.source.VerticalRuler;
+import org.eclipse.pde.emfforms.editor.EmfFormEditor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.editors.text.TextSourceViewerConfiguration;
+
+public class SimpleSourcePage extends AbstractSourcePage {
+
+	public SimpleSourcePage(EmfFormEditor<?> editor) {
+		super(editor);
+	}
+
+	@Override
+	public SourceViewer createSourceViewer(Composite parent) {
+		SourceViewer sourceViewer = new SourceViewer(parent, new VerticalRuler(VERTICAL_RULER_WIDTH), SWT.V_SCROLL | SWT.WRAP);
+
+		sourceViewer.getTextWidget().setFont(JFaceResources.getTextFont());
+
+		sourceViewer.configure(new TextSourceViewerConfiguration());
+		sourceViewer.setDocument(new Document());
+		sourceViewer.setEditable(false);
+
+		return sourceViewer;
+	}
+
+}
diff --git a/modeling/plugins/org.eclipse.pde.emfforms/src/org/eclipse/pde/emfforms/internal/editor/XmlSourcePage.java b/modeling/plugins/org.eclipse.pde.emfforms/src/org/eclipse/pde/emfforms/internal/editor/XmlSourcePage.java
new file mode 100644
index 0000000..04987f0
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.emfforms/src/org/eclipse/pde/emfforms/internal/editor/XmlSourcePage.java
@@ -0,0 +1,55 @@
+/**
+ * Copyright (c) 2009 Anyware Technologies and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Anyware Technologies - initial API and implementation
+ *
+ * $Id: Messages.java,v 1.2 2009/02/13 10:24:39 bcabe Exp $
+ */
+package org.eclipse.pde.emfforms.internal.editor;
+
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.source.*;
+import org.eclipse.pde.emfforms.editor.EmfFormEditor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.ui.internal.StructuredTextViewer;
+import org.eclipse.wst.xml.ui.StructuredTextViewerConfigurationXML;
+
+@SuppressWarnings("restriction")
+public class XmlSourcePage extends AbstractSourcePage {
+
+	public XmlSourcePage(EmfFormEditor<?> editor) {
+		super(editor);
+	}
+
+	@Override
+	public SourceViewer createSourceViewer(Composite parent) {
+		StructuredTextViewer sourceViewer = new org.eclipse.wst.sse.ui.internal.StructuredTextViewer(parent, new VerticalRuler(VERTICAL_RULER_WIDTH), null, false, SWT.V_SCROLL | SWT.WRAP);
+
+		sourceViewer.getTextWidget().setFont(JFaceResources.getFont("org.eclipse.wst.sse.ui.textfont")); //$NON-NLS-1$
+		IStructuredDocument document = StructuredModelManager.getModelManager().createStructuredDocumentFor("org.eclipse.core.runtime.xml"); //$NON-NLS-1$
+
+		SourceViewerConfiguration sourceViewerConfiguration = new StructuredTextViewerConfigurationXML() {
+			@Override
+			public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
+				return super.getContentAssistant(sourceViewer);
+			}
+		};
+
+		// sourceViewerConfiguration.getContentFormatter(_sourceStructuredTextViewer).format(document, new Region(0, document.getLength()));
+		sourceViewer.configure(sourceViewerConfiguration);
+		sourceViewer.setDocument(document);
+		sourceViewer.setEditable(false);
+
+		return sourceViewer;
+	}
+
+}