KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > texteditor > InsertLineAction


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  * Chris.Dennis@invidi.com - http://bugs.eclipse.org/bugs/show_bug.cgi?id=29027
11  *******************************************************************************/

12 package org.eclipse.ui.texteditor;
13
14 import java.util.ResourceBundle JavaDoc;
15
16 import org.eclipse.swt.custom.StyledText;
17
18 import org.eclipse.jface.text.BadLocationException;
19 import org.eclipse.jface.text.IDocument;
20 import org.eclipse.jface.text.IRegion;
21 import org.eclipse.jface.text.Position;
22 import org.eclipse.jface.text.source.ISourceViewer;
23
24 /**
25  * This action implements smart return.
26  * Instead of breaking the line where we are, we do the following:
27  * <p><b>Smart Enter</b>
28  * <ul>
29  * <li> if the caret is on a line containing any non-whitespace, a line is inserted below the
30  * current one and the caret moved to it,</li>
31  * <li> if the caret is on a whitespace-only line, a line is inserted below the current line,
32  * but the caret stays in its position.</li>
33  * </ul>
34  * </p>
35  * <p><b>Smart Enter Inverse</b>
36  * <ul>
37  * <li> if the caret is on a line containing any non-whitespace, we insert a line above the
38  * current one and move the caret to it (i.e. it stays at the same offset in the widget),</li>
39  * <li> if the caret is on a whitespace-only line, a line is inserted above the current line,
40  * but the caret stays in its logical position (i.e., it gets shifted one line down in the
41  * document, but keeps its position relative to the content following the caret).</li>
42  * </ul>
43  * </p>
44  * @since 3.0
45  */

46 public class InsertLineAction extends TextEditorAction {
47
48     /**
49      * <code>true</code> if this action inserts a line above the current (Smart Enter Inverse),
50      * <code>false</code> otherwise
51      */

52     protected boolean fAbove;
53
54     /**
55      * Creates a new smart enter action.
56      * @param bundle the resource bundle
57      * @param prefix the prefix to use to get properties from <code>bundle</code>
58      * @param textEditor the editor that the action acts upon
59      * @param above whether new lines are inserted above or below the caret's line.
60      */

61     public InsertLineAction(ResourceBundle JavaDoc bundle, String JavaDoc prefix, ITextEditor textEditor, boolean above) {
62         super(bundle, prefix, textEditor);
63         fAbove= above;
64     }
65
66     /*
67      * @see org.eclipse.ui.texteditor.TextEditorAction#update()
68      */

69     public void update() {
70         super.update();
71         if (isEnabled())
72             setEnabled(canModifyEditor());
73     }
74
75     /*
76      * @see org.eclipse.jface.action.IAction#run()
77      */

78     public void run() {
79         /*
80          * Implementation note: instead of computing any indentations needed
81          * (which we can't at this generic level), we simply insert a new
82          * line delimiter either at the end of the current line (normal) or
83          * the end of the previous line (reverse). By operating directly on
84          * the text widget, any auto-indent strategies can pick up on the
85          * delimiter and perform any content-dependent modifications.
86          */

87
88         ITextEditor ed= getTextEditor();
89         if (!(ed instanceof AbstractTextEditor))
90             return;
91
92         if (!validateEditorInputState())
93             return;
94
95         AbstractTextEditor editor= (AbstractTextEditor) ed;
96         ISourceViewer sv= editor.getSourceViewer();
97         if (sv == null)
98             return;
99
100         IDocument document= sv.getDocument();
101         if (document == null)
102             return;
103
104         StyledText st= sv.getTextWidget();
105         if (st == null || st.isDisposed())
106             return;
107
108         try {
109             // get current line
110
int widgetOffset= st.getCaretOffset();
111             int offset= AbstractTextEditor.widgetOffset2ModelOffset(sv, widgetOffset);
112             int currentLineNumber= document.getLineOfOffset(offset);
113             IRegion currentLine= document.getLineInformation(currentLineNumber);
114
115             int insertionOffset= -1;
116             if (fAbove) {
117                 if (currentLineNumber != 0) {
118                     IRegion previousLine= document.getLineInformation(currentLineNumber - 1);
119                     insertionOffset= previousLine.getOffset() + previousLine.getLength();
120                 }
121             } else {
122                 insertionOffset= currentLine.getOffset() + currentLine.getLength();
123             }
124
125             boolean updateCaret= true;
126             int widgetInsertionOffset= AbstractTextEditor.modelOffset2WidgetOffset(sv, insertionOffset);
127             if (widgetInsertionOffset == -1 && fAbove) {
128                 // assume that the previous line was not accessible
129
// (e.g. folded, or we are on line 0)
130
// -> we insert the newline at the beginning of the current line, after any leading WS
131
insertionOffset= currentLine.getOffset() + getIndentationLength(document, currentLine);
132                 widgetInsertionOffset= AbstractTextEditor.modelOffset2WidgetOffset(sv, insertionOffset);
133                 updateCaret= false;
134             }
135             if (widgetInsertionOffset == -1)
136                 return;
137
138             // mark caret
139
Position caret= new Position(insertionOffset, 0);
140             document.addPosition(caret);
141             st.setSelectionRange(widgetInsertionOffset, 0);
142
143             // operate directly on the widget
144
st.replaceTextRange(widgetInsertionOffset, 0, st.getLineDelimiter());
145
146             // restore caret unless an auto-indenter has already moved the caret
147
// then leave it alone
148
document.removePosition(caret);
149             if (updateCaret && st.getSelection().x == widgetInsertionOffset) {
150                 int widgetCaret= AbstractTextEditor.modelOffset2WidgetOffset(sv, caret.getOffset());
151                 if (widgetCaret != -1)
152                     st.setSelectionRange(widgetCaret, 0);
153                 st.showSelection();
154             }
155
156         } catch (BadLocationException e) {
157             // ignore
158
}
159     }
160
161     /**
162      * Computes the indentation length of a line.
163      *
164      * @param document the document
165      * @param line the line
166      * @return the number of whitespace characters at the beginning of
167      * <code>line</code>
168      * @throws BadLocationException on document access error
169      */

170     private int getIndentationLength(IDocument document, IRegion line) throws BadLocationException {
171         int pos= line.getOffset();
172         int max= pos + line.getLength();
173         while (pos < max) {
174             if (!Character.isWhitespace(document.getChar(pos)))
175                 break;
176             pos++;
177         }
178         return pos - line.getOffset();
179     }
180 }
181
Popular Tags