Updated spin button widget and example usage
This commit is contained in:
parent
8036be52dc
commit
c8aabca37d
4 changed files with 146 additions and 123 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
use cosmic::widget::divider::horizontal;
|
use cosmic::widget::divider::horizontal;
|
||||||
use cosmic::widget::{button, container, text, spin_button, spin_button::Direction};
|
use cosmic::widget::{button, container, text, spin_button, spin_button::Orientation};
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
app::{Core, Task},
|
app::{Core, Task},
|
||||||
iced::{
|
iced::{
|
||||||
|
|
@ -10,7 +10,7 @@ use cosmic::{
|
||||||
Application, Element,
|
Application, Element,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct VertSpinnerApp {
|
pub struct SpinButtonExamplApp {
|
||||||
core: Core,
|
core: Core,
|
||||||
i8_num: i8,
|
i8_num: i8,
|
||||||
i16_num: i16,
|
i16_num: i16,
|
||||||
|
|
@ -34,12 +34,12 @@ pub enum SpinBtnMessages {
|
||||||
UpdateSpinnerMsg,
|
UpdateSpinnerMsg,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for VertSpinnerApp {
|
impl Application for SpinButtonExamplApp {
|
||||||
type Executor = cosmic::executor::Default;
|
type Executor = cosmic::executor::Default;
|
||||||
type Flags = ();
|
type Flags = ();
|
||||||
type Message = SpinBtnMessages;
|
type Message = SpinBtnMessages;
|
||||||
|
|
||||||
const APP_ID: &'static str = "com.system76.VertSpinnerExample";
|
const APP_ID: &'static str = "com.system76.SpinButtonExample";
|
||||||
|
|
||||||
fn core(&self) -> &Core {
|
fn core(&self) -> &Core {
|
||||||
&self.core
|
&self.core
|
||||||
|
|
@ -68,10 +68,7 @@ impl Application for VertSpinnerApp {
|
||||||
|
|
||||||
fn update(&mut self, message: Self::Message) -> Task<Self::Message> {
|
fn update(&mut self, message: Self::Message) -> Task<Self::Message> {
|
||||||
match message {
|
match message {
|
||||||
SpinBtnMessages::UpdateI8Num(new_i8) => {
|
SpinBtnMessages::UpdateI8Num(new_i8) => self.i8_num = new_i8,
|
||||||
self.i8_num = new_i8;
|
|
||||||
SpinBtnMessages::UpdateSpinnerMsg;
|
|
||||||
},
|
|
||||||
SpinBtnMessages::UpdateI16Num(new_i16) => self.i16_num = new_i16,
|
SpinBtnMessages::UpdateI16Num(new_i16) => self.i16_num = new_i16,
|
||||||
SpinBtnMessages::UpdateI32Num(new_i32) => self.i32_num = new_i32,
|
SpinBtnMessages::UpdateI32Num(new_i32) => self.i32_num = new_i32,
|
||||||
SpinBtnMessages::UpdateI64Num(new_i64) => self.i64_num = new_i64,
|
SpinBtnMessages::UpdateI64Num(new_i64) => self.i64_num = new_i64,
|
||||||
|
|
@ -95,7 +92,7 @@ impl Application for VertSpinnerApp {
|
||||||
self.i8_num, // current value, this is also what's displayed in the center of the widget
|
self.i8_num, // current value, this is also what's displayed in the center of the widget
|
||||||
-5, // minimum value, if decremented below this the widget's current value rolls to the max value
|
-5, // minimum value, if decremented below this the widget's current value rolls to the max value
|
||||||
5, // maximum value, if incremented above this the widget's current value rolls to the min value
|
5, // maximum value, if incremented above this the widget's current value rolls to the min value
|
||||||
Direction::Vertical, // oreintation of the widget
|
Some(Orientation::Vertical), // oreintation of the widget
|
||||||
SpinBtnMessages::UpdateI8Num // message to send to the application's update function
|
SpinBtnMessages::UpdateI8Num // message to send to the application's update function
|
||||||
),
|
),
|
||||||
spin_button(
|
spin_button(
|
||||||
|
|
@ -104,7 +101,7 @@ impl Application for VertSpinnerApp {
|
||||||
self.i16_num,
|
self.i16_num,
|
||||||
0,
|
0,
|
||||||
10,
|
10,
|
||||||
Direction::Vertical,
|
Some(Orientation::Vertical),
|
||||||
SpinBtnMessages::UpdateI16Num
|
SpinBtnMessages::UpdateI16Num
|
||||||
),
|
),
|
||||||
spin_button(
|
spin_button(
|
||||||
|
|
@ -113,7 +110,7 @@ impl Application for VertSpinnerApp {
|
||||||
self.i32_num,
|
self.i32_num,
|
||||||
0,
|
0,
|
||||||
12,
|
12,
|
||||||
Direction::Vertical,
|
Some(Orientation::Vertical),
|
||||||
SpinBtnMessages::UpdateI32Num
|
SpinBtnMessages::UpdateI32Num
|
||||||
),
|
),
|
||||||
spin_button(
|
spin_button(
|
||||||
|
|
@ -122,7 +119,7 @@ impl Application for VertSpinnerApp {
|
||||||
self.i64_num,
|
self.i64_num,
|
||||||
15,
|
15,
|
||||||
35,
|
35,
|
||||||
Direction::Vertical,
|
Some(Orientation::Vertical),
|
||||||
SpinBtnMessages::UpdateI64Num
|
SpinBtnMessages::UpdateI64Num
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
@ -136,7 +133,7 @@ impl Application for VertSpinnerApp {
|
||||||
self.i128_num,
|
self.i128_num,
|
||||||
-1000,
|
-1000,
|
||||||
500,
|
500,
|
||||||
Direction::Horizontal,
|
None, // Passing None gives a default of a Horizontal Spin Button widget
|
||||||
SpinBtnMessages::UpdateI128Num
|
SpinBtnMessages::UpdateI128Num
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
@ -148,7 +145,7 @@ impl Application for VertSpinnerApp {
|
||||||
self.f32_num,
|
self.f32_num,
|
||||||
-35.3,
|
-35.3,
|
||||||
12.3,
|
12.3,
|
||||||
Direction::Horizontal,
|
Some(Orientation::Horizontal), // It can also be explicitly passed as Orientation::Horizontal
|
||||||
SpinBtnMessages::UpdateF32Num
|
SpinBtnMessages::UpdateF32Num
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|
@ -160,7 +157,7 @@ impl Application for VertSpinnerApp {
|
||||||
self.f64_num,
|
self.f64_num,
|
||||||
0.0,
|
0.0,
|
||||||
3.0,
|
3.0,
|
||||||
Direction::Horizontal,
|
None,
|
||||||
SpinBtnMessages::UpdateF64Num
|
SpinBtnMessages::UpdateF64Num
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|
|
||||||
2
iced
2
iced
|
|
@ -1 +1 @@
|
||||||
Subproject commit 256863574bacfb1d2797c2a48cba7a3388cbeb59
|
Subproject commit d0c2a0371b476866cb0f7045fba0215425493d62
|
||||||
|
|
@ -102,7 +102,7 @@ pub(crate) fn iced_settings<App: Application>(
|
||||||
iced.default_font = settings.default_font;
|
iced.default_font = settings.default_font;
|
||||||
iced.default_text_size = iced::Pixels(settings.default_text_size);
|
iced.default_text_size = iced::Pixels(settings.default_text_size);
|
||||||
let exit_on_close = settings.exit_on_close;
|
let exit_on_close = settings.exit_on_close;
|
||||||
iced.is_daemon = false;
|
//iced.is_daemon = false;
|
||||||
iced.exit_on_close_request = settings.is_daemon;
|
iced.exit_on_close_request = settings.is_daemon;
|
||||||
let mut window_settings = iced::window::Settings::default();
|
let mut window_settings = iced::window::Settings::default();
|
||||||
window_settings.exit_on_close_request = exit_on_close;
|
window_settings.exit_on_close_request = exit_on_close;
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,17 @@
|
||||||
// Copyright 2022 System76 <info@system76.com>
|
// Copyright 2022 System76 <info@system76.com>
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
// Updated by Bryan Hyland <bryan.hyland32@gmail.com>
|
||||||
|
// Updated on: 17Nov24
|
||||||
|
|
||||||
//! A control for incremental adjustments of a value.
|
//! A control for incremental adjustments of a value.
|
||||||
|
|
||||||
use std::borrow::{Borrow, Cow};
|
use std::fmt::Display;
|
||||||
use std::fmt::{Display, Formatter};
|
|
||||||
use std::ops::{Add, Sub};
|
use std::ops::{Add, Sub};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use apply::Apply;
|
use apply::Apply;
|
||||||
use fraction::Decimal;
|
|
||||||
use iced::alignment::Horizontal;
|
use iced::alignment::Horizontal;
|
||||||
use iced::{Alignment, Border, Length, Shadow};
|
use iced::{Alignment, Length};
|
||||||
use crate::{
|
use crate::{
|
||||||
Element,
|
Element,
|
||||||
widget::{
|
widget::{
|
||||||
|
|
@ -23,7 +24,8 @@ use crate::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub enum Direction {
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum Orientation {
|
||||||
Horizontal,
|
Horizontal,
|
||||||
Vertical,
|
Vertical,
|
||||||
}
|
}
|
||||||
|
|
@ -32,17 +34,23 @@ pub struct SpinButton<'a, T, M>
|
||||||
where
|
where
|
||||||
T: Add<Output = T> + Sub<Output = T> + PartialEq + PartialOrd + Display + Copy
|
T: Add<Output = T> + Sub<Output = T> + PartialEq + PartialOrd + Display + Copy
|
||||||
{
|
{
|
||||||
|
/// The label that the spin button widget will have.
|
||||||
|
/// It is placed on the top of and centered on the spin button widget itself.
|
||||||
label: String,
|
label: String,
|
||||||
/// The amount to increment or decrement the value.
|
/// The amount to increment or decrement the value.
|
||||||
pub step: T,
|
step: T,
|
||||||
/// The current value of the spin button.
|
/// The current value of the spin button.
|
||||||
pub value: T,
|
/// It is displayed in the center of the spin button widget, no matter the orientation.
|
||||||
|
value: T,
|
||||||
/// The minimum value permitted.
|
/// The minimum value permitted.
|
||||||
pub min: T,
|
/// If the value is decremented below this value the current value will rollover to the max value.
|
||||||
|
min: T,
|
||||||
/// The maximum value permitted.
|
/// The maximum value permitted.
|
||||||
pub max: T,
|
/// If the value is incremented above this value the current value will rollover to the min value.
|
||||||
|
max: T,
|
||||||
/// The direction that the spin button is laid out; Horizontal (default) or Vertical
|
/// The direction that the spin button is laid out; Horizontal (default) or Vertical
|
||||||
pub direction: Direction,
|
orientation: Option<Orientation>,
|
||||||
|
/// The message that the spin button emits to the application's update function.
|
||||||
on_press: Box<dyn Fn(T) -> M>,
|
on_press: Box<dyn Fn(T) -> M>,
|
||||||
phantom_data: PhantomData<&'a M>,
|
phantom_data: PhantomData<&'a M>,
|
||||||
}
|
}
|
||||||
|
|
@ -58,7 +66,7 @@ where
|
||||||
value: T,
|
value: T,
|
||||||
min: T,
|
min: T,
|
||||||
max: T,
|
max: T,
|
||||||
direction: Direction,
|
orientation: Option<Orientation>,
|
||||||
on_press: impl Fn(T) -> M + 'static,
|
on_press: impl Fn(T) -> M + 'static,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
@ -67,7 +75,7 @@ where
|
||||||
value,
|
value,
|
||||||
min,
|
min,
|
||||||
max,
|
max,
|
||||||
direction,
|
orientation,
|
||||||
on_press: Box::from(on_press),
|
on_press: Box::from(on_press),
|
||||||
phantom_data: PhantomData,
|
phantom_data: PhantomData,
|
||||||
}
|
}
|
||||||
|
|
@ -81,13 +89,13 @@ pub fn spin_button<'a, T, M>(
|
||||||
value: T,
|
value: T,
|
||||||
min: T,
|
min: T,
|
||||||
max: T,
|
max: T,
|
||||||
direction: Direction,
|
orientation: Option<Orientation>,
|
||||||
on_press: impl Fn(T) -> M + 'static,
|
on_press: impl Fn(T) -> M + 'static,
|
||||||
) -> SpinButton<'a, T, M>
|
) -> SpinButton<'a, T, M>
|
||||||
where
|
where
|
||||||
T: Add<Output = T> + Sub<Output = T> + PartialEq + PartialOrd + Display + Copy
|
T: Add<Output = T> + Sub<Output = T> + PartialEq + PartialOrd + Display + Copy
|
||||||
{
|
{
|
||||||
SpinButton::new(label, step, value, min, max, direction, on_press)
|
SpinButton::new(label, step, value, min, max, orientation, on_press)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn increment<T>(step: T, value: T, min: T, max: T) -> T
|
fn increment<T>(step: T, value: T, min: T, max: T) -> T
|
||||||
|
|
@ -120,10 +128,27 @@ where
|
||||||
T: Add<Output = T> + Sub<Output = T> + PartialEq + PartialOrd + Display + Copy
|
T: Add<Output = T> + Sub<Output = T> + PartialEq + PartialOrd + Display + Copy
|
||||||
{
|
{
|
||||||
fn from(this: SpinButton<'a, T, Message>) -> Self {
|
fn from(this: SpinButton<'a, T, Message>) -> Self {
|
||||||
//! Matching on the direction enum given by the developer when the
|
// Matching on the direction enum given by the developer when the
|
||||||
//! widget is initially created in the application's view function.
|
// widget is initially created in the application's view function.
|
||||||
match this.direction {
|
match this.orientation {
|
||||||
Direction::Horizontal => {
|
Some(orien) => match orien {
|
||||||
|
Orientation::Horizontal => create_horizontal_spin_button(&this),
|
||||||
|
Orientation::Vertical => create_vertical_spin_button(&this)
|
||||||
|
}
|
||||||
|
// Default behavior is to create a horizontal spin button widget
|
||||||
|
None => create_horizontal_spin_button(&this),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper Functions
|
||||||
|
// Create a horizontal spin button
|
||||||
|
// Implemented to make the creation easier to read in the from function for Element implementation.
|
||||||
|
fn create_horizontal_spin_button<'a, T, Message>(spin_btn: &SpinButton<T, Message>) -> Element<'a, Message>
|
||||||
|
where
|
||||||
|
Message: Clone + 'static,
|
||||||
|
T: Add<Output = T> + Sub<Output = T> + PartialEq + PartialOrd + Display + Copy
|
||||||
|
{
|
||||||
// Create a spinner container variable that contains the row with all of
|
// Create a spinner container variable that contains the row with all of
|
||||||
// the combined widgets that make up the widget.
|
// the combined widgets that make up the widget.
|
||||||
let spinner_container = column::with_capacity(2)
|
let spinner_container = column::with_capacity(2)
|
||||||
|
|
@ -131,7 +156,7 @@ where
|
||||||
row::with_children(
|
row::with_children(
|
||||||
vec![
|
vec![
|
||||||
// Using the title4 variant of text, just like the original spin button did.
|
// Using the title4 variant of text, just like the original spin button did.
|
||||||
text::title4(this.label.clone())
|
text::title4(spin_btn.label.clone())
|
||||||
.apply(container)
|
.apply(container)
|
||||||
.center_x(Length::Fill)
|
.center_x(Length::Fill)
|
||||||
.align_y(Alignment::Center)
|
.align_y(Alignment::Center)
|
||||||
|
|
@ -145,13 +170,12 @@ where
|
||||||
// Using an button instead of an icon for the decrement functionality.
|
// Using an button instead of an icon for the decrement functionality.
|
||||||
button::icon(icon::from_name("list-remove-symbolic"))
|
button::icon(icon::from_name("list-remove-symbolic"))
|
||||||
.padding([0, 12])
|
.padding([0, 12])
|
||||||
.on_press((this.on_press)(decrement::<T>(
|
.on_press((spin_btn.on_press)(decrement::<T>(
|
||||||
this.step, this.value, this.min, this.max,
|
spin_btn.step, spin_btn.value, spin_btn.min, spin_btn.max,
|
||||||
))
|
))
|
||||||
)
|
).into(),
|
||||||
.into(),
|
|
||||||
// Using the title4 variant of text for consistency.
|
// Using the title4 variant of text for consistency.
|
||||||
text::title4(format!("{}", this.value))
|
text::title4(format!("{}", spin_btn.value))
|
||||||
.apply(container)
|
.apply(container)
|
||||||
.center_x(Length::Fixed(48.0))
|
.center_x(Length::Fixed(48.0))
|
||||||
.align_y(Alignment::Center)
|
.align_y(Alignment::Center)
|
||||||
|
|
@ -159,11 +183,10 @@ where
|
||||||
// Using another button for the increment functionality.
|
// Using another button for the increment functionality.
|
||||||
button::icon(icon::from_name("list-add-symbolic"))
|
button::icon(icon::from_name("list-add-symbolic"))
|
||||||
.padding([0, 12])
|
.padding([0, 12])
|
||||||
.on_press((this.on_press)(increment::<T>(
|
.on_press((spin_btn.on_press)(increment::<T>(
|
||||||
this.step, this.value, this.min, this.max,
|
spin_btn.step, spin_btn.value, spin_btn.min, spin_btn.max,
|
||||||
))
|
))
|
||||||
)
|
).into(),
|
||||||
.into(),
|
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
.align_y(Alignment::Center)
|
.align_y(Alignment::Center)
|
||||||
|
|
@ -171,11 +194,18 @@ where
|
||||||
.align_x(Alignment::Center);
|
.align_x(Alignment::Center);
|
||||||
|
|
||||||
// Return the horizontal spin button from the match statement.
|
// Return the horizontal spin button from the match statement.
|
||||||
Self::new(spinner_container)
|
Element::new(spinner_container)
|
||||||
},
|
}
|
||||||
Direction::Vertical => {
|
|
||||||
|
// Used to create a vertical spin button widget.
|
||||||
|
// Implemented to make the creation easier to read in the from function for Element implementation.
|
||||||
|
fn create_vertical_spin_button<'a, T, Message>(spin_btn: &SpinButton<T, Message>) -> Element<'a, Message>
|
||||||
|
where
|
||||||
|
Message: Clone + 'static,
|
||||||
|
T: Add<Output = T> + Sub<Output = T> + PartialEq + PartialOrd + Display + Copy
|
||||||
|
{
|
||||||
// Create a text widget that holds the value
|
// Create a text widget that holds the value
|
||||||
let val_text = text(format!("{}", this.value)).size(14);
|
let val_text = text(format!("{}", spin_btn.value)).size(14);
|
||||||
// Create a spinner container variable that contains the column with all of
|
// Create a spinner container variable that contains the column with all of
|
||||||
// the combined widgets that make up the widget.
|
// the combined widgets that make up the widget.
|
||||||
let spinner_container = column::with_capacity(3)
|
let spinner_container = column::with_capacity(3)
|
||||||
|
|
@ -183,8 +213,8 @@ where
|
||||||
// Use a button for the increment functionality
|
// Use a button for the increment functionality
|
||||||
button::icon(icon::from_name("list-add-symbolic"))
|
button::icon(icon::from_name("list-add-symbolic"))
|
||||||
.padding([0, 12])
|
.padding([0, 12])
|
||||||
.on_press((this.on_press)(increment::<T>(
|
.on_press((spin_btn.on_press)(increment::<T>(
|
||||||
this.step, this.value, this.min, this.max,
|
spin_btn.step, spin_btn.value, spin_btn.min, spin_btn.max,
|
||||||
))),
|
))),
|
||||||
)
|
)
|
||||||
// Add the text widget that holds the current value
|
// Add the text widget that holds the current value
|
||||||
|
|
@ -193,8 +223,8 @@ where
|
||||||
// Use a button for the decrement functionality
|
// Use a button for the decrement functionality
|
||||||
button::icon(icon::from_name("list-remove-symbolic"))
|
button::icon(icon::from_name("list-remove-symbolic"))
|
||||||
.padding([0, 12])
|
.padding([0, 12])
|
||||||
.on_press((this.on_press)(decrement::<T>(
|
.on_press((spin_btn.on_press)(decrement::<T>(
|
||||||
this.step, this.value, this.min, this.max,
|
spin_btn.step, spin_btn.value, spin_btn.min, spin_btn.max,
|
||||||
))),
|
))),
|
||||||
)
|
)
|
||||||
.align_x(Horizontal::Center);
|
.align_x(Horizontal::Center);
|
||||||
|
|
@ -203,7 +233,7 @@ where
|
||||||
// First Row -> The label/title for the spin button.
|
// First Row -> The label/title for the spin button.
|
||||||
// Second Row -> The spin button container from above.
|
// Second Row -> The spin button container from above.
|
||||||
let content_list = column::with_children(vec![
|
let content_list = column::with_children(vec![
|
||||||
row::with_capacity(1).push(text(this.label)).into(),
|
row::with_capacity(1).push(text(spin_btn.label.clone())).into(),
|
||||||
row::with_children(vec![Element::from(spinner_container)]).into(),
|
row::with_children(vec![Element::from(spinner_container)]).into(),
|
||||||
])
|
])
|
||||||
.width(75)
|
.width(75)
|
||||||
|
|
@ -211,9 +241,5 @@ where
|
||||||
.align_x(Alignment::Center);
|
.align_x(Alignment::Center);
|
||||||
|
|
||||||
// Return the vertical spin button from the match statement.
|
// Return the vertical spin button from the match statement.
|
||||||
Self::new(content_list)
|
Element::new(content_list)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue