/* Copyright (c) 2008 Bluendo S.r.L.
* See about.html for details about license.
*
* $Id: ChatScreen.java 1586 2009-06-17 12:26:55Z luca $
*/
package lampiro.screens;
import it.yup.ui.UIButton;
import it.yup.ui.UICanvas;
import it.yup.ui.UICombobox;
import it.yup.ui.UIConfig;
import it.yup.ui.UIEmoLabel;
import it.yup.ui.UIHLayout;
import it.yup.ui.UIItem;
import it.yup.ui.UILabel;
import it.yup.ui.UILayout;
import it.yup.ui.UIMenu;
import it.yup.ui.UIPanel;
import it.yup.ui.UIScreen;
import it.yup.ui.UISeparator;
import it.yup.ui.UITextField;
import it.yup.ui.UIUtils;
// #mdebug
//@
//@import it.yup.util.Logger;
//@
// #enddebug
import it.yup.util.ResourceIDs;
import it.yup.util.ResourceManager;
import it.yup.util.Utils;
import it.yup.xml.Element;
import it.yup.xmlstream.BasicXmlStream;
import it.yup.xmlstream.EventQuery;
import it.yup.xmlstream.EventQueryRegistration;
import it.yup.xmlstream.PacketListener;
import it.yup.xmpp.Config;
import it.yup.xmpp.Contact;
import it.yup.xmpp.IQResultListener;
import it.yup.xmpp.MUC;
import it.yup.xmpp.XMPPClient;
import it.yup.xmpp.packets.Iq;
import it.yup.xmpp.packets.Message;
import it.yup.xmpp.packets.Presence;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import javax.microedition.io.ConnectionNotFoundException;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.TextField;
import lampiro.LampiroMidlet;
public class ChatScreen extends UIScreen implements PacketListener,
CommandListener {
class ForwardScreen extends UIScreen {
private UIPanel contactPanel = new UIPanel(true, true);
private UILabel cmd_exit = new UILabel(rm.getString(
ResourceIDs.STR_CLOSE).toUpperCase());
Vector orderedContacts = null;
private String messageToForward = "";
private String fromContact = "";
public ForwardScreen(String text, String fromContact) {
this.append(contactPanel);
this.messageToForward = text;
this.fromContact = fromContact;
this.setTitle(ChatScreen.this.getTitle());
this.orderedContacts = RosterScreen.getOrderedContacts();
UILabel instrLabel = new UILabel(rm
.getString(ResourceIDs.STR_FORWARD)
+ " \""
+ this.messageToForward
+ "\" "
+ rm.getString(ResourceIDs.STR_TO).toLowerCase() + ":");
instrLabel.setWrappable(true,
UICanvas.getInstance().getWidth() - 40);
instrLabel.setAnchorPoint(Graphics.HCENTER);
Font xFont = UIConfig.font_body;
Font lfont = Font.getFont(xFont.getFace(), Font.STYLE_BOLD, xFont
.getSize());
instrLabel.setFont(lfont);
UISeparator sep = new UISeparator(2, UIUtils.colorize(
UIConfig.bg_color, -10));
this.contactPanel.addItem(instrLabel);
this.contactPanel.addItem(sep);
instrLabel.setFocusable(false);
setMenu(new UIMenu(""));
UIMenu menu = getMenu();
menu.append(cmd_exit);
for (Enumeration en = orderedContacts.elements(); en
.hasMoreElements();) {
Contact c = (Contact) en.nextElement();
String printableName = c.getPrintableName();
Presence[] ps = c.getAllPresences();
if (ps.length == 1) {
UILabel ithContactLabel = new UILabel(printableName);
ithContactLabel.setFocusable(true);
ithContactLabel.setWrappable(true, UICanvas.getInstance()
.getWidth() - 40);
this.contactPanel.addItem(ithContactLabel);
ithContactLabel.setStatus(c);
} else if (ps.length >= 2) {
for (int i = 0; i < ps.length; i++) {
String printablePresName = printableName
+ " "
+ Contact.resource(ps[i]
.getAttribute(Message.ATT_FROM));
UILabel ithContactLabel = new UILabel(printablePresName);
ithContactLabel.setWrappable(true, UICanvas
.getInstance().getWidth() - 30);
ithContactLabel.setFocusable(true);
this.contactPanel.addItem(ithContactLabel);
ithContactLabel.setStatus(ps[i]);
}
}
}
// select the first contact
if (this.contactPanel.getItems().size() >= 3) contactPanel
.setSelectedIndex(2);
this.setSelectedItem(contactPanel);
}
public void itemAction(UIItem item) {
if (item instanceof UILabel) {
Object statusTo = item.getStatus();
if (statusTo != null) {
Message msg = null;
String forwardResource = null;
String to = (statusTo instanceof Contact ? ((Contact) statusTo).jid
: ((Presence) statusTo)
.getAttribute(Message.ATT_FROM));
Contact forwardContact = XMPPClient.getInstance()
.getRoster().getContactByJid(to);
if (statusTo instanceof Contact) {
to = ((Contact) statusTo).jid;
Presence[] resources = forwardContact.getAllPresences();
forwardResource = (resources != null
&& resources.length > 0 ? resources[0]
.getAttribute(Message.ATT_FROM) : to);
} else if (statusTo instanceof Presence) {
to = ((Presence) statusTo)
.getAttribute(Message.ATT_FROM);
forwardResource = to;
}
msg = new Message(to, Message.CHAT);
msg.setBody(rm.getString(ResourceIDs.STR_FORWARDED_TEXT)
+ fromContact + ": \"" + this.messageToForward
+ "\"");
XMPPClient.getInstance().sendPacket(msg);
user.addMessageToHistory(preferredResource, msg);
if (forwardContact != null) {
// i added to the message history and the remove it
// so that it is mantained now but the "icon" is not updated
forwardContact
.addMessageToHistory(forwardResource, msg);
forwardContact.resetMessageHistory(forwardResource);
}
}
this.closeMe();
}
}
public void menuAction(UIMenu menu, UIItem cmd) {
if (cmd == cmd_exit) {
closeMe();
}
}
private void closeMe() {
UICanvas.getInstance().close(this);
UICanvas.getInstance().open(ChatScreen.this, true);
}
}
class MUCUpdateListener extends IQResultListener {
public void handleError(Element e) {
}
public void handleResult(Element e) {
String mucJid = e.getAttribute(Message.ATT_FROM);
XMPPClient xmppClient = XMPPClient.getInstance();
Contact mucContact = xmppClient.getRoster().getContactByJid(mucJid);
if (mucContact == null) return;
MUC muc = (MUC) mucContact;
UICanvas.getInstance().close(ChatScreen.this);
RosterScreen.getInstance().chatWithContact(muc, null);
MUCScreen mucScreen = (MUCScreen) RosterScreen.getChatScreenList()
.get(mucJid);
// the jid of the already present contact
String cJid = ChatScreen.this.preferredResource;
if (cJid == null) cJid = ChatScreen.this.user.jid;
mucScreen.sendInvite(cJid);
mucScreen.setSelectedItem(mucScreen.chatPanel);
mucScreen.chatPanel.setSelectedItem(mucScreen.rosterCombo);
mucScreen.keyPressed(UICanvas.getInstance().getKeyCode(
UICanvas.FIRE));
// meanwhile send the whole history!! :D
Enumeration en = ChatScreen.this.current_conversation.elements();
String myJid = xmppClient.my_jid;
while (en.hasMoreElements()) {
ConversationEntry entry = (ConversationEntry) en.nextElement();
if (entry.messageType.equals(Message.CHAT)) {
Message m = new Message(mucJid, Message.GROUPCHAT);
m.setBody(entry.text);
Element delay = m.addElement(XMPPClient.NS_DELAY,
XMPPClient.DELAY);
String completeFrom = (entry.type == ConversationEntry.ENTRY_TO ? myJid
: cJid);
delay.setAttribute(Message.ATT_FROM, completeFrom);
xmppClient.sendPacket(m);
}
}
}
}
class UICutLabel extends UIEmoLabel {
private String completeText = "";
public UICutLabel(String newText, String completeText) {
super(newText);
this.completeText = completeText;
// TODO Auto-generated constructor stub
}
protected void paint(Graphics g, int w, int h) {
super.paint(g, w, h);
g.setColor(0x555555);
Font currentFont = this.getFont();
if (currentFont == null) currentFont = UIConfig.font_body;
String moreString = " " + rm.getString(ResourceIDs.STR_MORE) + " ";
int moreWidth = currentFont.stringWidth(moreString);
g.fillRect(w - moreWidth - 2, h - currentFont.getHeight() - 2,
moreWidth + 1, currentFont.getHeight() + 1);
g.setColor(0xFFFFFF);
g
.drawString(moreString, w - moreWidth - 1, h
- currentFont.getHeight() - 1, Graphics.TOP
| Graphics.LEFT);
}
}
static ResourceManager rm = ResourceManager.getManager("common", "en");
UITextField topic_name_field = new UITextField(rm.getString(
ResourceIDs.STR_ROOM_NAME), "", 50,
TextField.ANY);
UIButton topic_button = new UIButton(rm.getString(ResourceIDs.STR_SUBMIT));
/*
* Used to avoid to repaint for the same status twice
*/
private String oldStatus = "";
/*
* The area in which the screen can paint (hence excluding
* headers footers and title screen)
*/
protected int printableHeight = -1;
/*
* The total area screen. Since it may vary during execution
* its value is saved here
*/
protected int screenHeight = -1;
/*
* The header used to show stats and advice;
*/
protected UIHLayout header;
/*
* The user associated to this UIscreen
*
*/
protected Contact user;
UILabel cmd_exit;
private UILabel cmd_write;
protected UILabel cmd_clear;
protected UILabel addUser = new UILabel(rm
.getString(ResourceIDs.STR_GROUP_CHAT));
protected UILabel cmd_capture_img = new UILabel(rm
.getString(ResourceIDs.STR_SEND_IMAGE));
protected UILabel cmd_capture_aud = new UILabel(rm
.getString(ResourceIDs.STR_SEND_AUDIO));
protected UILabel cmd_send_file = new UILabel(rm
.getString(ResourceIDs.STR_SEND_FILE));
protected UILabel cmd_forward_message = new UILabel(rm
.getString(ResourceIDs.STR_FORWARD_MESSAGE));
/*
* The menu used by UIlabels in chatscreen to close the screen
*/
UIMenu closeMenu;
/*
* The UIlabel used by UIlabels in chatscreen to close the screen
*/
UILabel closeLabel;
// #mdebug
//@ private UILabel cmd_debug = new UILabel("Debug");
// #enddebug
private Hashtable cmd_urls = new Hashtable();
// XXX add a global handler for icons
protected static Image img_msg;
// the panel containing headers and labels
protected UIPanel chatPanel;
// private Image buffer;
// /** number of currently displayed entries */
// private int displayed_entries;
// private boolean _entries_scrolled = false;
static int scroll_color = 0x444444;
private EventQueryRegistration reg = null;
/** wrapped conversation cache */
static Hashtable conversations = new Hashtable();
private Vector current_conversation = null;
private int hs = 2 * Short.parseShort(Config.getInstance().getProperty(
Config.HISTORY_SIZE, "30"));
UIMenu zoomSubmenu = new UIMenu("");
UILabel zoomLabel = new UILabel("EXPAND");
protected String preferredResource;
UILabel headerImg = null;
UILabel headerStatus = null;
// the start index of the chat lines in the chat panel:
// 0 for chats and 2 for MUCs (the rosterCombo is present)
int chatLineStart = 0;
static {
try {
img_msg = Image.createImage("/icons/message.png");
} catch (IOException e) {
img_msg = Image.createImage(16, 16);
}
}
void askTopic() {
UIMenu topicNameMenu = UIUtils.easyMenu(rm
.getString(ResourceIDs.STR_CHOOSE_NAME), 10, 20, this
.getWidth() - 20, topic_name_field);
topic_name_field.setText(XMPPClient.getInstance().getMyContact().jid
.replace('@', '_')
+ MUCScreen.unnamedMUCCounter);
MUCScreen.unnamedMUCCounter++;
topicNameMenu.append(UIUtils.easyCenterLayout(topic_button, 100));
topicNameMenu.setDirty(true);
topicNameMenu.setSelectedIndex(topicNameMenu.indexOf(topic_name_field));
this.addPopup(topicNameMenu);
}
public ChatScreen(Contact u, String preferredResource) {
super();
// lots of insertion and deletion ...
//this.setFreezed(true);
// prepare closeMenu
closeMenu = new UIMenu("");
closeLabel = new UILabel(rm.getString(ResourceIDs.STR_CLOSE)
.toUpperCase());
closeMenu.append(closeLabel);
user = u;
this.preferredResource = preferredResource;
// buffer = null;
cmd_exit = new UILabel(rm.getString(ResourceIDs.STR_CLOSE));
cmd_write = new UILabel(rm.getString(ResourceIDs.STR_WRITE));
cmd_clear = new UILabel(rm.getString(ResourceIDs.STR_CLEAR_HIST));
setMenu(new UIMenu(""));
UIMenu menu = getMenu();
// #debug
//@ menu.append(cmd_debug);
menu.append(cmd_write);
menu.append(cmd_forward_message);
RosterScreen rs = RosterScreen.getInstance();
if (rs.isCameraOn()) menu.append(this.cmd_capture_img);
if (rs.isMicOn()) menu.append(this.cmd_capture_aud);
menu.append(this.cmd_send_file);
menu.append(cmd_clear);
if (rs.mucJid != null
&& user.supportsMUC(user.getPresence(preferredResource))) menu
.append(addUser);
menu.append(cmd_exit);
setTitle(rm.getString(ResourceIDs.STR_CHAT_WITH) + " "
+ user.getPrintableName());
current_conversation = (Vector) conversations.get(preferredResource);
if (current_conversation == null) {
current_conversation = new Vector();
conversations.put(preferredResource, current_conversation);
}
/*
* XXX: hack, create an item and select it, the item won't relinquish
* focus
*/
XMPPClient client = XMPPClient.getInstance();
chatPanel = new UIPanel();
chatPanel.setMaxHeight(-1);
chatPanel.setFocusable(true);
// the panel has a contestual menu that let close the the screen
// as well as the uilabels used to print the chat lines
chatPanel.setSubmenu(this.closeMenu);
chatPanel.setModal(true);
Image img = client.getPresenceIcon(user, preferredResource, user
.getAvailability(preferredResource));
header = new UIHLayout(2);
header.setGroup(false);
String status = getPrintableStatus();
headerStatus = new UILabel(status);
header.insert(headerStatus, 0, 50, UILayout.CONSTRAINT_PERCENTUAL);
headerImg = new UILabel(img);
headerImg.setBg_color(UIConfig.header_bg);
headerImg.setFg_color(UIConfig.menu_title);
headerStatus.setBg_color(UIConfig.header_bg);
headerStatus.setFg_color(UIConfig.menu_title);
header.insert(headerImg, 1, img.getWidth() + 2,
UILayout.CONSTRAINT_PIXELS);
header.setFocusable(false);
this.append(header);
UISeparator sep = new UISeparator(2);
sep.setFg_color(0xCCCCCC);
this.append(sep);
this.append(chatPanel);
this.setSelectedIndex(2);
// to compute the printableHeight the currently visualizd screen must be
// used and not this one since it may be invisible
getPrintableHeight(UICanvas.getInstance().getCurrentScreen()
.getGraphics(), this.height);
for (int j = 0; j < current_conversation.size(); j++) {
ConversationEntry entry = (ConversationEntry) current_conversation
.elementAt(j);
this.updateLabel(entry);
}
if (chatPanel.getItems().size() > 0) {
// remember the separator
chatPanel.setSelectedIndex(chatPanel.getItems().size() - 2);
chatPanel.setDirty(true);
this.askRepaint();
}
// prepare zoomSubMenu
zoomSubmenu.append(this.zoomLabel);
zoomLabel.setAnchorPoint(Graphics.HCENTER);
zoomSubmenu.setAbsoluteX(10);
zoomSubmenu.setAbsoluteY(10);
zoomSubmenu.setWidth(this.getWidth() - 30);
// listen for all incoming messages with bodies
EventQuery q = new EventQuery("message", null, null);
q.child = new EventQuery("body", null, null);
if (reg == null) {
reg = BasicXmlStream.addEventListener(q, this);
}
// so to reset the status in the roster
// it must be locked because it interferes
// with the items positioning in the roster screen!!!
// hence all these operations must be done alltogether
try {
UICanvas.lock();
updateConversation();
RosterScreen roster = RosterScreen.getInstance();
roster.reorganizeContact(user, Contact.CH_MESSAGE_READ);
} finally {
UICanvas.unlock();
}
this.askRepaint();
}
private String getPrintableStatus() {
String status = "";
Presence[] allPresences = user.getAllPresences();
// could even be null if the user is offline now
if (allPresences != null) {
Presence p = user.getPresence(preferredResource);
if (p != null) status = p.getStatus();
}
if (status == null || status.length() == 0) {
if (user.name.length() > 0) status = user.getPrintableName();
else {
Presence p = user.getPresence(preferredResource);
if (p != null) status = p.getAttribute(Iq.ATT_FROM);
else
status = user.getPrintableName();
}
}
return status;
}
void updateResource() {
if (preferredResource == null) return;
Image img = XMPPClient.getInstance().getPresenceIcon(user,
preferredResource, user.getAvailability(preferredResource));
this.headerImg.setImg(img);
this.headerStatus.setText(getPrintableStatus());
String status = "";
if (user.getAvailability(preferredResource) == Contact.AV_UNAVAILABLE) {
status = rm.getString(ResourceIDs.STR_OFFLINE);
} else {
String showStatus = user.getPresence(preferredResource).getStatus();
if (showStatus == null) showStatus = "";
status = (rm.getString(ResourceIDs.STR_ONLINE) + ": " + showStatus);
}
String msgText = user.getPrintableName() + " "
+ rm.getString(ResourceIDs.STR_IS) + " " + status;
if (msgText.equals(oldStatus)) return;
oldStatus = msgText;
Message msg = null;
msg = new Message(preferredResource, Message.HEADLINE);
msg.setAttribute(Message.ATT_FROM, preferredResource);
msg.setBody(msgText);
user.addMessageToHistory(preferredResource, msg);
}
protected void paint(Graphics g, int w, int h) {
if (this.updateConversation()) this.chatPanel.setDirty(true);
RosterScreen.getInstance().reorganizeContact(user,
Contact.CH_MESSAGE_READ);
super.paint(g, w, h);
}
protected void getPrintableHeight(Graphics g, int h) {
int maxHeight = h - 10;
maxHeight -= this.header.getHeight(g);
maxHeight -= this.headerLayout.getHeight(g);
maxHeight -= this.footer.getHeight(g);
this.printableHeight = maxHeight;
this.screenHeight = h;
}
/**
*
* @param screen_width
* @return true if new messages have been added
*/
boolean updateConversation() {
return this.updateResConversation(null);
}
boolean updateResConversation(String res) {
if (res == null) res = this.preferredResource;
// if the user is offline i get all the conversations
// Presence[] ps = user.getAllPresences();
Vector messages = null;
// if (ps == null || ps.length ==0)
messages = user.getMessageHistory(res);
// else
// messages = user.getAllMessageHistory();
if (messages == null || messages.size() == 0) { return false; }
for (int i = 0; i < messages.size(); i++) {
String msg[] = (String[]) messages.elementAt(i);
checkUrls(msg[1]);
ConversationEntry entry = wrapMessage(msg);
updateLabel(entry);
current_conversation.addElement(entry);
}
// if (ps == null || ps.length ==0)
user.resetMessageHistory(res);
// else
// user.resetAllMessageHistory();
// must be done here after repaint to be sure all the panel
// has been updated
this.chatPanel.setSelectedIndex(this.chatPanel.getItems().size() - 2);
return true;
}
/**
* @param entry
*/
private void updateLabel(ConversationEntry entry) {
String s = (String) entry.text;
s = getLabelHeader(entry) + s;
UIEmoLabel uel = new UIEmoLabel(s);
uel.setWrappable(true, this.width - 10);
uel.setFocusable(true);
int newBgColor = -1;
if (entry.type == ConversationEntry.ENTRY_TO) {
uel.setAnchorPoint(Graphics.RIGHT);
} else {
uel.setAnchorPoint(Graphics.LEFT);
newBgColor = UIUtils.colorize(UIConfig.bg_color, -10);
uel.setBg_color(newBgColor);
}
uel.setStatus(entry);
// little modifications depending on message type
if (entry.messageType.equals(Message.ERROR)) uel.setFg_color(0xCC0000);
else if (entry.messageType.equals(Message.HEADLINE)) uel
.setFg_color(0x00CC00);
this.chatPanel.addItem(uel);
uel.setSubmenu(this.closeMenu);
this.checkSize(uel);
UISeparator sep = new UISeparator(1);
sep.setFg_color(0xCCCCCC);
this.chatPanel.addItem(sep);
// empty oldMessages
while (this.chatPanel.getItems().size() > hs) {
this.chatPanel.removeItemAt(this.chatLineStart);
this.chatPanel.removeItemAt(this.chatLineStart);
}
}
/*
* Checks if the current label must be cut in order to fit the screen
*
* @param uel the current label that is inserted now
*/
private void checkSize(UIEmoLabel uel) {
//UIScreen currentScreen = UICanvas.getInstance().getCurrentScreen();
//if (currentScreen == null) return;
// first try to use the the Chatscreen
// otherwise the currentScreen just in case
// i am not shown (composing or other screen has focus)
UIScreen currentScreen = this;
Graphics tempGraphics = currentScreen.getGraphics();
if (tempGraphics == null) {
currentScreen = UICanvas.getInstance().getCurrentScreen();
if (currentScreen == null) return;
tempGraphics = currentScreen.getGraphics();
}
Font oldFont = tempGraphics.getFont();
tempGraphics.setFont(UIConfig.font_body);
int labelHeight = uel.getHeight(tempGraphics);
//int panelHeight = this.chatPanel.getHeight(tempGraphics);
UIMenu itemSubMenu = uel.getSubmenu();
if (labelHeight > this.printableHeight
&& (itemSubMenu == null || itemSubMenu != zoomSubmenu)) {
String oldText = uel.getText();
Vector oldTextLines = uel.getTextLines();
int lineHeight = labelHeight / oldTextLines.size();
oldTextLines.setSize(printableHeight / lineHeight - 1);
String newText = "";
Enumeration en = oldTextLines.elements();
while (en.hasMoreElements()) {
newText += (en.nextElement() + "\n");
}
newText = newText.substring(0, newText.length() - 1);
UICutLabel uicl = new UICutLabel(newText, oldText);
uicl.setWrappable(true, this.width - 10);
uicl.setSubmenu(zoomSubmenu);
uicl.setTextLines(null);
int index = this.chatPanel.getItems().indexOf(uel);
this.chatPanel.insertItemAt(uicl, index);
this.chatPanel.removeItem(uel);
}
uel.setTextLines(null);
tempGraphics.setFont(oldFont);
}
String getLabelHeader(ConversationEntry entry) {
String retString = "";
if (entry.arriveTime.length() > 0) {
retString = "[" + entry.arriveTime + "] ";
}
return retString;
}
public void showNotify() {
// reset the status img
Image img = XMPPClient.getInstance().getPresenceIcon(user,
preferredResource, user.getAvailability());
if (img != ((UILabel) this.header.getItem(1)).getImg()) {
((UILabel) this.header.getItem(1)).setImg(img);
this.askRepaint();
}
}
private void checkUrls(String text) {
// parse the urls and add to the command menu
Enumeration en = Utils.find_urls(text).elements();
while (en.hasMoreElements()) {
String url = (String) en.nextElement();
if (!cmd_urls.containsKey(url)) {
UILabel cmd = new UILabel(url);
cmd_urls.put(url, cmd);
UIMenu menu = getMenu();
menu.append(cmd);
}
}
}
/**
* Wrap a message so that it fits the windows
*
* @param
* @param screen_width
*
* @return
*/
ConversationEntry wrapMessage(String text[]) {
// #ifdef TIMING
long t1 = System.currentTimeMillis();
// #endif
String myJid = Contact.userhost(XMPPClient.getInstance().my_jid);
byte type = Contact.userhost(text[0]).equals(myJid) ? ConversationEntry.ENTRY_FROM
: ConversationEntry.ENTRY_TO;
// #ifdef TIMING
System.out.println("wrap conv: " + (System.currentTimeMillis() -
t1));
// #endif
ConversationEntry convEntry = new ConversationEntry(text[1], type);
if (text[3] != null) convEntry.arriveTime = text[3];
convEntry.messageType = text[4];
return convEntry;
}
public void menuAction(UIMenu menu, UIItem cmd) {
if (cmd == cmd_exit || cmd == this.closeLabel) {
closeMe();
} else if (cmd == cmd_capture_aud) {
RosterScreen.getInstance().captureMedia(preferredResource,
Config.audioType);
} else if (cmd == cmd_capture_img) {
RosterScreen.getInstance().captureMedia(preferredResource,
Config.imgType);
} else if (cmd == cmd_send_file) {
AlbumScreen alb = AlbumScreen.getInstance(preferredResource);
UICanvas.getInstance().open(alb, true);
} else if (cmd == cmd_write) {
SimpleComposerScreen cs = null;
if (user instanceof MUC == true) cs = new MUCComposer((MUC) user);
else
cs = new SimpleComposerScreen(user, this.preferredResource);
UICanvas.display(cs);
} else if (cmd == cmd_clear) {
current_conversation.removeAllElements();
Enumeration en = cmd_urls.elements();
UIMenu mn = getMenu();
while (en.hasMoreElements()) {
mn.remove((UILabel) en.nextElement());
}
this.setFreezed(true);
this.chatPanel.removeAllItems();
this.setFreezed(false);
cmd_urls.clear();
this.setDirty(true);
// #mdebug
//@ } else if (cmd == cmd_debug) {
//@ Logger.log(
//@
//@ "h:" + UICanvas.getInstance().getHeight() + "w:"
//@ + UICanvas.getInstance().getWidth() + "ch:");
//@ Logger.log(this.getGraphics().getClipHeight() + "cw:"
//@ + this.getGraphics().getClipWidth() + "ph:"
//@ + this.chatPanel.getHeight(getGraphics()));
//@ //
//@ DebugScreen debugScreen = new DebugScreen();
//@ UICanvas.getInstance().open(debugScreen, true);
// #enddebug
} else if (cmd == this.addUser) {
askTopic();
} else if (cmd == this.cmd_forward_message) {
String text = null;
UIItem selItem = (UIItem) chatPanel.getItems().elementAt(
chatPanel.getSelectedIndex());
if (selItem instanceof UILabel == false) return;
text = ((UILabel) selItem).getText();
Object status = selItem.getStatus();
if (status instanceof ConversationEntry == false) return;
ConversationEntry entry = (ConversationEntry) status;
String fromContact = "";
if (entry.type == ConversationEntry.ENTRY_TO) fromContact = XMPPClient
.getInstance().my_jid;
else
fromContact = (preferredResource != null ? preferredResource
: user.jid);
ForwardScreen fs = new ForwardScreen(text, fromContact);
UICanvas.getInstance().open(fs, true);
} else if (cmd == topic_button) {
RosterScreen rs = RosterScreen.getInstance();
rs.muc_name_field.setText(this.topic_name_field.getText());
this.topic_name_field.setText("");
rs.createMUC(new RosterScreen.MUCStateHandler(
new MUCUpdateListener()));
} else if (cmd == this.zoomLabel) {
UICutLabel selLabel = (UICutLabel) this.chatPanel.getSelectedItem();
final String selText = selLabel.completeText;
UITextField expField = new UITextField("", selText, selText
.length(), TextField.UNEDITABLE);
expField.setWrappable(true);
expField.setExpandable(false);
int maxHeight = UICanvas.getInstance().getClipHeight() - 10;
Graphics g = this.getGraphics();
maxHeight -= this.headerLayout.getHeight(g);
maxHeight -= this.footer.getHeight(g);
expField.setMaxHeight(maxHeight);
UIMenu expandMenu = new UIMenu("");
expandMenu.append(closeLabel);
UIScreen zoomScreen = new UIScreen() {
public void menuAction(UIMenu menu, UIItem cmd) {
if (cmd == closeLabel) {
// so that the user preferred resource is reset
UICanvas.getInstance().close(this);
UICanvas.getInstance().show(ChatScreen.this);
}
}
};
zoomScreen.setMenu(expandMenu);
zoomScreen.setTitle(rm.getString(ResourceIDs.STR_EXPANDED));
zoomScreen.append(expField);
zoomScreen.setSelectedItem(expField);
UICanvas.getInstance().open(zoomScreen, true);
expField.expand();
} else {
if (this.cmd_urls.contains(cmd)) {
String url = ((UILabel) cmd).getText();
try {
LampiroMidlet._lampiro.platformRequest(url);
} catch (ConnectionNotFoundException e) {
UICanvas.showAlert(AlertType.ERROR, "URL Error",
"Can't open URL:" + e.getMessage());
}
}
}
}
public void closeMe() {
// so that the user preferred resource is reset
user.lastResource = null;
Hashtable chatScreenList = RosterScreen.getChatScreenList();
// better to search me and nothing else
Enumeration en = chatScreenList.keys();
while (en.hasMoreElements()) {
Object ithKey = en.nextElement();
Object object = chatScreenList.get(ithKey);
if (object == this) chatScreenList.remove(ithKey);
}
//chatScreenList.remove(this.user.jid);
// reset the status in the roster
RosterScreen roster = RosterScreen.getInstance();
roster.updateContact(user, Contact.CH_MESSAGE_READ);
if (reg != null) {
reg.remove();
reg = null;
}
// to reset the header from outside this screen to ;
roster.setDirty(true);
UICanvas.getInstance().close(this);
}
boolean isPrintable(int key) {
int keyNum = -1;
switch (key) {
case Canvas.KEY_NUM0:
case Canvas.KEY_NUM1:
case Canvas.KEY_NUM2:
case Canvas.KEY_NUM3:
case Canvas.KEY_NUM4:
case Canvas.KEY_NUM5:
case Canvas.KEY_NUM6:
case Canvas.KEY_NUM7:
case Canvas.KEY_NUM8:
case Canvas.KEY_NUM9:
keyNum = key;
}
if (keyNum == -1
&& UICanvas.getInstance().getGameAction(key) != Canvas.FIRE) { return false; }
return true;
}
/**
* Handle key events
*
* @param kc
* the pressed key
*/
public boolean keyPressed(int kc) {
if (this.popupList.size() == 0
&& this.getMenu().isOpenedState() == false) {
int ga = UICanvas.getInstance().getGameAction(kc);
boolean ip = isPrintable(kc);
if (ip || ga == Canvas.FIRE) {
if (this.chatPanel.getSelectedIndex() < 0
|| this.chatPanel.getItems().elementAt(
this.chatPanel.getSelectedIndex()) instanceof UICombobox == false) {
SimpleComposerScreen cs = null;
if (user instanceof MUC == true) cs = new MUCComposer(
(MUC) user);
else
cs = new SimpleComposerScreen(user,
this.preferredResource);
UICanvas.display(cs);
return true;
}
}
switch (ga) {
case Canvas.RIGHT: {
RosterScreen roster = RosterScreen.getInstance();
roster.updateContact(user, Contact.CH_MESSAGE_READ);
RosterScreen.showNextScreen(this);
return true;
}
case Canvas.LEFT: {
RosterScreen roster = RosterScreen.getInstance();
roster.updateContact(user, Contact.CH_MESSAGE_READ);
RosterScreen.showPreviousScreen(this);
return true;
}
}
}
return super.keyPressed(kc);
}
public void packetReceived(Element e) {
// avoid useless repaint when computing conversation
this.setFreezed(true);
// check if it is a msg for myself so the img_msg is not shown
// and avoid fast bot problem
// String fullJid = user.getFullJid();
// fullJid could be null for offline contact
// so let's use in that case the userhost and nothing more
// if (fullJid == null) fullJid = user.jid;
// String userHost = Contact.userhost(fullJid);
boolean myPacket = isMyPacket(e);
boolean updated = false;
if (myPacket && needDisplay()
&& this == UICanvas.getInstance().getCurrentScreen()) {
try {
UICanvas.lock();
updated = updateConversation();
RosterScreen.getInstance().reorganizeContact(user,
Contact.CH_MESSAGE_READ);
} finally {
UICanvas.unlock();
}
if (updated == false) {
this.setFreezed(false);
return;
}
} else if (myPacket == false) {
((UILabel) this.header.getItem(1)).setImg(img_msg);
updated = true;
/*((UILabel) this.header.getItem(1)).setDirty(true);
this.askRepaint();*/
}
this.setFreezed(false);
if (updated) askRepaint();
}
boolean needDisplay() {
return user.getHistoryLength(this.preferredResource) > 0;
}
boolean isMyPacket(Element e) {
return e.getAttribute(Iq.ATT_FROM).equals(preferredResource);
}
/**
* Entry for a conversation
*/
static class ConversationEntry {
public String messageType;
/** message from */
public static final byte ENTRY_FROM = 0;
/** message to */
public static final byte ENTRY_TO = 1;
/** previous message wrap XXX ? */
public static final byte ENTRY_ERROR = 2;
/** message type in / on */
public byte type;
/** the message itself */
public String text;
/** first line of the entry that is displayed */
public int entry_offset = 0;
public String from = "";
public String arriveTime = "";
public ConversationEntry(String text, byte type) {
this.type = type;
this.text = text;
}
}
public void commandAction(Command cmd, Displayable disp) {
UICanvas.display(null);
this.dirty = true;
this.askRepaint();
}
}