def collapse(self, *_): if not self._collapsed: self.body.pack_forget() self._collapse_btn.config(text=get_icon("triangle_down")) self.pack_propagate(0) self.config(height=20) self._collapsed = True
def __init__(self, master=None, **config): super().__init__(master, **config) self._menu = config.get("menu") self.name_pad.config(text=config.get("label")) self.icon_pad.config(text=get_icon(self._type_def.get(config.get("type"))[0])) self.editable = True self.type = config.get("type") if config.get("type") == tk.CASCADE: self.is_terminal = False menu = config.get("sub_menu") if config.get("sub_menu") else tk.Menu(self.tree._menu, tearoff=False) self._sub_menu = menu self._menu.entryconfigure(config.get("index", tk.END), menu=self._sub_menu) else: self.is_terminal = True self._sub_menu = self._menu
def __init__(self, master, **cnf): super().__init__(master, **cnf) self.config(**self.style.dark) self._label_frame = Frame(self, **self.style.bright, height=20) self._label_frame.pack(side="top", fill="x", padx=2) self._label_frame.pack_propagate(0) self._label = Label(self._label_frame, **self.style.bright, **self.style.text_bright) self._label.pack(side="left") self._collapse_btn = Button(self._label_frame, width=20, **self.style.bright, **self.style.text_bright) self._collapse_btn.config(text=get_icon("triangle_up")) self._collapse_btn.pack(side="right", fill="y") self._collapse_btn.on_click(self.toggle) self.body = Frame(self, **self.style.dark) self.body.pack(side="top", fill="both", pady=2) self.__ref = Frame(self.body, height=0, width=0, **self.style.dark) self.__ref.pack(side="top") self._collapsed = False
def expand(self, *_): if self._collapsed: self.body.pack(side="top", fill="both") self.pack_propagate(1) self._collapse_btn.config(text=get_icon("triangle_up")) self._collapsed = False
class PseudoWidget: display_name = 'Widget' group = Groups.widget icon = get_icon("play") impl = None # special handlers (intercepts) for attributes that need additional processing # to interface with the studio easily _intercepts = { "image": _ImageIntercept, "selectimage": _ImageIntercept, "tristateimage": _ImageIntercept, "id": _IdIntercept, "textvariable": _VariableIntercept, "variable": _VariableIntercept, "listvariable": _VariableIntercept } def setup_widget(self): self.level = 0 self.layout = None self._properties = get_properties(self) self.set_name(self.id) self.node = None self.__on_context = None self.last_menu_position = (0, 0) self.bind("<Button-3>", self.__handle_context_menu, add='+') def set_name(self, name): pass def get_image_path(self): if hasattr(self, "image_path"): return self.image_path return self['image'] def set_tree_reference(self, node: MalleableTree.Node): self.node = node self.node.is_terminal = self._is_terminal def deselect_(self): if self.node is None: return self.node.deselect() def select_(self): if self.node is None: return self.node.deselect() @property def identity(self): return { "class": { "name": "class", "display_name": "class", "type": "text", "readonly": True, "value": f"{self.impl.__module__}.{self.impl.__name__}" }, "id": { "name": "id", "display_name": "widget id", "type": "text", "readonly": False, "value": self.id }, } def get_prop(self, prop): intercept = self._intercepts.get(prop) if intercept: return intercept.get(self, prop) return self[prop] def configure(self, options=None, **kw): for opt in list(kw.keys()): intercept = self._intercepts.get(opt) if intercept: intercept.set(self, kw[opt], opt) kw.pop(opt) return super().config(**kw) @property def properties(self): for key in self._properties: self._properties[key]["value"] = self.get_prop(key) return self._properties def create_menu(self): """ Add actions to the widget drop down. Override this method and use hoverset menu format to add items to the menu :return: """ return () def winfo_parent(self): return str(self.layout) def on_context_menu(self, callback, *args, **kwargs): self.__on_context = lambda e: callback(e, *args, **kwargs) def __handle_context_menu(self, event): self.last_menu_position = event.x_root, event.y_root if self.__on_context: self.__on_context(event) def copy_config_to(self, widget): widget.configure(**self.get_altered_options()) def get_altered_options(self): # second last item denotes the default value try: defaults = self.configure() defaults = {x: defaults[x][-2] for x in defaults} except TypeError: logging.error("options failed for" + str(self.id)) return {} options = self.properties # Get options whose values are different from their default values return { opt: self.get_prop(opt) for opt in options if str(defaults.get(opt)) != str(self.get_prop(opt)) }