org.jboss.tools.openshift.internal.ui.wizard.common.ResourceLabelsPage.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.tools.openshift.internal.ui.wizard.common.ResourceLabelsPage.java

Source

/*******************************************************************************
 * Copyright (c) 2015 Red Hat, Inc.
 * Distributed under license by Red Hat, Inc. All rights reserved.
 * This program is 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:
 *     Red Hat, Inc. - initial API and implementation
 ******************************************************************************/
package org.jboss.tools.openshift.internal.ui.wizard.common;

import java.util.Set;
import java.util.stream.Collectors;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.core.databinding.conversion.Converter;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
import org.eclipse.jface.databinding.viewers.ViewerProperties;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider;
import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.wizard.IWizard;
import org.eclipse.osgi.util.NLS;
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.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.jboss.tools.common.ui.databinding.ValueBindingBuilder;
import org.jboss.tools.openshift.internal.common.ui.utils.TableViewerBuilder;
import org.jboss.tools.openshift.internal.common.ui.utils.UIUtils;
import org.jboss.tools.openshift.internal.common.ui.wizard.AbstractOpenShiftWizardPage;
import org.jboss.tools.openshift.internal.common.ui.wizard.IKeyValueWizardModel;
import org.jboss.tools.openshift.internal.common.ui.wizard.KeyValueWizard;
import org.jboss.tools.openshift.internal.common.ui.wizard.KeyValueWizardModelBuilder;
import org.jboss.tools.openshift.internal.common.ui.wizard.OkCancelButtonWizardDialog;
import org.jboss.tools.openshift.internal.ui.validator.LabelKeyValidator;
import org.jboss.tools.openshift.internal.ui.validator.LabelValueValidator;
import org.jboss.tools.openshift.internal.ui.wizard.common.IResourceLabelsPageModel.Label;

/**
 * Page to edit the labels for a resource.  Labels with certain keys can be identified
 * as readonly where it is not possible to delete or modify them
 * 
 * @author jeff.cantrill
 */
public class ResourceLabelsPage extends AbstractOpenShiftWizardPage {

    public static final String PAGE_NAME = "Resource Labels Page";
    private static final String LABEL = "Label";
    private static final String RESOURCE_LABEL = "Resource Label";
    private static final String PAGE_DESCRIPTION = "Add or edit the labels to be added to each resource. "
            + "Labels are used to organize, group, or select objects and resources, such as pods and services.  Some labels cannot be modified and therefore"
            + " cannot be edited or removed.";

    private IResourceLabelsPageModel model;
    private TableViewer viewer;

    public ResourceLabelsPage(IWizard wizard, IResourceLabelsPageModel model) {
        super("Resource Labels", PAGE_DESCRIPTION, PAGE_NAME, wizard);
        this.model = model;
    }

    @Override
    protected void doCreateControls(Composite container, DataBindingContext dbc) {
        GridLayoutFactory.fillDefaults().margins(10, 10).applyTo(container);
        org.eclipse.swt.widgets.Label lblLabel = new org.eclipse.swt.widgets.Label(container, SWT.NONE);
        lblLabel.setText("Labels");

        Composite labelsGroup = new Composite(container, SWT.NONE);
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(labelsGroup);
        GridLayoutFactory.fillDefaults().numColumns(2).applyTo(labelsGroup);

        Composite tableContainer = new Composite(labelsGroup, SWT.NONE);

        this.viewer = createTable(tableContainer);
        GridDataFactory.fillDefaults().span(1, 5).align(SWT.FILL, SWT.FILL).grab(true, true)
                .applyTo(tableContainer);
        ValueBindingBuilder.bind(ViewerProperties.singleSelection().observe(viewer))
                .to(BeanProperties.value(IResourceLabelsPageModel.PROPERTY_SELECTED_LABEL).observe(model)).in(dbc);
        viewer.setContentProvider(new ObservableListContentProvider());
        viewer.setInput(BeanProperties.list(IResourceLabelsPageModel.PROPERTY_LABELS).observe(model));

        Button addButton = new Button(labelsGroup, SWT.PUSH);
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).applyTo(addButton);
        addButton.setText("Add...");
        addButton.addSelectionListener(onAdd());
        UIUtils.setDefaultButtonWidth(addButton);

        Button editExistingButton = new Button(labelsGroup, SWT.PUSH);
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).applyTo(editExistingButton);
        editExistingButton.setText("Edit...");
        editExistingButton.addSelectionListener(onEdit());
        ValueBindingBuilder.bind(WidgetProperties.enabled().observe(editExistingButton)).notUpdatingParticipant()
                .to(BeanProperties.value(IResourceLabelsPageModel.PROPERTY_SELECTED_LABEL).observe(model))
                .converting(new IsNotNullOrReadOnlyBooleanConverter()).in(dbc);
        UIUtils.setDefaultButtonWidth(editExistingButton);

        Button removeButton = new Button(labelsGroup, SWT.PUSH);
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).applyTo(removeButton);
        removeButton.setText("Remove...");
        removeButton.addSelectionListener(onRemove());
        ValueBindingBuilder.bind(WidgetProperties.enabled().observe(removeButton)).notUpdatingParticipant()
                .to(BeanProperties.value(IResourceLabelsPageModel.PROPERTY_SELECTED_LABEL).observe(model))
                .converting(new IsNotNullOrReadOnlyBooleanConverter()).in(dbc);
        UIUtils.setDefaultButtonWidth(removeButton);
    }

    private SelectionListener onRemove() {
        return new SelectionAdapter() {

            @Override
            public void widgetSelected(SelectionEvent e) {
                Label label = UIUtils.getFirstElement(viewer.getSelection(), Label.class);
                if (MessageDialog.openQuestion(getShell(), "Remove Label",
                        NLS.bind("Are you sure you want to delete the label {0} ", label.getName()))) {
                    model.removeLabel(label);
                    viewer.refresh();
                }
            }

        };
    }

    private SelectionListener onEdit() {
        return new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                final Label label = UIUtils.getFirstElement(viewer.getSelection(), Label.class);
                editLabel(label);
            }
        };
    }

    private void editLabel(Label label) {
        if (label == null || isReadOnly(label)) {
            return;
        }
        Set<String> usedKeys = getUsedKeys();
        usedKeys.remove(label.getKey());
        IKeyValueWizardModel<Label> dialogModel = new KeyValueWizardModelBuilder<>(label)
                .windowTitle(RESOURCE_LABEL).title("Edit Label").description("Edit the resource label.")
                .keyLabel(LABEL).keyDescription(LabelKeyValidator.keyDescription)
                .valueDescription(NLS.bind(LabelValueValidator.valueDescription, LabelValueValidator.defaultType))
                .groupLabel(LABEL)
                .keyAfterConvertValidator(new LabelKeyValidator(model.getReadOnlyLabels(), usedKeys))
                .valueAfterConvertValidator(new LabelValueValidator()).build();
        OkCancelButtonWizardDialog dialog = new OkCancelButtonWizardDialog(getShell(),
                new KeyValueWizard<>(label, dialogModel));
        if (OkCancelButtonWizardDialog.OK == dialog.open()) {
            model.updateLabel(label, dialogModel.getKey(), dialogModel.getValue());
        }
    }

    Set<String> getUsedKeys() {
        return model.getLabels().stream().map(l -> l.getKey()).collect(Collectors.toSet());
    }

    private SelectionListener onAdd() {
        return new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                IKeyValueWizardModel<Label> dialogModel = new KeyValueWizardModelBuilder<Label>()
                        .windowTitle(RESOURCE_LABEL).title("Add Label").description("Add a resource label.")
                        .keyLabel(LABEL).keyDescription(LabelKeyValidator.keyDescription)
                        .valueDescription(
                                NLS.bind(LabelValueValidator.valueDescription, LabelValueValidator.defaultType))
                        .groupLabel(LABEL)
                        .keyAfterConvertValidator(new LabelKeyValidator(model.getReadOnlyLabels(), getUsedKeys()))
                        .valueAfterConvertValidator(new LabelValueValidator()).build();
                OkCancelButtonWizardDialog dialog = new OkCancelButtonWizardDialog(getShell(), new KeyValueWizard<>(
                        UIUtils.getFirstElement(viewer.getSelection(), Label.class), dialogModel));
                if (OkCancelButtonWizardDialog.OK == dialog.open()) {
                    model.addLabel(dialogModel.getKey(), dialogModel.getValue());
                }
            }
        };
    }

    protected TableViewer createTable(Composite tableContainer) {
        Table table = new Table(tableContainer, SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.H_SCROLL);
        table.setLinesVisible(true);
        table.setHeaderVisible(true);

        this.viewer = new TableViewerBuilder(table, tableContainer).contentProvider(new ArrayContentProvider())
                .<Label>column(new DelegatingStyledCellLabelProvider(new LabelTextProvider() {
                    @Override
                    public String getValue(Label label) {
                        return label.getName();
                    }
                })).name("Name").align(SWT.LEFT).weight(2).minWidth(100).buildColumn()
                .<Label>column(new DelegatingStyledCellLabelProvider(new LabelTextProvider() {
                    @Override
                    public String getValue(Label label) {
                        return label.getValue();
                    }
                })).name("Value").align(SWT.LEFT).weight(2).minWidth(100).buildColumn().buildViewer();
        viewer.addDoubleClickListener(
                e -> editLabel((Label) ((IStructuredSelection) e.getSelection()).getFirstElement()));
        viewer.setComparator(new ViewerComparator() {

            @Override
            public int compare(Viewer viewer, Object e1, Object e2) {
                Label first = (Label) e1;
                Label other = (Label) e2;
                return first.getName().compareTo(other.getName());
            }

        });
        return viewer;
    }

    private abstract class LabelTextProvider extends ColumnLabelProvider implements IStyledLabelProvider {

        @Override
        public String getToolTipText(Object label) {
            return isReadOnly((Label) label) ? "This label can not be modified" : null;
        }

        @Override
        public String getText(Object element) {
            return getStyledText(element).getString();
        }

        @Override
        public StyledString getStyledText(Object element) {
            StyledString styledString = new StyledString();
            Label label = (Label) element;
            String text = getValue(label);
            if (isReadOnly(label)) {
                styledString.append(text, StyledString.QUALIFIER_STYLER);
            } else {
                styledString.append(text);
            }
            return styledString;
        }

        abstract public String getValue(Label label);
    }

    /*
     * Only allow editing or removal of labels that are not
     * deemed readonly.  Following the lead of the webconsole here
     */
    private class IsNotNullOrReadOnlyBooleanConverter extends Converter {

        public IsNotNullOrReadOnlyBooleanConverter() {
            super(Label.class, Boolean.class);
        }

        @Override
        public Object convert(Object arg) {
            if (arg == null)
                return Boolean.FALSE;
            return !isReadOnly((Label) arg);
        }

    }

    private boolean isReadOnly(Label label) {
        return model.getReadOnlyLabels().contains(label.getName());
    }
}