nit: Added link to `CONTRIBUTING.md` from the README
[nit.git] / lib / app / README.md
1 _app.nit_, a framework for portable applications
2
3 The framework provides services to manage common needs of modern mobile applications:
4
5 * Life-cycle
6 * User interface
7 * Persistence
8 * Package metadata
9 * Compilation and packaging
10
11 The features offered by _app.nit_ are common to all platforms, but
12 may not be available on all devices.
13
14 ## Application Life-Cycle
15
16 The _app.nit_ application life-cycle is compatible with all target platforms.
17 It relies on the following sequence of events, represented here by their callback method name:
18
19 1. `on_create`: The application is being created.
20    You should build the UI at this time.
21
22 2. `on_start`: The app is starting or restarting, background activities may
23
24 3. `on_resume`: The app enters the active state, it is in the foreground.
25
26 4. `on_pause`: The app leaves the active state and the foreground.
27    It may still be visible in the background.
28    It may then go back to `on_resume` or `on_stop`.
29
30 5. `on_stop`: The app is completely hidden.
31    It may then be destroyed (`on_destroy`) or go back to `on_start`.
32
33 6. `on_destroy`: The app is being destroyed.
34
35 Life-cycle events related to saving and restoring the application state are provided by two special callback methods:
36
37 * `on_save_state`: The app may be destroyed soon, save its state for a future `on_restore_state`.
38   More on how it can be done in the `app::data_store` section.
39
40 * `on_restore_state`: The app is launching, restore its state from a previous `on_save_state`.
41
42 These events are synchronized to the native platforms applications
43 The `App` instance is the first to be notified of these events.
44 Other UI elements, from the `ui` submodule, are notified of the same events using a simple depth first visit.
45 So all UI elements can react separately to live-cycle events.
46
47 ## User Interface
48
49 The `app::ui` module defines an abstract API to build a portable graphical application.
50 The API is composed of interactive `Control`s, visible `View`s and an active `Window`.
51
52 Here is a subset of the most useful controls and views:
53
54 * The classic pushable `Button` with text (usually rectangular).
55
56 * `TextInput` is a field for the user to enter text.
57
58 * `HorizontalLayout` and `VerticalLayout` organize other controls in order.
59
60 Each control is notified of input events by callbacks to `on_event`.
61 All controls have observers that are also notified of the events.
62 So there is two ways  to customize the behavior on a given event:
63
64 * Create a subclass of the wanted `Control`, let's say `Button`, and specialize `on_event`.
65
66 * Add an observer to a `Button` instance, and implement `on_event` in the observer.
67
68 ### Usage Example
69
70 The calculator example (at `../../examples/calculator/src/calculator.nit`) is a concrete,
71 simple and complete use of the _app.nit_ portable UI.
72
73 ### Platform-specific UI
74
75 You can go beyond the portable UI API of _app.nit_ by using the natives services of a platform.
76
77 The suggested approach is to use platform specific modules to customize the application on a precise platform.
78 This module redefine `Window::on_start` to call the native language of the platform and setup a native UI.
79
80 _TODO complete description and add concrete examples_
81
82 ## Persistent State with data\_store
83
84 _app.nit_ offers the submodule `app::data_store` to easily save the application state and user preferences.
85 The service is accessible by the method `App::data_store`. The `DataStore` itself defines 2 methods:
86
87 * `DataStore::[]=` saves and associates any serializable instances to a `String` key.
88 Pass `null` to clear the value associated to a key.
89
90 * `DataStore::[]` returns the object associated to a `String` key.
91 It returns `null` if nothing is associated to the key.
92
93 ### Usage Example
94
95 ~~~
96 import app::data_store
97
98 redef class App
99         var user_name: String
100
101         redef fun on_save_state
102         do
103                 app.data_store["first run"] = false
104                 app.data_store["user name"] = user_name
105
106                 super # call `on_save_state` on all attached instances of `AppComponent`
107         end
108
109         redef fun on_restore_state
110         do
111                 var first_run = app.data_store["first run"]
112                 if first_run != true then
113                         print "It's the first run of this application"
114                 end
115
116                 var user_name = app.data_store["user name"]
117                 if user_name isa String then
118                         self.user_name = user_name
119                 else self.user_name = "Undefined"
120
121                 super
122         end
123 end
124 ~~~
125
126 ## Metadata annotations
127
128 The _app.nit_ framework defines three annotations to customize the application package.
129
130 * `app_name` takes a single argument, the visible name of the application.
131   This name is used for launchers and window title.
132   By default, the name of the target module.
133
134 * `app_namespace` specifies the full namespace (or package name) of the application package.
135   This value usually identify the application uniquely on application stores.
136   It should not change once the application has benn published.
137   By default, the namespace is `org.nitlanguage.{module_name}`.
138
139 * `app_version` specifies the version of the application package.
140   This annotation expects at least one argument, usually we use three version numbers:
141   the major, minor and revision.
142   The special function `git_revision` will use the prefix of the hash of the latest git commit.
143   By default, the version is 0.1.
144
145 ### Usage Example
146
147 ~~~
148 module my_module is
149     app_name "My App"
150     app_namespace "org.example.my_app"
151     app_version(1, 0, git_revision)
152 end
153 ~~~
154
155 ## Compiling and Packaging an Application
156
157 The Nit compiler detects the target platform from the importations and generates the appropriate application format and package.
158
159 Applications using only the portable services of _app.nit_ require some special care at compilation.
160 Such an application, let's say `calculator.nit`, does not depend on a specific platform and use the portable UI.
161 The target platform must be specifed to the compiler for it to produce the correct application package.
162 There is two main ways to achieve this goal:
163
164 * The the mixin option (`-m path`) loads an additionnal module before compiling.
165   It can be used to load platform specific implementations of the _app.nit_ portable UI.
166
167   ~~~
168   # GNU/Linux version, using GTK
169   nitc calculator.nit -m NIT_DIR/lib/linux/ui.nit
170
171   # Android version
172   nitc calculator.nit -m NIT_DIR/lib/android/ui/
173   ~~~
174
175 * A common alternative for larger projects is to use platform specific modules.
176   Continuing with the `calculator.nit` example, it can be accompagnied by the module `calculator_linux.nit`.
177   This module imports both `calculator` and `linux::ui`, and can also use other GNU/Linux specific code.
178
179   ~~~
180   module calculator_linux
181
182   import calculator
183   import linux::ui
184   ~~~