Package net.helipilot50.stocktrade.displayproject

Source Code of net.helipilot50.stocktrade.displayproject.TableSorter$SortableHeaderRenderer

/*
Copyright (c) 2003-2009 ITerative Consulting Pty Ltd. All Rights Reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted
provided that the following conditions are met:

o Redistributions of source code must retain the above copyright notice, this list of conditions and
the following disclaimer.
 
o Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the distribution.
   
o This jcTOOL Helper Class software, whether in binary or source form may not be used within,
or to derive, any other product without the specific prior written permission of the copyright holder

 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


*/
package net.helipilot50.stocktrade.displayproject;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Polygon;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;

import net.helipilot50.stocktrade.displayproject.binding.ListViewTableModel;
import net.helipilot50.stocktrade.displayproject.controls.ListView;
import net.helipilot50.stocktrade.displayproject.events.ClientEventManager;
import net.helipilot50.stocktrade.framework.DynamicArray;
import net.helipilot50.stocktrade.framework.DynamicArrayListener;
import net.helipilot50.stocktrade.framework.ErrorMgr;
import net.helipilot50.stocktrade.framework.ParameterHolder;
import net.helipilot50.stocktrade.framework.UsageException;



/**
* TableSorter is a decorator for TableModels; adding sorting
* functionality to a supplied TableModel. TableSorter does
* not store or copy the data in its TableModel; instead it maintains
* a map from the row indexes of the view to the row indexes of the
* model. As requests are made of the sorter (like getValueAt(row, col))
* they are passed to the underlying model after the row numbers
* have been translated via the internal mapping array. This way,
* the TableSorter appears to hold another copy of the table
* with the rows in a different order.
* <p/>
* TableSorter registers itself as a listener to the underlying model,
* just as the JTable itself would. Events recieved from the model
* are examined, sometimes manipulated (typically widened), and then
* passed on to the TableSorter's listeners (typically the JTable).
* If a change to the model has invalidated the order of TableSorter's
* rows, a note of this is made and the sorter will resort the
* rows the next time a value is requested.
* <p/>
* When the tableHeader property is set, either by using the
* setTableHeader() method or the two argument constructor, the
* table header may be used as a complete UI for TableSorter.
* The default renderer of the tableHeader is decorated with a renderer
* that indicates the sorting status of each column. In addition,
* a mouse listener is installed with the following behavior:
* <ul>
* <li>
* Mouse-click: Clears the sorting status of all other columns
* and advances the sorting status of that column through three
* values: {NOT_SORTED, ASCENDING, DESCENDING} (then back to
* NOT_SORTED again).
* <li>
* SHIFT-mouse-click: Clears the sorting status of all other columns
* and cycles the sorting status of the column through the same * three values, in the opposite order: {NOT_SORTED, DESCENDING, ASCENDING}.
* <li>
* CONTROL-mouse-click and CONTROL-SHIFT-mouse-click: as above except
* that the changes to the column do not cancel the statuses of columns
* that are already sorting - giving a way to initiate a compound
* sort.
* </ul>
* <p/>
* This is a long overdue rewrite of a class of the same name that
* first appeared in the swing table demos in 1997.
*
* @author Philip Milne
* @author Brendon McLean
* @author Dan van Enckevort
* @author Parwinder Sekhon
* @version 2.0 02/27/04
*/
@SuppressWarnings({"serial", "unchecked"})
public class TableSorter extends AbstractTableModel {
    private boolean sortToggle = true;

    private ListView parent;

    protected TableModel tableModel;

    public static final int DESCENDING = -1;
    public static final int NOT_SORTED = 0;
    public static final int ASCENDING = 1;

    protected static Directive EMPTY_DIRECTIVE = new Directive(-1, NOT_SORTED);

    public static final Comparator<Comparable<?>> COMPARABLE_COMAPRATOR = new Comparator<Comparable<?>>() {
        public int compare(Comparable<?> o1, Comparable<?> o2) {
            return ((Comparable) o1).compareTo(o2);
        }
    };
    public static final Comparator<Object> LEXICAL_COMPARATOR = new Comparator<Object>() {
        public int compare(Object o1, Object o2) {
            return o1.toString().compareTo(o2.toString());
        }
    };

    private Row[] viewToModel;
    private int[] modelToView;

    private JTableHeader tableHeader;
    private MouseListener mouseListener;
    private TableModelListener tableModelListener;
    private Map<Class<?>, Comparator<?>> columnComparators = new HashMap<Class<?>, Comparator<?>>();
    private List<Directive> sortingColumns = new ArrayList<Directive>();

    /**
     * suppress sorting (don't allow any sorting)
     */
    private boolean suppressSort;

    /**
     * Only post the "RequestSort" event, don't actually do the sort.
     * CraigM:20/08/2008.
     */
    private boolean overrideSort;

  private boolean synchroniseDataModelAfterSorting = false;

    public TableSorter() {
        this.mouseListener = new MouseHandler();
        this.tableModelListener = new TableModelHandler();
    }

    public TableSorter(TableModel tableModel) {
        this();
        setTableModel(tableModel);
    }

    public TableSorter(TableModel tableModel, JTableHeader tableHeader) {
        this();
        setTableHeader(tableHeader);
        setTableModel(tableModel);
    }

    private void clearSortingState() {
        viewToModel = null;
        modelToView = null;
    }

    public TableModel getTableModel() {
        return tableModel;
    }

    public void setTableModel(TableModel tableModel) {
        if (this.tableModel != null) {
            this.tableModel.removeTableModelListener(tableModelListener);
        }

        this.tableModel = tableModel;
        if (this.tableModel != null) {
            this.tableModel.addTableModelListener(tableModelListener);
        }

        clearSortingState();
        fireTableStructureChanged();
    }

    public JTableHeader getTableHeader() {
        return tableHeader;
    }

    public void setTableHeader(JTableHeader tableHeader) {
        if (this.tableHeader != null) {
        if (!this.suppressSort)
          this.tableHeader.removeMouseListener(mouseListener);
            TableCellRenderer defaultRenderer = this.tableHeader.getDefaultRenderer();
            if (defaultRenderer instanceof SortableHeaderRenderer) {
                this.tableHeader.setDefaultRenderer(((SortableHeaderRenderer) defaultRenderer).tableCellRenderer);
            }
        }
        this.tableHeader = tableHeader;
        if (this.tableHeader != null) {
          if (!this.suppressSort)
            this.tableHeader.addMouseListener(mouseListener);
            this.tableHeader.setDefaultRenderer(
                    new SortableHeaderRenderer(this.tableHeader.getDefaultRenderer()));
        }
    }

    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;
            }
        }
        return EMPTY_DIRECTIVE;
    }

    public int getSortingStatus(int column) {
        return getDirective(column).direction;
    }

    private void sortingStatusChanged() {
      // TF:04/05/2009:After we change the sort criteria, we want to keep the same row selected.
    int selectedRow = this.parent.getSelectedRow()-1// Compensate for 1-based index...
    int selectedModelIndex = selectedRow >= 0 ? this.modelIndex(selectedRow) : -1;

        clearSortingState();
        fireTableDataChanged();
       
    // Restore the selected row
        if (selectedModelIndex >= 0) {
          int newViewSelection = this.viewIndex(selectedModelIndex);
      this.parent.getSelectionModel().setSelectionInterval(newViewSelection, newViewSelection);
    }
   
        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 setColumnComparator(Class<?> type, Comparator<?> comparator) {
        if (comparator == null) {
            columnComparators.remove(type);
        } else {
            columnComparators.put(type, comparator);
        }
    }

    protected Comparator<?> getComparator(int column) {
        Class<?> columnType = tableModel.getColumnClass(column);
        Comparator<?> comparator = columnComparators.get(columnType);
        if (comparator != null) {
            return comparator;
        }
        if (Comparable.class.isAssignableFrom(columnType)) {
            return COMPARABLE_COMAPRATOR;
        }
        return LEXICAL_COMPARATOR;
    }

    private Row[] getViewToModel() {
        // If we leave the viewToModel in there, exceptions can be thrown as this does not seem to
        // recompute the number of rows if the underlying data model changes.

    if (viewToModel == null || tableModel.getRowCount() > viewToModel.length) {
            int tableModelRowCount = tableModel.getRowCount();
            viewToModel = new Row[tableModelRowCount];
            for (int row = 0; row < tableModelRowCount; row++) {
                viewToModel[row] = new Row(row);
            }

            if (isSorting()) {
                Arrays.sort(viewToModel);
               
                if (synchroniseDataModelAfterSorting) {
          DynamicArray<Object> tableData = ((ListViewTableModel)tableModel).getData();
          DynamicArray<Object> oldDataClone = (DynamicArray<Object>) tableData.clone();
         
          //remove all listeners to avoid UI updates and add them after data model sync
          Vector<DynamicArrayListener> listeners = tableData.getListeners();
          ArrayList<DynamicArrayListener> listenersCache = new ArrayList<DynamicArrayListener>(listeners.size());
          listenersCache.addAll(listeners);
          listeners.clear();

          //clear current table data array
          tableData.clear();
         
          //data model for list need to be synchronised as well
          DefaultListModel listModel = (DefaultListModel)parent.getList().getModel();
          listModel.clear();
         
          //add elements to data arrays in sorted order
          for (int i = 0; i < viewToModel.length; i++) {
            Object node = oldDataClone.get(viewToModel[i].modelIndex);
            tableData.add(node);
            listModel.addElement(node);
          }
         
          //restore listeners
          listeners.addAll(listenersCache);

          //update indexes to get proper support of Table sorter
          viewToModel = new Row[tableModelRowCount];
          for (int row = 0; row < tableModelRowCount; row++) {
            viewToModel[row] = new Row(row);
          }

          //notify that sorting was complete
                    Hashtable<String, ParameterHolder> qq_Params = new Hashtable<String, ParameterHolder>();
                    qq_Params.put( "eventInfo", new ParameterHolder(new DisplayEvent()));
                    ClientEventManager.postEvent(parent, "AfterRequestSort", qq_Params);
        }
            }
        }
        return viewToModel;
    }

    public int viewIndex(int modelIndex) {
        Row[] results = getViewToModel();

        for (int i = 0; i < results.length; i++) {
            if (results[i].modelIndex == modelIndex)
                return i;
        }
        UsageException errorVar = new UsageException("modelIndex must be in the range [0->" + (results.length-1) + "]. The value passed was: "+ modelIndex);
        ErrorMgr.addError(errorVar);
        throw errorVar;
    }

    public int modelIndex(int viewIndex) {
        Row []results = getViewToModel();
        if (viewIndex >= 0 && viewIndex < results.length) {
            return results[viewIndex].modelIndex;
        }
        else {
            UsageException errorVar = new UsageException("viewIndex must be in the range [0->" + (results.length-1) + "]. The value passed was: "+ viewIndex);
            ErrorMgr.addError(errorVar);
            throw errorVar;
        }
    }

    private int[] getModelToView() {
        if (modelToView == null) {
            int n = getViewToModel().length;
            modelToView = new int[n];
            for (int i = 0; i < n; i++) {
                modelToView[modelIndex(i)] = i;
            }
        }
        return modelToView;
    }

    // TableModel interface methods

    public int getRowCount() {
        return (tableModel == null) ? 0 : tableModel.getRowCount();
    }

    public int getColumnCount() {
        return (tableModel == null) ? 0 : tableModel.getColumnCount();
    }

    public String getColumnName(int column) {
        return tableModel.getColumnName(column);
    }

    public Class<?> getColumnClass(int column) {
        return tableModel.getColumnClass(column);
    }

    public void setSortToggle(boolean sortToggle) {
    this.sortToggle = sortToggle;
  }
   
    public boolean isCellEditable(int row, int column) {
        return tableModel.isCellEditable(modelIndex(row), column);
    }

    public Object getValueAt(int row, int column) {
        return tableModel.getValueAt(modelIndex(row), column);
    }

    public void setValueAt(Object aValue, int row, int column) {
        tableModel.setValueAt(aValue, modelIndex(row), column);
    }
   
    public void sortColumn(int column, int status){
        cancelSorting();
        setSortingStatus(column, status);
    }

    //Wrapper method for the ArrayListModel
    public DisplayNode getRow(int rowIndex) {
        return ((ArrayFieldModel)tableModel).getRow(rowIndex);
    }

    //Wrapper method for the ArrayListModel
    public DisplayNode getCurrentRow() {
        return ((ArrayFieldModel)tableModel).getCurrentRow();
    }

    //Wrapper method for the ArrayListModel
    public void setCurrentRow(DisplayNode pNode) {
        ((ArrayFieldModel)tableModel).setCurrentRow(pNode);
    }

    /**
     * Select the row in the associated table that corresponds to <code>pNode</code>.
     * @param pNode
     */
    public void selectRow(DisplayNode pNode) {
      //TODO [Arch] DK: the method selectRow(DisplayNode) should be moved outside of TableSorter.
      //Because the TableSorter is a model of ListView component and
      //the class should not change selection and iterate directly to the table
     
      getViewToModel();// DK:24/02/2009: the request of getViewToModel() is forcing current sort to be applied. We need it to get correct model index after sorting.
        int modelIndex = ((ArrayFieldModel)tableModel).getRowIndex(pNode);
        if (modelIndex > -1) {
            int rowIndex = viewIndex(modelIndex);
            if (rowIndex > -1) {
                // ((ArrayFieldModel)tableModel).table.setRowSelectionInterval(rowIndex, rowIndex);
              // DK:24/02/2009:select the row and scroll to ensure the row is currently visible in ScrollPane
              final JTable table = ((ArrayFieldModel)tableModel).table;
        table.setAutoscrolls(true);
                table.changeSelection(rowIndex, table.getSelectedColumn(), false, false);
                table.setAutoscrolls(false);
            }
        }
    }

    // Helper classes

    private class Row implements Comparable<Object> {
        private int modelIndex = 0;

        public Row(int index) {
            this.modelIndex = index;
        }

    public int compareTo(Object o) {
            int row1 = modelIndex;
            int row2 = ((Row) o).modelIndex;

            for (Directive directive : sortingColumns) {
                int column = directive.column;
                Object o1 = tableModel.getValueAt(row1, column);
                Object o2 = tableModel.getValueAt(row2, column);

                // TF:25/7/07: If we attempt to sort column 0 of a list view, we'll get back the DisplayNode subclass,
                // as the Aligned cell renderer is expecting this in order to display the correct icon. So, to counteract
                // this we actually get the real value if this is the case
                if (tableModel instanceof ListViewTableModel) {
                    if (o1 instanceof DisplayNode) {
                        o1 = ((ListViewTableModel)tableModel).getValue(o1, 0);
                    }
                    if (o2 instanceof DisplayNode) {
                        o2 = ((ListViewTableModel)tableModel).getValue(o2, 0);
                    }
                }

                int comparison = 0;
                // Define null less than everything, except null.
                if (o1 == null && o2 == null) {
                    comparison = 0;
                } else if (o1 == null) {
                    comparison = -1;
                } else if (o2 == null) {
                    comparison = 1;
                } else {
                    // Old code
                    // comparison = getComparator(column).compare(o1, o2);

                    if (o1 instanceof Comparable && o2 instanceof Comparable) {
                        comparison = ((Comparable)o1).compareTo(o2);
                    }
                    else {
                        comparison = o1.toString().compareTo(o2.toString());
                    }
                }
                if (comparison != 0) {
                    return directive.direction == DESCENDING ? -comparison : comparison;
                }
            }
            return 0;
        }
       
        @Override
        public String toString() {
          return "Row for " + this.modelIndex;
        }
    }

    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();
                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()];
                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();
            fireTableDataChanged();
            return;
        }
    }

    public void setParent(ListView pParent) {
        this.parent = pParent;
    }

    private class MouseHandler extends MouseAdapter {
        public void mouseClicked(MouseEvent e) {
            JTableHeader h = (JTableHeader) e.getSource();
            TableColumnModel columnModel = h.getColumnModel();
            int viewColumn = columnModel.getColumnIndexAtX(e.getX());
//            FIC:DC If user clicks to right of last col. viewcol = -1
            if (viewColumn != -1) {
                int column = columnModel.getColumn(viewColumn).getModelIndex();
                if (column != -1) {
                    int status = getSortingStatus(column);
                   
                    // Cycle the sorting states through {NOT_SORTED, ASCENDING, DESCENDING} or
                    // {NOT_SORTED, DESCENDING, ASCENDING} depending on whether shift is pressed.
                    if (sortToggle){
                        status = status + (e.isShiftDown() ? -1 : 1);
                        status = (status + 4) % 3 - 1; // signed mod, returning {-1, 0, 1}
                    }

                    if (!overrideSort) {
                      if (!e.isControlDown()) {
                          cancelSorting();
                      }
                      setSortingStatus(column, status);
                    }

                    Hashtable<String, ParameterHolder> qq_Params = new Hashtable<String, ParameterHolder>();
                    qq_Params.put( "eventInfo", new ParameterHolder(new DisplayEvent()));
                    // TF:10/04/2008: Corrected the modifier parameter
                    qq_Params.put( "status", new ParameterHolder(status));
                    int mod = e.getModifiers();
                    int modifiers = 0;
                    if ((mod & ActionEvent.CTRL_MASK) > 0) {
                        modifiers = modifiers | Constants.KM_CTRL;
                    }
                    if ((mod & ActionEvent.SHIFT_MASK) > 0) {
                        modifiers = modifiers | Constants.KM_SHIFT;
                    }
                    if ((mod & ActionEvent.ALT_MASK) > 0) {
                        modifiers = modifiers | Constants.KM_ALT_OPTION;
                    }
                    if ((mod & ActionEvent.META_MASK) > 0) {
                        modifiers = modifiers | Constants.KM_CMD;
                    }
                    qq_Params.put( "modifier", new ParameterHolder(status));
                    qq_Params.put( "column", new ParameterHolder(column+1));
                    ClientEventManager.postEvent(parent, "RequestSort", qq_Params);
                }
            }
        }
    }


    private static class Arrow implements Icon {
        private boolean descending;
        private int size = 0;
        private int priority = 0;

        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) {
            // 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 = dx;
            // Align icon (roughly) with font baseline.
            y += size-dy-3;
            Polygon triangle = new Polygon();

            // TF: 14/2/07 changed the icons to have similar behaviour to windows explorer
            if (!descending) {
                triangle.addPoint(x, y+dy);
                triangle.addPoint(x+dx, y+dy);
                triangle.addPoint(x+(dx/2), y);
            }
            else {
                triangle.addPoint(x, y);
                triangle.addPoint(x+dx, y);
                triangle.addPoint(x+(dx/2), y+dy);
            }
            g.setColor(Color.BLACK);
            g.drawPolygon(triangle);
            g.fillPolygon(triangle);
        }

        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;
        }

        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;
                TableCellRenderer cellRenderer = table.getCellRenderer(row, column);

                if(cellRenderer instanceof DefaultTableCellRenderer){
                    l.setHorizontalAlignment((((DefaultTableCellRenderer)cellRenderer).getHorizontalAlignment()));
                }
                else {
                    // TF:21/11/07:Allowed the table sorter to handle the alignment of
                    // the text for the column model
                    TableColumn tableColumn = table.getColumnModel().getColumn(column);
                    if (tableColumn instanceof ArrayColumn) {
                        int alignment = ((ArrayColumn)tableColumn).getAlignment();
                        l.setHorizontalAlignment(UIutils.forteAlignmentToJava(alignment));
                    }
                }
                l.setHorizontalTextPosition(JLabel.LEFT);

                int modelColumn = table.convertColumnIndexToModel(column);
                l.setIcon(getHeaderRendererIcon(modelColumn, l.getFont().getSize()));
            }
            return c;
        }
    }

    public int getSortColumn() {
        if (sortingColumns.size() != 0) {
            Directive dir = (Directive)(sortingColumns.get(0));
            return dir.column;
        }
        return 0;
    }

    public int getSortDirection() {
        if (sortingColumns.size() != 0) {
            Directive dir = (Directive)(sortingColumns.get(0));
            return dir.direction;
        }
        return 0;
    }

    private static class Directive {
        private int column = 0;
        private int direction = 0;

        public Directive(int column, int direction) {
            this.column = column;
            this.direction = direction;
        }
    }

  public boolean isSuppressSort() {
    return suppressSort;
  }

  public void setSuppressSort(boolean suppressSort) {
    this.suppressSort = suppressSort;
    if (this.suppressSort){
      this.tableHeader.removeMouseListener(this.mouseListener);
    } else {
      this.tableHeader.addMouseListener(this.mouseListener);
    }
  }
   
  public void setOverrideSort() {
    this.overrideSort = true;
  }

  /**
   * Defines whether data model of the table need to be rearranged in sorted way after sorting.
   * The option is true by default.
   * @param synchroniseDataModelAfterSorting true to force sync
   */
  public void setSynchroniseDataModelAfterSorting(boolean synchroniseDataModelAfterSorting) {
    this.synchroniseDataModelAfterSorting = synchroniseDataModelAfterSorting;
  }
 
  public boolean isSynchroniseDataModelAfterSorting() {
    return synchroniseDataModelAfterSorting;
  }
}
TOP

Related Classes of net.helipilot50.stocktrade.displayproject.TableSorter$SortableHeaderRenderer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.