View Javadoc
1   /*******************************************************************************
2    * Copyhacked (H) 2012-2025.
3    * This program and the accompanying materials
4    * are made available under no term at all, use it like
5    * you want, but share and discuss it
6    * every time possible with every body.
7    * 
8    * Contributors:
9    *      ron190 at ymail dot com - initial implementation
10   ******************************************************************************/
11  package com.jsql.view.swing.tree;
12  
13  import com.jsql.util.LogLevelUtil;
14  import com.jsql.view.swing.tree.action.ActionCheckSingle;
15  import com.jsql.view.swing.tree.model.AbstractNodeModel;
16  import com.jsql.view.swing.util.MediatorHelper;
17  import org.apache.logging.log4j.LogManager;
18  import org.apache.logging.log4j.Logger;
19  
20  import javax.swing.*;
21  import javax.swing.event.TreeSelectionEvent;
22  import javax.swing.event.TreeSelectionListener;
23  import javax.swing.tree.DefaultMutableTreeNode;
24  import javax.swing.tree.TreeCellEditor;
25  import javax.swing.tree.TreePath;
26  import java.awt.*;
27  import java.awt.event.MouseEvent;
28  import java.awt.event.MouseListener;
29  
30  /**
31   * Tree cell editor responsible for mouse action on nodes.
32   */
33  public class CellEditorNode extends AbstractCellEditor implements TreeCellEditor, TreeSelectionListener, MouseListener {
34      
35      private static final Logger LOGGER = LogManager.getRootLogger();
36  
37      /**
38       * Renderer for nodes included JPanel, button, checkbox, icons...
39       */
40      private final CellRendererNode defaultTreeRenderer;
41  
42      /**
43       * Value contained in the editor.
44       * Returned by getCellEditorValue().
45       */
46      private transient AbstractNodeModel nodeModel;
47  
48      /**
49       * Build editor, add tree and mouse listener.
50       */
51      public CellEditorNode() {
52          this.defaultTreeRenderer = new CellRendererNode();
53          MediatorHelper.treeDatabase().addTreeSelectionListener(this);
54          MediatorHelper.treeDatabase().addMouseListener(this);
55      }
56  
57      @Override
58      public Component getTreeCellEditorComponent(
59          JTree tree, 
60          Object nodeRenderer, 
61          boolean selected, 
62          boolean expanded, 
63          boolean leaf, 
64          int row
65      ) {
66          var componentRenderer = this.defaultTreeRenderer.getTreeCellRendererComponent(
67              tree, nodeRenderer, true, expanded, leaf, row, true
68          );
69  
70          final DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) nodeRenderer;
71          var currentNodeModel = currentNode.getUserObject();
72          try {
73              this.nodeModel = (AbstractNodeModel) currentNodeModel;
74              if (componentRenderer instanceof JCheckBox) {
75                  ((JCheckBox) componentRenderer).addActionListener(
76                      new ActionCheckSingle(this.nodeModel, currentNode)
77                  );
78              }
79          } catch (Exception e) {
80              LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
81          }
82          return componentRenderer;
83      }
84  
85      @Override
86      public Object getCellEditorValue() {
87          return this.nodeModel;
88      }
89      
90      @Override
91      public void valueChanged(TreeSelectionEvent treeSelectionEvent) {
92          DefaultMutableTreeNode node = (DefaultMutableTreeNode) MediatorHelper.treeDatabase().getLastSelectedPathComponent();
93          if (node == null) {
94              return;
95          }
96  
97          if (node.getUserObject() instanceof AbstractNodeModel) {
98              AbstractNodeModel dataModel = (AbstractNodeModel) node.getUserObject();
99              if (!dataModel.isLoaded()) {
100                 dataModel.runAction();
101             }
102         }
103     }
104 
105     /**
106      * Fix compatibility issue with right click on Linux.
107      * @param mouseEvent Mouse event
108      */
109     private void showPopup(MouseEvent mouseEvent) {
110         if (!mouseEvent.isPopupTrigger()) {
111             return;
112         }
113         
114         JTree tree = (JTree) mouseEvent.getSource();
115         TreePath path = tree.getPathForLocation(mouseEvent.getX(), mouseEvent.getY());
116         if (path == null) {
117             return;
118         }
119 
120         DefaultMutableTreeNode currentTableNode = (DefaultMutableTreeNode) path.getLastPathComponent();
121         if (currentTableNode.getUserObject() instanceof AbstractNodeModel) {
122             AbstractNodeModel currentTableModel = (AbstractNodeModel) currentTableNode.getUserObject();
123             if (currentTableModel.isPopupDisplayable()) {
124                 currentTableModel.showPopup(currentTableNode, path, mouseEvent);
125             }
126         }
127     }
128 
129     @Override
130     public void mousePressed(MouseEvent e) {
131         this.showPopup(e);
132     }
133     
134     @Override
135     public void mouseReleased(MouseEvent e) {
136         this.showPopup(e);
137     }
138 
139     @Override
140     public void mouseClicked(MouseEvent e) {
141         // Do nothing
142     }
143     
144     @Override
145     public void mouseEntered(MouseEvent e) {
146         // Do nothing
147     }
148     
149     @Override
150     public void mouseExited(MouseEvent e) {
151         // Do nothing
152     }
153 }