| /******************************************************************************* |
| * Copyright (c) 2005, 2007 IBM Corporation and others. |
| * 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 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Jens Lukowski/Innoopract - initial renaming/restructuring |
| *******************************************************************************/ |
| package org.eclipse.wst.jsdt.web.ui.internal.autoedit; |
| |
| import org.eclipse.core.runtime.Preferences; |
| import org.eclipse.jface.text.BadLocationException; |
| import org.eclipse.jface.text.ConfigurableLineTracker; |
| import org.eclipse.jface.text.DocumentCommand; |
| import org.eclipse.jface.text.IAutoEditStrategy; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.ILineTracker; |
| import org.eclipse.jface.text.IRegion; |
| import org.eclipse.jface.text.TextUtilities; |
| import org.eclipse.ui.IEditorPart; |
| import org.eclipse.ui.IWorkbenchPage; |
| import org.eclipse.ui.IWorkbenchWindow; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.texteditor.ITextEditor; |
| import org.eclipse.ui.texteditor.ITextEditorExtension3; |
| import org.eclipse.wst.html.core.internal.HTMLCorePlugin; |
| import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames; |
| import org.eclipse.wst.jsdt.web.ui.internal.Logger; |
| |
| /** |
| * |
| |
| * Provisional API: This class/interface is part of an interim API that is still under development and expected to |
| * change significantly before reaching stability. It is being made available at this early stage to solicit feedback |
| * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken |
| * (repeatedly) as the API evolves. |
| */ |
| public class AutoEditStrategyForTabs implements IAutoEditStrategy { |
| private final String TAB_CHARACTER = "\t"; //$NON-NLS-1$ |
| |
| public void customizeDocumentCommand(IDocument document, DocumentCommand command) { |
| // if not in smart insert mode just ignore |
| if (!isSmartInsertMode()) { |
| return; |
| } |
| // spaces for tab character |
| if (command.length == 0 && command.text != null && command.text.length() > 0 && command.text.indexOf(TAB_CHARACTER) != -1) { |
| smartInsertForTab(command, document); |
| } |
| } |
| |
| /** |
| * Returns indentation width if using spaces for indentation, -1 otherwise |
| * |
| * @return |
| */ |
| private int getIndentationWidth() { |
| int width = -1; |
| Preferences preferences = HTMLCorePlugin.getDefault().getPluginPreferences(); |
| if (HTMLCorePreferenceNames.SPACE.equals(preferences.getString(HTMLCorePreferenceNames.INDENTATION_CHAR))) { |
| width = preferences.getInt(HTMLCorePreferenceNames.INDENTATION_SIZE); |
| } |
| return width; |
| } |
| |
| /** |
| * Calculate number of spaces for next tab stop |
| */ |
| private String getIndentString(int indentationWidth, int lineOffset, ILineTracker lineTracker, int index) { |
| int indentSize = indentationWidth; |
| int offsetInLine = -1; |
| if (lineTracker != null) { |
| try { |
| IRegion lineInfo = lineTracker.getLineInformationOfOffset(index); |
| if (lineInfo.getOffset() == 0 && lineOffset > -1) { |
| offsetInLine = lineOffset + index; |
| } else { |
| offsetInLine = index - lineInfo.getOffset(); |
| } |
| } catch (BadLocationException e) { |
| Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e); |
| } |
| } else { |
| if (lineOffset > -1) { |
| offsetInLine = lineOffset + index; |
| } |
| } |
| if (offsetInLine > -1 && indentationWidth > 0) { |
| int remainder = offsetInLine % indentationWidth; |
| indentSize = indentationWidth - remainder; |
| } |
| StringBuffer indent = new StringBuffer(); |
| for (int i = 0; i < indentSize; i++) { |
| indent.append(' '); |
| } |
| return indent.toString(); |
| } |
| |
| /** |
| * Set up a line tracker for text within command if text is multi-line |
| */ |
| private ILineTracker getLineTracker(IDocument document, String originalText) { |
| ConfigurableLineTracker lineTracker = null; |
| int[] delims = TextUtilities.indexOf(document.getLegalLineDelimiters(), originalText, 0); |
| if (delims[0] != -1 || delims[1] != -1) { |
| lineTracker = new ConfigurableLineTracker(document.getLegalLineDelimiters()); |
| lineTracker.set(originalText); |
| } |
| return lineTracker; |
| } |
| |
| /** |
| * Return true if active editor is in smart insert mode, false otherwise |
| * |
| * @return |
| */ |
| private boolean isSmartInsertMode() { |
| boolean isSmartInsertMode = false; |
| ITextEditor textEditor = null; |
| IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); |
| if (window != null) { |
| IWorkbenchPage page = window.getActivePage(); |
| if (page != null) { |
| IEditorPart editor = page.getActiveEditor(); |
| if (editor != null) { |
| if (editor instanceof ITextEditor) { |
| textEditor = (ITextEditor) editor; |
| } else { |
| textEditor = (ITextEditor) editor.getAdapter(ITextEditor.class); |
| } |
| } |
| } |
| } |
| // check if smart insert mode |
| if (textEditor instanceof ITextEditorExtension3 && ((ITextEditorExtension3) textEditor).getInsertMode() == ITextEditorExtension3.SMART_INSERT) { |
| isSmartInsertMode = true; |
| } |
| return isSmartInsertMode; |
| } |
| |
| /** |
| * Insert spaces for tabs |
| * |
| * @param command |
| */ |
| private void smartInsertForTab(DocumentCommand command, IDocument document) { |
| // tab key was pressed. now check preferences to see if need to insert |
| // spaces instead of tab |
| int indentationWidth = getIndentationWidth(); |
| if (indentationWidth > -1) { |
| String originalText = command.text; |
| StringBuffer newText = new StringBuffer(originalText); |
| // determine where in line this command begins |
| int lineOffset = -1; |
| try { |
| IRegion lineInfo = document.getLineInformationOfOffset(command.offset); |
| lineOffset = command.offset - lineInfo.getOffset(); |
| } catch (BadLocationException e) { |
| Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e); |
| } |
| ILineTracker lineTracker = getLineTracker(document, originalText); |
| int startIndex = 0; |
| int index = newText.indexOf(TAB_CHARACTER); |
| while (index != -1) { |
| String indent = getIndentString(indentationWidth, lineOffset, lineTracker, index); |
| // replace \t character with spaces |
| newText.replace(index, index + 1, indent); |
| if (lineTracker != null) { |
| try { |
| lineTracker.replace(index, 1, indent); |
| } catch (BadLocationException e) { |
| // if something goes wrong with replacing text, just |
| // reset to current string |
| lineTracker.set(newText.toString()); |
| Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e); |
| } |
| } |
| startIndex = index + indent.length(); |
| index = newText.indexOf(TAB_CHARACTER, startIndex); |
| } |
| command.text = newText.toString(); |
| } |
| } |
| } |