banshee r3140 - in trunk/banshee: . src/Core/Banshee.Services/Banshee.Playlist src/Core/Banshee.Services/Banshee.Sources src/Core/Banshee.ThickClient/Banshee.Collection.Gui src/Core/Banshee.ThickClient/Banshee.Gui.DragDrop src/Core/Banshee.ThickClient/Banshee.Sources.Gui src/Core/Hyena.Gui/Hyena.Data.Gui



Author: abock
Date: Sun Feb  3 20:43:04 2008
New Revision: 3140
URL: http://svn.gnome.org/viewvc/banshee?rev=3140&view=rev

Log:
2008-02-03  Aaron Bockover  <abock gnome org>

    This commit adds Drag and Drop support from the track list to the source
    view; i.e. you can drag tracks to the play queue or playlists

    * src/Core/Banshee.Services/Banshee.Sources/Source.cs:
    * src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs: Added
    and implemented AcceptsInputFromSource and MergeSourceInput methods
    that allows source to see if they are 'compatible' with other sources;
    for instance, copying some tracks from one source to another

    * src/Core/Banshee.ThickClient/Banshee.Collection.Gui/TrackListView.cs:
    Implemented source-mode drag and drop for the track list

    * src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView.cs:
    * src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView_DragAndDrop.cs:
    Implemented dest-mode drag and drop for track contexts (cannot DnD to/from
    source view yet)

    * src/Core/Banshee.ThickClient/Banshee.Gui.DragDrop/DragDropTarget.cs:
    Modernized the drop targets we'll start with for trunk

    * src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceRowRenderer.cs:
    Remove some obsolete properties

    * src/Core/Hyena.Gui/Hyena.Data.Gui/ListView.cs: Started fixing up
    click behavior for selections to work properly with multi-row DnD;
    currently there is still some bad behavior and it needs work - almost
    done though



Modified:
   trunk/banshee/ChangeLog
   trunk/banshee/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/TrackListView.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.DragDrop/DragDropTarget.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceRowRenderer.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView_DragAndDrop.cs
   trunk/banshee/src/Core/Hyena.Gui/Hyena.Data.Gui/ListView.cs

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Playlist/PlaylistSource.cs	Sun Feb  3 20:43:04 2008
@@ -114,6 +114,26 @@
 
 #endregion
 
+#region Source Overrides
+
+        public override bool AcceptsInputFromSource (Source source)
+        {
+            // TODO: Probably should be more restrictive than this
+            return source is DatabaseSource;
+        }
+        
+        public override void MergeSourceInput (Source from, bool selected)
+        {
+            DatabaseSource source = from as DatabaseSource;
+            if (source == null || !(source.TrackModel is TrackListDatabaseModel)) {
+                return;
+            }
+            
+            AddSelectedTracks ((TrackListDatabaseModel)source.TrackModel);
+        }
+
+#endregion
+
 #region AbstractPlaylist overrides
 
         protected override void Update ()
@@ -193,7 +213,7 @@
             ServiceManager.DbConnection.Execute (add_track_command);
             Reload ();
         }*/
-
+        
         public virtual void AddSelectedTracks (TrackListDatabaseModel from)
         {
             if (from == track_model)

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs	Sun Feb  3 20:43:04 2008
@@ -4,7 +4,7 @@
 // Author:
 //   Aaron Bockover <abockover novell com>
 //
-// Copyright (C) 2005-2007 Novell, Inc.
+// Copyright (C) 2005-2008 Novell, Inc.
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -103,6 +103,16 @@
             properties.SetString("Name", newName);
         }
         
+        public virtual bool AcceptsInputFromSource (Source source)
+        {
+            return false;
+        }
+        
+        public virtual void MergeSourceInput (Source source, bool selection)
+        {
+            throw new NotImplementedException ();
+        }
+        
         public void SetParentSource (Source parent)
         {
             this.parent = parent;

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/TrackListView.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/TrackListView.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/TrackListView.cs	Sun Feb  3 20:43:04 2008
@@ -32,6 +32,7 @@
 using Hyena.Data.Gui;
 
 using Banshee.Gui;
+using Banshee.Gui.DragDrop;
 using Banshee.ServiceStack;
 using Banshee.MediaEngine;
 using Banshee.Collection;
@@ -82,6 +83,8 @@
                     QueueDraw ();
                 };
             }
+            
+            ConfigureDragAndDrop ();
         }
 
         protected override bool OnPopupMenu ()
@@ -95,6 +98,32 @@
             QueueDraw ();
         }
         
+#region Drag and Drop
+
+        private static TargetEntry [] dnd_source_entries = new TargetEntry [] {
+            DragDropTarget.ModelSelection
+        };
+
+        private void ConfigureDragAndDrop ()
+        {
+            Gtk.Drag.SourceSet (this, Gdk.ModifierType.Button1Mask | Gdk.ModifierType.Button3Mask, 
+                dnd_source_entries, Gdk.DragAction.Copy | Gdk.DragAction.Move);
+                
+            Drag.SourceSetIconName (this, "audio-x-generic");
+        }
+
+        protected override void OnDragDataGet (Gdk.DragContext context, SelectionData selection_data, uint info, uint time)
+        {
+            byte [] selection_data_raw;
+            DragDropTargetType type = (DragDropTargetType)info;
+            
+            if (type != DragDropTargetType.ModelSelection || Selection.Count <= 0) {
+                return;
+            }
+        }
+
+#endregion
+        
         public ColumnController DefaultColumnController {
             get { return column_controller; }
         }

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.DragDrop/DragDropTarget.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.DragDrop/DragDropTarget.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.DragDrop/DragDropTarget.cs	Sun Feb  3 20:43:04 2008
@@ -33,26 +33,21 @@
 {
     public enum DragDropTargetType {
         Source,
-        PlaylistRows,
-        TrackInfoObjects,
+        ModelSelection,
         UriList
     };
         
     public static class DragDropTarget
     {
         public static readonly TargetEntry Source = 
-            new TargetEntry("application/x-banshee-source", TargetFlags.App, 
+            new TargetEntry ("application/x-banshee-source", TargetFlags.App, 
                 (uint)DragDropTargetType.Source);
 
-        public static readonly TargetEntry PlaylistRows = 
-            new TargetEntry("application/x-banshee-playlist-rows", TargetFlags.App, 
-                (uint)DragDropTargetType.PlaylistRows);
-
-        public static readonly TargetEntry TrackInfoObjects = 
-            new TargetEntry("application/x-banshee-track-info-objects", TargetFlags.App, 
-                (uint)DragDropTargetType.TrackInfoObjects);
+        public static readonly TargetEntry ModelSelection =
+            new TargetEntry ("application/x-banshee-model-selection", TargetFlags.App,
+                (uint)DragDropTargetType.ModelSelection);
 
         public static readonly TargetEntry UriList = 
-            new TargetEntry("text/uri-list", 0, (uint)DragDropTargetType.UriList);
+            new TargetEntry ("text/uri-list", 0, (uint)DragDropTargetType.UriList);
     }
 }

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceRowRenderer.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceRowRenderer.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceRowRenderer.cs	Sun Feb  3 20:43:04 2008
@@ -40,8 +40,6 @@
 {
     internal class SourceRowRenderer : CellRendererText
     {
-        public bool Selected = false;
-        public bool Italicized = false;
         public Source source;
         public SourceView view;
         public TreePath path;
@@ -67,7 +65,7 @@
             x_offset = 0;
             y_offset = 0;
             width = text_w;
-            height = (int)Math.Max (22, text_h) + 1;
+            height = (int)Math.Max (22, text_h) + 5;
         }
         
         protected override void Render (Gdk.Drawable drawable, Widget widget, Gdk.Rectangle background_area, 
@@ -127,7 +125,7 @@
                 ? Pango.Weight.Bold 
                 : Pango.Weight.Normal;
 
-            if (Italicized) {
+            if (source == view.NewPlaylistSource) {
                 fd.Style = Pango.Style.Italic;
                 hide_counts = true;
             }

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView.cs	Sun Feb  3 20:43:04 2008
@@ -30,12 +30,14 @@
 using System.Collections.Generic;
 using Gtk;
 using Cairo;
+using Mono.Unix;
 
 using Hyena.Data.Gui;
 using Hyena.Gui.Theatrics;
 
 using Banshee.ServiceStack;
 using Banshee.Sources;
+using Banshee.Playlist;
 
 using Banshee.Gui;
 
@@ -47,7 +49,7 @@
 
     public partial class SourceView : TreeView
     {
-        //private Source new_playlist_source = new PlaylistSource(-1);
+        private Source new_playlist_source = new PlaylistSource (Catalog.GetString ("New Playlist"));
         private TreeIter new_playlist_iter = TreeIter.Zero;
         private bool new_playlist_visible = false;
         
@@ -336,9 +338,6 @@
                 }
             }
 
-            // delegate (SourceEventArgs e) { AddSource (e.Source, iter); };
-            // delegate (SourceEventArgs e) { RemoveSource(e.Source); };
-            
             source.ChildSourceAdded += OnSourceChildSourceAdded; 
             source.ChildSourceRemoved += OnSourceChildSourceRemoved;
             source.UserNotifyUpdated += OnSourceUserNotifyUpdated;
@@ -462,8 +461,6 @@
                 return;
             }
             
-            renderer.Selected = renderer.source.Equals (ServiceManager.SourceManager.ActiveSource);
-            //renderer.Italicized = renderer.source.Equals (new_playlist_source);
             renderer.Sensitive = renderer.source.CanActivate;
         }
         
@@ -506,7 +503,6 @@
                 
         public Source HighlightedSource {
             get {
-                TreeModel model;
                 TreeIter iter;
                 
                 if (highlight_path == null || !store.GetIter (out iter, highlight_path)) {
@@ -544,6 +540,10 @@
         internal Stage<TreeIter> NotifyStage {
             get { return notify_stage; }
         }
+        
+        internal Source NewPlaylistSource {
+            get { return new_playlist_source; }
+        }
 
 #endregion        
 

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView_DragAndDrop.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView_DragAndDrop.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Sources.Gui/SourceView_DragAndDrop.cs	Sun Feb  3 20:43:04 2008
@@ -32,6 +32,7 @@
 using Gtk;
 using Gdk;
 
+using Banshee.ServiceStack;
 using Banshee.Collection;
 using Banshee.Playlist;
 
@@ -46,11 +47,12 @@
         };
             
         private static TargetEntry [] dnd_dest_entries = new TargetEntry [] {
-            Banshee.Gui.DragDrop.DragDropTarget.TrackInfoObjects,
-            Banshee.Gui.DragDrop.DragDropTarget.Source
+            Banshee.Gui.DragDrop.DragDropTarget.ModelSelection
         };
-    
-            
+        
+        private Source final_drag_source = null;
+        private uint final_drag_start_time = 0;
+        
         private void ConfigureDragAndDrop ()
         {
             EnableModelDragSource (Gdk.ModifierType.Button1Mask | Gdk.ModifierType.Button3Mask,
@@ -59,109 +61,87 @@
             EnableModelDragDest (dnd_dest_entries, DragAction.Copy | DragAction.Move);
         }
         
-        protected override void OnDragBegin (Gdk.DragContext context)
-        {
-            /*if(HighlightedSource.IsDragSource || HighlightedSource is IImportSource) {
-                base.OnDragBegin(context);
-            }*/
-        }
-        
-        protected override void OnDragDataGet (Gdk.DragContext context, SelectionData selectionData,
-            uint info, uint time)
-        {
-            switch ((DragDropTargetType)info) {
-                case DragDropTargetType.Source:
-                    new DragDropList<Source> (HighlightedSource, selectionData, context.Targets[0]);
-                    break;
-                default:
-                    return;
-            }
-            
-            base.OnDragDataGet (context, selectionData, info, time);
-        }
-        
         protected override bool OnDragMotion (Gdk.DragContext context, int x, int y, uint time)
         {
-            /*if(Gtk.Drag.GetSourceWidget(context) == this 
-                && !HighlightedSource.IsDragSource && !(HighlightedSource is IImportSource)) {
-                return false;
-            }
-        
-            base.OnDragMotion(context, x, y, time);
-            SetDragDestRow(null, TreeViewDropPosition.IntoOrAfter);
-            Gdk.Drag.Status(context, Gdk.DragAction.Copy, time);
-
-            // FIXME: We need to handle this nicer
-            if(Gtk.Drag.GetSourceWidget(context) != this && 
-                !(ServiceManager.SourceManager.ActiveSource is LibrarySource ||
-                ServiceManager.SourceManager.ActiveSource is PlaylistSource ||
-                ServiceManager.SourceManager.ActiveSource is Banshee.SmartPlaylist.SmartPlaylistSource ||
-                ServiceManager.SourceManager.ActiveSource is IImportable)) {
-                return false;
-            }
-        
-            if(!new_playlist_visible && Gtk.Drag.GetSourceWidget(context) != this) {
-                TreeIter library = FindSource(LibrarySource.Instance);
-                new_playlist_iter = store.AppendNode(library);
-                store.SetValue(new_playlist_iter, 0, new_playlist_source);
-                store.SetValue(new_playlist_iter, 1, 999);
+            base.OnDragMotion (context, x, y, time);
+            SetDragDestRow (null, TreeViewDropPosition.IntoOrAfter);
+            Gdk.Drag.Status (context, Gdk.DragAction.Copy, time);
+        
+            if (!new_playlist_visible && Gtk.Drag.GetSourceWidget (context) != this) {
+                TreeIter library = FindSource (ServiceManager.SourceManager.DefaultSource);
+                new_playlist_iter = store.AppendNode (library);
+                store.SetValue (new_playlist_iter, 0, new_playlist_source);
+                store.SetValue (new_playlist_iter, 1, 999);
                 new_playlist_visible = true;
 
-                UpdateView();
-                Expand(library);
+                UpdateView ();
+                Expand (library);
             }
         
             TreePath path;
             TreeViewDropPosition pos;
             
-            if(GetDestRowAtPos(x, y, out path, out pos)) {
-                Source source = GetSource(path);
-                
-                if(source == ServiceManager.SourceManager.ActiveSource) {
-                    return false;
-                }
-                
-                SetDragDestRow(path, TreeViewDropPosition.IntoOrAfter);
-                
-                if((source is LibrarySource && (ServiceManager.SourceManager.ActiveSource is IImportable 
-                    || ServiceManager.SourceManager.ActiveSource is IImportSource)) ||
-                    (source is PlaylistSource) || (source is DapSource) || source.AcceptsInput) {
-                    return true;
-                }
-
-                Gdk.Drag.Status(context, 0, time);
+            if (!GetDestRowAtPos (x, y, out path, out pos)) {
+                Gdk.Drag.Status (context, 0, time);
                 return true;
-            }*/
+            }
             
+            Source drop_source = GetSource (path);
+            Source active_source = ServiceManager.SourceManager.ActiveSource;
+
+            if (drop_source == null || drop_source == active_source 
+                || !drop_source.AcceptsInputFromSource (active_source)) {
+                return false;
+            }
+
+            SetDragDestRow (path, TreeViewDropPosition.IntoOrAfter);
             return true;
         }
         
-        private Source final_drag_source = null;
-        private uint final_drag_start_time = 0;
-    
         protected override void OnDragLeave (Gdk.DragContext context, uint time)
         {
-            /*TreePath path;
+            TreePath path;
             TreeViewDropPosition pos;
             GetDragDestRow (out path, out pos);
 
-            if(path == null) {
-                path = store.GetPath(new_playlist_iter);
+            if (path == null) {
+                path = store.GetPath (new_playlist_iter);
             }
             
             final_drag_source = GetSource (path);
             final_drag_start_time = context.StartTime;
         
-            if(new_playlist_visible) {
-                store.Remove(ref new_playlist_iter);
+            if (new_playlist_visible) {
+                store.Remove (ref new_playlist_iter);
                 new_playlist_visible = false;
-                UpdateView();
-            }*/
+                UpdateView ();
+            }
         }
 
         protected override void OnDragDataReceived (Gdk.DragContext context, int x, int y,
             Gtk.SelectionData selectionData, uint info, uint time)
         {
+            if (final_drag_start_time == context.StartTime && final_drag_source != null) {
+                Source drop_source = final_drag_source;
+                
+                if (final_drag_source == new_playlist_source) {
+                    PlaylistSource playlist = new PlaylistSource ("New Playlist");
+                    playlist.Save ();
+                    ServiceManager.SourceManager.DefaultSource.AddChildSource (playlist);
+                    drop_source = playlist;
+                }
+                
+                drop_source.MergeSourceInput (ServiceManager.SourceManager.ActiveSource, true);
+            }
+            
+            if (new_playlist_visible) {
+                store.Remove (ref new_playlist_iter);
+                new_playlist_visible = false;
+                UpdateView ();
+            }
+        
+            Gtk.Drag.Finish (context, true, false, time);
+            
             /*if(Gtk.Drag.GetSourceWidget(context) == this) {
                 DragDropList<Source> sources = selectionData;
                 if(sources.Count <= 0) { 
@@ -182,63 +162,28 @@
                 }
                 
                 return;
+            }*/
+        }
+                
+        /*protected override void OnDragBegin (Gdk.DragContext context)
+        {
+            if (HighlightedSource.IsDragSource || HighlightedSource is IImportSource) {
+                base.OnDragBegin (context);
             }
-            
-            if(final_drag_start_time == context.StartTime) {
-                PlaylistSource playlist_remove_on_failure = null;
-                try {
-                    DragDropList<TrackInfo> dnd_transfer = selectionData;
-                    TrackDropOperation(final_drag_source, dnd_transfer, out playlist_remove_on_failure);
-                } catch(Exception e) {
-                    if(playlist_remove_on_failure != null) {
-                        playlist_remove_on_failure.Unmap();
-                        playlist_remove_on_failure = null;
-                    }
-                    
-                    LogCore.Instance.PushError(Catalog.GetString("Could not import tracks"), e.Message);
-                }
-            }
-            
-            if(new_playlist_visible) {
-                store.Remove(ref new_playlist_iter);
-                new_playlist_visible = false;
-                UpdateView();
-            }
-        
-            Gtk.Drag.Finish(context, true, false, time);*/
         }
         
-        private void TrackDropOperation (Source source, IList<TrackInfo> tracks, out PlaylistSource newPlaylist)
+        protected override void OnDragDataGet (Gdk.DragContext context, SelectionData selectionData,
+            uint info, uint time)
         {
-            newPlaylist = null;
+            switch ((DragDropTargetType)info) {
+                case DragDropTargetType.Source:
+                    new DragDropList<Source> (HighlightedSource, selectionData, context.Targets[0]);
+                    break;
+                default:
+                    return;
+            }
             
-            /*if(source is LibrarySource && ServiceManager.SourceManager.ActiveSource is IImportable) {
-                IImportable import_source = ServiceManager.SourceManager.ActiveSource as IImportable;
-                import_source.Import(tracks);
-            } else if(source is PlaylistSource && ServiceManager.SourceManager.ActiveSource is IImportable) {
-                IImportable import_source = ServiceManager.SourceManager.ActiveSource as IImportable;
-                PlaylistSource playlist = null;
-                    
-                if(source == new_playlist_source) {
-                    playlist = new PlaylistSource();
-                    LibrarySource.Instance.AddChildSource(playlist);
-                    newPlaylist = playlist;
-                } else {
-                    playlist = source as PlaylistSource;
-                }
-                    
-                import_source.Import(tracks, playlist);
-            } else if(source == new_playlist_source) {
-                PlaylistSource playlist = new PlaylistSource();
-                playlist.AddTrack(tracks);
-                playlist.Rename(PlaylistUtil.GoodUniqueName(playlist.Tracks));
-                playlist.Commit();
-                LibrarySource.Instance.AddChildSource(playlist);
-                UpdateView();
-            } else if(source is PlaylistSource || source is DapSource || source.AcceptsInput) {
-                source.AddTrack(tracks);
-                source.Commit();
-            }*/
-        }
+            base.OnDragDataGet (context, selectionData, info, time);
+        }*/
     }
 }

Modified: trunk/banshee/src/Core/Hyena.Gui/Hyena.Data.Gui/ListView.cs
==============================================================================
--- trunk/banshee/src/Core/Hyena.Gui/Hyena.Data.Gui/ListView.cs	(original)
+++ trunk/banshee/src/Core/Hyena.Gui/Hyena.Data.Gui/ListView.cs	Sun Feb  3 20:43:04 2008
@@ -606,6 +606,7 @@
         }
         
         private int last_click_row_index = -1;
+        
         protected override bool OnButtonPressEvent(Gdk.EventButton press)
         {
             HasFocus = true;
@@ -617,8 +618,13 @@
                 }
             } else if (press.Window == list_window && model != null) {
                 GrabFocus ();
-                    
+                
                 int row_index = GetRowAtY ((int) press.Y);
+                
+                if (Selection.Count > 1 && Selection.Contains (row_index)) {
+                    return true;
+                }
+                
                 object item = model[row_index];
                 if (item == null) {
                     return true;
@@ -668,6 +674,7 @@
         
         protected override bool OnButtonReleaseEvent(Gdk.EventButton evnt)
         {
+           // Console.WriteLine 
             if(evnt.Window == header_window) {
                 if(resizing_column_index >= 0) {
                     resizing_column_index = -1;
@@ -681,7 +688,23 @@
                     Model.Reload();
                     InvalidateHeaderWindow();
                 }
+            } else if (evnt.Window == list_window && model != null && evnt.State == Gdk.ModifierType.None) {
+                GrabFocus ();
+                
+                int row_index = GetRowAtY ((int)evnt.Y);
+                object item = model[row_index];
+                if (item == null) {
+                    return true;
+                }
+                
+                if (Selection.Count > 1 && Selection.Contains (row_index)) {
+                    Selection.Clear(false);
+                    Selection.Select(row_index);
+                    FocusRow (row_index);
+                    return true;
+                }
             }
+
             
             return true;
         }



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