summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManos Pitsidianakis <el13635@mail.ntua.gr>2019-10-25 22:20:15 +0300
committerManos Pitsidianakis <el13635@mail.ntua.gr>2019-10-25 22:20:15 +0300
commit3b5ca78b01c6fa2103f267a8174eb835fa7d84b2 (patch)
treec3d1d7ee38210147cfb9a93a4739bd4ca52a033f
parent59190550b93840d8d19d96b86dc0a2749ee617c7 (diff)
Distribute cpu bars evenly
-rw-r--r--src/ui/components/kernel.rs340
1 files changed, 219 insertions, 121 deletions
diff --git a/src/ui/components/kernel.rs b/src/ui/components/kernel.rs
index 2534192..1a2bbd0 100644
--- a/src/ui/components/kernel.rs
+++ b/src/ui/components/kernel.rs
@@ -24,6 +24,8 @@ use std::fs::File;
use std::io::prelude::*;
use std::str::FromStr;
+/* if cpu_no > MAX_CPU_ROWS, the cpu bars wrap in columns */
+static MAX_CPU_ROWS: usize = 5;
/* Kernel metrics components */
#[derive(Debug)]
pub struct KernelMetrics {
@@ -65,113 +67,68 @@ impl KernelMetrics {
dirty: true,
}
}
-}
-impl Component for KernelMetrics {
- fn draw(
- &mut self,
- grid: &mut CellBuffer,
- area: Area,
- dirty_areas: &mut VecDeque<Area>,
- tick: bool,
- ) {
- if !is_valid_area!(area) {
- return;
- }
+ /* Returns width of entire widget */
+ fn draw_cpu_bars(&mut self, grid: &mut CellBuffer, area: Area) -> usize {
let upper_left = upper_left!(area);
- let bottom_right = bottom_right!(area);
- let total_rows = height!(area);
let total_cols = width!(area);
-
- let show_all_cores: bool = total_rows > 1 /* hostname, kernel version, uptime row */ + 1 /* CPU total bar row */ + 0 /* padding rows */ + 1 /* RAM row */;
- dirty_areas.push_back(area);
- if self.dirty {
- clear_area(grid, area);
- let (x, y) = write_string_to_grid(
- &self.hostname,
- grid,
- Color::Default,
- Color::Default,
- Attr::Bold,
- area,
- false,
- );
- let (x, y) = write_string_to_grid(
- &self.os_type,
- grid,
- Color::Default,
- Color::Default,
- Attr::Default,
- ((x + 2, y), bottom_right),
- false,
- );
- write_string_to_grid(
- &self.kernel,
- grid,
- Color::Default,
- Color::Default,
- Attr::Default,
- ((x + 2, y), bottom_right),
- false,
- );
- self.dirty = false;
+ /* no of bars is no of CPUs along with the total CPU usage */
+ let cpu_no = self.cpu_stat.len();
+
+ /* Calculate how much horizontal space the labels (ie CPU0, CPU1, CPU2) take in order to
+ * distribute the remainder for each column, specifically the bars */
+ let mut cpu_label_space = 0;
+ let mut cpu_bar_columns = 0;
+ let mut i = 0;
+ while i < cpu_no {
+ /* Reserve space for CPU labels */
+ if i < 10 {
+ /* label will be " CPU0 " */
+ cpu_label_space += 7;
+ } else if i < 100 {
+ /* label will be " CPU32 " */
+ cpu_label_space += 8;
+ } else {
+ /* label will be " CPU128 " */
+ cpu_label_space += 9;
+ }
+ /* each column holds MAX_CPU_ROWS */
+ i += MAX_CPU_ROWS;
+ cpu_bar_columns += 1;
}
-
- /* Draw uptime */
- let mut file = File::open("/proc/uptime").unwrap();
- self.uptime.clear();
- file.read_to_string(&mut self.uptime).unwrap();
- let seconds: usize =
- f64::from_str(self.uptime.split(" ").next().unwrap()).unwrap() as usize;
- let days = seconds / (60 * 60 * 24);
- let hours = seconds / 3600 - days * 24;
- let mins = seconds / 60 - hours * 60 - days * 24 * 60;
- let seconds = seconds % 60;
- let uptime = if days > 0 {
- format!(
- "uptime: {} days, {:02}:{:02}:{:02}",
- days, hours, mins, seconds
- )
+ /* max width of each cpu bar */
+ let bar_width = if cpu_no < MAX_CPU_ROWS {
+ total_cols
} else {
- format!("uptime: {:02}:{:02}:{:02}", hours, mins, seconds)
+ (total_cols - cpu_label_space) / (cpu_bar_columns)
};
- write_string_to_grid(
- &uptime,
- grid,
- Color::Default,
- Color::Default,
- Attr::Default,
- (
- (get_x(bottom_right) - uptime.len(), get_y(upper_left)),
- bottom_right,
- ),
- false,
- );
-
- let mut y_offset = 2;
-
- if !tick {
- return;
- }
- /* Draw CPU usage bars */
-
- let bar_max = std::cmp::min((0.6 * total_cols as f32) as usize, total_cols);
-
- let old_cpu_stat = self.cpu_stat[0];
let mut boot_time: usize = 0;
+
+ let mut x_offset = 0;
for (i, cpu_stat) in get_stat(&mut boot_time).into_iter().enumerate() {
+ let label_len = if i < 10 {
+ 8
+ } else if i < 100 {
+ 9
+ } else {
+ 10
+ };
+ let bottom_right = pos_inc(
+ upper_left,
+ (x_offset + bar_width + label_len, i % MAX_CPU_ROWS + 2),
+ );
let (mut x, y) = if i > 0 {
- if !show_all_cores {
- break;
- }
write_string_to_grid(
&format!("CPU{}", i),
grid,
Color::Default,
Color::Default,
Attr::Bold,
- (pos_inc(upper_left, (2, 2 + i)), bottom_right),
+ (
+ pos_inc(upper_left, (x_offset, 2 + (i % MAX_CPU_ROWS))),
+ bottom_right,
+ ),
false,
)
} else {
@@ -182,7 +139,10 @@ impl Component for KernelMetrics {
Color::Default,
Color::Default,
Attr::Default,
- (pos_inc(upper_left, (2, 2 + i)), bottom_right),
+ (
+ pos_inc(upper_left, (x_offset, 2 + i % MAX_CPU_ROWS)),
+ bottom_right,
+ ),
false,
);
write_string_to_grid(
@@ -207,60 +167,107 @@ impl Component for KernelMetrics {
/ (cpu_stat
.total_time()
.saturating_sub(self.cpu_stat[i].total_time())) as f64)
- * bar_max as f64) as usize;
+ * bar_width as f64) as usize;
if bar_length >= width!(area) {
- return;
+ return x_offset;
}
- let mut x_offset = 0;
- while x_offset < bar_length {
+ /* Sometimes you draw the bar */
+ let mut _x_offset = 0;
+ while _x_offset < bar_length {
write_string_to_grid(
"▁",
grid,
Color::Byte(235),
Color::Byte(240),
Attr::Default,
- ((x + x_offset, y), bottom_right),
+ ((x + _x_offset, y), bottom_right),
false,
);
- x_offset += 1;
+ _x_offset += 1;
}
- while x_offset < bar_max {
+ /* and sometimes the bar draws you */
+ while _x_offset <= bar_width {
write_string_to_grid(
"▁",
grid,
Color::Byte(236),
Color::Byte(235),
Attr::Default,
- ((x + x_offset, y), bottom_right),
+ ((x + _x_offset, y), bottom_right),
false,
);
- x_offset += 1;
+ _x_offset += 1;
}
self.cpu_stat[i] = cpu_stat;
- y_offset += 1;
+ if (i + 1) % MAX_CPU_ROWS == 0 {
+ x_offset += bar_width + label_len;
+ }
}
- self.boot_time = boot_time;
- /* Draw RAM usage bar */
+ self.boot_time = boot_time;
+ if (self.cpu_stat.len()) % MAX_CPU_ROWS == 0 {
+ x_offset
+ } else {
+ x_offset
+ + bar_width
+ + if self.cpu_stat.len() < 10 {
+ 8
+ } else if self.cpu_stat.len() < 100 {
+ 9
+ } else {
+ 10
+ }
+ }
+ }
- let bar_max = bar_max + 6;
+ fn draw_ram_bar(&mut self, grid: &mut CellBuffer, area: Area, bars_max: usize) {
+ let upper_left = upper_left!(area);
+ let bottom_right = bottom_right!(area);
+ if bars_max == 0 {
+ /* In first draw, we have no cpu data since there is no previous measurement to use
+ * in the calculation so bars_max will be 0 */
+ return;
+ }
let (available, total) = get_mem_info();
- let available_length = ((available as f64 / total as f64) * bar_max as f64) as usize;
- let mem_bar_length = bar_max - available_length;
+
+ /* available_length == the length the spaces takes up in this case:
+ * |******** | 50%
+ */
+ let available_length = ((available as f64 / total as f64) * bars_max as f64) as usize;
+ /* mem_bar length == the length the asterisks takes up in this case:
+ * |******** | 50%
+ */
+ let mem_bar_length = bars_max - available_length;
let mem_display = format!(
"RAM {}/{}",
Bytes((total - available) * 1024).as_convenient_string(),
Bytes(total * 1024).as_convenient_string()
);
- let mem_display_padding = bar_max.saturating_sub(mem_display.len()) / 2;
+ /* Put the "RAM XGB/YGB" in the middle of the RAM bar */
+ let mem_display_padding = bars_max.saturating_sub(mem_display.len()) / 2;
+ let y_offset = 2 + MAX_CPU_ROWS;
let mut x = 0;
/* Calculate spillover of mem_display string to available part of the bar in order to
- * paint it differently */
+ * paint it differently
+ *
+ * If "RAM 1GB/2GB" is printed over this bar:
+ *
+ * |********** |
+ *
+ * Some part of the string will have different colors than the rest of it, because the
+ * available part of the bar has different colors.
+ *
+ * cutoff
+ * ⇩
+ * RAM 1GB/2GB
+ * ↓ ↓ ↓ ↓ ↓ ↓ (string overlays asterisks and spaces)
+ * |********** |
+ * */
let cutoff = std::cmp::min(
- mem_display.len() - 1,
+ mem_display.len(),
if mem_display_padding + mem_display.len() > mem_bar_length {
mem_bar_length - mem_display_padding
} else {
@@ -268,7 +275,7 @@ impl Component for KernelMetrics {
},
);
- while x < mem_bar_length {
+ while x <= available_length + mem_bar_length {
if x == mem_display_padding {
let (_x, _) = write_string_to_grid(
&mem_display[0..cutoff],
@@ -293,7 +300,7 @@ impl Component for KernelMetrics {
x += 1;
}
}
- let x = if cutoff != mem_display.len() {
+ if cutoff != mem_display.len() {
let (_x, _) = write_string_to_grid(
&mem_display[cutoff..],
grid,
@@ -303,27 +310,117 @@ impl Component for KernelMetrics {
(pos_inc(upper_left, (x + 2, y_offset)), bottom_right),
false,
);
- _x
- } else {
- x
- };
- for x in x..bar_max {
+ }
+ }
+}
+
+impl Component for KernelMetrics {
+ fn draw(
+ &mut self,
+ grid: &mut CellBuffer,
+ area: Area,
+ dirty_areas: &mut VecDeque<Area>,
+ tick: bool,
+ ) {
+ if !is_valid_area!(area) {
+ return;
+ }
+ let upper_left = upper_left!(area);
+ let bottom_right = bottom_right!(area);
+ let total_cols = width!(area);
+
+ dirty_areas.push_back(area);
+ if self.dirty {
+ clear_area(grid, area);
+ let (x, y) = write_string_to_grid(
+ &self.hostname,
+ grid,
+ Color::Default,
+ Color::Default,
+ Attr::Bold,
+ area,
+ false,
+ );
+ let (x, y) = write_string_to_grid(
+ &self.os_type,
+ grid,
+ Color::Default,
+ Color::Default,
+ Attr::Default,
+ ((x + 2, y), bottom_right),
+ false,
+ );
write_string_to_grid(
- " ",
+ &self.kernel,
grid,
Color::Default,
- Color::Byte(235),
+ Color::Default,
Attr::Default,
- (pos_inc(upper_left, (x + 2, y_offset)), bottom_right),
+ ((x + 2, y), bottom_right),
false,
);
+ self.dirty = false;
}
+ /* Draw uptime */
+ let mut file = File::open("/proc/uptime").unwrap();
+ self.uptime.clear();
+ file.read_to_string(&mut self.uptime).unwrap();
+ let seconds: usize =
+ f64::from_str(self.uptime.split(" ").next().unwrap()).unwrap() as usize;
+ let days = seconds / (60 * 60 * 24);
+ let hours = seconds / 3600 - days * 24;
+ let mins = seconds / 60 - hours * 60 - days * 24 * 60;
+ let seconds = seconds % 60;
+ let uptime = if days > 0 {
+ format!(
+ "uptime: {} days, {:02}:{:02}:{:02}",
+ days, hours, mins, seconds
+ )
+ } else {
+ format!("uptime: {:02}:{:02}:{:02}", hours, mins, seconds)
+ };
+
+ write_string_to_grid(
+ &uptime,
+ grid,
+ Color::Default,
+ Color::Default,
+ Attr::Default,
+ (
+ (get_x(bottom_right) - uptime.len(), get_y(upper_left)),
+ bottom_right,
+ ),
+ false,
+ );
+
+ if !tick {
+ return;
+ }
+ let old_cpu_stat = self.cpu_stat[0];
+
+ /* Draw CPU usage bars */
+
+ /* max width of cpu bar area */
+ let bars_max = (0.6 * total_cols as f32) as usize;
+ let cpu_widget_width = self.draw_cpu_bars(
+ grid,
+ (
+ pos_inc(upper_left, (2, 0)),
+ pos_inc(upper_left, (bars_max + 1, MAX_CPU_ROWS + 1)),
+ ),
+ );
+ /* Draw RAM usage bar */
+
+ self.draw_ram_bar(grid, area, cpu_widget_width.saturating_sub(2));
/* Various values table */
+ /* max width of cpu bar area */
+ let bars_max = (0.6 * total_cols as f32) as usize;
/* CPU Times */
let mut cpu_column_width = "CPU".len();
- let upper_left = pos_inc(upper_left, (bar_max + 5, 2));
+ let upper_left = pos_inc(upper_left, (bars_max + 5, 2));
+ clear_area(grid, (upper_left, bottom_right));
if get_x(upper_left) >= get_x(bottom_right) {
return;
}
@@ -336,6 +433,7 @@ impl Component for KernelMetrics {
(upper_left, bottom_right),
false,
);
+
for (i, (tag, s, fg_color, bg_color)) in get_cpu_times(&old_cpu_stat, &self.cpu_stat[0])
.into_iter()
.enumerate()