Projektdateien hinzufügen.

This commit is contained in:
Kevin Krüger
2023-07-24 12:00:34 +02:00
parent 656751e10b
commit 0d00a90942
210 changed files with 45049 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
namespace VideoBrowser.Controls.CefSharpBrowser.ViewModels
{
/// <summary>
/// Defines the <see cref="DefaultTabHostViewModel" />.
/// </summary>
public class DefaultTabHostViewModel
{
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="DefaultTabHostViewModel"/> class.
/// </summary>
/// <param name="globalData">The globalData<see cref="GlobalBrowserData"/>.</param>
public DefaultTabHostViewModel(GlobalBrowserData globalData)
{
this.WebBrowserTabControlViewModel = new WebBrowserTabControlViewModel(globalData);
}
#endregion Constructors
#region Properties
/// <summary>
/// Gets the WebBrowserTabControlViewModel.
/// </summary>
public WebBrowserTabControlViewModel WebBrowserTabControlViewModel { get; }
#endregion Properties
}
}

View File

@@ -0,0 +1,110 @@
namespace VideoBrowser.Controls.CefSharpBrowser.ViewModels
{
using Ookii.Dialogs.Wpf;
using System.IO;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using VideoBrowser.Common;
using VideoBrowser.Controls.CefSharpBrowser.Helpers;
using VideoBrowser.Controls.CefSharpBrowser.Models;
using VideoBrowser.Extensions;
using VideoBrowser.Resources;
/// <summary>
/// Defines the <see cref="SettingsViewModel" />.
/// </summary>
public class SettingsViewModel : NotifyPropertyChanged
{
#region Fields
private string _outputFolder;
#endregion Fields
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="SettingsViewModel"/> class.
/// </summary>
internal SettingsViewModel()
{
this.GetFolderCommand = new RelayCommand(this.OnGetFolder);
var settings = BrowserSettingsHelper.Load();
if (settings != null)
{
this.BrowserSettings = settings;
}
var outputFolder = this.BrowserSettings.OutputFolder;
this.OutputFolder = string.IsNullOrEmpty(outputFolder) || !Directory.Exists(outputFolder) ? AppEnvironment.UserVideoFolder : outputFolder;
}
#endregion Constructors
#region Properties
/// <summary>
/// Gets the BrowserSettings.
/// </summary>
public BrowserSettings BrowserSettings { get; } = new BrowserSettings();
/// <summary>
/// Gets the GetFolderCommand.
/// </summary>
public ICommand GetFolderCommand { get; }
/// <summary>
/// Gets or sets the Icon.
/// </summary>
public Geometry Icon { get; set; } = Icons.Settings;
/// <summary>
/// Gets or sets the OutputFolder.
/// </summary>
public string OutputFolder
{
get => this._outputFolder;
set
{
this.Set(this.PropertyChangedHandler, ref this._outputFolder, value);
if (Directory.Exists(this.OutputFolder))
{
this.BrowserSettings.OutputFolder = this.OutputFolder;
}
}
}
/// <summary>
/// Gets or sets the OutputType.
/// </summary>
public string OutputType { get; set; }
#endregion Properties
#region Methods
/// <summary>
/// The OnGetFolder.
/// </summary>
/// <param name="obj">The obj<see cref="object"/>.</param>
private void OnGetFolder(object obj)
{
var dialog = new VistaFolderBrowserDialog
{
Description = "Download Folder Location",
UseDescriptionForTitle = true,
SelectedPath = this.OutputFolder
};
var element = obj as FrameworkElement;
var window = Window.GetWindow(element);
if ((bool)dialog.ShowDialog(window))
{
this.OutputFolder = dialog.SelectedPath;
}
}
#endregion Methods
}
}

View File

@@ -0,0 +1,346 @@
namespace VideoBrowser.Controls.CefSharpBrowser.ViewModels
{
using CefSharp;
using System;
using System.Collections.Generic;
using System.Windows.Input;
using System.Windows.Media;
using VideoBrowser.Common;
using VideoBrowser.Controls.CefSharpBrowser.Helpers;
using VideoBrowser.Core;
using VideoBrowser.Extensions;
using VideoBrowser.ViewModels;
/// <summary>
/// Defines the <see cref="VideoBrowserViewModel" />.
/// </summary>
public class VideoBrowserViewModel : NotifyPropertyChanged, IDisposable
{
#region Fields
private ICommand _backwardCommand;
private bool _canBackward;
private bool _canForward;
private CefWindowData _cefWindowData;
private ICommand _forwardCommand;
private string _header = "New Tab";
private string _navigateUrl = "youtube.com";
private ICommand _reloadCommand;
private IWebBrowser _webBrowser;
#endregion Fields
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="VideoBrowserViewModel"/> class.
/// </summary>
/// <param name="globalBrowserData">The globalBrowserData<see cref="GlobalBrowserData"/>.</param>
/// <param name="windowData">The windowData<see cref="CefWindowData"/>.</param>
internal VideoBrowserViewModel(GlobalBrowserData globalBrowserData, CefWindowData windowData)
{
this.GlobalBrowserData = globalBrowserData;
this.CefWindowData = windowData;
// BackwardCommand and ForwardCommand are set by the View.
this.DownloadCommand = new RelayCommand(this.OnDownload, "Download", (o) => this.UrlReader.IsDownloadable);
this.HomeCommand = new RelayCommand(this.OnHome, "Home");
this.NavigateUrlCommand = new RelayCommand(this.OnNavigateUrl, "NavigateUrl");
this.OpenOutputFolderCommand = new RelayCommand(this.OnOpenOutputFolder, "Open output folder");
this.IndicatorColor = new SolidColorBrush(Colors.DarkBlue);
this.UrlEditor = new UrlEditorViewModel(this.UrlReader, this.GlobalBrowserData.Settings)
{
NavigateUrlCommand = this.NavigateUrlCommand,
ShowMessageAsyncAction = this.ShowMessageAsync
};
this.UrlEditor.PropertyChanged += this.OnUrlEditor_PropertyChanged;
this.PropertyChanged += this.OnPropertyChanged;
this.OnHome(null);
}
#endregion Constructors
#region Properties
/// <summary>
/// Gets the AddInButtons.
/// </summary>
public ICollection<AddInButton> AddInButtons => this.GlobalBrowserData.AddInButtons;
/// <summary>
/// Gets or sets the BackwardCommand.
/// </summary>
public ICommand BackwardCommand { get => this._backwardCommand; set => this.Set(this.PropertyChangedHandler, ref this._backwardCommand, value); }
/// <summary>
/// Gets or sets a value indicating whether CanBackward.
/// </summary>
public bool CanBackward { get => this._canBackward; set => this.Set(this.PropertyChangedHandler, ref this._canBackward, value); }
/// <summary>
/// Gets or sets a value indicating whether CanForward.
/// </summary>
public bool CanForward { get => this._canForward; set => this.Set(this.PropertyChangedHandler, ref this._canForward, value); }
/// <summary>
/// Gets or sets the CefWindowData.
/// </summary>
public CefWindowData CefWindowData
{
get => _cefWindowData;
internal set
{
if (!this.Set(this.PropertyChangedHandler, ref _cefWindowData, value))
{
return;
};
this.InitializeHandlers();
}
}
/// <summary>
/// Gets the DownloadCommand.
/// </summary>
public ICommand DownloadCommand { get; }
/// <summary>
/// Gets or sets the ForwardCommand.
/// </summary>
public ICommand ForwardCommand { get => this._forwardCommand; set => this.Set(this.PropertyChangedHandler, ref this._forwardCommand, value); }
/// <summary>
/// Gets the GlobalBrowserData.
/// </summary>
public GlobalBrowserData GlobalBrowserData { get; }
/// <summary>
/// Gets or sets the Header.
/// </summary>
public string Header { get => _header; set => this.Set(this.PropertyChangedHandler, ref _header, value); }
/// <summary>
/// Gets the HomeCommand.
/// </summary>
public ICommand HomeCommand { get; }
/// <summary>
/// Gets the IndicatorColor.
/// </summary>
public Brush IndicatorColor { get; private set; }
/// <summary>
/// Sets the IsSuccessful.
/// </summary>
public bool? IsSuccessful
{
set
{
if (value == null)
IndicatorColor = new SolidColorBrush(Colors.LightBlue);
else if (value == false)
IndicatorColor = new SolidColorBrush(Colors.Red);
else
IndicatorColor = new SolidColorBrush(Colors.Green);
OnPropertyChanged(nameof(IndicatorColor));
}
}
/// <summary>
/// Gets or sets the NavigateUrl.
/// The current valid Url that is currently opened,
/// it is set by Url property if the Return key is pressed or link is clicked...
/// </summary>
public string NavigateUrl { get => this._navigateUrl; set => this.Set(this.PropertyChangedHandler, ref this._navigateUrl, value); }
/// <summary>
/// Gets the NavigateUrlCommand.
/// </summary>
public ICommand NavigateUrlCommand { get; }
/// <summary>
/// Gets the OpenOutputFolderCommand.
/// </summary>
public ICommand OpenOutputFolderCommand { get; }
/// <summary>
/// Gets or sets the ReloadCommand.
/// </summary>
public ICommand ReloadCommand { get => this._reloadCommand; set => this.Set(this.PropertyChangedHandler, ref this._reloadCommand, value); }
/// <summary>
/// Gets or sets the Url.
/// It is typed in the TextBox.
/// </summary>
public string Url { get => this.UrlEditor.Url; set => this.UrlEditor.Url = value; }
/// <summary>
/// Gets the UrlEditor.
/// </summary>
public UrlEditorViewModel UrlEditor { get; }
/// <summary>
/// Gets the UrlReader.
/// </summary>
public UrlReader UrlReader { get; } = new UrlReader();
/// <summary>
/// Gets or sets the WebBrowser.
/// </summary>
public IWebBrowser WebBrowser
{
get => _webBrowser;
set
{
if (this.WebBrowser == value)
{
return;
}
_webBrowser = value;
this.InitializeHandlers();
}
}
/// <summary>
/// Gets or sets the DownloadAction.
/// </summary>
internal Action<Operation> DownloadAction { get => this.UrlEditor.DownloadAction; set => this.UrlEditor.DownloadAction = value; }
#endregion Properties
#region Methods
/// <summary>
/// The Dispose.
/// </summary>
public void Dispose()
{
this.UrlEditor.Dispose();
this.UrlEditor.PropertyChanged -= this.OnUrlEditor_PropertyChanged;
this.UrlReader.Dispose();
}
/// <summary>
/// The InitializeHandlers.
/// </summary>
private void InitializeHandlers()
{
if (this.WebBrowser != null)
{
this.WebBrowser.DownloadHandler = this.GlobalBrowserData.DownloadHandler;
this.WebBrowser.MenuHandler = this.CefWindowData.CefContextMenuHandler;
this.WebBrowser.RequestHandler = this.CefWindowData.CefRequestHandler;
}
}
/// <summary>
/// The IsUrlValid.
/// </summary>
/// <returns>The <see cref="bool"/>.</returns>
private bool IsUrlValid()
{
return true;
}
/// <summary>
/// The OnDownload.
/// </summary>
/// <param name="obj">The obj<see cref="object"/>.</param>
private void OnDownload(object obj)
{
if (!this.IsUrlValid() || !this.UrlEditor.DownloadCommand.CanExecute(null))
{
return;
}
this.UrlEditor.DownloadCommand.Execute(null);
}
/// <summary>
/// The OnHome.
/// </summary>
/// <param name="obj">The obj<see cref="object"/>.</param>
private void OnHome(object obj)
{
this.Url = AppEnvironment.HomeUrl;
this.NavigateUrl = this.Url;
}
/// <summary>
/// The OnNavigateUrl called from Button.
/// </summary>
/// <param name="obj">The obj<see cref="object"/>.</param>
private void OnNavigateUrl(object obj)
{
this.Url = VideoBrowser.Helpers.UrlHelper.GetValidUrl(this.Url);
this.NavigateUrl = this.Url;
this.CefWindowData.IsAirspaceVisible = false;
}
/// <summary>
/// The OnOpenOutputFolder.
/// </summary>
/// <param name="obj">The obj<see cref="object"/>.</param>
private void OnOpenOutputFolder(object obj)
{
ProcessHelper.Start(this.GlobalBrowserData.Settings.OutputFolder);
}
/// <summary>
/// The OnPropertyChanged.
/// </summary>
/// <param name="sender">The sender<see cref="object"/>.</param>
/// <param name="e">The e<see cref="System.ComponentModel.PropertyChangedEventArgs"/>.</param>
private void OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case nameof(this.Url):
this.UrlReader.Url = this.Url;
break;
case nameof(this.NavigateUrl):
this.Url = this.NavigateUrl;
this.UrlEditor.NavigateUrl = this.NavigateUrl;
break;
default:
break;
}
}
/// <summary>
/// The OnUrlEditor_PropertyChanged.
/// </summary>
/// <param name="sender">The sender<see cref="object"/>.</param>
/// <param name="e">The e<see cref="System.ComponentModel.PropertyChangedEventArgs"/>.</param>
private void OnUrlEditor_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.IsMatch(nameof(this.UrlEditor.Url)))
{
this.OnPropertyChanged(nameof(this.Url));
}
}
/// <summary>
/// The ShowMessage.
/// </summary>
/// <param name="title">The title<see cref="string"/>.</param>
/// <param name="message">The message<see cref="string"/>.</param>
private void ShowMessageAsync(string title, string message)
{
this.CefWindowData.ShowMessageAsync(title, message);
}
#endregion Methods
}
}

View File

@@ -0,0 +1,97 @@
namespace VideoBrowser.Controls.CefSharpBrowser.ViewModels
{
using System;
using System.ComponentModel;
using VideoBrowser.Controls.CefSharpBrowser.Views;
using VideoBrowser.Core;
using VideoBrowser.Extensions;
using VideoBrowser.Helpers;
/// <summary>
/// Defines the <see cref="WebBrowserHeaderedItemViewModel" />.
/// </summary>
public class WebBrowserHeaderedItemViewModel : TabItem
{
#region Fields
private VideoBrowserViewModel _videoBrowserViewModel;
#endregion Fields
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="WebBrowserHeaderedItemViewModel"/> class.
/// </summary>
/// <param name="globalBrowserData">The globalBrowserData<see cref="GlobalBrowserData"/>.</param>
/// <param name="cefWindowData">The cefWindowData<see cref="CefWindowData"/>.</param>
/// <param name="downloadAction">The downloadAction<see cref="Action{Operation}"/>.</param>
internal WebBrowserHeaderedItemViewModel(GlobalBrowserData globalBrowserData, CefWindowData cefWindowData, Action<Operation> downloadAction)
{
this.VideoBrowserViewModel = new VideoBrowserViewModel(globalBrowserData, cefWindowData)
{
DownloadAction = downloadAction
};
this.VideoBrowserViewModel.PropertyChanged += this.OnVideoBrowserViewModel_PropertyChanged;
this.Title = this.VideoBrowserViewModel.Header;
UIThreadHelper.Invoke(() =>
{
this.VideoBrowserView = new VideoBrowserView { DataContext = this.VideoBrowserViewModel };
this.Content = this.VideoBrowserView;
});
}
#endregion Constructors
#region Properties
/// <summary>
/// Gets the VideoBrowserView.
/// </summary>
public VideoBrowserView VideoBrowserView { get; private set; }
/// <summary>
/// Gets the VideoBrowserViewModel.
/// </summary>
public VideoBrowserViewModel VideoBrowserViewModel { get => _videoBrowserViewModel; private set => this.Set(this.OnPropertyChanged, ref _videoBrowserViewModel, value); }
#endregion Properties
#region Methods
/// <summary>
/// The Dispose.
/// </summary>
/// <param name="disposing">The disposing<see cref="bool"/>.</param>
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (this.VideoBrowserViewModel == null)
{
return;
}
this.VideoBrowserViewModel.PropertyChanged -= this.OnVideoBrowserViewModel_PropertyChanged;
this.VideoBrowserViewModel.Dispose();
this.VideoBrowserViewModel = null;
this.VideoBrowserView.DataContext = null;
this.VideoBrowserView = null;
}
/// <summary>
/// The OnVideoBrowserViewModel_PropertyChanged.
/// </summary>
/// <param name="sender">The sender<see cref="object"/>.</param>
/// <param name="e">The e<see cref="PropertyChangedEventArgs"/>.</param>
private void OnVideoBrowserViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.IsMatch(nameof(this.VideoBrowserViewModel.Header)))
{
this.Title = this.VideoBrowserViewModel.Header;
}
}
#endregion Methods
}
}

View File

@@ -0,0 +1,348 @@
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;
/// <summary>
/// Defines the <see cref="WebBrowserTabControlViewModel" />.
/// </summary>
public class WebBrowserTabControlViewModel : INotifyPropertyChanged, IDisposable
{
#region Fields
private static int IdCounter;
private int _selectedTabIndex;
#endregion Fields
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="WebBrowserTabControlViewModel"/> class.
/// </summary>
/// <param name="globalBrowserData">The globalBrowserData<see cref="GlobalBrowserData"/>.</param>
public WebBrowserTabControlViewModel(GlobalBrowserData globalBrowserData)
{
this.GlobalBrowserData = globalBrowserData;
this.CefWindowData = new CefWindowData();
this.TabItems = new ObservableCollection<TabItem>();
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
/// <summary>
/// Defines the PropertyChanged.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
#endregion Events
#region Properties
/// <summary>
/// Gets the CefWindowData.
/// </summary>
public CefWindowData CefWindowData { get; }
/// <summary>
/// Gets the ClosingFloatingItemHandler.
/// </summary>
public ClosingFloatingItemCallback ClosingFloatingItemHandler => ClosingFloatingItemHandlerImpl;
/// <summary>
/// Gets the ClosingTabItemHandler.
/// </summary>
public ItemActionCallback ClosingTabItemHandler => ClosingTabItemHandlerImpl;
/// <summary>
/// Gets or sets the CreateBrowserFunc.
/// </summary>
public Func<HeaderedItemViewModel> CreateBrowserFunc { get; set; }
/// <summary>
/// Gets the GlobalBrowserData.
/// </summary>
public GlobalBrowserData GlobalBrowserData { get; }
/// <summary>
/// Gets or sets the Icon.
/// </summary>
public Geometry Icon { get; set; } = Icons.SearchVideo;
/// <summary>
/// Gets the Id.
/// </summary>
public int Id { get; } = IdCounter++;
/// <summary>
/// Gets the InterTabClient.
/// </summary>
public IInterTabClient InterTabClient => this.GlobalBrowserData.InterTabClient;
/// <summary>
/// Gets or sets the LoadedCommand.
/// </summary>
public ICommand LoadedCommand { get; set; }
/// <summary>
/// Gets or sets the SelectedTabIndex.
/// </summary>
public int SelectedTabIndex { get => _selectedTabIndex; set => this.Set(this.PropertyChanged, ref _selectedTabIndex, value); }
/// <summary>
/// Gets the TabItems.
/// </summary>
public ObservableCollection<TabItem> TabItems { get; }
/// <summary>
/// Gets the ToolItems.
/// </summary>
public ObservableCollection<HeaderedItemViewModel> ToolItems { get; } = new ObservableCollection<HeaderedItemViewModel>();
#endregion Properties
#region Methods
/// <summary>
/// The AddTab.
/// </summary>
/// <param name="item">The item<see cref="TabItem"/>.</param>
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;
}
/// <summary>
/// The Dispose.
/// </summary>
public void Dispose()
{
var settings = this.GlobalBrowserData.BrowserSettings;
BrowserSettingsHelper.Save(settings, this);
this.TabItems.CollectionChanged -= this.OnTabItems_CollectionChanged;
this.TabItems.ClearAndDispose();
}
/// <summary>
/// The IsTabItemExist.
/// </summary>
/// <param name="guid">The guid<see cref="Guid"/>.</param>
/// <returns>The <see cref="bool"/>.</returns>
public bool IsTabItemExist(Guid guid)
{
return this.TabItems.Any((o) => o.Guid == guid) && guid != Guid.Empty;
}
/// <summary>
/// Returns a <see cref="System.String" /> that represents this instance.
/// </summary>
/// <returns>The <see cref="string"/>.</returns>
public override string ToString()
{
var message = $"{nameof(WebBrowserTabControlViewModel)} {this.Id}";
return message;
}
/// <summary>
/// The SetActiveTab.
/// </summary>
/// <param name="guid">The guid<see cref="Guid"/>.</param>
internal void SetActiveTab(Guid guid)
{
for (var i = 0; i < this.TabItems.Count; i++)
{
if (this.TabItems[i].Guid == guid)
{
this.SelectedTabIndex = i;
break;
}
}
}
/// <summary>
/// Callback to handle floating toolbar/MDI window closing.
/// </summary>
/// <param name="args">The args<see cref="ItemActionCallbackArgs{Layout}"/>.</param>
private static void ClosingFloatingItemHandlerImpl(ItemActionCallbackArgs<Layout> 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();
}
}
/// <summary>
/// Callback to handle tab closing.
/// </summary>
/// <param name="args">The args<see cref="ItemActionCallbackArgs{TabablzControl}"/>.</param>
private static void ClosingTabItemHandlerImpl(ItemActionCallbackArgs<TabablzControl> 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);
}
/// <summary>
/// The CreateBrowser.
/// </summary>
/// <returns>The <see cref="HeaderedItemViewModel"/>.</returns>
private HeaderedItemViewModel CreateBrowser()
{
var model = new WebBrowserHeaderedItemViewModel(this.GlobalBrowserData, this.CefWindowData, null);
return model;
}
/// <summary>
/// The OnLoaded.
/// </summary>
/// <param name="obj">The obj<see cref="object"/>.</param>
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);
}
}
}
}
/// <summary>
/// The OnOpenUrlFromTab.
/// </summary>
/// <param name="url">The url<see cref="string"/>.</param>
private void OnOpenUrlFromTab(string url)
{
OnOpenUrlFromTab(url, string.Empty);
}
/// <summary>
/// The OnOpenUrlFromTab.
/// </summary>
/// <param name="url">The url<see cref="string"/>.</param>
/// <param name="title">The title<see cref="string"/>.</param>
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);
});
}
/// <summary>
/// The OnOpenUrlFromWindow.
/// </summary>
/// <param name="url">The url<see cref="string"/>.</param>
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<TabItem> items)
{
items.Add(browser);
}
});
}
/// <summary>
/// The OnTabItems_CollectionChanged.
/// </summary>
/// <param name="sender">The sender<see cref="object"/>.</param>
/// <param name="e">The e<see cref="NotifyCollectionChangedEventArgs"/>.</param>
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
}
}

View File

@@ -0,0 +1,84 @@
namespace VideoBrowser.Controls.CefSharpBrowser.ViewModels
{
using Dragablz;
using System;
using System.Windows.Input;
using System.Windows.Media;
using VideoBrowser.Common;
using VideoBrowser.Extensions;
/// <summary>
/// Defines the <see cref="WebBrowserTabHeaderViewModel" />.
/// </summary>
public class WebBrowserTabHeaderViewModel : NotifyPropertyChanged
{
#region Fields
private string _header;
private ImageSource _image;
private bool _isSelected;
#endregion Fields
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="WebBrowserTabHeaderViewModel"/> class.
/// </summary>
public WebBrowserTabHeaderViewModel()
{
this.MouseUpCommand = new RelayCommand(this.OnMouseUp, nameof(this.MouseUpCommand));
}
#endregion Constructors
#region Properties
/// <summary>
/// Gets or sets the Header.
/// </summary>
public string Header { get => _header; set => this.Set(this.PropertyChangedHandler, ref _header, value); }
/// <summary>
/// Gets or sets the Image.
/// </summary>
public ImageSource Image { get => _image; set => this.Set(this.PropertyChangedHandler, ref _image, value); }
/// <summary>
/// Gets or sets a value indicating whether IsSelected.
/// </summary>
public bool IsSelected { get => _isSelected; set => this.Set(this.PropertyChangedHandler, ref _isSelected, value); }
/// <summary>
/// Gets the MouseUpCommand.
/// </summary>
public ICommand MouseUpCommand { get; }
#endregion Properties
#region Methods
/// <summary>
/// The OnMouseUp.
/// </summary>
/// <param name="obj">The obj<see cref="object"/>.</param>
private void OnMouseUp(object obj)
{
Logger.Info($"Middle Mouse clicked on a browser tab to close it.");
var (_, args, commandParameter) = (ValueTuple<object, EventArgs, object>)obj;
if (args is MouseButtonEventArgs mouseEventArgs && mouseEventArgs.ChangedButton == MouseButton.Middle)
{
var dragablzItem = commandParameter as System.Windows.FrameworkElement;
var closeCommand = TabablzControl.CloseItemCommand;
if (closeCommand != null && closeCommand.CanExecute(commandParameter, dragablzItem))
{
closeCommand.Execute(dragablzItem, dragablzItem);
}
}
}
#endregion Methods
}
}