org.pdfsam.guiclient.commons.panels.JVisualPdfPageSelectionPanel.java Source code

Java tutorial

Introduction

Here is the source code for org.pdfsam.guiclient.commons.panels.JVisualPdfPageSelectionPanel.java

Source

/*
 * Created on 18-Jun-2008
 * Copyright (C) 2008 by Andrea Vacondio.
 *
 * 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.
 * 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., 
 *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
package org.pdfsam.guiclient.commons.panels;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DropMode;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.pdfsam.console.business.dto.commands.ConcatParsedCommand;
import org.pdfsam.guiclient.business.PagePreviewOpener;
import org.pdfsam.guiclient.business.PagesWorker;
import org.pdfsam.guiclient.business.listeners.EnterDoClickListener;
import org.pdfsam.guiclient.commons.business.listeners.VisualPdfSelectionActionListener;
import org.pdfsam.guiclient.commons.business.listeners.adapters.PageOpenerMouseAdapter;
import org.pdfsam.guiclient.commons.business.listeners.adapters.VisualPdfSelectionKeyAdapter;
import org.pdfsam.guiclient.commons.business.listeners.adapters.VisualPdfSelectionMouseAdapter;
import org.pdfsam.guiclient.commons.business.listeners.mediators.PagesActionsMediator;
import org.pdfsam.guiclient.commons.business.loaders.PdfThumbnailsLoader;
import org.pdfsam.guiclient.commons.components.JVisualSelectionList;
import org.pdfsam.guiclient.commons.dnd.handlers.VisualListExportTransferHandler;
import org.pdfsam.guiclient.commons.dnd.handlers.VisualListTransferHandler;
import org.pdfsam.guiclient.commons.models.VisualListModel;
import org.pdfsam.guiclient.commons.renderers.VisualListRenderer;
import org.pdfsam.guiclient.configuration.Configuration;
import org.pdfsam.guiclient.dto.DocumentInfo;
import org.pdfsam.guiclient.dto.Rotation;
import org.pdfsam.guiclient.dto.VisualPageListItem;
import org.pdfsam.guiclient.dto.VisualSelectedItem;
import org.pdfsam.i18n.GettextResource;

/**
 * Customizable panel for a visual page selection
 * @author Andrea Vacondio
 *
 */
public class JVisualPdfPageSelectionPanel extends JPanel {

    private static final long serialVersionUID = 1384691784810385438L;

    private static final Logger log = Logger.getLogger(JVisualPdfPageSelectionPanel.class.getPackage().getName());

    public static final int HORIZONTAL_ORIENTATION = 1;
    public static final int VERTICAL_ORIENTATION = 2;

    public static final int SINGLE_INTERVAL_SELECTION = ListSelectionModel.SINGLE_INTERVAL_SELECTION;
    public static final int MULTIPLE_INTERVAL_SELECTION = ListSelectionModel.MULTIPLE_INTERVAL_SELECTION;
    public static final int SINGLE_SELECTION = ListSelectionModel.SINGLE_SELECTION;

    public static final int STYLE_TOP_PANEL_HIDE = 0;
    public static final int STYLE_TOP_PANEL_MINIMAL = 1;
    public static final int STYLE_TOP_PANEL_MEDIUM = 2;
    public static final int STYLE_TOP_PANEL_FULL = 3;

    public static final int DND_SUPPORT_NONE = 0;
    public static final int DND_SUPPORT_FILES = 1;
    public static final int DND_SUPPORT_JAVAOBJECTS = 2;
    public static final int DND_SUPPORT_FILES_AND_JAVAOBJECTS = 3;

    public static final String OUTPUT_PATH_PROPERTY = "defaultOutputPath";

    private int orientation = HORIZONTAL_ORIENTATION;
    private File selectedPdfDocument = null;
    private String selectedPdfDocumentPassword = "";
    private boolean showButtonPanel = true;
    private int topPanelStyle = STYLE_TOP_PANEL_FULL;
    private boolean showContextMenu = true;
    private int dndSupport = DND_SUPPORT_NONE;
    private int selectionType = SINGLE_INTERVAL_SELECTION;
    private final JMenuItem menuItemSetOutputPath = new JMenuItem();
    /**
     * if true, deleted items appear with a red cross over 
     */
    private boolean drawDeletedItems = true;
    //if the JList uses wrap
    private boolean wrap = false;

    private Configuration config;
    private PagesWorker pagesWorker;
    //menu
    private final JButton loadFileButton = new JButton();
    private final JButton clearButton = new JButton();
    private final JButton zoomInButton = new JButton();
    private final JButton zoomOutButton = new JButton();

    private final JLabel documentProperties = new JLabel();
    private final JVisualSelectionList thumbnailList = new JVisualSelectionList();
    private PdfThumbnailsLoader pdfLoader;
    private VisualPdfSelectionActionListener pdfSelectionActionListener;
    private PagesActionsMediator pageActionListener;
    private final JPopupMenu popupMenu = new JPopupMenu();
    private final JMenuItem menuItemPreview = new JMenuItem();
    private final JPanel topPanel = new JPanel();

    //button panel
    private JPanel buttonPanel;
    private JButton undeleteButton;
    private JButton removeButton;
    private JButton moveUpButton;
    private JButton moveDownButton;
    private JButton rotateButton;
    private JButton rotateAntiButton;
    private JButton reverseButton;

    /**
     * default constructor
     */
    public JVisualPdfPageSelectionPanel() {
        this(HORIZONTAL_ORIENTATION);
    }

    /**
     * draw deleted items default value (true)
     * show button panel default value (true)
     * @param orientation panel orientation
     */
    public JVisualPdfPageSelectionPanel(int orientation) {
        this(orientation, true, true);
    }

    /**
     * @param orientation panel orientation
     * @param drawDeletedItems if true deleted items appear with a red cross over 
     * @param showButtonPanel true=shows button panel
     */
    public JVisualPdfPageSelectionPanel(int orientation, boolean drawDeletedItems, boolean showButtonPanel) {
        this(orientation, drawDeletedItems, showButtonPanel, true, STYLE_TOP_PANEL_FULL);
    }

    /**
     * 
     * @param orientation panel orientation
     * @param drawDeletedItems if true deleted items appear with a red cross over 
     * @param showButtonPanel true=shows button panel
     * @param showContextMenu
     * @param topPanelStyle
     */
    public JVisualPdfPageSelectionPanel(int orientation, boolean drawDeletedItems, boolean showButtonPanel,
            boolean showContextMenu, int topPanelStyle) {
        this(orientation, drawDeletedItems, showButtonPanel, showContextMenu, topPanelStyle,
                DND_SUPPORT_FILES_AND_JAVAOBJECTS, SINGLE_INTERVAL_SELECTION);
    }

    /**
     * 
     * @param orientation panel orientation
     * @param drawDeletedItems if true deleted items appear with a red cross over 
     * @param showButtonPanel true=shows button panel
     * @param showContextMenu
     * @param topPanelStyle top panel style
     * @param selectionType selection type
     */
    public JVisualPdfPageSelectionPanel(int orientation, boolean drawDeletedItems, boolean showButtonPanel,
            boolean showContextMenu, int topPanelStyle, int dndSupport, int selectionType) {
        this.orientation = orientation;
        this.config = Configuration.getInstance();
        this.pdfLoader = new PdfThumbnailsLoader(this);
        this.drawDeletedItems = drawDeletedItems;
        this.showButtonPanel = showButtonPanel;
        this.showContextMenu = showContextMenu;
        this.topPanelStyle = topPanelStyle;
        this.dndSupport = dndSupport;
        this.selectionType = selectionType;
        init();
    }

    /**
     * panel initialization
     */
    private void init() {
        setLayout(new GridBagLayout());

        thumbnailList.setDrawDeletedItems(drawDeletedItems);
        if (dndSupport == DND_SUPPORT_FILES) {
            thumbnailList.setTransferHandler(new VisualListExportTransferHandler(pdfLoader));
        } else if (dndSupport == DND_SUPPORT_JAVAOBJECTS) {
            thumbnailList.setTransferHandler(new VisualListTransferHandler());
        } else if (dndSupport == DND_SUPPORT_FILES_AND_JAVAOBJECTS) {
            thumbnailList.setTransferHandler(new VisualListTransferHandler(pdfLoader));
        } else {
            thumbnailList.setTransferHandler(new VisualListExportTransferHandler(null));
        }
        thumbnailList.setDragEnabled(true);
        thumbnailList.setDropMode(DropMode.INSERT);
        pagesWorker = new PagesWorker(thumbnailList);
        thumbnailList.addKeyListener(new VisualPdfSelectionKeyAdapter(pagesWorker));
        thumbnailList.addMouseListener(new PageOpenerMouseAdapter(thumbnailList));

        if (showButtonPanel) {
            initButtonPanel(pagesWorker);
            initKeyListener();
        }

        //JList orientation
        if (HORIZONTAL_ORIENTATION == orientation) {
            thumbnailList.setLayoutOrientation(JList.HORIZONTAL_WRAP);
        } else {
            if (wrap) {
                thumbnailList.setLayoutOrientation(JList.VERTICAL_WRAP);
            }
        }

        topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.LINE_AXIS));
        topPanel.setPreferredSize(new Dimension(400, 30));

        pdfSelectionActionListener = new VisualPdfSelectionActionListener(this, pdfLoader);
        if (topPanelStyle >= STYLE_TOP_PANEL_FULL) {
            //load button
            loadFileButton.setMargin(new Insets(1, 1, 1, 1));
            loadFileButton.setText(GettextResource.gettext(config.getI18nResourceBundle(), "Open"));
            loadFileButton.setPreferredSize(new Dimension(100, 30));
            loadFileButton
                    .setToolTipText(GettextResource.gettext(config.getI18nResourceBundle(), "Load a pdf document"));
            loadFileButton.setIcon(new ImageIcon(this.getClass().getResource("/images/add.png")));
            loadFileButton.addKeyListener(new EnterDoClickListener(loadFileButton));
            loadFileButton.setAlignmentX(Component.CENTER_ALIGNMENT);
            loadFileButton.setAlignmentY(Component.CENTER_ALIGNMENT);
            loadFileButton.setActionCommand(VisualPdfSelectionActionListener.ADD);
            loadFileButton.addActionListener(pdfSelectionActionListener);
        }
        documentProperties.setIcon(new ImageIcon(this.getClass().getResource("/images/info.png")));
        documentProperties.setVisible(false);

        if (topPanelStyle >= STYLE_TOP_PANEL_MEDIUM) {
            clearButton.setMargin(new Insets(1, 1, 1, 1));
            clearButton.setMinimumSize(new Dimension(30, 30));
            clearButton.setText(GettextResource.gettext(config.getI18nResourceBundle(), "Clear"));
            clearButton.setIcon(new ImageIcon(this.getClass().getResource("/images/clear.png")));
            clearButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    resetPanel();
                }
            });
        }

        zoomInButton.setMargin(new Insets(1, 1, 1, 1));
        zoomInButton.setMinimumSize(new Dimension(30, 30));
        zoomInButton.setText(GettextResource.gettext(config.getI18nResourceBundle(), "Zoom in"));
        zoomInButton.setIcon(new ImageIcon(this.getClass().getResource("/images/zoomin.png")));
        zoomInButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {
                    thumbnailList.incZoomLevel();
                    zoomOutButton.setEnabled(true);
                    if (thumbnailList.getCurrentZoomLevel() >= JVisualSelectionList.MAX_ZOOM_LEVEL) {
                        zoomInButton.setEnabled(false);
                    }
                    ((VisualListModel) thumbnailList.getModel()).elementsChanged();
                } catch (Exception ex) {
                    log.error(GettextResource.gettext(config.getI18nResourceBundle(), "Error setting zoom level."),
                            ex);
                }
            }
        });

        zoomOutButton.setMargin(new Insets(1, 1, 1, 1));
        zoomOutButton.setMinimumSize(new Dimension(30, 30));
        zoomOutButton.setText(GettextResource.gettext(config.getI18nResourceBundle(), "Zoom out"));
        zoomOutButton.setIcon(new ImageIcon(this.getClass().getResource("/images/zoomout.png")));
        zoomOutButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {
                    thumbnailList.deincZoomLevel();
                    zoomInButton.setEnabled(true);
                    if (thumbnailList.getCurrentZoomLevel() <= JVisualSelectionList.MIN_ZOOM_LEVEL) {
                        zoomOutButton.setEnabled(false);
                    }
                    ((VisualListModel) thumbnailList.getModel()).elementsChanged();
                } catch (Exception ex) {
                    log.error(GettextResource.gettext(config.getI18nResourceBundle(), "Error setting zoom level."),
                            ex);
                }
            }
        });

        thumbnailList.setModel(new VisualListModel());
        thumbnailList.setCellRenderer(new VisualListRenderer());
        thumbnailList.setVisibleRowCount(-1);
        thumbnailList.setSelectionMode(selectionType);
        JScrollPane listScroller = new JScrollPane(thumbnailList);

        //preview item   
        menuItemPreview.setIcon(new ImageIcon(this.getClass().getResource("/images/preview-viewer.png")));
        menuItemPreview.setText(GettextResource.gettext(config.getI18nResourceBundle(), "Preview"));
        menuItemPreview.addMouseListener(new MouseAdapter() {
            public void mouseReleased(MouseEvent e) {
                int[] selection = thumbnailList.getSelectedIndices();
                if (selection != null && selection.length == 1) {
                    VisualPageListItem item = (VisualPageListItem) thumbnailList.getModel()
                            .getElementAt(selection[0]);
                    PagePreviewOpener.getInstance().openPreview(item.getParentFileCanonicalPath(),
                            item.getDocumentPassword(), item.getPageNumber());
                }
            }
        });

        if (showContextMenu) {
            //popup
            final JMenuItem menuItemMoveUp = new JMenuItem();
            menuItemMoveUp.setIcon(new ImageIcon(this.getClass().getResource("/images/up.png")));
            menuItemMoveUp.setText(GettextResource.gettext(config.getI18nResourceBundle(), "Move Up"));
            menuItemMoveUp.addMouseListener(new VisualPdfSelectionMouseAdapter(PagesWorker.MOVE_UP, pagesWorker));
            popupMenu.add(menuItemMoveUp);

            final JMenuItem menuItemMoveDown = new JMenuItem();
            menuItemMoveDown.setIcon(new ImageIcon(this.getClass().getResource("/images/down.png")));
            menuItemMoveDown.setText(GettextResource.gettext(config.getI18nResourceBundle(), "Move Down"));
            menuItemMoveDown
                    .addMouseListener(new VisualPdfSelectionMouseAdapter(PagesWorker.MOVE_DOWN, pagesWorker));
            popupMenu.add(menuItemMoveDown);

            final JMenuItem menuItemRemove = new JMenuItem();
            menuItemRemove.setIcon(new ImageIcon(this.getClass().getResource("/images/remove.png")));
            menuItemRemove.setText(GettextResource.gettext(config.getI18nResourceBundle(), "Delete"));
            menuItemRemove.addMouseListener(new VisualPdfSelectionMouseAdapter(PagesWorker.REMOVE, pagesWorker));
            popupMenu.add(menuItemRemove);

            //if elements are physically deleted i don't need this item
            if (drawDeletedItems) {
                final JMenuItem menuItemUndelete = new JMenuItem();
                menuItemUndelete.setIcon(new ImageIcon(this.getClass().getResource("/images/remove.png")));
                menuItemUndelete.setText(GettextResource.gettext(config.getI18nResourceBundle(), "Undelete"));
                menuItemUndelete
                        .addMouseListener(new VisualPdfSelectionMouseAdapter(PagesWorker.UNDELETE, pagesWorker));
                popupMenu.add(menuItemUndelete);
            }

            //rotate item   
            final JMenuItem menuItemRotate = new JMenuItem();
            menuItemRotate.setIcon(new ImageIcon(this.getClass().getResource("/images/clockwise.png")));
            menuItemRotate.setText(GettextResource.gettext(config.getI18nResourceBundle(), "Rotate clockwise"));
            menuItemRotate
                    .addMouseListener(new VisualPdfSelectionMouseAdapter(PagesWorker.ROTATE_CLOCK, pagesWorker));
            popupMenu.add(menuItemRotate);

            //rotate anticlock item   
            final JMenuItem menuItemAntiRotate = new JMenuItem();
            menuItemAntiRotate.setIcon(new ImageIcon(this.getClass().getResource("/images/anticlockwise.png")));
            menuItemAntiRotate
                    .setText(GettextResource.gettext(config.getI18nResourceBundle(), "Rotate anticlockwise"));
            menuItemAntiRotate.addMouseListener(
                    new VisualPdfSelectionMouseAdapter(PagesWorker.ROTATE_ANTICLOCK, pagesWorker));
            popupMenu.add(menuItemAntiRotate);

            //reverse item   
            final JMenuItem menuItemReverse = new JMenuItem();
            menuItemReverse.setIcon(new ImageIcon(this.getClass().getResource("/images/reverse.png")));
            menuItemReverse.setText(GettextResource.gettext(config.getI18nResourceBundle(), "Reverse"));
            menuItemReverse.addMouseListener(new VisualPdfSelectionMouseAdapter(PagesWorker.REVERSE, pagesWorker));
            popupMenu.add(menuItemReverse);

            enableSetOutputPathMenuItem();

            addPopupShower();
        }

        popupMenu.add(menuItemPreview);

        if (topPanelStyle >= STYLE_TOP_PANEL_FULL) {
            topPanel.add(Box.createRigidArea(new Dimension(5, 0)));
            topPanel.add(loadFileButton);
        }
        if (topPanelStyle >= STYLE_TOP_PANEL_MEDIUM) {
            topPanel.add(Box.createRigidArea(new Dimension(5, 0)));
            topPanel.add(clearButton);
        }
        topPanel.add(Box.createRigidArea(new Dimension(5, 0)));
        topPanel.add(documentProperties);
        topPanel.add(Box.createHorizontalGlue());
        topPanel.add(zoomInButton);
        topPanel.add(Box.createRigidArea(new Dimension(5, 0)));
        topPanel.add(zoomOutButton);

        GridBagConstraints topConstraints = new GridBagConstraints();
        topConstraints.fill = GridBagConstraints.BOTH;
        topConstraints.gridx = 0;
        topConstraints.gridy = 0;
        topConstraints.gridwidth = 3;
        topConstraints.gridheight = 1;
        topConstraints.insets = new Insets(5, 5, 5, 5);
        topConstraints.weightx = 1.0;
        topConstraints.weighty = 0.0;
        if (topPanelStyle > STYLE_TOP_PANEL_HIDE) {
            add(topPanel, topConstraints);
        }

        GridBagConstraints thumbConstraints = new GridBagConstraints();
        thumbConstraints.fill = GridBagConstraints.BOTH;
        thumbConstraints.gridx = 0;
        thumbConstraints.gridy = 1;
        thumbConstraints.gridwidth = (showButtonPanel ? 2 : 3);
        thumbConstraints.gridheight = 2;
        thumbConstraints.insets = new Insets(5, 5, 5, 5);
        thumbConstraints.weightx = 1.0;
        thumbConstraints.weighty = 1.0;
        add(listScroller, thumbConstraints);

        if (showButtonPanel) {
            GridBagConstraints buttonsConstraints = new GridBagConstraints();
            buttonsConstraints.fill = GridBagConstraints.BOTH;
            buttonsConstraints.gridx = 2;
            buttonsConstraints.gridy = 1;
            buttonsConstraints.gridwidth = 1;
            buttonsConstraints.gridheight = 2;
            buttonsConstraints.insets = new Insets(5, 5, 5, 5);
            buttonsConstraints.weightx = 0.0;
            buttonsConstraints.weighty = 1.0;
            add(buttonPanel, buttonsConstraints);
        }
    }

    /**
      * adds a button to the button panel
      * @param button
      */
    private void addButtonToButtonPanel(JButton button) {
        button.setMinimumSize(new Dimension(90, 25));
        button.setMaximumSize(new Dimension(160, 25));
        buttonPanel.add(button);
        buttonPanel.add(Box.createRigidArea(new Dimension(0, 5)));
    }

    private void initButtonPanel(PagesWorker pagesWorker) {
        buttonPanel = new JPanel();
        buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));
        buttonPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));

        pageActionListener = new PagesActionsMediator(pagesWorker);

        //move up button
        moveUpButton = new JButton();
        moveUpButton.setMargin(new Insets(2, 2, 2, 2));
        moveUpButton.addActionListener(pageActionListener);
        moveUpButton.setIcon(new ImageIcon(this.getClass().getResource("/images/up.png")));
        moveUpButton.setActionCommand(PagesWorker.MOVE_UP);
        moveUpButton.setText(GettextResource.gettext(config.getI18nResourceBundle(), "Move Up"));
        moveUpButton
                .setToolTipText(GettextResource.gettext(config.getI18nResourceBundle(), "Move up selected pages")
                        + " " + GettextResource.gettext(config.getI18nResourceBundle(), "(Alt+ArrowUp)"));
        moveUpButton.addKeyListener(new EnterDoClickListener(moveUpButton));
        moveUpButton.setAlignmentX(Component.CENTER_ALIGNMENT);
        addButtonToButtonPanel(moveUpButton);

        //move down button
        moveDownButton = new JButton();
        moveDownButton.addActionListener(pageActionListener);
        moveDownButton.setIcon(new ImageIcon(this.getClass().getResource("/images/down.png")));
        moveDownButton.setActionCommand(PagesWorker.MOVE_DOWN);
        moveDownButton.setMargin(new Insets(2, 2, 2, 2));
        moveDownButton.setText(GettextResource.gettext(config.getI18nResourceBundle(), "Move Down"));
        moveDownButton
                .setToolTipText(GettextResource.gettext(config.getI18nResourceBundle(), "Move down selected pages")
                        + " " + GettextResource.gettext(config.getI18nResourceBundle(), "(Alt+ArrowDown)"));
        moveDownButton.addKeyListener(new EnterDoClickListener(moveDownButton));
        moveDownButton.setAlignmentX(Component.CENTER_ALIGNMENT);
        addButtonToButtonPanel(moveDownButton);

        //delete button
        removeButton = new JButton();
        removeButton.addActionListener(pageActionListener);
        removeButton.setIcon(new ImageIcon(this.getClass().getResource("/images/remove.png")));
        removeButton.setActionCommand(PagesWorker.REMOVE);
        removeButton.setMargin(new Insets(2, 2, 2, 2));
        removeButton.setText(GettextResource.gettext(config.getI18nResourceBundle(), "Delete"));
        removeButton.setToolTipText(GettextResource.gettext(config.getI18nResourceBundle(), "Delete selected pages")
                + " " + GettextResource.gettext(config.getI18nResourceBundle(), "(Canc)"));
        removeButton.addKeyListener(new EnterDoClickListener(removeButton));
        removeButton.setAlignmentX(Component.CENTER_ALIGNMENT);
        addButtonToButtonPanel(removeButton);

        //undelete button
        if (drawDeletedItems) {
            undeleteButton = new JButton();
            undeleteButton.addActionListener(pageActionListener);
            undeleteButton.setIcon(new ImageIcon(this.getClass().getResource("/images/remove.png")));
            undeleteButton.setActionCommand(PagesWorker.UNDELETE);
            undeleteButton.setMargin(new Insets(2, 2, 2, 2));
            undeleteButton.setText(GettextResource.gettext(config.getI18nResourceBundle(), "Undelete"));
            undeleteButton.setToolTipText(
                    GettextResource.gettext(config.getI18nResourceBundle(), "Undelete selected pages") + " "
                            + GettextResource.gettext(config.getI18nResourceBundle(), "(Ctrl+Z)"));
            undeleteButton.addKeyListener(new EnterDoClickListener(undeleteButton));
            undeleteButton.setAlignmentX(Component.CENTER_ALIGNMENT);
            addButtonToButtonPanel(undeleteButton);
        }

        //rotate button
        rotateButton = new JButton();
        rotateButton.addActionListener(pageActionListener);
        rotateButton.setIcon(new ImageIcon(this.getClass().getResource("/images/clockwise.png")));
        rotateButton.setActionCommand(PagesWorker.ROTATE_CLOCK);
        rotateButton.setMargin(new Insets(2, 2, 2, 2));
        rotateButton.setText(GettextResource.gettext(config.getI18nResourceBundle(), "Rotate right"));
        rotateButton.setToolTipText(
                GettextResource.gettext(config.getI18nResourceBundle(), "Rotate clockwise selected pages") + " "
                        + GettextResource.gettext(config.getI18nResourceBundle(), "(Alt+ArrowRight)"));
        rotateButton.addKeyListener(new EnterDoClickListener(rotateButton));
        rotateButton.setAlignmentX(Component.CENTER_ALIGNMENT);
        addButtonToButtonPanel(rotateButton);

        //rotate button
        rotateAntiButton = new JButton();
        rotateAntiButton.addActionListener(pageActionListener);
        rotateAntiButton.setIcon(new ImageIcon(this.getClass().getResource("/images/anticlockwise.png")));
        rotateAntiButton.setActionCommand(PagesWorker.ROTATE_ANTICLOCK);
        rotateAntiButton.setMargin(new Insets(2, 2, 2, 2));
        rotateAntiButton.setText(GettextResource.gettext(config.getI18nResourceBundle(), "Rotate left"));
        rotateAntiButton.setToolTipText(
                GettextResource.gettext(config.getI18nResourceBundle(), "Rotate anticlockwise selected pages") + " "
                        + GettextResource.gettext(config.getI18nResourceBundle(), "(Alt+ArrowLeft)"));
        rotateAntiButton.addKeyListener(new EnterDoClickListener(rotateAntiButton));
        rotateAntiButton.setAlignmentX(Component.CENTER_ALIGNMENT);
        addButtonToButtonPanel(rotateAntiButton);

        //reverse button
        reverseButton = new JButton();
        reverseButton.addActionListener(pageActionListener);
        reverseButton.setIcon(new ImageIcon(this.getClass().getResource("/images/reverse.png")));
        reverseButton.setActionCommand(PagesWorker.REVERSE);
        reverseButton.setMargin(new Insets(2, 2, 2, 2));
        reverseButton.setText(GettextResource.gettext(config.getI18nResourceBundle(), "Reverse"));
        reverseButton
                .setToolTipText(GettextResource.gettext(config.getI18nResourceBundle(), "Reverse pages order"));
        reverseButton.addKeyListener(new EnterDoClickListener(reverseButton));
        reverseButton.setAlignmentX(Component.CENTER_ALIGNMENT);
        addButtonToButtonPanel(reverseButton);
    }

    private void initKeyListener() {
        //key listener
        thumbnailList.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                if ((e.isAltDown()) && (e.getKeyCode() == KeyEvent.VK_UP)) {
                    moveUpButton.doClick();
                } else if ((e.isAltDown()) && (e.getKeyCode() == KeyEvent.VK_DOWN)) {
                    moveDownButton.doClick();
                } else if ((e.getKeyCode() == KeyEvent.VK_DELETE)) {
                    removeButton.doClick();
                } else if (drawDeletedItems && (e.isControlDown()) && (e.getKeyCode() == KeyEvent.VK_Z)) {
                    undeleteButton.doClick();
                } else if ((e.isAltDown()) && (e.getKeyCode() == KeyEvent.VK_RIGHT)) {
                    rotateButton.doClick();
                } else if ((e.isAltDown()) && (e.getKeyCode() == KeyEvent.VK_LEFT)) {
                    rotateAntiButton.doClick();
                }
            }
        });
    }

    /**
     * reset the panel
     */
    public void resetPanel() {
        thumbnailList.setCurrentZoomLevel(JVisualSelectionList.DEFAULT_ZOOM_LEVEL);
        zoomInButton.setEnabled(true);
        zoomOutButton.setEnabled(true);
        ((VisualListModel) thumbnailList.getModel()).clearData();
        selectedPdfDocument = null;
        selectedPdfDocumentPassword = "";
        setDocumentPropertiesVisible(false);
        getPdfLoader().cleanCreator();

    }

    /**
     * Set the visible the label that shows document properties
     * @param visible
     */
    public void setDocumentPropertiesVisible(boolean visible) {
        documentProperties.setVisible(visible);
    }

    /**
     * Set the document properties to be shown as a tooltip of the documentProperties JLabel
     * @param documetnInfo bean containing document informations
     */

    public void setDocumentProperties(DocumentInfo documetnInfo) {
        if (documetnInfo != null) {
            String encrypted = documetnInfo.isEncrypted()
                    ? GettextResource.gettext(config.getI18nResourceBundle(), "Yes")
                    : GettextResource.gettext(config.getI18nResourceBundle(), "No");
            documentProperties.setToolTipText("<html><body><b><p>"
                    + GettextResource.gettext(config.getI18nResourceBundle(), "File: ") + "</b>"
                    + documetnInfo.getFileName() + "</p>" + "<p><b>"
                    + GettextResource.gettext(config.getI18nResourceBundle(), "Pages: ") + "</b>"
                    + documetnInfo.getPages() + "</p>" + "<p><b>"
                    + GettextResource.gettext(config.getI18nResourceBundle(), "Pdf version: ") + "</b>"
                    + (documetnInfo.getPdfVersion() != null ? documetnInfo.getPdfVersion() : "") + "</p>" + "<p><b>"
                    + GettextResource.gettext(config.getI18nResourceBundle(), "Title: ") + "</b>"
                    + StringUtils.trimToEmpty(documetnInfo.getDocumentMetaData().getTitle()) + "</p>" + "<p><b>"
                    + GettextResource.gettext(config.getI18nResourceBundle(), "Author: ") + "</b>"
                    + StringUtils.trimToEmpty(documetnInfo.getDocumentMetaData().getAuthor()) + "</p>" + "<p><b>"
                    + GettextResource.gettext(config.getI18nResourceBundle(), "Creator: ") + "</b>"
                    + StringUtils.trimToEmpty(documetnInfo.getDocumentMetaData().getCreator()) + "</p>" + "<p><b>"
                    + GettextResource.gettext(config.getI18nResourceBundle(), "Producer: ") + "</b>"
                    + StringUtils.trimToEmpty(documetnInfo.getDocumentMetaData().getProducer()) + "</p>" + "<p><b>"
                    + GettextResource.gettext(config.getI18nResourceBundle(), "Encrypted: ") + "</b>" + encrypted
                    + "</p>" + "</body></html>");
        }

    }

    /**
     * @return the orientation
     */
    public int getOrientation() {
        return orientation;
    }

    /**
     * @return the selectedPdfDocument
     */
    public File getSelectedPdfDocument() {
        return selectedPdfDocument;
    }

    /**
     * @return the wrap
     */
    public boolean isWrap() {
        return wrap;
    }

    /**
     * @return the thumbnailList
     */
    public JVisualSelectionList getThumbnailList() {
        return thumbnailList;
    }

    /**
     * @param selectedPdfDocument the selectedPdfDocument to set
     */
    public void setSelectedPdfDocument(File selectedPdfDocument) {
        this.selectedPdfDocument = selectedPdfDocument;
    }

    /**
     * @return the dndSupport
     */
    public int getDndSupport() {
        return dndSupport;
    }

    /**
     * @return the drawDeletedItems
     */
    public boolean isDrawDeletedItems() {
        return drawDeletedItems;
    }

    /**
     * @param drawDeletedItems the drawDeletedItems to set
     */
    public void setDrawDeletedItems(boolean drawDeletedItems) {
        this.drawDeletedItems = drawDeletedItems;
    }

    /**
     * @return the pdfLoader
     */
    public PdfThumbnailsLoader getPdfLoader() {
        return pdfLoader;
    }

    /**
     * @return the topPanel
     */
    public JPanel getTopPanel() {
        return topPanel;
    }

    /**
     * @param pages input selection set
     * @return a String version of the input Set, ready to be used as -u parameter for the console
     */
    private String getSelectionString(Set<Integer> pages) {
        StringBuilder buffer = new StringBuilder();
        for (Integer page : pages) {
            buffer.append(page.toString()).append(",");
        }
        return StringUtils.chomp(buffer.toString(), ",");
    }

    /**
     * 
     * @return an ordered List of {@link VisualSelectedItem} corresponding to the panel elements.
     */
    private List<VisualSelectedItem> getSelectedItemsList() {
        List<VisualSelectedItem> retVal = new ArrayList<VisualSelectedItem>();
        List<VisualPageListItem> validElements = ((VisualListModel) thumbnailList.getModel()).getValidElements();
        VisualSelectedItem tmpElement = null;
        Set<Integer> pages = new LinkedHashSet<Integer>();
        for (VisualPageListItem currentElement : validElements) {
            //first element
            if (tmpElement == null) {
                tmpElement = new VisualSelectedItem(currentElement.getParentFileCanonicalPath(),
                        currentElement.getDocumentPassword());
                pages.add(currentElement.getPageNumber());
            } else {
                //filename changed
                if (!tmpElement.getSelectedFile().equals(currentElement.getParentFileCanonicalPath())) {
                    tmpElement.setPagesSelection(getSelectionString(pages));
                    retVal.add(tmpElement);
                    tmpElement = new VisualSelectedItem(currentElement.getParentFileCanonicalPath(),
                            currentElement.getDocumentPassword());
                    pages.clear();
                    pages.add(currentElement.getPageNumber());
                } else {
                    //page already there
                    if (!pages.add(currentElement.getPageNumber())) {
                        tmpElement.setPagesSelection(getSelectionString(pages));
                        retVal.add(tmpElement);
                        tmpElement = new VisualSelectedItem(currentElement.getParentFileCanonicalPath(),
                                currentElement.getDocumentPassword());
                        pages.clear();
                        pages.add(currentElement.getPageNumber());
                    }
                }
            }
        }
        tmpElement.setPagesSelection(getSelectionString(pages));
        retVal.add(tmpElement);
        return retVal;
    }

    /**
     * A of String List that can be used as input for the console. It contains the -f and -u parameters for this panel
     * @return
     */
    public List<String> getValidConsoleParameters() {
        List<String> retVal = new ArrayList<String>();
        StringBuilder builder = new StringBuilder();
        for (VisualSelectedItem item : getSelectedItemsList()) {
            builder.append(item.getPagesSelection()).append(":");
            retVal.add("-" + ConcatParsedCommand.F_ARG);
            if (StringUtils.isEmpty(item.getPassword())) {
                retVal.add(item.getSelectedFile());
            } else {
                retVal.add(item.getSelectedFile() + ":" + item.getPassword());
            }
        }
        retVal.add("-" + ConcatParsedCommand.U_ARG);
        retVal.add(builder.toString());
        return retVal;
    }

    /**
     * 
     * @return true if the panel has valid elements
     */
    public boolean hasValidElements() {
        List<VisualPageListItem> elements = ((VisualListModel) thumbnailList.getModel()).getValidElements();
        return (elements != null && !elements.isEmpty());
    }

    /**
     * @return a String that can be used as a -r param for the pdfsam-console
     */
    public String getRotatedElementsString() {
        StringBuilder retVal = new StringBuilder();
        Collection<VisualPageListItem> validElements = ((VisualListModel) thumbnailList.getModel())
                .getValidElements();
        if (validElements != null && !validElements.isEmpty()) {
            int i = 0;
            for (VisualPageListItem currentElement : validElements) {
                i++;
                if (!Rotation.DEGREES_0.equals(currentElement.getRotation())) {
                    retVal.append(i).append(":").append(currentElement.getRotation().getDegrees()).append(",");
                }
            }
        }
        return retVal.toString();
    }

    /**
     * Add a component on the left of the top panel
     * @param c
     */
    public void addToTopPanel(Component c) {
        topPanel.removeAll();
        /*TODO fix this*/
        if (c != null) {
            topPanel.add(Box.createRigidArea(new Dimension(5, 0)));
            topPanel.add(c);
        }
        if (topPanelStyle >= STYLE_TOP_PANEL_FULL) {
            topPanel.add(Box.createRigidArea(new Dimension(5, 0)));
            topPanel.add(loadFileButton);
        }
        if (topPanelStyle >= STYLE_TOP_PANEL_MEDIUM) {
            topPanel.add(Box.createRigidArea(new Dimension(5, 0)));
            topPanel.add(clearButton);
        }
        topPanel.add(Box.createRigidArea(new Dimension(5, 0)));
        topPanel.add(documentProperties);
        topPanel.add(Box.createHorizontalGlue());
        topPanel.add(zoomInButton);
        topPanel.add(Box.createRigidArea(new Dimension(5, 0)));
        topPanel.add(zoomOutButton);
    }

    /**
     * 
     * @return Returns an array of all the selected values, in increasing order based on their indices in the list or an empty array if nothing is selected
     */
    public VisualPageListItem[] getSelectedElements() {
        Object[] elems = thumbnailList.getSelectedValues();
        VisualPageListItem[] visElems = new VisualPageListItem[elems.length];
        System.arraycopy(elems, 0, visElems, 0, elems.length);
        return visElems;
    }

    /**
     * @param c
     * @see VisualListModel#appendAllElements(Collection)
     */
    public void appendElements(Collection<VisualPageListItem> c) {
        ((VisualListModel) thumbnailList.getModel()).appendAllElements(c);
    }

    /**
     * @param c
     * @see VisualListModel#prependAllElements(Collection)
     */
    public void prependElements(Collection<VisualPageListItem> c) {
        ((VisualListModel) thumbnailList.getModel()).prependAllElements(c);
    }

    /**
     * Adds a item to the popup menu
     * @param item
     */
    public void addMenuItem(JMenuItem item) {
        popupMenu.add(item);
    }

    /**
     * enables the set output path menu item
     */
    public void enableSetOutputPathMenuItem() {

        menuItemSetOutputPath.setIcon(new ImageIcon(this.getClass().getResource("/images/set_outfile.png")));
        menuItemSetOutputPath.setText(GettextResource.gettext(config.getI18nResourceBundle(), "Set output file"));
        menuItemSetOutputPath.addMouseListener(new MouseAdapter() {
            public void mouseReleased(MouseEvent e) {
                if (selectedPdfDocument != null) {
                    try {
                        String defaultOutputPath = selectedPdfDocument.getParent();
                        firePropertyChange(OUTPUT_PATH_PROPERTY, "", defaultOutputPath);
                    } catch (Exception ex) {
                        log.error(GettextResource.gettext(config.getI18nResourceBundle(),
                                "Error: Unable to get the file path."), ex);
                    }
                }
            }
        });
        popupMenu.add(menuItemSetOutputPath);

        if (!showContextMenu) {
            //show popup
            addPopupShower();
        }
    }

    /**
     * adds the listener that showes the popup
     */
    private void addPopupShower() {
        //show popup
        thumbnailList.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                if (e.isPopupTrigger()) {
                    showMenu(e);
                }
            }

            public void mouseReleased(MouseEvent e) {
                if (e.isPopupTrigger()) {
                    showMenu(e);
                }
            }

            private void showMenu(MouseEvent e) {
                int[] selection = thumbnailList.getSelectedIndices();
                if (!(selection != null && selection.length > 1)) {
                    thumbnailList.setSelectedIndex(thumbnailList.locationToIndex(e.getPoint()));
                    selection = thumbnailList.getSelectedIndices();
                }
                menuItemPreview.setEnabled(selection != null && selection.length == 1);
                popupMenu.show(thumbnailList, e.getX(), e.getY());
            }
        });
    }

    /**
     * remove the set ouput path menu item
     */
    public void disableSetOutputPathMenuItem() {
        popupMenu.remove(menuItemSetOutputPath);
    }

    /**
     * @return the selectedPdfDocumentPassword
     */
    public String getSelectedPdfDocumentPassword() {
        return selectedPdfDocumentPassword;
    }

    /**
     * @param selectedPdfDocumentPassword the selectedPdfDocumentPassword to set
     */
    public void setSelectedPdfDocumentPassword(String selectedPdfDocumentPassword) {
        this.selectedPdfDocumentPassword = selectedPdfDocumentPassword;
    }

    /**
     * @return the clearButton
     */
    public JButton getClearButton() {
        return clearButton;
    }

    /**
     * @return the zoomInButton
     */
    public JButton getZoomInButton() {
        return zoomInButton;
    }

    /**
     * @return the zoomOutButton
     */
    public JButton getZoomOutButton() {
        return zoomOutButton;
    }

    /**
     * @return the undeleteButton
     */
    public JButton getUndeleteButton() {
        return undeleteButton;
    }

    /**
     * @return the removeButton
     */
    public JButton getRemoveButton() {
        return removeButton;
    }

    /**
     * @return the moveUpButton
     */
    public JButton getMoveUpButton() {
        return moveUpButton;
    }

    /**
     * @return the moveDownButton
     */
    public JButton getMoveDownButton() {
        return moveDownButton;
    }

    /**
     * @return the rotateButton
     */
    public JButton getRotateButton() {
        return rotateButton;
    }

    /**
     * @return the rotateAntiButton
     */
    public JButton getRotateAntiButton() {
        return rotateAntiButton;
    }

    /**
     * @return the loadFileButton
     */
    public JButton getLoadFileButton() {
        return loadFileButton;
    }

    /**
     * @return the reverseButton
     */
    public JButton getReverseButton() {
        return reverseButton;
    }

}