~halega/+junk/sharpdevelop

« back to all changes in this revision

Viewing changes to src/Libraries/SharpTreeView/ICSharpCode.TreeView/SharpTreeView.cs

  • Committer: sk
  • Date: 2011-09-10 05:17:57 UTC
  • Revision ID: halega@halega.com-20110910051757-qfouz1llya9m6boy
4.1.0.7915 Release Candidate 1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
 
2
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
 
3
 
 
4
using System;
 
5
using System.Collections.Generic;
 
6
using System.Collections.Specialized;
 
7
using System.Diagnostics;
 
8
using System.Linq;
 
9
using System.Text;
 
10
using System.Windows;
 
11
using System.Windows.Controls;
 
12
using System.Windows.Controls.Primitives;
 
13
using System.Windows.Data;
 
14
using System.Windows.Documents;
 
15
using System.Windows.Input;
 
16
using System.Windows.Media;
 
17
using System.Windows.Threading;
 
18
 
 
19
namespace ICSharpCode.TreeView
 
20
{
 
21
        public class SharpTreeView : ListView
 
22
        {
 
23
                static SharpTreeView()
 
24
                {
 
25
                        DefaultStyleKeyProperty.OverrideMetadata(typeof(SharpTreeView),
 
26
                                                                 new FrameworkPropertyMetadata(typeof(SharpTreeView)));
 
27
 
 
28
                        SelectionModeProperty.OverrideMetadata(typeof(SharpTreeView),
 
29
                                                               new FrameworkPropertyMetadata(SelectionMode.Extended));
 
30
 
 
31
                        AlternationCountProperty.OverrideMetadata(typeof(SharpTreeView),
 
32
                                                                  new FrameworkPropertyMetadata(2));
 
33
 
 
34
                        DefaultItemContainerStyleKey =
 
35
                                new ComponentResourceKey(typeof(SharpTreeView), "DefaultItemContainerStyleKey");
 
36
 
 
37
                        VirtualizingStackPanel.VirtualizationModeProperty.OverrideMetadata(typeof(SharpTreeView),
 
38
                                                                                           new FrameworkPropertyMetadata(VirtualizationMode.Recycling));
 
39
                        
 
40
                        RegisterCommands();
 
41
                }
 
42
 
 
43
                public static ResourceKey DefaultItemContainerStyleKey { get; private set; }
 
44
 
 
45
                public SharpTreeView()
 
46
                {
 
47
                        SetResourceReference(ItemContainerStyleProperty, DefaultItemContainerStyleKey);
 
48
                }
 
49
 
 
50
                public static readonly DependencyProperty RootProperty =
 
51
                        DependencyProperty.Register("Root", typeof(SharpTreeNode), typeof(SharpTreeView));
 
52
 
 
53
                public SharpTreeNode Root
 
54
                {
 
55
                        get { return (SharpTreeNode)GetValue(RootProperty); }
 
56
                        set { SetValue(RootProperty, value); }
 
57
                }
 
58
 
 
59
                public static readonly DependencyProperty ShowRootProperty =
 
60
                        DependencyProperty.Register("ShowRoot", typeof(bool), typeof(SharpTreeView),
 
61
                                                    new FrameworkPropertyMetadata(true));
 
62
 
 
63
                public bool ShowRoot
 
64
                {
 
65
                        get { return (bool)GetValue(ShowRootProperty); }
 
66
                        set { SetValue(ShowRootProperty, value); }
 
67
                }
 
68
 
 
69
                public static readonly DependencyProperty ShowRootExpanderProperty =
 
70
                        DependencyProperty.Register("ShowRootExpander", typeof(bool), typeof(SharpTreeView),
 
71
                                                    new FrameworkPropertyMetadata(false));
 
72
 
 
73
                public bool ShowRootExpander
 
74
                {
 
75
                        get { return (bool)GetValue(ShowRootExpanderProperty); }
 
76
                        set { SetValue(ShowRootExpanderProperty, value); }
 
77
                }
 
78
 
 
79
                public static readonly DependencyProperty AllowDropOrderProperty =
 
80
                        DependencyProperty.Register("AllowDropOrder", typeof(bool), typeof(SharpTreeView));
 
81
 
 
82
                public bool AllowDropOrder
 
83
                {
 
84
                        get { return (bool)GetValue(AllowDropOrderProperty); }
 
85
                        set { SetValue(AllowDropOrderProperty, value); }
 
86
                }
 
87
 
 
88
                public static readonly DependencyProperty ShowLinesProperty =
 
89
                        DependencyProperty.Register("ShowLines", typeof(bool), typeof(SharpTreeView),
 
90
                                                    new FrameworkPropertyMetadata(true));
 
91
 
 
92
                public bool ShowLines
 
93
                {
 
94
                        get { return (bool)GetValue(ShowLinesProperty); }
 
95
                        set { SetValue(ShowLinesProperty, value); }
 
96
                }
 
97
 
 
98
                public static bool GetShowAlternation(DependencyObject obj)
 
99
                {
 
100
                        return (bool)obj.GetValue(ShowAlternationProperty);
 
101
                }
 
102
 
 
103
                public static void SetShowAlternation(DependencyObject obj, bool value)
 
104
                {
 
105
                        obj.SetValue(ShowAlternationProperty, value);
 
106
                }
 
107
 
 
108
                public static readonly DependencyProperty ShowAlternationProperty =
 
109
                        DependencyProperty.RegisterAttached("ShowAlternation", typeof(bool), typeof(SharpTreeView),
 
110
                                                            new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits));
 
111
                
 
112
                protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
 
113
                {
 
114
                        base.OnPropertyChanged(e);
 
115
                        if (e.Property == RootProperty ||
 
116
                            e.Property == ShowRootProperty ||
 
117
                            e.Property == ShowRootExpanderProperty) {
 
118
                                Reload();
 
119
                        }
 
120
                }
 
121
 
 
122
                TreeFlattener flattener;
 
123
 
 
124
                void Reload()
 
125
                {
 
126
                        if (flattener != null) {
 
127
                                flattener.Stop();
 
128
                        }
 
129
                        if (Root != null) {
 
130
                                if (!(ShowRoot && ShowRootExpander)) {
 
131
                                        Root.IsExpanded = true;
 
132
                                }
 
133
                                flattener = new TreeFlattener(Root, ShowRoot);
 
134
                                flattener.CollectionChanged += flattener_CollectionChanged;
 
135
                                this.ItemsSource = flattener;
 
136
                        }
 
137
                }
 
138
                
 
139
                void flattener_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
 
140
                {
 
141
                        // Deselect nodes that are being hidden
 
142
                        if (e.Action == NotifyCollectionChangedAction.Remove) {
 
143
                                List<SharpTreeNode> selectedOldItems = null;
 
144
                                foreach (SharpTreeNode node in e.OldItems) {
 
145
                                        if (node.IsSelected) {
 
146
                                                if (selectedOldItems == null)
 
147
                                                        selectedOldItems = new List<SharpTreeNode>();
 
148
                                                selectedOldItems.Add(node);
 
149
                                        }
 
150
                                }
 
151
                                if (selectedOldItems != null) {
 
152
                                        var list = SelectedItems.Cast<SharpTreeNode>().Except(selectedOldItems).ToList();
 
153
                                        SetSelectedItems(list);
 
154
                                }
 
155
                                // reset the focus to the previous node
 
156
                                SelectedIndex = Math.Max(0, e.OldStartingIndex - 1);
 
157
                                if (SelectedItem != null)
 
158
                                        FocusNode((SharpTreeNode)SelectedItem);
 
159
                        }
 
160
                }
 
161
                
 
162
                protected override DependencyObject GetContainerForItemOverride()
 
163
                {
 
164
                        return new SharpTreeViewItem();
 
165
                }
 
166
 
 
167
                protected override bool IsItemItsOwnContainerOverride(object item)
 
168
                {
 
169
                        return item is SharpTreeViewItem;
 
170
                }
 
171
 
 
172
                protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
 
173
                {
 
174
                        base.PrepareContainerForItemOverride(element, item);
 
175
                        SharpTreeViewItem container = element as SharpTreeViewItem;
 
176
                        container.ParentTreeView = this;
 
177
                }
 
178
                
 
179
                bool doNotScrollOnExpanding;
 
180
                
 
181
                /// <summary>
 
182
                /// Handles the node expanding event in the tree view.
 
183
                /// This method gets called only if the node is in the visible region (a SharpTreeNodeView exists).
 
184
                /// </summary>
 
185
                internal void HandleExpanding(SharpTreeNode node)
 
186
                {
 
187
                        if (doNotScrollOnExpanding)
 
188
                                return;
 
189
                        SharpTreeNode lastVisibleChild = node;
 
190
                        while (true) {
 
191
                                SharpTreeNode tmp = lastVisibleChild.Children.LastOrDefault(c => c.IsVisible);
 
192
                                if (tmp != null) {
 
193
                                        lastVisibleChild = tmp;
 
194
                                } else {
 
195
                                        break;
 
196
                                }
 
197
                        }
 
198
                        if (lastVisibleChild != node) {
 
199
                                // Make the the expanded children are visible; but don't scroll down
 
200
                                // to much (keep node itself visible)
 
201
                                base.ScrollIntoView(lastVisibleChild);
 
202
                                // For some reason, this only works properly when delaying it...
 
203
                                Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(
 
204
                                        delegate {
 
205
                                                base.ScrollIntoView(node);
 
206
                                        }));
 
207
                        }
 
208
                }
 
209
                
 
210
                protected override void OnKeyDown(KeyEventArgs e)
 
211
                {
 
212
                        SharpTreeViewItem container = e.OriginalSource as SharpTreeViewItem;
 
213
                        switch (e.Key) {
 
214
                                case Key.Left:
 
215
                                        if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this) {
 
216
                                                if (container.Node.IsExpanded) {
 
217
                                                        container.Node.IsExpanded = false;
 
218
                                                } else if (container.Node.Parent != null) {
 
219
                                                        this.FocusNode(container.Node.Parent);
 
220
                                                }
 
221
                                                e.Handled = true;
 
222
                                        }
 
223
                                        break;
 
224
                                case Key.Right:
 
225
                                        if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this) {
 
226
                                                if (!container.Node.IsExpanded && container.Node.ShowExpander) {
 
227
                                                        container.Node.IsExpanded = true;
 
228
                                                } else if (container.Node.Children.Count > 0) {
 
229
                                                        // jump to first child:
 
230
                                                        container.MoveFocus(new TraversalRequest(FocusNavigationDirection.Down));
 
231
                                                }
 
232
                                                e.Handled = true;
 
233
                                        }
 
234
                                        break;
 
235
                                case Key.Return:
 
236
                                case Key.Space:
 
237
                                        if (container != null && Keyboard.Modifiers == ModifierKeys.None && this.SelectedItems.Count == 1 && this.SelectedItem == container.Node) {
 
238
                                                container.Node.ActivateItem(e);
 
239
                                        }
 
240
                                        break;
 
241
                                case Key.Add:
 
242
                                        if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this) {
 
243
                                                container.Node.IsExpanded = true;
 
244
                                                e.Handled = true;
 
245
                                        }
 
246
                                        break;
 
247
                                case Key.Subtract:
 
248
                                        if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this) {
 
249
                                                container.Node.IsExpanded = false;
 
250
                                                e.Handled = true;
 
251
                                        }
 
252
                                        break;
 
253
                                case Key.Multiply:
 
254
                                        if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this) {
 
255
                                                container.Node.IsExpanded = true;
 
256
                                                ExpandRecursively(container.Node);
 
257
                                                e.Handled = true;
 
258
                                        }
 
259
                                        break;
 
260
                        }
 
261
                        if (!e.Handled)
 
262
                                base.OnKeyDown(e);
 
263
                }
 
264
                
 
265
                void ExpandRecursively(SharpTreeNode node)
 
266
                {
 
267
                        if (node.CanExpandRecursively) {
 
268
                                node.IsExpanded = true;
 
269
                                foreach (SharpTreeNode child in node.Children) {
 
270
                                        ExpandRecursively(child);
 
271
                                }
 
272
                        }
 
273
                }
 
274
                
 
275
                /// <summary>
 
276
                /// Scrolls the specified node in view and sets keyboard focus on it.
 
277
                /// </summary>
 
278
                public void FocusNode(SharpTreeNode node)
 
279
                {
 
280
                        if (node == null)
 
281
                                throw new ArgumentNullException("node");
 
282
                        ScrollIntoView(node);
 
283
                        // WPF's ScrollIntoView() uses the same if/dispatcher construct, so we call OnFocusItem() after the item was brought into view.
 
284
                        if (this.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated) {
 
285
                                OnFocusItem(node);
 
286
                        } else {
 
287
                                this.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new DispatcherOperationCallback(this.OnFocusItem), node);
 
288
                        }
 
289
                }
 
290
                
 
291
                public void ScrollIntoView(SharpTreeNode node)
 
292
                {
 
293
                        if (node == null)
 
294
                                throw new ArgumentNullException("node");
 
295
                        doNotScrollOnExpanding = true;
 
296
                        foreach (SharpTreeNode ancestor in node.Ancestors())
 
297
                                ancestor.IsExpanded = true;
 
298
                        doNotScrollOnExpanding = false;
 
299
                        base.ScrollIntoView(node);
 
300
                }
 
301
                
 
302
                object OnFocusItem(object item)
 
303
                {
 
304
                        FrameworkElement element = this.ItemContainerGenerator.ContainerFromItem(item) as FrameworkElement;
 
305
                        if (element != null) {
 
306
                                element.Focus();
 
307
                        }
 
308
                        return null;
 
309
                }
 
310
 
 
311
                #region Track selection
 
312
                
 
313
                protected override void OnSelectionChanged(SelectionChangedEventArgs e)
 
314
                {
 
315
                        foreach (SharpTreeNode node in e.RemovedItems) {
 
316
                                node.IsSelected = false;
 
317
                        }
 
318
                        foreach (SharpTreeNode node in e.AddedItems) {
 
319
                                node.IsSelected = true;
 
320
                        }
 
321
                        base.OnSelectionChanged(e);
 
322
                }
 
323
                
 
324
                #endregion
 
325
                
 
326
                #region Drag and Drop
 
327
                protected override void OnDragEnter(DragEventArgs e)
 
328
                {
 
329
                        OnDragOver(e);
 
330
                }
 
331
 
 
332
                protected override void OnDragOver(DragEventArgs e)
 
333
                {
 
334
                        e.Effects = DragDropEffects.None;
 
335
                        
 
336
                        if (Root != null && !ShowRoot) {
 
337
                                e.Handled = true;
 
338
                                Root.CanDrop(e, Root.Children.Count);
 
339
                        }
 
340
                }
 
341
 
 
342
                protected override void OnDrop(DragEventArgs e)
 
343
                {
 
344
                        e.Effects = DragDropEffects.None;
 
345
 
 
346
                        if (Root != null && !ShowRoot) {
 
347
                                e.Handled = true;
 
348
                                Root.InternalDrop(e, Root.Children.Count);
 
349
                        }
 
350
                }
 
351
 
 
352
                internal void HandleDragEnter(SharpTreeViewItem item, DragEventArgs e)
 
353
                {
 
354
                        HandleDragOver(item, e);
 
355
                }
 
356
 
 
357
                internal void HandleDragOver(SharpTreeViewItem item, DragEventArgs e)
 
358
                {
 
359
                        HidePreview();
 
360
 
 
361
                        var target = GetDropTarget(item, e);
 
362
                        if (target != null) {
 
363
                                e.Handled = true;
 
364
                                ShowPreview(target.Item, target.Place);
 
365
                        }
 
366
                }
 
367
 
 
368
                internal void HandleDrop(SharpTreeViewItem item, DragEventArgs e)
 
369
                {
 
370
                        try {
 
371
                                HidePreview();
 
372
 
 
373
                                var target = GetDropTarget(item, e);
 
374
                                if (target != null) {
 
375
                                        e.Handled = true;
 
376
                                        target.Node.InternalDrop(e, target.Index);
 
377
                                }
 
378
                        } catch (Exception ex) {
 
379
                                Debug.WriteLine(ex.ToString());
 
380
                                throw;
 
381
                        }
 
382
                }
 
383
 
 
384
                internal void HandleDragLeave(SharpTreeViewItem item, DragEventArgs e)
 
385
                {
 
386
                        HidePreview();
 
387
                        e.Handled = true;
 
388
                }
 
389
 
 
390
                class DropTarget
 
391
                {
 
392
                        public SharpTreeViewItem Item;
 
393
                        public DropPlace Place;
 
394
                        public double Y;
 
395
                        public SharpTreeNode Node;
 
396
                        public int Index;
 
397
                }
 
398
 
 
399
                DropTarget GetDropTarget(SharpTreeViewItem item, DragEventArgs e)
 
400
                {
 
401
                        var dropTargets = BuildDropTargets(item, e);
 
402
                        var y = e.GetPosition(item).Y;
 
403
                        foreach (var target in dropTargets) {
 
404
                                if (target.Y >= y) {
 
405
                                        return target;
 
406
                                }
 
407
                        }
 
408
                        return null;
 
409
                }
 
410
 
 
411
                List<DropTarget> BuildDropTargets(SharpTreeViewItem item, DragEventArgs e)
 
412
                {
 
413
                        var result = new List<DropTarget>();
 
414
                        var node = item.Node;
 
415
 
 
416
                        if (AllowDropOrder) {
 
417
                                TryAddDropTarget(result, item, DropPlace.Before, e);
 
418
                        }
 
419
 
 
420
                        TryAddDropTarget(result, item, DropPlace.Inside, e);
 
421
 
 
422
                        if (AllowDropOrder) {
 
423
                                if (node.IsExpanded && node.Children.Count > 0) {
 
424
                                        var firstChildItem = ItemContainerGenerator.ContainerFromItem(node.Children[0]) as SharpTreeViewItem;
 
425
                                        TryAddDropTarget(result, firstChildItem, DropPlace.Before, e);
 
426
                                }
 
427
                                else {
 
428
                                        TryAddDropTarget(result, item, DropPlace.After, e);
 
429
                                }
 
430
                        }
 
431
 
 
432
                        var h = item.ActualHeight;
 
433
                        var y1 = 0.2 * h;
 
434
                        var y2 = h / 2;
 
435
                        var y3 = h - y1;
 
436
 
 
437
                        if (result.Count == 2) {
 
438
                                if (result[0].Place == DropPlace.Inside &&
 
439
                                    result[1].Place != DropPlace.Inside) {
 
440
                                        result[0].Y = y3;
 
441
                                }
 
442
                                else if (result[0].Place != DropPlace.Inside &&
 
443
                                         result[1].Place == DropPlace.Inside) {
 
444
                                        result[0].Y = y1;
 
445
                                }
 
446
                                else {
 
447
                                        result[0].Y = y2;
 
448
                                }
 
449
                        }
 
450
                        else if (result.Count == 3) {
 
451
                                result[0].Y = y1;
 
452
                                result[1].Y = y3;
 
453
                        }
 
454
                        if (result.Count > 0) {
 
455
                                result[result.Count - 1].Y = h;
 
456
                        }
 
457
                        return result;
 
458
                }
 
459
 
 
460
                void TryAddDropTarget(List<DropTarget> targets, SharpTreeViewItem item, DropPlace place, DragEventArgs e)
 
461
                {
 
462
                        SharpTreeNode node;
 
463
                        int index;
 
464
 
 
465
                        GetNodeAndIndex(item, place, out node, out index);
 
466
 
 
467
                        if (node != null) {
 
468
                                e.Effects = DragDropEffects.None;
 
469
                                if (node.CanDrop(e, index)) {
 
470
                                        DropTarget target = new DropTarget() {
 
471
                                                Item = item,
 
472
                                                Place = place,
 
473
                                                Node = node,
 
474
                                                Index = index
 
475
                                        };
 
476
                                        targets.Add(target);
 
477
                                }
 
478
                        }
 
479
                }
 
480
 
 
481
                void GetNodeAndIndex(SharpTreeViewItem item, DropPlace place, out SharpTreeNode node, out int index)
 
482
                {
 
483
                        node = null;
 
484
                        index = 0;
 
485
 
 
486
                        if (place == DropPlace.Inside) {
 
487
                                node = item.Node;
 
488
                                index = node.Children.Count;
 
489
                        }
 
490
                        else if (place == DropPlace.Before) {
 
491
                                if (item.Node.Parent != null) {
 
492
                                        node = item.Node.Parent;
 
493
                                        index = node.Children.IndexOf(item.Node);
 
494
                                }
 
495
                        }
 
496
                        else {
 
497
                                if (item.Node.Parent != null) {
 
498
                                        node = item.Node.Parent;
 
499
                                        index = node.Children.IndexOf(item.Node) + 1;
 
500
                                }
 
501
                        }
 
502
                }
 
503
 
 
504
                SharpTreeNodeView previewNodeView;
 
505
                InsertMarker insertMarker;
 
506
                DropPlace previewPlace;
 
507
 
 
508
                enum DropPlace
 
509
                {
 
510
                        Before, Inside, After
 
511
                }
 
512
 
 
513
                void ShowPreview(SharpTreeViewItem item, DropPlace place)
 
514
                {
 
515
                        previewNodeView = item.NodeView;
 
516
                        previewPlace = place;
 
517
 
 
518
                        if (place == DropPlace.Inside) {
 
519
                                previewNodeView.TextBackground = SystemColors.HighlightBrush;
 
520
                                previewNodeView.Foreground = SystemColors.HighlightTextBrush;
 
521
                        }
 
522
                        else {
 
523
                                if (insertMarker == null) {
 
524
                                        var adornerLayer = AdornerLayer.GetAdornerLayer(this);
 
525
                                        var adorner = new GeneralAdorner(this);
 
526
                                        insertMarker = new InsertMarker();
 
527
                                        adorner.Child = insertMarker;
 
528
                                        adornerLayer.Add(adorner);
 
529
                                }
 
530
 
 
531
                                insertMarker.Visibility = Visibility.Visible;
 
532
 
 
533
                                var p1 = previewNodeView.TransformToVisual(this).Transform(new Point());
 
534
                                var p = new Point(p1.X + previewNodeView.CalculateIndent() + 4.5, p1.Y - 3);
 
535
 
 
536
                                if (place == DropPlace.After) {
 
537
                                        p.Y += previewNodeView.ActualHeight;
 
538
                                }
 
539
 
 
540
                                insertMarker.Margin = new Thickness(p.X, p.Y, 0, 0);
 
541
                                
 
542
                                SharpTreeNodeView secondNodeView = null;
 
543
                                var index = flattener.IndexOf(item.Node);
 
544
 
 
545
                                if (place == DropPlace.Before) {
 
546
                                        if (index > 0) {
 
547
                                                secondNodeView = (ItemContainerGenerator.ContainerFromIndex(index - 1) as SharpTreeViewItem).NodeView;
 
548
                                        }
 
549
                                }
 
550
                                else if (index + 1 < flattener.Count) {
 
551
                                        secondNodeView = (ItemContainerGenerator.ContainerFromIndex(index + 1) as SharpTreeViewItem).NodeView;
 
552
                                }
 
553
                                
 
554
                                var w = p1.X + previewNodeView.ActualWidth - p.X;
 
555
 
 
556
                                if (secondNodeView != null) {
 
557
                                        var p2 = secondNodeView.TransformToVisual(this).Transform(new Point());
 
558
                                        w = Math.Max(w, p2.X + secondNodeView.ActualWidth - p.X);
 
559
                                }
 
560
 
 
561
                                insertMarker.Width = w + 10;
 
562
                        }
 
563
                }
 
564
 
 
565
                void HidePreview()
 
566
                {
 
567
                        if (previewNodeView != null) {
 
568
                                previewNodeView.ClearValue(SharpTreeNodeView.TextBackgroundProperty);
 
569
                                previewNodeView.ClearValue(SharpTreeNodeView.ForegroundProperty);
 
570
                                if (insertMarker != null) {
 
571
                                        insertMarker.Visibility = Visibility.Collapsed;
 
572
                                }
 
573
                                previewNodeView = null;
 
574
                        }
 
575
                }
 
576
                #endregion
 
577
                
 
578
                #region Cut / Copy / Paste / Delete Commands
 
579
 
 
580
                static void RegisterCommands()
 
581
                {
 
582
                        CommandManager.RegisterClassCommandBinding(typeof(SharpTreeView),
 
583
                                                                   new CommandBinding(ApplicationCommands.Cut, HandleExecuted_Cut, HandleCanExecute_Cut));
 
584
 
 
585
                        CommandManager.RegisterClassCommandBinding(typeof(SharpTreeView),
 
586
                                                                   new CommandBinding(ApplicationCommands.Copy, HandleExecuted_Copy, HandleCanExecute_Copy));
 
587
 
 
588
                        CommandManager.RegisterClassCommandBinding(typeof(SharpTreeView),
 
589
                                                                   new CommandBinding(ApplicationCommands.Paste, HandleExecuted_Paste, HandleCanExecute_Paste));
 
590
 
 
591
                        CommandManager.RegisterClassCommandBinding(typeof(SharpTreeView),
 
592
                                                                   new CommandBinding(ApplicationCommands.Delete, HandleExecuted_Delete, HandleCanExecute_Delete));
 
593
                }
 
594
 
 
595
                static void HandleExecuted_Cut(object sender, ExecutedRoutedEventArgs e)
 
596
                {
 
597
                        
 
598
                }
 
599
 
 
600
                static void HandleCanExecute_Cut(object sender, CanExecuteRoutedEventArgs e)
 
601
                {
 
602
                        e.CanExecute = false;
 
603
                }
 
604
 
 
605
                static void HandleExecuted_Copy(object sender, ExecutedRoutedEventArgs e)
 
606
                {
 
607
                        
 
608
                }
 
609
 
 
610
                static void HandleCanExecute_Copy(object sender, CanExecuteRoutedEventArgs e)
 
611
                {
 
612
                        e.CanExecute = false;
 
613
                }
 
614
 
 
615
                static void HandleExecuted_Paste(object sender, ExecutedRoutedEventArgs e)
 
616
                {
 
617
                        
 
618
                }
 
619
 
 
620
                static void HandleCanExecute_Paste(object sender, CanExecuteRoutedEventArgs e)
 
621
                {
 
622
                        e.CanExecute = false;
 
623
                }
 
624
 
 
625
                static void HandleExecuted_Delete(object sender, ExecutedRoutedEventArgs e)
 
626
                {
 
627
                        SharpTreeView treeView = (SharpTreeView)sender;
 
628
                        foreach (SharpTreeNode node in treeView.GetTopLevelSelection().ToArray())
 
629
                                node.Delete();
 
630
                }
 
631
 
 
632
                static void HandleCanExecute_Delete(object sender, CanExecuteRoutedEventArgs e)
 
633
                {
 
634
                        SharpTreeView treeView = (SharpTreeView)sender;
 
635
                        e.CanExecute = treeView.GetTopLevelSelection().All(node => node.CanDelete());
 
636
                }
 
637
                
 
638
                /// <summary>
 
639
                /// Gets the selected items which do not have any of their ancestors selected.
 
640
                /// </summary>
 
641
                public IEnumerable<SharpTreeNode> GetTopLevelSelection()
 
642
                {
 
643
                        var selection = this.SelectedItems.OfType<SharpTreeNode>();
 
644
                        var selectionHash = new HashSet<SharpTreeNode>(selection);
 
645
                        return selection.Where(item => item.Ancestors().All(a => !selectionHash.Contains(a)));
 
646
                }
 
647
 
 
648
                #endregion
 
649
        }
 
650
}