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.
- core_10x/__init__.py +42 -0
- core_10x/backbone/__init__.py +0 -0
- core_10x/backbone/backbone_store.py +59 -0
- core_10x/backbone/backbone_traitable.py +30 -0
- core_10x/backbone/backbone_user.py +66 -0
- core_10x/backbone/bound_data_domain.py +49 -0
- core_10x/backbone/namespace.py +101 -0
- core_10x/backbone/vault.py +38 -0
- core_10x/code_samples/__init__.py +0 -0
- core_10x/code_samples/_package_manifest.py +3 -0
- core_10x/code_samples/directories.py +181 -0
- core_10x/code_samples/person.py +76 -0
- core_10x/concrete_traits.py +356 -0
- core_10x/conftest.py +12 -0
- core_10x/curve.py +321 -0
- core_10x/data_domain.py +48 -0
- core_10x/data_domain_binder.py +45 -0
- core_10x/directory.py +250 -0
- core_10x/entity.py +8 -0
- core_10x/entity_filter.py +5 -0
- core_10x/environment_variables.py +147 -0
- core_10x/exec_control.py +84 -0
- core_10x/experimental/__init__.py +0 -0
- core_10x/experimental/data_protocol_ex.py +34 -0
- core_10x/global_cache.py +121 -0
- core_10x/manual_tests/__init__.py +0 -0
- core_10x/manual_tests/calendar_test.py +35 -0
- core_10x/manual_tests/ctor_update_bug.py +58 -0
- core_10x/manual_tests/debug_graph_on.py +17 -0
- core_10x/manual_tests/debug_graphoff_inside_graph_on.py +28 -0
- core_10x/manual_tests/enum_bits_test.py +17 -0
- core_10x/manual_tests/env_vars_trivial_test.py +12 -0
- core_10x/manual_tests/existing_traitable.py +33 -0
- core_10x/manual_tests/k10x_test1.py +13 -0
- core_10x/manual_tests/named_constant_test.py +121 -0
- core_10x/manual_tests/nucleus_trivial_test.py +42 -0
- core_10x/manual_tests/polars_test.py +14 -0
- core_10x/manual_tests/py_class_test.py +4 -0
- core_10x/manual_tests/rc_test.py +42 -0
- core_10x/manual_tests/rdate_test.py +12 -0
- core_10x/manual_tests/reference_serialization_bug.py +19 -0
- core_10x/manual_tests/resource_trivial_test.py +10 -0
- core_10x/manual_tests/store_uri_test.py +6 -0
- core_10x/manual_tests/trait_definition_test.py +19 -0
- core_10x/manual_tests/trait_filter_test.py +15 -0
- core_10x/manual_tests/trait_flag_modification_test.py +42 -0
- core_10x/manual_tests/trait_modification_bug.py +26 -0
- core_10x/manual_tests/traitable_as_of_test.py +82 -0
- core_10x/manual_tests/traitable_heir_test.py +39 -0
- core_10x/manual_tests/traitable_history_test.py +41 -0
- core_10x/manual_tests/traitable_serialization_test.py +54 -0
- core_10x/manual_tests/traitable_trivial_test.py +71 -0
- core_10x/manual_tests/trivial_graph_test.py +16 -0
- core_10x/manual_tests/ts_class_association_test.py +64 -0
- core_10x/manual_tests/ts_trivial_test.py +35 -0
- core_10x/named_constant.py +425 -0
- core_10x/nucleus.py +81 -0
- core_10x/package_manifest.py +85 -0
- core_10x/package_refactoring.py +153 -0
- core_10x/py_class.py +431 -0
- core_10x/rc.py +155 -0
- core_10x/rdate.py +339 -0
- core_10x/resource.py +189 -0
- core_10x/roman_number.py +67 -0
- core_10x/testlib/__init__.py +0 -0
- core_10x/testlib/test_store.py +240 -0
- core_10x/testlib/traitable_history_tests.py +787 -0
- core_10x/testlib/ts_tests.py +280 -0
- core_10x/trait.py +377 -0
- core_10x/trait_definition.py +176 -0
- core_10x/trait_filter.py +205 -0
- core_10x/trait_method_error.py +36 -0
- core_10x/traitable.py +1082 -0
- core_10x/traitable_cli.py +153 -0
- core_10x/traitable_heir.py +33 -0
- core_10x/traitable_id.py +31 -0
- core_10x/ts_store.py +172 -0
- core_10x/ts_store_type.py +26 -0
- core_10x/ts_union.py +147 -0
- core_10x/ui_hint.py +153 -0
- core_10x/unit_tests/test_concrete_traits.py +156 -0
- core_10x/unit_tests/test_converters.py +51 -0
- core_10x/unit_tests/test_curve.py +157 -0
- core_10x/unit_tests/test_directory.py +54 -0
- core_10x/unit_tests/test_documentation.py +172 -0
- core_10x/unit_tests/test_environment_variables.py +15 -0
- core_10x/unit_tests/test_filters.py +239 -0
- core_10x/unit_tests/test_graph.py +348 -0
- core_10x/unit_tests/test_named_constant.py +98 -0
- core_10x/unit_tests/test_rc.py +11 -0
- core_10x/unit_tests/test_rdate.py +484 -0
- core_10x/unit_tests/test_trait_method_error.py +80 -0
- core_10x/unit_tests/test_trait_modification.py +19 -0
- core_10x/unit_tests/test_traitable.py +959 -0
- core_10x/unit_tests/test_traitable_history.py +1 -0
- core_10x/unit_tests/test_ts_store.py +1 -0
- core_10x/unit_tests/test_ts_union.py +369 -0
- core_10x/unit_tests/test_ui_nodes.py +81 -0
- core_10x/unit_tests/test_xxcalendar.py +471 -0
- core_10x/vault/__init__.py +0 -0
- core_10x/vault/sec_keys.py +133 -0
- core_10x/vault/security_keys_old.py +168 -0
- core_10x/vault/vault.py +56 -0
- core_10x/vault/vault_traitable.py +56 -0
- core_10x/vault/vault_user.py +70 -0
- core_10x/xdate_time.py +136 -0
- core_10x/xnone.py +71 -0
- core_10x/xxcalendar.py +228 -0
- infra_10x/__init__.py +0 -0
- infra_10x/manual_tests/__init__.py +0 -0
- infra_10x/manual_tests/test_misc.py +16 -0
- infra_10x/manual_tests/test_prepare_filter_and_pipeline.py +25 -0
- infra_10x/mongodb_admin.py +111 -0
- infra_10x/mongodb_store.py +346 -0
- infra_10x/mongodb_utils.py +129 -0
- infra_10x/unit_tests/conftest.py +13 -0
- infra_10x/unit_tests/test_mongo_db.py +36 -0
- infra_10x/unit_tests/test_mongo_history.py +1 -0
- py10x_universe-0.1.3.dist-info/METADATA +406 -0
- py10x_universe-0.1.3.dist-info/RECORD +214 -0
- py10x_universe-0.1.3.dist-info/WHEEL +4 -0
- py10x_universe-0.1.3.dist-info/licenses/LICENSE +21 -0
- ui_10x/__init__.py +0 -0
- ui_10x/apps/__init__.py +0 -0
- ui_10x/apps/collection_editor_app.py +100 -0
- ui_10x/choice.py +212 -0
- ui_10x/collection_editor.py +135 -0
- ui_10x/concrete_trait_widgets.py +220 -0
- ui_10x/conftest.py +8 -0
- ui_10x/entity_stocker.py +173 -0
- ui_10x/examples/__init__.py +0 -0
- ui_10x/examples/_guess_word_data.py +14076 -0
- ui_10x/examples/collection_editor.py +17 -0
- ui_10x/examples/date_selector.py +14 -0
- ui_10x/examples/entity_stocker.py +18 -0
- ui_10x/examples/guess_word.py +392 -0
- ui_10x/examples/message_box.py +20 -0
- ui_10x/examples/multi_choice.py +17 -0
- ui_10x/examples/py_data_browser.py +66 -0
- ui_10x/examples/radiobox.py +29 -0
- ui_10x/examples/single_choice.py +31 -0
- ui_10x/examples/style_sheet.py +47 -0
- ui_10x/examples/trivial_entity_editor.py +18 -0
- ui_10x/platform.py +20 -0
- ui_10x/platform_interface.py +517 -0
- ui_10x/py_data_browser.py +249 -0
- ui_10x/qt6/__init__.py +0 -0
- ui_10x/qt6/conftest.py +8 -0
- ui_10x/qt6/manual_tests/__init__.py +0 -0
- ui_10x/qt6/manual_tests/basic_test.py +35 -0
- ui_10x/qt6/platform_implementation.py +275 -0
- ui_10x/qt6/utils.py +665 -0
- ui_10x/rio/__init__.py +0 -0
- ui_10x/rio/apps/examples/examples/__init__.py +22 -0
- ui_10x/rio/apps/examples/examples/components/__init__.py +3 -0
- ui_10x/rio/apps/examples/examples/components/collection_editor.py +15 -0
- ui_10x/rio/apps/examples/examples/pages/collection_editor.py +21 -0
- ui_10x/rio/apps/examples/examples/pages/login_page.py +88 -0
- ui_10x/rio/apps/examples/examples/pages/style_sheet.py +21 -0
- ui_10x/rio/apps/examples/rio.toml +14 -0
- ui_10x/rio/component_builder.py +497 -0
- ui_10x/rio/components/__init__.py +9 -0
- ui_10x/rio/components/group_box.py +31 -0
- ui_10x/rio/components/labeled_checkbox.py +18 -0
- ui_10x/rio/components/line_edit.py +37 -0
- ui_10x/rio/components/radio_button.py +32 -0
- ui_10x/rio/components/separator.py +24 -0
- ui_10x/rio/components/splitter.py +121 -0
- ui_10x/rio/components/tree_view.py +75 -0
- ui_10x/rio/conftest.py +35 -0
- ui_10x/rio/internals/__init__.py +0 -0
- ui_10x/rio/internals/app.py +192 -0
- ui_10x/rio/manual_tests/__init__.py +0 -0
- ui_10x/rio/manual_tests/basic_test.py +24 -0
- ui_10x/rio/manual_tests/splitter.py +27 -0
- ui_10x/rio/platform_implementation.py +91 -0
- ui_10x/rio/style_sheet.py +53 -0
- ui_10x/rio/unit_tests/test_collection_editor.py +68 -0
- ui_10x/rio/unit_tests/test_internals.py +630 -0
- ui_10x/rio/unit_tests/test_style_sheet.py +37 -0
- ui_10x/rio/widgets/__init__.py +46 -0
- ui_10x/rio/widgets/application.py +109 -0
- ui_10x/rio/widgets/button.py +48 -0
- ui_10x/rio/widgets/button_group.py +60 -0
- ui_10x/rio/widgets/calendar.py +23 -0
- ui_10x/rio/widgets/checkbox.py +24 -0
- ui_10x/rio/widgets/dialog.py +137 -0
- ui_10x/rio/widgets/group_box.py +27 -0
- ui_10x/rio/widgets/layout.py +34 -0
- ui_10x/rio/widgets/line_edit.py +37 -0
- ui_10x/rio/widgets/list.py +105 -0
- ui_10x/rio/widgets/message_box.py +70 -0
- ui_10x/rio/widgets/scroll_area.py +31 -0
- ui_10x/rio/widgets/spacer.py +6 -0
- ui_10x/rio/widgets/splitter.py +45 -0
- ui_10x/rio/widgets/text_edit.py +28 -0
- ui_10x/rio/widgets/tree.py +89 -0
- ui_10x/rio/widgets/unit_tests/test_button.py +101 -0
- ui_10x/rio/widgets/unit_tests/test_button_group.py +33 -0
- ui_10x/rio/widgets/unit_tests/test_calendar.py +114 -0
- ui_10x/rio/widgets/unit_tests/test_checkbox.py +109 -0
- ui_10x/rio/widgets/unit_tests/test_group_box.py +158 -0
- ui_10x/rio/widgets/unit_tests/test_label.py +43 -0
- ui_10x/rio/widgets/unit_tests/test_line_edit.py +140 -0
- ui_10x/rio/widgets/unit_tests/test_list.py +146 -0
- ui_10x/table_header_view.py +305 -0
- ui_10x/table_view.py +174 -0
- ui_10x/trait_editor.py +189 -0
- ui_10x/trait_widget.py +131 -0
- ui_10x/traitable_editor.py +200 -0
- ui_10x/traitable_view.py +131 -0
- ui_10x/unit_tests/conftest.py +8 -0
- ui_10x/unit_tests/test_platform.py +9 -0
- 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
|