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

scalacss.AVs.scala Maven / Gradle / Ivy

There is a newer version: 0.5.6
Show newest version
package scalacss

import scala.collection.GenTraversable
import scalaz.Equal

/**
 * 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)

  @inline def apply(env: Env) =
    attr.gen(env)(value)
}

/**
 * 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 = toStream.mkString("AVs(", ", ", ")")

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

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

  def ++(avs: AVs): AVs =
    avs.toStream.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(Equal[Attr].equal(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 filterKeys f))

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

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

  def avStream: Stream[AV] =
    toStream.flatMap(t => t._2.toStream.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