示例#1
0
        public BasePointEditorControl()
        {
            XLabel = new UnfocusableTextField();

            XEditor = new NumericSpinEditor <T> ();
            XEditor.BackgroundColor = NSColor.Clear;
            XEditor.Value           = 0.0f;
            XEditor.ValueChanged   += OnInputUpdated;

            YLabel = new UnfocusableTextField();

            YEditor = new NumericSpinEditor <T> ();
            YEditor.BackgroundColor = NSColor.Clear;
            YEditor.Value           = 0.0f;
            YEditor.ValueChanged   += OnInputUpdated;

            AddSubview(XLabel);
            AddSubview(XEditor);
            AddSubview(YLabel);
            AddSubview(YEditor);

            this.DoConstraints(new[] {
                XEditor.ConstraintTo(this, (xe, c) => xe.Width == 90),
                XEditor.ConstraintTo(this, (xe, c) => xe.Height == DefaultControlHeight),
                YEditor.ConstraintTo(this, (ye, c) => ye.Width == 90),
                YEditor.ConstraintTo(this, (ye, c) => ye.Height == DefaultControlHeight),
            });

            UpdateTheme();
        }
        private void Initialize(IHostResourceProvider hostResources)
        {
            WantsLayer = true;
            Editors    = CreateEditors(hostResources, EditorType);

            this.hexLabel = new UnfocusableTextField {
                StringValue = "#:",
                Alignment   = NSTextAlignment.Right,
                ToolTip     = Properties.Resources.HexValue
            };
            AddSubview(this.hexLabel);

            this.hexEditor = new NSTextField {
                Alignment   = NSTextAlignment.Right,
                ControlSize = NSControlSize.Small,
                Font        = NSFont.SystemFontOfSize(NSFont.SystemFontSizeForControlSize(NSControlSize.Small))
            };
            AddSubview(this.hexEditor);

            this.hexEditor.EditingEnded += (o, e) => {
                if (CommonColor.TryParseArgbHex(this.hexEditor.StringValue, out CommonColor c))
                {
                    ViewModel.Color            = c;
                    this.hexEditor.StringValue = c.ToString();
                }
            };
        }
        public CategoryContainerControl(IHostResourceProvider hostResources, NSOutlineView outlineView) : base(hostResources)
        {
            if (outlineView == null)
            {
                throw new ArgumentNullException(nameof(outlineView));
            }

            this.outlineView = outlineView;

            this.disclosure = this.outlineView.MakeView("NSOutlineViewDisclosureButtonKey", outlineView) as NSButton;
            this.disclosure.TranslatesAutoresizingMaskIntoConstraints = false;
            AddSubview(this.disclosure);

            var label = new UnfocusableTextField {
                TranslatesAutoresizingMaskIntoConstraints = false
            };

            AddSubview(label);

            AddConstraints(new[] {
                NSLayoutConstraint.Create(this.disclosure, NSLayoutAttribute.CenterY, NSLayoutRelation.Equal, this, NSLayoutAttribute.CenterY, 1, 0),
                NSLayoutConstraint.Create(this.disclosure, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this, NSLayoutAttribute.Left, 1, 4),
                NSLayoutConstraint.Create(label, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this.disclosure, NSLayoutAttribute.Right, 1, 0),
                NSLayoutConstraint.Create(label, NSLayoutAttribute.Height, NSLayoutRelation.Equal, this, NSLayoutAttribute.Height, 1, 0),
            });
        }
            public override NSView GetView(NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item)
            {
                var label = (UnfocusableTextField)outlineView.MakeView(LabelId, outlineView);

                if (label == null)
                {
                    label = new UnfocusableTextField {
                        Identifier = LabelId
                    };
                }

                string text   = String.Empty;
                var    facade = (NSObjectFacade)item;

                if (facade.Target is KeyValuePair <string, SimpleCollectionView> kvp)
                {
                    text = kvp.Key;
                }
                else if (facade.Target is ITypeInfo type)
                {
                    text = type.Name;
                }

                label.StringValue = text;
                return(label);
            }
		public override NSView GetView (NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item)
		{
			var labelContainer = (UnfocusableTextField)outlineView.MakeView (PathIdentifier, this);
			if (labelContainer == null) {
				labelContainer = new UnfocusableTextField {
					Identifier = PathIdentifier,
				};
			}
			var target = (item as NSObjectFacade).Target;

			switch (target) {
			case PropertyTreeElement propertyTreeElement:
				labelContainer.StringValue = string.Format ("{0}: ({1})", propertyTreeElement.Property.Name, propertyTreeElement.Property.RealType.Name);
				break;

			case string targetName:
				labelContainer.StringValue = targetName;
				break;

			default:
				labelContainer.StringValue = Properties.Resources.TypeNotSupported;
				break;
			}

			return labelContainer;
		}
示例#6
0
        protected BasePointEditorControl(IHostResourceProvider hostResources)
            : base(hostResources)
        {
            XLabel = new UnfocusableTextField {
                Font = NSFont.FromFontName(DefaultFontName, DefaultDescriptionLabelFontSize),
                TranslatesAutoresizingMaskIntoConstraints = false,
            };

            XEditor = new NumericSpinEditor <T> (hostResources)
            {
                BackgroundColor = NSColor.Clear,
                Value           = 0.0f
            };
            XEditor.ProxyResponder = new ProxyResponder(this, ProxyRowType.FirstView);
            XEditor.ValueChanged  += OnInputUpdated;

            YLabel = new UnfocusableTextField {
                Font = NSFont.FromFontName(DefaultFontName, DefaultDescriptionLabelFontSize),
                TranslatesAutoresizingMaskIntoConstraints = false,
            };

            YEditor = new NumericSpinEditor <T> (hostResources)
            {
                BackgroundColor = NSColor.Clear,
                Value           = 0.0f
            };
            YEditor.ProxyResponder = new ProxyResponder(this, ProxyRowType.LastView);
            YEditor.ValueChanged  += OnInputUpdated;

            AddSubview(XLabel);
            AddSubview(XEditor);
            AddSubview(YLabel);
            AddSubview(YEditor);

            const float editorHeight = 18;

            this.AddConstraints(new[] {
                NSLayoutConstraint.Create(XEditor, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this, NSLayoutAttribute.Top, 1f, 3f),
                NSLayoutConstraint.Create(XEditor, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this, NSLayoutAttribute.Left, 1f, 0f),
                NSLayoutConstraint.Create(XEditor, NSLayoutAttribute.Right, NSLayoutRelation.Equal, YEditor, NSLayoutAttribute.Left, 1f, -10f),
                NSLayoutConstraint.Create(XEditor, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1f, editorHeight),

                NSLayoutConstraint.Create(XLabel, NSLayoutAttribute.Top, NSLayoutRelation.Equal, XEditor, NSLayoutAttribute.Bottom, 1f, -4f),
                NSLayoutConstraint.Create(XLabel, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1f, editorHeight),

                NSLayoutConstraint.Create(YEditor, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this, NSLayoutAttribute.Top, 1f, 3f),
                NSLayoutConstraint.Create(YEditor, NSLayoutAttribute.Right, NSLayoutRelation.Equal, this, NSLayoutAttribute.Right, 1f, 0),
                NSLayoutConstraint.Create(YEditor, NSLayoutAttribute.Width, NSLayoutRelation.Equal, XEditor, NSLayoutAttribute.Width, 1f, 0f),
                NSLayoutConstraint.Create(YEditor, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1f, editorHeight),

                NSLayoutConstraint.Create(YLabel, NSLayoutAttribute.Top, NSLayoutRelation.Equal, XLabel, NSLayoutAttribute.Top, 1f, 0f),
                NSLayoutConstraint.Create(YLabel, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1f, editorHeight),

                NSLayoutConstraint.Create(XLabel, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, XEditor.Subviews[0], NSLayoutAttribute.CenterX, 1f, 0),
                NSLayoutConstraint.Create(YLabel, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, YEditor.Subviews[0], NSLayoutAttribute.CenterX, 1f, 0),
            });

            AppearanceChanged();
        }
示例#7
0
        public ErrorMessageView(IHostResourceProvider hostResources, IEnumerable errors)
        {
            if (errors == null)
            {
                throw new ArgumentNullException(nameof(errors));
            }

            Frame = new CGRect(CGPoint.Empty, new CGSize(320, 240));

            var iconView = new NSButton(new CGRect(5, Frame.Height - 25, DefaultIconButtonSize, DefaultIconButtonSize))
            {
                Bordered = false,
                Image    = hostResources.GetNamedImage("pe-action-warning-16"),
                Title    = string.Empty,
                TranslatesAutoresizingMaskIntoConstraints = false,
            };

            AddSubview(iconView);

            var viewTitle = new UnfocusableTextField(new CGRect(30, Frame.Height - 26, 120, 24), "Errors");

            AddSubview(viewTitle);

            this.errorMessages = new NSTextField {
                BackgroundColor = NSColor.Clear,
                Editable        = false,
                TranslatesAutoresizingMaskIntoConstraints = false,
            };
            this.errorMessages.Cell.Wraps = true;

            foreach (var error in errors)
            {
                this.errorMessages.StringValue += error + "\n";
            }

            AddSubview(this.errorMessages);

            this.AddConstraints(new[] {
                NSLayoutConstraint.Create(iconView, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this, NSLayoutAttribute.Top, 1f, 5f),
                NSLayoutConstraint.Create(iconView, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this, NSLayoutAttribute.Left, 1f, 5f),
                NSLayoutConstraint.Create(iconView, NSLayoutAttribute.Width, NSLayoutRelation.Equal, 1f, DefaultIconButtonSize),
                NSLayoutConstraint.Create(iconView, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1f, DefaultIconButtonSize),

                NSLayoutConstraint.Create(viewTitle, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this, NSLayoutAttribute.Top, 1f, 7f),
                NSLayoutConstraint.Create(viewTitle, NSLayoutAttribute.Left, NSLayoutRelation.Equal, iconView, NSLayoutAttribute.Right, 1f, 5f),
                NSLayoutConstraint.Create(viewTitle, NSLayoutAttribute.Width, NSLayoutRelation.Equal, 1f, 120),
                NSLayoutConstraint.Create(viewTitle, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1f, PropertyEditorControl.DefaultControlHeight),

                NSLayoutConstraint.Create(this.errorMessages, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this, NSLayoutAttribute.Top, 1f, 35f),
                NSLayoutConstraint.Create(this.errorMessages, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this, NSLayoutAttribute.Left, 1f, 5f),
                NSLayoutConstraint.Create(this.errorMessages, NSLayoutAttribute.Width, NSLayoutRelation.Equal, this, NSLayoutAttribute.Width, 1f, -10f),
                NSLayoutConstraint.Create(this.errorMessages, NSLayoutAttribute.Height, NSLayoutRelation.Equal, this, NSLayoutAttribute.Height, 1f, -40f),
            });
        }
示例#8
0
        public BasePopOverControl(IHostResourceProvider hostResources, string title, string imageNamed) : base()
        {
            if (title == null)
            {
                throw new ArgumentNullException(nameof(title));
            }
            if (imageNamed == null)
            {
                throw new ArgumentNullException(nameof(imageNamed));
            }
            if (hostResources == null)
            {
                throw new ArgumentNullException(nameof(hostResources));
            }

            TranslatesAutoresizingMaskIntoConstraints = false;
            WantsLayer = true;

            HostResources = hostResources;

            var iconView = new NSImageView {
                Image        = hostResources.GetNamedImage(imageNamed),
                ImageScaling = NSImageScale.None,
                TranslatesAutoresizingMaskIntoConstraints = false,
            };

            AddSubview(iconView);

            this.viewTitle = new UnfocusableTextField {
                Font        = NSFont.BoldSystemFontOfSize(11),
                StringValue = title,
                TranslatesAutoresizingMaskIntoConstraints = false,
            };

            AddSubview(this.viewTitle);

            this.AddConstraints(new[] {
                NSLayoutConstraint.Create(iconView, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this, NSLayoutAttribute.Top, 1f, 5f),
                NSLayoutConstraint.Create(iconView, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this, NSLayoutAttribute.Left, 1f, 5f),
                NSLayoutConstraint.Create(iconView, NSLayoutAttribute.Width, NSLayoutRelation.Equal, 1f, DefaultIconButtonSize),
                NSLayoutConstraint.Create(iconView, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1f, DefaultIconButtonSize),

                NSLayoutConstraint.Create(this.viewTitle, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this, NSLayoutAttribute.Top, 1f, 7f),
                NSLayoutConstraint.Create(this.viewTitle, NSLayoutAttribute.Left, NSLayoutRelation.Equal, iconView, NSLayoutAttribute.Right, 1f, 5f),
                NSLayoutConstraint.Create(this.viewTitle, NSLayoutAttribute.Width, NSLayoutRelation.Equal, 1f, 120),
                NSLayoutConstraint.Create(this.viewTitle, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1f, PropertyEditorControl.DefaultControlHeight),
            });

            AppearanceChanged();
        }
示例#9
0
        public override NSView GetView(NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item)
        {
            var facade   = item as NSObjectFacade;
            var resource = facade?.Target as Resource;

            switch (tableColumn.Identifier)
            {
            case ResourceOutlineView.ResourcePreviewColId:
                var cbv = (CommonBrushView)outlineView.MakeView(resourceIdentifier, this);
                if (cbv == null)
                {
                    cbv = new CommonBrushView(this.hostResources)
                    {
                        Identifier       = resourceIdentifier,
                        Frame            = new CGRect(0, 0, 30, 18),
                        AutoresizingMask = NSViewResizingMask.WidthSizable
                    };
                }

                var commonBrush = BrushPropertyViewModel.GetCommonBrushForResource(resource);
                if (commonBrush != null)
                {
                    cbv.Brush = commonBrush;
                }

                return(cbv);

            case ResourceOutlineView.ResourceNameColId:
            default:
                var utf = (UnfocusableTextField)outlineView.MakeView(labelIdentifier, this);
                if (utf == null)
                {
                    utf = new UnfocusableTextField {
                        Identifier = labelIdentifier,
                    };
                }
                utf.StringValue = resource.Name;
                return(utf);
            }
        }
        public override void LoadView()
        {
            var stack = new NSStackView()
            {
                Orientation = NSUserInterfaceLayoutOrientation.Vertical
            };

            this.materialEditor = new MaterialView {
                ViewModel = ViewModel?.MaterialDesign
            };

            this.alphaChannelEditor = new AlphaChannelEditor();
            this.alphaSpinEditor    = new ComponentSpinEditor(this.hostResources, this.alphaChannelEditor)
            {
                BackgroundColor = NSColor.Clear
            };
            this.alphaSpinEditor.ValueChanged += UpdateComponent;

            var alphaStack = new NSStackView()
            {
                Orientation = NSUserInterfaceLayoutOrientation.Horizontal
            };

            var alphaLabel = new UnfocusableTextField {
                StringValue = $"{Properties.Resources.Alpha}:",
                Alignment   = NSTextAlignment.Left,
            };

            alphaLabel.Cell.LineBreakMode = NSLineBreakMode.Clipping;

            alphaStack.AddView(alphaLabel, NSStackViewGravity.Trailing);
            alphaStack.AddView(this.alphaSpinEditor, NSStackViewGravity.Trailing);

            stack.AddView(this.materialEditor, NSStackViewGravity.Leading);
            stack.AddView(alphaStack, NSStackViewGravity.Trailing);

            View = stack;
        }
示例#11
0
        // the table is looking for this method, picks it up automagically
        public override NSView GetViewForItem(NSTableView tableView, NSTableColumn tableColumn, nint row)
        {
            var resource = datasource.ViewModel.Resources [(int)row] as Resource;

            // Setup view based on the column
            switch (tableColumn.Identifier)
            {
            case RequestResourcePanel.ResourceImageColId:
                if (resource.Source.Type != ResourceSourceType.Application)
                {
                    var iconView = (NSImageView)tableView.MakeView(iconIdentifier, this);
                    if (iconView == null)
                    {
                        iconView = new NSImageView {
                            Image        = this.hostResources.GetNamedImage("pe-resource-editor-32"),
                            ImageScaling = NSImageScale.None,
                            Identifier   = iconIdentifier,
                        };
                    }
                    return(iconView);
                }

                // If we get here its a local resource
                return(new NSView());

            case RequestResourcePanel.ResourceTypeColId:
                var typeView = (UnfocusableTextField)tableView.MakeView(typeIdentifier, this);
                if (typeView == null)
                {
                    typeView = new UnfocusableTextField {
                        Identifier = typeIdentifier,
                    };
                }

                typeView.StringValue = resource.Source.Name;
                return(typeView);

            case RequestResourcePanel.ResourceNameColId:
                var nameView = (UnfocusableTextField)tableView.MakeView(nameIdentifier, this);
                if (nameView == null)
                {
                    nameView = new UnfocusableTextField {
                        Identifier = nameIdentifier,
                    };
                }

                nameView.StringValue = resource.Name;
                return(nameView);

            case RequestResourcePanel.ResourceValueColId:
                var valueView = MakeValueView(resource, tableView);

                // If still null we have no editor yet.
                valueView = valueView ?? new NSView();

                return(valueView);

            default:
                return(base.GetViewForItem(tableView, tableColumn, row));
            }
        }
        private void CreateColourPallette()
        {
            var subViews = Subviews;

            if (subViews.Length > 0)
            {
                foreach (var sv in subViews)
                {
                    if (sv is FocusableButton fb)
                    {
                        fb.Activated -= MaterialColourButton_Activated;
                    }
                    sv.RemoveFromSuperview();
                    sv.Dispose();
                }
            }

            if (ViewModel == null)
            {
                return;
            }

            var       colors      = ViewModel.Palettes.Select(p => new { p.Name, Color = p.MainColor }).ToArray();
            int       col         = 0;
            nfloat    x           = 0;
            nfloat    y           = 6;
            const int FrameWidth  = 430;            // TODO Get proper Frame.Width, but hacking to get this working
            const int FrameHeight = 202;            // TODO Get proper Frame.Height, but hacking to get this working
            var       width       = (FrameWidth - 54) / 10;
            var       height      = (FrameHeight - 49) / 4;


            MaterialColorLayer CreateLayer(CommonColor color)
            {
                var selectedColor = color.Lightness > 0.58 ? NSColor.Black : NSColor.White;

                return(new MaterialColorLayer {
                    BackgroundColor = color,
                    ForegroundColor = selectedColor.CGColor,
                    Text = color.Label,
                    FontSize = 12,
                    ContentsScale = NSScreen.MainScreen.BackingScaleFactor,
                    TextAlignmentMode = CATextLayerAlignmentMode.Center,
                });
            }

            foreach (var p in colors)
            {
                var frame         = new CGRect(x, y, width, height);
                var selectedColor = p.Color.Lightness > 0.58 ? NSColor.Black : NSColor.White;
                var isSelected    = ViewModel.Color == p.Color || ViewModel.ColorName == p.Name;
                var l             = new MaterialColorLayer {
                    Frame           = new CGRect(0, 0, width, height),
                    ForegroundColor = selectedColor.CGColor,
                    BackgroundColor = p.Color,
                    CornerRadius    = 3,
                    BorderColor     = new CGColor(.5f, .5f, .5f, .5f),
                    MasksToBounds   = false,
                    IsSelected      = isSelected
                };

                var materialColourButton = new FocusableButton {
                    Frame       = frame,
                    WantsLayer  = true,
                    Layer       = l,
                    ToolTip     = p.Name,
                    Transparent = false,
                    TranslatesAutoresizingMaskIntoConstraints = true,
                };
                if (isSelected)
                {
                    SelectedButton = materialColourButton;
                }

                materialColourButton.Activated += MaterialColourButton_Activated;

                AddSubview(materialColourButton);

                x += width + 6;
                col++;
                if (col >= 10)
                {
                    x   = 0;
                    y  += height + 6;
                    col = 0;
                }
            }

            var colourName = new UnfocusableTextField {
                Frame       = new CGRect(x, y + 6, FrameWidth, PropertyEditorControl.DefaultControlHeight),
                StringValue = ViewModel.ColorName,
                TranslatesAutoresizingMaskIntoConstraints = true,
            };

            AddSubview(colourName);

            y    += 25;
            x     = 0;
            width = FrameWidth / ViewModel.NormalColorScale.Count();

            foreach (var color in ViewModel.NormalColorScale)
            {
                var l          = CreateLayer(color.Value);
                var isSelected = color.Value == ViewModel.NormalColor || color.Value == ViewModel.Color;
                l.ColorType  = MaterialColorType.Normal;
                l.IsSelected = isSelected;
                l.Frame      = new CGRect(0, 0, width, height);

                var normalColourButton = new FocusableButton {
                    Frame       = new CGRect(x, y, width, height),
                    WantsLayer  = true,
                    Layer       = l,
                    ToolTip     = color.ToString(),
                    Transparent = false,
                    TranslatesAutoresizingMaskIntoConstraints = true,
                };
                if (isSelected)
                {
                    SelectedButton = normalColourButton;
                }

                normalColourButton.Activated += MaterialColourButton_Activated;

                AddSubview(normalColourButton);

                x += width;
            }

            var window = Window;

            if (!ViewModel.AccentColorScale.Any())
            {
                if (window != null)
                {
                    window.RecalculateKeyViewLoop();                      // Still needs to be called for the Buttons above.
                    if (SelectedButton != null)
                    {
                        window.MakeFirstResponder(SelectedButton);
                    }
                }
                return;
            }

            y += height + 6;
            x  = 0;

            width = FrameWidth / ViewModel.AccentColorScale.Count();
            foreach (var color in ViewModel.AccentColorScale)
            {
                var l          = CreateLayer(color.Value);
                var isSelected = color.Value == ViewModel.AccentColor || color.Value == ViewModel.Color;
                l.ColorType  = MaterialColorType.Accent;
                l.IsSelected = isSelected;
                l.Frame      = new CGRect(0, 0, width, height);

                var accentColourButton = new FocusableButton {
                    Frame       = new CGRect(x, y, width, height),
                    WantsLayer  = true,
                    Layer       = l,
                    ToolTip     = color.ToString(),
                    Transparent = false,
                    TranslatesAutoresizingMaskIntoConstraints = true,
                };
                if (isSelected)
                {
                    SelectedButton = accentColourButton;
                }

                accentColourButton.Activated += MaterialColourButton_Activated;

                AddSubview(accentColourButton);

                x += width;
            }

            if (window != null)
            {
                window.RecalculateKeyViewLoop();
                if (SelectedButton != null)
                {
                    window.MakeFirstResponder(SelectedButton);
                }
            }
        }
示例#13
0
        // the table is looking for this method, picks it up automagically
        public override NSView GetView(NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item)
        {
            var    facade         = (NSObjectFacade)item;
            var    vm             = facade.Target as PropertyViewModel;
            var    group          = facade.Target as IGroupingList <string, EditorViewModel>;
            string cellIdentifier = (group == null) ? vm.GetType().Name : group.Key;

            // Let's make the columns look pretty
            if (!goldenRatioApplied)
            {
                int    middleColumnWidth = 5;
                nfloat rightColumnWidth  = (outlineView.Frame.Width - middleColumnWidth) / 1.618f;
                nfloat leftColumnWidth   = outlineView.Frame.Width - rightColumnWidth - middleColumnWidth;
                outlineView.TableColumns()[0].Width = leftColumnWidth;
                outlineView.TableColumns()[1].Width = rightColumnWidth;
                goldenRatioApplied = true;
            }

            // Setup view based on the column
            switch (tableColumn.Identifier)
            {
            case PropertyEditorPanel.PropertyListColId:
                var view = (UnfocusableTextField)outlineView.MakeView("label", this);
                if (view == null)
                {
                    view = new UnfocusableTextField {
                        Identifier = "label",
                        Alignment  = NSTextAlignment.Right,
                    };
                }

                view.StringValue = ((group == null) ? vm.Property.Name + ":" : group.Key) ?? String.Empty;

                // Set tooltips only for truncated strings
                var stringWidth = view.AttributedStringValue.Size.Width + 30;
                if (stringWidth > tableColumn.Width)
                {
                    view.ToolTip = vm.Property.Name;
                }

                return(view);

            case PropertyEditorPanel.PropertyEditorColId:
                if (vm == null)
                {
                    return(null);
                }

                var editor = (PropertyEditorControl)outlineView.MakeView(cellIdentifier + "edits", this);
                if (editor == null)
                {
                    editor = GetEditor(vm, outlineView);
                    // If still null we have no editor yet.
                    if (editor == null)
                    {
                        return(new NSView());
                    }
                }

                // we must reset these every time, as the view may have been reused
                editor.TableRow = outlineView.RowForItem(item);

                // Force a row update due to new height, but only when we are non-default
                if (editor.TriggerRowChange)
                {
                    outlineView.NoteHeightOfRowsWithIndexesChanged(new NSIndexSet(editor.TableRow));
                }

                return(editor);
            }

            throw new Exception("Unknown column identifier: " + tableColumn.Identifier);
        }
        protected BaseRectangleEditorControl(IHostResourceProvider hostResources)
            : base(hostResources)
        {
            XLabel = new UnfocusableTextField {
                Font = NSFont.FromFontName(DefaultFontName, DefaultDescriptionLabelFontSize),
                TranslatesAutoresizingMaskIntoConstraints = false,
            };
            XEditor = new NumericSpinEditor <T> (hostResources)
            {
                BackgroundColor = NSColor.Clear,
                Value           = 0.0f
            };
            XEditor.ValueChanged += OnInputUpdated;

            YLabel = new UnfocusableTextField {
                Font = NSFont.FromFontName(DefaultFontName, DefaultDescriptionLabelFontSize),
                TranslatesAutoresizingMaskIntoConstraints = false,
            };
            YEditor = new NumericSpinEditor <T> (hostResources)
            {
                BackgroundColor = NSColor.Clear,
                Value           = 0.0f
            };
            YEditor.ValueChanged += OnInputUpdated;

            WidthLabel = new UnfocusableTextField {
                Font = NSFont.FromFontName(DefaultFontName, DefaultDescriptionLabelFontSize),
                TranslatesAutoresizingMaskIntoConstraints = false,
            };
            WidthEditor = new NumericSpinEditor <T> (hostResources)
            {
                BackgroundColor = NSColor.Clear,
                Value           = 0.0f
            };
            WidthEditor.ValueChanged += OnInputUpdated;

            HeightLabel = new UnfocusableTextField {
                Font = NSFont.FromFontName(DefaultFontName, DefaultDescriptionLabelFontSize),
                TranslatesAutoresizingMaskIntoConstraints = false,
            };
            HeightEditor = new NumericSpinEditor <T> (hostResources)
            {
                BackgroundColor = NSColor.Clear,
                Value           = 0.0f
            };
            HeightEditor.ValueChanged += OnInputUpdated;

            AddSubview(XLabel);
            AddSubview(XEditor);
            AddSubview(YLabel);
            AddSubview(YEditor);
            AddSubview(WidthLabel);
            AddSubview(WidthEditor);
            AddSubview(HeightLabel);
            AddSubview(HeightEditor);

            this.AddConstraints(new[] {
                NSLayoutConstraint.Create(XEditor, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this, NSLayoutAttribute.Top, 1f, 3f),
                NSLayoutConstraint.Create(XEditor, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this, NSLayoutAttribute.Left, 1f, 0f),
                NSLayoutConstraint.Create(XEditor, NSLayoutAttribute.Right, NSLayoutRelation.Equal, YEditor, NSLayoutAttribute.Left, 1f, -10f),
                NSLayoutConstraint.Create(XEditor, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1f, 18),

                NSLayoutConstraint.Create(XLabel, NSLayoutAttribute.Top, NSLayoutRelation.Equal, XEditor, NSLayoutAttribute.Bottom, 1f, -4f),
                NSLayoutConstraint.Create(XLabel, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1f, 18),

                NSLayoutConstraint.Create(YEditor, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this, NSLayoutAttribute.Top, 1f, 3f),
                NSLayoutConstraint.Create(YEditor, NSLayoutAttribute.Right, NSLayoutRelation.Equal, this, NSLayoutAttribute.Right, 1f, 0),
                NSLayoutConstraint.Create(YEditor, NSLayoutAttribute.Width, NSLayoutRelation.Equal, XEditor, NSLayoutAttribute.Width, 1f, 0f),
                NSLayoutConstraint.Create(YEditor, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1f, 18),

                NSLayoutConstraint.Create(YLabel, NSLayoutAttribute.Top, NSLayoutRelation.Equal, XLabel, NSLayoutAttribute.Top, 1f, 0f),
                NSLayoutConstraint.Create(YLabel, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1f, 18),

                NSLayoutConstraint.Create(WidthEditor, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this, NSLayoutAttribute.Top, 1f, 33f),
                NSLayoutConstraint.Create(WidthEditor, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this, NSLayoutAttribute.Left, 1f, 0f),
                NSLayoutConstraint.Create(WidthEditor, NSLayoutAttribute.Right, NSLayoutRelation.Equal, HeightEditor, NSLayoutAttribute.Left, 1f, -10f),
                NSLayoutConstraint.Create(WidthEditor, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1f, 18),

                NSLayoutConstraint.Create(WidthLabel, NSLayoutAttribute.Top, NSLayoutRelation.Equal, WidthEditor, NSLayoutAttribute.Bottom, 1f, -4f),
                NSLayoutConstraint.Create(WidthLabel, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1f, 18),

                NSLayoutConstraint.Create(HeightEditor, NSLayoutAttribute.Top, NSLayoutRelation.Equal, WidthEditor, NSLayoutAttribute.Top, 1f, 0f),
                NSLayoutConstraint.Create(HeightEditor, NSLayoutAttribute.Right, NSLayoutRelation.Equal, this, NSLayoutAttribute.Right, 1f, 0),
                NSLayoutConstraint.Create(HeightEditor, NSLayoutAttribute.Width, NSLayoutRelation.Equal, WidthEditor, NSLayoutAttribute.Width, 1f, 0f),
                NSLayoutConstraint.Create(HeightEditor, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1f, 18),

                NSLayoutConstraint.Create(HeightLabel, NSLayoutAttribute.Top, NSLayoutRelation.Equal, WidthLabel, NSLayoutAttribute.Top, 1f, 0f),
                NSLayoutConstraint.Create(HeightLabel, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1f, 18),


                NSLayoutConstraint.Create(XLabel, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, XEditor.Subviews[0], NSLayoutAttribute.CenterX, 1f, 0),
                NSLayoutConstraint.Create(YLabel, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, YEditor.Subviews[0], NSLayoutAttribute.CenterX, 1f, 0),
                NSLayoutConstraint.Create(WidthLabel, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, WidthEditor.Subviews[0], NSLayoutAttribute.CenterX, 1f, 0),
                NSLayoutConstraint.Create(HeightLabel, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, HeightEditor.Subviews[0], NSLayoutAttribute.CenterX, 1f, 0),
            });

            ViewDidChangeEffectiveAppearance();
        }
        public override NSView GetView(NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item)
        {
            GetVMGroupCellItendifiterFromFacade(item, out EditorViewModel evm, out PanelGroupViewModel group, out var cellIdentifier);

            if (group != null)
            {
                var labelContainer = (NSView)outlineView.MakeView(CategoryIdentifier, this);
                if (labelContainer == null)
                {
                    labelContainer = new NSView {
                        Identifier = CategoryIdentifier,
                    };

                    var disclosure = outlineView.MakeView("NSOutlineViewDisclosureButtonKey", outlineView);
                    disclosure.TranslatesAutoresizingMaskIntoConstraints = false;
                    labelContainer.AddSubview(disclosure);

                    var label = new UnfocusableTextField {
                        TranslatesAutoresizingMaskIntoConstraints = false
                    };
                    labelContainer.AddSubview(label);

                    labelContainer.AddConstraints(new[] {
                        NSLayoutConstraint.Create(disclosure, NSLayoutAttribute.CenterY, NSLayoutRelation.Equal, labelContainer, NSLayoutAttribute.CenterY, 1, 0),
                        NSLayoutConstraint.Create(disclosure, NSLayoutAttribute.Left, NSLayoutRelation.Equal, labelContainer, NSLayoutAttribute.Left, 1, 4),
                        NSLayoutConstraint.Create(label, NSLayoutAttribute.Left, NSLayoutRelation.Equal, disclosure, NSLayoutAttribute.Right, 1, 0),
                        NSLayoutConstraint.Create(label, NSLayoutAttribute.Height, NSLayoutRelation.Equal, labelContainer, NSLayoutAttribute.Height, 1, 0),
                    });
                }

                ((UnfocusableTextField)labelContainer.Subviews[1]).StringValue = group.Category;

                if (this.dataSource.DataContext.GetIsExpanded(group.Category))
                {
                    SynchronizationContext.Current.Post(s => {
                        outlineView.ExpandItem(item);
                    }, null);
                }

                return(labelContainer);
            }

            NSView editorOrContainer = null;

            if (this.firstCache.TryGetValue(cellIdentifier, out IEditorView editor))
            {
                this.firstCache.Remove(cellIdentifier);
                editorOrContainer = (editor.NativeView is PropertyEditorControl) ? new EditorContainer(this.hostResources, editor)
                {
                    Identifier = cellIdentifier
                } : editor.NativeView;
            }
            else
            {
                editorOrContainer = GetEditor(cellIdentifier, evm, outlineView);
                editor            = ((editorOrContainer as EditorContainer)?.EditorView) ?? editorOrContainer as IEditorView;
            }

            if (editorOrContainer is EditorContainer ec)
            {
                ec.ViewModel = evm;
                ec.Label     = evm.Name;

#if DEBUG // Currently only used to highlight which controls haven't been implemented
                if (editor == null)
                {
                    ec.LabelTextColor = NSColor.Red;
                }
#endif
            }

            if (editor != null)
            {
                var ovm = evm as ObjectPropertyViewModel;
                if (ovm != null && editorOrContainer is EditorContainer container)
                {
                    if (container.LeftEdgeView == null)
                    {
                        if (ovm.CanDelve)
                        {
                            container.LeftEdgeView = outlineView.MakeView("NSOutlineViewDisclosureButtonKey", outlineView);
                        }
                    }
                    else if (!ovm.CanDelve)
                    {
                        container.LeftEdgeView = null;
                    }
                }
                else if (!(editorOrContainer is EditorContainer))
                {
                    editor.ViewModel = evm;
                }

                bool openObjectRow = ovm != null && outlineView.IsItemExpanded(item);
                if (!openObjectRow)
                {
                    var parent = outlineView.GetParent(item);
                    openObjectRow = (parent != null && ((NSObjectFacade)parent).Target is ObjectPropertyViewModel);
                }

                SetRowValueBackground(editorOrContainer, openObjectRow);

                // Force a row update due to new height, but only when we are non-default
                if (editor.IsDynamicallySized)
                {
                    nint index = outlineView.RowForItem(item);
                    outlineView.NoteHeightOfRowsWithIndexesChanged(new NSIndexSet(index));
                }
            }
            else if (editorOrContainer is PanelHeaderEditorControl header)
            {
                header.ViewModel = this.dataSource.DataContext;
            }

            return(editorOrContainer);
        }