/*******************************************************************************
* Copyright (c) 2016 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.common.ui;
import org.eclipse.core.databinding.Binding;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.conversion.Converter;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.core.databinding.validation.ValidationStatus;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.databinding.fieldassist.ControlDecorationSupport;
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.fieldassist.AutoCompleteField;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.fieldassist.FieldDecoration;
import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
import org.eclipse.jface.fieldassist.TextContentAdapter;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.jboss.tools.common.ui.databinding.ValueBindingBuilder;
import org.jboss.tools.openshift.common.core.utils.ProjectUtils;
import org.jboss.tools.openshift.common.core.utils.StringUtils;
import org.jboss.tools.openshift.internal.common.ui.databinding.RequiredControlDecorationUpdater;
import org.jboss.tools.openshift.internal.common.ui.utils.UIUtils;
public class SelectProjectComponentBuilder {
String textLabel = "Use existing workspace project:";
String browseLabel = "Browse...";
String errorText = "Select an existing project";
int hSpan = 1;
boolean required = true;
IObservableValue<?> eclipseProjectObservable;
SelectionListener selectionListener;
ISWTObservableValue projectNameTextObservable;
public SelectProjectComponentBuilder() {}
public void build(Composite container, DataBindingContext dbc) {
Label existingProjectLabel = new Label(container, SWT.NONE);
existingProjectLabel.setText("Eclipse Project: ");
GridDataFactory.fillDefaults()
.align(SWT.FILL, SWT.CENTER)
.applyTo(existingProjectLabel);
final Text existingProjectNameText = new Text(container, SWT.BORDER);
GridDataFactory.fillDefaults()
.align(SWT.FILL, SWT.CENTER)
.span(hSpan, 1).align(SWT.FILL, SWT.CENTER).grab(true, false)
.applyTo(existingProjectNameText);
projectNameTextObservable = WidgetProperties.text(SWT.Modify).observe(existingProjectNameText);
Binding eclipseProjectBinding = ValueBindingBuilder
.bind(projectNameTextObservable)
.validatingAfterConvert(new IValidator() {
@Override
public IStatus validate(Object value) {
if(value instanceof String) {
return ValidationStatus.ok();
} else if(value == null) {
if(required) {
return ValidationStatus.error("Select an existing project");
} else if(!StringUtils.isEmpty(existingProjectNameText.getText())) {
return ValidationStatus.error(NLS.bind("Project {0} does not exist", existingProjectNameText.getText()));
}
}
return ValidationStatus.ok();
}
})
.converting(new Converter(String.class, IProject.class) {
@Override
public Object convert(Object fromObject) {
String name = (String)fromObject;
return ProjectUtils.getProject(name);
}
})
.to(eclipseProjectObservable)
.converting(new Converter(IProject.class, String.class) {
@Override
public Object convert(Object fromObject) {
return fromObject == null ? "" : ((IProject)fromObject).getName();
}
})
.in(dbc);
ControlDecorationSupport.create(
eclipseProjectBinding, SWT.LEFT | SWT.TOP, null, new RequiredControlDecorationUpdater(true));
// project name content assist
ControlDecoration dec = new ControlDecoration(existingProjectNameText, SWT.TOP | SWT.RIGHT);
FieldDecoration contentProposalFieldIndicator =
FieldDecorationRegistry.getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_CONTENT_PROPOSAL);
dec.setImage(contentProposalFieldIndicator.getImage());
dec.setDescriptionText("Auto-completion is enabled when you start typing a project name.");
dec.setShowOnlyOnFocus(true);
new AutoCompleteField(existingProjectNameText, new TextContentAdapter(), ProjectUtils.getAllAccessibleProjectNames());
// browse projects
Button browseProjectsButton = new Button(container, SWT.NONE);
browseProjectsButton.setText("Browse...");
GridDataFactory.fillDefaults()
.align(SWT.LEFT, SWT.CENTER)
.grab(false, false)
.applyTo(browseProjectsButton);
UIUtils.setDefaultButtonWidth(browseProjectsButton);
browseProjectsButton.addSelectionListener(selectionListener);
}
/**
* Set value of label at text input. Has only effect if called before build().
*
* @param label
* @return self for chaining
*/
public SelectProjectComponentBuilder setTextLabel(String label) {
textLabel = label;
return this;
}
/**
* Set value of model observable. Has only effect if called before build().
*
* @param label
* @return self for chaining
*/
public SelectProjectComponentBuilder setEclipseProjectObservable(IObservableValue<?> eclipseProjectObservable) {
this.eclipseProjectObservable = eclipseProjectObservable;
return this;
}
/**
* Set number of columns in the grid to take by text input.
* Grid needs one column for label, hSpan columns for text input, and one column for browse button.
* Has only effect if called before build().
*
* @param label
* @return
*/
public SelectProjectComponentBuilder setHorisontalSpan(int hSpan) {
this.hSpan = hSpan;
return this;
}
/**
* By default input is required.
* Set to false if selecting a project is not required.
* Has only effect if called before build().
* @param required
* @return self for chaining
*/
public SelectProjectComponentBuilder setRequired(boolean required) {
this.required = required;
return this;
}
/**
* Set selection listener that will run a customized dialog and consume selected project.
* Has only effect if called before build().
*
* @param label
* @return self for chaining
*/
public SelectProjectComponentBuilder setSelectionListener(SelectionListener listener) {
selectionListener = listener;
return this;
}
/**
* Returns swt observable for text input. Has only effect if called after build().
*
* @param label
* @return
*/
public ISWTObservableValue getProjectNameTextObservable() {
return projectNameTextObservable;
}
}