ch.marlovits.plz.MCCombo.java Source code

Java tutorial

Introduction

Here is the source code for ch.marlovits.plz.MCCombo.java

Source

/*******************************************************************************
 * Copyright (c) 2009 Harald Marlovits.
 * 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:
 *     Harald Marlovits    - initial implementation
 *                         initially based on CCombo, IBM, see below
 *******************************************************************************/
/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package ch.marlovits.plz;

import java.awt.MouseInfo;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.ACC;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleControlAdapter;
import org.eclipse.swt.accessibility.AccessibleControlEvent;
import org.eclipse.swt.accessibility.AccessibleEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.TypedListener;

public class MCCombo extends Composite {
    static final int ITEMS_SHOWING = 5;

    private boolean selected; // pressed enter/esc/tab for selection
    private Text text;
    private Shell popup;
    private boolean hasFocus;
    private String theText;
    private String oldText;
    private TableViewer tableViewer;
    private Table table;
    private String[] showFields = null; // shown fields in table (database fields)
                                        // the fields are used for querying from the db
                                        // if queryFields is not null, then queryFields is
                                        // used for querying
    private String[] queryFields = null; // used for querying from the db (database fields)
                                         // if more complex queries are needed, eg:
                                         //    'a' || databasefield as showFieldName1
                                         // 
    private String[] sortFields = null; // sort  fields in table, must be fields from showFields
    private Object[] returnFields = null; // fields into which data should be written
                                          // same number of items as in showFields, same order
                                          // must be fields from showFields
    private MCComboDataProvider dataProviderClass;
    boolean isTrackingTable = false;
    TestListener tempMouseListener = new TestListener();

    // test caller
    public void callDataProvider() {
        String[][] tmp = dataProviderClass.mCComboDataProvider(this);
        if (tmp == null) {
            dropDown(false);
        } else {
            setItems(tmp);
            if (table.getItemCount() > 0) {
                dropDown(true);
            } else {
                dropDown(false);
            }
        }
    }

    public void installDataProvider(MCComboDataProvider pDataProviderClass) {
        dataProviderClass = pDataProviderClass;
    }

    // this is the interface which must be implemeted as a real class
    public interface MCComboDataProvider {
        public String[][] mCComboDataProvider(MCCombo lThis);
    }

    public void setReturnFields(Object[] returnFields) {
        this.returnFields = returnFields;
    }

    public Object[] getReturnFields() {
        return returnFields;
    }

    public void setQueryFields(String[] queryFields) {
        this.queryFields = queryFields;
    }

    public String[] getQueryFields() {
        return queryFields;
    }

    public void setShowFields(String[] showFields) {
        this.showFields = showFields;
    }

    public String[] getShowFields() {
        return showFields;
    }

    public void setSortFields(String[] sortFields) {
        this.sortFields = sortFields;
    }

    public String[] getSortFields() {
        return sortFields;
    }

    public MCCombo(Composite parent, int style) {
        super(parent, checkStyle(style));

        style = getStyle();

        // das Textfeld erstellen ***************************************************
        int textStyle = SWT.SINGLE;
        if ((style & SWT.READ_ONLY) != 0)
            textStyle |= SWT.READ_ONLY;
        if ((style & SWT.FLAT) != 0)
            textStyle |= SWT.FLAT;
        text = new Text(this, textStyle);

        // die Shell erstellen, in welcher die Liste/Tabelle erstellt wird **********
        //popup = new Shell(getShell(), SWT.NO_TRIM);
        popup = new Shell(getShell(), SWT.NO_TRIM | SWT.TOOL);

        int listStyle = SWT.SINGLE | SWT.V_SCROLL | SWT.FULL_SELECTION;

        if ((style & SWT.FLAT) != 0)
            listStyle |= SWT.FLAT;
        if ((style & SWT.RIGHT_TO_LEFT) != 0)
            listStyle |= SWT.RIGHT_TO_LEFT;
        if ((style & SWT.LEFT_TO_RIGHT) != 0)
            listStyle |= SWT.LEFT_TO_RIGHT;

        // meine eigene Popup-Liste mit mehreren Spalten erstellen in popup *********
        tableViewer = new TableViewer(popup, listStyle);
        GridData gd = new GridData();
        gd.horizontalAlignment = SWT.FILL;
        gd.verticalAlignment = SWT.FILL;
        gd.grabExcessHorizontalSpace = true;
        gd.grabExcessVerticalSpace = true;

        tableViewer.getControl().setLayoutData(gd);
        table = tableViewer.getTable();
        table.setHeaderVisible(false);
        table.setLinesVisible(false);

        selected = false;

        // die Listener installieren ************************************************
        Listener listener = new Listener() {
            public void handleEvent(Event event) {
                if (popup == event.widget) {
                    //System.out.println("event.widget == popup, calling popupEvent(event)");
                    popupEvent(event);
                    return;
                }
                if (text == event.widget) {
                    //System.out.println("event.widget == text");
                    textEvent(event);
                    return;
                }
                if (table == event.widget) {
                    //System.out.println("event.widget == list, calling listEvent(event)");
                    listEvent(event);
                    return;
                }
                if (MCCombo.this == event.widget) {
                    //System.out.println("event.widget == MyCComboSaved2, calling comboEvent(event)");
                    comboEvent(event);
                    return;
                }
                //            if (table.getColumn(0) == event.widget) {
                //               System.out.println("event.widget == table.getColumn(0), calling columnEvent(event)");
                //               columnEvent(event);
                //               return;
                //            }
                System.out.println("other: event.widget == " + event.widget);
            }
        };

        int[] comboEvents = { SWT.Dispose, SWT.Move, SWT.Resize, SWT.DRAG, SWT.DragDetect, SWT.Traverse };
        for (int i = 0; i < comboEvents.length; i++)
            this.addListener(comboEvents[i], listener);

        int[] popupEvents = { SWT.Close, SWT.Paint, SWT.Deactivate, SWT.MouseMove, SWT.MouseExit };
        for (int i = 0; i < popupEvents.length; i++)
            popup.addListener(popupEvents[i], listener);

        int[] textEvents = { SWT.KeyDown, SWT.KeyUp, SWT.Modify, SWT.MouseDown, SWT.MouseUp, SWT.Traverse,
                SWT.FocusIn, SWT.FocusOut, SWT.DEL };
        for (int i = 0; i < textEvents.length; i++)
            text.addListener(textEvents[i], listener);

        int[] listEvents = { SWT.MouseUp, SWT.Selection, SWT.Traverse, SWT.KeyDown, SWT.KeyUp, SWT.FocusIn,
                SWT.FocusOut, SWT.MouseMove, SWT.DRAG, SWT.NONE, SWT.MouseDown, SWT.MouseHover, SWT.MouseExit,
                SWT.MouseEnter };
        for (int i = 0; i < listEvents.length; i++)
            table.addListener(listEvents[i], listener);

        //      int [] tableViewerEvents = {SWT.MouseUp, SWT.Selection, SWT.Traverse, SWT.KeyDown, SWT.KeyUp, SWT.FocusIn, SWT.FocusOut, SWT.MouseMove, SWT.DRAG, SWT.NONE, SWT.MouseDown, SWT.MouseHover, SWT.MouseExit};
        //      for (int i=0; i<tableViewerEvents.length; i++) table.getColumn(0).addListener(tableViewerEvents [i], listener);

        initAccessible();
    }

    /*
       void columnEvent(Event event) {
          switch(event.type) {
     case SWT.MouseUp:
        System.out.println("MouseUp");
        break;
     case SWT.Selection:
        System.out.println("Selection");
        break;
     case SWT.Traverse:
        System.out.println("KeyUp");
        break;
     //case SWT.KeyDown:
     //   break;
     case SWT.KeyUp:
        System.out.println("KeyUp");
        break;
     case SWT.FocusIn:
        System.out.println("FocusIn");
        break;
     case SWT.FocusOut:
        System.out.println("FocusOut");
        break;
     case SWT.MouseMove:
        System.out.println("MouseMove");
        break;
     case SWT.DRAG:
        System.out.println("DRAG");
        break;
     case SWT.NONE:
        System.out.println("NONE");
        break;
     case SWT.MouseDown:
        System.out.println("MouseDown");
        break;
     case SWT.MouseHover:
        System.out.println("MouseHover");
        break;
     case SWT.MouseExit:
        System.out.println("MouseExit");
        break;
     default:
        System.out.println("other");
        //textEvent(event);
        break;
          }
       }
        
    */
    public Table getList() {
        return table;
    }

    public TableViewer getTableViewer() {
        return tableViewer;
    }

    public Table getTable() {
        return table;
    }

    public void setListVisible(boolean visibility) {
        popup.setVisible(visibility);
    }

    public void setTableViewerVisible(boolean visibility) {
        popup.setVisible(visibility);
    }

    public void setTableVisible(boolean visibility) {
        table.setVisible(visibility);
    }

    static int checkStyle(int style) {
        int mask = SWT.BORDER | SWT.READ_ONLY | SWT.FLAT | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
        return style & mask;
    }

    //TODO
    /*
    public void add(String string) {
       checkWidget();
       if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
       list.add(string);
    }
    */
    //TODO
    /*
    public void add(String string, int index) {
       checkWidget();
       if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
       list.add(string, index);
    }
    */
    public void addModifyListener(ModifyListener listener) {
        ;
        checkWidget();
        if (listener == null)
            SWT.error(SWT.ERROR_NULL_ARGUMENT);
        TypedListener typedListener = new TypedListener(listener);
        addListener(SWT.Modify, typedListener);
    }

    public void addSelectionListener(SelectionListener listener) {
        checkWidget();
        if (listener == null)
            SWT.error(SWT.ERROR_NULL_ARGUMENT);
        TypedListener typedListener = new TypedListener(listener);
        addListener(SWT.Selection, typedListener);
        addListener(SWT.DefaultSelection, typedListener);
    }

    public void clearSelection() {
        checkWidget();
        text.clearSelection();
        table.deselectAll();
    }

    void comboEvent(Event event) {
        switch (event.type) {
        case SWT.Dispose:
            if (popup != null && !popup.isDisposed())
                popup.dispose();
            popup = null;
            text = null;
            tableViewer = null;
            break;
        case SWT.Move:
            //System.out.println("SWT.Move");
            dropDown(false);
            break;
        case SWT.Resize:
            internalLayout();
            break;
        //         default:
        //            text.setFocus();
        //            //textEvent(event);
        //            break;
        //         case SWT.Traverse:
        //            System.out.println("comboEvent Traverse");
        //            break;
        }
    }

    public Point computeSize(int wHint, int hHint, boolean changed) {
        Point listSize = new Point(0, 0);
        checkWidget();
        int width = 0, height = 0;
        Point textSize = text.computeSize(wHint, SWT.DEFAULT, changed);
        resizeColums();
        //listSize  = table.computeSize(wHint, SWT.DEFAULT, changed);
        listSize.x = table.getBorderWidth();
        listSize.y = table.getItemHeight() * ITEMS_SHOWING;
        int borderWidth = getBorderWidth();

        height = Math.max(hHint, textSize.y + 2 * borderWidth);
        //width = Math.max(wHint, Math.max(textSize.x + 2*borderWidth, listSize.x + 2)  );
        width = 2 * borderWidth + 2;
        return new Point(width, height);
    }

    public void deselect(int index) {
        checkWidget();
        table.deselect(index);
    }

    public void deselectAll() {
        checkWidget();
        table.deselectAll();
    }

    public void dropDown(boolean drop) {
        // no unnecessary redraw: exit if text is still the same 
        //      if (oldText == null) oldText = "";
        //      if (oldText.equals(text.getText()))   {
        //         return;
        //      }

        // need to recalc vertical size
        //if (drop == isDropped()) return;
        if ((drop) && (selected == true)) {
            return;
        }
        boolean justVertical = false;
        if (drop == isDropped()) {
            justVertical = true;
        }
        // if no drop then hide popup
        if (!drop) {
            popup.setVisible(false);
            text.setFocus();
            // no unnecessary redraws
            oldText = text.getText();
            return;
        }
        // if no items in list then hide popup
        if (table.getItemCount() < 1) {
            popup.setVisible(false);
            text.setFocus();
            // no unnecessary redraws
            oldText = text.getText();
            return;
        }
        int index = table.getSelectionIndex();
        if (index != -1)
            table.setTopIndex(index);

        // need the combosize, App main window, parent composite bounds, desktop
        Point comboSize = getSize();
        Display desktop = getDisplay();

        table.setHeaderVisible(true);
        table.setToolTipText("ToolTipText");
        table.getColumn(0).setAlignment(SWT.RIGHT);
        table.getColumn(1).setAlignment(SWT.RIGHT);
        table.getColumn(2).setAlignment(SWT.RIGHT);

        // recalc optimized column sizes
        resizeColums();

        // get table size, uncorrected
        Point tableSize = table.getSize();

        // rect contains the coordinates for placing topleft of popup relative to parent
        Rectangle rect = desktop.map(getParent(), null, getBounds());

        // calc  uncorrected vertical table size 
        tableSize.y = table.getItemHeight() * Math.min(table.getItemCount(), 32000);

        // correct vertical table size
        Point pt = text.getLocation();
        pt = text.toDisplay(pt);
        pt.y = pt.y + text.getBounds().height + 2 * text.getBorderWidth();
        pt.x = pt.x + +2 * text.getBorderWidth();
        int headerHeight = table.getHeaderHeight();
        int verticalSpace = desktop.getClientArea().height - headerHeight - pt.y - 4;
        if (tableSize.y > verticalSpace) {
            if (System.getProperties().getProperty("os.name").equals("Windows XP")) {
                tableSize.y = (int) ((verticalSpace / table.getItemHeight()) - 2) * table.getItemHeight()
                        + headerHeight;
            } else {
                tableSize.y = (int) (verticalSpace / table.getItemHeight()) * table.getItemHeight() + headerHeight;
            }
        }
        // correct horizontal table position: hSize remains, we just move the popup to the left
        int horizontalSpace = desktop.getClientArea().width - tableSize.x - 2;
        if (pt.x > horizontalSpace) {
            rect.x = desktop.getClientArea().width - tableSize.x - 2;
        }

        // set size of table and popup
        table.setBounds(1, 1, tableSize.x, tableSize.y);
        popup.setBounds(rect.x, rect.y + comboSize.y, tableSize.x + 2, tableSize.y + 2);

        // now make the list visible again/redraw
        popup.setVisible(true);

        // no unnecessary redraws
        oldText = text.getText();
    }

    public Control[] getChildren() {
        checkWidget();
        return new Control[0];
    }

    boolean getEditable() {
        return text.getEditable();
    }

    //TODO
    /*
    public String getItem(int index) {
       checkWidget();
       return list.getItem(index);
    }
    */
    public TableItem getItemNew(int index) {
        checkWidget();
        return table.getItem(index);
    }

    public int getItemCount() {
        checkWidget();
        return table.getItemCount();
    }

    public int getItemHeight() {
        checkWidget();
        return table.getItemHeight();
    }

    //TODO
    /*
    public String[] getItems() {
       checkWidget();
       return list.getItems();
    }
    */
    public TableItem[] getItemsNew() {
        checkWidget();
        return table.getItems();
    }

    public Point getSelection() {
        checkWidget();
        return text.getSelection();
    }

    public int getSelectionIndex() {
        checkWidget();
        return table.getSelectionIndex();
    }

    public String getText() {
        checkWidget();
        return text.getText();
    }

    public int getTextHeight() {
        checkWidget();
        return text.getLineHeight();
    }

    public int getTextLimit() {
        checkWidget();
        return text.getTextLimit();
    }

    //TODO
    /*
    public int indexOf(String string) {
       checkWidget();
       if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
       return list.indexOf(string);
    }
    */
    //TODO
    /*
    public int indexOf(String string, int start) {
       checkWidget();
       if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
       return list.indexOf(string, start);
    }
    */
    void initAccessible() {
        getAccessible().addAccessibleListener(new AccessibleAdapter() {
            public void getHelp(AccessibleEvent e) {
                e.result = getToolTipText();
            }
        });

        getAccessible().addAccessibleControlListener(new AccessibleControlAdapter() {
            public void getChildAtPoint(AccessibleControlEvent e) {
                Point testPoint = toControl(new Point(e.x, e.y));
                if (getBounds().contains(testPoint)) {
                    e.childID = ACC.CHILDID_SELF;
                }
            }

            public void getLocation(AccessibleControlEvent e) {
                Rectangle location = getBounds();
                Point pt = toDisplay(new Point(location.x, location.y));
                e.x = pt.x;
                e.y = pt.y;
                e.width = location.width;
                e.height = location.height;
            }

            public void getChildCount(AccessibleControlEvent e) {
                e.detail = 0;
            }

            public void getRole(AccessibleControlEvent e) {
                e.detail = ACC.ROLE_COMBOBOX;
            }

            public void getState(AccessibleControlEvent e) {
                e.detail = ACC.STATE_NORMAL;
            }

            public void getValue(AccessibleControlEvent e) {
                e.result = getText();
            }
        });
    }

    boolean isDropped() {
        return popup.getVisible();
    }

    public boolean isFocusControl() {
        checkWidget();
        if (text.isFocusControl() || table.isFocusControl() || popup.isFocusControl()) {
            return true;
        } else {
            return super.isFocusControl();
        }
    }

    /**
     * Neu Berechnen/Zeichnen des ganzen Konstrukts
     */
    void internalLayout() {
        if (isDropped())
            dropDown(false);

        Rectangle rect = getClientArea();
        int width = rect.width;
        int height = rect.height;
        text.setBounds(0, 0, width, height);

        Point size = getSize();
        int itemHeight = table.getItemHeight() * ITEMS_SHOWING;
        Point listSize = table.computeSize(SWT.DEFAULT, itemHeight, true);
        table.setBounds(1, 1, Math.max(size.x - 2, listSize.x), listSize.y);
    }

    /**
     * Sets the fields linked to this control. The data found in the current selection will be inserted 
     * into these fields. 
     * The fields are defined in returnFields[]. 
     * Every object that has the setText method can be used in this array.
     * @return true on success/if data has been found, false on error
     */
    boolean setLinkedFields() {
        // returnFields must be set
        if (returnFields == null) {
            //System.out.println("setLinkedFields(): the field returnFields has not yet been set.");
            return false;
        }
        // no selected row in table -> exit
        if (table.getSelectionIndex() == -1) {
            return false;
        }
        // loop through returnFields[] which contains the fields as objects-array
        for (int fieldIx = 0; fieldIx < returnFields.length; fieldIx++) {
            try {
                // get the object from the list
                Object obj = returnFields[fieldIx];
                if (obj == null)
                    continue;
                // find the class of this object
                Class<?> c = Class.forName(obj.getClass().getName());
                // create return params class
                Class[] params = new Class[1];
                params[0] = String.class;
                // get the setText method
                Method setTextCaller = c.getMethod("setText", params);
                // build params: read currently selected
                TableItem tableItem = table.getSelection()[0];
                String[] input = { new String(tableItem.getText(fieldIx)) };
                // call the method
                setTextCaller.invoke(obj, input);
            } catch (ClassNotFoundException x) {
                x.printStackTrace();
                return false;
            } catch (IllegalAccessException x) {
                x.printStackTrace();
                return false;
            } catch (SecurityException e) {
                e.printStackTrace();
                return false;
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
                return false;
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
                return false;
            } catch (InvocationTargetException e) {
                e.printStackTrace();
                return false;
            }
        }
        if (1 == 0)
            return true;
        return true;
    }

    class TestListener implements MouseMoveListener {
        public void mouseMove(MouseEvent e) {
            System.out.println("testListener: mouseMove");
        }
    }

    void listEvent(Event event) {
        //System.out.println("listEvent called");
        switch (event.type) {
        //      case SWT.SCROLL_LINE:
        //         System.out.println("List: SCROLL_LINE");
        //         break;
        case SWT.MouseEnter:
            System.out.println("List: MouseEnter");
            //isTrackingTable = true;
            break;
        case SWT.MouseExit:
            System.out.println("List: MouseExit");
            //isTrackingTable = false;
            break;
        case SWT.MouseDown:
            text.setFocus();
            isTrackingTable = true;
            Display desktop = getDisplay();
            table.setCapture(true);
            //         Composite cmp = this;
            //         while ((cmp = cmp.getParent()) != null)   {
            //            cmp.addListener(SWT.MouseMove, (Listener) tempMouseListener);
            //         }
            desktop.addListener(SWT.MouseMove, (Listener) tempMouseListener);
            break;
        case SWT.MouseUp: {
            if (event.button != 1)
                return;
            dropDown(false);
            Event e = new Event();
            e.time = event.time;
            notifyListeners(SWT.DefaultSelection, e);
            isTrackingTable = false;
            desktop = getDisplay();
            //         cmp = this;
            //         while ((cmp = cmp.getParent()) != null)   {
            //            cmp.removeListener(SWT.MouseMove, (Listener) tempMouseListener);
            //         }
            desktop.removeListener(SWT.MouseMove, (Listener) tempMouseListener);
            break;
        }
        case SWT.MouseMove: {
            int itemHeight = table.getItemHeight();
            if (isTrackingTable == false) {
                //table.setCapture(true);
                System.out.println("List: MouseMove");
                int itemSel = (event.y - table.getHeaderHeight()) / itemHeight;
                //System.out.println("itemSel: " + itemSel);
                int newSelection = table.getTopIndex() + itemSel;
                int currSel = table.getSelectionIndex();
                // windows behaviour
                if (currSel != newSelection) {
                    table.setSelection(newSelection);
                }
            } else {
                table.setCapture(true);
                Point pt = new Point((int) (MouseInfo.getPointerInfo().getLocation().getX()),
                        (int) MouseInfo.getPointerInfo().getLocation().getY());
                pt = table.toControl(pt);
                int itemSel = (pt.y - table.getHeaderHeight()) / itemHeight;
                //System.out.println("itemSel: " + itemSel);
                int newSelection = table.getTopIndex() + itemSel;
                int currSel = table.getSelectionIndex();
                Rectangle bounds = popup.getBounds();
                //if (bounds.contains(pt))   {
                if (currSel != newSelection) {
                    table.setSelection(newSelection);
                }
                //}
            }
        }
        case SWT.FocusIn: {
            if (hasFocus)
                return;
            hasFocus = true;
            if (getEditable())
                text.selectAll();
            Event e = new Event();
            e.time = event.time;
            notifyListeners(SWT.FocusIn, e);
            System.out.println("listEvent FocusIn");
            break;
        }
        case SWT.FocusOut: {
            //System.out.println("SWT.FocusOut");
            event.display.asyncExec(new Runnable() {
                public void run() {
                    if (MCCombo.this.isDisposed())
                        return;
                    Control focusControl = getDisplay().getFocusControl();
                    if (focusControl == text)
                        return;
                    hasFocus = false;
                    Event e = new Event();
                    notifyListeners(SWT.FocusOut, e);
                }
            });
            System.out.println("listEvent FocusOut");
            break;
        }
        case SWT.Selection: {
            //System.out.println("SWT.Selection");
            int index = table.getSelectionIndex();
            if (index == -1)
                return;
            text.setText(table.getItem(index).getText(0));
            setLinkedFields();
            text.selectAll();
            table.setSelection(index);
            table.setFocus();
            event.doit = false;
            if (1 == 1)
                break;
            Event e = new Event();
            e.time = event.time;
            e.stateMask = event.stateMask;
            e.doit = event.doit;
            notifyListeners(SWT.Selection, e);
            event.doit = e.doit;
            setLinkedFields();
            break;
        }
        case SWT.Traverse: {
            //System.out.println("listEvent: SWT.Traverse: before switch");
            switch (event.detail) {
            case SWT.TRAVERSE_TAB_NEXT:
            case SWT.TRAVERSE_RETURN:
            case SWT.TRAVERSE_ESCAPE:
            case SWT.TRAVERSE_ARROW_PREVIOUS:
            case SWT.TRAVERSE_ARROW_NEXT:
                event.doit = false;
                break;
            }
            //System.out.println("SWT.Traverse: after switch");
            Event e = new Event();
            e.time = event.time;
            e.detail = event.detail;
            e.doit = event.doit;
            e.keyCode = event.keyCode;
            //         if   ((event.keyCode == SWT.ARROW_LEFT) || (event.keyCode == SWT.ARROW_RIGHT))   {
            //            event.doit = false;
            //            e.doit = false;
            //            System.out.println("traverse cancel");
            //            break;
            //         }
            notifyListeners(SWT.Traverse, e);
            //System.out.println("event.keyCode: " + event.keyCode);
            event.doit = e.doit;
            break;
        }
        case SWT.KeyUp: {
            //System.out.println("listEvent: SWT.KeyUp");
            int index = table.getSelectionIndex();
            if (index == -1)
                return;
            ////////////text.setText(table.getItem(index).getText(0));
            Event e = new Event();
            e.time = event.time;
            e.character = event.character;
            e.keyCode = event.keyCode;
            e.stateMask = event.stateMask;
            if ((event.keyCode == SWT.ARROW_LEFT) || (event.keyCode == SWT.ARROW_RIGHT)) {
                //event.doit = false;
                //e.doit = false;
                //System.out.println("keyUp cancel");
                break;
            }
            notifyListeners(SWT.KeyUp, e);
            break;
        }
        case SWT.KeyDown: {
            System.out.println("listEvent: SWT.KeyDown");
            if (event.character == SWT.ESC) {
                // escape key cancels popup list
                dropDown(false);
            }
            if (event.character == SWT.CR || event.character == '\t') {
                // Enter and Tab cause default selection
                dropDown(false);
                selected = !selected;
                Event e = new Event();
                e.time = event.time;
                e.stateMask = event.stateMask;
                notifyListeners(SWT.DefaultSelection, e);
            }
            if ((event.keyCode == SWT.ARROW_LEFT) || (event.keyCode == SWT.ARROW_RIGHT)) {
                // Enter and Tab cause default selection
                //text.setSelection(text.getText().length());
                text.setFocus();
                event.doit = false;
                Event e = new Event();
                e.time = event.time;
                e.type = event.type;
                e.button = event.button;
                e.character = event.character;
                e.keyCode = event.keyCode;
                e.stateMask = event.stateMask;
                notifyListeners(SWT.DefaultSelection, e);
            }
            int oldIndex = table.getSelectionIndex();
            if (event.keyCode == SWT.ARROW_UP) {
                switch (oldIndex) {
                case (0):
                    text.setText("set from keyup");
                    break;
                default:
                    break;
                }
            }
            //At this point the widget may have been disposed.
            // If so, do not continue.
            if (isDisposed())
                break;
            Event e = new Event();
            e.time = event.time;
            e.character = event.character;
            e.keyCode = event.keyCode;
            e.stateMask = event.stateMask;
            notifyListeners(SWT.KeyDown, e);
            break;

        }
        }
    }

    void popupEvent(Event event) {
        switch (event.type) {
        case SWT.Paint:
            // draw black rectangle around list
            //System.out.println("popup: draw");
            Rectangle listRect;
            listRect = table.getBounds();
            Color black = getDisplay().getSystemColor(SWT.COLOR_BLACK);
            event.gc.setForeground(black);
            event.gc.drawRectangle(0, 0, listRect.width + 1, listRect.height + 1);
            break;
        case SWT.Close:
            //System.out.println("popup: close");
            event.doit = false;
            //dropDown(false);
            break;
        case SWT.Deactivate:
            //System.out.println("popup: deactivate");
            //dropDown(false);
            break;
        case SWT.MouseMove:
            System.out.println("popupEvent: MouseMove");
            break;
        case SWT.MouseHover:
            System.out.println("popupEvent: MouseHover");
            break;
        default:
            //System.out.println("popup: alles andere");
        }
    }

    public void redraw(int x, int y, int width, int height, boolean all) {
        checkWidget();
        if (!all)
            return;
        Point location = text.getLocation();
        text.redraw(x - location.x, y - location.y, width, height, all);
        location = table.getLocation();
        table.redraw(x - location.x, y - location.y, width, height, all);
    }

    public void remove(int index) {
        checkWidget();
        table.remove(index);
    }

    public void remove(int start, int end) {
        checkWidget();
        table.remove(start, end);
    }

    //TODO
    /*
    public void remove(String string) {
       checkWidget();
       if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
       if (isOldStyle){
     list.remove(string);
       } else {
     //table.remove(string);
       }
    }
    */
    public void removeAll() {
        checkWidget();
        text.setText(""); //$NON-NLS-1$
        table.deselectAll();
        table.removeAll();
    }

    public void removeModifyListener(ModifyListener listener) {
        checkWidget();
        if (listener == null)
            SWT.error(SWT.ERROR_NULL_ARGUMENT);
        removeListener(SWT.Modify, listener);
    }

    public void removeSelectionListener(SelectionListener listener) {
        checkWidget();
        if (listener == null)
            SWT.error(SWT.ERROR_NULL_ARGUMENT);
        removeListener(SWT.Selection, listener);
        removeListener(SWT.DefaultSelection, listener);
    }

    public void select(int index) {
        checkWidget();
        if (index == -1) {
            table.deselectAll();
            text.setText(""); //$NON-NLS-1$
            return;
        }
        if (0 <= index && index < table.getItemCount()) {
            if (index != getSelectionIndex()) {
                // TODO
                /////////////////////////text.setText(table.getItem(index));
                text.selectAll();
                table.select(index);
                //         TableItem currItem = table.getItem(index);
                //         table.setSelection(currItem);
                //         int[] indices = {index, index + 1, index + 2, index + 3};
                //         table.select(index, index+10);
                table.showSelection();
            }
        }
    }

    public void setBackground(Color color) {
        super.setBackground(color);
        if (text != null)
            text.setBackground(color);
        if (table != null)
            table.setBackground(color);
    }

    public boolean setFocus() {
        checkWidget();
        return text.setFocus();
    }

    public void setFont(Font font) {
        super.setFont(font);
        text.setFont(font);
        table.setFont(font);
        internalLayout();
    }

    public void setForeground(Color color) {
        super.setForeground(color);
        if (text != null)
            text.setForeground(color);
        if (table != null)
            table.setForeground(color);
    }

    //TODO
    /*
    public void setItem(int index, String string) {
       checkWidget();
       if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
       list.setItem(index, string);
    }
    */
    protected void resizeColums() {
        //////////////////////////////////////////////
        if (1 == 0)
            return;

        checkWidget();
        int width = 0;
        //////////////////////table.setBounds(0, 0, 500, 500);
        for (int colIx = 0; colIx < table.getColumnCount(); colIx++) {
            TableColumn currColumn = table.getColumns()[colIx];
            currColumn.setResizable(true);
            currColumn.pack();
            width = width + currColumn.getWidth();
        }
        //table.setSize(width, table.getSize().y);  // wrong: missing scrollbar!
        table.pack();
    }

    public void setItems(String[][] items) {
        //   setDataProviderCaller();
        checkWidget();

        if (items == null)
            SWT.error(SWT.ERROR_NULL_ARGUMENT);
        int style = getStyle();

        // no unnecessary redraw: exit if text is still the same 
        //   if ((oldText != null) && (oldText.equals(text.getText())))   {
        //      return;
        //   }

        /////////////////////if ((style & SWT.READ_ONLY) != 0) text.setText(""); //$NON-NLS-1$

        // remove old content
        table.removeAll();

        // create columns
        int numOfRows = items.length;
        if (numOfRows == 0)
            return;
        int numOfColumns = items[0].length;

        int currColumnCount = table.getColumnCount();
        if (numOfColumns < currColumnCount) {
            for (int i = numOfColumns; i < currColumnCount; i++) {
                table.getColumns()[i].dispose();
            }
        }

        for (int colIx = 0; colIx < numOfColumns; colIx++) {
            // detect or create column
            TableColumn currColumn = null;
            if (colIx < currColumnCount) {
                currColumn = table.getColumns()[colIx];
            } else {
                currColumn = new TableColumn(table, SWT.NULL);
            }
        }
        // no flickering when redrawing for XP
        popup.setRedraw(false);
        // insert data into table
        for (int rowIx = 0; rowIx < numOfRows; rowIx++) {
            TableItem tableItem = new TableItem(table, SWT.NULL);
            tableItem.setText(items[rowIx]);
        }
        // optimize size of the columns
        for (int colIx = 0; colIx < numOfColumns; colIx++) {
            table.getColumn(colIx).setWidth(1000); // bug workaround for Windows XP which makes colums smaller but not bigger in .pack
            table.getColumn(colIx).pack();
        }
        // no flickering when redrawing for XP
        popup.setRedraw(true);

        // no unnecessary redraw
        //oldText = text.getText();
        table.getItem(0).setGrayed(true);
    }

    public void setSelection(Point selection) {
        checkWidget();
        if (selection == null)
            SWT.error(SWT.ERROR_NULL_ARGUMENT);
        text.setSelection(selection.x, selection.y);
    }

    //TODO
    public void setText(String string) {
        checkWidget();

        text.setText(string);

        //      
        //      if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
        //      int index = list.indexOf(string);
        //      if (index == -1) {
        //         list.deselectAll();
        //         text.setText(string);
        //         return;
        //      }
        //      text.setText(string);
        //      text.selectAll();
        //      list.setSelection(index);
        //      list.showSelection();
    }

    public void setTextNew(String string) {
        checkWidget();
        if (string == null)
            SWT.error(SWT.ERROR_NULL_ARGUMENT);
        // TODO int index = list.indexOf(string);
        int index = 0; // TODO muss weg
        if (index == -1) {
            table.deselectAll();
            text.setText(string);
            return;
        }
        text.setText(string);
        text.selectAll();
        // TODO table.setSelection(index);
        table.showSelection();
    }

    public void setTextLimit(int limit) {
        checkWidget();
        text.setTextLimit(limit);
    }

    public void setToolTipText(String string) {
        checkWidget();
        super.setToolTipText(string);
        text.setToolTipText(string);
    }

    public void setVisible(boolean visible) {
        super.setVisible(visible);
        if (!visible)
            popup.setVisible(false);
    }

    void textEvent(Event event) {
        switch (event.type) {
        case SWT.FocusIn: {
            //System.out.println("textEvent: FocusIn");
            if (hasFocus)
                return;
            hasFocus = true;
            if (getEditable())
                text.selectAll();
            Event e = new Event();
            e.time = event.time;
            notifyListeners(SWT.FocusIn, e);
            //dropDown(true);
            System.out.println("textEvent FocusIn");
            break;
        }
        case SWT.FocusOut: {
            //System.out.println("textEvent: FocusOut");
            event.display.asyncExec(new Runnable() {
                public void run() {
                    if (MCCombo.this.isDisposed())
                        return;
                    Control focusControl = getDisplay().getFocusControl();
                    if (focusControl == table)
                        return;
                    hasFocus = false;
                    Event e = new Event();
                    notifyListeners(SWT.FocusOut, e);
                }
            });
            System.out.println("textEvent FocusOut");
            //dropDown(false);
            break;
        }
        case SWT.KeyDown: {
            boolean handled = false;
            //System.out.println("textEvent: KeyDown");
            if (event.character != SWT.CR) {
                selected = false;
            }
            if (event.character == SWT.ESC) { // escape key cancels popup list
                dropDown(selected);
                text.setText(theText);
                text.setSelection(text.getText().length());
                event.doit = false;
                theText = text.getText();
                table.removeAll();
                table.deselectAll();
                text.setFocus();
                handled = true;
                selected = !selected;
                break;
            }
            if (event.character == SWT.CR) {
                dropDown(selected);
                Event e = new Event();
                e.time = event.time;
                e.stateMask = event.stateMask;
                notifyListeners(SWT.DefaultSelection, e);
                event.doit = false;
                theText = text.getText();
                // this sets the linked fields from the selection
                setLinkedFields();
                selected = !selected;
                table.removeAll();
                table.deselectAll();
                text.setFocus();
                handled = true;
                break;
            }
            //At this point the widget may have been disposed.
            // If so, do not continue.
            if (isDisposed())
                break;

            if (event.keyCode == SWT.HOME) {
                table.setSelection(0);
                text.setText(table.getSelection()[0].getText());
                text.setSelection(text.getText().length());
                event.doit = false;
                handled = true;
            }
            if (event.keyCode == SWT.END) {
                table.setSelection(table.getItemCount() - 1);
                text.setText(table.getSelection()[0].getText());
                text.setSelection(text.getText().length());
                event.doit = false;
                handled = true;
            }
            if (event.keyCode == SWT.PAGE_DOWN) {
                Rectangle rect = table.getBounds();
                int itemHeight = table.getItemHeight();
                int numOfDisplayedRows = (rect.height / itemHeight);
                table.setSelection(
                        Math.min(table.getItemCount() - 1, table.getSelectionIndex() + numOfDisplayedRows - 1));
                text.setText(table.getSelection()[0].getText());
                text.setSelection(text.getText().length());
                event.doit = false;
                handled = true;
            }
            if (event.keyCode == SWT.PAGE_UP) {
                Rectangle rect = table.getBounds();
                int itemHeight = table.getItemHeight();
                int numOfDisplayedRows = (rect.height / itemHeight);
                table.setSelection(Math.max(0, table.getSelectionIndex() - numOfDisplayedRows + 1));
                text.setText(table.getSelection()[0].getText());
                text.setSelection(text.getText().length());
                event.doit = false;
                handled = true;
            }
            if (event.keyCode == SWT.ARROW_UP || event.keyCode == SWT.ARROW_DOWN) {
                int oldIndex = getSelectionIndex();
                if (event.keyCode == SWT.ARROW_UP) {
                    switch (oldIndex) {
                    case -1: {
                        // no item is currently selected -> save Text in theText, select last item, set text field, select end of text
                        theText = text.getText();
                        table.setSelection(table.getItemCount() - 1);
                        text.setText(table.getSelection()[0].getText());
                        text.setSelection(text.getText().length());
                        break;
                    }
                    case 0: {
                        // first item is currently selected -> deselect, set saved text, select end of text
                        table.deselectAll();
                        text.setText(theText);
                        text.setSelection(text.getText().length());
                        break;
                    }
                    default: {
                        // another item is selected -> select previous item, set text field, select end of text
                        table.setSelection(oldIndex - 1);
                        text.setText(table.getSelection()[0].getText());
                        text.setSelection(text.getText().length());
                        break;
                    }
                    }
                    event.doit = false;
                }
                if (event.keyCode == SWT.ARROW_DOWN) {
                    switch (oldIndex) {
                    case -1: {
                        // no item is currently selected -> save Text in theText, select first item, set text field, select end of text
                        theText = text.getText();
                        table.setSelection(0);
                        text.setText(table.getSelection()[0].getText());
                        text.setSelection(text.getText().length());
                        break;
                    }
                    default: {
                        if (oldIndex == table.getItemCount() - 1) {
                            // last item is currently selected -> deselect, set saved text, select end of text
                            table.deselectAll();
                            text.setText(theText);
                            text.setSelection(text.getText().length());
                        } else {
                            // another item is selected -> select next item, set text field, select end of text
                            table.setSelection(oldIndex + 1);
                            table.setSelection(oldIndex + 1);
                            text.setText(table.getSelection()[0].getText());
                            text.setSelection(text.getText().length());
                        }
                        break;
                    }
                    }
                    event.doit = false;
                } else {
                    //table.deselectAll();
                }

                if (oldIndex != getSelectionIndex()) {
                    Event e = new Event();
                    e.time = event.time;
                    e.character = event.character;
                    e.keyCode = event.keyCode;
                    e.stateMask = event.stateMask;
                    notifyListeners(SWT.Selection, e);
                }

                //At this point the widget may have been disposed.
                // If so, do not continue.
                if (isDisposed())
                    break;
                handled = true;
            }
            if (handled == false) {
                // all other keys
                table.deselectAll();
            } else {
            }

            // Further work : Need to add support for incremental search in 
            // pop up list as characters typed in text widget
            Event e = new Event();
            e.time = event.time;
            e.character = event.character;
            e.keyCode = event.keyCode;
            e.stateMask = event.stateMask;
            //notifyListeners(SWT.KeyDown, e);
            //System.out.println("textEvent.KeyDown: " + e.character);            

            break;
        }
        case SWT.KeyUp: {
            //if (1==1) break;
            //System.out.println("textEvent: KeyUp");
            Event e = new Event();
            e.time = event.time;
            e.character = event.character;
            e.keyCode = event.keyCode;
            e.stateMask = event.stateMask;
            char ch = event.character;
            notifyListeners(SWT.KeyUp, e);
            callDataProvider();
            break;
        }
        case SWT.Modify: {
            if (1 == 1)
                break;
            //System.out.println("textEvent: Modify");
            table.deselectAll();
            Event e = new Event();
            e.time = event.time;
            notifyListeners(SWT.Modify, e);
            //System.out.println("textEvent.Modify");
            callDataProvider();

            break;
        }
        case SWT.MouseDown: {
            //System.out.println("textEvent: MouseDown");
            if (event.button != 1)
                return;
            if (text.getEditable())
                return;
            boolean dropped = isDropped();
            text.selectAll();
            //if (!dropped) setFocus();
            //dropDown(!dropped);
            dropDown(true);
            Event e = new Event();
            e.time = event.time;
            e.x = event.x;
            e.y = event.y;
            notifyListeners(SWT.MouseDown, event);
            break;
        }
        case SWT.MouseUp: {
            //System.out.println("textEvent: MouseUp");
            if (event.button != 1)
                return;
            if (text.getEditable())
                return;
            text.selectAll();
            break;
        }
        case SWT.Traverse: {
            //System.out.println("textEvent: Traverse");
            switch (event.detail) {
            case SWT.TRAVERSE_RETURN:
            case SWT.TRAVERSE_ARROW_PREVIOUS:
            case SWT.TRAVERSE_ARROW_NEXT:
            case SWT.ARROW_DOWN:
            case SWT.ARROW_UP:
                //System.out.println("textEvent: first part");
                // The enter causes default selection and
                // the arrow keys are used to manipulate the list contents so
                // do not use them for traversal.
                event.doit = false;
                return;
            //break;
            }
            if (event.keyCode == SWT.TAB) {
                dropDown(false);
            }
            Event e = new Event();
            e.time = event.time;
            e.detail = event.detail;
            e.doit = event.doit;
            e.keyCode = event.keyCode;
            notifyListeners(SWT.Traverse, e);
            event.doit = e.doit;
            break;
        }
        }
    }
}