fix dangling pointer issues in ext2dr
[lunaix-os.git] / lunaix-os / scripts / build-tools / integration / libmenu.py
1 import curses
2 import integration.libtui as tui
3 from integration.libtui import ColorScope, TuiColor, Alignment, EventType
4
5 def create_buttons(main_ctx, btn_defs, sizes = "*,*"):
6     size_defs = ",".join(['*'] * len(btn_defs))
7
8     layout = tui.FlexLinearLayout(main_ctx, "buttons", size_defs)
9     layout.orientation(tui.FlexLinearLayout.LANDSCAPE)
10     layout.set_size(*(sizes.split(',')[:2]))
11     layout.set_padding(1, 1, 1, 1)
12     layout.set_alignment(Alignment.CENTER | Alignment.BOT)
13
14     for i, btn_def in enumerate(btn_defs):
15         but1 = tui.TuiButton(main_ctx, "b1")
16         but1.set_text(btn_def["text"])
17         but1.set_click_callback(btn_def["onclick"])
18         but1.set_alignment(Alignment.CENTER)
19         
20         layout.set_cell(i, but1)
21
22     return layout
23
24 def create_title(ctx, title):
25     _t = tui.TuiLabel(ctx, "label")
26     _t.set_text(title)
27     _t.set_local_pos(1, 0)
28     _t.set_alignment(Alignment.TOP | Alignment.CENTER)
29     _t.hightlight(True)
30     _t.pad_around(True)
31     return _t
32
33 class ListView(tui.TuiObject):
34     def __init__(self, context, id):
35         super().__init__(context, id)
36
37         self.__create_layout()
38
39         self.__sel_changed = None
40         self.__sel = None
41
42     def __create_layout(self):
43         hint_moveup = tui.TuiLabel(self._context, "movup")
44         hint_moveup.override_color(ColorScope.HINT)
45         hint_moveup.set_text("^^^ - MORE")
46         hint_moveup.set_visbility(False)
47         hint_moveup.set_alignment(Alignment.TOP)
48
49         hint_movedown = tui.TuiLabel(self._context, "movdown")
50         hint_movedown.override_color(ColorScope.HINT)
51         hint_movedown.set_text("vvv - MORE")
52         hint_movedown.set_visbility(False)
53         hint_movedown.set_alignment(Alignment.BOT)
54
55         list_ = tui.SimpleList(self._context, "list")
56         list_.set_size("*", "*")
57         list_.set_alignment(Alignment.CENTER | Alignment.TOP)
58
59         list_.set_onselected_cb(self._on_selected)
60         list_.set_onselection_change_cb(self._on_sel_changed)
61
62         scroll = tui.TuiScrollable(self._context, "scroll")
63         scroll.set_size("*", "*")
64         scroll.set_alignment(Alignment.CENTER)
65         scroll.set_content(list_)
66
67         layout = tui.FlexLinearLayout(
68                     self._context, f"main_layout", "2,*,2")
69         layout.set_size("*", "*")
70         layout.set_alignment(Alignment.CENTER)
71         layout.orientation(tui.FlexLinearLayout.PORTRAIT)
72         layout.set_parent(self)
73
74         layout.set_cell(0, hint_moveup)
75         layout.set_cell(1, scroll)
76         layout.set_cell(2, hint_movedown)
77
78         self.__hint_up   = hint_moveup
79         self.__hint_down = hint_movedown
80         self.__list      = list_
81         self.__scroll    = scroll
82         self.__layout    = layout
83
84     def add_item(self, item):
85         self.__list.add_item(item)
86
87     def clear(self):
88         self.__list.clear()
89
90     def on_draw(self):
91         super().on_draw()
92         
93         more_above = not self.__scroll.reached_top()
94         more_below = not self.__scroll.reached_last()
95         self.__hint_up.set_visbility(more_above)
96         self.__hint_down.set_visbility(more_below)
97
98         self.__layout.on_draw()
99
100     def on_layout(self):
101         super().on_layout()
102         self.__layout.on_layout()
103
104     def _on_sel_changed(self, listv, prev, new):
105         h = self.__scroll._size.y()
106         self.__scroll.set_scrollY((new + 1) // h * h)
107
108         if self.__sel_changed:
109             self.__sel_changed(listv, prev, new)
110
111     def _on_selected(self, listv, index, item):
112         if self.__sel:
113             self.__sel(listv, index, item)
114     
115     def set_onselected_cb(self, cb):
116         self.__sel = cb
117
118     def set_onselect_changed_cb(self, cb):
119         self.__sel_changed = cb
120
121 class Dialogue(tui.TuiContext):
122     Pending = 0
123     Yes = 1
124     No = 2
125     Abort = 3
126     def __init__(self, session, title = "", content = "", input=False,
127                  ok_btn = "OK", no_btn = "No", abort_btn = None):
128         super().__init__(session)
129
130         self.__btns = [
131             { "text": ok_btn, "onclick": lambda x: self._ok_onclick() }
132         ]
133
134         if no_btn:
135             self.__btns.append({ 
136                 "text": no_btn, 
137                 "onclick": lambda x: self._no_onclick() 
138             })
139         if abort_btn:
140             self.__btns.append({ 
141                 "text": abort_btn, 
142                 "onclick": lambda x: self._abort_onclick() 
143             })
144
145         self.__title_txt = title
146         self.__status = Dialogue.Pending
147         self.__content = content
148         self.__input_dialog = input
149         self._textbox = None
150
151         self.set_size("70", "0.5*")
152         self.set_alignment(Alignment.CENTER)
153
154     def set_content(self, content):
155         self.__content = content
156
157     def set_input_dialogue(self, yes):
158         self.__input_dialog = yes
159
160     def prepare(self):
161         self.__create_layout(self.__title_txt)
162
163     def _handle_key_event(self, key):
164         if key == 27:
165             self.__close()
166             return
167         super()._handle_key_event(key)
168         
169     
170     def _ok_onclick(self):
171         self.__status = Dialogue.Yes
172         self.__close()
173
174     def _no_onclick(self):
175         self.__status = Dialogue.No
176         self.__close()
177
178     def _abort_onclick(self):
179         self.__status = Dialogue.Abort
180         self.__close()
181
182     def __create_layout(self, title):
183         panel  = tui.TuiPanel(self, "panel")
184         layout = tui.FlexLinearLayout(self, "layout", "*,3")
185         btn_grp = create_buttons(self, self.__btns)
186         t = create_title(self, title)
187         content = self.__create_content()
188
189         self.__title = t
190         self.__layout = layout
191         self.__panel = panel
192
193         panel._dyn_size.set(self._dyn_size)
194         panel._local_pos.set(self._local_pos)
195         panel.set_alignment(self._align)
196         panel.drop_shadow(1, 2)
197         panel.border(True)
198
199         layout.orientation(tui.FlexLinearLayout.PORTRAIT)
200         layout.set_size("*", "*")
201         layout.set_padding(4, 1, 1, 1)
202
203         t.set_alignment(Alignment.CENTER | Alignment.TOP)
204
205         layout.set_cell(0, content)
206         layout.set_cell(1, btn_grp)
207
208         panel.add(t)
209         panel.add(layout)
210
211         self.set_root(panel)
212
213     def __create_content(self):
214         text = None
215         if isinstance(self.__content, str):
216             text = tui.TuiTextBlock(self, "tb")
217             text.set_size("0.6*", "0.5*")
218             text.set_alignment(Alignment.CENTER)
219             text.set_text(self.__content)
220         elif self.__content is not None:
221             return self.__content
222         
223         if not self.__input_dialog:
224             self.set_size(h = "20")
225             return text
226         
227         tb = tui.TuiTextBox(self, "input")
228         tb.set_size("0.5*", "3")
229         tb.set_alignment(Alignment.CENTER)
230         
231         if text:
232             layout = tui.FlexLinearLayout(self, "layout", "*,5")
233             layout.orientation(tui.FlexLinearLayout.PORTRAIT)
234             layout.set_size("*", "*")
235             layout.set_cell(0, text)
236             layout.set_cell(1, tb)
237         else:
238             layout = tb
239             self.set_size(h = "10")
240         
241         self.set_curser_mode(1)
242
243         self._textbox = tb
244
245         return layout
246         
247     def __close(self):
248         self.session().pop_context()
249
250     def status(self):
251         return self.__status
252     
253     def show(self, title=None):
254         if title:
255             self.__title.set_text(title)
256         self.session().push_context(self)
257
258
259 def show_dialog(session, title, text):
260     dia = Dialogue(session, title=title, content=text, no_btn=None)
261     dia.show()