Files
ltk/src/widget/progress_bar/mod.rs
T
admin a7f953ca42
CI / build + test (push) Has been cancelled
CI / cargo audit (push) Has been cancelled
layout: adaptive grid and vertical flex; enforce the mechanical style rules
grid_min_cell( width ) adds the adaptive mode WrapGrid was missing: instead of a fixed column count, the count is derived at layout time from the available width so every cell is at least `width` wide (any Length, so a fluid threshold works; never fewer than one column), re-derived on every resize. Cells then share the width equally, and WrapGrid::max_columns( n ) caps the derived count so cells grow instead of multiplying on very wide surfaces — the cap only applies to the adaptive mode, grid( n ) keeps the fixed behaviour untouched. Four new layout tests cover width derivation, spacing accounting, the one-column floor and the cap; the row-wrap assertions check X positions rather than Y because zero-height spacer children produce zero-height rows.
flex( child ) now distributes leftover height inside a Column, mirroring its leftover-width behaviour in a Row: flex children join the weight pool alongside weight-only spacers and y-scrolls, draw their child inside the allocated share at full inner width, and contribute zero to the column's natural height exactly like a row counts flex width. This closes the documented "vertical flex is not yet implemented" gap; the Flex rustdoc and the widgets.md entry now describe both axes.
Add scripts/style-check.sh and a make stylecheck target, wired into CI: mechanical verification of the grep-checkable subset of code_style_guide.md — tab indentation and spaces inside attribute brackets — with comment lines skipped so prose may cite raw attribute syntax. To turn the check on green, the 82 unspaced attribute sites across 24 files (#[test], #[derive(...)], #[cfg(...)], #[allow(...)]) were normalized to the spaced form. CONTRIBUTING and the style guide reference the new target; brace placement and paren spacing remain review concerns.
2026-07-30 22:20:21 +02:00

118 lines
3.1 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// SPDX-License-Identifier: LGPL-2.1-only
// Copyright (C) 2026 Liberux Labs, S. L. <info@liberux.net>
use crate::types::{ Color, Rect };
use crate::render::Canvas;
use super::Element;
mod theme;
#[ cfg( test ) ]
mod tests;
/// A linear progress indicator for determinate operations.
///
/// Renders a horizontal track with a coloured fill from the left edge to
/// `value × width`. `value` is clamped to `[0.0, 1.0]` at construction.
/// For indeterminate progress (the operation has no ETA) prefer an
/// animated spinner — `ltk` has no built-in spinner widget yet; build one
/// from a [`Container`](super::container::Container) that rotates a glyph
/// while [`crate::App::is_animating`] returns `true`.
///
/// ```rust,no_run
/// # use ltk::{ column, progress_bar, text, Element };
/// # #[ derive( Clone ) ] enum Msg {}
/// # struct App { progress: f32 }
/// # impl App { fn _ex( &self ) -> Element<Msg> {
/// // In view():
/// column()
/// .push( text( format!( "Downloading… {}%", ( self.progress * 100.0 ) as u32 ) ) )
/// .push( progress_bar( self.progress ) )
/// .into()
/// # }}
/// ```
pub struct ProgressBar
{
/// Current progress in `[0.0, 1.0]`. Always clamped at construction.
pub( crate ) value: f32,
/// Fill colour. Defaults to the theme's `accent` palette slot.
pub( crate ) fill: Color,
}
impl ProgressBar
{
/// Create a progress bar at the given fraction. `value` outside
/// `[0.0, 1.0]` is clamped silently.
pub fn new( value: f32 ) -> Self
{
Self { value: value.clamp( 0.0, 1.0 ), fill: theme::fill() }
}
/// Override the fill colour. Useful for "danger" / "success" variants
/// (red for nearly-full disks, green for completed work).
pub fn color( mut self, color: Color ) -> Self
{
self.fill = color;
self
}
/// Return the preferred `(width, height)`. Width fills the available
/// `max_width`; height is the theme-defined row height.
pub fn preferred_size( &self, max_width: f32, canvas: &Canvas ) -> (f32, f32)
{
( max_width, canvas.geom_px( theme::HEIGHT ) )
}
pub fn draw( &self, canvas: &mut Canvas, rect: Rect )
{
let track_h = canvas.geom_px( theme::TRACK_H );
let track_y = rect.y + ( rect.height - track_h ) / 2.0;
let track_r = track_h / 2.0;
let track_rect = Rect
{
x: rect.x,
y: track_y,
width: rect.width,
height: track_h,
};
canvas.fill_rect( track_rect, theme::track_bg(), track_r );
let fill_w = rect.width * self.value;
if fill_w > 0.0
{
let fill_rect = Rect
{
x: rect.x,
y: track_y,
width: fill_w,
height: track_h,
};
canvas.fill_rect( fill_rect, self.fill, track_r );
}
}
}
/// Create a [`ProgressBar`] at the given fraction (clamped to
/// `[0.0, 1.0]`).
///
/// ```rust,no_run
/// # use ltk::{ progress_bar, ProgressBar };
/// # struct App { download_fraction: f32 }
/// # impl App { fn _ex( &self ) -> ProgressBar {
/// progress_bar( self.download_fraction )
/// # }}
/// ```
pub fn progress_bar( value: f32 ) -> ProgressBar
{
ProgressBar::new( value )
}
impl<Msg: Clone> From<ProgressBar> for Element<Msg>
{
fn from( p: ProgressBar ) -> Self
{
Element::ProgressBar( p )
}
}