Semi-finish widget embedding. Need guffaw scrolling to be implemented in

2000-11-20  Havoc Pennington  <hp@redhat.com>

	* gtk/gtktextview.c, gtk/gtktextlayout.c, gtk/gtktextchild.c,
	gtk/testtext.c: Semi-finish widget embedding. Need guffaw
	scrolling to be implemented in GDK to finish. Also, right now
	we just size_allocate all children on every layout change,
	which is pretty lame. Test commented out of testtext.c,
	until it works better.
This commit is contained in:
Havoc Pennington 2000-11-20 23:51:51 +00:00 committed by Havoc Pennington
parent 2999f465b4
commit 6f7dd53b80
15 changed files with 402 additions and 45 deletions

View File

@ -1,3 +1,12 @@
2000-11-20 Havoc Pennington <hp@redhat.com>
* gtk/gtktextview.c, gtk/gtktextlayout.c, gtk/gtktextchild.c,
gtk/testtext.c: Semi-finish widget embedding. Need guffaw
scrolling to be implemented in GDK to finish. Also, right now
we just size_allocate all children on every layout change,
which is pretty lame. Test commented out of testtext.c,
until it works better.
2000-11-20 Alexander Larsson <alla@lysator.liu.se>
* gdk/linux-fb/gdkdrawable-fb2.c:

View File

@ -1,3 +1,12 @@
2000-11-20 Havoc Pennington <hp@redhat.com>
* gtk/gtktextview.c, gtk/gtktextlayout.c, gtk/gtktextchild.c,
gtk/testtext.c: Semi-finish widget embedding. Need guffaw
scrolling to be implemented in GDK to finish. Also, right now
we just size_allocate all children on every layout change,
which is pretty lame. Test commented out of testtext.c,
until it works better.
2000-11-20 Alexander Larsson <alla@lysator.liu.se>
* gdk/linux-fb/gdkdrawable-fb2.c:

View File

@ -1,3 +1,12 @@
2000-11-20 Havoc Pennington <hp@redhat.com>
* gtk/gtktextview.c, gtk/gtktextlayout.c, gtk/gtktextchild.c,
gtk/testtext.c: Semi-finish widget embedding. Need guffaw
scrolling to be implemented in GDK to finish. Also, right now
we just size_allocate all children on every layout change,
which is pretty lame. Test commented out of testtext.c,
until it works better.
2000-11-20 Alexander Larsson <alla@lysator.liu.se>
* gdk/linux-fb/gdkdrawable-fb2.c:

View File

@ -1,3 +1,12 @@
2000-11-20 Havoc Pennington <hp@redhat.com>
* gtk/gtktextview.c, gtk/gtktextlayout.c, gtk/gtktextchild.c,
gtk/testtext.c: Semi-finish widget embedding. Need guffaw
scrolling to be implemented in GDK to finish. Also, right now
we just size_allocate all children on every layout change,
which is pretty lame. Test commented out of testtext.c,
until it works better.
2000-11-20 Alexander Larsson <alla@lysator.liu.se>
* gdk/linux-fb/gdkdrawable-fb2.c:

View File

@ -1,3 +1,12 @@
2000-11-20 Havoc Pennington <hp@redhat.com>
* gtk/gtktextview.c, gtk/gtktextlayout.c, gtk/gtktextchild.c,
gtk/testtext.c: Semi-finish widget embedding. Need guffaw
scrolling to be implemented in GDK to finish. Also, right now
we just size_allocate all children on every layout change,
which is pretty lame. Test commented out of testtext.c,
until it works better.
2000-11-20 Alexander Larsson <alla@lysator.liu.se>
* gdk/linux-fb/gdkdrawable-fb2.c:

View File

@ -1,3 +1,12 @@
2000-11-20 Havoc Pennington <hp@redhat.com>
* gtk/gtktextview.c, gtk/gtktextlayout.c, gtk/gtktextchild.c,
gtk/testtext.c: Semi-finish widget embedding. Need guffaw
scrolling to be implemented in GDK to finish. Also, right now
we just size_allocate all children on every layout change,
which is pretty lame. Test commented out of testtext.c,
until it works better.
2000-11-20 Alexander Larsson <alla@lysator.liu.se>
* gdk/linux-fb/gdkdrawable-fb2.c:

View File

@ -1,3 +1,12 @@
2000-11-20 Havoc Pennington <hp@redhat.com>
* gtk/gtktextview.c, gtk/gtktextlayout.c, gtk/gtktextchild.c,
gtk/testtext.c: Semi-finish widget embedding. Need guffaw
scrolling to be implemented in GDK to finish. Also, right now
we just size_allocate all children on every layout change,
which is pretty lame. Test commented out of testtext.c,
until it works better.
2000-11-20 Alexander Larsson <alla@lysator.liu.se>
* gdk/linux-fb/gdkdrawable-fb2.c:

View File

@ -1117,10 +1117,10 @@ gtk_text_btree_create_child_anchor (GtkTextIter *iter)
seg = _gtk_widget_segment_new ();
tree = seg->body.child.tree = gtk_text_iter_get_btree (iter);
insert_pixbuf_or_widget_segment (iter, seg);
tree = seg->body.child.tree;
if (tree->child_anchor_table == NULL)
tree->child_anchor_table = g_hash_table_new (NULL, NULL);

View File

@ -242,7 +242,6 @@ _gtk_widget_segment_remove (GtkTextLineSegment *widget_segment,
GtkWidget *child)
{
g_return_if_fail (widget_segment->type = &gtk_text_child_type);
g_return_if_fail (widget_segment->body.child.tree != NULL);
widget_segment->body.child.widgets =
g_slist_remove (widget_segment->body.child.widgets,
@ -420,10 +419,12 @@ gtk_text_child_anchor_unregister_child (GtkTextChildAnchor *anchor,
{
g_return_if_fail (GTK_IS_TEXT_CHILD_ANCHOR (anchor));
g_return_if_fail (GTK_IS_WIDGET (child));
g_return_if_fail (_gtk_anchored_child_get_layout (child) != NULL);
gtk_text_child_anchor_queue_resize (anchor,
_gtk_anchored_child_get_layout (child));
if (_gtk_anchored_child_get_layout (child))
{
gtk_text_child_anchor_queue_resize (anchor,
_gtk_anchored_child_get_layout (child));
}
_gtk_anchored_child_set_layout (child, NULL);
@ -439,10 +440,12 @@ gtk_text_child_anchor_queue_resize (GtkTextChildAnchor *anchor,
GtkTextLineSegment *seg;
g_return_if_fail (GTK_IS_TEXT_CHILD_ANCHOR (anchor));
g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout));
seg = anchor->segment;
g_return_if_fail (seg->body.child.tree != NULL);
if (seg->body.child.tree == NULL)
return NULL;
gtk_text_buffer_get_iter_at_child_anchor (layout->buffer,
&start, anchor);
@ -452,3 +455,14 @@ gtk_text_child_anchor_queue_resize (GtkTextChildAnchor *anchor,
gtk_text_layout_invalidate (layout, &start, &end);
}
void
gtk_text_anchored_child_set_layout (GtkWidget *child,
GtkTextLayout *layout)
{
g_return_if_fail (GTK_IS_WIDGET (child));
g_return_if_fail (layout == NULL || GTK_IS_TEXT_LAYOUT (layout));
_gtk_anchored_child_set_layout (child, layout);
}

View File

@ -365,21 +365,30 @@ render_layout_line (GdkDrawable *drawable,
gint width, height;
GdkRectangle draw_rect;
GtkWidget *widget;
/* FIXME this doesn't work at all, and remember to use
* risen_y
*/
widget = GTK_WIDGET (shaped);
width = widget->allocation.width;
height = widget->allocation.height;
printf ("widget allocation at %d,%d %d x %d\n",
widget->allocation.x,
widget->allocation.y,
widget->allocation.width,
widget->allocation.height);
if (GTK_WIDGET_DRAWABLE (widget) &&
gtk_widget_intersect (widget,
&render_state->clip_rect,
&draw_rect))
gdk_rectangle_intersect (&widget->allocation,
&render_state->clip_rect,
&draw_rect))
{
printf ("drawing widget area %d,%d %d x %d\n",
draw_rect.x,
draw_rect.y,
draw_rect.width,
draw_rect.height);
gtk_widget_draw (widget, &draw_rect);
}

View File

@ -1346,7 +1346,8 @@ add_child_attrs (GtkTextLayout *layout,
height = req.height;
display->shaped_objects =
g_slist_append (display->shaped_objects, child);
g_slist_append (display->shaped_objects, child);
break;
}
@ -1430,17 +1431,69 @@ add_cursor (GtkTextLayout *layout,
}
}
static gboolean
is_shape (PangoLayoutRun *run)
{
GSList *tmp_list = run->item->extra_attrs;
while (tmp_list)
{
PangoAttribute *attr = tmp_list->data;
if (attr->klass->type == PANGO_ATTR_SHAPE)
return TRUE;
tmp_list = tmp_list->next;
}
return FALSE;
}
static void
allocate_child_widgets (GtkTextLayout *layout,
allocate_child_widgets (GtkTextLayout *text_layout,
GtkTextLineDisplay *display)
{
GSList *shaped = display->shaped_objects;
PangoLayout *layout = display->layout;
PangoLayoutIter *iter;
#if 0
gtk_signal_emit (GTK_OBJECT (layout),
signals[ALLOCATE_CHILD],
child,
x, y);
#endif
iter = pango_layout_get_iter (layout);
do
{
PangoLayoutRun *run = pango_layout_iter_get_run (iter);
if (run && is_shape (run))
{
GObject *shaped_object = shaped->data;
shaped = shaped->next;
if (GTK_IS_WIDGET (shaped_object))
{
PangoRectangle extents;
/* We emit "allocate_child" with the x,y of
* the widget with respect to the top of the line
* and the left side of the buffer
*/
pango_layout_iter_get_run_extents (iter,
NULL,
&extents);
printf ("extents at %d,%d\n", extents.x, extents.y);
gtk_signal_emit (GTK_OBJECT (text_layout),
signals[ALLOCATE_CHILD],
shaped_object,
PANGO_PIXELS (extents.x) + display->x_offset,
PANGO_PIXELS (extents.y) + display->top_margin);
}
}
}
while (pango_layout_iter_next_run (iter));
pango_layout_iter_free (iter);
}
static void
@ -1548,7 +1601,8 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
GSList *cursor_byte_offsets = NULL;
GSList *cursor_segs = NULL;
GSList *tmp_list1, *tmp_list2;
gboolean saw_widget = FALSE;
g_return_val_if_fail (line != NULL, NULL);
if (layout->one_display_cache)
@ -1688,6 +1742,8 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
}
else if (seg->type == &gtk_text_child_type)
{
saw_widget = TRUE;
add_generic_attrs (layout, &style->appearance,
seg->byte_count,
attrs, byte_offset,
@ -1804,7 +1860,8 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
layout->one_display_cache = display;
allocate_child_widgets (layout, display);
if (saw_widget)
allocate_child_widgets (layout, display);
return display;
}

View File

@ -368,6 +368,9 @@ void gtk_text_child_anchor_unregister_child (GtkTextChildAnchor *anchor,
void gtk_text_child_anchor_queue_resize (GtkTextChildAnchor *anchor,
GtkTextLayout *layout);
void gtk_text_anchored_child_set_layout (GtkWidget *child,
GtkTextLayout *layout);
void gtk_text_layout_spew (GtkTextLayout *layout);
#ifdef __cplusplus

View File

@ -244,6 +244,9 @@ struct _GtkTextViewChild
GtkTextChildAnchor *anchor;
gint from_top_of_line;
gint from_left_of_buffer;
/* These are ignored if anchor != NULL */
GtkTextWindowType type;
gint x;
@ -1613,9 +1616,12 @@ static void
gtk_text_view_destroy (GtkObject *object)
{
GtkTextView *text_view;
GtkTextLayout *layout;
text_view = GTK_TEXT_VIEW (object);
layout = text_view->layout;
gtk_text_view_destroy_layout (text_view);
gtk_text_view_set_buffer (text_view, NULL);
@ -1835,12 +1841,63 @@ gtk_text_view_size_request (GtkWidget *widget,
}
static void
gtk_text_view_allocate_children (GtkTextView *text_view)
gtk_text_view_update_child_allocation (GtkTextView *text_view,
GtkTextViewChild *vc)
{
gint buffer_y;
GtkTextIter iter;
GtkAllocation allocation;
gtk_text_buffer_get_iter_at_child_anchor (get_buffer (text_view),
&iter,
vc->anchor);
gtk_text_layout_get_line_yrange (text_view->layout, &iter,
&buffer_y, NULL);
buffer_y += vc->from_top_of_line;
allocation.x = vc->from_left_of_buffer;
allocation.y = buffer_y;
allocation.width = vc->widget->requisition.width;
allocation.height = vc->widget->requisition.height;
gtk_widget_size_allocate (vc->widget, &allocation);
}
static void
gtk_text_view_child_allocated (GtkTextLayout *layout,
GtkWidget *child,
gint x,
gint y,
gpointer data)
{
GtkTextViewChild *vc = NULL;
GtkTextView *text_view = data;
/* x,y is the position of the child from the top of the line, and
* from the left of the buffer. We have to translate that into text
* window coordinates, then size_allocate the child.
*/
vc = gtk_object_get_data (GTK_OBJECT (child),
"gtk-text-view-child");
g_assert (vc != NULL);
printf ("child allocated at %d,%d\n", x, y);
vc->from_left_of_buffer = x;
vc->from_top_of_line = y;
gtk_text_view_update_child_allocation (text_view, vc);
}
static void
gtk_text_view_validate_children (GtkTextView *text_view)
{
GSList *tmp_list;
return;
tmp_list = text_view->children;
while (tmp_list != NULL)
{
@ -1982,7 +2039,7 @@ gtk_text_view_size_allocate (GtkWidget *widget,
gtk_text_layout_set_screen_width (text_view->layout,
SCREEN_WIDTH (text_view));
gtk_text_view_allocate_children (text_view);
gtk_text_view_validate_children (text_view);
gtk_text_view_validate_onscreen (text_view);
gtk_text_view_scroll_calc_now (text_view);
@ -2146,7 +2203,8 @@ changed_handler (GtkTextLayout *layout,
if (old_height != new_height)
{
gboolean yoffset_changed = FALSE;
GSList *tmp_list;
if (start_y + old_height <= text_view->yoffset - text_view->first_para_pixels)
{
text_view->yoffset += new_height - old_height;
@ -2156,6 +2214,19 @@ changed_handler (GtkTextLayout *layout,
if (yoffset_changed)
gtk_adjustment_value_changed (get_vadjustment (text_view));
/* FIXME be smarter about which anchored widgets we update */
tmp_list = text_view->children;
while (tmp_list != NULL)
{
GtkTextViewChild *child = tmp_list->data;
if (child->anchor)
gtk_text_view_update_child_allocation (text_view, child);
tmp_list = g_slist_next (tmp_list);
}
}
gtk_text_view_scroll_calc_now (text_view);
@ -2167,7 +2238,8 @@ gtk_text_view_realize (GtkWidget *widget)
GtkTextView *text_view;
GdkWindowAttr attributes;
gint attributes_mask;
GSList *tmp_list;
text_view = GTK_TEXT_VIEW (widget);
GTK_WIDGET_SET_FLAGS (text_view, GTK_REALIZED);
@ -2218,7 +2290,8 @@ static void
gtk_text_view_unrealize (GtkWidget *widget)
{
GtkTextView *text_view;
GSList *tmp_list;
text_view = GTK_TEXT_VIEW (widget);
if (text_view->first_validate_idle)
@ -2254,7 +2327,7 @@ gtk_text_view_unrealize (GtkWidget *widget)
text_window_unrealize (text_view->bottom_window);
gtk_text_view_destroy_layout (text_view);
(* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
}
@ -3685,7 +3758,8 @@ gtk_text_view_ensure_layout (GtkTextView *text_view)
{
GtkTextAttributes *style;
PangoContext *ltr_context, *rtl_context;
GSList *tmp_list;
text_view->layout = gtk_text_layout_new ();
gtk_signal_connect (GTK_OBJECT (text_view->layout),
@ -3698,6 +3772,11 @@ gtk_text_view_ensure_layout (GtkTextView *text_view)
GTK_SIGNAL_FUNC (changed_handler),
text_view);
gtk_signal_connect (GTK_OBJECT (text_view->layout),
"allocate_child",
GTK_SIGNAL_FUNC (gtk_text_view_child_allocated),
text_view);
if (get_buffer (text_view))
gtk_text_layout_set_buffer (text_view->layout, get_buffer (text_view));
@ -3737,6 +3816,23 @@ gtk_text_view_ensure_layout (GtkTextView *text_view)
gtk_text_layout_set_default_style (text_view->layout, style);
gtk_text_attributes_unref (style);
/* Set layout for all anchored children */
tmp_list = text_view->children;
while (tmp_list != NULL)
{
GtkTextViewChild *vc = tmp_list->data;
if (vc->anchor)
{
gtk_text_anchored_child_set_layout (vc->widget,
text_view->layout);
/* vc may now be invalid! */
}
tmp_list = g_slist_next (tmp_list);
}
}
}
@ -3745,6 +3841,23 @@ gtk_text_view_destroy_layout (GtkTextView *text_view)
{
if (text_view->layout)
{
/* Remove layout from all anchored children */
GSList *tmp_list;
tmp_list = text_view->children;
while (tmp_list != NULL)
{
GtkTextViewChild *vc = tmp_list->data;
if (vc->anchor)
{
gtk_text_anchored_child_set_layout (vc->widget, NULL);
/* vc may now be invalid! */
}
tmp_list = g_slist_next (tmp_list);
}
gtk_text_view_stop_cursor_blink (text_view);
gtk_text_view_end_selection_drag (text_view, NULL);
@ -5178,6 +5291,9 @@ text_view_child_new_anchored (GtkWidget *child,
vc->widget = child;
vc->anchor = anchor;
vc->from_top_of_line = 0;
vc->from_left_of_buffer = 0;
g_object_ref (G_OBJECT (vc->widget));
g_object_ref (G_OBJECT (vc->anchor));
@ -5186,7 +5302,7 @@ text_view_child_new_anchored (GtkWidget *child,
vc);
gtk_text_child_anchor_register_child (anchor, child, layout);
return vc;
}
@ -5203,6 +5319,9 @@ text_view_child_new_window (GtkWidget *child,
vc->widget = child;
vc->anchor = NULL;
vc->from_top_of_line = 0;
vc->from_left_of_buffer = 0;
g_object_ref (G_OBJECT (vc->widget));
vc->type = type;

View File

@ -65,6 +65,7 @@ static void check_close_view (View *view);
static void close_view (View *view);
static void view_set_title (View *view);
static void view_init_menus (View *view);
static void view_add_example_widgets (View *view);
GSList *buffers = NULL;
GSList *views = NULL;
@ -419,8 +420,6 @@ static char *book_closed_xpm[] = {
" .. ",
" "};
void
fill_example_buffer (GtkTextBuffer *buffer)
{
@ -431,7 +430,8 @@ fill_example_buffer (GtkTextBuffer *buffer)
GdkPixbuf *pixbuf;
int i;
char *str;
GtkTextChildAnchor *anchor;
/* FIXME this is broken if called twice on a buffer, since
* we try to create tags a second time.
*/
@ -513,6 +513,18 @@ fill_example_buffer (GtkTextBuffer *buffer)
"left_margin", 20,
"right_margin", 20,
NULL);
#if 0
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
g_object_ref (G_OBJECT (anchor));
g_object_set_data_full (G_OBJECT (buffer), "anchor", anchor,
(GDestroyNotify) g_object_unref);
#endif
pixbuf = gdk_pixbuf_new_from_xpm_data (book_closed_xpm);
@ -840,6 +852,8 @@ do_example (gpointer callback_data,
new_view = get_empty_view (view);
fill_example_buffer (new_view->buffer->buffer);
view_add_example_widgets (new_view);
}
static void
@ -2103,7 +2117,7 @@ create_view (Buffer *buffer)
GtkWidget *sw;
GtkWidget *vbox;
view = g_new0 (View, 1);
views = g_slist_prepend (views, view);
@ -2185,11 +2199,43 @@ create_view (Buffer *buffer)
view_set_title (view);
view_init_menus (view);
view_add_example_widgets (view);
gtk_widget_show_all (view->window);
return view;
}
static void
view_add_example_widgets (View *view)
{
GtkTextChildAnchor *anchor;
Buffer *buffer;
return;
buffer = view->buffer;
anchor = gtk_object_get_data (GTK_OBJECT (buffer->buffer),
"anchor");
if (anchor && !gtk_text_child_anchor_get_deleted (anchor))
{
GtkWidget *widget;
widget = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
GTK_ICON_SIZE_DIALOG);
widget = gtk_button_new_with_label ("Foo");
gtk_text_view_add_child_at_anchor (GTK_TEXT_VIEW (view->text_view),
widget,
anchor);
gtk_widget_show (widget);
}
}
static gboolean
file_exists (const char *filename)
{

View File

@ -65,6 +65,7 @@ static void check_close_view (View *view);
static void close_view (View *view);
static void view_set_title (View *view);
static void view_init_menus (View *view);
static void view_add_example_widgets (View *view);
GSList *buffers = NULL;
GSList *views = NULL;
@ -419,8 +420,6 @@ static char *book_closed_xpm[] = {
" .. ",
" "};
void
fill_example_buffer (GtkTextBuffer *buffer)
{
@ -431,7 +430,8 @@ fill_example_buffer (GtkTextBuffer *buffer)
GdkPixbuf *pixbuf;
int i;
char *str;
GtkTextChildAnchor *anchor;
/* FIXME this is broken if called twice on a buffer, since
* we try to create tags a second time.
*/
@ -513,6 +513,18 @@ fill_example_buffer (GtkTextBuffer *buffer)
"left_margin", 20,
"right_margin", 20,
NULL);
#if 0
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
g_object_ref (G_OBJECT (anchor));
g_object_set_data_full (G_OBJECT (buffer), "anchor", anchor,
(GDestroyNotify) g_object_unref);
#endif
pixbuf = gdk_pixbuf_new_from_xpm_data (book_closed_xpm);
@ -840,6 +852,8 @@ do_example (gpointer callback_data,
new_view = get_empty_view (view);
fill_example_buffer (new_view->buffer->buffer);
view_add_example_widgets (new_view);
}
static void
@ -2103,7 +2117,7 @@ create_view (Buffer *buffer)
GtkWidget *sw;
GtkWidget *vbox;
view = g_new0 (View, 1);
views = g_slist_prepend (views, view);
@ -2185,11 +2199,43 @@ create_view (Buffer *buffer)
view_set_title (view);
view_init_menus (view);
view_add_example_widgets (view);
gtk_widget_show_all (view->window);
return view;
}
static void
view_add_example_widgets (View *view)
{
GtkTextChildAnchor *anchor;
Buffer *buffer;
return;
buffer = view->buffer;
anchor = gtk_object_get_data (GTK_OBJECT (buffer->buffer),
"anchor");
if (anchor && !gtk_text_child_anchor_get_deleted (anchor))
{
GtkWidget *widget;
widget = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
GTK_ICON_SIZE_DIALOG);
widget = gtk_button_new_with_label ("Foo");
gtk_text_view_add_child_at_anchor (GTK_TEXT_VIEW (view->text_view),
widget,
anchor);
gtk_widget_show (widget);
}
}
static gboolean
file_exists (const char *filename)
{