aboutsummaryrefslogtreecommitdiff
path: root/src/guiTextInputMenu.cpp
blob: 2cb8cae6295b3e5417989408d650d959986e10b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/*
Minetest-c55
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "guiTextInputMenu.h"
#include "debug.h"
#include "serialization.h"
#include <string>

GUITextInputMenu::GUITextInputMenu(gui::IGUIEnvironment* env,
		gui::IGUIElement* parent, s32 id,
		IMenuManager *menumgr,
		TextDest *dest,
		std::wstring initial_text
):
	GUIModalMenu(env, parent, id, menumgr),
	m_dest(dest),
	m_initial_text(initial_text)
{
}

GUITextInputMenu::~GUITextInputMenu()
{
	removeChildren();
	if(m_dest)
		delete m_dest;
}

void GUITextInputMenu::removeChildren()
{
	{
		gui::IGUIElement *e = getElementFromId(256);
		if(e != NULL)
			e->remove();
	}
	{
		gui::IGUIElement *e = getElementFromId(257);
		if(e != NULL)
			e->remove();
	}
}

void GUITextInputMenu::regenerateGui(v2u32 screensize)
{
	std::wstring text;

	{
		gui::IGUIElement *e = getElementFromId(256);
		if(e != NULL)
		{
			text = e->getText();
		}
		else
		{
			text = m_initial_text;
			m_initial_text = L"";
		}
	}

	/*
		Remove stuff
	*/
	removeChildren();
	
	/*
		Calculate new sizes and positions
	*/
	core::rect<s32> rect(
			screensize.X/2 - 580/2,
			screensize.Y/2 - 300/2,
			screensize.X/2 + 580/2,
			screensize.Y/2 + 300/2
	);
	
	DesiredRect = rect;
	recalculateAbsolutePosition(false);

	v2s32 size = rect.getSize();

	/*
		Add stuff
	*/
	{
		core::rect<s32> rect(0, 0, 300, 30);
		rect = rect + v2s32(size.X/2-300/2, size.Y/2-30/2-25);
		gui::IGUIElement *e = 
		Environment->addEditBox(text.c_str(), rect, true, this, 256);
		Environment->setFocus(e);
	}
	{
		core::rect<s32> rect(0, 0, 140, 30);
		rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2+25);
		Environment->addButton(rect, this, 257, L"Proceed");
	}
}

void GUITextInputMenu::drawMenu()
{
	gui::IGUISkin* skin = Environment->getSkin();
	if (!skin)
		return;
	video::IVideoDriver* driver = Environment->getVideoDriver();
	
	video::SColor bgcolor(140,0,0,0);
	driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);

	gui::IGUIElement::draw();
}

void GUITextInputMenu::acceptInput()
{
	if(m_dest)
	{
		gui::IGUIElement *e = getElementFromId(256);
		if(e != NULL)
		{
			m_dest->gotText(e->getText());
		}
		delete m_dest;
		m_dest = NULL;
	}
}

bool GUITextInputMenu::OnEvent(const SEvent& event)
{
	if(event.EventType==EET_KEY_INPUT_EVENT)
	{
		if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown)
		{
			quitMenu();
			return true;
		}
		if(event.KeyInput.Key==KEY_RETURN && event.KeyInput.PressedDown)
		{
			acceptInput();
			quitMenu();
			return true;
		}
	}
	if(event.EventType==EET_GUI_EVENT)
	{
		if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
				&& isVisible())
		{
			if(!canTakeFocus(event.GUIEvent.Element))
			{
				dstream<<"GUITextInputMenu: Not allowing focus change."
						<<std::endl;
				// Returning true disables focus change
				return true;
			}
		}
		if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
		{
			switch(event.GUIEvent.Caller->getID())
			{
			case 257:
				acceptInput();
				quitMenu();
				// quitMenu deallocates menu
				return true;
			}
		}
		if(event.GUIEvent.EventType==gui::EGET_EDITBOX_ENTER)
		{
			switch(event.GUIEvent.Caller->getID())
			{
			case 256:
				acceptInput();
				quitMenu();
				// quitMenu deallocates menu
				return true;
			}
		}
	}

	return Parent ? Parent->OnEvent(event) : false;
}

D_REASON_TOO_MANY_OBJECTS (1 << 14) #define MOD_REASON_STATIC_DATA_ADDED (1 << 15) #define MOD_REASON_STATIC_DATA_REMOVED (1 << 16) #define MOD_REASON_STATIC_DATA_CHANGED (1 << 17) #define MOD_REASON_EXPIRE_DAYNIGHTDIFF (1 << 18) #define MOD_REASON_VMANIP (1 << 19) #define MOD_REASON_UNKNOWN (1 << 20) //// //// MapBlock itself //// class MapBlock { public: MapBlock(Map *parent, v3s16 pos, IGameDef *gamedef, bool dummy=false); ~MapBlock(); /*virtual u16 nodeContainerId() const { return NODECONTAINER_ID_MAPBLOCK; }*/ Map * getParent() { return m_parent; } void reallocate() { delete[] data; data = new MapNode[nodecount]; for (u32 i = 0; i < nodecount; i++) data[i] = MapNode(CONTENT_IGNORE); raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_REALLOCATE); } MapNode* getData() { return data; } //// //// Modification tracking methods //// void raiseModified(u32 mod, u32 reason=MOD_REASON_UNKNOWN) { if (mod > m_modified) { m_modified = mod; m_modified_reason = reason; if (m_modified >= MOD_STATE_WRITE_AT_UNLOAD) m_disk_timestamp = m_timestamp; } else if (mod == m_modified) { m_modified_reason |= reason; } if (mod == MOD_STATE_WRITE_NEEDED) contents_cached = false; } inline u32 getModified() { return m_modified; } inline u32 getModifiedReason() { return m_modified_reason; } std::string getModifiedReasonString(); inline void resetModified() { m_modified = MOD_STATE_CLEAN; m_modified_reason = 0; } //// //// Flags //// inline bool isDummy() const { return !data; } inline void unDummify() { assert(isDummy()); // Pre-condition reallocate(); } // is_underground getter/setter inline bool getIsUnderground() { return is_underground; } inline void setIsUnderground(bool a_is_underground) { is_underground = a_is_underground; raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_IS_UNDERGROUND); } inline void setLightingComplete(u16 newflags) { if (newflags != m_lighting_complete) { m_lighting_complete = newflags; raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_LIGHTING_COMPLETE); } } inline u16 getLightingComplete() { return m_lighting_complete; } inline void setLightingComplete(LightBank bank, u8 direction, bool is_complete) { assert(direction >= 0 && direction <= 5); if (bank == LIGHTBANK_NIGHT) { direction += 6; } u16 newflags = m_lighting_complete; if (is_complete) { newflags |= 1 << direction; } else { newflags &= ~(1 << direction); } setLightingComplete(newflags); } inline bool isLightingComplete(LightBank bank, u8 direction) { assert(direction >= 0 && direction <= 5); if (bank == LIGHTBANK_NIGHT) { direction += 6; } return (m_lighting_complete & (1 << direction)) != 0; } inline bool isGenerated() { return m_generated; } inline void setGenerated(bool b) { if (b != m_generated) { raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_GENERATED); m_generated = b; } } //// //// Position stuff //// inline v3s16 getPos() { return m_pos; } inline v3s16 getPosRelative() { return m_pos_relative; } inline core::aabbox3d<s16> getBox() { return core::aabbox3d<s16>(getPosRelative(), getPosRelative() + v3s16(MAP_BLOCKSIZE, MAP_BLOCKSIZE, MAP_BLOCKSIZE) - v3s16(1,1,1)); } //// //// Regular MapNode get-setters //// inline bool isValidPosition(s16 x, s16 y, s16 z) { return data && x >= 0 && x < MAP_BLOCKSIZE && y >= 0 && y < MAP_BLOCKSIZE && z >= 0 && z < MAP_BLOCKSIZE; } inline bool isValidPosition(v3s16 p) { return isValidPosition(p.X, p.Y, p.Z); } inline MapNode getNode(s16 x, s16 y, s16 z, bool *valid_position) { *valid_position = isValidPosition(x, y, z); if (!*valid_position) return {CONTENT_IGNORE}; return data[z * zstride + y * ystride + x]; } inline MapNode getNode(v3s16 p, bool *valid_position) { return getNode(p.X, p.Y, p.Z, valid_position); } inline MapNode getNodeNoEx(v3s16 p) { bool is_valid; return getNode(p.X, p.Y, p.Z, &is_valid); } inline void setNode(s16 x, s16 y, s16 z, MapNode & n) { if (!isValidPosition(x, y, z)) throw InvalidPositionException(); data[z * zstride + y * ystride + x] = n; raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_NODE); } inline void setNode(v3s16 p, MapNode & n) { setNode(p.X, p.Y, p.Z, n); } //// //// Non-checking variants of the above //// inline MapNode getNodeNoCheck(s16 x, s16 y, s16 z, bool *valid_position) { *valid_position = data != nullptr; if (!*valid_position) return {CONTENT_IGNORE}; return data[z * zstride + y * ystride + x]; } inline MapNode getNodeNoCheck(v3s16 p, bool *valid_position) { return getNodeNoCheck(p.X, p.Y, p.Z, valid_position); } //// //// Non-checking, unsafe variants of the above //// MapBlock must be loaded by another function in the same scope/function //// Caller must ensure that this is not a dummy block (by calling isDummy()) //// inline const MapNode &getNodeUnsafe(s16 x, s16 y, s16 z) { return data[z * zstride + y * ystride + x]; } inline const MapNode &getNodeUnsafe(v3s16 &p) { return getNodeUnsafe(p.X, p.Y, p.Z); } inline void setNodeNoCheck(s16 x, s16 y, s16 z, MapNode & n) { if (!data) throw InvalidPositionException(); data[z * zstride + y * ystride + x] = n; raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_NODE_NO_CHECK); } inline void setNodeNoCheck(v3s16 p, MapNode & n) { setNodeNoCheck(p.X, p.Y, p.Z, n); } // These functions consult the parent container if the position // is not valid on this MapBlock. bool isValidPositionParent(v3s16 p); MapNode getNodeParent(v3s16 p, bool *is_valid_position = NULL); // Copies data to VoxelManipulator to getPosRelative() void copyTo(VoxelManipulator &dst); // Copies data from VoxelManipulator getPosRelative() void copyFrom(VoxelManipulator &dst); // Update day-night lighting difference flag. // Sets m_day_night_differs to appropriate value. // These methods don't care about neighboring blocks. void actuallyUpdateDayNightDiff(); // Call this to schedule what the previous function does to be done // when the value is actually needed. void expireDayNightDiff(); inline bool getDayNightDiff() { if (m_day_night_differs_expired) actuallyUpdateDayNightDiff(); return m_day_night_differs; } //// //// Miscellaneous stuff //// /* Tries to measure ground level. Return value: -1 = only air -2 = only ground -3 = random fail 0...MAP_BLOCKSIZE-1 = ground level */ s16 getGroundLevel(v2s16 p2d); //// //// Timestamp (see m_timestamp) //// // NOTE: BLOCK_TIMESTAMP_UNDEFINED=0xffffffff means there is no timestamp. inline void setTimestamp(u32 time) { m_timestamp = time; raiseModified(MOD_STATE_WRITE_AT_UNLOAD, MOD_REASON_SET_TIMESTAMP); } inline void setTimestampNoChangedFlag(u32 time) { m_timestamp = time; } inline u32 getTimestamp() { return m_timestamp; } inline u32 getDiskTimestamp() { return m_disk_timestamp; } //// //// Usage timer (see m_usage_timer)