KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > j > SidebarBufferTree


1 /*
2  * SidebarBufferTree.java
3  *
4  * Copyright (C) 2003-2004 Mike Rutter, Peter Graves
5  * $Id: SidebarBufferTree.java,v 1.10 2004/09/16 16:49:55 piso Exp $
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */

21
22 package org.armedbear.j;
23
24 import java.awt.Color JavaDoc;
25 import java.awt.Component JavaDoc;
26 import java.awt.Cursor JavaDoc;
27 import java.awt.Point JavaDoc;
28 import java.awt.Rectangle JavaDoc;
29 import java.awt.datatransfer.DataFlavor JavaDoc;
30 import java.awt.datatransfer.Transferable JavaDoc;
31 import java.awt.dnd.DnDConstants JavaDoc;
32 import java.awt.dnd.DragGestureEvent JavaDoc;
33 import java.awt.dnd.DragGestureListener JavaDoc;
34 import java.awt.dnd.DragGestureRecognizer JavaDoc;
35 import java.awt.dnd.DragSource JavaDoc;
36 import java.awt.dnd.DragSourceContext JavaDoc;
37 import java.awt.dnd.DragSourceDragEvent JavaDoc;
38 import java.awt.dnd.DragSourceDropEvent JavaDoc;
39 import java.awt.dnd.DragSourceEvent JavaDoc;
40 import java.awt.dnd.DragSourceListener JavaDoc;
41 import java.awt.dnd.DropTarget JavaDoc;
42 import java.awt.dnd.DropTargetDragEvent JavaDoc;
43 import java.awt.dnd.DropTargetDropEvent JavaDoc;
44 import java.awt.dnd.DropTargetEvent JavaDoc;
45 import java.awt.dnd.DropTargetListener JavaDoc;
46 import java.awt.event.ActionEvent JavaDoc;
47 import java.awt.event.ActionListener JavaDoc;
48 import java.awt.event.InputEvent JavaDoc;
49 import java.awt.event.KeyEvent JavaDoc;
50 import java.awt.event.KeyListener JavaDoc;
51 import java.awt.event.MouseEvent JavaDoc;
52 import java.awt.event.MouseListener JavaDoc;
53 import java.awt.event.MouseMotionListener JavaDoc;
54 import java.util.ArrayList JavaDoc;
55 import java.util.Enumeration JavaDoc;
56 import java.util.Iterator JavaDoc;
57 import java.util.List JavaDoc;
58 import javax.swing.JComponent JavaDoc;
59 import javax.swing.JLabel JavaDoc;
60 import javax.swing.JMenuItem JavaDoc;
61 import javax.swing.JPopupMenu JavaDoc;
62 import javax.swing.JTree JavaDoc;
63 import javax.swing.JViewport JavaDoc;
64 import javax.swing.SwingUtilities JavaDoc;
65 import javax.swing.ToolTipManager JavaDoc;
66 import javax.swing.UIManager JavaDoc;
67 import javax.swing.border.Border JavaDoc;
68 import javax.swing.border.CompoundBorder JavaDoc;
69 import javax.swing.border.EmptyBorder JavaDoc;
70 import javax.swing.tree.DefaultMutableTreeNode JavaDoc;
71 import javax.swing.tree.DefaultTreeModel JavaDoc;
72 import javax.swing.tree.TreeCellRenderer JavaDoc;
73 import javax.swing.tree.TreeNode JavaDoc;
74 import javax.swing.tree.TreePath JavaDoc;
75
76 // Consider an option to make the folders either the first things or last
77
// things in the buffer list. That way all of the folders will be listed
78
// together, and all of the buffers will be listed together.
79
public final class SidebarBufferTree extends SidebarTree implements Constants,
80     NavigationComponent, ActionListener JavaDoc, KeyListener JavaDoc, MouseListener JavaDoc,
81     MouseMotionListener JavaDoc, PreferencesChangeListener, DragGestureListener JavaDoc,
82     DragSourceListener JavaDoc, DropTargetListener JavaDoc
83 {
84     private JPopupMenu JavaDoc popup;
85     private int updateFlag;
86     private DefaultMutableTreeNode JavaDoc rootNode;
87     private Sidebar sidebar;
88
89     // DnD
90
private DragSource JavaDoc dragSource;
91     private static DragSourceContext JavaDoc dragSourceContext;
92     private Buffer draggedBuffer = null;
93     private int draggedBufferRow = -1;
94     // Metric used for determining the WAIT_TIME between scroll increments.
95
private int scrollY = 0;
96     private Runnable JavaDoc scroller = null;
97     // Variable times used to speed up scrolling the further the mouse is
98
// from the tree.
99
private static final long[] WAIT_TIMES = new long[] {
100         200, 175, 150, 125, 100, 75, 50, 37, 25, 15, 10, 5
101     };
102
103     // Is the buffer list sorted alphabetically?
104
private boolean alpha = false;
105     // Are we reordering the buffers when one is opened?
106
private boolean reorder = false;
107
108     public SidebarBufferTree(Sidebar sidebar)
109     {
110         super(null);
111         this.sidebar = sidebar;
112         setCellRenderer(new SidebarTreeCellRenderer(sidebar));
113         setFocusTraversalKeysEnabled(false);
114         addKeyListener(this);
115         addMouseListener(this);
116         addMouseMotionListener(this);
117         setToolTipText("");
118         setRootVisible(false);
119
120         dragSource = DragSource.getDefaultDragSource() ;
121         DragGestureRecognizer JavaDoc dgr =
122             dragSource.createDefaultDragGestureRecognizer(this,
123                                                           DnDConstants.ACTION_COPY_OR_MOVE,
124                                                           this);
125         dgr.setSourceActions(dgr.getSourceActions() & ~InputEvent.BUTTON3_MASK);
126         new DropTarget JavaDoc(this, this);
127
128         Preferences p = Editor.preferences();
129         if (p != null) {
130             updatePreferences(p);
131             p.addPreferencesChangeListener(this);
132         } else
133             Debug.bug();
134     }
135
136     // Grabs the rough tree structure from the current session and builds the
137
// data tree out of it. Also caches the session name so that we can check
138
// against that later on. If the session changes, this needs to be called
139
// again to repopulate the tree.
140
private void initializeTreeStructure()
141     {
142         final ArrayList JavaDoc arrayList = new ArrayList JavaDoc();
143         for (BufferIterator it = new BufferIterator(); it.hasNext();) {
144             Buffer buf = it.nextBuffer();
145             if (buf.isPrimary()) {
146                 arrayList.add(buf);
147                 // Add secondary buffer (if any) right after the corresponding
148
// primary buffer.
149
Buffer secondary = buf.getSecondary();
150                 if (secondary != null)
151                     arrayList.add(secondary);
152             }
153         }
154         // Re-create the tree.
155
rootNode = new DefaultMutableTreeNode JavaDoc("");
156         buildTreeFromList(rootNode, arrayList);
157         setModel(new DefaultTreeModel JavaDoc(rootNode));
158     }
159
160     private void updatePreferences(Preferences p)
161     {
162         alpha = p.getBooleanProperty(Property.SORT_BUFFER_LIST);
163         if (alpha)
164             reorder = false;
165         else
166             reorder = p.getIntegerProperty(Property.REORDER_BUFFERS) > 1;
167     }
168
169     private void buildTreeFromList(DefaultMutableTreeNode JavaDoc node, List JavaDoc buffers)
170     {
171         Iterator JavaDoc iter = buffers.iterator();
172         while (iter.hasNext()) {
173             Object JavaDoc next = iter.next();
174             if (next instanceof Buffer) {
175                 Buffer buffer = (Buffer) next;
176                 node.add(new DefaultMutableTreeNode JavaDoc(buffer));
177             }
178         }
179     }
180
181     public synchronized void setUpdateFlag(int mask)
182     {
183         updateFlag |= mask;
184     }
185
186     public synchronized void updateBufferList()
187     {
188         if (!SwingUtilities.isEventDispatchThread())
189             Debug.bug();
190         if ((updateFlag & SIDEBAR_BUFFER_LIST_CHANGED) != 0) {
191             refresh();
192             updateFlag |= SIDEBAR_REPAINT_BUFFER_LIST;
193         }
194         if ((updateFlag & SIDEBAR_MODIFIED_BUFFER_COUNT) != 0) {
195             // When this happens, we need to redraw at least one of the icons,
196
// so make sure that a repaint gets scheduled.
197
updateFlag |= SIDEBAR_REPAINT_BUFFER_LIST;
198             updateLabel();
199         }
200         // Select active buffer.
201
Buffer buffer = sidebar.getEditor().getBuffer();
202         if (buffer != getSelectedBuffer())
203             setSelectedBuffer(buffer);
204         else
205             scrollPathToVisible(getSelectionPath());
206         boolean repaint = (updateFlag & SIDEBAR_REPAINT_BUFFER_LIST) != 0;
207         updateFlag = 0;
208         if (repaint) {
209             // Schedule a repaint.
210
repaint();
211         }
212     }
213
214     public Buffer getSelectedBuffer()
215     {
216         if (getSelectionCount() > 0)
217             return getBufferFromPath(getSelectionPath());
218         else
219             return null;
220     }
221
222     public Buffer[] getSelectedBuffers()
223     {
224         int numSelected = getSelectionCount();
225         // Check to make sure there is something selected.
226
if (numSelected <= 0)
227             return new Buffer[0];
228         Buffer[] buffers = new Buffer[numSelected];
229         // Grab active buffers
230
TreePath JavaDoc[] paths = getSelectionPaths();
231         for (int i = 0; i < paths.length; i++)
232             buffers[i] = getBufferFromPath(paths[i]);
233         return buffers;
234     }
235
236     // Overrides the version from JTree to ensure that null is never returned.
237
public int[] getSelectionRows()
238     {
239         int[] rows = super.getSelectionRows();
240         if (rows == null)
241             rows = new int[0];
242         return rows;
243     }
244
245     // Returns the first row from getSelectionRows() if there are any rows
246
// selected, -1 otherwise.
247
public int getSelectionRow()
248     {
249         int rows[] = getSelectionRows();
250         if (rows.length > 0)
251             return rows[0];
252         return -1;
253     }
254
255     private Buffer getBufferFromPath(TreePath JavaDoc path)
256     {
257         TreeNode JavaDoc endNode = (TreeNode JavaDoc)path.getLastPathComponent();
258         if (endNode instanceof DefaultMutableTreeNode JavaDoc) {
259             Object JavaDoc obj = ((DefaultMutableTreeNode JavaDoc)endNode).getUserObject();
260             if (obj instanceof Buffer)
261                 return (Buffer) obj;
262         }
263         return null;
264     }
265
266     public void setSelectedBuffer(Buffer buffer)
267     {
268         DefaultMutableTreeNode JavaDoc node = findNodeForObject(buffer);
269         if (node != null) {
270             TreePath JavaDoc path = new TreePath JavaDoc(node.getPath());
271             setSelectionPath(path);
272             scrollPathToVisible(path);
273         }
274     }
275
276     public void scrollPathToVisible(TreePath JavaDoc path)
277     {
278     if (path != null) {
279         makeVisible(path);
280         Rectangle JavaDoc bounds = getPathBounds(path);
281         if (bounds != null) {
282                 bounds.y = Math.max(bounds.y - 17, 0);
283                 bounds.height = bounds.height + 34;
284         scrollRectToVisible(bounds);
285         if (accessibleContext != null)
286             ((AccessibleJTree)accessibleContext).fireVisibleDataPropertyChange();
287         }
288     }
289     }
290
291     public String JavaDoc getLabelText()
292     {
293         int total = 0;
294         int modified = 0;
295         for (BufferIterator it = new BufferIterator(); it.hasNext();) {
296             ++total;
297             if (it.nextBuffer().isModified())
298                 ++modified;
299         }
300         FastStringBuffer sb = new FastStringBuffer("Buffers");
301         sb.append(" (");
302         sb.append(total);
303         if (modified > 0) {
304             sb.append("; ");
305             sb.append(modified);
306             sb.append(" modified");
307         }
308         sb.append(')');
309         return sb.toString();
310     }
311
312     private synchronized void updateLabel()
313     {
314         sidebar.setBufferListLabelText(getLabelText());
315         updateFlag &= ~SIDEBAR_MODIFIED_BUFFER_COUNT;
316     }
317
318     private final Runnable JavaDoc refreshRunnable = new Runnable JavaDoc() {
319         public void run()
320         {
321             if ((updateFlag & SIDEBAR_MODIFIED_BUFFER_COUNT) != 0)
322                 updateLabel();
323             initializeTreeStructure();
324         }
325     };
326
327     public void refresh()
328     {
329         if (SwingUtilities.isEventDispatchThread())
330             refreshRunnable.run();
331         else
332             SwingUtilities.invokeLater(refreshRunnable);
333     }
334
335     public void updatePosition()
336     {
337     }
338
339     private void switchToBuffer()
340     {
341         Buffer buffer = getSelectedBuffer();
342         if (buffer != null) {
343             Editor editor = sidebar.getEditor();
344             if (Editor.preferences().getIntegerProperty(Property.REORDER_BUFFERS) > 1)
345                 editor.makeNext(buffer);
346             editor.switchToBuffer(buffer);
347             Editor.currentEditor().setFocusToDisplay();
348             editor.updateDisplay();
349         }
350     }
351
352     private void closeBuffers(Buffer[] array)
353     {
354         Editor editor = sidebar.getEditor();
355         for (int i = 0; i < array.length; i++)
356             editor.maybeKillBuffer(array[i]);
357         EditorIterator iter = new EditorIterator();
358         while (iter.hasNext())
359             iter.nextEditor().updateDisplay();
360         for (int i = 0; i < Editor.getFrameCount(); i++) {
361             Frame frame = Editor.getFrame(i);
362             Sidebar sidebar = frame.getSidebar();
363             if (sidebar != null) {
364                 sidebar.setUpdateFlag(SIDEBAR_BUFFER_LIST_ALL);
365                 SidebarBufferTree sidebarBufferTree = sidebar.getBufferTree();
366                 if (sidebarBufferTree != null)
367                     sidebarBufferTree.updateBufferList();
368             }
369         }
370     }
371
372     private void closeSelectedBuffers() {
373         int index = -1;
374         int[] rows = getSelectionRows();
375         if (rows.length > 0)
376             index = rows[0];
377         Buffer[] array = getSelectedBuffers();
378         closeBuffers(array);
379         if (index >= 0) {
380             // This works if getRowCount() returns the number of rows that can
381
// be displayed with the current expansions, as opposed to the
382
// number of rows that are currently being drawn.
383
if (index > getRowCount() - 1)
384                 index = getRowCount() - 1;
385             setSelectionRow(index);
386             scrollRowToVisible(index);
387         }
388     }
389
390     private void saveSelectedBuffers()
391     {
392         Editor editor = sidebar.getEditor();
393         Buffer[] array = getSelectedBuffers();
394         for (int i = 0; i < array.length; i++)
395             editor.save(array[i]);
396         Sidebar.repaintBufferListInAllFrames();
397     }
398
399     public void actionPerformed(ActionEvent JavaDoc e)
400     {
401         String JavaDoc command = e.getActionCommand();
402         if (command.equals("close"))
403             closeSelectedBuffers();
404         else if (command.equals("save"))
405             saveSelectedBuffers();
406     }
407
408     private void showPopup(Component JavaDoc c, int x, int y)
409     {
410         popup = new JPopupMenu JavaDoc();
411         TreePath JavaDoc path = getPathForLocation(x, y);
412         String JavaDoc bufferName = null;
413         if (path != null) {
414             Object JavaDoc last = path.getLastPathComponent();
415             Object JavaDoc value = ((DefaultMutableTreeNode JavaDoc)last).getUserObject();
416             if (value instanceof Buffer) {
417                 bufferName = last.toString();
418             }
419         }
420         JMenuItem JavaDoc menuItem = new JMenuItem JavaDoc("Save");
421         menuItem.setActionCommand("save");
422         menuItem.addActionListener(this);
423         popup.add(menuItem);
424         menuItem = new JMenuItem JavaDoc("Close");
425         menuItem.setActionCommand("close");
426         menuItem.addActionListener(this);
427         popup.add(menuItem);
428         popup.pack();
429         popup.show(c, x, y);
430     }
431
432     public String JavaDoc getToolTipText(MouseEvent JavaDoc e)
433     {
434         String JavaDoc text = null;
435         Point JavaDoc p = e.getPoint();
436         int index = getRowForLocation(p.x, p.y);
437         if (index >= 0 && index < getRowCount()) {
438             TreePath JavaDoc path = getPathForRow(index);
439             Buffer buffer = getBufferFromPath(path);
440             if (buffer == null)
441                 return null;
442             File file = buffer.getFile();
443             if (file != null)
444                 text = file.isRemote() ? file.netPath() : file.canonicalPath();
445             else
446                 text = buffer.getTitle();
447         }
448         return text;
449     }
450
451     public synchronized void preferencesChanged()
452     {
453         Preferences p = Editor.preferences();
454         if (p != null) {
455             updatePreferences(p);
456         }
457         else {
458             Debug.bug();
459         }
460     }
461
462     private DefaultMutableTreeNode JavaDoc findNodeForObject(Object JavaDoc userObj)
463     {
464         if (rootNode != null) {
465             Enumeration JavaDoc enumeration = rootNode.breadthFirstEnumeration();
466             while (enumeration.hasMoreElements()) {
467                 Object JavaDoc next = enumeration.nextElement();
468                 if (next instanceof DefaultMutableTreeNode JavaDoc) {
469                     Object JavaDoc obj = ((DefaultMutableTreeNode JavaDoc)next).getUserObject();
470                     if (userObj.equals(obj))
471                         return (DefaultMutableTreeNode JavaDoc) next;
472                 }
473             }
474         }
475         return null;
476     }
477
478     public void keyPressed(KeyEvent JavaDoc e)
479     {
480         final int keyCode = e.getKeyCode();
481         // Mask off the bits we don't care about (Java 1.4).
482
final int modifiers = e.getModifiers() & 0x0f;
483         final Editor editor = sidebar.getEditor();
484         switch (keyCode) {
485             // Ignore modifier keystrokes.
486
case KeyEvent.VK_SHIFT:
487             case KeyEvent.VK_CONTROL:
488             case KeyEvent.VK_ALT:
489             case KeyEvent.VK_META:
490                 return;
491             case KeyEvent.VK_ENTER:
492                 e.consume();
493                 switchToBuffer();
494                 if (modifiers == KeyEvent.ALT_MASK)
495                     editor.toggleSidebar();
496                 return;
497             case KeyEvent.VK_TAB:
498                 e.consume();
499                 if (modifiers == 0) {
500                     if (sidebar.getBottomComponent() != null) {
501                         sidebar.setBuffer();
502                         editor.setFocus((JComponent JavaDoc)sidebar.getBottomComponent());
503                     }
504                 }
505                 return;
506             case KeyEvent.VK_ESCAPE:
507                 e.consume();
508                 if (popup != null && popup.isVisible()) {
509                     popup.setVisible(false);
510                     popup = null;
511                 } else {
512                     sidebar.setBuffer();
513                     editor.setFocusToDisplay();
514                 }
515                 return;
516             case KeyEvent.VK_DELETE:
517                 e.consume();
518                 closeSelectedBuffers();
519                 return;
520         }
521         editor.getDispatcher().setEnabled(false);
522     }
523
524     public void keyReleased(KeyEvent JavaDoc e)
525     {
526         e.consume();
527         sidebar.getEditor().getDispatcher().setEnabled(true);
528     }
529
530     public void keyTyped(KeyEvent JavaDoc e)
531     {
532         e.consume();
533     }
534
535     public void mousePressed(MouseEvent JavaDoc e)
536     {
537         Editor editor = sidebar.getEditor();
538         editor.ensureActive();
539         // Mask off the bits we don't care about (Java 1.4).
540
int modifiers = e.getModifiers() & 0x1f;
541         Point JavaDoc p = e.getPoint();
542         if (modifiers == InputEvent.BUTTON1_MASK ||
543             modifiers == InputEvent.BUTTON2_MASK)
544         {
545             setSelectionRow(getRowForLocation(p.x, p.y));
546             paintImmediately(0, 0, getWidth(), getHeight());
547             switchToBuffer();
548         } else if (modifiers == InputEvent.BUTTON3_MASK) {
549             //setSelectedIndex(locationToIndex(e.getPoint()));
550
setSelectionRow(getRowForLocation(p.x, p.y));
551             sidebar.getFrame().setFocus(this);
552             paintImmediately(0, 0, getWidth(), getHeight());
553         } else {
554             sidebar.getFrame().setFocus(this);
555         }
556     }
557
558     public void mouseReleased(MouseEvent JavaDoc e)
559     {
560     }
561
562     public void mouseClicked(MouseEvent JavaDoc e)
563     {
564         // Mask off the bits we don't care about (Java 1.4).
565
int modifiers = e.getModifiers() & 0x1f;
566         Point JavaDoc p = e.getPoint();
567         // If the user clicks with the first or second mouse button while
568
// there is a popup menu visible, the tree doesn't get painted
569
// properly unless we repaint it here.
570
if (modifiers == InputEvent.BUTTON1_MASK ||
571             modifiers == InputEvent.BUTTON2_MASK)
572         {
573             setSelectionRow(getRowForLocation(p.x, p.y));
574             paintImmediately(0, 0, getWidth(), getHeight());
575             switchToBuffer();
576         } else if (e.getModifiers() == InputEvent.BUTTON3_MASK) {
577             showPopup(e.getComponent(), e.getX(), e.getY());
578         }
579     }
580
581     public void mouseMoved(MouseEvent JavaDoc e)
582     {
583         String JavaDoc text = getToolTipText(e);
584         if (text == null)
585             text = "";
586         sidebar.getFrame().setStatusText(text);
587     }
588
589     public void mouseEntered(MouseEvent JavaDoc e)
590     {
591         // This does not overide our mouse dragging cursor while doing drag
592
// and drop because we don't get a mouseEntered event while dragging.
593
setCursor(Cursor.getDefaultCursor());
594     }
595
596     public void mouseExited(MouseEvent JavaDoc e)
597     {
598         final Frame frame = sidebar.getFrame();
599         final StatusBar statusBar = frame.getStatusBar();
600         if (statusBar != null) {
601             statusBar.setText(null);
602             statusBar.repaintNow();
603         }
604         // Force tool tip to be hidden.
605
ToolTipManager.sharedInstance().setEnabled(false);
606         ToolTipManager.sharedInstance().setEnabled(true);
607         if (popup == null || !popup.isVisible()) {
608             if (frame.getFocusedComponent() == this) {
609                 Editor editor = sidebar.getEditor();
610                 sidebar.setBuffer();
611                 editor.setFocusToDisplay();
612             }
613         }
614     }
615
616     public void mouseDragged(MouseEvent JavaDoc e)
617     {
618     }
619
620     // From interface DragTargetListener.
621
public void dragEnter(DropTargetDragEvent JavaDoc event)
622     {
623         if (alpha || reorder)
624             return;
625         stopScroll();
626         if (Platform.isPlatformUnix() && dragSourceContext != null) {
627             Cursor JavaDoc c = Dispatcher.getCursorForAction(event.getDropAction());
628             dragSourceContext.setCursor(c);
629         }
630     }
631
632     // From interface DragTargetListener.
633
public void dragExit(DropTargetEvent JavaDoc e)
634     {
635         if (alpha || reorder)
636             return;
637         setSelectionRow(draggedBufferRow);
638         if (Platform.isPlatformUnix() && dragSourceContext != null)
639             dragSourceContext.setCursor(Dispatcher.getCursorForAction(-1));
640     }
641
642     // From interface DragTargetListener.
643
public void dragOver(DropTargetDragEvent JavaDoc event)
644     {
645         if (alpha || reorder)
646             return;
647         if (event.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
648             Point JavaDoc pt = event.getLocation();
649             int row = getRowForLocation(pt.x, pt.y);
650             if (row == -1)
651                 setSelectionRow(draggedBufferRow);
652             else
653                 setSelectionRow(row);
654         }
655     }
656
657     // From interface DragTargetListener.
658
public void drop(DropTargetDropEvent JavaDoc event)
659     {
660         if (alpha || reorder)
661             return;
662         Transferable JavaDoc t = event.getTransferable();
663         if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor) &&
664             draggedBuffer != null)
665         {
666             BufferList bufList = Editor.getBufferList();
667             Buffer movedTo = getSelectedBuffer();
668             // No dropping onto secondary buffers.
669
if (movedTo.isSecondary()) {
670                 setSelectionRow(draggedBufferRow);
671                 event.rejectDrop();
672                 return;
673             }
674             int index = bufList.indexOf(movedTo);
675             if (index >= 0) {
676                 bufList.move(draggedBuffer, index);
677                 refresh();
678                 // Make it so that the dragged buffer is selected in the tree.
679
setSelectionRow(index);
680             }
681         } else
682             event.rejectDrop();
683     }
684
685
686     // From interface DragTargetListener.
687
public void dropActionChanged(DropTargetDragEvent JavaDoc event) {}
688
689     // From interface DragGestureListener.
690
public void dragGestureRecognized(DragGestureEvent JavaDoc event)
691     {
692         if (alpha || reorder)
693             return;
694         Buffer buf = getSelectedBuffer();
695         if (buf != null && !buf.isSecondary()) {
696             String JavaDoc name = buf.getFileNameForDisplay();
697             Transferable JavaDoc transferable =
698                 new BufferSelection(new java.io.File JavaDoc(name));
699             draggedBuffer = buf;
700             draggedBufferRow = getSelectionRow();
701
702             int action = event.getDragAction();
703             Cursor JavaDoc cursor = null;
704             if (Platform.isPlatformUnix()) {
705                 cursor = Dispatcher.getCursorForAction(action);
706             }
707             dragSource.startDrag(event, cursor, transferable, this);
708             dragSourceContext = null;
709         }
710     }
711
712     // From interface DragSourceListener.
713
public void dragDropEnd(DragSourceDropEvent JavaDoc event)
714     {
715         draggedBuffer = null;
716         draggedBufferRow = -1;
717         stopScroll();
718         if (alpha || reorder)
719             return;
720         // Make sure that the currently selected row is visible.
721
int selectionRow = getSelectionRow();
722         if (selectionRow >= 0)
723             scrollRowToVisible(selectionRow);
724     }
725
726     // From interface DragSourceListener.
727
public void dragEnter(DragSourceDragEvent JavaDoc event)
728     {
729         if (alpha || reorder)
730             return;
731         stopScroll();
732         if (Platform.isPlatformUnix()) {
733             DragSourceContext JavaDoc dsc = event.getDragSourceContext();
734             dsc.setCursor(Dispatcher.getCursorForAction(event.getDropAction()));
735         }
736     }
737
738     // From interface DragSourceListener.
739
public void dragOver(DragSourceDragEvent JavaDoc event)
740     {
741         if (alpha || reorder)
742             return;
743         // OS X doesn't seem to like to pass along dragExit events, but it
744
// does pass along dragOver events even when the cursor is blissfully
745
// off somewhere completely different.
746
if (Platform.isPlatformMacOSX()) {
747             Component JavaDoc parent = getParent();
748             if (!(parent instanceof JViewport JavaDoc)) {
749                 stopScroll();
750                 return;
751             }
752             JViewport JavaDoc viewport = (JViewport JavaDoc)parent;
753             Rectangle JavaDoc rect = viewport.getViewRect();
754
755             Point JavaDoc frameLoc = Editor.getCurrentFrame().getLocationOnScreen();
756             Point JavaDoc loc = viewport.getLocationOnScreen();
757             int x = event.getX() - frameLoc.x + loc.x;
758             int y = event.getY() + frameLoc.y - loc.y;
759             if ((y < 0 || y > rect.height) && (x >= 0 && x <= rect.width)) {
760                 // Now that we've checked to make sure that the cursor is
761
// out of our bounds, we need to take x and y back to values
762
// that dragExit will like.
763
x += loc.x;
764                 y += loc.y;
765                 DragSourceEvent JavaDoc dse =
766                     new DragSourceEvent JavaDoc(event.getDragSourceContext(), x, y);
767                 dragExit(dse);
768             } else
769                 stopScroll();
770         }
771     }
772
773     // From interface DragSourceListener.
774
public void dropActionChanged(DragSourceDragEvent JavaDoc event) {}
775
776     // From interface DragSourceListener.
777
public void dragExit(DragSourceEvent JavaDoc event)
778     {
779         if (alpha || reorder)
780             return;
781         DragSourceContext JavaDoc dsc = event.getDragSourceContext();
782         if (Platform.isPlatformUnix())
783             dsc.setCursor(Dispatcher.getCursorForAction(-1));
784         dragSourceContext = dsc;
785         Component JavaDoc parent = getParent();
786         if (!(parent instanceof JViewport JavaDoc)) {
787             stopScroll();
788             return;
789         }
790         JViewport JavaDoc viewport = (JViewport JavaDoc)parent;
791         Rectangle JavaDoc rect = viewport.getViewRect();
792         int x = event.getX();
793         int y = event.getY();
794         Point JavaDoc p = getLocationOnScreen();
795         x -= p.x + rect.x;
796         y -= p.y + rect.y;
797         // We don't have to scroll if roughly half of the top or bottom element
798
// is visible, so we use a little fudge factor.
799
int rowFudge = (getRowBounds(0).height + 1) / 2;
800         int yDiff = getSize().height - rect.height - rect.y;
801         // All the cases where scrolling will not be necessary.
802
if (x < 0 || x >= rect.width || (y < 0 && rect.y < rowFudge) ||
803             (y > 0 && yDiff < rowFudge))
804         {
805             stopScroll();
806             return;
807         }
808         // Increasing the WAIT_TIMES index for every pixel is a little extreme,
809
// so do it for every two pixels.
810
if (y < 0) {
811             scrollY = (y - 1) / 2;
812         } else {
813             y -= rect.height;
814             scrollY = (y + 2) / 2;
815         }
816         startScroll();
817     }
818
819     // Initialize and start the scroller thread if it is not currently running.
820
private synchronized void startScroll() {
821         if (scroller == null) {
822             scroller = new TreeScroller();
823             Thread JavaDoc scroll = new Thread JavaDoc(scroller, "SidebarBufferTree scroller");
824             scroll.setDaemon(true);
825             scroll.setPriority(Thread.MIN_PRIORITY);
826             scroll.start();
827         }
828     }
829
830     // Set conditions so that any tree scrolling taking place will stop.
831
private synchronized void stopScroll() {
832         scrollY = 0;
833         scroller = null;
834     }
835
836     private class TreeScroller implements Runnable JavaDoc {
837         public void run()
838         {
839             Component JavaDoc parent = getParent();
840             if (!(parent instanceof JViewport JavaDoc)) {
841                 return;
842             }
843             final JViewport JavaDoc viewport = (JViewport JavaDoc)parent;
844             while (scrollY != 0) {
845                 if (viewport == null)
846                     break;
847                 Rectangle JavaDoc bounds = getRowBounds(0);
848                 if (bounds == null)
849                     break;
850                 int scrollInc = bounds.height;
851                 int diffY;
852                 final Rectangle JavaDoc rect = viewport.getViewRect();
853                 final Point JavaDoc pos = viewport.getViewPosition();
854                 if (scrollY < 0) {
855                     pos.y = Math.max(pos.y - scrollInc, 0);
856                     if (pos.y == 0)
857                         scrollY = 0;
858                 } else {
859                     int h = getSize().height;
860                     int yMax = h - rect.height;
861                     pos.y = Math.min(pos.y + scrollInc, yMax);
862                     if (pos.y == yMax)
863                         scrollY = 0;
864                 }
865                 Runnable JavaDoc r = new Runnable JavaDoc() {
866                     public void run()
867                     {
868                         if (viewport != null && pos != null) {
869                             viewport.setViewPosition(pos);
870                             repaint();
871                         }
872                     }
873                 };
874                 SwingUtilities.invokeLater(r);
875                 int absY = Math.abs(scrollY);
876                 int waitIndex = Math.min(absY, WAIT_TIMES.length-1);
877                 try {
878                     Thread.sleep(WAIT_TIMES[waitIndex]);
879                 }
880                 catch (InterruptedException JavaDoc ex) {}
881             }
882         }
883     }
884
885     private static class SidebarTreeCellRenderer extends JLabel JavaDoc
886         implements TreeCellRenderer JavaDoc
887     {
888         private static final Color JavaDoc textForeground =
889             UIManager.getColor("Tree.textForeground");
890         private static final Color JavaDoc textBackground =
891             UIManager.getColor("Tree.textBackground");
892         private static final Color JavaDoc selectionForeground =
893             UIManager.getColor("Tree.selectionForeground");
894         private static final Color JavaDoc selectionBackground =
895             UIManager.getColor("Tree.selectionBackground");
896         private static final Color JavaDoc noFocusSelectionBackground =
897             new Color JavaDoc(208, 208, 208);
898         private static final Border JavaDoc noFocusBorder =
899             new EmptyBorder JavaDoc(1, 1, 1, 1);
900
901         private final Sidebar sidebar;
902
903         public SidebarTreeCellRenderer(Sidebar sidebar)
904         {
905             super();
906             this.sidebar = sidebar;
907             setOpaque(true);
908         }
909
910         public Component JavaDoc getTreeCellRendererComponent(JTree JavaDoc tree, Object JavaDoc value,
911                                                       boolean selected,
912                                                       boolean expanded,
913                                                       boolean leaf, int row,
914                                                       boolean hasFocus)
915         {
916             Object JavaDoc userObject = null;
917             if (value instanceof DefaultMutableTreeNode JavaDoc)
918                 userObject = ((DefaultMutableTreeNode JavaDoc)value).getUserObject();
919             Border JavaDoc innerBorder = null;
920             if (userObject instanceof Buffer) {
921                 setText(userObject.toString());
922                 Buffer buffer = (Buffer) userObject;
923                 setIcon(buffer.getIcon());
924                 if (buffer.isSecondary())
925                     innerBorder = new EmptyBorder JavaDoc(0, 10, 0, 0);
926             } else
927                 setIcon(null);
928             Frame frame = sidebar.getFrame();
929             if (selected) {
930                 if (frame.isActive() && tree.hasFocus())
931                     setBackground(selectionBackground);
932                 else
933                     setBackground(noFocusSelectionBackground);
934                 setForeground(selectionForeground);
935             } else {
936                 setBackground(textBackground);
937                 setForeground(textForeground);
938             }
939             setEnabled(tree.isEnabled());
940             setFont(tree.getFont());
941             Border JavaDoc outerBorder;
942             if (hasFocus)
943                 outerBorder = UIManager.getBorder("List.focusCellHighlightBorder");
944             else
945                 outerBorder = noFocusBorder;
946             setBorder(new CompoundBorder JavaDoc(outerBorder, innerBorder));
947             return this;
948         }
949     }
950
951     private class BufferSelection implements Transferable JavaDoc
952     {
953         private List JavaDoc fileList = null;
954         private final DataFlavor JavaDoc[] flavors = new DataFlavor JavaDoc[] {
955             DataFlavor.javaFileListFlavor
956         };
957
958         public BufferSelection(java.io.File JavaDoc file)
959         {
960             fileList = new ArrayList JavaDoc(1);
961             fileList.add(file);
962         }
963
964         public Object JavaDoc getTransferData(DataFlavor JavaDoc flavor)
965         {
966             List JavaDoc retList = new ArrayList JavaDoc(1);
967             if (flavor == DataFlavor.javaFileListFlavor)
968                 retList.add(fileList.get(0));
969             return retList;
970         }
971
972         public DataFlavor JavaDoc[] getTransferDataFlavors()
973         {
974             return flavors;
975         }
976
977         public boolean isDataFlavorSupported(DataFlavor JavaDoc flavor)
978         {
979             for (int i = 0; i < flavors.length; i++) {
980                 if (flavor == flavors[i])
981                     return true;
982             }
983             return false;
984         }
985     }
986 }
987
Popular Tags