/* * Copyright (c) 2015 the original author or authors. * 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: * Simon Scholz (vogella GmbH) - initial API and implementation and initial documentation */ package org.eclipse.buildship.ui.wizard.project; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.ImmutableList; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.IWorkingSet; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.WorkingSetConfigurationBlock; import org.eclipse.buildship.core.GradlePluginsRuntimeException; /** * Enhances the {@link WorkingSetConfigurationBlock} class with {@link WorkingSetChangedListener} * functionality. * * @see WorkingSetChangedListener */ public final class WorkingSetConfigurationWidget extends WorkingSetConfigurationBlock { private final List<WorkingSetChangedListener> listener; private Button workingSetsEnabledButton; private Combo workingSetsCombo; private Button workingSetsSelectButton; public WorkingSetConfigurationWidget(String[] workingSetIds, IDialogSettings settings) { super(workingSetIds, settings); this.listener = new CopyOnWriteArrayList<WorkingSetChangedListener>(); } @SuppressWarnings("UnusedDeclaration") public WorkingSetConfigurationWidget(String[] workingSetIds, IDialogSettings settings, String addButtonLabel, String comboLabel, String selectLabel) { super(workingSetIds, settings, addButtonLabel, comboLabel, selectLabel); this.listener = new CopyOnWriteArrayList<WorkingSetChangedListener>(); } @Override public void createContent(Composite parent) { super.createContent(parent); // remove the colon from the 'Working sets:' label Label workingSetsLabel = findWorkingSetsLabel(parent); workingSetsLabel.setText(workingSetsLabel.getText().replace(":", "")); // add modification listener to the working sets checkbox this.workingSetsEnabledButton = findWorkingSetsEnabledButton(parent); this.workingSetsEnabledButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { fireWorkingSetChanged(); } }); // add modification and selection change listener to the working sets combo this.workingSetsCombo = findWorkingSetsCombo(parent); this.workingSetsCombo.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { fireWorkingSetChanged(); } }); this.workingSetsCombo.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { fireWorkingSetChanged(); } }); // fish out the Select button this.workingSetsSelectButton = findWorkingSetsSelectButton(parent); } private Label findWorkingSetsLabel(Composite parent) { return (Label) findControl(parent, Predicates.instanceOf(Label.class)); } private Button findWorkingSetsEnabledButton(Composite parent) { return (Button) findControl(parent, Predicates.instanceOf(Button.class)); } private Combo findWorkingSetsCombo(Composite parent) { return (Combo) findControl(parent, Predicates.instanceOf(Combo.class)); } private Button findWorkingSetsSelectButton(Composite parent) { Predicate<Object> isButton = Predicates.instanceOf(Button.class); Predicate<Control> hasPushStyle = new Predicate<Control>() { @Override public boolean apply(Control control) { return (control.getStyle() & SWT.PUSH) == SWT.PUSH; } }; return (Button) findControl(parent, Predicates.and(isButton, hasPushStyle)); } private Control findControl(Composite parent, Predicate<? super Control> predicate) { Control result = findControlRecursively(parent, predicate); if (result != null) { return result; } else { throw new IllegalStateException("Cannot find control under the root composite matching to the provided condition."); } } private Control findControlRecursively(Composite parent, Predicate<? super Control> predicate) { Control[] children = parent.getChildren(); for (Control control : children) { if (predicate.apply(control)) { return control; } else if (control instanceof Composite) { Control result = findControlRecursively((Composite) control, predicate); if (result != null) { return result; } } } return null; } public Button getWorkingSetsEnabledButton() { return this.workingSetsEnabledButton; } public Combo getWorkingSetsCombo() { return this.workingSetsCombo; } public Button getWorkingSetsSelectButton() { return this.workingSetsSelectButton; } public void addWorkingSetChangeListener(WorkingSetChangedListener workingSetListener) { this.listener.add(workingSetListener); } public void removeWorkingSetChangeListener(WorkingSetChangedListener workingSetListener) { this.listener.remove(workingSetListener); } private void fireWorkingSetChanged() { ImmutableList<IWorkingSet> workingSets = ImmutableList.copyOf(getSelectedWorkingSets()); for (WorkingSetChangedListener workingSetChangedListener : this.listener) { workingSetChangedListener.workingSetsChanged(workingSets); } } public void modifyCurrentWorkingSetItem(IWorkingSet[] result) { // this method changes the text of the currently selected label such that the target working sets are visible // this is the exact behavior what happens when the working set is changed with the dialog box // but because that implementation is private we can call it only via reflection try { Field selectedWorkingSets = WorkingSetConfigurationBlock.class.getDeclaredField("selectedWorkingSets"); selectedWorkingSets.setAccessible(true); selectedWorkingSets.set(this, result); if (result.length > 0) { PlatformUI.getWorkbench().getWorkingSetManager().addRecentWorkingSet(result[0]); } Method updateWorkingSetSelection = WorkingSetConfigurationBlock.class.getDeclaredMethod("updateWorkingSetSelection"); updateWorkingSetSelection.setAccessible(true); updateWorkingSetSelection.invoke(this); } catch (Exception e) { throw new GradlePluginsRuntimeException(e); } } }