/* * This file is part of Caliph & Emir. * * Caliph & Emir 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. * * Caliph & Emir 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 Caliph & Emir; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Copyright statement: * -------------------- * (c) 2002-2005 by Mathias Lux (mathias@juggle.at) * http://www.juggle.at, http://caliph-emir.sourceforge.net */ package at.lux.fotoretrieval.panels; import at.lux.fotoretrieval.ResultListEntry; import at.lux.fotoretrieval.RetrievalToolkit; import at.lux.fotoannotation.AnnotationFrame; import org.jdom.Document; import org.jdom.JDOMException; import org.jdom.transform.JDOMResult; import org.jdom.transform.JDOMSource; import javax.imageio.ImageIO; import javax.swing.*; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.transform.stream.StreamSource; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; import java.io.IOException; import java.io.FileInputStream; import java.net.*; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.*; import java.util.List; /** * ResultsPanel * * @author Mathias Lux, mathias@juggle.at */ public class ResultsPanel extends JPanel { private static int max = 20; private List<ResultListEntry> results; private JProgressBar progress; private boolean show_thumbs = true; private QualityConstraintPanel qualityConstraints = null; private static DecimalFormat df; static { df = ((DecimalFormat) DecimalFormat.getInstance()); df.setMaximumFractionDigits(2); } // private StreamSource streamSource = null; public ResultsPanel(List<ResultListEntry> results, JProgressBar progress) { this.results = results; this.progress = progress; init(); } public ResultsPanel(List<ResultListEntry> results, JProgressBar progress, QualityConstraintPanel qualityConstraints) { this.results = results; this.progress = progress; this.qualityConstraints = qualityConstraints; init(); } public ResultsPanel(Vector results) { this.results = results; this.progress = null; init(); } private void init() { this.setLayout(new BorderLayout()); JPanel thumbs = new JPanel(new GridLayout(0, 1)); JPanel descriptions = new JPanel(new GridLayout(0, 1)); JPanel resultsPanel = new JPanel(new BorderLayout()); DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(); df.setMaximumFractionDigits(2); // df.setMaximumIntegerDigits(3); if (progress != null) { progress.setMinimum(0); progress.setMaximum(Math.min(max, results.size())); progress.setValue(0); progress.setString("Formatting results"); } int count = 0; File file; String strDesc; ResultThumbnailPanel thumb = null; for (Iterator i = results.iterator(); i.hasNext();) { ResultListEntry entry = (ResultListEntry) i.next(); if (entry.getFilePath() != null) try { // long time = System.currentTimeMillis(); // file = new File(); thumb = null; int qualityRating = 1; if (show_thumbs) { if ((entry.getThumbPath() == null)) { thumb = new ResultThumbnailPanel(entry.getFilePath()); } else if (entry.getThumbPath().startsWith("file:")) { boolean isValid = true; URL thumbURL = new URI(entry.getThumbPath()).toURL(); try { thumbURL.openStream(); } catch (IOException ioex) { // so the url stored in the MPEG-7 file is false isValid = false; // System.err.println("Did not find thumbnail: " + thumbURL.toString()); } if (isValid == false) { // now we try and see if the file is in the directory of the description: String path = entry.getDescriptionPath().substring(0, entry.getDescriptionPath().lastIndexOf('\\')); String thumbnailFile = entry.getThumbPath().substring(entry.getThumbPath().lastIndexOf('/') + 1); String x = path + "\\" + thumbnailFile; // System.out.println(x); File thumbTwemp = new File(x); if (thumbTwemp.exists()) { // yes it's here ... thumbURL = thumbTwemp.toURL(); isValid = true; } } try { if (isValid) { thumb = new ResultThumbnailPanel(ImageIO.read(thumbURL), thumbURL.toString().replaceAll("tn_", "")); } else { File f = new File(entry.getDescriptionPath()); // debug(f.getParent() + thumbURL.getFile().substring(thumbURL.getFile().lastIndexOf('/'))); String thumbPath = f.getParent() + thumbURL.getFile().substring(thumbURL.getFile().lastIndexOf('/')); File inputFile = new File(thumbPath); thumb = new ResultThumbnailPanel(ImageIO.read(inputFile), thumbPath.replaceAll("tn_", "")); } } catch (IOException e) { thumb = new ResultThumbnailPanel(entry.getFilePath()); } } else { thumb = new ResultThumbnailPanel(ImageIO.read(new FileInputStream(entry.getThumbPath())), entry.getFilePath()); } thumb.setToolTipText("Right mouse button opens entry in Caliph / Editor."); } /* // old method ... String doc = "<html><i>Relevance: </i>" + df.format(entry.getRelevance()) + "<br>"; doc += "<i>Image: </i>" + entry.getImageFilePath() + ", " + entry.getImageSize() + "<br>"; doc += "<i>Creator: </i>" + entry.getCreatorName() + "<br>"; doc += "<i>Creation time: </i>" + entry.getCreationTime() + "<br>"; doc += "<i>Description: </i>" + entry.getFreeTextDescription() + "<br>"; doc += "<i>Semantics: </i>" + entry.getSemanticDescriptionString() + "<br>"; doc += "</html>"; */ JPanel descPanel = new JPanel(new BorderLayout()); GridLayout layout = new GridLayout(0, 1); layout.setHgap(1); layout.setVgap(1); JPanel namesPanel = new JPanel(layout); JPanel valuesPanel = new JPanel(layout); // Font plainFont = this.getFont().deriveFont(Font.PLAIN); namesPanel.add(createBoldLabel("Relevance: ")); namesPanel.add(createBoldLabel("Image: ")); namesPanel.add(createBoldLabel("Creator: ")); namesPanel.add(createBoldLabel("Time: ")); namesPanel.add(createBoldLabel("Description: ")); // namesPanel.add(new JLabel("Semantics: ")); valuesPanel.add(new JLabel(df.format(entry.getRelevance()))); valuesPanel.add(new JLabel(entry.getImageFilePath() + ", " + entry.getImageSize())); valuesPanel.add(new JLabel(entry.getCreatorName())); valuesPanel.add(new JLabel(entry.getCreationTime())); valuesPanel.add(new JLabel(entry.getFreeTextDescription())); // valuesPanel.add(new JLabel(entry.getSemanticDescriptionString())); // Component[] labels = valuesPanel.getComponents(); // for (int j = 0; j < labels.length; j++) { // Component label = labels[j]; // if (label instanceof JLabel) { // label.setFont(plainFont); // } // } descPanel.add(namesPanel, BorderLayout.WEST); descPanel.add(valuesPanel, BorderLayout.CENTER); descPanel.addMouseListener(new MyMouseAdapter(entry)); // String doc = entry.getHTMLSummary(); // String fpath = entry.getFilePath(); // JLabel desc; // debug(doc); // if (doc != null) { // desc = new JLabel(doc); // } else { // desc = new JLabel("No description available!"); // } JPanel rowPanel = new JPanel(new BorderLayout()); if (thumb != null) rowPanel.add(thumb, BorderLayout.WEST); rowPanel.add(descPanel, BorderLayout.CENTER); rowPanel.add(new JSeparator(), BorderLayout.SOUTH); JPanel tmpPanel = new JPanel(new BorderLayout()); boolean add = false; // if (entry!=null) debug("entry is not NULL"); // if (qualityConstraints!=null) debug("qualityConstraints is not NULL"); // debug("Quality: " + entry.getQuality() + ", Mode: " + qualityConstraints.getMode()); if (qualityConstraints != null) { if ((entry.getQuality() < 0 && qualityConstraints.getMode() != 2)) { // Die Beschreibung enth�lt keine Qualit�tsbewertung, daher wird das File immer angezeigt, // ausser man sucht nach einer bestimmten Qualit�t (genau) add = true; } else { if (qualityConstraints.getMode() == 0) { // eine untere Grenze wurde angegeben ... if (entry.getQuality() >= qualityConstraints.getQuality()) { add = true; } } else if (qualityConstraints.getMode() == 1) { // eine obere Grenze wurd angegeben if (entry.getQuality() <= qualityConstraints.getQuality()) { add = true; } } else if (qualityConstraints.getMode() == 2) { // eine bestimmte qualit�tsstufe wird gesucht ... if (entry.getQuality() == qualityConstraints.getQuality()) { add = true; } } } } else { add = true; } if (add) { tmpPanel.add(rowPanel, BorderLayout.NORTH); descriptions.add(tmpPanel); } if (progress != null) { progress.setValue(count++); } // System.out.println("One row: " + (System.currentTimeMillis() - time) + " ms"); } catch (Exception e) { e.printStackTrace(); } if (count > max) break; } resultsPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // resultsPanel.add(thumbs, BorderLayout.WEST); resultsPanel.add(descriptions, BorderLayout.CENTER); this.add(new JScrollPane(resultsPanel), BorderLayout.CENTER); } public Image getImage(String FileName) { // Load image Image loadedImage = Toolkit.getDefaultToolkit().getImage(FileName); // Wait until loaded try { MediaTracker mediaTracker = new MediaTracker(this); mediaTracker.addImage(loadedImage, 0); mediaTracker.waitForID(0); } catch (InterruptedException e) { e.printStackTrace(); } // Return loaded image return loadedImage; } private Document transform(Document in) throws JDOMException { Document d = null; try { Transformer transformer = TransformerFactory.newInstance(). newTransformer(new StreamSource(RetrievalToolkit.class.getResource("data/html-short.xsl").openStream())); JDOMResult out = new JDOMResult(); transformer.transform(new JDOMSource(in), out); d = out.getDocument(); } catch (TransformerException e) { debug("Transformation failed, TransformerException: " + e.getMessageAndLocation()); } catch (TransformerFactoryConfigurationError error) { debug("Transformation failed, " + error.toString()); } catch (IOException e) { debug("Transformation failed, IOException: " + e.getMessage()); } return d; } private void debug(String message) { System.out.println("[at.lux.fotoretrieval.panels.ResultsPanel] " + message); } private JLabel createBoldLabel(String text) { JLabel result = new JLabel(); result.setFont(result.getFont().deriveFont(Font.BOLD)); result.setText(text); return result; } /** * Returns an array containing all result file descriptions * * @return array containing all result file descriptions sorted by relevance. */ public String[] getResultFiles() { ArrayList<String> result = new ArrayList<String>(results.size()); for (Iterator<ResultListEntry> iterator = results.iterator(); iterator.hasNext();) { ResultListEntry entry = iterator.next(); result.add(entry.getDescriptionPath()); } return (String[]) result.toArray(new String[0]); } public String getResultHtml() { StringBuilder sb = new StringBuilder(1024); sb.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n" + "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" + "<head>\n" + "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\" />\n" + "<title>Emir Results</title>\n" + "<style type=\"text/css\">\n" + "<!--\n" + ".result {\n" + "\tborder-bottom-width: 1px;\n" + "\tborder-top-style: solid;\n" + "\tborder-right-style: solid;\n" + "\tborder-bottom-style: solid;\n" + "\tborder-left-style: solid;\n" + "\tborder-top-color: #999999;\n" + "\tborder-right-color: #999999;\n" + "\tborder-bottom-color: #999999;\n" + "\tborder-left-color: #999999;\n" + "\tborder-top-width: 0px;\n" + "\tborder-right-width: 0px;\n" + "\tborder-left-width: 0px;\n" + "\theight: 140px;\n" + "\tposition: relative;\n" + "\tleft: 140px;\n" + "}\n" + "body {\n" + "\tbackground-color: #FFFFFF;\n" + "\twidth: 640px;\n" + "\tfont-family: Georgia, Times, serif;\n" + "\tfont-size: 10pt;\n" + "}\n" + ".imgbox {\n" + "\tposition: relative;\n" + "\tleft: -140px;\n" + "\ttop: 0px;\n" + "\theight: 120px;\n" + "\twidth: 120px;\n" + "\tborder: 1px solid #CCCCCC;\n" + "\ttext-align: center;\n" + "\tvertical-align: middle;\n" + "\tmargin: 5px;\n" + "\tpadding: 5px;\n" + "}\n" + ".description {\n" + "\tposition: relative;\n" + "\ttop: -140px;\n" + "\tmargin-left: 5px;\n" + "}\n" + "-->\n" + "</style>\n" + "</head>\n" + "<body>\n"); for (ResultListEntry entry : results) { String descriptionPath = entry.getDescriptionPath(); int endIndex = Math.max(descriptionPath.lastIndexOf("\\"), descriptionPath.lastIndexOf("/")); String directory = descriptionPath.substring(0, endIndex); String thumbnail = entry.getThumbPath().replaceAll("file:", ""); thumbnail = thumbnail.substring(thumbnail.lastIndexOf("/")); thumbnail = directory + thumbnail; String imageFile = directory + "/" + entry.getImageFilePath(); sb.append("<div class=\"result\">\n" + " <div class=\"imgbox\" calss=\"imgbox\">" + "<a href=\"file://" + imageFile + "\">" + "<img src=\"file://" + thumbnail + "\" alt=\"img1.jpg\" border=\"0\" align=\"middle\" /></a></div>\n" + " <div class=\"description\"> <strong>Score:</strong> "+entry.getRelevance()+" <br />\n" + " <strong>File:</strong> " + entry.getImageFilePath() + " [<a href=\"file://"+descriptionPath +"\">open MPEG-7 file</a>] <br />\n" + " <strong>Description:</strong> "+entry.getFreeTextDescription()+" </div>\n" + "</div>\n"); } sb.append("</body>\n" + "</html>"); return sb.toString(); } private static class MyMouseAdapter extends MouseAdapter { private final ResultListEntry entry; private static AnnotationFrame caliph; public MyMouseAdapter(ResultListEntry entry) { this.entry = entry; } public void mouseClicked(MouseEvent e) { System.out.println("e = " + e.getButton()); if (e.getButton() == MouseEvent.BUTTON3) { if (caliph == null) { caliph = new AnnotationFrame(false); } String descriptionPath = entry.getDescriptionPath(); String filePath = entry.getFilePath(); int descriptionPathEndIndex = Math.max(descriptionPath.lastIndexOf('\\'), descriptionPath.lastIndexOf('/')); String file = descriptionPath.substring(0, descriptionPathEndIndex) + filePath.substring(filePath.lastIndexOf('/')); File description = new File(file); if (!description.exists()) JOptionPane.showMessageDialog(null, "Could not find file " + entry.getFilePath(), "Error loading description", JOptionPane.ERROR_MESSAGE); try { caliph.setCurrentFile(description); caliph.setVisible(true); } catch (IOException e1) { e1.printStackTrace(); } } } } }