factory.py 30 KB

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