X-Git-Url: http://secure.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/BlockCommentAction.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/BlockCommentAction.java new file mode 100644 index 0000000..74ffae5 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/BlockCommentAction.java @@ -0,0 +1,375 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package net.sourceforge.phpdt.internal.ui.actions; + +import java.util.Iterator; +import java.util.List; +import java.util.ResourceBundle; + +//incastrix +//import org.eclipse.jface.text.Assert; +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.BadPartitioningException; +import org.eclipse.jface.text.BadPositionCategoryException; +import org.eclipse.jface.text.DefaultPositionUpdater; +import org.eclipse.jface.text.DocumentEvent; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentExtension3; +import org.eclipse.jface.text.IPositionUpdater; +import org.eclipse.jface.text.IRewriteTarget; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; +import org.eclipse.ui.texteditor.ITextEditorExtension2; +import org.eclipse.ui.texteditor.TextEditorAction; + +/** + * Common block comment code. + * + * @since 3.0 + */ +public abstract class BlockCommentAction extends TextEditorAction { + + /** + * Creates a new instance. + * + * @param bundle + * @param prefix + * @param editor + */ + public BlockCommentAction(ResourceBundle bundle, String prefix, + ITextEditor editor) { + super(bundle, prefix, editor); + } + + /** + * An edit is a kind of DocumentEvent, in this case an edit + * instruction, that is affilitated with a Position on a + * document. The offset of the document event is not stored statically, but + * taken from the affiliated Position, which gets updated + * when other edits occurr. + */ + static class Edit extends DocumentEvent { + + /** + * Factory for edits which manages the creation, installation and + * destruction of position categories, position updaters etc. on a + * certain document. Once a factory has been obtained, Edit + * objects can be obtained from it which will be linked to the document + * by positions of one position category. + *

+ * Clients are required to call release once the + * Edits are not used any more, so the positions can be + * discarded. + *

+ */ + public static class EditFactory { + + /** The position category basename for this edits. */ + private static final String CATEGORY = "__positionalEditPositionCategory"; //$NON-NLS-1$ + + /** The count of factories. */ + private static int fgCount = 0; + + /** This factory's category. */ + private final String fCategory; + + private IDocument fDocument; + + private IPositionUpdater fUpdater; + + /** + * Creates a new EditFactory with an unambiguous + * position category name. + * + * @param document + * the document that is being edited. + */ + public EditFactory(IDocument document) { + fCategory = CATEGORY + fgCount++; + fDocument = document; + } + + /** + * Creates a new edition on the document of this factory. + * + * @param offset + * the offset of the edition at the point when is + * created. + * @param length + * the length of the edition (not updated via the + * position update mechanism) + * @param text + * the text to be replaced on the document + * @return an Edit reflecting the edition on the + * document + */ + public Edit createEdit(int offset, int length, String text) + throws BadLocationException { + + if (!fDocument.containsPositionCategory(fCategory)) { + fDocument.addPositionCategory(fCategory); + fUpdater = new DefaultPositionUpdater(fCategory); + fDocument.addPositionUpdater(fUpdater); + } + + Position position = new Position(offset); + try { + fDocument.addPosition(fCategory, position); + } catch (BadPositionCategoryException e) { + Assert.isTrue(false); + } + return new Edit(fDocument, length, text, position); + } + + /** + * Releases the position category on the document and uninstalls the + * position updater. Edits managed by this factory + * are not updated after this call. + */ + public void release() { + if (fDocument != null + && fDocument.containsPositionCategory(fCategory)) { + fDocument.removePositionUpdater(fUpdater); + try { + fDocument.removePositionCategory(fCategory); + } catch (BadPositionCategoryException e) { + Assert.isTrue(false); + } + fDocument = null; + fUpdater = null; + } + } + } + + /** The position in the document where this edit be executed. */ + private Position fPosition; + + /** + * Creates a new edition on document, taking its offset + * from position. + * + * @param document + * the document being edited + * @param length + * the length of the edition + * @param text + * the replacement text of the edition + * @param position + * the position keeping the edition's offset + */ + protected Edit(IDocument document, int length, String text, + Position position) { + super(document, 0, length, text); + fPosition = position; + } + + /* + * @see org.eclipse.jface.text.DocumentEvent#getOffset() + */ + public int getOffset() { + return fPosition.getOffset(); + } + + /** + * Executes the edition on document. The offset is taken from the + * position. + * + * @throws BadLocationException + * if the execution of the document fails. + */ + public void perform() throws BadLocationException { + getDocument().replace(getOffset(), getLength(), getText()); + } + + } + + public void run() { + if (!isEnabled()) + return; + + ITextEditor editor = getTextEditor(); + if (editor == null || !ensureEditable(editor)) + return; + + ITextSelection selection = getCurrentSelection(); + if (!isValidSelection(selection)) + return; + + if (!validateEditorInputState()) + return; + + IDocumentProvider docProvider = editor.getDocumentProvider(); + IEditorInput input = editor.getEditorInput(); + if (docProvider == null || input == null) + return; + + IDocument document = docProvider.getDocument(input); + if (document == null) + return; + + IDocumentExtension3 docExtension; + if (document instanceof IDocumentExtension3) + docExtension = (IDocumentExtension3) document; + else + return; + + IRewriteTarget target = (IRewriteTarget) editor + .getAdapter(IRewriteTarget.class); + if (target != null) { + target.beginCompoundChange(); + } + + Edit.EditFactory factory = new Edit.EditFactory(document); + + try { + runInternal(selection, docExtension, factory); + + } catch (BadLocationException e) { + // can happen on concurrent modification, deletion etc. of the + // document + // -> don't complain, just bail out + } catch (BadPartitioningException e) { + // should not happen + Assert.isTrue(false, "bad partitioning"); //$NON-NLS-1$ + } finally { + factory.release(); + + if (target != null) { + target.endCompoundChange(); + } + } + } + + /** + * Calls perform on all Edits in + * edits. + * + * @param edits + * a list of Edits + * @throws BadLocationException + * if an Edit threw such an exception. + */ + protected void executeEdits(List edits) throws BadLocationException { + for (Iterator it = edits.iterator(); it.hasNext();) { + Edit edit = (Edit) it.next(); + edit.perform(); + } + } + + /** + * Ensures that the editor is modifyable. If the editor is an instance of + * ITextEditorExtension2, its + * validateEditorInputState method is called, otherwise, the + * result of isEditable is returned. + * + * @param editor + * the editor to be checked + * @return true if the editor is editable, false + * otherwise + */ + protected boolean ensureEditable(ITextEditor editor) { + Assert.isNotNull(editor); + + if (editor instanceof ITextEditorExtension2) { + ITextEditorExtension2 ext = (ITextEditorExtension2) editor; + return ext.validateEditorInputState(); + } + + return editor.isEditable(); + } + + /* + * @see org.eclipse.ui.texteditor.IUpdate#update() + */ + public void update() { + super.update(); + + if (isEnabled()) { + if (!canModifyEditor() || !isValidSelection(getCurrentSelection())) + setEnabled(false); + } + } + + /** + * Returns the editor's selection, or null if no selection + * can be obtained or the editor is null. + * + * @return the selection of the action's editor, or null + */ + protected ITextSelection getCurrentSelection() { + ITextEditor editor = getTextEditor(); + if (editor != null) { + ISelectionProvider provider = editor.getSelectionProvider(); + if (provider != null) { + ISelection selection = provider.getSelection(); + if (selection instanceof ITextSelection) + return (ITextSelection) selection; + } + } + return null; + } + + /** + * Runs the real command once all the editor, document, and selection checks + * have succeeded. + * + * @param selection + * the current selection we are being called for + * @param docExtension + * the document extension where we get the partitioning from + * @param factory + * the edit factory we can use to create Edits + * @throws BadLocationException + * if an edition fails + * @throws BadPartitioningException + * if a partitioning call fails + */ + protected abstract void runInternal(ITextSelection selection, + IDocumentExtension3 docExtension, Edit.EditFactory factory) + throws BadLocationException, BadPartitioningException; + + /** + * Checks whether selection is valid. + * + * @param selection + * the selection to check + * @return true if the selection is valid, false + * otherwise + */ + protected abstract boolean isValidSelection(ITextSelection selection); + + /** + * Returns the text to be inserted at the selection start. + * + * @return the text to be inserted at the selection start + */ + protected String getCommentStart() { + // for now: no space story + return "/*"; //$NON-NLS-1$ + } + + /** + * Returns the text to be inserted at the selection end. + * + * @return the text to be inserted at the selection end + */ + protected String getCommentEnd() { + // for now: no space story + return "*/"; //$NON-NLS-1$ + } + +}