# See the License for the specific language governing permissions and
# limitations under the License.
-# Portable UI API for the _app.nit_ framework
+# 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
# This attribute is set by `push_window`.
var window: Window is noinit
- # Make visible and push `window` on the top of `pop_window`
+ # Make `window` visible and push it on the top of the `window_stack`
#
- # This method must be called at least once within `App::on_create`.
- # It can be called at any times while the app is active.
+ # 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
# Stack of active windows
var window_stack = new Array[Window]
- redef fun on_create do window.on_create
-
- redef fun on_start do window.on_start
+ redef fun on_create
+ do
+ var window = root_window
+ push_window window
+ end
redef fun on_resume do window.on_resume
redef fun on_stop do window.on_stop
- redef fun on_destroy do window.on_destroy
-
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
# 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
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`
redef fun on_create do for i in items do i.on_create
- redef fun on_start do for i in items do i.on_start
-
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_destroy do for i in items do i.on_destroy
-
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
fun on_back_button do app.pop_window
end
-# A viewable `Control`
+# A visible `Control`
abstract class View
super Control
var enabled: nullable Bool is writable, abstract, autoinit
end
-# A control with some `text`
+# A control displaying some `text`
+#
+# For a text-only control, see `Label`.
abstract class TextView
super View
# 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=(center: nullable Float) is autoinit do end
+ fun align=(align: nullable Float) is autoinit do end
end
# A control for the user to enter custom `text`
var is_password: nullable Bool is writable
end
-# A pushable button, raises `ButtonPressEvent`
+# A pressable button, raises `ButtonPressEvent`
class Button
super TextView
end
-# A text label
+# A simple text label
class Label
super TextView
end
-# Toggle control with two states and a label
+# Toggle control between two states, also displays a label
class CheckBox
super TextView
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