Skip to content

Commit

Permalink
#4446_Unite_dialogs_Close_New_Sign_Out
Browse files Browse the repository at this point in the history
  • Loading branch information
egrebenchenko authored Nov 7, 2024
1 parent 50b6108 commit ba978ec
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 167 deletions.
89 changes: 10 additions & 79 deletions source/MRCommonPlugins/ViewerButtons/MRSceneControlMenuItems.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "MRViewer/MRRibbonConstants.h"
#include "MRViewer/MRUIStyle.h"
#include "MRViewer/MRSceneCache.h"
#include "MRViewer/MRUISaveChangesPopup.h"
#include <array>

namespace
Expand Down Expand Up @@ -97,85 +98,15 @@ void ResetSceneMenuItem::preDraw_()
ImGui::SetNextWindowSize( windowSize, ImGuiCond_Always );
popupId_ = ImGui::GetID( "New scene##new scene" );


ImGui::PushStyleVar( ImGuiStyleVar_ItemSpacing, { 2.0f * cDefaultItemSpacing * scaling, 3.0f * cDefaultItemSpacing * scaling } );
ImGui::PushStyleVar( ImGuiStyleVar_WindowPadding, { cModalWindowPaddingX * scaling, cModalWindowPaddingY * scaling } );
if ( ImGui::BeginModalNoAnimation( "New scene##new scene", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar ) )
{
auto headerFont = RibbonFontManager::getFontByTypeStatic( RibbonFontManager::FontType::Headline );
if ( headerFont )
ImGui::PushFont( headerFont );

const auto headerWidth = ImGui::CalcTextSize( "New Scene" ).x;
ImGui::SetCursorPosX( ( windowSize.x - headerWidth ) * 0.5f );
ImGui::Text( "New Scene" );

if ( headerFont )
ImGui::PopFont();

// do not suggest saving empty scene
const bool showSave = !SceneCache::getAllObjects<VisualObject, ObjectSelectivityType::Selectable>().empty();
if ( showSave )
{
const char* text = "Save your changes?";
ImGui::SetCursorPosX( ( windowSize.x - ImGui::CalcTextSize( text ).x ) * 0.5f );
ImGui::Text( "%s", text );
}

const auto style = ImGui::GetStyle();
ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, { style.FramePadding.x, cButtonPadding * scaling } );

const float p = ImGui::GetStyle().ItemSpacing.x;
const Vector2f btnSize{ showSave ? ( ImGui::GetContentRegionAvail().x - p * 2 ) / 3.f : ( ImGui::GetContentRegionAvail().x - p ) / 2.f, 0 };

if ( showSave )
{
if ( UI::button( "Save", btnSize, ImGuiKey_Enter ) )
{
auto savePath = SceneRoot::getScenePath();
if ( savePath.empty() )
savePath = saveFileDialog( { .filters = SceneSave::getFilters() } );

ImGui::CloseCurrentPopup();
if ( !savePath.empty() )
ProgressBar::orderWithMainThreadPostProcessing( "Saving scene", [this, savePath, &root = SceneRoot::get()]()->std::function<void()>
{
auto res = ObjectSave::toAnySupportedSceneFormat( root, savePath, ProgressBar::callBackSetProgress );

return[this, savePath, res]()
{
if ( res )
{
getViewerInstance().onSceneSaved( savePath );
resetScene_();
}
else
showError( "Error saving scene: " + res.error() );
};
} );
}
UI::setTooltipIfHovered( "Save current scene and then remove all objects", scaling );
ImGui::SameLine();
}

if ( UI::buttonCommonSize( showSave ? "Don't Save" : "New", btnSize, ImGuiKey_N ) )
{
ImGui::CloseCurrentPopup();
resetScene_();
}
UI::setTooltipIfHovered( "Remove all objects without saving and ability to restore them", scaling );
ImGui::SameLine();
if ( UI::buttonCommonSize( "Cancel", btnSize, ImGuiKey_Escape ) )
ImGui::CloseCurrentPopup();

UI::setTooltipIfHovered( "Do not remove any objects, return back", scaling );

if ( ImGui::IsMouseClicked( 0 ) && !( ImGui::IsAnyItemHovered() || ImGui::IsWindowHovered( ImGuiHoveredFlags_AnyWindow ) ) )
ImGui::CloseCurrentPopup();
ImGui::PopStyleVar();
ImGui::EndPopup();
}
ImGui::PopStyleVar( 2 );
UI::SaveChangesPopupSettings settings;
settings.scaling = scaling;
settings.header = "New Scene";
settings.shortCloseText = "New";
settings.saveTooltip = "Save current scene and then remove all objects";
settings.dontSaveTooltip = "Remove all objects without saving and ability to restore them";
settings.cancelTooltip = "Do not remove any objects, return back";
settings.onOk = [this] () { resetScene_(); };
UI::saveChangesPopup( "New scene##new scene", settings );
}

void ResetSceneMenuItem::resetScene_()
Expand Down
104 changes: 16 additions & 88 deletions source/MRViewer/MRSaveOnClose.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <MRMesh/MRVisualObject.h>
#include "ImGuiHelpers.h"
#include "MRPch/MRSpdlog.h"
#include "MRUISaveChangesPopup.h"
#include <imgui_internal.h>
#include <GLFW/glfw3.h>

Expand Down Expand Up @@ -57,102 +58,29 @@ void SaveOnClosePlugin::preDraw_()
}
else if ( noModalWasPresent )
{
ImGui::OpenPopup( "Application close##modal" );
ImGui::OpenPopup( "Application Close##modal" );
showCloseModal_ = false;
}
else
{
showCloseModal_ = false;
}
}
const ImVec2 windowSize{ MR::cModalWindowWidth * scaling, -1 };
ImGui::SetNextWindowSize( windowSize, ImGuiCond_Always );
ImGui::PushStyleVar( ImGuiStyleVar_WindowPadding, { cModalWindowPaddingX * scaling, cModalWindowPaddingY * scaling } );
ImGui::PushStyleVar( ImGuiStyleVar_ItemSpacing, { 2.0f * cDefaultItemSpacing * scaling, 3.0f * cDefaultItemSpacing * scaling } );
if ( ImGui::BeginModalNoAnimation( "Application close##modal", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar ) )
{
auto headerFont = RibbonFontManager::getFontByTypeStatic( RibbonFontManager::FontType::Headline );
if ( headerFont )
ImGui::PushFont( headerFont );

const auto headerWidth = ImGui::CalcTextSize( "Application Close" ).x;

ImGui::SetCursorPosX( ( windowSize.x - headerWidth ) * 0.5f );
ImGui::Text( "Application Close" );

if ( headerFont )
ImGui::PopFont();

// do not suggest saving empty scene
const bool showSave = !SceneCache::getAllObjects<VisualObject, ObjectSelectivityType::Selectable>().empty();
if ( showSave )
{
const char* text = "Save your changes?";
ImGui::SetCursorPosX( ( windowSize.x - ImGui::CalcTextSize( text ).x ) * 0.5f );
ImGui::Text( "%s", text );
}

const auto style = ImGui::GetStyle();
ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, { style.FramePadding.x, cButtonPadding * scaling } );

const float p = ImGui::GetStyle().ItemSpacing.x;
const Vector2f btnSize{ showSave ? ( ImGui::GetContentRegionAvail().x - p * 2 ) / 3.f : ( ImGui::GetContentRegionAvail().x - p ) / 2.f, 0 };

if ( showSave )
{
if ( UI::button( "Save", btnSize, ImGuiKey_Enter ) )
{
auto savePath = SceneRoot::getScenePath();
if ( savePath.empty() )
savePath = saveFileDialog( { .filters = SceneSave::getFilters() } );

ImGui::CloseCurrentPopup();
if ( !savePath.empty() )
ProgressBar::orderWithMainThreadPostProcessing( "Saving scene", [&shouldClose = shouldClose_, savePath, &root = SceneRoot::get()]()->std::function<void()>
{
auto res = ObjectSave::toAnySupportedSceneFormat( root, savePath, ProgressBar::callBackSetProgress );

return[&shouldClose = shouldClose, savePath, res]()
{
if ( res )
{
getViewerInstance().onSceneSaved( savePath );
glfwSetWindowShouldClose( Viewer::instance()->window, true );
shouldClose = true;
}
else
showError( "Error saving scene: " + res.error() );
};
} );
}
UI::setTooltipIfHovered( "Save the current scene and close the application", scaling );
ImGui::SameLine( 0, p );
}

if ( UI::button( showSave ? "Don't Save" : "Close", btnSize, ImGuiKey_N ) )
{
glfwSetWindowShouldClose( Viewer::instance()->window, true );
shouldClose_ = true;
ImGui::CloseCurrentPopup();
}
UI::setTooltipIfHovered( "Close the application without saving", scaling );

ImGui::SameLine( 0, p );
if ( UI::button( "Cancel", btnSize, ImGuiKey_Escape ) )
{
ImGui::CloseCurrentPopup();
}
UI::setTooltipIfHovered( "Do not close the application", scaling );

if ( ImGui::IsMouseClicked( 0 ) && !( ImGui::IsAnyItemHovered() || ImGui::IsWindowHovered( ImGuiHoveredFlags_AnyWindow ) ) )
ImGui::CloseCurrentPopup();

ImGui::PopStyleVar();
ImGui::EndPopup();
}

ImGui::PopStyleVar( 2 );

UI::SaveChangesPopupSettings settings;
settings.scaling = scaling;
settings.header = "Application Close";
settings.saveTooltip = "Save the current scene and close the application";
settings.dontSaveTooltip = "Close the application without saving";
settings.cancelTooltip = "Do not close the application";
settings.onOk = [this] ()
{
glfwSetWindowShouldClose( Viewer::instance()->window, true );
shouldClose_ = true;
};
UI::saveChangesPopup(
"Application Close##modal",
settings );
}

void SaveOnClosePlugin::init( Viewer* _viewer )
Expand Down
116 changes: 116 additions & 0 deletions source/MRViewer/MRUISaveChangesPopup.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#include "MRUISaveChangesPopup.h"

#include "MRRibbonConstants.h"
#include "MRUIStyle.h"
#include "ImGuiHelpers.h"
#include "MRRibbonFontManager.h"
#include "MRFileDialog.h"
#include "MRProgressBar.h"
#include "MRShowModal.h"
#include "MRViewer.h"
#include "ImGuiMenu.h"
#include "MRSceneCache.h"
#include "MRMesh/MRSceneRoot.h"
#include "MRMesh/MRIOFormatsRegistry.h"
#include "MRMesh/MRObjectSave.h"
#include "MRMesh/MRVisualObject.h"

namespace MR
{

namespace UI
{

void saveChangesPopup( const char* str_id, const SaveChangesPopupSettings& settings )
{
const ImVec2 windowSize{ cModalWindowWidth * settings.scaling, -1 };
ImGui::SetNextWindowSize( windowSize, ImGuiCond_Always );

ImGui::PushStyleVar( ImGuiStyleVar_ItemSpacing, { 2.0f * cDefaultItemSpacing * settings.scaling, 3.0f * cDefaultItemSpacing * settings.scaling } );
ImGui::PushStyleVar( ImGuiStyleVar_WindowPadding, { cModalWindowPaddingX * settings.scaling, cModalWindowPaddingY * settings.scaling } );
if ( ImGui::BeginModalNoAnimation( str_id, nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar ) )
{
auto headerFont = RibbonFontManager::getFontByTypeStatic( RibbonFontManager::FontType::Headline );
if ( headerFont )
ImGui::PushFont( headerFont );

const auto headerWidth = ImGui::CalcTextSize( settings.header.c_str() ).x;
ImGui::SetCursorPosX( ( windowSize.x - headerWidth ) * 0.5f );
ImGui::Text( "%s", settings.header.c_str() );

if ( headerFont )
ImGui::PopFont();

// do not suggest saving empty scene
const bool showSave = !SceneCache::getAllObjects<VisualObject, ObjectSelectivityType::Selectable>().empty();
if ( showSave )
{
const char* text = "Save your changes?";
ImGui::SetCursorPosX( ( windowSize.x - ImGui::CalcTextSize( text ).x ) * 0.5f );
ImGui::Text( "%s", text );
}

const auto style = ImGui::GetStyle();
ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, { style.FramePadding.x, cButtonPadding * settings.scaling } );

const float p = ImGui::GetStyle().ItemSpacing.x;
const Vector2f btnSize{ showSave ? ( ImGui::GetContentRegionAvail().x - p * 2 ) / 3.f : ( ImGui::GetContentRegionAvail().x - p ) / 2.f, 0 };

if ( showSave )
{
if ( UI::button( "Save", btnSize, ImGuiKey_Enter ) )
{
auto savePath = SceneRoot::getScenePath();
if ( savePath.empty() )
savePath = saveFileDialog( { .filters = SceneSave::getFilters() } );

ImGui::CloseCurrentPopup();
if ( !savePath.empty() )
ProgressBar::orderWithMainThreadPostProcessing( "Saving scene", [customFunction = settings.onOk, savePath, &root = SceneRoot::get()] ()->std::function<void()>
{
auto res = ObjectSave::toAnySupportedSceneFormat( root, savePath, ProgressBar::callBackSetProgress );

return[customFunction = customFunction, savePath, res] ()
{
if ( res )
{
getViewerInstance().onSceneSaved( savePath );
if ( customFunction )
customFunction();
}
else
showError( "Error saving scene: " + res.error() );
};
} );
}
if( !settings.saveTooltip.empty() )
UI::setTooltipIfHovered( settings.saveTooltip.c_str(), settings.scaling );
ImGui::SameLine();
}

if ( UI::buttonCommonSize( showSave ? settings.dontSaveText.c_str() : settings.shortCloseText.c_str(), btnSize, ImGuiKey_N) )
{
ImGui::CloseCurrentPopup();
if ( settings.onOk )
settings.onOk();
}
if ( !settings.dontSaveTooltip.empty() )
UI::setTooltipIfHovered( settings.dontSaveTooltip.c_str(), settings.scaling );
ImGui::SameLine();
if ( UI::buttonCommonSize( "Cancel", btnSize, ImGuiKey_Escape ) )
ImGui::CloseCurrentPopup();

if ( !settings.cancelTooltip.empty() )
UI::setTooltipIfHovered( settings.cancelTooltip.c_str(), settings.scaling);

if ( ImGui::IsMouseClicked( 0 ) && !( ImGui::IsAnyItemHovered() || ImGui::IsWindowHovered( ImGuiHoveredFlags_AnyWindow ) ) )
ImGui::CloseCurrentPopup();
ImGui::PopStyleVar();
ImGui::EndPopup();
}
ImGui::PopStyleVar( 2 );
}

}

}
39 changes: 39 additions & 0 deletions source/MRViewer/MRUISaveChangesPopup.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#pragma once

#include <string>
#include <functional>

#include "exports.h"

namespace MR
{

namespace UI
{

struct SaveChangesPopupSettings
{
// menu scaling
float scaling = 1.0f;
// text that is shown if we have nothing to save
std::string shortCloseText = "Close";
// text that is shown if we have changes but don't want to save them
std::string dontSaveText = "Don't Save";

std::string saveTooltip = "Save current scene";
std::string dontSaveTooltip = "Donh't save current scene";
std::string cancelTooltip = "Cansel";
// header that is used in dialog
std::string header;
// if not empty this function is called on "save" and "not save" options( if succeed )
std::function<void()> onOk = {};
};
// Shows ImGui popup that suggests user to save changes,
// user need to call ImGui::OpenPopup( str_id ) to open this popup.
// It has 3 options: save, don't save, cancel
// str_id - ImGui string id for the popup window
// settings - settings for dialog
MRVIEWER_API void saveChangesPopup( const char* str_id, const SaveChangesPopupSettings& settings = {} );
}

}
Loading

0 comments on commit ba978ec

Please sign in to comment.