Java tutorial
/******************************************************************************* * Copyright (c) 2009, 2015 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.pde.internal.ui.shared.target; import java.util.*; import java.util.List; import org.eclipse.core.runtime.*; import org.eclipse.core.runtime.jobs.*; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.viewers.*; import org.eclipse.jface.window.Window; import org.eclipse.jface.wizard.IWizard; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.pde.core.target.*; import org.eclipse.pde.internal.core.PDECore; import org.eclipse.pde.internal.core.target.*; import org.eclipse.pde.internal.ui.PDEPlugin; import org.eclipse.pde.internal.ui.SWTFactory; import org.eclipse.pde.internal.ui.editor.FormLayoutFactory; import org.eclipse.pde.internal.ui.editor.targetdefinition.TargetEditor; import org.eclipse.pde.internal.ui.shared.target.IUContentProvider.IUWrapper; import org.eclipse.pde.internal.ui.wizards.target.TargetDefinitionContentPage; import org.eclipse.pde.ui.target.ITargetLocationEditor; import org.eclipse.pde.ui.target.ITargetLocationUpdater; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.progress.UIJob; /** * UI part that can be added to a dialog or to a form editor. Contains a table displaying * the bundle containers of a target definition. Also has buttons to add, edit and remove * bundle containers of varying types. * * @see TargetEditor * @see TargetDefinitionContentPage * @see ITargetDefinition * @see ITargetLocation */ public class TargetLocationsGroup { private TreeViewer fTreeViewer; private Button fAddButton; private Button fEditButton; private Button fRemoveButton; private Button fUpdateButton; private Button fReloadButton; private Button fShowContentButton; private ITargetDefinition fTarget; private ListenerList fChangeListeners = new ListenerList(); /** * Creates this part using the form toolkit and adds it to the given composite. * * @param parent parent composite * @param toolkit toolkit to create the widgets with * @return generated instance of the table part */ public static TargetLocationsGroup createInForm(Composite parent, FormToolkit toolkit) { TargetLocationsGroup contentTable = new TargetLocationsGroup(); contentTable.createFormContents(parent, toolkit); return contentTable; } /** * Creates this part using standard dialog widgets and adds it to the given composite. * * @param parent parent composite * @return generated instance of the table part */ public static TargetLocationsGroup createInDialog(Composite parent) { TargetLocationsGroup contentTable = new TargetLocationsGroup(); contentTable.createDialogContents(parent); return contentTable; } /** * Private constructor, use one of {@link #createTableInDialog(Composite, ITargetChangedListener)} * or {@link #createTableInForm(Composite, FormToolkit, ITargetChangedListener)}. * * @param reporter reporter implementation that will handle resolving and changes to the containers */ private TargetLocationsGroup() { } /** * Adds a listener to the set of listeners that will be notified when the bundle containers * are modified. This method has no effect if the listener has already been added. * * @param listener target changed listener to add */ public void addTargetChangedListener(ITargetChangedListener listener) { fChangeListeners.add(listener); } /** * Creates the part contents from a toolkit * @param parent parent composite * @param toolkit form toolkit to create widgets */ private void createFormContents(Composite parent, FormToolkit toolkit) { Composite comp = toolkit.createComposite(parent); comp.setLayout(FormLayoutFactory.createSectionClientGridLayout(false, 2)); comp.setLayoutData(new GridData(GridData.FILL_BOTH | GridData.GRAB_VERTICAL)); Tree atree = toolkit.createTree(comp, SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI); atree.setLayout(new GridLayout()); GridData gd = new GridData(GridData.FILL_BOTH); atree.setLayoutData(gd); atree.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if (e.keyCode == SWT.DEL && fRemoveButton.getEnabled()) { handleRemove(); } } }); Composite buttonComp = toolkit.createComposite(comp); GridLayout layout = new GridLayout(); layout.marginWidth = layout.marginHeight = 0; buttonComp.setLayout(layout); buttonComp.setLayoutData(new GridData(GridData.FILL_VERTICAL)); fAddButton = toolkit.createButton(buttonComp, Messages.BundleContainerTable_0, SWT.PUSH); fEditButton = toolkit.createButton(buttonComp, Messages.BundleContainerTable_1, SWT.PUSH); fRemoveButton = toolkit.createButton(buttonComp, Messages.BundleContainerTable_2, SWT.PUSH); fUpdateButton = toolkit.createButton(buttonComp, Messages.BundleContainerTable_3, SWT.PUSH); fReloadButton = toolkit.createButton(buttonComp, Messages.BundleContainerTable_4, SWT.PUSH); fShowContentButton = toolkit.createButton(comp, Messages.TargetLocationsGroup_1, SWT.CHECK); initializeTreeViewer(atree); initializeButtons(); toolkit.paintBordersFor(comp); } /** * Creates the part contents using SWTFactory * @param parent parent composite */ private void createDialogContents(Composite parent) { Composite comp = SWTFactory.createComposite(parent, 2, 1, GridData.FILL_BOTH, 0, 0); Tree atree = new Tree(comp, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER | SWT.MULTI); atree.setFont(comp.getFont()); atree.setLayout(new GridLayout()); GridData gd = new GridData(GridData.FILL_BOTH); gd.widthHint = 200; atree.setLayoutData(gd); atree.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if (e.keyCode == SWT.DEL && fRemoveButton.getEnabled()) { handleRemove(); } } }); Composite buttonComp = SWTFactory.createComposite(comp, 2, 1, GridData.FILL_BOTH); GridLayout layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; buttonComp.setLayout(layout); buttonComp.setLayoutData(new GridData(GridData.FILL_VERTICAL)); fAddButton = SWTFactory.createPushButton(buttonComp, Messages.BundleContainerTable_0, null); fEditButton = SWTFactory.createPushButton(buttonComp, Messages.BundleContainerTable_1, null); fRemoveButton = SWTFactory.createPushButton(buttonComp, Messages.BundleContainerTable_2, null); fUpdateButton = SWTFactory.createPushButton(buttonComp, Messages.BundleContainerTable_3, null); fReloadButton = SWTFactory.createPushButton(buttonComp, Messages.BundleContainerTable_4, null); fShowContentButton = SWTFactory.createCheckButton(comp, Messages.TargetLocationsGroup_1, null, false, 2); initializeTreeViewer(atree); initializeButtons(); } /** * Sets up the tree viewer using the given tree * @param tree */ private void initializeTreeViewer(Tree tree) { fTreeViewer = new TreeViewer(tree); fTreeViewer.setContentProvider(new TargetLocationContentProvider()); fTreeViewer.setLabelProvider(new TargetLocationLabelProvider(true, false)); fTreeViewer.setComparator(new ViewerComparator() { @Override public int compare(Viewer viewer, Object e1, Object e2) { // Status at the end of the list if (e1 instanceof IStatus && !(e2 instanceof IStatus)) { return 1; } if (e2 instanceof IStatus && !(e1 instanceof IStatus)) { return -1; } return super.compare(viewer, e1, e2); } }); fTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { updateButtons(); } }); fTreeViewer.addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { if (!event.getSelection().isEmpty()) { handleEdit(); } } }); fTreeViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS); } /** * Sets up the buttons, the button fields must already be created before calling this method */ private void initializeButtons() { fAddButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { handleAdd(); } }); fAddButton.setLayoutData(new GridData()); SWTFactory.setButtonDimensionHint(fAddButton); fEditButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { handleEdit(); } }); fEditButton.setLayoutData(new GridData()); fEditButton.setEnabled(false); SWTFactory.setButtonDimensionHint(fEditButton); fRemoveButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { handleRemove(); } }); fRemoveButton.setLayoutData(new GridData()); fRemoveButton.setEnabled(false); SWTFactory.setButtonDimensionHint(fRemoveButton); fUpdateButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { handleUpdate(); } }); fUpdateButton.setLayoutData(new GridData()); fUpdateButton.setEnabled(false); SWTFactory.setButtonDimensionHint(fUpdateButton); fReloadButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { handleReload(); } }); fReloadButton.setLayoutData(new GridData()); fReloadButton.setEnabled(true); SWTFactory.setButtonDimensionHint(fReloadButton); fShowContentButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { ((TargetLocationContentProvider) fTreeViewer.getContentProvider()) .setShowLocationContent(fShowContentButton.getSelection()); fTreeViewer.refresh(); fTreeViewer.expandAll(); } }); fShowContentButton.setLayoutData(new GridData()); SWTFactory.setButtonDimensionHint(fShowContentButton); } /** * Sets the target definition model to use as input for the tree, can be called with different * models to change the tree's input. * @param target target model */ public void setInput(ITargetDefinition target) { fTarget = target; fTreeViewer.setInput(fTarget); updateButtons(); } private void handleAdd() { AddBundleContainerWizard wizard = new AddBundleContainerWizard(fTarget); Shell parent = fTreeViewer.getTree().getShell(); WizardDialog dialog = new WizardDialog(parent, wizard); if (dialog.open() != Window.CANCEL) { contentsChanged(false); fTreeViewer.refresh(); updateButtons(); } } private void handleEdit() { IStructuredSelection selection = (IStructuredSelection) fTreeViewer.getSelection(); for (Iterator<?> iterator = selection.iterator(); iterator.hasNext();) { Object currentSelection = iterator.next(); if (currentSelection instanceof ITargetLocation) { ITargetLocation location = (ITargetLocation) currentSelection; ITargetLocationEditor editor = (ITargetLocationEditor) Platform.getAdapterManager() .getAdapter(location, ITargetLocationEditor.class); if (editor != null) { if (editor.canEdit(fTarget, location)) { IWizard editWizard = editor.getEditWizard(fTarget, location); if (editWizard != null) { Shell parent = fTreeViewer.getTree().getShell(); WizardDialog wizard = new WizardDialog(parent, editWizard); if (wizard.open() == Window.OK) { // Update the table // TODO Do we need to force a resolve for IUBundleContainers? contentsChanged(false); fTreeViewer.refresh(); updateButtons(); // TODO We can't restore selection if they replace the location fTreeViewer.setSelection(new StructuredSelection(location), true); } } break; //Only open for one selected item } } else if (location instanceof AbstractBundleContainer) { // TODO Custom code for locations that don't use adapters yet Shell parent = fTreeViewer.getTree().getShell(); EditBundleContainerWizard wizard = new EditBundleContainerWizard(fTarget, location); WizardDialog dialog = new WizardDialog(parent, wizard); if (dialog.open() == Window.OK) { contentsChanged(false); fTreeViewer.refresh(); updateButtons(); // TODO We can't restore selection if they replace the location fTreeViewer.setSelection(new StructuredSelection(location), true); } break; //Only open for one selected item } } else if (currentSelection instanceof IUWrapper) { // TODO Custom code to allow editing of individual IUs IUWrapper wrapper = (IUWrapper) currentSelection; Shell parent = fTreeViewer.getTree().getShell(); EditBundleContainerWizard editWizard = new EditBundleContainerWizard(fTarget, wrapper.getParent()); WizardDialog wizard = new WizardDialog(parent, editWizard); if (wizard.open() == Window.OK) { // Update the table // TODO Do we need to force a resolve for IUBundleContainers? contentsChanged(false); fTreeViewer.refresh(); updateButtons(); // TODO We can't restore selection if they replace the location fTreeViewer.setSelection(new StructuredSelection(wrapper.getParent()), true); } break; //Only open for one selected item } } } private void handleRemove() { // TODO Contains custom code to remove individual IUWrappers // TODO Contains custom code to force re-resolve if IUBundleContainer removed IStructuredSelection selection = (IStructuredSelection) fTreeViewer.getSelection(); ITargetLocation[] containers = fTarget.getTargetLocations(); if (!selection.isEmpty() && containers != null && containers.length > 0) { List<Object> toRemove = new ArrayList<Object>(); boolean removedSite = false; boolean removedContainer = false; for (Iterator<?> iterator = selection.iterator(); iterator.hasNext();) { Object currentSelection = iterator.next(); if (currentSelection instanceof ITargetLocation) { if (currentSelection instanceof IUBundleContainer) { removedSite = true; } removedContainer = true; toRemove.add(currentSelection); } if (currentSelection instanceof IUWrapper) { toRemove.add(currentSelection); } } if (removedContainer) { Set<ITargetLocation> newContainers = new HashSet<ITargetLocation>(); newContainers.addAll(Arrays.asList(fTarget.getTargetLocations())); newContainers.removeAll(toRemove); if (newContainers.size() > 0) { fTarget.setTargetLocations(newContainers.toArray(new ITargetLocation[newContainers.size()])); } else { fTarget.setTargetLocations(null); } // If we remove a site container, the content change update must force a re-resolve bug 275458 / bug 275401 contentsChanged(removedSite); fTreeViewer.refresh(false); updateButtons(); } else { for (Iterator<Object> iterator = toRemove.iterator(); iterator.hasNext();) { Object current = iterator.next(); if (current instanceof IUWrapper) { ((IUWrapper) current).getParent().removeInstallableUnit(((IUWrapper) current).getIU()); } } contentsChanged(removedSite); fTreeViewer.refresh(true); updateButtons(); } } } private void handleUpdate() { // TODO Only IUWrapper children are added to the map for special update processing IStructuredSelection selection = (IStructuredSelection) fTreeViewer.getSelection(); Map<ITargetLocation, Set<Object>> toUpdate = new HashMap<ITargetLocation, Set<Object>>(); for (Iterator<?> iterator = selection.iterator(); iterator.hasNext();) { Object currentSelection = iterator.next(); if (currentSelection instanceof ITargetLocation) toUpdate.put((ITargetLocation) currentSelection, new HashSet<Object>(0)); else if (currentSelection instanceof IUWrapper) { IUWrapper wrapper = (IUWrapper) currentSelection; Set<Object> iuSet = toUpdate.get(wrapper.getParent()); if (iuSet == null) { iuSet = new HashSet<Object>(); iuSet.add(wrapper.getIU().getId()); toUpdate.put(wrapper.getParent(), iuSet); } else if (!iuSet.isEmpty()) iuSet.add(wrapper.getIU().getId()); } } if (toUpdate.isEmpty()) return; JobChangeAdapter listener = new JobChangeAdapter() { @Override public void done(final IJobChangeEvent event) { UIJob job = new UIJob(Messages.UpdateTargetJob_UpdateJobName) { @Override public IStatus runInUIThread(IProgressMonitor monitor) { IStatus result = event.getJob().getResult(); if (!result.isOK()) { if (!fTreeViewer.getControl().isDisposed()) { ErrorDialog.openError(fTreeViewer.getTree().getShell(), Messages.TargetLocationsGroup_TargetUpdateErrorDialog, result.getMessage(), result); } } else if (result.getCode() != ITargetLocationUpdater.STATUS_CODE_NO_CHANGE) { // Update was successful and changed the target, if dialog/editor still open, update it if (!fTreeViewer.getControl().isDisposed()) { contentsChanged(true); fTreeViewer.refresh(true); updateButtons(); } // If the target is the current platform, run a load job for the user try { ITargetPlatformService service = (ITargetPlatformService) PDECore.getDefault() .acquireService(ITargetPlatformService.class.getName()); if (service != null) { ITargetHandle currentTarget = service.getWorkspaceTargetHandle(); if (fTarget.getHandle().equals(currentTarget)) LoadTargetDefinitionJob.load(fTarget); } } catch (CoreException e) { // do nothing if we could not set the current target. } } return Status.OK_STATUS; } }; job.schedule(); } }; UpdateTargetJob.update(fTarget, toUpdate, listener); } private void updateButtons() { IStructuredSelection selection = (IStructuredSelection) fTreeViewer.getSelection(); if (selection.isEmpty()) { fRemoveButton.setEnabled(false); fUpdateButton.setEnabled(false); fEditButton.setEnabled(false); } boolean canRemove = false; boolean canEdit = false; boolean canUpdate = false; for (Iterator<?> iterator = selection.iterator(); iterator.hasNext();) { Object currentSelection = iterator.next(); if (currentSelection instanceof ITargetLocation) { canRemove = true; if (!canEdit) { ITargetLocation location = (ITargetLocation) currentSelection; ITargetLocationEditor editor = (ITargetLocationEditor) Platform.getAdapterManager() .getAdapter(location, ITargetLocationEditor.class); if (editor != null) { canEdit = editor.canEdit(fTarget, location); } if (location instanceof AbstractBundleContainer) { // TODO Custom code for locations that don't use adapters yet canEdit = true; } } if (!canUpdate) { ITargetLocation location = (ITargetLocation) currentSelection; ITargetLocationUpdater updater = (ITargetLocationUpdater) Platform.getAdapterManager() .getAdapter(location, ITargetLocationUpdater.class); if (updater != null) { canUpdate = updater.canUpdate(fTarget, location); } } } else if (currentSelection instanceof IUWrapper) { // TODO Custom code to support editing/updating/removal of individual IUs canRemove = true; canEdit = true; canUpdate = true; } if (canRemove && canEdit && canUpdate) { break; } } fRemoveButton.setEnabled(canRemove); fEditButton.setEnabled(canEdit); fUpdateButton.setEnabled(canUpdate); // TODO Some code to find the parent location of items in the tree // For each selected item, find it's parent location and add it to the set // for (int i = 0; i < treeSelection.length; i++) { // TreeItem current = treeSelection[i]; // while (current != null){ // if (current instanceof ITargetLocation){ // selectedLocations.add(current); // break; // } // current = current.getParentItem(); // } // } } private void handleReload() { //delete profile try { P2TargetUtils.deleteProfile(fTarget.getHandle()); } catch (CoreException e) { PDEPlugin.log(e); } // increase sequence number if (fTarget instanceof TargetDefinition) ((TargetDefinition) fTarget).incrementSequenceNumber(); Job job = new UIJob("Reloading...") { //$NON-NLS-1$ @Override public IStatus runInUIThread(IProgressMonitor monitor) { contentsChanged(true); return Status.OK_STATUS; } }; job.schedule(); } /** * Informs the reporter for this table that something has changed * and is dirty. */ private void contentsChanged(boolean force) { Object[] listeners = fChangeListeners.getListeners(); for (int i = 0; i < listeners.length; i++) { ((ITargetChangedListener) listeners[i]).contentsChanged(fTarget, this, true, force); } } }