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

org.jdesktop.swingxset.util.RelativePainterHighlighter Maven / Gradle / Ivy

/*
 * Copyright 2009 Sun Microsystems, Inc., 4150 Network Circle,
 * Santa Clara, California 95054, U.S.A. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */
package org.jdesktop.swingxset.util;

import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.Point;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.Painter;

import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.decorator.ComponentAdapter;
import org.jdesktop.swingx.decorator.PainterHighlighter;
import org.jdesktop.swingx.painter.AbstractLayoutPainter;
import org.jdesktop.swingx.painter.AbstractLayoutPainter.HorizontalAlignment;
import org.jdesktop.swingx.painter.AbstractPainter;

// EUG wieso ist diese Klasse nicht in painters?
//  Relative Decorator
// Specialized PainterHighlighter which has a Relativizer
public class RelativePainterHighlighter extends PainterHighlighter {

    private Relativizer relativizer;

    // 
    public RelativePainterHighlighter() {
        this(null);
    }

    /**
     * Instantiates a RelativePainterHighlighter with the given Painter and default predicate.
     * ctor
     * @param delegate Painter
     */
    public RelativePainterHighlighter(Painter delegate) {
        super(delegate);
    }

    public void setHorizontalAlignment(HorizontalAlignment align) {
        getPainter().setHorizontalAlignment(align);
        fireStateChanged();
    }

    public HorizontalAlignment getHorizontalAlignment() {
        return getPainter().getHorizontalAlignment();
    }

    /**
     * 
     * @param relativizer the Relativizer (maxValue) to set
     */
    public void setRelativizer(Relativizer relativizer) {
        this.relativizer = relativizer;
        fireStateChanged();
    }

    public Relativizer getRelativizer() {
        return relativizer;
    }

    @Override
    protected Component doHighlight(Component component, ComponentAdapter adapter) {
        //  Relative Decorator
        // configures the RelativePainter with the value returned by the Relativizer
        float xPercent = relativizer.getRelativeValue(adapter);
        getPainter().setXFactor(xPercent);
        getPainter().setVisible(xPercent != Relativizer.ZERO);
        return super.doHighlight(component, adapter);
        // 
    }

    /**
     * Overridden to wrap a RelativePainter around the given, 
     * if not already is of type RelativePainter.
     */
    //  Relative Decorator
    // Wraps Painter into RelativePainter (hack around missing api in swingx)
    @Override
    public void setPainter(Painter painter) {
        if (!(painter instanceof RelativePainter)) {
            painter = new RelativePainter(painter);
        }
        super.setPainter(painter);
    }

    // 

    @Override
    public RelativePainter getPainter() {
        return (RelativePainter) super.getPainter();
    }

    @Override
    protected boolean canHighlight(Component component, ComponentAdapter adapter) {
        return relativizer != null && super.canHighlight(component, adapter);
    }

//------------------- Relativizer

    //  Relativizer
    /**
     * One-method interface to map a cell value to a float
     */
    public static interface Relativizer {
        /**
         * Returns a float in the range of 0.0f to 1.0f inclusive which
         * indicates the relative value of the given adapter's value.
         * 
         * @param adapter ComponentAdapter
         * @return the relative value
         */
        public float getRelativeValue(ComponentAdapter adapter);
        // 

        public static final float ZERO = 0.0f;
        public static final float ONE = 1.0f;

    }

    public static class NumberRelativizer implements Relativizer {

        private Number max;
        private Number current;
        private int valueColumn;
        private boolean spread;

        public NumberRelativizer(Number max) {
            this(max, max);
        }

        /**
         * convinient ctor
         * @param max Number
         * @param current Number
         */
        public NumberRelativizer(Number max, Number current) {
            this(0, max, current);
        }

        /**
         * convinient ctor
         * @param column valueColumn
         * @param max Number
         * @param current Number
         */
        public NumberRelativizer(int column, Number max, Number current) {
            this(column, false, max, current);
        }

        /**
         * ctor
         * @param column valueColumn
         * @param spreadColumns true if is spreadColumn
         * @param max Number
         * @param current Number
         */
        public NumberRelativizer(int column, boolean spreadColumns, Number max, Number current) {
            this.current = current;
            this.max = max;
            this.valueColumn = column;
            this.spread = spreadColumns;
        }

        //  Relativizer
        // Simplistic base implementation of Relativizer which handles Numbers
        @Override
        public float getRelativeValue(ComponentAdapter adapter) {
            if (getNumber(adapter) == null) {
                return ZERO;
            }
            float value = getNumber(adapter).floatValue();
            float limit = Math.min(getCurrent().floatValue(), value);
            if (isZero(limit)) {
                return ZERO;
            }
            float percent = limit / getMax().floatValue();

            if (!spread) {
                return percent;
            }

            int width = adapter.getComponent().getWidth();
            int pixelLocation = (int) (percent * width);
            int visualColumn = getColumnAt(adapter, pixelLocation);
            if (adapter.column < visualColumn) {
                return ONE;
            } else if (adapter.column > visualColumn) {
                return ZERO;
            }

            int visualColumnWidth = getColumnWidth(adapter, visualColumn);
            int startColumn = getColumnLocation(adapter, visualColumn);
            int valueWidth = pixelLocation - startColumn;
            return (float) valueWidth / (float) visualColumnWidth;
            // 
        }

        /**
         * Returns a Number representation of the cell value or null if it
         * doesn't have any. Subclasses are meant to override this for custom
         * mappings.
         * 

* * This implementation checks and returns the type of the current cell. * * @param adapter the ComponentAdapter which defines the current cell. * @return a Number representing the current cell or null */ // Relativizer // simple value-to-Number mapping which handles Number types. protected Number getNumber(ComponentAdapter adapter) { if (adapter.getValue() instanceof Number) return (Number) adapter.getValue(valueColumn); return null; } // private int getColumnLocation(ComponentAdapter adapter, int visualColumn) { if (!(adapter.getComponent() instanceof JXTable)) { return 0; } JXTable table = (JXTable) adapter.getComponent(); // PENDING JW: guard against null header return table.getTableHeader().getHeaderRect(visualColumn).x; } private int getColumnWidth(ComponentAdapter adapter, int visualColumn) { if (!(adapter.getComponent() instanceof JXTable)) { return adapter.getComponent().getWidth(); } JXTable table = (JXTable) adapter.getComponent(); return table.getColumn(visualColumn).getWidth(); } private int getColumnAt(ComponentAdapter adapter, int pixelLocation) { if (!(adapter.getComponent() instanceof JXTable)) { return 0; } JXTable table = (JXTable) adapter.getComponent(); // PENDING JW: guard against null header return table.getTableHeader().columnAtPoint(new Point(pixelLocation, 10)); } protected Number getCurrent() { return current; } protected Number getMax() { return max; } /** * * @param limit float * @return true if near ZERO */ protected boolean isZero(float limit) { return Math.abs(limit) < 0.002; } protected int getValueColumn() { return valueColumn; } } // --------- hack around missing size proportional painters private static class RelativePainter extends AbstractLayoutPainter { private Painter painter; private double xFactor; private double yFactor; private boolean visible; private PropertyChangeListener painterListener; public RelativePainter() { this(null); } public RelativePainter(Painter delegate) { this.painter = delegate; installPainterListener(); } public RelativePainter(Painter delegate, double xPercent) { this(delegate); xFactor = xPercent; } public void setPainter(Painter painter) { uninstallPainterListener(); Object old = getPainter(); this.painter = painter; installPainterListener(); firePropertyChange("painter", old, getPainter()); } public Painter getPainter() { return painter; } public void setXFactor(double xPercent) { double old = getXFactor(); this.xFactor = xPercent; firePropertyChange("xFactor", old, getXFactor()); } /** * @return */ public double getXFactor() { return xFactor; } public void setYFactor(double yPercent) { this.yFactor = yPercent; } @Override protected void doPaint(Graphics2D g, T object, int width, int height) { if (painter == null) return; // use epsilon if (xFactor != 0.0) { int oldWidth = width; width = (int) (xFactor * width); if (getHorizontalAlignment() == HorizontalAlignment.RIGHT) { g.translate(oldWidth - width, 0); } } if (yFactor != 0.0) { int oldHeight = height; height = (int) (yFactor * height); if (getVerticalAlignment() == VerticalAlignment.BOTTOM) { g.translate(0, oldHeight - height); } } painter.paint(g, object, width, height); } /** * Overridden to take over completely: super does strange things with * dirty which result in property changes fired during painting. */ @Override public boolean isVisible() { return visible; } /** * Overridden to take over completely: super does strange things with * dirty which result in property changes fired during painting. */ @Override public void setVisible(boolean visible) { if (isVisible() == visible) return; this.visible = visible; firePropertyChange("visible", !visible, isVisible()); } /** * Installs a listener to the painter if appropriate. This * implementation registers its painterListener if the Painter is of * type AbstractPainter. */ protected void installPainterListener() { if (getPainter() instanceof AbstractPainter) { ((AbstractPainter) getPainter()).addPropertyChangeListener(getPainterListener()); } } /** * Uninstalls a listener from the painter if appropriate. This * implementation removes its painterListener if the Painter is of type * AbstractPainter. */ protected void uninstallPainterListener() { if (getPainter() instanceof AbstractPainter) { ((AbstractPainter) getPainter()).removePropertyChangeListener(painterListener); } } /** * Lazyly creates and returns the property change listener used to * listen to changes of the painter. * * @return the property change listener used to listen to changes of the * painter. */ protected final PropertyChangeListener getPainterListener() { if (painterListener == null) { painterListener = createPainterListener(); } return painterListener; } /** * Creates and returns the property change listener used to listen to * changes of the painter. *

* * This implementation fires a stateChanged on receiving any * propertyChange, if the isAdjusting flag is false. Otherwise does * nothing. * * @return the property change listener used to listen to changes of the * painter. */ protected PropertyChangeListener createPainterListener() { PropertyChangeListener l = new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { setDirty(true); } }; return l; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy