parent
5c9691c66a
commit
93e993d72e
1 changed files with 78 additions and 82 deletions
160
src/main.rs
160
src/main.rs
|
|
@ -17,7 +17,6 @@ use cosmic::{
|
||||||
widget::text,
|
widget::text,
|
||||||
window, Alignment, Background, Color, Length, Limits, Point,
|
window, Alignment, Background, Color, Length, Limits, Point,
|
||||||
},
|
},
|
||||||
prelude::CollectionWidget,
|
|
||||||
style, theme,
|
style, theme,
|
||||||
widget::{self, button, icon, nav_bar, segmented_button},
|
widget::{self, button, icon, nav_bar, segmented_button},
|
||||||
Application, ApplicationExt, Apply, Element,
|
Application, ApplicationExt, Apply, Element,
|
||||||
|
|
@ -348,6 +347,7 @@ pub enum Message {
|
||||||
ProjectSearchResult(ProjectSearchResult),
|
ProjectSearchResult(ProjectSearchResult),
|
||||||
ProjectSearchSubmit,
|
ProjectSearchSubmit,
|
||||||
ProjectSearchValue(String),
|
ProjectSearchValue(String),
|
||||||
|
PromptSaveChanges(segmented_button::Entity),
|
||||||
Quit,
|
Quit,
|
||||||
Redo,
|
Redo,
|
||||||
Save,
|
Save,
|
||||||
|
|
@ -384,7 +384,6 @@ pub enum ContextPage {
|
||||||
GitManagement,
|
GitManagement,
|
||||||
//TODO: Move search to pop-up
|
//TODO: Move search to pop-up
|
||||||
ProjectSearch,
|
ProjectSearch,
|
||||||
PromptSaveChanges(segmented_button::Entity),
|
|
||||||
Settings,
|
Settings,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -395,12 +394,16 @@ impl ContextPage {
|
||||||
Self::DocumentStatistics => fl!("document-statistics"),
|
Self::DocumentStatistics => fl!("document-statistics"),
|
||||||
Self::GitManagement => fl!("git-management"),
|
Self::GitManagement => fl!("git-management"),
|
||||||
Self::ProjectSearch => fl!("project-search"),
|
Self::ProjectSearch => fl!("project-search"),
|
||||||
Self::PromptSaveChanges(_) => fl!("prompt-save-changes-title"),
|
|
||||||
Self::Settings => fl!("settings"),
|
Self::Settings => fl!("settings"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
|
enum DialogPage {
|
||||||
|
PromptSave(segmented_button::Entity),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
pub enum Find {
|
pub enum Find {
|
||||||
None,
|
None,
|
||||||
|
|
@ -425,6 +428,7 @@ pub struct App {
|
||||||
context_page: ContextPage,
|
context_page: ContextPage,
|
||||||
text_box_id: widget::Id,
|
text_box_id: widget::Id,
|
||||||
dialog_opt: Option<Dialog<Message>>,
|
dialog_opt: Option<Dialog<Message>>,
|
||||||
|
dialog_page_opt: Option<DialogPage>,
|
||||||
find_opt: Option<bool>,
|
find_opt: Option<bool>,
|
||||||
find_replace_id: widget::Id,
|
find_replace_id: widget::Id,
|
||||||
find_replace_value: String,
|
find_replace_value: String,
|
||||||
|
|
@ -1058,55 +1062,6 @@ impl App {
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prompt_save_changes(&self, entity: segmented_button::Entity) -> Element<Message> {
|
|
||||||
let (spacing, warning_color) = {
|
|
||||||
let theme = self.core().system_theme().cosmic();
|
|
||||||
(theme.spacing, theme.warning_text_color())
|
|
||||||
};
|
|
||||||
|
|
||||||
// "Save" is displayed regardless if the file was already saved because the message handles
|
|
||||||
// "Save As" if necessary
|
|
||||||
let save = fl!("save");
|
|
||||||
let save_button = widget::button::suggested(save)
|
|
||||||
.on_press(Message::Save)
|
|
||||||
.width(Length::Fill);
|
|
||||||
|
|
||||||
// "Save As" is only shown if the file has been saved previously
|
|
||||||
// Rationale: The user may want to save the modified buffer as a new file
|
|
||||||
let save_as_button = match self.tab_model.data(entity) {
|
|
||||||
Some(Tab::Editor(tab)) if tab.path_opt.is_some() => {
|
|
||||||
let save_as = fl!("save-as");
|
|
||||||
let save_as_button = widget::button::suggested(save_as)
|
|
||||||
.on_press(Message::SaveAsDialog)
|
|
||||||
.width(Length::Fill);
|
|
||||||
Some(save_as_button)
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: Maybe a button to show diffs in a split?
|
|
||||||
// And more info, such as the path if any?
|
|
||||||
// let diff = widget::text(fl!("diff"));
|
|
||||||
// let diff_button = widget::button(diff.into());
|
|
||||||
|
|
||||||
// Discards unsaved changes
|
|
||||||
let discard = fl!("discard");
|
|
||||||
let discard_button = widget::button::destructive(discard)
|
|
||||||
.on_press(Message::TabCloseForce(entity))
|
|
||||||
.width(Length::Fill);
|
|
||||||
|
|
||||||
widget::column::with_capacity(3)
|
|
||||||
.push(
|
|
||||||
widget::text(fl!("prompt-unsaved-changes"))
|
|
||||||
.style(theme::Text::Color(warning_color.into())),
|
|
||||||
)
|
|
||||||
.push(save_button)
|
|
||||||
.push_maybe(save_as_button)
|
|
||||||
.push(discard_button)
|
|
||||||
.spacing(spacing.space_s)
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn settings(&self) -> Element<Message> {
|
fn settings(&self) -> Element<Message> {
|
||||||
let app_theme_selected = match self.config.app_theme {
|
let app_theme_selected = match self.config.app_theme {
|
||||||
AppTheme::Dark => 1,
|
AppTheme::Dark => 1,
|
||||||
|
|
@ -1271,6 +1226,7 @@ impl Application for App {
|
||||||
context_page: ContextPage::Settings,
|
context_page: ContextPage::Settings,
|
||||||
text_box_id: widget::Id::unique(),
|
text_box_id: widget::Id::unique(),
|
||||||
dialog_opt: None,
|
dialog_opt: None,
|
||||||
|
dialog_page_opt: None,
|
||||||
find_opt: None,
|
find_opt: None,
|
||||||
find_replace_id: widget::Id::unique(),
|
find_replace_id: widget::Id::unique(),
|
||||||
find_replace_value: String::new(),
|
find_replace_value: String::new(),
|
||||||
|
|
@ -1425,6 +1381,52 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dialog(&self) -> Option<Element<Self::Message>> {
|
||||||
|
let Some(dialog) = self.dialog_page_opt else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
match dialog {
|
||||||
|
DialogPage::PromptSave(entity) => {
|
||||||
|
// "Save" is displayed regardless if the file was already saved because the message handles
|
||||||
|
// "Save As" if necessary
|
||||||
|
let save = fl!("save");
|
||||||
|
let save_button = widget::button::suggested(save).on_press(Message::Save);
|
||||||
|
|
||||||
|
// "Save As" is only shown if the file has been saved previously
|
||||||
|
// Rationale: The user may want to save the modified buffer as a new file
|
||||||
|
let save_as_button = match self.tab_model.data(entity) {
|
||||||
|
Some(Tab::Editor(tab)) if tab.path_opt.is_some() => {
|
||||||
|
let save_as = fl!("save-as");
|
||||||
|
let save_as_button =
|
||||||
|
widget::button::suggested(save_as).on_press(Message::SaveAsDialog);
|
||||||
|
Some(save_as_button)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Discards unsaved changes
|
||||||
|
let discard = fl!("discard");
|
||||||
|
let discard_button =
|
||||||
|
widget::button::destructive(discard).on_press(Message::TabCloseForce(entity));
|
||||||
|
|
||||||
|
let mut dialog = widget::dialog(fl!("prompt-save-changes-title"))
|
||||||
|
.body(fl!("prompt-unsaved-changes"))
|
||||||
|
.icon(icon::from_name("dialog-warning-symbolic").size(64))
|
||||||
|
.primary_action(save_button);
|
||||||
|
dialog = if let Some(save_as_button) = save_as_button {
|
||||||
|
dialog
|
||||||
|
.secondary_action(save_as_button)
|
||||||
|
.tertiary_action(discard_button)
|
||||||
|
} else {
|
||||||
|
dialog.secondary_action(discard_button)
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(dialog.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn update(&mut self, message: Message) -> Command<Message> {
|
fn update(&mut self, message: Message) -> Command<Message> {
|
||||||
match message {
|
match message {
|
||||||
Message::AppTheme(app_theme) => {
|
Message::AppTheme(app_theme) => {
|
||||||
|
|
@ -1979,6 +1981,9 @@ impl Application for App {
|
||||||
Message::ProjectSearchValue(value) => {
|
Message::ProjectSearchValue(value) => {
|
||||||
self.project_search_value = value;
|
self.project_search_value = value;
|
||||||
}
|
}
|
||||||
|
Message::PromptSaveChanges(entity) => {
|
||||||
|
self.dialog_page_opt = Some(DialogPage::PromptSave(entity));
|
||||||
|
}
|
||||||
Message::Quit => {
|
Message::Quit => {
|
||||||
//TODO: prompt for save?
|
//TODO: prompt for save?
|
||||||
return window::close(window::Id::MAIN);
|
return window::close(window::Id::MAIN);
|
||||||
|
|
@ -2049,8 +2054,8 @@ impl Application for App {
|
||||||
self.tab_model.text_set(entity, title);
|
self.tab_model.text_set(entity, title);
|
||||||
}
|
}
|
||||||
// Close save changes prompt only if the dialog succeeded
|
// Close save changes prompt only if the dialog succeeded
|
||||||
if let ContextPage::PromptSaveChanges(_) = self.context_page {
|
if self.dialog_page_opt == Some(DialogPage::PromptSave(entity)) {
|
||||||
self.core_mut().window.show_context = false;
|
self.dialog_page_opt = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2089,6 +2094,11 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Message::TabActivate(entity) => {
|
Message::TabActivate(entity) => {
|
||||||
|
// Close save changes dialog if switching to a different tab for consistency
|
||||||
|
if self.dialog_page_opt != Some(DialogPage::PromptSave(entity)) {
|
||||||
|
self.dialog_page_opt = None;
|
||||||
|
}
|
||||||
|
|
||||||
self.tab_model.activate(entity);
|
self.tab_model.activate(entity);
|
||||||
return self.update_tab();
|
return self.update_tab();
|
||||||
}
|
}
|
||||||
|
|
@ -2121,26 +2131,20 @@ impl Application for App {
|
||||||
match self.tab_model.data_mut::<Tab>(entity) {
|
match self.tab_model.data_mut::<Tab>(entity) {
|
||||||
// Only match a changed editor tab...
|
// Only match a changed editor tab...
|
||||||
Some(Tab::Editor(tab)) if tab.changed() => {
|
Some(Tab::Editor(tab)) if tab.changed() => {
|
||||||
// * The save prompt shouldn't be closed if `TabClose` is emitted again
|
// The save prompt shouldn't be closed if `TabClose` is emitted again for
|
||||||
// * Prompt should be opened if no pages are open
|
// the same tab.
|
||||||
// * Prompt should replace a different page (e.g. Settings)
|
|
||||||
//
|
//
|
||||||
// `PromptSaveChanges` for a different tab other than `entity` counts as
|
// `PromptSave` for a different tab other than `entity` counts as
|
||||||
// a different page
|
// a different dialog
|
||||||
// Ex. If tab 2 and 3 both have unsaved changes and `PromptSaveChanges` is
|
// Ex. If tab 2 and 3 both have unsaved changes and `PromptSave` is
|
||||||
// open for tab 2, closing tab 3 should open the page for tab 3
|
// emitted for tab 2, closing tab 3 should open the dialog for tab 3 in
|
||||||
if !self.core().window.show_context
|
// order for `Message::Save` to save the correct tab.
|
||||||
|| self.context_page != ContextPage::PromptSaveChanges(entity)
|
return Command::batch([
|
||||||
{
|
|
||||||
// Focus the tab in case the user is closing an unfocussed tab
|
// Focus the tab in case the user is closing an unfocussed tab
|
||||||
// Otherwise, closing an unfocussed tab would be very confusing
|
// Otherwise, closing an unfocussed tab would be very confusing
|
||||||
return Command::batch([
|
self.update(Message::TabActivate(entity)),
|
||||||
self.update(Message::TabActivate(entity)),
|
self.update(Message::PromptSaveChanges(entity)),
|
||||||
self.update(Message::ToggleContextPage(
|
]);
|
||||||
ContextPage::PromptSaveChanges(entity),
|
|
||||||
)),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// ...or else just close it
|
// ...or else just close it
|
||||||
_ => {
|
_ => {
|
||||||
|
|
@ -2166,16 +2170,9 @@ impl Application for App {
|
||||||
self.open_tab(None);
|
self.open_tab(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close PromptSaveChanges page if open for this entity
|
// Close PromptSave dialog if open for this entity
|
||||||
if self.core().window.show_context
|
if self.dialog_page_opt == Some(DialogPage::PromptSave(entity)) {
|
||||||
&& matches!(self.context_page, ContextPage::PromptSaveChanges(_))
|
self.dialog_page_opt = None;
|
||||||
{
|
|
||||||
return Command::batch([
|
|
||||||
self.update(Message::ToggleContextPage(ContextPage::PromptSaveChanges(
|
|
||||||
entity,
|
|
||||||
))),
|
|
||||||
self.update_tab(),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.update_tab();
|
return self.update_tab();
|
||||||
|
|
@ -2360,7 +2357,6 @@ impl Application for App {
|
||||||
ContextPage::DocumentStatistics => self.document_statistics(),
|
ContextPage::DocumentStatistics => self.document_statistics(),
|
||||||
ContextPage::GitManagement => self.git_management(),
|
ContextPage::GitManagement => self.git_management(),
|
||||||
ContextPage::ProjectSearch => self.project_search(),
|
ContextPage::ProjectSearch => self.project_search(),
|
||||||
ContextPage::PromptSaveChanges(entity) => self.prompt_save_changes(entity),
|
|
||||||
ContextPage::Settings => self.settings(),
|
ContextPage::Settings => self.settings(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue