All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jtattoo.plaf.BaseTableHeaderUI Maven / Gradle / Ivy

There is a newer version: 3.1
Show newest version
/*
 * Copyright (c) 2002 and later by MH Software-Entwicklung. All Rights Reserved.
 *  
 * JTattoo is multiple licensed. If your are an open source developer you can use
 * it under the terms and conditions of the GNU General Public License version 2.0
 * or later as published by the Free Software Foundation.
 *  
 * see: gpl-2.0.txt
 * 
 * If you pay for a license you will become a registered user who could use the
 * software under the terms and conditions of the GNU Lesser General Public License
 * version 2.0 or later with classpath exception as published by the Free Software
 * Foundation.
 * 
 * see: lgpl-2.0.txt
 * see: classpath-exception.txt
 * 
 * Registered users could also use JTattoo under the terms and conditions of the 
 * Apache License, Version 2.0 as published by the Apache Software Foundation.
 *  
 * see: APACHE-LICENSE-2.0.txt
 */

package com.jtattoo.plaf;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.util.Enumeration;
import java.util.List;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicTableHeaderUI;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

/**
 *
 * @author Michael Hagen
 */
public class BaseTableHeaderUI extends BasicTableHeaderUI {

  private TableCellRenderer    originalHeaderRenderer;
  protected MouseAdapter       myMouseAdapter       = null;
  protected MouseMotionAdapter myMouseMotionAdapter = null;
  protected int                rolloverCol          = -1;

  public static ComponentUI createUI(JComponent h) {
    return new BaseTableHeaderUI();
  }

  public void installUI(JComponent c) {
    super.installUI(c);
    if (header != null) {
      originalHeaderRenderer = header.getDefaultRenderer();
      if ((originalHeaderRenderer != null) && "sun.swing.table.DefaultTableCellHeaderRenderer".equals(originalHeaderRenderer.getClass().getName())) {
        header.setDefaultRenderer(new BaseDefaultHeaderRenderer());
      }
    }
  }

  public void uninstallUI(JComponent c) {
    if (header != null) {
      if (header.getDefaultRenderer() instanceof BaseDefaultHeaderRenderer) {
        header.setDefaultRenderer(originalHeaderRenderer);
      }
    }
    super.uninstallUI(c);
  }

  public void installListeners() {
    super.installListeners();
    myMouseAdapter = new MouseAdapter() {

      public void mouseReleased(MouseEvent e) {
        if ((header == null) || (header.getTable() == null)) {
          return;
        }
        boolean rolloverEnabled = Boolean.TRUE.equals(header.getClientProperty("rolloverEnabled"));
        boolean sortingAllowed = false;
        if (JTattooUtilities.getJavaVersion() >= 1.6) {
          sortingAllowed = header.getTable().getRowSorter() != null;
        }
        if (rolloverEnabled || sortingAllowed || header.getReorderingAllowed()) {
          final Point pt = e.getPoint();
          SwingUtilities.invokeLater(new Runnable() {

            public void run() {
              if (header.getBounds().contains(pt)) {
                int oldRolloverCol = rolloverCol;
                rolloverCol = header.getTable().columnAtPoint(pt);
                updateRolloverColumn(oldRolloverCol, rolloverCol);
              }
              else {
                int oldRolloverCol = rolloverCol;
                rolloverCol = -1;
                updateRolloverColumn(oldRolloverCol, rolloverCol);
              }
            }
          });
        }
      }

      public void mouseEntered(MouseEvent e) {
        if ((header == null) || (header.getTable() == null)) {
          return;
        }
        boolean rolloverEnabled = Boolean.TRUE.equals(header.getClientProperty("rolloverEnabled"));
        boolean sortingAllowed = false;
        if (JTattooUtilities.getJavaVersion() >= 1.6) {
          sortingAllowed = header.getTable().getRowSorter() != null;
        }
        if (rolloverEnabled || sortingAllowed || header.getReorderingAllowed()) {
          int oldRolloverCol = rolloverCol;
          rolloverCol = header.getTable().columnAtPoint(e.getPoint());
          updateRolloverColumn(oldRolloverCol, rolloverCol);
        }
      }

      public void mouseExited(MouseEvent e) {
        if ((header == null) || (header.getTable() == null)) {
          return;
        }
        boolean rolloverEnabled = Boolean.TRUE.equals(header.getClientProperty("rolloverEnabled"));
        boolean sortingAllowed = false;
        if (JTattooUtilities.getJavaVersion() >= 1.6) {
          sortingAllowed = header.getTable().getRowSorter() != null;
        }
        if (rolloverEnabled || sortingAllowed || header.getReorderingAllowed()) {
          int oldRolloverCol = rolloverCol;
          rolloverCol = -1;
          updateRolloverColumn(oldRolloverCol, rolloverCol);
        }
      }
    };
    myMouseMotionAdapter = new MouseMotionAdapter() {

      public void mouseMoved(MouseEvent e) {
        if ((header == null) || (header.getTable() == null)) {
          return;
        }
        boolean rolloverEnabled = Boolean.TRUE.equals(header.getClientProperty("rolloverEnabled"));
        boolean sortingAllowed = false;
        if (JTattooUtilities.getJavaVersion() >= 1.6) {
          sortingAllowed = header.getTable().getRowSorter() != null;
        }
        if (rolloverEnabled || sortingAllowed || header.getReorderingAllowed()) {
          if (header.getDraggedColumn() == null) {
            int oldRolloverCol = rolloverCol;
            rolloverCol = header.getTable().columnAtPoint(e.getPoint());
            updateRolloverColumn(oldRolloverCol, rolloverCol);
          }
        }
      }

      public void mouseDragged(MouseEvent e) {
        if ((header == null) || (header.getTable() == null)) {
          return;
        }
        boolean rolloverEnabled = Boolean.TRUE.equals(header.getClientProperty("rolloverEnabled"));
        boolean sortingAllowed = false;
        if (JTattooUtilities.getJavaVersion() >= 1.6) {
          sortingAllowed = header.getTable().getRowSorter() != null;
        }
        if (rolloverEnabled || sortingAllowed || header.getReorderingAllowed()) {
          if (header.getDraggedColumn() != null && header.getDraggedColumn().getIdentifier() != null) {
            rolloverCol = header.getColumnModel().getColumnIndex(header.getDraggedColumn().getIdentifier());
          }
          else if (header.getResizingColumn() != null) {
            rolloverCol = -1;
          }
        }
      }
    };
    header.addMouseListener(myMouseAdapter);
    header.addMouseMotionListener(myMouseMotionAdapter);
  }

  public void uninstallListeners() {
    header.removeMouseListener(myMouseAdapter);
    header.removeMouseMotionListener(myMouseMotionAdapter);
    super.uninstallListeners();
  }

  protected boolean drawAlwaysActive() {
    return false;
  }

  protected boolean drawRolloverBar() {
    return false;
  }

  protected Component getHeaderRenderer(int col) {
    if (header == null) {
      return null;
    }
    TableColumn tabCol = header.getColumnModel().getColumn(col);
    TableCellRenderer renderer = tabCol.getHeaderRenderer();
    if (renderer == null) {
      renderer = header.getDefaultRenderer();
    }
    return renderer.getTableCellRendererComponent(header.getTable(), tabCol.getHeaderValue(), false, false, -1, col);
  }

  private int getHeaderHeight() {
    if (header == null) {
      return 0;
    }
    int height = 0;
    boolean accomodatedDefault = false;
    TableColumnModel columnModel = header.getColumnModel();
    for (int column = 0; column < columnModel.getColumnCount(); column++) {
      TableColumn aColumn = columnModel.getColumn(column);
      boolean isDefault = (aColumn.getHeaderRenderer() == null);

      if (!isDefault || !accomodatedDefault) {
        Component comp = getHeaderRenderer(column);
        int rendererHeight = comp.getPreferredSize().height;
        height = Math.max(height, rendererHeight);

        // Configuring the header renderer to calculate its preferred size
        // is expensive. Optimise this by assuming the default renderer
        // always has the same height as the first non-zero height that
        // it returns for a non-null/non-empty value.
        if (isDefault && rendererHeight > 0) {
          Object headerValue = aColumn.getHeaderValue();
          if (headerValue != null) {
            headerValue = headerValue.toString();

            if (headerValue != null && !headerValue.equals("")) {
              accomodatedDefault = true;
            }
          }
        }
      }
    }
    return height + 2;
  }

  /**
   * Return the preferred size of the header. The preferred height is the maximum of the preferred heights of all of the components provided by the
   * header renderers. The preferred width is the sum of the preferred widths of each column (plus inter-cell spacing).
   * 
   * @return the preferredSize
   */
  public Dimension getPreferredSize(JComponent c) {
    if (header == null) {
      return new Dimension(0, 0);
    }
    long width = 0;
    Enumeration enumeration = header.getColumnModel().getColumns();
    while (enumeration.hasMoreElements()) {
      TableColumn aColumn = (TableColumn) enumeration.nextElement();
      width = width + aColumn.getPreferredWidth();
    }
    if (width > Integer.MAX_VALUE) {
      width = Integer.MAX_VALUE;
    }
    return new Dimension((int) width, getHeaderHeight());
  }

  protected void updateRolloverColumn(int oldColumn, int newColumn) {
    if (header == null) {
      return;
    }
    header.repaint(header.getHeaderRect(oldColumn));
    header.repaint(header.getHeaderRect(newColumn));
  }

  protected void rolloverColumnUpdated(int oldColumn, int newColumn) {
    // Empty to avoid multiple paints
  }

  public void paint(Graphics g, JComponent c) {
    if ((header == null) || header.getColumnModel().getColumnCount() <= 0) {
      return;
    }

    boolean ltr = header.getComponentOrientation().isLeftToRight();
    Rectangle clip = g.getClipBounds();
    Point left = clip.getLocation();
    Point right = new Point(clip.x + clip.width - 1, clip.y);
    TableColumnModel cm = header.getColumnModel();
    int cMin = header.columnAtPoint(ltr ? left : right);
    int cMax = header.columnAtPoint(ltr ? right : left);
    // This should never happen.
    if (cMin == -1) {
      cMin = 0;
    }
    // If the table does not have enough columns to fill the view we'll get -1.
    // Replace this with the index of the last column.
    if (cMax == -1) {
      cMax = cm.getColumnCount() - 1;
    }

    TableColumn draggedColumn = header.getDraggedColumn();
    Rectangle cellRect = header.getHeaderRect(ltr ? cMin : cMax);
    int columnWidth;
    TableColumn aColumn;
    if (ltr) {
      for (int column = cMin; column <= cMax; column++) {
        aColumn = cm.getColumn(column);
        columnWidth = aColumn.getWidth();
        cellRect.width = columnWidth;
        if (aColumn != draggedColumn) {
          paintCell(g, cellRect, column);
        }
        cellRect.x += columnWidth;
      }
    }
    else {
      for (int column = cMax; column >= cMin; column--) {
        aColumn = cm.getColumn(column);
        columnWidth = aColumn.getWidth();
        cellRect.width = columnWidth;
        if (aColumn != draggedColumn) {
          paintCell(g, cellRect, column);
        }
        cellRect.x += columnWidth;
      }
    }

    // Paint the dragged column if we are dragging.
    if (draggedColumn != null) {
      int draggedColumnIndex = viewIndexForColumn(draggedColumn);
      Rectangle draggedCellRect = header.getHeaderRect(draggedColumnIndex);
      // Draw a gray well in place of the moving column.
      g.setColor(header.getParent().getBackground());
      g.fillRect(draggedCellRect.x, draggedCellRect.y, draggedCellRect.width, draggedCellRect.height);
      draggedCellRect.x += header.getDraggedDistance();

      // Fill the background.
      g.setColor(header.getBackground());
      g.fillRect(draggedCellRect.x, draggedCellRect.y, draggedCellRect.width, draggedCellRect.height);
      paintCell(g, draggedCellRect, draggedColumnIndex);
    }

    // Remove all components in the rendererPane.
    rendererPane.removeAll();
  }

  protected void paintBackground(Graphics g, Rectangle cellRect, int col) {
    Component component = getHeaderRenderer(col);
    int x = cellRect.x;
    int y = cellRect.y;
    int w = cellRect.width;
    int h = cellRect.height;
    if (header.getBackground() instanceof ColorUIResource) {
      if ((col == rolloverCol) && (component != null) && component.isEnabled()) {
        JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getRolloverColors(), x, y, w, h);
      }
      else if (drawAlwaysActive() || JTattooUtilities.isFrameActive(header)) {
        JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getColHeaderColors(), x, y, w, h);
      }
      else {
        JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getInActiveColors(), x, y, w, h);
      }
    }
    else {
      g.setColor(header.getBackground());
      g.fillRect(x, y, w, h);
    }
  }

  protected void paintCell(Graphics g, Rectangle cellRect, int col) {
    if (header == null) {
      return;
    }
    Component component = getHeaderRenderer(col);
    if (!(component instanceof BaseDefaultHeaderRenderer)) {
      paintBackground(g, cellRect, col);
    }
    rendererPane.paintComponent(g, component, header, cellRect.x, cellRect.y, cellRect.width, cellRect.height, true);
  }

  private int viewIndexForColumn(TableColumn aColumn) {
    if (header == null) {
      return -1;
    }
    TableColumnModel cm = header.getColumnModel();
    for (int column = 0; column < cm.getColumnCount(); column++) {
      if (cm.getColumn(column) == aColumn) {
        return column;
      }
    }
    return -1;
  }

  // ----------------------------------------------------------------------------------------------------------------------
  // inner classes
  // ----------------------------------------------------------------------------------------------------------------------
  private class BaseDefaultHeaderRenderer extends DefaultTableCellRenderer {

    public BaseDefaultHeaderRenderer() {
      super();
    }

    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
      return new MyRenderComponent(table, value, isSelected, hasFocus, row, column);
    }
  }

  private class MyRenderComponent extends JLabel {

    private JTable table = null;
    private int    col   = 0;

    public MyRenderComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
      super();
      this.table = table;
      this.col = col;
      if (value != null) {
        setText(value.toString());
      }
      else {
        setText("");
      }
      setOpaque(false);
      if (table != null && table.getClientProperty("TableHeader.font") != null) {
        setFont((Font) table.getClientProperty("TableHeader.font"));
      }
      else {
        setFont(UIManager.getFont("TableHeader.font"));
      }
      if (col == rolloverCol) {
        setForeground(AbstractLookAndFeel.getTheme().getRolloverForegroundColor());
      }
      else {
        setForeground(UIManager.getColor("TableHeader.foreground"));
      }
      setHorizontalAlignment(JLabel.CENTER);
      setHorizontalTextPosition(SwingConstants.LEADING);
      setBorder(UIManager.getBorder("TableHeader.cellBorder"));
      if (table != null && (JTattooUtilities.getJavaVersion() >= 1.6) && (UIManager.getLookAndFeel() instanceof AbstractLookAndFeel)) {
        RowSorter rowSorter = table.getRowSorter();
        List keyList = rowSorter == null ? null : rowSorter.getSortKeys();
        if ((keyList != null) && (keyList.size() > 0)) {
          RowSorter.SortKey sortKey = (RowSorter.SortKey) keyList.get(0);
          if (sortKey.getColumn() == table.convertColumnIndexToModel(col)) {
            AbstractIconFactory iconFactory = ((AbstractLookAndFeel) UIManager.getLookAndFeel()).getIconFactory();
            if (sortKey.getSortOrder().equals(SortOrder.ASCENDING)) {
              setIcon(iconFactory.getUpArrowIcon());
            }
            else if (sortKey.getSortOrder().equals(SortOrder.DESCENDING)) {
              setIcon(iconFactory.getDownArrowIcon());
            }
          }
        }
      }
    }

    protected void paintBackground(Graphics g) {
      // BugFix: 12.12.2013
      // Currently I don't know why header is sometimes null, but if it's null it's better to ignore
      // the background instead of throwing a NPE.
      if (header == null) {
        JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getColHeaderColors(), 0, 0, getWidth(), getHeight());
        return;
      }
      int draggedColumn = -1;
      if (header.getTable() != null && header.getDraggedColumn() != null) {
        draggedColumn = header.getColumnModel().getColumnIndex(header.getDraggedColumn().getIdentifier());
      }
      int w = getWidth();
      int h = getHeight();
      if ((table != null) && table.isEnabled() && (col == rolloverCol || col == draggedColumn)) {
        JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getRolloverColors(), 0, 0, w, h);
        if (drawRolloverBar()) {
          g.setColor(AbstractLookAndFeel.getFocusColor());
          g.drawLine(0, 0, w - 1, 0);
          g.drawLine(0, 1, w - 1, 1);
          g.drawLine(0, 2, w - 1, 2);
        }
      }
      else if (drawAlwaysActive() || JTattooUtilities.isFrameActive(header)) {
        if (header.getBackground() instanceof ColorUIResource) {
          JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getColHeaderColors(), 0, 0, w, h);
        }
        else {
          g.setColor(header.getBackground());
          g.fillRect(0, 0, w, h);
        }
      }
      else {
        if (header.getBackground() instanceof ColorUIResource) {
          JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getInActiveColors(), 0, 0, w, h);
        }
        else {
          g.setColor(header.getBackground());
          g.fillRect(0, 0, w, h);
        }
      }
    }

    public void paint(Graphics g) {
      paintBackground(g);
      super.paint(g);
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy