001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 * 
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 * 
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.log4j.lf5.viewer;
018
019import java.awt.Adjustable;
020
021import javax.swing.JComponent;
022import javax.swing.JScrollPane;
023import javax.swing.JTable;
024import javax.swing.ListSelectionModel;
025import javax.swing.SwingUtilities;
026import javax.swing.table.TableModel;
027
028/**
029 * Provides methods to accomplish common yet non-trivial tasks
030 * with Swing. Obvious implementations of these methods have been
031 * tried and failed.
032 *
033 * @author Richard Wan
034 */
035
036// Contributed by ThoughtWorks Inc.
037
038public class LF5SwingUtils {
039  //--------------------------------------------------------------------------
040  //   Constants:
041  //--------------------------------------------------------------------------
042
043  //--------------------------------------------------------------------------
044  //   Protected Variables:
045  //--------------------------------------------------------------------------
046
047  //--------------------------------------------------------------------------
048  //   Private Variables:
049  //--------------------------------------------------------------------------
050
051  //--------------------------------------------------------------------------
052  //   Constructors:
053  //--------------------------------------------------------------------------
054
055  //--------------------------------------------------------------------------
056  //   Public Methods:
057  //--------------------------------------------------------------------------
058
059  /**
060   * Selects a the specified row in the specified JTable and scrolls
061   * the specified JScrollpane to the newly selected row. More importantly,
062   * the call to repaint() delayed long enough to have the table
063   * properly paint the newly selected row which may be offscre
064   * @param table should belong to the specified JScrollPane
065   */
066  public static void selectRow(int row, JTable table, JScrollPane pane) {
067    if (table == null || pane == null) {
068      return;
069    }
070    if (contains(row, table.getModel()) == false) {
071      return;
072    }
073    moveAdjustable(row * table.getRowHeight(), pane.getVerticalScrollBar());
074    selectRow(row, table.getSelectionModel());
075    // repaint must be done later because moveAdjustable
076    // posts requests to the swing thread which must execute before
077    // the repaint logic gets executed.
078    repaintLater(table);
079  }
080
081  /**
082   * Makes the specified Adjustable track if the view area expands and
083   * the specified Adjustable is located near the of the view.
084   */
085  public static void makeScrollBarTrack(Adjustable scrollBar) {
086    if (scrollBar == null) {
087      return;
088    }
089    scrollBar.addAdjustmentListener(new TrackingAdjustmentListener());
090  }
091
092  /**
093   * Makes the vertical scroll bar of the specified JScrollPane
094   * track if the view expands (e.g. if rows are added to an underlying
095   * table).
096   */
097  public static void makeVerticalScrollBarTrack(JScrollPane pane) {
098    if (pane == null) {
099      return;
100    }
101    makeScrollBarTrack(pane.getVerticalScrollBar());
102  }
103
104  //--------------------------------------------------------------------------
105  //   Protected Methods:
106  //--------------------------------------------------------------------------
107  protected static boolean contains(int row, TableModel model) {
108    if (model == null) {
109      return false;
110    }
111    if (row < 0) {
112      return false;
113    }
114    if (row >= model.getRowCount()) {
115      return false;
116    }
117    return true;
118  }
119
120  protected static void selectRow(int row, ListSelectionModel model) {
121    if (model == null) {
122      return;
123    }
124    model.setSelectionInterval(row, row);
125  }
126
127  protected static void moveAdjustable(int location, Adjustable scrollBar) {
128    if (scrollBar == null) {
129      return;
130    }
131    scrollBar.setValue(location);
132  }
133
134  /**
135   * Work around for JTable/viewport bug.
136   * @link http://developer.java.sun.com/developer/bugParade/bugs/4205145.html
137   */
138  protected static void repaintLater(final JComponent component) {
139    SwingUtilities.invokeLater(new Runnable() {
140      public void run() {
141        component.repaint();
142      }
143    });
144  }
145  //--------------------------------------------------------------------------
146  //   Private Methods:
147  //--------------------------------------------------------------------------
148
149  //--------------------------------------------------------------------------
150  //   Nested Top-Level Classes or Interfaces
151  //--------------------------------------------------------------------------
152}
153