Skip to content

Commit 65b8b52

Browse files
sapiersapier
sapier
authored and
sapier
committedJul 16, 2014
Add srollbar formspec element
1 parent 903d343 commit 65b8b52

File tree

5 files changed

+222
-50
lines changed

5 files changed

+222
-50
lines changed
 

‎builtin/common/misc_helpers.lua

+34-23
Original file line numberDiff line numberDiff line change
@@ -140,58 +140,58 @@ end
140140
--------------------------------------------------------------------------------
141141
function get_last_folder(text,count)
142142
local parts = text:split(DIR_DELIM)
143-
143+
144144
if count == nil then
145145
return parts[#parts]
146146
end
147-
147+
148148
local retval = ""
149149
for i=1,count,1 do
150150
retval = retval .. parts[#parts - (count-i)] .. DIR_DELIM
151151
end
152-
152+
153153
return retval
154154
end
155155

156156
--------------------------------------------------------------------------------
157157
function cleanup_path(temppath)
158-
158+
159159
local parts = temppath:split("-")
160-
temppath = ""
160+
temppath = ""
161161
for i=1,#parts,1 do
162162
if temppath ~= "" then
163163
temppath = temppath .. "_"
164164
end
165165
temppath = temppath .. parts[i]
166166
end
167-
167+
168168
parts = temppath:split(".")
169-
temppath = ""
169+
temppath = ""
170170
for i=1,#parts,1 do
171171
if temppath ~= "" then
172172
temppath = temppath .. "_"
173173
end
174174
temppath = temppath .. parts[i]
175175
end
176-
176+
177177
parts = temppath:split("'")
178-
temppath = ""
178+
temppath = ""
179179
for i=1,#parts,1 do
180180
if temppath ~= "" then
181181
temppath = temppath .. ""
182182
end
183183
temppath = temppath .. parts[i]
184184
end
185-
185+
186186
parts = temppath:split(" ")
187-
temppath = ""
187+
temppath = ""
188188
for i=1,#parts,1 do
189189
if temppath ~= "" then
190190
temppath = temppath
191191
end
192192
temppath = temppath .. parts[i]
193193
end
194-
194+
195195
return temppath
196196
end
197197

@@ -211,7 +211,7 @@ function core.splittext(text,charlimit)
211211
local retval = {}
212212

213213
local current_idx = 1
214-
214+
215215
local start,stop = string.find(text," ",current_idx)
216216
local nl_start,nl_stop = string.find(text,"\n",current_idx)
217217
local gotnewline = false
@@ -226,30 +226,30 @@ function core.splittext(text,charlimit)
226226
table.insert(retval,last_line)
227227
last_line = ""
228228
end
229-
229+
230230
if last_line ~= "" then
231231
last_line = last_line .. " "
232232
end
233-
233+
234234
last_line = last_line .. string.sub(text,current_idx,stop -1)
235-
235+
236236
if gotnewline then
237237
table.insert(retval,last_line)
238238
last_line = ""
239239
gotnewline = false
240240
end
241241
current_idx = stop+1
242-
242+
243243
start,stop = string.find(text," ",current_idx)
244244
nl_start,nl_stop = string.find(text,"\n",current_idx)
245-
245+
246246
if nl_start ~= nil and (start == nil or nl_start < start) then
247247
start = nl_start
248248
stop = nl_stop
249249
gotnewline = true
250250
end
251251
end
252-
252+
253253
--add last part of text
254254
if string.len(last_line) + (string.len(text) - current_idx) > charlimit then
255255
table.insert(retval,last_line)
@@ -258,7 +258,7 @@ function core.splittext(text,charlimit)
258258
last_line = last_line .. " " .. string.sub(text,current_idx)
259259
table.insert(retval,last_line)
260260
end
261-
261+
262262
return retval
263263
end
264264

@@ -400,6 +400,17 @@ function core.explode_textlist_event(evt)
400400
return {type="INV", index=0}
401401
end
402402

403+
--------------------------------------------------------------------------------
404+
function core.explode_scrollbar_event(evt)
405+
local retval = core.explode_textlist_event(evt)
406+
407+
retval.value = retval.index
408+
retval.index = nil
409+
410+
return retval
411+
end
412+
413+
--------------------------------------------------------------------------------
403414
function core.pos_to_string(pos)
404415
return "(" .. pos.x .. "," .. pos.y .. "," .. pos.z .. ")"
405416
end
@@ -410,14 +421,14 @@ end
410421
if INIT == "mainmenu" then
411422
function core.get_game(index)
412423
local games = game.get_games()
413-
424+
414425
if index > 0 and index <= #games then
415426
return games[index]
416427
end
417-
428+
418429
return nil
419430
end
420-
431+
421432
function fgettext(text, ...)
422433
text = core.gettext(text)
423434
local arg = {n=select('#', ...), ...}

‎builtin/mainmenu/tab_settings.lua

+42-24
Original file line numberDiff line numberDiff line change
@@ -75,29 +75,38 @@ local function showconfirm_reset(tabview)
7575
new_dlg:show()
7676
end
7777

78-
local function gui_scale_index()
78+
local function gui_scale_to_scrollbar()
7979

8080
local current_value = tonumber(core.setting_get("gui_scaling"))
8181

82-
if (current_value == nil) then
82+
if (current_value == nil) or current_value < 0.25 then
8383
return 0
84-
elseif current_value <= 0.5 then
85-
return 1
86-
elseif current_value <= 0.625 then
87-
return 2
88-
elseif current_value <= 0.75 then
89-
return 3
90-
elseif current_value <= 0.875 then
91-
return 4
92-
elseif current_value <= 1.0 then
93-
return 5
94-
elseif current_value <= 1.25 then
95-
return 6
96-
elseif current_value <= 1.5 then
97-
return 7
98-
else
99-
return 8
10084
end
85+
86+
if current_value <= 1.25 then
87+
return ((current_value - 0.25)/ 1.0) * 700
88+
end
89+
90+
if current_value <= 6 then
91+
return ((current_value -1.25) * 100) + 700
92+
end
93+
94+
return 1000
95+
end
96+
97+
local function scrollbar_to_gui_scale(value)
98+
99+
value = tonumber(value)
100+
101+
if (value <= 700) then
102+
return ((value / 700) * 1.0) + 0.25
103+
end
104+
105+
if (value <=1000) then
106+
return ((value - 700) / 100) + 1.25
107+
end
108+
109+
return 1
101110
end
102111

103112
local function formspec(tabview, name, tabdata)
@@ -138,8 +147,11 @@ local function formspec(tabview, name, tabdata)
138147
tab_string = tab_string ..
139148
"box[0.75,4.25;3.25,1.25;#999999]" ..
140149
"label[1,4.25;" .. fgettext("GUI scale factor") .. "]" ..
141-
"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;"
142-
.. gui_scale_index() .. "]"
150+
"scrollbar[1,4.75;2.75,0.4;sb_gui_scaling;horizontal;" ..
151+
gui_scale_to_scrollbar() .. "]" ..
152+
"tooltip[sb_gui_scaling;" ..
153+
fgettext("Scaling factor applied to menu elements: ") ..
154+
dump(core.setting_get("gui_scaling")) .. "]"
143155

144156
if ANDROID then
145157
tab_string = tab_string ..
@@ -257,6 +269,16 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
257269
core.show_keys_menu()
258270
return true
259271
end
272+
273+
if fields["sb_gui_scaling"] then
274+
local event = core.explode_scrollbar_event(fields["sb_gui_scaling"])
275+
276+
if event.type == "CHG" then
277+
local tosave = string.format("%.2f",scrollbar_to_gui_scale(event.value))
278+
core.setting_set("gui_scaling",tosave)
279+
return true
280+
end
281+
end
260282
if fields["cb_touchscreen_target"] then
261283
core.setting_set("touchtarget", fields["cb_touchscreen_target"])
262284
return true
@@ -272,10 +294,6 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
272294
core.setting_set("touchscreen_threshold",fields["dd_touchthreshold"])
273295
ddhandled = true
274296
end
275-
if fields["dd_gui_scaling"] then
276-
core.setting_set("gui_scaling",fields["dd_gui_scaling"])
277-
ddhandled = true
278-
end
279297

280298
return ddhandled
281299
end

‎doc/lua_api.txt

+18
Original file line numberDiff line numberDiff line change
@@ -1061,6 +1061,9 @@ box[<X>,<Y>;<W>,<H>;<color>]
10611061

10621062
dropdown[<X>,<Y>;<W>;<name>;<item 1>,<item 2>, ...,<item n>;<selected idx>]
10631063
^ show a dropdown field
1064+
^ IMPORTANT NOTE: There are two different operation modes:
1065+
^ 1) handle directly on change (only changed dropdown is submitted)
1066+
^ 2) read the value on pressing a button (all dropdown values are available)
10641067
^ x and y position of dropdown
10651068
^ width of dropdown
10661069
^ fieldname data is transfered to Lua
@@ -1075,6 +1078,18 @@ checkbox[<X>,<Y>;<name>;<label>;<selected>;<tooltip>]
10751078
^ selected (optional) true/false
10761079
^ tooltip (optional)
10771080

1081+
scrollbar[<X>,<Y>;<W>,<H>;<orientation>;<name>;<value>]
1082+
^ show a scrollbar
1083+
^ there are two ways to use it:
1084+
^ 1) handle the changed event (only changed scrollbar is available)
1085+
^ 2) read the value on pressing a button (all scrollbars are available)
1086+
^ x and y position of trackbar
1087+
^ width and height
1088+
^ orientation vertical/horizontal
1089+
^ fieldname data is transfered to lua
1090+
^ value this trackbar is set to (0-1000)
1091+
^ see also minetest.explode_scrollbar_event (main menu: engine.explode_scrollbar_event)
1092+
10781093
table[<X>,<Y>;<W>,<H>;<name>;<cell 1>,<cell 2>,...,<cell n>;<selected idx>]
10791094
^ show scrollable table using options defined by the previous tableoptions[]
10801095
^ displays cells as defined by the previous tablecolumns[]
@@ -1472,6 +1487,9 @@ minetest.explode_table_event(string) -> table
14721487
minetest.explode_textlist_event(string) -> table
14731488
^ returns e.g. {type="CHG", index=1}
14741489
^ type: "INV" (no row selected), "CHG" (selected) or "DCL" (double-click)
1490+
minetest.explode_scrollbar_event(string) -> table
1491+
^ returns e.g. {type="CHG", value=500}
1492+
^ type: "INV" (something failed), "CHG" (has been changed) or "VAL" (not changed)
14751493

14761494
Item handling:
14771495
minetest.inventorycube(img1, img2, img3)

‎src/guiFormSpecMenu.cpp

+124-2
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,7 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data,std::string element)
453453
);
454454

455455
spec.ftype = f_CheckBox;
456+
456457
gui::IGUICheckBox* e = Environment->addCheckBox(fselected, rect, this,
457458
spec.fid, spec.flabel.c_str());
458459

@@ -467,6 +468,94 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data,std::string element)
467468
errorstream<< "Invalid checkbox element(" << parts.size() << "): '" << element << "'" << std::endl;
468469
}
469470

471+
void GUIFormSpecMenu::parseScrollBar(parserData* data, std::string element)
472+
{
473+
std::vector<std::string> parts = split(element,';');
474+
475+
if (parts.size() >= 5) {
476+
std::vector<std::string> v_pos = split(parts[0],',');
477+
std::vector<std::string> v_dim = split(parts[1],',');
478+
std::string name = parts[2];
479+
std::string value = parts[4];
480+
481+
MY_CHECKPOS("scrollbar",0);
482+
483+
v2s32 pos = padding;
484+
pos.X += stof(v_pos[0]) * (float) spacing.X;
485+
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
486+
487+
if (v_dim.size() != 2) {
488+
errorstream<< "Invalid size for element " << "scrollbar"
489+
<< "specified: \"" << parts[1] << "\"" << std::endl;
490+
return;
491+
}
492+
493+
v2s32 dim;
494+
dim.X = stof(v_dim[0]) * (float) spacing.X;
495+
dim.Y = stof(v_dim[1]) * (float) spacing.Y;
496+
497+
core::rect<s32> rect =
498+
core::rect<s32>(pos.X, pos.Y, pos.X + dim.X, pos.Y + dim.Y);
499+
500+
FieldSpec spec(
501+
narrow_to_wide(name.c_str()),
502+
L"",
503+
L"",
504+
258+m_fields.size()
505+
);
506+
507+
bool is_horizontal = true;
508+
509+
if (parts[2] == "vertical")
510+
is_horizontal = false;
511+
512+
spec.ftype = f_ScrollBar;
513+
spec.send = true;
514+
gui::IGUIScrollBar* e =
515+
Environment->addScrollBar(is_horizontal,rect,this,spec.fid);
516+
517+
e->setMax(1000);
518+
e->setMin(0);
519+
e->setPos(stoi(parts[4]));
520+
e->setSmallStep(10);
521+
e->setLargeStep(100);
522+
523+
if (!m_lock) {
524+
core::rect<s32> relative_rect = e->getRelativePosition();
525+
526+
if (!is_horizontal) {
527+
s32 original_width = relative_rect.getWidth();
528+
s32 width = (original_width/(2.0/3.0))
529+
* porting::getDisplayDensity()
530+
* g_settings->getFloat("gui_scaling");
531+
e->setRelativePosition(core::rect<s32>(
532+
relative_rect.UpperLeftCorner.X,
533+
relative_rect.UpperLeftCorner.Y,
534+
relative_rect.LowerRightCorner.X + (width - original_width),
535+
relative_rect.LowerRightCorner.Y
536+
));
537+
}
538+
else {
539+
s32 original_height = relative_rect.getHeight();
540+
s32 height = (original_height/(2.0/3.0))
541+
* porting::getDisplayDensity()
542+
* g_settings->getFloat("gui_scaling");
543+
e->setRelativePosition(core::rect<s32>(
544+
relative_rect.UpperLeftCorner.X,
545+
relative_rect.UpperLeftCorner.Y,
546+
relative_rect.LowerRightCorner.X,
547+
relative_rect.LowerRightCorner.Y + (height - original_height)
548+
));
549+
}
550+
}
551+
552+
m_scrollbars.push_back(std::pair<FieldSpec,gui::IGUIScrollBar*>(spec,e));
553+
m_fields.push_back(spec);
554+
return;
555+
}
556+
errorstream<< "Invalid scrollbar element(" << parts.size() << "): '" << element << "'" << std::endl;
557+
}
558+
470559
void GUIFormSpecMenu::parseImage(parserData* data,std::string element)
471560
{
472561
std::vector<std::string> parts = split(element,';');
@@ -1731,6 +1820,11 @@ void GUIFormSpecMenu::parseElement(parserData* data, std::string element)
17311820
return;
17321821
}
17331822

1823+
if (type == "scrollbar") {
1824+
parseScrollBar(data, description);
1825+
return;
1826+
}
1827+
17341828
// Ignore others
17351829
infostream
17361830
<< "Unknown DrawSpec: type="<<type<<", data=\""<<description<<"\""
@@ -1798,6 +1892,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
17981892
m_itemimages.clear();
17991893
m_tables.clear();
18001894
m_checkboxes.clear();
1895+
m_scrollbars.clear();
18011896
m_fields.clear();
18021897
m_boxes.clear();
18031898
m_tooltips.clear();
@@ -2513,6 +2608,24 @@ void GUIFormSpecMenu::acceptInput(FormspecQuitMode quitmode=quit_mode_no)
25132608
fields[name] = "false";
25142609
}
25152610
}
2611+
else if (s.ftype == f_ScrollBar) {
2612+
// no dynamic cast possible due to some distributions shipped
2613+
// without rtti support in irrlicht
2614+
IGUIElement * element = getElementFromId(s.fid);
2615+
gui::IGUIScrollBar *e = NULL;
2616+
if ((element) && (element->getType() == gui::EGUIET_SCROLL_BAR)) {
2617+
e = static_cast<gui::IGUIScrollBar*>(element);
2618+
}
2619+
2620+
if (e != 0) {
2621+
std::stringstream os;
2622+
os << e->getPos();
2623+
if (s.fdefault == L"Changed")
2624+
fields[name] = "CHG:" + os.str();
2625+
else
2626+
fields[name] = "VAL:" + os.str();
2627+
}
2628+
}
25162629
else
25172630
{
25182631
IGUIElement* e = getElementFromId(s.fid);
@@ -3120,7 +3233,8 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
31203233
}
31213234
if((event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED) ||
31223235
(event.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED) ||
3123-
(event.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED)) {
3236+
(event.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED) ||
3237+
(event.GUIEvent.EventType == gui::EGET_SCROLL_BAR_CHANGED)) {
31243238
unsigned int btn_id = event.GUIEvent.Caller->getID();
31253239

31263240
if (btn_id == 257) {
@@ -3157,7 +3271,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
31573271
return true;
31583272
}
31593273
}
3160-
if ((s.ftype == f_DropDown) &&
3274+
else if ((s.ftype == f_DropDown) &&
31613275
(s.fid == event.GUIEvent.Caller->getID())) {
31623276
// only send the changed dropdown
31633277
for(u32 i=0; i<m_fields.size(); i++) {
@@ -3179,8 +3293,16 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
31793293
}
31803294
return true;
31813295
}
3296+
else if ((s.ftype == f_ScrollBar) &&
3297+
(s.fid == event.GUIEvent.Caller->getID()))
3298+
{
3299+
s.fdefault = L"Changed";
3300+
acceptInput(quit_mode_no);
3301+
s.fdefault = L"";
3302+
}
31823303
}
31833304
}
3305+
31843306
if(event.GUIEvent.EventType == gui::EGET_EDITBOX_ENTER) {
31853307
if(event.GUIEvent.Caller->getID() > 257) {
31863308

‎src/guiFormSpecMenu.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ typedef enum {
4040
f_TabHeader,
4141
f_CheckBox,
4242
f_DropDown,
43+
f_ScrollBar,
4344
f_Unknown
4445
} FormspecFieldType;
4546

@@ -306,7 +307,8 @@ class GUIFormSpecMenu : public GUIModalMenu
306307
std::vector<std::pair<FieldSpec,GUITable*> > m_tables;
307308
std::vector<std::pair<FieldSpec,gui::IGUICheckBox*> > m_checkboxes;
308309
std::map<std::wstring, TooltipSpec> m_tooltips;
309-
310+
std::vector<std::pair<FieldSpec,gui::IGUIScrollBar*> > m_scrollbars;
311+
310312
ItemSpec *m_selected_item;
311313
u32 m_selected_amount;
312314
bool m_selected_dragging;
@@ -397,6 +399,7 @@ class GUIFormSpecMenu : public GUIModalMenu
397399
void parseListColors(parserData* data,std::string element);
398400
void parseTooltip(parserData* data,std::string element);
399401
bool parseVersionDirect(std::string data);
402+
void parseScrollBar(parserData* data, std::string element);
400403

401404
/**
402405
* check if event is part of a double click

0 commit comments

Comments
 (0)
Please sign in to comment.