示例#1
4
  /**
   * Called to indicate that sending typing notification has failed.
   *
   * @param evt a <tt>TypingNotificationEvent</tt> containing the sender of the notification and its
   *     type.
   */
  public void typingNotificationDeliveryFailed(TypingNotificationEvent evt) {
    if (typingTimer.isRunning()) typingTimer.stop();

    String notificationMsg = "";

    MetaContact metaContact =
        GuiActivator.getContactListService().findMetaContactByContact(evt.getSourceContact());
    String contactName = metaContact.getDisplayName();

    if (contactName.equals("")) {
      contactName = GuiActivator.getResources().getI18NString("service.gui.UNKNOWN") + " ";
    }

    ChatPanel chatPanel = chatWindowManager.getContactChat(metaContact, false);

    notificationMsg =
        GuiActivator.getResources()
            .getI18NString("service.gui.CONTACT_TYPING_SEND_FAILED", new String[] {contactName});

    // Proactive typing notification
    if (!chatWindowManager.isChatOpenedFor(metaContact)) {
      return;
    }

    if (chatPanel != null) chatPanel.addErrorSendingTypingNotification(notificationMsg);

    typingTimer.setMetaContact(metaContact);
    typingTimer.start();
  }
示例#2
0
  /**
   * Shows a warning message to the user when message delivery has failed.
   *
   * @param evt the event containing details on the message delivery failure
   */
  public void messageDeliveryFailed(MessageDeliveryFailedEvent evt) {
    logger.error(evt.getReason());

    String errorMsg = null;

    Message sourceMessage = (Message) evt.getSource();

    Contact sourceContact = evt.getDestinationContact();

    MetaContact metaContact =
        GuiActivator.getContactListService().findMetaContactByContact(sourceContact);

    if (evt.getErrorCode() == MessageDeliveryFailedEvent.OFFLINE_MESSAGES_NOT_SUPPORTED) {
      errorMsg =
          GuiActivator.getResources()
              .getI18NString(
                  "service.gui.MSG_DELIVERY_NOT_SUPPORTED",
                  new String[] {sourceContact.getDisplayName()});
    } else if (evt.getErrorCode() == MessageDeliveryFailedEvent.NETWORK_FAILURE) {
      errorMsg = GuiActivator.getResources().getI18NString("service.gui.MSG_NOT_DELIVERED");
    } else if (evt.getErrorCode() == MessageDeliveryFailedEvent.PROVIDER_NOT_REGISTERED) {
      errorMsg =
          GuiActivator.getResources().getI18NString("service.gui.MSG_SEND_CONNECTION_PROBLEM");
    } else if (evt.getErrorCode() == MessageDeliveryFailedEvent.INTERNAL_ERROR) {
      errorMsg =
          GuiActivator.getResources().getI18NString("service.gui.MSG_DELIVERY_INTERNAL_ERROR");
    } else {
      errorMsg = GuiActivator.getResources().getI18NString("service.gui.MSG_DELIVERY_ERROR");
    }

    String reason = evt.getReason();
    if (reason != null)
      errorMsg +=
          " "
              + GuiActivator.getResources()
                  .getI18NString("service.gui.ERROR_WAS", new String[] {reason});

    ChatPanel chatPanel = chatWindowManager.getContactChat(metaContact, sourceContact);

    chatPanel.addMessage(
        sourceContact.getAddress(),
        metaContact.getDisplayName(),
        new Date(),
        Chat.OUTGOING_MESSAGE,
        sourceMessage.getContent(),
        sourceMessage.getContentType(),
        sourceMessage.getMessageUID(),
        evt.getCorrectedMessageUID());

    chatPanel.addErrorMessage(metaContact.getDisplayName(), errorMsg);

    chatWindowManager.openChat(chatPanel, false);
  }
示例#3
0
  /**
   * Establishes a call.
   *
   * @param isVideo indicates if a video call should be established.
   * @param isDesktopSharing indicates if a desktopSharing should be established.
   */
  private void call(boolean isVideo, boolean isDesktopSharing) {
    ChatPanel chatPanel = chatContainer.getCurrentChat();

    ChatSession chatSession = chatPanel.getChatSession();

    Class<? extends OperationSet> opSetClass;
    if (isVideo) {
      if (isDesktopSharing) opSetClass = OperationSetDesktopSharingServer.class;
      else opSetClass = OperationSetVideoTelephony.class;
    } else opSetClass = OperationSetBasicTelephony.class;

    List<ChatTransport> telTransports = null;
    if (chatSession != null) telTransports = chatSession.getTransportsForOperationSet(opSetClass);

    List<ChatTransport> contactOpSetSupported;

    contactOpSetSupported = getOperationSetForCapabilities(telTransports, opSetClass);

    List<UIContactDetail> res = new ArrayList<UIContactDetail>();
    for (ChatTransport ct : contactOpSetSupported) {
      HashMap<Class<? extends OperationSet>, ProtocolProviderService> m =
          new HashMap<Class<? extends OperationSet>, ProtocolProviderService>();
      m.put(opSetClass, ct.getProtocolProvider());

      UIContactDetailImpl d =
          new UIContactDetailImpl(
              ct.getName(), ct.getDisplayName(), null, null, null, m, null, ct.getName());
      PresenceStatus status = ct.getStatus();
      byte[] statusIconBytes = status.getStatusIcon();

      if (statusIconBytes != null && statusIconBytes.length > 0) {
        d.setStatusIcon(
            new ImageIcon(
                ImageLoader.getIndexedProtocolImage(
                    ImageUtils.getBytesInImage(statusIconBytes), ct.getProtocolProvider())));
      }

      res.add(d);
    }

    Point location = new Point(callButton.getX(), callButton.getY() + callButton.getHeight());

    SwingUtilities.convertPointToScreen(location, this);

    MetaContact metaContact = GuiActivator.getUIService().getChatContact(chatPanel);
    UIContactImpl uiContact = null;
    if (metaContact != null) uiContact = MetaContactListSource.getUIContact(metaContact);

    CallManager.call(res, uiContact, isVideo, isDesktopSharing, callButton, location);
  }
示例#4
0
  /**
   * Informs the user what is the typing state of his chat contacts.
   *
   * @param evt the event containing details on the typing notification
   */
  public void typingNotificationReceived(TypingNotificationEvent evt) {
    if (typingTimer.isRunning()) typingTimer.stop();

    String notificationMsg = "";

    MetaContact metaContact =
        GuiActivator.getContactListService().findMetaContactByContact(evt.getSourceContact());
    String contactName = metaContact.getDisplayName() + " ";

    if (contactName.equals("")) {
      contactName = GuiActivator.getResources().getI18NString("service.gui.UNKNOWN") + " ";
    }

    int typingState = evt.getTypingState();

    ChatPanel chatPanel = chatWindowManager.getContactChat(metaContact, false);

    if (typingState == OperationSetTypingNotifications.STATE_TYPING) {
      notificationMsg =
          GuiActivator.getResources()
              .getI18NString("service.gui.CONTACT_TYPING", new String[] {contactName});

      // Proactive typing notification
      if (!chatWindowManager.isChatOpenedFor(metaContact)) {
        return;
      }

      if (chatPanel != null) chatPanel.addTypingNotification(notificationMsg);

      typingTimer.setMetaContact(metaContact);
      typingTimer.start();
    } else if (typingState == OperationSetTypingNotifications.STATE_PAUSED) {
      notificationMsg =
          GuiActivator.getResources()
              .getI18NString("service.gui.CONTACT_PAUSED_TYPING", new String[] {contactName});

      if (chatPanel != null) chatPanel.addTypingNotification(notificationMsg);

      typingTimer.setMetaContact(metaContact);
      typingTimer.start();
    } else {
      if (chatPanel != null) chatPanel.removeTypingNotification();
    }
  }
示例#5
0
  /**
   * Disables/Enables history arrow buttons depending on whether the current page is the first, the
   * last page or a middle page.
   *
   * @param chatPanel the <tt>ChatPanel</tt> which has provoked the change.
   */
  public void changeHistoryButtonsState(ChatPanel chatPanel) {
    ChatConversationPanel convPanel = chatPanel.getChatConversationPanel();

    long firstMsgInHistory = chatPanel.getFirstHistoryMsgTimestamp().getTime();
    long lastMsgInHistory = chatPanel.getLastHistoryMsgTimestamp().getTime();
    Date firstMsgInPage = convPanel.getPageFirstMsgTimestamp();
    Date lastMsgInPage = convPanel.getPageLastMsgTimestamp();

    if (firstMsgInHistory == 0 || lastMsgInHistory == 0) {
      previousButton.setEnabled(false);
      nextButton.setEnabled(false);
      return;
    }

    previousButton.setEnabled(firstMsgInHistory < firstMsgInPage.getTime());

    nextButton.setEnabled(
        (lastMsgInPage.getTime() > 0) && (lastMsgInHistory > lastMsgInPage.getTime()));
  }
示例#6
0
  /**
   * When a sent message is delivered shows it in the chat conversation panel.
   *
   * @param evt the event containing details on the message delivery
   */
  public void messageDelivered(MessageDeliveredEvent evt) {
    Contact contact = evt.getDestinationContact();
    MetaContact metaContact =
        GuiActivator.getContactListService().findMetaContactByContact(contact);

    if (logger.isTraceEnabled())
      logger.trace("MESSAGE DELIVERED to contact: " + contact.getAddress());

    ChatPanel chatPanel = chatWindowManager.getContactChat(metaContact, false);

    if (chatPanel != null) {
      Message msg = evt.getSourceMessage();
      ProtocolProviderService protocolProvider = contact.getProtocolProvider();

      if (logger.isTraceEnabled())
        logger.trace(
            "MESSAGE DELIVERED: process message to chat for contact: "
                + contact.getAddress()
                + " MESSAGE: "
                + msg.getContent());

      chatPanel.addMessage(
          this.mainFrame.getAccountAddress(protocolProvider),
          this.mainFrame.getAccountDisplayName(protocolProvider),
          evt.getTimestamp(),
          Chat.OUTGOING_MESSAGE,
          msg.getContent(),
          msg.getContentType(),
          msg.getMessageUID(),
          evt.getCorrectedMessageUID());

      if (evt.isSmsMessage() && !ConfigurationUtils.isSmsNotifyTextDisabled()) {
        chatPanel.addMessage(
            contact.getDisplayName(),
            new Date(),
            Chat.ACTION_MESSAGE,
            GuiActivator.getResources().getI18NString("service.gui.SMS_SUCCESSFULLY_SENT"),
            "text");
      }
    }
  }
示例#7
0
  /**
   * Implements ChatChangeListener#chatChanged(ChatPanel).
   *
   * @param chatPanel the <tt>ChatPanel</tt>, which changed
   */
  public void chatChanged(ChatPanel chatPanel) {
    if (chatPanel == null) {
      setChatSession(null);
    } else {
      MetaContact contact = GuiActivator.getUIService().getChatContact(chatPanel);

      for (PluginComponent c : pluginContainer.getPluginComponents()) c.setCurrentContact(contact);

      ChatSession chatSession = chatPanel.getChatSession();
      setChatSession(chatSession);

      leaveChatRoomButton.setEnabled(chatSession instanceof ConferenceChatSession);

      desktopSharingButton.setEnabled(!(chatSession instanceof ConferenceChatSession));

      inviteButton.setEnabled(chatPanel.findInviteChatTransport() != null);

      sendFileButton.setEnabled(chatPanel.findFileTransferChatTransport() != null);
      inviteButton.setEnabled(!chatPanel.isPrivateMessagingChat());

      if (chatSession instanceof ConferenceChatSession) {
        updateInviteContactButton();

        callButton.setVisible(false);
        callVideoButton.setVisible(false);
        callButton.setEnabled(true);
        callVideoButton.setEnabled(true);
      } else if (contact != null) {
        callButton.setVisible(true);
        callVideoButton.setVisible(true);
        new UpdateCallButtonWorker(contact).start();
      }

      changeHistoryButtonsState(chatPanel);

      setCallButtonsName();
      setCallButtonsIcons();

      currentChatTransportChanged(chatSession);
    }
  }
示例#8
0
  /**
   * Implements ChatChangeListener#chatChanged(ChatPanel).
   *
   * @param chatPanel the <tt>ChatPanel</tt>, which changed
   */
  public void chatChanged(ChatPanel chatPanel) {
    if (chatPanel == null) {
      setChatSession(null);
    } else {
      MetaContact contact = GuiActivator.getUIService().getChatContact(chatPanel);

      for (PluginComponent c : pluginContainer.getPluginComponents()) c.setCurrentContact(contact);

      setChatSession(chatPanel.chatSession);

      leaveChatRoomButton.setEnabled(chatPanel.chatSession instanceof ConferenceChatSession);

      inviteButton.setEnabled(chatPanel.findInviteChatTransport() != null);

      sendFileButton.setEnabled(chatPanel.findFileTransferChatTransport() != null);

      new UpdateCallButtonWorker(contact).start();

      changeHistoryButtonsState(chatPanel);
    }
  }
示例#9
0
  /**
   * When a request has been received we show it to the user through the chat session renderer.
   *
   * @param event <tt>FileTransferRequestEvent</tt>
   * @see FileTransferListener#fileTransferRequestReceived(FileTransferRequestEvent)
   */
  public void fileTransferRequestReceived(FileTransferRequestEvent event) {
    IncomingFileTransferRequest request = event.getRequest();

    Contact sourceContact = request.getSender();

    MetaContact metaContact =
        GuiActivator.getContactListService().findMetaContactByContact(sourceContact);

    final ChatPanel chatPanel = chatWindowManager.getContactChat(metaContact, sourceContact);

    chatPanel.addIncomingFileTransferRequest(
        event.getFileTransferOperationSet(), request, event.getTimestamp());

    ChatTransport chatTransport =
        chatPanel.getChatSession().findChatTransportForDescriptor(sourceContact, null);

    chatPanel.setSelectedChatTransport(chatTransport, true);

    // Opens the chat panel with the new message in the UI thread.
    chatWindowManager.openChat(chatPanel, false);
  }
示例#10
0
  /**
   * Handles the <tt>ActionEvent</tt>, when one of the tool bar buttons is clicked.
   *
   * @param e the <tt>ActionEvent</tt> that notified us
   */
  public void actionPerformed(ActionEvent e) {
    AbstractButton button = (AbstractButton) e.getSource();
    String buttonText = button.getName();

    ChatPanel chatPanel = chatContainer.getCurrentChat();

    if (buttonText.equals("previous")) {
      chatPanel.loadPreviousPageFromHistory();
    } else if (buttonText.equals("next")) {
      chatPanel.loadNextPageFromHistory();
    } else if (buttonText.equals("sendFile")) {
      SipCommFileChooser scfc =
          GenericFileDialog.create(
              null,
              "Send file...",
              SipCommFileChooser.LOAD_FILE_OPERATION,
              ConfigurationUtils.getSendFileLastDir());
      File selectedFile = scfc.getFileFromDialog();
      if (selectedFile != null) {
        ConfigurationUtils.setSendFileLastDir(selectedFile.getParent());
        chatContainer.getCurrentChat().sendFile(selectedFile);
      }
    } else if (buttonText.equals("invite")) {
      ChatInviteDialog inviteDialog = new ChatInviteDialog(chatPanel);

      inviteDialog.setVisible(true);
    } else if (buttonText.equals("leave")) {
      ChatRoomWrapper chatRoomWrapper =
          (ChatRoomWrapper) chatPanel.getChatSession().getDescriptor();
      ChatRoomWrapper leavedRoomWrapped =
          GuiActivator.getMUCService().leaveChatRoom(chatRoomWrapper);
    } else if (buttonText.equals("call")) {
      call(false, false);
    } else if (buttonText.equals("callVideo")) {
      call(true, false);
    } else if (buttonText.equals("desktop")) {
      call(true, true);
    } else if (buttonText.equals("options")) {
      GuiActivator.getUIService().getConfigurationContainer().setVisible(true);
    } else if (buttonText.equals("font")) chatPanel.showFontChooserDialog();
    else if (buttonText.equals("createConference")) {
      chatPanel.showChatConferenceDialog();
    }
  }
示例#11
0
  /**
   * Handles the <tt>ActionEvent</tt>, when one of the tool bar buttons is clicked.
   *
   * @param e the <tt>ActionEvent</tt> that notified us
   */
  public void actionPerformed(ActionEvent e) {
    AbstractButton button = (AbstractButton) e.getSource();
    String buttonText = button.getName();

    ChatPanel chatPanel = chatContainer.getCurrentChat();

    if (buttonText.equals("previous")) {
      chatPanel.loadPreviousPageFromHistory();
    } else if (buttonText.equals("next")) {
      chatPanel.loadNextPageFromHistory();
    } else if (buttonText.equals("sendFile")) {
      SipCommFileChooser scfc =
          GenericFileDialog.create(
              null,
              "Send file...",
              SipCommFileChooser.LOAD_FILE_OPERATION,
              ConfigurationUtils.getSendFileLastDir());
      File selectedFile = scfc.getFileFromDialog();
      if (selectedFile != null) {
        ConfigurationUtils.setSendFileLastDir(selectedFile.getParent());
        chatContainer.getCurrentChat().sendFile(selectedFile);
      }
    } else if (buttonText.equals("history")) {
      HistoryWindow history;

      HistoryWindowManager historyWindowManager =
          GuiActivator.getUIService().getHistoryWindowManager();

      ChatSession chatSession = chatPanel.getChatSession();

      if (historyWindowManager.containsHistoryWindowForContact(chatSession.getDescriptor())) {
        history = historyWindowManager.getHistoryWindowForContact(chatSession.getDescriptor());

        if (history.getState() == JFrame.ICONIFIED) history.setState(JFrame.NORMAL);

        history.toFront();
      } else {
        history = new HistoryWindow(chatPanel.getChatSession().getDescriptor());

        history.setVisible(true);

        historyWindowManager.addHistoryWindowForContact(chatSession.getDescriptor(), history);
      }
    } else if (buttonText.equals("invite")) {
      ChatInviteDialog inviteDialog = new ChatInviteDialog(chatPanel);

      inviteDialog.setVisible(true);
    } else if (buttonText.equals("leave")) {
      ConferenceChatManager conferenceManager =
          GuiActivator.getUIService().getConferenceChatManager();
      conferenceManager.leaveChatRoom((ChatRoomWrapper) chatPanel.getChatSession().getDescriptor());
    } else if (buttonText.equals("call")) {
      call(false, false);
    } else if (buttonText.equals("callVideo")) {
      call(true, false);
    } else if (buttonText.equals("desktop")) {
      call(true, true);
    } else if (buttonText.equals("options")) {
      GuiActivator.getUIService().getConfigurationContainer().setVisible(true);
    } else if (buttonText.equals("font")) chatPanel.showFontChooserDialog();
  }
示例#12
0
  /** Initializes this component. */
  protected void init() {
    this.setLayout(new FlowLayout(FlowLayout.LEFT, 3, 0));
    this.setOpaque(false);

    this.add(inviteButton);

    // if we leave a chat room when we close the window
    // there is no need for this button
    if (!ConfigurationUtils.isLeaveChatRoomOnWindowCloseEnabled()) this.add(leaveChatRoomButton);

    this.add(callButton);
    this.add(callVideoButton);
    this.add(desktopSharingButton);
    this.add(sendFileButton);

    ChatPanel chatPanel = chatContainer.getCurrentChat();
    if (chatPanel == null || !(chatPanel.getChatSession() instanceof MetaContactChatSession))
      sendFileButton.setEnabled(false);

    this.addSeparator();

    this.add(historyButton);
    this.add(previousButton);
    this.add(nextButton);

    // We only add the options button if the property SHOW_OPTIONS_WINDOW
    // specifies so or if it's not set.
    Boolean showOptionsProp =
        GuiActivator.getConfigurationService()
            .getBoolean(ConfigurationFrame.SHOW_OPTIONS_WINDOW_PROPERTY, false);

    if (showOptionsProp.booleanValue()) {
      this.add(optionsButton);
    }

    this.addSeparator();

    if (ConfigurationUtils.isFontSupportEnabled()) {
      this.add(fontButton);
      fontButton.setName("font");
      fontButton.setToolTipText(
          GuiActivator.getResources().getI18NString("service.gui.CHANGE_FONT"));
      fontButton.addActionListener(this);
    }

    initSmiliesSelectorBox();

    this.addSeparator();

    this.inviteButton.setName("invite");
    this.inviteButton.setToolTipText(
        GuiActivator.getResources().getI18NString("service.gui.INVITE"));

    this.leaveChatRoomButton.setName("leave");
    this.leaveChatRoomButton.setToolTipText(
        GuiActivator.getResources().getI18NString("service.gui.LEAVE"));

    this.callButton.setName("call");
    this.callButton.setToolTipText(
        GuiActivator.getResources().getI18NString("service.gui.CALL_CONTACT"));

    this.callVideoButton.setName("callVideo");
    this.callVideoButton.setToolTipText(
        GuiActivator.getResources().getI18NString("service.gui.CALL_CONTACT"));

    this.desktopSharingButton.setName("desktop");
    this.desktopSharingButton.setToolTipText(
        GuiActivator.getResources().getI18NString("service.gui.SHARE_DESKTOP_WITH_CONTACT"));

    this.historyButton.setName("history");
    this.historyButton.setToolTipText(
        GuiActivator.getResources().getI18NString("service.gui.HISTORY") + " Ctrl-H");

    optionsButton.setName("options");
    optionsButton.setToolTipText(GuiActivator.getResources().getI18NString("service.gui.OPTIONS"));

    this.sendFileButton.setName("sendFile");
    this.sendFileButton.setToolTipText(
        GuiActivator.getResources().getI18NString("service.gui.SEND_FILE"));

    this.previousButton.setName("previous");
    this.previousButton.setToolTipText(
        GuiActivator.getResources().getI18NString("service.gui.PREVIOUS"));

    this.nextButton.setName("next");
    this.nextButton.setToolTipText(GuiActivator.getResources().getI18NString("service.gui.NEXT"));

    inviteButton.addActionListener(this);
    leaveChatRoomButton.addActionListener(this);
    callButton.addActionListener(this);
    callVideoButton.addActionListener(this);
    desktopSharingButton.addActionListener(this);
    historyButton.addActionListener(this);
    optionsButton.addActionListener(this);
    sendFileButton.addActionListener(this);
    previousButton.addActionListener(this);
    nextButton.addActionListener(this);
  }
示例#13
0
      public void actionPerformed(ActionEvent e) {
        ChatPanel chatPanel = chatWindowManager.getContactChat(metaContact, false);

        if (chatPanel != null) chatPanel.removeTypingNotification();
      }
示例#14
0
  /**
   * When a message is received determines whether to open a new chat window or chat window tab, or
   * to indicate that a message is received from a contact which already has an open chat. When the
   * chat is found checks if in mode "Auto popup enabled" and if this is the case shows the message
   * in the appropriate chat panel.
   *
   * @param protocolContact the source contact of the event
   * @param contactResource the resource from which the contact is writing
   * @param metaContact the metacontact containing <tt>protocolContact</tt>
   * @param message the message to deliver
   * @param eventType the event type
   * @param timestamp the timestamp of the event
   * @param correctedMessageUID the identifier of the corrected message
   * @param isPrivateMessaging if <tt>true</tt> the message is received from private messaging
   *     contact.
   * @param privateContactRoom the chat room associated with the private messaging contact.
   */
  private void messageReceived(
      final Contact protocolContact,
      final ContactResource contactResource,
      final MetaContact metaContact,
      final Message message,
      final int eventType,
      final Date timestamp,
      final String correctedMessageUID,
      final boolean isPrivateMessaging,
      final ChatRoom privateContactRoom) {
    if (!SwingUtilities.isEventDispatchThread()) {
      SwingUtilities.invokeLater(
          new Runnable() {
            public void run() {
              messageReceived(
                  protocolContact,
                  contactResource,
                  metaContact,
                  message,
                  eventType,
                  timestamp,
                  correctedMessageUID,
                  isPrivateMessaging,
                  privateContactRoom);
            }
          });
      return;
    }

    // Obtain the corresponding chat panel.
    final ChatPanel chatPanel =
        chatWindowManager.getContactChat(
            metaContact, protocolContact, contactResource, message.getMessageUID());

    // Show an envelope on the sender contact in the contact list and
    // in the systray.
    if (!chatPanel.isChatFocused()) contactList.setActiveContact(metaContact, true);

    // Distinguish the message type, depending on the type of event that
    // we have received.
    String messageType = null;

    if (eventType == MessageReceivedEvent.CONVERSATION_MESSAGE_RECEIVED) {
      messageType = Chat.INCOMING_MESSAGE;
    } else if (eventType == MessageReceivedEvent.SYSTEM_MESSAGE_RECEIVED) {
      messageType = Chat.SYSTEM_MESSAGE;
    } else if (eventType == MessageReceivedEvent.SMS_MESSAGE_RECEIVED) {
      messageType = Chat.SMS_MESSAGE;
    }

    String contactAddress =
        (contactResource != null)
            ? protocolContact.getAddress() + " (" + contactResource.getResourceName() + ")"
            : protocolContact.getAddress();

    chatPanel.addMessage(
        contactAddress,
        protocolContact.getDisplayName(),
        timestamp,
        messageType,
        message.getContent(),
        message.getContentType(),
        message.getMessageUID(),
        correctedMessageUID);

    String resourceName = (contactResource != null) ? contactResource.getResourceName() : null;

    if (isPrivateMessaging) {
      chatWindowManager.openPrivateChatForChatRoomMember(privateContactRoom, protocolContact);
    } else {
      chatWindowManager.openChat(chatPanel, false);
    }

    ChatTransport chatTransport =
        chatPanel.getChatSession().findChatTransportForDescriptor(protocolContact, resourceName);

    chatPanel.setSelectedChatTransport(chatTransport, true);
  }