author | Stephen Talley <stephen.talley@oracle.com> |
Mon, 28 Mar 2011 10:53:34 -0400 | |
changeset 685 | 767674b0a2fb |
parent 219 | 57841c113efe |
permissions | -rw-r--r-- |
0 | 1 |
/* |
2 |
* CDDL HEADER START |
|
3 |
* |
|
4 |
* The contents of this file are subject to the terms of the |
|
5 |
* Common Development and Distribution License (the "License"). |
|
6 |
* You may not use this file except in compliance with the License. |
|
7 |
* |
|
8 |
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
|
9 |
* or http://www.opensolaris.org/os/licensing. |
|
10 |
* See the License for the specific language governing permissions |
|
11 |
* and limitations under the License. |
|
12 |
* |
|
13 |
* When distributing Covered Code, include this CDDL HEADER in each |
|
14 |
* file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
|
15 |
* If applicable, add the following below this CDDL HEADER, with the |
|
16 |
* fields enclosed by brackets "[]" replaced with your own identifying |
|
17 |
* information: Portions Copyright [yyyy] [name of copyright owner] |
|
18 |
* |
|
19 |
* CDDL HEADER END |
|
20 |
*/ |
|
21 |
||
22 |
/* |
|
685
767674b0a2fb
18094 s/StringBuffer/StringBuilder/g
Stephen Talley <stephen.talley@oracle.com>
parents:
219
diff
changeset
|
23 |
* Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. |
0 | 24 |
*/ |
25 |
||
219
57841c113efe
6788 package names should share o.o.o.vp prefix
Stephen Talley <stephen.talley@sun.com>
parents:
119
diff
changeset
|
26 |
package org.opensolaris.os.vp.panels.coreadm.client.swing.path; |
0 | 27 |
|
28 |
import javax.swing.text.*; |
|
29 |
||
30 |
@SuppressWarnings({"serial"}) |
|
31 |
public class PathDocument extends DefaultStyledDocument { |
|
32 |
// |
|
33 |
// Inner classes |
|
34 |
// |
|
35 |
||
36 |
protected static class TokenSearchResult { |
|
37 |
// The found token, or null if not found |
|
38 |
public String token; |
|
39 |
||
40 |
// The index of the found token, or -1 if not found |
|
41 |
public int index = -1; |
|
42 |
} |
|
43 |
||
44 |
// |
|
45 |
// Static data |
|
46 |
// |
|
47 |
||
48 |
public static final String[] TOKENS = { |
|
49 |
"%d", "%f", "%g", "%m", "%n", "%p", "%t", "%u", "%z", "%%", |
|
50 |
}; |
|
51 |
||
52 |
private static int MAX_TOKEN_LENGTH; |
|
53 |
static { |
|
54 |
for (String token : TOKENS) { |
|
55 |
if (token.length() > MAX_TOKEN_LENGTH) { |
|
56 |
MAX_TOKEN_LENGTH = token.length(); |
|
57 |
} |
|
58 |
} |
|
59 |
} |
|
60 |
||
61 |
// |
|
62 |
// Instance data |
|
63 |
// |
|
64 |
||
65 |
private TokenAttributeSetFactory factory; |
|
66 |
||
67 |
// |
|
68 |
// Constructors |
|
69 |
// |
|
70 |
||
71 |
public PathDocument(TokenAttributeSetFactory factory) { |
|
72 |
this.factory = factory; |
|
73 |
} |
|
74 |
||
75 |
// |
|
76 |
// StyledDocument methods |
|
77 |
// |
|
78 |
||
79 |
@Override |
|
80 |
public void insertString(int offset, String str, AttributeSet a) |
|
81 |
throws BadLocationException { |
|
82 |
||
83 |
// Remove newlines |
|
84 |
if (str != null) { |
|
85 |
str = str.replace('\n', ' '); |
|
86 |
} |
|
87 |
||
88 |
// If offset is in the middle of a token element, move it to the end |
|
89 |
Element element = getCharacterElement(offset); |
|
90 |
if (isToken(element)) { |
|
91 |
offset = element.getStartOffset(); |
|
92 |
} |
|
93 |
||
94 |
super.insertString(offset, str, a); |
|
95 |
||
96 |
// Define the range to search for tokens |
|
97 |
||
98 |
int start = offset; |
|
99 |
for (int i = 0; i < MAX_TOKEN_LENGTH - 1; i++) { |
|
100 |
if (start - 1 < 0 || isPartOfToken(start - 1)) { |
|
101 |
break; |
|
102 |
} |
|
103 |
start--; |
|
104 |
} |
|
105 |
||
106 |
int docLength = getLength(); |
|
107 |
int insLength = str.length(); |
|
108 |
int end = offset + insLength; |
|
109 |
for (int i = 0; i < MAX_TOKEN_LENGTH - 1; i++) { |
|
110 |
if (end >= docLength || isPartOfToken(end)) { |
|
111 |
break; |
|
112 |
} |
|
113 |
end++; |
|
114 |
} |
|
115 |
||
116 |
try { |
|
117 |
String search = getText(start, end - start); |
|
118 |
// System.out.printf("doc: \"%s\", search: \"%s\" (%d - %d)\n", |
|
119 |
// getText(0, docLength), search, start, end); |
|
120 |
int sOffset = 0; |
|
121 |
while (true) { |
|
122 |
TokenSearchResult result = findToken(search, sOffset); |
|
123 |
if (result.token == null) { |
|
124 |
break; |
|
125 |
} |
|
126 |
||
127 |
// System.out.printf("Found \"%s\" within \"%s\" at point %d\n", |
|
128 |
// result.token, search, result.index); |
|
129 |
||
130 |
AttributeSet style = factory.getAttributeSet(result.token); |
|
131 |
||
132 |
int cStart = start + result.index; |
|
133 |
int cLength = result.token.length(); |
|
134 |
setCharacterAttributes(cStart, cLength, style, true); |
|
135 |
||
136 |
// Hack -- JTextPane doesn't always display updated styles, |
|
137 |
// so force an insert/remove |
|
138 |
int cEnd = cStart + cLength; |
|
139 |
super.insertString(cEnd, " ", SimpleAttributeSet.EMPTY); |
|
140 |
super.remove(cEnd, 1); |
|
141 |
||
142 |
sOffset = start + result.index + result.token.length(); |
|
143 |
} |
|
144 |
} catch (BadLocationException e) { |
|
145 |
// XXX |
|
146 |
e.printStackTrace(); |
|
147 |
} |
|
148 |
} |
|
149 |
||
150 |
@Override |
|
151 |
public void remove(int offset, int length) throws BadLocationException { |
|
152 |
// If the beginning or end of the deleted segment overlaps a token |
|
153 |
// element, remove the entire element |
|
154 |
||
155 |
Element element = getCharacterElement(offset); |
|
156 |
if (isToken(element)) { |
|
157 |
int sOffset = element.getStartOffset(); |
|
158 |
if (sOffset != offset) { |
|
159 |
length += offset - sOffset; |
|
160 |
offset = sOffset; |
|
161 |
} |
|
162 |
} |
|
163 |
||
164 |
element = getCharacterElement(offset + length - 1); |
|
165 |
if (isToken(element)) { |
|
166 |
length = element.getEndOffset() - offset; |
|
167 |
} |
|
168 |
||
169 |
super.remove(offset, length); |
|
170 |
} |
|
171 |
||
172 |
// |
|
173 |
// PathDocument methods |
|
174 |
// |
|
175 |
||
176 |
public String getText() { |
|
177 |
int start = -1; |
|
178 |
int offset = 0; |
|
685
767674b0a2fb
18094 s/StringBuffer/StringBuilder/g
Stephen Talley <stephen.talley@oracle.com>
parents:
219
diff
changeset
|
179 |
StringBuilder buffer = new StringBuilder(); |
0 | 180 |
|
181 |
try { |
|
182 |
for (int n = getLength(); offset < n; offset++) { |
|
183 |
Element element = getCharacterElement(offset); |
|
184 |
||
185 |
if (isToken(element)) { |
|
186 |
if (start != -1) { |
|
187 |
String token = |
|
188 |
getText(start, offset - start).replace("%", "%%"); |
|
189 |
buffer.append(token); |
|
190 |
start = -1; |
|
191 |
} |
|
192 |
||
193 |
int end = element.getEndOffset(); |
|
194 |
int length = end - offset; |
|
195 |
buffer.append(getText(offset, length)); |
|
196 |
offset = end - 1; |
|
197 |
} else if (start == -1) { |
|
198 |
start = offset; |
|
199 |
} |
|
200 |
} |
|
201 |
||
202 |
if (start != -1) { |
|
203 |
String token = |
|
204 |
getText(start, offset - start).replace("%", "%%"); |
|
205 |
buffer.append(token); |
|
206 |
} |
|
207 |
} catch (BadLocationException ignore) { |
|
208 |
ignore.printStackTrace(); |
|
209 |
} |
|
210 |
||
211 |
return buffer.toString(); |
|
212 |
} |
|
213 |
||
214 |
// |
|
215 |
// Private methods |
|
216 |
// |
|
217 |
||
218 |
private TokenSearchResult findToken(String text, int offset) { |
|
219 |
TokenSearchResult result = new TokenSearchResult(); |
|
220 |
||
221 |
for (String token : TOKENS) { |
|
222 |
int i = text.indexOf(token, offset); |
|
223 |
if (i != -1 && (result.index == -1 || i < result.index)) { |
|
224 |
result.index = i; |
|
225 |
result.token = token; |
|
226 |
} |
|
227 |
} |
|
228 |
||
229 |
return result; |
|
230 |
} |
|
231 |
||
232 |
private boolean isPartOfToken(int offset) { |
|
233 |
Element element = getCharacterElement(offset); |
|
234 |
return isToken(element); |
|
235 |
} |
|
236 |
||
237 |
// |
|
238 |
// Static data |
|
239 |
// |
|
240 |
||
241 |
protected static boolean isToken(Element element) { |
|
242 |
return element.getName().equals( |
|
243 |
StyleConstants.ComponentElementName); |
|
244 |
} |
|
245 |
} |