/* * 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.call; import java.awt.*; import java.awt.event.*; import java.beans.*; import javax.swing.*; import net.java.sip.communicator.impl.gui.*; import net.java.sip.communicator.plugin.desktoputil.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.util.Logger; import org.jitsi.util.*; import com.explodingpixels.macwidgets.*; /** * The <tt>CallPanel</tt> is the panel containing call information. It's created * and added to the main tabbed pane when user makes or receives calls. It shows * information about call peers, call duration, etc. * * @author Yana Stamcheva * @author Lyubomir Marinov * @author Adam Netocny */ public class OneToOneCallPanel extends TransparentPanel implements SwingCallRenderer, PropertyChangeListener { /** * Logger for the OneToOneCallPanel. */ private static final Logger logger = Logger.getLogger(OneToOneCallPanel.class); /** * Serial version UID. */ private static final long serialVersionUID = 0L; /** * The underlying <tt>Call</tt>, this panel is representing. */ private final Call call; /** * The parent call container. */ private final CallPanel callContainer; /** * The underlying <tt>CallPeer</tt>. */ private final CallPeer callPeer; /** * The check box allowing to turn on remote control when in a desktop * sharing session. */ private JCheckBox enableDesktopRemoteControl; /** * The component showing the name of the underlying call peer. */ private final JLabel nameLabel = new JLabel("", JLabel.CENTER); /** * The panel representing the underlying <tt>CallPeer</tt>. */ private OneToOneCallPeerPanel peerPanel; /** * The panel added on the south of this container. */ private JPanel southPanel; /** * The <tt>Component</tt> which is displayed at the top of this view and * contains {@link #nameLabel}. It is visible when this view is displayed in * windowed mode, it is not visible in full-screen mode. */ private JComponent topBar; /** * Initializes a new <tt>OneToOneCallPanel</tt> which is to depict a * one-to-one audio and/or video conversation of the local peer/user with a * specific remote <tt>CallPeer</tt> and which is to be used by a specific * <tt>CallPanel</tt> for that purpose. * * @param callContainer the <tt>CallPanel</tt> which requested the * initialization of the new instance and which is to use it to depict the * one-to-one audio and/or video conversation of the local peer/user with * the specified <tt>callPeer</tt> * @param callPeer the <tt>CallPeer</tt> whose one-to-one audio and/or video * conversation with the local peer/user is to be depicted by the new * instance * @param uiVideoHandler the utility which is to aid the new instance in * dealing with the video-related information */ public OneToOneCallPanel( CallPanel callContainer, CallPeer callPeer, UIVideoHandler2 uiVideoHandler) { super(new BorderLayout()); this.callContainer = callContainer; this.callPeer = callPeer; call = this.callPeer.getCall(); addCallPeerPanel(callPeer, uiVideoHandler); int preferredHeight = 400; if(GuiActivator.getConfigurationService().getBoolean( OneToOneCallPeerPanel.HIDE_PLACEHOLDER_PIC_PROP, false)) { preferredHeight = 128; } setPreferredSize(new Dimension(400, preferredHeight)); setTransferHandler(new CallTransferHandler(call)); this.callContainer.addPropertyChangeListener( CallContainer.PROP_FULL_SCREEN, this); } /** * Initializes and adds a new <tt>OneToOneCallPeerPanel</tt> instance which * is to depict a specific <tt>CallPeer</tt> on behalf of this instance. * * @param peer the <tt>CallPeer</tt> to be depicted by the new * <tt>OneToOneCallPeerPanel</tt> instance * @param uiVideoHandler the facility to aid the new instance in dealing * with the video-related information */ private void addCallPeerPanel(CallPeer peer, UIVideoHandler2 uiVideoHandler) { if (peerPanel == null) { // videoHandler.addVideoListener(callPeer); // videoHandler.addRemoteControlListener(callPeer); peerPanel = new OneToOneCallPeerPanel(this, peer, uiVideoHandler); /* Create the main Components of the UI. */ // use already obtained peer name to avoid double querying and // checking may result and // network search (ldap, various contact sources) nameLabel.setText( getPeerDisplayText(peer, peerPanel.getPeerName())); topBar = createTopComponent(); topBar.setVisible(!isFullScreen()); topBar.add(nameLabel); add(topBar, BorderLayout.NORTH); add(peerPanel); } } /** * Adds all desktop sharing related components to this container. */ public void addDesktopSharingComponents() { OperationSetDesktopSharingServer opSetDesktopSharingServer = callPeer.getProtocolProvider().getOperationSet( OperationSetDesktopSharingServer.class); if(opSetDesktopSharingServer != null && opSetDesktopSharingServer.isRemoteControlAvailable(callPeer)) { if (logger.isTraceEnabled()) logger.trace("Add desktop sharing related components."); if (enableDesktopRemoteControl == null) { enableDesktopRemoteControl = new JCheckBox( GuiActivator.getResources().getI18NString( "service.gui.ENABLE_DESKTOP_REMOTE_CONTROL")); southPanel = new TransparentPanel( new FlowLayout(FlowLayout.CENTER)); southPanel.add(enableDesktopRemoteControl); enableDesktopRemoteControl.setAlignmentX(CENTER_ALIGNMENT); enableDesktopRemoteControl.setOpaque(false); enableDesktopRemoteControl.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { CallManager.enableDesktopRemoteControl( callPeer, e.getStateChange() == ItemEvent.SELECTED); } }); } if (OSUtils.IS_MAC) { southPanel.setOpaque(true); southPanel.setBackground( new Color( GuiActivator.getResources().getColor( "service.gui.MAC_PANEL_BACKGROUND"))); } add(southPanel, BorderLayout.SOUTH); } revalidate(); repaint(); } /** * Creates the toolbar panel for this chat window, depending on the current * operating system. * * @return the created toolbar */ private JComponent createTopComponent() { JComponent topComponent = null; if (OSUtils.IS_MAC) { /* * The topBar is not visible in full-screen mode so * macPanelBackground does not interfere with the background set on * the ancestors in full-screen mode. */ Color macPanelBackground = new Color( GuiActivator.getResources().getColor( "service.gui.MAC_PANEL_BACKGROUND")); if (callContainer.getCallWindow() instanceof Window) { UnifiedToolBar macToolbarPanel = new UnifiedToolBar(); MacUtils.makeWindowLeopardStyle( callContainer.getCallWindow().getFrame().getRootPane()); macToolbarPanel.getComponent().setLayout(new BorderLayout()); macToolbarPanel.disableBackgroundPainter(); macToolbarPanel.installWindowDraggerOnWindow( callContainer.getCallWindow().getFrame()); topComponent = macToolbarPanel.getComponent(); } else { topComponent = new TransparentPanel(new BorderLayout()); topComponent.setOpaque(true); topComponent.setBackground(macPanelBackground); } /* * Set the background color of the center panel. However, that color * depends on whether this view is displayed on full-screen or * windowed mode (because it is common for full-screen mode to have * a black background). */ peerPanel.setOpaque(!isFullScreen()); peerPanel.setBackground(macPanelBackground); } else { JPanel panel = new TransparentPanel(new BorderLayout()); panel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3)); topComponent = panel; } return topComponent; } /** * {@inheritDoc} */ public void dispose() { callContainer.removePropertyChangeListener( CallContainer.PROP_FULL_SCREEN, this); if (peerPanel != null) peerPanel.dispose(); } /** * Returns the parent call container, where this renderer is contained. * @return the parent call container, where this renderer is contained */ public CallPanel getCallContainer() { return callContainer; } /** * Gets the <tt>CallPeer</tt> depicted by this instance. * * @return the <tt>CallPeer</tt> depicted by this instance */ public CallPeer getCallPeer() { return callPeer; } /** * Returns the <tt>CallPeerRenderer</tt> corresponding to the given * <tt>callPeer</tt>. * @param callPeer the <tt>CallPeer</tt>, for which we're looking for a * renderer * @return the <tt>CallPeerRenderer</tt> corresponding to the given * <tt>callPeer</tt> */ public SwingCallPeerRenderer getCallPeerRenderer(CallPeer callPeer) { return this.callPeer.equals(callPeer) ? peerPanel : null; } /** * A informative text to show for the peer. * @param peer the peer. * @return the text contain address and display name. */ private String getPeerDisplayText(CallPeer peer, String displayName) { String peerAddress = peer.getAddress(); if(StringUtils.isNullOrEmpty(displayName, true)) return peerAddress; if(!displayName.equalsIgnoreCase(peerAddress)) return displayName + " (" + peerAddress + ")"; return displayName; } /** * Determines whether this view is displayed in full-screen or windowed * mode. * * @return <tt>true</tt> if this view is displayed in full-screen mode or * <tt>false</tt> for windowed mode */ boolean isFullScreen() { return callContainer.isFullScreen(); } /** * Notifies this instance about a change in the value of a property of a * source which of interest to this instance. For example, * <tt>OneToOneCallPanel</tt> updates its user interface-related properties * upon changes in the value of the {@link CallContainer#PROP_FULL_SCREEN} * property of its associated {@link #callContainer}. * * @param ev a <tt>PropertyChangeEvent</tt> which identifies the source, the * name of the property and the old and new values */ public void propertyChange(PropertyChangeEvent ev) { String propertyName = ev.getPropertyName(); if (CallContainer.PROP_FULL_SCREEN.equals(propertyName) && callContainer.equals(ev.getSource())) { try { /* * Apply UI-related to Components which are explicitly owned by * this view or which this view tempers with. */ boolean fullScreen = isFullScreen(); if (topBar != null) topBar.setVisible(!fullScreen); if (OSUtils.IS_MAC && (peerPanel != null)) peerPanel.setOpaque(!fullScreen); } finally { /* * Fire the event as originating from this instance in order to * allow listeners to register with a source which is more * similar to them with respect to life span. */ firePropertyChange( propertyName, ev.getOldValue(), ev.getNewValue()); } } } /** * Removes all desktop sharing related components from this container. */ public void removeDesktopSharingComponents() { if (southPanel != null) { remove(southPanel); enableDesktopRemoteControl.setSelected(false); } revalidate(); repaint(); } /** * Sets the name of the peer. * @param name the name of the peer */ public void setPeerName(String name) { nameLabel.setText(getPeerDisplayText(callPeer, name)); } /** * Starts the timer that counts call duration. */ public void startCallTimer() { callContainer.startCallTimer(); } /** * Stops the timer that counts call duration. */ public void stopCallTimer() { callContainer.stopCallTimer(); } /** * Returns <code>true</code> if the call timer has been started, otherwise * returns <code>false</code>. * * @return <code>true</code> if the call timer has been started, otherwise * returns <code>false</code> */ public boolean isCallTimerStarted() { return callContainer.isCallTimerStarted(); } /** * Updates the state of the general hold button. The hold button is selected * only if all call peers are locally or mutually on hold at the same time. * In all other cases the hold button is unselected. */ public void updateHoldButtonState() { callContainer.updateHoldButtonState(); } }