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.
 
 
 
 

1458 lines
41 KiB

  1. /* lui.c
  2. *
  3. * lua binding to libui (https://github.com/andlabs/libui)
  4. *
  5. * Gunnar Zötl <gz@tset.de>, 2016
  6. * Released under MIT/X11 license. See file LICENSE for details.
  7. *
  8. * This file is included by lui.c
  9. */
  10. /* button control *********************************************************/
  11. /*** Object
  12. * Name: button
  13. * a button control
  14. */
  15. #define LUI_BUTTON "lui_button"
  16. #define lui_pushButton(L) lui_pushObject(L, LUI_BUTTON, 1)
  17. #define lui_checkButton(L, pos) ((lui_object*)luaL_checkudata(L, pos, LUI_BUTTON))
  18. /*** Property
  19. * Object: button
  20. * Name: text
  21. * the text on the button
  22. *** Property
  23. * Object: button
  24. * Name: onclicked
  25. * a function <code>onclicked(button)</code> that is called when the button
  26. * is clicked by the user.
  27. */
  28. static int lui_button__index(lua_State *L)
  29. {
  30. lui_object *lobj = lui_checkButton(L, 1);
  31. const char *what = luaL_checkstring(L, 2);
  32. if (strcmp(what, "text") == 0) {
  33. char *text = uiButtonText(uiButton(lobj->object));
  34. lua_pushstring(L, text);
  35. uiFreeText(text);
  36. } else if (strcmp(what, "onclicked") == 0) {
  37. lui_objectGetHandler(L, "onclicked");
  38. } else {
  39. return lui_control__index(L);
  40. }
  41. return 1;
  42. }
  43. static int lui_button__newindex(lua_State *L)
  44. {
  45. lui_object *lobj = lui_checkButton(L, 1);
  46. const char *what = luaL_checkstring(L, 2);
  47. if (strcmp(what, "text") == 0) {
  48. const char *text = luaL_checkstring(L, 3);
  49. uiButtonSetText(uiButton(lobj->object), text);
  50. } else if (strcmp(what, "onclicked") == 0) {
  51. lui_objectSetHandler(L, "onclicked", 3);
  52. } else {
  53. return lui_control__newindex(L);
  54. }
  55. return 1;
  56. }
  57. static void lui_buttonOnClickedCallback(uiButton *btn, void *data)
  58. {
  59. lua_State *L = (lua_State*) data;
  60. int top = lua_gettop(L);
  61. lui_objectHandlerCallback(L, uiControl(btn), "onclicked", top, 0, 1);
  62. lua_settop(L, top);
  63. }
  64. /*** Constructor
  65. * Object: button
  66. * Name: button
  67. * Signature: btn = lui.button(text, properties = nil)
  68. * create a new button. text is the text on the button.
  69. */
  70. static int lui_newButton(lua_State *L)
  71. {
  72. const char *text = luaL_checkstring(L, 1);
  73. int hastable = lui_aux_istable(L, 2);
  74. lui_object *lobj = lui_pushButton(L);
  75. lobj->object = uiNewButton(text);
  76. uiButtonOnClicked(uiButton(lobj->object), lui_buttonOnClickedCallback, L);
  77. if (hastable) { lui_aux_setFieldsFromTable(L, lua_gettop(L), 2); }
  78. lui_registerObject(L, lua_gettop(L));
  79. return 1;
  80. }
  81. /* metamethods for uibuttons */
  82. static const luaL_Reg lui_button_meta[] = {
  83. {"__index", lui_button__index},
  84. {"__newindex", lui_button__newindex},
  85. {0, 0}
  86. };
  87. /* entry control **********************************************************/
  88. /*** Object
  89. * Name: entry
  90. * an entry control.
  91. */
  92. #define LUI_ENTRY "lui_entry"
  93. #define lui_pushEntry(L) lui_pushObject(L, LUI_ENTRY, 1)
  94. #define lui_checkEntry(L, pos) ((lui_object*)luaL_checkudata(L, pos, LUI_ENTRY))
  95. /*** Property
  96. * Object: entry
  97. * Name: text
  98. * the text the entry contains.
  99. *** Property
  100. * Object: entry
  101. * Name: readonly
  102. * true if the entry control is / should be read only, false if not.
  103. *** Property
  104. * Object: entry
  105. * Name: onchanged
  106. * a function <code>onchanged(entry)</code> that is called when the contents
  107. * of the entry is changed by the user.
  108. */
  109. static int lui_entry__index(lua_State *L)
  110. {
  111. lui_object *lobj = lui_checkEntry(L, 1);
  112. const char *what = luaL_checkstring(L, 2);
  113. if (strcmp(what, "text") == 0) {
  114. char *text = uiEntryText(uiEntry(lobj->object));
  115. lua_pushstring(L, text);
  116. uiFreeText(text);
  117. } else if (strcmp(what, "readonly") == 0) {
  118. lua_pushboolean(L, uiEntryReadOnly(uiEntry(lobj->object)) != 0);
  119. } else if (strcmp(what, "onchanged") == 0) {
  120. lui_objectGetHandler(L, "onchanged");
  121. } else {
  122. return lui_control__index(L);
  123. }
  124. return 1;
  125. }
  126. static int lui_entry__newindex(lua_State *L)
  127. {
  128. lui_object *lobj = lui_checkEntry(L, 1);
  129. const char *what = luaL_checkstring(L, 2);
  130. if (strcmp(what, "text") == 0) {
  131. const char *text = lua_tostring(L, 3);
  132. uiEntrySetText(uiEntry(lobj->object), text);
  133. } else if (strcmp(what, "readonly") == 0) {
  134. int readonly = lua_toboolean(L, 3);
  135. uiEntrySetReadOnly(uiEntry(lobj->object), readonly);
  136. } else if (strcmp(what, "onchanged") == 0) {
  137. lui_objectSetHandler(L, "onchanged", 3);
  138. } else {
  139. return lui_control__newindex(L);
  140. }
  141. return 0;
  142. }
  143. static void lui_entryOnChangedCallback(uiEntry *btn, void *data)
  144. {
  145. lua_State *L = (lua_State*) data;
  146. int top = lua_gettop(L);
  147. lui_objectHandlerCallback(L, uiControl(btn), "onchanged", top, 0, 1);
  148. lua_settop(L, top);
  149. }
  150. static int lui_newBasicEntry(lua_State *L, uiEntry* (construct)(void))
  151. {
  152. int hastable = lui_aux_istable(L, 1);
  153. lui_object *lobj = lui_pushEntry(L);
  154. lobj->object = construct();
  155. uiEntryOnChanged(uiEntry(lobj->object), lui_entryOnChangedCallback, L);
  156. if (hastable) { lui_aux_setFieldsFromTable(L, lua_gettop(L), 1); }
  157. lui_registerObject(L, lua_gettop(L));
  158. return 1;
  159. }
  160. /*** Constructor
  161. * Object: entry
  162. * Name: entry
  163. * Signature: entry = lui.entry(properties = nil)
  164. * create a new entry control.
  165. */
  166. static int lui_newEntry(lua_State *L)
  167. {
  168. return lui_newBasicEntry(L, uiNewEntry);
  169. }
  170. /*** Constructor
  171. * Object: entry
  172. * Name: passwordentry
  173. * Signature: entry = lui.passwordentry(properties = nil)
  174. * create a new entry control that is suitable for entering passwords.
  175. */
  176. static int lui_newPasswordEntry(lua_State *L)
  177. {
  178. return lui_newBasicEntry(L, uiNewPasswordEntry);
  179. }
  180. /*** Constructor
  181. * Object: entry
  182. * Name: searchentry
  183. * Signature: entry = lui.searchentry(properties = nil)
  184. * create a new entry control that is suitable to be used as a search entry.
  185. */
  186. static int lui_newSearchEntry(lua_State *L)
  187. {
  188. return lui_newBasicEntry(L, uiNewSearchEntry);
  189. }
  190. /* metamethods for entries */
  191. static const luaL_Reg lui_entry_meta[] = {
  192. {"__index", lui_entry__index},
  193. {"__newindex", lui_entry__newindex},
  194. {0, 0}
  195. };
  196. /* checkbox control *******************************************************/
  197. /*** Object
  198. * Name: checkbox
  199. * a checkbox control.
  200. */
  201. #define LUI_CHECKBOX "lui_checkbox"
  202. #define lui_pushCheckbox(L) lui_pushObject(L, LUI_CHECKBOX, 1)
  203. #define lui_checkCheckbox(L, pos) ((lui_object*)luaL_checkudata(L, pos, LUI_CHECKBOX))
  204. /*** Property
  205. * Object: checkbox
  206. * Name: text
  207. * the label of the checkbox.
  208. *** Property
  209. * Object: checkbox
  210. * Name: checked
  211. * true if the entry is / should be chacked, false if not.
  212. *** Property
  213. * Object: checkbox
  214. * Name: ontoggled
  215. * a function <code>ontoggled(checkbox)</code> that is called when the
  216. * checkbox is toggled by the user.
  217. */
  218. static int lui_checkbox__index(lua_State *L)
  219. {
  220. lui_object *lobj = lui_checkCheckbox(L, 1);
  221. const char *what = luaL_checkstring(L, 2);
  222. if (strcmp(what, "text") == 0) {
  223. char *text = uiCheckboxText(uiCheckbox(lobj->object));
  224. lua_pushstring(L, text);
  225. uiFreeText(text);
  226. } else if (strcmp(what, "checked") == 0) {
  227. lua_pushboolean(L, uiCheckboxChecked(uiCheckbox(lobj->object)) != 0);
  228. } else if (strcmp(what, "ontoggled") == 0) {
  229. lui_objectGetHandler(L, "ontoggled");
  230. } else {
  231. return lui_control__index(L);
  232. }
  233. return 1;
  234. }
  235. static int lui_checkbox__newindex(lua_State *L)
  236. {
  237. lui_object *lobj = lui_checkCheckbox(L, 1);
  238. const char *what = luaL_checkstring(L, 2);
  239. if (strcmp(what, "text") == 0) {
  240. const char *text = lua_tostring(L, 3);
  241. uiCheckboxSetText(uiCheckbox(lobj->object), text);
  242. } else if (strcmp(what, "checked") == 0) {
  243. int checked = lua_toboolean(L, 3);
  244. uiCheckboxSetChecked(uiCheckbox(lobj->object), checked);
  245. } else if (strcmp(what, "ontoggled") == 0) {
  246. lui_objectSetHandler(L, "ontoggled", 3);
  247. } else {
  248. return lui_control__newindex(L);
  249. }
  250. return 0;
  251. }
  252. static void lui_entryOnToggledCallback(uiCheckbox *btn, void *data)
  253. {
  254. lua_State *L = (lua_State*) data;
  255. int top = lua_gettop(L);
  256. lui_objectHandlerCallback(L, uiControl(btn), "ontoggled", top, 0, 1);
  257. lua_settop(L, top);
  258. }
  259. /*** Constructor
  260. * Object: checkbox
  261. * Name: checkbox
  262. * Signature: checkbox = lui.checkbox(text, properties = nil)
  263. * create a new checkbox with label text.
  264. */
  265. static int lui_newCheckbox(lua_State *L)
  266. {
  267. const char *text = luaL_checkstring(L, 1);
  268. int hastable = lui_aux_istable(L, 2);
  269. lui_object *lobj = lui_pushCheckbox(L);
  270. lobj->object = uiNewCheckbox(text);
  271. uiCheckboxOnToggled(uiCheckbox(lobj->object), lui_entryOnToggledCallback, L);
  272. if (hastable) { lui_aux_setFieldsFromTable(L, lua_gettop(L), 2); }
  273. lui_registerObject(L, lua_gettop(L));
  274. return 1;
  275. }
  276. /* metamethods for checkboxes */
  277. static const luaL_Reg lui_checkbox_meta[] = {
  278. {"__index", lui_checkbox__index},
  279. {"__newindex", lui_checkbox__newindex},
  280. {0, 0}
  281. };
  282. /* label control **********************************************************/
  283. /*** Object
  284. * Name: label
  285. * a label control.
  286. */
  287. #define LUI_LABEL "lui_label"
  288. #define lui_pushLabel(L) lui_pushObject(L, LUI_LABEL, 1)
  289. #define lui_checkLabel(L, pos) ((lui_object*)luaL_checkudata(L, pos, LUI_LABEL))
  290. /*** Property
  291. * Object: label
  292. * Name: text
  293. * the text on the label.
  294. */
  295. static int lui_label__index(lua_State *L)
  296. {
  297. lui_object *lobj = lui_checkLabel(L, 1);
  298. const char *what = luaL_checkstring(L, 2);
  299. if (strcmp(what, "text") == 0) {
  300. char *text = uiLabelText(uiLabel(lobj->object));
  301. lua_pushstring(L, text);
  302. uiFreeText(text);
  303. } else {
  304. return lui_control__index(L);
  305. }
  306. return 1;
  307. }
  308. static int lui_label__newindex(lua_State *L)
  309. {
  310. lui_object *lobj = lui_checkLabel(L, 1);
  311. const char *what = luaL_checkstring(L, 2);
  312. if (strcmp(what, "text") == 0) {
  313. const char *text = lua_tostring(L, 3);
  314. uiLabelSetText(uiLabel(lobj->object), text);
  315. } else {
  316. return lui_control__newindex(L);
  317. }
  318. return 0;
  319. }
  320. /*** Constructor
  321. * Object: label
  322. * Name: label
  323. * Signature: label = lui.label(text)
  324. * create a new label.
  325. */
  326. static int lui_newLabel(lua_State *L)
  327. {
  328. const char *text = luaL_checkstring(L, 1);
  329. lui_object *lobj = lui_pushLabel(L);
  330. lobj->object = uiNewLabel(text);
  331. lui_registerObject(L, lua_gettop(L));
  332. return 1;
  333. }
  334. /* metamethods for labels */
  335. static const luaL_Reg lui_label_meta[] = {
  336. {"__index", lui_label__index},
  337. {"__newindex", lui_label__newindex},
  338. {0, 0}
  339. };
  340. /* spinbox control ********************************************************/
  341. /*** Object
  342. * Name: spinbox
  343. * a spinbox control.
  344. */
  345. #define LUI_SPINBOX "lui_spinbox"
  346. #define lui_pushSpinbox(L) lui_pushObject(L, LUI_SPINBOX, 1)
  347. #define lui_checkSpinbox(L, pos) ((lui_object*)luaL_checkudata(L, pos, LUI_SPINBOX))
  348. /*** Property
  349. * Object: spinbox
  350. * Name: value
  351. * the current value of the spinbox control.
  352. *** Property
  353. * Object: spinbox
  354. * Name: onchanged
  355. * a function <code>function(spinbox)</code> that is called when the value
  356. * of the spinbox is changed by the user.
  357. */
  358. static int lui_spinbox__index(lua_State *L)
  359. {
  360. lui_object *lobj = lui_checkSpinbox(L, 1);
  361. const char *what = luaL_checkstring(L, 2);
  362. if (strcmp(what, "value") == 0) {
  363. lua_pushinteger(L, uiSpinboxValue(uiSpinbox(lobj->object)));
  364. } else if (strcmp(what, "onchanged") == 0) {
  365. lui_objectGetHandler(L, "onchanged");
  366. } else {
  367. return lui_control__index(L);
  368. }
  369. return 1;
  370. }
  371. static int lui_spinbox__newindex(lua_State *L)
  372. {
  373. lui_object *lobj = lui_checkSpinbox(L, 1);
  374. const char *what = luaL_checkstring(L, 2);
  375. if (strcmp(what, "value") == 0) {
  376. int value = luaL_checkinteger(L, 3);
  377. uiSpinboxSetValue(uiSpinbox(lobj->object), value);
  378. } else if (strcmp(what, "onchanged") == 0) {
  379. lui_objectSetHandler(L, "onchanged", 3);
  380. } else {
  381. return lui_control__newindex(L);
  382. }
  383. return 0;
  384. }
  385. static void lui_spinboxOnChangedCallback(uiSpinbox *spb, void *data)
  386. {
  387. lua_State *L = (lua_State*) data;
  388. int top = lua_gettop(L);
  389. lui_objectHandlerCallback(L, uiControl(spb), "onchanged", top, 0, 1);
  390. lua_settop(L, top);
  391. }
  392. /*** Constructor
  393. * Object: spinbox
  394. * Name: spinbox
  395. * Signature: spinbox = lui.spinbox(min, max, properties = nil)
  396. * create a new spinbox where the value can be changed between integers min
  397. * and max (both inclusive).
  398. */
  399. static int lui_newSpinbox(lua_State *L)
  400. {
  401. int min = luaL_checkinteger(L, 1);
  402. int max = luaL_checkinteger(L, 2);
  403. int hastable = lui_aux_istable(L, 3);
  404. lui_object *lobj = lui_pushSpinbox(L);
  405. lobj->object = uiNewSpinbox(min, max);
  406. uiSpinboxOnChanged(uiSpinbox(lobj->object), lui_spinboxOnChangedCallback, L);
  407. if (hastable) { lui_aux_setFieldsFromTable(L, lua_gettop(L), 3); }
  408. lui_registerObject(L, lua_gettop(L));
  409. return 1;
  410. }
  411. /* metamethods for groups */
  412. static const luaL_Reg lui_spinbox_meta[] = {
  413. {"__index", lui_spinbox__index},
  414. {"__newindex", lui_spinbox__newindex},
  415. {0, 0}
  416. };
  417. /* progressbar control ****************************************************/
  418. /*** Object
  419. * Name: progressbar
  420. * a progressbar control.
  421. */
  422. #define LUI_PROGRESSBAR "lui_progressbar"
  423. #define lui_pushProgressbar(L) lui_pushObject(L, LUI_PROGRESSBAR, 1)
  424. #define lui_checkProgressbar(L, pos) ((lui_object*)luaL_checkudata(L, pos, LUI_PROGRESSBAR))
  425. /*** Property
  426. * Object: progressbar
  427. * Name: value
  428. * the value (0-100) of the progress bar. Set to -1 for an indeterminate
  429. * value.
  430. */
  431. static int lui_progressbar__index(lua_State *L)
  432. {
  433. lui_object *lobj = lui_checkProgressbar(L, 1);
  434. const char *what = luaL_checkstring(L, 2);
  435. if (strcmp(what, "value") == 0) {
  436. lua_pushinteger(L, uiProgressBarValue(uiProgressBar(lobj->object)));
  437. } else {
  438. return lui_control__index(L);
  439. }
  440. return 1;
  441. }
  442. static int lui_progressbar__newindex(lua_State *L)
  443. {
  444. lui_object *lobj = lui_checkProgressbar(L, 1);
  445. const char *what = luaL_checkstring(L, 2);
  446. if (strcmp(what, "value") == 0) {
  447. int value = luaL_checkinteger(L, 3);
  448. if (value < 0 || value > 100) {
  449. value = -1;
  450. }
  451. uiProgressBarSetValue(uiProgressBar(lobj->object), value);
  452. } else {
  453. return lui_control__newindex(L);
  454. }
  455. return 0;
  456. }
  457. /*** Constructor
  458. * Object: progressbar
  459. * Name: progressbar
  460. * Signature: progressbar = lui.progressbar(properties = nil)
  461. * create a new progressbar control.
  462. */
  463. static int lui_newProgressbar(lua_State *L)
  464. {
  465. int hastable = lui_aux_istable(L, 1);
  466. lui_object *lobj = lui_pushProgressbar(L);
  467. lobj->object = uiNewProgressBar();
  468. lua_pushinteger(L, 0);
  469. lui_aux_setUservalue(L, lua_gettop(L) - 1, "value", lua_gettop(L));
  470. lua_pop(L, 1);
  471. if (hastable) { lui_aux_setFieldsFromTable(L, lua_gettop(L), 1); }
  472. lui_registerObject(L, lua_gettop(L));
  473. return 1;
  474. }
  475. /* metamethods for groups */
  476. static const luaL_Reg lui_progressbar_meta[] = {
  477. {"__index", lui_progressbar__index},
  478. {"__newindex", lui_progressbar__newindex},
  479. {0, 0}
  480. };
  481. /* slider control *********************************************************/
  482. /*** Object
  483. * Name: slider
  484. * a slider control.
  485. */
  486. #define LUI_SLIDER "lui_slider"
  487. #define lui_pushSlider(L) lui_pushObject(L, LUI_SLIDER, 1)
  488. #define lui_checkSlider(L, pos) ((lui_object*)luaL_checkudata(L, pos, LUI_SLIDER))
  489. /*** Property
  490. * Object: slider
  491. * Name: value
  492. * the value of the slider.
  493. *** Property
  494. * Object: slider
  495. * Name: onchanged
  496. * a function <code>onchanged(slider)</code> that is called when the value of
  497. * the slider is changed by the user.
  498. */
  499. static int lui_slider__index(lua_State *L)
  500. {
  501. lui_object *lobj = lui_checkSlider(L, 1);
  502. const char *what = luaL_checkstring(L, 2);
  503. if (strcmp(what, "value") == 0) {
  504. lua_pushinteger(L, uiSliderValue(uiSlider(lobj->object)));
  505. } else if (strcmp(what, "onchanged") == 0) {
  506. lui_objectGetHandler(L, "onchanged");
  507. } else {
  508. return lui_control__index(L);
  509. }
  510. return 1;
  511. }
  512. static int lui_slider__newindex(lua_State *L)
  513. {
  514. lui_object *lobj = lui_checkSlider(L, 1);
  515. const char *what = luaL_checkstring(L, 2);
  516. if (strcmp(what, "value") == 0) {
  517. int value = luaL_checkinteger(L, 3);
  518. uiSliderSetValue(uiSlider(lobj->object), value);
  519. } else if (strcmp(what, "onchanged") == 0) {
  520. lui_objectSetHandler(L, "onchanged", 3);
  521. } else {
  522. return lui_control__newindex(L);
  523. }
  524. return 0;
  525. }
  526. static void lui_sliderOnChangedCallback(uiSlider *spb, void *data)
  527. {
  528. lua_State *L = (lua_State*) data;
  529. int top = lua_gettop(L);
  530. lui_objectHandlerCallback(L, uiControl(spb), "onchanged", top, 0, 1);
  531. lua_settop(L, top);
  532. }
  533. /*** Constructor
  534. * Object: slider
  535. * Name: slider
  536. * Signature: slider = lui.slider(min, max, properties = nil)
  537. * create a new slider where the value can be changed between integers min
  538. * and max.
  539. */
  540. static int lui_newSlider(lua_State *L)
  541. {
  542. int min = luaL_checkinteger(L, 1);
  543. int max = luaL_checkinteger(L, 2);
  544. int hastable = lui_aux_istable(L, 3);
  545. lui_object *lobj = lui_pushSlider(L);
  546. lobj->object = uiNewSlider(min, max);
  547. uiSliderOnChanged(uiSlider(lobj->object), lui_sliderOnChangedCallback, L);
  548. if (hastable) { lui_aux_setFieldsFromTable(L, lua_gettop(L), 3); }
  549. lui_registerObject(L, lua_gettop(L));
  550. return 1;
  551. }
  552. /* metamethods for groups */
  553. static const luaL_Reg lui_slider_meta[] = {
  554. {"__index", lui_slider__index},
  555. {"__newindex", lui_slider__newindex},
  556. {0, 0}
  557. };
  558. /* separator control ******************************************************/
  559. /*** Object
  560. * Name: separator
  561. * a separator control
  562. */
  563. #define LUI_SEPARATOR "lui_separator"
  564. #define lui_pushSeparator(L) lui_pushObject(L, LUI_SEPARATOR, 1)
  565. static int lui_newSeparator(lua_State *L, int isvertical)
  566. {
  567. lui_object *lobj = lui_pushSeparator(L);
  568. lobj->object = isvertical ? uiNewVerticalSeparator() : uiNewHorizontalSeparator();
  569. lui_registerObject(L, lua_gettop(L));
  570. return 1;
  571. }
  572. /*** Constructor
  573. * Object: separator
  574. * Name: hseparator
  575. * Signature: separator = lui.hseparator(vertical = false)
  576. * create a new horizontal separator control.
  577. */
  578. static int lui_newHSeparator(lua_State *L)
  579. {
  580. return lui_newSeparator(L, 0);
  581. }
  582. /*** Constructor
  583. * Object: separator
  584. * Name: vseparator
  585. * Signature: separator = lui.vseparator(vertical = false)
  586. * create a new vertical separator control.
  587. */
  588. static int lui_newVSeparator(lua_State *L)
  589. {
  590. return lui_newSeparator(L, 0);
  591. }
  592. /* combobox control *******************************************************/
  593. /*** Object
  594. * Name: combobox
  595. * a combobox control.
  596. */
  597. #define LUI_COMBOBOX "lui_combobox"
  598. #define lui_pushCombobox(L) lui_pushObject(L, LUI_COMBOBOX, 1)
  599. #define lui_checkCombobox(L, pos) ((lui_object*)luaL_checkudata(L, pos, LUI_COMBOBOX))
  600. /*** Property
  601. * Object: combobox
  602. * Name: selected
  603. * the index of the selected option.
  604. *** Property
  605. * Object: combobox
  606. * Name: text
  607. * the text of the selected option. This is a read-only property.
  608. *** Property
  609. * Object: combobox
  610. * Name: onselected
  611. * a function <code>onselected(combobox)</code> that is called when the value
  612. * of the combobox is changed by the user.
  613. */
  614. static int lui_combobox__index(lua_State *L)
  615. {
  616. lui_object *lobj = lui_checkCombobox(L, 1);
  617. const char *what = luaL_checkstring(L, 2);
  618. if (strcmp(what, "selected") == 0) {
  619. int selected = uiComboboxSelected(uiCombobox(lobj->object)) + 1;
  620. if (selected == 0) {
  621. lua_pushnil(L);
  622. } else {
  623. lua_pushinteger(L, selected);
  624. }
  625. } else if (strcmp(what, "text") == 0) {
  626. int which = uiComboboxSelected(uiCombobox(lobj->object)) + 1;
  627. if (which > 0) {
  628. if (lui_aux_getUservalue(L, 1, "values") != LUA_TNIL) {
  629. lua_rawgeti(L, -1, which);
  630. }
  631. }
  632. } else if (strcmp(what, "onselected") == 0) {
  633. lui_objectGetHandler(L, "onselected");
  634. } else {
  635. return lui_control__index(L);
  636. }
  637. return 1;
  638. }
  639. static int lui_combobox__newindex(lua_State *L)
  640. {
  641. lui_object *lobj = lui_checkCombobox(L, 1);
  642. const char *what = luaL_checkstring(L, 2);
  643. if (strcmp(what, "selected") == 0) {
  644. int value = luaL_checkinteger(L, 3) - 1;
  645. uiComboboxSetSelected(uiCombobox(lobj->object), value);
  646. } else if (strcmp(what, "onselected") == 0) {
  647. lui_objectSetHandler(L, "onselected", 3);
  648. } else {
  649. return lui_control__newindex(L);
  650. }
  651. return 0;
  652. }
  653. /*** Method
  654. * Object: combobox
  655. * Name: append
  656. * Signature: combobox:append(entry, ...)
  657. * append one or more entries to a combobox.
  658. */
  659. static int lui_comboboxAppend(lua_State *L)
  660. {
  661. lui_object *lobj = lui_checkCombobox(L, 1);
  662. const char *text = lua_tostring(L, 2);
  663. if (lui_aux_getUservalue(L, 1, "values") == LUA_TNIL) {
  664. lua_pop(L, 1);
  665. lua_newtable(L);
  666. }
  667. int tbl = lua_gettop(L);
  668. uiComboboxAppend(uiCombobox(lobj->object), text);
  669. lui_aux_tinsert(L, tbl, -1, 2);
  670. for (int i = 3; i < tbl; ++i) {
  671. text = lua_tostring(L, i);
  672. uiComboboxAppend(uiCombobox(lobj->object), text);
  673. lui_aux_tinsert(L, tbl, -1, i);
  674. }
  675. lui_aux_setUservalue(L, 1, "values", tbl);
  676. lua_pop(L, 1);
  677. return 0;
  678. }
  679. static void lui_comboboxOnSelectedCallback(uiCombobox *spb, void *data)
  680. {
  681. lua_State *L = (lua_State*) data;
  682. int top = lua_gettop(L);
  683. lui_objectHandlerCallback(L, uiControl(spb), "onselected", top, 0, 1);
  684. lua_settop(L, top);
  685. }
  686. /*** Constructor
  687. * Object: combobox
  688. * Name: combobox
  689. * Signature: combobox = lui.combobox(properties = nil)
  690. * create a new combobox control.
  691. */
  692. static int lui_newCombobox(lua_State *L)
  693. {
  694. int hastable = lui_aux_istable(L, 1);
  695. lui_object *lobj = lui_pushCombobox(L);
  696. lobj->object = uiNewCombobox();
  697. uiComboboxOnSelected(uiCombobox(lobj->object), lui_comboboxOnSelectedCallback, L);
  698. if (hastable) { lui_aux_setFieldsFromTable(L, lua_gettop(L), 1); }
  699. lui_registerObject(L, lua_gettop(L));
  700. return 1;
  701. }
  702. /* metamethods for comboboxes */
  703. static const luaL_Reg lui_combobox_meta[] = {
  704. {"__index", lui_combobox__index},
  705. {"__newindex", lui_combobox__newindex},
  706. {0, 0}
  707. };
  708. /* methods for comboboxes */
  709. static const luaL_Reg lui_combobox_methods[] = {
  710. {"append", lui_comboboxAppend},
  711. {0, 0}
  712. };
  713. /* editable combobox control **********************************************/
  714. /*** Object
  715. * Name: editablecombobox
  716. * an editable combobox control.
  717. */
  718. #define LUI_EDITABLECOMBOBOX "lui_editablecombobox"
  719. #define lui_pushEditableCombobox(L) lui_pushObject(L, LUI_EDITABLECOMBOBOX, 1)
  720. #define lui_checkEditableCombobox(L, pos) ((lui_object*)luaL_checkudata(L, pos, LUI_EDITABLECOMBOBOX))
  721. /*** Property
  722. * Object: editablecombobox
  723. * Name: text
  724. * the current value of the editable combobox.
  725. *** Property
  726. * Object: editablecombobox
  727. * Name: onchanged
  728. * a function <code>onchanged(editablecombobox)</code> that is called when
  729. * the value of the editable combobox is changed by the user.
  730. */
  731. static int lui_editableCombobox__index(lua_State *L)
  732. {
  733. lui_object *lobj = lui_checkEditableCombobox(L, 1);
  734. const char *what = luaL_checkstring(L, 2);
  735. if (strcmp(what, "text") == 0) {
  736. char *text = uiEditableComboboxText(uiEditableCombobox(lobj->object));
  737. lua_pushstring(L, text);
  738. uiFreeText(text);
  739. } else if (strcmp(what, "onchanged") == 0) {
  740. lui_objectGetHandler(L, "onchanged");
  741. } else {
  742. return lui_control__index(L);
  743. }
  744. return 1;
  745. }
  746. static int lui_editableCombobox__newindex(lua_State *L)
  747. {
  748. lui_object *lobj = lui_checkEditableCombobox(L, 1);
  749. const char *what = luaL_checkstring(L, 2);
  750. if (strcmp(what, "text") == 0) {
  751. const char *text = luaL_checkstring(L, 3);
  752. uiEditableComboboxSetText(uiEditableCombobox(lobj->object), text);
  753. } else if (strcmp(what, "onchanged") == 0) {
  754. lui_objectSetHandler(L, "onchanged", 3);
  755. } else {
  756. return lui_control__newindex(L);
  757. }
  758. return 0;
  759. }
  760. /*** Method
  761. * Object: editablecombobox
  762. * Name: append
  763. * Signature: editablecombobox:append(entry, ...)
  764. * append one or more entries to an editable combobox.
  765. */
  766. static int lui_editableComboboxAppend(lua_State *L)
  767. {
  768. lui_object *lobj = lui_checkEditableCombobox(L, 1);
  769. const char *text = lua_tostring(L, 2);
  770. uiEditableComboboxAppend(uiEditableCombobox(lobj->object), text);
  771. for (int i = 3; i <= lua_gettop(L); ++i) {
  772. text = lua_tostring(L, i);
  773. uiEditableComboboxAppend(uiEditableCombobox(lobj->object), text);
  774. }
  775. return 0;
  776. }
  777. static void lui_editableComboboxOnChangedCallback(uiEditableCombobox *spb, void *data)
  778. {
  779. lua_State *L = (lua_State*) data;
  780. int top = lua_gettop(L);
  781. lui_objectHandlerCallback(L, uiControl(spb), "onchanged", top, 0, 1);
  782. lua_settop(L, top);
  783. }
  784. /*** Constructor
  785. * Object: editablecombobox
  786. * Name: editablecombobox
  787. * Signature: editablecombobox = lui.editablecombobox(properties = nil)
  788. * create a new editable combobox.
  789. */
  790. static int lui_newEditableCombobox(lua_State *L)
  791. {
  792. int hastable = lui_aux_istable(L, 1);
  793. lui_object *lobj = lui_pushEditableCombobox(L);
  794. lobj->object = uiNewEditableCombobox();
  795. uiEditableComboboxOnChanged(uiEditableCombobox(lobj->object), lui_editableComboboxOnChangedCallback, L);
  796. if (hastable) { lui_aux_setFieldsFromTable(L, lua_gettop(L), 1); }
  797. lui_registerObject(L, lua_gettop(L));
  798. return 1;
  799. }
  800. /* metamethods for editable comboboxes */
  801. static const luaL_Reg lui_editableCombobox_meta[] = {
  802. {"__index", lui_editableCombobox__index},
  803. {"__newindex", lui_editableCombobox__newindex},
  804. {0, 0}
  805. };
  806. /* methods for editable comboboxes */
  807. static const luaL_Reg lui_editableCombobox_methods[] = {
  808. {"append", lui_editableComboboxAppend},
  809. {0, 0}
  810. };
  811. /* radio controls *********************************************************/
  812. /*** Object
  813. * Name: radiobuttons
  814. * a radiobuttons control.
  815. */
  816. #define LUI_RADIOBUTTONS "lui_radiobuttons"
  817. #define lui_pushRadiobuttons(L) lui_pushObject(L, LUI_RADIOBUTTONS, 1)
  818. #define lui_checkRadiobuttons(L, pos) ((lui_object*)luaL_checkudata(L, pos, LUI_RADIOBUTTONS))
  819. /*** Property
  820. * Object: radiobuttons
  821. * Name: selected
  822. * the index of the selected option.
  823. *** Property
  824. * Object: radiobuttons
  825. * Name: text
  826. * the text of the selected option. This is a read-only property.
  827. *** Property
  828. * Object: radiobuttons
  829. * Name: onselected
  830. * a function <code>onselected(radiobuttons)</code> that is called when the
  831. * value of the radiobuttons is changed by the user.
  832. */
  833. static int lui_radiobuttons__index(lua_State *L)
  834. {
  835. lui_object *lobj = lui_checkRadiobuttons(L, 1);
  836. const char *what = luaL_checkstring(L, 2);
  837. if (strcmp(what, "selected") == 0) {
  838. int selected = uiRadioButtonsSelected(uiRadioButtons(lobj->object)) + 1;
  839. if (selected == 0) {
  840. lua_pushnil(L);
  841. } else {
  842. lua_pushinteger(L, selected);
  843. }
  844. } else if (strcmp(what, "text") == 0) {
  845. int which = uiRadioButtonsSelected(uiRadioButtons(lobj->object)) + 1;
  846. if (which > 0) {
  847. if (lui_aux_getUservalue(L, 1, "values") != LUA_TNIL) {
  848. lua_rawgeti(L, -1, which);
  849. }
  850. }
  851. } else if (strcmp(what, "onselected") == 0) {
  852. lui_objectGetHandler(L, "onselected");
  853. } else {
  854. return lui_control__index(L);
  855. }
  856. return 1;
  857. }
  858. static int lui_radiobuttons__newindex(lua_State *L)
  859. {
  860. lui_object *lobj = lui_checkRadiobuttons(L, 1);
  861. const char *what = luaL_checkstring(L, 2);
  862. if (strcmp(what, "selected") == 0) {
  863. int selected = luaL_checkinteger(L, 3) - 1;
  864. uiRadioButtonsSetSelected(uiRadioButtons(lobj->object), selected);
  865. } else if (strcmp(what, "onselected") == 0) {
  866. lui_objectSetHandler(L, "onselected", 3);
  867. } else {
  868. return lui_control__newindex(L);
  869. }
  870. return 0;
  871. }
  872. /*** Method
  873. * Object: radiobuttons
  874. * Name: append
  875. * Signature: radiobuttons:append(option, ...)
  876. * append one or more options to a radiobuttons control.
  877. */
  878. static int lui_radiobuttonsAppend(lua_State *L)
  879. {
  880. lui_object *lobj = lui_checkRadiobuttons(L, 1);
  881. const char *text = lua_tostring(L, 2);
  882. if (lui_aux_getUservalue(L, 1, "values") == LUA_TNIL) {
  883. lua_pop(L, 1);
  884. lua_newtable(L);
  885. }
  886. int tbl = lua_gettop(L);
  887. uiRadioButtonsAppend(uiRadioButtons(lobj->object), text);
  888. lui_aux_tinsert(L, tbl, -1, 2);
  889. for (int i = 3; i < tbl; ++i) {
  890. text = lua_tostring(L, i);
  891. uiRadioButtonsAppend(uiRadioButtons(lobj->object), text);
  892. lui_aux_tinsert(L, tbl, -1, i);
  893. }
  894. lui_aux_setUservalue(L, 1, "values", tbl);
  895. lua_pop(L, 1);
  896. return 0;
  897. }
  898. static void lui_radiobuttonsOnSelectedCallback(uiRadioButtons *spb, void *data)
  899. {
  900. lua_State *L = (lua_State*) data;
  901. int top = lua_gettop(L);
  902. lui_objectHandlerCallback(L, uiControl(spb), "onselected", top, 0, 1);
  903. lua_settop(L, top);
  904. }
  905. /*** Constructor
  906. * Object: radiobuttons
  907. * Name: radiobuttons
  908. * Signature: radiobuttons = lui.radiobuttons()
  909. * create a radiobuttons control.
  910. */
  911. static int lui_newRadiobuttons(lua_State *L)
  912. {
  913. int hastable = lui_aux_istable(L, 1);
  914. lui_object *lobj = lui_pushRadiobuttons(L);
  915. lobj->object = uiNewRadioButtons();
  916. uiRadioButtonsOnSelected(uiRadioButtons(lobj->object), lui_radiobuttonsOnSelectedCallback, L);
  917. if (hastable) { lui_aux_setFieldsFromTable(L, lua_gettop(L), 1); }
  918. lui_registerObject(L, lua_gettop(L));
  919. return 1;
  920. }
  921. /* metamethods for radiobuttons */
  922. static const luaL_Reg lui_radiobuttons_meta[] = {
  923. {"__index", lui_radiobuttons__index},
  924. {"__newindex", lui_radiobuttons__newindex},
  925. {0, 0}
  926. };
  927. /* methods for radiobuttons */
  928. static const luaL_Reg lui_radiobuttons_methods[] = {
  929. {"append", lui_radiobuttonsAppend},
  930. {0, 0}
  931. };
  932. /* datetime picker ********************************************************/
  933. /*** Object
  934. * Name: datetimepicker
  935. * a date / time picker control.
  936. */
  937. #define LUI_DATETIMEPICKER "lui_datetimepicker"
  938. #define lui_pushDatetimepicker(L) lui_pushObject(L, LUI_DATETIMEPICKER, 1)
  939. #define lui_checkDatetimepicker(L, pos) ((lui_object*)luaL_checkudata(L, pos, LUI_DATETIMEPICKER))
  940. /*** Property
  941. * Object: datetimepicker
  942. * Name: day
  943. * the selected day, range from 1-31
  944. *** Property
  945. * Object: datetimepicker
  946. * Name: mon
  947. * the selected month, range from 1-12
  948. *** Property
  949. * Object: datetimepicker
  950. * Name: year
  951. * the selected year
  952. *** Property
  953. * Object: datetimepicker
  954. * Name: hour
  955. * the selected hour, range from 0-23
  956. *** Property
  957. * Object: datetimepicker
  958. * Name: min
  959. * the selected minute, range from 0-63
  960. *** Property
  961. * Object: datetimepicker
  962. * Name: sec
  963. * thee selected second, range from 0-63
  964. *** Property
  965. * Object: datetimepicker
  966. * Name: date
  967. * a table with fields day, mon, year
  968. *** Property
  969. * Object: datetimepicker
  970. * Name: time
  971. * a table with fields hour, min, sec
  972. *** Property
  973. * Object: datetimepicker
  974. * Name: datetime
  975. * a table with fields day, mon, year, hour, min, sec
  976. *** Property
  977. * Object: datetimepicker
  978. * Name: onchanged
  979. * a function <code>onchanged(datetimepicker)</code> that is called when the
  980. * contents of the datetimepicker is changed by the user.
  981. */
  982. static int lui_dateTimePicker__index(lua_State *L)
  983. {
  984. lui_object *lobj = lui_checkDatetimepicker(L, 1);
  985. const char *what = luaL_checkstring(L, 2);
  986. struct tm datetime;
  987. uiDateTimePickerTime(uiDateTimePicker(lobj->object), &datetime);
  988. if (strcmp(what, "day") == 0) {
  989. lua_pushinteger(L, datetime.tm_wday);
  990. } else if (strcmp(what, "mon") == 0) {
  991. lua_pushinteger(L, datetime.tm_mon + 1);
  992. } else if (strcmp(what, "year") == 0) {
  993. lua_pushinteger(L, datetime.tm_year + 1900);
  994. } else if (strcmp(what, "hour") == 0) {
  995. lua_pushinteger(L, datetime.tm_hour);
  996. } else if (strcmp(what, "min") == 0) {
  997. lua_pushinteger(L, datetime.tm_min);
  998. } else if (strcmp(what, "sec") == 0) {
  999. lua_pushinteger(L, datetime.tm_sec);
  1000. } else if (strcmp(what, "date") == 0) {
  1001. lua_newtable(L);
  1002. lua_pushinteger(L, datetime.tm_wday);
  1003. lua_setfield(L, -2, "day");
  1004. lua_pushinteger(L, datetime.tm_mon + 1);
  1005. lua_setfield(L, -2, "mon");
  1006. lua_pushinteger(L, datetime.tm_year + 1900);
  1007. lua_setfield(L, -2, "year");
  1008. } else if (strcmp(what, "time") == 0) {
  1009. lua_newtable(L);
  1010. lua_pushinteger(L, datetime.tm_hour);
  1011. lua_setfield(L, -2, "hour");
  1012. lua_pushinteger(L, datetime.tm_min);
  1013. lua_setfield(L, -2, "min");
  1014. lua_pushinteger(L, datetime.tm_sec);
  1015. lua_setfield(L, -2, "sec");
  1016. } else if (strcmp(what, "datetime") == 0) {
  1017. lua_newtable(L);
  1018. lua_pushinteger(L, datetime.tm_wday);
  1019. lua_setfield(L, -2, "day");
  1020. lua_pushinteger(L, datetime.tm_mon + 1);
  1021. lua_setfield(L, -2, "mon");
  1022. lua_pushinteger(L, datetime.tm_year + 1900);
  1023. lua_setfield(L, -2, "year");
  1024. lua_pushinteger(L, datetime.tm_hour);
  1025. lua_setfield(L, -2, "hour");
  1026. lua_pushinteger(L, datetime.tm_min);
  1027. lua_setfield(L, -2, "min");
  1028. lua_pushinteger(L, datetime.tm_sec);
  1029. lua_setfield(L, -2, "sec");
  1030. } else if (strcmp(what, "onchanged") == 0) {
  1031. lui_objectGetHandler(L, "onchanged");
  1032. } else {
  1033. return lui_control__index(L);
  1034. }
  1035. return 1;
  1036. }
  1037. static int lui_dateTimePicker__newindex(lua_State *L)
  1038. {
  1039. lui_object *lobj = lui_checkDatetimepicker(L, 1);
  1040. const char *what = luaL_checkstring(L, 2);
  1041. struct tm datetime;
  1042. uiDateTimePickerTime(uiDateTimePicker(lobj->object), &datetime);
  1043. if (strcmp(what, "day") == 0) {
  1044. datetime.tm_wday = luaL_checkinteger(L, 3);
  1045. } else if (strcmp(what, "mon") == 0) {
  1046. datetime.tm_mon = luaL_checkinteger(L, 3) - 1;
  1047. } else if (strcmp(what, "year") == 0) {
  1048. datetime.tm_year = luaL_checkinteger(L, 3) - 1900;
  1049. } else if (strcmp(what, "hour") == 0) {
  1050. datetime.tm_hour = luaL_checkinteger(L, 3);
  1051. } else if (strcmp(what, "min") == 0) {
  1052. datetime.tm_min = luaL_checkinteger(L, 3);
  1053. } else if (strcmp(what, "sec") == 0) {
  1054. datetime.tm_sec = luaL_checkinteger(L, 3);
  1055. } else if (strcmp(what, "date") == 0) {
  1056. luaL_checktype(L, 3, LUA_TTABLE);
  1057. lua_getfield(L, 3, "day");
  1058. datetime.tm_wday = luaL_checkinteger(L, -1);
  1059. lua_pop(L, 1);
  1060. lua_getfield(L, 3, "mon");
  1061. datetime.tm_mon = luaL_checkinteger(L, -1) - 1;
  1062. lua_pop(L, 1);
  1063. lua_getfield(L, 3, "year");
  1064. datetime.tm_year = luaL_checkinteger(L, -1) - 1900;
  1065. lua_pop(L, 1);
  1066. } else if (strcmp(what, "time") == 0) {
  1067. luaL_checktype(L, 3, LUA_TTABLE);
  1068. lua_getfield(L, 3, "hour");
  1069. datetime.tm_hour = luaL_checkinteger(L, -1);
  1070. lua_pop(L, 1);
  1071. lua_getfield(L, 3, "min");
  1072. datetime.tm_min = luaL_checkinteger(L, -1);
  1073. lua_pop(L, 1);
  1074. lua_getfield(L, 3, "sec");
  1075. datetime.tm_sec = luaL_checkinteger(L, -1);
  1076. lua_pop(L, 1);
  1077. } else if (strcmp(what, "datetime") == 0) {
  1078. luaL_checktype(L, 3, LUA_TTABLE);
  1079. lua_getfield(L, 3, "day");
  1080. datetime.tm_wday = luaL_checkinteger(L, -1);
  1081. lua_pop(L, 1);
  1082. lua_getfield(L, 3, "mon");
  1083. datetime.tm_mon = luaL_checkinteger(L, -1) - 1;
  1084. lua_pop(L, 1);
  1085. lua_getfield(L, 3, "year");
  1086. datetime.tm_year = luaL_checkinteger(L, -1) - 1900;
  1087. lua_pop(L, 1);
  1088. lua_getfield(L, 3, "hour");
  1089. datetime.tm_hour = luaL_checkinteger(L, -1);
  1090. lua_pop(L, 1);
  1091. lua_getfield(L, 3, "min");
  1092. datetime.tm_min = luaL_checkinteger(L, -1);
  1093. lua_pop(L, 1);
  1094. lua_getfield(L, 3, "sec");
  1095. datetime.tm_sec = luaL_checkinteger(L, -1);
  1096. lua_pop(L, 1);
  1097. } else if (strcmp(what, "onchanged") == 0) {
  1098. lui_objectSetHandler(L, "onchanged", 3);
  1099. } else {
  1100. return lui_control__newindex(L);
  1101. }
  1102. uiDateTimePickerSetTime(uiDateTimePicker(lobj->object), &datetime);
  1103. return 0;
  1104. }
  1105. static void lui_dateTimePickerOnChangedCallback(uiDateTimePicker *dtp, void *data)
  1106. {
  1107. lua_State *L = (lua_State*) data;
  1108. int top = lua_gettop(L);
  1109. lui_objectHandlerCallback(L, uiControl(dtp), "onchanged", top, 0, 1);
  1110. lua_settop(L, top);
  1111. }
  1112. /*** Constructor
  1113. * Object: datetimepicker
  1114. * Name: datetimepicker
  1115. * Signature: datetimepicker = lui.datetimepicker()
  1116. */
  1117. static int lui_newDatetimepicker(lua_State *L)
  1118. {
  1119. int hastable = lui_aux_istable(L, 1);
  1120. lui_object *lobj = lui_pushDatetimepicker(L);
  1121. lobj->object = uiNewDateTimePicker();
  1122. uiDateTimePickerOnChanged(uiDateTimePicker(lobj->object), lui_dateTimePickerOnChangedCallback, L);
  1123. if (hastable) { lui_aux_setFieldsFromTable(L, lua_gettop(L), 1); }
  1124. lui_registerObject(L, lua_gettop(L));
  1125. return 1;
  1126. }
  1127. /*** Constructor
  1128. * Object: datetimepicker
  1129. * Name: datepicker
  1130. * Signature: datetimepicker = lui.datepicker()
  1131. */
  1132. static int lui_newDatepicker(lua_State *L)
  1133. {
  1134. int hastable = lui_aux_istable(L, 1);
  1135. lui_object *lobj = lui_pushDatetimepicker(L);
  1136. lobj->object = uiNewDatePicker();
  1137. uiDateTimePickerOnChanged(uiDateTimePicker(lobj->object), lui_dateTimePickerOnChangedCallback, L);
  1138. if (hastable) { lui_aux_setFieldsFromTable(L, lua_gettop(L), 1); }
  1139. lui_registerObject(L, lua_gettop(L));
  1140. return 1;
  1141. }
  1142. /*** Constructor
  1143. * Object: datetimepicker
  1144. * Name: timepicker
  1145. * Signature: datetimepicker = lui.timepicker()
  1146. */
  1147. static int lui_newTimepicker(lua_State *L)
  1148. {
  1149. int hastable = lui_aux_istable(L, 1);
  1150. lui_object *lobj = lui_pushDatetimepicker(L);
  1151. lobj->object = uiNewTimePicker();
  1152. uiDateTimePickerOnChanged(uiDateTimePicker(lobj->object), lui_dateTimePickerOnChangedCallback, L);
  1153. if (hastable) { lui_aux_setFieldsFromTable(L, lua_gettop(L), 1); }
  1154. lui_registerObject(L, lua_gettop(L));
  1155. return 1;
  1156. }
  1157. /* metamethods for dateTimePicker */
  1158. static const luaL_Reg lui_dateTimePicker_meta[] = {
  1159. {"__index", lui_dateTimePicker__index},
  1160. {"__newindex", lui_dateTimePicker__newindex},
  1161. {0, 0}
  1162. };
  1163. /* multiline entry control ************************************************/
  1164. /*** Object
  1165. * Name: multilineentry
  1166. * a multiline entry control
  1167. */
  1168. #define LUI_MULTILINEENTRY "lui_multilineentry"
  1169. #define lui_pushMultilineEntry(L) lui_pushObject(L, LUI_MULTILINEENTRY, 1)
  1170. #define lui_checkMultilineEntry(L, pos) ((lui_object*)luaL_checkudata(L, pos, LUI_MULTILINEENTRY))
  1171. /*** Property
  1172. * Object: multilineentry
  1173. * Name: text
  1174. * the text the multiline entry contains.
  1175. *** Property
  1176. * Object: multilineentry
  1177. * Name: readonly
  1178. * true if the multiline entry is / should be read only, false if not.
  1179. *** Property
  1180. * Object: multilineentry
  1181. * Name: onchanged
  1182. * a function <code>onchanged(multilineentry)</code> that is called when the
  1183. * contents of the multilineentry is changed by the user.
  1184. */
  1185. static int lui_multilineEntry__index(lua_State *L)
  1186. {
  1187. lui_object *lobj = lui_checkMultilineEntry(L, 1);
  1188. const char *what = luaL_checkstring(L, 2);
  1189. if (strcmp(what, "text") == 0) {
  1190. char *text = uiMultilineEntryText(uiMultilineEntry(lobj->object));
  1191. lua_pushstring(L, text);
  1192. uiFreeText(text);
  1193. } else if (strcmp(what, "readonly") == 0) {
  1194. lua_pushboolean(L, uiMultilineEntryReadOnly(uiMultilineEntry(lobj->object)) != 0);
  1195. } else if (strcmp(what, "onchanged") == 0) {
  1196. lui_objectGetHandler(L, "onchanged");
  1197. } else {
  1198. return lui_control__index(L);
  1199. }
  1200. return 1;
  1201. }
  1202. static int lui_multilineEntry__newindex(lua_State *L)
  1203. {
  1204. lui_object *lobj = lui_checkMultilineEntry(L, 1);
  1205. const char *what = luaL_checkstring(L, 2);
  1206. if (strcmp(what, "text") == 0) {
  1207. const char *text = luaL_checkstring(L, 3);
  1208. uiMultilineEntrySetText(uiMultilineEntry(lobj->object), text);
  1209. } else if (strcmp(what, "readonly") == 0) {
  1210. int readonly = lua_toboolean(L, 3);
  1211. uiMultilineEntrySetReadOnly(uiMultilineEntry(lobj->object), readonly);
  1212. } else if (strcmp(what, "onchanged") == 0) {
  1213. lui_objectSetHandler(L, "onchanged", 3);
  1214. } else {
  1215. return lui_control__newindex(L);
  1216. }
  1217. return 0;
  1218. }
  1219. /*** Method
  1220. * Object: multilineentry
  1221. * Name: append
  1222. * Signature: multilineentry:append(text, ...)
  1223. * append one or more text pieces to the multilineentry control.
  1224. */
  1225. static int lui_multilineEntryAppend(lua_State *L)
  1226. {
  1227. lui_object *lobj = lui_checkMultilineEntry(L, 1);
  1228. const char *text = lua_tostring(L, 2);
  1229. uiMultilineEntryAppend(uiMultilineEntry(lobj->object), text);
  1230. for (int i = 3; i <= lua_gettop(L); ++i) {
  1231. text = lua_tostring(L, i);
  1232. uiMultilineEntryAppend(uiMultilineEntry(lobj->object), text);
  1233. } return 0;
  1234. }
  1235. static void lui_multilineEntryOnChangedCallback(uiMultilineEntry *spb, void *data)
  1236. {
  1237. lua_State *L = (lua_State*) data;
  1238. int top = lua_gettop(L);
  1239. lui_objectHandlerCallback(L, uiControl(spb), "onchanged", top, 0, 1);
  1240. lua_settop(L, top);
  1241. }
  1242. /*** Constructor
  1243. * Object: multilineentry
  1244. * Name: multilineentry
  1245. * Signature: multilineentry = lui.multilineentry(nowrapping = false, properties = nil)
  1246. * create a new multilineentry control. if nowrapping is true, the text will
  1247. * not wrap around when it exceeds the width of the control, but will be
  1248. * accessible via horizontal scrollbars instead.
  1249. */
  1250. static int lui_newMultilineEntry(lua_State *L)
  1251. {
  1252. int nowrapping = lua_toboolean(L, 1);
  1253. int hastable = lui_aux_istable(L, 2);
  1254. lui_object *lobj = lui_pushMultilineEntry(L);
  1255. if (nowrapping) {
  1256. lobj->object = uiNewNonWrappingMultilineEntry();
  1257. } else {
  1258. lobj->object = uiNewMultilineEntry();
  1259. }
  1260. uiMultilineEntryOnChanged(uiMultilineEntry(lobj->object), lui_multilineEntryOnChangedCallback, L);
  1261. if (hastable) { lui_aux_setFieldsFromTable(L, lua_gettop(L), 2); }
  1262. lui_registerObject(L, lua_gettop(L));
  1263. return 1;
  1264. }
  1265. /* metamethods for multiline entry */
  1266. static const luaL_Reg lui_multilineEntry_meta[] = {
  1267. {"__index", lui_multilineEntry__index},
  1268. {"__newindex", lui_multilineEntry__newindex},
  1269. {0, 0}
  1270. };
  1271. /* methods for multiline entry */
  1272. static const luaL_Reg lui_multilineEntry_methods[] = {
  1273. {"append", lui_multilineEntryAppend},
  1274. {0, 0}
  1275. };
  1276. /* controls function list table
  1277. */
  1278. static const struct luaL_Reg lui_control_funcs [] ={
  1279. {"button", lui_newButton},
  1280. {"entry", lui_newEntry},
  1281. {"passwordentry", lui_newPasswordEntry},
  1282. {"searchentry", lui_newSearchEntry},
  1283. {"checkbox", lui_newCheckbox},
  1284. {"label", lui_newLabel},
  1285. {"spinbox", lui_newSpinbox},
  1286. {"progressbar", lui_newProgressbar},
  1287. {"slider", lui_newSlider},
  1288. {"hseparator", lui_newHSeparator},
  1289. {"vseparator", lui_newVSeparator},
  1290. {"combobox", lui_newCombobox},
  1291. {"editablecombobox", lui_newEditableCombobox},
  1292. {"radiobuttons", lui_newRadiobuttons},
  1293. {"datetimepicker", lui_newDatetimepicker},
  1294. {"datepicker", lui_newDatepicker},
  1295. {"timepicker", lui_newTimepicker},
  1296. {"multilineentry", lui_newMultilineEntry},
  1297. {0, 0}
  1298. };
  1299. static int lui_init_controls(lua_State *L)
  1300. {
  1301. luaL_setfuncs(L, lui_control_funcs, 0);
  1302. lui_add_control_type(L, LUI_BUTTON, 0, lui_button_meta);
  1303. lui_add_control_type(L, LUI_BOX, lui_box_methods, lui_box_meta);
  1304. lui_add_control_type(L, LUI_ENTRY, 0, lui_entry_meta);
  1305. lui_add_control_type(L, LUI_CHECKBOX, 0, lui_checkbox_meta);
  1306. lui_add_control_type(L, LUI_LABEL, 0, lui_label_meta);
  1307. lui_add_control_type(L, LUI_SPINBOX, 0, lui_spinbox_meta);
  1308. lui_add_control_type(L, LUI_PROGRESSBAR, 0, lui_progressbar_meta);
  1309. lui_add_control_type(L, LUI_SLIDER, 0, lui_slider_meta);
  1310. lui_add_control_type(L, LUI_SEPARATOR, 0, 0);
  1311. lui_add_control_type(L, LUI_COMBOBOX, lui_combobox_methods, lui_combobox_meta);
  1312. lui_add_control_type(L, LUI_EDITABLECOMBOBOX, lui_editableCombobox_methods, lui_editableCombobox_meta);
  1313. lui_add_control_type(L, LUI_RADIOBUTTONS, lui_radiobuttons_methods, lui_radiobuttons_meta);
  1314. lui_add_control_type(L, LUI_DATETIMEPICKER, 0, lui_dateTimePicker_meta);
  1315. lui_add_control_type(L, LUI_MULTILINEENTRY, lui_multilineEntry_methods, lui_multilineEntry_meta);
  1316. return 1;
  1317. }