/* Copyright (C) 2003-2011 Raik Nagel
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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package net.sf.jabref.about ;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageProducer;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.UIManager;
import javax.swing.border.BevelBorder;
import net.sf.jabref.GUIGlobals;
import net.sf.jabref.Globals;
// AboutPanel class
public class AboutPanel extends JComponent
{
private Vector<TextBlock> textBlocks ;
private String versionStr ;
private String buildStr ;
private AnimationThread thread;
private ImageIcon image;
// animated text positions
public int TOP = 300 ; // offset from top - hide
public int BOTTOM = 0 ; // show
public int HEIGHT = 500 ;
public int WIDTH = 500 ;
private int borders[] ; // Border-Coordinates of paintarea (xLeft, xRight, yTop, yBottom)
private int paintWidth ;
private Font font1 ;
private Font font2 ;
private Font font3 ;
private AnimationListener aniListener ;
private ImageProducer iProducer ;
AboutPanel()
{
Font font = loadFont("ASTROLYT.TTF") ;
font1 = font.deriveFont(Font.BOLD, (float) 14.0) ;
font2 = font.deriveFont(Font.BOLD, (float) 20.0) ;
font = loadFont("AUGIE.TTF") ;
font3 = font.deriveFont(Font.BOLD, (float) 14.0) ;
versionStr = "Version " + Globals.VERSION ;
buildStr = " build " + Globals.BUILD ;
image = new ImageIcon(getClass().getResource("/images/autumn.png"));
HEIGHT = image.getIconHeight() ;
WIDTH = image.getIconWidth() ;
FontMetrics fm = getFontMetrics( font2 ) ;
TOP = 2*fm.getHeight() ;
fm = getFontMetrics( font1 ) ;
BOTTOM = 2*fm.getHeight() ;
borders = new int[4] ;
borders[0] = 0 ;
borders[1] = WIDTH ;
borders[2] = TOP ;
borders[3] = HEIGHT - TOP - BOTTOM ;
paintWidth = borders[1] - borders[0] ;
setForeground( Color.black) ;
setBackground( Color.white) ;
setBorder ( BorderFactory.createBevelBorder( BevelBorder.RAISED)) ;
textBlocks = new Vector<TextBlock>( 50 ) ;
loadAboutText() ;
this.setDoubleBuffered(true);
thread = new AnimationThread();
}
// ----------------------------------------------------------------------------
public void addAnimationListener(AnimationListener listener)
{
aniListener = listener ;
}
// ----------------------------------------------------------------------------
// returns
private int getMiddleX(String text, Font font)
{
FontMetrics fm = getFontMetrics(font);
return ( paintWidth/2 - ((fm.stringWidth(text) + 10) / 2)) ;
}
// ----------------------------------------------------------------------------
private Font loadFont(String fontName)
{
Font back = UIManager.getFont("Label.font") ;
try
{
InputStream myStream = getClass().getResourceAsStream(GUIGlobals.fontPath + fontName) ;
back = Font.createFont(Font.TRUETYPE_FONT, myStream) ;
}
catch (Exception e) { System.out.println(e) ; }
return back ;
}
// ----------------------------------------------------------------------------
private final void loadAboutText()
{
TextBlock block = null ;
AboutTextLine aLine = null ;
int index = -3 ;
FontMetrics fm = getFontMetrics(font3);
try
{
InputStream stream = getClass().getResourceAsStream(GUIGlobals.getLocaleHelpPath() + "credits.txt" ) ;
if (stream == null)
{
stream = getClass().getResourceAsStream( GUIGlobals.helpPre +
"credits.txt" ) ;
}
InputStreamReader reader = new InputStreamReader( stream ) ;
BufferedReader input = new BufferedReader(reader, 1000) ;
while ( input.ready() )
{
String line = input.readLine() ;
if (line != null)
{
line = line.trim() ;
if (line.length() > 0)
{
if (line.charAt(0) == '#') // new Block....
{
if (block != null) //insert previous block
{
textBlocks.add(block) ;
index+=2 ;
}
aLine = new AboutTextLine( line.substring(1).trim()) ;
aLine.setTag(2);
aLine.setPos(getMiddleX(aLine.getText(), font2), borders[0] -fm.getHeight()*(index+3)*1.5);
aLine.setDirection(0.0, 1.0);
aLine.setFont(font2);
block = new TextBlock() ;
block.setHeading(aLine);
block.setVisible(true);
}
else // Blocklines
{
aLine = new AboutTextLine( line.trim() ) ;
aLine.setPos( getMiddleX( line, font3 ),
borders[3] + ( index * fm.getHeight() * 1.5 ) ) ;
aLine.setTag( 10 ) ;
aLine.setDirection( 0.0, -1.0 ) ;
aLine.setFont( font3 ) ;
block = new TextBlock() ;
block.add( aLine ) ;
block.setVisible(true);
index++ ;
}
}
}
}
input.close() ;
}
catch ( Exception e )
{
block = new TextBlock() ;
block.setHeading( new AboutTextLine("failure") );
String line = "no infos available" ;
aLine = new AboutTextLine( line ) ;
block.add( aLine ) ;
}
textBlocks.add(block); // insert last block
}
// ----------------------------------------------------------------------------
public void paintComponent( Graphics g )
{
if (thread.mode == 0)
{
thread.start();
// thread.setEnabled(true);
}
else
if (thread.mode == 1)
{
image.paintIcon(this, g, 0, 0);
FontMetrics fm = g.getFontMetrics( font1 ) ;
int x1 = ( getWidth() - fm.stringWidth( versionStr ) ) / 2 ;
int y1 = getHeight() - fm.getHeight() - 4 ;
int y2 = getHeight() - 5 ;
/*
int x1 = ( getWidth() - fm.stringWidth( versionStr ) ) / 2 ;
int y1 = 4 ;
int y2 = fm.getHeight() +4 ;
*/
g.setFont( font1 ) ;
g.setColor( Color.black ) ;
g.drawString( versionStr, x1, y1 ) ;
g.drawString( buildStr, x1, y2 ) ;
g.setFont( font2) ;
fm = g.getFontMetrics( font2 ) ;
g.drawString( "JabRef", (getWidth() - fm.stringWidth("JabRef")) /2, fm.getHeight()+10) ;
for ( TextBlock block : textBlocks){
if (block.isVisible()) // only if Block is marked as visible
{
// print Heading
AboutTextLine head = block.getHeading() ;
drawLine(head, g) ;
for (AboutTextLine line : block){
drawLine(line, g) ;
}
}
}
}
else
{
image.paintIcon(this, g, 0, 0);
}
}
// ----------------------------------------------------------------------------
private void drawLine(AboutTextLine line, Graphics g)
{
int x = line.getPosX() ;
int y = line.getPosY() ;
if ( ( x > borders[0] - 10 ) && ( x < borders[1] + 10 ) &&
( y > borders[2] - 10 ) && ( y < borders[3] + 10 ) )
{
if ( line.getVisible() )
{
g.setFont( line.getFont() ) ;
g.setColor( line.getColor() ) ;
g.drawString( line.getText(), line.getPosX(), line.getPosY() ) ;
}
}
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
public Dimension getPreferredSize()
{
return new Dimension( WIDTH, HEIGHT ) ;
}
public void removeNotify()
{
super.removeNotify();
thread.kill();
}
public void skipAnimation()
{
thread.kill() ;
if (aniListener != null) aniListener.animationReady();
}
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
class AnimationThread extends Thread
{
private boolean running = true ;
private double help01 = 1.0 ;
private int mode = 0 ;
public int sleepTime = 50 ;
private int zone2Counter = 0 ;
private boolean runMode = true ;
AnimationThread()
{
super( "About box animation thread" ) ;
setPriority( Thread.MIN_PRIORITY ) ;
}
public void kill()
{
running = false ;
}
public void setEnabled(boolean onOff) { runMode = onOff ; }
public synchronized void setMode(int newMode) { mode = newMode ; }
public void run()
{
Object mutex = new Object() ;
mode = 1 ;
runMode = true ;
while ( running )
{
synchronized(mutex)
{
try
{
do
{
mutex.wait( sleepTime ) ;
} while (!runMode) ;
}
catch ( Exception e )
{
}
}
if (mode == 1) // Textanimation
{
int counter = 0 ;
for ( Enumeration<TextBlock> myE = textBlocks.elements() ; myE.hasMoreElements() ; )
{
TextBlock block = myE.nextElement() ;
AboutTextLine head = block.getHeading() ;
counter = performStep(head) ;
for (AboutTextLine line : block){
counter += performStep( line ) ;
}
}
if (counter < 1)
{
mode = 2 ;
}
repaint(borders[0]-10, borders[2]-10, borders[1]+10, borders[3]+10) ;
}
else if (mode == 2) // Picture animation
{
if (sleepTime < 2)
sleepTime = 5 ;
else
sleepTime -= sleepTime / 3 ;
image.setImage( createImage( iProducer) );
repaint(0, 0, WIDTH, HEIGHT) ;
}
}
}
private int performStep(AboutTextLine line)
{
int back = 0 ;
line.performTimeStep( 1.0 ) ;
if ( line.getTag() == 2 ) // Heading
{
int zone = (int) (HEIGHT / 3.5) ;
if ( line.getPosY() > zone )
{
line.setSpeed( 0.0 ) ;
line.setTag( 4 ) ;
zone2Counter = 0 ;
} else
if ( line.getPosY() > ( zone - 10) )
{
zone2Counter=1 ;
}
back++ ;
}
else if ( line.getTag() == 4) // Heading Blender
{
if (zone2Counter < 1)
{
Color col = line.getColor() ;
int rgb = col.getRGB() + 1023 ;
line.setColor( new Color( rgb ) ) ;
}
else
{
line.setVisible(false);
line.setTag(5);
}
}
else if ( line.getTag() == 10 ) // scrolling text
{
if ( line.getPosY() < ( HEIGHT / 3 ) )
{
line.setDirection( help01, 0.0 ) ;
line.setAccel( 0.5 ) ;
line.setTag( 11 ) ;
help01 = help01 * -1.0 ;
}
back = 1 ;
}
else if (line.getTag() == 11) // text line out
{
if ((line.getPosX() < -100) || (line.getPosX() > WIDTH+100))
{
line.setTag(12);
line.setVisible(false);
}
back = 1 ;
}
return back ;
}
}
}