| /******************************************************************************* |
| * Copyright (c) 2010, 2014 Andrew Gvozdev 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: |
| * Andrew Gvozdev (Quoin Inc.) - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.cdt.managedbuilder.internal.ui.commands; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.cdt.core.model.CoreModel; |
| import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; |
| import org.eclipse.cdt.core.settings.model.ICProjectDescription; |
| import org.eclipse.cdt.managedbuilder.ui.properties.ManagedBuilderUIImages; |
| import org.eclipse.cdt.managedbuilder.ui.properties.ManagedBuilderUIPlugin; |
| import org.eclipse.cdt.ui.CUIPlugin; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IncrementalProjectBuilder; |
| import org.eclipse.core.runtime.jobs.Job; |
| import org.eclipse.jface.dialogs.IDialogConstants; |
| import org.eclipse.jface.dialogs.IDialogSettings; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.viewers.CheckStateChangedEvent; |
| import org.eclipse.jface.viewers.ICheckStateListener; |
| import org.eclipse.jface.viewers.ILabelProvider; |
| import org.eclipse.jface.viewers.ILabelProviderListener; |
| import org.eclipse.jface.viewers.ITreeContentProvider; |
| import org.eclipse.jface.viewers.Viewer; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.events.SelectionListener; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.ui.dialogs.ContainerCheckedTreeViewer; |
| import org.eclipse.ui.internal.ide.actions.BuildUtilities; |
| import org.eclipse.ui.model.WorkbenchLabelProvider; |
| |
| /** |
| * Dialog to let the user to clean and rebuild configurations of the selected projects. |
| */ |
| public class RebuildConfigurationsDialog extends MessageDialog { |
| private static final String DIALOG_SETTINGS_SECTION = "RebuildConfigurationsDialogSettings"; //$NON-NLS-1$ |
| private static final String DIALOG_ORIGIN_X = "DIALOG_X_ORIGIN"; //$NON-NLS-1$ |
| private static final String DIALOG_ORIGIN_Y = "DIALOG_Y_ORIGIN"; //$NON-NLS-1$ |
| private static final String DIALOG_WIDTH = "DIALOG_WIDTH"; //$NON-NLS-1$ |
| private static final String DIALOG_HEIGHT = "DIALOG_HEIGHT"; //$NON-NLS-1$ |
| |
| private Button cleanCheckbox; |
| private Button buildCheckbox; |
| |
| private ContainerCheckedTreeViewer cfgCheckboxViewer; |
| |
| private IProject[] projects; |
| private Object[] selected; |
| private int cleanKind; |
| private int buildKind; |
| |
| private static class ConfigurationLabelProvider implements ILabelProvider { |
| WorkbenchLabelProvider workbenchLabelProvider = new WorkbenchLabelProvider(); |
| |
| @Override |
| public void addListener(ILabelProviderListener listener) { |
| workbenchLabelProvider.addListener(listener); |
| } |
| |
| @Override |
| public void dispose() { |
| workbenchLabelProvider.dispose(); |
| } |
| |
| @Override |
| public boolean isLabelProperty(Object element, String property) { |
| return workbenchLabelProvider.isLabelProperty(element, property); |
| } |
| |
| @Override |
| public void removeListener(ILabelProviderListener listener) { |
| workbenchLabelProvider.removeListener(listener); |
| } |
| |
| @Override |
| public Image getImage(Object element) { |
| if (element instanceof ICConfigurationDescription) |
| return ManagedBuilderUIImages.get(ManagedBuilderUIImages.IMG_BUILD_CONFIG); |
| return workbenchLabelProvider.getImage(element); |
| } |
| |
| @Override |
| public String getText(Object element) { |
| if (element instanceof ICConfigurationDescription) { |
| ICConfigurationDescription cfgDescription = (ICConfigurationDescription) element; |
| String name = cfgDescription.getName(); |
| if (cfgDescription.isActive()) { |
| return name + ' ' + Messages.RebuildConfigurationsDialog_Active; |
| } |
| return name; |
| } |
| |
| return workbenchLabelProvider.getText(element); |
| } |
| } |
| |
| private class ConfigurationContentProvider implements ITreeContentProvider { |
| @Override |
| public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { |
| } |
| |
| @Override |
| public void dispose() { |
| } |
| |
| @Override |
| public Object[] getElements(Object inputElement) { |
| return getChildren(inputElement); |
| } |
| |
| @Override |
| public boolean hasChildren(Object element) { |
| if (element instanceof IProject[]) |
| return ((IProject[]) element).length > 0; |
| |
| if (element instanceof IProject) { |
| IProject project = (IProject) element; |
| ICProjectDescription prjd = CoreModel.getDefault().getProjectDescription(project, false); |
| if (prjd == null) |
| return false; |
| |
| ICConfigurationDescription[] cfgDescriptions = prjd.getConfigurations(); |
| return cfgDescriptions != null && cfgDescriptions.length > 0; |
| } |
| return false; |
| } |
| |
| @Override |
| public Object getParent(Object element) { |
| if (element instanceof IProject) { |
| return projects; |
| } |
| if (element instanceof ICConfigurationDescription) { |
| ICConfigurationDescription cfgDescription = (ICConfigurationDescription) element; |
| return cfgDescription.getProjectDescription().getProject(); |
| } |
| return null; |
| } |
| |
| @Override |
| public Object[] getChildren(Object parentElement) { |
| if (parentElement instanceof IProject[]) |
| return (IProject[]) parentElement; |
| |
| if (parentElement instanceof IProject) { |
| IProject project = (IProject) parentElement; |
| ICProjectDescription prjd = CoreModel.getDefault().getProjectDescription(project, false); |
| if (prjd != null) { |
| ICConfigurationDescription[] cfgDescriptions = prjd.getConfigurations(); |
| return cfgDescriptions; |
| } |
| } |
| return new Object[0]; |
| } |
| } |
| |
| /** |
| * Creates a new Clean and Build dialog. |
| * |
| * @param projects - the currently selected projects |
| */ |
| public RebuildConfigurationsDialog(IProject[] projects) { |
| super(CUIPlugin.getActiveWorkbenchShell(), Messages.RebuildConfigurationsDialog_RebuildConfigurations, null, |
| Messages.RebuildConfigurationsDialog_SelectConfigurations, NONE, |
| new String[] { IDialogConstants.OK_LABEL, IDialogConstants.CANCEL_LABEL }, 0); |
| this.projects = projects; |
| } |
| |
| @Override |
| protected void buttonPressed(int buttonId) { |
| super.buttonPressed(buttonId); |
| if (buttonId != IDialogConstants.OK_ID) { |
| return; |
| } |
| |
| // Save all dirty editors. |
| BuildUtilities.saveEditors(null); |
| |
| if (selected != null) { |
| List<ICConfigurationDescription> cfgDescriptions = new ArrayList<>(); |
| for (Object sel : selected) { |
| if (sel instanceof ICConfigurationDescription) { |
| cfgDescriptions.add((ICConfigurationDescription) sel); |
| } |
| } |
| |
| if (cleanKind != 0 || buildKind != 0) { |
| ICConfigurationDescription[] cfgdArray = cfgDescriptions |
| .toArray(new ICConfigurationDescription[cfgDescriptions.size()]); |
| Job buildJob = new BuildConfigurationsJob(cfgdArray, cleanKind, buildKind); |
| buildJob.schedule(); |
| } |
| } |
| } |
| |
| @Override |
| protected Control createCustomArea(Composite parent) { |
| Composite area = new Composite(parent, SWT.NONE); |
| GridLayout layout = new GridLayout(); |
| layout.marginWidth = layout.marginHeight = 0; |
| layout.numColumns = 2; |
| layout.makeColumnsEqualWidth = true; |
| area.setLayout(layout); |
| area.setLayoutData(new GridData(GridData.FILL_BOTH)); |
| SelectionListener updateEnablement = new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| updateEnablement(); |
| } |
| }; |
| |
| // Second row. |
| createProjectSelectionTable(area); |
| |
| // Third row. |
| cleanCheckbox = new Button(parent, SWT.CHECK); |
| cleanCheckbox.setText(Messages.RebuildConfigurationsDialog_CleanConfigurations); |
| cleanCheckbox.setSelection(true); |
| cleanCheckbox.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); |
| cleanCheckbox.addSelectionListener(updateEnablement); |
| cleanKind = cleanCheckbox.getSelection() ? IncrementalProjectBuilder.CLEAN_BUILD : 0; |
| |
| buildCheckbox = new Button(parent, SWT.CHECK); |
| buildCheckbox.setText(Messages.RebuildConfigurationsDialog_BuildConfigurations); |
| buildCheckbox.setSelection(true); |
| buildCheckbox.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); |
| buildCheckbox.addSelectionListener(updateEnablement); |
| buildKind = buildCheckbox.getSelection() ? IncrementalProjectBuilder.INCREMENTAL_BUILD : 0; |
| |
| return area; |
| } |
| |
| private void createProjectSelectionTable(Composite area) { |
| cfgCheckboxViewer = new ContainerCheckedTreeViewer(area, SWT.BORDER); |
| cfgCheckboxViewer.setContentProvider(new ConfigurationContentProvider()); |
| cfgCheckboxViewer.setLabelProvider(new ConfigurationLabelProvider()); |
| cfgCheckboxViewer.setInput(projects); |
| GridData data = new GridData(GridData.FILL_BOTH); |
| data.horizontalSpan = 2; |
| data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH; |
| data.heightHint = IDialogConstants.ENTRY_FIELD_WIDTH; |
| cfgCheckboxViewer.getControl().setLayoutData(data); |
| |
| List<ICConfigurationDescription> initialSelection = new ArrayList<>(projects.length); |
| for (IProject prj : projects) { |
| ICProjectDescription prjd = CoreModel.getDefault().getProjectDescription(prj, false); |
| if (prjd == null) |
| continue; |
| cfgCheckboxViewer.setChecked(prjd.getActiveConfiguration(), true); |
| initialSelection.add(prjd.getActiveConfiguration()); |
| } |
| cfgCheckboxViewer.expandAll(); |
| cfgCheckboxViewer.addCheckStateListener(new ICheckStateListener() { |
| @Override |
| public void checkStateChanged(CheckStateChangedEvent event) { |
| updateEnablement(); |
| selected = cfgCheckboxViewer.getCheckedElements(); |
| } |
| }); |
| selected = cfgCheckboxViewer.getCheckedElements(); |
| selected = initialSelection.toArray(new ICConfigurationDescription[initialSelection.size()]); |
| } |
| |
| /** |
| * Updates the enablement of the dialog's OK button based on the current choices in the dialog. |
| */ |
| protected void updateEnablement() { |
| cleanKind = cleanCheckbox.getSelection() ? IncrementalProjectBuilder.CLEAN_BUILD : 0; |
| buildKind = buildCheckbox.getSelection() ? IncrementalProjectBuilder.INCREMENTAL_BUILD : 0; |
| boolean enabled = cfgCheckboxViewer.getCheckedElements().length > 0 && (cleanKind != 0 || buildKind != 0); |
| getButton(OK).setEnabled(enabled); |
| } |
| |
| @Override |
| public boolean close() { |
| persistDialogSettings(getShell(), DIALOG_SETTINGS_SECTION); |
| return super.close(); |
| } |
| |
| @Override |
| protected Point getInitialLocation(Point initialSize) { |
| Point p = getInitialLocation(DIALOG_SETTINGS_SECTION); |
| return p != null ? p : super.getInitialLocation(initialSize); |
| } |
| |
| @Override |
| protected Point getInitialSize() { |
| Point p = super.getInitialSize(); |
| return getInitialSize(DIALOG_SETTINGS_SECTION, p); |
| } |
| |
| /** |
| * Returns the initial location which is persisted in the IDE Plugin dialog settings under |
| * the provided dialog settings section name. If location is not persisted in the settings, |
| * the {@code null} is returned. |
| * |
| * @param dialogSettingsSectionName - The name of the dialog settings section |
| * @return The initial location or {@code null} |
| */ |
| private Point getInitialLocation(String dialogSettingsSectionName) { |
| IDialogSettings settings = getDialogSettings(dialogSettingsSectionName); |
| try { |
| int x = settings.getInt(DIALOG_ORIGIN_X); |
| int y = settings.getInt(DIALOG_ORIGIN_Y); |
| return new Point(x, y); |
| } catch (NumberFormatException e) { |
| } |
| return null; |
| } |
| |
| private IDialogSettings getDialogSettings(String dialogSettingsSectionName) { |
| IDialogSettings settings = ManagedBuilderUIPlugin.getDefault().getDialogSettings(); |
| IDialogSettings section = settings.getSection(dialogSettingsSectionName); |
| if (section == null) { |
| section = settings.addNewSection(dialogSettingsSectionName); |
| } |
| return section; |
| } |
| |
| /** |
| * Persists the location and dimensions of the shell and other user settings in the plugin's |
| * dialog settings under the provided dialog settings section name. |
| * |
| * @param shell - The shell whose geometry is to be stored |
| * @param dialogSettingsSectionName - The name of the dialog settings section |
| */ |
| private void persistDialogSettings(Shell shell, String dialogSettingsSectionName) { |
| Point shellLocation = shell.getLocation(); |
| Point shellSize = shell.getSize(); |
| IDialogSettings settings = getDialogSettings(dialogSettingsSectionName); |
| settings.put(DIALOG_ORIGIN_X, shellLocation.x); |
| settings.put(DIALOG_ORIGIN_Y, shellLocation.y); |
| settings.put(DIALOG_WIDTH, shellSize.x); |
| settings.put(DIALOG_HEIGHT, shellSize.y); |
| } |
| |
| /** |
| * Returns the initial size which is the larger of the {@code initialSize} or the size |
| * persisted in the IDE UI Plugin dialog settings under the provided dialog settings section |
| * name. If no size is persisted in the settings, the {@code initialSize} is returned. |
| * |
| * @param initialSize - The initialSize to compare against |
| * @param dialogSettingsSectionName - The name of the dialog settings section |
| * @return the initial size |
| */ |
| private Point getInitialSize(String dialogSettingsSectionName, Point initialSize) { |
| IDialogSettings settings = getDialogSettings(dialogSettingsSectionName); |
| try { |
| int x, y; |
| x = settings.getInt(DIALOG_WIDTH); |
| y = settings.getInt(DIALOG_HEIGHT); |
| return new Point(Math.max(x, initialSize.x), Math.max(y, initialSize.y)); |
| } catch (NumberFormatException e) { |
| } |
| return initialSize; |
| } |
| |
| @Override |
| protected boolean isResizable() { |
| return true; |
| } |
| } |