]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.ui/src/org/simantics/ui/workbench/dialogs/ElementListSelectionDialog.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.ui / src / org / simantics / ui / workbench / dialogs / ElementListSelectionDialog.java
diff --git a/bundles/org.simantics.ui/src/org/simantics/ui/workbench/dialogs/ElementListSelectionDialog.java b/bundles/org.simantics.ui/src/org/simantics/ui/workbench/dialogs/ElementListSelectionDialog.java
new file mode 100644 (file)
index 0000000..fe75370
--- /dev/null
@@ -0,0 +1,343 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+/*\r
+ * 7.6.2006\r
+ */\r
+package org.simantics.ui.workbench.dialogs;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.Collection;\r
+import java.util.Comparator;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.eclipse.jface.viewers.ILabelProvider;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.swt.widgets.Shell;\r
+import org.eclipse.swt.widgets.Text;\r
+import org.eclipse.ui.dialogs.AbstractElementListSelectionDialog;\r
+import org.eclipse.ui.dialogs.FilteredList;\r
+\r
+/**\r
+ * ElementListSelectionDialog. This dialog component automatically sorts\r
+ * previously selected objects to the top of the list. \r
+ * <p>\r
+ * The component uses title as key for distinguishing different dialog types.\r
+ * \r
+ * @author Toni Kalajainen\r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class ElementListSelectionDialog extends AbstractElementListSelectionDialog {\r
+\r
+    /** The number of previously selected objects to be remembered */\r
+    protected static final int REMEMBER_NUM             = 128;\r
+\r
+    /** The number of previously selected objects to be prioritized in the list */\r
+    protected static final int PRIORITIZE_NUM           = 5;\r
+    \r
+    protected String           title                    = "";\r
+\r
+    protected List<Object>     elementList              = new ArrayList<Object>();\r
+\r
+    protected ILabelProvider   labelProvider;\r
+\r
+    protected boolean          usePreviousSelectionSort = true;\r
+\r
+    protected Label            messageLabel;\r
+\r
+    protected Text             filterText;\r
+\r
+\r
+    /**\r
+     * Creates a list selection dialog.\r
+     * \r
+     * @param parent the parent widget.\r
+     * @param labelProvider the label provider.\r
+     */\r
+    public ElementListSelectionDialog(Shell parent, ILabelProvider labelProvider) {\r
+        super(parent, labelProvider);\r
+        this.labelProvider = labelProvider;\r
+        this.setIgnoreCase(true);\r
+    }\r
+\r
+    /**\r
+     * Sets the elements of the list.\r
+     * @param elements the elements of the list.\r
+     */\r
+    public void setElements(Object... elements) {\r
+        elementList = null;\r
+        addElements(elements);\r
+    }\r
+\r
+    public void addElements(Object... elements) {\r
+        if (elementList==null)\r
+            elementList = new ArrayList<Object>();\r
+        for (Object e : elements)\r
+            elementList.add(e);\r
+    }\r
+\r
+    /**\r
+     * Sets the elements of the list.\r
+     * @param elements the elements of the list.\r
+     */\r
+    @SuppressWarnings("rawtypes")\r
+    public void setElements(Collection c) {\r
+        elementList = null;\r
+        addElements(c);\r
+    }\r
+\r
+    @SuppressWarnings("rawtypes")\r
+    public void addElements(Collection c) {\r
+        if (elementList==null)\r
+            elementList = new ArrayList<Object>();\r
+        for (Object e : c)\r
+            elementList.add(e);\r
+    }\r
+\r
+    public void updateList() {\r
+        // Make sure that the filtered list exists before trying to update it.\r
+        if (fFilteredList != null && elementList != null) {\r
+            Object[] objs = elementList.toArray(new Object[elementList.size()]);\r
+            final boolean isEmpty = objs.length == 0;\r
+            setListElements(objs);\r
+            Runnable r = new Runnable() {\r
+                public void run() {\r
+                    handleListChange(isEmpty);\r
+                }\r
+            };\r
+            Display d = getShell().getDisplay();\r
+            if (Thread.currentThread() == d.getThread())\r
+                r.run();\r
+            else\r
+                d.asyncExec(r);\r
+        }\r
+    }\r
+\r
+    protected void handleListChange(boolean isEmpty) {\r
+        boolean wasEnabled = filterText.isEnabled();\r
+        boolean enable = !isEmpty;\r
+        messageLabel.setEnabled(enable);\r
+        filterText.setEnabled(enable);\r
+        fFilteredList.setEnabled(enable);\r
+        if (!wasEnabled)\r
+            filterText.setFocus();\r
+        updateOkState();\r
+    }\r
+\r
+    /**\r
+     * Do alphabetical sort for list elements\r
+     */\r
+    public void sortElements() {\r
+        if (elementList==null) return;\r
+        \r
+        Object[] objects = elementList.toArray(new Object[0]);\r
+        Arrays.sort(objects, new Comparator<Object>() {\r
+            public int compare(Object o1, Object o2) {\r
+                String n1 = labelProvider.getText(o1).toLowerCase();\r
+                String n2 = labelProvider.getText(o2).toLowerCase();\r
+                return n1.compareTo(n2);\r
+            }});\r
+        \r
+        elementList = new ArrayList<Object>(objects.length);\r
+        for (Object o : objects)\r
+            elementList.add(o);\r
+    }\r
+\r
+    /*\r
+     * @see SelectionStatusDialog#computeResult()\r
+     */\r
+    protected void computeResult() {\r
+        setResult(Arrays.asList(getSelectedElements()));\r
+    }\r
+\r
+    @Override\r
+    public void setTitle(String title) {\r
+        super.setTitle(title);\r
+        this.title = title;\r
+    }\r
+\r
+    public void setInitialSelection(Object selectedElement) {\r
+        this.setInitialSelections(new Object[] {selectedElement});\r
+    }\r
+\r
+    /**\r
+     * Overridden just to get a hold of the message area label.\r
+     * \r
+     * @see org.eclipse.ui.dialogs.AbstractElementListSelectionDialog#createMessageArea(org.eclipse.swt.widgets.Composite)\r
+     */\r
+    @Override\r
+    protected Label createMessageArea(Composite composite) {\r
+        messageLabel = super.createMessageArea(composite);\r
+        return messageLabel;\r
+    }\r
+\r
+    /**\r
+     * Overridden just to get a hold of the filter text.\r
+     *\r
+     * @see org.eclipse.ui.dialogs.AbstractElementListSelectionDialog#createFilterText(org.eclipse.swt.widgets.Composite)\r
+     */\r
+    @Override\r
+    protected Text createFilterText(Composite parent) {\r
+        filterText = super.createFilterText(parent);\r
+        return filterText;\r
+    }\r
+\r
+    @Override\r
+    protected FilteredList createFilteredList(Composite parent) {\r
+        FilteredList flist = super.createFilteredList(parent);\r
+\r
+        if (usePreviousSelectionSort) \r
+        {\r
+            List<Object> prioritizeList = new ArrayList<Object>();\r
+            int[] previousSelections = getPreviousSelections( title );\r
+            for (int i=0; i<previousSelections.length; i++)\r
+                for (int j=0; j<elementList.size(); j++)\r
+                    if (elementList.get(j).hashCode()==previousSelections[i])\r
+                    {\r
+                        String name = labelProvider.getText(elementList.get(j));\r
+                        if (name==null) continue;\r
+                        prioritizeList.add(name);\r
+                        if (prioritizeList.size()>PRIORITIZE_NUM)\r
+                            break;\r
+                    }\r
+        \r
+            flist.setComparator(new PrioritizeComparator(prioritizeList, isCaseIgnored()));\r
+        } else {\r
+        }\r
+        return flist;\r
+    }\r
+\r
+    protected void createControls(Composite contents) {\r
+        createMessageArea(contents);\r
+        createFilterText(contents);\r
+        createFilteredList(contents);\r
+    }\r
+    \r
+    /*\r
+     * @see Dialog#createDialogArea(Composite)\r
+     */\r
+    protected Control createDialogArea(Composite parent) {\r
+        Composite contents = (Composite) super.createDialogArea(parent);\r
+\r
+        createControls(contents);\r
+\r
+        setListElements(elementList.toArray(new Object[elementList.size()]));\r
+\r
+        // Select items\r
+        setSelection(getInitialElementSelections().toArray());\r
+\r
+        // If nothing is selected, select the first element\r
+        //if (getSelectionIndices()==null || getSelectionIndices().length==0)\r
+        //    this.fFilteredList.setSelection(new int[] {0});        \r
+\r
+        return contents;\r
+    }\r
+    \r
+    @Override\r
+    protected void okPressed() {\r
+        super.okPressed();\r
+        for (Object o : getResult())\r
+            addSelection(title, o);\r
+    }\r
+    \r
+    protected static Map<String, List<Integer>> previousSelections =\r
+         new HashMap<String, List<Integer>>();\r
+    \r
+    protected static synchronized int[] getPreviousSelections(String key)\r
+    {\r
+        List<Integer> list = previousSelections.get(key);\r
+        if (list==null) return new int[0];\r
+        int result[] = new int[list.size()];\r
+        for (int i=0; i<list.size(); i++)\r
+            result[i] = list.get(i);\r
+        return result;\r
+    }\r
+    \r
+    protected static synchronized void addSelection(String key, Object o)\r
+    {\r
+        List<Integer> list = previousSelections.get(key);\r
+        if (list==null) {\r
+            list = new ArrayList<Integer>();\r
+            previousSelections.put(key, list);\r
+        }\r
+        int hash = o.hashCode();\r
+        // remove previous\r
+        for (int i=0; i<list.size(); i++)\r
+            if (list.get(i)==hash)\r
+            {\r
+                list.remove(i);\r
+            }\r
+        // Add as first\r
+        list.add(0, o.hashCode());\r
+        \r
+        // remove last\r
+        if (list.size()>REMEMBER_NUM)\r
+            list.remove(list.size()-1);\r
+    }    \r
+    \r
+    public int[] getSelectionIndices() {\r
+        return super.getSelectionIndices();\r
+    }\r
+\r
+    public boolean isUsePreviousSelectionSort() {\r
+        return usePreviousSelectionSort;\r
+    }\r
+\r
+    /**\r
+     * Set usage for sorting of previous selections.\r
+     * When this sorting is enabled, the items that have been selected\r
+     * the items that have been selected previously in this same dialog\r
+     * are prioritized to appear first in the list\r
+     * \r
+     * (Dialogs are distinguished by their title :X)\r
+     * \r
+     * @param usePreviousSelectionSort\r
+     */\r
+    public void setUsePreviousSelectionSort(boolean usePreviousSelectionSort) {\r
+        this.usePreviousSelectionSort = usePreviousSelectionSort;\r
+    }\r
+    \r
+}\r
+\r
+class PrioritizeComparator implements Comparator<Object>\r
+{    \r
+    private final List<Object> prioritizeList;\r
+    private final boolean ignoreCase;\r
+    public PrioritizeComparator(List<Object> prioritizeList, boolean ignoreCase)\r
+    {\r
+        this.prioritizeList = prioritizeList;\r
+        this.ignoreCase = ignoreCase;\r
+    }\r
+    \r
+    public int getIndex(Object o)\r
+    {\r
+        for (int i=0; i<prioritizeList.size(); i++)\r
+            if (o==prioritizeList.get(i))\r
+                return i;\r
+        return Integer.MAX_VALUE/4;\r
+    }\r
+    \r
+    public int compare(Object o1, Object o2) {\r
+        int p1 = getIndex(o1);\r
+        int p2 = getIndex(o2);\r
+        if (p1==p2)            \r
+            return (ignoreCase?o1.toString().compareToIgnoreCase(o2.toString()):o1.toString().compareTo(o2.toString()));     \r
+        \r
+        return p1-p2;\r
+    }\r
+    \r
+}\r