source: other-projects/rsyntax-textarea/src/java/org/fife/ui/rsyntaxtextarea/templates/StaticCodeTemplate.java@ 25584

Last change on this file since 25584 was 25584, checked in by davidb, 12 years ago

Initial cut an a text edit area for GLI that supports color syntax highlighting

File size: 7.0 KB
Line 
1/*
2 * 02/21/2005
3 *
4 * CodeTemplate.java - A "template" (macro) for commonly-typed code.
5 *
6 * This library is distributed under a modified BSD license. See the included
7 * RSyntaxTextArea.License.txt file for details.
8 */
9package org.fife.ui.rsyntaxtextarea.templates;
10
11import java.io.IOException;
12import java.io.ObjectInputStream;
13import javax.swing.text.BadLocationException;
14import javax.swing.text.Caret;
15import javax.swing.text.Element;
16
17import org.fife.ui.rsyntaxtextarea.RSyntaxDocument;
18import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
19import org.fife.ui.rsyntaxtextarea.RSyntaxUtilities;
20
21
22/**
23 * A code template that inserts static text before and after the caret.<p>
24 *
25 * For example, you can associate the identifier <code>forb</code>
26 * (short for "for-block") with the following code:<p>
27 *
28 * <pre>
29 * for (&lt;caret&gt;) {
30 *
31 * }
32 * </pre>
33 *
34 * Then, whenever you type <code>forb</code> followed by a trigger
35 * (e.g., a space) into a text area with this <code>CodeTemplate</code>,
36 * the code snippet is added in place of <code>forb</code>. Further,
37 * the caret is placed at the position denoted by <code>&lt;caret&gt;</code>.
38 *
39 * @author Robert Futrell
40 * @version 0.1
41 * @see CodeTemplate
42 */
43public class StaticCodeTemplate extends AbstractCodeTemplate {
44
45 private static final long serialVersionUID = 1;
46
47 /**
48 * The code inserted before the caret position.
49 */
50 private String beforeCaret;
51
52 /**
53 * The code inserted after the caret position.
54 */
55 private String afterCaret;
56
57 /**
58 * Cached value representing whether <code>beforeCaret</code> contains
59 * one or more newlines.
60 */
61 private transient int firstBeforeNewline;
62
63 /**
64 * Cached value representing whether <code>afterCaret</code> contains
65 * one or more newlines.
66 */
67 private transient int firstAfterNewline;
68
69 private static final String EMPTY_STRING = "";
70
71
72 /**
73 * Constructor. This constructor only exists to support persistance
74 * through serialization.
75 */
76 public StaticCodeTemplate() {
77 }
78
79
80 /**
81 * Constructor.
82 *
83 * @param id The ID of this code template.
84 * @param beforeCaret The text to place before the caret.
85 * @param afterCaret The text to place after the caret.
86 */
87 public StaticCodeTemplate(String id, String beforeCaret, String afterCaret){
88 super(id);
89 setBeforeCaretText(beforeCaret);
90 setAfterCaretText(afterCaret);
91 }
92
93
94 /**
95 * Returns the text that will be placed after the caret.
96 *
97 * @return The text.
98 * @see #setAfterCaretText
99 */
100 public String getAfterCaretText() {
101 return afterCaret;
102 }
103
104
105 /**
106 * Returns the text that will be placed before the caret.
107 *
108 * @return The text.
109 * @see #setBeforeCaretText
110 */
111 public String getBeforeCaretText() {
112 return beforeCaret;
113 }
114
115
116 /**
117 * Returns the "after caret" text, with each new line indented by
118 * the specified amount.
119 *
120 * @param indent The amount to indent.
121 * @return The "after caret" text.
122 */
123 private String getAfterTextIndented(String indent) {
124 return getTextIndented(getAfterCaretText(), firstAfterNewline, indent);
125 }
126
127
128 /**
129 * Returns the "before caret" text, with each new line indented by
130 * the specified amount.
131 *
132 * @param indent The amount to indent.
133 * @return The "before caret" text.
134 */
135 private String getBeforeTextIndented(String indent) {
136 return getTextIndented(getBeforeCaretText(),firstBeforeNewline,indent);
137 }
138
139
140 /**
141 * Returns text with newlines indented by the specifed amount.
142 *
143 * @param text The original text.
144 * @param firstNewline The index of the first '\n' character.
145 * @param indent The amount to indent.
146 * @return The indented text.
147 */
148 private String getTextIndented(String text,int firstNewline,String indent) {
149 if (firstNewline==-1) {
150 return text;
151 }
152 int pos = 0;
153 int old = firstNewline+1;
154 StringBuffer sb = new StringBuffer(text.substring(0, old));
155 sb.append(indent);
156 while ((pos=text.indexOf('\n', old))>-1) {
157 sb.append(text.substring(old, pos+1));
158 sb.append(indent);
159 old = pos+1;
160 }
161 if (old<text.length()) {
162 sb.append(text.substring(old));
163 }
164 return sb.toString();
165 }
166
167
168 /**
169 * Invokes this code template. The changes are made to the given text
170 * area.
171 *
172 * @param textArea The text area to operate on.
173 * @throws BadLocationException If something bad happens.
174 */
175 public void invoke(RSyntaxTextArea textArea) throws BadLocationException {
176
177 Caret c = textArea.getCaret();
178 int dot = c.getDot();
179 int mark = c.getMark();
180 int p0 = Math.min(dot, mark);
181 int p1 = Math.max(dot, mark);
182 RSyntaxDocument doc = (RSyntaxDocument)textArea.getDocument();
183 Element map = doc.getDefaultRootElement();
184
185 int lineNum = map.getElementIndex(dot);
186 Element line = map.getElement(lineNum);
187 int start = line.getStartOffset();
188 int end = line.getEndOffset()-1; // Why always "-1"?
189 String s = textArea.getText(start,end-start);
190 int len = s.length();
191
192 // endWS is the end of the leading whitespace
193 // of the current line.
194 int endWS = 0;
195 while (endWS<len && RSyntaxUtilities.isWhitespace(s.charAt(endWS))) {
196 endWS++;
197 }
198 s = s.substring(0, endWS);
199 p0 -= getID().length();
200 String beforeText = getBeforeTextIndented(s);
201 String afterText = getAfterTextIndented(s);
202 doc.replace(p0,p1-p0, beforeText+afterText, null);
203 textArea.setCaretPosition(p0+beforeText.length());
204
205 }
206
207
208 /**
209 * Called when reading a serialized version of this document. This is
210 * overridden to initialize the transient members of this class.
211 *
212 * @param in The input stream to read from.
213 * @throws ClassNotFoundException Never.
214 * @throws IOException If an IO error occurs.
215 */
216 private void readObject(ObjectInputStream in) throws ClassNotFoundException,
217 IOException {
218 in.defaultReadObject();
219 // "Resetting" before and after text to the same values will replace
220 // nulls with empty srings, and set transient "first*Newline" values.
221 setBeforeCaretText(this.beforeCaret);
222 setAfterCaretText(this.afterCaret);
223 }
224
225
226 /**
227 * Sets the text to place after the caret.
228 *
229 * @param afterCaret The text.
230 * @see #getAfterCaretText()
231 */
232 public void setAfterCaretText(String afterCaret) {
233 this.afterCaret = afterCaret==null ? EMPTY_STRING : afterCaret;
234 firstAfterNewline = this.afterCaret.indexOf('\n');
235 }
236
237
238 /**
239 * Sets the text to place before the caret.
240 *
241 * @param beforeCaret The text.
242 * @see #getBeforeCaretText()
243 */
244 public void setBeforeCaretText(String beforeCaret) {
245 this.beforeCaret = beforeCaret==null ? EMPTY_STRING : beforeCaret;
246 firstBeforeNewline = this.beforeCaret.indexOf('\n');
247 }
248
249
250 /**
251 * Returns a string representation of this template for debugging
252 * purposes.
253 *
254 * @return A string representation of this template.
255 */
256 public String toString() {
257 return "[StaticCodeTemplate: id=" + getID() +
258 ", text=" + getBeforeCaretText() + "|" + getAfterCaretText() + "]";
259 }
260
261
262}
Note: See TracBrowser for help on using the repository browser.