Allow override of title and button label, implement choices
This commit is contained in:
parent
cce891827e
commit
1b2ab2c93c
1 changed files with 125 additions and 27 deletions
152
src/dialog.rs
152
src/dialog.rs
|
|
@ -14,7 +14,7 @@ use cosmic::{
|
|||
keyboard::{Event as KeyEvent, Modifiers},
|
||||
subscription::{self, Subscription},
|
||||
widget::scrollable,
|
||||
window, Event, Length, Size,
|
||||
window, Alignment, Event, Length, Size,
|
||||
},
|
||||
theme,
|
||||
widget::{self, menu::KeyBind, segmented_button},
|
||||
|
|
@ -69,6 +69,13 @@ impl DialogKind {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn accept_label(&self) -> String {
|
||||
match self {
|
||||
Self::SaveFile { .. } => fl!("save"),
|
||||
_ => fl!("open"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_dir(&self) -> bool {
|
||||
matches!(self, Self::OpenFolder | Self::OpenMultipleFolders)
|
||||
}
|
||||
|
|
@ -82,6 +89,31 @@ impl DialogKind {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct DialogChoiceOption {
|
||||
pub id: String,
|
||||
pub label: String,
|
||||
}
|
||||
|
||||
impl AsRef<str> for DialogChoiceOption {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.label
|
||||
}
|
||||
}
|
||||
|
||||
pub enum DialogChoice {
|
||||
CheckBox {
|
||||
id: String,
|
||||
label: String,
|
||||
value: bool,
|
||||
},
|
||||
ComboBox {
|
||||
id: String,
|
||||
label: String,
|
||||
options: Vec<DialogChoiceOption>,
|
||||
selected: Option<usize>,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct Dialog<M> {
|
||||
cosmic: Cosmic<App>,
|
||||
mapper: fn(DialogMessage) -> M,
|
||||
|
|
@ -142,6 +174,28 @@ impl<M: Send + 'static> Dialog<M> {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn set_title(&mut self, title: impl Into<String>) -> Command<M> {
|
||||
let mapper = self.mapper;
|
||||
self.cosmic.app.title = title.into();
|
||||
self.cosmic
|
||||
.app
|
||||
.update_title()
|
||||
.map(DialogMessage)
|
||||
.map(move |message| app::Message::App(mapper(message)))
|
||||
}
|
||||
|
||||
pub fn set_accept_label(&mut self, accept_label: impl Into<String>) {
|
||||
self.cosmic.app.accept_label = accept_label.into();
|
||||
}
|
||||
|
||||
pub fn choices(&self) -> &[DialogChoice] {
|
||||
&self.cosmic.app.choices
|
||||
}
|
||||
|
||||
pub fn set_choices(&mut self, choices: impl Into<Vec<DialogChoice>>) {
|
||||
self.cosmic.app.choices = choices.into();
|
||||
}
|
||||
|
||||
pub fn subscription(&self) -> Subscription<M> {
|
||||
self.cosmic
|
||||
.subscription()
|
||||
|
|
@ -186,6 +240,7 @@ struct Flags {
|
|||
#[derive(Clone, Debug)]
|
||||
enum Message {
|
||||
Cancel,
|
||||
Choice(usize, usize),
|
||||
Filename(String),
|
||||
Modifiers(Modifiers),
|
||||
NotifyEvents(Vec<DebouncedEvent>),
|
||||
|
|
@ -222,6 +277,9 @@ impl PartialEq for WatcherWrapper {
|
|||
struct App {
|
||||
core: Core,
|
||||
flags: Flags,
|
||||
title: String,
|
||||
accept_label: String,
|
||||
choices: Vec<DialogChoice>,
|
||||
filename_id: widget::Id,
|
||||
modifiers: Modifiers,
|
||||
nav_model: segmented_button::SingleSelectModel,
|
||||
|
|
@ -251,9 +309,8 @@ impl App {
|
|||
}
|
||||
|
||||
fn update_title(&mut self) -> Command<Message> {
|
||||
let title = self.flags.kind.title();
|
||||
self.set_header_title(title.clone());
|
||||
self.set_window_title(title, self.main_window_id())
|
||||
self.set_header_title(self.title.clone());
|
||||
self.set_window_title(self.title.clone(), self.main_window_id())
|
||||
}
|
||||
|
||||
fn update_watcher(&mut self) -> Command<Message> {
|
||||
|
|
@ -332,6 +389,9 @@ impl Application for App {
|
|||
//TODO: make set_nav_bar_toggle_condensed pub
|
||||
core.nav_bar_toggle_condensed();
|
||||
|
||||
let title = flags.kind.title();
|
||||
let accept_label = flags.kind.accept_label();
|
||||
|
||||
let mut nav_model = segmented_button::ModelBuilder::default();
|
||||
if let Some(dir) = dirs::home_dir() {
|
||||
nav_model = nav_model.insert(move |b| {
|
||||
|
|
@ -374,6 +434,9 @@ impl Application for App {
|
|||
let mut app = App {
|
||||
core,
|
||||
flags,
|
||||
title,
|
||||
accept_label,
|
||||
choices: Vec::new(),
|
||||
filename_id: widget::Id::unique(),
|
||||
modifiers: Modifiers::empty(),
|
||||
nav_model: nav_model.build(),
|
||||
|
|
@ -448,6 +511,22 @@ impl Application for App {
|
|||
return window::close(self.main_window_id());
|
||||
}
|
||||
}
|
||||
Message::Choice(choice_i, option_i) => {
|
||||
if let Some(choice) = self.choices.get_mut(choice_i) {
|
||||
match choice {
|
||||
DialogChoice::CheckBox { value, .. } => *value = option_i > 0,
|
||||
DialogChoice::ComboBox {
|
||||
options, selected, ..
|
||||
} => {
|
||||
if option_i < options.len() {
|
||||
*selected = Some(option_i);
|
||||
} else {
|
||||
*selected = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::Filename(new_filename) => {
|
||||
// Select based on filename
|
||||
self.tab.select_name(&new_filename);
|
||||
|
|
@ -693,30 +772,49 @@ impl Application for App {
|
|||
.map(move |message| Message::TabMessage(message)),
|
||||
);
|
||||
|
||||
tab_column = tab_column.push(
|
||||
widget::row::with_children(vec![
|
||||
if let DialogKind::SaveFile { filename } = &self.flags.kind {
|
||||
widget::text_input("", filename)
|
||||
.id(self.filename_id.clone())
|
||||
.on_input(Message::Filename)
|
||||
.on_submit(Message::Save(false))
|
||||
.into()
|
||||
} else {
|
||||
widget::horizontal_space(Length::Fill).into()
|
||||
},
|
||||
widget::button::standard(fl!("cancel"))
|
||||
.on_press(Message::Cancel)
|
||||
.into(),
|
||||
if self.flags.kind.save() {
|
||||
widget::button::suggested(fl!("save")).on_press(Message::Save(false))
|
||||
} else {
|
||||
widget::button::suggested(fl!("open")).on_press(Message::Open)
|
||||
}
|
||||
.into(),
|
||||
])
|
||||
let mut row = widget::row::with_capacity(self.choices.len() * 2 + 3)
|
||||
.align_items(Alignment::Center)
|
||||
.padding(space_xxs)
|
||||
.spacing(space_xxs),
|
||||
);
|
||||
.spacing(space_xxs);
|
||||
if let DialogKind::SaveFile { filename } = &self.flags.kind {
|
||||
row = row.push(
|
||||
widget::text_input("", filename)
|
||||
.id(self.filename_id.clone())
|
||||
.on_input(Message::Filename)
|
||||
.on_submit(Message::Save(false)),
|
||||
);
|
||||
} else {
|
||||
row = row.push(widget::horizontal_space(Length::Fill));
|
||||
}
|
||||
for (choice_i, choice) in self.choices.iter().enumerate() {
|
||||
match choice {
|
||||
DialogChoice::CheckBox { label, value, .. } => {
|
||||
row = row.push(widget::text::body(label));
|
||||
row = row.push(widget::checkbox("", *value, move |checked| {
|
||||
Message::Choice(choice_i, if checked { 1 } else { 0 })
|
||||
}));
|
||||
}
|
||||
DialogChoice::ComboBox {
|
||||
label,
|
||||
options,
|
||||
selected,
|
||||
..
|
||||
} => {
|
||||
row = row.push(widget::text::body(label));
|
||||
row = row.push(widget::dropdown(options, *selected, move |option_i| {
|
||||
Message::Choice(choice_i, option_i)
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
row = row.push(widget::button::standard(fl!("cancel")).on_press(Message::Cancel));
|
||||
row = row.push(if self.flags.kind.save() {
|
||||
widget::button::suggested(&self.accept_label).on_press(Message::Save(false))
|
||||
} else {
|
||||
widget::button::suggested(&self.accept_label).on_press(Message::Open)
|
||||
});
|
||||
|
||||
tab_column = tab_column.push(row);
|
||||
|
||||
let content: Element<_> = tab_column.into();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue