zoukankan      html  css  js  c++  java
  • basic coder » Hybrid开发手记之聊天窗口的WebKit支持

    basic coder » Hybrid开发手记之聊天窗口的WebKit支持

    Hybrid开发手记之聊天窗口的WebKit支持

    2011年8月5日
    levin 发表评论
    阅读评论
    2,838 人阅读过  

    近两天给Hybrid(https://github.com/levin108/hybrid)的聊天窗口加上了WebKit支持,之前没有实际用过WebKit,而且Web前台开发功力也不强,草草做了一个界面,但相比用GtkTextView来实现看上去还是要舒服好多,先上个图吧:

    本篇没有什么高深的东西,作为一个简单的开发文档。

    一,主题组件化的方法

    聊天窗口的显示区域已经组件化,并没有进行深层次的模块化,代码还是在一起编译的,只是逻辑上组件化了。

    之前是固定的由GtkTextView实现,在加入GtkWebKit的时候同时也保留了GtkTextView的实现,这两者是可选的,不管是GtkWebKit还是GtkTextView都需要实现四个最基本的函数:

    typedef GtkWidget* (*text_create)(void);
    typedef void (*text_append)(GtkWidget *, HybridAccount *,
    							HybridBuddy *,	const gchar *, time_t);
    typedef void (*text_notify)(GtkWidget *, const gchar *, gint);
    typedef void (*theme_set_ops_func)(void);

    前三个函数是组件的操作函数,功能分别是创建聊天区域,向聊天区域中添加消息,向聊天区域中添加提示消息,最后一个是设置操作集合的钩子函数。

    对于这两种不同的实现分别定义了两个文件,chat-textview.c和chat-webkit.c,这两个文件里面分别是两者各自的实现,而它们对外的接口只是一个GtkWidget,这得利于GOBJECT的这种类似多态的特性。

    对于不同的实现会定义操作集变量:

    static HybridChatTextOps webkit_ops = {
    	hybrid_chat_webkit_create,
    	hybrid_chat_webkit_append,
    	hybrid_chat_webkit_notify
    };

    聊天窗口当前使用的聊天区域实现方式全由该操作集来确定,而使用哪个操作集可以由两种方式各自的theme_set_ops_func函数来设置。

    我们可以把两种组件看成两个不同的主题,在聊天窗口文件中定义了该主题的列表:

    struct _HybridChatTheme {
    	const gchar *name;
    	theme_set_ops_func func;
    };
     
    static HybridChatTheme theme_list[] = {
    #ifdef USE_WEBKIT
    	{
    		"webkit",
    		hybrid_chat_set_webkit_ops
    	},
    #endif
    	{
    		"textview",
    		hybrid_chat_set_textview_ops
    	}, {
    		NULL, NULL
    	}
    };

    运行时程序会根据用户的当前配置情况来选择使用哪种主题。

    二,WebKit遇到的问题

    关于WebKit有几点小问题,第一次用难免会碰到些小问题,不过幸好还是解决掉了。

    1. undefined @1: ReferenceError: Can’t find variable

    WebKit外部来操作DOM模型主要是通过从外部调用webkit_web_view_execute_script()来实现的,当然我看最新的GtkWebKit API里面已经支持直接操作DOM了,但貌似手头的系统上安装的版本都还没有这个API函数,为了兼容性的考虑还是采用了传统的方法。在HTML模块中用Javascript定义了函数appendMessage(html),通过这个函数向WebKit中定义聊天信息,但当收到消息自动弹出的时候会提示undefined @1: ReferenceError: Can’t find variable appendMessage(),这种情况的原因很简单,函数是定义了但找不到,原因只能是因为模板字符串还没有加载完成便调用了appendMessage()函数,因此会出现这样的错误,因此在对WebKit进行脚本操作之前首先要等它初始化完成,也就是等它load_finished之后,WebKit提供了load_finished事件,但这个事件目前已经Deprecated了,替代的方法是使用load_status属性,属性和事件的使用方法明显不一样,关于WebKit deprecate load_finished事件的原因我没去仔细想,load_status属性的方法只能是轮询,在收到消息时检测load_status,或未加载完成,则调用g_timeout_add()将操作延时后执行,执行中再检测load_status,若仍未完成则继续延时,直到加载完成为止,实际上在实现的时候我给g_timeout_add的第一个参数写了0,事实证明在进入加调函数时需要的那个简单的HTML模板就已经加载完成了,这时候再去调用webkit_web_view_execute_script()去添加一条新消息。

    2. Message: console message: undefined @1: SyntaxError: Parse error

    同样是在调用webkit_web_view_execute_script()遇到了上面的错误,通过对比和分析发现我传入的字符串参数中夹带了\n字符,把这个字符换成空格后便没有这个问题了,但换行在HTML中应该是
    ,于是需要把\n替换成
    ,C语言以及glibc都没有提供形如replace()这种方便的函数,于是我用GString,把字符一个一个的贴过去,遇到\n就贴一个
    在后面,效率是低点,但实现起来比较方便,代码如下:

    static gchar*
    escape_string(const gchar *str)
    {
    	GString *res;
     
    	res = g_string_sized_new(strlen(str));
     
    	while (str && *str) {
    		switch (*str) {
    			case 13:
    				res = g_string_append(res, "<br/>");
    				break;
    			case '\"':
    				res = g_string_append(res, "\\\"");
    				break;
    			case '\t':
    				break;
    			default:
    				res = g_string_append_c(res, *str);
    				break;
    		}
    		str ++;
    	}
     
    	return g_string_free(res, FALSE);
    }

    以上大致完成了文章开头图片的样式,已经可以正常使用,但字体在我这slackware系统上还有些不太完美,也可能是我系统字体设置有问题,这个等后期再处理。

    原创文章,转载请注明: 转载自basic coder

    本文链接地址: http://basiccoder.com/hybrid_dev_note_webkit_support_in_chat_window.html

  • 相关阅读:
    elasticsearch 中的Multi Match Query
    activiti 流程部署的各种方式
    elasticsearch 嵌套对象之嵌套类型
    elasticsearch Java High Level REST 相关操作封装
    elasticsearch 字段数据类型
    ubuntu 安装 docker
    elasticsearch 通过HTTP RESTful API 操作数据
    facenet 人脸识别(二)——创建人脸库搭建人脸识别系统
    POJ 3093 Margaritas(Kind of wine) on the River Walk (背包方案统计)
    墨卡托投影, GPS 坐标转像素, GPS 坐标转距离
  • 原文地址:https://www.cnblogs.com/lexus/p/2596877.html
Copyright © 2011-2022 走看看