You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TreeScroller.java 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. * Copyright (c) 2006-2010 Chris Smith, Shane Mc Cormack, Gregory Holmes
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. * SOFTWARE.
  21. */
  22. package com.dmdirc.addons.ui_swing.components;
  23. import java.awt.event.MouseWheelEvent;
  24. import java.awt.event.MouseWheelListener;
  25. import javax.swing.JTree;
  26. import javax.swing.tree.DefaultMutableTreeNode;
  27. import javax.swing.tree.DefaultTreeModel;
  28. import javax.swing.tree.TreePath;
  29. import javax.swing.tree.TreeSelectionModel;
  30. /**
  31. * Utility class to provide mouse wheel scrolling to a JTree.
  32. */
  33. public class TreeScroller implements MouseWheelListener {
  34. /** Tree to scroll. */
  35. private final DefaultTreeModel model;
  36. /** Tree to scroll. */
  37. private final TreeSelectionModel selectionModel;
  38. /** Root visible. */
  39. private final boolean rootVisible;
  40. /** Root node. */
  41. private final DefaultMutableTreeNode rootNode;
  42. /** Tree. */
  43. protected JTree tree;
  44. /**
  45. * Creates a new instance of TreeScroller.
  46. *
  47. * @param tree Tree to scroll over
  48. */
  49. public TreeScroller(final JTree tree) {
  50. this.tree = tree;
  51. this.model = (DefaultTreeModel) tree.getModel();
  52. this.selectionModel = tree.getSelectionModel();
  53. rootVisible = tree.isRootVisible();
  54. rootNode =
  55. (DefaultMutableTreeNode) tree.getModel().getRoot();
  56. tree.addMouseWheelListener(this);
  57. }
  58. /**
  59. * Creates a new instance of TreeScroller.
  60. *
  61. * @param model Tree model to scroll over
  62. * @param selectionModel Tree selection model to scroll over
  63. * @param rootVisible Is the root node visible
  64. */
  65. public TreeScroller(final DefaultTreeModel model,
  66. final TreeSelectionModel selectionModel, final boolean rootVisible) {
  67. this.model = model;
  68. this.selectionModel = selectionModel;
  69. this.rootVisible = rootVisible;
  70. rootNode = (DefaultMutableTreeNode) model.getRoot();
  71. }
  72. /**
  73. * {@inheritDoc}
  74. *
  75. * @param e Mouse wheel event
  76. */
  77. @Override
  78. public void mouseWheelMoved(final MouseWheelEvent e) {
  79. if (e.getWheelRotation() < 0) {
  80. changeFocus(true);
  81. } else {
  82. changeFocus(false);
  83. }
  84. }
  85. /**
  86. * Activates the node above or below the active node in the tree.
  87. *
  88. * @param direction true = up, false = down.
  89. */
  90. public void changeFocus(final boolean direction) {
  91. DefaultMutableTreeNode thisNode;
  92. DefaultMutableTreeNode nextNode;
  93. if (rootNode == null) {
  94. //no root node or root node not visible
  95. return;
  96. }
  97. if (!rootVisible && rootNode.getChildCount() == 0) {
  98. //root node has no children
  99. return;
  100. }
  101. if (selectionModel.isSelectionEmpty()) {
  102. if (rootVisible) {
  103. thisNode = rootNode;
  104. } else {
  105. thisNode = (DefaultMutableTreeNode) rootNode.getChildAt(0);
  106. }
  107. } else {
  108. thisNode = (DefaultMutableTreeNode) selectionModel.getSelectionPath().getLastPathComponent();
  109. }
  110. //are we going up or down?
  111. if (direction) {
  112. //up
  113. nextNode = changeFocusUp(thisNode);
  114. } else {
  115. //down
  116. nextNode = changeFocusDown(thisNode);
  117. }
  118. setPath(new TreePath(model.getPathToRoot(nextNode)));
  119. }
  120. /**
  121. * Sets the tree selection path.
  122. *
  123. * @param path Path
  124. */
  125. protected void setPath(final TreePath path) {
  126. selectionModel.setSelectionPath(path);
  127. }
  128. /**
  129. * Changes the tree focus up.
  130. *
  131. * @param node Start node
  132. *
  133. * @return next node
  134. */
  135. private DefaultMutableTreeNode changeFocusUp(final DefaultMutableTreeNode node) {
  136. DefaultMutableTreeNode nextNode;
  137. nextNode = node.getPreviousNode();
  138. if (nextNode == null || (nextNode == model.getRoot() && !rootVisible)) {
  139. nextNode = rootNode.getLastLeaf();
  140. }
  141. return nextNode;
  142. }
  143. /**
  144. * Changes the tree focus down.
  145. *
  146. * @param node Start node
  147. *
  148. * @return next node
  149. */
  150. private DefaultMutableTreeNode changeFocusDown(final DefaultMutableTreeNode node) {
  151. DefaultMutableTreeNode nextNode;
  152. nextNode = node.getNextNode();
  153. if (nextNode == null && !rootVisible) {
  154. nextNode =
  155. (DefaultMutableTreeNode) rootNode.getFirstChild();
  156. } else if (nextNode == null) {
  157. nextNode = (DefaultMutableTreeNode) model.getRoot();
  158. }
  159. return nextNode;
  160. }
  161. }