[f-spot/infobox] Make InfoBox more flexible for new Properties
- From: Mike Gemünde <mgemuende src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [f-spot/infobox] Make InfoBox more flexible for new Properties
- Date: Wed, 27 Oct 2010 15:35:51 +0000 (UTC)
commit 57322a67e5d7de54d167d32bc09c0adaf87d2d5d
Author: Mike Gemünde <mike gemuende de>
Date: Mon Oct 25 21:59:07 2010 +0200
Make InfoBox more flexible for new Properties
lib/TagLib/TagLib | 2 +-
src/Clients/MainApp/FSpot.Widgets/InfoBox.cs | 1653 ++++++++++++--------------
src/Core/FSpot.Utils/FSpot.Utils/GtkUtil.cs | 3 +-
3 files changed, 739 insertions(+), 919 deletions(-)
---
diff --git a/lib/TagLib/TagLib b/lib/TagLib/TagLib
index b597fe7..d123960 160000
--- a/lib/TagLib/TagLib
+++ b/lib/TagLib/TagLib
@@ -1 +1 @@
-Subproject commit b597fe772b8f2278bde0cc3d0815c5a51c54370e
+Subproject commit d123960445605992b3cd74c626aab3b39526ff42
diff --git a/src/Clients/MainApp/FSpot.Widgets/InfoBox.cs b/src/Clients/MainApp/FSpot.Widgets/InfoBox.cs
index 6cb47b5..3d6ab8b 100644
--- a/src/Clients/MainApp/FSpot.Widgets/InfoBox.cs
+++ b/src/Clients/MainApp/FSpot.Widgets/InfoBox.cs
@@ -2,12 +2,12 @@
* FSpot.Widgets.InfoBox
*
* Author(s)
- * Ettore Perazzoli
- * Larry Ewing <lewing novell com>
- * Gabriel Burt
- * Stephane Delcroix <stephane delcroix org>
- * Ruben Vermeersch <ruben savanne be>
- * Mike Gemuende <mike gemuende de>
+ * Ettore Perazzoli
+ * Larry Ewing <lewing novell com>
+ * Gabriel Burt
+ * Stephane Delcroix <stephane delcroix org>
+ * Ruben Vermeersch <ruben savanne be>
+ * Mike Gemuende <mike gemuende de>
*
* This is free software. See COPYING for details.
*/
@@ -15,6 +15,7 @@
using Gtk;
using System;
+using System.Collections.Generic;
using System.IO;
using FSpot.Core;
using FSpot.Imaging;
@@ -30,915 +31,733 @@ using Hyena;
namespace FSpot.Widgets
{
- public class InfoBox : VBox {
- DelayedOperation update_delay;
-
- private IPhoto [] photos = new IPhoto [0];
- public IPhoto [] Photos {
- set {
- photos = value;
- update_delay.Start ();
- }
- private get {
- return photos;
- }
- }
-
- public IPhoto Photo {
- set {
- if (value != null) {
- Photos = new IPhoto [] { value };
- }
- }
- }
-
- private bool show_tags = false;
- public bool ShowTags {
- get { return show_tags; }
- set {
- if (show_tags == value)
- return;
-
- show_tags = value;
- tag_view.Visible = show_tags;
- }
- }
-
- private bool show_rating = false;
- public bool ShowRating {
- get { return show_rating; }
- set {
- if (show_rating == value)
- return;
-
- show_rating = value;
- rating_label.Visible = show_rating;
- rating_view.Visible = show_rating;
- }
- }
-
- public delegate void VersionChangedHandler (InfoBox info_box, IPhotoVersion version);
- public event VersionChangedHandler VersionChanged;
-
- private Expander info_expander;
- private Expander histogram_expander;
-
- private Gtk.Image histogram_image;
- private Histogram histogram;
-
- private DelayedOperation histogram_delay;
-
- // Context switching (toggles visibility).
- public event EventHandler ContextChanged;
-
- private ViewContext view_context = ViewContext.Unknown;
- public ViewContext Context {
- get { return view_context; }
- set {
- view_context = value;
- if (ContextChanged != null)
- ContextChanged (this, null);
- }
- }
-
- private readonly InfoBoxContextSwitchStrategy ContextSwitchStrategy;
-
- // Widgetry.
- private Label name_label;
- private Label name_value_label;
-
- private Label version_label;
- private ListStore version_list;
- private ComboBox version_combo;
-
- private Label date_label;
- private Label date_value_label;
-
- private Label size_label;
- private Label size_value_label;
-
- private Label exposure_label;
- private Label exposure_value_label;
-
- private Label focal_length_label;
- private Label focal_length_value_label;
-
- private Label camera_label;
- private Label camera_value_label;
-
- private Label file_size_label;
- private Label file_size_value_label;
-
- private Label rating_label;
- private RatingEntry rating_view;
-
- private TagView tag_view;
- private string default_exposure_string;
-
- private bool show_name;
- private bool show_date;
- private bool show_size;
- private bool show_exposure;
- private bool show_focal_length;
- private bool show_camera;
- private bool show_file_size;
-
- private void HandleRatingChanged (object o, EventArgs e)
- {
- App.Instance.Organizer.HandleRatingMenuSelected ((o as Widgets.RatingEntry).Value);
- }
-
- private Label CreateRightAlignedLabel (string text)
- {
- Label label = new Label ();
- label.UseMarkup = true;
- label.Markup = text;
- label.Xalign = 1;
-
- return label;
- }
-
- const int TABLE_XPADDING = 3;
- const int TABLE_YPADDING = 3;
- private Label AttachLabel (Table table, int row_num, Widget entry)
- {
- Label label = new Label (String.Empty);
- label.Xalign = 0;
- label.Selectable = true;
- label.Ellipsize = Pango.EllipsizeMode.End;
- label.Show ();
-
- label.PopulatePopup += HandlePopulatePopup;
-
- table.Attach (label, 1, 2, (uint) row_num, (uint) row_num + 1,
- AttachOptions.Expand | AttachOptions.Fill, AttachOptions.Expand | AttachOptions.Fill,
- (uint) entry.Style.XThickness + TABLE_XPADDING, (uint) entry.Style.YThickness);
-
- return label;
- }
-
- private void SetupWidgets ()
- {
-
- histogram_expander = new Expander (Catalog.GetString ("Histogram"));
- histogram_expander.Activated += delegate (object sender, EventArgs e) {
- ContextSwitchStrategy.SetHistogramVisible (Context, histogram_expander.Expanded);
- UpdateHistogram ();
- };
- histogram_expander.StyleSet += delegate (object sender, StyleSetArgs args) {
- Gdk.Color c = this.Toplevel.Style.Backgrounds [(int)Gtk.StateType.Active];
- histogram.RedColorHint = (byte) (c.Red / 0xff);
- histogram.GreenColorHint = (byte) (c.Green / 0xff);
- histogram.BlueColorHint = (byte) (c.Blue / 0xff);
- histogram.BackgroundColorHint = 0xff;
- UpdateHistogram ();
- };
- histogram_image = new Gtk.Image ();
- histogram = new Histogram ();
- histogram_expander.Add (histogram_image);
-
- Add (histogram_expander);
-
- info_expander = new Expander (Catalog.GetString ("Image Information"));
- info_expander.Activated += delegate (object sender, EventArgs e) {
- ContextSwitchStrategy.SetInfoBoxVisible (Context, info_expander.Expanded);
- };
-
- Table info_table = new Table (10, 2, false);
- info_table.BorderWidth = 0;
-
- string name_pre = "<b>";
- string name_post = "</b>";
-
- name_label = CreateRightAlignedLabel (name_pre + Catalog.GetString ("Name") + name_post);
- info_table.Attach (name_label, 0, 1, 0, 1, AttachOptions.Fill, AttachOptions.Fill, TABLE_XPADDING, TABLE_YPADDING);
-
- version_label = CreateRightAlignedLabel (name_pre + Catalog.GetString ("Version") + name_post);
- info_table.Attach (version_label, 0, 1, 1, 2, AttachOptions.Fill, AttachOptions.Fill, TABLE_XPADDING, TABLE_YPADDING);
-
- date_label = CreateRightAlignedLabel (name_pre + Catalog.GetString ("Date") + name_post + Environment.NewLine);
- info_table.Attach (date_label, 0, 1, 2, 3, AttachOptions.Fill, AttachOptions.Fill, TABLE_XPADDING, TABLE_YPADDING);
-
- size_label = CreateRightAlignedLabel (name_pre + Catalog.GetString ("Size") + name_post);
- info_table.Attach (size_label, 0, 1, 3, 4, AttachOptions.Fill, AttachOptions.Fill, TABLE_XPADDING, TABLE_YPADDING);
-
- default_exposure_string = name_pre + Catalog.GetString ("Exposure") + name_post;
- exposure_label = CreateRightAlignedLabel (default_exposure_string);
- info_table.Attach (exposure_label, 0, 1, 4, 5, AttachOptions.Fill, AttachOptions.Fill, TABLE_XPADDING, TABLE_YPADDING);
-
- focal_length_label = CreateRightAlignedLabel (name_pre + Catalog.GetString ("Focal Length") + name_post);
- info_table.Attach (focal_length_label, 0, 1, 5, 6, AttachOptions.Fill, AttachOptions.Fill, TABLE_XPADDING, TABLE_YPADDING);
-
- camera_label = CreateRightAlignedLabel (name_pre + Catalog.GetString ("Camera") + name_post);
- info_table.Attach (camera_label, 0, 1, 6, 7, AttachOptions.Fill, AttachOptions.Fill, TABLE_XPADDING, TABLE_YPADDING);
-
- file_size_label = CreateRightAlignedLabel (name_pre + Catalog.GetString ("File Size") + name_post);
- info_table.Attach (file_size_label, 0, 1, 7, 8, AttachOptions.Fill, AttachOptions.Fill, TABLE_XPADDING, TABLE_YPADDING);
-
- rating_label = CreateRightAlignedLabel (name_pre + Catalog.GetString ("Rating") + name_post);
- info_table.Attach (rating_label, 0, 1, 8, 9, AttachOptions.Fill, AttachOptions.Fill, TABLE_XPADDING, TABLE_YPADDING);
- rating_label.Visible = false;
-
- name_value_label = new Label ();
- name_value_label.Ellipsize = Pango.EllipsizeMode.Middle;
- name_value_label.Justify = Gtk.Justification.Left;
- name_value_label.Selectable = true;
- name_value_label.Xalign = 0;
- name_value_label.PopulatePopup += HandlePopulatePopup;
-
- info_table.Attach (name_value_label, 1, 2, 0, 1, AttachOptions.Fill | AttachOptions.Expand, AttachOptions.Fill, 3, 0);
-
- date_value_label = AttachLabel (info_table, 2, name_value_label);
- size_value_label = AttachLabel (info_table, 3, name_value_label);
- exposure_value_label = AttachLabel (info_table, 4, name_value_label);
-
- version_list = new ListStore (typeof (IPhotoVersion), typeof (string), typeof (bool));
- version_combo = new ComboBox ();
- CellRendererText version_name_cell = new CellRendererText ();
- version_name_cell.Ellipsize = Pango.EllipsizeMode.End;
- version_combo.PackStart (version_name_cell, true);
- version_combo.SetCellDataFunc (version_name_cell, new CellLayoutDataFunc (VersionNameCellFunc));
- version_combo.Model = version_list;
- version_combo.Changed += OnVersionComboChanged;
- info_table.Attach (version_combo, 1, 2, 1, 2, AttachOptions.Fill, AttachOptions.Fill, TABLE_XPADDING, TABLE_YPADDING);
-
- date_value_label.Text = Environment.NewLine;
- exposure_value_label.Text = Environment.NewLine;
- focal_length_value_label = AttachLabel (info_table, 5, name_value_label);
- camera_value_label = AttachLabel (info_table, 6, name_value_label);
- file_size_value_label = AttachLabel (info_table, 7, name_value_label);
-
- Gtk.Alignment rating_align = new Gtk.Alignment( 0, 0, 0, 0);
- info_table.Attach (rating_align, 1, 2, 8, 9, AttachOptions.Fill, AttachOptions.Fill, TABLE_XPADDING, TABLE_YPADDING);
-
- rating_view = new RatingEntry () { HasFrame = false };
- rating_view.Visible = false;
- rating_view.Changed += HandleRatingChanged;
- rating_align.Add (rating_view);
-
- tag_view = new TagView ();
- info_table.Attach (tag_view, 0, 2, 9, 10, AttachOptions.Fill, AttachOptions.Fill, TABLE_XPADDING, TABLE_YPADDING);
-
- info_table.ShowAll ();
-
- EventBox eb = new EventBox ();
- eb.Add (info_table);
- info_expander.Add (eb);
- eb.ButtonPressEvent += HandleButtonPressEvent;
-
- Add (info_expander);
- rating_label.Visible = show_rating;
- rating_view.Visible = show_rating;
- }
-
- // FIXME: We should pull this info directly out of IBrowsableItem
- private class ImageInfo {
- int width;
- int height;
- double? fnumber;
- double? exposure_time;
- uint? iso_speed;
- double? focal_length;
- string camera_model;
-
- public ImageInfo (IImageFile img)
- {
- if (img == null)
- return;
-
- using (var metadata = Metadata.Parse (img.Uri)) {
- width = metadata.Properties.PhotoWidth;
- height = metadata.Properties.PhotoHeight;
- fnumber = metadata.ImageTag.FNumber;
- exposure_time = metadata.ImageTag.ExposureTime;
- iso_speed = metadata.ImageTag.ISOSpeedRatings;
- focal_length = metadata.ImageTag.FocalLength;
- camera_model = metadata.ImageTag.Model;
- }
- }
-
- public string ExposureInfo {
- get {
- string info = String.Empty;
-
- if (fnumber.HasValue && fnumber.Value != 0.0) {
- try {
- info += String.Format ("f/{0:.0} ", fnumber.Value);
- } catch (FormatException) {
- return Catalog.GetString("(wrong format)");
- }
- }
-
- if (exposure_time.HasValue) {
- if (Math.Abs (exposure_time.Value) >= 1.0) {
- info += String.Format ("{0} sec ", exposure_time.Value);
- } else {
- info += String.Format ("1/{0} sec ", (int) (1 / exposure_time.Value));
- }
- }
-
- if (iso_speed.HasValue) {
- info += String.Format ("{0}ISO {1}", Environment.NewLine, iso_speed.Value);
- }
-
- if (info == String.Empty)
- return Catalog.GetString ("(None)");
-
- return info;
- }
- }
-
- public string FocalLength {
- get {
- if (focal_length == null)
- return Catalog.GetString ("(Unknown)");
-
- return String.Format ("{0} mm", focal_length.Value);
- }
- }
-
- public string CameraModel {
- get {
- if (camera_model != String.Empty)
- return camera_model;
- else
- return Catalog.GetString ("(Unknown)");
- }
- }
-
-
- public string Dimensions {
- get {
- if (width != 0 && height != 0)
- return String.Format ("{0}x{1}", width, height);
- else
- return Catalog.GetString ("(Unknown)");
- }
- }
- }
-
-
- public bool Update ()
- {
- if (Photos == null || Photos.Length == 0) {
- Hide ();
- } else if (Photos.Length == 1) {
- Show ();
- UpdateSingle ();
- } else if (Photos.Length > 1) {
- Show ();
- UpdateMultiple ();
- }
- return false;
- }
-
- private void UpdateSingle ()
- {
- ImageInfo info;
-
- IPhoto photo = Photos [0];
-
- histogram_expander.Visible = true;
- UpdateHistogram ();
-
- if (show_name) {
- name_value_label.Text = photo.Name != null ? photo.Name : String.Empty;
- }
- name_label.Visible = show_name;
- name_value_label.Visible = show_name;
-
- try {
- using (var img = ImageFile.Create (photo.DefaultVersion.Uri))
- {
- info = new ImageInfo (img);
- }
- } catch (System.Exception e) {
- Hyena.Log.Debug (e.StackTrace);
- info = new ImageInfo (null);
- }
-
- if (show_exposure) {
- exposure_value_label.Text = info.ExposureInfo;
- if (exposure_value_label.Text.IndexOf (Environment.NewLine) != -1)
- exposure_label.Markup = default_exposure_string + Environment.NewLine;
- else
- exposure_label.Markup = default_exposure_string;
- }
- exposure_label.Visible = show_exposure;
- exposure_value_label.Visible = show_exposure;
-
- if (show_size)
- size_value_label.Text = info.Dimensions;
- size_label.Visible = show_size;
- size_value_label.Visible = show_size;
-
- if (show_date) {
- DateTime local_time = photo.Time;
- date_value_label.Text = String.Format ("{0}{2}{1}",
- local_time.ToShortDateString (),
- local_time.ToShortTimeString (),
- Environment.NewLine
- );
- }
- date_label.Visible = show_date;
- date_value_label.Visible = show_date;
-
- if (show_focal_length)
- focal_length_value_label.Text = info.FocalLength;
- focal_length_label.Visible = show_focal_length;
- focal_length_value_label.Visible = show_focal_length;
-
- if (show_camera)
- camera_value_label.Text = info.CameraModel;
- camera_label.Visible = show_camera;
- camera_value_label.Visible = show_camera;
-
- version_label.Visible = true;
- version_combo.Visible = true;
- version_list.Clear ();
- version_combo.Changed -= OnVersionComboChanged;
-
- int count = 0;
- foreach (IPhotoVersion version in photo.Versions) {
- version_list.AppendValues (version, version.Name, true);
- if (version == photo.DefaultVersion)
- version_combo.Active = count;
- count++;
- }
-
- if (count <= 1) {
- version_combo.Sensitive = false;
- version_combo.TooltipText = Catalog.GetString ("(No Edits)");
- } else {
- version_combo.Sensitive = true;
- version_combo.TooltipText =
- String.Format (Catalog.GetPluralString ("(One Edit)", "({0} Edits)", count - 1), count - 1);
- }
- version_combo.Changed += OnVersionComboChanged;
-
- if (show_file_size) {
- try {
- GFile file = FileFactory.NewForUri (photo.DefaultVersion.Uri);
- GFileInfo file_info = file.QueryInfo ("standard::size", FileQueryInfoFlags.None, null);
- file_size_value_label.Text = Format.SizeForDisplay (file_info.Size);
- } catch (GLib.GException e) {
- file_size_value_label.Text = Catalog.GetString("(File read error)");
- Hyena.Log.DebugException (e);
- }
- }
-
- file_size_label.Visible = show_file_size;
- file_size_value_label.Visible = show_file_size;
-
- if (show_tags)
- tag_view.Current = photo;
- rating_label.Visible = show_rating;
- rating_view.Visible = show_rating;
- if (show_rating) {
- rating_view.Value = (int) photo.Rating;
- }
-
- Show ();
- }
-
- void VersionNameCellFunc (CellLayout cell_layout, CellRenderer cell, TreeModel tree_model, TreeIter iter)
- {
- string name = (string)tree_model.GetValue (iter, 1);
- (cell as CellRendererText).Text = name;
-
- cell.Sensitive = (bool)tree_model.GetValue (iter, 2);
- }
-
-
- void OnVersionComboChanged (object o, EventArgs e)
- {
- ComboBox combo = o as ComboBox;
- if (combo == null)
- return;
-
- TreeIter iter;
-
- if (combo.GetActiveIter (out iter))
- VersionChanged (this, (IPhotoVersion)version_list.GetValue (iter, 0));
- }
-
- private void UpdateMultiple ()
- {
- histogram_expander.Visible = false;
-
- name_label.Visible = false;
- name_value_label.Text = String.Format(Catalog.GetString("{0} Photos"), Photos.Length);
- name_value_label.Visible = true;
-
- version_label.Visible = false;
- version_combo.Visible = false;
-
- exposure_label.Visible = false;
- exposure_value_label.Visible = false;
-
- focal_length_label.Visible = false;
- focal_length_value_label.Visible = false;
-
- camera_label.Visible = false;
- camera_value_label.Visible = false;
-
- if (show_date) {
- IPhoto first = Photos[Photos.Length-1];
- IPhoto last = Photos [0];
- if (first.Time.Date == last.Time.Date) {
- //Note for translators: {0} is a date, {1} and {2} are times.
- date_value_label.Text = String.Format(Catalog.GetString("On {0} between \n{1} and {2}"),
- first.Time.ToShortDateString (),
- first.Time.ToShortTimeString (),
- last.Time.ToShortTimeString ());
- } else {
- date_value_label.Text = String.Format(Catalog.GetString("Between {0} \nand {1}"),
- first.Time.ToShortDateString (),
- last.Time.ToShortDateString ());
- }
- }
- date_label.Visible = show_date;
- date_value_label.Visible = show_date;
-
- if (show_file_size) {
- long file_size = 0;
- foreach (IPhoto photo in Photos) {
-
- try {
- GFile file = FileFactory.NewForUri (photo.DefaultVersion.Uri);
- GFileInfo file_info = file.QueryInfo ("standard::size", FileQueryInfoFlags.None, null);
- file_size += file_info.Size;
- } catch (GLib.GException e) {
- file_size = -1;
- Hyena.Log.DebugException (e);
- break;
- }
- }
-
- if (file_size != -1)
- file_size_value_label.Text = Format.SizeForDisplay (file_size);
-
- else
- file_size_value_label.Text = Catalog.GetString("(At least one File not found)");
- }
- file_size_label.Visible = show_file_size;
- file_size_value_label.Visible = show_file_size;
-
- size_label.Visible = false;
- size_value_label.Visible = false;
-
- rating_label.Visible = false;
- rating_view.Visible = false;
- }
-
- private Gdk.Pixbuf histogram_hint;
-
- private void UpdateHistogram ()
- {
- if (histogram_expander.Expanded)
- histogram_delay.Start ();
- }
-
- public void UpdateHistogram (Gdk.Pixbuf pixbuf) {
- histogram_hint = pixbuf;
- UpdateHistogram ();
- }
-
- private bool DelayedUpdateHistogram () {
- if (Photos.Length == 0)
- return false;
-
- IPhoto photo = Photos [0];
-
- Gdk.Pixbuf hint = histogram_hint;
- histogram_hint = null;
- int max = histogram_expander.Allocation.Width;
-
- try {
- if (hint == null)
- using (var img = ImageFile.Create (photo.DefaultVersion.Uri))
- hint = img.Load (256, 256);
-
- histogram_image.Pixbuf = histogram.Generate (hint, max);
-
- hint.Dispose ();
- } catch (System.Exception e) {
- Hyena.Log.Debug (e.StackTrace);
- using (Gdk.Pixbuf empty = new Gdk.Pixbuf (Gdk.Colorspace.Rgb, true, 8, 256, 256)) {
- empty.Fill (0x0);
- histogram_image.Pixbuf = histogram.Generate (empty, max);
- }
- }
-
- return false;
- }
-
- // Context switching
-
- private void HandleContextChanged (object sender, EventArgs args)
- {
- bool infobox_visible = ContextSwitchStrategy.InfoBoxVisible (Context);
- info_expander.Expanded = infobox_visible;
-
- bool histogram_visible = ContextSwitchStrategy.HistogramVisible (Context);
- histogram_expander.Expanded = histogram_visible;
-
- show_name = ContextSwitchStrategy.InfoBoxNameVisible (Context);
- show_date = ContextSwitchStrategy.InfoBoxDateVisible (Context);
- show_size = ContextSwitchStrategy.InfoBoxSizeVisible (Context);
- show_exposure = ContextSwitchStrategy.InfoBoxExposureVisible (Context);
- show_focal_length = ContextSwitchStrategy.InfoBoxFocalLengthVisible (Context);
- show_camera = ContextSwitchStrategy.InfoBoxCameraVisible (Context);
- show_file_size = ContextSwitchStrategy.InfoBoxFileSizeVisible (Context);
-
- if (infobox_visible)
- update_delay.Start ();
- }
-
- public void HandleMainWindowViewModeChanged (object o, EventArgs args)
- {
- MainWindow.ModeType mode = App.Instance.Organizer.ViewMode;
- if (mode == MainWindow.ModeType.IconView)
- Context = ViewContext.Library;
- else if (mode == MainWindow.ModeType.PhotoView)
- Context = ViewContext.Edit;
- }
-
- void HandleButtonPressEvent (object sender, ButtonPressEventArgs args)
- {
- if (args.Event.Button == 3) {
- Menu popup_menu = new Menu ();
-
- AddMenuItems (popup_menu);
-
- if (args.Event != null)
- popup_menu.Popup (null, null, null, args.Event.Button, args.Event.Time);
- else
- popup_menu.Popup (null, null, null, 0, Gtk.Global.CurrentEventTime);
-
- args.RetVal = true;
- }
- }
-
- void HandlePopulatePopup (object sender, PopulatePopupArgs args)
- {
- AddMenuItems (args.Menu);
-
- args.RetVal = true;
- }
-
- private void AddMenuItems (Menu popup_menu) {
-
- if (popup_menu.Children.Length > 0) {
- GtkUtil.MakeMenuSeparator (popup_menu);
- }
-
- MenuItem item;
-
- item = GtkUtil.MakeCheckMenuItem (popup_menu,
- Catalog.GetString ("Show Photo Name"),
- HandleMenuItemSelected,
- true,
- show_name,
- false);
-
- item.SetData ("cb", name_label.Handle);
-
- item = GtkUtil.MakeCheckMenuItem (popup_menu,
- Catalog.GetString ("Show Date"),
- HandleMenuItemSelected,
- true,
- show_date,
- false);
-
- item.SetData ("cb", date_label.Handle);
-
- item = GtkUtil.MakeCheckMenuItem (popup_menu,
- Catalog.GetString ("Show Size"),
- HandleMenuItemSelected,
- true,
- show_size,
- false);
-
- item.SetData ("cb", size_label.Handle);
-
- item = GtkUtil.MakeCheckMenuItem (popup_menu,
- Catalog.GetString ("Show Exposure"),
- HandleMenuItemSelected,
- true,
- show_exposure,
- false);
-
- item.SetData ("cb", exposure_label.Handle);
-
- item = GtkUtil.MakeCheckMenuItem (popup_menu,
- Catalog.GetString ("Show Focal Length"),
- HandleMenuItemSelected,
- true,
- show_focal_length,
- false);
-
- item.SetData ("cb", focal_length_label.Handle);
-
- item = GtkUtil.MakeCheckMenuItem (popup_menu,
- Catalog.GetString ("Show Camera"),
- HandleMenuItemSelected,
- true,
- show_camera,
- false);
-
- item.SetData ("cb", camera_label.Handle);
-
- item = GtkUtil.MakeCheckMenuItem (popup_menu,
- Catalog.GetString ("Show File Size"),
- HandleMenuItemSelected,
- true,
- show_file_size,
- false);
-
- item.SetData ("cb", file_size_label.Handle);
- }
-
- private void HandleMenuItemSelected (object sender, EventArgs args)
- {
- IntPtr handle = (sender as CheckMenuItem).GetData ("cb");
-
- if (handle == name_label.Handle) {
- show_name = (sender as CheckMenuItem).Active;
- ContextSwitchStrategy.SetInfoBoxNameVisible (Context, show_name);
- } else if (handle == date_label.Handle) {
- show_date = (sender as CheckMenuItem).Active;
- ContextSwitchStrategy.SetInfoBoxDateVisible (Context, show_date);
- } else if (handle == size_label.Handle) {
- show_size = (sender as CheckMenuItem).Active;
- ContextSwitchStrategy.SetInfoBoxSizeVisible (Context, show_size);
- } else if (handle == exposure_label.Handle) {
- show_exposure = (sender as CheckMenuItem).Active;
- ContextSwitchStrategy.SetInfoBoxExposureVisible (Context, show_exposure);
- } else if (handle == focal_length_label.Handle) {
- show_focal_length = (sender as CheckMenuItem).Active;
- ContextSwitchStrategy.SetInfoBoxFocalLengthVisible (Context, show_focal_length);
- } else if (handle == camera_label.Handle) {
- show_camera = (sender as CheckMenuItem).Active;
- ContextSwitchStrategy.SetInfoBoxCameraVisible (Context, show_camera);
- } else if (handle == file_size_label.Handle) {
- show_file_size = (sender as CheckMenuItem).Active;
- ContextSwitchStrategy.SetInfoBoxFileSizeVisible (Context, show_file_size);
- }
-
- update_delay.Start ();
- }
-
- // Constructor.
-
- public InfoBox () : base (false, 0)
- {
- ContextSwitchStrategy = new MRUInfoBoxContextSwitchStrategy ();
- ContextChanged += HandleContextChanged;
-
- SetupWidgets ();
-
- update_delay = new DelayedOperation (Update);
- update_delay.Start ();
-
- histogram_delay = new DelayedOperation (DelayedUpdateHistogram);
-
- BorderWidth = 2;
- Hide ();
- }
- }
-
- // Decides whether infobox / histogram should be shown for each context. Implemented
- // using the Strategy pattern, to make it swappable easily, in case the
- // default MRUInfoBoxContextSwitchStrategy is not sufficiently usable.
- public abstract class InfoBoxContextSwitchStrategy {
- public abstract bool InfoBoxVisible (ViewContext context);
- public abstract bool HistogramVisible (ViewContext context);
- public abstract bool InfoBoxNameVisible (ViewContext context);
- public abstract bool InfoBoxDateVisible (ViewContext context);
- public abstract bool InfoBoxSizeVisible (ViewContext context);
- public abstract bool InfoBoxExposureVisible (ViewContext context);
- public abstract bool InfoBoxFocalLengthVisible (ViewContext context);
- public abstract bool InfoBoxCameraVisible (ViewContext context);
- public abstract bool InfoBoxFileSizeVisible (ViewContext context);
-
- public abstract void SetInfoBoxVisible (ViewContext context, bool visible);
- public abstract void SetHistogramVisible (ViewContext context, bool visible);
- public abstract void SetInfoBoxNameVisible (ViewContext context, bool visible);
- public abstract void SetInfoBoxDateVisible (ViewContext context, bool visible);
- public abstract void SetInfoBoxSizeVisible (ViewContext context, bool visible);
- public abstract void SetInfoBoxExposureVisible (ViewContext context, bool visible);
- public abstract void SetInfoBoxFocalLengthVisible (ViewContext context, bool visible);
- public abstract void SetInfoBoxCameraVisible (ViewContext context, bool visible);
- public abstract void SetInfoBoxFileSizeVisible (ViewContext context, bool visible);
- }
-
- // Values are stored as strings, because bool is not nullable through Preferences.
- public class MRUInfoBoxContextSwitchStrategy : InfoBoxContextSwitchStrategy {
- public const string PREF_PREFIX = Preferences.APP_FSPOT + "ui";
-
- private string PrefKeyForContext (ViewContext context, string item) {
- return String.Format ("{0}/{1}_visible/{2}", PREF_PREFIX, item, context);
- }
-
- private string PrefKeyForContext (ViewContext context, string parent, string item) {
- return String.Format ("{0}/{1}_visible/{2}/{3}", PREF_PREFIX, parent, item, context);
- }
-
- private bool VisibilityForContext (ViewContext context, string item, bool default_value) {
- string visible = Preferences.Get<string> (PrefKeyForContext (context, item));
- if (visible == null)
- return default_value;
- else
- return visible == "1";
- }
-
- private bool VisibilityForContext (ViewContext context, string parent, string item, bool default_value) {
- string visible = Preferences.Get<string> (PrefKeyForContext (context, parent, item));
- if (visible == null)
- return default_value;
- else
- return visible == "1";
- }
-
- private void SetVisibilityForContext (ViewContext context, string item, bool visible) {
- Preferences.Set (PrefKeyForContext (context, item), visible ? "1" : "0");
- }
-
- private void SetVisibilityForContext (ViewContext context, string parent, string item, bool visible) {
- Preferences.Set (PrefKeyForContext (context, parent, item), visible ? "1" : "0");
- }
-
- public override bool InfoBoxVisible (ViewContext context) {
- return VisibilityForContext (context, "infobox", true);
- }
-
- public override bool HistogramVisible (ViewContext context) {
- return VisibilityForContext (context, "histogram", true);
- }
-
- public override bool InfoBoxNameVisible (ViewContext context) {
- return VisibilityForContext (context, "infobox", "name", true);
- }
-
- public override bool InfoBoxDateVisible (ViewContext context) {
- return VisibilityForContext (context, "infobox", "date", true);
- }
-
- public override bool InfoBoxSizeVisible (ViewContext context) {
- return VisibilityForContext (context, "infobox", "size", true);
- }
-
- public override bool InfoBoxExposureVisible (ViewContext context) {
- return VisibilityForContext (context, "infobox", "exposure", true);
- }
-
- public override bool InfoBoxFocalLengthVisible (ViewContext context) {
- return VisibilityForContext (context, "infobox", "focal_length", false);
- }
-
- public override bool InfoBoxCameraVisible (ViewContext context) {
- return VisibilityForContext (context, "infobox", "camera", false);
- }
-
- public override bool InfoBoxFileSizeVisible (ViewContext context) {
- return VisibilityForContext (context, "infobox", "file_size", false);
- }
-
- public override void SetInfoBoxVisible (ViewContext context, bool visible) {
- SetVisibilityForContext (context, "infobox", visible);
- }
-
- public override void SetHistogramVisible (ViewContext context, bool visible) {
- SetVisibilityForContext (context, "histogram", visible);
- }
-
- public override void SetInfoBoxNameVisible (ViewContext context, bool visible) {
- SetVisibilityForContext (context, "infobox", "name", visible);
- }
-
- public override void SetInfoBoxDateVisible (ViewContext context, bool visible) {
- SetVisibilityForContext (context, "infobox", "date", visible);
- }
-
- public override void SetInfoBoxSizeVisible (ViewContext context, bool visible) {
- SetVisibilityForContext (context, "infobox", "size", visible);
- }
-
- public override void SetInfoBoxExposureVisible (ViewContext context, bool visible) {
- SetVisibilityForContext (context, "infobox", "exposure", visible);
- }
-
- public override void SetInfoBoxFocalLengthVisible (ViewContext context, bool visible) {
- SetVisibilityForContext (context, "infobox", "focal_length", visible);
- }
-
- public override void SetInfoBoxCameraVisible (ViewContext context, bool visible) {
- SetVisibilityForContext (context, "infobox", "camera", visible);
- }
-
- public override void SetInfoBoxFileSizeVisible (ViewContext context, bool visible) {
- SetVisibilityForContext (context, "infobox", "file_size", visible);
- }
- }
+ public class InfoBox : VBox
+ {
+ DelayedOperation update_delay;
+
+ public struct InfoEntry
+ {
+ public bool TwoColumns;
+ public bool AlwaysVisible;
+ public bool DefaultVisibility;
+ public string Id;
+ public string Description;
+ public Widget LabelWidget;
+ public Widget InfoWidget;
+ public Action<Widget, IPhoto, TagLib.Image.File> SetSingle;
+ public Action<Widget, IPhoto[]> SetMultiple;
+ }
+
+ private List<InfoEntry> entries = new List<InfoEntry> ();
+
+ private void AddEntry (string id, string name, string description, Widget info_widget, float label_y_align,
+ bool default_visibility,
+ Action<Widget, IPhoto, TagLib.Image.File> set_single,
+ Action<Widget, IPhoto[]> set_multiple)
+ {
+ entries.Add (new InfoEntry {
+ TwoColumns = (name == null),
+ AlwaysVisible = (id == null) || (description == null),
+ DefaultVisibility = default_visibility,
+ Id = id,
+ Description = description,
+ LabelWidget = CreateRightAlignedLabel (String.Format ("<b>{0}</b>", name), label_y_align),
+ InfoWidget = info_widget,
+ SetSingle = set_single,
+ SetMultiple = set_multiple
+ });
+ }
+
+ private void AddEntry (string id, string name, string description, Widget info_widget, float label_y_align,
+ Action<Widget, IPhoto, TagLib.Image.File> set_single,
+ Action<Widget, IPhoto[]> set_multiple)
+ {
+ AddEntry (id, name, description, info_widget, label_y_align, true, set_single, set_multiple);
+ }
+
+ private void AddEntry (string id, string name, string description, Widget info_widget, bool default_visibility,
+ Action<Widget, IPhoto, TagLib.Image.File> set_single,
+ Action<Widget, IPhoto[]> set_multiple)
+ {
+ AddEntry (id, name, description, info_widget, 0.0f, default_visibility, set_single, set_multiple);
+ }
+
+ private void AddEntry (string id, string name, string description, Widget info_widget,
+ Action<Widget, IPhoto, TagLib.Image.File> set_single,
+ Action<Widget, IPhoto[]> set_multiple)
+ {
+ AddEntry (id, name, description, info_widget, 0.0f, set_single, set_multiple);
+ }
+
+ private void AddLabelEntry (string id, string name, string description,
+ Func<IPhoto, TagLib.Image.File, string> single_string,
+ Func<IPhoto[], string> multiple_string)
+ {
+ AddLabelEntry (id, name, description, true, single_string, multiple_string);
+ }
+
+ private void AddLabelEntry (string id, string name, string description, bool default_visibility,
+ Func<IPhoto, TagLib.Image.File, string> single_string,
+ Func<IPhoto[], string> multiple_string)
+ {
+ Action<Widget, IPhoto, TagLib.Image.File> set_single = (widget, photo, metadata) => {
+ (widget as Label).Text = single_string (photo, metadata);
+ };
+
+ Action<Widget, IPhoto[]> set_multiple = (widget, photos) => {
+ (widget as Label).Text = multiple_string (photos);
+ };
+
+ AddEntry (id, name, description, CreateLeftAlignedLabel (String.Empty), default_visibility,
+ single_string == null ? null : set_single,
+ multiple_string == null ? null : set_multiple);
+ }
+
+
+ private IPhoto[] photos = new IPhoto[0];
+ public IPhoto[] Photos {
+ private get { return photos; }
+ set {
+ photos = value;
+ update_delay.Start ();
+ }
+ }
+
+ public IPhoto Photo {
+ set {
+ if (value != null) {
+ Photos = new IPhoto[] { value };
+ }
+ }
+ }
+
+ private bool show_tags = false;
+ public bool ShowTags {
+ get { return show_tags; }
+ set {
+ if (show_tags == value)
+ return;
+
+ show_tags = value;
+ // tag_view.Visible = show_tags;
+ }
+ }
+
+ private bool show_rating = false;
+ public bool ShowRating {
+ get { return show_rating; }
+ set {
+ if (show_rating == value)
+ return;
+
+ show_rating = value;
+ // rating_label.Visible = show_rating;
+ // rating_view.Visible = show_rating;
+ }
+ }
+
+ public delegate void VersionChangedHandler (InfoBox info_box, IPhotoVersion version);
+ public event VersionChangedHandler VersionChanged;
+
+ private Expander info_expander;
+ private Expander histogram_expander;
+
+ private Gtk.Image histogram_image;
+ private Histogram histogram;
+
+ private DelayedOperation histogram_delay;
+
+ // Context switching (toggles visibility).
+ public event EventHandler ContextChanged;
+
+ private ViewContext view_context = ViewContext.Unknown;
+ public ViewContext Context {
+ get { return view_context; }
+ set {
+ view_context = value;
+ if (ContextChanged != null)
+ ContextChanged (this, null);
+ }
+ }
+
+ private readonly InfoBoxContextSwitchStrategy ContextSwitchStrategy;
+
+ // Widgetry.
+ private ListStore version_list;
+ private ComboBox version_combo;
+
+
+ private void HandleRatingChanged (object o, EventArgs e)
+ {
+ App.Instance.Organizer.HandleRatingMenuSelected ((o as Widgets.RatingEntry).Value);
+ }
+
+ private Label CreateRightAlignedLabel (string text, float yalign)
+ {
+ Label label = new Label ();
+ label.UseMarkup = true;
+ label.Markup = text;
+ label.Xalign = 1.0f;
+ label.Yalign = yalign;
+
+ return label;
+ }
+
+ private Label CreateLeftAlignedLabel (string text)
+ {
+ Label label = new Label ();
+ label.UseMarkup = true;
+ label.Markup = text;
+ label.Xalign = 0.0f;
+ label.Yalign = 0.0f;
+ label.Selectable = true;
+ label.Ellipsize = Pango.EllipsizeMode.End;
+
+ return label;
+ }
+
+ private Table info_table;
+
+ private void AttachRow (int row, InfoEntry entry)
+ {
+ if (!entry.TwoColumns) {
+ info_table.Attach (entry.LabelWidget, 0, 1, (uint)row, (uint)row + 1, AttachOptions.Fill, AttachOptions.Fill, TABLE_XPADDING, TABLE_YPADDING);
+ }
+
+ info_table.Attach (entry.InfoWidget, entry.TwoColumns ? 0u : 1u, 2, (uint)row, (uint)row + 1, AttachOptions.Expand | AttachOptions.Fill, AttachOptions.Expand | AttachOptions.Fill, TABLE_XPADDING, TABLE_YPADDING);
+
+ var info_label = entry.InfoWidget as Label;
+ if (info_label != null)
+ info_label.PopulatePopup += HandlePopulatePopup;
+
+ var info_entry = entry.InfoWidget as Entry;
+ if (info_entry != null)
+ info_entry.PopulatePopup += HandlePopulatePopup;
+ ;
+ }
+
+ private void UpdateTable ()
+ {
+ info_table.Resize ((uint)(head_rows + entries.Count), 2);
+ int i = 0;
+ foreach (var entry in entries) {
+ AttachRow (head_rows + i, entry);
+ i++;
+ }
+ }
+
+
+ private void SetEntryWidgetVisibility (InfoEntry entry, bool def)
+ {
+ entry.InfoWidget.Visible = ContextSwitchStrategy.InfoEntryVisible (Context, entry) && def;
+ entry.LabelWidget.Visible = ContextSwitchStrategy.InfoEntryVisible (Context, entry) && def;
+
+ }
+
+ private void UpdateEntries ()
+ {
+
+ }
+
+ const int TABLE_XPADDING = 3;
+ const int TABLE_YPADDING = 3;
+ private Label AttachLabel (Table table, int row_num, Widget entry)
+ {
+ Label label = new Label (String.Empty);
+ label.Xalign = 0;
+ label.Selectable = true;
+ label.Ellipsize = Pango.EllipsizeMode.End;
+ label.Show ();
+
+ label.PopulatePopup += HandlePopulatePopup;
+
+ table.Attach (label, 1, 2, (uint)row_num, (uint)row_num + 1, AttachOptions.Expand | AttachOptions.Fill, AttachOptions.Expand | AttachOptions.Fill, (uint)entry.Style.XThickness + TABLE_XPADDING, (uint)entry.Style.YThickness);
+
+ return label;
+ }
+
+ private const int head_rows = 0;
+
+ private void SetupWidgets ()
+ {
+
+ histogram_expander = new Expander (Catalog.GetString ("Histogram"));
+ histogram_expander.Activated += delegate(object sender, EventArgs e) {
+ ContextSwitchStrategy.SetHistogramVisible (Context, histogram_expander.Expanded);
+ UpdateHistogram ();
+ };
+ histogram_expander.StyleSet += delegate(object sender, StyleSetArgs args) {
+ Gdk.Color c = this.Toplevel.Style.Backgrounds[(int)Gtk.StateType.Active];
+ histogram.RedColorHint = (byte)(c.Red / 0xff);
+ histogram.GreenColorHint = (byte)(c.Green / 0xff);
+ histogram.BlueColorHint = (byte)(c.Blue / 0xff);
+ histogram.BackgroundColorHint = 0xff;
+ UpdateHistogram ();
+ };
+ histogram_image = new Gtk.Image ();
+ histogram = new Histogram ();
+ histogram_expander.Add (histogram_image);
+
+ Add (histogram_expander);
+
+ info_expander = new Expander (Catalog.GetString ("Image Information"));
+ info_expander.Activated += (sender, e) => {
+ ContextSwitchStrategy.SetInfoBoxVisible (Context, info_expander.Expanded);
+ };
+
+ info_table = new Table (head_rows, 2, false) { BorderWidth = 0 };
+
+ AddLabelEntry (null, null, null, null,
+ photos => { return String.Format (Catalog.GetString ("{0} Photos"), photos.Length); });
+
+ AddLabelEntry (null, Catalog.GetString ("Name"), null,
+ (photo, file) => { return photo.Name ?? String.Empty; }, null);
+
+ version_list = new ListStore (typeof(IPhotoVersion), typeof(string), typeof(bool));
+ version_combo = new ComboBox ();
+ CellRendererText version_name_cell = new CellRendererText ();
+ version_name_cell.Ellipsize = Pango.EllipsizeMode.End;
+ version_combo.PackStart (version_name_cell, true);
+ version_combo.SetCellDataFunc (version_name_cell, new CellLayoutDataFunc (VersionNameCellFunc));
+ version_combo.Model = version_list;
+ version_combo.Changed += OnVersionComboChanged;
+
+ AddEntry (null, Catalog.GetString ("Version"), null, version_combo, 0.5f,
+ (widget, photo, file) => {
+ version_list.Clear ();
+ version_combo.Changed -= OnVersionComboChanged;
+
+ int count = 0;
+ foreach (IPhotoVersion version in photo.Versions) {
+ version_list.AppendValues (version, version.Name, true);
+ if (version == photo.DefaultVersion)
+ version_combo.Active = count;
+ count++;
+ }
+
+ if (count <= 1) {
+ version_combo.Sensitive = false;
+ version_combo.TooltipText = Catalog.GetString ("(No Edits)");
+ } else {
+ version_combo.Sensitive = true;
+ version_combo.TooltipText =
+ String.Format (Catalog.GetPluralString ("(One Edit)", "({0} Edits)", count - 1),
+ count - 1);
+ }
+ version_combo.Changed += OnVersionComboChanged;
+ }, null);
+
+ AddLabelEntry ("date", Catalog.GetString ("Date"), Catalog.GetString ("Show Date"),
+ (photo, file) => {
+ return String.Format ("{0}{2}{1}",
+ photo.Time.ToShortDateString (),
+ photo.Time.ToShortTimeString (),
+ Environment.NewLine); },
+ photos => {
+ IPhoto first = photos[photos.Length - 1];
+ IPhoto last = photos[0];
+ if (first.Time.Date == last.Time.Date) {
+ //Note for translators: {0} is a date, {1} and {2} are times.
+ return String.Format (Catalog.GetString ("On {0} between \n{1} and {2}"),
+ first.Time.ToShortDateString (),
+ first.Time.ToShortTimeString (),
+ last.Time.ToShortTimeString ());
+ } else {
+ return String.Format (Catalog.GetString ("Between {0} \nand {1}"),
+ first.Time.ToShortDateString (),
+ last.Time.ToShortDateString ());
+ }
+ });
+
+ AddLabelEntry ("size", Catalog.GetString ("Size"), Catalog.GetString ("Show Size"),
+ (photo, metadata) => {
+ int width = metadata.Properties.PhotoWidth;
+ int height = metadata.Properties.PhotoHeight;
+
+ if (width != 0 && height != 0)
+ return String.Format ("{0}x{1}", width, height);
+ else
+ return Catalog.GetString ("(Unknown)");
+ }, null);
+
+ AddLabelEntry ("exposure", Catalog.GetString ("Exposure"), Catalog.GetString ("Show Exposure"),
+ (photo, metadata) => {
+ var fnumber = metadata.ImageTag.FNumber;
+ var exposure_time = metadata.ImageTag.ExposureTime;
+ var iso_speed = metadata.ImageTag.ISOSpeedRatings;
+
+ string info = String.Empty;
+
+ if (fnumber.HasValue && fnumber.Value != 0.0) {
+ info += String.Format ("f/{0:.0} ", fnumber.Value);
+ }
+
+ if (exposure_time.HasValue) {
+ if (Math.Abs (exposure_time.Value) >= 1.0) {
+ info += String.Format ("{0} sec ", exposure_time.Value);
+ } else {
+ info += String.Format ("1/{0} sec ", (int)(1 / exposure_time.Value));
+ }
+ }
+
+ if (iso_speed.HasValue) {
+ info += String.Format ("{0}ISO {1}", Environment.NewLine, iso_speed.Value);
+ }
+
+ var exif = metadata.ImageTag.Exif;
+ if (exif != null) {
+ var flash = exif.ExifIFD.GetLongValue (0, (ushort)TagLib.IFD.Tags.ExifEntryTag.Flash);
+
+ if (flash.HasValue) {
+ if ((flash.Value & 0x01) == 0x01)
+ info += String.Format (", {0}", Catalog.GetString ("flash fired"));
+ else
+ info += String.Format (", {0}", Catalog.GetString ("flash didn't fire"));
+ }
+ }
+
+ if (info == String.Empty)
+ return Catalog.GetString ("(None)");
+
+ return info;
+ }, null);
+
+ AddLabelEntry ("focal_length", Catalog.GetString ("Focal Length"), Catalog.GetString ("Show Focal Length"),
+ false, (photo, metadata) => {
+ var focal_length = metadata.ImageTag.FocalLength;
+
+ if (focal_length == null)
+ return Catalog.GetString ("(Unknown)");
+ else
+ return String.Format ("{0} mm", focal_length.Value);
+ }, null);
+
+ AddLabelEntry ("camera", Catalog.GetString ("Camera"), Catalog.GetString ("Show Camera"), false,
+ (photo, metadata) => { return metadata.ImageTag.Model ?? Catalog.GetString ("(Unknown)"); },
+ null);
+
+ AddLabelEntry ("creator", Catalog.GetString ("Creator"), Catalog.GetString ("Show Creator"),
+ (photo, metadata) => { return metadata.ImageTag.Creator ?? Catalog.GetString ("(Unknown)"); },
+ null);
+
+ AddLabelEntry ("file_size", Catalog.GetString ("File Size"), Catalog.GetString ("Show File Size"), false,
+ (photo, metadata) => {
+ try {
+ GFile file = FileFactory.NewForUri (photo.DefaultVersion.Uri);
+ GFileInfo file_info = file.QueryInfo ("standard::size", FileQueryInfoFlags.None, null);
+ return Format.SizeForDisplay (file_info.Size);
+ } catch (GLib.GException e) {
+ Hyena.Log.DebugException (e);
+ return Catalog.GetString ("(File read error)");
+ }
+ }, null);
+
+ var rating_entry = new RatingEntry { HasFrame = false, AlwaysShowEmptyStars = true };
+ rating_entry.Changed += HandleRatingChanged;
+ var rating_align = new Gtk.Alignment (0, 0, 0, 0);
+ rating_align.Add (rating_entry);
+ AddEntry ("rating", Catalog.GetString ("Rating"), Catalog.GetString ("Show Rating"), rating_align, false,
+ (widget, photo, metadata) => { ((widget as Alignment).Child as RatingEntry).Value = (int) photo.Rating; },
+ null);
+
+ AddEntry ("tag", null, Catalog.GetString ("Show Tags"), new TagView (), false,
+ (widget, photo, metadata) => { (widget as TagView).Current = photo; }, null);
+
+ UpdateTable ();
+
+ EventBox eb = new EventBox ();
+ eb.Add (info_table);
+ info_expander.Add (eb);
+ eb.ButtonPressEvent += HandleButtonPressEvent;
+
+ Add (info_expander);
+ }
+
+ public bool Update ()
+ {
+ if (Photos == null || Photos.Length == 0) {
+ Hide ();
+ } else if (Photos.Length == 1) {
+ var photo = Photos[0];
+
+ using (var metadata = Metadata.Parse (photo.DefaultVersion.Uri)) {
+ foreach (var entry in entries) {
+ bool is_single = (entry.SetSingle != null);
+
+ if (is_single)
+ entry.SetSingle (entry.InfoWidget, photo, metadata);
+
+ SetEntryWidgetVisibility (entry, is_single);
+ }
+ }
+ Show ();
+ } else if (Photos.Length > 1) {
+ foreach (var entry in entries) {
+ bool is_multiple = (entry.SetMultiple != null);
+
+ if (is_multiple)
+ entry.SetMultiple (entry.InfoWidget, Photos);
+
+ SetEntryWidgetVisibility (entry, is_multiple);
+ }
+ histogram_expander.Visible = false;
+ Show ();
+ }
+ return false;
+ }
+
+ void VersionNameCellFunc (CellLayout cell_layout, CellRenderer cell, TreeModel tree_model, TreeIter iter)
+ {
+ string name = (string)tree_model.GetValue (iter, 1);
+ (cell as CellRendererText).Text = name;
+
+ cell.Sensitive = (bool)tree_model.GetValue (iter, 2);
+ }
+
+ void OnVersionComboChanged (object o, EventArgs e)
+ {
+ ComboBox combo = o as ComboBox;
+ if (combo == null)
+ return;
+
+ TreeIter iter;
+
+ if (combo.GetActiveIter (out iter))
+ VersionChanged (this, (IPhotoVersion)version_list.GetValue (iter, 0));
+ }
+
+ private Gdk.Pixbuf histogram_hint;
+
+ private void UpdateHistogram ()
+ {
+ if (histogram_expander.Expanded)
+ histogram_delay.Start ();
+ }
+
+ public void UpdateHistogram (Gdk.Pixbuf pixbuf)
+ {
+ histogram_hint = pixbuf;
+ UpdateHistogram ();
+ }
+
+ private bool DelayedUpdateHistogram ()
+ {
+ if (Photos.Length == 0)
+ return false;
+
+ IPhoto photo = Photos[0];
+
+ Gdk.Pixbuf hint = histogram_hint;
+ histogram_hint = null;
+ int max = histogram_expander.Allocation.Width;
+
+ try {
+ if (hint == null)
+ using (var img = ImageFile.Create (photo.DefaultVersion.Uri)) {
+ hint = img.Load (256, 256);
+ }
+
+ histogram_image.Pixbuf = histogram.Generate (hint, max);
+
+ hint.Dispose ();
+ } catch (System.Exception e) {
+ Hyena.Log.Debug (e.StackTrace);
+ using (Gdk.Pixbuf empty = new Gdk.Pixbuf (Gdk.Colorspace.Rgb, true, 8, 256, 256)) {
+ empty.Fill (0x0);
+ histogram_image.Pixbuf = histogram.Generate (empty, max);
+ }
+ }
+
+ return false;
+ }
+
+ // Context switching
+
+ private void HandleContextChanged (object sender, EventArgs args)
+ {
+ bool infobox_visible = ContextSwitchStrategy.InfoBoxVisible (Context);
+ info_expander.Expanded = infobox_visible;
+
+ bool histogram_visible = ContextSwitchStrategy.HistogramVisible (Context);
+ histogram_expander.Expanded = histogram_visible;
+
+ if (infobox_visible)
+ update_delay.Start ();
+ }
+
+ public void HandleMainWindowViewModeChanged (object o, EventArgs args)
+ {
+ MainWindow.ModeType mode = App.Instance.Organizer.ViewMode;
+ if (mode == MainWindow.ModeType.IconView)
+ Context = ViewContext.Library; else if (mode == MainWindow.ModeType.PhotoView) {
+ Context = ViewContext.Edit;
+ }
+ }
+
+ void HandleButtonPressEvent (object sender, ButtonPressEventArgs args)
+ {
+ if (args.Event.Button == 3) {
+ Menu popup_menu = new Menu ();
+
+ AddMenuItems (popup_menu);
+
+ if (args.Event != null)
+ popup_menu.Popup (null, null, null, args.Event.Button, args.Event.Time);
+ else
+ popup_menu.Popup (null, null, null, 0, Gtk.Global.CurrentEventTime);
+
+ args.RetVal = true;
+ }
+ }
+
+ void HandlePopulatePopup (object sender, PopulatePopupArgs args)
+ {
+ AddMenuItems (args.Menu);
+
+ args.RetVal = true;
+ }
+
+ private void AddMenuItems (Menu popup_menu)
+ {
+ var items = new Dictionary <MenuItem, InfoEntry> ();
+
+ if (popup_menu.Children.Length > 0 && entries.Count > 0) {
+ GtkUtil.MakeMenuSeparator (popup_menu);
+ }
+
+ foreach (var entry in entries) {
+ if (entry.AlwaysVisible)
+ continue;
+
+ var item =
+ GtkUtil.MakeCheckMenuItem (popup_menu, entry.Description, (sender, args) => {
+ ContextSwitchStrategy.SetInfoEntryVisible (Context, items [sender as CheckMenuItem], (sender as CheckMenuItem).Active);
+ Update ();
+ },
+ true, ContextSwitchStrategy.InfoEntryVisible (Context, entry), false);
+
+ items.Add (item, entry);
+ }
+ }
+
+ private void HandleMenuItemSelected (object sender, EventArgs args)
+ {
+
+ }
+
+ // Constructor.
+
+ public InfoBox () : base(false, 0)
+ {
+ ContextSwitchStrategy = new MRUInfoBoxContextSwitchStrategy ();
+ ContextChanged += HandleContextChanged;
+
+ SetupWidgets ();
+
+ update_delay = new DelayedOperation (Update);
+ update_delay.Start ();
+
+ histogram_delay = new DelayedOperation (DelayedUpdateHistogram);
+
+ BorderWidth = 2;
+ Hide ();
+ }
+ }
+
+ // Decides whether infobox / histogram should be shown for each context. Implemented
+ // using the Strategy pattern, to make it swappable easily, in case the
+ // default MRUInfoBoxContextSwitchStrategy is not sufficiently usable.
+ public abstract class InfoBoxContextSwitchStrategy
+ {
+ public abstract bool InfoBoxVisible (ViewContext context);
+ public abstract bool HistogramVisible (ViewContext context);
+
+ public abstract bool InfoEntryVisible (ViewContext context, InfoBox.InfoEntry entry);
+
+ public abstract void SetInfoBoxVisible (ViewContext context, bool visible);
+ public abstract void SetHistogramVisible (ViewContext context, bool visible);
+
+ public abstract void SetInfoEntryVisible (ViewContext context, InfoBox.InfoEntry entry, bool visible);
+ }
+
+ // Values are stored as strings, because bool is not nullable through Preferences.
+ public class MRUInfoBoxContextSwitchStrategy : InfoBoxContextSwitchStrategy
+ {
+ public const string PREF_PREFIX = Preferences.APP_FSPOT + "ui";
+
+ private string PrefKeyForContext (ViewContext context, string item)
+ {
+ return String.Format ("{0}/{1}_visible/{2}", PREF_PREFIX, item, context);
+ }
+
+ private string PrefKeyForContext (ViewContext context, string parent, string item)
+ {
+ return String.Format ("{0}/{1}_visible/{2}/{3}", PREF_PREFIX, parent, item, context);
+ }
+
+ private bool VisibilityForContext (ViewContext context, string item, bool default_value)
+ {
+ string visible = Preferences.Get<string> (PrefKeyForContext (context, item));
+ if (visible == null)
+ return default_value;
+ else
+ return visible == "1";
+ }
+
+ private bool VisibilityForContext (ViewContext context, string parent, string item, bool default_value)
+ {
+ string visible = Preferences.Get<string> (PrefKeyForContext (context, parent, item));
+ if (visible == null)
+ return default_value;
+ else
+ return visible == "1";
+ }
+
+ private void SetVisibilityForContext (ViewContext context, string item, bool visible)
+ {
+ Preferences.Set (PrefKeyForContext (context, item), visible ? "1" : "0");
+ }
+
+ private void SetVisibilityForContext (ViewContext context, string parent, string item, bool visible)
+ {
+ Preferences.Set (PrefKeyForContext (context, parent, item), visible ? "1" : "0");
+ }
+
+ public override bool InfoBoxVisible (ViewContext context)
+ {
+ return VisibilityForContext (context, "infobox", true);
+ }
+
+ public override bool HistogramVisible (ViewContext context)
+ {
+ return VisibilityForContext (context, "histogram", true);
+ }
+
+ public override bool InfoEntryVisible (ViewContext context, InfoBox.InfoEntry entry)
+ {
+ if (entry.AlwaysVisible)
+ return true;
+
+ return VisibilityForContext (context, "infobox", entry.Id, true);
+ }
+
+ public override void SetInfoBoxVisible (ViewContext context, bool visible)
+ {
+ SetVisibilityForContext (context, "infobox", visible);
+ }
+
+ public override void SetHistogramVisible (ViewContext context, bool visible)
+ {
+ SetVisibilityForContext (context, "histogram", visible);
+ }
+
+ public override void SetInfoEntryVisible (ViewContext context, InfoBox.InfoEntry entry, bool visible)
+ {
+ Hyena.Log.DebugFormat ("Set Visibility for Entry {0} to {1}", entry.Id, visible);
+ if (entry.AlwaysVisible)
+ throw new Exception ("entry visibility cannot be set");
+
+ SetVisibilityForContext (context, "infobox", entry.Id, visible);
+ }
+ }
}
diff --git a/src/Core/FSpot.Utils/FSpot.Utils/GtkUtil.cs b/src/Core/FSpot.Utils/FSpot.Utils/GtkUtil.cs
index 9c9ff8c..be99f5e 100644
--- a/src/Core/FSpot.Utils/FSpot.Utils/GtkUtil.cs
+++ b/src/Core/FSpot.Utils/FSpot.Utils/GtkUtil.cs
@@ -56,10 +56,11 @@ namespace FSpot.Utils
public static Gtk.MenuItem MakeCheckMenuItem (Gtk.Menu menu, string label, EventHandler e, bool enabled, bool active, bool as_radio)
{
Gtk.CheckMenuItem i = new Gtk.CheckMenuItem (label);
- i.Activated += e;
i.Sensitive = enabled;
i.DrawAsRadio = as_radio;
i.Active = active;
+
+ i.Activated += e;
menu.Append(i);
i.Show ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]