Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

TreeScroller.java 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. * Copyright (c) 2006-2014 DMDirc Developers
  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 com.dmdirc.addons.ui_swing.UIUtilities;
  24. import java.awt.event.MouseWheelEvent;
  25. import java.awt.event.MouseWheelListener;
  26. import javax.swing.JTree;
  27. import javax.swing.tree.DefaultMutableTreeNode;
  28. import javax.swing.tree.DefaultTreeModel;
  29. import javax.swing.tree.TreePath;
  30. import javax.swing.tree.TreeSelectionModel;
  31. /**
  32. * Utility class to provide mouse wheel scrolling to a JTree.
  33. */
  34. public class TreeScroller implements MouseWheelListener {
  35. /** Tree to scroll. */
  36. private final DefaultTreeModel model;
  37. /** Tree to scroll. */
  38. private final TreeSelectionModel selectionModel;
  39. /** Root visible. */
  40. private final boolean rootVisible;
  41. /** Root node. */
  42. private final DefaultMutableTreeNode rootNode;
  43. /** Tree. */
  44. private JTree tree;
  45. /**
  46. * Creates a new instance of TreeScroller.
  47. *
  48. * @param tree Tree to scroll over
  49. */
  50. public TreeScroller(final JTree tree) {
  51. this.tree = tree;
  52. this.model = (DefaultTreeModel) tree.getModel();
  53. this.selectionModel = tree.getSelectionModel();
  54. rootVisible = tree.isRootVisible();
  55. rootNode = (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,
  67. final boolean rootVisible) {
  68. this.model = model;
  69. this.selectionModel = selectionModel;
  70. this.rootVisible = rootVisible;
  71. rootNode = (DefaultMutableTreeNode) model.getRoot();
  72. }
  73. /**
  74. * Registers a new tree scroller on the specified tree.
  75. *
  76. * @param tree Tree to scroll
  77. */
  78. public static void register(final JTree tree) {
  79. UIUtilities.invokeLater(() -> new TreeScroller(tree));
  80. }
  81. /**
  82. * Registers a new tree scroller for the specified models.
  83. *
  84. * @param model Tree model.
  85. * @param selectionModel Selection model.
  86. * @param rootVisible Root visible
  87. */
  88. public static void register(final DefaultTreeModel model,
  89. final TreeSelectionModel selectionModel,
  90. final boolean rootVisible) {
  91. UIUtilities.invokeLater(() -> new TreeScroller(model, selectionModel, rootVisible));
  92. }
  93. /**
  94. * Removes this tree scroller from the tree.
  95. */
  96. public void unregister() {
  97. if (tree != null) {
  98. tree.removeMouseWheelListener(this);
  99. }
  100. }
  101. @Override
  102. public void mouseWheelMoved(final MouseWheelEvent e) {
  103. if (e.getWheelRotation() < 0) {
  104. changeFocus(true);
  105. } else {
  106. changeFocus(false);
  107. }
  108. }
  109. /**
  110. * Activates the node above or below the active node in the tree.
  111. *
  112. * @param direction true = up, false = down.
  113. */
  114. public void changeFocus(final boolean direction) {
  115. final DefaultMutableTreeNode thisNode;
  116. final DefaultMutableTreeNode nextNode;
  117. if (rootNode == null) {
  118. //no root node or root node not visible
  119. return;
  120. }
  121. if (!rootVisible && rootNode.getChildCount() == 0) {
  122. //root node has no children
  123. return;
  124. }
  125. if (selectionModel.isSelectionEmpty()) {
  126. if (rootVisible) {
  127. thisNode = rootNode;
  128. } else {
  129. thisNode = (DefaultMutableTreeNode) rootNode.getChildAt(0);
  130. }
  131. } else {
  132. thisNode = (DefaultMutableTreeNode) selectionModel
  133. .getSelectionPath().getLastPathComponent();
  134. }
  135. //are we going up or down?
  136. if (direction) {
  137. //up
  138. nextNode = changeFocusUp(thisNode);
  139. } else {
  140. //down
  141. nextNode = changeFocusDown(thisNode);
  142. }
  143. setPath(new TreePath(model.getPathToRoot(nextNode)));
  144. }
  145. /**
  146. * Sets the tree selection path.
  147. *
  148. * @param path Path
  149. */
  150. protected void setPath(final TreePath path) {
  151. selectionModel.setSelectionPath(path);
  152. }
  153. /**
  154. * Changes the tree focus up.
  155. *
  156. * @param node Start node
  157. *
  158. * @return next node
  159. */
  160. private DefaultMutableTreeNode changeFocusUp(
  161. final DefaultMutableTreeNode node) {
  162. DefaultMutableTreeNode nextNode;
  163. nextNode = node.getPreviousNode();
  164. if (nextNode == null || (nextNode == model.getRoot() && !rootVisible)) {
  165. nextNode = rootNode.getLastLeaf();
  166. }
  167. return nextNode;
  168. }
  169. /**
  170. * Changes the tree focus down.
  171. *
  172. * @param node Start node
  173. *
  174. * @return next node
  175. */
  176. private DefaultMutableTreeNode changeFocusDown(
  177. final DefaultMutableTreeNode node) {
  178. DefaultMutableTreeNode nextNode;
  179. nextNode = node.getNextNode();
  180. if (nextNode == null && !rootVisible) {
  181. nextNode = (DefaultMutableTreeNode) rootNode.getFirstChild();
  182. } else if (nextNode == null) {
  183. nextNode = (DefaultMutableTreeNode) model.getRoot();
  184. }
  185. return nextNode;
  186. }
  187. }