001: /*
002: * SidebarTagList.java
003: *
004: * Copyright (C) 2000-2002 Peter Graves
005: * $Id: SidebarTagList.java,v 1.4 2003/11/30 00:06:22 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.event.InputEvent;
025: import java.awt.event.KeyEvent;
026: import java.awt.event.KeyListener;
027: import java.awt.event.MouseEvent;
028: import java.awt.event.MouseListener;
029: import java.awt.event.MouseMotionListener;
030: import java.util.List;
031: import javax.swing.SwingUtilities;
032: import javax.swing.ToolTipManager;
033:
034: public class SidebarTagList extends SidebarList implements Constants,
035: NavigationComponent, KeyListener, MouseListener,
036: MouseMotionListener {
037: private Editor editor;
038: private Buffer buffer;
039: private List tags;
040:
041: public SidebarTagList(Sidebar sidebar, Editor editor) {
042: super (sidebar);
043: this .editor = editor;
044: addKeyListener(this );
045: addMouseListener(this );
046: addMouseMotionListener(this );
047: }
048:
049: public final Editor getEditor() {
050: return editor;
051: }
052:
053: public synchronized final void setEditor(Editor editor) {
054: this .editor = editor;
055: }
056:
057: public final Buffer getBuffer() {
058: return buffer;
059: }
060:
061: public final void setBuffer(Buffer buffer) {
062: this .buffer = buffer;
063: }
064:
065: public final String getLabelText() {
066: File file = editor.getBuffer().getFile();
067: return file != null ? file.getName() : null;
068: }
069:
070: public synchronized void refresh() {
071: if (!SwingUtilities.isEventDispatchThread())
072: Debug
073: .bug("SidebarTagList.refresh() called from background thread!");
074: final Buffer buf = editor.getBuffer();
075: if (buf == null)
076: return;
077: if (tags != null && tags == buf.getTags())
078: return;
079: tags = buf.getTags();
080: if (tags != null) {
081: setListData(tags.toArray());
082: setBuffer(buf);
083: updatePosition();
084: return;
085: }
086: // Need to run tagger.
087: final Tagger tagger = buf.getMode().getTagger(buf);
088: if (tagger == null)
089: return;
090: Runnable runTaggerRunnable = new Runnable() {
091: public void run() {
092: boolean locked = false;
093: try {
094: buf.lockRead();
095: locked = true;
096: } catch (InterruptedException e) {
097: Log.error(e);
098: }
099: if (locked) {
100: try {
101: tagger.run();
102: tags = buf.getTags();
103: } finally {
104: buf.unlockRead();
105: }
106: }
107: if (tags != null) {
108: final Object[] listData = tags.toArray();
109: Runnable replaceListDataRunnable = new Runnable() {
110: public void run() {
111: // Make sure user didn't change buffers while we
112: // were preparing the tag list.
113: replaceListData(buf, listData);
114: }
115: };
116: SwingUtilities.invokeLater(replaceListDataRunnable);
117: }
118: }
119: };
120: Thread thread = new Thread(runTaggerRunnable,
121: "SidebarTagList.refresh()");
122: thread.setDaemon(true);
123: thread.start();
124: }
125:
126: private synchronized void replaceListData(Buffer buf,
127: Object[] listData) {
128: if (editor.getBuffer() == buf) {
129: setListData(listData);
130: setBuffer(buf);
131: updatePosition();
132: }
133: }
134:
135: // Set the selection to the last tag before the position of the caret in
136: // the current editor.
137: public synchronized void updatePosition() {
138: if (tags == null)
139: return;
140: final Position dot = editor.getDot();
141: if (dot == null)
142: return;
143: final Line dotLine = dot.getLine();
144: int index = -1;
145: Line lastTagLine = null;
146: final int size = tags.size();
147: for (int i = 0; i < size; i++) {
148: LocalTag t = (LocalTag) tags.get(i);
149: if (t.getPosition().isAfter(dot)) {
150: if (t.getLine() == dotLine
151: && t.getLine() != lastTagLine) {
152: index = i;
153: lastTagLine = t.getLine();
154: }
155: break;
156: } else {
157: index = i;
158: lastTagLine = t.getLine();
159: }
160: }
161: if (index != getSelectedIndex()) {
162: if (index >= 0) {
163: setSelectedIndex(index);
164: centerIndex(index);
165: } else {
166: clearSelection();
167: ensureIndexIsVisible(0);
168: }
169: }
170: }
171:
172: private synchronized void gotoTag() {
173: if (tags == null)
174: return;
175: int index = getSelectedIndex();
176: if (index >= 0 && index < tags.size()) {
177: LocalTag tag = (LocalTag) tags.get(index);
178: tag.gotoTag(editor);
179: }
180: editor.setFocusToDisplay();
181: }
182:
183: public synchronized String getToolTipText(MouseEvent e) {
184: if (tags != null) {
185: int index = locationToIndex(e.getPoint());
186: if (index >= 0 && index < tags.size()) {
187: LocalTag t = (LocalTag) tags.get(index);
188: return t.getToolTipText();
189: }
190: }
191: return null;
192: }
193:
194: public void keyPressed(KeyEvent e) {
195: int keyCode = e.getKeyCode();
196: int modifiers = e.getModifiers();
197: // Mask off the bits we don't care about (Java 1.4).
198: modifiers &= 0x0f;
199: switch (keyCode) {
200: // Ignore modifier keystrokes.
201: case KeyEvent.VK_SHIFT:
202: case KeyEvent.VK_CONTROL:
203: case KeyEvent.VK_ALT:
204: case KeyEvent.VK_META:
205: return;
206: case KeyEvent.VK_ENTER:
207: e.consume();
208: gotoTag();
209: if (modifiers == KeyEvent.ALT_MASK)
210: sidebar.getFrame().frameToggleSidebar();
211: return;
212: case KeyEvent.VK_TAB:
213: e.consume();
214: if (modifiers == 0) {
215: if (sidebar.getBufferList() != null) {
216: updatePosition();
217: editor.setFocus(sidebar.getBufferList());
218: }
219: }
220: return;
221: case KeyEvent.VK_ESCAPE:
222: e.consume();
223: sidebar.setBuffer();
224: updatePosition();
225: editor.setFocusToDisplay();
226: return;
227: }
228: editor.getDispatcher().setEnabled(false);
229: }
230:
231: public void keyReleased(KeyEvent e) {
232: e.consume();
233: editor.getDispatcher().setEnabled(true);
234: }
235:
236: public void keyTyped(KeyEvent e) {
237: e.consume();
238: }
239:
240: public void mousePressed(MouseEvent e) {
241: LocationBar.cancelInput();
242: editor.ensureActive();
243: // Mask off the bits we don't care about (Java 1.4).
244: int modifiers = e.getModifiers() & 0x1f;
245: if (modifiers == InputEvent.BUTTON1_MASK
246: || modifiers == InputEvent.BUTTON2_MASK) {
247: if (modifiers == InputEvent.BUTTON2_MASK)
248: setSelectedIndex(locationToIndex(e.getPoint()));
249: paintImmediately(0, 0, getWidth(), getHeight());
250: Editor.setCurrentEditor(editor);
251: sidebar.setUpdateFlag(SIDEBAR_SET_BUFFER);
252: gotoTag();
253: } else
254: editor.setFocusToDisplay();
255: }
256:
257: public void mouseReleased(MouseEvent e) {
258: }
259:
260: public void mouseClicked(MouseEvent e) {
261: }
262:
263: public void mouseMoved(MouseEvent e) {
264: String text = getToolTipText(e);
265: sidebar.getFrame().setStatusText(text != null ? text : "");
266: }
267:
268: public void mouseEntered(MouseEvent e) {
269: }
270:
271: public void mouseExited(MouseEvent e) {
272: final Frame frame = sidebar.getFrame();
273: final StatusBar statusBar = frame.getStatusBar();
274: if (statusBar != null) {
275: statusBar.setText(null);
276: statusBar.repaintNow();
277: }
278: // Force tool tip to be hidden.
279: ToolTipManager.sharedInstance().setEnabled(false);
280: ToolTipManager.sharedInstance().setEnabled(true);
281: if (frame.getFocusedComponent() == this ) {
282: updatePosition();
283: editor.setFocusToDisplay();
284: }
285: }
286:
287: public void mouseDragged(MouseEvent e) {
288: }
289: }
|