package vooga.scroller.viewUtil;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.swing.AbstractAction;
import javax.swing.ButtonGroup;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JToggleButton;
import vooga.scroller.util.Pixmap;
/**
* This class handles both the logical and visual grouping for a group of Radio Buttons.
* It notifies the listener provided at instantiation.
* @author Dagbedji Fagnisse
*
*/
public class RadioGroup extends JPanel {
static int DEFAULT_BUTTON_MARGIN = 16;
private List<JToggleButton> myButtons;
private ButtonGroup myGrouper;
private ActionListener myListener;
/**
* For internal logical handling
*/
private Map<String, String> myOptions;
private RadioGroup(ActionListener listener) {
myButtons = new ArrayList<JToggleButton>();
myGrouper = new ButtonGroup();
myListener = listener;
myOptions = new TreeMap<String, String>();
}
/**
* Create a RadioGroup with the specified Radio Options
* @param listener - listener supposed to handle events for the Radio Group
* @param buttons - representing Radio options
*/
public RadioGroup(Dimension containerSize, ActionListener listener, List<JToggleButton> buttons) {
this(listener);
add(buttons);
applyLayout(containerSize);
}
/**
* Create a RadioGroup with the specified optionsMap
* @param listener - listener supposed to handle events for the Radio Group
* @param optionsMap - representing Radio options (key-value pairs)
*/
public RadioGroup(Dimension containerSize, ActionListener listener, Map<? extends Object, String> optionsMap) {
this(containerSize, listener, makeRadioButtons(optionsMap));
}
/**
* Create a simple RadioGroup with the specified Radio String Options
* @param listener - listener supposed to handle events for the Radio Group
* @param options - representing Radio options (literals)
*/
public RadioGroup(Dimension containerSize, ActionListener listener, String ...options) {
this(containerSize, listener, makeRadioButtons(mapify(options)));
}
/**
* Create 2 radio groups and retrieve the user input in an interactive manner.
* Show retrieval through the command line.
* @param args
*/
public static void main (String[] args) {
JFrame tester = new JFrame("RadioGroup Tester");
tester.setSize(250, 150);
tester.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ActionListener testAction = getTestAction();
RadioGroup rg1 = new RadioGroup(tester.getSize(), testAction, "2013", "2014", "2015", "2016");
System.out.println(rg1.getHTML());
Map<String, String> sex = new HashMap<String, String>();
sex.put("Male", "M");
sex.put("Female", "F");
RadioGroup rg2 = new RadioGroup(tester.getSize(), testAction, sex);
System.out.println(rg2);
EasyGridFactory.layout(tester, rg1, rg2);
tester.pack();
tester.setVisible(true);
}
/**
* Add the buttons passes to the RadioGroup
* @param buttons - to be added
*/
public void add (List<JToggleButton>buttons) {
for (JToggleButton b:buttons) {
add(b);
}
}
private void applyLayout(Dimension containerSize) {
this.setLayout(new GridLayout(0, getButtonsPerRow(containerSize)));
}
private int getButtonsPerRow (Dimension containerSize) {
int sampleWidth = myButtons.get(0).getSize().width;
if(sampleWidth == 0) {
sampleWidth = 40;
}
sampleWidth += DEFAULT_BUTTON_MARGIN;
int result = containerSize.width/sampleWidth;
return result;
}
private void add (JToggleButton b) {
super.add(b);
myButtons.add(b);
myGrouper.add(b);
myOptions.put(b.getText(), b.getActionCommand());
b.addActionListener(myListener);
}
private String compose (String before, String after) {
StringBuilder res = new StringBuilder();
for (JToggleButton b: myButtons) {
String n = b.getText();
res.append(before + n + after + "\n");
}
return res.toString();
}
/**
*
* @return an HTML version of this element
*/
public String getHTML() {
StringBuilder res = new StringBuilder();
for (JToggleButton b: myButtons) {
String n = getHTML(b);
res.append(n + "\n");
}
return res.toString();
}
private String getHTML(JToggleButton b) {
String myName = "group";
return "<input type=\"radio\" " +
"name=" + myName + " " +
"value=" + b.getActionCommand() +
" />"
+ b.getText() + "<br>";
}
private static List<JToggleButton> makeRadioButtons(Map<? extends Object, String> optionsMap) {
List<JToggleButton> buttons = new ArrayList<JToggleButton>();
for (Object o: optionsMap.keySet()) {
JToggleButton currB = new JToggleButton();
if (o instanceof String) {
String s = (String)o;
currB = makeRadioOption(s, optionsMap.get(o));
}
else if (o instanceof Icon) {
Icon i = (Icon)o;
currB = makeRadioOption(i, optionsMap.get(o));
}
else if (o instanceof Image) {
Image i = (Image)o;
currB = makeRadioOption(getIcon(i, 40), optionsMap.get(o));
}
else if (o instanceof Pixmap) {
Pixmap p = (Pixmap)o;
currB = makeRadioOption(p, optionsMap.get(o));
}
buttons.add(currB);
}
return buttons;
}
private static JRadioButton makeRadioOption (Pixmap p, String optionValue) {
JRadioButton res = new JRadioButton((Icon) p);
res.setActionCommand(optionValue);
res.setSelected(true);
return res;
}
private static JToggleButton makeRadioOption (String optionLabel, String optionValue) {
JToggleButton res = new JToggleButton(optionLabel);
res.setActionCommand(optionValue);
res.setSelected(true);
return res;
}
private static ImageIcon getIcon (Image a, int size) {
return new ImageIcon(a.getScaledInstance(size, size,
Image.SCALE_SMOOTH));
}
private static JToggleButton makeRadioOption (Icon c, String optionValue) {
JToggleButton res = new JToggleButton(c);
res.setActionCommand(optionValue);
res.setSelected(true);
return res;
}
private static Map<String, String> mapify(String ...options) {
Map<String, String> res = new HashMap<String, String>();
for (String o: options) {
res.put(o, o);
}
return res;
}
@Override
public String toString() {
return compose("� ", "");
}
/**
* Test Action (for JUnit testing)
* @author Dagbedji Fagnisse
*
*/
public static class TestAction extends AbstractAction {
/**
*
*/
private static final long serialVersionUID = -3838081948621848563L;
TestAction() {
super("TestAction");
}
@Override
public void actionPerformed (ActionEvent e) {
System.out.println(e.getActionCommand());
}
}
private static final long serialVersionUID = 1L;
public static AbstractAction getTestAction() {
return new TestAction();
}
}