use base_render::HasRenderConfig;
use base_render::RenderConfig;
use cursive::utils::markup::StyledString;
use model::Field;
use model::FieldId;
use model::Queriable;
use model::Recursive;
#[derive(Clone)]
pub enum ViewStyle {
HighlightAbove(Field),
HighlightBelow(Field),
}
pub const PRESSURE_HIGHLIGHT: ViewStyle = ViewStyle::HighlightAbove(Field::F64(40.0));
pub const CPU_HIGHLIGHT: ViewStyle = ViewStyle::HighlightAbove(Field::F64(100.0));
pub const MEM_HIGHLIGHT: ViewStyle = ViewStyle::HighlightBelow(Field::U64(2 << 20));
#[derive(Clone, Default)]
pub struct ViewConfig {
pub render_config: RenderConfig,
pub view_style: Option<ViewStyle>,
}
impl ViewConfig {
pub fn update<T: Into<RenderConfig>>(mut self, overrides: T) -> Self {
self.render_config = self.render_config.update(overrides);
self
}
pub fn set_style(mut self, style: ViewStyle) -> Self {
self.view_style = Some(style);
self
}
fn apply_style(&self, rendered: String, field: Option<Field>) -> StyledString {
match &self.view_style {
Some(view_style) => match view_style {
ViewStyle::HighlightAbove(threshold) => {
if field.as_ref().map_or(false, |field| field > threshold) {
StyledString::styled(
rendered,
cursive::theme::Color::Light(cursive::theme::BaseColor::Red),
)
} else {
StyledString::plain(rendered)
}
}
ViewStyle::HighlightBelow(threshold) => {
if field.as_ref().map_or(false, |field| field < threshold) {
StyledString::styled(
rendered,
cursive::theme::Color::Light(cursive::theme::BaseColor::Red),
)
} else {
StyledString::plain(rendered)
}
}
},
None => StyledString::plain(rendered),
}
}
pub fn render_title(&self) -> String {
self.render_config.render_title(true)
}
pub fn render(&self, field: Option<Field>) -> StyledString {
let rendered = self.render_config.render(field.clone(), true);
self.apply_style(rendered, field)
}
pub fn render_tight(&self, field: Option<Field>) -> StyledString {
let rendered = self.render_config.render(field.clone(), false);
self.apply_style(rendered, field)
}
pub fn render_indented(&self, field: Option<Field>, depth: usize) -> StyledString {
let rendered = self
.render_config
.render_indented(field.clone(), true, depth);
self.apply_style(rendered, field)
}
}
#[derive(Clone, Default)]
pub struct ViewItem<F: FieldId> {
pub field_id: F,
pub config: ViewConfig,
}
pub trait HasViewStyle: Queriable {
fn get_view_style(_field_id: &Self::FieldId) -> Option<ViewStyle> {
None
}
}
impl<T, F> ViewItem<F>
where
T: Queriable<FieldId = F> + HasRenderConfig + HasViewStyle,
F: FieldId<Queriable = T>,
{
pub fn from_default(field_id: F) -> Self {
let config = ViewConfig {
render_config: T::get_render_config(&field_id),
view_style: T::get_view_style(&field_id),
};
Self { field_id, config }
}
}
impl<F: FieldId> ViewItem<F> {
pub fn update<T: Into<RenderConfig>>(mut self, overrides: T) -> Self {
self.config = self.config.update(overrides);
self
}
pub fn set_style(mut self, style: ViewStyle) -> Self {
self.config = self.config.set_style(style);
self
}
pub fn render(&self, model: &F::Queriable) -> StyledString {
self.config.render(model.query(&self.field_id))
}
pub fn render_tight(&self, model: &F::Queriable) -> StyledString {
self.config.render_tight(model.query(&self.field_id))
}
}
impl<F, T> ViewItem<F>
where
T: Queriable<FieldId = F> + Recursive,
F: FieldId<Queriable = T>,
{
pub fn render_indented(&self, model: &T) -> StyledString {
self.config
.render_indented(model.query(&self.field_id), model.get_depth())
}
}