Support showing multiple different error messages in editor

Previously the same message popup context was used for all error messages. While multiple message popups could be opened at the same time, the message would always be the same for all, as the same buffer was used for all popups.

This is fixed by creating and destroying the message popup contexts dynamically, so there can be any number of message popups with different messages. Additionally, if a popup with an identical message is already open, it will first be closed and then reopened at the new position, to prevent duplicate message popups.
This commit is contained in:
Robert Müller 2023-07-11 19:32:41 +02:00
parent 13806f1581
commit fcd219bf22
2 changed files with 45 additions and 4 deletions

View file

@ -5252,13 +5252,27 @@ void CEditor::InvokeFileDialog(int StorageType, int FileType, const char *pTitle
void CEditor::ShowFileDialogError(const char *pFormat, ...)
{
static CUI::SMessagePopupContext s_MessagePopupContext;
s_MessagePopupContext.ErrorColor();
char aMessage[1024];
va_list VarArgs;
va_start(VarArgs, pFormat);
str_format_v(s_MessagePopupContext.m_aMessage, sizeof(s_MessagePopupContext.m_aMessage), pFormat, VarArgs);
str_format_v(aMessage, sizeof(aMessage), pFormat, VarArgs);
va_end(VarArgs);
UI()->ShowPopupMessage(UI()->MouseX(), UI()->MouseY(), &s_MessagePopupContext);
auto ContextIterator = m_PopupMessageContexts.find(aMessage);
CUI::SMessagePopupContext *pContext;
if(ContextIterator != m_PopupMessageContexts.end())
{
pContext = ContextIterator->second;
UI()->ClosePopupMenu(pContext);
}
else
{
pContext = new CUI::SMessagePopupContext();
pContext->ErrorColor();
str_copy(pContext->m_aMessage, aMessage);
m_PopupMessageContexts[pContext->m_aMessage] = pContext;
}
UI()->ShowPopupMessage(UI()->MouseX(), UI()->MouseY(), pContext);
}
void CEditor::RenderModebar(CUIRect View)
@ -6504,6 +6518,7 @@ void CEditor::Render()
// Popup menus must be rendered before the statusbar, because UI elements in
// popup menus can set tooltips, which are rendered in the status bar.
UI()->RenderPopupMenus();
FreeDynamicPopupMenus();
if(m_GuiActive)
RenderStatusbar(StatusBar);
@ -6544,6 +6559,22 @@ void CEditor::RenderSavingIndicator(CUIRect View)
UI()->DoLabel(&Label, "Saving…", 24.0f, TEXTALIGN_BR);
}
void CEditor::FreeDynamicPopupMenus()
{
auto Iterator = m_PopupMessageContexts.begin();
while(Iterator != m_PopupMessageContexts.end())
{
if(!UI()->IsPopupOpen(Iterator->second))
{
CUI::SMessagePopupContext *pContext = Iterator->second;
Iterator = m_PopupMessageContexts.erase(Iterator);
delete pContext;
}
else
++Iterator;
}
}
void CEditor::RenderMousePointer()
{
if(!m_ShowMousePointer)

View file

@ -21,6 +21,7 @@
#include <chrono>
#include <deque>
#include <map>
#include <string>
#include <vector>
@ -890,6 +891,14 @@ public:
void InvokeFileDialog(int StorageType, int FileType, const char *pTitle, const char *pButtonText,
const char *pBasepath, const char *pDefaultName,
bool (*pfnFunc)(const char *pFilename, int StorageType, void *pUser), void *pUser);
struct SStringKeyComparator
{
bool operator()(char const *pLhs, char const *pRhs) const
{
return str_comp(pLhs, pRhs) < 0;
}
};
std::map<const char *, CUI::SMessagePopupContext *, SStringKeyComparator> m_PopupMessageContexts;
void ShowFileDialogError(const char *pFormat, ...)
GNUC_ATTRIBUTE((format(printf, 2, 3)));
@ -902,6 +911,7 @@ public:
void RenderPressedKeys(CUIRect View);
void RenderSavingIndicator(CUIRect View);
void FreeDynamicPopupMenus();
void RenderMousePointer();
void ResetMenuBackgroundPositions();