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; $x = $x < 0 ? $this->width + $x: $x; $lines = preg_split( '/\r?(\n|\r)/', $text ); foreach( $lines as $id => $line ) { 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; } } ?>