Creating a Mind-Map UI in SwiftUI | raywenderlich.com

Thank you for the reply. I wanted to do something like this →

Inside NodeMapView

VStack(alignment: .center, spacing: 10) {
  NodeView(node: node, selection: self.selection)
    .onTapGesture {
      self.selection.selectNode(node)
    }

  if let children = node.children, !children.isEmpty {
    Rectangle()
      .fill(Color.blue)
      .frame(width: 1.5, height: 20)
    HStack(alignment: .top, spacing: 5) {
      ForEach(self.node.children, id: \.visualID) { node in
        NodeMapView(selection: selection, node: $node)
      }
    }
  }

I want the nodes to be positioned vertically and the children to be horizontally joined. This will allow the mesh to reposition and space itself automatically. Let me know if this is a good idea.

The map lays itself out in absolute terms. See in NodeMapView the nodes are in a single Z-Stack positioned relative to the centre of the view

NodeView(node: node, selection: self.selection)
      .offset(x: node.position.x, y: node.position.y)

It’s not impossible but

To get this working you’d need to

  • track group membership of nodes in the model
  • stack that group in HStack/Vstack
  • apply offset to the containing stack to put it where you wanted

Thanks.

Just to be clear,

  • Add an array of Nodes inside my model to track group membership called children
  • when creating a new node, add the new node to the parents children
  • stack the group in view and apply offset

I just want to make sure this is the course of action needed to implement this

Its one course of action. The model in the tutorial isn’t designed to track group membership. One possible design of many is

Add a NodeGroup entity to the model. Maybe:

struct NodeGroup {
	var groupID: String 
	var members: Set<Node> = []

	init(groupID: String) {
		self.groupID = groupID
	}

	func addMember(node: Node) {
         //stuff
	}

	func removeMember(node: Node) {
         //stuff
	}
}

Add groups: [NodeGroup] to Mesh

From there when you declare the layout, declare layout for groups first then declare ungrouped nodes that are not already in a group.

ZStack {
      ForEach(self.groups, id: \.visualID) { group in
        YourGroupedView(group: group, selection: self.selection)
          .offset(x: group.position.x, y: group.position.y)
      }
      ForEach(self.nodesThatAreNotInGroups, id: \.visualID) { node in
        NodeView(node: node, selection: self.selection)
          .offset(x: node.position.x, y: node.position.y)
     }
    }

Just go and mess around and see what can be done. SwiftUI is very amenable to playing. I dont have any exact answers for your problem.