/*
Minetest
Copyright (C) 2013 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 Lesser General Public License as published by
the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser 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 <cstdlib>
#include <algorithm>
#include <iterator>
#include <sstream>
#include <limits>
#include "guiFormSpecMenu.h"
#include "constants.h"
#include "gamedef.h"
#include "keycode.h"
#include "strfnd.h"
#include <IGUICheckBox.h>
#include <IGUIEditBox.h>
#include <IGUIButton.h>
#include <IGUIStaticText.h>
#include <IGUIFont.h>
#include <IGUIListBox.h>
#include <IGUITabControl.h>
#include <IGUIScrollBar.h>
#include <IGUIComboBox.h>
#include "log.h"
#include "tile.h" // ITextureSource
#include "util/string.h"
#include "util/numeric.h"
#include "filesys.h"
#include "gettext.h"
#define MY_CHECKPOS(a,b) \
if (v_pos.size() != 2) { \
errorstream<< "Invalid pos for element " << a << "specified: \"" \
<< parts[b] << "\"" << std::endl; \
return; \
}
#define MY_CHECKGEOM(a,b) \
if (v_geom.size() != 2) { \
errorstream<< "Invalid pos for element " << a << "specified: \"" \
<< parts[b] << "\"" << std::endl; \
return; \
}
void drawItemStack(video::IVideoDriver *driver,
gui::IGUIFont *font,
const ItemStack &item,
const core::rect<s32> &rect,
const core::rect<s32> *clip,
IGameDef *gamedef)
{
if(item.empty())
return;
const ItemDefinition &def = item.getDefinition(gamedef->idef());
video::ITexture *texture = gamedef->idef()->getInventoryTexture(def.name, gamedef);
// Draw the inventory texture
if(texture != NULL)
{
const video::SColor color(255,255,255,255);
const video::SColor colors[] = {color,color,color,color};
driver->draw2DImage(texture, rect,
core::rect<s32>(core::position2d<s32>(0,0),
core::dimension2di(texture->getOriginalSize())),
clip, colors, true);
}
if(def.type == ITEM_TOOL && item.wear != 0)
{
// Draw a progressbar
float barheight = rect.getHeight()/16;
float barpad_x = rect.getWidth()/16;
float barpad_y = rect.getHeight()/16;
core::rect<s32> progressrect(
rect.UpperLeftCorner.X + barpad_x,
rect.LowerRightCorner.Y - barpad_y - barheight,
rect.LowerRightCorner.X - barpad_x,
rect.LowerRightCorner.Y - barpad_y);
// Shrink progressrect by amount of tool damage
float wear = item.wear / 65535.0;
int progressmid =
wear * progressrect.UpperLeftCorner.X +
(1-wear) * progressrect.LowerRightCorner.X;
// Compute progressbar color
// wear = 0.0: green
// wear = 0.5: yellow
// wear = 1.0: red
video::SColor color(255,255,255,255);
int wear_i = MYMIN(floor(wear * 600), 511);
wear_i = MYMIN(wear_i + 10, 511);
if(wear_i <= 255)
color.set(255, wear_i, 255, 0);
else
color.set(255, 255, 511-wear_i, 0);
core::rect<s32> progressrect2 = progressrect;
progressrect2.LowerRightCorner.X = progressmid;
driver->draw2DRectangle(color, progressrect2, clip);
color = video::SColor(255,0,0,0);
progressrect2 = progressrect;
progressrect2.UpperLeftCorner.X = progressmid;
driver->draw2DRectangle(color, progressrect2, clip);
}
if(font != NULL && item.count >= 2)
{
// Get the item count as a string
std::string text = itos(item.count);
v2u32 dim = font->getDimension(narrow_to_wide(text).c_str());
v2s32 sdim(dim.X,dim.Y);
core::rect<s32> rect2(
/*rect.UpperLeftCorner,
core::dimension2d<u32>(rect.getWidth(), 15)*/
rect.LowerRightCorner - sdim,
sdim
);
video::SColor bgcolor(128,0,0,0);
driver->draw2DRectangle(bgcolor, rect2, clip);
video::SColor color(255,255,255,255);
font->draw(text.c_str(), rect2, color, false, false, clip);
}
}
/*
GUIFormSpecMenu
*/
GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev,
gui::IGUIElement* parent, s32 id,
IMenuManager *menumgr,
InventoryManager *invmgr,
IGameDef *gamedef
):
GUIModalMenu(dev->getGUIEnvironment(), parent, id, menumgr),
m_device(dev),
m_invmgr(invmgr),
m_gamedef(gamedef),
m_form_src(NULL),
m_text_dst(NULL),
m_selected_item(NULL),
m_selected_amount(0),
m_selected_dragging(false),
m_tooltip_element(NULL),
m_allowclose(true),
m_use_gettext(false),
m_lock(false)
{
current_keys_pending.key_down = false;
current_keys_pending.key_up = false;
current_keys_pending.key_enter = false;
}
GUIFormSpecMenu::~GUIFormSpecMenu()
{
removeChildren();
delete m_selected_item;
delete m_form_src;
delete m_text_dst;
}
void GUIFormSpecMenu::removeChildren()
{
const core::list<gui::IGUIElement*> &children = getChildren();
core::list<gui::IGUIElement*> children_copy;
for(core::list<gui::IGUIElement*>::ConstIterator
i = children.begin(); i != children.end(); i++)
{
children_copy.push_back(*i);
}
for(core::list<gui::IGUIElement*>::Iterator
i = children_copy.begin();
i != children_copy.end(); i++)
{
(*i)->remove();
}
/*{
gui::IGUIElement *e = getElementFromId(256);
if(e != NULL)
e->remove();
}*/
if(m_tooltip_element)
{
m_tooltip_element->remove();
m_tooltip_element = NULL;
}
}
int GUIFormSpecMenu::getListboxIndex(std::string listboxname) {
std::wstring wlistboxname = narrow_to_wide(listboxname.c_str());
for(unsigned int i=0; i < m_listboxes.size(); i++) {
std::wstring name(m_listboxes[i].first.fname.c_str());
if ( name == wlistboxname) {
return m_listboxes[i].second->getSelected();
}
}
return -1;
}
std::vector<std::string> split(const std::string &s, char delim, bool escape=false) {
std::vector<std::string> tokens;
if (!escape) {
int startpos = 0;
size_t nextpos = s.find(delim);
while(nextpos != std::string::npos) {
std::string toadd = s.substr(startpos,nextpos-startpos);
tokens.push_back(toadd);
startpos = nextpos+1;
nextpos = s.find(delim,nextpos+1);
}
//push last element
tokens.push_back(s.substr(startpos));
}
else {
std::string current = "";
current += s.c_str()[0];
bool last_was_escape = false;
for(unsigned int i=1; i < s.size(); i++) {
if (last_was_escape) {
current += '\\';
current += s.c_str()[i];
last_was_escape = false;
}
else {
if (s.c_str()[i] == delim) {
tokens.push_back(current);
current = "";
last_was_escape = false;
}
else if (s.c_str()[i] == '\\'){
last_was_escape = true;
}
else {
current += s.c_str()[i];
last_was_escape = false;
}
}
}
//push last element
tokens.push_back(current);
}
return tokens;
}
void GUIFormSpecMenu::parseSize(parserData* data,std::string element) {
std::vector<std::string> parts = split(element,',');
if (parts.size() == 2) {
v2f invsize;
if (parts[1].find(';') != std::string::npos)
parts[1] = parts[1].substr(0,parts[1].find(';'));
invsize.X = stof(parts[0]);
invsize.Y = stof(parts[1]);
infostream<<"Form size ("<<invsize.X<<","<<invsize.Y<<")"<<std::endl;
if (m_lock) {
|