| 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 |
1
1. <init> : removed call to com/jsql/view/swing/tree/TreeDatabase::addTreeSelectionListener → NO_COVERAGE |
MediatorHelper.treeDatabase().addTreeSelectionListener(this); |
| 54 |
1
1. <init> : removed call to com/jsql/view/swing/tree/TreeDatabase::addMouseListener → NO_COVERAGE |
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 |
1
1. getTreeCellEditorComponent : negated conditional → NO_COVERAGE |
if (componentRenderer instanceof JCheckBox) { |
| 75 |
1
1. getTreeCellEditorComponent : removed call to javax/swing/JCheckBox::addActionListener → NO_COVERAGE |
((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 |
1
1. getTreeCellEditorComponent : replaced return value with null for com/jsql/view/swing/tree/CellEditorNode::getTreeCellEditorComponent → NO_COVERAGE |
return componentRenderer; |
| 83 | } | |
| 84 | ||
| 85 | @Override | |
| 86 | public Object getCellEditorValue() { | |
| 87 |
1
1. getCellEditorValue : replaced return value with null for com/jsql/view/swing/tree/CellEditorNode::getCellEditorValue → NO_COVERAGE |
return this.nodeModel; |
| 88 | } | |
| 89 | | |
| 90 | @Override | |
| 91 | public void valueChanged(TreeSelectionEvent treeSelectionEvent) { | |
| 92 | DefaultMutableTreeNode node = (DefaultMutableTreeNode) MediatorHelper.treeDatabase().getLastSelectedPathComponent(); | |
| 93 |
1
1. valueChanged : negated conditional → NO_COVERAGE |
if (node == null) { |
| 94 | return; | |
| 95 | } | |
| 96 | ||
| 97 |
1
1. valueChanged : negated conditional → NO_COVERAGE |
if (node.getUserObject() instanceof AbstractNodeModel) { |
| 98 | AbstractNodeModel dataModel = (AbstractNodeModel) node.getUserObject(); | |
| 99 |
1
1. valueChanged : negated conditional → NO_COVERAGE |
if (!dataModel.isLoaded()) { |
| 100 |
1
1. valueChanged : removed call to com/jsql/view/swing/tree/model/AbstractNodeModel::runAction → NO_COVERAGE |
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 |
1
1. showPopup : negated conditional → NO_COVERAGE |
if (!mouseEvent.isPopupTrigger()) { |
| 111 | return; | |
| 112 | } | |
| 113 | | |
| 114 | JTree tree = (JTree) mouseEvent.getSource(); | |
| 115 | TreePath path = tree.getPathForLocation(mouseEvent.getX(), mouseEvent.getY()); | |
| 116 |
1
1. showPopup : negated conditional → NO_COVERAGE |
if (path == null) { |
| 117 | return; | |
| 118 | } | |
| 119 | ||
| 120 | DefaultMutableTreeNode currentTableNode = (DefaultMutableTreeNode) path.getLastPathComponent(); | |
| 121 |
1
1. showPopup : negated conditional → NO_COVERAGE |
if (currentTableNode.getUserObject() instanceof AbstractNodeModel) { |
| 122 | AbstractNodeModel currentTableModel = (AbstractNodeModel) currentTableNode.getUserObject(); | |
| 123 |
1
1. showPopup : negated conditional → NO_COVERAGE |
if (currentTableModel.isPopupDisplayable()) { |
| 124 |
1
1. showPopup : removed call to com/jsql/view/swing/tree/model/AbstractNodeModel::showPopup → NO_COVERAGE |
currentTableModel.showPopup(currentTableNode, path, mouseEvent); |
| 125 | } | |
| 126 | } | |
| 127 | } | |
| 128 | ||
| 129 | @Override | |
| 130 | public void mousePressed(MouseEvent e) { | |
| 131 |
1
1. mousePressed : removed call to com/jsql/view/swing/tree/CellEditorNode::showPopup → NO_COVERAGE |
this.showPopup(e); |
| 132 | } | |
| 133 | | |
| 134 | @Override | |
| 135 | public void mouseReleased(MouseEvent e) { | |
| 136 |
1
1. mouseReleased : removed call to com/jsql/view/swing/tree/CellEditorNode::showPopup → NO_COVERAGE |
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 | } | |
Mutations | ||
| 53 |
1.1 |
|
| 54 |
1.1 |
|
| 74 |
1.1 |
|
| 75 |
1.1 |
|
| 82 |
1.1 |
|
| 87 |
1.1 |
|
| 93 |
1.1 |
|
| 97 |
1.1 |
|
| 99 |
1.1 |
|
| 100 |
1.1 |
|
| 110 |
1.1 |
|
| 116 |
1.1 |
|
| 121 |
1.1 |
|
| 123 |
1.1 |
|
| 124 |
1.1 |
|
| 131 |
1.1 |
|
| 136 |
1.1 |