using System; using AppKit; using Foundation; using Xamarin.PropertyEditing.ViewModels; namespace Xamarin.PropertyEditing.Mac { internal abstract class PropertyEditorControl : NSView, IEditorView { protected PropertyEditorControl (IHostResourceProvider hostResources) { if (hostResources == null) throw new ArgumentNullException (nameof (hostResources)); HostResources = hostResources; } public IHostResourceProvider HostResources { get; } public string Label { get; set; } public abstract NSView FirstKeyView { get; } public abstract NSView LastKeyView { get; } public NSTableView TableView { get; set; } public const int DefaultControlHeight = 24; public const int DefaultFontSize = 11; public const int DefaultPropertyLabelFontSize = 11; public const int DefaultDescriptionLabelFontSize = 9; public const string DefaultFontName = ".AppleSystemUIFont"; public const float DefaultButtonWidth = 70f; public virtual bool IsDynamicallySized => false; PropertyViewModel viewModel; public PropertyViewModel ViewModel { get { return this.viewModel; } set { if (this.ViewModel == value) return; PropertyViewModel oldModel = this.viewModel; if (oldModel != null) { oldModel.PropertyChanged -= OnPropertyChanged; } this.viewModel = value; OnViewModelChanged (oldModel); if (this.viewModel != null) { this.viewModel.PropertyChanged += OnPropertyChanged; } } } EditorViewModel IEditorView.ViewModel { get { return this.ViewModel; } set { ViewModel = (PropertyViewModel)value; } } NSView INativeContainer.NativeView => this; [Export ("_primitiveSetDefaultNextKeyView:")] public void SetDefaultNextKeyView (NSView child) { if (child == FirstKeyView || child == LastKeyView) { UpdateKeyViews (); } } public virtual bool NeedsPropertyButton => true; public void UpdateKeyViews () { if (TableView != null) { nint row = TableView.RowForView (this); if (row <= 0) return; NSView view; PropertyEditorControl ctrl = null; do { row--; view = TableView.GetView (0, row, makeIfNecessary: false); if (view is PropertyEditorControl pec) { // This is to include the CategoryContainer ctrl = pec; } else { ctrl = (view as EditorContainer)?.EditorView?.NativeView as PropertyEditorControl; } } while (row > 0 && ctrl == null); if (ctrl != null) { ctrl.LastKeyView.NextKeyView = FirstKeyView; ctrl.UpdateKeyViews (); } else if (row == 0 && view is PanelHeaderEditorControl header) { header.SetNextKeyView (FirstKeyView); } } } /// You should treat the implementation of this as static. public virtual nint GetHeight (EditorViewModel vm) { return 24; } protected virtual void UpdateValue () { } protected virtual void OnViewModelChanged (PropertyViewModel oldModel) { if (ViewModel != null) { SetEnabled (); UpdateValue (); UpdateAccessibilityValues (); } } protected virtual void OnPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (e.PropertyName == "Value") { UpdateValue (); } } protected virtual void SetEnabled () { } protected virtual void UpdateAccessibilityValues () { } protected virtual void AppearanceChanged () { } public sealed override void ViewDidChangeEffectiveAppearance () { base.ViewDidChangeEffectiveAppearance (); AppearanceChanged (); } } internal abstract class PropertyEditorControl : PropertyEditorControl where TViewModel : PropertyViewModel { public PropertyEditorControl (IHostResourceProvider hostResources) : base (hostResources) { } internal new TViewModel ViewModel { get { return (TViewModel)base.ViewModel; } set { base.ViewModel = value; } } } }