package org.openlca.app.editors.flows;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ImageHyperlink;
import org.eclipse.ui.forms.widgets.Section;
import org.openlca.app.App;
import org.openlca.app.M;
import org.openlca.app.editors.UsageView;
import org.openlca.app.rcp.images.Icon;
import org.openlca.app.util.Colors;
import org.openlca.app.util.Controls;
import org.openlca.app.util.Labels;
import org.openlca.app.util.UI;
import org.openlca.core.database.FlowDao;
import org.openlca.core.database.IDatabase;
import org.openlca.core.database.ProcessDao;
import org.openlca.core.model.Flow;
import org.openlca.core.model.Process;
import org.openlca.core.model.descriptors.Descriptors;
import org.openlca.core.model.descriptors.ProcessDescriptor;
import org.openlca.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Renders the section with links to providers and recipients of a given flow.
*/
class FlowUseSection {
/**
* Shows the maximum number of links that should be shown in a section. A
* section is currently not usable or even crashes if there is a huge number
* of links.
*/
private int MAX_LINKS = 25;
private Logger log = LoggerFactory.getLogger(getClass());
private Flow flow;
private IDatabase database;
private Composite parent;
private FormToolkit toolkit;
FlowUseSection(Flow flow, IDatabase database) {
this.flow = flow;
this.database = database;
}
void render(Composite body, FormToolkit toolkit) {
log.trace("render flow-use-section for flow {}", flow);
FlowDao dao = new FlowDao(database);
Set<Long> recipients = dao.getRecipients(flow.getId());
Set<Long> providers = dao.getProviders(flow.getId());
if (recipients.isEmpty() && providers.isEmpty())
return;
Section section = UI.section(body, toolkit, M.UsedInProcesses);
section.setExpanded(false);
parent = UI.sectionClient(section, toolkit);
this.toolkit = toolkit;
App.runInUI("Render usage links", () -> {
renderLinks(M.ConsumedBy, recipients,
Icon.INPUT.get());
renderLinks(M.ProducedBy, providers,
Icon.OUTPUT.get());
});
}
private void renderLinks(String label, Set<Long> processIds, Image image) {
if (processIds.isEmpty())
return;
UI.formLabel(parent, toolkit, label);
Composite composite = toolkit.createComposite(parent);
UI.gridLayout(composite, 1).verticalSpacing = 0;
for (ProcessDescriptor d : loadDescriptors(processIds)) {
renderFlowLink(image, composite, d);
}
int size = processIds.size();
if (size > MAX_LINKS) {
int rest = size - MAX_LINKS;
renderUsageLink(image, composite, rest);
}
}
private List<ProcessDescriptor> loadDescriptors(Set<Long> ids) {
if (ids.isEmpty())
return Collections.emptyList();
ProcessDao dao = new ProcessDao(database);
TreeSet<Long> firstIds = new TreeSet<>();
int i = 0;
for (Long id : ids) {
firstIds.add(id);
i++;
if (i > MAX_LINKS)
break;
}
List<ProcessDescriptor> list = dao.getDescriptors(firstIds);
list.sort((d1, d2) -> {
return Strings.compare(Labels.getDisplayName(d1), Labels.getDisplayName(d2));
});
return list;
}
private void renderFlowLink(Image image, Composite composite,
ProcessDescriptor d) {
ImageHyperlink link = new ImageHyperlink(composite, SWT.TOP);
link.setText(Labels.getDisplayName(d));
link.setToolTipText(Labels.getDisplayInfoText(d));
link.setImage(image);
link.setForeground(Colors.linkBlue());
Controls.onClick(link, e -> {
ProcessDao dao = new ProcessDao(database);
Process p = dao.getForId(d.getId());
App.openEditor(p);
});
}
private void renderUsageLink(Image image, Composite composite, int rest) {
if (rest < 1)
return;
ImageHyperlink link = new ImageHyperlink(composite, SWT.TOP);
link.setText(rest + " more"); // TODO: @translate
link.setImage(image);
link.setForeground(Colors.linkBlue());
Controls.onClick(link,
e -> UsageView.open(Descriptors.toDescriptor(flow)));
}
}