in packages/boxed-expression-component/src/expressions/FunctionExpression/JavaFunctionExpression.tsx [73:465]
export function JavaFunctionExpression({
functionExpression,
isNested,
}: {
functionExpression: Normalized<BoxedFunctionJava>;
isNested: boolean;
}) {
const { i18n } = useBoxedExpressionEditorI18n();
const { expressionHolderId, widthsById, isReadOnly } = useBoxedExpressionEditor();
const { setExpression, setWidthsById } = useBoxedExpressionEditorDispatch();
const getClassContextEntry = useCallback((c: Normalized<DMN15__tContext>) => {
return c.contextEntry?.find(({ variable }) => variable?.["@_name"] === "class");
}, []);
const getVariableContextEntry = useCallback((c: Normalized<DMN15__tContext>) => {
return c.contextEntry?.find(({ variable }) => variable?.["@_name"] === "method signature");
}, []);
const id = functionExpression["@_id"]!;
const widths = useMemo(() => widthsById.get(id) ?? [], [id, widthsById]);
const getClassAndMethodNamesWidth = useCallback((widths: number[]) => {
return widths[JAVA_FUNCTION_EXPRESSION_VALUES_COLUMN_WIDTH_INDEX] ?? JAVA_FUNCTION_EXPRESSION_VALUES_MIN_WIDTH;
}, []);
const classAndMethodNamesWidth = useMemo(
() => getClassAndMethodNamesWidth(widths),
[getClassAndMethodNamesWidth, widths]
);
const setClassAndMethodNamesWidth = useCallback(
(newWidthAction: React.SetStateAction<number | undefined>) => {
setWidthsById(({ newMap }) => {
const prev = newMap.get(id) ?? [];
const newWidth =
typeof newWidthAction === "function" ? newWidthAction(getClassAndMethodNamesWidth(prev)) : newWidthAction;
if (newWidth) {
const minSize = JAVA_FUNCTION_EXPRESSION_VALUES_COLUMN_WIDTH_INDEX + 1;
const newValues = [...prev];
newValues.push(
...Array<number>(Math.max(0, minSize - newValues.length)).fill(JAVA_FUNCTION_EXPRESSION_VALUES_MIN_WIDTH)
);
newValues.splice(JAVA_FUNCTION_EXPRESSION_VALUES_COLUMN_WIDTH_INDEX, 1, newWidth);
newMap.set(id, newValues);
}
});
},
[getClassAndMethodNamesWidth, id, setWidthsById]
);
const parametersColumnHeader = useFunctionExpressionParametersColumnHeader(
functionExpression.formalParameter,
isReadOnly ?? false
);
const parametersId = useMemo(
() => (functionExpression["@_id"] ? `${functionExpression["@_id"]}-parameters` : "parameters"),
[functionExpression]
);
const beeTableColumns = useMemo<ReactTable.Column<JAVA_ROWTYPE>[]>(() => {
return [
{
accessor: expressionHolderId as any, // FIXME: https://github.com/apache/incubator-kie-issues/issues/169
label: functionExpression["@_label"] ?? DEFAULT_EXPRESSION_VARIABLE_NAME,
dataType: functionExpression["@_typeRef"] ?? DmnBuiltInDataType.Undefined,
isRowIndexColumn: false,
width: undefined,
columns: [
{
headerCellElement: parametersColumnHeader,
accessor: parametersId as any,
label: "parameters",
isRowIndexColumn: false,
dataType: undefined as any,
width: undefined,
columns: [
{
label: "label",
accessor: "label" as any,
dataType: undefined as any,
isRowIndexColumn: false,
isWidthPinned: true,
isWidthConstant: true,
width: JAVA_FUNCTION_EXPRESSION_LABEL_MIN_WIDTH,
minWidth: JAVA_FUNCTION_EXPRESSION_LABEL_MIN_WIDTH,
},
{
label: "value",
accessor: "value" as any,
dataType: undefined as any,
isRowIndexColumn: false,
width: classAndMethodNamesWidth,
setWidth: setClassAndMethodNamesWidth,
minWidth: JAVA_FUNCTION_EXPRESSION_VALUES_MIN_WIDTH,
},
],
},
],
},
];
}, [
expressionHolderId,
functionExpression,
classAndMethodNamesWidth,
parametersColumnHeader,
setClassAndMethodNamesWidth,
parametersId,
]);
const headerVisibility = useMemo(() => {
return isNested ? BeeTableHeaderVisibility.SecondToLastLevel : BeeTableHeaderVisibility.AllLevels;
}, [isNested]);
const onColumnUpdates = useCallback(
([{ name, typeRef }]: BeeTableColumnUpdate<JAVA_ROWTYPE>[]) => {
const expressionChangedArgs: ExpressionChangedArgs = {
action: Action.VariableChanged,
variableUuid: expressionHolderId,
typeChange:
typeRef !== functionExpression["@_typeRef"]
? {
from: functionExpression["@_typeRef"] ?? "",
to: typeRef,
}
: undefined,
nameChange:
name !== functionExpression["@_label"]
? {
from: functionExpression["@_label"] ?? "",
to: name,
}
: undefined,
};
setExpression({
setExpressionAction: (prev: Normalized<BoxedFunctionJava>) => {
// Do not inline this variable for type safety. See https://github.com/microsoft/TypeScript/issues/241
const ret: Normalized<BoxedFunctionJava> = {
...prev,
"@_label": name,
"@_typeRef": typeRef,
};
return ret;
},
expressionChangedArgs,
});
},
[expressionHolderId, functionExpression, setExpression]
);
// It is always a Context
const context = functionExpression.expression! as Normalized<DMN15__tContext>;
const clazz = getClassContextEntry(context);
const method = getVariableContextEntry(context);
const beeTableOperationConfig = useMemo<BeeTableOperationConfig>(() => {
return [
{
group: i18n.terms.selection.toUpperCase(),
items: [{ name: i18n.terms.copy, type: BeeTableOperation.SelectionCopy }],
},
{
group: i18n.function.toUpperCase(),
items: [{ name: i18n.rowOperations.reset, type: BeeTableOperation.RowReset }],
},
];
}, [i18n]);
const beeTableRows = useMemo<JAVA_ROWTYPE[]>(() => {
return [
{
label: "Class name",
value: (clazz?.expression as DMN15__tLiteralExpression | undefined)?.text?.__$$text ?? "",
},
{
label: "Method signature",
value: (method?.expression as DMN15__tLiteralExpression | undefined)?.text?.__$$text ?? "",
},
];
}, [clazz?.expression, method?.expression]);
const controllerCell = useFunctionExpressionControllerCell(BoxedFunctionKind.Java);
const getRowKey = useCallback((r: ReactTable.Row<JAVA_ROWTYPE>) => {
return r.id;
}, []);
const onRowReset = useCallback(() => {
setExpression({
setExpressionAction: (prev: Normalized<BoxedFunctionJava>) => {
// Do not inline this variable for type safety. See https://github.com/microsoft/TypeScript/issues/241
const ret: Normalized<BoxedFunctionJava> = {
...prev,
expression: undefined!,
};
return ret;
},
expressionChangedArgs: { action: Action.RowReset, rowIndex: 0 },
});
}, [setExpression]);
/// //////////////////////////////////////////////////////
/// ///////////// RESIZING WIDTHS ////////////////////////
/// //////////////////////////////////////////////////////
const columns = useMemo(
() => [
{
minWidth: JAVA_FUNCTION_EXPRESSION_LABEL_MIN_WIDTH,
width: JAVA_FUNCTION_EXPRESSION_LABEL_MIN_WIDTH,
isFrozen: true,
},
{
minWidth: JAVA_FUNCTION_EXPRESSION_VALUES_MIN_WIDTH,
width: classAndMethodNamesWidth,
},
],
[classAndMethodNamesWidth]
);
const { onColumnResizingWidthChange, isPivoting, columnResizingWidths } = usePublishedBeeTableResizableColumns(
functionExpression["@_id"]!,
columns.length,
true
);
const beeTableRef = React.useRef<BeeTableRef>(null);
useApportionedColumnWidthsIfNestedTable(
beeTableRef,
isPivoting,
isNested,
JAVA_FUNCTION_EXPRESSION_EXTRA_WIDTH,
columns,
columnResizingWidths,
useMemo(() => [], []) // rows
);
useEffect(() => {
beeTableRef.current?.updateColumnResizingWidths(
new Map([[1, { isPivoting: false, value: JAVA_FUNCTION_EXPRESSION_LABEL_MIN_WIDTH }]])
);
}, []);
/// //////////////////////////////////////////////////////
const cellComponentByColumnAccessor: BeeTableProps<JAVA_ROWTYPE>["cellComponentByColumnAccessor"] = useMemo(
() => ({
label: (props) => <JavaFunctionExpressionLabelCell {...props} />,
}),
[]
);
const onCellUpdates = useCallback(
(cellUpdates: BeeTableCellUpdate<JAVA_ROWTYPE>[]) => {
for (const u of cellUpdates) {
const context: Normalized<DMN15__tContext> = functionExpression.expression!;
const clazz = getClassContextEntry(context) ?? {
"@_id": generateUuid(),
expression: {
__$$element: "literalExpression",
"@_id": generateUuid(),
text: { __$$text: "" },
},
variable: {
"@_id": generateUuid(),
"@_name": "class",
},
};
const method = getVariableContextEntry(context) ?? {
"@_id": generateUuid(),
expression: {
__$$element: "literalExpression",
"@_id": generateUuid(),
text: { __$$text: "" },
},
variable: {
"@_id": generateUuid(),
"@_name": "method signature",
},
};
// Class
if (u.rowIndex === 0) {
setExpression({
setExpressionAction: (prev: Normalized<BoxedFunctionJava>) => {
// Do not inline this variable for type safety. See https://github.com/microsoft/TypeScript/issues/241
const ret: Normalized<BoxedFunction> = {
...prev,
expression: {
__$$element: "context",
...context,
contextEntry: [
{
...clazz,
expression: {
...clazz.expression,
__$$element: "literalExpression",
text: {
__$$text: u.value,
},
},
},
method,
],
},
};
return ret;
},
expressionChangedArgs: {
action: Action.LiteralTextExpressionChanged,
from: clazz.expression.__$$element === "literalExpression" ? clazz.expression.text?.__$$text ?? "" : "",
to: u.value,
},
});
}
// Method
else if (u.rowIndex === 1) {
setExpression({
setExpressionAction: (prev: Normalized<BoxedFunctionJava>) => {
// Do not inline this variable for type safety. See https://github.com/microsoft/TypeScript/issues/241
const ret: Normalized<BoxedFunction> = {
...prev,
expression: {
__$$element: "context",
...context,
contextEntry: [
clazz,
{
...method,
expression: {
...method.expression,
__$$element: "literalExpression",
"@_id": method.expression["@_id"] ?? generateUuid(),
text: {
__$$text: u.value,
},
},
},
],
},
};
return ret;
},
expressionChangedArgs: {
action: Action.LiteralTextExpressionChanged,
from: method.expression.__$$element === "literalExpression" ? method.expression.text?.__$$text ?? "" : "",
to: u.value,
},
});
}
}
},
[functionExpression.expression, getClassContextEntry, getVariableContextEntry, setExpression]
);
const allowedOperations = useCallback((conditions: BeeTableContextMenuAllowedOperationsConditions) => {
return [BeeTableOperation.SelectionCopy];
}, []);
return (
<div className={`function-expression ${functionExpression["@_id"]}`}>
<BeeTable<JAVA_ROWTYPE>
forwardRef={beeTableRef}
isReadOnly={isReadOnly}
onColumnResizingWidthChange={onColumnResizingWidthChange}
resizerStopBehavior={ResizerStopBehavior.SET_WIDTH_WHEN_SMALLER}
operationConfig={beeTableOperationConfig}
allowedOperations={allowedOperations}
onColumnUpdates={onColumnUpdates}
getRowKey={getRowKey}
onRowReset={onRowReset}
onCellUpdates={onCellUpdates}
columns={beeTableColumns}
rows={beeTableRows}
headerLevelCountForAppendingRowIndexColumn={2}
skipLastHeaderGroup={true}
cellComponentByColumnAccessor={cellComponentByColumnAccessor}
headerVisibility={headerVisibility}
controllerCell={controllerCell}
shouldRenderRowIndexColumn={true}
shouldShowRowsInlineControls={false}
shouldShowColumnsInlineControls={false}
/>
</div>
);
}