Index: src/PhotoImageView.cs
===================================================================
--- src/PhotoImageView.cs	(revisione 3522)
+++ src/PhotoImageView.cs	(copia locale)
@@ -345,6 +345,15 @@
 			
 			this.UnsetSelection ();
 
+			//Load photo tags over the image for tags with coordinates
+			if (Query != null)
+				foreach (Tag t in Query[item.Index].Tags ) {
+					if (t.TagCoordinates != null && t.TagCoordinates.Width != 0 && t.TagCoordinates.Height != 0) {
+						Console.WriteLine ("Drawing tagarea on image {0} {1} {2} {3}", t.TagCoordinates.StartX, t.TagCoordinates.StartY, t.TagCoordinates.Width, t.TagCoordinates.Height);
+						this.QueueDrawArea (t.TagCoordinates.StartX, t.TagCoordinates.StartY, t.TagCoordinates.Width, t.TagCoordinates.Height);
+					}
+				}
+
 			if (PhotoChanged != null)
 				PhotoChanged (this);
 		}
Index: src/TagStore.cs
===================================================================
--- src/TagStore.cs	(revisione 3522)
+++ src/TagStore.cs	(copia locale)
@@ -152,7 +152,16 @@
 		}	
 	}
 
+	//Coords
+	private TagCoordinates tag_coords;
+	public TagCoordinates TagCoordinates {
+		set {
+			tag_coords = value;
+		}
+		get { return tag_coords; }
+	}
 
+
 	// You are not supposed to invoke these constructors outside of the TagStore class.
 	public Tag (Category category, uint id, string name)
 		: base (id)
@@ -188,7 +197,36 @@
 	}
 }
 
+// Tag coordinates over the image
+public class TagCoordinates {
+	int start_x;
+	int start_y;
+	int width;
+	int height;
 
+	public TagCoordinates (int x, int y, int xl, int yl)
+	{
+		this.start_x = x;
+		this.start_y = y;
+		this.width = xl;
+		this.height = yl;
+
+	}
+
+	public int StartX { 
+		get { return start_x; }
+	}
+	public int StartY { 
+		get { return start_y; }
+	}
+	public int Width { 
+		get { return width; }
+	}
+	public int Height { 
+		get { return height; }
+	}
+}
+
 // A Category is a Tag which has contains sub-Tags (we use the same terminology as Photoshop Album).
 public class Category : Tag {
 	ArrayList children;
Index: src/PhotoStore.cs
===================================================================
--- src/PhotoStore.cs	(revisione 3522)
+++ src/PhotoStore.cs	(copia locale)
@@ -791,7 +791,11 @@
 		Database.ExecuteNonQuery (
 			"CREATE TABLE photo_tags (     " +
 			"	photo_id      INTEGER, " +
-			"       tag_id        INTEGER  " +
+			"       tag_id        INTEGER, " +
+			"       start_x       INTEGER, " +
+			"       start_y       INTEGER, " +
+			"       width         INTEGER, " +
+			"       height        INTEGER  " +
 			")");
 
 
@@ -868,11 +872,18 @@
 
 	private void GetTags (Photo photo)
 	{
-		SqliteDataReader reader = Database.Query(new DbCommand("SELECT tag_id FROM photo_tags WHERE photo_id = :id", "id", photo.Id));
+		SqliteDataReader reader = Database.Query(new DbCommand("SELECT tag_id, start_x, start_y, width, height FROM photo_tags WHERE photo_id = :id", "id", photo.Id));
 
 		while (reader.Read ()) {
 			uint tag_id = Convert.ToUInt32 (reader [0]);
+			TagCoordinates tc = new TagCoordinates (0, 0, 0, 0);
+			int start_x = Convert.ToInt32 (reader [1]);
+			int start_y = Convert.ToInt32 (reader [2]);
+			int width = Convert.ToInt32 (reader [3]);
+			int height = Convert.ToInt32 (reader [4]);
+			tc = new TagCoordinates (start_x, start_y, width, height);
 			Tag tag = Core.Database.Tags.Get (tag_id) as Tag;
+			tag.TagCoordinates = tc;
 			photo.AddTagUnsafely (tag);
 		}
 		reader.Close();
@@ -914,10 +925,16 @@
 	}
 
 	private void GetAllTags () {
-		SqliteDataReader reader = Database.Query("SELECT photo_id, tag_id FROM photo_tags");
+		SqliteDataReader reader = Database.Query("SELECT photo_id, tag_id, start_x, start_y, width, height FROM photo_tags");
 
 		while (reader.Read ()) {
 			uint id = Convert.ToUInt32 (reader [0]);
+			TagCoordinates tc = new TagCoordinates (0, 0, 0, 0);
+			int start_x = Convert.ToInt32 (reader [2]);
+			int start_y = Convert.ToInt32 (reader [3]);
+			int width = Convert.ToInt32 (reader [4]);
+			int height = Convert.ToInt32 (reader [5]);
+			tc = new TagCoordinates (start_x, start_y, width, height);
 			Photo photo = LookupInCache (id) as Photo;
 				
 			if (photo == null) {
@@ -933,6 +950,7 @@
 		        if (reader [1] != null) {
 				uint tag_id = Convert.ToUInt32 (reader [1]);
 				Tag tag = Core.Database.Tags.Get (tag_id) as Tag;
+				tag.TagCoordinates = tc;
 				photo.AddTagUnsafely (tag);
 			}
 		}
@@ -1113,9 +1131,13 @@
 		Database.ExecuteNonQuery (new DbCommand ("DELETE FROM photo_tags WHERE photo_id = :id", "id", photo.Id));
 
 		foreach (Tag tag in photo.Tags) {
-			Database.ExecuteNonQuery (new DbCommand ("INSERT INTO photo_tags (photo_id, tag_id) " +
-                                         " VALUES (:photo_id, :tag_id)",
-                                         "photo_id", photo.Id, "tag_id", tag.Id));
+			Database.ExecuteNonQuery (new DbCommand ("INSERT INTO photo_tags (photo_id, tag_id, start_x, start_y, width, height) " +
+                                         " VALUES (:photo_id, :tag_id, :start_x, :start_y, :width, :height)",
+                                         "photo_id", photo.Id, "tag_id", tag.Id, 
+					 "start_x", tag.TagCoordinates.StartX,
+					 "start_y", tag.TagCoordinates.StartY,
+					 "width", tag.TagCoordinates.Width,
+					 "height", tag.TagCoordinates.Height));
 		}
 
 		// Update versions.
Index: src/Updater.cs
===================================================================
--- src/Updater.cs	(revisione 3522)
+++ src/Updater.cs	(copia locale)
@@ -210,7 +210,26 @@
  					"FROM  {0} ", tmp_photos));
  			}, false);
  
-			// Update to version 11.0
+ 			// Update to version 11.0, make id autoincrement
+ 			AddUpdate (new Version (11,0),delegate () {
+ 				string tmp_photo_tags = MoveTableToTemp ("photo_tags");
+ 				ExecuteNonQuery (
+					"CREATE TABLE photo_tags (     " +
+					"	photo_id      INTEGER, " +
+					"       tag_id        INTEGER, " +
+					"       start_x       INTEGER, " +
+					"       start_y       INTEGER, " +
+					"       width         INTEGER, " +
+					"       height        INTEGER  " +
+ 					")");
+ 
+ 				ExecuteNonQuery (String.Format (
+ 					"INSERT INTO photo_tags (photo_id, tag_id) " +
+ 					"SELECT photo_id, tag_id  " + 
+ 					"FROM  {0} ", tmp_photo_tags));
+ 			}, false);
+ 
+			// Update to version 12.0
 			//AddUpdate (new Version (0,0),delegate () {
 			//	do update here
 			//});
Index: src/PhotoView.cs
===================================================================
--- src/PhotoView.cs	(revisione 3522)
+++ src/PhotoView.cs	(copia locale)
@@ -3,6 +3,7 @@
 using Gtk;
 using GtkSharp;
 using System;
+using System.Collections;
 using Mono.Unix;
 using FSpot.Xmp;
 
@@ -26,6 +27,7 @@
 	private Gtk.ToolButton color_button;	
 	private Gtk.ToolButton desaturate_button;
 	private Gtk.ToolButton sepia_button;
+	private Gtk.ToolButton areatag_button;
 
 	private OptionMenu constraints_option_menu;
 	private int selection_constraint_ratio_idx;
@@ -33,6 +35,11 @@
 
 	private System.Collections.Hashtable constraint_table = new System.Collections.Hashtable ();
 
+	// Editor types
+	private enum ProcessType {
+		Crop,
+		RedEye
+	};
 	// Public events.
 
 	public delegate void PhotoChangedHandler (PhotoView me);
@@ -150,9 +157,11 @@
 		if (valid && has_selection) {
 			crop_button.SetTooltip (tips, Catalog.GetString ("Crop photo to selected area"), String.Empty);
 			redeye_button.SetTooltip (tips, Catalog.GetString ("Remove redeye from selected area"), String.Empty);
+			areatag_button.SetTooltip (tips, Catalog.GetString ("Attach a tag to the selected area"), String.Empty);
 		} else {
 			crop_button.SetTooltip (tips, Catalog.GetString ("Select an area to crop"), null);
 			redeye_button.SetTooltip (tips, Catalog.GetString ("Select an area to remove redeye"), null);
+			areatag_button.SetTooltip (tips, Catalog.GetString ("Select an area to attach a tag"), String.Empty);
 		}
 		
 		crop_button.Sensitive = valid;
@@ -160,6 +169,7 @@
 		color_button.Sensitive = valid;
 		desaturate_button.Sensitive = valid;
 		sepia_button.Sensitive = valid;
+		areatag_button.Sensitive = valid;
 	}
 
 	private void UpdateCountLabel ()
@@ -248,14 +258,72 @@
 
 	private void HandleRedEyeButtonClicked (object sender, EventArgs args)
 	{
-		ProcessImage (true);
+		ProcessImage (ProcessType.RedEye);
 	}
 	
 	private void HandleCropButtonClicked (object sender, EventArgs args)
 	{
-		ProcessImage (false);
+		ProcessImage (ProcessType.Crop);
 	}
 
+	private void HandleAreaTagButtonClicked (object sender, EventArgs args)
+	{
+		if (!Item.IsValid)
+			return;
+			
+		//Same used in ProcessImage. Should be perhaps unified
+		int x, y, width, height;
+		if (! photo_view.GetSelection (out x, out y, out width, out height)) {
+			string msg = Catalog.GetString ("No selection available");
+			string desc = Catalog.GetString ("This tool requires an active selection. Please select a region of the photo and try the operation again");
+			
+			HigMessageDialog md = new HigMessageDialog ((Gtk.Window)this.Toplevel, DialogFlags.DestroyWithParent, 
+								    Gtk.MessageType.Error, ButtonsType.Ok, 
+								    msg,
+								    desc);
+
+			md.Run ();
+			md.Destroy ();
+			return;
+		}		
+
+		//Create a dialog for tag entering
+		Dialog atdialog = new Dialog ();
+		atdialog.Modal = true;
+		Gtk.Label label1 = new Gtk.Label (Catalog.GetString ("Attach tag"));
+		Gtk.OptionMenu category_option_menu;
+
+		HBox hbox = new HBox (false, 12);
+		hbox.PackStart (label1, false, false, 0);
+
+		FSpot.Widgets.TagEntry miniatures_tags;
+		miniatures_tags = new FSpot.Widgets.TagEntry (MainWindow.Toplevel.Database.Tags, false);
+		miniatures_tags.UpdateFromTagNames (new string []{});
+		hbox.PackStart (miniatures_tags, false, false, 0);
+		atdialog.VBox.PackStart (hbox, false, false, 12);
+		atdialog.AddButton (Catalog.GetString ("Cancel"), (int) ResponseType.Cancel);
+		atdialog.AddButton (Catalog.GetString ("Attach"), (int) ResponseType.Ok);
+         
+		atdialog.ShowAll ();
+		if (atdialog.Run () == (int)ResponseType.Ok) {
+			ArrayList taglist = new ArrayList();
+			TagCoordinates tc = new TagCoordinates (x, y, width, height);
+			foreach (string tag_name in miniatures_tags.GetTypedTagNames ()) {
+				Tag t = MainWindow.Toplevel.Database.Tags.GetTagByName (tag_name); 
+				if (t != null) {
+					t.TagCoordinates = tc;
+					taglist.Add(t);
+				}
+			}
+			foreach (Tag t in taglist)
+				((Photo)Item.Current).AddTag (t);
+			PhotoQuery pq = query as PhotoQuery;
+			pq.Commit (Item.Index);
+		}
+		atdialog.Destroy ();
+
+	}
+
 	private void ShowError (System.Exception e, Photo photo)
 	{
 		string msg = Catalog.GetString ("Error editing photo");
@@ -306,7 +374,7 @@
 
 	// FIXME this design sucks, I'm just doing it this way while
 	// I redesign the editing system.
-	private void ProcessImage (bool redeye)
+	private void ProcessImage (ProcessType operation)
 	{
 		int x, y, width, height;
 		if (! photo_view.GetSelection (out x, out y, out width, out height)) {
@@ -330,18 +398,21 @@
 				return;
 			}
 			
-			Pixbuf edited;
-			if (redeye) {
+			Pixbuf edited = null;
+			switch (operation) {
+			case ProcessType.RedEye: 
 				Gdk.Rectangle area = new Gdk.Rectangle (x, y, width, height);
 				edited = PixbufUtils.RemoveRedeye (original_pixbuf, 
 								   area,
 								   (int) Preferences.Get (Preferences.EDIT_REDEYE_THRESHOLD));
-			} else { // Crop (I told you it was ugly)
+				break; 
+			case ProcessType.Crop:
 				edited = new Pixbuf (original_pixbuf.Colorspace, 
 						     original_pixbuf.HasAlpha, original_pixbuf.BitsPerSample,
 						     width, height);
 				
 				original_pixbuf.CopyArea (x, y, width, height, edited, 0, 0);
+				break;
 			}
 			
 			bool create_version = photo.DefaultVersion.IsProtected;
@@ -525,6 +596,10 @@
 		autocolor_btn.SetTooltip (tips, autocolor.Tooltip, String.Empty);
 		toolbar.Insert (autocolor_btn, -1);
 
+		areatag_button = GtkUtil.ToolButtonFromTheme ("areatag", Catalog.GetString ("Area tag"), false);
+		toolbar.Insert (areatag_button, -1);
+		areatag_button.Clicked += new EventHandler (HandleAreaTagButtonClicked);
+
 		SeparatorToolItem white_space = new SeparatorToolItem ();
 		white_space.Draw = false;
 		white_space.Expand = true;
Index: ChangeLog
===================================================================
--- ChangeLog	(revisione 3522)
+++ ChangeLog	(copia locale)
@@ -1,3 +1,11 @@
+2008-01-02  Lorenzo Milesi <maxxer@yetopen.it>
+
+	* src/PhotoImageView.cs:
+	* src/TagStore.cs:
+	* src/PhotoStore.cs:
+	* src/Updater.cs:
+	* src/PhotoView.cs: tag image area, facebook like. Fix bgo#324391.
+
 2007-12-21  Stephane Delcroix  <sdelcroix@novell.com>
 
 	* Updater.cs: use the return value of MoveTableToTemp, drop
