final FurnitureController controller) {
// Get unit name matching current unit
String unitName = preferences.getLengthUnit().getName();
// Create id label and its text field bound to ID controller property
this.idLabel = new JLabel(SwingTools.getLocalizedLabelText(preferences, FurniturePanel.class, "idLabel.text"));
this.idTextField = new JTextField(controller.getId(), 10);
if (!OperatingSystem.isMacOSX()) {
SwingTools.addAutoSelectionOnFocusGain(this.idTextField);
}
final PropertyChangeListener idChangeListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
idTextField.setText(controller.getId());
}
};
controller.addPropertyChangeListener(FurnitureController.Property.ID, idChangeListener);
this.idTextField.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent ev) {
controller.removePropertyChangeListener(FurnitureController.Property.ID, idChangeListener);
String id = idTextField.getText();
if (id == null || id.trim().length() == 0) {
controller.setId(null);
} else {
controller.setId(id);
}
controller.addPropertyChangeListener(FurnitureController.Property.ID, idChangeListener);
}
public void insertUpdate(DocumentEvent ev) {
changedUpdate(ev);
}
public void removeUpdate(DocumentEvent ev) {
changedUpdate(ev);
}
});
// Create name label and its text field bound to NAME controller property
this.nameLabel = new JLabel(SwingTools.getLocalizedLabelText(preferences, FurniturePanel.class, "nameLabel.text"));
this.nameTextField = new JTextField(controller.getName(), 10);
if (!OperatingSystem.isMacOSX()) {
SwingTools.addAutoSelectionOnFocusGain(this.nameTextField);
}
final PropertyChangeListener nameChangeListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
nameTextField.setText(controller.getName());
}
};
controller.addPropertyChangeListener(FurnitureController.Property.NAME, nameChangeListener);
this.nameTextField.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent ev) {
controller.removePropertyChangeListener(FurnitureController.Property.NAME, nameChangeListener);
String name = nameTextField.getText();
if (name == null || name.trim().length() == 0) {
controller.setName(null);
} else {
controller.setName(name);
}
controller.addPropertyChangeListener(FurnitureController.Property.NAME, nameChangeListener);
}
public void insertUpdate(DocumentEvent ev) {
changedUpdate(ev);
}
public void removeUpdate(DocumentEvent ev) {
changedUpdate(ev);
}
});
// Create description label and its text field bound to DESCRIPTION controller property
this.descriptionLabel = new JLabel(SwingTools.getLocalizedLabelText(preferences, FurniturePanel.class, "descriptionLabel.text"));
this.descriptionTextField = new JTextField(controller.getDescription(), 10);
if (!OperatingSystem.isMacOSX()) {
SwingTools.addAutoSelectionOnFocusGain(this.descriptionTextField);
}
final PropertyChangeListener descriptionChangeListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
descriptionTextField.setText(controller.getDescription());
}
};
controller.addPropertyChangeListener(FurnitureController.Property.DESCRIPTION, descriptionChangeListener);
this.descriptionTextField.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent ev) {
controller.removePropertyChangeListener(FurnitureController.Property.DESCRIPTION, descriptionChangeListener);
String description = descriptionTextField.getText();
if (description == null || description.trim().length() == 0) {
controller.setDescription(null);
} else {
controller.setDescription(description);
}
controller.addPropertyChangeListener(FurnitureController.Property.DESCRIPTION, descriptionChangeListener);
}
public void insertUpdate(DocumentEvent ev) {
changedUpdate(ev);
}
public void removeUpdate(DocumentEvent ev) {
changedUpdate(ev);
}
});
this.categoryLabel = new JLabel(SwingTools.getLocalizedLabelText(preferences,
FurniturePanel.class, "categoryLabel.text"));
final List<FurnitureCategory> categories = controller.getAvailableCategories();
List<FurnitureCategory> categoriesList = new ArrayList<FurnitureCategory>(categories);
final boolean nullableComboBox = controller.getCategory() == null;
if (nullableComboBox) {
categoriesList.add(0, null);
}
this.categoryComboBox = new JComboBox(categoriesList.toArray());
this.categoryComboBox.setEditable(true);
final ComboBoxEditor defaultEditor = this.categoryComboBox.getEditor();
// Change editor to edit category name
this.categoryComboBox.setEditor(new ComboBoxEditor() {
public Object getItem() {
String name = (String)defaultEditor.getItem();
name = name.trim();
// If category is empty, replace it by the last selected item
if (name.length() == 0) {
setItem(nullableComboBox ? null : categoryComboBox.getSelectedItem());
}
FurnitureCategory category = new FurnitureCategory(name);
// Search an existing category
int categoryIndex = Collections.binarySearch(categories, category);
if (categoryIndex >= 0) {
return categories.get(categoryIndex);
}
// If no existing category was found, return a new one
return category;
}
public void setItem(Object value) {
if (value != null) {
FurnitureCategory category = (FurnitureCategory)value;
defaultEditor.setItem(category.getName());
}
}
public void addActionListener(ActionListener l) {
defaultEditor.addActionListener(l);
}
public Component getEditorComponent() {
return defaultEditor.getEditorComponent();
}
public void removeActionListener(ActionListener l) {
defaultEditor.removeActionListener(l);
}
public void selectAll() {
defaultEditor.selectAll();
}
});
this.categoryComboBox.setRenderer(new DefaultListCellRenderer() {
public Component getListCellRendererComponent(JList list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
if (value == null) {
value = " ";
} else {
value = ((FurnitureCategory)value).getName();
}
return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
}
});
this.categoryComboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent ev) {
controller.setCategory((FurnitureCategory)ev.getItem());
}
});
controller.addPropertyChangeListener(FurnitureController.Property.CATEGORY,
new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
// If category changes update category combo box
FurnitureCategory category = controller.getCategory();
if (category != null) {
categoryComboBox.setSelectedItem(category);
}
}
});
if (this.categoryComboBox.getItemCount() > 0) {
this.categoryComboBox.setSelectedItem(controller.getCategory());
}
this.categoryComboBox.setMaximumRowCount(15);
// Create price label and its spinner bound to PRICE controller property
this.priceLabel = new JLabel(SwingTools.getLocalizedLabelText(preferences,
FurniturePanel.class, "priceLabel.text"));
final NullableSpinner.NullableSpinnerNumberModel priceSpinnerModel =
new NullableSpinner.NullableSpinnerNumberModel(1, 0.00999f, 1000000f, 1f);
this.priceSpinner = new AutoCommitSpinner(priceSpinnerModel);
priceSpinnerModel.setNullable(controller.getPrice() == null);
priceSpinnerModel.setValue(controller.getPrice());
final PropertyChangeListener priceChangeListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
priceSpinnerModel.setNullable(ev.getNewValue() == null);
priceSpinnerModel.setValue((Float)ev.getNewValue());
}
};
controller.addPropertyChangeListener(FurnitureController.Property.PRICE, priceChangeListener);
priceSpinnerModel.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent ev) {
controller.removePropertyChangeListener(FurnitureController.Property.PRICE, priceChangeListener);
Object value = priceSpinnerModel.getValue();
controller.setPrice(value != null
? new BigDecimal((Float)value).setScale(2, BigDecimal.ROUND_HALF_UP)
: (BigDecimal)value);
controller.addPropertyChangeListener(FurnitureController.Property.PRICE, priceChangeListener);
}
});
// Create VAT % label and its spinner bound to VALUE_ADDED_TAX_PERCENTAGE controller property
this.valueAddedTaxPercentageLabel = new JLabel(SwingTools.getLocalizedLabelText(preferences,
FurniturePanel.class, "valueAddedTaxPercentageLabel.text"));
final NullableSpinner.NullableSpinnerNumberModel valueAddedTaxPercentageSpinnerModel =
new NullableSpinner.NullableSpinnerNumberModel(0, 0, 100f, 0.1f);
this.valueAddedTaxPercentageSpinner = new AutoCommitSpinner(valueAddedTaxPercentageSpinnerModel);
valueAddedTaxPercentageSpinnerModel.setNullable(controller.getValueAddedTaxPercentage() == null);
valueAddedTaxPercentageSpinnerModel.setValue(controller.getValueAddedTaxPercentage() == null
? null
: controller.getValueAddedTaxPercentage().floatValue() * 100);
final PropertyChangeListener valueAddedTaxPercentageChangeListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
valueAddedTaxPercentageSpinnerModel.setNullable(ev.getNewValue() == null);
valueAddedTaxPercentageSpinnerModel.setValue(ev.getNewValue() == null
? null
: ((Float)ev.getNewValue()) * 100);
}
};
controller.addPropertyChangeListener(FurnitureController.Property.VALUE_ADDED_TAX_PERCENTAGE, valueAddedTaxPercentageChangeListener);
valueAddedTaxPercentageSpinnerModel.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent ev) {
controller.removePropertyChangeListener(FurnitureController.Property.VALUE_ADDED_TAX_PERCENTAGE, valueAddedTaxPercentageChangeListener);
Object value = valueAddedTaxPercentageSpinnerModel.getValue();
controller.setValueAddedTaxPercentage(value != null
? new BigDecimal((Float)value / 100).setScale(3, BigDecimal.ROUND_HALF_UP)
: (BigDecimal)value);
controller.addPropertyChangeListener(FurnitureController.Property.VALUE_ADDED_TAX_PERCENTAGE, valueAddedTaxPercentageChangeListener);
}
});
// Create width label and its spinner bound to WIDTH controller property
this.widthLabel = new JLabel(SwingTools.getLocalizedLabelText(preferences,
FurniturePanel.class, "widthLabel.text", unitName));
final float minimumLength = preferences.getLengthUnit().getMinimumLength();
final NullableSpinner.NullableSpinnerLengthModel widthSpinnerModel =
new NullableSpinner.NullableSpinnerLengthModel(preferences, minimumLength, 100000f);
this.widthSpinner = new AutoCommitSpinner(widthSpinnerModel);
final PropertyChangeListener widthChangeListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
Float width = controller.getWidth();
widthSpinnerModel.setNullable(width == null);
widthSpinnerModel.setLength(width);
if (width != null) {
widthSpinnerModel.setMinimum(Math.min(width, minimumLength));
}
}
};
widthChangeListener.propertyChange(null);
controller.addPropertyChangeListener(FurnitureController.Property.WIDTH, widthChangeListener);
widthSpinnerModel.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent ev) {
controller.removePropertyChangeListener(FurnitureController.Property.WIDTH, widthChangeListener);
controller.setWidth(widthSpinnerModel.getLength());
if (!controller.isProportional()) {
resetIcon(false);
}
controller.addPropertyChangeListener(FurnitureController.Property.WIDTH, widthChangeListener);
}
});
// Create depth label and its spinner bound to DEPTH controller property
this.depthLabel = new JLabel(SwingTools.getLocalizedLabelText(preferences,
FurniturePanel.class, "depthLabel.text", unitName));
final NullableSpinner.NullableSpinnerLengthModel depthSpinnerModel =
new NullableSpinner.NullableSpinnerLengthModel(preferences, minimumLength, 100000f);
this.depthSpinner = new NullableSpinner(depthSpinnerModel);
final PropertyChangeListener depthChangeListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
Float depth = controller.getDepth();
depthSpinnerModel.setNullable(depth == null);
depthSpinnerModel.setLength(depth);
if (depth != null) {
depthSpinnerModel.setMinimum(Math.min(depth, minimumLength));
}
}
};
depthChangeListener.propertyChange(null);
controller.addPropertyChangeListener(FurnitureController.Property.DEPTH, depthChangeListener);
depthSpinnerModel.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent ev) {
controller.removePropertyChangeListener(FurnitureController.Property.DEPTH, depthChangeListener);
controller.setDepth(depthSpinnerModel.getLength());
if (!controller.isProportional()) {
resetIcon(false);
}
controller.addPropertyChangeListener(FurnitureController.Property.DEPTH, depthChangeListener);
}
});
// Create height label and its spinner bound to HEIGHT controller property
this.heightLabel = new JLabel(SwingTools.getLocalizedLabelText(preferences,
FurniturePanel.class, "heightLabel.text", unitName));
final NullableSpinner.NullableSpinnerLengthModel heightSpinnerModel =
new NullableSpinner.NullableSpinnerLengthModel(preferences, minimumLength, 100000f);
this.heightSpinner = new NullableSpinner(heightSpinnerModel);
final PropertyChangeListener heightChangeListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
Float height = controller.getHeight();
heightSpinnerModel.setNullable(height == null);
heightSpinnerModel.setLength(height);
if (height != null) {
heightSpinnerModel.setMinimum(Math.min(height, minimumLength));
}
}
};
heightChangeListener.propertyChange(null);
controller.addPropertyChangeListener(FurnitureController.Property.HEIGHT, heightChangeListener);
heightSpinnerModel.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent ev) {
controller.removePropertyChangeListener(FurnitureController.Property.HEIGHT, heightChangeListener);
controller.setHeight(heightSpinnerModel.getLength());
if (!controller.isProportional()) {
resetIcon(false);
}
controller.addPropertyChangeListener(FurnitureController.Property.HEIGHT, heightChangeListener);
}
});
this.keepProportionsCheckBox = new JCheckBox(SwingTools.getLocalizedLabelText(preferences,
FurniturePanel.class, "keepProportionsCheckBox.text"), controller.isProportional());
this.keepProportionsCheckBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent ev) {
controller.setProportional(keepProportionsCheckBox.isSelected());
}
});
controller.addPropertyChangeListener(FurnitureController.Property.PROPORTIONAL,
new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
// If proportional property changes update keep proportions check box
keepProportionsCheckBox.setSelected(controller.isProportional());
}
});
// Create elevation label and its spinner bound to ELEVATION controller property
this.elevationLabel = new JLabel(SwingTools.getLocalizedLabelText(preferences,
FurniturePanel.class, "elevationLabel.text", unitName));
final NullableSpinner.NullableSpinnerLengthModel elevationSpinnerModel =
new NullableSpinner.NullableSpinnerLengthModel(preferences, 0f, 1000f);
this.elevationSpinner = new NullableSpinner(elevationSpinnerModel);
elevationSpinnerModel.setNullable(controller.getElevation() == null);
elevationSpinnerModel.setLength(controller.getElevation());
final PropertyChangeListener elevationChangeListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
elevationSpinnerModel.setNullable(ev.getNewValue() == null);
elevationSpinnerModel.setLength((Float)ev.getNewValue());
}
};
controller.addPropertyChangeListener(FurnitureController.Property.ELEVATION,
elevationChangeListener);
elevationSpinnerModel.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent ev) {
controller.removePropertyChangeListener(FurnitureController.Property.ELEVATION,
elevationChangeListener);
controller.setElevation(elevationSpinnerModel.getLength());
controller.addPropertyChangeListener(FurnitureController.Property.ELEVATION,
elevationChangeListener);
}
});
// Create movable check box bound to MOVABLE controller property
this.movableCheckBox = new NullableCheckBox(SwingTools.getLocalizedLabelText(preferences,
FurniturePanel.class, "movableCheckBox.text"));
this.movableCheckBox.setNullable(controller.getMovable() == null);
this.movableCheckBox.setValue(controller.getMovable());
final PropertyChangeListener movableChangeListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
movableCheckBox.setNullable(ev.getNewValue() == null);
movableCheckBox.setValue((Boolean)ev.getNewValue());
}
};
controller.addPropertyChangeListener(FurnitureController.Property.MOVABLE, movableChangeListener);
this.movableCheckBox.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent ev) {
controller.removePropertyChangeListener(FurnitureController.Property.MOVABLE, movableChangeListener);
controller.setMovable(movableCheckBox.getValue());
controller.addPropertyChangeListener(FurnitureController.Property.MOVABLE, movableChangeListener);
}
});
// Create doorOrWindow check box bound to DOOR_OR_WINDOW controller property
this.doorOrWindowCheckBox = new NullableCheckBox(SwingTools.getLocalizedLabelText(preferences,
FurniturePanel.class, "doorOrWindowCheckBox.text"));
this.doorOrWindowCheckBox.setNullable(controller.getDoorOrWindow() == null);
this.doorOrWindowCheckBox.setValue(controller.getDoorOrWindow());
final PropertyChangeListener doorOrWindowChangeListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
doorOrWindowCheckBox.setNullable(ev.getNewValue() == null);
doorOrWindowCheckBox.setValue((Boolean)ev.getNewValue());
}
};
controller.addPropertyChangeListener(FurnitureController.Property.DOOR_OR_WINDOW, doorOrWindowChangeListener);
this.doorOrWindowCheckBox.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent ev) {
controller.removePropertyChangeListener(FurnitureController.Property.DOOR_OR_WINDOW, doorOrWindowChangeListener);
controller.setDoorOrWindow(doorOrWindowCheckBox.getValue());
controller.addPropertyChangeListener(FurnitureController.Property.DOOR_OR_WINDOW, doorOrWindowChangeListener);
}
});
// Create back face shown check box bound to BACK_FACE_SHOWN controller property
this.backFaceShownCheckBox = new NullableCheckBox(SwingTools.getLocalizedLabelText(preferences,
FurniturePanel.class, "backFaceShownCheckBox.text"));
this.backFaceShownCheckBox.setNullable(controller.getBackFaceShown() == null);
this.backFaceShownCheckBox.setValue(controller.getBackFaceShown());
final PropertyChangeListener backFaceShownChangeListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
backFaceShownCheckBox.setNullable(ev.getNewValue() == null);
backFaceShownCheckBox.setValue((Boolean)ev.getNewValue());
}
};
controller.addPropertyChangeListener(FurnitureController.Property.BACK_FACE_SHOWN, backFaceShownChangeListener);
this.backFaceShownCheckBox.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent ev) {
controller.removePropertyChangeListener(FurnitureController.Property.BACK_FACE_SHOWN, backFaceShownChangeListener);
controller.setBackFaceShown(backFaceShownCheckBox.getValue());
resetIcon(false);
controller.addPropertyChangeListener(FurnitureController.Property.BACK_FACE_SHOWN, backFaceShownChangeListener);
}
});
// Create resizable check box bound to RESIZABLE controller property
this.resizableCheckBox = new NullableCheckBox(SwingTools.getLocalizedLabelText(preferences,
FurniturePanel.class, "resizableCheckBox.text"));
this.resizableCheckBox.setNullable(controller.getResizable() == null);
this.resizableCheckBox.setValue(controller.getResizable());
final PropertyChangeListener resizableChangeListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
resizableCheckBox.setNullable(ev.getNewValue() == null);
resizableCheckBox.setValue((Boolean)ev.getNewValue());
}
};
controller.addPropertyChangeListener(FurnitureController.Property.RESIZABLE, resizableChangeListener);
this.resizableCheckBox.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent ev) {
controller.removePropertyChangeListener(FurnitureController.Property.RESIZABLE, resizableChangeListener);
controller.setResizable(resizableCheckBox.getValue());
controller.addPropertyChangeListener(FurnitureController.Property.RESIZABLE, resizableChangeListener);
}
});
// Create deformable check box bound to DEFORMABLE controller property
this.deformableCheckBox = new NullableCheckBox(SwingTools.getLocalizedLabelText(preferences,
FurniturePanel.class, "deformableCheckBox.text"));
this.deformableCheckBox.setNullable(controller.getDeformable() == null);
this.deformableCheckBox.setValue(controller.getDeformable());
final PropertyChangeListener deformableChangeListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
deformableCheckBox.setNullable(ev.getNewValue() == null);
deformableCheckBox.setValue((Boolean)ev.getNewValue());
}
};
controller.addPropertyChangeListener(FurnitureController.Property.DEFORMABLE, deformableChangeListener);
this.deformableCheckBox.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent ev) {
controller.removePropertyChangeListener(FurnitureController.Property.DEFORMABLE, deformableChangeListener);
controller.setDeformable(deformableCheckBox.getValue());
controller.addPropertyChangeListener(FurnitureController.Property.DEFORMABLE, deformableChangeListener);
}
});
// Create creator label and its text field bound to CREATOR controller property
this.creatorLabel = new JLabel(SwingTools.getLocalizedLabelText(preferences, FurniturePanel.class, "creatorLabel.text"));
this.creatorTextField = new JTextField(controller.getCreator(), 10);
if (!OperatingSystem.isMacOSX()) {
SwingTools.addAutoSelectionOnFocusGain(this.creatorTextField);
}
final PropertyChangeListener creatorChangeListener = new PropertyChangeListener() {