Browse Source

Merge pull request #4384 from Laserlicht/shortcut

add shortcut for list item ordering
Ivan Savenko 1 year ago
parent
commit
89dca5061d

+ 112 - 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),
@@ -229,7 +233,7 @@ CHeroList::CHeroItem::CHeroItem(CHeroList *parent, const CGHeroInstance * Hero)
 
 	update();
 
-	addUsedEvents(GESTURE);
+	addUsedEvents(GESTURE | KEYBOARD);
 }
 
 void CHeroList::CHeroItem::update()
@@ -300,6 +304,55 @@ void CHeroList::CHeroItem::gesture(bool on, const Point & initialPosition, const
 	GH.windows().createAndPushWindow<RadialMenu>(pos.center(), menuElements, true);
 }
 
+void CHeroList::CHeroItem::keyPressed(EShortcut key)
+{
+	if(!hero)
+		return;
+
+	if(parent->selected != this->shared_from_this())
+		return;
+
+	auto & heroes = LOCPLINT->localState->getWanderingHeroes();
+
+	if(key == EShortcut::LIST_HERO_DISMISS)
+	{
+		LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[22], [=](){ LOCPLINT->cb->dismissHero(hero); }, 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)
@@ -369,7 +422,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()
@@ -418,24 +471,77 @@ 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);
 }
 
+void CTownList::CTownItem::keyPressed(EShortcut key)
+{
+	if(parent->selected != this->shared_from_this())
+		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();

+ 7 - 4
client/adventureMap/CList.h

@@ -29,9 +29,10 @@ class CList : public Scrollable
 protected:
 	class CListItem : public CIntObject, public std::enable_shared_from_this<CListItem>
 	{
-		CList * parent;
 		std::shared_ptr<CIntObject> selection;
 	public:
+		CList * parent;
+
 		CListItem(CList * parent);
 		~CListItem();
 
@@ -55,9 +56,6 @@ protected:
 
 private:
 	const size_t size;
-
-	//for selection\deselection
-	std::shared_ptr<CListItem> selected;
 	void select(std::shared_ptr<CListItem> which);
 	friend class CListItem;
 
@@ -81,6 +79,9 @@ protected:
 	void update();
 
 public:
+	//for selection\deselection
+	std::shared_ptr<CListItem> selected;
+
 	/// functions that will be called when selection changes
 	CFunctionList<void()> onSelect;
 
@@ -128,6 +129,7 @@ class CHeroList	: public CList
 		void open() override;
 		void showTooltip() override;
 		void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override;
+		void keyPressed(EShortcut key) override;
 		std::string getHoverText() override;
 	};
 
@@ -162,6 +164,7 @@ class CTownList	: public CList
 		void open() override;
 		void showTooltip() override;
 		void gesture(bool on, const Point & initialPosition, const Point & finalPosition) 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_DISMISS,
+	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          },
+		{"listHeroDismiss",          EShortcut::LIST_HERO_DISMISS         },
+		{"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":               "Ctrl+PageUp",
+		"listHeroDown":             "Ctrl+PageDown",
+		"listHeroTop":              "Ctrl+Home",
+		"listHeroBottom":           "Ctrl+End",
+		"listHeroDismiss":          "Delete",
+		"listTownUp":               "Ctrl+PageUp",
+		"listTownDown":             "Ctrl+PageDown",
+		"listTownTop":              "Ctrl+Home",
+		"listTownBottom":           "Ctrl+End",
 		
 		// Controller-specific
 		"mouseCursorX":             [],