diff options
author | sapier <Sapier at GMX dot net> | 2014-06-19 18:17:35 +0200 |
---|---|---|
committer | sapier <Sapier at GMX dot net> | 2014-07-16 15:02:56 +0200 |
commit | 65b8b524c02df853163fc1284a00a684a046d67c (patch) | |
tree | 2d5262f153efcd5740096edd690472a2b4eaa4a3 | |
parent | 903d343b08df17c88eafdd698af5b9f73ef6e389 (diff) | |
download | minetest-65b8b524c02df853163fc1284a00a684a046d67c.tar.gz minetest-65b8b524c02df853163fc1284a00a684a046d67c.tar.bz2 minetest-65b8b524c02df853163fc1284a00a684a046d67c.zip |
Add srollbar formspec element
-rw-r--r-- | builtin/common/misc_helpers.lua | 57 | ||||
-rw-r--r-- | builtin/mainmenu/tab_settings.lua | 66 | ||||
-rw-r--r-- | doc/lua_api.txt | 18 | ||||
-rw-r--r-- | src/guiFormSpecMenu.cpp | 126 | ||||
-rw-r--r-- | src/guiFormSpecMenu.h | 5 |
5 files changed, 222 insertions, 50 deletions
diff --git a/builtin/common/misc_helpers.lua b/builtin/common/misc_helpers.lua index e53ca373f..f57efc138 100644 --- a/builtin/common/misc_helpers.lua +++ b/builtin/common/misc_helpers.lua @@ -140,58 +140,58 @@ end -------------------------------------------------------------------------------- function get_last_folder(text,count) local parts = text:split(DIR_DELIM) - + if count == nil then return parts[#parts] end - + local retval = "" for i=1,count,1 do retval = retval .. parts[#parts - (count-i)] .. DIR_DELIM end - + return retval end -------------------------------------------------------------------------------- function cleanup_path(temppath) - + local parts = temppath:split("-") - temppath = "" + temppath = "" for i=1,#parts,1 do if temppath ~= "" then temppath = temppath .. "_" end temppath = temppath .. parts[i] end - + parts = temppath:split(".") - temppath = "" + temppath = "" for i=1,#parts,1 do if temppath ~= "" then temppath = temppath .. "_" end temppath = temppath .. parts[i] end - + parts = temppath:split("'") - temppath = "" + temppath = "" for i=1,#parts,1 do if temppath ~= "" then temppath = temppath .. "" end temppath = temppath .. parts[i] end - + parts = temppath:split(" ") - temppath = "" + temppath = "" for i=1,#parts,1 do if temppath ~= "" then temppath = temppath end temppath = temppath .. parts[i] end - + return temppath end @@ -211,7 +211,7 @@ function core.splittext(text,charlimit) local retval = {} local current_idx = 1 - + local start,stop = string.find(text," ",current_idx) local nl_start,nl_stop = string.find(text,"\n",current_idx) local gotnewline = false @@ -226,30 +226,30 @@ function core.splittext(text,charlimit) table.insert(retval,last_line) last_line = "" end - + if last_line ~= "" then last_line = last_line .. " " end - + last_line = last_line .. string.sub(text,current_idx,stop -1) - + if gotnewline then table.insert(retval,last_line) last_line = "" gotnewline = false end current_idx = stop+1 - + start,stop = string.find(text," ",current_idx) nl_start,nl_stop = string.find(text,"\n",current_idx) - + if nl_start ~= nil and (start == nil or nl_start < start) then start = nl_start stop = nl_stop gotnewline = true end end - + --add last part of text if string.len(last_line) + (string.len(text) - current_idx) > charlimit then table.insert(retval,last_line) @@ -258,7 +258,7 @@ function core.splittext(text,charlimit) last_line = last_line .. " " .. string.sub(text,current_idx) table.insert(retval,last_line) end - + return retval end @@ -400,6 +400,17 @@ function core.explode_textlist_event(evt) return {type="INV", index=0} 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) return "(" .. pos.x .. "," .. pos.y .. "," .. pos.z .. ")" end @@ -410,14 +421,14 @@ end if INIT == "mainmenu" then function core.get_game(index) local games = game.get_games() - + if index > 0 and index <= #games then return games[index] end - + return nil end - + function fgettext(text, ...) text = core.gettext(text) local arg = {n=select('#', ...), ...} diff --git a/builtin/mainmenu/tab_settings.lua b/builtin/mainmenu/tab_settings.lua index dec28a961..2311978e0 100644 --- a/builtin/mainmenu/tab_settings.lua +++ b/builtin/mainmenu/tab_settings.lua @@ -75,29 +75,38 @@ local function showconfirm_reset(tabview) new_dlg:show() end -local function gui_scale_index() +local function gui_scale_to_scrollbar() 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 - 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 + + 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 local function formspec(tabview, name, tabdata) @@ -138,8 +147,11 @@ local function formspec(tabview, name, tabdata) tab_string = tab_string .. "box[0.75,4.25;3.25,1.25;#999999]" .. "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;" - .. gui_scale_index() .. "]" + "scrollbar[1,4.75;2.75,0.4;sb_gui_scaling;horizontal;" .. + gui_scale_to_scrollbar() .. "]" .. + "tooltip[sb_gui_scaling;" .. + fgettext("Scaling factor applied to menu elements: ") .. + dump(core.setting_get("gui_scaling")) .. "]" if ANDROID then tab_string = tab_string .. @@ -257,6 +269,16 @@ local function handle_settings_buttons(this, fields, tabname, tabdata) core.show_keys_menu() return true 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 core.setting_set("touchtarget", fields["cb_touchscreen_target"]) return true @@ -272,10 +294,6 @@ local function handle_settings_buttons(this, fields, tabname, tabdata) core.setting_set("touchscreen_threshold",fields["dd_touchthreshold"]) ddhandled = true end - if fields["dd_gui_scaling"] then - core.setting_set("gui_scaling",fields["dd_gui_scaling"]) - ddhandled = true - end return ddhandled end diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 81cdb3258..28509a267 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1061,6 +1061,9 @@ box[<X>,<Y>;<W>,<H>;<color>] dropdown[<X>,<Y>;<W>;<name>;<item 1>,<item 2>, ...,<item n>;<selected idx>] ^ 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 ^ width of dropdown ^ fieldname data is transfered to Lua @@ -1075,6 +1078,18 @@ checkbox[<X>,<Y>;<name>;<label>;<selected>;<tooltip>] ^ selected (optional) true/false ^ 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>] ^ show scrollable table using options defined by the previous tableoptions[] ^ displays cells as defined by the previous tablecolumns[] @@ -1472,6 +1487,9 @@ minetest.explode_table_event(string) -> table minetest.explode_textlist_event(string) -> table ^ returns e.g. {type="CHG", index=1} ^ 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: minetest.inventorycube(img1, img2, img3) diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index 7ba3305bc..910a0a6b7 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -453,6 +453,7 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data,std::string element) ); spec.ftype = f_CheckBox; + gui::IGUICheckBox* e = Environment->addCheckBox(fselected, rect, this, 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; } +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) { std::vector<std::string> parts = split(element,';'); @@ -1731,6 +1820,11 @@ void GUIFormSpecMenu::parseElement(parserData* data, std::string element) return; } + if (type == "scrollbar") { + parseScrollBar(data, description); + return; + } + // Ignore others infostream << "Unknown DrawSpec: type="<<type<<", data=\""<<description<<"\"" @@ -1798,6 +1892,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) m_itemimages.clear(); m_tables.clear(); m_checkboxes.clear(); + m_scrollbars.clear(); m_fields.clear(); m_boxes.clear(); m_tooltips.clear(); @@ -2513,6 +2608,24 @@ void GUIFormSpecMenu::acceptInput(FormspecQuitMode quitmode=quit_mode_no) 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 { IGUIElement* e = getElementFromId(s.fid); @@ -3120,7 +3233,8 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) } if((event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED) || (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(); if (btn_id == 257) { @@ -3157,7 +3271,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) return true; } } - if ((s.ftype == f_DropDown) && + else if ((s.ftype == f_DropDown) && (s.fid == event.GUIEvent.Caller->getID())) { // only send the changed dropdown for(u32 i=0; i<m_fields.size(); i++) { @@ -3179,8 +3293,16 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) } 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.Caller->getID() > 257) { diff --git a/src/guiFormSpecMenu.h b/src/guiFormSpecMenu.h index 72a188bc5..15bc628d1 100644 --- a/src/guiFormSpecMenu.h +++ b/src/guiFormSpecMenu.h @@ -40,6 +40,7 @@ typedef enum { f_TabHeader, f_CheckBox, f_DropDown, + f_ScrollBar, f_Unknown } FormspecFieldType; @@ -306,7 +307,8 @@ protected: std::vector<std::pair<FieldSpec,GUITable*> > m_tables; std::vector<std::pair<FieldSpec,gui::IGUICheckBox*> > m_checkboxes; std::map<std::wstring, TooltipSpec> m_tooltips; - + std::vector<std::pair<FieldSpec,gui::IGUIScrollBar*> > m_scrollbars; + ItemSpec *m_selected_item; u32 m_selected_amount; bool m_selected_dragging; @@ -397,6 +399,7 @@ private: void parseListColors(parserData* data,std::string element); void parseTooltip(parserData* data,std::string element); bool parseVersionDirect(std::string data); + void parseScrollBar(parserData* data, std::string element); /** * check if event is part of a double click |