[longomatch] Closes #603274: Enable multiple selection of plays



commit e1a4b3658b679bf6cfcf3e54053ebe38f7ffeea8
Author: Andoni Morales Alastruey <ylatuya gmail com>
Date:   Mon Nov 30 00:16:38 2009 +0100

    Closes #603274: Enable multiple selection of plays

 LongoMatch/Gui/TreeView/PlaysTreeView.cs |  147 +++++++++++++++++++++---------
 1 files changed, 105 insertions(+), 42 deletions(-)
---
diff --git a/LongoMatch/Gui/TreeView/PlaysTreeView.cs b/LongoMatch/Gui/TreeView/PlaysTreeView.cs
index 9a25893..d8b7c43 100644
--- a/LongoMatch/Gui/TreeView/PlaysTreeView.cs
+++ b/LongoMatch/Gui/TreeView/PlaysTreeView.cs
@@ -19,6 +19,7 @@
 //
 
 using System;
+using System.Collections.Generic;
 using Gdk;
 using Gtk;
 using Mono.Unix;
@@ -41,26 +42,25 @@ namespace LongoMatch.Gui.Component
 		public event SnapshotSeriesHandler SnapshotSeriesEvent;
 		public event PlayersTaggedHandler PlayersTagged;
 
-		private TreeIter selectedIter;
 		private Menu menu;
 		private MenuItem local;
 		private	MenuItem visitor;
 		private MenuItem noTeam;
 		private MenuItem addPLN;
 		private MenuItem deleteKeyFrame;
+		private MenuItem snapshot;
+		private MenuItem name;
+		private MenuItem players;
+		
 		private Gtk.CellRendererText nameCell;
-		private TreePath path;
 		private Gtk.TreeViewColumn nameColumn;
-		//Using TimeNode as in the tree there are Media and Sections timenodes
-		private TimeNode selectedTimeNode;
 		private Color[] colors;
 		private bool editing;
 
 
-
-
 		public PlaysTreeView() {
-
+			Selection.Mode = SelectionMode.Multiple;
+			Selection.SelectFunction = SelectFunction;
 			this.RowActivated += new RowActivatedHandler(OnTreeviewRowActivated);
 
 			SetMenu();
@@ -70,7 +70,6 @@ namespace LongoMatch.Gui.Component
 			nameColumn = new Gtk.TreeViewColumn();
 			nameColumn.Title = "Name";
 			nameCell = new Gtk.CellRendererText();
-			//nameCell.Editable = true;
 			nameCell.Edited += OnNameCellEdited;
 			Gtk.CellRendererPixbuf miniatureCell = new Gtk.CellRendererPixbuf();
 			nameColumn.PackStart(miniatureCell, true);
@@ -111,16 +110,16 @@ namespace LongoMatch.Gui.Component
 
 			menu = new Menu();
 
-			MenuItem name = new MenuItem(Catalog.GetString("Edit"));
+			name = new MenuItem(Catalog.GetString("Edit"));
 			MenuItem team = new MenuItem(Catalog.GetString("Team Selection"));
 			team.Submenu = teamMenu;
-			MenuItem players = new MenuItem(Catalog.GetString("Tag player"));
+			players = new MenuItem(Catalog.GetString("Tag player"));
 			players.Submenu = playersMenu;
 			MenuItem quit = new MenuItem(Catalog.GetString("Delete"));
 			deleteKeyFrame = new MenuItem(Catalog.GetString("Delete key frame"));
 			addPLN = new MenuItem(Catalog.GetString("Add to playlist"));
 			addPLN.Sensitive=false;
-			MenuItem snapshot = new MenuItem(Catalog.GetString("Export to PGN images"));
+			snapshot = new MenuItem(Catalog.GetString("Export to PGN images"));
 
 			menu.Append(name);
 			menu.Append(team);
@@ -148,7 +147,18 @@ namespace LongoMatch.Gui.Component
 			return int.Parse(path.ToString().Split(':')[0]);
 		}
 
-
+		private TimeNode GetValueFromPath(TreePath path){
+			Gtk.TreeIter iter;
+			Model.GetIter(out iter, path);
+			return (TimeNode)this.Model.GetValue(iter,0);					
+		}	
+		
+		private void MultiSelectMenu (bool enabled){
+			name.Sensitive = !enabled;
+			snapshot.Sensitive = !enabled;
+			players.Sensitive = !enabled;
+		}
+		
 		private void RenderMiniature(Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter)
 		{
 			TimeNode tNode = (TimeNode) model.GetValue(iter, 0);
@@ -166,10 +176,10 @@ namespace LongoMatch.Gui.Component
 		{
 			TimeNode tNode = (TimeNode) model.GetValue(iter, 0);
 
-			//Handle special case in which we replace the test in the cell by the name of the TimeNode
+			//Handle special case in which we replace the text in the cell by the name of the TimeNode
 			//We need to check if we are editing and only change it for the path that's currently beeing edited
 
-			if (editing && selectedIter.Equals(iter))
+			if (editing && Selection.IterIsSelected(iter))
 				(cell as Gtk.CellRendererText).Markup = tNode.Name;
 			else if (tNode is MediaTimeNode) {
 				(cell as Gtk.CellRendererText).BackgroundGdk = colors[GetSectionFromIter(iter)];
@@ -197,6 +207,21 @@ namespace LongoMatch.Gui.Component
 			if (TimeNodeChanged != null)
 				TimeNodeChanged(tNode,args.NewText);
 		}
+		
+		private bool SelectFunction(TreeSelection selection, TreeModel model, TreePath path, bool selected){
+			// Don't allow multiselect for categories
+			if (!selected &&  selection.GetSelectedRows().Length > 0){
+				if (selection.GetSelectedRows().Length == 1){
+					return !(GetValueFromPath(selection.GetSelectedRows()[0]) is SectionsTimeNode);
+				}
+				else{
+					return !(GetValueFromPath(path) is SectionsTimeNode);			
+				}					
+			}
+			// Always unselect
+			else
+				return true;
+		}
 
 		protected virtual void OnTreeviewRowActivated(object o, Gtk.RowActivatedArgs args)
 		{
@@ -209,37 +234,58 @@ namespace LongoMatch.Gui.Component
 		}
 
 		protected override bool OnButtonPressEvent(EventButton evnt)
-		{
-			//Call base class, to allow normal handling,
-			//such as allowing the row to be selected by the right-click:
-			bool returnValue = base.OnButtonPressEvent(evnt);
-
-			//Then do our custom stuff:
+		{			
+			TreePath[] paths = Selection.GetSelectedRows();
+			
 			if ((evnt.Type == EventType.ButtonPress) && (evnt.Button == 3))
 			{
-
-				this.GetPathAtPos((int)evnt.X,(int)evnt.Y,out path);
-				if (path!=null) {
-					this.Model.GetIter(out selectedIter,path);
-					selectedTimeNode = (TimeNode)this.Model.GetValue(selectedIter, 0);
+				// We don't want to unselect the play when several
+				// plays are selected and we clik the right button
+				// For multiedition
+				if (paths.Length <= 1){
+					base.OnButtonPressEvent(evnt);
+					paths = Selection.GetSelectedRows();
+				}
+				
+				Console.WriteLine(paths.Length);
+				if (paths.Length == 1) {
+					TimeNode selectedTimeNode = GetValueFromPath(paths[0]);
 					if (selectedTimeNode is MediaTimeNode) {
 						deleteKeyFrame.Sensitive = (selectedTimeNode as MediaTimeNode).KeyFrameDrawing != null;
+						MultiSelectMenu(false);
 						menu.Popup();
 					}
 					else {
 						nameCell.Editable = true;
-						this.SetCursor(path,  nameColumn, true);
+						this.SetCursor(paths[0],  nameColumn, true);
 					}
 				}
+				else if (paths.Length > 1){
+					MultiSelectMenu(true);
+					menu.Popup();								
+				}
 			}
-			return returnValue;
+			else 
+				base.OnButtonPressEvent(evnt);
+			return true;
 		}
 
 		protected void OnDeleted(object obj, EventArgs args) {
-			if (TimeNodeDeleted != null)
-				TimeNodeDeleted((MediaTimeNode)selectedTimeNode,int.Parse(path.ToString().Split(':')[0]));
+			if (TimeNodeDeleted == null)
+				return;
+			List<MediaTimeNode> list = new List<MediaTimeNode>();
+			TreePath[] paths = Selection.GetSelectedRows();
+			for (int i=0; i<paths.Length; i++){	
+				list.Add((MediaTimeNode)GetValueFromPath(paths[i]));
+			}
+			// When a TimeNode is deleted from the tree the path changes.
+			// We need first to retrieve all the TimeNodes to delete using the 
+			// current path of each one and then send the TimeNodeDeleted event
+			for (int i=0; i<paths.Length; i++){	
+				TimeNodeDeleted(list[i], int.Parse(paths[i].ToString().Split(':')[0]));
+			}			
 		}
-
+		
 		protected void OnDeleteKeyFrame(object obj, EventArgs args) {
 			MessageDialog md = new MessageDialog((Gtk.Window)Toplevel,
 			                                     DialogFlags.Modal,
@@ -248,17 +294,24 @@ namespace LongoMatch.Gui.Component
 			                                     false,
 			                                     Catalog.GetString("Do you want to delete the key frame for this play?")
 			                                    );
-			if (md.Run() == (int)ResponseType.Yes)
-				//TODO also refresh the thumbnail
-				(selectedTimeNode as MediaTimeNode).KeyFrameDrawing = null;
+			if (md.Run() == (int)ResponseType.Yes){
+				TreePath[] paths = Selection.GetSelectedRows();
+				for (int i=0; i<paths.Length; i++){	
+					MediaTimeNode tNode = (MediaTimeNode)GetValueFromPath(paths[i]);
+					tNode.KeyFrameDrawing = null;
+				}
+				// Refresh the thumbnails
+				QueueDraw();
+			}
 			md.Destroy();
 		}
 
 		protected virtual void OnEdit(object obj, EventArgs args) {
+			TreePath[] paths = Selection.GetSelectedRows();
 			editing = true;
 			nameCell.Editable = true;
-			nameCell.Markup = selectedTimeNode.Name;
-			SetCursor(path,  nameColumn, true);
+			nameCell.Markup = GetValueFromPath(paths[0]).Name;
+			SetCursor(paths[0],  nameColumn, true);
 		}
 
 		protected void OnTeamSelection(object obj, EventArgs args) {
@@ -270,28 +323,38 @@ namespace LongoMatch.Gui.Component
 				team = Team.VISITOR;
 			else if (sender == noTeam)
 				team = Team.NONE;
-			((MediaTimeNode)selectedTimeNode).Team= team;
-
+			
+			TreePath[] paths = Selection.GetSelectedRows();
+			for (int i=0; i<paths.Length; i++){	
+					MediaTimeNode tNode = (MediaTimeNode)GetValueFromPath(paths[i]);
+					tNode.Team = team;
+			}
 		}
 
 		protected void OnAdded(object obj, EventArgs args) {
-			if (PlayListNodeAdded != null)
-				PlayListNodeAdded((MediaTimeNode)selectedTimeNode);
+			if (PlayListNodeAdded != null){
+				TreePath[] paths = Selection.GetSelectedRows();
+				for (int i=0; i<paths.Length; i++){	
+					MediaTimeNode tNode = (MediaTimeNode)GetValueFromPath(paths[i]);
+					PlayListNodeAdded(tNode);
+				}
+			}
 		}
 
 		protected void OnSnapshot(object obj, EventArgs args) {
 			if (SnapshotSeriesEvent != null)
-				SnapshotSeriesEvent((MediaTimeNode)selectedTimeNode);
+				SnapshotSeriesEvent((MediaTimeNode)GetValueFromPath(Selection.GetSelectedRows()[0]));
 		}
 
 		protected virtual void OnLocalPlayers(object o, EventArgs args) {
 			if (PlayersTagged != null)
-				PlayersTagged((MediaTimeNode)selectedTimeNode, Team.LOCAL);
+				PlayersTagged((MediaTimeNode)GetValueFromPath(Selection.GetSelectedRows()[0]), Team.LOCAL);
 		}
 
 		protected virtual void OnVisitorPlayers(object o, EventArgs args) {
 			if (PlayersTagged != null)
-				PlayersTagged((MediaTimeNode)selectedTimeNode, Team.VISITOR);
+				PlayersTagged((MediaTimeNode)GetValueFromPath(Selection.GetSelectedRows()[0]), Team.VISITOR);
 		}
+		
 	}
 }
\ No newline at end of file



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]