blob: 5f70a67ad66db3fe07bc37522109ad7d9e397acd [file] [log] [blame]
// Copyright 2016 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.bazel.e4b.wizard;
import java.io.File;
import java.io.IOException;
import java.util.function.Consumer;
import org.eclipse.jface.bindings.keys.KeyStroke;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.fieldassist.ContentProposalAdapter;
import org.eclipse.jface.fieldassist.TextContentAdapter;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
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.DirectoryDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Text;
import com.google.common.collect.ImmutableList;
import com.google.devtools.bazel.e4b.Activator;
import com.google.devtools.bazel.e4b.command.BazelNotFoundException;
/**
* This is a quick wizard page that ask the user for the various targets and source path he wants to
* include.
*/
public class WorkspaceWizardPage extends WizardPage {
private Label workspaceRoot;
private List targets;
private Text target;
private Button addTargetButton;
private Button removeTargetButton;
private CheckboxTreeViewer directories;
private Composite container;
private Button workspaceRootButton;
private DirectoryDialog dialog;
private BazelTargetCompletionContentProposalProvider completionProvider;
protected WorkspaceWizardPage() {
super("Import Bazel project");
setTitle("Import Bazel project");
}
/**
* Returns the list of targets selected by the user.
*/
ImmutableList<String> getTargets() {
return ImmutableList.copyOf(targets.getItems());
}
/**
* Returns the list of directories selected by the user.
*/
ImmutableList<String> getDirectories() {
return DirectoryTreeContentProvider.getSelectPathsRelativeToRoot(directories);
}
/**
* Returns the workspace root selected by the user.
*/
public String getWorkspaceRoot() {
return workspaceRoot.getText();
}
@Override
public void createControl(Composite parent) {
container = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 3;
container.setLayout(layout);
createWorkspaceSelectionControls();
addLabel("Directories: ", 1, 5);
directories = DirectoryTreeContentProvider.createTreeView(container);
setControlGridData(directories.getTree(), 2, 5, true);
directories.addCheckStateListener(e -> updateControls());
new Label(container, SWT.NONE).setText("Targets:");
createTargetTextField();
setControlGridData(target, 1, 1, false);
addTargetButton = createButton("+", e -> addTarget());
targets = new List(container, SWT.SINGLE | SWT.BORDER);
setControlGridData(targets, 2, 5, true);
removeTargetButton = createButton("-", e -> deleteTarget());
targets.addSelectionListener(createSelectionListener(
e -> removeTargetButton.setEnabled(targets.getSelectionCount() > 0)));
setControl(container);
updateControls();
}
// A simple helper to use lambdas to create a SelectionListener that does the same action on all
// cases.
private static SelectionListener createSelectionListener(Consumer<SelectionEvent> f) {
return new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
f.accept(e);
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
f.accept(e);
}
};
}
private Button createButton(String text, Consumer<SelectionEvent> handler) {
Button result = new Button(container, SWT.DEFAULT);
result.setText(text);
result.addSelectionListener(createSelectionListener(handler));
result.setEnabled(false);
return result;
}
private void createWorkspaceSelectionControls() {
Label label = new Label(container, SWT.NONE);
label.setText("Workpsace root: ");
workspaceRoot = new Label(container, SWT.BORDER);
workspaceRoot.setText("");
workspaceRoot.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false));
dialog = new DirectoryDialog(getShell(), SWT.OPEN);
workspaceRootButton = new Button(container, SWT.DEFAULT);
workspaceRootButton.setText("...");
workspaceRootButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
String wr = dialog.open();
if (wr != null) {
workspaceRoot.setText(wr);
DirectoryTreeContentProvider.setFileTreeRoot(directories, new File(wr));
try {
completionProvider.setBazelInstance(
Activator.getDefault().getCommand().getInstance(new File(getWorkspaceRoot())));
} catch (IOException e1) {
MessageDialog.openError(getShell(), "Error",
getWorkspaceRoot() + " does not seems to be a Bazel workspace");
} catch (InterruptedException e1) {
Activator.error("Bazel was interrupted", e1);
} catch (BazelNotFoundException e1) {
MessageDialog.openError(getShell(), "Error", "Cannot found Bazel: " + e1.getMessage());
}
}
updateControls();
}
});
workspaceRootButton.setLayoutData(new GridData(GridData.END, GridData.CENTER, false, false));
}
private void setControlGridData(Control control, int horizontalSpan, int verticalSpan,
boolean verticalGrow) {
GridData data = new GridData(GridData.FILL, verticalGrow ? GridData.FILL : GridData.CENTER,
true, verticalGrow);
data.horizontalSpan = horizontalSpan;
data.verticalSpan = verticalSpan;
control.setLayoutData(data);
}
private void addLabel(String labelText, int horizontalSpan, int verticalSpan) {
Label label = new Label(container, SWT.NONE);
label.setText(labelText);
GridData data = new GridData(GridData.BEGINNING, GridData.FILL, false, true);
data.horizontalSpan = horizontalSpan;
data.verticalSpan = verticalSpan;
label.setLayoutData(data);
}
private void updateControls() {
boolean enabled = !workspaceRoot.getText().isEmpty();
directories.getTree().setEnabled(enabled);
targets.setEnabled(enabled);
target.setEnabled(enabled);
addTargetButton.setEnabled(enabled && !target.getText().isEmpty());
removeTargetButton.setEnabled(enabled && targets.getSelectionCount() > 0);
setPageComplete(
enabled && (directories.getCheckedElements().length > 0) && (targets.getItemCount() > 0));
}
private void setAutoCompletion() {
try {
ContentProposalAdapter adapter = null;
completionProvider = new BazelTargetCompletionContentProposalProvider();
KeyStroke ks = KeyStroke.getInstance("Ctrl+Space");
adapter = new ContentProposalAdapter(target, new TextContentAdapter(), completionProvider, ks,
null);
adapter.setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_REPLACE);
} catch (Exception e) {
e.printStackTrace();
}
}
private void createTargetTextField() {
target = new Text(container, SWT.BORDER);
setAutoCompletion();
target.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent ke) {
if (ke.keyCode == '\r' && (ke.stateMask & SWT.SHIFT) != 0 && !target.getText().isEmpty()) {
addTarget();
}
}
});
target.addModifyListener(e -> updateControls());
}
private void addTarget() {
targets.add(target.getText());
target.setText("");
setAutoCompletion();
updateControls();
}
private void deleteTarget() {
targets.remove(targets.getSelectionIndices());
updateControls();
}
}