| /******************************************************************************* |
| * Copyright (c) 2007, 2018 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.team.internal.ccvs.ui; |
| |
| import java.util.*; |
| import java.util.List; |
| |
| import org.eclipse.jface.viewers.*; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.ControlAdapter; |
| import org.eclipse.swt.events.ControlEvent; |
| import org.eclipse.swt.graphics.*; |
| import org.eclipse.swt.widgets.*; |
| import org.eclipse.team.internal.ccvs.core.CVSRepositoryLocationMatcher; |
| import org.eclipse.team.internal.ccvs.core.ICVSRepositoryLocation; |
| import org.eclipse.team.internal.ccvs.core.connection.CVSRepositoryLocation; |
| import org.eclipse.team.internal.ccvs.core.util.KnownRepositories; |
| |
| public class ConfigureRepositoryLocationsTable implements ICellModifier, |
| IStructuredContentProvider, ITableLabelProvider { |
| |
| private static final class AlternativeRepositoryComparator extends |
| ViewerComparator { |
| |
| public AlternativeRepositoryComparator() { |
| } |
| |
| private int getCategory(Object element) { |
| if (element instanceof RepositoryLocationItem) { |
| return 0; |
| } |
| return 2; |
| } |
| |
| @Override |
| public int compare(Viewer viewer, Object e1, Object e2) { |
| final int compare = getCategory(e1) - getCategory(e2); |
| if (compare != 0) |
| return compare; |
| return super.compare(viewer, ((Item) e1).location, |
| ((Item) e2).location); |
| } |
| } |
| |
| public abstract static class Item implements Comparable { |
| public final ICVSRepositoryLocation location; |
| public List alternativeList; |
| public int selected; |
| |
| public Item(ICVSRepositoryLocation name, List alternative) { |
| this.location = name; |
| this.alternativeList = alternative; |
| this.selected = 0; |
| } |
| |
| @Override |
| public int compareTo(Object o) { |
| return location.getLocation(false).compareTo( |
| ((Item) o).location.getLocation(false)); |
| } |
| } |
| |
| public static class RepositoryLocationItem extends Item { |
| public RepositoryLocationItem( |
| ICVSRepositoryLocation projectSetRepositoryLocation, |
| List suggestedRepositoryLocations) { |
| super(projectSetRepositoryLocation, suggestedRepositoryLocations); |
| } |
| } |
| |
| protected static final String ITEM = "item"; //$NON-NLS-1$ |
| protected static final String PROPERTY_ALTERNATIVE_LIST = "alternativeList"; //$NON-NLS-1$ |
| |
| private TableViewer fTableViewer; |
| |
| private CellEditor[] cellEditors; |
| |
| private TextCellEditor dummyAlternativeRepositoryEditor; |
| |
| private Table table; |
| |
| /** |
| * List of <code>AlternativeRepositoryTable.RepositoryLocationItem</code> |
| * used as an input to the table. |
| */ |
| private List fAlternatives; |
| |
| private boolean fShowOnlyCompatibeLocations = true; |
| |
| public ConfigureRepositoryLocationsTable(Map alternativesMap) { |
| fAlternatives = new ArrayList(); |
| for (Iterator iterator = alternativesMap.entrySet().iterator(); iterator |
| .hasNext();) { |
| Map.Entry entry = (Map.Entry) iterator.next(); |
| fAlternatives |
| .add(new ConfigureRepositoryLocationsTable.RepositoryLocationItem( |
| (ICVSRepositoryLocation) entry.getKey(), |
| (List) entry.getValue())); |
| } |
| } |
| |
| public Composite createControl(final Composite composite) { |
| /** |
| * Create a table. |
| */ |
| table = new Table(composite, SWT.V_SCROLL | SWT.BORDER | SWT.MULTI |
| | SWT.FULL_SELECTION); |
| // table.setLayoutData(SWTUtils.createHVFillGridData()); |
| table.setLinesVisible(true); |
| table.setHeaderVisible(true); |
| table.addListener(SWT.MeasureItem, event -> { |
| // int clientWidth = table.getClientArea().width; |
| event.height = event.gc.getFontMetrics().getHeight() + 5; |
| // event.width = clientWidth * 2; |
| }); |
| |
| /** |
| * The 'Project set repository location' column |
| */ |
| final TableColumn projectSetRepositoryColumn = new TableColumn(table, |
| SWT.NONE, 0); |
| projectSetRepositoryColumn |
| .setText(CVSUIMessages.ConfigureRepositoryLocationsWizard_column0); |
| |
| /** |
| * The 'Repository location' column |
| */ |
| final TableColumn alternativeRepositoryColums = new TableColumn(table, |
| SWT.NONE, 1); |
| alternativeRepositoryColums |
| .setText(CVSUIMessages.ConfigureRepositoryLocationsWizard_column1); |
| |
| composite.addControlListener(new ControlAdapter() { |
| @Override |
| public void controlResized(ControlEvent e) { |
| Rectangle area = composite.getClientArea(); |
| Point size = table.computeSize(SWT.DEFAULT, SWT.DEFAULT); |
| ScrollBar vBar = table.getVerticalBar(); |
| int width = area.width - table.computeTrim(0, 0, 0, 0).width |
| - vBar.getSize().x; |
| if (size.y > area.height + table.getHeaderHeight()) { |
| // Subtract the scrollbar width from the total column width |
| // if a vertical scrollbar will be required |
| Point vBarSize = vBar.getSize(); |
| width -= vBarSize.x; |
| } |
| Point oldSize = table.getSize(); |
| if (oldSize.x > area.width) { |
| // table is getting smaller so make the columns |
| // smaller first and then resize the table to |
| // match the client area width |
| projectSetRepositoryColumn.setWidth(width / 2); |
| alternativeRepositoryColums.setWidth(width |
| - projectSetRepositoryColumn.getWidth()); |
| table.setSize(area.width, area.height); |
| } else { |
| // table is getting bigger so make the table |
| // bigger first and then make the columns wider |
| // to match the client area width |
| table.setSize(area.width, area.height); |
| projectSetRepositoryColumn.setWidth(width / 2); |
| alternativeRepositoryColums.setWidth(width |
| - projectSetRepositoryColumn.getWidth()); |
| } |
| } |
| }); |
| |
| /** |
| * Create a viewer for the table. |
| */ |
| fTableViewer = new TableViewer(table); |
| fTableViewer.setContentProvider(this); |
| fTableViewer.setLabelProvider(this); |
| fTableViewer.setComparator(new AlternativeRepositoryComparator()); |
| |
| /** |
| * Add a cell editor in the 'Repository location' column |
| */ |
| TableViewerFocusCellManager focusCellManager = new TableViewerFocusCellManager( |
| fTableViewer, new FocusCellOwnerDrawHighlighter(fTableViewer)); |
| ColumnViewerEditorActivationStrategy editorActivationStrategy = new ColumnViewerEditorActivationStrategy( |
| fTableViewer) { |
| @Override |
| protected boolean isEditorActivationEvent( |
| ColumnViewerEditorActivationEvent event) { |
| return event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION |
| || (event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == SWT.F2); |
| } |
| }; |
| TableViewerEditor.create(fTableViewer, focusCellManager, |
| editorActivationStrategy, ColumnViewerEditor.DEFAULT |
| | ColumnViewerEditor.KEYBOARD_ACTIVATION); |
| |
| cellEditors = new CellEditor[2]; |
| cellEditors[0] = null; |
| // to enable cell editing, create a dummy cell editor |
| cellEditors[1] = dummyAlternativeRepositoryEditor = new TextCellEditor( |
| table, SWT.READ_ONLY); |
| |
| fTableViewer.setCellEditors(cellEditors); |
| fTableViewer.setColumnProperties(new String[] { ITEM, |
| PROPERTY_ALTERNATIVE_LIST }); |
| fTableViewer.setCellModifier(this); |
| fTableViewer.setInput(fAlternatives); |
| |
| // set initial selection |
| for (int i = 0; i < fTableViewer.getTable().getItemCount(); i++) { |
| Object element = fTableViewer.getElementAt(i); |
| RepositoryLocationItem locationItem = (RepositoryLocationItem) element; |
| // select second entry only when it's compatible and the first is |
| // unknown (from project set file) |
| if (locationItem.alternativeList.size() > 1 |
| && !KnownRepositories |
| .getInstance() |
| .isKnownRepository( |
| ((ICVSRepositoryLocation) locationItem.alternativeList |
| .get(0)).getLocation(false)) |
| && CVSRepositoryLocationMatcher |
| .isCompatible( |
| locationItem.location, |
| (ICVSRepositoryLocation) locationItem.alternativeList |
| .get(1), false)) { |
| locationItem.selected = 1; |
| } |
| } |
| fTableViewer.refresh(); |
| return table; |
| } |
| |
| @Override |
| public Object getValue(Object element, String property) { |
| |
| final Item item = (Item) element; |
| |
| if (PROPERTY_ALTERNATIVE_LIST.equals(property)) { |
| return Integer.valueOf(item.selected); |
| } |
| return null; |
| } |
| |
| @Override |
| public boolean canModify(Object element, String property) { |
| // set the correct cell editor for this element |
| cellEditors[1] = getCellEditor(element); |
| // only allow modification for editable elements |
| return PROPERTY_ALTERNATIVE_LIST.equals(property); |
| } |
| |
| private CellEditor getCellEditor(Object element) { |
| |
| if (element instanceof RepositoryLocationItem) { |
| // create combo-box list of alternative repositories |
| RepositoryLocationItem item = (RepositoryLocationItem) element; |
| |
| return new ComboBoxCellEditor(table, getFilteredAlternativeRepositoriesForDisplay(item), |
| SWT.READ_ONLY); |
| } |
| return dummyAlternativeRepositoryEditor; |
| } |
| |
| @Override |
| public void modify(Object element, String property, Object value) { |
| |
| final IStructuredSelection selection = fTableViewer.getStructuredSelection(); |
| final Item item = (Item) selection.getFirstElement(); |
| if (item == null) |
| return; |
| |
| final int comboIndex = ((Integer) value).intValue(); |
| |
| if (PROPERTY_ALTERNATIVE_LIST.equals(property)) { |
| item.selected = comboIndex; |
| } |
| fTableViewer.refresh(item); |
| } |
| |
| @Override |
| public Image getColumnImage(Object element, int columnIndex) { |
| return null; |
| } |
| |
| @Override |
| public String getColumnText(Object element, int columnIndex) { |
| final Item item = (Item) element; |
| |
| switch (columnIndex) { |
| case 0: |
| return item.location.getLocation(false); |
| case 1: |
| return getFilteredAlternativeRepositoriesForDisplay(item)[item.selected]; |
| default: |
| return null; |
| } |
| } |
| |
| @Override |
| public void addListener(ILabelProviderListener listener) { |
| } |
| |
| @Override |
| public void dispose() { |
| } |
| |
| @Override |
| public boolean isLabelProperty(Object element, String property) { |
| return false; |
| } |
| |
| @Override |
| public void removeListener(ILabelProviderListener listener) { |
| } |
| |
| @Override |
| public Object[] getElements(Object inputElement) { |
| return ((Collection) inputElement).toArray(); |
| } |
| |
| @Override |
| public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { |
| } |
| |
| public IStructuredSelection getSelection() { |
| return fTableViewer.getStructuredSelection(); |
| } |
| |
| public TableViewer getViewer() { |
| return fTableViewer; |
| } |
| |
| /** |
| * @return a selected (in a combo box) alternative repository location for |
| * the first selected element |
| */ |
| public CVSRepositoryLocation getSelectedAlternativeRepository() { |
| RepositoryLocationItem firstElement = (RepositoryLocationItem) getSelection() |
| .getFirstElement(); |
| return (CVSRepositoryLocation) getFilteredAlternativeRepositories(firstElement) |
| .get(firstElement.selected); |
| } |
| |
| /** |
| * Add newly created repository location to all RepositoryLocationItems. The |
| * location is added at the end of a list. For selected and compatible rows |
| * it will be automatically selected. |
| * |
| * @param location |
| * Location to add. |
| */ |
| void addAlternativeRepository(ICVSRepositoryLocation location) { |
| for (int i = 0; i < fTableViewer.getTable().getItemCount(); i++) { |
| Object element = fTableViewer.getElementAt(i); |
| RepositoryLocationItem rli = (RepositoryLocationItem) element; |
| // TODO: at this moment a newly created repository location |
| // is added at the end of every locationItem, we could |
| // consider sorting the list again |
| rli.alternativeList.add(location); |
| if (getSelection().toList().contains(element) |
| && CVSRepositoryLocationMatcher.isCompatible(location, |
| rli.location, false)) { |
| // at the end |
| rli.selected = getFilteredAlternativeRepositories(rli).size() - 1; |
| } |
| } |
| fTableViewer.refresh(true); |
| } |
| |
| /** |
| * @return A map with repository location from the project set as a key and |
| * selected repository location from a combo box as value. |
| */ |
| public Map getSelected() { |
| Map map = new HashMap(); |
| for (Iterator iterator = fAlternatives.iterator(); iterator.hasNext();) { |
| RepositoryLocationItem rli = (RepositoryLocationItem) iterator |
| .next(); |
| map.put(rli.location, getFilteredAlternativeRepositories(rli).get(rli.selected)); |
| } |
| return map; |
| } |
| |
| /** |
| * Change the fShowOnlyCompatibeLocations flag. If set to <code>true</code> |
| * only compatible repository locations are shown, current selection will be |
| * updated when a non-compatible entry is selected. If set to |
| * <code>false</code> all repository locations are shown, current |
| * selection will be updated if necessary. |
| * |
| * @param show |
| * The flag |
| */ |
| public void setShowOnlyCompatibleLocations(boolean show) { |
| fShowOnlyCompatibeLocations = show; |
| for (int i = 0; i < fTableViewer.getTable().getItemCount(); i++) { |
| Object element = fTableViewer.getElementAt(i); |
| RepositoryLocationItem rli = (RepositoryLocationItem) element; |
| updateSelection(rli); |
| } |
| fTableViewer.refresh(true); |
| } |
| |
| private List getFilteredAlternativeRepositories(Item item) { |
| return getFilteredAlternativeRepositories(item, fShowOnlyCompatibeLocations); |
| } |
| |
| private List getFilteredAlternativeRepositories(Item item, boolean showOnlyCompatible) { |
| List alternativeList = item.alternativeList; |
| if (!showOnlyCompatible) { |
| return alternativeList; |
| } else { |
| List alternativeFiltered = new ArrayList(); |
| for (int i = 0; i < alternativeList.size(); i++) { |
| CVSRepositoryLocation repo = (CVSRepositoryLocation) alternativeList.get(i); |
| // If "Show only compatible..." option is on add only compatible |
| // locations or the location itself |
| if (!CVSRepositoryLocationMatcher.isCompatible(item.location, |
| repo, true)){ |
| continue; // skip this repo location |
| } |
| alternativeFiltered.add(repo); |
| } |
| return alternativeFiltered; |
| } |
| } |
| |
| private void updateSelection(Item item) { |
| if (fShowOnlyCompatibeLocations) { |
| int shift = 0; |
| for (int j = 0; j <= item.selected; j++) { |
| ICVSRepositoryLocation rl = (ICVSRepositoryLocation) item.alternativeList |
| .get(j); |
| if (!CVSRepositoryLocationMatcher.isCompatible(item.location, |
| rl, true)) { |
| shift++; |
| } |
| } |
| item.selected -= shift; |
| |
| // the selected location is neither compatible nor equal to the |
| // one from the project set |
| ICVSRepositoryLocation selected = (ICVSRepositoryLocation) getFilteredAlternativeRepositories( |
| item).get(item.selected); |
| if (!CVSRepositoryLocationMatcher.isCompatible(item.location, |
| selected, true)) { |
| item.selected = 0; // default |
| // find compatible |
| for (int j = 0; j < item.alternativeList.size(); j++) { |
| ICVSRepositoryLocation l = (ICVSRepositoryLocation) item.alternativeList |
| .get(j); |
| if (CVSRepositoryLocationMatcher.isCompatible(l, |
| item.location, true)) { |
| item.selected = j; |
| break; |
| } |
| } |
| } |
| } else { |
| // show all |
| int shift = 0; |
| // index of (item.)selected object from the full list |
| for (int j = 0; j <= getFilteredAlternativeRepositories(item) |
| .indexOf( |
| getFilteredAlternativeRepositories(item, true).get( |
| item.selected)); j++) { |
| ICVSRepositoryLocation rl = (ICVSRepositoryLocation) item.alternativeList |
| .get(j); |
| if (!CVSRepositoryLocationMatcher.isCompatible(item.location, rl, |
| true)) { |
| shift++; |
| } |
| } |
| item.selected += shift; |
| } |
| } |
| |
| private String[] getFilteredAlternativeRepositoriesForDisplay(Item item) { |
| List filteredAlternativeList = getFilteredAlternativeRepositories(item); |
| List repositoriesForDisplay = new ArrayList(); |
| for (int i = 0; i < filteredAlternativeList.size(); i++) { |
| CVSRepositoryLocation rl = (CVSRepositoryLocation) filteredAlternativeList |
| .get(i); |
| repositoriesForDisplay.add(rl.getLocation()); |
| } |
| return (String[]) repositoriesForDisplay.toArray(new String[0]); |
| } |
| |
| } |