PageRenderTime 46ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-1-pre5/org/gjt/sp/jedit/browser/BrowserView.java

#
Java | 910 lines | 672 code | 117 blank | 121 comment | 136 complexity | 248a446be5d150b1466e118c2385d679 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * BrowserView.java
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 2000, 2001, 2002 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. package org.gjt.sp.jedit.browser;
  23. //{{{ Imports
  24. import javax.swing.border.EmptyBorder;
  25. import javax.swing.event.*;
  26. import javax.swing.tree.*;
  27. import javax.swing.*;
  28. import java.awt.event.*;
  29. import java.awt.*;
  30. import java.io.File;
  31. import java.util.Enumeration;
  32. import java.util.Hashtable;
  33. import java.util.Vector;
  34. import org.gjt.sp.jedit.io.*;
  35. import org.gjt.sp.jedit.*;
  36. //}}}
  37. /**
  38. * VFS browser tree view.
  39. * @author Slava Pestov
  40. * @version $Id: BrowserView.java 4310 2002-08-16 18:02:18Z spestov $
  41. */
  42. class BrowserView extends JPanel
  43. {
  44. //{{{ BrowserView constructor
  45. public BrowserView(VFSBrowser browser, final boolean splitHorizontally)
  46. {
  47. this.browser = browser;
  48. this.splitHorizontally = splitHorizontally;
  49. parentDirectories = new JList();
  50. parentDirectories.getSelectionModel().setSelectionMode(
  51. TreeSelectionModel.SINGLE_TREE_SELECTION);
  52. parentDirectories.setCellRenderer(new ParentDirectoryRenderer());
  53. parentDirectories.setVisibleRowCount(5);
  54. parentDirectories.addMouseListener(new MouseHandler());
  55. rootNode = new DefaultMutableTreeNode(null,true);
  56. model = new DefaultTreeModel(rootNode,true);
  57. tree = new BrowserJTree(model);
  58. tree.setCellRenderer(renderer);
  59. tree.setEditable(false);
  60. tree.addTreeExpansionListener(new TreeHandler());
  61. // looks bad with the OS X L&F, apparently...
  62. if(!OperatingSystem.isMacOSLF())
  63. tree.putClientProperty("JTree.lineStyle", "Angled");
  64. tree.setRootVisible(false);
  65. tree.setShowsRootHandles(true);
  66. tree.setVisibleRowCount(12);
  67. final JScrollPane parentScroller = new JScrollPane(parentDirectories);
  68. parentScroller.setMinimumSize(new Dimension(0,0));
  69. JScrollPane treeScroller = new JScrollPane(tree);
  70. treeScroller.setMinimumSize(new Dimension(0,0));
  71. splitPane = new JSplitPane(
  72. splitHorizontally ? JSplitPane.HORIZONTAL_SPLIT : JSplitPane.VERTICAL_SPLIT,
  73. parentScroller,treeScroller);
  74. splitPane.setOneTouchExpandable(true);
  75. SwingUtilities.invokeLater(new Runnable()
  76. {
  77. public void run()
  78. {
  79. String prop = splitHorizontally ? "vfs.browser.horizontalSplitter" : "vfs.browser.splitter";
  80. int loc = jEdit.getIntegerProperty(prop,-1);
  81. if(loc == -1)
  82. loc = parentScroller.getPreferredSize().height;
  83. splitPane.setDividerLocation(loc);
  84. parentDirectories.ensureIndexIsVisible(
  85. parentDirectories.getModel()
  86. .getSize());
  87. }
  88. });
  89. tmpExpanded = new Hashtable();
  90. if(browser.isMultipleSelectionEnabled())
  91. tree.getSelectionModel().setSelectionMode(
  92. TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
  93. else
  94. tree.getSelectionModel().setSelectionMode(
  95. TreeSelectionModel.SINGLE_TREE_SELECTION);
  96. setLayout(new BorderLayout());
  97. add(BorderLayout.CENTER,splitPane);
  98. propertiesChanged();
  99. } //}}}
  100. //{{{ focusOnFileView() method
  101. public void focusOnFileView()
  102. {
  103. tree.requestFocus();
  104. } //}}}
  105. //{{{ removeNotify() method
  106. public void removeNotify()
  107. {
  108. String prop = splitHorizontally ? "vfs.browser.horizontalSplitter" : "vfs.browser.splitter";
  109. jEdit.setIntegerProperty(prop,splitPane.getDividerLocation());
  110. super.removeNotify();
  111. } //}}}
  112. //{{{ getSelectedFiles() method
  113. public VFS.DirectoryEntry[] getSelectedFiles()
  114. {
  115. Vector selected = new Vector(tree.getSelectionCount());
  116. TreePath[] paths = tree.getSelectionPaths();
  117. if(paths == null)
  118. return new VFS.DirectoryEntry[0];
  119. for(int i = 0; i < paths.length; i++)
  120. {
  121. DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)
  122. paths[i].getLastPathComponent();
  123. Object obj = treeNode.getUserObject();
  124. if(obj instanceof VFS.DirectoryEntry)
  125. selected.addElement(obj);
  126. }
  127. VFS.DirectoryEntry[] retVal = new VFS.DirectoryEntry[selected.size()];
  128. selected.copyInto(retVal);
  129. return retVal;
  130. } //}}}
  131. //{{{ selectNone() method
  132. public void selectNone()
  133. {
  134. tree.setSelectionPaths(new TreePath[0]);
  135. } //}}}
  136. //{{{ loadDirectory() method
  137. public void loadDirectory(String path)
  138. {
  139. // called by VFSBrowser.setDirectory()
  140. tmpExpanded.clear();
  141. loadDirectory(rootNode,path,false);
  142. } //}}}
  143. //{{{ directoryLoaded() method
  144. public void directoryLoaded(DefaultMutableTreeNode node,
  145. String path, Vector directory)
  146. {
  147. if(node == rootNode)
  148. {
  149. DefaultListModel parentList = new DefaultListModel();
  150. String parent = path;
  151. if(parent.length() != 1 && (parent.endsWith("/")
  152. || parent.endsWith(File.separator)))
  153. parent = parent.substring(0,parent.length() - 1);
  154. for(;;)
  155. {
  156. VFS _vfs = VFSManager.getVFSForPath(
  157. parent);
  158. // create a DirectoryEntry manually
  159. // instead of using _vfs._getDirectoryEntry()
  160. // since so many VFS's have broken
  161. // implementations of this method
  162. parentList.insertElementAt(new VFS.DirectoryEntry(
  163. _vfs.getFileName(parent),
  164. parent,parent,
  165. VFS.DirectoryEntry.DIRECTORY,
  166. 0L,false),0);
  167. String newParent = _vfs.getParentOfPath(parent);
  168. if(newParent.length() != 1 && (newParent.endsWith("/")
  169. || newParent.endsWith(File.separator)))
  170. newParent = newParent.substring(0,newParent.length() - 1);
  171. if(newParent == null || parent.equals(newParent))
  172. break;
  173. else
  174. parent = newParent;
  175. }
  176. parentDirectories.setModel(parentList);
  177. int index = parentList.getSize() - 1;
  178. parentDirectories.setSelectedIndex(index);
  179. parentDirectories.ensureIndexIsVisible(index);
  180. }
  181. node.removeAllChildren();
  182. Vector toExpand = new Vector();
  183. if(directory != null)
  184. {
  185. for(int i = 0; i < directory.size(); i++)
  186. {
  187. VFS.DirectoryEntry file = (VFS.DirectoryEntry)
  188. directory.elementAt(i);
  189. boolean allowsChildren = (file.type != VFS.DirectoryEntry.FILE);
  190. DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(file,allowsChildren);
  191. node.add(newNode);
  192. if(tmpExpanded.get(file.path) != null)
  193. {
  194. tmpExpanded.remove(file.path);
  195. toExpand.addElement(new TreePath(newNode.getPath()));
  196. }
  197. }
  198. }
  199. // fire events
  200. model.reload(node);
  201. tree.expandPath(new TreePath(node.getPath()));
  202. // expand branches that were expanded before
  203. for(int i = 0; i < toExpand.size(); i++)
  204. {
  205. TreePath treePath = (TreePath)toExpand.elementAt(i);
  206. tree.expandPath(treePath);
  207. }
  208. timer.stop();
  209. typeSelectBuffer.setLength(0);
  210. } //}}}
  211. //{{{ updateFileView() method
  212. public void updateFileView()
  213. {
  214. tree.repaint();
  215. } //}}}
  216. //{{{ maybeReloadDirectory() method
  217. public void maybeReloadDirectory(String path)
  218. {
  219. tmpExpanded.clear();
  220. // because this method is called for *every* VFS update,
  221. // we don't want to scan the tree all the time. So we
  222. // use the following algorithm to determine if the path
  223. // might be part of the tree:
  224. // - if the path starts with the browser's current directory,
  225. // we do the tree scan
  226. // - if the browser's directory is 'favorites:' -- we have to
  227. // do the tree scan, as every path can appear under the
  228. // favorites list
  229. // - if the browser's directory is 'roots:' and path is on
  230. // the local filesystem, do a tree scan
  231. String browserDir = browser.getDirectory();
  232. if(browserDir.startsWith(FavoritesVFS.PROTOCOL))
  233. maybeReloadDirectory(rootNode,path);
  234. else if(browserDir.startsWith(FileRootsVFS.PROTOCOL))
  235. {
  236. if(!MiscUtilities.isURL(path) || MiscUtilities.getProtocolOfURL(path)
  237. .equals("file"))
  238. maybeReloadDirectory(rootNode,path);
  239. }
  240. else if(path.startsWith(browserDir))
  241. maybeReloadDirectory(rootNode,path);
  242. } //}}}
  243. //{{{ getDefaultFocusComponent() method
  244. public Component getDefaultFocusComponent()
  245. {
  246. return tree;
  247. } //}}}
  248. //{{{ propertiesChanged() method
  249. public void propertiesChanged()
  250. {
  251. showIcons = jEdit.getBooleanProperty("vfs.browser.showIcons");
  252. renderer.propertiesChanged();
  253. tree.setRowHeight(renderer.getTreeCellRendererComponent(
  254. tree,new DefaultMutableTreeNode("foo"),
  255. false,false,false,0,false).getSize().height);
  256. splitPane.setBorder(null);
  257. } //}}}
  258. //{{{ getTree() method
  259. public BrowserJTree getTree()
  260. {
  261. return tree;
  262. } //}}}
  263. //{{{ Private members
  264. //{{{ Instance variables
  265. private VFSBrowser browser;
  266. private JSplitPane splitPane;
  267. private JList parentDirectories;
  268. private BrowserJTree tree;
  269. private Hashtable tmpExpanded;
  270. private DefaultTreeModel model;
  271. private DefaultMutableTreeNode rootNode;
  272. private BrowserCommandsMenu popup;
  273. private boolean showIcons;
  274. private boolean splitHorizontally;
  275. private FileCellRenderer renderer = new FileCellRenderer();
  276. private StringBuffer typeSelectBuffer = new StringBuffer();
  277. private Timer timer = new Timer(0,new ClearTypeSelect());
  278. //}}}
  279. //{{{ maybeReloadDirectory() method
  280. private boolean maybeReloadDirectory(DefaultMutableTreeNode node, String path)
  281. {
  282. // nodes which are not expanded need not be checked
  283. if(!tree.isExpanded(new TreePath(node.getPath())))
  284. return false;
  285. if(node == rootNode && path.equals(browser.getDirectory()))
  286. {
  287. loadDirectory(rootNode,path,false);
  288. return true;
  289. }
  290. Object userObject = node.getUserObject();
  291. if(userObject instanceof VFS.DirectoryEntry)
  292. {
  293. VFS.DirectoryEntry file = (VFS.DirectoryEntry)userObject;
  294. // we don't need to do anything with files!
  295. if(file.type == VFS.DirectoryEntry.FILE)
  296. return false;
  297. if(path.equals(file.path))
  298. {
  299. loadDirectory(node,path,false);
  300. return true;
  301. }
  302. }
  303. if(node.getChildCount() != 0)
  304. {
  305. Enumeration children = node.children();
  306. while(children.hasMoreElements())
  307. {
  308. DefaultMutableTreeNode child = (DefaultMutableTreeNode)
  309. children.nextElement();
  310. if(maybeReloadDirectory(child,path))
  311. return true;
  312. }
  313. }
  314. return false;
  315. } //}}}
  316. //{{{ loadDirectory() method
  317. private void loadDirectory(DefaultMutableTreeNode node, String path,
  318. boolean showLoading)
  319. {
  320. saveExpansionState(node);
  321. path = MiscUtilities.constructPath(browser.getDirectory(),path);
  322. VFS vfs = VFSManager.getVFSForPath(path);
  323. Object session = vfs.createVFSSession(path,this);
  324. if(session == null)
  325. return;
  326. if(node == rootNode)
  327. {
  328. setListModel(parentDirectories,new Object[] {
  329. new LoadingPlaceholder() });
  330. }
  331. if(showLoading)
  332. {
  333. node.removeAllChildren();
  334. node.add(new DefaultMutableTreeNode(new LoadingPlaceholder(),false));
  335. model.reload(node);
  336. }
  337. VFSManager.runInWorkThread(new BrowserIORequest(
  338. BrowserIORequest.LIST_DIRECTORY,browser,
  339. session,vfs,path,null,node,node == rootNode));
  340. } //}}}
  341. //{{{ saveExpansionState() method
  342. private void saveExpansionState(DefaultMutableTreeNode node)
  343. {
  344. for(int i = 0; i < node.getChildCount(); i++)
  345. {
  346. DefaultMutableTreeNode child = (DefaultMutableTreeNode)
  347. node.getChildAt(i);
  348. TreePath treePath = new TreePath(child.getPath());
  349. if(tree.isExpanded(treePath))
  350. {
  351. VFS.DirectoryEntry file = ((VFS.DirectoryEntry)
  352. child.getUserObject());
  353. tmpExpanded.put(file.path,file.path);
  354. if(file.type != VFS.DirectoryEntry.FILE)
  355. saveExpansionState(child);
  356. }
  357. }
  358. } //}}}
  359. //{{{ showFilePopup() method
  360. private void showFilePopup(VFS.DirectoryEntry[] files, Component comp,
  361. Point point)
  362. {
  363. popup = new BrowserCommandsMenu(browser,files);
  364. // for the parent directory right-click; on the click we select
  365. // the clicked item, but when the popup goes away we select the
  366. // currently showing directory.
  367. popup.addPopupMenuListener(new PopupMenuListener()
  368. {
  369. public void popupMenuCanceled(PopupMenuEvent e) {}
  370. public void popupMenuWillBecomeVisible(PopupMenuEvent e) {}
  371. public void popupMenuWillBecomeInvisible(PopupMenuEvent e)
  372. {
  373. int index = parentDirectories.getModel().getSize() - 1;
  374. parentDirectories.setSelectedIndex(index);
  375. }
  376. });
  377. GUIUtilities.showPopupMenu(popup,comp,point.x,point.y);
  378. } //}}}
  379. //{{{ setListModel() method
  380. /**
  381. * This should be in the JDK API.
  382. */
  383. private void setListModel(JList list, final Object[] model)
  384. {
  385. list.setModel(new AbstractListModel()
  386. {
  387. public int getSize() { return model.length; }
  388. public Object getElementAt(int i) { return model[i]; }
  389. });
  390. } //}}}
  391. //}}}
  392. //{{{ Inner classes
  393. //{{{ ClearTypeSelect
  394. class ClearTypeSelect implements ActionListener
  395. {
  396. public void actionPerformed(ActionEvent evt)
  397. {
  398. typeSelectBuffer.setLength(0);
  399. browser.filesSelected();
  400. }
  401. } //}}}
  402. //{{{ ParentDirectoryRenderer class
  403. class ParentDirectoryRenderer extends DefaultListCellRenderer
  404. {
  405. Font plainFont, boldFont;
  406. ParentDirectoryRenderer()
  407. {
  408. plainFont = UIManager.getFont("Tree.font");
  409. boldFont = new Font(plainFont.getName(),Font.BOLD,plainFont.getSize());
  410. }
  411. public Component getListCellRendererComponent(
  412. JList list,
  413. Object value,
  414. int index,
  415. boolean isSelected,
  416. boolean cellHasFocus)
  417. {
  418. super.getListCellRendererComponent(list,value,index,
  419. isSelected,cellHasFocus);
  420. ParentDirectoryRenderer.this.setBorder(new EmptyBorder(
  421. 1,index * 5 + 1,1,1));
  422. if(value instanceof LoadingPlaceholder)
  423. {
  424. ParentDirectoryRenderer.this.setFont(plainFont);
  425. setIcon(showIcons ? FileCellRenderer.loadingIcon : null);
  426. setText(jEdit.getProperty("vfs.browser.tree.loading"));
  427. }
  428. else if(value instanceof VFS.DirectoryEntry)
  429. {
  430. VFS.DirectoryEntry dirEntry = (VFS.DirectoryEntry)value;
  431. ParentDirectoryRenderer.this.setFont(boldFont);
  432. setIcon(showIcons ? FileCellRenderer.getIconForFile(dirEntry,true)
  433. : null);
  434. setText(dirEntry.name);
  435. }
  436. else if(value == null)
  437. setText("VFS does not follow VFS API");
  438. return this;
  439. }
  440. } //}}}
  441. //{{{ MouseHandler class
  442. class MouseHandler extends MouseAdapter
  443. {
  444. public void mousePressed(MouseEvent evt)
  445. {
  446. int row = parentDirectories.locationToIndex(evt.getPoint());
  447. if(row != -1)
  448. {
  449. Object obj = parentDirectories.getModel()
  450. .getElementAt(row);
  451. if(obj instanceof VFS.DirectoryEntry)
  452. {
  453. VFS.DirectoryEntry dirEntry = ((VFS.DirectoryEntry)obj);
  454. if(GUIUtilities.isPopupTrigger(evt))
  455. {
  456. if(popup != null && popup.isVisible())
  457. {
  458. popup.setVisible(false);
  459. popup = null;
  460. }
  461. else
  462. {
  463. parentDirectories.setSelectedIndex(row);
  464. showFilePopup(new VFS.DirectoryEntry[] {
  465. dirEntry },parentDirectories,
  466. evt.getPoint());
  467. }
  468. }
  469. }
  470. }
  471. }
  472. public void mouseReleased(MouseEvent evt)
  473. {
  474. // ignore double clicks
  475. if(evt.getClickCount() % 2 == 0)
  476. return;
  477. int row = parentDirectories.locationToIndex(evt.getPoint());
  478. if(row != -1)
  479. {
  480. Object obj = parentDirectories.getModel()
  481. .getElementAt(row);
  482. if(obj instanceof VFS.DirectoryEntry)
  483. {
  484. VFS.DirectoryEntry dirEntry = ((VFS.DirectoryEntry)obj);
  485. if(!GUIUtilities.isPopupTrigger(evt))
  486. {
  487. browser.setDirectory(dirEntry.path);
  488. focusOnFileView();
  489. }
  490. }
  491. }
  492. }
  493. } //}}}
  494. //{{{ BrowserJTree class
  495. class BrowserJTree extends JTree
  496. {
  497. //{{{ BrowserJTree constructor
  498. BrowserJTree(TreeModel model)
  499. {
  500. super(model);
  501. ToolTipManager.sharedInstance().registerComponent(this);
  502. } //}}}
  503. //{{{ getToolTipText() method
  504. public final String getToolTipText(MouseEvent evt)
  505. {
  506. TreePath path = getPathForLocation(evt.getX(), evt.getY());
  507. if(path != null)
  508. {
  509. Rectangle cellRect = getPathBounds(path);
  510. if(cellRect != null && !cellRectIsVisible(cellRect))
  511. return path.getLastPathComponent().toString();
  512. }
  513. return null;
  514. } //}}}
  515. //{{{ getToolTipLocation() method
  516. public final Point getToolTipLocation(MouseEvent evt)
  517. {
  518. TreePath path = getPathForLocation(evt.getX(), evt.getY());
  519. if(path != null)
  520. {
  521. Rectangle cellRect = getPathBounds(path);
  522. if(cellRect != null && !cellRectIsVisible(cellRect))
  523. {
  524. return new Point(cellRect.x + (showIcons ? 14 : - 4),
  525. cellRect.y);
  526. }
  527. }
  528. return null;
  529. } //}}}
  530. //{{{ processKeyEvent() method
  531. public void processKeyEvent(KeyEvent evt)
  532. {
  533. // could make things somewhat easier...
  534. // ... but KeyEventWorkaround 'output contract' will
  535. // change in 4.1, so not a good idea
  536. //evt = KeyEventWorkaround.processKeyEvent(evt);
  537. //if(evt == null)
  538. // return;
  539. if(evt.getID() == KeyEvent.KEY_PRESSED)
  540. {
  541. switch(evt.getKeyCode())
  542. {
  543. case KeyEvent.VK_UP:
  544. case KeyEvent.VK_DOWN:
  545. super.processKeyEvent(evt);
  546. if(browser.getMode() != VFSBrowser.BROWSER)
  547. browser.filesSelected();
  548. break;
  549. case KeyEvent.VK_ENTER:
  550. browser.filesActivated((evt.isShiftDown()
  551. ? VFSBrowser.M_OPEN_NEW_VIEW
  552. : VFSBrowser.M_OPEN),false);
  553. evt.consume();
  554. break;
  555. case KeyEvent.VK_LEFT:
  556. String directory = browser.getDirectory();
  557. browser.setDirectory(MiscUtilities
  558. .getParentOfPath(directory));
  559. evt.consume();
  560. break;
  561. }
  562. }
  563. else if(evt.getID() == KeyEvent.KEY_TYPED)
  564. {
  565. if(evt.isControlDown() || evt.isAltDown()
  566. || evt.isMetaDown())
  567. {
  568. return;
  569. }
  570. // hack...
  571. if(evt.isShiftDown() && evt.getKeyChar() == '\n')
  572. return;
  573. switch(evt.getKeyChar())
  574. {
  575. case '~':
  576. browser.setDirectory(System.getProperty("user.home"));
  577. break;
  578. case '/':
  579. browser.rootDirectory();
  580. break;
  581. case '-':
  582. View view = browser.getView();
  583. Buffer buffer = view.getBuffer();
  584. browser.setDirectory(MiscUtilities.getParentOfPath(
  585. buffer.getPath()));
  586. break;
  587. default:
  588. typeSelectBuffer.append(evt.getKeyChar());
  589. doTypeSelect(typeSelectBuffer.toString(),true);
  590. timer.stop();
  591. timer.setInitialDelay(750);
  592. timer.setRepeats(false);
  593. timer.start();
  594. break;
  595. }
  596. return;
  597. }
  598. if(!evt.isConsumed())
  599. super.processKeyEvent(evt);
  600. } //}}}
  601. //{{{ processMouseEvent() method
  602. protected void processMouseEvent(MouseEvent evt)
  603. {
  604. ToolTipManager ttm = ToolTipManager.sharedInstance();
  605. TreePath path = getPathForLocation(evt.getX(),evt.getY());
  606. switch(evt.getID())
  607. {
  608. //{{{ MOUSE_ENTERED...
  609. case MouseEvent.MOUSE_ENTERED:
  610. toolTipInitialDelay = ttm.getInitialDelay();
  611. toolTipReshowDelay = ttm.getReshowDelay();
  612. ttm.setInitialDelay(200);
  613. ttm.setReshowDelay(0);
  614. super.processMouseEvent(evt);
  615. break; //}}}
  616. //{{{ MOUSE_EXITED...
  617. case MouseEvent.MOUSE_EXITED:
  618. ttm.setInitialDelay(toolTipInitialDelay);
  619. ttm.setReshowDelay(toolTipReshowDelay);
  620. super.processMouseEvent(evt);
  621. break; //}}}
  622. //{{{ MOUSE_CLICKED...
  623. case MouseEvent.MOUSE_CLICKED:
  624. if(path != null)
  625. {
  626. if((evt.getModifiers() & MouseEvent.BUTTON1_MASK) != 0)
  627. {
  628. // A double click is not only when clickCount == 2
  629. // because every other click can open a new directory
  630. if(evt.getClickCount() % 2 == 0)
  631. {
  632. setSelectionPath(path);
  633. // don't pass double-clicks to tree, otherwise
  634. // directory nodes will be expanded and we don't
  635. // want that
  636. browser.filesActivated((evt.isShiftDown()
  637. ? VFSBrowser.M_OPEN_NEW_VIEW
  638. : VFSBrowser.M_OPEN),true);
  639. break;
  640. }
  641. else
  642. {
  643. if(!isPathSelected(path))
  644. setSelectionPath(path);
  645. }
  646. }
  647. if((evt.getModifiers() & MouseEvent.BUTTON2_MASK) != 0)
  648. {
  649. setSelectionPath(path);
  650. browser.filesActivated((evt.isShiftDown()
  651. ? VFSBrowser.M_OPEN_NEW_VIEW
  652. : VFSBrowser.M_OPEN),true);
  653. }
  654. super.processMouseEvent(evt);
  655. break;
  656. }
  657. else if(GUIUtilities.isPopupTrigger(evt))
  658. break;
  659. //}}}
  660. //{{{ MOUSE_PRESSED...
  661. case MouseEvent.MOUSE_PRESSED:
  662. if((evt.getModifiers() & MouseEvent.BUTTON1_MASK) != 0)
  663. {
  664. if(evt.getClickCount() % 2 == 0)
  665. break;
  666. }
  667. else if(GUIUtilities.isPopupTrigger(evt))
  668. {
  669. if(popup != null && popup.isVisible())
  670. {
  671. popup.setVisible(false);
  672. popup = null;
  673. break;
  674. }
  675. if(path == null)
  676. showFilePopup(null,this,evt.getPoint());
  677. else
  678. {
  679. if(!isPathSelected(path))
  680. setSelectionPath(path);
  681. showFilePopup(getSelectedFiles(),this,evt.getPoint());
  682. }
  683. break;
  684. }
  685. super.processMouseEvent(evt);
  686. break;
  687. //}}}
  688. //{{{ MOUSE_RELEASED...
  689. case MouseEvent.MOUSE_RELEASED:
  690. if(!GUIUtilities.isPopupTrigger(evt)
  691. && path != null)
  692. {
  693. browser.filesSelected();
  694. }
  695. if(evt.getClickCount() % 2 != 0)
  696. super.processMouseEvent(evt);
  697. break;
  698. //}}}
  699. default:
  700. super.processMouseEvent(evt);
  701. break;
  702. }
  703. } //}}}
  704. //{{{ Private members
  705. private int toolTipInitialDelay = -1;
  706. private int toolTipReshowDelay = -1;
  707. //{{{ cellRectIsVisible() method
  708. private boolean cellRectIsVisible(Rectangle cellRect)
  709. {
  710. Rectangle vr = BrowserJTree.this.getVisibleRect();
  711. return vr.contains(cellRect.x,cellRect.y) &&
  712. vr.contains(cellRect.x + cellRect.width,
  713. cellRect.y + cellRect.height);
  714. } //}}}
  715. //{{{ doTypeSelect() method
  716. void doTypeSelect(String str, boolean ignoreCase)
  717. {
  718. if(getSelectionCount() == 0)
  719. doTypeSelect(str,0,getRowCount(),ignoreCase);
  720. else
  721. {
  722. int start = getMaxSelectionRow();
  723. boolean retVal = doTypeSelect(str,start,getRowCount(),
  724. ignoreCase);
  725. if(!retVal)
  726. {
  727. // scan from selection to end failed, so
  728. // scan from start to selection
  729. doTypeSelect(str,0,start,ignoreCase);
  730. }
  731. }
  732. } //}}}
  733. //{{{ doTypeSelect() method
  734. private boolean doTypeSelect(String str, int start, int end,
  735. boolean ignoreCase)
  736. {
  737. for(int i = start; i < end; i++)
  738. {
  739. DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)
  740. getPathForRow(i).getLastPathComponent();
  741. Object obj = treeNode.getUserObject();
  742. if(obj instanceof VFS.DirectoryEntry)
  743. {
  744. VFS.DirectoryEntry file = (VFS.DirectoryEntry)obj;
  745. if(file.name.regionMatches(ignoreCase,
  746. 0,str,0,str.length()))
  747. {
  748. setSelectionRow(i);
  749. scrollRowToVisible(i);
  750. return true;
  751. }
  752. }
  753. }
  754. return false;
  755. } //}}}
  756. //}}}
  757. } //}}}
  758. //{{{ TreeHandler class
  759. class TreeHandler implements TreeExpansionListener
  760. {
  761. //{{{ treeExpanded() method
  762. public void treeExpanded(TreeExpansionEvent evt)
  763. {
  764. TreePath path = evt.getPath();
  765. DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)
  766. path.getLastPathComponent();
  767. Object userObject = treeNode.getUserObject();
  768. if(userObject instanceof VFS.DirectoryEntry)
  769. {
  770. loadDirectory(treeNode,((VFS.DirectoryEntry)
  771. userObject).path,true);
  772. }
  773. } //}}}
  774. //{{{ treeCollapsed() method
  775. public void treeCollapsed(TreeExpansionEvent evt)
  776. {
  777. TreePath path = evt.getPath();
  778. DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)
  779. path.getLastPathComponent();
  780. if(treeNode.getUserObject() instanceof VFS.DirectoryEntry)
  781. {
  782. // we add the placeholder so that the node has
  783. // 1 child (otherwise the user won't be able to
  784. // expand it again)
  785. treeNode.removeAllChildren();
  786. treeNode.add(new DefaultMutableTreeNode(new LoadingPlaceholder(),false));
  787. model.reload(treeNode);
  788. }
  789. } //}}}
  790. } //}}}
  791. static class LoadingPlaceholder {}
  792. //}}}
  793. }