package org.objectstyle.wolips.templateeditor;
import jp.aonir.fuzzyxml.FuzzyXMLDocument;
import jp.aonir.fuzzyxml.FuzzyXMLElement;
import jp.aonir.fuzzyxml.FuzzyXMLParser;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
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.text.source.IVerticalRuler;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.Saveable;
import org.eclipse.ui.texteditor.AbstractTextEditor;
import org.eclipse.ui.texteditor.AnnotationPreferenceLookup;
import org.eclipse.ui.texteditor.MarkerAnnotationPreferences;
import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
import org.objectstyle.wolips.bindings.wod.IWodElement;
import org.objectstyle.wolips.components.editor.ComponentEditorInteraction;
import org.objectstyle.wolips.components.editor.IEmbeddedEditor;
import org.objectstyle.wolips.locate.LocateException;
import org.objectstyle.wolips.variables.BuildProperties;
import org.objectstyle.wolips.wodclipse.core.Activator;
import org.objectstyle.wolips.wodclipse.core.completion.WodParserCache;
import org.objectstyle.wolips.wodclipse.core.document.ITextWOEditor;
import org.objectstyle.wolips.wodclipse.core.refactoring.DeleteTagRefactoring;
import org.objectstyle.wolips.wodclipse.core.util.WodHtmlUtils;
import tk.eclipse.plugin.htmleditor.HTMLPlugin;
import tk.eclipse.plugin.htmleditor.editors.HTMLConfiguration;
import tk.eclipse.plugin.htmleditor.editors.HTMLSourceEditor;
import tk.eclipse.plugin.htmleditor.editors.IHTMLOutlinePage;
public class TemplateSourceEditor extends HTMLSourceEditor implements ITextWOEditor, IEmbeddedEditor {
public static final String ACTION_DELETE_TAG = "_template_deleteTag";
public static final String ACTION_UNWRAP_TAG = "_template_unwrapTag";
private TemplateOutlinePage _templateOutlinePage;
private WodParserCache _cache;
private TemplateBreadcrumb _breadcrumb;
private boolean _cacheOutOfSync;
private ComponentEditorInteraction _editorInteraction;
public TemplateSourceEditor(HTMLConfiguration config) {
super(config);
setAction(TemplateSourceEditor.ACTION_DELETE_TAG, new DeleteTagAction());
setAction(TemplateSourceEditor.ACTION_UNWRAP_TAG, new UnwrapTagAction());
}
public void initEditorInteraction(ComponentEditorInteraction editorInteraction) {
_editorInteraction = editorInteraction;
}
public ComponentEditorInteraction getEditorInteraction() {
return _editorInteraction;
}
@Override
public void doSave(IProgressMonitor monitor) {
if (_editorInteraction == null || _editorInteraction.embeddedEditorWillSave(monitor)) {
super.doSave(monitor);
}
}
@Override
protected void initializeKeyBindingScopes() {
setKeyBindingScopes(new String[] { "org.objectstyle.wolips.componenteditor.componentEditorScope" }); //$NON-NLS-1$
}
@Override
protected void doSetInput(IEditorInput input) throws CoreException {
super.doSetInput(input);
_cache = null;
}
@Override
public MarkerAnnotationPreferences getAnnotationPreferences() {
return super.getAnnotationPreferences();
}
@Override
public AnnotationPreferenceLookup getAnnotationPreferenceLookup() {
return super.getAnnotationPreferenceLookup();
}
@Override
public void createPartControl(Composite parent) {
Composite templateParent = new Composite(parent, SWT.NONE);
GridLayout templateLayout = new GridLayout();
templateLayout.marginTop = 0;
templateLayout.marginLeft = 0;
templateLayout.marginBottom = 0;
templateLayout.marginRight = 0;
templateLayout.marginHeight = 0;
templateLayout.marginWidth = 0;
templateLayout.verticalSpacing = 0;
templateLayout.horizontalSpacing = 0;
templateParent.setLayout(templateLayout);
Composite editorParent = new Composite(templateParent, SWT.NONE);
editorParent.setLayoutData(new GridData(GridData.FILL_BOTH));
FillLayout editorLayout = new FillLayout();
editorLayout.marginHeight = 0;
editorLayout.marginWidth = 0;
editorParent.setLayout(editorLayout);
super.createPartControl(editorParent);
_breadcrumb = new TemplateBreadcrumb(this, templateParent, SWT.NONE);
_breadcrumb.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
getViewer().addTextListener(new ITextListener() {
public void textChanged(TextEvent event) {
setCacheOutOfSync(true);
}
});
}
@Override
protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
return super.createSourceViewer(parent, ruler, styles);
}
protected void setCacheOutOfSync(boolean cacheOutOfSync) {
_cacheOutOfSync = cacheOutOfSync;
}
@Override
protected void handleCursorPositionChanged() {
super.handleCursorPositionChanged();
}
public Point getSelectedRange() {
return getSourceViewer().getSelectedRange();
}
@Override
public void dispose() {
try {
WodParserCache cache = getParserCache();
cache.getHtmlEntry().setDocument(null);
}
catch (Exception e) {
e.printStackTrace();
}
super.dispose();
}
@Override
public void update() {
try {
WodParserCache cache = TemplateSourceEditor.this.getParserCache();
cache.getHtmlEntry().setDocument(getDocumentProvider().getDocument(getEditorInput()));
}
catch (Exception e) {
e.printStackTrace();
}
super.update();
}
@Override
protected void doValidate() {
// if(!isFileEditorInput()){
// return;
// }
try {
String[] natureIds = HTMLPlugin.getDefault().getNoValidationNatureId();
IFile file = ((IFileEditorInput) getEditorInput()).getFile();
for (int i = 0; i < natureIds.length; i++) {
if (file.getProject().hasNature(natureIds[i])) {
return;
}
}
boolean autoBuild = ResourcesPlugin.getPlugin().getPluginPreferences().getDefaultBoolean(ResourcesPlugin.PREF_AUTO_BUILDING);
if (!autoBuild) {
ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) {
_validate();
}
}, null);
}
}
catch (Exception ex) {
HTMLPlugin.logException(ex);
}
}
protected void _validate() {
try {
WodParserCache cache = TemplateSourceEditor.this.getParserCache();
cache.parse();
cache.validate(false, true);
if (_breadcrumb != null) {
_breadcrumb.updateBreadcrumb();
}
}
catch (Exception ex) {
Activator.getDefault().log(ex);
}
}
public WodParserCache getParserCache() throws CoreException, LocateException {
if (_cache == null) {
IFileEditorInput input = (IFileEditorInput) getEditorInput();
IFile inputFile = input.getFile();
_cache = WodParserCache.parser(inputFile);
}
return _cache;
}
@Override
protected void handleElementContentReplaced() {
super.handleElementContentReplaced();
}
public FuzzyXMLDocument getHtmlXmlDocument(boolean refreshModel) throws Exception {
FuzzyXMLDocument doc;
if (refreshModel || isDirty()) {
BuildProperties buildProperties = (BuildProperties)getParserCache().getProject().getAdapter(BuildProperties.class);
FuzzyXMLParser parser = new FuzzyXMLParser(buildProperties != null ? buildProperties.isWellFormedTemplateRequired() : false, true);
doc = parser.parse(getHTMLSource());
getParserCache().getHtmlEntry().setModel(doc);
setCacheOutOfSync(false);
}
else {
doc = getParserCache().getHtmlEntry().getModel();
}
return doc;
}
public IWodElement getSelectedElement(boolean resolveWodElement, boolean refreshModel) throws Exception {
IWodElement wodElement = null;
WodParserCache cache = getParserCache();
if (getSelectionProvider() != null) {
ISelection realSelection = getSelectionProvider().getSelection();
if (realSelection instanceof ITextSelection) {
ITextSelection textSelection = (ITextSelection) realSelection;
FuzzyXMLDocument document = getHtmlXmlDocument(refreshModel);
if (document != null) {
FuzzyXMLElement element = document.getElementByOffset(textSelection.getOffset());
BuildProperties buildProperties = (BuildProperties)cache.getProject().getAdapter(BuildProperties.class);
wodElement = WodHtmlUtils.getWodElement(element, buildProperties, resolveWodElement, cache);
}
}
else if (realSelection instanceof IStructuredSelection) {
IStructuredSelection structuredSelection = (IStructuredSelection) realSelection;
Object obj = structuredSelection.getFirstElement();
if (obj instanceof FuzzyXMLElement) {
FuzzyXMLElement element = (FuzzyXMLElement) obj;
BuildProperties buildProperties = (BuildProperties)cache.getProject().getAdapter(BuildProperties.class);
wodElement = WodHtmlUtils.getWodElement(element, buildProperties, resolveWodElement, cache);
}
}
}
return wodElement;
}
public TemplateOutlinePage getTemplateOutlinePage() {
if (_templateOutlinePage == null) {
_templateOutlinePage = (TemplateOutlinePage) createOutlinePage();
}
return _templateOutlinePage;
}
@Override
protected IHTMLOutlinePage createOutlinePage() {
_templateOutlinePage = new TemplateOutlinePage(this);
return _templateOutlinePage;
}
// public String getHTMLSource(){
// String source = super.getHTMLSource();
// source = HTMLUtil.scriptlet2space(source,false);
// return source;
// }
@Override
protected void addContextMenuActions(IMenuManager menu) {
super.addContextMenuActions(menu);
addAction(menu, TemplateSourceEditor.GROUP_HTML, TemplateSourceEditor.ACTION_DELETE_TAG);
addAction(menu, TemplateSourceEditor.GROUP_HTML, TemplateSourceEditor.ACTION_UNWRAP_TAG);
}
@Override
protected void updateSelectionDependentActions() {
super.updateSelectionDependentActions();
// ITextSelection sel = (ITextSelection) getSelectionProvider().getSelection();
// if (sel.getText().equals("")) {
// getAction(ACTION_JSP_COMMENT).setEnabled(false);
// }
// else {
// getAction(ACTION_JSP_COMMENT).setEnabled(true);
// }
}
@Override
protected void rulerContextMenuAboutToShow(IMenuManager menu) {
super.rulerContextMenuAboutToShow(menu);
}
/**
* Update informations about code-completion.
*/
@Override
protected void updateAssist() {
super.updateAssist();
}
public int getOffsetAtPoint(Point point) {
StyledText st = getViewer().getTextWidget();
int modelOffset;
if (!st.getBounds().contains(point)) {
modelOffset = -1;
}
else {
try {
int offset = st.getOffsetAtLocation(point);
modelOffset = AbstractTextEditor.widgetOffset2ModelOffset(getSourceViewer(), offset);
}
catch (IllegalArgumentException e) {
modelOffset = -1;
}
}
return modelOffset;
}
public ISourceViewer getWOSourceViewer() {
return getViewer();
}
public StyledText getWOEditorControl() {
return getViewer().getTextWidget();
}
public IWodElement getWodElementAtPoint(Point point, boolean resolveWodElement, boolean refreshModel) throws Exception {
IWodElement wodElement = null;
FuzzyXMLElement element = getElementAtPoint(point, refreshModel);
if (WodHtmlUtils.isWOTag(element)) {
WodParserCache cache = getParserCache();
BuildProperties buildProperties = (BuildProperties)cache.getProject().getAdapter(BuildProperties.class);
wodElement = WodHtmlUtils.getWodElement(element, buildProperties, resolveWodElement, cache);
}
return wodElement;
}
public FuzzyXMLElement getElementAtPoint(Point point, boolean refreshModel) throws Exception {
int offset = getOffsetAtPoint(point);
FuzzyXMLElement element = getElementAtOffset(offset, refreshModel);
return element;
}
public FuzzyXMLElement getElementAtOffset(int offset, boolean refreshModel) throws Exception {
FuzzyXMLElement element = null;
if (offset >= 0) {
FuzzyXMLDocument xmlDocument = getHtmlXmlDocument(refreshModel);
if (xmlDocument != null) {
element = xmlDocument.getElementByOffset(offset);
}
}
return element;
}
public IRegion getSelectionRegionAtPoint(Point point, boolean regionForInsert, boolean refreshModel) throws Exception {
int offset = getOffsetAtPoint(point);
return getSelectionRegionAtOffset(offset, regionForInsert, refreshModel);
}
public IRegion getSelectionRegionForElementAtPoint(FuzzyXMLElement element, Point point, boolean regionForInsert) throws Exception {
int offset = getOffsetAtPoint(point);
return getSelectionRegionForElementAtOffset(element, offset, regionForInsert);
}
public IRegion getSelectionRegionAtOffset(int offset, boolean regionForInsert, boolean refreshModel) throws Exception {
FuzzyXMLElement element = getElementAtOffset(offset, refreshModel);
IRegion region = getSelectionRegionForElementAtOffset(element, offset, regionForInsert);
return region;
}
public IRegion getSelectionRegionForElementAtOffset(FuzzyXMLElement element, int offset, boolean regionForInsert) throws Exception {
IRegion region = null;
if (element != null) {
IDocument doc = getParserCache().getHtmlEntry().getDocument();
region = element.getRegionAtOffset(offset, doc, regionForInsert);
}
return region;
}
@Override
protected SourceViewerDecorationSupport getSourceViewerDecorationSupport(ISourceViewer viewer) {
if (fSourceViewerDecorationSupport == null) {
fSourceViewerDecorationSupport = new TemplateSourceViewerDecorationSupport(viewer, getOverviewRuler(), getAnnotationAccess(), getSharedColors());
configureSourceViewerDecorationSupport(fSourceViewerDecorationSupport);
}
return fSourceViewerDecorationSupport;
}
@Override
public Saveable[] getSaveables() {
return super.getSaveables();
}
public class DeleteTagAction extends Action {
public DeleteTagAction() {
super("Delete Tag");
}
@Override
public void run() {
try {
ITextSelection templateSelection = (ITextSelection) getSelectionProvider().getSelection();
if (templateSelection != null) {
int offset = templateSelection.getOffset();
FuzzyXMLElement element = getElementAtOffset(offset, true);
if (element != null) {
BuildProperties buildProperties = (BuildProperties)getParserCache().getProject().getAdapter(BuildProperties.class);
DeleteTagRefactoring.run(element, false, buildProperties, getParserCache(), new NullProgressMonitor());
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
public class UnwrapTagAction extends Action {
public UnwrapTagAction() {
super("Unwrap Tag");
}
@Override
public void run() {
try {
ITextSelection templateSelection = (ITextSelection) getSelectionProvider().getSelection();
if (templateSelection != null) {
int offset = templateSelection.getOffset();
FuzzyXMLElement element = getElementAtOffset(offset, true);
if (element != null) {
BuildProperties buildProperties = (BuildProperties)getParserCache().getProject().getAdapter(BuildProperties.class);
DeleteTagRefactoring.run(element, true, buildProperties, getParserCache(), new NullProgressMonitor());
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}