How to define an image position into GoSubGraph?

Hi Support!

I created a class to create a SubProcess object ( BPM item )… But I would like to know how to configure a image inside this object, and when resize, image will move correctly…Should I changed LayoutChildren()?
And is there a way to insert a event in image click ?
Thanks!

See my image as result of my class:

My Class:

public class SubProcessItem : GoSubGraphBase
{
    //Variables
    private static Pen subprocessBorderPen;
    private GoShape mBorder = null;
    private GoButton mButton = null;
    private GoText mLabel = null;
    private static readonly Pen StandardPen = new Pen(Color.Black, 1);
    private static readonly Pen HighlightPen = new Pen(Color.Green, 1);
    //This field keeps track of this process item image
    private ProcessItemImage mProcessItemImage;

    public SubProcessItem()
    {

        this.Initializing = true;

        //Add rectangle into GoSubGraphBase
        mBorder = new GoRoundedRectangle();
        mBorder.Selectable = false;
        if (subprocessBorderPen == null)
        {
            Pen p = new Pen(Color.Black, 1);
            p.DashStyle = DashStyle.Solid;
            subprocessBorderPen = p;
        }
        mBorder.Pen = subprocessBorderPen;
        mBorder.Size = new SizeF(100, 100);
        Add(mBorder);

        //Add label
        mLabel = new GoText();
        mLabel.Text ="SubProcess";
        mLabel.Selectable = false;
        mLabel.Editable = true;
        Add(mLabel);


        ProcessItemImage m_ProcessItemImage = new ProcessItemImage(ItemKind.SubProcess);

        mProcessItemImage = m_ProcessItemImage;
        Add(m_ProcessItemImage);

        this.Initializing = false;
        LayoutChildren(mBorder);
    }



    //Override to keep fields up-to-date
    protected override void CopyChildren(GoGroup newgroup, GoCopyDictionary env)
    {
        base.CopyChildren(newgroup, env);
        SubProcessItem newobj = (SubProcessItem)newgroup;
        newobj.mBorder = (GoShape)env[mBorder];
        newobj.mLabel = (GoText)env[mLabel];
    }

    //This property is for convenience in accessing the Process Item Image class
    public ProcessItemImage ProcessImage
    {
        get { return mProcessItemImage; }
    }

    //Override to keep fields up-to-date
    public override bool Remove(GoObject obj)
    {
        bool result = base.Remove(obj);
        if (obj == mBorder)
            mBorder = null;
        else if (obj == mLabel)
            mLabel = null;
        return result;
    }

    // Determine the smallest rectangle that encloses all of the other children of this area.
    // This might return null, if there are no other objects besides the Border.
    public RectangleF ComputeBorder()
    {
        RectangleF rect = RectangleF.Empty;
        bool first = true;
        foreach (GoObject obj in this)
        {
            if (obj == this.Border) continue;
            if (obj == this.Label) continue;
            if (first)
            {
                first = false;
                rect = obj.Bounds;
            }
            else
            {
                // add the object's bounding rect to this one
                rect = RectangleF.Union(rect, obj.Bounds);
            }
        }
        if (!first)
        {
            // leave some room as a margin
            rect.Inflate(4, 4);
        }
        return rect;
    }



    //Override to keep mBorder surrounding the other child objects
    public override void LayoutChildren(GoObject childchanged)
    {
        if (this.Initializing)
        {
            return;
        }
        

        GoObject border = this.Border;
        GoObject label = this.Label;


        if (childchanged == border && border != null && label != null)
        {
            RectangleF rect = border.Bounds;
            label.SetSpotLocation(BottomLeft, new PointF(rect.X, rect.Y - 2));
        }
        else if (!this.AllowDragInOut)
        {
            // compute the minimum rectangle needed to enclose the children except for the Border
            RectangleF rect = ComputeBorder();
            if (rect != RectangleF.Empty)
            {
                // but don't have the box shrink to minimum size continuously
                rect = RectangleF.Union(rect, border.Bounds);
                border.Bounds = rect;
                if (label != null)
                {
                    this.Label.SetSpotLocation(BottomLeft, new PointF(rect.X, rect.Y - 2));
                }
            }
        }
    }

    // When this property is true, OnSelectionDropped will add the selected objects to this BoxArea.
    // When this property is true, you should implement a GoView.BackgroundSelectionDropped
    // event handler that calls AddCollection on a document layer with the GoView.Selection.
    // For dragging out of a BoxArea:
    //private void goView1_BackgroundSelectionDropped(object sender, Northwoods.Go.GoInputEventArgs e) {
    //  GoView view = (GoView)sender;
    //  // see if there are any selected objects that belong to a BoxArea
    //  bool wasinbox = false;
    //  foreach (GoObject obj in view.Selection) {
    //    if (obj.Parent is BoxArea) {
    //      wasinbox = true;
    //      break;
    //    }
    //  }
    //  if (wasinbox) {  // only if a selected object belonged to a BoxArea do we reparent the selection
    //    // add all selected objects as top-level objects in the DefaultLayer
    //    view.Selection.AddRange(view.Document.DefaultLayer.AddCollection(view.Selection, true));
    //  }
    //}
    //
    // When this property is false, there should not be a BackgroundSelectionDropped event
    // handler, and this node will not support reparenting of its children -- the border
    // will always surround its children.
    public bool AllowDragInOut
    {
        get { return true; }
    }

    //Highlight when dragging
    public override bool OnEnterLeave(GoObject from, GoObject to, GoView view)
    {
        if (from is SubProcessItem)
        {  // unhighlight any BoxArea that we have left
            from.SkipsUndoManager = true;
            ((SubProcessItem)from).Border.Pen = subprocessBorderPen;
            from.SkipsUndoManager = false;
        }
        if (this.AllowDragInOut && view.Tool is GoToolDragging)
        {  // only highlight when we are dragging
            if (to == this)
            {  // highlight this BoxArea that we are entering
                this.SkipsUndoManager = true;
                this.Border.Pen = HighlightPen;
                this.SkipsUndoManager = false;
                return true;  // don't highlight parent BoxAreas, if any
            }
        }
        return false;  // continue by calling parent.OnEnterLeave
    }

    public override bool OnSelectionDropped(GoObjectEventArgs evt, GoView view)
    {
        if (this.AllowDragInOut)
        {
            // add all selected objects to this BoxArea
            view.Selection.AddRange(AddCollection(view.Selection, true));
            // update the border to include all selected objects in case the selection crosses the border
            GoObject border = this.Border;
            if (border != null)
            {
                RectangleF rect = ComputeBorder();
                if (rect != RectangleF.Empty)
                {
                    // but don't have the box shrink to minimum size continuously
                    rect = RectangleF.Union(rect, border.Bounds);
                    border.Bounds = rect;
                }
            }
                
            view.Selection.AddRange(AddItems(view.Selection));
            return true;
        }
        else
        {
            return false;
        }
    }

    // Allow the user to interactively resize the border;
    // this ensures that the border surrounds all of the children.
    public override void DoResize(GoView view, RectangleF origRect, PointF newPoint, int whichHandle, GoInputState evttype, SizeF min, SizeF max)
    {
        // compute rectangle for normal resizing
        RectangleF newRect = ComputeResize(origRect, newPoint, whichHandle, min, max, true);
        // account for the height of the Label
        newRect.Y += this.Label.Height + 2;
        newRect.Height -= this.Label.Height + 2;
        // compute rectangle required by the child objects
        RectangleF minRect = ComputeBorder();
        if (minRect != RectangleF.Empty)
        {
            newRect = RectangleF.Union(newRect, minRect);
        }
        // update the bounding rect of the Border
        this.Border.Bounds = newRect;
    }

    public GoShape Border
    {
        get { return mBorder; }
    }

    public GoButton Button
    {
        get { return mButton; }
    }

    public override GoText Label
    {
        get { return mLabel; }
        set { }
    }



    //Don't add Lanes/Pool/SubProcess as children of this Display
    public virtual bool IsAddable(GoObject obj)
    {
        if ((obj is Lane) || (obj is Pool) || (obj is SubProcessItem))
        {
            return false;
        }
        else
        {
            return true;
        }
    }

    //Return a collection of objects that actually are added to this Lane
    public virtual IGoCollection AddItems(IGoCollection coll)
    {
    
        GoCollection items = new GoCollection();

        foreach (GoObject obj in coll)
        {
            if (IsAddable(obj))
            {
                items.Add(obj);
            }
        }

        if (items.IsEmpty)
        {
            return items;
        }

        IGoCollection added = AddCollection(items, false);

        return added;
    }
}

See the information for LayoutHandle in the API reference (in Visual Studio help).

You want that positioning for the handle when it is collapsed, right? I don’t recall where BPMN puts the button to collapse an expanded subprocess.

Sorry, this is the correct image, so the image will be always in the middle of box…After collapsed or expanded. How to do it?

Does LimitingSubGraph accepts drag and Drop objects as BoxArea example? I saw that GoSubGraph has Collapsed and expanded mechanism… and GoSubGraphBase has Drop mechanism… I would like to mix…because I need drag/Drop and collapsed/expanded button

You can try this:



public override void LayoutHandle() {

GoSubGraphHandle h = this.Handle;

if (h != null && h.CanView()) {

// keep handle up-to-date

RectangleF b = ComputeBorder();

h.SetSpotLocation(MiddleBottom, new PointF(b.Left + (b.Width / 2), b.Bottom));

}

}



protected override PointF ComputeReferencePoint() {

return this.Label.Position;

}