// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; using System.Windows.Controls; using System.Windows; using System.Windows.Controls.Primitives; using System.Windows.Media; using System.ComponentModel; using System.Diagnostics; namespace ICSharpCode.TreeView { public class SharpTreeNodeView : Control { static SharpTreeNodeView() { DefaultStyleKeyProperty.OverrideMetadata(typeof(SharpTreeNodeView), new FrameworkPropertyMetadata(typeof(SharpTreeNodeView))); } public static readonly DependencyProperty TextBackgroundProperty = DependencyProperty.Register("TextBackground", typeof(Brush), typeof(SharpTreeNodeView)); public Brush TextBackground { get { return (Brush)GetValue(TextBackgroundProperty); } set { SetValue(TextBackgroundProperty, value); } } public SharpTreeNode Node { get { return DataContext as SharpTreeNode; } } public SharpTreeViewItem ParentItem { get; private set; } public static readonly DependencyProperty CellEditorProperty = DependencyProperty.Register("CellEditor", typeof(Control), typeof(SharpTreeNodeView), new FrameworkPropertyMetadata()); public Control CellEditor { get { return (Control)GetValue(CellEditorProperty); } set { SetValue(CellEditorProperty, value); } } public SharpTreeView ParentTreeView { get { return ParentItem.ParentTreeView; } } internal LinesRenderer LinesRenderer { get; private set; } public override void OnApplyTemplate() { base.OnApplyTemplate(); LinesRenderer = Template.FindName("linesRenderer", this) as LinesRenderer; UpdateTemplate(); } protected override void OnVisualParentChanged(DependencyObject oldParent) { base.OnVisualParentChanged(oldParent); ParentItem = this.FindAncestor(); ParentItem.NodeView = this; } protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) { base.OnPropertyChanged(e); if (e.Property == DataContextProperty) { UpdateDataContext(e.OldValue as SharpTreeNode, e.NewValue as SharpTreeNode); } } void UpdateDataContext(SharpTreeNode oldNode, SharpTreeNode newNode) { if (newNode != null) { newNode.PropertyChanged += Node_PropertyChanged; if (Template != null) { UpdateTemplate(); } } if (oldNode != null) { oldNode.PropertyChanged -= Node_PropertyChanged; } } void Node_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "IsEditing") { OnIsEditingChanged(); } else if (e.PropertyName == "IsLast") { if (ParentTreeView.ShowLines) { foreach (var child in Node.VisibleDescendantsAndSelf()) { var container = ParentTreeView.ItemContainerGenerator.ContainerFromItem(child) as SharpTreeViewItem; if (container != null && container.NodeView != null) { container.NodeView.LinesRenderer.InvalidateVisual(); } } } } else if (e.PropertyName == "IsExpanded") { if (Node.IsExpanded) ParentTreeView.HandleExpanding(Node); } } void OnIsEditingChanged() { var textEditorContainer = Template.FindName("textEditorContainer", this) as Border; if (Node.IsEditing) { if (CellEditor == null) textEditorContainer.Child = new EditTextBox() { Item = ParentItem }; else textEditorContainer.Child = CellEditor; } else { textEditorContainer.Child = null; } } void UpdateTemplate() { var spacer = Template.FindName("spacer", this) as FrameworkElement; spacer.Width = CalculateIndent(); var expander = Template.FindName("expander", this) as ToggleButton; if (ParentTreeView.Root == Node && !ParentTreeView.ShowRootExpander) { expander.Visibility = Visibility.Collapsed; } else { expander.ClearValue(VisibilityProperty); } } internal double CalculateIndent() { var result = 19 * Node.Level; if (ParentTreeView.ShowRoot) { if (!ParentTreeView.ShowRootExpander) { if (ParentTreeView.Root != Node) { result -= 15; } } } else { result -= 19; } if (result < 0) { Debug.WriteLine("SharpTreeNodeView.CalculateIndent() on node without correctly-set level"); return 0; } return result; } } }