Skip to content

Commit

Permalink
added property to set whether the outline is hull or rect
Browse files Browse the repository at this point in the history
  • Loading branch information
leandroberetta committed Oct 24, 2023
1 parent 8696649 commit 258a452
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 33 deletions.
1 change: 1 addition & 0 deletions packages/demo-app-ts/src/components/StyleGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ const StyleGroup: React.FunctionComponent<StyleGroupProps> = ({
collapsedWidth={collapsedWidth}
collapsedHeight={collapsedHeight}
showLabel={detailsLevel === ScaleDetailsLevel.high}
hulledOutline={true}
{...rest}
{...passedData}
>
Expand Down
2 changes: 2 additions & 0 deletions packages/module/src/components/groups/DefaultGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ interface DefaultGroupProps {
onContextMenu?: (e: React.MouseEvent) => void;
/** Flag indicating that the context menu for the node is currently open */
contextMenuOpen?: boolean;
/** Flag indicating whether to use hull layout or rect layout for expanded groups. Defaults to hull (true) */
hulledOutline?: boolean;
}

type DefaultGroupInnerProps = Omit<DefaultGroupProps, 'element'> & { element: Node };
Expand Down
79 changes: 46 additions & 33 deletions packages/module/src/components/groups/DefaultGroupExpanded.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
WithSelectionProps
} from '../../behavior';
import { CollapsibleGroupProps } from './types';
import Rect from '../../geom/Rect';

type DefaultGroupExpandedProps = {
className?: string;
Expand All @@ -41,6 +42,7 @@ type DefaultGroupExpandedProps = {
labelIconClass?: string; // Icon to show in label
labelIcon?: string;
labelIconPadding?: number;
hulledOutline?: boolean;
} & CollapsibleGroupProps & WithDragNodeProps & WithSelectionProps & WithDndDropProps & WithContextMenuProps;

type PointWithSize = [number, number, number];
Expand Down Expand Up @@ -96,7 +98,8 @@ const DefaultGroupExpanded: React.FunctionComponent<DefaultGroupExpandedProps> =
labelIconClass,
labelIcon,
labelIconPadding,
onCollapseChange
onCollapseChange,
hulledOutline,
}) => {
const [hovered, hoverRef] = useHover();
const [labelHover, labelHoverRef] = useHover();
Expand All @@ -107,6 +110,8 @@ const DefaultGroupExpanded: React.FunctionComponent<DefaultGroupExpandedProps> =
const outlineRef = useCombineRefs(dndDropRef, anchorRef);
const labelLocation = React.useRef<PointWithSize>();
const pathRef = React.useRef<string>();
const boxRef = React.useRef<Rect | null>(null);
const nodeElement = element as Node;

let parent = element.getParent();
let altGroup = false;
Expand All @@ -118,40 +123,47 @@ const DefaultGroupExpanded: React.FunctionComponent<DefaultGroupExpandedProps> =
// cast to number and coerce
const padding = maxPadding(element.getStyle<NodeStyle>().padding ?? 17);
const hullPadding = (point: PointWithSize | PointTuple) => (point[2] || 0) + padding;

if (!droppable || !pathRef.current || !labelLocation.current) {
const children = element.getNodes().filter(c => c.isVisible());
if (children.length === 0) {
return null;
}
const points: (PointWithSize | PointTuple)[] = [];
_.forEach(children, c => {
if (c.getNodeShape() === NodeShape.circle) {
const bounds = c.getBounds();
const { width, height } = bounds;
const { x, y } = bounds.getCenter();
const radius = Math.max(width, height) / 2;
points.push([x, y, radius] as PointWithSize);
} else {
// add all 4 corners
const { width, height, x, y } = c.getBounds();
points.push([x, y, 0] as PointWithSize);
points.push([x + width, y, 0] as PointWithSize);
points.push([x, y + height, 0] as PointWithSize);
points.push([x + width, y + height, 0] as PointWithSize);

if (hulledOutline) {
if (!droppable || !pathRef.current || !labelLocation.current) {
const children = element.getNodes().filter(c => c.isVisible());
if (children.length === 0) {
return null;
}
const points: (PointWithSize | PointTuple)[] = [];
_.forEach(children, c => {
if (c.getNodeShape() === NodeShape.circle) {
const bounds = c.getBounds();
const { width, height } = bounds;
const { x, y } = bounds.getCenter();
const radius = Math.max(width, height) / 2;
points.push([x, y, radius] as PointWithSize);
} else {
// add all 4 corners
const { width, height, x, y } = c.getBounds();
points.push([x, y, 0] as PointWithSize);
points.push([x + width, y, 0] as PointWithSize);
points.push([x, y + height, 0] as PointWithSize);
points.push([x + width, y + height, 0] as PointWithSize);
}
});
const hullPoints: (PointWithSize | PointTuple)[] =
points.length > 2 ? polygonHull(points as PointTuple[]) : (points as PointTuple[]);
if (!hullPoints) {
return null;
}
});
const hullPoints: (PointWithSize | PointTuple)[] =
points.length > 2 ? polygonHull(points as PointTuple[]) : (points as PointTuple[]);
if (!hullPoints) {
return null;
}

// change the box only when not dragging
pathRef.current = hullPath(hullPoints as PointTuple[], hullPadding);
// change the box only when not dragging
pathRef.current = hullPath(hullPoints as PointTuple[], hullPadding);

// Compute the location of the group label.
labelLocation.current = computeLabelLocation(hullPoints as PointWithSize[]);
// Compute the location of the group label.
labelLocation.current = computeLabelLocation(hullPoints as PointWithSize[]);
}
} else {
if (!droppable || !boxRef.current) {
// change the box only when not dragging
boxRef.current = nodeElement.getBounds();
}
}

const groupClassName = css(
Expand All @@ -177,7 +189,8 @@ const DefaultGroupExpanded: React.FunctionComponent<DefaultGroupExpandedProps> =
<g ref={labelHoverRef} onContextMenu={onContextMenu} onClick={onSelect} className={groupClassName}>
<Layer id={GROUPS_LAYER}>
<g ref={refs} onContextMenu={onContextMenu} onClick={onSelect} className={innerGroupClassName}>
<path ref={outlineRef} className={styles.topologyGroupBackground} d={pathRef.current} />
{hulledOutline && <path ref={outlineRef} className={styles.topologyGroupBackground} d={pathRef.current} />}
{!hulledOutline && <rect ref={outlineRef} className={styles.topologyGroupBackground} x={boxRef.current.x} y={boxRef.current.y} width={boxRef.current.width} height={boxRef.current.height}/>}
</g>
</Layer>
{showLabel && (label || element.getLabel()) && (
Expand Down

0 comments on commit 258a452

Please sign in to comment.