123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423 |
- /*
- * Copyright 2000-2018 Vaadin Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
- package com.vaadin.ui;
-
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Objects;
- import java.util.StringTokenizer;
-
- import org.jsoup.nodes.Attributes;
- import org.jsoup.nodes.Element;
-
- import com.vaadin.event.FieldEvents;
- import com.vaadin.event.FieldEvents.BlurEvent;
- import com.vaadin.event.FieldEvents.BlurListener;
- import com.vaadin.event.FieldEvents.FocusAndBlurServerRpcDecorator;
- import com.vaadin.event.FieldEvents.FocusEvent;
- import com.vaadin.event.FieldEvents.FocusListener;
- import com.vaadin.shared.MouseEventDetails;
- import com.vaadin.shared.Registration;
- import com.vaadin.shared.ui.ComponentStateUtil;
- import com.vaadin.shared.ui.checkbox.CheckBoxServerRpc;
- import com.vaadin.shared.ui.checkbox.CheckBoxState;
- import com.vaadin.ui.declarative.DesignAttributeHandler;
- import com.vaadin.ui.declarative.DesignContext;
-
- public class CheckBox extends AbstractField<Boolean>
- implements FieldEvents.BlurNotifier, FieldEvents.FocusNotifier {
-
- private CheckBoxServerRpc rpc = (boolean checked,
- MouseEventDetails mouseEventDetails) -> {
- if (isReadOnly()) {
- return;
- }
-
- /*
- * Client side updates the state before sending the event so we need to
- * make sure the cached state is updated to match the client. If we do
- * not do this, a reverting setValue() call in a listener will not cause
- * the new state to be sent to the client.
- *
- * See #11028, #10030.
- */
- getUI().getConnectorTracker().getDiffState(CheckBox.this).put("checked",
- checked);
-
- final Boolean oldValue = getValue();
- final Boolean newValue = checked;
-
- if (!newValue.equals(oldValue)) {
- // The event is only sent if the switch state is changed
- setValue(newValue, true);
- }
- };
-
- private CheckBoxInputElement checkBoxInputElement = null;
- private CheckBoxLabelElement checkBoxLabelElement = null;
-
- /**
- * The inner input element of the CheckBox.
- */
- public static class CheckBoxInputElement implements HasStyleNames {
-
- private final CheckBox checkBox;
-
- private CheckBoxInputElement(CheckBox checkBox) {
- this.checkBox = checkBox;
- }
-
- @Override
- // Implementation copied from AbstractComponent
- public String getStyleName() {
- // replaced String with StringBuilder
- StringBuilder s = new StringBuilder();
- if (ComponentStateUtil
- .hasStyles(checkBox.getState(false).inputStyles)) {
- for (final Iterator<String> it = checkBox
- .getState(false).inputStyles.iterator(); it
- .hasNext();) {
- s.append(it.next());
- if (it.hasNext()) {
- s.append(" ");
- }
- }
- }
- return s.toString();
- }
-
- @Override
- // Implementation copied from AbstractComponent
- public void setStyleName(String style) {
- if (style == null || style.isEmpty()) {
- checkBox.getState().inputStyles = null;
- return;
- }
- if (checkBox.getState().inputStyles == null) {
- checkBox.getState().inputStyles = new ArrayList<>();
- }
- List<String> styles = checkBox.getState().inputStyles;
- styles.clear();
- StringTokenizer tokenizer = new StringTokenizer(style, " ");
- while (tokenizer.hasMoreTokens()) {
- styles.add(tokenizer.nextToken());
- }
- }
-
- @Override
- // Implementation copied from AbstractComponent
- public void addStyleName(String style) {
- if (style == null || style.isEmpty()) {
- return;
- }
- if (checkBox.getState().inputStyles != null
- && checkBox.getState().inputStyles.contains(style)) {
- return;
- }
- if (style.contains(" ")) {
- // Split space separated style names and add them one by one.
- StringTokenizer tokenizer = new StringTokenizer(style, " ");
- while (tokenizer.hasMoreTokens()) {
- addStyleName(tokenizer.nextToken());
- }
- return;
- }
-
- if (checkBox.getState().inputStyles == null) {
- checkBox.getState().inputStyles = new ArrayList<>();
- }
- List<String> styles = checkBox.getState().inputStyles;
- styles.add(style);
- }
-
- @Override
- // Implementation copied from AbstractComponent
- public void removeStyleName(String style) {
- if (ComponentStateUtil.hasStyles(checkBox.getState().inputStyles)) {
- StringTokenizer tokenizer = new StringTokenizer(style, " ");
- while (tokenizer.hasMoreTokens()) {
- checkBox.getState().inputStyles
- .remove(tokenizer.nextToken());
- }
- }
- }
- }
-
- /**
- * The inner label element of the CheckBox.
- */
- public static class CheckBoxLabelElement implements HasStyleNames {
-
- private final CheckBox checkBox;
-
- private CheckBoxLabelElement(CheckBox checkBox) {
- this.checkBox = checkBox;
- }
-
- @Override
- // Implementation copied from AbstractComponent
- public String getStyleName() {
- // replaced String with StringBuilder
- StringBuilder s = new StringBuilder();
- if (ComponentStateUtil
- .hasStyles(checkBox.getState(false).labelStyles)) {
- for (final Iterator<String> it = checkBox
- .getState(false).labelStyles.iterator(); it
- .hasNext();) {
- s.append(it.next());
- if (it.hasNext()) {
- s.append(" ");
- }
- }
- }
- return s.toString();
- }
-
- @Override
- // Implementation copied from AbstractComponent
- public void setStyleName(String style) {
- if (style == null || style.isEmpty()) {
- checkBox.getState().labelStyles = null;
- return;
- }
- if (checkBox.getState().labelStyles == null) {
- checkBox.getState().labelStyles = new ArrayList<>();
- }
- List<String> styles = checkBox.getState().labelStyles;
- styles.clear();
- StringTokenizer tokenizer = new StringTokenizer(style, " ");
- while (tokenizer.hasMoreTokens()) {
- styles.add(tokenizer.nextToken());
- }
- }
-
- @Override
- // Implementation copied from AbstractComponent
- public void addStyleName(String style) {
- if (style == null || style.isEmpty()) {
- return;
- }
- if (checkBox.getState().labelStyles != null
- && checkBox.getState().labelStyles.contains(style)) {
- return;
- }
- if (style.contains(" ")) {
- // Split space separated style names and add them one by one.
- StringTokenizer tokenizer = new StringTokenizer(style, " ");
- while (tokenizer.hasMoreTokens()) {
- addStyleName(tokenizer.nextToken());
- }
- return;
- }
-
- if (checkBox.getState().labelStyles == null) {
- checkBox.getState().labelStyles = new ArrayList<>();
- }
- List<String> styles = checkBox.getState().labelStyles;
- styles.add(style);
- }
-
- @Override
- // Implementation copied from AbstractComponent
- public void removeStyleName(String style) {
- if (ComponentStateUtil.hasStyles(checkBox.getState().labelStyles)) {
- StringTokenizer tokenizer = new StringTokenizer(style, " ");
- while (tokenizer.hasMoreTokens()) {
- checkBox.getState().labelStyles
- .remove(tokenizer.nextToken());
- }
- }
- }
- }
-
- /**
- * Creates a new checkbox.
- */
- public CheckBox() {
- registerRpc(rpc);
- registerRpc(new FocusAndBlurServerRpcDecorator(this, this::fireEvent));
- setValue(Boolean.FALSE);
- }
-
- /**
- * Creates a new checkbox with a set caption.
- *
- * @param caption
- * the Checkbox caption.
- */
- public CheckBox(String caption) {
- this();
- setCaption(caption);
- }
-
- /**
- * Creates a new checkbox with a caption and a set initial state.
- *
- * @param caption
- * the caption of the checkbox
- * @param initialState
- * the initial state of the checkbox
- */
- public CheckBox(String caption, boolean initialState) {
- this(caption);
- setValue(initialState);
- }
-
- @Override
- public Boolean getValue() {
- return getState(false).checked;
- }
-
- /**
- * Sets the value of this CheckBox. If the new value is not equal to
- * {@code getValue()}, fires a {@link ValueChangeEvent}. Throws
- * {@code NullPointerException} if the value is null.
- *
- * @param value
- * the new value, not {@code null}
- * @throws NullPointerException
- * if {@code value} is {@code null}
- */
- @Override
- public void setValue(Boolean value) {
- Objects.requireNonNull(value, "CheckBox value must not be null");
- super.setValue(value);
- }
-
- /**
- * Sets the value of this CheckBox. If the new value is not equal to
- * {@code getValue()}, fires a {@link ValueChangeEvent}. Throws
- * {@code NullPointerException} if the value is null.
- *
- * @param value
- * the new value, not {@code null}
- * @param userOriginated
- * {@code true} if this event originates from the client,
- * {@code false} otherwise.
- * @throws NullPointerException
- * if {@code value} is {@code null}
- */
- @Override
- protected boolean setValue(Boolean value, boolean userOriginated) {
- Objects.requireNonNull(value, "CheckBox value must not be null");
- return super.setValue(value, userOriginated);
- }
-
- @Override
- public Boolean getEmptyValue() {
- return false;
- }
-
- @Override
- protected CheckBoxState getState() {
- return (CheckBoxState) super.getState();
- }
-
- @Override
- protected CheckBoxState getState(boolean markAsDirty) {
- return (CheckBoxState) super.getState(markAsDirty);
- }
-
- @Override
- protected void doSetValue(Boolean value) {
- getState().checked = value;
- }
-
- @Override
- public Registration addBlurListener(BlurListener listener) {
- return addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener,
- BlurListener.blurMethod);
- }
-
- @Override
- public Registration addFocusListener(FocusListener listener) {
- return addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener,
- FocusListener.focusMethod);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.ui.AbstractField#readDesign(org.jsoup.nodes.Element,
- * com.vaadin.ui.declarative.DesignContext)
- */
- @Override
- public void readDesign(Element design, DesignContext designContext) {
- super.readDesign(design, designContext);
- if (design.hasAttr("checked")) {
- this.setValue(DesignAttributeHandler.readAttribute("checked",
- design.attributes(), Boolean.class), false);
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.ui.AbstractField#getCustomAttributes()
- */
- @Override
- protected Collection<String> getCustomAttributes() {
- Collection<String> attributes = super.getCustomAttributes();
- attributes.add("checked");
- return attributes;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.ui.AbstractField#writeDesign(org.jsoup.nodes.Element,
- * com.vaadin.ui.declarative.DesignContext)
- */
- @Override
- public void writeDesign(Element design, DesignContext designContext) {
- super.writeDesign(design, designContext);
- CheckBox def = designContext.getDefaultInstance(this);
- Attributes attr = design.attributes();
- DesignAttributeHandler.writeAttribute("checked", attr, getValue(),
- def.getValue(), Boolean.class, designContext);
- }
-
- /**
- * Returns the {@link CheckBoxInputElement} element to manipulate the style
- * name of the {@code input} element of the {@link CheckBox}.
- *
- * @since 8.7
- * @return the current {@link CheckBoxInputElement}, not {@code null}.
- */
- public CheckBoxInputElement getInputElement() {
- if (checkBoxInputElement == null) {
- checkBoxInputElement = new CheckBoxInputElement(this);
- }
- return checkBoxInputElement;
- }
-
- /**
- * Returns the {@link CheckBoxLabelElement} element to manipulate the style
- * name of the {@code label} element of the {@link CheckBox}.
- *
- * @since 8.7
- * @return the current {@link CheckBoxLabelElement}, not {@code null}.
- */
- public CheckBoxLabelElement getLabelElement() {
- if (checkBoxLabelElement == null) {
- checkBoxLabelElement = new CheckBoxLabelElement(this);
- }
- return checkBoxLabelElement;
- }
- }
|