Views and services to use the Android native user interface

Redefined classes

redef class Activity

android :: ui $ Activity

An Android activity
redef extern class Android_app_Fragment

android :: ui $ Android_app_Fragment

Java class: android.app.Fragment
redef extern class Android_widget_ArrayAdapter

android :: ui $ Android_widget_ArrayAdapter

Java class: android.widget.ArrayAdapter
redef class App

android :: ui $ App

App subclasses are cross-platform applications
redef class Button

android :: ui $ Button

A pressable button, raises ButtonPressEvent
redef class CheckBox

android :: ui $ CheckBox

Toggle control between two states, also displays a label
redef class CompositeControl

android :: ui $ CompositeControl

A Control grouping other controls
redef class Control

android :: ui $ Control

A control implementing the UI
redef class HorizontalLayout

android :: ui $ HorizontalLayout

An horizontal linear organization
redef extern class JavaString

android :: ui $ JavaString

A standard Java string java.lang.String
redef class Label

android :: ui $ Label

A simple text label
redef abstract class Layout

android :: ui $ Layout

A layout to visually organize Controls
redef class ListLayout

android :: ui $ ListLayout

Scrollable list of views in a simple list
redef extern class NativeActivity

android :: ui $ NativeActivity

An activity, a single, focused thing a user can do on Android
redef extern class NativeButton

android :: ui $ NativeButton

redef extern class NativeEditText

android :: ui $ NativeEditText

redef abstract class Text

android :: ui $ Text

High-level abstraction for all text representations
redef class TextInput

android :: ui $ TextInput

A control for the user to enter custom text
redef abstract class TextView

android :: ui $ TextView

A control displaying some text
redef class VerticalLayout

android :: ui $ VerticalLayout

A vertical linear organization
redef abstract class View

android :: ui $ View

A visible Control
redef class Window

android :: ui $ Window

On Android, a window is implemented with the fragment native

All class definitions

redef class Activity

android :: ui $ Activity

An Android activity
redef extern class Android_app_Fragment

android :: ui $ Android_app_Fragment

Java class: android.app.Fragment
redef extern class Android_widget_ArrayAdapter

android :: ui $ Android_widget_ArrayAdapter

Java class: android.widget.ArrayAdapter
redef class App

android :: ui $ App

App subclasses are cross-platform applications
redef class Button

android :: ui $ Button

A pressable button, raises ButtonPressEvent
redef class CheckBox

android :: ui $ CheckBox

Toggle control between two states, also displays a label
redef class CompositeControl

android :: ui $ CompositeControl

A Control grouping other controls
redef class Control

android :: ui $ Control

A control implementing the UI
redef class HorizontalLayout

android :: ui $ HorizontalLayout

An horizontal linear organization
redef extern class JavaString

android :: ui $ JavaString

A standard Java string java.lang.String
redef class Label

android :: ui $ Label

A simple text label
redef abstract class Layout

android :: ui $ Layout

A layout to visually organize Controls
redef class ListLayout

android :: ui $ ListLayout

Scrollable list of views in a simple list
redef extern class NativeActivity

android :: ui $ NativeActivity

An activity, a single, focused thing a user can do on Android
redef extern class NativeButton

android :: ui $ NativeButton

redef extern class NativeEditText

android :: ui $ NativeEditText

redef abstract class Text

android :: ui $ Text

High-level abstraction for all text representations
redef class TextInput

android :: ui $ TextInput

A control for the user to enter custom text
redef abstract class TextView

android :: ui $ TextView

A control displaying some text
redef class VerticalLayout

android :: ui $ VerticalLayout

A vertical linear organization
redef abstract class View

android :: ui $ View

A visible Control
redef class Window

android :: ui $ Window

On Android, a window is implemented with the fragment native
package_diagram android::ui ui android::native_ui native_ui android::ui->android::native_ui app::ui ui android::ui->app::ui android::data_store data_store android::ui->android::data_store android::assets assets android::ui->android::assets android::nit_activity nit_activity android::native_ui->android::nit_activity app::app_base app_base app::ui->app::app_base app::data_store data_store android::data_store->app::data_store android\>shared_preferences\> shared_preferences android::data_store->android\>shared_preferences\> android::assets_and_resources assets_and_resources android::assets->android::assets_and_resources ...android::nit_activity ... ...android::nit_activity->android::nit_activity ...app::app_base ... ...app::app_base->app::app_base ...app::data_store ... ...app::data_store->app::data_store ...android\>shared_preferences\> ... ...android\>shared_preferences\>->android\>shared_preferences\> ...android::assets_and_resources ... ...android::assets_and_resources->android::assets_and_resources android::http_request http_request android::http_request->android::ui android::ui_test ui_test android::ui_test->android::ui a_star-m a_star-m a_star-m->android::http_request a_star-m->android::ui_test a_star-m... ... a_star-m...->a_star-m

Ancestors

module abstract_collection

core :: abstract_collection

Abstract collection classes and services.
module abstract_text

core :: abstract_text

Abstract class for manipulation of sequences of characters
module activities

android :: activities

Android Activities wrapper
module app

app :: app

app.nit is a framework to create cross-platform applications
module app_base

app :: app_base

Base of the app.nit framework, defines App
module array

core :: array

This module introduces the standard array structure.
module assets

app :: assets

Portable services to load resources from the assets folder
module assets_and_resources

android :: assets_and_resources

Android Assets and Resources Management
module aware

android :: aware

Android compatibility module
module bitset

core :: bitset

Services to handle BitSet
module bundle

android :: bundle

A mapping class of String to various value types used by the
module bytes

core :: bytes

Services for byte streams and arrays
module caching

serialization :: caching

Services for caching serialization engines
module circular_array

core :: circular_array

Efficient data structure to access both end of the sequence.
module codec_base

core :: codec_base

Base for codecs to use with streams
module codecs

core :: codecs

Group module for all codec-related manipulations
module collection

core :: collection

This module define several collection classes.
module collections

java :: collections

Basic Java collections
module core

core :: core

Standard classes and methods used by default by Nit programs and libraries.
module dalvik

android :: dalvik

Java related services specific to Android and its Dalvik VM
module data_store

app :: data_store

Key/value storage services
module engine_tools

serialization :: engine_tools

Advanced services for serialization engines
module environ

core :: environ

Access to the environment variables of the process
module error

core :: error

Standard error-management infrastructure.
module error

json :: error

Intro JsonParseError which is exposed by all JSON reading APIs
module exec

core :: exec

Invocation and management of operating system sub-processes.
module ffi_support

java :: ffi_support

Core supporting services for the FFI with Java
module file

core :: file

File manipulations (create, read, write, etc.)
module fixed_ints

core :: fixed_ints

Basic integers of fixed-precision
module fixed_ints_text

core :: fixed_ints_text

Text services to complement fixed_ints
module flat

core :: flat

All the array-based text representations
module gc

core :: gc

Access to the Nit internal garbage collection mechanism
module hash_collection

core :: hash_collection

Introduce HashMap and HashSet.
module inspect

serialization :: inspect

Refine Serializable::inspect to show more useful information
module io

java :: io

Services from the java.io package
module iso8859_1

core :: iso8859_1

Codec for ISO8859-1 I/O
module java

java :: java

Supporting services for the FFI with Java and to access Java libraries
module json

json :: json

Read and write JSON formatted text using the standard serialization services
module jvm

jvm :: jvm

Java Virtual Machine invocation API and others services from the JNI C API
module kernel

core :: kernel

Most basic classes and methods.
module list

core :: list

This module handle double linked lists
module log

android :: log

Advanced Android logging services
module math

core :: math

Mathematical operations
module meta

meta :: meta

Simple user-defined meta-level to manipulate types of instances as object.
module native

core :: native

Native structures for text and bytes
module nit_activity

android :: nit_activity

Core implementation of app.nit on Android using a custom Java entry point
module numeric

core :: numeric

Advanced services for Numeric types
module parser_base

parser_base :: parser_base

Simple base for hand-made parsers of all kinds
module platform

android :: platform

Triggers compilation for the android platform
module poset

poset :: poset

Pre order sets and partial order set (ie hierarchies)
module protocol

core :: protocol

module queue

core :: queue

Queuing data structures and wrappers
module range

core :: range

Module for range of discrete objects.
module re

core :: re

Regular expression support for all services based on Pattern
module ropes

core :: ropes

Tree-based representation of a String.
module safe

serialization :: safe

Services for safer deserialization engines
module serialization

serialization :: serialization

General serialization services
module serialization_core

serialization :: serialization_core

Abstract services to serialize Nit objects to different formats
module serialization_read

json :: serialization_read

Services to read JSON: deserialize_json and JsonDeserializer
module serialization_write

json :: serialization_write

Services to write Nit objects to JSON strings: serialize_to_json and JsonSerializer
module shared_preferences

android :: shared_preferences

Services allowing to save and load datas to internal android device
module shared_preferences_api10

android :: shared_preferences_api10

Services to save/load data using android.content.SharedPreferences for the android platform
module sorter

core :: sorter

This module contains classes used to compare things and sorts arrays.
module static

json :: static

Static interface to read Nit objects from JSON strings
module stream

core :: stream

Input and output streams of characters
module text

core :: text

All the classes and methods related to the manipulation of text entities
module time

core :: time

Management of time and dates
module union_find

core :: union_find

union–find algorithm using an efficient disjoint-set data structure
module utf8

core :: utf8

Codec for UTF-8 I/O

Parents

module assets

android :: assets

Implementation of app::assets
module data_store

android :: data_store

Implements app::data_store using shared_preferences
module native_ui

android :: native_ui

Native services from the android.view and android.widget namespaces
module ui

app :: ui

Portable UI controls for mobiles apps

Children

module http_request

android :: http_request

Android implementation of app:http_request
module ui_test

android :: ui_test

Test for app.nit's UI services

Descendants

module a_star-m

a_star-m

# Views and services to use the Android native user interface
module ui is
	# `adjustPan` allows to use EditText in a ListLayout
	android_manifest_activity """android:windowSoftInputMode="adjustPan""""
end

# Implementation note:
#
# We cannot rely on `Activity::on_restore_instance_state` to implement
# `on_restore_state` is it only invoked if there is a bundled state,
# and we don't use the Android bundled state.

import native_ui
import log
import nit_activity

import app::ui
private import data_store
import assets

redef class Control
	# The Android element used to implement `self`
	fun native: NATIVE is abstract

	# Type of `native`
	type NATIVE: JavaObject
end

redef class NativeActivity

	private fun remove_title_bar in "Java" `{
		self.requestWindowFeature(android.view.Window.FEATURE_NO_TITLE);
	`}

	# Insert a single layout as the root of the activity window
	private fun insert_root_layout(root_layout_id: Int)
	in "Java" `{
		android.widget.FrameLayout layout = new android.widget.FrameLayout(self);
		layout.setId((int)root_layout_id);
		self.setContentView(layout);
	`}

	# Replace the currently visible fragment, if any, with `native_fragment`
	private fun show_fragment(root_layout_id: Int, native_fragment: Android_app_Fragment)
	in "Java" `{
		android.app.FragmentTransaction transaction = self.getFragmentManager().beginTransaction();
		transaction.replace((int)root_layout_id, native_fragment);
		transaction.commit();
	`}
end

redef class App
	redef fun on_create
	do
		app.native_activity.remove_title_bar
		native_activity.insert_root_layout(root_layout_id)
		super
	end

	# Identifier of the container holding the fragments
	private var root_layout_id = 0xFFFF

	redef fun window=(window)
	do
		native_activity.show_fragment(root_layout_id, window.native)
		super
	end

	redef fun on_start do window.on_start

	redef fun on_destroy do window.on_destroy
end

redef class CompositeControl
	redef fun on_start do for i in items do i.on_start

	redef fun on_destroy do for i in items do i.on_destroy
end

redef class Activity
	redef fun on_back_pressed
	do
		var window = app.window
		if window.enable_back_button then
			window.on_back_button
			return true
		end

		return false
	end
end

# On Android, a window is implemented with the fragment `native`
redef class Window
	redef var native = (new Android_app_Fragment(self)).new_global_ref

	redef type NATIVE: Android_app_Fragment

	# Root high-level view of this window
	var view: nullable View = null

	redef fun add(item)
	do
		if item isa View then view = item
		super
	end

	private fun on_create_fragment: NativeView
	do
		on_create

		var view = view
		assert view != null else print_error "{class_name} needs a `view` after `Window::on_create` returns"
		return view.native
	end
end

redef class View
	redef type NATIVE: NativeView

	redef fun enabled=(enabled) do native.enabled = enabled or else true
	redef fun enabled do return native.enabled
end

redef class Layout
	redef type NATIVE: NativeViewGroup

	redef fun add(item)
	do
		super

		assert item isa View

		# FIXME abstract the use either homogeneous or weight to balance views size in a layout
		native.add_view_with_weight(item.native, 1.0)
	end

	redef fun remove(item)
	do
		super
		if item isa View then native.remove_view item.native
	end
end

redef class HorizontalLayout
	redef var native do
		var layout = new NativeLinearLayout(app.native_activity)
		layout = layout.new_global_ref
		layout.set_horizontal
		return layout
	end
end

redef class VerticalLayout
	redef var native do
		var layout = new NativeLinearLayout(app.native_activity)
		layout = layout.new_global_ref
		layout.set_vertical
		return layout
	end
end

redef class ListLayout
	redef type NATIVE: Android_widget_ListView

	redef var native do
		var layout = new Android_widget_ListView(app.native_activity)
		layout = layout.new_global_ref
		return layout
	end

	private var adapter: Android_widget_ArrayAdapter do
		var adapter = new Android_widget_ArrayAdapter(app.native_activity,
			android_r_layout_simple_list_item_1, self)
		native.set_adapter adapter
		return adapter.new_global_ref
	end

	redef fun add(item)
	do
		super
		if item isa View then adapter.add item.native
	end

	private fun create_view(position: Int): NativeView
	do
		var ctrl = items[position]
		assert ctrl isa View
		return ctrl.native
	end
end

redef class Android_widget_ArrayAdapter
	private new (context: NativeContext, res: Int, sender: ListLayout)
	import ListLayout.create_view in "Java" `{
		final nit.app.NitObject final_sender_object = sender;
		ListLayout_incr_ref(sender);

		return new android.widget.ArrayAdapter(context, (int)res) {
				@Override
				public android.view.View getView(int position, android.view.View convertView, android.view.ViewGroup parent) {
					return ListLayout_create_view(final_sender_object, position);
				}
			};
	`}
end

redef class TextView
	redef type NATIVE: NativeTextView

	redef fun text do return native.text.to_s
	redef fun text=(value) do
		if value == null then value = ""
		native.text = value.to_java_string
	end

	redef fun size=(size) do set_size_native(app.native_activity, native, size or else 1.0)

	private fun set_size_native(context: NativeContext, view: NativeTextView, size: Float)
	in "Java" `{
		int s;
		if (size == 1.0d)
			s = android.R.style.TextAppearance_Medium;
		else if (size < 1.0d)
			s = android.R.style.TextAppearance_Small;
		else // if (size > 1.0d)
			s = android.R.style.TextAppearance_Large;

		view.setTextAppearance(context, s);
	`}

	redef fun align=(align) do set_align_native(native, align or else 0.0)

	private fun set_align_native(view: NativeTextView, align: Float)
	in "Java" `{
		int g;
		if (align == 0.5d)
			g = android.view.Gravity.CENTER_HORIZONTAL;
		else if (align < 0.5d)
			g = android.view.Gravity.LEFT;
		else // if (align > 0.5d)
			g = android.view.Gravity.RIGHT;

		view.setGravity(g | android.view.Gravity.CENTER_VERTICAL);
	`}
end

redef class Label
	redef type NATIVE: NativeTextView
	redef var native do return (new NativeTextView(app.native_activity)).new_global_ref
end

redef class CheckBox
	redef type NATIVE: Android_widget_CompoundButton
	redef var native do return (new Android_widget_CheckBox(app.native_activity)).new_global_ref
	init do set_callback_on_toggle(native)

	redef fun is_checked do return native.is_checked
	redef fun is_checked=(value) do native.set_checked(value)

	private fun on_toggle do notify_observers new ToggleEvent(self)

	private fun set_callback_on_toggle(view: NATIVE)
	import on_toggle in "Java" `{
		final nit.app.NitObject final_sender_object = self;
		CheckBox_incr_ref(final_sender_object);

		view.setOnCheckedChangeListener(
			new android.widget.CompoundButton.OnCheckedChangeListener() {
				@Override
				public void onCheckedChanged(android.widget.CompoundButton buttonView, boolean isChecked) {
					CheckBox_on_toggle(final_sender_object);
				}
			});
	`}
end

redef class TextInput
	redef type NATIVE: NativeEditText
	redef var native = (new NativeEditText(app.native_activity)).new_global_ref

	redef fun is_password=(value)
	do
		native.is_password = value or else false
		super
	end
end

redef class NativeEditText

	# Configure this view to hide passwords
	fun is_password=(value: Bool) in "Java" `{
		if (value) {
			self.setInputType(android.text.InputType.TYPE_CLASS_TEXT | android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD);
			self.setTransformationMethod(android.text.method.PasswordTransformationMethod.getInstance());
		} else {
			self.setInputType(android.text.InputType.TYPE_CLASS_TEXT);
			self.setTransformationMethod(null);
		}
	`}
end

redef class Button
	super Finalizable

	redef type NATIVE: NativeButton
	redef var native = (new NativeButton(app.native_activity, self)).new_global_ref

	private fun on_click do notify_observers new ButtonPressEvent(self)

	redef fun finalize do native.delete_global_ref
end

redef class NativeButton
	private new (context: NativeActivity, sender_object: Button)
	import Button.on_click in "Java" `{
		final nit.app.NitObject final_sender_object = sender_object;
		Button_incr_ref(final_sender_object);

		return new android.widget.Button(context) {
			@Override
			public boolean onTouchEvent(android.view.MotionEvent event) {
				if (event.getAction() == android.view.MotionEvent.ACTION_UP) {
					Button_on_click(final_sender_object);
					return true;
				} else if (event.getAction() == android.view.MotionEvent.ACTION_DOWN) {
					return true;
				}
				return false;
			}
		};
	`}
end

redef class Android_app_Fragment
	private new (nit_window: Window)
	import Window.on_create_fragment in "Java" `{
		final nit.app.NitObject final_nit_window = nit_window;
		Window_incr_ref(nit_window);

		return new android.app.Fragment(){
			@Override
			public android.view.View onCreateView(android.view.LayoutInflater inflater,
				android.view.ViewGroup container, android.os.Bundle state) {

				return Window_on_create_fragment(final_nit_window);
			}
		};
	`}
end

redef class Text
	redef fun open_in_browser
	do to_java_string.native_open_in_browser(app.native_activity)
end

redef class JavaString
	private fun native_open_in_browser(context: NativeContext)
	in "Java" `{
		android.content.Intent intent = new android.content.Intent(
			android.content.Intent.ACTION_VIEW,
			android.net.Uri.parse(self));
		context.startActivity(intent);
	`}
end
lib/android/ui/ui.nit:15,1--379,3