// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.debug.ui.liveedit;
import java.util.ArrayList;
import java.util.List;
import org.chromium.debug.core.model.ConnectedTargetData;
import org.chromium.debug.core.model.PushChangesPlan;
import org.chromium.debug.core.util.ScriptTargetMapping;
import org.chromium.debug.ui.TableUtils;
import org.chromium.debug.ui.TableUtils.ColumnBasedLabelProvider;
import org.chromium.debug.ui.TableUtils.ColumnData;
import org.chromium.debug.ui.TableUtils.TrivialAdapter;
import org.chromium.debug.ui.TableUtils.ValueAdapter;
import org.chromium.debug.ui.actions.ChooseVmControl;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
/**
* A dialog that shows LiveEdit update results.
*/
public class LiveEditResultDialog extends Dialog {
/**
* A dialog input. It's essentially an algebraic type, all cases are available
* via {@link #accept(InputVisitor)} method.
*/
public interface Input {
<RES> RES accept(InputVisitor<RES> visitor);
}
/**
* A specialized type of dialog input: one that associated with a particular VM.
*/
public interface SingleInput extends Input {
<RES> RES acceptSingle(SingleInputVisitor<RES> visitor);
ScriptTargetMapping getFilePair();
}
public interface InputVisitor<RES> extends SingleInputVisitor<RES> {
RES visitMultipleResult(MultipleResult multipleResult);
}
public interface SingleInputVisitor<RES> {
RES visitSuccess(SuccessResult successResult);
RES visitErrorMessage(String text);
}
public interface MultipleResult {
List<? extends SingleInput> getList();
}
public interface SuccessResult {
boolean hasDroppedFrames();
/** @return may be null */
OldScriptData getOldScriptData();
}
public interface OldScriptData {
LiveEditDiffViewer.Input getScriptStructure();
String getOldScriptName();
}
public static SingleInput createTextInput(final String text,
final PushChangesPlan changesPlan) {
return new LiveEditResultDialog.SingleInput() {
public <RES> RES accept(LiveEditResultDialog.InputVisitor<RES> visitor) {
return acceptSingle(visitor);
}
public <RES> RES acceptSingle(LiveEditResultDialog.SingleInputVisitor<RES> visitor) {
return visitor.visitErrorMessage(text);
}
public ScriptTargetMapping getFilePair() {
return changesPlan.getScriptTargetMapping();
}
};
}
private final Input input;
public LiveEditResultDialog(Shell shell, Input input) {
super(shell);
this.input = input;
}
@Override
protected boolean isResizable() {
return true;
}
@Override
protected void configureShell(Shell shell) {
super.configureShell(shell);
shell.setText(Messages.LiveEditResultDialog_TITLE);
}
@Override
protected void createButtonsForButtonBar(Composite parent) {
// create only OK button
createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
}
@Override
protected Control createDialogArea(Composite parent) {
final Composite composite = (Composite) super.createDialogArea(parent);
input.accept(new InputVisitor<Void>() {
public Void visitErrorMessage(String text) {
createErrorMessageControls(composite, text);
return null;
}
public Void visitSuccess(SuccessResult successResult) {
createSuccessResultControls(composite, successResult);
return null;
}
public Void visitMultipleResult(MultipleResult multipleResult) {
createMultipleResultsControl(composite, multipleResult);
return null;
}
});
return composite;
}
private void createErrorMessageControls(Composite parent, String text) {
Text textControl = new Text(parent, SWT.WRAP);
Display display = textControl.getDisplay();
textControl.setBackground(display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
textControl.setText(text);
}
private void createSuccessResultControls(Composite parent, SuccessResult successResult) {
Label label1 = new Label(parent, SWT.NONE);
label1.setText(Messages.LiveEditResultDialog_SUCCESS);
if (successResult.hasDroppedFrames()) {
Label label2 = new Label(parent, SWT.NONE);
label2.setText(Messages.LiveEditResultDialog_FRAMES_DROPPED);
}
final OldScriptData withOldScript = successResult.getOldScriptData();
if (withOldScript != null) {
Label new_script_label = new Label(parent, SWT.NONE);
new_script_label.setText(Messages.LiveEditResultDialog_SCRIPT_CREATED);
LiveEditDiffViewer.Configuration configuration =
new LiveEditDiffViewer.Configuration() {
public String getNewLabel() {
return Messages.LiveEditResultDialog_CURRENT_SCRIPT;
}
public String getOldLabel() {
return NLS.bind(Messages.LiveEditResultDialog_OLD_SCRIPT,
withOldScript.getOldScriptName());
}
public boolean oldOnLeft() {
return false;
}
};
LiveEditDiffViewer viewer = LiveEditDiffViewer.create(parent, configuration);
viewer.setInput(withOldScript.getScriptStructure());
}
}
/**
* Result for several VMs' update is shown as a table.
*/
private void createMultipleResultsControl(Composite parent, MultipleResult multipleResult) {
Label label = new Label(parent, SWT.NONE);
label.setText(Messages.LiveEditResultDialog_SEVERAL_VMS);
label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
final Table table = new Table(parent, SWT.BORDER);
table.setFont(parent.getFont());
table.setLayoutData(new GridData(GridData.FILL_BOTH));
table.setHeaderVisible(true);
ValueAdapter<SingleInput, ConnectedTargetData> inputToTargetAdapter =
new ValueAdapter<SingleInput, ConnectedTargetData>() {
public ConnectedTargetData convert(SingleInput from) {
return from.getFilePair().getConnectedTargetData();
}
};
List<ColumnData<SingleInput, ?>> columnDataList = new ArrayList<ColumnData<SingleInput,?>>(
ChooseVmControl.createLaunchTargetColumns(inputToTargetAdapter));
columnDataList.add(
ColumnData.create(new TrivialAdapter<SingleInput>(), new StatusLabelProvider()));
// Create physical columns in the table.
for (ColumnData<?,?> data : columnDataList) {
data.getLabelProvider().createColumn(table);
}
final TableViewer tableViewer = new TableViewer(table);
IStructuredContentProvider contentProvider = new IStructuredContentProvider() {
public Object[] getElements(Object inputElement) {
MultipleResult input = (MultipleResult) inputElement;
return input.getList().toArray();
}
public void dispose() {}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {}
};
tableViewer.setContentProvider(contentProvider);
ColumnBasedLabelProvider<SingleInput> labelProvider = new ColumnBasedLabelProvider<SingleInput>(
TableUtils.createCastAdapter(SingleInput.class), columnDataList);
tableViewer.setLabelProvider(labelProvider);
tableViewer.setInput(multipleResult);
}
private static class StatusLabelProvider extends TableUtils.ColumnLabelProvider<SingleInput> {
@Override public Image getColumnImage(SingleInput element) {
return null;
}
@Override public String getColumnText(SingleInput element) {
return element.acceptSingle(textGetterVisitor);
}
@Override public TableColumn createColumn(Table table) {
TableColumn statusCol = new TableColumn(table, SWT.NONE);
statusCol.setText(Messages.LiveEditResultDialog_STATUS);
statusCol.setWidth(200);
return statusCol;
}
private final SingleInputVisitor<String> textGetterVisitor = new SingleInputVisitor<String>() {
public String visitErrorMessage(String text) {
return NLS.bind(Messages.LiveEditResultDialog_FAILURE, text);
}
public String visitSuccess(SuccessResult successResult) {
return Messages.LiveEditResultDialog_OK;
}
};
}
}