Created
August 4, 2018 19:02
-
-
Save xpaulnim/6d37c794c041a78b4c8e1dd8d21560d9 to your computer and use it in GitHub Desktop.
Load remote images asyncronously using a cache.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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("&", "&")); | |
// 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