001: package snow.texteditor;
002:
003: import snow.Basics;
004: import javax.swing.text.*;
005: import javax.swing.*;
006: import java.awt.*;
007: import java.util.*;
008: import java.io.*;
009:
010: public final class DocumentUtils {
011: private DocumentUtils() {
012: }
013:
014: /** Indent the lines between the given document positions (NOT LINE NUMBERS !)
015: */
016: public static void indentLines(Document doc, int fromPos, int toPos) {
017: int lineStart = getLineNumber(doc, fromPos);
018: int lineEnd = getLineNumber(doc, toPos);
019:
020: for (int line = lineStart; line <= lineEnd; line++) {
021: try {
022: Element li = doc.getDefaultRootElement().getElement(
023: line);
024: doc.insertString(li.getStartOffset(), " ", li
025: .getAttributes());
026: } catch (Exception e) {
027: e.printStackTrace();
028: }
029: }
030: }
031:
032: /** Indents the lines between the given document positions (positions, NOT LINE NUMBERS !)
033: */
034: public static void unindentLines(Document doc, int fromPos,
035: int toPos) {
036: int lineStart = getLineNumber(doc, fromPos);
037: int lineEnd = getLineNumber(doc, toPos);
038:
039: for (int line = lineStart; line <= lineEnd; line++) {
040: try {
041: Element li = doc.getDefaultRootElement().getElement(
042: line);
043: char ci = doc.getText(li.getStartOffset(), 1).charAt(0);
044: if (Character.isWhitespace(ci) && ci != '\n') {
045: doc.remove(li.getStartOffset(), 1);
046: }
047: } catch (Exception e) {
048: e.printStackTrace();
049: }
050: }
051: }
052:
053: /** comment out the lines between the given document positions (NOT LINE NUMBERS !)
054: * comment out means adding "//" at the beginning of the line.
055: * the uncommentout is the reverse operation
056: */
057: public static void commentOutLines(Document doc, int fromPos,
058: int toPos) {
059: int lineStart = getLineNumber(doc, fromPos);
060: int lineEnd = getLineNumber(doc, toPos);
061:
062: for (int line = lineStart; line <= lineEnd; line++) {
063: try {
064: Element li = doc.getDefaultRootElement().getElement(
065: line);
066: doc.insertString(li.getStartOffset(), "//", li
067: .getAttributes());
068: } catch (Exception e) {
069: e.printStackTrace();
070: }
071: }
072: }
073:
074: /** uncomment out the lines between the given document positions (NOT LINE NUMBERS !)
075: * reverse operation of commentOut. This only removes // at the beginning
076: */
077: public static void unCommentOutLines(Document doc, int fromPos,
078: int toPos) {
079: int lineStart = getLineNumber(doc, fromPos);
080: int lineEnd = getLineNumber(doc, toPos);
081:
082: for (int line = lineStart; line <= lineEnd; line++) {
083: try {
084: Element li = doc.getDefaultRootElement().getElement(
085: line);
086: if (li.getEndOffset() - li.getStartOffset() > 1) {
087: if (doc.getText(li.getStartOffset(), 2)
088: .equals("//")) {
089: doc.remove(li.getStartOffset(), 2);
090: }
091: }
092: } catch (Exception e) {
093: e.printStackTrace();
094: }
095: }
096: }
097:
098: /** normally search an {, with close }
099: */
100: public static int getPreviousOpeningPosition(SimpleDocument doc,
101: char toSearch, char close, int from, int skipCount) {
102: int found = 0;
103: l1: for (int pos = from; pos >= 0; pos--) {
104: char c = doc.getCharAt(pos);
105: if (c == close)
106: found--;
107: if (c == toSearch)
108: found++;
109: if (found > skipCount)
110: return pos;
111: }
112: return -1;
113: }
114:
115: /** take a java single word yyy, NOT xxx.yyy.zzz like the standard editor kit
116: pos must be in the word or at the beginning.
117: give pos-1 if you want the word before the caret.
118: */
119: public static String getWordAt(SimpleDocument doc, int pos) {
120: try {
121: // search for the bounds of a word
122: int start = pos;
123: int end = pos;
124: l1: for (start = pos; start >= 0; start--) {
125: char c = doc.getCharAt(start);
126: if (!Character.isJavaIdentifierPart(c)) {
127: if (Character.isJavaIdentifierStart(c)) // ? sense ? can be part if not start ?
128: {
129: // accept it
130: break l1;
131: } else {
132: // refuse it
133: start++;
134: break l1;
135: }
136: }
137: }
138:
139: l2: for (end = pos; end < doc.getLength(); end++) {
140: char c = doc.getCharAt(end);
141: if (!Character.isJavaIdentifierPart(c))
142: break l2;
143: }
144:
145: //System.out.println("text from "+start+" to "+end);
146: if (start < 0)
147: start = 0;
148: if (start >= end)
149: return null; // not found
150:
151: return doc.getText(start, end - start);
152: } catch (Exception e) {
153: e.printStackTrace();
154: }
155: return null;
156: }
157:
158: /** used to find the id on which the mouse is in the editor.
159: */
160: public static int getWordEndPosition(SimpleDocument doc,
161: int posInWord) {
162: try {
163: // search for the bounds of a word
164: int end = posInWord;
165:
166: l2: for (; end < doc.getLength(); end++) {
167: char c = doc.getCharAt(end);
168: if (!Character.isJavaIdentifierPart(c))
169: break l2;
170: }
171:
172: //System.out.println("text from "+start+" to "+end);
173: return end;
174: } catch (Exception e) {
175: e.printStackTrace();
176: }
177: return -1;
178: }
179:
180: public static void main(String[] a) {
181: String str = " hello ";
182: for (int i = 0; i < str.length(); i++) {
183: System.out.println(Character.isJavaIdentifierPart(str
184: .charAt(i)));
185: }
186: }
187:
188: /** @return the line number corresponding to the document position.
189: * the first line has index 0.
190: */
191: public static int getLineNumber(Document doc, int pos) {
192: // a document is modelled as a list of lines (Element)=> index = line number
193: Element map = doc.getDefaultRootElement();
194: int line = map.getElementIndex(pos);
195: return line;
196: }
197:
198: /* not used alone... always together with the line. so we minimize mismatch with offset !
199: * @return the column, first is 0
200: * use getLineColumnNumbers() to directly receive line and column numbers !
201: *
202: public static int getColumnNumber_(Document doc, int pos)
203: {
204: Element map = doc.getDefaultRootElement();
205: int line = map.getElementIndex(pos);
206: Element lineElt = map.getElement(line);
207: return pos-lineElt.getStartOffset();
208: }*/
209:
210: /** @return the {line,column}, first is 0
211: */
212: public static int[] getLineColumnNumbers(Document doc, int pos) {
213: Element map = doc.getDefaultRootElement();
214: int line = map.getElementIndex(pos);
215: Element lineElt = map.getElement(line);
216: return new int[] { line, pos - lineElt.getStartOffset() };
217: }
218:
219: public static int getLineStartOffsetForPos(StyledDocument doc,
220: int pos) {
221: // a document is modelled as a list of lines (Element)=> index = line number
222: Element line = doc.getParagraphElement(pos);
223: return line.getStartOffset();
224: }
225:
226: public static void deleteLineAtPos(StyledDocument doc, int pos)
227: throws Exception {
228: Element line = doc.getParagraphElement(pos);
229: doc.remove(line.getStartOffset(), line.getEndOffset()
230: - line.getStartOffset());
231: }
232:
233: /** @return the text at the line containing the given position. With eventual carriage return and line feeds...
234: */
235: public static String getTextOfLineAtPosition(StyledDocument doc,
236: int pos) {
237: // a document is modelled as a list of lines (Element)=> index = line number
238: Element line = doc.getParagraphElement(pos);
239: try {
240: return doc.getText(line.getStartOffset(), line
241: .getEndOffset()
242: - line.getStartOffset());
243: } catch (Exception e) {
244: return null;
245: }
246: }
247:
248: /** @return the text at the line containing the given position
249: */
250: public static String getTextOfLineAtPosition_onlyUpToPos(
251: StyledDocument doc, int pos) {
252: // a document is modelled as a list of lines (Element)=> index = line number
253: Element line = doc.getParagraphElement(pos);
254: try {
255: return doc.getText(line.getStartOffset(), pos
256: - line.getStartOffset());
257: } catch (Exception e) {
258: return null;
259: }
260: }
261:
262: /** @return the text at the line containing the given position
263: */
264: public static String getTextOfLine(Document doc, int line) {
265: // a document is modelled as a list of lines (Element)=> index = line number
266: Element map = doc.getDefaultRootElement();
267: Element lineElt = map.getElement(line);
268: try {
269: return doc.getText(lineElt.getStartOffset(), lineElt
270: .getEndOffset()
271: - lineElt.getStartOffset());
272: } catch (Exception e) {
273: return null;
274: }
275: }
276:
277: /** -1 if not found open = '{', close = '}'
278: TODO: ignore comments and string quotes ...
279: */
280: public static int getPositionOfCorrespondingOpeningBrace(char open,
281: char close, SimpleDocument doc, int pos) {
282: int level = 0;
283: try {
284: for (int i = pos - 1; i >= 0; i--) {
285: char ci = doc.getCharAt(i);
286: if (ci == close)
287: level++;
288: if (ci == open) {
289: if (level <= 0) {
290: return i;
291: }
292: level--;
293: }
294: }
295: } catch (Exception e) {
296: e.printStackTrace();
297: }
298:
299: return -1;
300: }
301:
302: /** -1 if not found open = '{', close = '}'
303: TODO: ignore comments and string quotes ...
304: */
305: public static int getPositionOfCorrespondingClosingBrace(char open,
306: char close, SimpleDocument doc, int pos) {
307: int level = 0;
308: try {
309: //int len = doc.getLength()
310: for (int i = pos + 1; i < doc.getLength(); i++) {
311: char ci = doc.getCharAt(i);
312: if (ci == open)
313: level++;
314: if (ci == close) {
315: if (level <= 0) {
316: return i;
317: }
318: level--;
319: }
320: }
321: } catch (Exception e) {
322: e.printStackTrace();
323: }
324:
325: return -1;
326: }
327:
328: public static String getSpacesAtBeginning(String text) {
329: StringBuilder sb = new StringBuilder();
330: for (int i = 0; i < text.length(); i++) {
331: char ci = text.charAt(i);
332: if (Character.isWhitespace(ci) && ci != '\r' && ci != '\n') {
333: sb.append(text.charAt(i));
334: } else {
335: break;
336: }
337: }
338: return sb.toString();
339: }
340:
341: public static void scrollPosToMiddle(int pos, JTextPane textPane,
342: JScrollPane editorScrollPane, int h) {
343: try {
344: Rectangle r = textPane.modelToView(pos);
345: //r.translate(0,-this.getHeight()/4);
346: //textPane.scrollRectToVisible( r );
347: //this.scroll
348: //int h2 = (int)editorScrollPane.getViewport().getExtentSize().getHeight()/2;
349: //System.out.println(""+h2);
350: editorScrollPane.getViewport().setViewPosition(
351: new Point(0, Math.max(r.y - h, 0)));
352: //textPane.requestFocus(); // to make the selection visible
353:
354: } catch (Exception e) {
355: Basics.ignore(e);
356: }
357: }
358:
359: /** In fact, 1/4 below upper limit is nicer...
360: scrolls the start of the line to the middle of the screen
361: */
362: public static void scrollToMiddle(JTextComponent tp, int pos) {
363: // look if a parent exists, this is only the case IF the text pane has been added in a scrollpane
364: if (tp.getParent() == null)
365: return;
366: if (!(tp.getParent() instanceof JViewport)) {
367: new Throwable("parent of textpane is not a viewport !")
368: .printStackTrace();
369: }
370:
371: JViewport vp = (JViewport) tp.getParent();
372:
373: try {
374: Rectangle pt = tp.modelToView(pos);
375: int h = (int) (pt.getY() - vp.getHeight() / 4);
376: if (h < 0)
377: h = 0;
378: vp.setViewPosition(new Point(0, h));
379: } catch (Exception e) {
380: e.printStackTrace();
381: }
382: }
383:
384: public static int[] getVisibleDocPosBounds(JTextPane textPane,
385: JScrollPane editorScrollPane) {
386: int[] pos = new int[2];
387: try {
388: Point pt = editorScrollPane.getViewport().getViewPosition();
389: pos[0] = textPane.viewToModel(pt);
390: Dimension dim = editorScrollPane.getViewport()
391: .getExtentSize();
392:
393: Point pt2 = new Point((int) (pt.getX() + dim.getWidth()),
394: (int) (pt.getY() + dim.getHeight()));
395: pos[1] = textPane.viewToModel(pt2);
396: //System.out.println(""+h2);
397: } catch (Exception e) {
398: e.printStackTrace();
399: }
400: return pos;
401: }
402:
403: /** @param line zero based.
404: * @param column zero based
405: */
406: public static int getDocPositionFor(Document doc, int line,
407: int column) {
408: if (line < 0)
409: return -1;
410: Element map = doc.getDefaultRootElement();
411: Element lineElt = map.getElement(line);
412: try {
413: int pos = lineElt.getStartOffset()
414: + (column > 0 ? column : 0);
415: if (pos < 0)
416: return 0; // [April2007]: security...
417: if (pos > doc.getLength())
418: return doc.getLength();
419: return pos;
420: } catch (Exception e) {
421: throw new RuntimeException(e);
422: }
423: }
424:
425: }
|