mirror of
https://github.com/Syllo/nvtop.git
synced 2026-04-22 15:08:12 -04:00
The interface layout selection has been updated to support the interface option. The interface option stores which data that needs to be plotted for each devices. The plot drawing code now supports the reverse plotting option. The interface uses the ring buffer, the updated version of the layout computation and plots the data specified by the interface options.
139 lines
4.9 KiB
C
139 lines
4.9 KiB
C
#include <string.h>
|
|
#include <tgmath.h>
|
|
|
|
#include "nvtop/plot.h"
|
|
|
|
static inline int data_level(double rows, double data, double increment) {
|
|
return (int)(rows - round(data / increment));
|
|
}
|
|
|
|
void nvtop_line_plot(WINDOW *win, size_t num_data, const double *data,
|
|
double min, double max, unsigned num_plots,
|
|
bool legend_left, char legend[4][PLOT_MAX_LEGEND_SIZE]) {
|
|
if (num_data == 0)
|
|
return;
|
|
int rows, cols;
|
|
getmaxyx(win, rows, cols);
|
|
rows -= 1; // Maximum drawable character
|
|
double increment = (max - min) / (double)(rows);
|
|
int low_data_level = data_level(0, min, increment);
|
|
for (size_t k = 0; k < num_plots; ++k) {
|
|
int level_previous = data_level(rows, data[k], increment) - low_data_level;
|
|
int level_next, level_current;
|
|
wattron(win, COLOR_PAIR(1 + k % 5));
|
|
for (size_t i = k; i < num_data || i < (size_t)cols; i += num_plots) {
|
|
level_next = i + num_plots >= num_data
|
|
? level_next
|
|
: data_level(rows, data[i + num_plots], increment) -
|
|
low_data_level;
|
|
level_current = data_level(rows, data[i], increment) - low_data_level;
|
|
int top, bottom;
|
|
if (level_current == level_previous) {
|
|
mvwaddch(win, level_current, i, ACS_HLINE);
|
|
top = bottom = level_current;
|
|
} else {
|
|
if (level_current < level_previous) {
|
|
top = level_previous;
|
|
bottom = level_current;
|
|
} else {
|
|
top = level_current;
|
|
bottom = level_previous;
|
|
}
|
|
for (int j = bottom + 1; j < top; j++) {
|
|
mvwaddch(win, j, i, ACS_VLINE);
|
|
}
|
|
if (level_current > level_previous) {
|
|
mvwaddch(win, level_current, i, ACS_LLCORNER);
|
|
mvwaddch(win, level_previous, i, ACS_URCORNER);
|
|
} else {
|
|
mvwaddch(win, level_current, i, ACS_ULCORNER);
|
|
mvwaddch(win, level_previous, i, ACS_LRCORNER);
|
|
}
|
|
}
|
|
for (unsigned j = 0; j < num_plots; ++j) {
|
|
if (j == k)
|
|
continue;
|
|
int cross_level = -low_data_level;
|
|
if (j < k || i + j < num_plots + k)
|
|
cross_level += data_level(rows, data[i - k + j], increment);
|
|
else
|
|
cross_level +=
|
|
data_level(rows, data[i - k + j - num_plots], increment);
|
|
if (cross_level == top && top == bottom)
|
|
continue;
|
|
|
|
if (cross_level > bottom && cross_level < top) {
|
|
mvwaddch(win, cross_level, i, ACS_PLUS);
|
|
} else {
|
|
if (cross_level == top) {
|
|
mvwaddch(win, cross_level, i, ACS_BTEE);
|
|
} else {
|
|
if (cross_level == bottom) {
|
|
mvwaddch(win, cross_level, i, ACS_TTEE);
|
|
} else {
|
|
wattroff(win, COLOR_PAIR(1 + k % 5));
|
|
wattron(win, COLOR_PAIR(1 + j % 5));
|
|
mvwaddch(win, cross_level, i, ACS_HLINE);
|
|
wattroff(win, COLOR_PAIR(1 + j % 5));
|
|
wattron(win, COLOR_PAIR(1 + k % 5));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
level_previous = level_current;
|
|
}
|
|
wattroff(win, COLOR_PAIR(1 + k % 5));
|
|
}
|
|
int plot_y_position = 0;
|
|
for (unsigned i = 0; i < num_plots && plot_y_position < rows; ++i) {
|
|
if (legend[i]) {
|
|
wattron(win, COLOR_PAIR(1 + i % 5));
|
|
if (legend_left) {
|
|
mvwprintw(win, plot_y_position, 0, "%.*s", cols, legend[i]);
|
|
} else {
|
|
size_t length = strlen(legend[i]);
|
|
if (length <= (size_t)cols) {
|
|
mvwprintw(win, plot_y_position, cols - length, "%s", legend[i]);
|
|
} else {
|
|
mvwprintw(win, plot_y_position, 0, "%.*s", length - cols, legend[i]);
|
|
}
|
|
}
|
|
wattroff(win, COLOR_PAIR(1 + i % 5));
|
|
plot_y_position++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void nvtop_bar_plot(WINDOW *win, size_t num_data, const double *data,
|
|
double min, double max) {
|
|
if (num_data == 0)
|
|
return;
|
|
int rows, cols;
|
|
getmaxyx(win, rows, cols);
|
|
rows -= 1;
|
|
double increment = (max - min) / (double)(rows);
|
|
int low_data_level = data_level(0, min, increment);
|
|
for (size_t i = 0; i < num_data || i < (size_t)cols; ++i) {
|
|
for (int j = data_level(rows, data[i], increment) - low_data_level;
|
|
j <= rows; j++) {
|
|
mvwaddch(win, j, i, ACS_CKBOARD);
|
|
}
|
|
}
|
|
}
|
|
|
|
void draw_rectangle(WINDOW *win, unsigned startX, unsigned startY,
|
|
unsigned sizeX, unsigned sizeY) {
|
|
for (unsigned i = 0; i < sizeX - 2; ++i) {
|
|
mvwaddch(win, startY, startX + 1 + i, ACS_HLINE);
|
|
mvwaddch(win, startY + sizeY - 1, startX + 1 + i, ACS_HLINE);
|
|
}
|
|
for (unsigned i = 0; i < sizeY - 2; ++i) {
|
|
mvwaddch(win, startY + 1 + i, startX, ACS_VLINE);
|
|
mvwaddch(win, startY + 1 + i, startX + sizeX - 1, ACS_VLINE);
|
|
}
|
|
mvwaddch(win, startY, startX, ACS_ULCORNER);
|
|
mvwaddch(win, startY, startX + sizeX - 1, ACS_URCORNER);
|
|
mvwaddch(win, startY + sizeY - 1, startX, ACS_LLCORNER);
|
|
mvwaddch(win, startY + sizeY - 1, startX + sizeX - 1, ACS_LRCORNER);
|
|
}
|