private void reloadTree(final ProgramDnDTree tree, boolean checkRoot) {
		if (tree == null) {
			return;
		}
		ProgramNode rootNode = (ProgramNode) tree.getModel().getRoot();
		synchronized (rootNode) {
			if (checkRoot && rootNode.isValid(tree.getVersionTag())) {
				return;
			}
			ProgramModule rootModule =
				currentProgram.getListing().getRootModule(tree.getTreeName());
			if (rootModule != null && rootModule.getName().equals(rootNode.getName())) {
				tree.setBusyCursor(false);

				List<GroupPath> expandList = new ArrayList<>();// tree paths
				List<?> selectList = new ArrayList<>();
				List<?> nodeList = tree.getNodeList();
				List<?> origViewList = tree.getViewList();
				List<GroupPath> newViewList = new ArrayList<>();

				for (int i = 0; i < nodeList.size(); i++) {

					ProgramNode node = (ProgramNode) nodeList.get(i);
					TreePath path = node.getTreePath();
					GroupPath gp = node.getGroupPath();
					if (tree.isExpanded(path)) {
						expandList.add(gp);
					}
					if (origViewList.contains(path)) {
						newViewList.add(gp);
					}
				}
				tree.reload();

				for (Object element : selectList) {
					GroupPath gp = (GroupPath) element;
					tree.addGroupSelectionPath(gp);
				}

				for (GroupPath gp : expandList) {
					tree.expand(gp);
				}
				for (GroupPath gp : newViewList) {
					tree.addGroupViewPath(gp);
				}
				if (newViewList.size() > 0 && tree.getViewList().size() == 0) {
					tree.addGroupViewPath(new GroupPath(rootNode.getName()));
				}
			}
			else {
				// set the root module to the view
				tree.reload();

				// set selection to root node
				tree.addToView(((ProgramNode) tree.getModel().getRoot()).getTreePath());
			}
			tree.fireTreeViewChanged();

			Listing listing = currentProgram.getListing();
			// check the name indexer
			StringKeyIndexer indexer = tree.getNameIndexer();
			String[] keys = indexer.getKeys();
			String treeName = tree.getTreeName();
			for (String element : keys) {
				ProgramModule m = listing.getModule(treeName, element);
				if (m != null) {
					continue;
				}
				ProgramFragment f = listing.getFragment(treeName, element);
				if (f == null) {
					// program does not contain any modules or
					// fragments with this name, so remove it from
					// the table.
					indexer.remove(element);
				}
			}
		}
	}
Remember expansion and selection state, and the reload the program
because it just got restored from an undo operation.
Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramTreePlugin.java