]> git.proxmox.com Git - mirror_edk2.git/blobdiff - Tools/Source/FrameworkWizard/src/org/tianocore/frameworkwizard/platform/ui/TableSorter.java
Re-implement sorting algorithm of table and modified FpdFrameworkModules.java to...
[mirror_edk2.git] / Tools / Source / FrameworkWizard / src / org / tianocore / frameworkwizard / platform / ui / TableSorter.java
index 2453f12a1cf91f7dc45acfb440a0fc6f64013169..3f37efb38c6f7f5497a06dbe9e70d551b25e78a4 100644 (file)
@@ -1,11 +1,22 @@
+/** @file
+ The file is used to sort FrameworkModules of Fpd file
+ Copyright (c) 2006, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution.  The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ **/
 package org.tianocore.frameworkwizard.platform.ui;
 
-import java.awt.*;
 import java.awt.event.*;
 import java.util.*;
-import java.util.List;
 
-import javax.swing.*;
 import javax.swing.event.TableModelEvent;
 import javax.swing.event.TableModelListener;
 import javax.swing.table.*;
@@ -17,55 +28,45 @@ public class TableSorter extends AbstractTableModel {
      */
     private static final long serialVersionUID = 1L;
 
-    protected TableModel tableModel;
+    protected DefaultTableModel tableModel;
+    private TableRow[] rowInView;
+    private int[] viewPos;
 
-    public static final int DESCENDING = -1;
-    public static final int NOT_SORTED = 0;
-    public static final int ASCENDING = 1;
-
-    private static Directive EMPTY_DIRECTIVE = new Directive(-1, NOT_SORTED);
-    
-
-    private Row[] viewToModel;
-    private int[] modelToView;
+    public static final String DESCENDING = "down";
+    public static final String NOT_SORTED = "none";
+    public static final String ASCENDING = "up";
 
     private JTableHeader tableHeader;
-    private MouseListener mouseListener;
-    private TableModelListener tableModelListener;
+    private MouseListener mouseListener = new MouseHandler();
+    private TableModelListener tableModelListener = new TableModelHandler();
     
-    private List<Directive> sortingColumns = new ArrayList<Directive>();
-
-    public TableSorter() {
-        this.mouseListener = new MouseHandler();
-        this.tableModelListener = new TableModelHandler();
-    }
+    private HashMap<Integer, String> sortingOrders = new HashMap<Integer, String>();
 
-    public TableSorter(TableModel tableModel) {
-        this();
+    public TableSorter(DefaultTableModel tableModel) {
         setTableModel(tableModel);
     }
 
 
-    private void clearSortingState() {
-        viewToModel = null;
-        modelToView = null;
+    private void resetSortState() {
+        rowInView = null;
+        viewPos = null;
     }
 
-    public TableModel getTableModel() {
+    public DefaultTableModel getTableModel() {
         return tableModel;
     }
 
-    public void setTableModel(TableModel tableModel) {
-        if (this.tableModel != null) {
-            this.tableModel.removeTableModelListener(tableModelListener);
+    public void setTableModel(DefaultTableModel dtm) {
+        if (tableModel != null) {
+            tableModel.removeTableModelListener(tableModelListener);
         }
 
-        this.tableModel = tableModel;
-        if (this.tableModel != null) {
-            this.tableModel.addTableModelListener(tableModelListener);
+        tableModel = dtm;
+        if (tableModel != null) {
+            tableModel.addTableModelListener(tableModelListener);
         }
 
-        clearSortingState();
+        resetSortState();
         fireTableStructureChanged();
     }
 
@@ -73,153 +74,132 @@ public class TableSorter extends AbstractTableModel {
         return tableHeader;
     }
 
-    public void setTableHeader(JTableHeader tableHeader) {
-        if (this.tableHeader != null) {
-            this.tableHeader.removeMouseListener(mouseListener);
-            TableCellRenderer defaultRenderer = this.tableHeader.getDefaultRenderer();
-            if (defaultRenderer instanceof SortableHeaderRenderer) {
-                this.tableHeader.setDefaultRenderer(((SortableHeaderRenderer) defaultRenderer).tableCellRenderer);
-            }
+    public void setTableHeader(JTableHeader th) {
+        if (tableHeader != null) {
+            tableHeader.removeMouseListener(mouseListener);
         }
-        this.tableHeader = tableHeader;
-        if (this.tableHeader != null) {
-            this.tableHeader.addMouseListener(mouseListener);
-            this.tableHeader.setDefaultRenderer(
-                    new SortableHeaderRenderer(this.tableHeader.getDefaultRenderer()));
+        tableHeader = th;
+        if (tableHeader != null) {
+            tableHeader.addMouseListener(mouseListener);
+            
         }
     }
 
-    public boolean isSorting() {
-        return sortingColumns.size() != 0;
-    }
-
-    private Directive getDirective(int column) {
-        for (int i = 0; i < sortingColumns.size(); i++) {
-            Directive directive = (Directive)sortingColumns.get(i);
-            if (directive.column == column) {
-                return directive;
-            }
+    private String getSortState(int column) {
+        Integer i = new Integer(column);
+        if (sortingOrders.get(i) != null) {
+            return sortingOrders.get(i);
         }
-        return EMPTY_DIRECTIVE;
+        return NOT_SORTED;
     }
 
-    public int getSortingStatus(int column) {
-        return getDirective(column).direction;
-    }
-
-    private void sortingStatusChanged() {
-        clearSortingState();
+    private void sortStateChanged() {
+        resetSortState();
         fireTableDataChanged();
-        if (tableHeader != null) {
-            tableHeader.repaint();
-        }
-    }
-
-    public void setSortingStatus(int column, int status) {
-        Directive directive = getDirective(column);
-        if (directive != EMPTY_DIRECTIVE) {
-            sortingColumns.remove(directive);
-        }
-        if (status != NOT_SORTED) {
-            sortingColumns.add(new Directive(column, status));
-        }
-        sortingStatusChanged();
-    }
 
-    protected Icon getHeaderRendererIcon(int column, int size) {
-        Directive directive = getDirective(column);
-        if (directive == EMPTY_DIRECTIVE) {
-            return null;
-        }
-        return new Arrow(directive.direction == DESCENDING, size, sortingColumns.indexOf(directive));
     }
 
-    private void cancelSorting() {
-        sortingColumns.clear();
-        sortingStatusChanged();
+    public void setSortState(int column, String status) {
+        Integer i = new Integer(column);
+        sortingOrders.put(i, status);
+        sortStateChanged();
     }
 
-    private Row[] getViewToModel() {
-        if (viewToModel == null) {
-            int tableModelRowCount = tableModel.getRowCount();
-            viewToModel = new Row[tableModelRowCount];
-            for (int row = 0; row < tableModelRowCount; row++) {
-                viewToModel[row] = new Row(row);
+    private TableRow[] getSortedViewRows() {
+        if (rowInView == null) {
+            int rowCount = tableModel.getRowCount();
+            rowInView = new TableRow[rowCount];
+            int i = 0;
+            while ( i < rowCount ) {
+                rowInView[i] = new TableRow(i);
+                ++i;
             }
 
-            if (isSorting()) {
-                Arrays.sort(viewToModel);
+            if (sortingOrders.size() != 0) {
+                Arrays.sort(rowInView);
             }
         }
-        return viewToModel;
+        return rowInView;
     }
 
-    public int modelIndex(int viewIndex) {
-        return getViewToModel()[viewIndex].modelIndex;
+    public int getModelRowIndex(int viewIndex) {
+        TableRow[] rArray = getSortedViewRows();
+        return rArray[viewIndex].modelIndex;
     }
 
-    public int[] getModelToView() {
-        if (modelToView == null) {
-            int n = getViewToModel().length;
-            modelToView = new int[n];
+    public int[] getViewIndexArray() {
+        if (viewPos == null) {
+            int n = getSortedViewRows().length;
+            viewPos = new int[n];
             for (int i = 0; i < n; i++) {
-                modelToView[modelIndex(i)] = i;
+                viewPos[getModelRowIndex(i)] = i;
             }
         }
-        return modelToView;
+        return viewPos;
     }
 
-    // TableModel interface methods 
+  
 
     public int getRowCount() {
-        return (tableModel == null) ? 0 : tableModel.getRowCount();
+        if (tableModel == null) {
+            return 0;
+        }
+        return tableModel.getRowCount();
     }
 
-    public int getColumnCount() {
-        return (tableModel == null) ? 0 : tableModel.getColumnCount();
+    public String getColumnName(int col) {
+        return tableModel.getColumnName(col);
     }
 
-    public String getColumnName(int column) {
-        return tableModel.getColumnName(column);
+    public int getColumnCount() {
+        if (tableModel == null) {
+            return 0;
+        }
+        return tableModel.getColumnCount();
     }
 
-    public Class<?> getColumnClass(int column) {
-        return tableModel.getColumnClass(column);
+    public Class<?> getColumnClass(int col) {
+        return tableModel.getColumnClass(col);
     }
 
-    public boolean isCellEditable(int row, int column) {
-        return tableModel.isCellEditable(modelIndex(row), column);
+    public boolean isCellEditable(int row, int col) {
+        int modelIndex = getModelRowIndex(row);
+        return tableModel.isCellEditable(modelIndex, col);
     }
 
-    public Object getValueAt(int row, int column) {
-        return tableModel.getValueAt(modelIndex(row), column);
+    public Object getValueAt(int row, int col) {
+        int modelIndex = getModelRowIndex(row);
+        return tableModel.getValueAt(modelIndex, col);
     }
 
-    public void setValueAt(Object aValue, int row, int column) {
-        tableModel.setValueAt(aValue, modelIndex(row), column);
+    public void setValueAt(Object val, int row, int col) {
+        int modelIndex = getModelRowIndex(row);
+        tableModel.setValueAt(val, modelIndex, col);
     }
 
     // Helper classes
     
-    private class Row implements Comparable {
+    private class TableRow implements Comparable {
         private int modelIndex;
 
-        public Row(int index) {
+        public TableRow(int index) {
             this.modelIndex = index;
         }
 
         public int compareTo(Object o) {
             int row1 = modelIndex;
-            int row2 = ((Row) o).modelIndex;
+            int row2 = ((TableRow) o).modelIndex;
+            
+            Iterator<Integer> mapIter = sortingOrders.keySet().iterator();
 
-            for (Iterator it = sortingColumns.iterator(); it.hasNext();) {
-                Directive directive = (Directive) it.next();
-                int column = directive.column;
+            while (mapIter.hasNext()) {
+                
+                Integer column = mapIter.next();
                 Object o1 = tableModel.getValueAt(row1, column);
                 Object o2 = tableModel.getValueAt(row2, column);
 
                 int comparison = 0;
-                // Define null less than everything, except null.
                 if (o1 == null && o2 == null) {
                     comparison = 0;
                 } else if (o1 == null) {
@@ -230,7 +210,10 @@ public class TableSorter extends AbstractTableModel {
                     comparison = o1.toString().compareTo(o2.toString());;
                 }
                 if (comparison != 0) {
-                    return directive.direction == DESCENDING ? -comparison : comparison;
+                    if (getSortState(column.intValue()).equals(DESCENDING)) {
+                        return -comparison;
+                    }
+                    return comparison;
                 }
             }
             return 0;
@@ -239,54 +222,29 @@ public class TableSorter extends AbstractTableModel {
 
     private class TableModelHandler implements TableModelListener {
         public void tableChanged(TableModelEvent e) {
-            // If we're not sorting by anything, just pass the event along.             
-            if (!isSorting()) {
-                clearSortingState();
+            if (sortingOrders.size() != 0) {
+                resetSortState();
                 fireTableChanged(e);
                 return;
             }
-                
-            // If the table structure has changed, cancel the sorting; the             
-            // sorting columns may have been either moved or deleted from             
-            // the model. 
             if (e.getFirstRow() == TableModelEvent.HEADER_ROW) {
-                cancelSorting();
+                
                 fireTableChanged(e);
                 return;
             }
-
-            // We can map a cell event through to the view without widening             
-            // when the following conditions apply: 
-            // 
-            // a) all the changes are on one row (e.getFirstRow() == e.getLastRow()) and, 
-            // b) all the changes are in one column (column != TableModelEvent.ALL_COLUMNS) and,
-            // c) we are not sorting on that column (getSortingStatus(column) == NOT_SORTED) and, 
-            // d) a reverse lookup will not trigger a sort (modelToView != null)
-            //
-            // Note: INSERT and DELETE events fail this test as they have column == ALL_COLUMNS.
-            // 
-            // The last check, for (modelToView != null) is to see if modelToView 
-            // is already allocated. If we don't do this check; sorting can become 
-            // a performance bottleneck for applications where cells  
-            // change rapidly in different parts of the table. If cells 
-            // change alternately in the sorting column and then outside of             
-            // it this class can end up re-sorting on alternate cell updates - 
-            // which can be a performance problem for large tables. The last 
-            // clause avoids this problem. 
             int column = e.getColumn();
             if (e.getFirstRow() == e.getLastRow()
                     && column != TableModelEvent.ALL_COLUMNS
-                    && getSortingStatus(column) == NOT_SORTED
-                    && modelToView != null) {
-                int viewIndex = getModelToView()[e.getFirstRow()];
+                    && getSortState(column).equals(NOT_SORTED)
+                    && viewPos != null) {
+                int viewIndex = getViewIndexArray()[e.getFirstRow()];
                 fireTableChanged(new TableModelEvent(TableSorter.this, 
                                                      viewIndex, viewIndex, 
                                                      column, e.getType()));
                 return;
             }
 
-            // Something has happened to the data that may have invalidated the row order. 
-            clearSortingState();
+            resetSortState();
             fireTableDataChanged();
             return;
         }
@@ -298,105 +256,22 @@ public class TableSorter extends AbstractTableModel {
             TableColumnModel columnModel = h.getColumnModel();
             int viewColumn = columnModel.getColumnIndexAtX(e.getX());
             int column = columnModel.getColumn(viewColumn).getModelIndex();
-            if (column != -1) {
-                int status = getSortingStatus(column);
-                if (!e.isControlDown()) {
-                    cancelSorting();
-                }
-                // Cycle the sorting states through {NOT_SORTED, ASCENDING, DESCENDING} or 
-                // {NOT_SORTED, DESCENDING, ASCENDING} depending on whether shift is pressed. 
-                status = status + (e.isShiftDown() ? -1 : 1);
-                status = (status + 4) % 3 - 1; // signed mod, returning {-1, 0, 1}
-                setSortingStatus(column, status);
-            }
-        }
-    }
-
-    private static class Arrow implements Icon {
-        private boolean descending;
-        private int size;
-        private int priority;
-
-        public Arrow(boolean descending, int size, int priority) {
-            this.descending = descending;
-            this.size = size;
-            this.priority = priority;
-        }
-
-        public void paintIcon(Component c, Graphics g, int x, int y) {
-            Color color = c == null ? Color.GRAY : c.getBackground();             
-            // In a compound sort, make each succesive triangle 20% 
-            // smaller than the previous one. 
-            int dx = (int)(size/2*Math.pow(0.8, priority));
-            int dy = descending ? dx : -dx;
-            // Align icon (roughly) with font baseline. 
-            y = y + 5*size/6 + (descending ? -dy : 0);
-            int shift = descending ? 1 : -1;
-            g.translate(x, y);
-
-            // Right diagonal. 
-            g.setColor(color.darker());
-            g.drawLine(dx / 2, dy, 0, 0);
-            g.drawLine(dx / 2, dy + shift, 0, shift);
-            
-            // Left diagonal. 
-            g.setColor(color.brighter());
-            g.drawLine(dx / 2, dy, dx, 0);
-            g.drawLine(dx / 2, dy + shift, dx, shift);
-            
-            // Horizontal line. 
-            if (descending) {
-                g.setColor(color.darker().darker());
-            } else {
-                g.setColor(color.brighter().brighter());
-            }
-            g.drawLine(dx, 0, 0, 0);
-
-            g.setColor(color);
-            g.translate(-x, -y);
-        }
-
-        public int getIconWidth() {
-            return size;
-        }
-
-        public int getIconHeight() {
-            return size;
-        }
-    }
-
-    private class SortableHeaderRenderer implements TableCellRenderer {
-        private TableCellRenderer tableCellRenderer;
-
-        public SortableHeaderRenderer(TableCellRenderer tableCellRenderer) {
-            this.tableCellRenderer = tableCellRenderer;
-        }
+            if (column == 0) {
+                String status = getSortState(column);
+                
 
-        public Component getTableCellRendererComponent(JTable table, 
-                                                       Object value,
-                                                       boolean isSelected, 
-                                                       boolean hasFocus,
-                                                       int row, 
-                                                       int column) {
-            Component c = tableCellRenderer.getTableCellRendererComponent(table, 
-                    value, isSelected, hasFocus, row, column);
-            if (c instanceof JLabel) {
-                JLabel l = (JLabel) c;
-                l.setHorizontalTextPosition(JLabel.LEFT);
-                int modelColumn = table.convertColumnIndexToModel(column);
-                l.setIcon(getHeaderRendererIcon(modelColumn, l.getFont().getSize()));
+                if (status.equals(ASCENDING)) {
+                    status = DESCENDING;
+                }
+                else if (status.equals(DESCENDING)) {
+                    status = NOT_SORTED;
+                }
+                else if (status.equals(NOT_SORTED)) {
+                    status = ASCENDING;
+                }
+                setSortState(column, status);
             }
-            return c;
         }
     }
 
-    private static class Directive {
-        private int column;
-        private int direction;
-
-        public Directive(int column, int direction) {
-            this.column = column;
-            this.direction = direction;
-        }
-    }
 }