DockPanel.java :  » XML-UI » xui32 » com » blogofbug » swing » components » Java Open Source

Java Open Source » XML UI » xui32 
xui32 » com » blogofbug » swing » components » DockPanel.java
/*
 * DockPanel.java
 *
 * Created on January 9, 2007, 6:22 AM
 *
 * Re-implementation of the dock to use a grid-bag-laid-out panel instead
 * of the very complicated code I was developing.
 *
 * Copyright 2006-2007 Nigel Hughes 
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at http://www.apache.org/
 * licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language 
 * governing permissions and limitations under the License.
 */

package com.blogofbug.swing.components;

import com.blogofbug.swing.SwingBugUtilities;
import com.blogofbug.swing.components.effects.ComponentEffect;
import com.blogofbug.swing.components.effects.ComponentTextEffect;
import com.blogofbug.swing.components.effects.ContainerEffectManager;
import com.blogofbug.swing.components.effects.EffectContainer;
import com.blogofbug.swing.delegates.MouseTracker;
import com.blogofbug.swing.delegates.MouseTrackerListener;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.util.Hashtable;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.Insets;

/**
 * A dock that can be added to the glass pane of a frame
 * @author nigel
 */
public class DockPanel extends JPanel implements MouseTrackerListener, ActionListener, 
                                        ContainerEffectManager.ComponentEffectSupplier{
    /**
     * Enumeration object to contain the side of the screen/window the dock is against
     *
     */
    public enum       Side {
        /**
         * Lock dock to top of the window
         */
        NORTH, 
        /**
         * Lock the dock to the bottom of the window
         */
        SOUTH, 
        /**
         * Locks the dock to the right of the dock
         */
        EAST, 
        /**
         * Lock the dock to the left of the window
         */
        WEST};
    
    //The enlarged size of the icons
    /**
     * The "mouse over" size of a dock entry
     */
    private int       enlargedSize = 96;
    
    //The normal size of the icons
    /**
     * The "mouse out" size
     */
    private int       normalSize   = 32;
    
    //Insets around each dock icon
    /**
     * The insets around the dock
     */
    private int       insets       = 2;
    
    //The side the dock is docked to
    /**
     * The frame the dock is associated with
     */
    private Side      dockedTo     = Side.SOUTH;
    
    //Autohide?
    /**
     * Should the dock automatically hide when the mouse is outside of the area
     */
    private boolean   autoHide     = false;
    
    //Auto-hiding!
    /**
     * True if the dock is currently being hidden
     */
    private boolean   hiding       = false;
    
    //Layout and standard constraints
    /**
     * The layout being used for the container
     */
    private GridBagLayout       layout = new GridBagLayout();
    /**
     * The constraint for the filler objects
     */
    private GridBagConstraints  filler = new GridBagConstraints();
    /**
     * The constraints for the title object
     */
    private GridBagConstraints  title  = new GridBagConstraints();
    /**
     * The constraints for an icon in the dock...
     */
    private GridBagConstraints  icon   = new GridBagConstraints();
    
    /**
     * Spacer object above the dock
     */
    protected JSpacer              spacer; ;
    /**
     * Spacer on the "left" of the dock
     */
    protected JSpacer              firstSpacer; ;
    /**
     * Spacer on the right of the dock
     */
    protected JSpacer              lastSpacer;
    
    /**
     * Controls whether or not autohiding is already on a trigger
     */
    protected boolean               delayedAutoHide = false;
    
    /** 
     * Determines current in/out status
     */
    protected boolean               couldAutoHide = false;
    
    /**
     * Hold index of components and their titles
     */
    private Hashtable<Component,String>   iconLabels = new Hashtable<Component,String>();
    
    
    /**
     * Track mouse movements (will be over the entire component)
     */
    private MouseTracker        mouseTracker;
    
    
    /**
     * Animation timer
     */
    //private Timer               timer = new Timer(0,this);
    /**
     * Records in an animation is currently planning
     */
    private boolean             animating = false;
    
    private int minHidingSize = 16;
    
    //Mouse location (last known)
    /**
     * Last known location of the mouse
     */
    private Point            lastKnownMouse = new Point(0,0);
    
    private boolean          returnToNormal     = true;
    private boolean          overDockComponent  = false;
    private boolean          normalTimerRunning = false;
    
    /** 
     * Effects for the dock components
     */
    protected ContainerEffectManager    effects = 
                                        new ContainerEffectManager(this,this,true);
    
    /**
     * Debug mode
     */
    private static final boolean        DEBUG_MODE = true;
    
    /**
     * Creates a new instance of DockPanel
     * @param normalSize The normal size of the dock icons
     * @param enlargedSize The "mouse over" size of the dock icons
     * @param dockedTo The side the dock is attached to
     */
    public DockPanel(int normalSize, int enlargedSize, Side dockedTo) {
        //Set up the basics
        this.dockedTo = dockedTo;
        this.enlargedSize = enlargedSize;
        this.normalSize = normalSize;
        
        //Prepare the timer
//        timer.setCoalesce(true);
//        timer.setDelay(20);
//        timer.setRepeats(true);
//        timer.start();
        startTimer();
        addComponentListener(new ComponentListener() {
            public void componentHidden(ComponentEvent componentEvent) {
                stopTimer();
            }
            public void componentMoved(ComponentEvent componentEvent) {
            }
            public void componentResized(ComponentEvent componentEvent) {
            }
            public void componentShown(ComponentEvent componentEvent) {
                startTimer();
            }
        });
        
        //make me transparent
        setBackground(null);
        setOpaque(false);
        
        //Set up the mouse tracker
        mouseTracker = new MouseTracker(this,this);
        
        //Set up the spacers
        spacer = new JSpacer();
        firstSpacer = new JSpacer();
        lastSpacer = new JSpacer();
        
        //Initial setup
        setLayout(layout);
        initializeLayout();
        add(spacer,filler);
        add(firstSpacer,icon);
        add(lastSpacer,icon);
        
        //Perform initial layout
        updateLayout(null);
    }
    
    private void startTimer(){
        SwingBugUtilities.addTimerListener(this);
    }
    
    private void stopTimer(){
        SwingBugUtilities.removeTimerListener(this);
    }
    
    /**
     * Determines if the dock is currently hiding (or hidden)
     * @return True if it is auto-hiding...
     */
    public boolean isAutoHiding(){
        return autoHide;
    }
    
    /**
     * Turns auto-hiding on or off
     * @param autoHide True to turn it on, false to turn it off
     */
    public void setAutoHiding(boolean autoHide){
        this.autoHide = autoHide;
        mouseMoved(lastKnownMouse);
    }
    
    /**
     * Creates a new instance of the dock which will attach to the south of the frame
     * @param normalSize The normal size of the icon
     * @param enlargedSize The mouse-over size of icons in the dock
     */
    public DockPanel(int normalSize, int enlargedSize){
        this(normalSize,enlargedSize,Side.SOUTH);
    }
    
    /**
     * Sets the normal size of an icon in the dock
     * @param normalSize The normal size. 
     */
    public void setNormalSize(int normalSize){
        this.normalSize = normalSize;
        updateLayout(null);
        layout.layoutContainer(this);
    }
    
    /**
     * Sets the minimum dimension of the hidden component
     * @param minSize The minimum dimension. 
     */
    public void setMinHidingSize( int minSize )
    {
      minHidingSize = minSize;
    }
    /**
     * Sets the mouse-over size of an icon in the dock
     * @param enlargedSize The enlarged size
     */
    public void setEnlargedSize(int enlargedSize){
        this.enlargedSize = enlargedSize;
        updateLayout(null);
        layout.layoutContainer(this);
    }
    
    /**
     * Sets up the basic layout and then calls updateLayout to finalize the
     * individual dock elements
     */
    private void initializeLayout(){
        //Standard settings for the filler panel
        filler.fill = GridBagConstraints.BOTH;
        filler.weightx = 1.0;
        filler.weighty = 1.0;
        
        //Standard settings for the title components
        title.anchor = GridBagConstraints.CENTER;
        
        //Standard settings for the icon components
        icon.anchor = GridBagConstraints.CENTER;
        icon.weightx = 0.0;
        icon.weighty = 0.0;
        icon.insets = new Insets(insets/2,insets/2,insets/2,insets/2);
        
        //Do various bits of specific constraints layout
        switch (dockedTo){
            case SOUTH:
                filler.gridx = 0;
                filler.gridy = 0;
                filler.gridheight =1;
                filler.gridwidth = GridBagConstraints.REMAINDER;
                title.gridx  = 0;
                title.gridy = 1;
                icon.gridx = 0;
                icon.gridy = 2;
                icon.anchor = GridBagConstraints.SOUTH;
                break;
            case NORTH:
                filler.gridx = 0;
                filler.gridy = 2;
                filler.gridheight =1;
                filler.gridwidth = GridBagConstraints.REMAINDER;
                title.gridx  = 0;
                title.gridy = 1;
                icon.gridx = 0;
                icon.gridy = 0;
                icon.anchor = GridBagConstraints.NORTH;
                break;
            case WEST:
                filler.gridx = 2;
                filler.gridy = 0;
                filler.gridheight =GridBagConstraints.REMAINDER;
                filler.gridwidth = 1;
                title.gridx  = 1;
                title.gridy = 0;              
                icon.gridx = 0;
                icon.gridy = 0;
                icon.anchor = GridBagConstraints.WEST;
                break;
            case EAST:
                filler.gridx = 0;
                filler.gridy = 0;
                filler.gridheight =GridBagConstraints.REMAINDER;
                filler.gridwidth = 1;
                title.gridx  = 1;
                title.gridy = 0;
                icon.gridx = 2;
                icon.gridy = 0;
                icon.anchor = GridBagConstraints.EAST;
                break;
        }
    }
    
    /**
     * Changes the side of the panel the dock is attached to
     * @param dockedTo Determines the side of the frame the dock is connected to 
     */
    public void setDockedTo(DockPanel.Side dockedTo) {
        this.dockedTo = dockedTo;
        initializeLayout();
        layout.setConstraints(spacer,filler);
        updateLayout(null);
        layout.layoutContainer(this);
    }
    
    /**
     * Determines the appropriate gridbag weight for the "book-end" spacers
     * at either end of the dock
     *
     * @return The weight
     */
    private double spacerWeightX(){
        switch (dockedTo){
            case NORTH:
            case SOUTH:
                return 1.0;
            case EAST:
            case WEST:
                return 0.0;
        }
        return 0.0;
    }
    
    /**
     * Determines the appropriate gridbag weight for the "book-end" spacers
     * at either end of the dock
     *
     * @return The weight
     */
    private double spacerWeightY(){
        return 1.0-spacerWeightX();
    }
    
    /**
     * Determines the appropriate size for the component based on the current "mouse over"
     * component, the location in the dock area relative to the overall dock panel, and a given component
     * This is protected so it can be over-ridden to apply a better alogrithm .
     *
     * @param p The location of the mouse relative to the overall dock
     * @param component The component to be sized
     * @param highlightedComponent The current component with the mouse over it
     * @return A Dimension object with the recommened size of the component
     */
    protected Dimension getComponentPreferedSize(Point p, Component component, Component highlightedComponent){
        //If we are hiding it should be small
        if (hiding){
          int size = Math.max( insets*3, minHidingSize );
            return new Dimension(size,size);
        }

        //determine it's distance based on half the size of the biggest component
        double compSize = component.getSize().height;
        double distanceFromCenter = 0;
        double delta = (double) (enlargedSize-normalSize);
                     
        if ((highlightedComponent!=null)){
            switch (dockedTo){
                case NORTH:
                case SOUTH:
                    distanceFromCenter = Math.abs((double) ((component.getLocation().x + compSize/2 )- p.x));
                    break;
                case EAST:
                case WEST:
                    distanceFromCenter = Math.abs((double) ((component.getLocation().y + compSize/2 )- p.y));
                    break;
            }

            
//            if (highlightedComponent==component){
            if (distanceFromCenter<enlargedSize/2){
                return new Dimension(enlargedSize,enlargedSize);
            }

            double cdy = 1.0 - distanceFromCenter/(double) (enlargedSize*2);
            double tSize = Math.max((double) normalSize + cdy * delta,(double) normalSize);
            int    size = (int) tSize;
            
            return new Dimension(size,size);
        } else {
            if (returnToNormal){
                return new Dimension(normalSize,normalSize);                
            } else {
                return component.getPreferredSize();
            }
        }
    }
    
    /**
     * Essentially removes the spacer that forces the dock to the bottom of the
     * panel, neat if you would like to use the panel as something like a
     * special tab top.
     *
     * @param fillSpace true if the panel should fill up any empty space above the dock,
     * false if it should not
     */
    public void fillSpace(boolean fillSpace){
        spacer.setVisible(fillSpace);
    }
    
    /**
     * Determines a value between the current and target including easing. Can
     * be over-ridden if desired to have different sizing behavior. Implementers 
     * should note that if the size is not clipped to ensure that the icons will
     * all fit in the dock, gridbag does Bad Things (tm). 
     *
     * @param current The current value
     * @param target  The target value
     * @return A value equal to or between target and current
     */
    protected double tweenValue(double current, double target){
        //Just make sure we do nothing if they are the same
        if (current==target){
            return target;
        }
        
        //Determine the difference
        double delta = (target-current)/8.0;
        
        //Tween in the right direction, but always by at least one pixel
        if (delta>0){
            delta = Math.max(1.0,delta);
        } else if (delta<0){
            delta = Math.min(-1.0,delta);
        }
        
        switch (dockedTo){
            case SOUTH:
            case NORTH:
                return Math.min(current+delta,( getWidth()-insets*iconLabels.size()*2)/iconLabels.size()-10);
            default:
                return Math.min(current+delta,(getHeight()-insets*iconLabels.size()*2)/iconLabels.size());
        }
    }
    
    /**
     * Determines if a component is in the dock
     * @param component The component you wish to test to see if its in the dock
     * @return True if it does, false if it doesn't
     */
    public boolean dockContains(Component component){
        if (iconLabels.get(component)!=null){
            return true;
        }
        return false;
    }
    
    /**
     * Takes a current size, and determines a new size setting up an animation
     * if needed.
     *
     * @param currentSize The current size of the component
     * @param newSize     The new size of the component
     * @return The in-between size
     */
    private Dimension tweenSize(Dimension currentSize, Dimension newSize){
        if ((newSize.width != currentSize.width) || (newSize.height != currentSize.height)){
            animating = true;
            newSize.width = (int) tweenValue(currentSize.width,newSize.width);
            newSize.height = (int) tweenValue(currentSize.height,newSize.height);
        }
        return newSize;
    }

    /**
     * 
     *
     */
    private void setReturnToNormal(){
        if (returnToNormal){
            return;
        }
        normalTimerRunning=true;
        SwingBugUtilities.invokeAfter(new Runnable() {
            public void run() {
                if (!overDockComponent){
                    returnToNormal=true;
                    normalTimerRunning = false;
                    validate();
                }
            }
        },100);
    }
    
    /** 
     * Debug method
     * 
     * @param component The component
     */
    protected void showComponentLabel(JComponent component,String text){
        //Debugging information
        if (DEBUG_MODE){
            ComponentEffect ce = effects.getEffectFor((JComponent) component);
            if ((ce!=null) && (ce instanceof ComponentTextEffect)){
                ((ComponentTextEffect) ce).setText(text);
            }
        }                
    }
    
    
    /**
     * Determines the new settings for the gridbag layout, and then applies them
     * to all components
     * @param p The point the mouse is at
     */
    private void updateLayout(Point p){
        Component highlightedComponent = null;
        animating = false;
        if (p!=null){
            highlightedComponent = getComponentAt(p);
            //Make sure it's at least in the dock zone
            switch (dockedTo){
                case NORTH:
                    if (p.y>spacer.getY()){
                        highlightedComponent=null;
                    }
                    break;
                case SOUTH:
                    if (p.y<spacer.getHeight()){
                        highlightedComponent=null;
                    }
                    break;
                case WEST:
                    if (p.x>spacer.getX()){
                        highlightedComponent=null;
                    }
                    break;
                case EAST:
                    if (p.x<spacer.getWidth()){
                        highlightedComponent=null;
                    }
                    break;
            }
            if ((highlightedComponent==firstSpacer) || (highlightedComponent==lastSpacer)){
                highlightedComponent = null;
            }
        }
        //Variables used for incrementing grid-x's and grid-y's
        int dx=0,dy=0;
        switch (dockedTo){
            case NORTH:
            case SOUTH:
                dx=1;
                break;
            case EAST:
            case WEST:
                dy=1;
                break;
        }
        
        //Set everything up as it should be
        initializeLayout();
        
        //Add first spacer and move to next position
        icon.weightx = spacerWeightX();
        icon.weighty = spacerWeightY();
        icon.fill = GridBagConstraints.BOTH;
        layout.setConstraints(firstSpacer,icon);
        icon.fill = GridBagConstraints.NONE;
        icon.gridx += dx;
        icon.gridy += dy;
        title.gridx += dx;
        title.gridy += dy;
        
        if (highlightedComponent==null){
            setReturnToNormal();
            overDockComponent=false;
        } else {
            overDockComponent = true;
            returnToNormal=false;
        }

            
        //Iterate through the components updating everything
        Component[] components = getComponents();
        for (Component component : components){
            //Make sure it's not a filler or a title
            if (!((component == spacer) || (component instanceof DockLabel) || (component == firstSpacer) || (component == lastSpacer))){
                //Set the weight
                icon.weightx = 0.0;
                icon.weighty = 0.0;
                //Icon first
                layout.setConstraints(component, icon);
                
                //Set the prefered size of the component
                component.setPreferredSize(tweenSize(component.getSize(),getComponentPreferedSize(p,component,highlightedComponent)));
                
                //Set the visibility of its label
                if (highlightedComponent==component){
                    showComponentLabel((JComponent) component, iconLabels.get(component));
                } else {
                    showComponentLabel((JComponent) component, "");
                }
                                
                //Move to next position
                icon.gridx += dx;
                icon.gridy += dy;
                title.gridx += dx;
                title.gridy += dy;
            }
        }
        
        //Add the last spacer
        icon.weightx = spacerWeightX();
        icon.weighty = spacerWeightY();
        icon.fill = GridBagConstraints.BOTH;
        layout.setConstraints(lastSpacer,icon);
    }
    
    /**
     * Adds a new item to the dock
     * @param component The component to add
     * @param label The label to display when the mouse is over the dock item
     */
    public void addDockElement(Component component, String label){
        if (iconLabels.get(component)!=null){
            return;
        }
                
        //We would like it to do something funcky as it adds them and make them grow
        component.setPreferredSize(new Dimension(0,0));
        iconLabels.put(component,label);
        add(component);
        updateLayout(mouseTracker.getPosition());
    }
    
    /**
     * Not interested
     * @param mouseEntered True if the mouse came in 
     */
    public void mouseCrossThreshold(boolean mouseEntered) {
    }
    
    /** 
     * Fires an auto-hide check after a delay to ensure the mouse didn't just
     * stray out of the dock on the way from one place to another. 
     */
    protected void delayedAutoHide(){
        if (delayedAutoHide){
            return;
        }
        delayedAutoHide=true;
        SwingBugUtilities.invokeAfter(new Runnable() {
            public void run() {
                hiding = couldAutoHide;
                if (hiding){
                    validate();
                }
                delayedAutoHide=false;
            }
        },1000);             
    }
    
    /**
     * When the mouse moves, update the layout. Should be optimized when the
     * highlighted component is the spacer to not do anything
     * @param position The location of the mouse
     */
    public void mouseMoved(Point position) {
        if (autoHide){
            Component mouseOver = getComponentAt(position);
            final Component self = this;
            if ((mouseOver == firstSpacer) || (mouseOver == lastSpacer) || (spacer==mouseOver) || (mouseOver == this)){
                couldAutoHide=true;
                if (hiding == false){
                    delayedAutoHide();
                }
            } else {
                hiding = false;
                couldAutoHide=false;
            }
        } else {
            hiding = false;
            couldAutoHide = false;
        }
        lastKnownMouse = position;
        updateLayout(position);
        layout.layoutContainer(this);
    }
    
    /**
     * Returns true if the mouse is over a dock component, but false at all other times. This will cause
     * swing to pass on the event to the next layer down.
     * @param x The frame relative dock location x-cordination
     * @param y The frame relative dock location y-coordinate
     * @return True if the mouse is over a dock icon, false otherwise
     */
    public boolean contains(int x, int y) {
        Rectangle rect=new Rectangle();
        //Have to implement our own componentAt here
        for (Component comp : getComponents()){
            rect=comp.getBounds(rect);
            if (rect.contains(x,y)){
                if (comp instanceof JSpacer){
//                    System.out.println("Out");
                    mouseMoved(new Point(-1,-1));
                    return false;
                }
//                System.out.println("In");
                return true;
            }
        }
        //A little non-intuitive. If it's not over a normal component or a spacer, it's in the dock area
        return true;
    }    

    protected void paintChildren(Graphics graphics) {
        super.paintChildren(graphics);
        if (DEBUG_MODE){
            effects.paintEffects(graphics);
        }
    }

    
    /**
     * Paints the component.
     *
     * @param graphics The graphics context
     */
    public void paintComponent(Graphics graphics) {
        graphics.setColor( getBackground());
        Rectangle dockSize = null;
        int oldNormalSize=normalSize;
        if (hiding){
            normalSize = Math.min(normalSize, ((dockedTo==Side.NORTH) || (dockedTo==Side.SOUTH)) ? firstSpacer.getHeight(): firstSpacer.getWidth());
            normalSize = Math.max( normalSize, minHidingSize );
        }
        //Draw the main dock background
        switch (dockedTo){
            case NORTH:
                dockSize = new Rectangle(firstSpacer.getX()+firstSpacer.getWidth(),0,getWidth()-(lastSpacer.getWidth()+firstSpacer.getWidth()),normalSize);
                break;
            case SOUTH:
                dockSize = new Rectangle(firstSpacer.getX()+firstSpacer.getWidth(),getHeight()-normalSize,getWidth()-(lastSpacer.getWidth()+firstSpacer.getWidth()),normalSize);
                break;
            case WEST:
                dockSize = new Rectangle(0,firstSpacer.getHeight(),normalSize,getHeight()-(lastSpacer.getHeight()+firstSpacer.getHeight()));               
                break;
            case EAST:
                dockSize = new Rectangle(getWidth()-normalSize,firstSpacer.getHeight(),normalSize,getHeight()-(lastSpacer.getHeight()+firstSpacer.getHeight()));
                break;
        }
        if (hiding){
            normalSize = oldNormalSize;
        }
        
        dockSize.x-=insets;
        dockSize.y-=insets;
        dockSize.width+=insets*2;
        dockSize.height+=insets*2;
        graphics.fillRect(dockSize.x,dockSize.y,dockSize.width,dockSize.height);
        
        
        //Draw the outline
        graphics.setColor(new Color(255,255,255,127));
        switch (dockedTo){
            case SOUTH:
                graphics.drawRect(dockSize.x,dockSize.y,dockSize.width-1,dockSize.height);
                break;
        }
        super.paintComponent(graphics);
    }
    
    /**
     * Called when the animation timer fires
     * @param actionEvent The action event
     */
    public void actionPerformed(ActionEvent actionEvent) {
        if (animating){
            updateLayout(lastKnownMouse);
            layout.layoutContainer(this);
        }
    }

    public ComponentEffect getEffect(JComponent forComponent, Container inComponent, EffectContainer effectEngine) {
        if (this.DEBUG_MODE){
            if (forComponent instanceof JSpacer){
                return null;
            } else {
                return new ComponentTextEffect(inComponent,forComponent,effectEngine, 
                        "", ComponentTextEffect.TextLocation.NORTH);
            }
        } 
        return null;
    }
    
    //For convenience
    /**
     * A utilitity class to fill the gaps around the dock contents
     */
    public class JSpacer extends JComponent {
        /**
         * Creates a new instance of the dock spacer
         */
        public JSpacer(){
            setBackground(null);
            setOpaque(false);
        }

        
        
    }
    
    //Temporary until I do something else
    /**
     * A utiliity class to represent the label of the currently mouse-over dock item
     */
    public class DockLabel extends StrokedLabel {
        /**
         * Creats a new instance of the dock label
         * @param title The text of the label
         */
        public DockLabel(String title){
            super(title);
        }
        
    };
}

java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.