/**
* Copyright (C) 2002-2012 The FreeCol Team
*
* This file is part of FreeCol.
*
* FreeCol 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.
*
* FreeCol 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 FreeCol. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.freecol.client.gui.panel;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.logging.Logger;
import javax.swing.JPanel;
import javax.swing.Timer;
import net.sf.freecol.client.FreeColClient;
import net.sf.freecol.client.gui.GUI;
import net.sf.freecol.common.resources.FAFile;
import net.sf.freecol.common.resources.ResourceManager;
import net.sf.freecol.common.util.Utils;
/**
* This panel displays the signing of the Declaration of Independence.
*/
public final class DeclarationDialog extends FreeColDialog<Boolean> {
@SuppressWarnings("unused")
private static final Logger logger = Logger.getLogger(DeclarationDialog.class.getName());
private final SignaturePanel signaturePanel;
private final DeclarationDialog theDialog = this;
/**
* Creates a DeclarationDialog.
*
* @param freeColClient The <code>FreeColClient</code> for the game.
* @param gui The <code>GUI</code> to display on.
*/
public DeclarationDialog(FreeColClient freeColClient, GUI gui) {
super(freeColClient, gui);
this.signaturePanel = new SignaturePanel();
setLayout(null);
Image image = ResourceManager.getImage("Declaration.image");
setSize(image.getWidth(null), image.getHeight(null));
setOpaque(false);
setBorder(null);
signaturePanel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e2) {
theDialog.setResponse(Boolean.TRUE);
}
};
Timer t = new Timer(10000, al);
t.setRepeats(false);
t.start();
}
});
add(signaturePanel);
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
theDialog.setResponse(Boolean.TRUE);
}
});
initialize();
}
/**
* Paints an image of the Declaration of Independence on this panel.
*/
public void paintComponent(Graphics g) {
Image image = ResourceManager.getImage("Declaration.image");
g.drawImage(image, 0, 0, null);
}
/**
* Initializes this panel.
*/
public void initialize() {
final int SIGNATURE_Y = 450;
resetResponse();
signaturePanel.initialize(getMyPlayer().getName());
signaturePanel.setLocation((getWidth() - signaturePanel.getWidth()) / 2,
(getHeight() + SIGNATURE_Y - signaturePanel.getHeight()) / 2 - 15);
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e) {
signaturePanel.startAnimation();
}
};
Timer t = new Timer(2000, al);
t.setRepeats(false);
t.start();
}
/**
* A panel for displaying an animated signature.
*
* <br>
* <br>
*
* The panel should be {@link #initialize(String) initialized} with a name
* before the animation is {@link #startAnimation() started}.
*/
private class SignaturePanel extends JPanel {
private FAFile faFile;
private ArrayList<ActionListener> actionListeners = new ArrayList<ActionListener>();
private Point[] points = null;
private int counter = 0;
SignaturePanel() {
faFile = (FAFile) ResourceManager.getFAFile("AnimatedFont");
setOpaque(false);
}
/**
* Gets an abbreviated version of the given name.
*
* @param name The name to be abbreviated
* @return The abbreviated version of the given name. The name is made
* small enough to fit within the bounds the
* <code>DeclarationDialog</code>.
*/
private String getAbbreviatedName(String name) {
if (!isTooLarge(name)) {
return name;
}
String[] partNames = name.split(" ");
// Abbreviate middle names:
for (int i = 1; i < partNames.length - 1 && isTooLarge(Utils.join(" ", partNames)); i++) {
partNames[i] = partNames[i].charAt(0) + ".";
}
// Remove middle names:
while (partNames.length > 2 && isTooLarge(Utils.join(" ", partNames))) {
String[] newPartNames = new String[partNames.length - 1];
newPartNames[0] = partNames[0];
for (int i = 1; i < newPartNames.length; i++) {
newPartNames[i] = partNames[i + 1];
}
partNames = newPartNames;
}
if (!isTooLarge(Utils.join(" ", partNames))) {
return Utils.join(" ", partNames);
} else if (!isTooLarge(partNames[0].charAt(0) + ". " + partNames[1])) {
return partNames[0].charAt(0) + ". " + partNames[1];
} else if (!isTooLarge(partNames[0] + " " + partNames[1].charAt(0) + ".")) {
return partNames[0] + " " + partNames[1].charAt(0) + ".";
} else {
return partNames[0].charAt(0) + ". " + partNames[1].charAt(0) + ".";
}
}
/**
* Checks if the given string is to large to be displayed within this
* panel.
*
* @param name The string to be tested.
* @return <code>true</code> if the given string was to large to be
* fully displayed.
*/
private boolean isTooLarge(String name) {
Dimension d = faFile.getDimension(name);
return (d.width > theDialog.getWidth() - 10);
}
/**
* Initializes this panel with the given name.
*
* @param name The name to be used when making the signature.
*/
public void initialize(String name) {
name = getAbbreviatedName(name);
points = faFile.getPoints(name);
counter = 0;
setSize(faFile.getDimension(name));
}
/**
* Adds an <code>ActionListener</code> to this
* <code>SignaturePanel</code>. An event gets fired when the
* animation is stopped.
*
* @param al The <code>ActionListener</code>.
* @see #startAnimation()
*/
public void addActionListener(ActionListener al) {
if (!actionListeners.contains(al)) {
actionListeners.add(al);
}
}
private void notifyStopped() {
for (int i = 0; i < actionListeners.size(); i++) {
actionListeners.get(i).actionPerformed(
new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "AnimationStopped"));
}
}
/**
* Starts the animation of the signature. An <code>ActionEvent</code>
* gets sent to the registered listeners when the animation has stopped.
*
* @see #addActionListener(ActionListener)
*/
public void startAnimation() {
int delay = 50; // milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (counter < points.length - 1) {
counter += 20;
if (counter > points.length) {
counter = points.length - 1;
((Timer) evt.getSource()).stop();
notifyStopped();
}
validate();
repaint();
} else {
((Timer) evt.getSource()).stop();
notifyStopped();
}
}
};
new Timer(delay, taskPerformer).start();
}
/**
* Paints the signature.
*/
public void paintComponent(Graphics g) {
if (points == null || points.length == 0) {
return;
}
if (isOpaque()) {
super.paintComponent(g);
}
g.setColor(Color.BLACK);
((Graphics2D) g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.75f));
for (int i = 0; i < counter-1; i++) {
Point p1 = points[i];
Point p2 = points[i+1];
g.drawLine((int) p1.getX(), (int) p1.getY(),
(int) p2.getX(), (int) p2.getY());
}
}
}
}