4

I want to make a chat application where the emoticons are necessary. I was trying to write my own TextBox to handle some unicode caracters and replace them with smiles and emoticons, but that was a hard work to do and I encountered many problems.

Then I tried to make a custom font that will have emoticons in it but I found that a font is made in black and white and cannot be colored.

I tried then to use different EditFields so when I find a Bitmap I draw it and start a different EditField but that didnt work for several lines and selection problems occured.

The best way was to write my own textField that will find a special unicode caracter, add 2 spaces to, get the location of the unicode caracter and then draw the bitmap image in this location. But that was very slow when the number of emoticons becomes bigger

Is there a tool or an API or a way that I missed that will do the emoticons for me on BlackBerry devices? Please help in this topic I searched everywhere and nothing found yet

Michael Donohue
  • 11,776
  • 5
  • 31
  • 44
Farid Farhat
  • 2,300
  • 1
  • 16
  • 29
  • Search around on the Java Development forum for RIM (http://supportforums.blackberry.com/t5/Java-Development/bd-p/java_dev), a lot of people have asked this and you may be able to get some good suggestions on there. – jprofitt Sep 01 '11 at 13:15
  • I was one of those persons who asked over their more than 3 questions and still cant get an answer for that – Farid Farhat Sep 01 '11 at 14:03
  • 3
    I gave a pretty lengthy description of a possible solution at http://stackoverflow.com/questions/6175545/blackberry-smileys-in-text-field/6176555#6176555 It might be helfpul – jprofitt Sep 01 '11 at 15:44
  • Well this was not helpful :) I tried all the things you talked about in that post, and nothing from them worked. All these approaches end with a big problem remaining. I created a Custom Edit Field that did the job but was too slow because I needed a lot of calculation and drawing. – Farid Farhat Sep 02 '11 at 06:39
  • are you struggling to bring the animated images ? – Arun Kumar Munusamy Sep 06 '11 at 07:51
  • I think you can easily find the solution in some open source messaging apps, exactly i don't know about blackberry, but in iphone it would be easy since they have granted the source codes of most of the controls, instead of implementing whole functionality yourself, copy paste as most as u can from there controls – Saboor Awan Sep 11 '11 at 20:27
  • 1
    http://supportforums.blackberry.com/t5/Java-Development/Open-source-Black-berry-Messenger/td-p/626029 – Saboor Awan Sep 11 '11 at 20:34

1 Answers1

3

We could try to use a web forums approach:

  • allow users to input ASCII codes for emoticons
  • in message edit mode show emoticons as a text codes
  • in message history show emoticons as images (use BrowserField for this purpose)
  • use additional html formatting

simulator screen shot with chat application

Try this code:

public final class ChatScreen extends MainScreen implements FieldChangeListener {
    static final int INT_MSG_MAX_LEN = 200;
    static final DateFormat FRMT_TIME = DateFormat
            .getInstance(DateFormat.TIME_SHORT);
    static final String STR_FRMT_IMG = "<img src=\"{0}\"></img>";
    static final String STR_FRMT_MSG = "<b>{0}</b> [{1}]: {2}</p>";

    // several emoticon ASCII codes
    static final String STR_CODE_SMILE = ":)";
    static final String STR_CODE_SADSMILE = ":(";
    static final String STR_CODE_WINK = ";)";

    // use emoticons from http://www.skypeemoticonslist.com
    static final String STR_IMG_URL = "http://www.skypeemoticonslist.com/images/";
    static final String STR_IMG_NAME_SMILE = "emoticon-0100-smile.png";
    static final String STR_IMG_NAME_SADSMILE = "emoticon-0101-sadsmile.png";
    static final String STR_IMG_NAME_WINK = "emoticon-0105-wink.png";

    static final Hashtable TABLE_URL = new Hashtable();
    static final Hashtable TABLE_IMG = new Hashtable();

    private static void initCode(String code, String imgFName) {
        String tag;
        // prepare table for online use
        // generate img tag with live url
        tag = MessageFormat.format(STR_FRMT_IMG, new Object[] { STR_IMG_URL
                + imgFName });
        TABLE_URL.put(code, tag);

        // prepare table for offline use
        // retrieve image from project resources
        try {
            EncodedImage img = EncodedImage.getEncodedImageResource(imgFName);
            // generate img tag with embedded data url
            String dataStr = getDataUrl(img.getData(), img.getMIMEType());
            tag = MessageFormat.format(STR_FRMT_IMG, new Object[] { dataStr });
            TABLE_IMG.put(code, tag);
        } catch (IOException e) {
            System.out.println("\n Troubles preparing res for code " + code
                    + "  \n");
        }
    }

    static {
        initCode(STR_CODE_SMILE, STR_IMG_NAME_SMILE);
        initCode(STR_CODE_SADSMILE, STR_IMG_NAME_SADSMILE);
        initCode(STR_CODE_WINK, STR_IMG_NAME_WINK);
    }

    boolean mIsOffline = true;
    String mChatHistory = "";

    BrowserField mBrowserField = new BrowserField();
    EditField mTextField = new EditField("Input message: ", "",
            INT_MSG_MAX_LEN, Field.USE_ALL_WIDTH);
    ButtonField mBtnUserLeft = new ButtonField("Send as Mr. Left",
            Field.FIELD_LEFT | ButtonField.CONSUME_CLICK);
    ButtonField mBtnUserRight = new ButtonField("Send as Mr. Right",
            Field.FIELD_RIGHT | ButtonField.CONSUME_CLICK);

    public ChatScreen() {
        super(Manager.NO_VERTICAL_SCROLL | Manager.NO_HORIZONTAL_SCROLLBAR);
        add(mTextField);
        HorizontalFieldManager hfm = new HorizontalFieldManager(
                Field.USE_ALL_WIDTH | Field.FIELD_HCENTER);
        mBtnUserLeft.setChangeListener(this);
        mBtnUserRight.setChangeListener(this);
        hfm.add(mBtnUserLeft);
        hfm.add(mBtnUserRight);
        add(hfm);
        VerticalFieldManager vfm = new VerticalFieldManager(Field.USE_ALL_WIDTH
                | Manager.VERTICAL_SCROLL | Manager.VERTICAL_SCROLLBAR);
        vfm.add(mBrowserField);
        add(vfm);
    }

    protected void makeMenu(Menu menu, int instance) {
        menu.add(new MenuItem(mIsOffline ? "Go Online" : "Go Offline", 0, 0) {
            public void run() {
                mIsOffline = !mIsOffline;
            }
        });
        super.makeMenu(menu, instance);
    }

    public void fieldChanged(final Field field, int context) {
        if (field == mBtnUserLeft) {
            addMessage("Mr. Left");
        } else if (field == mBtnUserRight) {
            addMessage("Mr. Right");
        }
    }

    private void addMessage(String userName) {
        String message = mTextField.getText();

        // update message with emoticons
        message = replaceCodeWithImg(message, STR_CODE_SMILE);
        message = replaceCodeWithImg(message, STR_CODE_SADSMILE);
        message = replaceCodeWithImg(message, STR_CODE_WINK);
        String timeStr = FRMT_TIME.format(new Date(System.currentTimeMillis()));
        String text = MessageFormat.format(STR_FRMT_MSG, new Object[] {
                userName, timeStr, message });
        mChatHistory = text + mChatHistory;
        mTextField.setText("");
        // fix IllegalStateException up to
        // http://supportforums.blackberry.com/t5/Java-Development/IllegalStateException-at-displayContent-on-browserfield/td-p/1071991
        mBrowserField.setFocus();

        mBrowserField.displayContent("<html>" + mChatHistory + "</html>", "");
    }

    private String replaceCodeWithImg(String message, String code) {
        Hashtable table = mIsOffline ? TABLE_IMG : TABLE_URL;
        int index = message.indexOf(code);
        while (index != -1) {
            String begin = message.substring(0, index);
            String end = message.substring(index + code.length());
            String tag = (String) table.get(code);
            message = begin + tag + end;

            index = message.indexOf(code, index + tag.length());
        }
        return message;
    }

    // src taken from http://bfo.com/blog/files/src/DataStreamHandler.java
    private static final String getDataUrl(byte[] data, String mimetype)
            throws IOException {
        final StringBuffer sb = new StringBuffer();
        sb.append("data:");
        sb.append(mimetype);
        sb.append(";base64,");
        OutputStream out = new OutputStream() {
            public void write(int c) {
                sb.append((char) (c & 0xFF));
            }
        };
        Base64OutputStream fout = new Base64OutputStream(out);
        fout.write(data);
        fout.close();
        return sb.toString();
    }
}
Maksym Gontar
  • 22,765
  • 10
  • 78
  • 114
  • Well no its not an appropriate solution. I want emoticons in the edit field and in the rich text field. I dont want to use the browser field. I want selection events and copy events – Farid Farhat Oct 24 '11 at 08:08
  • 2
    @FaridFarhat if you want copy/paste/modify functionality - you still can do this. Display every message as a separate browserfield. Then on edit or view put a text version into text box. – Maksym Gontar Oct 24 '11 at 15:17
  • I didn't get you clearly, how can you copy a text from a browser field? – Farid Farhat Oct 24 '11 at 19:24
  • 1
    @FaridFarhat with proper business logic (storing messages in some collection) we don't need to copy content from BrowserField back. Just take an index or some key id of appropriate browserfield, and get message from collection. – Maksym Gontar Oct 25 '11 at 09:16
  • Well I want to make it like BBM to be more specific. I want to enable native selection and native copy and paste. This will work but without native things... – Farid Farhat Oct 25 '11 at 11:08