Skip to content

Commit 8966c16

Browse files
kahrlShadowNinja
authored andcommittedJan 13, 2014
Add formspec table
1 parent 2b1eff7 commit 8966c16

13 files changed

+1798
-246
lines changed
 

‎builtin/gamemgr.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ end
3131
--------------------------------------------------------------------------------
3232
function gamemgr.handle_games_buttons(fields)
3333
if fields["gamelist"] ~= nil then
34-
local event = explode_textlist_event(fields["gamelist"])
34+
local event = engine.explode_textlist_event(fields["gamelist"])
3535
gamemgr.selected_game = event.index
3636
end
3737

‎builtin/mainmenu.lua

+11-11
Original file line numberDiff line numberDiff line change
@@ -459,8 +459,8 @@ function tabbuilder.handle_multiplayer_buttons(fields)
459459
end
460460

461461
if fields["favourites"] ~= nil then
462-
local event = explode_textlist_event(fields["favourites"])
463-
if event.typ == "DCL" then
462+
local event = engine.explode_textlist_event(fields["favourites"])
463+
if event.type == "DCL" then
464464
if event.index <= #menu.favorites then
465465
gamedata.address = menu.favorites[event.index].address
466466
gamedata.port = menu.favorites[event.index].port
@@ -484,7 +484,7 @@ function tabbuilder.handle_multiplayer_buttons(fields)
484484
end
485485
end
486486

487-
if event.typ == "CHG" then
487+
if event.type == "CHG" then
488488
if event.index <= #menu.favorites then
489489
local address = menu.favorites[event.index].address
490490
local port = menu.favorites[event.index].port
@@ -586,12 +586,12 @@ function tabbuilder.handle_server_buttons(fields)
586586
local world_doubleclick = false
587587

588588
if fields["srv_worlds"] ~= nil then
589-
local event = explode_textlist_event(fields["srv_worlds"])
589+
local event = engine.explode_textlist_event(fields["srv_worlds"])
590590

591-
if event.typ == "DCL" then
591+
if event.type == "DCL" then
592592
world_doubleclick = true
593593
end
594-
if event.typ == "CHG" then
594+
if event.type == "CHG" then
595595
engine.setting_set("mainmenu_last_selected_world",
596596
filterlist.get_raw_index(worldlist,engine.get_textlist_index("srv_worlds")))
597597
end
@@ -737,13 +737,13 @@ function tabbuilder.handle_singleplayer_buttons(fields)
737737
local world_doubleclick = false
738738

739739
if fields["sp_worlds"] ~= nil then
740-
local event = explode_textlist_event(fields["sp_worlds"])
740+
local event = engine.explode_textlist_event(fields["sp_worlds"])
741741

742-
if event.typ == "DCL" then
742+
if event.type == "DCL" then
743743
world_doubleclick = true
744744
end
745745

746-
if event.typ == "CHG" then
746+
if event.type == "CHG" then
747747
engine.setting_set("mainmenu_last_selected_world",
748748
filterlist.get_raw_index(worldlist,engine.get_textlist_index("sp_worlds")))
749749
end
@@ -813,8 +813,8 @@ end
813813
--------------------------------------------------------------------------------
814814
function tabbuilder.handle_texture_pack_buttons(fields)
815815
if fields["TPs"] ~= nil then
816-
local event = explode_textlist_event(fields["TPs"])
817-
if event.typ == "CHG" or event.typ=="DCL" then
816+
local event = engine.explode_textlist_event(fields["TPs"])
817+
if event.type == "CHG" or event.type == "DCL" then
818818
local index = engine.get_textlist_index("TPs")
819819
engine.setting_set("mainmenu_last_selected_TP",
820820
index)

‎builtin/misc_helpers.lua

+31-20
Original file line numberDiff line numberDiff line change
@@ -115,26 +115,6 @@ function math.hypot(x, y)
115115
return x * math.sqrt(1 + t * t)
116116
end
117117

118-
--------------------------------------------------------------------------------
119-
function explode_textlist_event(text)
120-
121-
local retval = {}
122-
retval.typ = "INV"
123-
124-
local parts = text:split(":")
125-
126-
if #parts == 2 then
127-
retval.typ = parts[1]:trim()
128-
retval.index= tonumber(parts[2]:trim())
129-
130-
if type(retval.index) ~= "number" then
131-
retval.typ = "INV"
132-
end
133-
end
134-
135-
return retval
136-
end
137-
138118
--------------------------------------------------------------------------------
139119
function get_last_folder(text,count)
140120
local parts = text:split(DIR_DELIM)
@@ -368,6 +348,37 @@ if minetest then
368348
end
369349
end
370350

351+
--------------------------------------------------------------------------------
352+
function tbl.explode_table_event(evt)
353+
if evt ~= nil then
354+
local parts = evt:split(":")
355+
if #parts == 3 then
356+
local t = parts[1]:trim()
357+
local r = tonumber(parts[2]:trim())
358+
local c = tonumber(parts[3]:trim())
359+
if type(r) == "number" and type(c) == "number" and t ~= "INV" then
360+
return {type=t, row=r, column=c}
361+
end
362+
end
363+
end
364+
return {type="INV", row=0, column=0}
365+
end
366+
367+
--------------------------------------------------------------------------------
368+
function tbl.explode_textlist_event(evt)
369+
if evt ~= nil then
370+
local parts = evt:split(":")
371+
if #parts == 2 then
372+
local t = parts[1]:trim()
373+
local r = tonumber(parts[2]:trim())
374+
if type(r) == "number" and t ~= "INV" then
375+
return {type=t, index=r}
376+
end
377+
end
378+
end
379+
return {type="INV", index=0}
380+
end
381+
371382
--------------------------------------------------------------------------------
372383
-- mainmenu only functions
373384
--------------------------------------------------------------------------------

‎builtin/modmgr.lua

+3-3
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ function modmgr.handle_modmgr_buttons(fields)
572572
}
573573

574574
if fields["modlist"] ~= nil then
575-
local event = explode_textlist_event(fields["modlist"])
575+
local event = engine.explode_textlist_event(fields["modlist"])
576576
modmgr.selected_mod = event.index
577577
end
578578

@@ -693,10 +693,10 @@ end
693693
--------------------------------------------------------------------------------
694694
function modmgr.handle_configure_world_buttons(fields)
695695
if fields["world_config_modlist"] ~= nil then
696-
local event = explode_textlist_event(fields["world_config_modlist"])
696+
local event = engine.explode_textlist_event(fields["world_config_modlist"])
697697
modmgr.world_config_selected_mod = event.index
698698

699-
if event.typ == "DCL" then
699+
if event.type == "DCL" then
700700
modmgr.world_config_enable_mod(nil)
701701
end
702702
end

‎doc/lua_api.txt

+62
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,7 @@ textlist[<X>,<Y>;<W>,<H>;<name>;<listelem 1>,<listelem 2>,...,<listelem n>;<sele
10111011
^ if you want a listelement to start with # write ##
10121012
^ index to be selected within textlist
10131013
^ true/false draw transparent background
1014+
^ see also minetest.explode_textlist_event (main menu: engine.explode_textlist_event)
10141015

10151016
tabheader[<X>,<Y>;<name>;<caption 1>,<caption 2>,...,<caption n>;<current_tab>;<transparent>;<draw_border>]
10161017
^ show a tabHEADER at specific position (ignores formsize)
@@ -1043,6 +1044,57 @@ checkbox[<X>,<Y>;<name>;<label>;<selected>]
10431044
^ label to be shown left of checkbox
10441045
^ selected (optional) true/false
10451046

1047+
table[<X>,<Y>;<W>,<H>;<name>;<cell 1>,<cell 2>,...,<cell n>;<selected idx>]
1048+
^ show scrollable table using options defined by the previous tableoptions[]
1049+
^ displays cells as defined by the previous tablecolumns[]
1050+
^ x and y position the itemlist relative to the top left of the menu
1051+
^ w and h are the size of the itemlist
1052+
^ name fieldname sent to server on row select or doubleclick
1053+
^ cell 1...n cell contents given in row-major order
1054+
^ selected idx: index of row to be selected within table (first row = 1)
1055+
^ see also minetest.explode_table_event (main menu: engine.explode_table_event)
1056+
1057+
tableoptions[<opt 1>;<opt 2>;...]
1058+
^ sets options for table[]:
1059+
^ color=#RRGGBB
1060+
^^ default text color (HEX-Color), defaults to #FFFFFF
1061+
^ background=#RRGGBB
1062+
^^ table background color (HEX-Color), defaults to #000000
1063+
^ border=<true/false>
1064+
^^ should the table be drawn with a border? (default true)
1065+
^ highlight=#RRGGBB
1066+
^^ highlight background color (HEX-Color), defaults to #466432
1067+
^ highlight_text=#RRGGBB
1068+
^^ highlight text color (HEX-Color), defaults to #FFFFFF
1069+
^ opendepth=<value>
1070+
^^ all subtrees up to depth < value are open (default value = 0)
1071+
^^ only useful when there is a column of type "tree"
1072+
1073+
tablecolumns[<type 1>,<opt 1a>,<opt 1b>,...;<type 2>,<opt 2a>,<opt 2b>;...]
1074+
^ sets columns for table[]:
1075+
^ types: text, image, color, indent, tree
1076+
^^ text: show cell contents as text
1077+
^^ image: cell contents are an image index, use column options to define images
1078+
^^ color: cell contents are a HEX-Color and define color of following cell
1079+
^^ indent: cell contents are a number and define indentation of following cell
1080+
^^ tree: same as indent, but user can open and close subtrees (treeview-like)
1081+
^ column options:
1082+
^^ align=<value> for "text" and "image": content alignment within cells
1083+
^^ available values: left (default), center, right, inline
1084+
^^ width=<value> for "text" and "image": minimum width in em (default 0)
1085+
^^ for "indent" and "tree": indent width in em (default 1.5)
1086+
^^ padding=<value> padding left of the column, in em (default 0.5)
1087+
^^ exception: defaults to 0 for indent columns
1088+
^^ tooltip=<value> tooltip text (default empty)
1089+
^ "image" column options:
1090+
^^ 0=<value> sets image for image index 0
1091+
^^ 1=<value> sets image for image index 1
1092+
^^ 2=<value> sets image for image index 2
1093+
^^ and so on; defined indices need not be contiguous
1094+
^^ empty or non-numeric cells are treated as 0
1095+
^ "color" column options:
1096+
^^ span=<value> number of following columns to affect (default infinite)
1097+
10461098
Note: do NOT use a element name starting with "key_" those names are reserved to
10471099
pass key press events to formspec!
10481100

@@ -1346,11 +1398,21 @@ minetest.get_inventory(location) -> InvRef
13461398
minetest.create_detached_inventory(name, callbacks) -> InvRef
13471399
^ callbacks: See "Detached inventory callbacks"
13481400
^ Creates a detached inventory. If it already exists, it is cleared.
1401+
1402+
Formspec:
13491403
minetest.show_formspec(playername, formname, formspec)
13501404
^ playername: name of player to show formspec
13511405
^ formname: name passed to on_player_receive_fields callbacks
13521406
^ should follow "modname:<whatever>" naming convention
13531407
^ formspec: formspec to display
1408+
minetest.formspec_escape(string) -> string
1409+
^ escapes characters [ ] \ , ; that can not be used in formspecs
1410+
minetest.explode_table_event(string) -> table
1411+
^ returns e.g. {type="CHG", row=1, column=2}
1412+
^ type: "INV" (no row selected), "CHG" (selected) or "DCL" (double-click)
1413+
minetest.explode_textlist_event(string) -> table
1414+
^ returns e.g. {type="CHG", index=1}
1415+
^ type: "INV" (no row selected), "CHG" (selected) or "DCL" (double-click)
13541416

13551417
Item handling:
13561418
minetest.inventorycube(img1, img2, img3)

‎doc/menu_lua_api.txt

+23-17
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,33 @@ engine.sound_play(spec, looped) -> handle
8989
^ looped = bool
9090
engine.sound_stop(handle)
9191

92-
GUI:
92+
Formspec:
9393
engine.update_formspec(formspec)
94-
- engine.set_background(type, texturepath)
94+
engine.get_table_index(tablename) -> index
95+
^ can also handle textlists
96+
engine.formspec_escape(string) -> string
97+
^ escapes characters [ ] \ , ; that can not be used in formspecs
98+
engine.explode_table_event(string) -> table
99+
^ returns e.g. {type="CHG", row=1, column=2}
100+
^ type: "INV" (no row selected), "CHG" (selected) or "DCL" (double-click)
101+
engine.explode_textlist_event(string) -> table
102+
^ returns e.g. {type="CHG", index=1}
103+
^ type: "INV" (no row selected), "CHG" (selected) or "DCL" (double-click)
104+
105+
GUI:
106+
engine.set_background(type, texturepath)
95107
^ type: "background", "overlay", "header" or "footer"
96108
engine.set_clouds(<true/false>)
97109
engine.set_topleft_text(text)
110+
engine.show_keys_menu()
111+
engine.file_open_dialog(formname,caption)
112+
^ shows a file open dialog
113+
^ formname is base name of dialog response returned in fields
114+
^ -if dialog was accepted "_accepted"
115+
^^ will be added to fieldname containing the path
116+
^ -if dialog was canceled "_cancelled"
117+
^ will be added to fieldname value is set to formname itself
118+
^ returns nil or selected file/folder
98119

99120
Games:
100121
engine.get_game(index)
@@ -155,22 +176,7 @@ engine.get_worlds() -> list of worlds (possible in async calls)
155176
engine.create_world(worldname, gameid)
156177
engine.delete_world(index)
157178

158-
159-
UI:
160-
engine.get_textlist_index(textlistname) -> index
161-
engine.show_keys_menu()
162-
engine.file_open_dialog(formname,caption)
163-
^ shows a file open dialog
164-
^ formname is base name of dialog response returned in fields
165-
^ -if dialog was accepted "_accepted"
166-
^^ will be added to fieldname containing the path
167-
^ -if dialog was canceled "_cancelled"
168-
^ will be added to fieldname value is set to formname itself
169-
^ returns nil or selected file/folder
170-
171179
Helpers:
172-
engine.formspec_escape(string) -> string
173-
^ escapes characters [ ] \ , ; that can not be used in formspecs
174180
engine.gettext(string) -> string
175181
^ look up the translation of a string in the gettext message catalog
176182
fgettext(string, ...) -> string

‎src/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ set(minetest_SRCS
374374
guiMessageMenu.cpp
375375
guiTextInputMenu.cpp
376376
guiFormSpecMenu.cpp
377+
guiTable.cpp
377378
guiPauseMenu.cpp
378379
guiPasswordChange.cpp
379380
guiVolumeChange.cpp

‎src/guiFormSpecMenu.cpp

+154-168
Large diffs are not rendered by default.

‎src/guiFormSpecMenu.h

+14-19
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2727
#include "inventory.h"
2828
#include "inventorymanager.h"
2929
#include "modalMenu.h"
30+
#include "guiTable.h"
3031

3132
class IGameDef;
3233
class InventoryManager;
3334
class ISimpleTextureSource;
3435

3536
typedef enum {
3637
f_Button,
37-
f_ListBox,
38+
f_Table,
3839
f_TabHeader,
3940
f_CheckBox,
4041
f_DropDown,
@@ -231,7 +232,10 @@ class GUIFormSpecMenu : public GUIModalMenu
231232
bool preprocessEvent(const SEvent& event);
232233
bool OnEvent(const SEvent& event);
233234

234-
int getListboxIndex(std::string listboxname);
235+
GUITable* getTable(std::wstring tablename);
236+
237+
static bool parseColor(const std::string &value,
238+
video::SColor &color, bool quiet);
235239

236240
protected:
237241
v2s32 getBasePos() const
@@ -260,7 +264,7 @@ class GUIFormSpecMenu : public GUIModalMenu
260264
std::vector<ImageDrawSpec> m_itemimages;
261265
std::vector<BoxDrawSpec> m_boxes;
262266
std::vector<FieldSpec> m_fields;
263-
std::vector<std::pair<FieldSpec,gui::IGUIListBox*> > m_listboxes;
267+
std::vector<std::pair<FieldSpec,GUITable*> > m_tables;
264268
std::vector<std::pair<FieldSpec,gui::IGUICheckBox*> > m_checkboxes;
265269

266270
ItemSpec *m_selected_item;
@@ -273,12 +277,6 @@ class GUIFormSpecMenu : public GUIModalMenu
273277
ItemStack m_selected_content_guess;
274278
InventoryLocation m_selected_content_guess_inventory;
275279

276-
// WARNING: BLACK IRRLICHT MAGIC, see checkListboxClick()
277-
std::wstring m_listbox_click_fname;
278-
int m_listbox_click_index;
279-
u32 m_listbox_click_time;
280-
bool m_listbox_doubleclick;
281-
282280
v2s32 m_pointer;
283281
gui::IGUIStaticText *m_tooltip_element;
284282

@@ -302,8 +300,10 @@ class GUIFormSpecMenu : public GUIModalMenu
302300
int bp_set;
303301
v2u32 screensize;
304302
std::wstring focused_fieldname;
305-
std::map<std::wstring,int> listbox_selections;
306-
std::map<std::wstring,int> listbox_scroll;
303+
GUITable::TableOptions table_options;
304+
GUITable::TableColumns table_columns;
305+
// used to restore table selection/scroll/treeview state
306+
std::map<std::wstring,GUITable::DynamicData> table_dyndata;
307307
} parserData;
308308

309309
typedef struct {
@@ -315,12 +315,6 @@ class GUIFormSpecMenu : public GUIModalMenu
315315

316316
fs_key_pendig current_keys_pending;
317317

318-
// Determine whether listbox click was double click
319-
// (Using some black Irrlicht magic)
320-
bool checkListboxClick(std::wstring wlistboxname, int eventtype);
321-
322-
gui::IGUIScrollBar* getListboxScrollbar(gui::IGUIListBox *listbox);
323-
324318
void parseElement(parserData* data,std::string element);
325319

326320
void parseSize(parserData* data,std::string element);
@@ -330,6 +324,9 @@ class GUIFormSpecMenu : public GUIModalMenu
330324
void parseItemImage(parserData* data,std::string element);
331325
void parseButton(parserData* data,std::string element,std::string typ);
332326
void parseBackground(parserData* data,std::string element);
327+
void parseTableOptions(parserData* data,std::string element);
328+
void parseTableColumns(parserData* data,std::string element);
329+
void parseTable(parserData* data,std::string element);
333330
void parseTextList(parserData* data,std::string element);
334331
void parseDropDown(parserData* data,std::string element);
335332
void parsePwdField(parserData* data,std::string element);
@@ -344,8 +341,6 @@ class GUIFormSpecMenu : public GUIModalMenu
344341
void parseBox(parserData* data,std::string element);
345342
void parseBackgroundColor(parserData* data,std::string element);
346343
void parseListColors(parserData* data,std::string element);
347-
348-
bool parseColor(std::string &value, video::SColor &color, bool quiet);
349344
};
350345

351346
class FormspecFormSource: public IFormSource

‎src/guiTable.cpp

+1,212
Large diffs are not rendered by default.

‎src/guiTable.h

+269
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
/*
2+
Minetest
3+
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4+
5+
This program is free software; you can redistribute it and/or modify
6+
it under the terms of the GNU Lesser General Public License as published by
7+
the Free Software Foundation; either version 2.1 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public License along
16+
with this program; if not, write to the Free Software Foundation, Inc.,
17+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*/
19+
20+
21+
#ifndef GUITABLE_HEADER
22+
#define GUITABLE_HEADER
23+
24+
#include <map>
25+
#include <set>
26+
#include <string>
27+
#include <vector>
28+
#include <iostream>
29+
30+
#include "irrlichttypes_extrabloated.h"
31+
32+
class ISimpleTextureSource;
33+
34+
/*
35+
A table GUI element for GUIFormSpecMenu.
36+
37+
Sends a EGET_TABLE_CHANGED event to the parent when
38+
an item is selected or double-clicked.
39+
Call checkEvent() to get info.
40+
41+
Credits: The interface and implementation of this class are (very)
42+
loosely based on the Irrlicht classes CGUITable and CGUIListBox.
43+
CGUITable and CGUIListBox are licensed under the Irrlicht license;
44+
they are Copyright (C) 2002-2012 Nikolaus Gebhardt
45+
*/
46+
class GUITable : public gui::IGUIElement
47+
{
48+
public:
49+
/*
50+
Stores dynamic data that should be preserved
51+
when updating a formspec
52+
*/
53+
struct DynamicData
54+
{
55+
s32 selected;
56+
s32 scrollpos;
57+
s32 keynav_time;
58+
core::stringw keynav_buffer;
59+
std::set<s32> opened_trees;
60+
61+
DynamicData()
62+
{
63+
selected = 0;
64+
scrollpos = 0;
65+
keynav_time = 0;
66+
}
67+
};
68+
69+
/*
70+
An option of the form <name>=<value>
71+
*/
72+
struct Option
73+
{
74+
std::string name;
75+
std::string value;
76+
77+
Option(const std::string &name_, const std::string &value_)
78+
{
79+
name = name_;
80+
value = value_;
81+
}
82+
};
83+
84+
/*
85+
A list of options that concern the entire table
86+
*/
87+
typedef std::vector<Option> TableOptions;
88+
89+
/*
90+
A column with options
91+
*/
92+
struct TableColumn
93+
{
94+
std::string type;
95+
std::vector<Option> options;
96+
};
97+
typedef std::vector<TableColumn> TableColumns;
98+
99+
100+
GUITable(gui::IGUIEnvironment *env,
101+
gui::IGUIElement *parent, s32 id,
102+
core::rect<s32> rectangle,
103+
ISimpleTextureSource *tsrc);
104+
105+
virtual ~GUITable();
106+
107+
/* Split a string of the form "name=value" into name and value */
108+
static Option splitOption(const std::string &str);
109+
110+
/* Set textlist-like options, columns and data */
111+
void setTextList(const std::vector<std::string> &content,
112+
bool transparent);
113+
114+
/* Set generic table options, columns and content */
115+
// Adds empty strings to end of content if there is an incomplete row
116+
void setTable(const TableOptions &options,
117+
const TableColumns &columns,
118+
std::vector<std::string> &content);
119+
120+
/* Clear the table */
121+
void clear();
122+
123+
/* Get info about last event (string such as "CHG:1:2") */
124+
// Call this after EGET_TABLE_CHANGED
125+
std::string checkEvent();
126+
127+
/* Get index of currently selected row (first=1; 0 if none selected) */
128+
s32 getSelected() const;
129+
130+
/* Set currently selected row (first=1; 0 if none selected) */
131+
// If given index is not visible at the moment, select its parent
132+
// Autoscroll to make the selected row fully visible
133+
void setSelected(s32 index);
134+
135+
/* Get selection, scroll position and opened (sub)trees */
136+
DynamicData getDynamicData() const;
137+
138+
/* Set selection, scroll position and opened (sub)trees */
139+
void setDynamicData(const DynamicData &dyndata);
140+
141+
/* Returns "GUITable" */
142+
virtual const c8* getTypeName() const;
143+
144+
/* Must be called when position or size changes */
145+
virtual void updateAbsolutePosition();
146+
147+
/* Irrlicht draw method */
148+
virtual void draw();
149+
150+
/* Irrlicht event handler */
151+
virtual bool OnEvent(const SEvent &event);
152+
153+
protected:
154+
enum ColumnType {
155+
COLUMN_TYPE_TEXT,
156+
COLUMN_TYPE_IMAGE,
157+
COLUMN_TYPE_COLOR,
158+
COLUMN_TYPE_INDENT,
159+
COLUMN_TYPE_TREE,
160+
};
161+
162+
struct Cell {
163+
s32 xmin;
164+
s32 xmax;
165+
s32 xpos;
166+
ColumnType content_type;
167+
s32 content_index;
168+
s32 tooltip_index;
169+
video::SColor color;
170+
bool color_defined;
171+
s32 reported_column;
172+
};
173+
174+
struct Row {
175+
Cell *cells;
176+
s32 cellcount;
177+
s32 indent;
178+
// visible_index >= 0: is index of row in m_visible_rows
179+
// visible_index == -1: parent open but other ancestor closed
180+
// visible_index == -2: parent closed
181+
s32 visible_index;
182+
};
183+
184+
// Texture source
185+
ISimpleTextureSource *m_tsrc;
186+
187+
// Table content (including hidden rows)
188+
std::vector<Row> m_rows;
189+
// Table content (only visible; indices into m_rows)
190+
std::vector<s32> m_visible_rows;
191+
bool m_is_textlist;
192+
bool m_has_tree_column;
193+
194+
// Selection status
195+
s32 m_selected; // index of row (1...n), or 0 if none selected
196+
s32 m_sel_column;
197+
bool m_sel_doubleclick;
198+
199+
// Keyboard navigation stuff
200+
s32 m_keynav_time;
201+
core::stringw m_keynav_buffer;
202+
203+
// Drawing and geometry information
204+
bool m_border;
205+
video::SColor m_color;
206+
video::SColor m_background;
207+
video::SColor m_highlight;
208+
video::SColor m_highlight_text;
209+
s32 m_rowheight;
210+
gui::IGUIFont *m_font;
211+
gui::IGUIScrollBar *m_scrollbar;
212+
213+
// Allocated strings and images
214+
std::vector<core::stringw> m_strings;
215+
std::vector<video::ITexture*> m_images;
216+
std::map<std::string, s32> m_alloc_strings;
217+
std::map<std::string, s32> m_alloc_images;
218+
219+
s32 allocString(const std::string &text);
220+
s32 allocImage(const std::string &imagename);
221+
void allocationComplete();
222+
223+
// Helper for draw() that draws a single cell
224+
void drawCell(const Cell *cell, video::SColor color,
225+
const core::rect<s32> &rowrect,
226+
const core::rect<s32> &client_clip);
227+
228+
// Returns the i-th visible row (NULL if i is invalid)
229+
const Row *getRow(s32 i) const;
230+
231+
// Key navigation helper
232+
bool doesRowStartWith(const Row *row, const core::stringw &str) const;
233+
234+
// Returns the row at a given screen Y coordinate
235+
// Returns index i such that m_rows[i] is valid (or -1 on error)
236+
s32 getRowAt(s32 y, bool &really_hovering) const;
237+
238+
// Returns the cell at a given screen X coordinate within m_rows[row_i]
239+
// Returns index j such that m_rows[row_i].cells[j] is valid
240+
// (or -1 on error)
241+
s32 getCellAt(s32 x, s32 row_i) const;
242+
243+
// Make the selected row fully visible
244+
void autoScroll();
245+
246+
// Should be called when m_rowcount or m_rowheight changes
247+
void updateScrollBar();
248+
249+
// Sends EET_GUI_EVENT / EGET_TABLE_CHANGED to parent
250+
void sendTableEvent(s32 column, bool doubleclick);
251+
252+
// Functions that help deal with hidden rows
253+
// The following functions take raw row indices (hidden rows not skipped)
254+
void getOpenedTrees(std::set<s32> &opened_trees) const;
255+
void setOpenedTrees(const std::set<s32> &opened_trees);
256+
void openTree(s32 to_open);
257+
void closeTree(s32 to_close);
258+
// The following function takes a visible row index (hidden rows skipped)
259+
// dir: -1 = left (close), 0 = auto (toggle), 1 = right (open)
260+
void toggleVisibleTree(s32 row_i, int dir, bool move_selection);
261+
262+
// Aligns cell content in column according to alignment specification
263+
// align = 0: left aligned, 1: centered, 2: right aligned, 3: inline
264+
static void alignContent(Cell *cell, s32 xmax, s32 content_width,
265+
s32 align);
266+
};
267+
268+
#endif
269+

‎src/script/lua_api/l_mainmenu.cpp

+15-7
Original file line numberDiff line numberDiff line change
@@ -183,18 +183,25 @@ int ModApiMainMenu::l_set_clouds(lua_State *L)
183183

184184
/******************************************************************************/
185185
int ModApiMainMenu::l_get_textlist_index(lua_State *L)
186+
{
187+
// get_table_index accepts both tables and textlists
188+
return l_get_table_index(L);
189+
}
190+
191+
/******************************************************************************/
192+
int ModApiMainMenu::l_get_table_index(lua_State *L)
186193
{
187194
GUIEngine* engine = getGuiEngine(L);
188195
assert(engine != 0);
189196

190-
std::string listboxname(luaL_checkstring(L, 1));
197+
std::wstring tablename(narrow_to_wide(luaL_checkstring(L, 1)));
198+
GUITable *table = engine->m_menu->getTable(tablename);
199+
s32 selection = table ? table->getSelected() : 0;
191200

192-
int selection = engine->m_menu->getListboxIndex(listboxname);
193-
194-
if (selection >= 0)
195-
selection++;
196-
197-
lua_pushinteger(L, selection);
201+
if (selection >= 1)
202+
lua_pushinteger(L, selection);
203+
else
204+
lua_pushnil(L);
198205
return 1;
199206
}
200207

@@ -1026,6 +1033,7 @@ void ModApiMainMenu::Initialize(lua_State *L, int top)
10261033
API_FCT(update_formspec);
10271034
API_FCT(set_clouds);
10281035
API_FCT(get_textlist_index);
1036+
API_FCT(get_table_index);
10291037
API_FCT(get_worlds);
10301038
API_FCT(get_games);
10311039
API_FCT(start);

‎src/script/lua_api/l_mainmenu.h

+2
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ class ModApiMainMenu : public ModApiBase {
9797

9898
static int l_get_textlist_index(lua_State *L);
9999

100+
static int l_get_table_index(lua_State *L);
101+
100102
static int l_set_background(lua_State *L);
101103

102104
static int l_update_formspec(lua_State *L);

0 commit comments

Comments
 (0)
Please sign in to comment.