Exemple #1
0
/**
 * adg_gtk_area_get_extents:
 * @area: an #AdgGtkArea
 *
 * Gets the extents of the canvas bound to @area. The returned
 * struct is owned by @area and should not modified or freed.
 *
 * The extents of an #AdgGtkArea instance are the extents of
 * its canvas (as returned by adg_entity_get_extents()) with
 * the margins added to it and the #AdgGtkArea:render-map
 * transformation applied.
 *
 * If @area does not have any canvas associated to it or the
 * canvas is invalid or empty, an undefined #CpmlExtents
 * struct will be returned.
 *
 * The canvas will be updated, meaning adg_entity_arrange()
 * is called before the extents computation.
 *
 * Returns: the extents of the @area canvas or <constant>NULL</constant> on errors.
 *
 * Since: 1.0
 **/
const CpmlExtents *
adg_gtk_area_get_extents(AdgGtkArea *area)
{
    g_return_val_if_fail(ADG_GTK_IS_AREA(area), NULL);

    return _adg_get_extents(area);
}
Exemple #2
0
/**
 * adg_gtk_area_reset:
 * @area: an #AdgGtkArea
 *
 * Forcibly resets the zoom ratio and position of the canvas bound
 * to @area. This means the canvas will be scaled and centered on
 * the current available space.
 **/
void
adg_gtk_area_reset(AdgGtkArea *area)
{
    AdgGtkAreaPrivate *data;
    GtkWidget *parent;
    const CpmlExtents *sheet;
    GtkAllocation allocation;
    CpmlPair size;
    gdouble zoom;

    g_return_if_fail(ADG_GTK_IS_AREA(area));

    data = adg_gtk_area_get_instance_private(area);
    cairo_matrix_init_identity(&data->render_map);

    sheet = _adg_get_extents(area);
    if (!sheet->is_defined || sheet->size.x <= 0 || sheet->size.y <= 0)
        return;

    parent = gtk_widget_get_parent((GtkWidget *) area);
    gtk_widget_get_allocation(parent, &allocation);
    size.x = allocation.width;
    size.y = allocation.height;
    zoom = MIN(size.x / sheet->size.x, size.y / sheet->size.y);

    cairo_matrix_scale(&data->render_map, zoom, zoom);
    cairo_matrix_translate(&data->render_map,
                           (size.x / zoom - sheet->size.x) / 2 - sheet->org.x,
                           (size.y / zoom - sheet->size.y) / 2 - sheet->org.y);

    /* Trigger a resize trying to hide the scrollbars on the parent */
    gtk_widget_queue_resize(parent);
}
Exemple #3
0
static void
_adg_size_request(GtkWidget *widget, GtkRequisition *requisition)
{
    AdgGtkArea *area = (AdgGtkArea *) widget;
    const CpmlExtents *extents = _adg_get_extents(area);

    if (extents->is_defined) {
        requisition->width = extents->size.x;
        requisition->height = extents->size.y;
    }
}
Exemple #4
0
static void
_adg_get_preferred_width_for_height(GtkWidget *widget, gint height,
                                    gint *minimum_width, gint *natural_width)
{
    AdgGtkArea *area;
    const CpmlExtents *extents;

    area = (AdgGtkArea *) widget;
    extents = _adg_get_extents(area);

    if (extents->is_defined && extents->size.y > 0) {
        *minimum_width = extents->size.x;
        *natural_width = *minimum_width * height / extents->size.y;
    }
}
Exemple #5
0
static void
_adg_get_preferred_height_for_width(GtkWidget *widget, gint width,
                                    gint *minimum_height, gint *natural_height)
{
    AdgGtkArea *area;
    const CpmlExtents *extents;

    area = (AdgGtkArea *) widget;
    extents = _adg_get_extents(area);

    if (extents->is_defined && extents->size.x > 0) {
        *minimum_height = extents->size.y;
        *natural_height = *minimum_height * width / extents->size.x;
    }
}
Exemple #6
0
/**
 * _adg_size_allocate:
 * @widget: an #AdgGtkArea widget
 * @allocation: the new allocation struct
 *
 * Scales the drawing according to the new allocation if
 * #AdgGtkArea:autozoom is <constant>TRUE</constant>.
 *
 * TODO: the current implementation initially centers the canvas
 * on the allocation space. Further allocations (due to a
 * window resizing, for example) use the top/left corner of the
 * canvas as reference point. Plan different policies for either
 * those situations.
 *
 * Since: 1.0
 **/
static void
_adg_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
{
    AdgGtkArea *area;
    AdgGtkAreaPrivate *data;
    const CpmlExtents *sheet;
    CpmlVector size;
    gdouble factor;

    if (_ADG_OLD_WIDGET_CLASS->size_allocate)
        _ADG_OLD_WIDGET_CLASS->size_allocate(widget, allocation);

    area = (AdgGtkArea *) widget;
    data = area->data;

    sheet = _adg_get_extents(area);
    if (!sheet->is_defined || sheet->size.x <= 0 || sheet->size.y <= 0)
        return;

    size.x = allocation->width;
    size.y = allocation->height;

    if (data->autozoom)  {
        /* Adjust the zoom according to the allocation and sheet size */
        factor = MIN(size.x / sheet->size.x, size.y / sheet->size.y);
    } else if (!data->initialized) {
        /* First allocation with autozoom off: keep the current zoom */
        factor = 1;
    } else {
        /* Not the first allocation and autozoom off: keep the old map */
        return;
    }

    if (!data->initialized) {
        /* TODO: plan different attachment policies other than centering */
        cairo_matrix_init_translate(&data->render_map,
                                    (size.x - sheet->size.x) / 2 - sheet->org.x,
                                    (size.y - sheet->size.y) / 2 - sheet->org.y);
        data->initialized = TRUE;
    }

    /* TODO: plan other reference points other than left/top (x0, y0) */
    data->render_map.x0 *= factor;
    data->render_map.y0 *= factor;
    data->render_map.xx *= factor;
    data->render_map.yy *= factor;
}
Exemple #7
0
static void
_adg_set_map(GtkWidget *widget,
             gboolean local_space,
             const cairo_matrix_t *map)
{
    AdgGtkAreaPrivate *data = adg_gtk_area_get_instance_private((AdgGtkArea *) widget);
    AdgEntity *entity = (AdgEntity *) data->canvas;

    if (entity == NULL)
        return;

    if (local_space) {
        /* TODO: this forcibly overwrites any local transformation */
        adg_entity_set_local_map(entity, map);
    } else {
        adg_matrix_transform(&data->render_map, map, ADG_TRANSFORM_BEFORE);
    }

    /* This will emit the extents-changed signal when applicable */
    _adg_get_extents((AdgGtkArea *) widget);
}