Advertisement
Guest User

Untitled

a guest
Jul 1st, 2016
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.07 KB | None | 0 0
  1. package CustonComponents;
  2.  
  3. import java.awt.BorderLayout;
  4. import java.awt.Component;
  5. import java.awt.event.MouseEvent;
  6. import java.awt.event.MouseListener;
  7. import java.util.EventListener;
  8. import java.util.EventObject;
  9. import java.util.HashMap;
  10. import java.util.HashSet;
  11.  
  12. import javax.swing.JCheckBox;
  13. import javax.swing.JPanel;
  14. import javax.swing.JTree;
  15. import javax.swing.event.EventListenerList;
  16. import javax.swing.tree.DefaultMutableTreeNode;
  17. import javax.swing.tree.DefaultTreeSelectionModel;
  18. import javax.swing.tree.TreeCellRenderer;
  19. import javax.swing.tree.TreeModel;
  20. import javax.swing.tree.TreeNode;
  21. import javax.swing.tree.TreePath;
  22.  
  23. public class JCheckBoxTree extends JTree {
  24.  
  25. private static final long serialVersionUID = -4194122328392241790L;
  26.  
  27. JCheckBoxTree selfPointer = this;
  28.  
  29. // Defining data structure that will enable to fast check-indicate the state of each node
  30. // It totally replaces the "selection" mechanism of the JTree
  31. private class CheckedNode {
  32.  
  33. boolean isSelected;
  34. boolean hasChildren;
  35. boolean allChildrenSelected;
  36.  
  37. public CheckedNode(boolean isSelected_, boolean hasChildren_, boolean allChildrenSelected_) {
  38. isSelected = isSelected_;
  39. hasChildren = hasChildren_;
  40. allChildrenSelected = allChildrenSelected_;
  41. }
  42. }
  43. HashMap<TreePath, CheckedNode> nodesCheckingState;
  44. HashSet<TreePath> checkedPaths = new HashSet<TreePath>();
  45.  
  46. // Defining a new event type for the checking mechanism and preparing event-handling mechanism
  47. protected EventListenerList listenerList = new EventListenerList();
  48.  
  49. public class CheckChangeEvent extends EventObject {
  50.  
  51. private static final long serialVersionUID = -8100230309044193368L;
  52.  
  53. public CheckChangeEvent(Object source) {
  54. super(source);
  55. }
  56. }
  57.  
  58. public interface CheckChangeEventListener extends EventListener {
  59.  
  60. public void checkStateChanged(CheckChangeEvent event);
  61. }
  62.  
  63. public void addCheckChangeEventListener(CheckChangeEventListener listener) {
  64. listenerList.add(CheckChangeEventListener.class, listener);
  65. }
  66.  
  67. public void removeCheckChangeEventListener(CheckChangeEventListener listener) {
  68. listenerList.remove(CheckChangeEventListener.class, listener);
  69. }
  70.  
  71. void fireCheckChangeEvent(CheckChangeEvent evt) {
  72. Object[] listeners = listenerList.getListenerList();
  73. for (int i = 0; i < listeners.length; i++) {
  74. if (listeners[i] == CheckChangeEventListener.class) {
  75. ((CheckChangeEventListener) listeners[i + 1]).checkStateChanged(evt);
  76. }
  77. }
  78. }
  79.  
  80. // Override
  81. public void setModel(TreeModel newModel) {
  82. super.setModel(newModel);
  83. resetCheckingState();
  84. }
  85.  
  86. // New method that returns only the checked paths (totally ignores original "selection" mechanism)
  87. public TreePath[] getCheckedPaths() {
  88. return checkedPaths.toArray(new TreePath[checkedPaths.size()]);
  89. }
  90.  
  91. // Returns true in case that the node is selected, has children but not all of them are selected
  92. public boolean isSelectedPartially(TreePath path) {
  93. CheckedNode cn = nodesCheckingState.get(path);
  94. return cn.isSelected && cn.hasChildren && !cn.allChildrenSelected;
  95. }
  96.  
  97. private void resetCheckingState() {
  98. nodesCheckingState = new HashMap<TreePath, CheckedNode>();
  99. checkedPaths = new HashSet<TreePath>();
  100. DefaultMutableTreeNode node = (DefaultMutableTreeNode) getModel().getRoot();
  101. if (node == null) {
  102. return;
  103. }
  104. addSubtreeToCheckingStateTracking(node);
  105. }
  106.  
  107. // Creating data structure of the current model for the checking mechanism
  108. private void addSubtreeToCheckingStateTracking(DefaultMutableTreeNode node) {
  109. TreeNode[] path = node.getPath();
  110. TreePath tp = new TreePath(path);
  111. CheckedNode cn = new CheckedNode(false, node.getChildCount() > 0, false);
  112. nodesCheckingState.put(tp, cn);
  113. for (int i = 0; i < node.getChildCount(); i++) {
  114. addSubtreeToCheckingStateTracking((DefaultMutableTreeNode) tp.pathByAddingChild(node.getChildAt(i)).getLastPathComponent());
  115. }
  116. }
  117.  
  118. // Overriding cell renderer by a class that ignores the original "selection" mechanism
  119. // It decides how to show the nodes due to the checking-mechanism
  120. private class CheckBoxCellRenderer extends JPanel implements TreeCellRenderer {
  121.  
  122. private static final long serialVersionUID = -7341833835878991719L;
  123. JCheckBox checkBox;
  124.  
  125. public CheckBoxCellRenderer() {
  126. super();
  127. this.setLayout(new BorderLayout());
  128. checkBox = new JCheckBox();
  129. add(checkBox, BorderLayout.CENTER);
  130. setOpaque(false);
  131. }
  132.  
  133. @Override
  134. public Component getTreeCellRendererComponent(JTree tree, Object value,
  135. boolean selected, boolean expanded, boolean leaf, int row,
  136. boolean hasFocus) {
  137. DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
  138. Object obj = node.getUserObject();
  139. TreePath tp = new TreePath(node.getPath());
  140. CheckedNode cn = nodesCheckingState.get(tp);
  141. if (cn == null) {
  142. return this;
  143. }
  144. checkBox.setSelected(cn.isSelected);
  145. checkBox.setText(obj.toString());
  146. checkBox.setOpaque(cn.isSelected && cn.hasChildren && !cn.allChildrenSelected);
  147. return this;
  148. }
  149. }
  150.  
  151. public JCheckBoxTree() {
  152. super();
  153. // Disabling toggling by double-click
  154. this.setToggleClickCount(0);
  155. // Overriding cell renderer by new one defined above
  156. CheckBoxCellRenderer cellRenderer = new CheckBoxCellRenderer();
  157. this.setCellRenderer(cellRenderer);
  158.  
  159. // Overriding selection model by an empty one
  160. DefaultTreeSelectionModel dtsm = new DefaultTreeSelectionModel() {
  161. private static final long serialVersionUID = -8190634240451667286L;
  162.  
  163. // Totally disabling the selection mechanism
  164. public void setSelectionPath(TreePath path) {
  165. }
  166.  
  167. public void addSelectionPath(TreePath path) {
  168. }
  169.  
  170. public void removeSelectionPath(TreePath path) {
  171. }
  172.  
  173. public void setSelectionPaths(TreePath[] pPaths) {
  174. }
  175. };
  176. // Calling checking mechanism on mouse click
  177. this.addMouseListener(new MouseListener() {
  178. public void mouseClicked(MouseEvent arg0) {
  179. TreePath tp = selfPointer.getPathForLocation(arg0.getX(), arg0.getY());
  180. if (tp == null) {
  181. return;
  182. }
  183. boolean checkMode = !nodesCheckingState.get(tp).isSelected;
  184. checkSubTree(tp, checkMode);
  185. updatePredecessorsWithCheckMode(tp, checkMode);
  186. // Firing the check change event
  187. fireCheckChangeEvent(new CheckChangeEvent(new Object()));
  188. // Repainting tree after the data structures were updated
  189. selfPointer.repaint();
  190. }
  191.  
  192. public void mouseEntered(MouseEvent arg0) {
  193. }
  194.  
  195. public void mouseExited(MouseEvent arg0) {
  196. }
  197.  
  198. public void mousePressed(MouseEvent arg0) {
  199. }
  200.  
  201. public void mouseReleased(MouseEvent arg0) {
  202. }
  203. });
  204. this.setSelectionModel(dtsm);
  205. }
  206.  
  207. // When a node is checked/unchecked, updating the states of the predecessors
  208. protected void updatePredecessorsWithCheckMode(TreePath tp, boolean check) {
  209. TreePath parentPath = tp.getParentPath();
  210. // If it is the root, stop the recursive calls and return
  211. if (parentPath == null) {
  212. return;
  213. }
  214. CheckedNode parentCheckedNode = nodesCheckingState.get(parentPath);
  215. DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) parentPath.getLastPathComponent();
  216. parentCheckedNode.allChildrenSelected = true;
  217. parentCheckedNode.isSelected = false;
  218. for (int i = 0; i < parentNode.getChildCount(); i++) {
  219. TreePath childPath = parentPath.pathByAddingChild(parentNode.getChildAt(i));
  220. CheckedNode childCheckedNode = nodesCheckingState.get(childPath);
  221. // It is enough that even one subtree is not fully selected
  222. // to determine that the parent is not fully selected
  223. if (!childCheckedNode.allChildrenSelected) {
  224. parentCheckedNode.allChildrenSelected = false;
  225. }
  226. // If at least one child is selected, selecting also the parent
  227. if (childCheckedNode.isSelected) {
  228. parentCheckedNode.isSelected = true;
  229. }
  230. }
  231. if (parentCheckedNode.isSelected) {
  232. checkedPaths.add(parentPath);
  233. } else {
  234. checkedPaths.remove(parentPath);
  235. }
  236. // Go to upper predecessor
  237. updatePredecessorsWithCheckMode(parentPath, check);
  238. }
  239.  
  240. // Recursively checks/unchecks a subtree
  241. protected void checkSubTree(TreePath tp, boolean check) {
  242. CheckedNode cn = nodesCheckingState.get(tp);
  243. cn.isSelected = check;
  244. DefaultMutableTreeNode node = (DefaultMutableTreeNode) tp.getLastPathComponent();
  245. for (int i = 0; i < node.getChildCount(); i++) {
  246. checkSubTree(tp.pathByAddingChild(node.getChildAt(i)), check);
  247. }
  248. cn.allChildrenSelected = check;
  249. if (check) {
  250. checkedPaths.add(tp);
  251. } else {
  252. checkedPaths.remove(tp);
  253. }
  254. }
  255.  
  256. }
  257.  
  258. package checkboxtree;
  259.  
  260. public class NovoJFrame extends javax.swing.JFrame {
  261.  
  262. public NovoJFrame() {
  263. initComponents();
  264. }
  265.  
  266. @SuppressWarnings("unchecked")
  267. // <editor-fold defaultstate="collapsed" desc="Generated Code">
  268. private void initComponents() {
  269.  
  270. jScrollPane1 = new javax.swing.JScrollPane();
  271. jCheckBoxTree1 = new CustonComponents.JCheckBoxTree();
  272.  
  273. setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
  274.  
  275. jScrollPane1.setViewportView(jCheckBoxTree1);
  276.  
  277. javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
  278. getContentPane().setLayout(layout);
  279. layout.setHorizontalGroup(
  280. layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  281. .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 152, javax.swing.GroupLayout.PREFERRED_SIZE)
  282. );
  283. layout.setVerticalGroup(
  284. layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  285. .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 245, javax.swing.GroupLayout.PREFERRED_SIZE)
  286. );
  287.  
  288. pack();
  289. }// </editor-fold>
  290.  
  291. /**
  292. * @param args the command line arguments
  293. */
  294. public static void main(String args[]) {
  295. /* Set the Nimbus look and feel */
  296. //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
  297. /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
  298. * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
  299. */
  300. try {
  301. for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
  302. if ("Nimbus".equals(info.getName())) {
  303. javax.swing.UIManager.setLookAndFeel(info.getClassName());
  304. break;
  305. }
  306. }
  307. } catch (ClassNotFoundException ex) {
  308. java.util.logging.Logger.getLogger(NovoJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
  309. } catch (InstantiationException ex) {
  310. java.util.logging.Logger.getLogger(NovoJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
  311. } catch (IllegalAccessException ex) {
  312. java.util.logging.Logger.getLogger(NovoJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
  313. } catch (javax.swing.UnsupportedLookAndFeelException ex) {
  314. java.util.logging.Logger.getLogger(NovoJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
  315. }
  316. //</editor-fold>
  317.  
  318. /* Create and display the form */
  319. java.awt.EventQueue.invokeLater(new Runnable() {
  320. public void run() {
  321. new NovoJFrame().setVisible(true);
  322. }
  323. });
  324. }
  325.  
  326. // Variables declaration - do not modify
  327. private CustonComponents.JCheckBoxTree jCheckBoxTree1;
  328. private javax.swing.JScrollPane jScrollPane1;
  329. // End of variables declaration
  330. }
  331.  
  332. public CheckedNode(boolean isSelected_, boolean hasChildren_, boolean allChildrenSelected_) {
  333. isSelected = isSelected_;
  334. hasChildren = hasChildren_;
  335. allChildrenSelected = allChildrenSelected_;
  336. }
  337.  
  338. CheckedNode cn = new CheckedNode(false, node.getChildCount() > 0, false);
  339.  
  340. CheckedNode cn = new CheckedNode(true, node.getChildCount() > 0, true);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement