blob: 384a8f82824dfc37fd175d5a4afbb6d1e8c9c846 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 IBM Corporation and others.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.team.internal.ui.history;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.jface.action.*;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.*;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.team.core.history.IFileHistoryProvider;
import org.eclipse.team.core.history.IFileRevision;
import org.eclipse.team.internal.ui.*;
import org.eclipse.team.ui.history.*;
import org.eclipse.ui.*;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.ide.ResourceUtil;
import org.eclipse.ui.part.*;
public class GenericHistoryView extends ViewPart implements IHistoryView {
class PageContainer {
private Page page;
private SubActionBars subBars;
public PageContainer(Page page) {
this.page = page;
}
public Page getPage() {
return page;
}
public void setPage(Page page) {
this.page = page;
}
public SubActionBars getSubBars() {
return subBars;
}
public void setSubBars(SubActionBars subBars) {
this.subBars = subBars;
}
}
/**
* The pagebook control, or <code>null</code> if not initialized.
*/
private PageBook book;
/**
* View actions
*/
private Action refreshAction;
private Action linkWithEditorAction;
private Action pinAction;
/**
* The page container for the default page.
*/
private PageContainer defaultPageContainer;
/**
* The current page container
*/
PageContainer currentPageContainer;
/**
* The drop target + drop target listener
*/
DropTarget dropTarget;
GenericHistoryDropAdapter dropAdapter;
/**
* Keeps track of the last selected element (either by selecting or opening an editor)
*/
private Object lastSelectedElement;
private IPartListener partListener = new IPartListener() {
public void partActivated(IWorkbenchPart part) {
if (part instanceof IEditorPart)
editorActivated((IEditorPart) part);
}
public void partBroughtToTop(IWorkbenchPart part) {
if (part == GenericHistoryView.this)
editorActivated(getViewSite().getPage().getActiveEditor());
}
public void partOpened(IWorkbenchPart part) {
if (part == GenericHistoryView.this)
editorActivated(getViewSite().getPage().getActiveEditor());
}
public void partClosed(IWorkbenchPart part) {
}
public void partDeactivated(IWorkbenchPart part) {
}
};
private IPartListener2 partListener2 = new IPartListener2() {
public void partActivated(IWorkbenchPartReference ref) {
}
public void partBroughtToTop(IWorkbenchPartReference ref) {
}
public void partClosed(IWorkbenchPartReference ref) {
}
public void partDeactivated(IWorkbenchPartReference ref) {
}
public void partOpened(IWorkbenchPartReference ref) {
}
public void partHidden(IWorkbenchPartReference ref) {
}
public void partVisible(IWorkbenchPartReference ref) {
if (ref.getPart(true) == GenericHistoryView.this)
editorActivated(getViewSite().getPage().getActiveEditor());
}
public void partInputChanged(IWorkbenchPartReference ref) {
}
};
private ISelectionListener selectionListener = new ISelectionListener() {
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
if (selection instanceof IStructuredSelection) {
IStructuredSelection structSelection = (IStructuredSelection) selection;
//Always take the first element - this is not intended to work with multiple selection
//Also, hang on to this selection for future use in case the history view is not visible
lastSelectedElement = structSelection.getFirstElement();
if (!isLinkingEnabled() || !checkIfPageIsVisible()) {
return;
}
if (lastSelectedElement != null){
Object resource = Utils.getAdapter(lastSelectedElement, IResource.class);
if (resource != null)
itemDropped((IResource) resource, false);
else
itemDropped(lastSelectedElement, false);
//reset lastSelectedElement
lastSelectedElement = null;
}
}
}
};
private boolean linkingEnabled;
private boolean viewPinned;
/**
* Refreshes the global actions for the active page.
*/
void refreshGlobalActionHandlers() {
// Clear old actions.
IActionBars bars = getViewSite().getActionBars();
bars.clearGlobalActionHandlers();
// Set new actions.
Map newActionHandlers = currentPageContainer.getSubBars().getGlobalActionHandlers();
if (newActionHandlers != null) {
Set keys = newActionHandlers.entrySet();
Iterator iter = keys.iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
bars.setGlobalActionHandler((String) entry.getKey(), (IAction) entry.getValue());
}
}
//add refresh action handler from history view
bars.setGlobalActionHandler(ActionFactory.REFRESH.getId(), refreshAction);
}
public void createPartControl(Composite parent) {
// Create the page book.
book = new PageBook(parent, SWT.NONE);
this.linkingEnabled = TeamUIPlugin.getPlugin().getPreferenceStore().getBoolean(IFileHistoryConstants.PREF_GENERIC_HISTORYVIEW_EDITOR_LINKING);
// Create the default page rec.
defaultPageContainer = createDefaultPage(book);
//Contribute toolbars
configureToolbars(getViewSite().getActionBars());
//add global action handler
getViewSite().getActionBars().setGlobalActionHandler(ActionFactory.REFRESH.getId(), refreshAction);
//initialize the drag and drop
initDragAndDrop();
// Show the default page
showPageRec(defaultPageContainer);
// add listener for editor page activation - this is to support editor
// linking
getSite().getPage().addPartListener(partListener);
getSite().getPage().addPartListener(partListener2);
// add listener for selections
getSite().getPage().addSelectionListener(selectionListener);
}
private void configureToolbars(IActionBars actionBars) {
pinAction = new Action(TeamUIMessages.GenericHistoryView_PinCurrentHistory, TeamUIPlugin.getImageDescriptor(ITeamUIImages.IMG_PINNED)) {
public void run() {
if (isChecked()) {
//uncheck editor linking and disable
linkWithEditorAction.setChecked(false);
linkWithEditorAction.setEnabled(false);
setLinkingEnabled(false);
} else {
//renable the linking button
linkWithEditorAction.setEnabled(true);
}
setViewPinned(isChecked());
}
};
pinAction.setChecked(isViewPinned());
pinAction.setToolTipText(TeamUIMessages.GenericHistoryView_0);
refreshAction = new Action(TeamUIMessages.GenericHistoryView_Refresh, TeamUIPlugin.getImageDescriptor(ITeamUIImages.IMG_REFRESH)) {
public void run() {
((IHistoryPage) currentPageContainer.getPage()).refresh();
}
};
refreshAction.setToolTipText(TeamUIMessages.GenericHistoryView_RefreshTooltip);
refreshAction.setEnabled(true);
linkWithEditorAction = new Action(TeamUIMessages.GenericHistoryView_LinkWithEditor, TeamUIPlugin.getImageDescriptor(ITeamUIImages.IMG_LINK_WITH)) {
public void run() {
setLinkingEnabled(isViewPinned() ? false : isChecked());
}
};
linkWithEditorAction.setChecked(isLinkingEnabled());
linkWithEditorAction.setToolTipText(TeamUIMessages.GenericHistoryView_LinkWithTooltip);
//Create the local tool bar
IToolBarManager tbm = actionBars.getToolBarManager();
tbm.add(new Separator("historyView")); //$NON-NLS-1$
tbm.appendToGroup("historyView", refreshAction); //$NON-NLS-1$
tbm.appendToGroup("historyView", linkWithEditorAction); //$NON-NLS-1$
tbm.appendToGroup("historyView", pinAction); //$NON-NLS-1$
tbm.update(false);
}
boolean isLinkingEnabled() {
return linkingEnabled;
}
/**
* Enabled linking to the active editor
* @param enabled flag indiciating whether linking is enabled
*/
public void setLinkingEnabled(boolean enabled) {
this.linkingEnabled = enabled;
// remember the last setting in the dialog settings
TeamUIPlugin.getPlugin().getPreferenceStore().setValue(IFileHistoryConstants.PREF_GENERIC_HISTORYVIEW_EDITOR_LINKING, enabled);
// if turning linking on, update the selection to correspond to the active editor
if (enabled) {
editorActivated(getSite().getPage().getActiveEditor());
}
}
/**
* Sets the current view pinned
* @param b
*/
void setViewPinned(boolean pinned) {
this.viewPinned = pinned;
}
/**
* Adds drag and drop support to the history view.
*/
void initDragAndDrop() {
int ops = DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK;
Transfer[] transfers = new Transfer[] {ResourceTransfer.getInstance(), PluginTransfer.getInstance()};
dropTarget = new DropTarget(book, ops);
dropTarget.setTransfer(transfers);
dropAdapter = new GenericHistoryDropAdapter(this);
dropTarget.addDropListener(dropAdapter);
}
public void setFocus() {
if (isLinkingEnabled()){
if (lastSelectedElement != null){
if (lastSelectedElement instanceof IEditorPart){
editorActivated((IEditorPart) lastSelectedElement);
} else {
Object resource = Utils.getAdapter(lastSelectedElement, IResource.class);
if (resource != null)
itemDropped((IResource) resource, false);
else
itemDropped(lastSelectedElement, false);
}
//reset lastSelectedElement to null to prevent updating history view if it just gets focus
lastSelectedElement = null;
}
}
if (currentPageContainer.page instanceof IPage){
((IPage) currentPageContainer.page).setFocus();
}
}
/**
* Shows page contained in the given page record in this view. The page record must
* be one from this pagebook view.
* <p>
* The <code>PageBookView</code> implementation of this method asks the
* pagebook control to show the given page's control, and records that the
* given page is now current. Subclasses may extend.
* </p>
*
* @param pageContainer the page record containing the page to show
*/
protected void showPageRec(PageContainer pageContainer) {
// If already showing do nothing
if (currentPageContainer == pageContainer)
return;
// If the page is the same, just set activeRec to pageRec
if (currentPageContainer != null && pageContainer != null && currentPageContainer == pageContainer) {
currentPageContainer = pageContainer;
return;
}
// Hide old page.
if (currentPageContainer != null) {
currentPageContainer.getSubBars().deactivate();
//give the current page a chance to dispose
currentPageContainer.getPage().dispose();
currentPageContainer.getSubBars().dispose();
}
// Show new page.
currentPageContainer = pageContainer;
Control pageControl = currentPageContainer.getPage().getControl();
if (pageControl != null && !pageControl.isDisposed()) {
// Verify that the page control is not disposed
// If we are closing, it may have already been disposed
book.showPage(pageControl);
currentPageContainer.getSubBars().activate();
refreshGlobalActionHandlers();
// Update action bars.
getViewSite().getActionBars().updateActionBars();
}
}
/**
* Initializes the given page with a page site.
* <p>
* Subclasses should call this method after
* the page is created but before creating its
* controls.
* </p>
* <p>
* Subclasses may override
* </p>
* @param page The page to initialize
*/
protected PageSite initPage(IPageBookViewPage page) {
try {
PageSite site = new PageSite(getViewSite());
page.init(site);
return site;
} catch (PartInitException e) {
TeamUIPlugin.log(e);
}
return null;
}
public IHistoryPage itemDropped(Object object, boolean refresh) {
//check to see if history view is visible - if it's not, don't bother
//going to the trouble of fetching the history
if (!this.getSite().getPage().isPartVisible(this))
return null;
IResource resource = Utils.getResource(object);
if (resource != null) {
//check to see if this resource is alreadu being displayed in another page
IHistoryPage existingPage = checkForExistingPage(object, resource.getName(), refresh);
if (existingPage != null){
return existingPage;
}
//now check to see if this view is pinned
IHistoryPage pinnedPage = checkForPinnedView(object, resource.getName(), refresh);
if (pinnedPage != null)
return pinnedPage;
//check to see if resource is managed
RepositoryProvider teamProvider = RepositoryProvider.getProvider(resource.getProject());
//couldn't find a repo provider; try showing it in a local page
Object tempPageSource = null;
if (teamProvider == null){
tempPageSource = new LocalHistoryPageSource();
} else {
IFileHistoryProvider fileHistory = teamProvider.getFileHistoryProvider();
if (fileHistory != null) {
tempPageSource = Utils.getAdapter(fileHistory, IHistoryPageSource.class,true);
}
if (tempPageSource == null) {
tempPageSource = Utils.getAdapter(teamProvider, IHistoryPageSource.class,true);
}
}
if (tempPageSource instanceof IHistoryPageSource) {
IHistoryPageSource pageSource = (IHistoryPageSource) tempPageSource;
//If a current page exists, see if it can handle the dropped item
if (currentPageContainer.getPage() instanceof IHistoryPage) {
PageContainer tempPageContainer = currentPageContainer;
if (!((IHistoryPage) tempPageContainer.getPage()).isValidInput(resource)) {
tempPageContainer = createPage(pageSource, resource);
}
if (tempPageContainer != null) {
if (((IHistoryPage) tempPageContainer.getPage()).setInput(resource)){
((HistoryPage) tempPageContainer.getPage()).setHistoryView(this);
setContentDescription(resource.getName());
showPageRec(tempPageContainer);
return (IHistoryPage) tempPageContainer.getPage();
}
} else {
showPageRec(defaultPageContainer);
}
}
}
}
else if (object != null){
IHistoryPageSource historyPageSource = (IHistoryPageSource) Utils.getAdapter(object, IHistoryPageSource.class);
//Check to see that this object can be adapted to an IHistoryPageSource, else
//we don't know how to display it
if (historyPageSource == null)
return null;
//If a current page exists, see if it can handle the dropped item
if (currentPageContainer.getPage() instanceof IHistoryPage) {
PageContainer tempPageContainer = currentPageContainer;
if (!((IHistoryPage) tempPageContainer.getPage()).isValidInput(object)) {
tempPageContainer = createPage(historyPageSource, object);
}
if (tempPageContainer != null) {
//check to see if this resource is alreadu being displayed in another page
IHistoryPage existingPage = checkForExistingPage(object, ((IHistoryPage) tempPageContainer.getPage()).getName(), refresh);
if (existingPage != null){
return existingPage;
}
IHistoryPage pinnedPage = checkForPinnedView(object, ((IHistoryPage) tempPageContainer.getPage()).getName(), refresh);
if (pinnedPage != null)
return pinnedPage;
if (((IHistoryPage) tempPageContainer.getPage()).setInput(object)){
((HistoryPage) tempPageContainer.getPage()).setHistoryView(this);
setContentDescription(((IHistoryPage) tempPageContainer.getPage()).getName());
showPageRec(tempPageContainer);
return (IHistoryPage) tempPageContainer.getPage();
}
} else {
showPageRec(defaultPageContainer);
}
}
}
return null;
}
private IHistoryPage checkForPinnedView(Object object, String objectName, boolean refresh) {
if (isViewPinned()) {
try {
IViewPart view = null;
//check to see if a view already contains this object
String id = VIEW_ID + System.currentTimeMillis();
IHistoryPage page = searchHistoryViewsForObject(object, refresh);
if (page != null)
return page;
//check to see if an unpinned version of the history view exists
GenericHistoryView historyView = findUnpinnedHistoryView();
if (historyView != null){
getSite().getPage().activate(historyView);
return historyView.itemDropped(object, refresh);
}
view = getSite().getPage().showView(VIEW_ID, id, IWorkbenchPage.VIEW_CREATE);
getSite().getPage().activate(view);
if (view instanceof GenericHistoryView)
return ((GenericHistoryView) view).itemDropped(object, refresh);
} catch (PartInitException e) {
}
}
return null;
}
private IHistoryPage checkForExistingPage(Object object, String objectName, boolean refresh) {
//first check to see if the main history view contains the current resource
if (currentPageContainer != null &&
((IHistoryPage)currentPageContainer.getPage()).getInput() != null){
if (((IHistoryPage)currentPageContainer.getPage()).getInput().equals(object)){
//current page contains object, so just refresh it
IHistoryPage tempPage =((IHistoryPage)currentPageContainer.getPage());
if (refresh)
tempPage.refresh();
return tempPage;
}
}
return searchHistoryViewsForObject(object, refresh);
}
private IHistoryPage searchHistoryViewsForObject(Object object, boolean refresh) {
IWorkbenchPage page = getSite().getPage();
IViewReference[] historyViews = page.getViewReferences();
for (int i = 0; i < historyViews.length; i++) {
if (historyViews[i].getId().equals(VIEW_ID)){
IViewPart historyView = historyViews[i].getView(true);
if (historyView != null){
IHistoryPage historyPage = ((IHistoryView)historyView).getHistoryPage();
if (historyPage != null){
Object input = historyPage.getInput();
if (input != null && input.equals(object)){
//this view already contains the file, so just reuse it
getSite().getPage().bringToTop(historyView);
return ((GenericHistoryView) historyView).itemDropped(object, refresh);
}
}
}
}
}
return null;
}
private GenericHistoryView findUnpinnedHistoryView(){
IWorkbenchPage page = getSite().getPage();
IViewReference[] historyViews = page.getViewReferences();
for (int i = 0; i < historyViews.length; i++) {
if (historyViews[i].getId().equals(VIEW_ID)){
IViewPart historyView = historyViews[i].getView(false);
if (!((GenericHistoryView)historyView).isViewPinned())
return (GenericHistoryView) historyView;
}
}
return null;
}
boolean isViewPinned() {
return viewPinned;
}
private PageContainer createPage(IHistoryPageSource participant, Object object) {
Page page = participant.createPage(object);
PageSite site = initPage(page);
((IHistoryPage) page).setSite(new WorkbenchHistoryPageSite(this, page.getSite()));
page.createControl(book);
PageContainer container = new PageContainer(page);
container.setSubBars((SubActionBars) site.getActionBars());
return container;
}
protected PageContainer createDefaultPage(PageBook book) {
GenericHistoryViewDefaultPage page = new GenericHistoryViewDefaultPage();
PageSite site = initPage(page);
page.createControl(book);
PageContainer container = new PageContainer(page);
container.setSubBars((SubActionBars) site.getActionBars());
return container;
}
/**
* An editor has been activated. Fetch the history if the file is shared and the history view
* is visible in the current page.
*
* @param editor the active editor
*/
protected void editorActivated(IEditorPart editor) {
//If this history view is not visible, keep track of this editor
//for future use
if (editor != null && !checkIfPageIsVisible())
lastSelectedElement = editor;
//Only fetch contents if the view is shown in the current page.
if (editor == null || !isLinkingEnabled() || !checkIfPageIsVisible() || isViewPinned()) {
return;
}
IEditorInput input = editor.getEditorInput();
if (input instanceof FileRevisionEditorInput) {
//See if the input adapts to a file revision
Object fileRev =((FileRevisionEditorInput) input).getAdapter(IFileRevision.class);
if (fileRev != null){
itemDropped(fileRev, false);
}
} // Handle regular file editors
else {
IFile file = ResourceUtil.getFile(input);
if (file != null) {
itemDropped(file, false); /* don't fetch if already cached */
}
//see if it adapts to an IHistoryPageSource
Object pageSource = Utils.getAdapter(input, IHistoryPageSource.class);
if (pageSource != null)
itemDropped(input, false);
}
}
private boolean checkIfPageIsVisible() {
return getViewSite().getPage().isPartVisible(this);
}
public void dispose() {
super.dispose();
//Remove the drop listener
if (dropTarget != null && !dropTarget.isDisposed())
dropTarget.removeDropListener(dropAdapter);
//Call dispose on current and default pages
currentPageContainer.getPage().dispose();
defaultPageContainer.getPage().dispose();
currentPageContainer = null;
defaultPageContainer = null;
//Remove the part listeners
getSite().getPage().removePartListener(partListener);
getSite().getPage().removePartListener(partListener2);
//Remove the selection listener
getSite().getPage().removeSelectionListener(selectionListener);
}
public IHistoryPage showHistoryFor(Object object) {
return itemDropped(object, true);
}
public IHistoryPage getHistoryPage() {
if (currentPageContainer != null &&
currentPageContainer.getPage() != null)
return (IHistoryPage) currentPageContainer.getPage();
return (IHistoryPage) defaultPageContainer.getPage();
}
/**
* Updates the content description of the view with the passed
* in string.
* @param description
*/
public void updateContentDescription(String description){
setContentDescription(description);
}
}