Skip to content
This repository was archived by the owner on May 5, 2021. It is now read-only.

Master memory devtools chm #153

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 45 additions & 7 deletions packages/core/src/JWEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ import { AtomicNode } from './VNodes/AtomicNode';
import { SeparatorNode } from './VNodes/SeparatorNode';
import { ModeIdentifier, ModeDefinition, Mode, RuleProperty } from './Mode';
import { Memory, ChangesLocations } from './Memory/Memory';
import { makeVersionable } from './Memory/Versionable';
import { makeVersionable, markNotVersionable } from './Memory/Versionable';
import { VersionableArray } from './Memory/VersionableArray';
import { VersionableSet } from './Memory/VersionableSet';
import { MemoryOrigin } from '../../plugin-devtools/src/components/MemoryComponent';
import { Point, VNode } from './VNodes/VNode';

export enum EditorStage {
Expand Down Expand Up @@ -85,6 +87,10 @@ export interface PluginMap extends Map<typeof JWPlugin, JWPlugin> {
get<T extends typeof JWPlugin>(constructor: T): InstanceType<T>;
}

interface MemoryInfo extends MemoryOrigin {
uiCommand: boolean;
}

export class JWEditor {
private _stage: EditorStage = EditorStage.CONFIGURATION;
dispatcher: Dispatcher;
Expand All @@ -101,7 +107,7 @@ export class JWEditor {
deadlockTimeout: 10000,
};
memory: Memory;
memoryInfo: { commandNames: string[]; uiCommand: boolean };
memoryInfo: MemoryInfo;
private _memoryID = 0;
selection: VSelection;
loaders: Record<string, Loader> = {};
Expand Down Expand Up @@ -161,7 +167,18 @@ export class JWEditor {
this.memory = new Memory();
this.memory.attach(this.selection.range.start);
this.memory.attach(this.selection.range.end);
this.memoryInfo = makeVersionable({ commandNames: [], uiCommand: false });
this.memoryInfo = makeVersionable({
// for dev tools and plugin's values merge
commandNames: [],
uiCommand: false,
layers: new Set([]),
actionID: '',
actionArgs: {} as object,
base: '',
current: this._memoryID.toString(),
isMaster: true,
error: null,
});
this.memory.attach(this.memoryInfo);
this.memory.create(this._memoryID.toString());

Expand Down Expand Up @@ -500,7 +517,10 @@ export class JWEditor {
const origin = this.memory.sliceKey;
const memorySlice = this._memoryID.toString();
this.memory.switchTo(memorySlice);
this.memoryInfo.isMaster = false;
this.memoryInfo.layers = new VersionableSet([memorySlice]);
this.memoryInfo.commandNames = new VersionableArray();
this.memoryInfo.actionID = null;
this.memoryInfo.uiCommand = false;
let commandNames = this.memoryInfo.commandNames;

Expand All @@ -510,13 +530,16 @@ export class JWEditor {
if (typeof commandName === 'function') {
const name = '@custom' + (commandName.name ? ':' + commandName.name : '');
this.memoryInfo.commandNames.push(name);
this.memoryInfo.actionID = name;
await commandName(this.contextManager.defaultContext);
if (this.memory.sliceKey !== memorySlice) {
// Override by the current commandName if the slice changed.
commandNames = [name];
}
} else {
this.memoryInfo.commandNames.push(commandName);
if (params) markNotVersionable(params);
this.memoryInfo.actionID = commandName;
await this.dispatcher.dispatch(commandName, params);
if (this.memory.sliceKey !== memorySlice) {
// Override by the current commandName if the slice changed.
Expand All @@ -538,7 +561,14 @@ export class JWEditor {
exec().then(resolve, reject);
});

// Prepare nex slice and freeze the memory.
// The running memory slice becomes a master slice.
if (!this.memory.isFrozen()) {
this.memoryInfo.isMaster = true;
this.memoryInfo.base = memorySlice;
this.memoryInfo.current = this._memoryID.toString();
}

// Prepare next slice and freeze the memory.
this._memoryID++;
const nextMemorySlice = this._memoryID.toString();
this.memory.create(nextMemorySlice);
Expand Down Expand Up @@ -567,6 +597,12 @@ export class JWEditor {

const failedSlice = this.memory.sliceKey;

// The failed memory slice becomes a master slice.
this.memory.create(failedSlice + '-fail').switchTo(failedSlice + '-fail');
this.memoryInfo.isMaster = false;
this.memoryInfo.base = memorySlice;
this.memoryInfo.error = error.message;

// When an error occurs, we go back to part of the functional memory.
this.memory.switchTo(origin);

Expand Down Expand Up @@ -609,12 +645,14 @@ export class JWEditor {
params?: CommandParamsType<P, C>,
): Promise<void> {
if (typeof commandName === 'function') {
this.memoryInfo.commandNames.push(
'@custom' + (commandName.name ? ':' + commandName.name : ''),
);
const name = '@custom' + (commandName.name ? ':' + commandName.name : '');
this.memoryInfo.commandNames.push(name);
this.memoryInfo.actionID = name;
await commandName(this.contextManager.defaultContext);
} else {
this.memoryInfo.commandNames.push(commandName);
if (params) markNotVersionable(params);
this.memoryInfo.actionID = commandName;
await this.dispatcher.dispatch(commandName, params);
}
}
Expand Down
129 changes: 129 additions & 0 deletions packages/plugin-devtools/assets/DevTools.xml
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,131 @@
</devtools-contents>
</devtools-panel>

<!-- MEMORY SVG COMPONENT -->
<g t-name="MemoryIntermediateLayout" t-attf-transform="translate(0, {{props.intermediate.offsetY * props.heigth}})" class="MemoryIntermediateLayout">
<g t-if="props.intermediate.nexts.length" t-attf-transform="translate({{props.width}}, 0)">
<MemoryIntermediateLayout
t-foreach="props.intermediate.nexts" t-as="next"
activeSlice="props.activeSlice"
selectedSlice="props.selectedSlice"
intermediate="next"
width="props.width"
heigth="props.heigth"/>
<line x1="0" t-att-y1="props.heigth" x2="0" t-att-y2="props.intermediate.height * props.heigth" stroke="black"/>
</g>
<g>
<text t-on-click="selectAction" x="6" y="28" fill="red" stroke="none"
style="font-size: 10px;font-family: arial; cursor: pointer;"><t t-esc="props.intermediate.origin.actionID"/></text>
<line x1="0" t-att-y1="props.heigth" t-att-x2="props.width" t-att-y2="props.heigth" stroke="black"/>
<circle
t-on-click="selectMemory"
t-att-cx="props.width" t-att-cy="props.heigth" r="5"
stroke-width="1"
t-att-fill="props.activeSlice === props.intermediate.key ? 'green' : (props.selectedSlice === props.intermediate.key ? 'yellow' : '#dddddd')"
style="cursor: pointer;"/>
</g>
</g>
<g t-name="MemoryIntermediateFluxLayout" class="MemoryIntermediateFluxLayout" transform="translate(12, 0)">
<!-- <rect t-att-width="props.flux.width * props.width - 24" t-att-height="props.flux.height * props.heigth" fill="transparent" stroke="#dddddd" stroke-width="1"/> -->
<line t-foreach="props.flux.origins" t-as="origin"
t-att-x1="origin.offsetX * props.width" t-att-y1="origin.offsetY * props.heigth"
t-att-x2="flux.width * props.width - 24" t-att-y2="origin.offsetY * props.heigth" stroke="green"/>
<line t-if="props.flux.origins.length"
t-att-x1="flux.width * props.width - 24" t-att-y1="flux.origins[flux.origins.length - 1].offsetY * props.heigth"
t-att-x2="flux.width * props.width - 24" y2="0" stroke="green"/>
<MemoryIntermediateLayout
t-foreach="flux.intermediates" t-as="intermediate"
activeSlice="props.activeSlice"
selectedSlice="props.selectedSlice"
intermediate="intermediate"
width="props.width"
heigth="props.heigth"/>
<line x1="0" y1="0" x2="0" t-att-y2="props.flux.height * props.heigth" stroke="black"/>
</g>
<g t-name="MemoryMasterLayout" class="MemoryMasterLayout" t-attf-transform="translate(0, {{props.master.offsetY * props.heigth}})">
<MemoryIntermediateFluxLayout
activeSlice="props.activeSlice"
selectedSlice="props.selectedSlice"
flux="props.master.flux"
width="props.width"
heigth="props.heigth"/>
<g t-if="!props.master.finished &amp;&amp; props.master.nexts.length" t-attf-transform="translate({{props.master.flux.width * props.width}},0)">
<MemoryMasterLayout
t-foreach="props.master.nexts" t-as="next"
activeSlice="props.activeSlice"
selectedSlice="props.selectedSlice"
master="next"
width="props.width"
heigth="props.heigth"/>
<line t-if="props.master.nexts.length > 1" x1="0" y1="0" x2="0" t-att-y2="props.master.nexts[props.master.nexts.length - 1].offsetY * props.heigth" stroke="black" stroke-width="2"/>
</g>
<line t-if="!props.master.finished &amp;&amp; !props.master.nexts.length"
t-attf-x1="{{props.master.flux.width * props.width}}" y1="0" y2="0" t-attf-x2="{{(props.master.flux.width + 1) * props.width}}" stroke="black" stroke-width="2"/>
<g>
<text t-if="!props.firstItem"
t-on-click="selectAction" x="12" y="-6" fill="red" stroke="none"
style="font-size: 10px;font-family: arial; cursor: pointer;"><t t-esc="props.master.origin.actionID"/></text>
<line x1="0" y1="0" y2="0" t-attf-x2="{{props.master.flux.width * props.width}}" stroke="black" stroke-width="2"/>
<circle
t-on-click="selectMemory"
t-on-dblclick="switchMemory"
t-att-cx="props.master.flux.width * props.width" cy="0" r="8"
stroke-width="1"
t-att-fill="props.activeSlice === props.master.key ? 'green' : (props.selectedSlice === props.master.key ? 'yellow' : '#dddddd')"
style="cursor: pointer;"/>
</g>
</g>
<svg t-name="MemoryFluxLayout" t-att-width="props.flux.width * 105 + 40" t-att-height="(props.flux.height + 1) * 30 + 20">
<g t-attf-transform="translate(0, 20)">
<MemoryMasterLayout
activeSlice="props.activeSlice"
selectedSlice="props.selectedSlice"
master="props.flux.first"
firstItem="true"
width="100"
heigth="30"/>
</g>
</svg>

<!-- MEMORY -->
<devtools-panel t-name="MemoryComponent"
t-on-memory-selected="onSelectMemory"
t-on-memory-switch="onSwitchMemory"
class="active" tabindex="2">
<devtools-contents>
<devtools-mainpane>
<MemoryFluxLayout t-if="state.flux" flux="state.flux" activeSlice="state.activeSlice" selectedSlice="state.selectedSlice"/>
<MemoryFluxLayout t-if="state.flux2" flux="state.flux2" activeSlice="state.activeSlice" selectedSlice="state.selectedSlice"/>
</devtools-mainpane>
<devtools-sidepane>
<div class="about">
<span class="type">Memory Slice</span> <t t-esc="state.selected.current"/>
</div>
<div class="properties">
<div style="cursor: pointer;"
t-if="state.selected.parent"
t-on-click="selectMemory(state.selected.parent)" class="divider">👤 Parent (<t t-esc="state.selected.parent"/>)</div>
<div class="divider">👪 Children</div>
<table>
<tbody>
<tr t-foreach="state.selected.children" t-as="name" t-key="index">
<td><span style="cursor: pointer;" t-on-click="selectMemory(name)"> <t t-esc="name"/> </span></td>
</tr>
</tbody>
</table>
<devtools-infotitle>📖 Commands</devtools-infotitle>
<table>
<tbody>
<tr t-foreach="state.selected.commandNames" t-as="commandName" t-key="index">
<td><t t-esc="commandName"/></td>
</tr>
</tbody>
</table>
</div>
</devtools-sidepane>
</devtools-contents>
</devtools-panel>

<!-- MAIN -->
<jw-devtools t-name="devtools"
t-att-class="{
Expand All @@ -494,6 +619,9 @@
<devtools-button t-on-click="openTab('modes')" t-att-class="{
selected: state.currentTab == 'modes',
}">Modes</devtools-button>
<devtools-button t-on-click="openTab('memory')" t-att-class="{
selected: state.currentTab == 'memory',
}">Memory</devtools-button>
<devtools-button t-on-click="inspectDom()">&#128269;</devtools-button>
</devtools-navbar>
<t t-if="!state.closed">
Expand All @@ -503,6 +631,7 @@
<ShortcutsComponent isOpen="state.currentTab == 'shortcuts'"/>
<PluginsComponent isOpen="state.currentTab == 'plugins'"/>
<ModesComponent isOpen="state.currentTab == 'modes'"/>
<MemoryComponent t-if="state.currentTab == 'memory'" actions="state.actions"/>
</t>
</jw-devtools>

Expand Down
2 changes: 2 additions & 0 deletions packages/plugin-devtools/src/components/DevToolsComponent.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { CommandsComponent } from './CommandsComponent';
import { InspectorComponent } from './InspectorComponent';
import { MemoryComponent } from './MemoryComponent';
import { ShortcutsComponent } from './ShortcutsComponent';
import { PluginsComponent } from './PluginsComponent';
import { ModesComponent } from './ModesComponent';
Expand All @@ -21,6 +22,7 @@ export class DevToolsComponent<T = {}> extends OwlComponent<T> {
static components = {
CommandsComponent: CommandsComponent,
InspectorComponent,
MemoryComponent,
ShortcutsComponent,
PluginsComponent,
ModesComponent,
Expand Down
Loading