blob: 8379c9e18150ef884da6aaf3dcc4b97ac53ae356 [file] [log] [blame]
jeffliuec1c4782006-05-24 14:16:24 +00001/*******************************************************************************
david_williams63edb282005-07-19 21:26:49 +00002 * Copyright (c) 2005 IBM Corporation and others.
jeffliuec1c4782006-05-24 14:16:24 +00003 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
david_williams63edb282005-07-19 21:26:49 +00005 * which accompanies this distribution, and is available at
jeffliuec1c4782006-05-24 14:16:24 +00006 * http://www.eclipse.org/legal/epl-v10.html
david_williams63edb282005-07-19 21:26:49 +00007 *
8 * Contributors:
jeffliuec1c4782006-05-24 14:16:24 +00009 * IBM Corporation - initial API and implementation
10 * Jens Lukowski/Innoopract - initial renaming/restructuring
11 *******************************************************************************/
12
david_williams63edb282005-07-19 21:26:49 +000013package org.eclipse.jst.jsp.ui.internal.autoedit;
14
15import org.eclipse.core.runtime.Preferences;
16import org.eclipse.jface.text.BadLocationException;
nitind893cb9b2005-08-11 03:24:01 +000017import org.eclipse.jface.text.ConfigurableLineTracker;
david_williams63edb282005-07-19 21:26:49 +000018import org.eclipse.jface.text.DocumentCommand;
19import org.eclipse.jface.text.IAutoEditStrategy;
20import org.eclipse.jface.text.IDocument;
nitind893cb9b2005-08-11 03:24:01 +000021import org.eclipse.jface.text.ILineTracker;
david_williams63edb282005-07-19 21:26:49 +000022import org.eclipse.jface.text.IRegion;
nitind893cb9b2005-08-11 03:24:01 +000023import org.eclipse.jface.text.TextUtilities;
24import org.eclipse.jst.jsp.ui.internal.Logger;
25import org.eclipse.ui.IEditorPart;
26import org.eclipse.ui.IWorkbenchPage;
27import org.eclipse.ui.IWorkbenchWindow;
28import org.eclipse.ui.PlatformUI;
29import org.eclipse.ui.texteditor.ITextEditor;
30import org.eclipse.ui.texteditor.ITextEditorExtension3;
david_williams63edb282005-07-19 21:26:49 +000031import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
32import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
david_williams63edb282005-07-19 21:26:49 +000033
34/**
35 * AutoEditStrategy to handle characters inserted when Tab key is pressed
36 */
37public class AutoEditStrategyForTabs implements IAutoEditStrategy {
nitind893cb9b2005-08-11 03:24:01 +000038 private final String TAB_CHARACTER = "\t"; //$NON-NLS-1$
david_williams63edb282005-07-19 21:26:49 +000039
40 public void customizeDocumentCommand(IDocument document, DocumentCommand command) {
nitind893cb9b2005-08-11 03:24:01 +000041 // if not in smart insert mode just ignore
42 if (!isSmartInsertMode())
43 return;
44
david_williams63edb282005-07-19 21:26:49 +000045 // spaces for tab character
nitind893cb9b2005-08-11 03:24:01 +000046 if (command.length == 0 && command.text != null && command.text.length() > 0 && command.text.indexOf(TAB_CHARACTER) != -1)
david_williams63edb282005-07-19 21:26:49 +000047 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
nitind893cb9b2005-08-11 03:24:01 +000058 int indentationWidth = getIndentationWidth();
59 if (indentationWidth > -1) {
60 String originalText = command.text;
61 StringBuffer newText = new StringBuffer(originalText);
david_williams63edb282005-07-19 21:26:49 +000062
nitind893cb9b2005-08-11 03:24:01 +000063 // 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_williams63edb282005-07-19 21:26:49 +000070 }
71
nitind893cb9b2005-08-11 03:24:01 +000072 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_williams63edb282005-07-19 21:26:49 +000096 }
97 }
nitind893cb9b2005-08-11 03:24:01 +000098
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 }
nitindacb60bf2005-09-14 23:47:20 +0000120 if (offsetInLine > -1 && indentationWidth > 0) {
nitind893cb9b2005-08-11 03:24:01 +0000121 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_williams63edb282005-07-19 21:26:49 +0000187}