void groupRemoved(ProgramNode node, String parentModuleName, boolean updateViewList) {

		synchronized (root) {

			ProgramNode parent = (ProgramNode) node.getParent();

			if (parent == null) {
				return; // tree has been updated already
			}

			if (parentModuleName.equals(root.getModule().getName())) {
				// use the node name and not "Root"
				parentModuleName = root.getName();
			}

			// find all nodes where this node's group resides
			ProgramNode[] nodes = findNodes(node.getName());

			if (nodes.length == 0) {
				return; // nothing to do
			}

			for (ProgramNode child : nodes) {

				parent = (ProgramNode) child.getParent();
				if (parent == null) {
					// shouldn't happen
					throw new RuntimeException("Parent in node " + node + " is null!");
				}

				if (parentModuleName.equals(parent.getName())) {
					TreePath childPath = child.getTreePath();
					model.removeNodeFromParent(child);
					child.removeAllChildren();
					child.removeFromParent();
					if (updateViewList) {
						removeDescendantsFromView(childPath);
					}
				}
			}

			// delete the name from the nameIndexer if the group no
			// longer exists...
			String name = node.getName();
			ProgramModule m = listing.getModule(treeName, name);
			ProgramFragment f = listing.getFragment(treeName, name);
			if (m == null && f == null) {
				nameIndexer.remove(name);
			}
			buildNodeList();
		}
		repaint();
	}
Called to update the tree when a Group is removed.
Called from the AWT event thread, or from the thread that
distributed domain object change events.
@param node node being removed
@param parentModuleName name of module from which the child is
being removed
@param updateViewList true means to check the view for this node's
path being in the view; if it is, then remove it; false means
don't check the view list at all
Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramDnDTree.java