Browse Source

add shortcut for list item moving

Laserlicht 1 year ago
parent
commit
7071647b72

+ 143 - 6
client/adventureMap/CList.cpp

@@ -18,10 +18,12 @@
 #include "../widgets/ObjectLists.h"
 #include "../widgets/RadialMenu.h"
 #include "../windows/InfoWindows.h"
+#include "../windows/CCastleInterface.h"
 #include "../CGameInfo.h"
 #include "../CPlayerInterface.h"
 #include "../PlayerLocalState.h"
 #include "../gui/CGuiHandler.h"
+#include "../gui/Shortcut.h"
 #include "../gui/WindowHandler.h"
 #include "../render/Canvas.h"
 #include "../render/Colors.h"
@@ -32,6 +34,8 @@
 #include "../../lib/mapObjects/CGHeroInstance.h"
 #include "../../lib/mapObjects/CGTownInstance.h"
 
+#include "../../CCallback.h"
+
 CList::CListItem::CListItem(CList * Parent)
 	: CIntObject(LCLICK | SHOW_POPUP | HOVER),
 	parent(Parent),
@@ -230,7 +234,7 @@ CHeroList::CHeroItem::CHeroItem(CHeroList *parent, const CGHeroInstance * Hero)
 
 	update();
 
-	addUsedEvents(GESTURE);
+	addUsedEvents(GESTURE | KEYBOARD);
 }
 
 void CHeroList::CHeroItem::update()
@@ -301,6 +305,72 @@ void CHeroList::CHeroItem::gesture(bool on, const Point & initialPosition, const
 	GH.windows().createAndPushWindow<RadialMenu>(pos.center(), menuElements, true);
 }
 
+bool CHeroList::CHeroItem::captureThisKey(EShortcut key)
+{
+
+	switch(key)
+	{
+	case EShortcut::LIST_HERO_UP:
+	case EShortcut::LIST_HERO_DOWN:
+	case EShortcut::LIST_HERO_TOP:
+	case EShortcut::LIST_HERO_BOTTOM:
+	case EShortcut::LIST_HERO_DELETE:
+		return hero && pos.isInside(GH.getCursorPosition());
+	}
+	return false;
+}
+
+void CHeroList::CHeroItem::keyPressed(EShortcut key)
+{
+	if(!hero)
+		return;
+
+	if(!pos.isInside(GH.getCursorPosition()))
+		return;
+
+	auto & heroes = LOCPLINT->localState->getWanderingHeroes();
+
+	if(key == EShortcut::LIST_HERO_DELETE)
+	{
+		CFunctionList<void()> ony = [=](){ };
+		ony += [=](){ LOCPLINT->cb->dismissHero(hero); };
+		LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[22], ony, nullptr);
+		return;
+	}
+
+	if(heroes.size() < 2)
+		return;
+
+	size_t heroPos = vstd::find_pos(heroes, hero);
+	const CGHeroInstance * heroUpper = (heroPos < 1) ? nullptr : heroes.at(heroPos - 1);
+	const CGHeroInstance * heroLower = (heroPos > heroes.size() - 2) ? nullptr : heroes.at(heroPos + 1);
+
+	switch(key)
+	{
+	case EShortcut::LIST_HERO_UP:
+		if(heroUpper)
+			LOCPLINT->localState->swapWanderingHero(heroPos, heroPos - 1);
+		break;
+
+	case EShortcut::LIST_HERO_DOWN:
+		if(heroLower)
+			LOCPLINT->localState->swapWanderingHero(heroPos, heroPos + 1);
+		break;
+
+	case EShortcut::LIST_HERO_TOP:
+		if(heroUpper)
+			for (size_t i = heroPos; i > 0; i--)
+				LOCPLINT->localState->swapWanderingHero(i, i - 1);
+		break;
+
+	case EShortcut::LIST_HERO_BOTTOM:
+		if(heroLower)
+			for (int i = heroPos; i < heroes.size() - 1; i++)
+				LOCPLINT->localState->swapWanderingHero(i, i + 1);
+		break;
+	}
+}
+
 std::shared_ptr<CIntObject> CHeroList::createItem(size_t index)
 {
 	if (LOCPLINT->localState->getWanderingHeroes().size() > index)
@@ -370,7 +440,7 @@ CTownList::CTownItem::CTownItem(CTownList *parent, const CGTownInstance *Town):
 	pos = picture->pos;
 	update();
 
-	addUsedEvents(GESTURE);
+	addUsedEvents(GESTURE | KEYBOARD);
 }
 
 std::shared_ptr<CIntObject> CTownList::CTownItem::genSelection()
@@ -419,24 +489,91 @@ void CTownList::CTownItem::gesture(bool on, const Point & initialPosition, const
 	int townUpperPos = (townIndex < 1) ? -1 : townIndex - 1;
 	int townLowerPos = (townIndex > towns.size() - 2) ? -1 : townIndex + 1;
 
+	auto updateList = [](){
+		for (auto ki : GH.windows().findWindows<CCastleInterface>())
+			ki->townChange(); //update list
+	};
+
 	std::vector<RadialMenuConfig> menuElements = {
-		{ RadialMenuConfig::ITEM_ALT_NN, townUpperPos > -1, "altUpTop", "vcmi.radialWheel.moveTop", [townIndex]()
+		{ RadialMenuConfig::ITEM_ALT_NN, townUpperPos > -1, "altUpTop", "vcmi.radialWheel.moveTop", [updateList, townIndex]()
 		{
 			for (int i = townIndex; i > 0; i--)
 				LOCPLINT->localState->swapOwnedTowns(i, i - 1);
+			updateList();
 		} },
-		{ RadialMenuConfig::ITEM_ALT_NW, townUpperPos > -1, "altUp", "vcmi.radialWheel.moveUp", [townIndex, townUpperPos](){LOCPLINT->localState->swapOwnedTowns(townIndex, townUpperPos); } },
-		{ RadialMenuConfig::ITEM_ALT_SW, townLowerPos > -1, "altDown", "vcmi.radialWheel.moveDown", [townIndex, townLowerPos](){ LOCPLINT->localState->swapOwnedTowns(townIndex, townLowerPos); } },
-		{ RadialMenuConfig::ITEM_ALT_SS, townLowerPos > -1, "altDownBottom", "vcmi.radialWheel.moveBottom", [townIndex, towns]()
+		{ RadialMenuConfig::ITEM_ALT_NW, townUpperPos > -1, "altUp", "vcmi.radialWheel.moveUp", [updateList, townIndex, townUpperPos](){LOCPLINT->localState->swapOwnedTowns(townIndex, townUpperPos); updateList(); } },
+		{ RadialMenuConfig::ITEM_ALT_SW, townLowerPos > -1, "altDown", "vcmi.radialWheel.moveDown", [updateList, townIndex, townLowerPos](){ LOCPLINT->localState->swapOwnedTowns(townIndex, townLowerPos); updateList(); } },
+		{ RadialMenuConfig::ITEM_ALT_SS, townLowerPos > -1, "altDownBottom", "vcmi.radialWheel.moveBottom", [updateList, townIndex, towns]()
 		{
 			for (int i = townIndex; i < towns.size() - 1; i++)
 				LOCPLINT->localState->swapOwnedTowns(i, i + 1);
+			updateList();
 		} },
 	};
 
 	GH.windows().createAndPushWindow<RadialMenu>(pos.center(), menuElements, true);
 }
 
+bool CTownList::CTownItem::captureThisKey(EShortcut key)
+{
+
+	switch(key)
+	{
+	case EShortcut::LIST_TOWN_UP:
+	case EShortcut::LIST_TOWN_DOWN:
+	case EShortcut::LIST_TOWN_TOP:
+	case EShortcut::LIST_TOWN_BOTTOM:
+		return town && pos.isInside(GH.getCursorPosition());
+	}
+	return false;
+}
+
+void CTownList::CTownItem::keyPressed(EShortcut key)
+{
+	if(!pos.isInside(GH.getCursorPosition()))
+		return;
+
+	const std::vector<const CGTownInstance *> towns = LOCPLINT->localState->getOwnedTowns();
+	size_t townIndex = vstd::find_pos(towns, town);
+
+	if(townIndex + 1 > towns.size() || !towns.at(townIndex))
+		return;
+
+	if(towns.size() < 2)
+		return;
+
+	int townUpperPos = (townIndex < 1) ? -1 : townIndex - 1;
+	int townLowerPos = (townIndex > towns.size() - 2) ? -1 : townIndex + 1;
+
+	switch(key)
+	{
+	case EShortcut::LIST_TOWN_UP:
+		if(townUpperPos > -1)
+			LOCPLINT->localState->swapOwnedTowns(townIndex, townUpperPos);
+		break;
+
+	case EShortcut::LIST_TOWN_DOWN:
+		if(townLowerPos > -1)
+			LOCPLINT->localState->swapOwnedTowns(townIndex, townLowerPos);
+		break;
+
+	case EShortcut::LIST_TOWN_TOP:
+		if(townUpperPos > -1)
+			for (int i = townIndex; i > 0; i--)
+				LOCPLINT->localState->swapOwnedTowns(i, i - 1);
+		break;
+
+	case EShortcut::LIST_TOWN_BOTTOM:
+		if(townLowerPos > -1)
+			for (int i = townIndex; i < towns.size() - 1; i++)
+				LOCPLINT->localState->swapOwnedTowns(i, i + 1);
+		break;
+	}
+
+	for (auto ki : GH.windows().findWindows<CCastleInterface>())
+		ki->townChange(); //update list
+}
+
 std::string CTownList::CTownItem::getHoverText()
 {
 	return town->getObjectName();

+ 4 - 0
client/adventureMap/CList.h

@@ -128,6 +128,8 @@ class CHeroList	: public CList
 		void open() override;
 		void showTooltip() override;
 		void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override;
+		bool captureThisKey(EShortcut key) override;
+		void keyPressed(EShortcut key) override;
 		std::string getHoverText() override;
 	};
 
@@ -162,6 +164,8 @@ class CTownList	: public CList
 		void open() override;
 		void showTooltip() override;
 		void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override;
+		bool captureThisKey(EShortcut key) override;
+		void keyPressed(EShortcut key) override;
 		std::string getHoverText() override;
 	};
 

+ 10 - 0
client/gui/Shortcut.h

@@ -293,5 +293,15 @@ enum class EShortcut
 	SPELLBOOK_TAB_ADVENTURE,
 	SPELLBOOK_TAB_COMBAT,
 
+	LIST_HERO_UP,
+	LIST_HERO_DOWN,
+	LIST_HERO_TOP,
+	LIST_HERO_BOTTOM,
+	LIST_HERO_DELETE,
+	LIST_TOWN_UP,
+	LIST_TOWN_DOWN,
+	LIST_TOWN_TOP,
+	LIST_TOWN_BOTTOM,
+
 	AFTER_LAST
 };

+ 9 - 0
client/gui/ShortcutHandler.cpp

@@ -275,6 +275,15 @@ EShortcut ShortcutHandler::findShortcut(const std::string & identifier ) const
 		{"heroCostumeLoad9",         EShortcut::HERO_COSTUME_LOAD_9       },
 		{"spellbookTabAdventure",    EShortcut::SPELLBOOK_TAB_ADVENTURE   },
 		{"spellbookTabCombat",       EShortcut::SPELLBOOK_TAB_COMBAT      },
+		{"listHeroUp",               EShortcut::LIST_HERO_UP              },
+		{"listHeroDown",             EShortcut::LIST_HERO_DOWN            },
+		{"listHeroTop",              EShortcut::LIST_HERO_TOP             },
+		{"listHeroBottom",           EShortcut::LIST_HERO_BOTTOM          },
+		{"listHeroDelete",           EShortcut::LIST_HERO_DELETE          },
+		{"listTownUp",               EShortcut::LIST_TOWN_UP              },
+		{"listTownDown",             EShortcut::LIST_TOWN_DOWN            },
+		{"listTownTop",              EShortcut::LIST_TOWN_TOP             },
+		{"listTownBottom",           EShortcut::LIST_TOWN_BOTTOM          },
 		{"mainMenuHotseat",          EShortcut::MAIN_MENU_HOTSEAT         },
 		{"mainMenuHostGame",         EShortcut::MAIN_MENU_HOST_GAME       },
 		{"mainMenuJoinGame",         EShortcut::MAIN_MENU_JOIN_GAME       },

+ 9 - 0
config/shortcutsConfig.json

@@ -242,6 +242,15 @@
 		"townOpenThievesGuild":     "G",
 		"townOpenVisitingHero":     "Ctrl+H",
 		"townSwapArmies":           "Space",
+		"listHeroUp":               "PageUp",
+		"listHeroDown":             "PageDown",
+		"listHeroTop":              "Home",
+		"listHeroBottom":           "End",
+		"listHeroDelete":           "Delete",
+		"listTownUp":               "PageUp",
+		"listTownDown":             "PageDown",
+		"listTownTop":              "Home",
+		"listTownBottom":           "End",
 		
 		// Controller-specific
 		"mouseCursorX":             [],