Skip to content

Commit

Permalink
Polish scene tree table (#324)
Browse files Browse the repository at this point in the history
* Polish scene tree table

* Comment cleanup

* remove color test

* eslint
  • Loading branch information
brentyi authored Nov 10, 2024
1 parent 4d3c500 commit 102a1bb
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 67 deletions.
4 changes: 3 additions & 1 deletion src/viser/client/src/ControlPanel/ControlPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ import SidebarPanel from "./SidebarPanel";
// Must match constant in Python.
const ROOT_CONTAINER_ID = "root";

const MemoizedGeneratedGuiContainer = React.memo(GeneratedGuiContainer);

export default function ControlPanel(props: {
control_layout: ThemeConfigurationMessage["control_layout"];
}) {
Expand Down Expand Up @@ -99,7 +101,7 @@ export default function ControlPanel(props: {
<ServerControls />
</Collapse>
<Collapse in={showGenerated && !showSettings}>
<GeneratedGuiContainer containerUuid={ROOT_CONTAINER_ID} />
<MemoizedGeneratedGuiContainer containerUuid={ROOT_CONTAINER_ID} />
</Collapse>
</>
);
Expand Down
10 changes: 2 additions & 8 deletions src/viser/client/src/ControlPanel/SceneTreeTable.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,14 @@ export const propsWrapper = style({
padding: vars.spacing.xs,
boxSizing: "border-box",
margin: vars.spacing.xs,
marginTop: "0.1em",
marginTop: "0.2em",
marginBottom: "0.2em",
overflowX: "auto",
display: "flex",
flexDirection: "column",
gap: vars.spacing.xs,
});

export const caretIcon = style({
opacity: 0.5,
height: "1em",
width: "1em",
transform: "translateY(0.1em)",
});

export const editIconWrapper = style({
opacity: "0",
});
Expand Down
135 changes: 78 additions & 57 deletions src/viser/client/src/ControlPanel/SceneTreeTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ import {
IconDeviceFloppy,
IconX,
} from "@tabler/icons-react";
import React, { Suspense } from "react";
import React from "react";
import {
caretIcon,
editIconWrapper,
propsWrapper,
tableRow,
Expand All @@ -25,6 +24,8 @@ import {
TextInput,
Tooltip,
ColorInput,
useMantineColorScheme,
useMantineTheme,
} from "@mantine/core";

function EditNodeProps({
Expand Down Expand Up @@ -108,35 +109,39 @@ function EditNodeProps({
component="form"
onSubmit={form.onSubmit(handleSubmit)}
>
<Box
style={{
display: "flex",
alignItems: "center",
}}
>
<Box fw="500" style={{ flexGrow: "1" }} fz="sm">
{node.message.type
.replace("Message", "")
.replace(/([A-Z])/g, " $1")
.trim()}{" "}
Props
<Box>
<Box
style={{
display: "flex",
alignItems: "center",
}}
>
<Box fw="500" style={{ flexGrow: "1" }} fz="sm">
{node.message.type
.replace("Message", "")
.replace(/([A-Z])/g, " $1")
.trim()}{" "}
Props
</Box>
<Tooltip label={"Close props"}>
<IconX
style={{
cursor: "pointer",
width: "1em",
height: "1em",
display: "block",
opacity: "0.7",
}}
onClick={(evt) => {
evt.stopPropagation();
close();
}}
/>
</Tooltip>
</Box>
<Box fz="xs" opacity="0.5">
{nodeName}
</Box>
<Tooltip label={"Close props"}>
<IconX
style={{
cursor: "pointer",
width: "1em",
height: "1em",
display: "block",
color: "--mantine-color-error",
opacity: "0.7",
}}
onClick={(evt) => {
evt.stopPropagation();
close();
}}
/>
</Tooltip>
</Box>
{Object.entries(props).map(([key, value]) => {
if (value instanceof Uint8Array) {
Expand Down Expand Up @@ -267,16 +272,14 @@ export default function SceneTreeTable() {
);
return (
<ScrollArea className={tableWrapper}>
<Suspense fallback={<div>Loading...</div>}>
{childrenName.map((name) => (
<SceneTreeTableRow
nodeName={name}
key={name}
isParentVisible={true}
indentCount={0}
/>
))}
</Suspense>
{childrenName.map((name) => (
<SceneTreeTableRow
nodeName={name}
key={name}
isParentVisible={true}
indentCount={0}
/>
))}
</ScrollArea>
);
}
Expand Down Expand Up @@ -328,27 +331,56 @@ const SceneTreeTableRow = React.memo(function SceneTreeTableRow(props: {
const [propsPanelOpened, { open: openPropsPanel, close: closePropsPanel }] =
useDisclosure(false);

const colorScheme = useMantineColorScheme();
const theme = useMantineTheme();

return (
<>
<Box
className={tableRow}
style={{
cursor: expandable ? "pointer" : undefined,
marginLeft: (props.indentCount * 0.75).toString() + "em",
}}
onClick={expandable ? toggleExpanded : undefined}
onMouseOver={() => setLabelVisibility(props.nodeName, true)}
onMouseOut={() => setLabelVisibility(props.nodeName, false)}
>
{new Array(props.indentCount).fill(null).map((_, i) => (
<Box
key={i}
style={{
borderLeft: "0.3em solid",
borderColor:
colorScheme.colorScheme == "dark"
? theme.colors.gray[7]
: theme.colors.gray[2],
width: "0.2em",
marginLeft: "0.375em",
height: "2em",
}}
/>
))}
<Box
style={{
opacity: expandable ? 1 : 0.3,
opacity: expandable ? 0.7 : 0.1,
}}
>
{expanded ? (
<IconCaretDown className={caretIcon} />
<IconCaretDown
style={{
height: "1em",
width: "1em",
transform: "translateY(0.1em)",
}}
/>
) : (
<IconCaretRight className={caretIcon} />
<IconCaretRight
style={{
height: "1em",
width: "1em",
transform: "translateY(0.1em)",
}}
/>
)}
</Box>
<Box style={{ width: "1.5em", height: "1.5em" }}>
Expand All @@ -369,19 +401,8 @@ const SceneTreeTableRow = React.memo(function SceneTreeTableRow(props: {
</Tooltip>
</Box>
<Box style={{ flexGrow: "1" }}>
{props.nodeName
.split("/")
.filter((part) => part.length > 0)
.map((part, index, all) => (
// We set userSelect to prevent users from accidentally
// selecting text when dragging over the hide/show icons.
<span key={index} style={{ userSelect: "none" }}>
<span style={{ opacity: "0.3" }}>
{index === all.length - 1 ? "/" : `/${part}`}
</span>
{index === all.length - 1 ? part : ""}
</span>
))}
<span style={{ opacity: "0.3" }}>/</span>
{props.nodeName.split("/").at(-1)}
</Box>
{!propsPanelOpened ? (
<Box
Expand Down
3 changes: 2 additions & 1 deletion src/viser/client/src/ControlPanel/ServerControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { Stats } from "@react-three/drei";
import React from "react";
import SceneTreeTable from "./SceneTreeTable";

const MemoizedTable = React.memo(SceneTreeTable);

export default function ServerControls() {
const viewer = React.useContext(ViewerContext)!;
const [showStats, setShowStats] = React.useState(false);
Expand All @@ -22,7 +24,6 @@ export default function ServerControls() {
event.currentTarget.blur();
event.currentTarget.focus();
}
const MemoizedTable = React.memo(SceneTreeTable);

return (
<>
Expand Down

0 comments on commit 102a1bb

Please sign in to comment.