Commit 8e7c4ad1 authored by Timm Bäder's avatar Timm Bäder 👎

WIP: Add GtkImageView

parent b4acf816
Pipeline #37713 failed with stages
in 10 minutes and 15 seconds
......@@ -175,6 +175,7 @@
<file>iconview.c</file>
<file>iconview_edit.c</file>
<file>images.c</file>
<file>image_view.c</file>
<file>infobar.c</file>
<file>links.c</file>
<file>listbox.c</file>
......@@ -215,6 +216,9 @@
<file>textmask.c</file>
<file>video_player.c</file>
</gresource>
<gresource prefix="/imageview">
<file>image_view.ui</file>
</gresource>
<gresource prefix="/textview">
<file>floppybuddy.gif</file>
</gresource>
......
/* Image View
*/
#include <gtk/gtk.h>
#include "paintable.h"
GtkWidget *image_view;
GtkWidget *uri_entry;
void
reset_view_button_clicked_cb ()
{
gtk_image_view_set_scale (GTK_IMAGE_VIEW (image_view), 1.0);
gtk_image_view_set_angle (GTK_IMAGE_VIEW (image_view), 0.0);
}
void
load_from_file_cb (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
{
GError *error = NULL;
gtk_image_view_load_from_file_finish (GTK_IMAGE_VIEW (image_view),
result,
&error);
if (error != NULL)
{
g_warning ("load_from_file_async error: %s", error->message);
}
}
void
file_set_cb (GtkFileChooserButton *widget,
gpointer user_data)
{
char *filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
GFile *file = g_file_new_for_path (filename);
gtk_image_view_load_from_file_async (GTK_IMAGE_VIEW (image_view),
file,
NULL,
load_from_file_cb,
NULL);
g_free (filename);
g_object_unref (file);
}
static void
image_loaded_cb (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
{
GtkImageView *image_view = GTK_IMAGE_VIEW (source_object);
GError *error = NULL;
gtk_image_view_load_from_file_finish (image_view,
result,
&error);
if (error)
{
g_message ("Error: %s", error->message);
return;
}
}
void
load_button_cb ()
{
const char *uri = gtk_entry_get_text (GTK_ENTRY (uri_entry));
GFile *file = g_file_new_for_uri (uri);
g_message (__FUNCTION__);
gtk_image_view_load_from_file_async (GTK_IMAGE_VIEW (image_view),
file,
NULL,
image_loaded_cb,
NULL);
g_object_unref (file);
}
void
angle_changed_cb (GtkRange *range,
gpointer user_data)
{
double value = gtk_range_get_value (range);
gtk_image_view_set_angle (GTK_IMAGE_VIEW (image_view), value);
}
void
scale_changed_cb (GtkRange *range,
gpointer user_data)
{
double value = gtk_range_get_value (range);
gtk_image_view_set_scale (GTK_IMAGE_VIEW (image_view), value);
}
void
rotate_left_clicked_cb ()
{
double current_angle = gtk_image_view_get_angle (GTK_IMAGE_VIEW (image_view));
gtk_image_view_set_angle (GTK_IMAGE_VIEW (image_view), current_angle - 90);
}
void
rotate_right_clicked_cb ()
{
double current_angle = gtk_image_view_get_angle (GTK_IMAGE_VIEW (image_view));
gtk_image_view_set_angle (GTK_IMAGE_VIEW (image_view), current_angle + 90);
}
void
scrolled_switch_active_cb (GObject *source)
{
GtkWidget *parent = gtk_widget_get_parent (image_view);
if (GTK_IS_SCROLLED_WINDOW (parent))
{
GtkWidget *grandparent = gtk_widget_get_parent (parent);
g_assert (grandparent != NULL);
g_object_ref (G_OBJECT (image_view));
gtk_container_remove (GTK_CONTAINER (parent), image_view);
gtk_container_remove (GTK_CONTAINER (grandparent), parent);
gtk_container_add (GTK_CONTAINER (grandparent), image_view);
gtk_widget_show (image_view);
g_object_unref (G_OBJECT (image_view));
}
else
{
GtkWidget *scroller = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroller),
GTK_POLICY_ALWAYS,
GTK_POLICY_ALWAYS);
g_object_ref (image_view);
gtk_container_remove (GTK_CONTAINER (parent), image_view);
gtk_container_add (GTK_CONTAINER (scroller), image_view);
gtk_container_add (GTK_CONTAINER (parent), scroller);
gtk_widget_show (scroller);
g_object_unref (image_view);
}
}
gchar *
angle_scale_format_value_cb (GtkScale *scale,
double value,
gpointer user_data)
{
return g_strdup_printf ("%.2f°", value);
}
gchar *
scale_scale_format_value_cb (GtkScale *scale,
double value,
gpointer user_data)
{
return g_strdup_printf ("%.2f", value);
}
void
load_pixbuf_button_clicked_cb ()
{
GdkPixbuf *pixbuf;
GdkTexture *texture;
pixbuf = gdk_pixbuf_new_from_file ("/usr/share/backgrounds/gnome/Mirror.jpg", NULL);
texture = gdk_texture_new_for_pixbuf (pixbuf);
g_object_unref (pixbuf);
gtk_image_view_set_paintable (GTK_IMAGE_VIEW (image_view),
GDK_PAINTABLE (texture));
}
void
load_hidpi_pixbuf_button_clicked_cb ()
{
GdkPaintable *p;
p = gtk_nuclear_animation_new ();
gtk_image_view_set_paintable (GTK_IMAGE_VIEW (image_view), p);
g_object_unref (p);
}
void
clear_button_clicked_cb ()
{
gtk_image_view_set_paintable (GTK_IMAGE_VIEW (image_view), NULL);
}
GtkWidget *
do_image_view (GtkWidget *do_widget)
{
GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
GtkBuilder *builder = gtk_builder_new_from_resource ("/imageview/image_view.ui");
GtkWidget *box = GTK_WIDGET (gtk_builder_get_object (builder, "box"));
GtkWidget *snap_angle_switch = GTK_WIDGET (gtk_builder_get_object (builder, "snap_angle_switch"));
GtkWidget *fit_allocation_switch = GTK_WIDGET (gtk_builder_get_object (builder, "fit_allocation_switch"));
GtkWidget *rotate_gesture_switch = GTK_WIDGET (gtk_builder_get_object (builder, "rotate_gesture_switch"));
GtkWidget *zoom_gesture_switch = GTK_WIDGET (gtk_builder_get_object (builder, "zoom_gesture_switch"));
GtkWidget *transitions_switch = GTK_WIDGET (gtk_builder_get_object (builder, "transitions_switch"));
GtkAdjustment *scale_adjustment = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "scale_adjustment"));
GtkAdjustment *angle_adjustment = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "angle_adjustment"));
image_view = GTK_WIDGET (gtk_builder_get_object (builder, "image_view"));
uri_entry = GTK_WIDGET (gtk_builder_get_object (builder, "uri_entry"));
g_object_bind_property (scale_adjustment, "value", image_view, "scale",
G_BINDING_BIDIRECTIONAL);
g_object_bind_property (angle_adjustment, "value", image_view, "angle",
G_BINDING_SYNC_CREATE);
g_object_bind_property (image_view, "angle", angle_adjustment, "value",
G_BINDING_SYNC_CREATE);
g_object_bind_property (image_view, "snap-angle", snap_angle_switch, "active",
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
g_object_bind_property (image_view, "fit-allocation", fit_allocation_switch, "active",
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
g_object_bind_property (image_view, "rotatable",
rotate_gesture_switch, "active",
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
g_object_bind_property (image_view, "zoomable",
zoom_gesture_switch, "active",
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
g_object_bind_property (image_view, "transitions-enabled",
transitions_switch, "active",
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
gtk_container_add (GTK_CONTAINER (window), box);
gtk_builder_connect_signals (builder, NULL);
gtk_window_resize (GTK_WINDOW (window), 800, 600);
gtk_widget_show (window);
g_object_unref (builder);
return window;
}
<?xml version="1.0"?>
<interface>
<object class="GtkAdjustment" id="scale_adjustment">
<property name="upper">5</property>
<property name="lower">0.05</property>
<property name="value">1.0</property>
<property name="step-increment">0.01</property>
<property name="page-increment">0.01</property>
</object>
<object class="GtkAdjustment" id="angle_adjustment">
<property name="upper">360</property>
<property name="value">0</property>
<property name="step_increment">0.1</property>
<property name="page-increment">1</property>
</object>
<object class="GtkBox" id="box">
<property name="visible">true</property>
<property name="orientation">horizontal</property>
<child>
<object class="GtkGrid" id="grid">
<property name="visible">true</property>
<property name="row_spacing">6</property>
<property name="column_spacing">12</property>
<property name="margin">6</property>
<child>
<object class="GtkEntry" id="uri_entry">
<property name="visible">true</property>
<property name="placeholder_text">URI</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="load_button">
<property name="visible">true</property>
<property name="label" translatable="yes">Load</property>
<signal name="clicked" handler="load_button_cb" />
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkFileChooserButton">
<property name="visible">true</property>
<property name="valign">baseline</property>
<signal name="file-set" handler="file_set_cb" />
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="visible">true</property>
<property name="label" translatable="yes">Load Pixbuf</property>
<signal name="clicked" handler="load_pixbuf_button_clicked_cb" object="image_view"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="visible">true</property>
<property name="label" translatable="yes">Load HiDPI Pixbuf</property>
<signal name="clicked" handler="load_hidpi_pixbuf_button_clicked_cb" object="image_view"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="visible">true</property>
<property name="label" translatable="yes">Clear</property>
<signal name="clicked" handler="clear_button_clicked_cb" />
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">4</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">true</property>
<property name="label" translatable="yes">Fit Allocation</property>
<property name="halign">start</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">6</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="fit_allocation_switch">
<property name="halign">end</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">6</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">true</property>
<property name="label">In ScrolledWindow</property>
<property name="halign">start</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">7</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="scrolled_switch">
<property name="halign">end</property>
<property name="active">true</property>
<signal name="notify::active" handler="scrolled_switch_active_cb" />
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">7</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">true</property>
<property name="label">Zoomable</property>
<property name="halign">start</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">8</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="zoom_gesture_switch">
<property name="halign">end</property>
<property name="active">true</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">8</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">true</property>
<property name="label">Rotatable</property>
<property name="halign">start</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">9</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="rotate_gesture_switch">
<property name="halign">end</property>
<property name="active">true</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">9</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">true</property>
<property name="label" translatable="yes">Snap Angle</property>
<property name="halign">start</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">10</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="snap_angle_switch">
<property name="halign">end</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">10</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">true</property>
<property name="label" translatable="yes">Transitions</property>
<property name="halign">start</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">11</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="transitions_switch">
<property name="halign">end</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">11</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">true</property>
<property name="label" translatable="yes">Angle</property>
<property name="margin_top">12</property>
<property name="halign">start</property>
<attributes>
<attribute name="weight" value="bold" />
</attributes>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">12</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkScale" id="angle_spin_button">
<property name="draw-value">0</property>
<property name="visible">true</property>
<property name="digits">2</property>
<property name="draw-value">0</property>
<property name="adjustment">angle_adjustment</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">13</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">true</property>
<property name="label" translatable="yes">Scale</property>
<property name="halign">start</property>
<property name="xalign">0.0</property>
<attributes>
<attribute name="weight" value="bold" />
</attributes>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">14</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkScale" id="scale_spin_button">
<property name="draw-value">0</property>
<property name="visible">true</property>
<property name="digits">2</property>
<property name="adjustment">scale_adjustment</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">15</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">true</property>
<property name="orientation">horizontal</property>
<property name="halign">center</property>
<style>
<class name="linked" />
</style>
<child>
<object class="GtkButton">
<property name="visible">true</property>
<signal name="clicked" handler="rotate_left_clicked_cb" />
<child>
<object class="GtkImage">
<property name="visible">true</property>
<property name="icon-name">object-rotate-left-symbolic</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkButton">
<property name="visible">true</property>
<signal name="clicked" handler="rotate_right_clicked_cb" />
<child>
<object class="GtkImage">
<property name="visible">true</property>
<property name="icon-name">object-rotate-right-symbolic</property>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">16</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="reset_button">
<property name="visible">true</property>
<property name="label" translatable="true">Reset View</property>
<property name="valign">end</property>
<property name="vexpand">true</property>
<signal name="clicked" handler="reset_view_button_clicked_cb" />
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">17</property>
<property name="width">2</property>
</packing>
</child>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">true</property>
<child>
<object class="GtkImageView" id="image_view">
<property name="visible">true</property>
<property name="hexpand">true</property>
<property name="vexpand">true</property>
<property name="width_request">400</property>
<property name="height_request">400</property>
</object>
</child>
</object>
</child>
</object>
</interface>
......@@ -33,6 +33,7 @@ demos = files([
'iconview.c',
'iconview_edit.c',
'images.c',
'image_view.c',
'infobar.c',
'links.c',
'listbox.c',
......
......@@ -104,6 +104,7 @@
<xi:include href="xml/gtklabel.xml" />
<xi:include href="xml/gtkimage.xml" />
<xi:include href="xml/gtkpicture.xml" />
<xi:include href="xml/gtkimageview.xml" />
<xi:include href="xml/gtkspinner.xml" />
<xi:include href="xml/gtkinfobar.xml" />
<xi:include href="xml/gtkprogressbar.xml" />
......
......@@ -1552,6 +1552,45 @@ GtkImageIconNameData
GtkImageGIconData
</SECTION>
<SECTION>
<FILE>gtkimageview</FILE>
<TITLE>GtkImageView</TITLE>
GtkImageView
gtk_image_view_new
gtk_image_view_set_pixbuf
gtk_image_view_set_surface
gtk_image_view_set_animation
gtk_image_view_load_from_file_async
gtk_image_view_load_from_file_finish
gtk_image_view_load_from_stream_async
gtk_image_view_load_from_stream_finish
gtk_image_view_set_scale
gtk_image_view_get_scale
gtk_image_view_set_angle
gtk_image_view_get_angle
gtk_image_view_set_snap_angle
gtk_image_view_get_snap_angle
gtk_image_view_set_fit_allocation
gtk_image_view_get_fit_allocation
gtk_image_view_set_rotatable
gtk_image_view_get_rotatable
gtk_image_view_set_zoomable
gtk_image_view_get_zoomable
gtk_image_view_get_scale_set
gtk_image_view_set_transitions_enabled
gtk_image_view_get_transitions_enabled
<SUBSECTION Standard>
GTK_IMAGE_VIEW
GTK_IS_IMAGE_VIEW
GTK_TYPE_IMAGE_VIEW
GTK_IMAGE__VIEW_CLASS
GTK_IS_IMAGE_VIEW_CLASS
GTK_IMAGE_VIEW_GET_CLASS
<SUBSECTION Private>