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 } }