ready for testing

This commit is contained in:
Xjph 2024-01-21 13:35:03 -03:30
commit 97e981bae2
92 changed files with 3058 additions and 1183 deletions

View file

@ -23,7 +23,7 @@
</ItemGroup> </ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Condition=" '$(OS)' == 'Windows_NT' " Command="xcopy &quot;$(TargetPath)&quot; &quot;$(ProjectDir)..\ObservatoryCore\$(OutDir)plugins\&quot; /y" /> <Exec Condition=" '$(OS)' == 'Windows_NT' " Command="xcopy &quot;$(TargetPath)&quot; &quot;$(ProjectDir)..\ObservatoryCore\$(OutDir)..\net6.0-windows\plugins\&quot; /y" />
<Exec Condition=" '$(OS)' != 'Windows_NT' " Command="cp &quot;$(TargetPath)&quot; &quot;$(ProjectDir)../ObservatoryCore/$(OutDir)plugins/&quot; -f" /> <Exec Condition=" '$(OS)' != 'Windows_NT' " Command="cp &quot;$(TargetPath)&quot; &quot;$(ProjectDir)../ObservatoryCore/$(OutDir)plugins/&quot; -f" />
</Target> </Target>

View file

@ -70,6 +70,12 @@
<setting name="StartReadAll" serializeAs="String"> <setting name="StartReadAll" serializeAs="String">
<value>False</value> <value>False</value>
</setting> </setting>
<setting name="Theme" serializeAs="String">
<value>Dark</value>
</setting>
<setting name="ColumnSizing" serializeAs="String">
<value />
</setting>
</Observatory.Properties.Core> </Observatory.Properties.Core>
</userSettings> </userSettings>
</configuration> </configuration>

View file

@ -0,0 +1,73 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Observatory.Assets {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Observatory.Assets.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
/// </summary>
internal static System.Drawing.Icon EOCIcon_Presized {
get {
object obj = ResourceManager.GetObject("EOCIcon_Presized", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
}
}

View file

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="EOCIcon_Presized" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>EOCIcon-Presized.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View file

@ -1,5 +1,6 @@
using Observatory.Framework; using Observatory.Framework;
using Observatory.UI; using Observatory.UI;
using System;
namespace Observatory.NativeNotification namespace Observatory.NativeNotification
{ {
@ -21,6 +22,11 @@ namespace Observatory.NativeNotification
notification.FormClosed += NotifyWindow_Closed; notification.FormClosed += NotifyWindow_Closed;
foreach(var notificationForm in notifications)
{
notificationForm.Value.AdjustOffset(true);
}
notifications.Add(notificationGuid, notification); notifications.Add(notificationGuid, notification);
notification.Show(); notification.Show();
}); });
@ -34,6 +40,11 @@ namespace Observatory.NativeNotification
{ {
var currentNotification = (NotificationForm)sender; var currentNotification = (NotificationForm)sender;
foreach (var notification in notifications.Where(n => n.Value.CreationTime < currentNotification.CreationTime))
{
notification.Value.AdjustOffset(false);
}
if (notifications.ContainsKey(currentNotification.Guid)) if (notifications.ContainsKey(currentNotification.Guid))
{ {
notifications.Remove(currentNotification.Guid); notifications.Remove(currentNotification.Guid);

View file

@ -10,7 +10,7 @@ namespace Observatory.NativeNotification
{ {
public class NativeVoice public class NativeVoice
{ {
private Queue<NotificationArgs> notificationEvents; private readonly Queue<NotificationArgs> notificationEvents;
private bool processing; private bool processing;
public NativeVoice() public NativeVoice()
@ -83,19 +83,23 @@ namespace Observatory.NativeNotification
processing = false; processing = false;
} }
private string AddVoiceToSsml(string ssml, string voiceName) private static string AddVoiceToSsml(string ssml, string voiceName)
{ {
XmlDocument ssmlDoc = new(); XmlDocument ssmlDoc = new();
ssmlDoc.LoadXml(ssml); ssmlDoc.LoadXml(ssml);
var ssmlNamespace = ssmlDoc.DocumentElement.NamespaceURI; var ssmlNamespace = ssmlDoc.DocumentElement?.NamespaceURI;
XmlNamespaceManager ssmlNs = new(ssmlDoc.NameTable); XmlNamespaceManager ssmlNs = new(ssmlDoc.NameTable);
ssmlNs.AddNamespace("ssml", ssmlNamespace); ssmlNs.AddNamespace("ssml", ssmlNamespace ?? string.Empty);
var voiceNode = ssmlDoc.SelectSingleNode("/ssml:speak/ssml:voice", ssmlNs); var voiceNode = ssmlDoc.SelectSingleNode("/ssml:speak/ssml:voice", ssmlNs);
voiceNode.Attributes.GetNamedItem("name").Value = voiceName; var voiceNameNode = voiceNode?.Attributes?.GetNamedItem("name");
if (voiceNameNode != null)
{
voiceNameNode.Value = voiceName;
}
return ssmlDoc.OuterXml; return ssmlDoc.OuterXml;
} }

View file

@ -22,8 +22,9 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Security.Extensions" Version="1.2.0" /> <PackageReference Include="Microsoft.Security.Extensions" Version="1.3.0" />
<PackageReference Include="System.Speech" Version="7.0.0" /> <PackageReference Include="NAudio" Version="2.2.1" />
<PackageReference Include="System.Speech" Version="8.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -33,6 +34,11 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Update="Assets\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Update="Properties\Core.Designer.cs"> <Compile Update="Properties\Core.Designer.cs">
<DesignTimeSharedInput>True</DesignTimeSharedInput> <DesignTimeSharedInput>True</DesignTimeSharedInput>
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
@ -46,6 +52,10 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Update="Assets\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Update="Properties\Resources.resx"> <EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator> <Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
@ -59,6 +69,10 @@
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Resources\" />
</ItemGroup>
<Target Name="PreBuild" BeforeTargets="PreBuildEvent"> <Target Name="PreBuild" BeforeTargets="PreBuildEvent">
<Exec Condition=" '$(OS)' == 'Windows_NT'" Command="if not exist &quot;$(ProjectDir)..\ObservatoryFramework\bin\Release\net6.0\ObservatoryFramework.dll&quot; dotnet build &quot;$(ProjectDir)..\ObservatoryFramework\ObservatoryFramework.csproj&quot; -c Release" /> <Exec Condition=" '$(OS)' == 'Windows_NT'" Command="if not exist &quot;$(ProjectDir)..\ObservatoryFramework\bin\Release\net6.0\ObservatoryFramework.dll&quot; dotnet build &quot;$(ProjectDir)..\ObservatoryFramework\ObservatoryFramework.csproj&quot; -c Release" />
<Exec Condition=" '$(OS)' == 'Windows_NT'" Command="if not exist &quot;$(OutDir)plugins\ObservatoryExplorer.dll&quot; dotnet build &quot;$(ProjectDir)..\ObservatoryExplorer\ObservatoryExplorer.csproj&quot; -c $(ConfigurationName)" /> <Exec Condition=" '$(OS)' == 'Windows_NT'" Command="if not exist &quot;$(OutDir)plugins\ObservatoryExplorer.dll&quot; dotnet build &quot;$(ProjectDir)..\ObservatoryExplorer\ObservatoryExplorer.csproj&quot; -c $(ConfigurationName)" />

View file

@ -14,11 +14,15 @@ namespace Observatory.PluginManagement
private readonly NativeVoice NativeVoice; private readonly NativeVoice NativeVoice;
private readonly NativePopup NativePopup; private readonly NativePopup NativePopup;
private bool OverridePopup;
private bool OverrideAudio;
public PluginCore() public PluginCore(bool OverridePopup = false, bool OverrideAudio = false)
{ {
NativeVoice = new(); NativeVoice = new();
NativePopup = new(); NativePopup = new();
this.OverridePopup = OverridePopup;
this.OverrideAudio = OverrideAudio;
} }
public string Version => System.Reflection.Assembly.GetEntryAssembly()?.GetName().Version?.ToString() ?? "0"; public string Version => System.Reflection.Assembly.GetEntryAssembly()?.GetName().Version?.ToString() ?? "0";
@ -31,10 +35,7 @@ namespace Observatory.PluginManagement
}; };
} }
public Status GetStatus() public Status GetStatus() => LogMonitor.GetInstance.Status;
{
throw new NotImplementedException();
}
public Guid SendNotification(string title, string text) public Guid SendNotification(string title, string text)
{ {
@ -53,12 +54,12 @@ namespace Observatory.PluginManagement
handler?.Invoke(this, notificationArgs); handler?.Invoke(this, notificationArgs);
} }
if (Properties.Core.Default.NativeNotify && notificationArgs.Rendering.HasFlag(NotificationRendering.NativeVisual)) if (!OverridePopup && Properties.Core.Default.NativeNotify && notificationArgs.Rendering.HasFlag(NotificationRendering.NativeVisual))
{ {
guid = NativePopup.InvokeNativeNotification(notificationArgs); guid = NativePopup.InvokeNativeNotification(notificationArgs);
} }
if (Properties.Core.Default.VoiceNotify && notificationArgs.Rendering.HasFlag(NotificationRendering.NativeVocal)) if (!OverrideAudio && Properties.Core.Default.VoiceNotify && notificationArgs.Rendering.HasFlag(NotificationRendering.NativeVocal))
{ {
NativeVoice.EnqueueAndAnnounce(notificationArgs); NativeVoice.EnqueueAndAnnounce(notificationArgs);
} }
@ -69,14 +70,13 @@ namespace Observatory.PluginManagement
public void CancelNotification(Guid id) public void CancelNotification(Guid id)
{ {
NativePopup.CloseNotification(id); ExecuteOnUIThread(() => NativePopup.CloseNotification(id));
} }
public void UpdateNotification(Guid id, NotificationArgs notificationArgs) public void UpdateNotification(Guid id, NotificationArgs notificationArgs)
{ {
if (!IsLogMonitorBatchReading) if (!IsLogMonitorBatchReading)
{ {
if (notificationArgs.Rendering.HasFlag(NotificationRendering.PluginNotifier)) if (notificationArgs.Rendering.HasFlag(NotificationRendering.PluginNotifier))
{ {
var handler = Notification; var handler = Notification;
@ -140,6 +140,8 @@ namespace Observatory.PluginManagement
public event EventHandler<NotificationArgs> Notification; public event EventHandler<NotificationArgs> Notification;
internal event EventHandler<PluginMessageArgs> PluginMessage;
public string PluginStorageFolder public string PluginStorageFolder
{ {
get get
@ -161,25 +163,19 @@ namespace Observatory.PluginManagement
} }
} }
public async Task PlayAudioFile(string filePath)
{
await AudioHandler.PlayFile(filePath);
}
public void SendPluginMessage(IObservatoryPlugin plugin, object message)
{
PluginMessage?.Invoke(this, new PluginMessageArgs(plugin.Name, plugin.Version, message));
}
internal void Shutdown() internal void Shutdown()
{ {
NativePopup.CloseAll(); NativePopup.CloseAll();
} }
private static bool FirstRowIsAllNull(IObservatoryWorker worker)
{
bool allNull = true;
Type itemType = worker.PluginUI.DataGrid[0].GetType();
foreach (var property in itemType.GetProperties())
{
if (property.GetValue(worker.PluginUI.DataGrid[0], null) != null)
{
allNull = false;
break;
}
}
return allNull;
}
} }
} }

View file

@ -110,6 +110,14 @@ namespace Observatory.PluginManagement
} }
} }
public void OnPluginMessageEvent(object _, PluginMessageArgs messageArgs)
{
foreach (var plugin in observatoryNotifiers.Cast<IObservatoryPlugin>().Concat(observatoryWorkers))
{
plugin.HandlePluginMessage(messageArgs.SourceName, messageArgs.SourceVersion, messageArgs.Message);
}
}
private void ResetTimer() private void ResetTimer()
{ {
timer.Stop(); timer.Stop();
@ -146,4 +154,18 @@ namespace Observatory.PluginManagement
} }
} }
} }
internal class PluginMessageArgs
{
internal string SourceName;
internal string SourceVersion;
internal object Message;
internal PluginMessageArgs(string sourceName, string sourceVersion, object message)
{
SourceName = sourceName;
SourceVersion = sourceVersion;
Message = message;
}
}
} }

View file

@ -50,7 +50,10 @@ namespace Observatory.PluginManagement
logMonitor.StatusUpdate += pluginHandler.OnStatusUpdate; logMonitor.StatusUpdate += pluginHandler.OnStatusUpdate;
logMonitor.LogMonitorStateChanged += pluginHandler.OnLogMonitorStateChanged; logMonitor.LogMonitorStateChanged += pluginHandler.OnLogMonitorStateChanged;
core = new PluginCore(); var ovPopup = notifyPlugins.Any(n => n.plugin.OverridePopupNotifications);
var ovAudio = notifyPlugins.Any(n => n.plugin.OverrideAudioNotifications);
core = new PluginCore(ovPopup, ovAudio);
List<IObservatoryPlugin> errorPlugins = new(); List<IObservatoryPlugin> errorPlugins = new();
@ -97,6 +100,7 @@ namespace Observatory.PluginManagement
notifyPlugins.RemoveAll(n => errorPlugins.Contains(n.plugin)); notifyPlugins.RemoveAll(n => errorPlugins.Contains(n.plugin));
core.Notification += pluginHandler.OnNotificationEvent; core.Notification += pluginHandler.OnNotificationEvent;
core.PluginMessage += pluginHandler.OnPluginMessageEvent;
if (errorList.Any()) if (errorList.Any())
ErrorReporter.ShowErrorPopup("Plugin Load Error" + (errorList.Count > 1 ? "s" : String.Empty), errorList); ErrorReporter.ShowErrorPopup("Plugin Load Error" + (errorList.Count > 1 ? "s" : String.Empty), errorList);
@ -114,7 +118,15 @@ namespace Observatory.PluginManagement
if (!String.IsNullOrWhiteSpace(savedSettings)) if (!String.IsNullOrWhiteSpace(savedSettings))
{ {
pluginSettings = JsonSerializer.Deserialize<Dictionary<string, object>>(savedSettings); var settings = JsonSerializer.Deserialize<Dictionary<string, object>>(savedSettings);
if (settings != null)
{
pluginSettings = settings;
}
else
{
pluginSettings = new();
}
} }
else else
{ {
@ -138,7 +150,7 @@ namespace Observatory.PluginManagement
var properties = settings.GetType().GetProperties(); var properties = settings.GetType().GetProperties();
foreach (var property in properties) foreach (var property in properties)
{ {
var attrib = property.GetCustomAttribute<Framework.SettingDisplayName>(); var attrib = property.GetCustomAttribute<SettingDisplayName>();
if (attrib == null) if (attrib == null)
{ {
settingNames.Add(property, property.Name); settingNames.Add(property, property.Name);
@ -396,7 +408,7 @@ namespace Observatory.PluginManagement
if (constructor != null) if (constructor != null)
{ {
object instance = constructor.Invoke(Array.Empty<object>()); object instance = constructor.Invoke(Array.Empty<object>());
notifiers.Add(((instance as IObservatoryNotifier)!, PluginStatus.Signed)); notifiers.Add(((instance as IObservatoryNotifier)!, pluginStatus));
pluginCount++; pluginCount++;
} }
} }

View file

@ -12,7 +12,7 @@ namespace Observatory.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.3.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.8.0.0")]
internal sealed partial class Core : global::System.Configuration.ApplicationSettingsBase { internal sealed partial class Core : global::System.Configuration.ApplicationSettingsBase {
private static Core defaultInstance = ((Core)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Core()))); private static Core defaultInstance = ((Core)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Core())));
@ -285,5 +285,29 @@ namespace Observatory.Properties {
this["UnsignedAllowed"] = value; this["UnsignedAllowed"] = value;
} }
} }
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("Dark")]
public string Theme {
get {
return ((string)(this["Theme"]));
}
set {
this["Theme"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string ColumnSizing {
get {
return ((string)(this["ColumnSizing"]));
}
set {
this["ColumnSizing"] = value;
}
}
} }
} }

View file

@ -68,5 +68,11 @@
<Setting Name="UnsignedAllowed" Type="System.Collections.Specialized.StringCollection" Scope="User"> <Setting Name="UnsignedAllowed" Type="System.Collections.Specialized.StringCollection" Scope="User">
<Value Profile="(Default)" /> <Value Profile="(Default)" />
</Setting> </Setting>
<Setting Name="Theme" Type="System.String" Scope="User">
<Value Profile="(Default)">Dark</Value>
</Setting>
<Setting Name="ColumnSizing" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
</Settings> </Settings>
</SettingsFile> </SettingsFile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View file

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Observatory.UI
{
public class ColumnSizing
{
public string PluginName { get; set; }
public string PluginVersion { get; set; }
public Dictionary<string, int> ColumnWidth
{
get
{
_columnWidth ??= new Dictionary<string, int>();
return _columnWidth;
}
set => _columnWidth = value;
}
private Dictionary<string, int>? _columnWidth;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,31 +1,34 @@
using Observatory.PluginManagement; using Observatory.PluginManagement;
using Observatory.Framework.Interfaces; using Observatory.Framework.Interfaces;
using System.Linq;
namespace Observatory.UI namespace Observatory.UI
{ {
partial class CoreForm partial class CoreForm
{ {
private Dictionary<ListViewItem, IObservatoryPlugin>? ListedPlugins;
private void PopulatePluginList() private void PopulatePluginList()
{ {
List<IObservatoryPlugin> uniquePlugins = new(); ListedPlugins = new();
foreach (var (plugin, signed) in PluginManager.GetInstance.workerPlugins) foreach (var (plugin, signed) in PluginManager.GetInstance.workerPlugins)
{ {
if (!uniquePlugins.Contains(plugin)) if (!ListedPlugins.ContainsValue(plugin))
{ {
uniquePlugins.Add(plugin);
ListViewItem item = new ListViewItem(new[] { plugin.Name, "Worker", plugin.Version, PluginStatusString(signed) }); ListViewItem item = new ListViewItem(new[] { plugin.Name, "Worker", plugin.Version, PluginStatusString(signed) });
ListedPlugins.Add(item, plugin);
PluginList.Items.Add(item); PluginList.Items.Add(item);
} }
} }
foreach (var (plugin, signed) in PluginManager.GetInstance.notifyPlugins) foreach (var (plugin, signed) in PluginManager.GetInstance.notifyPlugins)
{ {
if (!uniquePlugins.Contains(plugin)) if (!ListedPlugins.ContainsValue(plugin))
{ {
uniquePlugins.Add(plugin);
ListViewItem item = new ListViewItem(new[] { plugin.Name, "Notifier", plugin.Version, PluginStatusString(signed) }); ListViewItem item = new ListViewItem(new[] { plugin.Name, "Notifier", plugin.Version, PluginStatusString(signed) });
ListedPlugins.Add(item, plugin);
PluginList.Items.Add(item); PluginList.Items.Add(item);
} }
} }
@ -71,39 +74,87 @@ namespace Observatory.UI
{ {
pluginList.Add(item.Text, item); pluginList.Add(item.Text, item);
} }
CoreMenu.Width = GetExpandedMenuWidth();
} }
private void CreatePluginSettings() private void DisableOverriddenNotification()
{ {
foreach (var plugin in PluginManager.GetInstance.workerPlugins) var notifyPlugins = PluginManager.GetInstance.notifyPlugins;
var ovPopupPlugins = notifyPlugins.Where(n => n.plugin.OverridePopupNotifications);
if (ovPopupPlugins.Any())
{ {
var pluginSettingsPanel = new SettingsPanel(plugin.plugin, AdjustPanelsBelow); PopupCheckbox.Checked = false;
AddSettingsPanel(pluginSettingsPanel); PopupCheckbox.Enabled = false;
DisplayDropdown.Enabled = false;
CornerDropdown.Enabled = false;
FontDropdown.Enabled = false;
ScaleSpinner.Enabled = false;
DurationSpinner.Enabled = false;
ColourButton.Enabled = false;
TestButton.Enabled = false;
var pluginNames = string.Join(", ", ovPopupPlugins.Select(o => o.plugin.ShortName));
PopupSettingsPanel.MouseMove += (_, _) =>
{
OverrideTooltip.SetToolTip(PopupSettingsPanel, "Disabled by plugin: " + pluginNames);
};
} }
foreach (var plugin in PluginManager.GetInstance.notifyPlugins)
var ovAudioPlugins = notifyPlugins.Where(n => n.plugin.OverrideAudioNotifications);
if (ovAudioPlugins.Any())
{ {
var pluginSettingsPanel = new SettingsPanel(plugin.plugin, AdjustPanelsBelow); VoiceCheckbox.Checked = false;
AddSettingsPanel(pluginSettingsPanel); VoiceCheckbox.Enabled = false;
VoiceVolumeSlider.Enabled = false;
VoiceSpeedSlider.Enabled = false;
VoiceDropdown.Enabled = false;
VoiceTestButton.Enabled = false;
var pluginNames = string.Join(", ", ovAudioPlugins.Select(o => o.plugin.ShortName));
VoiceSettingsPanel.MouseMove += (_, _) =>
{
OverrideTooltip.SetToolTip(VoiceSettingsPanel, "Disabled by plugin: " + pluginNames);
};
} }
} }
private void AddSettingsPanel(SettingsPanel panel) private int GetExpandedMenuWidth()
{ {
int lowestPoint = 0; int maxWidth = 0;
foreach (Control control in CorePanel.Controls) foreach (ToolStripMenuItem item in CoreMenu.Items)
{ {
if (control.Location.Y + control.Height > lowestPoint) var itemWidth = TextRenderer.MeasureText(item.Text, item.Font);
lowestPoint = control.Location.Y + control.Height; maxWidth = itemWidth.Width > maxWidth ? itemWidth.Width : maxWidth;
} }
DuplicateControlVisuals(PopupNotificationLabel, panel.Header);
panel.Header.TextAlign = PopupNotificationLabel.TextAlign;
panel.Header.Location = new Point(PopupNotificationLabel.Location.X, lowestPoint);
DuplicateControlVisuals(PopupSettingsPanel, panel, false); return maxWidth + 5;
panel.Location = new Point(PopupSettingsPanel.Location.X, lowestPoint + panel.Header.Height);
panel.Visible = false;
CorePanel.Controls.Add(panel.Header);
CorePanel.Controls.Add(panel);
} }
private void PluginSettingsButton_Click(object sender, EventArgs e)
{
if (ListedPlugins != null && PluginList.SelectedItems.Count != 0)
{
var plugin = ListedPlugins[PluginList.SelectedItems[0]];
if (SettingsForms.ContainsKey(plugin))
{
SettingsForms[plugin].Activate();
}
else
{
SettingsForm settingsForm = new(plugin);
SettingsForms.Add(plugin, settingsForm);
settingsForm.FormClosed += (_, _) => SettingsForms.Remove(plugin);
settingsForm.Show();
}
}
}
private Dictionary<IObservatoryPlugin, SettingsForm> SettingsForms = new();
} }
} }

View file

@ -2,6 +2,7 @@
using Observatory.Framework.Interfaces; using Observatory.Framework.Interfaces;
using Observatory.PluginManagement; using Observatory.PluginManagement;
using Observatory.Utils; using Observatory.Utils;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Windows.Forms; using System.Windows.Forms;
@ -9,10 +10,25 @@ namespace Observatory.UI
{ {
public partial class CoreForm : Form public partial class CoreForm : Form
{ {
private Dictionary<object, Panel> uiPanels; private readonly Dictionary<object, Panel> uiPanels;
[DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);
private const int WM_SETREDRAW = 11;
private static void SuspendDrawing(Control control)
{
SendMessage(control.Handle, WM_SETREDRAW, false, 0);
}
private static void ResumeDrawing(Control control)
{
SendMessage(control.Handle, WM_SETREDRAW, true, 0);
control.Refresh();
}
public CoreForm() public CoreForm()
{ {
DoubleBuffered = true;
InitializeComponent(); InitializeComponent();
PopulateDropdownOptions(); PopulateDropdownOptions();
@ -24,14 +40,20 @@ namespace Observatory.UI
string version = System.Reflection.Assembly.GetEntryAssembly()?.GetName().Version?.ToString() ?? "0"; string version = System.Reflection.Assembly.GetEntryAssembly()?.GetName().Version?.ToString() ?? "0";
Text += $" - v{version}"; Text += $" - v{version}";
CoreMenu.SizeChanged += CoreMenu_SizeChanged; CoreMenu.SizeChanged += CoreMenu_SizeChanged;
uiPanels = new(); uiPanels = new()
uiPanels.Add(coreToolStripMenuItem, CorePanel); {
{ coreToolStripMenuItem, CorePanel }
};
pluginList = new Dictionary<string, ToolStripMenuItem>(); pluginList = new Dictionary<string, ToolStripMenuItem>();
CreatePluginTabs(); CreatePluginTabs();
CreatePluginSettings(); DisableOverriddenNotification();
CoreMenu.ItemClicked += CoreMenu_ItemClicked; CoreMenu.ItemClicked += CoreMenu_ItemClicked;
PreCollapsePanels(); PreCollapsePanels();
ThemeManager.GetInstance.RegisterControl(this);
} }
private void PreCollapsePanels() private void PreCollapsePanels()
@ -47,17 +69,7 @@ namespace Observatory.UI
} }
private Dictionary<string, ToolStripMenuItem> pluginList; private readonly Dictionary<string, ToolStripMenuItem> pluginList;
private static void DuplicateControlVisuals(Control source, Control target, bool applyHeight = true)
{
if (applyHeight) target.Height = source.Height;
target.Width = source.Width;
target.Font = source.Font;
target.ForeColor = source.ForeColor;
target.BackColor = source.BackColor;
target.Anchor = source.Anchor;
}
private void ToggleMonitorButton_Click(object sender, EventArgs e) private void ToggleMonitorButton_Click(object sender, EventArgs e)
{ {
@ -73,9 +85,25 @@ namespace Observatory.UI
} }
} }
private void CoreMenu_ItemClicked(object? _, ToolStripItemClickedEventArgs e) private void ResizePanels(Point location, int widthChange)
{ {
CorePanel.Location = location;
CorePanel.Width += widthChange;
foreach (var panel in uiPanels)
{
if (Controls.Contains(panel.Value))
{
panel.Value.Location = CorePanel.Location;
panel.Value.Size = CorePanel.Size;
}
}
}
private void CoreMenu_ItemClicked(object? _, ToolStripItemClickedEventArgs e)
{
SuspendDrawing(this);
if (e.ClickedItem.Text == "<") if (e.ClickedItem.Text == "<")
{ {
foreach (KeyValuePair<string, ToolStripMenuItem> menuItem in pluginList) foreach (KeyValuePair<string, ToolStripMenuItem> menuItem in pluginList)
@ -86,8 +114,7 @@ namespace Observatory.UI
menuItem.Value.Text = menuItem.Key[..1]; menuItem.Value.Text = menuItem.Key[..1];
} }
CoreMenu.Width = 40; CoreMenu.Width = 40;
CorePanel.Location = new Point(43, 12); ResizePanels(new Point(43, 12), 0);
// CorePanel.Width += 40;
} }
else if (e.ClickedItem.Text == ">") else if (e.ClickedItem.Text == ">")
{ {
@ -98,9 +125,8 @@ namespace Observatory.UI
else else
menuItem.Value.Text = menuItem.Key; menuItem.Value.Text = menuItem.Key;
} }
CoreMenu.Width = 120; CoreMenu.Width = GetExpandedMenuWidth();
CorePanel.Location = new Point(123, 12); ResizePanels(new Point(CoreMenu.Width + 3, 12), 0);
// CorePanel.Width -= 40;
} }
else else
{ {
@ -114,11 +140,23 @@ namespace Observatory.UI
uiPanels[e.ClickedItem].Location = CorePanel.Location; uiPanels[e.ClickedItem].Location = CorePanel.Location;
uiPanels[e.ClickedItem].Size = CorePanel.Size; uiPanels[e.ClickedItem].Size = CorePanel.Size;
uiPanels[e.ClickedItem].BackColor = CorePanel.BackColor; uiPanels[e.ClickedItem].BackColor = CorePanel.BackColor;
uiPanels[e.ClickedItem].Parent = CorePanel.Parent;
Controls.Add(uiPanels[e.ClickedItem]); Controls.Add(uiPanels[e.ClickedItem]);
} }
uiPanels[e.ClickedItem].Visible = true; uiPanels[e.ClickedItem].Visible = true;
}
SetClickedItem(e.ClickedItem);
}
ResumeDrawing(this);
}
private void SetClickedItem(ToolStripItem item)
{
foreach (ToolStripItem menuItem in CoreMenu.Items)
{
bool bold = menuItem == item;
menuItem.Font = new Font(menuItem.Font, bold ? FontStyle.Bold : FontStyle.Regular);
}
} }
private static void ColourListHeader(ref ListView list, Color backColor, Color foreColor) private static void ColourListHeader(ref ListView list, Color backColor, Color foreColor)
@ -128,12 +166,12 @@ namespace Observatory.UI
list.DrawColumnHeader += list.DrawColumnHeader +=
new DrawListViewColumnHeaderEventHandler new DrawListViewColumnHeaderEventHandler
( (
(sender, e) => headerDraw(sender, e, backColor, foreColor) (sender, e) => HeaderDraw(sender, e, backColor, foreColor)
); );
list.DrawItem += new DrawListViewItemEventHandler(bodyDraw); list.DrawItem += new DrawListViewItemEventHandler(BodyDraw);
} }
private static void headerDraw(object? _, DrawListViewColumnHeaderEventArgs e, Color backColor, Color foreColor) private static void HeaderDraw(object? _, DrawListViewColumnHeaderEventArgs e, Color backColor, Color foreColor)
{ {
using (SolidBrush backBrush = new(backColor)) using (SolidBrush backBrush = new(backColor))
{ {
@ -149,9 +187,11 @@ namespace Observatory.UI
if (e.Font != null && e.Header != null) if (e.Font != null && e.Header != null)
using (SolidBrush foreBrush = new(foreColor)) using (SolidBrush foreBrush = new(foreColor))
{ {
var format = new StringFormat(); var format = new StringFormat
format.Alignment = (StringAlignment)e.Header.TextAlign; {
format.LineAlignment = StringAlignment.Center; Alignment = (StringAlignment)e.Header.TextAlign,
LineAlignment = StringAlignment.Center
};
var paddedBounds = new Rectangle(e.Bounds.X + 2, e.Bounds.Y + 2, e.Bounds.Width - 4, e.Bounds.Height - 4); var paddedBounds = new Rectangle(e.Bounds.X + 2, e.Bounds.Y + 2, e.Bounds.Width - 4, e.Bounds.Height - 4);
@ -159,7 +199,7 @@ namespace Observatory.UI
} }
} }
private static void bodyDraw(object? _, DrawListViewItemEventArgs e) private static void BodyDraw(object? _, DrawListViewItemEventArgs e)
{ {
e.DrawDefault = true; e.DrawDefault = true;
} }
@ -180,7 +220,11 @@ namespace Observatory.UI
private void ReadAllButton_Click(object sender, EventArgs e) private void ReadAllButton_Click(object sender, EventArgs e)
{ {
LogMonitor.GetInstance.ReadAllJournals(); var readAllDialogue = new ReadAllForm();
ThemeManager.GetInstance.RegisterControl(readAllDialogue);
readAllDialogue.StartPosition = FormStartPosition.Manual;
readAllDialogue.Location = Point.Add(Location, new Size(100,100));
readAllDialogue.ShowDialog();
} }
private void PopupNotificationLabel_Click(object _, EventArgs e) private void PopupNotificationLabel_Click(object _, EventArgs e)
@ -238,6 +282,8 @@ namespace Observatory.UI
Up, Down Up, Down
} }
private Observatory.NativeNotification.NativePopup? nativePopup;
private void TestButton_Click(object sender, EventArgs e) private void TestButton_Click(object sender, EventArgs e)
{ {
NotificationArgs args = new() NotificationArgs args = new()
@ -245,9 +291,10 @@ namespace Observatory.UI
Title = "Test Notification", Title = "Test Notification",
Detail = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec at elit maximus, ornare dui nec, accumsan velit. Vestibulum fringilla elit." Detail = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec at elit maximus, ornare dui nec, accumsan velit. Vestibulum fringilla elit."
}; };
var testNotify = new NotificationForm(new Guid(), args);
testNotify.Show();
nativePopup ??= new Observatory.NativeNotification.NativePopup();
nativePopup.InvokeNativeNotification(args);
} }
} }
} }

View file

@ -1,4 +1,64 @@
<root> <?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true"> <xsd:element name="root" msdata:IsDataSet="true">
@ -63,6 +123,9 @@
<metadata name="PopupColour.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="PopupColour.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>126, 17</value> <value>126, 17</value>
</metadata> </metadata>
<metadata name="OverrideTooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>251, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>

View file

@ -28,55 +28,54 @@
/// </summary> /// </summary>
private void InitializeComponent() private void InitializeComponent()
{ {
this.Title = new System.Windows.Forms.Label(); Title = new Label();
this.Body = new System.Windows.Forms.Label(); Body = new Label();
this.SuspendLayout(); SuspendLayout();
// //
// Title // Title
// //
this.Title.Font = new System.Drawing.Font("Segoe UI", 24F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); Title.Font = new Font("Segoe UI", 24F, FontStyle.Regular, GraphicsUnit.Point);
this.Title.ForeColor = System.Drawing.Color.OrangeRed; Title.ForeColor = Color.OrangeRed;
this.Title.Location = new System.Drawing.Point(5, 5); Title.Location = new Point(5, 5);
this.Title.MaximumSize = new System.Drawing.Size(355, 0); Title.MaximumSize = new Size(355, 0);
this.Title.Name = "Title"; Title.Name = "Title";
this.Title.Size = new System.Drawing.Size(338, 45); Title.Size = new Size(338, 45);
this.Title.TabIndex = 0; Title.TabIndex = 0;
this.Title.Text = "Title"; Title.Text = "Title";
// //
// Body // Body
// //
this.Body.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) Body.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
| System.Windows.Forms.AnchorStyles.Right))); Body.AutoSize = true;
this.Body.AutoSize = true; Body.Font = new Font("Segoe UI", 14.25F, FontStyle.Regular, GraphicsUnit.Point);
this.Body.Font = new System.Drawing.Font("Segoe UI", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); Body.ForeColor = Color.OrangeRed;
this.Body.ForeColor = System.Drawing.Color.OrangeRed; Body.Location = new Point(12, 45);
this.Body.Location = new System.Drawing.Point(12, 45); Body.MaximumSize = new Size(320, 85);
this.Body.MaximumSize = new System.Drawing.Size(320, 85); Body.Name = "Body";
this.Body.Name = "Body"; Body.Size = new Size(51, 31);
this.Body.Size = new System.Drawing.Size(51, 31); Body.TabIndex = 1;
this.Body.TabIndex = 1; Body.Text = "Body";
this.Body.Text = "Body"; Body.UseCompatibleTextRendering = true;
this.Body.UseCompatibleTextRendering = true;
// //
// NotificationForm // NotificationForm
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); AutoScaleDimensions = new SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; AutoScaleMode = AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64))))); BackColor = Color.FromArgb(64, 64, 64);
this.ClientSize = new System.Drawing.Size(355, 145); ClientSize = new Size(355, 145);
this.ControlBox = false; ControlBox = false;
this.Controls.Add(this.Body); Controls.Add(Body);
this.Controls.Add(this.Title); Controls.Add(Title);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; Enabled = false;
this.MaximizeBox = false; FormBorderStyle = FormBorderStyle.None;
this.MinimizeBox = false; MaximizeBox = false;
this.Name = "NotificationForm"; MinimizeBox = false;
this.ShowIcon = false; Name = "NotificationForm";
this.ShowInTaskbar = false; ShowIcon = false;
this.Text = "NotificationForm"; ShowInTaskbar = false;
this.ResumeLayout(false); Text = "NotificationForm";
this.PerformLayout(); ResumeLayout(false);
PerformLayout();
} }
#endregion #endregion

View file

@ -36,6 +36,7 @@ namespace Observatory.UI
{ {
_guid = guid; _guid = guid;
_color = Color.FromArgb((int)Properties.Core.Default.NativeNotifyColour); _color = Color.FromArgb((int)Properties.Core.Default.NativeNotifyColour);
CreationTime = DateTime.Now;
InitializeComponent(); InitializeComponent();
Title.Paint += DrawText; Title.Paint += DrawText;
@ -65,7 +66,7 @@ namespace Observatory.UI
Body.ForeColor = _color; Body.ForeColor = _color;
Body.Text = args.Detail; Body.Text = args.Detail;
Body.Font = new Font(Properties.Core.Default.NativeNotifyFont, 14); Body.Font = new Font(Properties.Core.Default.NativeNotifyFont, 14);
this.Paint += DrawBorder; Paint += DrawBorder;
AdjustPosition(args.XPos / 100, args.YPos / 100); AdjustPosition(args.XPos / 100, args.YPos / 100);
@ -78,10 +79,36 @@ namespace Observatory.UI
} }
} }
private void NotificationForm_FormClosed(object? sender, FormClosedEventArgs e)
{
throw new NotImplementedException();
}
public DateTime CreationTime { get; private init; }
public void Update(NotificationArgs notificationArgs) public void Update(NotificationArgs notificationArgs)
{ {
Title.Text = notificationArgs.Title; // Catch Cross-thread access and invoke
Body.Text = notificationArgs.Detail; try
{
Title.Text = notificationArgs.Title;
Body.Text = notificationArgs.Detail;
}
catch
{
try
{
Invoke(() =>
{
Title.Text = notificationArgs.Title;
Body.Text = notificationArgs.Detail;
});
}
catch (Exception ex)
{
throw new Exception("Notification Update Failure, please inform Vithigar. Details: " + ex.Message);
}
}
} }
private void AdjustPosition(double x = -1.0, double y = -1.0) private void AdjustPosition(double x = -1.0, double y = -1.0)
@ -90,7 +117,6 @@ namespace Observatory.UI
int corner = Properties.Core.Default.NativeNotifyCorner; int corner = Properties.Core.Default.NativeNotifyCorner;
Rectangle screenBounds; Rectangle screenBounds;
if (screen == -1 || screen > Screen.AllScreens.Length) if (screen == -1 || screen > Screen.AllScreens.Length)
if (Screen.AllScreens.Length == 1) if (Screen.AllScreens.Length == 1)
screenBounds = Screen.GetBounds(this); screenBounds = Screen.GetBounds(this);
@ -115,7 +141,7 @@ namespace Observatory.UI
case 0: case 0:
Location = Point.Add( Location = Point.Add(
new Point(screenBounds.Right, screenBounds.Bottom), new Point(screenBounds.Right, screenBounds.Bottom),
new Size(-(Width+50), -(Height+50))); new Size(-(Width + 50), -(Height + 50)));
break; break;
case 1: case 1:
Location = Point.Add( Location = Point.Add(
@ -190,13 +216,29 @@ namespace Observatory.UI
public Guid Guid { get => _guid; } public Guid Guid { get => _guid; }
private void AdjustText() public void AdjustOffset(bool increase)
{ {
if (_defaultPosition)
{
if (increase || Location != _originalLocation)
{
var corner = Properties.Core.Default.NativeNotifyCorner;
if ((corner >= 2 && increase) || (corner <= 1 && !increase))
{
Location = new Point(Location.X, Location.Y + Height);
}
else
{
Location = new Point(Location.X, Location.Y - Height);
}
}
}
} }
private void CloseNotification(object? sender, System.Timers.ElapsedEventArgs e) private void CloseNotification(object? sender, System.Timers.ElapsedEventArgs e)
{ {
// Catch Cross-thread access and invoke
try try
{ {
Close(); Close();
@ -205,11 +247,11 @@ namespace Observatory.UI
{ {
try try
{ {
this.Invoke(() => Close()); Invoke(() => Close());
} }
catch catch (Exception ex)
{ {
throw new Exception("blah"); throw new Exception("Notification Close Failure, please inform Vithigar. Details: " + ex.Message);
} }
} }

Some files were not shown because too many files have changed in this diff Show more