001: /*
002: * Created on 13-Jan-2006
003: */
004: package uk.org.ponder.rsf.components;
005:
006: import uk.org.ponder.stringutil.StringSet;
007:
008: /**
009: * Backs a selection control of some kind, where named values are presented in a
010: * list to the user. The returned value which is submitted may be a single
011: * selection, multiple selection, or empty, depending on the component type in
012: * the <code>selection</code> field.
013: * <p>
014: * The value binding <code>valuebinding</code> in the superclass, if
015: * non-empty, will retrieve an object list, which will be supplied during fixup
016: * to the resolving beans referenced by <code>nameresolver</code> (which must
017: * not be empty in this case) and <code>idresolver</code>. If idresolver is
018: * empty, the list is assumed to be a list of IDs already.
019: *
020: */
021:
022: public class UISelect extends UIComponent implements FixableComponent {
023: /** A component representing the options which the user has to choose from **/
024: public UIBoundList optionlist;
025:
026: /** A component representing the rendered labels for the list control */
027: public UIBoundList optionnames;
028: /**
029: * The input component representing the actual selected value. Expected to be
030: * either UIInput or UIInputMany.
031: */
032: public UIBound selection;
033: /**
034: * This field is set during fixup for reference of the renderer. Do not set
035: * this manually.
036: */
037: public StringSet selected;
038:
039: /** Creates a selection control without a value binding, either
040: * non-submitting, or suitable for use in a GET form */
041: public static UISelect make(UIContainer tofill, String ID,
042: String[] values, String[] labels, String value,
043: boolean willinput) {
044: UISelect togo = new UISelect();
045: togo.optionlist = new UIOutputMany();
046: togo.ID = ID;
047: togo.optionlist.setValue(values);
048: togo.optionnames = new UIBoundList();
049: togo.optionnames.setValue(labels);
050: togo.selection = new UIBoundString();
051: if (value != null) {
052: ((UIBoundString) togo.selection).setValue(value);
053: }
054: togo.selection.willinput = willinput;
055: tofill.addComponent(togo);
056: return togo;
057: }
058:
059: /** A "skeleton" make method to prepare for more complex constructions */
060: public static UISelect make(UIContainer tofill, String ID) {
061: UISelect togo = new UISelect();
062: togo.ID = ID;
063: tofill.addComponent(togo);
064: return togo;
065: }
066:
067: // TODO: perhaps split this as a "postConstruct()" and "postFixup()"
068: // method. Will we actually ever have complex components?
069: public void fixupComponent() {
070: if (optionnames != null) {
071: if (optionnames.valuebinding == null) {
072: optionnames.valuebinding = optionlist.valuebinding;
073: }
074: } else {
075: throw new IllegalArgumentException(
076: "UISelect component with full ID " + getFullID()
077: + " does not have optionnames set");
078: }
079: selected = computeSelectionSet(selection);
080: }
081:
082: public static StringSet computeSelectionSet(UIBound selection) {
083: StringSet togo = new StringSet();
084: if (selection instanceof UIBoundList) {
085: togo.addAll(((UIBoundList) selection).getValue());
086: } else if (selection instanceof UIBoundString) {
087: togo.add(((UIBoundString) selection).getValue());
088: }
089: return togo;
090: }
091:
092: protected static UISelect make(UIContainer tofill, String ID,
093: String[] options) {
094: UISelect togo = new UISelect();
095: togo.ID = ID;
096: togo.optionlist = togo.optionnames = UIOutputMany.make(options);
097: tofill.addComponent(togo);
098: return togo;
099: }
100:
101: /**
102: * Constructs a single selection control, where the submitted values are
103: * identical with the rendered labels
104: */
105: public static UISelect make(UIContainer tofill, String ID,
106: String[] options, String valuebinding, String initvalue) {
107: UISelect togo = make(tofill, ID, options);
108: UIInput selection = UIInput.make(valuebinding);
109: if (initvalue != null) {
110: selection.setValue(initvalue);
111: }
112: togo.selection = selection;
113: return togo;
114: }
115:
116: /** @see #make(UIContainer, String, String[], String[], String, String)
117: */
118: public static UISelect make(UIContainer tofill, String ID,
119: String[] options, String[] labels, String valuebinding) {
120: return UISelect.make(tofill, ID, options, labels, valuebinding,
121: null);
122: }
123:
124: /**
125: * Constructs a single selection control, with labels distinct from the
126: * submitting values.
127: */
128:
129: public static UISelect make(UIContainer tofill, String ID,
130: String[] options, String[] labels, String valuebinding,
131: String initvalue) {
132: UISelect togo = make(tofill, ID, options, valuebinding,
133: initvalue);
134: if (labels != null) {
135: togo.optionnames = UIOutputMany.make(labels);
136: }
137: return togo;
138: }
139:
140: /**
141: * Constructs a multiple selection control, where the submitted values are
142: * identical with the rendered labels. Named differently to allow overload
143: * where the final parameter is null.
144: */
145: public static UISelect makeMultiple(UIContainer tofill, String ID,
146: String[] options, String valuebinding, String[] initvalue) {
147: UISelect togo = make(tofill, ID, options);
148: UIInputMany selection = UIInputMany.make(valuebinding);
149: if (initvalue != null) {
150: selection.setValue(initvalue);
151: }
152: togo.selection = selection;
153: return togo;
154: }
155:
156: /**
157: * Constructs a multiple selection control, with distinct submitted values and
158: * rendered labels.
159: */
160: public static UISelect makeMultiple(UIContainer tofill, String ID,
161: String[] options, String[] labels, String valuebinding,
162: String[] initvalue) {
163: UISelect togo = make(tofill, ID, options);
164: UIInputMany selection = UIInputMany.make(valuebinding);
165: if (initvalue != null) {
166: selection.setValue(initvalue);
167: }
168: if (labels != null) {
169: togo.optionnames = UIOutputMany.make(labels);
170: }
171: togo.selection = selection;
172: return togo;
173: }
174:
175: /** Sets the option labels for this selection control to be interpreted
176: * as message keys, rather than as raw Strings.
177: */
178: public UISelect setMessageKeys() {
179: optionnames.resolver = new ELReference("#{messageLocator}");
180: return this;
181: }
182:
183: }
|