22
+ − 1
<?php
+ − 2
+ − 3
/**
+ − 4
* Class for drawing progress bars in a vt100 console.
+ − 5
* @author Dan Fuhry
+ − 6
* @license Public domain
+ − 7
*/
+ − 8
+ − 9
class ProgressBar
+ − 10
{
+ − 11
/**
+ − 12
* Shell escape character.
+ − 13
* @const string
+ − 14
*/
+ − 15
+ − 16
const SHELL_ESCAPE = "\x1B";
+ − 17
+ − 18
/**
+ − 19
* Carriage return (0x0D)
+ − 20
* @const string
+ − 21
*/
+ − 22
+ − 23
const CARRIAGE_RETURN = "\r";
+ − 24
+ − 25
/**
+ − 26
* Colors of the foreground, background, foreground text, and background text, respectively
+ − 27
* @var int
+ − 28
* @var int
+ − 29
* @var int
+ − 30
* @var int
+ − 31
*/
+ − 32
+ − 33
private $color_bar, $color_empty, $color_text, $color_emptytext;
+ − 34
+ − 35
/**
+ − 36
* Text to the left of the bar.
+ − 37
* @var string
+ − 38
*/
+ − 39
+ − 40
private $bar_left;
+ − 41
+ − 42
/**
+ − 43
* Text to the right of the bar.
+ − 44
* @var string
+ − 45
*/
+ − 46
+ − 47
private $bar_right;
+ − 48
+ − 49
/**
+ − 50
* Text in the middle of the bar.
+ − 51
* @var string
+ − 52
*/
+ − 53
+ − 54
private $bar_text;
+ − 55
+ − 56
/**
+ − 57
* The current location of the bar in %.
+ − 58
* @var int
+ − 59
*/
+ − 60
+ − 61
private $bar_pos = 0;
+ − 62
+ − 63
/**
+ − 64
* Position where the text should start.
+ − 65
* @var int
+ − 66
*/
+ − 67
+ − 68
private $text_pos = 0;
+ − 69
+ − 70
/**
+ − 71
* Width of the current terminal.
+ − 72
* @var int
+ − 73
*/
+ − 74
+ − 75
private $term_width = 80;
+ − 76
+ − 77
/**
+ − 78
* Width of the actual bar.
+ − 79
* @var int
+ − 80
*/
+ − 81
+ − 82
private $bar_width = 0;
+ − 83
+ − 84
/**
+ − 85
* State of the bar's color. Used to avoid echoing tons of color codes.
+ − 86
* @var int
+ − 87
*/
+ − 88
+ − 89
private $color_state = 0;
+ − 90
+ − 91
/**
+ − 92
* Color state constants
+ − 93
* @const int
+ − 94
* @const int
+ − 95
* @const int
+ − 96
* @const int
+ − 97
* @const int
+ − 98
*/
+ − 99
+ − 100
const COLOR_STATE_RESET = 0;
+ − 101
const COLOR_STATE_FULL_HIDE = 1;
+ − 102
const COLOR_STATE_FULL_SHOW = 2;
+ − 103
const COLOR_STATE_EMPTY_HIDE = 3;
+ − 104
const COLOR_STATE_EMPTY_SHOW = 4;
+ − 105
+ − 106
/**
+ − 107
* Constructor. All parameters are optional. Color choices are defined in color_to_code.
+ − 108
* @param string $bar_left
+ − 109
* @param string $bar_right
+ − 110
* @param string $bar_text
+ − 111
* @param string $color_bar
+ − 112
* @param string $color_empty
+ − 113
* @param string $color_text
+ − 114
* @param string $color_emptytext
+ − 115
*/
+ − 116
+ − 117
public function __construct($bar_left = '[', $bar_right = ']', $bar_text = '', $color_bar = 'red', $color_empty = 'black', $color_text = 'white', $color_emptytext = 'cyan')
+ − 118
{
+ − 119
$this->bar_left = $bar_left;
+ − 120
$this->bar_right = $bar_right;
+ − 121
$this->color_bar = $this->color_to_code($color_bar);
+ − 122
$this->color_empty = $this->color_to_code($color_empty);
+ − 123
$this->color_text = $this->color_to_code($color_text);
+ − 124
$this->color_emptytext = $this->color_to_code($color_emptytext);
+ − 125
+ − 126
if ( isset($_SERVER['COLUMNS']) )
+ − 127
{
+ − 128
$this->term_width = intval($_SERVER['COLUMNS']);
+ − 129
}
+ − 130
$this->bar_width = $this->term_width - strlen($this->bar_left) - strlen($this->bar_right);
+ − 131
+ − 132
$this->update_text_quiet($bar_text);
+ − 133
}
+ − 134
+ − 135
/**
+ − 136
* Updates the text on the progress bar and recalculates the position without redrawing.
+ − 137
* @param string Text in the bar. If omitted, blanked.
+ − 138
*/
+ − 139
+ − 140
public function update_text_quiet($bar_text = '')
+ − 141
{
+ − 142
$this->bar_text = strval($bar_text);
+ − 143
+ − 144
if ( !empty($this->bar_text) )
+ − 145
{
+ − 146
$this->text_pos = round(( $this->bar_width / 2 ) - ( strlen($this->bar_text) / 2 ));
+ − 147
}
+ − 148
}
+ − 149
+ − 150
/**
+ − 151
* Updates the text on the progress bar, recalculates the position, and redraws.
+ − 152
* @param string Text in the bar. If omitted, blanked.
+ − 153
*/
+ − 154
+ − 155
function update_text($bar_text = '')
+ − 156
{
+ − 157
$this->update_text_quiet($bar_text);
+ − 158
$this->set($this->bar_pos);
+ − 159
}
+ − 160
+ − 161
/**
+ − 162
* Starts output of the bar.
+ − 163
*/
+ − 164
+ − 165
function start()
+ − 166
{
+ − 167
echo self::CARRIAGE_RETURN;
+ − 168
echo $this->bar_left;
+ − 169
}
+ − 170
+ − 171
/**
+ − 172
* Closes the bar.
+ − 173
*/
+ − 174
+ − 175
function end()
+ − 176
{
+ − 177
$this->set($this->bar_pos, $this->bar_width);
+ − 178
echo "\n";
+ − 179
}
+ − 180
+ − 181
/**
+ − 182
* Sets the position of the bar.
+ − 183
* @param int Position in %. If a second parameter is set, this is treated as a numerator with the second parameter being the denominator and that is used to calculate position.
+ − 184
* @param int Optional. Total number of units to allow fraction usage instead of percentage.
+ − 185
*/
+ − 186
+ − 187
function set($pos, $max = 100)
+ − 188
{
+ − 189
// if our pos is higher than 100%, reduce it
+ − 190
if ( $pos > $max )
+ − 191
$pos = $max;
+ − 192
+ − 193
// arithmetic one-liner
+ − 194
// this is where we should stop showing the "full" color and instead use "empty"
+ − 195
$bar_pos = round($this->bar_width * ( $pos / $max ));
+ − 196
$this->bar_pos = 100 * ( $pos / $max );
+ − 197
+ − 198
// reset the cursor
+ − 199
echo self::CARRIAGE_RETURN . $this->bar_left;
+ − 200
+ − 201
// print everything out
+ − 202
for ( $i = 0; $i < $this->bar_width; $i++ )
+ − 203
{
+ − 204
$char = ' ';
+ − 205
$hide = true;
+ − 206
if ( !empty($this->bar_text) )
+ − 207
{
+ − 208
// we have some text to display in the middle; see where we are.
+ − 209
$show_text = ( $i >= $this->text_pos && $i < ( $this->text_pos + strlen($this->bar_text) ) );
+ − 210
if ( $show_text )
+ − 211
{
+ − 212
$char = substr($this->bar_text, $i - $this->text_pos, 1);
+ − 213
if ( strlen($char) < 1 )
+ − 214
$char = ' ';
+ − 215
else
+ − 216
$hide = false;
+ − 217
}
+ − 218
}
+ − 219
// determine color
+ − 220
if ( $i > $bar_pos )
+ − 221
{
+ − 222
$hide ? $this->set_color_empty_hide() : $this->set_color_empty_show();
+ − 223
}
+ − 224
else
+ − 225
{
+ − 226
$hide ? $this->set_color_full_hide() : $this->set_color_full_show();
+ − 227
}
+ − 228
echo $char;
+ − 229
}
+ − 230
$this->set_color_reset();
+ − 231
echo $this->bar_right;
+ − 232
}
+ − 233
+ − 234
#
+ − 235
# PRIVATE METHODS
+ − 236
#
+ − 237
+ − 238
function set_color_full_hide()
+ − 239
{
+ − 240
if ( $this->color_state == self::COLOR_STATE_FULL_HIDE )
+ − 241
return;
+ − 242
$this->color_state = self::COLOR_STATE_FULL_HIDE;
+ − 243
+ − 244
$fgcolor = 30 + $this->color_bar;
+ − 245
$bgcolor = $fgcolor + 10;
+ − 246
echo self::SHELL_ESCAPE . "[0;{$fgcolor};{$bgcolor};8m";
+ − 247
}
+ − 248
+ − 249
function set_color_full_show()
+ − 250
{
+ − 251
if ( $this->color_state == self::COLOR_STATE_FULL_SHOW )
+ − 252
return;
+ − 253
$this->color_state = self::COLOR_STATE_FULL_SHOW;
+ − 254
+ − 255
$fgcolor = 30 + $this->color_text;
+ − 256
$bgcolor = 40 + $this->color_bar;
+ − 257
echo self::SHELL_ESCAPE . "[0;1;{$fgcolor};{$bgcolor}m";
+ − 258
}
+ − 259
+ − 260
function set_color_empty_hide()
+ − 261
{
+ − 262
if ( $this->color_state == self::COLOR_STATE_EMPTY_HIDE )
+ − 263
return;
+ − 264
$this->color_state = self::COLOR_STATE_EMPTY_HIDE;
+ − 265
+ − 266
$fgcolor = 30 + $this->color_empty;
+ − 267
$bgcolor = $fgcolor + 10;
+ − 268
echo self::SHELL_ESCAPE . "[0;{$fgcolor};{$bgcolor};8m";
+ − 269
}
+ − 270
+ − 271
function set_color_empty_show()
+ − 272
{
+ − 273
if ( $this->color_state == self::COLOR_STATE_EMPTY_SHOW )
+ − 274
return;
+ − 275
$this->color_state = self::COLOR_STATE_EMPTY_SHOW;
+ − 276
+ − 277
$fgcolor = 30 + $this->color_emptytext;
+ − 278
$bgcolor = 40 + $this->color_empty;
+ − 279
echo self::SHELL_ESCAPE . "[0;1;{$fgcolor};{$bgcolor}m";
+ − 280
}
+ − 281
+ − 282
function set_color_reset()
+ − 283
{
+ − 284
if ( $this->color_state == self::COLOR_STATE_RESET )
+ − 285
return;
+ − 286
$this->color_state = self::COLOR_STATE_RESET;
+ − 287
+ − 288
echo self::SHELL_ESCAPE . "[0m";
+ − 289
}
+ − 290
+ − 291
/**
+ − 292
* Converts a color name to an ASCII color code. Valid color names are black, red, green, yellow, blue, magenta, cyan, and white.
+ − 293
* @param string Color name
+ − 294
* @return int
+ − 295
*/
+ − 296
+ − 297
private function color_to_code($color)
+ − 298
{
+ − 299
static $colors = array(
+ − 300
'black' => 0,
+ − 301
'red' => 1,
+ − 302
'green' => 2,
+ − 303
'yellow' => 3,
+ − 304
'blue' => 4,
+ − 305
'magenta' => 5,
+ − 306
'cyan' => 6,
+ − 307
'white' => 7
+ − 308
);
+ − 309
return ( isset($colors[$color]) ) ? $colors[$color] : $colors['white'];
+ − 310
}
+ − 311
}