using Microsoft.Maui; using Microsoft.Maui.Layouts; using Sarand.Net.Mobile.Maui.App; using Sarand.Net.Mobile.Maui.Layouts; using Sarand.Net.Mobile.Maui.Panels; using Sarand.Net.Mobile.Maui.Views; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Sarand.Net.Mobile.Maui.Controls { public class SamTabControl : ContentView, ISamView { // --- Data Members --- private readonly List tabPanels = new List(); private short currentTabIdx = -1; // Main layout to host header and body. private SamStackLayout mainLayout = new SamStackLayout() { Orientation = StackOrientation.Vertical }; // Header layout - horizontal row. private SamFlexLayout headerPanel = new SamFlexLayout() { Direction = FlexDirection.Row, AlignItems = FlexAlignItems.Center, JustifyContent = FlexJustify.Start, HorizontalOptions = LayoutOptions.Start }; // Body - Content view to host tab panel. private SamContentView bodyPanel = new SamContentView(); // --- Construction --- public SamTabControl() { // --- Main layout --- VerticalOptions = LayoutOptions.FillAndExpand; mainLayout.VerticalOptions = LayoutOptions.FillAndExpand; mainLayout.Spacing = 2.0; Content = mainLayout; // --- Header panel --- headerPanel.BackgroundColor = Sam.Visuals.Form.TabControl.HeaderBackgroundColor; mainLayout.Children.Add(headerPanel); // --- Default font size --- DefaultHeaderFontSize = new Label().FontSize; HeaderFontSize = DefaultHeaderFontSize; // --- Body panel --- bodyPanel.HorizontalOptions = LayoutOptions.Fill; bodyPanel.VerticalOptions = LayoutOptions.FillAndExpand; bodyPanel.BackgroundColor = Sam.Visuals.Form.TabControl.BodyBackgroundColor; mainLayout.Children.Add(bodyPanel); } // --- Properties --- // Header. public Color HeaderBackgroundColor { get { return headerPanel.BackgroundColor; } set { headerPanel.BackgroundColor = value; } } public Color CaptionBackgroundColor { get; set; } = Sam.Visuals.Form.TabControl.CaptionBackgroundColor; public double DefaultHeaderFontSize { get; } public double HeaderFontSize { get; set; } public double HeaderMarginBottom { get { return mainLayout.Spacing; } set { if (mainLayout.Spacing == value) return; mainLayout.Spacing = value; } } public Thickness HeaderPadding { get { return mainLayout.Padding; } set { if (mainLayout.Padding == value) return; mainLayout.Padding = value; } } public Thickness HeaderCaptionPadding { get; set; } = new Thickness(12.0, 4.0); public double HeaderCaptionSpacing { get; set; } = 4.0; // Tab panels. public Color BodyBackgroundColor { get { return bodyPanel.BackgroundColor; } set { bodyPanel.BackgroundColor = value; } } public int PanelCount { get { return tabPanels.Count; } } public short TabPanelIndex { get { return currentTabIdx; } set { ChangeTabPanel(value); } } // --- Tab panels --- public void ClearPanels() { tabPanels.Clear(); RefreshLayout(); } public void AddPanel(String caption, SamContentView panel) { AddPanel(new SamTabPanel(caption, panel)); } public void AddPanel(SamTabPanel tabPanel) { AddPanels(new List() { tabPanel }); } public void AddPanels(IEnumerable tabPanels) { this.tabPanels.AddRange(tabPanels); RefreshLayout(); } // --- Refresh layout --- private void RefreshLayout() { // Clear existing components. headerPanel.Children.Clear(); bodyPanel.Content = null; // Add each Tab panel in turn. for (short tabPanelIdx = 0; tabPanelIdx < tabPanels.Count; tabPanelIdx++) { short tabPanelIdx_Local = tabPanelIdx; // Loop closure. SamTabPanel tabPanel = tabPanels[tabPanelIdx]; // Header caption. SamContentView captionPanel = new SamContentView() { Padding = HeaderCaptionPadding, BackgroundColor = CaptionBackgroundColor, HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.FillAndExpand }; if (tabPanelIdx > 0) captionPanel.Margin = new Thickness(HeaderCaptionSpacing, 0, 0, 0); SamLabel captionLabel = new SamLabel() { Text = tabPanel.Caption, FontSize = HeaderFontSize }; captionPanel.Content = captionLabel; headerPanel.Children.Add(captionPanel); // Tap Gesture. var tapGestureRecognizer = new TapGestureRecognizer(); tapGestureRecognizer.Tapped += (s, e) => { ChangeTabPanel(tabPanelIdx_Local); }; captionPanel.GestureRecognizers.Add(tapGestureRecognizer); } // Current tab retains previous value if still valid (in panel range), // is restricted to the range 0 to number of panels - 1 if there are panels, // or -1 if no panels. currentTabIdx = (short)(tabPanels.Count > 0 ? Math.Max(0, Math.Min(tabPanels.Count - 1, currentTabIdx)) : -1); if (tabPanels.Count > 0) ChangeTabPanel(currentTabIdx); } // --- Change tab panel --- private void ChangeTabPanel(short tabPanelIdx) { // Validate requested panel index. if (tabPanelIdx < 0 || tabPanelIdx >= tabPanels.Count) throw new IndexOutOfRangeException("Tab panel index must be between 0 & " + (tabPanels.Count - 1) + ". Supplied value: " + tabPanelIdx); // Highlight selected tab panel header caption. for (short headerPanelIdx = 0; headerPanelIdx < headerPanel.Children.Count; headerPanelIdx++) { // View. View? headerPanelView = headerPanel.Children[headerPanelIdx] as View; // Label. Label? headerPanelLabel = (headerPanelView as Label); if (headerPanelLabel == null && headerPanelView is ContentView) headerPanelLabel = ((ContentView)headerPanelView).Content as Label; if (headerPanelLabel != null) { if (headerPanelIdx == tabPanelIdx) headerPanelLabel.FontAttributes = FontAttributes.Bold; else headerPanelLabel.FontAttributes = FontAttributes.None; } } // Display selected tab panel. bodyPanel.Content = tabPanels[tabPanelIdx]; currentTabIdx = tabPanelIdx; } // --- Component state --- public void ConfigureComponents() { } public void SetControlActivity(bool enabled) { if (IsEnabled != enabled) IsEnabled = enabled; SetControlsReadOnly(); } public void SetControlsReadOnly() { } // --- The End --- } }