package org.openlca.app.editors.dq_systems; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.events.TraverseEvent; import org.eclipse.swt.events.TraverseListener; import org.eclipse.swt.graphics.FontMetrics; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.forms.IManagedForm; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.ScrolledForm; import org.eclipse.ui.forms.widgets.Section; import org.openlca.app.M; import org.openlca.app.editors.InfoSection; import org.openlca.app.editors.ModelPage; import org.openlca.app.util.Controls; import org.openlca.app.util.DQUI; import org.openlca.app.util.UI; import org.openlca.core.model.DQIndicator; import org.openlca.core.model.DQScore; import org.openlca.core.model.DQSystem; import org.openlca.core.model.ModelType; class DQSystemInfoPage extends ModelPage<DQSystem> { private FormToolkit toolkit; private ScrolledForm form; private Composite body; private Section indicatorSection; private Section uncertaintySection; private Map<Integer, Text> indicatorTexts = new HashMap<>(); private Map<Integer, Text> scoreTexts = new HashMap<>(); DQSystemInfoPage(DQSystemEditor editor) { super(editor, "DQSystemInfoPage", M.GeneralInformation); } void redraw() { indicatorTexts.clear(); indicatorSection.dispose(); if (uncertaintySection != null) uncertaintySection.dispose(); createAdditionalInfo(body); form.reflow(true); } @Override protected void createFormContent(IManagedForm managedForm) { form = UI.formHeader(managedForm); updateFormTitle(); toolkit = managedForm.getToolkit(); body = UI.formBody(form, toolkit); InfoSection infoSection = new InfoSection(getEditor()); infoSection.render(body, toolkit); createDropComponent(M.Source, "source", ModelType.SOURCE, infoSection.getContainer()); createAdditionalInfo(body); body.setFocus(); form.reflow(true); } @Override protected void updateFormTitle() { if (form == null) return; form.setText(M.DataQualitySystem + ": " + getModel().getName()); } private void createAdditionalInfo(Composite body) { Collections.sort(getModel().indicators); for (DQIndicator indicator : getModel().indicators) { Collections.sort(indicator.scores); } indicatorSection = UI.section(body, toolkit, M.IndicatorsScores); Composite indicatorClient = UI.sectionClient(indicatorSection, toolkit); createIndicatorMatrix(indicatorClient); if (!getModel().hasUncertainties) return; uncertaintySection = UI.section(body, toolkit, M.Uncertainties); Composite uncertaintyClient = UI.sectionClient(uncertaintySection, toolkit); createUncertaintyMatrix(uncertaintyClient); } private void createIndicatorMatrix(Composite composite) { UI.gridLayout(composite, getModel().getScoreCount() + 2); createHeader(composite, true); createAddScoreButton(composite); for (DQIndicator indicator : getModel().indicators) { Text nameText = createTextCell(composite, 1, 15); ((GridData) nameText.getLayoutData()).verticalAlignment = SWT.TOP; getBinding().onString(() -> indicator, "name", nameText); indicatorTexts.put(indicator.position, nameText); for (DQScore score : indicator.scores) { Text descriptionText = createTextCell(composite, 8, 8); getBinding().onString(() -> score, "description", descriptionText); descriptionText.setBackground(DQUI.getColor(score.position, getModel().getScoreCount())); } createRemoveIndicatorButton(composite, indicator.position); } createAddIndicatorButton(composite); for (int i = 1; i <= getModel().getScoreCount(); i++) { createRemoveScoreButton(composite, i); } } private void createUncertaintyMatrix(Composite composite) { UI.gridLayout(composite, getModel().getScoreCount() + 1); createHeader(composite, false); for (DQIndicator indicator : getModel().indicators) { String name = indicator.name != null ? indicator.name : ""; Label label = toolkit.createLabel(composite, name); label.setToolTipText(name); setGridData(label, 1, 15); Text indicatorText = indicatorTexts.get(indicator.position); indicatorText.addModifyListener((e) -> { label.setText(indicatorText.getText()); label.setToolTipText(indicatorText.getText()); }); for (DQScore score : indicator.scores) { Text uncertaintyText = createTextCell(composite, 1, 8); getBinding().onDouble(() -> score, "uncertainty", uncertaintyText); } } } private void createHeader(Composite composite, boolean editable) { UI.formLabel(composite, ""); for (int i = 1; i <= getModel().getScoreCount(); i++) { String scoreLabel = getModel().getScoreLabel(i); if (scoreLabel == null) { scoreLabel = Integer.toString(i); } if (editable) { Text labelText = createTextCell(composite, 1, 8); labelText.setText(scoreLabel); int pos = i; labelText.addModifyListener((e) -> { getModel().setScoreLabel(pos, labelText.getText()); getEditor().setDirty(true); }); scoreTexts.put(i, labelText); } else { Label label = UI.formLabel(composite, scoreLabel); label.setToolTipText(scoreLabel); setGridData(label, 1, 8); ((GridData) label.getLayoutData()).horizontalAlignment = SWT.CENTER; Text scoreText = scoreTexts.get(i); scoreText.addModifyListener((e) -> { label.setText(scoreText.getText()); label.setToolTipText(scoreText.getText()); }); } } } private Text createTextCell(Composite composite, int heightFactor, int widthFactor) { Text text = toolkit.createText(composite, null, SWT.BORDER | SWT.MULTI | SWT.WRAP); text.addTraverseListener(new TraverseListener() { public void keyTraversed(TraverseEvent e) { if (e.detail == SWT.TRAVERSE_TAB_NEXT || e.detail == SWT.TRAVERSE_TAB_PREVIOUS) { e.doit = true; } } }); setGridData(text, heightFactor, widthFactor); return text; } private void setGridData(Control control, int heightFactor, int widthFactor) { GC gc = new GC(control); try { gc.setFont(control.getFont()); FontMetrics fm = gc.getFontMetrics(); GridData gd = new GridData(SWT.LEFT, SWT.CENTER, false, false); gd.heightHint = heightFactor * fm.getHeight(); gd.widthHint = widthFactor * fm.getHeight(); control.setLayoutData(gd); } finally { gc.dispose(); } } private void createAddScoreButton(Composite parent) { Button button = toolkit.createButton(parent, M.AddScore, SWT.NONE); if (getModel().indicators.size() == 0) { button.setEnabled(false); return; } Controls.onSelect(button, (e) -> { int newScore = getModel().getScoreCount() + 1; for (DQIndicator indicator : getModel().indicators) { DQScore score = new DQScore(); score.position = newScore; score.label = "Score " + newScore; score.description = indicator.name + " - score " + newScore; indicator.scores.add(score); } getEditor().setDirty(true); redraw(); }); } private void createRemoveScoreButton(Composite parent, int position) { Button button = toolkit.createButton(parent, M.RemoveScore, SWT.NONE); Controls.onSelect(button, (e) -> { for (DQIndicator indicator : getModel().indicators) { for (DQScore score : new ArrayList<>(indicator.scores)) { if (score.position < position) continue; if (score.position == position) { indicator.scores.remove(score); continue; } score.position--; } } getEditor().setDirty(true); redraw(); }); } private void createAddIndicatorButton(Composite parent) { Button button = toolkit.createButton(parent, M.AddIndicator, SWT.NONE); Controls.onSelect(button, (e) -> { DQIndicator indicator = new DQIndicator(); indicator.name = "Indicator " + (getModel().indicators.size() + 1); indicator.position = getModel().indicators.size() + 1; for (int i = 1; i <= getModel().getScoreCount(); i++) { DQScore score = new DQScore(); score.position = i; score.label = getModel().getScoreLabel(i); score.description = indicator.name + " - score " + i; indicator.scores.add(score); } getModel().indicators.add(indicator); getEditor().setDirty(true); redraw(); }); } private void createRemoveIndicatorButton(Composite parent, int position) { Button button = toolkit.createButton(parent, M.RemoveIndicator, SWT.NONE); Controls.onSelect(button, (e) -> { for (DQIndicator indicator : new ArrayList<>(getModel().indicators)) { if (indicator.position < position) continue; if (indicator.position == position) { getModel().indicators.remove(indicator); continue; } indicator.position--; } getEditor().setDirty(true); redraw(); }); } }