terminalSize = $this->customTerminalSize ?? TerminalSize::detect(); $this->options = $options ?? LayoutOptions::default(); $this->theme = $this->options->theme ?? DefaultThemes::getConsoleTheme('default'); } public function getTerminalSize(): TerminalSize { return $this->terminalSize; } public function getOptions(): LayoutOptions { return $this->options; } public function getTheme(): ConsoleTheme { return $this->theme; } /** * Get effective width for layout (considering padding and margins) */ protected function getEffectiveWidth(): int { $width = $this->options->width > 0 ? $this->options->width : $this->terminalSize->getUsableWidth(); // Subtract margins and padding $totalMargin = ($this->options->margin * 2); $totalPadding = ($this->options->padding * 2); return max(40, $width - $totalMargin - $totalPadding); } /** * Get effective height for layout */ protected function getEffectiveHeight(): int { return $this->terminalSize->getUsableHeight(); } /** * Check if layout should be responsive */ protected function isResponsive(): bool { return $this->options->responsive; } /** * Get border characters based on border style */ protected function getBorderChars(): array { return match ($this->options->borderStyle) { 'double' => [ 'top-left' => '╔', 'top-right' => '╗', 'bottom-left' => '╚', 'bottom-right' => '╝', 'horizontal' => '═', 'vertical' => '║', 'cross' => '╬', 'top-cross' => '╦', 'bottom-cross' => '╩', 'left-cross' => '╠', 'right-cross' => '╣', ], 'rounded' => [ 'top-left' => '╭', 'top-right' => '╮', 'bottom-left' => '╰', 'bottom-right' => '╯', 'horizontal' => '─', 'vertical' => '│', 'cross' => '┼', 'top-cross' => '┬', 'bottom-cross' => '┴', 'left-cross' => '├', 'right-cross' => '┤', ], 'none' => [ 'top-left' => '', 'top-right' => '', 'bottom-left' => '', 'bottom-right' => '', 'horizontal' => '', 'vertical' => '', 'cross' => '', 'top-cross' => '', 'bottom-cross' => '', 'left-cross' => '', 'right-cross' => '', ], default => [ // 'single' 'top-left' => '┌', 'top-right' => '┐', 'bottom-left' => '└', 'bottom-right' => '┘', 'horizontal' => '─', 'vertical' => '│', 'cross' => '┼', 'top-cross' => '┬', 'bottom-cross' => '┴', 'left-cross' => '├', 'right-cross' => '┤', ], }; } /** * Render a horizontal border line */ protected function renderHorizontalBorder(string $left = '', string $right = '', ?string $middle = null): string { if (!$this->options->showBorders) { return ''; } $chars = $this->getBorderChars(); $width = $this->getEffectiveWidth(); $horizontal = str_repeat($chars['horizontal'], $width); $leftChar = $left !== '' ? $left : $chars['horizontal']; $rightChar = $right !== '' ? $right : $chars['horizontal']; if ($middle !== null) { $horizontal = $leftChar . $middle . $rightChar; } else { $horizontal = $leftChar . $horizontal . $rightChar; } return $horizontal; } /** * Wrap content with padding */ protected function wrapWithPadding(string $content): string { if ($this->options->padding === 0) { return $content; } $padding = str_repeat(' ', $this->options->padding); $lines = explode("\n", $content); $wrapped = []; foreach ($lines as $line) { $wrapped[] = $padding . $line; } return implode("\n", $wrapped); } /** * Wrap content with borders */ protected function wrapWithBorders(string $content): string { if (!$this->options->showBorders) { return $content; } $chars = $this->getBorderChars(); $width = $this->getEffectiveWidth(); $lines = explode("\n", $content); $bordered = []; // Top border $bordered[] = $chars['top-left'] . str_repeat($chars['horizontal'], $width) . $chars['top-right']; // Content lines with vertical borders foreach ($lines as $line) { $paddedLine = str_pad($line, $width); $bordered[] = $chars['vertical'] . $paddedLine . $chars['vertical']; } // Bottom border $bordered[] = $chars['bottom-left'] . str_repeat($chars['horizontal'], $width) . $chars['bottom-right']; return implode("\n", $bordered); } }