View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17
    18  package org.apache.log4j.chainsaw;
    19
    20  import org.apache.log4j.chainsaw.helper.SwingHelper;
    21
    22  import javax.swing.JTable;
    23  import javax.swing.table.JTableHeader;
    24  import javax.swing.table.TableColumnModel;
    25  import java.awt.Color;
    26  import java.awt.event.InputEvent;
    27  import java.awt.event.MouseEvent;
    28  import java.awt.event.MouseListener;
    29
    30
    31  /**
    32   * A Sortable JTable implementation that allows a user to click on a
    33   * specific Column and have the row information sorted by that column.
    34   *
    35   * @author Claude Duguay
    36   * @author Scott Deboy &lt;sdeboy@apache.org&gt;
    37   */
    38  public class JSortTable extends JTable implements MouseListener {
    39      protected int sortedColumnIndex = -1;
    40      protected boolean sortedColumnAscending = true;
    41      private String sortedColumn;
    42      private int lastSelectedColumn = -1;
    43
    44      public JSortTable(SortTableModel model) {
    45          super(model);
    46          initSortHeader();
    47      }
    48
    49      public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
    50          //selection of the msg field causes rendering to flash...skip over it
    51          int colToSelect = columnIndex;
    52          //CHAINSAW columns are 1-based indexes
    53          if (columnIndex + 1 == ChainsawColumns.INDEX_MESSAGE_COL_NAME) {
    54              colToSelect = lastSelectedColumn < columnIndex ? columnIndex + 1 : columnIndex - 1;
    55              super.changeSelection(rowIndex, colToSelect, toggle, extend);
    56          } else {
    57              super.changeSelection(rowIndex, columnIndex, toggle, extend);
    58          }
    59          lastSelectedColumn = colToSelect;
    60      }
    61
    62      protected void initSortHeader() {
    63          JTableHeader header = getTableHeader();
    64          header.setBackground(Color.WHITE);
    65          header.setDefaultRenderer(new SortHeaderRenderer());
    66          header.addMouseListener(this);
    67      }
    68
    69      public int getSortedColumnIndex() {
    70          return sortedColumnIndex;
    71      }
    72
    73      public void updateSortedColumn() {
    74          if (sortedColumn != null) {
    75              try {
    76                  sortedColumnIndex = columnModel.getColumnIndex(sortedColumn);
    77                  getTableHeader().resizeAndRepaint();
    78              } catch (IllegalArgumentException ie) {//nothing...column is not in the model
    79                  setSortedColumnIndex(-1);
    80              }
    81          }
    82      }
    83
    84      public void setSortedColumnIndex(int index) {
    85          sortedColumnIndex = index;
    86          if (sortedColumnIndex > -1) {
    87              SortTableModel model = (SortTableModel) getModel();
    88              model.sortColumn(sortedColumnIndex, sortedColumnAscending);
    89          }
    90          getTableHeader().resizeAndRepaint();
    91      }
    92
    93      //Allow synchronous updates if already on the EDT
    94      private void scrollTo(final int row, final int col) {
    95          SwingHelper.invokeOnEDT(() -> {
    96              final int currentRow = getSelectedRow();
    97              if ((row > -1) && (row < getRowCount())) {
    98                  try {
    99                      //get the requested row off of the bottom and top of the screen by making the 5 rows around the requested row visible
    100                     //if new past current row, scroll to display the 20th row past new selected row
    101                     scrollRectToVisible(getCellRect(row, col, true));
    102                     if (row > currentRow) {
    103                         scrollRectToVisible(getCellRect(row + 5, col, true));
    104                     }
    105                     if (row < currentRow) {
    106                         scrollRectToVisible(getCellRect(row - 5, col, true));
    107                     }
    108                     scrollRectToVisible(getCellRect(row, col, true));
    109                     setRowSelectionInterval(row, row);
    110                 } catch (IllegalArgumentException iae) {
    111                     //ignore..out of bounds
    112                 }
    113             }
    114         });
    115     }
    116
    117     public void scrollToRow(int row) {
    118         scrollTo(row, columnAtPoint(getVisibleRect().getLocation()));
    119     }
    120
    121     public boolean isSortedColumnAscending() {
    122         return sortedColumnAscending;
    123     }
    124
    125     public void mouseClicked(MouseEvent event) {
    126
    127         if (event.getClickCount() < 2 || event.isPopupTrigger()) {
    128             return;
    129         } else if (event.getClickCount() > 1 && ((event.getModifiers() & InputEvent.BUTTON2_MASK) > 0)) {
    130             return;
    131         }
    132
    133         TableColumnModel colModel = getColumnModel();
    134         int index = colModel.getColumnIndexAtX(event.getX());
    135         int modelIndex = colModel.getColumn(index).getModelIndex();
    136         SortTableModel model = (SortTableModel) getModel();
    137
    138         if (model.isSortable(modelIndex)) {
    139             // toggle ascension, if already sorted
    140             if (sortedColumnIndex == index) {
    141                 sortedColumnAscending = !sortedColumnAscending;
    142             }
    143
    144             sortedColumnIndex = index;
    145             sortedColumn = colModel.getColumn(index).getHeaderValue().toString();
    146             model.sortColumn(modelIndex, sortedColumnAscending);
    147             getTableHeader().resizeAndRepaint();
    148         }
    149     }
    150
    151     public void mousePressed(MouseEvent event) {
    152     }
    153
    154     public void mouseReleased(MouseEvent event) {
    155     }
    156
    157     public void mouseEntered(MouseEvent event) {
    158     }
    159
    160     public void mouseExited(MouseEvent event) {
    161     }
    162 }