/******************************************************************************* * 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.uitools.cell; import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.ComboBoxModel; import javax.swing.Icon; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.ListCellRenderer; import javax.swing.UIManager; /** * Make the cell look like a combo-box, with an optional label. */ public class ComboBoxTreeCellRenderer extends LabeledTreeCellRenderer implements TreeCellEditorAdapter.Renderer { /** the listener to be notified on an immediate edit */ protected TreeCellEditorAdapter.ImmediateEditListener immediateEditListener; /** hold the original colors of the combo-box */ protected Color defaultComboBoxForeground; protected Color defaultComboBoxBackground; // ********** constructors ********** /** * Construct a cell renderer that will display the specified text and icon * in the combo-box's label. */ public ComboBoxTreeCellRenderer(ComboBoxModel model, String labelText, Icon labelIcon) { super(labelText, labelIcon); this.setModel(model); } /** * Construct a cell renderer that will display the specified text * in the combo-box's label. */ public ComboBoxTreeCellRenderer(ComboBoxModel model, String labelText) { super(labelText); this.setModel(model); } /** * Construct a cell renderer that will display the specified icon * in the combo-box's label. */ public ComboBoxTreeCellRenderer(ComboBoxModel model, Icon labelIcon) { super(labelIcon); this.setModel(model); } /** * Construct a cell renderer that has no label and uses the default * combo-box renderer to draw the values, * which calls the values' #toString() methods. */ public ComboBoxTreeCellRenderer(ComboBoxModel model) { super(); this.setModel(model); } /** * Construct a cell renderer that will display the specified text and icon * in the combo-box's label and uses the specified * combo-box renderer to draw the values. */ public ComboBoxTreeCellRenderer(ComboBoxModel model, String labelText, Icon labelIcon, ListCellRenderer renderer) { this(model, labelText, labelIcon); this.setRenderer(renderer); } /** * Construct a cell renderer that has no label and uses the specified * combo-box renderer to draw the selected value. */ public ComboBoxTreeCellRenderer(ComboBoxModel model, ListCellRenderer renderer) { this(model); this.setRenderer(renderer); } // ********** initialization ********** protected JComponent buildComponent() { JComboBox comboBox = new JComboBox(); // see javax.swing.DefaultCellEditor for usage comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE); comboBox.addActionListener(this.buildActionListener()); // save the original colors of the combo-box, so we // can use them to paint non-selected cells this.defaultComboBoxForeground = comboBox.getForeground(); this.defaultComboBoxBackground = comboBox.getBackground(); return comboBox; } private ActionListener buildActionListener() { return new ActionListener() { public void actionPerformed(ActionEvent e) { JComboBox comboBox = (JComboBox) e.getSource(); Object selectedItem = comboBox.getSelectedItem(); // Only update the selected item and invoke immediateEdit() if the // selected item actually changed, during the initialization of the // editing, the model changes and causes this method to be invoked, // it causes CR#3963675 to occur because immediateEdit() stop the // editing, which is done at the wrong time if (ComboBoxTreeCellRenderer.this.getValue() != selectedItem) { ComboBoxTreeCellRenderer.this.setValue(comboBox.getSelectedItem()); ComboBoxTreeCellRenderer.this.immediateEdit(); } } }; } void immediateEdit() { if (this.immediateEditListener != null) { this.immediateEditListener.immediateEdit(); } } // ********** TreeCellRenderer implementation ********** /** * Cast the component to something helpful. */ protected JComboBox getComboBox() { return (JComboBox) this.component; } /** * Tweak the combo-box colors. */ protected void setForeground(Color c) { super.setForeground(c); if (c == UIManager.getColor("Tree.textForeground")) { this.component.setForeground(this.defaultComboBoxForeground); } } /** * Tweak the combo-box colors. */ protected void setBackground(Color c) { super.setBackground(c); if (c == UIManager.getColor("Tree.textBackground")) { this.component.setBackground(this.defaultComboBoxBackground); } } /** * Set the value of the combo-box. */ protected void setValue(Object value) { this.getComboBox().setSelectedItem(value); } // ********** TableCellEditorAdapter.Renderer implementation ********** /** * @see TreeCellEditorAdapter#getValue() */ public Object getValue() { return this.getComboBox().getSelectedItem(); } /** * @see TreeCellEditorAdapter#setImmediateEditListener(TreeCellEditorAdapter.ImmediateEditListener) */ public void setImmediateEditListener(TreeCellEditorAdapter.ImmediateEditListener listener) { this.immediateEditListener = listener; } // ********** public API ********** /** * Set the model used by the combo-box. */ public void setModel(ComboBoxModel model) { this.getComboBox().setModel(model); } /** * Set the renderer used by the combo-box to draw the selected value. * The default renderer calls the value's #toString() method. */ public void setRenderer(ListCellRenderer renderer) { this.getComboBox().setRenderer(renderer); } // ********** API used by the cell editor ********** protected void addActionListener(ActionListener listener) { this.getComboBox().addActionListener(listener); } }