/FileExtraction/Java_unseen/X0Ken_FreeMind/freemind/view/mindmapview/NodeFoldingComponent.java
/*FreeMind - A Program for creating and viewing Mindmaps
 *Copyright (C) 2000-2001  Joerg Mueller <joergmueller@bigfoot.com>
 *See COPYING for Details
 *
 *This program is free software; you can redistribute it and/or
 *modify it under the terms of the GNU General Public License
 *as published by the Free Software Foundation; either version 2
 *of the License, or (at your option) any later version.
 *
 *This program 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 General Public License for more details.
 *
 *You should have received a copy of the GNU General Public License
 *along with this program; if not, write to the Free Software
 *Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
/*$Id: NodeMotionListenerView.java,v 1.1.4.4.4.9 2009/03/29 19:37:23 christianfoltin Exp $*/
package freemind.view.mindmapview;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Ellipse2D;

import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.DefaultButtonModel;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.Timer;
import javax.swing.plaf.basic.BasicButtonListener;
import javax.swing.plaf.basic.BasicButtonUI;

import freemind.main.FreeMind;
import freemind.main.Resources;
import freemind.main.Tools;
import freemind.modes.MindMapNode;

/**
 * @author Foltin
 * 
 */
public class NodeFoldingComponent extends JButton {
	private static final int TIMER_DELAY = 50;
	private static final int COLOR_COUNTER_MAX = 15;
	private static final int SIZE_FACTOR_ON_MOUSE_OVER = 4;
	protected static java.util.logging.Logger logger = null;
	private boolean mIsEntered;
	private int mColorCounter = 0;
	private NodeView nodeView;
	private boolean mIsEnabled = true;
	private Timer mTimer = null;

	public NodeFoldingComponent(NodeView view) {
		super();
		if (logger == null) {
			logger = freemind.main.Resources.getInstance().getLogger(
					this.getClass().getName());			
		}
		this.nodeView = view;
		setModel(new DefaultButtonModel());
		init(null, null);
		setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
		setBackground(Color.BLACK);
		setContentAreaFilled(false);
		setFocusPainted(false);
		setFocusable(false);
		setAlignmentY(Component.TOP_ALIGNMENT);
		setUI(new RoundImageButtonUI());
		mIsEnabled = Resources.getInstance().getBoolProperty(
				FreeMind.RESOURCES_DISPLAY_FOLDING_BUTTONS);
		if (mIsEnabled) {
			addMouseListener(new MouseListener() {
	
				public void mouseReleased(MouseEvent pE) {
				}
	
				public void mousePressed(MouseEvent pE) {
				}
	
				public void mouseExited(MouseEvent pE) {
					mIsEntered = false;
					mColorCounter = COLOR_COUNTER_MAX;
					repaint();
				}
	
				public void mouseEntered(MouseEvent pE) {
					mIsEntered = true;
					startTimer();
					repaint();
				}
	
				public void mouseClicked(MouseEvent pE) {
				}
			});
			int delay = TIMER_DELAY;
			ActionListener taskPerformer = new ActionListener() {
				public void actionPerformed(ActionEvent evt) {
					if (mIsEntered && mColorCounter < COLOR_COUNTER_MAX) {
						mColorCounter++;
						repaint();
					}
					if (!mIsEntered && mColorCounter > 0) {
						mColorCounter--;
						if(mColorCounter == 0) {
							stopTimer();
						}
						repaint();
					}
	
				}
			};
			mTimer = new Timer(delay, taskPerformer);
		}
	}

	public Dimension getPreferredSize() {
		return getUI().getPreferredSize(this);
	}

	/**
	 * @return
	 */
	private int getZoomedCircleRadius() {
		return nodeView.getZoomedFoldingSymbolHalfWidth();
	}

	class RoundImageButtonUI extends BasicButtonUI {
		protected Shape shape, base;

		protected void installDefaults(AbstractButton b) {
			super.installDefaults(b);
			clearTextShiftOffset();
			defaultTextShiftOffset = 0;
			b.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
			b.setContentAreaFilled(false);
			b.setFocusPainted(false);
			b.setOpaque(false);
			b.setBackground(Color.BLACK);
			b.setAlignmentY(Component.TOP_ALIGNMENT);
			initShape(b);
		}

		/* Is called by a button class automatically.*/
		protected void installListeners(AbstractButton b) {
			BasicButtonListener listener = new BasicButtonListener(b) {

				public void mousePressed(MouseEvent e) {
					AbstractButton b = (AbstractButton) e.getSource();
					initShape(b);
					if (shape.contains(e.getX(), e.getY())) {
						super.mousePressed(e);
					}
				}

				public void mouseEntered(MouseEvent e) {
					AbstractButton b = (AbstractButton) e.getSource();
					initShape(b);
					if (shape.contains(e.getX(), e.getY())) {
						super.mouseEntered(e);
					}
				}

				public void mouseMoved(MouseEvent e) {
					AbstractButton b = (AbstractButton) e.getSource();
					initShape(b);
					if (shape.contains(e.getX(), e.getY())) {
						super.mouseEntered(e);
					} else {
						super.mouseExited(e);
					}
				}
			};
			b.addMouseListener(listener);
			b.addMouseMotionListener(listener);
			b.addFocusListener(listener);
			b.addPropertyChangeListener(listener);
			b.addChangeListener(listener);
		}

		public void paint(Graphics g, JComponent c) {
			super.paint(g, c);
			Graphics2D g2 = (Graphics2D) g;
			initShape(c);
			// Border
			Object oldRenderingHint = nodeView.getController()
					.setEdgesRenderingHint(g2);
			g2.setColor(c.getBackground());
			g2.setStroke(BubbleMainView.DEF_STROKE);
			NodeFoldingComponent b = (NodeFoldingComponent) c;
			Rectangle bounds = shape.getBounds();
			Color col = getColorForCounter();
			Color lineColor = nodeView.getModel().getEdge().getColor();
			if (b.mIsEntered) {
				Color oldColor = g2.getColor();
				g2.setColor(nodeView.getMap().getBackground());
				g2.fillOval(bounds.x, bounds.y, bounds.width, bounds.height);
				g2.setColor(lineColor);
				int xmiddle = bounds.x + bounds.width / 2;
				int ymiddle = bounds.y + bounds.height / 2;
				g2.drawLine(bounds.x, ymiddle, bounds.x + bounds.width, ymiddle);
				if (isFolded()) {
					g2.drawLine(xmiddle, bounds.y, xmiddle, bounds.y
							+ bounds.height);
				}
				g2.draw(shape);
				g2.setColor(oldColor);
			} else {
				int xmiddle = bounds.x + bounds.width / 2;
				int ymiddle = bounds.y + bounds.height / 2;
				int foldingCircleDiameter = bounds.width
						/ SIZE_FACTOR_ON_MOUSE_OVER;
				Color oldColor = g2.getColor();
				if (mColorCounter != 0) {
					int diameter = bounds.width * mColorCounter
							/ COLOR_COUNTER_MAX;
					if (isFolded()) {
						diameter = Math.max(diameter, foldingCircleDiameter);
					}
					int radius = diameter / 2;
					g2.setColor(nodeView.getMap().getBackground());
					g2.fillOval(xmiddle - radius, ymiddle - radius, diameter,
							diameter);
					g2.setColor(col);
					if (isFolded()) {
						g2.drawLine(xmiddle, ymiddle - radius, xmiddle, ymiddle
								+ radius);
					}
					g2.drawLine(xmiddle - radius, ymiddle, xmiddle + radius,
							ymiddle);
					g2.setColor(lineColor);
					g2.drawOval(xmiddle - radius, ymiddle - radius, diameter,
							diameter);
					g2.setColor(oldColor);
				} else {
					if (isFolded()) {
						int radius = foldingCircleDiameter / 2;
						g2.setColor(nodeView.getMap().getBackground());
						g2.fillOval(xmiddle - radius, ymiddle - radius,
								foldingCircleDiameter, foldingCircleDiameter);
						g2.setColor(lineColor);
						g2.drawOval(xmiddle - radius, ymiddle - radius,
								foldingCircleDiameter, foldingCircleDiameter);
						g2.setColor(oldColor);
					}
				}
			}
			Tools.restoreAntialiasing(g2, oldRenderingHint);
		}

		/**
		 * @return
		 */
		private Color getColorForCounter() {
			Color color = nodeView.getModel().getEdge().getColor();

			int col = 16 * mColorCounter;
			return new Color((int) (color.getRed()), (int) (color.getGreen()),
					(int) (color.getBlue()), col);
		}

		public Dimension getPreferredSize(JComponent c) {
			JButton b = (JButton) c;
			Insets i = b.getInsets();
			int iw = (int) (getZoomedCircleRadius() * 2f * SIZE_FACTOR_ON_MOUSE_OVER);
			return new Dimension(iw + i.right + i.left, iw + i.top + i.bottom);
		}

		private void initShape(JComponent c) {
			if (!c.getBounds().equals(base)) {
				Dimension s = c.getPreferredSize();
				base = c.getBounds();
				shape = new Ellipse2D.Float(0, 0, s.width - 1, s.height - 1);
			}
		}
	}

	public NodeView getNodeView() {
		return nodeView;
	}

	public void setCorrectedLocation(Point p) {
		int zoomedCircleRadius = getZoomedCircleRadius();
		boolean left = nodeView.getModel().isLeft();
		int xCorrection = (int) (zoomedCircleRadius * (SIZE_FACTOR_ON_MOUSE_OVER + ((left) ? +1f
				: -1f)));
		setLocation(p.x - xCorrection, (int) (p.y - zoomedCircleRadius
				* SIZE_FACTOR_ON_MOUSE_OVER));
	}

	public void dispose() {
		if (mTimer != null) {
			stopTimer();
			mTimer = null;
		}
	}

	protected boolean isFolded() {
		MindMapNode model = nodeView.getModel();
		return model.isFolded() && model.isVisible();
	}

	protected synchronized void startTimer() {
		if (!mTimer.isRunning()) {
			mTimer.start();
		}
	}

	protected synchronized void stopTimer() {
		if (mTimer.isRunning()) {
			mTimer.stop();
		}
	}

}
