@@ -43,6 +43,8 @@ const short cDialog::BG_DARK = 5, cDialog::BG_LIGHT = 16;
|
||||
short cDialog::defaultBackground = cDialog::BG_DARK;
|
||||
cDialog* cDialog::topWindow = nullptr;
|
||||
void (*cDialog::redraw_everything)() = nullptr;
|
||||
std::function<void(const cDialog&)> cDialog::onOpen;
|
||||
std::function<void(const cDialog&)> cDialog::onClose;
|
||||
std::function<void(sf::RenderWindow& win)> cDialog::onLostFocus;
|
||||
std::function<void(sf::RenderWindow& win)> cDialog::onGainedFocus;
|
||||
std::function<void(sf::RenderWindow& win)> cDialog::onHandleEvents;
|
||||
@@ -502,7 +504,7 @@ bool cDialog::sendInput(cKey key) {
|
||||
void cDialog::run(std::function<void(cDialog&)> onopen){
|
||||
cPict::resetAnim();
|
||||
cDialog* formerTop = topWindow;
|
||||
// TODO: The introduction of the static topWindow means I may be able to use this instead of parent->win; do I still need parent?
|
||||
|
||||
sf::RenderWindow* parentWin = &(parent ? parent->win : mainPtr());
|
||||
auto parentPos = parentWin->getPosition();
|
||||
auto parentSz = parentWin->getSize();
|
||||
@@ -542,11 +544,16 @@ void cDialog::run(std::function<void(cDialog&)> onopen){
|
||||
// but it does prevent editing other dialogs, and it also keeps this window on top
|
||||
// even when it loses focus.
|
||||
ModalSession dlog(win, *parentWin);
|
||||
if(onopen) onopen(*this);
|
||||
animTimer.restart();
|
||||
|
||||
has_focus = true;
|
||||
topWindow = this;
|
||||
|
||||
// Run the static onOpen event first
|
||||
if(cDialog::onOpen) cDialog::onOpen(*this);
|
||||
// Run this dialog's onOpen event
|
||||
if(onopen) onopen(*this);
|
||||
|
||||
handle_events();
|
||||
|
||||
win.setVisible(false);
|
||||
@@ -555,6 +562,7 @@ void cDialog::run(std::function<void(cDialog&)> onopen){
|
||||
set_cursor(former_curs);
|
||||
topWindow = formerTop;
|
||||
stackWindowsCorrectly();
|
||||
if(cDialog::onClose) cDialog::onClose(*this);
|
||||
}
|
||||
|
||||
void cDialog::runWithHelp(short help1, short help2, bool help_forced) {
|
||||
|
@@ -82,7 +82,11 @@ class cDialog : public iComponent, public iNameGiver {
|
||||
bool doAnimations;
|
||||
bool has_focus = false;
|
||||
public:
|
||||
static bool anyOpen() { return topWindow != nullptr; }
|
||||
static void (*redraw_everything)();
|
||||
// Global onOpen and onClose events are for tracking things, not for modifying the dialogs.
|
||||
static std::function<void(const cDialog&)> onOpen;
|
||||
static std::function<void(const cDialog&)> onClose;
|
||||
static std::function<void(sf::RenderWindow& win)> onLostFocus;
|
||||
static std::function<void(sf::RenderWindow& win)> onGainedFocus;
|
||||
// Attach a handler here for any update/input logic that uses target-specific code
|
||||
|
@@ -348,13 +348,22 @@ void init_scened(int argc, char* argv[]) {
|
||||
init_shaders();
|
||||
init_tiling();
|
||||
init_snd_tool();
|
||||
|
||||
// When a dialog is open, scenario action undo/redo needs to be disabled for 2 reasons:
|
||||
// 1. it is very unsafe to pop from the stack while any edit operation is underway
|
||||
// 2. the menu item must be disabled for cDialog to receive undo/redo keyboard shortcuts
|
||||
// for text field editing
|
||||
cDialog::onOpen = cDialog::onClose = [](const cDialog& dialog) {
|
||||
update_edit_menu();
|
||||
};
|
||||
#ifdef SFML_SYSTEM_MACOS
|
||||
init_menubar(); // This is called twice because Windows and Mac have different ordering requirements
|
||||
|
||||
cDialog::onHandleEvents = [](sf::RenderWindow&) {
|
||||
if (menuChoiceId>=0) {
|
||||
handle_menu_choice(eMenu(menuChoiceId), true);
|
||||
if(menuChoiceId>=0) {
|
||||
short wasChoice = menuChoiceId;
|
||||
menuChoiceId=-1;
|
||||
handle_menu_choice(eMenu(wasChoice));
|
||||
}
|
||||
};
|
||||
#endif
|
||||
@@ -399,8 +408,9 @@ void handle_events() {
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (menuChoiceId>=0) {
|
||||
handle_menu_choice(eMenu(menuChoiceId));
|
||||
short wasChoice = menuChoiceId;
|
||||
menuChoiceId=-1;
|
||||
handle_menu_choice(eMenu(wasChoice));
|
||||
}
|
||||
#endif
|
||||
while(pollEvent(mainPtr(), currentEvent)) handle_one_event(currentEvent);
|
||||
@@ -470,12 +480,29 @@ static void show_outdated_warning() {
|
||||
showWarning(outdated_help1, outdated_help2);
|
||||
}
|
||||
|
||||
// When any dialog is open, only allow menu items that work with text fields.
|
||||
// NOTE: EDIT_UNDO and EDIT_REDO are included, even though currently, those menu items will be
|
||||
// disabled (only the keyboard shortcuts work for undo/redo on text editing).
|
||||
// Someday, update_edit_menu() could keep them enabled but change their text to show
|
||||
// the undo action of the active text field--but that would be complicated to do, and require
|
||||
// changing update_edit_menu() for all 3 platforms right now.
|
||||
std::set<eMenu> dialog_allowed_menu_choices = {
|
||||
eMenu::NONE, eMenu::EDIT_UNDO, eMenu::EDIT_REDO, eMenu::EDIT_CUT, eMenu::EDIT_COPY,
|
||||
eMenu::EDIT_PASTE, eMenu::EDIT_DELETE, eMenu::EDIT_SELECT_ALL,
|
||||
};
|
||||
|
||||
void handle_menu_choice(eMenu item_hit) {
|
||||
extern cUndoList undo_list;
|
||||
bool isEdit = false, isHelp = false, isOutdated = false;
|
||||
std::string helpDlog;
|
||||
fs::path file_to_load;
|
||||
cKey editKey = {true};
|
||||
|
||||
if(cDialog::anyOpen() && !dialog_allowed_menu_choices.count(item_hit)){
|
||||
showWarning("You must confirm or cancel what you're currently doing first.");
|
||||
return;
|
||||
}
|
||||
|
||||
switch(item_hit) {
|
||||
case eMenu::NONE: return;
|
||||
case eMenu::FILE_OPEN:
|
||||
|
@@ -329,7 +329,7 @@ void OpenBoESceneditMenu::update_for_mode_4() {
|
||||
void OpenBoESceneditMenu::update_edit_menu(cUndoList const & undo_list) {
|
||||
auto menubar = this->get_menubar_ptr();
|
||||
|
||||
menubar->setMenuItemEnabled({ "Edit", "Undo Ctrl-Z" }, !undo_list.noUndo());
|
||||
menubar->setMenuItemEnabled({ "Edit", "Redo Ctrl-Y" }, !undo_list.noRedo());
|
||||
menubar->setMenuItemEnabled({ "Edit", "Undo Ctrl-Z" }, !(undo_list.noUndo() || cDialog::anyOpen()));
|
||||
menubar->setMenuItemEnabled({ "Edit", "Redo Ctrl-Y" }, !(undo_list.noRedo() || cDialog::anyOpen()));
|
||||
}
|
||||
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include "tools/winutil.hpp"
|
||||
#include "tools/undo.hpp"
|
||||
#include "dialogxml/dialogs/dialog.hpp"
|
||||
|
||||
extern short menuChoiceId;
|
||||
|
||||
@@ -154,7 +155,7 @@ void shut_down_menus(short mode) {
|
||||
|
||||
void update_edit_menu() {
|
||||
NSMenuItem* mi_undo = [edit_menu itemAtIndex: 0];
|
||||
if(undo_list.noUndo()) {
|
||||
if(undo_list.noUndo() || cDialog::anyOpen()) {
|
||||
[mi_undo setTitle: @"Can't Undo"];
|
||||
[mi_undo setEnabled: NO];
|
||||
} else {
|
||||
@@ -163,7 +164,7 @@ void update_edit_menu() {
|
||||
[mi_undo setEnabled: YES];
|
||||
}
|
||||
NSMenuItem* mi_redo = [edit_menu itemAtIndex: 1];
|
||||
if(undo_list.noRedo()) {
|
||||
if(undo_list.noRedo() || cDialog::anyOpen()) {
|
||||
[mi_redo setTitle: @"Can't Redo"];
|
||||
[mi_redo setEnabled: NO];
|
||||
} else {
|
||||
|
@@ -190,7 +190,7 @@ void shut_down_menus(short mode) {
|
||||
void update_edit_menu() {
|
||||
if(menuHandle == NULL) return;
|
||||
HMENU edit_menu = GetSubMenu(menuHandle, EDIT_MENU_POS);
|
||||
if(undo_list.noUndo()) {
|
||||
if(undo_list.noUndo() || cDialog::anyOpen()) {
|
||||
ModifyMenuA(edit_menu, IDM_EDIT_UNDO, MF_BYCOMMAND, IDM_EDIT_UNDO, "Can't Undo\tCtrl+Z");
|
||||
EnableMenuItem(edit_menu, IDM_EDIT_UNDO, MF_BYCOMMAND | MF_GRAYED);
|
||||
} else {
|
||||
@@ -198,7 +198,7 @@ void update_edit_menu() {
|
||||
ModifyMenuA(edit_menu, IDM_EDIT_UNDO, MF_BYCOMMAND, IDM_EDIT_UNDO, title.c_str());
|
||||
EnableMenuItem(edit_menu, IDM_EDIT_UNDO, MF_BYCOMMAND | MF_ENABLED);
|
||||
}
|
||||
if(undo_list.noRedo()) {
|
||||
if(undo_list.noRedo() || cDialog::anyOpen()) {
|
||||
ModifyMenuA(edit_menu, IDM_EDIT_REDO, MF_BYCOMMAND, IDM_EDIT_REDO, "Can't Redo\tCtrl+Y");
|
||||
EnableMenuItem(edit_menu, IDM_EDIT_REDO, MF_BYCOMMAND | MF_GRAYED);
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user