namespace VideoBrowser.Controls.CefSharpBrowser.ViewModels
{
using Dragablz;
using Dragablz.Dockablz;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using VideoBrowser.Common;
using VideoBrowser.Controls.CefSharpBrowser.Helpers;
using VideoBrowser.Extensions;
using VideoBrowser.Helpers;
using VideoBrowser.Resources;
///
/// Defines the .
///
public class WebBrowserTabControlViewModel : INotifyPropertyChanged, IDisposable
{
#region Fields
private static int IdCounter;
private int _selectedTabIndex;
#endregion Fields
#region Constructors
///
/// Initializes a new instance of the class.
///
/// The globalBrowserData.
public WebBrowserTabControlViewModel(GlobalBrowserData globalBrowserData)
{
this.GlobalBrowserData = globalBrowserData;
this.CefWindowData = new CefWindowData();
this.TabItems = new ObservableCollection();
this.TabItems.CollectionChanged += this.OnTabItems_CollectionChanged;
this.CreateBrowserFunc = this.CreateBrowser;
this.CefWindowData.CefRequestHandler.OpenUrlFromTabAction = this.OnOpenUrlFromTab;
this.CefWindowData.CefContextMenuHandler.OpenInNewTabAction = this.OnOpenUrlFromTab;
this.CefWindowData.CefContextMenuHandler.OpenInNewWindowAction = this.OnOpenUrlFromWindow;
this.LoadedCommand = new RelayCommand(this.OnLoaded, nameof(this.LoadedCommand));
}
#endregion Constructors
#region Events
///
/// Defines the PropertyChanged.
///
public event PropertyChangedEventHandler PropertyChanged;
#endregion Events
#region Properties
///
/// Gets the CefWindowData.
///
public CefWindowData CefWindowData { get; }
///
/// Gets the ClosingFloatingItemHandler.
///
public ClosingFloatingItemCallback ClosingFloatingItemHandler => ClosingFloatingItemHandlerImpl;
///
/// Gets the ClosingTabItemHandler.
///
public ItemActionCallback ClosingTabItemHandler => ClosingTabItemHandlerImpl;
///
/// Gets or sets the CreateBrowserFunc.
///
public Func CreateBrowserFunc { get; set; }
///
/// Gets the GlobalBrowserData.
///
public GlobalBrowserData GlobalBrowserData { get; }
///
/// Gets or sets the Icon.
///
public Geometry Icon { get; set; } = Icons.SearchVideo;
///
/// Gets the Id.
///
public int Id { get; } = IdCounter++;
///
/// Gets the InterTabClient.
///
public IInterTabClient InterTabClient => this.GlobalBrowserData.InterTabClient;
///
/// Gets or sets the LoadedCommand.
///
public ICommand LoadedCommand { get; set; }
///
/// Gets or sets the SelectedTabIndex.
///
public int SelectedTabIndex { get => _selectedTabIndex; set => this.Set(this.PropertyChanged, ref _selectedTabIndex, value); }
///
/// Gets the TabItems.
///
public ObservableCollection TabItems { get; }
///
/// Gets the ToolItems.
///
public ObservableCollection ToolItems { get; } = new ObservableCollection();
#endregion Properties
#region Methods
///
/// The AddTab.
///
/// The item.
public void AddTab(TabItem item)
{
if (this.IsTabItemExist(item.Guid))
{
this.SetActiveTab(item.Guid);
Logger.Info($"Add tab canceled: Tab {item.Title} exists.");
return;
}
this.TabItems.Add(item);
Logger.Info($"Tab {item.Title} is added.");
this.SelectedTabIndex = this.TabItems.Count - 1;
}
///
/// The Dispose.
///
public void Dispose()
{
var settings = this.GlobalBrowserData.BrowserSettings;
BrowserSettingsHelper.Save(settings, this);
this.TabItems.CollectionChanged -= this.OnTabItems_CollectionChanged;
this.TabItems.ClearAndDispose();
}
///
/// The IsTabItemExist.
///
/// The guid.
/// The .
public bool IsTabItemExist(Guid guid)
{
return this.TabItems.Any((o) => o.Guid == guid) && guid != Guid.Empty;
}
///
/// Returns a that represents this instance.
///
/// The .
public override string ToString()
{
var message = $"{nameof(WebBrowserTabControlViewModel)} {this.Id}";
return message;
}
///
/// The SetActiveTab.
///
/// The guid.
internal void SetActiveTab(Guid guid)
{
for (var i = 0; i < this.TabItems.Count; i++)
{
if (this.TabItems[i].Guid == guid)
{
this.SelectedTabIndex = i;
break;
}
}
}
///
/// Callback to handle floating toolbar/MDI window closing.
///
/// The args.
private static void ClosingFloatingItemHandlerImpl(ItemActionCallbackArgs args)
{
//in here you can dispose stuff or cancel the close
//here's your view model:
if (args.DragablzItem.DataContext is IDisposable disposable)
{
disposable.Dispose();
}
}
///
/// Callback to handle tab closing.
///
/// The args.
private static void ClosingTabItemHandlerImpl(ItemActionCallbackArgs args)
{
//in here you can dispose stuff or cancel the close
//here's your view model:
var viewModel = args.DragablzItem.DataContext as HeaderedItemViewModel;
if (viewModel.Content is FrameworkElement element && element.DataContext is IDisposable disposable)
{
disposable?.Dispose();
}
//here's how you can cancel stuff:
//args.Cancel();
System.Diagnostics.Debug.Assert(viewModel != null);
}
///
/// The CreateBrowser.
///
/// The .
private HeaderedItemViewModel CreateBrowser()
{
var model = new WebBrowserHeaderedItemViewModel(this.GlobalBrowserData, this.CefWindowData, null);
return model;
}
///
/// The OnLoaded.
///
/// The obj.
private void OnLoaded(object obj)
{
if (!this.GlobalBrowserData.IsSettingsLoaded)
{
this.GlobalBrowserData.IsSettingsLoaded = true;
var settings = this.GlobalBrowserData.BrowserSettings;
var tabSettings = settings.TabSettingModels;
if (tabSettings.Any())
{
var firstTab = (this.TabItems.First().Content as FrameworkElement).DataContext as VideoBrowserViewModel;
firstTab.NavigateUrl = tabSettings.First().Url;
firstTab.Header = tabSettings.First().Title;
for (var i = 1; i < tabSettings.Count; i++)
{
var tabItemSetting = tabSettings[i];
this.OnOpenUrlFromTab(tabItemSetting.Url, tabItemSetting.Title);
}
Task.Run(async () =>
{
await Task.Delay(1000);
this.SelectedTabIndex = settings.SelectedTabSettingIndex;
});
}
foreach (var downloadItem in settings.DownloadItems)
{
if (System.IO.File.Exists(downloadItem.OutputPath))
{
this.GlobalBrowserData.DownloadItemModels.Add(downloadItem);
}
}
}
}
///
/// The OnOpenUrlFromTab.
///
/// The url.
private void OnOpenUrlFromTab(string url)
{
OnOpenUrlFromTab(url, string.Empty);
}
///
/// The OnOpenUrlFromTab.
///
/// The url.
/// The title.
private void OnOpenUrlFromTab(string url, string title)
{
UIThreadHelper.InvokeAsync(() =>
{
var browser = this.CreateBrowserFunc() as WebBrowserHeaderedItemViewModel;
browser.VideoBrowserViewModel.NavigateUrl = url;
if (!string.IsNullOrEmpty(title))
{
browser.VideoBrowserViewModel.Header = title;
}
this.AddTab(browser);
});
}
///
/// The OnOpenUrlFromWindow.
///
/// The url.
private void OnOpenUrlFromWindow(string url)
{
var browser = this.CreateBrowserFunc() as WebBrowserHeaderedItemViewModel;
browser.VideoBrowserViewModel.NavigateUrl = url;
UIThreadHelper.Invoke(() =>
{
var (Window, TabablzControl) = this.GlobalBrowserData.InterTabClient.CreateWindow();
Window.Show();
if (TabablzControl.ItemsSource is ICollection items)
{
items.Add(browser);
}
});
}
///
/// The OnTabItems_CollectionChanged.
///
/// The sender.
/// The e.
private void OnTabItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (var item in e.NewItems)
{
if (item is WebBrowserHeaderedItemViewModel browserTabItem)
{
browserTabItem.VideoBrowserViewModel.CefWindowData = this.CefWindowData;
}
}
}
}
#endregion Methods
}
}