blob: a863f399d330bd76337029cbddd62a571ca4148e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2002 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v0.5
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v05.html
*
* Contributors:
* IBM - Initial implementation
******************************************************************************/
package org.eclipse.team.internal.ui.target;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.*;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.internal.core.target.IRemoteTargetResource;
import org.eclipse.team.internal.core.target.ISiteListener;
import org.eclipse.team.internal.core.target.Site;
import org.eclipse.team.internal.core.target.TargetManager;
import org.eclipse.team.internal.ui.IHelpContextIds;
import org.eclipse.team.internal.ui.Policy;
import org.eclipse.team.internal.ui.TeamUIPlugin;
import org.eclipse.team.internal.ui.UIConstants;
import org.eclipse.team.ui.TeamImages;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.dialogs.PropertyDialogAction;
import org.eclipse.ui.help.WorkbenchHelp;
import org.eclipse.ui.internal.WorkbenchImages;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.part.ViewPart;
/**
* Is a view that allows browsing remote target sites. It is modeled after
* a file explorer: a tree of folders is show with a table of the folder's
* contents.
* <p>
* Progress is shown in the main workbench window's status line progress
* monitor.</p>
*
* @see Site
* @see IRemoteTargetResource
*/
public class SiteExplorerView extends ViewPart implements ISiteListener {
public static final String VIEW_ID = "org.eclipse.team.ui.target.SiteExplorerView"; //$NON-NLS-1$
// The tree viewer showing the folders and sites
private TreeViewer folderTree;
// The table view that shows the resources in the currently selected folder
// from the folders tree.
private TableViewer folderContentsTable;
// The root
private SiteRootsElement root;
// Embedded progress monitor part used to display progress when contacting the server
// Note: this feature is not enabled yet and is still under construction
private IProgressMonitor progressMonitorPart;
// The view's actions
private Action addSiteAction;
private Action newFolderAction;
private PropertyDialogAction propertiesAction;
/**
* Sorter for the folderContents table
*/
class FolderListingSorter extends ViewerSorter {
private boolean reversed = false;
private int columnNumber;
public static final int NAME = 0;
public static final int SIZE = 1;
public static final int MODIFIED = 2;
// column headings: "Name" "Size" "Modified"
private int[][] SORT_ORDERS_BY_COLUMN = {
{NAME}, /* name */
{SIZE, NAME}, /* size */
{MODIFIED, NAME, SIZE}, /* modified */
};
public FolderListingSorter(int columnNumber) {
this.columnNumber = columnNumber;
}
public int compare(Viewer viewer, Object o1, Object o2) {
RemoteResourceElement e1 = (RemoteResourceElement)o1;
RemoteResourceElement e2 = (RemoteResourceElement)o2;
int[] columnSortOrder = SORT_ORDERS_BY_COLUMN[columnNumber];
int result = 0;
for (int i = 0; i < columnSortOrder.length; ++i) {
result = compareColumnValue(columnSortOrder[i], e1, e2);
if (result != 0)
break;
}
if (reversed)
result = -result;
return result;
}
int compareColumnValue(int columnNumber, RemoteResourceElement e1, RemoteResourceElement e2) {
IRemoteTargetResource r1 = e1.getRemoteResource();
IRemoteTargetResource r2 = e2.getRemoteResource();
switch (columnNumber) {
case NAME:
if (r1.isContainer() && r2.isContainer())
return compareNames(r1, r2);
else if (r1.isContainer())
return -1;
else if (r2.isContainer())
return 1;
return compareNames(r1, r2);
case SIZE:
return new Integer(e1.getSize()).compareTo(new Integer(e2.getSize()));
case MODIFIED:
return getCollator().compare(e1.getLastModified(), e2.getLastModified());
default:
return 0;
}
}
protected int compareNames(IRemoteTargetResource resource1, IRemoteTargetResource resource2) {
return resource1.getName().compareTo(resource2.getName());
}
/**
* Returns the number of the column by which this is sorting.
*/
public int getColumnNumber() {
return columnNumber;
}
/**
* Returns true for descending, or false
* for ascending sorting order.
*/
public boolean isReversed() {
return reversed;
}
/**
* Sets the sorting order.
*/
public void setReversed(boolean newReversed) {
reversed = newReversed;
}
}
/**
* @see IWorkbenchPart#createPartControl(Composite)
*/
public void createPartControl(Composite top) {
Composite p = new Composite(top, SWT.NULL);
GridData data = new GridData (GridData.FILL_BOTH);
p.setLayoutData(data);
GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 3;
gridLayout.marginHeight = 0;
gridLayout.marginWidth = 0;
p.setLayout (gridLayout);
SashForm sash = new SashForm(p, SWT.HORIZONTAL);
data = new GridData(GridData.FILL_BOTH);
data.horizontalSpan = 3;
sash.setLayoutData(data);
folderTree = new TreeViewer(sash, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
folderTree.setContentProvider(new SiteLazyContentProvider());
folderTree.setLabelProvider(new WorkbenchLabelProvider());
folderTree.setSorter(new SiteViewSorter());
folderTree.getControl().addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent event) {
if (event.keyCode == SWT.F5) {
RemoteResourceElement[] selectedFolders = getSelectedRemoteFolder((IStructuredSelection)folderTree.getSelection());
if(selectedFolders.length == 1) {
selectedFolders[0].setCachedChildren(null);
folderTree.refresh(selectedFolders[0]);
updateFileTable(selectedFolders[0]);
}
}
}
});
folderTree.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
IStructuredSelection selection = (IStructuredSelection)folderTree.getSelection();
final RemoteResourceElement[] remoteFolders = getSelectedRemoteFolder(selection);
if(remoteFolders.length == 1) {
updateFileTable(remoteFolders[0]);
}
}
});
folderTree.addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent e) {
IStructuredSelection selection = (IStructuredSelection)folderTree.getSelection();
if(selection.size() == 1) {
expandInTreeCurrentSelection(selection, true /*toggle expanded*/);
}
}
});
folderTree.setSorter(new ViewerSorter() {
public int compare(Viewer viewer, Object e1, Object e2) {
String name1 = ""; //$NON-NLS-1$
String name2 = ""; //$NON-NLS-1$
if(e1 instanceof RemoteResourceElement) {
name1 = ((RemoteResourceElement)e1).getRemoteResource().getName();
} else if(e1 instanceof SiteElement) {
name1 = ((SiteElement)e1).getSite().getURL().toExternalForm();
}
if(e2 instanceof RemoteResourceElement) {
name2 = ((RemoteResourceElement)e2).getRemoteResource().getName();
} else if(e2 instanceof SiteElement) {
name2 = ((SiteElement)e2).getSite().getURL().toExternalForm();
}
return getCollator().compare(name1, name2);
}
});
// show only folders in tree
folderTree.addFilter(new ViewerFilter() {
public boolean select(Viewer viewer, Object parentElement, Object element) {
if(element instanceof RemoteResourceElement) {
return ((RemoteResourceElement)element).getRemoteResource().isContainer();
}
return false;
}
});
Table table = new Table(sash, SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL);
TableLayout layout = new TableLayout();
table.setLayout(layout);
table.setHeaderVisible(true);
TableColumn tableColumn = new TableColumn(table, SWT.NULL);
tableColumn.setText(Policy.bind("SiteExplorerView.Name_1")); //$NON-NLS-1$
tableColumn.addSelectionListener(getColumnListener());
layout.addColumnData(new ColumnWeightData(30, true));
tableColumn = new TableColumn(table, SWT.NULL);
tableColumn.setText(Policy.bind("SiteExplorerView.Size_2")); //$NON-NLS-1$
tableColumn.setAlignment(SWT.RIGHT);
tableColumn.addSelectionListener(getColumnListener());
layout.addColumnData(new ColumnWeightData(10, true));
tableColumn = new TableColumn(table, SWT.NULL);
tableColumn.setText(Policy.bind("SiteExplorerView.Modified_3")); //$NON-NLS-1$
tableColumn.addSelectionListener(getColumnListener());
layout.addColumnData(new ColumnWeightData(30, true));
tableColumn = new TableColumn(table, SWT.NULL);
tableColumn.setText(Policy.bind("SiteExplorerView.URL_4")); //$NON-NLS-1$
layout.addColumnData(new ColumnWeightData(30, true));
folderContentsTable = new TableViewer(table);
folderContentsTable.setContentProvider(new SiteLazyContentProvider());
folderContentsTable.setLabelProvider(new SiteExplorerViewLabelProvider());
folderContentsTable.getControl().addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent event) {
if (event.keyCode == SWT.F5) {
RemoteResourceElement folder = (RemoteResourceElement)folderContentsTable.getInput();
if(folder != null) {
folder.setCachedChildren(null);
folderContentsTable.refresh();
}
}
}
});
folderContentsTable.addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent e) {
IStructuredSelection selection = (IStructuredSelection)folderContentsTable.getSelection();
if(selection.size() == 1) {
final RemoteResourceElement[] remoteFolders = getSelectedRemoteFolder(selection);
if(remoteFolders.length == 1) {
IStructuredSelection treeSelection = (IStructuredSelection)folderTree.getSelection();
expandInTreeCurrentSelection(treeSelection, false /*don't toggle*/);
folderTree.setSelection(new StructuredSelection(remoteFolders[0]));
}
}
}
});
FolderListingSorter sorter = new FolderListingSorter(FolderListingSorter.NAME);
sorter.setReversed(false);
folderContentsTable.setSorter(sorter);
sash.setWeights(new int[] {33, 67});
TargetManager.addSiteListener(this);
root = new SiteRootsElement(getViewSite().getWorkbenchWindow());
initalizeActions();
folderTree.setInput(root);
// F1 Help
WorkbenchHelp.setHelp(folderTree.getControl(), IHelpContextIds.SITE_EXPLORER_VIEW);
}
private Shell getShell() {
return folderTree.getTree().getShell();
}
private RemoteResourceElement[] getSelectedRemoteFolder(IStructuredSelection selection) {
if (!selection.isEmpty()) {
final List folders = new ArrayList();
Iterator it = selection.iterator();
while(it.hasNext()) {
Object o = it.next();
if(o instanceof RemoteResourceElement) {
folders.add(o);
}
}
return (RemoteResourceElement[]) folders.toArray(new RemoteResourceElement[folders.size()]);
}
return new RemoteResourceElement[0];
}
private void expandInTreeCurrentSelection(IStructuredSelection selection, boolean toggle) {
if (!selection.isEmpty()) {
Iterator it = selection.iterator();
while(it.hasNext()) {
Object element = it.next();
if(toggle) {
folderTree.setExpandedState(element, !folderTree.getExpandedState(element));
} else {
folderTree.setExpandedState(element, true);
}
}
}
}
/**
* Method updateFileTable.
*/
private void updateFileTable(RemoteResourceElement remoteFolder) {
if(remoteFolder != null && !remoteFolder.equals(folderContentsTable.getInput())) {
folderContentsTable.setInput(remoteFolder);
}
}
private void initalizeActions() {
final Shell shell = folderContentsTable.getTable().getShell();
// Create actions
// Refresh (toolbar)
addSiteAction = new Action(Policy.bind("SiteExplorerView.addSiteAction"), TeamImages.getImageDescriptor(UIConstants.IMG_SITE_ELEMENT)) { //$NON-NLS-1$
public void run() {
ConfigureTargetWizard wizard = new ConfigureTargetWizard();
wizard.init(null, null);
WizardDialog dialog = new WizardDialog(shell, wizard);
dialog.open();
}
};
addSiteAction.setToolTipText(Policy.bind("SiteExplorerView.addSiteActionTooltip")); //$NON-NLS-1$
WorkbenchHelp.setHelp(addSiteAction, IHelpContextIds.ADD_SITE_ACTION);
newFolderAction = new Action(Policy.bind("SiteExplorerView.newFolderAction"), WorkbenchImages.getImageDescriptor(org.eclipse.ui.ISharedImages.IMG_OBJ_FOLDER)) { //$NON-NLS-1$
public void run() {
final Shell shell = folderTree.getTree().getShell();
try {
// assume that only one folder is selected in the folder tree, this
// is enforced by isEnable() method for this action
IStructuredSelection selection = (IStructuredSelection)folderTree.getSelection();
Object currentSelection = selection.getFirstElement();
RemoteResourceElement selectedFolder;
if(!selection.isEmpty()) {
selectedFolder = getSelectedRemoteFolder(selection)[0];
} else {
selectedFolder = (RemoteResourceElement)folderContentsTable.getInput();
}
IRemoteTargetResource newFolder = CreateNewFolderAction.createDir(shell, selectedFolder.getRemoteResource(), Policy.bind("CreateNewFolderAction.newFolderName")); //$NON-NLS-1$
if (newFolder == null)
return;
// force a refresh
selectedFolder.setCachedChildren(null);
// select the newly added folder
RemoteResourceElement newFolderUIElement = new RemoteResourceElement(newFolder);
folderTree.refresh(currentSelection);
expandInTreeCurrentSelection(new StructuredSelection(currentSelection), false);
folderTree.setSelection(new StructuredSelection(newFolderUIElement));
} catch (TeamException e) {
TeamUIPlugin.handle(e);
return;
}
}
public boolean isEnabled() {
return folderContentsTable.getInput() != null ||
getSelectedRemoteFolder((IStructuredSelection)folderTree.getSelection()).length == 1;
}
};
WorkbenchHelp.setHelp(newFolderAction, IHelpContextIds.NEW_FOLDER_ACTION);
IActionBars bars = getViewSite().getActionBars();
IToolBarManager tbm = bars.getToolBarManager();
tbm.add(addSiteAction);
tbm.update(false);
// Properties
propertiesAction = new PropertyDialogAction(shell, folderTree);
getViewSite().getActionBars().setGlobalActionHandler(IWorkbenchActionConstants.PROPERTIES, propertiesAction);
IStructuredSelection selection = (IStructuredSelection)folderTree.getSelection();
if (selection.size() == 1 && selection.getFirstElement() instanceof SiteElement) {
propertiesAction.setEnabled(true);
} else {
propertiesAction.setEnabled(false);
}
folderTree.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
IStructuredSelection ss = (IStructuredSelection)event.getSelection();
boolean enabled = ss.size() == 1 && ss.getFirstElement() instanceof SiteElement;
propertiesAction.setEnabled(enabled);
}
});
MenuManager treeMgr = new MenuManager();
MenuManager tableMgr = new MenuManager();
Tree tree = folderTree.getTree();
Table table = folderContentsTable.getTable();
Menu treeMenu = treeMgr.createContextMenu(tree);
Menu tableMenu = tableMgr.createContextMenu(table);
IMenuListener menuListener = new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
// Misc additions
MenuManager sub = new MenuManager(Policy.bind("SiteExplorerView.newMenu"), IWorkbenchActionConstants.GROUP_ADD); //$NON-NLS-1$
sub.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
manager.add(sub);
manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
sub.add(addSiteAction);
sub.add(newFolderAction);
manager.add(propertiesAction);
}
};
treeMgr.addMenuListener(menuListener);
treeMgr.setRemoveAllWhenShown(true);
tableMgr.addMenuListener(menuListener);
tableMgr.setRemoveAllWhenShown(true);
tree.setMenu(treeMenu);
table.setMenu(tableMenu);
getSite().registerContextMenu(tableMgr, folderContentsTable);
getSite().registerContextMenu(treeMgr, folderTree);
}
/**
* Add the new site to the viewer and make it the current selection.
*
* @see ISiteListener#siteAdded(Site)
*/
public void siteAdded(Site site) {
SiteElement element = new SiteElement(site, getViewSite().getWorkbenchWindow());
folderTree.add(root, element);
folderTree.setSelection(new StructuredSelection(element));
}
/**
* Remote the site from the viewer and select the next site in the
* tree.
*
* @see ISiteListener#siteRemoved(Site)
*/
public void siteRemoved(Site site) {
folderTree.remove(new SiteElement(site));
selectNextObjectInTreeViewer();
}
private void selectNextObjectInTreeViewer() {
Object[] items = folderTree.getVisibleExpandedElements();
if(items.length > 0) {
folderTree.setSelection(new StructuredSelection(items[0]));
} else {
folderContentsTable.setInput(null);
}
}
/**
* Adds the listener that sets the sorter.
*/
private SelectionListener getColumnListener() {
/**
* This class handles selections of the column headers.
* Selection of the column header will cause resorting
* of the shown tasks using that column's sorter.
* Repeated selection of the header will toggle
* sorting order (ascending versus descending).
*/
return new SelectionAdapter() {
/**
* Handles the case of user selecting the
* header area.
* <p>If the column has not been selected previously,
* it will set the sorter of that column to be
* the current tasklist sorter. Repeated
* presses on the same column header will
* toggle sorting order (ascending/descending).
*/
public void widgetSelected(SelectionEvent e) {
// column selected - need to sort
// only allow sorting on name for now
int column = folderContentsTable.getTable().indexOf((TableColumn) e.widget);
if(column == FolderListingSorter.NAME) {
FolderListingSorter oldSorter = (FolderListingSorter)folderContentsTable.getSorter();
if (oldSorter != null && column == oldSorter.getColumnNumber()) {
oldSorter.setReversed(!oldSorter.isReversed());
folderContentsTable.refresh();
} else {
folderContentsTable.setSorter(new FolderListingSorter(column));
}
}
}
};
}
/**
* @see IWorkbenchPart#setFocus()
*/
public void setFocus() {
}
}