2008-02-28 16:39:33 +00:00
|
|
|
<?php
|
|
|
|
class NcApp {
|
|
|
|
var $screen;
|
|
|
|
|
|
|
|
function __construct( $echo = false, $cursor = false ) {
|
|
|
|
ncurses_init();
|
|
|
|
$echo ? ncurses_echo() : ncurses_noecho();
|
|
|
|
ncurses_curs_set( (bool)$cursor );
|
|
|
|
$this->screen = ncurses_newwin( 0, 0, 0, 0 );
|
|
|
|
ncurses_refresh();
|
|
|
|
$this->run();
|
|
|
|
}
|
|
|
|
function __destruct() {
|
|
|
|
ncurses_clear();
|
|
|
|
ncurses_refresh();
|
|
|
|
ncurses_end();
|
|
|
|
}
|
|
|
|
function run() {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class NcWindow {
|
|
|
|
var $frame;
|
|
|
|
var $window;
|
|
|
|
var $panels = array();
|
|
|
|
var $children = array();
|
|
|
|
var $parent = false;
|
|
|
|
var $x;
|
|
|
|
var $y;
|
|
|
|
var $width;
|
|
|
|
var $height;
|
|
|
|
var $title;
|
|
|
|
|
|
|
|
function __construct( &$parent, $height, $width, $y, $x, $framed = true ) {
|
|
|
|
if( $parent instanceof NcWindow ) {
|
|
|
|
$this->parent = $parent;
|
|
|
|
//TODO: Find out why this drives php nuts at script termination
|
|
|
|
$this->parent->add_child( $this );
|
|
|
|
$x += $parent->x;
|
|
|
|
$y += $parent->y;
|
|
|
|
$width += $width <= 0 ? $parent->width : 0;
|
|
|
|
$height += $height <= 0 ? $parent->height : 0;
|
|
|
|
}
|
|
|
|
if( $framed ) {
|
|
|
|
$this->frame = ncurses_newwin( $height, $width, $y, $x );
|
|
|
|
ncurses_getmaxyx( $this->frame, $max_y, $max_x );
|
|
|
|
if( $max_y >= 2 && $max_x >= 2 ) {
|
|
|
|
$this->window = ncurses_newwin( $max_y - 2, $max_x - 2, $y + 1, $x + 1 );
|
|
|
|
ncurses_wborder( $this->frame, 0,0, 0,0, 0,0, 0,0 );
|
|
|
|
ncurses_wrefresh( $this->frame );
|
|
|
|
$this->panels[] = ncurses_new_panel( $this->frame );
|
|
|
|
} else {
|
|
|
|
$this->window = $this->frame;
|
|
|
|
$this->frame = false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$this->frame = false;
|
|
|
|
$this->window = ncurses_newwin( $height, $width, $y, $x );
|
|
|
|
ncurses_getmaxyx( $this->window, $max_y, $max_x );
|
|
|
|
}
|
|
|
|
$this->width = $this->frame ? $max_x - 2 : $max_x;
|
|
|
|
$this->height = $this->frame ? $max_y - 2 : $max_y;
|
|
|
|
$this->x = $this->frame ? $x + 1 : $x;
|
|
|
|
$this->y = $this->frame ? $y + 1 : $y;
|
|
|
|
ncurses_wrefresh( $this->window );
|
|
|
|
$this->panels[] = ncurses_new_panel( $this->window );
|
|
|
|
ncurses_update_panels();
|
|
|
|
}
|
|
|
|
function __destruct() {
|
|
|
|
foreach( $this->panels as $id => $panel ) {
|
|
|
|
ncurses_del_panel( $this->panels[$id] );
|
|
|
|
}
|
|
|
|
ncurses_delwin( $this->window );
|
|
|
|
if( $this->frame !== false ) {
|
|
|
|
ncurses_delwin( $this->frame );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function title( $value = false ) {
|
|
|
|
if( $value === false ) {
|
|
|
|
return $this->title;
|
|
|
|
} elseif( $this->frame !== false ) {
|
|
|
|
$this->title = $value;
|
|
|
|
ncurses_wborder( $this->frame, 0,0, 0,0, 0,0, 0,0 );
|
|
|
|
ncurses_mvwaddstr( $this->frame, 0, 1, $this->title );
|
|
|
|
ncurses_update_panels();
|
|
|
|
ncurses_doupdate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function attribute_on( $attribute ) {
|
|
|
|
ncurses_wattron( $this->window, $attribute );
|
|
|
|
}
|
|
|
|
function attribute_off( $attribute ) {
|
|
|
|
ncurses_wattroff( $this->window, $attribute );
|
|
|
|
}
|
|
|
|
function write( $y, $x, $text, $update = true ) {
|
|
|
|
$y = $y < 0 ? $this->height + $y : $y;
|
2008-02-28 16:57:39 +00:00
|
|
|
$x = $x < 0 ? $this->width + $x : $x;
|
2008-02-28 16:39:33 +00:00
|
|
|
$lines = preg_split( '/\r?(\n|\r)/', $text );
|
|
|
|
foreach( $lines as $id => $line ) {
|
2008-02-28 16:57:39 +00:00
|
|
|
$line = substr( $line, 0, $this->width - $x );
|
2008-02-28 16:39:33 +00:00
|
|
|
ncurses_mvwaddstr( $this->window, $y + $id, $x, $line );
|
|
|
|
}
|
|
|
|
if( $update ) {
|
|
|
|
ncurses_update_panels();
|
|
|
|
ncurses_doupdate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function write_centered( $y, $text, $update = true ) {
|
|
|
|
$this->write(
|
|
|
|
$y,
|
|
|
|
floor( $this->width / 2 ) - floor( strlen( $text ) / 2 ),
|
|
|
|
$text,
|
|
|
|
$update
|
|
|
|
);
|
|
|
|
}
|
|
|
|
function write_fixed( $y, $x, $text, $width = 0, $update = true ) {
|
|
|
|
$width = $width > 0 ? $width : $this->width - $x;
|
|
|
|
$this->write( $y, $x, $this->_string_fixed( $text, $width ), $update );
|
|
|
|
}
|
|
|
|
function _string_fixed( $text, $width = 0 ) {
|
|
|
|
$width = $width < 0 ? 0 : $width;
|
|
|
|
$text = substr( $text, 0, $width );
|
|
|
|
$text .= str_repeat( ' ', $width - strlen( $text ) );
|
|
|
|
return $text;
|
|
|
|
}
|
|
|
|
function add_child( $child ) {
|
|
|
|
$this->children[] = $child;
|
|
|
|
}
|
|
|
|
function hide( $update = true ) {
|
|
|
|
foreach( $this->panels as $panel ) {
|
|
|
|
ncurses_hide_panel( $panel );
|
|
|
|
}
|
|
|
|
foreach( $this->children as $child ) {
|
|
|
|
$child->hide( false );
|
|
|
|
}
|
|
|
|
if( $update ) {
|
|
|
|
ncurses_update_panels();
|
|
|
|
ncurses_doupdate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function show( $update = true ) {
|
|
|
|
foreach( $this->panels as $panel ) {
|
|
|
|
ncurses_show_panel( $panel );
|
|
|
|
}
|
|
|
|
foreach( $this->children as $child ) {
|
|
|
|
$child->show( false );
|
|
|
|
}
|
|
|
|
ncurses_update_panels();
|
|
|
|
ncurses_doupdate();
|
|
|
|
}
|
|
|
|
function erase() {
|
|
|
|
ncurses_werase( $this->window );
|
|
|
|
ncurses_wrefresh( $this->window );
|
|
|
|
ncurses_doupdate();
|
|
|
|
}
|
|
|
|
function get_char( $flush = true ) {
|
|
|
|
if( $flush ) {
|
|
|
|
ncurses_flushinp();
|
|
|
|
}
|
|
|
|
return ncurses_getch();
|
|
|
|
//return ncurses_wgetch( $this->window );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class NcProgressBar extends NcWindow {
|
|
|
|
var $max;
|
|
|
|
var $value;
|
|
|
|
var $show_pct;
|
|
|
|
|
|
|
|
function __construct( &$parent, $width, $y, $x, $max = 100, $show_pct = true ) {
|
|
|
|
parent::__construct( $parent, 1, $width, $y, $x, false );
|
|
|
|
$this->max = $max;
|
|
|
|
$this->show_pct = $show_pct;
|
|
|
|
$this->pos( 0 );
|
|
|
|
}
|
|
|
|
function pos( $value = false ) {
|
|
|
|
if( $value === false ) {
|
|
|
|
return $this->value;
|
|
|
|
} else {
|
|
|
|
$value = $value > $this->max ? $this->max : $value;
|
|
|
|
$this->value = $value;
|
|
|
|
$this->write( 0, 0, '[', false );
|
|
|
|
$width = $this->width - ( $this->show_pct ? 7 : 2 );
|
|
|
|
$width = $width >= 0 ? $width : 0;
|
|
|
|
$complete = floor( $width * $value / $this->max );
|
|
|
|
$this->write( 0, 1, str_repeat( '#', $complete ), false );
|
|
|
|
$this->write( 0, 1 + $complete, str_repeat( ' ', $width - $complete ), false );
|
|
|
|
$this->write( 0, $width + 1, ']', false );
|
|
|
|
if( $this->show_pct ) {
|
|
|
|
$this->write( 0, $width + 3, sprintf( '%3d%%', floor( $value / $this->max * 100 ) ), false );
|
|
|
|
}
|
|
|
|
ncurses_update_panels();
|
|
|
|
ncurses_doupdate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function max( $value = false ) {
|
|
|
|
if( $value === false ) {
|
|
|
|
return $this->max;
|
|
|
|
} else {
|
|
|
|
$this->max = $value > 0 ? $value : $this->max;
|
|
|
|
$this->pos( $this->value );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class NcTextInput extends NcWindow {
|
|
|
|
var $value = '';
|
|
|
|
var $active = false;
|
|
|
|
var $filter = false;
|
|
|
|
|
|
|
|
function __construct( &$parent, $width, $y, $x, $value = '', $filter = false ) {
|
|
|
|
parent::__construct( $parent, 1, $width, $y, $x, false );
|
|
|
|
$this->value = $value;
|
|
|
|
$this->filter = $filter !== false && @preg_match( $filter, '' ) !== false ? $filter : false;
|
|
|
|
$this->update();
|
|
|
|
}
|
|
|
|
function update() {
|
|
|
|
$this->attribute_on( NCURSES_A_UNDERLINE );
|
|
|
|
if( $this->active ) {
|
|
|
|
$this->attribute_on( NCURSES_A_REVERSE );
|
|
|
|
}
|
|
|
|
$this->write_fixed( 0, 0, substr( $this->value, - $this->width ) );
|
|
|
|
$this->attribute_off( NCURSES_A_UNDERLINE );
|
|
|
|
$this->attribute_off( NCURSES_A_REVERSE );
|
|
|
|
}
|
|
|
|
function value( $value = false ) {
|
|
|
|
if( $value === false ) {
|
|
|
|
return $this->value;
|
|
|
|
} else {
|
|
|
|
$this->value = $value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function get() {
|
|
|
|
$this->active = true;
|
|
|
|
$this->update();
|
|
|
|
while( $this->active ) {
|
|
|
|
$key = $this->get_char();
|
|
|
|
switch( $key ) {
|
|
|
|
case NCURSES_KEY_BACKSPACE:
|
|
|
|
$this->value = substr( $this->value, 0, strlen( $this->value ) - 1 );
|
|
|
|
break;
|
|
|
|
case 13:
|
|
|
|
$this->active = false;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if( in_array( $key, range( 32, 126 ) ) ) {
|
|
|
|
$this->value .= chr( $key );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$this->update();
|
|
|
|
}
|
|
|
|
$this->update();
|
|
|
|
return $this->filter !== false && @preg_match( $this->filter, $this->value ) < 1 ? false : $this->value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class NcTableView extends NcWindow {
|
|
|
|
var $columns;
|
|
|
|
var $records;
|
|
|
|
var $selected;
|
|
|
|
|
|
|
|
function __construct( &$parent, $height, $width, $y, $x, $params = array() ) {
|
|
|
|
parent::__construct( $parent, $height, $width, $y, $x );
|
|
|
|
$params = !is_array( $params ) ? array() : $params;
|
|
|
|
$this->columns = isset( $params['columns'] ) && is_array( $params['columns'] ) ? $params['columns'] : array();
|
|
|
|
$this->records = isset( $params['records'] ) && is_array( $params['records'] ) ? array_values( $params['records'] ) : array();
|
|
|
|
}
|
|
|
|
function update( $selected = 0 ) {
|
|
|
|
$selected = $selected >= 0 ? $selected : 0;
|
|
|
|
$selected = $selected < count( $this->records ) ? $selected : count( $this->records ) - 1;
|
|
|
|
$this->selected = $selected;
|
|
|
|
$cols = isset( $this->columns ) && is_array( $this->columns ) ? $this->columns : array();
|
|
|
|
if( count( $cols ) == 0 ) {
|
|
|
|
// If there's no columns defined, try and grab 'em from the keys from the first record
|
|
|
|
$record = $this->records[0];
|
|
|
|
$record = is_array( $record ) ? $record : array( $record );
|
|
|
|
foreach( array_keys( $record ) as $col ) {
|
|
|
|
$cols[$col] = $col;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$column_ids = array_keys( $cols );
|
|
|
|
$column_widths = $rows = array();
|
|
|
|
foreach( $cols as $id => $column ) {
|
|
|
|
$column_widths[$id] = strlen( $column );
|
|
|
|
}
|
|
|
|
foreach( $this->records as $id => $record ) {
|
|
|
|
$record = is_array( $record ) ? $record : array( $record );
|
|
|
|
$fields = array();
|
|
|
|
foreach( $column_ids as $col ) {
|
|
|
|
$field = isset( $record[$col] ) ? $record[$col] : '';
|
|
|
|
$field = is_scalar( $field ) ? $field : gettype( $field );
|
|
|
|
$fields[$col] = $field;
|
|
|
|
$column_widths[$col] = $column_widths[$col] < strlen( $field ) ? strlen( $field ) : $column_widths[$col];
|
|
|
|
}
|
|
|
|
$rows[] = $fields;
|
|
|
|
}
|
|
|
|
foreach( $cols as $id => $col ) {
|
|
|
|
$cols[$id] = $col . str_repeat( ' ', $column_widths[$id] - strlen( $col ) );
|
|
|
|
}
|
|
|
|
$this->attribute_on( NCURSES_A_UNDERLINE );
|
|
|
|
$this->attribute_on( NCURSES_A_BOLD );
|
|
|
|
$this->write_fixed( 0, 0, implode( ' | ', $cols ) );
|
|
|
|
$this->attribute_off( NCURSES_A_UNDERLINE );
|
|
|
|
$this->attribute_off( NCURSES_A_BOLD );
|
|
|
|
$max_items = ( $this->height - 2 );
|
|
|
|
$offset = ( $selected > $max_items ) ? $selected - $max_items : 0;
|
|
|
|
foreach( $rows as $id => $row ) {
|
|
|
|
if( $id < $offset ) {
|
|
|
|
continue;
|
|
|
|
} elseif( $id - $offset > $max_items ) {
|
|
|
|
// We've reached the maximum row height for this window
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
foreach( $row as $col => $field ) {
|
|
|
|
$row[$col] = $field . str_repeat( ' ', $column_widths[$col] - strlen( $field ) );
|
|
|
|
}
|
|
|
|
if( $selected == $id ) {
|
|
|
|
$this->attribute_on( NCURSES_A_REVERSE );
|
|
|
|
}
|
|
|
|
$this->write_fixed( $id - $offset + 1, 0, implode( ' | ', $row ) );
|
|
|
|
$this->attribute_off( NCURSES_A_REVERSE );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function load( $records ) {
|
|
|
|
if( !is_array( $records ) ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
$this->records = array_values( $records );
|
|
|
|
$this->update();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
?>
|