py10x-universe 0.1.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. core_10x/__init__.py +42 -0
  2. core_10x/backbone/__init__.py +0 -0
  3. core_10x/backbone/backbone_store.py +59 -0
  4. core_10x/backbone/backbone_traitable.py +30 -0
  5. core_10x/backbone/backbone_user.py +66 -0
  6. core_10x/backbone/bound_data_domain.py +49 -0
  7. core_10x/backbone/namespace.py +101 -0
  8. core_10x/backbone/vault.py +38 -0
  9. core_10x/code_samples/__init__.py +0 -0
  10. core_10x/code_samples/_package_manifest.py +3 -0
  11. core_10x/code_samples/directories.py +181 -0
  12. core_10x/code_samples/person.py +76 -0
  13. core_10x/concrete_traits.py +356 -0
  14. core_10x/conftest.py +12 -0
  15. core_10x/curve.py +321 -0
  16. core_10x/data_domain.py +48 -0
  17. core_10x/data_domain_binder.py +45 -0
  18. core_10x/directory.py +250 -0
  19. core_10x/entity.py +8 -0
  20. core_10x/entity_filter.py +5 -0
  21. core_10x/environment_variables.py +147 -0
  22. core_10x/exec_control.py +84 -0
  23. core_10x/experimental/__init__.py +0 -0
  24. core_10x/experimental/data_protocol_ex.py +34 -0
  25. core_10x/global_cache.py +121 -0
  26. core_10x/manual_tests/__init__.py +0 -0
  27. core_10x/manual_tests/calendar_test.py +35 -0
  28. core_10x/manual_tests/ctor_update_bug.py +58 -0
  29. core_10x/manual_tests/debug_graph_on.py +17 -0
  30. core_10x/manual_tests/debug_graphoff_inside_graph_on.py +28 -0
  31. core_10x/manual_tests/enum_bits_test.py +17 -0
  32. core_10x/manual_tests/env_vars_trivial_test.py +12 -0
  33. core_10x/manual_tests/existing_traitable.py +33 -0
  34. core_10x/manual_tests/k10x_test1.py +13 -0
  35. core_10x/manual_tests/named_constant_test.py +121 -0
  36. core_10x/manual_tests/nucleus_trivial_test.py +42 -0
  37. core_10x/manual_tests/polars_test.py +14 -0
  38. core_10x/manual_tests/py_class_test.py +4 -0
  39. core_10x/manual_tests/rc_test.py +42 -0
  40. core_10x/manual_tests/rdate_test.py +12 -0
  41. core_10x/manual_tests/reference_serialization_bug.py +19 -0
  42. core_10x/manual_tests/resource_trivial_test.py +10 -0
  43. core_10x/manual_tests/store_uri_test.py +6 -0
  44. core_10x/manual_tests/trait_definition_test.py +19 -0
  45. core_10x/manual_tests/trait_filter_test.py +15 -0
  46. core_10x/manual_tests/trait_flag_modification_test.py +42 -0
  47. core_10x/manual_tests/trait_modification_bug.py +26 -0
  48. core_10x/manual_tests/traitable_as_of_test.py +82 -0
  49. core_10x/manual_tests/traitable_heir_test.py +39 -0
  50. core_10x/manual_tests/traitable_history_test.py +41 -0
  51. core_10x/manual_tests/traitable_serialization_test.py +54 -0
  52. core_10x/manual_tests/traitable_trivial_test.py +71 -0
  53. core_10x/manual_tests/trivial_graph_test.py +16 -0
  54. core_10x/manual_tests/ts_class_association_test.py +64 -0
  55. core_10x/manual_tests/ts_trivial_test.py +35 -0
  56. core_10x/named_constant.py +425 -0
  57. core_10x/nucleus.py +81 -0
  58. core_10x/package_manifest.py +85 -0
  59. core_10x/package_refactoring.py +153 -0
  60. core_10x/py_class.py +431 -0
  61. core_10x/rc.py +155 -0
  62. core_10x/rdate.py +339 -0
  63. core_10x/resource.py +189 -0
  64. core_10x/roman_number.py +67 -0
  65. core_10x/testlib/__init__.py +0 -0
  66. core_10x/testlib/test_store.py +240 -0
  67. core_10x/testlib/traitable_history_tests.py +787 -0
  68. core_10x/testlib/ts_tests.py +280 -0
  69. core_10x/trait.py +377 -0
  70. core_10x/trait_definition.py +176 -0
  71. core_10x/trait_filter.py +205 -0
  72. core_10x/trait_method_error.py +36 -0
  73. core_10x/traitable.py +1082 -0
  74. core_10x/traitable_cli.py +153 -0
  75. core_10x/traitable_heir.py +33 -0
  76. core_10x/traitable_id.py +31 -0
  77. core_10x/ts_store.py +172 -0
  78. core_10x/ts_store_type.py +26 -0
  79. core_10x/ts_union.py +147 -0
  80. core_10x/ui_hint.py +153 -0
  81. core_10x/unit_tests/test_concrete_traits.py +156 -0
  82. core_10x/unit_tests/test_converters.py +51 -0
  83. core_10x/unit_tests/test_curve.py +157 -0
  84. core_10x/unit_tests/test_directory.py +54 -0
  85. core_10x/unit_tests/test_documentation.py +172 -0
  86. core_10x/unit_tests/test_environment_variables.py +15 -0
  87. core_10x/unit_tests/test_filters.py +239 -0
  88. core_10x/unit_tests/test_graph.py +348 -0
  89. core_10x/unit_tests/test_named_constant.py +98 -0
  90. core_10x/unit_tests/test_rc.py +11 -0
  91. core_10x/unit_tests/test_rdate.py +484 -0
  92. core_10x/unit_tests/test_trait_method_error.py +80 -0
  93. core_10x/unit_tests/test_trait_modification.py +19 -0
  94. core_10x/unit_tests/test_traitable.py +959 -0
  95. core_10x/unit_tests/test_traitable_history.py +1 -0
  96. core_10x/unit_tests/test_ts_store.py +1 -0
  97. core_10x/unit_tests/test_ts_union.py +369 -0
  98. core_10x/unit_tests/test_ui_nodes.py +81 -0
  99. core_10x/unit_tests/test_xxcalendar.py +471 -0
  100. core_10x/vault/__init__.py +0 -0
  101. core_10x/vault/sec_keys.py +133 -0
  102. core_10x/vault/security_keys_old.py +168 -0
  103. core_10x/vault/vault.py +56 -0
  104. core_10x/vault/vault_traitable.py +56 -0
  105. core_10x/vault/vault_user.py +70 -0
  106. core_10x/xdate_time.py +136 -0
  107. core_10x/xnone.py +71 -0
  108. core_10x/xxcalendar.py +228 -0
  109. infra_10x/__init__.py +0 -0
  110. infra_10x/manual_tests/__init__.py +0 -0
  111. infra_10x/manual_tests/test_misc.py +16 -0
  112. infra_10x/manual_tests/test_prepare_filter_and_pipeline.py +25 -0
  113. infra_10x/mongodb_admin.py +111 -0
  114. infra_10x/mongodb_store.py +346 -0
  115. infra_10x/mongodb_utils.py +129 -0
  116. infra_10x/unit_tests/conftest.py +13 -0
  117. infra_10x/unit_tests/test_mongo_db.py +36 -0
  118. infra_10x/unit_tests/test_mongo_history.py +1 -0
  119. py10x_universe-0.1.3.dist-info/METADATA +406 -0
  120. py10x_universe-0.1.3.dist-info/RECORD +214 -0
  121. py10x_universe-0.1.3.dist-info/WHEEL +4 -0
  122. py10x_universe-0.1.3.dist-info/licenses/LICENSE +21 -0
  123. ui_10x/__init__.py +0 -0
  124. ui_10x/apps/__init__.py +0 -0
  125. ui_10x/apps/collection_editor_app.py +100 -0
  126. ui_10x/choice.py +212 -0
  127. ui_10x/collection_editor.py +135 -0
  128. ui_10x/concrete_trait_widgets.py +220 -0
  129. ui_10x/conftest.py +8 -0
  130. ui_10x/entity_stocker.py +173 -0
  131. ui_10x/examples/__init__.py +0 -0
  132. ui_10x/examples/_guess_word_data.py +14076 -0
  133. ui_10x/examples/collection_editor.py +17 -0
  134. ui_10x/examples/date_selector.py +14 -0
  135. ui_10x/examples/entity_stocker.py +18 -0
  136. ui_10x/examples/guess_word.py +392 -0
  137. ui_10x/examples/message_box.py +20 -0
  138. ui_10x/examples/multi_choice.py +17 -0
  139. ui_10x/examples/py_data_browser.py +66 -0
  140. ui_10x/examples/radiobox.py +29 -0
  141. ui_10x/examples/single_choice.py +31 -0
  142. ui_10x/examples/style_sheet.py +47 -0
  143. ui_10x/examples/trivial_entity_editor.py +18 -0
  144. ui_10x/platform.py +20 -0
  145. ui_10x/platform_interface.py +517 -0
  146. ui_10x/py_data_browser.py +249 -0
  147. ui_10x/qt6/__init__.py +0 -0
  148. ui_10x/qt6/conftest.py +8 -0
  149. ui_10x/qt6/manual_tests/__init__.py +0 -0
  150. ui_10x/qt6/manual_tests/basic_test.py +35 -0
  151. ui_10x/qt6/platform_implementation.py +275 -0
  152. ui_10x/qt6/utils.py +665 -0
  153. ui_10x/rio/__init__.py +0 -0
  154. ui_10x/rio/apps/examples/examples/__init__.py +22 -0
  155. ui_10x/rio/apps/examples/examples/components/__init__.py +3 -0
  156. ui_10x/rio/apps/examples/examples/components/collection_editor.py +15 -0
  157. ui_10x/rio/apps/examples/examples/pages/collection_editor.py +21 -0
  158. ui_10x/rio/apps/examples/examples/pages/login_page.py +88 -0
  159. ui_10x/rio/apps/examples/examples/pages/style_sheet.py +21 -0
  160. ui_10x/rio/apps/examples/rio.toml +14 -0
  161. ui_10x/rio/component_builder.py +497 -0
  162. ui_10x/rio/components/__init__.py +9 -0
  163. ui_10x/rio/components/group_box.py +31 -0
  164. ui_10x/rio/components/labeled_checkbox.py +18 -0
  165. ui_10x/rio/components/line_edit.py +37 -0
  166. ui_10x/rio/components/radio_button.py +32 -0
  167. ui_10x/rio/components/separator.py +24 -0
  168. ui_10x/rio/components/splitter.py +121 -0
  169. ui_10x/rio/components/tree_view.py +75 -0
  170. ui_10x/rio/conftest.py +35 -0
  171. ui_10x/rio/internals/__init__.py +0 -0
  172. ui_10x/rio/internals/app.py +192 -0
  173. ui_10x/rio/manual_tests/__init__.py +0 -0
  174. ui_10x/rio/manual_tests/basic_test.py +24 -0
  175. ui_10x/rio/manual_tests/splitter.py +27 -0
  176. ui_10x/rio/platform_implementation.py +91 -0
  177. ui_10x/rio/style_sheet.py +53 -0
  178. ui_10x/rio/unit_tests/test_collection_editor.py +68 -0
  179. ui_10x/rio/unit_tests/test_internals.py +630 -0
  180. ui_10x/rio/unit_tests/test_style_sheet.py +37 -0
  181. ui_10x/rio/widgets/__init__.py +46 -0
  182. ui_10x/rio/widgets/application.py +109 -0
  183. ui_10x/rio/widgets/button.py +48 -0
  184. ui_10x/rio/widgets/button_group.py +60 -0
  185. ui_10x/rio/widgets/calendar.py +23 -0
  186. ui_10x/rio/widgets/checkbox.py +24 -0
  187. ui_10x/rio/widgets/dialog.py +137 -0
  188. ui_10x/rio/widgets/group_box.py +27 -0
  189. ui_10x/rio/widgets/layout.py +34 -0
  190. ui_10x/rio/widgets/line_edit.py +37 -0
  191. ui_10x/rio/widgets/list.py +105 -0
  192. ui_10x/rio/widgets/message_box.py +70 -0
  193. ui_10x/rio/widgets/scroll_area.py +31 -0
  194. ui_10x/rio/widgets/spacer.py +6 -0
  195. ui_10x/rio/widgets/splitter.py +45 -0
  196. ui_10x/rio/widgets/text_edit.py +28 -0
  197. ui_10x/rio/widgets/tree.py +89 -0
  198. ui_10x/rio/widgets/unit_tests/test_button.py +101 -0
  199. ui_10x/rio/widgets/unit_tests/test_button_group.py +33 -0
  200. ui_10x/rio/widgets/unit_tests/test_calendar.py +114 -0
  201. ui_10x/rio/widgets/unit_tests/test_checkbox.py +109 -0
  202. ui_10x/rio/widgets/unit_tests/test_group_box.py +158 -0
  203. ui_10x/rio/widgets/unit_tests/test_label.py +43 -0
  204. ui_10x/rio/widgets/unit_tests/test_line_edit.py +140 -0
  205. ui_10x/rio/widgets/unit_tests/test_list.py +146 -0
  206. ui_10x/table_header_view.py +305 -0
  207. ui_10x/table_view.py +174 -0
  208. ui_10x/trait_editor.py +189 -0
  209. ui_10x/trait_widget.py +131 -0
  210. ui_10x/traitable_editor.py +200 -0
  211. ui_10x/traitable_view.py +131 -0
  212. ui_10x/unit_tests/conftest.py +8 -0
  213. ui_10x/unit_tests/test_platform.py +9 -0
  214. ui_10x/utils.py +661 -0
@@ -0,0 +1,46 @@
1
+ from .application import Application, Style
2
+ from .button import Label, PushButton
3
+ from .button_group import ButtonGroup, RadioButton
4
+ from .calendar import CalendarWidget
5
+ from .checkbox import CheckBox
6
+ from .dialog import Dialog
7
+ from .group_box import GroupBox
8
+ from .layout import FormLayout, HBoxLayout, VBoxLayout
9
+ from .line_edit import LineEdit
10
+ from .list import FindFlags, ListItem, ListWidget
11
+ from .message_box import MessageBox, Separator
12
+ from .scroll_area import SCROLL, ScrollArea
13
+ from .spacer import Spacer
14
+ from .splitter import Direction, Splitter
15
+ from .text_edit import TextEdit
16
+ from .tree import TreeItem, TreeWidget
17
+
18
+ __all__ = [
19
+ 'SCROLL',
20
+ 'Application',
21
+ 'ButtonGroup',
22
+ 'CalendarWidget',
23
+ 'CheckBox',
24
+ 'Dialog',
25
+ 'Direction',
26
+ 'FindFlags',
27
+ 'FormLayout',
28
+ 'GroupBox',
29
+ 'HBoxLayout',
30
+ 'Label',
31
+ 'LineEdit',
32
+ 'ListItem',
33
+ 'ListWidget',
34
+ 'MessageBox',
35
+ 'PushButton',
36
+ 'RadioButton',
37
+ 'ScrollArea',
38
+ 'Separator',
39
+ 'Spacer',
40
+ 'Splitter',
41
+ 'Style',
42
+ 'TextEdit',
43
+ 'TreeItem',
44
+ 'TreeWidget',
45
+ 'VBoxLayout',
46
+ ]
@@ -0,0 +1,109 @@
1
+ from __future__ import annotations
2
+
3
+ from core_10x.named_constant import EnumBits
4
+
5
+ import ui_10x.platform_interface as i
6
+
7
+
8
+ class Style(i.Style):
9
+ class EnumMeta(type):
10
+ def __getattr__(cls, value):
11
+ if value != value.upper():
12
+ return getattr(cls, value.upper()).value
13
+
14
+ class StandardPixmap(EnumBits, metaclass=EnumMeta):
15
+ """Mapping of Qt QStyle::StandardPixmap values to Material Icons."""
16
+
17
+ # Dialog Buttons
18
+ SP_DIALOGAPPLYBUTTON = ('done',)
19
+ SP_DIALOGCANCELBUTTON = ('close',)
20
+ SP_DIALOGCLOSEBUTTON = ('close',)
21
+ SP_DIALOGDISCARDBUTTON = ('close',)
22
+ SP_DIALOGHELPBUTTON = ('help_outline',)
23
+ SP_DIALOGNOBUTTON = ('close',)
24
+ SP_DIALOGOKBUTTON = ('check',)
25
+ SP_DIALOGOPENBUTTON = ('folder_open',)
26
+ SP_DIALOGRESETBUTTON = ('restart_alt',)
27
+ SP_DIALOGSAVEBUTTON = ('save',)
28
+ SP_DIALOGYESBUTTON = ('check',)
29
+ # Arrows and Navigation
30
+ SP_ARROWBACK = ('arrow_back',)
31
+ SP_ARROWDOWN = ('arrow_downward',)
32
+ SP_ARROWFORWARD = ('arrow_forward',)
33
+ SP_ARROWLEFT = ('arrow_left',)
34
+ SP_ARROWRIGHT = ('arrow_right',)
35
+ SP_ARROWUP = ('arrow_upward',)
36
+ # File System and Folders
37
+ SP_DIRCLOSEDICON = ('folder',)
38
+ SP_DIRHOMEICON = ('home',)
39
+ SP_DIRICON = ('folder',)
40
+ SP_DIRLINKICON = ('folder_special',)
41
+ SP_DIROPENICON = ('folder_open',)
42
+ SP_FILEDIALOGBACK = ('arrow_back',)
43
+ SP_FILEDIALOGCONTENTSVIEW = ('view_list',)
44
+ SP_FILEDIALOGDETAILEDVIEW = ('grid_view',)
45
+ SP_FILEDIALOGEND = ('last_page',)
46
+ SP_FILEDIALOGINFOVIEW = ('info',)
47
+ SP_FILEDIALOGLISTVIEW = ('list',)
48
+ SP_FILEDIALOGNEWFOLDER = ('create_new_folder',)
49
+ SP_FILEDIALOGSTART = ('first_page',)
50
+ SP_FILEDIALOGTOPARENT = ('arrow_upward',)
51
+ SP_FILEICON = ('description',)
52
+ SP_FILELINKICON = ('insert_link',)
53
+ # Drives and Devices
54
+ SP_COMPUTERICON = ('computer',)
55
+ SP_DESKTOPICON = ('desktop_windows',)
56
+ SP_DRIVECDICON = ('album',)
57
+ SP_DRIVEDVDICON = ('album',)
58
+ SP_DRIVEFDICON = ('save',)
59
+ SP_DRIVEHDICON = ('storage',)
60
+ SP_DRIVENETICON = ('cloud',)
61
+ SP_HOMEICON = ('home',)
62
+ SP_TRASHICON = ('delete',)
63
+ # Media Controls
64
+ SP_MEDIAPAUSE = ('pause',)
65
+ SP_MEDIAPLAY = ('play_arrow',)
66
+ SP_MEDIASEEKBACKWARD = ('fast_rewind',)
67
+ SP_MEDIASEEKFORWARD = ('fast_forward',)
68
+ SP_MEDIASKIPBACKWARD = ('skip_previous',)
69
+ SP_MEDIASKIPFORWARD = ('skip_next',)
70
+ SP_MEDIASTOP = ('stop',)
71
+ SP_MEDIAVOLUME = ('volume_up',)
72
+ SP_MEDIAVOLUMEMUTED = ('volume_off',)
73
+ # Message Boxes
74
+ SP_MESSAGEBOXCRITICAL = ('error',)
75
+ SP_MESSAGEBOXINFORMATION = ('info',)
76
+ SP_MESSAGEBOXQUESTION = ('help',)
77
+ SP_MESSAGEBOXWARNING = ('warning',)
78
+ # Browser Controls
79
+ SP_BROWSERRELOAD = ('refresh',)
80
+ SP_BROWSERSTOP = ('stop',)
81
+ # Title Bar and Window Controls
82
+ SP_TITLEBARCLOSEBUTTON = ('close',)
83
+ SP_TITLEBARCONTEXTHELPBUTTON = ('help_outline',)
84
+ SP_TITLEBARMAXBUTTON = ('maximize',)
85
+ SP_TITLEBARMENUBUTTON = ('menu',)
86
+ SP_TITLEBARMINBUTTON = ('minimize',)
87
+ SP_TITLEBARNORMALBUTTON = ('restore',)
88
+ SP_TITLEBARSHADEBUTTON = ('expand_less',)
89
+ SP_TITLEBARUNSHADEBUTTON = ('expand_more',)
90
+ # Toolbar and Dock Widgets
91
+ SP_DOCKWIDGETCLOSEBUTTON = ('close',)
92
+ SP_TOOLBARHORIZONTALEXTENSIONBUTTON = ('chevron_right',)
93
+ SP_TOOLBARVERTICALEXTENSIONBUTTON = ('chevron_down',)
94
+ # Platform-Specific
95
+ SP_COMMANDLINK = ('arrow_right_alt',)
96
+ SP_VISTASHIELD = ('security',)
97
+
98
+ def standard_icon(self, style_icon: int):
99
+ return f'material/{self.StandardPixmap.s_reverse_dir[style_icon].label}'
100
+
101
+
102
+ class Application(i.Application):
103
+ @classmethod
104
+ def instance(cls) -> Application:
105
+ raise NotImplementedError()
106
+
107
+ @classmethod
108
+ def style(cls):
109
+ return Style()
@@ -0,0 +1,48 @@
1
+ from __future__ import annotations
2
+
3
+ import inspect
4
+ from functools import partial
5
+ from typing import TYPE_CHECKING
6
+
7
+ import rio
8
+ import ui_10x.platform_interface as i
9
+ from ui_10x.rio.component_builder import Widget
10
+
11
+ if TYPE_CHECKING:
12
+ from collections.abc import Callable
13
+
14
+
15
+ class Label(Widget, i.Label):
16
+ s_component_class = rio.Text
17
+ s_forced_kwargs = {'selectable': False} # , 'align_x': 0}
18
+ s_single_child = True
19
+ s_children_attr = 'text'
20
+ s_default_kwargs = {'text': ''}
21
+
22
+
23
+ class PushButton(Label, i.PushButton):
24
+ s_component_class = rio.Button
25
+ s_forced_kwargs = {}
26
+ s_children_attr = 'content'
27
+ s_default_kwargs = {'content': ''}
28
+
29
+ def clicked_connect(self, bound_method: Callable[[bool], None]):
30
+ unbound_params = [
31
+ p.name for p in inspect.signature(bound_method).parameters.values() if p.default is p.empty and not p.kind.name.startswith('VAR_')
32
+ ]
33
+ assert len(unbound_params) < 2, f'Expected 0 or 1 unbound parameters in {bound_method.__name__}, but found {unbound_params}'
34
+ if len(unbound_params) > 0:
35
+ bound_method = partial(bound_method, False)
36
+ self['on_press'] = self.callback(bound_method)
37
+
38
+ def set_flat(self, flat: bool):
39
+ self['style'] = 'plain-text' if flat else 'major'
40
+
41
+ def __init__(self, *args, **kwargs):
42
+ super().__init__(**kwargs)
43
+ if args:
44
+ label = args[-1]
45
+ assert label is not None
46
+ icon = args[0] if len(args) > 1 else None
47
+ self.set_text(label)
48
+ self['icon'] = icon
@@ -0,0 +1,60 @@
1
+ from __future__ import annotations
2
+
3
+ import ui_10x.platform_interface as i
4
+ import ui_10x.rio.components as rio_components
5
+ from ui_10x.rio.component_builder import Widget
6
+
7
+
8
+ class RadioButton(Widget, i.RadioButton):
9
+ __slots__ = '_button_group'
10
+ s_component_class = rio_components.RadioButton
11
+
12
+ def __init__(self, *args, **kwargs):
13
+ super().__init__(*args, **kwargs)
14
+ if 'label' not in self._kwargs:
15
+ self['label'] = self.get_children().pop(0)
16
+ if 'value' not in self._kwargs:
17
+ self['value'] = self._kwargs['label']
18
+ self['on_select'] = self.on_select
19
+ self['checked'] = False
20
+ self._button_group = None
21
+
22
+ def set_checked(self, checked: bool):
23
+ self['checked'] = checked
24
+ if self._button_group:
25
+ self._button_group.on_change(self)
26
+
27
+ def on_select(self):
28
+ self.set_checked(not self['checked'])
29
+
30
+
31
+ class ButtonGroup(Widget, i.ButtonGroup):
32
+ s_component_class = rio_components.GroupBox
33
+ s_pass_children_in_kwargs = True
34
+
35
+ def __init__(self, *args, **kwargs):
36
+ super().__init__(*args, **kwargs)
37
+
38
+ def on_change(self, changed_button: RadioButton):
39
+ if changed_button['checked']:
40
+ for child in self.get_children():
41
+ if child is not changed_button:
42
+ child['checked'] = False
43
+
44
+ def add_button(self, button, id):
45
+ if id < len(self.get_children()):
46
+ self.get_children()[id] = button
47
+ else:
48
+ assert len(self.get_children()) == id
49
+ self.get_children().append(button)
50
+ button._button_group = self
51
+
52
+ def button(self, id: int) -> RadioButton:
53
+ return self.get_children()[id]
54
+
55
+ def checked_id(self):
56
+ # TODO: optimize
57
+ for idx, button in enumerate(self.get_children()):
58
+ if button['checked']:
59
+ return idx
60
+ return -1
@@ -0,0 +1,23 @@
1
+ from __future__ import annotations
2
+
3
+ from datetime import date
4
+
5
+ import rio
6
+ import ui_10x.platform_interface as i
7
+ from ui_10x.rio.component_builder import Widget
8
+
9
+
10
+ class CalendarWidget(Widget, i.CalendarWidget):
11
+ s_component_class = rio.Calendar
12
+ s_default_kwargs = dict(value=date.today())
13
+ s_children_attr = 'value'
14
+ s_single_child = True
15
+
16
+ def set_grid_visible(self, grid_visible: bool):
17
+ pass
18
+
19
+ def set_selected_date(self, selected_date: date):
20
+ self['value'] = selected_date
21
+
22
+ def selected_date(self) -> date:
23
+ return self['value']
@@ -0,0 +1,24 @@
1
+ from __future__ import annotations
2
+
3
+ import ui_10x.platform_interface as i
4
+ import ui_10x.rio.components as rio_components
5
+ from ui_10x.rio.component_builder import Widget
6
+
7
+
8
+ class CheckBox(Widget, i.CheckBox):
9
+ s_component_class = rio_components.LabeledCheckBox
10
+
11
+ def set_checked(self, checked: bool):
12
+ self['is_on'] = checked
13
+
14
+ def is_checked(self) -> bool:
15
+ return self['is_on']
16
+
17
+ def state_changed_connect(self, bound_method):
18
+ def state_change_handler(event):
19
+ bound_method(event.is_on)
20
+
21
+ self['on_change'] = self.callback(state_change_handler)
22
+
23
+ def set_text(self, text: str):
24
+ self['label'] = text
@@ -0,0 +1,137 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ import rio
6
+ import ui_10x.platform_interface as i
7
+ from ui_10x.rio.component_builder import DynamicComponent, UserSessionContext, Widget
8
+ from ui_10x.rio.internals.app import App10x
9
+
10
+ if TYPE_CHECKING:
11
+ import uvicorn
12
+
13
+
14
+ class Dialog(Widget, i.Dialog):
15
+ __slots__ = ('_dialog', '_modal', '_parent', '_server', 'accepted', 'on_accept', 'on_reject', 'title')
16
+ s_component_class = rio.Column
17
+ s_forced_kwargs = {'grow_x': True, 'grow_y': True}
18
+
19
+ def _make_kwargs(self, **kwargs):
20
+ kwargs = super()._make_kwargs(**kwargs)
21
+ del kwargs['align_y']
22
+ return kwargs
23
+
24
+ def __init__(self, parent: Widget | None = None, children=(), title=None, on_accept=None, on_reject=None, **kwargs):
25
+ assert isinstance(parent, Widget | None)
26
+ super().__init__(*children, **kwargs)
27
+ self.on_accept = self._wrapper(on_accept, accept=True)
28
+ self.on_reject = self._wrapper(on_reject)
29
+ self.accepted = True
30
+ self.title = title
31
+ self._dialog = None
32
+ self._server = None
33
+ self._parent = parent
34
+ self._modal = True
35
+
36
+ def set_window_title(self, title: str):
37
+ self.title = title
38
+
39
+ def _wrapper(self, func, accept=False):
40
+ func = self.callback(func) if func else None
41
+
42
+ def wrapper(*args):
43
+ self.accepted = accept
44
+ if func:
45
+ func(*args)
46
+ self._on_close()
47
+
48
+ return wrapper
49
+
50
+ def reject(self):
51
+ self._on_close()
52
+
53
+ def done(self, result: int):
54
+ self._on_close()
55
+ self.accepted = bool(result)
56
+
57
+ def _on_close(self):
58
+ if self._dialog:
59
+ dialog = self._dialog.result()
60
+ dialog._root_component.session.create_task(dialog.close())
61
+ self._dialog = None
62
+ elif self._server:
63
+ self._server.should_exit = True
64
+
65
+ def _on_server_created(self, server: uvicorn.Server):
66
+ self._server = server
67
+
68
+ def _on_dialog_open(self, future):
69
+ self._dialog = future
70
+
71
+ def exec(self):
72
+ if self.current_session():
73
+ print('Cannot exec() in an existing event loop - using show() instead. WARNING: this only works with callbacks!')
74
+ self.show()
75
+ return
76
+
77
+ assert not self._parent, 'Parent is not allowed for top level dialog'
78
+
79
+ title = self.title or 'Dialog'
80
+ sessions = set()
81
+
82
+ def on_session_start(session):
83
+ sessions.add(session)
84
+ print('on_session_start:', len(sessions))
85
+
86
+ def on_session_close(session):
87
+ for component in session._weak_components_by_id.values():
88
+ if isinstance(component, DynamicComponent):
89
+ component.builder.component = None
90
+ component.builder.subcomponent = None
91
+ sessions.remove(session)
92
+ print('on_session_close:', len(sessions))
93
+
94
+ def build():
95
+ print('build:', len(sessions))
96
+ if len(sessions) == 1:
97
+ component = DynamicComponent(builder=self)
98
+ if component.session in sessions:
99
+ return component
100
+
101
+ from rio.components.error_placeholder import ErrorPlaceholder
102
+
103
+ return ErrorPlaceholder(error_summary='Only one session is allowed for `Dialog.exec`', error_details='')
104
+
105
+ app = rio.App(
106
+ name=title,
107
+ build=build,
108
+ on_session_start=on_session_start,
109
+ on_session_close=on_session_close,
110
+ default_attachments=[UserSessionContext(host='localhost', dbname='test')],
111
+ )
112
+ debug = True
113
+ if debug:
114
+ from rio.debug.monkeypatches import apply_monkeypatches
115
+
116
+ apply_monkeypatches()
117
+ App10x(app)._run_in_window(debug_mode=debug, on_server_created=self._on_server_created)
118
+ return self.accepted
119
+
120
+ def show(self):
121
+ if not self.current_session():
122
+ self.exec()
123
+ else:
124
+ future = self.current_session().show_custom_dialog(
125
+ build=self,
126
+ on_close=self._on_close,
127
+ modal=self._modal,
128
+ user_closable=False,
129
+ owning_component=self._parent.component if self._parent else None,
130
+ )
131
+ self.current_session().create_task(future).add_done_callback(self._on_dialog_open)
132
+
133
+ def set_window_flags(self, flags):
134
+ raise NotImplementedError
135
+
136
+ def set_modal(self, modal: bool):
137
+ self._modal = modal
@@ -0,0 +1,27 @@
1
+ from __future__ import annotations
2
+
3
+ import ui_10x.platform_interface as i
4
+ import ui_10x.rio.components as rio_components
5
+ from ui_10x.rio.component_builder import Widget
6
+
7
+
8
+ class GroupBox(Widget, i.GroupBox):
9
+ s_component_class = rio_components.GroupBox
10
+ s_pass_children_in_kwargs = True
11
+ s_unwrap_single_child = False
12
+
13
+ def __init__(self, *args, **kwargs):
14
+ _parent = None
15
+ title = kwargs.pop('title', '')
16
+ children = ()
17
+ if len(args) == 1:
18
+ _parent = args[0]
19
+ elif len(args) >= 2:
20
+ assert not title, 'title specified twice'
21
+ _parent, title = args[:2]
22
+ children = args[2:]
23
+ super().__init__(*children, **kwargs)
24
+ self['title'] = title
25
+
26
+ def set_title(self, title: str):
27
+ self['title'] = title
@@ -0,0 +1,34 @@
1
+ from __future__ import annotations
2
+
3
+ import rio
4
+ import ui_10x.platform_interface as i
5
+ from ui_10x.rio.component_builder import Layout
6
+
7
+
8
+ class BoxLayout(Layout): ...
9
+
10
+
11
+ class VBoxLayout(BoxLayout, i.VBoxLayout):
12
+ s_component_class = rio.Column
13
+ s_stretch_arg = 'grow_y'
14
+
15
+ def _make_kwargs(self, **kwargs):
16
+ kwargs = super()._make_kwargs(**kwargs)
17
+ del kwargs['align_y']
18
+ return kwargs
19
+
20
+
21
+ class HBoxLayout(BoxLayout, i.HBoxLayout):
22
+ s_component_class = rio.Row
23
+ s_stretch_arg = 'grow_x'
24
+
25
+
26
+ class FormLayout(Layout, i.FormLayout):
27
+ s_component_class = rio.Grid
28
+ s_children_attr = 'rows'
29
+
30
+ def add_row(self, *args):
31
+ self.add_children(args)
32
+
33
+ def _build_children(self, session: rio.Session):
34
+ return [[child() for child in children] for children in self._get_children()] # children are 2d array
@@ -0,0 +1,37 @@
1
+ from __future__ import annotations
2
+
3
+ import ui_10x.platform_interface as i
4
+ import ui_10x.rio.components as rio_components
5
+ from ui_10x.rio.component_builder import MouseEvent, Widget
6
+
7
+
8
+ class LineEdit(Widget, i.LineEdit):
9
+ s_default_kwargs = dict(text='')
10
+ s_component_class = rio_components.LineEditComponent
11
+ s_single_child = True
12
+ s_children_attr = 'text'
13
+
14
+ def set_text(self, text: str):
15
+ self['text'] = text or ''
16
+
17
+ def text(self):
18
+ return self['text']
19
+
20
+ def text_edited_connect(self, bound_method):
21
+ self['on_change'] = self.callback(lambda ev: bound_method(ev.text))
22
+
23
+ def set_password_mode(self):
24
+ self['is_secret'] = True
25
+
26
+ def editing_finished_connect(self, bound_method):
27
+ self['on_lose_focus'] = self.callback(lambda ev: bound_method())
28
+
29
+ def _make_kwargs(self, **kwargs):
30
+ kw = super()._make_kwargs(**kwargs)
31
+ handler = self.mouse_press_event
32
+ if handler.__func__ != LineEdit.mouse_press_event: # do not set unless re-implemented
33
+ kw['on_pointer_up'] = self.callback(lambda event: handler(MouseEvent(event)))
34
+ return kw
35
+
36
+ def mouse_press_event(self, event: i.MouseEvent):
37
+ pass
@@ -0,0 +1,105 @@
1
+ from __future__ import annotations
2
+
3
+ from functools import partial
4
+
5
+ from core_10x.named_constant import Enum
6
+
7
+ import rio
8
+ import ui_10x.platform_interface as i
9
+ from ui_10x.rio.component_builder import Widget
10
+
11
+
12
+ class FindFlags(Enum):
13
+ MATCH_EXACTLY = ()
14
+
15
+
16
+ class ListItem(Widget, i.ListItem):
17
+ __slots__ = ('_list_widget',)
18
+ s_component_class = rio.SimpleListItem
19
+ args = dict(key=lambda kwargs: kwargs['text'])
20
+
21
+ def _make_kwargs(self, **kwargs):
22
+ kwargs = super()._make_kwargs(**kwargs)
23
+ del kwargs['align_y']
24
+ return kwargs
25
+
26
+ def __init__(self, *args, **kwargs):
27
+ super().__init__(*args, **kwargs)
28
+ self._list_widget = None
29
+
30
+ def row(self):
31
+ if self._list_widget:
32
+ return self._list_widget.row(self)
33
+
34
+ def set_selected(self, selected: bool):
35
+ return self._list_widget.set_selected(self, selected)
36
+
37
+
38
+ class ListWidget(Widget, i.ListWidget):
39
+ __slots__ = ('_on_press',)
40
+ s_component_class = rio.ListView
41
+ s_default_kwargs = dict(selection_mode='single')
42
+ s_unwrap_single_child = False
43
+
44
+ def __init__(self, *args, **kwargs):
45
+ super().__init__(*args, **kwargs)
46
+ self['grow_y'] = True
47
+
48
+ def add_items(self, items: list[i.ListItem | str]):
49
+ for item in items:
50
+ self.add_item(item)
51
+
52
+ def clicked_connect(self, bound_method):
53
+ self._on_press = self.callback(bound_method)
54
+
55
+ def _handle_on_press(self, item):
56
+ if self._on_press:
57
+ self._on_press(item)
58
+
59
+ def add_item(self, item: ListItem | str):
60
+ item = ListItem(text=item) if isinstance(item, str) else item
61
+ item['on_press'] = partial(self._handle_on_press, item)
62
+ item._list_widget = self
63
+ self._kwargs[self.s_children_attr].append(item)
64
+ self.force_update()
65
+
66
+ def clear(self):
67
+ self._kwargs['children'] = []
68
+ self._kwargs['selected_items'] = []
69
+ self.force_update()
70
+
71
+ def find_items(self, text, flags):
72
+ assert flags == FindFlags.MATCH_EXACTLY, 'only MatchExactly supported'
73
+ return [item for item in self._kwargs[self.s_children_attr] if text == item['text']]
74
+
75
+ def row(self, item: ListItem) -> int:
76
+ return self._kwargs[self.s_children_attr].index(item)
77
+
78
+ def take_item(self, row: int):
79
+ try:
80
+ return self._kwargs[self.s_children_attr].pop(row)
81
+ finally:
82
+ self.force_update()
83
+
84
+ def set_selected(self, item: ListItem, selected: bool):
85
+ # TODO: this is called from on-click handler for list item, which is
86
+ # inefficient and duplicates rio built-in functionality
87
+ selected_items = self.setdefault('selected_items', [])
88
+ key = item['key']
89
+ old_selected = key in selected_items
90
+ print(selected_items, selected, old_selected, key)
91
+
92
+ if not old_selected and selected:
93
+ if self['selection_mode'] == 'single':
94
+ selected_items = []
95
+ selected_items.append(key)
96
+
97
+ if old_selected and not selected:
98
+ selected_items.remove(key)
99
+ print(selected_items)
100
+ self['selected_items'] = selected_items
101
+
102
+ def set_enabled(self, enabled: bool):
103
+ self['selection_mode'] = 'single' if enabled else 'none'
104
+ for item in self._kwargs[self.s_children_attr]:
105
+ item['on_press'] = partial(self._handle_on_press, item) if enabled else None