ghidra-master/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/associate/SyncRefreshAction.java
/* ###
 * IP: GHIDRA
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package ghidra.app.plugin.core.datamgr.actions.associate;

import docking.ActionContext;
import docking.action.DockingAction;
import docking.action.MenuData;
import docking.widgets.tree.GTreeState;
import ghidra.app.plugin.core.datamgr.*;
import ghidra.app.plugin.core.datamgr.archive.DataTypeManagerHandler;
import ghidra.app.plugin.core.datamgr.tree.ArchiveNode;
import ghidra.app.plugin.core.datamgr.tree.DataTypeArchiveGTree;
import ghidra.program.model.data.DataTypeManager;
import ghidra.program.model.data.SourceArchive;
import ghidra.util.HelpLocation;
import ghidra.util.Msg;

public class SyncRefreshAction extends DockingAction {

	public static final String MENU_NAME = "Refresh Sync Indicators For";
	private DataTypeManagerHandler dataTypeManagerHandler;
	private final DataTypeManager dtm;
	private final SourceArchive sourceArchive;
	private final DataTypeManagerPlugin plugin;
	private DataTypeSynchronizer synchronizer;
	private ArchiveNode archiveNode;

	public SyncRefreshAction(DataTypeManagerPlugin plugin,
			DataTypeManagerHandler dataTypeManagerHandler, DataTypeManager dtm,
			ArchiveNode archiveNode, SourceArchive sourceArchive, boolean isEnabled) {

		super("Refresh The Sync Indicators For Archive", plugin.getName());
		this.plugin = plugin;
		this.dataTypeManagerHandler = dataTypeManagerHandler;
		this.dtm = dtm;
		this.archiveNode = archiveNode;
		this.sourceArchive = sourceArchive;
		synchronizer = new DataTypeSynchronizer(dataTypeManagerHandler, dtm, sourceArchive);
		setEnabled(isEnabled);
		setPopupMenuData(new MenuData(new String[] { MENU_NAME, sourceArchive.getName() }));
		setHelpLocation(new HelpLocation(plugin.getName(), getHelpTopic()));
	}

	protected String getHelpTopic() {
		return "Refresh_Sync_Indicators";
	}

	@Override
	public void actionPerformed(ActionContext context) {
		if (!dtm.isUpdatable()) {
			Msg.showError(getClass(), plugin.getTool().getToolFrame(), "Sync Refresh Failed", "\"" +
				dtm.getName() + "\" must be open for editing.");
			return;
		}
		DataTypeManager sourceDTM = dataTypeManagerHandler.getDataTypeManager(sourceArchive);
		if (sourceDTM == null) {
			Msg.showInfo(getClass(), plugin.getTool().getToolFrame(),
				"Cannot Access Source Archive", "Can't access the data types for the " +
					sourceArchive.getName() + " archive.");
			return;
		}

		//
		// Note: we collapse the node before performing this work because there is a 
		//       potential for a large number of events to be generated.  Further, if the
		//       given archive node has many children (like 10s of thousands), then the
		//       copious events generated herein could lock the UI.  By closing the node, 
		//       the tree is not invalidating/validating its cache as a result of these
		//       events.
		//
		DataTypesProvider provider = plugin.getProvider();
		DataTypeArchiveGTree tree = provider.getGTree();
		GTreeState treeState = tree.getTreeState();
		tree.collapseAll(archiveNode);

		synchronizer.reSyncDataTypes();

		Msg.showInfo(
			getClass(),
			plugin.getTool().getToolFrame(),
			"Refresh Completed",
			"Sync indicators have been refreshed between " + dtm.getName() + " and archive \"" +
				sourceArchive.getName() + "\".");

		tree.restoreTreeState(treeState);
	}

}
