    001// Copyright 2008-2024 The Apache Software Foundation
    002//
    003// Licensed under the Apache License, Version 2.0 (the "License");
    004// you may not use this file except in compliance with the License.
    005// You may obtain a copy of the License at
    006//
    007//     http://www.apache.org/licenses/LICENSE-2.0
    008//
    009// Unless required by applicable law or agreed to in writing, software
    010// distributed under the License is distributed on an "AS IS" BASIS,
    011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    012// See the License for the specific language governing permissions and
    013// limitations under the License.
    014
    015package org.apache.tapestry5.internal.util;
    016
    017import org.apache.tapestry5.*;
    018
    019import java.util.Map;
    020
    021public class SelectModelRenderer implements SelectModelVisitor
    022{
    023    private final MarkupWriter writer;
    024
    025    private final ValueEncoder encoder;
    026
    027    private final boolean raw;
    028
    029    private int optgroupIdx = -1;
    030    private boolean inOptgroup = false;
    031
    032    public SelectModelRenderer(final MarkupWriter writer, ValueEncoder encoder, boolean raw)
    033    {
    034        this.writer = writer;
    035        this.encoder = encoder;
    036        this.raw = raw;
    037    }
    038
    039    @Override
    040    public void beginOptionGroup(OptionGroupModel groupModel)
    041    {
    042        this.optgroupIdx++;
    043        this.inOptgroup = true;
    044        this.writer.element("optgroup", "label", groupModel.getLabel());
    045
    046        writeDisabled(groupModel.isDisabled());
    047        writeAttributes(groupModel.getAttributes());
    048    }
    049
    050    @Override
    051    public void endOptionGroup(OptionGroupModel groupModel)
    052    {
    053        this.inOptgroup = false;
    054        this.writer.end(); // select
    055    }
    056
    057    @Override
    058    @SuppressWarnings("unchecked")
    059    public void option(OptionModel optionModel)
    060    {
    061        Object optionValue = optionModel.getValue();
    062
    063        String clientValue = this.encoder.toClient(optionValue);
    064
    065        this.writer.element("option", "value", clientValue);
    066
    067        if (this.inOptgroup && this.optgroupIdx > -1)
    068        {
    069            this.writer.attributes("data-optgroup-idx", this.optgroupIdx);
    070        }
    071
    072        if (isOptionSelected(optionModel, clientValue))
    073        {
    074            this.writer.attributes("selected", "selected");
    075        }
    076
    077        writeDisabled(optionModel.isDisabled());
    078        writeAttributes(optionModel.getAttributes());
    079
    080
    081        if (this.raw)
    082        {
    083            this.writer.writeRaw(optionModel.getLabel());
    084        } else
    085        {
    086            this.writer.write(optionModel.getLabel());
    087        }
    088
    089        this.writer.end();
    090    }
    091
    092    private void writeDisabled(boolean disabled)
    093    {
    094        if (disabled)
    095        {
    096            this.writer.attributes("disabled", "disabled");
    097        }
    098    }
    099
    100    private void writeAttributes(Map<String, String> attributes)
    101    {
    102        if (attributes == null)
    103        {
    104            return;
    105        }
    106
    107        for (Map.Entry<String, String> e : attributes.entrySet())
    108        {
    109            this.writer.attributes(e.getKey(), e.getValue());
    110        }
    111    }
    112
    113    /**
    114     * If true, then the selected attribute will be written. This implementation always returns false.
    115     */
    116    protected boolean isOptionSelected(OptionModel optionModel, String clientValue)
    117    {
    118        return false;
    119    }
    120
    121}