Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added float value support to Slider2 fixing #976 #1005

Merged
merged 7 commits into from
Oct 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ public void encodeEnd(FacesContext context, UIComponent component) throws IOExce
}

/**
* Add script to enable the input mask. If the mask attribute starts with {@code {}} the value is expected to be a
* Add script to enable the input mask. If the mask attribute starts with {@code {} the value is expected to be a
* JSON object (and can for example be used to set a regular expression: {@code {regex:'[0-9\u0600-\u06FF]*'}}).
*
* See https://github.com/RobinHerbots/Inputmask.
Expand Down
44 changes: 32 additions & 12 deletions src/main/java/net/bootsfaces/component/slider2/Slider2Core.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,26 @@ public String toString() {
return ((this.toString != null) ? this.toString : super.toString());
}
}

/**
* Convert object to number. To be backwards compatible with bound integers to properties where we now also want
* to accept floats now.
*
* @param object Object to convert to number. Should be either a number or a string.
*
* @return Object converted to number.
*
* @throws IllegalArgumentException When an incorrect type is provided.
*/
private static Number toNumber(Object object) {
if (object instanceof Number) {
return (Number) object;
}
if (object instanceof String) {
return Float.valueOf((String) object);
}
throw new IllegalArgumentException("Use number or string");
}

/**
* Setting this flag updates the widget on every AJAX request. <P>
Expand Down Expand Up @@ -267,32 +287,32 @@ public void setLabelledBy(String _labelledBy) {
* The maximum value of the slider. (default 100) <P>
* @return Returns the value of the attribute, or 100, if it hasn't been set by the JSF file.
*/
public int getMax() {
return (int) (Integer) getStateHelper().eval(PropertyKeys.max, 100);
public Object getMax() {
return getStateHelper().eval(PropertyKeys.max, 100);
}

/**
* The maximum value of the slider. (default 100) <P>
* Usually this method is called internally by the JSF engine.
*/
public void setMax(int _max) {
getStateHelper().put(PropertyKeys.max, _max);
public void setMax(Object _max) {
getStateHelper().put(PropertyKeys.max, toNumber(_max));
}

/**
* The maximum value of the slider. (default 0) <P>
* @return Returns the value of the attribute, or 0, if it hasn't been set by the JSF file.
*/
public int getMin() {
return (int) (Integer) getStateHelper().eval(PropertyKeys.min, 0);
public Object getMin() {
return getStateHelper().eval(PropertyKeys.min, 0);
}

/**
* The maximum value of the slider. (default 0) <P>
* Usually this method is called internally by the JSF engine.
*/
public void setMin(int _min) {
getStateHelper().put(PropertyKeys.min, _min);
public void setMin(Object _min) {
getStateHelper().put(PropertyKeys.min, toNumber(_min));
}

/**
Expand Down Expand Up @@ -427,16 +447,16 @@ public void setSpan(int _span) {
* Increment step <P>
* @return Returns the value of the attribute, or 1, if it hasn't been set by the JSF file.
*/
public int getStep() {
return (int) (Integer) getStateHelper().eval(PropertyKeys.step, 1);
public Object getStep() {
return getStateHelper().eval(PropertyKeys.step, 1);
}

/**
* Increment step <P>
* Usually this method is called internally by the JSF engine.
*/
public void setStep(int _step) {
getStateHelper().put(PropertyKeys.step, _step);
public void setStep(Object _step) {
getStateHelper().put(PropertyKeys.step, toNumber(_step));
}

/**
Expand Down
85 changes: 52 additions & 33 deletions src/main/java/net/bootsfaces/component/slider2/Slider2Renderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,15 @@
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Map;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
//!//import javax.faces.convert.DoubleConverter;
import javax.faces.render.FacesRenderer;

import net.bootsfaces.component.ajax.AJAXRenderer;
import net.bootsfaces.component.badge.BadgeRenderer;
import net.bootsfaces.render.A;
import static net.bootsfaces.render.CoreRenderer.getRequestParameter;
import static net.bootsfaces.render.CoreRenderer.getValueType;
import net.bootsfaces.render.R;
import net.bootsfaces.render.Tooltip;
import net.bootsfaces.utils.BsfUtils;
Expand All @@ -57,26 +56,14 @@ public void decode(FacesContext context, UIComponent component) {
decodeBehaviors(context, slider);

String clientId = slider.getClientId(context);
String submittedValue = (String) context.getExternalContext().getRequestParameterMap().get(clientId);
Number submittedValue = convert(component, Float.valueOf(getRequestParameter(context, clientId)));

if (submittedValue != null) {
slider.setSubmittedValue(submittedValue);
}
new AJAXRenderer().decode(context, component, clientId);
}
/* !
@Override
public Object getConvertedValue(FacesContext fc, UIComponent c, Object sval) throws ConverterException {
Converter cnv = resolveConverter(fc, c);

if (cnv != null) {
return cnv.getAsObject(fc, c, (String) sval);
} else {
cnv = new DoubleConverter();
return cnv.getAsObject(fc, c, (String) sval);
}
}
*/
/**
* This methods generates the HTML code of the current b:slider2.
* @param context the FacesContext.
Expand All @@ -93,35 +80,67 @@ public void encodeBegin(FacesContext context, UIComponent component) throws IOEx
encodeHTML(slider, context, rw);
}

/**
* Returns converted value of the provided float value (to the type that is used on the component's value
* attribute).
*
* @param component Component to convert value for.
* @param value Float value to convert.
*
* @return Converted value of the provided float value (to the type that is used on the component's value
* attribute).
*/
private Number convert(UIComponent component, Float value) {
return convert((Class<? extends Number>) getValueType(component), value);
}

/**
* Returns converted value of the provided float value (to the provided type).
*
* @param type Type to convert float to. Currently only {@link Float} and {@link Integer} are supported.
* @param value Float value to convert.
*
* @return Converted value of the provided float value (to the provided type).
*
* @throws IllegalArgumentException If an unsupported type is provided.
*/
private Number convert(Class<? extends Number> type, Float value) {
if (int.class.isAssignableFrom(type) || Integer.class.isAssignableFrom(type)) {
return value.intValue();
}
if (float.class.isAssignableFrom(type) || Float.class.isAssignableFrom(type)) {
return value;
}
throw new IllegalArgumentException("Use integer or float");
}

private void encodeHTML(Slider2 slider, FacesContext context, ResponseWriter rw) throws IOException {
String clientId = slider.getClientId(context);

String mode = slider.getMode();
String label = slider.getLabel();
Class<? extends Number> type = (Class<? extends Number>) getValueType(slider);
if (type == null) {
type = Integer.class;
}

int min = slider.getMin();
int max = slider.getMax();
float min = ((Number) slider.getMin()).floatValue();
float max = ((Number) slider.getMax()).floatValue();
Object v = slider.getSubmittedValue();
if (v == null) {
v = slider.getValue();
}
if (v == null) {
v = slider.getValue();
slider.setValue(v);
}
if (v == null) {
v = max / 2;
slider.setValue(v);
v = min + (max - min) / 2;
}
//!//double val = A.toDouble(v);
int val = A.toInt(v);
Float val = A.toFloat(v);
if (val > max) {
val = max;
}
if (val < min) {
val = min;
}
//!//String valS = Double.toString(val);
slider.setValue(convert(type, val));
String o;
if (slider.getOrientation() != null) {
o = slider.getOrientation();
Expand Down Expand Up @@ -167,7 +186,7 @@ private void encodeHTML(Slider2 slider, FacesContext context, ResponseWriter rw)
rw.startElement("div", null);
rw.writeAttribute("class", "row", "class");
}
encodeInput(slider, rw, mode, context, val, clientId, isVertical, min, max);
encodeInput(slider, rw, mode, context, convert(type, val), clientId, isVertical, convert(type, min), convert(type, max));
if (!bottom) {
rw.endElement("div"); /* Row */

Expand Down Expand Up @@ -218,7 +237,7 @@ private void encodeHTML(Slider2 slider, FacesContext context, ResponseWriter rw)
rw.startElement("div", null);
rw.writeAttribute("class", "row", "class");

encodeInput(slider, rw, mode, context, val, clientId, isVertical, min, max);
encodeInput(slider, rw, mode, context, convert(type, val), clientId, isVertical, convert(type, min), convert(type, max));

encodeSliderInput(slider, rw, isVertical, span, clientId, val);
rw.endElement("div");/* Row */
Expand Down Expand Up @@ -246,8 +265,8 @@ private void encodeVLabel(Slider2 slider, ResponseWriter rw, String label) throw
rw.endElement("div"); // Column
}

private void encodeInput(Slider2 slider, ResponseWriter rw, String mode, FacesContext context, int val,
String clientId, boolean vo, int min, int max) throws IOException {
private void encodeInput(Slider2 slider, ResponseWriter rw, String mode, FacesContext context, Number val,
String clientId, boolean vo, Number min, Number max) throws IOException {
int cols = (vo ? 12 : slider.getBadgeSpan());
if (!mode.equals("basic")) {
/*
Expand All @@ -257,7 +276,7 @@ private void encodeInput(Slider2 slider, ResponseWriter rw, String mode, FacesCo
R.encodeColumn(rw, null, cols, cols, cols, cols, 0, 0, 0, 0, null, null);
if (mode.equals("badge")) {
generateBadge(context, slider, rw, clientId, slider.getBadgeStyleClass(), slider.getBadgeStyle(),
Integer.toString(val), "_badge");
val.toString(), "_badge");
}
}
removeMisleadingType(slider);
Expand Down Expand Up @@ -315,7 +334,7 @@ private void removeMisleadingType(Slider2 slider) {

}

private void encodeSliderInput(Slider2 slider, ResponseWriter rw, boolean vo, int span, String clientId, int val)
private void encodeSliderInput(Slider2 slider, ResponseWriter rw, boolean vo, int span, String clientId, float val)
throws IOException {
int cols = span;
if (!slider.getMode().equals("basic")) {
Expand Down
40 changes: 38 additions & 2 deletions src/main/java/net/bootsfaces/render/CoreRenderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Map;

import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.application.ProjectStage;
Expand All @@ -37,7 +36,6 @@
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.render.Renderer;

import net.bootsfaces.beans.ELTools;
import net.bootsfaces.component.ajax.AJAXRenderer;
import net.bootsfaces.component.form.Form;
Expand Down Expand Up @@ -566,7 +564,45 @@ protected Converter resolveConverter(FacesContext context, UIComponent c, Object
return null;
}
}

/**
* Returns request parameter value for the provided parameter name.
*
* @param context Faces context.
* @param name Parameter name to get value for.
*
* @return Request parameter value for the provided parameter name.
*/
public static String getRequestParameter(FacesContext context, String name) {
return context.getExternalContext().getRequestParameterMap().get(name);
}

/**
* Returns type of the value attribute's {@link ValueExpression} of the provided component.
*
* @param component Component to get attribute type for.
*
* @return Type of the value attribute's {@link ValueExpression} of the provided component.
*/
public static Class<?> getValueType(UIComponent component) {
return getAttributeType(component, "value");
}

/**
* Returns type of the provided attribute name's {@link ValueExpression} of the provided component.
*
* @param component Component to get attribute type for.
* @param attribute Attribute to get type for.
*
* @return Type of the provided attribute name's {@link ValueExpression} of the provided component.
*/
public static Class<?> getAttributeType(UIComponent component, String attribute) {
ValueExpression valueExpression = component.getValueExpression(attribute);
return valueExpression == null
? null
: valueExpression.getType(FacesContext.getCurrentInstance().getELContext());
}

public static void endDisabledFieldset(IContentDisabled component, ResponseWriter rw) throws IOException {
if (component.isContentDisabled()) {
rw.endElement("fieldset");
Expand Down
6 changes: 3 additions & 3 deletions src/main/meta/META-INF/bootsfaces-b.taglib.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25611,13 +25611,13 @@
<description><![CDATA[The maximum value of the slider. (default 100)]]></description>
<name>max</name>
<required>false</required>
<type>java.lang.Integer</type>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[The maximum value of the slider. (default 0)]]></description>
<name>min</name>
<required>false</required>
<type>java.lang.Integer</type>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[Mode of the Slider Widget. There are three modes available : badge, edit and basic. In basic mode, only the slider and the label(if present) will be shown and the slider value will be hidden. In badge mode, the default, the slider value will be shown in a badge. In edit mode, an editable input field showing the slider value will be shown; in this mode you can change the value by sliding or editing the value in the field.]]></description>
Expand Down Expand Up @@ -25677,7 +25677,7 @@
<description><![CDATA[Increment step]]></description>
<name>step</name>
<required>false</required>
<type>java.lang.Integer</type>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[Inline style of the entire slider.]]></description>
Expand Down
6 changes: 3 additions & 3 deletions xtext/BootsFaces.jsfdsl
Original file line number Diff line number Diff line change
Expand Up @@ -2211,8 +2211,8 @@ widget slider2
label-style "The CSS inline style of the label."
label-style-class "The CSS class of the label."
labelled-by "Labels for the slider handle's, Use array for multiple values in a range slider."
max Integer default "100" "The maximum value of the slider. (default 100)"
min Integer default "0" "The maximum value of the slider. (default 0)"
max Object default "100" "The maximum value of the slider. (default 100)"
min Object default "0" "The maximum value of the slider. (default 0)"
mode default "badge" "Mode of the Slider Widget. There are three modes available : badge, edit and basic. In basic mode, only the slider and the label(if present) will be shown and the slider value will be hidden. In badge mode, the default, the slider value will be shown in a badge. In edit mode, an editable input field showing the slider value will be shown; in this mode you can change the value by sliding or editing the value in the field."
natural_arrow_keys Boolean default "false" "The natural order is used for the arrow keys. Arrow up select the upper slider value for vertical sliders, arrow right the righter slider value for a horizontal slider - no matter if the slider was reversed or not. By default the arrow keys are oriented by arrow up/right to the higher slider value, arrow down/left to the lower slider value."
orientation default "horizontal" "Set the orientation. Accepts 'vertical' or 'horizontal'"
Expand All @@ -2222,7 +2222,7 @@ widget slider2
scale default "linear" "Set to 'logarithmic' to use a logarithmic scale."
selection default "before" "Selection placement. Accepts: 'before', 'after' or 'none'. In case of a range slider, the selection will be placed between the handles."
span Integer default "12" "The column span of the slider."
step Integer default "1" "Increment step"
step Object default "1" "Increment step"
tooltip-visibility default "show" "Whether to show the tooltip on drag, hide the tooltip, or always show the tooltip. Accepts: 'show', 'hide', or 'always'."
tooltip-split Boolean default "false" "If false show one tootip if true show two tooltips one for each handler."
tooltip-slider-position "Position of tooltip, relative to slider. Accepts 'top'/'bottom' for horizontal sliders and 'left'/'right' for vertically orientated sliders. Default positions are 'top' for horizontal and 'right' for vertical slider."
Expand Down