pythonnative 0.4.0__py3-none-any.whl → 0.5.0__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.
- pythonnative/__init__.py +45 -65
- pythonnative/cli/pn.py +15 -14
- pythonnative/components.py +241 -0
- pythonnative/element.py +47 -0
- pythonnative/native_views.py +800 -0
- pythonnative/page.py +319 -247
- pythonnative/reconciler.py +129 -0
- pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/PageFragment.kt +2 -1
- pythonnative/utils.py +21 -29
- {pythonnative-0.4.0.dist-info → pythonnative-0.5.0.dist-info}/METADATA +35 -17
- {pythonnative-0.4.0.dist-info → pythonnative-0.5.0.dist-info}/RECORD +15 -35
- pythonnative/activity_indicator_view.py +0 -71
- pythonnative/button.py +0 -113
- pythonnative/date_picker.py +0 -76
- pythonnative/image_view.py +0 -78
- pythonnative/label.py +0 -133
- pythonnative/list_view.py +0 -76
- pythonnative/material_activity_indicator_view.py +0 -71
- pythonnative/material_button.py +0 -69
- pythonnative/material_date_picker.py +0 -87
- pythonnative/material_progress_view.py +0 -70
- pythonnative/material_search_bar.py +0 -69
- pythonnative/material_switch.py +0 -69
- pythonnative/material_time_picker.py +0 -76
- pythonnative/picker_view.py +0 -69
- pythonnative/progress_view.py +0 -70
- pythonnative/scroll_view.py +0 -101
- pythonnative/search_bar.py +0 -69
- pythonnative/stack_view.py +0 -199
- pythonnative/switch.py +0 -68
- pythonnative/text_field.py +0 -132
- pythonnative/text_view.py +0 -135
- pythonnative/time_picker.py +0 -77
- pythonnative/view.py +0 -173
- pythonnative/web_view.py +0 -60
- {pythonnative-0.4.0.dist-info → pythonnative-0.5.0.dist-info}/WHEEL +0 -0
- {pythonnative-0.4.0.dist-info → pythonnative-0.5.0.dist-info}/entry_points.txt +0 -0
- {pythonnative-0.4.0.dist-info → pythonnative-0.5.0.dist-info}/licenses/LICENSE +0 -0
- {pythonnative-0.4.0.dist-info → pythonnative-0.5.0.dist-info}/top_level.txt +0 -0
pythonnative/switch.py
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
from abc import ABC, abstractmethod
|
|
2
|
-
|
|
3
|
-
from .utils import IS_ANDROID, get_android_context
|
|
4
|
-
from .view import ViewBase
|
|
5
|
-
|
|
6
|
-
# ========================================
|
|
7
|
-
# Base class
|
|
8
|
-
# ========================================
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class SwitchBase(ABC):
|
|
12
|
-
@abstractmethod
|
|
13
|
-
def __init__(self) -> None:
|
|
14
|
-
super().__init__()
|
|
15
|
-
|
|
16
|
-
@abstractmethod
|
|
17
|
-
def set_on(self, value: bool) -> "SwitchBase":
|
|
18
|
-
pass
|
|
19
|
-
|
|
20
|
-
@abstractmethod
|
|
21
|
-
def is_on(self) -> bool:
|
|
22
|
-
pass
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if IS_ANDROID:
|
|
26
|
-
# ========================================
|
|
27
|
-
# Android class
|
|
28
|
-
# https://developer.android.com/reference/android/widget/Switch
|
|
29
|
-
# ========================================
|
|
30
|
-
|
|
31
|
-
from java import jclass
|
|
32
|
-
|
|
33
|
-
class Switch(SwitchBase, ViewBase):
|
|
34
|
-
def __init__(self, value: bool = False) -> None:
|
|
35
|
-
super().__init__()
|
|
36
|
-
self.native_class = jclass("android.widget.Switch")
|
|
37
|
-
context = get_android_context()
|
|
38
|
-
self.native_instance = self.native_class(context)
|
|
39
|
-
self.set_on(value)
|
|
40
|
-
|
|
41
|
-
def set_on(self, value: bool) -> "Switch":
|
|
42
|
-
self.native_instance.setChecked(value)
|
|
43
|
-
return self
|
|
44
|
-
|
|
45
|
-
def is_on(self) -> bool:
|
|
46
|
-
return self.native_instance.isChecked()
|
|
47
|
-
|
|
48
|
-
else:
|
|
49
|
-
# ========================================
|
|
50
|
-
# iOS class
|
|
51
|
-
# https://developer.apple.com/documentation/uikit/uiswitch
|
|
52
|
-
# ========================================
|
|
53
|
-
|
|
54
|
-
from rubicon.objc import ObjCClass
|
|
55
|
-
|
|
56
|
-
class Switch(SwitchBase, ViewBase):
|
|
57
|
-
def __init__(self, value: bool = False) -> None:
|
|
58
|
-
super().__init__()
|
|
59
|
-
self.native_class = ObjCClass("UISwitch")
|
|
60
|
-
self.native_instance = self.native_class.alloc().init()
|
|
61
|
-
self.set_on(value)
|
|
62
|
-
|
|
63
|
-
def set_on(self, value: bool) -> "Switch":
|
|
64
|
-
self.native_instance.setOn_animated_(value, False)
|
|
65
|
-
return self
|
|
66
|
-
|
|
67
|
-
def is_on(self) -> bool:
|
|
68
|
-
return self.native_instance.isOn()
|
pythonnative/text_field.py
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
from abc import ABC, abstractmethod
|
|
2
|
-
from typing import Any
|
|
3
|
-
|
|
4
|
-
from .utils import IS_ANDROID, get_android_context
|
|
5
|
-
from .view import ViewBase
|
|
6
|
-
|
|
7
|
-
# ========================================
|
|
8
|
-
# Base class
|
|
9
|
-
# ========================================
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class TextFieldBase(ABC):
|
|
13
|
-
@abstractmethod
|
|
14
|
-
def __init__(self) -> None:
|
|
15
|
-
super().__init__()
|
|
16
|
-
|
|
17
|
-
@abstractmethod
|
|
18
|
-
def set_text(self, text: str) -> "TextFieldBase":
|
|
19
|
-
pass
|
|
20
|
-
|
|
21
|
-
@abstractmethod
|
|
22
|
-
def get_text(self) -> str:
|
|
23
|
-
pass
|
|
24
|
-
|
|
25
|
-
@abstractmethod
|
|
26
|
-
def set_text_color(self, color: Any) -> "TextFieldBase":
|
|
27
|
-
pass
|
|
28
|
-
|
|
29
|
-
@abstractmethod
|
|
30
|
-
def set_text_size(self, size: float) -> "TextFieldBase":
|
|
31
|
-
pass
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if IS_ANDROID:
|
|
35
|
-
# ========================================
|
|
36
|
-
# Android class
|
|
37
|
-
# https://developer.android.com/reference/android/widget/EditText
|
|
38
|
-
# ========================================
|
|
39
|
-
|
|
40
|
-
from java import jclass
|
|
41
|
-
|
|
42
|
-
class TextField(TextFieldBase, ViewBase):
|
|
43
|
-
def __init__(self, text: str = "") -> None:
|
|
44
|
-
super().__init__()
|
|
45
|
-
self.native_class = jclass("android.widget.EditText")
|
|
46
|
-
context = get_android_context()
|
|
47
|
-
self.native_instance = self.native_class(context)
|
|
48
|
-
self.native_instance.setSingleLine(True)
|
|
49
|
-
self.set_text(text)
|
|
50
|
-
|
|
51
|
-
def set_text(self, text: str) -> "TextField":
|
|
52
|
-
self.native_instance.setText(text)
|
|
53
|
-
return self
|
|
54
|
-
|
|
55
|
-
def get_text(self) -> str:
|
|
56
|
-
return self.native_instance.getText().toString()
|
|
57
|
-
|
|
58
|
-
def set_text_color(self, color: Any) -> "TextField":
|
|
59
|
-
if isinstance(color, str):
|
|
60
|
-
c = color.strip()
|
|
61
|
-
if c.startswith("#"):
|
|
62
|
-
c = c[1:]
|
|
63
|
-
if len(c) == 6:
|
|
64
|
-
c = "FF" + c
|
|
65
|
-
color_int = int(c, 16)
|
|
66
|
-
else:
|
|
67
|
-
color_int = int(color)
|
|
68
|
-
try:
|
|
69
|
-
self.native_instance.setTextColor(color_int)
|
|
70
|
-
except Exception:
|
|
71
|
-
pass
|
|
72
|
-
return self
|
|
73
|
-
|
|
74
|
-
def set_text_size(self, size_sp: float) -> "TextField":
|
|
75
|
-
try:
|
|
76
|
-
self.native_instance.setTextSize(float(size_sp))
|
|
77
|
-
except Exception:
|
|
78
|
-
pass
|
|
79
|
-
return self
|
|
80
|
-
|
|
81
|
-
else:
|
|
82
|
-
# ========================================
|
|
83
|
-
# iOS class
|
|
84
|
-
# https://developer.apple.com/documentation/uikit/uitextfield
|
|
85
|
-
# ========================================
|
|
86
|
-
|
|
87
|
-
from rubicon.objc import ObjCClass
|
|
88
|
-
|
|
89
|
-
class TextField(TextFieldBase, ViewBase):
|
|
90
|
-
def __init__(self, text: str = "") -> None:
|
|
91
|
-
super().__init__()
|
|
92
|
-
self.native_class = ObjCClass("UITextField")
|
|
93
|
-
self.native_instance = self.native_class.alloc().init()
|
|
94
|
-
self.set_text(text)
|
|
95
|
-
|
|
96
|
-
def set_text(self, text: str) -> "TextField":
|
|
97
|
-
self.native_instance.setText_(text)
|
|
98
|
-
return self
|
|
99
|
-
|
|
100
|
-
def get_text(self) -> str:
|
|
101
|
-
return self.native_instance.text()
|
|
102
|
-
|
|
103
|
-
def set_text_color(self, color: Any) -> "TextField":
|
|
104
|
-
if isinstance(color, str):
|
|
105
|
-
c = color.strip()
|
|
106
|
-
if c.startswith("#"):
|
|
107
|
-
c = c[1:]
|
|
108
|
-
if len(c) == 6:
|
|
109
|
-
c = "FF" + c
|
|
110
|
-
color_int = int(c, 16)
|
|
111
|
-
else:
|
|
112
|
-
color_int = int(color)
|
|
113
|
-
try:
|
|
114
|
-
UIColor = ObjCClass("UIColor")
|
|
115
|
-
a = ((color_int >> 24) & 0xFF) / 255.0
|
|
116
|
-
r = ((color_int >> 16) & 0xFF) / 255.0
|
|
117
|
-
g = ((color_int >> 8) & 0xFF) / 255.0
|
|
118
|
-
b = (color_int & 0xFF) / 255.0
|
|
119
|
-
color_obj = UIColor.colorWithRed_green_blue_alpha_(r, g, b, a)
|
|
120
|
-
self.native_instance.setTextColor_(color_obj)
|
|
121
|
-
except Exception:
|
|
122
|
-
pass
|
|
123
|
-
return self
|
|
124
|
-
|
|
125
|
-
def set_text_size(self, size: float) -> "TextField":
|
|
126
|
-
try:
|
|
127
|
-
UIFont = ObjCClass("UIFont")
|
|
128
|
-
font = UIFont.systemFontOfSize_(float(size))
|
|
129
|
-
self.native_instance.setFont_(font)
|
|
130
|
-
except Exception:
|
|
131
|
-
pass
|
|
132
|
-
return self
|
pythonnative/text_view.py
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
from abc import ABC, abstractmethod
|
|
2
|
-
from typing import Any
|
|
3
|
-
|
|
4
|
-
from .utils import IS_ANDROID, get_android_context
|
|
5
|
-
from .view import ViewBase
|
|
6
|
-
|
|
7
|
-
# ========================================
|
|
8
|
-
# Base class
|
|
9
|
-
# ========================================
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class TextViewBase(ABC):
|
|
13
|
-
@abstractmethod
|
|
14
|
-
def __init__(self) -> None:
|
|
15
|
-
super().__init__()
|
|
16
|
-
|
|
17
|
-
@abstractmethod
|
|
18
|
-
def set_text(self, text: str) -> "TextViewBase":
|
|
19
|
-
pass
|
|
20
|
-
|
|
21
|
-
@abstractmethod
|
|
22
|
-
def get_text(self) -> str:
|
|
23
|
-
pass
|
|
24
|
-
|
|
25
|
-
@abstractmethod
|
|
26
|
-
def set_text_color(self, color: Any) -> "TextViewBase":
|
|
27
|
-
pass
|
|
28
|
-
|
|
29
|
-
@abstractmethod
|
|
30
|
-
def set_text_size(self, size: float) -> "TextViewBase":
|
|
31
|
-
pass
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if IS_ANDROID:
|
|
35
|
-
# ========================================
|
|
36
|
-
# Android class
|
|
37
|
-
# https://developer.android.com/reference/android/widget/EditText
|
|
38
|
-
# ========================================
|
|
39
|
-
|
|
40
|
-
from java import jclass
|
|
41
|
-
|
|
42
|
-
class TextView(TextViewBase, ViewBase):
|
|
43
|
-
def __init__(self, text: str = "") -> None:
|
|
44
|
-
super().__init__()
|
|
45
|
-
self.native_class = jclass("android.widget.EditText")
|
|
46
|
-
context = get_android_context()
|
|
47
|
-
self.native_instance = self.native_class(context)
|
|
48
|
-
self.native_instance.setLines(3)
|
|
49
|
-
self.native_instance.setMaxLines(5)
|
|
50
|
-
self.native_instance.setVerticalScrollBarEnabled(True)
|
|
51
|
-
# self.native_instance.movementMethod = ScrollingMovementMethod()
|
|
52
|
-
self.set_text(text)
|
|
53
|
-
|
|
54
|
-
def set_text(self, text: str) -> "TextView":
|
|
55
|
-
self.native_instance.setText(text)
|
|
56
|
-
return self
|
|
57
|
-
|
|
58
|
-
def get_text(self) -> str:
|
|
59
|
-
return self.native_instance.getText().toString()
|
|
60
|
-
|
|
61
|
-
def set_text_color(self, color: Any) -> "TextView":
|
|
62
|
-
if isinstance(color, str):
|
|
63
|
-
c = color.strip()
|
|
64
|
-
if c.startswith("#"):
|
|
65
|
-
c = c[1:]
|
|
66
|
-
if len(c) == 6:
|
|
67
|
-
c = "FF" + c
|
|
68
|
-
color_int = int(c, 16)
|
|
69
|
-
else:
|
|
70
|
-
color_int = int(color)
|
|
71
|
-
try:
|
|
72
|
-
self.native_instance.setTextColor(color_int)
|
|
73
|
-
except Exception:
|
|
74
|
-
pass
|
|
75
|
-
return self
|
|
76
|
-
|
|
77
|
-
def set_text_size(self, size_sp: float) -> "TextView":
|
|
78
|
-
try:
|
|
79
|
-
self.native_instance.setTextSize(float(size_sp))
|
|
80
|
-
except Exception:
|
|
81
|
-
pass
|
|
82
|
-
return self
|
|
83
|
-
|
|
84
|
-
else:
|
|
85
|
-
# ========================================
|
|
86
|
-
# iOS class
|
|
87
|
-
# https://developer.apple.com/documentation/uikit/uitextview
|
|
88
|
-
# ========================================
|
|
89
|
-
|
|
90
|
-
from rubicon.objc import ObjCClass
|
|
91
|
-
|
|
92
|
-
class TextView(TextViewBase, ViewBase):
|
|
93
|
-
def __init__(self, text: str = "") -> None:
|
|
94
|
-
super().__init__()
|
|
95
|
-
self.native_class = ObjCClass("UITextView")
|
|
96
|
-
self.native_instance = self.native_class.alloc().init()
|
|
97
|
-
self.set_text(text)
|
|
98
|
-
|
|
99
|
-
def set_text(self, text: str) -> "TextView":
|
|
100
|
-
self.native_instance.setText_(text)
|
|
101
|
-
return self
|
|
102
|
-
|
|
103
|
-
def get_text(self) -> str:
|
|
104
|
-
return self.native_instance.text()
|
|
105
|
-
|
|
106
|
-
def set_text_color(self, color: Any) -> "TextView":
|
|
107
|
-
if isinstance(color, str):
|
|
108
|
-
c = color.strip()
|
|
109
|
-
if c.startswith("#"):
|
|
110
|
-
c = c[1:]
|
|
111
|
-
if len(c) == 6:
|
|
112
|
-
c = "FF" + c
|
|
113
|
-
color_int = int(c, 16)
|
|
114
|
-
else:
|
|
115
|
-
color_int = int(color)
|
|
116
|
-
try:
|
|
117
|
-
UIColor = ObjCClass("UIColor")
|
|
118
|
-
a = ((color_int >> 24) & 0xFF) / 255.0
|
|
119
|
-
r = ((color_int >> 16) & 0xFF) / 255.0
|
|
120
|
-
g = ((color_int >> 8) & 0xFF) / 255.0
|
|
121
|
-
b = (color_int & 0xFF) / 255.0
|
|
122
|
-
color_obj = UIColor.colorWithRed_green_blue_alpha_(r, g, b, a)
|
|
123
|
-
self.native_instance.setTextColor_(color_obj)
|
|
124
|
-
except Exception:
|
|
125
|
-
pass
|
|
126
|
-
return self
|
|
127
|
-
|
|
128
|
-
def set_text_size(self, size: float) -> "TextView":
|
|
129
|
-
try:
|
|
130
|
-
UIFont = ObjCClass("UIFont")
|
|
131
|
-
font = UIFont.systemFontOfSize_(float(size))
|
|
132
|
-
self.native_instance.setFont_(font)
|
|
133
|
-
except Exception:
|
|
134
|
-
pass
|
|
135
|
-
return self
|
pythonnative/time_picker.py
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
from abc import ABC, abstractmethod
|
|
2
|
-
|
|
3
|
-
from .utils import IS_ANDROID
|
|
4
|
-
from .view import ViewBase
|
|
5
|
-
|
|
6
|
-
# ========================================
|
|
7
|
-
# Base class
|
|
8
|
-
# ========================================
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class TimePickerBase(ABC):
|
|
12
|
-
@abstractmethod
|
|
13
|
-
def __init__(self) -> None:
|
|
14
|
-
super().__init__()
|
|
15
|
-
|
|
16
|
-
@abstractmethod
|
|
17
|
-
def set_time(self, hour: int, minute: int) -> "TimePickerBase":
|
|
18
|
-
pass
|
|
19
|
-
|
|
20
|
-
@abstractmethod
|
|
21
|
-
def get_time(self) -> tuple:
|
|
22
|
-
pass
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if IS_ANDROID:
|
|
26
|
-
# ========================================
|
|
27
|
-
# Android class
|
|
28
|
-
# https://developer.android.com/reference/android/widget/TimePicker
|
|
29
|
-
# ========================================
|
|
30
|
-
|
|
31
|
-
from typing import Any
|
|
32
|
-
|
|
33
|
-
from java import jclass
|
|
34
|
-
|
|
35
|
-
class TimePicker(TimePickerBase, ViewBase):
|
|
36
|
-
def __init__(self, context: Any, hour: int = 0, minute: int = 0) -> None:
|
|
37
|
-
super().__init__()
|
|
38
|
-
self.native_class = jclass("android.widget.TimePicker")
|
|
39
|
-
self.native_instance = self.native_class(context)
|
|
40
|
-
self.set_time(hour, minute)
|
|
41
|
-
|
|
42
|
-
def set_time(self, hour: int, minute: int) -> "TimePicker":
|
|
43
|
-
self.native_instance.setHour(hour)
|
|
44
|
-
self.native_instance.setMinute(minute)
|
|
45
|
-
return self
|
|
46
|
-
|
|
47
|
-
def get_time(self) -> tuple:
|
|
48
|
-
hour = self.native_instance.getHour()
|
|
49
|
-
minute = self.native_instance.getMinute()
|
|
50
|
-
return hour, minute
|
|
51
|
-
|
|
52
|
-
else:
|
|
53
|
-
# ========================================
|
|
54
|
-
# iOS class
|
|
55
|
-
# https://developer.apple.com/documentation/uikit/uidatepicker
|
|
56
|
-
# ========================================
|
|
57
|
-
|
|
58
|
-
from datetime import time
|
|
59
|
-
|
|
60
|
-
from rubicon.objc import ObjCClass
|
|
61
|
-
|
|
62
|
-
class TimePicker(TimePickerBase, ViewBase):
|
|
63
|
-
def __init__(self, hour: int = 0, minute: int = 0) -> None:
|
|
64
|
-
super().__init__()
|
|
65
|
-
self.native_class = ObjCClass("UIDatePicker")
|
|
66
|
-
self.native_instance = self.native_class.alloc().init()
|
|
67
|
-
self.native_instance.setDatePickerMode_(1) # Setting mode to Time
|
|
68
|
-
self.set_time(hour, minute)
|
|
69
|
-
|
|
70
|
-
def set_time(self, hour: int, minute: int) -> "TimePicker":
|
|
71
|
-
t = time(hour, minute)
|
|
72
|
-
self.native_instance.setTime_(t)
|
|
73
|
-
return self
|
|
74
|
-
|
|
75
|
-
def get_time(self) -> tuple:
|
|
76
|
-
t = self.native_instance.time()
|
|
77
|
-
return t.hour, t.minute
|
pythonnative/view.py
DELETED
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
from abc import ABC
|
|
2
|
-
from typing import Any, Optional, Tuple
|
|
3
|
-
|
|
4
|
-
# ========================================
|
|
5
|
-
# Base class
|
|
6
|
-
# ========================================
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class ViewBase(ABC):
|
|
10
|
-
def __init__(self) -> None:
|
|
11
|
-
# Native bridge handles return types dynamically; these attributes are set at runtime.
|
|
12
|
-
self.native_instance: Any = None
|
|
13
|
-
self.native_class: Any = None
|
|
14
|
-
# Record margins for parents that can apply them (Android LinearLayout)
|
|
15
|
-
self._pn_margin: Optional[Tuple[int, int, int, int]] = None
|
|
16
|
-
|
|
17
|
-
# ========================================
|
|
18
|
-
# Lightweight style helpers
|
|
19
|
-
# ========================================
|
|
20
|
-
|
|
21
|
-
def set_background_color(self, color: Any) -> "ViewBase":
|
|
22
|
-
"""Set background color. Accepts platform color int or CSS-like hex string. Returns self."""
|
|
23
|
-
try:
|
|
24
|
-
from .utils import IS_ANDROID
|
|
25
|
-
|
|
26
|
-
if isinstance(color, str):
|
|
27
|
-
# Support formats: #RRGGBB or #AARRGGBB
|
|
28
|
-
c = color.strip()
|
|
29
|
-
if c.startswith("#"):
|
|
30
|
-
c = c[1:]
|
|
31
|
-
if len(c) == 6:
|
|
32
|
-
c = "FF" + c
|
|
33
|
-
color_int = int(c, 16)
|
|
34
|
-
else:
|
|
35
|
-
color_int = int(color)
|
|
36
|
-
|
|
37
|
-
if IS_ANDROID:
|
|
38
|
-
# Android expects ARGB int
|
|
39
|
-
self.native_instance.setBackgroundColor(color_int)
|
|
40
|
-
else:
|
|
41
|
-
# iOS expects a UIColor
|
|
42
|
-
from rubicon.objc import ObjCClass
|
|
43
|
-
|
|
44
|
-
UIColor = ObjCClass("UIColor")
|
|
45
|
-
a = ((color_int >> 24) & 0xFF) / 255.0
|
|
46
|
-
r = ((color_int >> 16) & 0xFF) / 255.0
|
|
47
|
-
g = ((color_int >> 8) & 0xFF) / 255.0
|
|
48
|
-
b = (color_int & 0xFF) / 255.0
|
|
49
|
-
try:
|
|
50
|
-
color_obj = UIColor.colorWithRed_green_blue_alpha_(r, g, b, a)
|
|
51
|
-
except Exception:
|
|
52
|
-
color_obj = UIColor.blackColor()
|
|
53
|
-
try:
|
|
54
|
-
self.native_instance.setBackgroundColor_(color_obj)
|
|
55
|
-
except Exception:
|
|
56
|
-
try:
|
|
57
|
-
# Some UIKit classes expose 'backgroundColor' property
|
|
58
|
-
self.native_instance.setBackgroundColor_(color_obj)
|
|
59
|
-
except Exception:
|
|
60
|
-
pass
|
|
61
|
-
except Exception:
|
|
62
|
-
pass
|
|
63
|
-
return self
|
|
64
|
-
|
|
65
|
-
def set_padding(
|
|
66
|
-
self,
|
|
67
|
-
left: Optional[int] = None,
|
|
68
|
-
top: Optional[int] = None,
|
|
69
|
-
right: Optional[int] = None,
|
|
70
|
-
bottom: Optional[int] = None,
|
|
71
|
-
all: Optional[int] = None,
|
|
72
|
-
horizontal: Optional[int] = None,
|
|
73
|
-
vertical: Optional[int] = None,
|
|
74
|
-
) -> "ViewBase":
|
|
75
|
-
"""Set padding (dp on Android; best-effort on iOS where supported). Returns self.
|
|
76
|
-
|
|
77
|
-
When provided, 'all' applies to all sides; 'horizontal' applies to left and right;
|
|
78
|
-
'vertical' applies to top and bottom; individual overrides take precedence.
|
|
79
|
-
"""
|
|
80
|
-
try:
|
|
81
|
-
from .utils import IS_ANDROID, get_android_context
|
|
82
|
-
|
|
83
|
-
left_value = left
|
|
84
|
-
top_value = top
|
|
85
|
-
right_value = right
|
|
86
|
-
bottom_value = bottom
|
|
87
|
-
if all is not None:
|
|
88
|
-
left_value = top_value = right_value = bottom_value = all
|
|
89
|
-
if horizontal is not None:
|
|
90
|
-
left_value = horizontal if left_value is None else left_value
|
|
91
|
-
right_value = horizontal if right_value is None else right_value
|
|
92
|
-
if vertical is not None:
|
|
93
|
-
top_value = vertical if top_value is None else top_value
|
|
94
|
-
bottom_value = vertical if bottom_value is None else bottom_value
|
|
95
|
-
left_value = left_value or 0
|
|
96
|
-
top_value = top_value or 0
|
|
97
|
-
right_value = right_value or 0
|
|
98
|
-
bottom_value = bottom_value or 0
|
|
99
|
-
|
|
100
|
-
if IS_ANDROID:
|
|
101
|
-
density = get_android_context().getResources().getDisplayMetrics().density
|
|
102
|
-
lpx = int(left_value * density)
|
|
103
|
-
tpx = int(top_value * density)
|
|
104
|
-
rpx = int(right_value * density)
|
|
105
|
-
bpx = int(bottom_value * density)
|
|
106
|
-
self.native_instance.setPadding(lpx, tpx, rpx, bpx)
|
|
107
|
-
else:
|
|
108
|
-
# Best-effort: many UIKit views don't have direct padding; leave to containers (e.g. UIStackView)
|
|
109
|
-
# No-op by default.
|
|
110
|
-
pass
|
|
111
|
-
except Exception:
|
|
112
|
-
pass
|
|
113
|
-
return self
|
|
114
|
-
|
|
115
|
-
def set_margin(
|
|
116
|
-
self,
|
|
117
|
-
left: Optional[int] = None,
|
|
118
|
-
top: Optional[int] = None,
|
|
119
|
-
right: Optional[int] = None,
|
|
120
|
-
bottom: Optional[int] = None,
|
|
121
|
-
all: Optional[int] = None,
|
|
122
|
-
horizontal: Optional[int] = None,
|
|
123
|
-
vertical: Optional[int] = None,
|
|
124
|
-
) -> "ViewBase":
|
|
125
|
-
"""Record margins for this view (applied where supported). Returns self.
|
|
126
|
-
|
|
127
|
-
Currently applied automatically when added to Android LinearLayout (StackView).
|
|
128
|
-
"""
|
|
129
|
-
try:
|
|
130
|
-
left_value = left
|
|
131
|
-
top_value = top
|
|
132
|
-
right_value = right
|
|
133
|
-
bottom_value = bottom
|
|
134
|
-
if all is not None:
|
|
135
|
-
left_value = top_value = right_value = bottom_value = all
|
|
136
|
-
if horizontal is not None:
|
|
137
|
-
left_value = horizontal if left_value is None else left_value
|
|
138
|
-
right_value = horizontal if right_value is None else right_value
|
|
139
|
-
if vertical is not None:
|
|
140
|
-
top_value = vertical if top_value is None else top_value
|
|
141
|
-
bottom_value = vertical if bottom_value is None else bottom_value
|
|
142
|
-
left_value = int(left_value or 0)
|
|
143
|
-
top_value = int(top_value or 0)
|
|
144
|
-
right_value = int(right_value or 0)
|
|
145
|
-
bottom_value = int(bottom_value or 0)
|
|
146
|
-
self._pn_margin = (left_value, top_value, right_value, bottom_value)
|
|
147
|
-
except Exception:
|
|
148
|
-
pass
|
|
149
|
-
return self
|
|
150
|
-
|
|
151
|
-
def wrap_in_scroll(self) -> Any:
|
|
152
|
-
"""Return a ScrollView containing this view as its only child. Returns the ScrollView."""
|
|
153
|
-
try:
|
|
154
|
-
# Local import to avoid circulars
|
|
155
|
-
from .scroll_view import ScrollView
|
|
156
|
-
|
|
157
|
-
sv = ScrollView()
|
|
158
|
-
sv.add_view(self)
|
|
159
|
-
return sv
|
|
160
|
-
except Exception:
|
|
161
|
-
return None
|
|
162
|
-
|
|
163
|
-
# @abstractmethod
|
|
164
|
-
# def add_view(self, view):
|
|
165
|
-
# pass
|
|
166
|
-
#
|
|
167
|
-
# @abstractmethod
|
|
168
|
-
# def set_layout(self, layout):
|
|
169
|
-
# pass
|
|
170
|
-
#
|
|
171
|
-
# @abstractmethod
|
|
172
|
-
# def show(self):
|
|
173
|
-
# pass
|
pythonnative/web_view.py
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
from abc import ABC, abstractmethod
|
|
2
|
-
|
|
3
|
-
from .utils import IS_ANDROID, get_android_context
|
|
4
|
-
from .view import ViewBase
|
|
5
|
-
|
|
6
|
-
# ========================================
|
|
7
|
-
# Base class
|
|
8
|
-
# ========================================
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class WebViewBase(ABC):
|
|
12
|
-
@abstractmethod
|
|
13
|
-
def __init__(self) -> None:
|
|
14
|
-
super().__init__()
|
|
15
|
-
|
|
16
|
-
@abstractmethod
|
|
17
|
-
def load_url(self, url: str) -> "WebViewBase":
|
|
18
|
-
pass
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if IS_ANDROID:
|
|
22
|
-
# ========================================
|
|
23
|
-
# Android class
|
|
24
|
-
# https://developer.android.com/reference/android/webkit/WebView
|
|
25
|
-
# ========================================
|
|
26
|
-
|
|
27
|
-
from java import jclass
|
|
28
|
-
|
|
29
|
-
class WebView(WebViewBase, ViewBase):
|
|
30
|
-
def __init__(self, url: str = "") -> None:
|
|
31
|
-
super().__init__()
|
|
32
|
-
self.native_class = jclass("android.webkit.WebView")
|
|
33
|
-
context = get_android_context()
|
|
34
|
-
self.native_instance = self.native_class(context)
|
|
35
|
-
self.load_url(url)
|
|
36
|
-
|
|
37
|
-
def load_url(self, url: str) -> "WebView":
|
|
38
|
-
self.native_instance.loadUrl(url)
|
|
39
|
-
return self
|
|
40
|
-
|
|
41
|
-
else:
|
|
42
|
-
# ========================================
|
|
43
|
-
# iOS class
|
|
44
|
-
# https://developer.apple.com/documentation/webkit/wkwebview
|
|
45
|
-
# ========================================
|
|
46
|
-
|
|
47
|
-
from rubicon.objc import NSURL, NSURLRequest, ObjCClass
|
|
48
|
-
|
|
49
|
-
class WebView(WebViewBase, ViewBase):
|
|
50
|
-
def __init__(self, url: str = "") -> None:
|
|
51
|
-
super().__init__()
|
|
52
|
-
self.native_class = ObjCClass("WKWebView")
|
|
53
|
-
self.native_instance = self.native_class.alloc().init()
|
|
54
|
-
self.load_url(url)
|
|
55
|
-
|
|
56
|
-
def load_url(self, url: str) -> "WebView":
|
|
57
|
-
ns_url = NSURL.URLWithString_(url)
|
|
58
|
-
request = NSURLRequest.requestWithURL_(ns_url)
|
|
59
|
-
self.native_instance.loadRequest_(request)
|
|
60
|
-
return self
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|