From: Jean Privat Date: Wed, 26 Nov 2014 23:05:15 +0000 (-0500) Subject: Merge: jwrapper: no whitespace before new line X-Git-Tag: v0.6.11~11 X-Git-Url: http://nitlanguage.org?hp=2f5616b4a9cda796c6bbc0aa826affe7a5c20cbf Merge: jwrapper: no whitespace before new line Pull-Request: #938 Reviewed-by: Jean Privat --- diff --git a/examples/calculator/Makefile b/examples/calculator/Makefile index 9782660..acb600b 100644 --- a/examples/calculator/Makefile +++ b/examples/calculator/Makefile @@ -1,3 +1,8 @@ all: mkdir -p bin/ - ../../bin/nitg --dir bin/ src/calculator_test.nit src/calculator_gtk.nit + ../../bin/nitg --dir bin/ src/calculator_gtk.nit src/calculator_test.nit + +android: + mkdir -p bin/ res/ + ../../contrib/inkscape_tools/bin/svg_to_icons art/icon.svg --android --out res/ + ../../bin/nitg -o bin/calculator.apk src/calculator_android.nit diff --git a/examples/calculator/art/icon.svg b/examples/calculator/art/icon.svg new file mode 100644 index 0000000..ccd533c --- /dev/null +++ b/examples/calculator/art/icon.svg @@ -0,0 +1,139 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + = + + diff --git a/examples/calculator/src/calculator_android.nit b/examples/calculator/src/calculator_android.nit new file mode 100644 index 0000000..e66fea8 --- /dev/null +++ b/examples/calculator/src/calculator_android.nit @@ -0,0 +1,108 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Copyright 2014 Alexis Laferrière +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Android calculator application +module calculator_android is + app_name "app.nit Calc." + app_version(0, 1, git_revision) + java_package "org.nitlanguage.calculator" + + # Use a translucent background and lock in portrait mode + android_manifest_activity """ + android:theme="@android:style/Theme.Holo.Wallpaper" + android:screenOrientation="portrait"""" +end + +import android +import android::ui + +import calculator_logic + +redef class App + private var context = new CalculatorContext + + # The main display, at the top of the screen + private var display: EditText + + # Maps operators as `String` to their `Button` + private var op2but = new HashMap[String, Button] + + # Has this window been initialized? + private var inited = false + + redef fun init_window + do + super + + if inited then return + inited = true + + # Setup UI + var context = native_activity + var layout = new NativeLinearLayout(context) + layout.set_vertical + + # Display screen + var display = new EditText + layout.add_view_with_weight(display.native, 1.0) + display.text_size = 36.0 + self.display = display + + # Buttons; numbers and operators + var ops = [["7", "8", "9", "+"], + ["4", "5", "6", "-"], + ["1", "2", "3", "*"], + ["0", ".", "C", "/"], + ["="]] + + for line in ops do + var buts_layout = new NativeLinearLayout(context) + buts_layout.set_horizontal + layout.add_view_with_weight(buts_layout, 1.0) + + for op in line do + var but = new Button + but.text = op + but.text_size = 40 + buts_layout.add_view_with_weight(but.native, 1.0) + op2but[op] = but + end + end + + context.content_view = layout + end + + redef fun catch_event(event) + do + if event isa ClickEvent then + var sender = event.sender + var op = sender.text + + if op == "." then + sender.enabled = false + context.switch_to_decimals + else if op.is_numeric then + var n = op.to_i + context.push_digit n + else + op2but["."].enabled = true + context.push_op op.chars.first + end + + display.text = context.display_text + end + end +end diff --git a/lib/android/examples/Makefile b/lib/android/examples/Makefile new file mode 100644 index 0000000..5255657 --- /dev/null +++ b/lib/android/examples/Makefile @@ -0,0 +1,11 @@ +android: + mkdir -p bin/ res/ + ../../../contrib/inkscape_tools/bin/svg_to_icons art/icon.svg --android --out res/ + ../../../bin/nitg --dir bin/ src/ui_test.nit + adb install -r bin/ui_test.apk + +install: android + adb install -r bin/ui.apk + +clean: + rm -rf bin diff --git a/lib/android/examples/art/icon.svg b/lib/android/examples/art/icon.svg new file mode 100644 index 0000000..fb46e63 --- /dev/null +++ b/lib/android/examples/art/icon.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + App + nit + UI + + diff --git a/lib/android/examples/src/ui_test.nit b/lib/android/examples/src/ui_test.nit new file mode 100644 index 0000000..f6c2a1b --- /dev/null +++ b/lib/android/examples/src/ui_test.nit @@ -0,0 +1,91 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Copyright 2014 Alexis Laferrière +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Test for app.nit's UI services +module ui_test is + app_name("app.nit UI test") + app_version(0, 1, git_revision) + java_package("org.nitlanguage.ui_test") + android_manifest_activity """android:theme="@android:style/Theme.Light"""" +end + +import android +import android::ui +import android::toast +import android::notification + +redef class App + + var but_notif: Button + var but_toast: Button + + var notif: nullable Notification = null + + var inited = false + redef fun init_window + do + super + + if inited then return + inited = true + + # Setup UI + var context = native_activity + var layout = new NativeLinearLayout(context) + layout.set_vertical + + but_notif = new Button + but_notif.text = "Show Notification" + layout.add_view but_notif.native + + but_toast = new Button + but_toast.text = "Show Toast" + layout.add_view but_toast.native + + context.content_view = layout + end + + fun act_notif + do + var notif = self.notif + if notif == null then + notif = new Notification("From app.nit", "Some content...") + notif.ticker = "Ticker text..." + notif.show + self.notif = notif + else + notif.cancel + self.notif = null + end + end + + fun act_toast + do + toast("Sample toast from app.nit at {get_time}", false) + end + + redef fun catch_event(event) + do + if event isa ClickEvent then + var sender = event.sender + if sender == but_notif then + act_notif + else if sender == but_toast then + act_toast + end + end + end +end diff --git a/lib/android/native_app_glue.nit b/lib/android/native_app_glue.nit index 50368de..fc5a19f 100644 --- a/lib/android/native_app_glue.nit +++ b/lib/android/native_app_glue.nit @@ -114,12 +114,22 @@ in "C body" `{ } `} +# An Android activity context +extern class NativeContext in "Java" `{ android.content.Context `} + super JavaObject +end + +# A wrapper of context +extern class NativeContextWrapper in "Java" `{ android.content.ContextWrapper `} + super NativeContext +end + # Android SDK's `android.app.NativeActivity`. # # Can be used to get anything related to the `Context` of the activity in Java # and as anchor to execute Java UI code. extern class NativeActivity in "Java" `{ android.app.NativeActivity `} - super JavaObject + super NativeContextWrapper end redef class App @@ -252,11 +262,11 @@ extern class NdkNativeActivity `{ ANativeActivity * `} # The `NativeActivity`, as in the Java object, associated to `self` fun java_native_activity: NativeActivity `{ return recv->clazz; `} - # Path to this application's internal data directory. + # Path to this application's internal data directory. fun internal_data_path: NativeString `{ return (char*)recv->internalDataPath; `} # Path to this application's external (removable/mountable) data directory. - fun external_data_path: NativeString `{ return (char*)recv->externalDataPath; `} + fun external_data_path: NativeString `{ return (char*)recv->externalDataPath; `} # The platform's SDK version code. fun sdk_version: Int `{ return recv->sdkVersion; `} diff --git a/lib/android/notification/native_notification.nit b/lib/android/notification/native_notification.nit new file mode 100644 index 0000000..988727f --- /dev/null +++ b/lib/android/notification/native_notification.nit @@ -0,0 +1,71 @@ +# This file is part of NIT (http://www.nitlanguage.org). +# +# Copyright 2014 Alexis Laferrière +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Native Java classes for notifications +module native_notification is min_api_version 11 + +import android::assets_and_resources + +in "Java" `{ + import android.content.Context; + import android.app.NotificationManager; + import android.app.Notification; +`} + +redef class NativeActivity + fun notification_manager: NativeNotificationManager in "Java" `{ + return (NotificationManager)recv.getSystemService(Context.NOTIFICATION_SERVICE); + `} +end + +extern class NativeNotificationManager in "Java" `{ android.app.NotificationManager `} + + fun notify(tag: JavaString, id: Int, notif: NativeNotification) in "Java" `{ + recv.notify(tag, (int)id, notif); + `} + + fun cancel(tag: JavaString, id: Int) in "Java" `{ recv.cancel(tag, (int)id); `} + + fun cancel_all in "Java" `{ recv.cancelAll(); `} +end + +extern class NativeNotification in "Java" `{ android.app.Notification `} +end + +extern class NativeNotificationBuilder in "Java" `{ android.app.Notification$Builder `} + + new (context: NativeActivity) in "Java" `{ return new Notification.Builder(context); `} + + fun create: NativeNotification in "Java" `{ + // Deprecated since API 16, which introduces `build`, + // refinement and global compilation should prevent warnings. + return recv.getNotification(); + `} + + fun title=(value: JavaString) in "Java" `{ recv.setContentTitle(value); `} + + fun text=(value: JavaString) in "Java" `{ recv.setContentText(value); `} + + fun ticker=(value: JavaString) in "Java" `{ recv.setTicker(value); `} + + fun small_icon=(value: Int) in "Java" `{ recv.setSmallIcon((int)value); `} + + fun auto_cancel=(value: Bool) in "Java" `{ recv.setAutoCancel(value); `} + + fun number=(value: Int) in "Java" `{ recv.setNumber((int)value); `} + + fun ongoing=(value: Bool) in "Java" `{ recv.setOngoing(value); `} +end diff --git a/lib/android/notification/notification.nit b/lib/android/notification/notification.nit new file mode 100644 index 0000000..07d1c00 --- /dev/null +++ b/lib/android/notification/notification.nit @@ -0,0 +1,132 @@ +# This file is part of NIT (http://www.nitlanguage.org). +# +# Copyright 2014 Alexis Laferrière +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Services to show notification in the Android status bar +# +# ~~~~ +# # Create and show a notification +# var notif = new Notification("My Title", "Some content") +# notif.ticker = "Ticker text" +# notif.show +# +# # Update the notification +# notif.text = "New content!" +# notif.ongoing = true # Make it un-dismissable +# nofif.show +# +# # Hide the notification +# notif.cancel +# ~~~~ +# +# For more information, see: +# http://developer.android.com/guide/topics/ui/notifiers/notifications.html +module notification + +import standard +private import native_notification + +# An Android notification, shown at the top of the screen +class Notification + # Title of this notification + var title: nullable Text is writable + + # Text content of this notification + var text: nullable Text is writable + + # Text to show in the bar as the notification appears + var ticker: nullable Text = null is writable + + # Name of a resource found in the `res/drawable-*` folders to use for the small icon + # + # By default, we use the app's icon, named "icon". A valid icon must be used + # to display notifications. + var small_icon: nullable Text = null is writable + + # Number to display on the bottom right part of the notification + var number: nullable Int = null is writable + + # Is this notification ongoing? Not user dismissable. + var ongoing: Bool = false is writable + + private var id: nullable Int = null + private var tag = "app.nit notification" + + # Show the notification + fun show + do + sys.jni_env.push_local_frame(8) + + var context = app.native_activity + var builder = new NativeNotificationBuilder(context) + + # If no custom icon is specified, use app's + var small_icon = self.small_icon + if small_icon == null then small_icon = "icon" + var small_icon_id = app.resource_manager.other_id(small_icon.to_s, "drawable") + builder.small_icon = small_icon_id + + # Other options + if title != null then builder.title = title.to_java_string + if text != null then builder.text = text.to_java_string + if ticker != null then builder.ticker = ticker.to_java_string + builder.ongoing = ongoing + + var notif = builder.create + var manager = context.notification_manager + + var id = self.id + if id == null then id = sys.next_notification_id + manager.notify(tag.to_java_string, id, notif) + + self.id = id + + sys.jni_env.pop_local_frame + end + + # Was this notification shown with `show`? + # + # This does not indicates whether is has been dismissed or not. Only that + # it was shown at least once. + private fun was_shown: Bool do return id != null + + # Cancel this notification and hide it if it is currently displayed + fun cancel + do + var id = self.id + if id != null then + sys.jni_env.push_local_frame(8) + + var manager = app.native_activity.notification_manager + manager.cancel(tag.to_java_string, id) + + self.id = null + + sys.jni_env.pop_local_frame + end + end +end + +redef class Sys + private var next_notification_id_cache = 0 + + # Returns a unique ID for new notifications + private fun next_notification_id: Int + do + var id = next_notification_id_cache + next_notification_id_cache = id + 1 + return id + end +end diff --git a/lib/android/toast.nit b/lib/android/toast.nit new file mode 100644 index 0000000..dd8e149 --- /dev/null +++ b/lib/android/toast.nit @@ -0,0 +1,49 @@ +# This file is part of NIT (http://www.nitlanguage.org). +# +# Copyright 2014 Alexis Laferrière +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Services to display a _toast_, a small popup on Android +module toast + +import native_app_glue + +in "Java" `{ + import android.widget.Toast; +`} + +redef class App + # Display a _toast_ with `message`, for longer if `is_long` + fun toast(message: String, is_long: Bool) + do + var jstr = message.to_java_string + native_toast(jstr, is_long) + jstr.delete_local_ref + end + + private fun native_toast(message: JavaString, is_long: Bool) + import native_activity in "Java" `{ + final android.app.NativeActivity context = App_native_activity(recv); + final CharSequence final_message = message; + final int duration = is_long? Toast.LENGTH_LONG: Toast.LENGTH_SHORT; + + context.runOnUiThread(new Runnable() { + @Override + public void run() { + Toast toast = Toast.makeText(context, final_message, duration); + toast.show(); + } + }); + `} +end diff --git a/lib/android/ui.nit b/lib/android/ui.nit new file mode 100644 index 0000000..b4ed822 --- /dev/null +++ b/lib/android/ui.nit @@ -0,0 +1,417 @@ +# This file is part of NIT (http://www.nitlanguage.org). +# +# Copyright 2014 Alexis Laferrière +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Views and services to use the Android native user interface +# +# Events, such as a button click, come from the UI thread and are then +# passed to the main thread. It is recommended to specialize one of the +# methods of the main thread to customize the response to a given event. +# +# This graph shows the path of a button click: +# ~~~ +# UI Thread # Main thread +# +# User +# | +# V +# Button::click_ui --> Button::click +# | +# V +# App::catch_event +# ~~~ +module ui is min_api_version 14 + +import native_app_glue +import pthreads::concurrent_collections + +in "Java" `{ + import android.app.NativeActivity; + + import android.view.Gravity; + import android.view.MotionEvent; + import android.view.ViewGroup; + import android.view.ViewGroup.MarginLayoutParams; + + import android.widget.Button; + import android.widget.LinearLayout; + import android.widget.GridLayout; + import android.widget.PopupWindow; + import android.widget.TextView; + + import java.lang.*; + import java.util.*; +`} + +# An event from the `app.nit` framework +interface AppEvent + # Reaction to this event + fun react do end +end + +# A control click event +class ClickEvent + super AppEvent + + # Sender of this event + var sender: Button + + redef fun react do sender.click self +end + +# Receiver of events not handled directly by the sender +interface EventCatcher + fun catch_event(event: AppEvent) do end +end + +redef class App + super EventCatcher + + # Queue of events to be received by the main thread + var event_queue = new ConcurrentList[AppEvent] + + # Call `react` on all `AppEvent` available in `event_queue` + protected fun loop_on_ui_callbacks + do + var queue = event_queue + while not queue.is_empty do + var event = queue.pop + event.react + end + end + + redef fun run + do + loop + # Process Android events + poll_looper 100 + + # Process app.nit events + loop_on_ui_callbacks + end + end +end + +redef extern class NativeActivity + + # Fill this entire `NativeActivity` with `popup` + # + # This is a workaround for the use on `takeSurface` in `NativeActivity.java` + # + # TODO replace NativeActivity by our own NitActivity + private fun dedicate_to_popup(popup: NativePopupWindow, popup_layout: NativeViewGroup) in "Java" `{ + final LinearLayout final_main_layout = new LinearLayout(recv); + final ViewGroup final_popup_layout = popup_layout; + final PopupWindow final_popup = popup; + final NativeActivity final_recv = recv; + + recv.runOnUiThread(new Runnable() { + @Override + public void run() { + MarginLayoutParams params = new MarginLayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.MATCH_PARENT); + + final_recv.setContentView(final_main_layout, params); + + final_popup.showAtLocation(final_popup_layout, Gravity.TOP, 0, 40); + } + }); + `} + + # Set the main layout of this activity + fun content_view=(layout: NativeViewGroup) + do + var popup = new NativePopupWindow(self) + popup.content_view = layout + dedicate_to_popup(popup, layout) + end + + # Set the real content view of this activity, without hack + # + # TODO bring use this instead of the hack with `dedicate_to_pupup` + private fun real_content_view=(layout: NativeViewGroup) in "Java" `{ + final ViewGroup final_layout = layout; + final NativeActivity final_recv = recv; + + recv.runOnUiThread(new Runnable() { + @Override + public void run() { + final_recv.setContentView(final_layout); + + final_layout.requestFocus(); + } + }); + `} +end + +# An `Object` that raises events +abstract class Eventful + var event_catcher: EventCatcher = app is lazy, writable +end + +# +## Nity classes and services +# + +# An Android control with text +abstract class TextView + super Finalizable + super Eventful + + # Native Java variant to this Nity class + type NATIVE: NativeTextView + + # The native Java object encapsulated by `self` + var native: NATIVE is noinit + + # Get the text of this view + fun text: String + do + var jstr = native.text + var str = jstr.to_s + jstr.delete_local_ref + return str + end + + # Set the text of this view + fun text=(value: Text) + do + var jstr = value.to_s.to_java_string + native.text = jstr + jstr.delete_local_ref + end + + # Get whether this view is enabled or not + fun enabled: Bool do return native.enabled + + # Set if this view is enabled + fun enabled=(val: Bool) do native.enabled = val + + # Set the size of the text in this view at `dpi` + fun text_size=(dpi: Numeric) do native.text_size = dpi.to_f + + private var finalized = false + redef fun finalize + do + if not finalized then + native.delete_global_ref + finalized = true + end + end +end + +# An Android button +class Button + super TextView + + redef type NATIVE: NativeButton + + init + do + var native = new NativeButton(app.native_activity, app.event_queue, self) + self.native = native.new_global_ref + end + + # Click event on the Main thread + # + # By default, this method calls `app.catch_event`. It can be specialized + # with custom behavior or the receiver of `catch_event` can be changed + # with `event_catcher=`. + fun click(event: AppEvent) do event_catcher.catch_event(event) + + # Click event on the UI thread + # + # This method is called on the UI thread and redirects the event to `click` + # throught `App::event_queue`. In most cases, you should implement `click` + # and leave `click_ui` as is. + fun click_ui do app.event_queue.add(new ClickEvent(self)) +end + +# An Android editable text field +class EditText + super TextView + + redef type NATIVE: NativeEditText + + init + do + var native = new NativeEditText(app.native_activity) + self.native = native.new_global_ref + end +end + +# +## Native classes +# + +# A `View` for Android +extern class NativeView in "Java" `{ android.view.View `} + super JavaObject + + fun minimum_width=(val: Int) in "Java" `{ recv.setMinimumWidth((int)val); `} + fun minimum_height=(val: Int) in "Java" `{ recv.setMinimumHeight((int)val); `} +end + +# A collection of `NativeView` +extern class NativeViewGroup in "Java" `{ android.view.ViewGroup `} + super NativeView + + fun add_view(view: NativeView) in "Java" `{ recv.addView(view); `} +end + +# A `NativeViewGroup` organized in a line +extern class NativeLinearLayout in "Java" `{ android.widget.LinearLayout `} + super NativeViewGroup + + new(context: NativeActivity) in "Java" `{ return new LinearLayout(context); `} + + fun set_vertical in "Java" `{ recv.setOrientation(LinearLayout.VERTICAL); `} + fun set_horizontal in "Java" `{ recv.setOrientation(LinearLayout.HORIZONTAL); `} + + redef fun add_view(view) in "Java" + `{ + MarginLayoutParams params = new MarginLayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT); + recv.addView(view, params); + `} + + fun add_view_with_weight(view: NativeView, weight: Float) + in "Java" `{ + recv.addView(view, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT, (float)weight)); + `} +end + +# A `NativeViewGroup` organized as a grid +extern class NativeGridLayout in "Java" `{ android.widget.GridLayout `} + super NativeViewGroup + + new(context: NativeActivity) in "Java" `{ return new android.widget.GridLayout(context); `} + + fun row_count=(val: Int) in "Java" `{ recv.setRowCount((int)val); `} + + fun column_count=(val: Int) in "Java" `{ recv.setColumnCount((int)val); `} + + redef fun add_view(view) in "Java" `{ recv.addView(view); `} +end + +extern class NativePopupWindow in "Java" `{ android.widget.PopupWindow `} + super NativeView + + new (context: NativeActivity) in "Java" `{ + PopupWindow recv = new PopupWindow(context); + recv.setWindowLayoutMode(LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.MATCH_PARENT); + recv.setClippingEnabled(false); + return recv; + `} + + fun content_view=(layout: NativeViewGroup) in "Java" `{ recv.setContentView(layout); `} +end + +extern class NativeTextView in "Java" `{ android.widget.TextView `} + super NativeView + + new (context: NativeActivity) in "Java" `{ return new TextView(context); `} + + fun text: JavaString in "Java" `{ return recv.getText().toString(); `} + + fun text=(value: JavaString) in "Java" `{ + + android.util.Log.d("Nity", "1"); + final TextView final_recv = recv; + final String final_value = value; + + android.util.Log.d("Nity", "4"); + ((NativeActivity)recv.getContext()).runOnUiThread(new Runnable() { + @Override + public void run() { + android.util.Log.d("Nity", "-5"); + android.util.Log.d("Nity", final_value); + android.util.Log.d("Nity", "-5.5"); + final_recv.setText(final_value); + android.util.Log.d("Nity", "-6"); + } + }); + android.util.Log.d("Nity", "7"); + `} + + fun enabled: Bool in "Java" `{ return recv.isEnabled(); `} + fun enabled=(value: Bool) in "Java" `{ + final TextView final_recv = recv; + final boolean final_value = value; + + ((NativeActivity)recv.getContext()).runOnUiThread(new Runnable() { + @Override + public void run() { + final_recv.setEnabled(final_value); + } + }); + `} + + fun gravity_center in "Java" `{ + recv.setGravity(Gravity.CENTER); + `} + + fun text_size=(dpi: Float) in "Java" `{ + recv.setTextSize(android.util.TypedValue.COMPLEX_UNIT_DIP, (float)dpi); + `} +end + +extern class NativeEditText in "Java" `{ android.widget.EditText `} + super NativeTextView + + redef type SELF: NativeEditText + + new (context: NativeActivity) in "Java" `{ return new android.widget.EditText(context); `} + + fun width=(val: Int) in "Java" `{ recv.setWidth((int)val); `} + + fun input_type_text in "Java" `{ recv.setInputType(android.text.InputType.TYPE_CLASS_TEXT); `} + + redef fun new_global_ref: SELF import sys, Sys.jni_env `{ + Sys sys = NativeEditText_sys(recv); + JNIEnv *env = Sys_jni_env(sys); + return (*env)->NewGlobalRef(env, recv); + `} +end + +extern class NativeButton in "Java" `{ android.widget.Button `} + super NativeTextView + + redef type SELF: NativeButton + + new (context: NativeActivity, queue: ConcurrentList[AppEvent], sender_object: Object) import Button.click_ui in "Java" `{ + final int final_sender_object = sender_object; + + return new Button(context){ + @Override + public boolean onTouchEvent(MotionEvent event) { + if(event.getAction() == MotionEvent.ACTION_DOWN) { + Button_click_ui(final_sender_object); + return true; + } + return false; + } + }; + `} + + redef fun new_global_ref: SELF import sys, Sys.jni_env `{ + Sys sys = NativeButton_sys(recv); + JNIEnv *env = Sys_jni_env(sys); + return (*env)->NewGlobalRef(env, recv); + `} +end