1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 | Object.defineProperty(exports, "__esModule", { value: true });
|
18 | exports.ShouldSaveDialog = exports.setDirty = exports.SaveableWidget = exports.close = exports.Saveable = exports.DelegatingSaveable = void 0;
|
19 | const event_1 = require("../common/event");
|
20 | const keys_1 = require("./keyboard/keys");
|
21 | const dialogs_1 = require("./dialogs");
|
22 | const widgets_1 = require("./widgets");
|
23 | const nls_1 = require("../common/nls");
|
24 | const common_1 = require("../common");
|
25 | class DelegatingSaveable {
|
26 | constructor() {
|
27 | this.dirty = false;
|
28 | this.onDirtyChangedEmitter = new event_1.Emitter();
|
29 | this.autoSave = 'off';
|
30 | }
|
31 | get onDirtyChanged() {
|
32 | return this.onDirtyChangedEmitter.event;
|
33 | }
|
34 | async save(options) {
|
35 | var _a;
|
36 | await ((_a = this._delegate) === null || _a === void 0 ? void 0 : _a.save(options));
|
37 | }
|
38 | set delegate(delegate) {
|
39 | var _a, _b, _c, _d;
|
40 | (_a = this.toDispose) === null || _a === void 0 ? void 0 : _a.dispose();
|
41 | this._delegate = delegate;
|
42 | this.toDispose = delegate.onDirtyChanged(() => {
|
43 | this.dirty = delegate.dirty;
|
44 | this.onDirtyChangedEmitter.fire();
|
45 | });
|
46 | this.autoSave = delegate.autoSave;
|
47 | if (this.dirty !== delegate.dirty) {
|
48 | this.dirty = delegate.dirty;
|
49 | this.onDirtyChangedEmitter.fire();
|
50 | }
|
51 | this.revert = (_b = delegate.revert) === null || _b === void 0 ? void 0 : _b.bind(delegate);
|
52 | this.createSnapshot = (_c = delegate.createSnapshot) === null || _c === void 0 ? void 0 : _c.bind(delegate);
|
53 | this.applySnapshot = (_d = delegate.applySnapshot) === null || _d === void 0 ? void 0 : _d.bind(delegate);
|
54 | }
|
55 | }
|
56 | exports.DelegatingSaveable = DelegatingSaveable;
|
57 | var Saveable;
|
58 | (function (Saveable) {
|
59 | function isSource(arg) {
|
60 | return (0, common_1.isObject)(arg) && is(arg.saveable);
|
61 | }
|
62 | Saveable.isSource = isSource;
|
63 | function is(arg) {
|
64 | return (0, common_1.isObject)(arg) && 'dirty' in arg && 'onDirtyChanged' in arg;
|
65 | }
|
66 | Saveable.is = is;
|
67 | function get(arg) {
|
68 | if (is(arg)) {
|
69 | return arg;
|
70 | }
|
71 | if (isSource(arg)) {
|
72 | return arg.saveable;
|
73 | }
|
74 | return undefined;
|
75 | }
|
76 | Saveable.get = get;
|
77 | function getDirty(arg) {
|
78 | const saveable = get(arg);
|
79 | if (saveable && saveable.dirty) {
|
80 | return saveable;
|
81 | }
|
82 | return undefined;
|
83 | }
|
84 | Saveable.getDirty = getDirty;
|
85 | function isDirty(arg) {
|
86 | return !!getDirty(arg);
|
87 | }
|
88 | Saveable.isDirty = isDirty;
|
89 | async function save(arg, options) {
|
90 | const saveable = get(arg);
|
91 | if (saveable) {
|
92 | await saveable.save(options);
|
93 | }
|
94 | }
|
95 | Saveable.save = save;
|
96 | async function closeWithoutSaving(doRevert = true) {
|
97 | const saveable = get(this);
|
98 | if (saveable && doRevert && saveable.dirty && saveable.revert) {
|
99 | await saveable.revert();
|
100 | }
|
101 | this[exports.close]();
|
102 | return (0, widgets_1.waitForClosed)(this);
|
103 | }
|
104 | function createCloseWithSaving(getOtherSaveables, doSave) {
|
105 | let closing = false;
|
106 | return async function (options) {
|
107 | var _a;
|
108 | if (closing) {
|
109 | return;
|
110 | }
|
111 | const saveable = get(this);
|
112 | if (!saveable) {
|
113 | return;
|
114 | }
|
115 | closing = true;
|
116 | try {
|
117 | const result = await shouldSave(saveable, () => {
|
118 | var _a;
|
119 | const notLastWithDocument = !closingWidgetWouldLoseSaveable(this, (_a = getOtherSaveables === null || getOtherSaveables === void 0 ? void 0 : getOtherSaveables()) !== null && _a !== void 0 ? _a : []);
|
120 | if (notLastWithDocument) {
|
121 | return this.closeWithoutSaving(false).then(() => undefined);
|
122 | }
|
123 | if (options && options.shouldSave) {
|
124 | return options.shouldSave();
|
125 | }
|
126 | return new ShouldSaveDialog(this).open();
|
127 | });
|
128 | if (typeof result === 'boolean') {
|
129 | if (result) {
|
130 | await ((_a = doSave === null || doSave === void 0 ? void 0 : doSave(this)) !== null && _a !== void 0 ? _a : Saveable.save(this));
|
131 | if (!isDirty(this)) {
|
132 | await this.closeWithoutSaving();
|
133 | }
|
134 | }
|
135 | else {
|
136 | await this.closeWithoutSaving();
|
137 | }
|
138 | }
|
139 | }
|
140 | finally {
|
141 | closing = false;
|
142 | }
|
143 | };
|
144 | }
|
145 | async function confirmSaveBeforeClose(toClose, others) {
|
146 | var _a;
|
147 | for (const widget of toClose) {
|
148 | const saveable = Saveable.get(widget);
|
149 | if (saveable === null || saveable === void 0 ? void 0 : saveable.dirty) {
|
150 | if (!closingWidgetWouldLoseSaveable(widget, others)) {
|
151 | continue;
|
152 | }
|
153 | const userWantsToSave = await new ShouldSaveDialog(widget).open();
|
154 | if (userWantsToSave === undefined) {
|
155 | return undefined;
|
156 | }
|
157 | else if (userWantsToSave) {
|
158 | await saveable.save();
|
159 | }
|
160 | else {
|
161 | await ((_a = saveable.revert) === null || _a === void 0 ? void 0 : _a.call(saveable));
|
162 | }
|
163 | }
|
164 | }
|
165 | return true;
|
166 | }
|
167 | Saveable.confirmSaveBeforeClose = confirmSaveBeforeClose;
|
168 | |
169 |
|
170 |
|
171 |
|
172 |
|
173 | function closingWidgetWouldLoseSaveable(widget, others) {
|
174 | const saveable = get(widget);
|
175 | return !!saveable && !others.some(otherWidget => otherWidget !== widget && get(otherWidget) === saveable);
|
176 | }
|
177 | function apply(widget, getOtherSaveables, doSave) {
|
178 | if (SaveableWidget.is(widget)) {
|
179 | return widget;
|
180 | }
|
181 | const saveable = Saveable.get(widget);
|
182 | if (!saveable) {
|
183 | return undefined;
|
184 | }
|
185 | const saveableWidget = widget;
|
186 | setDirty(saveableWidget, saveable.dirty);
|
187 | saveable.onDirtyChanged(() => setDirty(saveableWidget, saveable.dirty));
|
188 | const closeWithSaving = createCloseWithSaving(getOtherSaveables, doSave);
|
189 | return Object.assign(saveableWidget, {
|
190 | closeWithoutSaving,
|
191 | closeWithSaving,
|
192 | close: closeWithSaving,
|
193 | [exports.close]: saveableWidget.close,
|
194 | });
|
195 | }
|
196 | Saveable.apply = apply;
|
197 | async function shouldSave(saveable, cb) {
|
198 | if (!saveable.dirty) {
|
199 | return false;
|
200 | }
|
201 | if (saveable.autoSave !== 'off') {
|
202 | return true;
|
203 | }
|
204 | return cb();
|
205 | }
|
206 | Saveable.shouldSave = shouldSave;
|
207 | })(Saveable = exports.Saveable || (exports.Saveable = {}));
|
208 | exports.close = Symbol('close');
|
209 | var SaveableWidget;
|
210 | (function (SaveableWidget) {
|
211 | function is(widget) {
|
212 | return !!widget && 'closeWithoutSaving' in widget;
|
213 | }
|
214 | SaveableWidget.is = is;
|
215 | function getDirty(widgets) {
|
216 | return get(widgets, Saveable.isDirty);
|
217 | }
|
218 | SaveableWidget.getDirty = getDirty;
|
219 | function* get(widgets, filter = () => true) {
|
220 | for (const widget of widgets) {
|
221 | if (SaveableWidget.is(widget) && filter(widget)) {
|
222 | yield widget;
|
223 | }
|
224 | }
|
225 | }
|
226 | SaveableWidget.get = get;
|
227 | })(SaveableWidget = exports.SaveableWidget || (exports.SaveableWidget = {}));
|
228 | ;
|
229 |
|
230 |
|
231 |
|
232 | const DIRTY_CLASS = 'theia-mod-dirty';
|
233 | function setDirty(widget, dirty) {
|
234 | const dirtyClass = ` ${DIRTY_CLASS}`;
|
235 | widget.title.className = widget.title.className.replace(dirtyClass, '');
|
236 | if (dirty) {
|
237 | widget.title.className += dirtyClass;
|
238 | }
|
239 | }
|
240 | exports.setDirty = setDirty;
|
241 | class ShouldSaveDialog extends dialogs_1.AbstractDialog {
|
242 | constructor(widget) {
|
243 | super({
|
244 | title: nls_1.nls.localizeByDefault('Do you want to save the changes you made to {0}?', widget.title.label || widget.title.caption)
|
245 | }, {
|
246 | node: widget.node.ownerDocument.createElement('div')
|
247 | });
|
248 | this.shouldSave = true;
|
249 | const messageNode = this.node.ownerDocument.createElement('div');
|
250 | messageNode.textContent = nls_1.nls.localizeByDefault("Your changes will be lost if you don't save them.");
|
251 | messageNode.setAttribute('style', 'flex: 1 100%; padding-bottom: calc(var(--theia-ui-padding)*3);');
|
252 | this.contentNode.appendChild(messageNode);
|
253 | this.appendCloseButton();
|
254 | this.dontSaveButton = this.appendDontSaveButton();
|
255 | this.appendAcceptButton(nls_1.nls.localizeByDefault('Save'));
|
256 | }
|
257 | appendDontSaveButton() {
|
258 | const button = this.createButton(nls_1.nls.localizeByDefault("Don't Save"));
|
259 | this.controlPanel.appendChild(button);
|
260 | button.classList.add('secondary');
|
261 | return button;
|
262 | }
|
263 | onAfterAttach(msg) {
|
264 | super.onAfterAttach(msg);
|
265 | this.addKeyListener(this.dontSaveButton, keys_1.Key.ENTER, () => {
|
266 | this.shouldSave = false;
|
267 | this.accept();
|
268 | }, 'click');
|
269 | }
|
270 | get value() {
|
271 | return this.shouldSave;
|
272 | }
|
273 | }
|
274 | exports.ShouldSaveDialog = ShouldSaveDialog;
|
275 |
|
\ | No newline at end of file |