Esempio n. 1
0
            public ViewModelBinding(ConsoleControl control, PropertyInfo controlProperty, ObservableObject viewModel, string observablePropertyName)
            {
                var viewModelObservableProperty = viewModel.GetType().GetProperty(observablePropertyName);

                if (viewModelObservableProperty.PropertyType != controlProperty.PropertyType &&
                    viewModelObservableProperty.PropertyType.IsSubclassOf(controlProperty.PropertyType) == false &&
                    viewModelObservableProperty.PropertyType.GetInterfaces().Contains(controlProperty.PropertyType) == false)
                {
                    throw new InvalidOperationException($"ViewModel property '{viewModel.GetType().FullName}.{observablePropertyName}' of type {viewModelObservableProperty.PropertyType.FullName} is not compatible with control property '{controlProperty.DeclaringType.FullName}.{controlProperty.Name}' of type {controlProperty.PropertyType.FullName} ");
                }

                viewModel.SynchronizeForLifetime(observablePropertyName, () =>
                {
                    var newValue = viewModelObservableProperty.GetValue(viewModel);
                    if (newValue == latestValue)
                    {
                        return;
                    }
                    latestValue = newValue;
                    controlProperty.SetValue(control, newValue);
                }, control.LifetimeManager);

                control.SubscribeForLifetime(controlProperty.Name, () =>
                {
                    var newValue = controlProperty.GetValue(control);
                    if (newValue == latestValue)
                    {
                        return;
                    }
                    latestValue = newValue;
                    viewModelObservableProperty.SetValue(viewModel, newValue);
                }, control.LifetimeManager);
            }
Esempio n. 2
0
        public static T FillAndPreserveAspectRatio <T>(this T child, ConsoleControl parent = null, Thickness?padding = null) where T : ConsoleControl
        {
            parent = parent ?? child.Parent;
            var    effectivePadding = padding.HasValue ? padding.Value : new Thickness(0, 0, 0, 0);
            Action syncAction       = () =>
            {
                if (parent.Width == 0 || parent.Height == 0)
                {
                    return;
                }

                var aspectRatio = (float)child.Width / child.Height;
                var newW        = parent.Width - (effectivePadding.Left + effectivePadding.Right);
                var newH        = (int)Math.Round(newW / aspectRatio);

                if (newH > parent.Height)
                {
                    newH = parent.Height;
                    newW = (int)Math.Round(newH * aspectRatio);
                }

                var newLeft = (parent.Width - newW) / 2;
                var newTop  = (parent.Height - newH) / 2;

                child.Bounds = new Rectangle(newLeft, newTop, newW, newH);
            };

            parent.SubscribeForLifetime(nameof(ConsoleControl.Bounds), syncAction, parent);
            syncAction();
            return(child);
        }
Esempio n. 3
0
        public static T Fill <T>(this T child, ConsoleControl parent = null, Thickness?padding = null) where T : ConsoleControl
        {
            parent = parent ?? child.Parent;
            var    effectivePadding = padding.HasValue ? padding.Value : new Thickness(0, 0, 0, 0);
            Action syncAction       = () =>
            {
                if (parent.Width == 0 || parent.Height == 0)
                {
                    return;
                }

                var newBounds = new Rectangle(new Point(0, 0), parent.Size);
                newBounds.X     += effectivePadding.Left;
                newBounds.Width -= effectivePadding.Left;
                newBounds.Width -= effectivePadding.Right;

                newBounds.Y      += effectivePadding.Top;
                newBounds.Height -= effectivePadding.Top;
                newBounds.Height -= effectivePadding.Bottom;

                child.Bounds = newBounds;
            };

            parent.SubscribeForLifetime(nameof(ConsoleControl.Bounds), syncAction, parent);
            syncAction();
            return(child);
        }
Esempio n. 4
0
        public static T FillVertically <T>(this T child, ConsoleControl parent = null) where T : ConsoleControl
        {
            parent = parent ?? child.Parent;
            Action syncAction = () => { child.Bounds = new Rectangle(child.X, 0, child.Width, parent.Height); };

            parent.SubscribeForLifetime(nameof(ConsoleControl.Bounds), syncAction, parent.LifetimeManager);
            syncAction();
            return(child);
        }
Esempio n. 5
0
        public ViewModelBinding(ConsoleControl control, PropertyInfo controlProperty, ObservableObject viewModel, string observablePath, Func <object, object> mapper, Func <object, object> reverseMapper)
        {
            this.mapper        = mapper;
            this.reverseMapper = reverseMapper;
            var exp              = ObjectPathExpression.Parse(observablePath);
            var trace            = exp.EvaluateAndTraceInfo(viewModel);
            var observableObject = trace[trace.Count - 2].Value as ObservableObject;

            var viewModelObservableProperty = trace.Last()?.MemberInfo as PropertyInfo;

            if (observableObject == null)
            {
                throw new InvalidOperationException($"ViewModel property '{viewModel.GetType().FullName}.{observablePath}' is not observable");
            }

            if (viewModelObservableProperty == null)
            {
                throw new InvalidOperationException($"Cannot resolve ViewModel property '{viewModel.GetType().FullName}.{observablePath}'");
            }

            if (mapper != null && reverseMapper != null)
            {
                if (viewModelObservableProperty.PropertyType != controlProperty.PropertyType &&
                    viewModelObservableProperty.PropertyType.IsSubclassOf(controlProperty.PropertyType) == false &&
                    viewModelObservableProperty.PropertyType.GetInterfaces().Contains(controlProperty.PropertyType) == false)
                {
                    throw new InvalidOperationException($"ViewModel type '{viewModel.GetType().FullName} property {observablePath}' of type {viewModelObservableProperty.PropertyType.FullName} is not compatible with control property '{controlProperty.DeclaringType.FullName}.{controlProperty.Name}' of type {controlProperty.PropertyType.FullName} ");
                }
            }

            observableObject.SynchronizeForLifetime(trace.Last().MemberInfo.Name, () =>
            {
                var newValue = viewModelObservableProperty.GetValue(observableObject);
                if (newValue == latestValue)
                {
                    return;
                }
                latestValue = newValue;
                controlProperty.SetValue(control, mapper != null ? mapper(newValue) : newValue);
            }, control.LifetimeManager);

            control.SubscribeForLifetime(controlProperty.Name, () =>
            {
                var newValue = controlProperty.GetValue(control);
                if (newValue == latestValue)
                {
                    return;
                }
                latestValue = newValue;
                viewModelObservableProperty.SetValue(observableObject, reverseMapper != null ? reverseMapper(newValue) : newValue);
            }, control.LifetimeManager);
        }
Esempio n. 6
0
        public static T DockToLeft <T>(this T child, ConsoleControl parent = null, int padding = 0) where T : ConsoleControl
        {
            parent = parent ?? child.Parent;
            Action syncAction = () =>
            {
                child.X = padding;
            };

            child.SubscribeForLifetime(nameof(ConsoleControl.Bounds), syncAction, parent);
            parent.SubscribeForLifetime(nameof(ConsoleControl.Bounds), syncAction, parent);
            syncAction();
            return(child);
        }
Esempio n. 7
0
        public static T FillVertically <T>(this T child, ConsoleControl parent = null, Thickness?padding = null) where T : ConsoleControl
        {
            parent = parent ?? child.Parent;
            var    effectivePadding = padding.HasValue ? padding.Value : new Thickness(0, 0, 0, 0);
            Action syncAction       = () =>
            {
                child.Bounds = new Rectangle(child.X, effectivePadding.Top, child.Width, parent.Height - (effectivePadding.Top + effectivePadding.Bottom));
            };

            parent.SubscribeForLifetime(nameof(ConsoleControl.Bounds), syncAction, parent);
            syncAction();
            return(child);
        }
Esempio n. 8
0
        public static T DockToBottom <T>(this T child, ConsoleControl parent = null, int padding = 0) where T : ConsoleControl
        {
            parent = parent ?? child.Parent;
            Action syncAction = () =>
            {
                if (parent.Height == 0)
                {
                    return;
                }
                child.Y = parent.Height - child.Height - padding;
            };

            child.SubscribeForLifetime(nameof(ConsoleControl.Bounds), syncAction, parent);
            parent.SubscribeForLifetime(nameof(ConsoleControl.Bounds), syncAction, parent);
            syncAction();
            return(child);
        }
Esempio n. 9
0
        public static T FillHorizontally <T>(this T child, ConsoleControl parent = null, Thickness?padding = null) where T : ConsoleControl
        {
            parent = parent ?? child.Parent;
            var    effectivePadding = padding.HasValue ? padding.Value : new Thickness(0, 0, 0, 0);
            Action syncAction       = () =>
            {
                if (parent.Width == 0)
                {
                    return;
                }

                child.Bounds = new Rectangle(effectivePadding.Left, child.Y, parent.Width - (effectivePadding.Right + effectivePadding.Left), child.Height);
            };

            parent.SubscribeForLifetime(nameof(ConsoleControl.Bounds), syncAction, parent);
            syncAction();
            return(child);
        }
Esempio n. 10
0
        public static T DockToRight <T>(this T child, ConsoleControl parent = null, int padding = 0) where T : ConsoleControl
        {
            parent = parent ?? child.Parent;
            Action syncAction = () =>
            {
                if (parent.Width == 0 || child.Width == 0)
                {
                    return;
                }

                child.X = parent.Width - child.Width - padding;
            };

            child.SubscribeForLifetime(nameof(ConsoleControl.Bounds), syncAction, parent.LifetimeManager);
            parent.SubscribeForLifetime(nameof(ConsoleControl.Bounds), syncAction, parent.LifetimeManager);
            syncAction();
            return(child);
        }
Esempio n. 11
0
        /// <summary>
        /// Adds the current control to the current focus context
        /// </summary>
        /// <param name="c">The control to add</param>
        internal void Add(ConsoleControl c)
        {
            if (focusStack.Peek().Controls.Contains(c))
            {
                throw new InvalidOperationException("Item already being tracked");
            }
            focusStack.Peek().Controls.Add(c);

            if (c.Id != null && c.Id == currentFocusedControlId)
            {
                c.TryFocus();
            }

            c.SubscribeForLifetime(nameof(c.CanFocus), () =>
            {
                if (c.CanFocus == false && c.HasFocus)
                {
                    TryMoveFocus();
                }
            }, c);
        }
Esempio n. 12
0
        public static T CenterHorizontally <T>(this T child, ConsoleControl parent = null) where T : ConsoleControl
        {
            parent = parent ?? child.Parent;

            Action syncAction = () =>
            {
                if (parent.Width == 0 || child.Width == 0)
                {
                    return;
                }

                var gap = parent.Width - child.Width;
                var x   = gap / 2;
                child.X = Math.Max(0, x);
            };

            parent.SubscribeForLifetime(nameof(ConsoleControl.Bounds), syncAction, parent);
            child.SubscribeForLifetime(nameof(ConsoleControl.Bounds), syncAction, parent);
            syncAction();

            return(child);
        }
Esempio n. 13
0
 private void ScrollableControls_Added(ConsoleControl c)
 {
     c.SubscribeForLifetime(nameof(Bounds), UpdateScrollbars, c.LifetimeManager);
 }
Esempio n. 14
0
 private void ScrollableControls_Added(ConsoleControl c)
 {
     c.SubscribeForLifetime(nameof(Bounds), UpdateScrollbars, c.LifetimeManager);
 }
Esempio n. 15
0
            public ViewModelBinding(ConsoleControl control, PropertyInfo controlProperty, ObservableObject viewModel, string observablePropertyName)
            {
                var viewModelObservableProperty = viewModel.GetType().GetProperty(observablePropertyName);

                if (viewModelObservableProperty.PropertyType != controlProperty.PropertyType &&
                    viewModelObservableProperty.PropertyType.IsSubclassOf(controlProperty.PropertyType) == false &&
                    viewModelObservableProperty.PropertyType.GetInterfaces().Contains(controlProperty.PropertyType) == false)
                {
                    throw new InvalidOperationException($"ViewModel property '{viewModel.GetType().FullName}.{observablePropertyName}' of type {viewModelObservableProperty.PropertyType.FullName} is not compatible with control property '{controlProperty.DeclaringType.FullName}.{controlProperty.Name}' of type {controlProperty.PropertyType.FullName} ");
                }

                viewModel.SynchronizeForLifetime(observablePropertyName, () =>
                {
                    var newValue = viewModelObservableProperty.GetValue(viewModel);
                    if (newValue == latestValue) return;
                    latestValue = newValue;
                    controlProperty.SetValue(control, newValue);
                }, control.LifetimeManager);

                control.SubscribeForLifetime(controlProperty.Name, () =>
                {
                    var newValue = controlProperty.GetValue(control);
                    if (newValue == latestValue) return;
                    latestValue = newValue;
                    viewModelObservableProperty.SetValue(viewModel, newValue);
                }, control.LifetimeManager);
            }