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

scalacss.internal.AVs.scala Maven / Gradle / Ivy

The newest version!
package scalacss.internal

import japgolly.univeq._

/**
 * An Attribute-and-Value pair.
 */
final case class AV(attr: Attr, value: Value) {
  def important: AV =
    if (value endsWith _important)
      this
    else
      copy(value = this.value + _important)

  def apply(env: Env) =
    attr.gen(env)(value)
}
object AV {
  implicit def univEq: UnivEq[AV] = UnivEq.derive
}

/**
 * One or more ordered attributes, each with one or more ordered values.
 */
final class AVs private[AVs](val order: NonEmptyVector[Attr], val data: Map[Attr, NonEmptyVector[Value]]) {
  override def toString = iterator.mkString("AVs(", ", ", ")")

  def +(av: AV): AVs =
    add(av.attr, av.value)

  def ++(avs: Iterable[AV]): AVs =
    avs.foldLeft(this)(_ + _)

  def ++(avs: AVs): AVs =
    avs.iterator.foldLeft(this)((q, t) => q.addAll(t._1, t._2))

  def add(a: Attr, v: Value): AVs =
    addTail(a, NonEmptyVector.end(_, v))

  def addAll(a: Attr, vs: NonEmptyVector[Value]): AVs =
    addTail(a, _ ++: vs)

  private def addTail(a: Attr, f: Vector[Value] => NonEmptyVector[Value]): AVs =
    addf(a, f, e => if (e.isEmpty) order :+ a else order)

  private def addf(a: Attr, f: Vector[Value] => NonEmptyVector[Value], g: Vector[Value] => NonEmptyVector[Attr]): AVs = {
    val existing = getv(a)
    val newOrder = g(existing)
    val newData  = data.updated(a, f(existing))
    new AVs(newOrder, newData)
  }

  private def addHead(a: Attr, f: Vector[Value] => NonEmptyVector[Value]): AVs =
    addf(a, f,
      e => if (e.isEmpty)
        a +: order
      else
        NonEmptyVector(a, order.whole.filterNot(a ==* _)))

  def +:(av: AV): AVs =
    addHead(av.attr, NonEmptyVector(av.value, _))

  def get(a: Attr): Option[NonEmptyVector[Value]] =
    data.get(a)

  def getv(a: Attr): Vector[Value] =
    data.get(a).fold(Vector.empty[Value])(_.whole)

  def filterKeys(f: Attr => Boolean): Option[AVs] =
    NonEmptyVector.option(order.whole.filter(f))
      .map(o => new AVs(o, data.iterator.filter(kv => f(kv._1)).toMap))

  def modify(a: Attr, f: Vector[Value] => NonEmptyVector[Value]): AVs =
    addTail(a, f)

  def iterator: Iterator[(Attr, NonEmptyVector[Value])] =
    order.iterator.map(a => (a, data(a)))

  def avIterator: Iterator[AV] =
    iterator.flatMap(t => t._2.iterator.map(AV(t._1, _)))
}

object AVs {
  def apply(av1: AV, avn: AV*): AVs =
    apply(av1.attr, av1.value) ++ avn

  def apply(a: Attr, v: Value): AVs =
    apply(a, NonEmptyVector one v)

  def apply(a: Attr, vs: NonEmptyVector[Value]): AVs =
    new AVs(NonEmptyVector one a, Map.empty.updated(a, vs))
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy