chatcontainer.java.svn-base
来自「开源项目openfire的完整源程序」· SVN-BASE 代码 · 共 1,309 行 · 第 1/3 页
SVN-BASE
1,309 行
/**
* $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.MainWindow;
import org.jivesoftware.Spark;
import org.jivesoftware.resource.Res;
import org.jivesoftware.resource.SparkRes;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.FromContainsFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.component.tabbedPane.SparkTab;
import org.jivesoftware.spark.component.tabbedPane.SparkTabbedPane;
import org.jivesoftware.spark.component.tabbedPane.SparkTabbedPaneListener;
import org.jivesoftware.spark.ui.rooms.ChatRoomImpl;
import org.jivesoftware.spark.ui.rooms.GroupChatRoom;
import org.jivesoftware.spark.util.ModelUtil;
import org.jivesoftware.spark.util.SwingTimerTask;
import org.jivesoftware.spark.util.TaskEngine;
import org.jivesoftware.spark.util.log.Log;
import org.jivesoftware.sparkimpl.plugin.alerts.SparkToaster;
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.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JTabbedPane;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TimerTask;
/**
* Contains all <code>ChatRoom</code> objects within Spark.
*
* @author Derek DeMoro
*/
public class ChatContainer extends SparkTabbedPane implements MessageListener, ChangeListener, KeyListener {
/**
* List of all ChatRoom Listeners.
*/
private final List<ChatRoomListener> chatRoomListeners = new ArrayList<ChatRoomListener>();
private final List<ChatRoom> chatRoomList = new ArrayList<ChatRoom>();
private final Map<String, PacketListener> presenceMap = new HashMap<String, PacketListener>();
private static final String WELCOME_TITLE = SparkRes.getString(SparkRes.WELCOME);
private ChatFrame chatFrame;
private final TimerTask focusTask;
/**
* Creates the ChatRooms to hold all ChatRooms.
*/
public ChatContainer() {
// Assign location
super(SettingsManager.getLocalPreferences().isTabTopPosition() ? JTabbedPane.TOP : JTabbedPane.BOTTOM);
// Set minimum size
setMinimumSize(new Dimension(400, 200));
// Don't allow tabs to shrink and allow scrolling.
addSparkTabbedPaneListener(new SparkTabbedPaneListener() {
public void tabRemoved(SparkTab tab, Component component, int index) {
stateChanged(null);
if (component instanceof ChatRoom) {
cleanupChatRoom((ChatRoom)component);
}
else if (component instanceof ContainerComponent) {
((ContainerComponent)component).closing();
}
}
public void tabAdded(SparkTab tab, Component component, int index) {
stateChanged(null);
}
public void tabSelected(SparkTab tab, Component component, int index) {
stateChanged(null);
// Notify ChatRoomListeners that the tab has been activated.
if (component instanceof ChatRoom) {
fireChatRoomActivated((ChatRoom)component);
}
}
public void allTabsRemoved() {
chatFrame.setTitle("");
chatFrame.dispose();
}
public boolean canTabClose(SparkTab tab, Component component) {
return true;
}
});
setCloseButtonEnabled(true);
// Add Key Navigation
addKeyNavigation();
this.setFocusable(false);
setOpaque(true);
setBackground(Color.white);
// Create task for focusing chat.
focusTask = new SwingTimerTask() {
public void doRun() {
try {
//chatFrame.requestFocus();
ChatRoom chatRoom = getActiveChatRoom();
chatRoom.requestFocusInWindow();
chatRoom.getChatInputEditor().requestFocusInWindow();
}
catch (ChatRoomNotFoundException e1) {
// Ignore. There may legitamtly not be a chat room.
}
}
};
}
/**
* Adds navigation capability to chat rooms. Users can navigate using the alt-left or right arrow keys.
*/
private void addKeyNavigation() {
KeyStroke leftStroke = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0);
String leftStrokeString = org.jivesoftware.spark.util.StringUtils.keyStroke2String(leftStroke);
// Handle Left Arrow
this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("alt " + leftStrokeString + ""), "navigateLeft");
this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("alt " + leftStrokeString + ""), "navigateLeft");
this.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke("alt " + leftStrokeString + ""), "navigateLeft");
this.getActionMap().put("navigateLeft", new AbstractAction("navigateLeft") {
public void actionPerformed(ActionEvent evt) {
navigateLeft();
}
});
KeyStroke rightStroke = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0);
String rightStrokeString = org.jivesoftware.spark.util.StringUtils.keyStroke2String(rightStroke);
// Handle Right Arrow
this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("alt " + rightStrokeString + ""), "navigateRight");
this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("alt " + rightStrokeString + ""), "navigateRight");
this.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke("alt " + rightStrokeString + ""), "navigateRight");
this.getActionMap().put("navigateRight", new AbstractAction("navigateRight") {
public void actionPerformed(ActionEvent evt) {
navigateRight();
}
});
this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("ESCAPE"), "escape");
this.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke("ESCAPE"), "escape");
this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("Ctrl W"), "escape");
this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_W, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "escape");
this.getActionMap().put("escape", new AbstractAction("escape") {
public void actionPerformed(ActionEvent evt) {
closeActiveRoom();
}
});
this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_W, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | InputEvent.SHIFT_MASK), "shiftCmdW");
this.getActionMap().put("shiftCmdW", new AbstractAction("shiftCmdW") {
public void actionPerformed(ActionEvent evt) {
closeAllChatRooms();
}
});
// Add KeyMappings
getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_F, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "searchContacts");
getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("control F"), "searchContacts");
getActionMap().put("searchContacts", new AbstractAction("searchContacts") {
public void actionPerformed(ActionEvent evt) {
SparkManager.getUserManager().searchContacts("", SparkManager.getChatManager().getChatContainer().getChatFrame());
}
});
}
/**
* Adds a new ChatRoom to Spark.
*
* @param room the ChatRoom to add.
*/
public synchronized void addChatRoom(final ChatRoom room) {
createFrameIfNeeded();
room.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.LIGHT_GRAY));
AndFilter presenceFilter = new AndFilter(new PacketTypeFilter(Presence.class), new FromContainsFilter(room.getRoomname()));
// Next, create a packet listener. We use an anonymous inner class for brevity.
PacketListener myListener = new PacketListener() {
public void processPacket(final Packet packet) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
handleRoomPresence((Presence)packet);
}
});
}
};
SparkManager.getConnection().addPacketListener(myListener, presenceFilter);
// Add to PresenceMap
presenceMap.put(room.getRoomname(), myListener);
String tooltip = "";
if (room instanceof ChatRoomImpl) {
tooltip = ((ChatRoomImpl)room).getParticipantJID();
String nickname = SparkManager.getUserManager().getUserNicknameFromJID(((ChatRoomImpl)room).getParticipantJID());
tooltip = "<html><body><b>Contact: </b>" + nickname + "<br><b>JID: </b>" + tooltip;
}
else {
tooltip = room.getRoomname();
}
// Create ChatRoom UI and dock
SparkTab tab = addTab(room.getTabTitle(), room.getTabIcon(), room, tooltip);
tab.addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
checkTabPopup(e);
}
public void mousePressed(MouseEvent e) {
checkTabPopup(e);
}
});
room.addMessageListener(this);
// Remove brand panel
final String title = getTabAt(0).getActualText();
if (title.equals(WELCOME_TITLE)) {
chatFrame.setTitle(room.getRoomTitle());
}
final TimerTask visibleTask = new SwingTimerTask() {
public void doRun() {
checkVisibility(room);
}
};
TaskEngine.getInstance().schedule(visibleTask, 100);
// Add to ChatRoomList
chatRoomList.add(room);
// Notify users that the chat room has been opened.
fireChatRoomOpened(room);
// Focus Chat
focusChat();
// Add Room listeners to override issue with input maps and keybinding on the mac.
if (Spark.isMac()) {
room.getChatInputEditor().addKeyListener(this);
}
}
public void addContainerComponent(ContainerComponent comp) {
createFrameIfNeeded();
SparkTab tab = addTab(comp.getTabTitle(), comp.getTabIcon(), comp.getGUI(), comp.getToolTipDescription());
chatFrame.setTitle(comp.getFrameTitle());
checkVisibility(comp.getGUI());
if (getSelectedComponent() != comp) {
// Notify Decorators
SparkManager.getChatManager().notifySparkTabHandlers(comp.getGUI());
}
}
/**
* Handles the presence of a one to one chat room.
*
* @param p the presence to handle.
*/
private void handleRoomPresence(final Presence p) {
final String roomname = StringUtils.parseBareAddress(p.getFrom());
ChatRoom chatRoom;
try {
chatRoom = getChatRoom(roomname);
}
catch (ChatRoomNotFoundException e1) {
Log.debug("Could not locate chat room " + roomname);
return;
}
final String userid = StringUtils.parseResource(p.getFrom());
if (p.getType() == Presence.Type.unavailable) {
fireUserHasLeft(chatRoom, userid);
}
else if (p.getType() == Presence.Type.available) {
fireUserHasJoined(chatRoom, userid);
}
// Change tab icon
if (chatRoom instanceof ChatRoomImpl) {
// Notify state change.
int tabLoc = indexOfComponent(chatRoom);
if (tabLoc != -1) {
SparkManager.getChatManager().notifySparkTabHandlers(chatRoom);
}
}
}
private void checkVisibility(Component component) {
if (!chatFrame.isVisible() && SparkManager.getMainWindow().isFocusOwner()) {
chatFrame.setState(Frame.NORMAL);
chatFrame.setVisible(true);
}
else if (chatFrame.isVisible() && !chatFrame.isInFocus()) {
startFlashing(component);
}
else if (chatFrame.isVisible() && chatFrame.getState() == Frame.ICONIFIED) {
// Set to new tab.
int tabLocation = indexOfComponent(component);
setSelectedIndex(tabLocation);
// If the ContactList is in the tray, we need better notification by flashing
// the chatframe.
startFlashing(component);
}
// Handle when chat frame is visible but the Contact List is not.
else if (chatFrame.isVisible() && !SparkManager.getMainWindow().isVisible()) {
startFlashing(component);
}
else if (!chatFrame.isVisible()) {
// Set to new tab.
int tabLocation = indexOfComponent(component);
setSelectedIndex(tabLocation);
chatFrame.dispose();
if (Spark.isWindows()) {
chatFrame.setFocusableWindowState(false);
chatFrame.setState(Frame.ICONIFIED);
}
chatFrame.setVisible(true);
chatFrame.setFocusableWindowState(true);
// If the ContactList is in the tray, we need better notification by flashing
// the chatframe.
if (!SparkManager.getMainWindow().isVisible()) {
startFlashing(component);
}
else if (chatFrame.getState() == Frame.ICONIFIED) {
startFlashing(component);
}
if (component instanceof ChatRoom) {
chatFrame.setTitle(((ChatRoom)component).getRoomTitle());
}
}
}
private void handleMessageNotification(final ChatRoom chatRoom) {
ChatRoom activeChatRoom = null;
try {
activeChatRoom = getActiveChatRoom();
}
catch (ChatRoomNotFoundException e1) {
Log.error(e1);
}
if (chatFrame.isVisible() && (chatFrame.getState() == Frame.ICONIFIED || chatFrame.getInactiveTime() > 20000)) {
int tabLocation = indexOfComponent(chatRoom);
setSelectedIndex(tabLocation);
startFlashing(chatRoom);
return;
}
if (!chatFrame.isVisible() && SparkManager.getMainWindow().isFocusOwner()) {
chatFrame.setState(Frame.NORMAL);
chatFrame.setVisible(true);
}
else if (chatFrame.isVisible() && !chatFrame.isInFocus()) {
startFlashing(chatRoom);
}
else if (chatFrame.isVisible() && chatFrame.getState() == Frame.ICONIFIED) {
// Set to new tab.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?