/******************************************************************************* * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Oracle - initial API and implementation from Oracle TopLink ******************************************************************************/ package org.eclipse.persistence.tools.workbench.framework.ui.chooser; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dialog; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.Window; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.Arrays; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.eclipse.persistence.tools.workbench.framework.app.ApplicationNode; import org.eclipse.persistence.tools.workbench.framework.context.ApplicationContext; import org.eclipse.persistence.tools.workbench.framework.context.WorkbenchContext; import org.eclipse.persistence.tools.workbench.framework.ui.dialog.AbstractDialog; import org.eclipse.persistence.tools.workbench.framework.uitools.SwingComponentFactory; import org.eclipse.persistence.tools.workbench.uitools.DisplayableStringConverter; import org.eclipse.persistence.tools.workbench.uitools.FilteringListPanel; import org.eclipse.persistence.tools.workbench.uitools.cell.DisplayableListCellRenderer; import org.eclipse.persistence.tools.workbench.utility.CollectionTools; /** * This dialog presents a list of nodes to the user that can be filtered * down by typing in the text field. When the user selects one of the nodes, * we display the node's path in the lower list box. * * Once the user presses the OK button, clients of this dialog * can retrieve the selected node by calling #selection(). */ public class NodeChooserDialog extends AbstractDialog { /** The complete list of nodes. */ private ApplicationNode[] nodes; /** Hold this so we can give it the initial focus. */ private FilteringListPanel filteringPanel; /** Hold this so we can manipulate it some. */ private JList pathListBox; private static final Object[] EMPTY_LIST = new Object[0]; // ********** static methods ********** /** Factory method. */ public static NodeChooserDialog createDialog(ApplicationNode[] nodes, WorkbenchContext context) { Window window = context.getCurrentWindow(); if (window instanceof Dialog) { return new NodeChooserDialog(nodes, context, (Dialog) window); } return new NodeChooserDialog(nodes, context); } private static String title(ApplicationContext context) { return context.getResourceRepository().getString("NODE_CHOOSER_DIALOG.TITLE"); } // ********** constructors ********** private NodeChooserDialog(ApplicationNode[] nodes, WorkbenchContext context) { super(context, title(context.getApplicationContext())); this.initialize(nodes); } private NodeChooserDialog(ApplicationNode[] nodes, WorkbenchContext context, Dialog owner) { super(context, title(context.getApplicationContext()), owner); this.initialize(nodes); } // ********** initialization ********** private void initialize(ApplicationNode[] allNodes) { this.nodes = allNodes; Arrays.sort(this.nodes); } // ********** main panel ********** protected Component buildMainPanel() { JPanel mainPanel = new JPanel(new GridBagLayout()); mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5)); GridBagConstraints constraints = new GridBagConstraints(); // filtering panel this.filteringPanel = new FilteringListPanel(this.nodes, null, DisplayableStringConverter.instance()); this.configureLabel(this.filteringPanel.getTextFieldLabel(), "NODE_CHOOSER_DIALOG.TEXT_FIELD_LABEL"); this.configureLabel(this.filteringPanel.getListBoxLabel(), "NODE_CHOOSER_DIALOG.NODE_LIST_BOX_LABEL"); this.filteringPanel.setListBoxCellRenderer(new DisplayableListCellRenderer()); this.filteringPanel.getListBox().getSelectionModel().addListSelectionListener(this.buildNodeListSelectionListener()); this.filteringPanel.getListBox().addMouseListener(this.buildDoubleClickMouseListener()); constraints.gridx = 0; constraints.gridy = 0; constraints.gridwidth = 1; constraints.gridheight = 1; constraints.weightx = 1; constraints.weighty = 3; constraints.anchor = GridBagConstraints.PAGE_START; constraints.fill = GridBagConstraints.BOTH; constraints.insets = new Insets(0, 0, 0, 0); mainPanel.add(this.filteringPanel, constraints); // path list box JPanel pathListPanel = new JPanel(new BorderLayout()); JLabel pathListLabel = new JLabel(); this.configureLabel(pathListLabel, "NODE_CHOOSER_DIALOG.PATH_LIST_BOX_LABEL"); pathListLabel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0)); pathListPanel.add(pathListLabel, BorderLayout.PAGE_START); this.pathListBox = SwingComponentFactory.buildList(); this.pathListBox.setDoubleBuffered(true); this.pathListBox.setCellRenderer(new DisplayableListCellRenderer()); this.pathListBox.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); pathListLabel.setLabelFor(this.pathListBox); pathListPanel.add(new JScrollPane(this.pathListBox), BorderLayout.CENTER); constraints.gridx = 0; constraints.gridy = 1; constraints.gridwidth = 1; constraints.gridheight = 1; constraints.weightx = 1; constraints.weighty = 1; constraints.anchor = GridBagConstraints.PAGE_END; constraints.fill = GridBagConstraints.BOTH; constraints.insets = new Insets(0, 0, 0, 0); mainPanel.add(pathListPanel, constraints); return mainPanel; } /** * Build a listener that makes a double-click equivalent to * clicking the OK button. */ private MouseListener buildDoubleClickMouseListener() { return new MouseAdapter() { public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { NodeChooserDialog.this.clickOK(); } } }; } /** * Configure the specified label's text and mnemonic. */ private void configureLabel(JLabel label, String key) { label.setText(this.resourceRepository().getString(key)); label.setDisplayedMnemonic(this.resourceRepository().getMnemonic(key)); } private ListSelectionListener buildNodeListSelectionListener() { return new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { if ( ! e.getValueIsAdjusting()) { NodeChooserDialog.this.nodeSelectionChanged(e); } } }; } // ********** AbstractDialog implementation/overrides ********** /** * nothing is selected initially - so disable the OK button */ protected Action buildOKAction() { Action action = super.buildOKAction(); action.setEnabled(false); return action; } protected String helpTopicId() { return "dialog.nodeChooser"; } protected Component initialFocusComponent() { return this.filteringPanel.getTextField(); } protected void prepareToShow() { this.setSize(350, 566); // use the golden ratio this.setLocationRelativeTo(this.getParent()); } /** * increase visibility slightly for inner class */ protected void clickOK() { super.clickOK(); } // ********** behavior ********** void nodeSelectionChanged(ListSelectionEvent e) { ApplicationNode selectedNode = (ApplicationNode) this.filteringPanel.getSelection(); if (selectedNode == null) { this.pathListBox.setListData(EMPTY_LIST); } else { this.pathListBox.setListData(this.reversePathFor(selectedNode)); } // enable the OK button only when the user has selected a node this.getOKAction().setEnabled(selectedNode != null); } private Object[] reversePathFor(ApplicationNode node) { Object[] path = node.path(); Object[] shortPath = new Object[path.length - 1]; System.arraycopy(path, 0, shortPath, 0, shortPath.length); return CollectionTools.reverse(shortPath); } // ********** public API ********** /** * Return the type selected by the user. */ public ApplicationNode selection() { if ( ! this.wasConfirmed()) { throw new IllegalStateException(); } return (ApplicationNode) this.filteringPanel.getSelection(); } }