/** * 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); } } } }