/******************************************************************************* * Copyright (c) 2016 MEDEVIT <office@medevit.at>. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * MEDEVIT <office@medevit.at> - initial API and implementation ******************************************************************************/ package ch.elexis.core.findings.ui.composites; import java.time.LocalDate; import java.util.Comparator; import java.util.List; import java.util.Optional; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.ToolBarManager; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.nebula.widgets.nattable.data.IColumnAccessor; import org.eclipse.nebula.widgets.nattable.extension.glazedlists.GlazedListsDataProvider; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.ToolBar; import ca.odell.glazedlists.BasicEventList; import ca.odell.glazedlists.EventList; import ch.elexis.core.data.activator.CoreHub; import ch.elexis.core.data.events.ElexisEventDispatcher; import ch.elexis.core.findings.ICoding; import ch.elexis.core.findings.ICondition; import ch.elexis.core.findings.ICondition.ConditionCategory; import ch.elexis.core.findings.ICondition.ConditionStatus; import ch.elexis.core.findings.ui.dialogs.ConditionEditDialog; import ch.elexis.core.findings.ui.services.CodingServiceComponent; import ch.elexis.core.findings.ui.services.FindingsServiceComponent; import ch.elexis.core.model.IPersistentObject; import ch.elexis.core.ui.icons.Images; import ch.elexis.core.ui.locks.AcquireLockBlockingUi; import ch.elexis.core.ui.locks.AcquireLockUi; import ch.elexis.core.ui.locks.ILockHandler; import ch.elexis.core.ui.util.NatTableFactory; import ch.elexis.core.ui.util.NatTableWrapper; import ch.elexis.core.ui.util.NatTableWrapper.IDoubleClickListener; import ch.elexis.data.Patient; /** * {@link Composite} implementation for managing the {@link ICondition} entries, of a * {@link Patient}. * * @author thomas * */ public class DiagnoseListComposite extends Composite { private NatTableWrapper natTableWrapper; private ToolBarManager toolbarManager; private EventList<ICondition> dataList = new BasicEventList<>(); public DiagnoseListComposite(Composite parent, int style){ super(parent, style); setLayout(new GridLayout(1, false)); toolbarManager = new ToolBarManager(); toolbarManager.add(new AddConditionAction()); toolbarManager.add(new RemoveConditionAction()); ToolBar toolbar = toolbarManager.createControl(this); toolbar.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false)); toolbar.setBackground(parent.getBackground()); natTableWrapper = NatTableFactory.createSingleColumnTable(this, new GlazedListsDataProvider<ICondition>(dataList, new IColumnAccessor<ICondition>() { @Override public int getColumnCount(){ return 1; } @Override public Object getDataValue(ICondition condition, int columnIndex){ switch (columnIndex) { case 0: return getFormattedDescriptionText(condition); } return ""; } private Object getFormattedDescriptionText(ICondition condition){ StringBuilder text = new StringBuilder(); StringBuilder contentText = new StringBuilder(); // first display text Optional<String> conditionText = condition.getText(); conditionText.ifPresent(t -> { if (contentText.length() > 0) { contentText.append("\n"); } contentText.append(t); }); // then display the coding List<ICoding> codings = condition.getCoding(); if (codings != null && !codings.isEmpty()) { for (ICoding iCoding : codings) { if (contentText.length() > 0) { contentText.append(", "); } contentText.append("[") .append(CodingServiceComponent.getService().getShortLabel(iCoding)) .append("] "); } } // add additional information before content text.append("<strong>"); ConditionStatus status = condition.getStatus(); text.append(status.getLocalized()); Optional<String> start = condition.getStart(); start.ifPresent(string -> text.append(" (").append(string).append(" - ")); Optional<String> end = condition.getEnd(); end.ifPresent(string -> text.append(string)); start.ifPresent(string -> text.append(")")); List<String> notes = condition.getNotes(); if(!notes.isEmpty()) { text.append(" (" + notes.size() + ")"); } if (contentText.toString().contains("\n")) { text.append("</strong>\n").append(contentText.toString()); } else { text.append("</strong> ").append(contentText.toString()); } return text.toString(); } @Override public void setDataValue(ICondition condition, int arg1, Object arg2){ // setting data values is not enabled here. } }), null); natTableWrapper.getNatTable().setLayoutData(new GridData(GridData.FILL_BOTH)); natTableWrapper.addDoubleClickListener(new IDoubleClickListener() { @Override public void doubleClick(NatTableWrapper source, ISelection selection){ if (selection instanceof StructuredSelection && !selection.isEmpty()) { ICondition condition = (ICondition) ((StructuredSelection) selection).getFirstElement(); AcquireLockBlockingUi.aquireAndRun((IPersistentObject) condition, new ILockHandler() { @Override public void lockFailed(){ // do nothing } @Override public void lockAcquired(){ ConditionEditDialog dialog = new ConditionEditDialog(condition, getShell()); if (dialog.open() == Dialog.OK) { dialog.getCondition().ifPresent(c -> { source.getNatTable().refresh(); }); } } }); } } }); final MenuManager mgr = new MenuManager(); mgr.setRemoveAllWhenShown(true); mgr.addMenuListener(new ConditionsMenuListener()); natTableWrapper.getNatTable().setMenu(mgr.createContextMenu(natTableWrapper.getNatTable())); } public void setInput(List<ICondition> conditions){ dataList.clear(); conditions.sort(new Comparator<ICondition>() { @Override public int compare(ICondition left, ICondition right){ Optional<LocalDate> lrecorded = left.getDateRecorded(); Optional<LocalDate> rrecorded = right.getDateRecorded(); if(lrecorded.isPresent() && rrecorded.isPresent()) { return rrecorded.get().compareTo(lrecorded.get()); } else { Optional<String> lstart = left.getStart(); Optional<String> rstart = right.getStart(); if (lstart.isPresent() && rstart.isPresent()) { return rstart.get().compareTo(lstart.get()); } } return 0; } }); dataList.addAll(conditions); natTableWrapper.getNatTable().refresh(); } @Override public Point computeSize(int wHint, int hHint, boolean changed){ Point ret = toolbarManager.getControl().computeSize(wHint, hHint); Point natRet = natTableWrapper.computeSize(wHint, hHint); ret.y += natRet.y; ret.x = natRet.x; return ret; } @Override public void setBackground(Color color){ super.setBackground(color); if (natTableWrapper != null && !natTableWrapper.isDisposed()) { natTableWrapper.getNatTable().setBackground(color); } } private class ConditionsMenuListener implements IMenuListener { @Override public void menuAboutToShow(IMenuManager manager){ ISelection currentSelection = natTableWrapper.getSelection(); if (currentSelection instanceof StructuredSelection) { StructuredSelection sSelection = (StructuredSelection) currentSelection; if (sSelection.size() == 1) { ICondition selectedCondition = (ICondition) sSelection.getFirstElement(); ConditionStatus selectionStatus = selectedCondition.getStatus(); if (selectionStatus != ConditionStatus.ACTIVE) { manager .add(new ToggleStatusAction(selectedCondition, ConditionStatus.ACTIVE)); } if (selectionStatus != ConditionStatus.RESOLVED) { manager.add( new ToggleStatusAction(selectedCondition, ConditionStatus.RESOLVED)); } if (selectionStatus != ConditionStatus.RELAPSE) { manager.add( new ToggleStatusAction(selectedCondition, ConditionStatus.RELAPSE)); } if (selectionStatus != ConditionStatus.REMISSION) { manager.add( new ToggleStatusAction(selectedCondition, ConditionStatus.REMISSION)); } } if (!sSelection.isEmpty()) { manager.add(new RemoveConditionAction()); } } } } private class ToggleStatusAction extends Action { private ConditionStatus status; private ICondition condition; public ToggleStatusAction(ICondition condition, ConditionStatus status){ this.status = status; this.condition = condition; } @Override public String getText(){ return "Status " + status.getLocalized(); } @Override public void run(){ AcquireLockUi.aquireAndRun((IPersistentObject) condition, new ILockHandler() { @Override public void lockFailed(){} @Override public void lockAcquired(){ condition.setStatus(status); } }); natTableWrapper.getNatTable().refresh(); } } private class AddConditionAction extends Action { @Override public ImageDescriptor getImageDescriptor(){ return Images.IMG_NEW.getImageDescriptor(); } @Override public String getText(){ return "erstellen"; } @Override public void run(){ Patient selectedPatient = ElexisEventDispatcher.getSelectedPatient(); if (selectedPatient != null) { ConditionEditDialog dialog = new ConditionEditDialog(ConditionCategory.DIAGNOSIS, getShell()); if (dialog.open() == Dialog.OK) { dialog.getCondition().ifPresent(c -> { c.setPatientId(selectedPatient.getId()); // touch after creation CoreHub.getLocalLockService().acquireLock((IPersistentObject) c); dataList.add(c); natTableWrapper.getNatTable().refresh(); }); } } } } private class RemoveConditionAction extends Action { @Override public ImageDescriptor getImageDescriptor(){ return Images.IMG_DELETE.getImageDescriptor(); } @Override public String getText(){ return "entfernen"; } @Override public void run(){ ISelection selection = natTableWrapper.getSelection(); if (selection instanceof StructuredSelection && !selection.isEmpty()) { @SuppressWarnings("unchecked") List<ICondition> list = ((StructuredSelection) selection).toList(); list.stream().forEach(c -> { AcquireLockUi.aquireAndRun((IPersistentObject) c, new ILockHandler() { @Override public void lockFailed(){} @Override public void lockAcquired(){ FindingsServiceComponent.getService().deleteFinding(c); dataList.remove(c); natTableWrapper.getNatTable().refresh(); } }); }); } } } }