给Spark添加聊天记录搜索功能


How to add Search-history-message-function in Spark.

———————————————
很幸运,这个功能的Patch已经被Spark Dev开发小组加入到SVN,大家从SVN库Check out 代码就能获得这个功能了。
相关信息:http://www.igniterealtime.org/issues/browse/SPARK-896
———————————————

目标:实现简单的文本搜索功能。

Spark的聊天记录处理程序主要由org.jivesoftware.sparkimpl.plugin.transcripts.ChatTranscriptPlugin类提供UI界面,
org.jivesoftware.sparkimpl.plugin.transcripts.ChatTranscript类提供历史记录
本次功能的添加,就是通过修改这两个类来实现的。

未完成的问题:搜索框提示信息没有添加进入in18资源文件,这一步修改比较简单,就不再赘述。

开始作业:
1、在ChatTranscript类中增加一个方法,用于返回包含搜索关键字的聊天记录,代码如下:

    /**
     * Returns messages that included search keywords.
     *
     * @param text search keywords.If the search keywords is null, return all message.
     * @return the messages that included search keywords.
     */
    public List<HistoryMessage> getMessage(String text) {
        if(text == null || "".equals(text)) {
            return messages;
        } else {
            List<HistoryMessage> searchResult = new ArrayList<HistoryMessage>();
            for(HistoryMessage message : messages) {
                // ignore keywords’ case
                if(message.getBody().toLowerCase().indexOf(text.toLowerCase()) != -1) {
                    searchResult.add(message);
                }
            }
            return searchResult;
        }
    }

2、修改ChatTranscriptPlugin类的showHistory方法,增加搜索输入框,增加焦点事件监听,增加回车键时间监听。
在final JPanel mainPanel = new BackgroundPanel();代码和final JEditorPane window = new JEditorPane();代码之间,修改代码如下:

// add search text input
final JPanel topPanel = new BackgroundPanel();
topPanel.setLayout(new GridBagLayout());

final VCardPanel vacardPanel = new VCardPanel(jid);
final JTextField searchField = new JTextField(25);
searchField.setText(Res.getString("message.search.for.history"));
searchField.setToolTipText(Res.getString("message.search.for.history"));
searchField.setForeground((Color) UIManager.get("TextField.lightforeground"));

topPanel.add(vacardPanel, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(1, 5, 1, 1), 0, 0));
topPanel.add(searchField, new GridBagConstraints(1, 0, GridBagConstraints.REMAINDER, 1, 1.0, 1.0, GridBagConstraints.SOUTHEAST, GridBagConstraints.NONE, new Insets(1, 1, 6, 1), 0, 0));

mainPanel.add(topPanel, BorderLayout.NORTH);

上面这段代码添加了一个搜索输入框。并且设置了提示信息、默认文本以及默认文本的颜色。另外这个搜索输入框和原来的VCardPanel使用网袋布局管理器布局,以保证窗口放大缩小时控件所在的位置正确。关于网袋布局管理器我之前也没有认真学过,以前用的时候,都是直接用Eclipse设置布局管理器为null,然后画好控件之后直接设置网袋布局管理器就OK了,这次,为了写好这个,还好好学习一把,下面把网袋布局管理器的参数提供给大家,也算是给自己的一个备忘。

Gridx——组件的横向坐标
Girdy——组件的纵向坐标
Gridwidth——组件的横向宽度,也就是指组件占用的列数,这与HTML的colspan类似
Gridheight——组件的纵向长度,也就是指组件占用的行数,这与HTML的rowspan类似
Weightx——指行的权重,告诉布局管理器如何分配额外的水平空间
Weighty——指列的权重,告诉布局管理器如何分配额外的垂直空间
Anchor——告诉布局管理器组件在表格空间中的位置
Fill——如果显示区域比组件的区域大的时候,可以用来控制组件的行为。控制组件是垂直填充,还是水平填充,或者两个方向一起填充
Insets——指组件与表格空间四周边缘的空白区域的大小
Ipadx—— 组件间的横向间距,组件的宽度就是这个组件的最小宽度加上ipadx值
ipady—— 组件间的纵向间距,组件的高度就是这个组件的最小高度加上ipady值

3、搜索输入框做完了之后,添加事件监听,需要监听的有三个事件,首先是当鼠标点入搜索框的时候,默认文本需要消失,并且恢复字体颜色为黑色;其次当然是失去鼠标时,需要把搜索框复原了;最后当然是输入搜索关键字按下回车需要执行搜索功能了。

在showHistory方法最后的代码TaskEngine.getInstance().schedule(transcriptTask, 10);之上添加三个事件监听代码

        searchField.addKeyListener(new KeyListener() {           
            @Override
            public void keyTyped(KeyEvent e) {               
            }
            @Override
            public void keyReleased(KeyEvent e) {
                if(e.getKeyChar() == KeyEvent.VK_ENTER) {
                    TaskEngine.getInstance().schedule(transcriptTask, 10);
                    searchField.requestFocus();
                }
            }
            @Override
            public void keyPressed(KeyEvent e) {
            }
        });
        searchField.addFocusListener(new FocusListener() {
            public void focusGained(FocusEvent e) {
                searchField.setText("");
                searchField.setForeground((Color) UIManager.get("TextField.foreground"));
            }

            public void focusLost(FocusEvent e) {
                searchField.setForeground((Color) UIManager.get("TextField.lightforeground"));
                searchField.setText(Res.getString("message.search.for.history"));
            }
        });

4、事件监听代码也添加完了,还忘了件事情,就是把取得Message信息的方法修改成我们自己添加的方法。
把之前的代码

final List<HistoryMessage> list = transcript.getMessage();

修改成

final List<HistoryMessage> list = transcript.getMessage(
                                                            Res.getString("message.search.for.history").equals(searchField.getText())
                                                                ? null : searchField.getText());

5、给所有的i18n资源文件添加message.search.for.history = Search History值,有多国语言能力的还可以翻译成其他语种。

6、一切OK,看效果图
没有获得焦点时
image 
获得焦点后
 image
搜索效果
image

Advertisements

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s