f4f3c4bb96f7326826b396f9496b946434d9f93e
[debian/jabref.git] / src / java / net / sf / jabref / about / AboutPanel.java
1 /*
2  animated about dialog
3
4 Copyright (C) 2005 Raik Nagel <kiar@users.sourceforge.net>
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9
10 * Redistributions of source code must retain the above copyright notice,
11   this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright notice,
13   this list of conditions and the following disclaimer in the documentation
14   and/or other materials provided with the distribution.
15 * Neither the name of the author nor the names of its contributors may be
16   used to endorse or promote products derived from this software without
17   specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
23 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31 // created by : r.nagel 05.05.2005
32 //
33 // todo     :
34 //
35 // modified :
36
37
38 package net.sf.jabref.about ;
39
40 import java.io.* ;
41 import java.util.* ;
42
43 import java.awt.* ;
44 import java.awt.image.* ;
45 import javax.swing.* ;
46 import javax.swing.border.* ;
47
48 import net.sf.jabref.* ;
49
50 // AboutPanel class
51 public class AboutPanel extends JComponent
52 {
53   private Vector textBlocks ;
54   private String versionStr ;
55   private String buildStr ;
56   private AnimationThread thread;
57   private ImageIcon image;
58
59
60   // animated text positions
61   public int TOP = 300 ; // offset from top - hide
62   public int BOTTOM = 0 ; // show
63
64   public int HEIGHT = 500 ;
65   public int WIDTH = 500 ;
66
67   private int borders[] ;  // Border-Coordinates of paintarea (xLeft, xRight, yTop, yBottom)
68   private int paintWidth ;
69
70   private Font font1 ;
71   private Font font2 ;
72   private Font font3 ;
73
74   private AnimationListener aniListener ;
75   private ImageProducer iProducer ;
76   private HighlightFilter filter ;
77
78   AboutPanel()
79   {
80     Font font = loadFont("ASTROLYT.TTF") ;
81     font1 = font.deriveFont(Font.BOLD, (float) 14.0) ;
82     font2 = font.deriveFont(Font.BOLD, (float) 20.0) ;
83
84     font = loadFont("AUGIE.TTF") ;
85     font3 = font.deriveFont(Font.BOLD, (float) 14.0) ;
86
87     versionStr = "Version " + Globals.VERSION ;
88     buildStr = " build " + Globals.BUILD ;
89
90     image = new ImageIcon(getClass().getResource("/images/autumn.png"));
91
92     filter = new HighlightFilter(false, 5) ;
93     filter.setMiddle(image.getIconWidth(), image.getIconHeight());
94     iProducer = new FilteredImageSource( image.getImage().getSource(), filter) ;
95
96     HEIGHT = image.getIconHeight() ;
97     WIDTH = image.getIconWidth() ;
98
99     FontMetrics fm = getFontMetrics( font2 ) ;
100     TOP = 2*fm.getHeight() ;
101     fm = getFontMetrics( font1 ) ;
102     BOTTOM = 2*fm.getHeight() ;
103
104     borders = new int[4] ;
105     borders[0] = 0 ;
106     borders[1] = WIDTH ;
107     borders[2] = TOP ;
108     borders[3] = HEIGHT - TOP - BOTTOM ;
109
110
111     paintWidth = borders[1] - borders[0] ;
112
113     setForeground( Color.black) ;
114     setBackground( Color.white) ;
115
116     setBorder ( BorderFactory.createBevelBorder( BevelBorder.RAISED)) ;
117
118     textBlocks = new Vector( 50 ) ;
119
120     loadAboutText() ;
121
122     this.setDoubleBuffered(true);
123
124     thread = new AnimationThread();
125   }
126 // ----------------------------------------------------------------------------
127
128   public void addAnimationListener(AnimationListener listener)
129   {
130     aniListener = listener ;
131   }
132
133 // ----------------------------------------------------------------------------
134
135   // returns
136   private int getMiddleX(String text, Font font)
137   {
138     FontMetrics fm = getFontMetrics(font);
139     return ( paintWidth/2 - ((fm.stringWidth(text) + 10) / 2)) ;
140   }
141
142 // ----------------------------------------------------------------------------
143
144   private Font loadFont(String fontName)
145   {
146     Font back = UIManager.getFont("Label.font") ;
147     try
148     {
149       InputStream myStream = getClass().getResourceAsStream(GUIGlobals.fontPath + fontName) ;
150       back = Font.createFont(Font.TRUETYPE_FONT, myStream) ;
151     }
152     catch (Exception e) { System.out.println(e) ; }
153
154     return back ;
155   }
156
157 // ----------------------------------------------------------------------------
158
159   private final void loadAboutText()
160   {
161     TextBlock block = null ;
162     AboutTextLine aLine = null ;
163
164     int index = -3 ;
165     FontMetrics fm = getFontMetrics(font3);
166     try
167     {
168       InputStream stream = getClass().getResourceAsStream(GUIGlobals.getLocaleHelpPath() + "credits.txt" ) ;
169       if (stream == null)
170       {
171         stream = getClass().getResourceAsStream( GUIGlobals.helpPre +
172                                                  "credits.txt" ) ;
173       }
174       InputStreamReader reader = new InputStreamReader( stream ) ;
175 //          getClass().getResourceAsStream(GUIGlobals.getLocaleHelpPath() + "credits.txt" ) ) ;
176 //          getClass().getResourceAsStream( "/help/credits.txt" ) ) ;
177       BufferedReader input = new BufferedReader(reader, 1000) ;
178
179 //      System.out.println("encoding :" +reader.getEncoding() ) ;
180
181       while ( input.ready() )
182       {
183         String line = input.readLine() ;
184
185         if (line != null)
186         {
187           line = line.trim() ;
188
189           if (line.length() > 0)
190           {
191             if (line.charAt(0) == '#')  // new Block....
192             {
193               if (block != null)  //insert previous block
194               {
195                 textBlocks.add(block) ;
196                 index+=2 ;
197               }
198
199               aLine = new AboutTextLine( line.substring(1).trim()) ;
200               aLine.setTag(2);
201               aLine.setPos(getMiddleX(aLine.getText(), font2), borders[0] -fm.getHeight()*(index+3)*1.5);
202               aLine.setDirection(0.0, 1.0);
203               aLine.setFont(font2);
204
205               block = new TextBlock() ;
206               block.setHeading(aLine);
207               block.setVisible(true);
208
209             }
210             else  // Blocklines
211             {
212               aLine = new AboutTextLine( line.trim() ) ;
213               aLine.setPos( getMiddleX( line, font3 ),
214                             borders[3] + ( index * fm.getHeight() * 1.5 ) ) ;
215               aLine.setTag( 10 ) ;
216               aLine.setDirection( 0.0, -1.0 ) ;
217               aLine.setFont( font3 ) ;
218
219 //              System.out.println( "line " +aLine.getText() +"<" +(borders[3] + ( index * fm.getHeight() * 1.5 )) +">" ) ;
220
221               block.add( aLine ) ;
222               index++ ;
223             }
224           }
225         }
226       }
227       input.close() ;
228     }
229
230     catch ( Exception e )
231     {
232       block = new TextBlock() ;
233       block.setHeading( new AboutTextLine("failure") );
234       String line = "no infos available" ;
235       aLine = new AboutTextLine( line ) ;
236       block.add( aLine ) ;
237     }
238
239     textBlocks.add(block);  // insert last block
240   }
241
242 // ----------------------------------------------------------------------------
243
244   public void paintComponent( Graphics g )
245   {
246     if (thread.mode == 0)
247     {
248       thread.start();
249 //      thread.setEnabled(true);
250     }
251     else
252     if (thread.mode == 1)
253     {
254       image.paintIcon(this, g, 0, 0);
255
256       FontMetrics fm = g.getFontMetrics( font1 ) ;
257
258       int x1 = ( getWidth() - fm.stringWidth( versionStr ) ) / 2 ;
259       int y1 = getHeight() - fm.getHeight() - 4 ;
260       int y2 = getHeight() - 5 ;
261 /*
262       int x1 = ( getWidth() - fm.stringWidth( versionStr ) ) / 2 ;
263       int y1 = 4 ;
264       int y2 = fm.getHeight() +4 ;
265 */
266       g.setFont( font1 ) ;
267
268       g.setColor( Color.black ) ;
269       g.drawString( versionStr, x1, y1 ) ;
270       g.drawString( buildStr, x1, y2 ) ;
271
272       g.setFont( font2) ;
273       fm = g.getFontMetrics( font2 ) ;
274       g.drawString( "JabRef", (getWidth() - fm.stringWidth("JabRef")) /2, fm.getHeight()+10) ;
275
276
277       for ( Enumeration myE = textBlocks.elements() ; myE.hasMoreElements() ; )
278       {
279         TextBlock block = (TextBlock) myE.nextElement() ;
280
281         if (block.isVisible()) // only if Block is marked as visible
282         {
283           // print Heading
284           AboutTextLine head = block.getHeading() ;
285           drawLine(head, g) ;
286
287           for ( Enumeration myEnum = block.getEnumeration() ; myEnum.hasMoreElements() ; )
288           {
289             AboutTextLine line = ( AboutTextLine ) myEnum.nextElement() ;
290             drawLine(line, g) ;
291           }
292         }
293       }
294     }
295     else
296     {
297       image.paintIcon(this, g, 0, 0);
298       if (filter.isReady())
299       {
300         skipAnimation() ;
301       }
302     }
303   }
304 // ----------------------------------------------------------------------------
305
306   private void drawLine(AboutTextLine line, Graphics g)
307   {
308     int x = line.getPosX() ;
309     int y = line.getPosY() ;
310     if ( ( x > borders[0] - 10 ) && ( x < borders[1] + 10 ) &&
311          ( y > borders[2] - 10 ) && ( y < borders[3] + 10 ) )
312     {
313       if ( line.getVisible() )
314       {
315         g.setFont( line.getFont() ) ;
316         g.setColor( line.getColor() ) ;
317         g.drawString( line.getText(), line.getPosX(), line.getPosY() ) ;
318       }
319     }
320   }
321 // ----------------------------------------------------------------------------
322 // ----------------------------------------------------------------------------
323
324   public Dimension getPreferredSize()
325   {
326     return new Dimension( WIDTH, HEIGHT ) ;
327   }
328
329   public void removeNotify()
330   {
331     super.removeNotify();
332     thread.kill();
333   }
334
335   public void skipAnimation()
336   {
337     thread.kill() ;
338     if (aniListener != null) aniListener.animationReady();
339   }
340
341 // ---------------------------------------------------------------------------
342 // ---------------------------------------------------------------------------
343
344   class AnimationThread extends Thread
345   {
346     private boolean running = true ;
347     private double help01 = 1.0 ;
348     private int mode = 0 ;
349     public int sleepTime = 50 ;
350     private int zone2Counter = 0 ;
351     private boolean runMode = true ;
352
353     AnimationThread()
354     {
355       super( "About box animation thread" ) ;
356       setPriority( Thread.MIN_PRIORITY ) ;
357     }
358
359     public void kill()
360     {
361       running = false ;
362     }
363
364     public void setEnabled(boolean onOff) { runMode = onOff ; }
365
366     public synchronized void setMode(int newMode) { mode = newMode ; }
367
368     public void run()
369     {
370       Object mutex = new Object() ;
371
372       mode = 1 ;
373       runMode = true ;
374       while ( running )
375       {
376
377         synchronized(mutex)
378         {
379           try
380           {
381             do
382             {
383               mutex.wait( sleepTime ) ;
384             } while (!runMode) ;
385           }
386           catch ( Exception e )
387           {
388           }
389         }
390         if (mode == 1)  // Textanimation
391         {
392           int counter = 0 ;
393
394           for ( Enumeration myE = textBlocks.elements() ; myE.hasMoreElements() ; )
395           {
396             TextBlock block = ( TextBlock ) myE.nextElement() ;
397             AboutTextLine head = block.getHeading() ;
398             counter = performStep(head) ;
399
400             for ( Enumeration myEnum = block.getEnumeration() ; myEnum.hasMoreElements() ; )
401             {
402               AboutTextLine line = ( AboutTextLine ) myEnum.nextElement() ;
403               counter += performStep( line ) ;
404             }
405           }
406           if (counter < 1)
407           {
408             mode = 2 ;
409           }
410           repaint(borders[0]-10, borders[2]-10, borders[1]+10, borders[3]+10) ;
411         }
412         else if (mode == 2)  // Picture animation
413         {
414           if (sleepTime < 2)
415             sleepTime = 5 ;
416           else
417             sleepTime -= sleepTime / 3 ;
418
419           image.setImage( createImage( iProducer) );
420           filter.nextStep();
421           repaint(0, 0, WIDTH, HEIGHT) ;
422         }
423       }
424     }
425
426     private int performStep(AboutTextLine line)
427     {
428       int back = 0 ;
429
430       line.performTimeStep( 1.0 ) ;
431
432       if ( line.getTag() == 2 )  // Heading
433       {
434         int zone = (int) (HEIGHT / 3.5) ;
435         if ( line.getPosY() > zone )
436         {
437           line.setSpeed( 0.0 ) ;
438           line.setTag( 4 ) ;
439           zone2Counter = 0 ;
440         } else
441         if ( line.getPosY() > ( zone - 10) )
442         {
443           zone2Counter=1 ;
444         }
445         back++ ;
446       }
447       else if ( line.getTag() == 4) // Heading Blender
448       {
449         if (zone2Counter < 1)
450         {
451           Color col = line.getColor() ;
452           int rgb = col.getRGB() + 1023 ;
453           line.setColor( new Color( rgb ) ) ;
454         }
455         else
456         {
457           line.setVisible(false);
458           line.setTag(5);
459         }
460       }
461       else if ( line.getTag() == 10 )  // scrolling text
462       {
463         if ( line.getPosY() < ( HEIGHT / 3 ) )
464         {
465           line.setDirection( help01, 0.0 ) ;
466           line.setAccel( 0.5 ) ;
467           line.setTag( 11 ) ;
468           help01 = help01 * -1.0 ;
469         }
470         back = 1 ;
471       }
472       else if (line.getTag() == 11) // text line out
473       {
474          if ((line.getPosX() < -100) || (line.getPosX() > WIDTH+100))
475          {
476            line.setTag(12);
477            line.setVisible(false);
478          }
479          back = 1 ;
480       }
481
482       return back ;
483     }
484   }
485
486 }
487