def generate_GUI(menus): app_gui = TabbedPanel() app_gui.clear_tabs() app_gui.orientation = "vertical" app_gui.do_default_tab = False app_gui.tab_width = 150 for menu_key, sub_menu in menus.items(): main_menu = TabbedPanelHeader(text=menu_key) scroll_pane = ScrollView() scroll_pane.scroll_type = ['bars', 'content'] scroll_pane.bar_pos_y = 'left' scroll_pane.bar_width = 6 scroll_pane.do_scroll_y = True scroll_pane.do_scroll_x = False scroll_pane.scroll_y = 1 menu_grid = GridLayout(cols=1, spacing=2, size_hint_y=None) menu_grid.orientation = "vertical" menu_grid.padding = 10 menu_grid.row_default_height = 1 menu_height = 0 print(">>>" + menu_key) for sub_menu_key, items in sub_menu.items(): menu_grid.add_widget( Label(text=" " + sub_menu_key, size_hint=(None, None), font_size=14, halign="left", valign="middle")) print("\t" + sub_menu_key) for option in items: if "Name" in option: print("\t\t" + option["Name"]) btn = Button(text=option["Name"], size_hint=(0.1, None), background_color=(0.2, 1, 1, 0.8)) btn.bind(on_press=lambda x: webbrowser.open(option["URL"])) else: print("\t\t" + "<EMPTY>") btn = Button(text="<EMPTY>", size_hint=(0.1, None), background_color=(0.2, 1, 1, 0.8)) btn.bind(on_press=lambda x: webbrowser.open(option["URL"])) btn.width = 250 btn.height = 50 menu_grid.add_widget(btn) menu_height += 80 menu_height += 51 menu_grid.height = menu_height scroll_pane.add_widget(menu_grid) main_menu.content = scroll_pane main_menu.orientation = "vertical" # Adding headers to main layout app_gui.add_widget(main_menu) return app_gui
class GameManager(App): logging_pairs = [ ("Client", "Archipelago"), ] base_title: str = "Archipelago Client" last_autofillable_command: str def __init__(self, ctx: context_type): self.title = self.base_title self.ctx = ctx self.commandprocessor = ctx.command_processor(ctx) self.icon = r"data/icon.png" self.json_to_kivy_parser = KivyJSONtoTextParser(ctx) self.log_panels = {} # keep track of last used command to autofill on click self.last_autofillable_command = "hint" autofillable_commands = ("hint_location", "hint", "getitem") original_say = ctx.on_user_say def intercept_say(text): text = original_say(text) if text: for command in autofillable_commands: if text.startswith("!" + command): self.last_autofillable_command = command break return text ctx.on_user_say = intercept_say super(GameManager, self).__init__() def build(self): self.container = ContainerLayout() self.grid = MainLayout() self.grid.cols = 1 self.connect_layout = BoxLayout(orientation="horizontal", size_hint_y=None, height=30) # top part server_label = ServerLabel() self.connect_layout.add_widget(server_label) self.server_connect_bar = ConnectBarTextInput(text="archipelago.gg", size_hint_y=None, height=30, multiline=False, write_tab=False) self.server_connect_bar.bind( on_text_validate=self.connect_button_action) self.connect_layout.add_widget(self.server_connect_bar) self.server_connect_button = Button(text="Connect", size=(100, 30), size_hint_y=None, size_hint_x=None) self.server_connect_button.bind(on_press=self.connect_button_action) self.connect_layout.add_widget(self.server_connect_button) self.grid.add_widget(self.connect_layout) self.progressbar = ProgressBar(size_hint_y=None, height=3) self.grid.add_widget(self.progressbar) # middle part self.tabs = TabbedPanel(size_hint_y=1) self.tabs.default_tab_text = "All" self.log_panels["All"] = self.tabs.default_tab_content = UILog( *(logging.getLogger(logger_name) for logger_name, name in self.logging_pairs)) for logger_name, display_name in self.logging_pairs: bridge_logger = logging.getLogger(logger_name) panel = TabbedPanelItem(text=display_name) self.log_panels[display_name] = panel.content = UILog( bridge_logger) self.tabs.add_widget(panel) self.grid.add_widget(self.tabs) if len(self.logging_pairs) == 1: # Hide Tab selection if only one tab self.tabs.clear_tabs() self.tabs.do_default_tab = False self.tabs.current_tab.height = 0 self.tabs.tab_height = 0 # bottom part bottom_layout = BoxLayout(orientation="horizontal", size_hint_y=None, height=30) info_button = Button(height=30, text="Command:", size_hint_x=None) info_button.bind(on_release=self.command_button_action) bottom_layout.add_widget(info_button) self.textinput = TextInput(size_hint_y=None, height=30, multiline=False, write_tab=False) self.textinput.bind(on_text_validate=self.on_message) def text_focus(event): """Needs to be set via delay, as unfocusing happens after on_message""" self.textinput.focus = True self.textinput.text_focus = text_focus bottom_layout.add_widget(self.textinput) self.grid.add_widget(bottom_layout) self.commandprocessor("/help") Clock.schedule_interval(self.update_texts, 1 / 30) self.container.add_widget(self.grid) return self.container def update_texts(self, dt): if hasattr(self.tabs.content.children[0], 'fix_heights'): self.tabs.content.children[0].fix_heights( ) # TODO: remove this when Kivy fixes this upstream if self.ctx.server: self.title = self.base_title + " " + Utils.__version__ + \ f" | Connected to: {self.ctx.server_address} " \ f"{'.'.join(str(e) for e in self.ctx.server_version)}" self.server_connect_button.text = "Disconnect" self.progressbar.max = len(self.ctx.checked_locations) + len( self.ctx.missing_locations) self.progressbar.value = len(self.ctx.checked_locations) else: self.server_connect_button.text = "Connect" self.title = self.base_title + " " + Utils.__version__ self.progressbar.value = 0 def command_button_action(self, button): if self.ctx.server: logging.getLogger("Client").info( "/help for client commands and !help for server commands.") else: logging.getLogger("Client").info( "/help for client commands and once you are connected, " "!help for server commands.") def connect_button_action(self, button): if self.ctx.server: self.ctx.server_address = None asyncio.create_task(self.ctx.disconnect()) else: asyncio.create_task( self.ctx.connect( self.server_connect_bar.text.replace("/connect ", ""))) def on_stop(self): # "kill" input tasks for x in range(self.ctx.input_requests): self.ctx.input_queue.put_nowait("") self.ctx.input_requests = 0 self.ctx.exit_event.set() def on_message(self, textinput: TextInput): try: input_text = textinput.text.strip() textinput.text = "" if self.ctx.input_requests > 0: self.ctx.input_requests -= 1 self.ctx.input_queue.put_nowait(input_text) elif input_text: self.commandprocessor(input_text) Clock.schedule_once(textinput.text_focus) except Exception as e: logging.getLogger("Client").exception(e) def print_json(self, data: typing.List[JSONMessagePart]): text = self.json_to_kivy_parser(data) self.log_panels["Archipelago"].on_message_markup(text) self.log_panels["All"].on_message_markup(text) def enable_energy_link(self): if not hasattr(self, "energy_link_label"): self.energy_link_label = Label(text="Energy Link: Standby", size_hint_x=None, width=150) self.connect_layout.add_widget(self.energy_link_label) def set_new_energy_link_value(self): if hasattr(self, "energy_link_label"): self.energy_link_label.text = f"EL: {Utils.format_SI_prefix(self.ctx.current_energy_link_value)}J"