lib/linux: implement multiple windows
[nit.git] / lib / linux / ui.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Implementation of the app.nit UI module for GNU/Linux
16 module ui
17
18 import app::ui
19 import gtk::v3_10
20
21 import data_store
22
23 redef class App
24 redef fun setup do gtk_init
25
26 # Single GTK window of this application
27 var native_window: GtkWindow is lazy do
28 var win = new GtkWindow(new GtkWindowType.toplevel)
29 win.connect_destroy_signal_to_quit
30 win.titlebar = native_header_bar
31 win.add native_stack
32 return win
33 end
34
35 # GTK 3 header bar
36 var native_header_bar: GtkHeaderBar is lazy do
37 var bar = new GtkHeaderBar
38 bar.title = "app.nit" # TODO offer a portable API to name windows
39 bar.show_close_button = true
40
41 # TODO add back button
42
43 return bar
44 end
45
46 # Root `GtkStack` used to simulate the many app.nit windows
47 var native_stack: GtkStack is lazy do
48 var stack = new GtkStack
49 stack.homogeneous = false
50 return stack
51 end
52
53 # On GNU/Linux, we go through all the callbacks once,
54 # there is no complex life-cycle.
55 redef fun run
56 do
57 app.on_create
58 app.on_restore_state
59 app.on_start
60 app.on_resume
61
62 native_window.show_all
63 gtk_main
64
65 app.on_pause
66 app.on_stop
67 app.on_save_state
68 app.on_destroy
69 end
70
71 # Spacing between GTK controls, default at 2
72 var control_spacing = 2 is writable
73
74 redef fun window=(window)
75 do
76 var root_view = window.view
77 assert root_view != null
78 native_stack.add root_view.native
79 native_stack.visible_child = root_view.native
80 super
81 end
82 end
83
84 redef class Control
85 super GtkCallable
86 super Finalizable
87
88 # The GTK element used to implement `self`
89 fun native: NATIVE is abstract
90
91 # Type of `native`
92 type NATIVE: GtkWidget
93
94 redef fun finalize
95 do
96 var native = native
97 if not native.address_is_null then native.destroy
98 end
99 end
100
101 redef class CompositeControl
102 redef type NATIVE: GtkContainer
103
104 redef fun add(item)
105 do
106 super
107 native.add item.native
108 end
109 end
110
111 # On GNU/Linux, a window is implemented by placing the `view` in a `GtkStack` in the single GTK window
112 redef class Window
113
114 # Root view of this window
115 var view: nullable View = null
116
117 redef fun add(view)
118 do
119 if view isa View then
120 self.view = view
121 end
122
123 # TODO skip local CompositeControl::add but call intro
124 #super
125 end
126 end
127
128 redef class View
129 init do native.show
130
131 redef fun enabled do return native.sensitive
132 redef fun enabled=(enabled) do native.sensitive = enabled or else true
133 end
134
135 redef class Layout
136 redef type NATIVE: GtkBox
137 redef fun remove(view)
138 do
139 super
140 native.remove view.native
141 end
142 end
143
144 redef class HorizontalLayout
145 redef var native = new GtkBox(new GtkOrientation.horizontal, app.control_spacing)
146
147 redef fun add(item)
148 do
149 super
150 native.homogeneous = true
151 native.set_child_packing(item.native, true, true, 0, new GtkPackType.start)
152 end
153 end
154
155 redef class VerticalLayout
156 redef var native = new GtkBox(new GtkOrientation.vertical, app.control_spacing)
157
158 redef fun add(item)
159 do
160 super
161
162 # FIXME abstract the use either homogeneous or weight to balance views size in a layout
163 native.homogeneous = true
164 native.set_child_packing(item.native, true, true, 0, new GtkPackType.start)
165 end
166 end
167
168 redef class ListLayout
169 redef type NATIVE: GtkListBox
170 redef var native = new GtkListBox
171
172 init do native.selection_mode = new GtkSelectionMode.none
173 end
174
175 redef class Button
176 redef type NATIVE: GtkButton
177 redef var native = new GtkButton
178
179 redef fun text do return native.text
180 redef fun text=(value) do native.text = (value or else "").to_s
181
182 redef fun signal(sender, data) do notify_observers new ButtonPressEvent(self)
183
184 init do native.signal_connect("clicked", self, null)
185 end
186
187 redef class Label
188 redef type NATIVE: GtkLabel
189 redef var native = new GtkLabel("")
190
191 redef fun text do return native.text
192 redef fun text=(value) do native.text = (value or else "").to_s
193 end
194
195 redef class TextInput
196 redef type NATIVE: GtkEntry
197 redef var native = new GtkEntry
198
199 redef fun text do return native.text
200 redef fun text=(value) do
201 if value == null then value = ""
202 native.text = value.to_s
203 end
204
205 redef fun is_password=(value)
206 do
207 native.visibility = value != true
208 super
209 end
210 end