/**
* $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.history;
import org.jivesoftware.resource.Res;
import org.jivesoftware.resource.SparkRes;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.plugin.Plugin;
import org.jivesoftware.spark.ui.ChatRoom;
import org.jivesoftware.spark.ui.ContactItem;
import org.jivesoftware.spark.ui.ContactList;
import org.jivesoftware.spark.ui.MessageFilter;
import org.jivesoftware.spark.ui.rooms.ChatRoomImpl;
import org.jivesoftware.spark.util.GraphicUtils;
import org.jivesoftware.spark.util.log.Log;
import org.xmlpull.mxp1.MXParser;
import org.xmlpull.v1.XmlPullParser;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.ListCellRenderer;
import javax.swing.SwingUtilities;
/**
* Allows users to see the last 10 people they have talked with.
*
* @author Derek DeMoro
*/
public class ConversationHistoryPlugin implements Plugin {
private List<String> historyList = new ArrayList<String>();
private File transcriptDir;
private File conFile;
private final DefaultListModel model = new DefaultListModel();
private JList contacts;
private Window window;
private Map<JLabel, String> jidMap = new HashMap<JLabel, String>();
public void initialize() {
transcriptDir = new File(SparkManager.getUserDirectory(), "transcripts");
conFile = new File(transcriptDir, "conversations.xml");
contacts = new JList(model);
contacts.setCellRenderer(new InternalRenderer());
window = new Window(SparkManager.getMainWindow());
final JPanel mainPanel = new JPanel(new BorderLayout());
final JLabel titleLabel = new JLabel(Res.getString("label.recent.conversation"));
titleLabel.setFont(new Font("Dialog", Font.BOLD, 11));
titleLabel.setHorizontalAlignment(JLabel.CENTER);
mainPanel.add(titleLabel, BorderLayout.NORTH);
mainPanel.add(contacts, BorderLayout.CENTER);
mainPanel.setBorder(BorderFactory.createLineBorder(Color.gray));
window.add(mainPanel);
// Add Listeners
contacts.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
contacts.setSelectedIndex(contacts.locationToIndex(e
.getPoint()));
String user = jidMap.get((JLabel) contacts
.getSelectedValue());
ContactItem contact = SparkManager.getContactList()
.getContactItemByJID(user);
SparkManager.getContactList().setSelectedUser(contact.getJID());
SparkManager.getContactList().showPopup(contacts, e,
contact);
}
if (e.getClickCount() == 2) {
final JLabel label = (JLabel) contacts.getSelectedValue();
String user = jidMap.get(label);
if (user != null) {
final String contactUsername = SparkManager
.getUserManager().getUserNicknameFromJID(user);
SparkManager.getChatManager().activateChat(user,
contactUsername);
window.dispose();
}
}
}
});
contacts.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
if (e.getKeyChar() == KeyEvent.VK_ENTER) {
final JLabel label = (JLabel) contacts.getSelectedValue();
String user = jidMap.get(label);
if (user != null) {
final String contactUsername = SparkManager.getUserManager().getUserNicknameFromJID(user);
SparkManager.getChatManager().activateChat(user, contactUsername);
window.dispose();
}
}
else if (e.getKeyChar() == KeyEvent.VK_ESCAPE) {
window.dispose();
}
}
});
contacts.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
}
public void focusLost(FocusEvent e) {
window.dispose();
}
});
// Load Previous History
loadPreviousHistory();
// Add Keymapping to ContactList
SparkManager.getMainWindow().getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_E, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "historyPeople");
SparkManager.getMainWindow().getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_E, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "historyPeople");
SparkManager.getMainWindow().getRootPane().getActionMap().put("historyPeople", new AbstractAction("historyPeople") {
private static final long serialVersionUID = 2465628887318732082L;
public void actionPerformed(ActionEvent e) {
// Show History Popup
showHistoryPopup();
}
});
// Persist order of conversations.
SparkManager.getChatManager().addMessageFilter(new MessageFilter() {
public void filterOutgoing(ChatRoom room, Message message) {
addUserToHistory(room);
}
public void filterIncoming(ChatRoom room, Message message) {
addUserToHistory(room);
}
});
}
/**
* Adds the last user to the history tags.
*
* @param room the ChatRoom where the conversation took place.
*/
private void addUserToHistory(ChatRoom room) {
if (room instanceof ChatRoomImpl) {
ChatRoomImpl roomImpl = (ChatRoomImpl) room;
String jid = roomImpl.getParticipantJID();
jid = StringUtils.parseBareAddress(jid);
historyList.remove(jid);
historyList.add(0, jid);
}
}
/**
* Displays the Previous Conversation Window.
*/
private void showHistoryPopup() {
// Get Transcript Directory
if (!transcriptDir.exists()) {
return;
}
jidMap.clear();
model.clear();
final ContactList contactList = SparkManager.getWorkspace().getContactList();
int limit = historyList.size() > 10 ? 10 : historyList.size();
for (final String user : historyList.subList(0, limit)) {
ContactItem contactItem = contactList.getContactItemByJID(user);
Icon icon;
if (contactItem != null) {
icon = contactItem.getIcon();
if (icon == null) {
icon = SparkRes.getImageIcon(SparkRes.CLEAR_BALL_ICON);
}
JLabel label = new JLabel();
label.setText(contactItem.getDisplayName());
label.setIcon(icon);
model.addElement(label);
jidMap.put(label, user);
}
}
window.setSize(200, 200);
GraphicUtils.centerWindowOnComponent(window, SparkManager.getMainWindow());
if (model.size() > 0) {
contacts.setSelectedIndex(0);
}
window.setVisible(true);
}
/**
* Loads the previous history.
*/
private void loadPreviousHistory() {
if (!conFile.exists()) {
return;
}
// Otherwise load it.
try {
final MXParser parser = new MXParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(conFile), "UTF-8"));
parser.setInput(in);
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG && "user".equals(parser.getName())) {
String jid = StringUtils.parseBareAddress(parser.nextText());
historyList.add(jid);
}
else if (eventType == XmlPullParser.END_TAG && "conversations".equals(parser.getName())) {
done = true;
}
}
}
catch (Exception e) {
Log.error(e);
}
}
public void shutdown() {
final StringBuilder builder = new StringBuilder();
builder.append("<conversations>");
for (String user : historyList) {
builder.append("<user>").append(user).append("</user>");
}
builder.append("</conversations>");
// Write out to file system.
if (!transcriptDir.exists()) {
transcriptDir.mkdirs();
}
// Write out new File
try {
File conFile = new File(transcriptDir, "conversations.xml");
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(conFile), "UTF-8"));
out.write(builder.toString());
out.close();
}
catch (IOException e) {
Log.error(e);
}
}
public boolean canShutDown() {
return true;
}
public void uninstall() {
}
/**
* Internal handling of a Jlabel Renderer.
*/
public class InternalRenderer extends JLabel implements ListCellRenderer {
private static final long serialVersionUID = 1812281106979897477L;
/**
* Construct Default Renderer.
*/
public InternalRenderer() {
setOpaque(true);
}
public Component getListCellRendererComponent(JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus) {
if (isSelected) {
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
}
else {
setBackground(list.getBackground());
setForeground(list.getForeground());
}
JLabel label = (JLabel) value;
setText(label.getText());
setIcon(label.getIcon());
return this;
}
}
}