def __init__(self, parent): super().__init__(parent) self.config(**self.style.surface) image = load_tk_image( get_resource_path("studio", 'resources/images/logo.png'), 320, 103) Label(self, image=image, **self.style.surface).pack(side="top", fill="y", pady=20, padx=50) About.Spec(self, "python", sys.version_info) About.Spec(self, "loader version", version_description(formation.__version__)) About.Spec(self, "studio version", version_description(studio.__version__)) About.Spec(self, "Platform", platform.platform()) Label(self, text="Make designing user interfaces in python a breeze!", **self.style.text).pack(side="top", fill="y", pady=5) copy_right = "Copyright © 2019-2022 Hoverset group" Label(self, text=copy_right, **self.style.text_passive).pack(side="top", fill="y") self.pack(fill="both", expand=True)
def render(self, _): self.detail = Label(self, **self.style.dark_text, text=self.message) self.detail.pack(fill="x") warn_frame = Frame(self, **self.style.dark) self._warning = Label( warn_frame, **self.style.dark_text_passive, padx=5, anchor='w', compound="left", image=get_tk_image("dialog_warning", 15, 15), ) self.event_pad = Label( self, **self.style.dark_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) self.event_pad.bind("<Button-1>", lambda e: self.event_pad.focus_set()) self.event_pad.pack(fill="both", expand=True)
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 = {}
def _show_progress(self, **kw): self.title(kw.get("title", self.title())) text = kw.get('message', 'progress') icon = None if kw.get('icon'): icon = get_icon_image(kw.get('icon'), 50, 50) Label(self, **self.style.text, text=text, anchor="w", compound="left", wrap=600, justify="left", pady=5, padx=15, image=icon ).pack(side="top", fill="x") self.progress = ProgressBar(self) self.progress.pack(side='top', fill='x', padx=20, pady=20) self.progress.mode(kw.get('mode', ProgressBar.DETERMINATE)) self.progress.color(kw.get('colors', self.style.colors.get('accent', 'white'))) self.progress.interval(kw.get('interval', ProgressBar.DEFAULT_INTERVAL))
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, 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, studio=None, **cnf): super().__init__(master, studio, **cnf) f = Frame(self, **self.style.dark) f.pack(side="top", fill="both", expand=True, pady=4) f.pack_propagate(0) self._variable_pane = ScrolledFrame(f, width=150) self._variable_pane.place(x=0, y=0, relwidth=0.4, relheight=1) self._detail_pane = ScrolledFrame(f, width=150) self._detail_pane.place(relx=0.4, y=0, relwidth=0.6, relheight=1, x=15, width=-20) self._search_btn = Button(self._header, image=get_icon_image("search", 15, 15), width=25, height=25, **self.style.dark_button) self._search_btn.pack(side="right") self._search_btn.on_click(self.start_search) self._add = MenuButton(self._header, **self.style.dark_button) self._add.configure(image=get_icon_image("add", 15, 15)) self._add.pack(side="right") self._delete_btn = Button(self._header, image=get_icon_image("delete", 15, 15), width=25, height=25, **self.style.dark_button) self._delete_btn.pack(side="right") self._delete_btn.on_click(self._delete) self._var_types_menu = self.make_menu(self._get_add_menu(), self._add) self._add.config(menu=self._var_types_menu) self._selected = None self._links = {} self._overlay = Label(f, **self.style.dark_text_passive, text="Add variables", compound="top") self._overlay.configure(image=get_icon_image("add", 25, 25)) self._show_overlay(True) self._editors = []
def __init__(self, master=None, **cnf): super().__init__(master, **cnf) self.config(**self.style.no_highlight, **self.style.dark) self._entry = Entry(self, **self.style.dark_input) self._clear_btn = Button(self, image=get_icon_image("close", 15, 15), **self.style.dark_button, width=25, height=25) self._clear_btn.pack(side="right", fill="y") self._clear_btn.on_click(self._clear) Label(self, **self.style.dark_text, image=get_icon_image("search", 15, 15)).pack(side="left") self._entry.pack(side="left", fill="both", expand=True, padx=2) self._entry.on_entry(self._change) self._on_change = None self._on_clear = None
def __init__(self, master, studio=None, **cnf): if not self._var_init: self._init_var(studio) super().__init__(master, studio, **cnf) f = Frame(self, **self.style.surface) f.pack(side="top", fill="both", expand=True, pady=4) f.pack_propagate(0) self._widget_set = Spinner(self._header, width=150) self._widget_set.config(**self.style.no_highlight) self._widget_set.set_values(list(self.CLASSES.keys())) self._widget_set.pack(side="left") self._widget_set.on_change(self.collect_groups) self._select_pane = ScrolledFrame(f, width=150) self._select_pane.place(x=0, y=0, relwidth=0.4, relheight=1) self._search_btn = Button(self._header, image=get_icon_image("search", 15, 15), width=25, height=25, **self.style.button) self._search_btn.pack(side="right") self._search_btn.on_click(self.start_search) self._search_selector = Label(self._select_pane.body, **self.style.text, text="search", anchor="w") self._search_selector.configure(**self.style.hover) self._widget_pane = ScrolledFrame(f, width=150) self._select_pane.body.config(**self.style.surface) self._widget_pane.place(relx=0.4, y=0, relwidth=0.6, relheight=1) self._pool = {} self._selectors = [] self._selected = None self._component_cache = None self._extern_groups = [] self._widget = None self.collect_groups(self.get_pref("widget_set")) # add custom widgets config to settings templates.update(_widget_pref_template) self._custom_group = None self._custom_widgets = [] Preferences.acquire().add_listener(self._custom_pref_path, self._init_custom) self._reload_custom()
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 __init__(self, master, studio=None, **cnf): if not self._var_init: self._init_var(studio) super().__init__(master, studio, **cnf) f = Frame(self, **self.style.dark) f.pack(side="top", fill="both", expand=True, pady=4) f.pack_propagate(0) self._widget_set = Spinner(self._header, width=150) self._widget_set.config(**self.style.no_highlight) self._widget_set.set_values(list(self.CLASSES.keys())) self._widget_set.pack(side="left") self._widget_set.on_change(self.collect_groups) self._select_pane = ScrolledFrame(f, width=150) self._select_pane.place(x=0, y=0, relwidth=0.4, relheight=1) self._search_btn = Button(self._header, image=get_icon_image("search", 15, 15), width=25, height=25, **self.style.dark_button) self._search_btn.pack(side="right") self._search_btn.on_click(self.start_search) self._search_selector = Label(self._select_pane.body, **self.style.dark_text, text="search", anchor="w") self._search_selector.configure(**self.style.dark_on_hover) self._widget_pane = ScrolledFrame(f, width=150, bg="orange") self._select_pane.body.config(**self.style.dark) self._widget_pane.place(relx=0.4, y=0, relwidth=0.6, relheight=1) self._pool = {} self._selectors = [] self._selected = None self._component_cache = None self.collect_groups(self.get_pref("widget_set"))
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 render(self): if not self.value: Label(self, **self.style.text, text="select", anchor="w").pack(fill="both") return Label(self, **self.style.text, text=self._value, anchor="w").pack(fill="both")
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 __init__(self, master, studio): super().__init__(master) self.id = None self.context = master self.studio = studio self.name_generator = NameGenerator(self.studio.pref) self.setup_widget() self.parent = self 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.highlight.on_start(self._on_start) 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._displace_active = False self._last_displace = time.time() self._frame.bind("<Button-1>", lambda _: self.focus_set(), '+') self._frame.bind("<Button-1>", self.set_pos, '+') self._frame.bind('<Motion>', self.on_motion, '+') self._frame.bind('<KeyRelease>', self._stop_displace, '+') self._padding = 30 self.design_path = None self.builder = DesignBuilder(self) self._shortcut_mgr = KeyMap(self._frame) self._set_shortcuts() self._last_click_pos = None self._empty = Label( self, image=get_tk_image("paint", 30, 30), compound="top", text=" ", **self.style.text_passive, ) self._empty.config(**self.style.bright) self._show_empty(True) # create the dynamic menu self._context_menu = MenuUtils.make_dynamic( self.studio.menu_template + (LoadLater(self.studio.tool_manager.get_tool_menu), ) + (LoadLater(lambda: self.current_obj.create_menu() if self.current_obj else ()), ), self.studio, self.style) design_menu = (EnableIf( lambda: self.studio._clipboard is not None, ("command", "paste", icon("clipboard", 14, 14), lambda: self.paste(self.studio._clipboard, paste_to=self), {})), ) self.set_up_context(design_menu) self._empty.set_up_context(design_menu) if Designer._coord_indicator is None: Designer._coord_indicator = self.studio.install_status_widget( CoordinateIndicator) self._text_editor = Text(self, wrap='none') self._text_editor.on_change(self._text_change) self._text_editor.bind("<FocusOut>", self._text_hide) self._base_font = FontStyle()
def __init__(self, master, widget, menu=None): super().__init__(master, widget) self.title(f'Edit menu for {widget.id}') if not isinstance(menu, tk.Menu): menu = tk.Menu(widget, tearoff=False) widget.configure(menu=menu) self._base_menu = menu self._tool_bar = Frame(self, **self.style.dark, **self.style.dark_highlight_dim, height=30) self._tool_bar.pack(side="top", fill="x") self._tool_bar.pack_propagate(False) self._pane = PanedWindow(self, **self.style.dark_pane_horizontal) self._tree = MenuTree(self._pane, widget, menu) self._tree.allow_multi_select(True) self._tree.on_select(self._refresh_styles) self._tree.on_structure_change(self._refresh_styles) self._editor_pane = ScrolledFrame(self._pane) self._editor_pane_cover = Label(self._editor_pane, **self.style.dark_text_passive) self._editor_pane.pack(side="top", fill="both", expand=True) self._menu_item_styles = CollapseFrame(self._editor_pane.body) self._menu_item_styles.pack(side="top", fill="x", pady=4) self._menu_item_styles.label = "Menu Item attributes" self._menu_styles = CollapseFrame(self._editor_pane.body) self._menu_styles.pack(side="top", fill="x", pady=4) self._menu_styles.label = "Menu attributes" self._style_item_ref = {} self._menu_style_ref = {} self._prev_selection = None self._add = MenuButton(self._tool_bar, **self.style.dark_button) self._add.pack(side="left") self._add.configure(image=get_icon_image("add", 15, 15)) _types = MenuTree.Node._type_def menu_types = self._tool_bar.make_menu( [( tk.COMMAND, i.title(), get_icon_image(_types[i][0], 14, 14), functools.partial(self.add_item, i), {} ) for i in _types], self._add) menu_types.configure(tearoff=True) self._add.config(menu=menu_types) self._delete_btn = Button(self._tool_bar, image=get_icon_image("delete", 15, 15), **self.style.dark_button, width=25, height=25) self._delete_btn.pack(side="left") self._delete_btn.on_click(self._delete) self._preview_btn = Button(self._tool_bar, image=get_icon_image("play", 15, 15), **self.style.dark_button, width=25, height=25) self._preview_btn.pack(side="left") self._preview_btn.on_click(self._preview) self._pane.pack(side="top", fill="both", expand=True) self._pane.add(self._tree, minsize=350, sticky='nswe', width=350, height=500) self._pane.add(self._editor_pane, minsize=320, sticky='nswe', width=320, height=500) self.load_menu(menu, self._tree) self._show_editor_message(self._MESSAGE_EDITOR_EMPTY) self.enable_centering() self.focus_set() self._load_all_properties()
def __init__(self, master, studio=None, **cnf): super().__init__(master, studio, **cnf) f = Frame(self, **self.style.surface) f.pack(side="top", fill="both", expand=True, pady=4) f.pack_propagate(0) self._variable_pane = ScrolledFrame(f, width=150) self._variable_pane.place(x=0, y=0, relwidth=0.4, relheight=1) self._detail_pane = ScrolledFrame(f, width=150) self._detail_pane.place(relx=0.4, y=0, relwidth=0.6, relheight=1, x=15, width=-20) Label(self._detail_pane.body, **self.style.text_passive, text="Type", anchor="w").pack(side="top", fill="x") self.var_type_lbl = Label(self._detail_pane.body, **self.style.text, anchor="w") self.var_type_lbl.pack(side="top", fill="x") Label(self._detail_pane.body, **self.style.text_passive, text="Name", anchor="w").pack(side="top", fill="x") self.var_name = editors.get_editor(self._detail_pane.body, self._definitions["name"]) self.var_name.pack(side="top", fill="x") Label(self._detail_pane.body, **self.style.text_passive, text="Value", anchor="w").pack(fill="x", side="top") self._editors = {} self._editor = None self._search_btn = Button(self._header, image=get_icon_image("search", 15, 15), width=25, height=25, **self.style.button) self._search_btn.pack(side="right") self._search_btn.on_click(self.start_search) self._search_query = None self._add = MenuButton(self._header, **self.style.button) self._add.configure(image=get_icon_image("add", 15, 15)) self._add.pack(side="right") self._delete_btn = Button(self._header, image=get_icon_image("delete", 15, 15), width=25, height=25, **self.style.button) self._delete_btn.pack(side="right") self._delete_btn.on_click(self._delete) self._var_types_menu = self.make_menu(self._get_add_menu(), self._add, title="Add variable") self._var_types_menu.configure(tearoff=True) self._add.config(menu=self._var_types_menu) self._selected = None self._links = {} self._overlay = Label(f, **self.style.text_passive, text=self._empty_message, compound="top") self._overlay.configure(image=get_icon_image("add", 25, 25)) self._show_overlay(True)
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 = StringVar(None, self.get_pref('side')) self.is_visible = BooleanVar(None, self.get_pref('visible')) t.trace_add( "write", lambda *_: self.set_pref('inactive_transparency', t.get())) self.studio = studio Label(self._header, **self.style.text_accent, text=self.name).pack(side="left") self._min = Button(self._header, image=get_icon_image("close", 15, 15), **self.style.button, width=25, height=25) self._min.pack(side="right") self._min.on_click(self.minimize) self._pref = MenuButton(self._header, **self.style.button) self._pref.configure(image=get_icon_image("settings", 15, 15)) self._pref.pack(side="right") self._pref.tooltip("Options") 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.surface) 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 render(self): Label(self, **self.style.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=None, **cnf): super().__init__(master, **cnf) # Load icon asynchronously to prevent issues which have been known to occur when loading it synchronously icon_image = load_tk_image(self.ICON_PATH) self.load_styles(self.THEME_PATH) self.iconphoto(True, icon_image) self.pref = pref self._restore_position() self.title('Formation Studio') self.protocol('WM_DELETE_WINDOW', self._on_close) self.shortcuts = ShortcutManager(self, pref) self.shortcuts.bind_all() self._register_actions() self._toolbar = Frame(self, **self.style.surface, height=30) self._toolbar.pack(side="top", fill="x") self._toolbar.pack_propagate(0) self._statusbar = Frame(self, **self.style.surface, height=20) self._statusbar.pack(side="bottom", fill="x") self._statusbar.pack_propagate(0) body = Frame(self, **self.style.surface) body.pack(fill="both", expand=True, side="top") self._right_bar = SideBar(body) self._right_bar.pack(side="right", fill="y") self._left_bar = SideBar(body) self._left_bar.pack(side="left", fill="y") self._pane = PanedWindow(body, **self.style.pane_horizontal) self._pane.pack(side="left", fill="both", expand=True) self._left = FeaturePane(self._pane, **self.style.pane_vertical) self._center = PanedWindow(self._pane, **self.style.pane_vertical) self._right = FeaturePane(self._pane, **self.style.pane_vertical) self._bin = [] self._clipboard = None self.current_preview = None self._pane.add(self._left, minsize=320, sticky='nswe', width=320) self._pane.add(self._center, minsize=400, width=16000, sticky='nswe') self._pane.add(self._right, minsize=320, sticky='nswe', width=320) self._panes = { "left": (self._left, self._left_bar), "right": (self._right, self._right_bar), "center": (self._center, None) } icon = get_icon_image self.actions = ( ("Delete", icon("delete", 20, 20), lambda e: self.delete(), "Delete selected widget"), ("Undo", icon("undo", 20, 20), lambda e: self.undo(), "Undo action"), ("Redo", icon("redo", 20, 20), lambda e: self.redo(), "Redo action"), ("Cut", icon("cut", 20, 20), lambda e: self.cut(), "Cut selected widget"), ("separator",), ("Fullscreen", icon("image_editor", 20, 20), lambda e: self.close_all(), "Design mode"), ("Separate", icon("separate", 20, 20), lambda e: self.features_as_windows(), "Open features in window mode"), ("Dock", icon("flip_horizontal", 15, 15), lambda e: self.features_as_docked(), "Dock all features"), ("separator",), ("New", icon("add", 20, 20), lambda e: self.open_new(), "New design"), ("Save", icon("save", 20, 20), lambda e: self.save(), "Save design"), ("Preview", icon("play", 20, 20), lambda e: self.preview(), "Preview design"), ) self.init_toolbar() self.selected = None # set the image option to blank if there is no image for the menu option self.blank_img = blank_img = icon("blank", 14, 14) self.tool_manager = ToolManager(self) # -------------------------------------------- menu definition ------------------------------------------------ self.menu_template = (EnableIf( lambda: self.selected, ("separator",), ("command", "copy", icon("copy", 14, 14), actions.get('STUDIO_COPY'), {}), ("command", "duplicate", icon("copy", 14, 14), actions.get('STUDIO_DUPLICATE'), {}), EnableIf( lambda: self._clipboard is not None, ("command", "paste", icon("clipboard", 14, 14), actions.get('STUDIO_PASTE'), {}) ), ("command", "cut", icon("cut", 14, 14), actions.get('STUDIO_CUT'), {}), ("separator",), ("command", "delete", icon("delete", 14, 14), actions.get('STUDIO_DELETE'), {}), ),) self.menu_bar = MenuUtils.make_dynamic( (( ("cascade", "formation", None, None, {"menu": ( ("command", "Restart", None, actions.get('STUDIO_RESTART'), {}), ("separator", ), ("command", "About Formation", icon("formation", 14, 14), lambda: about_window(self), {}), ), "name": "apple"}), ) if platform_is(MAC) else ()) + ( ("cascade", "File", None, None, {"menu": ( ("command", "New", icon("add", 14, 14), actions.get('STUDIO_NEW'), {}), ("command", "Open", icon("folder", 14, 14), actions.get('STUDIO_OPEN'), {}), ("cascade", "Recent", icon("clock", 14, 14), None, {"menu": self._create_recent_menu()}), ("separator",), EnableIf( lambda: self.designer, ("command", "Save", icon("save", 14, 14), actions.get('STUDIO_SAVE'), {}), ("command", "Save As", icon("blank", 14, 14), actions.get('STUDIO_SAVE_AS'), {}) ), EnableIf( # more than one design contexts open lambda: len([i for i in self.contexts if isinstance(i, DesignContext)]) > 1, ("command", "Save All", icon("blank", 14, 14), actions.get('STUDIO_SAVE_ALL'), {}) ), ("separator",), ("command", "Settings", icon("settings", 14, 14), actions.get('STUDIO_SETTINGS'), {}), ("command", "Restart", icon("blank", 14, 14), actions.get('STUDIO_RESTART'), {}), ("command", "Exit", icon("close", 14, 14), actions.get('STUDIO_EXIT'), {}), )}), ("cascade", "Edit", None, None, {"menu": ( EnableIf(lambda: self.context and self.context.has_undo(), ("command", "undo", icon("undo", 14, 14), actions.get('STUDIO_UNDO'), {})), EnableIf(lambda: self.context and self.context.has_redo(), ("command", "redo", icon("redo", 14, 14), actions.get('STUDIO_REDO'), {})), *self.menu_template, )}), ("cascade", "Code", None, None, {"menu": ( EnableIf( lambda: self.designer and self.designer.root_obj, ("command", "Preview design", icon("play", 14, 14), actions.get('STUDIO_PREVIEW'), {}), ("command", "close preview", icon("close", 14, 14), actions.get('STUDIO_PREVIEW_CLOSE'), {}), ("separator", ), EnableIf( lambda: self.designer and self.designer.design_path, ("command", "Reload design file", icon("rotate_clockwise", 14, 14), actions.get('STUDIO_RELOAD'), {}), ), ) )}), ("cascade", "View", None, None, {"menu": ( ("command", "show all panes", blank_img, actions.get('FEATURE_SHOW_ALL'), {}), ("command", "close all panes", icon("close", 14, 14), actions.get('FEATURE_CLOSE_ALL'), {}), ("command", "close all panes on the right", blank_img, actions.get('FEATURE_CLOSE_RIGHT'), {}), ("command", "close all panes on the left", blank_img, actions.get('FEATURE_CLOSE_LEFT'), {}), ("separator",), ("command", "Undock all windows", blank_img, actions.get('FEATURE_UNDOCK_ALL'), {}), ("command", "Dock all windows", blank_img, actions.get('FEATURE_DOCK_ALL'), {}), ("separator",), LoadLater(self.get_features_as_menu), ("separator",), EnableIf( lambda: self.context, ("command", "close tab", icon("close", 14, 14), actions.get('CONTEXT_CLOSE'), {}), ("command", "close all tabs", blank_img, actions.get('CONTEXT_CLOSE_ALL'), {}), EnableIf( lambda: self.context and len(self.tab_view.tabs()) > 1, ("command", "close other tabs", blank_img, actions.get('CONTEXT_CLOSE_OTHER'), {}) ), EnableIf( lambda: self.context and self.context._contexts_right(), ("command", "close all tabs on the right", blank_img, actions.get('CONTEXT_CLOSE_OTHER_RIGHT'), {}) ) ), ("separator",), ("command", "Save window positions", blank_img, actions.get('FEATURE_SAVE_POS'), {}) )}), ("cascade", "Tools", None, None, {"menu": (LoadLater(self.tool_manager.get_tools_as_menu), )}), ("cascade", "Help", None, None, {"menu": ( ("command", "Help", icon('dialog_info', 14, 14), actions.get('STUDIO_HELP'), {}), ("command", "Check for updates", icon("cloud", 14, 14), self._check_updates, {}), ("separator",), ("command", "About Formation", icon("formation", 14, 14), lambda: about_window(self), {}), )}) ), self, self.style, False) self.config(menu=self.menu_bar) if platform_is(MAC): self.createcommand("tk::mac::ShowPreferences", lambda: actions.get('STUDIO_SETTINGS').invoke()) self.createcommand("tk::mac::ShowHelp", lambda: actions.get('STUDIO_HELP').invoke()) self.createcommand("tk::mac::Quit", lambda: actions.get('STUDIO_EXIT').invoke()) self.features = [] self.context = None self.contexts = [] self.tab_view = TabView(self._center) self.tab_view.malleable(True) self.tab_view.bind("<<TabSelectionChanged>>", self.on_context_switch) self.tab_view.bind("<<TabClosed>>", self.on_context_close) self.tab_view.bind("<<TabAdded>>", self.on_context_add) self.tab_view.bind("<<TabOrderChanged>>", lambda _: self.save_tab_status()) self._center.add(self.tab_view, sticky='nswe') self._tab_view_empty = Label( self.tab_view, **self.style.text_passive, compound='top', image=get_icon_image("paint", 60, 60) ) self._tab_view_empty.config(**self.style.bright) # install features for feature in FEATURES: self.install(feature) # common feature references self.style_pane = self.get_feature(StylePane) # initialize tools with everything ready self.tool_manager.initialize() self._ignore_tab_status = False self._startup() self._exit_failures = 0 self._is_shutting_down = False
def drag(self, event): if not self.editable or not MalleableTree.drag_active: return # only initialize if not initialized if not MalleableTree.drag_popup: 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.text).pack(side="top", fill="x") break Label(MalleableTree.drag_popup, text=component.name, anchor='w', **self.style.text).pack(side="top", fill="x") count += 1 self._edge_scroll(event) widget = self.containing(event.x_root, event.y_root, self) # 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, self.__class__) and (not self.strict_mode or widget.tree == self.tree): # We can only react if we have resolved the widget to a compatible 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__) and (not self.strict_mode or tree == self.tree): # 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, debugger): super(ElementPane, self).__init__(master) Label(self._header, **self.style.text_accent, text=self.name).pack(side="left") ElementTreeView.Node.debugger = debugger self._tree = ElementTreeView(self) self._tree.pack(side="top", fill="both", expand=True, pady=4) self._tree.allow_multi_select(True) self._tree.on_select(self.on_select) 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", padx=2) self._search_btn.on_click(self.start_search) self._reload_btn = Button( self._header, **self.style.button, image=get_icon_image("rotate_clockwise", 15, 15), width=25, height=25, ) self._reload_btn.pack(side="right", padx=2) self._reload_btn.tooltip("reload tree") 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", padx=2) self._select_btn = ToggleButton( self._header, **self.style.button, image=get_icon_image("cursor", 15, 15), width=25, height=25, ) self._select_btn.pack(side="right", padx=2) self._select_btn.tooltip("select element to inspect") self.debugger = debugger self._tree.add_as_node( widget=debugger.root).update_preload_status(False) self.debugger.bind("<<WidgetCreated>>", self.on_widget_created) self.debugger.bind("<<WidgetDeleted>>", self.on_widget_deleted) self.debugger.bind("<<WidgetModified>>", self.on_widget_modified) tkinter.Misc.bind_all(self.debugger.root, "<Motion>", self.on_motion) tkinter.Misc.bind_all(self.debugger.root, "<Button-1>", self.on_widget_tap) tkinter.Misc.bind_all(self.debugger.root, "<Button-3>", self.on_widget_tap) tkinter.Misc.bind_all(self.debugger.root, "<Map>", self.on_widget_map) tkinter.Misc.bind_all(self.debugger.root, "<Unmap>", self.on_widget_unmap) self.highlighted = None
def render(self): if not self.value: super().render() return Label(self, **self.style.text, cursor=self.value, text=self.value, anchor='w').pack(fill="both")