Bug 350990 - Web Page Editor intolerably slow
diff --git a/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/HTMLEditor.java b/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/HTMLEditor.java
index d513d47..56306c8 100644
--- a/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/HTMLEditor.java
+++ b/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/HTMLEditor.java
@@ -43,6 +43,7 @@
 import org.eclipse.jst.pagedesigner.IJMTConstants;
 import org.eclipse.jst.pagedesigner.PDPlugin;
 import org.eclipse.jst.pagedesigner.dnd.internal.DesignerSourceMouseTrackAdapter;
+import org.eclipse.jst.pagedesigner.editors.actions.DesignPageActionContributor;
 import org.eclipse.jst.pagedesigner.editors.pagedesigner.PageDesignerResources;
 import org.eclipse.jst.pagedesigner.jsp.core.pagevar.IPageVariablesProvider;
 import org.eclipse.jst.pagedesigner.jsp.core.pagevar.adapter.IDocumentPageVariableAdapter;
@@ -75,10 +76,14 @@
 import org.eclipse.ui.part.MultiPageEditorPart;
 import org.eclipse.ui.part.MultiPageEditorSite;
 import org.eclipse.ui.part.MultiPageSelectionProvider;
+import org.eclipse.ui.texteditor.IDocumentProvider;
 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
 import org.eclipse.ui.views.properties.IPropertySheetPage;
 import org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
 import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
 import org.eclipse.wst.sse.ui.StructuredTextEditor;
 import org.eclipse.wst.sse.ui.internal.provisional.extensions.ISourceEditingTextTools;
 import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
@@ -153,6 +158,8 @@
 
 	private ISelectionChangedListener _selChangedListener;
 
+	private DesignPageActionContributor _designPageActionContributor;
+
     // TODO:This class is never used locally
 //	private class TextInputListener implements ITextInputListener {
 //		public void inputDocumentAboutToBeChanged(IDocument oldInput,
@@ -640,8 +647,10 @@
 				result = _textEditor.getAdapter(key);
 			}
 		} else if (key == IPageVariablesProvider.class) {
-			Object obj = ((IDOMModel) getModel()).getDocument().getAdapterFor(
+			IStructuredModel model = getModel();
+			Object obj = ((IDOMModel)model).getDocument().getAdapterFor(
 					IDocumentPageVariableAdapter.class);
+			model.releaseFromEdit();
 			if (obj instanceof IPageVariablesProvider) {
 				return obj;
 			}
@@ -706,7 +715,19 @@
 	public IStructuredModel getModel() {
 		IStructuredModel model = null;
 		if (_textEditor != null) {
-			model = ((DesignerStructuredTextEditorJSP) _textEditor).getModel();
+			IDocumentProvider documentProvider = _textEditor.getDocumentProvider();
+			if (documentProvider != null) {
+				IDocument document = documentProvider.getDocument(_textEditor.getEditorInput());
+				if (document instanceof IStructuredDocument) {
+					IModelManager modelManager =  StructuredModelManager.getModelManager();
+					if (modelManager != null) {
+						model = modelManager.getExistingModelForEdit(document);
+						if (model == null) {
+							model = modelManager.getModelForEdit((IStructuredDocument)document);
+						}
+					}
+				}
+			}
 		}
 		return model;
 	}
@@ -891,7 +912,6 @@
 		// TextViewer to set us straight
 		super.setInput(input);
 		if (_designViewer != null) {
-
 			_designViewer.setModel(getModel());
 		}
 		setPartName(input.getName());
@@ -1019,19 +1039,24 @@
 			// display it.
 			StringBuffer result = new StringBuffer();
 			try {
-				// PreviewHandler.generatePreview(this.getModel(),
-				// this.getEditorInput(), result);
+				//Bug 350990 - Web Page Editor intolerably slow
+				if (_mode == MODE_SOURCE) {
+					_designViewer.setModel(getModel());
+				}
 				DocumentEditPart part = (DocumentEditPart) this._designViewer
 						.getGraphicViewer().getContents();
 				PreviewHandlerNew.generatePreview(part, result);
+				//Bug 350990 - Web Page Editor intolerably slow
+				if (_mode == MODE_SOURCE) {
+					_designViewer.setModel(null);
+				}
 			} catch (Exception ex) {
 				result = new StringBuffer();
-				result
-						.append(this.getModel().getStructuredDocument()
-								.getText());
+				IStructuredModel model = getModel();
+				result.append(model.getStructuredDocument().getText());
+				model.releaseFromEdit();
 				// Error in page changing
 				_log.info("Error.HTMLEditor.6", ex); //$NON-NLS-1$
-				ex.printStackTrace();
 			}
 			File file = PreviewUtil.toFile(result, getEditorInput());
 			if (file != null) {
@@ -1054,7 +1079,7 @@
 	 * @param mode
 	 */
 	public void setDesignerMode(int mode) {
-		boolean requiresResynch = (_mode == MODE_SOURCE);
+		boolean modeWasSourceOnly = (_mode == MODE_SOURCE);
 		if (_sashEditorPart != null && _mode != mode) {
 			switch (mode) {
 			case MODE_SASH_HORIZONTAL:
@@ -1065,6 +1090,11 @@
 				break;
 			case MODE_SOURCE:
 				_sashEditorPart.setMaximizedEditor(this._textEditor);
+				//Bug 350990 - Web Page Editor intolerably slow
+				_designViewer.setModel(null);
+				if (_designPageActionContributor != null) {
+					_designPageActionContributor.disableRangeModeActions();
+				}
 				break;
 			case MODE_SASH_VERTICAL:
 			default:
@@ -1075,11 +1105,22 @@
 			}
 		}
 		this._mode = mode;
-		if (requiresResynch) {
+		if (modeWasSourceOnly) {
+			//Bug 350990 - Web Page Editor intolerably slow
+			_designViewer.setModel(getModel());
 			resynch();
 		}
 	}
 
+	/**
+	 * Sets the current DesignPageActionContributor instance.
+	 * @param designPageActionContributor Current DesignPageActionContributor instance.
+	 */
+	public void setDesignPageActionContributor(
+			final DesignPageActionContributor designPageActionContributor) {
+		_designPageActionContributor = designPageActionContributor;
+	}
+
 	/*
 	 * Set the sash editor mode from the stored file property
 	 * or the default preference.
diff --git a/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/SimpleGraphicalEditor.java b/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/SimpleGraphicalEditor.java
index 885bb4f..a013094 100644
--- a/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/SimpleGraphicalEditor.java
+++ b/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/SimpleGraphicalEditor.java
@@ -184,6 +184,7 @@
 	public void dispose() {
 		if (_model != null) {
 			_model.getUndoManager().disconnect(this);
+			_model.releaseFromEdit();
 		}
 
 		_paletteViewerPage = null;
@@ -385,6 +386,14 @@
         return false;
 	}
 
+	/**
+	 * Returns <code>true</code> if the current model is valid.
+	 * @return <code>true</code> if the current model is valid, else <code>false</code>.
+	 */
+	public boolean isModelValid() {
+		return _model != null;
+	}
+
 	/*
 	 * (non-Javadoc)
 	 * 
@@ -395,6 +404,7 @@
 			if (_model.getUndoManager() != null)
 				_model.getUndoManager().disconnect(this);
 			_model.removeModelStateListener(_internalModelListener);
+			_model.releaseFromEdit();
 		}
 
 		this._model = model;
diff --git a/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/actions/DesignPageActionContributor.java b/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/actions/DesignPageActionContributor.java
index 09989f2..2f59528 100644
--- a/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/actions/DesignPageActionContributor.java
+++ b/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/actions/DesignPageActionContributor.java
@@ -51,6 +51,12 @@
 
 	private IEditorPart _editorPart;
 
+	private DesignerToolBarAction uAction = null;
+	private DesignerToolBarAction bAction = null;
+	private DesignerToolBarAction iAction = null;
+	private DesignerToolBarAction smallAction = null;
+	private DesignerToolBarAction bigAction = null;
+
 	/**
 	 * @param manager
 	 * @param id
@@ -81,20 +87,20 @@
 	private void initToolbar(IToolBarManager toolbar) {
 		DesignActionBarFactory factory = DesignActionBarFactory.getInstance();
 
-		Action action = factory.getStyleAction(IHTMLConstants.TAG_U);
-		toolbar.add(action);
+		uAction = factory.getStyleAction(IHTMLConstants.TAG_U);
+		toolbar.add(uAction);
 
-		action = factory.getStyleAction(IHTMLConstants.TAG_B);
-		toolbar.add(action);
+		bAction = factory.getStyleAction(IHTMLConstants.TAG_B);
+		toolbar.add(bAction);
 
-		action = factory.getStyleAction(IHTMLConstants.TAG_I);
-		toolbar.add(action);
+		iAction = factory.getStyleAction(IHTMLConstants.TAG_I);
+		toolbar.add(iAction);
 
-		action = factory.getStyleAction(IHTMLConstants.TAG_SMALL);
-		toolbar.add(action);
+		smallAction = factory.getStyleAction(IHTMLConstants.TAG_SMALL);
+		toolbar.add(smallAction);
 
-		action = factory.getStyleAction(IHTMLConstants.TAG_BIG);
-		toolbar.add(action);
+		bigAction = factory.getStyleAction(IHTMLConstants.TAG_BIG);
+		toolbar.add(bigAction);
 		// action = factory.getStyleAction(PARAGRAPH_ACTION_ID);
 		// toolbar.add(action);
 	}
@@ -212,20 +218,36 @@
 	}
 
 	private void setViewerOnActions(IHTMLGraphicalViewer viewer) {
-		IContributionItem[] items = getActionBars().getToolBarManager()
-				.getItems();
+		final IContributionItem[] items = getActionBars().getToolBarManager().getItems();
 		if (items != null) {
 			for (int i = 0; i < items.length; i++) {
-				if (items[i] instanceof ActionContributionItem) {
-					IAction action = ((ActionContributionItem) items[i])
-							.getAction();
+				final IContributionItem item = items[i]; 
+				if (item instanceof ActionContributionItem) {
+					final IAction action = ((ActionContributionItem) item).getAction();
 					if (action instanceof DesignerToolBarAction) {
 						((DesignerToolBarAction) action).setViewer(viewer);
 					}
 				}
 			}
 		}
+		//under e4, contributions are not as expected, so we need to take extra steps
+		uAction.setViewer(viewer);
+		bAction.setViewer(viewer);
+		iAction.setViewer(viewer);
+		smallAction.setViewer(viewer);
+		bigAction.setViewer(viewer);
+	}
 
+	/**
+	 * Disables actions that work on a range (which is not possible while the graphical viewer is
+	 * hidden).
+	 */
+	public void disableRangeModeActions() {
+		uAction.setEnabled(false);
+		bAction.setEnabled(false);
+		iAction.setEnabled(false);
+		smallAction.setEnabled(false);
+		bigAction.setEnabled(false);
 	}
 
 	/**
diff --git a/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/actions/PageDesignerActionBarContributor2.java b/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/actions/PageDesignerActionBarContributor2.java
index b081c16..3b272ec 100644
--- a/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/actions/PageDesignerActionBarContributor2.java
+++ b/jsf/plugins/org.eclipse.jst.pagedesigner/src/org/eclipse/jst/pagedesigner/editors/actions/PageDesignerActionBarContributor2.java
@@ -196,6 +196,7 @@
 	public void setActiveEditor(IEditorPart targetEditor) {
 		if (targetEditor instanceof HTMLEditor) {
 			_htmlEditor = (HTMLEditor) targetEditor;
+			_htmlEditor.setDesignPageActionContributor(_designViewerActionBarContributor);
 			//StructuredTextEditor textEditor = _htmlEditor.getTextEditor();
 			// TODO: never read this._model = textEditor.getModel();
 		}