Package frost.messaging.frost.gui

Source Code of frost.messaging.frost.gui.DescColumnRenderer

/*
  MessageTextPane.java / Frost
  Copyright (C) 2006  Frost Project <jtcfrost.sourceforge.net>
  Some changes by Stefan Majewski <e9926279@stud3.tuwien.ac.at>

  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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package frost.messaging.frost.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.Font;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.BorderFactory;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
import javax.swing.text.Utilities;

import frost.Core;
import frost.MainFrame;
import frost.SettingsClass;
import frost.fileTransfer.download.DownloadManager;
import frost.fileTransfer.download.FrostDownloadItem;
import frost.gui.AddNewDownloadsDialog;
import frost.gui.KnownBoardsManager;
import frost.gui.SearchMessagesConfig;
import frost.gui.TargetFolderChooser;
import frost.messaging.frost.AttachmentList;
import frost.messaging.frost.BoardAttachment;
import frost.messaging.frost.FileAttachment;
import frost.messaging.frost.FrostMessageObject;
import frost.messaging.frost.boards.Board;
import frost.messaging.frost.boards.Folder;
import frost.util.CopyToClipboard;
import frost.util.FileAccess;
import frost.util.gui.JSkinnablePopupMenu;
import frost.util.gui.SmileyCache;
import frost.util.gui.TextHighlighter;
import frost.util.gui.search.FindAction;
import frost.util.gui.search.TextComponentFindAction;
import frost.util.gui.textpane.AntialiasedTextPane;
import frost.util.gui.textpane.MessageDecoder;
import frost.util.gui.textpane.MouseHyperlinkEvent;
import frost.util.gui.textpane.TextPane;
import frost.util.gui.translation.Language;
import frost.util.gui.translation.LanguageEvent;
import frost.util.gui.translation.LanguageListener;

@SuppressWarnings("serial")
public class MessageTextPane extends JPanel {

    private final Language language = Language.getInstance();
    private final Logger logger = Logger.getLogger(MessageTextPane.class.getName());

    private AntialiasedTextPane messageTextArea = null;
    private JSplitPane messageSplitPane = null;
    private JSplitPane attachmentsSplitPane = null;

    private AttachedFilesTableModel attachedFilesModel;
    private AttachedBoardTableModel attachedBoardsModel;
    private JTable filesTable = null;
    private JTable boardsTable = null;
    private JScrollPane filesTableScrollPane;
    private JScrollPane boardsTableScrollPane;
    private JScrollPane messageBodyScrollPane;

    private PopupMenuAttachmentBoard popupMenuAttachmentBoard = null;
    private PopupMenuAttachmentFile popupMenuAttachmentTable = null;
    private PopupMenuHyperLink popupMenuHyperLink = null;
    private PopupMenuTofText popupMenuTofText = null;

    private FrostMessageObject selectedMessage;

    private final MainFrame mainFrame = MainFrame.getInstance();

    private final Component parentFrame;

    private PropertyChangeListener propertyChangeListener;

    private SearchMessagesConfig searchMessagesConfig = null;
    private TextHighlighter textHighlighter = null;
    private static Color highlightColor = new Color(0x20, 0xFF, 0x20); // light green
    private static Color idLineHighlightColor = Color.LIGHT_GRAY;
    private final TextHighlighter idLineTextHighlighter = new TextHighlighter(idLineHighlightColor);

    public MessageTextPane(final Component parentFrame) {
        this(parentFrame, null);
    }

    public MessageTextPane(final Component parentFrame, final SearchMessagesConfig smc) {
        super();
        this.parentFrame = parentFrame;
        this.searchMessagesConfig = smc;
        initialize();
    }

    /**
     * Called if there are no boards in the board list.
     */
    public void update_noBoardsFound() {
        messageSplitPane.setBottomComponent(null);
        messageSplitPane.setDividerSize(0);
        setMessageText(language.getString("MessagePane.defaultText.welcomeMessage"));
    }

    /**
     * Called if a board is selected, but no message in message table.
     */
    public void update_boardSelected() {
        messageSplitPane.setBottomComponent(null);
        messageSplitPane.setDividerSize(0);
        setMessageText(language.getString("MessagePane.defaultText.noMessageSelected"));
    }

    /**
     * Called if a folder is selected.
     */
    public void update_folderSelected() {
        messageSplitPane.setBottomComponent(null);
        messageSplitPane.setDividerSize(0);
        setMessageText(language.getString("MessagePane.defaultText.noBoardSelected"));
    }

    private void setMessageText(final String txt) {
        idLineTextHighlighter.removeHighlights(messageTextArea);
        SmileyCache.clearCachedSmileys();
        messageTextArea.setText(txt);
    }

    public TextPane getTextArea() {
        return messageTextArea;
    }

    /**
     * Find the offset in text where the caret must be positioned to
     * show the line at 'offset' on top of visible text.
     * Scans through the visible text and counts 'linesDown' visible lines (maybe wrapped!).
     */
    private int calculateCaretPosition(final JTextComponent c, int offset, int linesDown) {
        final int len = c.getDocument().getLength();
        try {
            while (offset < len) {
                int end = Utilities.getRowEnd(c, offset);
                if (end < 0) {
                    break;
                }

                // Include the last character on the line
                end = Math.min(end+1, len);

                offset = end;
                linesDown--;
                if( linesDown == 0 ) {
                    return offset;
                }
            }
        } catch (final BadLocationException e) {
        }
        return len;
    }

    /**
     * Called if a message is selected.
     */
    public void update_messageSelected(final FrostMessageObject msg) {

        selectedMessage = msg;

        if( textHighlighter != null ) {
            textHighlighter.removeHighlights(messageTextArea);
        }

        final AttachmentList<FileAttachment> fileAttachments = selectedMessage.getAttachmentsOfTypeFile();
        final AttachmentList<BoardAttachment> boardAttachments = selectedMessage.getAttachmentsOfTypeBoard();
       
        attachedFilesModel.setData(fileAttachments);
        attachedBoardsModel.setData(boardAttachments);

        final int textViewHeight = positionDividers(fileAttachments.size(), boardAttachments.size());

        setMessageText(selectedMessage.getContent());

        messageBodyScrollPane.getVerticalScrollBar().setValueIsAdjusting(true);
        messageBodyScrollPane.getVerticalScrollBar().setValue(0);

        // for search messages don't scroll down to begin of text
        if( searchMessagesConfig == null ) {
            int pos = selectedMessage.getIdLinePos();
            final int len = selectedMessage.getIdLineLen();
            if( pos > -1 && len > 10 ) {
                // highlite id line if there are valid infos abpout the idline in message
                idLineTextHighlighter.highlight(messageTextArea, pos, len, true);
            } else {
                // fallback
                pos = selectedMessage.getContent().lastIndexOf("----- "+selectedMessage.getFromName()+" ----- ");
            }

            if( pos >= 0 ) {
                // scroll to begin of reply
                final int h = messageTextArea.getFontMetrics(messageTextArea.getFont()).getHeight();
                final int s = textViewHeight; // messageBodyScrollPane.getViewport().getHeight();
                final int v = s/h - 1; // how many lines are visible?

                pos = calculateCaretPosition(messageTextArea, pos, v);

                messageTextArea.getCaret().setDot(pos);
            } else {
                // scroll to end of message
                pos = selectedMessage.getContent().length();
                messageTextArea.getCaret().setDot(pos);
            }
        }

        messageBodyScrollPane.getVerticalScrollBar().setValueIsAdjusting(false);

        if( searchMessagesConfig != null &&
            searchMessagesConfig.content != null &&
            searchMessagesConfig.content.size() > 0 )
        {
            // highlight words in content that the user searched for
            if( textHighlighter == null ) {
                textHighlighter = new TextHighlighter(highlightColor, true);
            }
            textHighlighter.highlight(messageTextArea, searchMessagesConfig.content, false);
        }
    }

    private void initialize() {

        setLayout(new BorderLayout());

        final MessageDecoder decoder = new MessageDecoder();
        decoder.setSmileyDecode(Core.frostSettings.getBoolValue(SettingsClass.SHOW_SMILEYS));
        decoder.setFreenetKeysDecode(Core.frostSettings.getBoolValue(SettingsClass.SHOW_KEYS_AS_HYPERLINKS));
        messageTextArea = new AntialiasedTextPane(decoder);
        messageTextArea.setEditable(false);
        messageTextArea.setDoubleBuffered(true);
        messageTextArea.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
//        messageTextArea.setLineWrap(true);
//        messageTextArea.setWrapStyleWord(true);

        messageTextArea.setAntiAliasEnabled(Core.frostSettings.getBoolValue(SettingsClass.MESSAGE_BODY_ANTIALIAS));

        messageBodyScrollPane = new JScrollPane(messageTextArea);
        messageBodyScrollPane.setWheelScrollingEnabled(true);

        // build attached files scroll pane
        attachedFilesModel = new AttachedFilesTableModel();
        filesTable = new JTable(attachedFilesModel);
        attachedFilesModel.configureTable(filesTable);
        filesTableScrollPane = new JScrollPane(filesTable);
        filesTableScrollPane.setWheelScrollingEnabled(true);

        // build attached boards scroll pane
        attachedBoardsModel = new AttachedBoardTableModel();
        boardsTable = new JTable(attachedBoardsModel) {
            DescColumnRenderer descColRenderer = new DescColumnRenderer();
            @Override
            public TableCellRenderer getCellRenderer(final int row, final int column) {
                if( column == 2 ) {
                    return descColRenderer;
                }
                return super.getCellRenderer(row, column);
            }
            // renderer that show a tooltip text, used for the description column
            class DescColumnRenderer extends DefaultTableCellRenderer {
                @Override
                public Component getTableCellRendererComponent(
                    final JTable table,
                    final Object value,
                    final boolean isSelected,
                    final boolean hasFocus,
                    final int row,
                    final int column)
                {
                    super.getTableCellRendererComponent(
                        table,
                        value,
                        isSelected,
                        hasFocus,
                        row,
                        column);

                    final String sval = (String)value;
                    if( sval != null &&
                        sval.length() > 0 )
                    {
                        setToolTipText(sval);
                    } else {
                        setToolTipText(null);
                    }
                    return this;
                }
            }
        };
        boardsTableScrollPane = new JScrollPane(boardsTable);
        boardsTableScrollPane.setWheelScrollingEnabled(true);

        fontChanged();

        //Put everything together
        attachmentsSplitPane =
            new JSplitPane(
                JSplitPane.VERTICAL_SPLIT,
                filesTableScrollPane,
                boardsTableScrollPane);
        attachmentsSplitPane.setResizeWeight(0.5);
        attachmentsSplitPane.setDividerSize(3);
        attachmentsSplitPane.setDividerLocation(0.5);

        messageSplitPane =
            new JSplitPane(
                JSplitPane.VERTICAL_SPLIT,
                messageBodyScrollPane,
                attachmentsSplitPane);
        messageSplitPane.setDividerSize(0);
        messageSplitPane.setDividerLocation(1.0);
        messageSplitPane.setResizeWeight(1.0);

        add(messageSplitPane, BorderLayout.CENTER);

        messageTextArea.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(final MouseEvent e) {
                if (e.isPopupTrigger()) {
                    showTofTextAreaPopupMenu(e);
                }
            }
            @Override
            public void mouseReleased(final MouseEvent e) {
                if (e.isPopupTrigger()) {
                    showTofTextAreaPopupMenu(e);
                }
            }
        });
        messageTextArea.addKeyListener(new KeyAdapter() {
            @Override
            public void keyTyped(final KeyEvent e) {
                if( e == null ) {
                    return;
                } else if(e.getKeyChar() == KeyEvent.VK_DELETE && parentFrame == mainFrame ) {
                    mainFrame.getMessagePanel().deleteSelectedMessage();
                }
            }
        });

        final FindAction findAction = new TextComponentFindAction();
        findAction.install(messageTextArea);

        messageTextArea.addHyperlinkListener(new HyperlinkListener() {
            public void hyperlinkUpdate(final HyperlinkEvent evt) {
                if( !(evt instanceof MouseHyperlinkEvent) ) {
                    logger.severe("INTERNAL ERROR, hyperlinkevent is wrong object!");
                    return;
                }
                final MouseHyperlinkEvent e = (MouseHyperlinkEvent) evt;
                if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
                    // user clicked on 'clickedKey', List 'allKeys' contains all keys
                    final List<String> allKeys = ((MessageDecoder)messageTextArea.getDecoder()).getHyperlinkedKeys();
                    final String clickedKey = e.getDescription();
                    // show menu to download this/all keys and copy this/all to clipboard
                    showHyperLinkPopupMenu(
                            e,
                            clickedKey,
                            allKeys,
                            e.getMouseEvent().getX(),
                            e.getMouseEvent().getY());
                }
            }
        });
        filesTable.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(final MouseEvent e) {
                if (e.isPopupTrigger()) {
                    showAttachedFilesPopupMenu(e);
                }
            }
            @Override
            public void mouseReleased(final MouseEvent e) {
                if (e.isPopupTrigger()) {
                    showAttachedFilesPopupMenu(e);
                }
            }
        });
        boardsTable.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(final MouseEvent e) {
                if (e.isPopupTrigger()) {
                    showAttachedBoardsPopupMenu(e);
                }
            }
            @Override
            public void mouseReleased(final MouseEvent e) {
                if (e.isPopupTrigger()) {
                    showAttachedBoardsPopupMenu(e);
                }
            }
        });

        propertyChangeListener = new PropertyChangeListener() {
            public void propertyChange(final PropertyChangeEvent evt) {
                if (evt.getPropertyName().equals(SettingsClass.MESSAGE_BODY_ANTIALIAS)) {
                    messageTextArea.setAntiAliasEnabled(Core.frostSettings.getBoolValue(SettingsClass.MESSAGE_BODY_ANTIALIAS));
                } else if (evt.getPropertyName().equals(SettingsClass.MESSAGE_BODY_FONT_NAME)) {
                    fontChanged();
                } else if (evt.getPropertyName().equals(SettingsClass.MESSAGE_BODY_FONT_SIZE)) {
                    fontChanged();
                } else if (evt.getPropertyName().equals(SettingsClass.MESSAGE_BODY_FONT_STYLE)) {
                    fontChanged();
                } else if (evt.getPropertyName().equals(SettingsClass.SHOW_SMILEYS)) {
                    ((MessageDecoder)messageTextArea.getDecoder()).setSmileyDecode(Core.frostSettings.getBoolValue(SettingsClass.SHOW_SMILEYS));
                    if( selectedMessage != null ) {
                        update_messageSelected(selectedMessage);
                    } else {
                        setMessageText(messageTextArea.getText());
                    }
                } else if (evt.getPropertyName().equals(SettingsClass.SHOW_KEYS_AS_HYPERLINKS)) {
                    ((MessageDecoder)messageTextArea.getDecoder()).setFreenetKeysDecode(Core.frostSettings.getBoolValue(SettingsClass.SHOW_KEYS_AS_HYPERLINKS));
                    if( selectedMessage != null ) {
                        update_messageSelected(selectedMessage);
                    } else {
                        setMessageText(messageTextArea.getText());
                    }
                }
            }
        };

        Core.frostSettings.addPropertyChangeListener(SettingsClass.MESSAGE_BODY_FONT_NAME, propertyChangeListener);
        Core.frostSettings.addPropertyChangeListener(SettingsClass.MESSAGE_BODY_FONT_SIZE, propertyChangeListener);
        Core.frostSettings.addPropertyChangeListener(SettingsClass.MESSAGE_BODY_FONT_STYLE, propertyChangeListener);
        Core.frostSettings.addPropertyChangeListener(SettingsClass.MESSAGE_BODY_ANTIALIAS, propertyChangeListener);
        Core.frostSettings.addPropertyChangeListener(SettingsClass.SHOW_SMILEYS, propertyChangeListener);
        Core.frostSettings.addPropertyChangeListener(SettingsClass.SHOW_KEYS_AS_HYPERLINKS, propertyChangeListener);
    }

    private void fontChanged() {
        final String fontName = Core.frostSettings.getValue(SettingsClass.MESSAGE_BODY_FONT_NAME);
        final int fontStyle = Core.frostSettings.getIntValue(SettingsClass.MESSAGE_BODY_FONT_STYLE);
        final int fontSize = Core.frostSettings.getIntValue(SettingsClass.MESSAGE_BODY_FONT_SIZE);
        Font font = new Font(fontName, fontStyle, fontSize);
        if (!font.getFamily().equals(fontName)) {
            logger.severe(
                "The selected font was not found in your system\n"
                    + "That selection will be changed to \"Monospaced\".");
            Core.frostSettings.setValue(SettingsClass.MESSAGE_BODY_FONT_NAME, "Monospaced");
            font = new Font("Monospaced", fontStyle, fontSize);
        }
        messageTextArea.setFont(font);
    }

    private int positionDividers(final int attachedFiles, final int attachedBoards) {

        if (attachedFiles == 0 && attachedBoards == 0) {
            // Neither files nor boards
            messageSplitPane.setBottomComponent(null);
            messageSplitPane.setDividerSize(0);
            messageSplitPane.setDividerLocation(1.0);
            return messageSplitPane.getDividerLocation();
        }

        messageSplitPane.setDividerSize(3);
        messageSplitPane.setDividerLocation(0.75);

        if (attachedFiles != 0 && attachedBoards == 0) {
            // Only files
            attachmentsSplitPane.setTopComponent(null);
            attachmentsSplitPane.setBottomComponent(null);

            messageSplitPane.setBottomComponent(filesTableScrollPane);
            return messageSplitPane.getDividerLocation();
        }
        if (attachedFiles == 0 && attachedBoards != 0) {
            // Only boards
            attachmentsSplitPane.setTopComponent(null);
            attachmentsSplitPane.setBottomComponent(null);

            messageSplitPane.setBottomComponent(boardsTableScrollPane);
            return messageSplitPane.getDividerLocation();
        }
        if (attachedFiles != 0 && attachedBoards != 0) {
            // Both files and boards
            attachmentsSplitPane.setTopComponent(filesTableScrollPane);
            attachmentsSplitPane.setBottomComponent(boardsTableScrollPane);

            messageSplitPane.setBottomComponent(attachmentsSplitPane);
        }
        return messageSplitPane.getDividerLocation();
    }

    public void saveMessageButton_actionPerformed() {
        FileAccess.saveDialog(
            MainFrame.getInstance(),
            messageTextArea.getText(),
            Core.frostSettings.getValue(SettingsClass.DIR_LAST_USED),
            language.getString("MessagePane.messageText.saveDialog.title"));
    }

    private void addBoardsToKnownBoards() {
        int[] selectedRows = boardsTable.getSelectedRows();

        if (selectedRows.length == 0) {
            // add all rows
            boardsTable.selectAll();
            selectedRows = boardsTable.getSelectedRows();
            if (selectedRows.length == 0) {
                return;
            }
        }
        final AttachmentList<BoardAttachment> boards = selectedMessage.getAttachmentsOfTypeBoard();
        final LinkedList<Board> addBoards = new LinkedList<Board>();
        for( final int element : selectedRows ) {
            addBoards.add(boards.get(element).getBoardObj());
        }

        KnownBoardsManager.addNewKnownBoards(addBoards);
    }
   
    /**
     * Adds all boards from the attachedBoardsTable to board list.
     * If targetFolder is null the boards are added to the root folder.
     */
    private void downloadBoards(final Folder targetFolder) {
        logger.info("adding boards");
        int[] selectedRows = boardsTable.getSelectedRows();

        if (selectedRows.length == 0) {
            // add all rows
            boardsTable.selectAll();
            selectedRows = boardsTable.getSelectedRows();
            if (selectedRows.length == 0) {
                return;
            }
        }
        final AttachmentList<BoardAttachment> boardAttachmentList = selectedMessage.getAttachmentsOfTypeBoard();
        for( final int element : selectedRows ) {
            final Board fbo = boardAttachmentList.get(element).getBoardObj();
            final String boardName = fbo.getName();

            // search board in exising boards list
            final Board board = mainFrame.getFrostMessageTab().getTofTreeModel().getBoardByName(boardName);

            //ask if we already have the board
            if (board != null) {
                if (JOptionPane.showConfirmDialog(
                        this,
                        "You already have a board named " + boardName + ".\n" +
                            "Are you sure you want to add this one over it?",
                        "Board already exists",
                        JOptionPane.YES_NO_OPTION) != 0)
                {
                    continue; // next row of table / next attached board
                } else {
                    // change existing board keys to keys of new board
                    board.setPublicKey(fbo.getPublicKey());
                    board.setPrivateKey(fbo.getPrivateKey());
                    mainFrame.updateTofTree(board);
                }
            } else {
                // its a new board
                if(targetFolder == null) {
                    mainFrame.getFrostMessageTab().getTofTreeModel().addNodeToTree(fbo);
                } else {
                    mainFrame.getFrostMessageTab().getTofTreeModel().addNodeToTree(fbo, targetFolder);
                }
            }
        }
    }

    private void showAttachedBoardsPopupMenu(final MouseEvent e) {
        if (popupMenuAttachmentBoard == null) {
            popupMenuAttachmentBoard = new PopupMenuAttachmentBoard();
            language.addLanguageListener(popupMenuAttachmentBoard);
        }
        popupMenuAttachmentBoard.show(e.getComponent(), e.getX(), e.getY());
    }

    private void showAttachedFilesPopupMenu(final MouseEvent e) {
        if (popupMenuAttachmentTable == null) {
            popupMenuAttachmentTable = new PopupMenuAttachmentFile();
            language.addLanguageListener(popupMenuAttachmentTable);
        }
        popupMenuAttachmentTable.show(e.getComponent(), e.getX(), e.getY());
    }

    private void showHyperLinkPopupMenu(final HyperlinkEvent e, final String clickedKey, final List<String> allKeys, final int x, final int y) {
        if (popupMenuHyperLink == null) {
            popupMenuHyperLink = new PopupMenuHyperLink();
            language.addLanguageListener(popupMenuHyperLink);
        }
        popupMenuHyperLink.setClickedKey(clickedKey);
        popupMenuHyperLink.setAllKeys(allKeys);

        popupMenuHyperLink.show(messageTextArea, x, y);
    }

    private void showTofTextAreaPopupMenu(final MouseEvent e) {
        if (popupMenuTofText == null) {
            popupMenuTofText = new PopupMenuTofText(messageTextArea);
            language.addLanguageListener(popupMenuTofText);
        }
        popupMenuTofText.show(e.getComponent(), e.getX(), e.getY());
    }
   
   
    private void addKeysInText(final String text) {
      // parse text for keys
      List<FrostDownloadItem> parsedKeysfrostDownloadItemList = DownloadManager.parseKeys(text);

      List<FrostDownloadItem> frostDownloadItemList = new ArrayList<FrostDownloadItem>();
      HashMap<String, FrostDownloadItem> frostDownloadItemNameMap = new HashMap<String, FrostDownloadItem>();
      for(FrostDownloadItem frostDownloadItem : parsedKeysfrostDownloadItemList) {
       
        // duplicate check
        if( frostDownloadItemNameMap.containsKey(frostDownloadItem.getFileName())) {
          continue;
        }
       
        // add to download list
        frostDownloadItemList.add(frostDownloadItem);
       
        // configure download items
        frostDownloadItem.setAssociatedMessageId(selectedMessage.getMessageId());
        frostDownloadItem.setAssociatedBoardName(selectedMessage.getBoard().getBoardFilename());
        if( Core.frostSettings.getBoolValue(SettingsClass.USE_BOARDNAME_DOWNLOAD_SUBFOLDER_ENABLED) ){
          frostDownloadItem.setDownloadDir(frostDownloadItem.getDownloadDir().concat(frostDownloadItem.getAssociatedBoardName()));
        }
       
        // remember filename for duplicate check
        frostDownloadItemNameMap.put(frostDownloadItem.getFileName(), frostDownloadItem);
      }

      // Start add download dialog
      new AddNewDownloadsDialog(MainFrame.getInstance()).startDialog(frostDownloadItemList);
    }
   
    private void addKeysOfCurrentMessage() {
      // get message content
      String threadMessageContent = selectedMessage.getContent();
     
      // get start of current message
      int pos = selectedMessage.getIdLinePos();
      String currentMessageText;
      if( pos > -1 ) {
        currentMessageText = threadMessageContent.substring(pos);
      } else {
        currentMessageText = threadMessageContent;
      }

      addKeysInText(currentMessageText);
    }
  
    private class PopupMenuAttachmentBoard
    extends JSkinnablePopupMenu
    implements ActionListener, LanguageListener {

//        private JMenuItem cancelItem = new JMenuItem();
        private final JMenuItem saveBoardsItem = new JMenuItem();
        private final JMenuItem saveBoardsToFolderItem = new JMenuItem();
        private final JMenuItem addBoardsToKnownBoards = new JMenuItem();

        public PopupMenuAttachmentBoard() {
            super();
            initialize();
        }

        public void actionPerformed(final ActionEvent e) {
            if (e.getSource() == saveBoardsItem) {
                downloadBoards(null);
            } else if (e.getSource() == saveBoardsToFolderItem) {
                final TargetFolderChooser tfc = new TargetFolderChooser(mainFrame.getFrostMessageTab().getTofTreeModel());
                final Folder targetFolder = tfc.startDialog();
                if( targetFolder != null ) {
                    downloadBoards(targetFolder);
                }
            } else if( e.getSource() == addBoardsToKnownBoards ) {
                addBoardsToKnownBoards();
            }
        }

        private void initialize() {
            languageChanged(null);

            saveBoardsItem.addActionListener(this);
            saveBoardsToFolderItem.addActionListener(this);
            addBoardsToKnownBoards.addActionListener(this);
        }

        public void languageChanged(final LanguageEvent event) {
            saveBoardsItem.setText(language.getString("MessagePane.boardAttachmentTable.popupmenu.addBoards"));
            saveBoardsToFolderItem.setText(language.getString("MessagePane.boardAttachmentTable.popupmenu.addBoardsToFolder")+" ...");
            addBoardsToKnownBoards.setText(language.getString("MessagePane.boardAttachmentTable.popupmenu.addBoardsToKnownBoards"));
//            cancelItem.setText(language.getString("Common.cancel"));
        }

        @Override
        public void show(final Component invoker, final int x, final int y) {
            removeAll();

            add(saveBoardsItem);
            add(saveBoardsToFolderItem);
            add(addBoardsToKnownBoards);
//            addSeparator();
//            add(cancelItem);

            super.show(invoker, x, y);
        }
    }

    private class PopupMenuAttachmentFile
        extends JSkinnablePopupMenu
        implements ActionListener, LanguageListener {

//        private JMenuItem cancelItem = new JMenuItem();
        private final JMenuItem saveAttachmentItem = new JMenuItem();
        private final JMenuItem saveAttachmentsItem = new JMenuItem();

        private final JMenu copyToClipboardMenu = new JMenu();
        private final JMenuItem copyKeysAndNamesItem = new JMenuItem();
        private final JMenuItem copyExtendedInfoItem = new JMenuItem();

        private final JMenuItem openFileInBrowserItem = new JMenuItem();
        private final JMenuItem openAllFilesInBrowserItem = new JMenuItem();

        public PopupMenuAttachmentFile() throws HeadlessException {
            super();
            initialize();
        }

        public void actionPerformed(final ActionEvent e) {
            if (e.getSource() == saveAttachmentsItem || e.getSource() == saveAttachmentItem) {
                downloadAttachments();
            } else if (e.getSource() == copyKeysAndNamesItem) {
                CopyToClipboard.copyKeysAndFilenames( getItems().toArray() );
            } else if (e.getSource() == copyExtendedInfoItem) {
                CopyToClipboard.copyExtendedInfo( getItems().toArray() );
            } else if (e.getSource() == openFileInBrowserItem) {
              openFileInBrowser_actionWrapper( getItems() );
            } else if (e.getSource() == openAllFilesInBrowserItem) {
              openFileInBrowser_actionWrapper( getItems() );
            }
        }

        private void initialize() {
            languageChanged(null);

            copyToClipboardMenu.add(copyKeysAndNamesItem);
            copyToClipboardMenu.add(copyExtendedInfoItem);

            copyKeysAndNamesItem.addActionListener(this);
            copyExtendedInfoItem.addActionListener(this);

            saveAttachmentsItem.addActionListener(this);
            saveAttachmentItem.addActionListener(this);
           
            String browserAddress = Core.frostSettings.getValue(SettingsClass.BROWSER_ADDRESS);
            if( browserAddress != null && browserAddress.length() > 0 ) {
              openFileInBrowserItem.addActionListener(this);
              openAllFilesInBrowserItem.addActionListener(this);
            }
        }

        public void languageChanged(final LanguageEvent event) {
            copyKeysAndNamesItem.setText(language.getString("Common.copyToClipBoard.copyKeysWithFilenames"));
            copyExtendedInfoItem.setText(language.getString("Common.copyToClipBoard.copyExtendedInfo"));
            copyToClipboardMenu.setText(language.getString("Common.copyToClipBoard") + "...");

            saveAttachmentsItem.setText(language.getString("MessagePane.fileAttachmentTable.popupmenu.downloadAttachments"));
            saveAttachmentItem.setText(language.getString("MessagePane.fileAttachmentTable.popupmenu.downloadSelectedAttachment"));

            openFileInBrowserItem.setText(language.getString("MessagePane.fileAttachmentTable.popupmenu.openAttachmentInBrowser"));
            openAllFilesInBrowserItem.setText(language.getString("MessagePane.fileAttachmentTable.popupmenu.openAllAttachementsInBrowser"));
        }

        @Override
        public void show(final Component invoker, final int x, final int y) {
            removeAll();

            add(copyToClipboardMenu);
            addSeparator();

            if (filesTable.getSelectedRow() == -1) {
                add(saveAttachmentsItem);
            } else {
                add(saveAttachmentItem);
            }

            addSeparator();

            if (filesTable.getSelectedRow() == -1) {
                add(openAllFilesInBrowserItem);
            } else {
                add(openFileInBrowserItem);
            }

            super.show(invoker, x, y);
        }

        /**
         * Adds either the selected or all files from the attachmentTable to downloads table.
         */
        private void downloadAttachments() {
            final Iterator<FileAttachment> it = getItems().iterator();
           
            List<FrostDownloadItem> frostDownloadItemList = new LinkedList<FrostDownloadItem>();
            HashMap<String, FrostDownloadItem> frostDownloadItemKeyMap = new HashMap<String, FrostDownloadItem>();
            HashMap<String, FrostDownloadItem> frostDownloadItemNameMap = new HashMap<String, FrostDownloadItem>();
           
            while (it.hasNext()) {
                final FileAttachment fa = it.next();
               
                if( frostDownloadItemKeyMap.containsKey(fa.getKey())) {
                continue;
              }
               
                String filename = fa.getFileName();
                // maybe convert html codes (e.g. %2c -> , )
                if( filename.indexOf("%") > 0 ) {
                    try {
                        filename = java.net.URLDecoder.decode(filename, "UTF-8");
                    } catch (final java.io.UnsupportedEncodingException ex) {
                        logger.log(Level.SEVERE, "Decode of HTML code failed", ex);
                    }
                }
                if( frostDownloadItemNameMap.containsKey(filename)) {
                  continue;
                }
                final FrostDownloadItem frostDwonloadItem = new FrostDownloadItem(
                  filename,
                  fa.getKey(),
                  fa.getFileSize()
                );
               
                frostDwonloadItem.setAssociatedMessageId(selectedMessage.getMessageId());
                frostDwonloadItem.setAssociatedBoardName(selectedMessage.getBoard().getBoardFilename());
                if( Core.frostSettings.getBoolValue(SettingsClass.USE_BOARDNAME_DOWNLOAD_SUBFOLDER_ENABLED) ){
                  frostDwonloadItem.setDownloadDir(frostDwonloadItem.getDownloadDir().concat(frostDwonloadItem.getAssociatedBoardName()));
                }
                frostDownloadItemList.add( frostDwonloadItem );
                frostDownloadItemKeyMap.put(fa.getKey(), frostDwonloadItem);
                frostDownloadItemNameMap.put(filename, frostDwonloadItem);
            }
           
            frostDownloadItemKeyMap.clear();
            frostDownloadItemNameMap.clear();
           
            new AddNewDownloadsDialog(mainFrame).startDialog(frostDownloadItemList);
        }

        /**
         * Returns a list of all items to process, either selected ones or all.
         */
        private AttachmentList<FileAttachment> getItems() {
            final int[] selectedRows = filesTable.getSelectedRows();
           
            if (selectedRows.length == 0) {
                // If no rows are selected, add all attachments to download table
                return selectedMessage.getAttachmentsOfTypeFile();
           
            } else {
                final AttachmentList<FileAttachment> attachments = selectedMessage.getAttachmentsOfTypeFile();
                AttachmentList<FileAttachment> items = new AttachmentList<FileAttachment>();
                for( final int rowPos : selectedRows ) {
                    items.add(attachments.get(rowPos));
                }
               
                return items;
            }
        }
       
        private void openFileInBrowser_actionWrapper(final List<FileAttachment> fileAttachementList) {
          List<String> keys = new LinkedList<String>();
          for(final FileAttachment fileAttachement : fileAttachementList) {
            keys.add(fileAttachement.getKey());
            }
          openFileInBrowser_action(keys);
        }
    }

  private class PopupMenuHyperLink
    extends JSkinnablePopupMenu
    implements ActionListener, LanguageListener {

        private final JMenuItem cancelItem = new JMenuItem();

        private final JMenuItem copyKeyOnlyToClipboard = new JMenuItem();

        private final JMenuItem copyFreesiteLinkToClipboard = new JMenuItem();

        private final JMenuItem copyFileLinkToClipboard = new JMenuItem();
        private final JMenuItem copyAllFileLinksToClipboard = new JMenuItem();

        private final JMenuItem downloadFile = new JMenuItem();
        private final JMenuItem downloadAllFiles = new JMenuItem();
        private final JMenuItem downloadAllFilesOfMessage = new JMenuItem();

        private final JMenuItem openFileInBrowser = new JMenuItem();
        private final JMenuItem openAllFilesInBrowser = new JMenuItem();

        private String clickedKey = null;
        private List<String> allKeys = null;

        public PopupMenuHyperLink() throws HeadlessException {
            super();
            initialize();
        }

        public void setClickedKey(final String s) {
            clickedKey = s;
        }
        public void setAllKeys(final List<String> listAllKeys) {
            allKeys = listAllKeys;
        }

        public void actionPerformed(final ActionEvent e) {
            if( e.getSource() == copyKeyOnlyToClipboard ) {
                copyToClipboard(false);
            } else if( e.getSource() == copyFreesiteLinkToClipboard ) {
                copyToClipboard(false);
            } else if( e.getSource() == copyFileLinkToClipboard ) {
                copyToClipboard(false);
            } else if( e.getSource() == copyAllFileLinksToClipboard ) {
                copyToClipboard(true);
            } else if( e.getSource() == downloadFile ) {
                downloadItems(false);
            } else if( e.getSource() == downloadAllFiles ) {
                downloadItems(true);
            } else if( e.getSource() == downloadAllFilesOfMessage ) {
              addKeysOfCurrentMessage();
            } else if( e.getSource() == openFileInBrowser ) {
              openFileInBrowser_action(getItems(false));
            } else if( e.getSource() == openAllFilesInBrowser ) {
              openFileInBrowser_action(getItems(true));
            }
        }

        private void initialize() {
            languageChanged(null);

            copyKeyOnlyToClipboard.addActionListener(this);
            copyFreesiteLinkToClipboard.addActionListener(this);
            copyFileLinkToClipboard.addActionListener(this);
            copyAllFileLinksToClipboard.addActionListener(this);
            downloadFile.addActionListener(this);
            downloadAllFiles.addActionListener(this);
            downloadAllFilesOfMessage.addActionListener(this);
           
          openFileInBrowser.addActionListener(this);
            openAllFilesInBrowser.addActionListener(this);
        }

        public void languageChanged(final LanguageEvent event) {
            copyKeyOnlyToClipboard.setText(language.getString("MessagePane.hyperlink.popupmenu.copyKeyToClipboard"));
            copyFreesiteLinkToClipboard.setText(language.getString("MessagePane.hyperlink.popupmenu.copyFreesiteLinkToClipboard"));
            copyFileLinkToClipboard.setText(language.getString("MessagePane.hyperlink.popupmenu.copyFileKeyToClipboard"));
            copyAllFileLinksToClipboard.setText(language.getString("MessagePane.hyperlink.popupmenu.copyAllFileKeysToClipboard"));
            downloadFile.setText(language.getString("MessagePane.hyperlink.popupmenu.downloadFileKey"));
            downloadAllFiles.setText(language.getString("MessagePane.hyperlink.popupmenu.downloadAllFileKeys"));
            downloadAllFilesOfMessage.setText(language.getString("MessagePane.hyperlink.popupmenu.downloadAllFileKeysOfMessage"));
            openFileInBrowser.setText(language.getString("MessagePane.hyperlink.popupmenu.openFileInBrowser"));
            openAllFilesInBrowser.setText(language.getString("MessagePane.hyperlink.popupmenu.openAllFlesInBrowser"));

            cancelItem.setText(language.getString("Common.cancel"));
        }

        @Override
        public void show(final Component invoker, final int x, final int y) {
            removeAll();

            // if clickedLink conatins no '/', its only a key without file, allow to copy this to clipboard only
            // if clickedLink ends with a '/' its a freesite link, allow to copy this to clipboard only
            // else the clickedLink is a filelink, allow to copy/download this link or ALL filelinks

      if (clickedKey.indexOf("/") < 0) {
                // key only
                add(copyKeyOnlyToClipboard);
            } else if( clickedKey.endsWith("/") ) {
                // freesite link
                add(copyFreesiteLinkToClipboard);

        String browserAddress = Core.frostSettings.getValue(SettingsClass.BROWSER_ADDRESS);
              if( browserAddress != null && browserAddress.length() > 0 ) {
                addSeparator();
                add(openFileInBrowser);
          if (allKeys.size() > 1) {
            add(openAllFilesInBrowser);
          }
              }
       
            } else {
                // file key
                add(copyFileLinkToClipboard);
                if( allKeys.size() > 1 ) {
                    add(copyAllFileLinksToClipboard);
                }
                addSeparator();
                add(downloadFile);
                add(downloadAllFilesOfMessage);
                if( allKeys.size() > 1 ) {
                    add(downloadAllFiles);
                }
                String browserAddress = Core.frostSettings.getValue(SettingsClass.BROWSER_ADDRESS);
              if( browserAddress != null && browserAddress.length() > 0 ) {
                addSeparator();
                add(openFileInBrowser);
          if (allKeys.size() > 1) {
            add(openAllFilesInBrowser);
          }
              }
      }

            addSeparator();
            add(cancelItem);

            super.show(invoker, x, y);
        }

        /**
         * Adds either the selected or all files from the attachmentTable to downloads table.
         */
        private void downloadItems(final boolean getAll) {

            final List<String> items = getItems(getAll);
            if( items == null ) {
                return;
            }
           
            List<FrostDownloadItem> frostDownloadItemList = new LinkedList<FrostDownloadItem>();
            HashMap<String, FrostDownloadItem> frostDownloadItemKeyMap = new HashMap<String, FrostDownloadItem>();
            HashMap<String, FrostDownloadItem> frostDownloadItemNameMap = new HashMap<String, FrostDownloadItem>();

            for( final String key : items ) {
              if( frostDownloadItemKeyMap.containsKey(key)) {
                continue;
              }
             
                String name = key.substring(key.lastIndexOf("/")+1);
                // maybe convert html codes (e.g. %2c -> , )
                if( name.indexOf("%") >= 0 ) {
                    try {
                        name = java.net.URLDecoder.decode(name, "UTF-8");
                    } catch (final java.io.UnsupportedEncodingException ex) {
                        logger.log(Level.SEVERE, "Decode of HTML code failed", ex);
                    }
                }
                if( frostDownloadItemNameMap.containsKey(name)) {
                  continue;
                }
               
                FrostDownloadItem frostDownloadItem = new FrostDownloadItem(name, key);
                frostDownloadItem.setAssociatedMessageId(selectedMessage.getMessageId());
                frostDownloadItem.setAssociatedBoardName(selectedMessage.getBoard().getBoardFilename());
                if( Core.frostSettings.getBoolValue(SettingsClass.USE_BOARDNAME_DOWNLOAD_SUBFOLDER_ENABLED) ){
                  frostDownloadItem.setDownloadDir(frostDownloadItem.getDownloadDir().concat(frostDownloadItem.getAssociatedBoardName()));
                }
                frostDownloadItemList.add( frostDownloadItem );
                frostDownloadItemKeyMap.put(key, frostDownloadItem);
                frostDownloadItemNameMap.put(name, frostDownloadItem);
            }
            frostDownloadItemKeyMap.clear();
            frostDownloadItemNameMap.clear();
           
            new AddNewDownloadsDialog(mainFrame).startDialog(frostDownloadItemList);
        }
       
       
        private List<String> getItems(final boolean getAll) {
            List<String> items;
            if( getAll ) {
                items = allKeys;
            } else {
                items = Collections.singletonList(clickedKey);
            }
            if( items == null || items.size() == 0 ) {
                return null;
            }
            return items;
        }

        /**
         * This method copies the CHK keys and file names of the selected or all items to the clipboard.
         */
        private void copyToClipboard(final boolean getAll) {

            final List<String> items = getItems(getAll);
            if( items == null ) {
                return;
            }

            String text;
            if( items.size() > 1 ) {
                final StringBuilder textToCopy = new StringBuilder();
              for( final String key : items ) {
                textToCopy.append(key).append("\n");
              }
              text = textToCopy.toString();
            } else {
              // don't include a trailing \n if we only have one item
              text = items.get(0);
            }
            CopyToClipboard.copyText(text);
        }
       
    }

    private void openFileInBrowser_action(final List<String> items) {
    if (!java.awt.Desktop.isDesktopSupported()) {
      return;
    }
    if (!Desktop.getDesktop().isSupported(java.awt.Desktop.Action.BROWSE)) {
      return;
    }

    final String browserAddress = Core.frostSettings
        .getValue(SettingsClass.BROWSER_ADDRESS);
    if (browserAddress.length() == 0) {
      System.out.println("DEBUG - Borser address not configured");
      return;
    }
    if (items == null || items.size() < 1) {
      return;
    }

    for (final String key : items) {
      try {
        final URI browserURI = new URI(browserAddress);
        final URI uri = new URI(browserURI.getScheme(), browserURI
            .getSchemeSpecificPart()
            + key, null);
        Desktop.getDesktop().browse(uri);
      } catch (IOException ex) {
        ex.printStackTrace();
      } catch (URISyntaxException e) {
        e.printStackTrace();
      }
    }
  }

    private class PopupMenuTofText extends JSkinnablePopupMenu implements ActionListener, LanguageListener {

    private static final long serialVersionUID = 1L;

    private final JTextComponent sourceTextComponent;

        private final JMenuItem copyItem = new JMenuItem();
        private final JMenuItem saveMessageItem = new JMenuItem();
        private final JMenuItem downloadKeys = new JMenuItem();
        private final JMenuItem downloadAllFilesOfMessage = new JMenuItem();

        public PopupMenuTofText(final JTextComponent sourceTextComponent) {
            super();
            this.sourceTextComponent = sourceTextComponent;
            initialize();
        }

        public void actionPerformed(final ActionEvent e) {
            if (e.getSource() == saveMessageItem) {
                saveMessageButton_actionPerformed();
               
            } else if (e.getSource() == copyItem) {
              final String text = sourceTextComponent.getSelectedText();
                CopyToClipboard.copyText(text);
               
            } else if(e.getSource() == downloadKeys ) {
              addKeysInText(sourceTextComponent.getSelectedText());
             
            } else if(e.getSource() == downloadAllFilesOfMessage ) {
              addKeysOfCurrentMessage();
            }
        }

        private void initialize() {
            languageChanged(null);

            copyItem.addActionListener(this);
            saveMessageItem.addActionListener(this);
            downloadKeys.addActionListener(this);
            downloadAllFilesOfMessage.addActionListener(this);

            add(copyItem);
            addSeparator();
            add(saveMessageItem);
            addSeparator();
            add(downloadKeys);
            add(downloadAllFilesOfMessage);
        }

        public void languageChanged(final LanguageEvent event) {
            copyItem.setText(language.getString("MessagePane.messageText.popupmenu.copy"));
            saveMessageItem.setText(language.getString("MessagePane.messageText.popupmenu.saveMessageToDisk"));
            downloadKeys.setText(language.getString("MessagePane.messageText.popupmenu.downloadKeys"));
            downloadAllFilesOfMessage.setText(language.getString("MessagePane.hyperlink.popupmenu.downloadAllFileKeysOfMessage"));
        }

        @Override
        public void show(final Component invoker, final int x, final int y) {
            if ((selectedMessage != null) && (selectedMessage.getContent() != null)) {
                if (sourceTextComponent.getSelectedText() != null) {
                    copyItem.setEnabled(true);
                    downloadKeys.setEnabled(true);
                } else {
                    copyItem.setEnabled(false);
                    downloadKeys.setEnabled(false);
                }
                super.show(invoker, x, y);
            }
        }
    }

    protected void close() {
        Core.frostSettings.removePropertyChangeListener(SettingsClass.MESSAGE_BODY_FONT_NAME, propertyChangeListener);
        Core.frostSettings.removePropertyChangeListener(SettingsClass.MESSAGE_BODY_FONT_SIZE, propertyChangeListener);
        Core.frostSettings.removePropertyChangeListener(SettingsClass.MESSAGE_BODY_FONT_STYLE, propertyChangeListener);
        Core.frostSettings.removePropertyChangeListener(SettingsClass.MESSAGE_BODY_ANTIALIAS, propertyChangeListener);

        if (popupMenuAttachmentBoard != null) {
            language.removeLanguageListener(popupMenuAttachmentBoard);
        }
        if (popupMenuAttachmentTable != null) {
            language.removeLanguageListener(popupMenuAttachmentTable);
        }
        if (popupMenuTofText != null) {
            language.removeLanguageListener(popupMenuTofText);
        }
    }

    /**
     * Used by MessageWindow to attach a KeyListener for ESC.
     */
    @Override
    public void addKeyListener(final KeyListener l) {
        super.addKeyListener(l);
        messageTextArea.addKeyListener(l);
        filesTable.addKeyListener(l);
        boardsTable.addKeyListener(l);
    }
    /**
     * Used by MessageWindow to detach a KeyListener for ESC.
     */
    @Override
    public void removeKeyListener(final KeyListener l) {
        super.removeKeyListener(l);
        messageTextArea.removeKeyListener(l);
        filesTable.removeKeyListener(l);
        boardsTable.removeKeyListener(l);
    }
}
TOP

Related Classes of frost.messaging.frost.gui.DescColumnRenderer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.