/*
* AboutDialog.java - About jEdit dialog box
* :tabSize=4:indentSize=4:noTabs=false:
* :folding=explicit:collapseFolds=1:
*
* Copyright (C) 2000, 2001, 2002 Slava Pestov
*
* 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 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.
*/
package org.gjt.sp.jedit.gui;
//{{{ Imports
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.util.*;
import java.util.List;
import org.gjt.sp.jedit.*;
import org.gjt.sp.util.Log;
//}}}
/** "About jEdit" dialog
*/
public class AboutDialog extends JDialog implements ActionListener
{
//{{{ AboutDialog constructor
public AboutDialog(View view)
{
super(view,jEdit.getProperty("about.title"), true);
setResizable(false);
JButton closeBtn = new JButton(jEdit.getProperty("common.close"));
closeBtn.addActionListener(this);
getRootPane().setDefaultButton(closeBtn);
JPanel p = new JPanel(new BorderLayout());
final AboutPanel aboutPanel = new AboutPanel();
JPanel flowP = new JPanel(new FlowLayout());
flowP.add(closeBtn);
flowP.add(Box.createRigidArea(new Dimension(40, 40)));
Dimension dim = new Dimension(10, 0);
p.add(BorderLayout.WEST, Box.createRigidArea(dim));
p.add(BorderLayout.EAST, Box.createRigidArea(dim));
p.add(BorderLayout.NORTH, Box.createRigidArea(new Dimension(10, 10)));
p.add(BorderLayout.SOUTH, flowP);
p.add(BorderLayout.CENTER, aboutPanel);
closeBtn.setToolTipText(jEdit.getProperty("about.navigate"));
closeBtn.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
aboutPanel.handleKeyEvent(e);
}
});
setContentPane(p);
pack();
setLocationRelativeTo(jEdit.getActiveView());
addWindowListener(new WindowAdapter()
{
@Override
public void windowClosing(WindowEvent e)
{
closeDialog();
}
});
setVisible(true);
} //}}}
//{{{ actionPerformed() method
public void actionPerformed(ActionEvent e)
{
closeDialog();
} //}}}
//{{{ closeDialog() method
private void closeDialog()
{
AboutPanel.stopThread();
dispose();
} //}}}
//{{{ AboutPanel class
private static class AboutPanel extends JComponent implements Runnable
{
private BufferedImage bufImage;
private Graphics2D g;
private static final Font defaultFont = UIManager.getFont("Label.font");
private final Font bottomLineFont = defaultFont.deriveFont(9.8f);
private final String sBottomLine;
private final ImageIcon image;
private final List<String> vLines;
private static boolean doWork;
private Thread th;
private final FontMetrics fm;
private int iLineHeight = 0, iListHeight, iLineCount = 0,
iBottomLineXOffset = 0, iBottomLineYOffset = 0,
iPipeLineCount = 0, w = 0, h = 0, y = 0;
private static final int
SLEEP_TIME = 30,
iBottomPadding = 36,
iTopPadding = 120;
private static Rectangle2D.Float rectangle;
private static GradientPaint gradientPaint;
private boolean skipDrain = false;
AboutPanel()
{
String mode;
if (jEdit.getEditServer() != null)
{
if (jEdit.isBackgroundModeEnabled())
mode = jEdit.getProperty("about.mode.server-background");
else
mode = jEdit.getProperty("about.mode.server");
}
else
mode = jEdit.getProperty("about.mode.standalone");
String[] args = { jEdit.getVersion(), mode, System.getProperty("java.vendor"), System.getProperty("java.version") };
sBottomLine = jEdit.getProperty("about.version",args);
setFont(defaultFont);
fm = getFontMetrics(defaultFont);
FontMetrics fmBottom = getFontMetrics(bottomLineFont);
iLineHeight = fm.getHeight();
image = (ImageIcon)GUIUtilities.loadIcon("about.png");
MediaTracker tracker = new MediaTracker(this);
tracker.addImage(image.getImage(), 0);
try
{
tracker.waitForID(0);
}
catch(Exception exc)
{
tell("AboutPanel: " + exc);
}
Dimension d = new Dimension(image.getIconWidth(), image.getIconHeight());
setSize(d);
setPreferredSize(d);
w = d.width;
h = d.height;
iBottomLineXOffset = (w / 2) - (fmBottom.stringWidth(sBottomLine) / 2);
iBottomLineYOffset = h-iLineHeight/2;
String aboutText = jEdit.getProperty("about.text.prefix") + "\n \n"
+ jEdit.getProperty("about.text.contributors") + "\n \n" +
jEdit.getProperty("about.text.suffix");
String[] contributors = aboutText.split("\n");
vLines = Arrays.asList(contributors);
iLineCount = vLines.size();
iListHeight = iLineCount * iLineHeight;
startThread();
updateUI();
}
private void handleKeyEvent(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_DOWN)
{
skipDrain = false;
Collections.rotate(vLines, -1);
}
else if (e.getKeyCode() == KeyEvent.VK_UP)
{
skipDrain = false;
Collections.rotate(vLines, 1);
}
else if ((e.getKeyCode() == KeyEvent.VK_LEFT) ||
(e.getKeyCode() == KeyEvent.VK_RIGHT) ||
(e.getKeyCode() == KeyEvent.VK_SPACE))
{
skipDrain = ! skipDrain;
e.consume();
}
else if ((e.getKeyCode()) == KeyEvent.VK_ESCAPE)
{
e.consume();
JDialog d = GUIUtilities.getParentDialog(this);
stopThread();
d.dispose();
}
}
private void drain()
{
if (skipDrain)
return;
if (bufImage == null)
{
//pre-computing all data that can be known at this time
Dimension d = getSize();
bufImage = new BufferedImage(d.width, d.height,
BufferedImage.TYPE_INT_RGB);
g = bufImage.createGraphics();
rectangle = new Rectangle2D.Float(0, iTopPadding,
d.width, d.height-iBottomPadding-iTopPadding);
//"+1" makes sure every new line from below comes up smoothly
//cause it gets pre-painted and clipped as needed
iPipeLineCount = 1 + (int)Math.ceil(rectangle.height/iLineHeight);
y = d.height+iBottomPadding;
g.setFont(defaultFont);
gradientPaint = new GradientPaint(
rectangle.width/2, iTopPadding+80, new Color(80, 80, 80),
rectangle.width/2, iTopPadding, new Color(205, 205, 205)
);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}
g.drawImage(image.getImage(), 0, 0, w, h, this);
g.setFont(bottomLineFont);
g.setPaint(new Color(55, 55, 55));
g.drawString(sBottomLine, iBottomLineXOffset, iBottomLineYOffset);
// Draw a highlight effect
g.setPaint(new Color(255, 255, 255, 50));
g.drawString(sBottomLine, iBottomLineXOffset + 1, iBottomLineYOffset + 1);
g.setFont(defaultFont);
g.setPaint(Color.black);
g.drawRect(0, 0, w-1, h-1);
g.clip(rectangle);
g.setPaint(gradientPaint);
int iDrawnLinesCount = 0, yCoor = 0;
for (int i=0; i<iLineCount; i++)
{
//check whether the text line is above the canvas, if so, the code skips it
yCoor = y+ i * iLineHeight;
if (yCoor < iTopPadding)
{
continue;
}
//good to go, now draw only iPipeLineCount lines and get out from loop
String sLine = vLines.get(i);
int x = (w - fm.stringWidth(sLine))/2;
g.drawString(sLine, x, yCoor);
if (++iDrawnLinesCount >= iPipeLineCount)
{
break;
}
}
y--;
paint(getGraphics());
//check if the end of the list has been reached,
//if so rewind
if ((y + iListHeight) < iTopPadding)
{
y = h+iBottomPadding;
}
}
@Override
public void update(Graphics g)
{
paint(g);
}
@Override
public void paint(Graphics panelGraphics)
{
if (panelGraphics != null && bufImage != null)
{
panelGraphics.drawImage(bufImage, 0, 0, w, h, this);
}
}
public void run()
{
try
{
while(doWork)
{
drain();
Thread.sleep(SLEEP_TIME);
}
}
catch(Exception exc)
{
Log.log(Log.ERROR, this, exc);
}
doWork = false;
th = null;
}
public void startThread()
{
if (th == null)
{
th = new Thread(this);
doWork = true;
th.start();
}
}
public static void stopThread()
{
doWork = false;
}
public static void tell(Object obj)
{
String str = obj == null ? "NULL" : obj.toString();
JOptionPane.showMessageDialog(jEdit.getActiveView(), str, "Title", 1);
}
} //}}}
}