org.openmicroscopy.shoola.agents.metadata.editor.DocComponent.java Source code

Java tutorial

Introduction

Here is the source code for org.openmicroscopy.shoola.agents.metadata.editor.DocComponent.java

Source

/*
 * org.openmicroscopy.shoola.agents.metadata.editor.DocComponent 
 *
 *------------------------------------------------------------------------------
 *  Copyright (C) 2006-2014 University of Dundee. All rights reserved.
 *
 *
 *    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.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *------------------------------------------------------------------------------
 */
package org.openmicroscopy.shoola.agents.metadata.editor;

//Java imports
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.swing.Box;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;

//Third-party libraries
import org.apache.commons.lang.StringUtils;

//Application-internal dependencies
import omero.model.OriginalFile;
import org.openmicroscopy.shoola.agents.editor.EditorAgent;
import org.openmicroscopy.shoola.agents.events.editor.EditFileEvent;
import org.openmicroscopy.shoola.agents.metadata.IconManager;
import org.openmicroscopy.shoola.agents.metadata.MetadataViewerAgent;
import org.openmicroscopy.shoola.agents.util.DataObjectListCellRenderer;
import org.openmicroscopy.shoola.agents.util.EditorUtil;
import org.openmicroscopy.shoola.agents.util.editorpreview.PreviewPanel;
import org.openmicroscopy.shoola.agents.util.ui.EditorDialog;
import org.openmicroscopy.shoola.env.config.Registry;
import org.openmicroscopy.shoola.env.data.model.DownloadActivityParam;
import org.openmicroscopy.shoola.env.event.EventBus;
import org.openmicroscopy.shoola.env.ui.UserNotifier;
import org.openmicroscopy.shoola.util.filter.file.BMPFilter;
import org.openmicroscopy.shoola.util.filter.file.CustomizedFileFilter;
import org.openmicroscopy.shoola.util.filter.file.JPEGFilter;
import org.openmicroscopy.shoola.util.filter.file.PNGFilter;
import org.openmicroscopy.shoola.util.filter.file.TIFFFilter;
import org.openmicroscopy.shoola.util.image.geom.Factory;
import org.openmicroscopy.shoola.util.ui.UIUtilities;
import org.openmicroscopy.shoola.util.ui.filechooser.FileChooser;
import org.openmicroscopy.shoola.util.ui.tdialog.TinyDialog;

import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;

import pojos.AnnotationData;
import pojos.BooleanAnnotationData;
import pojos.DataObject;
import pojos.DoubleAnnotationData;
import pojos.ExperimenterData;
import pojos.FileAnnotationData;
import pojos.LongAnnotationData;
import pojos.TagAnnotationData;
import pojos.TermAnnotationData;
import pojos.XMLAnnotationData;

/** 
 * Component displaying the annotation, either <code>FileAnnotationData</code>
 * or <code>TagAnnotationData</code>.
 *
 * @author  Jean-Marie Burel &nbsp;&nbsp;&nbsp;&nbsp;
 * <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a>
 * @author Donald MacDonald &nbsp;&nbsp;&nbsp;&nbsp;
 * <a href="mailto:donald@lifesci.dundee.ac.uk">donald@lifesci.dundee.ac.uk</a>
 * @version 3.0
 * <small>
 * (<b>Internal version:</b> $Revision: $Date: $)
 * </small>
 * @since 3.0-Beta4
 */
class DocComponent extends JPanel implements ActionListener, PropertyChangeListener {

    /** Flag indicates to load the image from the server. */
    static final int LOAD_FROM_SERVER = 0;

    /** Flag indicates to load the image from the local machine. */
    static final int LOAD_FROM_LOCAL = 1;

    /** Action id to unlink the annotation. */
    private static final int REMOVE = 0;

    /** Action id to edit the annotation. */
    private static final int EDIT = 1;

    /** Action id to download the file. */
    private static final int DOWNLOAD = 2;

    /** Action id to open the annotation. */
    private static final int OPEN = 3;

    /** Collection of filters supported. */
    private static final ImmutableCollection<CustomizedFileFilter> FILTERS = ImmutableList.of(new TIFFFilter(),
            new JPEGFilter(), new PNGFilter(), new BMPFilter());

    /** The maximum length of the text to display.*/
    private static final int TEXT_LENGTH = 10;

    /** The annotation hosted by this component. */
    private Object data;

    /** Reference to the model. */
    private EditorModel model;

    /** Button to unlink the annotation. */
    private JMenuItem unlinkButton;

    /** Button to edit the annotation. */
    private JMenuItem editButton;

    /** Button to download the file linked to the annotation. */
    private JMenuItem downloadButton;

    /** Button to open the file linked to the annotation. */
    private JMenuItem openButton;

    /** Button to display information. */
    private JMenuItem infoButton;

    /** Component displaying the file name. */
    private JLabel label;

    /** The location of the mouse click. */
    private Point popupPoint;

    /** The original description of the tag. */
    private String originalDescription;

    /** The original description of the tag. */
    private String originalName;

    /** The Button used to display the managing option. */
    private JButton menuButton;

    /** 
     * The component used to display the summary of the protocol or
     * experiment.
     */
    private PreviewPanel preview;

    /** 
     * Index indicating that the attachment is an image that
     * can be displayed as a thumbnail e.g. TIFF, JPEG, PNG, etc.
     */
    private int imageToLoad;

    /** 
     * The thumbnail corresponding to the attachment, <code>null</code>
     * if the attachment is not a supported image.
     */
    private Icon thumbnail;

    /** The pop-up menu. */
    private JPopupMenu popMenu;

    /** Flag indicating if the node can be deleted. */
    private boolean deletable;

    /** Flag indicating if it is a XML modulo annotation.*/
    private boolean isModulo;

    /**
     * Enables or disables the various buttons depending on the passed value.
     * Returns <code>true</code> if some controls are visible, 
     * <code>false</code> otherwise.
     * 
     * @param enabled    Pass <code>true</code> to enable the controls,
     *                <code>false</code> otherwise.
     * @return See above.
     */
    private boolean setControlsEnabled(boolean enabled) {
        int count = 0;
        if (infoButton != null) {
            infoButton.setEnabled(true);
            infoButton.setVisible(true);
            count++;
        }
        if (!enabled) {
            if (unlinkButton != null) {
                unlinkButton.setEnabled(false);
                unlinkButton.setVisible(false);
            }
            if (editButton != null) {
                editButton.setEnabled(false);
                editButton.setVisible(false);
            }
            if (downloadButton != null) {
                downloadButton.setEnabled(false);
                downloadButton.setVisible(false);
            }
            if (openButton != null) {
                openButton.setEnabled(false);
                openButton.setVisible(false);
            }
            return count > 0;
        }
        boolean b = false;
        if (unlinkButton != null) {
            b = model.canDeleteLink(data);
            if (b && isModulo) { //check if it is a modulo annotation. Do not remove.
                b = false;
            }
            unlinkButton.setEnabled(b);
            unlinkButton.setVisible(b);
            if (b)
                count++;
        }

        if (editButton != null) {
            b = model.canEdit(data);
            editButton.setEnabled(b);
            editButton.setVisible(b);
            if (b)
                count++;
        }
        if (downloadButton != null) {
            b = true;
            downloadButton.setEnabled(b);
            downloadButton.setVisible(b);
            if (b)
                count++;
        }
        if (openButton != null) {
            b = true;
            openButton.setEnabled(b);
            openButton.setVisible(b);
            if (b)
                count++;
        }
        return count > 0;
    }

    /** Opens the file. */
    private void openFile() {
        if (!(data instanceof FileAnnotationData))
            return;
        EventBus bus = MetadataViewerAgent.getRegistry().getEventBus();
        bus.post(new EditFileEvent(model.getSecurityContext(), (FileAnnotationData) data));
    }

    /** 
     * Brings up the menu. 
     * 
     * @param invoker The component where the clicks occurred.
     * @param p The location of the mouse pressed.
     */
    private void showMenu(JComponent invoker, Point p) {
        if (popMenu == null) {
            popMenu = new JPopupMenu();
            if (editButton != null)
                popMenu.add(editButton);
            if (unlinkButton != null)
                popMenu.add(unlinkButton);
            if (downloadButton != null)
                popMenu.add(downloadButton);
            if (openButton != null)
                popMenu.add(openButton);
            if (infoButton != null)
                popMenu.add(infoButton);
        }
        popMenu.show(invoker, p.x, p.y);
    }

    /**
     * Displays information about the attachment.
     * 
     * @param invoker The component where the clicks occurred.
     * @param p The location of the mouse pressed.
     */
    private void displayInformation(JComponent invoker, Point p) {
        String text = label.getToolTipText();
        if (text == null || text.trim().length() == 0)
            return;
        JComponent comp;
        if (preview != null) {
            comp = preview;
        } else {
            JLabel l = new JLabel();
            l.setText(text);
            comp = l;
        }

        TinyDialog d = new TinyDialog(null, comp, TinyDialog.CLOSE_ONLY);
        d.setModal(true);
        d.getContentPane().setBackground(UIUtilities.BACKGROUND_COLOUR_EVEN);
        SwingUtilities.convertPointToScreen(p, invoker);
        d.pack();
        d.setLocation(p);
        d.setVisible(true);
    }

    /**
     * Adds the experimenters who use the annotation if any.
     * 
     * @param buf The buffer
     * @param annotation The annotation to handle.
     */
    private void checkAnnotators(StringBuffer buf, AnnotationData annotation) {
        List<ExperimenterData> annotators = model.getAnnotators(annotation);
        if (annotators.size() == 0)
            return;
        Iterator<ExperimenterData> i = annotators.iterator();
        ExperimenterData annotator;
        buf.append("<b>Linked by:</b><br>");
        while (i.hasNext()) {
            annotator = i.next();
            buf.append(EditorUtil.formatExperimenter(annotator) + "<br>");
        }
        if (annotators.size() > 1) {
            String text = label.getText();
            text += " [" + annotators.size() + "]";
            label.setText(text);
        }
    }

    /**
     * Returns the list of users who annotated that image only if the
     * annotation cannot be unlinked.
     * 
     * @param object The object the annotation is linked to.
     * @param annotation The annotation to handle.
     */
    private String formatAnnotators(DataObject object, AnnotationData annotation) {
        StringBuffer buffer = new StringBuffer();
        List<ExperimenterData> annotators = model.getAnnotators(object, annotation);
        if (annotators.size() == 0)
            return null;
        long userID = model.getCurrentUser().getId();
        Iterator<ExperimenterData> i = annotators.iterator();
        ExperimenterData annotator;
        int n = annotators.size() - 1;
        int index = 0;
        buffer.append(" (");
        while (i.hasNext()) {
            annotator = i.next();
            if (annotator.getId() != userID) {
                buffer.append(EditorUtil.formatExperimenter(annotator));
                if (index != n)
                    buffer.append(", ");
                index++;
            }
        }
        if (index == 0)
            return null;
        buffer.append(")");
        return buffer.toString();
    }

    /**
     * Formats the passed annotation.
     * 
     * @param annotation The value to format.
     * @param name The full name.
     * @return See above.
     */
    private String formatToolTip(AnnotationData annotation, String name) {
        StringBuffer buf = new StringBuffer();
        buf.append("<html><body>");
        if (model.isMultiSelection()) {
            Map<DataObject, Boolean> m = null;
            Entry<DataObject, Boolean> e;
            Iterator<Entry<DataObject, Boolean>> j;
            String text = "";
            if (annotation instanceof TagAnnotationData) {
                m = model.getTaggedObjects(annotation);
                text += "Can remove Tag from ";
            } else if (annotation instanceof FileAnnotationData) {
                m = model.getObjectsWith(annotation);
                text += "Can remove Attachment from ";
            } else if (annotation instanceof XMLAnnotationData) {
                m = model.getObjectsWith(annotation);
                text += "Can remove XML files from ";
            } else if (annotation instanceof TermAnnotationData) {
                m = model.getObjectsWith(annotation);
                text += "Can remove Term from ";
            }
            if (m == null)
                return "";
            j = m.entrySet().iterator();
            Collection<Boolean> l = m.values();
            int n = 0;
            Iterator<Boolean> k = l.iterator();
            while (k.hasNext()) {
                if (k.next().booleanValue())
                    n++;
            }
            buf.append(text);
            buf.append(n);
            int index = 0;
            String s;
            while (j.hasNext()) {
                e = j.next();
                if (index == 0) {
                    buf.append(" ");
                    buf.append("<b>");
                    buf.append(model.getObjectTypeAsString(e.getKey()));
                    if (n > 1)
                        buf.append("s");
                    buf.append(":</b>");
                    buf.append("<br>");
                    index++;
                }
                buf.append("<b>");
                buf.append("ID ");
                buf.append(e.getKey().getId());
                buf.append(":</b> ");
                buf.append(UIUtilities.formatPartialName(model.getObjectName(e.getKey())));
                //Indicates who annotates the object if not the user
                //currently logged in.
                s = formatAnnotators(e.getKey(), annotation);
                if (s != null)
                    buf.append(s);
                buf.append("<br>");
            }
            buf.append("</body></html>");
            return buf.toString();
        }

        ExperimenterData exp = null;
        if (name != null) {
            buf.append("<b>");
            buf.append("Name: ");
            buf.append("</b>");
            buf.append(name);
            buf.append("<br>");
        }
        if (annotation.getId() > 0)
            exp = model.getOwner(annotation);
        if (exp != null) {
            buf.append("<b>");
            buf.append("Owner: ");
            buf.append("</b>");
            buf.append(EditorUtil.formatExperimenter(exp));
            buf.append("<br>");
        }

        if (data instanceof FileAnnotationData) {
            String ns = ((FileAnnotationData) data).getNameSpace();
            if (FileAnnotationData.EDITOR_EXPERIMENT_NS.equals(ns)
                    || FileAnnotationData.EDITOR_PROTOCOL_NS.equals(ns)) {
                FileAnnotationData fa = (FileAnnotationData) data;
                preview = new PreviewPanel(fa.getDescription(), fa.getId());
                buf.append("<b>");
                if (FileAnnotationData.EDITOR_EXPERIMENT_NS.equals(ns))
                    buf.append("Experiment Description: ");
                else
                    buf.append("Protocol Description: ");
                buf.append("</b>");
                List<String> values = preview.getFormattedDesciption();
                Iterator<String> i = values.iterator();
                while (i.hasNext()) {
                    buf.append(i.next());
                    buf.append("<br>");
                }
                buf.append("<b>");
            }
            if (annotation.getId() > 0) {
                buf.append("<b>");
                buf.append("Annotation ID: ");
                buf.append("</b>");
                buf.append(annotation.getId());
                buf.append("<br>");
                buf.append("<b>");
                buf.append("File ID: ");
                buf.append("</b>");
                FileAnnotationData fa = (FileAnnotationData) data;
                buf.append(fa.getFileID());
                buf.append("<br>");
                buf.append("<b>");
                buf.append("Date Added: ");
                buf.append("</b>");
                buf.append(UIUtilities.formatWDMYDate(annotation.getLastModified()));
                buf.append("<br>");
                buf.append("<b>");
            }

            buf.append("Size: ");
            buf.append("</b>");
            //size not kb
            long size = ((FileAnnotationData) annotation).getFileSize();
            buf.append(UIUtilities.formatFileSize(size));
            buf.append("<br>");
            checkAnnotators(buf, annotation);
            if (!StringUtils.isBlank(ns)) {
                buf.append("<b>");
                buf.append("Namespace: ");
                buf.append("</b>");
                buf.append(ns);
                buf.append("<br>");
            }
        } else if (data instanceof TagAnnotationData || data instanceof XMLAnnotationData
                || data instanceof TermAnnotationData || data instanceof LongAnnotationData
                || data instanceof DoubleAnnotationData || data instanceof BooleanAnnotationData) {
            checkAnnotators(buf, annotation);
        }
        buf.append("</body></html>");
        return buf.toString();
    }

    /** 
     * Posts an event on the eventBus, with the attachment file's ID, name etc.
     */
    private void postFileClicked() {
        if (data == null)
            return;
        if (data instanceof FileAnnotationData) {
            FileAnnotationData f = (FileAnnotationData) data;
            Registry reg = MetadataViewerAgent.getRegistry();
            reg.getEventBus().post(new EditFileEvent(model.getSecurityContext(), f));
        }
    }

    /** Initializes the various buttons. */
    private void initButtons() {
        IconManager icons = IconManager.getInstance();
        menuButton = new JButton(icons.getIcon(IconManager.UP_DOWN_9_12));
        UIUtilities.unifiedButtonLookAndFeel(menuButton);
        menuButton.setBackground(UIUtilities.BACKGROUND_COLOR);
        menuButton.addMouseListener(new MouseAdapter() {

            public void mousePressed(MouseEvent e) {
                showMenu(menuButton, e.getPoint());
            }
        });
        infoButton = new JMenuItem(icons.getIcon(IconManager.INFO));
        infoButton.setText("Info...");
        infoButton.addMouseListener(new MouseAdapter() {

            public void mousePressed(MouseEvent e) {
                popMenu.setVisible(false);
                displayInformation(label, e.getPoint());
            }
        });
        unlinkButton = new JMenuItem(icons.getIcon(IconManager.MINUS_12));
        unlinkButton.setText("Remove");
        unlinkButton.addActionListener(this);
        unlinkButton.setActionCommand("" + REMOVE);
        if (data instanceof FileAnnotationData) {
            FileAnnotationData fa = (FileAnnotationData) data;
            unlinkButton.setToolTipText("Remove the attachment.");

            if (fa.getId() > 0) {
                unlinkButton.setEnabled(deletable);
                downloadButton = new JMenuItem(icons.getIcon(IconManager.DOWNLOAD_12));
                downloadButton.setText("Download...");
                downloadButton.setToolTipText("Download the selected file.");
                downloadButton.setActionCommand("" + DOWNLOAD);
                downloadButton.addActionListener(this);

                String ns = fa.getNameSpace();
                openButton = new JMenuItem(icons.getIcon(IconManager.VIEW_DOC_12));
                openButton.setText("View");
                openButton.setToolTipText("View the file.");
                openButton.setActionCommand("" + OPEN);
                openButton.addActionListener(this);
                if (FileAnnotationData.COMPANION_FILE_NS.equals(ns) || FileAnnotationData.MEASUREMENT_NS.equals(ns))
                    unlinkButton = null;
            }
        } else if (data instanceof TagAnnotationData || data instanceof XMLAnnotationData
                || data instanceof TermAnnotationData || data instanceof LongAnnotationData
                || data instanceof DoubleAnnotationData) {
            unlinkButton.setToolTipText("Remove the annotation.");
            editButton = new JMenuItem(icons.getIcon(IconManager.EDIT_12));
            if (isModulo)
                editButton.setText("View");
            else
                editButton.setText("Edit");
            editButton.setActionCommand("" + EDIT);
            editButton.addActionListener(this);
            editButton.addMouseListener(new MouseAdapter() {

                /** 
                 * Sets the location of the mouse click.
                 * @see MouseAdapter#mousePressed(MouseEvent)
                 */
                public void mousePressed(MouseEvent e) {
                    popupPoint = e.getPoint();
                }

            });
        }
    }

    /** Initializes the components composing the display. */
    private void initComponents() {
        isModulo = model.isModulo(data);
        imageToLoad = -1;
        initButtons();
        label = new JLabel();
        label.setForeground(UIUtilities.DEFAULT_FONT_COLOR);
        if (data == null) {
            label.setText(AnnotationUI.DEFAULT_TEXT);
        } else {
            if (data instanceof FileAnnotationData) {
                FileAnnotationData f = (FileAnnotationData) data;
                String fileName = f.getFileName();
                String s = fileName;
                if (FileAnnotationData.MEASUREMENT_NS.equals(f.getNameSpace())) {
                    String desc = f.getDescription();
                    if (desc != null && desc.trim().length() > 0)
                        label.setText(desc);
                    else {
                        label.setText(UIUtilities.formatPartialName(EditorUtil.getPartialName(fileName)));
                    }
                    s = label.getText();
                } else {
                    label.setText(UIUtilities.formatPartialName(EditorUtil.getPartialName(fileName)));
                }

                label.setToolTipText(formatToolTip(f, s));
                Iterator<CustomizedFileFilter> i = FILTERS.iterator();
                CustomizedFileFilter filter;
                long id = f.getId();
                while (i.hasNext()) {
                    filter = i.next();
                    if (filter.accept(fileName)) {
                        if (id > 0)
                            imageToLoad = LOAD_FROM_SERVER;
                        else
                            imageToLoad = LOAD_FROM_LOCAL;
                        break;
                    }
                }
                if (id < 0)
                    label.setForeground(DataObjectListCellRenderer.NEW_FOREGROUND_COLOR);
                switch (imageToLoad) {
                case LOAD_FROM_LOCAL:
                    if (thumbnail == null)
                        setThumbnail(f.getFilePath());
                    break;
                /*
                case LOAD_FROM_SERVER:
                if (thumbnail == null) {
                 model.loadFile((FileAnnotationData) data, this);
                }
                */
                }
            } else if (data instanceof File) {
                File f = (File) data;
                label.setText(EditorUtil.getPartialName(f.getName()));
                label.setForeground(Color.BLUE);
            } else if (data instanceof TagAnnotationData) {
                TagAnnotationData tag = (TagAnnotationData) data;
                label.setText(tag.getTagValue());
                label.setToolTipText(formatToolTip(tag, null));
                if (tag.getId() < 0)
                    label.setForeground(DataObjectListCellRenderer.NEW_FOREGROUND_COLOR);
            } else if (data instanceof XMLAnnotationData) {
                XMLAnnotationData tag = (XMLAnnotationData) data;
                label.setText(EditorUtil.truncate(tag.getText(), TEXT_LENGTH, false));
                label.setToolTipText(formatToolTip(tag, null));
                if (tag.getId() < 0)
                    label.setForeground(DataObjectListCellRenderer.NEW_FOREGROUND_COLOR);
            } else if (data instanceof TermAnnotationData) {
                TermAnnotationData tag = (TermAnnotationData) data;
                label.setText(tag.getTerm());
                label.setToolTipText(formatToolTip(tag, null));
                if (tag.getId() < 0)
                    label.setForeground(DataObjectListCellRenderer.NEW_FOREGROUND_COLOR);
            } else if (data instanceof LongAnnotationData) {
                LongAnnotationData tag = (LongAnnotationData) data;
                label.setText(tag.getContentAsString());
                label.setToolTipText(formatToolTip(tag, null));
                if (tag.getId() < 0)
                    label.setForeground(DataObjectListCellRenderer.NEW_FOREGROUND_COLOR);
            } else if (data instanceof DoubleAnnotationData) {
                DoubleAnnotationData tag = (DoubleAnnotationData) data;
                label.setText(tag.getContentAsString());
                label.setToolTipText(formatToolTip(tag, null));
                if (tag.getId() < 0)
                    label.setForeground(DataObjectListCellRenderer.NEW_FOREGROUND_COLOR);
            }
        }

        label.addMouseListener(new MouseAdapter() {

            /** 
             * Posts an event to edit the file.
             * @see MouseAdapter#mouseReleased(MouseEvent)
             */
            public void mouseReleased(MouseEvent e) {
                if (e.getClickCount() == 1) {
                    if (e.isPopupTrigger())
                        showMenu(label, e.getPoint());
                } else if (e.getClickCount() == 2)
                    postFileClicked();
            }

            /** 
             * Shows menu
             * @see MouseAdapter#mouseReleased(MouseEvent)
             */
            public void mousePressed(MouseEvent e) {
                if (e.isPopupTrigger())
                    showMenu(label, e.getPoint());
            }
        });
    }

    /** Builds and lays out the UI. */
    private void buildGUI() {
        setBackground(UIUtilities.BACKGROUND_COLOR);
        setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
        add(label);
        JToolBar bar = new JToolBar();
        bar.setBackground(UIUtilities.BACKGROUND_COLOR);
        bar.setFloatable(false);
        bar.setRollover(true);
        bar.setBorder(null);
        bar.setOpaque(true);
        boolean b = setControlsEnabled(data != null);
        int count = 0;
        if (editButton != null)
            count++;
        if (unlinkButton != null)
            count++;
        if (downloadButton != null)
            count++;
        if (infoButton != null)
            count++;
        if (openButton != null)
            count++;
        if (count > 0 && data != null) {
            menuButton.setEnabled(true);
            if (model.isAcrossGroups())
                menuButton.setEnabled(false);
            bar.add(menuButton);
            if (!b)
                bar.add(Box.createHorizontalStrut(8));
            add(bar);
        }
    }

    /** Adds or edits the description of the tag. */
    private void editDescription() {
        if (!(data instanceof AnnotationData))
            return;
        String text = model.getAnnotationDescription((AnnotationData) data);
        originalDescription = text;
        SwingUtilities.convertPointToScreen(popupPoint, this);
        JFrame f = MetadataViewerAgent.getRegistry().getTaskBar().getFrame();
        int type = EditorDialog.EDIT_TYPE;
        if (isModulo)
            type = EditorDialog.VIEW_TYPE;
        EditorDialog d = new EditorDialog(f, (AnnotationData) data, false, type);
        if (isModulo)
            d.allowEdit(false);
        d.addPropertyChangeListener(this);
        d.setOriginalDescription(originalDescription);
        d.setSize(300, 250);
        UIUtilities.showOnScreen(d, popupPoint);
    }

    /** 
     * Brings up a dialog so that the user can select where to 
     * download the file.
     */
    private void download() {
        String name = null;
        if (data instanceof FileAnnotationData) {
            name = ((FileAnnotationData) data).getFileName();
        }
        JFrame f = EditorAgent.getRegistry().getTaskBar().getFrame();
        FileChooser chooser = new FileChooser(f, FileChooser.SAVE, "Download", "Select where to download the file.",
                null, true, true);
        if (StringUtils.isNotBlank(name))
            chooser.setSelectedFileFull(name);
        IconManager icons = IconManager.getInstance();
        chooser.setTitleIcon(icons.getIcon(IconManager.DOWNLOAD_48));
        chooser.setApproveButtonText("Download");
        chooser.addPropertyChangeListener(this);
        chooser.centerDialog();
    }

    /**
     * Creates a new instance,
     * 
     * @param data   The document annotation. 
     * @param model Reference to the model. Mustn't be <code>null</code>.
     * @param deletable Pass <code>false</code> to indicate that the document
     *               cannot be deleted regardless of the permissions,
     *               <code>true</code> otherwise.
     */
    DocComponent(Object data, EditorModel model, boolean deletable) {
        if (model == null)
            throw new IllegalArgumentException("No Model.");
        originalDescription = null;
        this.model = model;
        this.data = data;
        this.deletable = deletable;
        initComponents();
        buildGUI();
    }

    /**
     * Creates a new instance,
     * 
     * @param data   The document annotation. 
     * @param model Reference to the model. Mustn't be <code>null</code>.
     */
    DocComponent(Object data, EditorModel model) {
        this(data, model, true);
    }

    /**
     * Returns <code>true</code> if a thumbnail has to be loaded,
     * <code>false</code> otherwise.
     * 
     * @return See above.
     */
    boolean hasThumbnailToLoad() {
        return false;//(imageToLoad == LOAD_FROM_SERVER && thumbnail == null);
    }

    /**
     * Returns the object hosted by this component.
     * 
     * @return See above.
     */
    Object getData() {
        return data;
    }

    /**
     * Returns <code>true</code> if the description of the tag has been 
     * modified, <code>false</code> otherwise.
     * 
     * @return See above.
     */
    boolean hasBeenModified() {
        if (originalName == null)
            return false;
        if (data instanceof TagAnnotationData) {
            TagAnnotationData tag = (TagAnnotationData) data;
            if (!originalName.equals(tag.getTagValue()))
                return true;
            String txt = tag.getTagDescription();
            if (txt != null)
                return !(originalDescription.equals(txt));
            return false;
        }
        return false;
    }

    /**
     * Returns <code>true</code> if the image has been loaded, 
     * <code>false</code> otherwise.
     * 
     * @return See above.
     */
    boolean isImageLoaded() {
        return thumbnail != null;
    }

    /**
     * Returns <code>true</code> if the object can be unlinked,
     * <code>false</code> otherwise.
     * 
     * @return See above.
     */
    boolean canUnlink() {
        if (unlinkButton == null)
            return false;
        return unlinkButton.isVisible();
    }

    /**
     * Sets the image representing the file.
     * 
     * @param path The path to the file.
     */
    void setThumbnail(String path) {
        if (path == null)
            return;
        this.thumbnail = Factory.createIcon(path, Factory.THUMB_DEFAULT_WIDTH / 2,
                Factory.THUMB_DEFAULT_HEIGHT / 2);
        if (thumbnail != null) {
            label.setText("");
            label.setIcon(thumbnail);
            label.repaint();
            revalidate();
            repaint();
        }
    }

    /** 
     * Deletes or edits the annotation.
     * @see ActionListener#actionPerformed(ActionEvent)
     */
    public void actionPerformed(ActionEvent e) {
        int index = Integer.parseInt(e.getActionCommand());
        switch (index) {
        case REMOVE:
            firePropertyChange(AnnotationUI.REMOVE_ANNOTATION_PROPERTY, null, this);
            break;
        case EDIT:
            editDescription();
            break;
        case DOWNLOAD:
            download();
            break;
        case OPEN:
            openFile();
            break;
        }
    }

    /**
     * Listens to property fired by the Editor dialog.
     * @see PropertyChangeListener#propertyChange(PropertyChangeEvent)
     */
    public void propertyChange(PropertyChangeEvent evt) {
        String name = evt.getPropertyName();
        if (EditorDialog.CREATE_NO_PARENT_PROPERTY.equals(name)) {
            //reset text and tooltip
            String text = "";
            String description = "";
            AnnotationData annotation = null;
            if (data instanceof TagAnnotationData || data instanceof TermAnnotationData
                    || data instanceof XMLAnnotationData) {
                annotation = (AnnotationData) data;
                text = annotation.getContentAsString();
            }
            description = model.getAnnotationDescription(annotation);
            if (annotation == null)
                return;
            label.setText(text);
            label.setToolTipText(formatToolTip(annotation, null));
            originalName = text;
            originalDescription = description;
            firePropertyChange(AnnotationUI.EDIT_TAG_PROPERTY, null, this);
        } else if (FileChooser.APPROVE_SELECTION_PROPERTY.equals(name)) {
            if (data == null)
                return;
            FileAnnotationData fa = (FileAnnotationData) data;
            OriginalFile f = (OriginalFile) fa.getContent();
            File folder;
            Object o = evt.getNewValue();
            if (o instanceof String) {
                String path = (String) o;
                if (!path.endsWith(File.separator)) {
                    path += File.separator;
                }
                path += fa.getFileName();
                folder = new File(path);
            } else {
                File[] files = (File[]) o;
                folder = files[0];
            }
            if (folder == null)
                folder = UIUtilities.getDefaultFolder();
            UserNotifier un = EditorAgent.getRegistry().getUserNotifier();

            IconManager icons = IconManager.getInstance();

            DownloadActivityParam activity = new DownloadActivityParam(f, folder,
                    icons.getIcon(IconManager.DOWNLOAD_22));
            //Check Name space
            activity.setLegend(fa.getDescription());
            un.notifyActivity(model.getSecurityContext(), activity);
        }
    }

}