/* * WPCleaner: A tool to help on Wikipedia maintenance tasks. * Copyright (C) 2013 Nicolas Vervelle * * See README.txt file for licensing information. */ package org.wikipediacleaner.gui.swing.basic; import java.awt.Color; import java.awt.Component; import java.awt.Cursor; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.KeyboardFocusManager; import java.awt.RenderingHints; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.font.FontRenderContext; import java.awt.font.TextLayout; import java.awt.geom.Rectangle2D; import javax.swing.JComponent; import javax.swing.JRootPane; import javax.swing.SwingUtilities; /** * Progress panel. */ public class ProgressPanel extends JComponent implements MouseListener, KeyListener { private static final long serialVersionUID = -4675782468350775884L; private String application = ""; private String text = ""; private int alphaLevel = 255; private float shield = 0.70F; private RenderingHints hints = null; private Color background = Color.GRAY; private Color textBackground = Color.CYAN; private Color textBorder = Color.BLUE; private boolean started = false; private Component recentFocusOwner = null; /** * Constructor. */ public ProgressPanel() { this(null); } /** * Constructor. * * @param application Application name. */ public ProgressPanel(String application) { this(application, null); } /** * Constructor. * * @param application Application name. * @param text Displayed text. */ public ProgressPanel(String application, String text) { this(application, text, 0.70F); } /** * Constructor. * * @param application Application name. * @param text Displayed text. * @param shield Transparency. */ public ProgressPanel(String application, String text, float shield) { this.application = application; this.text = text; this.shield = shield; this.hints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); this.hints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); this.hints.put(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); this.background = new Color(255, 255, 255, (int) (alphaLevel * this.shield)); this.textBackground = new Color(0, 255, 255, (int) (alphaLevel * this.shield)); setOpaque(false); setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); } /** * @param text Displayed text. */ public void setText(String text) { this.text = text; repaint(); } /** * @return Displayed text. */ public String getText() { return text; } /** * Start progress panel. */ public void start() { startPanel(); } /** * Stop progress panel. */ public void stop() { stopPanel(); } /** * Interrupt progress panel. */ public void interrupt() { stopPanel(); } /** * Start progress panel. */ private void startPanel() { started = true; addMouseListener(this); addKeyListener(this); setVisible(true); repaint(); } /** * Stop progress panel. */ private void stopPanel() { started = false; removeMouseListener(this); removeKeyListener(this); setText(""); setVisible(false); } /* (non-Javadoc) * @see javax.swing.JComponent#setVisible(boolean) */ @Override public void setVisible(boolean visible) { boolean oldVisible = isVisible(); super.setVisible(visible); JRootPane rootPane = SwingUtilities.getRootPane(this); if ((rootPane != null) && (isVisible() != oldVisible)) { if (isVisible()) { Component focusOwner = KeyboardFocusManager. getCurrentKeyboardFocusManager().getPermanentFocusOwner(); if ((focusOwner != null) && SwingUtilities.isDescendingFrom(focusOwner, rootPane)) { recentFocusOwner = focusOwner; } rootPane.getLayeredPane().setVisible(false); requestFocusInWindow(); } else { rootPane.getLayeredPane().setVisible(true); if (recentFocusOwner != null) { recentFocusOwner.requestFocusInWindow(); } recentFocusOwner = null; } } } /* (non-Javadoc) * @see javax.swing.JComponent#paintComponent(java.awt.Graphics) */ @Override public void paintComponent(Graphics g) { if (!started) { return; } int width = getWidth(); int height = getHeight(); // Draw layered pane below glass pane JRootPane rootPane = SwingUtilities.getRootPane(this); if (rootPane != null) { // It is important to call print() instead of paint() here // because print() doesn't affect the frame's double buffer rootPane.getLayeredPane().print(g); } // Draw background Graphics2D g2 = (Graphics2D) g; g2.setRenderingHints(hints); g2.setColor(background); g2.fillRect(0, 0, width, height); // Draw text if (((application != null) && (application.length() > 0)) || ((text != null) && (text.length() > 0))) { // Positions float xMin = Float.MAX_VALUE; float xMax = Float.MIN_VALUE; float yMin = Float.MAX_VALUE; float yMax = Float.MIN_VALUE; float xSpace = 10F; float ySpace = 5F; // Compute bonds FontRenderContext context = g2.getFontRenderContext(); TextLayout layoutApplication = null; float xApplication = Float.MAX_VALUE; float yApplication = Float.MIN_VALUE; if ((application != null) && (application.length() > 0)) { layoutApplication = new TextLayout(application, getFont(), context); Rectangle2D boundsApplication = layoutApplication.getBounds(); xApplication = (float) (width - boundsApplication.getWidth()) / 2; yApplication = Math.max((float) ((float) height / 2 - 2 * boundsApplication.getHeight()), 0); xMin = Math.min(xMin, (float) (xApplication + boundsApplication.getMinX() - xSpace)); xMax = Math.max(xMax, (float) (xApplication + boundsApplication.getMaxX() + xSpace)); yMin = Math.min(yMin, (float) (yApplication + boundsApplication.getMinY() - ySpace)); yMax = Math.max(yMax, (float) (yApplication + boundsApplication.getMaxY() + ySpace)); } TextLayout layoutText = null; float xText = Float.MAX_VALUE; float yText = Float.MIN_VALUE; if ((text != null) && (text.length() > 0)) { layoutText = new TextLayout(text, getFont(), context); Rectangle2D boundsText = layoutText.getBounds(); xText = (float) (width - boundsText.getWidth()) / 2; yText = Math.max((float) ((float) height / 2 + boundsText.getHeight()), 0); xMin = Math.min(xMin, (float) (xText + boundsText.getMinX() - xSpace)); xMax = Math.max(xMax, (float) (xText + boundsText.getMaxX() + xSpace)); yMin = Math.min(yMin, (float) (yText + boundsText.getMinY() - ySpace)); yMax = Math.max(yMax, (float) (yText + boundsText.getMaxY() + ySpace)); } // Draw border if ((xMin < xMax) && (yMin < yMax)) { g2.setColor(textBackground); g2.fillRoundRect((int) xMin, (int) yMin, (int) (xMax - xMin), (int) (yMax - yMin), 10, 10); g2.setColor(textBorder); g2.drawRoundRect((int) xMin, (int) yMin, (int) (xMax - xMin), (int) (yMax - yMin), 10, 10); } // Draw text g2.setColor(getForeground()); if (layoutApplication != null) { layoutApplication.draw(g2, xApplication, yApplication); } if (layoutText != null) { layoutText.draw(g2, xText, yText); } } } /* ====================================================================== */ /* MouseListener implementation */ /* ====================================================================== */ /* (non-Javadoc) * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent) */ @Override public void mouseClicked(@SuppressWarnings("unused") MouseEvent e) { // } /* (non-Javadoc) * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent) */ @Override public void mouseEntered(@SuppressWarnings("unused") MouseEvent e) { // } /* (non-Javadoc) * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent) */ @Override public void mouseExited(@SuppressWarnings("unused") MouseEvent e) { // } /* (non-Javadoc) * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent) */ @Override public void mousePressed(@SuppressWarnings("unused") MouseEvent e) { // } /* (non-Javadoc) * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent) */ @Override public void mouseReleased(@SuppressWarnings("unused") MouseEvent e) { // } /* ====================================================================== */ /* KeyListener implementation */ /* ====================================================================== */ /* (non-Javadoc) * @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent) */ @Override public void keyPressed(KeyEvent e) { e.consume(); } /* (non-Javadoc) * @see java.awt.event.KeyListener#keyReleased(java.awt.event.KeyEvent) */ @Override public void keyReleased(KeyEvent e) { e.consume(); } /* (non-Javadoc) * @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent) */ @Override public void keyTyped(KeyEvent e) { e.consume(); } }