Closed tonybeckett closed 8 years ago
Ok, I have to admit, I'm not sure what you are aiming for. Do you want a drop down/combo box w/ a selection of items? Can you post/gist your whole class?
I want to select one of the items and then be able to then edit the properties of the selected item. The button launches another property editor for that selected item.
When you click on a Color entry the two buttons appear. When you click on this combobox nothing happens. It seems to be a mouse action is missing.
public class TBPropertyEditor extends AbstractPropertyEditor
{
private final JButton button;
// private final Renderer label;
private Object oldValue;
private Object selectedValue;
private Icon[] icons;
private final Map<String, Object> map = new HashMap();
private JComboBox combo;
public TBPropertyEditor()
{
combo = new JComboBox()
{
@Override
public void setSelectedItem(Object anObject)
{
oldValue = getSelectedItem();
super.setSelectedItem(anObject);
selectedValue = anObject;
}
};
editor = new JPanel(new PercentLayout(PercentLayout.HORIZONTAL, 0));
((JPanel) editor).add(combo);
// ((JPanel) editor).add("*", label = new Renderer());
// label.setOpaque(false);
((JPanel) editor).add(button = ComponentFactory.Helper.getFactory()
.createMiniButton());
button.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
editProperties(selectedValue);
}
});
((JPanel) editor).setOpaque(true);
combo.setRenderer(new TBPropertyEditor.Renderer());
combo.setEditable(false);
combo.addPopupMenuListener(new PopupMenuListener()
{
@Override
public void popupMenuCanceled(PopupMenuEvent e)
{
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e)
{
TBPropertyEditor.this.firePropertyChange(oldValue, combo.getSelectedItem());
}
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e)
{
}
});
combo.addKeyListener(new KeyAdapter()
{
@Override
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_ENTER)
{
TBPropertyEditor.this.firePropertyChange(oldValue, combo.getSelectedItem());
}
}
});
ArrayList<String> items = new ArrayList();
List itemList = getItems();
for (Object o : itemList)
{
items.add(o.getClass().getSimpleName());
map.put(o.getClass().getSimpleName(), o);
}
setAvailableValues(items.toArray());
// combo.setSelectedIndex(-1);
}
protected List getItems()
{
return new ArrayList();
}
public void setAvailableValues(Object[] values)
{
combo.setModel(new DefaultComboBoxModel(values));
}
public void setAvailableIcons(Icon[] icons)
{
this.icons = icons;
}
protected void editProperties(Object selectedItem)
{
// ResourceManager rm = ResourceManager.all(FilePropertyEditor.class);
// String title = rm.getString("TBPropertyEditor.title");
// Color selectedColor = JColorChooser.showDialog(editor, title, color);
//
// if (selectedColor != null)
// {
// Color oldColor = color;
// Color newColor = selectedColor;
//// label.setValue(newColor);
// color = newColor;
// firePropertyChange(oldColor, newColor);
// }
}
@Override
public Object getValue()
{
Object selected = combo.getSelectedItem();
if (selected instanceof Value)
{
return ((Value) selected).value;
} else
{
return map.get((String) selected);
}
}
@Override
public void setValue(Object value)
{
Object current = null;
int index = -1;
for (int i = 0, c = combo.getModel().getSize(); i < c; i++)
{
current = combo.getModel().getElementAt(i);
if (value == current || (current != null && current.equals(value)))
{
index = i;
break;
}
}
combo.setSelectedIndex(index);
}
public class Renderer extends DefaultListCellRenderer
{
@Override
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus)
{
Component component = super.getListCellRendererComponent(
list,
(value instanceof TBPropertyEditor.Value) ? ((TBPropertyEditor.Value) value).visualValue : value,
index,
isSelected,
cellHasFocus);
if (icons != null && index >= 0 && component instanceof JLabel)
{
((JLabel) component).setIcon(icons[index]);
}
return component;
}
}
public static class AsInt extends TBPropertyEditor
{
// @Override
// public void setValue(Object arg0)
// {
// if (arg0 instanceof Integer)
// {
// super.setValue(new Color(((Integer) arg0).intValue()));
// } else
// {
// super.setValue(arg0);
// }
// }
//
// @Override
// public Object getValue()
// {
// Object value = super.getValue();
// if (value == null)
// {
// return null;
// } else
// {
// return new Integer(((Color) value).getRGB());
// }
// }
@Override
protected void firePropertyChange(Object oldValue, Object newValue)
{
// if (oldValue instanceof Color)
// {
// oldValue = new Integer(((Color) oldValue).getRGB());
// }
// if (newValue instanceof Color)
// {
// newValue = new Integer(((Color) newValue).getRGB());
// }
super.firePropertyChange(oldValue, newValue);
}
}
public static final class Value
{
private Object value;
public Object visualValue;
public Value(Object value, Object visualValue)
{
this.value = value;
this.visualValue = visualValue;
}
@Override
public boolean equals(Object o)
{
if (o == this)
{
return true;
}
if (value == o || (value != null && value.equals(o)))
{
return true;
}
return false;
}
@Override
public int hashCode()
{
return value == null ? 0 : value.hashCode();
}
}
I think the popup menu is interfering in the UI. Also, I'm still not sure what is going on, here is my assumption:
What I usually create an editor and renderer for each type that will be present. Each editor class and renderer class registers with that type. If you add:
private OuterClass oc = new OuterClass();
public OuterClass getOuter() {
return oc;
}
public void setOuter(OuterClass value) {
oc = value;
}
to the Bean class in PropertySheetPage.java the dropdown w/ the available properties show up w/ the button as well.
I was having problems with the control when the popup menu was enabled, so I removed that. I'm not sure what was going on there. When I was clicking in the left hand section of the cell, the control would immediately disappear. But if I clicked in the right, it was fine. Is this a step in the right direction? I want to help and have this tool work!
--Files-- TBPropertiesEditor.java
package com.l2fprod.common.demo;
import com.l2fprod.common.annotations.EditorRegistry;
import com.l2fprod.common.beans.editor.AbstractPropertyEditor;
import com.l2fprod.common.swing.ComponentFactory;
import com.l2fprod.common.swing.PercentLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
@EditorRegistry(type = {OuterClass.class})
public class TBPropertyEditor extends AbstractPropertyEditor {
private final JButton button;
// private final Renderer label;
private Object oldValue;
private Object selectedValue;
private Icon[] icons;
private final Map<String, Object> map = new HashMap();
private JComboBox combo;
public TBPropertyEditor() {
combo = new JComboBox() {
@Override
public void setSelectedItem(Object anObject) {
oldValue = getSelectedItem();
super.setSelectedItem(anObject);
selectedValue = anObject;
}
};
editor = new JPanel(new PercentLayout(PercentLayout.HORIZONTAL, 0));
((JPanel) editor).add(combo);
// ((JPanel) editor).add("*", label = new Renderer());
// label.setOpaque(false);
((JPanel) editor).add(button = ComponentFactory.Helper.getFactory()
.createMiniButton());
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
editProperties(selectedValue);
}
});
((JPanel) editor).setOpaque(true);
combo.setRenderer(new TBPropertyEditor.Renderer());
combo.setEditable(false);
// combo.addPopupMenuListener(new PopupMenuListener() {
// @Override
// public void popupMenuCanceled(PopupMenuEvent e) {
// }
//
// @Override
// public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
// TBPropertyEditor.this.firePropertyChange(oldValue, combo.getSelectedItem());
// }
//
// @Override
// public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
//
// }
// });
// combo.addKeyListener(new KeyAdapter() {
// @Override
// public void keyPressed(KeyEvent e) {
// if (e.getKeyCode() == KeyEvent.VK_ENTER) {
// TBPropertyEditor.this.firePropertyChange(oldValue, combo.getSelectedItem());
// }
// }
// });
ArrayList<String> items = new ArrayList();
List itemList = getItems();
for (Object o : itemList) {
items.add(o.getClass().getSimpleName());
map.put(o.getClass().getSimpleName(), o);
}
setAvailableValues(items.toArray());
// combo.setSelectedIndex(-1);
}
protected List getItems() {
return new ArrayList();
}
public void setAvailableValues(Object[] values) {
combo.setModel(new DefaultComboBoxModel(values));
}
public void setAvailableIcons(Icon[] icons) {
this.icons = icons;
}
protected void editProperties(Object selectedItem) {
// ResourceManager rm = ResourceManager.all(FilePropertyEditor.class);
// String title = rm.getString("TBPropertyEditor.title");
// Color selectedColor = JColorChooser.showDialog(editor, title, color);
//
// if (selectedColor != null)
// {
// Color oldColor = color;
// Color newColor = selectedColor;
//// label.setValue(newColor);
// color = newColor;
// firePropertyChange(oldColor, newColor);
// }
}
@Override
public Object getValue() {
return this.value;
// Object selected = combo.getSelectedItem();
// if (selected instanceof Value) {
// return ((Value) selected).value;
// } else {
// return map.get((String) selected);
// }
}
private Object value;
@Override
public void setValue(Object value) {
if (value == null) {
return;
} else {
this.value = value;
}
try {
PropertyDescriptor[] cbProps = Introspector.getBeanInfo(value.getClass()).getPropertyDescriptors();
ArrayList<String> items = new ArrayList<>();
for(PropertyDescriptor dp : cbProps) {
if(dp.getReadMethod() != null && dp.getWriteMethod() != null) {
items.add(dp.getName());
}
}
setAvailableValues(items.toArray());
// Object current = null;
// int index = -1;
// for (int i = 0, c = combo.getModel().getSize(); i < c; i++) {
// current = combo.getModel().getElementAt(i);
// if (value == current || (current != null && current.equals(value))) {
// index = i;
// break;
// }
// }
// combo.setSelectedIndex(index);
} catch (IntrospectionException ex) {
Logger.getLogger(TBPropertyEditor.class.getName()).log(Level.SEVERE, null, ex);
}
}
public class Renderer extends DefaultListCellRenderer {
@Override
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus) {
Component component = super.getListCellRendererComponent(
list,
(value instanceof TBPropertyEditor.Value) ? ((TBPropertyEditor.Value) value).visualValue : value,
index,
isSelected,
cellHasFocus);
if (icons != null && index >= 0 && component instanceof JLabel) {
((JLabel) component).setIcon(icons[index]);
}
return component;
}
}
public static class AsInt extends TBPropertyEditor {
// @Override
// public void setValue(Object arg0)
// {
// if (arg0 instanceof Integer)
// {
// super.setValue(new Color(((Integer) arg0).intValue()));
// } else
// {
// super.setValue(arg0);
// }
// }
//
// @Override
// public Object getValue()
// {
// Object value = super.getValue();
// if (value == null)
// {
// return null;
// } else
// {
// return new Integer(((Color) value).getRGB());
// }
// }
@Override
protected void firePropertyChange(Object oldValue, Object newValue) {
// if (oldValue instanceof Color)
// {
// oldValue = new Integer(((Color) oldValue).getRGB());
// }
// if (newValue instanceof Color)
// {
// newValue = new Integer(((Color) newValue).getRGB());
// }
super.firePropertyChange(oldValue, newValue);
}
}
public static final class Value {
private Object value;
public Object visualValue;
public Value(Object value, Object visualValue) {
this.value = value;
this.visualValue = visualValue;
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (value == o || (value != null && value.equals(o))) {
return true;
}
return false;
}
@Override
public int hashCode() {
return value == null ? 0 : value.hashCode();
}
}
}
OuterClass.java
package com.l2fprod.common.demo;
public class OuterClass {
private int i;
private InnerClass d;
public int getIntegerValue() {
return i;
}
public void setIntegerValue(int value) {
i = value;
}
public InnerClass getInnerBean() {
return d;
}
public void setInnerBean(InnerClass value) {
d = value;
}
}
InnerClass.java
package com.l2fprod.common.demo;
public class InnerClass {
private boolean x;
public boolean getBooleanValue() {
return x;
}
public void setBooleanValue(boolean value) {
x = value;
}
}
I have pushed changes to my fork of this repository that added a bean(as in seed) property that shows the issue.
I have to commend out the following line:
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e)
{
// TBPropertyEditor.this.firePropertyChange(oldValue, combo.getSelectedItem());
}
This is causing the combo box to disappear too soon (goes from editing to rendering mode). However, I am getting that the combo box will initially show-up, drop-down, and then pull back up, but will still be rendered for future selection. I don't know why this is the case.
I am running Oracle Java8 w/ Linux. I don't have access to any other platforms for testing.
I also changed this line in your setValues() method:
if (value == current || (current != null && current.equals(value.getClass().getSimpleName()))) {
as the previous check for equals(...) wasn't sufficient since current is a String and value is an Object of type Bean.
I am running on Windows 10. Selecting the combobox does nothing. I have to select the button or the void area to the right to get the selection to show up.
Unfortunately, I do not have windows 10, so I can't test this. All I can say is that it does work w/ Linux. But the behavior you had is what I was experiencing until I took out the pop-up menu behavior.
OK, so I was playing around with trying to fix the appear/disappear on first drop-down. Try substituting in this code in your TBPropertyEditor.java file
final java.util.concurrent.atomic.AtomicBoolean first = new java.util.concurrent.atomic.AtomicBoolean(true);
combo.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
if (first.get()) {
first.set(false);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
combo.showPopup();
}
});
}
}
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
}
});
Still has some issues if the combo box is not the first item selected, then this will lead to it being re-opened the first time. It seems to be an event firing that I don't know that is causing this. If you find a fix, let me know.
You can try adding something that will check to see if the events are firing too close together: This says that if less than 75 milliseconds happened between the viz, and inviz, fire the viz again.
final java.util.concurrent.atomic.AtomicBoolean first = new java.util.concurrent.atomic.AtomicBoolean(true);
final java.util.concurrent.atomic.AtomicLong vis = new java.util.concurrent.atomic.AtomicLong(0);
final java.util.concurrent.atomic.AtomicLong invis = new java.util.concurrent.atomic.AtomicLong(0);
combo.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
invis.set(Calendar.getInstance().getTimeInMillis());
// System.out.println(invis.get() - vis.get());
long threshold = 75;
if (invis.get() - vis.get() < threshold) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
combo.showPopup();
}
});
}
if (first.get()) {
first.set(false);
}
}
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
vis.set(Calendar.getInstance().getTimeInMillis());
}
});
Attempting to create a combobox and button editor. The code runs but I can not get the combobox to appear unless I select the button.
Any thoughts? Cheers Tony