/**
* Copyright (C) 2015 Valkyrie RCP
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.valkyriercp.form.binding.swing;
import com.jgoodies.forms.factories.FormFactory;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.RowSpec;
import org.springframework.util.Assert;
import org.valkyriercp.binding.form.FormModel;
import org.valkyriercp.form.binding.support.CustomBinding;
import org.valkyriercp.util.ValkyrieRepository;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Radiobutton binding for Enum values.
*
* Labels for the radio buttons can be configured in the messages:
*
* <pre>
* my.package.MyClass.MY_ENUM = My Enum Label
* my.package.MyClass.null = None
* </pre>
*
* @author Lieven Doclo
*
*/
public class EnumRadioButtonBinding extends CustomBinding {
private JPanel contentPanel;
private List<Enum> selectableEnumsList;
private Map<String, ContainerJRadioButton<Enum>> radioButtons;
private Class propertyType;
private ButtonGroup group;
private boolean horizontalLayout = false;
public EnumRadioButtonBinding(JPanel contentPanel, FormModel formModel,
String formPropertyPath, Class<?> propertyType,
List<Enum> selectableEnumsList, boolean horizontalLayout) {
super(formModel, formPropertyPath, propertyType);
this.contentPanel = contentPanel;
this.propertyType = propertyType;
radioButtons = new LinkedHashMap<String, ContainerJRadioButton<Enum>>();
this.selectableEnumsList = selectableEnumsList;
this.horizontalLayout = horizontalLayout;
createRadioButtons();
}
@Override
protected void valueModelChanged(Object newValue) {
deselectAll();
Enum enumValue = (Enum) newValue;
ContainerJRadioButton<Enum> button;
if (enumValue == null) {
button = radioButtons.get(null);
} else {
button = radioButtons.get(enumValue.name());
}
if (button != null) {
button.setSelected(true);
}
}
private void deselectAll() {
if (group != null)
group.clearSelection();
}
@Override
protected JComponent doBindControl() {
Assert.notNull(selectableEnumsList);
return createBindingControl();
}
private JPanel createBindingControl() {
// group = new ButtonGroup();
group = new ButtonGroup() {
@Override
public void setSelected(ButtonModel m, boolean b) {
if (b && m != null && m != getSelection()) {
super.setSelected(m, b);
} else if (!b && m == getSelection()) {
clearSelection();
controlValueChanged(null);
}
}
};
FormLayout layout = new FormLayout(
new ColumnSpec[] { FormFactory.DEFAULT_COLSPEC },
getDefaultRowsWithGap(radioButtons.keySet().size()));
int count = 1;
// contentPanel.setLayout(layout);
// contentPanel.setLayout(new BoxLayout(target, axis));
contentPanel.setLayout(new BoxLayout(contentPanel,
horizontalLayout ? BoxLayout.X_AXIS : BoxLayout.Y_AXIS));
for (ContainerJRadioButton<Enum> button : radioButtons.values()) {
group.add(button);
contentPanel.add(button);
// contentPanel.add(button, new CellConstraints(1, count));
// contentPanel.add(button, new CellConstraints(count, 1));
count += 2;
}
valueModelChanged(getValue());
return contentPanel;
}
private static RowSpec[] getDefaultRowsWithGap(int rowCount) {
List<RowSpec> rows = new ArrayList<RowSpec>();
for (int i = 0; i < rowCount; i++) {
rows.add(new RowSpec("fill:pref:nogrow"));
rows.add(FormFactory.LINE_GAP_ROWSPEC);
}
rows.remove(rows.size() - 1);
return rows.toArray(new RowSpec[] {});
}
@Override
protected void enabledChanged() {
for (ContainerJRadioButton<Enum> button : radioButtons.values()) {
button.setEnabled(isEnabled());
}
}
@Override
protected void readOnlyChanged() {
for (ContainerJRadioButton<Enum> button : radioButtons.values()) {
button.setEnabled(!isReadOnly());
}
}
private void createRadioButtons() {
for (Enum enumValue : selectableEnumsList) {
ContainerJRadioButton<Enum> button = new ContainerJRadioButton<Enum>();
String text;
if (enumValue == null) {
text = ValkyrieRepository.getInstance().getApplicationConfig().messageSourceAccessor().getMessage(propertyType.getName()
+ ".null", "null");
button.setText(text == null ? propertyType.getName() + ".null"
: text);
} else {
text = ValkyrieRepository.getInstance().getApplicationConfig().messageSourceAccessor().getMessage(propertyType.getName()
+ "." + enumValue.name(), enumValue.name());
button.setText(text == null ? propertyType.getName() + "."
+ enumValue.name() : text);
}
button.setContainedObject(enumValue);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ContainerJRadioButton<Enum> button = (ContainerJRadioButton<Enum>) e
.getSource();
if (button.isSelected()) {
controlValueChanged(button.getContainedObject());
}
}
});
if (enumValue == null)
radioButtons.put(null, button);
else
radioButtons.put(enumValue.name(), button);
}
}
private class ContainerJRadioButton<T> extends JRadioButton {
private T containedObject;
public T getContainedObject() {
return containedObject;
}
public void setContainedObject(T containedObject) {
this.containedObject = containedObject;
}
}
}