Mercurial > libervia-desktop-kivy
annotate cagou/core/cagou_widget.py @ 357:4d3a0c4f2430
core: better back key (ESC) management:
- back key (which is mapped to esc keycode by SDL2 backend) is now handler with a platform
specific method when on root widget (i.e. a default widget is selected, or nothing is
selected). Default behaviour is to do nothing, while on Android the app is put to
background
- CagouWidget now has a default key_input method which go back to default widget.
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 18 Jan 2020 23:12:52 +0100 |
parents | 19422bbd9c8e |
children | 9ef01266e3fe |
rev | line source |
---|---|
10 | 1 #!/usr/bin/python |
2 # -*- coding: utf-8 -*- | |
3 | |
4 # Cagou: desktop/mobile frontend for Salut à Toi XMPP client | |
282 | 5 # Copyright (C) 2016-2019 Jérôme Poisson (goffi@goffi.org) |
10 | 6 |
7 # This program is free software: you can redistribute it and/or modify | |
8 # it under the terms of the GNU Affero General Public License as published by | |
9 # the Free Software Foundation, either version 3 of the License, or | |
10 # (at your option) any later version. | |
11 | |
12 # This program is distributed in the hope that it will be useful, | |
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 # GNU Affero General Public License for more details. | |
16 | |
17 # You should have received a copy of the GNU Affero General Public License | |
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | |
20 | |
21 from sat.core import log as logging | |
353
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
22 from sat.core import exceptions |
25
d09bd16dbbe2
code (cagou widget), selector: icons handling + use of new muchoslava icon set
Goffi <goffi@goffi.org>
parents:
20
diff
changeset
|
23 from kivy.uix.behaviors import ButtonBehavior |
10 | 24 from kivy.uix.boxlayout import BoxLayout |
25 from kivy.uix.dropdown import DropDown | |
353
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
26 from kivy.uix.screenmanager import Screen |
20
29b507826eed
header's input field is now accessible with self.header_input and call onHeaderInput() on text entered
Goffi <goffi@goffi.org>
parents:
16
diff
changeset
|
27 from kivy import properties |
16
ba14b596b90e
host can now be get as a global value:
Goffi <goffi@goffi.org>
parents:
15
diff
changeset
|
28 from cagou import G |
353
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
29 from .common import ActionIcon |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
30 |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
31 |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
32 log = logging.getLogger(__name__) |
10 | 33 |
34 | |
25
d09bd16dbbe2
code (cagou widget), selector: icons handling + use of new muchoslava icon set
Goffi <goffi@goffi.org>
parents:
20
diff
changeset
|
35 class HeaderWidgetChoice(ButtonBehavior, BoxLayout): |
164
60b2b2bad747
core (widget selector): adjusted selector size to content, and added some spacing
Goffi <goffi@goffi.org>
parents:
158
diff
changeset
|
36 |
25
d09bd16dbbe2
code (cagou widget), selector: icons handling + use of new muchoslava icon set
Goffi <goffi@goffi.org>
parents:
20
diff
changeset
|
37 def __init__(self, cagou_widget, plugin_info): |
d09bd16dbbe2
code (cagou widget), selector: icons handling + use of new muchoslava icon set
Goffi <goffi@goffi.org>
parents:
20
diff
changeset
|
38 self.plugin_info = plugin_info |
d09bd16dbbe2
code (cagou widget), selector: icons handling + use of new muchoslava icon set
Goffi <goffi@goffi.org>
parents:
20
diff
changeset
|
39 super(HeaderWidgetChoice, self).__init__() |
38
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
29
diff
changeset
|
40 self.bind(on_release=lambda btn: cagou_widget.switchWidget(plugin_info)) |
25
d09bd16dbbe2
code (cagou widget), selector: icons handling + use of new muchoslava icon set
Goffi <goffi@goffi.org>
parents:
20
diff
changeset
|
41 |
d09bd16dbbe2
code (cagou widget), selector: icons handling + use of new muchoslava icon set
Goffi <goffi@goffi.org>
parents:
20
diff
changeset
|
42 |
179
7177fe2d9725
common: new ActionIcon widget which display symbol or image icon according to what is specified in plugin_info
Goffi <goffi@goffi.org>
parents:
164
diff
changeset
|
43 class HeaderWidgetCurrent(ButtonBehavior, ActionIcon): |
14 | 44 pass |
45 | |
46 | |
10 | 47 class HeaderWidgetSelector(DropDown): |
14 | 48 |
49 def __init__(self, cagou_widget): | |
50 super(HeaderWidgetSelector, self).__init__() | |
353
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
51 plg_info_cls = cagou_widget.plugin_info_class or cagou_widget.__class__ |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
52 for plugin_info in G.host.getPluggedWidgets(except_cls=plg_info_cls): |
25
d09bd16dbbe2
code (cagou widget), selector: icons handling + use of new muchoslava icon set
Goffi <goffi@goffi.org>
parents:
20
diff
changeset
|
53 choice = HeaderWidgetChoice(cagou_widget, plugin_info) |
d09bd16dbbe2
code (cagou widget), selector: icons handling + use of new muchoslava icon set
Goffi <goffi@goffi.org>
parents:
20
diff
changeset
|
54 self.add_widget(choice) |
10 | 55 |
164
60b2b2bad747
core (widget selector): adjusted selector size to content, and added some spacing
Goffi <goffi@goffi.org>
parents:
158
diff
changeset
|
56 def add_widget(self, *args): |
60b2b2bad747
core (widget selector): adjusted selector size to content, and added some spacing
Goffi <goffi@goffi.org>
parents:
158
diff
changeset
|
57 widget = args[0] |
60b2b2bad747
core (widget selector): adjusted selector size to content, and added some spacing
Goffi <goffi@goffi.org>
parents:
158
diff
changeset
|
58 widget.bind(minimum_width=self.set_width) |
60b2b2bad747
core (widget selector): adjusted selector size to content, and added some spacing
Goffi <goffi@goffi.org>
parents:
158
diff
changeset
|
59 return super(HeaderWidgetSelector, self).add_widget(*args) |
60b2b2bad747
core (widget selector): adjusted selector size to content, and added some spacing
Goffi <goffi@goffi.org>
parents:
158
diff
changeset
|
60 |
60b2b2bad747
core (widget selector): adjusted selector size to content, and added some spacing
Goffi <goffi@goffi.org>
parents:
158
diff
changeset
|
61 def set_width(self, choice, minimum_width): |
60b2b2bad747
core (widget selector): adjusted selector size to content, and added some spacing
Goffi <goffi@goffi.org>
parents:
158
diff
changeset
|
62 self.width = max([c.minimum_width for c in self.container.children]) |
60b2b2bad747
core (widget selector): adjusted selector size to content, and added some spacing
Goffi <goffi@goffi.org>
parents:
158
diff
changeset
|
63 |
10 | 64 |
65 class CagouWidget(BoxLayout): | |
353
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
66 main_container = properties.ObjectProperty(None) |
20
29b507826eed
header's input field is now accessible with self.header_input and call onHeaderInput() on text entered
Goffi <goffi@goffi.org>
parents:
16
diff
changeset
|
67 header_input = properties.ObjectProperty(None) |
115
e0c41f209c28
CagouWidget: instances can now add their own extra widgets in header with headerInputAddExtra
Goffi <goffi@goffi.org>
parents:
108
diff
changeset
|
68 header_box = properties.ObjectProperty(None) |
353
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
69 # set to True if you want to be able to switch between visible widgets of this |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
70 # class using a carousel |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
71 collection_carousel = False |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
72 # set to True if you a global ScreenManager global to all widgets of this class. |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
73 # The screen manager is created in WHWrapper |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
74 global_screen_manager = False |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
75 # override this if a specific class (i.e. not self.__class__) must be used for |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
76 # plugin info. Useful when a CagouWidget is used with global_screen_manager. |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
77 plugin_info_class = None |
10 | 78 |
353
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
79 def __init__(self, **kwargs): |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
80 plg_info_cls = self.plugin_info_class or self.__class__ |
25
d09bd16dbbe2
code (cagou widget), selector: icons handling + use of new muchoslava icon set
Goffi <goffi@goffi.org>
parents:
20
diff
changeset
|
81 for p in G.host.getPluggedWidgets(): |
353
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
82 if p['main'] == plg_info_cls: |
25
d09bd16dbbe2
code (cagou widget), selector: icons handling + use of new muchoslava icon set
Goffi <goffi@goffi.org>
parents:
20
diff
changeset
|
83 self.plugin_info = p |
d09bd16dbbe2
code (cagou widget), selector: icons handling + use of new muchoslava icon set
Goffi <goffi@goffi.org>
parents:
20
diff
changeset
|
84 break |
353
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
85 super().__init__(**kwargs) |
14 | 86 self.selector = HeaderWidgetSelector(self) |
87 | |
353
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
88 @property |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
89 def screen_manager(self): |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
90 if ((not self.global_screen_manager |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
91 and not (self.plugin_info_class is not None |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
92 and self.plugin_info_class.global_screen_manager))): |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
93 raise exceptions.InternalError( |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
94 "screen_manager property can't be used if global_screen_manager is not " |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
95 "set") |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
96 screen = self.getAncestor(Screen) |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
97 if screen is None: |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
98 raise exceptions.NotFound("Can't find parent Screen") |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
99 if screen.manager is None: |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
100 raise exceptions.NotFound("Can't find parent ScreenManager") |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
101 return screen.manager |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
102 |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
103 @property |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
104 def whwrapper(self): |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
105 """Retrieve parent widget handler""" |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
106 return G.host.getParentWHWrapper(self) |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
107 |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
108 def screenManagerInit(self, screen_manager): |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
109 """Override this method to do init when ScreenManager is instantiated |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
110 |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
111 This is only called once even if collection_carousel is used. |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
112 """ |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
113 if not self.global_screen_manager: |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
114 raise exceptions.InternalError("screenManagerInit should not be called") |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
115 |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
116 def getAncestor(self, cls): |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
117 """Helper method to use host.getAncestorWidget with self""" |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
118 return G.host.getAncestorWidget(self, cls) |
19422bbd9c8e
core (widgets handler): refactoring:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
119 |
14 | 120 def switchWidget(self, plugin_info): |
121 self.selector.dismiss() | |
122 factory = plugin_info["factory"] | |
20
29b507826eed
header's input field is now accessible with self.header_input and call onHeaderInput() on text entered
Goffi <goffi@goffi.org>
parents:
16
diff
changeset
|
123 new_widget = factory(plugin_info, None, iter(G.host.profiles)) |
16
ba14b596b90e
host can now be get as a global value:
Goffi <goffi@goffi.org>
parents:
15
diff
changeset
|
124 G.host.switchWidget(self, new_widget) |
20
29b507826eed
header's input field is now accessible with self.header_input and call onHeaderInput() on text entered
Goffi <goffi@goffi.org>
parents:
16
diff
changeset
|
125 |
357
4d3a0c4f2430
core: better back key (ESC) management:
Goffi <goffi@goffi.org>
parents:
353
diff
changeset
|
126 def key_input(self, window, key, scancode, codepoint, modifier): |
4d3a0c4f2430
core: better back key (ESC) management:
Goffi <goffi@goffi.org>
parents:
353
diff
changeset
|
127 if key == 27: |
4d3a0c4f2430
core: better back key (ESC) management:
Goffi <goffi@goffi.org>
parents:
353
diff
changeset
|
128 # we go back to root screen |
4d3a0c4f2430
core: better back key (ESC) management:
Goffi <goffi@goffi.org>
parents:
353
diff
changeset
|
129 G.host.switchWidget(self) |
4d3a0c4f2430
core: better back key (ESC) management:
Goffi <goffi@goffi.org>
parents:
353
diff
changeset
|
130 return True |
4d3a0c4f2430
core: better back key (ESC) management:
Goffi <goffi@goffi.org>
parents:
353
diff
changeset
|
131 |
20
29b507826eed
header's input field is now accessible with self.header_input and call onHeaderInput() on text entered
Goffi <goffi@goffi.org>
parents:
16
diff
changeset
|
132 def onHeaderInput(self): |
312 | 133 log.info("header input text entered") |
51 | 134 |
108
953ddf817b8a
cagou widget: added onHeaderInputComplete method which is called when text is changed, and should be used for completion
Goffi <goffi@goffi.org>
parents:
51
diff
changeset
|
135 def onHeaderInputComplete(self, wid, text): |
953ddf817b8a
cagou widget: added onHeaderInputComplete method which is called when text is changed, and should be used for completion
Goffi <goffi@goffi.org>
parents:
51
diff
changeset
|
136 return |
953ddf817b8a
cagou widget: added onHeaderInputComplete method which is called when text is changed, and should be used for completion
Goffi <goffi@goffi.org>
parents:
51
diff
changeset
|
137 |
51 | 138 def on_touch_down(self, touch): |
139 if self.collide_point(*touch.pos): | |
140 G.host.selected_widget = self | |
158
976f22cb3ecc
core (cagou widget): return parent value in on_touch_down
Goffi <goffi@goffi.org>
parents:
126
diff
changeset
|
141 return super(CagouWidget, self).on_touch_down(touch) |
115
e0c41f209c28
CagouWidget: instances can now add their own extra widgets in header with headerInputAddExtra
Goffi <goffi@goffi.org>
parents:
108
diff
changeset
|
142 |
e0c41f209c28
CagouWidget: instances can now add their own extra widgets in header with headerInputAddExtra
Goffi <goffi@goffi.org>
parents:
108
diff
changeset
|
143 def headerInputAddExtra(self, widget): |
e0c41f209c28
CagouWidget: instances can now add their own extra widgets in header with headerInputAddExtra
Goffi <goffi@goffi.org>
parents:
108
diff
changeset
|
144 """add a widget on the right of header input""" |
e0c41f209c28
CagouWidget: instances can now add their own extra widgets in header with headerInputAddExtra
Goffi <goffi@goffi.org>
parents:
108
diff
changeset
|
145 self.header_box.add_widget(widget) |
264
3e11b5d923e2
core: call new methods onVisible and onNotVisible when a widget is displayed or hidden + fixed a deletion bug on _removeVisibleWidget
Goffi <goffi@goffi.org>
parents:
222
diff
changeset
|
146 |
3e11b5d923e2
core: call new methods onVisible and onNotVisible when a widget is displayed or hidden + fixed a deletion bug on _removeVisibleWidget
Goffi <goffi@goffi.org>
parents:
222
diff
changeset
|
147 def onVisible(self): |
3e11b5d923e2
core: call new methods onVisible and onNotVisible when a widget is displayed or hidden + fixed a deletion bug on _removeVisibleWidget
Goffi <goffi@goffi.org>
parents:
222
diff
changeset
|
148 pass |
3e11b5d923e2
core: call new methods onVisible and onNotVisible when a widget is displayed or hidden + fixed a deletion bug on _removeVisibleWidget
Goffi <goffi@goffi.org>
parents:
222
diff
changeset
|
149 # log.debug(u"{self} is visible".format(self=self)) |
3e11b5d923e2
core: call new methods onVisible and onNotVisible when a widget is displayed or hidden + fixed a deletion bug on _removeVisibleWidget
Goffi <goffi@goffi.org>
parents:
222
diff
changeset
|
150 |
3e11b5d923e2
core: call new methods onVisible and onNotVisible when a widget is displayed or hidden + fixed a deletion bug on _removeVisibleWidget
Goffi <goffi@goffi.org>
parents:
222
diff
changeset
|
151 def onNotVisible(self): |
3e11b5d923e2
core: call new methods onVisible and onNotVisible when a widget is displayed or hidden + fixed a deletion bug on _removeVisibleWidget
Goffi <goffi@goffi.org>
parents:
222
diff
changeset
|
152 pass |
3e11b5d923e2
core: call new methods onVisible and onNotVisible when a widget is displayed or hidden + fixed a deletion bug on _removeVisibleWidget
Goffi <goffi@goffi.org>
parents:
222
diff
changeset
|
153 # log.debug(u"{self} is not visible anymore".format(self=self)) |