using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using Tango.BL.Entities; using Tango.Touch.Components; using Tango.Touch.Controls; namespace Tango.PPC.Common.Controls { public class TwineCatalogRenderer : FrameworkElement { private class ItemContainer { public DrawingVisual Visual { get; set; } public ColorCatalogsItem Item { get; set; } public double PositionY { get; set; } public Rect ImageRect { get; set; } } private class GroupContainer { public DrawingVisual Visual { get; set; } public ColorCatalogsGroup Group { get; set; } public double PositionY { get; set; } public List Items { get; set; } public GroupContainer() { Items = new List(); } } private readonly VisualCollection _children; private List _catalogItems; private List _groupItems; private double ellipseWidth = 70; private double ellipseHeight = 70; private double textHeight = 20; private double ellipseMarginX = 18; private double ellipseMarginY = 50; private double textMargin = 8; private double groupMargin = 50; private bool selectedFromClick; private LightTouchScrollViewer _scrollViewer; // private BitmapSource _myColorBitmap; private double imageWidth = 24; private double imageHeight = 22; private Point _lastMouseClickPoint; public IEnumerable Groups { get { return (IEnumerable)GetValue(GroupsProperty); } set { SetValue(GroupsProperty, value); } } public static readonly DependencyProperty GroupsProperty = DependencyProperty.Register("Groups", typeof(IEnumerable), typeof(TwineCatalogRenderer), new PropertyMetadata(null, (d, e) => { (d as TwineCatalogRenderer).OnCatalogChanged(); })); public ColorCatalogsItem SelectedItem { get { return (ColorCatalogsItem)GetValue(SelectedItemProperty); } set { SetValue(SelectedItemProperty, value); } } public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(ColorCatalogsItem), typeof(TwineCatalogRenderer), new PropertyMetadata(null, (d, e) => (d as TwineCatalogRenderer).OnSelectedItemChanged(e.OldValue, e.NewValue))); public Brush Foreground { get { return (Brush)this.GetValue(ForegroundProperty); } set { this.SetValue(ForegroundProperty, value); } } public static readonly DependencyProperty ForegroundProperty = TextBlock.ForegroundProperty.AddOwner(typeof(TwineCatalogRenderer)); public Brush Background { get { return (Brush)GetValue(BackgroundProperty); } set { SetValue(BackgroundProperty, value); } } public static readonly DependencyProperty BackgroundProperty = DependencyProperty.Register("Background", typeof(Brush), typeof(TwineCatalogRenderer), new PropertyMetadata(null)); public TwineCatalogRenderer() { Background = new SolidColorBrush(Colors.White); _children = new VisualCollection(this); _catalogItems = new List(); _groupItems = new List(); this.PreviewMouseUp += TwineCatalogRenderer_MouseLeftButtonUp; this.Loaded += TwineCatalogRenderer_Loaded; // _myColorBitmap = new BitmapImage(new Uri($"pack://application:,,,/Tango.PPC.JobsV2;component/Images/ColorSelection/Heart.png", UriKind.Absolute)); } private void TwineCatalogRenderer_Loaded(object sender, RoutedEventArgs e) { _scrollViewer = this.FindAncestor(); } public ColorCatalogsGroup GetVisibleGroup() { double currentPosition = _scrollViewer.GetScrollPosition(); var viewportRect = _scrollViewer.GetViewPortRect(); foreach (var group in _groupItems.Where(x => x.Items.Count > 0).Reverse().ToList()) { var groupRect = GetGroupRect(group); if (groupRect.IntersectsWith(viewportRect)) { return group.Group; } } return null; } public double GetGroupPosition(ColorCatalogsGroup group) { return _groupItems.Single(x => x.Group == group).PositionY; } private Rect GetGroupRect(GroupContainer group) { var height = group.Items.Last().PositionY - group.PositionY; return new Rect(0, group.PositionY + (height / 4), ActualWidth, height); } private void TwineCatalogRenderer_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { if (!_scrollViewer.IsAfterScrolling) { // Retreive the coordinates of the mouse button event. Point pt = e.GetPosition((UIElement)this); _lastMouseClickPoint = pt; // Initiate the hit test by setting up a hit test result callback method. VisualTreeHelper.HitTest(this, null, HitTestCallback, new PointHitTestParameters(pt)); } } // If a child visual object is hit, toggle its opacity to visually indicate a hit. public HitTestResultBehavior HitTestCallback(HitTestResult result) { if (result.VisualHit.GetType() == typeof(System.Windows.Media.DrawingVisual)) { var visual = result.VisualHit as DrawingVisual; if (visual != null) { var container = _catalogItems.SingleOrDefault(x => x.Visual == visual); if (container != null && container.Item is ColorCatalogsItem) { if (container.ImageRect.Contains(_lastMouseClickPoint)) { // clicked on image } selectedFromClick = true; SelectedItem = container.Item; selectedFromClick = false; } } } // Stop the hit test enumeration of objects in the visual tree. return HitTestResultBehavior.Stop; } private void OnSelectedItemChanged(object oldValue, object newValue) { var newItem = _catalogItems.SingleOrDefault(x => x.Item == newValue); var oldItem = _catalogItems.SingleOrDefault(x => x.Item == oldValue); if (newItem != null) { (newItem.Visual.Transform as ScaleTransform).ScaleX = 1.3; (newItem.Visual.Transform as ScaleTransform).ScaleY = 1.3; if (!selectedFromClick && _scrollViewer != null) { _scrollViewer.ScrollToPosition(newItem.PositionY - _scrollViewer.ActualHeight / 2); } } if (oldItem != null) { (oldItem.Visual.Transform as ScaleTransform).ScaleX = 1; (oldItem.Visual.Transform as ScaleTransform).ScaleY = 1; } } private ItemContainer AddCatalogItem(DrawingVisual visual, ColorCatalogsItem item, double y, Rect imageRect) { _children.Add(visual); var container = new ItemContainer() { Visual = visual, Item = item, PositionY = y, ImageRect = imageRect }; _catalogItems.Add(container); return container; } private GroupContainer AddGroupItem(DrawingVisual visual, ColorCatalogsGroup group, double y) { _children.Add(visual); var container = new GroupContainer() { Visual = visual, Group = group, PositionY = y, }; _groupItems.Add(container); return container; } private void OnCatalogChanged() { _children.Clear(); _catalogItems.Clear(); _groupItems.Clear(); double position_y = 0; double position_x = 0; if (Groups != null) { foreach (var group in Groups.OrderBy(x => x.GroupIndex)) { position_x = 0; var groupContainer = AddGroupItem(CreateGroup(group.Name, position_y), group, position_y); position_y += ellipseMarginX; foreach (var item in group.ColorCatalogsItems.OrderBy(x => x.ItemIndex)) { double x = position_x + ellipseMarginX; if (x + ellipseWidth > ActualWidth) { position_x = 0; position_y += (ellipseHeight + ellipseMarginY + textMargin + textHeight); } Rect imageRect = new Rect(new Point(position_x + ellipseWidth, position_y + ellipseMarginY/2 + 2), new Size( imageWidth, imageHeight)); var itemContainer = AddCatalogItem(CreateItem(item, position_x + ellipseMarginX, position_y + ellipseMarginY, imageRect), item, position_y + ellipseMarginY, imageRect); groupContainer.Items.Add(itemContainer); position_x += ellipseWidth + ellipseMarginX; } position_y += (ellipseHeight + ellipseMarginY + textMargin + textHeight + groupMargin); } Height = position_y; } UpdateLayout(); if (SelectedItem != null) { OnSelectedItemChanged( null, SelectedItem); } //InvalidateVisual(); } private DrawingVisual CreateItem(ColorCatalogsItem item, double x, double y, Rect imageRect) { DrawingVisual drawingVisual = new DrawingVisual(); DrawingContext drawingContext = drawingVisual.RenderOpen(); // drawingContext.DrawImage(_myColorBitmap, imageRect); drawingContext.DrawEllipse(new SolidColorBrush(item.Color), null, new Point(x + ellipseWidth / 2, y + ellipseHeight / 2), ellipseWidth / 2, ellipseHeight / 2); var formattedText = new FormattedText(item.Name, CultureInfo.GetCultureInfo("en-us"), FlowDirection.LeftToRight, new Typeface("Flexo"), 16, Foreground); formattedText.MaxTextWidth = ellipseWidth + ellipseMarginX; drawingContext.DrawText(formattedText, new Point((x + (ellipseWidth / 2)) - (formattedText.Width / 2), y + ellipseHeight + textMargin)); var center = new Point(x + ellipseWidth / 2, (y + ellipseHeight / 2) + textHeight + textMargin); drawingVisual.Transform = new ScaleTransform(1, 1, center.X, center.Y); drawingContext.Close(); return drawingVisual; } private void Clear() { DrawingVisual drawingVisual = new DrawingVisual(); DrawingContext drawingContext = drawingVisual.RenderOpen(); drawingContext.DrawRectangle(Background, null, new Rect(0, 0, ActualWidth, ActualHeight)); drawingContext.Close(); _children.Add(drawingVisual); } private DrawingVisual CreateGroup(String name, double y) { DrawingVisual drawingVisual = new DrawingVisual(); DrawingContext drawingContext = drawingVisual.RenderOpen(); var formattedText = new FormattedText(name, CultureInfo.GetCultureInfo("en-us"), FlowDirection.LeftToRight, new Typeface("Flexo"), 23, Foreground); //formattedText.SetFontWeight(FontWeights.SemiBold); // drawingContext.DrawText(formattedText, new Point((ActualWidth / 2) - (formattedText.Width / 2), y)); drawingContext.DrawText(formattedText, new Point(ellipseMarginX, y)); drawingContext.Close(); return drawingVisual; } // Provide a required override for the VisualChildrenCount property. protected override int VisualChildrenCount => _children != null ? _children.Count : 0; // Provide a required override for the GetVisualChild method. protected override Visual GetVisualChild(int index) { if (index < 0 || index >= _children.Count) { throw new ArgumentOutOfRangeException(); } return _children[index]; } public void ScrollToFirstFindItem(ICollectionFilter collectionFilter) { foreach (var group in _groupItems.Where(x => x.Items.Count > 0).Reverse().ToList()) { foreach( var item in group.Items) { if(collectionFilter.Filter(item.Item)) { if (_scrollViewer != null) _scrollViewer.ScrollToPosition(item.PositionY - _scrollViewer.ActualHeight / 2); break; } } } } } }