/* * Copyright (C) 2014 Civilian Framework. * * Licensed under the Civilian License (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.civilian-framework.org/license.txt * * 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.civilian.form; import org.civilian.template.HtmlUtil; import org.civilian.template.TemplateWriter; import org.civilian.text.keys.KeyList; import org.civilian.util.Check; /** * Select represents a HTML select element. * It is backed by a KeyList which defines the options of the select * element. */ public class Select<T> extends Control<T> { private static final byte FLAG_CHECK_REQUEST_VALUE = (byte)1; private static final byte FLAG_USE_OPTION_GROUPS = (byte)2; /** * Creates the Select. * @param name the field name * @param keyList the keylist which backs the select options */ public Select(String name, KeyList<T> keyList) { super(Check.notNull(keyList, "keyList").getType(), name); keyList_ = keyList; } /** * Returns the KeyList passed to the Select constructor. */ public KeyList<T> getKeyList() { return keyList_; } /** * Returns the text corresponding to the selected value within the KeyList of the field. */ public String getSelectedText() { return keyList_.getText(getValue()); } /** * Returns the index corresponding to the selected value within the KeyList of the field. */ public int getSelectedIndex() { return keyList_.indexOf(getValue()); } /** * Returns the value of the size attribute which determines the number of displayed rows. */ @Override public int getRows() { return rows_; } /** * Sets the size of the select field which determines the number of displayed rows. */ public Select<T> setRows(int rows) { rows_ = rows; return this; } private boolean getFlag(byte f) { return (flags_ & f) > 0; } private Select<T> setFlag(byte f, boolean on) { if (on) flags_ |= f; else flags_ &= ~f; return this; } /** * Returns if the Select prints out option groups. * If true, then every item in the KeyList with a null value * is interpreted as option group, instead of a normal key entry. * The default is not to use option groups. */ public boolean useOptionGroups() { return getFlag(FLAG_USE_OPTION_GROUPS); } /** * Sets if the select uses option groups. */ public Select<T> setUseOptionGroups(boolean on) { return setFlag(FLAG_USE_OPTION_GROUPS, on); } public Select<T> setDefaultOption() { return setDefaultOption("", null); } public Select<T> setDefaultOption(String text, T key) { defaultKey_ = key; defaultText_ = text; return this; } public Select<T> removeDefaultOption() { return setDefaultOption(null, null); } /** * Prints the field markup. */ @Override public void print(TemplateWriter out, String... attrs) { start(out, attrs); out.increaseTab(); printDefaultOption(out); printOptions(out); out.decreaseTab(); end(out); } /** * Prints the start tag of the select element. */ public void start(TemplateWriter out) { start(out, (String[])null); } /** * Prints the start tag of the select element. */ public void start(TemplateWriter out, String... attrs) { out.print("<select"); HtmlUtil.attr(out, "name", getName()); if (rows_ > 1) HtmlUtil.attr(out, "size", rows_); if (isReadOnly()) out.print(" readonly"); if (isDisabled()) out.print(" disabled"); if (isRequired()) out.print(" required"); printAttrs(out, attrs); out.println(">"); } /** * Prints the end tag of the select element. */ public void end(TemplateWriter out) { out.print("</select>"); } /** * Prints the option list of the select elements. */ public void printOptions(TemplateWriter out) { int keySize = keyList_.size(); boolean useOptionGroups = useOptionGroups(); boolean isInGroup = false; for (int i=0; i<keySize; i++) { if ((keyList_.getValue(i) == null) && useOptionGroups) { if (isInGroup) printGroupEnd(out); isInGroup = true; printGroupStart(out, keyList_.getText(i)); } else printOption(out, i); } if (isInGroup) printGroupEnd(out); } /** * Prints a single option in the select field's option list * @param value the option value * @param text the option text * @param selected is the option selected? */ public void printOption(TemplateWriter out, T value, String text, boolean selected) { String s = formatValue(value); printOptionImpl(out, s, text, selected); } /** * Prints a single option. */ public void printOption(TemplateWriter out, int i) { T value = keyList_.getValue(i); String svalue = keyList_.getType().format(value, i); String text = keyList_.getText(i); boolean selected = equals(value, getValue()); printOptionImpl(out, svalue, text, selected); } private void printOptionImpl(TemplateWriter out, String value, String text, boolean selected) { out.print("<option"); HtmlUtil.attr(out, "value", value); if (selected) out.print(" selected"); out.print(">"); out.print(text); out.println("</option>"); } public void printDefaultOption(TemplateWriter out) { if (defaultText_ != null) printOption(out, defaultKey_, defaultText_, false); } public void printGroupStart(TemplateWriter out, String label) { out.print("<optgroup"); HtmlUtil.attr(out, "label", label); out.println(">"); out.decreaseTab(); } public void printGroupEnd(TemplateWriter out) { out.decreaseTab(); out.print("</optgroup>"); } /** * Returns this. */ @Override public Control<T> toFocusControl() { return this; } private KeyList<T> keyList_; private int rows_; private T defaultKey_; private byte flags_ = FLAG_CHECK_REQUEST_VALUE; private String defaultText_ = ""; // by default the Select has a default option }