From 38479ea5735bb2ff57439910f2c16d4e3b0ae2a6 Mon Sep 17 00:00:00 2001
From: NatLeung96
Date: Wed, 9 Apr 2025 10:29:29 +0100
Subject: [PATCH 01/18] Added styling
---
src/ui/widgets/MenuButton/menuButton.tsx | 71 +++++++++++++++++++-----
1 file changed, 57 insertions(+), 14 deletions(-)
diff --git a/src/ui/widgets/MenuButton/menuButton.tsx b/src/ui/widgets/MenuButton/menuButton.tsx
index bd2fd48a..3abbd09d 100644
--- a/src/ui/widgets/MenuButton/menuButton.tsx
+++ b/src/ui/widgets/MenuButton/menuButton.tsx
@@ -7,7 +7,9 @@ import {
BoolPropOpt,
ColorPropOpt,
InferWidgetProps,
- StringPropOpt
+ StringArrayPropOpt,
+ StringPropOpt,
+ FontPropOpt
} from "../propTypes";
import { DType } from "../../../types/dtypes";
import {
@@ -21,6 +23,9 @@ import {
import { FileContext } from "../../../misc/fileContext";
import { Border } from "../../../types/border";
import { Color } from "../../../types/color";
+import { MenuItem, Select } from "@mui/material";
+import { diamondTheme } from "../../../diamondTheme";
+import { Font } from "../../../types";
export interface MenuButtonProps {
connected: boolean;
@@ -35,6 +40,8 @@ export interface MenuButtonProps {
foregroundColor?: Color;
backgroundColor?: Color;
border?: Border;
+ font?: Font;
+ items?: string[];
}
export const MenuButtonComponent = (props: MenuButtonProps): JSX.Element => {
@@ -45,7 +52,8 @@ export const MenuButtonComponent = (props: MenuButtonProps): JSX.Element => {
actionsFromPv = true,
itemsFromPv = false,
pvName,
- label
+ label,
+ items = ["Item 1", "Item 2"]
} = props;
const fromPv = actionsFromPv || itemsFromPv;
let actions: WidgetAction[] = props.actions?.actions || [];
@@ -95,15 +103,19 @@ export const MenuButtonComponent = (props: MenuButtonProps): JSX.Element => {
cursor: disabled ? "not-allowed" : "default"
};
- const mappedOptions = options.map((text, index): JSX.Element => {
+ const mappedOptions = items.map((text, index): JSX.Element => {
return (
-
+
);
});
@@ -116,18 +128,43 @@ export const MenuButtonComponent = (props: MenuButtonProps): JSX.Element => {
}
return (
-
+
);
};
@@ -143,6 +180,8 @@ export const SmartMenuButton = (props: {
foregroundColor?: Color;
backgroundColor?: Color;
border?: Border;
+ items?: string[];
+ font?: Font;
}): JSX.Element => {
const files = useContext(FileContext);
// Function to send the value on to the PV
@@ -164,6 +203,8 @@ export const SmartMenuButton = (props: {
label={props.label}
foregroundColor={props.foregroundColor}
backgroundColor={props.backgroundColor}
+ items={props.items}
+ font={props.font}
/>
);
};
@@ -174,7 +215,9 @@ const MenuButtonWidgetProps = {
itemsFromPv: BoolPropOpt,
label: StringPropOpt,
foregroundColor: ColorPropOpt,
- backgroundColor: ColorPropOpt
+ backgroundColor: ColorPropOpt,
+ items: StringArrayPropOpt,
+ font: FontPropOpt
};
export const MenuButton = (
From 0a5e18e20d8191a3bde1977c1127425b8e107a78 Mon Sep 17 00:00:00 2001
From: NatLeung96
Date: Wed, 9 Apr 2025 16:52:49 +0100
Subject: [PATCH 02/18] Setup placeholder until option is clicked
---
src/ui/widgets/MenuButton/menuButton.tsx | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/src/ui/widgets/MenuButton/menuButton.tsx b/src/ui/widgets/MenuButton/menuButton.tsx
index 3abbd09d..a7b1e706 100644
--- a/src/ui/widgets/MenuButton/menuButton.tsx
+++ b/src/ui/widgets/MenuButton/menuButton.tsx
@@ -1,4 +1,4 @@
-import React, { CSSProperties, useContext } from "react";
+import React, { CSSProperties, useContext, useState } from "react";
import { commonCss, Widget } from "../widget";
import { PVWidgetPropType } from "../widgetProps";
@@ -106,9 +106,9 @@ export const MenuButtonComponent = (props: MenuButtonProps): JSX.Element => {
const mappedOptions = items.map((text, index): JSX.Element => {
return (
`;
diff --git a/src/ui/widgets/Label/label.module.css b/src/ui/widgets/Label/label.module.css
deleted file mode 100644
index 3de03a30..00000000
--- a/src/ui/widgets/Label/label.module.css
+++ /dev/null
@@ -1,15 +0,0 @@
-.Label {
- left: 0%;
- top: 0%;
- height: 100%;
- width: 100%;
- display: flex;
- padding: 0;
- background-color: #ffffff;
- font: 14px helvetica, sans-serif;
- text-align: center;
- justify-content: center;
- align-items: center;
- white-space: pre;
- overflow: hidden;
-}
\ No newline at end of file
diff --git a/src/ui/widgets/Label/label.test.tsx b/src/ui/widgets/Label/label.test.tsx
index 0274e94e..10fae2f0 100644
--- a/src/ui/widgets/Label/label.test.tsx
+++ b/src/ui/widgets/Label/label.test.tsx
@@ -14,15 +14,9 @@ describe("", (): void => {
});
test("it handles transparent prop", (): void => {
- render();
- const label = screen.getByText("hello");
- // The text is in the span, not the parent div.
- if (label.parentElement && "style" in label.parentElement) {
- expect(label.parentElement.style).toHaveProperty(
- "backgroundColor",
- "transparent"
- );
- }
- expect.assertions(1);
+ const { asFragment } = render(
+
+ );
+ expect(asFragment()).toMatchSnapshot();
});
});
diff --git a/src/ui/widgets/Label/label.tsx b/src/ui/widgets/Label/label.tsx
index 64be7186..0cb4966f 100644
--- a/src/ui/widgets/Label/label.tsx
+++ b/src/ui/widgets/Label/label.tsx
@@ -1,7 +1,6 @@
-import React, { CSSProperties } from "react";
+import React from "react";
-import classes from "./label.module.css";
-import { Widget, commonCss } from "../widget";
+import { Widget } from "../widget";
import { WidgetPropType } from "../widgetProps";
import { registerWidget } from "../register";
import {
@@ -15,6 +14,8 @@ import {
FloatPropOpt,
MacrosPropOpt
} from "../propTypes";
+import { Typography as MuiTypography, styled } from "@mui/material";
+import { diamondTheme } from "../../../diamondTheme";
const LabelProps = {
macros: MacrosPropOpt,
@@ -28,7 +29,7 @@ const LabelProps = {
foregroundColor: ColorPropOpt,
backgroundColor: ColorPropOpt,
border: BorderPropOpt,
- rotationAngle: FloatPropOpt,
+ rotationStep: FloatPropOpt,
wrapWords: BoolPropOpt
};
@@ -37,65 +38,66 @@ const LabelWidgetProps = {
...WidgetPropType
};
+const Typography = styled(MuiTypography)({
+ width: "100%",
+ height: "100%",
+ display: "flex",
+ overflow: "hidden",
+ padding: 0
+});
+
export const LabelComponent = (
props: InferWidgetProps
): JSX.Element => {
// Default labels to transparent.
- const editedProps = {
- ...props,
- transparent: props.transparent ?? true
- };
- const style: CSSProperties = commonCss(editedProps);
const {
+ transparent = true,
+ foregroundColor = diamondTheme.palette.primary.contrastText,
textAlign = "left",
textAlignV = "top",
text = "",
- rotationAngle,
- wrapWords
+ rotationStep = 0,
+ wrapWords = true
} = props;
- const className = props.className ?? `Label ${classes.Label}`;
+ const backgroundColor = transparent
+ ? "transparent"
+ : (props.backgroundColor?.toString() ?? diamondTheme.palette.primary.main);
+ const font = props.font?.css() ?? diamondTheme.typography;
+
// Since display is "flex", use "flex-start" and "flex-end" to align
// the content.
let alignment = "center";
if (textAlign === "left") {
alignment = "flex-start";
- if (wrapWords) {
- style["textAlign"] = "left";
- }
} else if (textAlign === "right") {
alignment = "flex-end";
- if (wrapWords) {
- style["textAlign"] = "right";
- }
- } else {
- if (wrapWords) {
- style["textAlign"] = "center";
- }
}
- style["justifyContent"] = alignment;
- style["cursor"] = "default";
+
let alignmentV = "center";
if (textAlignV === "top") {
alignmentV = "flex-start";
} else if (textAlignV === "bottom") {
alignmentV = "flex-end";
}
- style["alignItems"] = alignmentV;
- let transform = undefined;
- if (rotationAngle) {
- transform = `rotate(${rotationAngle}deg)`;
- }
-
- if (wrapWords) {
- style["wordBreak"] = "break-word";
- style["whiteSpace"] = "break-spaces";
- }
// Simple component to display text - defaults to black text and dark grey background
return (
-
- {text}
-
+
+ {text}
+
);
};
diff --git a/src/ui/widgets/Readback/readback.tsx b/src/ui/widgets/Readback/readback.tsx
index 82162193..7b9fa5f4 100644
--- a/src/ui/widgets/Readback/readback.tsx
+++ b/src/ui/widgets/Readback/readback.tsx
@@ -34,7 +34,7 @@ const ReadbackProps = {
foregroundColor: ColorPropOpt,
backgroundColor: ColorPropOpt,
border: BorderPropOpt,
- rotationAngle: FloatPropOpt,
+ rotationStep: FloatPropOpt,
visible: BoolPropOpt,
wrapWords: BoolPropOpt
};
@@ -60,7 +60,7 @@ export const ReadbackComponent = (
textAlignV = "top",
showUnits = false,
precisionFromPv = false,
- rotationAngle,
+ rotationStep,
visible,
wrapWords = false
} = props;
@@ -140,7 +140,7 @@ export const ReadbackComponent = (
foregroundColor={foregroundColor}
backgroundColor={backgroundColor}
border={border}
- rotationAngle={rotationAngle}
+ rotationStep={rotationStep}
visible={visible}
wrapWords={wrapWords}
>
diff --git a/src/ui/widgets/Symbol/__snapshots__/symbol.test.tsx.snap b/src/ui/widgets/Symbol/__snapshots__/symbol.test.tsx.snap
index 27183781..55519cea 100644
--- a/src/ui/widgets/Symbol/__snapshots__/symbol.test.tsx.snap
+++ b/src/ui/widgets/Symbol/__snapshots__/symbol.test.tsx.snap
@@ -82,14 +82,11 @@ exports[` from .opi file > matches snapshot 1`] = `
-
-
- Fake value
-
-
+ Fake value
+
From ad7b5be78afb704df7f86038508cec70b9fe34f1 Mon Sep 17 00:00:00 2001
From: NatLeung96 <84187731+NatLeung96@users.noreply.github.com>
Date: Wed, 9 Apr 2025 08:48:21 +0100
Subject: [PATCH 05/18] Replaced Checkbox with MUI Checkbox (#89)
* Replaced Checkbox with MUI Checkbox
* Removed ThemeProvider and added additional styling to FormControlLabel
* Moved static styling to styled API. Not-allowed cursor when widget is disabled. Added font styling.
* Removed padding
* Removed padding and fixed alignments
---
src/ui/widgets/Checkbox/checkbox.tsx | 84 ++++++++++++++++++++--------
1 file changed, 60 insertions(+), 24 deletions(-)
diff --git a/src/ui/widgets/Checkbox/checkbox.tsx b/src/ui/widgets/Checkbox/checkbox.tsx
index 2570f3fa..734c5cf7 100644
--- a/src/ui/widgets/Checkbox/checkbox.tsx
+++ b/src/ui/widgets/Checkbox/checkbox.tsx
@@ -1,23 +1,53 @@
import React, { useState } from "react";
-import { commonCss, Widget } from "../widget";
+import { Widget } from "../widget";
import {
InferWidgetProps,
StringPropOpt,
FloatPropOpt,
FontPropOpt,
- ColorPropOpt
+ ColorPropOpt,
+ BoolPropOpt
} from "../propTypes";
import { PVComponent, PVWidgetPropType } from "../widgetProps";
import { registerWidget } from "../register";
+import {
+ FormControlLabel as MuiFormControlLabel,
+ Checkbox as MuiCheckbox,
+ styled
+} from "@mui/material";
+import { diamondTheme } from "../../../diamondTheme";
export const CheckboxProps = {
label: StringPropOpt,
width: FloatPropOpt,
height: FloatPropOpt,
font: FontPropOpt,
- foregroundColor: ColorPropOpt
+ foregroundColor: ColorPropOpt,
+ enabled: BoolPropOpt
};
+const FormControlLabel = styled(MuiFormControlLabel)({
+ "&.MuiFormControlLabel-root": {
+ height: "100%",
+ width: "100%",
+ maxHeight: "100%",
+ maxWidth: "100%",
+ display: "flex",
+ justifyContent: "flex-start",
+ alignItems: "center",
+ cursor: "pointer",
+ whiteSpace: "nowrap",
+ wordBreak: "break-word",
+ overflow: "hidden",
+ padding: 0,
+ margin: 0
+ },
+ "&.Mui-disabled": {
+ cursor: "not-allowed",
+ pointerEvents: "all !important"
+ }
+});
+
export type CheckboxComponentProps = InferWidgetProps &
PVComponent;
@@ -31,33 +61,39 @@ export type CheckboxComponentProps = InferWidgetProps &
export const CheckboxComponent = (
props: CheckboxComponentProps
): JSX.Element => {
- const style = {
- ...commonCss(props as any),
- display: "flex",
- alignItems: "center",
- cursor: "pointer"
- };
-
+ const { enabled = true } = props;
const [checked, setChecked] = useState(true);
- const toggle = (): void => {
+ const handleChange = (): void => {
setChecked(!checked);
};
- const inp = (
-
- );
return (
-
+
+ }
+ label={props.label}
+ />
);
};
From 66eb3159b4153b63110669931c185fa30820acdb Mon Sep 17 00:00:00 2001
From: NatLeung96
Date: Thu, 10 Apr 2025 13:02:05 +0100
Subject: [PATCH 06/18] Tidied nested for-loop
---
src/ui/widgets/MenuButton/menuButton.tsx | 45 ++++++++++++------------
1 file changed, 22 insertions(+), 23 deletions(-)
diff --git a/src/ui/widgets/MenuButton/menuButton.tsx b/src/ui/widgets/MenuButton/menuButton.tsx
index a7b1e706..e3e6e742 100644
--- a/src/ui/widgets/MenuButton/menuButton.tsx
+++ b/src/ui/widgets/MenuButton/menuButton.tsx
@@ -68,31 +68,29 @@ export const MenuButtonComponent = (props: MenuButtonProps): JSX.Element => {
// Show 0 by default where there is only one option
let displayIndex = 0;
- if (fromPv && pvName) {
- if (!connected || value === null) {
- disabled = true;
- } else if (value?.display?.choices) {
- options = options.concat(value?.display?.choices);
- actions = options.map((option, i) => {
- const writePv: WritePv = {
- type: WRITE_PV,
- writePvInfo: {
- pvName: pvName,
- value: i
- }
- };
- return writePv;
- });
- displayIndex = (value.getDoubleValue() ?? 0) + displayOffset;
- } else {
- disabled = true;
- }
- } else {
+ if (!(fromPv && pvName)) {
options = options.concat(
actions.map(action => {
return getActionDescription(action);
})
);
+ } else if (!connected || value === null) {
+ disabled = true;
+ } else if (value?.display?.choices) {
+ options = options.concat(value?.display?.choices);
+ actions = options.map((option, i) => {
+ const writePv: WritePv = {
+ type: WRITE_PV,
+ writePvInfo: {
+ pvName: pvName,
+ value: i
+ }
+ };
+ return writePv;
+ });
+ displayIndex = (value.getDoubleValue() ?? 0) + displayOffset;
+ } else {
+ disabled = true;
}
const style: CSSProperties = {
@@ -107,8 +105,8 @@ export const MenuButtonComponent = (props: MenuButtonProps): JSX.Element => {
return (