diff --git a/Mods/vcmi/Sprites/lobby/delete-normal.png b/Mods/vcmi/Sprites/lobby/delete-normal.png new file mode 100644 index 000000000..75913ed54 Binary files /dev/null and b/Mods/vcmi/Sprites/lobby/delete-normal.png differ diff --git a/Mods/vcmi/Sprites/lobby/delete-pressed.png b/Mods/vcmi/Sprites/lobby/delete-pressed.png new file mode 100644 index 000000000..10df2b640 Binary files /dev/null and b/Mods/vcmi/Sprites/lobby/delete-pressed.png differ diff --git a/Mods/vcmi/Sprites/lobby/deleteButton.json b/Mods/vcmi/Sprites/lobby/deleteButton.json new file mode 100644 index 000000000..100145767 --- /dev/null +++ b/Mods/vcmi/Sprites/lobby/deleteButton.json @@ -0,0 +1,8 @@ +{ + "basepath" : "lobby/", + "images" : + [ + { "frame" : 0, "file" : "delete-normal.png"}, + { "frame" : 1, "file" : "delete-pressed.png"} + ] +} diff --git a/Mods/vcmi/config/english.json b/Mods/vcmi/config/english.json index c0d674f63..bab849734 100644 --- a/Mods/vcmi/config/english.json +++ b/Mods/vcmi/config/english.json @@ -107,6 +107,11 @@ "vcmi.lobby.handicap.income" : "Changes the player's various incomes by the percentage. Is rounded up.", "vcmi.lobby.handicap.growth" : "Changes the growth rate of creatures in the towns owned by the player. Is rounded up.", "vcmi.lobby.deleteUnsupportedSave" : "Unsupported saves found (e.g. from previous versions).\n\nDelete them?", + "vcmi.lobby.deleteSaveGameTitle" : "Select a Saved Game to delete", + "vcmi.lobby.deleteMapTitle" : "Select a Scenario to delete", + "vcmi.lobby.deleteFile" : "Do you want to delete following file?", + "vcmi.lobby.deleteFolder" : "Do you want to delete following folder?", + "vcmi.lobby.deleteMode" : "Switch to delete mode and back", "vcmi.lobby.login.title" : "VCMI Online Lobby", "vcmi.lobby.login.username" : "Username:", diff --git a/client/lobby/SelectionTab.cpp b/client/lobby/SelectionTab.cpp index 1554d183e..646753de2 100644 --- a/client/lobby/SelectionTab.cpp +++ b/client/lobby/SelectionTab.cpp @@ -154,7 +154,7 @@ static ESortBy getSortBySelectionScreen(ESelectionScreen Type) } SelectionTab::SelectionTab(ESelectionScreen Type) - : CIntObject(LCLICK | SHOW_POPUP | KEYBOARD | DOUBLECLICK), callOnSelect(nullptr), tabType(Type), selectionPos(0), sortModeAscending(true), inputNameRect{32, 539, 350, 20}, curFolder(""), currentMapSizeFilter(0), showRandom(false) + : CIntObject(LCLICK | SHOW_POPUP | KEYBOARD | DOUBLECLICK), callOnSelect(nullptr), tabType(Type), selectionPos(0), sortModeAscending(true), inputNameRect{32, 539, 350, 20}, curFolder(""), currentMapSizeFilter(0), showRandom(false), deleteMode(false) { OBJECT_CONSTRUCTION; @@ -194,20 +194,24 @@ SelectionTab::SelectionTab(ESelectionScreen Type) int positionsToShow = 18; std::string tabTitle; + std::string tabTitleDelete; switch(tabType) { case ESelectionScreen::newGame: - tabTitle = CGI->generaltexth->arraytxt[229]; + tabTitle = "{" + CGI->generaltexth->arraytxt[229] + "}"; + tabTitleDelete = "{red|" + CGI->generaltexth->translate("vcmi.lobby.deleteMapTitle") + "}"; break; case ESelectionScreen::loadGame: - tabTitle = CGI->generaltexth->arraytxt[230]; + tabTitle = "{" + CGI->generaltexth->arraytxt[230] + "}"; + tabTitleDelete = "{red|" + CGI->generaltexth->translate("vcmi.lobby.deleteSaveGameTitle") + "}"; break; case ESelectionScreen::saveGame: positionsToShow = 16; - tabTitle = CGI->generaltexth->arraytxt[231]; + tabTitle = "{" + CGI->generaltexth->arraytxt[231] + "}"; + tabTitleDelete = "{red|" + CGI->generaltexth->translate("vcmi.lobby.deleteSaveGameTitle") + "}"; break; case ESelectionScreen::campaignList: - tabTitle = CGI->generaltexth->allTexts[726]; + tabTitle = "{" + CGI->generaltexth->allTexts[726] + "}"; setRedrawParent(true); // we use parent background so we need to make sure it's will be redrawn too pos.w = parent->pos.w; pos.h = parent->pos.h; @@ -227,12 +231,26 @@ SelectionTab::SelectionTab(ESelectionScreen Type) auto sortByDate = std::make_shared(Point(371, 85), AnimationPath::builtin("selectionTabSortDate"), CButton::tooltip("", CGI->generaltexth->translate("vcmi.lobby.sortDate")), std::bind(&SelectionTab::sortBy, this, ESortBy::_changeDate), EShortcut::MAPS_SORT_CHANGEDATE); sortByDate->setOverlay(std::make_shared(ImagePath::builtin("lobby/selectionTabSortDate"))); buttonsSortBy.push_back(sortByDate); + + if(tabType == ESelectionScreen::loadGame || tabType == ESelectionScreen::saveGame || tabType == ESelectionScreen::newGame) + { + buttonDeleteMode = std::make_shared(Point(367, 18), AnimationPath::builtin("lobby/deleteButton"), CButton::tooltip("", CGI->generaltexth->translate("vcmi.lobby.deleteMode")), [this, tabTitle, tabTitleDelete](){ + deleteMode = !deleteMode; + if(deleteMode) + labelTabTitle->setText(tabTitleDelete); + else + labelTabTitle->setText(tabTitle); + }); + + if(tabType == ESelectionScreen::newGame) + buttonDeleteMode->setEnabled(false); + } } for(int i = 0; i < positionsToShow; i++) listItems.push_back(std::make_shared(Point(30, 129 + i * 25))); - labelTabTitle = std::make_shared(205, 28, FONT_MEDIUM, ETextAlignment::CENTER, Colors::YELLOW, tabTitle); + labelTabTitle = std::make_shared(205, 28, FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE, tabTitle); slider = std::make_shared(Point(372, 86 + (enableUiEnhancements ? 30 : 0)), (tabType != ESelectionScreen::saveGame ? 480 : 430) - (enableUiEnhancements ? 30 : 0), std::bind(&SelectionTab::sliderMove, this, _1), positionsToShow, (int)curItems.size(), 0, Orientation::VERTICAL, CSlider::BLUE); slider->setPanningStep(24); @@ -311,7 +329,22 @@ void SelectionTab::clickReleased(const Point & cursorPosition) if(line != -1) { - select(line); + if(!deleteMode) + select(line); + else + { + int py = line + slider->getValue(); + vstd::amax(py, 0); + vstd::amin(py, curItems.size() - 1); + + if(curItems[py]->isFolder && boost::algorithm::starts_with(curItems[py]->folderName, "..")) + { + select(line); + return; + } + + std::cout << (curItems[py]->isFolder ? curItems[py]->folderName : curItems[py]->fullFileURI) << "\n"; + } } #ifdef VCMI_MOBILE // focus input field if clicked inside it @@ -477,6 +510,9 @@ void SelectionTab::filter(int size, bool selectFirst) curItems.clear(); + if(buttonDeleteMode) + buttonDeleteMode->setEnabled(tabType != ESelectionScreen::newGame || showRandom); + for(auto elem : allItems) { if((elem->mapHeader && (!size || elem->mapHeader->width == size)) || tabType == ESelectionScreen::campaignList) diff --git a/client/lobby/SelectionTab.h b/client/lobby/SelectionTab.h index 86c625a58..74dc43bd6 100644 --- a/client/lobby/SelectionTab.h +++ b/client/lobby/SelectionTab.h @@ -117,6 +117,9 @@ private: ESelectionScreen tabType; Rect inputNameRect; + std::shared_ptr buttonDeleteMode; + bool deleteMode; + auto checkSubfolder(std::string path); bool isMapSupported(const CMapInfo & info);