/** * gwy_data_view_get_top_layer: * @data_view: A #GwyDataView. * * Returns the top layer this data view currently uses, or %NULL if none * is present. * * Returns: The currently used top layer. **/ GwyVectorLayer* gwy_data_view_get_top_layer(GwyDataView *data_view) { g_return_val_if_fail(GWY_IS_DATA_VIEW(data_view), NULL); return GWY_VECTOR_LAYER(data_view->top_layer); }
/** * gwy_data_view_get_pixbuf: * @data_view: A #GwyDataView. * @max_width: Pixbuf width that should not be exceeeded. Value smaller than * 1 means unlimited size. * @max_height: Pixbuf height that should not be exceeeded. Value smaller than * 1 means unlimited size. * * Creates and returns a pixbuf from the data view. * * If the data is not square, the resulting pixbuf is also nonsquare, this is * different from gwy_data_view_get_thumbnail(). The returned pixbuf also * never has alpha channel. * * Returns: The pixbuf as a newly created #GdkPixbuf, it should be freed * when no longer needed. It is never larger than the actual data * size, as @max_width and @max_height are only upper limits. * * Since: 1.5 **/ GdkPixbuf* gwy_data_view_get_pixbuf(GwyDataView *data_view, gint max_width, gint max_height) { GdkPixbuf *pixbuf; gint width, height, width_scaled, height_scaled; gdouble xscale, yscale, scale; g_return_val_if_fail(GWY_IS_DATA_VIEW(data_view), NULL); g_return_val_if_fail(data_view->pixbuf, NULL); width = gdk_pixbuf_get_width(data_view->pixbuf); height = gdk_pixbuf_get_height(data_view->pixbuf); xscale = (max_width > 0) ? (gdouble)max_width/width : 1.0; yscale = (max_height > 0) ? (gdouble)max_height/height : 1.0; scale = MIN(MIN(xscale, yscale), 1.0); width_scaled = (gint)(scale*width); height_scaled = (gint)(scale*height); if (max_width) width_scaled = CLAMP(width_scaled, 1, max_width); if (max_height) height_scaled = CLAMP(height_scaled, 1, max_height); pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, BITS_PER_SAMPLE, width_scaled, height_scaled); gwy_debug_objects_creation(G_OBJECT(pixbuf)); gdk_pixbuf_scale(data_view->pixbuf, pixbuf, 0, 0, width_scaled, height_scaled, 0.0, 0.0, scale, scale, GDK_INTERP_TILES); return pixbuf; }
static void gwy_data_view_set_layer(GwyDataView *data_view, GwyDataViewLayer **which, GwyDataViewLayer *layer) { g_return_if_fail(GWY_IS_DATA_VIEW(data_view)); g_return_if_fail(which); if (layer == *which) return; if (*which) { gwy_data_view_layer_unplugged(*which); (*which)->parent = NULL; g_object_unref(*which); } if (layer) { g_assert(layer->parent == NULL); g_object_ref(layer); gtk_object_sink(GTK_OBJECT(layer)); layer->parent = (GtkWidget*)data_view; gwy_data_view_layer_plugged(layer); } *which = layer; data_view->force_update = TRUE; }
/** * gwy_data_view_get_thumbnail: * @data_view: A #GwyDataView. * @size: Requested thumbnail size. * * Creates and returns a thumbnail of the data view. * * If the data is not square, it is centered onto the pixbuf, with transparent * borders. The returned pixbuf always has an alpha channel, even if it fits * exactly. * * Returns: The thumbnail as a newly created #GdkPixbuf, which should be freed * when no longer needed. **/ GdkPixbuf* gwy_data_view_get_thumbnail(GwyDataView *data_view, gint size) { GdkPixbuf *pixbuf; gint width, height, width_scaled, height_scaled; gdouble scale; g_return_val_if_fail(GWY_IS_DATA_VIEW(data_view), NULL); g_return_val_if_fail(data_view->pixbuf, NULL); g_return_val_if_fail(size > 0, NULL); pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, BITS_PER_SAMPLE, size, size); gwy_debug_objects_creation(G_OBJECT(pixbuf)); gdk_pixbuf_fill(pixbuf, 0x00000000); width = gdk_pixbuf_get_width(data_view->pixbuf); height = gdk_pixbuf_get_height(data_view->pixbuf); scale = MIN((gdouble)size/width, (gdouble)size/height); width_scaled = CLAMP((gint)(scale*width), 1, size); height_scaled = CLAMP((gint)(scale*height), 1, size); gdk_pixbuf_scale(data_view->pixbuf, pixbuf, (size - width_scaled)/2, (size - height_scaled)/2, width_scaled, height_scaled, (size - width_scaled)/2, (size - height_scaled)/2, scale, scale, GDK_INTERP_TILES); return pixbuf; }
/** * gwy_data_view_get_alpha_layer: * @data_view: A #GwyDataView. * * Returns the alpha layer this data view currently uses, or %NULL if none * is present. * * Returns: The currently used alpha layer. **/ GwyPixmapLayer* gwy_data_view_get_alpha_layer(GwyDataView *data_view) { g_return_val_if_fail(GWY_IS_DATA_VIEW(data_view), NULL); return GWY_PIXMAP_LAYER(data_view->alpha_layer); }
/** * gwy_data_view_get_vexcess: * @data_view: A #GwyDataView. * * Return the vertical excess of widget size to data size. * * Do not use. Only useful for #GwyDataWindow implementation. * * Returns: The execess. **/ gdouble gwy_data_view_get_vexcess(GwyDataView *data_view) { g_return_val_if_fail(GWY_IS_DATA_VIEW(data_view), 0); if (!data_view->pixbuf) return 0; return (gdouble)GTK_WIDGET(data_view)->allocation.height / gdk_pixbuf_get_height(data_view->pixbuf) - 1.0; }
/** * gwy_data_view_coords_real_to_xy: * @data_view: A #GwyDataView. * @xreal: A physical x-coordinate in the data sample.. * @yreal: A physical y-coordinate in the data sample. * @xscr: Where the screen x-coordinate relative to widget origin should be * stored. * @yscr: Where the screen y-coordinate relative to widget origin should be * stored. * * Recomputes physical coordinate in the sample to screen coordinate relative * to widget origin. **/ void gwy_data_view_coords_real_to_xy(GwyDataView *data_view, gdouble xreal, gdouble yreal, gint *xscr, gint *yscr) { g_return_if_fail(GWY_IS_DATA_VIEW(data_view)); if (xscr) *xscr = floor(xreal/data_view->xmeasure + 0.5) + data_view->xoff; if (yscr) *yscr = floor(yreal/data_view->ymeasure + 0.5) + data_view->yoff; }
/** * gwy_data_view_coords_xy_to_real: * @data_view: A #GwyDataView. * @xscr: A screen x-coordinate relative to widget origin. * @yscr: A screen y-coordinate relative to widget origin. * @xreal: Where the physical x-coordinate in the data sample should be stored. * @yreal: Where the physical y-coordinate in the data sample should be stored. * * Recomputes screen coordinates relative to widget origin to physical * coordinates in the sample. **/ void gwy_data_view_coords_xy_to_real(GwyDataView *data_view, gint xscr, gint yscr, gdouble *xreal, gdouble *yreal) { g_return_if_fail(GWY_IS_DATA_VIEW(data_view)); if (xreal) *xreal = (xscr - data_view->xoff) * data_view->xmeasure; if (yreal) *yreal = (yscr - data_view->yoff) * data_view->ymeasure; }
/** * gwy_data_view_update: * @data_view: A #GwyDataView. * * Instructs a data view to update self and repaint. * * It causes "updated" signal emission, among other things. * * FIXME: This function exists because it's impossible [now?] to watch changes * of datafields (and other things) properly. Call it when you changed data * and want the view to reflect the change. **/ void gwy_data_view_update(GwyDataView *data_view) { GtkWidget *widget; gwy_debug(" "); g_return_if_fail(GWY_IS_DATA_VIEW(data_view)); data_view->force_update = TRUE; gwy_data_view_maybe_resize(data_view); widget = GTK_WIDGET(data_view); if (widget->window) gdk_window_invalidate_rect(widget->window, NULL, TRUE); g_signal_emit(data_view, data_view_signals[UPDATED], 0); }
/** * gwy_set_data_preview_size: * @data_view: A data view used for module preview. * @max_size: Maximum allowed @data_view size (width and height). * * Sets up data view zoom to not exceed specified size. * * Before calling this function, data keys have be set, data fields and layers * have to be present and physically square mode set in the container. * Sizing of both pixel-wise square and physically square displays is performed * correctly. * * Since: 2.7 **/ void gwy_set_data_preview_size(GwyDataView *data_view, gint max_size) { GwyContainer *container; GwyDataField *data_field; GwyPixmapLayer *layer; gdouble zoomval, scale, xreal, yreal; gboolean realsquare; gint xres, yres; const gchar *prefix; gchar *key; g_return_if_fail(GWY_IS_DATA_VIEW(data_view)); g_return_if_fail(max_size >= 2); container = gwy_data_view_get_data(data_view); g_return_if_fail(GWY_IS_CONTAINER(container)); layer = gwy_data_view_get_base_layer(data_view); g_return_if_fail(GWY_IS_PIXMAP_LAYER(layer)); prefix = gwy_pixmap_layer_get_data_key(layer); g_return_if_fail(prefix); data_field = gwy_container_get_object_by_name(container, prefix); g_return_if_fail(GWY_IS_DATA_FIELD(data_field)); prefix = gwy_data_view_get_data_prefix(data_view); g_return_if_fail(prefix); key = g_strconcat(prefix, "/realsquare", NULL); realsquare = FALSE; gwy_container_gis_boolean_by_name(container, key, &realsquare); g_free(key); xres = gwy_data_field_get_xres(data_field); yres = gwy_data_field_get_yres(data_field); if (!realsquare) zoomval = max_size/(gdouble)MAX(xres, yres); else { xreal = gwy_data_field_get_xreal(data_field); yreal = gwy_data_field_get_yreal(data_field); scale = MAX(xres/xreal, yres/yreal); zoomval = max_size/(scale*MAX(xreal, yreal)); } gwy_data_view_set_zoom(data_view, zoomval); }
/** * gwy_data_view_set_zoom: * @data_view: A #GwyDataView. * @zoom: A new zoom value. * * Sets zoom of @data_view to @zoom. * * Zoom greater than 1 means larger image on screen and vice versa. * * Note window manager can prevent the window from resize and thus the zoom * from change. **/ void gwy_data_view_set_zoom(GwyDataView *data_view, gdouble zoom) { g_return_if_fail(GWY_IS_DATA_VIEW(data_view)); /* XXX: what was this meant for? if (!data_view->pixbuf || !data_view->base_pixbuf) return; */ gwy_debug("zoom = %g, new = %g", data_view->newzoom, zoom); if (fabs(log(data_view->newzoom/zoom)) < 0.001) return; data_view->newzoom = zoom; gtk_widget_queue_resize(GTK_WIDGET(data_view)); }
static void gwy_data_view_destroy(GtkObject *object) { GwyDataView *data_view; gwy_debug("destroying a GwyDataView %p (refcount = %u)", object, G_OBJECT(object)->ref_count); g_return_if_fail(GWY_IS_DATA_VIEW(object)); data_view = GWY_DATA_VIEW(object); gwy_data_view_set_layer(data_view, &data_view->top_layer, NULL); gwy_data_view_set_layer(data_view, &data_view->alpha_layer, NULL); gwy_data_view_set_layer(data_view, &data_view->base_layer, NULL); if (GTK_OBJECT_CLASS(parent_class)->destroy) (*GTK_OBJECT_CLASS(parent_class)->destroy)(object); }
/** * gwy_data_view_coords_xy_clamp: * @data_view: A #GwyDataView. * @xscr: A screen x-coordinate relative to widget origin. * @yscr: A screen y-coordinate relative to widget origin. * * Fixes screen coordinates @xscr and @yscr to be inside the data-displaying * area (which can be smaller than widget size). **/ void gwy_data_view_coords_xy_clamp(GwyDataView *data_view, gint *xscr, gint *yscr) { GtkWidget *widget; gint size; g_return_if_fail(GWY_IS_DATA_VIEW(data_view)); widget = GTK_WIDGET(data_view); if (xscr) { size = gdk_pixbuf_get_width(data_view->pixbuf); *xscr = CLAMP(*xscr, data_view->xoff, data_view->xoff + size-1); } if (yscr) { size = gdk_pixbuf_get_height(data_view->pixbuf); *yscr = CLAMP(*yscr, data_view->yoff, data_view->yoff + size-1); } }
static void gwy_data_view_finalize(GObject *object) { GwyDataView *data_view; gwy_debug("finalizing a GwyDataView (refcount = %u)", object->ref_count); g_return_if_fail(GWY_IS_DATA_VIEW(object)); data_view = GWY_DATA_VIEW(object); gwy_object_unref(data_view->base_layer); gwy_object_unref(data_view->alpha_layer); gwy_object_unref(data_view->top_layer); gwy_debug(" child data ref count %d", G_OBJECT(data_view->data)->ref_count); gwy_object_unref(data_view->data); G_OBJECT_CLASS(parent_class)->finalize(object); }
static void gwy_data_view_size_allocate(GtkWidget *widget, GtkAllocation *allocation) { GwyDataView *data_view; gwy_debug("allocating %d x %d", allocation->width, allocation->height); g_return_if_fail(widget != NULL); g_return_if_fail(GWY_IS_DATA_VIEW(widget)); g_return_if_fail(allocation != NULL); widget->allocation = *allocation; if (GTK_WIDGET_REALIZED(widget)) { data_view = GWY_DATA_VIEW(widget); gdk_window_move_resize(widget->window, allocation->x, allocation->y, allocation->width, allocation->height); gwy_data_view_make_pixmap(data_view); } }
/** * gwy_data_view_get_data: * @data_view: A #GwyDataView. * * Returns the data container used by @data_view. * * Returns: The data as a #GwyContainer. **/ GwyContainer* gwy_data_view_get_data(GwyDataView *data_view) { g_return_val_if_fail(GWY_IS_DATA_VIEW(data_view), NULL); return data_view->data; }
/** * gwy_data_view_get_ymeasure: * @data_view: A #GwyDataView. * * Returns the ratio between vertical physical lengths and horizontal * screen lengths in pixels. * * Returns: The vertical measure. **/ gdouble gwy_data_view_get_ymeasure(GwyDataView *data_view) { g_return_val_if_fail(GWY_IS_DATA_VIEW(data_view), 1.0); return data_view->ymeasure; }
/** * gwy_data_view_get_zoom: * @data_view: A #GwyDataView. * * Returns current zoom of @data_view. * * When a resize is queued, the new zoom value is returned. * * Returns: The zoom. **/ gdouble gwy_data_view_get_zoom(GwyDataView *data_view) { g_return_val_if_fail(GWY_IS_DATA_VIEW(data_view), 1.0); return data_view->newzoom; }