/*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();
}
}
}