diff --git a/Userland/DevTools/HackStudio/EditorWrapper.h b/Userland/DevTools/HackStudio/EditorWrapper.h index ea72912180..5493be746e 100644 --- a/Userland/DevTools/HackStudio/EditorWrapper.h +++ b/Userland/DevTools/HackStudio/EditorWrapper.h @@ -37,7 +37,8 @@ public: void set_mode_displayable(); void set_mode_non_displayable(); void set_filename(const String&); - const String& filename() const {return m_filename;} + const String& filename() const { return m_filename; } + bool document_dirty() const { return m_document_dirty; } private: EditorWrapper(); @@ -48,7 +49,7 @@ private: RefPtr m_filename_label; RefPtr m_cursor_label; RefPtr m_editor; - bool m_document_dirty {false}; + bool m_document_dirty { false }; }; } diff --git a/Userland/DevTools/HackStudio/HackStudioWidget.cpp b/Userland/DevTools/HackStudio/HackStudioWidget.cpp index 5f7f0e5d32..5082480f96 100644 --- a/Userland/DevTools/HackStudio/HackStudioWidget.cpp +++ b/Userland/DevTools/HackStudio/HackStudioWidget.cpp @@ -896,6 +896,9 @@ void HackStudioWidget::create_toolbar(GUI::Widget& parent) NonnullRefPtr HackStudioWidget::create_build_action() { return GUI::Action::create("&Build", { Mod_Ctrl, Key_B }, Gfx::Bitmap::load_from_file("/res/icons/16x16/build.png"), [this](auto&) { + if (warn_unsaved_changes("There are unsaved changes, do you want to save before building?") == ContinueDecision::No) + return; + reveal_action_tab(*m_terminal_wrapper); build(*m_terminal_wrapper); m_stop_action->set_enabled(true); @@ -1129,4 +1132,35 @@ HackStudioWidget::~HackStudioWidget() } } +HackStudioWidget::ContinueDecision HackStudioWidget::warn_unsaved_changes(const String& prompt) +{ + if (!any_document_is_dirty()) + return ContinueDecision::Yes; + + auto result = GUI::MessageBox::show(window(), prompt, "Unsaved changes", GUI::MessageBox::Type::Warning, GUI::MessageBox::InputType::YesNoCancel); + + if (result == GUI::MessageBox::ExecCancel) + return ContinueDecision::No; + + if (result == GUI::MessageBox::ExecYes) { + for (auto& editor_wrapper : m_all_editor_wrappers) { + if (editor_wrapper.document_dirty()) { + editor_wrapper.save(); + } + } + } + + return ContinueDecision::Yes; +} + +bool HackStudioWidget::any_document_is_dirty() const +{ + for (auto& editor_wrapper : m_all_editor_wrappers) { + if (editor_wrapper.document_dirty()) { + return true; + } + } + return false; +} + } diff --git a/Userland/DevTools/HackStudio/HackStudioWidget.h b/Userland/DevTools/HackStudio/HackStudioWidget.h index 5d386712fa..be71cd480b 100644 --- a/Userland/DevTools/HackStudio/HackStudioWidget.h +++ b/Userland/DevTools/HackStudio/HackStudioWidget.h @@ -50,6 +50,12 @@ public: return *m_locator; } + enum class ContinueDecision { + No, + Yes + }; + ContinueDecision warn_unsaved_changes(const String& prompt); + private: static String get_full_path_of_serenity_source(const String& file); Vector selected_file_paths() const; @@ -112,6 +118,7 @@ private: void build(TerminalWrapper& wrapper); void hide_action_tabs(); + bool any_document_is_dirty() const; NonnullRefPtrVector m_all_editor_wrappers; RefPtr m_current_editor_wrapper; diff --git a/Userland/DevTools/HackStudio/main.cpp b/Userland/DevTools/HackStudio/main.cpp index 0cb393c89b..cea0bda219 100644 --- a/Userland/DevTools/HackStudio/main.cpp +++ b/Userland/DevTools/HackStudio/main.cpp @@ -81,6 +81,12 @@ int main(int argc, char** argv) s_hack_studio_widget->initialize_menubar(menubar); s_window->set_menubar(menubar); + s_window->on_close_request = [&]() -> GUI::Window::CloseRequestDecision { + if (s_hack_studio_widget->warn_unsaved_changes("There are unsaved changes, do you want to save before exiting?") == HackStudioWidget::ContinueDecision::Yes) + return GUI::Window::CloseRequestDecision::Close; + return GUI::Window::CloseRequestDecision::StayOpen; + }; + s_window->show(); s_hack_studio_widget->update_actions();