Portable UI controls for mobiles apps

import app::ui

class MyWindow
    super Window

    var layout = new ListLayout(parent=self)
    var lbl = new Label(parent=layout, text="Hello world", align=0.5)
    var but = new Button(parent=layout, text="Press here")

    redef fun on_event(event) do lbl.text = "Pressed!"
end

redef fun root_window do return new MyWindow

Introduced classes

interface AppEvent

app :: AppEvent

An event created by an AppComponent and sent to AppObservers
interface AppObserver

app :: AppObserver

Observer of AppEvents raised by AppComponents
class Button

app :: Button

A pressable button, raises ButtonPressEvent
class ButtonPressEvent

app :: ButtonPressEvent

A Button press event
class CheckBox

app :: CheckBox

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

app :: CompositeControl

A Control grouping other controls
class Control

app :: Control

A control implementing the UI
class HorizontalLayout

app :: HorizontalLayout

An horizontal linear organization
class Label

app :: Label

A simple text label
abstract class Layout

app :: Layout

A layout to visually organize Controls
class ListLayout

app :: ListLayout

Scrollable list of views in a simple list
class TextInput

app :: TextInput

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

app :: TextView

A control displaying some text
class ToggleEvent

app :: ToggleEvent

The CheckBox sender has been toggled
class VerticalLayout

app :: VerticalLayout

A vertical linear organization
abstract class View

app :: View

A visible Control
class ViewEvent

app :: ViewEvent

Event sent from a VIEW
class Window

app :: Window

A window, root of the Control tree

Redefined classes

redef class App

app :: ui $ App

App subclasses are cross-platform applications
redef abstract class AppComponent

app :: ui $ AppComponent

An element of an application that is notified of the application life cycle
redef class Sys

app :: ui $ Sys

The main class of the program.
redef abstract class Text

app :: ui $ Text

High-level abstraction for all text representations

All class definitions

redef class App

app :: ui $ App

App subclasses are cross-platform applications
redef abstract class AppComponent

app :: ui $ AppComponent

An element of an application that is notified of the application life cycle
interface AppEvent

app $ AppEvent

An event created by an AppComponent and sent to AppObservers
interface AppObserver

app $ AppObserver

Observer of AppEvents raised by AppComponents
class Button

app $ Button

A pressable button, raises ButtonPressEvent
class ButtonPressEvent

app $ ButtonPressEvent

A Button press event
class CheckBox

app $ CheckBox

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

app $ CompositeControl

A Control grouping other controls
class Control

app $ Control

A control implementing the UI
class HorizontalLayout

app $ HorizontalLayout

An horizontal linear organization
class Label

app $ Label

A simple text label
abstract class Layout

app $ Layout

A layout to visually organize Controls
class ListLayout

app $ ListLayout

Scrollable list of views in a simple list
redef class Sys

app :: ui $ Sys

The main class of the program.
redef abstract class Text

app :: ui $ Text

High-level abstraction for all text representations
class TextInput

app $ TextInput

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

app $ TextView

A control displaying some text
class ToggleEvent

app $ ToggleEvent

The CheckBox sender has been toggled
class VerticalLayout

app $ VerticalLayout

A vertical linear organization
abstract class View

app $ View

A visible Control
class ViewEvent

app $ ViewEvent

Event sent from a VIEW
class Window

app $ Window

A window, root of the Control tree
package_diagram app::ui ui app::app_base app_base app::ui->app::app_base core core app::app_base->core ...core ... ...core->core android::ui ui android::ui->app::ui app::http_request_example http_request_example app::http_request_example->app::ui app::ui_example ui_example app::ui_example->app::ui ios::ui ui ios::ui->app::ui linux::ui ui linux::ui->app::ui android::http_request http_request android::http_request->android::ui android::ui_test ui_test android::ui_test->android::ui android::http_request... ... android::http_request...->android::http_request android::ui_test... ... android::ui_test...->android::ui_test a_star-m a_star-m a_star-m->app::http_request_example a_star-m->app::ui_example a_star-m->ios::ui a_star-m->linux::ui 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 array

core :: array

This module introduces the standard array structure.
module bitset

core :: bitset

Services to handle BitSet
module bytes

core :: bytes

Services for byte streams and arrays
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 core

core :: core

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

core :: environ

Access to the environment variables of the process
module error

core :: error

Standard error-management infrastructure.
module exec

core :: exec

Invocation and management of operating system sub-processes.
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 iso8859_1

core :: iso8859_1

Codec for ISO8859-1 I/O
module kernel

core :: kernel

Most basic classes and methods.
module list

core :: list

This module handle double linked lists
module math

core :: math

Mathematical operations
module native

core :: native

Native structures for text and bytes
module numeric

core :: numeric

Advanced services for Numeric types
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 sorter

core :: sorter

This module contains classes used to compare things and sorts arrays.
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 app_base

app :: app_base

Base of the app.nit framework, defines App

Children

module http_request_example

app :: http_request_example

Example for the app::http_request main service AsyncHttpRequest
module ui

android :: ui

Views and services to use the Android native user interface
module ui

ios :: ui

Implementation of app::ui for iOS
module ui

linux :: ui

Implementation of the app.nit UI module for GNU/Linux
module ui_example

app :: ui_example

User interface example using app::ui

Descendants

module a_star-m

a_star-m

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
# Portable UI controls for mobiles apps
#
# ~~~
# import app::ui
#
# class MyWindow
#     super Window
#
#     var layout = new ListLayout(parent=self)
#     var lbl = new Label(parent=layout, text="Hello world", align=0.5)
#     var but = new Button(parent=layout, text="Press here")
#
#     redef fun on_event(event) do lbl.text = "Pressed!"
# end
#
# redef fun root_window do return new MyWindow
# ~~~
module ui

import app_base

# Platform variations
import linux::ui is conditional(linux)
import android::ui is conditional(android)
import ios::ui is conditional(ios)

redef class App
	super AppComponent

	# The current `Window` of this activity
	#
	# This attribute is set by `push_window`.
	var window: Window is noinit

	# Make `window` visible and push it on the top of the `window_stack`
	#
	# This method can be called at any times while the app is active.
	fun push_window(window: Window)
	do
		window_stack.add window
		self.window = window
		window.on_create
	end

	# Pop the current `window` from the stack and show the previous one
	#
	# Require: `window_stack.not_empty`
	fun pop_window
	do
		assert window_stack.not_empty
		window_stack.pop
		window = window_stack.last
		window.on_resume
	end

	# Stack of active windows
	var window_stack = new Array[Window]

	redef fun on_create
	do
		var window = root_window
		push_window window
	end

	redef fun on_resume do window.on_resume

	redef fun on_pause do window.on_pause

	redef fun on_stop do window.on_stop

	redef fun on_restore_state do window.on_restore_state

	redef fun on_save_state do window.on_save_state
end

# Hook to create the first window shown to the user
#
# By default, a `Window` is created, which can be refined to customize it.
# However, most apps should refine this method to return a different window,
# this way the app can have more than one window.
fun root_window: Window do return new Window

# An event created by an `AppComponent` and sent to `AppObserver`s
interface AppEvent
end

# Observer of `AppEvent`s raised by `AppComponent`s
interface AppObserver
	# Notification of `event` raised by `sender`
	#
	# To be implemented in subclasses as needed.
	fun on_event(event: AppEvent) do end
end

redef class AppComponent
	super AppObserver

	# All `AppObserver` notified of events raised by `self`
	#
	# By default, only `self` is an observer.
	# Any other `AppObserver` can be added to this collection.
	var observers = new HashSet[AppObserver].from([self: AppObserver])

	# Propagate `event` to all `observers` by calling `AppObserver::on_event`
	fun notify_observers(event: AppEvent)
	do
		for observer in observers do
			observer.on_event(event)
		end
	end
end

# A control implementing the UI
class Control
	super AppComponent

	# Direct parent `Control` in the control tree
	#
	# The parents (direct and indirect) receive all events from `self`,
	# like the `observers`.
	#
	# If `null` then `self` is at the root of the tree, or not yet attached.
	var parent: nullable CompositeControl = null is private writable(set_parent)

	# Direct parent `Control` in the control tree
	#
	# The parents (direct and indirect) receive all events from `self`,
	# like the `observers`.
	#
	# Setting `parent` calls `remove` on the old parent and `add` on the new one.
	fun parent=(parent: nullable CompositeControl)
	is autoinit	do
		var old_parent = self.parent
		if old_parent != null and old_parent != parent then
			old_parent.remove self
		end

		if parent != null then parent.add self

		set_parent parent
	end

	# Also notify the parents (both direct and indirect)
	redef fun notify_observers(event)
	do
		super

		var p = parent
		while p != null do
			p.on_event event
			p = p.parent
		end
	end
end

# A `Control` grouping other controls
class CompositeControl
	super Control

	# Child controls composing this control
	protected var items = new Array[Control]

	# Add `item` as a child of `self`
	protected fun add(item: Control) do items.add item

	# Remove `item` from `self`
	fun remove(item: Control) do if has(item) then items.remove item

	# Is `item` in `self`?
	fun has(item: Control): Bool do return items.has(item)

	# Remove all items from `self`
	fun clear do for item in items.to_a do remove item

	redef fun on_create do for i in items do i.on_create

	redef fun on_resume do for i in items do i.on_resume

	redef fun on_pause do for i in items do i.on_pause

	redef fun on_stop do for i in items do i.on_stop

	redef fun on_restore_state do for i in items do i.on_restore_state

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

# A window, root of the `Control` tree
#
# Each window should hold a single control, usually a `CompositeControl`,
# which in turn holds all the displayed controls.
class Window
	super CompositeControl

	# Should the back button be shown and used to go back to a previous window?
	fun enable_back_button: Bool do return app.window_stack.length > 1

	# The back button has been pressed, usually to open the previous window
	fun on_back_button do app.pop_window
end

# A visible `Control`
abstract class View
	super Control

	# Is this control enabled so the user can interact with it?
	#
	# By default, or if set to `null`, the control is enabled.
	var enabled: nullable Bool is writable, abstract, autoinit
end

# A control displaying some `text`
#
# For a text-only control, see `Label`.
abstract class TextView
	super View

	# Main `Text` of this control
	#
	# By default, or if set to `null`, no text is shown.
	var text: nullable Text is writable, abstract, autoinit

	# Set the relative size of the text
	#
	# A value of 1.0, the default, use the platform default text size.
	# Values under 1.0 set a smaller text size, and over 1.0 a larger size.
	#
	# Implementation varies per platform, and some controls may be unaffected
	# depending on the customization options of each platform.
	# For consistent results, it is recommended to use only on instances
	# of `Label` and `size` should be either 0.5, 1.0 or 1.5.
	fun size=(size: nullable Float) is autoinit do end

	# Align the text horizontally
	#
	# Use 0.0 to align left (the default), 0.5 to align in the center and
	# 1.0 to align on the right.
	#
	# Implementation varies per platform, and some controls may be unaffected
	# depending on the customization options of each platform.
	# For consistent results, it is recommended to use only on instances
	# of `Label` and `size` should be either 0.0, 0.5 or 1.0.
	fun align=(align: nullable Float) is autoinit do end
end

# A control for the user to enter custom `text`
class TextInput
	super TextView

	# Hide password or any content entered in this view?
	var is_password: nullable Bool is writable
end

# A pressable button, raises `ButtonPressEvent`
class Button
	super TextView
end

# A simple text label
class Label
	super TextView
end

# Toggle control between two states, also displays a label
class CheckBox
	super TextView

	# Is this control in the checked/on state?
	var is_checked = false is writable
end

# Event sent from a `VIEW`
class ViewEvent
	super AppEvent

	# The `VIEW` that raised this event
	var sender: VIEW

	# Type of the `sender`
	type VIEW: View
end

# A `Button` press event
class ButtonPressEvent
	super ViewEvent

	redef type VIEW: Button
end

# The `CheckBox` `sender` has been toggled
class ToggleEvent
	super ViewEvent

	redef type VIEW: CheckBox
end

# A layout to visually organize `Control`s
abstract class Layout
	super View
	super CompositeControl
end

# An horizontal linear organization
class HorizontalLayout
	super Layout
end

# A vertical linear organization
class VerticalLayout
	super Layout
end

# Scrollable list of views in a simple list
class ListLayout
	super View
	super CompositeControl
end

redef class Text
	# Open the URL `self` with the default browser
	fun open_in_browser do print_error "Text::open_in_browser not implemented on this platform."
end
lib/app/ui.nit:15,1--336,3