Skip to content

Commit e88e115

Browse files
authored
Merge pull request #36 from gregzanch/ui-updates
ui updates
2 parents 0838e55 + 216e8b0 commit e88e115

File tree

20 files changed

+498
-36
lines changed

20 files changed

+498
-36
lines changed

src/common/helpers.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,3 +413,4 @@ export const omit = <T extends Object, K extends keyof T>(props: K[], obj: T) =>
413413

414414

415415

416+
export const ensureArray = <T>(value: T|T[]) => value instanceof Array ? value : [value];

src/components/ObjectProperties/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import GenericObjectProperties, { GenericObjectPropertiesProps } from './Generic
1010
import Container from "../../objects/container";
1111
import Solver from "../../compute/solver";
1212
import Messenger from "../../messenger";
13+
import { SourceTab } from "../parameter-config/SourceTab";
1314

1415
export interface ObjectPropertyInputEvent {
1516
name: string;
@@ -44,7 +45,7 @@ export default class ObjectProperties extends React.Component<ObjectPropertiesPr
4445
}
4546
render() {
4647
switch (this.props.object.kind) {
47-
case "source": return <SourceProperties {...this.props as SourcePropertiesProps} />;
48+
case "source": return <SourceTab uuid={this.props.object.uuid} />;
4849
case "receiver": return <ReceiverProperties {...this.props as ReceiverPropertiesProps} />;
4950
case "room": return <RoomProperties {...this.props as RoomPropertiesProps} />;
5051
case "surface": return <SurfaceProperties {...this.props as SurfacePropertiesProps} />;

src/components/number-input/NumberInput.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export function NumberInput(props: NumberInputProps) {
2020
const _props = {
2121
onChange: (e: React.ChangeEvent<HTMLInputElement>) =>
2222
props.onChange({
23-
value: e.currentTarget.value,
23+
value: Number(e.currentTarget.value),
2424
name: props.name,
2525
id: props.id,
2626
type: "number"
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import React, { useEffect, useState } from "react";
2+
import { emit, on } from "../../messenger";
3+
import { Source, Receiver, Surface, Room } from "../../objects";
4+
import { useContainer } from "../../store";
5+
import PropertyRow from "./property-row/PropertyRow";
6+
import PropertyRowLabel from "./property-row/PropertyRowLabel";
7+
import PropertyRowButton from "./property-row/PropertyRowButton";
8+
import { PropertyRowCheckbox } from "./property-row/PropertyRowCheckbox";
9+
import { PropertyRowTextInput } from "./property-row/PropertyRowTextInput";
10+
import { PropertyRowNumberInput } from "./property-row/PropertyRowNumberInput";
11+
import { AllowedNames, ensureArray } from '../../common/helpers';
12+
import { PropertyRowVectorInput } from "./property-row/PropertyRowVectorInput";
13+
import { PropertyRowSelect } from "./property-row/PropertyRowSelect";
14+
15+
16+
type SetPropertyEventTypes =
17+
| AllowedNames<EventTypes, SetPropertyPayload<Source>>
18+
| AllowedNames<EventTypes, SetPropertyPayload<Receiver>>
19+
| AllowedNames<EventTypes, SetPropertyPayload<Surface>>
20+
| AllowedNames<EventTypes, SetPropertyPayload<Room>>;
21+
22+
type Containers = Source | Receiver | Surface | Room;
23+
24+
export function useContainerProperty<T extends Containers, K extends keyof T>(
25+
uuid: string,
26+
property: K,
27+
event: SetPropertyEventTypes
28+
) {
29+
const defaultValue = useContainer<T[K]>(
30+
(state) => (state.containers[uuid] as T)[property]
31+
);
32+
const [state, setState] = useState<T[K]>(defaultValue);
33+
useEffect(
34+
() => on(event, (props) => {
35+
//@ts-ignore
36+
if(props.uuid === uuid && props.property === property) setState(props.value)
37+
}),
38+
[uuid]
39+
);
40+
//@ts-ignore
41+
const changeHandler = (e) => emit(event, { uuid, property, value: e.value });
42+
43+
return [state, changeHandler] as [typeof state, typeof changeHandler];
44+
}
45+
46+
type Option = { value: string, label: string }
47+
48+
type PropertyRowInputElement = ({ value, onChange, options }: { value: any, onChange: any, options?: Option[]}) => JSX.Element;
49+
type ConnectedPropertyRowInputElement = ({ uuid, property }) => JSX.Element;
50+
const connectComponent = <T extends Containers>(
51+
event: SetPropertyEventTypes,
52+
Element: PropertyRowInputElement
53+
) => <K extends keyof T>({ uuid, property, options }: {
54+
uuid: string;
55+
property: K;
56+
options?: Option[];
57+
}) => {
58+
const [state, changeHandler] = useContainerProperty<T, K>(uuid, property, event);
59+
return <Element value={state} onChange={changeHandler} {...{ options }} />
60+
};
61+
62+
63+
64+
type Props<T extends Containers, K extends keyof T> = {
65+
uuid: string;
66+
property: K | K[];
67+
label: string;
68+
tooltip: string;
69+
options?: Option[]
70+
};
71+
72+
export const createPropertyInput = <T extends Containers>(
73+
Element: ConnectedPropertyRowInputElement
74+
) => <K extends keyof T>({ uuid, property, label, tooltip, options }: Props<T, K>) => {
75+
return (
76+
<PropertyRow>
77+
<PropertyRowLabel label={label} hasToolTip tooltip={tooltip} />
78+
<div>{ensureArray(property).map((prop, index) => <Element uuid={uuid} property={prop} key={`${uuid}-${prop}-${index}`} {...{options}}/>)}</div>
79+
</PropertyRow>
80+
);
81+
};
82+
83+
export const createPropertyInputs = <T extends Containers>(event: SetPropertyEventTypes) => ({
84+
PropertyTextInput: createPropertyInput<T>(connectComponent<T>(event, PropertyRowTextInput)),
85+
PropertyNumberInput: createPropertyInput<T>(connectComponent<T>(event, PropertyRowNumberInput)),
86+
PropertyCheckboxInput: createPropertyInput<T>(connectComponent<T>(event, PropertyRowCheckbox)),
87+
PropertyVectorInput: createPropertyInput<T>(connectComponent<T>(event, PropertyRowVectorInput)),
88+
PropertySelect: createPropertyInput<T>(connectComponent<T>(event, PropertyRowSelect)),
89+
})
90+

src/components/parameter-config/RayTracerTab.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,17 @@ import Select from "react-select";
1111
import PropertyRow from "./property-row/PropertyRow";
1212
import PropertyRowFolder from "./property-row/PropertyRowFolder";
1313
import Solver from "../../compute/solver";
14-
import { createPropertyInputs, useSolverProperty, PropertyButton } from "./SolverComponents";
14+
import { createPropertyInputs, useSolverProperty } from "./SolverComponents";
1515
import useToggle from "../hooks/use-toggle";
1616
import PropertyRowLabel from "./property-row/PropertyRowLabel";
1717
import PropertyRowCheckbox from "./property-row/PropertyRowCheckbox";
18+
import PropertyButton from "./property-row/PropertyButton";
1819

1920
const { PropertyTextInput, PropertyNumberInput, PropertyCheckboxInput } = createPropertyInputs<RayTracer>(
2021
"RAYTRACER_SET_PROPERTY"
2122
);
2223

23-
const Option = ({ item }) => <option value={item.uuid}>{item.name}</option>;
24+
// const Option = ({ item }) => <option value={item.uuid}>{item.name}</option>;
2425

2526
export const ReceiverSelect = ({ uuid }: { uuid: string }) => {
2627
const receivers = useContainer((state) => {
@@ -53,6 +54,7 @@ export const ReceiverSelect = ({ uuid }: { uuid: string }) => {
5354
</>
5455
);
5556
};
57+
5658
export const SourceSelect = ({ uuid }: { uuid: string }) => {
5759
const sources = useContainer((state) => {
5860
return filteredMapObject(state.containers, (container) =>

src/components/parameter-config/SolverComponents.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ export const createPropertyInputs = <T extends RayTracer|FDTD_2D|ImageSourceSolv
6767
PropertyCheckboxInput: createPropertyInput<T>(event, PropertyRowCheckbox),
6868
})
6969

70+
7071
export const PropertyButton = <T extends keyof EventTypes>({
7172
args,
7273
event,
@@ -106,3 +107,4 @@ export const PropertyButtonDisabled = <T extends keyof EventTypes>({
106107
</PropertyRow>
107108
);
108109
};
110+
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import React from "react";
2+
import Source, { SignalSource, SignalSourceOptions } from "../../objects/source";
3+
import Container from "../../objects/container";
4+
import { useContainer } from "../../store";
5+
import { filteredMapObject, pickProps } from "../../common/helpers";
6+
import PropertyRow from "./property-row/PropertyRow";
7+
import PropertyRowFolder from "./property-row/PropertyRowFolder";
8+
import { createPropertyInputs, useContainerProperty } from "./ContainerComponents";
9+
import useToggle from "../hooks/use-toggle";
10+
import PropertyRowLabel from "./property-row/PropertyRowLabel";
11+
import PropertyRowCheckbox from "./property-row/PropertyRowCheckbox";
12+
import PropertyButton from "./property-row/PropertyButton";
13+
14+
const { PropertyTextInput, PropertyNumberInput, PropertyCheckboxInput, PropertyVectorInput, PropertySelect } = createPropertyInputs<Source>(
15+
"SOURCE_SET_PROPERTY"
16+
);
17+
18+
const General = ({ uuid }: { uuid: string }) => {
19+
const [open, toggle] = useToggle(true);
20+
return (
21+
<PropertyRowFolder label="General" open={open} onOpenClose={toggle}>
22+
<PropertyTextInput uuid={uuid} label="Name" property="name" tooltip="Sets the name of this container" />
23+
</PropertyRowFolder>
24+
);
25+
};
26+
27+
const Visual = ({ uuid }: { uuid: string }) => {
28+
const [open, toggle] = useToggle(true);
29+
return (
30+
<PropertyRowFolder label="Visual" open={open} onOpenClose={toggle}>
31+
<PropertyCheckboxInput
32+
uuid={uuid}
33+
label="Visible"
34+
property="visible"
35+
tooltip="Toggles the visibility of this container"
36+
/>
37+
</PropertyRowFolder>
38+
);
39+
};
40+
41+
42+
43+
44+
const Transform = ({ uuid }: { uuid: string }) => {
45+
const [open, toggle] = useToggle(true);
46+
return (
47+
<PropertyRowFolder label="Transform" open={open} onOpenClose={toggle}>
48+
<PropertyVectorInput
49+
uuid={uuid}
50+
label="Position"
51+
property={["x", "y", "z"]}
52+
tooltip="Sets the container's position"
53+
/>
54+
<PropertyVectorInput
55+
uuid={uuid}
56+
label="Scale"
57+
property={["scalex", "scaley", "scalez"]}
58+
tooltip="Sets the container's scale"
59+
/>
60+
<PropertyVectorInput
61+
uuid={uuid}
62+
label="Rotation"
63+
property={["rotationx", "rotationy", "rotationz"]}
64+
tooltip="Sets the container's rotation"
65+
/>
66+
</PropertyRowFolder>
67+
);
68+
};
69+
70+
71+
const Configuration = ({ uuid }: { uuid: string }) => {
72+
const [open, toggle] = useToggle(true);
73+
return (
74+
<PropertyRowFolder label="Configuration" open={open} onOpenClose={toggle}>
75+
<PropertyNumberInput
76+
uuid={uuid}
77+
label="θ Theta"
78+
property="theta"
79+
tooltip="Sets theta"
80+
/>
81+
<PropertyNumberInput
82+
uuid={uuid}
83+
label="φ Phi"
84+
property="phi"
85+
tooltip="Sets phi"
86+
/>
87+
</PropertyRowFolder>
88+
);
89+
};
90+
91+
const FDTDConfig =({ uuid }: { uuid: string }) => {
92+
const [open, toggle] = useToggle(true);
93+
return (
94+
<PropertyRowFolder label="FDTD Config" open={open} onOpenClose={toggle}>
95+
<PropertySelect
96+
uuid={uuid}
97+
label="Signal Source"
98+
tooltip="The source thats generating it's signal"
99+
property="signalSource"
100+
options={SignalSourceOptions}
101+
/>
102+
<PropertyNumberInput uuid={uuid} label="Frequency" property="frequency" tooltip="The source's frequency" />
103+
<PropertyNumberInput uuid={uuid} label="Amplitude" property="amplitude" tooltip="The source's amplitude" />
104+
<PropertyButton label="Signal Data" tooltip="The source's signal data" event="SOURCE_CALL_METHOD" args={{ uuid, method: "saveSamples" }} />
105+
</PropertyRowFolder>
106+
)
107+
}
108+
109+
110+
// const StyleProperties = ({ uuid }: { uuid: string }) => {
111+
// const [open, toggle] = useToggle(true);
112+
// return (
113+
// <PropertyRowFolder label="Style Properties" open={open} onOpenClose={toggle}>
114+
// <PropertyNumberInput
115+
// uuid={uuid}
116+
// label="Point Size"
117+
// property="pointSize"
118+
// tooltip="Sets the size of each interection point"
119+
// />
120+
// <PropertyCheckboxInput
121+
// uuid={uuid}
122+
// label="Rays Visible"
123+
// property="raysVisible"
124+
// tooltip="Toggles the visibility of the rays"
125+
// />
126+
// <PropertyCheckboxInput
127+
// uuid={uuid}
128+
// label="Points Visible"
129+
// property="pointsVisible"
130+
// tooltip="Toggles the visibility of the intersection points"
131+
// />
132+
// </PropertyRowFolder>
133+
// );
134+
// };
135+
// const ContainerControls = ({ uuid }: { uuid: string }) => {
136+
// const [open, toggle] = useToggle(true);
137+
// return (
138+
// <PropertyRowFolder label="Container Controls" open={open} onOpenClose={toggle}>
139+
// <PropertyCheckboxInput uuid={uuid} label="Running" property="isRunning" tooltip="Starts/stops the raytracer" />
140+
// <PropertyButton event="RAYTRACER_CLEAR_RAYS" args={uuid} label="Clear Rays" tooltip="Clears all of the rays" />
141+
// </PropertyRowFolder>
142+
// );
143+
// };
144+
145+
export const SourceTab = ({ uuid }: { uuid: string }) => {
146+
return (
147+
<div>
148+
<General uuid={uuid} />
149+
<Visual uuid={uuid} />
150+
<Transform uuid={uuid} />
151+
</div>
152+
);
153+
};
154+
155+
export default SourceTab;

src/components/parameter-config/image-source-tab/ImageSourceTab.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ import { filteredMapObject, pickProps } from "../../../common/helpers";
1212
import GridRowSeperator from "../../grid-row/GridRowSeperator";
1313
import Select from 'react-select';
1414
import useToggle from "../../hooks/use-toggle";
15-
import { createPropertyInputs, useSolverProperty, PropertyButton, PropertyButtonDisabled } from "../SolverComponents";
15+
import { createPropertyInputs, useSolverProperty, PropertyButton, PropertyButtonDisabled } from "../SolverComponents";
1616
import PropertyRowFolder from "../property-row/PropertyRowFolder";
17+
import PropertyButton from '../property-row/PropertyButton';
1718
import PropertyRow from "../property-row/PropertyRow";
1819
import PropertyRowLabel from "../property-row/PropertyRowLabel";
1920
import PropertyRowCheckbox from "../property-row/PropertyRowCheckbox";
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { emit } from "../../../messenger";;
2+
import React from "react";
3+
import PropertyRow from "./PropertyRow";
4+
import PropertyRowButton from "./PropertyRowButton";
5+
import PropertyRowLabel from "./PropertyRowLabel";
6+
7+
export const PropertyButton = <T extends keyof EventTypes>({
8+
args,
9+
event,
10+
label,
11+
tooltip
12+
}: {
13+
args: EventTypes[T];
14+
event: T;
15+
label: string;
16+
tooltip: string;
17+
}) => {
18+
return (
19+
<PropertyRow>
20+
<PropertyRowLabel label={label} hasToolTip tooltip={tooltip} />
21+
<PropertyRowButton onClick={(e) => emit(event, args)} label={label} />
22+
</PropertyRow>
23+
);
24+
};
25+
26+
27+
28+
export default PropertyButton;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import React from "react";
2+
import styled from 'styled-components';
3+
4+
5+
const StyledSelect = styled.select`
6+
7+
`;
8+
9+
10+
interface Props {
11+
value: string;
12+
onChange: ({ value }: { value: string }) => void;
13+
options: {value: string, label: string}[];
14+
}
15+
16+
export const PropertyRowSelect = ({ value, onChange, options }: Props) => {
17+
return (
18+
<StyledSelect
19+
onChange={(e) => onChange({ value: e.currentTarget.value })}
20+
value={value}
21+
>
22+
{options.map(({value, label}, i)=><option value={value} key={`${value}-${label}-${i}`}>{label}</option>)}
23+
</StyledSelect>
24+
)
25+
}

0 commit comments

Comments
 (0)