Totally understand… I think it would take a great deal of time to reproduce a sample. We will keep looking into the issue and come to that as a last resort. In the mean time, I can provide some snippets in the event that is helpful…
Here is how we are initializing the diagram:
const dia = $(go.Diagram, {
allowClipboard: false,
allowCopy: false,
allowDelete: true,
allowDragOut: false,
allowDrop: false,
allowGroup: false,
allowInsert: false,
allowLink: false,
allowMove: true,
allowRelink: false,
allowReshape: false,
allowResize: false,
allowRotate: true,
allowSelect: true,
allowTextEdit: false,
allowUndo: true,
allowUngroup: false,
contentAlignment: go.Spot.Center,
contextMenuTool: new ContextMenuZoomTool(this.contextMenuPositioner, this.editModeService),
initialAutoScale: go.AutoScale.Uniform,
scrollMode: go.ScrollMode.Document,
'animationManager.isEnabled': false,
padding: Constants.DIAGRAM_PADDING,
'dragSelectingTool.delay': 250,
'toolManager.toolTipDuration': Number.POSITIVE_INFINITY,
draggingTool: this.multiSelectionDraggingTool,
'undoManager.isEnabled': false,
'ChangedSelection': this.updateMultiSelectionPart,
"ModelChanged": e => {
if (e.isTransactionFinished) this.updateMultiSelectionPart()
},
skipsUndoManager: true,
model: new go.GraphLinksModel({
nodeKeyProperty: 'key',
linkKeyProperty: 'key', // IMPORTANT! must be defined for merges and data sync when using GraphLinksModel
skipsUndoManager: true
}),
});
dia.layout.isOngoing = false;
... listeners to follow
When a user right clicks a node, a context menu pops up above it allowing text resize as one of many edit options. When that data is updated from the context menu, we are updating the data as such:
editNodeProperty(nodeModifier: NodeModifier) {
const model = this.diagram?.model
this.diagram?.startTransaction(Constants.EDIT_NODE);
this.diagram?.selection.each(n => {
const node = this.diagram?.findNodeForData(n.part?.data);
if (node?.data.hasOwnProperty(nodeModifier.nodeKey)) {
model?.setDataProperty(node?.data, nodeModifier.nodeKey, nodeModifier.value);
}
})
this.diagram?.commitTransaction(Constants.EDIT_NODE);
}
The template for the node we are editing:
const gridNodeTemplate = go.GraphObject.make(
go.Node,
{
locationSpot: go.Spot.TopLeft,
rotationSpot: go.Spot.Center,
contextMenu: contextMenu(this.editModeService, this.contextMenuPositioner)
},
new go.Binding('location', 'location', (location) => new go.Point(location.item1, location.item2), (point: go.Point) => this.nodeHelperService.createLocation(point.x, point.y)),
new go.Binding('angle', 'rotationAngle').makeTwoWay(),
new go.Binding('background', 'fill', (fill) => this.colorService.convertColorStringTo(ColorFormat.Rgba, fill)),
new go.Binding('zOrder'),
new go.Binding('movable', 'editMode').ofModel(),
new go.Binding('selectable', 'editMode').ofModel(),
new go.Binding('rotatable', 'editMode').ofModel(),
new go.Binding('deletable', 'editMode').ofModel(),
go.GraphObject.make(
go.Panel,
'Table',
{
defaultAlignment: go.Spot.Left,
},
go.GraphObject.make(
go.Panel,
'TableRow',
{
isPanelMain: true,
alignment: go.Spot.Left,
toolTip: go.GraphObject.make(
go.Adornment,
new go.Binding('visible', 'toolTip', (toolTip?: ToolTipInfo) =>
this.tooltipHelperService.showToolTip(toolTip)
),
'Auto',
go.GraphObject.make(
go.Shape,
'RoundedRectangle',
{
// Set fixed width of 250 for the tooltip shape node
width: Constants.TOOLTIP_SHAPE_WIDTH,
},
new go.Binding('fill', 'theme', (theme: string) =>
this.apmThemeService.getThemeValue(ThemeConstants.colorFillCommonOverlay, theme)
).ofModel(),
new go.Binding('stroke', 'theme', (theme: string) =>
this.apmThemeService.getThemeValue(ThemeConstants.colorFillCtaSecondaryHover, theme)
).ofModel()
),
go.GraphObject.make(
go.Panel,
'Auto',
{
// Setting the padding here allows for padding between the TextBlock and the Shape
padding: new go.Margin(8, 12),
alignment: go.Spot.Left,
},
go.GraphObject.make(
go.TextBlock,
{
width: Constants.TOOLTIP_TEXTBLOCK_WIDTH,
alignment: go.Spot.Left,
textAlign: 'left',
},
new go.Binding('stroke', 'theme', (theme: string) =>
this.apmThemeService.getThemeValue(ThemeConstants.colorTextCommonInversePrimary, theme)
).ofModel(),
new go.Binding('text', 'toolTip', (toolTip?: ToolTipInfo) =>
this.tooltipHelperService.getToolTip(toolTip)
)
)
)
),
mouseHover: (e, obj) => this.tooltipHelperService.loadMeasurementPointPath(e, obj),
},
/**
* Description: In System1 you can configure the measurement view, that can hide/show the Point and Tag names. If `showName` is false in the get-hmi API results, this binding will hide the Point/Tag Names. See the Developer Notes for a visual breakdown.
* [GitHub Wiki - Grid Node Template]{@link https://github.com/BentlyNevada-bh/s1-hmi-lib/wiki/Developer-Notes#grid-node-template-information}
*
*/
new go.Binding('visible', 'showName'),
go.GraphObject.make(
go.Shape,
'lineV',
{
row: 0,
column: 0,
desiredSize: new go.Size(5, 32),
alignment: go.Spot.Center,
},
new go.Binding('angle', 'probeAngle'),
new go.Binding('visible', 'showAngle'),
new go.Binding('stroke', 'foreground', (foreground): go.Brush => {
const rgbaForeground = this.colorService.convertColorStringTo(ColorFormat.Rgba, foreground);
/**
* this is a custom brush that will display half the height of the lineV shape.
* This is used to display to probe angle.
*/
return go.GraphObject.make(go.Brush, 'Linear', {
0.0: rgbaForeground,
0.5: rgbaForeground,
// From 51% to 100% stroke is to be transparent
0.51: 'rgba(0,0,0,0)',
1.0: 'rgba(0,0,0,0)',
})
}
)
),
// Circle for Point-Tag Status Indicator
go.GraphObject.make(
go.Shape,
'Circle',
{
row: 0,
column: 0,
width: 18,
strokeWidth: 1,
margin: 8,
},
new go.Binding('fill', 'status'),
new go.Binding('stroke', 'status', (status) => (status !== Constants.TRANSPARENT ? status : 'grey'))
),
// Channel Block
go.GraphObject.make(
go.TextBlock,
new go.Binding('text', 'text'),
{ column: 1, columnSpan: 3, alignment: go.Spot.Left, margin: new go.Margin(0, 0, 0, 2) },
new go.Binding('stroke', 'foreground', (foreground: string) =>
this.colorService.convertColorStringTo(ColorFormat.Rgba, foreground)
),
new go.Binding(
'font',
'textInfo',
(textInfo: TextInfo) =>
`${textInfo.fontStyle} normal ${textInfo.fontWeight} ${textInfo.fontSize}px 'Noto Sans', sans-serif`
),
new go.Binding('isUnderline', 'fontDecoration', (fontDecoration: string) => fontDecoration === 'Underline'),
new go.Binding('isDeletable', 'editMode').ofModel(),
)
),
new go.Binding('itemArray', 'measurementInfo'),
new go.Binding('visible', 'isStubTable', (isStubTable: boolean) => !isStubTable),
{
itemTemplate: go.GraphObject.make(
go.Panel,
'TableRow',
{
toolTip: go.GraphObject.make(
go.Adornment,
new go.Binding('visible', 'toolTip', (toolTip?: ToolTipInfo) =>
this.tooltipHelperService.showToolTip(toolTip)
),
'Auto',
go.GraphObject.make(
go.Shape,
'RoundedRectangle',
{
// Set fixed width of 250 for the tooltip shape node
width: Constants.TOOLTIP_SHAPE_WIDTH,
},
new go.Binding('fill', 'theme', (theme: string) =>
this.apmThemeService.getThemeValue(ThemeConstants.colorFillCommonOverlay, theme)
).ofModel(),
new go.Binding('stroke', 'theme', (theme: string) =>
this.apmThemeService.getThemeValue(ThemeConstants.colorFillCtaSecondaryHover, theme)
).ofModel()
),
go.GraphObject.make(
go.Panel,
'Auto',
{
// Setting the padding here allows for padding between the TextBlock and the Shape
padding: new go.Margin(8, 12),
alignment: go.Spot.Left,
},
go.GraphObject.make(
go.TextBlock,
{
width: Constants.TOOLTIP_TEXTBLOCK_WIDTH,
alignment: go.Spot.Left,
textAlign: 'left',
},
new go.Binding('stroke', 'theme', (theme: string) =>
this.apmThemeService.getThemeValue(ThemeConstants.colorTextCommonInversePrimary, theme)
).ofModel(),
new go.Binding('text', 'toolTip', (toolTip?: ToolTipInfo) =>
this.tooltipHelperService.getToolTip(toolTip)
)
)
)
),
mouseHover: (e, obj) => this.tooltipHelperService.loadMeasurementValuePath(e, obj),
},
go.GraphObject.make(go.TextBlock, { column: 0, margin: new go.Margin(4, 0, 0, 0) }),
// Circle for Measurement Status Indicator
go.GraphObject.make(
go.Shape,
'Circle',
{
column: 1,
desiredSize: new go.Size(10, 10),
strokeWidth: 1,
},
// This binding will show/hide the Measurement Status Indicator. See the Developer Notes for a visual breakdown
new go.Binding('visible', 'showStatusSample'),
new go.Binding('fill', 'measurementSeverityColor'),
new go.Binding('stroke', 'measurementSeverityColor', (status) =>
status !== Constants.TRANSPARENT ? status : 'grey'
)
),
go.GraphObject.make(
go.TextBlock,
{ column: 2, margin: new go.Margin(0, 2, 0, 6), overflow: go.TextBlock.OverflowEllipsis },
// This binding will show/hide the Measurement Name. See the Developer Notes for a visual breakdown
new go.Binding('visible', 'showName'),
new go.Binding('text', 'name'),
new go.Binding('height', '', (data, shape) => shape.part.data.fontSize * Constants.TEXTBLOCK_ADDITIONAL_HEIGHT),
new go.Binding('width', '', (data, shape) => shape.part.data.width),
new go.Binding(
'font',
'',
(data, shape) =>
`${shape.part.data.textInfo.fontStyle} normal ${shape.part.data.textInfo.fontWeight} ${shape.part.data.textInfo.fontSize}px 'Noto Sans', sans-serif`
),
new go.Binding('isUnderline', '', (data, shape) => shape.part.data.fontDecoration === 'Underline'),
new go.Binding('stroke', '', (data, shape) =>
this.colorService.convertColorStringTo(ColorFormat.Rgba, shape.part.data.foreground)
)
),
go.GraphObject.make(
go.TextBlock,
{ column: 3, margin: 0, minSize: new go.Size(22, 10), alignment: go.Spot.Left },
new go.Binding('text', '', (data) =>
data.value !== undefined
? `${this.nodeHelperService.formatMeasurementValue(data.value)} ${data.unit} ${data.subUnit}`
: `${this.translationService.getText(Constants.No_Data_Text_Id)} ${data.unit} ${data.subUnit}`
),
new go.Binding('height', '', (data, shape) => shape.part.data.fontSize * Constants.TEXTBLOCK_ADDITIONAL_HEIGHT),
new go.Binding(
'font',
'',
(data, shape) =>
`${shape.part.data.textInfo.fontStyle} normal ${shape.part.data.textInfo.fontWeight} ${shape.part.data.textInfo.fontSize}px 'Noto Sans', sans-serif`
),
new go.Binding('isUnderline', '', (data, shape) => shape.part.data.fontDecoration === 'Underline'),
new go.Binding('stroke', '', (data, shape) =>
this.colorService.convertColorStringTo(ColorFormat.Rgba, shape.part.data.foreground)
)
)
),
}
),
go.GraphObject.make(
go.Panel,
'Table',
go.GraphObject.make(
go.Panel,
'TableRow',
// Placeholder template if isStubTable is true
{
background: Constants.STUB_NODE_BACKGROUND_COLOR,
},
go.GraphObject.make(go.TextBlock, {
row: 0,
column: 0,
text: 'Measurement Table Placeholder',
margin: 4,
})
),
new go.Binding('visible', 'isStubTable', (isStubTable: boolean) => isStubTable)
)
);