chatroom.java

来自「开源项目openfire的完整源程序」· Java 代码 · 共 1,006 行 · 第 1/3 页

JAVA
1,006
字号
/**
 * $Revision: $
 * $Date: $
 *
 * Copyright (C) 2006 Jive Software. All rights reserved.
 *
 * This software is published under the terms of the GNU Lesser Public License (LGPL),
 * a copy of which is included in this distribution.
 */

package org.jivesoftware.spark.ui;

import org.jivesoftware.resource.Res;
import org.jivesoftware.resource.SparkRes;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.spark.ChatAreaSendField;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.component.BackgroundPanel;
import org.jivesoftware.spark.component.RolloverButton;
import org.jivesoftware.spark.plugin.ContextMenuListener;
import org.jivesoftware.spark.util.GraphicUtils;
import org.jivesoftware.spark.util.log.Log;
import org.jivesoftware.sparkimpl.settings.local.LocalPreferences;
import org.jivesoftware.sparkimpl.settings.local.SettingsManager;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSplitPane;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
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.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * The base implementation of all ChatRoom conversations. You would implement this class to have most types of Chat.
 */
public abstract class ChatRoom extends BackgroundPanel implements ActionListener, PacketListener, DocumentListener, ConnectionListener, FocusListener, ContextMenuListener {
    private final JPanel chatPanel;
    private final JSplitPane splitPane;
    private JSplitPane verticalSplit;

    private final JLabel notificationLabel;
    private final TranscriptWindow transcriptWindow;
    private final ChatAreaSendField chatAreaButton;
    private final ChatToolBar toolbar;
    private final JScrollPane textScroller;
    private final JPanel bottomPanel;
    private final JPanel editorBar;
    private JPanel chatWindowPanel;

    private int unreadMessageCount;

    private boolean mousePressed;

    private List<ChatRoomClosingListener> closingListeners = new CopyOnWriteArrayList<ChatRoomClosingListener>();


    private ChatRoomTransferHandler transferHandler;

    private final List<String> packetIDList;
    private final List<MessageListener> messageListeners;
    private List<Message> transcript;
    private List<FileDropListener> fileDropListeners;

    private MouseAdapter transcriptWindowMouseListener;

    private KeyAdapter chatEditorKeyListener;

    /**
     * Initializes the base layout and base background color.
     */
    protected ChatRoom() {
        chatPanel = new JPanel(new GridBagLayout());
        transcriptWindow = new TranscriptWindow();
        splitPane = new JSplitPane();
        packetIDList = new ArrayList<String>();
        notificationLabel = new JLabel();
        toolbar = new ChatToolBar();
        bottomPanel = new JPanel();

        messageListeners = new ArrayList<MessageListener>();
        transcript = new ArrayList<Message>();
        editorBar = new JPanel(new FlowLayout(FlowLayout.LEFT, 1, 1));
        fileDropListeners = new ArrayList<FileDropListener>();

        transcriptWindowMouseListener = new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                getChatInputEditor().requestFocus();
            }

            public void mouseReleased(MouseEvent e) {
                if (transcriptWindow.getSelectedText() == null) {
                    getChatInputEditor().requestFocus();
                }
            }
        };

        transcriptWindow.addMouseListener(transcriptWindowMouseListener);

        chatAreaButton = new ChatAreaSendField(SparkRes.getString(SparkRes.SEND));
        /*{
            public Dimension getPreferredSize() {
                Dimension dim = super.getPreferredSize();

                int windowHeight = getChatRoom().getHeight();

                if (dim.getHeight() > windowHeight - 200) {
                    dim.height = windowHeight - 200;
                }

                return dim;
            }
        };
        */


        textScroller = new JScrollPane(transcriptWindow);

        textScroller.setBackground(transcriptWindow.getBackground());
        textScroller.getViewport().setBackground(Color.white);
        transcriptWindow.setBackground(Color.white);

        getChatInputEditor().setSelectedTextColor((Color)UIManager.get("ChatInput.SelectedTextColor"));
        getChatInputEditor().setSelectionColor((Color)UIManager.get("ChatInput.SelectionColor"));


        init();

        // Initally, set the right pane to null to keep it empty.
        getSplitPane().setRightComponent(null);

        notificationLabel.setIcon(SparkRes.getImageIcon(SparkRes.BLANK_IMAGE));


        getTranscriptWindow().addContextMenuListener(this);

        transferHandler = new ChatRoomTransferHandler(this);

        getTranscriptWindow().setTransferHandler(transferHandler);
        getChatInputEditor().setTransferHandler(transferHandler);

        add(toolbar, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));

        // Add Connection Listener
        SparkManager.getConnection().addConnectionListener(this);

        // Add Focus Listener
        addFocusListener(this);
    }

    // Setup base layout.
    private void init() {
        setLayout(new GridBagLayout());

        // Remove Default Beveled Borders
        splitPane.setBorder(null);
        splitPane.setOneTouchExpandable(false);

        // Add Vertical Split Pane
        verticalSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
        add(verticalSplit, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));

        verticalSplit.setBorder(null);
        verticalSplit.setOneTouchExpandable(false);

        verticalSplit.setTopComponent(splitPane);

        textScroller.setAutoscrolls(true);

        // Speed up scrolling. It was way too slow.
        textScroller.getVerticalScrollBar().setBlockIncrement(50);
        textScroller.getVerticalScrollBar().setUnitIncrement(20);

        chatWindowPanel = new JPanel();
        chatWindowPanel.setLayout(new GridBagLayout());
        chatWindowPanel.add(textScroller, new GridBagConstraints(0, 10, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
        chatWindowPanel.setOpaque(false);

        // Layout Components
        chatPanel.add(chatWindowPanel, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 5, 0, 5), 0, 0));

        // Add Chat Panel to Split Pane
        splitPane.setLeftComponent(chatPanel);

        // Add edit buttons to Chat Room
        editorBar.setOpaque(false);
        chatPanel.setOpaque(false);


        editorBar.add(new JSeparator(JSeparator.VERTICAL));

        bottomPanel.setOpaque(false);
        splitPane.setOpaque(false);
        bottomPanel.setLayout(new GridBagLayout());
        bottomPanel.add(chatAreaButton, new GridBagConstraints(0, 1, 5, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 5, 5, 5), 0, 15));
        bottomPanel.add(editorBar, new GridBagConstraints(0, 0, 5, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 0, 5), 0, 0));

        // Set bottom panel border
        bottomPanel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(197, 213, 230)));
        verticalSplit.setOpaque(false);

        verticalSplit.setBottomComponent(bottomPanel);
        verticalSplit.setResizeWeight(1.0);
        verticalSplit.setDividerSize(2);

        // Add listener to send button
        chatAreaButton.getButton().addActionListener(this);

        // Add Key Listener to Send Field
        getChatInputEditor().getDocument().addDocumentListener(this);

        // Add Key Listener to Send Field
        chatEditorKeyListener = new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                checkForEnter(e);
            }
        };

        getChatInputEditor().addKeyListener(chatEditorKeyListener);

        getChatInputEditor().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ctrl F4"), "closeTheRoom");
        getChatInputEditor().getActionMap().put("closeTheRoom", new AbstractAction("closeTheRoom") {
            public void actionPerformed(ActionEvent evt) {
                // Leave this chat.
                closeChatRoom();
            }
        });
    }


    // I would normally use the command pattern, but
    // have no real use when dealing with just a couple options.
    public void actionPerformed(ActionEvent e) {
        sendMessage();

        // Clear send field and disable send button
        getChatInputEditor().clear();
        chatAreaButton.getButton().setEnabled(false);
    }

    /**
     * Creates and sends a message object from the text in
     * the Send Field, using the default nickname specified in your
     * Chat Preferences.
     */
    protected abstract void sendMessage();

    /**
     * Creates a Message object from the given text and delegates to the room
     * for sending.
     *
     * @param text the text to send.
     */
    protected abstract void sendMessage(String text);

    /**
     * Sends the current message.
     *
     * @param message - the message to send.
     */
    public abstract void sendMessage(Message message);

    /**
     * Returns the nickname of the current agent as specified in Chat
     * Preferences.
     *
     * @return the nickname of the agent.
     */
    public String getNickname() {
        LocalPreferences pref = SettingsManager.getLocalPreferences();
        return pref.getNickname();
    }


    /**
     * The main entry point when receiving any messages. This will
     * either handle a message from a customer or delegate itself
     * as an agent handler.
     *
     * @param message - the message receieved.
     */
    public void insertMessage(Message message) {
        // Fire Message Filters
        SparkManager.getChatManager().filterIncomingMessage(this, message);

        SparkManager.getChatManager().fireGlobalMessageReceievedListeners(this, message);

        addToTranscript(message, true);

        fireMessageReceived(message);
    }


    /**
     * Add a <code>ChatResponse</chat> to the current discussion chat area.
     *
     * @param message    the message to add to the transcript list
     * @param updateDate true if you wish the date label to be updated with the
     *                   date and time the message was received.
     */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?