void html_cluealigned_init (HTMLClueAligned *aligned, HTMLClueAlignedClass *klass, HTMLObject *parent, gint x, gint y, gint max_width, gint percent) { HTMLClue *clue; HTMLObject *object; clue = HTML_CLUE (aligned); object = HTML_OBJECT (aligned); html_clue_init (clue, HTML_CLUE_CLASS (klass)); object->x = x; object->y = y; object->max_width = max_width; object->percent = percent; if (percent > 0) object->flags &= ~HTML_OBJECT_FLAG_FIXEDWIDTH; clue->valign = HTML_VALIGN_BOTTOM; clue->halign = HTML_HALIGN_LEFT; aligned->next_aligned = NULL; object->parent = parent; object->flags |= HTML_OBJECT_FLAG_ALIGNED; }
void html_cluev_init (HTMLClueV *cluev, HTMLClueVClass *klass, gint x, gint y, gint percent) { HTMLObject *object; HTMLClue *clue; object = HTML_OBJECT (cluev); clue = HTML_CLUE (cluev); html_clue_init (clue, HTML_CLUE_CLASS (klass)); object->x = x; object->y = y; object->percent = percent; clue->valign = HTML_VALIGN_BOTTOM; clue->halign = HTML_HALIGN_NONE; cluev->dir = HTML_DIRECTION_DERIVED; clue->head = clue->tail = clue->curr = NULL; cluev->align_left_list = NULL; cluev->align_right_list = NULL; cluev->padding = 0; cluev->border_style = HTML_BORDER_NONE; cluev->border_width = 0; cluev->border_color = NULL; cluev->background_color = NULL; }
HTMLTableCell * html_engine_new_cell (HTMLEngine *e, HTMLTable *table) { HTMLObject *cell; HTMLObject *text; HTMLObject *flow; cell = html_table_cell_new (1, 1, table->padding); flow = html_clueflow_new (HTML_CLUEFLOW_STYLE_NORMAL, g_byte_array_new (), HTML_LIST_TYPE_UNORDERED, 0, HTML_CLEAR_NONE); text = html_engine_new_text_empty (e); html_clue_append (HTML_CLUE (flow), text); html_clue_append (HTML_CLUE (cell), flow); return HTML_TABLE_CELL (cell); }
static void set_max_width (HTMLObject *o, HTMLPainter *painter, gint max_width) { HTMLObject *obj; o->max_width = max_width; max_width -= 2 * (HTML_CLUEV (o)->padding + HTML_CLUEV (o)->border_width) * html_painter_get_pixel_size (painter); for (obj = HTML_CLUE (o)->head; obj != NULL; obj = obj->next) html_object_set_max_width (obj, painter, max_width); }
static void set_max_width (HTMLObject *o, HTMLPainter *painter, gint max_width) { HTMLObject *obj; o->max_width = max_width; for (obj = HTML_CLUE (o)->head; obj != 0; obj = obj->next) html_object_set_max_width (obj, painter, max_width); }
static void set_max_height (HTMLObject *o, HTMLPainter *painter, gint height) { HTMLClue *clue = HTML_CLUE (o); /* Is it necessary to calc size here? It doesn't seem to. */ /* html_object_calc_size (o, painter, NULL); */ if (o->ascent < height) { (* HTML_OBJECT_CLASS (parent_class)->set_max_height) (o, painter, height); clue->curr = NULL; } }
static void table_set_align (HTMLEngine *e, HTMLTable *t, HTMLHAlignType align, HTMLUndoDirection dir) { HTMLTableSetAttrUndo *undo; /* table gone */ if (!t) return; g_return_if_fail (HTML_OBJECT (t)->parent); undo = attr_undo_new (HTML_TABLE_ALIGN); undo->attr.align = HTML_CLUE (HTML_OBJECT (t)->parent)->halign; if (align == HTML_HALIGN_NONE || align == HTML_HALIGN_CENTER) { if (HTML_IS_CLUEALIGNED (HTML_OBJECT (t)->parent)) { HTMLObject *aclue = HTML_OBJECT (t)->parent; html_clue_remove (HTML_CLUE (aclue), HTML_OBJECT (t)); html_clue_append_after (HTML_CLUE (aclue->parent), HTML_OBJECT (t), aclue); html_clue_remove (HTML_CLUE (aclue->parent), aclue); html_object_destroy (aclue); } } else if (align == HTML_HALIGN_LEFT || align == HTML_HALIGN_RIGHT) { if (HTML_IS_CLUEFLOW (HTML_OBJECT (t)->parent)) { HTMLObject *aclue, *flow = HTML_OBJECT (t)->parent; html_clue_remove (HTML_CLUE (flow), HTML_OBJECT (t)); aclue = html_cluealigned_new (NULL, 0, 0, flow->max_width, 100); html_clue_append (HTML_CLUE (flow), aclue); html_clue_append (HTML_CLUE (aclue), HTML_OBJECT (t)); } } else g_assert_not_reached (); html_undo_add_action (e->undo, e, html_undo_action_new ("Set table align", table_set_align_undo_action, HTML_UNDO_DATA (undo), html_cursor_get_position (e->cursor), html_cursor_get_position (e->cursor)), dir); HTML_CLUE (HTML_OBJECT (t)->parent)->halign = align; html_object_change_set (HTML_OBJECT (t)->parent, HTML_CHANGE_ALL_CALC); html_engine_schedule_update (e); }
static gboolean html_clue_aligned_real_calc_size (HTMLObject *o, HTMLPainter *painter, GList **changed_objs) { HTMLObject *obj; gboolean changed; gint old_width, old_ascent; changed = HTML_OBJECT_CLASS (&html_clue_class)->calc_size (o, painter, changed_objs); old_width = o->width; old_ascent = o->ascent; o->width = 0; o->ascent = ALIGN_BORDER; o->descent = 0; /* FIXME: Shouldn't it call `calc_size()' on the children first!?! */ for (obj = HTML_CLUE (o)->head; obj != 0; obj = obj->next) { if (obj->width > o->width) o->width = obj->width; o->ascent += obj->ascent + obj->descent; if (obj->x != ALIGN_BORDER) { obj->x = ALIGN_BORDER; changed = TRUE; } if (obj->y != o->ascent - obj->descent) { obj->y = o->ascent - obj->descent; changed = TRUE; } } o->ascent += ALIGN_BORDER; o->width += ALIGN_BORDER * 2; if (old_width != o->width || old_ascent != o->ascent) changed = TRUE; return changed; }
static gboolean relayout (HTMLObject *self, HTMLEngine *engine, HTMLObject *child) { gint prev_width, prev_ascent, prev_descent; gboolean changed; if (html_engine_frozen (engine)) return FALSE; if (child == NULL) child = HTML_CLUE (self)->head; html_object_calc_size (child, engine->painter, NULL); HTML_CLUE (self)->curr = NULL; prev_width = self->width; prev_ascent = self->ascent; prev_descent = self->descent; changed = html_cluev_do_layout (self, engine->painter, FALSE, NULL); if (changed) html_engine_queue_draw (engine, self); if (prev_width == self->width && prev_ascent == self->ascent && prev_descent == self->descent) return FALSE; if (self->parent == NULL) { /* FIXME resize the widget, e.g. scrollbars and such. */ html_engine_queue_draw (engine, self); /* FIXME extreme ugliness. */ self->x = 0; self->y = self->ascent; } else { /* Relayout our parent starting from us. */ if (!html_object_relayout (self->parent, engine, self)) html_engine_queue_draw (engine, self); } /* If the object has shrunk, we have to clean the areas around it so that we don't leave garbage on the screen. FIXME: this wastes some time if there is an object on the right of or under this one. */ if (prev_ascent + prev_descent > self->ascent + self->descent) html_engine_queue_clear (engine, self->x, self->y + self->descent, self->width, (prev_ascent + prev_descent - (self->ascent + self->descent))); if (prev_width > self->width) html_engine_queue_clear (engine, self->x + self->width, self->y - self->ascent, prev_width - self->width, self->ascent + self->descent); return TRUE; }
static HTMLObject * check_point (HTMLObject *self, HTMLPainter *painter, gint x, gint y, guint *offset_return, gboolean for_cursor) { HTMLObject *p; HTMLObject *obj; HTMLClueAligned *clue; gint padding = HTML_CLUEV (self)->padding; if (x < self->x || x >= self->x + self->width || y < self->y - self->ascent || y >= self->y + self->descent) return NULL; x = x - self->x; y = y - self->y + self->ascent; if (!for_cursor) { if (x < padding || y < padding) { if (offset_return) *offset_return = 0; return self; } if (x >= self->width - padding || y >= self->ascent + self->descent - padding) { if (offset_return) *offset_return = 1; return self; } } for (clue = HTML_CLUEALIGNED (HTML_CLUEV (self)->align_left_list); clue != NULL; clue = clue->next_aligned) { HTMLObject *parent; parent = HTML_OBJECT (clue)->parent; obj = html_object_check_point (HTML_OBJECT (clue), painter, x - parent->x, y - parent->y + parent->ascent, offset_return, for_cursor); if (obj != NULL) { return obj; } } for (clue = HTML_CLUEALIGNED (HTML_CLUEV (self)->align_right_list); clue != NULL; clue = clue->next_aligned) { HTMLObject *parent; parent = HTML_OBJECT (clue)->parent; obj = html_object_check_point (HTML_OBJECT (clue), painter, x - parent->x, y - parent->y + parent->ascent, offset_return, for_cursor); if (obj != NULL) { return obj; } } for (p = HTML_CLUE (self)->head; p != 0; p = p->next) { gint x1, y1; if (!for_cursor) { x1 = x; y1 = y; } else { if (x >= p->x + p->width) { x1 = MAX (0, p->x + p->width - 1); } else if (x < p->x) { x1 = p->x; } else { x1 = x; } if (p->next == NULL && y > p->y + p->descent - 1) { x1 = MAX (0, p->x + p->width - 1); y1 = p->y + p->descent - 1; } else if (p->prev == NULL && y < p->y - p->ascent) { y1 = p->y - p->ascent; } else { y1 = y; } } obj = html_object_check_point (p, painter, x1, y1, offset_return, for_cursor); if (obj != NULL) return obj; } if (!for_cursor) { if (x >= 0 && y >= 0 && x < self->width && y < self->ascent + self->descent) { if (offset_return) { if (x < self->width/2) *offset_return = 0; else *offset_return = 1; } return self; } } return NULL; }
static gboolean html_cluev_do_layout (HTMLObject *o, HTMLPainter *painter, gboolean calc_size, GList **changed_objs) { HTMLClueV *cluev; HTMLClue *clue; HTMLObject *obj; HTMLObject *aclue; GList *local_changed_objs; gint lmargin; gboolean changed; gint old_width, old_ascent, old_descent; gint new_x; gint pixel_size; gint padding; gint padding2; gboolean first_change; gint first_y_off = 0; /* printf ("HTMLClueV::do_layout\n"); */ cluev = HTML_CLUEV (o); clue = HTML_CLUE (o); pixel_size = html_painter_get_pixel_size (painter); padding = pixel_size * (cluev->padding + cluev->border_width); padding2 = 2 * padding; old_width = o->width; old_ascent = o->ascent; old_descent = o->descent; changed = FALSE; first_change = TRUE; local_changed_objs = NULL; lmargin = get_lmargin (o, painter); /* If we have already called calc_size for the children, then just continue from the last object done in previous call. */ if (clue->curr != NULL) { if (clue->curr->prev) o->ascent = clue->curr->prev->y + clue->curr->prev->descent; else o->ascent = padding; remove_aligned_by_parent (cluev, clue->curr); } else { o->width = 0; o->ascent = padding; o->descent = 0; clue->curr = clue->head; } while (clue->curr != NULL) { gint old_y, old_y_off, new_y_off; /* Set an initial ypos so that the alignment stuff knows where the top of this object is */ old_y = clue->curr->y; old_y_off = clue->curr->y - clue->curr->ascent; clue->curr->y = o->ascent; switch (html_object_get_clear (clue->curr)) { case HTML_CLEAR_ALL: { gint y; do { y = clue->curr->y; clue->curr->y = html_clue_get_left_clear (clue, clue->curr->y); clue->curr->y = html_clue_get_right_clear (clue, clue->curr->y); } while (clue->curr->y != y); break; } case HTML_CLEAR_LEFT: clue->curr->y = html_clue_get_left_clear (clue, clue->curr->y); break; case HTML_CLEAR_RIGHT: clue->curr->y = html_clue_get_right_clear (clue, clue->curr->y); break; case HTML_CLEAR_NONE: break; case HTML_CLEAR_INHERIT: /* TODO */ break; } o->ascent = clue->curr->y; lmargin = get_lmargin (o, painter); if (calc_size) changed |= html_object_calc_size (clue->curr, painter, changed_objs); if (o->width < clue->curr->width + padding2) o->width = clue->curr->width + padding2; o->ascent += clue->curr->ascent + clue->curr->descent; new_y_off = o->ascent - clue->curr->descent - clue->curr->ascent; if (clue->curr->x != lmargin || old_y_off != new_y_off) { if (changed_objs) { /* printf ("y: %d ", o->ascent - clue->curr->descent); */ if (first_change) { first_change = FALSE; /* if it's new one (y == 0) clear from new y_off, else from old one or new one, which one is higher */ first_y_off = old_y && old_y_off < new_y_off ? old_y_off : new_y_off; /* printf ("\nfirst_y_off: %d x %d --> %d\n", old_y_off, new_y_off, first_y_off); */ } html_object_add_to_changed (&local_changed_objs, clue->curr); } } clue->curr->x = lmargin; clue->curr->y = o->ascent - clue->curr->descent; clue->curr = clue->curr->next; } o->ascent += padding; /* Remember the last object so that we can start from here next time we are called. */ clue->curr = clue->tail; if (o->max_width != 0 && o->width < o->max_width) o->width = o->max_width; if (clue->halign == HTML_HALIGN_CENTER) { for (obj = clue->head; obj != 0; obj = obj->next) { new_x = lmargin + (o->width - obj->width - padding2) / 2; if (obj->x != new_x) { obj->x = new_x; changed = TRUE; } } } else if (clue->halign == HTML_HALIGN_RIGHT) { for (obj = clue->head; obj != 0; obj = obj->next) { new_x = lmargin + (o->width - obj->width - padding2); if (obj->x != new_x) { obj->x = new_x; changed = TRUE; } } } for (aclue = cluev->align_left_list; aclue != NULL; aclue = cluev_next_aligned (aclue)) { if (aclue->y + aclue->parent->y - aclue->parent->ascent > o->ascent) o->ascent = aclue->y + aclue->parent->y - aclue->parent->ascent; } for (aclue = cluev->align_right_list; aclue != NULL; aclue = cluev_next_aligned (aclue)) { if (aclue->y + aclue->parent->y - aclue->parent->ascent > o->ascent) o->ascent = aclue->y + aclue->parent->y - aclue->parent->ascent; } if (!changed && (o->ascent != old_ascent || o->descent != old_descent || o->width != old_width)) changed = TRUE; if (changed_objs && local_changed_objs) { if (!first_change && o->width > o->max_width) { add_clear_area_behind (changed_objs, o, o->max_width, first_y_off, o->width - o->max_width, o->ascent + o->descent - first_y_off); } *changed_objs = g_list_concat (local_changed_objs, *changed_objs); } return changed; }