Browse Source

make town title editable

Laserlicht 3 weeks ago
parent
commit
f5d1657041

+ 74 - 0
client/widgets/CTextInput.cpp

@@ -27,6 +27,80 @@
 std::list<CFocusable *> CFocusable::focusables;
 CFocusable * CFocusable::inputWithFocus;
 
+CTextInputWithConfirm::CTextInputWithConfirm(const Rect & Pos, EFonts font, ETextAlignment alignment, std::string text, bool limitToRect, std::function<void()> confirmCallback)
+	: CTextInput(Pos, font, alignment, false), confirmCb(confirmCallback), limitToRect(limitToRect), initialText(text)
+{
+	setText(text);
+}
+
+bool CTextInputWithConfirm::captureThisKey(EShortcut key)
+{
+	return hasFocus() && (key == EShortcut::GLOBAL_ACCEPT || key == EShortcut::GLOBAL_CANCEL || key == EShortcut::GLOBAL_BACKSPACE);
+}
+
+void CTextInputWithConfirm::keyPressed(EShortcut key)
+{
+	if(!hasFocus())
+		return;
+
+	if(key == EShortcut::GLOBAL_ACCEPT)
+		confirm();
+	else if(key == EShortcut::GLOBAL_CANCEL)
+	{
+		setText(initialText);
+		removeFocus();
+	}
+	
+	CTextInput::keyPressed(key);
+}
+
+bool CTextInputWithConfirm::receiveEvent(const Point & position, int eventType) const
+{
+	return eventType == AEventsReceiver::LCLICK; // capture all left clicks (not only within control)
+}
+
+void CTextInputWithConfirm::clickReleased(const Point & cursorPosition)
+{
+	if(!pos.isInside(cursorPosition)) // clicked outside
+		confirm();
+}
+
+void CTextInputWithConfirm::clickPressed(const Point & cursorPosition)
+{
+	if(pos.isInside(cursorPosition)) // clickPressed should respect control area (receiveEvent also affects this)
+		CTextInput::clickPressed(cursorPosition);
+}
+
+void CTextInputWithConfirm::onFocusGot()
+{
+	initialText = getText();
+
+	CTextInput::onFocusGot();
+}
+
+void CTextInputWithConfirm::textInputted(const std::string & enteredText)
+{
+	if(!hasFocus())
+		return;
+
+	CTextInput::textInputted(enteredText);
+
+	std::string visibleText = getVisibleText();
+	const auto & font = ENGINE->renderHandler().loadFont(label->font);
+	while(limitToRect && font->getStringWidth(visibleText) > pos.w)
+	{
+		TextOperations::trimRightUnicode(currentText);
+		visibleText = getVisibleText();
+	}
+}
+
+void CTextInputWithConfirm::confirm()
+{
+	if(confirmCb && initialText != getText())
+		confirmCb();
+	removeFocus();
+}
+
 CTextInput::CTextInput(const Rect & Pos)
 	:originalAlignment(ETextAlignment::CENTERLEFT)
 {

+ 30 - 10
client/widgets/CTextInput.h

@@ -45,8 +45,9 @@ public:
 };
 
 /// Text input box where players can enter text
-class CTextInput final : public CFocusable
+class CTextInput : public CFocusable
 {
+protected:
 	using TextEditedCallback = std::function<void(const std::string &)>;
 	using TextFilterCallback = std::function<void(std::string &, const std::string &)>;
 
@@ -71,12 +72,12 @@ class CTextInput final : public CFocusable
 	void createLabel(bool giveFocusToInput);
 	void updateLabel();
 
-	void clickPressed(const Point & cursorPosition) final;
-	void textInputted(const std::string & enteredText) final;
-	void textEdited(const std::string & enteredText) final;
-	void onFocusGot() final;
-	void onFocusLost() final;
-	void showPopupWindow(const Point & cursorPosition) final;
+	void clickPressed(const Point & cursorPosition) override;
+	void textInputted(const std::string & enteredText) override;
+	void textEdited(const std::string & enteredText) override;
+	void onFocusGot() override;
+	void onFocusLost() override;
+	void showPopupWindow(const Point & cursorPosition) override;
 
 	CTextInput(const Rect & Pos);
 public:
@@ -105,7 +106,26 @@ public:
 	void setAlignment(ETextAlignment alignment);
 
 	// CIntObject interface impl
-	void keyPressed(EShortcut key) final;
-	void activate() final;
-	void deactivate() final;
+	void keyPressed(EShortcut key) override;
+	void activate() override;
+	void deactivate() override;
+};
+
+class CTextInputWithConfirm final : public CTextInput
+{
+	std::string initialText;
+	std::function<void()> confirmCb;
+	bool limitToRect;
+
+	void confirm();
+public:
+	CTextInputWithConfirm(const Rect & Pos, EFonts font, ETextAlignment alignment, std::string text, bool limitToRect, std::function<void()> confirmCallback);
+
+	bool captureThisKey(EShortcut key) override;
+	void keyPressed(EShortcut key) override;
+	void clickReleased(const Point & cursorPosition) override;
+	void clickPressed(const Point & cursorPosition) override;
+	bool receiveEvent(const Point & position, int eventType) const override;
+	void onFocusGot() override;
+	void textInputted(const std::string & enteredText) override;
 };

+ 2 - 1
client/windows/CCastleInterface.cpp

@@ -30,6 +30,7 @@
 #include "../widgets/MiscWidgets.h"
 #include "../widgets/CComponent.h"
 #include "../widgets/CGarrisonInt.h"
+#include "../widgets/CTextInput.h"
 #include "../widgets/Buttons.h"
 #include "../widgets/TextControls.h"
 #include "../widgets/RadialMenu.h"
@@ -1435,7 +1436,7 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst
 	garr->setRedrawParent(true);
 
 	heroes = std::make_shared<HeroSlots>(town, Point(241, 387), Point(241, 483), garr, true);
-	title = std::make_shared<CLabel>(85, 387, FONT_MEDIUM, ETextAlignment::TOPLEFT, Colors::WHITE, town->getNameTranslated());
+	title = std::make_shared<CTextInputWithConfirm>(Rect(83, 386, 140, 20), FONT_MEDIUM, ETextAlignment::TOPLEFT, town->getNameTranslated(), true, [this](){ std::cout << title->getText(); });
 	income = std::make_shared<CLabel>(195, 443, FONT_SMALL, ETextAlignment::CENTER);
 	icon = std::make_shared<CAnimImage>(AnimationPath::builtin("ITPT"), 0, 0, 15, 387);
 

+ 2 - 1
client/windows/CCastleInterface.h

@@ -37,6 +37,7 @@ class CGarrisonInt;
 class CComponent;
 class CComponentBox;
 class LRClickableArea;
+class CTextInputWithConfirm;
 
 /// Building "button"
 class CBuildingRect : public CShowableAnim
@@ -225,7 +226,7 @@ public:
 /// Class which manages the castle window
 class CCastleInterface final : public CStatusbarWindow, public IGarrisonHolder, public IArtifactsHolder
 {
-	std::shared_ptr<CLabel> title;
+	std::shared_ptr<CTextInputWithConfirm> title;
 	std::shared_ptr<CLabel> income;
 	std::shared_ptr<CAnimImage> icon;
 

+ 6 - 1
lib/mapObjects/CGTownInstance.cpp

@@ -852,7 +852,7 @@ CBonusSystemNode & CGTownInstance::whatShouldBeAttached()
 
 std::string CGTownInstance::getNameTranslated() const
 {
-	return LIBRARY->generaltexth->translate(nameTextId);
+	return customName.empty() ? LIBRARY->generaltexth->translate(nameTextId) : customName;
 }
 
 std::string CGTownInstance::getNameTextID() const
@@ -865,6 +865,11 @@ void CGTownInstance::setNameTextId( const std::string & newName )
 	nameTextId = newName;
 }
 
+void CGTownInstance::setCustomName( const std::string & newName )
+{
+	customName = newName;
+}
+
 const CArmedInstance * CGTownInstance::getUpperArmy() const
 {
 	if(getGarrisonHero())

+ 4 - 0
lib/mapObjects/CGTownInstance.h

@@ -46,6 +46,7 @@ class DLL_LINKAGE CGTownInstance : public CGDwelling, public IShipyard, public I
 {
 	friend class CTownInstanceConstructor;
 	std::string nameTextId; // name of town
+	std::string customName;
 
 	std::map<BuildingID, TownRewardableBuildingInstance*> convertOldBuildings(std::vector<TownRewardableBuildingInstance*> oldVector);
 	std::set<BuildingID> builtBuildings;
@@ -75,6 +76,8 @@ public:
 	{
 		h & static_cast<CGDwelling&>(*this);
 		h & nameTextId;
+		if (h.version >= Handler::Version::CUSTOM_NAMES)
+			h & customName;
 		h & built;
 		h & destroyed;
 		h & identifier;
@@ -128,6 +131,7 @@ public:
 	std::string getNameTranslated() const;
 	std::string getNameTextID() const;
 	void setNameTextId(const std::string & newName);
+	void setCustomName(const std::string & newName);
 
 	//////////////////////////////////////////////////////////////////////////
 

+ 2 - 1
lib/serializer/ESerializationVersion.h

@@ -50,8 +50,9 @@ enum class ESerializationVersion : int32_t
 	BONUS_HIDDEN, // hidden bonus
 	MORE_MAP_LAYERS, // more map layers
 	CONFIGURABLE_RESOURCES, // configurable resources
+	CUSTOM_NAMES, // custom names
 
-	CURRENT = CONFIGURABLE_RESOURCES,
+	CURRENT = CUSTOM_NAMES,
 };
 
 static_assert(ESerializationVersion::MINIMAL <= ESerializationVersion::CURRENT, "Invalid serialization version definition!");