xwt/Xwt.WPF/Xwt.WPFBackend/TreeViewBackend.cs

407 строки
13 KiB
C#
Исходник Обычный вид История

//
2012-01-24 03:01:53 +04:00
// TreeViewBackend.cs
//
2012-01-24 03:01:53 +04:00
// Author:
// Eric Maupin <ermau@xamarin.com>
//
2012-04-12 23:44:45 +04:00
// Copyright (c) 2012 Xamarin, Inc.
//
2012-01-24 03:01:53 +04:00
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
2012-01-24 03:01:53 +04:00
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
2012-01-24 03:01:53 +04:00
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Data;
using System.Windows.Markup;
2012-04-11 19:58:14 +04:00
using System.Windows.Media;
using System.Windows.Shapes;
using Xwt.Engine;
2012-01-24 03:01:53 +04:00
using Xwt.Backends;
using Xwt.WPFBackend.Utilities;
using System.Windows;
2012-01-24 03:01:53 +04:00
using SWC=System.Windows.Controls;
using System.Windows.Controls;
2012-01-24 03:01:53 +04:00
namespace Xwt.WPFBackend
{
public class TreeViewBackend
: WidgetBackend, ITreeViewBackend
2012-01-24 03:01:53 +04:00
{
private static readonly ResourceDictionary TreeResourceDictionary;
static TreeViewBackend()
2012-01-24 03:01:53 +04:00
{
Uri uri = new Uri ("pack://application:,,,/Xwt.WPF;component/XWT.WPFBackend/TreeView.xaml");
TreeResourceDictionary = (ResourceDictionary)XamlReader.Load (System.Windows.Application.GetResourceStream (uri).Stream);
2012-01-24 03:01:53 +04:00
}
public TreeViewBackend ()
{
Tree = new ExTreeView();
Tree.Resources.MergedDictionaries.Add (TreeResourceDictionary);
2012-04-11 19:58:14 +04:00
Tree.ItemTemplate = new HierarchicalDataTemplate { ItemsSource = new Binding ("Children") };
2012-04-17 18:42:30 +04:00
Tree.SetValue (VirtualizingStackPanel.IsVirtualizingProperty, true);
}
2012-04-11 20:08:12 +04:00
public ScrollPolicy VerticalScrollPolicy {
get { return ScrollViewer.GetVerticalScrollBarVisibility (Tree).ToXwtScrollPolicy (); }
set { ScrollViewer.SetVerticalScrollBarVisibility (Tree, value.ToWpfScrollBarVisibility ()); }
}
2012-04-11 20:08:12 +04:00
public ScrollPolicy HorizontalScrollPolicy {
get { return ScrollViewer.GetHorizontalScrollBarVisibility (Tree).ToXwtScrollPolicy (); }
set { ScrollViewer.SetHorizontalScrollBarVisibility (Tree, value.ToWpfScrollBarVisibility ()); }
2012-01-24 03:01:53 +04:00
}
2012-04-11 20:08:12 +04:00
public TreePosition[] SelectedRows {
get { return Tree.SelectedItems.Cast<TreePosition> ().ToArray (); }
2012-01-24 03:01:53 +04:00
}
2012-04-11 19:58:14 +04:00
private bool headersVisible = true;
public bool HeadersVisible {
get { return this.headersVisible; }
set
{
this.headersVisible = value;
if (value) {
if (Tree.View.ColumnHeaderContainerStyle != null)
Tree.View.ColumnHeaderContainerStyle.Setters.Remove (HideHeaderSetter);
} else {
if (Tree.View.ColumnHeaderContainerStyle == null)
Tree.View.ColumnHeaderContainerStyle = new Style();
Tree.View.ColumnHeaderContainerStyle.Setters.Add (HideHeaderSetter);
}
}
2012-01-24 03:01:53 +04:00
}
2012-03-22 03:32:53 +04:00
public void SelectRow (TreePosition pos)
2012-01-24 03:01:53 +04:00
{
Tree.SelectedItems.Add (pos);
2012-01-24 03:01:53 +04:00
}
2012-03-22 03:32:53 +04:00
public void UnselectRow (TreePosition pos)
2012-02-27 21:35:54 +04:00
{
Tree.SelectedItems.Remove (pos);
2012-02-27 21:35:54 +04:00
}
2012-03-22 03:32:53 +04:00
public bool IsRowSelected (TreePosition row)
2012-01-24 03:01:53 +04:00
{
return Tree.SelectedItems.Contains (row);
2012-03-22 03:32:53 +04:00
}
public bool IsRowExpanded (TreePosition row)
{
return ((TreeStoreNode) row).IsExpanded;
2012-03-22 03:32:53 +04:00
}
public void ExpandToRow (TreePosition pos)
{
TreeStoreNode parent = ((TreeStoreNode) pos).Parent;
if (parent != null)
parent.IsExpanded = true;
2012-02-27 21:35:54 +04:00
}
2012-01-24 03:01:53 +04:00
public void ExpandRow (TreePosition row, bool expandChildren)
{
TreeStoreNode node = ((TreeStoreNode) row);
node.IsExpanded = true;
if (expandChildren) {
foreach (TreeStoreNode childNode in node.Children)
childNode.IsExpanded = true;
}
2012-01-24 03:01:53 +04:00
}
public void CollapseRow (TreePosition row)
{
((TreeStoreNode) row).IsExpanded = false;
2012-01-24 03:01:53 +04:00
}
2012-02-27 21:35:54 +04:00
public void ScrollToRow (TreePosition pos)
{
GetVisibleTreeItem (pos).BringIntoView();
}
public void SetSelectionMode (SelectionMode mode)
{
Tree.SelectionMode = (mode == SelectionMode.Single)
? SWC.SelectionMode.Single
: SWC.SelectionMode.Extended;
}
public void SelectAll ()
{
Tree.SelectAllExpanded();
2012-02-27 21:35:54 +04:00
}
2012-01-24 03:01:53 +04:00
public void UnselectAll ()
{
Tree.UnselectAll();
2012-01-24 03:01:53 +04:00
}
public void SetSource (ITreeDataSource source, IBackend sourceBackend)
2012-01-24 03:01:53 +04:00
{
Tree.ItemsSource = (TreeStoreBackend) sourceBackend;
2012-01-24 03:01:53 +04:00
}
public object AddColumn (ListViewColumn column)
2012-01-24 03:01:53 +04:00
{
var col = new GridViewColumn ();
2012-04-11 19:58:14 +04:00
UpdateColumn (column, col, ListViewColumnChange.Title);
2012-04-11 19:58:14 +04:00
Tree.View.Columns.Add (col);
UpdateColumn (column, col, ListViewColumnChange.Cells);
return col;
2012-01-24 03:01:53 +04:00
}
public void UpdateColumn (ListViewColumn column, object handle, ListViewColumnChange change)
{
var col = ((GridViewColumn) handle);
switch (change) {
case ListViewColumnChange.Title:
col.Header = column.Title;
break;
2012-04-11 19:58:14 +04:00
case ListViewColumnChange.Cells:
2012-04-11 19:58:14 +04:00
var cellTemplate = CellUtil.CreateBoundColumnTemplate (column.Views);
col.CellTemplate = new DataTemplate { VisualTree = cellTemplate };
int index = Tree.View.Columns.IndexOf (col);
if (index == 0) {
2012-04-11 20:08:12 +04:00
var dockFactory = CreateExpanderDock ();
2012-04-11 19:58:14 +04:00
dockFactory.AppendChild (cellTemplate);
col.CellTemplate.VisualTree = dockFactory;
}
break;
}
2012-01-24 03:01:53 +04:00
}
public void RemoveColumn (ListViewColumn column, object handle)
{
2012-04-11 19:58:14 +04:00
Tree.View.Columns.Remove ((GridViewColumn) handle);
2012-01-24 03:01:53 +04:00
}
public bool GetDropTargetRow (double x, double y, out RowDropPosition pos, out TreePosition nodePosition)
2012-01-24 03:01:53 +04:00
{
pos = RowDropPosition.Into;
x *= WidthPixelRatio;
y *= HeightPixelRatio;
var result = VisualTreeHelper.HitTest (Tree, new System.Windows.Point (x, y)) as PointHitTestResult;
var element = (result != null) ? result.VisualHit as FrameworkElement : null;
while (element != null) {
if (element is ExTreeViewItem)
break;
element = VisualTreeHelper.GetParent (element) as FrameworkElement;
}
if (element == null) {
nodePosition = default(TreePosition);
return false;
}
double edge = element.ActualHeight * 0.18;
if (result.PointHit.Y <= edge) {
pos = RowDropPosition.Before;
} else if (result.PointHit.Y >= element.ActualHeight - edge)
pos = RowDropPosition.After;
nodePosition = element.DataContext as TreeStoreNode;
return true;
}
public override void EnableEvent (object eventId)
{
base.EnableEvent (eventId);
2012-04-11 20:08:12 +04:00
if (eventId is TableViewEvent) {
switch ((TableViewEvent)eventId) {
case TableViewEvent.SelectionChanged:
Tree.SelectedItemsChanged += OnSelectedItemsChanged;
break;
}
}
}
public override void DisableEvent (object eventId)
{
base.DisableEvent (eventId);
2012-04-11 20:08:12 +04:00
if (eventId is TableViewEvent) {
switch ((TableViewEvent)eventId) {
case TableViewEvent.SelectionChanged:
Tree.SelectedItemsChanged -= OnSelectedItemsChanged;
break;
}
}
2012-01-24 03:01:53 +04:00
}
2012-04-11 20:08:12 +04:00
protected ExTreeView Tree {
get { return (ExTreeView)Widget; }
set { Widget = value; }
}
2012-04-11 20:08:12 +04:00
protected ITreeViewEventSink TreeViewEventSink {
get { return (ITreeViewEventSink)EventSink; }
}
protected override double DefaultNaturalHeight {
get { return -1; }
}
protected override double DefaultNaturalWidth {
get { return -1; }
}
public override WidgetSize GetPreferredHeight()
{
return new WidgetSize (0);
}
public override WidgetSize GetPreferredHeightForWidth(double width)
{
return GetPreferredHeight ();
}
public override WidgetSize GetPreferredWidth()
{
return new WidgetSize (0);
}
public override WidgetSize GetPreferredWidthForHeight(double height)
{
return GetPreferredWidth ();
}
private void OnSelectedItemsChanged (object sender, EventArgs e)
{
Toolkit.Invoke (TreeViewEventSink.OnSelectionChanged);
}
private ExTreeViewItem GetVisibleTreeItem (TreePosition pos, Action<ExTreeViewItem> walk = null)
{
Stack<TreeStoreNode> nodes = new Stack<TreeStoreNode> ();
TreeStoreNode node = (TreeStoreNode) pos;
do {
nodes.Push (node);
node = node.Parent;
} while (node != null);
ExTreeViewItem treeItem = null;
ItemContainerGenerator g = this.Tree.ItemContainerGenerator;
while (nodes.Count > 0) {
node = nodes.Pop ();
treeItem = (ExTreeViewItem) g.ContainerFromItem (node);
treeItem.UpdateLayout ();
g = treeItem.ItemContainerGenerator;
if (walk != null)
walk (treeItem);
}
return treeItem;
}
2012-04-11 19:58:14 +04:00
private FrameworkElementFactory CreateExpanderDock ()
{
2012-04-11 19:58:14 +04:00
var dockFactory = new FrameworkElementFactory (typeof (DockPanel));
var source = new RelativeSource (RelativeSourceMode.FindAncestor, typeof (ExTreeViewItem), 1);
Style expanderStyle = new Style (typeof (SWC.Primitives.ToggleButton));
expanderStyle.Setters.Add (new Setter (UIElement.FocusableProperty, false));
expanderStyle.Setters.Add (new Setter (FrameworkElement.WidthProperty, 19d));
expanderStyle.Setters.Add (new Setter (FrameworkElement.HeightProperty, 13d));
var expanderTemplate = new ControlTemplate (typeof (SWC.Primitives.ToggleButton));
var outerBorderFactory = new FrameworkElementFactory (typeof (Border));
outerBorderFactory.SetValue (FrameworkElement.WidthProperty, 19d);
outerBorderFactory.SetValue (FrameworkElement.HeightProperty, 13d);
outerBorderFactory.SetValue (Control.BackgroundProperty, Brushes.Transparent);
outerBorderFactory.SetBinding (UIElement.VisibilityProperty,
new Binding ("HasItems") { RelativeSource = source, Converter = BoolVisibilityConverter });
var innerBorderFactory = new FrameworkElementFactory (typeof (Border));
innerBorderFactory.SetValue (FrameworkElement.WidthProperty, 9d);
innerBorderFactory.SetValue (FrameworkElement.HeightProperty, 9d);
innerBorderFactory.SetValue (Control.BorderThicknessProperty, new Thickness (1));
innerBorderFactory.SetValue (Control.BorderBrushProperty, new SolidColorBrush (Color.FromRgb (120, 152, 181)));
innerBorderFactory.SetValue (Border.CornerRadiusProperty, new CornerRadius (1));
innerBorderFactory.SetValue (UIElement.SnapsToDevicePixelsProperty, true);
innerBorderFactory.SetValue (Control.BackgroundProperty, ExpanderBackgroundBrush);
var pathFactory = new FrameworkElementFactory (typeof (Path));
pathFactory.SetValue (FrameworkElement.MarginProperty, new Thickness (1));
pathFactory.SetValue (Shape.FillProperty, Brushes.Black);
pathFactory.SetBinding (Path.DataProperty,
new Binding ("IsChecked") {
RelativeSource = new RelativeSource (RelativeSourceMode.FindAncestor, typeof (SWC.Primitives.ToggleButton), 1),
Converter = BooleanGeometryConverter
});
innerBorderFactory.AppendChild (pathFactory);
outerBorderFactory.AppendChild (innerBorderFactory);
expanderTemplate.VisualTree = outerBorderFactory;
expanderStyle.Setters.Add (new Setter (Control.TemplateProperty, expanderTemplate));
var toggleFactory = new FrameworkElementFactory (typeof (SWC.Primitives.ToggleButton));
toggleFactory.SetValue (FrameworkElement.StyleProperty, expanderStyle);
toggleFactory.SetBinding (FrameworkElement.MarginProperty,
new Binding ("Level") { RelativeSource = source, Converter = LevelConverter });
toggleFactory.SetBinding (SWC.Primitives.ToggleButton.IsCheckedProperty,
new Binding ("IsExpanded") { RelativeSource = source });
toggleFactory.SetValue (SWC.Primitives.ButtonBase.ClickModeProperty, ClickMode.Press);
dockFactory.AppendChild (toggleFactory);
return dockFactory;
}
private static readonly LevelToIndentConverter LevelConverter = new LevelToIndentConverter();
private static readonly BooleanToVisibilityConverter BoolVisibilityConverter = new BooleanToVisibilityConverter();
2012-04-11 19:58:14 +04:00
private static readonly LinearGradientBrush ExpanderBackgroundBrush = new LinearGradientBrush {
StartPoint = new System.Windows.Point (0, 0),
EndPoint = new System.Windows.Point (1, 1),
GradientStops = new GradientStopCollection {
new GradientStop (Colors.White, 0.2),
new GradientStop (Color.FromRgb (192, 183, 166), 1)
}
2012-04-11 19:58:14 +04:00
};
2012-04-11 19:58:14 +04:00
private static readonly Geometry Plus = Geometry.Parse ("M 0 2 L 0 3 L 2 3 L 2 5 L 3 5 L 3 3 L 5 3 L 5 2 L 3 2 L 3 0 L 2 0 L 2 2 Z");
private static readonly Geometry Minus = Geometry.Parse ("M 0 2 L 0 3 L 5 3 L 5 2 Z");
private static readonly BooleanToValueConverter BooleanGeometryConverter =
new BooleanToValueConverter { TrueValue = Minus, FalseValue = Plus };
private static readonly Setter HideHeaderSetter = new Setter (UIElement.VisibilityProperty, Visibility.Collapsed);
}
2012-01-24 03:01:53 +04:00
}