jeffliu | ec1c478 | 2006-05-24 14:16:24 +0000 | [diff] [blame] | 1 | /******************************************************************************* |
david_williams | 63edb28 | 2005-07-19 21:26:49 +0000 | [diff] [blame] | 2 | * Copyright (c) 2005 IBM Corporation and others. |
jeffliu | ec1c478 | 2006-05-24 14:16:24 +0000 | [diff] [blame] | 3 | * All rights reserved. This program and the accompanying materials |
| 4 | * are made available under the terms of the Eclipse Public License v1.0 |
david_williams | 63edb28 | 2005-07-19 21:26:49 +0000 | [diff] [blame] | 5 | * which accompanies this distribution, and is available at |
jeffliu | ec1c478 | 2006-05-24 14:16:24 +0000 | [diff] [blame] | 6 | * http://www.eclipse.org/legal/epl-v10.html |
david_williams | 63edb28 | 2005-07-19 21:26:49 +0000 | [diff] [blame] | 7 | * |
| 8 | * Contributors: |
jeffliu | ec1c478 | 2006-05-24 14:16:24 +0000 | [diff] [blame] | 9 | * IBM Corporation - initial API and implementation |
| 10 | * Jens Lukowski/Innoopract - initial renaming/restructuring |
| 11 | *******************************************************************************/ |
| 12 | |
david_williams | 63edb28 | 2005-07-19 21:26:49 +0000 | [diff] [blame] | 13 | package org.eclipse.jst.jsp.ui.internal.autoedit; |
| 14 | |
| 15 | import org.eclipse.core.runtime.Preferences; |
| 16 | import org.eclipse.jface.text.BadLocationException; |
nitind | 893cb9b | 2005-08-11 03:24:01 +0000 | [diff] [blame] | 17 | import org.eclipse.jface.text.ConfigurableLineTracker; |
david_williams | 63edb28 | 2005-07-19 21:26:49 +0000 | [diff] [blame] | 18 | import org.eclipse.jface.text.DocumentCommand; |
| 19 | import org.eclipse.jface.text.IAutoEditStrategy; |
| 20 | import org.eclipse.jface.text.IDocument; |
nitind | 893cb9b | 2005-08-11 03:24:01 +0000 | [diff] [blame] | 21 | import org.eclipse.jface.text.ILineTracker; |
david_williams | 63edb28 | 2005-07-19 21:26:49 +0000 | [diff] [blame] | 22 | import org.eclipse.jface.text.IRegion; |
nitind | 893cb9b | 2005-08-11 03:24:01 +0000 | [diff] [blame] | 23 | import org.eclipse.jface.text.TextUtilities; |
| 24 | import org.eclipse.jst.jsp.ui.internal.Logger; |
| 25 | import org.eclipse.ui.IEditorPart; |
| 26 | import org.eclipse.ui.IWorkbenchPage; |
| 27 | import org.eclipse.ui.IWorkbenchWindow; |
| 28 | import org.eclipse.ui.PlatformUI; |
| 29 | import org.eclipse.ui.texteditor.ITextEditor; |
| 30 | import org.eclipse.ui.texteditor.ITextEditorExtension3; |
david_williams | 63edb28 | 2005-07-19 21:26:49 +0000 | [diff] [blame] | 31 | import org.eclipse.wst.html.core.internal.HTMLCorePlugin; |
| 32 | import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames; |
david_williams | 63edb28 | 2005-07-19 21:26:49 +0000 | [diff] [blame] | 33 | |
| 34 | /** |
| 35 | * AutoEditStrategy to handle characters inserted when Tab key is pressed |
| 36 | */ |
| 37 | public class AutoEditStrategyForTabs implements IAutoEditStrategy { |
nitind | 893cb9b | 2005-08-11 03:24:01 +0000 | [diff] [blame] | 38 | private final String TAB_CHARACTER = "\t"; //$NON-NLS-1$ |
david_williams | 63edb28 | 2005-07-19 21:26:49 +0000 | [diff] [blame] | 39 | |
| 40 | public void customizeDocumentCommand(IDocument document, DocumentCommand command) { |
nitind | 893cb9b | 2005-08-11 03:24:01 +0000 | [diff] [blame] | 41 | // if not in smart insert mode just ignore |
| 42 | if (!isSmartInsertMode()) |
| 43 | return; |
| 44 | |
david_williams | 63edb28 | 2005-07-19 21:26:49 +0000 | [diff] [blame] | 45 | // spaces for tab character |
nitind | 893cb9b | 2005-08-11 03:24:01 +0000 | [diff] [blame] | 46 | if (command.length == 0 && command.text != null && command.text.length() > 0 && command.text.indexOf(TAB_CHARACTER) != -1) |
david_williams | 63edb28 | 2005-07-19 21:26:49 +0000 | [diff] [blame] | 47 | smartInsertForTab(command, document); |
| 48 | } |
| 49 | |
| 50 | /** |
| 51 | * Insert spaces for tabs |
| 52 | * |
| 53 | * @param command |
| 54 | */ |
| 55 | private void smartInsertForTab(DocumentCommand command, IDocument document) { |
| 56 | // tab key was pressed. now check preferences to see if need to insert |
| 57 | // spaces instead of tab |
nitind | 893cb9b | 2005-08-11 03:24:01 +0000 | [diff] [blame] | 58 | int indentationWidth = getIndentationWidth(); |
| 59 | if (indentationWidth > -1) { |
| 60 | String originalText = command.text; |
| 61 | StringBuffer newText = new StringBuffer(originalText); |
david_williams | 63edb28 | 2005-07-19 21:26:49 +0000 | [diff] [blame] | 62 | |
nitind | 893cb9b | 2005-08-11 03:24:01 +0000 | [diff] [blame] | 63 | // determine where in line this command begins |
| 64 | int lineOffset = -1; |
| 65 | try { |
| 66 | IRegion lineInfo = document.getLineInformationOfOffset(command.offset); |
| 67 | lineOffset = command.offset - lineInfo.getOffset(); |
| 68 | } catch (BadLocationException e) { |
| 69 | Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e); |
david_williams | 63edb28 | 2005-07-19 21:26:49 +0000 | [diff] [blame] | 70 | } |
| 71 | |
nitind | 893cb9b | 2005-08-11 03:24:01 +0000 | [diff] [blame] | 72 | ILineTracker lineTracker = getLineTracker(document, originalText); |
| 73 | |
| 74 | int startIndex = 0; |
| 75 | int index = newText.indexOf(TAB_CHARACTER); |
| 76 | while (index != -1) { |
| 77 | String indent = getIndentString(indentationWidth, lineOffset, lineTracker, index); |
| 78 | |
| 79 | // replace \t character with spaces |
| 80 | newText.replace(index, index + 1, indent); |
| 81 | if (lineTracker != null) { |
| 82 | try { |
| 83 | lineTracker.replace(index, 1, indent); |
| 84 | } catch (BadLocationException e) { |
| 85 | // if something goes wrong with replacing text, just |
| 86 | // reset to current string |
| 87 | lineTracker.set(newText.toString()); |
| 88 | Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e); |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | startIndex = index + indent.length(); |
| 93 | index = newText.indexOf(TAB_CHARACTER, startIndex); |
| 94 | } |
| 95 | command.text = newText.toString(); |
david_williams | 63edb28 | 2005-07-19 21:26:49 +0000 | [diff] [blame] | 96 | } |
| 97 | } |
nitind | 893cb9b | 2005-08-11 03:24:01 +0000 | [diff] [blame] | 98 | |
| 99 | /** |
| 100 | * Calculate number of spaces for next tab stop |
| 101 | */ |
| 102 | private String getIndentString(int indentationWidth, int lineOffset, ILineTracker lineTracker, int index) { |
| 103 | int indentSize = indentationWidth; |
| 104 | int offsetInLine = -1; |
| 105 | if (lineTracker != null) { |
| 106 | try { |
| 107 | IRegion lineInfo = lineTracker.getLineInformationOfOffset(index); |
| 108 | if (lineInfo.getOffset() == 0 && lineOffset > -1) |
| 109 | offsetInLine = lineOffset + index; |
| 110 | else |
| 111 | offsetInLine = index - lineInfo.getOffset(); |
| 112 | } catch (BadLocationException e) { |
| 113 | Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e); |
| 114 | } |
| 115 | } else { |
| 116 | if (lineOffset > -1) { |
| 117 | offsetInLine = lineOffset + index; |
| 118 | } |
| 119 | } |
nitind | acb60bf | 2005-09-14 23:47:20 +0000 | [diff] [blame] | 120 | if (offsetInLine > -1 && indentationWidth > 0) { |
nitind | 893cb9b | 2005-08-11 03:24:01 +0000 | [diff] [blame] | 121 | int remainder = offsetInLine % indentationWidth; |
| 122 | indentSize = indentationWidth - remainder; |
| 123 | } |
| 124 | |
| 125 | StringBuffer indent = new StringBuffer(); |
| 126 | for (int i = 0; i < indentSize; i++) |
| 127 | indent.append(' '); |
| 128 | return indent.toString(); |
| 129 | } |
| 130 | |
| 131 | /** |
| 132 | * Set up a line tracker for text within command if text is multi-line |
| 133 | */ |
| 134 | private ILineTracker getLineTracker(IDocument document, String originalText) { |
| 135 | ConfigurableLineTracker lineTracker = null; |
| 136 | int[] delims = TextUtilities.indexOf(document.getLegalLineDelimiters(), originalText, 0); |
| 137 | if (delims[0] != -1 || delims[1] != -1) { |
| 138 | lineTracker = new ConfigurableLineTracker(document.getLegalLineDelimiters()); |
| 139 | lineTracker.set(originalText); |
| 140 | } |
| 141 | return lineTracker; |
| 142 | } |
| 143 | |
| 144 | /** |
| 145 | * Return true if active editor is in smart insert mode, false otherwise |
| 146 | * |
| 147 | * @return |
| 148 | */ |
| 149 | private boolean isSmartInsertMode() { |
| 150 | boolean isSmartInsertMode = false; |
| 151 | |
| 152 | ITextEditor textEditor = null; |
| 153 | IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); |
| 154 | if (window != null) { |
| 155 | IWorkbenchPage page = window.getActivePage(); |
| 156 | if (page != null) { |
| 157 | IEditorPart editor = page.getActiveEditor(); |
| 158 | if (editor != null) { |
| 159 | if (editor instanceof ITextEditor) |
| 160 | textEditor = (ITextEditor) editor; |
| 161 | else |
| 162 | textEditor = (ITextEditor) editor.getAdapter(ITextEditor.class); |
| 163 | } |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | // check if smart insert mode |
| 168 | if (textEditor instanceof ITextEditorExtension3 && ((ITextEditorExtension3) textEditor).getInsertMode() == ITextEditorExtension3.SMART_INSERT) |
| 169 | isSmartInsertMode = true; |
| 170 | return isSmartInsertMode; |
| 171 | } |
| 172 | |
| 173 | /** |
| 174 | * Returns indentation width if using spaces for indentation, -1 otherwise |
| 175 | * |
| 176 | * @return |
| 177 | */ |
| 178 | private int getIndentationWidth() { |
| 179 | int width = -1; |
| 180 | |
| 181 | Preferences preferences = HTMLCorePlugin.getDefault().getPluginPreferences(); |
| 182 | if (HTMLCorePreferenceNames.SPACE.equals(preferences.getString(HTMLCorePreferenceNames.INDENTATION_CHAR))) |
| 183 | width = preferences.getInt(HTMLCorePreferenceNames.INDENTATION_SIZE); |
| 184 | |
| 185 | return width; |
| 186 | } |
david_williams | 63edb28 | 2005-07-19 21:26:49 +0000 | [diff] [blame] | 187 | } |