001/**
002 * Copyright 2005-2018 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.krad.uif.element;
017
018import org.kuali.rice.krad.datadictionary.parse.BeanTag;
019import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
020import org.kuali.rice.krad.datadictionary.parse.BeanTags;
021import org.kuali.rice.krad.uif.CssConstants;
022import org.kuali.rice.krad.uif.UifConstants;
023import org.kuali.rice.krad.uif.util.LifecycleElement;
024
025import java.util.ArrayList;
026import java.util.List;
027
028/**
029 * Element which shows a visual progress bar based on percentageValue passed in or segmentPercentages passed in
030 *
031 * @author Kuali Rice Team (rice.collab@kuali.org)
032 */
033@BeanTags({@BeanTag(name = "progressBar-bean", parent = "Uif-ProgressBar"),
034        @BeanTag(name = "progressBarVertical-bean", parent = "Uif-ProgressBar-Vertical")})
035public class ProgressBar extends ContentElementBase {
036    private static final long serialVersionUID = -2643777398164666573L;
037
038    private Integer percentComplete;
039
040    private List<Integer> segmentPercentages;
041    private List<String> segmentSizes;
042    private List<String> segmentClasses;
043
044    private boolean vertical;
045
046    public ProgressBar() {
047        segmentSizes = new ArrayList<String>();
048        segmentClasses = new ArrayList<String>();
049        this.setRole(UifConstants.AriaRoles.PROGRESS_BAR);
050    }
051
052    /**
053     * Sets the appropriate classes and bar widths based on values in percentComplete or segmentPercentages
054     *
055     * {@inheritDoc}
056     */
057    @Override
058    public void performFinalize(Object model, LifecycleElement parent) {
059        super.performFinalize(model, parent);
060
061        // Css property used by bars based on vertical flag (width or height)
062        String cssDimension = CssConstants.WIDTH;
063        if (vertical) {
064            cssDimension = CssConstants.HEIGHT;
065        }
066
067        boolean explicitlySetSizes = segmentPercentages != null && !getSegmentPercentages().isEmpty();
068
069        // Simply use the percentage if set, and no explicitly set sizes (use those instead if set)
070        if (!explicitlySetSizes && percentComplete != null) {
071            segmentClasses = new ArrayList<String>();
072
073            // Add appropriate style string based on dimension and percentage
074            segmentSizes.add(cssDimension + percentComplete + "%");
075            segmentClasses.add(
076                    CssConstants.ProgressBar.PROGRESS_BAR + " " + CssConstants.ProgressBar.SUCCESS_PROGRESS_BAR);
077
078            this.setTitle(percentComplete.toString() + "%");
079
080            // Set aria attributes
081            this.addAriaAttribute(UifConstants.AriaAttributes.VALUE_MIN, "0");
082            this.addAriaAttribute(UifConstants.AriaAttributes.VALUE_MAX, "100");
083            this.addAriaAttribute(UifConstants.AriaAttributes.VALUE_NOW, percentComplete.toString());
084        } else if (explicitlySetSizes && !(this instanceof StepProgressBar)) {
085            if (segmentClasses == null || segmentClasses.size() != segmentPercentages.size()) {
086                throw new RuntimeException(
087                        "If segmentPercentages are set on a base ProgressBar type, segmentClasses must "
088                                + "also be explicitly set and contain the same number of items");
089            }
090
091            // Add appropriate style string based on dimension and percentage
092            percentComplete = 0;
093            for (int index = 0; index < segmentPercentages.size(); index++) {
094                segmentSizes.add(cssDimension + segmentPercentages.get(index) + "%");
095                percentComplete = percentComplete + segmentPercentages.get(index);
096            }
097
098            // Set aria attributes
099            this.addAriaAttribute(UifConstants.AriaAttributes.VALUE_MIN, "0");
100            this.addAriaAttribute(UifConstants.AriaAttributes.VALUE_MAX, "100");
101            this.addAriaAttribute(UifConstants.AriaAttributes.VALUE_NOW, percentComplete.toString());
102        }
103
104    }
105
106    /**
107     * Percent value complete used to visually indicate this ProgressBar's completeness
108     *
109     * @return the Integer value representing perecent complete for this ProgressBar
110     */
111    @BeanTagAttribute(name = "percentComplete")
112    public Integer getPercentComplete() {
113        return percentComplete;
114    }
115
116    /**
117     * @see ProgressBar#getPercentComplete()
118     */
119    public void setPercentComplete(Integer percentComplete) {
120        this.percentComplete = percentComplete;
121    }
122
123    /**
124     * List of bar classes to use for each bar "section" for coloring or styling purposes, only settable for
125     * full configuration purposes and should not normally be set
126     *
127     * <p>These are normally set automatically by the framework, but can be explicitly defined if segmentPercentages
128     * are also explicitly set.  When setting segmentClasses, it's list size MUST equal segmentPercentages.</p>
129     *
130     * @return the list of bar classes
131     */
132    @BeanTagAttribute(name = "segmentClasses", type = BeanTagAttribute.AttributeType.LISTVALUE)
133    public List<String> getSegmentClasses() {
134        return segmentClasses;
135    }
136
137    /**
138     * @see org.kuali.rice.krad.uif.element.ProgressBar#getSegmentClasses()
139     */
140    public void setSegmentClasses(List<String> segmentClasses) {
141        this.segmentClasses = segmentClasses;
142    }
143
144    /**
145     * The percentage each bar "section" will take up on the progress bar, only settable for
146     * full configuration purposes and should not normally be set
147     *
148     * <p>This is normally automatically set by the framework with no additional configuration.
149     * When explicitly set for ProgressBars, barClases should ALSO be set
150     * (this however is optional for StepProgressBars).
151     * The percentages effects how much space each section will take up on the bar and the total should not
152     * exceed 100.  For StepProgressBars, this list's size must equal the number of steps.</p>
153     *
154     * @return the bar percentages to use
155     */
156    @BeanTagAttribute(name = "segmentPercentages", type = BeanTagAttribute.AttributeType.LISTVALUE)
157    public List<Integer> getSegmentPercentages() {
158        return segmentPercentages;
159    }
160
161    /**
162     * @see org.kuali.rice.krad.uif.element.ProgressBar#getSegmentPercentages()
163     */
164    public void setSegmentPercentages(List<String> segmentPercentages) {
165        // Note: This is purposely taking in a list of String to make bean configuration easier
166        if (this.segmentPercentages == null) {
167            this.segmentPercentages = new ArrayList<Integer>();
168        }
169
170        for (String percentage : segmentPercentages) {
171            this.segmentPercentages.add(new Integer(percentage));
172        }
173    }
174
175    /**
176     * The bar sizes as String css style properties (ie, "width: 20%") in a list, framework only,
177     * not settable.
178     *
179     * @return the bar sizes as String css style properties
180     */
181    public List<String> getSegmentSizes() {
182        return segmentSizes;
183    }
184
185    /**
186     * True if this ProgressBar should render vertical (this requires a defined height - which by default is
187     * defined in the css, or by the framework for StepProgressBars), false otherwise
188     *
189     * @return true if this
190     */
191    @BeanTagAttribute(name = "vertical")
192    public boolean isVertical() {
193        return vertical;
194    }
195
196    /**
197     * @see ProgressBar#isVertical()
198     */
199    public void setVertical(boolean vertical) {
200        this.vertical = vertical;
201    }
202
203}