/******************************************************************************* * 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.uitools; import java.awt.GridBagConstraints; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JMenuItem; import javax.swing.KeyStroke; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.eclipse.persistence.tools.workbench.framework.context.ApplicationContext; import org.eclipse.persistence.tools.workbench.framework.ui.view.AbstractPanel; import org.eclipse.persistence.tools.workbench.uitools.app.ListValueModel; import org.eclipse.persistence.tools.workbench.uitools.app.PropertyValueModel; import org.eclipse.persistence.tools.workbench.uitools.app.SimplePropertyValueModel; import org.eclipse.persistence.tools.workbench.uitools.app.swing.ListModelAdapter; import org.eclipse.persistence.tools.workbench.uitools.app.swing.ObjectListSelectionModel; import org.eclipse.persistence.tools.workbench.uitools.chooser.NodeSelector; import org.eclipse.persistence.tools.workbench.utility.events.ListChangeAdapter; import org.eclipse.persistence.tools.workbench.utility.events.ListChangeEvent; import org.eclipse.persistence.tools.workbench.utility.events.ListChangeListener; public abstract class AddRemovePanel extends AbstractPanel { private Adapter adapter; private NodeSelector nodeSelector; /** * This holds the button group orientation choice, the default is bottom * the choices are bottom, top, right, and left and are defined by the statics. */ private int buttonOrientation; public final static int BOTTOM = 2; public final static int LEFT = 4; public final static int RIGHT = 3; public final static int TOP = 1; private JButton addButton; private JButton removeButton; private JButton optionalButton; private JButton upButton; private JButton downButton; private ObjectListSelectionModel rowSelectionModel; private PropertyValueModel selectedItemHolder; public AddRemovePanel(ApplicationContext context, Adapter adapter, ListValueModel listModel) { this(context, adapter, listModel, BOTTOM); } public AddRemovePanel(ApplicationContext context, Adapter adapter, ListValueModel listModel, int buttonOrientation) { this(context, adapter, listModel, buttonOrientation, new NodeSelector.DefaultNodeSelector()); } public AddRemovePanel(ApplicationContext context, Adapter adapter, ListValueModel listModel, int buttonOrientation, NodeSelector nodeSelector) { super(context); this.adapter = adapter; this.buttonOrientation = buttonOrientation; this.nodeSelector = nodeSelector; initialize(listModel); } protected void initialize(ListValueModel listModel) { this.rowSelectionModel = buildRowSelectionModel(listModel); listModel.addListChangeListener(this.buildListChangeListener()); this.selectedItemHolder = buildSelectedItemHolder(); this.addButton = buildAddButton(); this.removeButton = buildRemoveButton(); this.optionalButton = buildOptionalButton((this.adapter instanceof OptionAdapter) ? (OptionAdapter) this.adapter : null); this.upButton = buildUpButton((this.adapter instanceof UpDownAdapter) ? (UpDownAdapter) this.adapter : null); this.downButton = buildDownButton((this.adapter instanceof UpDownAdapter) ? (UpDownAdapter) this.adapter : null); } protected JMenuItem buildGoToMenuItem() { JMenuItem menuItem = new JMenuItem(resourceRepository().getString("SELECT_IN_NAVIGATOR_POPUP_MENU_ITEM")); menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F3, 0)); menuItem.addActionListener(this.buildGoToListener()); return menuItem; } private ActionListener buildGoToListener() { return new ActionListener() { public void actionPerformed(ActionEvent e) { AddRemovePanel.this.goToSelectedItem(); } }; } protected KeyListener buildF3KeyListener() { return new KeyAdapter() { public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_F3) { AddRemovePanel.this.goToSelectedItem(); } } }; } private void goToSelectedItem() { if (getSelectedValue() != null) { AddRemovePanel.this.nodeSelector.selectNodeFor(getSelectedValue()); } } public Object getSelectedValue() { return getSelectionModel().getSelectedValue(); } protected ObjectListSelectionModel buildRowSelectionModel(ListValueModel listModel) { ObjectListSelectionModel rowSelectionModel = new ObjectListSelectionModel(new ListModelAdapter(listModel)); rowSelectionModel.addListSelectionListener(this.buildRowSelectionListener()); return rowSelectionModel; } private ListSelectionListener buildRowSelectionListener() { return new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { if (!e.getValueIsAdjusting()) { AddRemovePanel.this.rowSelectionChanged(e); } } }; } private void rowSelectionChanged(ListSelectionEvent e) { if (e.getValueIsAdjusting()) { return; } if (getSelectionModel().getSelectedValuesSize() == 1) { selectedItemHolder.setValue(getSelectionModel().getSelectedValue()); } else { selectedItemHolder.setValue(null); } this.updateButtons(); fireListSelectionEvent(e); } private ListChangeListener buildListChangeListener() { return new ListChangeAdapter() { public void listChanged(ListChangeEvent e) { AddRemovePanel.this.updateButtons(); } }; } protected void updateButtons() { this.updateAddButton(this.addButton); this.updateRemoveButton(this.removeButton); this.updateOptionalButton(this.optionalButton); this.updateUpButton(this.upButton); this.updateDownButton(this.downButton); } protected void updateAddButton(JButton addButton) { } protected void updateRemoveButton(JButton removeButton) { removeButton.setEnabled(this.getSelectionModel().getSelectedValue() != null); } protected void updateOptionalButton(JButton optionalButton) { if (this.adapter instanceof OptionAdapter) { optionalButton.setEnabled(((OptionAdapter) this.adapter).enableOptionOnSelectionChange(this.rowSelectionModel)); } } protected void updateUpButton(JButton upButton) { upButton.setEnabled(this.getSelectionModel().getMinSelectionIndex() > 0); } protected void updateDownButton(JButton downButton) { downButton.setEnabled(!this.getSelectionModel().isSelectionEmpty() && this.getSelectionModel().getMaxSelectionIndex() < getSelectionModel().getListModel().getSize() - 1); } /** * Adds the given listener to the list. The listener will be notified when * the list's selection will changed. * * @param listener The listener to be added */ public void addListSelectionListener(ListSelectionListener listener) { this.listenerList.add(ListSelectionListener.class, listener); } public void removeListSelectionListener(ListSelectionListener l) { this.listenerList.remove(ListSelectionListener.class, l); } private void fireListSelectionEvent(ListSelectionEvent e) { ListSelectionListener[] listeners = (ListSelectionListener[]) this.listenerList.getListeners(ListSelectionListener.class); for (int index = listeners.length; --index >= 0;) listeners[index].valueChanged(e); } private PropertyValueModel buildSelectedItemHolder() { return new SimplePropertyValueModel(null); } protected void initializeButtonPanel() { GridBagConstraints constraints = new GridBagConstraints(); JComponent buttonPanel = buildButtonPanel(); if (this.buttonOrientation == TOP) { constraints.gridx = 0; constraints.gridy = 0; constraints.insets = new Insets(0, 0, 5, 0); constraints.anchor = GridBagConstraints.LINE_START; constraints.fill = GridBagConstraints.NONE; } else if (this.buttonOrientation == LEFT) { constraints.gridx = 0; constraints.gridy = 0; constraints.insets = new Insets(0, 0, 0, 5); constraints.anchor = GridBagConstraints.PAGE_START; constraints.fill = GridBagConstraints.HORIZONTAL; } else if (this.buttonOrientation == RIGHT) { constraints.gridx = 1; constraints.gridy = 0; constraints.insets = new Insets(0, 5, 0, 0); constraints.anchor = GridBagConstraints.PAGE_START; constraints.fill = GridBagConstraints.HORIZONTAL; } else { constraints.gridx = 0; constraints.gridy = 1; constraints.insets = new Insets(5, 0, 0, 0); constraints.anchor = GridBagConstraints.LINE_END; constraints.fill = GridBagConstraints.NONE; } constraints.gridwidth = 1; constraints.gridheight = 1; constraints.weightx = 0; constraints.weighty = 0; add(buttonPanel, constraints); } /** * Creates a container that will properly lay out the given buttons, the * layout will be created once this method has added all its widgets, this * will let any subclass the ability to add or reorder the buttons. * * @param addButton The button used to add a new item * @param removeButton The button used to remove the selected items * @param optionalButton A button that can perform additional operation * over the selected item * @return A new container containing the given widgets */ protected void buildButtonPanel(JComponent buttonPanel) { buttonPanel.add(this.addButton); buttonPanel.add(this.removeButton); buttonPanel.add(this.optionalButton); buttonPanel.add(this.upButton); buttonPanel.add(this.downButton); } /** * Creates the button panel where the given buttons will be added to it. If * the order or more buttons need to be added, then * {@link #buildButtonPanel(JComponent, JButton, JButton, JButton)} needs to * be used. * * @param addButton The button used to add a new item * @param removeButton The button used to remove the selected items * @param optionalButton A button that can perform additional operation * over the selected item * @param orientation The position of the button panel in its container * @return A new container containing the given widgets */ private JComponent buildButtonPanel() { if (this.buttonOrientation == LEFT) { addAlignLeft(this.addButton); addAlignLeft(this.removeButton); addAlignLeft(this.optionalButton); addAlignLeft(this.upButton); addAlignLeft(this.downButton); } else if (this.buttonOrientation == RIGHT) { addAlignRight(this.addButton); addAlignRight(this.removeButton); addAlignRight(this.optionalButton); addAlignRight(this.upButton); addAlignRight(this.downButton); } AccessibleTitledPanel panel = new AccessibleTitledPanel(); buildButtonPanel(panel); int count = panel.getComponentCount(); if ((this.buttonOrientation == LEFT) || (this.buttonOrientation == RIGHT)) { panel.setLayout(new GridLayout(count, 1, 0, 5)); } else { panel.setLayout(new GridLayout(1, count, 5, 0)); } return panel; } // *************** add button ************* protected String addButtonKey() { return "ADD_BUTTON"; } protected JButton buildAddButton() { JButton addButton = buildButton(addButtonKey()); addButton.addActionListener(buildAddItemActionHandler()); return addButton; } private ActionListener buildAddItemActionHandler() { return new ActionListener() { public void actionPerformed(ActionEvent e) { AddRemovePanel.this.addNewItem(); } }; } protected void addNewItem() { getAdapter().addNewItem(getSelectionModel()); } // *************** remove button ************* protected String removeButtonKey() { return "REMOVE_BUTTON"; } protected JButton buildRemoveButton() { JButton removeButton = buildButton(removeButtonKey()); removeButton.addActionListener(buildRemoveItemsActionHandler()); removeButton.setEnabled(false); return removeButton; } private ActionListener buildRemoveItemsActionHandler() { return new ActionListener() { public void actionPerformed(ActionEvent e) { AddRemovePanel.this.removeSelectedItems(); } }; } protected void removeSelectedItems() { getAdapter().removeSelectedItems(getSelectionModel()); } // *************** optional button ************* protected JButton buildOptionalButton(OptionAdapter adapter) { JButton optionalButton = null; if (adapter != null) { optionalButton = buildButton(adapter.optionalButtonKey()); optionalButton.addActionListener(buildOptionalActionHandler()); optionalButton.setEnabled(false); } else { optionalButton = new JButton(); optionalButton.setVisible(false); } return optionalButton; } private ActionListener buildOptionalActionHandler() { return new ActionListener() { public void actionPerformed(ActionEvent e) { ((OptionAdapter) getAdapter()).optionOnSelection(getSelectionModel()); } }; } // *************** up button ************* protected String upButtonKey() { return "UP_BUTTON_TEXT"; } protected JButton buildUpButton(UpDownAdapter adapter) { JButton upButton = null; if (adapter != null) { upButton = buildButton(upButtonKey()); upButton.addActionListener(buildUpActionHandler()); upButton.setEnabled(false); } else { upButton = new JButton(); upButton.setVisible(false); } return upButton; } private ActionListener buildUpActionHandler() { return new ActionListener() { public void actionPerformed(ActionEvent e) { AddRemovePanel.this.moveItemsUp(); } }; } protected void moveItemsUp() { Object[] selectedValues = getSelectionModel().getSelectedValues(); ((UpDownAdapter) getAdapter()).moveItemsUp(selectedValues); getSelectionModel().setSelectedValues(selectedValues); } // *************** down button ************* protected String downButtonKey() { return "DOWN_BUTTON_TEXT"; } protected JButton buildDownButton(UpDownAdapter adapter) { JButton upButton = null; if (adapter != null) { upButton = buildButton(downButtonKey()); upButton.addActionListener(buildDownActionHandler()); upButton.setEnabled(false); } else { upButton = new JButton(); upButton.setVisible(false); } return upButton; } private ActionListener buildDownActionHandler() { return new ActionListener() { public void actionPerformed(ActionEvent e) { AddRemovePanel.this.moveItemsDown(); } }; } protected void moveItemsDown() { Object[] selectedValues = getSelectionModel().getSelectedValues(); ((UpDownAdapter) getAdapter()).moveItemsDown(selectedValues); getSelectionModel().setSelectedValues(selectedValues); } public ObjectListSelectionModel getSelectionModel() { return this.rowSelectionModel; } public PropertyValueModel getSelectedItemHolder() { return this.selectedItemHolder; } protected Adapter getAdapter() { return this.adapter; } protected JButton getAddButton() { return this.addButton; } protected JButton getRemoveButton() { return this.removeButton; } protected JButton getOptionalButton() { return this.optionalButton; } protected int getButtonOrientation() { return this.buttonOrientation; } public void setEnabled(boolean enabled) { super.setEnabled(enabled); getComponent().setEnabled(enabled); this.addButton.setEnabled(enabled); int selectedValuesSize = getSelectionModel().getSelectedValuesSize(); this.removeButton.setEnabled(enabled && (selectedValuesSize > 0)); this.optionalButton.setEnabled(enabled && (selectedValuesSize == 1)); } public abstract JComponent getComponent(); public void setOptionalButtonEnabled(boolean enabled) { this.optionalButton.setEnabled(enabled); } public void setRemoveButtonEnabled(boolean enabled) { this.removeButton.setEnabled(enabled); } public void setAddButtonEnabled(boolean enabled) { this.addButton.setEnabled(enabled); } public void setSelectedValue(Object anObject, boolean shouldScroll) { getSelectionModel().setSelectedValue(anObject); } public interface Adapter { /** * Invoked when the user selects the Add button */ void addNewItem(ObjectListSelectionModel listSelectionModel); /** * Invoked when the user selects the Remove button */ void removeSelectedItems(ObjectListSelectionModel listSelectionModel); } public interface OptionAdapter extends Adapter { /** * Resource string key for the optional button */ String optionalButtonKey(); /** * Invoked when the user selects the optional button */ void optionOnSelection(ObjectListSelectionModel listSelectionModel); /** * Invoked when selection changes. * Implementation dictates whether button should be enabled. */ boolean enableOptionOnSelectionChange(ObjectListSelectionModel listSelectionModel); } public interface UpDownAdapter extends Adapter { void moveItemsUp(Object[] items); void moveItemsDown(Object[] items); } public interface UpDownOptionAdapter extends OptionAdapter, UpDownAdapter { //just a convenience for implementing both optionAdapter and UpDownAdapter } }