Coverage Report - org.jtheque.core.managers.view.impl.components.filthy.java2d.AboutPane
 
Classes in this File Line Coverage Branch Coverage Complexity
AboutPane
0 %
0/145
0 %
0/36
2.227
AboutPane$1
0 %
0/3
N/A
2.227
AboutPane$MouseController
0 %
0/12
0 %
0/10
2.227
AboutPane$MouseMotionController
0 %
0/5
0 %
0/6
2.227
 
 1  
 package org.jtheque.core.managers.view.impl.components.filthy.java2d;
 2  
 
 3  
 import org.jdesktop.animation.timing.Animator;
 4  
 import org.jdesktop.animation.timing.TimingTargetAdapter;
 5  
 import org.jdesktop.animation.timing.triggers.TimingTrigger;
 6  
 import org.jdesktop.animation.timing.triggers.TimingTriggerEvent;
 7  
 import org.jtheque.core.managers.Managers;
 8  
 import org.jtheque.core.managers.core.application.Application;
 9  
 import org.jtheque.core.managers.language.ILanguageManager;
 10  
 import org.jtheque.core.managers.language.Internationalizable;
 11  
 import org.jtheque.core.managers.view.able.IAboutView;
 12  
 import org.jtheque.core.managers.view.able.IViewManager;
 13  
 import org.jtheque.core.utils.ui.AnimationUtils;
 14  
 import org.jtheque.utils.DesktopUtils;
 15  
 import org.jtheque.utils.StringUtils;
 16  
 import org.jtheque.utils.ui.ImageUtils;
 17  
 import org.jtheque.utils.ui.PaintUtils;
 18  
 import org.jtheque.utils.ui.SizeTracker;
 19  
 import org.jtheque.utils.ui.SwingUtils;
 20  
 
 21  
 import javax.annotation.PostConstruct;
 22  
 import java.awt.Color;
 23  
 import java.awt.Component;
 24  
 import java.awt.Cursor;
 25  
 import java.awt.Font;
 26  
 import java.awt.FontMetrics;
 27  
 import java.awt.Graphics;
 28  
 import java.awt.Graphics2D;
 29  
 import java.awt.Rectangle;
 30  
 import java.awt.Shape;
 31  
 import java.awt.event.MouseAdapter;
 32  
 import java.awt.event.MouseEvent;
 33  
 import java.awt.event.MouseMotionAdapter;
 34  
 import java.awt.font.TextAttribute;
 35  
 import java.awt.geom.GeneralPath;
 36  
 import java.awt.geom.Path2D;
 37  
 import java.awt.image.BufferedImage;
 38  
 import java.util.HashMap;
 39  
 import java.util.Map;
 40  
 
 41  
 /*
 42  
  * This file is part of JTheque.
 43  
  *
 44  
  * JTheque is free software: you can redistribute it and/or modify
 45  
  * it under the terms of the GNU General Public License as published by
 46  
  * the Free Software Foundation, either version 3 of the License.
 47  
  *
 48  
  * JTheque is distributed in the hope that it will be useful,
 49  
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 50  
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 51  
  * GNU General Public License for more details.
 52  
  *
 53  
  * You should have received a copy of the GNU General Public License
 54  
  * along with JTheque.  If not, see <http://www.gnu.org/licenses/>.
 55  
  */
 56  
 
 57  
 /**
 58  
  * An about view using filthy paint with Java 2D.
 59  
  *
 60  
  * @author Baptiste Wicht
 61  
  */
 62  0
 public final class AboutPane extends AbstractAboutPane implements IAboutView, Internationalizable {
 63  
     private static final int CREDITS_HEIGHT = 75;
 64  
     private static final int VIEW_HEIGHT = 400;
 65  
     private static final int INFO_MARGIN = 15;
 66  
     private static final int CREDIT_HEIGHT = 25;
 67  
     private static final int INFO_HEIGHT = 20;
 68  
 
 69  0
     private final SizeTracker tracker = new SizeTracker(this);
 70  
 
 71  0
     private int xStart = -1;
 72  0
     private int yStart = -1;
 73  
 
 74  0
     private final Map<String, Shape> shapes = new HashMap<String, Shape>(3);
 75  0
     private final Map<Rectangle, String> urlRectangles = new HashMap<Rectangle, String>(5);
 76  
 
 77  
     private BufferedImage logo;
 78  
     private BufferedImage infosImage;
 79  
     private BufferedImage creditsImage;
 80  
 
 81  
     private Font fontName;
 82  
     private Font fontInfos;
 83  
 
 84  
     private int max;
 85  
 
 86  
     private boolean inited;
 87  
 
 88  
     private int start;
 89  
 
 90  
     private int paintWidth;
 91  
 
 92  
     @Override
 93  
     @PostConstruct
 94  
     void init() {
 95  0
         super.init();
 96  
 
 97  0
         setOpaque(false);
 98  0
         setVisible(true);
 99  
 
 100  0
         Managers.getManager(ILanguageManager.class).addInternationalizable(this);
 101  
 
 102  0
         Application application = Managers.getCore().getApplication();
 103  
 
 104  0
         if (!StringUtils.isEmpty(application.getLogo())) {
 105  
             //We must use directly that, or we can also add prefix file to use as Spring resource
 106  0
             logo = ImageUtils.openCompatibleImageFromFileSystem(application.getLogo() + '.' + application.getLogoType().getExtension());
 107  
         }
 108  
 
 109  0
         inited = false;
 110  
 
 111  0
         addMouseListener(new MouseController());
 112  0
         addMouseMotionListener(new MouseMotionController());
 113  
 
 114  0
         setAnimator(AnimationUtils.createLoopEffect(this, 4 * 1000, "start", getCreditsHeight()));
 115  
 
 116  0
         shapes.put("licence", new GeneralPath()); //Set a default path to avoid NPE if display licence is false
 117  0
     }
 118  
 
 119  
     @Override
 120  
     public void paint(Graphics g) {
 121  0
         Graphics2D g2 = (Graphics2D) g;
 122  
 
 123  0
         if (!inited) {
 124  0
             initView(g2);
 125  
         }
 126  
 
 127  0
         PaintUtils.initHints(g2);
 128  
 
 129  0
         Color textColor = new Color(255, 255, 255, (int) (getAlpha() * 255));
 130  
 
 131  0
         if (tracker.hasSizeChanged()) {
 132  0
             xStart = (getWidth() - paintWidth) / 2;
 133  0
             yStart = (getHeight() - VIEW_HEIGHT) / 2;
 134  
 
 135  0
             calcQuitShape(xStart, yStart);
 136  
         }
 137  
 
 138  0
         paintBackground(g2);
 139  0
         paintTitle(g2, xStart, yStart, textColor);
 140  
 
 141  0
         if (logo != null) {
 142  0
             PaintUtils.drawAlphaImage(g2, logo, xStart, yStart + 65, getAlpha());
 143  
         }
 144  
 
 145  0
         int y = paintInfos(g2, yStart + 65);
 146  
 
 147  0
         y = Math.max(y, 65 + (logo == null ? 0 : logo.getHeight())) + 30;
 148  
 
 149  0
         int x = (getWidth() - creditsImage.getWidth()) / 2;
 150  
 
 151  0
         paintCredits(g2, x, y);
 152  
 
 153  0
         PaintUtils.drawString(g2, getCopyright(), xStart, y + 120, fontInfos, textColor);
 154  
 
 155  0
         paintLicence(g2, textColor, x, y);
 156  
 
 157  0
         tracker.updateSize();
 158  0
     }
 159  
 
 160  
     /**
 161  
      * Paint the infos.
 162  
      *
 163  
      * @param g2     The graphics 2D elements.
 164  
      * @param yStart The y position to start from to paint.
 165  
      * @return The y position stop of the infos.
 166  
      */
 167  
     private int paintInfos(Graphics2D g2, int yStart) {
 168  0
         int startX = logo == null ? 0 : logo.getWidth() + (getWidth() - paintWidth) / 2 + INFO_MARGIN;
 169  
 
 170  0
         if (tracker.hasSizeChanged()) {
 171  0
             createBufferInfosImage(yStart, startX);
 172  
         }
 173  
 
 174  0
         PaintUtils.drawAlphaImage(g2, infosImage, startX, yStart, getAlpha());
 175  
 
 176  0
         return yStart + infosImage.getHeight();
 177  
     }
 178  
 
 179  
     /**
 180  
      * Create the image of the informations to improve performance. The image is only modified when the size of the window
 181  
      * has changed.
 182  
      *
 183  
      * @param yStart The y position to start painting.
 184  
      * @param startX The x position to start painting.
 185  
      */
 186  
     private void createBufferInfosImage(int yStart, int startX) {
 187  0
         infosImage = ImageUtils.createCompatibleImage(paintWidth - 30, getInfos().length * (INFO_HEIGHT + 2), BufferedImage.TRANSLUCENT);
 188  
 
 189  0
         Graphics g = infosImage.getGraphics();
 190  
 
 191  0
         Path2D urlPath = new GeneralPath();
 192  
 
 193  0
         for (int i = 0; i < getInfos().length; i++) {
 194  0
             Info info = getInfos()[i];
 195  
 
 196  0
             int x = max - info.getLeftWidth();
 197  0
             int y = i * INFO_HEIGHT + INFO_HEIGHT;
 198  
 
 199  0
             PaintUtils.drawString(g, info.getLeft() + " : ", x, y, fontInfos);
 200  
 
 201  0
             x += info.getLeftWidth() + INFO_MARGIN;
 202  
 
 203  0
             if (info.isUrl() || info.isMail()) {
 204  0
                 Map<TextAttribute, Object> attributes = new HashMap<TextAttribute, Object>(1);
 205  0
                 attributes.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
 206  
 
 207  0
                 PaintUtils.drawString(g, info.getRight(), x, y, fontInfos.deriveFont(attributes));
 208  
 
 209  0
                 Rectangle rectangle = new Rectangle(startX, yStart + y - 10, info.getRightWidth(), CREDIT_HEIGHT);
 210  
 
 211  0
                 urlPath.append(rectangle, false);
 212  
 
 213  0
                 urlRectangles.put(rectangle, info.getRight());
 214  0
             } else {
 215  0
                 PaintUtils.drawString(g, info.getRight(), x, y, fontInfos);
 216  
             }
 217  
         }
 218  
 
 219  0
         shapes.put("url", urlPath);
 220  
 
 221  0
         g.dispose();
 222  0
     }
 223  
 
 224  
     /**
 225  
      * Paint the licence clickable text.
 226  
      *
 227  
      * @param g2        The graphics 2D elements.
 228  
      * @param textColor The text color.
 229  
      * @param x         The x position to start painting the licence.
 230  
      * @param y         The y position to start painting the licence.
 231  
      */
 232  
     private void paintLicence(Graphics g2, Color textColor, int x, int y) {
 233  0
         if (Managers.getCore().getApplication().isDisplayLicence()) {
 234  0
             Path2D licencePath = new GeneralPath();
 235  
 
 236  0
             int xLicence = x + paintWidth - getFontMetrics(fontInfos).stringWidth(getLicenceMessage());
 237  
 
 238  0
             PaintUtils.drawString(g2, getLicenceMessage(), xLicence, y + 150, fontInfos, textColor);
 239  
 
 240  0
             licencePath.append(new Rectangle(xLicence, y + 140, getFontMetrics(fontInfos).stringWidth(getLicenceMessage()), CREDIT_HEIGHT), false);
 241  
 
 242  0
             shapes.put("licence", licencePath);
 243  
         }
 244  0
     }
 245  
 
 246  
     /**
 247  
      * Paint the credits image.
 248  
      *
 249  
      * @param g2 The graphics 2D elements.
 250  
      * @param x  The x position to start painting the credits image.
 251  
      * @param y  The y position to start painting the credits image.
 252  
      */
 253  
     private void paintCredits(Graphics2D g2, int x, int y) {
 254  0
         if (start >= creditsImage.getHeight()) {
 255  0
             start = 0;
 256  
         }
 257  
 
 258  0
         if (start + CREDITS_HEIGHT > creditsImage.getHeight()) {
 259  0
             int painted = creditsImage.getHeight() - start;
 260  
 
 261  0
             PaintUtils.drawAlphaImage(g2, creditsImage, //Image
 262  
                     x, y, x + creditsImage.getWidth(), y + painted, //Destination
 263  
                     0, start, creditsImage.getWidth(), creditsImage.getHeight(), getAlpha()); //Source
 264  
 
 265  0
             PaintUtils.drawAlphaImage(g2, creditsImage, //Image
 266  
                     x, y + painted, x + creditsImage.getWidth(), y + CREDITS_HEIGHT, //Destination
 267  
                     0, 0, creditsImage.getWidth(), CREDITS_HEIGHT - painted, getAlpha()); //Source
 268  0
         } else {
 269  0
             PaintUtils.drawAlphaImage(g2, creditsImage, //Image
 270  
                     x, y, x + creditsImage.getWidth(), y + CREDITS_HEIGHT, //Destination
 271  
                     0, start, creditsImage.getWidth(), start + CREDITS_HEIGHT, getAlpha()); //Source
 272  
         }
 273  0
     }
 274  
 
 275  
     /**
 276  
      * Paint the title of the view.
 277  
      *
 278  
      * @param g2        The graphics 2D elements.
 279  
      * @param xStart    The x position to start.
 280  
      * @param yStart    The y position to start.
 281  
      * @param textColor The text color.
 282  
      */
 283  
     private void paintTitle(Graphics g2, int xStart, int yStart, Color textColor) {
 284  0
         PaintUtils.drawString(g2, Managers.getCore().getApplication().getName(), xStart, yStart, fontName, textColor);
 285  
 
 286  0
         PaintUtils.fillRect(g2, xStart, yStart + 20, paintWidth, 3, textColor);
 287  0
     }
 288  
 
 289  
     /**
 290  
      * Paint the background.
 291  
      *
 292  
      * @param g2 The graphics 2D elements.
 293  
      */
 294  
     private void paintBackground(Graphics g2) {
 295  0
         Color backgroundColor = new Color(0, 0, 0, (int) (getAlpha() * 255));
 296  
 
 297  0
         PaintUtils.fillRect(g2, 0, 0, getWidth(), getHeight(), backgroundColor);
 298  0
     }
 299  
 
 300  
     /**
 301  
      * Calculate the quit shape.
 302  
      *
 303  
      * @param xStart The x position to start.
 304  
      * @param yStart The y position to start.
 305  
      */
 306  
     private void calcQuitShape(int xStart, int yStart) {
 307  0
         Path2D path = new GeneralPath();
 308  
 
 309  0
         path.append(new Rectangle(0, 0, getWidth(), yStart), false);
 310  0
         path.append(new Rectangle(0, yStart, xStart, VIEW_HEIGHT), false);
 311  0
         path.append(new Rectangle(xStart + paintWidth, yStart, getWidth() - paintWidth - xStart, VIEW_HEIGHT), false);
 312  0
         path.append(new Rectangle(0, yStart + VIEW_HEIGHT, getWidth(), yStart), false);
 313  
 
 314  0
         shapes.put("quit", path);
 315  0
     }
 316  
 
 317  
     /**
 318  
      * Init the view.
 319  
      *
 320  
      * @param g2 The graphics 2D elements.
 321  
      */
 322  
     private void initView(Graphics g2) {
 323  0
         fontName = SwingUtils.getDefaultFont().deriveFont(24f).deriveFont(Font.BOLD);
 324  0
         fontInfos = SwingUtils.getDefaultFont().deriveFont(18f).deriveFont(Font.PLAIN);
 325  
 
 326  0
         computeWidths(g2);
 327  0
         createCreditsImage(g2);
 328  
 
 329  0
         inited = true;
 330  0
     }
 331  
 
 332  
     /**
 333  
      * Compute the widths.
 334  
      *
 335  
      * @param g2 The graphics 2D elements.
 336  
      */
 337  
     private void computeWidths(Graphics g2) {
 338  0
         FontMetrics metrics = getFontMetrics(fontInfos);
 339  
 
 340  0
         int maxRight = 0;
 341  
 
 342  0
         for (Info info : getInfos()) {
 343  0
             info.setLeftWidth(metrics.stringWidth(info.getLeft()));
 344  
 
 345  0
             info.setRightWidth(metrics.stringWidth(info.getRight()));
 346  
 
 347  0
             if (info.isUrl() || info.isMail()) {
 348  0
                 info.setRightWidth(info.getRightWidth() + 5);
 349  
             }
 350  
 
 351  0
             max = Math.max(max, info.getLeftWidth());
 352  0
             maxRight = Math.max(maxRight, info.getRightWidth());
 353  
         }
 354  
 
 355  0
         metrics = g2.getFontMetrics(fontName);
 356  
 
 357  0
         int logoWidth = logo == null ? 0 : logo.getWidth();
 358  
 
 359  0
         paintWidth = Math.max(metrics.stringWidth(Managers.getCore().getApplication().getName()), logoWidth + 30 + max + 20 + maxRight);
 360  0
     }
 361  
 
 362  
     /**
 363  
      * Create the credits image.
 364  
      *
 365  
      * @param g2 The graphics 2D elements.
 366  
      */
 367  
     private void createCreditsImage(Graphics g2) {
 368  0
         creditsImage = ImageUtils.createCompatibleImage(paintWidth - 30, getCredits().size() * CREDIT_HEIGHT, BufferedImage.TRANSLUCENT);
 369  
 
 370  0
         Graphics2D gImage = (Graphics2D) creditsImage.getGraphics();
 371  
 
 372  0
         PaintUtils.initHints(gImage);
 373  
 
 374  0
         FontMetrics metrics = g2.getFontMetrics(fontInfos);
 375  
 
 376  0
         gImage.setFont(fontInfos);
 377  
 
 378  0
         int y = CREDIT_HEIGHT;
 379  0
         for (String credit : getCredits()) {
 380  0
             gImage.drawString(credit, (creditsImage.getWidth() - metrics.stringWidth(credit)) / 2, y);
 381  0
             y += CREDIT_HEIGHT;
 382  
         }
 383  
 
 384  0
         gImage.dispose();
 385  0
     }
 386  
 
 387  
     /**
 388  
      * Return the start position.
 389  
      *
 390  
      * @return The start position.
 391  
      */
 392  
     public int getStart() {
 393  0
         return start;
 394  
     }
 395  
 
 396  
     /**
 397  
      * Set the start position.
 398  
      *
 399  
      * @param start The position. +
 400  
      */
 401  
     public void setStart(int start) {
 402  0
         this.start = start;
 403  
 
 404  0
         repaint();
 405  0
     }
 406  
 
 407  
     /**
 408  
      * Return the credits height.
 409  
      *
 410  
      * @return The credits height.
 411  
      */
 412  
     int getCreditsHeight() {
 413  0
         return getCredits().size() * CREDIT_HEIGHT;
 414  
     }
 415  
 
 416  
     @Override
 417  
     public void appear() {
 418  0
         Animator fadeIn = AnimationUtils.createFadeInAnimator(this);
 419  0
         TimingTrigger.addTrigger(fadeIn, getAnimator(), TimingTriggerEvent.STOP);
 420  0
         fadeIn.start();
 421  0
     }
 422  
 
 423  
     @Override
 424  
     public void disappear() {
 425  0
         getAnimator().pause();
 426  
 
 427  0
         Animator fadeOut = AnimationUtils.createFadeOutAnimator(this);
 428  0
         fadeOut.addTarget(new TimingTargetAdapter() {
 429  
             @Override
 430  
             public void end() {
 431  0
                 setVisible(false);
 432  0
             }
 433  
         });
 434  0
         fadeOut.start();
 435  0
     }
 436  
 
 437  
     @Override
 438  
     public void refreshText() {
 439  0
         super.init();
 440  0
         init();
 441  0
         repaint();
 442  0
     }
 443  
 
 444  
     @Override
 445  
     public Component getImpl() {
 446  0
         return this;
 447  
     }
 448  
 
 449  
     /**
 450  
      * The mouse controller of the view.
 451  
      */
 452  0
     private final class MouseController extends MouseAdapter {
 453  
         @Override
 454  
         public void mouseClicked(MouseEvent event) {
 455  0
             if (shapes.get("quit").contains(event.getPoint())) {
 456  0
                 disappear();
 457  0
             } else if (shapes.get("url").contains(event.getPoint())) {
 458  0
                 for (Map.Entry<Rectangle, String> entry : urlRectangles.entrySet()) {
 459  0
                     if (entry.getKey().contains(event.getPoint())) {
 460  0
                         DesktopUtils.browse(entry.getValue());
 461  
 
 462  0
                         return;
 463  
                     }
 464  
                 }
 465  0
             } else if (shapes.get("licence").contains(event.getPoint())) {
 466  0
                 disappear();
 467  0
                 Managers.getManager(IViewManager.class).getViews().getLicenceView().display();
 468  
             }
 469  0
         }
 470  
     }
 471  
 
 472  
     /**
 473  
      * The mouse motion controller for the view.
 474  
      */
 475  0
     private final class MouseMotionController extends MouseMotionAdapter {
 476  
         @Override
 477  
         public void mouseMoved(MouseEvent event) {
 478  0
             if (shapes.get("quit").contains(event.getPoint()) ||
 479  
                     shapes.get("url").contains(event.getPoint()) ||
 480  
                     shapes.get("licence").contains(event.getPoint())) {
 481  0
                 setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
 482  
             } else {
 483  0
                 setCursor(Cursor.getDefaultCursor());
 484  
             }
 485  0
         }
 486  
     }
 487  
 }