Change folder structure

This commit is contained in:
Duc Le
2025-06-13 13:21:12 -07:00
parent b1e8a35899
commit 11c162e7a3
116 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,97 @@
//******************************************************************************//
// AsyncObservableCollection.cs
// 12/4/2023
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// POC: Alex Kravchenko (1118268)
//******************************************************************************//
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Threading;
namespace Raytheon.LogDashboard.Helpers
{
public class AsyncObservableCollection<T> : ObservableCollection<T>
{
private readonly SynchronizationContext synchronizationContext = SynchronizationContext.Current;
public AsyncObservableCollection()
{
}
public AsyncObservableCollection(IEnumerable<T> list)
: base(list)
{
}
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if(SynchronizationContext.Current == synchronizationContext)
{
// Execute the CollectionChanged event on the current thread
RaiseCollectionChanged(e);
}
else
{
// Raises the CollectionChanged event on the creator thread
synchronizationContext.Send(RaiseCollectionChanged, e);
}
}
private void RaiseCollectionChanged(object param)
{
// We are in the creator thread, call the base implementation directly
base.OnCollectionChanged((NotifyCollectionChangedEventArgs)param);
}
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
if(SynchronizationContext.Current == synchronizationContext)
{
// Execute the PropertyChanged event on the current thread
RaisePropertyChanged(e);
}
else
{
// Raises the PropertyChanged event on the creator thread
synchronizationContext.Send(RaisePropertyChanged, e);
}
}
private void RaisePropertyChanged(object param)
{
// We are in the creator thread, call the base implementation directly
base.OnPropertyChanged((PropertyChangedEventArgs)param);
}
}
}

View File

@@ -0,0 +1,92 @@
//******************************************************************************//
// BindableSelectedItemBehavior.cs
// 12/4/2023
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// POC: Alex Kravchenko (1118268)
//******************************************************************************//
using System.Windows.Controls;
using System.Windows;
using System.Windows.Interactivity;
namespace Raytheon.LogDashboard.Helpers
{
/// <summary>
/// Behavior that makes the
/// <see>
/// <cref>System.Windows.Controls.TreeView.SelectedItem</cref>
/// </see>
/// bindable.
/// </summary>
public class BindableSelectedItemBehavior : Behavior<TreeView>
{
#region SelectedItem Property
public object SelectedItem
{
get => GetValue(SelectedItemProperty);
set => SetValue(SelectedItemProperty, value);
}
public static readonly DependencyProperty SelectedItemProperty =
DependencyProperty.Register("SelectedItem", typeof(object), typeof(BindableSelectedItemBehavior), new UIPropertyMetadata(null, OnSelectedItemChanged));
private static void OnSelectedItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
TreeViewItem item = e.NewValue as TreeViewItem;
item?.SetValue(TreeViewItem.IsSelectedProperty, true);
}
#endregion
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.SelectedItemChanged += OnTreeViewSelectedItemChanged;
}
protected override void OnDetaching()
{
base.OnDetaching();
if(AssociatedObject != null)
{
AssociatedObject.SelectedItemChanged -= OnTreeViewSelectedItemChanged;
}
}
private void OnTreeViewSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
SelectedItem = e.NewValue;
}
}
}

View File

@@ -0,0 +1,102 @@
//******************************************************************************//
// EnumerationExtension.cs
// 12/4/2023
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// POC: Alex Kravchenko (1118268)
//******************************************************************************//
using System;
using System.ComponentModel;
using System.Linq;
using System.Windows.Markup;
namespace Raytheon.LogDashboard.Helpers
{
public class EnumerationExtension : MarkupExtension
{
private Type _enumType;
public EnumerationExtension(Type enumType)
{
EnumType = enumType ?? throw new ArgumentNullException(nameof(enumType));
}
public Type EnumType
{
get { return _enumType; }
private set
{
if(_enumType == value)
{
return;
}
var enumType = Nullable.GetUnderlyingType(value) ?? value;
if(enumType.IsEnum == false)
{
throw new ArgumentException("Type must be an Enum.");
}
_enumType = value;
}
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
var enumValues = Enum.GetValues(EnumType);
return (
from object enumValue in enumValues
select new EnumerationMember
{
Value = enumValue,
Description = GetDescription(enumValue)
}).ToArray();
}
private string GetDescription(object enumValue)
{
return EnumType
.GetField(enumValue.ToString())
.GetCustomAttributes(typeof(DescriptionAttribute), false)
.FirstOrDefault() is DescriptionAttribute descriptionAttribute
? descriptionAttribute.Description
: enumValue.ToString();
}
public class EnumerationMember
{
public string Description { get; set; }
public object Value { get; set; }
}
}
}

View File

@@ -0,0 +1,280 @@
//******************************************************************************//
// ExtensionMethods.cs
// 12/4/2023
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// POC: Alex Kravchenko (1118268)
//******************************************************************************//
using Raytheon.LogDashboard.Model;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Media;
namespace Raytheon.LogDashboard.Helpers
{
public static class ExtensionMethods
{
/// <summary>
/// Checks whether a FileInfo or DirectoryInfo object is a directory, or intended to be a directory.
/// </summary>
/// <param name="fileSystemInfo"></param>
/// <returns></returns>
public static bool IsDirectory(this FileSystemInfo fileSystemInfo)
{
if(fileSystemInfo == null)
{
return false;
}
if((int)fileSystemInfo.Attributes != -1)
{
// if attributes are initialized check the directory flag
return fileSystemInfo.Attributes.HasFlag(FileAttributes.Directory);
}
// If we get here the file probably doesn't exist yet. The best we can do is
// try to judge intent. Because directories can have extensions and files
// can lack them, we can't rely on filename.
//
// We can reasonably assume that if the path doesn't exist yet and
// FileSystemInfo is a DirectoryInfo, a directory is intended. FileInfo can
// make a directory, but it would be a bizarre code path.
return fileSystemInfo is DirectoryInfo;
}
public static string FirstCharToUpper(this string input)
{
switch(input)
{
case null:
throw new ArgumentNullException(nameof(input));
case "":
throw new ArgumentException($"{nameof(input)} cannot be empty", nameof(input));
default:
return input.First().ToString().ToUpper() + input.Substring(1);
}
}
public static bool Contains(this string source, string toCheck, StringComparison comp)
{
return source?.IndexOf(toCheck, comp) >= 0;
}
public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> source, int N)
{
return source.Skip(Math.Max(0, source.Count() - N));
}
public static IEnumerable<TSource> DistinctBy<TSource, TKey>
(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
HashSet<TKey> seenKeys = new HashSet<TKey>();
foreach(TSource element in source)
{
if(seenKeys.Add(keySelector(element)))
{
yield return element;
}
}
}
/// <summary>
/// Convert the Brush to a ARGB - Color.
/// </summary>
/// <param name="brush">your object</param>
/// <returns>
/// White = #ffffffff
/// Green = #ff00ff00
/// </returns>
public static string ToARGB(this SolidColorBrush brush)
{
if(brush == null)
{
throw new ArgumentNullException();
}
var c = brush.Color;
return $"#{c.A:X2}{c.R:X2}{c.G:X2}{c.B:X2}";
}
/// <summary>
/// set the current brush to a new color based on the #argb string
/// </summary>
/// <param name="brush">your object</param>
/// <param name="argb">The #ARGB Color</param>
/// <returns>the same object as you run the function</returns>
public static SolidColorBrush FromARGB(this SolidColorBrush brush, string argb)
{
if(argb.Length != 9)
{
throw new FormatException("we need #aarrggbb as color");
}
byte a = Convert.ToByte(int.Parse(argb.Substring(1, 2), NumberStyles.HexNumber));
byte r = Convert.ToByte(int.Parse(argb.Substring(3, 2), NumberStyles.HexNumber));
byte g = Convert.ToByte(int.Parse(argb.Substring(5, 2), NumberStyles.HexNumber));
byte b = Convert.ToByte(int.Parse(argb.Substring(7, 2), NumberStyles.HexNumber));
Color c = Color.FromArgb(a, r, g, b);
brush.Color = c;
return brush;
}
public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source, IEqualityComparer<T> comparer = null)
{
return new HashSet<T>(source.ToList(), comparer);
}
/// <summary>
/// returns true if string contains any of the members in search array
/// </summary>
/// <param name="line"></param>
/// <param name="search"></param>
/// <param name="ignoreCase"></param>
/// <returns></returns>
public static bool ContainsAnyOf(this String line, string[] search, bool ignoreCase = false)
{
return search.Any(x => ignoreCase ? line.ToUpper().Contains(x.ToUpper()) : line.Contains(x));
}
/// <summary>
/// returns true if string contains any of the members in search list patterns
/// </summary>
/// <param name="input"></param>
/// <param name="patterns"></param>
/// <param name="ignoreCase"></param>
/// <returns></returns>
public static bool ContainsAnyOfPattern(this string input, string[] patterns, bool ignoreCase = false)
{
foreach(string pattern in patterns)
{
if(Regex.IsMatch(input, pattern, ignoreCase ? RegexOptions.IgnoreCase : RegexOptions.None))
{
return true;
}
}
return false;
}
/// <summary>
/// does the string begins with regex pattern?
/// </summary>
/// <param name="input"></param>
/// <param name="pattern"></param>
/// <returns></returns>
public static bool StartsWithPattern(this string input, string pattern)
{
if(string.IsNullOrEmpty(input))
{
return false;
}
return Regex.IsMatch(input, $"^{pattern}");
}
/// <summary>
/// truncates DateTime
/// </summary>
/// <param name="dateTime"></param>
/// <param name="timeSpan"></param>
/// <returns></returns>
public static DateTime Truncate(this DateTime dateTime, TimeSpan timeSpan)
{
if(timeSpan == TimeSpan.Zero)
{
return dateTime; // Or could throw an ArgumentException
}
if(dateTime == DateTime.MinValue || dateTime == DateTime.MaxValue)
{
return dateTime; // do not modify "guard" values
}
return dateTime.AddTicks(-(dateTime.Ticks % timeSpan.Ticks));
}
/// <summary>
/// filters log messages from the main list
/// </summary>
/// <param name="messages"></param>
/// <param name="text"></param>
/// <param name="matchCase"></param>
/// <param name="matchWholeWord"></param>
/// <param name="useRegularExp"></param>
/// <param name="level"></param>
/// <returns></returns>
public static IEnumerable<LogMessage> Filter(this IEnumerable<LogMessage> messages,
string text,
bool matchCase,
bool matchWholeWord,
bool useRegularExp,
DashboardLogLevel level = DashboardLogLevel.Trace)
{
IEnumerable<LogMessage> searchResult = messages.ToList();
if(!matchCase && !matchWholeWord)
{
return searchResult.Where(x => level.HasFlag(x.Level) &&
(x.Message.ToUpper().Contains(text, StringComparison.OrdinalIgnoreCase) ||
(useRegularExp && Regex.IsMatch(x.Message.ToUpper(), text, RegexOptions.IgnoreCase))));
}
if(matchCase && !matchWholeWord)
{
return searchResult.Where(x => level.HasFlag(x.Level) && (x.Message.Contains(text) || (useRegularExp && Regex.IsMatch(x.Message, text))));
}
if(matchCase && matchWholeWord)
{
return searchResult.Where(x => level.HasFlag(x.Level) && (x.Message.Contains($" {text} ") ||
x.Message.StartsWith($"{text} ") ||
x.Message.EndsWith($" {text}") ||
(x.Message.StartsWith(text) && x.Message.EndsWith(text)) ||
(useRegularExp && Regex.IsMatch(x.Message, text))));
}
if(!matchCase && matchWholeWord)
{
return searchResult.Where(x => (level.HasFlag(x.Level) && (x.Message.Contains($" {text} ", StringComparison.OrdinalIgnoreCase) ||
x.Message.StartsWith($"{text} ", StringComparison.OrdinalIgnoreCase) ||
x.Message.EndsWith($" {text}", StringComparison.OrdinalIgnoreCase) ||
(x.Message.StartsWith(text, StringComparison.OrdinalIgnoreCase) &&
x.Message.EndsWith(text, StringComparison.OrdinalIgnoreCase)))) ||
(useRegularExp && Regex.IsMatch(x.Message.ToUpper(), text, RegexOptions.IgnoreCase)));
}
return searchResult;
}
}
}

View File

@@ -0,0 +1,101 @@
//******************************************************************************//
// FileWatcher.cs
// 12/4/2023
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// POC: Alex Kravchenko (1118268)
//******************************************************************************//
using Raytheon.LogDashboard.Model;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace Raytheon.LogDashboard.Helpers
{
public class FileWatcher
{
private CancellationTokenSource cancellationToken;
public string FilePath { get; set; }
public long Position { get; set; }
public LogTemplate Template { get; set; }
public ImportLogFile ImportLogFile { get; set; }
public event EventHandler<FileWatcher> FileChanged;
/// <summary>
/// starts watching the file for changes with hard-coded one sec interval
/// </summary>
public void StartWatch()
{
cancellationToken = new CancellationTokenSource();
Task.Run(() =>
{
while(true)
{
if(cancellationToken.Token.IsCancellationRequested)
{
return;
}
long currentLength;
using(FileStream stream = File.Open(FilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
currentLength = stream.Length;
}
if(currentLength > Position)
{
OnFileChanged(this);
}
Position = currentLength;
Thread.Sleep(1000);
}
});
}
public void StopWatch()
{
cancellationToken.Cancel();
}
protected virtual void OnFileChanged(FileWatcher fileWatcher)
{
FileChanged?.Invoke(this, fileWatcher);
}
}
}

View File

@@ -0,0 +1,255 @@
//******************************************************************************//
// SearchableTextControl.cs
// 12/4/2023
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// POC: Alex Kravchenko (1118268)
//******************************************************************************//
// Ignore Spelling: Searchable
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows;
namespace Raytheon.LogDashboard.Helpers
{
public class SearchableTextControl : Control
{
static SearchableTextControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(SearchableTextControl),
new FrameworkPropertyMetadata(typeof(SearchableTextControl)));
}
#region DependencyProperties
/// <summary>
/// Text sandbox which is used to get or set the value from a dependency property.
/// </summary>
public string Text
{
get => (string)GetValue(TextProperty);
set => SetValue(TextProperty, value);
}
// Real implementation about TextProperty which registers a dependency property with
// the specified property name, property type, owner type, and property metadata.
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(SearchableTextControl),
new UIPropertyMetadata(string.Empty,
UpdateControlCallBack));
/// <summary>
/// HighlightBackground sandbox which is used to get or set the value from a dependency property,
/// if it gets a value,it should be forced to bind to a Brushes type.
/// </summary>
public Brush HighlightBackground
{
get => (Brush)GetValue(HighlightBackgroundProperty);
set => SetValue(HighlightBackgroundProperty, value);
}
// Real implementation about HighlightBackgroundProperty which registers a dependency property
// with the specified property name, property type, owner type, and property metadata.
public static readonly DependencyProperty HighlightBackgroundProperty =
DependencyProperty.Register("HighlightBackground", typeof(Brush), typeof(SearchableTextControl),
new UIPropertyMetadata(Brushes.Yellow, UpdateControlCallBack));
/// <summary>
/// HighlightForeground sandbox which is used to get or set the value from a dependency property,
/// if it gets a value,it should be forced to bind to a Brushes type.
/// </summary>
public Brush HighlightForeground
{
get => (Brush)GetValue(HighlightForegroundProperty);
set => SetValue(HighlightForegroundProperty, value);
}
// Real implementation about HighlightForegroundProperty which registers a dependency property with
// the specified property name, property type, owner type, and property metadata.
public static readonly DependencyProperty HighlightForegroundProperty =
DependencyProperty.Register("HighlightForeground", typeof(Brush), typeof(SearchableTextControl),
new UIPropertyMetadata(Brushes.Black, UpdateControlCallBack));
/// <summary>
/// IsMatchCase sandbox which is used to get or set the value from a dependency property,
/// if it gets a value,it should be forced to bind to a bool type.
/// </summary>
public bool IsMatchCase
{
get => (bool)GetValue(IsMatchCaseProperty);
set => SetValue(IsMatchCaseProperty, value);
}
// Real implementation about IsMatchCaseProperty which registers a dependency property with
// the specified property name, property type, owner type, and property metadata.
public static readonly DependencyProperty IsMatchCaseProperty =
DependencyProperty.Register("IsMatchCase", typeof(bool), typeof(SearchableTextControl),
new UIPropertyMetadata(true, UpdateControlCallBack));
/// <summary>
/// IsHighlight sandbox which is used to get or set the value from a dependency property,
/// if it gets a value,it should be forced to bind to a bool type.
/// </summary>
public bool IsHighlight
{
get => (bool)GetValue(IsHighlightProperty);
set => SetValue(IsHighlightProperty, value);
}
// Real implementation about IsHighlightProperty which registers a dependency property with
// the specified property name, property type, owner type, and property metadata.
public static readonly DependencyProperty IsHighlightProperty =
DependencyProperty.Register("IsHighlight", typeof(bool), typeof(SearchableTextControl),
new UIPropertyMetadata(false, UpdateControlCallBack));
/// <summary>
/// SearchText sandbox which is used to get or set the value from a dependency property,
/// if it gets a value,it should be forced to bind to a string type.
/// </summary>
public string SearchText
{
get => (string)GetValue(SearchTextProperty);
set => SetValue(SearchTextProperty, value);
}
/// <summary>
/// Real implementation about SearchTextProperty which registers a dependency property with
/// the specified property name, property type, owner type, and property metadata.
/// </summary>
public static readonly DependencyProperty SearchTextProperty =
DependencyProperty.Register("SearchText", typeof(string), typeof(SearchableTextControl),
new UIPropertyMetadata(string.Empty, UpdateControlCallBack));
/// <summary>
/// Create a call back function which is used to invalidate the rendering of the element,
/// and force a complete new layout pass.
/// One such advanced scenario is if you are creating a PropertyChangedCallback for a
/// dependency property that is not on a Freezable or FrameworkElement derived class that
/// still influences the layout when it changes.
/// </summary>
private static void UpdateControlCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
SearchableTextControl obj = d as SearchableTextControl;
obj.InvalidateVisual();
}
#endregion
/// <summary>
/// override the OnRender method which is used to search for the keyword and highlight
/// it when the operation gets the result.
/// </summary>
protected override void OnRender(DrawingContext drawingContext)
{
// Define a TextBlock to hold the search result.
TextBlock displayTextBlock = Template.FindName("PART_TEXT", this) as TextBlock;
displayTextBlock.TextWrapping = TextWrapping.NoWrap;
if(string.IsNullOrEmpty(Text))
{
base.OnRender(drawingContext);
return;
}
if(!IsHighlight)
{
displayTextBlock.Text = Text;
base.OnRender(drawingContext);
return;
}
displayTextBlock.Inlines.Clear();
string searchstring = IsMatchCase ? SearchText : SearchText.ToUpper();
string compareText = IsMatchCase ? Text : Text.ToUpper();
string displayText = Text;
Run run;
while(!string.IsNullOrEmpty(searchstring) && compareText.IndexOf(searchstring) >= 0)
{
int position = compareText.IndexOf(searchstring);
run = GenerateRun(displayText.Substring(0, position), false);
if(run != null)
{
displayTextBlock.Inlines.Add(run);
}
run = GenerateRun(displayText.Substring(position, searchstring.Length), true);
if(run != null)
{
displayTextBlock.Inlines.Add(run);
}
compareText = compareText.Substring(position + searchstring.Length);
displayText = displayText.Substring(position + searchstring.Length);
}
run = GenerateRun(displayText, false);
if(run != null)
{
displayTextBlock.Inlines.Add(run);
}
base.OnRender(drawingContext);
}
/// <summary>
/// Set inline-level flow content element intended to contain a run of formatted or unformatted
/// text into your background and foreground setting.
/// </summary>
private Run GenerateRun(string searchedString, bool isHighlight)
{
if(!string.IsNullOrEmpty(searchedString))
{
Run run = new Run(searchedString)
{
Background = isHighlight ? HighlightBackground : Background,
Foreground = isHighlight ? HighlightForeground : Foreground,
// Set the source text with the style which is Bold.
FontWeight = isHighlight ? FontWeights.Bold : FontWeights.Normal,
};
return run;
}
return null;
}
}
}

View File

@@ -0,0 +1,298 @@
//******************************************************************************//
// StringExtensions.cs
// 12/4/2023
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// POC: Alex Kravchenko (1118268)
//******************************************************************************//
using System;
using System.Globalization;
using System.Text.RegularExpressions;
namespace Raytheon.LogDashboard.Helpers
{
public static class StringExtensions
{
/// <summary>
/// takes the left of the string from given index
/// </summary>
/// <param name="value"></param>
/// <param name="maxLength"></param>
/// <returns></returns>
public static string Left(this string value, int maxLength)
{
if(string.IsNullOrEmpty(value))
{
return string.Empty;
}
maxLength = Math.Abs(maxLength);
return (value.Length <= maxLength ? value : value.Substring(0, maxLength));
}
/// <summary>
/// takes a left of a string from given character
/// </summary>
/// <param name="value"></param>
/// <param name="character"></param>
/// <returns></returns>
public static string LeftFrom(this string value, char character)
{
if(string.IsNullOrEmpty(value))
{
return string.Empty;
}
int index = value.IndexOf(character);
if(index == -1)
{
return value;
}
return value.Substring(0, index);
}
/// <summary>
/// takes a left of a string from given string
/// </summary>
/// <param name="value"></param>
/// <param name="characters"></param>
/// <returns></returns>
public static string LeftFrom(this string value, string characters)
{
if(string.IsNullOrEmpty(value))
{
return string.Empty;
}
int index = value.IndexOf(characters);
if(index == -1)
{
return value;
}
return value.Substring(0, index);
}
/// <summary>
/// takes a left of a string from given regular expression
/// </summary>
/// <param name="value"></param>
/// <param name="regex"></param>
/// <returns></returns>
public static string LeftFromRegex(this string value, string regex)
{
if(string.IsNullOrEmpty(value))
{
return string.Empty;
}
Match match = Regex.Match(value, regex);
if(!match.Success)
{
return value;
}
return value.Substring(0, match.Index);
}
/// <summary>
/// takes a right of a string from given length
/// </summary>
/// <param name="value"></param>
/// <param name="length"></param>
/// <returns></returns>
public static string Right(this string value, int length)
{
if(string.IsNullOrEmpty(value))
{
return string.Empty;
}
return value.Length <= length ? value : value.Substring(value.Length - length);
}
/// <summary>
/// takes a right of a string from given character
/// </summary>
/// <param name="value"></param>
/// <param name="character"></param>
/// <returns></returns>
public static string RightFrom(this string value, char character)
{
if(string.IsNullOrEmpty(value))
{
return string.Empty;
}
int index = value.LastIndexOf(character);
if(index == -1)
{
return value;
}
return value.Substring(index + 1);
}
/// <summary>
/// takes a right of a string from given string including that string
/// </summary>
/// <param name="value"></param>
/// <param name="characters"></param>
/// <returns></returns>
public static string RightFrom(this string value, string characters)
{
if(string.IsNullOrEmpty(value))
{
return string.Empty;
}
int index = value.LastIndexOf(characters);
if(index == -1)
{
return value;
}
return value.Substring(index);
}
/// <summary>
/// takes a right of a string from given string not including the string
/// </summary>
/// <param name="value"></param>
/// <param name="characters"></param>
/// <returns></returns>
public static string RightAfter(this string value, string characters)
{
if(string.IsNullOrEmpty(value))
{
return string.Empty;
}
int index = value.LastIndexOf(characters);
if(index == -1)
{
return value;
}
if(value.Length > index + characters.Length)
{
return value.Substring(index + characters.Length);
}
else
{
return string.Empty;
}
}
/// <summary>
/// takes a right of a string form given regular expression
/// </summary>
/// <param name="value"></param>
/// <param name="regex"></param>
/// <returns></returns>
public static string RightFromRegex(this string value, string regex)
{
if(string.IsNullOrEmpty(value))
{
return string.Empty;
}
Match match = Regex.Match(value, regex);
if(!match.Success)
{
return value;
}
return value.Substring(match.Index + match.Length);
}
/// <summary>
/// returns the first match of the regular expression
/// </summary>
/// <param name="input"></param>
/// <param name="pattern"></param>
/// <returns></returns>
public static string GetFirstMatch(this string input, string pattern)
{
var match = Regex.Match(input, pattern);
return match.Groups[0].Value;
}
/// <summary>
/// reads the next value after provided identifier
/// for example:
/// in the string RESULT=123 and identifier = RESULT this function returns 123
/// </summary>
/// <param name="input"></param>
/// <param name="identifier"></param>
/// <returns></returns>
public static T GetValueAfterIdentifier<T>(this string input, string identifier) => TypeConverter.ChangeType<T>(GetFirstMatch(input, $"(?<={identifier}=)[^ ]+|$"));
/// <summary>
/// checks for numeric value
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static bool IsNumeric(this string input)
{
if(string.IsNullOrEmpty(input))
{
return false;
}
return Regex.IsMatch(input.Trim(), @"^[\d.-]+$");
}
/// <summary>
/// converts string to Pascal Case
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public static string ToPascalCase(this string text)
{
string yourString = text.ToLower().Replace("_", " ");
TextInfo info = CultureInfo.CurrentCulture.TextInfo;
return info.ToTitleCase(yourString).Replace(" ", string.Empty);
}
}
}

View File

@@ -0,0 +1,136 @@
//******************************************************************************//
// TVIExtender.cs
// 12/4/2023
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// POC: Alex Kravchenko (1118268)
//******************************************************************************//
using System.Windows.Controls.Primitives;
using System.Windows.Controls;
using System.Windows;
namespace Raytheon.LogDashboard.Helpers
{
public class TVIExtender
{
private TreeViewItem item;
public static DependencyProperty UseExtenderProperty =
DependencyProperty.RegisterAttached("UseExtender", typeof(bool), typeof(TVIExtender),
new PropertyMetadata(false, OnChangedUseExtender));
public static bool GetUseExtender(DependencyObject sender)
{
return (bool)sender.GetValue(UseExtenderProperty);
}
public static void SetUseExtender(DependencyObject sender, bool useExtender)
{
sender.SetValue(UseExtenderProperty, useExtender);
}
private static void OnChangedUseExtender(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
if(sender is TreeViewItem item)
{
if((bool)e.NewValue)
{
if(item.ReadLocalValue(ItemExtenderProperty) == DependencyProperty.UnsetValue)
{
TVIExtender extender = new TVIExtender(item);
item.SetValue(ItemExtenderProperty, extender);
}
}
else
{
if(item.ReadLocalValue(ItemExtenderProperty) != DependencyProperty.UnsetValue)
{
TVIExtender extender = (TVIExtender)item.ReadLocalValue(ItemExtenderProperty);
extender.Detach();
item.SetValue(ItemExtenderProperty, DependencyProperty.UnsetValue);
}
}
}
}
public static DependencyProperty ItemExtenderProperty =
DependencyProperty.RegisterAttached("ItemExtender", typeof(TVIExtender), typeof(TVIExtender));
public static DependencyProperty IsLastOneProperty =
DependencyProperty.RegisterAttached("IsLastOne", typeof(bool), typeof(TVIExtender));
public static bool GetIsLastOne(DependencyObject sender)
{
return (bool)sender.GetValue(IsLastOneProperty);
}
public static void SetIsLastOne(DependencyObject sender, bool isLastOne)
{
sender.SetValue(IsLastOneProperty, isLastOne);
}
public TVIExtender(TreeViewItem item)
{
this.item = item;
ItemsControl ic = ItemsControl.ItemsControlFromItemContainer(this.item);
ic.ItemContainerGenerator.ItemsChanged += OnItemsChangedItemContainerGenerator;
item.SetValue(IsLastOneProperty, ic.ItemContainerGenerator.IndexFromContainer(this.item) == ic.Items.Count - 1);
}
private void OnItemsChangedItemContainerGenerator(object sender, ItemsChangedEventArgs e)
{
ItemsControl ic = ItemsControl.ItemsControlFromItemContainer(item);
if(null != ic)
{
item.SetValue(IsLastOneProperty, ic.ItemContainerGenerator.IndexFromContainer(item) == ic.Items.Count - 1);
}
}
private void Detach()
{
if(item != null)
{
ItemsControl ic = ItemsControl.ItemsControlFromItemContainer(item);
if(ic == null)
{
return;
}
ic.ItemContainerGenerator.ItemsChanged -= OnItemsChangedItemContainerGenerator;
item = null;
}
}
}
}

View File

@@ -0,0 +1,91 @@
//******************************************************************************//
// TypeConverter.cs
// 12/4/2023
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// POC: Alex Kravchenko (1118268)
//******************************************************************************//
using System;
using System.ComponentModel;
namespace Raytheon.LogDashboard.Helpers
{
//
// Summary:
// type conversion utility with a special case for enums
public static class TypeConverter
{
//
// Summary:
// special rule for enumeration when converting a type
//
// Parameters:
// value:
//
// Type parameters:
// T:
public static T ChangeType<T>(object value)
{
if(!typeof(T).IsEnum)
{
return (T)ChangeType(typeof(T), value);
}
return (T)Enum.Parse(typeof(T), value.ToString());
}
//
// Summary:
// convert type with TypeDescriptor
//
// Parameters:
// t:
//
// value:
public static object ChangeType(Type t, object value)
{
return TypeDescriptor.GetConverter(t).ConvertFrom(value);
}
//
// Summary:
// register type with the type descriptor for later conversion
//
// Type parameters:
// T:
//
// TC:
public static void RegisterTypeConverter<T, TC>() where TC : System.ComponentModel.TypeConverter
{
TypeDescriptor.AddAttributes(typeof(T), new TypeConverterAttribute(typeof(TC)));
}
}
}

View File

@@ -0,0 +1,100 @@
//******************************************************************************//
// UnsafeNative.cs
// 12/4/2023
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// POC: Alex Kravchenko (1118268)
//******************************************************************************//
// Ignore Spelling: COPYDATA
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;
namespace Raytheon.LogDashboard.Helpers
{
internal static class UnsafeNative
{
public const int WM_COPYDATA = 0x004A;
public static string GetMessage(int message, IntPtr lParam)
{
if(message == WM_COPYDATA)
{
try
{
var data = Marshal.PtrToStructure<CopyDataStruct>(lParam);
string result = string.Copy(data.LpData);
return result;
}
catch
{
return null;
}
}
return null;
}
public static void SendMessage(IntPtr hwnd, string message)
{
byte[] messageBytes = Encoding.Unicode.GetBytes(message); /* ANSII encoding */
CopyDataStruct data = new CopyDataStruct
{
DwData = IntPtr.Zero,
LpData = message,
CbData = messageBytes.Length + 1 /* +1 because of \0 string termination */
};
if(SendMessage(hwnd, WM_COPYDATA, IntPtr.Zero, ref data) != 0)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("User32.dll", EntryPoint = "SendMessage")]
private static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref CopyDataStruct lParam);
[StructLayout(LayoutKind.Sequential)]
private struct CopyDataStruct
{
public IntPtr DwData;
public int CbData;
[MarshalAs(UnmanagedType.LPWStr)]
public string LpData;
}
}
}