1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.myfaces.tobago.internal.renderkit.renderer;
21
22 import org.apache.myfaces.tobago.context.Markup;
23 import org.apache.myfaces.tobago.internal.component.AbstractUISelectManyShuttle;
24 import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
25 import org.apache.myfaces.tobago.internal.util.SelectItemUtils;
26 import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
27 import org.apache.myfaces.tobago.renderkit.css.Icons;
28 import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
29 import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
30 import org.apache.myfaces.tobago.renderkit.html.HtmlButtonTypes;
31 import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
32 import org.apache.myfaces.tobago.util.ComponentUtils;
33 import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
34
35 import javax.faces.component.UIComponent;
36 import javax.faces.context.FacesContext;
37 import javax.faces.model.SelectItem;
38 import java.io.IOException;
39 import java.util.List;
40
41 public class SelectManyShuttleRenderer<T extends AbstractUISelectManyShuttle> extends SelectManyRendererBase<T> {
42
43 @Override
44 public HtmlElements getComponentTag() {
45 return HtmlElements.TOBAGO_SELECT_MANY_SHUTTLE;
46 }
47
48 @Override
49 public void encodeBeginField(final FacesContext facesContext, final T component) throws IOException {
50
51 final TobagoResponseWriter writer = getResponseWriter(facesContext);
52 final String clientId = component.getClientId(facesContext);
53 final Markup markup = component.getMarkup();
54
55 writer.startElement(HtmlElements.DIV);
56 writer.writeClassAttribute(
57 TobagoClass.SELECT_MANY_SHUTTLE,
58 TobagoClass.SELECT_MANY_SHUTTLE.createMarkup(markup),
59 component.getCustomClass(),
60 markup != null && markup.contains(Markup.SPREAD) ? TobagoClass.SPREAD : null);
61 HtmlRendererUtils.writeDataAttributes(facesContext, writer, component);
62 final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, component);
63 if (title != null) {
64 writer.writeAttribute(HtmlAttributes.TITLE, title, true);
65 }
66
67 final List<SelectItem> items = SelectItemUtils.getItemList(facesContext, component);
68 final boolean disabled = !items.iterator().hasNext() || component.isDisabled();
69 final boolean readonly = component.isReadonly();
70
71 final String unselectedLabel = component.getUnselectedLabel();
72 if (unselectedLabel != null) {
73 writer.startElement(HtmlElements.DIV);
74 writer.writeClassAttribute(TobagoClass.SELECT_MANY_SHUTTLE__UNSELECTED_LABEL);
75 writer.write(unselectedLabel);
76 writer.endElement(HtmlElements.DIV);
77 }
78 Integer size = component.getSize();
79 size = Math.max(size != null ? size : items.size(), 2);
80
81 writer.startElement(HtmlElements.SELECT);
82 final String unselectedClientId = clientId + ComponentUtils.SUB_SEPARATOR + "unselected";
83 writer.writeIdAttribute(unselectedClientId);
84 writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
85 writer.writeAttribute(HtmlAttributes.READONLY, readonly);
86
87
88 writer.writeAttribute(HtmlAttributes.TABINDEX, component.getTabIndex());
89
90 writer.writeClassAttribute(TobagoClass.SELECT_MANY_SHUTTLE__UNSELECTED, BootstrapClass.FORM_CONTROL);
91
92 writer.writeAttribute(HtmlAttributes.MULTIPLE, true);
93 writer.writeAttribute(HtmlAttributes.SIZE, size);
94
95 final Object[] values = component.getSelectedValues();
96 final String[] submittedValues = getSubmittedValues(component);
97 HtmlRendererUtils.renderSelectItems(
98 component, TobagoClass.SELECT_MANY_SHUTTLE__OPTION, items, values, submittedValues, false, writer,
99 facesContext);
100
101 writer.endElement(HtmlElements.SELECT);
102 writer.startElement(HtmlElements.DIV);
103 writer.writeClassAttribute(TobagoClass.SELECT_MANY_SHUTTLE__TOOL_BAR, BootstrapClass.BTN_GROUP_VERTICAL);
104 createButton(facesContext, component, writer, disabled | readonly,
105 Icons.ANGLE_DOUBLE_RIGHT, "addAll", TobagoClass.SELECT_MANY_SHUTTLE__ADD_ALL);
106 createButton(facesContext, component, writer, disabled | readonly,
107 Icons.ANGLE_RIGHT, "add", TobagoClass.SELECT_MANY_SHUTTLE__ADD);
108 createButton(facesContext, component, writer, disabled | readonly,
109 Icons.ANGLE_LEFT, "remove", TobagoClass.SELECT_MANY_SHUTTLE__REMOVE);
110 createButton(facesContext, component, writer, disabled | readonly,
111 Icons.ANGLE_DOUBLE_LEFT, "removeAll", TobagoClass.SELECT_MANY_SHUTTLE__REMOVE_ALL);
112 writer.endElement(HtmlElements.DIV);
113 final String selectedLabel = component.getSelectedLabel();
114 if (selectedLabel != null) {
115 writer.startElement(HtmlElements.DIV);
116 writer.writeClassAttribute(TobagoClass.SELECT_MANY_SHUTTLE__SELECTED_LABEL);
117 writer.write(selectedLabel);
118 writer.endElement(HtmlElements.DIV);
119 }
120
121 writer.startElement(HtmlElements.SELECT);
122 final String selectedClientId = clientId + ComponentUtils.SUB_SEPARATOR + "selected";
123 writer.writeIdAttribute(selectedClientId);
124
125 writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
126 writer.writeAttribute(HtmlAttributes.READONLY, readonly);
127 writer.writeAttribute(HtmlAttributes.TABINDEX, component.getTabIndex());
128 writer.writeClassAttribute(
129 TobagoClass.SELECT_MANY_SHUTTLE__SELECTED,
130 BootstrapClass.borderColor(ComponentUtils.getMaximumSeverity(component)),
131 BootstrapClass.FORM_CONTROL);
132 writer.writeAttribute(HtmlAttributes.MULTIPLE, true);
133 writer.writeAttribute(HtmlAttributes.SIZE, size);
134 HtmlRendererUtils.renderSelectItems(
135 component, TobagoClass.SELECT_MANY_SHUTTLE__OPTION, items, values, submittedValues, true, writer,
136 facesContext);
137
138 writer.endElement(HtmlElements.SELECT);
139 writer.startElement(HtmlElements.SELECT);
140 writer.writeClassAttribute(TobagoClass.SELECT_MANY_SHUTTLE__HIDDEN);
141 final String hiddenClientId = clientId + ComponentUtils.SUB_SEPARATOR + "hidden";
142 writer.writeIdAttribute(hiddenClientId);
143 writer.writeNameAttribute(clientId);
144 writer.writeAttribute(HtmlAttributes.MULTIPLE, true);
145 writer.writeAttribute(HtmlAttributes.REQUIRED, component.isRequired());
146 HtmlRendererUtils.renderSelectItems(
147 component, TobagoClass.SELECT_MANY_SHUTTLE__OPTION, items, values, submittedValues, writer, facesContext);
148 writer.endElement(HtmlElements.SELECT);
149 }
150
151 @Override
152 public void encodeEndField(final FacesContext facesContext, final T component) throws IOException {
153 final TobagoResponseWriter writer = getResponseWriter(facesContext);
154 writer.endElement(HtmlElements.DIV);
155
156 encodeBehavior(writer, facesContext, component);
157 }
158
159 private void createButton(
160 final FacesContext context, final UIComponent component, final TobagoResponseWriter writer,
161 final boolean disabled, final Icons icon, final String sub, final TobagoClass cssClass) throws IOException {
162 writer.startElement(HtmlElements.BUTTON);
163 writer.writeAttribute(HtmlAttributes.TYPE, HtmlButtonTypes.BUTTON);
164 writer.writeClassAttribute(cssClass, BootstrapClass.BTN, BootstrapClass.BTN_SECONDARY);
165 writer.writeIdAttribute(component.getClientId(context) + ComponentUtils.SUB_SEPARATOR + sub);
166 writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
167 writer.startElement(HtmlElements.I);
168 writer.writeClassAttribute(Icons.FA, icon);
169 writer.endElement(HtmlElements.I);
170 writer.endElement(HtmlElements.BUTTON);
171 }
172
173 @Override
174 protected String getFieldId(final FacesContext facesContext, final T component) {
175 return component.getClientId(facesContext) + ComponentUtils.SUB_SEPARATOR + "unselected";
176 }
177 }