Esempio n. 1
0
 def create_item(self,
                 component,
                 coords=(),
                 item=None,
                 canvas=None,
                 silently=False,
                 **kwargs):
     canvas = canvas or self.canvas
     if item is None:
         opts = dict(**component.defaults)
         opts.update(kwargs)
         item = component(canvas, *coords, **opts)
         # generate a unique id
         item.name = self.generator.generate(component, self._ids)
     canvas._cv_items.append(item)
     item._prev_index = canvas._cv_items.index(item)
     node = canvas._cv_tree.add_as_node(item=item)
     item.bind("<ButtonRelease-1>", lambda e: self._handle_select(item, e),
               True)
     item.bind("<ButtonRelease-1>", lambda e: self._handle_end(item, e),
               True)
     item.bind("<Motion>", lambda e: self._handle_move(item, e), True)
     MenuUtils.bind_context(item, self._show_item_menu(item))
     MenuUtils.bind_all_context(node, self._show_item_menu(item))
     if not silently:
         self.studio.new_action(
             Action(lambda _: self.remove_items([item], silently=True),
                    lambda _: self.restore_items([item])))
     return item
Esempio n. 2
0
 def setup_widget(self):
     self.level = 0
     self.layout = None
     self.recent_layout_info = None
     self._properties = get_properties(self)
     self.set_name(self.id)
     self.node = None
     self.__on_context = None
     self.last_menu_position = (0, 0)
     MenuUtils.bind_context(self, self.__handle_context_menu, add='+')
Esempio n. 3
0
    def on_widget_add(self, widget: PseudoWidget, parent=None):
        if parent is None:
            node = self._tree.add_as_node(widget=widget)
        else:
            parent = parent.node
            node = parent.add_as_node(widget=widget)

        # let the designer render the menu for us
        MenuUtils.bind_all_context(
            node, lambda e: self.studio.designer.show_menu(e, widget)
            if self.studio.designer else None)
Esempio n. 4
0
 def __init__(self, canvas, tool, item=None, **kw):
     super(LinearController, self).__init__(canvas, tool, item, **kw)
     if item:
         self.highlight(item)
     self._link_context = MenuUtils.make_dynamic(
         (("command", "add point", icon(
             "add", 14, 14), self._add_point, {}), ), tool.studio,
         tool.studio.style)
     self._coord_context = MenuUtils.make_dynamic(
         (("command", "remove", icon(
             "close", 14, 14), self._remove_point, {}), ), tool.studio,
         tool.studio.style)
     self._active_link = None
     self._active_coord = None
     self._active_point = None
Esempio n. 5
0
 def __init__(self, canvas, controller, coord1, coord2):
     self.canvas = canvas
     self.controller = controller
     self._id = canvas.create_line(
         coord1.x,
         coord1.y,
         coord2.x,
         coord2.y,
         fill=self.controller.tool.studio.style.colors["accent"],
         tag=("link", "controller"),
         dash=(5, 4),
         width=2)
     self.link_coord(coord1, coord2)
     canvas.tag_bind(self._id, "<ButtonRelease-1>", self._end_drag)
     MenuUtils.bind_canvas_context(self.canvas, self._id,
                                   self._context_menu)
     canvas.tag_bind(self._id, "<Motion>", self._drag)
     self.active.add(self)
     self._coord_latch = None
Esempio n. 6
0
 def __init__(self, canvas, controller, x, y):
     self.radius = self.min_radius
     self.canvas = canvas
     self.controller = controller
     self.x = x
     self.y = y
     self._id = canvas.create_oval(
         x - self.radius,
         y - self.radius,
         x + self.radius,
         y + self.radius,
         fill=self.controller.tool.studio.style.colors["accent"],
         tags=("coordinate", "controller"))
     canvas.tag_bind(self._id, "<ButtonRelease-1>", self._end_drag)
     canvas.tag_bind(self._id, "<Motion>", self._drag)
     canvas.tag_bind(self._id, "<Enter>", lambda _: self.grow_effect())
     canvas.tag_bind(self._id, "<Leave>", lambda _: self.grow_effect(True))
     MenuUtils.bind_canvas_context(self.canvas, self._id,
                                   self._context_menu)
     self.active.add(self)
     self._listeners = []
Esempio n. 7
0
 def _attach(self, obj):
     # bind events for context menu and object selection
     # all widget additions call this method so clear empty message
     self._show_empty(False)
     MenuUtils.bind_all_context(obj,
                                lambda e: self.show_menu(e, obj),
                                add='+')
     obj.bind_all(
         '<Shift-ButtonPress-1>',
         lambda e: self.highlight.set_function(self.highlight.move, e),
         add='+')
     obj.bind_all('<Motion>', self.on_motion, '+')
     obj.bind_all('<ButtonRelease>', self.highlight.clear_resize, '+')
     if "text" in obj.keys():
         obj.bind_all("<Double-Button-1>",
                      lambda _: self._show_text_editor(obj))
     self.objects.append(obj)
     if self.root_obj is None:
         self.root_obj = obj
     obj.bind_all("<Button-1>",
                  lambda e: self._handle_select(obj, e),
                  add='+')
     # bind shortcuts
     self._shortcut_mgr.bind_widget(obj)
Esempio n. 8
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)
Esempio n. 9
0
 def show_menu(self, event, obj=None):
     # select object generating the context menu event first
     if obj is not None:
         self.select(obj)
     MenuUtils.popup(event, self._context_menu)
Esempio n. 10
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()
Esempio n. 11
0
 def show(event):
     if item in self.selected_items:
         MenuUtils.popup(event, self._item_context_menu)
Esempio n. 12
0
    def __init__(self, studio, manager):
        super(CanvasTool, self).__init__(studio, manager)
        self._component_pane: ComponentPane = self.studio.get_feature(
            ComponentPane)
        self.item_select = self._component_pane.register_group(
            "Canvas", CANVAS_ITEMS, SelectToDrawGroup, self._evaluator)
        self.style_group = studio.style_pane.add_group(CanvasStyleGroup,
                                                       tool=self)

        CanvasStudioAdapter._tool = self
        # connect the canvas adapter to load canvas objects to the studio
        DesignBuilder.add_adapter(CanvasStudioAdapter, Canvas)
        self.generator = NameGenerator(self.studio.pref)

        self.items = []
        self.item_select.on_select(self.set_draw)
        self.canvas = None
        self._cursor = "arrow"
        self.current_draw = None
        self.selected_items = []
        self._clipboard = None
        self._latch_pos = 0, 0

        self._image_placeholder = icon("image_dark", 60, 60)

        self.square_draw = SquareDraw(self)
        self.line_draw = LinearDraw(self)
        self.text_draw = TextDraw(self)
        self.bitmap_draw = PointDraw(self, bitmap="gray25")
        self.image_draw = PointDraw(self, image=self._image_placeholder)

        self.draw_map = {
            Oval: self.square_draw,
            Rectangle: self.square_draw,
            Arc: self.square_draw,
            Line: self.line_draw,
            Polygon: self.line_draw,
            Text: self.text_draw,
            Bitmap: self.bitmap_draw,
            Image: self.image_draw,
        }

        self.controller_map = {
            Oval: SquareController,
            Rectangle: SquareController,
            Arc: SquareController,
            Line: LinearController,
            Polygon: ClosedLinearController,
            Text: PointController,
            Bitmap: PointController,
            Image: PointController,
        }

        self.keymap = KeyMap(None)
        CTRL = KeyMap.CTRL
        self.routines = (
            Routine(self.cut_items, 'CV_CUT', 'Cut selected items', 'canvas',
                    CTRL + CharKey('x')),
            Routine(self.copy_items, 'CV_COPY', 'Copy selected items',
                    'canvas', CTRL + CharKey('c')),
            Routine(self.paste_items, 'CV_PASTE', 'Paste selected items',
                    'canvas', CTRL + CharKey('v')),
            Routine(self.delete_items, 'CV_DELETE', 'Delete selected items',
                    'canvas', KeyMap.DELETE),
            Routine(self.duplicate_items, 'CV_DUPLICATE',
                    'Duplicate selected items', 'canvas', CTRL + CharKey('d')),
            Routine(self._send_back, 'CV_BACK', 'Send item to back', 'canvas',
                    CharKey(']')),
            Routine(self._bring_front, 'CV_FRONT', 'Bring item to front',
                    'canvas', CharKey('[')),
            Routine(lambda: self._send_back(1), 'CV_BACK_1',
                    'send item back one step', 'canvas', CTRL + CharKey(']')),
            Routine(lambda: self._bring_front(1), 'CV_FRONT_1',
                    'bring item forward one step', 'canvas',
                    CTRL + CharKey('[')),
        )
        self.keymap.add_routines(*self.routines)

        self._item_context_menu = MenuUtils.make_dynamic((EnableIf(
            lambda: self.selected_items,
            ("separator", ),
            ("command", "copy", icon("copy", 14,
                                     14), self._get_routine('CV_COPY'), {}),
            ("command", "duplicate", icon(
                "copy", 14, 14), self._get_routine('CV_DUPLICATE'), {}),
            EnableIf(lambda: self._clipboard is not None,
                     ("command", "paste", icon("clipboard", 14, 14),
                      self._get_routine('CV_PASTE'), {})),
            ("command", "cut", icon("cut", 14,
                                    14), self._get_routine('CV_CUT'), {}),
            ("separator", ),
            ("command", "delete", icon(
                "delete", 14, 14), self._get_routine('CV_DELETE'), {}),
            ("separator", ),
            ("command", "send to back", icon(
                "send_to_back", 14, 14), self._get_routine('CV_BACK'), {}),
            ("command", "bring to front", icon(
                "bring_to_front", 14, 14), self._get_routine('CV_FRONT'), {}),
            ("command", "back one step", icon(
                "send_to_back", 14, 14), self._get_routine('CV_BACK_1'), {}),
            ("command", "forward one step", icon("bring_to_front", 14, 14),
             self._get_routine('CV_FRONT_1'), {}),
        ), ), self.studio, self.studio.style)

        self._canvas_menu = MenuUtils.make_dynamic(
            (EnableIf(lambda: self._clipboard is not None,
                      ("command", "paste", icon("clipboard", 14, 14),
                       self._get_routine('CV_PASTE'), {})), ), self.studio,
            self.studio.style)
Esempio n. 13
0
 def on_coord_context(self, coord, event):
     MenuUtils.popup(event, self._coord_context)
     self._active_coord = coord
     self._active_point = self.canvas.canvasx(event.x), self.canvas.canvasy(
         event.y)
Esempio n. 14
0
 def on_link_context(self, link, event):
     MenuUtils.popup(event, self._link_context)
     self._active_link = link
     self._active_point = self.canvas.canvasx(event.x), self.canvas.canvasy(
         event.y)
Esempio n. 15
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.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.dark, height=30)
        self._toolbar.pack(side="top", fill="x")
        self._toolbar.pack_propagate(0)
        self._statusbar = Frame(self, **self.style.dark, height=20)
        self._statusbar.pack(side="bottom", fill="x")
        self._statusbar.pack_propagate(0)
        body = Frame(self, **self.style.dark)
        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.dark_pane_horizontal)
        self._pane.pack(side="left", fill="both", expand=True)
        self._left = PanedWindow(self._pane, **self.style.dark_pane_vertical)
        self._center = PanedWindow(self._pane, **self.style.dark_pane_vertical)
        self._right = PanedWindow(self._pane, **self.style.dark_pane_vertical)

        self._bin = []
        self._clipboard = None
        self._undo_stack = []
        self._redo_stack = []
        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)

        # -------------------------------------------- menu definition ------------------------------------------------
        self.menu_template = (EnableIf(
            lambda: self.selected,
            ("separator", ),
            ("command", "copy", icon("copy", 14,
                                     14), actions.get('STUDIO_COPY'), {}),
            ("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", "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", ),
                    ("command", "Save", icon(
                        "save", 14, 14), actions.get('STUDIO_SAVE'), {}),
                    ("command", "Save As", icon(
                        "save", 14, 14), actions.get('STUDIO_SAVE_AS'), {}),
                    ("separator", ),
                    ("command", "Settings", icon("settings", 14, 14),
                     actions.get('STUDIO_SETTINGS'), {}),
                    ("command", "Exit", icon(
                        "exit", 14, 14), actions.get('STUDIO_EXIT'), {}),
                )
            }), ("cascade", "Edit", None, None, {
                "menu": (
                    EnableIf(lambda: len(self._undo_stack),
                             ("command", "undo", icon("undo", 14, 14),
                              actions.get('STUDIO_UNDO'), {})),
                    EnableIf(lambda: len(self._redo_stack),
                             ("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'), {})))
            }), ("cascade", "Window", None, None, {
                "menu":
                (("command", "show all", blank_img,
                  actions.get('FEATURE_SHOW_ALL'), {}),
                 ("command", "close all", icon(
                     "close", 14, 14), actions.get('FEATURE_CLOSE_ALL'), {}),
                 ("command", "close all on the right", blank_img,
                  actions.get('FEATURE_CLOSE_RIGHT'), {}),
                 ("command", "close all 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", ),
                 ("command", "Save window positions", blank_img,
                  actions.get('FEATURE_SAVE_POS'), {}))
            }), ("cascade", "Tools", None, None, {
                "menu": ToolManager.get_tools_as_menu(self)
            }), ("cascade", "Help", None, None, {
                "menu": (
                    ("command", "Help", icon('dialog_info', 14, 14),
                     actions.get('STUDIO_HELP'), {}),
                    ("command", "Check for updates", icon("cloud", 14,
                                                          14), None, {}),
                    ("separator", ),
                    ("command", "About Studio", blank_img,
                     lambda: about_window(self), {}),
                )
            })), self, self.style, False)
        self.config(menu=self.menu_bar)

        self.features = []

        self.designer = Designer(self._center, self)
        self._center.add(self.designer, sticky='nswe')
        self.install(ComponentPane)
        self.install(ComponentTree)
        self.install(StylePane)
        self.install(VariablePane)
        self._startup()
        self._restore_position()
Esempio n. 16
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
Esempio n. 17
0
 def show(event):
     x, y = canvas.canvasx(event.x), canvas.canvasy(event.y)
     self._latch_pos = x, y
     if not canvas.find_overlapping(x, y, x, y):
         MenuUtils.popup(event, self._canvas_menu)
     return 'break'