Skip to content

Instantly share code, notes, and snippets.

@xpaulnim
Created August 4, 2018 19:02
Show Gist options
  • Save xpaulnim/6d37c794c041a78b4c8e1dd8d21560d9 to your computer and use it in GitHub Desktop.
Save xpaulnim/6d37c794c041a78b4c8e1dd8d21560d9 to your computer and use it in GitHub Desktop.
Load remote images asyncronously using a cache.
// Compile with valac --pkg gtk+-3.0 --pkg=gio-2.0 Application.vala
public class Application : Gtk.Application {
private const int COVER_SIZE = 170;
private const int NAP_TIME = 500; // 0.1 Seconds
private const int MAX_TIMEOUT = 30000; // 30 Seconds
public Application () {
Object(application_id: "testing.my.application",
flags: ApplicationFlags.FLAGS_NONE);
}
public static File? open_file(string path) {
if(path.index_of("file:") == 0 || path.index_of("resource:") == 0 || path.index_of("http:") == 0 || path.index_of("https:") == 0) {
return GLib.File.new_for_uri(path);
} else {
return GLib.File.new_for_path(path);
}
}
public static void create_cover_image (Gtk.Image image, Gdk.Pixbuf pixbuf, int image_size) throws Error {
Gdk.Pixbuf cover_image = pixbuf;
if (cover_image.height == cover_image.width)
cover_image = cover_image.scale_simple (image_size, image_size, Gdk.InterpType.BILINEAR);
if (cover_image.height > cover_image.width) {
int new_height = image_size * cover_image.height / cover_image.width;
int new_width = image_size;
int offset = (new_height - new_width) / 2;
cover_image = new Gdk.Pixbuf.subpixbuf(cover_image.scale_simple (new_width, new_height, Gdk.InterpType.BILINEAR), 0, offset, image_size, image_size);
} else if (cover_image.height < cover_image.width) {
int new_height = image_size;
int new_width = image_size * cover_image.width / cover_image.height;
int offset = (new_width - new_height) / 2;
cover_image = new Gdk.Pixbuf.subpixbuf(cover_image.scale_simple (new_width, new_height, Gdk.InterpType.BILINEAR), offset, 0, image_size, COVER_SIZE);
}
if(image != null) {
image.clear();
image.set_from_pixbuf (cover_image);
}
}
private Gee.HashSet<string> queue = new Gee.HashSet<string>();
private Gee.HashMap<string, Gdk.Pixbuf> cache = new Gee.HashMap<string, Gdk.Pixbuf>();
public async void set_image(Gtk.Image image, string path) throws Error {
GLib.File file = open_file(path);
if (cache.has_key(path)) {
print("Path in the cache. Setting it to image. \n");
Gdk.Pixbuf cover_image = cache.get(path);
create_cover_image(image, cover_image, COVER_SIZE);
}
if(!queue.contains(path)) {
print("Path is in the queue\n");
queue.add(path);
GLib.InputStream stream = yield file.read_async ();
Gdk.Pixbuf cover_image = yield new Gdk.Pixbuf.from_stream_async (stream);
create_cover_image(image, cover_image, COVER_SIZE);
queue.remove(path);
cache.@set(path, cover_image);
} else {
do_stuff.begin (path, image, (obj, async_res) => {
print("done waiting for image.\n");
});
}
}
private async void do_stuff (string path, Gtk.Image image) {
for(int i = 0; i < MAX_TIMEOUT || cache.has_key(path); i+= NAP_TIME) {
yield nap (NAP_TIME);
if (cache.has_key(path)) {
Gdk.Pixbuf cover_image = cache.get(path);
create_cover_image(image, cover_image, COVER_SIZE);
}
}
}
public async void nap (uint interval, int priority = GLib.Priority.DEFAULT) {
GLib.Timeout.add (interval, () => {
nap.callback ();
return false;
}, priority);
yield;
}
protected override void activate () {
var window = new Gtk.ApplicationWindow (this);
window.set_default_size (400, 400);
window.title = "My Gtk.Application";
var button = new Gtk.Button.with_label("Click me");
button.clicked.connect(() => {
print("Clicked!\n");
});
var path = "https://upload.wikimedia.org/wikipedia/commons/8/8e/Velazquez-The_Surrender_of_Breda.jpg";
var image = new Gtk.Image();
image.pixel_size = COVER_SIZE;
set_image.begin (image, path, (obj, res) => {
window.show_all();
});
var image2 = new Gtk.Image();
set_image.begin (image2, path, (obj, res) => {
window.show_all();
});
var image3 = new Gtk.Image();
set_image.begin (image3, path, (obj, res) => {
window.show_all();
});
var image4 = new Gtk.Image();
set_image.begin (image4, path, (obj, res) => {
window.show_all();
});
var image5 = new Gtk.Image();
set_image.begin (image5, path, (obj, res) => {
window.show_all();
});
var container = new Gtk.Box(Gtk.Orientation.VERTICAL, 5);
container.add(button);
container.add(image);
container.add(image2);
container.add(image3);
container.add(image4);
container.add(image5);
// var label = new Gtk.Label("<b>Success With God & Psych</b>".replace("&", "&amp;"));
// label.wrap = true;
// label.use_markup = true;
window.add(container);
window.show_all ();
}
public static int main (string[] args) {
Application app = new Application ();
return app.run (args);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment