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

com.github.mvysny.karibudsl.v8.ClassList.kt Maven / Gradle / Ivy

The newest version!
package com.github.mvysny.karibudsl.v8

import com.vaadin.ui.*
import com.vaadin.ui.components.grid.FooterCell
import com.vaadin.ui.components.grid.FooterRow
import com.vaadin.ui.components.grid.HeaderCell
import com.vaadin.ui.components.grid.HeaderRow
import java.io.Serializable

/**
 * Represents a mutable class list (or style names as Vaadin calls them).
 */
public interface ClassList : MutableSet, Serializable {

    /**
     * Sets or removes the given class name, based on the `set` parameter.
     *
     * @param className the class name to set or remove, cannot contain spaces.
     * @param set true to set the class name, false to remove it
     * @return true if the class list was modified (class name added or
     * removed), false otherwise
     */
    public fun set(className: String, set: Boolean): Boolean {
        require(!className.containsWhitespace()) { "'$className' cannot contain whitespace" }
        return if (set) {
            add(className)
        } else {
            remove(className)
        }
    }

    /**
     * Toggles given [className] (removes it if it's present, or adds it if it's absent).
     * @param className the class name to toggle, cannot contain spaces.
     */
    public fun toggle(className: String) {
        require(!className.containsWhitespace()) { "'$className' cannot contain whitespace" }
        set(className, !contains(className))
    }
}

public abstract class AbstractStringBasedClassList : AbstractMutableSet(), ClassList {
    /**
     * Returns a space-separated list of style names.
     */
    protected abstract fun getStyleName(): String

    /**
     * Sets new space-separated list of style names, overriding any previous value.
     */
    protected abstract fun setStyleName(styleNames: Set)

    override val size: Int
        get() = styleNames.size

    private val styleNames: Set get() = getStyleName().split(' ').filterNotBlank().toSet()

    override fun contains(element: String): Boolean {
        require(!element.containsWhitespace()) { "'$element' cannot contain whitespace" }
        return styleNames.contains(element)
    }

    override fun add(element: String): Boolean {
        require(!element.containsWhitespace()) { "'$element' cannot contain whitespace" }
        val names = styleNames
        if (!names.contains(element)) {
            setStyleName(names + element)
            return true
        }
        return false
    }

    override fun remove(element: String): Boolean {
        require(!element.containsWhitespace()) { "'$element' cannot contain whitespace" }
        val names = styleNames
        if (names.contains(element)) {
            setStyleName(names - element)
            return true
        }
        return false
    }

    private inner class ClassListIterator : MutableIterator {
        private val delegate = styleNames.iterator()
        private lateinit var current: String
        override fun hasNext(): Boolean = delegate.hasNext()
        override fun next(): String {
            current = delegate.next()
            return current
        }

        override fun remove() {
            remove(current)
        }
    }

    override fun iterator(): MutableIterator = ClassListIterator()

    override fun isEmpty(): Boolean = getStyleName().isBlank()

    override fun clear() {
        setStyleName(setOf())
    }
}

private class ComponentClassList(val component: Component) : AbstractStringBasedClassList() {
    override fun getStyleName(): String = component.styleName
    override fun setStyleName(styleNames: Set) {
        component.styleName = styleNames.joinToString(" ")
    }
}

/**
 * Returns a mutable set of styles currently present on the component.
 */
public val (@VaadinDsl Component).styleNames: ClassList get() = ComponentClassList(this)

/**
 * Adds or removes given [style] from the component, depending on the value of the [isPresent] parameter.
 */
public fun (@VaadinDsl Component).toggleStyleName(style: String, isPresent: Boolean) {
    if (isPresent) addStyleName(style) else removeStyleName(style)
}

/**
 * Checks whether the component has given [style] (or multiple styles if the string contains space).
 * @param style if contains a space, this is considered to be a list of styles. In such case, all styles must be present on the component.
 */
public fun (@VaadinDsl Component).hasStyleName(style: String): Boolean {
    if (style.contains(' ')) return style.split(' ').filterNotBlank().all { hasStyleName(style) }
    return styleNames.contains(style)
}

private class NotificationClassList(val notification: Notification) : AbstractStringBasedClassList() {
    override fun getStyleName(): String = notification.styleName ?: ""
    override fun setStyleName(styleNames: Set) {
        notification.styleName = if (styleNames.isEmpty()) null else styleNames.joinToString(" ")
    }
}

/**
 * Returns a mutable set of styles currently present on the component.
 */
public val (@VaadinDsl Notification).styleNames: ClassList get() = NotificationClassList(this)

private class HasStylesClassList(val hasStyles: HasStyleNames) : AbstractStringBasedClassList() {
    override fun getStyleName(): String = hasStyles.styleName
    override fun setStyleName(styleNames: Set) {
        hasStyles.styleName = styleNames.joinToString(" ")
    }
}

/**
 * Returns a mutable set of styles currently present on the component.
 */
public val (@VaadinDsl HasStyleNames).styleNames: ClassList get() = HasStylesClassList(this)

private class TabClassList(val tab: TabSheet.Tab) : AbstractStringBasedClassList() {
    override fun getStyleName(): String = tab.styleName ?: ""
    override fun setStyleName(styleNames: Set) {
        tab.styleName = if (styleNames.isEmpty()) null else styleNames.joinToString(" ")
    }
}

/**
 * Returns a mutable set of styles currently present on the component.
 */
public val (@VaadinDsl TabSheet.Tab).styleNames: ClassList get() = TabClassList(this)

private class MenuItemClassList(val menuItem: MenuBar.MenuItem) : AbstractStringBasedClassList() {
    override fun getStyleName(): String = menuItem.styleName ?: ""
    override fun setStyleName(styleNames: Set) {
        menuItem.styleName = if (styleNames.isEmpty()) null else styleNames.joinToString(" ")
    }
}

/**
 * Returns a mutable set of styles currently present on the component.
 */
public val (@VaadinDsl MenuBar.MenuItem).styleNames: ClassList get() = MenuItemClassList(this)

private class FooterCellClassList(val footerCell: FooterCell) : AbstractStringBasedClassList() {
    override fun getStyleName(): String = footerCell.styleName ?: ""
    override fun setStyleName(styleNames: Set) {
        footerCell.styleName = if (styleNames.isEmpty()) null else styleNames.joinToString(" ")
    }
}

/**
 * Returns a mutable set of styles currently present on the component.
 */
public val (@VaadinDsl FooterCell).styleNames: ClassList get() = FooterCellClassList(this)

private class FooterRowClassList(val footerRow: FooterRow) : AbstractStringBasedClassList() {
    override fun getStyleName(): String = footerRow.styleName ?: ""
    override fun setStyleName(styleNames: Set) {
        footerRow.styleName = if (styleNames.isEmpty()) null else styleNames.joinToString(" ")
    }
}

/**
 * Returns a mutable set of styles currently present on the component.
 */
public val (@VaadinDsl FooterRow).styleNames: ClassList get() = FooterRowClassList(this)

private class HeaderRowClassList(val headerRow: HeaderRow) : AbstractStringBasedClassList() {
    override fun getStyleName(): String = headerRow.styleName ?: ""
    override fun setStyleName(styleNames: Set) {
        headerRow.styleName = if (styleNames.isEmpty()) null else styleNames.joinToString(" ")
    }
}

/**
 * Returns a mutable set of styles currently present on the component.
 */
public val (@VaadinDsl HeaderRow).styleNames: ClassList get() = HeaderRowClassList(this)

private class HeaderCellClassList(val headerCell: HeaderCell) : AbstractStringBasedClassList() {
    override fun getStyleName(): String = headerCell.styleName ?: ""
    override fun setStyleName(styleNames: Set) {
        headerCell.styleName = if (styleNames.isEmpty()) null else styleNames.joinToString(" ")
    }
}

/**
 * Returns a mutable set of styles currently present on the component.
 */
public val (@VaadinDsl HeaderCell).styleNames: ClassList get() = HeaderCellClassList(this)




© 2015 - 2025 Weber Informatics LLC | Privacy Policy