#include "util/numeric.h"
#include "filesys.h"
#include "gettime.h"
-
#include "gettext.h"
-
#define MY_CHECKPOS(a,b) \
if (v_pos.size() != 2) { \
errorstream<< "Invalid pos for element " << a << "specified: \"" \
gui::IGUIElement* parent, s32 id,
IMenuManager *menumgr,
InventoryManager *invmgr,
- IGameDef *gamedef
+ IGameDef *gamedef,
+ ISimpleTextureSource *tsrc
):
GUIModalMenu(dev->getGUIEnvironment(), parent, id, menumgr),
m_device(dev),
m_invmgr(invmgr),
m_gamedef(gamedef),
+ m_tsrc(tsrc),
m_form_src(NULL),
m_text_dst(NULL),
m_selected_item(NULL),
m_listbox_doubleclick(false),
m_tooltip_element(NULL),
m_allowclose(true),
- m_use_gettext(false),
m_lock(false)
{
current_keys_pending.key_down = false;
if(e != NULL)
e->remove();
}*/
+
if(m_tooltip_element)
{
m_tooltip_element->remove();
+ m_tooltip_element->drop();
m_tooltip_element = NULL;
}
+
+}
+
+void GUIFormSpecMenu::setInitialFocus()
+{
+ // Set initial focus according to following order of precedence:
+ // 1. first empty editbox
+ // 2. first editbox
+ // 3. first listbox
+ // 4. last button
+ // 5. first focusable (not statictext, not tabheader)
+ // 6. first child element
+
+ core::list<gui::IGUIElement*> children = getChildren();
+
+ // in case "children" contains any NULL elements, remove them
+ for (core::list<gui::IGUIElement*>::Iterator it = children.begin();
+ it != children.end();) {
+ if (*it)
+ ++it;
+ else
+ it = children.erase(it);
+ }
+
+ // 1. first empty editbox
+ for (core::list<gui::IGUIElement*>::Iterator it = children.begin();
+ it != children.end(); ++it) {
+ if ((*it)->getType() == gui::EGUIET_EDIT_BOX
+ && (*it)->getText()[0] == 0) {
+ Environment->setFocus(*it);
+ return;
+ }
+ }
+
+ // 2. first editbox
+ for (core::list<gui::IGUIElement*>::Iterator it = children.begin();
+ it != children.end(); ++it) {
+ if ((*it)->getType() == gui::EGUIET_EDIT_BOX) {
+ Environment->setFocus(*it);
+ return;
+ }
+ }
+
+ // 3. first listbox
+ for (core::list<gui::IGUIElement*>::Iterator it = children.begin();
+ it != children.end(); ++it) {
+ if ((*it)->getType() == gui::EGUIET_LIST_BOX) {
+ Environment->setFocus(*it);
+ return;
+ }
+ }
+
+ // 4. last button
+ for (core::list<gui::IGUIElement*>::Iterator it = children.getLast();
+ it != children.end(); --it) {
+ if ((*it)->getType() == gui::EGUIET_BUTTON) {
+ Environment->setFocus(*it);
+ return;
+ }
+ }
+
+ // 5. first focusable (not statictext, not tabheader)
+ for (core::list<gui::IGUIElement*>::Iterator it = children.begin();
+ it != children.end(); ++it) {
+ if ((*it)->getType() != gui::EGUIET_STATIC_TEXT &&
+ (*it)->getType() != gui::EGUIET_TAB_CONTROL) {
+ Environment->setFocus(*it);
+ return;
+ }
+ }
+
+ // 6. first child element
+ if (children.empty())
+ Environment->setFocus(this);
+ else
+ Environment->setFocus(*(children.begin()));
}
int GUIFormSpecMenu::getListboxIndex(std::string listboxname) {
invsize.X = stof(parts[0]);
invsize.Y = stof(parts[1]);
- infostream<<"Form size ("<<invsize.X<<","<<invsize.Y<<")"<<std::endl;
-
if (m_lock) {
v2u32 current_screensize = m_device->getVideoDriver()->getScreenSize();
v2u32 delta = current_screensize - m_lockscreensize;
v2s32 geom;
geom.X = stoi(v_geom[0]);
geom.Y = stoi(v_geom[1]);
- infostream<<"list inv="<<location<<", listname="<<listname
- <<", pos=("<<pos.X<<","<<pos.Y<<")"
- <<", geom=("<<geom.X<<","<<geom.Y<<")"
- <<std::endl;
s32 start_i = 0;
if(startindex != "")
std::wstring wlabel = narrow_to_wide(label.c_str());
- if (m_use_gettext)
- wlabel = wstrgettext(label);
-
FieldSpec spec = FieldSpec(
narrow_to_wide(name.c_str()),
L"",
spec.flabel = wlabel; //Needed for displaying text on MSVC
gui::IGUICheckBox* e = Environment->addCheckBox(fselected, rect, this,
spec.fid, spec.flabel.c_str());
+
+ if (spec.fname == data->focused_fieldname) {
+ Environment->setFocus(e);
+ }
+
m_checkboxes.push_back(std::pair<FieldSpec,gui::IGUICheckBox*>(spec,e));
m_fields.push_back(spec);
return;
if (parts.size() == 3) {
std::vector<std::string> v_pos = split(parts[0],',');
std::vector<std::string> v_geom = split(parts[1],',');
- std::string name = parts[2];
+ std::string name = unescape_string(parts[2]);
MY_CHECKPOS("image",0);
MY_CHECKGEOM("image",1);
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
v2s32 geom;
- geom.X = stoi(v_geom[0]) * (float)imgsize.X;
- geom.Y = stoi(v_geom[1]) * (float)imgsize.Y;
+ geom.X = stof(v_geom[0]) * (float)imgsize.X;
+ geom.Y = stof(v_geom[1]) * (float)imgsize.Y;
- infostream<<"image name="<<name
- <<", pos=("<<pos.X<<","<<pos.Y<<")"
- <<", geom=("<<geom.X<<","<<geom.Y<<")"
- <<std::endl;
if(data->bp_set != 2)
errorstream<<"WARNING: invalid use of image without a size[] element"<<std::endl;
m_images.push_back(ImageDrawSpec(name, pos, geom));
if (parts.size() == 2) {
std::vector<std::string> v_pos = split(parts[0],',');
- std::string name = parts[1];
+ std::string name = unescape_string(parts[1]);
MY_CHECKPOS("image",0);
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
- std::cout<<"image name="<<name
- <<", pos=("<<pos.X<<","<<pos.Y<<")"
- <<std::endl;
if(data->bp_set != 2)
errorstream<<"WARNING: invalid use of image without a size[] element"<<std::endl;
m_images.push_back(ImageDrawSpec(name, pos));
geom.X = stoi(v_geom[0]) * (float)imgsize.X;
geom.Y = stoi(v_geom[1]) * (float)imgsize.Y;
- infostream<<"item name="<<name
- <<", pos=("<<pos.X<<","<<pos.Y<<")"
- <<", geom=("<<geom.X<<","<<geom.Y<<")"
- <<std::endl;
if(data->bp_set != 2)
errorstream<<"WARNING: invalid use of item_image without a size[] element"<<std::endl;
m_itemimages.push_back(ImageDrawSpec(name, pos, geom));
std::wstring wlabel = narrow_to_wide(label.c_str());
- if (m_use_gettext)
- wlabel = wstrgettext(label);
-
FieldSpec spec = FieldSpec(
narrow_to_wide(name.c_str()),
wlabel,
if(type == "button_exit")
spec.is_exit = true;
- Environment->addButton(rect, this, spec.fid, spec.flabel.c_str());
+ gui::IGUIButton* e = Environment->addButton(rect, this, spec.fid,
+ spec.flabel.c_str());
+
+ if (spec.fname == data->focused_fieldname) {
+ Environment->setFocus(e);
+ }
+
m_fields.push_back(spec);
return;
}
if (parts.size() == 3) {
std::vector<std::string> v_pos = split(parts[0],',');
std::vector<std::string> v_geom = split(parts[1],',');
- std::string name = parts[2];
+ std::string name = unescape_string(parts[2]);
MY_CHECKPOS("background",0);
MY_CHECKGEOM("background",1);
geom.X = stof(v_geom[0]) * (float)spacing.X;
geom.Y = stof(v_geom[1]) * (float)spacing.Y;
- infostream<<"image name="<<name
- <<", pos=("<<pos.X<<","<<pos.Y<<")"
- <<", geom=("<<geom.X<<","<<geom.Y<<")"
- <<std::endl;
if(data->bp_set != 2)
errorstream<<"WARNING: invalid use of background without a size[] element"<<std::endl;
m_backgrounds.push_back(ImageDrawSpec(name, pos, geom));
//now really show list
gui::IGUIListBox *e = Environment->addListBox(rect, this,spec.fid);
- //don't reset if we already have a user specified selection
- if (data->listbox_selections.find(fname_w) == data->listbox_selections.end()) {
- e->setAutoScrollEnabled(false);
+ if (spec.fname == data->focused_fieldname) {
+ Environment->setFocus(e);
}
if (str_transparent == "false")
std::wstring toadd =
narrow_to_wide(unescape_string(items[i]).c_str() + 7);
-
e->addItem(toadd.c_str());
irr::video::SColor toset;
//now really show list
gui::IGUIComboBox *e = Environment->addComboBox(rect, this,spec.fid);
- //don't reset if we already have a user specified selection
- //if (data->combobox_selections.find(fname_w) == data->listbox_selections.end()) {
- // e->setAutoScrollEnabled(false);
- //}
+ if (spec.fname == data->focused_fieldname) {
+ Environment->setFocus(e);
+ }
for (unsigned int i=0; i < items.size(); i++) {
e->addItem(narrow_to_wide(items[i]).c_str());
if (str_initial_selection != "")
e->setSelected(stoi(str_initial_selection.c_str())-1);
- //if (data->listbox_selections.find(fname_w) != data->listbox_selections.end()) {
- // e->setSelected(data->listbox_selections[fname_w]);
- //}
-
- //m_listboxes.push_back(std::pair<FieldSpec,gui::IGUIListBox*>(spec,e));
m_fields.push_back(spec);
return;
}
std::wstring wlabel = narrow_to_wide(label.c_str());
- if (m_use_gettext) {
- if (label.length() > 1)
- wlabel = wstrgettext(label);
- else
- wlabel = L"";
- }
-
FieldSpec spec = FieldSpec(
narrow_to_wide(name.c_str()),
wlabel,
spec.send = true;
gui::IGUIEditBox * e = Environment->addEditBox(0, rect, true, this, spec.fid);
- Environment->setFocus(e);
+
+ if (spec.fname == data->focused_fieldname) {
+ Environment->setFocus(e);
+ }
if (label.length() > 1)
{
std::wstring wlabel = narrow_to_wide(label.c_str());
- if (m_use_gettext) {
- if (label.length() > 1)
- wlabel = wstrgettext(label);
- else
- wlabel = L"";
- }
-
FieldSpec spec = FieldSpec(
narrow_to_wide(name.c_str()),
wlabel,
{
spec.send = true;
gui::IGUIEditBox *e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid);
- Environment->setFocus(e);
+
+ if (spec.fname == data->focused_fieldname) {
+ Environment->setFocus(e);
+ }
irr::SEvent evt;
evt.EventType = EET_KEY_INPUT_EVENT;
std::wstring wlabel = narrow_to_wide(label.c_str());
- if (m_use_gettext) {
- if (label.length() > 1)
- wlabel = wstrgettext(label);
- else
- wlabel = L"";
- }
-
FieldSpec spec = FieldSpec(
narrow_to_wide(name.c_str()),
wlabel,
{
spec.send = true;
gui::IGUIEditBox *e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid);
- Environment->setFocus(e);
+
+ if (spec.fname == data->focused_fieldname) {
+ Environment->setFocus(e);
+ }
if (type == "textarea")
{
std::wstring wlabel = narrow_to_wide(text.c_str());
- if (m_use_gettext)
- wlabel = wstrgettext(text);
-
FieldSpec spec = FieldSpec(
L"",
wlabel,
if (parts.size() == 2) {
std::vector<std::string> v_pos = split(parts[0],',');
- std::string text = parts[1];
+ std::wstring text = narrow_to_wide(unescape_string(parts[1]));
MY_CHECKPOS("vertlabel",1);
if(data->bp_set != 2)
errorstream<<"WARNING: invalid use of label without a size[] element"<<std::endl;
- text = unescape_string(text);
- std::string label = "";
-
- if (m_use_gettext) {
- const char* toset = gettext(text.c_str());
-
- text = std::string(toset);
- }
+ std::wstring label = L"";
for (unsigned int i=0; i < text.length(); i++) {
- label += text.c_str()[i];
- label += "\n";
+ label += text[i];
+ label += L"\n";
}
FieldSpec spec = FieldSpec(
L"",
- narrow_to_wide(label.c_str()),
+ label,
L"",
258+m_fields.size()
);
core::rect<s32> rect = core::rect<s32>(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y);
if(data->bp_set != 2)
- errorstream<<"WARNING: invalid use of item_image_button without a size[] element"<<std::endl;
+ errorstream<<"WARNING: invalid use of image_button without a size[] element"<<std::endl;
+ image_name = unescape_string(image_name);
+ pressed_image_name = unescape_string(pressed_image_name);
label = unescape_string(label);
std::wstring wlabel = narrow_to_wide(label.c_str());
- if (m_use_gettext)
- wlabel = wstrgettext(label);
-
FieldSpec spec = FieldSpec(
narrow_to_wide(name.c_str()),
wlabel,
video::ITexture *texture = 0;
video::ITexture *pressed_texture = 0;
- //if there's no gamedef specified try to get direct
- //TODO check for possible texture leak
- if (m_gamedef != 0) {
- texture = m_gamedef->tsrc()->getTexture(image_name);
- if ((parts.size() == 8)) {
- pressed_texture = m_gamedef->tsrc()->getTexture(pressed_image_name);
- }
- } else {
- if (fs::PathExists(image_name)) {
- texture = Environment->getVideoDriver()->getTexture(image_name.c_str());
- m_Textures.push_back(texture);
- }
- if (fs::PathExists(pressed_image_name)) {
- pressed_texture = Environment->getVideoDriver()->getTexture(pressed_image_name.c_str());
- m_Textures.push_back(pressed_texture);
- }
- }
- if (parts.size() < 8)
+ texture = m_tsrc->getTexture(image_name);
+ if (parts.size() == 8)
+ pressed_texture = m_tsrc->getTexture(pressed_image_name);
+ else
pressed_texture = texture;
gui::IGUIButton *e = Environment->addButton(rect, this, spec.fid, spec.flabel.c_str());
+
+ if (spec.fname == data->focused_fieldname) {
+ Environment->setFocus(e);
+ }
+
e->setUseAlphaChannel(true);
e->setImage(texture);
e->setPressedImage(pressed_texture);
gui::IGUITabControl *e = Environment->addTabControl(rect,this,show_background,show_border,spec.fid);
+ if (spec.fname == data->focused_fieldname) {
+ Environment->setFocus(e);
+ }
+
e->setNotClipped(true);
for (unsigned int i=0; i< buttons.size(); i++) {
wchar_t* wbutton = 0;
- if (m_use_gettext)
- wbutton = wgettext(buttons[i].c_str());
- else
- wbutton = (wchar_t*) narrow_to_wide(buttons[i].c_str()).c_str();
+ std::wstring wlabel = narrow_to_wide(buttons[i]); //Needed for displaying text on windows
+ wbutton = (wchar_t*) wlabel.c_str();
e->addTab(wbutton,-1);
-
- if (m_use_gettext)
- delete[] wbutton;
}
if ((tab_index >= 0) &&
);
gui::IGUIButton *e = Environment->addButton(rect, this, spec.fid, spec.flabel.c_str());
+
+ if (spec.fname == data->focused_fieldname) {
+ Environment->setFocus(e);
+ }
+
e->setUseAlphaChannel(true);
e->setImage(texture);
e->setPressedImage(texture);
}
}
+ //preserve focus
+ gui::IGUIElement *focused_element = Environment->getFocus();
+ if (focused_element && focused_element->getParent() == this) {
+ s32 focused_id = focused_element->getID();
+ if (focused_id > 257) {
+ for (u32 i=0; i<m_fields.size(); i++) {
+ if (m_fields[i].fid == focused_id) {
+ mydata.focused_fieldname =
+ m_fields[i].fname;
+ break;
+ }
+ }
+ }
+ }
+
// Remove children
removeChildren();
m_tooltip_element->setOverrideColor(video::SColor(255,255,255,255));
m_tooltip_element->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
m_tooltip_element->setWordWrap(false);
+ //we're not parent so no autograb for this one!
+ m_tooltip_element->grab();
}
+
+ //set initial focus if parser didn't set it
+ focused_element = Environment->getFocus();
+ if (!focused_element
+ || !isMyChild(focused_element)
+ || focused_element->getType() == gui::EGUIET_TAB_CONTROL)
+ setInitialFocus();
}
GUIFormSpecMenu::ItemSpec GUIFormSpecMenu::getItemAtPos(v2s32 p) const
for(u32 i=0; i<m_backgrounds.size(); i++)
{
const ImageDrawSpec &spec = m_backgrounds[i];
- video::ITexture *texture = 0;
-
- if (m_gamedef != 0)
- texture = m_gamedef->tsrc()->getTexture(spec.name);
- else
- {
- texture = driver->getTexture(spec.name.c_str());
- m_Textures.push_back(texture);
- }
+ video::ITexture *texture = m_tsrc->getTexture(spec.name);
if (texture != 0) {
// Image size on screen
for(u32 i=0; i<m_images.size(); i++)
{
const ImageDrawSpec &spec = m_images[i];
- video::ITexture *texture = 0;
+ video::ITexture *texture = m_tsrc->getTexture(spec.name);
- if (m_gamedef != 0)
- texture = m_gamedef->tsrc()->getTexture(spec.name);
- else
- {
- texture = driver->getTexture(spec.name.c_str());
- m_Textures.push_back(texture);
- }
if (texture != 0) {
const core::dimension2d<u32>& img_origsize = texture->getOriginalSize();
// Image size on screen
}
}
+bool GUIFormSpecMenu::preprocessEvent(const SEvent& event)
+{
+ // Fix Esc/Return key being eaten by checkboxen and listboxen
+ if(event.EventType==EET_KEY_INPUT_EVENT)
+ {
+ KeyPress kp(event.KeyInput);
+ if (kp == EscapeKey || kp == getKeySetting("keymap_inventory")
+ || event.KeyInput.Key==KEY_RETURN)
+ {
+ gui::IGUIElement *focused = Environment->getFocus();
+ if (focused && isMyChild(focused) &&
+ (focused->getType() == gui::EGUIET_LIST_BOX ||
+ focused->getType() == gui::EGUIET_CHECK_BOX)) {
+ OnEvent(event);
+ return true;
+ }
+ }
+ }
+ // Mouse wheel events: send to hovered element instead of focused
+ if(event.EventType==EET_MOUSE_INPUT_EVENT
+ && event.MouseInput.Event == EMIE_MOUSE_WHEEL)
+ {
+ s32 x = event.MouseInput.X;
+ s32 y = event.MouseInput.Y;
+ gui::IGUIElement *hovered =
+ Environment->getRootGUIElement()->getElementFromPoint(
+ core::position2d<s32>(x, y));
+ if (hovered && isMyChild(hovered)) {
+ hovered->OnEvent(event);
+ return true;
+ }
+ }
+ return false;
+}
+
bool GUIFormSpecMenu::OnEvent(const SEvent& event)
{
if(event.EventType==EET_KEY_INPUT_EVENT)
s.send = true;
acceptInput();
s.send = false;
- // Restore focus to the full form
- Environment->setFocus(this);
return true;
}
}
return true;
}else{
s.send = false;
- // Restore focus to the full form
- Environment->setFocus(this);
return true;
}
}
s.send = true;
acceptInput();
s.send=false;
- // Restore focus to the full form
- Environment->setFocus(this);
}
}
return true;