Merge branch 'object-array-editor' into 'master'
Object array editor This introduces a new generic ObjectArrayEditor which allows adding assignable classes of a type T to a list (shown in a JList) and configuring those objects in a GenericObjectEditor instance.  This thing is useful in multiple instances: - MetaEvA - To select problems and configure them (dimension, init range, etc.) - To select optimizers (configuration will be ignored) - Experiment Generator (future project) - To select problems and configure optimizer to be executed in a run matrix ToDo: - [x] Allow deactivating/hiding the "Config" button - [x] Make sure this will automatically be used for objects that have an `Anything[]` - [x] Find a way to get a better `toString()` (CEC2005 for some reason looks fine) See merge request !10
This commit is contained in:
commit
6a24e01e45
@ -4,23 +4,17 @@ import eva2.gui.editor.GenericObjectEditor;
|
||||
import eva2.optimization.tools.FileTools;
|
||||
import eva2.tools.BasicResourceLoader;
|
||||
import eva2.tools.SerializedObject;
|
||||
import eva2.tools.StringTools;
|
||||
import eva2.util.annotation.Description;
|
||||
import eva2.yaml.BeanSerializer;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
import javax.swing.plaf.basic.BasicComboBoxRenderer;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
@ -34,15 +28,11 @@ public class OptimizationEditorPanel extends JPanel implements ItemListener {
|
||||
/**
|
||||
* The chooser component
|
||||
*/
|
||||
private JComboBox<Item> objectChooser;
|
||||
private TypeSelector typeSelector;
|
||||
/**
|
||||
* The component that performs classifier customization
|
||||
*/
|
||||
private PropertySheetPanel propertySheetPanel;
|
||||
/**
|
||||
* The model containing the list of names to select from
|
||||
*/
|
||||
private DefaultComboBoxModel<Item> comboBoxModel;
|
||||
/**
|
||||
* Open object from disk
|
||||
*/
|
||||
@ -77,9 +67,8 @@ public class OptimizationEditorPanel extends JPanel implements ItemListener {
|
||||
}
|
||||
|
||||
private void buildTypeSelectionPanel() {
|
||||
comboBoxModel = new DefaultComboBoxModel<>(new Vector<>());
|
||||
objectChooser = new JComboBox<>(comboBoxModel);
|
||||
objectChooser.setEditable(false);
|
||||
typeSelector = new TypeSelector();
|
||||
typeSelector.setEditable(false);
|
||||
|
||||
GridBagConstraints gbConstraints = new GridBagConstraints();
|
||||
|
||||
@ -89,7 +78,7 @@ public class OptimizationEditorPanel extends JPanel implements ItemListener {
|
||||
gbConstraints.gridy = 0;
|
||||
|
||||
JLabel typeLabel = new JLabel("Type:");
|
||||
typeLabel.setLabelFor(objectChooser);
|
||||
typeLabel.setLabelFor(typeSelector);
|
||||
typeLabel.setDisplayedMnemonic('t');
|
||||
typeSelectionPanel.add(typeLabel, gbConstraints);
|
||||
|
||||
@ -97,7 +86,7 @@ public class OptimizationEditorPanel extends JPanel implements ItemListener {
|
||||
gbConstraints.gridy = 0;
|
||||
gbConstraints.weightx = 1.0;
|
||||
gbConstraints.fill = GridBagConstraints.HORIZONTAL;
|
||||
typeSelectionPanel.add(objectChooser, gbConstraints);
|
||||
typeSelectionPanel.add(typeSelector, gbConstraints);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -181,9 +170,6 @@ public class OptimizationEditorPanel extends JPanel implements ItemListener {
|
||||
((JDialog) container).dispose();
|
||||
});
|
||||
|
||||
// 10px padding
|
||||
setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||
|
||||
setLayout(new GridBagLayout());
|
||||
GridBagConstraints gbConstraints = new GridBagConstraints();
|
||||
|
||||
@ -225,7 +211,7 @@ public class OptimizationEditorPanel extends JPanel implements ItemListener {
|
||||
updateChooser();
|
||||
updateChildPropertySheet();
|
||||
}
|
||||
objectChooser.addItemListener(this);
|
||||
typeSelector.addItemListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -317,59 +303,24 @@ public class OptimizationEditorPanel extends JPanel implements ItemListener {
|
||||
*
|
||||
*/
|
||||
public void updateClassType() {
|
||||
List<String> classesLongNames;
|
||||
ArrayList<Class<?>> instances = new ArrayList<>(5);
|
||||
classesLongNames = GenericObjectEditor.getClassesFromProperties(genericObjectEditor.getClassType().getName(), instances);
|
||||
LOGGER.finest("Selected type for OptimizationEditorPanel: " + genericObjectEditor.getClassType().getName());
|
||||
if (classesLongNames.size() > 1) {
|
||||
Vector<Item> classesList = new Vector<>();
|
||||
String[] toolTips = collectComboToolTips(instances, tipMaxLen);
|
||||
int i = 0;
|
||||
for (String className : classesLongNames) {
|
||||
String displayName = StringTools.cutClassName(className);
|
||||
typeSelector.updateClassType(genericObjectEditor.getClassType().getName());
|
||||
|
||||
classesList.add(new Item(className, displayName, toolTips[i++]));
|
||||
}
|
||||
comboBoxModel = new DefaultComboBoxModel<>(classesList);
|
||||
objectChooser.setModel(comboBoxModel);
|
||||
objectChooser.setRenderer(new ToolTipComboBoxRenderer());
|
||||
if (typeSelector.getItemCount() > 1) {
|
||||
typeSelectionPanel.setVisible(true);
|
||||
} else {
|
||||
typeSelectionPanel.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
private String[] collectComboToolTips(List<Class<?>> instances, int maxLen) {
|
||||
String[] tips = new String[instances.size()];
|
||||
|
||||
for (int i = 0; i < tips.length; i++) {
|
||||
tips[i] = null;
|
||||
|
||||
String tip = null;
|
||||
|
||||
Description description = instances.get(i).getAnnotation(Description.class);
|
||||
if (description != null) {
|
||||
tip = description.value();
|
||||
}
|
||||
|
||||
if (tip != null) {
|
||||
if (tip.length() <= maxLen) {
|
||||
tips[i] = tip;
|
||||
} else {
|
||||
tips[i] = tip.substring(0, maxLen - 2) + "..";
|
||||
}
|
||||
}
|
||||
}
|
||||
return tips;
|
||||
}
|
||||
|
||||
public void updateChooser() {
|
||||
String objectName = genericObjectEditor.getValue().getClass().getName();
|
||||
for (int i = 0; i < comboBoxModel.getSize(); i++) {
|
||||
Item element = comboBoxModel.getElementAt(i);
|
||||
for (int i = 0; i < typeSelector.getItemCount(); i++) {
|
||||
TypeSelectorItem element = typeSelector.getItemAt(i);
|
||||
|
||||
if (objectName.equals(element.getId())) {
|
||||
objectChooser.getModel().setSelectedItem(element);
|
||||
typeSelector.getModel().setSelectedItem(element);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -393,8 +344,8 @@ public class OptimizationEditorPanel extends JPanel implements ItemListener {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
String className;
|
||||
|
||||
if ((e.getSource() == objectChooser) && (e.getStateChange() == ItemEvent.SELECTED)) {
|
||||
className = ((Item)objectChooser.getSelectedItem()).getId();
|
||||
if ((e.getSource() == typeSelector) && (e.getStateChange() == ItemEvent.SELECTED)) {
|
||||
className = ((TypeSelectorItem) typeSelector.getSelectedItem()).getId();
|
||||
try {
|
||||
Object n = Class.forName(className).newInstance();
|
||||
genericObjectEditor.setValue(n);
|
||||
@ -403,8 +354,8 @@ public class OptimizationEditorPanel extends JPanel implements ItemListener {
|
||||
System.err.println("Exception in itemStateChanged " + ex.getMessage());
|
||||
System.err.println("Classpath is " + System.getProperty("java.class.path"));
|
||||
ex.printStackTrace();
|
||||
objectChooser.hidePopup();
|
||||
objectChooser.setSelectedIndex(0);
|
||||
typeSelector.hidePopup();
|
||||
typeSelector.setSelectedIndex(0);
|
||||
JOptionPane.showMessageDialog(this,
|
||||
"Could not create an example of\n"
|
||||
+ className + "\n"
|
||||
@ -415,75 +366,3 @@ public class OptimizationEditorPanel extends JPanel implements ItemListener {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ToolTipComboBoxRenderer extends BasicComboBoxRenderer {
|
||||
|
||||
private static final long serialVersionUID = -5781643352198561208L;
|
||||
|
||||
public ToolTipComboBoxRenderer() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value,
|
||||
int index, boolean isSelected, boolean cellHasFocus) {
|
||||
|
||||
super.getListCellRendererComponent(list, value, index,
|
||||
isSelected, cellHasFocus);
|
||||
|
||||
if (value != null) {
|
||||
Item item = (Item)value;
|
||||
setText(item.getDisplayName());
|
||||
|
||||
if (isSelected) {
|
||||
setBackground(list.getSelectionBackground());
|
||||
setForeground(list.getSelectionForeground());
|
||||
list.setToolTipText(item.getDescription());
|
||||
} else {
|
||||
setBackground(list.getBackground());
|
||||
setForeground(list.getForeground());
|
||||
}
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
Item item = (Item)value;
|
||||
setText(item.getDisplayName());
|
||||
}
|
||||
|
||||
setFont(list.getFont());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
class Item
|
||||
{
|
||||
private String id;
|
||||
private String displayName;
|
||||
private String description;
|
||||
|
||||
public Item(String id, String displayName, String description)
|
||||
{
|
||||
this.id = id;
|
||||
this.displayName = displayName;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getDescription()
|
||||
{
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,8 @@ public class PropertyDialog extends JDialog {
|
||||
setLayout(new BorderLayout());
|
||||
propertyEditor = editor;
|
||||
editorComponent = editor.getCustomEditor();
|
||||
|
||||
((JPanel)getContentPane()).setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||
add(editorComponent, BorderLayout.CENTER);
|
||||
|
||||
pack();
|
||||
|
@ -3,12 +3,17 @@ package eva2.gui;
|
||||
import eva2.gui.editor.*;
|
||||
import eva2.optimization.individuals.codings.gp.GPArea;
|
||||
import eva2.optimization.operator.terminators.InterfaceTerminator;
|
||||
import eva2.tools.Primitives;
|
||||
import eva2.tools.SelectedTag;
|
||||
import eva2.tools.StringSelection;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.beans.PropertyEditor;
|
||||
import java.beans.PropertyEditorManager;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class PropertyEditorProvider {
|
||||
// if true, we use the GenericObjectEditor whenever no specific one is registered, so keep it true
|
||||
@ -23,13 +28,24 @@ public class PropertyEditorProvider {
|
||||
public static PropertyEditor findEditor(Class<?> cls) {
|
||||
PropertyEditor editor = PropertyEditorManager.findEditor(cls);
|
||||
|
||||
// Try to unwrap primitives
|
||||
if (editor == null && Primitives.isWrapperType(cls)) {
|
||||
editor = PropertyEditorManager.findEditor(Primitives.unwrap(cls));
|
||||
}
|
||||
|
||||
if ((editor == null) && useDefaultGOE) {
|
||||
if (cls.isArray()) {
|
||||
editor = new ArrayEditor();
|
||||
Class<?> unwrapped = Primitives.isWrapperType(cls.getComponentType()) ? Primitives.unwrap(cls.getComponentType()) : cls;
|
||||
if (unwrapped.isPrimitive()) {
|
||||
editor = new ArrayEditor();
|
||||
} else {
|
||||
editor = new ObjectArrayEditor<>(unwrapped.getComponentType());
|
||||
}
|
||||
} else if (cls.isEnum()) {
|
||||
editor = new EnumEditor();
|
||||
} else {
|
||||
editor = new GenericObjectEditor();
|
||||
((GenericObjectEditor)editor).setClassType(cls);
|
||||
}
|
||||
}
|
||||
return editor;
|
||||
@ -42,6 +58,7 @@ public class PropertyEditorProvider {
|
||||
* @return
|
||||
*/
|
||||
public static PropertyEditor findEditor(PropertyDescriptor prop, Object value) {
|
||||
|
||||
PropertyEditor editor = null;
|
||||
Class pec = prop.getPropertyEditorClass();
|
||||
Class type = prop.getPropertyType();
|
||||
@ -56,10 +73,9 @@ public class PropertyEditorProvider {
|
||||
|
||||
if (editor == null) {
|
||||
if (value != null) {
|
||||
|
||||
// ToDo: This should be handled by the registerEditor below. findEditor however always returns the sun.beans.editor stuff.
|
||||
if (value instanceof Enum) {
|
||||
editor = new EnumEditor();
|
||||
// Try to unwrap primitives
|
||||
if (Primitives.isWrapperType(value.getClass())) {
|
||||
editor = PropertyEditorManager.findEditor(Primitives.unwrap(value.getClass()));
|
||||
} else {
|
||||
editor = PropertyEditorManager.findEditor(value.getClass());
|
||||
}
|
||||
@ -84,11 +100,17 @@ public class PropertyEditorProvider {
|
||||
|
||||
if ((editor == null) && useDefaultGOE) {
|
||||
if (type.isArray()) {
|
||||
editor = new ArrayEditor();
|
||||
Class<?> unwrapped = Primitives.isWrapperType(type.getComponentType()) ? Primitives.unwrap(type.getComponentType()) : type;
|
||||
if (unwrapped.isPrimitive()) {
|
||||
editor = new ArrayEditor();
|
||||
} else {
|
||||
editor = new ObjectArrayEditor<>(unwrapped.getComponentType());
|
||||
}
|
||||
} else if (type.isEnum()) {
|
||||
editor = new EnumEditor();
|
||||
} else {
|
||||
editor = new GenericObjectEditor();
|
||||
((GenericObjectEditor)editor).setClassType(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -116,6 +138,8 @@ public class PropertyEditorProvider {
|
||||
PropertyEditorManager.registerEditor(Enum.class, EnumEditor.class);
|
||||
PropertyEditorManager.registerEditor(int[].class, ArrayEditor.class);
|
||||
PropertyEditorManager.registerEditor(double[].class, ArrayEditor.class);
|
||||
PropertyEditorManager.registerEditor(String[].class, ArrayEditor.class);
|
||||
|
||||
PropertyEditorManager.registerEditor(InterfaceTerminator[].class, ArrayEditor.class);
|
||||
|
||||
|
||||
|
@ -227,7 +227,7 @@ public final class PropertySheetPanel extends JPanel implements PropertyChangeLi
|
||||
gbConstraints.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbConstraints.anchor = GridBagConstraints.PAGE_START;
|
||||
|
||||
add(buildTitledSeperator("Info"), gbConstraints);
|
||||
add(new TitledSeparator("Info"), gbConstraints);
|
||||
|
||||
gbConstraints.gridy = 1;
|
||||
add(infoPanel, gbConstraints);
|
||||
@ -307,9 +307,7 @@ public final class PropertySheetPanel extends JPanel implements PropertyChangeLi
|
||||
|
||||
|
||||
gbConstraints.gridy = 2;
|
||||
|
||||
|
||||
add(buildTitledSeperator("Properties"), gbConstraints);
|
||||
add(new TitledSeparator("Properties"), gbConstraints);
|
||||
|
||||
JScrollPane scrollableTable = new JScrollPane(propertyTable, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||
gbConstraints.gridx = 0;
|
||||
@ -320,6 +318,8 @@ public final class PropertySheetPanel extends JPanel implements PropertyChangeLi
|
||||
scrollableTable.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
|
||||
add(scrollableTable, gbConstraints);
|
||||
|
||||
setMinimumSize(new Dimension(350, 0));
|
||||
|
||||
validate();
|
||||
setVisible(true);
|
||||
}
|
||||
@ -333,24 +333,6 @@ public final class PropertySheetPanel extends JPanel implements PropertyChangeLi
|
||||
return label;
|
||||
}
|
||||
|
||||
private static JPanel buildTitledSeperator(String title) {
|
||||
JPanel titledSeperator = new JPanel(new GridBagLayout());
|
||||
|
||||
GridBagConstraints gbConstraints = new GridBagConstraints();
|
||||
gbConstraints.gridx = 0;
|
||||
gbConstraints.gridy = 0;
|
||||
|
||||
titledSeperator.add(new JLabel("<html><b>" + title), gbConstraints);
|
||||
|
||||
gbConstraints.gridx = 1;
|
||||
gbConstraints.gridy = 0;
|
||||
gbConstraints.weightx = 1.0;
|
||||
gbConstraints.fill = GridBagConstraints.HORIZONTAL;
|
||||
titledSeperator.add(new JSeparator(JSeparator.HORIZONTAL), gbConstraints);
|
||||
|
||||
return titledSeperator;
|
||||
}
|
||||
|
||||
public static PropertyDescriptor[] getProperties(Object target) {
|
||||
BeanInfo bi;
|
||||
try {
|
||||
|
@ -59,6 +59,8 @@ public class TabbedFrameMaker implements Serializable, PanelMaker, InterfaceNoti
|
||||
|
||||
for (PanelMaker element : pmContainer) {
|
||||
JComponent panel = element.makePanel();
|
||||
|
||||
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||
if (element instanceof ModuleButtonPanelMaker) {
|
||||
extToolBar.add(panel);
|
||||
butPanelMkr = (ModuleButtonPanelMaker) element;
|
||||
|
25
src/main/java/eva2/gui/TitledSeparator.java
Normal file
25
src/main/java/eva2/gui/TitledSeparator.java
Normal file
@ -0,0 +1,25 @@
|
||||
package eva2.gui;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* Created by halfdan on 17/12/15.
|
||||
*/
|
||||
public final class TitledSeparator extends JPanel {
|
||||
public TitledSeparator(String title) {
|
||||
setLayout(new GridBagLayout());
|
||||
|
||||
GridBagConstraints gbConstraints = new GridBagConstraints();
|
||||
gbConstraints.gridx = 0;
|
||||
gbConstraints.gridy = 0;
|
||||
|
||||
add(new JLabel("<html><b>" + title), gbConstraints);
|
||||
|
||||
gbConstraints.gridx = 1;
|
||||
gbConstraints.gridy = 0;
|
||||
gbConstraints.weightx = 1.0;
|
||||
gbConstraints.fill = GridBagConstraints.HORIZONTAL;
|
||||
add(new JSeparator(JSeparator.HORIZONTAL), gbConstraints);
|
||||
}
|
||||
}
|
114
src/main/java/eva2/gui/TypeSelector.java
Normal file
114
src/main/java/eva2/gui/TypeSelector.java
Normal file
@ -0,0 +1,114 @@
|
||||
package eva2.gui;
|
||||
|
||||
import eva2.gui.editor.GenericObjectEditor;
|
||||
import eva2.tools.StringTools;
|
||||
import eva2.util.annotation.Description;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.plaf.basic.BasicComboBoxRenderer;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Created by fabian on 16/12/15.
|
||||
*/
|
||||
public class TypeSelector extends JComboBox<TypeSelectorItem> {
|
||||
private static final Logger LOGGER = Logger.getLogger(TypeSelector.class.getName());
|
||||
/**
|
||||
* The model containing the list of names to select from
|
||||
*/
|
||||
private DefaultComboBoxModel<TypeSelectorItem> comboBoxModel;
|
||||
|
||||
public TypeSelector() {
|
||||
|
||||
comboBoxModel = new DefaultComboBoxModel<>(new Vector<>());
|
||||
}
|
||||
|
||||
public void updateClassType(String classTypeName) {
|
||||
java.util.List<String> classesLongNames;
|
||||
ArrayList<Class<?>> instances = new ArrayList<>(5);
|
||||
classesLongNames = GenericObjectEditor.getClassesFromProperties(classTypeName, instances);
|
||||
LOGGER.finest("Selected type for OptimizationEditorPanel: " + classTypeName);
|
||||
if (classesLongNames.size() > 1) {
|
||||
Vector<TypeSelectorItem> classesList = new Vector<>();
|
||||
String[] toolTips = collectComboToolTips(instances, 100);
|
||||
int i = 0;
|
||||
for (String className : classesLongNames) {
|
||||
String displayName = StringTools.cutClassName(className);
|
||||
|
||||
classesList.add(new TypeSelectorItem(className, displayName, toolTips[i++]));
|
||||
}
|
||||
comboBoxModel = new DefaultComboBoxModel<>(classesList);
|
||||
this.setModel(comboBoxModel);
|
||||
this.setRenderer(new ToolTipComboBoxRenderer());
|
||||
}
|
||||
}
|
||||
|
||||
private String[] collectComboToolTips(List<Class<?>> instances, int maxLen) {
|
||||
String[] tips = new String[instances.size()];
|
||||
|
||||
for (int i = 0; i < tips.length; i++) {
|
||||
tips[i] = null;
|
||||
|
||||
String tip = null;
|
||||
|
||||
Description description = instances.get(i).getAnnotation(Description.class);
|
||||
if (description != null) {
|
||||
tip = description.value();
|
||||
}
|
||||
|
||||
if (tip != null) {
|
||||
if (tip.length() <= maxLen) {
|
||||
tips[i] = tip;
|
||||
} else {
|
||||
tips[i] = tip.substring(0, maxLen - 2) + "..";
|
||||
}
|
||||
}
|
||||
}
|
||||
return tips;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ToolTipComboBoxRenderer extends BasicComboBoxRenderer {
|
||||
|
||||
private static final long serialVersionUID = -5781643352198561208L;
|
||||
|
||||
public ToolTipComboBoxRenderer() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value,
|
||||
int index, boolean isSelected, boolean cellHasFocus) {
|
||||
|
||||
super.getListCellRendererComponent(list, value, index,
|
||||
isSelected, cellHasFocus);
|
||||
|
||||
if (value != null) {
|
||||
TypeSelectorItem item = (TypeSelectorItem)value;
|
||||
setText(item.getDisplayName());
|
||||
|
||||
if (isSelected) {
|
||||
setBackground(list.getSelectionBackground());
|
||||
setForeground(list.getSelectionForeground());
|
||||
list.setToolTipText(item.getDescription());
|
||||
} else {
|
||||
setBackground(list.getBackground());
|
||||
setForeground(list.getForeground());
|
||||
}
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
TypeSelectorItem item = (TypeSelectorItem)value;
|
||||
setText(item.getDisplayName());
|
||||
}
|
||||
|
||||
setFont(list.getFont());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
34
src/main/java/eva2/gui/TypeSelectorItem.java
Normal file
34
src/main/java/eva2/gui/TypeSelectorItem.java
Normal file
@ -0,0 +1,34 @@
|
||||
package eva2.gui;
|
||||
|
||||
public class TypeSelectorItem
|
||||
{
|
||||
private String id;
|
||||
private String displayName;
|
||||
private String description;
|
||||
|
||||
public TypeSelectorItem(String id, String displayName, String description)
|
||||
{
|
||||
this.id = id;
|
||||
this.displayName = displayName;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getDescription()
|
||||
{
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
}
|
@ -79,7 +79,7 @@ public class ArrayEditor extends JPanel implements PropertyEditor {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
boolean consistentView = true; // be optimistic...
|
||||
boolean consistentView;
|
||||
if (view instanceof PropertyText) { // check consistency!
|
||||
consistentView = ((PropertyText) view).checkConsistency();
|
||||
if (!consistentView) {
|
||||
@ -238,7 +238,7 @@ public class ArrayEditor extends JPanel implements PropertyEditor {
|
||||
list.ensureIndexIsVisible(index);
|
||||
propPanel.getEditor().setValue(item);
|
||||
propPanel.showDialog();
|
||||
propPanel = null;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -291,7 +291,7 @@ public class ArrayEditor extends JPanel implements PropertyEditor {
|
||||
((GenericObjectEditor) e).setClassType(valueClass);
|
||||
}
|
||||
e.setValue(value);
|
||||
JPanel cellPanel = new JPanel() {
|
||||
return new JPanel() {
|
||||
|
||||
@Override
|
||||
public void paintComponent(Graphics g) {
|
||||
@ -315,7 +315,6 @@ public class ArrayEditor extends JPanel implements PropertyEditor {
|
||||
return newPref;
|
||||
}
|
||||
};
|
||||
return cellPanel;
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
@ -401,7 +400,6 @@ public class ArrayEditor extends JPanel implements PropertyEditor {
|
||||
}
|
||||
}
|
||||
|
||||
//setPreferredSize(new Dimension(400,500));
|
||||
|
||||
if (withAddButton && !(upperButtonList.contains(addButton))) {
|
||||
upperButtonList.add(addButton);
|
||||
@ -415,9 +413,6 @@ public class ArrayEditor extends JPanel implements PropertyEditor {
|
||||
|
||||
// Upper Button Panel
|
||||
JPanel combiUpperPanel = new JPanel(getButtonLayout(0, upperButtonList));
|
||||
// ToDo Figure out how to now show this on Job Pane
|
||||
combiUpperPanel.add(view);
|
||||
view.setVisible(withAddButton);
|
||||
|
||||
for (JButton but : upperButtonList) {
|
||||
combiUpperPanel.add(but);
|
||||
@ -431,6 +426,12 @@ public class ArrayEditor extends JPanel implements PropertyEditor {
|
||||
gbConstraints.gridy = 0;
|
||||
add(combiUpperPanel, gbConstraints);
|
||||
|
||||
gbConstraints.gridy++;
|
||||
gbConstraints.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbConstraints.weightx = 1.0;
|
||||
add(view, gbConstraints);
|
||||
view.setVisible(withAddButton);
|
||||
|
||||
// Job List
|
||||
gbConstraints.gridy++;
|
||||
gbConstraints.fill = GridBagConstraints.BOTH;
|
||||
@ -461,13 +462,7 @@ public class ArrayEditor extends JPanel implements PropertyEditor {
|
||||
add(additionalCenterComp, gbConstraints);
|
||||
}
|
||||
|
||||
elementEditor.addPropertyChangeListener(new PropertyChangeListener() {
|
||||
|
||||
@Override
|
||||
public void propertyChange(final PropertyChangeEvent event) {
|
||||
repaint();
|
||||
}
|
||||
});
|
||||
elementEditor.addPropertyChangeListener(event -> repaint());
|
||||
|
||||
addPopupMenu();
|
||||
} catch (Exception ex) {
|
||||
@ -493,8 +488,8 @@ public class ArrayEditor extends JPanel implements PropertyEditor {
|
||||
* @return
|
||||
*/
|
||||
private LayoutManager getButtonLayout(int additionalOffset, List<JButton> bList) {
|
||||
int lines = 1 + ((bList.size() + additionalOffset - 1) / 3);
|
||||
int cols = 3;
|
||||
int lines = 1 + ((bList.size() + additionalOffset - 1) / cols);
|
||||
return new GridLayout(lines, cols);
|
||||
}
|
||||
|
||||
@ -531,15 +526,11 @@ public class ArrayEditor extends JPanel implements PropertyEditor {
|
||||
* @return
|
||||
*/
|
||||
private ActionListener makeSelectionKnownAL(final ActionListener al) {
|
||||
return new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (selectableList != null) {
|
||||
selectableList.setSelectionByIndices(elementList.getSelectedIndices());
|
||||
}
|
||||
al.actionPerformed(e);
|
||||
return e -> {
|
||||
if (selectableList != null) {
|
||||
selectableList.setSelectionByIndices(elementList.getSelectedIndices());
|
||||
}
|
||||
al.actionPerformed(e);
|
||||
};
|
||||
}
|
||||
|
||||
@ -576,12 +567,7 @@ public class ArrayEditor extends JPanel implements PropertyEditor {
|
||||
}
|
||||
|
||||
public boolean areAllSelected() {
|
||||
for (int i = 0; i < elementList.getModel().getSize(); i++) {
|
||||
if (!elementList.isSelectedIndex(i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return elementList.getSelectedIndices().length == elementList.getModel().getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -647,7 +633,6 @@ public class ArrayEditor extends JPanel implements PropertyEditor {
|
||||
private JMenuItem createMenuItem(String title, boolean enabled,
|
||||
ActionListener aListener) {
|
||||
JMenuItem item = new JMenuItem(title);
|
||||
// if (bgColor!=null) item.setForeground(bgColor);
|
||||
item.addActionListener(aListener);
|
||||
item.setEnabled(enabled);
|
||||
return item;
|
||||
|
214
src/main/java/eva2/gui/editor/ObjectArrayEditor.java
Normal file
214
src/main/java/eva2/gui/editor/ObjectArrayEditor.java
Normal file
@ -0,0 +1,214 @@
|
||||
package eva2.gui.editor;
|
||||
|
||||
import eva2.gui.*;
|
||||
import eva2.tools.StringTools;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.beans.PropertyEditor;
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
/**
|
||||
* Created by halfdan on 17/12/15.
|
||||
*/
|
||||
public class ObjectArrayEditor<T> extends JPanel implements PropertyEditor {
|
||||
private T[] value;
|
||||
private JList<T> objectList;
|
||||
private DefaultListModel<T> listModel;
|
||||
private PropertyChangeSupport propChangeSupport;
|
||||
private JButton configButton;
|
||||
|
||||
public ObjectArrayEditor(Class<T> type) {
|
||||
listModel = new DefaultListModel<>();
|
||||
|
||||
setLayout(new GridBagLayout());
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.gridwidth = 2;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.weightx = 1.0;
|
||||
c.weighty = 0.0;
|
||||
c.gridx = 0;
|
||||
c.gridy = 0;
|
||||
|
||||
TypeSelector typeSelector = new TypeSelector();
|
||||
typeSelector.updateClassType(type.getName());
|
||||
|
||||
add(typeSelector, c);
|
||||
|
||||
JButton addButton = new JButton("Add");
|
||||
c.gridwidth = 1;
|
||||
c.gridx = 2;
|
||||
c.gridy = 0;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.weightx = 1.0;
|
||||
c.weighty = 0.0;
|
||||
add(addButton, c);
|
||||
|
||||
JButton removeButton = new JButton("Remove");
|
||||
c.gridx = 2;
|
||||
c.gridy = 1;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.weightx = 1.0;
|
||||
c.weighty = 0.0;
|
||||
add(removeButton, c);
|
||||
|
||||
configButton = new JButton("Config");
|
||||
c.gridx = 2;
|
||||
c.gridy = 2;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.weightx = 1.0;
|
||||
c.weighty = 0.0;
|
||||
|
||||
add(configButton, c);
|
||||
|
||||
objectList = new JList<>(listModel);
|
||||
objectList.setVisibleRowCount(10);
|
||||
|
||||
c.gridwidth = 2;
|
||||
c.gridheight = 5;
|
||||
c.gridx = 0;
|
||||
c.gridy = 1;
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
c.weightx = 1.0;
|
||||
c.weighty = 1.0;
|
||||
|
||||
JScrollPane scrollPane = new JScrollPane(objectList);
|
||||
add(scrollPane, c);
|
||||
|
||||
addButton.addActionListener(event -> {
|
||||
String className = ((TypeSelectorItem) typeSelector.getSelectedItem()).getId();
|
||||
try {
|
||||
T n = (T) Class.forName(className).newInstance();
|
||||
listModel.addElement(n);
|
||||
propChangeSupport.firePropertyChange("", null, null);
|
||||
} catch (Exception ex) {
|
||||
System.err.println("Exception in itemStateChanged " + ex.getMessage());
|
||||
System.err.println("Classpath is " + System.getProperty("java.class.path"));
|
||||
ex.printStackTrace();
|
||||
|
||||
JOptionPane.showMessageDialog(this,
|
||||
"Could not create an example of\n"
|
||||
+ className + "\n"
|
||||
+ "from the current classpath. Is the resource folder at the right place?\nIs the class abstract or the default constructor missing?",
|
||||
"GenericObjectEditor",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
});
|
||||
|
||||
removeButton.addActionListener(event -> {
|
||||
if (!objectList.isSelectionEmpty()) {
|
||||
listModel.remove(objectList.getSelectedIndex());
|
||||
propChangeSupport.firePropertyChange("", null, null);
|
||||
}
|
||||
});
|
||||
|
||||
configButton.addActionListener(event -> {
|
||||
T selected = objectList.getSelectedValue();
|
||||
PropertyEditor editor = PropertyEditorProvider.findEditor(selected.getClass());
|
||||
editor.setValue(selected);
|
||||
PropertyDialog propertyDialog = new PropertyDialog(null, editor, StringTools.cutClassName(editor.getClass().getName()));
|
||||
propertyDialog.setPreferredSize(new Dimension(500, 300));
|
||||
propertyDialog.setModal(true);
|
||||
propertyDialog.setVisible(true);
|
||||
propChangeSupport.firePropertyChange("", null, null);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Object value) {
|
||||
this.value = (T[])value;
|
||||
listModel.removeAllElements();
|
||||
for(T i : this.value) {
|
||||
listModel.addElement(i);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
if (listModel == null) {
|
||||
return null;
|
||||
} else {
|
||||
// Convert the listmodel to an array of T and return it.
|
||||
int length = listModel.getSize();
|
||||
Object result = Array.newInstance(value.getClass().getComponentType(), length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
Array.set(result, i, listModel.elementAt(i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPaintable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintValue(Graphics gfx, Rectangle box) {
|
||||
FontMetrics fm = gfx.getFontMetrics();
|
||||
int vpad = (box.height - fm.getAscent()) / 2;
|
||||
String rep;
|
||||
if (listModel.getSize() == 0) {
|
||||
rep = "Empty";
|
||||
} else {
|
||||
rep = listModel.getSize() + " of " + StringTools.cutClassName(value.getClass().getComponentType().getName());
|
||||
Object maybeName = BeanInspector.callIfAvailable(listModel.get(0), "getName", new Object[]{});
|
||||
if (maybeName != null) {
|
||||
rep = rep + " (" + maybeName + "...)";
|
||||
}
|
||||
}
|
||||
gfx.drawString(rep, 2, fm.getHeight() + vpad - 3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJavaInitializationString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsText() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAsText(String text) throws IllegalArgumentException {
|
||||
throw new IllegalArgumentException(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getTags() {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getCustomEditor() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsCustomEditor() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPropertyChangeListener(PropertyChangeListener l) {
|
||||
if (propChangeSupport == null) {
|
||||
propChangeSupport = new PropertyChangeSupport(this);
|
||||
}
|
||||
propChangeSupport.addPropertyChangeListener(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePropertyChangeListener(PropertyChangeListener l) {
|
||||
if (propChangeSupport == null) {
|
||||
propChangeSupport = new PropertyChangeSupport(this);
|
||||
}
|
||||
propChangeSupport.removePropertyChangeListener(l);
|
||||
}
|
||||
|
||||
public void toggleConfigButton() {
|
||||
this.configButton.setEnabled(!configButton.isEnabled());
|
||||
}
|
||||
}
|
@ -162,11 +162,8 @@ public class OptimizationJobList extends PropertySelectableList<OptimizationJob>
|
||||
(StatisticsOnTwoSampledData[]) StatisticalEvaluation.statsParams.getTwoSampledStats().getSelectedEnum(StatisticsOnTwoSampledData.values()));
|
||||
ActionListener sl = e -> arrayEditor.selectDeselectAll();
|
||||
|
||||
ActionListener cliButtonListener = actionEvent -> System.out.println("Generating CLI call");
|
||||
|
||||
ActionListener sal = e -> jobList.saveSelectedJobs(arrayEditor);
|
||||
|
||||
arrayEditor.addUpperActionButton("Get CLI", cliButtonListener);
|
||||
arrayEditor.addUpperActionButton("(De-)Sel. all", sl);
|
||||
arrayEditor.addUpperActionButton("Test Stats", al);
|
||||
|
||||
|
33
src/main/java/eva2/tools/Primitives.java
Normal file
33
src/main/java/eva2/tools/Primitives.java
Normal file
@ -0,0 +1,33 @@
|
||||
package eva2.tools;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by halfdan on 17/12/15.
|
||||
*/
|
||||
public class Primitives {
|
||||
public static Class<?> unwrap(Class<?> clazz) {
|
||||
return getWrapperTypes().get(clazz);
|
||||
}
|
||||
|
||||
public static boolean isWrapperType(Class<?> clazz)
|
||||
{
|
||||
return getWrapperTypes().containsKey(clazz);
|
||||
}
|
||||
|
||||
private static Map<Class<?>, Class<?>> getWrapperTypes()
|
||||
{
|
||||
Map<Class<?>, Class<?>> ret = new HashMap<>();
|
||||
ret.put(Boolean.class, boolean.class);
|
||||
ret.put(Character.class, char.class);
|
||||
ret.put(Byte.class, byte.class);
|
||||
ret.put(Short.class, short.class);
|
||||
ret.put(Integer.class, int.class);
|
||||
ret.put(Long.class, long.class);
|
||||
ret.put(Float.class, float.class);
|
||||
ret.put(Double.class, double.class);
|
||||
ret.put(Void.class, void.class);
|
||||
return ret;
|
||||
}
|
||||
}
|
40
src/test/java/eva2/gui/TypeSelectorItemTest.java
Normal file
40
src/test/java/eva2/gui/TypeSelectorItemTest.java
Normal file
@ -0,0 +1,40 @@
|
||||
package eva2.gui;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class TypeSelectorItemTest {
|
||||
TypeSelectorItem item;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
item = new TypeSelectorItem(
|
||||
"eva2.problem.AbstractProblemDouble",
|
||||
"AbstractProblemDouble",
|
||||
"An abstract problem"
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetId() throws Exception {
|
||||
assertEquals("eva2.problem.AbstractProblemDouble", item.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDescription() throws Exception {
|
||||
assertEquals("An abstract problem", item.getDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDisplayName() throws Exception {
|
||||
assertEquals("AbstractProblemDouble", item.getDisplayName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToString() throws Exception {
|
||||
// Should match the id
|
||||
assertEquals("eva2.problem.AbstractProblemDouble", item.toString());
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user