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

kreuzberg.engine.common.TreeNode.scala Maven / Gradle / Ivy

There is a newer version: 0.10.3
Show newest version
package kreuzberg.engine.common
import kreuzberg.*

type HeadlessOrComponent = Component | HeadlessComponent

/**
 * A Tree Representation of a component.
 * @param component
 *   Kreuzberg Service / Component
 * @param html
 *   HTML representation
 * @param children
 *   children nodes
 * @param handlers
 *   Event bindings
 * @param subscriptions
 *   subscribed models
 */
case class TreeNode(
    component: HeadlessOrComponent,
    html: Html,
    children: Vector[TreeNode],
    handlers: Vector[EventBinding[?]],
    subscriptions: Vector[Identifier]
) {
  override def toString: String = s"Component ${id}/${component}"

  /** Renders the tree node. */
  def render(): String = {
    val sb = StringBuilder()
    renderTo(sb)
    sb.result()
  }

  /** Render into a StringBuilder. */
  def renderTo(sb: StringBuilder): Unit = {
    flatHtml.render(sb, renderChild)
  }

  /** All subscriptions of this tree, modelId to component id. */
  def allSubscriptions: Iterator[(Identifier, Identifier)] = {
    for {
      node         <- iterator
      subscription <- node.subscriptions
    } yield {
      subscription -> node.id
    }
  }

  /** All referenced component ids. */
  def allReferencedComponentIds: Iterator[Identifier] = {
    iterator.map(_.id)
  }

  def foreach(f: TreeNode => Unit): Unit = {
    children.foreach(_.foreach(f))
    f(this)
  }

  def iterator: Iterator[TreeNode] = {
    Iterator(this) ++ children.iterator.flatMap(_.iterator)
  }

  private lazy val childrenMap: Map[Identifier, TreeNode] = children.map { t => t.id -> t }.toMap

  private def renderChild(id: Identifier, sb: StringBuilder): Unit = {
    childrenMap(id).renderTo(sb)
  }

  lazy val flatHtml: FlatHtml = html.flat()

  /** Returns the event identifier. */
  def id: Identifier = component.id
}

object TreeNode {

  object emptyComponent extends Component {
    type Runtime = Unit
    def assemble(using c: AssemblerContext): Assembly = {
      Assembly(emptyRootHtml)
    }
  }

  val empty = TreeNode(
    component = emptyComponent,
    html = emptyRootHtml,
    children = Vector.empty,
    handlers = Vector.empty,
    subscriptions = Vector.empty
  )

  private def emptyRootHtml: Html =
    SimpleHtml("div", children = Vector(SimpleHtmlNode.Text("Empty Root"))).withId(Identifier.RootComponent)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy