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.manager;
12  
13  import com.jsql.util.LogLevelUtil;
14  import com.jsql.view.swing.tree.CellEditorNode;
15  import com.jsql.view.swing.tree.CellRendererNode;
16  import com.jsql.view.swing.tree.TreeDatabase;
17  import com.jsql.view.swing.tree.model.AbstractNodeModel;
18  import com.jsql.view.swing.tree.model.NodeModelEmpty;
19  import com.jsql.view.swing.util.I18nViewUtil;
20  import com.jsql.view.swing.util.MediatorHelper;
21  import org.apache.logging.log4j.LogManager;
22  import org.apache.logging.log4j.Logger;
23  
24  import javax.swing.*;
25  import javax.swing.event.TreeModelEvent;
26  import javax.swing.event.TreeModelListener;
27  import javax.swing.tree.DefaultMutableTreeNode;
28  import javax.swing.tree.TreePath;
29  import javax.swing.tree.TreeSelectionModel;
30  import java.awt.*;
31  import java.awt.event.KeyAdapter;
32  import java.awt.event.KeyEvent;
33  import java.awt.event.MouseAdapter;
34  import java.awt.event.MouseEvent;
35  
36  /**
37   * Manager to code/decode string in various methods.
38   */
39  public class ManagerDatabase extends JPanel {
40  
41      private static final Logger LOGGER = LogManager.getRootLogger();
42  
43      private final TreeDatabase tree;
44      public static final String TREE_DATABASES = "treeDatabases";
45  
46      /**
47       * Create a panel to encode a string.
48       */
49      public ManagerDatabase() {
50          super(new BorderLayout());
51  
52          // First node in tree
53          AbstractNodeModel nodeModelEmpty = new NodeModelEmpty(I18nViewUtil.valueByKey("DATABASE_EMPTY"));
54          var root = new DefaultMutableTreeNode(nodeModelEmpty);
55          I18nViewUtil.addComponentForKey("DATABASE_EMPTY", nodeModelEmpty);
56  
57          this.tree = new TreeDatabase(root);
58          this.tree.setName(ManagerDatabase.TREE_DATABASES);
59          MediatorHelper.register(this.tree);
60  
61          this.tree.setCellRenderer(new CellRendererNode());
62          this.tree.addMouseListener(this.getTreeMouseListener());
63          this.tree.addKeyListener(this.getTreeKeyListener());
64          this.tree.setCellEditor(new CellEditorNode());
65          this.tree.setEditable(true);  // allows repaint nodes
66          this.tree.setShowsRootHandles(true);
67          this.tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
68          this.tree.getModel().addTreeModelListener(new TreeModelProgressListener());  // required to repaint progress bar
69  
70          this.add(new JScrollPane(this.tree), BorderLayout.CENTER);
71      }
72  
73      private KeyAdapter getTreeKeyListener() {
74          return new KeyAdapter() {
75              @Override
76              public void keyPressed(KeyEvent e) {
77                  if (e.getKeyCode() == KeyEvent.VK_F2) {
78                      DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) ManagerDatabase.this.tree.getLastSelectedPathComponent();
79                      if (treeNode != null) {
80                          AbstractNodeModel nodeModel = (AbstractNodeModel) treeNode.getUserObject();
81                          if (nodeModel != null && nodeModel.getPanel() != null && !nodeModel.isRunning()) {
82                              nodeModel.setIsEdited(true);
83                          }
84                      }
85                  }
86              }
87          };
88      }
89  
90      private MouseAdapter getTreeMouseListener() {
91          return new MouseAdapter() {
92              @Override
93              public void mousePressed(MouseEvent event) {
94                  int selRow = ManagerDatabase.this.tree.getRowForLocation(event.getX(), event.getY());
95                  TreePath selPath = ManagerDatabase.this.tree.getPathForLocation(event.getX(), event.getY());
96                  if (selRow != -1 && event.getClickCount() == 2) {
97                      // Fix ArrayIndexOutOfBoundsException on collapsePath()
98                      try {
99                          if (ManagerDatabase.this.tree.isExpanded(selPath)) {
100                             ManagerDatabase.this.tree.collapsePath(selPath);
101                         } else {
102                             ManagerDatabase.this.tree.expandPath(selPath);
103                         }
104                     } catch (ArrayIndexOutOfBoundsException e) {
105                         LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
106                     }
107                 }
108             }
109         };
110     }
111     
112     private class TreeModelProgressListener implements TreeModelListener {
113         @Override
114         public void treeNodesChanged(TreeModelEvent treeModelEvent) {
115             if (treeModelEvent == null) {
116                 return;
117             }
118             try {  // Fix #96324: ArrayIndexOutOfBoundsException on firePropertyChange()
119                 ManagerDatabase.this.tree.firePropertyChange(
120                     JTree.ROOT_VISIBLE_PROPERTY,
121                     !ManagerDatabase.this.tree.isRootVisible(),
122                     ManagerDatabase.this.tree.isRootVisible()
123                 );
124             } catch (ArrayIndexOutOfBoundsException e) {
125                 LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
126             }
127             ManagerDatabase.this.tree.treeDidChange();
128         }
129         @Override
130         public void treeStructureChanged(TreeModelEvent treeModelEvent) {
131             // Do nothing
132         }
133         @Override
134         public void treeNodesRemoved(TreeModelEvent treeModelEvent) {
135             // Do nothing
136         }
137         @Override
138         public void treeNodesInserted(TreeModelEvent treeModelEvent) {
139             // Do nothing
140         }
141     }
142 }