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