/** * <copyright> * </copyright> * * */ package org.dresdenocl.language.ocl.resource.ocl.ui; import java.util.LinkedHashMap; import java.util.Map; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocumentExtension3; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextOperationTarget; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.text.ITypedRegion; import org.eclipse.jface.text.Region; import org.eclipse.jface.text.TextUtilities; import org.eclipse.jface.viewers.ISelection; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.handlers.HandlerUtil; public class OclToggleCommentHandler extends AbstractHandler { public static String[] COMMENT_PREFIXES = new String[] { "//" }; private IDocument document; private ITextOperationTarget operationTarget; private Map<String, String[]> prefixesMap; @Override public boolean isEnabled() { IEditorPart activeEditor = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); if (activeEditor instanceof org.dresdenocl.language.ocl.resource.ocl.ui.OclEditor) { ITextOperationTarget operationTarget = (ITextOperationTarget) activeEditor.getAdapter(ITextOperationTarget.class); return (operationTarget != null && operationTarget.canDoOperation(ITextOperationTarget.PREFIX) && operationTarget.canDoOperation(ITextOperationTarget.STRIP_PREFIX)); } return false; } public Object execute(ExecutionEvent event) throws ExecutionException { IEditorPart editorPart = HandlerUtil.getActiveEditor(event); org.dresdenocl.language.ocl.resource.ocl.ui.OclEditor editor = null; if (editorPart instanceof org.dresdenocl.language.ocl.resource.ocl.ui.OclEditor) { editor = (org.dresdenocl.language.ocl.resource.ocl.ui.OclEditor) editorPart; operationTarget = (ITextOperationTarget) editorPart.getAdapter(ITextOperationTarget.class); document = editor.getDocumentProvider().getDocument(editor.getEditorInput()); } if (editor == null || operationTarget == null || document == null) { return null; } prefixesMap = new LinkedHashMap<String, String[]>(); prefixesMap.put(IDocument.DEFAULT_CONTENT_TYPE, COMMENT_PREFIXES); ISelection currentSelection = editor.getSelectionProvider().getSelection(); final int operationCode; if (isSelectionCommented(currentSelection)) { operationCode = ITextOperationTarget.STRIP_PREFIX; } else { operationCode = ITextOperationTarget.PREFIX; } if (!operationTarget.canDoOperation(operationCode)) { return null; } Shell shell = editorPart.getSite().getShell(); Display display = null; if (shell != null && !shell.isDisposed()) { display = shell.getDisplay(); } BusyIndicator.showWhile(display, new Runnable() { public void run() { operationTarget.doOperation(operationCode); } }); return null; } // Parts of the implementation below have been copied from // org.eclipse.jdt.internal.ui.javaeditor.ToggleCommentAction. private boolean isSelectionCommented(ISelection selection) { if (!(selection instanceof ITextSelection)) { return false; } ITextSelection textSelection = (ITextSelection) selection; if (textSelection.getStartLine() < 0 || textSelection.getEndLine() < 0) { return false; } try { IRegion block = getTextBlockFromSelection(textSelection, document); ITypedRegion[] regions = TextUtilities.computePartitioning(document, IDocumentExtension3.DEFAULT_PARTITIONING, block.getOffset(), block.getLength(), false); int[] lines = new int[regions.length * 2]; // [startline, endline, startline, endline, ...] for (int i = 0, j = 0; i < regions.length; i++, j+= 2) { // start line of region lines[j] = getFirstCompleteLineOfRegion(regions[i], document); // end line of region int length = regions[i].getLength(); int offset = regions[i].getOffset() + length; if (length > 0) { offset--; } lines[j + 1] = (lines[j] == -1 ? -1 : document.getLineOfOffset(offset)); } // Perform the check for (int i = 0, j = 0; i < regions.length; i++, j += 2) { String[] prefixes = prefixesMap.get(regions[i].getType()); if (prefixes != null && prefixes.length > 0 && lines[j] >= 0 && lines[j + 1] >= 0) { if (!isBlockCommented(lines[j], lines[j + 1], prefixes, document)) { return false; } } } return true; } catch (BadLocationException x) { // should not happen } return false; } private IRegion getTextBlockFromSelection(ITextSelection selection, IDocument document) { try { IRegion line = document.getLineInformationOfOffset(selection.getOffset()); int length = selection.getLength() == 0 ? line.getLength() : selection.getLength() + (selection.getOffset() - line.getOffset()); return new Region(line.getOffset(), length); } catch (BadLocationException x) { // should not happen } return null; } private int getFirstCompleteLineOfRegion(IRegion region, IDocument document) { try { final int startLine = document.getLineOfOffset(region.getOffset()); int offset = document.getLineOffset(startLine); if (offset >= region.getOffset()) { return startLine; } final int nextLine = startLine + 1; if (nextLine == document.getNumberOfLines()) { return -1; } offset = document.getLineOffset(nextLine); return (offset > region.getOffset() + region.getLength() ? -1 : nextLine); } catch (BadLocationException x) { // should not happen } return -1; } private boolean isBlockCommented(int startLine, int endLine, String[] prefixes, IDocument document) { try { // check for occurrences of prefixes in the given lines for (int i = startLine; i <= endLine; i++) { IRegion line = document.getLineInformation(i); String text = document.get(line.getOffset(), line.getLength()); int[] found = TextUtilities.indexOf(prefixes, text, 0); if (found[0] == -1) { // found a line which is not commented return false; } String s = document.get(line.getOffset(), found[0]); s = s.trim(); if (s.length() != 0) { // found a line which is not commented return false; } } return true; } catch (BadLocationException x) { // should not happen } return false; } }