001: /*
002: * TagCommands.java
003: *
004: * Copyright (C) 1998-2002 Peter Graves
005: * $Id: TagCommands.java,v 1.7 2002/11/10 01:03:35 piso Exp $
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: */
021:
022: package org.armedbear.j;
023:
024: import java.awt.AWTEvent;
025: import java.awt.event.MouseEvent;
026: import java.util.ArrayList;
027: import java.util.Iterator;
028: import java.util.List;
029: import javax.swing.SwingUtilities;
030: import javax.swing.undo.CompoundEdit;
031:
032: public final class TagCommands implements Constants {
033: public static void nextTag() {
034: final Editor editor = Editor.currentEditor();
035: final Position dot = editor.getDot();
036: if (dot != null) {
037: final List tags = editor.getBuffer().getTags();
038: if (tags != null) {
039: // Find the next tag after dot.
040: final int dotLineNumber = dot.lineNumber();
041: final int limit = tags.size();
042: for (int i = 0; i < limit; i++) {
043: LocalTag tag = (LocalTag) tags.get(i);
044: if (tag.lineNumber() > dotLineNumber) {
045: editor.moveDotTo(tag.getPosition());
046: return;
047: }
048: }
049: }
050: }
051: }
052:
053: public static void previousTag() {
054: final Editor editor = Editor.currentEditor();
055: final Position dot = editor.getDot();
056: if (dot != null) {
057: final List tags = editor.getBuffer().getTags();
058: if (tags != null) {
059: // Find the last tag before dot.
060: final int dotLineNumber = dot.lineNumber();
061: for (int i = tags.size() - 1; i >= 0; i--) {
062: LocalTag tag = (LocalTag) tags.get(i);
063: if (tag.lineNumber() < dotLineNumber) {
064: editor.moveDotTo(tag.getPosition());
065: return;
066: }
067: }
068: }
069: }
070: }
071:
072: public static void findTag() {
073: final Editor editor = Editor.currentEditor();
074: final LocationBar locationBar = editor.getLocationBar();
075: locationBar.setLabelText(LocationBar.PROMPT_TAG);
076: HistoryTextField textField = locationBar.getTextField();
077: textField.setHandler(new FindTagTextFieldHandler(editor,
078: textField));
079: textField.setHistory(new History("findTag.tag"));
080: textField.setText("");
081: if (editor.getDispatcher().getLastEvent().getSource() instanceof MenuItem) {
082: Runnable r = new Runnable() {
083: public void run() {
084: editor.setFocusToTextField();
085: }
086: };
087: SwingUtilities.invokeLater(r);
088: } else
089: editor.setFocusToTextField();
090: }
091:
092: private static boolean findTag(Editor editor,
093: Expression expression, boolean useOtherWindow) {
094: List tags = findMatchingTags(editor.getBuffer(), expression);
095: if (tags == null || tags.size() == 0)
096: return false;
097: if (tags.size() == 1) {
098: // One match.
099: Tag tag = (Tag) tags.get(0);
100: editor.pushPosition();
101: if (tag instanceof LocalTag)
102: gotoLocalTag(editor, (LocalTag) tag, useOtherWindow);
103: else if (tag instanceof GlobalTag)
104: gotoGlobalTag(editor, (GlobalTag) tag, useOtherWindow);
105: else
106: Debug.bug();
107: } else {
108: // More than one match.
109: editor.setDefaultCursor();
110: ListTagsBuffer buf = new ListTagsBuffer(editor, "findTag",
111: expression.getName(), tags);
112: editor.makeNext(buf);
113: Editor ed = editor.activateInOtherWindow(buf);
114: ed.setDot(buf.getInitialDotPos());
115: ed.moveCaretToDotCol();
116: ed.updateDisplay();
117: }
118: return true;
119: }
120:
121: public static List findMatchingTags(Buffer buffer,
122: Expression expression) {
123: final Mode mode = buffer.getMode();
124: if (!mode.isTaggable())
125: return null;
126: // We'll start by looking in the current buffer. If we find an exact
127: // match there, we're done.
128: List list = findMatchingTagsInBuffer(buffer, expression);
129: if (list == null) {
130: // No exact match in the current buffer. Look in the current
131: // directory.
132: final File currentDirectory = buffer.getCurrentDirectory();
133: list = findMatchingTagsInDirectory(expression,
134: currentDirectory, mode);
135: if (list == null) {
136: // Look at all the directories in the buffer's tag path.
137: List dirs = getDirectoriesInTagPath(buffer);
138: if (dirs != null) {
139: for (int i = 0; i < dirs.size(); i++) {
140: String dir = (String) dirs.get(i);
141: File directory = File.getInstance(
142: currentDirectory, dir);
143: if (directory == null)
144: continue;
145: if (directory.equals(currentDirectory))
146: continue;
147: List tagsInDir = findMatchingTagsInDirectory(
148: expression, directory, mode);
149: if (tagsInDir != null) {
150: if (list == null)
151: list = new ArrayList();
152: list.addAll(tagsInDir);
153: }
154: }
155: }
156: }
157: }
158: return list;
159: }
160:
161: private static List findMatchingTagsInBuffer(Buffer buffer,
162: Expression expression) {
163: if (buffer.getTags() == null) {
164: Tagger tagger = buffer.getMode().getTagger(buffer);
165: if (tagger != null)
166: tagger.run();
167: }
168: List list = null;
169: final List localTags = buffer.getTags();
170: if (localTags != null) {
171: // Look through all the local tags.
172: Iterator iter = localTags.iterator();
173: while (iter.hasNext()) {
174: LocalTag localTag = (LocalTag) iter.next();
175: if (expression.matches(localTag)) {
176: if (list == null)
177: list = new ArrayList();
178: list.add(localTag);
179: }
180: }
181: }
182: return list;
183: }
184:
185: public static List findMatchingTagsInDirectory(
186: Expression expression, File directory, Mode mode) {
187: if (!mode.isTaggable())
188: return null;
189: final String name = expression.getName();
190: final int arity = expression.getArity();
191: List tags = Editor.getTagFileManager().getTags(directory, mode);
192: if (tags == null) {
193: if (!directory.isRemote())
194: Editor.getTagFileManager().addToQueue(directory, mode);
195: return null;
196: }
197: List list = null;
198: Iterator iter = tags.iterator();
199: while (iter.hasNext()) {
200: GlobalTag tag = (GlobalTag) iter.next();
201: String methodName = tag.getMethodName();
202: if (methodName != null && methodName.equals(name)) {
203: if (arity >= 0) {
204: int n = Expression.getArity(tag
205: .getCanonicalSignature());
206: if (n >= 0 && n != arity)
207: continue;
208: }
209: if (list == null)
210: list = new ArrayList();
211: list.add(tag);
212: }
213: }
214: return list;
215: }
216:
217: public static List findMatchingTagsInDirectory(String name,
218: File directory, Mode mode, int arity, boolean ignoreCase) {
219: if (!mode.isTaggable())
220: return null;
221: List tags = Editor.getTagFileManager().getTags(directory, mode);
222: if (tags == null) {
223: if (!directory.isRemote())
224: Editor.getTagFileManager().addToQueue(directory, mode);
225: return null;
226: }
227: boolean isQualified = mode.isQualifiedName(name);
228: List list = new ArrayList();
229: Iterator iter = tags.iterator();
230: while (iter.hasNext()) {
231: GlobalTag tag = (GlobalTag) iter.next();
232: String tagName = tag.getName();
233: if ((ignoreCase && tagName.equalsIgnoreCase(name))
234: || tagName.equals(name)) {
235: if (arity >= 0) {
236: int n = Expression.getArity(tag
237: .getCanonicalSignature());
238: if (n == -1 || n == arity) {
239: list.add(tag);
240: continue;
241: }
242: } else {
243: list.add(tag);
244: continue;
245: }
246: }
247: if (!isQualified) {
248: // The name we're looking for does not have a class prefix.
249: String methodName = tag.getMethodName();
250: if (methodName != null) {
251: if ((ignoreCase && methodName
252: .equalsIgnoreCase(name))
253: || methodName.equals(name)) {
254: if (arity >= 0) {
255: int n = Expression.getArity(tag
256: .getCanonicalSignature());
257: if (n < 0 || n == arity)
258: list.add(tag);
259: } else
260: list.add(tag);
261: }
262: }
263: }
264: }
265: return list.size() > 0 ? list : null;
266: }
267:
268: public static boolean findClass(Editor editor, String className,
269: boolean useOtherWindow) {
270: editor.setWaitCursor();
271: boolean succeeded = false;
272: File file = JavaSource.findSource(editor.getBuffer(),
273: className, false);
274: if (file != null) {
275: Buffer buf = Editor.getBuffer(file);
276: if (buf != null) {
277: Editor ed;
278: if (useOtherWindow)
279: ed = editor.displayInOtherWindow(buf);
280: else
281: ed = editor;
282: ed.makeNext(buf);
283: ed.activate(buf);
284: ed.repaintDisplay();
285: List localTags = buf.getTags(true);
286: if (localTags != null) {
287: Position pos = null;
288: for (int i = 0; i < localTags.size(); i++) {
289: JavaTag tag = (JavaTag) localTags.get(i);
290: int type = tag.getType();
291: if (type == TAG_CLASS || type == TAG_INTERFACE) {
292: String name = tag.getMethodName();
293: if (name.startsWith("class"))
294: name = name.substring(5).trim();
295: else if (name.startsWith("interface"))
296: name = name.substring(9).trim();
297: if (name.equals(className)) {
298: pos = tag.getPosition();
299: break;
300: }
301: }
302: }
303: if (pos != null) {
304: CompoundEdit compoundEdit = editor
305: .beginCompoundEdit();
306: ed.addUndo(SimpleEdit.FOLD);
307: ed.unfoldMethod(pos.getLine());
308: ed.moveDotTo(pos);
309: centerTag(ed);
310: ed.endCompoundEdit(compoundEdit);
311: ed.updateDisplay();
312: succeeded = true;
313: }
314: }
315: }
316: }
317: editor.setDefaultCursor();
318: return succeeded;
319: }
320:
321: public static void listMatchingTags() {
322: final Editor editor = Editor.currentEditor();
323: FindTagDialog findTagDialog = new FindTagDialog(editor,
324: "List Matching Tags");
325: editor.centerDialog(findTagDialog);
326: findTagDialog.show();
327: listMatchingTags(editor, findTagDialog.getInput());
328: }
329:
330: public static void listMatchingTags(String name) {
331: listMatchingTags(Editor.currentEditor(), name);
332: }
333:
334: public static void listMatchingTagsAtDot() {
335: final Editor editor = Editor.currentEditor();
336: listMatchingTags(editor, editor.getMode().getIdentifier(
337: editor.getDot()));
338: }
339:
340: private static void listMatchingTags(Editor editor, String name) {
341: if (name != null && name.length() > 0) {
342: editor.repaintNow();
343: editor.setWaitCursor();
344: final Buffer buffer = editor.getBuffer();
345: List tags = findMatchingTagsInDirectory(name, buffer
346: .getCurrentDirectory(), buffer.getMode(), -1,
347: Utilities.isLowerCase(name));
348: editor.setDefaultCursor();
349: if (tags != null) {
350: ListTagsBuffer buf = new ListTagsBuffer(editor,
351: "listMatchingTags", name, tags);
352: editor.makeNext(buf);
353: Editor ed = editor.activateInOtherWindow(buf);
354: ed.setDot(buf.getInitialDotPos());
355: ed.moveCaretToDotCol();
356: ed.updateDisplay();
357: } else
358: editor.status("Tag \"" + name + "\" not found");
359: }
360: }
361:
362: public static void gotoLocalTag(Editor editor, LocalTag localTag,
363: boolean useOtherWindow) {
364: Editor ed;
365: if (useOtherWindow)
366: ed = editor.displayInOtherWindow(editor.getBuffer());
367: else
368: ed = editor;
369: localTag.gotoTag(ed);
370: }
371:
372: public static void gotoGlobalTag(Editor editor,
373: GlobalTag globalTag, boolean useOtherWindow) {
374: Buffer buf = editor.getBuffer(File.getInstance(globalTag
375: .getFileName()));
376: Editor ed;
377: if (useOtherWindow)
378: ed = editor.displayInOtherWindow(buf);
379: else
380: ed = editor;
381: globalTag.gotoTag(ed);
382: }
383:
384: public static List getDirectoriesInTagPath(Buffer buffer) {
385: String tagPath = buffer.getStringProperty(Property.TAG_PATH);
386: if (tagPath == null)
387: return null;
388: return Utilities.getDirectoriesInPath(tagPath);
389: }
390:
391: public static void centerTag() {
392: centerTag(Editor.currentEditor());
393: }
394:
395: public static void centerTag(Editor editor) {
396: final Buffer buffer = editor.getBuffer();
397: final List tags = buffer.getTags();
398: if (tags == null)
399: return;
400: final int size = tags.size();
401: int dotLineNumber = editor.getDotLineNumber();
402: Line begin = null;
403: Line end = null;
404: for (int i = 0; i < size; i++) {
405: LocalTag tag = (LocalTag) tags.get(i);
406: if (tag.lineNumber() <= dotLineNumber) {
407: begin = tag.getLine();
408: } else {
409: // tag.lineNumber() > dotLineNumber
410: end = tag.getLine();
411: break;
412: }
413: }
414: if (begin != null)
415: editor.getDisplay().centerRegion(begin, end);
416: }
417:
418: public static void makeTagFile() {
419: final Editor editor = Editor.currentEditor();
420: File directory = editor.getCurrentDirectory();
421: if (directory.isRemote()) {
422: MessageDialog
423: .showMessageDialog(
424: "Tag files are not supported for remote directories",
425: "Make Tag File");
426: return;
427: }
428: Mode mode = editor.getMode();
429: if (!mode.isTaggable()) {
430: MessageDialog.showMessageDialog(
431: "Tag files are not supported in " + mode + " mode",
432: "Make Tag File");
433: return;
434: }
435: editor.repaintNow();
436: editor.setWaitCursor();
437: Editor.getTagFileManager().makeTagFile(directory, mode);
438: editor.setDefaultCursor();
439: MessageDialog.showMessageDialog("Tag file is ready",
440: "Make Tag File");
441: }
442:
443: public static void findTagAtDot() {
444: findTagAtDotInternal(Editor.currentEditor(), false, false);
445: }
446:
447: public static void findTagAtDotOtherWindow() {
448: findTagAtDotInternal(Editor.currentEditor(), false, true);
449: }
450:
451: public static void mouseFindTag() {
452: final Editor editor = Editor.currentEditor();
453: AWTEvent e = editor.getDispatcher().getLastEvent();
454: if (e instanceof MouseEvent) {
455: editor.mouseMoveDotToPoint((MouseEvent) e);
456: findTagAtDotInternal(editor, true, false);
457: }
458: }
459:
460: private static void findTagAtDotInternal(Editor editor,
461: boolean exact, boolean useOtherWindow) {
462: editor.setWaitCursor();
463: Expression expr = editor.getMode().getExpressionAtDot(editor,
464: exact);
465: if (expr != null) {
466: boolean succeeded = findTag(editor, expr, useOtherWindow);
467: if (!succeeded && editor.getModeId() == C_MODE) {
468: // Special case for Emacs source.
469: // If name is "Frun_hooks", look for "run-hooks".
470: String name = expr.getName();
471: if (name != null && name.length() > 0
472: && name.charAt(0) == 'F')
473: name = name.substring(1).replace('_', '-');
474: succeeded = findTag(editor, new Expression(name),
475: useOtherWindow);
476: }
477: if (!succeeded)
478: editor.status("Tag \"" + expr.getName()
479: + "\" not found");
480: }
481: editor.setDefaultCursor();
482: }
483: }
|