/******************************************************************************* * Copyright (c) 2009 Andrey Loskutov. * All rights reserved. This program and the accompanying materials * are 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 * Contributor: Andrey Loskutov - initial API and implementation *******************************************************************************/ package de.loskutov.anyedit.actions; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.viewers.ISelection; import de.loskutov.anyedit.util.LineReplaceResult; import de.loskutov.anyedit.util.TextReplaceResultSet; public abstract class AbstractReplaceAction extends AbstractTextAction { /** contains possible error information during replace */ protected boolean shouldStopReplace; @Override protected TextReplaceResultSet estimateActionRange(IDocument doc){ TextReplaceResultSet result = new TextReplaceResultSet(); if (doc == null || getEditor().getSelectionProvider() == null) { return result; } ISelection selection = getEditor().getSelectionProvider().getSelection(); if(selection == null || !(selection instanceof ITextSelection)){ return result; } ITextSelection textSelection = (ITextSelection)selection; if(textSelection.isEmpty()){ return result; } result.setStartLine(textSelection.getStartLine()); result.setStopLine(textSelection.getEndLine()); return result; } @Override protected void doTextOperation(IDocument doc, String actionID, TextReplaceResultSet resultSet) throws BadLocationException { ITextSelection textSelection = (ITextSelection) getEditor() .getSelectionProvider().getSelection(); int actionKey = getActionKey(actionID); int startSelection = textSelection.getOffset(); int stopSelection = startSelection + textSelection.getLength(); int maxNbr = resultSet.getStartLine() + resultSet.getNumberOfLines(); for (int i = resultSet.getStartLine(); i < maxNbr; i++) { IRegion lineInfo = doc.getLineInformation(i); boolean useStartLineOffset = lineInfo.getOffset() > startSelection; int startReplaceIndex; if(useStartLineOffset){ startReplaceIndex = 0; } else { startReplaceIndex = startSelection - lineInfo.getOffset(); } int stopReplace; boolean useStopLineOffset = lineInfo.getOffset() + lineInfo.getLength() > stopSelection; if(useStopLineOffset){ stopReplace = stopSelection - lineInfo.getOffset(); } else { stopReplace = lineInfo.getLength(); } int rangeToReplace = stopReplace - startReplaceIndex; if(rangeToReplace <= 0){ resultSet.add(null); continue; } String line = doc.get( lineInfo.getOffset() + startReplaceIndex, rangeToReplace); if(line == null){ resultSet.add(null); continue; } // call abstract replace operation String newText = performReplace(line, actionKey); if(shouldStopReplace) { shouldStopReplace = false; resultSet.clear(); return; } boolean changed = !line.equals(newText); if(changed){ LineReplaceResult result = new LineReplaceResult(); result.startReplaceIndex = startReplaceIndex; result.rangeToReplace = rangeToReplace; result.textToReplace = newText; resultSet.add(result); } else { resultSet.add(null); } } } /** * Does custom replace operation. * @param line text to "replace" * @param actionKey any one action key as delivered by getActionKey(String) * method * @return "replace" result or old unchanged string, if replace was not performed */ protected abstract String performReplace(String line, int actionKey); /** * Mapping between String actions and "smarter" custom int's for * inernal (in performReplace() method) use only! * @param actionID action id <b>starts</b> with one of AbstractTextAction.ACTION_ID_ * constants (it starts with the constant cause we have multiple actions * there which are used once for key bindings and once for editor actions). * @return any one int value for given action */ protected abstract int getActionKey(String actionID); }