gtksourceview3/gtksourceview/gtksourcepixbufhelper.c

347 lines
7.4 KiB
C

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
* gtksourcepixbufhelper.c
* This file is part of GtkSourceView
*
* Copyright (C) 2010 - Jesse van den Kieboom
*
* GtkSourceView is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* GtkSourceView is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "gtksourcepixbufhelper.h"
typedef enum _IconType
{
ICON_TYPE_PIXBUF,
ICON_TYPE_STOCK,
ICON_TYPE_GICON,
ICON_TYPE_NAME
} IconType;
struct _GtkSourcePixbufHelper
{
GdkPixbuf *cached_pixbuf;
IconType type;
GdkPixbuf *pixbuf;
gchar *icon_name;
gchar *stock_id;
GIcon *gicon;
};
GtkSourcePixbufHelper *
gtk_source_pixbuf_helper_new (void)
{
return g_slice_new0 (GtkSourcePixbufHelper);
}
void
gtk_source_pixbuf_helper_free (GtkSourcePixbufHelper *helper)
{
if (helper->pixbuf)
{
g_object_unref (helper->pixbuf);
}
if (helper->cached_pixbuf)
{
g_object_unref (helper->cached_pixbuf);
}
if (helper->gicon)
{
g_object_unref (helper->gicon);
}
g_free (helper->stock_id);
g_free (helper->icon_name);
g_slice_free (GtkSourcePixbufHelper, helper);
}
static void
set_cache (GtkSourcePixbufHelper *helper,
GdkPixbuf *pixbuf)
{
if (helper->cached_pixbuf)
{
g_object_unref (helper->cached_pixbuf);
helper->cached_pixbuf = NULL;
}
if (pixbuf)
{
helper->cached_pixbuf = pixbuf;
}
}
static void
clear_cache (GtkSourcePixbufHelper *helper)
{
set_cache (helper, NULL);
}
void
gtk_source_pixbuf_helper_set_pixbuf (GtkSourcePixbufHelper *helper,
const GdkPixbuf *pixbuf)
{
helper->type = ICON_TYPE_PIXBUF;
if (helper->pixbuf)
{
g_object_unref (helper->pixbuf);
helper->pixbuf = NULL;
}
if (pixbuf)
{
helper->pixbuf = gdk_pixbuf_copy (pixbuf);
}
clear_cache (helper);
}
GdkPixbuf *
gtk_source_pixbuf_helper_get_pixbuf (GtkSourcePixbufHelper *helper)
{
return helper->pixbuf;
}
void
gtk_source_pixbuf_helper_set_stock_id (GtkSourcePixbufHelper *helper,
const gchar *stock_id)
{
helper->type = ICON_TYPE_STOCK;
if (helper->stock_id)
{
g_free (helper->stock_id);
}
helper->stock_id = g_strdup (stock_id);
clear_cache (helper);
}
const gchar *
gtk_source_pixbuf_helper_get_stock_id (GtkSourcePixbufHelper *helper)
{
return helper->stock_id;
}
void
gtk_source_pixbuf_helper_set_icon_name (GtkSourcePixbufHelper *helper,
const gchar *icon_name)
{
helper->type = ICON_TYPE_NAME;
if (helper->icon_name)
{
g_free (helper->icon_name);
}
helper->icon_name = g_strdup (icon_name);
clear_cache (helper);
}
const gchar *
gtk_source_pixbuf_helper_get_icon_name (GtkSourcePixbufHelper *helper)
{
return helper->icon_name;
}
void
gtk_source_pixbuf_helper_set_gicon (GtkSourcePixbufHelper *helper,
GIcon *gicon)
{
helper->type = ICON_TYPE_GICON;
if (helper->gicon)
{
g_object_unref (helper->gicon);
helper->gicon = NULL;
}
if (gicon)
{
helper->gicon = g_object_ref (gicon);
}
clear_cache (helper);
}
GIcon *
gtk_source_pixbuf_helper_get_gicon (GtkSourcePixbufHelper *helper)
{
return helper->gicon;
}
static void
from_pixbuf (GtkSourcePixbufHelper *helper,
GtkWidget *widget,
gint size)
{
if (helper->pixbuf == NULL)
{
return;
}
if (gdk_pixbuf_get_width (helper->pixbuf) <= size)
{
if (!helper->cached_pixbuf)
{
set_cache (helper, gdk_pixbuf_copy (helper->pixbuf));
}
return;
}
/* Make smaller */
set_cache (helper, gdk_pixbuf_scale_simple (helper->pixbuf,
size,
size,
GDK_INTERP_BILINEAR));
}
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
static void
from_stock (GtkSourcePixbufHelper *helper,
GtkWidget *widget,
gint size)
{
GtkIconSize icon_size;
gchar *name;
name = g_strdup_printf ("GtkSourcePixbufHelper%d", size);
icon_size = gtk_icon_size_from_name (name);
if (icon_size == GTK_ICON_SIZE_INVALID)
{
icon_size = gtk_icon_size_register (name, size, size);
}
g_free (name);
set_cache (helper, gtk_widget_render_icon_pixbuf (widget,
helper->stock_id,
icon_size));
}
G_GNUC_END_IGNORE_DEPRECATIONS;
static void
from_gicon (GtkSourcePixbufHelper *helper,
GtkWidget *widget,
gint size)
{
GdkScreen *screen;
GtkIconTheme *icon_theme;
GtkIconInfo *info;
GtkIconLookupFlags flags;
screen = gtk_widget_get_screen (widget);
icon_theme = gtk_icon_theme_get_for_screen (screen);
flags = GTK_ICON_LOOKUP_USE_BUILTIN;
info = gtk_icon_theme_lookup_by_gicon (icon_theme,
helper->gicon,
size,
flags);
if (info)
{
set_cache (helper, gtk_icon_info_load_icon (info, NULL));
}
}
static void
from_name (GtkSourcePixbufHelper *helper,
GtkWidget *widget,
gint size)
{
GdkScreen *screen;
GtkIconTheme *icon_theme;
GtkIconInfo *info;
GtkIconLookupFlags flags;
gint scale;
screen = gtk_widget_get_screen (widget);
icon_theme = gtk_icon_theme_get_for_screen (screen);
flags = GTK_ICON_LOOKUP_USE_BUILTIN;
scale = gtk_widget_get_scale_factor (widget);
info = gtk_icon_theme_lookup_icon_for_scale (icon_theme,
helper->icon_name,
size,
scale,
flags);
if (info)
{
GdkPixbuf *pixbuf;
if (gtk_icon_info_is_symbolic (info))
{
GtkStyleContext *context;
context = gtk_widget_get_style_context (widget);
pixbuf = gtk_icon_info_load_symbolic_for_context (info, context, NULL, NULL);
}
else
{
pixbuf = gtk_icon_info_load_icon (info, NULL);
}
set_cache (helper, pixbuf);
}
}
GdkPixbuf *
gtk_source_pixbuf_helper_render (GtkSourcePixbufHelper *helper,
GtkWidget *widget,
gint size)
{
if (helper->cached_pixbuf &&
gdk_pixbuf_get_width (helper->cached_pixbuf) == size)
{
return helper->cached_pixbuf;
}
switch (helper->type)
{
case ICON_TYPE_PIXBUF:
from_pixbuf (helper, widget, size);
break;
case ICON_TYPE_STOCK:
from_stock (helper, widget, size);
break;
case ICON_TYPE_GICON:
from_gicon (helper, widget, size);
break;
case ICON_TYPE_NAME:
from_name (helper, widget, size);
break;
default:
g_assert_not_reached ();
}
return helper->cached_pixbuf;
}