/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Copyright @ 2015 Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.java.sip.communicator.impl.gui.main.chat;
import java.awt.Component; // disambiguation
import java.util.*;
import javax.swing.*;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.customcontrols.*;
import net.java.sip.communicator.impl.gui.main.chat.conference.*;
import net.java.sip.communicator.impl.gui.main.chatroomslist.*;
import net.java.sip.communicator.impl.gui.main.contactlist.*;
import net.java.sip.communicator.service.contactlist.*;
import net.java.sip.communicator.service.gui.*;
import net.java.sip.communicator.service.gui.event.*;
import net.java.sip.communicator.service.muc.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.Logger;
import net.java.sip.communicator.util.account.*;
import org.jitsi.util.*;
/**
* Manages chat windows and panels.
*
* @author Yana Stamcheva
* @author Valentin Martinet
* @author Lyubomir Marinov
* @author Hristo Terezov
*/
public class ChatWindowManager
{
/**
* The <tt>Logger</tt> used by the <tt>ChatWindowManager</tt> class and its
* instances for logging output.
*/
private static final Logger logger
= Logger.getLogger(ChatWindowManager.class);
private final List<ChatPanel> chatPanels
= new ArrayList<ChatPanel>();
private final List <ChatListener> chatListeners
= new ArrayList <ChatListener> ();
private final Object chatSyncRoot = new Object();
/**
* Opens the specified <tt>ChatPanel</tt> and optionally brings it to the
* front.
*
* @param chatPanel the <tt>ChatPanel</tt> to be opened
* @param setSelected <tt>true</tt> if <tt>chatPanel</tt> (and respectively
* its <tt>ChatWindow</tt>) should be brought to the front; otherwise,
* <tt>false</tt>
*/
public void openChat(final ChatPanel chatPanel, final boolean setSelected)
{
if (!SwingUtilities.isEventDispatchThread())
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
openChat(chatPanel, setSelected);
}
});
return;
}
synchronized (chatSyncRoot)
{
ChatContainer chatContainer = chatPanel.getChatContainer();
if(!chatPanel.isShown())
chatContainer.addChat(chatPanel);
chatContainer.openChat(chatPanel, setSelected);
}
}
/**
* Opens the specified <tt>ChatPanel</tt> and optionally brings it to the
* front.
*
* @param room the chat room associated with the contact.
* @param nickname the nickname of the contact in the chat room.
*/
public void openPrivateChatForChatRoomMember(final ChatRoom room,
final String nickname)
{
if (!SwingUtilities.isEventDispatchThread())
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
openPrivateChatForChatRoomMember(room, nickname);
}
});
return;
}
Contact sourceContact = room.getPrivateContactByNickname(
nickname);
openPrivateChatForChatRoomMember(room, sourceContact);
}
/**
* Opens the specified <tt>ChatPanel</tt> and optionally brings it to the
* front.
* @param room the chat room associated with the contact.
* @param sourceContact the contact.
*/
public void openPrivateChatForChatRoomMember(final ChatRoom room,
final Contact sourceContact)
{
if (!SwingUtilities.isEventDispatchThread())
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
openPrivateChatForChatRoomMember(room, sourceContact);
}
});
return;
}
MetaContact metaContact
= GuiActivator.getContactListService()
.findMetaContactByContact(sourceContact);
room.updatePrivateContactPresenceStatus(sourceContact);
ChatPanel chatPanel = getContactChat(metaContact, sourceContact);
chatPanel.setPrivateMessagingChat(true);
openChat(chatPanel, true);
}
/**
* Returns <tt>true</tt> if there is an opened <tt>ChatPanel</tt> for the
* given <tt>MetaContact</tt>.
*
* @param metaContact the <tt>MetaContact</tt>, for which the chat is about
* @return <tt>true</tt> if there is an opened <tt>ChatPanel</tt> for the
* given <tt>MetaContact</tt>
*/
public boolean isChatOpenedFor(MetaContact metaContact)
{
return isChatOpenedForDescriptor(metaContact);
}
/**
* Determines whether there is an opened <tt>ChatPanel</tt> for a specific
* chat descriptor.
*
* @param descriptor the chat descriptor which is to be checked whether
* there is an opened <tt>ChatPanel</tt> for
* @return <tt>true</tt> if there is an opened <tt>ChatPanel</tt> for the
* specified chat descriptor; <tt>false</tt>, otherwise
*/
private boolean isChatOpenedForDescriptor(Object descriptor)
{
synchronized (chatSyncRoot)
{
ChatPanel chatPanel = findChatPanelForDescriptor(descriptor);
return ((chatPanel != null) && chatPanel.isShown());
}
}
/**
* Closes the given chat panel.
*
* @param chatPanel the chat panel to close
*/
public void closeChat(final ChatPanel chatPanel)
{
if (!SwingUtilities.isEventDispatchThread())
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
closeChat(chatPanel);
}
});
return;
}
synchronized (chatSyncRoot)
{
if(containsChat(chatPanel))
{
Date lastMsgTimestamp = chatPanel.getChatConversationPanel()
.getLastIncomingMsgTimestamp();
if (!chatPanel.isWriteAreaEmpty())
{
int answer = showWarningMessage(
"service.gui.NON_EMPTY_CHAT_WINDOW_CLOSE",
chatPanel);
if (answer == JOptionPane.OK_OPTION)
closeChatPanel(chatPanel);
}
else if (System.currentTimeMillis() - lastMsgTimestamp.getTime()
< 2 * 1000)
{
int answer = showWarningMessage(
"service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE",
chatPanel);
if (answer == JOptionPane.OK_OPTION)
closeChatPanel(chatPanel);
}
else if (chatPanel.containsActiveFileTransfers())
{
int answer = showWarningMessage(
"service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER",
chatPanel);
if (answer == JOptionPane.OK_OPTION)
{
chatPanel.cancelActiveFileTransfers();
closeChatPanel(chatPanel);
}
}
else if (chatPanel.getChatSession() instanceof
AdHocConferenceChatSession)
{
AdHocConferenceChatSession adHocSession
= (AdHocConferenceChatSession) chatPanel
.getChatSession();
GuiActivator.getUIService().getConferenceChatManager()
.leaveChatRoom(
(AdHocChatRoomWrapper) adHocSession.getDescriptor());
closeChatPanel(chatPanel);
}
else
{
closeChatPanel(chatPanel);
}
}
}
}
/**
* Disposes the chat window.
*
* @param chatContainer the <tt>ChatContainer</tt> to dispose of
*/
private void closeAllChats(ChatContainer chatContainer)
{
Collection<ChatPanel> chatPanelsToClose = new HashSet<ChatPanel>();
chatPanelsToClose.addAll(chatContainer.getChats());
synchronized (chatPanels)
{
chatPanelsToClose.addAll(chatPanels);
}
ChatPanel currentChat = chatContainer.getCurrentChat();
for (ChatPanel chatPanel : chatPanelsToClose)
{
/*
* We'll close the current ChatPanel last in order to avoid multiple
* changes of the current ChatPanel.
*/
if (chatPanel != currentChat)
{
try
{
closeChatPanel(chatPanel);
}
catch (Exception e)
{
logger.error("Failed to close chat: " + chatPanel, e);
}
}
}
/* As mentioned earlier, close the current ChatPanel last. */
if ((currentChat != null) && chatPanels.contains(currentChat))
closeChatPanel(currentChat);
// Remove the envelope from the all active contacts in the contact list.
if (chatContainer.getChatCount() <= 0)
GuiActivator.getContactList().deactivateAll();
}
/**
* Closes all chats in the specified <tt>ChatContainer</tt> and makes them
* available for garbage collection.
*
* @param chatContainer the <tt>ChatContainer</tt> containing the chats to
* close
* @param warningEnabled indicates if the user should be warned that we're
* closing all the chats. This would be done only if there are currently
* active file transfers or waiting messages
*/
void closeAllChats(ChatContainer chatContainer, boolean warningEnabled)
{
synchronized (chatSyncRoot)
{
// If no warning is enabled we just close all chats without asking
// and return.
if (!warningEnabled)
{
closeAllChats(chatContainer);
return;
}
ChatPanel activePanel = null;
for (ChatPanel chatPanel : chatPanels)
{
if (chatPanel.getChatSession() instanceof
AdHocConferenceChatSession)
{
AdHocConferenceChatSession adHocSession
= (AdHocConferenceChatSession) chatPanel
.getChatSession();
GuiActivator.getUIService().getConferenceChatManager()
.leaveChatRoom(
(AdHocChatRoomWrapper) adHocSession.getDescriptor());
}
Date lastMsgTimestamp = chatPanel.getChatConversationPanel()
.getLastIncomingMsgTimestamp();
if (!chatPanel.isWriteAreaEmpty()
|| chatPanel.containsActiveFileTransfers()
|| System.currentTimeMillis()
- lastMsgTimestamp.getTime() < 2 * 1000)
{
activePanel = chatPanel;
}
}
if (activePanel == null)
{
this.closeAllChats(chatContainer);
return;
}
Date lastMsgTimestamp = activePanel.getChatConversationPanel()
.getLastIncomingMsgTimestamp();
if (!activePanel.isWriteAreaEmpty())
{
int answer = showWarningMessage(
"service.gui.NON_EMPTY_CHAT_WINDOW_CLOSE",
chatContainer.getFrame());
if (answer == JOptionPane.OK_OPTION)
this.closeAllChats(chatContainer);
}
else if (System.currentTimeMillis()
- lastMsgTimestamp.getTime() < 2 * 1000)
{
int answer = showWarningMessage(
"service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE",
chatContainer.getFrame());
if (answer == JOptionPane.OK_OPTION)
this.closeAllChats(chatContainer);
}
else if (activePanel.containsActiveFileTransfers())
{
int answer = showWarningMessage(
"service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER",
chatContainer.getFrame());
if (answer == JOptionPane.OK_OPTION)
{
for (ChatPanel chatPanel : chatPanels)
chatPanel.cancelActiveFileTransfers();
this.closeAllChats(chatContainer);
}
}
}
}
/**
* Gets the <tt>ChatPanel</tt> corresponding to the specified
* <tt>MetaContact</tt> and optionally creates it if it does not exist.
*
* @param metaContact the <tt>MetaContact</tt> to get the corresponding
* <tt>ChatPanel</tt> of
* @param create <tt>true</tt> to create a <tt>ChatPanel</tt> corresponding
* to the specified <tt>MetaContact</tt> if such <tt>ChatPanel</tt> does not
* exist yet
* @return the <tt>ChatPanel</tt> corresponding to the specified
* <tt>MetaContact</tt>; <tt>null</tt> if there is no such
* <tt>ChatPanel</tt> and <tt>create</tt> is <tt>false</tt>
*/
public ChatPanel getContactChat(MetaContact metaContact, boolean create)
{
// if we are not creating a ui we don't need any execution
// in event dispatch thread, lets execute now
if(!create)
return getContactChat(metaContact, null, null, false, null);
else
{
// we may create using event dispatch thread
MetaContactChatCreateRunnable runnable
= new MetaContactChatCreateRunnable(
metaContact, null, null, null);
return runnable.getChatPanel();
}
}
/**
* Gets the <tt>ChatPanel</tt> corresponding to the specified
* <tt>MetaContact</tt> and optionally creates it if it does not exist.
*
* @param metaContact the <tt>MetaContact</tt> to get the corresponding
* <tt>ChatPanel</tt> of
* @param create <tt>true</tt> to create a <tt>ChatPanel</tt> corresponding
* to the specified <tt>MetaContact</tt> if such <tt>ChatPanel</tt> does not
* exist yet
* @param escapedMessageID the message ID of the message that should be
* excluded from the history when the last one is loaded in the chat
* @return the <tt>ChatPanel</tt> corresponding to the specified
* <tt>MetaContact</tt>; <tt>null</tt> if there is no such
* <tt>ChatPanel</tt> and <tt>create</tt> is <tt>false</tt>
*/
public ChatPanel getContactChat(MetaContact metaContact, boolean create,
String escapedMessageID)
{
// if we are not creating a ui we don't need any execution
// in event dispatch thread, lets execute now
if(!create)
return getContactChat( metaContact,
null,
null,
false,
escapedMessageID);
else
{
// we may create using event dispatch thread
MetaContactChatCreateRunnable runnable
= new MetaContactChatCreateRunnable(
metaContact,
null,
null,
escapedMessageID);
return runnable.getChatPanel();
}
}
/**
* Returns the chat panel corresponding to the given meta contact
*
* @param metaContact the meta contact.
* @param protocolContact the protocol specific contact
* @return the chat panel corresponding to the given meta contact
*/
public ChatPanel getContactChat(MetaContact metaContact,
Contact protocolContact)
{
return getContactChat(metaContact, protocolContact, null, null);
}
/**
* Returns the chat panel corresponding to the given meta contact
*
* @param metaContact the meta contact.
* @param protocolContact the protocol specific contact
* @param contactResource the resource from which the contact is writing
* @param escapedMessageID the message ID of the message that should be
* excluded from the history when the last one is loaded in the chat
* @return the chat panel corresponding to the given meta contact
*/
public ChatPanel getContactChat(MetaContact metaContact,
Contact protocolContact,
ContactResource contactResource,
String escapedMessageID)
{
// we may create using event dispatch thread
MetaContactChatCreateRunnable runnable
= new MetaContactChatCreateRunnable(
metaContact,
protocolContact,
contactResource,
escapedMessageID);
return runnable.getChatPanel();
}
/**
* Gets the <tt>ChatPanel</tt> corresponding to the specified
* <tt>MetaContact</tt> and optionally creates it if it does not exist.
* Must be executed on the event dispatch thread as it is creating UI.
*
* @param metaContact the <tt>MetaContact</tt> to get the corresponding
* <tt>ChatPanel</tt> of
* @param protocolContact the <tt>Contact</tt> (respectively its
* <tt>ChatTransport</tt>) to be selected in the newly created
* <tt>ChatPanel</tt>; <tt>null</tt> to select the default <tt>Contact</tt>
* of <tt>metaContact</tt> if it is online or one of its <tt>Contact</tt>s
* which supports offline messaging
* @param create <tt>true</tt> to create a <tt>ChatPanel</tt> corresponding
* to the specified <tt>MetaContact</tt> if such <tt>ChatPanel</tt> does not
* exist yet
* @param escapedMessageID the message ID of the message to be excluded from
* the history when the last one is loaded in the newly created
* <tt>ChatPanel</tt>
* @return the <tt>ChatPanel</tt> corresponding to the specified
* <tt>MetaContact</tt>; <tt>null</tt> if there is no such
* <tt>ChatPanel</tt> and <tt>create</tt> is <tt>false</tt>
*/
private ChatPanel getContactChat(
MetaContact metaContact,
Contact protocolContact,
ContactResource contactResource,
boolean create,
String escapedMessageID)
{
synchronized (chatSyncRoot)
{
ChatPanel chatPanel = findChatPanelForDescriptor(metaContact);
if ((chatPanel == null) && create)
chatPanel
= createChat(
metaContact,
protocolContact,
contactResource,
escapedMessageID);
return chatPanel;
}
}
/**
* Returns the currently selected <tt>ChatPanel</tt>.
*
* @return the currently selected <tt>ChatPanel</tt>
*/
public ChatPanel getSelectedChat()
{
ChatPanel selectedChat = null;
Iterator<ChatPanel> chatPanelsIter = chatPanels.iterator();
synchronized (chatSyncRoot)
{
if (ConfigurationUtils.isMultiChatWindowEnabled())
{
if (chatPanelsIter.hasNext())
{
ChatPanel firstChatPanel = chatPanelsIter.next();
selectedChat
= firstChatPanel.getChatContainer().getCurrentChat();
}
}
else
{
while (chatPanelsIter.hasNext())
{
ChatPanel chatPanel = chatPanelsIter.next();
if (chatPanel.getChatContainer().getFrame().isFocusOwner())
selectedChat = chatPanel;
}
}
return selectedChat;
}
}
/**
* Gets the <tt>ChatPanel</tt> corresponding to the specified
* <tt>ChatRoomWrapper</tt> and optionally creates it if it does not exist
* yet.
*
* @param chatRoomWrapper the <tt>ChatRoomWrapper</tt> to get the
* corresponding <tt>ChatPanel</tt> of
* @param create <tt>true</tt> to create a new <tt>ChatPanel</tt> for the
* specified <tt>ChatRoomWrapper</tt> if no such <tt>ChatPanel</tt> exists
* already; otherwise, <tt>false</tt>
* @return the <tt>ChatPanel</tt> corresponding to the specified
* <tt>ChatRoomWrapper</tt> or <tt>null</tt> if no such <tt>ChatPanel</tt>
* exists and <tt>create</tt> is <tt>false</tt>
*/
private ChatPanel getMultiChatInternal(
ChatRoomWrapper chatRoomWrapper,
boolean create)
{
synchronized (chatSyncRoot)
{
ChatPanel chatPanel = findChatPanelForDescriptor(chatRoomWrapper);
if ((chatPanel == null) && create)
chatPanel = createChat(chatRoomWrapper);
return chatPanel;
}
}
/**
* Gets the <tt>ChatPanel</tt> corresponding to the specified
* <tt>ChatRoomWrapper</tt> and optionally creates it if it does not exist
* yet.
* Must be executed on the event dispatch thread.
*
* @param chatRoomWrapper the <tt>ChatRoomWrapper</tt> to get the
* corresponding <tt>ChatPanel</tt> of
* @param create <tt>true</tt> to create a new <tt>ChatPanel</tt> for the
* specified <tt>ChatRoomWrapper</tt> if no such <tt>ChatPanel</tt> exists
* already; otherwise, <tt>false</tt>
* @return the <tt>ChatPanel</tt> corresponding to the specified
* <tt>ChatRoomWrapper</tt> or <tt>null</tt> if no such <tt>ChatPanel</tt>
* exists and <tt>create</tt> is <tt>false</tt>
*/
public ChatPanel getMultiChat(
ChatRoomWrapper chatRoomWrapper,
boolean create)
{
if(!create)
return getMultiChatInternal(chatRoomWrapper, false);
else
{
// tries to execute creating of the ui on the
// event dispatch thread
return new CreateChatRoomWrapperRunner(chatRoomWrapper)
.getChatPanel();
}
}
/**
* Gets the <tt>ChatPanel</tt> corresponding to the specified
* <tt>AdHocChatRoomWrapper</tt> and optionally creates it if it does not
* exist yet.
*
* @param chatRoomWrapper the <tt>AdHocChatRoomWrapper</tt> to get the
* corresponding <tt>ChatPanel</tt> of
* @param create <tt>true</tt> to create a new <tt>ChatPanel</tt> for the
* specified <tt>AdHocChatRoomWrapper</tt> if no such <tt>ChatPanel</tt>
* exists already; otherwise, <tt>false</tt>
* @return the <tt>ChatPanel</tt> corresponding to the specified
* <tt>AdHocChatRoomWrapper</tt> or <tt>null</tt> if no such
* <tt>ChatPanel</tt> exists and <tt>create</tt> is <tt>false</tt>
*/
private ChatPanel getMultiChatInternal(
AdHocChatRoomWrapper chatRoomWrapper,
boolean create)
{
synchronized (chatSyncRoot)
{
ChatPanel chatPanel = findChatPanelForDescriptor(chatRoomWrapper);
if ((chatPanel == null) && create)
chatPanel = createChat(chatRoomWrapper);
return chatPanel;
}
}
/**
* Gets the <tt>ChatPanel</tt> corresponding to the specified
* <tt>AdHocChatRoomWrapper</tt> and optionally creates it if it does not
* exist yet.
* Must be executed on the event dispatch thread.
*
* @param chatRoomWrapper the <tt>AdHocChatRoomWrapper</tt> to get the
* corresponding <tt>ChatPanel</tt> of
* @param create <tt>true</tt> to create a new <tt>ChatPanel</tt> for the
* specified <tt>AdHocChatRoomWrapper</tt> if no such <tt>ChatPanel</tt>
* exists already; otherwise, <tt>false</tt>
* @return the <tt>ChatPanel</tt> corresponding to the specified
* <tt>AdHocChatRoomWrapper</tt> or <tt>null</tt> if no such
* <tt>ChatPanel</tt> exists and <tt>create</tt> is <tt>false</tt>
*/
public ChatPanel getMultiChat(
AdHocChatRoomWrapper chatRoomWrapper,
boolean create)
{
if(!create)
return getMultiChatInternal(chatRoomWrapper, false);
else
{
// tries to execute creating of the ui on the
// event dispatch thread
return new CreateAdHocChatRoomWrapperRunner(chatRoomWrapper)
.getChatPanel();
}
}
/**
* Gets the <tt>ChatPanel</tt> corresponding to the specified
* <tt>AdHocChatRoom</tt> and optionally creates it if it does not exist.
*
* @param adHocChatRoom the <tt>AdHocChatRoom</tt> to get the corresponding
* <tt>ChatPanel</tt> of
* @param create <tt>true</tt> to create a <tt>ChatPanel</tt> corresponding
* to the specified <tt>AdHocChatRoom</tt> if such <tt>ChatPanel</tt> does
* not exist yet
* @return the <tt>ChatPanel</tt> corresponding to the specified
* <tt>AdHocChatRoom</tt>; <tt>null</tt> if there is no such
* <tt>ChatPanel</tt> and <tt>create</tt> is <tt>false</tt>
*/
public ChatPanel getMultiChat(AdHocChatRoom adHocChatRoom, boolean create)
{
return getMultiChat(adHocChatRoom, create, null);
}
/**
* Gets the <tt>ChatPanel</tt> corresponding to the specified
* <tt>ChatRoom</tt> and optionally creates it if it does not exist.
*
* @param chatRoom the <tt>ChatRoom</tt> to get the corresponding
* <tt>ChatPanel</tt> of
* @param create <tt>true</tt> to create a <tt>ChatPanel</tt> corresponding
* to the specified <tt>ChatRoom</tt> if such <tt>ChatPanel</tt> does not
* exist yet
* @return the <tt>ChatPanel</tt> corresponding to the specified
* <tt>ChatRoom</tt>; <tt>null</tt> if there is no such <tt>ChatPanel</tt>
* and <tt>create</tt> is <tt>false</tt>
*/
public ChatPanel getMultiChat(ChatRoom chatRoom, boolean create)
{
return getMultiChat(chatRoom, create, null);
}
/**
* Gets the <tt>ChatPanel</tt> corresponding to the specified
* <tt>ChatRoom</tt> and optionally creates it if it does not exist.
*
* @param chatRoom the <tt>ChatRoom</tt> to get the corresponding
* <tt>ChatPanel</tt> of
* @param create <tt>true</tt> to create a <tt>ChatPanel</tt> corresponding
* to the specified <tt>ChatRoom</tt> if such <tt>ChatPanel</tt> does not
* exist yet
* @param escapedMessageID the message ID of the message that should be
* excluded from the history when the last one is loaded in the chat
* @return the <tt>ChatPanel</tt> corresponding to the specified
* <tt>ChatRoom</tt>; <tt>null</tt> if there is no such <tt>ChatPanel</tt>
* and <tt>create</tt> is <tt>false</tt>
*/
private ChatPanel getMultiChatInternal(ChatRoom chatRoom,
boolean create,
String escapedMessageID)
{
synchronized (chatSyncRoot)
{
ChatRoomWrapper chatRoomWrapper
= GuiActivator.getMUCService().getChatRoomWrapperByChatRoom(
chatRoom, create);
ChatPanel chatPanel = null;
if (chatRoomWrapper != null)
{
chatPanel = findChatPanelForDescriptor(chatRoomWrapper);
if ((chatPanel == null) && create)
chatPanel = createChat(chatRoomWrapper, escapedMessageID);
}
return chatPanel;
}
}
/**
* Gets the <tt>ChatPanel</tt> corresponding to the specified
* <tt>ChatRoom</tt> and optionally creates it if it does not exist.
* Must be executed on the event dispatch thread.
*
* @param chatRoom the <tt>ChatRoom</tt> to get the corresponding
* <tt>ChatPanel</tt> of
* @param create <tt>true</tt> to create a <tt>ChatPanel</tt> corresponding
* to the specified <tt>ChatRoom</tt> if such <tt>ChatPanel</tt> does not
* exist yet
* @param escapedMessageID the message ID of the message that should be
* excluded from the history when the last one is loaded in the chat
* @return the <tt>ChatPanel</tt> corresponding to the specified
* <tt>ChatRoom</tt>; <tt>null</tt> if there is no such <tt>ChatPanel</tt>
* and <tt>create</tt> is <tt>false</tt>
*/
public ChatPanel getMultiChat(ChatRoom chatRoom,
boolean create,
String escapedMessageID)
{
if(!create)
return getMultiChatInternal(chatRoom, false, escapedMessageID);
else
{
return new CreateChatRoomRunner(chatRoom, escapedMessageID)
.getChatPanel();
}
}
/**
* Gets the <tt>ChatPanel</tt> corresponding to the specified
* <tt>AdHocChatRoom</tt> and optionally creates it if it does not exist.
* Must be executed on the event dispatch thread.
*
* @param adHocChatRoom the <tt>AdHocChatRoom</tt> to get the corresponding
* <tt>ChatPanel</tt> of
* @param create <tt>true</tt> to create a <tt>ChatPanel</tt> corresponding
* to the specified <tt>AdHocChatRoom</tt> if such <tt>ChatPanel</tt> does
* not exist yet
* @param escapedMessageID the message ID of the message that should be
* excluded from the history when the last one is loaded in the chat
* @return the <tt>ChatPanel</tt> corresponding to the specified
* <tt>AdHocChatRoom</tt>; <tt>null</tt> if there is no such
* <tt>ChatPanel</tt> and <tt>create</tt> is <tt>false</tt>
*/
private ChatPanel getMultiChatInternal(AdHocChatRoom adHocChatRoom,
boolean create,
String escapedMessageID)
{
synchronized (chatSyncRoot)
{
AdHocChatRoomList chatRoomList = GuiActivator.getUIService()
.getConferenceChatManager().getAdHocChatRoomList();
// Search in the chat room's list for a chat room that correspond
// to the given one.
AdHocChatRoomWrapper chatRoomWrapper
= chatRoomList
.findChatRoomWrapperFromAdHocChatRoom(adHocChatRoom);
if ((chatRoomWrapper == null) && create)
{
AdHocChatRoomProviderWrapper parentProvider
= chatRoomList.findServerWrapperFromProvider(
adHocChatRoom.getParentProvider());
chatRoomWrapper =
new AdHocChatRoomWrapper(parentProvider, adHocChatRoom);
chatRoomList.addAdHocChatRoom(chatRoomWrapper);
}
ChatPanel chatPanel = null;
if (chatRoomWrapper != null)
{
chatPanel = findChatPanelForDescriptor(chatRoomWrapper);
if ((chatPanel == null) && create)
chatPanel = createChat(chatRoomWrapper, escapedMessageID);
}
return chatPanel;
}
}
/**
* Gets the <tt>ChatPanel</tt> corresponding to the specified
* <tt>AdHocChatRoom</tt> and optionally creates it if it does not exist.
* Must be executed on the event dispatch thread.
*
* @param adHocChatRoom the <tt>AdHocChatRoom</tt> to get the corresponding
* <tt>ChatPanel</tt> of
* @param create <tt>true</tt> to create a <tt>ChatPanel</tt> corresponding
* to the specified <tt>AdHocChatRoom</tt> if such <tt>ChatPanel</tt> does
* not exist yet
* @param escapedMessageID the message ID of the message that should be
* excluded from the history when the last one is loaded in the chat
* @return the <tt>ChatPanel</tt> corresponding to the specified
* <tt>AdHocChatRoom</tt>; <tt>null</tt> if there is no such
* <tt>ChatPanel</tt> and <tt>create</tt> is <tt>false</tt>
*/
public ChatPanel getMultiChat(AdHocChatRoom adHocChatRoom,
boolean create,
String escapedMessageID)
{
if(!create)
return getMultiChatInternal(
adHocChatRoom, false, escapedMessageID);
else
return new CreateAdHocChatRoomRunner(
adHocChatRoom, escapedMessageID).getChatPanel();
}
/**
* Returns all open <code>ChatPanel</code>s.
*
* @return A list of <code>ChatPanel</code>s
*/
public List<ChatPanel> getChatPanels()
{
return chatPanels;
}
/**
* Starts a chat with the given <tt>MetaContact</tt>.
* @param metaContact the destination <tt>MetaContact</tt>
*/
public void startChat(MetaContact metaContact)
{
SwingUtilities.invokeLater(new RunChatWindow(metaContact));
}
/**
* Starts a chat with the given <tt>MetaContact</tt>.
* @param metaContact the destination <tt>MetaContact</tt>
* @param protocolContact the protocol contact of the destination
* @param isSmsMessage indicates if the chat should be opened for an SMS
* message
*/
public void startChat( MetaContact metaContact,
Contact protocolContact,
boolean isSmsMessage)
{
SwingUtilities.invokeLater(
new RunChatWindow(metaContact, protocolContact, isSmsMessage));
}
public void startChat(String contactString)
{
startChat(contactString, false);
}
/**
* Start the chat with contact which is using the supplied protocol
*provider.
* @param contactID the contact id to start chat with
* @param pps the protocol provider
*/
public void startChat(String contactID, ProtocolProviderService pps)
{
OperationSetPersistentPresence opSet
= pps.getOperationSet(OperationSetPersistentPresence.class);
if (opSet != null)
{
Contact c = opSet.findContactByID(contactID);
if (c != null)
{
MetaContact metaContact = GuiActivator.getContactListService()
.findMetaContactByContact(c);
if(metaContact == null)
{
logger.error(
"Chat not started. Cannot find metacontact for "
+ contactID + " and protocol:" + pps);
return;
}
startChat(metaContact, c, false);
return;
}
}
logger.error("Cannot start chat for " + contactID + " for "
+ pps.getAccountID().getAccountAddress());
}
public void startChat(String contactString, boolean isSmsEnabled)
{
List<ProtocolProviderService> imProviders
= AccountUtils.getRegisteredProviders(
OperationSetBasicInstantMessaging.class);
List<ProtocolProviderService> smsProviders
= AccountUtils.getRegisteredProviders(
OperationSetSmsMessaging.class);
if ((imProviders.size()
+ (smsProviders == null ? 0 : smsProviders.size())) < 1)
throw new IllegalStateException("No im or sms providers!");
Contact contact = null;
MetaContactListService metaContactListService
= GuiActivator.getContactListService();
MetaContact metaContact = null;
boolean startChat = false;
for (ProtocolProviderService imProvider : imProviders)
{
try
{
OperationSetPresence presenceOpSet
= imProvider.getOperationSet(OperationSetPresence.class);
if (presenceOpSet != null)
{
contact = presenceOpSet.findContactByID(contactString);
if (contact != null)
{
metaContact
= metaContactListService.findMetaContactByContact(
contact);
if (metaContact != null)
{
startChat = true;
break;
}
}
else
{
contact =
presenceOpSet.createUnresolvedContact(
contactString, null);
metaContact =
metaContactListService.findMetaContactByContact(
contact);
if (metaContact != null)
{
startChat = true;
break;
}
}
}
}
catch (Throwable t)
{
if (t instanceof ThreadDeath)
throw (ThreadDeath) t;
}
}
if (startChat)
startChat(metaContact, contact, isSmsEnabled);
else if(isSmsEnabled)
{
// nothing found but we want to send sms, lets check and create
// the contact as it may not exist
if(smsProviders == null || smsProviders.size() == 0)
return;
OperationSetSmsMessaging smsOpSet
= smsProviders.get(0)
.getOperationSet(OperationSetSmsMessaging.class);
contact = smsOpSet.getContact(contactString);
if (contact != null)
{
metaContact
= metaContactListService.findMetaContactByContact(contact);
if (metaContact != null)
{
startChat(metaContact, contact, true);
}
}
}
}
/**
* Removes the non read state of the currently selected chat session. This
* will result in removal of all icons representing the non read state (like
* envelopes in contact list).
*
* @param chatPanel the <tt>ChatPanel</tt> for which we would like to remove
* non read chat state
*/
public void removeNonReadChatState(ChatPanel chatPanel)
{
ChatSession chatSession = chatPanel.getChatSession();
if(chatSession instanceof MetaContactChatSession)
{
MetaContact selectedMetaContact
= (MetaContact) chatSession.getDescriptor();
TreeContactList clist
= GuiActivator.getContactList();
// Remove the envelope from the contact when the chat has
// gained the focus.
if(clist.isContactActive(selectedMetaContact))
{
clist.setActiveContact(selectedMetaContact, false);
}
chatPanel.fireChatFocusEvent(ChatFocusEvent.FOCUS_GAINED);
}
}
/**
* Closes the selected chat tab or the window if there are no tabs.
*
* @param chatPanel the chat panel to close.
*/
private void closeChatPanel(ChatPanel chatPanel)
{
ChatContainer chatContainer = chatPanel.getChatContainer();
if (chatContainer != null)
chatContainer.removeChat(chatPanel);
boolean isChatPanelContained;
synchronized (chatPanels)
{
isChatPanelContained = chatPanels.remove(chatPanel);
}
if (isChatPanelContained)
{
chatPanel.dispose();
fireChatClosed(chatPanel);
}
}
/**
* Gets the default <tt>Contact</tt> of the specified <tt>MetaContact</tt>
* if it is online; otherwise, gets one of its <tt>Contact</tt>s which
* supports offline messaging.
*
* @param metaContact the <tt>MetaContact</tt> to get the default
* <tt>Contact</tt> of
* @return the default <tt>Contact</tt> of the specified
* <tt>MetaContact</tt> if it is online; otherwise, gets one of its
* <tt>Contact</tt>s which supports offline messaging
*/
private Contact getDefaultContact(MetaContact metaContact)
{
Contact defaultContact = metaContact.getDefaultContact(
OperationSetBasicInstantMessaging.class);
if(defaultContact == null)
{
defaultContact = metaContact.getDefaultContact(
OperationSetSmsMessaging.class);
if(defaultContact == null)
return null;
}
ProtocolProviderService defaultProvider
= defaultContact.getProtocolProvider();
OperationSetBasicInstantMessaging defaultIM
= defaultProvider
.getOperationSet(OperationSetBasicInstantMessaging.class);
if (defaultContact.getPresenceStatus().getStatus() < 1
&& (!defaultIM.isOfflineMessagingSupported()
|| !defaultProvider.isRegistered()))
{
Iterator<Contact> protoContacts = metaContact.getContacts();
while(protoContacts.hasNext())
{
Contact contact = protoContacts.next();
ProtocolProviderService protoContactProvider
= contact.getProtocolProvider();
OperationSetBasicInstantMessaging protoContactIM
= protoContactProvider
.getOperationSet(
OperationSetBasicInstantMessaging.class);
if( protoContactIM != null
&& protoContactIM.isOfflineMessagingSupported()
&& protoContactProvider.isRegistered())
{
defaultContact = contact;
}
}
}
return defaultContact;
}
/**
* Creates a <tt>ChatPanel</tt> for the given contact and saves it in the
* list of created <tt>ChatPanel</tt>s.
*
* @param metaContact the <tt>MetaContact</tt> to create a
* <tt>ChatPanel</tt> for
* @param protocolContact the <tt>Contact</tt> (respectively its
* <tt>ChatTransport</tt>) to be selected in the newly created
* <tt>ChatPanel</tt>; <tt>null</tt> to select the default <tt>Contact</tt>
* of <tt>metaContact</tt> if it is online or one of its <tt>Contact</tt>s
* which supports offline messaging
* @param contactResource the <tt>ContactResource</tt>, to be selected in
* the newly created <tt>ChatPanel</tt>
* @param escapedMessageID the message ID of the message that should be
* excluded from the history when the last one is loaded in the chat.
* @return The <code>ChatPanel</code> newly created.
*/
private ChatPanel createChat( MetaContact metaContact,
Contact protocolContact,
ContactResource contactResource,
String escapedMessageID)
{
if (protocolContact == null)
protocolContact = getDefaultContact(metaContact);
if(protocolContact == null)
return null;
ChatContainer chatContainer = getChatContainer();
ChatPanel chatPanel = new ChatPanel(chatContainer);
MetaContactChatSession chatSession
= new MetaContactChatSession( chatPanel,
metaContact,
protocolContact,
contactResource);
chatPanel.setChatSession(chatSession);
synchronized (chatPanels)
{
this.chatPanels.add(chatPanel);
}
chatPanel.loadHistory(escapedMessageID);
fireChatCreated(chatPanel);
return chatPanel;
}
/**
* Gets a <tt>ChatContainer</tt> instance. If there is no existing
* <tt>ChatContainer</tt> or chats are configured to be displayed in their
* own windows instead of arranged in tabs in a single window, creates a
* new chat container.
*
* @return a <tt>ChatContainer</tt> instance
*/
private ChatContainer getChatContainer()
{
ChatContainer chatContainer
= GuiActivator.getUIService().getSingleWindowContainer();
// If we're in a single window mode we just return the chat container.
if (chatContainer != null)
return chatContainer;
// If we're in a multi-window mode we have two possibilities - multi
// chat window or single chat windows.
if (ConfigurationUtils.isMultiChatWindowEnabled())
{
Iterator<ChatPanel> chatPanelsIter = chatPanels.iterator();
/*
* If we're in a tabbed window we're looking for the chat window
* through one of the existing chats.
*/
if (chatPanelsIter.hasNext())
chatContainer = chatPanelsIter.next().getChatContainer();
else
{
chatContainer = new ChatWindow();
GuiActivator.getUIService().registerExportedWindow(
(ExportedWindow) chatContainer);
}
}
else
chatContainer = new ChatWindow();
return chatContainer;
}
/**
* Creates a <tt>ChatPanel</tt> for the given <tt>ChatRoom</tt> and saves it
* in the list of created <tt>ChatPanel</tt>s.
*
* @param chatRoomWrapper the <tt>ChatRoom</tt>, for which the chat will be
* created
* @return The <code>ChatPanel</code> newly created.
*/
private ChatPanel createChat(ChatRoomWrapper chatRoomWrapper)
{
return createChat(chatRoomWrapper, null);
}
/**
* Creates a <tt>ChatPanel</tt> for the given <tt>AdHocChatRoom</tt> and
* saves it in the list of created <tt>ChatPanel</tt>s.
*
* @param chatRoomWrapper the <tt>AdHocChatRoom</tt>, for which the chat
* will be created
* @return The <code>ChatPanel</code> newly created.
*/
private ChatPanel createChat(AdHocChatRoomWrapper chatRoomWrapper)
{
return createChat(chatRoomWrapper, null);
}
/**
* Creates a <tt>ChatPanel</tt> for the given <tt>ChatRoom</tt> and saves it
* in the list of created <tt>ChatPanel</tt>s.
*
* @param chatRoomWrapper the <tt>ChatRoom</tt>, for which the chat will be
* created
* @param escapedMessageID the message ID of the message that should be
* excluded from the history when the last one is loaded in the chat.
* @return The <code>ChatPanel</code> newly created.
*/
private ChatPanel createChat( ChatRoomWrapper chatRoomWrapper,
String escapedMessageID)
{
ChatContainer chatContainer = getChatContainer();
ChatPanel chatPanel = new ChatPanel(chatContainer);
ConferenceChatSession chatSession
= new ConferenceChatSession(chatPanel,
chatRoomWrapper);
chatPanel.setChatSession(chatSession);
synchronized (chatPanels)
{
this.chatPanels.add(chatPanel);
}
chatPanel.loadHistory(escapedMessageID);
fireChatCreated(chatPanel);
return chatPanel;
}
/**
* Creates a <tt>ChatPanel</tt> for the given <tt>AdHocChatRoom</tt> and
* saves it in the list of created <tt>ChatPanel</tt>s.
*
* @param chatRoomWrapper the <tt>AdHocChatRoom</tt>, for which the chat
* will be created
* @param escapedMessageID the message ID of the message that should be
* excluded from the history when the last one is loaded in the chat.
* @return The <code>ChatPanel</code> newly created.
*/
private ChatPanel createChat( AdHocChatRoomWrapper chatRoomWrapper,
String escapedMessageID)
{
ChatContainer chatContainer = getChatContainer();
ChatPanel chatPanel = new ChatPanel(chatContainer);
AdHocConferenceChatSession chatSession
= new AdHocConferenceChatSession(chatPanel, chatRoomWrapper);
chatPanel.setChatSession(chatSession);
synchronized (chatPanels)
{
this.chatPanels.add(chatPanel);
}
chatPanel.loadHistory(escapedMessageID);
fireChatCreated(chatPanel);
return chatPanel;
}
/**
* Finds the <tt>ChatPanel</tt> corresponding to the given chat descriptor.
*
* @param descriptor the chat descriptor.
* @return the <tt>ChatPanel</tt> corresponding to the given chat descriptor
* if any; otherwise, <tt>null</tt>
*/
private ChatPanel findChatPanelForDescriptor(Object descriptor)
{
for (ChatPanel chatPanel : chatPanels)
if (chatPanel.getChatSession().getDescriptor().equals(descriptor))
return chatPanel;
return null;
}
/**
* Notifies the <tt>ChatListener</tt>s registered with this instance that
* a specific <tt>Chat</tt> has been closed.
*
* @param chat the <tt>Chat</tt> which has been closed and which the
* <tt>ChatListener</tt>s registered with this instance are to be notified
* about
*/
private void fireChatClosed(Chat chat)
{
List <ChatListener> listeners;
synchronized (chatListeners)
{
listeners = new ArrayList<ChatListener>(chatListeners);
}
for(ChatListener listener : listeners)
listener.chatClosed(chat);
}
/**
* Notifies the <tt>ChatListener</tt>s registered with this instance that
* a specific <tt>Chat</tt> has been created.
*
* @param chat the <tt>Chat</tt> which has been created and which the
* <tt>ChatListener</tt>s registered with this instance are to be notified
* about
*/
private void fireChatCreated(Chat chat)
{
List <ChatListener> listeners;
synchronized (chatListeners)
{
listeners = new ArrayList<ChatListener>(chatListeners);
}
for(ChatListener listener : listeners)
listener.chatCreated(chat);
}
/**
* Returns <tt>true</tt> if this chat window contains the given chatPanel;
* <tt>false</tt>, otherwise.
*
* @param chatPanel the chat panel that we're looking for.
* @return <tt>true</tt> if this chat window contains the given chatPanel;
* <tt>false</tt>, otherwise
*/
private boolean containsChat(ChatPanel chatPanel)
{
synchronized (chatPanels)
{
return chatPanels.contains(chatPanel);
}
}
/**
* Runs the chat window for the specified contact
*/
private class RunChatWindow implements Runnable
{
private final MetaContact metaContact;
private final Contact protocolContact;
private final Boolean isSmsSelected;
/**
* Creates an instance of <tt>RunMessageWindow</tt> by specifying the
*
* @param metaContact the meta contact to which we will talk.
*/
public RunChatWindow(MetaContact metaContact)
{
this(metaContact, null);
}
/**
* Creates a chat window.
*
* @param metaContact the destination <tt>MetaContact</tt>
* @param protocolContact the destination protocol contact
*/
public RunChatWindow( MetaContact metaContact,
Contact protocolContact)
{
this(metaContact, protocolContact, null);
}
/**
* Creates a chat window
*
* @param metaContact the meta contact to which we will talk.
* @param protocolContact the destination protocol contact
* @param isSmsSelected whether the sms option should be selected
*/
public RunChatWindow( MetaContact metaContact,
Contact protocolContact,
Boolean isSmsSelected)
{
this.metaContact = metaContact;
this.protocolContact = protocolContact;
this.isSmsSelected = isSmsSelected;
}
/**
* Opens a chat window
*/
@Override
public void run()
{
ChatPanel chatPanel = getContactChat(metaContact, protocolContact);
if(chatPanel == null)
return;
// if not explicitly set, do not set it, leave it to default or
// internally make the decision
if(isSmsSelected != null)
chatPanel.setSmsSelected(isSmsSelected);
openChat(chatPanel, true);
}
}
/**
* Returns all currently instantiated <tt>ChatPanels</tt>.
* @return all instantiated <tt>ChatPanels</tt>
*/
public Collection <ChatPanel> getAllChats()
{
synchronized (chatSyncRoot)
{
return chatPanels;
}
}
/**
* Registers a <tt>NewChatListener</tt> to be informed when new <tt>Chats</tt>
* are created.
* @param listener listener to be registered
*/
public void addChatListener(ChatListener listener)
{
synchronized (chatListeners)
{
if (!chatListeners.contains(listener))
chatListeners.add(listener);
}
}
/**
* Removes the registration of a <tt>NewChatListener</tt>.
* @param listener listener to be unregistered
*/
public void removeChatListener(ChatListener listener)
{
synchronized (chatListeners)
{
chatListeners.remove(listener);
}
}
/**
* Displays a custom warning message.
*
* @param resourceString The resource name of the message to display.
* @param parentComponent Determines the Frame in which the dialog is
* displayed; if null, or if the parentComponent has no Frame, a default
* Frame is used
*
* @return The integer corresponding to the option choosen by the user.
*/
private static int showWarningMessage(
String resourceString,
Component parentComponent)
{
SIPCommMsgTextArea msgText
= new SIPCommMsgTextArea(
GuiActivator.getResources().getI18NString(resourceString));
JComponent textComponent = msgText;
if(OSUtils.IS_LINUX)
{
JScrollPane jScrollPane = new JScrollPane(msgText);
jScrollPane.setBorder(null);
textComponent = jScrollPane;
}
return JOptionPane.showConfirmDialog(
parentComponent,
textComponent,
GuiActivator.getResources().getI18NString(
"service.gui.WARNING"),
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.WARNING_MESSAGE);
}
/**
* Runnable used as base for all that creates chat panels.
*/
private abstract class AbstractChatPanelCreateRunnable
implements Runnable
{
/**
* The result panel.
*/
private ChatPanel chatPanel;
/**
* Returns the result chat panel.
* @return the result chat panel.
*/
public ChatPanel getChatPanel()
{
try
{
if(!SwingUtilities.isEventDispatchThread())
SwingUtilities.invokeAndWait(this);
else
this.run();
}
catch(Throwable t)
{
logger.warn("Cannot dispatch on event dispatch thread", t);
// if we cannot execute on event dispatch thread
this.run();
}
return chatPanel;
}
/**
* Runs on event dispatch thread.
*/
public void run()
{
chatPanel = createChatPanel();
}
/**
* The method that will create the panel.
* @return the result chat panel.
*/
protected abstract ChatPanel createChatPanel();
}
/**
* Creates/Obtains chat panel on swing event dispatch thread.
*/
private class MetaContactChatCreateRunnable
extends AbstractChatPanelCreateRunnable
{
/**
* The source meta contact.
*/
private final MetaContact metaContact;
/**
* The protocol contact used for creating chat panel.
*/
private final Contact protocolContact;
/**
* The contact resource, from which the message is sent.
*/
private final ContactResource contactResource;
/**
* The message ID of the message to be excluded from
* newly created chat panel.
*/
private final String escapedMessageID;
/**
* Creates a chat.
*
* @param metaContact the from meta contact
* @param protocolContact the from protocol contact
* @param contactResource the contact resource, from which the message
* is sent
* @param escapedMessageID the identifier of the escaped message
*/
private MetaContactChatCreateRunnable(MetaContact metaContact,
Contact protocolContact,
ContactResource contactResource,
String escapedMessageID)
{
this.metaContact = metaContact;
this.protocolContact = protocolContact;
this.contactResource = contactResource;
this.escapedMessageID = escapedMessageID;
}
/**
* Runs on event dispatch thread.
*/
@Override
protected ChatPanel createChatPanel()
{
return getContactChat(
metaContact,
protocolContact,
contactResource,
true,
this.escapedMessageID);
}
}
/**
* Creates chat room wrapper in event dispatch thread.
*/
private class CreateChatRoomWrapperRunner
extends AbstractChatPanelCreateRunnable
{
/**
* The source chat room.
*/
private ChatRoomWrapper chatRoomWrapper;
/**
* Constructs.
* @param chatRoomWrapper the <tt>ChatRoomWrapper</tt> to use
* for creating a panel.
*/
private CreateChatRoomWrapperRunner(ChatRoomWrapper chatRoomWrapper)
{
this.chatRoomWrapper = chatRoomWrapper;
}
/**
* Runs on event dispatch thread.
*/
@Override
protected ChatPanel createChatPanel()
{
return getMultiChatInternal(chatRoomWrapper, true);
}
}
/**
* Creates chat room wrapper in event dispatch thread.
*/
private class CreateAdHocChatRoomWrapperRunner
extends AbstractChatPanelCreateRunnable
{
/**
* The source chat room.
*/
private AdHocChatRoomWrapper chatRoomWrapper;
/**
* Constructs.
* @param chatRoomWrapper the <tt>AdHocChatRoom</tt>, for which
* the chat will be created.
*/
private CreateAdHocChatRoomWrapperRunner(
AdHocChatRoomWrapper chatRoomWrapper)
{
this.chatRoomWrapper = chatRoomWrapper;
}
/**
* Runs on event dispatch thread.
*/
@Override
protected ChatPanel createChatPanel()
{
return getMultiChatInternal(chatRoomWrapper, true);
}
}
/**
* Creates chat room in event dispatch thread.
*/
private class CreateChatRoomRunner
extends AbstractChatPanelCreateRunnable
{
/**
* The source chat room.
*/
private ChatRoom chatRoom;
private String escapedMessageID;
/**
* Constructs.
* @param chatRoom the <tt>ChatRoom</tt> used to create the
* corresponding <tt>ChatPanel</tt>.
*/
private CreateChatRoomRunner(ChatRoom chatRoom,
String escapedMessageID)
{
this.chatRoom = chatRoom;
this.escapedMessageID = escapedMessageID;
}
/**
* Runs on event dispatch thread.
*/
@Override
protected ChatPanel createChatPanel()
{
return getMultiChatInternal(chatRoom, true, escapedMessageID);
}
}
/**
* Creates chat room in event dispatch thread.
*/
private class CreateAdHocChatRoomRunner
extends AbstractChatPanelCreateRunnable
{
/**
* The source chat room.
*/
private AdHocChatRoom adHocChatRoom;
private String escapedMessageID;
/**
* Constructs.
* @param adHocChatRoom the <tt>AdHocChatRoom</tt> used to create
* the corresponding <tt>ChatPanel</tt>.
*/
private CreateAdHocChatRoomRunner(AdHocChatRoom adHocChatRoom,
String escapedMessageID)
{
this.adHocChatRoom = adHocChatRoom;
this.escapedMessageID = escapedMessageID;
}
/**
* Runs on event dispatch thread.
*/
@Override
protected ChatPanel createChatPanel()
{
return getMultiChatInternal(adHocChatRoom, true, escapedMessageID);
}
}
}