Added everything
This commit is contained in:
187
StatusBarManager.cpp
Normal file
187
StatusBarManager.cpp
Normal file
@@ -0,0 +1,187 @@
|
||||
#include "StatusBarManager.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
using std::cout;
|
||||
using std::flush;
|
||||
using std::string;
|
||||
|
||||
StatusBarManager::StatusBarManager()
|
||||
: m_is_started(false)
|
||||
{}
|
||||
|
||||
StatusBarManager::~StatusBarManager()
|
||||
{
|
||||
if(m_is_started)
|
||||
{
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
StatusBarManager::TermSize StatusBarManager::get_terminal_size()
|
||||
{
|
||||
struct winsize win;
|
||||
StatusBarManager::TermSize result = { 0, 0 };
|
||||
|
||||
if(ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
result.rows = win.ws_row;
|
||||
result.columns = win.ws_col;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void StatusBarManager::setup_terminal_scroll_area(int nr_rows)
|
||||
{
|
||||
int status_rows = m_progress_messages.size();
|
||||
if (nr_rows <= 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// scroll down a bit to avoid visual glitch when the screen
|
||||
// area shrinks by needed ammount of rows
|
||||
for (int i = 0; i < status_rows; ++i)
|
||||
{
|
||||
cout << std::endl;
|
||||
}
|
||||
|
||||
// save cursor
|
||||
cout << "\e7";
|
||||
|
||||
// set scroll region (this will place the cursor in the top left)
|
||||
cout << "\e[0;" << std::to_string(nr_rows - status_rows) << "r";
|
||||
|
||||
// restore cursor but ensure its inside the scrolling area
|
||||
cout << "\e8";
|
||||
cout << "\e[" << status_rows << "A";
|
||||
|
||||
// ensure its flushed
|
||||
flush(cout);
|
||||
|
||||
// Leftovers from apt
|
||||
#if 0
|
||||
// setup tty size to ensure xterm/linux console are working properly too
|
||||
// see bug #731738
|
||||
struct winsize win;
|
||||
if (ioctl(child_pty, TIOCGWINSZ, (char *)&win) != -1)
|
||||
{
|
||||
win.ws_row = nr_rows - 1;
|
||||
ioctl(child_pty, TIOCSWINSZ, (char *)&win);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void StatusBarManager::start()
|
||||
{
|
||||
if (!m_is_started)
|
||||
{
|
||||
int const nr_terminal_rows = get_terminal_size().rows;
|
||||
setup_terminal_scroll_area(nr_terminal_rows);
|
||||
m_is_started = true;
|
||||
}
|
||||
}
|
||||
|
||||
void StatusBarManager::stop()
|
||||
{
|
||||
if (m_is_started)
|
||||
{
|
||||
int const nr_terminal_rows = get_terminal_size().rows;
|
||||
if (nr_terminal_rows > 0)
|
||||
{
|
||||
setup_terminal_scroll_area(nr_terminal_rows + m_progress_messages.size());
|
||||
|
||||
// override the progress line (sledgehammer)
|
||||
static const char* clear_screen_below_cursor = "\e[J";
|
||||
cout << clear_screen_below_cursor;
|
||||
flush(cout);
|
||||
}
|
||||
|
||||
m_is_started = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool StatusBarManager::draw_status_line()
|
||||
{
|
||||
if (!m_is_started)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
StatusBarManager::TermSize const size = get_terminal_size();
|
||||
if (size.rows < 1 || size.columns < 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static string save_cursor = "\e7";
|
||||
static string restore_cursor = "\e8";
|
||||
|
||||
// green
|
||||
static string set_bg_color = "\e[42m";
|
||||
// black
|
||||
static string set_fg_color = "\e[30m";
|
||||
|
||||
static string restore_bg = "\e[49m";
|
||||
static string restore_fg = "\e[39m";
|
||||
|
||||
cout << save_cursor;
|
||||
|
||||
int status_rows = m_progress_messages.size();
|
||||
for (int i = 0; i < status_rows; ++i)
|
||||
{
|
||||
// move cursor position to current row
|
||||
cout << "\e[" << std::to_string(size.rows + 1 - status_rows + i) << ";0f"
|
||||
<< set_bg_color
|
||||
<< set_fg_color;
|
||||
if (nullptr != m_progress_messages[i])
|
||||
{
|
||||
cout << *(m_progress_messages[i]);
|
||||
}
|
||||
flush(cout);
|
||||
}
|
||||
|
||||
cout << restore_bg
|
||||
<< restore_fg;
|
||||
flush(cout);
|
||||
|
||||
// leftover progress-bar from apt
|
||||
#if 0
|
||||
// draw text progress bar
|
||||
int padding = 4;
|
||||
auto const progressbar_size = size.columns - padding - String::DisplayLength(progress_str);
|
||||
auto const current_percent = percentage / 100.0f;
|
||||
cout << " "
|
||||
<< GetTextProgressStr(current_percent, progressbar_size)
|
||||
<< " ";
|
||||
flush(cout);
|
||||
#endif
|
||||
|
||||
// restore
|
||||
cout << restore_cursor;
|
||||
flush(cout);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void StatusBarManager::add_progress_message(Progress* message)
|
||||
{
|
||||
if (message == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_progress_messages.push_back(message);
|
||||
}
|
||||
|
||||
void StatusBarManager::clear()
|
||||
{
|
||||
m_progress_messages.clear();
|
||||
}
|
||||
Reference in New Issue
Block a user