package org.openlca.app.components; import java.util.Collection; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.forms.widgets.FormToolkit; import org.openlca.app.M; import org.openlca.app.util.CostResultDescriptor; import org.openlca.app.util.CostResults; import org.openlca.app.viewers.combo.AbstractComboViewer; import org.openlca.app.viewers.combo.CostResultViewer; import org.openlca.app.viewers.combo.FlowViewer; import org.openlca.app.viewers.combo.ImpactCategoryViewer; import org.openlca.core.database.EntityCache; import org.openlca.core.model.ModelType; import org.openlca.core.model.descriptors.FlowDescriptor; import org.openlca.core.model.descriptors.ImpactCategoryDescriptor; import org.openlca.core.results.IResultProvider; import org.openlca.core.results.SimpleResultProvider; /** * Two combo boxes showing flows and impact categories. The impact categories * are only shown if the are category items available. The user can activate the * flow or impact combo and the selection change fires the selection of the * current activated combo. */ public class ResultTypeSelection { private ModelType resultType = ModelType.FLOW; private EntityCache cache; private Collection<FlowDescriptor> flows; private Collection<ImpactCategoryDescriptor> impacts; private Collection<CostResultDescriptor> costs; private Object initialSelection; private EventHandler eventHandler; private FlowViewer flowCombo; private ImpactCategoryViewer impactCombo; private CostResultViewer costCombo; public static Dispatch on(IResultProvider result, EntityCache cache) { ResultTypeSelection selection = new ResultTypeSelection(cache); selection.flows = result.getFlowDescriptors(); if (result.hasImpactResults()) selection.impacts = result.getImpactDescriptors(); if (result.hasCostResults() && (result instanceof SimpleResultProvider)) selection.costs = CostResults.getDescriptors( (SimpleResultProvider<?>) result); return new Dispatch(selection); } private ResultTypeSelection(EntityCache cache) { this.cache = cache; } public void selectWithEvent(Object o) { if (o == null) return; if (o instanceof FlowDescriptor) selectFlow(o); else if (o instanceof ImpactCategoryDescriptor) selectImpact(o); else if (o instanceof CostResultDescriptor) selectCost(o); } public Object getSelection() { switch (resultType) { case FLOW: return flowCombo.getSelected(); case IMPACT_CATEGORY: return impactCombo.getSelected(); case CURRENCY: return costCombo.getSelected(); default: return null; } } private void selectImpact(Object o) { resultType = ModelType.IMPACT_CATEGORY; if (impactCombo != null) { impactCombo.select((ImpactCategoryDescriptor) o); impactCombo.setEnabled(true); } if (flowCombo != null) flowCombo.setEnabled(false); if (costCombo != null) costCombo.setEnabled(false); } private void selectFlow(Object o) { resultType = ModelType.FLOW; if (flowCombo != null) { flowCombo.select((FlowDescriptor) o); flowCombo.setEnabled(true); } if (impactCombo != null) impactCombo.setEnabled(false); if (costCombo != null) costCombo.setEnabled(false); } private void selectCost(Object o) { resultType = ModelType.CURRENCY; if (costCombo != null) { costCombo.select((CostResultDescriptor) o); costCombo.setEnabled(true); } if (flowCombo != null) flowCombo.setEnabled(false); if (impactCombo != null) impactCombo.setEnabled(false); } private void render(Composite parent, FormToolkit toolkit) { ModelType initType = getType(initialSelection); if (initType != ModelType.UNKNOWN) resultType = initType; if (flows != null && !flows.isEmpty()) initFlowCombo(toolkit, parent); if (impacts != null && !impacts.isEmpty()) initImpactCombo(toolkit, parent); if (costs != null && !costs.isEmpty()) initCostCombo(toolkit, parent); } private void initFlowCombo(FormToolkit toolkit, Composite section) { boolean enabled = getType(initialSelection) == ModelType.FLOW; Button check = toolkit.createButton(section, M.Flow, SWT.RADIO); check.setSelection(enabled); flowCombo = new FlowViewer(section, cache); flowCombo.setEnabled(enabled); FlowDescriptor[] input = flows .toArray(new FlowDescriptor[flows.size()]); flowCombo.setInput(input); flowCombo.selectFirst(); flowCombo.addSelectionChangedListener((val) -> fireSelection()); if (enabled) flowCombo.select((FlowDescriptor) initialSelection); new ResultTypeCheck(flowCombo, check, ModelType.FLOW); } private void initImpactCombo(FormToolkit toolkit, Composite section) { boolean enabled = getType(initialSelection) == ModelType.IMPACT_CATEGORY; Button check = toolkit.createButton(section, M.ImpactCategory, SWT.RADIO); check.setSelection(enabled); impactCombo = new ImpactCategoryViewer(section); impactCombo.setEnabled(enabled); impactCombo.setInput(impacts); impactCombo.selectFirst(); impactCombo.addSelectionChangedListener((val) -> fireSelection()); if (enabled) impactCombo.select((ImpactCategoryDescriptor) initialSelection); new ResultTypeCheck(impactCombo, check, ModelType.IMPACT_CATEGORY); } private void initCostCombo(FormToolkit toolkit, Composite section) { boolean enabled = getType(initialSelection) == ModelType.CURRENCY; Button check = toolkit.createButton(section, M.CostCategory, SWT.RADIO); check.setSelection(enabled); costCombo = new CostResultViewer(section); costCombo.setEnabled(enabled); costCombo.setInput(costs); costCombo.selectFirst(); costCombo.addSelectionChangedListener((val) -> fireSelection()); if (enabled) costCombo.select((CostResultDescriptor) initialSelection); new ResultTypeCheck(costCombo, check, ModelType.CURRENCY); } private void fireSelection() { if (eventHandler == null || resultType == null) return; switch (resultType) { case FLOW: eventHandler.flowSelected(flowCombo.getSelected()); break; case IMPACT_CATEGORY: eventHandler.impactCategorySelected(impactCombo.getSelected()); break; case CURRENCY: eventHandler.costResultSelected(costCombo.getSelected()); break; default: break; } } private ModelType getType(Object o) { if (o instanceof FlowDescriptor) return ModelType.FLOW; else if (o instanceof ImpactCategoryDescriptor) return ModelType.IMPACT_CATEGORY; else if (o instanceof CostResultDescriptor) return ModelType.CURRENCY; else return ModelType.UNKNOWN; } private class ResultTypeCheck implements SelectionListener { private AbstractComboViewer<?> viewer; private Button check; private ModelType type; public ResultTypeCheck(AbstractComboViewer<?> viewer, Button check, ModelType type) { this.viewer = viewer; this.check = check; this.type = type; check.addSelectionListener(this); } @Override public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } @Override public void widgetSelected(SelectionEvent e) { if (check.getSelection()) { viewer.setEnabled(true); resultType = this.type; fireSelection(); } else viewer.setEnabled(false); } } /** * The event handler for selection changes. */ public interface EventHandler { void flowSelected(FlowDescriptor flow); void impactCategorySelected(ImpactCategoryDescriptor impact); void costResultSelected(CostResultDescriptor cost); } /** * Dispatch class for the initialization of the widgets. */ public static class Dispatch { private ResultTypeSelection selection; private Dispatch(ResultTypeSelection selection) { this.selection = selection; } public Dispatch withSelection(Object item) { selection.initialSelection = item; return this; } public Dispatch withEventHandler(EventHandler handler) { selection.eventHandler = handler; return this; } public ResultTypeSelection create(Composite parent, FormToolkit toolkit) { selection.render(parent, toolkit); return selection; } } }