[evolution-patches] patch to implement editable text interface
- From: yuedong du <yuedong du sun com>
- To: patches <evolution-patches ximian com>, Radek Doulik <rodo ximian com>
- Cc: sceri-acc <sceri-evolution-acc sun com>
- Subject: [evolution-patches] patch to implement editable text interface
- Date: Thu, 21 Aug 2003 14:28:36 +0800
Hi Radek,
The patch is tested with GOK, please review.
After the patch, I can select a paragraph of text in mail composer, and
copy, cut and paste using GOK's text manipulation interface.
The editable-text.patch implemented insert_text, copy_text, cut_text,
delete_text and paste_text method.
Note that at end of paste_text and cut_text method, there is a
grab_focus signal emitted. This is because after these operations, html
object tree changed, and the focused html object may also changed. Thus
we need to use atk_focus_notify API to notify AT app.
And the htmlobject.patch and a new datalist to html object. The data
list different from orginal one in that it will not be copied when you
dup a htmlobject. See the copy() in htmlobject.c,
static void
copy (HTMLObject *self, HTMLObject *dest)
{
... ...
g_datalist_init (&dest->object_data);
html_object_copy_data_from_object (dest, self);
... ...
}
This will cause html object associated to a wrong acc object in
composer. So in the utils.[ch], change to use the new datalist instead
of the old one.
Another change in utils.c is add a acc_unref(). By setting it to the
destroy function of the new datalist, acc_unref will called when the
htmlobject is destroyed, we need to break the htmlobject<->acc
association.
Regards
York
Index: text.c
===================================================================
RCS file: /cvs/gnome/gtkhtml/a11y/text.c,v
retrieving revision 1.4
diff -u -r1.4 text.c
--- text.c 6 Aug 2003 10:47:16 -0000 1.4
+++ text.c 21 Aug 2003 05:39:22 -0000
@@ -62,6 +62,32 @@
static gint html_a11y_text_get_caret_offset (AtkText *text);
static gboolean html_a11y_text_set_caret_offset (AtkText *text, gint offset);
+/* Editable text interface. */
+static void atk_editable_text_interface_init (AtkEditableTextIface *iface);
+static void html_a11y_text_set_text_contents (AtkEditableText *text,
+ const gchar *string);
+static void html_a11y_text_insert_text (AtkEditableText *text,
+ const gchar *string,
+ gint length,
+ gint *position);
+static void html_a11y_text_copy_text (AtkEditableText *text,
+ gint start_pos,
+ gint end_pos);
+static void html_a11y_text_cut_text (AtkEditableText *text,
+ gint start_pos,
+ gint end_pos);
+static void html_a11y_text_delete_text (AtkEditableText *text,
+ gint start_pos,
+ gint end_pos);
+static void html_a11y_text_paste_text (AtkEditableText *text,
+ gint position);
+static void html_a11y_text_paste_received (GtkClipboard *clipboard,
+ const gchar *text,
+ gpointer data);
+
+static AtkStateSet* html_a11y_text_ref_state_set (AtkObject *accessible);
+
+
static AtkObjectClass *parent_class = NULL;
GType
@@ -95,9 +121,17 @@
NULL
};
+ static const GInterfaceInfo atk_editable_text_info =
+ {
+ (GInterfaceInitFunc) atk_editable_text_interface_init,
+ (GInterfaceFinalizeFunc) NULL,
+ NULL
+ };
+
type = g_type_register_static (G_TYPE_HTML_A11Y, "HTMLA11YText", &tinfo, 0);
g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info);
g_type_add_interface_static (type, ATK_TYPE_TEXT, &atk_text_info);
+ g_type_add_interface_static (type, ATK_TYPE_EDITABLE_TEXT, &atk_editable_text_info);
}
return type;
@@ -127,6 +161,7 @@
iface->get_selection = html_a11y_text_get_selection;
iface->remove_selection = html_a11y_text_remove_selection;
iface->set_selection = html_a11y_text_set_selection;
+ iface->add_selection = html_a11y_text_add_selection;
iface->get_caret_offset = html_a11y_text_get_caret_offset;
iface->set_caret_offset = html_a11y_text_set_caret_offset;
}
@@ -167,6 +202,7 @@
parent_class = g_type_class_peek_parent (klass);
atk_class->initialize = html_a11y_text_initialize;
+ atk_class->ref_state_set = html_a11y_text_ref_state_set;
gobject_class->finalize = html_a11y_text_finalize;
}
@@ -195,6 +231,28 @@
return accessible;
}
+/* atkobject.h */
+
+static AtkStateSet*
+html_a11y_text_ref_state_set (AtkObject *accessible)
+{
+ AtkStateSet *state_set;
+ GtkHTML * html;
+
+ state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (accessible);
+ html = GTK_HTML_A11Y_GTKHTML(html_a11y_get_gtkhtml_parent(HTML_A11Y(accessible)));
+ if (!html || !html->engine)
+ return state_set;
+
+ if (html_engine_get_editable(html->engine))
+ atk_state_set_add_state (state_set, ATK_STATE_EDITABLE);
+
+ atk_state_set_add_state (state_set, ATK_STATE_MULTI_LINE);
+ atk_state_set_add_state (state_set, ATK_STATE_MULTI_LINE);
+
+ return state_set;
+}
+
/*
* AtkComponent interface
*/
@@ -276,6 +334,7 @@
g_return_val_if_fail(p && HTML_IS_TEXT(p), 0);
html = GTK_HTML_A11Y_GTKHTML(html_a11y_get_gtkhtml_parent(HTML_A11Y(text)));
+
g_return_val_if_fail(html && GTK_IS_HTML(html) && html->engine, 0);
e = html_engine_get_top_html_engine(html->engine);
@@ -426,3 +485,156 @@
gint offset);
*/
+
+
+static void
+atk_editable_text_interface_init (AtkEditableTextIface *iface)
+{
+ g_return_if_fail (iface != NULL);
+
+ iface->set_text_contents = html_a11y_text_set_text_contents;
+ iface->insert_text = html_a11y_text_insert_text;
+ iface->copy_text = html_a11y_text_copy_text;
+ iface->cut_text = html_a11y_text_cut_text;
+ iface->delete_text = html_a11y_text_delete_text;
+ iface->paste_text = html_a11y_text_paste_text;
+ iface->set_run_attributes = NULL;
+}
+
+static void
+html_a11y_text_set_text_contents (AtkEditableText *text,
+ const gchar *string)
+{
+ GtkHTML * html;
+ HTMLText *t;
+
+ /* fprintf(stderr, "atk set text contents called \n");*/
+ g_return_if_fail(string);
+
+ html = GTK_HTML_A11Y_GTKHTML(html_a11y_get_gtkhtml_parent(HTML_A11Y(text)));
+ g_return_if_fail(html && html->engine && html_engine_get_editable(html->engine));
+ t = HTML_TEXT(HTML_A11Y_HTML(text));
+ g_return_if_fail (t);
+
+ html_engine_freeze (html->engine);
+ html_text_set_text (t, string);
+ html_engine_thaw (html->engine);
+}
+
+static void
+html_a11y_text_insert_text (AtkEditableText *text,
+ const gchar *string,
+ gint length,
+ gint *position)
+{
+ GtkHTML * html;
+ HTMLText *t;
+ gint index;
+
+ /* fprintf(stderr, "atk insert text called \n"); */
+
+ g_return_if_fail(string && (length > 0));
+ t = HTML_TEXT(HTML_A11Y_HTML(text));
+ g_return_if_fail (t);
+
+ html = GTK_HTML_A11Y_GTKHTML(html_a11y_get_gtkhtml_parent(HTML_A11Y(text)));
+ g_return_if_fail(html && html->engine && html_engine_get_editable(html->engine));
+ html_cursor_jump_to(html->engine->cursor, html->engine, HTML_OBJECT(t), *position);
+ html_engine_paste_text(html->engine, string, -1);
+}
+
+static void
+html_a11y_text_copy_text (AtkEditableText *text,
+ gint start_pos,
+ gint end_pos)
+{
+ GtkHTML * html;
+ gchar * str;
+ HTMLText *t;
+ gint start_index, end_index;
+
+ /* fprintf(stderr, "atk copy text called \n"); */
+ html = GTK_HTML_A11Y_GTKHTML(html_a11y_get_gtkhtml_parent(HTML_A11Y(text)));
+ g_return_if_fail(html && html->engine && html_engine_get_editable(html->engine));
+ t = HTML_TEXT(HTML_A11Y_HTML(text));
+ g_return_if_fail (t);
+
+ html_engine_hide_cursor (html->engine);
+ html_cursor_jump_to(html->engine->cursor, html->engine, HTML_OBJECT(t), start_pos);
+ html_engine_set_mark(html->engine);
+ html_cursor_jump_to(html->engine->cursor, html->engine, HTML_OBJECT(t), end_pos);
+ html_engine_update_selection_if_necessary (html->engine);
+
+ html_engine_copy(html->engine);
+ html_engine_show_cursor (html->engine);
+}
+
+static void
+html_a11y_text_cut_text (AtkEditableText *text,
+ gint start_pos,
+ gint end_pos)
+{
+ GtkHTML * html;
+ HTMLText *t;
+ gint start_index, end_index;
+ gchar * str;
+
+ /* fprintf(stderr, "atk cut text called.\n"); */
+ html = GTK_HTML_A11Y_GTKHTML(html_a11y_get_gtkhtml_parent(HTML_A11Y(text)));
+ g_return_if_fail(html && html->engine && html_engine_get_editable(html->engine));
+ t = HTML_TEXT(HTML_A11Y_HTML(text));
+ g_return_if_fail (t);
+
+ html_engine_hide_cursor (html->engine);
+ html_cursor_jump_to(html->engine->cursor, html->engine, HTML_OBJECT(t), start_pos);
+ html_engine_set_mark(html->engine);
+ html_cursor_jump_to(html->engine->cursor, html->engine, HTML_OBJECT(t), end_pos);
+ html_engine_update_selection_if_necessary (html->engine);
+ html_engine_cut(html->engine);
+ html_engine_show_cursor (html->engine);
+
+ g_signal_emit_by_name(html, "grab_focus");
+}
+
+static void
+html_a11y_text_delete_text (AtkEditableText *text,
+ gint start_pos,
+ gint end_pos)
+{
+ GtkHTML * html;
+ HTMLText *t;
+ gint start_index, end_index;
+ gchar * str;
+
+ /* fprintf(stderr, "atk delete text called.\n"); */
+ html = GTK_HTML_A11Y_GTKHTML(html_a11y_get_gtkhtml_parent(HTML_A11Y(text)));
+ g_return_if_fail(html && html->engine && html_engine_get_editable(html->engine));
+ t = HTML_TEXT(HTML_A11Y_HTML(text));
+ g_return_if_fail (t);
+
+ html_cursor_jump_to(html->engine->cursor, html->engine, HTML_OBJECT(t), start_pos);
+ html_engine_delete_n(html->engine, end_pos-start_pos, TRUE);
+ g_signal_emit_by_name(html, "grab_focus");
+}
+
+static void
+html_a11y_text_paste_text (AtkEditableText *text,
+ gint position)
+{
+ GtkHTML * html;
+ HTMLText *t;
+
+ /* fprintf(stderr, "atk paste text called.\n"); */
+
+ html = GTK_HTML_A11Y_GTKHTML(html_a11y_get_gtkhtml_parent(HTML_A11Y(text)));
+ g_return_if_fail(html && html->engine && html_engine_get_editable(html->engine));
+ t = HTML_TEXT(HTML_A11Y_HTML(text));
+ g_return_if_fail (t);
+
+ html_engine_show_cursor (html->engine);
+ html_cursor_jump_to(html->engine->cursor, html->engine, HTML_OBJECT(t), position);
+ html_engine_paste(html->engine);
+ html_engine_show_cursor (html->engine);
+
+ g_signal_emit_by_name(html, "grab_focus");
+}
Index: utils.c
===================================================================
RCS file: /cvs/gnome/gtkhtml/a11y/utils.c,v
retrieving revision 1.4
diff -u -r1.4 utils.c
--- utils.c 6 Aug 2003 10:47:16 -0000 1.4
+++ utils.c 21 Aug 2003 05:39:22 -0000
@@ -85,6 +85,13 @@
return accessible;
}
+static void
+acc_unref(gpointer data)
+{
+ g_object_set_data(G_OBJECT(data), HTML_ID, NULL);
+ g_object_unref(G_OBJECT(data));
+}
+
AtkObject *
html_utils_get_accessible (HTMLObject *o, AtkObject *parent)
{
@@ -92,13 +99,13 @@
g_return_val_if_fail(o != NULL, NULL);
- accessible = html_object_get_data (o, ACCESSIBLE_ID);
+ accessible = html_object_get_data_nocp (o, ACCESSIBLE_ID);
if (!accessible) {
accessible = create_accessible (o, parent);
if (accessible) {
g_object_ref (accessible);
- html_object_set_data_full (o, ACCESSIBLE_ID, accessible, g_object_unref);
+ html_object_set_data_full_nocp (o, ACCESSIBLE_ID, accessible, acc_unref);
}
}
Index: utils.h
===================================================================
RCS file: /cvs/gnome/gtkhtml/a11y/utils.h,v
retrieving revision 1.2
diff -u -r1.2 utils.h
--- utils.h 1 Nov 2002 15:34:27 -0000 1.2
+++ utils.h 21 Aug 2003 05:39:22 -0000
@@ -28,7 +28,7 @@
#include "htmlobject.h"
#define ACCESSIBLE_ID "atk-accessible-object"
-#define HTML_OBJECT_ACCESSIBLE(o) ATK_OBJECT (html_object_get_data (HTML_OBJECT (o), ACCESSIBLE_ID))
+#define HTML_OBJECT_ACCESSIBLE(o) ATK_OBJECT (html_object_get_data_nocp (HTML_OBJECT (o), ACCESSIBLE_ID))
AtkObject *html_utils_get_accessible (HTMLObject *o, AtkObject *parent);
Index: htmlobject.c
===================================================================
RCS file: /cvs/gnome/gtkhtml/src/htmlobject.c,v
retrieving revision 1.164
diff -u -r1.164 htmlobject.c
--- htmlobject.c 1 Aug 2003 08:43:56 -0000 1.164
+++ htmlobject.c 21 Aug 2003 06:17:00 -0000
@@ -64,7 +64,9 @@
self->next = NULL;
self->prev = NULL;
#endif
+
g_datalist_clear (&self->object_data);
+ g_datalist_clear (&self->object_data_nocp);
if (self->redraw_pending) {
self->free_pending = TRUE;
@@ -98,6 +100,8 @@
g_datalist_init (&dest->object_data);
html_object_copy_data_from_object (dest, self);
+
+ g_datalist_init (&dest->object_data_nocp);
}
static HTMLObject *
@@ -677,6 +681,7 @@
o->draw_focused = FALSE;
g_datalist_init (&o->object_data);
+ g_datalist_init (&o->object_data_nocp);
}
HTMLObject *
@@ -1571,6 +1576,24 @@
html_object_get_index (HTMLObject *self, guint offset)
{
return html_object_is_text (self) ? html_text_get_index (HTML_TEXT (self), offset) : offset;
+}
+
+void
+html_object_set_data_nocp (HTMLObject *object, const gchar *key, const gchar *value)
+{
+ g_datalist_set_data_full (&object->object_data_nocp, key, g_strdup (value), g_free);
+}
+
+void
+html_object_set_data_full_nocp (HTMLObject *object, const gchar *key, const gpointer value, GDestroyNotify func)
+{
+ g_datalist_set_data_full (&object->object_data_nocp, key, value, func);
+}
+
+gpointer
+html_object_get_data_nocp (HTMLObject *object, const gchar *key)
+{
+ return g_datalist_get_data (&object->object_data_nocp, key);
}
void
Index: htmlobject.h
===================================================================
RCS file: /cvs/gnome/gtkhtml/src/htmlobject.h,v
retrieving revision 1.124
diff -u -r1.124 htmlobject.h
--- htmlobject.h 23 Jul 2003 17:35:22 -0000 1.124
+++ htmlobject.h 21 Aug 2003 06:17:01 -0000
@@ -71,6 +71,7 @@
guint draw_focused : 1;
GData *object_data;
+ GData *object_data_nocp;
};
struct _HTMLObjectClearRectangle {
@@ -518,6 +519,18 @@
HTMLObject *src);
gboolean html_object_save_data (HTMLObject *self,
HTMLEngineSaveState *state);
+
+/* for acc object */
+void html_object_set_data_nocp (HTMLObject *object,
+ const gchar *key,
+ const gchar *value);
+void html_object_set_data_full_nocp (HTMLObject *object,
+ const gchar *key,
+ const gpointer value,
+ GDestroyNotify func);
+gpointer html_object_get_data_nocp (HTMLObject *object,
+ const gchar *key);
+
/*
* editing
*/
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]