001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.extensions.markup.html.form.palette.component; 018 019import java.util.Iterator; 020import java.util.Map; 021 022import org.apache.wicket.extensions.markup.html.form.palette.Palette; 023import org.apache.wicket.markup.ComponentTag; 024import org.apache.wicket.markup.MarkupStream; 025import org.apache.wicket.markup.head.IHeaderResponse; 026import org.apache.wicket.markup.head.OnDomReadyHeaderItem; 027import org.apache.wicket.markup.html.form.FormComponent; 028import org.apache.wicket.markup.html.form.IChoiceRenderer; 029import org.apache.wicket.util.convert.IConverter; 030import org.apache.wicket.util.string.Strings; 031import org.apache.wicket.util.value.IValueMap; 032 033 034/** 035 * Generates html option elements based on iterator specified by getOptionsIterator() and 036 * IChoiceRender specified by the palette 037 * 038 * @param <T> 039 * @author Igor Vaynberg ( ivaynberg ) 040 */ 041public abstract class AbstractOptions<T> extends FormComponent<T> 042{ 043 private static final long serialVersionUID = 1L; 044 045 private final Palette<T> palette; 046 047 protected Palette<T> getPalette() 048 { 049 return palette; 050 } 051 052 /** 053 * @param id 054 * component id 055 * @param palette 056 * parent palette 057 */ 058 public AbstractOptions(final String id, final Palette<T> palette) 059 { 060 super(id); 061 this.palette = palette; 062 setOutputMarkupId(true); 063 } 064 065 protected abstract Iterator<T> getOptionsIterator(); 066 067 /** 068 * {@inheritDoc} 069 */ 070 @Override 071 public void onComponentTagBody(final MarkupStream markupStream, final ComponentTag openTag) 072 { 073 StringBuilder buffer = new StringBuilder(128); 074 Iterator<T> options = getOptionsIterator(); 075 IChoiceRenderer<? super T> renderer = getPalette().getChoiceRenderer(); 076 077 boolean localizeDisplayValues = localizeDisplayValues(); 078 079 while (options.hasNext()) 080 { 081 final T choice = options.next(); 082 083 final CharSequence id; 084 { 085 String value = renderer.getIdValue(choice, 0); 086 087 if (getEscapeModelStrings()) 088 { 089 id = Strings.escapeMarkup(value); 090 } 091 else 092 { 093 id = value; 094 } 095 } 096 097 final CharSequence value; 098 { 099 Object displayValue = renderer.getDisplayValue(choice); 100 Class<?> displayClass = displayValue == null ? null : displayValue.getClass(); 101 102 @SuppressWarnings("unchecked") 103 IConverter<Object> converter = (IConverter<Object>)getConverter(displayClass); 104 String displayString = converter.convertToString(displayValue, getLocale()); 105 if (localizeDisplayValues) 106 { 107 displayString = getLocalizer().getString(displayString, this, displayString); 108 } 109 110 if (getEscapeModelStrings()) 111 { 112 value = Strings.escapeMarkup(displayString); 113 } 114 else 115 { 116 value = displayString; 117 } 118 } 119 120 buffer.append("\n<option value=\"").append(id).append("\""); 121 122 Map<String, String> additionalAttributesMap = getAdditionalAttributes(choice); 123 if (additionalAttributesMap != null) 124 { 125 for (Map.Entry<String, String> entry : additionalAttributesMap.entrySet()) 126 { 127 buffer.append(' ') 128 .append(entry.getKey()) 129 .append("=\"") 130 .append(entry.getValue()) 131 .append("\""); 132 } 133 } 134 135 buffer.append(">").append(value).append("</option>"); 136 } 137 138 buffer.append("\n"); 139 140 replaceComponentTagBody(markupStream, openTag, buffer); 141 } 142 143 /** 144 * Should display values be localized. 145 * 146 * @return default {@code true} 147 */ 148 protected boolean localizeDisplayValues() 149 { 150 return true; 151 } 152 153 /** 154 * @param choice 155 * @return map of attribute/value pairs (String/String) 156 */ 157 protected Map<String, String> getAdditionalAttributes(final T choice) 158 { 159 return null; 160 } 161 162 /** 163 * {@inheritDoc} 164 */ 165 @Override 166 protected void onComponentTag(final ComponentTag tag) 167 { 168 checkComponentTag(tag, "select"); 169 170 super.onComponentTag(tag); 171 IValueMap attrs = tag.getAttributes(); 172 173 attrs.put("multiple", "multiple"); 174 attrs.put("size", getPalette().getRows()); 175 176 if (!palette.isPaletteEnabled()) 177 { 178 attrs.put("disabled", "disabled"); 179 } 180 } 181 182 @Override 183 public void renderHead(IHeaderResponse response) 184 { 185 super.renderHead(response); 186 187 // A piece of javascript to avoid serializing the options during AJAX serialization. 188 response.render(OnDomReadyHeaderItem.forScript( 189 "if (typeof(Wicket) != \"undefined\" && typeof(Wicket.Form) != \"undefined\")" 190 + " Wicket.Form.excludeFromAjaxSerialization." + getMarkupId() + "='true';")); 191 } 192 193 /** 194 * {@inheritDoc} 195 */ 196 @Override 197 public void updateModel() 198 { 199 } 200 201 /** 202 * {@inheritDoc} 203 */ 204 @Override 205 protected String getModelValue() 206 { 207 return null; 208 } 209}