package com.hilotec.elexis.kgview.diagnoseliste; import java.io.ByteArrayInputStream; import java.util.ArrayList; import java.util.List; import java.util.Stack; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.TitleAreaDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.custom.TreeEditor; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.DropTargetEvent; import org.eclipse.swt.dnd.HTMLTransfer; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.ui.part.ViewPart; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; import ch.elexis.core.data.events.ElexisEvent; import ch.elexis.core.data.events.ElexisEventDispatcher; import ch.elexis.core.data.events.ElexisEventListener; import ch.elexis.core.ui.UiDesk; import ch.elexis.core.ui.icons.Images; import ch.elexis.core.ui.util.PersistentObjectDragSource; import ch.elexis.core.ui.util.PersistentObjectDropTarget; import ch.elexis.core.ui.util.SWTHelper; import ch.elexis.core.ui.util.ViewMenus; import ch.elexis.data.Patient; import ch.elexis.data.PersistentObject; import ch.elexis.icpc.IcpcCode; import ch.rgw.tools.StringTool; import com.hilotec.elexis.kgview.data.KonsData; /* * Helper class to draw multiline tree items, kind of ugly, but according * to the eclipse forum there is no other way at the moment. * * Derived From: http://git.eclipse.org/c/platform/ * + eclipse.platform.swt.git/tree/examples/org.eclipse.swt.snippets/ * + src/org/eclipse/swt/snippets/Snippet227.java * Copyright (c) 2000, 2006 IBM Corporation and others (EPL) */ class MultilinePaintListener implements Listener { public void handleEvent(Event event){ switch (event.type) { case SWT.MeasureItem: { TreeItem item = (TreeItem) event.item; String text = getText(item, event.index); Point size = event.gc.textExtent(text); event.width = size.x; event.height = Math.max(event.height, size.y); break; } case SWT.PaintItem: { TreeItem item = (TreeItem) event.item; String text = getText(item, event.index); Point size = event.gc.textExtent(text); int offset2 = event.index == 0 ? Math.max(0, (event.height - size.y) / 2) : 0; event.gc.drawText(text, event.x, event.y + offset2, true); break; } case SWT.EraseItem: { event.detail &= ~SWT.FOREGROUND; break; } } } String getText(TreeItem item, int column){ String text = item.getText(column); /* * if (column != 0) { TreeItem parent = item.getParentItem(); int index = parent == null ? * tree.indexOf(item) : parent.indexOf(item); if ((index+column) % 3 == 1){ text * +="\nnew line"; } if ((index+column) % 3 == 2) { text +="\nnew line\nnew line"; } } */ return text; } } /** * Nicht-persistente Representation eines Diagnosebaums. */ class DNode { public String text = ""; public ArrayList<DNode> children = new ArrayList<DNode>(); /** * Neues Kindelement erstellen. */ public DNode newChild(){ DNode dn = new DNode(); children.add(dn); return dn; } /** * Text an diesen Knoten anhaengen */ public void append(String s){ text += s; } /** * Text aufgeraeumt zurueckgeben */ public String getClean(){ return text.trim().replaceAll("[ \t]+", " ").replaceAll("\n+", "\n"); } /** * Unter-Nodes in DiagnoselisteItem persistent abspeichern */ public void storeChildren(DiagnoselisteItem it){ for (DNode c : children) { DiagnoselisteItem ci = it.createChild(); ci.setText(c.getClean()); c.storeChildren(ci); } } } /** * Dialog zum anzeigen eines Baums aus DNodes. */ class DLDialog extends TitleAreaDialog { private DNode di; private Tree tree; public DLDialog(Shell parentShell, DNode di){ super(parentShell); this.di = di; } @Override protected Control createDialogArea(Composite parent){ ScrolledComposite scroll = new ScrolledComposite(parent, SWT.BORDER | SWT.V_SCROLL); Composite comp = new Composite(scroll, SWT.NONE); scroll.setLayoutData(SWTHelper.getFillGridData(1, true, 1, true)); scroll.setContent(comp); comp.setLayout(new GridLayout()); comp.setLayoutData(SWTHelper.getFillGridData(1, true, 1, false)); tree = new Tree(comp, SWT.NONE); tree.setLayoutData(SWTHelper.getFillGridData(1, true, 1, false)); final TreeEditor editor = new TreeEditor(tree); editor.grabHorizontal = true; editor.grabVertical = true; MultilinePaintListener mlListener = new MultilinePaintListener(); tree.addListener(SWT.MeasureItem, mlListener); tree.addListener(SWT.PaintItem, mlListener); tree.addListener(SWT.EraseItem, mlListener); addNodes(di, null); comp.setSize(comp.computeSize(SWT.DEFAULT, SWT.DEFAULT)); return scroll; } private void addNodes(DNode dn, TreeItem parent){ TreeItem ti; for (DNode n : dn.children) { if (parent == null) ti = new TreeItem(tree, 0); else ti = new TreeItem(parent, 0); ti.setText(n.getClean()); addNodes(n, ti); ti.setExpanded(true); } } @Override public void create(){ super.create(); getShell().setText("Diagnosen Importieren"); } @Override protected void okPressed(){ close(); } } /** * Parser um copy&paste-Daten aus OpenOffice zu uebernehmen. Sehr hacky. */ class DLParser { /** * Versucht den String in eine DNode-Repraesentation zu parsen */ public DNode parse(String html){ DNode dn = parseItems(html); if (dn == null) { dn = parseManualList(html); } System.out.println(dn); if (dn != null) { for (DNode c : dn.children) { System.out.println(c.text); } } return dn; } /** * Root Element fuer XML Dokument geparst aus code holen */ private Element parseXML(String code){ try { byte[] bytes = code.getBytes(); DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); dbFactory.setValidating(false); dbFactory.setNamespaceAware(true); dbFactory.setIgnoringComments(false); dbFactory.setIgnoringElementContentWhitespace(false); dbFactory.setExpandEntityReferences(false); DocumentBuilder dBuilder; dBuilder = dbFactory.newDocumentBuilder(); Document doc = dBuilder.parse(new ByteArrayInputStream(bytes)); return doc.getDocumentElement(); } catch (Exception e) { e.printStackTrace(); return null; } } /** * HTML UL-Aufzaehlungsliste parsen */ private DNode parseItems(String html){ System.out.println("{{" + html + "}}"); Element e = parseXML(html); if (e == null) return null; DNode dn = new DNode(); parseUL(e, dn); return dn; } /** * Konkretes UL-Element parsen, indirekt rekursiv. Dabei wird dn benutzt um die entstehenden * Kindknoten einzutragen. */ private void parseUL(Element e, DNode dn){ if (!e.getNodeName().equals("ul")) return; NodeList nl = e.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node n = nl.item(i); if (n instanceof Element && n.getNodeName().equals("li")) { Element li = (Element) n; li.normalize(); parseLI(li, dn.newChild()); } } } /** * Einzelnes LI-Element einer UL-Liste parsen, rekursiv. Der Text und allfaellige Kindknoten * werden in dn eingetragen. */ private void parseLI(Element li, DNode dn){ NodeList nl = li.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node n = nl.item(i); if (n instanceof Element) { Element e = (Element) n; e.normalize(); if (e.getNodeName().equals("ul")) { parseUL(e, dn); } else if (e.getNodeName().equals("br")) { dn.append("\n"); } else if (e.getNodeName().equals("p")) { dn.append("\n"); parseLI(e, dn); dn.append("\n"); } else { parseLI(e, dn); } } else if (n instanceof Text) { Text t = (Text) n; dn.append(t.getTextContent().trim()); } } } /** * Parsen der manuell erstellten Aufzaehlungslisten (mit - und tabulatoren) Gar nicht allgemein. */ private DNode parseManualList(String html){ try { // Versuchen html in gueltiges XML umzuwandeln String enc = "utf-8"; if (System.getProperty("os.name").startsWith("Windows")) enc = "iso-8859-1"; html = "<?xml version=\"1.0\" encoding=\"" + enc + "\"?>" + "<root>\n" + html + "\n</root>"; html = html.replaceAll("<br>", "<br/>"); html = html.replaceAll("<BR>", "<br/>"); html = html.replaceAll("ALIGN=JUSTIFY", ""); html = html.replaceAll("­", "-"); System.out.println("Cleaned xml:\n{{" + html + "}}"); // Parsen Element root = parseXML(html); NodeList nl = root.getChildNodes(); Stack<DNode> stack = new Stack<DNode>(); stack.push(new DNode()); for (int i = 0; i < nl.getLength(); i++) { Node n = nl.item(i); if (!(n instanceof Element)) continue; Element e = (Element) n; // Wir wollen nur P-elemente String txt = e.getTextContent(); if (!e.getNodeName().equalsIgnoreCase("p") || !txt.startsWith("-")) { throw new Exception("Nicht p-Element"); } // Pruefen ob das class-Attribut mit list-n- anfaengt String c = e.getAttribute("class"); if (c.isEmpty()) c = e.getAttribute("CLASS"); c = c.toLowerCase(); if (!c.matches("liste?-[0-9]-.*")) { throw new Exception("p-Element ohne passende class"); } // level Zahl aus class parsen int lvl = Integer.parseInt(c.replaceAll("^liste?-", "").substring(0, 1)); while (stack.size() > lvl) stack.pop(); if (stack.size() < lvl) { throw new Exception("Stack underflow beim parsen"); } // Knoten erstellen DNode dn = stack.peek().newChild(); parseManualP(dn, e); // Text etwas aufraeumen dn.text = dn.text.substring(1).replaceAll("[ \t\n\r]+", " "); dn.text = dn.text.trim(); stack.push(dn); } while (stack.size() > 1) stack.pop(); return stack.pop(); } catch (Exception e) { e.printStackTrace(); return null; } } /** * Text aus P-Element in manuell erstellter Liste parsen * * @throws Exception */ private void parseManualP(DNode dn, Element e) throws Exception{ e.normalize(); NodeList nl = e.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node n = nl.item(i); if (n instanceof Text) { dn.append(n.getNodeValue()); } else if (n instanceof Element && n.getNodeName().equalsIgnoreCase("br")) { dn.append("\n"); } else { throw new Exception("Ungueltigen Node angetroffen: {" + n.getNodeName() + "}"); } } } } public abstract class DiagnoselisteBaseView extends ViewPart implements ElexisEventListener { /** Typ der anzuzeigenden items */ protected final int typ; /** Sollen neue eintraege erstellt werden koenenn? */ protected boolean canAdd = true; /** Sollen alle Eintraege geloescht werden koennen? */ protected boolean canClear = false; /** Soll das Datum bei Eintraegen angezeigt werden? */ protected boolean showDate = true; /** Koennen Eintraege anderes Typs importiert werden (SA, PA) */ protected boolean allowImport = false; /** Koennen Eintraege aus der Diagnoseliste importiert werden (uebergang) */ protected boolean allowImportDL = true; /** Koennen Eintraege aus der Zwischenablage importiert werden? */ protected boolean allowImportCB = true; /** Koennen ICPC-Eintraege hinterlegt/angezeigt werden? */ protected boolean allowICPC = true; private Tree tree; Action actAdd; Action actEdit; Action actAddChild; Action actDel; Action actDelICPC; Action actClear; Action actMoveUp; Action actMoveDown; Action actImportPA; Action actImportSA; Action actImportDL; Action actImportCB; /** * Diagnoseliste Anzeige fuer Items eines bestimmten Typs initialisieren. * * @param typ * Typ der anzuzeigenden Elemente */ public DiagnoselisteBaseView(int typ){ super(); this.typ = typ; } private void setupTI(TreeItem ti, DiagnoselisteItem di){ String text = di.getText(); if (showDate) text += " (" + di.getDatum() + ")"; if (allowICPC) { text = "[" + di.getICPC() + "] " + text; } ti.setText(text); ti.setData(di); } /** * Neues TreeItem für die übergebene Diagnose am angegebenen Index erstellen. */ private TreeItem createTI(DiagnoselisteItem di, TreeItem tip, int index){ TreeItem ti; if (tip == null) ti = new TreeItem(tree, SWT.NONE, index); else ti = new TreeItem(tip, SWT.NONE, index); setupTI(ti, di); return ti; } private void insertSubtree(DiagnoselisteItem dip, TreeItem tip){ TreeItem ti; for (DiagnoselisteItem di : dip.getChildren()) { ti = createTI(di, tip, di.getPosition()); insertSubtree(di, ti); } } private void updateTree(){ updateTree(ElexisEventDispatcher.getSelectedPatient()); } private void updateTree(Patient pat){ tree.removeAll(); boolean en = (pat != null); actAdd.setEnabled(en && canAdd); actAddChild.setEnabled(en && canAdd); actEdit.setEnabled(en); actDel.setEnabled(en); actDelICPC.setEnabled(en && allowICPC); actMoveUp.setEnabled(en); actMoveDown.setEnabled(en); actImportPA.setEnabled(en && allowImport); actImportSA.setEnabled(en && allowImport); actImportDL.setEnabled(en && allowImportDL); actImportCB.setEnabled(en && allowImportCB); actClear.setEnabled(en && canClear); if (pat == null) return; insertSubtree(DiagnoselisteItem.getRoot(pat, typ), null); } /** * Root-Item eines bestimmten Typs fuer den aktuellen Patienten suchen */ private static DiagnoselisteItem getRoot(int typ){ Patient pat = ElexisEventDispatcher.getSelectedPatient(); return DiagnoselisteItem.getRoot(pat, typ); } @Override public void createPartControl(Composite parent){ tree = new Tree(parent, SWT.NONE); final TreeEditor editor = new TreeEditor(tree); editor.horizontalAlignment = SWT.LEFT; editor.grabHorizontal = true; // SelectionListener um Eintraege inline bearbeiten zu koennen. /* * tree.addSelectionListener(new SelectionListener() { public void * widgetDefaultSelected(SelectionEvent e) { } public void widgetSelected(SelectionEvent e) * { TreeItem diagItem = (TreeItem) e.item; if (diagItem == null) return; * * Control old = editor.getEditor(); if (old != null) old.dispose(); * * Text diagEditor = new Text(tree, SWT.MULTI | SWT.WRAP); diagEditor.setData(diagItem); * diagEditor.setText(diagItem.getText()); * * // ModifyListener um Aenderungen zu speichern diagEditor.addModifyListener(new * ModifyListener() { public void modifyText(ModifyEvent e) { Text te = (Text) e.widget; * TreeItem ti = (TreeItem) te.getData(); DiagnoselisteItem di = (DiagnoselisteItem) * ti.getData(); ti.setText(te.getText()); di.setText(te.getText()); } }); * //diagEditor.selectAll(); diagEditor.setFocus(); editor.setEditor(diagEditor, diagItem); * } }); */ MultilinePaintListener mlListener = new MultilinePaintListener(); tree.addListener(SWT.MeasureItem, mlListener); tree.addListener(SWT.PaintItem, mlListener); tree.addListener(SWT.EraseItem, mlListener); // Drop Target um neue Eintraege zu erstellen new PersistentObjectDropTarget(tree, new PersistentObjectDropTarget.IReceiver() { @Override public void dropped(PersistentObject o, DropTargetEvent e){ // Ausgewaehltes Element suchen TreeItem selTi = tree.getItem(tree.toControl(e.x, e.y)); DiagnoselisteItem it = null; if (selTi != null) it = (DiagnoselisteItem) selTi.getData(); else it = getRoot(typ); if (o instanceof IcpcCode && selTi != null) { // ICPC2 code IcpcCode i = (IcpcCode) o; it.setICPC(i.getCode()); setupTI(selTi, it); } else if (o instanceof KonsData) { // Eintrag aus Problemliste KonsData kd = (KonsData) o; DiagnoselisteItem di = it.createChild(); di.setText(kd.getDiagnose()); di.setDatum(kd.getKonsultation().getDatum()); createTI(di, selTi, di.getPosition()); } else if (o instanceof DiagnoselisteItem) { // Eintrag aus Diagnoseliste DiagnoselisteItem d = (DiagnoselisteItem) o; if (d.getTyp() != typ) { // Aus anderer DL View importItemTo(d, it); } else { // Innerhalb selber DL View DiagnoselisteItem par = d.getParent(); if (par == null) return; // Aufpassen dass wir keine Zyklen einfuehren if (it.isDescendantOf(d)) return; par.removeChild(d); if (!par.equals(it)) { d.setPosition(it.nextChildPos()); d.setParent(it); } } updateTree(); } } @Override public boolean accept(PersistentObject o){ if (o instanceof IcpcCode) return allowICPC; if (o instanceof KonsData) return true; if (!(o instanceof DiagnoselisteItem)) return false; DiagnoselisteItem d = (DiagnoselisteItem) o; // Pruefen ob der Typ importiert werden kann int t = d.getTyp(); if (t == DiagnoselisteItem.TYP_DIAGNOSELISTE && allowImportDL) return true; else if (allowImport && (t == DiagnoselisteItem.TYP_PERSANAMNESE || t == DiagnoselisteItem.TYP_SYSANAMNESE)) return true; else if (typ == t) return true; return false; } }); new PersistentObjectDragSource(tree, new PersistentObjectDragSource.ISelectionRenderer() { public List<PersistentObject> getSelection(){ TreeItem[] tis = tree.getSelection(); if (tis == null) return null; ArrayList<PersistentObject> res = new ArrayList<PersistentObject>(tis.length); // Auswahl in Liste von Items umwandeln for (TreeItem ti : tis) { DiagnoselisteItem di = (DiagnoselisteItem) ti.getData(); res.add(di); } return res; } }); makeActions(); tree.addMouseListener(new MouseListener() { public void mouseUp(MouseEvent e){} public void mouseDown(MouseEvent e){} public void mouseDoubleClick(MouseEvent e){ actEdit.run(); } }); tree.addKeyListener(new KeyListener() { public void keyReleased(KeyEvent e){} public void keyPressed(KeyEvent e){ if (e.keyCode != SWT.DEL) return; if (actDel.isEnabled()) actDel.run(); } }); // Menus oben rechts in der View ViewMenus menus = new ViewMenus(getViewSite()); ArrayList<IAction> m = new ArrayList<IAction>(5); IAction[] a = new IAction[1]; // Toolbar zusammenstellen if (canAdd) m.add(actAdd); m.add(actMoveUp); m.add(actMoveDown); menus.createToolbar(m.toArray(a)); m.clear(); // View-Menu zusammenstellen if (allowImport) m.add(actImportPA); if (allowImport) m.add(actImportSA); if (allowImportDL) m.add(actImportDL); if (allowImportCB) m.add(actImportCB); if (canClear) m.add(actClear); menus.createMenu(m.toArray(a)); m.clear(); // Context menu if (canAdd) m.add(actAddChild); m.add(actDel); if (allowICPC) m.add(actDelICPC); menus.createControlContextMenu(tree, m.toArray(a)); ElexisEventDispatcher.getInstance().addListeners(this); updateTree(); } /** * Importiert alle Kind-Items von sp nach dp. */ private void importFrom(DiagnoselisteItem sp, DiagnoselisteItem dp){ for (DiagnoselisteItem si : sp.getChildren()) { importItemTo(si, dp); } } /** * Importiert item als Kind-Item in newParent item falls es noch nicht enthalten ist. Sonst * werden nur die Unterelemente rekursiv eingefuegt. * * @param item * Quell-Item * @param newParent * Neues Ziel-Parent Item */ private void importItemTo(DiagnoselisteItem item, DiagnoselisteItem newParent){ DiagnoselisteItem di = newParent.getBySrc(item); if (di == null) { di = newParent.createChildFrom(item); } // Rekursiv Kind-Item behandeln importFrom(item, di); } /** * Action zum Importieren aus Views eines anderen Typs. */ private class ImportAction extends Action { int fromTyp; public ImportAction(int typ){ super(); if (typ == DiagnoselisteItem.TYP_PERSANAMNESE) { setText("Import Pers. Anamnese"); } else if (typ == DiagnoselisteItem.TYP_SYSANAMNESE) { setText("Import Systemanamnese"); } else if (typ == DiagnoselisteItem.TYP_DIAGNOSELISTE) { setText("Import Diagnoseliste"); } setImageDescriptor(Images.IMG_IMPORT.getImageDescriptor()); fromTyp = typ; } @Override public void run(){ Patient pat = ElexisEventDispatcher.getSelectedPatient(); importFrom(DiagnoselisteItem.getRoot(pat, fromTyp), DiagnoselisteItem.getRoot(pat, typ)); updateTree(pat); } } private void makeActions(){ actEdit = new Action("Bearbeiten") { { setImageDescriptor(Images.IMG_EDIT.getImageDescriptor()); } @Override public void run(){ if (tree.getSelectionCount() == 0) return; TreeItem ti = tree.getSelection()[0]; DiagnoselisteItem di = (DiagnoselisteItem) ti.getData(); (new DiagnoseDialog(getSite().getShell(), di, showDate, allowICPC)).open(); setupTI(ti, di); } }; actAdd = new Action("Neue Kategorie") { { setImageDescriptor(Images.IMG_NEW.getImageDescriptor()); } @Override public void run(){ Patient p = ElexisEventDispatcher.getSelectedPatient(); DiagnoselisteItem root = DiagnoselisteItem.getRoot(p, typ); DiagnoselisteItem di = root.createChild(); (new DiagnoseDialog(getSite().getShell(), di, showDate, false)).open(); createTI(di, null, di.getPosition()); } }; actAddChild = new Action("Neue Unterdiagnose") { { setImageDescriptor(Images.IMG_ADDITEM.getImageDescriptor()); } @Override public void run(){ TreeItem[] tis = tree.getSelection(); if (tis.length > 0) { DiagnoselisteItem di = (DiagnoselisteItem) tis[0].getData(); DiagnoselisteItem ndi = di.createChild(); DiagnoseDialog dd = new DiagnoseDialog(getSite().getShell(), ndi, showDate, false); if (dd.open() == DiagnoseDialog.OK) { createTI(ndi, tis[0], ndi.getPosition()); // Parent expanden tis[0].setExpanded(true); } else { ndi.delete(); } } } }; actDel = new Action("Löschen") { { setImageDescriptor(Images.IMG_DELETE.getImageDescriptor()); } @Override public void run(){ TreeItem[] tis = tree.getSelection(); if (tis.length > 0) { DiagnoselisteItem di = (DiagnoselisteItem) tis[0].getData(); if (!di.getChildren().isEmpty()) { SWTHelper.alert("Es existieren noch Unterdiagnosen", "Bitte zuerst alle Unterdiagnosen der zu löschenden" + " Diagnose entfernen."); return; } if (!SWTHelper.askYesNo("Löschen", "Soll die ausgewählte " + "Diagnose unwiderrufbar gelöscht werden?")) return; di.delete(); tis[0].dispose(); } } }; actDelICPC = new Action("ICPC Code löschen") { { setImageDescriptor(Images.IMG_REMOVEITEM.getImageDescriptor()); } @Override public void run(){ TreeItem[] tis = tree.getSelection(); if (tis.length != 1) return; DiagnoselisteItem di = (DiagnoselisteItem) tis[0].getData(); if (StringTool.isNothing(di.getICPC())) return; di.setICPC(""); setupTI(tis[0], di); } }; actClear = new Action("Alle Löschen") { @Override public void run(){ if (SWTHelper.askYesNo("Alle Eintraege loeschen", "Sollen alle Eintraege unweiderruflich gelöscht werden?")) { Patient pat = ElexisEventDispatcher.getSelectedPatient(); DiagnoselisteItem.getRoot(pat, typ).deleteChildren(); updateTree(); } } }; actMoveUp = new Action("Hoch") { { setImageDescriptor(Images.IMG_ARROWUP.getImageDescriptor()); } @Override public void run(){ TreeItem[] tis = tree.getSelection(); if (tis.length > 0) { DiagnoselisteItem di = (DiagnoselisteItem) tis[0].getData(); di.moveUp(); TreeItem parent = tis[0].getParentItem(); tis[0].dispose(); // Item neu erstellen an neuer Position TreeItem ti = createTI(di, parent, di.getPosition()); insertSubtree(di, ti); tree.select(ti); } } }; actMoveDown = new Action("Runter") { { setImageDescriptor(Images.IMG_ARROWDOWN.getImageDescriptor()); } @Override public void run(){ TreeItem[] tis = tree.getSelection(); if (tis.length > 0) { DiagnoselisteItem di = (DiagnoselisteItem) tis[0].getData(); di.moveDown(); TreeItem parent = tis[0].getParentItem(); tis[0].dispose(); // Item neu erstellen an neuer Position TreeItem ti = createTI(di, parent, di.getPosition()); insertSubtree(di, ti); tree.select(ti); } } }; actImportPA = new ImportAction(DiagnoselisteItem.TYP_PERSANAMNESE); actImportSA = new ImportAction(DiagnoselisteItem.TYP_SYSANAMNESE); actImportDL = new ImportAction(DiagnoselisteItem.TYP_DIAGNOSELISTE); actImportCB = new Action("Import Zwischenablage") { { setImageDescriptor(Images.IMG_IMPORT.getImageDescriptor()); setToolTipText("Aus Zwischenablage importieren"); setDescription("Sollen die Diagnosen wie unten angegeben " + "importiert werden?"); } @Override public void run(){ // Daten aus Zwischenablage holen Clipboard cb = new Clipboard(UiDesk.getDisplay()); String s = (String) cb.getContents(HTMLTransfer.getInstance()); if (s == null) return; // Wurzel des Diagnosebaums holen Patient p = ElexisEventDispatcher.getSelectedPatient(); DiagnoselisteItem root = DiagnoselisteItem.getRoot(p, typ); // Daten parsen DNode dn = new DLParser().parse(s); if (dn == null) return; DLDialog di = new DLDialog(UiDesk.getTopShell(), dn); if (di.open() == DLDialog.OK) { dn.storeChildren(root); updateTree(p); } } }; } @Override public void setFocus(){} @Override public void dispose(){ ElexisEventDispatcher.getInstance().removeListeners(this); super.dispose(); } public void catchElexisEvent(final ElexisEvent ev){ UiDesk.syncExec(new Runnable() { public void run(){ if (ev.getType() == ElexisEvent.EVENT_SELECTED) { updateTree((Patient) ev.getObject()); } } }); } private final ElexisEvent eetmpl = new ElexisEvent(null, Patient.class, ElexisEvent.EVENT_SELECTED); public ElexisEvent getElexisEventFilter(){ return eetmpl; } }