| /******************************************************************************* |
| * 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() { |
| } |
| } |