ch.elexis.core.ui.contacts.views.ContactSelectorView.java Source code

Java tutorial

Introduction

Here is the source code for ch.elexis.core.ui.contacts.views.ContactSelectorView.java

Source

/*******************************************************************************
 * Copyright (c) 2014 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.ui.contacts.views;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.jexl2.Expression;
import org.apache.commons.jexl2.JexlEngine;
import org.apache.commons.jexl2.JexlException;
import org.apache.commons.jexl2.MapContext;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.beans.BeansObservables;
import org.eclipse.core.databinding.observable.list.WritableList;
import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
import org.eclipse.jface.viewers.ILabelDecorator;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
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.IWorkbenchActionConstants;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.views.properties.IPropertySheetPage;
import org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;

import ch.elexis.core.data.beans.ContactBeanFactory;
import ch.elexis.core.data.events.ElexisEventDispatcher;
import ch.elexis.core.model.IContact;
import ch.elexis.core.ui.contacts.views.comparator.ContactSelectorViewerComparator;
import ch.elexis.core.ui.contacts.views.dnd.ContactSelectorDragListener;
import ch.elexis.core.ui.contacts.views.dnd.ContactSelectorDropListener;
import ch.elexis.core.ui.contacts.views.filter.KontaktAnzeigeTextFieldViewerFilter;
import ch.elexis.core.ui.contacts.views.filter.KontaktAnzeigeTypViewerFilter;
import ch.elexis.core.ui.contacts.views.provider.ContactSelectorObservableMapLabelProvider;
import ch.elexis.core.ui.contacts.views.provider.TableDecoratingLabelProvider;
import ch.elexis.data.Kontakt;
import ch.elexis.data.Patient;
import ch.elexis.data.Person;
import ch.elexis.data.Query;

/**
 * @since 3.0.0
 */
public class ContactSelectorView extends ViewPart implements ITabbedPropertySheetPageContributor {

    public static final String ID = "ch.elexis.core.ui.contacts.views.ContactSelectorView";

    private ObservableListContentProvider contentProvider = null;

    private TableViewer tableViewerContacts;
    private WritableList contactList;

    private Text txtFilter;
    private KontaktAnzeigeTypViewerFilter filterAnzeigeTyp;
    private KontaktAnzeigeTextFieldViewerFilter filterPositionTitle;
    private LoadContactsRunnable loadContactsRunnable;

    private Label lblStatus;

    public ContactSelectorView() {
        contactList = new WritableList();
        contentProvider = new ObservableListContentProvider();
        filterPositionTitle = new KontaktAnzeigeTextFieldViewerFilter();
        loadContactsRunnable = new LoadContactsRunnable();
    }

    @Override
    public void createPartControl(Composite parent) {
        Composite composite = new Composite(parent, SWT.NONE);
        composite.setLayout(new GridLayout(1, false));

        Composite compositeSearch = new Composite(composite, SWT.NONE);
        compositeSearch.setLayout(new GridLayout(1, false));
        compositeSearch.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));

        txtFilter = new Text(compositeSearch, SWT.BORDER | SWT.SEARCH | SWT.CANCEL);
        txtFilter.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));

        tableViewerContacts = new TableViewer(composite, SWT.BORDER | SWT.FULL_SELECTION);
        Table table = tableViewerContacts.getTable();
        table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));

        Composite compositeStatus = new Composite(composite, SWT.NONE);
        compositeStatus.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
        compositeStatus.setLayout(new GridLayout(1, false));

        lblStatus = new Label(compositeStatus, SWT.NONE);
        lblStatus.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));

        tableViewerContacts.setComparator(new ContactSelectorViewerComparator(tableViewerContacts));
        filterAnzeigeTyp = new KontaktAnzeigeTypViewerFilter(tableViewerContacts);
        ViewerFilter[] filters = new ViewerFilter[] { filterAnzeigeTyp, filterPositionTitle };
        tableViewerContacts.setFilters(filters);

        int operations = DND.DROP_COPY | DND.DROP_MOVE;
        Transfer[] transferTypes = new Transfer[] { TextTransfer.getInstance() };
        tableViewerContacts.addDragSupport(operations, transferTypes,
                new ContactSelectorDragListener(tableViewerContacts));
        tableViewerContacts.addDropSupport(operations, transferTypes,
                new ContactSelectorDropListener(tableViewerContacts));

        txtFilter.addKeyListener(new FilterKeyListener(txtFilter, tableViewerContacts));
        txtFilter.addSelectionListener(new SelectionAdapter() {
            public void widgetDefaultSelected(SelectionEvent e) {
                if (e.detail == SWT.CANCEL) {
                    filterPositionTitle.setSearchText(null);
                    tableViewerContacts.getControl().setRedraw(false);
                    tableViewerContacts.refresh();
                    tableViewerContacts.getControl().setRedraw(true);
                }
            }
        });

        initDataBindings();

        MenuManager menuManager = new MenuManager();
        menuManager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
        tableViewerContacts.getTable().setMenu(menuManager.createContextMenu(tableViewerContacts.getTable()));

        getSite().registerContextMenu(menuManager, tableViewerContacts);
        getSite().setSelectionProvider(tableViewerContacts);

        contactList.getRealm().asyncExec(loadContactsRunnable);

        tableViewerContacts.addSelectionChangedListener(new ContactSelectionChangedToEventDispatcher());
        tableViewerContacts.addSelectionChangedListener(new ISelectionChangedListener() {

            @Override
            public void selectionChanged(SelectionChangedEvent event) {
                StructuredSelection ss = (StructuredSelection) event.getSelection();
                tableViewerContacts.refresh(ss.getFirstElement());
            }
        });
    }

    protected DataBindingContext initDataBindings() {
        DataBindingContext bindingContext = new DataBindingContext();

        tableViewerContacts.setContentProvider(contentProvider);
        IObservableMap[] observeMaps = BeansObservables.observeMaps(contentProvider.getKnownElements(),
                IContact.class, new String[] { "description1", "description2", "mandator", "patient", "user" });
        ILabelDecorator decorator = PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator();
        tableViewerContacts.setLabelProvider(new TableDecoratingLabelProvider(
                new ContactSelectorObservableMapLabelProvider(observeMaps), decorator));
        tableViewerContacts.setInput(contactList);
        return bindingContext;
    }

    public void addContact(IContact contact) {
        contactList.add(contact);
    }

    @Override
    public void setFocus() {
        txtFilter.setFocus();
        tableViewerContacts.refresh();
    }

    @Override
    public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
        if (adapter == IPropertySheetPage.class)
            return new TabbedPropertySheetPage(this);
        return super.getAdapter(adapter);
    }

    @Override
    public String getContributorId() {
        return getSite().getId();
    }

    /**
     * Listener for the txtFilter text control. Updates the search text filter in
     * {@link KontaktAnzeigeTextFieldViewerFilter} on key press.
     */
    private class FilterKeyListener extends KeyAdapter {
        private Text text;
        private StructuredViewer viewer;

        FilterKeyListener(Text filterTxt, StructuredViewer viewer) {
            text = filterTxt;
            this.viewer = viewer;
        }

        @Override
        public void keyPressed(KeyEvent e) {
            text.setMessage("");
        }

        public void keyReleased(KeyEvent ke) {
            String txt = text.getText();

            // We have a formula, if the string starts with "="
            if (txt.startsWith("=")) {
                String formula;
                if (txt.contains(";")) {
                    formula = txt.substring(1, txt.indexOf(";"));

                    Map<String, Object> functions = new HashMap<>();
                    functions.put("math", Math.class);
                    JexlEngine jexl = new JexlEngine();
                    jexl.setLenient(false);
                    jexl.setFunctions(functions);

                    try {
                        Expression expr = jexl.createExpression(formula);
                        Object result = expr.evaluate(new MapContext());
                        text.setText("");
                        text.setMessage(formula + "=" + result + "");
                        result = null;
                    } catch (JexlException e) {
                        text.setText("");
                        text.setMessage("Invalid expression: " + formula);
                    }
                }
                return;
            }

            if (txt.length() > 1) {
                filterPositionTitle.setSearchText(txt);
                viewer.getControl().setRedraw(false);
                viewer.refresh();
                viewer.getControl().setRedraw(true);
            } else {
                filterPositionTitle.setSearchText(null);
                viewer.getControl().setRedraw(false);
                viewer.refresh();
                viewer.getControl().setRedraw(true);
            }
        }
    }

    private class LoadContactsRunnable implements Runnable {
        @Override
        public void run() {
            // Date d, e, f, g, h, i, j;
            // d = new Date();
            Query<Kontakt> qbe = new Query<Kontakt>(Kontakt.class, null, null, Kontakt.TABLENAME,
                    new String[] { Kontakt.FLD_DELETED, Kontakt.FLD_IS_PERSON, Kontakt.FLD_IS_ORGANIZATION,
                            Kontakt.FLD_IS_MANDATOR, Kontakt.FLD_IS_USER, Kontakt.FLD_IS_PATIENT, Kontakt.FLD_NAME1,
                            Kontakt.FLD_NAME2, Kontakt.FLD_NAME3, Person.BIRTHDATE, Person.SEX, Patient.FLD_PATID,
                            Person.TITLE, Person.FLD_TITLE_SUFFIX });
            // e = new Date();
            List<Kontakt> qre = qbe.execute();
            // f = new Date(); // 2598
            List<? extends IContact> result = ContactBeanFactory.createContactBeans(qre);
            // g = new Date();
            lblStatus.setText(qbe.size() + " contacts found.");
            // h = new Date(); // 4001 !!!
            tableViewerContacts.getControl().setRedraw(false);
            contactList.clear();
            contactList.addAll(result);
            // i = new Date();
            // j = new Date();
            tableViewerContacts.getControl().setRedraw(true);
            // System.out.println("d-e: "+(e.getTime()-d.getTime()));
            // System.out.println("e-f: "+(f.getTime()-e.getTime()));
            // System.out.println("f-g: "+(g.getTime()-f.getTime()));
            // System.out.println("g-h: "+(h.getTime()-g.getTime()));
            // System.out.println("h-i: "+(i.getTime()-h.getTime()));
            // System.out.println("i-j: "+(j.getTime()-i.getTime()));
            // System.out.println("sum: "+(i.getTime()-d.getTime()));
        }
    }

    /**
     * Forwards selections in the contact viewer table to the ElexisEventDispatcher
     */
    private class ContactSelectionChangedToEventDispatcher implements ISelectionChangedListener {

        @Override
        public void selectionChanged(SelectionChangedEvent event) {
            ISelection selection = event.getSelection();
            if (selection == null)
                return;
            IStructuredSelection strucSelection = (IStructuredSelection) selection;
            Object selectedObject = strucSelection.getFirstElement();
            if (selectedObject == null)
                return;
            if (selectedObject instanceof IContact) {
                IContact contact = (IContact) selectedObject;
                if (contact.isPatient()) {
                    ElexisEventDispatcher.fireSelectionEvent(Patient.load(contact.getId()));
                }
            }
        }
    }
}