1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
|
# (C) Copyright 2005-2023 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!
from pyface.action.schema.api import SMenu, SMenuBar, SToolBar
from pyface.api import (
ConfirmationDialog,
FileDialog,
ImageResource,
YES,
OK,
CANCEL,
)
from pyface.tasks.api import (
Task,
TaskLayout,
PaneItem,
IEditor,
IEditorAreaPane,
EditorAreaPane,
)
from pyface.tasks.action.api import DockPaneToggleGroup, TaskAction
from traits.api import observe, Property, Instance
from example_panes import PythonScriptBrowserPane
from python_editor import PythonEditor
class ExampleTask(Task):
""" A simple task for editing Python code.
"""
# Task interface -------------------------------------------------------
id = "example.example_task"
name = "Multi-Tab Editor"
active_editor = Property(
Instance(IEditor), observe="editor_area.active_editor"
)
editor_area = Instance(IEditorAreaPane)
menu_bar = SMenuBar(
SMenu(
TaskAction(name="New", method="new", accelerator="Ctrl+N"),
TaskAction(name="Open...", method="open", accelerator="Ctrl+O"),
TaskAction(name="Save", method="save", accelerator="Ctrl+S"),
id="File",
name="&File",
),
SMenu(DockPaneToggleGroup(), id="View", name="&View"),
)
tool_bars = [
SToolBar(
TaskAction(
method="new",
tooltip="New file",
image=ImageResource("document_new"),
),
TaskAction(
method="open",
tooltip="Open a file",
image=ImageResource("document_open"),
),
TaskAction(
method="save",
tooltip="Save the current file",
image=ImageResource("document_save"),
),
image_size=(32, 32),
show_tool_names=False,
)
]
# ------------------------------------------------------------------------
# 'Task' interface.
# ------------------------------------------------------------------------
def _default_layout_default(self):
return TaskLayout(left=PaneItem("example.python_script_browser_pane"))
def activated(self):
""" Overriden to set the window's title.
"""
return
filename = self.active_editor.path if self.active_editor else ""
self.window.title = filename if filename else "Untitled"
def create_central_pane(self):
""" Create the central pane: the script editor.
"""
self.editor_area = EditorAreaPane()
return self.editor_area
def create_dock_panes(self):
""" Create the file browser and connect to its double click event.
"""
browser = PythonScriptBrowserPane()
handler = lambda _: self._open_file(browser.selected_file)
browser.observe(handler, "activated")
return [browser]
# ------------------------------------------------------------------------
# 'ExampleTask' interface.
# ------------------------------------------------------------------------
def new(self):
""" Opens a new empty window
"""
editor = PythonEditor()
self.editor_area.add_editor(editor)
self.editor_area.activate_editor(editor)
self.activated()
def open(self):
""" Shows a dialog to open a file.
"""
dialog = FileDialog(parent=self.window.control, wildcard="*.py")
if dialog.open() == OK:
self._open_file(dialog.path)
def save(self):
""" Attempts to save the current file, prompting for a path if
necessary. Returns whether the file was saved.
"""
editor = self.active_editor
try:
editor.save()
except IOError:
# If you are trying to save to a file that doesn't exist, open up a
# FileDialog with a 'save as' action.
dialog = FileDialog(
parent=self.window.control, action="save as", wildcard="*.py"
)
if dialog.open() == OK:
editor.save(dialog.path)
else:
return False
return True
# ------------------------------------------------------------------------
# Protected interface.
# ------------------------------------------------------------------------
def _open_file(self, filename):
""" Opens the file at the specified path in the editor.
"""
editor = PythonEditor(path=filename)
self.editor_area.add_editor(editor)
self.editor_area.activate_editor(editor)
self.activated()
def _prompt_for_save(self):
""" Prompts the user to save if necessary. Returns whether the dialog
was cancelled.
"""
dirty_editors = dict(
[
(editor.name, editor)
for editor in self.editor_area.editors
if editor.dirty
]
)
if not dirty_editors.keys():
return True
message = "You have unsaved files. Would you like to save them?"
dialog = ConfirmationDialog(
parent=self.window.control,
message=message,
cancel=True,
default=CANCEL,
title="Save Changes?",
)
result = dialog.open()
if result == CANCEL:
return False
elif result == YES:
for name, editor in dirty_editors.items():
editor.save(editor.path)
return True
# Trait change handlers ------------------------------------------------
@observe("window:closing")
def _prompt_on_close(self, event):
""" Prompt the user to save when exiting.
"""
close = self._prompt_for_save()
window = event.new
window.veto = not close
# Trait property getter/setters ----------------------------------------
def _get_active_editor(self):
if self.editor_area is not None:
return self.editor_area.active_editor
return None
|