factory.py 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  1. # Copyright 2021-2025 Avaiga Private Limited
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
  4. # the License. You may obtain a copy of the License at
  5. #
  6. # http://www.apache.org/licenses/LICENSE-2.0
  7. #
  8. # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
  9. # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
  10. # specific language governing permissions and limitations under the License.
  11. import re
  12. import typing as t
  13. from datetime import datetime
  14. from ..types import PropertyType
  15. from .builder import _Builder
  16. if t.TYPE_CHECKING:
  17. from ..extension.library import ElementLibrary
  18. from ..gui import Gui
  19. class _Factory:
  20. DEFAULT_CONTROL = "text"
  21. _START_SUFFIX = ".start"
  22. _END_SUFFIX = ".end"
  23. __TAIPY_NAME_SPACE = "taipy."
  24. __CONTROL_DEFAULT_PROP_NAME = {
  25. "alert": "message",
  26. "button": "label",
  27. "chat": "messages",
  28. "chart": "data",
  29. "content": "value",
  30. "date": "date",
  31. "date_range": "dates",
  32. "dialog": "open",
  33. "expandable": "title",
  34. "file_download": "content",
  35. "file_selector": "content",
  36. "image": "content",
  37. "indicator": "display",
  38. "input": "value",
  39. "layout": "columns",
  40. "login": "title",
  41. "menu": "lov",
  42. "metric": "value",
  43. "navbar": "value",
  44. "number": "value",
  45. "pane": "open",
  46. "part": "class_name",
  47. "progress": "value",
  48. "selector": "value",
  49. "slider": "value",
  50. "status": "value",
  51. "table": "data",
  52. "text": "value",
  53. "time": "time",
  54. "toggle": "value",
  55. "tree": "value",
  56. }
  57. _TEXT_ATTRIBUTES = ["format", "id", "hover_text", "raw"]
  58. __TEXT_ANCHORS = ["bottom", "top", "left", "right"]
  59. __TEXT_ANCHOR_NONE = "none"
  60. __LIBRARIES: t.Dict[str, t.List["ElementLibrary"]] = {}
  61. __CONTROL_BUILDERS = {
  62. "alert": lambda gui, control_type, attrs: _Builder(
  63. gui=gui,
  64. control_type=control_type,
  65. element_name="Alert",
  66. prop_values=attrs,
  67. )
  68. .set_value_and_default(var_type=PropertyType.dynamic_string)
  69. .set_attributes(
  70. [
  71. ("severity", PropertyType.dynamic_string),
  72. ("variant", PropertyType.dynamic_string),
  73. ("render", PropertyType.dynamic_boolean, True),
  74. ]
  75. ),
  76. "button": lambda gui, control_type, attrs: _Builder(
  77. gui=gui,
  78. control_type=control_type,
  79. element_name="Button",
  80. prop_values=attrs,
  81. )
  82. .set_value_and_default(with_update=False)
  83. .set_attributes(
  84. [
  85. ("on_action", PropertyType.function),
  86. ("active", PropertyType.dynamic_boolean, True),
  87. ("hover_text", PropertyType.dynamic_string),
  88. ("width", PropertyType.string_or_number),
  89. ("size", PropertyType.string),
  90. ("variant", PropertyType.string),
  91. ]
  92. ),
  93. "chat": lambda gui, control_type, attrs: _Builder(
  94. gui=gui, control_type=control_type, element_name="Chat", prop_values=attrs, default_value=None
  95. )
  96. .set_value_and_default(with_update=True, with_default=False, var_type=PropertyType.data)
  97. .set_attributes(
  98. [
  99. ("on_action", PropertyType.function),
  100. ("active", PropertyType.dynamic_boolean, True),
  101. ("hover_text", PropertyType.dynamic_string),
  102. ("with_input", PropertyType.dynamic_boolean, True),
  103. ("users", PropertyType.lov),
  104. ("sender_id",),
  105. ("height",),
  106. ("page_size", PropertyType.number),
  107. ("max_file_size", PropertyType.number),
  108. ("show_sender", PropertyType.boolean, False),
  109. ("allow_send_images", PropertyType.boolean, True),
  110. ("mode",),
  111. ]
  112. ),
  113. "chart": lambda gui, control_type, attrs: _Builder(
  114. gui=gui, control_type=control_type, element_name="Chart", prop_values=attrs, default_value=None
  115. )
  116. .set_value_and_default(with_default=False, var_type=PropertyType.data)
  117. .set_attributes(
  118. [
  119. ("title", PropertyType.dynamic_string),
  120. ("width", PropertyType.string_or_number),
  121. ("height", PropertyType.string_or_number),
  122. ("layout", PropertyType.dynamic_dict),
  123. ("animation_data", PropertyType.data),
  124. ("plot_config", PropertyType.dict),
  125. ("on_range_change", PropertyType.function),
  126. ("active", PropertyType.dynamic_boolean, True),
  127. ("render", PropertyType.dynamic_boolean, True),
  128. ("hover_text", PropertyType.dynamic_string),
  129. ("on_change", PropertyType.function),
  130. ("template", PropertyType.dict),
  131. ("template[dark]", PropertyType.dict, gui._get_config("chart_dark_template", None)),
  132. ("template[light]", PropertyType.dict),
  133. ("figure", PropertyType.to_json),
  134. ("on_click", PropertyType.function),
  135. ]
  136. )
  137. ._get_chart_config("scatter", "lines+markers")
  138. ._set_propagate(),
  139. "content": lambda gui, control_type, attrs: _Builder(
  140. gui=gui, control_type=control_type, element_name="PageContent", prop_values=attrs
  141. ),
  142. "date": lambda gui, control_type, attrs: _Builder(
  143. gui=gui,
  144. control_type=control_type,
  145. element_name="DateSelector",
  146. prop_values=attrs,
  147. default_value=datetime.fromtimestamp(0),
  148. )
  149. .set_value_and_default(var_type=PropertyType.date)
  150. .set_attributes(
  151. [
  152. ("with_time", PropertyType.boolean),
  153. ("active", PropertyType.dynamic_boolean, True),
  154. ("analogic", PropertyType.boolean),
  155. ("min", PropertyType.dynamic_date),
  156. ("max", PropertyType.dynamic_date),
  157. ("editable", PropertyType.dynamic_boolean, True),
  158. ("hover_text", PropertyType.dynamic_string),
  159. ("label",),
  160. ("on_change", PropertyType.function),
  161. ("format",),
  162. ("width", PropertyType.string_or_number),
  163. ]
  164. )
  165. ._set_propagate(),
  166. "date_range": lambda gui, control_type, attrs: _Builder(
  167. gui=gui,
  168. control_type=control_type,
  169. element_name="DateRange",
  170. prop_values=attrs,
  171. )
  172. .set_value_and_default(var_type=PropertyType.date_range)
  173. .set_attributes(
  174. [
  175. ("with_time", PropertyType.boolean),
  176. ("active", PropertyType.dynamic_boolean, True),
  177. ("analogic", PropertyType.boolean),
  178. ("editable", PropertyType.dynamic_boolean, True),
  179. ("hover_text", PropertyType.dynamic_string),
  180. ("label_start",),
  181. ("label_end",),
  182. ("on_change", PropertyType.function),
  183. ("format",),
  184. ("width", PropertyType.string_or_number),
  185. ]
  186. )
  187. ._set_propagate(),
  188. "dialog": lambda gui, control_type, attrs: _Builder(
  189. gui=gui,
  190. control_type=control_type,
  191. element_name="Dialog",
  192. prop_values=attrs,
  193. )
  194. .set_value_and_default(var_type=PropertyType.dynamic_boolean)
  195. ._set_partial() # partial should be set before page
  196. .set_attributes(
  197. [
  198. ("page",),
  199. ("title",),
  200. ("on_action", PropertyType.function),
  201. ("close_label", PropertyType.string),
  202. ("labels", PropertyType.string_list),
  203. ("active", PropertyType.dynamic_boolean, True),
  204. ("width", PropertyType.string_or_number),
  205. ("height", PropertyType.string_or_number),
  206. ("hover_text", PropertyType.dynamic_string),
  207. ("ref_id", PropertyType.dynamic_string),
  208. ("popup", PropertyType.boolean),
  209. ]
  210. )
  211. ._set_propagate(),
  212. "expandable": lambda gui, control_type, attrs: _Builder(
  213. gui=gui, control_type=control_type, element_name="Expandable", prop_values=attrs, default_value=None
  214. )
  215. .set_value_and_default()
  216. ._set_partial() # partial should be set before page
  217. .set_attributes(
  218. [
  219. ("page",),
  220. ("expanded", PropertyType.dynamic_boolean, True, True, False),
  221. ("hover_text", PropertyType.dynamic_string),
  222. ("on_change", PropertyType.function),
  223. ]
  224. ),
  225. "file_download": lambda gui, control_type, attrs: _Builder(
  226. gui=gui,
  227. control_type=control_type,
  228. element_name="FileDownload",
  229. prop_values=attrs,
  230. )
  231. .set_value_and_default(var_name="label", with_update=False)
  232. ._set_content("content", image=False)
  233. .set_attributes(
  234. [
  235. ("on_action", PropertyType.function),
  236. ("active", PropertyType.dynamic_boolean, True),
  237. ("render", PropertyType.dynamic_boolean, True),
  238. ("auto", PropertyType.boolean, False),
  239. ("bypass_preview", PropertyType.boolean, True),
  240. ("name",),
  241. ("hover_text", PropertyType.dynamic_string),
  242. ("width", PropertyType.string_or_number),
  243. ]
  244. ),
  245. "file_selector": lambda gui, control_type, attrs: _Builder(
  246. gui=gui,
  247. control_type=control_type,
  248. element_name="FileSelector",
  249. prop_values=attrs,
  250. )
  251. .set_value_and_default(var_name="label", with_update=False)
  252. ._set_file_content()
  253. .set_attributes(
  254. [
  255. ("on_action", PropertyType.function),
  256. ("active", PropertyType.dynamic_boolean, True),
  257. ("multiple", PropertyType.boolean, False),
  258. ("selection_type", PropertyType.string),
  259. ("extensions",),
  260. ("drop_message",),
  261. ("hover_text", PropertyType.dynamic_string),
  262. ("notify", PropertyType.boolean, True),
  263. ("width", PropertyType.string_or_number),
  264. ]
  265. ),
  266. "image": lambda gui, control_type, attrs: _Builder(
  267. gui=gui,
  268. control_type=control_type,
  269. element_name="Image",
  270. prop_values=attrs,
  271. )
  272. .set_value_and_default(var_name="label", with_update=False)
  273. ._set_content("content")
  274. .set_attributes(
  275. [
  276. ("on_action", PropertyType.function),
  277. ("active", PropertyType.dynamic_boolean, True),
  278. ("width",),
  279. ("height",),
  280. ("hover_text", PropertyType.dynamic_string),
  281. ]
  282. ),
  283. "indicator": lambda gui, control_type, attrs: _Builder(
  284. gui=gui,
  285. control_type=control_type,
  286. element_name="Indicator",
  287. prop_values=attrs,
  288. )
  289. .set_value_and_default(with_update=False, native_type=True)
  290. .set_attributes(
  291. [
  292. ("min", PropertyType.number),
  293. ("max", PropertyType.number),
  294. ("value", PropertyType.dynamic_number),
  295. ("format",),
  296. ("orientation",),
  297. ("width",),
  298. ("height",),
  299. ]
  300. ),
  301. "input": lambda gui, control_type, attrs: _Builder(
  302. gui=gui,
  303. control_type=control_type,
  304. element_name="Input",
  305. prop_values=attrs,
  306. )
  307. ._set_input_type("text", True)
  308. .set_value_and_default()
  309. ._set_propagate()
  310. .set_attributes(
  311. [
  312. ("active", PropertyType.dynamic_boolean, True),
  313. ("hover_text", PropertyType.dynamic_string),
  314. ("on_change", PropertyType.function),
  315. ("on_action", PropertyType.function),
  316. ("action_keys",),
  317. ("label",),
  318. ("change_delay", PropertyType.number, gui._get_config("change_delay", None)),
  319. ("action_on_blur", PropertyType.boolean, False),
  320. ("multiline", PropertyType.boolean, False),
  321. ("lines_shown", PropertyType.number, 5),
  322. ("width", PropertyType.string_or_number),
  323. ("size", PropertyType.string),
  324. ]
  325. ),
  326. "layout": lambda gui, control_type, attrs: _Builder(
  327. gui=gui, control_type=control_type, element_name="Layout", prop_values=attrs, default_value=None
  328. )
  329. .set_value_and_default(with_default=False)
  330. .set_attributes(
  331. [
  332. ("columns[mobile]",),
  333. ("gap",),
  334. ]
  335. ),
  336. "login": lambda gui, control_type, attrs: _Builder(
  337. gui=gui, control_type=control_type, element_name="Login", prop_values=attrs, default_value=None
  338. )
  339. .set_value_and_default(default_val="Log-in")
  340. .set_attributes(
  341. [
  342. ("message", PropertyType.dynamic_string),
  343. ("on_action", PropertyType.function, "on_login"),
  344. ("labels", PropertyType.string_list),
  345. ]
  346. ),
  347. "menu": lambda gui, control_type, attrs: _Builder(
  348. gui=gui,
  349. control_type=control_type,
  350. element_name="MenuCtl",
  351. prop_values=attrs,
  352. )
  353. .set_attributes(
  354. [
  355. ("lov", PropertyType.lov),
  356. ("label",),
  357. ("on_action", PropertyType.function),
  358. ("selected", PropertyType.dynamic_list),
  359. ("inactive_ids", PropertyType.dynamic_list),
  360. ("active", PropertyType.dynamic_boolean, True),
  361. ("hover_text", PropertyType.dynamic_string),
  362. ("width",),
  363. ("width[mobile]",),
  364. ("expanded", PropertyType.boolean, False),
  365. ]
  366. )
  367. ._set_propagate(),
  368. "metric": lambda gui, control_type, attrs: _Builder(
  369. gui=gui,
  370. control_type=control_type,
  371. element_name="Metric",
  372. prop_values=attrs,
  373. )
  374. .set_value_and_default(var_type=PropertyType.dynamic_number, native_type=True)
  375. .set_attributes(
  376. [
  377. ("title",),
  378. ("active", PropertyType.dynamic_boolean, True),
  379. ("layout", PropertyType.dynamic_dict),
  380. ("type", PropertyType.string, "circular"),
  381. ("min", PropertyType.number, 0),
  382. ("max", PropertyType.number, 100),
  383. ("delta", PropertyType.dynamic_number),
  384. ("delta_color", PropertyType.string),
  385. ("negative_delta_color", PropertyType.string),
  386. ("threshold", PropertyType.dynamic_number),
  387. ("width", PropertyType.string_or_number),
  388. ("height", PropertyType.string_or_number),
  389. ("show_value", PropertyType.boolean, True),
  390. ("format", PropertyType.string),
  391. ("delta_format", PropertyType.string),
  392. ("bar_color", PropertyType.string),
  393. ("color_map", PropertyType.dict),
  394. ("hover_text", PropertyType.dynamic_string),
  395. ("template", PropertyType.dict),
  396. ("template[dark]", PropertyType.dict),
  397. ("template[light]", PropertyType.dict),
  398. ]
  399. ),
  400. "navbar": lambda gui, control_type, attrs: _Builder(
  401. gui=gui, control_type=control_type, element_name="NavBar", prop_values=attrs, default_value=None
  402. ).set_attributes(
  403. [
  404. ("active", PropertyType.dynamic_boolean, True),
  405. ("hover_text", PropertyType.dynamic_string),
  406. ("lov", PropertyType.single_lov),
  407. ]
  408. ),
  409. "number": lambda gui, control_type, attrs: _Builder(
  410. gui=gui,
  411. control_type=control_type,
  412. element_name="Input",
  413. prop_values=attrs,
  414. default_value=0,
  415. )
  416. ._set_input_type("number")
  417. .set_value_and_default(var_type=PropertyType.dynamic_number)
  418. ._set_propagate()
  419. .set_attributes(
  420. [
  421. ("active", PropertyType.dynamic_boolean, True),
  422. ("step", PropertyType.dynamic_number, 1),
  423. ("step_multiplier", PropertyType.dynamic_number, 10),
  424. ("min", PropertyType.dynamic_number),
  425. ("max", PropertyType.dynamic_number),
  426. ("hover_text", PropertyType.dynamic_string),
  427. ("on_change", PropertyType.function),
  428. ("on_action", PropertyType.function),
  429. ("label",),
  430. ("change_delay", PropertyType.number, gui._get_config("change_delay", None)),
  431. ("action_on_blur", PropertyType.boolean, False),
  432. ("width", PropertyType.string_or_number),
  433. ]
  434. ),
  435. "pane": lambda gui, control_type, attrs: _Builder(
  436. gui=gui, control_type=control_type, element_name="Pane", prop_values=attrs, default_value=None
  437. )
  438. .set_value_and_default(var_type=PropertyType.dynamic_boolean)
  439. ._set_partial() # partial should be set before page
  440. .set_attributes(
  441. [
  442. ("page",),
  443. ("anchor", PropertyType.string, "left"),
  444. ("on_close", PropertyType.function),
  445. ("persistent", PropertyType.boolean, False),
  446. ("active", PropertyType.dynamic_boolean, True),
  447. ("width", PropertyType.string_or_number, "30vw"),
  448. ("height", PropertyType.string_or_number, "30vh"),
  449. ("hover_text", PropertyType.dynamic_string),
  450. ("on_change", PropertyType.function),
  451. ("show_button", PropertyType.boolean, False),
  452. ]
  453. )
  454. ._set_propagate(),
  455. "part": lambda gui, control_type, attrs: _Builder(
  456. gui=gui, control_type=control_type, element_name="Part", prop_values=attrs, default_value=None
  457. )
  458. ._set_partial() # partial should be set before page
  459. .set_attributes(
  460. [
  461. ("page", PropertyType.dynamic_string),
  462. ("render", PropertyType.dynamic_boolean, True),
  463. ("height", PropertyType.dynamic_string),
  464. ("content", PropertyType.toHtmlContent),
  465. ("width", PropertyType.string_or_number),
  466. ("drag_type", PropertyType.string),
  467. ("drop_types", PropertyType.string_list),
  468. ("on_action", PropertyType.function),
  469. ("drag_parameters", PropertyType.dict),
  470. ]
  471. ),
  472. "progress": lambda gui, control_type, attrs: _Builder(
  473. gui=gui,
  474. control_type=control_type,
  475. element_name="Progress",
  476. prop_values=attrs,
  477. )
  478. .set_value_and_default(var_type=PropertyType.dynamic_number, native_type=True)
  479. .set_attributes(
  480. [
  481. ("linear", PropertyType.boolean, False),
  482. ("show_value", PropertyType.boolean, False),
  483. ("title", PropertyType.dynamic_string),
  484. ("title_anchor", PropertyType.string, "bottom"),
  485. ("render", PropertyType.dynamic_boolean, True),
  486. ("width", PropertyType.string_or_number),
  487. ]
  488. ),
  489. "selector": lambda gui, control_type, attrs: _Builder(
  490. gui=gui, control_type=control_type, element_name="Selector", prop_values=attrs, default_value=None
  491. )
  492. .set_value_and_default(with_default=False, var_type=PropertyType.lov_value)
  493. .set_attributes(
  494. [
  495. ("active", PropertyType.dynamic_boolean, True),
  496. ("dropdown", PropertyType.boolean, False),
  497. ("filter", PropertyType.boolean),
  498. ("height", PropertyType.string_or_number),
  499. ("hover_text", PropertyType.dynamic_string),
  500. ("value_by_id", PropertyType.boolean),
  501. ("multiple", PropertyType.boolean),
  502. ("width", PropertyType.string_or_number),
  503. ("on_change", PropertyType.function),
  504. ("label",),
  505. ("mode",),
  506. ("lov", PropertyType.lov),
  507. ("selection_message", PropertyType.dynamic_string),
  508. ("show_select_all", PropertyType.boolean),
  509. ("drag_type", PropertyType.string),
  510. ("drop_types", PropertyType.string_list),
  511. ("on_action", PropertyType.function),
  512. ]
  513. )
  514. ._set_propagate(),
  515. "slider": lambda gui, control_type, attrs: _Builder(
  516. gui=gui,
  517. control_type=control_type,
  518. element_name="Slider",
  519. prop_values=attrs,
  520. default_value=0,
  521. )
  522. .set_value_and_default(native_type=True, var_type=PropertyType.slider_value)
  523. .set_attributes(
  524. [
  525. ("active", PropertyType.dynamic_boolean, True),
  526. ("height",),
  527. ("hover_text", PropertyType.dynamic_string),
  528. ("value_by_id", PropertyType.boolean),
  529. ("max", PropertyType.number, 100),
  530. ("min", PropertyType.number, 0),
  531. ("step", PropertyType.number, 1),
  532. ("orientation",),
  533. ("width", PropertyType.string, "300px"),
  534. ("on_change", PropertyType.function),
  535. ("continuous", PropertyType.boolean, None),
  536. ("lov", PropertyType.lov),
  537. ("change_delay", PropertyType.number, gui._get_config("change_delay", None)),
  538. ]
  539. )
  540. ._set_labels()
  541. ._set_string_with_check("text_anchor", _Factory.__TEXT_ANCHORS + [_Factory.__TEXT_ANCHOR_NONE], "bottom")
  542. ._set_propagate(),
  543. "status": lambda gui, control_type, attrs: _Builder(
  544. gui=gui,
  545. control_type=control_type,
  546. element_name="Status",
  547. prop_values=attrs,
  548. )
  549. .set_value_and_default(with_update=False)
  550. .set_attributes(
  551. [
  552. ("without_close", PropertyType.boolean, False),
  553. ("hover_text", PropertyType.dynamic_string),
  554. ]
  555. )
  556. ._set_indexed_icons(),
  557. "table": lambda gui, control_type, attrs: _Builder(
  558. gui=gui,
  559. control_type=control_type,
  560. element_name="Table",
  561. prop_values=attrs,
  562. )
  563. .set_value_and_default(with_default=False, var_type=PropertyType.data)
  564. ._get_dataframe_attributes()
  565. ._get_list_attribute("selected", PropertyType.number)
  566. .set_attributes(
  567. [
  568. ("page_size", PropertyType.number, "100"),
  569. ("allow_all_rows", PropertyType.boolean),
  570. ("show_all", PropertyType.boolean),
  571. ("auto_loading", PropertyType.boolean),
  572. ("width", PropertyType.string_or_number, "100%"),
  573. ("height", PropertyType.string_or_number, "80vh"),
  574. ("active", PropertyType.dynamic_boolean, True),
  575. ("editable", PropertyType.dynamic_boolean, False),
  576. ("on_edit", PropertyType.function, gui._get_call_method_name("table_on_edit")),
  577. ("on_delete", PropertyType.function, gui._get_call_method_name("table_on_delete")),
  578. ("on_add", PropertyType.function, gui._get_call_method_name("table_on_add")),
  579. ("on_action", PropertyType.function),
  580. ("nan_value",),
  581. ("filter", PropertyType.boolean),
  582. ("hover_text", PropertyType.dynamic_string),
  583. ("size",),
  584. ("downloadable", PropertyType.boolean),
  585. ("use_checkbox", PropertyType.boolean),
  586. ("sortable", PropertyType.boolean, True),
  587. ]
  588. )
  589. ._set_propagate()
  590. ._set_table_pagesize_options(),
  591. "text": lambda gui, control_type, attrs: _Builder(
  592. gui=gui,
  593. control_type=control_type,
  594. element_name="Field",
  595. prop_values=attrs,
  596. )
  597. .set_value_and_default(with_update=False)
  598. ._set_dataType()
  599. .set_attributes(
  600. [
  601. ("format",),
  602. ("hover_text", PropertyType.dynamic_string),
  603. ("raw", PropertyType.boolean, False),
  604. ("mode",),
  605. ("width", PropertyType.string_or_number),
  606. ]
  607. ),
  608. "time": lambda gui, control_type, attrs: _Builder(
  609. gui=gui,
  610. control_type=control_type,
  611. element_name="TimeSelector",
  612. prop_values=attrs,
  613. default_value=datetime.today().time(),
  614. )
  615. .set_value_and_default(var_type=PropertyType.time)
  616. .set_attributes(
  617. [
  618. ("active", PropertyType.dynamic_boolean, True),
  619. ("analogic", PropertyType.boolean),
  620. ("editable", PropertyType.dynamic_boolean, True),
  621. ("hover_text", PropertyType.dynamic_string),
  622. ("label",),
  623. ("format",),
  624. ("width", PropertyType.string_or_number),
  625. ]
  626. )
  627. ._set_propagate(),
  628. "toggle": lambda gui, control_type, attrs: _Builder(
  629. gui=gui, control_type=control_type, element_name="Toggle", prop_values=attrs, default_value=None
  630. )
  631. .set_value_and_default(with_default=False, var_type=PropertyType.toggle_value)
  632. .set_attributes(
  633. [
  634. ("active", PropertyType.dynamic_boolean, True),
  635. ("hover_text", PropertyType.dynamic_string),
  636. ("label",),
  637. ("value_by_id", PropertyType.boolean),
  638. ("allow_unselect", PropertyType.boolean),
  639. ("on_change", PropertyType.function),
  640. ("mode",),
  641. ("lov", PropertyType.single_lov),
  642. ("width", PropertyType.string_or_number),
  643. ]
  644. )
  645. ._set_kind()
  646. ._set_propagate(),
  647. "tree": lambda gui, control_type, attrs: _Builder(
  648. gui=gui,
  649. control_type=control_type,
  650. element_name="TreeView",
  651. prop_values=attrs,
  652. )
  653. .set_value_and_default(with_default=False, var_type=PropertyType.lov_value)
  654. .set_attributes(
  655. [
  656. ("active", PropertyType.dynamic_boolean, True),
  657. ("expanded", PropertyType.boolean_or_list, True),
  658. ("filter", PropertyType.boolean),
  659. ("hover_text", PropertyType.dynamic_string),
  660. ("height", PropertyType.string_or_number),
  661. ("value_by_id", PropertyType.boolean),
  662. ("multiple", PropertyType.boolean),
  663. ("width", PropertyType.string_or_number),
  664. ("on_change", PropertyType.function),
  665. ("select_leafs_only", PropertyType.boolean),
  666. ("row_height", PropertyType.string),
  667. ("lov", PropertyType.lov),
  668. ("drag_type", PropertyType.string),
  669. ("drop_types", PropertyType.string_list),
  670. ("on_action", PropertyType.function),
  671. ]
  672. )
  673. ._set_propagate(),
  674. }
  675. # TODO: process \" in property value
  676. _PROPERTY_RE = re.compile(r"\s+([a-zA-Z][\.a-zA-Z_$0-9]*(?:\[(?:.*?)\])?)=\"((?:(?:(?<=\\)\")|[^\"])*)\"")
  677. __COUNTER = 0
  678. @staticmethod
  679. def set_library(library: "ElementLibrary"):
  680. from ..extension.library import Element, ElementLibrary
  681. if isinstance(library, ElementLibrary) and isinstance(library.get_name(), str) and library.get_elements():
  682. elements = library.get_elements()
  683. for name, element in elements.items():
  684. if isinstance(element, Element):
  685. element.check(name)
  686. fact_lib = _Factory.__LIBRARIES.get(library.get_name())
  687. if fact_lib is None:
  688. _Factory.__LIBRARIES.update({library.get_name(): [library]})
  689. else:
  690. fact_lib.append(library)
  691. @staticmethod
  692. def get_default_property_name(control_name: str) -> t.Optional[str]:
  693. name = (
  694. control_name[: -len(_Factory._START_SUFFIX)]
  695. if control_name.endswith(_Factory._START_SUFFIX)
  696. else control_name[: -len(_Factory._END_SUFFIX)]
  697. if control_name.endswith(_Factory._END_SUFFIX)
  698. else control_name
  699. )
  700. name = name[len(_Factory.__TAIPY_NAME_SPACE) :] if name.startswith(_Factory.__TAIPY_NAME_SPACE) else name
  701. prop = _Factory.__CONTROL_DEFAULT_PROP_NAME.get(name)
  702. if prop is None:
  703. _, _, element = _Factory.__get_library_element(name)
  704. if element:
  705. prop = element.default_attribute
  706. return prop
  707. @staticmethod
  708. def __get_library_element(name: str):
  709. parts = name.split(".")
  710. if len(parts) > 1:
  711. element_name = ".".join(parts[1:])
  712. for lib in _Factory.__LIBRARIES.get(parts[0], []):
  713. elts = lib.get_elements()
  714. if isinstance(elts, dict):
  715. if element := elts.get(element_name):
  716. return lib, element_name, element
  717. else:
  718. element_name = name
  719. for libs in list(_Factory.__LIBRARIES.values()):
  720. for lib in libs:
  721. elts = lib.get_elements()
  722. if isinstance(elts, dict):
  723. if element := elts.get(element_name):
  724. return lib, element_name, element
  725. return None, None, None
  726. @staticmethod
  727. def call_builder(
  728. gui: "Gui", name: str, all_properties: t.Optional[t.Dict[str, t.Any]] = None, is_html: t.Optional[bool] = False
  729. ) -> t.Union[t.Any, t.Tuple[str, str], None]:
  730. name = name[len(_Factory.__TAIPY_NAME_SPACE) :] if name.startswith(_Factory.__TAIPY_NAME_SPACE) else name
  731. builder = _Factory.__CONTROL_BUILDERS.get(name)
  732. built = None
  733. _Factory.__COUNTER += 1
  734. with gui._get_authorization(): # type: ignore[attr-defined]
  735. if builder is None:
  736. lib, element_name, element = _Factory.__get_library_element(name)
  737. if lib:
  738. from ..extension.library import Element
  739. if isinstance(element, Element):
  740. return element._call_builder(
  741. element_name, gui, all_properties, lib, is_html, counter=_Factory.__COUNTER
  742. )
  743. else:
  744. built = builder(gui, name, all_properties)
  745. if isinstance(built, _Builder):
  746. return built._build_to_string() if is_html else built.get_element()
  747. return None