org.eclipse.buildship.ui.wizard.project.WorkingSetConfigurationWidget.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.buildship.ui.wizard.project.WorkingSetConfigurationWidget.java

Source

/*
 * 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);
        }
    }

}