cross platform gui lib for lua
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

656 lines
21 KiB

  1. /* uiTableModel *************************************************************/
  2. /*** Object
  3. * Name: tablemodel
  4. * a tablemodel provided the data to a table. Communication happens through
  5. * callback functions.
  6. */
  7. /* TODO L should really be a void* (userdata) associated with the model,
  8. * instead of the modelhandler. Check if (when) this will be implemented
  9. * in libui */
  10. struct myUiTableModelHandler {
  11. struct uiTableModelHandler handler;
  12. lua_State *L;
  13. };
  14. #define uiTableModel(this) ((uiTableModel *) (this))
  15. #define LUI_TABLEMODEL "lui_tablemodel"
  16. #define lui_pushTableModel(L) lui_pushObject(L, LUI_TABLEMODEL, 1)
  17. #define lui_checkTableModel(L, pos) ((lui_object*)luaL_checkudata(L, pos, LUI_TABLEMODEL))
  18. #define LUI_TABLEMODEL_REGISTRY "lui_tablemodel_registry"
  19. static int lui_tablemodel__gc(lua_State *L)
  20. {
  21. lui_object *lobj = lui_checkTableModel(L, 1);
  22. if (lobj->object) {
  23. DEBUGMSG("lui_tablemodel__gc (%s)", lui_debug_controlTostring(L, 1));
  24. uiFreeTableModel(uiTableModel(lobj->object));
  25. lobj->object = 0;
  26. }
  27. return 0;
  28. }
  29. /* metamethods for tablemodel */
  30. static const luaL_Reg lui_tablemodel_meta[] = {
  31. {"__gc", lui_tablemodel__gc},
  32. {0, 0}
  33. };
  34. /*** Method
  35. * Object: tablemodel
  36. * Name: row_inserted
  37. * Signature: mdl:row_inserted(rownumber)
  38. * signals to any connected table that a row has been inserted into the data
  39. * represented by the table model.
  40. */
  41. static int lui_tablemodel_row_inserted(lua_State *L)
  42. {
  43. lui_object *lobj = lui_checkTableModel(L, 1);
  44. int row = lua_tointeger(L, 2);
  45. uiTableModelRowInserted(uiTableModel(lobj->object), row);
  46. return 0;
  47. }
  48. /*** Method
  49. * Object: tablemodel
  50. * Name: row_changed
  51. * Signature: mdl:row_changed(rownumber)
  52. * signals to any connected table that a row has been changed in the data
  53. * represented by the table model. You need to only call this when the data
  54. * is changed by the program, if it has been changed by editing a cell in
  55. * the table control, you do not need to signal this to the table.
  56. */
  57. static int lui_tablemodel_row_changed(lua_State *L)
  58. {
  59. lui_object *lobj = lui_checkTableModel(L, 1);
  60. int row = lua_tointeger(L, 2);
  61. uiTableModelRowChanged(uiTableModel(lobj->object), row);
  62. return 0;
  63. }
  64. /*** Method
  65. * Object: tablemodel
  66. * Name: row_deleted
  67. * Signature: mdl:row_deleted(rownumber)
  68. * signals to any connected table that a row has been deleted from the data
  69. * represented by the table model.
  70. */
  71. static int lui_tablemodel_row_deleted(lua_State *L)
  72. {
  73. lui_object *lobj = lui_checkTableModel(L, 1);
  74. int row = lua_tointeger(L, 2);
  75. uiTableModelRowDeleted(uiTableModel(lobj->object), row);
  76. return 0;
  77. }
  78. /* methods for tablemodel */
  79. static const luaL_Reg lui_tablemodel_methods[] = {
  80. {"row_inserted", lui_tablemodel_row_inserted},
  81. {"row_changed", lui_tablemodel_row_changed},
  82. {"row_deleted", lui_tablemodel_row_deleted},
  83. {0, 0}
  84. };
  85. /* lui control registry handling
  86. */
  87. static int lui_registerTableModel(lua_State *L, int pos)
  88. {
  89. lui_object *lobj = lui_toObject(L, pos);
  90. lua_getfield(L, LUA_REGISTRYINDEX, LUI_TABLEMODEL_REGISTRY);
  91. lua_pushlightuserdata(L, lobj->object);
  92. lua_pushvalue(L, pos);
  93. lua_settable(L, -3);
  94. lua_pop(L, 1);
  95. return 0;
  96. }
  97. static int lui_findTableModel(lua_State *L, const uiTableModel *tm)
  98. {
  99. lua_getfield(L, LUA_REGISTRYINDEX, LUI_TABLEMODEL_REGISTRY);
  100. lua_pushlightuserdata(L, (uiTableModel*)tm);
  101. lua_gettable(L, -2);
  102. lua_replace(L, -2);
  103. return lua_type(L, -1);
  104. }
  105. static int lui_findhandler(lua_State *L, uiTableModel *tm, const char *func)
  106. {
  107. if (lui_findTableModel(L, tm) == LUA_TNIL) {
  108. lua_pop(L, 1);
  109. return 0; // TODO should this be a lua error?
  110. }
  111. if (lui_aux_getUservalue(L, -1, "handler") == LUA_TTABLE) {
  112. lua_getfield(L, -1, func);
  113. lua_replace(L, -3);
  114. lua_pop(L, 1);
  115. return 1;
  116. }
  117. lua_pop(L, 2);
  118. return 0;
  119. }
  120. static int lui_tablemodelhandler_numcolumns(uiTableModelHandler *tmh, uiTableModel *tm)
  121. {
  122. lua_State *L = ((struct myUiTableModelHandler*)tmh)->L;
  123. if (lui_findhandler(L, tm, "numcolumns")) {
  124. lua_call(L, 0, 1);
  125. int res = lua_tointeger(L, -1);
  126. lua_pop(L, 1);
  127. return res;
  128. }
  129. return 0;
  130. }
  131. static int lui_tablemodelhandler_numrows(uiTableModelHandler *tmh, uiTableModel *tm)
  132. {
  133. lua_State *L = ((struct myUiTableModelHandler*)tmh)->L;
  134. if (lui_findhandler(L, tm, "numrows")) {
  135. lua_call(L, 0, 1);
  136. int res = lua_tointeger(L, -1);
  137. lua_pop(L, 1);
  138. return res;
  139. }
  140. return 0;
  141. }
  142. typedef enum {
  143. lui_TableValueTypeNull,
  144. lui_TableValueTypeString,
  145. lui_TableValueTypeInt,
  146. lui_TableValueTypeBool,
  147. lui_TableValueTypeImage,
  148. lui_TableValueTypeColor,
  149. } lui_TableValueType;
  150. static lui_TableValueType lui_tablemodelhandler_rawcolumntype(uiTableModelHandler *tmh, uiTableModel *tm, int col)
  151. {
  152. DEBUGMSG("lui_tablemodelhandler_rawcolumntype called for col %d", col);
  153. uiTableValueType res = lui_TableValueTypeNull;
  154. lua_State *L = ((struct myUiTableModelHandler*)tmh)->L;
  155. if (lui_findTableModel(L, tm) != LUA_TNIL) {
  156. if (lui_aux_getUservalue(L, -1, "columntype") != LUA_TTABLE) {
  157. lua_pop(L, 1);
  158. lua_newtable(L);
  159. lui_aux_setUservalue(L, -2, "columntype", -1);
  160. }
  161. if (lua_rawgeti(L, -1, col) != LUA_TNIL) {
  162. res = lua_tointeger(L, -1);
  163. lua_pop(L, 3);
  164. return res;
  165. }
  166. lua_pop(L, 1); // tm uv
  167. if (lui_findhandler(L, tm, "columntype")) {
  168. lua_pushinteger(L, col);
  169. lua_call(L, 1, 1);
  170. const char *type = lua_tostring(L, -1);
  171. if (!type || !strcmp(type, "string")) {
  172. res = lui_TableValueTypeString;
  173. } else if (!strcmp(type, "int") || !strcmp(type, "integer")) {
  174. res = lui_TableValueTypeInt;
  175. } else if (!strcmp(type, "bool") || !strcmp(type, "boolean")) {
  176. res = lui_TableValueTypeBool;
  177. } else if (!strcmp(type, "image")) {
  178. res = lui_TableValueTypeImage;
  179. } else if (!strcmp(type, "color")) {
  180. res = lui_TableValueTypeColor;
  181. } else {
  182. puts("Error!\n");//TODO error
  183. }
  184. lua_pop(L, 1);
  185. }
  186. lua_pushinteger(L, res);
  187. lua_rawseti(L, -2, col);
  188. lua_pop(L, 2);
  189. }
  190. return res;
  191. }
  192. static uiTableValueType lui_tablemodelhandler_columntype(uiTableModelHandler *tmh, uiTableModel *tm, int col)
  193. {
  194. DEBUGMSG("lui_tablemodelhandler_columntype called for col %d", col);
  195. lui_TableValueType raw = lui_tablemodelhandler_rawcolumntype(tmh, tm, col);
  196. uiTableValueType res = uiTableValueTypeString;
  197. switch (raw) {
  198. case lui_TableValueTypeNull:
  199. case lui_TableValueTypeString:
  200. res = uiTableValueTypeString;
  201. break;
  202. case lui_TableValueTypeInt:
  203. case lui_TableValueTypeBool:
  204. res = uiTableValueTypeInt;
  205. break;
  206. case lui_TableValueTypeImage:
  207. res = uiTableValueTypeImage;
  208. break;
  209. case lui_TableValueTypeColor:
  210. res = uiTableValueTypeColor;
  211. break;
  212. }
  213. return res;
  214. }
  215. static uiTableValue *lui_tablemodel_totablevaluestring(lua_State *L, int pos)
  216. {
  217. if (pos < 0) {
  218. pos = lua_gettop(L) + 1 + pos;
  219. }
  220. lua_getglobal(L, "tostring");
  221. lua_pushvalue(L, -2);
  222. lua_call(L, 1, 1);
  223. uiTableValue *res = uiNewTableValueString(lua_tostring(L, -1));
  224. lua_pop(L, 1);
  225. return res;
  226. }
  227. static uiTableValue *lui_tablemodelhandler_cellvalue(uiTableModelHandler *tmh, uiTableModel *tm, int row, int col)
  228. {
  229. DEBUGMSG("lui_tablemodelhandler_cellvalue called for row %d col %d", row, col);
  230. uiTableValue *res = NULL;
  231. lua_State *L = ((struct myUiTableModelHandler*)tmh)->L;
  232. if (lui_findhandler(L, tm, "cellvalue")) {
  233. lua_pushinteger(L, row + 1);
  234. lua_pushinteger(L, col);
  235. lua_call(L, 2, 1);
  236. uiTableValueType vtype = lui_tablemodelhandler_columntype(tmh, tm, col);
  237. switch (lua_type(L, -1)) {
  238. case LUA_TBOOLEAN:
  239. if (vtype == uiTableValueTypeInt) {
  240. res = uiNewTableValueInt(lua_toboolean(L, -1));
  241. } else if (vtype == uiTableValueTypeString) {
  242. res = lui_tablemodel_totablevaluestring(L, -1);
  243. } else {
  244. puts("Error!\n");// TODO error
  245. }
  246. break;
  247. case LUA_TNUMBER:
  248. if (vtype == uiTableValueTypeInt) {
  249. res = uiNewTableValueInt(lua_tointeger(L, -1));
  250. } else if (vtype == uiTableValueTypeString) {
  251. res = uiNewTableValueString(lua_tostring(L, -1));
  252. } else {
  253. puts("Error!\n");// TODO error
  254. }
  255. break;
  256. case LUA_TTABLE:
  257. if (vtype == uiTableValueTypeColor) {
  258. double r, g, b, a;
  259. lui_aux_rgbaFromTable(L, -1, &r, &g, &b, &a);
  260. res = uiNewTableValueColor(r, g, b, a);
  261. } else if (vtype == uiTableValueTypeString) {
  262. res = lui_tablemodel_totablevaluestring(L, -1);
  263. } else {
  264. puts("Error!\n");// TODO error
  265. }
  266. break;
  267. case LUA_TUSERDATA:
  268. if (vtype == uiTableValueTypeImage) {
  269. lui_object *lobj = lui_checkImage(L, -1);
  270. res = uiNewTableValueImage(lobj->object);
  271. } else if (vtype == uiTableValueTypeString) {
  272. res = lui_tablemodel_totablevaluestring(L, -1);
  273. } else {
  274. puts("Error!\n");// TODO error
  275. }
  276. break;
  277. case LUA_TSTRING:
  278. default:
  279. if (vtype == uiTableValueTypeString) {
  280. res = lui_tablemodel_totablevaluestring(L, -1);
  281. } else {
  282. puts("Error!\n");// TODO error
  283. }
  284. break;
  285. }
  286. if (!res) {
  287. // TODO error
  288. uiNewTableValueString("Oh Boy 1...");
  289. }
  290. lua_pop(L, 1);
  291. return res;
  292. }
  293. if (!res) {
  294. // TODO error
  295. uiNewTableValueString("Oh Boy 2...");
  296. }
  297. return res;
  298. }
  299. static void lui_tablemodelhandler_setcellvalue(uiTableModelHandler *tmh, uiTableModel *tm, int row, int col, const uiTableValue *tv)
  300. {
  301. DEBUGMSG("lui_tablemodelhandler_setcellvalue called for row %d col %d", row, col);
  302. lua_State *L = ((struct myUiTableModelHandler*)tmh)->L;
  303. if (lui_findhandler(L, tm, "setcellvalue")) {
  304. lua_pushinteger(L, row + 1);
  305. lua_pushinteger(L, col);
  306. if (tv) {
  307. lui_TableValueType rtype = lui_tablemodelhandler_rawcolumntype(tmh, tm, col);
  308. switch (uiTableValueGetType(tv)) {
  309. case uiTableValueTypeString:
  310. if (rtype == lui_TableValueTypeNull || rtype == lui_TableValueTypeString) {
  311. lua_pushstring(L, uiTableValueString(tv));
  312. } else {
  313. //TODO error
  314. lua_pushnil(L);
  315. }
  316. break;
  317. case uiTableValueTypeInt:
  318. if (rtype == lui_TableValueTypeInt) {
  319. lua_pushinteger(L, uiTableValueInt(tv));
  320. } else if (rtype == lui_TableValueTypeBool) {
  321. lua_pushboolean(L, uiTableValueInt(tv));
  322. } else {
  323. //TODO error
  324. lua_pushnil(L);
  325. }
  326. break;
  327. default:
  328. lua_pushnil(L); // this should not happen
  329. }
  330. } else {
  331. lua_pushnil(L);
  332. }
  333. lua_call(L, 3, 0);
  334. }
  335. }
  336. static int lui_checkHandlerTable(lua_State *L, int pos)
  337. {
  338. lua_pushnil(L);
  339. while (lua_next(L, pos) != 0) {
  340. const char *name = lua_tostring(L, -2);
  341. int vtype = lua_type(L, -1);
  342. if (strcmp(name, "numcolumns") != 0 &&
  343. strcmp(name, "columntype") != 0 &&
  344. strcmp(name, "numrows") != 0 &&
  345. strcmp(name, "cellvalue") != 0 &&
  346. strcmp(name, "setcellvalue") != 0) {
  347. return luaL_error(L, "invalid field in handler table");
  348. }
  349. if (vtype != LUA_TFUNCTION) {
  350. return luaL_error(L, "invalid value in handdler table");
  351. }
  352. lua_pop(L, 1);
  353. }
  354. return 1;
  355. }
  356. /*** Constructor
  357. * Object: tablemodel
  358. * Name: tablemodel
  359. * signature: mdl = lui.tablemodel( handlerfuncs )
  360. * creates a new table model. handlerfuncs is a table with 5 named entries,
  361. * which are user supplied functions the table uses to get and set data from
  362. * the model. These functions are:
  363. *
  364. * numcolumns()
  365. * must return the number of columns in the data
  366. * numrows()
  367. * must return the number of rows in the data
  368. * columntype(col)
  369. * must return the type of data in column col. Valid return values are
  370. * string, integer, boolean, image and color. All values that have a
  371. * textual representation in a cell must be returned as string, the
  372. * other types are only valid for special column types. Note that the
  373. * type for a column must remain fixed throughout the tabemoodels life
  374. * time. Your function is most probably only called once.
  375. * cellvalue(row, col)
  376. * must return the data in row, col. The data must correspond to the
  377. * type returned by columntype for this column, except in the case of
  378. * string. Anything will be converted to it's string representation
  379. * for string type columns.
  380. * setcellvalue(row, col, val)
  381. * must set the data in row, col to value val.
  382. */
  383. static int lui_newTableModel(lua_State *L)
  384. {
  385. struct myUiTableModelHandler *tmh = calloc(1, sizeof(struct myUiTableModelHandler));
  386. tmh->handler.NumColumns = lui_tablemodelhandler_numcolumns;
  387. tmh->handler.ColumnType = lui_tablemodelhandler_columntype;
  388. tmh->handler.NumRows = lui_tablemodelhandler_numrows;
  389. tmh->handler.CellValue = lui_tablemodelhandler_cellvalue;
  390. tmh->handler.SetCellValue = lui_tablemodelhandler_setcellvalue;
  391. tmh->L = L;
  392. // TODO does the model own the modelhandler? should probably handle with __gc?
  393. lui_checkHandlerTable(L, 1);
  394. lui_object *lobj = lui_pushTableModel(L);
  395. lobj->object = uiNewTableModel((uiTableModelHandler *)tmh);
  396. lua_getuservalue(L, -1);
  397. // TODO what about tmh?
  398. lua_pushvalue(L, 1);
  399. lua_setfield(L, -2, "handler");
  400. lua_pop(L, 1);
  401. lui_registerTableModel(L, lua_gettop(L));
  402. return 1;
  403. }
  404. /* uiTable ******************************************************************/
  405. /*** Object
  406. * Name: table
  407. */
  408. #define uiTable(this) ((uiTable *) (this))
  409. #define LUI_TABLE "lui_table"
  410. #define lui_pushTable(L) lui_pushObject(L, LUI_TABLE, 1)
  411. #define lui_checkTable(L, pos) ((lui_object*)luaL_checkudata(L, pos, LUI_TABLE))
  412. /*** Method
  413. * Object: table
  414. * Name: appendtextcolumn
  415. * Signature: tbl:appendtextcolumn(name, datacolumn, editable = false, textcolorcolumn = nil)
  416. * appends a text column to a table. name is displayed as the column header.
  417. * datacolumn is the column from the underlying datamodel, where the text
  418. * comes from. If a row is editable according to the editable parameter,
  419. * SetCellValue() is called with datacolumn as the column. If the
  420. * textcolorcolumn argument is ~= nil, it is a column that must hold a
  421. * color value which is to be used for the text color for this column.
  422. */
  423. static int lui_table_appendtextcolumn(lua_State *L)
  424. {
  425. lui_object *lobj = lui_checkTable(L, 1);
  426. const char *name = luaL_checkstring(L, 2);
  427. int column = luaL_checkinteger(L, 3);
  428. int editable = lua_toboolean(L, 4) ? uiTableModelColumnAlwaysEditable : uiTableModelColumnNeverEditable;
  429. int cmc = luaL_optinteger(L, 5, -1);
  430. uiTableTextColumnOptionalParams tparm = { .ColorModelColumn = cmc };
  431. uiTableAppendTextColumn(uiTable(lobj->object), name, column, editable, &tparm);
  432. return 0;
  433. }
  434. /*** Method
  435. * Object: table
  436. * Name: appendimagecolumn
  437. * Signature: tbl:appendimagecolumn(name, datacolumn)
  438. * appends an image column to a table. name is displayed as the column
  439. * header. datacolumn is the column from the data model that must hold an
  440. * image object to be displayed in this column.
  441. */
  442. static int lui_table_appendimagecolumn(lua_State *L)
  443. {
  444. lui_object *lobj = lui_checkTable(L, 1);
  445. const char *name = luaL_checkstring(L, 2);
  446. int column = luaL_checkinteger(L, 3);
  447. uiTableAppendImageColumn(uiTable(lobj->object), name, column);
  448. return 0;
  449. }
  450. /*** Method
  451. * Object: table
  452. * Name: appendimagetextcolumn
  453. * Signature: tbl:appendimagetextcolumn(name, icolumn, tcolumn, editable = false, textcolorcolumn = nil)
  454. * appends a column to a table that displays both an image and a text.
  455. * name is displayed as the column header. icolumn is the column from the
  456. * datamodel that must hold an image object to be displayed in this column.
  457. * tcolumn is the column from the underlying datamodel, where the text
  458. * comes from. If a row is editable according to the editable parameter,
  459. * SetCellValue() is called with datacolumn as the column. If the
  460. * textcolorcolumn argument is ~= nil, it is a column that must hold a
  461. * color value which is to be used for the text color for this column.
  462. */
  463. static int lui_table_appendimagetextcolumn(lua_State *L)
  464. {
  465. lui_object *lobj = lui_checkTable(L, 1);
  466. const char *name = luaL_checkstring(L, 2);
  467. int icolumn = luaL_checkinteger(L, 3);
  468. int tcolumn = luaL_checkinteger(L, 4);
  469. int editable = lua_toboolean(L, 5) ? uiTableModelColumnAlwaysEditable : uiTableModelColumnNeverEditable;
  470. int cmc = luaL_optinteger(L, 6, -1);
  471. uiTableTextColumnOptionalParams tparm = { .ColorModelColumn = cmc };
  472. uiTableAppendImageTextColumn(uiTable(lobj->object), name, icolumn, tcolumn, editable, &tparm);
  473. return 0;
  474. }
  475. /*** Method
  476. * Object: table
  477. * Name: appendcheckboxcolumn
  478. * Signature: tbl:appendcheckboxcolumn(name, datacolumn, editable)
  479. * appends a column that contains a checkbox. name is displayed as the
  480. * column header. datacolumn is the column from the datamodel that holds the
  481. * data for this checkbox. The data in this column must be either an integer
  482. * with values 0 or 1, or a boolean. If editable is true, this checkbox can
  483. * be interacted with, and setcellvalue() will be called with datamodelcolumn
  484. * as the column in this case.
  485. */
  486. static int lui_table_appendcheckboxcolumn(lua_State *L)
  487. {
  488. lui_object *lobj = lui_checkTable(L, 1);
  489. const char *name = luaL_checkstring(L, 2);
  490. int column = luaL_checkinteger(L, 3);
  491. int editable = lua_toboolean(L, 4) ? uiTableModelColumnAlwaysEditable : uiTableModelColumnNeverEditable;
  492. uiTableAppendCheckboxColumn(uiTable(lobj->object), name, column, editable);
  493. return 0;
  494. }
  495. /*** Method
  496. * Object: table
  497. * Name: appendcheckboxtextcolumn
  498. * Signature: tbl:appendcheckboxtextcolumn(name, ccolumn, ceditable, tcolumn, teditable = false, textcolorcolumn = nil)
  499. * appends a column that contains both a checkbox and text. ccolumn is
  500. * the data column for the checkbox, ceditable is the flag whether the
  501. * checkbox can be interacted with. tcolumn and teditable are the same for
  502. * the text, and textcolurcolumn is the optional column for the text
  503. * foreground color. The checkbox arguments work as they do for the
  504. * appendcheckboxcolumn() method, the text arguments work as they do for the
  505. * appendtextcolumn() method.
  506. */
  507. static int lui_table_appendcheckboxtextcolumn(lua_State *L)
  508. {
  509. lui_object *lobj = lui_checkTable(L, 1);
  510. const char *name = luaL_checkstring(L, 2);
  511. int ccolumn = luaL_checkinteger(L, 3);
  512. int ceditable = lua_toboolean(L, 4) ? uiTableModelColumnAlwaysEditable : uiTableModelColumnNeverEditable;
  513. int tcolumn = luaL_checkinteger(L, 5);
  514. int teditable = lua_toboolean(L, 6) ? uiTableModelColumnAlwaysEditable : uiTableModelColumnNeverEditable;
  515. int cmc = luaL_optinteger(L, 7, -1);
  516. uiTableTextColumnOptionalParams tparm = { .ColorModelColumn = cmc };
  517. uiTableAppendCheckboxTextColumn(uiTable(lobj->object), name, ccolumn, ceditable, tcolumn, teditable, &tparm);
  518. return 0;
  519. }
  520. /*** Method
  521. * Object: table
  522. * Name: appendprogressbarcolumn
  523. * Signature: tbl:appendprogressbarcolumn(name, column)
  524. * appends a column that displays a progress bar. These columns work
  525. * like lui.progressBar: a cell value of 0..100 displays that percentage,
  526. * and a cell value of -1 displays an indeterminate progress bar. The data
  527. * type to use for this column is integer.
  528. */
  529. static int lui_table_appendprogressbarcolumn(lua_State *L)
  530. {
  531. lui_object *lobj = lui_checkTable(L, 1);
  532. const char *name = luaL_checkstring(L, 2);
  533. int column = luaL_checkinteger(L, 3);
  534. uiTableAppendProgressBarColumn(uiTable(lobj->object), name, column);
  535. return 0;
  536. }
  537. /*** Method
  538. * Object: table
  539. * Name: appendbuttoncolumn
  540. * Signature: tbl:appendbuttoncolumn(name, datacolumn, clickable = false)
  541. * appends a column that shows a button that the user can click on. When
  542. * the user does click on the button, SetCellValue() is called with a nil
  543. * value and datacolumn as the column. cellvalue() on datacolumn should
  544. * return the text to show in the button.
  545. */
  546. static int lui_table_appendbuttoncolumn(lua_State *L)
  547. {
  548. lui_object *lobj = lui_checkTable(L, 1);
  549. const char *name = luaL_checkstring(L, 2);
  550. int column = luaL_checkinteger(L, 3);
  551. int clickable = lua_toboolean(L, 4) ? uiTableModelColumnAlwaysEditable : uiTableModelColumnNeverEditable;
  552. uiTableAppendButtonColumn(uiTable(lobj->object), name, column, clickable);
  553. return 0;
  554. }
  555. /* methods for table */
  556. static const luaL_Reg lui_table_methods[] = {
  557. {"appendtextcolumn", lui_table_appendtextcolumn},
  558. {"appendimagecolumn", lui_table_appendimagecolumn},
  559. {"appendimagetextcolumn", lui_table_appendimagetextcolumn},
  560. {"appendcheckboxcolumn", lui_table_appendcheckboxcolumn},
  561. {"appendcheckboxtextcolumn", lui_table_appendcheckboxtextcolumn},
  562. {"appendprogressbarcolumn", lui_table_appendprogressbarcolumn},
  563. {"appendbuttoncolumn", lui_table_appendbuttoncolumn},
  564. {0, 0}
  565. };
  566. /*** Constructor
  567. * Object: table
  568. * Name: table
  569. * TODO
  570. */
  571. static int lui_newTable(lua_State *L)
  572. {
  573. lui_object *lmodel = lui_checkTableModel(L, 1);
  574. int rbgcmc = luaL_optinteger(L, 2, -1);
  575. struct uiTableParams tparms = { .Model = lmodel->object, .RowBackgroundColorModelColumn = rbgcmc };
  576. lui_object *lobj = lui_pushTable(L);
  577. lobj->object = uiNewTable(&tparms);
  578. lui_aux_setUservalue(L, -1, "model", 1);
  579. return 1;
  580. }
  581. static const struct luaL_Reg lui_table_funcs [] ={
  582. /* utility constructors */
  583. {"tablemodel", lui_newTableModel},
  584. {"table", lui_newTable},
  585. {0, 0}
  586. };
  587. static int lui_init_table(lua_State *L)
  588. {
  589. luaL_setfuncs(L, lui_table_funcs, 0);
  590. lui_add_utility_type(L, LUI_TABLEMODEL, lui_tablemodel_methods, lui_tablemodel_meta);
  591. lui_add_control_type(L, LUI_TABLE, lui_table_methods, NULL);
  592. /* create tablemodel registry */
  593. lua_newtable(L);
  594. lua_newtable(L);
  595. lua_pushstring(L, "v");
  596. lua_setfield(L, -2, "__mode");
  597. lua_setmetatable(L, -2);
  598. lua_setfield(L, LUA_REGISTRYINDEX, LUI_TABLEMODEL_REGISTRY);
  599. return 1;
  600. }