alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 *
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun
 * Microsystems, Inc. All Rights Reserved.
 */
package org.netbeans.swing.scrollbars.impl;

import org.netbeans.swing.scrollbars.spi.Mark;
import org.netbeans.swing.scrollbars.spi.MarkingModel;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.ScrollBarUI;
import java.awt.*;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

/**
 * A generic scrollbar which displays marks.
 *
 */
public class GenericMarkedScrollbar extends JScrollBar implements PropertyChangeListener, AdjustmentListener, ChangeListener {
    private MarkingModel mdl;
    private JScrollBar delegate;
    public GenericMarkedScrollbar (MarkingModel mdl) {
        this.mdl = mdl;
        init();
    }

    public void addNotify() {
        super.addNotify();
        mdl.addChangeListener (this);
        ToolTipManager.sharedInstance().registerComponent(this);
    }

    public void removeNotify () {
        mdl.removeChangeListener (this);
        ToolTipManager.sharedInstance().unregisterComponent(this);
        super.removeNotify();
    }

    private void init() {
        delegate = new JScrollBar();
        delegate.addPropertyChangeListener(this);
        delegate.addAdjustmentListener(this);
        add (delegate);
        addMouseListener (new MarkAndTrackListener());
    }

    private int getGap() {
        return 8;
    }

    private int getMargin() {
        return 2;
    }

    public String getToolTipText (MouseEvent me) {
        Rectangle r = getMarksRect();
        Point p = me.getPoint();
        if (r.contains (p)) {
            Mark m = markAtPoint (p);
            if (m != null) {
                return m.getText();
            }
        }
        return null;
    }

    public void paintComponent (Graphics g) {
        super.paintComponent (g);
        paintMarks(g);
    }

    /** Get the rectangle within which marks can be displayed.
     * @return The rectangle
     */
    protected final Rectangle getMarksRect () {
        Rectangle r = new Rectangle (0, 0, getWidth(), getHeight());
        if (getOrientation() == HORIZONTAL) {
            r.y = r.height - getGap();
            r.height -= getGap();
        } else {
            r.x = r.width - getGap();
            r.width -= getGap();
        }
        return r;
    }

    /** Get the total number of possible thumb positions on the resizable axis of the
     * scrollbar - the track height or width, depending on the scrollbar's
     * orientation
     * @return The total
     */
    protected final int getVisibleRange () {
        Rectangle mrect = getMarksRect();
        return (getOrientation() == JScrollBar.VERTICAL) ?
            mrect.height : mrect.width;
    }

    /** Translate a location as given by a call to someMark.getStart()
     * into the coordinate space of the scrollbar.
     * @param loc The location given by the Mark object
     * @param max The maximum, given by the model
     * @return The coordinate in the space of the scrollbar, as a position along the
     * scrollbar's resizable axis.
     */
    protected final int translate (int loc, int max) {
        int range = getVisibleRange();
        double factor = range / max;
        double pos = factor * loc;
        return Math.round(Math.round(pos));
    }

    private java.util.HashMap marksRects = new java.util.HashMap();
    /** Find the mark at a given point in the component's coordinate space
     * @return The Mark object at that point, or null
     * @param p A point in the scrollbar's coordinate space
     */
    public Mark markAtPoint (Point p) {
        Rectangle rect = getMarksRect();
        if (!(rect.contains(p))) return null;
        java.util.Iterator i = marksRects.keySet().iterator();
        while (i.hasNext()) {
            Rectangle r = (Rectangle) i.next();
            if (r.contains(p)) return (Mark) marksRects.get(r);
        }
        return null;
    }

    /** Paint the marks displayed by this component.  Calculates the rectangle of the
     * mark and calls paintMark() with it.
     * @param g The Graphics object passed to the paint method
     */
    public void paintMarks (Graphics g) {
        boolean vertical = getOrientation() == JScrollBar.VERTICAL;

        Rectangle r = getMarksRect();
        if (mdl.size() == 0) return;

        int markRange = mdl.getMaxMarkLocation();
        java.util.Enumeration e = mdl.getMarks();

        while (e.hasMoreElements()) {
            Mark m = (Mark) e.nextElement();
            Rectangle curr;
            if (vertical) {
                r.y = translate (m.getStart(), markRange);
                r.height = Math.max(getGap(), translate (m.getLength(), markRange));
                r.width = getGap();
                curr = new Rectangle(r.x-2, r.y, r.width+2, r.height);
                marksRects.put (curr, m);
            } else {
                r.x = translate (m.getStart(), markRange);
                r.width = Math.max(getGap(), translate (m.getLength(), markRange));
                r.height = getGap();
                curr = new Rectangle(r.x, r.y, r.width, r.height);
                marksRects.put (curr, m);
            }
            Color color = (Color) m.get ("color"); //NOI18N
            if (color == null) {
                color = UIManager.getColor("windowText"); //NOI18N
            }
//            System.err.println ("Mark " + m + " rect " + r);
            g.setColor (color);
            g.fillRect (r.x + getMargin(), r.y, r.width-getMargin()-1, r.height);
            g.setColor (color.darker());
            g.drawRect (r.x + getMargin(), r.y, r.width-getMargin()-1, r.height);
        }
    }

    public void updateUI() {
        if (getUI() == null) {
            setUI ((ScrollBarUI) GenericScrollbarUI.createUI(this));
        }
    }

    public void doLayout() {
        delegate.setBounds (0, 0, getWidth() - getGap(), getHeight());
    }

    public BoundedRangeModel getModel() {
        return delegate.getModel();
    }

    public void setModel (BoundedRangeModel mdl) {
        delegate.setModel (mdl);
    }

    public int getMaximum() {
        return delegate.getMaximum();
    }

    public int getMinimum() {
        return delegate.getMinimum();
    }

    public int getOrientation() {
        return delegate.getOrientation();
    }

    public void setOrientation (int o) {
        delegate.setOrientation(o);
    }

    public int getBlockIncrement() {
        return delegate.getBlockIncrement();
    }

    public int getUnitIncrement() {
        return delegate.getUnitIncrement();
    }

    public int getUnitIncrement(int dir) {
        return delegate.getUnitIncrement(dir);
    }

    public int getVisibleAmount() {
        return delegate.getVisibleAmount();
    }

    public void setEnabled (boolean val) {
        super.setEnabled(val);
        delegate.setEnabled(val);
    }

    public void setBlockIncrement (int val) {
        delegate.setBlockIncrement(val);
    }

    public void setValueIsAdjusting (boolean val) {
        delegate.setValueIsAdjusting(val);
    }

    public void setValues (int newValue, int newExtent, int newMin, int newMax) {
        delegate.setValues (newValue, newExtent, newMin, newMax);
    }

    public void setVisibleAmount (int val) {
        delegate.setVisibleAmount(val);
    }

    public boolean getValueIsAdjusting() {
        return delegate.getValueIsAdjusting();
    }

    public int getValue() {
        return delegate.getValue();
    }

    public void setValue (int i) {
        delegate.setValue(i);
    }

    public Dimension getPreferredSize() {
        Dimension result = new Dimension (delegate.getPreferredSize());
        if (getOrientation() == HORIZONTAL) {
            result.height += getGap();
        } else {
            result.width += getGap();
        }
        return result;
    }

    public Dimension getMaximumSize() {
        Dimension result = new Dimension (delegate.getMaximumSize());
        if (getOrientation() == HORIZONTAL) {
            result.height += getGap();
        } else {
            result.width += getGap();
        }
        return result;
    }

    public Dimension getMinimumSize() {
        Dimension result = new Dimension (delegate.getMaximumSize());
        if (getOrientation() == HORIZONTAL) {
            result.height += getGap();
        } else {
            result.width += getGap();
        }
        return result;
    }

    /**
     * This method gets called when a bound property is changed.
     *
     * @param evt A PropertyChangeEvent object describing the event source
     *            and the property that has changed.
     */
    public void propertyChange(PropertyChangeEvent evt) {
        String name = evt.getPropertyName();
        Object newValue = evt.getNewValue();
        Object oldValue = evt.getOldValue();
        if ("preferredSize".equals(name) || "minimumSize".equals(name) || "maximumSize".equals(name)) { //NOI18N
            newValue = new Dimension ((Dimension) newValue);
            oldValue = new Dimension ((Dimension) oldValue);
            if (getOrientation() == JScrollBar.VERTICAL) {
                ((Dimension) newValue).width += getGap();
                ((Dimension) oldValue).width += getGap();
            } else {
                ((Dimension) newValue).height += getGap();
                ((Dimension) oldValue).height += getGap();
            }
        }
        firePropertyChange (evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
    }

    /**
     * Invoked when the value of the adjustable has changed.
     */
    public void adjustmentValueChanged(AdjustmentEvent e) {
        fireAdjustmentValueChanged(e.getID(), e.getAdjustmentType(), e.getValue());
    }

    private void goToMark (Mark m) {
        Rectangle r = getMarksRect();
        int loc = translate (m.getStart(), r.height);
        setValue(translateToScrollbarModel (loc));
        m.select();
    }

    private int translateToScrollbarModel (int i) {
        BoundedRangeModel mod = getModel();
        int min = mod.getMinimum();
        int max = mod.getMaximum();
        int mrange = max - min;

        double factor = mrange / mdl.getMaxMarkLocation();
        double pos = (i * factor) + min;
        return Math.round(Math.round(pos));
    }

    /**
     * Invoked when the target of the listener has changed its state.
     *
     * @param e a ChangeEvent object
     */
    public void stateChanged(ChangeEvent e) {
        Rectangle r = getMarksRect();
        repaint(r.x, r.y, r.width, r.height);
    }

    protected class MarkAndTrackListener extends MouseAdapter {
        public void mousePressed (MouseEvent e) {
            if (getValueIsAdjusting ()) {
                super.mousePressed (e);
                return;
            }
            if (SwingUtilities.isRightMouseButton(e) ||
             SwingUtilities.isMiddleMouseButton(e) || !isEnabled()) {
                return;
            }

            Point p = e.getPoint();
            Rectangle r = getMarksRect();

            if (r.contains (p)) {
                Mark m = markAtPoint (p);
                if (m != null) {
                    goToMark (m);
                }
            } else {
                super.mousePressed(e);
            }
        }
    }

}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.