Advertisement
Guest User

RelativePainterHighlighter.java

a guest
Aug 18th, 2014
149
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 14.83 KB | None | 0 0
  1. /*
  2.   * $Id$
  3.   *
  4.   * Copyright 2009 Sun Microsystems, Inc., 4150 Network Circle,
  5.   * Santa Clara, California 95054, U.S.A. All rights reserved.
  6.   *
  7.   * This library is free software; you can redistribute it and/or
  8.   * modify it under the terms of the GNU Lesser General Public
  9.   * License as published by the Free Software Foundation; either
  10.   * version 2.1 of the License, or (at your option) any later version.
  11.   *  
  12.   * This library is distributed in the hope that it will be useful,
  13.   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.   * Lesser General Public License for more details.
  16.   *  
  17.   * You should have received a copy of the GNU Lesser General Public
  18.   * License along with this library; if not, write to the Free Software
  19.   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  20.   *
  21.   */
  22.  package org.jdesktop.swingxset.util;
  23.  
  24.  import java.awt.Component;
  25.  import java.awt.Graphics2D;
  26.  import java.awt.Point;
  27.  import java.beans.PropertyChangeEvent;
  28.  import java.beans.PropertyChangeListener;
  29.  
  30.  import org.jdesktop.swingx.JXTable;
  31.  import org.jdesktop.swingx.decorator.ComponentAdapter;
  32.  import org.jdesktop.swingx.decorator.PainterHighlighter;
  33.  import org.jdesktop.swingx.painter.AbstractLayoutPainter;
  34.  import org.jdesktop.swingx.painter.AbstractLayoutPainter.HorizontalAlignment;
  35.  import org.jdesktop.swingx.painter.AbstractPainter;
  36.  import org.jdesktop.swingx.painter.Painter;
  37.  
  38.  // <snip> Relative Decorator
  39.  // Specialized PainterHighlighter which has a Relativizer
  40.  public class RelativePainterHighlighter extends PainterHighlighter {
  41.  
  42.      private Relativizer relativizer;
  43.  
  44.      // </snip>
  45.      public RelativePainterHighlighter() {
  46.          this(null);
  47.      }
  48.  
  49.      public RelativePainterHighlighter(Painter delegate) {
  50.          super(delegate);
  51.      }
  52.  
  53.      public void setHorizontalAlignment(HorizontalAlignment align) {
  54.          getPainter().setHorizontalAlignment(align);
  55.          fireStateChanged();
  56.      }
  57.  
  58.      public HorizontalAlignment getHorizontalAlignment() {
  59.          return getPainter().getHorizontalAlignment();
  60.      }
  61.  
  62.      /**
  63.       * @param maxValue the maxValue to set
  64.       */
  65.      public void setRelativizer(Relativizer relativizer) {
  66.          this.relativizer = relativizer;
  67.          fireStateChanged();
  68.      }
  69.  
  70.      public Relativizer getRelativizer() {
  71.          return relativizer;
  72.      }
  73.  
  74.      @Override
  75.      protected Component doHighlight(Component component,
  76.              ComponentAdapter adapter) {
  77.          // <snip> Relative Decorator
  78.          // configures the RelativePainter with the value returned by the
  79.          // Relativizer
  80.          float xPercent = relativizer.getRelativeValue(adapter);
  81.          getPainter().setXFactor(xPercent);
  82.          getPainter().setVisible(xPercent != Relativizer.ZERO);
  83.          return super.doHighlight(component, adapter);
  84.          // </snip>
  85.      }
  86.  
  87.      /**
  88.       * Overridden to wrap a RelativePainter around the given, if not already is
  89.       * of type RelativePainter.
  90.       */
  91.      // <snip> Relative Decorator
  92.      // Wraps Painter into RelativePainter (hack around missing api in swingx)
  93.      @Override
  94.      public void setPainter(Painter painter) {
  95.          if (!(painter instanceof RelativePainter)) {
  96.              painter = new RelativePainter(painter);
  97.          }
  98.          super.setPainter(painter);
  99.      }
  100.  
  101.      // </snip>
  102.  
  103.      @Override
  104.      public RelativePainter getPainter() {
  105.          return (RelativePainter) super.getPainter();
  106.      }
  107.  
  108.      @Override
  109.      protected boolean canHighlight(Component component, ComponentAdapter adapter) {
  110.          return relativizer != null && super.canHighlight(component, adapter);
  111.      }
  112.  
  113.      // ------------------- Relativizer
  114.  
  115.      // <snip> Relativizer
  116.      // One-method interface to map a cell value to a float
  117.      public static interface Relativizer {
  118.          /**
  119.           * Returns a float in the range of 0.0f to 1.0f inclusive which
  120.           * indicates the relative value of the given adapter's value.
  121.           *  
  122.           * @param adapter
  123.           * @return
  124.           */
  125.          public float getRelativeValue(ComponentAdapter adapter);
  126.  
  127.          // </snip>
  128.  
  129.          public static final float ZERO = 0.0f;
  130.  
  131.          public static final float ONE = 1.0f;
  132.  
  133.      }
  134.  
  135.      public static class NumberRelativizer implements Relativizer {
  136.  
  137.          private Number max;
  138.  
  139.          private Number current;
  140.  
  141.          private int valueColumn;
  142.  
  143.          private boolean spread;
  144.  
  145.          public NumberRelativizer(Number max) {
  146.              this(max, max);
  147.          }
  148.  
  149.          public NumberRelativizer(Number max, Number current) {
  150.              this(0, max, current);
  151.          }
  152.  
  153.          /**
  154.           * @param i
  155.           * @param max
  156.           * @param current
  157.           */
  158.          public NumberRelativizer(int column, Number max, Number current) {
  159.              this(column, false, max, current);
  160.          }
  161.  
  162.          public NumberRelativizer(int column, boolean spreadColumns, Number max,
  163.                  Number current) {
  164.              this.current = current;
  165.              this.max = max;
  166.              this.valueColumn = column;
  167.              this.spread = spreadColumns;
  168.          }
  169.  
  170.          // <snip> Relativizer
  171.          // Simplistic base implementation of Relativizer which handles Numbers
  172.          @Override
  173.          public float getRelativeValue(ComponentAdapter adapter) {
  174.              if (getNumber(adapter) == null) {
  175.                  return ZERO;
  176.              }
  177.              float value = getNumber(adapter).floatValue();
  178.              float limit = Math.min(getCurrent().floatValue(), value);
  179.              if (isZero(limit)) {
  180.                  return ZERO;
  181.              }
  182.              float percent = limit / getMax().floatValue();
  183.  
  184.              if (!spread) {
  185.                  return percent;
  186.              }
  187.  
  188.              int width = adapter.getComponent().getWidth();
  189.              int pixelLocation = (int) (percent * width);
  190.              int visualColumn = getColumnAt(adapter, pixelLocation);
  191.              if (adapter.column < visualColumn) {
  192.                  return ONE;
  193.              } else if (adapter.column > visualColumn) {
  194.                  return ZERO;
  195.              }
  196.  
  197.              int visualColumnWidth = getColumnWidth(adapter, visualColumn);
  198.              int startColumn = getColumnLocation(adapter, visualColumn);
  199.              int valueWidth = pixelLocation - startColumn;
  200.              return (float) valueWidth / (float) visualColumnWidth;
  201.              // </snip>
  202.          }
  203.  
  204.          /**
  205.           * Returns a Number representation of the cell value or null if it
  206.           * doesn't have any. Subclasses are meant to override this for custom
  207.           * mappings.
  208.           * <p>
  209.           *  
  210.           * This implementation checks and returns the type of the current cell.
  211.           *  
  212.           * @param adapter the ComponentAdapter which defines the current cell.
  213.           * @return a Number representing the current cell or null
  214.           */
  215.          // <snip> Relativizer
  216.          // simple value-to-Number mapping which handles Number types.
  217.          protected Number getNumber(ComponentAdapter adapter) {
  218.              if (adapter.getValue() instanceof Number)
  219.                  return (Number) adapter.getValue(valueColumn);
  220.              return null;
  221.          }
  222.          // </snip>
  223.  
  224.          private int getColumnLocation(ComponentAdapter adapter, int visualColumn) {
  225.              if (!(adapter.getComponent() instanceof JXTable)) {
  226.                  return 0;
  227.              }
  228.              JXTable table = (JXTable) adapter.getComponent();
  229.              // PENDING JW: guard against null header
  230.              return table.getTableHeader().getHeaderRect(visualColumn).x;
  231.          }
  232.  
  233.          private int getColumnWidth(ComponentAdapter adapter, int visualColumn) {
  234.              if (!(adapter.getComponent() instanceof JXTable)) {
  235.                  return adapter.getComponent().getWidth();
  236.              }
  237.              JXTable table = (JXTable) adapter.getComponent();
  238.              return table.getColumn(visualColumn).getWidth();
  239.          }
  240.  
  241.          private int getColumnAt(ComponentAdapter adapter, int pixelLocation) {
  242.              if (!(adapter.getComponent() instanceof JXTable)) {
  243.                  return 0;
  244.              }
  245.              JXTable table = (JXTable) adapter.getComponent();
  246.              // PENDING JW: guard against null header
  247.              return table.getTableHeader().columnAtPoint(
  248.                      new Point(pixelLocation, 10));
  249.          }
  250.  
  251.          protected Number getCurrent() {
  252.              return current;
  253.          }
  254.  
  255.          protected Number getMax() {
  256.              return max;
  257.          }
  258.  
  259.          protected boolean isZero(float limit) {
  260.              return Math.abs(limit) < 0.002;
  261.          }
  262.  
  263.          protected int getValueColumn() {
  264.              return valueColumn;
  265.          }
  266.      }
  267.  
  268.      // --------- hack around missing size proportional painters
  269.  
  270.      public static class RelativePainter<T> extends AbstractLayoutPainter<T> {
  271.  
  272.          private Painter<? super T> painter;
  273.  
  274.          private double xFactor;
  275.  
  276.          private double yFactor;
  277.  
  278.          private boolean visible;
  279.  
  280.          private PropertyChangeListener painterListener;
  281.  
  282.          public RelativePainter() {
  283.              this(null);
  284.          }
  285.  
  286.          public RelativePainter(Painter<? super T> delegate) {
  287.              this.painter = delegate;
  288.              installPainterListener();
  289.          }
  290.  
  291.          public RelativePainter(Painter<? super T> delegate, double xPercent) {
  292.              this(delegate);
  293.              xFactor = xPercent;
  294.          }
  295.  
  296.          public void setPainter(Painter<? super T> painter) {
  297.              uninstallPainterListener();
  298.              Object old = getPainter();
  299.              this.painter = painter;
  300.              installPainterListener();
  301.              firePropertyChange("painter", old, getPainter());
  302.          }
  303.  
  304.          public Painter<? super T> getPainter() {
  305.              return painter;
  306.          }
  307.  
  308.          public void setXFactor(double xPercent) {
  309.              double old = getXFactor();
  310.              this.xFactor = xPercent;
  311.              firePropertyChange("xFactor", old, getXFactor());
  312.          }
  313.  
  314.          /**
  315.           * @return
  316.           */
  317.          public double getXFactor() {
  318.              return xFactor;
  319.          }
  320.  
  321.          public void setYFactor(double yPercent) {
  322.              this.yFactor = yPercent;
  323.          }
  324.  
  325.          @Override
  326.          protected void doPaint(Graphics2D g, T object, int width, int height) {
  327.              if (painter == null)
  328.                  return;
  329.              // use epsilon
  330.              if (xFactor != 0.0) {
  331.                  int oldWidth = width;
  332.                  width = (int) (xFactor * width);
  333.                  if (getHorizontalAlignment() == HorizontalAlignment.RIGHT) {
  334.                      g.translate(oldWidth - width, 0);
  335.                  }
  336.              }
  337.              if (yFactor != 0.0) {
  338.                  int oldHeight = height;
  339.                  height = (int) (yFactor * height);
  340.                  if (getVerticalAlignment() == VerticalAlignment.BOTTOM) {
  341.                      g.translate(0, oldHeight - height);
  342.                  }
  343.              }
  344.  
  345.              painter.paint(g, object, width, height);
  346.          }
  347.  
  348.          /**
  349.           * Overridden to take over completely: super does strange things with
  350.           * dirty which result in property changes fired during painting.
  351.           */
  352.          @Override
  353.          public boolean isVisible() {
  354.              return visible;
  355.          }
  356.  
  357.          /**
  358.           * Overridden to take over completely: super does strange things with
  359.           * dirty which result in property changes fired during painting.
  360.           */
  361.          @Override
  362.          public void setVisible(boolean visible) {
  363.              if (isVisible() == visible)
  364.                  return;
  365.              this.visible = visible;
  366.              firePropertyChange("visible", !visible, isVisible());
  367.          }
  368.  
  369.          /**
  370.           * Installs a listener to the painter if appropriate. This
  371.           * implementation registers its painterListener if the Painter is of
  372.           * type AbstractPainter.
  373.           */
  374.          protected void installPainterListener() {
  375.              if (getPainter() instanceof AbstractPainter) {
  376.                  ((AbstractPainter) getPainter())
  377.                          .addPropertyChangeListener(getPainterListener());
  378.              }
  379.          }
  380.  
  381.          /**
  382.           * Uninstalls a listener from the painter if appropriate. This
  383.           * implementation removes its painterListener if the Painter is of type
  384.           * AbstractPainter.
  385.           */
  386.          protected void uninstallPainterListener() {
  387.              if (getPainter() instanceof AbstractPainter) {
  388.                  ((AbstractPainter) getPainter())
  389.                          .removePropertyChangeListener(painterListener);
  390.              }
  391.          }
  392.  
  393.          /**
  394.           * Lazyly creates and returns the property change listener used to
  395.           * listen to changes of the painter.
  396.           *  
  397.           * @return the property change listener used to listen to changes of the
  398.           *         painter.
  399.           */
  400.          protected final PropertyChangeListener getPainterListener() {
  401.              if (painterListener == null) {
  402.                  painterListener = createPainterListener();
  403.              }
  404.              return painterListener;
  405.          }
  406.  
  407.          /**
  408.           * Creates and returns the property change listener used to listen to
  409.           * changes of the painter.
  410.           * <p>
  411.           *  
  412.           * This implementation fires a stateChanged on receiving any
  413.           * propertyChange, if the isAdjusting flag is false. Otherwise does
  414.           * nothing.
  415.           *  
  416.           * @return the property change listener used to listen to changes of the
  417.           *         painter.
  418.           */
  419.          protected PropertyChangeListener createPainterListener() {
  420.              PropertyChangeListener l = new PropertyChangeListener() {
  421.  
  422.                  public void propertyChange(PropertyChangeEvent evt) {
  423.                      setDirty(true);
  424.                  }
  425.  
  426.              };
  427.              return l;
  428.          }
  429.  
  430.      }
  431.  
  432.  }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement