/**
* $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.sparkimpl.plugin.filetransfer.transfer.ui;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.Font;
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.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import org.jivesoftware.resource.Res;
import org.jivesoftware.resource.SparkRes;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.filetransfer.FileTransfer;
import org.jivesoftware.smackx.filetransfer.FileTransfer.Status;
import org.jivesoftware.smackx.filetransfer.FileTransferManager;
import org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.component.FileDragLabel;
import org.jivesoftware.spark.ui.ContactItem;
import org.jivesoftware.spark.ui.ContactList;
import org.jivesoftware.spark.util.ByteFormat;
import org.jivesoftware.spark.util.GraphicUtils;
import org.jivesoftware.spark.util.SwingWorker;
import org.jivesoftware.spark.util.log.Log;
public class SendFileTransfer extends JPanel {
private static final long serialVersionUID = -4403839897649365671L;
private FileDragLabel imageLabel = new FileDragLabel();
private JLabel titleLabel = new JLabel();
private JLabel fileLabel = new JLabel();
private TransferButton cancelButton = new TransferButton();
private JProgressBar progressBar = new JProgressBar();
private File fileToSend;
private OutgoingFileTransfer transfer;
private TransferButton retryButton = new TransferButton();
private FileTransferManager transferManager;
private String fullJID;
private String nickname;
private JLabel progressLabel = new JLabel();
private long _starttime;
public SendFileTransfer() {
setLayout(new GridBagLayout());
setBackground(new Color(250, 249, 242));
add(imageLabel, new GridBagConstraints(0, 0, 1, 3, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
add(titleLabel, new GridBagConstraints(1, 0, 2, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
titleLabel.setFont(new Font("Dialog", Font.BOLD, 11));
titleLabel.setForeground(new Color(211, 174, 102));
add(fileLabel, new GridBagConstraints(1, 1, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 5, 5), 0, 0));
cancelButton.setText(Res.getString("cancel"));
retryButton.setText(Res.getString("retry"));
cancelButton.setIcon(SparkRes.getImageIcon(SparkRes.SMALL_DELETE));
retryButton.setIcon(SparkRes.getImageIcon(SparkRes.REFRESH_IMAGE));
add(cancelButton, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0));
add(retryButton, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0));
retryButton.setVisible(false);
retryButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
File file = new File(transfer.getFilePath());
transfer = transferManager.createOutgoingFileTransfer(fullJID);
transfer.sendFile(file, "Sending");
}
catch (XMPPException e1) {
Log.error(e1);
}
sendFile(transfer, transferManager, fullJID, nickname);
}
});
cancelButton.setForeground(new Color(73, 113, 196));
cancelButton.setFont(new Font("Dialog", Font.BOLD, 11));
cancelButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196)));
retryButton.setForeground(new Color(73, 113, 196));
retryButton.setFont(new Font("Dialog", Font.BOLD, 11));
retryButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196)));
setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.white));
}
public void sendFile(final OutgoingFileTransfer transfer, FileTransferManager transferManager, final String jid, final String nickname) {
this.transferManager = transferManager;
cancelButton.setVisible(true);
retryButton.setVisible(false);
this.fullJID = jid;
this.nickname = nickname;
this.transfer = transfer;
String fileName = transfer.getFileName();
long fileSize = transfer.getFileSize();
ByteFormat format = new ByteFormat();
String text = format.format(fileSize);
fileToSend = new File(transfer.getFilePath());
imageLabel.setFile(fileToSend);
fileLabel.setText(fileName + " (" + text + ")");
ContactList contactList = SparkManager.getWorkspace().getContactList();
ContactItem contactItem = contactList.getContactItemByJID(jid);
titleLabel.setText(Res.getString("message.transfer.waiting.on.user", contactItem.getDisplayName()));
if (isImage(fileName)) {
try {
URL imageURL = new File(transfer.getFilePath()).toURI().toURL();
ImageIcon image = new ImageIcon(imageURL);
image = GraphicUtils.scaleImageIcon(image, 64, 64);
imageLabel.setIcon(image);
}
catch (MalformedURLException e) {
Log.error("Could not locate image.", e);
imageLabel.setIcon(SparkRes.getImageIcon(SparkRes.DOCUMENT_INFO_32x32));
}
}
else {
File file = new File(transfer.getFilePath());
Icon icon = GraphicUtils.getIcon(file);
imageLabel.setIcon(icon);
}
cancelButton.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent mouseEvent) {
transfer.cancel();
}
});
cancelButton.addMouseListener(new MouseAdapter() {
public void mouseEntered(MouseEvent e) {
cancelButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
}
public void mouseExited(MouseEvent e) {
cancelButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
});
progressBar.setMaximum(100);
progressBar.setVisible(false);
progressBar.setStringPainted(true);
add(progressBar, new GridBagConstraints(1, 2, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 150, 0));
add(progressLabel, new GridBagConstraints(1, 3, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 150, 0));
SwingWorker worker = new SwingWorker() {
public Object construct() {
while (true) {
try {
if(transfer.getBytesSent() >0 && _starttime==0){
_starttime = System.currentTimeMillis();
}
long starttime = System.currentTimeMillis();
long startbyte = transfer.getBytesSent();
Thread.sleep(500);
FileTransfer.Status status = transfer.getStatus();
if (status == Status.error ||
status == Status.complete || status == Status.cancelled ||
status == Status.refused) {
break;
}
long endtime = System.currentTimeMillis();
long endbyte = transfer.getBytesSent();
long timediff = endtime-starttime;
long bytediff = endbyte-startbyte;
updateBar(transfer, nickname, TransferUtils.calculateSpeed(bytediff, timediff) );
}
catch (InterruptedException e) {
Log.error("Unable to sleep thread.", e);
}
}
return "";
}
public void finished() {
updateBar(transfer, nickname, "??MB/s");
}
};
worker.start();
makeClickable(imageLabel);
makeClickable(titleLabel);
}
private void makeClickable(final JLabel label) {
label.setToolTipText(Res.getString("message.click.to.open"));
label.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
openFile(fileToSend);
}
public void mouseEntered(MouseEvent e) {
label.setCursor(new Cursor(Cursor.HAND_CURSOR));
}
public void mouseExited(MouseEvent e) {
label.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
});
}
private void openFile(File downloadedFile) {
try {
Desktop.getDesktop().open(downloadedFile);
} catch (IOException e) {
Log.error(e);
}
}
private void updateBar(final OutgoingFileTransfer transfer, String nickname, String kBperSecond) {
FileTransfer.Status status = transfer.getStatus();
if (status == Status.negotiating_stream) {
titleLabel.setText(Res.getString("message.negotiation.file.transfer", nickname));
}
else if (status == Status.error) {
if (transfer.getException() != null) {
Log.error("Error occured during file transfer.", transfer.getException());
}
progressBar.setVisible(false);
progressLabel.setVisible(false);
titleLabel.setText(Res.getString("message.unable.to.send.file", nickname));
cancelButton.setVisible(false);
retryButton.setVisible(true);
showAlert(true);
}
else if (status == Status.in_progress) {
titleLabel.setText(Res.getString("message.sending.file.to", nickname));
showAlert(false);
if (!progressBar.isVisible()) {
progressBar.setVisible(true);
progressLabel.setVisible(true);
}
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
// 100 % = Filesize
// x % = Currentsize
long p = (transfer.getBytesSent() * 100 / transfer.getFileSize() );
progressBar.setValue(Math.round(p));
}
});
}
catch (Exception e) {
Log.error(e);
}
ByteFormat format = new ByteFormat();
String bytesSent = format.format(transfer.getBytesSent());
String est = TransferUtils.calculateEstimate(transfer.getBytesSent(), transfer.getFileSize(), _starttime, System.currentTimeMillis());
progressLabel.setText(Res.getString("message.transfer.progressbar.text.sent", bytesSent, kBperSecond, est));
}
else if (status == Status.complete) {
progressBar.setVisible(false);
String fin = TransferUtils.convertSecondstoHHMMSS(Math.round(System.currentTimeMillis()-_starttime)/1000);
progressLabel.setText(Res.getString("label.time", fin));
titleLabel.setText(Res.getString("message.you.have.sent", nickname));
cancelButton.setVisible(false);
showAlert(true);
}
else if (status == Status.cancelled) {
progressBar.setVisible(false);
progressLabel.setVisible(false);
titleLabel.setText(Res.getString("message.file.transfer.canceled"));
cancelButton.setVisible(false);
retryButton.setVisible(true);
showAlert(true);
}
else if (status == Status.refused) {
progressBar.setVisible(false);
progressLabel.setVisible(false);
titleLabel.setText(Res.getString("message.file.transfer.rejected", nickname));
cancelButton.setVisible(false);
retryButton.setVisible(true);
showAlert(true);
}
}
private class TransferButton extends JButton {
private static final long serialVersionUID = 8807434179541503654L;
public TransferButton() {
decorate();
}
/**
* Decorates the button with the approriate UI configurations.
*/
private void decorate() {
setBorderPainted(false);
setOpaque(true);
setContentAreaFilled(false);
setMargin(new Insets(1, 1, 1, 1));
}
}
private boolean isImage(String fileName) {
fileName = fileName.toLowerCase();
String[] imageTypes = {"jpeg", "gif", "jpg", "png"};
for (String imageType : imageTypes) {
if (fileName.endsWith(imageType)) {
return true;
}
}
return false;
}
private void showAlert(boolean alert) {
if (alert) {
titleLabel.setForeground(new Color(211, 174, 102));
setBackground(new Color(250, 249, 242));
}
else {
setBackground(new Color(239, 245, 250));
titleLabel.setForeground(new Color(65, 139, 179));
}
}
public void cancelTransfer() {
if (transfer != null) {
transfer.cancel();
}
}
}