diff libervia/desktop_kivy/core/cagou_widget.py @ 493:b3cedbee561d

refactoring: rename `cagou` to `libervia.desktop_kivy` + update imports and names following backend changes
author Goffi <goffi@goffi.org>
date Fri, 02 Jun 2023 18:26:16 +0200
parents cagou/core/cagou_widget.py@203755bbe0fe
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libervia/desktop_kivy/core/cagou_widget.py	Fri Jun 02 18:26:16 2023 +0200
@@ -0,0 +1,199 @@
+#!/usr/bin/env python3
+
+
+#Libervia Desktop-Kivy
+# Copyright (C) 2016-2021 Jérôme Poisson (goffi@goffi.org)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+from functools import total_ordering
+from libervia.backend.core import log as logging
+from libervia.backend.core import exceptions
+from kivy.uix.behaviors import ButtonBehavior
+from kivy.uix.boxlayout import BoxLayout
+from kivy.uix.dropdown import DropDown
+from kivy.uix.screenmanager import Screen
+from kivy.uix.textinput import TextInput
+from kivy import properties
+from libervia.desktop_kivy import G
+from .common import ActionIcon
+from . import menu
+
+
+log = logging.getLogger(__name__)
+
+
+class HeaderChoice(ButtonBehavior, BoxLayout):
+    pass
+
+
+class HeaderChoiceWidget(HeaderChoice):
+    cagou_widget = properties.ObjectProperty()
+    plugin_info = properties.ObjectProperty()
+
+    def __init__(self, **kwargs):
+        super().__init__(**kwargs)
+        self.bind(on_release=lambda btn: self.cagou_widget.switch_widget(
+            self.plugin_info))
+
+
+class HeaderChoiceExtraMenu(HeaderChoice):
+    pass
+
+
+class HeaderWidgetCurrent(ButtonBehavior, ActionIcon):
+    pass
+
+
+class HeaderWidgetSelector(DropDown):
+
+    def __init__(self, cagou_widget):
+        super(HeaderWidgetSelector, self).__init__()
+        plg_info_cls = cagou_widget.plugin_info_class or cagou_widget.__class__
+        for plugin_info in G.host.get_plugged_widgets(except_cls=plg_info_cls):
+            choice = HeaderChoiceWidget(
+                cagou_widget=cagou_widget,
+                plugin_info=plugin_info,
+            )
+            self.add_widget(choice)
+        main_menu = HeaderChoiceExtraMenu(on_press=self.on_extra_menu)
+        self.add_widget(main_menu)
+
+    def add_widget(self, *args):
+        widget = args[0]
+        widget.bind(minimum_width=self.set_width)
+        return super(HeaderWidgetSelector, self).add_widget(*args)
+
+    def set_width(self, choice, minimum_width):
+        self.width = max([c.minimum_width for c in self.container.children])
+
+    def on_extra_menu(self, *args):
+        self.dismiss()
+        menu.ExtraSideMenu().show()
+
+
+@total_ordering
+class LiberviaDesktopKivyWidget(BoxLayout):
+    main_container = properties.ObjectProperty(None)
+    header_input = properties.ObjectProperty(None)
+    header_box = properties.ObjectProperty(None)
+    use_header_input = False
+    # set to True if you want to be able to switch between visible widgets of this
+    # class using a carousel
+    collection_carousel = False
+    # set to True if you a global ScreenManager global to all widgets of this class.
+    # The screen manager is created in WHWrapper
+    global_screen_manager = False
+    # override this if a specific class (i.e. not self.__class__) must be used for
+    # plugin info. Useful when a LiberviaDesktopKivyWidget is used with global_screen_manager.
+    plugin_info_class = None
+
+    def __init__(self, **kwargs):
+        plg_info_cls = self.plugin_info_class or self.__class__
+        for p in G.host.get_plugged_widgets():
+            if p['main'] == plg_info_cls:
+                self.plugin_info = p
+                break
+        super().__init__(**kwargs)
+        self.selector = HeaderWidgetSelector(self)
+        if self.use_header_input:
+            self.header_input = TextInput(
+                background_normal=G.host.app.expand(
+                    '{media}/misc/borders/border_hollow_light.png'),
+                multiline=False,
+            )
+            self.header_input.bind(
+                on_text_validate=lambda *args: self.on_header_wid_input(),
+                text=self.on_header_wid_input_complete,
+            )
+            self.header_box.add_widget(self.header_input)
+
+    def __lt__(self, other):
+        # XXX: sorting is notably used when collection_carousel is set
+        try:
+            target = str(self.target)
+        except AttributeError:
+            target = str(list(self.targets)[0])
+            other_target = str(list(other.targets)[0])
+        else:
+            other_target = str(other.target)
+        return target < other_target
+
+    @property
+    def screen_manager(self):
+        if ((not self.global_screen_manager
+             and not (self.plugin_info_class is not None
+                      and self.plugin_info_class.global_screen_manager))):
+            raise exceptions.InternalError(
+                "screen_manager property can't be used if global_screen_manager is not "
+                "set")
+        screen = self.get_ancestor(Screen)
+        if screen is None:
+            raise exceptions.NotFound("Can't find parent Screen")
+        if screen.manager is None:
+            raise exceptions.NotFound("Can't find parent ScreenManager")
+        return screen.manager
+
+    @property
+    def whwrapper(self):
+        """Retrieve parent widget handler"""
+        return G.host.get_parent_wh_wrapper(self)
+
+    def screen_manager_init(self, screen_manager):
+        """Override this method to do init when ScreenManager is instantiated
+
+        This is only called once even if collection_carousel is used.
+        """
+        if not self.global_screen_manager:
+            raise exceptions.InternalError("screen_manager_init should not be called")
+
+    def get_ancestor(self, cls):
+        """Helper method to use host.get_ancestor_widget with self"""
+        return G.host.get_ancestor_widget(self, cls)
+
+    def switch_widget(self, plugin_info):
+        self.selector.dismiss()
+        factory = plugin_info["factory"]
+        new_widget = factory(plugin_info, None, iter(G.host.profiles))
+        G.host.switch_widget(self, new_widget)
+
+    def key_input(self, window, key, scancode, codepoint, modifier):
+        if key == 27:
+            # we go back to root screen
+            G.host.switch_widget(self)
+            return True
+
+    def on_header_wid_input(self):
+        log.info("header input text entered")
+
+    def on_header_wid_input_complete(self, wid, text):
+        return
+
+    def on_touch_down(self, touch):
+        if self.collide_point(*touch.pos):
+            G.host.selected_widget = self
+        return super(LiberviaDesktopKivyWidget, self).on_touch_down(touch)
+
+    def header_input_add_extra(self, widget):
+        """add a widget on the right of header input"""
+        self.header_box.add_widget(widget)
+
+    def on_visible(self):
+        pass
+        # log.debug(u"{self} is visible".format(self=self))
+
+    def on_not_visible(self):
+        pass
+        # log.debug(u"{self} is not visible anymore".format(self=self))