154 lines
4.0 KiB
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;
|
||
|
}
|
||
|
}
|