Add srollbar formspec element

master
sapier 2014-06-19 18:17:35 +02:00
parent 903d343b08
commit 65b8b524c0
5 changed files with 222 additions and 50 deletions

View File

@ -400,6 +400,17 @@ function core.explode_textlist_event(evt)
return {type="INV", index=0} return {type="INV", index=0}
end end
--------------------------------------------------------------------------------
function core.explode_scrollbar_event(evt)
local retval = core.explode_textlist_event(evt)
retval.value = retval.index
retval.index = nil
return retval
end
--------------------------------------------------------------------------------
function core.pos_to_string(pos) function core.pos_to_string(pos)
return "(" .. pos.x .. "," .. pos.y .. "," .. pos.z .. ")" return "(" .. pos.x .. "," .. pos.y .. "," .. pos.z .. ")"
end end

View File

@ -75,29 +75,38 @@ local function showconfirm_reset(tabview)
new_dlg:show() new_dlg:show()
end end
local function gui_scale_index() local function gui_scale_to_scrollbar()
local current_value = tonumber(core.setting_get("gui_scaling")) local current_value = tonumber(core.setting_get("gui_scaling"))
if (current_value == nil) then if (current_value == nil) or current_value < 0.25 then
return 0 return 0
elseif current_value <= 0.5 then
return 1
elseif current_value <= 0.625 then
return 2
elseif current_value <= 0.75 then
return 3
elseif current_value <= 0.875 then
return 4
elseif current_value <= 1.0 then
return 5
elseif current_value <= 1.25 then
return 6
elseif current_value <= 1.5 then
return 7
else
return 8
end end
if current_value <= 1.25 then
return ((current_value - 0.25)/ 1.0) * 700
end
if current_value <= 6 then
return ((current_value -1.25) * 100) + 700
end
return 1000
end
local function scrollbar_to_gui_scale(value)
value = tonumber(value)
if (value <= 700) then
return ((value / 700) * 1.0) + 0.25
end
if (value <=1000) then
return ((value - 700) / 100) + 1.25
end
return 1
end end
local function formspec(tabview, name, tabdata) local function formspec(tabview, name, tabdata)
@ -138,8 +147,11 @@ local function formspec(tabview, name, tabdata)
tab_string = tab_string .. tab_string = tab_string ..
"box[0.75,4.25;3.25,1.25;#999999]" .. "box[0.75,4.25;3.25,1.25;#999999]" ..
"label[1,4.25;" .. fgettext("GUI scale factor") .. "]" .. "label[1,4.25;" .. fgettext("GUI scale factor") .. "]" ..
"dropdown[1,4.75;3.0;dd_gui_scaling;0.5,0.625,0.75,0.875,1.0,1.25,1.5,2.0;" "scrollbar[1,4.75;2.75,0.4;sb_gui_scaling;horizontal;" ..
.. gui_scale_index() .. "]" gui_scale_to_scrollbar() .. "]" ..
"tooltip[sb_gui_scaling;" ..
fgettext("Scaling factor applied to menu elements: ") ..
dump(core.setting_get("gui_scaling")) .. "]"
if ANDROID then if ANDROID then
tab_string = tab_string .. tab_string = tab_string ..
@ -257,6 +269,16 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
core.show_keys_menu() core.show_keys_menu()
return true return true
end end
if fields["sb_gui_scaling"] then
local event = core.explode_scrollbar_event(fields["sb_gui_scaling"])
if event.type == "CHG" then
local tosave = string.format("%.2f",scrollbar_to_gui_scale(event.value))
core.setting_set("gui_scaling",tosave)
return true
end
end
if fields["cb_touchscreen_target"] then if fields["cb_touchscreen_target"] then
core.setting_set("touchtarget", fields["cb_touchscreen_target"]) core.setting_set("touchtarget", fields["cb_touchscreen_target"])
return true return true
@ -272,10 +294,6 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
core.setting_set("touchscreen_threshold",fields["dd_touchthreshold"]) core.setting_set("touchscreen_threshold",fields["dd_touchthreshold"])
ddhandled = true ddhandled = true
end end
if fields["dd_gui_scaling"] then
core.setting_set("gui_scaling",fields["dd_gui_scaling"])
ddhandled = true
end
return ddhandled return ddhandled
end end

View File

@ -1061,6 +1061,9 @@ box[<X>,<Y>;<W>,<H>;<color>]
dropdown[<X>,<Y>;<W>;<name>;<item 1>,<item 2>, ...,<item n>;<selected idx>] dropdown[<X>,<Y>;<W>;<name>;<item 1>,<item 2>, ...,<item n>;<selected idx>]
^ show a dropdown field ^ show a dropdown field
^ IMPORTANT NOTE: There are two different operation modes:
^ 1) handle directly on change (only changed dropdown is submitted)
^ 2) read the value on pressing a button (all dropdown values are available)
^ x and y position of dropdown ^ x and y position of dropdown
^ width of dropdown ^ width of dropdown
^ fieldname data is transfered to Lua ^ fieldname data is transfered to Lua
@ -1075,6 +1078,18 @@ checkbox[<X>,<Y>;<name>;<label>;<selected>;<tooltip>]
^ selected (optional) true/false ^ selected (optional) true/false
^ tooltip (optional) ^ tooltip (optional)
scrollbar[<X>,<Y>;<W>,<H>;<orientation>;<name>;<value>]
^ show a scrollbar
^ there are two ways to use it:
^ 1) handle the changed event (only changed scrollbar is available)
^ 2) read the value on pressing a button (all scrollbars are available)
^ x and y position of trackbar
^ width and height
^ orientation vertical/horizontal
^ fieldname data is transfered to lua
^ value this trackbar is set to (0-1000)
^ see also minetest.explode_scrollbar_event (main menu: engine.explode_scrollbar_event)
table[<X>,<Y>;<W>,<H>;<name>;<cell 1>,<cell 2>,...,<cell n>;<selected idx>] table[<X>,<Y>;<W>,<H>;<name>;<cell 1>,<cell 2>,...,<cell n>;<selected idx>]
^ show scrollable table using options defined by the previous tableoptions[] ^ show scrollable table using options defined by the previous tableoptions[]
^ displays cells as defined by the previous tablecolumns[] ^ displays cells as defined by the previous tablecolumns[]
@ -1472,6 +1487,9 @@ minetest.explode_table_event(string) -> table
minetest.explode_textlist_event(string) -> table minetest.explode_textlist_event(string) -> table
^ returns e.g. {type="CHG", index=1} ^ returns e.g. {type="CHG", index=1}
^ type: "INV" (no row selected), "CHG" (selected) or "DCL" (double-click) ^ type: "INV" (no row selected), "CHG" (selected) or "DCL" (double-click)
minetest.explode_scrollbar_event(string) -> table
^ returns e.g. {type="CHG", value=500}
^ type: "INV" (something failed), "CHG" (has been changed) or "VAL" (not changed)
Item handling: Item handling:
minetest.inventorycube(img1, img2, img3) minetest.inventorycube(img1, img2, img3)

View File

@ -453,6 +453,7 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data,std::string element)
); );
spec.ftype = f_CheckBox; spec.ftype = f_CheckBox;
gui::IGUICheckBox* e = Environment->addCheckBox(fselected, rect, this, gui::IGUICheckBox* e = Environment->addCheckBox(fselected, rect, this,
spec.fid, spec.flabel.c_str()); spec.fid, spec.flabel.c_str());
@ -467,6 +468,94 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data,std::string element)
errorstream<< "Invalid checkbox element(" << parts.size() << "): '" << element << "'" << std::endl; errorstream<< "Invalid checkbox element(" << parts.size() << "): '" << element << "'" << std::endl;
} }
void GUIFormSpecMenu::parseScrollBar(parserData* data, std::string element)
{
std::vector<std::string> parts = split(element,';');
if (parts.size() >= 5) {
std::vector<std::string> v_pos = split(parts[0],',');
std::vector<std::string> v_dim = split(parts[1],',');
std::string name = parts[2];
std::string value = parts[4];
MY_CHECKPOS("scrollbar",0);
v2s32 pos = padding;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
if (v_dim.size() != 2) {
errorstream<< "Invalid size for element " << "scrollbar"
<< "specified: \"" << parts[1] << "\"" << std::endl;
return;
}
v2s32 dim;
dim.X = stof(v_dim[0]) * (float) spacing.X;
dim.Y = stof(v_dim[1]) * (float) spacing.Y;
core::rect<s32> rect =
core::rect<s32>(pos.X, pos.Y, pos.X + dim.X, pos.Y + dim.Y);
FieldSpec spec(
narrow_to_wide(name.c_str()),
L"",
L"",
258+m_fields.size()
);
bool is_horizontal = true;
if (parts[2] == "vertical")
is_horizontal = false;
spec.ftype = f_ScrollBar;
spec.send = true;
gui::IGUIScrollBar* e =
Environment->addScrollBar(is_horizontal,rect,this,spec.fid);
e->setMax(1000);
e->setMin(0);
e->setPos(stoi(parts[4]));
e->setSmallStep(10);
e->setLargeStep(100);
if (!m_lock) {
core::rect<s32> relative_rect = e->getRelativePosition();
if (!is_horizontal) {
s32 original_width = relative_rect.getWidth();
s32 width = (original_width/(2.0/3.0))
* porting::getDisplayDensity()
* g_settings->getFloat("gui_scaling");
e->setRelativePosition(core::rect<s32>(
relative_rect.UpperLeftCorner.X,
relative_rect.UpperLeftCorner.Y,
relative_rect.LowerRightCorner.X + (width - original_width),
relative_rect.LowerRightCorner.Y
));
}
else {
s32 original_height = relative_rect.getHeight();
s32 height = (original_height/(2.0/3.0))
* porting::getDisplayDensity()
* g_settings->getFloat("gui_scaling");
e->setRelativePosition(core::rect<s32>(
relative_rect.UpperLeftCorner.X,
relative_rect.UpperLeftCorner.Y,
relative_rect.LowerRightCorner.X,
relative_rect.LowerRightCorner.Y + (height - original_height)
));
}
}
m_scrollbars.push_back(std::pair<FieldSpec,gui::IGUIScrollBar*>(spec,e));
m_fields.push_back(spec);
return;
}
errorstream<< "Invalid scrollbar element(" << parts.size() << "): '" << element << "'" << std::endl;
}
void GUIFormSpecMenu::parseImage(parserData* data,std::string element) void GUIFormSpecMenu::parseImage(parserData* data,std::string element)
{ {
std::vector<std::string> parts = split(element,';'); std::vector<std::string> parts = split(element,';');
@ -1731,6 +1820,11 @@ void GUIFormSpecMenu::parseElement(parserData* data, std::string element)
return; return;
} }
if (type == "scrollbar") {
parseScrollBar(data, description);
return;
}
// Ignore others // Ignore others
infostream infostream
<< "Unknown DrawSpec: type="<<type<<", data=\""<<description<<"\"" << "Unknown DrawSpec: type="<<type<<", data=\""<<description<<"\""
@ -1798,6 +1892,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
m_itemimages.clear(); m_itemimages.clear();
m_tables.clear(); m_tables.clear();
m_checkboxes.clear(); m_checkboxes.clear();
m_scrollbars.clear();
m_fields.clear(); m_fields.clear();
m_boxes.clear(); m_boxes.clear();
m_tooltips.clear(); m_tooltips.clear();
@ -2513,6 +2608,24 @@ void GUIFormSpecMenu::acceptInput(FormspecQuitMode quitmode=quit_mode_no)
fields[name] = "false"; fields[name] = "false";
} }
} }
else if (s.ftype == f_ScrollBar) {
// no dynamic cast possible due to some distributions shipped
// without rtti support in irrlicht
IGUIElement * element = getElementFromId(s.fid);
gui::IGUIScrollBar *e = NULL;
if ((element) && (element->getType() == gui::EGUIET_SCROLL_BAR)) {
e = static_cast<gui::IGUIScrollBar*>(element);
}
if (e != 0) {
std::stringstream os;
os << e->getPos();
if (s.fdefault == L"Changed")
fields[name] = "CHG:" + os.str();
else
fields[name] = "VAL:" + os.str();
}
}
else else
{ {
IGUIElement* e = getElementFromId(s.fid); IGUIElement* e = getElementFromId(s.fid);
@ -3120,7 +3233,8 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
} }
if((event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED) || if((event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED) ||
(event.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED) || (event.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED) ||
(event.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED)) { (event.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED) ||
(event.GUIEvent.EventType == gui::EGET_SCROLL_BAR_CHANGED)) {
unsigned int btn_id = event.GUIEvent.Caller->getID(); unsigned int btn_id = event.GUIEvent.Caller->getID();
if (btn_id == 257) { if (btn_id == 257) {
@ -3157,7 +3271,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
return true; return true;
} }
} }
if ((s.ftype == f_DropDown) && else if ((s.ftype == f_DropDown) &&
(s.fid == event.GUIEvent.Caller->getID())) { (s.fid == event.GUIEvent.Caller->getID())) {
// only send the changed dropdown // only send the changed dropdown
for(u32 i=0; i<m_fields.size(); i++) { for(u32 i=0; i<m_fields.size(); i++) {
@ -3179,8 +3293,16 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
} }
return true; return true;
} }
else if ((s.ftype == f_ScrollBar) &&
(s.fid == event.GUIEvent.Caller->getID()))
{
s.fdefault = L"Changed";
acceptInput(quit_mode_no);
s.fdefault = L"";
} }
} }
}
if(event.GUIEvent.EventType == gui::EGET_EDITBOX_ENTER) { if(event.GUIEvent.EventType == gui::EGET_EDITBOX_ENTER) {
if(event.GUIEvent.Caller->getID() > 257) { if(event.GUIEvent.Caller->getID() > 257) {

View File

@ -40,6 +40,7 @@ typedef enum {
f_TabHeader, f_TabHeader,
f_CheckBox, f_CheckBox,
f_DropDown, f_DropDown,
f_ScrollBar,
f_Unknown f_Unknown
} FormspecFieldType; } FormspecFieldType;
@ -306,6 +307,7 @@ protected:
std::vector<std::pair<FieldSpec,GUITable*> > m_tables; std::vector<std::pair<FieldSpec,GUITable*> > m_tables;
std::vector<std::pair<FieldSpec,gui::IGUICheckBox*> > m_checkboxes; std::vector<std::pair<FieldSpec,gui::IGUICheckBox*> > m_checkboxes;
std::map<std::wstring, TooltipSpec> m_tooltips; std::map<std::wstring, TooltipSpec> m_tooltips;
std::vector<std::pair<FieldSpec,gui::IGUIScrollBar*> > m_scrollbars;
ItemSpec *m_selected_item; ItemSpec *m_selected_item;
u32 m_selected_amount; u32 m_selected_amount;
@ -397,6 +399,7 @@ private:
void parseListColors(parserData* data,std::string element); void parseListColors(parserData* data,std::string element);
void parseTooltip(parserData* data,std::string element); void parseTooltip(parserData* data,std::string element);
bool parseVersionDirect(std::string data); bool parseVersionDirect(std::string data);
void parseScrollBar(parserData* data, std::string element);
/** /**
* check if event is part of a double click * check if event is part of a double click