Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Icon Checkbox for Changing Properties in Explorer Views

DZone's Guide to

Icon Checkbox for Changing Properties in Explorer Views

· Java Zone
Free Resource

Learn how to troubleshoot and diagnose some of the most common performance issues in Java today. Brought to you in partnership with AppDynamics.

Let's say we need to display our boolean properties as icon checkboxes that should be clickable to change the underlying value. When the underlying value changes, the icon itself should also change. So, here's one state:

But when the icon is clicked, the other state is represented by a new icon:

Similarly, in an OutlineView:

The difference between the first image and the second is that the icon shown in the first image was clicked, causing the icon to change, representing a change in the underlying value.

How to achieve this?

Well, below is all the relevant code, i.e., an interesting new property editor for boolean values, while all the source code is here:

http://java.net/projects/nb-api-samples/sources/api-samples/show/versions/7.1/misc/IconCheckboxDemo

public class StatusNode extends AbstractNode {

private Icon selected = new DiamondIcon(Color.RED, true);
private Icon unselected = new DiamondIcon(Color.BLACK, false);

public StatusNode(StatusObject statusObject) {
super(Children.LEAF, Lookups.singleton(statusObject));
}

@Override
protected Sheet createSheet() {
Sheet sheet = Sheet.createDefault();
Sheet.Set set = Sheet.createPropertiesSet();
set.put(new StatusProperty(getLookup().lookup(StatusObject.class)));
sheet.put(set);
return sheet;
}

public class StatusProperty extends PropertySupport.ReadWrite<String> {

private StatusObject statusObject;

public StatusProperty(StatusObject statusObject) {
super("visible", String.class, "visible", "Visibility of Object");
this.statusObject = statusObject;
}

@Override
public PropertyEditor getPropertyEditor() {
return new StatusPropertyEditorSupport(statusObject);
}

@Override
public String getValue() throws IllegalAccessException,
InvocationTargetException {
return String.valueOf(statusObject.isVisible());
}

@Override
public void setValue(String newValue) throws IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
statusObject.setVisible(Boolean.valueOf(newValue));
}

}

private class StatusPropertyEditorSupport extends PropertyEditorSupport implements ExPropertyEditor, InplaceEditor.Factory {

private StatusObject statusObject;

private StatusPropertyEditorSupport(StatusObject statusObject) {
this.statusObject = statusObject;
}

@Override
public boolean isPaintable() {
return true;
}

@Override
public void paintValue(Graphics g, Rectangle r) {
Image image;
if (statusObject.isVisible()) {
image = ImageUtilities.icon2Image(selected);
} else {
image = ImageUtilities.icon2Image(unselected);
}
ImageIcon icon = new ImageIcon(image);
if (icon != null) {
int iconWidth = icon.getIconWidth();
int iconHeight = icon.getIconHeight();
double scale = (double) iconWidth / iconHeight;
if (iconWidth > r.width) {
iconWidth = r.width;
iconHeight = (int) (iconWidth / scale);
}
if (iconHeight > r.height) {
iconHeight = r.height;
iconWidth = (int) (iconHeight / scale);
}
int x;
if (iconWidth < r.x) {
x = (r.x - iconWidth) / 2;
} else {
x = -1;
}
int y;
if (iconHeight < r.y) {
y = (r.y - iconHeight) / 2;
} else {
y = 5;
}
Graphics g2 = g.create(r.x, r.y, r.width, r.height);
g2.drawImage(icon.getImage(), x, y, iconWidth, iconHeight, null);
}

}

@Override
public void attachEnv(PropertyEnv env) {
env.registerInplaceEditorFactory(this);
}
private InplaceEditor ed = null;

@Override
public InplaceEditor getInplaceEditor() {
if (ed == null) {
ed = new Inplace(statusObject);
}
return ed;
}

}

public class Inplace implements InplaceEditor {

private final JCheckBox cb = new JCheckBox(selected);
private PropertyEditor editor = null;
private final StatusObject c;

private Inplace(final StatusObject c) {
this.c = c;
}

@Override
public void connect(PropertyEditor propertyEditor, PropertyEnv env) {
editor = propertyEditor;
reset();
}

@Override
public JComponent getComponent() {
cb.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
reset();
}
});
return cb;
}

@Override
public void clear() {
editor = null;
model = null;
}

@Override
public Object getValue() {
return String.valueOf(c.isVisible());
}

@Override
public void setValue(Object object) {
Boolean valueOf = Boolean.valueOf((String) object);
c.setVisible(valueOf);
}

@Override
public boolean supportsTextEntry() {
return false;
}

@Override
public void reset() {
if (cb.isSelected()) {
c.setVisible(true);
cb.setIcon(selected);
cb.setSelectedIcon(selected);
} else {
c.setVisible(false);
cb.setIcon(unselected);
}
}

@Override
public KeyStroke[] getKeyStrokes() {
return new KeyStroke[0];
}

@Override
public PropertyEditor getPropertyEditor() {
return editor;
}

@Override
public PropertyModel getPropertyModel() {
return model;
}
private PropertyModel model;

@Override
public void setPropertyModel(PropertyModel propertyModel) {
this.model = propertyModel;
}

@Override
public boolean isKnownComponent(Component component) {
return component == cb || cb.isAncestorOf(component);
}

@Override
public void addActionListener(ActionListener actionListener) {
}

@Override
public void removeActionListener(ActionListener actionListener) {
}
}

class DiamondIcon implements Icon {

private Color color;
private boolean selected;
private int width;
private int height;
private Polygon poly;
private static final int DEFAULT_WIDTH = 10;
private static final int DEFAULT_HEIGHT = 10;

public DiamondIcon(Color color) {
this(color, true, DEFAULT_WIDTH, DEFAULT_HEIGHT);
}

public DiamondIcon(Color color, boolean selected) {
this(color, selected, DEFAULT_WIDTH, DEFAULT_HEIGHT);
}

public DiamondIcon(Color color, boolean selected, int width, int height) {
this.color = color;
this.selected = selected;
this.width = width;
this.height = height;
initPolygon();
}

private void initPolygon() {
poly = new Polygon();
int halfWidth = width / 2;
int halfHeight = height / 2;
poly.addPoint(0, halfHeight);
poly.addPoint(halfWidth, 0);
poly.addPoint(width, halfHeight);
poly.addPoint(halfWidth, height);
}

@Override
public int getIconHeight() {
return height;
}

@Override
public int getIconWidth() {
return width;
}

@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
g.setColor(color);
g.translate(x, y);
if (selected) {
g.fillPolygon(poly);
} else {
g.drawPolygon(poly);
}
g.translate(-x, -y);
}

}

}

Ultimately, you should be able to use the above code to create a clickable control panel that looks something like this:

Understand the needs and benefits around implementing the right monitoring solution for a growing containerized market. Brought to you in partnership with AppDynamics.

Topics:

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}