Created
May 18, 2012 19:49
-
-
Save oranj/2727284 to your computer and use it in GitHub Desktop.
Shell based application rendering system.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
include(dirname(__FILE__).'/shelly.php'); | |
$Window = new ShellWindow(); | |
$item1 = new ShellItem(30, 20, Array('left' => 5, 'top' => 3), 'X', 'yellow'); | |
$item2 = new ShellItem('10', '10', Array('right' => 5, 'bottom' => 10), '*', 'red'); | |
$Window->add_children($item1, $item2); | |
$Window->draw(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class ShellItem { | |
const SIZE_MODE_SCALE = 0; | |
const SIZE_MODE_CONST = 1; | |
private $width; | |
private $height; | |
private $width_mode; | |
private $height_mode; | |
private $anchors; | |
private $parent; | |
private $children; | |
private $border_color; | |
private $border_width; | |
private $border_style; | |
private $padding; | |
private $stream; | |
public static function terminal_width() { | |
return (int)trim(`tput cols`); | |
} | |
public static function terminal_height() { | |
return (int)trim(`tput lines`); | |
} | |
public static function terminal_clear() { | |
system('clear'); | |
} | |
public static function terminal_set_cursor_position($row, $column) { | |
echo "\033[".$row.";".$column."H"; | |
} | |
public static $foreground_colors = array( | |
'bold' => '1', 'dim' => '2', | |
'black' => '0;30', 'dark_gray' => '1;30', | |
'blue' => '0;34', 'light_blue' => '1;34', | |
'green' => '0;32', 'light_green' => '1;32', | |
'cyan' => '0;36', 'light_cyan' => '1;36', | |
'red' => '0;31', 'light_red' => '1;31', | |
'purple' => '0;35', 'light_purple' => '1;35', | |
'brown' => '0;33', 'yellow' => '1;33', | |
'light_gray' => '0;37', 'white' => '1;37', | |
'normal' => '0;39', | |
); | |
public static $background_colors = array( | |
'black' => '40', 'red' => '41', | |
'green' => '42', 'yellow' => '43', | |
'blue' => '44', 'magenta' => '45', | |
'cyan' => '46', 'light_gray' => '47', | |
); | |
public static function colorize($text, $foreground, $background = false) { | |
$str = "\033[".self::$foreground_colors[$foreground]."m"; | |
if ($background) { | |
$str .= "\033[".self::$background_colors[$background]."m"; | |
} | |
$str .= $text; | |
$str .= "\033[0m"; | |
return $str; | |
} | |
public function width() { | |
if (! is_null($this->anchors['left']) && ! is_null($this->anchors['right'])) { | |
return $this->parent->width() - $this->parent->inset(); | |
} else if (! is_null($this->parent)) { | |
switch($this->width_mode) { | |
case self::SIZE_MODE_SCALE: | |
return ($this->width / 100) * $this->parent->width(); | |
break; | |
case self::SIZE_MODE_CONST: | |
return $this->width; | |
break; | |
default: | |
break; | |
} | |
} else { | |
return self::terminal_width(); | |
} | |
} | |
public function height() { | |
if (! is_null($this->anchors['top']) && ! is_null($this->anchors['bottom'])) { | |
return $this->parent->height() - $this->parent->inset(); | |
} else if (! is_null($this->parent)) { | |
switch($this->height_mode) { | |
case self::SIZE_MODE_SCALE: | |
return ($this->height / 100) * $this->parent->height(); | |
break; | |
case self::SIZE_MODE_CONST: | |
return $this->height; | |
break; | |
default: | |
break; | |
} | |
} else { | |
return self::terminal_height() - 1; | |
} | |
} | |
public function inset() { | |
return $this->padding + $this->border_width; | |
} | |
public function offset() { | |
$node = $this->parent; | |
$top = $left = 0; | |
while (! is_null($node)) { | |
$offset = $node->offset(); | |
$top += $offset['x']; | |
$left += $offset['y']; | |
$node = $node->parent; | |
} | |
if ($this->parent) { | |
$parent_width = $this->parent->width(); | |
$parent_height = $this->parent->height(); | |
} else { | |
$parent_width = 0; | |
$parent_height = 0; | |
} | |
if (! is_null($this->anchors['left']) && ! is_null($this->anchors['right'])) { | |
$left += floor(($this->parent->width() - $this->width()) / 2); | |
} else if (! is_null($this->anchors['left'])) { | |
$left += $this->anchors['left']; | |
} else if (! is_null($this->anchors['right'])) { | |
$left += ($this->parent->width() - ($this->width() + $this->anchors['right'])); | |
} | |
if (! is_null($this->anchors['top']) && ! is_null($this->anchors['bottom'])) { | |
$top += floor(($this->parent->height() - $this->height()) / 2); | |
} else if (! is_null($this->anchors['left'])) { | |
$top += $this->anchors['top']; | |
} else if (! is_null($this->anchors['bottom'])) { | |
$top += ($this->parent->height() - ($this->height() + $this->anchors['bottom'])); | |
} | |
return Array('x' => $left, 'y' => $top); | |
} | |
public function __construct($width, $height, $anchors = array(), $border_style = '#', $border_color = 'blue', $border_width = 1, $padding = 1) { | |
$this->anchors = Array('left'=>null, 'top'=>null, 'right'=>null, 'bottom'=>null); | |
$this->width_mode = ((substr($width, -1) == '%')?self::SIZE_MODE_SCALE:self::SIZE_MODE_CONST); | |
$this->height_mode = ((substr($height, -1) == '%')?self::SIZE_MODE_SCALE:self::SIZE_MODE_CONST); | |
$this->width = (int)$width; | |
$this->height = (int)$height; | |
$this->border_width = $border_width; | |
$this->border_style = $border_style; | |
$this->border_color = $border_color; | |
$this->children = Array(); | |
$this->padding = $padding; | |
$this->stream = STDERR; | |
foreach ($this->anchors as $key => $value) { | |
if (isset($anchors[$key])) { | |
$this->anchors[$key] = $anchors[$key]; | |
} | |
} | |
} | |
public function add_children() { | |
$children = func_get_args(); | |
foreach ($children as &$child) { | |
$this->children []= $child; | |
$child->set_parent($this); | |
} | |
} | |
public function set_parent($parent) { | |
$this->parent = $parent; | |
} | |
public function draw() { | |
$offset = $this->offset(); | |
$max_x = $offset['x'] + $this->width(); | |
$max_y = $offset['y'] + $this->height(); | |
$inset = $this->inset(); | |
$inset_x = $offset['x'] + $inset; | |
$inset_max_x = $max_x - $inset; | |
$inset_y = $offset['y'] + $inset; | |
$inset_max_y = $max_y - $inset; | |
#print_r(Array($offset['x'], $max_x, $offset['y'], $max_y, $this)); | |
$_x = 0; | |
for ($x = $offset['x']; $x < $max_x; $x++) { | |
$_y = 0; | |
for ($y = $offset['y']; $y < $max_y; $y++) { | |
self::terminal_set_cursor_position($y, $x); | |
if ($x - $this->border_width < $offset['x'] || $y - $this->border_width < $offset['y'] || $x + $this->border_width >= $max_x || $y + $this->border_width >= $max_y) { | |
echo self::colorize($this->border_style, $this->border_color);; | |
} else { | |
} | |
$_y++; | |
} | |
$_x++; | |
} | |
foreach ($this->children as $child) { | |
$child->draw(); | |
} | |
self::terminal_set_cursor_position($this->height(), 0); | |
} | |
} | |
class ShellWindow extends ShellItem { | |
public function __construct() { | |
parent::__construct(null, null); | |
} | |
public function draw() { | |
self::terminal_clear(); | |
parent::draw(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment