Trying to left align text

Hi -
I have a group with the following template. I need to left align the panel that the text block is in (title panel) so the text appears to be left aligned. Unfortunately I also need to make sure that the group maintains its width (that is why the title panel has ‘stretch: GraphObject.Fill,’. How can I left align that panel and still make sure that the group maintains the proper width?

import type { InputEvent, Part } from 'gojs';
import {
  Adornment,
  Binding,
  Map as GoMap,
  GraphObject,
  Group,
  Panel,
  Picture,
  Placeholder,
  Point,
  Shape,
  Size,
  Spot,
  TextBlock,
} from 'gojs';

import type { GroupNodeData } from '../adapter/models';
import type { IGlobalSettings } from '../common/globalSettings';
import ContainerCaptionHTMLInfo from '../go/textEditors/containerCaptionHTMLInfo';
import { GROUP_TITLE_PANEL_NAME, name, selectionChanged } from '../util/groupHelpers';

import { GROUP_DISABLED_BUTTON, GROUP_FOLDED_BUTTON, OPACITY_DISABLED, OPACITY_ENABLED } from './constants';
import maximizeDiagonal from './icons/maximize-diagonal.svg';
import minimizeDiagonal from './icons/minimize-diagonal.svg';
import switchOff from './icons/Switch_Off.svg';
import switchOn from './icons/Switch_On.svg';

const { make: $ } = GraphObject;

const margin = 5;

const highlightGroup = (e: InputEvent, group: GraphObject, show: boolean): void => {
  const grp = group as Group;
  if (!grp) return;
  e.handled = true;
  if (show) {
    const tool = group.diagram.toolManager.draggingTool;
    const map = tool.draggedParts || tool.copiedParts;
    if (grp.canAddMembers(map.toKeySet()) && !grp.data.disabled && !grp.data.folded) {
      grp.isHighlighted = true;
      return;
    }
  }
  grp.isHighlighted = false;
};

const getDisablePanel = () =>
  $(
    Panel,
    {
      alignment: Spot.Left,
      column: 0,
      margin,
      name: 'groupDisablePanel',
      row: 0,
    },
    $(
      Picture,
      {
        cursor: 'pointer',
        height: 12,
        name: GROUP_DISABLED_BUTTON,
        width: 21,
      },
      new Binding('source', 'disabled', (disabled): any => (disabled ? switchOff : switchOn)),
    ),
  );

const getFoldedPanel = () =>
  $(
    Panel,
    {
      alignment: Spot.Right,
      column: 2,
      height: 12,
      margin,
      row: 0,
      width: 12,
    },
    $(
      Picture,
      { cursor: 'pointer', desiredSize: new Size(12, 12), height: 12, name: GROUP_FOLDED_BUTTON, width: 12 },
      new Binding('source', '', (data: GroupNodeData) => (data.folded ? maximizeDiagonal : minimizeDiagonal)),
    ),
  );

const getTitlePanel = () =>
  $(
    Panel,
    'Auto',
    {
      cursor: 'all-scroll',
      name: GROUP_TITLE_PANEL_NAME,
      stretch: GraphObject.Fill,
    },
    // this puts a border around the auto panel
    $(
      Shape,
      'Rectangle',
      {
        strokeWidth: 1,
      },
      new Binding('fill', 'fillColor'),
      new Binding('stroke', 'borderColor'),
    ),
    $(
      Panel,
      'Table',
      { stretch: GraphObject.Fill },
      getDisablePanel(),
      $(
        TextBlock,
        {
          column: 1,
          editable: true,
          isMultiline: false,
          margin,
          name: 'caption',
          opacity: 1,
          row: 0,
          textAlign: 'left',
          textEditor: new ContainerCaptionHTMLInfo(),
        },
        new Binding('text', 'caption').makeTwoWay(),
        new Binding('stroke', 'textColor'),
        new Binding(
          'font',
          '',
          (modelData: IGlobalSettings): string => `${modelData.groupFontSize} ${modelData.font}`,
        ).ofModel(),
      ),
      getFoldedPanel(),
    ),
  );

export const getGroupTemplate = () =>
  $(
    Group,
    'Vertical',
    {
      background: 'transparent',
      computesBoundsAfterDrag: true,
      handlesDragDropForMembers: true,
      locationObjectName: name,
      mouseDragEnter: (e: InputEvent, group: GraphObject): void => highlightGroup(e, group as Group, true),
      mouseDragLeave: (e: InputEvent, group: GraphObject): void => highlightGroup(e, group as Group, false),
      name,
      selectionAdornmentTemplate: $(
        Adornment,
        'Auto',
        $(
          Shape,
          'Rectangle',
          {
            fill: null,
            strokeDashArray: [4, 2],
            strokeWidth: 2,
          },
          new Binding('stroke', 'selectionColor').ofModel(),
        ),
        $(Placeholder),
      ),
      selectionChanged: (thisPart: Part) => selectionChanged(thisPart as Group),
      // TODO: change this if we support vertical layout (should come from top)
      toSpot: Spot.Left,
    },
    new Binding('isSubGraphExpanded', 'folded', (exp: any) => !exp),
    new Binding('position', 'location', Point.parse).makeTwoWay(Point.stringify),
    new Binding('opacity', 'isParentDisabled', exp => (exp ? OPACITY_DISABLED : OPACITY_ENABLED)),
    new Binding('selectable', 'isParentDisabled', exp => !exp),
    new Binding('pickable', 'isParentDisabled', exp => !exp),
    new Binding('zOrder', 'zIndex'),
    getTitlePanel(),
    $(
      Panel,
      'Auto',
      { stretch: GraphObject.Fill },
      $(
        Shape,
        'Rectangle',
        new Binding('fill', 'fillColor'),
        new Binding('stroke', 'borderColor'),
        new Binding('strokeWidth', '', (node: Part): number => (node.isHighlighted ? 3 : 1)).ofObject(),
      ),
      $(
        Placeholder,
        { alignment: Spot.TopLeft, name: 'groupPanelPlaceholder', padding: 20 },
        new Binding('opacity', 'disabled', (disabled: boolean) => (disabled ? OPACITY_DISABLED : OPACITY_ENABLED)),
      ),
    ),
  );

const getGroupTemplateMap = () => {
  const map = new GoMap<string, Group>();
  map.add('', getGroupTemplate());
  return map;
};

export default getGroupTemplateMap;

The first thing you should do is put some colors on the objects in question to see how much space they’re really taking up. Something like

background: 'red' on the text, at least. You may see something like this:

Which makes sense. The table containing the text is stretching, but the text is sitting in the middle of a large column 1.

So you might have a lot of options. One is to also stretch the text:

      $(go.TextBlock, {
        column: 1,
        stretch: go.Stretch.Horizontal,

And you might get this:

Another is to align-left the text:

      $(go.TextBlock, {
        column: 1,
        alignment: go.Spot.Left,

This is probably preferable, as it less risks distorting whatever text you might put in there if it needs to wrap or anything later on. But one of these may make more sense than the other in your template for other reasons, as I haven’t reproduced the whole thing.