def _detail_for(self, variable): self._detail_pane.clear_children() Label(self._detail_pane.body, **self.style.dark_text_passive, text="Type", anchor="w").pack(fill="x", side="top") Label(self._detail_pane.body, **self.style.dark_text, text=variable.var_type_name, anchor="w").pack(fill="x", side="top") Label(self._detail_pane.body, **self.style.dark_text_passive, text="Name", anchor="w").pack(fill="x", side="top") name = editors.get_editor(self._detail_pane.body, self._definitions["name"]) name.pack(side="top", fill="x") name.set(variable.name) name.on_change(variable.set_name) Label(self._detail_pane.body, **self.style.dark_text_passive, text="Value", anchor="w").pack(fill="x", side="top") value = editors.get_editor(self._detail_pane.body, variable.definition) value.set(variable.value) value.pack(side="top", fill="x") value.on_change(variable.set)
def __init__(self, master, studio=None, **cnf): super().__init__(master, studio, **cnf) self._toggle_btn = Button(self._header, image=get_icon_image("chevron_down", 15, 15), **self.style.button, width=25, height=25) self._toggle_btn.pack(side="right") self._toggle_btn.on_click(self._toggle) 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.body = Frame(self, **self.style.surface) self.body.pack(side="top", fill="both", expand=True) self._empty_label = Label(self.body, **self.style.text_passive) self._selected = None self._expanded = False self._tree = None
def render(self): if not self.value: Label(self, **self.style.text, width=2).pack(side="left") Label(self, **self.style.text, text="select").pack(side="left") else: Label(self, **self.style.text, bitmap=self.value).pack(side="left") Label(self, **self.style.text, text=self.value).pack(side="left")
def __init__(self, master): super().__init__(master) self.config(**self.style.surface) self._progress = ProgressBar(self) self._progress.pack(side="top", fill="x", padx=20, pady=20) self._progress_text = Label(self, **self.style.text_small, anchor="w") self._progress_text.pack(side="top", fill="x", padx=20, pady=10) self._message = Label( self, **self.style.text, anchor="w", compound="left", wrap=400, justify="left", pady=5, padx=5, ) self._action_btn = Button(self, text="Retry", **self.style.button_highlight, width=80, height=25) self.extra_info = Text(self, width=40, height=6, state='disabled', font='consolas 10') self.pack(fill="both", expand=True) self.check_for_update()
def __init__(self, pref): super().__init__() self.pref = pref self.load_styles(pref.get("resource::theme")) try: self.wm_attributes("-type", "splash") except: self.enable_centering() self.overrideredirect(1) self.configure(**self.style.surface) image = load_tk_image( get_resource_path("studio", "resources/images/logo.png"), 240, 77) Label(self, image=image, **self.style.surface).pack(side="top", fill="y", padx=20, pady=20) self._progress = ProgressBar(self) self._progress.pack(side="top", fill="x", padx=20, pady=10) self._progress.set(0) self._progress_text = Label(self, **self.style.text_small, text="Waiting for resource loader...", anchor="w") self._progress_text.pack(side="top", fill="x", padx=20, pady=10) self.update_idletasks() # give the loader some time to render before starting load self.after(200, self.start_load)
def render(self): if not self.value: Label(self, **self.style.dark_text, text="select", anchor="w").pack(fill="both") return Label(self, **self.style.dark_text, text=self._value, anchor="w").pack(fill="both")
def render(self, _): self.detail = Label(self, **self.style.text, text=self.message) self.detail.pack(fill="x") warn_frame = Frame(self, **self.style.surface) self._warning = Label( warn_frame, **self.style.text_passive, padx=5, anchor='w', compound="left", image=get_tk_image("dialog_warning", 15, 15), ) self.event_pad = Label( self, **self.style.text_accent) self._add_button(text="Cancel", value=None) self._add_button(text="Okay", command=self.exit_with_key, focus=True) warn_frame.pack(side="bottom", fill="x") self.event_pad.config( **self.style.bright, takefocus=True, text="Tap here to begin capturing shortcuts." ) self.event_pad.bind("<Any-KeyPress>", self.on_key_change) # for some reason alt needs to be bound separately self.event_pad.bind("<Alt-KeyPress>", self.on_key_change) self.event_pad.bind("<Button-1>", lambda e: self.event_pad.focus_set()) self.event_pad.pack(fill="both", expand=True)
def render(self): if not self.value: Label(self, width=2, **self.style.text, bd=2).pack(side="left") Label(self, text="select", **self.style.text).pack(side="left", padx=4) else: Label(self, relief=self.value, width=2, **self.style.text, bd=2).pack(side="left") Label(self, text=self.value, **self.style.text).pack(side="left", padx=4)
def __init__(self, parent, label, value): super().__init__(parent, height=20) self.config(**self.style.surface) Label(self, text=label, **self.style.text, anchor='e').place(x=0, y=0, relwidth=0.5, height=20) Label(self, text=value, **self.style.text_passive, anchor='w').place(relx=0.5, y=0, relwidth=0.5, height=20) self.pack(side="top", fill="x", padx=10, pady=1)
def render(self): self.key_label = Label(self, text=self.value[1].label, **self.style.dark_text_accent) self.key_label.pack(side="right") routine = actions.get_routine(self.value[0]) self.desc = Label(self, text=routine.desc, **self.style.dark_text) self.desc.pack(side="left")
class Color(Editor): def __init__(self, master, style_def=None): super().__init__(master, style_def) self.config(**self.style.dark_highlight_active) self._entry = Entry(self, **self.style.dark_input, **self.style.no_highlight) self._color_button = Label(self, relief='groove', bd=1) self._color_button.bind('<ButtonRelease-1>', self._chooser) self._color_button.place(x=2, y=2, width=20, height=20) self._picker = ColorPicker(self, **self.style.dark_button) self._picker.place(relx=1, x=-22, y=0, width=20, height=20) self._picker.on_pick(self.set) self._entry.place(x=22, y=0, relheight=1, relwidth=1, width=-46) self._entry.on_change(self._change) def _change(self, value=None): value = self._entry.get() if value is None else value val = self._parse_color(value) if val: self._color_button.config(bg=value) if self._on_change: self._on_change(value) def _parse_color(self, value): try: val = self.winfo_rgb(value) except Exception: return "" val = tuple(map(lambda x: round((x / 65535) * 255), val)) return to_hex(val) def get(self): return self._entry.get() def set(self, value): self.adjust(value) def on_change(self, func, *args, **kwargs): super().on_change(func, *args, **kwargs) def adjust(self, value): self._entry.update_idletasks() self._entry.set(value) try: self._color_button.config(bg=value) except Exception: self._color_button.config(bg="#000000") def _chooser(self, *_): dialog = ColorDialog(self.window) dialog.update_idletasks() self.window.update_idletasks() dialog.post(self._color_button, side="auto", padding=4) if self.get().startswith("#"): dialog.set(self.get()) elif self.get(): dialog.set(self._parse_color(self.get())) dialog.on_change(self.adjust)
class CollapseFrame(Frame): 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 update_state(self): self.__ref.pack(side="top") 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 clear_children(self): self.body.clear_children() 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 def toggle(self, *_): if self._collapsed: self.expand() else: self.collapse() @property def label(self): return self._label["text"] @label.setter def label(self, value): self._label.config(text=value)
def begin_drag(self, event): if not self.editable: return # If cursor is moved while holding the left button down for the first time we begin drag if event.state & EventMask.MOUSE_BUTTON_1 and not MalleableTree.drag_active and \ self.tree.selected_count(): MalleableTree.drag_popup = DragWindow(self.window).set_position(event.x_root, event.y_root + 20) MalleableTree.drag_components = self.tree._selected MalleableTree.drag_instance = self.tree count = 0 for component in MalleableTree.drag_components: # Display all items upto the drag_display_limit if count == MalleableTree.drag_display_limit: overflow = len(MalleableTree.drag_components) - count # Display the overflow information Label(MalleableTree.drag_popup, text=f"and {overflow} other{'' if overflow == 1 else 's'}...", anchor='w', **self.style.dark_text).pack(side="top", fill="x") break Label(MalleableTree.drag_popup, text=component.name, anchor='w', **self.style.dark_text).pack(side="top", fill="x") count += 1 MalleableTree.drag_active = True elif MalleableTree.drag_active: widget = self.winfo_containing(event.x_root, event.y_root) # The widget can be a child to Node but not necessarily a node but we need a node so # Resolve the node that is immediately under the cursor position by iteratively getting widget's parent # For the sake of performance not more than 4 iterations limit = 4 while not isinstance(widget, self.__class__): if widget is None: # This happens when someone hovers outside the current top level window break widget = self.nametowidget(widget.winfo_parent()) limit -= 1 if not limit: break tree = self.event_first(event, self.tree, MalleableTree) if isinstance(widget, MalleableTree.Node): # We can only react if we have resolved the widget to a Node object widget.react(event) # Store the currently reacting widget so we can apply actions to it on ButtonRelease/ drag_end MalleableTree.drag_select = widget elif isinstance(tree, self.tree.__class__): # if the tree found is compatible to the current tree i.e belongs to same class or is subclass of # disallow incompatible trees from interacting as this may cause errors tree.react(event) MalleableTree.drag_select = tree else: # No viable node found on resolution so clear all highlights and indicators if MalleableTree.drag_select: MalleableTree.drag_select.clear_indicators() MalleableTree.drag_select = None MalleableTree.drag_popup.set_position(event.x_root, event.y_root + 20)
def __init__(self, master, style_def=None): super().__init__(master, style_def) self._entry.config(from_=0, to=1e6) self._entry.set_validator(numeric_limit, 0, 1e6) self._entry.pack_forget() self._unit = Label(self, **self.style.dark_text_passive) self._unit.pack(side="right") self.set_def(style_def) self._entry.pack(side="left", fill="x")
def __init__(self, master, pane, **cnf): super().__init__(master) self._title = Label(self, **self.style.text_accent) self._title.pack(side="top", fill="x") self._tab_view = TabView(self) self._tab_view.pack(fill="both") self.column_config = ColumnConfig(self, pane, **cnf) self.row_config = RowConfig(self, pane, **cnf) self._tab_view.add(self.column_config, text="Column") self._tab_view.add(self.row_config, text="Row")
def __init__(self, master, component: PseudoWidget.__class__, _=None): super().__init__(master) self.config(**self.style.surface) self._icon = Label(self, **self.style.text_accent, image=get_icon_image(component.icon, 15, 15)) self._icon.pack(side="left") self._text = Label(self, **self.style.text, anchor="w", text=component.display_name) self._text.pack(side="left", fill="x") self.bind("<Enter>", self.select) self.bind("<Leave>", self.deselect) self.component = component self.allow_drag = True
def __init__(self, master, style_def=None): super().__init__(master, style_def) self.config(**self.style.dark_highlight_active) self._entry = Entry(self, **self.style.dark_input) self._color_button = Label(self, relief='groove', bd=1) self._color_button.bind('<ButtonRelease-1>', self._chooser) self._color_button.place(x=2, y=2, width=20, height=20) self._picker = ColorPicker(self, **self.style.dark_button) self._picker.place(relx=1, x=-22, y=0, width=20, height=20) self._picker.on_pick(self.set) self._entry.place(x=22, y=0, relheight=1, relwidth=1, width=-46) self._entry.on_change(self._change)
class Component(Frame): def __init__(self, master, component: PseudoWidget.__class__, _=None): super().__init__(master) self.config(**self.style.surface) self._icon = Label(self, **self.style.text_accent, image=get_icon_image(component.icon, 15, 15)) self._icon.pack(side="left") self._text = Label(self, **self.style.text, anchor="w", text=component.display_name) self._text.pack(side="left", fill="x") self.bind("<Enter>", self.select) self.bind("<Leave>", self.deselect) self.component = component self.allow_drag = True def select(self, *_): self.config_all(**self.style.hover) def deselect(self, *_): self.config_all(**self.style.surface) def render_drag(self, window): Label(window, **self.style.text_accent, image=get_icon_image(self.component.icon, 15, 15)).pack(side="left") Label(window, **self.style.text, anchor="w", text=self.component.display_name).pack(side="left", fill="x") def drag_start_pos(self, event): window = self.window.drag_window if window: window.update_idletasks() return ( event.x_root - int(window.winfo_width() / 2), event.y_root - int(window.winfo_height() / 2) ) return super(Component, self).drag_start_pos(event) def _adjust_event(self, event): # adjust event position so it appears out the drag window # this allows us to determine studio widget at said position if self.window.drag_window: event.x_root = self.window.drag_window.get_center()[0] event.y_root = self.window.drag_window.pos[1] - 1 def on_drag(self, event): self._adjust_event(event) widget = self.event_first(event, self, Container) if widget and self.window.drag_window: widget.react(*self.window.drag_window.get_center()) def on_drag_end(self, event): self._adjust_event(event) widget = self.event_first(event, self, Container) if isinstance(widget, Container): widget.add_new(self.component, *self.window.drag_window.get_center())
class Component(Frame): drag_popup = None drag_active = None def __init__(self, master, component: PseudoWidget.__class__): super().__init__(master) self.config(**self.style.dark) self._icon = Label(self, **self.style.dark_text_accent, image=get_icon_image(component.icon, 15, 15)) self._icon.pack(side="left") self._text = Label(self, **self.style.dark_text, anchor="w", text=component.display_name) self._text.pack(side="left", fill="x") self.bind("<Enter>", self.select) self.bind("<Leave>", self.deselect) self.component = component self.bind_all("<Motion>", self.drag) self.bind_all("<ButtonRelease-1>", self.release) def select(self, *_): self.config_all(**self.style.dark_on_hover) def deselect(self, *_): self.config_all(**self.style.dark) def drag(self, event): # If cursor is moved while holding the left button down for the first time we begin drag if event.state & EventMask.MOUSE_BUTTON_1 and not self.drag_active: self.drag_popup = DragWindow(self.window).set_position( event.x_root, event.y_root) Label(self.drag_popup, text=self.component.display_name).pack() self.drag_active = True elif self.drag_active: widget = self.event_first(event, self, Designer) if isinstance(widget, Designer): widget.react(event) self.drag_popup.set_position(event.x_root, event.y_root) def release(self, event): if not self.drag_active: return self.drag_active = False self.drag_popup.destroy() self.drag_popup = None widget = self.event_first(event, self, Container) if isinstance(widget, Container): widget.add_new(self.component, event.x_root, event.y_root)
def __init__(self, master, pane, **cnf): super().__init__(master) self.style_pane = pane self.configure(**{**self.style.surface, **cnf}) self._empty_message = "Select an item to see styles" self._empty = Frame(self.body, **self.style.surface) self._empty_label = Label( self._empty, **self.style.text_passive, ) self._empty_label.pack(fill="both", expand=True, pady=15) self._widget = None self._prev_widget = None self._has_initialized = False # Flag to mark whether Style Items have been created self.items = {}
class CoordinateIndicator(Frame): def __init__(self, master, **cnf): super().__init__(master, **cnf) Label(self, **self.style.dark_text_accent_1, text="x: ", width=3).pack(side='left') self._x = Label(self, **self.style.dark_text, width=5, anchor='w') self._x.pack(side='left') Label(self, **self.style.dark_text_accent_1, text="y: ", width=3).pack(side='left') self._y = Label(self, **self.style.dark_text, width=5, anchor='w') self._y.pack(side='left') def set_coord(self, x, y): self._y['text'] = int(y) self._x['text'] = int(x)
class ComponentTreeView(MalleableTreeView): class Node(MalleableTreeView.Node): def __init__(self, master=None, **config): super().__init__(master, **config) self.widget: PseudoWidget = config.get("widget") self.widget.node = self self.name_pad.configure(text=self.widget.id) self.icon_pad.configure( image=get_icon_image(self.widget.icon, 15, 15)) def widget_modified(self, widget): self.widget = widget self.name_pad.configure(text=self.widget.id) self.icon_pad.configure( image=get_icon_image(self.widget.icon, 15, 15)) def initialize_tree(self): super(ComponentTreeView, self).initialize_tree() self._empty = Frame(self, **self.style.surface) self._empty_text = Label(self._empty, **self.style.text_passive) self._empty_text.pack(fill="both", expand=True, pady=30) self._show_empty("No items created yet") def add(self, node): super().add(node) self._remove_empty() def insert(self, index=None, *nodes): super(ComponentTreeView, self).insert(index, *nodes) self._remove_empty() def remove(self, node): super().remove(node) if len(self.nodes) == 0: self._show_empty("No items created yet") def _show_empty(self, text): self._empty_text["text"] = text self._empty.place(x=0, y=0, relheight=1, relwidth=1) def _remove_empty(self): self._empty.place_forget() def search(self, query): if not super().search(query): self._show_empty("No items match your search") else: self._remove_empty()
def __init__(self, master, studio): super().__init__(master) self.id = None self.setup_widget() self.parent = self self.studio = studio self.config(**self.style.bright, takefocus=True) self.objects = [] self.root_obj = None self.layout_strategy = DesignLayoutStrategy(self) self.highlight = HighLight(self) self.highlight.on_resize(self._on_size_changed) self.highlight.on_move(self._on_move) self.highlight.on_release(self._on_release) self._update_throttling() self.studio.pref.add_listener( "designer::frame_skip", self._update_throttling ) self.current_obj = None self.current_container = None self.current_action = None self._frame.bind("<Button-1>", lambda *_: self.focus_set()) self._frame.bind('<Motion>', self.on_motion, '+') self._padding = 30 self.design_path = None self.xml = XMLForm(self) self._load_progress = None self._shortcut_mgr = KeyMap(self._frame) self._set_shortcuts() self._last_click_pos = None # create the dynamic menu self._context_menu = MenuUtils.make_dynamic( self.studio.menu_template + ToolManager.get_tool_menu(self.studio) + (LoadLater(lambda: self.current_obj.create_menu() if self.current_obj else ()),), self.studio, self.style ) self._coord_indicator = self.studio.install_status_widget(CoordinateIndicator) self._empty = Label( self, image=get_tk_image("paint", 30, 30), compound="top", text="Drag a container here to start", **self.style.dark_text_passive, ) self._empty.config(**self.style.bright) self._show_empty(True)
def __init__(self, parent): super().__init__(parent) self.config(**self.style.dark) image = load_tk_image( get_resource_path('studio', 'resources/images/logo.png'), 400, 129) Label(self, image=image, **self.style.dark).pack(side="top", fill="y") Label(self, text="Version {} alpha".format(formation.__version__), **self.style.dark_text).pack(side="top", fill="y", pady=15) Label(self, text="Make designing user interfaces in python a breeze!", **self.style.dark_text).pack(side="top", fill="y", pady=5) copy_right = "Copyright © 2019-2020 Hoverset group" Label(self, text=copy_right, **self.style.dark_text_passive).pack(side="top", fill="y") self.pack(fill="both", expand=True)
def render(self): if self.value: item = VariableItem(self, self.value) item.pack(fill="both") item.pack_propagate(0) else: Label(self, text="", **self.style.dark_text).pack(fill="x")
def render(self): Label(self, **self.style.dark_text, anchor="w", image=get_icon_image(self.value.icon, 14, 14), text=" " + self.value.name, compound='left').pack(fill="x")
def __init__(self, master, studio=None, **cnf): super().__init__(master, **cnf) self.update_defaults() self.__class__._instance = self if not self.__class__._view_mode: self.__class__._view_mode = StringVar(None, self.get_pref('mode')) self.__class__._transparency_flag = t = BooleanVar(None, self.get_pref('inactive_transparency')) self.__class__._side = side = StringVar(None, self.get_pref('side')) t.trace_add("write", lambda *_: self.set_pref('inactive_transparency', t.get())) self.studio = studio self._header = Frame(self, **self.style.dark, **self.style.dark_highlight_dim, height=30) self._header.pack(side="top", fill="x") self._header.pack_propagate(0) self._header.allow_drag = True Label(self._header, **self.style.dark_text_passive, text=self.name).pack(side="left") self._min = Button(self._header, image=get_icon_image("close", 15, 15), **self.style.dark_button, width=25, height=25) self._min.pack(side="right") self._min.on_click(self.minimize) self._pref = MenuButton(self._header, **self.style.dark_button) self._pref.configure(image=get_icon_image("settings", 15, 15)) self._pref.pack(side="right") self._pref.tooltip("Options") self._search_bar = SearchBar(self._header, height=20) self._search_bar.on_query_clear(self.on_search_clear) self._search_bar.on_query_change(self.on_search_query) menu = self.make_menu(( ("cascade", "View Mode", None, None, {"menu": ( ("radiobutton", "Docked", None, self.open_as_docked, {"variable": self._view_mode, "value": "docked"}), ("radiobutton", "Window", None, self.open_as_window, {"variable": self._view_mode, "value": "window"}), )}), ("cascade", "Position", None, None, {"menu": ( ("radiobutton", "Left", None, lambda: self.reposition("left"), {"variable": self._side, "value": "left"}), ("radiobutton", "Right", None, lambda: self.reposition("right"), {"variable": self._side, "value": "right"}), )}), EnableIf(lambda: self._view_mode.get() == 'window', ("cascade", "Window options", None, None, {"menu": ( ( "checkbutton", "Transparent when inactive", None, None, {"variable": self._transparency_flag}), )})), ("command", "Close", get_icon_image("close", 14, 14), self.minimize, {}), ("separator",), *self.create_menu() ), self._pref) self._pref.config(menu=menu) # self._pref.on_click(self.minimize) self.config(**self.style.dark) self.indicator = None self.window_handle = None self.on_focus(self._on_focus_get) self.on_focus_lost(self._on_focus_release) self.on_close(self.close_window) self._mode_map = { 'window': self.open_as_window, 'docked': self.open_as_docked }
def __init__(self, parent, style_definition, on_change=None): super().__init__(parent.body) self.pref = get_active_pref(self) self.definition = style_definition self.name = style_definition.get("name") self.config(**self.style.surface) display = get_display_name(style_definition, self.pref) self._label = Label(self, **parent.style.text_passive, text=display, anchor="w") self._label.grid(row=0, column=0, sticky='ew') self._editor = get_editor(self, style_definition) self._editor.grid(row=0, column=1, sticky='ew') self.grid_columnconfigure(1, weight=1, uniform=1) self.grid_columnconfigure(0, weight=1, uniform=1) self._on_change = on_change self._editor.set(style_definition.get("value")) self._editor.on_change(self._change)
def __init__(self, master, debugger): super(StylePane, self).__init__(master) Label(self._header, **self.style.text_accent, text=self.name).pack(side="left") self.debugger = debugger self.setup_style_pane() self.add_group(LayoutGroup) self.add_group(AttributeGroup) self.debugger.bind("<<WidgetSelectionChanged>>", self.on_selection_changed)
def _message(self, text, icon=None): # set default icon to INFO if icon is None: icon = self.ICON_INFO Label(self, **self.style.text, text=text, anchor="w", compound="left", wrap=600, justify="left", pady=5, padx=15, image=get_icon_image(icon, 50, 50) ).pack(side="top", fill="x")