Skip to content

Commit 8b8b6e7

Browse files
committed
refactor: simplify color / gradient handling logic
1 parent 887b338 commit 8b8b6e7

File tree

1 file changed

+25
-38
lines changed

1 file changed

+25
-38
lines changed

tui-bar-graph/src/lib.rs

+25-38
Original file line numberDiff line numberDiff line change
@@ -191,28 +191,14 @@ impl BarGraph {
191191
self
192192
}
193193

194-
/// Gets the color of a bar based on its value.
195-
fn color(&self, value: f64) -> Color {
196-
if let Some(gradient) = &self.gradient {
197-
let color = gradient.at(value as f32);
198-
to_ratatui_color(&color)
199-
} else {
200-
Color::Reset
201-
}
202-
}
203-
204194
/// Renders the graph using solid blocks (█).
205195
fn render_solid(&self, area: Rect, buf: &mut Buffer, min: f64, max: f64) {
206196
let range = max - min;
207197
for (&value, column) in self.data.iter().zip(area.columns()) {
208198
let normalized = (value - min) / range;
209199
let column_height = (normalized * area.height as f64).ceil() as usize;
210200
for (i, row) in column.rows().rev().enumerate().take(column_height) {
211-
let color_value = match self.color_mode {
212-
ColorMode::Solid => value,
213-
ColorMode::VerticalGradient => min + i as f64 / area.height as f64 * range,
214-
};
215-
let color = self.color(color_value);
201+
let color = self.color_for(area, min, range, value, i);
216202
buf[row].set_symbol("█").set_fg(color);
217203
}
218204
}
@@ -243,15 +229,11 @@ impl BarGraph {
243229
let column_height = (left_total_dots.max(right_total_dots) as f64 / DOTS_PER_ROW as f64)
244230
.ceil() as usize;
245231

246-
for (i, row) in column.rows().rev().enumerate().take(column_height) {
247-
let color_value = match self.color_mode {
248-
// Use the average of the left and right values for solid color mode
249-
ColorMode::Solid => (left_value + right_value) / 2.0,
250-
ColorMode::VerticalGradient => min + i as f64 / area.height as f64 * range,
251-
};
252-
let color = self.color(color_value);
232+
for (row_index, row) in column.rows().rev().enumerate().take(column_height) {
233+
let value = f64::midpoint(left_value, right_value);
234+
let color = self.color_for(area, min, max, value, row_index);
253235

254-
let dots_below = i * DOTS_PER_ROW;
236+
let dots_below = row_index * DOTS_PER_ROW;
255237
let left_dots = left_total_dots.saturating_sub(dots_below).min(4);
256238
let right_dots = right_total_dots.saturating_sub(dots_below).min(4);
257239

@@ -260,36 +242,41 @@ impl BarGraph {
260242
}
261243
}
262244
}
245+
246+
fn color_for(&self, area: Rect, min: f64, max: f64, value: f64, row: usize) -> Color {
247+
let color_value = match self.color_mode {
248+
ColorMode::Solid => value,
249+
ColorMode::VerticalGradient => min + row as f64 / area.height as f64 * (max - min),
250+
};
251+
self.gradient
252+
.as_ref()
253+
.map(|gradient| {
254+
let color = gradient.at(color_value as f32);
255+
let rgba = color.to_rgba8();
256+
// TODO this can be changed to .into() in ratatui 0.30
257+
Color::Rgb(rgba[0], rgba[1], rgba[2])
258+
})
259+
.unwrap_or(Color::Reset)
260+
}
263261
}
264262

265263
impl Widget for BarGraph {
266264
fn render(self, area: Rect, buf: &mut Buffer) {
267265
// f64 doesn't impl Ord because NaN != NaN, so we use fold instead of iter::max/min
268-
let max = self
269-
.max
270-
.unwrap_or_else(|| self.data.iter().copied().fold(f64::NEG_INFINITY, f64::max));
271266
let min = self
272267
.min
273268
.unwrap_or_else(|| self.data.iter().copied().fold(f64::INFINITY, f64::min));
274-
275-
if max == min {
276-
// don't render anything for a single value
277-
return;
278-
}
279-
269+
let max = self
270+
.max
271+
.unwrap_or_else(|| self.data.iter().copied().fold(f64::NEG_INFINITY, f64::max));
272+
let max = max.max(min + f64::EPSILON); // avoid division by zero if min == max
280273
match self.bar_style {
281274
BarStyle::Solid => self.render_solid(area, buf, min, max),
282275
BarStyle::Braille => self.render_braille(area, buf, min, max),
283276
}
284277
}
285278
}
286279

287-
/// Converts a colorgrad color to a ratatui color.
288-
fn to_ratatui_color(color: &colorgrad::Color) -> Color {
289-
let rgba = color.to_rgba8();
290-
Color::Rgb(rgba[0], rgba[1], rgba[2])
291-
}
292-
293280
#[cfg(test)]
294281
mod tests {
295282
use super::*;

0 commit comments

Comments
 (0)