package tk.eclipse.plugin.htmleditor.editors;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.jrcs.diff.AddDelta;
import org.apache.commons.jrcs.diff.ChangeDelta;
import org.apache.commons.jrcs.diff.DeleteDelta;
import org.apache.commons.jrcs.diff.Delta;
import org.apache.commons.jrcs.diff.Diff;
import org.apache.commons.jrcs.diff.Revision;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
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.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.ITextViewerExtension2;
import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.text.source.IOverviewRuler;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.IVerticalRuler;
import org.eclipse.jface.text.source.MatchingCharacterPainter;
import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel;
import org.eclipse.jface.text.source.projection.ProjectionSupport;
import org.eclipse.jface.text.source.projection.ProjectionViewer;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IStorageEditorInput;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.editors.text.TextEditor;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
import org.eclipse.ui.texteditor.ChainedPreferenceStore;
import org.eclipse.ui.texteditor.ContentAssistAction;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
import org.objectstyle.wolips.wodclipse.core.util.CursorPositionSupport;
import org.objectstyle.wolips.wodclipse.core.util.ICursorPositionListener;
import tk.eclipse.plugin.htmleditor.ColorProvider;
import tk.eclipse.plugin.htmleditor.HTMLHyperlinkDetector;
import tk.eclipse.plugin.htmleditor.HTMLPlugin;
import tk.eclipse.plugin.htmleditor.HTMLProjectParams;
import tk.eclipse.plugin.htmleditor.HTMLUtil;
import tk.eclipse.plugin.htmleditor.assist.HTMLAssistProcessor;
import tk.eclipse.plugin.htmleditor.assist.InnerJavaScriptAssistProcessor;
/**
* HTML source editor.
*/
public class HTMLSourceEditor extends TextEditor {
private CursorPositionSupport _cursorPositionSupport;
private ColorProvider _colorProvider;
private IHTMLOutlinePage _outlinePage;
private HTMLCharacterPairMatcher _pairMatcher;
private SoftTabVerifyListener _softTabListener;
public static final String GROUP_HTML = "_html";
public static final String ACTION_ESCAPE_HTML = "_escape_html";
public static final String ACTION_COMMENT = "_comment";
public static final String ACTION_OPEN_PALETTE = "_open_palette";
public static final String ACTION_CHOOSE_COLOR = "_choose_color";
public static final String ACTION_COMPLETION = "ContentAssistProposal";
// private boolean useSoftTab;
// private String softTab;
private boolean validation = true;
public HTMLSourceEditor(HTMLConfiguration config) {
super();
config.setEditorPart(this);
_colorProvider = HTMLPlugin.getDefault().getColorProvider();
setSourceViewerConfiguration(config);
setPreferenceStore(new ChainedPreferenceStore(new IPreferenceStore[] { getPreferenceStore(), HTMLPlugin.getDefault().getPreferenceStore() }));
setAction(ACTION_ESCAPE_HTML, new EscapeHTMLAction());
//setAction(ACTION_OPEN_PALETTE, new OpenPaletteAction());
//setAction(ACTION_CHOOSE_COLOR, new ChooseColorAction(this));
IPreferenceStore store = HTMLPlugin.getDefault().getPreferenceStore();
_softTabListener = new SoftTabVerifyListener();
_softTabListener.setUseSoftTab(store.getBoolean(HTMLPlugin.PREF_USE_SOFTTAB));
_softTabListener.setSoftTabWidth(store.getInt(HTMLPlugin.PREF_SOFTTAB_WIDTH));
_outlinePage = createOutlinePage();
_cursorPositionSupport = new CursorPositionSupport(this);
}
protected HTMLCharacterPairMatcher getPairMatcher() {
return this._pairMatcher;
}
public void setValidation(boolean validation) {
this.validation = validation;
}
public boolean getValidation() {
return this.validation;
}
protected IHTMLOutlinePage createOutlinePage() {
return new HTMLOutlinePage(this);
}
/**
* TODO Move to SourceViewerConfiguration!!
*/
protected final HTMLHyperlinkDetector createHyperlinkSupport() {
return new HTMLHyperlinkDetector();
}
private ProjectionSupport fProjectionSupport;
@Override
protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
ISourceViewer viewer = new ProjectionViewer(parent, ruler, getOverviewRuler(), true, styles);
getSourceViewerDecorationSupport(viewer);
viewer.getTextWidget().addVerifyListener(_softTabListener);
return viewer;
}
@Override
public IOverviewRuler getOverviewRuler() {
return super.getOverviewRuler();
}
public ISourceViewer getViewer() {
return this.getSourceViewer();
}
public synchronized void addCursorPositionListener(ICursorPositionListener listener) {
_cursorPositionSupport.addCursorPositionListener(listener);
}
public synchronized void removeCursorPositionListener(ICursorPositionListener listener) {
_cursorPositionSupport.removeCursorPositionListener(listener);
}
@Override
protected void handleCursorPositionChanged() {
super.handleCursorPositionChanged();
_cursorPositionSupport.cursorPositionChanged(getViewer().getSelectedRange());
}
@Override
public void createPartControl(Composite parent) {
super.createPartControl(parent);
ProjectionViewer projectionViewer = (ProjectionViewer) getSourceViewer();
fProjectionSupport = new ProjectionSupport(projectionViewer, getAnnotationAccess(), getSharedColors());
fProjectionSupport.install();
projectionViewer.doOperation(ProjectionViewer.TOGGLE);
projectionViewer.getTextWidget().setTabs(getPreferenceStore().getInt(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH));
// projectionViewer.setHyperlinkDetectors(new IHyperlinkDetector[]{
// new URLHyperlinkDetector(projectionViewer),
// createHyperlinkSupport()
// }, SWT.CTRL);
ITextViewerExtension2 extension = (ITextViewerExtension2) getSourceViewer();
_pairMatcher = new HTMLCharacterPairMatcher();
_pairMatcher.setEnable(getPreferenceStore().getBoolean(HTMLPlugin.PREF_PAIR_CHAR));
MatchingCharacterPainter painter = new MatchingCharacterPainter(getSourceViewer(), _pairMatcher);
painter.setColor(Display.getDefault().getSystemColor(SWT.COLOR_GRAY));
extension.addPainter(painter);
getSourceViewer().getTextWidget().getParent().setBackground(parent.getBackground());
update();
}
// public void addTextListener(ITextListener l){
// getSourceViewer().addTextListener(l);
// }
//
// public void removeTextListener(ITextListener l){
// getSourceViewer().removeTextListener(l);
// }
/** This method is called when configuration is changed. */
@Override
protected boolean affectsTextPresentation(PropertyChangeEvent event) {
return super.affectsTextPresentation(event) || _colorProvider.affectsTextPresentation(event);
}
/** This method is called when configuration is changed. */
@Override
protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
_colorProvider.handlePreferenceStoreChanged(event);
updateAssistProperties(event);
_softTabListener.preferenceChanged(event);
String key = event.getProperty();
if (key.equals(HTMLPlugin.PREF_PAIR_CHAR)) {
Object value = event.getNewValue();
boolean enable = false;
if (value instanceof String) {
enable = Boolean.valueOf((String) value).booleanValue();
}
else if (value instanceof Boolean) {
enable = ((Boolean) value).booleanValue();
}
_pairMatcher.setEnable(enable);
}
super.handlePreferenceStoreChanged(event);
}
private void updateAssistProperties(PropertyChangeEvent event) {
String key = event.getProperty();
try {
// auto activation delay
if (key.equals(HTMLPlugin.PREF_ASSIST_TIMES)) {
ContentAssistant assistant = (ContentAssistant) getSourceViewerConfiguration().getContentAssistant(null);
assistant.setAutoActivationDelay(Integer.parseInt((String) event.getNewValue()));
// auto activation trigger
}
else if (key.equals(HTMLPlugin.PREF_ASSIST_CHARS)) {
ContentAssistant assistant = (ContentAssistant) getSourceViewerConfiguration().getContentAssistant(null);
HTMLAssistProcessor processor = (HTMLAssistProcessor) assistant.getContentAssistProcessor(IDocument.DEFAULT_CONTENT_TYPE);
processor.setAutoAssistChars(((String) event.getNewValue()).toCharArray());
// completion close tag
}
else if (key.equals(HTMLPlugin.PREF_ASSIST_CLOSE)) {
ContentAssistant assistant = (ContentAssistant) getSourceViewerConfiguration().getContentAssistant(null);
HTMLAssistProcessor processor = (HTMLAssistProcessor) assistant.getContentAssistProcessor(IDocument.DEFAULT_CONTENT_TYPE);
processor.setAssistCloseTag(((Boolean) event.getNewValue()).booleanValue());
// enable auto activation or not
}
else if (key.equals(HTMLPlugin.PREF_ASSIST_AUTO)) {
ContentAssistant assistant = (ContentAssistant) getSourceViewerConfiguration().getContentAssistant(null);
assistant.enableAutoActivation(((Boolean) event.getNewValue()).booleanValue());
}
}
catch (Exception ex) {
HTMLPlugin.logException(ex);
}
}
/**
* Adds actions to the context menu.
* <p>
* If you want to customize the context menu,
* you can override this method in the sub-class
* instead of editorContextMenuAboutToShow(),
*
* @param menu IMenuManager
*/
protected void addContextMenuActions(IMenuManager menu) {
menu.add(new Separator(GROUP_HTML));
//addAction(menu, GROUP_HTML, ACTION_CHOOSE_COLOR);
//addAction(menu, GROUP_HTML, ACTION_OPEN_PALETTE);
addAction(menu, GROUP_HTML, ACTION_ESCAPE_HTML);
addAction(menu, GROUP_HTML, ACTION_COMMENT);
}
@Override
protected void editorContextMenuAboutToShow(IMenuManager menu) {
super.editorContextMenuAboutToShow(menu);
addContextMenuActions(menu);
}
@Override
protected void updateSelectionDependentActions() {
super.updateSelectionDependentActions();
ITextSelection sel = (ITextSelection) getSelectionProvider().getSelection();
if (sel.getText().equals("")) {
getAction(ACTION_COMMENT).setEnabled(false);
getAction(ACTION_ESCAPE_HTML).setEnabled(false);
}
else {
getAction(ACTION_COMMENT).setEnabled(true);
getAction(ACTION_ESCAPE_HTML).setEnabled(true);
}
}
/**
* Validates HTML document.
* If the editor provides other validation, do override at the subclass.
*/
protected void doValidate() {
try {
ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
try {
IFileEditorInput input = (IFileEditorInput) getEditorInput();
IFile file = input.getFile();
file.deleteMarkers(IMarker.PROBLEM, false, 0);
HTMLProjectParams params = new HTMLProjectParams(file.getProject());
if (params.getValidateHTML()) {
new HTMLValidator(input.getFile()).doValidate();
}
}
catch (Exception ex) {
//HTMLPlugin.logException(ex);
}
}
}, null);
}
catch (Exception ex) {
HTMLPlugin.logException(ex);
}
}
/**
* Returns HTML source which can be parse by FuzzyXML.
*
* @return HTML source
*/
public String getHTMLSource() {
return getDocumentProvider().getDocument(getEditorInput()).get();
}
/**
* This method is called in the following timing:
* <ul>
* <li>Initialize editor</li>
* <li>Save document</li>
* </ul>
* And do the following sequence.
* <ul>
* <li>invoke {@link HTMLSourceEditor#updateFolding()}</li>
* <li>invoke {@link HTMLSourceEditor#updateAssist()}</li>
* <li>invoke {@link HTMLOutlinePage#update()}</li>
* <li>update {@link HTMLHyperlinkSupport}
* <li>invoke {@link HTMLSourceEditor#doValidate()()} (only getValidation() returns true)</li>
* </ul>
* If it's required to update some information about the editor,
* do override at the subclass.
*/
public void update() {
updateFolding();
updateAssist();
_outlinePage.update();
if (validation && isFileEditorInput()) {
doValidate();
}
HTMLHyperlinkDetector hyperlinkDetector = ((HTMLConfiguration) getSourceViewerConfiguration()).getHyperlinkDetector();
hyperlinkDetector.setEditor(this);
}
/**
* Update informations about code-completion.
*/
protected void updateAssist() {
String html = getDocumentProvider().getDocument(getEditorInput()).get();
// Update AssistProcessors
HTMLAssistProcessor processor = ((HTMLConfiguration) getSourceViewerConfiguration()).getAssistProcessor();
processor.update(this, html);
if (!isFileEditorInput()) {
return;
}
InnerJavaScriptAssistProcessor jsProcessor = ((HTMLConfiguration) getSourceViewerConfiguration()).getJavaScriptAssistProcessor();
jsProcessor.update(((IFileEditorInput) getEditorInput()).getFile());
}
/*
protected void initializeDragAndDrop(ISourceViewer viewer) {
super.initializeDragAndDrop(viewer);
DropTarget target = new DropTarget(viewer.getTextWidget(),DND.DROP_DEFAULT|DND.DROP_COPY);
LocalSelectionTransfer selTransfer = LocalSelectionTransfer.getInstance();
// FileTransfer fileTransfer = FileTransfer.getInstance();
// TextTransfer textTransfer = TextTransfer.getInstance();
// Transfer[] types = new Transfer[]{fileTransfer,textTransfer};
Transfer[] types = new Transfer[]{selTransfer};
target.setTransfer(types);
target.addDropListener(new HTMLDropListener());
// getSourceViewer().getTextWidget().addMouseMoveListener(new HTMLDropMouseMoveListener());
}
*/
@Override
public void dispose() {
if (isFileEditorInput() && validation) {
try {
ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
try {
IFileEditorInput input = (IFileEditorInput) getEditorInput();
HTMLProjectParams params = new HTMLProjectParams(input.getFile().getProject());
if (params.getRemoveMarkers()) {
input.getFile().deleteMarkers(IMarker.PROBLEM, false, 0);
}
}
catch (Exception ex) {
}
}
}, null);
}
catch (Exception ex) {
}
}
fProjectionSupport.dispose();
_pairMatcher.dispose();
super.dispose();
}
public ProjectionSupport getProjectionSupport() {
return fProjectionSupport;
}
/**
* Returns a java.io.File object that is editing in this editor.
*/
public File getFile() {
IFile file = ((FileEditorInput) this.getEditorInput()).getFile();
return file.getLocation().makeAbsolute().toFile();
}
/**
* Returns a java.io.File object of a temporary file for preview.
*/
public File getTempFile() {
IFile file = ((FileEditorInput) this.getEditorInput()).getFile();
return new File(file.getLocation().makeAbsolute().toFile().getParentFile(), "." + file.getName());
}
@Override
protected void createActions() {
super.createActions();
// add content assist action
IAction action = new ContentAssistAction(HTMLPlugin.getDefault().getResourceBundle(), "ContentAssistProposal", this);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
setAction(ACTION_COMPLETION, action);
setAction(ACTION_COMMENT, new CommentAction());
}
@Override
public Object getAdapter(Class adapter) {
if (IContentOutlinePage.class.equals(adapter)) {
return _outlinePage;
}
if (ProjectionAnnotationModel.class.equals(adapter) && fProjectionSupport != null) {
Object obj = fProjectionSupport.getAdapter(getSourceViewer(), adapter);
if (obj != null) {
return obj;
}
}
if (IDocumentProvider.class.equals(adapter)) {
return getDocumentProvider();
}
if (ISelectionProvider.class.equals(adapter)) {
return getSelectionProvider();
}
return super.getAdapter(adapter);
}
protected IDocumentProvider createDocumentProvider(IEditorInput input) {
if (input instanceof IFileEditorInput) {
return new HTMLTextDocumentProvider();
}
else if (input instanceof IStorageEditorInput) {
return new HTMLFileDocumentProvider();
}
else {
return new HTMLTextDocumentProvider();
}
}
@Override
protected void doSetInput(IEditorInput input) throws CoreException {
setDocumentProvider(createDocumentProvider(input));
if (input instanceof IFileEditorInput) {
IFile file = ((IFileEditorInput) input).getFile();
if (file.getName().endsWith(".xhtml")) {
HTMLConfiguration config = (HTMLConfiguration) getSourceViewerConfiguration();
config.getAssistProcessor().setXHTMLMode(true);
}
}
super.doSetInput(input);
}
@Override
public void doSave(IProgressMonitor progressMonitor) {
super.doSave(progressMonitor);
update();
}
@Override
public void doSaveAs() {
super.doSaveAs();
update();
}
public void setDiff(String text) {
// apply the graphical editor contents to the source editor
IEditorInput input = getEditorInput();
IDocument doc = getDocumentProvider().getDocument(input);
getSourceViewer().getTextWidget().setRedraw(false);
String[] text1 = doc.get().split("\n");
String[] text2 = text.split("\n");
try {
Revision rev = Diff.diff(text1, text2);
int count1 = 0;
int count2 = 0;
int index = 0;
for (int i = 0; i < rev.size(); i++) {
Delta delta = rev.getDelta(i);
Range orgRange = new Range(delta.getOriginal().rangeString());
Range revRange = new Range(delta.getRevised().rangeString());
// matched
while (count1 != orgRange.getFrom() - 1) {
index = index + text1[count1].length() + 1;
count1++;
}
count1 = orgRange.getFrom() - 1;
count2 = revRange.getFrom() - 1;
// added
if (delta instanceof AddDelta) {
while (count2 != revRange.getTo()) {
doc.replace(index, 0, text2[count2] + "\n");
index = index + text2[count2].length() + 1;
count2++;
}
// removed
}
else if (delta instanceof DeleteDelta) {
while (count1 != orgRange.getTo()) {
doc.replace(index, text1[count1].length() + 1, "");
count1++;
}
// replaced
}
else if (delta instanceof ChangeDelta) {
while (count1 != orgRange.getTo()) {
doc.replace(index, text1[count1].length() + 1, "");
count1++;
}
while (count2 != revRange.getTo()) {
doc.replace(index, 0, text2[count2] + "\n");
index = index + text2[count2].length() + 1;
count2++;
}
}
count1 = orgRange.getTo();
count2 = revRange.getTo();
}
}
catch (Exception ex) {
doc.set(text);
}
getSourceViewer().getTextWidget().setRedraw(true);
}
/** This class is used in setDiff(). */
private class Range {
private int from;
private int to;
public Range(String rangeString) {
if (rangeString.indexOf(",") != -1) {
String[] dim = rangeString.split(",");
from = Integer.parseInt(dim[0]);
to = Integer.parseInt(dim[1]);
}
else {
from = Integer.parseInt(rangeString);
to = Integer.parseInt(rangeString);
}
}
public int getFrom() {
return this.from;
}
public int getTo() {
return to;
}
}
/** Regular expression to search tags. */
private Pattern tagPattern = Pattern.compile("<([^<]*?)>");
private Pattern valuePattern = Pattern.compile("\".*?\"");
/**
* Update folding informations.
*/
private void updateFolding() {
try {
ProjectionViewer viewer = (ProjectionViewer) getSourceViewer();
if (viewer == null) {
return;
}
ProjectionAnnotationModel model = viewer.getProjectionAnnotationModel();
if (model == null) {
return;
}
List<FoldingInfo> list = new ArrayList<FoldingInfo>();
Stack<FoldingInfo> stack = new Stack<FoldingInfo>();
IDocument doc = getDocumentProvider().getDocument(getEditorInput());
String xml = HTMLUtil.scriptlet2space(HTMLUtil.comment2space(doc.get(), true), true);
// trim attribute values
Matcher matcher = valuePattern.matcher(xml);
while (matcher.find()) {
int start = matcher.start(0);
int length = matcher.group(0).length();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; i++) {
sb.append(" ");
}
xml = xml.substring(0, start) + sb.toString() + xml.substring(start + length);
}
matcher = tagPattern.matcher(xml);
while (matcher.find()) {
String text = matcher.group(1).trim();
// skip XML declaration
if (text.startsWith("?")) {
continue;
}
// DOCTYPE declaration
if (text.startsWith("!DOCTYPE")) {
// Don't fold if start offset and end offset are same line
if (doc.getLineOfOffset(matcher.start()) != doc.getLineOfOffset(matcher.end())) {
FoldingInfo info = new FoldingInfo(matcher.start(), matcher.end(), "!DOCTYPE");
info.setEnd(info.getEnd() + FoldingInfo.countUpLineDelimiter(xml, matcher.end()));
list.add(info);
}
continue;
}
// JSP (I think this shouldn't process in here)
if (text.startsWith("%")) {
// Don't fold if start offset and end offset are same line
if (doc.getLineOfOffset(matcher.start()) != doc.getLineOfOffset(matcher.end())) {
FoldingInfo info = new FoldingInfo(matcher.start(), matcher.end(), "%");
info.setEnd(info.getEnd() + FoldingInfo.countUpLineDelimiter(xml, matcher.end()));
list.add(info);
}
continue;
}
// comment
if (text.startsWith("!--")) {
// Don't fold if start offset and end offset are same line
if (doc.getLineOfOffset(matcher.start()) != doc.getLineOfOffset(matcher.end())) {
FoldingInfo info = new FoldingInfo(matcher.start(), matcher.end(), "!--");
info.setEnd(info.getEnd() + FoldingInfo.countUpLineDelimiter(xml, matcher.end()));
list.add(info);
}
continue;
}
// close tag
if (text.startsWith("/")) {
text = text.substring(1, text.length());
while (stack.size() != 0) {
FoldingInfo info = stack.pop();
if (info.getType().equalsIgnoreCase(text) || (info.getType().toLowerCase().startsWith("tb:") && text.toLowerCase().startsWith("tb")) || (info.getType().toLowerCase().startsWith("wo:") && text.toLowerCase().startsWith("wo"))) {
info.setEnd(matcher.end());
// Don't fold if start offset and end offset are same line
if (doc.getLineOfOffset(info.getStart()) != doc.getLineOfOffset(info.getEnd())) {
info.setEnd(info.getEnd() + FoldingInfo.countUpLineDelimiter(xml, matcher.end()));
list.add(info);
}
break;
}
}
continue;
}
// empty tag
if (text.endsWith("/")) {
// Don't fold if start offset and end offset are same line
if (doc.getLineOfOffset(matcher.start()) != doc.getLineOfOffset(matcher.end())) {
text.substring(0, text.length() - 1);
if (text.indexOf(" ") != -1) {
text = text.substring(0, text.indexOf(" "));
}
FoldingInfo info = new FoldingInfo(matcher.start(), matcher.end(), text);
info.setEnd(info.getEnd() + FoldingInfo.countUpLineDelimiter(xml, matcher.end()));
list.add(info);
}
continue;
}
// start tag (put to the stack)
text = text.replaceAll("[\\s\r\n]+", " ");
if (text.indexOf(" ") != -1) {
text = text.substring(0, text.indexOf(" "));
}
stack.push(new FoldingInfo(matcher.start(), 0, text));
}
FoldingInfo.applyModifiedAnnotations(model, list);
}
catch (Exception ex) {
HTMLPlugin.logException(ex);
}
}
////////////////////////////////////////////////////////////////////////////
// Drag & Drop
////////////////////////////////////////////////////////////////////////////
/*
private class HTMLDropListener extends DropTargetAdapter {
public void dragEnter(DropTargetEvent evt){
evt.detail = DND.DROP_COPY;
setFocus();
}
// public void dragLeave(DropTargetEvent event) {
// }
private Point calcLocation(Composite composite,Point point){
Point compPoint = composite.getLocation();
Point nextPoint = new Point(compPoint.x + point.x ,compPoint.y + point.y);
Composite parent = composite.getParent();
if(parent!=null){
Point result = calcLocation(parent,nextPoint);
return result;
} else {
return new Point(nextPoint.x + 30, nextPoint.y + 48);
}
}
public void dragOver(DropTargetEvent event) {
try {
Point point = calcLocation(getSourceViewer().getTextWidget().getParent(),new Point(0,0));
int x = event.x - point.x;
int y = event.y - point.y;
int offset = getSourceViewer().getTextWidget().getOffsetAtLocation(new Point(x,y));
getSourceViewer().getTextWidget().setCaretOffset(offset);
} catch(Exception ex){
}
}
public void drop(DropTargetEvent evt){
for(int i=0;i<evt.dataTypes.length;i++){
if (TextTransfer.getInstance().isSupportedType(evt.dataTypes[i])){
String text = (String)evt.data;
}
else if (FileTransfer.getInstance().isSupportedType(evt.dataTypes[i])){
String[] files = (String[])evt.data;
for(int j=0;j<files.length;j++){
File file = new File(files[j]);
}
}
else if (LocalSelectionTransfer.getInstance().isSupportedType(evt.dataTypes[i])){
IStructuredSelection sel = (IStructuredSelection)evt.data;
Object obj = sel.getFirstElement();
if(obj instanceof IPaletteItem){
((IPaletteItem)obj).execute(HTMLSourceEditor.this);
}
}
}
}
}
*/
public boolean isFileEditorInput() {
if (getEditorInput() instanceof IFileEditorInput) {
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////////////
// actions
////////////////////////////////////////////////////////////////////////////
/** The action to escape HTML tags in the selection. */
private class EscapeHTMLAction extends Action {
public EscapeHTMLAction() {
super(HTMLPlugin.getResourceString("HTMLEditor.EscapeAction"));
setEnabled(false);
setAccelerator(SWT.CTRL | '\\');
}
@Override
public void run() {
ITextSelection sel = (ITextSelection) getSelectionProvider().getSelection();
IDocument doc = getDocumentProvider().getDocument(getEditorInput());
try {
doc.replace(sel.getOffset(), sel.getLength(), HTMLUtil.escapeHTML(sel.getText()));
}
catch (BadLocationException e) {
HTMLPlugin.logException(e);
}
}
}
/** The action to comment out selection range. */
private class CommentAction extends Action {
public CommentAction() {
super(HTMLPlugin.getResourceString("HTMLEditor.CommentAction"));
setActionDefinitionId("tk.eclipse.plugin.htmleditor.comment");
}
@Override
public void run() {
ITextSelection sel = (ITextSelection) getSelectionProvider().getSelection();
IDocument doc = getDocumentProvider().getDocument(getEditorInput());
String text = sel.getText().trim();
try {
if (text.startsWith("<!--") && text.indexOf("-->") > 3) {
text = sel.getText().replaceFirst("<!--", "");
text = text.replaceFirst("-->", "");
doc.replace(sel.getOffset(), sel.getLength(), text);
}
else {
doc.replace(sel.getOffset(), sel.getLength(), "<!--" + sel.getText() + "-->");
}
}
catch (BadLocationException e) {
HTMLPlugin.logException(e);
}
}
}
/** The action to open the palette view. */
private class OpenPaletteAction extends Action {
public OpenPaletteAction() {
super(HTMLPlugin.getResourceString("HTMLEditor.OpenPaletteAction"), HTMLPlugin.getDefault().getImageRegistry().getDescriptor(HTMLPlugin.ICON_PALETTE));
setEnabled(true);
}
@Override
public void run() {
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
try {
window.getActivePage().showView("tk.eclipse.plugin.htmleditor.views.PaletteView");
}
catch (Exception ex) {
HTMLPlugin.openAlertDialog(ex.toString());
}
}
}
}