예제 #1
0
    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)
예제 #2
0
 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)
예제 #3
0
 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 = {}
예제 #4
0
 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))
예제 #5
0
 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)
예제 #6
0
 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)
예제 #7
0
    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 = []
예제 #8
0
 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
예제 #9
0
    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()
예제 #10
0
 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
예제 #11
0
    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"))
예제 #12
0
 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")
예제 #13
0
 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")
예제 #14
0
 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")
예제 #15
0
    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()
예제 #16
0
파일: menus.py 프로젝트: mardukbp/Formation
    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()
예제 #17
0
    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)
예제 #18
0
 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
     }
예제 #19
0
 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")
예제 #20
0
    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
예제 #21
0
        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)
예제 #22
0
    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
예제 #23
0
 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")