http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/licences/epl-v10.html
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/licences/epl-v10.html b/zookeeper-contrib/zookeeper-contrib-zooinspector/licences/epl-v10.html
new file mode 100644
index 0000000..fd39122
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/licences/epl-v10.html
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+<title>Eclipse Public License - Version 1.0</title>
+<style type="text/css">
+ body {
+ size: 8.5in 11.0in;
+ margin: 0.25in 0.5in 0.25in 0.5in;
+ tab-interval: 0.5in;
+ }
+ p {
+ margin-left: auto;
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+ }
+ p.list {
+ margin-left: 0.5in;
+ margin-top: 0.05em;
+ margin-bottom: 0.05em;
+ }
+ </style>
+
+</head>
+
+<body lang="EN-US">
+
+<h2>Eclipse Public License - v 1.0</h2>
+
+<p>THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
+PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR
+DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS
+AGREEMENT.</p>
+
+<p><b>1. DEFINITIONS</b></p>
+
+<p>"Contribution" means:</p>
+
+<p class="list">a) in the case of the initial Contributor, the initial
+code and documentation distributed under this Agreement, and</p>
+<p class="list">b) in the case of each subsequent Contributor:</p>
+<p class="list">i) changes to the Program, and</p>
+<p class="list">ii) additions to the Program;</p>
+<p class="list">where such changes and/or additions to the Program
+originate from and are distributed by that particular Contributor. A
+Contribution 'originates' from a Contributor if it was added to the
+Program by such Contributor itself or anyone acting on such
+Contributor's behalf. Contributions do not include additions to the
+Program which: (i) are separate modules of software distributed in
+conjunction with the Program under their own license agreement, and (ii)
+are not derivative works of the Program.</p>
+
+<p>"Contributor" means any person or entity that distributes
+the Program.</p>
+
+<p>"Licensed Patents" mean patent claims licensable by a
+Contributor which are necessarily infringed by the use or sale of its
+Contribution alone or when combined with the Program.</p>
+
+<p>"Program" means the Contributions distributed in accordance
+with this Agreement.</p>
+
+<p>"Recipient" means anyone who receives the Program under
+this Agreement, including all Contributors.</p>
+
+<p><b>2. GRANT OF RIGHTS</b></p>
+
+<p class="list">a) Subject to the terms of this Agreement, each
+Contributor hereby grants Recipient a non-exclusive, worldwide,
+royalty-free copyright license to reproduce, prepare derivative works
+of, publicly display, publicly perform, distribute and sublicense the
+Contribution of such Contributor, if any, and such derivative works, in
+source code and object code form.</p>
+
+<p class="list">b) Subject to the terms of this Agreement, each
+Contributor hereby grants Recipient a non-exclusive, worldwide,
+royalty-free patent license under Licensed Patents to make, use, sell,
+offer to sell, import and otherwise transfer the Contribution of such
+Contributor, if any, in source code and object code form. This patent
+license shall apply to the combination of the Contribution and the
+Program if, at the time the Contribution is added by the Contributor,
+such addition of the Contribution causes such combination to be covered
+by the Licensed Patents. The patent license shall not apply to any other
+combinations which include the Contribution. No hardware per se is
+licensed hereunder.</p>
+
+<p class="list">c) Recipient understands that although each Contributor
+grants the licenses to its Contributions set forth herein, no assurances
+are provided by any Contributor that the Program does not infringe the
+patent or other intellectual property rights of any other entity. Each
+Contributor disclaims any liability to Recipient for claims brought by
+any other entity based on infringement of intellectual property rights
+or otherwise. As a condition to exercising the rights and licenses
+granted hereunder, each Recipient hereby assumes sole responsibility to
+secure any other intellectual property rights needed, if any. For
+example, if a third party patent license is required to allow Recipient
+to distribute the Program, it is Recipient's responsibility to acquire
+that license before distributing the Program.</p>
+
+<p class="list">d) Each Contributor represents that to its knowledge it
+has sufficient copyright rights in its Contribution, if any, to grant
+the copyright license set forth in this Agreement.</p>
+
+<p><b>3. REQUIREMENTS</b></p>
+
+<p>A Contributor may choose to distribute the Program in object code
+form under its own license agreement, provided that:</p>
+
+<p class="list">a) it complies with the terms and conditions of this
+Agreement; and</p>
+
+<p class="list">b) its license agreement:</p>
+
+<p class="list">i) effectively disclaims on behalf of all Contributors
+all warranties and conditions, express and implied, including warranties
+or conditions of title and non-infringement, and implied warranties or
+conditions of merchantability and fitness for a particular purpose;</p>
+
+<p class="list">ii) effectively excludes on behalf of all Contributors
+all liability for damages, including direct, indirect, special,
+incidental and consequential damages, such as lost profits;</p>
+
+<p class="list">iii) states that any provisions which differ from this
+Agreement are offered by that Contributor alone and not by any other
+party; and</p>
+
+<p class="list">iv) states that source code for the Program is available
+from such Contributor, and informs licensees how to obtain it in a
+reasonable manner on or through a medium customarily used for software
+exchange.</p>
+
+<p>When the Program is made available in source code form:</p>
+
+<p class="list">a) it must be made available under this Agreement; and</p>
+
+<p class="list">b) a copy of this Agreement must be included with each
+copy of the Program.</p>
+
+<p>Contributors may not remove or alter any copyright notices contained
+within the Program.</p>
+
+<p>Each Contributor must identify itself as the originator of its
+Contribution, if any, in a manner that reasonably allows subsequent
+Recipients to identify the originator of the Contribution.</p>
+
+<p><b>4. COMMERCIAL DISTRIBUTION</b></p>
+
+<p>Commercial distributors of software may accept certain
+responsibilities with respect to end users, business partners and the
+like. While this license is intended to facilitate the commercial use of
+the Program, the Contributor who includes the Program in a commercial
+product offering should do so in a manner which does not create
+potential liability for other Contributors. Therefore, if a Contributor
+includes the Program in a commercial product offering, such Contributor
+("Commercial Contributor") hereby agrees to defend and
+indemnify every other Contributor ("Indemnified Contributor")
+against any losses, damages and costs (collectively "Losses")
+arising from claims, lawsuits and other legal actions brought by a third
+party against the Indemnified Contributor to the extent caused by the
+acts or omissions of such Commercial Contributor in connection with its
+distribution of the Program in a commercial product offering. The
+obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In
+order to qualify, an Indemnified Contributor must: a) promptly notify
+the Commercial Contributor in writing of such claim, and b) allow the
+Commercial Contributor to control, and cooperate with the Commercial
+Contributor in, the defense and any related settlement negotiations. The
+Indemnified Contributor may participate in any such claim at its own
+expense.</p>
+
+<p>For example, a Contributor might include the Program in a commercial
+product offering, Product X. That Contributor is then a Commercial
+Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Contributor's responsibility
+alone. Under this section, the Commercial Contributor would have to
+defend claims against the other Contributors related to those
+performance claims and warranties, and if a court requires any other
+Contributor to pay any damages as a result, the Commercial Contributor
+must pay those damages.</p>
+
+<p><b>5. NO WARRANTY</b></p>
+
+<p>EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
+PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION,
+ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
+OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+responsible for determining the appropriateness of using and
+distributing the Program and assumes all risks associated with its
+exercise of rights under this Agreement , including but not limited to
+the risks and costs of program errors, compliance with applicable laws,
+damage to or loss of data, programs or equipment, and unavailability or
+interruption of operations.</p>
+
+<p><b>6. DISCLAIMER OF LIABILITY</b></p>
+
+<p>EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
+NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
+WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
+DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</p>
+
+<p><b>7. GENERAL</b></p>
+
+<p>If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of
+the remainder of the terms of this Agreement, and without further action
+by the parties hereto, such provision shall be reformed to the minimum
+extent necessary to make such provision valid and enforceable.</p>
+
+<p>If Recipient institutes patent litigation against any entity
+(including a cross-claim or counterclaim in a lawsuit) alleging that the
+Program itself (excluding combinations of the Program with other
+software or hardware) infringes such Recipient's patent(s), then such
+Recipient's rights granted under Section 2(b) shall terminate as of the
+date such litigation is filed.</p>
+
+<p>All Recipient's rights under this Agreement shall terminate if it
+fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of time
+after becoming aware of such noncompliance. If all Recipient's rights
+under this Agreement terminate, Recipient agrees to cease use and
+distribution of the Program as soon as reasonably practicable. However,
+Recipient's obligations under this Agreement and any licenses granted by
+Recipient relating to the Program shall continue and survive.</p>
+
+<p>Everyone is permitted to copy and distribute copies of this
+Agreement, but in order to avoid inconsistency the Agreement is
+copyrighted and may only be modified in the following manner. The
+Agreement Steward reserves the right to publish new versions (including
+revisions) of this Agreement from time to time. No one other than the
+Agreement Steward has the right to modify this Agreement. The Eclipse
+Foundation is the initial Agreement Steward. The Eclipse Foundation may
+assign the responsibility to serve as the Agreement Steward to a
+suitable separate entity. Each new version of the Agreement will be
+given a distinguishing version number. The Program (including
+Contributions) may always be distributed subject to the version of the
+Agreement under which it was received. In addition, after a new version
+of the Agreement is published, Contributor may elect to distribute the
+Program (including its Contributions) under the new version. Except as
+expressly stated in Sections 2(a) and 2(b) above, Recipient receives no
+rights or licenses to the intellectual property of any Contributor under
+this Agreement, whether expressly, by implication, estoppel or
+otherwise. All rights in the Program not expressly granted under this
+Agreement are reserved.</p>
+
+<p>This Agreement is governed by the laws of the State of New York and
+the intellectual property laws of the United States of America. No party
+to this Agreement will bring a legal action under this Agreement more
+than one year after the cause of action arose. Each party waives its
+rights to a jury trial in any resulting litigation.</p>
+
+</body>
+
+</html>
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/ZooInspector.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/ZooInspector.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/ZooInspector.java
new file mode 100644
index 0000000..b637bfd
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/ZooInspector.java
@@ -0,0 +1,66 @@
+/**
+ * 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;
+
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.UIManager;
+
+import org.apache.zookeeper.inspector.gui.ZooInspectorPanel;
+import org.apache.zookeeper.inspector.logger.LoggerFactory;
+import org.apache.zookeeper.inspector.manager.ZooInspectorManagerImpl;
+
+/**
+ *
+ */
+public class ZooInspector {
+ /**
+ * @param args
+ * - not used. The value of these parameters will have no effect
+ * on the application
+ */
+ public static void main(String[] args) {
+ try {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ JFrame frame = new JFrame("ZooInspector");
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ final ZooInspectorPanel zooInspectorPanel = new ZooInspectorPanel(
+ new ZooInspectorManagerImpl());
+ frame.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosed(WindowEvent e) {
+ super.windowClosed(e);
+ zooInspectorPanel.disconnect(true);
+ }
+ });
+
+ frame.setContentPane(zooInspectorPanel);
+ frame.setSize(1024, 768);
+ frame.setVisible(true);
+ } catch (Exception e) {
+ LoggerFactory.getLogger().error(
+ "Error occurred loading ZooInspector", e);
+ JOptionPane.showMessageDialog(null,
+ "ZooInspector failed to start: " + e.getMessage(), "Error",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/encryption/BasicDataEncryptionManager.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/encryption/BasicDataEncryptionManager.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/encryption/BasicDataEncryptionManager.java
new file mode 100644
index 0000000..a9e5ac4
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/encryption/BasicDataEncryptionManager.java
@@ -0,0 +1,50 @@
+/**
+ * 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.encryption;
+
+/**
+ *
+ */
+public class BasicDataEncryptionManager implements DataEncryptionManager {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.zookeeper.inspector.encryption.DataEncryptionManager#decryptData
+ * (byte[])
+ */
+ public String decryptData(byte[] encrypted) throws Exception {
+ return new String(encrypted);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.zookeeper.inspector.encryption.DataEncryptionManager#encryptData
+ * (java.lang.String)
+ */
+ public byte[] encryptData(String data) throws Exception {
+ if (data == null) {
+ return new byte[0];
+ }
+ return data.getBytes();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/encryption/DataEncryptionManager.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/encryption/DataEncryptionManager.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/encryption/DataEncryptionManager.java
new file mode 100644
index 0000000..15a9ee4
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/encryption/DataEncryptionManager.java
@@ -0,0 +1,39 @@
+/**
+ * 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.encryption;
+
+/**
+ * A class which describes how data should be encrypted and decrypted
+ */
+public interface DataEncryptionManager {
+ /**
+ * @param data
+ * - the data to be encrypted
+ * @return the encrypted data
+ * @throws Exception
+ */
+ public byte[] encryptData(String data) throws Exception;
+
+ /**
+ * @param encrypted
+ * - the data to be decrypted
+ * @return the decrypted data
+ * @throws Exception
+ */
+ public String decryptData(byte[] encrypted) throws Exception;
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/NodeViewersChangeListener.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/NodeViewersChangeListener.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/NodeViewersChangeListener.java
new file mode 100644
index 0000000..b0b1e98
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/NodeViewersChangeListener.java
@@ -0,0 +1,37 @@
+/**
+ * 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.util.List;
+
+import org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer;
+
+/**
+ * A Listener for changes to the configuration of which node viewers are shown
+ */
+public interface NodeViewersChangeListener {
+ /**
+ * Called when the node viewers configuration is changed (i.e node viewers
+ * are added, removed or the order of the node viewers is changed)
+ *
+ * @param newViewers
+ * - a {@link List} of {@link ZooInspectorNodeViewer}s which are
+ * to be shown
+ */
+ public void nodeViewersChanged(List<ZooInspectorNodeViewer> newViewers);
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorAboutDialog.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorAboutDialog.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorAboutDialog.java
new file mode 100644
index 0000000..fbae8f1
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorAboutDialog.java
@@ -0,0 +1,80 @@
+/**
+ * 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.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Frame;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.IOException;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JEditorPane;
+import javax.swing.JPanel;
+
+import org.apache.zookeeper.inspector.logger.LoggerFactory;
+
+/**
+ * The About Dialog for the application
+ */
+public class ZooInspectorAboutDialog extends JDialog {
+ /**
+ * @param frame
+ * - the Frame from which the dialog is displayed
+ */
+ public ZooInspectorAboutDialog(Frame frame) {
+ super(frame);
+ this.setLayout(new BorderLayout());
+ this.setIconImage(ZooInspectorIconResources.getInformationIcon()
+ .getImage());
+ this.setTitle("About ZooInspector");
+ this.setModal(true);
+ this.setAlwaysOnTop(true);
+ this.setResizable(false);
+ JPanel panel = new JPanel();
+ panel.setLayout(new BorderLayout());
+ JEditorPane aboutPane = new JEditorPane();
+ aboutPane.setEditable(false);
+ aboutPane.setOpaque(false);
+ java.net.URL aboutURL = ZooInspectorAboutDialog.class
+ .getResource("about.html");
+ try {
+ aboutPane.setPage(aboutURL);
+ } catch (IOException e) {
+ LoggerFactory.getLogger().error(
+ "Error loading about.html, file may be corrupt", e);
+ }
+ panel.add(aboutPane, BorderLayout.CENTER);
+ panel.setPreferredSize(new Dimension(600, 200));
+ 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) {
+ ZooInspectorAboutDialog.this.dispose();
+ }
+ });
+ buttonsPanel.add(okButton);
+ this.add(panel, BorderLayout.CENTER);
+ this.add(buttonsPanel, BorderLayout.SOUTH);
+ this.pack();
+ }
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorConnectionPropertiesDialog.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorConnectionPropertiesDialog.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorConnectionPropertiesDialog.java
new file mode 100644
index 0000000..c7db524
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorConnectionPropertiesDialog.java
@@ -0,0 +1,321 @@
+/**
+ * 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.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Map.Entry;
+
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+import org.apache.zookeeper.inspector.logger.LoggerFactory;
+import org.apache.zookeeper.inspector.manager.Pair;
+
+/**
+ * The connection properties dialog. This is used to determine the settings for
+ * connecting to a zookeeper instance
+ */
+public class ZooInspectorConnectionPropertiesDialog extends JDialog {
+
+ private final HashMap<String, JComponent> components;
+
+ /**
+ * @param lastConnectionProps
+ * - the last connection properties used. if this is the first
+ * conneciton since starting the applications this will be the
+ * default settings
+ * @param connectionPropertiesTemplateAndLabels
+ * - the connection properties and labels to show in this dialog
+ * @param zooInspectorPanel
+ * - the {@link ZooInspectorPanel} linked to this dialog
+ */
+ public ZooInspectorConnectionPropertiesDialog(
+ Properties lastConnectionProps,
+ Pair<Map<String, List<String>>, Map<String, String>> connectionPropertiesTemplateAndLabels,
+ final ZooInspectorPanel zooInspectorPanel) {
+ final Map<String, List<String>> connectionPropertiesTemplate = connectionPropertiesTemplateAndLabels
+ .getKey();
+ final Map<String, String> connectionPropertiesLabels = connectionPropertiesTemplateAndLabels
+ .getValue();
+ this.setLayout(new BorderLayout());
+ this.setTitle("Connection Settings");
+ this.setModal(true);
+ this.setAlwaysOnTop(true);
+ this.setResizable(false);
+ final JPanel options = new JPanel();
+ final JFileChooser fileChooser = new JFileChooser();
+ options.setLayout(new GridBagLayout());
+ int i = 0;
+ components = new HashMap<String, JComponent>();
+ for (Entry<String, List<String>> entry : connectionPropertiesTemplate
+ .entrySet()) {
+ int rowPos = 2 * i + 1;
+ JLabel label = new JLabel(connectionPropertiesLabels.get(entry
+ .getKey()));
+ GridBagConstraints c1 = new GridBagConstraints();
+ c1.gridx = 0;
+ c1.gridy = rowPos;
+ c1.gridwidth = 1;
+ c1.gridheight = 1;
+ c1.weightx = 0;
+ c1.weighty = 0;
+ c1.anchor = GridBagConstraints.WEST;
+ c1.fill = GridBagConstraints.HORIZONTAL;
+ c1.insets = new Insets(5, 5, 5, 5);
+ c1.ipadx = 0;
+ c1.ipady = 0;
+ options.add(label, c1);
+ if (entry.getValue().size() == 0) {
+ JTextField text = new JTextField();
+ GridBagConstraints c2 = new GridBagConstraints();
+ c2.gridx = 2;
+ c2.gridy = rowPos;
+ c2.gridwidth = 1;
+ c2.gridheight = 1;
+ c2.weightx = 0;
+ c2.weighty = 0;
+ c2.anchor = GridBagConstraints.WEST;
+ c2.fill = GridBagConstraints.HORIZONTAL;
+ c2.insets = new Insets(5, 5, 5, 5);
+ c2.ipadx = 0;
+ c2.ipady = 0;
+ options.add(text, c2);
+ components.put(entry.getKey(), text);
+ } else if (entry.getValue().size() == 1) {
+ JTextField text = new JTextField(entry.getValue().get(0));
+ GridBagConstraints c2 = new GridBagConstraints();
+ c2.gridx = 2;
+ c2.gridy = rowPos;
+ c2.gridwidth = 1;
+ c2.gridheight = 1;
+ c2.weightx = 0;
+ c2.weighty = 0;
+ c2.anchor = GridBagConstraints.WEST;
+ c2.fill = GridBagConstraints.HORIZONTAL;
+ c2.insets = new Insets(5, 5, 5, 5);
+ c2.ipadx = 0;
+ c2.ipady = 0;
+ options.add(text, c2);
+ components.put(entry.getKey(), text);
+ } else {
+ List<String> list = entry.getValue();
+ JComboBox combo = new JComboBox(list.toArray(new String[list
+ .size()]));
+ combo.setSelectedItem(list.get(0));
+ GridBagConstraints c2 = new GridBagConstraints();
+ c2.gridx = 2;
+ c2.gridy = rowPos;
+ c2.gridwidth = 1;
+ c2.gridheight = 1;
+ c2.weightx = 0;
+ c2.weighty = 0;
+ c2.anchor = GridBagConstraints.WEST;
+ c2.fill = GridBagConstraints.HORIZONTAL;
+ c2.insets = new Insets(5, 5, 5, 5);
+ c2.ipadx = 0;
+ c2.ipady = 0;
+ options.add(combo, c2);
+ components.put(entry.getKey(), combo);
+ }
+ i++;
+ }
+ loadConnectionProps(lastConnectionProps);
+ JPanel buttonsPanel = new JPanel();
+ buttonsPanel.setLayout(new GridBagLayout());
+ JButton loadPropsFileButton = new JButton("Load from file");
+ loadPropsFileButton.addActionListener(new ActionListener() {
+
+ public void actionPerformed(ActionEvent e) {
+ int result = fileChooser
+ .showOpenDialog(ZooInspectorConnectionPropertiesDialog.this);
+ if (result == JFileChooser.APPROVE_OPTION) {
+ File propsFilePath = fileChooser.getSelectedFile();
+ Properties props = new Properties();
+ try {
+ FileReader reader = new FileReader(propsFilePath);
+ try {
+ props.load(reader);
+ loadConnectionProps(props);
+ } finally {
+ reader.close();
+ }
+ } catch (IOException ex) {
+ LoggerFactory
+ .getLogger()
+ .error(
+ "An Error occurred loading connection properties from file",
+ ex);
+ JOptionPane
+ .showMessageDialog(
+ ZooInspectorConnectionPropertiesDialog.this,
+ "An Error occurred loading connection properties from file",
+ "Error", JOptionPane.ERROR_MESSAGE);
+ }
+ options.revalidate();
+ options.repaint();
+ }
+
+ }
+ });
+ GridBagConstraints c3 = new GridBagConstraints();
+ c3.gridx = 0;
+ c3.gridy = 0;
+ c3.gridwidth = 1;
+ c3.gridheight = 1;
+ c3.weightx = 0;
+ c3.weighty = 1;
+ c3.anchor = GridBagConstraints.SOUTHWEST;
+ c3.fill = GridBagConstraints.NONE;
+ c3.insets = new Insets(5, 5, 5, 5);
+ c3.ipadx = 0;
+ c3.ipady = 0;
+ buttonsPanel.add(loadPropsFileButton, c3);
+ JButton saveDefaultPropsFileButton = new JButton("Set As Default");
+ saveDefaultPropsFileButton.addActionListener(new ActionListener() {
+
+ public void actionPerformed(ActionEvent e) {
+
+ Properties connectionProps = getConnectionProps();
+ try {
+ zooInspectorPanel
+ .setdefaultConnectionProps(connectionProps);
+ } catch (IOException ex) {
+ LoggerFactory
+ .getLogger()
+ .error(
+ "An Error occurred saving the default connection properties file",
+ ex);
+ JOptionPane
+ .showMessageDialog(
+ ZooInspectorConnectionPropertiesDialog.this,
+ "An Error occurred saving the default connection properties file",
+ "Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ });
+ GridBagConstraints c6 = new GridBagConstraints();
+ c6.gridx = 1;
+ c6.gridy = 0;
+ c6.gridwidth = 1;
+ c6.gridheight = 1;
+ c6.weightx = 1;
+ c6.weighty = 1;
+ c6.anchor = GridBagConstraints.SOUTHWEST;
+ c6.fill = GridBagConstraints.NONE;
+ c6.insets = new Insets(5, 5, 5, 5);
+ c6.ipadx = 0;
+ c6.ipady = 0;
+ buttonsPanel.add(saveDefaultPropsFileButton, c6);
+ JButton okButton = new JButton("OK");
+ okButton.addActionListener(new ActionListener() {
+
+ public void actionPerformed(ActionEvent e) {
+ ZooInspectorConnectionPropertiesDialog.this.dispose();
+ Properties connectionProps = getConnectionProps();
+ zooInspectorPanel.connect(connectionProps);
+ }
+ });
+ GridBagConstraints c4 = new GridBagConstraints();
+ c4.gridx = 2;
+ c4.gridy = 0;
+ c4.gridwidth = 1;
+ c4.gridheight = 1;
+ c4.weightx = 0;
+ c4.weighty = 1;
+ c4.anchor = GridBagConstraints.SOUTH;
+ c4.fill = GridBagConstraints.HORIZONTAL;
+ c4.insets = new Insets(5, 5, 5, 5);
+ c4.ipadx = 0;
+ c4.ipady = 0;
+ buttonsPanel.add(okButton, c4);
+ JButton cancelButton = new JButton("Cancel");
+ cancelButton.addActionListener(new ActionListener() {
+
+ public void actionPerformed(ActionEvent e) {
+ ZooInspectorConnectionPropertiesDialog.this.dispose();
+ }
+ });
+ GridBagConstraints c5 = new GridBagConstraints();
+ c5.gridx = 3;
+ c5.gridy = 0;
+ c5.gridwidth = 1;
+ c5.gridheight = 1;
+ c5.weightx = 0;
+ c5.weighty = 1;
+ c5.anchor = GridBagConstraints.SOUTH;
+ c5.fill = GridBagConstraints.HORIZONTAL;
+ c5.insets = new Insets(5, 5, 5, 5);
+ c5.ipadx = 0;
+ c5.ipady = 0;
+ buttonsPanel.add(cancelButton, c5);
+ this.add(options, BorderLayout.CENTER);
+ this.add(buttonsPanel, BorderLayout.SOUTH);
+ this.pack();
+ }
+
+ private void loadConnectionProps(Properties props) {
+ if (props != null) {
+ for (Object key : props.keySet()) {
+ String propsKey = (String) key;
+ if (components.containsKey(propsKey)) {
+ JComponent component = components.get(propsKey);
+ String value = props.getProperty(propsKey);
+ if (component instanceof JTextField) {
+ ((JTextField) component).setText(value);
+ } else if (component instanceof JComboBox) {
+ ((JComboBox) component).setSelectedItem(value);
+ }
+ }
+ }
+ }
+ }
+
+ private Properties getConnectionProps() {
+ Properties connectionProps = new Properties();
+ for (Entry<String, JComponent> entry : components.entrySet()) {
+ String value = null;
+ JComponent component = entry.getValue();
+ if (component instanceof JTextField) {
+ value = ((JTextField) component).getText();
+ } else if (component instanceof JComboBox) {
+ value = ((JComboBox) component).getSelectedItem().toString();
+ }
+ connectionProps.put(entry.getKey(), value);
+ }
+ return connectionProps;
+ }
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorIconResources.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorIconResources.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorIconResources.java
new file mode 100644
index 0000000..fa45ab3
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorIconResources.java
@@ -0,0 +1,118 @@
+/**
+ * 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 javax.swing.ImageIcon;
+
+/**
+ * A class containing static methods for retrieving {@link ImageIcon}s used in
+ * the application
+ */
+public class ZooInspectorIconResources {
+
+ /**
+ * @return file icon
+ */
+ public static ImageIcon getTreeLeafIcon() {
+ return new ImageIcon("icons/file_obj.gif"); //$NON-NLS-1$
+ }
+
+ /**
+ * @return folder open icon
+ */
+ public static ImageIcon getTreeOpenIcon() {
+ return new ImageIcon("icons/fldr_obj.gif"); //$NON-NLS-1$
+ }
+
+ /**
+ * @return folder closed icon
+ */
+ public static ImageIcon getTreeClosedIcon() {
+ return new ImageIcon("icons/fldr_obj.gif"); //$NON-NLS-1$
+ }
+
+ /**
+ * @return connect icon
+ */
+ public static ImageIcon getConnectIcon() {
+ return new ImageIcon("icons/launch_run.gif"); //$NON-NLS-1$
+ }
+
+ /**
+ * @return disconnect icon
+ */
+ public static ImageIcon getDisconnectIcon() {
+ return new ImageIcon("icons/launch_stop.gif"); //$NON-NLS-1$
+ }
+
+ /**
+ * @return save icon
+ */
+ public static ImageIcon getSaveIcon() {
+ return new ImageIcon("icons/save_edit.gif"); //$NON-NLS-1$
+ }
+
+ /**
+ * @return add icon
+ */
+ public static ImageIcon getAddNodeIcon() {
+ return new ImageIcon("icons/new_con.gif"); //$NON-NLS-1$
+ }
+
+ /**
+ * @return delete icon
+ */
+ public static ImageIcon getDeleteNodeIcon() {
+ return new ImageIcon("icons/trash.gif"); //$NON-NLS-1$
+ }
+
+ /**
+ * @return refresh icon
+ */
+ public static ImageIcon getRefreshIcon() {
+ return new ImageIcon("icons/refresh.gif"); //$NON-NLS-1$
+ }
+
+ /**
+ * @return information icon
+ */
+ public static ImageIcon getInformationIcon() {
+ return new ImageIcon("icons/info_obj.gif"); //$NON-NLS-1$
+ }
+
+ /**
+ * @return node viewers icon
+ */
+ public static ImageIcon getChangeNodeViewersIcon() {
+ return new ImageIcon("icons/edtsrclkup_co.gif"); //$NON-NLS-1$
+ }
+
+ /**
+ * @return up icon
+ */
+ public static ImageIcon getUpIcon() {
+ return new ImageIcon("icons/search_prev.gif"); //$NON-NLS-1$
+ }
+
+ /**
+ * @return down icon
+ */
+ public static ImageIcon getDownIcon() {
+ return new ImageIcon("icons/search_next.gif"); //$NON-NLS-1$
+ }
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorNodeViewersDialog.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorNodeViewersDialog.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorNodeViewersDialog.java
new file mode 100644
index 0000000..fd0b00a
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorNodeViewersDialog.java
@@ -0,0 +1,605 @@
+/**
+ * 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);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorNodeViewersPanel.java
----------------------------------------------------------------------
diff --git a/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorNodeViewersPanel.java b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorNodeViewersPanel.java
new file mode 100644
index 0000000..05c256b
--- /dev/null
+++ b/zookeeper-contrib/zookeeper-contrib-zooinspector/src/main/java/org/apache/zookeeper/inspector/gui/ZooInspectorNodeViewersPanel.java
@@ -0,0 +1,140 @@
+/**
+ * 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.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.TreePath;
+
+import org.apache.zookeeper.inspector.gui.nodeviewer.ZooInspectorNodeViewer;
+import org.apache.zookeeper.inspector.manager.ZooInspectorManager;
+import org.apache.zookeeper.inspector.manager.ZooInspectorNodeManager;
+
+/**
+ * This is the {@link JPanel} which contains the {@link ZooInspectorNodeViewer}s
+ */
+public class ZooInspectorNodeViewersPanel extends JPanel implements
+ TreeSelectionListener, ChangeListener {
+
+ private final List<ZooInspectorNodeViewer> nodeVeiwers = new ArrayList<ZooInspectorNodeViewer>();
+ private final List<Boolean> needsReload = new ArrayList<Boolean>();
+ private final JTabbedPane tabbedPane;
+ private final List<String> selectedNodes = new ArrayList<String>();
+ private final ZooInspectorNodeManager zooInspectorManager;
+
+ /**
+ * @param zooInspectorManager
+ * - the {@link ZooInspectorManager} for the application
+ * @param nodeVeiwers
+ * - the {@link ZooInspectorNodeViewer}s to show
+ */
+ public ZooInspectorNodeViewersPanel(
+ ZooInspectorNodeManager zooInspectorManager,
+ List<ZooInspectorNodeViewer> nodeVeiwers) {
+ this.zooInspectorManager = zooInspectorManager;
+ this.setLayout(new BorderLayout());
+ tabbedPane = new JTabbedPane(JTabbedPane.TOP,
+ JTabbedPane.WRAP_TAB_LAYOUT);
+ setNodeViewers(nodeVeiwers);
+ tabbedPane.addChangeListener(this);
+ this.add(tabbedPane, BorderLayout.CENTER);
+ reloadSelectedViewer();
+ }
+
+ /**
+ * @param nodeViewers
+ * - the {@link ZooInspectorNodeViewer}s to show
+ */
+ public void setNodeViewers(List<ZooInspectorNodeViewer> nodeViewers) {
+ this.nodeVeiwers.clear();
+ this.nodeVeiwers.addAll(nodeViewers);
+ needsReload.clear();
+ tabbedPane.removeAll();
+ for (ZooInspectorNodeViewer nodeViewer : nodeVeiwers) {
+ nodeViewer.setZooInspectorManager(zooInspectorManager);
+ needsReload.add(true);
+ tabbedPane.add(nodeViewer.getTitle(), nodeViewer);
+ }
+ this.revalidate();
+ this.repaint();
+ }
+
+ private void reloadSelectedViewer() {
+ int index = this.tabbedPane.getSelectedIndex();
+ if (index != -1 && this.needsReload.get(index)) {
+ ZooInspectorNodeViewer viewer = this.nodeVeiwers.get(index);
+ viewer.nodeSelectionChanged(selectedNodes);
+ this.needsReload.set(index, false);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * javax.swing.event.TreeSelectionListener#valueChanged(javax.swing.event
+ * .TreeSelectionEvent)
+ */
+ public void valueChanged(TreeSelectionEvent e) {
+ TreePath[] paths = e.getPaths();
+ selectedNodes.clear();
+ for (TreePath path : paths) {
+ boolean appended = false;
+ StringBuilder sb = new StringBuilder();
+ Object[] pathArray = path.getPath();
+ for (Object o : pathArray) {
+ if (o != null) {
+ String nodeName = o.toString();
+ if (nodeName != null) {
+ if (nodeName.length() > 0) {
+ appended = true;
+ sb.append("/"); //$NON-NLS-1$
+ sb.append(o.toString());
+ }
+ }
+ }
+ }
+ if (appended) {
+ selectedNodes.add(sb.toString());
+ }
+ }
+ for (int i = 0; i < needsReload.size(); i++) {
+ this.needsReload.set(i, true);
+ }
+ reloadSelectedViewer();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent
+ * )
+ */
+ public void stateChanged(ChangeEvent e) {
+ reloadSelectedViewer();
+ }
+}
|