Skip to content

Commit

Permalink
Add option to set a position of legend
Browse files Browse the repository at this point in the history
  • Loading branch information
lyuha committed Mar 30, 2024
1 parent 2ee0df1 commit 2f9d17b
Show file tree
Hide file tree
Showing 10 changed files with 147 additions and 12 deletions.
14 changes: 8 additions & 6 deletions docs/content/configuration/command-line-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,17 @@ see information on these options by running `btm -h`, or run `btm --help` to dis
| ----------------------- | --------------------------------------------------------- |
| `--enable_cache_memory` | Enable collecting and displaying cache and buffer memory. |
| `--mem_as_value` | Defaults to showing process memory usage by value. |
| `--memory_legend` | Determine where render a legend of the memory widget |

## Network Options

| Option | Behaviour |
| ----------------------------- | ------------------------------------------------- |
| `--network_use_binary_prefix` | Displays the network widget with binary prefixes. |
| `--network_use_bytes` | Displays the network widget using bytes. |
| `--network_use_log` | Displays the network widget with a log scale. |
| `--use_old_network_legend` | DEPRECATED - uses a separate network legend. |
| Option | Behaviour |
| ----------------------------- | ----------------------------------------------------- |
| `--network_use_binary_prefix` | Displays the network widget with binary prefixes. |
| `--network_use_bytes` | Displays the network widget using bytes. |
| `--network_use_log` | Displays the network widget with a log scale. |
| `--network_legend` | Determine where render a legend of the network widget. |
| `--use_old_network_legend` | DEPRECATED - uses a separate network legend. |

## Battery Options

Expand Down
3 changes: 3 additions & 0 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub use states::*;
use unicode_segmentation::{GraphemeCursor, UnicodeSegmentation};

use crate::{
canvas::components::time_chart::LegendPosition,
constants,
data_collection::temperature,
data_conversion::ConvertedData,
Expand Down Expand Up @@ -62,8 +63,10 @@ pub struct AppConfigFields {
pub enable_cache_memory: bool,
pub show_table_scroll_position: bool,
pub is_advanced_kill: bool,
pub memory_legend_position: Option<LegendPosition>,
// TODO: Remove these, move network details state-side.
pub network_unit_type: DataUnit,
pub network_legend_position: Option<LegendPosition>,
pub network_scale_type: AxisScaling,
pub network_use_binary_prefix: bool,
pub retention_ms: u64,
Expand Down
9 changes: 8 additions & 1 deletion src/canvas/components/time_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ use tui::{
};
use unicode_segmentation::UnicodeSegmentation;

use super::time_chart::{Axis, Dataset, Point, TimeChart, DEFAULT_LEGEND_CONSTRAINTS};
use super::time_chart::{
Axis, Dataset, LegendPosition, Point, TimeChart, DEFAULT_LEGEND_CONSTRAINTS,
};

/// Represents the data required by the [`TimeGraph`].
pub struct GraphData<'a> {
Expand Down Expand Up @@ -48,6 +50,9 @@ pub struct TimeGraph<'a> {
/// The title style.
pub title_style: Style,

/// The legend position.
pub legend_position: Option<LegendPosition>,

/// Any legend constraints.
pub legend_constraints: Option<(Constraint, Constraint)>,

Expand Down Expand Up @@ -142,6 +147,7 @@ impl<'a> TimeGraph<'a> {
.y_axis(y_axis)
.marker(self.marker)
.legend_style(self.graph_style)
.legend_position(self.legend_position)
.hidden_legend_constraints(
self.legend_constraints
.unwrap_or(DEFAULT_LEGEND_CONSTRAINTS),
Expand Down Expand Up @@ -202,6 +208,7 @@ mod test {
border_style: Style::default().fg(Color::Blue),
is_expanded: false,
title_style: Style::default().fg(Color::Cyan),
legend_position: None,
legend_constraints: None,
marker: Marker::Braille,
}
Expand Down
24 changes: 22 additions & 2 deletions src/canvas/components/tui_widget/time_chart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
mod canvas;
mod points;

use std::cmp::max;
use std::{cmp::max, str::FromStr};

use canvas::*;
use tui::{
Expand Down Expand Up @@ -122,7 +122,6 @@ pub enum LegendPosition {
/// Legend is in the bottom-left corner
BottomLeft,
}

impl LegendPosition {
fn layout(
&self, area: Rect, legend_width: u16, legend_height: u16, x_title_width: u16,
Expand Down Expand Up @@ -213,6 +212,27 @@ impl LegendPosition {
}
}

#[derive(Debug, PartialEq)]
pub struct ParseLegendPositionError;

impl FromStr for LegendPosition {
type Err = ParseLegendPositionError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_ascii_lowercase().as_str() {
"top" => Ok(Self::Top),
"topleft" => Ok(Self::TopLeft),
"topright" => Ok(Self::TopRight),
"left" => Ok(Self::Left),
"right" => Ok(Self::Right),
"bottom" => Ok(Self::Bottom),
"bottomleft" => Ok(Self::BottomLeft),
"bottomright" => Ok(Self::BottomRight),
_ => Err(ParseLegendPositionError),
}
}
}

/// A group of data points
///
/// This is the main element composing a [`TimeChart`].
Expand Down
1 change: 1 addition & 0 deletions src/canvas/widgets/cpu_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ impl Painter {
title,
is_expanded: app_state.is_expanded,
title_style: self.colours.widget_title_style,
legend_position: None,
legend_constraints: None,
marker,
}
Expand Down
3 changes: 3 additions & 0 deletions src/canvas/widgets/mem_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ impl Painter {
Marker::Braille
};

let legend_position = app_state.app_config_fields.memory_legend_position;

TimeGraph {
x_bounds,
hide_x_labels,
Expand All @@ -133,6 +135,7 @@ impl Painter {
title: " Memory ".into(),
is_expanded: app_state.is_expanded,
title_style: self.colours.widget_title_style,
legend_position,
legend_constraints: Some((Constraint::Ratio(3, 4), Constraint::Ratio(3, 4))),
marker,
}
Expand Down
3 changes: 3 additions & 0 deletions src/canvas/widgets/network_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ impl Painter {
Marker::Braille
};

let legend_position = app_state.app_config_fields.network_legend_position;

TimeGraph {
x_bounds,
hide_x_labels,
Expand All @@ -162,6 +164,7 @@ impl Painter {
title: " Network ".into(),
is_expanded: app_state.is_expanded,
title_style: self.colours.widget_title_style,
legend_position,
legend_constraints: Some(legend_constraints),
marker,
}
Expand Down
49 changes: 48 additions & 1 deletion src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use starship_battery::Manager;
use self::config::{layout::Row, IgnoreList, StringOrNum};
use crate::{
app::{filter::Filter, layout_manager::*, *},
canvas::{styling::CanvasStyling, ColourScheme},
canvas::{components::time_chart::LegendPosition, styling::CanvasStyling, ColourScheme},
constants::*,
data_collection::temperature::TemperatureType,
utils::{
Expand Down Expand Up @@ -126,6 +126,9 @@ pub fn init_app(
}
};

let network_legend_position = get_network_legend(matches, config)?;
let memory_legend_position = get_memory_legend(matches, config)?;

// TODO: Can probably just reuse the options struct.
let app_config_fields = AppConfigFields {
update_rate: get_update_rate(matches, config)
Expand All @@ -150,6 +153,8 @@ pub fn init_app(
enable_cache_memory: get_enable_cache_memory(matches, config),
show_table_scroll_position: is_flag_enabled!(show_table_scroll_position, matches, config),
is_advanced_kill,
memory_legend_position,
network_legend_position,
network_scale_type,
network_unit_type,
network_use_binary_prefix,
Expand Down Expand Up @@ -772,6 +777,48 @@ fn get_retention(matches: &ArgMatches, config: &Config) -> error::Result<u64> {
}
}

fn get_network_legend(
matches: &ArgMatches, config: &Config,
) -> error::Result<Option<LegendPosition>> {
let error = |_| BottomError::ConfigError("cannot set the network legend position, it must be one of: ['top', 'topleft', 'topright', 'left', 'right', 'bottom', 'bottomright', 'bottomleft', 'none'".to_string());
if let Some(s) = matches.get_one::<String>("network_legend") {
match s.to_ascii_lowercase().trim() {
"none" | "" => Ok(None),
position => Ok(Some(position.parse::<LegendPosition>().map_err(error)?)),
}
} else if let Some(flags) = &config.flags {
if let Some(legend) = &flags.network_legend {
Ok(Some(legend.parse::<LegendPosition>().map_err(error)?))
} else {
Ok(Some(LegendPosition::default()))
}
} else {
Ok(Some(LegendPosition::default()))
}
}

fn get_memory_legend(
matches: &ArgMatches, config: &Config,
) -> error::Result<Option<LegendPosition>> {
let error = |_| {
BottomError::ConfigError("cannot set the memory legend position, it must be one of values ['top', 'topleft', 'topright', 'left', 'right', 'bottom', 'bottomright', 'bottomleft', 'none'".to_string())
};
if let Some(s) = matches.get_one::<String>("memory_legend") {
match s.to_ascii_lowercase().trim() {
"none" | "" => Ok(None),
position => Ok(Some(position.parse::<LegendPosition>().map_err(error)?)),
}
} else if let Some(flags) = &config.flags {
if let Some(legend) = &flags.memory_legend {
Ok(Some(legend.parse::<LegendPosition>().map_err(error)?))
} else {
Ok(Some(LegendPosition::default()))
}
} else {
Ok(Some(LegendPosition::default()))
}
}

#[cfg(test)]
mod test {
use clap::ArgMatches;
Expand Down
51 changes: 49 additions & 2 deletions src/options/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,18 +436,41 @@ fn mem_args(cmd: Command) -> Command {
to showing it by percentage.",
);

let memory_legend = Arg::new("memory_legend")
.long("memory_legend")
.action(ArgAction::Set)
.value_name("POSITION")
.ignore_case(true)
.help(
"Where to render the legend in memory widget. \
[possible values: none, topleft, top, topright, left, right, bottom, bottomleft, bottomright]",
)
.hide_possible_values(true)
.value_parser([
"none",
"topleft",
"top",
"topright",
"left",
"right",
"bottom",
"bottomleft",
"bottomright",
"",
]);

#[cfg(not(target_os = "windows"))]
{
let enable_cache_memory = Arg::new("enable_cache_memory")
.long("enable_cache_memory")
.action(ArgAction::SetTrue)
.help("Enable collecting and displaying cache and buffer memory.");

cmd.args(args![mem_as_value, enable_cache_memory])
cmd.args(args![mem_as_value, memory_legend, enable_cache_memory])
}
#[cfg(target_os = "windows")]
{
cmd.arg(mem_as_value)
cmd.args(args![mem_as_value, memory_legend])
}
}

Expand All @@ -464,6 +487,29 @@ fn network_args(cmd: Command) -> Command {
display is not tested anymore and may be broken.",
);

let network_legend = Arg::new("network_legend")
.long("network_legend")
.action(ArgAction::Set)
.value_name("POSITION")
.ignore_case(true)
.help(
"Where to render the legend in network widget. \
[possible values: none, topleft, top, topright, left, right, bottom, bottomleft, bottomright]"
)
.hide_possible_values(true)
.value_parser([
"none",
"topleft",
"top",
"topright",
"left",
"right",
"bottom",
"bottomleft",
"bottomright",
"",
]);

let network_use_bytes = Arg::new("network_use_bytes")
.long("network_use_bytes")
.action(ArgAction::SetTrue)
Expand All @@ -487,6 +533,7 @@ fn network_args(cmd: Command) -> Command {

cmd.args(args![
use_old_network_legend,
network_legend,
network_use_bytes,
network_use_log,
network_use_binary_prefix,
Expand Down
2 changes: 2 additions & 0 deletions src/options/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ pub(crate) struct ConfigFlags {
pub(crate) battery: Option<bool>,
pub(crate) disable_click: Option<bool>,
pub(crate) no_write: Option<bool>,
pub(crate) network_legend: Option<String>,
pub(crate) memory_legend: Option<String>,
/// For built-in colour palettes.
pub(crate) color: Option<String>,
pub(crate) mem_as_value: Option<bool>,
Expand Down

0 comments on commit 2f9d17b

Please sign in to comment.