/** * Sets the mute status icon to the status panel. * * @param isMute indicates if the call with this peer is muted */ public void setMute(final boolean isMute) { if (!SwingUtilities.isEventDispatchThread()) { SwingUtilities.invokeLater( new Runnable() { public void run() { setMute(isMute); } }); return; } if (isMute) { muteStatusLabel.setIcon(new ImageIcon(ImageLoader.getImage(ImageLoader.MUTE_STATUS_ICON))); muteStatusLabel.setBorder(BorderFactory.createEmptyBorder(2, 3, 2, 3)); } else { muteStatusLabel.setIcon(null); muteStatusLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); } // Update input volume control button state to reflect the current // mute status. if (localLevel.isSelected() != isMute) localLevel.setSelected(isMute); this.revalidate(); this.repaint(); }
/** * Indicates that the security is timeouted, is not supported by the other end. * * @param evt Details about the event that caused this message. */ public void securityTimeout(final CallPeerSecurityTimeoutEvent evt) { if (!SwingUtilities.isEventDispatchThread()) { SwingUtilities.invokeLater( new Runnable() { public void run() { securityTimeout(evt); } }); return; } if (securityPanel != null) securityPanel.securityTimeout(evt); }
/** * Sets the name of the peer. * * @param name the name of the peer */ public void setPeerName(final String name) { if (!SwingUtilities.isEventDispatchThread()) { SwingUtilities.invokeLater( new Runnable() { public void run() { setPeerName(name); } }); return; } peerName = name; ((OneToOneCallPanel) callRenderer).setPeerName(name); }
/** * Updates this view i.e. <tt>OneToOneCallPeerPanel</tt> so that it depicts the current state of * its model i.e. <tt>callPeer</tt>. */ private void updateViewFromModel() { /* * We receive events/notifications from various threads and we respond * to them in the AWT event dispatching thread. It is possible to first * schedule an event to be brought to the AWT event dispatching thread, * then to have #dispose() invoked on this instance and, finally, to * receive the scheduled event in the AWT event dispatching thread. In * such a case, this disposed instance should not respond to the event * because it may, for example, steal a visual Components depicting * video (which cannot belong to more than one parent at a time) from * another non-disposed OneToOneCallPeerPanel. */ if (!disposed) { if (SwingUtilities.isEventDispatchThread()) updateViewFromModelInEventDispatchThread(); else { SwingUtilities.invokeLater(updateViewFromModelInEventDispatchThread); } } }
/** * Sets the reason of a call failure if one occurs. The renderer should display this reason to the * user. * * @param reason the reason to display */ public void setErrorReason(final String reason) { if (!SwingUtilities.isEventDispatchThread()) { SwingUtilities.invokeLater( new Runnable() { public void run() { setErrorReason(reason); } }); return; } if (errorMessageComponent == null) { errorMessageComponent = new JTextPane(); JTextPane textPane = (JTextPane) errorMessageComponent; textPane.setEditable(false); textPane.setOpaque(false); StyledDocument doc = textPane.getStyledDocument(); MutableAttributeSet standard = new SimpleAttributeSet(); StyleConstants.setAlignment(standard, StyleConstants.ALIGN_CENTER); StyleConstants.setFontFamily(standard, textPane.getFont().getFamily()); StyleConstants.setFontSize(standard, 12); doc.setParagraphAttributes(0, 0, standard, true); GridBagConstraints constraints = new GridBagConstraints(); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridx = 0; constraints.gridy = 4; constraints.weightx = 1; constraints.weighty = 0; constraints.insets = new Insets(5, 0, 0, 0); add(errorMessageComponent, constraints); this.revalidate(); } errorMessageComponent.setText(reason); if (isVisible()) errorMessageComponent.repaint(); }
/** * Sets the state of the contained call peer by specifying the state name. * * @param oldState the previous state of the peer * @param newState the new state of the peer * @param stateString the state of the contained call peer */ public void setPeerState( final CallPeerState oldState, final CallPeerState newState, final String stateString) { if (!SwingUtilities.isEventDispatchThread()) { SwingUtilities.invokeLater( new Runnable() { public void run() { setPeerState(oldState, newState, stateString); } }); return; } this.callStatusLabel.setText(stateString); if (newState == CallPeerState.CONNECTED && !CallPeerState.isOnHold(oldState) && !securityStatusLabel.isSecurityStatusSet()) { securityStatusLabel.setSecurityOff(); } }
/** * Indicates that the security has gone off. * * @param evt the <tt>CallPeerSecurityOffEvent</tt> that notified us */ public void securityOff(final CallPeerSecurityOffEvent evt) { if (!SwingUtilities.isEventDispatchThread()) { SwingUtilities.invokeLater( new Runnable() { public void run() { securityOff(evt); } }); return; } if (evt.getSessionType() == CallPeerSecurityOffEvent.AUDIO_SESSION) { securityStatusLabel.setText(""); securityStatusLabel.setSecurityOff(); if (securityStatusLabel.getBorder() == null) securityStatusLabel.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 3)); } securityPanel.securityOff(evt); }
/** * Sets the "on hold" property value. * * @param isOnHold indicates if the call with this peer is put on hold */ public void setOnHold(final boolean isOnHold) { if (!SwingUtilities.isEventDispatchThread()) { SwingUtilities.invokeLater( new Runnable() { public void run() { setOnHold(isOnHold); } }); return; } if (isOnHold) { holdStatusLabel.setIcon(new ImageIcon(ImageLoader.getImage(ImageLoader.HOLD_STATUS_ICON))); holdStatusLabel.setBorder(BorderFactory.createEmptyBorder(2, 3, 2, 3)); } else { holdStatusLabel.setIcon(null); holdStatusLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); } this.revalidate(); this.repaint(); }
/** * Re-dispatches glass pane mouse events only in case they occur on the security panel. * * @param glassPane the glass pane * @param e the mouse event in question */ private void redispatchMouseEvent(Component glassPane, MouseEvent e) { Point glassPanePoint = e.getPoint(); Point securityPanelPoint = SwingUtilities.convertPoint(glassPane, glassPanePoint, securityPanel); Component component; Point componentPoint; if (securityPanelPoint.y > 0) { component = securityPanel; componentPoint = securityPanelPoint; } else { Container contentPane = callRenderer.getCallContainer().getCallWindow().getFrame().getContentPane(); Point containerPoint = SwingUtilities.convertPoint(glassPane, glassPanePoint, contentPane); component = SwingUtilities.getDeepestComponentAt(contentPane, containerPoint.x, containerPoint.y); componentPoint = SwingUtilities.convertPoint(contentPane, glassPanePoint, component); } if (component != null) component.dispatchEvent( new MouseEvent( component, e.getID(), e.getWhen(), e.getModifiers(), componentPoint.x, componentPoint.y, e.getClickCount(), e.isPopupTrigger())); e.consume(); }
/** * Set the image of the peer * * @param image new image */ public void setPeerImage(byte[] image) { // If the image is still null we try to obtain it from one of the // available contact sources. if (image == null || image.length <= 0) { GuiActivator.getContactList().setSourceContactImage(peerName, photoLabel, 100, 100); } else { peerImage = ImageUtils.getScaledRoundedIcon(image, 100, 100); if (peerImage == null) peerImage = getPhotoLabelIcon(); if (!SwingUtilities.isEventDispatchThread()) { SwingUtilities.invokeLater( new Runnable() { public void run() { photoLabel.setIcon(peerImage); photoLabel.repaint(); } }); } else { photoLabel.setIcon(peerImage); photoLabel.repaint(); } } }
/** * 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 = OperationSetDesktopStreaming.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); }
/** * Shows/hides the security panel. * * @param isVisible <tt>true</tt> to show the security panel, <tt>false</tt> to hide it */ public void setSecurityPanelVisible(final boolean isVisible) { if (!SwingUtilities.isEventDispatchThread()) { SwingUtilities.invokeLater( new Runnable() { public void run() { setSecurityPanelVisible(isVisible); } }); return; } final JFrame callFrame = callRenderer.getCallContainer().getCallWindow().getFrame(); final JPanel glassPane = (JPanel) callFrame.getGlassPane(); if (!isVisible) { // Need to hide the security panel explicitly in order to keep the // fade effect. securityPanel.setVisible(false); glassPane.setVisible(false); glassPane.removeAll(); } else { glassPane.setLayout(null); glassPane.addMouseListener( new MouseListener() { public void mouseClicked(MouseEvent e) { redispatchMouseEvent(glassPane, e); } public void mouseEntered(MouseEvent e) { redispatchMouseEvent(glassPane, e); } public void mouseExited(MouseEvent e) { redispatchMouseEvent(glassPane, e); } public void mousePressed(MouseEvent e) { redispatchMouseEvent(glassPane, e); } public void mouseReleased(MouseEvent e) { redispatchMouseEvent(glassPane, e); } }); Point securityLabelPoint = securityStatusLabel.getLocation(); Point newPoint = SwingUtilities.convertPoint( securityStatusLabel.getParent(), securityLabelPoint.x, securityLabelPoint.y, callFrame); securityPanel.setBeginPoint(new Point((int) newPoint.getX() + 15, 0)); securityPanel.setBounds(0, (int) newPoint.getY() - 5, this.getWidth(), 130); glassPane.add(securityPanel); // Need to show the security panel explicitly in order to keep the // fade effect. securityPanel.setVisible(true); glassPane.setVisible(true); glassPane.addComponentListener( new ComponentAdapter() { /** Invoked when the component's size changes. */ @Override public void componentResized(ComponentEvent e) { if (glassPane.isVisible()) { glassPane.setVisible(false); callFrame.removeComponentListener(this); } } }); } }
/** * Indicates that the security is turned on. * * <p>Sets the secured status icon to the status panel and initializes/updates the corresponding * security details. * * @param evt Details about the event that caused this message. */ public void securityOn(final CallPeerSecurityOnEvent evt) { if (!SwingUtilities.isEventDispatchThread()) { SwingUtilities.invokeLater( new Runnable() { public void run() { securityOn(evt); } }); return; } // If the securityOn is called without a specific event, we'll just set // the security label status to on. if (evt == null) { securityStatusLabel.setSecurityOn(); return; } SrtpControl srtpControl = evt.getSecurityController(); if (!srtpControl.requiresSecureSignalingTransport() || callPeer.getProtocolProvider().isSignalingTransportSecure()) { if (srtpControl instanceof ZrtpControl) { securityStatusLabel.setText("zrtp"); if (!((ZrtpControl) srtpControl).isSecurityVerified()) securityStatusLabel.setSecurityPending(); else securityStatusLabel.setSecurityOn(); } else securityStatusLabel.setSecurityOn(); } // if we have some other panel, using other control if (!srtpControl.getClass().isInstance(securityPanel.getSecurityControl()) || (securityPanel instanceof ParanoiaTimerSecurityPanel)) { setSecurityPanelVisible(false); securityPanel = SecurityPanel.create(this, callPeer, srtpControl); if (srtpControl instanceof ZrtpControl) ((ZrtpSecurityPanel) securityPanel).setSecurityStatusLabel(securityStatusLabel); } securityPanel.securityOn(evt); boolean isSecurityLowPriority = Boolean.parseBoolean( GuiActivator.getResources() .getSettingsString("impl.gui.I_DONT_CARE_THAT_MUCH_ABOUT_SECURITY")); // Display ZRTP panel in case SAS was not verified or a AOR mismtach // was detected during creation of ZrtpSecurityPanel. // Don't show panel if user does not care about security at all. if (srtpControl instanceof ZrtpControl && !isSecurityLowPriority && (!((ZrtpControl) srtpControl).isSecurityVerified() || ((ZrtpSecurityPanel) securityPanel).isZidAorMismatch())) { setSecurityPanelVisible(true); } this.revalidate(); }
/** * 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); }