| /******************************************************************************* |
| * Copyright (c) 2000, 2016 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.jdt.internal.ui.wizards.buildpaths.newsourcepage; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.DisposeEvent; |
| import org.eclipse.swt.events.DisposeListener; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Shell; |
| |
| import org.eclipse.core.resources.IResource; |
| |
| import org.eclipse.jface.layout.PixelConverter; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.ISelectionChangedListener; |
| import org.eclipse.jface.viewers.SelectionChangedEvent; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| |
| import org.eclipse.ui.forms.events.HyperlinkAdapter; |
| import org.eclipse.ui.forms.events.HyperlinkEvent; |
| import org.eclipse.ui.forms.widgets.FormText; |
| import org.eclipse.ui.forms.widgets.FormToolkit; |
| import org.eclipse.ui.forms.widgets.TableWrapData; |
| import org.eclipse.ui.forms.widgets.TableWrapLayout; |
| |
| import org.eclipse.jdt.core.IPackageFragmentRoot; |
| import org.eclipse.jdt.core.JavaModelException; |
| |
| import org.eclipse.jdt.internal.corext.util.Messages; |
| |
| import org.eclipse.jdt.internal.ui.JavaPlugin; |
| import org.eclipse.jdt.internal.ui.preferences.ScrolledPageContent; |
| import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages; |
| |
| |
| /** |
| * Displays a set of available links to modify or adjust the project. |
| * The links contain a short description about the consequences of |
| * this action. |
| * |
| * The content depends on the selection made on the project. |
| * If selection changes, then the <code>HintTextGroup</code> will be |
| * notified through the <code>IPackageExplorerActionListener</code> interface. |
| */ |
| public final class HintTextGroup implements ISelectionChangedListener { |
| |
| private Composite fTopComposite; |
| private DialogPackageExplorerActionGroup fActionGroup; |
| private List<IResource> fNewFolders; |
| private HashMap<String, Image> fImageMap; |
| |
| public HintTextGroup() { |
| fNewFolders= new ArrayList<>(); |
| fImageMap= new HashMap<>(); |
| } |
| |
| public Composite createControl(Composite parent) { |
| fTopComposite= new Composite(parent, SWT.NONE); |
| fTopComposite.setFont(parent.getFont()); |
| |
| GridData gridData= new GridData(GridData.FILL_BOTH); |
| PixelConverter converter= new PixelConverter(parent); |
| gridData.heightHint= converter.convertHeightInCharsToPixels(12); |
| gridData.widthHint= converter.convertWidthInCharsToPixels(25); |
| GridLayout gridLayout= new GridLayout(); |
| gridLayout.marginWidth= 0;//-converter.convertWidthInCharsToPixels(2); |
| gridLayout.marginHeight= 0;//= -4; |
| fTopComposite.setLayout(gridLayout); |
| fTopComposite.setLayoutData(gridData); |
| fTopComposite.setData(null); |
| fTopComposite.addDisposeListener(new DisposeListener() { |
| @Override |
| public void widgetDisposed(DisposeEvent e) { |
| Collection<Image> collection= fImageMap.values(); |
| Iterator<Image> iterator= collection.iterator(); |
| while(iterator.hasNext()) { |
| Image image= iterator.next(); |
| image.dispose(); |
| } |
| } |
| }); |
| return fTopComposite; |
| } |
| |
| private Shell getShell() { |
| return JavaPlugin.getActiveWorkbenchShell(); |
| } |
| |
| /** |
| * An action group managing the actions needed by |
| * the <code>HintTextGroup</code>. |
| * |
| * Note: This method has to be called on initialization. |
| * Calling this method in the constructor is not |
| * possible because the actions might need a reference to |
| * this class. |
| * |
| * @param actionGroup the action group containing the necessary |
| * actions |
| * |
| * @see DialogPackageExplorerActionGroup |
| */ |
| public void setActionGroup(DialogPackageExplorerActionGroup actionGroup) { |
| fActionGroup= actionGroup; |
| } |
| |
| /** |
| * Creates a form text. |
| * |
| * @param parent the parent to put the form text on |
| * @param text the form text to be displayed |
| * @return the created form text |
| * |
| * @see FormToolkit#createFormText(org.eclipse.swt.widgets.Composite, boolean) |
| */ |
| private FormText createFormText(Composite parent, String text) { |
| FormToolkit toolkit= new FormToolkit(getShell().getDisplay()); |
| try { |
| FormText formText= toolkit.createFormText(parent, true); |
| formText.setFont(parent.getFont()); |
| try { |
| formText.setText(text, true, false); |
| } catch (IllegalArgumentException e) { |
| formText.setText(e.getMessage(), false, false); |
| JavaPlugin.log(e); |
| } |
| formText.marginHeight= 2; |
| formText.marginWidth= 0; |
| formText.setBackground(parent.getBackground()); |
| formText.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB)); |
| return formText; |
| } finally { |
| toolkit.dispose(); |
| } |
| } |
| |
| /** |
| * Create a label with a hyperlink and a picture. |
| * |
| * @param parent the parent widget of the label |
| * @param text the text of the label |
| * @param action the action to be executed if the hyperlink is activated |
| */ |
| private void createLabel(Composite parent, String text, final BuildpathModifierAction action) { |
| FormText formText= createFormText(parent, text); |
| Image image= fImageMap.get(action.getId()); |
| if (image == null) { |
| image= action.getImageDescriptor().createImage(); |
| fImageMap.put(action.getId(), image); |
| } |
| formText.setImage("defaultImage", image); //$NON-NLS-1$ |
| formText.addHyperlinkListener(new HyperlinkAdapter() { |
| |
| @Override |
| public void linkActivated(HyperlinkEvent e) { |
| action.run(); |
| } |
| |
| }); |
| } |
| |
| /** |
| * Handle folder creation. This includes: |
| * <li>Set the selection of the <code>fPackageExplorer</code> |
| * to the result object, unless the result object is <code> |
| * null</code></li> |
| * <li>Add the created folder to the list of new folders</li> |
| * <li>Adjust the text of <code>fOutputLocationField</code> |
| * and add the project's new output location to the list of |
| * new folders, if necessary |
| * |
| * In this case, the list consists only of one element on which the |
| * new folder has been created |
| * |
| * @param result a list with only one element to be selected by the |
| * <code>fPackageExplorer</code>, or an empty list if creation was |
| * aborted |
| */ |
| void handleFolderCreation(List<IPackageFragmentRoot> result) { |
| if (result.size() == 1) { |
| try { |
| fNewFolders.add(result.get(0).getCorrespondingResource()); |
| } catch (JavaModelException e) { |
| JavaPlugin.log(e); |
| } |
| } |
| } |
| |
| public List<IResource> getCreatedResources() { |
| return fNewFolders; |
| } |
| |
| public void resetCreatedResources() { |
| fNewFolders.clear(); |
| } |
| |
| @Override |
| public void selectionChanged(SelectionChangedEvent event) { |
| if (event.getSelection() instanceof StructuredSelection) { |
| handlePostSelectionChange((StructuredSelection)event.getSelection()); |
| } else { |
| handlePostSelectionChange(StructuredSelection.EMPTY); |
| } |
| } |
| |
| private void handlePostSelectionChange(StructuredSelection selection) { |
| |
| BuildpathModifierAction[] actions= fActionGroup.getHintTextGroupActions(); |
| String[] descriptions= new String[actions.length]; |
| for (int i= 0; i < actions.length; i++) { |
| descriptions[i]= actions[i].getDetailedDescription(); |
| } |
| |
| // Get the child composite of the top composite |
| Composite childComposite= (Composite)fTopComposite.getData(); |
| |
| // Dispose old composite (if necessary) |
| if (childComposite != null && childComposite.getParent() != null) |
| childComposite.getParent().dispose(); |
| |
| PixelConverter converter= new PixelConverter(fTopComposite); |
| |
| // Create new composite |
| ScrolledPageContent spc= new ScrolledPageContent(fTopComposite, SWT.V_SCROLL); |
| spc.getVerticalBar().setIncrement(5); |
| |
| GridData gridData= new GridData(GridData.FILL_BOTH); |
| |
| gridData.heightHint= converter.convertHeightInCharsToPixels(12); |
| gridData.widthHint= converter.convertWidthInCharsToPixels(25); |
| spc.setLayoutData(gridData); |
| |
| childComposite= spc.getBody(); |
| TableWrapLayout tableWrapLayout= new TableWrapLayout(); |
| tableWrapLayout.leftMargin= 0; |
| tableWrapLayout.rightMargin= 0; |
| childComposite.setLayout(tableWrapLayout); |
| gridData= new GridData(GridData.FILL_BOTH); |
| gridData.heightHint= converter.convertHeightInCharsToPixels(12); |
| gridData.widthHint= converter.convertWidthInCharsToPixels(25); |
| childComposite.setLayoutData(gridData); |
| |
| fTopComposite.setData(childComposite); |
| |
| if (noContextHelpAvailable(actions)) { |
| String noAction= noAction(selection); |
| createFormText(childComposite, Messages.format(NewWizardMessages.HintTextGroup_NoAction, noAction)); |
| fTopComposite.layout(true); |
| return; |
| } |
| |
| for (int i= 0; i < actions.length; i++) { |
| createLabel(childComposite, descriptions[i], actions[i]); |
| } |
| |
| |
| fTopComposite.layout(true); |
| spc.reflow(true); |
| } |
| |
| private String noAction(ISelection selection) { |
| if (selection instanceof StructuredSelection) { |
| return noAction(((StructuredSelection)selection).toList()); |
| } else { |
| return noAction(Collections.EMPTY_LIST); |
| } |
| } |
| |
| private String noAction(List<?> selectedElements) { |
| if (selectedElements.size() == 0) |
| return NewWizardMessages.PackageExplorerActionGroup_NoAction_NullSelection; |
| |
| if (selectedElements.size() == 1) |
| return NewWizardMessages.PackageExplorerActionGroup_NoAction_NoReason; |
| |
| return NewWizardMessages.PackageExplorerActionGroup_NoAction_MultiSelection; |
| } |
| |
| /** |
| * Check if for the current type of selection, no context specific actions can |
| * be applied. Note: this does not mean, that there are NO actions available at all.<p> |
| * |
| * For example: if the default package is selected, there is no specific action for this kind |
| * of selection as no operations are allowed on the default package. Nevertheless, the |
| * <code>PackageExplorerActionEvent</code> will return at least one action that allows to |
| * link to an existing folder in the file system, but this operation is always available |
| * and does not add any supporting information to the current selection. Therefore, |
| * it can be filtered and the correct answer to the user is that there is no specific |
| * action for the default package. |
| * |
| * @param actions an array of provided actions |
| * @return <code>true</code> if there is at least one action that allows context |
| * sensitive operations, <code>false</code> otherwise. |
| */ |
| private boolean noContextHelpAvailable(BuildpathModifierAction[] actions) { |
| if (actions.length == 0) |
| return true; |
| if (actions.length == 1) { |
| int id= Integer.parseInt(actions[0].getId()); |
| if (id == BuildpathModifierAction.CREATE_LINK) |
| return true; |
| } |
| if (actions.length == 2) { |
| int idLink= Integer.parseInt(actions[0].getId()); |
| int idReset= Integer.parseInt(actions[1].getId()); |
| if (idReset == BuildpathModifierAction.RESET_ALL && |
| idLink == BuildpathModifierAction.CREATE_LINK) |
| return true; |
| } |
| return false; |
| } |
| } |