PanelNode.java
/*******************************************************************************
* Copyhacked (H) 2012-2020.
* This program and the accompanying materials
* are made available under no term at all, use it like
* you want, but share and discuss about it
* every time possible with every body.
*
* Contributors:
* ron190 at ymail dot com - initial implementation
******************************************************************************/
package com.jsql.view.swing.tree;
import com.jsql.util.I18nUtil;
import com.jsql.view.swing.tree.model.AbstractNodeModel;
import com.jsql.view.swing.util.UiStringUtil;
import com.jsql.view.swing.util.UiUtil;
import javax.swing.*;
import javax.swing.plaf.basic.BasicProgressBarUI;
import javax.swing.tree.DefaultMutableTreeNode;
import java.awt.*;
import java.awt.event.*;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.stream.Stream;
/**
* A tree Node composed of an icon, a GIF loader, a progress bar, a label.
*/
public class PanelNode extends JPanel {
/**
* Default icon of the node (database or table).
*/
private final JLabel icon = new JLabel();
/**
* A GIF loader, displayed if progress track is unknown (like columns).
*/
private final JLabel loader = new JLabel();
/**
* Progress bar displayed during injection, with pause icon displayed if user paused the process.
*/
private final ProgressBarPausable progressBar = new ProgressBarPausable();
/**
* Text of the node.
*/
private final JLabel label = new JLabel();
private final JTextField textFieldEditable = new JTextField(15);
/**
* Create Panel for tree nodes.
* @param tree JTree to populate
* @param currentNode Node to draw in the tree
*/
public PanelNode(final JTree tree, final DefaultMutableTreeNode currentNode) {
var animatedGIF = new ImageIcon(Objects.requireNonNull(PanelNode.class.getClassLoader().getResource(UiUtil.PATH_PROGRESSBAR)));
animatedGIF.setImageObserver(new ImageObserverAnimated(tree, currentNode));
this.loader.setIcon(animatedGIF);
this.loader.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
this.progressBar.setPreferredSize(new Dimension(20, 20));
this.progressBar.setUI(new BasicProgressBarUI());
this.progressBar.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(4, 3, 4, 3),
BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(Color.GRAY),
BorderFactory.createLineBorder(Color.WHITE)
)
));
this.label.setOpaque(true);
this.label.setBorder(UiUtil.BORDER_FOCUS_GAINED);
this.icon.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
this.setBackground(Color.WHITE);
this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
Stream.of(
this.icon,
this.loader,
this.progressBar,
this.label,
this.textFieldEditable
)
.forEach(component -> {
this.add(component);
component.setVisible(false);
});
this.setComponentOrientation(ComponentOrientation.getOrientation(I18nUtil.getLocaleDefault()));
this.initializeTextFieldEditable(tree, currentNode);
this.addFocusListener(new FocusListener() {
@Override
public void focusLost(FocusEvent e) {
PanelNode.this.label.setBackground(UiUtil.COLOR_FOCUS_LOST);
PanelNode.this.label.setBorder(UiUtil.BORDER_FOCUS_LOST);
}
@Override
public void focusGained(FocusEvent e) {
PanelNode.this.label.setBackground(UiUtil.COLOR_FOCUS_GAINED);
PanelNode.this.label.setBorder(UiUtil.BORDER_FOCUS_GAINED);
}
});
}
private void initializeTextFieldEditable(final JTree tree, final DefaultMutableTreeNode currentNode) {
this.textFieldEditable.setFont(UiUtil.FONT_NON_MONO);
this.textFieldEditable.setBorder(BorderFactory.createLineBorder(UiUtil.COLOR_FOCUS_GAINED, 1, false));
this.textFieldEditable.addActionListener(e -> {
AbstractNodeModel nodeModel = (AbstractNodeModel) currentNode.getUserObject();
nodeModel.setIsEdited(false);
this.label.setVisible(true);
this.textFieldEditable.setVisible(false);
tree.requestFocusInWindow();
nodeModel.getElementDatabase().setElementValue(new String(
this.textFieldEditable.getText().getBytes(StandardCharsets.UTF_8),
StandardCharsets.UTF_8
));
this.label.setText(UiStringUtil.detectUtf8Html(nodeModel.getElementDatabase().getLabelCount()));
tree.revalidate();
tree.repaint();
});
this.textFieldEditable.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
AbstractNodeModel nodeModel = (AbstractNodeModel) currentNode.getUserObject();
nodeModel.setIsEdited(false);
tree.revalidate();
tree.repaint();
}
});
KeyAdapter keyAdapterF2 = new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
AbstractNodeModel nodeModel = (AbstractNodeModel) currentNode.getUserObject();
if (e.getKeyCode() == KeyEvent.VK_F2 && !nodeModel.isRunning()) {
nodeModel.setIsEdited(true);
PanelNode.this.label.setVisible(false);
PanelNode.this.textFieldEditable.setVisible(true);
PanelNode.this.textFieldEditable.requestFocusInWindow();
tree.revalidate();
tree.repaint();
}
}
};
this.addKeyListener(keyAdapterF2);
this.textFieldEditable.addKeyListener(keyAdapterF2);
}
/**
* Change the text icon.
* @param newIcon An icon to display next to the text.
*/
public void setIcon(Icon newIcon) {
this.icon.setIcon(newIcon);
}
/**
* Display the normal text icon to the left.
*/
public void showIcon() {
this.icon.setVisible(true);
}
/**
* Mask the node icon for example when the loader component is displayed.
*/
public void hideIcon() {
this.icon.setVisible(false);
}
/**
* Change the loader icon.
* @param newIcon An icon to display for the loader.
*/
public void setLoaderIcon(Icon newIcon) {
this.loader.setIcon(newIcon);
}
/**
* Display the animated gif loader.
*/
public void showLoader() {
this.loader.setVisible(true);
}
// Getter and setter
public ProgressBarPausable getProgressBar() {
return this.progressBar;
}
public JLabel getLabel() {
return this.label;
}
public JTextField getEditable() {
return this.textFieldEditable;
}
}