зеркало из https://github.com/DeGsoft/maui-linux.git
401 строка
9.6 KiB
C#
401 строка
9.6 KiB
C#
using System;
|
|
using System.Collections.Specialized;
|
|
using System.ComponentModel;
|
|
using AppKit;
|
|
using CoreGraphics;
|
|
using Xamarin.Forms.Internals;
|
|
using Xamarin.Forms.PlatformConfiguration.macOSSpecific;
|
|
|
|
namespace Xamarin.Forms.Platform.MacOS
|
|
{
|
|
public class TabbedPageRenderer : NSTabViewController, IVisualElementRenderer, IEffectControlProvider
|
|
{
|
|
const float DefaultImageSizeSegmentedButton = 19;
|
|
const int TabHolderHeight = 30;
|
|
|
|
bool _disposed;
|
|
bool _updatingControllers;
|
|
bool _barBackgroundColorWasSet;
|
|
bool _barTextColorWasSet;
|
|
bool _defaultBarTextColorSet;
|
|
bool _defaultBarColorSet;
|
|
VisualElementTracker _tracker;
|
|
bool _loaded;
|
|
Size _queuedSize;
|
|
|
|
|
|
public VisualElement Element { get; private set; }
|
|
|
|
public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
|
|
|
|
public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
|
|
{
|
|
return NativeView.GetSizeRequest(widthConstraint, heightConstraint);
|
|
}
|
|
|
|
public NSView NativeView => View;
|
|
|
|
public void SetElement(VisualElement element)
|
|
{
|
|
var oldElement = Element;
|
|
Element = element;
|
|
|
|
if (oldElement != null)
|
|
{
|
|
oldElement.PropertyChanged -= OnPropertyChanged;
|
|
var tabbedPage = oldElement as TabbedPage;
|
|
if (tabbedPage != null) tabbedPage.PagesChanged -= OnPagesChanged;
|
|
}
|
|
|
|
if (element != null)
|
|
{
|
|
if (_tracker == null)
|
|
{
|
|
_tracker = new VisualElementTracker(this);
|
|
_tracker.NativeControlUpdated += (sender, e) => UpdateNativeWidget();
|
|
}
|
|
}
|
|
|
|
OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
|
|
|
|
ConfigureTabView();
|
|
|
|
OnPagesChanged(null, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
|
|
|
Tabbed.PropertyChanged += OnPropertyChanged;
|
|
Tabbed.PagesChanged += OnPagesChanged;
|
|
|
|
UpdateBarBackgroundColor();
|
|
|
|
UpdateBarTextColor();
|
|
|
|
EffectUtilities.RegisterEffectControlProvider(this, oldElement, element);
|
|
}
|
|
|
|
Page Page => Element as Page;
|
|
|
|
void IEffectControlProvider.RegisterEffect(Effect effect)
|
|
{
|
|
var platformEffect = effect as PlatformEffect;
|
|
if (platformEffect != null)
|
|
platformEffect.SetContainer(View);
|
|
}
|
|
|
|
public void SetElementSize(Size size)
|
|
{
|
|
if (_loaded)
|
|
Element.Layout(new Rectangle(Element.X, Element.Y, size.Width, size.Height));
|
|
else
|
|
_queuedSize = size;
|
|
}
|
|
|
|
public NSViewController ViewController => this;
|
|
|
|
public override void ViewWillLayout()
|
|
{
|
|
base.ViewWillLayout();
|
|
|
|
if (Element == null)
|
|
return;
|
|
|
|
if (!Element.Bounds.IsEmpty)
|
|
View.Frame = new System.Drawing.RectangleF((float)Element.X, (float)Element.Y, (float)Element.Width, (float)Element.Height);
|
|
|
|
var frame = View.Frame;
|
|
Page.ContainerArea = new Rectangle(0, 0, frame.Width, frame.Height - TabHolderHeight);
|
|
|
|
if (!_queuedSize.IsZero)
|
|
{
|
|
Element.Layout(new Rectangle(Element.X, Element.Y, _queuedSize.Width, _queuedSize.Height));
|
|
_queuedSize = Size.Zero;
|
|
}
|
|
|
|
_loaded = true;
|
|
}
|
|
|
|
|
|
public override nint SelectedTabViewItemIndex
|
|
{
|
|
get { return base.SelectedTabViewItemIndex; }
|
|
set
|
|
{
|
|
base.SelectedTabViewItemIndex = value;
|
|
if (!_updatingControllers)
|
|
UpdateCurrentPage();
|
|
}
|
|
}
|
|
|
|
public override void ViewDidAppear()
|
|
{
|
|
Page.SendAppearing();
|
|
base.ViewDidAppear();
|
|
}
|
|
|
|
public override void ViewDidDisappear()
|
|
{
|
|
base.ViewDidDisappear();
|
|
Page.SendDisappearing();
|
|
}
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (disposing && !_disposed)
|
|
{
|
|
_disposed = true;
|
|
Page.SendDisappearing();
|
|
Tabbed.PropertyChanged -= OnPropertyChanged;
|
|
Tabbed.PagesChanged -= OnPagesChanged;
|
|
|
|
if (_tracker != null)
|
|
{
|
|
_tracker.Dispose();
|
|
_tracker = null;
|
|
}
|
|
}
|
|
|
|
base.Dispose(disposing);
|
|
}
|
|
|
|
protected virtual void ConfigureTabView()
|
|
{
|
|
View.WantsLayer = true;
|
|
TabView.WantsLayer = true;
|
|
TabView.DrawsBackground = false;
|
|
var tabStyle = Tabbed.OnThisPlatform().GetTabsStyle();
|
|
switch (tabStyle)
|
|
{
|
|
case TabsStyle.OnNavigation:
|
|
case TabsStyle.Hidden:
|
|
TabStyle = NSTabViewControllerTabStyle.Unspecified;
|
|
break;
|
|
case TabsStyle.Icons:
|
|
TabStyle = NSTabViewControllerTabStyle.Toolbar;
|
|
break;
|
|
case TabsStyle.OnBottom:
|
|
TabStyle = NSTabViewControllerTabStyle.SegmentedControlOnBottom;
|
|
break;
|
|
default:
|
|
TabStyle = NSTabViewControllerTabStyle.SegmentedControlOnTop;
|
|
break;
|
|
}
|
|
|
|
TabView.TabViewType = NSTabViewType.NSNoTabsNoBorder;
|
|
}
|
|
|
|
protected virtual void OnElementChanged(VisualElementChangedEventArgs e)
|
|
{
|
|
ElementChanged?.Invoke(this, e);
|
|
}
|
|
|
|
protected virtual NSTabViewItem GetTabViewItem(Page page, IVisualElementRenderer pageRenderer)
|
|
{
|
|
var tvi = new NSTabViewItem { ViewController = pageRenderer.ViewController, Label = page.Title ?? "" };
|
|
if (!string.IsNullOrEmpty (page.Icon)) {
|
|
var image = GetTabViewItemIcon (page.Icon);
|
|
if (image != null)
|
|
tvi.Image = image;
|
|
}
|
|
return tvi;
|
|
}
|
|
|
|
protected virtual NSImage GetTabViewItemIcon(string imageName)
|
|
{
|
|
var image = NSImage.ImageNamed (imageName);
|
|
if(image == null)
|
|
image = new NSImage (imageName);
|
|
|
|
if (image == null)
|
|
return null;
|
|
|
|
bool shouldResize = TabStyle == NSTabViewControllerTabStyle.SegmentedControlOnTop ||
|
|
TabStyle == NSTabViewControllerTabStyle.SegmentedControlOnBottom;
|
|
if (shouldResize)
|
|
image = image.ResizeTo(new CGSize(DefaultImageSizeSegmentedButton, DefaultImageSizeSegmentedButton));
|
|
return image;
|
|
}
|
|
|
|
protected virtual void UpdateNativeWidget()
|
|
{
|
|
TabView.Layout();
|
|
}
|
|
|
|
protected TabbedPage Tabbed => (TabbedPage)Element;
|
|
|
|
void OnPagePropertyChanged(object sender, PropertyChangedEventArgs e)
|
|
{
|
|
if (e.PropertyName == Page.TitleProperty.PropertyName)
|
|
{
|
|
var page = (Page)sender;
|
|
var index = TabbedPage.GetIndex(page);
|
|
TabViewItems[index].Label = page.Title;
|
|
}
|
|
else if (e.PropertyName == Page.IconProperty.PropertyName)
|
|
{
|
|
var page = (Page)sender;
|
|
|
|
var index = TabbedPage.GetIndex(page);
|
|
TabViewItems[index].Label = page.Title;
|
|
|
|
if (!string.IsNullOrEmpty(page.Icon))
|
|
{
|
|
TabViewItems[index].Image = new NSImage(page.Icon);
|
|
}
|
|
else if (TabViewItems[index].Image != null)
|
|
{
|
|
TabViewItems[index].Image = new NSImage();
|
|
}
|
|
}
|
|
}
|
|
|
|
void OnPagesChanged(object sender, NotifyCollectionChangedEventArgs e)
|
|
{
|
|
e.Apply((o, i, c) => SetupPage((Page)o, i), (o, i) => TeardownPage((Page)o), Reset);
|
|
|
|
SetControllers();
|
|
|
|
UpdateChildrenOrderIndex();
|
|
|
|
SetSelectedTabViewItem();
|
|
}
|
|
|
|
void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
|
|
{
|
|
if (e.PropertyName == nameof(TabbedPage.CurrentPage))
|
|
{
|
|
var current = Tabbed.CurrentPage;
|
|
if (current == null)
|
|
return;
|
|
|
|
SetSelectedTabViewItem();
|
|
}
|
|
else if (e.PropertyName == TabbedPage.BarBackgroundColorProperty.PropertyName)
|
|
UpdateBarBackgroundColor();
|
|
else if (e.PropertyName == TabbedPage.BarTextColorProperty.PropertyName)
|
|
UpdateBarTextColor();
|
|
}
|
|
|
|
void Reset()
|
|
{
|
|
var i = 0;
|
|
foreach (var page in Tabbed.Children)
|
|
SetupPage(page, i++);
|
|
}
|
|
|
|
void SetControllers()
|
|
{
|
|
_updatingControllers = true;
|
|
for (var i = 0; i < Element.LogicalChildren.Count; i++)
|
|
{
|
|
var child = Element.LogicalChildren[i];
|
|
var page = child as Page;
|
|
if (page == null)
|
|
continue;
|
|
|
|
var pageRenderer = Platform.GetRenderer(page);
|
|
if (pageRenderer != null)
|
|
{
|
|
pageRenderer.ViewController.Identifier = i.ToString();
|
|
|
|
NSTabViewItem newTvi = GetTabViewItem(page, pageRenderer);
|
|
|
|
AddTabViewItem(newTvi);
|
|
}
|
|
}
|
|
_updatingControllers = false;
|
|
}
|
|
|
|
void SetupPage(Page page, int index)
|
|
{
|
|
var renderer = Platform.GetRenderer(page);
|
|
if (renderer == null)
|
|
{
|
|
renderer = Platform.CreateRenderer(page);
|
|
Platform.SetRenderer(page, renderer);
|
|
}
|
|
|
|
renderer.ViewController.Identifier = index.ToString();
|
|
|
|
page.PropertyChanged += OnPagePropertyChanged;
|
|
}
|
|
|
|
void TeardownPage(Page page)
|
|
{
|
|
page.PropertyChanged -= OnPagePropertyChanged;
|
|
|
|
Platform.SetRenderer(page, null);
|
|
}
|
|
|
|
void SetSelectedTabViewItem()
|
|
{
|
|
if (Tabbed.CurrentPage == null)
|
|
return;
|
|
var selectedIndex = TabbedPage.GetIndex(Tabbed.CurrentPage);
|
|
SelectedTabViewItemIndex = selectedIndex;
|
|
}
|
|
|
|
void UpdateChildrenOrderIndex()
|
|
{
|
|
for (var i = 0; i < TabViewItems.Length; i++)
|
|
{
|
|
int originalIndex;
|
|
if (int.TryParse(TabViewItems[i].ViewController.Identifier, out originalIndex))
|
|
{
|
|
var page = Page.InternalChildren[originalIndex];
|
|
TabbedPage.SetIndex(page as Page, i);
|
|
}
|
|
}
|
|
}
|
|
|
|
void UpdateCurrentPage()
|
|
{
|
|
var count = Page.InternalChildren.Count;
|
|
Tabbed.CurrentPage = SelectedTabViewItemIndex >= 0 && SelectedTabViewItemIndex < count
|
|
? Tabbed.GetPageByIndex((int)SelectedTabViewItemIndex)
|
|
: null;
|
|
}
|
|
|
|
//TODO: Implement UpdateBarBackgroundColor
|
|
void UpdateBarBackgroundColor()
|
|
{
|
|
if (Tabbed == null || TabView == null)
|
|
return;
|
|
|
|
var barBackgroundColor = Tabbed.BarBackgroundColor;
|
|
var isDefaultColor = barBackgroundColor.IsDefault;
|
|
|
|
if (isDefaultColor && !_barBackgroundColorWasSet)
|
|
return;
|
|
|
|
if (!_defaultBarColorSet)
|
|
{
|
|
//_defaultBarColor = TabView.color;
|
|
_defaultBarColorSet = true;
|
|
}
|
|
|
|
if (!isDefaultColor)
|
|
_barBackgroundColorWasSet = true;
|
|
}
|
|
|
|
//TODO: Implement UpdateBarTextColor
|
|
void UpdateBarTextColor()
|
|
{
|
|
if (Tabbed == null || TabView == null)
|
|
return;
|
|
|
|
var barTextColor = Tabbed.BarTextColor;
|
|
var isDefaultColor = barTextColor.IsDefault;
|
|
|
|
if (isDefaultColor && !_barTextColorWasSet)
|
|
return;
|
|
|
|
if (!_defaultBarTextColorSet)
|
|
{
|
|
// _defaultBarTextColor = TabBar.TintColor;
|
|
_defaultBarTextColorSet = true;
|
|
}
|
|
|
|
if (!isDefaultColor)
|
|
_barTextColorWasSet = true;
|
|
}
|
|
}
|
|
} |