lib/crapto: Introduce 2 new attacks on XOR ciphers
[nit.git] / lib / android / ui / ui.nit
1 # This file is part of NIT (http://www.nitlanguage.org).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Views and services to use the Android native user interface
16 module ui
17
18 # Implementation note:
19 #
20 # We cannot rely on `Activity::on_restore_instance_state` to implement
21 # `on_restore_state` is it only invoked if there is a bundled state,
22 # and we don't use the Android bundled state.
23
24 import native_ui
25 import log
26 import nit_activity
27
28 import app::ui
29 private import data_store
30 import assets
31
32 redef class Control
33 # The Android element used to implement `self`
34 fun native: NATIVE is abstract
35
36 # Type of `native`
37 type NATIVE: JavaObject
38 end
39
40 redef class NativeActivity
41
42 private fun remove_title_bar in "Java" `{
43 self.requestWindowFeature(android.view.Window.FEATURE_NO_TITLE);
44 `}
45
46 # Insert a single layout as the root of the activity window
47 private fun insert_root_layout(root_layout_id: Int)
48 in "Java" `{
49 android.widget.FrameLayout layout = new android.widget.FrameLayout(self);
50 layout.setId((int)root_layout_id);
51 self.setContentView(layout);
52 `}
53
54 # Replace the currently visible fragment, if any, with `native_fragment`
55 private fun show_fragment(root_layout_id: Int, native_fragment: Android_app_Fragment)
56 in "Java" `{
57 android.app.FragmentTransaction transaction = self.getFragmentManager().beginTransaction();
58 transaction.replace((int)root_layout_id, native_fragment);
59 transaction.commit();
60 `}
61 end
62
63 redef class App
64 redef fun on_create
65 do
66 app.native_activity.remove_title_bar
67 native_activity.insert_root_layout(root_layout_id)
68 super
69 end
70
71 # Identifier of the container holding the fragments
72 private var root_layout_id = 0xFFFF
73
74 redef fun window=(window)
75 do
76 native_activity.show_fragment(root_layout_id, window.native)
77 super
78 end
79 end
80
81 # On Android, a window is implemented with the fragment `native`
82 redef class Window
83 redef var native = (new Android_app_Fragment(self)).new_global_ref
84
85 redef type NATIVE: Android_app_Fragment
86
87 # Root high-level view of this window
88 var view: nullable View = null
89
90 redef fun add(item)
91 do
92 if item isa View then view = item
93 super
94 end
95
96 private fun on_create_fragment: NativeView
97 do
98 on_create
99
100 var view = view
101 assert view != null else print_error "{class_name} needs a `view` after `Window::on_create` returns"
102 return view.native
103 end
104 end
105
106 redef class View
107 redef type NATIVE: NativeView
108
109 redef fun enabled=(enabled) do native.enabled = enabled or else true
110 redef fun enabled do return native.enabled
111 end
112
113 redef class Layout
114 redef type NATIVE: NativeViewGroup
115
116 redef fun add(item)
117 do
118 super
119
120 assert item isa View
121
122 # FIXME abstract the use either homogeneous or weight to balance views size in a layout
123 native.add_view_with_weight(item.native, 1.0)
124 end
125
126 redef fun remove(item)
127 do
128 super
129 if item isa View then native.remove_view item.native
130 end
131 end
132
133 redef class HorizontalLayout
134 redef var native do
135 var layout = new NativeLinearLayout(app.native_activity)
136 layout = layout.new_global_ref
137 layout.set_horizontal
138 return layout
139 end
140 end
141
142 redef class VerticalLayout
143 redef var native do
144 var layout = new NativeLinearLayout(app.native_activity)
145 layout = layout.new_global_ref
146 layout.set_vertical
147 return layout
148 end
149 end
150
151 redef class ListLayout
152 redef type NATIVE: Android_widget_ListView
153
154 redef var native do
155 var layout = new Android_widget_ListView(app.native_activity)
156 layout = layout.new_global_ref
157 return layout
158 end
159
160 private var adapter: Android_widget_ArrayAdapter do
161 var adapter = new Android_widget_ArrayAdapter(app.native_activity,
162 android_r_layout_simple_list_item_1, self)
163 native.set_adapter adapter
164 return adapter.new_global_ref
165 end
166
167 redef fun add(item)
168 do
169 super
170 if item isa View then adapter.add item.native
171 end
172
173 private fun create_view(position: Int): NativeView
174 do
175 var ctrl = items[position]
176 assert ctrl isa View
177 return ctrl.native
178 end
179 end
180
181 redef class Android_widget_ArrayAdapter
182 private new (context: NativeContext, res: Int, sender: ListLayout)
183 import ListLayout.create_view in "Java" `{
184 final int final_sender_object = sender;
185
186 return new android.widget.ArrayAdapter(context, (int)res) {
187 @Override
188 public android.view.View getView(int position, android.view.View convertView, android.view.ViewGroup parent) {
189 return ListLayout_create_view(final_sender_object, position);
190 }
191 };
192 `}
193 end
194
195 redef class TextView
196 redef type NATIVE: NativeTextView
197
198 redef fun text do return native.text.to_s
199 redef fun text=(value) do
200 if value == null then value = ""
201 native.text = value.to_java_string
202 end
203
204 redef fun size=(size) do set_size_native(app.native_activity, native, size or else 1.0)
205
206 private fun set_size_native(context: NativeContext, view: NativeTextView, size: Float)
207 in "Java" `{
208 int s;
209 if (size == 1.0d)
210 s = android.R.style.TextAppearance_Medium;
211 else if (size < 1.0d)
212 s = android.R.style.TextAppearance_Small;
213 else // if (size > 1.0d)
214 s = android.R.style.TextAppearance_Large;
215
216 view.setTextAppearance(context, s);
217 `}
218
219 redef fun align=(align) do set_align_native(native, align or else 0.0)
220
221 private fun set_align_native(view: NativeTextView, align: Float)
222 in "Java" `{
223 int g;
224 if (align == 0.5d)
225 g = android.view.Gravity.CENTER_HORIZONTAL;
226 else if (align < 0.5d)
227 g = android.view.Gravity.LEFT;
228 else // if (align > 0.5d)
229 g = android.view.Gravity.RIGHT;
230
231 view.setGravity(g);
232 `}
233 end
234
235 redef class Label
236 redef type NATIVE: NativeTextView
237 redef var native do return (new NativeTextView(app.native_activity)).new_global_ref
238 end
239
240 redef class CheckBox
241 redef type NATIVE: Android_widget_CompoundButton
242 redef var native do return (new Android_widget_CheckBox(app.native_activity)).new_global_ref
243
244 redef fun is_checked do return native.is_checked
245 redef fun is_checked=(value) do native.set_checked(value)
246 end
247
248 redef class TextInput
249 redef type NATIVE: NativeEditText
250 redef var native = (new NativeEditText(app.native_activity)).new_global_ref
251
252 redef fun is_password=(value)
253 do
254 native.is_password = value or else false
255 super
256 end
257 end
258
259 redef class NativeEditText
260
261 # Configure this view to hide passwords
262 fun is_password=(value: Bool) in "Java" `{
263 if (value) {
264 self.setInputType(android.text.InputType.TYPE_CLASS_TEXT | android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD);
265 self.setTransformationMethod(android.text.method.PasswordTransformationMethod.getInstance());
266 } else {
267 self.setInputType(android.text.InputType.TYPE_CLASS_TEXT);
268 self.setTransformationMethod(null);
269 }
270 `}
271 end
272
273 redef class Button
274 super Finalizable
275
276 redef type NATIVE: NativeButton
277 redef var native = (new NativeButton(app.native_activity, self)).new_global_ref
278
279 private fun on_click do notify_observers new ButtonPressEvent(self)
280
281 redef fun finalize do native.delete_global_ref
282 end
283
284 redef class NativeButton
285 private new (context: NativeActivity, sender_object: Button)
286 import Button.on_click in "Java" `{
287 final int final_sender_object = sender_object;
288 Button_incr_ref(final_sender_object);
289
290 return new android.widget.Button(context){
291 @Override
292 public boolean onTouchEvent(android.view.MotionEvent event) {
293 if(event.getAction() == android.view.MotionEvent.ACTION_DOWN) {
294 Button_on_click(final_sender_object);
295 return true;
296 }
297 return false;
298 }
299 };
300 `}
301 end
302
303 redef class Android_app_Fragment
304 private new (nit_window: Window)
305 import Window.on_create_fragment in "Java" `{
306 final int final_nit_window = nit_window;
307
308 return new android.app.Fragment(){
309 @Override
310 public android.view.View onCreateView(android.view.LayoutInflater inflater,
311 android.view.ViewGroup container, android.os.Bundle state) {
312
313 return Window_on_create_fragment(final_nit_window);
314 }
315 };
316 `}
317 end