Mercurial > libervia-desktop-kivy
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))