/* Copyright (C) 2005-2011 Fabio Riccardi */
package com.lightcrafts.ui.browser.view;
import com.lightcrafts.image.metadata.ImageMetadata;
import com.lightcrafts.ui.browser.model.ImageDatum;
import com.lightcrafts.ui.browser.model.ImageDatumType;
import com.lightcrafts.ui.browser.model.ImageGroup;
import com.lightcrafts.ui.browser.model.ImageList;
import com.lightcrafts.ui.LightZoneSkin;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.image.RenderedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/**
* Like ExpandedImageBrowser, except only the one ImageDatum in each ImageGroup
* with the most recent file modification time is shown.
*/
public class CollapsedImageBrowser extends AbstractImageBrowser {
public CollapsedImageBrowser(ImageList list) {
super(list);
}
protected void paintComponent(Graphics graphics) {
if (justShown) {
if (!paintTimer.isRunning())
paintTimer.start();
return;
}
if (! isWidthInitialized) {
// Only paint if the component size has been initialized. Layout
// jumps are typical the first time this component is displayed,
// because the preferred height depends on the component width.
return;
}
Graphics2D g = (Graphics2D) graphics;
Rectangle clip = g.getClipBounds();
// Figure out which ImageDatums fall within the clip bounds.
List<ImageDatum> datums = getAllImageData();
int[] indices = getIndices(datums.size(), clip);
// Iterate backwards through indices, so repaints get enqueued
// in a visually pleasing order.
for (int i=indices.length-1; i>=0; i--) {
int index = indices[i];
if (index < 0) {
continue;
}
ImageDatum datum = datums.get(index);
if (datum == null) {
// A race; the image disappeared during painting.
continue;
}
RenderedImage image = datum.getImage(this);
// This queue prevents GC of recently painted images:
recentImages.add(image);
Rectangle rect = getBounds(index);
g.setClip(clip.intersection(rect));
File file = datum.getFile();
String label = file.getName();
ImageDatumType type = datum.getType();
String tag = type.toString();
ImageMetadata meta = datum.getMetadata(true);
int rating = meta.getRating();
boolean selected = selection.isSelected(datum);
renderer.paint(g, image, label, tag, rating, rect, selected);
ImageGroup group = datum.getGroup();
if (group.isNonTrivial()) {
ImageGroupCountRenderer.paint(g, rect, datum);
}
}
g.setClip(clip);
// The control is drawn as an overlay.
if (controller.isEnabled()) {
Rectangle ctrlRect = controller.getRect();
if (ctrlRect != null) {
if (ctrlRect.intersects(clip)) {
controller.paint(g);
}
}
}
}
/**
* Get the ImageDatums rendered in this AbstractImageBrowser: the ones that
* are the most recently modified among all ImageDatums in their ImageGroup.
*/
ArrayList<ImageDatum> getAllImageData() {
List<ImageDatum> allDatums = list.getAllImageData();
Set<ImageDatum> recentDatums = new LinkedHashSet<ImageDatum>();
for (ImageDatum datum : allDatums) {
ImageGroup group = datum.getGroup();
List<ImageDatum> members = group.getImageDatums();
long lastTime = 0;
ImageDatum lastMember = null;
for (ImageDatum member : members) {
File file = member.getFile();
long modTime = file.lastModified();
if (modTime > lastTime) {
lastMember = member;
lastTime = modTime;
}
}
recentDatums.add(lastMember);
}
return new ArrayList<ImageDatum>(recentDatums);
}
void updateSelectionDatumRemoved(ImageDatum datum, int index) {
List<ImageDatum> selected = selection.getSelected();
if (selected.contains(datum)) {
if (selected.size() == 1) {
ArrayList<ImageDatum> visible = getAllImageData();
ArrayList<ImageDatum> all = list.getAllImageData();
ImageDatum next = null;
if (index == 0) {
// If the first image was deleted, select the new first
if (visible.size() > 0) {
next = visible.get(0);
}
}
else {
// If the deleted one was NOT a version, walk FORWARDS
// starting at the SAME position until we find a visible
// image.
if (! datum.getType().hasLznData()) {
int max = all.size() - 1;
while ((index < max) && (! visible.contains(next))) {
next = all.get(index++);
}
}
// Otherwise, walk BACKWARDS starting with the PREVIOUS
// position until we find a visible image
else {
while ((index > 0) && (! visible.contains(next))) {
next = all.get(--index);
}
}
}
if (next != null) {
int i = visible.indexOf(next);
selection.setLeadSelected(next);
if (i >= 0) {
Rectangle bounds = getBounds(i);
scrollRectToVisible(bounds);
}
}
}
else {
selection.removeSelected(datum);
}
}
}
}