Package com.screenrunner.ui

Source Code of com.screenrunner.ui.MediaPicker$FileListRefresh

/*
* (c) Copyright 2009 Tim Jenkins
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* ITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package com.screenrunner.ui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.font.FontRenderContext;
import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextAttribute;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.AttributedString;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Vector;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import com.screenrunner.ScreenRunner;
import com.screenrunner.data.I18n;
import com.screenrunner.data.ImageSlide;
import com.screenrunner.data.VectorListModel;

/**
* @author Tim Jenkins
*
* Media picker dialog
* Used for both inserting images and video into the current playlist
* and showing on-the-fly media (in "immediate" mode)
*
*/
public class MediaPicker extends CookSwingDialog {
 
  private static final int ICON_WIDTH = 80;
  private static final int ICON_HEIGHT = 60;
 
  private static final int PREVIEW_WIDTH = 200;
  private static final int PREVIEW_HEIGHT = 150;
 
  public JDialog rootDialog;
  public JTextField currentDirField;
  public JList itemsList;
  public JPanel previewPanel;
  public JLabel previewNameLabel;
  public JLabel previewSizeLabel;
  public JButton doneButton;
  public JButton cancelButton;
  public JButton chooseButton;
 
  private boolean isImmediate = false;
  private boolean allowImages = false;
  private boolean allowVideos = false;
  private String initialDir = null;
 
  private PreviewImageLoader curPreviewLoader = null;
 
  private VectorListModel<String> fileList = null;
  private Hashtable<String, BufferedImage> previews = null;
  private Hashtable<String, BufferedImage> thumbs = null;
  private Hashtable<String, Dimension> imgSizes = null;
  //private Hashtable<String, Boolean> previewUpdates = null;
 
  public MediaPicker(boolean immediate, boolean allowimages, boolean allowvideos, String initialDir) {
    isImmediate = immediate;
    allowImages = allowimages;
    allowVideos = allowvideos;
    fileList = new VectorListModel<String>();
    previews = new Hashtable<String, BufferedImage>();
    thumbs = new Hashtable<String, BufferedImage>();
    imgSizes = new Hashtable<String, Dimension>();
    //previewUpdates = new Hashtable<String, Boolean>();
    this.initialDir = initialDir;
  }
 
  @Override
  protected String getDialogXml() {
    return "com/screenrunner/ui/xml/MediaPicker.xml";
  }

  @Override
  protected void initDialog() {
    previewPanel.setLayout(new BorderLayout());
    doneButton.setVisible(isImmediate);
    rootDialog.setTitle(isImmediate ? I18n.get("ui/dialogs/mediapicker/title?show") : I18n.get("ui/dialogs/mediapicker/title?add"));
    cancelButton.setVisible(!isImmediate);
    chooseButton.setText(isImmediate ? I18n.get("ui/dialogs/generic/show") : I18n.get("ui/dialogs/generic/add"));
    itemsList.setSelectionMode(isImmediate ? ListSelectionModel.SINGLE_SELECTION : ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    itemsList.setModel(fileList);
    itemsList.setCellRenderer(new ListCellRenderer() {

      @Override
      public Component getListCellRendererComponent(JList list,
          Object value, int index, boolean isSelected,
          boolean cellHasFocus) {
        UIDefaults uid = UIManager.getLookAndFeel().getDefaults();
        Color itemBg = (isSelected ? uid.getColor("List.selectionBackground") : uid.getColor("List.background"));
        Color itemFg = (isSelected ? uid.getColor("List.selectionForeground") : uid.getColor("List.foreground"));
       
        JLabel lbl = new JLabel();
        JPanel lblPnl = new JPanel(new GridBagLayout()) {
          private static final long serialVersionUID = 1L;

          @Override
          protected void paintComponent(Graphics g) {
            boolean temp = this.isOpaque();
            this.setOpaque(false);
            if(temp) {
              Graphics2D g2d = (Graphics2D)g;
              g2d.setColor(this.getBackground());
              g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
              g2d.fillRoundRect(0, 0, this.getWidth(), this.getHeight(), 10, 10);
            }
            super.paintComponent(g);
            this.setOpaque(temp);
          }
        };
       
        wrapTextIntoLabel(lbl, value.toString(), list.getFixedCellWidth() - 6);
       
        JLabel imglbl = new JLabel();
        if(previews.containsKey(value.toString())) {
          BufferedImage img = previews.get(value.toString());
          if(isSelected) {
            img = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);
            Graphics g = img.getGraphics();
            g.drawImage(previews.get(value.toString()), 0, 0, img.getWidth(), img.getHeight(), null);
            g.setColor(new Color(itemBg.getRed(), itemBg.getGreen(), itemBg.getBlue(), 127));
            g.fillRect(0, 0, img.getWidth(), img.getHeight());
          }
          imglbl.setIcon(new ImageIcon(img));
        }
       
        Dimension sz = new Dimension(80, 60);
        imglbl.setIconTextGap(1);
        imglbl.setPreferredSize(sz);
        imglbl.setMaximumSize(sz);
        imglbl.setMinimumSize(sz);
        imglbl.setHorizontalAlignment(JLabel.CENTER);
        imglbl.setVerticalAlignment(JLabel.CENTER);
       
        lbl.setHorizontalAlignment(JLabel.CENTER);
        lbl.setHorizontalTextPosition(JLabel.CENTER);
        lbl.setVerticalAlignment(JLabel.TOP);
        lbl.setVerticalTextPosition(JLabel.TOP);
        lbl.setForeground(itemFg);
       
        JPanel pnl = new JPanel(new GridBagLayout());
        pnl.setOpaque(false);
        lblPnl.setBackground(itemBg);
        lblPnl.setOpaque(isSelected);
       
        lblPnl.add(lbl, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(1,3,3,3), 0, 0));
       
        pnl.add(imglbl, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(2,2,2,2), 0, 0));
        pnl.add(lblPnl, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.NORTH, GridBagConstraints.NONE, new Insets(0,0,0,0), 0, 0));
       
       
        return pnl;
      }
     
    });
   
    currentDirField.setText(initialDir);
    fillMediaList();
  }
 
  private class PreviewImageLoader implements Runnable {
   
    private boolean cancel = false;
   
    public PreviewImageLoader() {
     
    }
   
    public synchronized void cancelProcess() {
      cancel = true;
    }
   
    public synchronized boolean cancelRequested() {
      return cancel;
    }
   
    @Override
    public void run() {
      for(int i = 0; i < fileList.size() && !cancelRequested(); i++) {
        String file = fileList.get(i);
        if(file == null) continue;
        File f = new File(getFullPath(file));
        if(f.exists() && !f.isDirectory()) {
          try {
            BufferedImage img = ImageIO.read(f);
            while(!previewPanel.prepareImage(img, previewPanel)) {
              Thread.yield();
              if(cancelRequested()) return;
            }
            Dimension thumbsz = calculateNewSize(img.getWidth(), img.getHeight(), PREVIEW_WIDTH, PREVIEW_HEIGHT);
            Dimension pvwsz = calculateNewSize(img.getWidth(), img.getHeight(), ICON_WIDTH, ICON_HEIGHT);
            BufferedImage thumbimg = new BufferedImage(thumbsz.width, thumbsz.height, BufferedImage.TYPE_INT_ARGB);
            BufferedImage pvwimg = new BufferedImage(pvwsz.width, pvwsz.height, BufferedImage.TYPE_INT_ARGB);
            while(!thumbimg.getGraphics().drawImage(img, 0, 0, thumbsz.width, thumbsz.height, null)) {
              Thread.yield();
              if(cancelRequested()) return;
            }
            while(!pvwimg.getGraphics().drawImage(img, 0, 0, pvwsz.width, pvwsz.height, null)) {
              Thread.yield();
              if(cancelRequested()) return;
            }
            thumbs.put(file, thumbimg);
            previews.put(file, pvwimg);
            imgSizes.put(file, new Dimension(img.getWidth(), img.getHeight()));
           
            SwingUtilities.invokeLater(new FileListRefresh(i));
           
            if(itemsList.getSelectedIndex() != -1 && (itemsList.getSelectedValue().toString().contentEquals(fileList.get(i))))
              updatePreview();
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
        if(cancelRequested()) return;
      }
    }
   
  }
 
  private class FileListRefresh implements Runnable {
    private int index;
    public FileListRefresh(int index) {
      this.index = index;
    }
   
    @Override
    public void run() {
      int sel = itemsList.getSelectedIndex();
      fileList.add(index, fileList.remove(index));
      if(sel != -1)
        itemsList.setSelectedIndex(sel);
    }
   
  };
 
  private void wrapTextIntoLabel(JLabel lbl, String text, int width) {
    AttributedString astr = new AttributedString(text);
    astr.addAttribute(TextAttribute.FONT, lbl.getFont());
    FontRenderContext frc = lbl.getFontMetrics(lbl.getFont()).getFontRenderContext();
    LineBreakMeasurer lbm = new LineBreakMeasurer(astr.getIterator(), frc);
    Vector<String> lines = new Vector<String>();
    int prevOffs = 0;
    int offs = lbm.nextOffset(width, text.length(), false);
    do {
      lines.add(text.substring(prevOffs, offs));
      lbm.setPosition(offs);
      prevOffs = offs;
      offs = lbm.nextOffset(width, text.length(), false);
    } while(offs > prevOffs);
   
    StringBuilder output = new StringBuilder();
    output.append("<html><center>");
    for(int i = 0; i < lines.size(); i++) {
      if(i > 0) output.append("<br/>");
      output.append(lines.get(i));
    }
    output.append("</center></html>");
    lbl.setText(output.toString());
  }
 
  private Dimension calculateNewSize(int srcw, int srch, int boxw, int boxh) {
    if(srcw <= boxw && srch <= boxh) return new Dimension(srcw, srch);
   
    Dimension rv = new Dimension(boxw, boxh);
    float srca = (float)srcw / (float)srch;
    float boxa = (float)boxw / (float)boxh;
    if(srca > boxa) {
      rv.height = (int)(((float)boxw / (float)srcw) * srch);
    } else if(srca < boxa) {
      rv.width = (int)(((float)boxh / (float)srch) * srcw);
    }
    return rv;
  }
 
  private String getFullPath(String file) {
    String dir = currentDirField.getText();
    dir += dir.endsWith(File.separator) ? "" : File.separator;
    dir += file;
    return dir;
  }
 
  /**
   * General dialog action listener. Handles buttons and
   * version combobox changes.
   */
  public ActionListener actions = new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
      String cmd = e.getActionCommand();
      if(cmd.equals("cancel")) {
        setDialogResult(SongPicker.RESULT_CANCEL);
        rootDialog.setVisible(false);
      }
      else if(cmd.equals("ok")) {
        if(!isImmediate) {
          setDialogResult(SongPicker.RESULT_OK);
          rootDialog.setVisible(false);
        } else {
          showSelectedMedia();
        }
      }
      else if(cmd.equals("browse")) {
        browseForMediaFolder();
      }
      else {
        System.out.println("FIXME: actions: Unhandled action: '" + cmd + "'");
      }
    }
  };
 
  /**
   * Handles selection changes for the main list on the dialog
   */
  public ListSelectionListener listSelection = new ListSelectionListener() {
    @Override
    public void valueChanged(ListSelectionEvent e) {
      if(!e.getValueIsAdjusting()) {
        if(e.getSource() == itemsList) {
          updatePreview();
          setButtonsEnabled();
        }
        else {
          System.out.println("MediaPicker: listSelection: unknown source");
        }
      }
    }
  };
 
  public MouseListener listMouse = new MouseListener() {

    @Override
    public void mouseClicked(MouseEvent e) { }

    @Override
    public void mouseEntered(MouseEvent e) { }

    @Override
    public void mouseExited(MouseEvent e) { }

    @Override
    public void mousePressed(MouseEvent e) {
      if(e.getButton() == MouseEvent.BUTTON1) {
        int idx = itemsList.locationToIndex(e.getPoint());
        if(idx == -1) return;
        Rectangle rt = itemsList.getCellBounds(idx, idx);
        if(rt == null) return;
        if(!rt.contains(e.getPoint())) {
          itemsList.clearSelection();
          e.consume();
        }
      }
    }

    @Override
    public void mouseReleased(MouseEvent e) { }
   
  };
 
  private void browseForMediaFolder() {
    String curdir = currentDirField.getText();
    JFileChooser jfc = new JFileChooser(curdir);
    jfc.setDialogTitle(I18n.get("ui/dialogs/mediapicker/folderbrowser?title"));
    jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
    jfc.setMultiSelectionEnabled(false);
    if(jfc.showDialog(rootDialog, I18n.get("ui/dialogs/generic/select")) != JFileChooser.APPROVE_OPTION) return;
   
    currentDirField.setText(jfc.getSelectedFile().getAbsolutePath());
    fillMediaList();
  }
 
  private void fillMediaList() {
    File dir = new File(currentDirField.getText());
    fileList.clear();
    previews.clear();
    thumbs.clear();
    if(!dir.exists() || !dir.isDirectory()) return;
    String[] contents = dir.list();
    Arrays.sort(contents);
   
    Vector<String> exts = new Vector<String>();
    if(allowImages) {
      String[] imgExts = ImageIO.getReaderFileSuffixes();
      for(int i = 0; i < imgExts.length; i++) {
        exts.add(imgExts[i].toLowerCase());
      }
    }
    if(allowVideos) {
      // TODO add video extensions here
    }
   
    for(int i = 0; i < contents.length; i++) {
      File f = new File(dir.getAbsolutePath() + (dir.getAbsolutePath().endsWith(File.separator) ? "" : File.separator) + contents[i]);
      if(!f.exists() || f.isDirectory()) continue;
      for(int j = 0; j < exts.size(); j++) {
        if(contents[i].toLowerCase().endsWith(exts.get(j))) {
          fileList.add(fileList.size(), contents[i]);
          break;
        }
      }
    }
   
    if(curPreviewLoader != null)
      curPreviewLoader.cancelProcess();
   
    curPreviewLoader = new PreviewImageLoader();
    new Thread(curPreviewLoader).start();
  }
 
  private void updatePreview() {
    String img = (String)itemsList.getSelectedValue();
    previewPanel.removeAll();
    previewNameLabel.setText("");
    previewSizeLabel.setText("");
    if(img == null) return;
    if(!thumbs.containsKey(img)) return;
    previewPanel.add(new JLabel(new ImageIcon(thumbs.get(img))), BorderLayout.CENTER);
    Dimension sz = imgSizes.get(img);
    wrapTextIntoLabel(previewNameLabel, I18n.get("ui/dialogs/mediapicker/namelbl", img), previewPanel.getWidth() - 4);
    wrapTextIntoLabel(previewSizeLabel, I18n.get("ui/dialogs/mediapicker/sizelbl", Integer.toString(sz.width) + "x" + Integer.toString(sz.height)), previewPanel.getWidth() - 4);
  }
 
  /**
   * Called when the "display" button is clicked in immediate mode.
   * Shows the currently selected media on the display/preview screens.
   */
  private void showSelectedMedia() {
    int idx = itemsList.getSelectedIndex();
    ImageSlide imgslide = new ImageSlide();
    if(idx == -1) {
      Display.getDisplay().prepareNextBackground(ScreenRunner.currentStyle, imgslide.getStyleType());
      Display.getDisplay().prepareNextSlide(null, 1, ScreenRunner.currentStyle);
    } else {
      Display.getDisplay().prepareNextBackground(ScreenRunner.currentStyle, imgslide.getStyleType());
      imgslide.setUserData(getImageSlidePathString());
      Display.getDisplay().prepareNextSlide(imgslide, 1, ScreenRunner.currentStyle);
    }
    Display.getDisplay().applyChanges();
   
    //if(idx < (fileList.size() - 1)) itemsList.setSelectedIndex(idx + 1);
  }
 
  public String[] getSelectedPaths() {
    Object[] items = itemsList.getSelectedValues();
    String[] files = new String[items.length];
    for(int i = 0; i < items.length; i++) {
      files[i] = getFullPath(items[i].toString());
    }
    return files;
  }
 
  public String getImageSlidePathString() {
    String[] paths = getSelectedPaths();
    String rv = "";
    for(int i = 0; i < paths.length; i++) {
      rv += (i == 0 ? "" : File.pathSeparator) + paths[i];
    }
    return rv;
  }
 
  private void setButtonsEnabled() {
    int idx = itemsList.getSelectedIndex();
    chooseButton.setEnabled((idx != -1));
  }

}
TOP

Related Classes of com.screenrunner.ui.MediaPicker$FileListRefresh

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.