nur-sery/nur_src/v/base/AbstractLayoutManager.php

154 lines
4.0 KiB
PHP

<?php
namespace nur\v\base;
use nur\A;
use nur\v\model\ILayoutManager;
abstract class AbstractLayoutManager implements ILayoutManager {
function __construct() {
$this->stack = [[
"mark" => null,
"pending" => null,
"end" => null,
"have_content" => false,
]];
$this->index = 0;
}
/** @var array */
protected $stack;
/** @var int */
protected $index;
function haveContent(): bool {
return $this->stack[$this->index]["have_content"];
}
function add($vs): void {
if ($vs !== null) {
$pending =& $this->stack[$this->index]["pending"];
if ($pending === null) $pending = [];
$pending[] = $vs;
}
}
function flushContent(bool $haveContent=false): ?array {
$content = null;
foreach ($this->stack as &$item) {
if ($haveContent) A::append_nn($content, $item["pending"]);
$item["pending"] = null;
}; unset($item);
$this->stack[$this->index]["have_content"] = $haveContent;
return $content;
}
function flush(bool $haveContent=false): ?array {
$currentHaveContent = $this->haveContent();
$content = $this->flushContent($currentHaveContent);
if ($haveContent != $currentHaveContent) $this->flushContent($haveContent);
return $content;
}
function push($mark, ?array $start=null, ?array $end=null): ?array {
$content = $this->flush();
A::append_nn($content, $start);
$this->stack[] = [
"mark" => $mark,
"pending" => null,
"end" => $end,
"have_content" => false,
];
$this->index++;
return $content;
}
protected function haveMark($mark): bool {
$index = $this->index;
while ($index > 0) {
$item = $this->stack[$index--];
if ($item["mark"] === $mark) return true;
}
return false;
}
function pop($mark): ?array {
if (!$this->haveMark($mark)) return null;
$content = null;
while ($this->index > 0) {
$item = array_pop($this->stack);
$this->index--;
if ($item["have_content"]) A::append_nn($content, $item["pending"]);
A::append_nn($content, $item["end"]);
if ($item["mark"] === $mark) break;
}
return $content;
}
protected abstract function getRowTags($options): array;
function startRow($options=null): ?array {
$content = $this->flush();
$rowTags = $this->getRowTags($options);
A::append_nn($content, $this->push([$this, "row"], ...$rowTags));
return $content;
}
function row($options=null): ?array {
$content = $this->endRow();
A::append_nn($content, $this->startRow($options));
return $content;
}
protected abstract function getColTags($size, $options): array;
function startCol($size, $options=null): ?array {
$content = $this->flush();
$colTags = $this->getColTags($size, $options);
A::append_nn($content, $this->push([$this, "col"], ...$colTags));
return $content;
}
function col($size, $options=null): ?array {
$content = $this->endCol();
A::append_nn($content, $this->startCol($size, $options));
return $content;
}
protected abstract function getPanelTags($title, $options): array;
function startPanel($title, $options=null): ?array {
$content = $this->flush(true);
$panelTags = $this->getPanelTags($title, $options);
A::append_nn($content, $this->push([$this, "panel"], ...$panelTags));
return $content;
}
function panel($title, $options=null): ?array {
$content = $this->endPanel();
A::append_nn($content, $this->startPanel($title, $options));
return $content;
}
function endPanel(): ?array {
return $this->pop([$this, "panel"]);
}
function endCol(): ?array {
return $this->pop([$this, "col"]);
}
function endRow(): ?array {
return $this->pop([$this, "row"]);
}
function end(): ?array {
$content = null;
A::append_nn($content, $this->flush());
A::append_nn($content, $this->endPanel());
A::append_nn($content, $this->endCol());
A::append_nn($content, $this->endRow());
return $content;
}
}