/*******************************************************************************
* Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Exadel, Inc. and Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.model.ui.texteditors;
import java.util.ResourceBundle;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextListener;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.TextEvent;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.texteditor.IAbstractTextEditorHelpContextIds;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.IDocumentProviderExtension;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.texteditor.ITextEditorActionConstants;
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
import org.eclipse.ui.texteditor.ResourceAction;
import org.eclipse.ui.texteditor.RevertToSavedAction;
import org.eclipse.ui.texteditor.SaveAction;
import org.jboss.tools.common.editor.ObjectTextEditor;
import org.jboss.tools.common.model.XModelObject;
import org.jboss.tools.common.model.ui.ModelUIPlugin;
import org.jboss.tools.common.model.ui.editor.IModelObjectEditorInput;
import org.jboss.tools.common.model.ui.texteditors.propertyeditor.PropertiesTextEditorStub;
import org.jboss.tools.common.propertieseditor.PropertiesCompoundEditor;
import org.jboss.tools.common.propertieseditor.text.PropertyTextEditorSupport;
/**
* @author Jeremy
*
*/
public class PropertiesTextEditorComponent extends PropertiesTextEditorStub implements ITextListener, ITextProvider, ObjectTextEditor {
protected TextEditorSupport support = createSupport();
protected boolean isObjectNull = false;
public void createPartControl(Composite parent) {
super.createPartControl(parent);
dnd.enable();
setModified(false);
getSourceViewer().getDocument().addDocumentListener(this);
}
public PropertiesTextEditorComponent() {
support.setProvider(this);
}
protected TextEditorSupport createSupport() {
return new PropertyTextEditorSupport();
}
public TextEditorSupport getSupport() {
return support;
}
public void setObject(XModelObject object) {
isObjectNull = (object == null);
if(isObjectNull) return;
getSourceViewer().getDocument().removeDocumentListener(this);
support.setObject(object);
getSourceViewer().getDocument().addDocumentListener(this);
}
public void updateDocument() {
support.update();
}
public void dispose() {
super.dispose();
}
public boolean isDirty() {
return (isObjectNull) ? super.isDirty() : false;
}
public String getText() {
String text = null;
if(getSourceViewer() == null) return null;
if(getSourceViewer().getDocument() == null) return null;
text = getSourceViewer().getDocument().get();
return (text == null) ? "" : text; //$NON-NLS-1$
}
public boolean isEditable() {
return !isEditorInputReadOnly();
}
public boolean isEditorInputReadOnly() {
if(!(getEditorInput() instanceof IModelObjectEditorInput)) return super.isEditorInputReadOnly();
IModelObjectEditorInput input = (IModelObjectEditorInput)getEditorInput();
return input != null && input.getXModelObject() != null && !input.getXModelObject().isObjectEditable();
}
public void setModified(boolean set) {
if(set == support.isModified()) return;
support.setModified(set);
firePropertyChange(IEditorPart.PROP_DIRTY);
}
public boolean isModified() {
return support.isModified();
}
protected void doSetInput(IEditorInput input) throws CoreException {
super.doSetInput(input);
if(getSourceViewer() != null && getSourceViewer().getDocument() != null) {
getSourceViewer().getDocument().removeDocumentListener(this);
getSourceViewer().getDocument().addDocumentListener(this);
}
}
public void save() {
if(!isObjectNull && !support.canSave(false)) return;
if(isObjectNull) super.doSave(null); else support.save();
}
public void addFocusListener(FocusListener listener) {
getSourceViewer().getTextWidget().addFocusListener(listener);
}
public void removeFocusListener(FocusListener listener) {
getSourceViewer().getTextWidget().removeFocusListener(listener);
}
public void setCursor(int line, int position) {
ISourceViewer sv = getSourceViewer();
if(sv == null) return;
IDocument d = sv.getDocument();
if(d == null) return;
try {
int i = d.getLineOffset(line - 1) + position - 1;
sv.setSelectedRange(i, 0);
} catch (BadLocationException e) {
ModelUIPlugin.getPluginLog().logError(e);
}
}
public void doSaveAs() {}
public void doSave(IProgressMonitor monitor){
if(isObjectNull) super.doSave(monitor);
}
private boolean textChangedLock = false;
public void textChanged(TextEvent event) {
if(textChangedLock) {
firePropertyChange(IEditorPart.PROP_DIRTY);
} else {
setModified(true);
}
}
public void setText(String text) {
textChangedLock = true;
try {
if(getSourceViewer() == null || getSourceViewer().getDocument() == null) return;
String txt = getSourceViewer().getDocument().get();
if(txt != null && txt.length() > 0) {
if(!TextMerge.replace(getSourceViewer().getDocument(), text)) {
getSourceViewer().getDocument().set(text);
}
} else {
getSourceViewer().getDocument().set(text);
}
} finally {
textChangedLock = false;
}
}
public boolean isEqualText(String text) {
return (getSourceViewer().getDocument() != null && text.equals(getText()));
}
public void doSanityCheckState(IEditorInput input) {
super.safelySanityCheckState(input);
if(isObjectNull) return;
Display.getDefault().syncExec(
new Runnable() {
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
//ignore
}
support.save();
}
}
);
}
public void doRevertToSaved() {
support.save();
support.revertToSaved();
}
protected void createActions() {
super.createActions();
ResourceAction action = new RevertToSavedAction3(this);
action.setHelpContextId(IAbstractTextEditorHelpContextIds.REVERT_TO_SAVED_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.REVERT_TO_SAVED);
setAction(ITextEditorActionConstants.REVERT_TO_SAVED, action);
action = new SaveAction3(this);
action.setHelpContextId(IAbstractTextEditorHelpContextIds.SAVE_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.SAVE);
setAction(ITextEditorActionConstants.SAVE, action);
markAsPropertyDependentAction(ITextEditorActionConstants.SAVE, true);
}
public void selectModelObject(XModelObject object) {
String text = getText();
String name = object.getAttributeValue("name"); //$NON-NLS-1$
String dname = object.getAttributeValue("dirtyname"); //$NON-NLS-1$
String nvs = object.getAttributeValue("name-value-separator"); //$NON-NLS-1$
int i = text.indexOf(dname + nvs);
if(i < 0) return;
i = text.indexOf(name, i);
int j = text.indexOf('\n', i);
if(j < 0) j = text.length();
selectAndReveal(i, j - i);
}
public void selectModelObject(XModelObject object, String attribute) {
selectModelObject(object);
}
protected void handleEditorInputChanged() {
final IDocumentProvider provider= getDocumentProvider();
if (provider == null) {
// fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=15066
close(false);
return;
}
final IEditorInput input= getEditorInput();
if (provider.isDeleted(input)) {
if (isSaveAsAllowed()) {
if (true) {
IProgressMonitor pm= getProgressMonitor();
performSaveAs(pm);
if (pm.isCanceled())
handleEditorInputChanged();
} else {
close(false);
}
} else {
if (true) close(false);
}
} else {
if (true) {
try {
if (provider instanceof IDocumentProviderExtension) {
IDocumentProviderExtension extension= (IDocumentProviderExtension) provider;
extension.synchronize(input);
} else {
doSetInput(input);
}
} catch (CoreException x) {
ModelUIPlugin.getPluginLog().logError(x);
}
}
}
}
public void documentAboutToBeChanged(DocumentEvent event) {}
public void documentChanged(DocumentEvent event) {
textChanged(null);
}
public void updateModification() {
XModelObject object = support.getModelObject();
if(object != null && !object.isModified() && support.isModified()) {
//external update
setModified(false);
} else {
firePropertyChange(ITextEditor.PROP_DIRTY);
}
}
public XModelObject findModelObjectAtCursor() {
XModelObject o = getModelObject();
if(!PropertiesCompoundEditor.isPropertiesFile(o)) return null;
ISelection selection = getSelectionProvider().getSelection();
if(!(selection instanceof ITextSelection)) return null;
int offset = ((ITextSelection)selection).getOffset();
IDocument doc = getDocumentProvider().getDocument(getEditorInput());
try {
int line = doc.getLineOfOffset(offset);
int lineStart = doc.getLineOffset(line);
int length = doc.getLineLength(line);
String txt = doc.get(lineStart, length);
XModelObject[] cs = o.getChildren();
String trimmed = txt.trim();
for (int i = 0; i < cs.length; i++) {
String n = cs[i].getAttributeValue("name"); //$NON-NLS-1$
if(!trimmed.startsWith(n)) continue;
String sep = cs[i].getAttributeValue("name-value-separator"); //$NON-NLS-1$
if(sep == null || sep.length() == 0) sep = "="; //$NON-NLS-1$
int q = trimmed.indexOf('=');
if(q < 0) continue;
String s = trimmed.substring(n.length(), q).trim();
if(s.length() > 0) continue;
return cs[i];
}
} catch (BadLocationException e) {
e.printStackTrace();
}
return null;
}
}
class RevertToSavedAction3 extends RevertToSavedAction {
PropertiesTextEditorComponent t;
RevertToSavedAction3(PropertiesTextEditorComponent t) {
super(ResourceBundle.getBundle("org.eclipse.ui.texteditor.ConstructedEditorMessages"), "Editor.Revert.", t); //$NON-NLS-1$ //$NON-NLS-2$
this.t = t;
}
public void update() {
setEnabled(t != null && t.support != null && (t.support.canRevertToSaved() || t.isModified()));
}
}
class SaveAction3 extends SaveAction {
PropertiesTextEditorComponent t;
SaveAction3(PropertiesTextEditorComponent t) {
super(ResourceBundle.getBundle("org.eclipse.ui.texteditor.ConstructedEditorMessages"), "Editor.Save.", t); //$NON-NLS-1$ //$NON-NLS-2$
this.t = t;
}
public void update() {
XModelObject o = (t == null) ? null : t.getModelObject();
setEnabled(o != null && o.isModified());
}
public void run() {
IEditorPart p = getTextEditor().getSite().getPage().findEditor(t.getEditorInput());
if(p != null) getTextEditor().getSite().getPage().saveEditor(p, false);
}
}