1/* 2 * This file is part of gitg 3 * 4 * Copyright (C) 2016 - Jesse van den Kieboom 5 * 6 * gitg is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * gitg is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with gitg. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20[GtkTemplate (ui = "/org/gnome/gitg/ui/gitg-diff-view-file-renderer-image.ui")] 21class Gitg.DiffViewFileRendererImage : Gtk.Grid, DiffViewFileRenderer 22{ 23 public Ggit.DiffDelta? delta { get; construct set; } 24 public Repository repository { get; construct set; } 25 26 [GtkChild( name = "diff_image_side_by_side" )] 27 private Gitg.DiffImageSideBySide d_diff_image_side_by_side; 28 29 [GtkChild( name = "diff_image_slider" )] 30 private Gitg.DiffImageSlider d_diff_image_slider; 31 32 [GtkChild( name = "scale_slider_adjustment" )] 33 private Gtk.Adjustment d_scale_slider_adjustment; 34 35 [GtkChild( name = "diff_image_overlay" )] 36 private Gitg.DiffImageOverlay d_diff_image_overlay; 37 38 [GtkChild( name = "scale_overlay_adjustment" )] 39 private Gtk.Adjustment d_scale_overlay_adjustment; 40 41 [GtkChild( name = "diff_image_difference" )] 42 private Gitg.DiffImageDifference d_diff_image_difference; 43 44 [GtkChild( name = "stack_switcher" )] 45 private Gtk.StackSwitcher d_stack_switcher; 46 47 private SurfaceCache d_cache; 48 49 public DiffViewFileRendererImage(Repository repository, Ggit.DiffDelta delta) 50 { 51 Object(repository: repository, delta: delta); 52 } 53 54 construct 55 { 56 d_cache = new SurfaceCache(pixbuf_for_file(delta.get_old_file()), 57 pixbuf_for_file(delta.get_new_file())); 58 59 d_diff_image_side_by_side.cache = d_cache; 60 d_diff_image_slider.cache = d_cache; 61 d_diff_image_overlay.cache = d_cache; 62 d_diff_image_difference.cache = d_cache; 63 64 if (d_cache.old_pixbuf == null || d_cache.new_pixbuf == null || 65 d_cache.old_pixbuf.get_width() != d_cache.new_pixbuf.get_width() || 66 d_cache.old_pixbuf.get_height() != d_cache.new_pixbuf.get_height()) 67 { 68 d_stack_switcher.sensitive = false; 69 } 70 71 d_scale_slider_adjustment.bind_property("value", d_diff_image_slider, "position", BindingFlags.DEFAULT | BindingFlags.SYNC_CREATE); 72 d_scale_overlay_adjustment.bind_property("value", d_diff_image_overlay, "alpha", BindingFlags.DEFAULT | BindingFlags.SYNC_CREATE); 73 } 74 75 private Gdk.Pixbuf? pixbuf_for_file(Ggit.DiffFile file) 76 { 77 if ((file.get_flags() & Ggit.DiffFlag.VALID_ID) == 0 || file.get_oid().is_zero()) 78 { 79 return null; 80 } 81 82 Ggit.Blob blob; 83 84 try 85 { 86 blob = repository.lookup<Ggit.Blob>(file.get_oid()); 87 } 88 catch (Error e) 89 { 90 stderr.printf(@"ERROR: failed to load image blob: $(e.message)\n"); 91 return null; 92 } 93 94 var stream = new MemoryInputStream.from_data(blob.get_raw_content(), null); 95 96 try 97 { 98 return new Gdk.Pixbuf.from_stream(stream); 99 } 100 catch (Error e) 101 { 102 stderr.printf(@"ERROR: failed to create pixbuf: $(e.message)\n"); 103 return null; 104 } 105 } 106 107 public void add_hunk(Ggit.DiffHunk hunk, Gee.ArrayList<Ggit.DiffLine> lines) 108 { 109 } 110 111 private class SurfaceCache : Object, Gitg.DiffImageSurfaceCache { 112 private Cairo.Surface? d_old_surface; 113 private Cairo.Surface? d_new_surface; 114 115 public Gdk.Pixbuf? old_pixbuf { get; construct set; } 116 public Gdk.Pixbuf? new_pixbuf { get; construct set; } 117 118 public Gdk.Window window { get; construct set; } 119 120 public SurfaceCache(Gdk.Pixbuf? old_pixbuf, Gdk.Pixbuf? new_pixbuf) 121 { 122 Object(old_pixbuf: old_pixbuf, new_pixbuf: new_pixbuf); 123 } 124 125 public Cairo.Surface? get_old_surface(Gdk.Window window) 126 { 127 return get_cached_surface(window, old_pixbuf, ref d_old_surface); 128 } 129 130 public Cairo.Surface? get_new_surface(Gdk.Window window) 131 { 132 return get_cached_surface(window, new_pixbuf, ref d_new_surface); 133 } 134 135 private Cairo.Surface? get_cached_surface(Gdk.Window window, Gdk.Pixbuf? pixbuf, ref Cairo.Surface? cached) 136 { 137 if (pixbuf == null) 138 { 139 return null; 140 } 141 142 if (cached == null) 143 { 144 cached = Gdk.cairo_surface_create_from_pixbuf(pixbuf, 0, window); 145 } 146 147 return cached; 148 } 149 } 150} 151 152// ex:ts=4 noet 153