/******************************************************************************* * Copyright (c) 2007-2013, D. Lutz and Elexis. * 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: * D. Lutz - initial API and implementation * Gerry Weirich - angepasst an neues Rezeptmodell * - angepasst an neues Eventmodell * * Sponsors: * Dr. Peter Schönbucher, Luzern ******************************************************************************/ package org.iatrix.views; import java.util.List; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.DropTarget; import org.eclipse.swt.dnd.DropTargetEvent; import org.eclipse.swt.dnd.DropTargetListener; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.ISaveablePart2; import org.eclipse.ui.forms.events.HyperlinkAdapter; import org.eclipse.ui.forms.events.HyperlinkEvent; import org.eclipse.ui.forms.widgets.ExpandableComposite; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.Hyperlink; import org.eclipse.ui.forms.widgets.ScrolledForm; import org.eclipse.ui.part.ViewPart; import org.iatrix.actions.IatrixEventHelper; import org.iatrix.data.Problem; import org.iatrix.widgets.ProblemFixMediDisplay; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ch.elexis.core.data.activator.CoreHub; import ch.elexis.core.data.events.ElexisEvent; import ch.elexis.core.data.events.ElexisEventDispatcher; import ch.elexis.core.data.interfaces.IDiagnose; import ch.elexis.core.ui.UiDesk; import ch.elexis.core.ui.actions.GlobalActions; import ch.elexis.core.ui.actions.GlobalEventDispatcher; import ch.elexis.core.ui.actions.IActivationListener; import ch.elexis.core.ui.events.ElexisUiEventListenerImpl; import ch.elexis.core.ui.util.SWTHelper; import ch.elexis.core.ui.util.ViewMenus; import ch.elexis.core.ui.views.codesystems.DiagnosenView; import ch.elexis.data.Konsultation; import ch.elexis.data.Patient; import ch.elexis.data.PersistentObject; import ch.elexis.icpc.Episode; import ch.rgw.tools.ExHandler; /** * View for editing Problem properties. * * TODO When a Prescription is removed from the Patient's Prescriptions (e. g. in the * PatientDetailView), the Prescription should be removed from the Problem, too. Is there an event * available for this? * * @author danlutz */ public class ProblemView extends ViewPart implements IActivationListener, ISaveablePart2 { public static final String ID = "org.iatrix.views.ProblemView"; private static Logger log = LoggerFactory.getLogger(org.iatrix.views.JournalView.class); private Problem actProblem; private FormToolkit tk; private ScrolledForm form; private ExpandableComposite dauermedikationSection; private ProblemFixMediDisplay dlDauerMedi; private Composite diagnosenComposite; private TableViewer diagnosenViewer; private TableViewer konsultationenViewer; /* diagnosenViewer */ private IAction delDiagnoseAction; /* konsultationenViewer */ private IAction unassignProblemAction; private ViewMenus menus; private ElexisUiEventListenerImpl eeli_problem = null; private ElexisUiEventListenerImpl eeli_patient = null; private void makeListeners() { eeli_problem = new ElexisUiEventListenerImpl(Episode.class, ElexisEvent.EVENT_SELECTED | ElexisEvent.EVENT_DESELECTED | ElexisEvent.EVENT_UPDATE) { @Override public void runInUi(ElexisEvent ev){ if (ev.getType() == ElexisEvent.EVENT_SELECTED) { PersistentObject obj = ev.getObject(); if (obj instanceof Episode) { Episode episode = (Episode) obj; setProblem(Problem.convertEpisodeToProblem(episode)); } else { // not an episode object, silently ignore setProblem(null); } } else if (ev.getType() == ElexisEvent.EVENT_DESELECTED) { setProblem(null); } else if (ev.getType() == ElexisEvent.EVENT_UPDATE) { PersistentObject obj = ev.getObject(); if (obj instanceof Episode) { Episode updatedEpisode = (Episode) obj; Episode actEpisode = actProblem; if (updatedEpisode.getId().equals(actEpisode.getId())) { setProblem(actProblem); } } else { // not an episode object, silently ignore setProblem(null); } } } }; eeli_patient = new ElexisUiEventListenerImpl(Patient.class, ElexisEvent.EVENT_SELECTED | ElexisEvent.EVENT_DESELECTED) { @Override public void runInUi(ElexisEvent ev){ // make sure the current problem belongs to the newly selected patient if (ev.getType() == ElexisEvent.EVENT_SELECTED) { PersistentObject obj = ev.getObject(); if (obj instanceof Patient) { Patient selectedPatient = (Patient) obj; if (actProblem != null) { // check whether Problem matches the currently selected patient if (selectedPatient != null && !actProblem.getPatient().getId().equals(selectedPatient.getId())) { // selected patient doesn't match the current problem's patient setProblem(null); } } else { // re-select the previously selected problem // actually, this should never occur, but currently happens since // there is no responsible event manager for Episode events yet Problem previousProblem = IatrixEventHelper.getSelectedProblem(); if (selectedPatient != null && previousProblem != null && previousProblem.getPatient().getId() .equals(selectedPatient.getId())) { setProblem(previousProblem); } } } } } }; } @Override public void createPartControl(Composite parent){ parent.setLayout(new FillLayout()); Composite main = new Composite(parent, SWT.NONE); main.setLayout(new FillLayout()); tk = UiDesk.getToolkit(); form = tk.createScrolledForm(main); form.getBody().setLayout(new GridLayout(1, true)); SashForm mainSash = new SashForm(form.getBody(), SWT.VERTICAL); mainSash.setLayoutData(SWTHelper.getFillGridData(1, true, 1, true)); dauermedikationSection = tk.createExpandableComposite(mainSash, ExpandableComposite.EXPANDED | ExpandableComposite.TWISTIE); dauermedikationSection.setText("Fixmedikation"); Composite dauermedikationComposite = tk.createComposite(dauermedikationSection); dauermedikationSection.setClient(dauermedikationComposite); Composite bottomComposite = tk.createComposite(mainSash); mainSash.setWeights(new int[] { 25, 75 }); // Dauermedikation dauermedikationComposite.setLayout(new GridLayout()); // Label lDauermedikation = tk.createLabel(dauermedikationComposite, "Fixmedikation"); // lDauermedikation.setLayoutData(SWTHelper.getFillGridData(1, true, 1, false)); dlDauerMedi = new ProblemFixMediDisplay(dauermedikationComposite, getViewSite()); bottomComposite.setLayout(new GridLayout()); SashForm bottomSash = new SashForm(bottomComposite, SWT.HORIZONTAL); bottomSash.setLayoutData(SWTHelper.getFillGridData(1, true, 1, true)); diagnosenComposite = tk.createComposite(bottomSash); Composite konsultationenComposite = tk.createComposite(bottomSash); bottomSash.setWeights(new int[] { 25, 75 }); diagnosenComposite.setLayout(new GridLayout(1, true)); Hyperlink hDiagnosen = tk.createHyperlink(diagnosenComposite, "Diagnosen", SWT.NONE); hDiagnosen.setLayoutData(SWTHelper.getFillGridData(1, true, 1, false)); hDiagnosen.addHyperlinkListener(new HyperlinkAdapter() { @Override public void linkActivated(HyperlinkEvent e){ try { getViewSite().getPage().showView(DiagnosenView.ID); } catch (Exception ex) { ExHandler.handle(ex); log.error("Fehler beim Starten des Diagnosencodes " + ex.getMessage()); } } }); Table diagnosenTable = tk.createTable(diagnosenComposite, SWT.SINGLE); diagnosenTable.setLayoutData(SWTHelper.getFillGridData(1, true, 1, true)); diagnosenViewer = new TableViewer(diagnosenTable); diagnosenViewer.getControl().setLayoutData(SWTHelper.getFillGridData(1, true, 1, true)); diagnosenViewer.setContentProvider(new IStructuredContentProvider() { @Override public Object[] getElements(Object inputElement){ if (actProblem != null) { List<IDiagnose> diagnosen = actProblem.getDiagnosen(); return diagnosen.toArray(); } return new Object[0]; } @Override public void dispose(){ // nothing to do } @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput){ // nothing to do } }); diagnosenViewer.setLabelProvider(new LabelProvider() { @Override public String getText(Object element){ if (!(element instanceof IDiagnose)) { return ""; } IDiagnose diagnose = (IDiagnose) element; return diagnose.getLabel(); } }); diagnosenViewer.setInput(this); konsultationenComposite.setLayout(new GridLayout(1, true)); Label lKonsultationen = tk.createLabel(konsultationenComposite, "Konsultationen", SWT.LEFT); lKonsultationen.setLayoutData(SWTHelper.getFillGridData(1, true, 1, false)); Table konsultationenTable = tk.createTable(konsultationenComposite, SWT.SINGLE); konsultationenTable.setLayoutData(SWTHelper.getFillGridData(1, true, 1, true)); konsultationenViewer = new TableViewer(konsultationenTable); konsultationenViewer.getControl() .setLayoutData(SWTHelper.getFillGridData(1, true, 1, true)); konsultationenViewer.setContentProvider(new IStructuredContentProvider() { @Override public Object[] getElements(Object inputElement){ if (actProblem != null) { List<Konsultation> konsultationen = actProblem.getKonsultationen(); return konsultationen.toArray(); } return new Object[0]; } @Override public void dispose(){ // nothing to do } @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput){ // nothing to do } }); konsultationenViewer.setLabelProvider(new LabelProvider() { @Override public String getText(Object element){ if (!(element instanceof Konsultation)) { return ""; } Konsultation konsultation = (Konsultation) element; return konsultation.getLabel(); } }); konsultationenViewer.setInput(this); /* Implementation Drag&Drop */ final TextTransfer textTransfer = TextTransfer.getInstance(); Transfer[] types = new Transfer[] { textTransfer }; // diagnosenComposite DropTarget dtarget = new DropTarget(diagnosenComposite, DND.DROP_COPY); dtarget.setTransfer(types); dtarget.addDropListener(new DropTargetListener() { @Override public void dragEnter(DropTargetEvent event){ /* Wir machen nur Copy-Operationen */ event.detail = DND.DROP_COPY; } /* Mausbewegungen mit gedrückter Taste sind uns egal */ @Override public void dragLeave(DropTargetEvent event){ /* leer */ } @Override public void dragOperationChanged(DropTargetEvent event){ /* leer */ } @Override public void dragOver(DropTargetEvent event){ /* leer */ } /* Erst das Loslassen interessiert uns wieder */ @Override public void drop(DropTargetEvent event){ String drp = (String) event.data; String[] dl = drp.split(","); for (String obj : dl) { PersistentObject dropped = CoreHub.poFactory.createFromString(obj); if (dropped instanceof IDiagnose) { IDiagnose diagnose = (IDiagnose) dropped; actProblem.addDiagnose(diagnose); // tell other viewers that something has changed IatrixEventHelper.updateProblem(actProblem); // update ourselves // TODO: implement ObjectListener diagnosenViewer.refresh(); } } } @Override public void dropAccept(DropTargetEvent event){ /* leer */ } }); makeListeners(); makeActions(); menus = new ViewMenus(getViewSite()); menus.createViewerContextMenu(diagnosenViewer, delDiagnoseAction); menus.createViewerContextMenu(konsultationenViewer, unassignProblemAction); GlobalEventDispatcher.addActivationListener(this, this); } @Override public void setFocus(){ } /* * (non-Javadoc) * * @see org.eclipse.ui.part.WorkbenchPart#dispose() */ @Override public void dispose(){ GlobalEventDispatcher.removeActivationListener(this, this); super.dispose(); } private void makeActions(){ // Diagnosen delDiagnoseAction = new Action("Diagnose entfernen") { @Override public void run(){ Object sel = ((IStructuredSelection) diagnosenViewer.getSelection()).getFirstElement(); if (sel != null && actProblem != null) { IDiagnose diagnose = (IDiagnose) sel; actProblem.removeDiagnose(diagnose); // TODO Diagnosen von Konsultationen entfernen diagnosenViewer.refresh(); // tell other viewers that something has changed IatrixEventHelper.updateProblem(actProblem); } } }; // Konsultationen unassignProblemAction = new Action("Problem entfernen") { { setToolTipText("Problem von Konsulation entfernen"); } @Override public void run(){ Object sel = ((IStructuredSelection) konsultationenViewer.getSelection()).getFirstElement(); if (sel != null && actProblem != null) { Konsultation konsultation = (Konsultation) sel; // remove problem. ask user if encounter still contains data. IatrixViewTool.removeProblemFromKonsultation(konsultation, actProblem); konsultationenViewer.refresh(); // tell other viewers that something has changed IatrixEventHelper.updateProblem(actProblem); } } }; } @Override public void activation(boolean mode){ // do nothing } @Override public void visible(boolean mode){ if (mode == true) { Problem problem = IatrixEventHelper.getSelectedProblem(); if (problem != null) { // check whether Problem matches the currently selected patient Patient selectedPatient = ElexisEventDispatcher.getSelectedPatient(); if (selectedPatient != null && problem.getPatient().getId().equals(selectedPatient.getId())) { setProblem(problem); } else { setProblem(null); } } else { setProblem(null); } ElexisEventDispatcher.getInstance().addListeners(eeli_problem, eeli_patient); } else { ElexisEventDispatcher.getInstance().removeListeners(eeli_problem, eeli_patient); } } /* * Die folgenden 6 Methoden implementieren das Interface ISaveablePart2 Wir benötigen das * Interface nur, um das Schliessen einer View zu verhindern, wenn die Perspektive fixiert ist. * Gibt es da keine einfachere Methode? */ @Override public int promptToSaveOnClose(){ return GlobalActions.fixLayoutAction.isChecked() ? ISaveablePart2.CANCEL : ISaveablePart2.NO; } @Override public void doSave(IProgressMonitor monitor){ /* leer */} @Override public void doSaveAs(){ /* leer */} @Override public boolean isDirty(){ return true; } @Override public boolean isSaveAsAllowed(){ return false; } @Override public boolean isSaveOnCloseNeeded(){ return true; } private void setProblem(Problem problem){ actProblem = problem; if (actProblem != null) { form.setText( "Problem " + problem.getLabel() + " von " + problem.getPatient().getLabel()); } else { form.setText("Kein Problem ausgewählt"); } diagnosenViewer.refresh(); konsultationenViewer.refresh(); // Fixmedikation // TODO work-around // we need to call "reload" two times to make the list expand // unknown why this is required dlDauerMedi.reload(); dlDauerMedi.reload(); dauermedikationSection.layout(true); form.reflow(true); } // FocusListener fuer Felder class Focusreact extends FocusAdapter { private final String field; Focusreact(String f){ field = f; } @Override public void focusLost(FocusEvent e){ if (actProblem == null) { return; } String oldvalue = actProblem.get(field); String newvalue = ((Text) e.getSource()).getText(); if (oldvalue != null) { if (oldvalue.equals(newvalue)) { return; } } if (newvalue != null) { actProblem.set(field, newvalue); } } } }