/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.zookeeper.inspector.gui;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.datatransfer.Transferable;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.DropMode;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.TransferHandler;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer;
import org.apache.zookeeper.inspector.logger.LoggerFactory;
import org.apache.zookeeper.inspector.manager.ZooInspectorManager;
/**
* A {@link JDialog} for configuring which {@link ZooInspectorNodeViewer}s to
* show in the application
*/
public class ZooInspectorNodeViewersDialog extends JDialog implements
ListSelectionListener {
private final JButton upButton;
private final JButton downButton;
private final JButton removeButton;
private final JButton addButton;
private final JList viewersList;
private final JButton saveFileButton;
private final JButton loadFileButton;
private final JButton setDefaultsButton;
private final JFileChooser fileChooser = new JFileChooser(new File("."));
/**
* @param frame
* - the Frame from which the dialog is displayed
* @param currentViewers
* - the {@link ZooInspectorNodeViewer}s to show
* @param listeners
* - the {@link NodeViewersChangeListener}s which need to be
* notified of changes to the node viewers configuration
* @param manager
* - the {@link ZooInspectorManager} for the application
*
*/
public ZooInspectorNodeViewersDialog(Frame frame,
final List<ZooInspectorNodeViewer> currentViewers,
final Collection<NodeViewersChangeListener> listeners,
final ZooInspectorManager manager) {
super(frame);
final List<ZooInspectorNodeViewer> newViewers = new ArrayList<ZooInspectorNodeViewer>(
currentViewers);
this.setLayout(new BorderLayout());
this.setIconImage(ZooInspectorIconResources.getChangeNodeViewersIcon()
.getImage());
this.setTitle("About ZooInspector");
this.setModal(true);
this.setAlwaysOnTop(true);
this.setResizable(true);
final JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
viewersList = new JList();
DefaultListModel model = new DefaultListModel();
for (ZooInspectorNodeViewer viewer : newViewers) {
model.addElement(viewer);
}
viewersList.setModel(model);
viewersList.setCellRenderer(new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList list,
Object value, int index, boolean isSelected,
boolean cellHasFocus) {
ZooInspectorNodeViewer viewer = (ZooInspectorNodeViewer) value;
JLabel label = (JLabel) super.getListCellRendererComponent(
list, value, index, isSelected, cellHasFocus);
label.setText(viewer.getTitle());
return label;
}
});
viewersList.setDropMode(DropMode.INSERT);
viewersList.enableInputMethods(true);
viewersList.setDragEnabled(true);
viewersList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
viewersList.getSelectionModel().addListSelectionListener(this);
viewersList.setTransferHandler(new TransferHandler() {
@Override
public boolean canImport(TransferHandler.TransferSupport info) {
// we only import NodeViewers
if (!info
.isDataFlavorSupported(ZooInspectorNodeViewer.nodeViewerDataFlavor)) {
return false;
}
JList.DropLocation dl = (JList.DropLocation) info
.getDropLocation();
if (dl.getIndex() == -1) {
return false;
}
return true;
}
@Override
public boolean importData(TransferHandler.TransferSupport info) {
JList.DropLocation dl = (JList.DropLocation) info
.getDropLocation();
DefaultListModel listModel = (DefaultListModel) viewersList
.getModel();
int index = dl.getIndex();
boolean insert = dl.isInsert();
// Get the string that is being dropped.
Transferable t = info.getTransferable();
String data;
try {
data = (String) t
.getTransferData(ZooInspectorNodeViewer.nodeViewerDataFlavor);
} catch (Exception e) {
return false;
}
try {
ZooInspectorNodeViewer viewer = (ZooInspectorNodeViewer) Class
.forName(data).newInstance();
if (listModel.contains(viewer)) {
listModel.removeElement(viewer);
}
if (insert) {
listModel.add(index, viewer);
} else {
listModel.set(index, viewer);
}
return true;
} catch (Exception e) {
LoggerFactory.getLogger().error(
"Error instantiating class: " + data, e);
return false;
}
}
@Override
public int getSourceActions(JComponent c) {
return MOVE;
}
@Override
protected Transferable createTransferable(JComponent c) {
JList list = (JList) c;
ZooInspectorNodeViewer value = (ZooInspectorNodeViewer) list
.getSelectedValue();
return value;
}
});
JScrollPane scroller = new JScrollPane(viewersList);
GridBagConstraints c1 = new GridBagConstraints();
c1.gridx = 0;
c1.gridy = 0;
c1.gridwidth = 3;
c1.gridheight = 3;
c1.weightx = 0;
c1.weighty = 1;
c1.anchor = GridBagConstraints.CENTER;
c1.fill = GridBagConstraints.BOTH;
c1.insets = new Insets(5, 5, 5, 5);
c1.ipadx = 0;
c1.ipady = 0;
panel.add(scroller, c1);
upButton = new JButton(ZooInspectorIconResources.getUpIcon());
downButton = new JButton(ZooInspectorIconResources.getDownIcon());
removeButton = new JButton(ZooInspectorIconResources
.getDeleteNodeIcon());
addButton = new JButton(ZooInspectorIconResources.getAddNodeIcon());
upButton.setEnabled(false);
downButton.setEnabled(false);
removeButton.setEnabled(false);
addButton.setEnabled(true);
upButton.setToolTipText("Move currently selected node viewer up");
downButton.setToolTipText("Move currently selected node viewer down");
removeButton.setToolTipText("Remove currently selected node viewer");
addButton.setToolTipText("Add node viewer");
final JTextField newViewerTextField = new JTextField();
GridBagConstraints c2 = new GridBagConstraints();
c2.gridx = 3;
c2.gridy = 0;
c2.gridwidth = 1;
c2.gridheight = 1;
c2.weightx = 0;
c2.weighty = 0;
c2.anchor = GridBagConstraints.NORTH;
c2.fill = GridBagConstraints.HORIZONTAL;
c2.insets = new Insets(5, 5, 5, 5);
c2.ipadx = 0;
c2.ipady = 0;
panel.add(upButton, c2);
GridBagConstraints c3 = new GridBagConstraints();
c3.gridx = 3;
c3.gridy = 2;
c3.gridwidth = 1;
c3.gridheight = 1;
c3.weightx = 0;
c3.weighty = 0;
c3.anchor = GridBagConstraints.NORTH;
c3.fill = GridBagConstraints.HORIZONTAL;
c3.insets = new Insets(5, 5, 5, 5);
c3.ipadx = 0;
c3.ipady = 0;
panel.add(downButton, c3);
GridBagConstraints c4 = new GridBagConstraints();
c4.gridx = 3;
c4.gridy = 1;
c4.gridwidth = 1;
c4.gridheight = 1;
c4.weightx = 0;
c4.weighty = 0;
c4.anchor = GridBagConstraints.NORTH;
c4.fill = GridBagConstraints.HORIZONTAL;
c4.insets = new Insets(5, 5, 5, 5);
c4.ipadx = 0;
c4.ipady = 0;
panel.add(removeButton, c4);
GridBagConstraints c5 = new GridBagConstraints();
c5.gridx = 0;
c5.gridy = 3;
c5.gridwidth = 3;
c5.gridheight = 1;
c5.weightx = 0;
c5.weighty = 0;
c5.anchor = GridBagConstraints.CENTER;
c5.fill = GridBagConstraints.BOTH;
c5.insets = new Insets(5, 5, 5, 5);
c5.ipadx = 0;
c5.ipady = 0;
panel.add(newViewerTextField, c5);
GridBagConstraints c6 = new GridBagConstraints();
c6.gridx = 3;
c6.gridy = 3;
c6.gridwidth = 1;
c6.gridheight = 1;
c6.weightx = 0;
c6.weighty = 0;
c6.anchor = GridBagConstraints.CENTER;
c6.fill = GridBagConstraints.BOTH;
c6.insets = new Insets(5, 5, 5, 5);
c6.ipadx = 0;
c6.ipady = 0;
panel.add(addButton, c6);
upButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
DefaultListModel listModel = (DefaultListModel) viewersList
.getModel();
ZooInspectorNodeViewer viewer = (ZooInspectorNodeViewer) viewersList
.getSelectedValue();
int index = viewersList.getSelectedIndex();
if (listModel.contains(viewer)) {
listModel.removeElementAt(index);
listModel.insertElementAt(viewer, index - 1);
viewersList.setSelectedValue(viewer, true);
}
}
});
downButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
DefaultListModel listModel = (DefaultListModel) viewersList
.getModel();
ZooInspectorNodeViewer viewer = (ZooInspectorNodeViewer) viewersList
.getSelectedValue();
int index = viewersList.getSelectedIndex();
if (listModel.contains(viewer)) {
listModel.removeElementAt(index);
listModel.insertElementAt(viewer, index + 1);
viewersList.setSelectedValue(viewer, true);
}
}
});
removeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
DefaultListModel listModel = (DefaultListModel) viewersList
.getModel();
ZooInspectorNodeViewer viewer = (ZooInspectorNodeViewer) viewersList
.getSelectedValue();
int index = viewersList.getSelectedIndex();
if (listModel.contains(viewer)) {
listModel.removeElement(viewer);
viewersList
.setSelectedIndex(index == listModel.size() ? index - 1
: index);
}
}
});
addButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String className = newViewerTextField.getText();
if (className == null || className.length() == 0) {
JOptionPane
.showMessageDialog(
ZooInspectorNodeViewersDialog.this,
"Please enter the full class name for a Node Viewer and click the add button",
"Input Error", JOptionPane.ERROR_MESSAGE);
} else {
try {
DefaultListModel listModel = (DefaultListModel) viewersList
.getModel();
ZooInspectorNodeViewer viewer = (ZooInspectorNodeViewer) Class
.forName(className).newInstance();
if (listModel.contains(viewer)) {
JOptionPane
.showMessageDialog(
ZooInspectorNodeViewersDialog.this,
"Node viewer already exists. Each node viewer can only be added once.",
"Input Error",
JOptionPane.ERROR_MESSAGE);
} else {
listModel.addElement(viewer);
}
} catch (Exception ex) {
LoggerFactory
.getLogger()
.error(
"An error occurred while instaniating the node viewer. ",
ex);
JOptionPane.showMessageDialog(
ZooInspectorNodeViewersDialog.this,
"An error occurred while instaniating the node viewer: "
+ ex.getMessage(), "Error",
JOptionPane.ERROR_MESSAGE);
}
}
}
});
saveFileButton = new JButton("Save");
loadFileButton = new JButton("Load");
setDefaultsButton = new JButton("Set As Defaults");
saveFileButton
.setToolTipText("Save current node viewer configuration to file");
loadFileButton
.setToolTipText("Load node viewer configuration frm file");
setDefaultsButton
.setToolTipText("Set current configuration asd defaults");
GridBagConstraints c7 = new GridBagConstraints();
c7.gridx = 0;
c7.gridy = 4;
c7.gridwidth = 1;
c7.gridheight = 1;
c7.weightx = 1;
c7.weighty = 0;
c7.anchor = GridBagConstraints.WEST;
c7.fill = GridBagConstraints.VERTICAL;
c7.insets = new Insets(5, 5, 5, 5);
c7.ipadx = 0;
c7.ipady = 0;
panel.add(saveFileButton, c7);
GridBagConstraints c8 = new GridBagConstraints();
c8.gridx = 1;
c8.gridy = 4;
c8.gridwidth = 1;
c8.gridheight = 1;
c8.weightx = 0;
c8.weighty = 0;
c8.anchor = GridBagConstraints.WEST;
c8.fill = GridBagConstraints.VERTICAL;
c8.insets = new Insets(5, 5, 5, 5);
c8.ipadx = 0;
c8.ipady = 0;
panel.add(loadFileButton, c8);
GridBagConstraints c9 = new GridBagConstraints();
c9.gridx = 2;
c9.gridy = 4;
c9.gridwidth = 1;
c9.gridheight = 1;
c9.weightx = 0;
c9.weighty = 0;
c9.anchor = GridBagConstraints.WEST;
c9.fill = GridBagConstraints.VERTICAL;
c9.insets = new Insets(5, 5, 5, 5);
c9.ipadx = 0;
c9.ipady = 0;
panel.add(setDefaultsButton, c9);
saveFileButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int result = fileChooser
.showSaveDialog(ZooInspectorNodeViewersDialog.this);
if (result == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooser.getSelectedFile();
int answer = JOptionPane.YES_OPTION;
if (selectedFile.exists()) {
answer = JOptionPane
.showConfirmDialog(
ZooInspectorNodeViewersDialog.this,
"The specified file already exists. do you want to overwrite it?",
"Confirm Overwrite",
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE);
}
if (answer == JOptionPane.YES_OPTION) {
DefaultListModel listModel = (DefaultListModel) viewersList
.getModel();
List<String> nodeViewersClassNames = new ArrayList<String>();
Object[] modelContents = listModel.toArray();
for (Object o : modelContents) {
nodeViewersClassNames
.add(((ZooInspectorNodeViewer) o)
.getClass().getCanonicalName());
}
try {
manager.saveNodeViewersFile(selectedFile,
nodeViewersClassNames);
} catch (IOException ex) {
LoggerFactory
.getLogger()
.error(
"Error saving node veiwer configuration from file.",
ex);
JOptionPane.showMessageDialog(
ZooInspectorNodeViewersDialog.this,
"Error saving node veiwer configuration from file: "
+ ex.getMessage(), "Error",
JOptionPane.ERROR_MESSAGE);
}
}
}
}
});
loadFileButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int result = fileChooser
.showOpenDialog(ZooInspectorNodeViewersDialog.this);
if (result == JFileChooser.APPROVE_OPTION) {
try {
List<String> nodeViewersClassNames = manager
.loadNodeViewersFile(fileChooser
.getSelectedFile());
List<ZooInspectorNodeViewer> nodeViewers = new ArrayList<ZooInspectorNodeViewer>();
for (String nodeViewersClassName : nodeViewersClassNames) {
ZooInspectorNodeViewer viewer = (ZooInspectorNodeViewer) Class
.forName(nodeViewersClassName)
.newInstance();
nodeViewers.add(viewer);
}
DefaultListModel model = new DefaultListModel();
for (ZooInspectorNodeViewer viewer : nodeViewers) {
model.addElement(viewer);
}
viewersList.setModel(model);
panel.revalidate();
panel.repaint();
} catch (Exception ex) {
LoggerFactory
.getLogger()
.error(
"Error loading node veiwer configuration from file.",
ex);
JOptionPane.showMessageDialog(
ZooInspectorNodeViewersDialog.this,
"Error loading node veiwer configuration from file: "
+ ex.getMessage(), "Error",
JOptionPane.ERROR_MESSAGE);
}
}
}
});
setDefaultsButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int answer = JOptionPane
.showConfirmDialog(
ZooInspectorNodeViewersDialog.this,
"Are you sure you want to save this configuration as the default?",
"Confirm Set Defaults",
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE);
if (answer == JOptionPane.YES_OPTION) {
DefaultListModel listModel = (DefaultListModel) viewersList
.getModel();
List<String> nodeViewersClassNames = new ArrayList<String>();
Object[] modelContents = listModel.toArray();
for (Object o : modelContents) {
nodeViewersClassNames.add(((ZooInspectorNodeViewer) o)
.getClass().getCanonicalName());
}
try {
manager
.setDefaultNodeViewerConfiguration(nodeViewersClassNames);
} catch (IOException ex) {
LoggerFactory
.getLogger()
.error(
"Error setting default node veiwer configuration.",
ex);
JOptionPane.showMessageDialog(
ZooInspectorNodeViewersDialog.this,
"Error setting default node veiwer configuration: "
+ ex.getMessage(), "Error",
JOptionPane.ERROR_MESSAGE);
}
}
}
});
JPanel buttonsPanel = new JPanel();
buttonsPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 10));
JButton okButton = new JButton("OK");
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ZooInspectorNodeViewersDialog.this.dispose();
DefaultListModel listModel = (DefaultListModel) viewersList
.getModel();
newViewers.clear();
Object[] modelContents = listModel.toArray();
for (Object o : modelContents) {
newViewers.add((ZooInspectorNodeViewer) o);
}
currentViewers.clear();
currentViewers.addAll(newViewers);
for (NodeViewersChangeListener listener : listeners) {
listener.nodeViewersChanged(currentViewers);
}
}
});
buttonsPanel.add(okButton);
JButton cancelButton = new JButton("Cancel");
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ZooInspectorNodeViewersDialog.this.dispose();
}
});
buttonsPanel.add(cancelButton);
this.add(panel, BorderLayout.CENTER);
this.add(buttonsPanel, BorderLayout.SOUTH);
this.pack();
}
/*
* (non-Javadoc)
*
* @see
* javax.swing.event.ListSelectionListener#valueChanged(javax.swing.event
* .ListSelectionEvent)
*/
public void valueChanged(ListSelectionEvent e) {
int index = viewersList.getSelectedIndex();
if (index == -1) {
removeButton.setEnabled(false);
upButton.setEnabled(false);
downButton.setEnabled(false);
} else {
removeButton.setEnabled(true);
if (index == 0) {
upButton.setEnabled(false);
} else {
upButton.setEnabled(true);
}
if (index == ((DefaultListModel) viewersList.getModel()).getSize()) {
downButton.setEnabled(false);
} else {
downButton.setEnabled(true);
}
}
}
}