Index: src/Common/DelftTools.Controls.Swf/TreeViewControls/TreeView.cs =================================================================== diff -u -r5fc71a385897af92ccb092f2f969b5709afab85a -rd8e4bf47a1ff5b13a9d9e6eaf60b9ca9cd7c7555 --- src/Common/DelftTools.Controls.Swf/TreeViewControls/TreeView.cs (.../TreeView.cs) (revision 5fc71a385897af92ccb092f2f969b5709afab85a) +++ src/Common/DelftTools.Controls.Swf/TreeViewControls/TreeView.cs (.../TreeView.cs) (revision d8e4bf47a1ff5b13a9d9e6eaf60b9ca9cd7c7555) @@ -29,7 +29,7 @@ private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private readonly TreeNodeList nodes; - internal bool isUpdateSuspended; + private bool isUpdateSuspended; private TreeViewController controller; private int dropAtLocation; private Point lastDragOverPoint; @@ -200,16 +200,6 @@ return controller.CanRenameNode(SelectedNode); } - public void EnableDataEventListeners() - { - controller.EnableDataEventListeners(); - } - - public void DisableDataEventListeners() - { - controller.DisableDataEventListeners(); - } - public new void CollapseAll() { foreach (var node in Nodes) @@ -442,15 +432,6 @@ controller.OnTreeViewHandleCreated(); } - protected override void OnHandleDestroyed(EventArgs e) - { - if (controller != null) - { - controller.OnTreeViewHandleDestroyed(); - } - base.OnHandleDestroyed(e); - } - /// /// Custom drawing. /// @@ -473,8 +454,6 @@ { if (disposing && controller != null) { - controller.OnTreeViewHandleDestroyed(); - controller.Dispose(); controller = null; } @@ -789,10 +768,8 @@ if (node.IsOnCheckBox(point)) { - DisableDataEventListeners(); node.Checked = !node.Checked; - EnableDataEventListeners(); - } + } if (node.IsOnExpandButton(point)) { Index: src/Common/DelftTools.Controls.Swf/TreeViewControls/TreeViewController.cs =================================================================== diff -u -r0e4ad7f336db012434ae38027a3e3dacf1398358 -rd8e4bf47a1ff5b13a9d9e6eaf60b9ca9cd7c7555 --- src/Common/DelftTools.Controls.Swf/TreeViewControls/TreeViewController.cs (.../TreeViewController.cs) (revision 0e4ad7f336db012434ae38027a3e3dacf1398358) +++ src/Common/DelftTools.Controls.Swf/TreeViewControls/TreeViewController.cs (.../TreeViewController.cs) (revision d8e4bf47a1ff5b13a9d9e6eaf60b9ca9cd7c7555) @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.Linq; using System.Windows.Forms; using DelftTools.Utils.Collections; @@ -9,21 +8,13 @@ namespace DelftTools.Controls.Swf.TreeViewControls { - public class TreeViewController : IDisposable + public class TreeViewController { - public static bool SkipEvents; // for debugging purposes, find a better way (see usage) private static readonly ILog Log = LogManager.GetLogger(typeof(TreeViewController)); private readonly ITreeView treeView; private readonly IEventedList nodePresenters = new EventedList(); - // use timer in order to combine property and collection change - // note that timer is active only when there is a full refresh taking place - private readonly Timer fullRefreshTimer = new Timer - { - Interval = 250 - }; - private readonly Dictionary nodeTagTypePresenters = new Dictionary(); private object data; @@ -42,13 +33,6 @@ this.treeView = treeView; nodePresenters.CollectionChanged += NodePresentersCollectionChanged; - - // for a time being we use timer here to perform full refresh to avoid double refresh - fullRefreshTimer.Tick += (sender, args) => - { - fullRefreshTimer.Stop(); - treeView.Refresh(); - }; } /// @@ -73,11 +57,6 @@ } set { - if (data != null) - { - DisableDataEventListeners(); - } - treeView.Nodes.Clear(); data = value; @@ -87,15 +66,14 @@ } CreateRootNode(); - EnableDataEventListeners(); treeView.SelectedNode = treeView.Nodes.Count > 0 ? treeView.Nodes[0] : null; } } public void WaitUntilAllEventsAreProcessed() { - while (treeView.IsUpdateSuspended || (treeView.Visible && fullRefreshTimer.Enabled)) + while (treeView.IsUpdateSuspended || treeView.Visible) { Application.DoEvents(); } @@ -345,60 +323,6 @@ treeView.Refresh(); // Ensure the treeview is always up to date after creating handle (data is set and might be changed before enabling the delayed event handlers) } - public void OnTreeViewHandleDestroyed() - { - fullRefreshTimer.Stop(); - } - - #region Implementation of IDisposable - - public void Dispose() - { - DisableDataEventListeners(); - } - - #endregion - - internal void EnableDataEventListeners() - { - var notifyPropertyChanged = data as INotifyPropertyChanged; - if (notifyPropertyChanged != null) - { - (notifyPropertyChanged).PropertyChanged += DataPropertyChanged; - } - - var notifyCollectionChange = data as INotifyCollectionChange; - if (notifyCollectionChange != null) - { - (notifyCollectionChange).CollectionChanged += DataCollectionChanged; - } - } - - internal void DisableDataEventListeners() - { - var notifyPropertyChanged = data as INotifyPropertyChanged; - if (notifyPropertyChanged != null) - { - (notifyPropertyChanged).PropertyChanged -= DataPropertyChanged; - } - - var notifyCollectionChange = data as INotifyCollectionChange; - if (notifyCollectionChange != null) - { - (notifyCollectionChange).CollectionChanged -= DataCollectionChanged; - } - } - - private void FullRefreshEventHandler(object sender, EventArgs eventArgs) - { - if (fullRefreshTimer.Enabled) - { - fullRefreshTimer.Stop(); // Reset timer when already started before - } - - fullRefreshTimer.Start(); // schedule full refresh - } - private IEnumerable GetAllLoadedChildNodes(ITreeNode node, string[] forceNodeLoad = null) { if (!node.IsLoaded && (forceNodeLoad == null || !forceNodeLoad.Contains(node.FullPath))) @@ -472,56 +396,6 @@ return nodePresenterFunction(nodePresenter); } - private void DataCollectionChanged(object sender, NotifyCollectionChangingEventArgs e) - { - if (SkipEvents) - { - return; - } - - DataCollectionChangedSynchronized(sender, e); - - FullRefreshEventHandler(sender, e); - } - - private void DataCollectionChangedSynchronized(object sender, NotifyCollectionChangingEventArgs e) - { - var nodePresenter = ResolveNodePresenterForData(e.Item); - if (nodePresenter == null) - { - return; - } - - nodePresenter.OnCollectionChanged(sender, e); - } - - private void DataPropertyChanged(object sender, PropertyChangedEventArgs e) - { - if (SkipEvents) - { - return; - } - - var nodePresenter = ResolveNodePresenterForData(sender); - - if (nodePresenter == null) - { - return; - } - var node = treeView.GetNodeByTag(sender); - - // HACK: bug in WaterFlowModel1DBoundaryDataNodeDataNodePresenter, in some cases event somes with a sender which is child of actual node.Tag object - find out how to fix it - var actualSender = sender; - if (node != null && sender != node.Tag) - { - actualSender = node.Tag; - } - - nodePresenter.OnPropertyChanged(actualSender, node, e); - - FullRefreshEventHandler(sender, e); - } - private void CreateRootNode() { var rootNode = new TreeNode(treeView) Index: src/DeltaShell/DeltaShell.Plugins.ProjectExplorer/ProjectExplorer.cs =================================================================== diff -u -rfa9b36343401d44cb6813d7871903782d0dedec9 -rd8e4bf47a1ff5b13a9d9e6eaf60b9ca9cd7c7555 --- src/DeltaShell/DeltaShell.Plugins.ProjectExplorer/ProjectExplorer.cs (.../ProjectExplorer.cs) (revision fa9b36343401d44cb6813d7871903782d0dedec9) +++ src/DeltaShell/DeltaShell.Plugins.ProjectExplorer/ProjectExplorer.cs (.../ProjectExplorer.cs) (revision d8e4bf47a1ff5b13a9d9e6eaf60b9ca9cd7c7555) @@ -60,16 +60,6 @@ public Image Image { get; set; } public ViewInfo ViewInfo { get; set; } - public void EndWaitMode() - { - ProjectTreeView.EnableEvents(); - } - - public void BeginWaitMode() - { - ProjectTreeView.DisableEvents(); - } - public new void Dispose() { ProjectTreeView.Data = null; Index: src/DeltaShell/DeltaShell.Plugins.ProjectExplorer/ProjectExplorerGuiPlugin.cs =================================================================== diff -u -rfa9b36343401d44cb6813d7871903782d0dedec9 -rd8e4bf47a1ff5b13a9d9e6eaf60b9ca9cd7c7555 --- src/DeltaShell/DeltaShell.Plugins.ProjectExplorer/ProjectExplorerGuiPlugin.cs (.../ProjectExplorerGuiPlugin.cs) (revision fa9b36343401d44cb6813d7871903782d0dedec9) +++ src/DeltaShell/DeltaShell.Plugins.ProjectExplorer/ProjectExplorerGuiPlugin.cs (.../ProjectExplorerGuiPlugin.cs) (revision d8e4bf47a1ff5b13a9d9e6eaf60b9ca9cd7c7555) @@ -157,12 +157,12 @@ private void ApplicationProjectSaved(Project project) { - ProjectExplorer.EndWaitMode(); + // Place for actions after project is already saved } private void ApplicationOnProjectSaving(Project project) { - ProjectExplorer.BeginWaitMode(); + // Place for actions after project is about to be saved } private void ApplicationProjectClosed(Project project) Index: src/DeltaShell/DeltaShell.Plugins.ProjectExplorer/ProjectTreeView.cs =================================================================== diff -u -r9e0b372066f8d8be8c231b3be8922d29a1c61e1f -rd8e4bf47a1ff5b13a9d9e6eaf60b9ca9cd7c7555 --- src/DeltaShell/DeltaShell.Plugins.ProjectExplorer/ProjectTreeView.cs (.../ProjectTreeView.cs) (revision 9e0b372066f8d8be8c231b3be8922d29a1c61e1f) +++ src/DeltaShell/DeltaShell.Plugins.ProjectExplorer/ProjectTreeView.cs (.../ProjectTreeView.cs) (revision d8e4bf47a1ff5b13a9d9e6eaf60b9ca9cd7c7555) @@ -143,17 +143,7 @@ return null; } - - public void EnableEvents() - { - treeView.EnableDataEventListeners(); - } - - public void DisableEvents() - { - treeView.DisableDataEventListeners(); // HACK: dangerous, all changes in the tree nodes during save won't be shown - } - + public new void Dispose() { if (gui != null) Index: test/Common/DelftTools.Tests/Controls/Swf/TreeViewControls/TreeViewTest.cs =================================================================== diff -u -r5fc71a385897af92ccb092f2f969b5709afab85a -rd8e4bf47a1ff5b13a9d9e6eaf60b9ca9cd7c7555 --- test/Common/DelftTools.Tests/Controls/Swf/TreeViewControls/TreeViewTest.cs (.../TreeViewTest.cs) (revision 5fc71a385897af92ccb092f2f969b5709afab85a) +++ test/Common/DelftTools.Tests/Controls/Swf/TreeViewControls/TreeViewTest.cs (.../TreeViewTest.cs) (revision d8e4bf47a1ff5b13a9d9e6eaf60b9ca9cd7c7555) @@ -1,17 +1,12 @@ -using System; using System.Collections; -using System.Diagnostics; using System.Linq; -using System.Threading; -using System.Windows.Forms; using DelftTools.Controls; using DelftTools.Controls.Swf.TreeViewControls; using DelftTools.Tests.TestObjects; using DelftTools.TestUtils; using NUnit.Framework; using Rhino.Mocks; using SharpTestsEx; -using TreeView = DelftTools.Controls.Swf.TreeViewControls.TreeView; namespace DelftTools.Tests.Controls.Swf.TreeViewControls { @@ -310,74 +305,8 @@ treeView.Nodes[0].Nodes[0].IsExpanded.Should("node remains expanded").Be.True(); } - [Test] - public void TreeViewUpdateOnManyPropertyChangesShouldBeFast(string a) + private class DynamicParentNodePresenter : TreeViewNodePresenterBase { - var parent = new Child - { - Name = "parent" - }; - - for (var i = 0; i < 100; i++) - { - parent.Children.Add(new Child - { - Name = i.ToString() - }); - } - - // measure time to perform action without tree view - Func processingAction = () => - { - var stopwatch = new Stopwatch(); - stopwatch.Start(); - var rnd = new Random(); - for (var i = 0; i < 99; i++) - { - var child = parent.Children[rnd.Next(99)]; - child.Name = i.ToString(); - } - stopwatch.Stop(); - - return stopwatch.ElapsedMilliseconds; - }; - - Console.WriteLine("Elapsed time to perform action without tree view: " + processingAction()); - - var treeView = new TreeView - { - NodePresenters = - { - new ChildNodePresenter() - }, - Data = parent - }; - - // expand / collapse / expand - treeView.ExpandAll(); - - double elapsedMillisecondsWithTreeView = 0; - Action
onShow = delegate - { - var stopwatch = new Stopwatch(); - stopwatch.Start(); - - elapsedMillisecondsWithTreeView = processingAction(); - Console.WriteLine("Elapsed time to perform action with tree view: " + elapsedMillisecondsWithTreeView); - - treeView.WaitUntilAllEventsAreProcessed(); - - stopwatch.Stop(); - Console.WriteLine("Elapsed time to refresh tree view: " + stopwatch.ElapsedMilliseconds); - }; - - WindowsFormsTestHelper.ShowModal(treeView, onShow); - - TestHelper.AssertIsFasterThan(10, () => Thread.Sleep((int) elapsedMillisecondsWithTreeView)); - } - - public class DynamicParentNodePresenter : TreeViewNodePresenterBase - { public override void UpdateNode(ITreeNode parentNode, ITreeNode node, Parent nodeData) { node.Text = nodeData.Name;