All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.patternfly.component.badge.Badge Maven / Gradle / Ivy

There is a newer version: 0.2.11
Show newest version
/*
 *  Copyright 2023 Red Hat
 *
 *  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
 *
 *      https://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 org.patternfly.component.badge;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;

import org.patternfly.component.BaseComponent;
import org.patternfly.component.ComponentType;
import org.patternfly.component.HasValue;
import org.patternfly.component.WithObservableValue;
import org.patternfly.core.ObservableValue;
import org.patternfly.handler.ChangeHandler;
import org.patternfly.style.Classes;

import elemental2.dom.Event;
import elemental2.dom.HTMLElement;

import static org.jboss.elemento.Elements.span;
import static org.patternfly.style.Classes.badge;
import static org.patternfly.style.Classes.component;
import static org.patternfly.style.Classes.modifier;
import static org.patternfly.style.Classes.read;
import static org.patternfly.style.Classes.unread;

/**
 * A badge is used to annotate other information like a label or an object name.
 *
 * @see https://www.patternfly.org/components/badge
 */
public class Badge extends BaseComponent
        implements HasValue, WithObservableValue {

    // ------------------------------------------------------ factory

    public static Badge badge(int count) {
        return new Badge(count);
    }

    public static Badge badge(int count, int limit) {
        return new Badge(count, limit);
    }

    // ------------------------------------------------------ instance

    private final HTMLElement valueElement;
    private final List> changeHandler;
    private int value;
    private int limit;
    private HTMLElement screenReader;
    private Function display;
    private Function maxDisplay;
    private ObservableValue ov;

    Badge(int count) {
        this(count, Integer.MAX_VALUE);
    }

    Badge(int count, int limit) {
        super(ComponentType.Badge, span().css(component(badge)).element());
        this.valueElement = add(span()).element();
        this.limit = limit;
        this.changeHandler = new ArrayList<>();
        count(count);
    }

    // ------------------------------------------------------ builder

    /** Marks the badge as read. */
    public Badge read() {
        element().classList.remove(modifier(unread));
        element().classList.add(modifier(read));
        return this;
    }

    /** Marks the badge as unread. */
    public Badge unread() {
        element().classList.remove(modifier(read));
        element().classList.add(modifier(unread));
        return this;
    }

    /** Same as {@linkplain #count(int, boolean) count(count, false)} */
    public Badge count(int count) {
        return count(count, false);
    }

    /** Sets the count of this badge. */
    public Badge count(int count, boolean fireEvent) {
        boolean changed = value != count;
        value = count;
        updateValue(this.value);
        if (fireEvent && changed) {
            changeHandler.forEach(handler -> handler.onChange(new Event(""), this, value));
        }
        return this;
    }

    /**
     * Use a function to render the text for the value of {@link #count()}. If not set {@code String.valueOf(count)} is used
     * implicitly.
     */
    public Badge display(Function display) {
        this.display = display;
        updateValue(ov != null ? ov.get() : this.value);
        return this;
    }

    /**
     * Use a function to render the text if {@link #count()} > {@link #limit(int)}. If not set {@code count + "+"} is used
     * implicitly.
     */
    public Badge maxDisplay(Function maxDisplay) {
        this.maxDisplay = maxDisplay;
        updateValue(ov != null ? ov.get() : this.value);
        return this;
    }

    /** Sets the limit of this badge */
    public Badge limit(int limit) {
        this.limit = limit;
        updateValue(ov != null ? ov.get() : this.value);
        return this;
    }

    public Badge screenReader(String text) {
        if (screenReader == null) {
            add(screenReader = span().css(Classes.screenReader).element());
        }
        screenReader.textContent = text;
        return this;
    }

    /**
     * Binds an observable value to this component. If you're using an observable value, you must not use {@link #count(int)} or
     * {@link #count(int, boolean)} to set the value. Use {@link ObservableValue#set(Object)} instead.
     */
    @Override
    public Badge bind(ObservableValue ov) {
        this.ov = ov;
        this.ov.subscribe((current, previous) -> {
            updateValue(current);
            if (!Objects.equals(current, previous)) {
                changeHandler.forEach(handler -> handler.onChange(new Event(""), this, current));
            }
        });
        updateValue(ov.get());
        return this;
    }

    @Override
    public Badge that() {
        return this;
    }

    // ------------------------------------------------------ events

    /**
     * Defines a change handler that is called when the {@link #value()} of this badge changes.
     */
    public Badge onChange(ChangeHandler changeHandler) {
        this.changeHandler.add(changeHandler);
        return this;
    }

    // ------------------------------------------------------ api

    public int count() {
        return ov != null ? ov.get() : this.value;
    }

    @Override
    public Integer value() {
        return ov != null ? ov.get() : this.value;
    }

    // ------------------------------------------------------ internal

    private void updateValue(int value) {
        if (value > limit) {
            if (maxDisplay != null) {
                valueElement.textContent = maxDisplay.apply(value);
            } else {
                valueElement.textContent = limit + "+";
            }
        } else {
            if (display != null) {
                valueElement.textContent = display.apply(value);
            } else {
                valueElement.textContent = String.valueOf(value);
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy