Skip to content

Commit 91f0f8d

Browse files
Merge pull request #77 from DiamondLightSource/update-groupbox-widget
Update GroupBox widget
2 parents ea23657 + 55e3ad1 commit 91f0f8d

File tree

5 files changed

+185
-83
lines changed

5 files changed

+185
-83
lines changed

src/ui/widgets/EmbeddedDisplay/bobParser.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const BOB_WIDGET_MAPPING: { [key: string]: any } = {
4444
display: "display",
4545
ellipse: "ellipse",
4646
embedded: "embeddedDisplay",
47-
group: "groupingcontainer",
47+
group: "groupbox",
4848
label: "label",
4949
led: "led",
5050
textupdate: "readback",
@@ -377,7 +377,9 @@ export function parseBob(
377377
initialIndex: ["initial_index", bobParseNumber],
378378
showIndex: ["show_index", opiParseBoolean],
379379
fallbackSymbol: ["fallback_symbol", opiParseString],
380-
rotation: ["rotation", bobParseNumber]
380+
rotation: ["rotation", bobParseNumber],
381+
styleOpt: ["style", bobParseNumber],
382+
lineColor: ["line_color", opiParseColor]
381383
};
382384

383385
const complexParsers = {

src/ui/widgets/EmbeddedDisplay/embeddedDisplay.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ export const EmbeddedDisplay = (
208208
if (props.border?.style === BorderStyle.GroupBox) {
209209
return (
210210
<MacroContext.Provider value={embeddedDisplayMacroContext}>
211-
<GroupBoxComponent name={resolvedName} compat={true}>
211+
<GroupBoxComponent name={resolvedName} styleOpt={0}>
212212
{component}
213213
</GroupBoxComponent>
214214
</MacroContext.Provider>
Lines changed: 66 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,73 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

3-
exports[`<GroupingContainerComponent /> > it matches the snapshot 1`] = `
4-
<div
5-
style={
6-
{
7-
"backgroundColor": "transparent",
8-
"height": "100%",
9-
"outline": "1px dotted black",
10-
"outlineOffset": "-7px",
11-
"width": "100%",
12-
}
13-
}
14-
>
3+
exports[`<GroupBoxComponent /> snapshots > it matches the snapshot for Group Box style 1`] = `
4+
<DocumentFragment>
155
<div
16-
style={
17-
{
18-
"backgroundColor": "rgba(255,255,255,255)",
19-
"fontSize": "13px",
20-
"left": "20px",
21-
"padding": "0 2px 0 2px",
22-
"position": "absolute",
23-
"top": "0",
24-
}
25-
}
6+
style="width: 100%; height: 100%; position: absolute; padding: 0px 10px 10px 10px; box-sizing: border-box;"
267
>
27-
Test
8+
<fieldset
9+
class="MuiBox-root css-1ho00z6"
10+
>
11+
<legend>
12+
Test
13+
</legend>
14+
<div
15+
style="position: relative; overflow: visible; color: black;"
16+
/>
17+
</fieldset>
2818
</div>
19+
</DocumentFragment>
20+
`;
21+
22+
exports[`<GroupBoxComponent /> snapshots > it matches the snapshot for Line style 1`] = `
23+
<DocumentFragment>
24+
<div
25+
style="width: 100%; height: 100%; position: absolute; padding: 0px; box-sizing: border-box;"
26+
>
27+
<fieldset
28+
class="MuiBox-root css-1wd2nmm"
29+
>
30+
<div
31+
style="position: relative; overflow: visible; color: black;"
32+
/>
33+
</fieldset>
34+
</div>
35+
</DocumentFragment>
36+
`;
37+
38+
exports[`<GroupBoxComponent /> snapshots > it matches the snapshot for Title Bar style 1`] = `
39+
<DocumentFragment>
2940
<div
30-
style={
31-
{
32-
"padding": "16px",
33-
"position": "relative",
34-
}
35-
}
36-
/>
37-
</div>
41+
style="width: 100%; height: 100%; position: absolute; padding: 0px; box-sizing: border-box;"
42+
>
43+
<fieldset
44+
class="MuiBox-root css-1wd2nmm"
45+
>
46+
<div
47+
style="height: 20px; width: 100%; background-color: rgb(0, 0, 0); font-family: Liberation sans,sans-serif; font-weight: normal; font-style: normal; font-size: 1rem; text-align: left; color: rgb(0, 0, 0);"
48+
>
49+
Title
50+
</div>
51+
<div
52+
style="position: relative; overflow: visible; color: black;"
53+
/>
54+
</fieldset>
55+
</div>
56+
</DocumentFragment>
57+
`;
58+
59+
exports[`<GroupBoxComponent /> snapshots > it matches the snapshot for no style 1`] = `
60+
<DocumentFragment>
61+
<div
62+
style="width: 100%; height: 100%; position: absolute; padding: 0px; box-sizing: border-box;"
63+
>
64+
<fieldset
65+
class="MuiBox-root css-m53wvz"
66+
>
67+
<div
68+
style="position: relative; overflow: visible; color: black;"
69+
/>
70+
</fieldset>
71+
</div>
72+
</DocumentFragment>
3873
`;

src/ui/widgets/GroupBox/groupBox.test.tsx

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,42 @@
11
import React from "react";
22
import { GroupBoxComponent } from "./groupBox";
3-
import { create } from "react-test-renderer";
43
import { Color } from "../../../types/color";
54
import { render } from "@testing-library/react";
65

7-
describe("<GroupingContainerComponent />", (): void => {
8-
test("it matches the snapshot", (): void => {
9-
const snapshot = create(
10-
<GroupBoxComponent name={"Test"} backgroundColor={Color.WHITE} />
6+
describe("<GroupBoxComponent /> snapshots", (): void => {
7+
test("it matches the snapshot for Group Box style", (): void => {
8+
const { asFragment } = render(
9+
<GroupBoxComponent
10+
name={"Test"}
11+
backgroundColor={Color.WHITE}
12+
styleOpt={0}
13+
/>
1114
);
12-
expect(snapshot.toJSON()).toMatchSnapshot();
15+
expect(asFragment()).toMatchSnapshot();
1316
});
17+
test("it matches the snapshot for Title Bar style", (): void => {
18+
const { asFragment } = render(
19+
<GroupBoxComponent name={"Title"} styleOpt={1} />
20+
);
21+
expect(asFragment()).toMatchSnapshot();
22+
});
23+
test("it matches the snapshot for Line style", (): void => {
24+
const { asFragment } = render(
25+
<GroupBoxComponent name={"No Title"} styleOpt={2} />
26+
);
27+
expect(asFragment()).toMatchSnapshot();
28+
});
29+
test("it matches the snapshot for no style", (): void => {
30+
const { asFragment } = render(
31+
<GroupBoxComponent name={"None"} styleOpt={3} />
32+
);
33+
expect(asFragment()).toMatchSnapshot();
34+
});
35+
});
1436

37+
describe("<GroupBoxComponent />", (): void => {
1538
test("it renders the title", (): void => {
16-
const grouping = <GroupBoxComponent name={"Test"} />;
39+
const grouping = <GroupBoxComponent name={"Test"} styleOpt={1} />;
1740
const { getByText } = render(grouping);
1841
expect(getByText("Test")).toBeInTheDocument();
1942
});

src/ui/widgets/GroupBox/groupBox.tsx

Lines changed: 84 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,33 @@ import { Widget } from "../widget";
44
import { WidgetPropType } from "../widgetProps";
55
import { registerWidget } from "../register";
66
import {
7-
StringProp,
87
ChildrenPropOpt,
98
InferWidgetProps,
109
ColorPropOpt,
11-
BoolPropOpt
10+
BoolPropOpt,
11+
FontPropOpt,
12+
IntPropOpt,
13+
StringPropOpt
1214
} from "../propTypes";
15+
import { Font } from "../../../types/font";
16+
import { Color } from "../../../types/color";
17+
import Box from "@mui/material/Box";
18+
19+
const INNER_DIV_STYLE: CSSProperties = {
20+
position: "relative",
21+
overflow: "visible",
22+
color: "black"
23+
};
1324

1425
const GroupBoxProps = {
15-
name: StringProp,
26+
name: StringPropOpt,
1627
children: ChildrenPropOpt,
1728
backgroundColor: ColorPropOpt,
18-
compat: BoolPropOpt
29+
foregroundColor: ColorPropOpt,
30+
lineColor: ColorPropOpt,
31+
font: FontPropOpt,
32+
styleOpt: IntPropOpt,
33+
transparent: BoolPropOpt
1934
};
2035

2136
// Widget that renders a group-box style border showing the name prop.
@@ -24,53 +39,80 @@ const GroupBoxProps = {
2439
export const GroupBoxComponent = (
2540
props: InferWidgetProps<typeof GroupBoxProps>
2641
): JSX.Element => {
27-
const { compat = false } = props;
28-
// Manually render a group-box style border.
29-
const innerDivStyle: CSSProperties = {
30-
position: "relative",
31-
padding: "16px"
42+
const {
43+
backgroundColor = Color.fromRgba(240, 240, 240),
44+
foregroundColor = Color.fromRgba(0, 0, 0),
45+
lineColor = Color.fromRgba(0, 0, 0),
46+
font = new Font(16),
47+
styleOpt = 0,
48+
transparent = false
49+
} = props;
50+
51+
const outerDivStyle: CSSProperties = {
52+
width: "100%",
53+
height: "100%",
54+
position: "absolute",
55+
padding: "0px",
56+
boxSizing: "border-box"
57+
};
58+
59+
const boxStyle: CSSProperties = {
60+
width: "100%",
61+
height: "100%",
62+
padding: "0px",
63+
border: "1px solid " + lineColor.toString(),
64+
whiteSpace: "nowrap",
65+
overflow: "visible",
66+
backgroundColor: transparent ? "transparent" : backgroundColor.toString(),
67+
color: foregroundColor.toString(),
68+
...font.css()
3269
};
33-
// Specific styling to match the group boxes in opibuilder.
34-
if (compat) {
35-
innerDivStyle.padding = undefined;
36-
innerDivStyle.top = "16px";
37-
innerDivStyle.left = "16px";
38-
innerDivStyle.height = "calc(100% - 32px)";
39-
innerDivStyle.width = "calc(100% - 32px)";
40-
innerDivStyle.overflow = "hidden";
70+
71+
if (styleOpt === 0) {
72+
// Typical group box with label
73+
outerDivStyle.padding = "10px";
74+
outerDivStyle.paddingTop = "0px";
75+
boxStyle.paddingLeft = "8px";
76+
} else if (styleOpt === 3) {
77+
// No groupbox
78+
boxStyle.border = "none";
79+
}
80+
81+
let name = "";
82+
if (props.name !== undefined) {
83+
name = props.name;
4184
}
42-
// Dimensions match those in the opibuilder groupbox borders.
85+
4386
return (
44-
<div
45-
style={{
46-
width: "100%",
47-
height: "100%",
48-
outline: "1px dotted black",
49-
outlineOffset: "-7px",
50-
backgroundColor: "transparent"
51-
}}
52-
>
53-
<div
54-
style={{
55-
position: "absolute",
56-
top: "0",
57-
left: "20px",
58-
fontSize: "13px",
59-
padding: "0 2px 0 2px",
60-
backgroundColor:
61-
props.backgroundColor?.toString() ?? "rgb(200,200,200)"
62-
}}
63-
>
64-
{props.name}
65-
</div>
66-
<div style={innerDivStyle}>{props.children}</div>
87+
<div style={outerDivStyle}>
88+
<Box component="fieldset" sx={boxStyle}>
89+
{styleOpt === 1 ? (
90+
<div
91+
style={{
92+
height: "20px",
93+
width: "100%",
94+
backgroundColor: lineColor.toString(),
95+
...font.css(),
96+
textAlign: "left",
97+
color: foregroundColor.toString()
98+
}}
99+
>
100+
{name}
101+
</div>
102+
) : (
103+
<></>
104+
)}
105+
{styleOpt === 0 ? <legend>{name}</legend> : <></>}
106+
<div style={INNER_DIV_STYLE}>{props.children}</div>
107+
</Box>
67108
</div>
68109
);
69110
};
70111

71112
const GroupBoxWidgetProps = {
72113
...WidgetPropType,
73-
name: StringProp,
114+
...GroupBoxProps,
115+
name: StringPropOpt,
74116
children: ChildrenPropOpt
75117
};
76118

0 commit comments

Comments
 (0)