예제 #1
0
파일: adg-table-cell.c 프로젝트: bert/adg
/**
 * adg_table_cell_size_request:
 * @table_cell: a valid #AdgTableCell
 * @row_extents: the extents of the container #AdgTableRow
 *
 * Computes the minimum space needed to properly render @table_cell
 * and updates the size component of the internal #CpmlExtents struct,
 * returning it to the caller. The returned #CpmlPair is owned by
 * @table_cell and should not be modified or freed.
 *
 * Returns: (transfer none): the minimum size required.
 *
 * Since: 1.0
 **/
const CpmlPair *
adg_table_cell_size_request(AdgTableCell *table_cell,
                            const CpmlExtents *row_extents)
{
    CpmlVector *size;
    AdgAlignment *title_alignment;
    AdgAlignment *value_alignment;
    AdgTable *table;

    size = &table_cell->extents.size;

    if (table_cell->title) {
        title_alignment = (AdgAlignment *) adg_entity_get_parent(table_cell->title);
        adg_entity_arrange((AdgEntity *) title_alignment);
    } else {
        title_alignment = NULL;
    }

    if (table_cell->value) {
        value_alignment = (AdgAlignment *) adg_entity_get_parent(table_cell->value);
        adg_entity_arrange((AdgEntity *) value_alignment);
    } else {
        value_alignment = NULL;
    }

    table = adg_table_cell_get_table(table_cell);
    size->y = row_extents->size.y;

    if (table_cell->width == 0) {
        AdgTableStyle *table_style = (AdgTableStyle *) adg_table_get_table_style(table);
        const CpmlExtents *extents;

        /* The width depends on the cell content (default = 0) */
        size->x = 0;

        if (title_alignment) {
            extents = adg_entity_get_extents((AdgEntity *) title_alignment);
            size->x = extents->size.x;
        }

        if (value_alignment) {
            extents = adg_entity_get_extents((AdgEntity *) value_alignment);
            if (extents->size.x > size->x)
                size->x = extents->size.x;
        }

        size->x += adg_table_style_get_cell_spacing(table_style)->x * 2;
    } else {
        size->x = table_cell->width;
    }

    return size;
}
예제 #2
0
파일: adg-alignment.c 프로젝트: ntd/adg
static void
_adg_arrange(AdgEntity *entity)
{
    AdgAlignmentPrivate *data;
    const CpmlExtents *extents;
    CpmlExtents new_extents;
    cairo_matrix_t ctm, ctm_inverted, old_map;

    if (_ADG_OLD_ENTITY_CLASS->arrange == NULL)
        return;

    data = adg_alignment_get_instance_private((AdgAlignment *) entity);
    extents = adg_entity_get_extents(entity);
    data->shift.x = 0;
    data->shift.y = 0;

    /* The shift is performed only when relevant */
    if (data->factor.x != 0 || data->factor.y != 0) {
        /* Force the ctm to be the identity matrix */
        adg_matrix_copy(&old_map, adg_entity_get_global_map(entity));
        adg_matrix_copy(&ctm, adg_entity_get_global_map(entity));
        adg_matrix_transform(&ctm, adg_entity_get_local_matrix(entity),
                             ADG_TRANSFORM_AFTER);
        adg_matrix_copy(&ctm_inverted, &ctm);
        cairo_matrix_invert(&ctm_inverted);
        adg_entity_transform_global_map(entity, &ctm_inverted,
                                        ADG_TRANSFORM_AFTER);
        adg_entity_global_changed(entity);

        /* Calculating the shift */
        _ADG_OLD_ENTITY_CLASS->arrange(entity);
        extents = adg_entity_get_extents(entity);
        if (extents->is_defined) {
            data->shift.x = -extents->size.x * data->factor.x;
            data->shift.y = -extents->size.y * data->factor.y;
            cpml_vector_transform(&data->shift, &ctm);
        }

        /* Restore the old global map */
        adg_entity_set_global_map(entity, &old_map);
        adg_entity_global_changed(entity);
    }

    /* Add the shift to the extents */
    _ADG_OLD_ENTITY_CLASS->arrange(entity);
    cpml_extents_copy(&new_extents, adg_entity_get_extents(entity));
    new_extents.org.x += data->shift.x;
    new_extents.org.y += data->shift.y;
    adg_entity_set_extents(entity, &new_extents);
}
예제 #3
0
파일: adg-stroke.c 프로젝트: bert/adg
static void
_adg_arrange(AdgEntity *entity)
{
    AdgStroke *stroke;
    AdgStrokePrivate *data;
    const CpmlExtents *trail_extents;
    CpmlExtents extents;

    /* Check for cached result */
    if (adg_entity_get_extents(entity)->is_defined)
        return;

    stroke = (AdgStroke *) entity;
    data = stroke->data;
    trail_extents = adg_trail_get_extents(data->trail);

    /* Ensure a trail is bound to this entity */
    if (trail_extents == NULL)
        return;

    cpml_extents_copy(&extents, trail_extents);
    cpml_extents_transform(&extents, adg_entity_get_local_matrix(entity));
    cpml_extents_transform(&extents, adg_entity_get_global_matrix(entity));
    adg_entity_set_extents(entity, &extents);
}
예제 #4
0
파일: adg-gtk-area.c 프로젝트: ntd/adg
static const CpmlExtents *
_adg_get_extents(AdgGtkArea *area)
{
    AdgGtkAreaPrivate *data = adg_gtk_area_get_instance_private(area);
    CpmlExtents old_extents = data->extents;
    AdgCanvas *canvas = data->canvas;

    data->extents.is_defined = FALSE;

    if (ADG_IS_CANVAS(canvas)) {
        const CpmlExtents *extents;
        AdgEntity *entity;

        entity = (AdgEntity *) canvas;

        adg_entity_arrange(entity);
        extents = adg_entity_get_extents(entity);

        if (extents != NULL) {
            data->extents = *extents;
            adg_canvas_apply_margins(canvas, &data->extents);
            cpml_extents_transform(&data->extents, &data->render_map);
        }
    }

    if (!cpml_extents_equal(&data->extents, &old_extents))
        g_signal_emit(area, _adg_signals[EXTENTS_CHANGED], 0, &old_extents);

    return &data->extents;
}
예제 #5
0
파일: test-canvas.c 프로젝트: ntd/adg
static void
_adg_behavior_entity(void)
{
    AdgCanvas *canvas;
    const CpmlExtents *extents;
    AdgTitleBlock *title_block;

    canvas = ADG_CANVAS(adg_test_canvas());

    adg_entity_arrange(ADG_ENTITY(canvas));
    extents = adg_entity_get_extents(ADG_ENTITY(canvas));
    g_assert_true(extents->is_defined);
    adg_assert_isapprox(extents->size.x, 1);
    adg_assert_isapprox(extents->size.y, 1);

    adg_entity_invalidate(ADG_ENTITY(canvas));
    extents = adg_entity_get_extents(ADG_ENTITY(canvas));
    g_assert_false(extents->is_defined);

    title_block = adg_title_block_new();
    adg_canvas_set_title_block(canvas, title_block);
    adg_entity_arrange(ADG_ENTITY(canvas));
    extents = adg_entity_get_extents(ADG_ENTITY(canvas));
    g_assert_true(extents->is_defined);
    g_assert_cmpfloat(extents->size.x, >, 1);
    g_assert_cmpfloat(extents->size.y, >, 1);
    g_assert_cmpfloat(extents->size.x, <, 5000);
    g_assert_cmpfloat(extents->size.y, <, 5000);

    adg_canvas_set_size_explicit(canvas, 5000, 5000);
    adg_entity_arrange(ADG_ENTITY(canvas));
    extents = adg_entity_get_extents(ADG_ENTITY(canvas));
    g_assert_true(extents->is_defined);
    adg_assert_isapprox(extents->size.x, 5000);
    adg_assert_isapprox(extents->size.y, 5000);

    adg_entity_destroy(ADG_ENTITY(canvas));
}
예제 #6
0
파일: adg-dim.c 프로젝트: bert/adg
static void
_adg_arrange(AdgEntity *entity)
{
    AdgDim *dim;
    AdgDimPrivate *data;
    AdgEntity *quote_entity;
    AdgContainer *quote_container;
    AdgEntity *value_entity;
    AdgEntity *min_entity;
    AdgEntity *max_entity;
    const CpmlPair *shift;
    cairo_matrix_t map;

    dim = (AdgDim *) entity;
    data = dim->data;

    /* Resolve the dim style */
    if (data->dim_style == NULL)
        data->dim_style = (AdgDimStyle *)
            adg_entity_style(entity, data->dim_dress);

    if (data->quote.entity == NULL)
        data->quote.entity = g_object_new(ADG_TYPE_ALIGNMENT,
                                          "local-mix", ADG_MIX_NONE,
                                          "parent", dim, NULL);

    quote_entity = (AdgEntity *) data->quote.entity;
    quote_container = (AdgContainer *) data->quote.entity;

    if (data->quote.value == NULL) {
        AdgDimClass *klass;
        AdgDress dress;
        const gchar *tag;
        gchar *value;
        gchar *text;

        klass = ADG_DIM_GET_CLASS(dim);
        dress = adg_dim_style_get_value_dress(data->dim_style);
        tag = adg_dim_style_get_number_tag(data->dim_style);
        value = klass->default_value ? klass->default_value(dim) : NULL;

        data->quote.value = g_object_new(ADG_TYPE_BEST_TEXT,
                                         "local-mix", ADG_MIX_PARENT,
                                         "font-dress", dress, NULL);
        adg_container_add(quote_container, (AdgEntity *) data->quote.value);

        if (data->value)
            text = adg_string_replace(data->value, tag, value);
        else
            text = g_strdup(value);

        g_free(value);

        adg_textual_set_text(data->quote.value, text);
        g_free(text);
    }

    if (data->quote.min == NULL && data->min != NULL) {
        AdgDress dress = adg_dim_style_get_min_dress(data->dim_style);

        data->quote.min = g_object_new(ADG_TYPE_BEST_TEXT,
                                       "local-mix", ADG_MIX_PARENT,
                                       "font-dress", dress, NULL);

        adg_container_add(quote_container, (AdgEntity *) data->quote.min);
        adg_textual_set_text(data->quote.min, data->min);
    }

    if (data->quote.max == NULL && data->max != NULL) {
        AdgDress dress = adg_dim_style_get_max_dress(data->dim_style);

        data->quote.max = g_object_new(ADG_TYPE_BEST_TEXT,
                                       "local-mix", ADG_MIX_PARENT,
                                       "font-dress", dress, NULL);

        adg_container_add(quote_container, (AdgEntity *) data->quote.max);
        adg_textual_set_text(data->quote.max, data->max);
    }

    value_entity = (AdgEntity *) data->quote.value;
    min_entity = (AdgEntity *) data->quote.min;
    max_entity = (AdgEntity *) data->quote.max;
    shift = adg_dim_style_get_quote_shift(data->dim_style);

    adg_entity_set_global_map(quote_entity, adg_matrix_identity());
    adg_entity_global_changed(quote_entity);

    cairo_matrix_init_translate(&map, 0, shift->y);
    adg_entity_set_global_map(value_entity, &map);
    adg_entity_arrange(value_entity);

    /* Limit values (min and max) */
    if (min_entity != NULL || max_entity != NULL) {
        const CpmlPair *limits_shift;
        gdouble spacing;
        CpmlPair size;
        CpmlPair org_min, org_max;

        limits_shift = adg_dim_style_get_limits_shift(data->dim_style);
        spacing = adg_dim_style_get_limits_spacing(data->dim_style);
        size = adg_entity_get_extents(value_entity)->size;
        org_min.x = size.x + limits_shift->x;
        org_min.y = -size.y / 2 + limits_shift->y;
        org_max = org_min;

        if (min_entity && max_entity) {
            /* Prearrange the min entity to get its extents */
            adg_entity_arrange(min_entity);
            size = adg_entity_get_extents(min_entity)->size;

            org_min.y += spacing / 2;
            org_max.y = org_min.y - size.y - spacing / 2;
        }

        if (min_entity != NULL) {
            cairo_matrix_init_translate(&map, org_min.x, org_min.y);
            adg_entity_set_global_map(min_entity, &map);
            adg_entity_arrange(min_entity);
        }

        if (max_entity != NULL) {
            cairo_matrix_init_translate(&map, org_max.x, org_max.y);
            adg_entity_set_global_map(max_entity, &map);
            adg_entity_arrange(max_entity);
        }
    }
}
예제 #7
0
파일: adg-adim.c 프로젝트: bert/adg
static void
_adg_arrange(AdgEntity *entity)
{
    AdgADim *adim;
    AdgDim *dim;
    AdgADimPrivate *data;
    AdgAlignment *quote;
    const cairo_matrix_t *global, *local;
    CpmlPair ref1, ref2, base1, base12, base2;
    CpmlPair pair;
    CpmlExtents extents;
    AdgEntity *marker_entity;

    if (_ADG_OLD_ENTITY_CLASS->arrange)
        _ADG_OLD_ENTITY_CLASS->arrange(entity);

    adim = (AdgADim *) entity;

    if (! _adg_update_geometry(adim))
        return;

    dim = (AdgDim *) adim;
    data = adim->data;
    quote = adg_dim_get_quote(dim);

    _adg_update_entities(adim);

    if (data->cairo.path.status == CAIRO_STATUS_SUCCESS) {
        AdgEntity *quote_entity = (AdgEntity *) quote;
        adg_entity_set_global_map(quote_entity, &data->quote.global_map);
        return;
    }

    global = adg_entity_get_global_matrix(entity);
    local = adg_entity_get_local_matrix(entity);
    extents.is_defined = FALSE;

    cpml_pair_copy(&ref1, (CpmlPair *) adg_dim_get_ref1(dim));
    cpml_pair_copy(&ref2, (CpmlPair *) adg_dim_get_ref2(dim));
    cpml_pair_copy(&base1, &data->point.base1);
    cpml_pair_copy(&base12, &data->point.base12);
    cpml_pair_copy(&base2, &data->point.base2);

    /* Apply the local matrix to the relevant points */
    cpml_pair_transform(&ref1, local);
    cpml_pair_transform(&ref2, local);
    cpml_pair_transform(&base1, local);
    cpml_pair_transform(&base12, local);
    cpml_pair_transform(&base2, local);

    /* Combine points and global shifts to build the path */
    pair.x = ref1.x + data->shift.from1.x;
    pair.y = ref1.y + data->shift.from1.y;
    cpml_pair_to_cairo(&pair, &data->cairo.data[6]);

    pair.x = base1.x + data->shift.base1.x;
    pair.y = base1.y + data->shift.base1.y;
    cpml_pair_to_cairo(&pair, &data->cairo.data[1]);

    pair.x += data->shift.to1.x;
    pair.y += data->shift.to1.y;
    cpml_pair_to_cairo(&pair, &data->cairo.data[8]);

    pair.x = base12.x + data->shift.base12.x;
    pair.y = base12.y + data->shift.base12.y;
    cpml_pair_to_cairo(&pair, &data->cairo.data[3]);

    pair.x = ref2.x + data->shift.from2.x;
    pair.y = ref2.y + data->shift.from2.y;
    cpml_pair_to_cairo(&pair, &data->cairo.data[10]);

    pair.x = base2.x + data->shift.base2.x;
    pair.y = base2.y + data->shift.base2.y;
    cpml_pair_to_cairo(&pair, &data->cairo.data[4]);

    pair.x += data->shift.to2.x;
    pair.y += data->shift.to2.y;
    cpml_pair_to_cairo(&pair, &data->cairo.data[12]);

    /* Play with header lengths to show or hide the extension lines */
    if (data->has_extension1) {
        data->cairo.data[7].header.length = data->has_extension2 ? 2 : 6;
    } else {
        data->cairo.data[2].header.length = data->has_extension2 ? 7 : 11;
    }

    data->cairo.path.status = CAIRO_STATUS_SUCCESS;

    /* Arrange the quote */
    if (quote != NULL) {
        AdgEntity *quote_entity;
        gdouble angle;
        cairo_matrix_t map;

        quote_entity = (AdgEntity *) quote;
        angle = adg_dim_quote_angle(dim, (data->angle1 + data->angle2) / 2 + G_PI_2);
        cpml_pair_from_cairo(&pair, &data->cairo.data[3]);

        adg_alignment_set_factor_explicit(quote, 0.5, 0);

        cairo_matrix_init_translate(&map, pair.x, pair.y);
        cairo_matrix_rotate(&map, angle);
        adg_entity_set_global_map(quote_entity, &map);
        adg_entity_arrange(quote_entity);
        cpml_extents_add(&extents, adg_entity_get_extents(quote_entity));

        adg_matrix_copy(&data->quote.global_map, &map);
    }

    /* Arrange the trail */
    if (data->trail != NULL) {
        CpmlExtents trail_extents;
        cpml_extents_copy(&trail_extents, adg_trail_get_extents(data->trail));
        cpml_extents_transform(&trail_extents, global);
        cpml_extents_add(&extents, &trail_extents);
    } else {
        _adg_dispose_markers(adim);
    }

    /* Arrange the markers */
    if (data->marker1 != NULL) {
        marker_entity = (AdgEntity *) data->marker1;
        adg_marker_set_segment(data->marker1, data->trail, 1);
        adg_entity_local_changed(marker_entity);
        adg_entity_arrange(marker_entity);
        cpml_extents_add(&extents, adg_entity_get_extents(marker_entity));
    }
    if (data->marker2 != NULL) {
        marker_entity = (AdgEntity *) data->marker2;
        adg_marker_set_segment(data->marker2, data->trail, 1);
        adg_entity_local_changed(marker_entity);
        adg_entity_arrange(marker_entity);
        cpml_extents_add(&extents, adg_entity_get_extents(marker_entity));
    }

    adg_entity_set_extents(entity, &extents);
}