Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 57 additions & 11 deletions cursive-core/src/views/slider_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,28 @@ pub struct SliderView {
on_enter: Option<Rc<SliderCallback>>,
value: usize,
max_value: usize,
min_value: usize,
length: usize,
dragging: bool,
}

impl SliderView {
/// Creates a new `SliderView` in the given orientation.
///
/// The view will have a fixed length of `max_value`,
/// The view will have a fixed length of `max_value - min_value`,
/// with one tick per block.
///
/// The actual range of values for this slider is `[0, max_value - 1]`.
/// The actual range of values for this slider is `[min_value, max_value - 1]`.
///
/// `min_value` defaults to `0` and can be set with [`set_min_value`](Self::set_min_value) or [`min_value`](Self::min_value).
pub fn new(orientation: Orientation, max_value: usize) -> Self {
let min_value = 0;
SliderView {
orientation,
value: 0,
value: min_value,
min_value,
max_value,
length: max_value - min_value,
on_change: None,
on_enter: None,
dragging: false,
Expand Down Expand Up @@ -83,6 +90,29 @@ impl SliderView {
})
}

/// Sets the min value, adjusting the current value if needed.
///
/// Returns `false` if the new `min_value` is greater than or equal to `max_value`.
pub fn set_min_value(&mut self, min_value: usize) -> bool {
if min_value >= self.max_value {
return false;
}
self.min_value = min_value;
self.length = self.max_value - self.min_value;
self.value = self.value.max(self.min_value);
true
}

/// Sets the min value.
///
/// Chainable variant.
#[must_use]
pub fn min_value(self, min_value: usize) -> Self {
self.with(|s| {
s.set_min_value(min_value);
})
}

/// Gets the current value.
pub fn get_value(&self) -> usize {
self.value
Expand All @@ -93,6 +123,11 @@ impl SliderView {
self.max_value
}

/// Gets the min value.
pub fn get_min_value(&self) -> usize {
self.min_value
}

/// Sets a callback to be called when the slider is moved.
#[crate::callback_helpers]
pub fn set_on_change<F>(&mut self, callback: F)
Expand Down Expand Up @@ -150,7 +185,7 @@ impl SliderView {
}

fn slide_minus(&mut self) -> EventResult {
if self.value > 0 {
if self.value > self.min_value {
self.value -= 1;
self.get_change_result()
} else {
Expand All @@ -159,15 +194,15 @@ impl SliderView {
}

fn req_size(&self) -> Vec2 {
self.orientation.make_vec(self.max_value, 1)
self.orientation.make_vec(self.length, 1)
}
}

impl View for SliderView {
fn draw(&self, printer: &Printer) {
match self.orientation {
Orientation::Vertical => printer.print_vline((0, 0), self.max_value, "|"),
Orientation::Horizontal => printer.print_hline((0, 0), self.max_value, "-"),
Orientation::Vertical => printer.print_vline((0, 0), self.length, "|"),
Orientation::Horizontal => printer.print_hline((0, 0), self.length, "-"),
}

let style = if printer.focused {
Expand All @@ -177,7 +212,10 @@ impl View for SliderView {
};

printer.with_style(style, |printer| {
printer.print(self.orientation.make_vec(self.value, 0), " ");
printer.print(
self.orientation.make_vec(self.value - self.min_value, 0),
" ",
);
});
}

Expand Down Expand Up @@ -208,8 +246,11 @@ impl View for SliderView {
offset,
} if self.dragging => {
let position = position.saturating_sub(offset);
let position = self.orientation.get(&position);
let position = ::std::cmp::min(position, self.max_value.saturating_sub(1));
let position = self
.orientation
.get(&position)
.saturating_add(self.min_value);
let position = position.min(self.max_value.saturating_sub(1));
self.value = position;
self.get_change_result()
}
Expand All @@ -220,7 +261,12 @@ impl View for SliderView {
} if position.fits_in_rect(offset, self.req_size()) => {
if let Some(position) = position.checked_sub(offset) {
self.dragging = true;
self.value = self.orientation.get(&position);
let position = self
.orientation
.get(&position)
.saturating_add(self.min_value);
let position = position.min(self.max_value.saturating_sub(1));
self.value = position;
}
self.get_change_result()
}
Expand Down
1 change: 1 addition & 0 deletions cursive/examples/slider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ fn main() {
Dialog::around(
// We give the number of steps in the constructor
SliderView::horizontal(15)
.min_value(5)
// Sets the initial value
.value(7)
.on_change(|s, v| {
Expand Down