Sic03/Sicentury.Core/UserControls/ParameterNodeTreeViewContro...

480 lines
16 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/************************************************************************
*@file FrameworkLocal\UIClient\CenterViews\Core\UserControls\ParameterNodeTreeViewControl.cs
* @author Su Liang
* @Date 2022-08-01
*
* @copyright &copy Sicentury Inc.
*
* @brief Reconstructed to support rich functions.
*
* @details
* *****************************************************************************/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Microsoft.VisualBasic.FileIO;
using Sicentury.Core.Dialogs;
using Sicentury.Core.Tree;
namespace Sicentury.Core.UserControls
{
/// <summary>
/// Interaction logic for ParameterNodeTreeViewControl.xaml
/// </summary>
public partial class ParameterNodeTreeViewControl
{
#region Variables
private bool _clearGroupSelectionOnly = false;
#endregion
/// <summary>
/// 父级文件夹。
/// </summary>
private const string PRESET_GROUP_SUB_FOLDER_NAME = "PresetGroups";
public ParameterNodeTreeViewControl()
{
//InitializeComponent();
}
protected override void OnInitialized(System.EventArgs e)
{
InitializeComponent();
base.OnInitialized(e);
LoadPresetGroupFilesList();
}
#region Properties
public static readonly DependencyProperty TreeRootProperty = DependencyProperty.Register(
nameof(TreeRoot), typeof(TreeNode), typeof(ParameterNodeTreeViewControl),
new PropertyMetadata(default(TreeNode), (o, p) =>
{
if (o is ParameterNodeTreeViewControl control)
{
if (p.NewValue is TreeNode tree)
{
tree.TerminalNodeSelectionChanged += (sender, b) =>
{
control.RaiseEvent(new RoutedEventArgs(TerminalNodeSelectionChangedEvent, sender));
};
}
}
}));
/// <summary>
/// 设置或返回TreeView数据源。
/// </summary>
public TreeNode TreeRoot
{
get => (TreeNode)GetValue(TreeRootProperty);
set => SetValue(TreeRootProperty, value);
}
public static readonly DependencyProperty PresetGroupsFolderNameProperty = DependencyProperty.Register(
"PresetGroupsFolderName", typeof(string), typeof(ParameterNodeTreeViewControl),
new PropertyMetadata(default(string)));
/// <summary>
/// 设置或返回存放预设组信息的子文件夹名称。
/// </summary>
public string PresetGroupsFolderName
{
get => (string)GetValue(PresetGroupsFolderNameProperty);
set => SetValue(PresetGroupsFolderNameProperty, value);
}
#endregion
#region Routed Events
// Register a custom routed event using the Bubble routing strategy.
public static readonly RoutedEvent TerminalNodeSelectionChangedEvent = EventManager.RegisterRoutedEvent(
name: nameof(TerminalNodeSelectionChanged),
routingStrategy: RoutingStrategy.Bubble,
handlerType: typeof(RoutedEventHandler),
ownerType: typeof(ParameterNodeTreeViewControl));
// Provide CLR accessors for assigning an event handler.
public event RoutedEventHandler TerminalNodeSelectionChanged
{
add => AddHandler(TerminalNodeSelectionChangedEvent, value);
remove => RemoveHandler(TerminalNodeSelectionChangedEvent, value);
}
#endregion
#region Methods
/// <summary>
/// 返回组信息文件名的完整路径。
/// </summary>
/// <param name="groupName">组名称</param>
/// <returns></returns>
private string GetPresetGroupFullFileName(string groupName)
{
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, PRESET_GROUP_SUB_FOLDER_NAME,
PresetGroupsFolderName, groupName + ".json");
}
/// <summary>
/// 返回保存组信息的文件夹名称。
/// </summary>
/// <returns></returns>
private string GetPresetGroupsFolderName()
{
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, PRESET_GROUP_SUB_FOLDER_NAME,
PresetGroupsFolderName);
}
/// <summary>
/// 加载指定文件夹内的所有json文件。
/// </summary>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
private void LoadPresetGroupFilesList(string selectedGroupName = "")
{
if (string.IsNullOrEmpty(PresetGroupsFolderName))
throw new ArgumentException("the preset group files folder is not set.",
paramName: nameof(PresetGroupsFolderName));
var folderName = GetPresetGroupsFolderName();
var previousSelection = selectedGroupName;
// 如果未指定下次待加载的项目,则保存当前的选择
if (string.IsNullOrEmpty(previousSelection))
if (cbxPresetList.SelectedItem != null)
previousSelection = cbxPresetList.SelectedItem.ToString();
// 如果文件夹不存在,返回空列表
if (!Directory.Exists(folderName))
{
Directory.CreateDirectory(folderName);
cbxPresetList.ItemsSource = new List<string>();
}
else
{
var source =
Directory.EnumerateFiles(folderName, "*.json")
.Select(Path.GetFileNameWithoutExtension)
.ToList();
cbxPresetList.ItemsSource = source;
// 重新选择上次的选择
if (string.IsNullOrEmpty(previousSelection) == false)
{
if (source.FirstOrDefault(x => x == previousSelection) != null)
cbxPresetList.SelectedItem = previousSelection;
}
else
{
// 如果TreeView还没有加载内容则不要自动选择
if (TreeRoot != null)
cbxPresetList.SelectedIndex = 0;
}
}
}
/// <summary>
/// 仅清空Group下拉框的选项而不清除TreeView的选择状态。
/// <para>通常用于DataGrid中删除条目后清除Group选项。</para>
/// </summary>
public void ClearPresetGroupSelectionOnly()
{
_clearGroupSelectionOnly = true;
cbxPresetList.SelectedIndex = -1;
_clearGroupSelectionOnly = false;
}
#endregion
#region Events
/// <summary>
/// 重新加载组列表。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnRefreshPresetList_OnClick(object sender, RoutedEventArgs e)
{
try
{
LoadPresetGroupFilesList();
}
catch (Exception ex)
{
var err = $"Unable to refresh the group list, {ex.Message}";
MessageBox.Show(err, "Error", MessageBoxButton.OK,
MessageBoxImage.Error);
}
}
/// <summary>
/// 新建组。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnNewGroup_OnClick(object sender, RoutedEventArgs e)
{
try
{
TreeRoot.UnselectAll();
cbxPresetList.SelectedIndex = -1;
}
catch (Exception ex)
{
var err = $"Unable to create new group, {ex.Message}";
MessageBox.Show(err, "Error", MessageBoxButton.OK,
MessageBoxImage.Error);
}
}
/// <summary>
/// 保存组。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnSave_OnClick(object sender, RoutedEventArgs e)
{
var groupName = "";
//if (TreeRoot.SelectedTerminalCount > TreeNode.QUERY_LIMIT_COUNT)
//{
// MessageBox.Show($"Too many items are selected, it's limited to {TreeNode.QUERY_LIMIT_COUNT}.",
// "Error", MessageBoxButton.OK,
// MessageBoxImage.Error);
// return;
//}
if (cbxPresetList.SelectedIndex == -1)
{
var dlg = new PresetGroupSaveDialog("Save Group", cbxPresetList.ItemsSource?.Cast<string>());
var ret = dlg.ShowDialog();
if (ret.HasValue && ret.Value == true)
{
groupName = dlg.GroupName;
}
else
{
return;
}
}
else
{
groupName = cbxPresetList.SelectedItem.ToString();
}
try
{
// 保存
TreeNodeSelectionGroupInfo.SaveToJsonFile(GetPresetGroupFullFileName(groupName), TreeRoot);
LoadPresetGroupFilesList(groupName);
}
catch (Exception ex)
{
var err = $"Unable to save group {groupName}, {ex.Message}";
MessageBox.Show(err, "Error", MessageBoxButton.OK,
MessageBoxImage.Error);
}
}
/// <summary>
/// 另存为组。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnSaveAs_OnClick(object sender, RoutedEventArgs e)
{
if (cbxPresetList.SelectedIndex == -1)
{
MessageBox.Show("No group is selected.", "Error", MessageBoxButton.OK,
MessageBoxImage.Error);
return;
}
var newName = $"Copy of {cbxPresetList.SelectedValue}";
var dlg = new PresetGroupSaveDialog("Save As Group",
cbxPresetList.ItemsSource?.Cast<string>(),
newName);
var ret = dlg.ShowDialog();
if (ret.HasValue && ret.Value)
{
var groupName = cbxPresetList.SelectedItem.ToString();
try
{
// 保存
TreeNodeSelectionGroupInfo.SaveToJsonFile(GetPresetGroupFullFileName(groupName), TreeRoot);
// 保存一个空文件
TreeNodeSelectionGroupInfo.SaveToJsonFile(GetPresetGroupFullFileName(dlg.GroupName), TreeRoot);
LoadPresetGroupFilesList(dlg.GroupName);
}
catch (Exception ex)
{
var err = $"Unable to save as group {groupName}, {ex.Message}";
MessageBox.Show(err, "Error", MessageBoxButton.OK,
MessageBoxImage.Error);
}
}
}
/// <summary>
/// 选择组。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CbxPresetList_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (cbxPresetList.SelectedIndex == -1)
{
//
if (_clearGroupSelectionOnly)
return;
TreeRoot.UnselectAll();
return;
}
var groupName = cbxPresetList.SelectedValue.ToString();
try
{
TreeNodeSelectionGroupInfo.RecoveryFromJsonFile(GetPresetGroupFullFileName(groupName), TreeRoot);
}
catch (Exception ex)
{
var err = $"Unable to recovery group {groupName}, {ex.Message}";
MessageBox.Show(err, "Error", MessageBoxButton.OK,
MessageBoxImage.Error);
}
}
/// <summary>
/// 删除组。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnDelete_OnClick(object sender, RoutedEventArgs e)
{
// 如果没选中任何组,忽略操作
if (cbxPresetList.SelectedIndex == -1)
return;
var groupName = cbxPresetList.SelectedItem.ToString();
if (string.IsNullOrEmpty(groupName))
return;
var ret = MessageBox.Show($"Are you sure to delete the group {groupName}", "Warning",
MessageBoxButton.YesNo, MessageBoxImage.Question);
if (ret == MessageBoxResult.Yes)
{
try
{
FileSystem.DeleteFile(GetPresetGroupFullFileName(groupName), UIOption.OnlyErrorDialogs,
RecycleOption.SendToRecycleBin);
LoadPresetGroupFilesList();
}
catch (Exception ex)
{
var err = $"Unable to delete group {groupName}, {ex.Message}";
MessageBox.Show(err, "Error", MessageBoxButton.OK,
MessageBoxImage.Error);
}
}
}
/// <summary>
/// 折叠所有节点。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnCollapseAll_OnClick(object sender, RoutedEventArgs e)
{
TreeRoot.CollapseAll();
}
/// <summary>
/// 展开所有节点。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnExpandAll_OnClick(object sender, RoutedEventArgs e)
{
TreeRoot.ExpandAll();
}
/// <summary>
/// 应用筛选器。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <exception cref="NotImplementedException"></exception>
private void BtnApplyFilter_OnClick(object sender, RoutedEventArgs e)
{
TreeRoot.SuspendUpdate();
TreeRoot.ApplyFilter(txtFilterKeyword.Text);
TreeRoot.ResumeUpdate();
txtFilterKeyword.SelectAll();
txtFilterKeyword.Focus();
}
/// <summary>
/// 清除筛选器
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnClearFilter_OnClick(object sender, RoutedEventArgs e)
{
TreeRoot.SuspendUpdate();
TreeRoot.ClearFilter();
TreeRoot.ResumeUpdate();
txtFilterKeyword.Text = "";
txtFilterKeyword.Focus();
}
private void TxtFilterKeyword_OnKeyDown(object sender, KeyEventArgs e)
{
if (e.Key != Key.Enter)
return;
TreeRoot.ApplyFilter(txtFilterKeyword.Text);
txtFilterKeyword.SelectAll();
txtFilterKeyword.Focus();
}
private void BtnShowSelectedOnly_OnClick(object sender, RoutedEventArgs e)
{
TreeRoot.ShowSelectedOnly();
}
private void BtnShowAll_OnClick(object sender, RoutedEventArgs e)
{
TreeRoot.ShowAll();
}
#endregion
}
}