This repository has been archived by the owner on Oct 23, 2023. It is now read-only.
/
element-command.ts
124 lines (105 loc) · 3.06 KB
/
element-command.ts
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
import { Command } from './command';
import { Page } from '../page/page';
import { PageElement } from '../page/page-element';
import { Store } from '../store';
/**
* A user operation on a page element, ensuring that the page is loaded and references get
* refreshed.
*/
export abstract class ElementCommand extends Command {
/**
* The element the user operation is performed on.
*/
protected element: PageElement;
/**
* The ID of the element the user operation is performed on,
* if the element is already part of a page.
*/
protected elementId: string;
/**
* The ID of the page the operation is performed on.
*/
protected pageId: string;
/**
* Creates a new user operation on a page element.
* @param element The element the user operation is performed on.
* @param propertyId The ID of the property to change.
* @param value The new value for the property.
* @param path A dot ('.') separated optional path within an object property to point to a deep
* property. E.g., setting propertyId to 'image' and path to 'src.srcSet.xs',
* the operation edits 'image.src.srcSet.xs' on the element.
*/
// tslint:disable-next-line:no-any
public constructor(element: PageElement) {
super();
this.element = element;
// Memorize the element and page IDs.
// This way, closing and opening a page does not break the command.
this.elementId = element.getId();
const page = element.getPage();
if (page) {
this.pageId = page.getId();
}
}
/**
* Ensures that the page of this command is currently open in the store, and opens it if not.
* Then ensures that the element is used from that open page.
* @return Whether the operation was successful. On failure, the execute/undo should abort.
*/
protected ensurePageAndElement(): boolean {
let currentPage: Page | undefined = Store.getInstance().getCurrentPage();
if (!currentPage || currentPage.getId() !== this.pageId) {
if (!Store.getInstance().openPage(this.pageId)) {
return false;
}
currentPage = Store.getInstance().getCurrentPage() as Page;
}
if (this.elementId) {
const element: PageElement | undefined = currentPage.getElementById(this.elementId);
if (!element) {
return false;
}
this.element = element;
}
return true;
}
/**
* @inheritDoc
*/
public execute(): boolean {
if (!this.ensurePageAndElement()) {
return false;
}
const page = this.element.getPage();
if (page) {
page.getProject().touch();
Store.getInstance().setSelectedElement(this.element);
}
return true;
}
/**
* @inheritDoc
*/
public maybeMergeWith(previousCommand: Command): boolean {
if (previousCommand.getType() !== this.getType()) {
return false;
}
const previousElementCommand: ElementCommand = previousCommand as ElementCommand;
if (previousElementCommand.elementId !== this.elementId) {
return false;
}
return true;
}
/**
* @inheritDoc
*/
public undo(): boolean {
if (!this.ensurePageAndElement()) {
return false;
}
if (this.element.getPage()) {
Store.getInstance().setSelectedElement(this.element);
}
return true;
}
}