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 checkboxRenderer) {
75                  checkboxRenderer.addActionListener(new ActionCheckSingle(this.nodeModel, currentNode));
76              }
77          } catch (Exception e) {
78              LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
79          }
80          return componentRenderer;
81      }
82  
83      @Override
84      public Object getCellEditorValue() {
85          return this.nodeModel;
86      }
87      
88      @Override
89      public void valueChanged(TreeSelectionEvent treeSelectionEvent) {
90          DefaultMutableTreeNode node = (DefaultMutableTreeNode) MediatorHelper.treeDatabase().getLastSelectedPathComponent();
91          if (node == null) {
92              return;
93          }
94  
95          if (node.getUserObject() instanceof AbstractNodeModel dataModel && !dataModel.isLoaded()) {
96              dataModel.runAction();
97          }
98      }
99  
100     /**
101      * Fix compatibility issue with right click on Linux.
102      * @param mouseEvent Mouse event
103      */
104     private void showPopup(MouseEvent mouseEvent) {
105         if (!mouseEvent.isPopupTrigger()) {
106             return;
107         }
108         
109         JTree tree = (JTree) mouseEvent.getSource();
110         TreePath path = tree.getPathForLocation(mouseEvent.getX(), mouseEvent.getY());
111         if (path == null) {
112             return;
113         }
114 
115         DefaultMutableTreeNode currentTableNode = (DefaultMutableTreeNode) path.getLastPathComponent();
116         if (
117             currentTableNode.getUserObject() instanceof AbstractNodeModel currentTableModel
118             && currentTableModel.isPopupDisplayable()
119         ) {
120             currentTableModel.showPopup(currentTableNode, path, mouseEvent);
121         }
122     }
123 
124     @Override
125     public void mousePressed(MouseEvent e) {
126         this.showPopup(e);
127     }
128     
129     @Override
130     public void mouseReleased(MouseEvent e) {
131         this.showPopup(e);
132     }
133 
134     @Override
135     public void mouseClicked(MouseEvent e) {
136         // Do nothing
137     }
138     
139     @Override
140     public void mouseEntered(MouseEvent e) {
141         // Do nothing
142     }
143     
144     @Override
145     public void mouseExited(MouseEvent e) {
146         // Do nothing
147     }
148 }