/** * $RCSfile: ,v $ * $Revision: $ * $Date: $ * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * 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 org.jivesoftware.sparkplugin.ui.call; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.text.SimpleDateFormat; import java.util.Date; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import net.java.sipmack.sip.Call; import net.java.sipmack.sip.InterlocutorUI; import net.java.sipmack.softphone.SoftPhoneManager; import net.java.sipmack.softphone.SoftPhoneManager.CallRoomState; import org.jivesoftware.spark.ChatManager; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.plugin.phone.resource.PhoneRes; import org.jivesoftware.spark.ui.ChatRoom; import org.jivesoftware.spark.util.ModelUtil; import org.jivesoftware.spark.util.SwingWorker; import org.jivesoftware.spark.util.log.Log; import org.jivesoftware.sparkplugin.components.CallPanelButton; import org.jivesoftware.sparkplugin.components.EndCallButton; import org.jivesoftware.sparkplugin.components.RedialButton; import org.jivesoftware.sparkplugin.ui.PhonePad; import org.jivesoftware.sparkplugin.ui.components.ControlPanel; import org.jivesoftware.sparkplugin.ui.components.JavaMixer; import org.jivesoftware.sparkplugin.ui.transfer.TransferManager; /** * The UI to represent a phone call. * * @author Derek DeMoro */ public class NonRosterPanel extends PhonePanel { private static final long serialVersionUID = -1826003278845440442L; private JLabel connectedLabel; private String phoneNumber; private PreviousConversationPanel historyPanel; private boolean onHold; private boolean muted; private CallPanelButton muteButton; private CallPanelButton holdButton; private CallPanelButton transferButton; private EndCallButton hangUpButton; private RedialButton redialButton; private SoftPhoneManager softPhone; private String CONNECTED = PhoneRes.getIString("phone.connected"); private InterlocutorUI activeCall; private CallManager callManager; private boolean callWasTransferred; private boolean uiBuilt; private JavaMixer mixer = new JavaMixer(); public NonRosterPanel() { setLayout(new GridBagLayout()); setBorder(BorderFactory.createLineBorder(Color.lightGray)); callManager = CallManager.getInstance(); // Initilize mixer. softPhone = SoftPhoneManager.getInstance(); } public JPanel buildTopPanel() { final JLabel avatarLabel = new JLabel(PhoneRes.getImageIcon("LARGE_PHONE_ICON")); final JLabel nameLabel = new JLabel(); nameLabel.setFont(new Font("Arial", Font.BOLD, 19)); nameLabel.setForeground(new Color(64, 103, 162)); String remoteName = getActiveCall().getCall().getRemoteName(); nameLabel.setText(remoteName); final JPanel topPanel = new JPanel(); topPanel.setOpaque(false); topPanel.setLayout(new GridBagLayout()); // Add Connected Label connectedLabel = new JLabel(CONNECTED); connectedLabel.setFont(new Font("Arial", Font.BOLD, 16)); connectedLabel.setForeground(greenColor); // Add All Items to Top Panel topPanel.add(avatarLabel, new GridBagConstraints(0, 0, 1, 2, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); topPanel.add(nameLabel, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); topPanel.add(connectedLabel, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); topPanel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.lightGray)); return topPanel; } /** * Builds the Control Panel. * * @return the control panel. */ private JPanel buildMiddlePanel() { // Add Control Panel final JPanel mainPanel = new JPanel(new GridBagLayout()) { private static final long serialVersionUID = 1571929852761037052L; public Dimension getPreferredSize() { final Dimension dim = super.getPreferredSize(); dim.height = 100; return dim; } }; mainPanel.setOpaque(false); // Add Input Volume To Control Panel try { final ControlPanel inputPanel = new ControlPanel(new GridBagLayout()); final JLabel inputIcon = new JLabel(PhoneRes.getImageIcon("MICROPHONE_IMAGE")); inputPanel.add(mixer.getPrefferedInputVolume(), new GridBagConstraints(0, 0, 1, 1, 0.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.VERTICAL, new Insets(2, 2, 2, 2), 0, 0)); inputPanel.add(inputIcon, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); mainPanel.add(inputPanel, new GridBagConstraints(0, 0, 1, 1, 0.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.VERTICAL, new Insets(2, 1, 2, 1), 0, 0)); } catch (Exception e) { Log.error(e); } try { // Add Output Volume To Control Panel final ControlPanel outputPanel = new ControlPanel(new GridBagLayout()); final JLabel outputIcon = new JLabel(PhoneRes.getImageIcon("SPEAKER_IMAGE")); Component component = mixer.getPrefferedMasterVolume(); if (component != null) outputPanel.add(component, new GridBagConstraints(0, 0, 1, 1, 0.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.VERTICAL, new Insets(2, 2, 2, 2), 0, 0)); outputPanel.add(outputIcon, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0)); mainPanel.add(outputPanel, new GridBagConstraints(1, 0, 1, 1, 0.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.VERTICAL, new Insets(2, 1, 2, 5), 0, 0)); } catch (Exception e) { Log.error(e); } // Build ControlPanel List final JPanel controlPanel = new JPanel(new GridBagLayout()); controlPanel.setOpaque(false); muteButton = new CallPanelButton(PhoneRes.getImageIcon("MUTE_IMAGE").getImage(), PhoneRes.getIString("phone.mute")); muteButton.setToolTipText(PhoneRes.getIString("phone.tips.mute")); controlPanel.add(muteButton, new GridBagConstraints(0, 0, 1, 1, 0.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(2, 2, 2, 2), 0, 0)); holdButton = new CallPanelButton(PhoneRes.getImageIcon("ON_HOLD_IMAGE").getImage(), PhoneRes.getIString("phone.hold")); holdButton.setToolTipText(PhoneRes.getIString("phone.tips.hold")); controlPanel.add(holdButton, new GridBagConstraints(1, 0, 1, 1, 0.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(2, 2, 2, 2), 0, 0)); transferButton = new CallPanelButton(PhoneRes.getImageIcon("TRANSFER_IMAGE").getImage(), PhoneRes.getIString("phone.transfer")); transferButton.setToolTipText(PhoneRes.getIString("phone.tips.transfer")); controlPanel.add(transferButton, new GridBagConstraints(2, 0, 1, 1, 0.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(2, 2, 2, 2), 0, 0)); // Add End Call button hangUpButton = new EndCallButton(); redialButton = new RedialButton(); redialButton.setVisible(false); // Add Components to Main Panel mainPanel.add(controlPanel, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(2, 1, 2, 1), 0, 0)); mainPanel.add(hangUpButton, new GridBagConstraints(3, 0, 1, 1, 1.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(2, 1, 2, 1), 0, 0)); mainPanel.add(redialButton, new GridBagConstraints(3, 0, 1, 1, 1.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(2, 1, 2, 1), 0, 0)); return mainPanel; } public void setInterlocutorUI(final InterlocutorUI interlocutorUI) { this.activeCall = interlocutorUI; // Set defaults muted = false; onHold = false; this.phoneNumber = interlocutorUI.getCall().getNumber(); if (!uiBuilt) { buildDefaultUI(); } callStarted(); } private void buildDefaultUI() { // Add Top Panel final JPanel topPanel = buildTopPanel(); add(topPanel, new GridBagConstraints(0, 0, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); // Build Control Panel final JPanel middlePanel = buildMiddlePanel(); add(middlePanel, new GridBagConstraints(0, 6, 2, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); // Build Bottom Panel final PhonePad phonePad = new PhonePad(); historyPanel = new PreviousConversationPanel(); add(phonePad, new GridBagConstraints(0, 8, 1, 1, 0.0, 0.9, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); add(historyPanel, new GridBagConstraints(1, 8, 1, 1, 1.0, 0.9, GridBagConstraints.NORTH, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); // Setup default settings setupDefaults(); uiBuilt = true; } public void setupDefaults() { holdButton.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent mouseEvent) { toggleHold(); } }); muteButton.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent mouseEvent) { toggleMute(); } }); transferButton.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent mouseEvent) { TransferManager ui = new TransferManager(); final String number = ui.getNumber(SparkManager.getChatManager().getChatContainer().getChatFrame()); if (ModelUtil.hasLength(number)) { setStatus(PhoneRes.getIString("phone.transferring")+"...", blueColor); historyPanel.transferring(); SwingWorker transferringThread = new SwingWorker() { public Object construct() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } return true; } public void finished() { setStatus(PhoneRes.getIString("phone.transfered"), blueColor); historyPanel.transfer(number); callWasTransferred = true; softPhone.handleTransfer(getActiveCall().getID(), number); callEnded(); } }; transferringThread.start(); } } }); final SoftPhoneManager manager = SoftPhoneManager.getInstance(); hangUpButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { manager.getDefaultGuiManager().hangup(activeCall); hangUpButton.setEnabled(false); muteButton.setButtonSelected(false); holdButton.setButtonSelected(false); } }); redialButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { manager.getDefaultGuiManager().dial(activeCall.getCall().getNumber()); redialButton.setVisible(false); hangUpButton.setVisible(true); } }); } /** * Called when a new call is established. */ private void callStarted() { redialButton.setVisible(false); hangUpButton.setVisible(true); hangUpButton.setEnabled(true); muteButton.setEnabled(true); holdButton.setEnabled(true); transferButton.setEnabled(true); setStatus(CONNECTED, false); // Show History historyPanel.removeAll(); historyPanel.addPreviousConversations(phoneNumber); // Add notification to ChatRoom if one exists. final ChatRoom chatRoom = callManager.getAssociatedChatRoom(this); if (chatRoom != null) { final SimpleDateFormat formatter = new SimpleDateFormat("h:mm a"); String time = formatter.format(new Date()); chatRoom.getTranscriptWindow().insertNotificationMessage(PhoneRes.getIString("phone.callstartedat")+ " " + time, ChatManager.NOTIFICATION_COLOR); } } /** * Called when the call is ended. This does basic container cleanup. */ public void callEnded() { if (!callWasTransferred) { historyPanel.callEnded(); setStatus(PhoneRes.getIString("phone.callended"), new Color(211, 0, 0)); } hangUpButton.setVisible(false); redialButton.setVisible(true); muteButton.setEnabled(false); holdButton.setEnabled(false); transferButton.setEnabled(false); // Add notification to ChatRoom if one exists. final ChatRoom chatRoom = callManager.getAssociatedChatRoom(this); if (chatRoom != null) { final SimpleDateFormat formatter = new SimpleDateFormat("h:mm a"); String time = formatter.format(new Date()); chatRoom.getTranscriptWindow().insertNotificationMessage(PhoneRes.getIString("phone.callendedat")+" " + time, ChatManager.NOTIFICATION_COLOR); } changeState(CallRoomState.callWasEnded); } private void setStatus(String status, boolean alert) { if (alert) { connectedLabel.setForeground(orangeColor); } else { connectedLabel.setForeground(greenColor); } connectedLabel.setText(status); } private void setStatus(String status, Color color) { connectedLabel.setForeground(color); connectedLabel.setText(status); } private void toggleMute() { if (onHold) { toggleHold(); } if (muted) { muted = false; muteButton.setToolTipText(PhoneRes.getIString("phone.mute")); muteButton.setButtonSelected(false); setStatus(CONNECTED, false); // Change the state. changeState(CallRoomState.inCall); } else { muted = true; muteButton.setToolTipText(PhoneRes.getIString("phone.unmute")); muteButton.setButtonSelected(true); setStatus("Muted", true); // Change the state. changeState(CallRoomState.muted); } muteButton.invalidate(); muteButton.validate(); muteButton.repaint(); softPhone.getDefaultGuiManager().mute(activeCall, !muted); } private void toggleHold() { if (muted) { toggleMute(); } if (onHold) { onHold = false; holdButton.setToolTipText(PhoneRes.getIString("phone.hold")); holdButton.setButtonSelected(false); setStatus(CONNECTED, false); // Change the state. changeState(CallRoomState.inCall); } else { onHold = true; holdButton.setButtonSelected(true); holdButton.setToolTipText("Unhold"); setStatus(PhoneRes.getIString("phone.onhold"), true); // Change the state. changeState(CallRoomState.onHold); } softPhone.getDefaultGuiManager().hold(activeCall); } public void actionPerformed(ActionEvent e) { } public String getTabTitle() { return phoneNumber; } public String getFrameTitle() { if (activeCall.getCallState() == Call.CONNECTED) { return PhoneRes.getIString("phone.onphonewith")+" " + phoneNumber; } else { return PhoneRes.getIString("phone.callendedwith")+" " + phoneNumber; } } public ImageIcon getTabIcon() { return PhoneRes.getImageIcon("RECEIVER2_IMAGE"); } public JComponent getGUI() { return this; } public String getToolTipDescription() { return phoneNumber; } public boolean closing() { return true; } public String getPhoneNumber() { return phoneNumber; } public void paintComponent(Graphics g) { BufferedImage cache = new BufferedImage(2, getHeight(), BufferedImage.TYPE_INT_RGB); Graphics2D g2d = cache.createGraphics(); GradientPaint paint = new GradientPaint(0, 0, new Color(241, 245, 250), 0, getHeight(), new Color(244, 250, 255), true); g2d.setPaint(paint); g2d.fillRect(0, 0, getWidth(), getHeight()); g2d.dispose(); g.drawImage(cache, 0, 0, getWidth(), getHeight(), null); } public Dimension getPreferredSize() { Dimension dim = super.getPreferredSize(); dim.width = 0; return dim; } public InterlocutorUI getActiveCall() { return activeCall; } private void changeState(CallRoomState state) { softPhone.addCallSession(this, state); SparkManager.getChatManager().notifySparkTabHandlers(this); } }