package org.limewire.ui.swing.friends.chat; import java.awt.BorderLayout; import java.util.HashMap; import java.util.Map; import javax.swing.JComponent; import javax.swing.JPanel; import org.limewire.friend.api.MessageWriter; import org.limewire.friend.api.ChatState; import org.limewire.friend.api.FriendEvent; import org.limewire.friend.api.feature.FeatureEvent; import org.limewire.inject.LazySingleton; import org.limewire.listener.ListenerSupport; import org.limewire.listener.EventListener; import org.limewire.listener.SwingEDTEvent; import com.google.inject.Inject; import com.google.inject.name.Named; /** * Contains all the ConversationPanes. Each friend that has an open conversation * will have a unique ConversationPane. Only one ConversationPane can be open at * a given time. */ @LazySingleton class ConversationPanel { private final ConversationPaneFactory conversationFactory; private final JPanel component; /** Map of friendId's to the conversation pane. */ private final Map<String, ConversationPane> chats; /** * Used to coordinate removal from friends list when chat is no longer needed. * When friend is signed off and afterwards we close the conversation, * the friend should be removed from the friends list. */ private final ChatModel chatModel; /** * Friend who's conversation is currently displayed, null if no conversation is * being displayed. */ private ChatFriend selectedConversation = null; /** * Listeners for chat related events targeted for specific conversation panes */ private final ListenerSupport<ChatMessageEvent> messageListenerManager; private final ListenerSupport<ChatStateEvent> chatStateListenerManager; private final ListenerSupport<FeatureEvent> featureListenerManager; private final ListenerSupport<FriendEvent> friendListenerManager; private final EventListener<ChatMessageEvent> messageEventListener; private final EventListener<ChatStateEvent> chatStateEventListener; private final EventListener<FeatureEvent> featureEventListener; private final EventListener<FriendEvent> friendEventListener; @Inject public ConversationPanel(ConversationPaneFactory conversationFactory, ListenerSupport<ChatMessageEvent> messageListenerManager, ListenerSupport<ChatStateEvent> chatStateListenerManager, @Named("available")ListenerSupport<FriendEvent> friendListenerManager, ListenerSupport<FeatureEvent> featureListenerManager, ChatModel chatModel) { this.conversationFactory = conversationFactory; this.chatModel = chatModel; component = new JPanel(new BorderLayout()); this.chats = new HashMap<String, ConversationPane>(); this.messageListenerManager = messageListenerManager; this.chatStateListenerManager = chatStateListenerManager; this.friendListenerManager = friendListenerManager; this.featureListenerManager = featureListenerManager; this.messageEventListener = new EventListener<ChatMessageEvent>() { @SwingEDTEvent @Override public void handleEvent(ChatMessageEvent event) { Message message = event.getData(); String friendId = message.getFriendID(); if (chats.containsKey(friendId)) { chats.get(friendId).newChatMessage(message); } } }; this.chatStateEventListener = new EventListener<ChatStateEvent>() { @SwingEDTEvent @Override public void handleEvent(ChatStateEvent event) { ChatState chatState = event.getType(); String friendId = event.getSource(); if (chats.containsKey(friendId)) { chats.get(friendId).newChatState(chatState); } } }; this.featureEventListener = new EventListener<FeatureEvent>() { @SwingEDTEvent @Override public void handleEvent(FeatureEvent event) { String friendId = event.getSource().getFriend().getId(); if (chats.containsKey(friendId)) { chats.get(friendId).featureUpdate(event.getData(), event.getType()); } } }; this.friendEventListener = new EventListener<FriendEvent>() { @SwingEDTEvent @Override public void handleEvent(FriendEvent event) { String friendId = event.getData().getId(); if (chats.containsKey(friendId)) { chats.get(friendId).friendAvailableUpdate(event.getType()); } } }; } public void registerListeners() { messageListenerManager.addListener(messageEventListener); chatStateListenerManager.addListener(chatStateEventListener); friendListenerManager.addListener(friendEventListener); featureListenerManager.addListener(featureEventListener); } public void unregisterListeners() { messageListenerManager.removeListener(messageEventListener); chatStateListenerManager.removeListener(chatStateEventListener); friendListenerManager.removeListener(friendEventListener); featureListenerManager.removeListener(featureEventListener); } /** * Returns the panel containing the conversations. */ public JComponent getComponent() { return component; } private void setConversationPanel(JComponent chatComponent) { component.removeAll(); component.add(chatComponent, BorderLayout.CENTER); component.repaint(); } /** * Displays the conversation with the given ChatFriend. */ public void displayConverstaion(ChatFriend chatFriend) { ConversationPane chatPane = chats.get(chatFriend.getID()); selectedConversation = chatFriend; selectedConversation.setHasUnviewedMessages(false); setConversationPanel(chatPane.asComponent()); chatPane.handleDisplay(); } /** * Returns the ChatFriend whose conversation is currently * displayed. If no conversation is selected returns null. */ public ChatFriend getCurrentConversationFriend() { return selectedConversation; } /** * Returns true if a conversation already exists with the given friend, * false otherwise. */ public boolean hasConversation(ChatFriend chatFriend) { return chats.containsKey(chatFriend.getID()); } /** * Destroys a conversation with a given friend. */ public void removeConversation(ChatFriend chatFriend) { if(chatFriend.equals(selectedConversation)) { selectedConversation = null; setConversationPanel(new JPanel()); } if(hasConversation(chatFriend)) { chatFriend.stopChat(); Conversation conversation = chats.remove(chatFriend.getID()); conversation.dispose(); chatModel.removeFriendIfNecessary(chatFriend); if (chats.isEmpty()) { unregisterListeners(); } } } /** * Destroys all conversations with all friends. */ public void removeAllConversations() { selectedConversation = null; setConversationPanel(new JPanel()); for(String key : chats.keySet()) { chats.get(key).dispose(); } chats.clear(); unregisterListeners(); } /** * Starts a new chat with the given friend. */ public void startNewChat(ChatFriend chatFriend, MessageWriter messageWriter) { // if there are currently no chats, register the listeners if (chats.isEmpty()) { registerListeners(); } ConversationPane chatPane = conversationFactory.create(messageWriter, chatFriend); chats.put(chatFriend.getID(), chatPane); selectedConversation = chatFriend; selectedConversation.setHasUnviewedMessages(false); setConversationPanel(chatPane); chatPane.handleDisplay(); } }