def _set_shortcuts(self): shortcut_mgr = self._shortcut_mgr shortcut_mgr.bind() shortcut_mgr.add_routines( actions.get('STUDIO_COPY'), actions.get('STUDIO_CUT'), actions.get('STUDIO_DELETE'), actions.get('STUDIO_PASTE'), ) # allow control of widget position using arrow keys shortcut_mgr.add_shortcut( (lambda: self.displace('right'), KeyMap.RIGHT), (lambda: self.displace('left'), KeyMap.LEFT), (lambda: self.displace('up'), KeyMap.UP), (lambda: self.displace('down'), KeyMap.DOWN), )
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 __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()