KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > gjt > sp > jedit > browser > BrowserView


1 /*
2  * BrowserView.java
3  * :tabSize=8:indentSize=8:noTabs=false:
4  * :folding=explicit:collapseFolds=1:
5  *
6  * Copyright (C) 2000, 2003 Slava Pestov
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  */

22
23 package org.gjt.sp.jedit.browser;
24
25 //{{{ Imports
26
import javax.swing.border.EmptyBorder JavaDoc;
27 import javax.swing.event.*;
28 import javax.swing.*;
29
30 import java.awt.event.*;
31 import java.awt.*;
32 import java.io.File JavaDoc;
33 import java.util.*;
34
35 import org.gjt.sp.jedit.gui.DockableWindowManager;
36 import org.gjt.sp.jedit.io.*;
37 import org.gjt.sp.jedit.*;
38 //}}}
39

40 /**
41  * VFS browser tree view.
42  * @author Slava Pestov
43  * @version $Id: BrowserView.java 8676 2007-01-19 20:14:58Z kpouer $
44  */

45 class BrowserView extends JPanel
46 {
47     //{{{ BrowserView constructor
48
BrowserView(final VFSBrowser browser)
49     {
50         this.browser = browser;
51
52         tmpExpanded = new HashSet();
53         DockableWindowManager dwm = jEdit.getActiveView().getDockableWindowManager();
54         KeyListener keyListener = dwm.closeListener(VFSBrowser.NAME);
55
56         parentDirectories = new ParentDirectoryList();
57         parentDirectories.addKeyListener(keyListener);
58         
59         parentDirectories.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
60         parentDirectories.setCellRenderer(new ParentDirectoryRenderer());
61         parentDirectories.setVisibleRowCount(5);
62         parentDirectories.addMouseListener(new ParentMouseHandler());
63
64         final JScrollPane parentScroller = new JScrollPane(parentDirectories);
65         parentScroller.setMinimumSize(new Dimension(0,0));
66
67         table = new VFSDirectoryEntryTable(this);
68         table.addMouseListener(new TableMouseHandler());
69         JScrollPane tableScroller = new JScrollPane(table);
70         tableScroller.setMinimumSize(new Dimension(0,0));
71         tableScroller.getViewport().setBackground(table.getBackground());
72         tableScroller.getViewport().addMouseListener(new TableMouseHandler());
73         splitPane = new JSplitPane(
74             browser.isHorizontalLayout()
75             ? JSplitPane.HORIZONTAL_SPLIT : JSplitPane.VERTICAL_SPLIT,
76             jEdit.getBooleanProperty("appearance.continuousLayout"),
77             parentScroller,tableScroller);
78         splitPane.setOneTouchExpandable(true);
79
80         SwingUtilities.invokeLater(new Runnable JavaDoc()
81         {
82             public void run()
83             {
84                 String JavaDoc prop = browser.isHorizontalLayout() ? "vfs.browser.horizontalSplitter" : "vfs.browser.splitter";
85                 int loc = jEdit.getIntegerProperty(prop,-1);
86                 if(loc == -1)
87                     loc = parentScroller.getPreferredSize().height;
88
89                 splitPane.setDividerLocation(loc);
90                 parentDirectories.ensureIndexIsVisible(
91                     parentDirectories.getModel()
92                     .getSize());
93             }
94         });
95
96         if(browser.isMultipleSelectionEnabled())
97             table.getSelectionModel().setSelectionMode(
98                 ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
99         else
100             table.getSelectionModel().setSelectionMode(
101                 ListSelectionModel.SINGLE_SELECTION);
102
103         setLayout(new BorderLayout());
104
105         add(BorderLayout.CENTER,splitPane);
106
107         propertiesChanged();
108     } //}}}
109

110     //{{{ focusOnFileView() method
111
public void focusOnFileView()
112     {
113         table.requestFocus();
114     } //}}}
115

116     //{{{ removeNotify() method
117
public void removeNotify()
118     {
119         String JavaDoc prop = browser.isHorizontalLayout() ? "vfs.browser.horizontalSplitter" : "vfs.browser.splitter";
120         jEdit.setIntegerProperty(prop,splitPane.getDividerLocation());
121
122         super.removeNotify();
123     } //}}}
124

125     //{{{ getSelectedFiles() method
126
public VFSFile[] getSelectedFiles()
127     {
128         return table.getSelectedFiles();
129     } //}}}
130

131     //{{{ selectNone() method
132
public void selectNone()
133     {
134         table.clearSelection();
135     } //}}}
136

137     //{{{ saveExpansionState() method
138
public void saveExpansionState()
139     {
140         tmpExpanded.clear();
141         table.getExpandedDirectories(tmpExpanded);
142     } //}}}
143

144     //{{{ clearExpansionState() method
145
public void clearExpansionState()
146     {
147         tmpExpanded.clear();
148     } //}}}
149

150     //{{{ loadDirectory() method
151
public void loadDirectory(Object JavaDoc node, String JavaDoc path,
152         boolean addToHistory)
153     {
154         path = MiscUtilities.constructPath(browser.getDirectory(),path);
155         VFS vfs = VFSManager.getVFSForPath(path);
156
157         Object JavaDoc session = vfs.createVFSSession(path,this);
158         if(session == null)
159             return;
160
161         if(node == null)
162         {
163             parentDirectories.setListData(new Object JavaDoc[] {
164                 new LoadingPlaceholder() });
165         }
166
167         Object JavaDoc[] loadInfo = new Object JavaDoc[2];
168
169         VFSManager.runInWorkThread(new BrowserIORequest(
170             BrowserIORequest.LIST_DIRECTORY,browser,
171             session,vfs,path,null,loadInfo));
172         browser.directoryLoaded(node,loadInfo,addToHistory);
173     } //}}}
174

175     //{{{ directoryLoaded() method
176
public void directoryLoaded(Object JavaDoc node, String JavaDoc path, ArrayList directory)
177     {
178         //{{{ If reloading root, update parent directory list
179
if(node == null)
180         {
181             DefaultListModel parentList = new DefaultListModel();
182
183             String JavaDoc parent = path;
184
185             for(;;)
186             {
187                 VFS _vfs = VFSManager.getVFSForPath(
188                     parent);
189                 // create a DirectoryEntry manually
190
// instead of using _vfs._getFile()
191
// since so many VFS's have broken
192
// implementations of this method
193
parentList.insertElementAt(new VFSFile(
194                     _vfs.getFileName(parent),
195                     parent,parent,
196                     VFSFile.DIRECTORY,
197                     0L,false),0);
198                 String JavaDoc newParent = _vfs.getParentOfPath(parent);
199
200                 if(newParent == null ||
201                     MiscUtilities.pathsEqual(parent,newParent))
202                     break;
203                 else
204                     parent = newParent;
205             }
206
207             parentDirectories.setModel(parentList);
208             int index = parentList.getSize() - 1;
209             parentDirectories.setSelectedIndex(index);
210             parentDirectories.ensureIndexIsVisible(index);
211         } //}}}
212

213         table.setDirectory(VFSManager.getVFSForPath(path),
214             node,directory,tmpExpanded);
215     } //}}}
216

217     //{{{ updateFileView() method
218
public void updateFileView()
219     {
220         table.repaint();
221     } //}}}
222

223     //{{{ maybeReloadDirectory() method
224
public void maybeReloadDirectory(String JavaDoc path)
225     {
226         String JavaDoc browserDir = browser.getDirectory();
227         String JavaDoc symlinkBrowserDir;
228         if(MiscUtilities.isURL(browserDir))
229         {
230             symlinkBrowserDir = browserDir;
231         }
232         else
233         {
234             symlinkBrowserDir = MiscUtilities.resolveSymlinks(
235                 browserDir);
236         }
237
238         if(MiscUtilities.pathsEqual(path,symlinkBrowserDir))
239         {
240             saveExpansionState();
241             loadDirectory(null,browserDir,false);
242         }
243
244         // because this method is called for *every* VFS update,
245
// we don't want to scan the tree all the time. So we
246
// use the following algorithm to determine if the path
247
// might be part of the tree:
248
// - if the path starts with the browser's current directory,
249
// we do the tree scan
250
// - if the browser's directory is 'favorites:' -- we have to
251
// do the tree scan, as every path can appear under the
252
// favorites list
253
// - if the browser's directory is 'roots:' and path is on
254
// the local filesystem, do a tree scan
255

256         if(!browserDir.startsWith(FavoritesVFS.PROTOCOL)
257             && !browserDir.startsWith(FileRootsVFS.PROTOCOL)
258             && !path.startsWith(symlinkBrowserDir))
259             return;
260
261         if(browserDir.startsWith(FileRootsVFS.PROTOCOL)
262             && MiscUtilities.isURL(path)
263             && !MiscUtilities.getProtocolOfURL(path)
264             .equals("file"))
265             return;
266
267         table.maybeReloadDirectory(path);
268     } //}}}
269

270     //{{{ propertiesChanged() method
271
public void propertiesChanged()
272     {
273         showIcons = jEdit.getBooleanProperty("vfs.browser.showIcons");
274         table.propertiesChanged();
275         GUIUtilities.initContinuousLayout(splitPane);
276         splitPane.setBorder(null);
277     } //}}}
278

279     //{{{ getBrowser() method
280
/**
281      * Returns the associated <code>VFSBrowser</code> instance.
282      * @since jEdit 4.2pre1
283      */

284     public VFSBrowser getBrowser()
285     {
286         return browser;
287     } //}}}
288

289     //{{{ getTable() method
290
public VFSDirectoryEntryTable getTable()
291     {
292         return table;
293     } //}}}
294

295     //{{{ getParentDirectoryList() method
296
public JList getParentDirectoryList()
297     {
298         return parentDirectories;
299     } //}}}
300

301     //{{{ Private members
302

303     //{{{ Instance variables
304
private VFSBrowser browser;
305
306     private JSplitPane splitPane;
307     private JList parentDirectories;
308     private VFSDirectoryEntryTable table;
309     private Set tmpExpanded;
310     private BrowserCommandsMenu popup;
311     private boolean showIcons;
312     //}}}
313

314     //{{{ showFilePopup() method
315
private void showFilePopup(VFSFile[] files, Component comp,
316         Point point)
317     {
318         popup = new BrowserCommandsMenu(browser,files);
319         // for the parent directory right-click; on the click we select
320
// the clicked item, but when the popup goes away we select the
321
// currently showing directory.
322
popup.addPopupMenuListener(new PopupMenuListener()
323         {
324             public void popupMenuCanceled(PopupMenuEvent e) {}
325
326             public void popupMenuWillBecomeVisible(PopupMenuEvent e) {}
327
328             public void popupMenuWillBecomeInvisible(PopupMenuEvent e)
329             {
330                 // we use SwingUtilities.invokeLater()
331
// so that the action is executed before
332
// the popup is hidden.
333
SwingUtilities.invokeLater(new Runnable JavaDoc()
334                 {
335                     public void run()
336                     {
337                         int index = parentDirectories
338                             .getModel()
339                             .getSize() - 1;
340                         parentDirectories.setSelectedIndex(index);
341                     }
342                 });
343             }
344         });
345         GUIUtilities.showPopupMenu(popup,comp,point.x,point.y);
346     } //}}}
347

348     //}}}
349

350     //{{{ Inner classes
351

352     //{{{ ParentDirectoryRenderer class
353
class ParentDirectoryRenderer extends DefaultListCellRenderer
354     {
355         Font plainFont, boldFont;
356
357         ParentDirectoryRenderer()
358         {
359             plainFont = UIManager.getFont("Tree.font");
360             if(plainFont == null)
361                 plainFont = jEdit.getFontProperty("metal.secondary.font");
362             boldFont = new Font(plainFont.getName(),Font.BOLD,plainFont.getSize());
363         }
364
365         public Component getListCellRendererComponent(
366             JList list,
367             Object JavaDoc value,
368             int index,
369             boolean isSelected,
370             boolean cellHasFocus)
371         {
372             super.getListCellRendererComponent(list,value,index,
373                 isSelected,cellHasFocus);
374
375             ParentDirectoryRenderer.this.setBorder(new EmptyBorder JavaDoc(
376                 1,index * 5 + 1,1,1));
377
378             if(value instanceof LoadingPlaceholder)
379             {
380                 ParentDirectoryRenderer.this.setFont(plainFont);
381
382                 setIcon(showIcons ? FileCellRenderer.loadingIcon : null);
383                 setText(jEdit.getProperty("vfs.browser.tree.loading"));
384             }
385             else if(value instanceof VFSFile)
386             {
387                 VFSFile dirEntry = (VFSFile)value;
388                 ParentDirectoryRenderer.this.setFont(boldFont);
389
390                 setIcon(showIcons ? FileCellRenderer.getIconForFile(dirEntry,true)
391                     : null);
392                 setText(dirEntry.getName());
393             }
394             else if(value == null)
395                 setText("VFS does not follow VFS API");
396
397             return this;
398         }
399     } //}}}
400

401     //{{{ ParentMouseHandler class
402
class ParentMouseHandler extends MouseAdapter
403     {
404         public void mousePressed(MouseEvent evt)
405         {
406             int row = parentDirectories.locationToIndex(evt.getPoint());
407             if(row != -1)
408             {
409                 Object JavaDoc obj = parentDirectories.getModel()
410                     .getElementAt(row);
411                 if(obj instanceof VFSFile)
412                 {
413                     VFSFile dirEntry = ((VFSFile)obj);
414                     if(GUIUtilities.isPopupTrigger(evt))
415                     {
416                         if(popup != null && popup.isVisible())
417                         {
418                             popup.setVisible(false);
419                             popup = null;
420                         }
421                         else
422                         {
423                             parentDirectories.setSelectedIndex(row);
424                             showFilePopup(new VFSFile[] {
425                                 dirEntry },parentDirectories,
426                                 evt.getPoint());
427                         }
428                     }
429                 }
430             }
431         }
432
433         public void mouseReleased(MouseEvent evt)
434         {
435             if(evt.getClickCount() % 2 != 0 &&
436                 !GUIUtilities.isMiddleButton(evt.getModifiers()))
437                 return;
438
439             int row = parentDirectories.locationToIndex(evt.getPoint());
440             if(row != -1)
441             {
442                 Object JavaDoc obj = parentDirectories.getModel()
443                     .getElementAt(row);
444                 if(obj instanceof VFSFile)
445                 {
446                     VFSFile dirEntry = ((VFSFile)obj);
447                     if(!GUIUtilities.isPopupTrigger(evt))
448                     {
449                         browser.setDirectory(dirEntry.getPath());
450                         if(browser.getMode() == VFSBrowser.BROWSER)
451                         focusOnFileView();
452                     }
453                 }
454             }
455         }
456     } //}}}
457

458     //{{{ TableMouseHandler class
459
class TableMouseHandler extends MouseAdapter
460     {
461         //{{{ mouseClicked() method
462
public void mouseClicked(MouseEvent evt)
463         {
464             Point p = evt.getPoint();
465             int row = table.rowAtPoint(p);
466             int column = table.columnAtPoint(p);
467             if(row == -1)
468                 return;
469             if(column == 0)
470             {
471                 VFSDirectoryEntryTableModel.Entry entry
472                     = (VFSDirectoryEntryTableModel.Entry)
473                     table.getModel().getValueAt(row,0);
474                 if(FileCellRenderer.ExpansionToggleBorder
475                     .isExpansionToggle(entry.level,p.x))
476                 {
477                     return;
478                 }
479             }
480
481             if((evt.getModifiers() & InputEvent.BUTTON1_MASK) != 0
482                 && evt.getClickCount() % 2 == 0)
483             {
484                 browser.filesActivated((evt.isShiftDown()
485                     ? VFSBrowser.M_OPEN_NEW_VIEW
486                     : VFSBrowser.M_OPEN),true);
487             }
488             else if(GUIUtilities.isMiddleButton(evt.getModifiers()))
489             {
490                 if(evt.isShiftDown())
491                     table.getSelectionModel().addSelectionInterval(row,row);
492                 else
493                     table.getSelectionModel().setSelectionInterval(row,row);
494                 browser.filesActivated((evt.isShiftDown()
495                     ? VFSBrowser.M_OPEN_NEW_VIEW
496                     : VFSBrowser.M_OPEN),true);
497             }
498         } //}}}
499

500         //{{{ mousePressed() method
501
public void mousePressed(MouseEvent evt)
502         {
503             Point p = evt.getPoint();
504             if(evt.getSource() != table)
505             {
506                 p.x -= table.getX();
507                 p.y -= table.getY();
508             }
509
510             int row = table.rowAtPoint(p);
511             int column = table.columnAtPoint(p);
512             if(column == 0 && row != -1)
513             {
514                 VFSDirectoryEntryTableModel.Entry entry
515                     = (VFSDirectoryEntryTableModel.Entry)
516                     table.getModel().getValueAt(row,0);
517                 if(FileCellRenderer.ExpansionToggleBorder
518                     .isExpansionToggle(entry.level,p.x))
519                 {
520                     table.toggleExpanded(row);
521                     return;
522                 }
523             }
524
525             if(GUIUtilities.isMiddleButton(evt.getModifiers()))
526             {
527                 if(row == -1)
528                     /* nothing */;
529                 else if(evt.isShiftDown())
530                     table.getSelectionModel().addSelectionInterval(row,row);
531                 else
532                     table.getSelectionModel().setSelectionInterval(row,row);
533             }
534             else if(GUIUtilities.isPopupTrigger(evt))
535             {
536                 if(popup != null && popup.isVisible())
537                 {
538                     popup.setVisible(false);
539                     popup = null;
540                     return;
541                 }
542
543                 if(row == -1)
544                     showFilePopup(null,table,evt.getPoint());
545                 else
546                 {
547                     if(!table.getSelectionModel().isSelectedIndex(row))
548                         table.getSelectionModel().setSelectionInterval(row,row);
549                     showFilePopup(getSelectedFiles(),table,evt.getPoint());
550                 }
551             }
552         } //}}}
553

554         //{{{ mouseReleased() method
555
public void mouseReleased(MouseEvent evt)
556         {
557             if(!GUIUtilities.isPopupTrigger(evt)
558                 && table.getSelectedRow() != -1)
559             {
560                 browser.filesSelected();
561             }
562         } //}}}
563
} //}}}
564

565     static class LoadingPlaceholder {}
566     //}}}
567

568     class ParentDirectoryList extends JList
569     {
570
571         public String JavaDoc getPath(int row) {
572             LinkedList<String JavaDoc> components = new LinkedList<String JavaDoc>();
573             for (int i=1; i<=row; ++i) components.add(getModel().getElementAt(i).toString());
574             return getModel().getElementAt(0) + TextUtilities.join(components, File.separator);
575         }
576         protected void processKeyEvent(KeyEvent evt)
577         {
578             if (evt.getID() == KeyEvent.KEY_PRESSED) {
579                 ActionContext ac = VFSBrowser.getActionContext();
580                 int row = parentDirectories.getSelectedIndex();
581                 switch(evt.getKeyCode()) {
582                 case KeyEvent.VK_DOWN:
583                     evt.consume();
584                     if (row < parentDirectories.getSize().height-1)
585                         parentDirectories.setSelectedIndex(++row);
586                     break;
587                 case KeyEvent.VK_TAB:
588                           table.requestFocus();
589                           evt.consume();
590                           break;
591                 case KeyEvent.VK_UP :
592                     evt.consume();
593                     if (row > 0)
594                         parentDirectories.setSelectedIndex(--row);
595                     break;
596                 case KeyEvent.VK_BACK_SPACE:
597                     evt.consume();
598                     EditAction ea = ac.getAction("vfs.browser.up");
599                     ac.invokeAction(evt, ea);
600                     break;
601                 case KeyEvent.VK_F5:
602                     evt.consume();
603                     ac = VFSBrowser.getActionContext();
604                     ea = ac.getAction("vfs.browser.reload");
605                     ac.invokeAction(evt, ea);
606                     break;
607                 case KeyEvent.VK_ENTER:
608                     evt.consume();
609                     String JavaDoc path = getPath(row);
610                     getBrowser().setDirectory(path);
611                     table.requestFocus();
612                     break;
613 /* These actions don't work because they look at the EntryTable for the current selected
614  * item. We need actions that look at the parentDirectoryList item instead.
615  *
616                 case KeyEvent.VK_DELETE:
617                     evt.consume();
618                     ea = ac.getAction("vfs.browser.delete");
619                     ac.invokeAction(evt, ea);
620                     break;
621                 case KeyEvent.CTRL_MASK | KeyEvent.VK_N:
622                     evt.consume();
623                     ea = ac.getAction("vfs.browser.new-file");
624                     ac.invokeAction(evt, ea);
625                     break;
626                 case KeyEvent.VK_INSERT:
627                     evt.consume();
628                     ea = ac.getAction("vfs.browser.new-directory");
629                     ac.invokeAction(evt, ea);
630                     break; */

631                 }
632             }
633             else if(evt.getID() == KeyEvent.KEY_TYPED) {
634                 if(evt.isControlDown() || evt.isAltDown()
635                     || evt.isMetaDown())
636                 {
637                     evt.consume();
638                     return;
639                 }
640                 switch(evt.getKeyChar())
641                 {
642                 case '~':
643                     evt.consume();
644                     if(browser.getMode() == VFSBrowser.BROWSER)
645                         browser.setDirectory(System.getProperty(
646                             "user.home"));
647                     break;
648                 case '/':
649                     evt.consume();
650                     if(browser.getMode() == VFSBrowser.BROWSER)
651                         browser.rootDirectory();
652                     break;
653                 case '-':
654                     evt.consume();
655                     if(browser.getMode() == VFSBrowser.BROWSER)
656                     {
657                         browser.setDirectory(
658                             browser.getView().getBuffer()
659                             .getDirectory());
660                     }
661                     break; }
662             }
663             if (!evt.isConsumed()) super.processKeyEvent(evt);
664         }
665     }
666     
667 }
668
Popular Tags