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;
 | 
						|
  }
 | 
						|
}
 |