2 * Copyright (c) 2003-2004 Christopher Lenz and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * Christopher Lenz - initial API and implementation
11 * $Id: CssAutoEditStrategy.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
14 package net.sourceforge.phpeclipse.css.ui.internal.text;
16 import net.sourceforge.phpeclipse.css.core.internal.text.CssTextUtils;
17 import net.sourceforge.phpeclipse.css.ui.CssUI;
18 import net.sourceforge.phpeclipse.css.ui.internal.CssUIPreferences;
20 import org.eclipse.jface.preference.IPreferenceStore;
21 import org.eclipse.jface.text.BadLocationException;
22 import org.eclipse.jface.text.DefaultAutoIndentStrategy;
23 import org.eclipse.jface.text.DefaultLineTracker;
24 import org.eclipse.jface.text.DocumentCommand;
25 import org.eclipse.jface.text.IDocument;
26 import org.eclipse.jface.text.ILineTracker;
27 import org.eclipse.jface.text.IRegion;
28 import org.eclipse.ui.IEditorPart;
29 import org.eclipse.ui.IWorkbenchPage;
30 import org.eclipse.ui.IWorkbenchWindow;
31 import org.eclipse.ui.PlatformUI;
32 import org.eclipse.ui.texteditor.ITextEditorExtension3;
33 import org.eclipse.ui.texteditor.ITextEditorExtension3.InsertMode;
36 * Implements various auto-editing aspects for editing CSS:
39 * Smart indenting after opening or closing a block
42 * Smart insertion of closing braces
45 * All these only operate when 'Smart Insert' mode is enabled, and the closing
46 * of braces, brackets, parenthesis and strings can be disabled in the editor
49 public class CssAutoEditStrategy extends DefaultAutoIndentStrategy {
51 // Constants ---------------------------------------------------------------
54 * Alias for the preference constant <code>EDITOR_SPACES_FOR_TABS</code>.
56 public static final String SPACES_FOR_TABS =
57 CssUIPreferences.EDITOR_SPACES_FOR_TABS;
60 * Alias for the preference constant <code>EDITOR_TAB_WIDTH</code>.
62 public static final String TAB_WIDTH =
63 CssUIPreferences.EDITOR_TAB_WIDTH;
65 // Instance Variables ------------------------------------------------------
70 private ILineTracker lineTracker;
73 * The preference store.
75 private IPreferenceStore store;
77 // Constructors ------------------------------------------------------------
80 * Default constructor.
82 public CssAutoEditStrategy() {
83 lineTracker = new DefaultLineTracker();
84 store = CssUI.getDefault().getPreferenceStore();
87 // DefaultAutoIndentStrategy Implementation --------------------------------
90 * @see org.eclipse.jface.text.IAutoEditStrategy#customizeDocumentCommand(IDocument, DocumentCommand)
92 public void customizeDocumentCommand(IDocument d, DocumentCommand c) {
93 if (isSmartInsertMode()) {
94 if (isNewLine(d, c)) {
95 smartIndentAfterNewLine(d, c);
96 } else if (c.text != null) {
97 if (c.text.length() == 1) {
98 switch (c.text.charAt(0)) {
100 smartInsertClosingBrace(d, c);
108 if (store.getBoolean(SPACES_FOR_TABS)) {
115 // Private Methods ---------------------------------------------------------
117 private void convertTabs(IDocument d, DocumentCommand c) {
118 int index = c.text.indexOf('\t');
120 StringBuffer buffer = new StringBuffer();
121 lineTracker.set(c.text);
122 int lines = lineTracker.getNumberOfLines();
124 for (int i = 0; i < lines; i++) {
125 int offset = lineTracker.getLineOffset(i);
126 int endOffset = offset + lineTracker.getLineLength(i);
127 String line = c.text.substring(offset, endOffset);
131 d.getLineInformationOfOffset(c.offset);
132 position = c.offset - firstLine.getOffset();
134 int length = line.length();
135 for (int j = 0; j < length; j++) {
136 char ch = line.charAt(j);
138 int tabWidth = getTabWidth();
139 int remainder = position % tabWidth;
140 remainder = tabWidth - remainder;
141 for (int k = 0; k < remainder; k++) {
144 position += remainder;
151 c.text = buffer.toString();
152 } catch (BadLocationException e) {
158 private String getIndentOfLine(IDocument d, int line)
159 throws BadLocationException {
161 int start = d.getLineOffset(line);
162 int end = start + d.getLineLength(line) - 1;
163 int whiteEnd = findEndOfWhiteSpace(d, start, end);
164 return d.get(start, whiteEnd - start);
166 return ""; //$NON-NLS-1$
170 private int getTabWidth() {
171 return store.getInt(TAB_WIDTH);
174 private boolean isNewLine(IDocument d, DocumentCommand c) {
175 if ((c.length == 0) && (c.text != null)) {
176 String[] delimiters = d.getLegalLineDelimiters();
177 for (int i = 0; i < delimiters.length; i++) {
178 if (c.text.equals(delimiters[i])) {
186 private boolean isSmartInsertMode() {
187 IWorkbenchWindow window =
188 PlatformUI.getWorkbench().getActiveWorkbenchWindow();
189 if (window != null) {
190 IWorkbenchPage page = window.getActivePage();
192 IEditorPart part = page.getActiveEditor();
193 if (part instanceof ITextEditorExtension3) {
194 InsertMode insertMode =
195 ((ITextEditorExtension3) part).getInsertMode();
196 return (insertMode == ITextEditorExtension3.SMART_INSERT);
203 private String createIndentation(int level) {
204 StringBuffer buf = new StringBuffer();
205 if (store.getBoolean(SPACES_FOR_TABS)) {
206 int tabWidth = getTabWidth();
207 for (int i = 0; i < level * tabWidth; i++) {
211 for (int i = 0; i < level; i++) {
215 return buf.toString();
218 private void smartInsertClosingBrace(IDocument d, DocumentCommand c) {
219 int docLength = d.getLength();
220 if ((c.offset == -1) || (docLength == 0)) {
224 int lineOffset = d.getLineInformationOfOffset(c.offset).getOffset();
225 if (c.offset == findEndOfWhiteSpace(d, lineOffset, c.offset)) {
226 int openingBraceOffset =
227 CssTextUtils.findMatchingOpeningPeer(d, c.offset - 1, '}');
228 if (openingBraceOffset >= 0) {
229 int openingBraceLine =
230 d.getLineOfOffset(openingBraceOffset);
232 new StringBuffer(getIndentOfLine(d, openingBraceLine));
234 c.length += c.offset - lineOffset;
235 c.offset = lineOffset;
236 c.text = buf.toString();
239 } catch (BadLocationException e) {
241 "Failed to smart indent after closing brace", e); //$NON-NLS-1$
245 private void smartIndentAfterNewLine(IDocument d, DocumentCommand c) {
247 int docLength = d.getLength();
248 if ((c.offset == -1) || (docLength == 0)) {
251 StringBuffer buf = new StringBuffer(c.text);
252 if ((c.offset < docLength) && (d.getChar(c.offset - 1) == '}')) {
253 // indent with the same amount used before the block was opened
254 int openingBraceOffset =
255 CssTextUtils.findMatchingOpeningPeer(d, c.offset - 2, '}');
256 if (openingBraceOffset >= 0) {
257 int openingBraceLine =
258 d.getLineOfOffset(openingBraceOffset);
259 buf.append(getIndentOfLine(d, openingBraceLine));
261 } else if ((c.offset < docLength)
262 && (d.getChar(c.offset - 1) == '{')) {
263 int previousLine = d.getLineOfOffset(c.offset);
264 buf.append(getIndentOfLine(d, previousLine));
265 buf.append(createIndentation(1));
267 int previousLine = d.getLineOfOffset(c.offset);
268 buf.append(getIndentOfLine(d, previousLine));
270 c.text = buf.toString();
271 } catch (BadLocationException e) {
273 "Failed to smart indent after new line", e); //$NON-NLS-1$