/*******************************************************************************
* Copyright (C) 2016 Thomas Wolf <thomas.wolf@paranor.ch>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.egit.ui.internal.selection;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.Map;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.ui.AbstractSourceProvider;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.ISources;
import org.eclipse.ui.IWindowListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.services.IServiceLocator;
/**
* An {@link AbstractSourceProvider} that provides the current repository (based
* on the current selection) as a variable in an Eclipse
* {@link org.eclipse.core.expressions.IEvaluationContext}. To avoid interfering
* with repository removal, which in EGit relies on {@link WeakReference}
* semantics, the variable provides not the {@link Repository} directly but its
* git directory as a string, which can then be used to obtain the
* {@link Repository} instance via
* {@link org.eclipse.egit.core.RepositoryCache#getRepository(java.io.File)}. If
* no repository can be determined, the variable's value is the empty string.
*/
public class RepositorySourceProvider extends AbstractSourceProvider
implements ISelectionListener, IWindowListener {
/**
* Key for the new variable in the
* {@link org.eclipse.core.expressions.IEvaluationContext}; may be used in a
* <with> element in plugin.xml to reference the variable.
*/
public static final String REPOSITORY_PROPERTY = "org.eclipse.egit.ui.currentRepository"; //$NON-NLS-1$
/**
* Use a weak reference here to not preclude repository removal.
*/
private WeakReference<Repository> repositoryRef;
@Override
public void initialize(IServiceLocator locator) {
super.initialize(locator);
PlatformUI.getWorkbench().addWindowListener(this);
}
@Override
public void dispose() {
PlatformUI.getWorkbench().removeWindowListener(this);
repositoryRef = null;
}
@Override
public Map getCurrentState() {
@SuppressWarnings("resource")
Repository repository = repositoryRef == null ? null
: repositoryRef.get();
if (repository == null) {
return Collections.singletonMap(REPOSITORY_PROPERTY, ""); //$NON-NLS-1$
}
return Collections.singletonMap(REPOSITORY_PROPERTY,
repository.getDirectory().getAbsolutePath());
}
@Override
public String[] getProvidedSourceNames() {
return new String[] { REPOSITORY_PROPERTY };
}
@Override
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
Repository newRepository;
if (selection == null) {
newRepository = null;
} else {
newRepository = SelectionUtils.getRepository(
SelectionUtils.getStructuredSelection(selection));
}
@SuppressWarnings("resource")
Repository currentRepository = repositoryRef == null ? null
: repositoryRef.get();
if (currentRepository == null && repositoryRef != null) {
repositoryRef = null;
if (newRepository == null) {
// Last evaluation was non-null, but that repo has since gone.
fireSourceChanged(ISources.ACTIVE_WORKBENCH_WINDOW,
REPOSITORY_PROPERTY, ""); //$NON-NLS-1$
return;
}
}
if (currentRepository != newRepository) {
if (newRepository != null) {
repositoryRef = new WeakReference<>(newRepository);
fireSourceChanged(ISources.ACTIVE_WORKBENCH_WINDOW,
REPOSITORY_PROPERTY,
newRepository.getDirectory().getAbsolutePath());
} else {
repositoryRef = null;
fireSourceChanged(ISources.ACTIVE_WORKBENCH_WINDOW,
REPOSITORY_PROPERTY, ""); //$NON-NLS-1$
}
}
}
@Override
public void windowActivated(IWorkbenchWindow window) {
window.getSelectionService().addSelectionListener(this);
}
@Override
public void windowDeactivated(IWorkbenchWindow window) {
window.getSelectionService().removeSelectionListener(this);
}
@Override
public void windowClosed(IWorkbenchWindow window) {
// Nothing to do
}
@Override
public void windowOpened(IWorkbenchWindow window) {
// Nothing to do
}
}