package org.openlca.app.editors.units;
import java.util.Objects;
import java.util.UUID;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.ITableFontProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.TableItem;
import org.openlca.app.M;
import org.openlca.app.db.Database;
import org.openlca.app.rcp.images.Icon;
import org.openlca.app.util.Error;
import org.openlca.app.util.Numbers;
import org.openlca.app.util.UI;
import org.openlca.app.util.tables.Tables;
import org.openlca.app.viewers.table.AbstractTableViewer;
import org.openlca.app.viewers.table.modify.CheckBoxCellModifier;
import org.openlca.app.viewers.table.modify.ModifySupport;
import org.openlca.app.viewers.table.modify.TextCellModifier;
import org.openlca.app.viewers.table.modify.field.DoubleModifier;
import org.openlca.app.viewers.table.modify.field.StringModifier;
import org.openlca.core.database.UnitDao;
import org.openlca.core.database.usage.UnitUseSearch;
import org.openlca.core.model.Unit;
import org.openlca.core.model.UnitGroup;
class UnitViewer extends AbstractTableViewer<Unit> {
private static final String CONVERSION_FACTOR = M.ConversionFactor;
private static final String DESCRIPTION = M.Description;
private static final String FORMULA = M.Formula;
private static final String IS_REFERENCE = M.IsReference;
private static final String NAME = M.Name;
private static final String SYNONYMS = M.Synonyms;
private final UnitGroupEditor editor;
public UnitViewer(Composite parent, UnitGroupEditor editor) {
super(parent);
this.editor = editor;
ModifySupport<Unit> ms = getModifySupport();
ms.bind(NAME, new NameModifier());
ms.bind(DESCRIPTION, new StringModifier<>(editor, "description"));
ms.bind(SYNONYMS, new StringModifier<>(editor, "synonyms"));
ms.bind(CONVERSION_FACTOR, new ConversionModifier());
ms.bind(IS_REFERENCE, new ReferenceModifier());
getViewer().refresh(true);
Tables.bindColumnWidths(getViewer(), 0.25, 0.15, 0.15, 0.15, 0.15, 0.15);
Tables.onDoubleClick(getViewer(), (event) -> {
TableItem item = Tables.getItem(getViewer(), event);
if (item == null)
onCreate();
});
getViewer().getTable().getColumns()[3].setAlignment(SWT.RIGHT);
}
@Override
protected IBaseLabelProvider getLabelProvider() {
return new UnitLabelProvider();
}
@Override
protected String[] getColumnHeaders() {
return new String[] { NAME, DESCRIPTION, SYNONYMS, CONVERSION_FACTOR,
FORMULA, IS_REFERENCE };
}
@OnAdd
protected void onCreate() {
UnitDao dao = new UnitDao(Database.get());
Unit unit = new Unit();
String name = "new unit";
UnitGroup group = editor.getModel();
int i = 2;
while (!dao.getForName(name).isEmpty() || group.getUnit(name) != null)
name = "new unit " + i++;
unit.setName(name);
unit.setRefId(UUID.randomUUID().toString());
unit.setConversionFactor(1d);
group.getUnits().add(unit);
setInput(group.getUnits());
editor.setDirty(true);
}
@OnRemove
protected void onRemove() {
UnitGroup group = editor.getModel();
for (Unit unit : getAllSelected()) {
if (Objects.equals(group.getReferenceUnit(), unit)) {
Error.showBox(M.CannotDeleteReferenceUnit,
M.ReferenceUnitCannotBeDeleted);
continue;
}
UnitUseSearch usage = new UnitUseSearch(Database.get());
if (!usage.findUses(unit).isEmpty()) {
Error.showBox(M.CannotDeleteUnit,
M.UnitIsUsed);
continue;
}
group.getUnits().remove(unit);
}
setInput(group.getUnits());
editor.setDirty(true);
}
private class UnitLabelProvider extends LabelProvider implements
ITableLabelProvider, ITableFontProvider {
@Override
public Image getColumnImage(Object element, int column) {
if (column != 5)
return null;
UnitGroup group = editor.getModel();
Unit refUnit = group != null ? group.getReferenceUnit() : null;
if (refUnit != null && refUnit.equals(element))
return Icon.CHECK_TRUE.get();
return Icon.CHECK_FALSE.get();
}
@Override
public String getColumnText(Object element, int columnIndex) {
if (!(element instanceof Unit))
return null;
Unit unit = (Unit) element;
switch (columnIndex) {
case 0:
return unit.getName();
case 1:
return unit.getDescription();
case 2:
return unit.getSynonyms();
case 3:
return Numbers.format(unit.getConversionFactor());
case 4:
return getFormulaText(unit);
default:
return null;
}
}
private String getFormulaText(Unit unit) {
UnitGroup group = editor.getModel();
Unit refUnit = group != null ? group.getReferenceUnit() : null;
if (refUnit == null)
return null;
String amount = "1.0 " + unit.getName();
String factor = Numbers.format(unit.getConversionFactor());
String refAmount = factor + " " + refUnit.getName();
return amount + " = " + refAmount;
}
@Override
public Font getFont(Object element, int columnIndex) {
UnitGroup group = editor.getModel();
Unit refUnit = group != null ? group.getReferenceUnit() : null;
if (refUnit != null && refUnit.equals(element)) {
return UI.boldFont();
}
return null;
}
}
private class NameModifier extends TextCellModifier<Unit> {
@Override
protected String getText(Unit unit) {
return unit.getName();
}
@Override
protected void setText(Unit unit, String text) {
if (Objects.equals(unit.getName(), text))
return;
if (!new UnitDao(Database.get()).getForName(text).isEmpty()
|| editor.getModel().getUnit(text) != null) {
Error.showBox("A unit with the name '" + text + "' already exists");
return;
}
unit.setName(text);
editor.setDirty(true);
}
}
private class ConversionModifier extends DoubleModifier<Unit> {
private ConversionModifier() {
super(editor, "conversionFactor");
}
@Override
public boolean canModify(Unit unit) {
if (unit == null)
return false;
return !unit.equals(editor.getModel().getReferenceUnit());
}
}
private class ReferenceModifier extends CheckBoxCellModifier<Unit> {
@Override
protected boolean isChecked(Unit element) {
UnitGroup group = editor.getModel();
return Objects.equals(group.getReferenceUnit(), element);
}
@Override
protected void setChecked(Unit element, boolean value) {
UnitGroup group = editor.getModel();
if (!value)
return;
if (Objects.equals(element, group.getReferenceUnit()))
return;
group.setReferenceUnit(element);
double f = element.getConversionFactor();
for (Unit unit : group.getUnits()) {
double factor = unit.getConversionFactor() / f;
unit.setConversionFactor(factor);
}
editor.setDirty(true);
}
@Override
public boolean affectsOtherElements() {
return true;
}
}
}