Java tutorial
/******************************************************************************* * Copyright (c) 2007, 2011 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.equinox.p2.ui; import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Hashtable; import org.eclipse.core.runtime.*; import org.eclipse.equinox.internal.p2.core.helpers.LogHelper; import org.eclipse.equinox.internal.p2.ui.*; import org.eclipse.equinox.internal.p2.ui.dialogs.*; import org.eclipse.equinox.internal.p2.ui.model.*; import org.eclipse.equinox.internal.p2.ui.viewers.*; import org.eclipse.equinox.internal.provisional.p2.repository.RepositoryEvent; import org.eclipse.equinox.p2.core.ProvisionException; import org.eclipse.equinox.p2.operations.ProvisioningSession; import org.eclipse.equinox.p2.operations.RepositoryTracker; import org.eclipse.jface.dialogs.*; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.preference.PreferencePage; import org.eclipse.jface.viewers.*; import org.eclipse.jface.window.Window; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.accessibility.AccessibleAdapter; import org.eclipse.swt.accessibility.AccessibleEvent; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.dnd.*; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.eclipse.ui.*; import org.eclipse.ui.dialogs.PatternFilter; import org.eclipse.ui.progress.WorkbenchJob; import org.eclipse.ui.statushandlers.StatusManager; /** * Page that allows users to update, add, remove, import, and * export repositories. This page can be hosted inside a preference * dialog or inside its own dialog. * * When hosting this page inside a non-preference dialog, some of the * dialog methods will likely have to call page methods. The following * snippet shows how to host this page inside a TitleAreaDialog. * <pre> * TitleAreaDialog dialog = new TitleAreaDialog(shell) { * * RepositoryManipulationPage page; * * protected Control createDialogArea(Composite parent) { * page = new RepositoryManipulationPage(); * page.setProvisioningUI(ProvisioningUI.getDefaultUI()); * page.createControl(parent); * this.setTitle("Software Sites"); * this.setMessage("The enabled sites will be searched for software. Disabled sites are ignored."); * return page.getControl(); * } * * protected void okPressed() { * if (page.performOk()) * super.okPressed(); * } * * protected void cancelPressed() { * if (page.performCancel()) * super.cancelPressed(); * } * }; * dialog.open(); * </pre> * * @noextend This class is not intended to be subclassed by clients. * * @since 2.0 */ public class RepositoryManipulationPage extends PreferencePage implements IWorkbenchPreferencePage, ICopyable { final static String DEFAULT_FILTER_TEXT = ProvUIMessages.RepositoryManipulationPage_DefaultFilterString; private final static int FILTER_DELAY = 200; StructuredViewerProvisioningListener listener; CheckboxTableViewer repositoryViewer; Table table; ProvisioningUI ui; Policy policy; Display display; boolean changed = false; MetadataRepositoryElementComparator comparator; RepositoryDetailsLabelProvider labelProvider; RepositoryTracker tracker; RepositoryTracker localCacheRepoManipulator; /** * The input field is initialized lazily and should only be accessed via the {@link #getInput()} method. */ CachedMetadataRepositories input; Text pattern, details; PatternFilter filter; WorkbenchJob filterJob; Button addButton, removeButton, editButton, refreshButton, disableButton, exportButton; class CachedMetadataRepositories extends MetadataRepositories { private Hashtable<String, MetadataRepositoryElement> cachedElements; CachedMetadataRepositories() { super(ui); setIncludeDisabledRepositories(getPolicy().getRepositoriesVisible()); } public int getQueryType() { return QueryProvider.METADATA_REPOS; } public Object[] fetchChildren(Object o, IProgressMonitor monitor) { if (cachedElements == null) { Object[] children = super.fetchChildren(o, monitor); cachedElements = new Hashtable<String, MetadataRepositoryElement>(children.length); for (int i = 0; i < children.length; i++) { if (children[i] instanceof MetadataRepositoryElement) { put((MetadataRepositoryElement) children[i]); } } } return cachedElements.values().toArray(); } MetadataRepositoryElement[] getElements() { return cachedElements.values().toArray(new MetadataRepositoryElement[cachedElements.size()]); } void remove(MetadataRepositoryElement element) { cachedElements.remove(getKey(element.getLocation())); } void put(MetadataRepositoryElement element) { cachedElements.put(getKey(element.getLocation()), element); } MetadataRepositoryElement get(URI location) { return cachedElements.get(getKey(location)); } String getKey(URI location) { String key = URIUtil.toUnencodedString(location); int length = key.length(); if (length > 0 && key.charAt(length - 1) == '/') { key = key.substring(0, length - 1); } return key; } } class MetadataRepositoryPatternFilter extends PatternFilter { MetadataRepositoryPatternFilter() { setIncludeLeadingWildcard(true); } public boolean isElementVisible(Viewer viewer, Object element) { if (element instanceof MetadataRepositoryElement) { return wordMatches(labelProvider.getColumnText(element, RepositoryDetailsLabelProvider.COL_NAME) + " " + labelProvider.getColumnText(element, RepositoryDetailsLabelProvider.COL_LOCATION)); //$NON-NLS-1$ } return false; } } /** * Create a repository manipulation page that will display the repositories * available to the user. */ public RepositoryManipulationPage() { this.setProvisioningUI(ProvisioningUI.getDefaultUI()); } /** * Set the provisioning UI that provides the session, policy, and other * services for the UI. This method must be called before the contents are * created or it will have no effect. * * @param ui the provisioning UI to use for this page. */ public void setProvisioningUI(ProvisioningUI ui) { this.ui = ui; this.policy = ui.getPolicy(); tracker = ui.getRepositoryTracker(); } protected Control createContents(Composite parent) { display = parent.getDisplay(); // The help refers to the full-blown dialog. No help if it's read only. if (policy.getRepositoriesVisible()) PlatformUI.getWorkbench().getHelpSystem().setHelp(parent.getShell(), IProvHelpContextIds.REPOSITORY_MANIPULATION_DIALOG); Composite composite = new Composite(parent, SWT.NONE); GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); composite.setLayoutData(gd); GridLayout layout = new GridLayout(); layout.numColumns = policy.getRepositoriesVisible() ? 2 : 1; layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); composite.setLayout(layout); // Filter box pattern = new Text(composite, SWT.SINGLE | SWT.BORDER | SWT.SEARCH | SWT.CANCEL); pattern.getAccessible().addAccessibleListener(new AccessibleAdapter() { public void getName(AccessibleEvent e) { e.result = DEFAULT_FILTER_TEXT; } }); pattern.setText(DEFAULT_FILTER_TEXT); pattern.selectAll(); pattern.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { applyFilter(); } }); pattern.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { if (e.keyCode == SWT.ARROW_DOWN) { if (table.getItemCount() > 0) { table.setFocus(); } else if (e.character == SWT.CR) { return; } } } }); pattern.addFocusListener(new FocusAdapter() { public void focusGained(FocusEvent e) { display.asyncExec(new Runnable() { public void run() { if (!pattern.isDisposed()) { if (DEFAULT_FILTER_TEXT.equals(pattern.getText().trim())) { pattern.selectAll(); } } } }); } }); gd = new GridData(SWT.FILL, SWT.FILL, true, false); pattern.setLayoutData(gd); // spacer to fill other column if (policy.getRepositoriesVisible()) new Label(composite, SWT.NONE); // Table of available repositories table = new Table(composite, SWT.CHECK | SWT.MULTI | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); repositoryViewer = new CheckboxTableViewer(table); // Key listener for delete table.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { if (e.keyCode == SWT.DEL) { removeRepositories(); } } }); setTableColumns(); CopyUtils.activateCopy(this, table); repositoryViewer.setComparer(new ProvElementComparer()); comparator = new MetadataRepositoryElementComparator(RepositoryDetailsLabelProvider.COL_NAME); repositoryViewer.setComparator(comparator); filter = new MetadataRepositoryPatternFilter(); repositoryViewer.setFilters(new ViewerFilter[] { filter }); // We don't need a deferred content provider because we are caching local results before // actually querying repositoryViewer.setContentProvider(new ProvElementContentProvider()); labelProvider = new RepositoryDetailsLabelProvider(); repositoryViewer.setLabelProvider(labelProvider); // Edit the nickname repositoryViewer.setCellModifier(new ICellModifier() { public boolean canModify(Object element, String property) { return element instanceof MetadataRepositoryElement; } public Object getValue(Object element, String property) { return ((MetadataRepositoryElement) element).getName(); } public void modify(Object element, String property, Object value) { if (value != null && value.toString().length() >= 0) { MetadataRepositoryElement repo; if (element instanceof Item) { repo = (MetadataRepositoryElement) ((Item) element).getData(); } else if (element instanceof MetadataRepositoryElement) { repo = (MetadataRepositoryElement) element; } else { return; } if (!value.toString().equals(repo.getName())) { changed = true; repo.setNickname(value.toString()); if (comparator.getSortKey() == RepositoryDetailsLabelProvider.COL_NAME) repositoryViewer.refresh(true); else repositoryViewer.update(repo, null); } } } }); repositoryViewer.setColumnProperties(new String[] { "nickname" }); //$NON-NLS-1$ repositoryViewer.setCellEditors(new CellEditor[] { new TextCellEditor(repositoryViewer.getTable()) }); repositoryViewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { if (policy.getRepositoriesVisible()) validateButtons(); setDetails(); } }); repositoryViewer.setCheckStateProvider(new ICheckStateProvider() { public boolean isChecked(Object element) { return ((MetadataRepositoryElement) element).isEnabled(); } public boolean isGrayed(Object element) { return false; } }); repositoryViewer.addCheckStateListener(new ICheckStateListener() { public void checkStateChanged(CheckStateChangedEvent event) { MetadataRepositoryElement element = (MetadataRepositoryElement) event.getElement(); element.setEnabled(event.getChecked()); // paranoid that an equal but not identical element was passed in as the selection. // update the cache map just in case. getInput().put(element); // update the viewer to show the change updateForEnablementChange(new MetadataRepositoryElement[] { element }); } }); // Input last repositoryViewer.setInput(getInput()); GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); data.widthHint = convertWidthInCharsToPixels(ILayoutConstants.DEFAULT_TABLE_WIDTH); data.heightHint = convertHeightInCharsToPixels(ILayoutConstants.DEFAULT_TABLE_HEIGHT); table.setLayoutData(data); // Drop targets and vertical buttons only if repository manipulation is provided. if (policy.getRepositoriesVisible()) { DropTarget target = new DropTarget(table, DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK); target.setTransfer(new Transfer[] { URLTransfer.getInstance(), FileTransfer.getInstance() }); target.addDropListener(new RepositoryManipulatorDropTarget(ui, table)); // Vertical buttons Composite verticalButtonBar = createVerticalButtonBar(composite); data = new GridData(SWT.FILL, SWT.FILL, false, false); data.verticalAlignment = SWT.TOP; data.verticalIndent = 0; verticalButtonBar.setLayoutData(data); listener = getViewerProvisioningListener(); ProvUI.getProvisioningEventBus(ui.getSession()).addListener(listener); composite.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent event) { ProvUI.getProvisioningEventBus(ui.getSession()).removeListener(listener); } }); validateButtons(); } // Details area details = new Text(composite, SWT.READ_ONLY | SWT.WRAP); data = new GridData(SWT.FILL, SWT.FILL, true, false); data.heightHint = convertHeightInCharsToPixels(ILayoutConstants.DEFAULT_SITEDETAILS_HEIGHT); details.setLayoutData(data); Dialog.applyDialogFont(composite); return composite; } private Button createVerticalButton(Composite parent, String label, boolean defaultButton) { Button button = new Button(parent, SWT.PUSH); button.setText(label); GridData data = setVerticalButtonLayoutData(button); data.horizontalAlignment = GridData.FILL; button.setToolTipText(label); if (defaultButton) { Shell shell = parent.getShell(); if (shell != null) { shell.setDefaultButton(button); } } return button; } private GridData setVerticalButtonLayoutData(Button button) { GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL); int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); Point minSize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); data.widthHint = Math.max(widthHint, minSize.x); button.setLayoutData(data); return data; } private void setTableColumns() { table.setHeaderVisible(true); String[] columnHeaders; if (policy.getRepositoriesVisible()) columnHeaders = new String[] { ProvUIMessages.RepositoryManipulationPage_NameColumnTitle, ProvUIMessages.RepositoryManipulationPage_LocationColumnTitle, ProvUIMessages.RepositoryManipulationPage_EnabledColumnTitle }; else columnHeaders = new String[] { ProvUIMessages.RepositoryManipulationPage_NameColumnTitle, ProvUIMessages.RepositoryManipulationPage_LocationColumnTitle }; for (int i = 0; i < columnHeaders.length; i++) { TableColumn tc = new TableColumn(table, SWT.NONE, i); tc.setResizable(true); tc.setText(columnHeaders[i]); if (i == RepositoryDetailsLabelProvider.COL_ENABLEMENT) { tc.setWidth(convertWidthInCharsToPixels(ILayoutConstants.DEFAULT_SMALL_COLUMN_WIDTH)); tc.setAlignment(SWT.CENTER); } else if (i == RepositoryDetailsLabelProvider.COL_NAME) { tc.setWidth(convertWidthInCharsToPixels(ILayoutConstants.DEFAULT_COLUMN_WIDTH)); } else { tc.setWidth(convertWidthInCharsToPixels(ILayoutConstants.DEFAULT_PRIMARY_COLUMN_WIDTH)); } tc.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { columnSelected((TableColumn) e.widget); } public void widgetSelected(SelectionEvent e) { columnSelected((TableColumn) e.widget); } }); // First column only if (i == 0) { table.setSortColumn(tc); table.setSortDirection(SWT.UP); } } } private Composite createVerticalButtonBar(Composite parent) { // Create composite. Composite composite = new Composite(parent, SWT.NONE); initializeDialogUnits(composite); // create a layout with spacing and margins appropriate for the font // size. GridLayout layout = new GridLayout(); layout.numColumns = 1; layout.marginWidth = 5; layout.marginHeight = 0; layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); composite.setLayout(layout); createVerticalButtons(composite); return composite; } private void createVerticalButtons(Composite parent) { addButton = createVerticalButton(parent, ProvUIMessages.RepositoryManipulationPage_Add, false); addButton.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { addRepository(); } }); editButton = createVerticalButton(parent, ProvUIMessages.RepositoryManipulationPage_Edit, false); editButton.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { changeRepositoryProperties(); } }); removeButton = createVerticalButton(parent, ProvUIMessages.RepositoryManipulationPage_Remove, false); removeButton.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { removeRepositories(); } }); refreshButton = createVerticalButton(parent, ProvUIMessages.RepositoryManipulationPage_RefreshConnection, false); refreshButton.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { refreshRepository(); } }); disableButton = createVerticalButton(parent, ProvUIMessages.RepositoryManipulationPage_DisableButton, false); disableButton.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { toggleRepositoryEnablement(); } }); Button button = createVerticalButton(parent, ProvUIMessages.RepositoryManipulationPage_Import, false); button.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { importRepositories(); } }); exportButton = createVerticalButton(parent, ProvUIMessages.RepositoryManipulationPage_Export, false); exportButton.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { exportRepositories(); } }); } CachedMetadataRepositories getInput() { if (input == null) input = new CachedMetadataRepositories(); return input; } /* * (non-Javadoc) * @see org.eclipse.jface.preference.PreferencePage#performOk() */ public boolean performOk() { if (changed) ElementUtils.updateRepositoryUsingElements(ui, getElements(), getShell()); return super.performOk(); } private StructuredViewerProvisioningListener getViewerProvisioningListener() { return new StructuredViewerProvisioningListener(RepositoryManipulationPage.this.getClass().getName(), repositoryViewer, ProvUIProvisioningListener.PROV_EVENT_METADATA_REPOSITORY, ui.getOperationRunner()) { protected void repositoryDiscovered(RepositoryEvent e) { RepositoryManipulationPage.this.safeRefresh(null); } protected void repositoryChanged(RepositoryEvent e) { RepositoryManipulationPage.this.safeRefresh(null); } }; } MetadataRepositoryElement[] getElements() { return getInput().getElements(); } MetadataRepositoryElement[] getSelectedElements() { Object[] items = ((IStructuredSelection) repositoryViewer.getSelection()).toArray(); ArrayList<Object> list = new ArrayList<Object>(items.length); for (int i = 0; i < items.length; i++) { if (items[i] instanceof MetadataRepositoryElement) list.add(items[i]); } return list.toArray(new MetadataRepositoryElement[list.size()]); } void validateButtons() { MetadataRepositoryElement[] elements = getSelectedElements(); exportButton.setEnabled(elements.length > 0); removeButton.setEnabled(elements.length > 0); editButton.setEnabled(elements.length == 1); refreshButton.setEnabled(elements.length == 1); if (elements.length >= 1) { if (toggleMeansDisable(elements)) disableButton.setText(ProvUIMessages.RepositoryManipulationPage_DisableButton); else disableButton.setText(ProvUIMessages.RepositoryManipulationPage_EnableButton); disableButton.setEnabled(true); } else { disableButton.setText(ProvUIMessages.RepositoryManipulationPage_EnableButton); disableButton.setEnabled(false); } } void addRepository() { AddRepositoryDialog dialog = new AddRepositoryDialog(getShell(), ui) { protected RepositoryTracker getRepositoryTracker() { return RepositoryManipulationPage.this.getLocalCacheRepoTracker(); } }; dialog.setTitle(ProvUIMessages.ColocatedRepositoryManipulator_AddSiteOperationLabel); dialog.open(); } void refreshRepository() { final MetadataRepositoryElement[] selected = getSelectedElements(); final ProvisionException[] fail = new ProvisionException[1]; final boolean[] remove = new boolean[1]; remove[0] = false; if (selected.length != 1) return; final URI location = selected[0].getLocation(); ProgressMonitorDialog dialog = new ProgressMonitorDialog(getShell()); try { dialog.run(true, true, new IRunnableWithProgress() { public void run(IProgressMonitor monitor) { monitor.beginTask( NLS.bind(ProvUIMessages.RepositoryManipulationPage_ContactingSiteMessage, location), 100); try { // Batch the events for this operation so that any events on reload (discovery, etc.) will be ignored // in the UI as they happen. ui.signalRepositoryOperationStart(); tracker.clearRepositoryNotFound(location); // If the managers don't know this repo, refreshing it will not work. // We temporarily add it, but we must remove it in case the user cancels out of this page. if (!includesRepo(tracker.getKnownRepositories(ui.getSession()), location)) { remove[0] = true; // We don't want to use the tracker here because it ensures that additions are // reported as user events to be responded to. We don't want, for example, the // install wizard to change combo selections based on what is done here. ProvUI.getMetadataRepositoryManager(ui.getSession()).addRepository(location); ProvUI.getArtifactRepositoryManager(ui.getSession()).addRepository(location); } // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=312332 // We assume repository colocation here. Ideally we should not do this, but the // RepositoryTracker API is swallowing the refresh errors. SubMonitor sub = SubMonitor.convert(monitor, 200); try { ProvUI.getMetadataRepositoryManager(ui.getSession()).refreshRepository(location, sub.newChild(100)); } catch (ProvisionException e) { fail[0] = e; } try { ProvUI.getArtifactRepositoryManager(ui.getSession()).refreshRepository(location, sub.newChild(100)); } catch (ProvisionException e) { // Failure in the artifact repository. We will not report this because the user has no separate visibility // of the artifact repository. We should log the error. If this repository fails during a download, the error // will be reported at that time to the user, when it matters. This also prevents false error reporting when // a metadata repository didn't actually have a colocated artifact repository. LogHelper.log(e); } } catch (OperationCanceledException e) { // Catch canceled login attempts fail[0] = new ProvisionException(new Status(IStatus.CANCEL, ProvUIActivator.PLUGIN_ID, ProvUIMessages.RepositoryManipulationPage_RefreshOperationCanceled, e)); } finally { // Check if the monitor was canceled if (fail[0] == null && monitor.isCanceled()) fail[0] = new ProvisionException(new Status(IStatus.CANCEL, ProvUIActivator.PLUGIN_ID, ProvUIMessages.RepositoryManipulationPage_RefreshOperationCanceled)); // If we temporarily added a repo so we could read it, remove it. if (remove[0]) { ProvUI.getMetadataRepositoryManager(ui.getSession()).removeRepository(location); ProvUI.getArtifactRepositoryManager(ui.getSession()).removeRepository(location); } ui.signalRepositoryOperationComplete(null, false); } } }); } catch (InvocationTargetException e) { // nothing to report } catch (InterruptedException e) { // nothing to report } if (fail[0] != null) { // If the repo was not found, tell ProvUI that we will be reporting it. // We are going to report problems directly to the status manager because we // do not want the automatic repo location editing to kick in. if (fail[0].getStatus().getCode() == ProvisionException.REPOSITORY_NOT_FOUND) { tracker.addNotFound(location); } if (!fail[0].getStatus().matches(IStatus.CANCEL)) { // An error is only shown if the dialog was not canceled ProvUI.handleException(fail[0], null, StatusManager.SHOW); } } else { // Confirm that it was successful MessageDialog.openInformation(getShell(), ProvUIMessages.RepositoryManipulationPage_TestConnectionTitle, NLS.bind(ProvUIMessages.RepositoryManipulationPage_TestConnectionSuccess, URIUtil.toUnencodedString(location))); } repositoryViewer.update(selected[0], null); setDetails(); } boolean includesRepo(URI[] repos, URI repo) { for (int i = 0; i < repos.length; i++) if (repos[i].equals(repo)) return true; return false; } void toggleRepositoryEnablement() { MetadataRepositoryElement[] selected = getSelectedElements(); if (selected.length >= 1) { boolean enableSites = !toggleMeansDisable(selected); for (int i = 0; i < selected.length; i++) { selected[i].setEnabled(enableSites); getInput().put(selected[i]); } updateForEnablementChange(selected); } validateButtons(); } void updateForEnablementChange(MetadataRepositoryElement[] updated) { if (comparator.getSortKey() == RepositoryDetailsLabelProvider.COL_ENABLEMENT) repositoryViewer.refresh(true); else for (int i = 0; i < updated.length; i++) repositoryViewer.update(updated[i], null); changed = true; } void importRepositories() { BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() { public void run() { MetadataRepositoryElement[] imported = UpdateManagerCompatibility.importSites(getShell()); if (imported.length > 0) { changed = true; for (int i = 0; i < imported.length; i++) getInput().put(imported[i]); safeRefresh(null); } } }); } void exportRepositories() { BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() { public void run() { MetadataRepositoryElement[] elements = getSelectedElements(); if (elements.length == 0) elements = getElements(); UpdateManagerCompatibility.exportSites(getShell(), elements); } }); } void changeRepositoryProperties() { final MetadataRepositoryElement[] selected = getSelectedElements(); if (selected.length != 1) return; RepositoryNameAndLocationDialog dialog = new RepositoryNameAndLocationDialog(getShell(), ui) { protected String getInitialLocationText() { return URIUtil.toUnencodedString(selected[0].getLocation()); } protected String getInitialNameText() { return selected[0].getName(); } }; int retCode = dialog.open(); if (retCode == Window.OK) { selected[0].setNickname(dialog.getName()); selected[0].setLocation(dialog.getLocation()); changed = true; repositoryViewer.update(selected[0], null); setDetails(); } } void columnSelected(TableColumn tc) { TableColumn[] cols = table.getColumns(); for (int i = 0; i < cols.length; i++) { if (cols[i] == tc) { if (i != comparator.getSortKey()) { comparator.setSortKey(i); table.setSortColumn(tc); comparator.sortAscending(); table.setSortDirection(SWT.UP); } else { if (comparator.isAscending()) { table.setSortDirection(SWT.DOWN); comparator.sortDescending(); } else { table.setSortDirection(SWT.UP); comparator.sortAscending(); } } repositoryViewer.refresh(); break; } } } void safeRefresh(final MetadataRepositoryElement elementToSelect) { Runnable runnable = new Runnable() { public void run() { repositoryViewer.refresh(); if (elementToSelect != null) repositoryViewer.setSelection(new StructuredSelection(elementToSelect), true); } }; if (Display.getCurrent() == null) display.asyncExec(runnable); else runnable.run(); } void applyFilter() { String text = pattern.getText(); if (text == DEFAULT_FILTER_TEXT) text = ""; //$NON-NLS-1$ if (text.length() == 0) filter.setPattern(null); else filter.setPattern(text); if (filterJob != null) filterJob.cancel(); filterJob = new WorkbenchJob("filter job") { //$NON-NLS-1$ public IStatus runInUIThread(IProgressMonitor monitor) { if (monitor.isCanceled()) return Status.CANCEL_STATUS; if (!repositoryViewer.getTable().isDisposed()) repositoryViewer.refresh(); return Status.OK_STATUS; } }; filterJob.setSystem(true); filterJob.schedule(FILTER_DELAY); } void setDetails() { MetadataRepositoryElement[] selections = getSelectedElements(); if (selections.length == 1) { details.setText(selections[0].getDescription()); } else { details.setText(""); //$NON-NLS-1$ } } /* (non-Javadoc) * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench) */ public void init(IWorkbench workbench) { noDefaultAndApplyButton(); if (ui == null) { setProvisioningUI(ProvisioningUI.getDefaultUI()); } } void removeRepositories() { MetadataRepositoryElement[] selections = getSelectedElements(); if (selections.length > 0) { String message = ProvUIMessages.RepositoryManipulationPage_RemoveConfirmMessage; if (selections.length == 1) message = NLS.bind(ProvUIMessages.RepositoryManipulationPage_RemoveConfirmSingleMessage, URIUtil.toUnencodedString(selections[0].getLocation())); if (MessageDialog.openQuestion(getShell(), ProvUIMessages.RepositoryManipulationPage_RemoveConfirmTitle, message)) { changed = true; for (int i = 0; i < selections.length; i++) { getInput().remove(selections[i]); } safeRefresh(null); } } } // Return a repo manipulator that only operates on the local cache. // Labels and other presentation info are used from the original manipulator. RepositoryTracker getLocalCacheRepoTracker() { if (localCacheRepoManipulator == null) localCacheRepoManipulator = new RepositoryTracker() { public void addRepository(URI location, String nickname, ProvisioningSession session) { MetadataRepositoryElement element = getInput().get(location); if (element == null) { element = new MetadataRepositoryElement(getInput(), null, ui, location, true); getInput().put(element); } if (nickname != null) element.setNickname(nickname); changed = true; safeRefresh(element); } public URI[] getKnownRepositories(ProvisioningSession session) { return RepositoryManipulationPage.this.getKnownRepositories(); } public void removeRepositories(URI[] repoLocations, ProvisioningSession session) { RepositoryManipulationPage.this.removeRepositories(); } public void refreshRepositories(URI[] locations, ProvisioningSession session, IProgressMonitor monitor) { // Nothing to refresh in the local cache } public IStatus validateRepositoryLocation(ProvisioningSession session, URI location, boolean contactRepositories, IProgressMonitor monitor) { IStatus status = super.validateRepositoryLocation(session, location, contactRepositories, monitor); if (status.isOK()) { String repoString = URIUtil.toUnencodedString(location); int length = repoString.length(); if (length > 0 && repoString.charAt(length - 1) == '/') { try { location = URIUtil.fromString(repoString.substring(0, length - 1)); } catch (URISyntaxException e) { return status; } status = super.validateRepositoryLocation(session, location, contactRepositories, monitor); } } return status; } }; return localCacheRepoManipulator; } /* * (non-Javadoc) * @see org.eclipse.equinox.p2.ui.ICopyable#copyToClipboard(org.eclipse.swt.widgets.Control) */ public void copyToClipboard(Control activeControl) { MetadataRepositoryElement[] elements = getSelectedElements(); if (elements.length == 0) elements = getElements(); String text = ""; //$NON-NLS-1$ StringBuffer buffer = new StringBuffer(); for (int i = 0; i < elements.length; i++) { buffer.append(labelProvider.getClipboardText(elements[i], CopyUtils.DELIMITER)); if (i > 0) buffer.append(CopyUtils.NEWLINE); } text = buffer.toString(); if (text.length() == 0) return; Clipboard clipboard = new Clipboard(PlatformUI.getWorkbench().getDisplay()); clipboard.setContents(new Object[] { text }, new Transfer[] { TextTransfer.getInstance() }); clipboard.dispose(); } // If more than half of the selected repos are enabled, toggle means disable. // Otherwise it means enable. private boolean toggleMeansDisable(MetadataRepositoryElement[] elements) { double count = 0; for (int i = 0; i < elements.length; i++) if (elements[i].isEnabled()) count++; return (count / elements.length) > 0.5; } URI[] getKnownRepositories() { MetadataRepositoryElement[] elements = getElements(); URI[] locations = new URI[elements.length]; for (int i = 0; i < elements.length; i++) locations[i] = elements[i].getLocation(); return locations; } }