diff options
Diffstat (limited to 'src/events/EventDirectoryItem.vala')
-rw-r--r-- | src/events/EventDirectoryItem.vala | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/src/events/EventDirectoryItem.vala b/src/events/EventDirectoryItem.vala new file mode 100644 index 0000000..5b2026b --- /dev/null +++ b/src/events/EventDirectoryItem.vala @@ -0,0 +1,189 @@ +/* Copyright 2011-2014 Yorba Foundation + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +class EventDirectoryItem : CheckerboardItem { + private static int CROPPED_SCALE { + get { + return ThumbnailCache.Size.MEDIUM.get_scale() + + ((ThumbnailCache.Size.BIG.get_scale() - ThumbnailCache.Size.MEDIUM.get_scale()) / 2); + } + } + + public static Scaling squared_scaling = Scaling.to_fill_viewport(Dimensions(CROPPED_SCALE, + CROPPED_SCALE)); + + public Event event; + + private Gdk.Rectangle paul_lynde = Gdk.Rectangle(); + + public EventDirectoryItem(Event event) { + base (event, Dimensions(CROPPED_SCALE, CROPPED_SCALE), get_formatted_title(event), event.get_comment(), true, + Pango.Alignment.CENTER); + + this.event = event; + + // find the center square + paul_lynde = get_paul_lynde_rect(event.get_primary_source()); + + // don't display yet, but claim its dimensions + clear_image(Dimensions.for_rectangle(paul_lynde)); + + // monitor the event for changes + Event.global.items_altered.connect(on_events_altered); + } + + ~EventDirectoryItem() { + Event.global.items_altered.disconnect(on_events_altered); + } + + // square the photo's dimensions and locate the pixbuf's center square + private static Gdk.Rectangle get_paul_lynde_rect(MediaSource source) { + Dimensions scaled = squared_scaling.get_scaled_dimensions(source.get_dimensions()); + + Gdk.Rectangle paul_lynde = Gdk.Rectangle(); + paul_lynde.x = (scaled.width - CROPPED_SCALE).clamp(0, scaled.width) / 2; + paul_lynde.y = (scaled.height - CROPPED_SCALE).clamp(0, scaled.height) / 2; + paul_lynde.width = CROPPED_SCALE; + paul_lynde.height = CROPPED_SCALE; + + return paul_lynde; + } + + // scale and crop the center square of the media + private static Gdk.Pixbuf get_paul_lynde(MediaSource media, Gdk.Rectangle paul_lynde) throws Error { + Gdk.Pixbuf pixbuf = media.get_preview_pixbuf(squared_scaling); + + Dimensions thumbnail_dimensions = Dimensions.for_pixbuf(pixbuf); + + if (thumbnail_dimensions.width > 2 * paul_lynde.width || + thumbnail_dimensions.height > paul_lynde.height * 2 ) { + LibraryPhoto photo = (LibraryPhoto) media; + pixbuf = photo.get_pixbuf(squared_scaling); + thumbnail_dimensions = Dimensions.for_pixbuf(pixbuf); + } + + // to catch rounding errors in the two algorithms + paul_lynde = clamp_rectangle(paul_lynde, thumbnail_dimensions); + + // crop the center square + return new Gdk.Pixbuf.subpixbuf(pixbuf, paul_lynde.x, paul_lynde.y, paul_lynde.width, + paul_lynde.height); + } + + private static string get_formatted_title(Event event) { + bool has_photos = MediaSourceCollection.has_photo(event.get_media()); + bool has_videos = MediaSourceCollection.has_video(event.get_media()); + + int count = event.get_media_count(); + string count_text = ""; + if (has_photos && has_videos) + count_text = ngettext("%d Photo/Video", "%d Photos/Videos", count).printf(count); + else if (has_videos) + count_text = ngettext("%d Video", "%d Videos", count).printf(count); + else + count_text = ngettext("%d Photo", "%d Photos", count).printf(count); + + string? daterange = event.get_formatted_daterange(); + string name = event.get_name(); + + // if we don't have a daterange or if it's the same as name, then don't print it; otherwise + // print it beneath the preview photo + if (daterange == null || daterange == name) + return "<b>%s</b>\n%s".printf(guarded_markup_escape_text(name), + guarded_markup_escape_text(count_text)); + else + return "<b>%s</b>\n%s\n%s".printf(guarded_markup_escape_text(name), + guarded_markup_escape_text(count_text), guarded_markup_escape_text(daterange)); + } + + public override void exposed() { + if (is_exposed()) + return; + + try { + set_image(get_paul_lynde(event.get_primary_source(), paul_lynde)); + } catch (Error err) { + critical("Unable to fetch preview for %s: %s", event.to_string(), err.message); + } + + update_comment(); + + base.exposed(); + } + + public override void unexposed() { + if (!is_exposed()) + return; + + clear_image(Dimensions.for_rectangle(paul_lynde)); + + base.unexposed(); + } + + private void on_events_altered(Gee.Map<DataObject, Alteration> map) { + update_comment(); + if (map.has_key(event)) + set_title(get_formatted_title(event), true, Pango.Alignment.CENTER); + } + + protected override void thumbnail_altered() { + MediaSource media = event.get_primary_source(); + + // get new center square + paul_lynde = get_paul_lynde_rect(media); + + if (is_exposed()) { + try { + set_image(get_paul_lynde(media, paul_lynde)); + } catch (Error err) { + critical("Unable to fetch preview for %s: %s", event.to_string(), err.message); + } + } else { + clear_image(Dimensions.for_rectangle(paul_lynde)); + } + + base.thumbnail_altered(); + } + + protected override void paint_shadow(Cairo.Context ctx, Dimensions dimensions, Gdk.Point origin, + int radius, float initial_alpha) { + Dimensions altered = Dimensions(dimensions.width - 25, dimensions.height - 25); + base.paint_shadow(ctx, altered, origin, 36, initial_alpha); + } + + protected override void paint_border(Cairo.Context ctx, Dimensions object_dimensions, + Gdk.Point object_origin, int border_width) { + Dimensions dimensions = get_border_dimensions(object_dimensions, border_width); + Gdk.Point origin = get_border_origin(object_origin, border_width); + + draw_rounded_corners_filled(ctx, dimensions, origin, 6.0); + } + + protected override void paint_image(Cairo.Context ctx, Gdk.Pixbuf pixbuf, + Gdk.Point origin) { + Dimensions dimensions = Dimensions.for_pixbuf(pixbuf); + + if (pixbuf.get_has_alpha()) + draw_rounded_corners_filled(ctx, dimensions, origin, 6.0); + + // use rounded corners on events + context_rounded_corners(ctx, dimensions, origin, 6.0); + Gdk.cairo_set_source_pixbuf(ctx, pixbuf, origin.x, origin.y); + ctx.paint(); + } + + private void update_comment(bool init = false) { + string comment = event.get_comment(); + if (is_string_empty(comment)) + clear_comment(); + else if (!init) + set_comment(comment); + else + set_comment(""); + } +} + + |