class ControlPanel(Group): CONFIG = { "listen_to_events": True, "panel_kwargs": { "width": FRAME_WIDTH / 4, "height": MED_SMALL_BUFF + FRAME_HEIGHT, "fill_color": GREY_C, "fill_opacity": 1.0, "stroke_width": 0.0 }, "opener_kwargs": { "width": FRAME_WIDTH / 8, "height": 0.5, "fill_color": GREY_C, "fill_opacity": 1.0 }, "opener_text_kwargs": { "text": "Control Panel", "size": 0.4 } } def __init__(self, *controls, **kwargs): digest_config(self, kwargs) self.panel = Rectangle(**self.panel_kwargs) self.panel.to_corner(UP + LEFT, buff=0) self.panel.shift(self.panel.get_height() * UP) self.panel_opener_rect = Rectangle(**self.opener_kwargs) self.panel_info_text = Text(**self.opener_text_kwargs) self.panel_info_text.move_to(self.panel_opener_rect) self.panel_opener = Group(self.panel_opener_rect, self.panel_info_text) self.panel_opener.next_to(self.panel, DOWN, aligned_edge=DOWN) self.controls = Group(*controls) self.controls.arrange(DOWN, center=False, aligned_edge=ORIGIN) self.controls.move_to(self.panel) super().__init__(self.panel, self.panel_opener, self.controls, **kwargs) self.move_panel_and_controls_to_panel_opener() self.fix_in_frame() def move_panel_and_controls_to_panel_opener(self): self.panel.next_to(self.panel_opener_rect, direction=UP, buff=0) controls_old_x = self.controls.get_x() self.controls.next_to(self.panel_opener_rect, direction=UP, buff=MED_SMALL_BUFF) self.controls.set_x(controls_old_x) def add_controls(self, *new_controls): self.controls.add(*new_controls) self.move_panel_and_controls_to_panel_opener() def remove_controls(self, *controls_to_remove): self.controls.remove(*controls_to_remove) self.move_panel_and_controls_to_panel_opener() def open_panel(self): panel_opener_x = self.panel_opener.get_x() self.panel_opener.to_corner(DOWN + LEFT, buff=0.0) self.panel_opener.set_x(panel_opener_x) self.move_panel_and_controls_to_panel_opener() return self def close_panel(self): panel_opener_x = self.panel_opener.get_x() self.panel_opener.to_corner(UP + LEFT, buff=0.0) self.panel_opener.set_x(panel_opener_x) self.move_panel_and_controls_to_panel_opener() return self def on_mouse_drag(self, point, d_point, buttons, modifiers): if self.panel_opener.is_point_touching(point): self.panel_opener.match_y(Dot(point)) self.move_panel_and_controls_to_panel_opener() return False def on_mouse_scroll(self, point, offset): if self.panel.is_point_touching(point): factor = 10 * offset[1] self.controls.set_y(self.controls.get_y() + factor) return False
class Textbox(ContolMobject): CONFIG = { "value_type": np.dtype(object), "box_kwargs": { "width": 2.0, "height": 1.0, "fill_color": WHITE, "fill_opacity": 1.0, }, "text_kwargs": { "color": BLUE }, "text_buff": MED_SMALL_BUFF, "isInitiallyActive": False, "active_color": BLUE, "deactive_color": RED, } def __init__(self, value="", **kwargs): digest_config(self, kwargs) self.isActive = self.isInitiallyActive self.box = Rectangle(**self.box_kwargs) self.text = Text(value, **self.text_kwargs) super().__init__(value, self.box, self.text, **kwargs) self.update_text(value) self.active_anim(self.isActive) def set_value_anim(self, value): self.update_text(value) def update_text(self, value): text = self.text self.remove(text) text.__init__(value, **self.text_kwargs) height = text.get_height() text.set_width(self.box.get_width() - 2 * self.text_buff) if text.get_height() > height: text.set_height(height) text.add_updater(lambda mob: mob.move_to(self.box)) text.fix_in_frame() self.add(text) def active_anim(self, isActive): if isActive: self.box.set_stroke(self.active_color) else: self.box.set_stroke(self.deactive_color) def on_mouse_press(self, point, button, mods): if self.box.is_point_touching(point): self.isActive = not self.isActive self.active_anim(self.isActive) return False def on_key_press(self, symbol, modifiers): char = chr(symbol) if self.isActive: old_value = self.get_value() new_value = old_value if char.isalnum(): if (modifiers & PygletWindowKeys.MOD_SHIFT) or ( modifiers & PygletWindowKeys.MOD_CAPSLOCK): new_value = old_value + char.upper() else: new_value = old_value + char.lower() elif symbol in [PygletWindowKeys.SPACE]: new_value = old_value + char elif symbol == PygletWindowKeys.TAB: new_value = old_value + '\t' elif symbol == PygletWindowKeys.BACKSPACE: new_value = old_value[:-1] or '' self.set_value(new_value) return False