コード例 #1
0
ファイル: editors.py プロジェクト: Shiloli-r/Formation
class Anchor(Editor):
    def __init__(self, master, style_def):
        super().__init__(master, style_def)
        self.set_def(style_def)
        self.config(width=150, height=110)
        self.n = ToggleButton(self, text="N", width=20, height=20)
        self.n.grid(row=0, column=0, columnspan=3, sticky='ns')
        self.w = ToggleButton(self, text='W', width=20, height=20)
        self.w.grid(row=1, column=0, sticky='ew')
        self.pad = Frame(self,
                         width=60,
                         height=60,
                         **self.style.dark,
                         **self.style.dark_highlight_active)
        self.pad.grid(row=1, column=1, padx=1, pady=1)
        self.pad.grid_propagate(0)
        self.pad.grid_columnconfigure(0, minsize=60)
        self.pad.grid_rowconfigure(0, minsize=60)
        self.floating = Frame(self.pad,
                              **self.style.dark_on_hover,
                              width=20,
                              height=20)
        self.floating.grid(row=0, column=0, pady=1, padx=1)
        self.e = ToggleButton(self, text="E", width=20, height=20)
        self.e.grid(row=1, column=2, sticky='ew')
        self.s = ToggleButton(self, text='S', width=20, height=20)
        self.s.grid(row=2, column=0, columnspan=3, sticky='ns')
        self.anchors = {"n": self.n, "w": self.w, "e": self.e, "s": self.s}
        self._order = ("n", "s", "e", "w")
        self._selected = []
        self._exclusive_pairs = ({"n", "s"}, {"e", "w"})
        self._is_multiple = re.compile(r'(.*[ns].*[ns])|(.*[ew].*[ew])')
        for anchor in self.anchors:
            self.anchors[anchor].on_change(self._change, anchor)

    def _is_exclusive_of(self, anchor1, anchor2):
        return {anchor1, anchor2} in self._exclusive_pairs

    def _change(self, _, anchor):
        if not self.multiple:
            self._sanitize(anchor)
        self._adjust()
        if self._on_change:
            self._on_change(self.get())

    def _sanitize(self, anchor):
        ex_anchor = [i for i in self.get() if self._is_exclusive_of(i, anchor)]
        if len(ex_anchor):
            self.anchors.get(ex_anchor[0]).set(False)

    def _adjust(self):
        sticky = '' if self.get() == 'center' else self.get()
        self.floating.grid(row=0, column=0, pady=1, padx=1, sticky=sticky)

    def get(self):
        anchor = ''.join([i for i in self._order if self.anchors[i].get()])
        # No anchor means center but only when we are acting as an anchor editor
        # if self.multiple is True then we are a stickiness editor and an empty string will suffice
        if anchor == '':
            if not self.multiple:
                return 'center'
        return anchor

    def set(self, value):
        # bypass the special value 'center' before subjecting to validity check
        value = '' if value == 'center' else str(value)
        # Ignore invalid values
        if self._is_multiple.match(str(value)) and not self.multiple:
            return
        # Assume no anchor means center
        for anchor in self.anchors:
            self.anchors.get(anchor).set(anchor in value)

        self._adjust()

    def set_def(self, definition):
        # This flag determines whether multiple anchors are allowed at a time
        # set to True to obtain a sticky property editor
        self.multiple = definition.get("multiple", True)
        super().set_def(definition)
コード例 #2
0
ファイル: eventspane.py プロジェクト: ObaraEmmanuel/Formation
class EventPane(BaseFeature):
    name = "Event pane"
    icon = "blank"
    _defaults = {
        **BaseFeature._defaults,
        "side": "right",
    }
    NO_SELECTION_MSG = "You have not selected any widget selected"
    NO_EVENT_MSG = "You have not added any bindings"
    NO_MATCH_MSG = "No items match your search"

    def __init__(self, master, studio, **cnf):
        super().__init__(master, studio, **cnf)
        self.header = Frame(self, **self.style.surface)
        self.header.pack(side="top", fill="x")
        for i, title in enumerate(("Sequence", "Handler", "Add", " " * 3)):
            Label(
                self.header,
                **self.style.text_passive,
                text=title,
                anchor="w",
            ).grid(row=0, column=i, sticky='ew')

        # set the first two columns to expand evenly
        for column in range(2):
            self.header.grid_columnconfigure(column, weight=1, uniform=1)

        self.bindings = BindingsTable(self)
        self.bindings.on_value_change(self.modify_item)
        self.bindings.on_item_delete(self.delete_item)
        self.bindings.pack(fill="both", expand=True)

        self._add = Button(self._header,
                           **self.style.button,
                           width=25,
                           height=25,
                           image=get_icon_image("add", 15, 15))
        self._add.pack(side="right")
        self._add.tooltip("Add event binding")
        self._add.on_click(self.add_new)

        self._search_btn = Button(
            self._header,
            **self.style.button,
            image=get_icon_image("search", 15, 15),
            width=25,
            height=25,
        )
        self._search_btn.pack(side="right")
        self._search_btn.on_click(self.start_search)

        self._empty_frame = Label(self.bindings, **self.style.text_passive)
        self._show_empty(self.NO_SELECTION_MSG)

    def _show_empty(self, message):
        self._empty_frame.place(x=0, y=0, relwidth=1, relheight=1)
        self._empty_frame["text"] = message

    def _remove_empty(self):
        self._empty_frame.place_forget()

    def add_new(self, *_):
        if self.studio.selected is None:
            return
        self._remove_empty()
        new_binding = make_event("<>", "", False)
        widget = self.studio.selected
        if not hasattr(widget, "_event_map_"):
            setattr(widget, "_event_map_", {})
        widget._event_map_[new_binding.id] = new_binding
        self.bindings.add(new_binding)

    def delete_item(self, item):
        widget = self.studio.selected
        if widget is None:
            return
        widget._event_map_.pop(item.id)
        self.bindings.remove(item.id)

    def modify_item(self, value: EventBinding):
        widget = self.studio.selected
        widget._event_map_[value.id] = value

    def on_select(self, widget):
        if widget is None:
            self._show_empty(self.NO_SELECTION_MSG)
            return
        self._remove_empty()
        bindings = getattr(widget, "_event_map_", {})
        values = bindings.values()
        self.bindings.clear()
        self.bindings.add(*values)
        if not values:
            self._show_empty(self.NO_EVENT_MSG)

    def start_search(self, *_):
        if self.studio.selected:
            super().start_search()

    def on_search_query(self, query: str):
        showing = 0
        self._remove_empty()
        self.bindings.hide_all()
        for item in self.bindings.items:
            if query in item.value.sequence or query in item.value.handler:
                item.show()
                showing += 1
        if not showing:
            self._show_empty(self.NO_MATCH_MSG)

    def on_search_clear(self):
        self._remove_empty()
        self.bindings.hide_all()
        for item in self.bindings.items:
            item.show()
        super().on_search_clear()