001: package tide.editor;
002:
003: import snow.texteditor.*;
004: import javax.swing.text.*;
005: import java.util.*;
006: import java.awt.*;
007: import java.awt.event.*;
008: import javax.swing.*;
009: import javax.swing.event.*;
010:
011: /** Here we can add actions, to the ones defined in DefaultEditorKit and StyledEditorKit.
012: Usage: just create and set this to be the editorpane's kit with editor.setEditorKit( kit );
013: */
014: public class SourceEditorKit extends StyledEditorKit {
015: public static final String IndentLinesActionName = "IndentLines";
016: public static final String UnindentLinesActionName = "UnindentLines";
017: public static final String CommentLinesActionName = "CommentLines";
018: public static final String UncommentLinesActionName = "UncommentLines";
019: public static final String UppercaseWordActionName = "UppercaseWord";
020: public static final String DeleteLineActionName = "DeleteLine";
021:
022: /*
023: public SourceEditorKit()
024: {
025: super();
026:
027: // these are the actions like "right-justify", ...
028: //for(Action a: this.getActions())
029: //{
030: // System.out.println(""+a.getValue(Action.NAME));
031: //}
032:
033:
034: }*/
035:
036: /** Installs the editorkit in the text pane and map the keys.
037: */
038: @Override
039: public void install(JEditorPane c) {
040: super .install(c);
041:
042: Keymap map = c.getKeymap();
043:
044: map.addActionForKeyStroke(Accelerators.indentLine,
045: new IndentAction());
046: map.addActionForKeyStroke(Accelerators.unindentLine,
047: new UnindentAction());
048:
049: map.addActionForKeyStroke(Accelerators.commentOutLines,
050: new CommentOutLinesAction());
051: map.addActionForKeyStroke(Accelerators.uncommentOutLines,
052: new UncommentOutLinesAction());
053:
054: //[Feb2008]: removed, never used... map.addActionForKeyStroke( Accelerators.toUppercaseWord, new UpWord() );
055: map.addActionForKeyStroke(Accelerators.deleteLine,
056: new DeleteLineAction());
057: }
058:
059: /** Helper method to add the actions defined here to a menu.
060: Very useful in a MenuBar: They make the editor shortcuts visible to the user.
061: */
062: public void addActions(JMenu menu) {
063: // jut appears in the menu, really defined in the editorPanel
064: JMenuItem indent = new JMenuItem(new IndentAction());
065: menu.add(indent);
066:
067: JMenuItem unindent = new JMenuItem(new UnindentAction());
068: menu.add(unindent);
069:
070: JMenuItem comment = new JMenuItem(new CommentOutLinesAction());
071: menu.add(comment);
072:
073: JMenuItem uncomment = new JMenuItem(
074: new UncommentOutLinesAction());
075: menu.add(uncomment);
076:
077: JMenuItem del = new JMenuItem(new DeleteLineAction());
078: menu.add(del);
079: }
080:
081: @Override
082: public Action[] getActions() {
083: Action[] acts = TextAction.augmentList(super .getActions(), this
084: .getCustomActions());
085: return acts;
086: }
087:
088: private Action[] getCustomActions() {
089: return new Action[] {
090: // not really necessary, we've mapped them with the keys !
091: new IndentAction(), new UnindentAction(),
092: new CommentOutLinesAction(),
093: new UncommentOutLinesAction(),
094: //new UpWord(),
095: new SelectWord(), // overwrite the default action
096: new CaretEndLine() // overwrite default action
097: };
098: // ...
099: }
100:
101: /** Indent selected lines with DocumentUtils.indentLines()
102: */
103: public static class IndentAction extends
104: StyledEditorKit.StyledTextAction {
105: public IndentAction() {
106: super (IndentLinesActionName);
107: this .putValue(Action.ACCELERATOR_KEY,
108: Accelerators.indentLine);
109: this .putValue(Action.NAME, "Indent selected lines");
110: }
111:
112: public void actionPerformed(ActionEvent e) {
113: JEditorPane editor = getEditor(e);
114:
115: if (editor != null) {
116: if (!editor.isEditable())
117: return;
118:
119: int start = editor.getSelectionStart();
120: int end = editor.getSelectionEnd();
121:
122: // TODO: deactivate the filter
123: if (end - start > 0) {
124: DocumentUtils.indentLines(editor.getDocument(),
125: start, end);
126: } else {
127: DocumentUtils.indentLines(editor.getDocument(),
128: editor.getCaretPosition(), editor
129: .getCaretPosition());
130: }
131: }
132: }
133: }
134:
135: public static class UnindentAction extends
136: StyledEditorKit.StyledTextAction {
137: public UnindentAction() {
138: super (UnindentLinesActionName);
139: this .putValue(Action.ACCELERATOR_KEY,
140: Accelerators.unindentLine);
141: this .putValue(Action.NAME, "Unindent selected lines");
142: }
143:
144: public void actionPerformed(ActionEvent e) {
145: JEditorPane editor = getEditor(e);
146: if (editor != null) {
147: if (!editor.isEditable())
148: return;
149:
150: int start = editor.getSelectionStart();
151: int end = editor.getSelectionEnd();
152: if (end - start > 0) {
153: DocumentUtils.unindentLines(editor.getDocument(),
154: start, end);
155: } else {
156: DocumentUtils.unindentLines(editor.getDocument(),
157: editor.getCaretPosition(), editor
158: .getCaretPosition());
159: }
160: }
161: }
162: }
163:
164: public static class CommentOutLinesAction extends
165: StyledEditorKit.StyledTextAction {
166: public CommentOutLinesAction() {
167: super (CommentLinesActionName);
168: this .putValue(Action.ACCELERATOR_KEY,
169: Accelerators.commentOutLines);
170: this .putValue(Action.NAME, "Comment out selected lines");
171: }
172:
173: public void actionPerformed(ActionEvent e) {
174: JEditorPane editor = getEditor(e);
175: if (editor != null) {
176: if (!editor.isEditable())
177: return;
178:
179: int start = editor.getSelectionStart();
180: int end = editor.getSelectionEnd();
181: if (end - start > 0) {
182: DocumentUtils.commentOutLines(editor.getDocument(),
183: start, end);
184: } else {
185: DocumentUtils.commentOutLines(editor.getDocument(),
186: editor.getCaretPosition(), editor
187: .getCaretPosition());
188: }
189: }
190: }
191: }
192:
193: public static class UncommentOutLinesAction extends
194: StyledEditorKit.StyledTextAction {
195: public UncommentOutLinesAction() {
196: super (UncommentLinesActionName);
197: this .putValue(Action.ACCELERATOR_KEY,
198: Accelerators.uncommentOutLines);
199: this .putValue(Action.NAME, "Uncomment selected lines");
200: }
201:
202: public void actionPerformed(ActionEvent e) {
203: JEditorPane editor = getEditor(e);
204: if (editor != null) {
205: if (!editor.isEditable())
206: return;
207:
208: int start = editor.getSelectionStart();
209: int end = editor.getSelectionEnd();
210: if (end - start > 0) {
211: DocumentUtils.unCommentOutLines(editor
212: .getDocument(), start, end);
213: } else {
214: DocumentUtils.unCommentOutLines(editor
215: .getDocument(), editor.getCaretPosition(),
216: editor.getCaretPosition());
217: }
218: }
219: }
220: }
221:
222: /**
223: */
224: public static class DeleteLineAction extends
225: StyledEditorKit.StyledTextAction {
226: public DeleteLineAction() {
227: super (DeleteLineActionName);
228: this .putValue(Action.ACCELERATOR_KEY,
229: Accelerators.deleteLine);
230: this .putValue(Action.NAME, "Delete line");
231: }
232:
233: public void actionPerformed(ActionEvent ae) {
234: JEditorPane editor = getEditor(ae);
235: if (editor != null) {
236: if (!editor.isEditable())
237: return;
238: int pos = editor.getCaretPosition();
239: StyledDocument doc = getStyledDocument(editor);
240: try {
241: DocumentUtils.deleteLineAtPos(doc, pos);
242: } catch (Exception e) {
243: e.printStackTrace();
244: }
245: }
246: }
247: }
248:
249: /* not good, never used.
250: *
251: public static class UpWord extends TextAction
252: {
253: public UpWord()
254: {
255: super(UppercaseWordActionName);
256: this.putValue(Action.ACCELERATOR_KEY, Accelerators.toUppercaseWord);
257: this.putValue(Action.NAME, "Uppercase/Lowercase word");
258: }
259:
260: public void actionPerformed(ActionEvent e) {
261: // change current word (or selected words) to upper case
262: JTextComponent comp = getTextComponent(e);
263: if (comp == null)
264: return;
265: Document doc = comp.getDocument();
266: int start = comp.getSelectionStart();
267: int end = comp.getSelectionEnd();
268: try
269: {
270: if(!comp.isEditable()) return;
271:
272: int left = javax.swing.text.Utilities.getWordStart(comp, start);
273: int right = javax.swing.text.Utilities.getWordEnd(comp, end);
274: String word = doc.getText(left, right - left);
275: doc.remove(left, right - left);
276: String nWord = word.toUpperCase(Locale.getDefault());
277: if(word.equals(nWord))
278: {
279: nWord = word.toLowerCase(Locale.getDefault());
280: }
281: doc.insertString(left, nWord, null);
282: comp.setSelectionStart(start); // restore previous
283: // position/selection
284: comp.setSelectionEnd(end);
285: } catch (BadLocationException ble) {
286: return;
287: }
288: }
289: }
290: */
291:
292: public final static class CaretEndLine extends StyledTextAction {
293: public CaretEndLine() {
294: super ("caret-end-line");
295: }
296:
297: public void actionPerformed(ActionEvent e) {
298: JEditorPane editor = getEditor(e);
299: if (editor == null)
300: return;
301:
302: StyledDocument doc = getStyledDocument(editor);
303: int pos = editor.getCaretPosition();
304: String line = DocumentUtils.getTextOfLineAtPosition(doc,
305: pos);
306:
307: int offset = DocumentUtils.getLineStartOffsetForPos(doc,
308: pos);
309: if (line.trim().length() == 0) {
310: editor.setCaretPosition(offset);
311: return; // do nothing.
312: }
313:
314: for (int i = line.length() - 1; i >= 0; i--) {
315: if (!Character.isWhitespace(line.charAt(i))) {
316: pos = i + 1;
317: break;
318: }
319: }
320:
321: if (offset + pos <= doc.getLength()) {
322: editor.setCaretPosition(offset + pos);
323: }
324:
325: }
326: }
327:
328: /** Selects a java id !
329: * Replaces the original selection.
330: * Takes points if CTRL is pressed.
331: *
332: * [Aug2007]: selects numbers if word failed
333: */
334: public final static class SelectWord extends StyledTextAction {
335: public SelectWord() {
336: super ("select-word");
337: }
338:
339: public void actionPerformed(ActionEvent e) {
340: JEditorPane editor = getEditor(e);
341: if (editor == null)
342: return;
343:
344: StyledDocument doc = getStyledDocument(editor);
345:
346: boolean acceptPts = (e.getModifiers() & e.CTRL_MASK) == e.CTRL_MASK;
347:
348: int pos = editor.getCaretPosition();
349:
350: // go back to next space
351: int start = pos;
352: int lastValidStart = -1;
353: StringBuilder id = new StringBuilder();
354: try {
355: wl: while (start >= 0) {
356: char c = doc.getText(start, 1).charAt(0);
357: if (Character.isWhitespace(c)
358: || ",%;:|^\"\'-+*/{}[]<>&".indexOf(c) >= 0)
359: break wl;
360: id.insert(0, c);
361: if (isValidJavaID(id, acceptPts))
362: lastValidStart = start;
363:
364: start--;
365: }
366:
367: // keep the valid part !
368: if (lastValidStart > 0) {
369: id.setLength(0);
370: id.append(doc.getText(lastValidStart, pos
371: - lastValidStart));
372: }
373: } catch (Exception e2) {
374: e2.printStackTrace();
375: }
376:
377: if (lastValidStart < 0) {
378: MainEditorFrame.debugOut("no id here (1)");
379:
380: // select a number !
381: selectNumber(editor, doc, pos);
382:
383: return;
384: }
385:
386: // break at first invalid.
387: int end = pos + 1;
388: int lastValidEnd = end;
389: try {
390: wl: while (end < doc.getLength()) {
391: char c = doc.getText(end, 1).charAt(0);
392: if (Character.isWhitespace(c)
393: || ",%;:|^\"\'-+*/{}[]<>&".indexOf(c) >= 0)
394: break wl;
395: id.append(c);
396: if (isValidJavaID(id, acceptPts)) {
397: lastValidEnd = end + 1;
398: } else {
399: break wl;
400: }
401:
402: end++;
403: }
404:
405: // keep the valid part !
406: id.setLength(0);
407: id.append(doc.getText(lastValidStart, lastValidEnd
408: - lastValidStart));
409: } catch (Exception e2) {
410: e2.printStackTrace();
411: }
412:
413: if (lastValidEnd < 0) {
414: MainEditorFrame.debugOut("no id here (2)");
415: return;
416: }
417:
418: editor.setSelectionStart(lastValidStart);
419: editor.setSelectionEnd(lastValidEnd);
420: }
421:
422: void selectNumber(JEditorPane editor, StyledDocument doc,
423: int pos) {
424: // go back to next space
425: int start = pos;
426: int lastValidStart = -1;
427: //StringBuilder id = new StringBuilder();
428: try {
429: wl: while (start >= 0) // -234.24523e-23
430: {
431: char c = Character.toLowerCase(doc
432: .getText(start, 1).charAt(0));
433:
434: // Oct2007: added "()"
435: if (Character.isWhitespace(c)
436: || "()=,%;:|^\"\'*/{}[]<>&".indexOf(c) >= 0)
437: break wl;
438: if (c != 'e' && Character.isLetter(c))
439: break wl;
440:
441: // id.insert(0, c);
442: //if(isValidJavaID(id, acceptPts)) lastValidStart = start;
443: lastValidStart = start;
444:
445: start--;
446: }
447:
448: // keep the valid part !
449: /*if(lastValidStart>0)
450: {
451: id.setLength(0);
452: id.append( doc.getText( lastValidStart, pos-lastValidStart) );
453: }*/
454:
455: } catch (Exception e2) {
456: e2.printStackTrace();
457: }
458:
459: if (lastValidStart < 0) {
460: MainEditorFrame.debugOut("no id here (3)");
461: return;
462: }
463:
464: // break at first invalid.
465: int end = pos + 1;
466: int lastValidEnd = end;
467: boolean hasE = false;
468: char prev = ' ';
469: try {
470: wl: while (end < doc.getLength()) {
471: char c = Character.toLowerCase(doc.getText(end, 1)
472: .charAt(0));
473: //if(Character.isWhitespace(c) || ",%;:|^\"\'-+*/{}[]<>&".indexOf(c)>=0) break wl;
474: //id.append(c);
475: boolean isE = c == 'e';
476: if (hasE) {
477: if (isE)
478: break wl;
479: }
480:
481: if (isE)
482: hasE = true;
483:
484: if (isE || Character.isDigit(c)
485: || ((c == '-' || c == '+') && prev == 'e')) {
486: lastValidEnd = end + 1;
487: } else {
488: break wl;
489: }
490:
491: prev = c;
492:
493: end++;
494: }
495:
496: // keep the valid part !
497: // id.setLength(0);
498: // id.append( doc.getText( lastValidStart, lastValidEnd-lastValidStart) );
499: } catch (Exception e2) {
500: e2.printStackTrace();
501: }
502:
503: if (lastValidEnd < 0) {
504: MainEditorFrame.debugOut("no id here (4)");
505: return;
506: }
507:
508: editor.setSelectionStart(lastValidStart);
509: editor.setSelectionEnd(lastValidEnd);
510:
511: }
512: }
513:
514: public static boolean isValidJavaID(CharSequence sb,
515: boolean acceptPts) {
516: if (sb.length() == 0)
517: return false;
518: if (!Character.isJavaIdentifierStart(sb.charAt(0)))
519: return false;
520: for (int i = 1; i < sb.length(); i++) {
521: if (!Character.isJavaIdentifierPart(sb.charAt(i))) {
522: if (acceptPts && sb.charAt(i) == '.')
523: continue;
524: return false;
525: }
526: }
527: return true;
528: }
529:
530: }
|