package org.openlca.app.editors.processes;
import java.util.Objects;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
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.Text;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.events.HyperlinkAdapter;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Hyperlink;
import org.eclipse.ui.forms.widgets.ImageHyperlink;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.openlca.app.App;
import org.openlca.app.Event;
import org.openlca.app.M;
import org.openlca.app.db.Database;
import org.openlca.app.editors.InfoSection;
import org.openlca.app.editors.ModelPage;
import org.openlca.app.editors.processes.data_quality.DataQualityShell;
import org.openlca.app.editors.processes.kml.EditorHandler;
import org.openlca.app.editors.processes.kml.KmlUtil;
import org.openlca.app.editors.processes.kml.MapEditor;
import org.openlca.app.navigation.Navigator;
import org.openlca.app.preferencepages.FeatureFlag;
import org.openlca.app.rcp.images.Images;
import org.openlca.app.rcp.images.Overlay;
import org.openlca.app.util.Controls;
import org.openlca.app.util.Editors;
import org.openlca.app.util.Error;
import org.openlca.app.util.UI;
import org.openlca.app.viewers.combo.ExchangeViewer;
import org.openlca.app.viewers.combo.LocationViewer;
import org.openlca.core.database.LocationDao;
import org.openlca.core.model.DQSystem;
import org.openlca.core.model.Location;
import org.openlca.core.model.ModelType;
import org.openlca.core.model.Process;
import org.openlca.util.Geometries;
import org.openlca.util.KeyGen;
import com.google.common.eventbus.Subscribe;
class InfoPage extends ModelPage<Process> {
private ProcessEditor editor;
private FormToolkit toolkit;
private ImageHyperlink kmlLink;
private ScrolledForm form;
private ExchangeViewer quanRefViewer;
private LocationViewer locationViewer;
InfoPage(ProcessEditor editor) {
super(editor, "ProcessInfoPage", M.GeneralInformation);
this.editor = editor;
editor.getEventBus().register(this);
}
@Subscribe
public void handleExchangesChange(Event event) {
if (!event.match(editor.EXCHANGES_CHANGED))
return;
quanRefViewer.setInput(getModel());
}
@Override
protected void createFormContent(IManagedForm managedForm) {
form = UI.formHeader(managedForm);
updateFormTitle();
if (FeatureFlag.SHOW_REFRESH_BUTTONS.isEnabled())
Editors.addRefresh(form, editor);
toolkit = managedForm.getToolkit();
Composite body = UI.formBody(form, toolkit);
InfoSection infoSection = new InfoSection(getEditor());
infoSection.render(body, toolkit);
createCheckBox(M.InfrastructureProcess, "infrastructureProcess",
infoSection.getContainer());
createSystemButton(infoSection.getContainer());
createQuanRefSection(body);
createTimeSection(body);
createGeographySection(body);
createTechnologySection(body);
createDQSection(body);
body.setFocus();
form.reflow(true);
}
@Override
protected void updateFormTitle() {
if (form == null)
return;
form.setText(M.Process + ": " + getModel().getName());
}
private void createSystemButton(Composite container) {
toolkit.createLabel(container, "");
Button button = toolkit.createButton(container,
M.CreateProductSystem, SWT.NONE);
button.setImage(Images.get(ModelType.PRODUCT_SYSTEM, Overlay.NEW));
Controls.onSelect(button, (e) -> {
SystemCreation.run(getModel());
});
}
private void createQuanRefSection(Composite body) {
Composite composite = UI.formSection(body, toolkit,
M.QuantitativeReference);
UI.formLabel(composite, toolkit, M.QuantitativeReference);
quanRefViewer = new ExchangeViewer(composite, ExchangeViewer.OUTPUTS,
ExchangeViewer.PRODUCTS);
quanRefViewer.setInput(getModel());
getBinding().onModel(() -> getModel(), "quantitativeReference",
quanRefViewer);
editor.onSaved(() -> {
quanRefViewer.setInput(getModel());
quanRefViewer.select(getModel().getQuantitativeReference());
});
}
private void createTechnologySection(Composite body) {
Composite composite = UI
.formSection(body, toolkit, M.Technology);
createMultiText(M.Description, "documentation.technology",
composite);
}
private void createTimeSection(Composite body) {
Composite composite = UI.formSection(body, toolkit, M.Time);
createDate(M.StartDate, "documentation.validFrom", composite);
createDate(M.EndDate, "documentation.validUntil", composite);
createMultiText(M.Description, "documentation.time", composite);
}
private void createDQSection(Composite body) {
Composite composite = UI.formSection(body, toolkit, M.DataQuality);
toolkit.createLabel(composite, M.ProcessSchema);
DQSystemViewer processSystemViewer = new DQSystemViewer(composite);
processSystemViewer.setNullable(true);
processSystemViewer.setInput(Database.get());
getBinding().onModel(() -> getModel(), "dqSystem", processSystemViewer);
createDqEntryRow(composite);
toolkit.createLabel(composite, M.FlowSchema);
DQSystemViewer ioSystemViewer = new DQSystemViewer(composite);
ioSystemViewer.setNullable(true);
ioSystemViewer.setInput(Database.get());
getBinding().onModel(() -> getModel(), "exchangeDqSystem", ioSystemViewer);
toolkit.createLabel(composite, M.SocialSchema);
DQSystemViewer socialSystemViewer = new DQSystemViewer(composite);
socialSystemViewer.setNullable(true);
socialSystemViewer.setInput(Database.get());
getBinding().onModel(() -> getModel(), "socialDqSystem", socialSystemViewer);
}
private Hyperlink createDqEntryRow(Composite parent) {
UI.formLabel(parent, toolkit, M.DataQualityEntry);
Hyperlink link = UI.formLink(parent, toolkit, getDqEntryLabel());
Controls.onClick(
link,
e -> {
if (getModel().dqSystem == null) {
Error.showBox("Please select a data quality system first");
return;
}
String oldVal = getModel().dqEntry;
DQSystem system = getModel().dqSystem;
String entry = getModel().dqEntry;
DataQualityShell shell = DataQualityShell.withoutUncertainty(parent.getShell(), system, entry);
shell.onOk = InfoPage.this::onDqEntryDialogOk;
shell.onDelete = InfoPage.this::onDqEntryDialogDelete;
shell.addDisposeListener(e2 -> {
if (Objects.equals(oldVal, getModel().dqEntry))
return;
link.setText(getDqEntryLabel());
getEditor().setDirty(true);
});
shell.open();
});
return link;
}
private void onDqEntryDialogOk(DataQualityShell shell) {
getModel().dqEntry = shell.getSelection();
}
private void onDqEntryDialogDelete(DataQualityShell shell) {
getModel().dqEntry = null;
}
private String getDqEntryLabel() {
if (getModel().dqEntry != null)
return getModel().dqEntry;
return "(not specified)";
}
private void createGeographySection(Composite body) {
Composite composite = UI.formSection(body, toolkit, M.Geography);
toolkit.createLabel(composite, M.Location);
locationViewer = new LocationViewer(composite);
locationViewer.setNullable(true);
locationViewer.setInput(Database.get());
getBinding().onModel(() -> getModel(), "location", locationViewer);
locationViewer.addSelectionChangedListener((s) -> kmlLink
.setText(getKmlDisplayText()));
createKmlSection(composite);
createMultiText(M.Description, "documentation.geography",
composite);
}
private void createKmlSection(Composite parent) {
UI.formLabel(parent, "KML");
Composite composite = toolkit.createComposite(parent);
UI.gridData(composite, true, true);
GridLayout layout = UI.gridLayout(composite, 2);
layout.marginWidth = 0;
layout.marginHeight = 0;
kmlLink = toolkit.createImageHyperlink(composite, SWT.TOP);
kmlLink.addHyperlinkListener(new MapEditorDispatch());
UI.gridData(kmlLink, true, false).horizontalSpan = 2;
kmlLink.setText(getKmlDisplayText());
}
private String getKmlDisplayText() {
Process process = getModel();
if (process.getLocation() != null)
if (process.getLocation().getKmz() != null)
return KmlUtil.getDisplayText(process.getLocation().getKmz());
return "none";
}
private void openMap(EditorHandler handler) {
String name = getName();
String kml = getKml();
if (kml != null)
// prepare the KML for the map so that no syntax errors are thrown
kml = kml.trim().replace("\n", "").replace("\r", "");
MapEditor.open(name, kml, handler);
}
private String getKml() {
Process process = getModel();
if (process.getLocation() != null)
if (process.getLocation().getKmz() != null)
return KmlUtil.toKml(process.getLocation().getKmz());
return null;
}
private String getName() {
if (getModel().getLocation() == null)
return "";
return getModel().getLocation().getName();
}
private class MapEditorDispatch extends HyperlinkAdapter implements
SelectionListener, EditorHandler {
private LocationDao locationDao = new LocationDao(Database.get());
public void widgetDefaultSelected(SelectionEvent e) {
openMap(this);
}
@Override
public void widgetSelected(SelectionEvent e) {
openMap(this);
}
@Override
public void linkActivated(HyperlinkEvent e) {
openMap(this);
}
@Override
public boolean contentSaved(String kml) {
Location location = createLocation(kml);
if (location == null) // user aborted
return false;
locationViewer.setInput(Database.get());
locationViewer.select(location);
kmlLink.setText(getKmlDisplayText());
Navigator.refresh();
return true;
}
private Location createLocation(String kml) {
Location location = new Location();
String[] nameAndCode = promptForNameAndCode();
if (nameAndCode == null) // user aborted dialog
return null;
location.setName(nameAndCode[0]);
location.setCode(nameAndCode[1]);
location.setRefId(KeyGen.get(nameAndCode[1]));
if (kml != null)
location.setKmz(Geometries.kmlToKmz(kml));
else
location.setKmz(null);
return locationDao.insert(location);
}
@Override
public boolean hasModel() {
return getModel().getLocation() != null;
}
@Override
public void openModel() {
if (!hasModel())
return;
App.openEditor(getModel().getLocation());
}
private String[] promptForNameAndCode() {
NameAndCodeDialog dialog = new NameAndCodeDialog();
if (dialog.open() == Dialog.CANCEL)
return null;
return new String[] { dialog.name, dialog.code };
}
private class NameAndCodeDialog extends Dialog {
private String name;
private String code;
private NameAndCodeDialog() {
super(UI.shell());
}
@Override
protected Control createDialogArea(Composite parent) {
Composite body = new Composite(parent, SWT.NONE);
UI.gridLayout(body, 1);
UI.gridData(body, true, true);
UI.formLabel(body,
M.EnterLocationNameAndCode);
Composite container = UI.formComposite(body);
UI.gridData(container, true, true);
final Text nameText = UI.formText(container, M.Name);
nameText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
name = nameText.getText();
updateButtons();
}
});
final Text codeText = UI.formText(container, M.Code);
codeText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
code = codeText.getText();
updateButtons();
}
});
return body;
}
private void updateButtons() {
getButton(IDialogConstants.OK_ID).setEnabled(isPageComplete());
}
private boolean isPageComplete() {
return name != null && !name.isEmpty();
}
@Override
protected Control createButtonBar(Composite parent) {
Control buttonBar = super.createButtonBar(parent);
updateButtons();
return buttonBar;
}
}
}
}