All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.tinymediamanager.ui.panels.ImagePanel Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2012 - 2019 Manuel Laggner
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.tinymediamanager.ui.panels;

import java.awt.FlowLayout;
import java.awt.Point;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.nio.file.Path;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingWorker;

import org.apache.commons.lang3.StringUtils;
import org.imgscalr.Scalr;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tinymediamanager.core.ImageCache;
import org.tinymediamanager.core.ImageUtils;
import org.tinymediamanager.core.entities.MediaFile;
import org.tinymediamanager.ui.MainWindow;
import org.tinymediamanager.ui.WrapLayout;

import net.miginfocom.swing.MigLayout;

/**
 * The Image Panel is used to display all images for a MediaEntity
 * 
 * @author Manuel Laggner
 */
public class ImagePanel extends JPanel implements HierarchyListener {
  private static final long   serialVersionUID = -5344085698387374260L;
  private static final Logger LOGGER           = LoggerFactory.getLogger(ImagePanel.class);

  protected int               maxWidth         = 300;
  protected int               maxHeight        = 100;
  private List     mediaFiles       = null;

  private ImageLoader         activeWorker     = null;

  /**
   * UI components
   */
  private JPanel              panelImages;
  private JScrollPane         scrollPane;

  public ImagePanel(List mediaFiles) {
    this.mediaFiles = mediaFiles;
    setLayout(new MigLayout("", "[400lp,grow]", "[300lp,grow]"));

    scrollPane = new JScrollPane();
    scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    scrollPane.getVerticalScrollBar().setUnitIncrement(16);
    add(scrollPane, "cell 0 0,grow");

    panelImages = new JPanel();
    panelImages.setLayout(new WrapLayout(FlowLayout.LEFT));
    scrollPane.setViewportView(panelImages);
  }

  /**
   * Trigger to rebuild the panel
   */
  public void rebuildPanel() {
    if (activeWorker != null && !activeWorker.isDone()) {
      activeWorker.cancel(true);
    }

    panelImages.removeAll();
    panelImages.revalidate();
    scrollPane.repaint();

    // fetch image in separate worker -> performance
    activeWorker = new ImageLoader(mediaFiles);
    activeWorker.execute();
  }

  public int getMaxWidth() {
    return maxWidth;
  }

  public int getMaxHeight() {
    return maxHeight;
  }

  public void setMaxWidth(int maxWidth) {
    this.maxWidth = maxWidth;
  }

  public void setMaxHeight(int maxHeight) {
    this.maxHeight = maxHeight;
  }

  @Override
  public void hierarchyChanged(HierarchyEvent arg0) {
    if (isShowing() && panelImages.getComponents().length == 0 && mediaFiles.size() > 0) {
      // rebuild the panel
      rebuildPanel();
    }
  }

  @Override
  public void addNotify() {
    super.addNotify();
    addHierarchyListener(this);
  }

  @Override
  public void removeNotify() {
    removeHierarchyListener(this);
    super.removeNotify();
  }

  /**
   * worker to load the images asynchrony
   */
  protected class ImageLoader extends SwingWorker {
    private List mediaFiles;

    private ImageLoader(List mediaFiles) {
      this.mediaFiles = mediaFiles;
    }

    @Override
    protected Void doInBackground() {
      for (MediaFile mediaFile : mediaFiles) {
        if (isShowing()) {
          if (isCancelled()) {
            return null;
          }
          try {
            Path file = ImageCache.getCachedFile(mediaFile);
            if (file == null) {
              file = mediaFile.getFileAsPath();
            }
            BufferedImage bufferedImage = ImageUtils.createImage(file);
            Point size = ImageUtils.calculateSize(maxWidth, maxHeight, bufferedImage.getWidth(), bufferedImage.getHeight(), true);
            BufferedImage img = Scalr.resize(bufferedImage, Scalr.Method.QUALITY, Scalr.Mode.AUTOMATIC, size.x, size.y, Scalr.OP_ANTIALIAS);
            bufferedImage = null;

            if (isCancelled()) {
              return null;
            }

            publish(new ImageChunk(mediaFile.getFileAsPath().toString(), img));
            img = null;
          }
          catch (Exception e) {
            LOGGER.trace("scaling image failed: {}", e.getMessage());
          }
        }
      }
      return null;
    }

    @Override
    protected void process(List chunks) {
      for (ImageChunk chunk : chunks) {
        try {
          if (isCancelled()) {
            return;
          }

          JLabel lblImageJLabel = new JLabel(new ImageIcon(chunk.image));
          lblImageJLabel.addMouseListener(new ImageLabelClickListener(chunk.pathToImage));
          panelImages.add(lblImageJLabel);
          panelImages.revalidate();
          scrollPane.repaint();
        }
        catch (Exception ignored) {
        }
      }
    }
  }

  protected class ImageChunk {
    private String        pathToImage;
    private BufferedImage image;

    private ImageChunk(String path, BufferedImage image) {
      this.pathToImage = path;
      this.image = image;
    }
  }

  /*
   * click listener for creating a lightbox effect
   */
  private class ImageLabelClickListener implements MouseListener {
    private String pathToFile;

    private ImageLabelClickListener(String path) {
      this.pathToFile = path;
    }

    @Override
    public void mouseClicked(MouseEvent arg0) {
      if (StringUtils.isNotBlank(pathToFile)) {
        MainWindow.getActiveInstance().createLightbox(pathToFile, "");
      }
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

    @Override
    public void mousePressed(MouseEvent e) {
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy