2020-08-11 22:26:49 +08:00
using System ;
2020-04-16 12:05:59 +08:00
using System.Collections.Generic ;
using System.Linq ;
using System.Threading.Tasks ;
2020-08-11 22:26:49 +08:00
using AntDesign.JsInterop ;
using Microsoft.AspNetCore.Components ;
using Microsoft.AspNetCore.Components.Web ;
2020-04-16 12:05:59 +08:00
2020-05-29 00:33:49 +08:00
namespace AntDesign
2020-04-16 12:05:59 +08:00
{
2020-06-07 19:41:00 +08:00
public partial class Tabs : AntDomComponentBase
2020-04-16 12:05:59 +08:00
{
private const string PrefixCls = "ant-tabs" ;
2020-06-07 19:41:00 +08:00
private bool IsHorizontal { get = > TabPosition = = AntDesign . TabPosition . Top | | TabPosition = = AntDesign . TabPosition . Bottom ; }
2020-06-10 13:34:51 +08:00
//private ClassMapper _barClassMapper = new ClassMapper();
//private ClassMapper _prevClassMapper = new ClassMapper();
//private ClassMapper _nextClassMapper = new ClassMapper();
//private ClassMapper _navClassMapper = new ClassMapper();
2020-06-07 19:41:00 +08:00
private TabPane _activePane ;
2020-06-10 13:34:51 +08:00
2020-06-07 19:41:00 +08:00
private TabPane _renderedActivePane ;
2020-06-10 13:34:51 +08:00
2020-04-16 12:05:59 +08:00
private ElementReference _scrollTabBar ;
private ElementReference _tabBars ;
2020-06-10 13:34:51 +08:00
2020-04-16 12:05:59 +08:00
private string _inkStyle ;
2020-06-10 13:34:51 +08:00
2020-04-16 12:05:59 +08:00
private string _navStyle ;
2020-06-10 13:34:51 +08:00
//private string _contentStyle;
//private bool? _prevIconEnabled;
//private bool? _nextIconEnabled;
private string _operationClass ;
private string _tabsNavWarpPingClass ;
private string _operationStyle ;
2020-04-16 12:05:59 +08:00
private int _navIndex ;
2020-06-10 13:34:51 +08:00
private int _scrollOffset ;
2020-04-16 12:05:59 +08:00
private int _navTotal ;
private int _navSection ;
private bool _needRefresh ;
2020-12-03 13:44:49 +08:00
private bool _afterFirstRender ;
private bool _activePaneChanged ;
2020-11-30 10:53:41 +08:00
2020-06-07 19:41:00 +08:00
internal List < TabPane > _panes = new List < TabPane > ( ) ;
2020-04-16 12:05:59 +08:00
#region Parameters
[Parameter]
public RenderFragment ChildContent { get ; set ; }
private string _activeKey ;
/// <summary>
2020-06-07 19:41:00 +08:00
/// Current <see cref="TabPane"/>'s <see cref="TabPane.Key"/>
2020-04-16 12:05:59 +08:00
/// </summary>
[Parameter]
public string ActiveKey
{
get
{
return _activeKey ;
}
set
{
if ( _activeKey ! = value )
{
2020-11-30 10:53:41 +08:00
_activeKey = value ;
2020-08-11 22:26:49 +08:00
if ( _panes . Count = = 0 )
return ;
2020-11-30 10:53:41 +08:00
var tabPane = _panes . Find ( p = > p . Key = = value ) ;
2020-08-11 22:26:49 +08:00
if ( tabPane = = null )
return ;
2020-07-08 23:01:00 +08:00
ActivatePane ( tabPane ) ;
2020-04-16 12:05:59 +08:00
}
}
}
2020-07-22 00:30:31 +08:00
[Parameter]
public EventCallback < string > ActiveKeyChanged { get ; set ; }
2020-04-16 12:05:59 +08:00
/// <summary>
2020-06-07 19:41:00 +08:00
/// Whether to change tabs with animation. Only works while <see cref="TabPosition"/> = <see cref="TabPosition.Top"/> or <see cref="TabPosition.Bottom"/>
2020-04-16 12:05:59 +08:00
/// </summary>
[Parameter]
public bool Animated { get ; set ; } = true ;
/// <summary>
/// Replace the TabBar
/// </summary>
[Parameter]
public object RenderTabBar { get ; set ; }
/// <summary>
2020-06-07 19:41:00 +08:00
/// Initial active <see cref="TabPane"/>'s <see cref="TabPane.Key"/>, if <see cref="ActiveKey"/> is not set
2020-04-16 12:05:59 +08:00
/// </summary>
[Parameter]
public string DefaultActiveKey { get ; set ; }
/// <summary>
2020-06-07 19:41:00 +08:00
/// Hide plus icon or not. Only works while <see cref="Type"/> = <see cref="TabType.EditableCard"/>
2020-04-16 12:05:59 +08:00
/// </summary>
[Parameter]
public bool HideAdd { get ; set ; } = false ;
/// <summary>
/// Preset tab bar size
/// </summary>
[Parameter]
2020-06-07 19:41:00 +08:00
public string Size { get ; set ; } = TabSize . Default ;
2020-04-16 12:05:59 +08:00
/// <summary>
/// Extra content in tab bar
/// </summary>
[Parameter]
public RenderFragment TabBarExtraContent { get ; set ; }
/// <summary>
/// The gap between tabs
/// </summary>
[Parameter]
public int TabBarGutter { get ; set ; }
/// <summary>
/// Tab bar style object
/// </summary>
[Parameter]
public string TabBarStyle { get ; set ; }
/// <summary>
/// Position of tabs
/// </summary>
[Parameter]
2020-06-07 19:41:00 +08:00
public string TabPosition { get ; set ; } = AntDesign . TabPosition . Top ;
2020-04-16 12:05:59 +08:00
/// <summary>
/// Basic style of tabs
/// </summary>
[Parameter]
2020-06-07 19:41:00 +08:00
public string Type { get ; set ; } = TabType . Line ;
2020-04-16 12:05:59 +08:00
/// <summary>
/// Callback executed when active tab is changed
/// </summary>
[Parameter]
2020-08-11 22:26:49 +08:00
public EventCallback < string > OnChange { get ; set ; }
2020-04-16 12:05:59 +08:00
/// <summary>
2020-06-07 19:41:00 +08:00
/// Callback executed when tab is added or removed. Only works while <see cref="Type"/> = <see cref="TabType.EditableCard"/>
2020-04-16 12:05:59 +08:00
/// </summary>
[Parameter]
2020-11-30 10:53:41 +08:00
public Func < string , string , Task < bool > > OnEdit { get ; set ; } = ( key , action ) = > Task . FromResult ( true ) ;
[Parameter]
public EventCallback OnAddClick { get ; set ; }
[Parameter]
public EventCallback < string > AfterTabCreated { get ; set ; }
2020-04-16 12:05:59 +08:00
/// <summary>
/// Callback executed when next button is clicked
/// </summary>
[Parameter]
public EventCallback OnNextClick { get ; set ; }
/// <summary>
/// Callback executed when prev button is clicked
/// </summary>
[Parameter]
public EventCallback OnPrevClick { get ; set ; }
/// <summary>
/// Callback executed when tab is clicked
/// </summary>
[Parameter]
2020-08-11 22:26:49 +08:00
public EventCallback < string > OnTabClick { get ; set ; }
2020-04-16 12:05:59 +08:00
/// <summary>
/// Whether to turn on keyboard navigation
/// </summary>
[Parameter]
public bool Keyboard { get ; set ; } = true ;
2020-04-16 20:53:03 +08:00
[Parameter]
public bool Draggable { get ; set ; }
2020-09-20 10:43:40 +08:00
[CascadingParameter]
public Card Card { get ; set ; }
2020-04-16 12:05:59 +08:00
#endregion Parameters
2020-12-03 13:44:49 +08:00
protected override void OnInitialized ( )
{
base . OnInitialized ( ) ;
ClassMapper . Clear ( )
. Add ( PrefixCls )
2020-12-18 15:59:25 +08:00
. GetIf ( ( ) = > $"{PrefixCls}-{TabPosition}" , ( ) = > TabPosition . IsIn ( AntDesign . TabPosition . Top , AntDesign . TabPosition . Bottom , AntDesign . TabPosition . Left , AntDesign . TabPosition . Right ) )
. GetIf ( ( ) = > $"{PrefixCls}-{Type}" , ( ) = > Type . IsIn ( TabType . Card , TabType . EditableCard , TabType . Line ) )
2020-12-03 13:44:49 +08:00
. If ( $"{PrefixCls}-large" , ( ) = > Size = = TabSize . Large | | Card ! = null )
. If ( $"{PrefixCls}-head-tabs" , ( ) = > Card ! = null )
. If ( $"{PrefixCls}-small" , ( ) = > Size = = TabSize . Small )
. GetIf ( ( ) = > $"{PrefixCls}-{TabType.Card}" , ( ) = > Type = = TabType . EditableCard )
2021-03-12 17:02:11 +08:00
. If ( $"{PrefixCls}-no-animation" , ( ) = > ! Animated )
. If ( $"{PrefixCls}-rtl" , ( ) = > RTL ) ;
2020-12-03 13:44:49 +08:00
}
2020-04-16 12:05:59 +08:00
public override Task SetParametersAsync ( ParameterView parameters )
{
_needRefresh = true ;
_renderedActivePane = null ;
string type = parameters . GetValueOrDefault < string > ( nameof ( Type ) ) ;
2020-06-07 19:41:00 +08:00
if ( type = = TabType . Card )
2020-04-16 12:05:59 +08:00
{
// according to ant design documents,
// Animated default to false when type="card"
Animated = false ;
}
string position = parameters . GetValueOrDefault < string > ( nameof ( TabPosition ) ) ;
if ( ! string . IsNullOrEmpty ( position ) )
{
_navIndex = 0 ;
}
return base . SetParametersAsync ( parameters ) ;
}
protected override void OnParametersSet ( )
{
base . OnParametersSet ( ) ;
2020-06-10 13:34:51 +08:00
//if (Type == TabType.EditableCard && !HideAdd)
//{
// TabBarExtraContent = (b) =>
// {
// b.OpenComponent<Icon>(0);
// b.AddAttribute(1, "Type", "plus");
// b.AddAttribute(2, "class", $"{PrefixCls}-new-tab");
// b.AddAttribute(3, "onclick", EventCallback.Factory.Create(this, AddTabPane));
// b.CloseComponent();
// };
//}
2020-04-16 12:05:59 +08:00
2020-06-10 13:34:51 +08:00
//_barClassMapper.Clear()
// .Add($"{PrefixCls}-bar")
// .Add($"{PrefixCls}-{TabPosition}-bar")
// .Add($"{PrefixCls}-{Type}-bar")
// .If($"{PrefixCls}-{TabType.Card}-bar", () => Type == TabType.EditableCard)
// .If($"{PrefixCls}-large-bar", () => Size == TabSize.Large)
// .If($"{PrefixCls}-small-bar", () => Size == TabSize.Small);
//_prevClassMapper.Clear()
// .Add($"{PrefixCls}-tab-prev")
// .If($"{PrefixCls}-tab-btn-disabled", () => !_prevIconEnabled.HasValue || !_prevIconEnabled.Value)
// .If($"{PrefixCls}-tab-arrow-show", () => _prevIconEnabled.HasValue);
//_nextClassMapper.Clear()
// .Add($"{PrefixCls}-tab-next")
// .If($"{PrefixCls}-tab-btn-disabled", () => !_nextIconEnabled.HasValue || !_nextIconEnabled.Value)
// .If($"{PrefixCls}-tab-arrow-show", () => _nextIconEnabled.HasValue);
//_navClassMapper.Clear()
// .Add($"{PrefixCls}-nav-container")
// .If($"{PrefixCls}-nav-container-scrolling", () => _prevIconEnabled.HasValue || _nextIconEnabled.HasValue);
//_navStyle = "transform: translate3d(0px, 0px, 0px);";
_inkStyle = "left: 0px; width: 0px;" ;
//_contentStyle = "margin-" + (IsHorizontal ? "left" : "top") + ": 0;";
2020-04-16 12:05:59 +08:00
}
/// <summary>
2020-12-03 13:44:49 +08:00
/// Add <see cref="TabPane"/> to <see cref="Tabs"/>
2020-04-16 12:05:59 +08:00
/// </summary>
/// <param name="tabPane">The AntTabPane to be added</param>
/// <exception cref="ArgumentNullException">Key is null</exception>
/// <exception cref="ArgumentException">An AntTabPane with the same key already exists</exception>
2020-06-07 19:41:00 +08:00
internal void AddTabPane ( TabPane tabPane )
2020-04-16 12:05:59 +08:00
{
if ( string . IsNullOrEmpty ( tabPane . Key ) )
{
2020-04-24 18:32:50 +08:00
throw new ArgumentNullException ( nameof ( tabPane ) , "Key is null" ) ;
2020-04-16 12:05:59 +08:00
}
2020-04-24 18:32:50 +08:00
if ( _panes . Select ( p = > p . Key ) . Contains ( tabPane . Key ) )
2020-04-16 12:05:59 +08:00
{
throw new ArgumentException ( "An AntTabPane with the same key already exists" ) ;
}
2020-04-24 18:32:50 +08:00
_panes . Add ( tabPane ) ;
2020-11-30 10:53:41 +08:00
}
2020-12-03 13:44:49 +08:00
internal void Complete ( TabPane content )
2020-11-30 10:53:41 +08:00
{
var pane = _panes . FirstOrDefault ( x = > x . Key = = content . Key ) ;
if ( pane ! = null & & pane . IsComplete ( ) )
2020-04-16 12:05:59 +08:00
{
2020-12-03 13:44:49 +08:00
if ( _panes . Any ( x = > ! x . IsComplete ( ) ) )
2020-06-10 21:44:21 +08:00
{
2020-12-03 13:44:49 +08:00
return ;
2020-06-10 21:44:21 +08:00
}
2020-12-03 13:44:49 +08:00
if ( ! string . IsNullOrWhiteSpace ( ActiveKey ) )
2020-08-11 22:26:49 +08:00
{
2020-11-30 10:53:41 +08:00
var activedPane = _panes . Find ( x = > x . Key = = ActiveKey ) ;
if ( activedPane ? . IsActive = = false )
2020-08-11 22:26:49 +08:00
{
2020-11-30 10:53:41 +08:00
ActivatePane ( activedPane ) ;
}
}
2020-12-03 13:44:49 +08:00
else if ( ! string . IsNullOrWhiteSpace ( DefaultActiveKey ) )
{
var defaultPane = _panes . FirstOrDefault ( x = > x . Key = = DefaultActiveKey ) ;
if ( defaultPane ! = null )
{
ActivatePane ( defaultPane ) ;
}
}
if ( _activePane = = null | | _panes . All ( x = > ! x . IsActive ) )
{
ActivatePane ( _panes . FirstOrDefault ( ) ) ;
}
2020-11-30 10:53:41 +08:00
if ( AfterTabCreated . HasDelegate )
{
AfterTabCreated . InvokeAsync ( pane . Key ) ;
2020-08-11 22:26:49 +08:00
}
}
}
public async Task RemoveTabPane ( TabPane pane )
{
2020-11-30 10:53:41 +08:00
if ( await OnEdit . Invoke ( pane . Key , "remove" ) )
2020-08-11 22:26:49 +08:00
{
2020-11-30 10:53:41 +08:00
var index = _panes . IndexOf ( pane ) ;
2020-08-11 22:26:49 +08:00
_panes . Remove ( pane ) ;
if ( pane ! = null & & pane . IsActive & & _panes . Count > 0 )
2020-04-24 18:32:50 +08:00
{
2020-11-30 10:53:41 +08:00
ActivatePane ( index > 1 ? _panes [ index - 1 ] : _panes [ 0 ] ) ;
2020-08-11 22:26:49 +08:00
}
2020-11-30 10:53:41 +08:00
_needRefresh = true ;
StateHasChanged ( ) ;
2020-04-16 12:05:59 +08:00
}
}
2020-12-03 13:44:49 +08:00
internal void HandleTabClick ( TabPane tabPane )
2020-04-16 12:05:59 +08:00
{
2020-11-24 18:47:52 +08:00
if ( tabPane . IsActive )
2020-11-30 10:53:41 +08:00
return ;
2020-11-24 18:47:52 +08:00
2020-08-11 22:26:49 +08:00
if ( OnTabClick . HasDelegate )
2020-04-16 12:05:59 +08:00
{
2020-08-11 22:26:49 +08:00
OnTabClick . InvokeAsync ( tabPane . Key ) ;
2020-04-16 12:05:59 +08:00
}
2020-08-11 22:26:49 +08:00
ActivatePane ( tabPane ) ;
2020-04-16 12:05:59 +08:00
}
2020-06-07 19:41:00 +08:00
private void ActivatePane ( TabPane tabPane )
2020-04-16 12:05:59 +08:00
{
2020-04-24 18:32:50 +08:00
if ( ! tabPane . Disabled & & _panes . Contains ( tabPane ) )
2020-04-16 12:05:59 +08:00
{
if ( _activePane ! = null )
{
_activePane . IsActive = false ;
}
tabPane . IsActive = true ;
_activePane = tabPane ;
2020-08-11 22:26:49 +08:00
if ( _activeKey ! = _activePane . Key )
2020-07-22 00:30:31 +08:00
{
2020-08-11 22:26:49 +08:00
if ( ! string . IsNullOrEmpty ( _activeKey ) )
2020-07-22 00:30:31 +08:00
{
2020-08-11 22:26:49 +08:00
if ( ActiveKeyChanged . HasDelegate )
{
ActiveKeyChanged . InvokeAsync ( _activePane . Key ) ;
}
if ( OnChange . HasDelegate )
{
OnChange . InvokeAsync ( _activePane . Key ) ;
}
2020-07-22 00:30:31 +08:00
}
2020-08-11 22:26:49 +08:00
_activeKey = _activePane . Key ;
2020-07-22 00:30:31 +08:00
}
2020-12-03 13:44:49 +08:00
_needRefresh = true ;
_activePaneChanged = true ;
2020-09-20 10:43:40 +08:00
Card ? . SetBody ( _activePane . ChildContent ) ;
2020-04-16 12:05:59 +08:00
StateHasChanged ( ) ;
}
}
2020-07-22 00:30:31 +08:00
protected override async Task OnAfterRenderAsync ( bool firstRender )
2020-04-16 12:05:59 +08:00
{
await base . OnAfterRenderAsync ( firstRender ) ;
2020-12-03 13:44:49 +08:00
if ( firstRender )
{
_afterFirstRender = true ;
}
2020-04-16 12:05:59 +08:00
2020-12-03 13:44:49 +08:00
if ( _afterFirstRender & & _activePane ! = null )
2020-04-16 12:05:59 +08:00
{
2020-11-30 10:53:41 +08:00
await TryRenderInk ( ) ;
await TryRenderNavOperation ( ) ;
}
2020-04-16 12:05:59 +08:00
_needRefresh = false ;
}
2020-06-10 13:34:51 +08:00
private async Task TryRenderNavOperation ( )
2020-04-16 12:05:59 +08:00
{
2020-09-09 00:52:14 +08:00
int navWidth = ( await JsInvokeAsync < Element > ( JSInteropConstants . GetDomInfo , _tabBars ) ) . clientWidth ;
int navTotalWidth = ( await JsInvokeAsync < Element > ( JSInteropConstants . GetDomInfo , _scrollTabBar ) ) . clientWidth ;
2020-06-10 13:34:51 +08:00
if ( navTotalWidth < navWidth )
2020-04-16 12:05:59 +08:00
{
2020-06-10 13:34:51 +08:00
_operationClass = "ant-tabs-nav-operations ant-tabs-nav-operations-hidden" ;
_operationStyle = "visibility: hidden; order: 1;" ;
_tabsNavWarpPingClass = string . Empty ;
}
else
{
_operationClass = "ant-tabs-nav-operations" ;
_tabsNavWarpPingClass = "ant-tabs-nav-wrap-ping-right" ;
_operationStyle = string . Empty ;
2020-04-16 12:05:59 +08:00
}
2020-06-10 13:34:51 +08:00
StateHasChanged ( ) ;
2020-04-16 12:05:59 +08:00
}
private async Task TryRenderInk ( )
{
2020-12-03 13:44:49 +08:00
if ( _renderedActivePane = = _activePane )
2020-04-16 12:05:59 +08:00
{
2020-12-03 13:44:49 +08:00
return ;
}
2020-11-24 18:47:52 +08:00
2020-12-03 13:44:49 +08:00
// TODO: slide to activated tab
// animate Active Ink
// ink bar
var element = await JsInvokeAsync < Element > ( JSInteropConstants . GetDomInfo , _activePane . TabBar ) ;
var navSection = await JsInvokeAsync < Element > ( JSInteropConstants . GetDomInfo , _tabBars ) ;
if ( IsHorizontal )
{
//_inkStyle = "left: 0px; width: 0px;";
_inkStyle = $"left: {element.offsetLeft}px; width: {element.clientWidth}px" ;
if ( element . offsetLeft > _scrollOffset + navSection . clientWidth
| | element . offsetLeft < _scrollOffset )
2020-04-16 12:05:59 +08:00
{
2020-12-03 13:44:49 +08:00
// need to scroll tab bars
_scrollOffset = element . offsetLeft ;
_navStyle = $"transform: translate(-{_scrollOffset}px, 0px);" ;
2020-04-16 12:05:59 +08:00
}
2020-12-03 13:44:49 +08:00
}
else
{
_inkStyle = $"top: {element.offsetTop}px; height: {element.clientHeight}px;" ;
if ( element . offsetTop > _scrollOffset + navSection . clientHeight
| | element . offsetTop < _scrollOffset )
2020-04-16 12:05:59 +08:00
{
2020-12-03 13:44:49 +08:00
// need to scroll tab bars
_scrollOffset = element . offsetTop ;
_navStyle = $"transform: translate(0px, -{_scrollOffset}px);" ;
2020-04-16 12:05:59 +08:00
}
}
2020-12-03 13:44:49 +08:00
StateHasChanged ( ) ;
_renderedActivePane = _activePane ;
2020-04-16 12:05:59 +08:00
}
2020-06-10 13:34:51 +08:00
//private async void OnPrevClicked()
//{
// _needRefresh = true;
// if (OnPrevClick.HasDelegate)
// {
// await OnPrevClick.InvokeAsync(null);
// }
// // get the old offset to the left, and _navIndex != 0 because prev will be disabled
// int left = _navIndex * _navSection;
// if (IsHorizontal)
// {
// _navSection = (await JsInvokeAsync<Element>(JSInteropConstants.getDomInfo, _scrollTabBar)).clientWidth;
// _navTotal = (await JsInvokeAsync<Element>(JSInteropConstants.getDomInfo, _tabBars)).clientWidth;
// }
// else
// {
// _navSection = (await JsInvokeAsync<Element>(JSInteropConstants.getDomInfo, _scrollTabBar)).clientHeight;
// _navTotal = (await JsInvokeAsync<Element>(JSInteropConstants.getDomInfo, _tabBars)).clientHeight;
// }
// // calculate the current _navIndex after users resize the browser, and _navIndex > 0 guaranteed since left > 0
// _navIndex = (int)Math.Ceiling(1.0 * left / _navSection);
// int offset = --_navIndex * _navSection;
// if (IsHorizontal)
// {
// _navStyle = $"transform: translate3d(-{offset}px, 0px, 0px);";
// }
// else
// {
// _navStyle = $"transform: translate3d(0px, -{offset}px, 0px);";
// }
// RefreshNavIcon();
// _needRefresh = false;
//}
//private async void OnNextClicked()
//{
// // BUG: when vertical
// _needRefresh = true;
// if (OnNextClick.HasDelegate)
// {
// await OnNextClick.InvokeAsync(null);
// }
// // get the old offset to the left
// int left = _navIndex * _navSection;
// if (IsHorizontal)
// {
// _navSection = (await JsInvokeAsync<Element>(JSInteropConstants.getDomInfo, _scrollTabBar)).clientWidth;
// _navTotal = (await JsInvokeAsync<Element>(JSInteropConstants.getDomInfo, _tabBars)).clientWidth;
// }
// else
// {
// _navSection = (await JsInvokeAsync<Element>(JSInteropConstants.getDomInfo, _scrollTabBar)).clientHeight;
// _navTotal = (await JsInvokeAsync<Element>(JSInteropConstants.getDomInfo, _tabBars)).clientHeight;
// }
// // calculate the current _navIndex after users resize the browser
// _navIndex = left / _navSection;
// int offset = Math.Min(++_navIndex * _navSection, _navTotal / _navSection * _navSection);
// if (IsHorizontal)
// {
// _navStyle = $"transform: translate3d(-{offset}px, 0px, 0px);";
// }
// else
// {
// _navStyle = $"transform: translate3d(0px, -{offset}px, 0px);";
// }
// RefreshNavIcon();
// _needRefresh = false;
//}
//private void RefreshNavIcon()
//{
// if (_navTotal > _navSection)
// {
// if (_navIndex == 0)
// {
// // reach the first section
// _prevIconEnabled = false;
// }
// else
// {
// _prevIconEnabled = true;
// }
// if ((_navIndex + 1) * _navSection > _navTotal)
// {
// // reach the last section
// _nextIconEnabled = false;
// }
// else
// {
// _nextIconEnabled = true;
// }
// }
// else
// {
// // hide icon
// _prevIconEnabled = null;
// _nextIconEnabled = null;
// }
// StateHasChanged();
//}
2020-04-16 12:05:59 +08:00
protected override bool ShouldRender ( )
{
return _needRefresh | | _renderedActivePane ! = _activePane ;
}
2020-04-16 20:53:03 +08:00
#region DRAG & DROP
2020-06-07 19:41:00 +08:00
private TabPane _draggingPane ;
2020-04-16 20:53:03 +08:00
2020-11-30 10:53:41 +08:00
internal void HandleDragStart ( DragEventArgs args , TabPane pane )
2020-04-16 20:53:03 +08:00
{
if ( Draggable )
{
args . DataTransfer . DropEffect = "move" ;
args . DataTransfer . EffectAllowed = "move" ;
_draggingPane = pane ;
}
}
2020-11-30 10:53:41 +08:00
internal void HandleDrop ( TabPane pane )
2020-04-16 20:53:03 +08:00
{
if ( Draggable & & _draggingPane ! = null )
{
2020-04-24 18:32:50 +08:00
int newIndex = _panes . IndexOf ( pane ) ;
_panes . Remove ( _draggingPane ) ;
_panes . Insert ( newIndex , _draggingPane ) ;
2020-04-16 20:53:03 +08:00
_draggingPane = null ;
_needRefresh = true ;
_renderedActivePane = null ;
StateHasChanged ( ) ;
}
}
2020-04-24 18:32:50 +08:00
#endregion DRAG & DROP
2020-04-16 12:05:59 +08:00
}
2020-04-24 18:32:50 +08:00
}