Package util.ui

Source Code of util.ui.UiUtilities$ComboSeparatorsRenderer

/*
* TV-Browser
* Copyright (C) 04-2003 Martin Oberhauser (martin_oat@yahoo.de)
*
* 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*
* CVS information:
*  $RCSfile$
*   $Source$
*     $Date: 2011-03-26 16:33:30 +0100 (Sat, 26 Mar 2011) $
*   $Author: bananeweizen $
* $Revision: 6967 $
*/

package util.ui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.Transparency;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicReference;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.ListCellRenderer;
import javax.swing.border.Border;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;

import org.apache.commons.lang.StringUtils;

import tvbrowser.ui.mainframe.MainFrame;
import util.browserlauncher.Launch;
import util.misc.OperatingSystem;

/**
* Provides utilities for UI stuff.
*
* @author Til Schneider, www.murfman.de
*/
public class UiUtilities {

  /** The helper label. */
  private static final JLabel HELPER_LABEL = new JLabel();

  /** The border to use for dialogs. */
  public static final Border DIALOG_BORDER = BorderFactory.createEmptyBorder(
      10, 10, 0, 10);

  public static final Insets ZERO_INSETS = new Insets(0, 0, 0, 0);

  /**
   * Centers a window to its parent frame and shows it.
   * <p>
   * If the window has no parent frame it will be centered to the screen.
   *
   * @param win
   *          The window to center and show.
   */
  public static void centerAndShow(Window win) {
    Dimension wD = win.getSize();
    Dimension frameD;
    Point framePos;
    Frame frame = JOptionPane.getFrameForComponent(win);

    // Should this window be centered to its parent frame?
    boolean centerToParentFrame = (frame != null) && (frame != win)
        && frame.isShowing();

    // Center to parent frame or to screen
    if (centerToParentFrame) {
      frameD = frame.getSize();
      framePos = frame.getLocation();
    } else {
      GraphicsEnvironment ge = GraphicsEnvironment
          .getLocalGraphicsEnvironment();
      // dual head, use first screen
      if (ge.getScreenDevices().length > 1) {
        try {
          GraphicsDevice gd = ge.getDefaultScreenDevice();
          GraphicsConfiguration config = gd.getConfigurations()[0];
          frameD = config.getBounds().getSize();
          framePos = config.getBounds().getLocation();
        } catch (RuntimeException e) {
          frameD = Toolkit.getDefaultToolkit().getScreenSize();
          framePos = new Point(0, 0);
        }
      }
      // single screen only
      else {
        frameD = Toolkit.getDefaultToolkit().getScreenSize();
        framePos = new Point(0, 0);
      }
    }

    Point wPos = new Point(framePos.x + (frameD.width - wD.width) / 2,
        framePos.y + (frameD.height - wD.height) / 2);
    wPos.x = Math.max(0, wPos.x); // Make x > 0
    wPos.y = Math.max(0, wPos.y); // Make y > 0
    win.setLocation(wPos);
    win.setVisible(true);
  }

  /**
   * @param parent
   *          A component in the component tree where the dialog should be
   *          created for.
   * @param modal
   *          Should the new dialog be modal?
   * @return A new JDialog.
   */
  public static JDialog createDialog(Component parent, final boolean modal) {
    final AtomicReference<JDialog> result = new AtomicReference<JDialog>();
    final Window parentWin = getBestDialogParent(parent);
    try {
      UIThreadRunner.invokeAndWait(new Runnable() {

        @Override
        public void run() {
          JDialog dialog = new JDialog(parentWin);
          dialog.setModal(modal);
          result.set(dialog);
        }
      });
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (InvocationTargetException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    return result.get();
  }

  /**
   * Gets the best dialog parent for a new JDialog. The best parent is the last
   * visible modal dialog in the component tree.
   * <p>
   * If there is no visible modal dialog the root frame will be returned.
   *
   * @param parent
   *          One component of the component tree.
   * @return the best dialog parent for a new JDialog.
   */
  public static Window getBestDialogParent(Component parent) {
    Frame root = JOptionPane.getFrameForComponent(parent);
    return getLastModalChildOf(root);
  }

  /**
   * Gets the last visible modal child dialog of the specified window.
   * <p>
   * If there is no visible modal child the window itself will be returned.
   *
   * @param parent
   *          The window to get the child from.
   * @return the last visible modal child dialog of the specified window.
   */
  public static Window getLastModalChildOf(Window parent) {
    Window[] children = parent.getOwnedWindows();
    for (Window child : children) {
      if (child instanceof Dialog) {
        Dialog dlg = (Dialog) child;
        if (dlg.isVisible() && dlg.isModal()) {
          return getLastModalChildOf(dlg);
        }
      }
    }

    // this is the last window
    return parent;
  }

  /**
   * Gets if a dialog child of the given window is modal.
   *
   * @param parent
   *          The window to check the children of.
   * @return <code>True</code> if a child is modal, <code>false</code>
   *         otherwise.
   *
   * @since 2.7
   */
  public static boolean containsModalDialogChild(Window parent) {
    Window[] children = parent.getOwnedWindows();

    for (Window child : children) {
      if (containsModalDialogChild(child)) {
        return true;
      }
    }

    return (parent instanceof JDialog && parent.isVisible() && ((JDialog) parent)
        .isModal());
  }

  /**
   * Gibt einen Button mit Icon und Schrift zur�ck, der so initialisiert ist,
   * da� man ihn gut f�r Symbolleisten nutzen kann (Rahmen nur bei Rollover
   * sichtbar usw.).
   * <P>
   * Wenn text und iconDateiname angegeben sind, dann wird text als TooltipText
   * gesetzt.
   *
   * @param text
   *          Der Text des Buttons (Kann null sein, wenn der Button keinen Text
   *          enthalten soll)
   * @param icon
   *          Das Icon des Buttons (Kann ebenfalls null sein, wenn der Button
   *          kein Icon enthalten soll).
   * @return button
   */
  public static JButton createToolBarButton(String text, Icon icon) {
    final JButton btn;
    if (icon == null) {
      btn = new JButton(text);
    } else {
      btn = new JButton(icon);
      btn.setToolTipText(text);
      btn.setBorderPainted(false);
      btn.setMargin(ZERO_INSETS);

      btn.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseEntered(MouseEvent e) {
          if (btn.isEnabled()) {
            btn.setBorderPainted(true);
          }
        }

        @Override
        public void mouseExited(MouseEvent e) {
          btn.setBorderPainted(false);
        }
      });
    }
    btn.setFocusPainted(false);

    return btn;
  }

  /**
   * Gets the width of the specified String.
   *
   * @param str
   *          The String to get the width for.
   * @param font
   *          The font being the base of the measure.
   * @return the width of the specified String.
   */
  public static int getStringWidth(Font font, String str) {
    if (str == null) {
      return 0;
    }

    FontMetrics metrics = HELPER_LABEL.getFontMetrics(font);
    return metrics.stringWidth(str);
  }

  /**
   * Gets the width of the specified char array.
   *
   * @param chars
   *          The char array to get the width for.
   * @param offset
   *          The offset where to start.
   * @param length
   *          The length of the measure.
   * @param font
   *          The font being the base of the measure.
   * @return the width of the specified char array.
   */
  public static int getCharsWidth(Font font, char[] chars, int offset,
      int length) {
    if (chars == null) {
      return 0;
    }

    FontMetrics metrics = HELPER_LABEL.getFontMetrics(font);
    return metrics.charsWidth(chars, offset, length);
  }

  /**
   * Creates a text area that holds a help text.
   *
   * @param msg
   *          The help text.
   * @return A text area containing the help text.
   */
  public static JTextArea createHelpTextArea(String msg) {
    JTextArea descTA = new JTextArea(msg);
    descTA.setBorder(BorderFactory.createEmptyBorder());
    descTA.setFont(new JLabel().getFont());
    descTA.setEditable(false);
    descTA.setOpaque(false);
    descTA.setWrapStyleWord(true);
    descTA.setLineWrap(true);
    descTA.setFocusable(false);

    Color bg = new JPanel().getBackground();

    descTA.setBackground(new Color(bg.getRed(),bg.getGreen(),bg.getBlue()));

    return descTA;
  }

  /**
   * Creates a Html EditorPane that holds a HTML-Help Text
   *
   * Links will be displayed and are clickable
   *
   * @param html
   *          HTML-Text to display
   * @return EditorPane that holds a Help Text
   * @since 2.2
   */
  public static JEditorPane createHtmlHelpTextArea(String html) {
    return createHtmlHelpTextArea(html, new JPanel().getBackground());
  }

  /**
   * Creates a Html EditorPane that holds a HTML-Help Text
   *
   * Links will be displayed and are clickable
   *
   * @param html
   *          HTML-Text to display
   * @param background The color for the background.
   * @return EditorPane that holds a Help Text
   * @since 2.7.2
   */
  public static JEditorPane createHtmlHelpTextArea(String html, Color background) {
    return createHtmlHelpTextArea(html, new HyperlinkListener() {
      private String mTooltip;

      public void hyperlinkUpdate(HyperlinkEvent evt) {
        JEditorPane pane = (JEditorPane) evt.getSource();
        if (evt.getEventType() == HyperlinkEvent.EventType.ENTERED) {
          mTooltip = pane.getToolTipText();
          pane.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
          if (evt.getURL() != null) {
            pane.setToolTipText(evt.getURL().toExternalForm());
          }
        }
        if (evt.getEventType() == HyperlinkEvent.EventType.EXITED) {
          pane.setCursor(Cursor.getDefaultCursor());
          pane.setToolTipText(mTooltip);
        }
        if (evt.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
          URL url = evt.getURL();
          if (url != null) {
            Launch.openURL(url.toString());
          }
        }
      }
    },background);
  }

  /**
   * Creates a Html EditorPane that holds a HTML-Help Text.
   *
   * Add a Listener if you want to have clickable Links
   *
   * @param html
   *          HTML-Text to display
   * @param listener
   *          Link-Listener for this HelpText
   * @return EditorPane that holds a Help Text
   * @since 2.2
   */
  public static JEditorPane createHtmlHelpTextArea(String html,
      HyperlinkListener listener) {
    return createHtmlHelpTextArea(html,listener,new JPanel().getBackground());
  }

  /**
   * Creates a Html EditorPane that holds a HTML-Help Text.
   *
   * Add a Listener if you want to have clickable Links
   *
   * @param html
   *          HTML-Text to display
   * @param listener
   *          Link-Listener for this HelpText
   * @param background The color for the background.
   * @return EditorPane that holds a Help Text
   * @since 2.7.2
   */
  public static JEditorPane createHtmlHelpTextArea(String html,
      HyperlinkListener listener, Color background) {
    // Quick "hack". Remove HTML-Code and replace it with Code that includes the
    // correct Font
    if (html.indexOf("<html>") >= 0) {
      html = StringUtils.substringBetween(html, "<html>", "</html>");
    }
    JLabel label = new JLabel();
    Font font = label.getFont();
    html = "<html><div style=\"color:" + UiUtilities.getHTMLColorCode(label.getForeground())+";font-family:" + font.getName()
        + "; font-size:" + font.getSize() +";background-color:rgb(" + background.getRed() + "," + background.getGreen() + "," + background.getBlue() + ");\">" + html + "</div></html>";

    final JEditorPane pane = new JEditorPane("text/html", html);
    pane.setBorder(BorderFactory.createEmptyBorder());
    pane.setEditable(false);
    pane.setFont(font);
    pane.setOpaque(false);
    pane.setFocusable(false);

    if (listener != null) {
      pane.addHyperlinkListener(listener);
    }
    return pane;
  }

  /**
   * returns a color code as used in HTML, e.g. #FF0000 for pure red
   * @param color
   * @return HTML color code
   */
  public static String getHTMLColorCode(Color color) {
    return '#' + StringUtils.leftPad(Integer.toString(color.getRed(), 16), 2, '0')
        + StringUtils.leftPad(Integer.toString(color.getGreen(), 16), 2, '0')
        + StringUtils.leftPad(Integer.toString(color.getBlue(), 16), 2, '0');
  }

  /**
   * Moves Selected Items from one List to another
   *
   * @param fromList
   *          Move from this List
   * @param toList
   *          Move into this List
   * @return Moved Elements
   */
  public static Object[] moveSelectedItems(JList fromList, JList toList) {
    DefaultListModel fromModel = (DefaultListModel) fromList.getModel();
    DefaultListModel toModel = (DefaultListModel) toList.getModel();

    // get the selection
    int[] selection = fromList.getSelectedIndices();

    if (selection.length == 0) {
      return new Object[] {};
    }

    Object[] objects = new Object[selection.length];
    for (int i = 0; i < selection.length; i++) {
      objects[i] = fromModel.getElementAt(selection[i]);
    }

    // get the target insertion position
    int targetPos = toList.getMaxSelectionIndex();
    if (targetPos == -1) {
      targetPos = toModel.getSize();
    } else {
      targetPos++;
    }

    // suppress updates on both lists
    if (selection.length >= 5) {
      fromList.setModel(new DefaultListModel());
      toList.setModel(new DefaultListModel());
    }

    // move the elements
    for (int i = selection.length - 1; i >= 0; i--) {
      Object value = fromModel.remove(selection[i]);
      toModel.add(targetPos, value);
    }

    if (selection.length >= 5) {
      fromList.setModel(fromModel);
      toList.setModel(toModel);
    }

    // change selection of the fromList
    if (fromModel.getSize() > 0) {
      int newSelection = selection[0];
      if (newSelection >= fromModel.getSize()) {
        newSelection = fromModel.getSize() - 1;
      }
      fromList.setSelectedIndex(newSelection);
    }

    if (selection.length >= 5) {
      fromList.repaint();
      fromList.revalidate();
      toList.repaint();
      toList.revalidate();
    }

    // change selection of the toList
    toList.setSelectionInterval(targetPos, targetPos + selection.length - 1);

    // ensure the selection is visible
    toList.ensureIndexIsVisible(toList.getMaxSelectionIndex());
    toList.ensureIndexIsVisible(toList.getMinSelectionIndex());

    return objects;
  }

  /**
   * Moves Selected Items from one List to another
   *
   * @param fromList
   *          Move from this List
   * @param toList
   *          Move into this List
   * @param row
   *          The target row where to insert
   * @return Moved Elements
   */
  public static Object[] moveSelectedItems(JList fromList, JList toList, int row) {
    DefaultListModel fromModel = (DefaultListModel) fromList.getModel();
    DefaultListModel toModel = (DefaultListModel) toList.getModel();

    // get the selection
    int[] selection = fromList.getSelectedIndices();

    if (selection.length == 0) {
      return new Object[] {};
    }

    Object[] objects = new Object[selection.length];
    for (int i = 0; i < selection.length; i++) {
      objects[i] = fromModel.getElementAt(selection[i]);
    }

    // move the elements
    for (int i = selection.length - 1; i >= 0; i--) {
      Object value = fromModel.remove(selection[i]);
      toModel.insertElementAt(value, row);
    }

    // change selection of the fromList
    if (fromModel.getSize() > 0) {
      int newSelection = selection[0];
      if (newSelection >= fromModel.getSize()) {
        newSelection = fromModel.getSize() - 1;
      }
      // fromList.setSelectedIndex(-1);
    }

    // change selection of the toList
    toList.setSelectionInterval(row, row + selection.length - 1);

    // ensure the selection is visible
    toList.ensureIndexIsVisible(toList.getMaxSelectionIndex());
    toList.ensureIndexIsVisible(toList.getMinSelectionIndex());

    return objects;
  }

  /**
   * Move selected Items in the JList
   *
   * @param list
   *          Move Items in this List
   * @param row
   *          The target row where to insert
   * @param sort
   *          Dummy parameter, does nothing
   */
  public static void moveSelectedItems(JList list, int row, boolean sort) {
    DefaultListModel model = (DefaultListModel) list.getModel();

    // get the selection
    int[] selection = list.getSelectedIndices();
    if (selection.length == 0) {
      return;
    }

    boolean lower = false;
    // Remove the selected items
    Object[] items = new Object[selection.length];
    for (int i = selection.length - 1; i >= 0; i--) {
      if (selection[i] < row && !lower) {
        row = row - i - 1;
        lower = true;
      }
      items[i] = model.remove(selection[i]);
    }

    for (int i = items.length - 1; i >= 0; i--) {
      model.insertElementAt(items[i], row);
    }

    // change selection of the toList
    list.setSelectionInterval(row, row + selection.length - 1);

    // ensure the selection is visible
    list.ensureIndexIsVisible(list.getMaxSelectionIndex());
    list.ensureIndexIsVisible(list.getMinSelectionIndex());
  }

  /**
   * Move selected Items in the JList
   *
   * @param list
   *          Move Items in this List
   * @param nrRows
   *          Move Items nrRows up/down
   */
  public static void moveSelectedItems(JList list, int nrRows) {
    DefaultListModel model = (DefaultListModel) list.getModel();

    // get the selection
    int[] selection = list.getSelectedIndices();
    if (selection.length == 0) {
      return;
    }

    // Remove the selected items
    Object[] items = new Object[selection.length];
    for (int i = selection.length - 1; i >= 0; i--) {
      items[i] = model.remove(selection[i]);
    }

    // insert the elements at the target position
    int targetPos = selection[0] + nrRows;
    targetPos = Math.max(targetPos, 0);
    targetPos = Math.min(targetPos, model.getSize());
    for (int i = 0; i < items.length; i++) {
      model.add(targetPos + i, items[i]);
    }

    // change selection of the toList
    list.setSelectionInterval(targetPos, targetPos + selection.length - 1);

    // ensure the selection is visible
    list.ensureIndexIsVisible(list.getMaxSelectionIndex());
    list.ensureIndexIsVisible(list.getMinSelectionIndex());
  }

  /**
   * Scale Icons to a specific width. The aspect ratio is kept.
   *
   * @param icon
   *          The icon to scale.
   * @param newWidth
   *          The new width of the icon.
   * @return The scaled Icon.
   */
  public static Icon scaleIcon(Icon icon, int newWidth) {
    if (icon == null) {
      return null;
    }
    return scaleIcon(icon, newWidth, (int) ((newWidth / (float) icon
        .getIconWidth()) * icon.getIconHeight()));
  }

  /**
   * Scales Icons to a specific size
   *
   * @param icon
   *          Icon that should be scaled
   * @param width
   *          scaled width
   * @param height
   *          scaled height
   * @return Scaled Icon
   */
  public static Icon scaleIcon(Icon icon, int width, int height) {
    if (icon == null) {
      return null;
    }
    int currentWidth = icon.getIconWidth();
    int currentHeight = icon.getIconHeight();
    if ((currentWidth == width) && (currentHeight == height)) {
      return icon;
    }
    try {
      // Create Image with Icon
      BufferedImage iconImage = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(),
          BufferedImage.TYPE_INT_ARGB);
      Graphics2D g2 = iconImage.createGraphics();
      g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
          RenderingHints.VALUE_INTERPOLATION_BICUBIC);
      g2.setRenderingHint(RenderingHints.KEY_RENDERING,
          RenderingHints.VALUE_RENDER_QUALITY);
      AffineTransform z = g2.getTransform();
      g2.setTransform(z);
      icon.paintIcon(null, g2, 0, 0);
      g2.dispose();
      BufferedImage scaled = scaleDown(iconImage, width, height);
      // Return new Icon
      return new ImageIcon(scaled);
    } catch (Exception ex) {
      ex.printStackTrace();
    }

    return icon;
  }

  /**
   * Scales an image to a specific size and returns an BufferedImage
   *
   * @param img
   *          Scale this IMage
   * @param width
   *          new width
   * @param height
   *          new height
   * @return Scaled BufferedImage
   *
   * @since 2.5
   */
  public static BufferedImage scaleIconToBufferedImage(BufferedImage img,
      int width, int height) {
    return scaleIconToBufferedImage(img, width, height, img.getType());
  }

  /**
   * Scales an image to a specific size and returns an BufferedImage
   *
   * @param img
   *          Scale this image
   * @param width
   *          new width
   * @param height
   *          new height
   * @param type The type of the image.
   * @return Scaled BufferedImage
   *
   * @since 2.7
   */
  public static BufferedImage scaleIconToBufferedImage(BufferedImage img,
      int width, int height, int type) {
    return scaleIconToBufferedImage(img, width, height, type, null);
  }

  /**
   * Scales an image to a specific size and returns an BufferedImage
   *
   * @param img
   *          Scale this image
   * @param width
   *          new width
   * @param height
   *          new height
   * @param type The type of the image.
   * @return Scaled BufferedImage
   *
   * @since 3.0
   */
  public static BufferedImage scaleIconToBufferedImage(BufferedImage img,
      int width, int height, int type, Color backgroundColor) {
    // Scale Image
    Image image = img.getScaledInstance(width, height, Image.SCALE_SMOOTH);

    BufferedImage im = new BufferedImage(width, height, type);

    Graphics2D g2 = im.createGraphics();
    if (backgroundColor != null) {
      g2.setColor(backgroundColor);
      g2.fillRect(0, 0 , width, height);
    }

    g2.drawImage(image, null, null);
    g2.dispose();

    im.flush();
    return im;

  }

  /**
   * Convenience method that returns a scaled instance of the
   * provided {@code BufferedImage}.
   *
   * @param img the original image to be scaled
   * @param targetWidth the desired width of the scaled instance,
   *    in pixels
   * @param targetHeight the desired height of the scaled instance,
   *    in pixels
   * @return a scaled version of the original {@code BufferedImage}
   */
  public static BufferedImage scaleDown(final BufferedImage img, final int targetWidth, final int targetHeight) {
    if (targetWidth > img.getWidth() || targetHeight > img.getHeight()) {
      return scaleIconToBufferedImage(img, targetWidth, targetHeight);
    }

    int type = (img.getTransparency() == Transparency.OPAQUE) ? BufferedImage.TYPE_INT_RGB
        : BufferedImage.TYPE_INT_ARGB;
    BufferedImage result = img;
    int w = img.getWidth();
    int h = img.getHeight();

    do {
      w /= 2;
      if (w < targetWidth) {
        w = targetWidth;
      }
      h /= 2;
      if (h < targetHeight) {
        h = targetHeight;
      }

      BufferedImage tmp = new BufferedImage(w, h, type);
      Graphics2D g2 = tmp.createGraphics();
      g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
      g2.drawImage(result, 0, 0, w, h, null);
      g2.dispose();

      result = tmp;
    } while (w != targetWidth || h != targetHeight);

    return result;
  }

  /**
   * Creates a scaled Version of the Icon.
   *
   * The scaled Version will have a Background and a Border.
   *
   * @param ic
   * @return ImageIcon
   * @since 2.1
   */
  public static ImageIcon createChannelIcon(Icon ic) {
    BufferedImage img = new BufferedImage(getChannelIconWidth(), getChannelIconHeight(), BufferedImage.TYPE_INT_RGB);

    if (ic == null) {
      ic = new ImageIcon("./imgs/tvbrowser16.png");
    }

    int height = 20;
    int width = 40;

    if ((ic.getIconWidth() != 0) && (ic.getIconHeight() != 0)) {
      double iWidth = ic.getIconWidth();
      double iHeight = ic.getIconHeight();
      if (iWidth / iHeight < 2.0) {
        width = (int) (iWidth * (20.0 / iHeight));
      } else {
        height = (int) (iHeight * (40.0 / iWidth));
      }
    }
    ic = scaleIcon(ic, width, height);

    Graphics2D g = img.createGraphics();

    g.setColor(Color.WHITE);
    g.fillRect(1, 1, 40, 20);

    int x = 1 + 20 - ic.getIconWidth() / 2;
    int y = 1 + 10 - ic.getIconHeight() / 2;

    ic.paintIcon(null, g, x, y);

    g.setColor(Color.BLACK);
    g.drawRect(0, 0, 42, 22);

    return new ImageIcon(img);
  }

  public static int getChannelIconHeight() {
    return 22;
  }

  public static int getChannelIconWidth() {
    return 42;
  }

  /**
   * Registers the escape key as close key for a component.
   *
   * @param component
   *          The component to close on pressing escape key.
   */
  public static void registerForClosing(final WindowClosingIf component) {
    Action a = new AbstractAction() {
      private static final long serialVersionUID = 1L;

      public void actionPerformed(ActionEvent e) {
        component.close();
      }
    };

    if (OperatingSystem.isMacOs()) {
      // Add MacOS Apple+W for Closing of Dialogs
      KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_W,
          InputEvent.META_DOWN_MASK);
      component.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
          .put(stroke, "CLOSE_ON_APPLE_W");
      component.getRootPane().getActionMap().put("CLOSE_ON_APPLE_W", a);

      stroke = KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.META_DOWN_MASK);
      component.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
          .put(stroke, "CLOSE_COMPLETE_ON_APPLE");
      component.getRootPane().getActionMap().put("CLOSE_COMPLETE_ON_APPLE",
          new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
              MainFrame.getInstance().quit();
            }
          });
    }

    KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
    component.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
        stroke, "CLOSE_ON_ESCAPE");
    component.getRootPane().getActionMap().put("CLOSE_ON_ESCAPE", a);
  }

  /**
   * set the size of a dialog, but never sizes it smaller than the preferred
   * size
   *
   * @param dialog
   *          dialog to be sized
   * @param width
   *          wanted width
   * @param height
   *          wanted height
   */
  public static void setSize(JDialog dialog, int width, int height) {
    dialog.pack();
    Dimension size = dialog.getMinimumSize();
    if (width > size.width) {
      size.width = width;
    }
    if (height > size.height) {
      size.height = height;
    }
    dialog.setSize(size);
  }

  public static void addSeparatorsAfterIndexes(final JComboBox combo,
      int[] indexes) {
    combo.setRenderer(new ComboSeparatorsRenderer(combo.getRenderer(), indexes));
  }

  public static void addSeparatorsAfterIndexes(final JComboBox combo,
      Integer[] indexes) {
    int[] primitives = new int[indexes.length];
    for (int i = 0; i < primitives.length; i++) {
      primitives[i] = indexes[i];
    }
    combo.setRenderer(new ComboSeparatorsRenderer(combo.getRenderer(), primitives));
  }

  private static class ComboSeparatorsRenderer implements ListCellRenderer {
    private ListCellRenderer mOldRenderer;
    private JPanel mSeparatorPanel = new JPanel(new BorderLayout());
    private JSeparator mSeparator = new JSeparator();
    private ArrayList<Integer> mIndexes;

    public ComboSeparatorsRenderer(ListCellRenderer delegate,
        final int[] indexes) {
      mOldRenderer = delegate;
      mIndexes = new ArrayList<Integer>(indexes.length);
      for (int index : indexes) {
        mIndexes.add(index);
      }
    }

    public Component getListCellRendererComponent(JList list, Object value,
        int index, boolean isSelected, boolean cellHasFocus) {
      Component comp = mOldRenderer.getListCellRendererComponent(list, value,
          index, isSelected, cellHasFocus);
      if (index != -1 && mIndexes.contains(index + 1)) { // index==1 if renderer is
                                                      // used to paint current
                                                      // value in combo
        mSeparatorPanel.removeAll();
        mSeparatorPanel.add(comp, BorderLayout.CENTER);
        mSeparatorPanel.add(mSeparator, BorderLayout.SOUTH);
        return mSeparatorPanel;
      } else {
        return comp;
      }
    }
  }

}
TOP

Related Classes of util.ui.UiUtilities$ComboSeparatorsRenderer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.