Skip to content

Commit

Permalink
finish split panel scenegraph inspector
Browse files Browse the repository at this point in the history
  • Loading branch information
triwav committed Mar 21, 2024
1 parent ce451de commit b60cfb5
Show file tree
Hide file tree
Showing 7 changed files with 553 additions and 429 deletions.
9 changes: 9 additions & 0 deletions src/viewProviders/BaseRdbViewProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ export abstract class BaseRdbViewProvider extends BaseWebviewViewProvider {
});
return Promise.resolve(true);
});

this.addMessageCommandCallback(ViewProviderCommand.getStoredNodeReferences, (message) => {
const response = this.dependencies.rtaManager.getStoredNodeReferences();
this.postOrQueueMessage({
...message,
response: response
});
return Promise.resolve(true);
});
}

protected onViewReady() {
Expand Down
10 changes: 0 additions & 10 deletions src/viewProviders/SceneGraphInspectorViewProvider.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type * as vscode from 'vscode';
import { BaseRdbViewProvider } from './BaseRdbViewProvider';
import { ViewProviderId } from './ViewProviderId';
import { ViewProviderCommand } from './ViewProviderCommand';

export class SceneGraphInspectorViewProvider extends BaseRdbViewProvider {
public readonly id = ViewProviderId.sceneGraphInspectorView;
Expand All @@ -10,14 +9,5 @@ export class SceneGraphInspectorViewProvider extends BaseRdbViewProvider {
super(context, dependencies);

this.registerCommandWithWebViewNotifier(context, 'extension.brightscript.sceneGraphInspectorView.refreshNodeTree');

this.addMessageCommandCallback(ViewProviderCommand.getStoredNodeReferences, (message) => {
const response = this.dependencies.rtaManager.getStoredNodeReferences();
this.postOrQueueMessage({
...message,
response: response
});
return Promise.resolve(true);
});
}
}
2 changes: 1 addition & 1 deletion webviews/src/shared/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ export type PathContentsInfo = Omit<Partial<Awaited<ReturnType<typeof odc.statPa
};

export type TreeNodeWithBase = Partial<TreeNode> & {
base: keyof typeof BaseType;
base?: keyof typeof BaseType;
};
57 changes: 34 additions & 23 deletions webviews/src/views/RokuDeviceView/RokuDeviceView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -73,37 +73,42 @@
let focusedTreeNode: TreeNode | null;
$: {
if (mouseIsOverView && isInspectingNodes) {
if (focusedTreeNode) {
if (lastFocusedTreeNodeRef !== focusedTreeNode.ref) {
lastFocusedTreeNodeRef = focusedTreeNode.ref;
const treeNode = {
// Optimization since we only need the reference for linking with the sceneGraphInspectorView
ref: focusedTreeNode.ref
}
const message = intermediary.createEventMessage(ViewProviderEvent.onTreeNodeFocused, {
treeNode: treeNode
});
intermediary.sendMessageToWebviews(ViewProviderId.sceneGraphInspectorView, message);
}
} else {
const message = intermediary.createEventMessage(ViewProviderEvent.onTreeNodeFocused, {
treeNode: null
});
if (focusedTreeNode && lastFocusedTreeNodeRef !== focusedTreeNode.ref) {
lastFocusedTreeNodeRef = focusedTreeNode.ref;
sendOnTreeNodeFocusedEvent(focusedTreeNode);
}
}
}
intermediary.sendMessageToWebviews(ViewProviderId.sceneGraphInspectorView, message);
function sendOnTreeNodeFocusedEvent(treeNode, shouldOpen = false) {
if (!shouldOpen) {
treeNode = {
// Optimization since we only need the keyPath for linking with the sceneGraphInspectorView unless we are opening that node
keyPath: treeNode?.keyPath
}
}
const message = intermediary.createEventMessage(ViewProviderEvent.onTreeNodeFocused, {
// Keeping outer treeNode structure just so the events being sent from this view to the sceneGraphInspectorView are the same as we receive
treeNode: treeNode,
shouldOpen: shouldOpen
});
intermediary.sendMessageToWebviews(ViewProviderId.sceneGraphInspectorView, message);
}
intermediary.observeEvent(ViewProviderEvent.onTreeNodeFocused, (message) => {
focusedTreeNode = message.context.treeNode;
});
intermediary.observeEvent(ViewProviderEvent.onStoredNodeReferencesUpdated, (message) => {
focusedTreeNode = null;
intermediary.observeEvent(ViewProviderEvent.onStoredNodeReferencesUpdated, async (message) => {
if (focusedTreeNode) {
const result = await intermediary.getStoredNodeReferences();
for (const treeNode of result.flatTree) {
if (treeNode.keyPath === focusedTreeNode.keyPath) {
focusedTreeNode = treeNode;
break;
}
}
}
});
let nodeSelectionCursorLeft = 0;
Expand Down Expand Up @@ -170,7 +175,6 @@
}
lastFindNodesAtLocationArgs = args;
const {matches} = await onDeviceComponent.findNodesAtLocation(args);
focusedTreeNode = matches[0];
}
Expand All @@ -184,6 +188,11 @@
}
function onMouseDown() {
// We want to send one last event that will also trigger the node
if(isInspectingNodes && focusedTreeNode) {
sendOnTreeNodeFocusedEvent(focusedTreeNode, true);
}
isInspectingNodes = false;
}
Expand Down Expand Up @@ -379,10 +388,12 @@
<b>height:</b> {focusedTreeNode.sceneRect.height}
</div>
{/if}
{#if screenshotUrl}
<img
id="screenshot"
alt="Screenshot from Roku device"
src="{screenshotUrl}" />
{/if}

</div>
{:else}
Expand Down
88 changes: 46 additions & 42 deletions webviews/src/views/SceneGraphInspectorView/Branch.svelte
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<!-- svelte-ignore a11y-click-events-have-key-events -->
<script lang="ts">
import type { TreeNode } from 'roku-test-automation';
import throttle from 'just-throttle';
import { odc } from '../../ExtensionIntermediary';
import { utils } from '../../utils';
import { Edit, Eye, EyeClosed, DebugBreakpointDataUnverified, Move } from 'svelte-codicons';
import { Eye, EyeClosed, DebugBreakpointDataUnverified, Move } from 'svelte-codicons';
import Chevron from '../../shared/Chevron.svelte';
import type { TreeNodeWithBase } from '../../shared/types';
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
export let treeNode: TreeNode;
export let treeNode: TreeNodeWithBase;
export let depth = 0;
let self: HTMLDivElement;
Expand All @@ -23,40 +23,46 @@
}
}
let selected = false;
export let focusedNode = -1;
export let expandTreeNode: TreeNodeWithBase | undefined;
$: {
// If we are the focused node then we want to scroll down to this node
if (focusedNode !== -1 && treeNode.ref === focusedNode) {
// We need to expand all the parents before we can calculate how far we need to scroll down
dispatch('childExpanded');
selected = true;
// Go ahead and expand us as well to speed up digging into children if desired
expanded = true
const scrollToElement = (element) => {
const offset = getOffset(element);
document.getElementById('container').scrollTo({
left: 0,
top: offset.top - 90,
behavior: 'auto'
});
}
setTimeout(() => {
scrollToElement(self);
}, 0);
} else {
selected = false;
// Don't want to run on empty keypaths as these are at the base level and should stay expanded
if (treeNode.keyPath) {
// Want to collapse for everything but Scene which has an empty key path
expanded = doTreeNodesMatch(treeNode, expandTreeNode);
}
}
let selected = false;
export let selectTreeNode: TreeNodeWithBase | undefined;
$: {
selected = doTreeNodesMatch(treeNode, selectTreeNode);
}
$: hasChildren = treeNode.children.length > 0;
function doTreeNodesMatch(treeNodeA: TreeNodeWithBase, treeNodeB: TreeNodeWithBase | undefined) {
if (treeNodeB) {
if (treeNodeA.subtype === 'MainNode') {
}
if (treeNodeA.parentRef >= 0 && treeNodeB.parentRef >= 0) {
// Use key path to compare if we have a parentRef
if (treeNodeA.keyPath === treeNodeB.keyPath && treeNodeB.base === treeNodeB.base) {
return true;
}
} else {
// Else use ref
if (treeNodeA.ref === treeNodeB.ref) {
return true;
}
}
}
return false;
}
function toggleExpand() {
if (!hasChildren) {
open();
return;
}
expanded = !expanded;
Expand Down Expand Up @@ -150,7 +156,6 @@
position: relative;
padding-left: var(--leftGutterPadding);
cursor: pointer;
height: 100%;
display: flex;
}
Expand Down Expand Up @@ -179,7 +184,7 @@
.actions {
position: absolute;
right: 5px;
right: 0px;
display: none;
height: 100%;
align-items: center;
Expand All @@ -206,7 +211,8 @@
.content {
display: flex;
padding: 4px 0px;
padding: 4px 4px 4px 0;
width: 100%;
}
</style>

Expand All @@ -216,14 +222,17 @@
class:selected
on:mouseenter="{onNodeMouseEnter}"
on:mouseleave="{onNodeMouseLeave}"
on:click|stopPropagation={toggleExpand}>
on:click|stopPropagation={toggleExpand}
>
{#each { length: depth ?? 0 } as _, i}
<span class="indent-guide">&nbsp;</span>
{/each}
<div class="content">
<div class="content" on:click|stopPropagation={open}>
<span class="item-icon">
{#if hasChildren}
<Chevron expanded={expanded} />
<span on:click|stopPropagation={toggleExpand}>
<Chevron expanded={expanded} />
</span>
{:else}
<DebugBreakpointDataUnverified style="opacity: .2" />
{/if}
Expand All @@ -248,12 +257,6 @@
{#if treeNode.visible}<Eye />{:else}<EyeClosed />{/if}
</span>
{/if}
<span
title="Edit Node"
class="icon-button editButton"
on:click|stopPropagation={open}>
<Edit />
</span>
</div>
</div>
<div class="children" class:hide={!expanded}>
Expand All @@ -264,6 +267,7 @@
on:childExpanded={onChildExpanded}
depth={depth + 1}
treeNode={treeNodeChild}
focusedNode={focusedNode} />
selectTreeNode={selectTreeNode}
expandTreeNode={expandTreeNode} />
{/each}
</div>
Loading

0 comments on commit b60cfb5

Please sign in to comment.