mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Android: make keyboard appear and disappear only on demand
This commit is contained in:
		
				
					committed by
					
						 Andrii Danylchenko
						Andrii Danylchenko
					
				
			
			
				
	
			
			
			
						parent
						
							6da233c387
						
					
				
				
					commit
					2710d1df50
				
			| @@ -268,10 +268,14 @@ void SelectionTab::clickLeft(tribool down, bool previousState) | ||||
| 	if(down) | ||||
| 	{ | ||||
| 		int line = getLine(); | ||||
|  | ||||
| 		if(line != -1) | ||||
| 		{ | ||||
| 			select(line); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void SelectionTab::keyPressed(const SDL_KeyboardEvent & key) | ||||
| { | ||||
| 	if(key.state != SDL_PRESSED) | ||||
|   | ||||
| @@ -67,7 +67,7 @@ void CLabel::setAutoRedraw(bool value) | ||||
| 	autoRedraw = value; | ||||
| } | ||||
|  | ||||
| void CLabel::setText(const std::string &Txt) | ||||
| void CLabel::setText(const std::string & Txt) | ||||
| { | ||||
| 	text = Txt; | ||||
| 	if(autoRedraw) | ||||
| @@ -96,7 +96,7 @@ size_t CLabel::getWidth() | ||||
| 	return graphics->fonts[font]->getStringWidth(visibleText());; | ||||
| } | ||||
|  | ||||
| CMultiLineLabel::CMultiLineLabel(Rect position, EFonts Font, EAlignment Align, const SDL_Color &Color, const std::string &Text): | ||||
| CMultiLineLabel::CMultiLineLabel(Rect position, EFonts Font, EAlignment Align, const SDL_Color & Color, const std::string & Text) : | ||||
| 	CLabel(position.x, position.y, Font, Align, Color, Text), | ||||
| 	visibleSize(0, 0, position.w, position.h) | ||||
| { | ||||
| @@ -124,32 +124,32 @@ void CMultiLineLabel::scrollTextTo(int distance, bool redrawAfterScroll) | ||||
| 	setVisibleSize(size, redrawAfterScroll); | ||||
| } | ||||
|  | ||||
| void CMultiLineLabel::setText(const std::string &Txt) | ||||
| void CMultiLineLabel::setText(const std::string & Txt) | ||||
| { | ||||
| 	splitText(Txt, false); //setText used below can handle redraw | ||||
| 	CLabel::setText(Txt); | ||||
| } | ||||
|  | ||||
| void CTextContainer::blitLine(SDL_Surface *to, Rect destRect, std::string what) | ||||
| void CTextContainer::blitLine(SDL_Surface * to, Rect destRect, std::string what) | ||||
| { | ||||
| 	const auto f = graphics->fonts[font]; | ||||
| 	Point where = destRect.topLeft(); | ||||
|  | ||||
| 	// input is rect in which given text should be placed | ||||
| 	// calculate proper position for top-left corner of the text | ||||
| 	if (alignment == TOPLEFT) | ||||
| 	if(alignment == TOPLEFT) | ||||
| 	{ | ||||
| 		where.x += getBorderSize().x; | ||||
| 		where.y += getBorderSize().y; | ||||
| 	} | ||||
|  | ||||
| 	if (alignment == CENTER) | ||||
| 	if(alignment == CENTER) | ||||
| 	{ | ||||
| 		where.x += (int(destRect.w) - int(f->getStringWidth(what))) / 2; | ||||
| 		where.y += (int(destRect.h) - int(f->getLineHeight())) / 2; | ||||
| 	} | ||||
|  | ||||
| 	if (alignment == BOTTOMRIGHT) | ||||
| 	if(alignment == BOTTOMRIGHT) | ||||
| 	{ | ||||
| 		where.x += getBorderSize().x + destRect.w - (int)f->getStringWidth(what); | ||||
| 		where.y += getBorderSize().y + destRect.h - (int)f->getLineHeight(); | ||||
| @@ -162,11 +162,11 @@ void CTextContainer::blitLine(SDL_Surface *to, Rect destRect, std::string what) | ||||
| 	do | ||||
| 	{ | ||||
| 		size_t end = what.find_first_of(delimeters[currDelimeter % 2], begin); | ||||
| 		if (begin != end) | ||||
| 		if(begin != end) | ||||
| 		{ | ||||
| 			std::string toPrint = what.substr(begin, end - begin); | ||||
|  | ||||
| 			if (currDelimeter % 2) // Enclosed in {} text - set to yellow | ||||
| 			if(currDelimeter % 2) // Enclosed in {} text - set to yellow | ||||
| 				f->renderTextLeft(to, toPrint, Colors::YELLOW, where); | ||||
| 			else // Non-enclosed text, use default color | ||||
| 				f->renderTextLeft(to, toPrint, color, where); | ||||
| @@ -175,15 +175,15 @@ void CTextContainer::blitLine(SDL_Surface *to, Rect destRect, std::string what) | ||||
| 			where.x += (int)f->getStringWidth(toPrint); | ||||
| 		} | ||||
| 		currDelimeter++; | ||||
| 	} | ||||
| 	while (begin++ != std::string::npos); | ||||
| 	} while(begin++ != std::string::npos); | ||||
| } | ||||
|  | ||||
| CTextContainer::CTextContainer(EAlignment alignment, EFonts font, SDL_Color color): | ||||
| CTextContainer::CTextContainer(EAlignment alignment, EFonts font, SDL_Color color) : | ||||
| 	alignment(alignment), | ||||
| 	font(font), | ||||
| 	color(color) | ||||
| {} | ||||
| { | ||||
| } | ||||
|  | ||||
| void CMultiLineLabel::showAll(SDL_Surface * to) | ||||
| { | ||||
| @@ -196,12 +196,12 @@ void CMultiLineLabel::showAll(SDL_Surface * to) | ||||
| 	int beginLine = visibleSize.y; | ||||
| 	int endLine = getTextLocation().h + visibleSize.y; | ||||
|  | ||||
| 	if (beginLine < 0) | ||||
| 	if(beginLine < 0) | ||||
| 		beginLine = 0; | ||||
| 	else | ||||
| 		beginLine /= (int)f->getLineHeight(); | ||||
|  | ||||
| 	if (endLine < 0) | ||||
| 	if(endLine < 0) | ||||
| 		endLine = 0; | ||||
| 	else | ||||
| 		endLine /= (int)f->getLineHeight(); | ||||
| @@ -213,16 +213,16 @@ void CMultiLineLabel::showAll(SDL_Surface * to) | ||||
|  | ||||
| 	CSDL_Ext::CClipRectGuard guard(to, getTextLocation()); // to properly trim text that is too big to fit | ||||
|  | ||||
| 	for (int i = beginLine; i < std::min(totalLines, endLine); i++) | ||||
| 	for(int i = beginLine; i < std::min(totalLines, endLine); i++) | ||||
| 	{ | ||||
| 		if (!lines[i].empty()) //non-empty line | ||||
| 		if(!lines[i].empty()) //non-empty line | ||||
| 			blitLine(to, Rect(lineStart, lineSize), lines[i]); | ||||
|  | ||||
| 		lineStart.y += (int)f->getLineHeight(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CMultiLineLabel::splitText(const std::string &Txt, bool redrawAfter) | ||||
| void CMultiLineLabel::splitText(const std::string & Txt, bool redrawAfter) | ||||
| { | ||||
| 	lines.clear(); | ||||
|  | ||||
| @@ -233,8 +233,8 @@ void CMultiLineLabel::splitText(const std::string &Txt, bool redrawAfter) | ||||
|  | ||||
| 	textSize.y = lineHeight * (int)lines.size(); | ||||
| 	textSize.x = 0; | ||||
| 	for(const std::string &line : lines) | ||||
| 		vstd::amax( textSize.x, f->getStringWidth(line.c_str())); | ||||
| 	for(const std::string & line : lines) | ||||
| 		vstd::amax(textSize.x, f->getStringWidth(line.c_str())); | ||||
| 	if(redrawAfter) | ||||
| 		redraw(); | ||||
| } | ||||
| @@ -244,7 +244,7 @@ Rect CMultiLineLabel::getTextLocation() | ||||
| 	// this method is needed for vertical alignment alignment of text | ||||
| 	// when height of available text is smaller than height of widget | ||||
| 	// in this case - we should add proper offset to display text at required position | ||||
| 	if (pos.h <= textSize.y) | ||||
| 	if(pos.h <= textSize.y) | ||||
| 		return pos; | ||||
|  | ||||
| 	Point textSize(pos.w, (int)graphics->fonts[font]->getLineHeight() * (int)lines.size()); | ||||
| @@ -263,12 +263,12 @@ Rect CMultiLineLabel::getTextLocation() | ||||
| CLabelGroup::CLabelGroup(EFonts Font, EAlignment Align, const SDL_Color & Color) | ||||
| 	: font(Font), align(Align), color(Color) | ||||
| { | ||||
| 	defActions = 255-DISPOSE; | ||||
| 	defActions = 255 - DISPOSE; | ||||
| } | ||||
|  | ||||
| void CLabelGroup::add(int x, int y, const std::string &text) | ||||
| void CLabelGroup::add(int x, int y, const std::string & text) | ||||
| { | ||||
| 	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); | ||||
| 	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE); | ||||
| 	labels.push_back(std::make_shared<CLabel>(x, y, font, align, color, text)); | ||||
| } | ||||
|  | ||||
| @@ -277,11 +277,11 @@ size_t CLabelGroup::currentSize() const | ||||
| 	return labels.size(); | ||||
| } | ||||
|  | ||||
| CTextBox::CTextBox(std::string Text, const Rect &rect, int SliderStyle, EFonts Font, EAlignment Align, const SDL_Color &Color): | ||||
| CTextBox::CTextBox(std::string Text, const Rect & rect, int SliderStyle, EFonts Font, EAlignment Align, const SDL_Color & Color) : | ||||
| 	sliderStyle(SliderStyle), | ||||
| 	slider(nullptr) | ||||
| { | ||||
| 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); | ||||
| 	OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE); | ||||
| 	label = std::make_shared<CMultiLineLabel>(rect, Font, Align, Color); | ||||
|  | ||||
| 	type |= REDRAW_PARENT; | ||||
| @@ -310,7 +310,7 @@ void CTextBox::resize(Point newSize) | ||||
| 	setText(label->getText()); // force refresh | ||||
| } | ||||
|  | ||||
| void CTextBox::setText(const std::string &text) | ||||
| void CTextBox::setText(const std::string & text) | ||||
| { | ||||
| 	label->pos.w = pos.w; // reset to default before textSize.y check | ||||
| 	label->setText(text); | ||||
| @@ -332,7 +332,7 @@ void CTextBox::setText(const std::string &text) | ||||
| 		label->pos.w = pos.w - 32; | ||||
| 		label->setText(text); | ||||
|  | ||||
| 		OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); | ||||
| 		OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE); | ||||
| 		slider = std::make_shared<CSlider>(Point(pos.w - 32, 0), pos.h, std::bind(&CTextBox::sliderMoved, this, _1), | ||||
| 			label->pos.h, label->textSize.y, 0, false, CSlider::EStyle(sliderStyle)); | ||||
| 		slider->setScrollStep((int)graphics->fonts[label->font]->getLineHeight()); | ||||
| @@ -364,7 +364,7 @@ CGStatusBar::CGStatusBar(std::shared_ptr<CPicture> background_, EFonts Font, EAl | ||||
| CGStatusBar::CGStatusBar(int x, int y, std::string name, int maxw) | ||||
| 	: CLabel(x, y, FONT_SMALL, CENTER) | ||||
| { | ||||
| 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); | ||||
| 	OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE); | ||||
| 	background = std::make_shared<CPicture>(name); | ||||
| 	pos = background->pos; | ||||
|  | ||||
| @@ -391,12 +391,12 @@ void CGStatusBar::init() | ||||
| Point CGStatusBar::getBorderSize() | ||||
| { | ||||
| 	//Width of borders where text should not be printed | ||||
| 	static const Point borderSize(5,1); | ||||
| 	static const Point borderSize(5, 1); | ||||
|  | ||||
| 	switch(alignment) | ||||
| 	{ | ||||
| 	case TOPLEFT:     return Point(borderSize.x, borderSize.y); | ||||
| 	case CENTER:      return Point(pos.w/2, pos.h/2); | ||||
| 	case CENTER:      return Point(pos.w / 2, pos.h / 2); | ||||
| 	case BOTTOMRIGHT: return Point(pos.w - borderSize.x, pos.h - borderSize.y); | ||||
| 	} | ||||
| 	assert(0); | ||||
| @@ -408,35 +408,43 @@ void CGStatusBar::lock(bool shouldLock) | ||||
| 	textLock = shouldLock; | ||||
| } | ||||
|  | ||||
| CTextInput::CTextInput(const Rect &Pos, EFonts font, const CFunctionList<void(const std::string &)> &CB) | ||||
| CTextInput::CTextInput(const Rect & Pos, EFonts font, const CFunctionList<void(const std::string &)> & CB) | ||||
| 	: CLabel(Pos.x, Pos.y, font, CENTER), | ||||
| 	cb(CB) | ||||
| 	cb(CB), | ||||
| 	CFocusable(std::make_shared<CKeyboardFocusListener>(this)) | ||||
| { | ||||
| 	type |= REDRAW_PARENT; | ||||
| 	focus = false; | ||||
| 	pos.h = Pos.h; | ||||
| 	pos.w = Pos.w; | ||||
| 	captureAllKeys = true; | ||||
| 	background.reset(); | ||||
| 	addUsedEvents(LCLICK | KEYBOARD | TEXTINPUT); | ||||
|  | ||||
| #ifndef VCMI_ANDROID | ||||
| 	giveFocus(); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| CTextInput::CTextInput(const Rect & Pos, const Point & bgOffset, const std::string & bgName, const CFunctionList<void(const std::string &)> & CB) | ||||
| 	:cb(CB) | ||||
| 	:cb(CB), 	CFocusable(std::make_shared<CKeyboardFocusListener>(this)) | ||||
| { | ||||
| 	focus = false; | ||||
| 	pos += Pos; | ||||
| 	pos.h = Pos.h; | ||||
| 	pos.w = Pos.w; | ||||
|  | ||||
| 	captureAllKeys = true; | ||||
| 	OBJ_CONSTRUCTION; | ||||
| 	background = std::make_shared<CPicture>(bgName, bgOffset.x, bgOffset.y); | ||||
| 	addUsedEvents(LCLICK | KEYBOARD | TEXTINPUT); | ||||
|  | ||||
| #ifndef VCMI_ANDROID | ||||
| 	giveFocus(); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| CTextInput::CTextInput(const Rect & Pos, SDL_Surface * srf) | ||||
| 	:CFocusable(std::make_shared<CKeyboardFocusListener>(this)) | ||||
| { | ||||
| 	focus = false; | ||||
| 	pos += Pos; | ||||
| 	captureAllKeys = true; | ||||
| 	OBJ_CONSTRUCTION; | ||||
| @@ -450,35 +458,48 @@ CTextInput::CTextInput(const Rect & Pos, SDL_Surface * srf) | ||||
| 	pos.h = background->pos.h; | ||||
| 	background->pos = pos; | ||||
| 	addUsedEvents(LCLICK | KEYBOARD | TEXTINPUT); | ||||
| 	giveFocus(); | ||||
| } | ||||
|  | ||||
| void CTextInput::focusGot() | ||||
| { | ||||
| 	CSDL_Ext::startTextInput(&pos); | ||||
| #ifdef VCMI_ANDROID | ||||
| 	notifyAndroidTextInputChanged(text); | ||||
| #ifndef VCMI_ANDROID | ||||
| 	giveFocus(); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void CTextInput::focusLost() | ||||
| std::atomic<int> CKeyboardFocusListener::usageIndex(0); | ||||
|  | ||||
| CKeyboardFocusListener::CKeyboardFocusListener(CTextInput * textInput) | ||||
| 	:textInput(textInput) | ||||
| { | ||||
| 	CSDL_Ext::stopTextInput(); | ||||
| } | ||||
|  | ||||
| void CKeyboardFocusListener::focusGot() | ||||
| { | ||||
| 	CSDL_Ext::startTextInput(&textInput->pos); | ||||
| #ifdef VCMI_ANDROID | ||||
| 	textInput->notifyAndroidTextInputChanged(textInput->text); | ||||
| #endif | ||||
| 	usageIndex++; | ||||
| } | ||||
|  | ||||
| void CKeyboardFocusListener::focusLost() | ||||
| { | ||||
| 	if(0 == --usageIndex) | ||||
| 	{ | ||||
| 		CSDL_Ext::stopTextInput(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| std::string CTextInput::visibleText() | ||||
| { | ||||
| 	return focus ? text + newText + "_" : text; | ||||
| } | ||||
|  | ||||
| void CTextInput::clickLeft( tribool down, bool previousState ) | ||||
| void CTextInput::clickLeft(tribool down, bool previousState) | ||||
| { | ||||
| 	if(down && !focus) | ||||
| 		giveFocus(); | ||||
| } | ||||
|  | ||||
| void CTextInput::keyPressed( const SDL_KeyboardEvent & key ) | ||||
| void CTextInput::keyPressed(const SDL_KeyboardEvent & key) | ||||
| { | ||||
|  | ||||
| 	if(!focus || key.state != SDL_PRESSED) | ||||
| @@ -513,7 +534,7 @@ void CTextInput::keyPressed( const SDL_KeyboardEvent & key ) | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 	if (redrawNeeded) | ||||
| 	if(redrawNeeded) | ||||
| 	{ | ||||
| 		redraw(); | ||||
| 		cb(text); | ||||
| @@ -523,7 +544,7 @@ void CTextInput::keyPressed( const SDL_KeyboardEvent & key ) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CTextInput::setText( const std::string &nText, bool callCb ) | ||||
| void CTextInput::setText(const std::string & nText, bool callCb) | ||||
| { | ||||
| 	CLabel::setText(nText); | ||||
| 	if(callCb) | ||||
| @@ -550,8 +571,8 @@ void CTextInput::textInputed(const SDL_TextInputEvent & event) | ||||
|  | ||||
| 	text += event.text; | ||||
|  | ||||
| 	filters(text,oldText); | ||||
| 	if (text != oldText) | ||||
| 	filters(text, oldText); | ||||
| 	if(text != oldText) | ||||
| 	{ | ||||
| 		redraw(); | ||||
| 		cb(text); | ||||
| @@ -570,7 +591,7 @@ void CTextInput::textEdited(const SDL_TextEditingEvent & event) | ||||
|  | ||||
| 	newText = event.text; | ||||
| 	redraw(); | ||||
| 	cb(text+newText); | ||||
| 	cb(text + newText); | ||||
|  | ||||
| #ifdef VCMI_ANDROID | ||||
| 	auto editedText = text + newText; | ||||
| @@ -582,7 +603,7 @@ void CTextInput::filenameFilter(std::string & text, const std::string &) | ||||
| { | ||||
| 	static const std::string forbiddenChars = "<>:\"/\\|?*\r\n"; //if we are entering a filename, some special characters won't be allowed | ||||
| 	size_t pos; | ||||
| 	while ((pos = text.find_first_of(forbiddenChars)) != std::string::npos) | ||||
| 	while((pos = text.find_first_of(forbiddenChars)) != std::string::npos) | ||||
| 		text.erase(pos, 1); | ||||
| } | ||||
|  | ||||
| @@ -590,16 +611,16 @@ void CTextInput::numberFilter(std::string & text, const std::string & oldText, i | ||||
| { | ||||
| 	assert(minValue < maxValue); | ||||
|  | ||||
| 	if (text.empty()) | ||||
| 	if(text.empty()) | ||||
| 		text = "0"; | ||||
|  | ||||
| 	size_t pos = 0; | ||||
| 	if (text[0] == '-') //allow '-' sign as first symbol only | ||||
| 	if(text[0] == '-') //allow '-' sign as first symbol only | ||||
| 		pos++; | ||||
|  | ||||
| 	while (pos < text.size()) | ||||
| 	while(pos < text.size()) | ||||
| 	{ | ||||
| 		if (text[pos] < '0' || text[pos] > '9') | ||||
| 		if(text[pos] < '0' || text[pos] > '9') | ||||
| 		{ | ||||
| 			text = oldText; | ||||
| 			return; //new text is not number. | ||||
| @@ -609,9 +630,9 @@ void CTextInput::numberFilter(std::string & text, const std::string & oldText, i | ||||
| 	try | ||||
| 	{ | ||||
| 		int value = boost::lexical_cast<int>(text); | ||||
| 		if (value < minValue) | ||||
| 		if(value < minValue) | ||||
| 			text = boost::lexical_cast<std::string>(minValue); | ||||
| 		else if (value > maxValue) | ||||
| 		else if(value > maxValue) | ||||
| 			text = boost::lexical_cast<std::string>(maxValue); | ||||
| 	} | ||||
| 	catch(boost::bad_lexical_cast &) | ||||
| @@ -625,7 +646,7 @@ void CTextInput::numberFilter(std::string & text, const std::string & oldText, i | ||||
| #ifdef VCMI_ANDROID | ||||
| void CTextInput::notifyAndroidTextInputChanged(std::string & text) | ||||
| { | ||||
| 	if (!focus) | ||||
| 	if(!focus) | ||||
| 		return; | ||||
|  | ||||
| 	auto fun = [&text](JNIEnv * env, jclass cls, jmethodID method) | ||||
| @@ -641,6 +662,12 @@ void CTextInput::notifyAndroidTextInputChanged(std::string & text) | ||||
| #endif //VCMI_ANDROID | ||||
|  | ||||
| CFocusable::CFocusable() | ||||
| 	:CFocusable(std::make_shared<IFocusListener>()) | ||||
| { | ||||
| } | ||||
|  | ||||
| CFocusable::CFocusable(std::shared_ptr<IFocusListener> focusListener) | ||||
| 	: focusListener(focusListener) | ||||
| { | ||||
| 	focus = false; | ||||
| 	focusables.push_back(this); | ||||
| @@ -648,24 +675,30 @@ CFocusable::CFocusable() | ||||
|  | ||||
| CFocusable::~CFocusable() | ||||
| { | ||||
| 	if(inputWithFocus == this) | ||||
| 	if(hasFocus()) | ||||
| 	{ | ||||
| 		focusLost(); | ||||
| 		inputWithFocus = nullptr; | ||||
| 		focusListener->focusLost(); | ||||
| 	} | ||||
|  | ||||
| 	focusables -= this; | ||||
| } | ||||
|  | ||||
| bool CFocusable::hasFocus() const | ||||
| { | ||||
| 	return inputWithFocus == this; | ||||
| } | ||||
|  | ||||
| void CFocusable::giveFocus() | ||||
| { | ||||
| 	focus = true; | ||||
| 	focusGot(); | ||||
| 	focusListener->focusGot(); | ||||
| 	redraw(); | ||||
|  | ||||
| 	if(inputWithFocus) | ||||
| 	{ | ||||
| 		inputWithFocus->focus = false; | ||||
| 		inputWithFocus->focusListener->focusLost(); | ||||
| 		inputWithFocus->redraw(); | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -48,12 +48,12 @@ public: | ||||
|  | ||||
| 	std::string getText(); | ||||
| 	virtual void setAutoRedraw(bool option); | ||||
| 	virtual void setText(const std::string &Txt); | ||||
| 	virtual void setText(const std::string & Txt); | ||||
| 	virtual void setColor(const SDL_Color & Color); | ||||
| 	size_t getWidth(); | ||||
|  | ||||
| 	CLabel(int x=0, int y=0, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, | ||||
| 	       const SDL_Color &Color = Colors::WHITE, const std::string &Text =  ""); | ||||
| 	CLabel(int x = 0, int y = 0, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, | ||||
| 		const SDL_Color & Color = Colors::WHITE, const std::string & Text = ""); | ||||
| 	void showAll(SDL_Surface * to) override; //shows statusbar (with current text) | ||||
| }; | ||||
|  | ||||
| @@ -65,8 +65,8 @@ class CLabelGroup : public CIntObject | ||||
| 	EAlignment align; | ||||
| 	SDL_Color color; | ||||
| public: | ||||
| 	CLabelGroup(EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE); | ||||
| 	void add(int x=0, int y=0, const std::string &text =  ""); | ||||
| 	CLabelGroup(EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color & Color = Colors::WHITE); | ||||
| 	void add(int x = 0, int y = 0, const std::string & text = ""); | ||||
| 	size_t currentSize() const; | ||||
| }; | ||||
|  | ||||
| @@ -80,15 +80,15 @@ class CMultiLineLabel : public CLabel | ||||
| 	// area of text that actually will be printed, default is widget size | ||||
| 	Rect visibleSize; | ||||
|  | ||||
| 	void splitText(const std::string &Txt, bool redrawAfter); | ||||
| 	void splitText(const std::string & Txt, bool redrawAfter); | ||||
| 	Rect getTextLocation(); | ||||
| public: | ||||
| 	// total size of text, x = longest line of text, y = total height of lines | ||||
| 	Point textSize; | ||||
|  | ||||
| 	CMultiLineLabel(Rect position, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE, const std::string &Text =  ""); | ||||
| 	CMultiLineLabel(Rect position, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color & Color = Colors::WHITE, const std::string & Text = ""); | ||||
|  | ||||
| 	void setText(const std::string &Txt) override; | ||||
| 	void setText(const std::string & Txt) override; | ||||
| 	void showAll(SDL_Surface * to) override; | ||||
|  | ||||
| 	void setVisibleSize(Rect visibleSize, bool redrawElement = true); | ||||
| @@ -140,24 +140,50 @@ public: | ||||
| 	void lock(bool shouldLock); //If true, current text cannot be changed until lock(false) is called | ||||
| }; | ||||
|  | ||||
| class CFocusable; | ||||
|  | ||||
| class IFocusListener | ||||
| { | ||||
| public: | ||||
| 	virtual void focusGot() {}; | ||||
| 	virtual void focusLost() {}; | ||||
| 	virtual ~IFocusListener() = default; | ||||
| }; | ||||
|  | ||||
| /// UIElement which can get input focus | ||||
| class CFocusable : public virtual CIntObject | ||||
| { | ||||
| protected: | ||||
| 	virtual void focusGot(){}; | ||||
| 	virtual void focusLost(){}; | ||||
| private: | ||||
| 	std::shared_ptr<IFocusListener> focusListener; | ||||
|  | ||||
| public: | ||||
| 	bool focus; //only one focusable control can have focus at one moment | ||||
|  | ||||
| 	void giveFocus(); //captures focus | ||||
| 	void moveFocus(); //moves focus to next active control (may be used for tab switching) | ||||
| 	bool hasFocus() const; | ||||
|  | ||||
| 	static std::list<CFocusable *> focusables; //all existing objs | ||||
| 	static CFocusable * inputWithFocus; //who has focus now | ||||
|  | ||||
| 	static std::list<CFocusable*> focusables; //all existing objs | ||||
| 	static CFocusable *inputWithFocus; //who has focus now | ||||
| 	CFocusable(); | ||||
| 	CFocusable(std::shared_ptr<IFocusListener> focusListener); | ||||
| 	~CFocusable(); | ||||
| }; | ||||
|  | ||||
| class CTextInput; | ||||
| class CKeyboardFocusListener : public IFocusListener | ||||
| { | ||||
| private: | ||||
| 	static std::atomic<int> usageIndex; | ||||
| 	CTextInput * textInput; | ||||
|  | ||||
| public: | ||||
| 	CKeyboardFocusListener(CTextInput * textInput); | ||||
| 	void focusGot() override; | ||||
| 	void focusLost() override; | ||||
| }; | ||||
|  | ||||
| /// Text input box where players can enter text | ||||
| class CTextInput : public CLabel, public CFocusable | ||||
| { | ||||
| @@ -165,20 +191,17 @@ class CTextInput : public CLabel, public CFocusable | ||||
| protected: | ||||
| 	std::string visibleText() override; | ||||
|  | ||||
| 	void focusGot() override; | ||||
| 	void focusLost() override; | ||||
|  | ||||
| #ifdef VCMI_ANDROID | ||||
| 	void notifyAndroidTextInputChanged(std::string & text); | ||||
| #endif | ||||
| public: | ||||
| 	CFunctionList<void(const std::string &)> cb; | ||||
| 	CFunctionList<void(std::string &, const std::string &)> filters; | ||||
| 	void setText(const std::string &nText, bool callCb = false); | ||||
| 	void setText(const std::string & nText, bool callCb = false); | ||||
|  | ||||
| 	CTextInput(const Rect &Pos, EFonts font, const CFunctionList<void(const std::string &)> &CB); | ||||
| 	CTextInput(const Rect &Pos, const Point &bgOffset, const std::string &bgName, const CFunctionList<void(const std::string &)> &CB); | ||||
| 	CTextInput(const Rect &Pos, SDL_Surface *srf = nullptr); | ||||
| 	CTextInput(const Rect & Pos, EFonts font, const CFunctionList<void(const std::string &)> & CB); | ||||
| 	CTextInput(const Rect & Pos, const Point & bgOffset, const std::string & bgName, const CFunctionList<void(const std::string &)> & CB); | ||||
| 	CTextInput(const Rect & Pos, SDL_Surface * srf = nullptr); | ||||
|  | ||||
| 	void clickLeft(tribool down, bool previousState) override; | ||||
| 	void keyPressed(const SDL_KeyboardEvent & key) override; | ||||
| @@ -188,8 +211,10 @@ public: | ||||
| 	void textEdited(const SDL_TextEditingEvent & event) override; | ||||
|  | ||||
| 	//Filter that will block all characters not allowed in filenames | ||||
| 	static void filenameFilter(std::string &text, const std::string & oldText); | ||||
| 	static void filenameFilter(std::string & text, const std::string & oldText); | ||||
| 	//Filter that will allow only input of numbers in range min-max (min-max are allowed) | ||||
| 	//min-max should be set via something like std::bind | ||||
| 	static void numberFilter(std::string &text, const std::string & oldText, int minValue, int maxValue); | ||||
| 	static void numberFilter(std::string & text, const std::string & oldText, int minValue, int maxValue); | ||||
|  | ||||
| 	friend class CKeyboardFocusListener; | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user