diff --git a/Intersect.Client.Framework/Audio/GameAudioInstance.cs b/Intersect.Client.Framework/Audio/GameAudioInstance.cs index 1cd5ad1cf4..19da298582 100644 --- a/Intersect.Client.Framework/Audio/GameAudioInstance.cs +++ b/Intersect.Client.Framework/Audio/GameAudioInstance.cs @@ -1,57 +1,55 @@ -namespace Intersect.Client.Framework.Audio +namespace Intersect.Client.Framework.Audio; + + +public abstract partial class GameAudioInstance { - public abstract partial class GameAudioInstance + public enum AudioInstanceState { - public enum AudioInstanceState - { - - Stopped = 0, + Stopped = 0, - Playing = 1, + Playing = 1, - Paused = 2, + Paused = 2, - Disposed = 3, + Disposed = 3, - } + } - private bool mIsLooping; + private bool mIsLooping; - protected GameAudioInstance(GameAudioSource source) - { - Source = source; - } + protected GameAudioInstance(GameAudioSource source) + { + Source = source; + } - public GameAudioSource Source { get; } + public GameAudioSource Source { get; } - public bool IsLooping + public bool IsLooping + { + get => mIsLooping; + set { - get => mIsLooping; - set - { - mIsLooping = value; - InternalLoopSet(); - } + mIsLooping = value; + InternalLoopSet(); } + } - public abstract AudioInstanceState State { get; } - - protected abstract void InternalLoopSet(); + public abstract AudioInstanceState State { get; } - public abstract void Play(); + protected abstract void InternalLoopSet(); - public abstract void Pause(); + public abstract void Play(); - public abstract void Stop(); + public abstract void Pause(); - public abstract void SetVolume(int volume, bool isMusic = false); + public abstract void Stop(); - public abstract int GetVolume(); + public abstract void SetVolume(int volume, bool isMusic = false); - public abstract void Dispose(); + public abstract int GetVolume(); - } + public abstract void Dispose(); } diff --git a/Intersect.Client.Framework/Audio/GameAudioSource.cs b/Intersect.Client.Framework/Audio/GameAudioSource.cs index cb977d3981..9a3cb50064 100644 --- a/Intersect.Client.Framework/Audio/GameAudioSource.cs +++ b/Intersect.Client.Framework/Audio/GameAudioSource.cs @@ -1,14 +1,12 @@ using Intersect.Client.Framework.Content; -namespace Intersect.Client.Framework.Audio -{ +namespace Intersect.Client.Framework.Audio; - public abstract partial class GameAudioSource : IAsset - { - public string Name { get; set; } - public abstract GameAudioInstance CreateInstance(); +public abstract partial class GameAudioSource : IAsset +{ + public string Name { get; set; } - } + public abstract GameAudioInstance CreateInstance(); } diff --git a/Intersect.Client.Framework/Audio/IAudioManager.cs b/Intersect.Client.Framework/Audio/IAudioManager.cs index 5a1ca1e7db..c9ddfe1b97 100644 --- a/Intersect.Client.Framework/Audio/IAudioManager.cs +++ b/Intersect.Client.Framework/Audio/IAudioManager.cs @@ -1,65 +1,64 @@ using Intersect.Client.Framework.Core.Sounds; using Intersect.Client.Framework.Entities; -namespace Intersect.Client.Framework.Audio +namespace Intersect.Client.Framework.Audio; + +/// +/// Manages game audio for the client instance. +/// +public interface IAudioManager { /// - /// Manages game audio for the client instance. + /// Start playing a map sound. /// - public interface IAudioManager - { - /// - /// Start playing a map sound. - /// - /// The sound file name to start playing. - /// The X location to start playing this sound at. - /// The Y location to start playing this sound at. - /// The map Id to start playing this song on. - /// Determines whether the sound loops once it's over or not. - /// The time (in ms) between the sound stopping and starting again once it loops. - /// The maximum distance from which the sound can still be heard. - /// The this sound belongs to. - /// Returns a new instance of for the sound that will be played. - IMapSound PlayMapSound(string filename, int x, int y, Guid mapId, bool loop, int loopInterval, int distance, IEntity parent = null); + /// The sound file name to start playing. + /// The X location to start playing this sound at. + /// The Y location to start playing this sound at. + /// The map Id to start playing this song on. + /// Determines whether the sound loops once it's over or not. + /// The time (in ms) between the sound stopping and starting again once it loops. + /// The maximum distance from which the sound can still be heard. + /// The this sound belongs to. + /// Returns a new instance of for the sound that will be played. + IMapSound PlayMapSound(string filename, int x, int y, Guid mapId, bool loop, int loopInterval, int distance, IEntity parent = null); - /// - /// Start playing a sound effect. - /// - /// The sound file name to start playing. - /// Determines whether the sound loops once it's over or not. - /// Returns a new instance of for the sound that will be played. - ISound PlaySound(string filename, bool loop); + /// + /// Start playing a sound effect. + /// + /// The sound file name to start playing. + /// Determines whether the sound loops once it's over or not. + /// Returns a new instance of for the sound that will be played. + ISound PlaySound(string filename, bool loop); - /// - /// Stop a sound effect. - /// - /// The sound to stop playing. - void StopSound(ISound sound); + /// + /// Stop a sound effect. + /// + /// The sound to stop playing. + void StopSound(ISound sound); - /// - /// Stop a sound effect. - /// - /// The sound to stop playing. - void StopSound(IMapSound sound); + /// + /// Stop a sound effect. + /// + /// The sound to stop playing. + void StopSound(IMapSound sound); - /// - /// Stop all currently playing sound effects. - /// - void StopAllSounds(); + /// + /// Stop all currently playing sound effects. + /// + void StopAllSounds(); - /// - /// Play a music track, automatically fading out the old track with the configured values. - /// - /// The song file name to start playing. A blank filename will only stop the currently playing music track. - /// The time (in ms) it should take to fade in the new music track. - /// The time (in ms) it should take to fade out the current music track. - /// Determines whether the song loops once it's over or not. - void PlayMusic(string filename, int fadeout = 0, int fadein = 0, bool loop = false); + /// + /// Play a music track, automatically fading out the old track with the configured values. + /// + /// The song file name to start playing. A blank filename will only stop the currently playing music track. + /// The time (in ms) it should take to fade in the new music track. + /// The time (in ms) it should take to fade out the current music track. + /// Determines whether the song loops once it's over or not. + void PlayMusic(string filename, int fadeout = 0, int fadein = 0, bool loop = false); - /// - /// Stops the current playing music track. - /// - /// The time (in ms) it should take to fade out the current music track. - void StopMusic(int fadeout = 0); - } + /// + /// Stops the current playing music track. + /// + /// The time (in ms) it should take to fade out the current music track. + void StopMusic(int fadeout = 0); } diff --git a/Intersect.Client.Framework/Content/AssetTypeAttribute.cs b/Intersect.Client.Framework/Content/AssetTypeAttribute.cs index 93864d35ef..b4bb517caf 100644 --- a/Intersect.Client.Framework/Content/AssetTypeAttribute.cs +++ b/Intersect.Client.Framework/Content/AssetTypeAttribute.cs @@ -1,27 +1,25 @@ -namespace Intersect.Client.Framework.Content +namespace Intersect.Client.Framework.Content; + + +[AttributeUsage(AttributeTargets.Field)] +public partial class AssetTypeAttribute : Attribute { - [AttributeUsage(AttributeTargets.Field)] - public partial class AssetTypeAttribute : Attribute + public AssetTypeAttribute(Type type) { - - public AssetTypeAttribute(Type type) + if (!typeof(IAsset).IsAssignableFrom(type)) { - if (!typeof(IAsset).IsAssignableFrom(type)) - { - throw new ArgumentException($@"Invalid asset type {type.FullName}. Must inherit from {nameof(IAsset)}.", nameof(type)); - } - - if (!type.IsClass) - { - throw new ArgumentException($@"Invalid asset type {type.FullName}. Must be a class (abstract is acceptable).", nameof(type)); - } - - Type = type; + throw new ArgumentException($@"Invalid asset type {type.FullName}. Must inherit from {nameof(IAsset)}.", nameof(type)); } - public Type Type { get; } + if (!type.IsClass) + { + throw new ArgumentException($@"Invalid asset type {type.FullName}. Must be a class (abstract is acceptable).", nameof(type)); + } + Type = type; } + public Type Type { get; } + } diff --git a/Intersect.Client.Framework/Content/ContentTypes.cs b/Intersect.Client.Framework/Content/ContentTypes.cs index 38730ec4ca..35c30793f3 100644 --- a/Intersect.Client.Framework/Content/ContentTypes.cs +++ b/Intersect.Client.Framework/Content/ContentTypes.cs @@ -1,64 +1,62 @@ using Intersect.Client.Framework.Audio; using Intersect.Client.Framework.Graphics; -namespace Intersect.Client.Framework.Content -{ +namespace Intersect.Client.Framework.Content; - public enum ContentTypes - { - [AssetType(typeof(GameTexture))] - Animation, - [AssetType(typeof(GameTexture))] - Entity, +public enum ContentTypes +{ + [AssetType(typeof(GameTexture))] + Animation, - [AssetType(typeof(GameTexture))] - Face, + [AssetType(typeof(GameTexture))] + Entity, - [AssetType(typeof(GameTexture))] - Fog, + [AssetType(typeof(GameTexture))] + Face, - [AssetType(typeof(GameFont))] - Font, + [AssetType(typeof(GameTexture))] + Fog, - [AssetType(typeof(GameTexture))] - Image, + [AssetType(typeof(GameFont))] + Font, - [AssetType(typeof(GameTexture))] - Interface, + [AssetType(typeof(GameTexture))] + Image, - [AssetType(typeof(GameTexture))] - Item, + [AssetType(typeof(GameTexture))] + Interface, - [AssetType(typeof(GameTexture))] - Miscellaneous, + [AssetType(typeof(GameTexture))] + Item, - [AssetType(typeof(GameAudioSource))] - Music, + [AssetType(typeof(GameTexture))] + Miscellaneous, - [AssetType(typeof(GameTexture))] - Paperdoll, + [AssetType(typeof(GameAudioSource))] + Music, - [AssetType(typeof(GameTexture))] - Resource, + [AssetType(typeof(GameTexture))] + Paperdoll, - [AssetType(typeof(GameShader))] - Shader, + [AssetType(typeof(GameTexture))] + Resource, - [AssetType(typeof(GameAudioSource))] - Sound, + [AssetType(typeof(GameShader))] + Shader, - [AssetType(typeof(GameTexture))] - Spell, + [AssetType(typeof(GameAudioSource))] + Sound, - [AssetType(typeof(GameTexture))] - TexturePack, + [AssetType(typeof(GameTexture))] + Spell, - [AssetType(typeof(GameTexture))] - TileSet, + [AssetType(typeof(GameTexture))] + TexturePack, - [Obsolete] Gui = Interface + [AssetType(typeof(GameTexture))] + TileSet, - } + [Obsolete] Gui = Interface } diff --git a/Intersect.Client.Framework/Content/ContentTypesExtensions.cs b/Intersect.Client.Framework/Content/ContentTypesExtensions.cs index f9126806ef..f359139c59 100644 --- a/Intersect.Client.Framework/Content/ContentTypesExtensions.cs +++ b/Intersect.Client.Framework/Content/ContentTypesExtensions.cs @@ -1,29 +1,27 @@ -namespace Intersect.Client.Framework.Content +namespace Intersect.Client.Framework.Content; + + +public static partial class ContentTypesExtensions { - public static partial class ContentTypesExtensions + public static Type GetAssetType(this ContentTypes contentType) { - - public static Type GetAssetType(this ContentTypes contentType) + var memberName = contentType.ToString(); + var memberInfo = typeof(ContentTypes).GetMember(memberName).FirstOrDefault(); + if (memberInfo == null) { - var memberName = contentType.ToString(); - var memberInfo = typeof(ContentTypes).GetMember(memberName).FirstOrDefault(); - if (memberInfo == null) - { - throw new InvalidOperationException($@"{nameof(ContentTypes)} missing expected member: {memberName}"); - } - - var attribute = memberInfo.GetCustomAttributes(typeof(AssetTypeAttribute), true).FirstOrDefault(); - if (attribute is AssetTypeAttribute assetTypeAttribute) - { - return assetTypeAttribute.Type; - } + throw new InvalidOperationException($@"{nameof(ContentTypes)} missing expected member: {memberName}"); + } - throw new InvalidOperationException( - $@"{nameof(ContentTypes)} missing {nameof(AssetTypeAttribute)} on member: {memberName}" - ); + var attribute = memberInfo.GetCustomAttributes(typeof(AssetTypeAttribute), true).FirstOrDefault(); + if (attribute is AssetTypeAttribute assetTypeAttribute) + { + return assetTypeAttribute.Type; } + throw new InvalidOperationException( + $@"{nameof(ContentTypes)} missing {nameof(AssetTypeAttribute)} on member: {memberName}" + ); } } diff --git a/Intersect.Client.Framework/Content/ContentWatcher.cs b/Intersect.Client.Framework/Content/ContentWatcher.cs index 7c578e1f22..b2937277c5 100644 --- a/Intersect.Client.Framework/Content/ContentWatcher.cs +++ b/Intersect.Client.Framework/Content/ContentWatcher.cs @@ -1,146 +1,145 @@ using System.Collections.Concurrent; -namespace Intersect.Client.Framework.Content +namespace Intersect.Client.Framework.Content; + +public sealed partial class ContentWatcher { - public sealed partial class ContentWatcher + public enum Event { - public enum Event - { - Change, - Create, - Delete, - Rename, - } + Change, + Create, + Delete, + Rename, + } - private readonly ConcurrentDictionary _ignore; - private readonly Dictionary>> _mappedHandlers; - private readonly string _root; - private readonly FileSystemWatcher _watcher; + private readonly ConcurrentDictionary _ignore; + private readonly Dictionary>> _mappedHandlers; + private readonly string _root; + private readonly FileSystemWatcher _watcher; - public ContentWatcher(string root) + public ContentWatcher(string root) + { + + _ignore = new ConcurrentDictionary(); + _mappedHandlers = new Dictionary>>(); + _root = !string.IsNullOrWhiteSpace(root) ? root : throw new ArgumentNullException(nameof(root)); + _watcher = new FileSystemWatcher(_root) { + EnableRaisingEvents = false, + IncludeSubdirectories = true, + NotifyFilter = NotifyFilters.Attributes + | NotifyFilters.CreationTime + | NotifyFilters.DirectoryName + | NotifyFilters.FileName + | NotifyFilters.LastAccess + | NotifyFilters.LastWrite + | NotifyFilters.Security + | NotifyFilters.Size + }; + + _watcher.Changed += HandleChanged; + _watcher.Created += HandleCreated; + _watcher.Deleted += HandleDeleted; + _watcher.Renamed += HandleRenamed; + } - _ignore = new ConcurrentDictionary(); - _mappedHandlers = new Dictionary>>(); - _root = !string.IsNullOrWhiteSpace(root) ? root : throw new ArgumentNullException(nameof(root)); - _watcher = new FileSystemWatcher(_root) - { - EnableRaisingEvents = false, - IncludeSubdirectories = true, - NotifyFilter = NotifyFilters.Attributes - | NotifyFilters.CreationTime - | NotifyFilters.DirectoryName - | NotifyFilters.FileName - | NotifyFilters.LastAccess - | NotifyFilters.LastWrite - | NotifyFilters.Security - | NotifyFilters.Size - }; - - _watcher.Changed += HandleChanged; - _watcher.Created += HandleCreated; - _watcher.Deleted += HandleDeleted; - _watcher.Renamed += HandleRenamed; - } + public bool Enabled + { + get => _watcher.EnableRaisingEvents; + set => _watcher.EnableRaisingEvents = value; + } + + public void AddEventListener(Event watcherEvent, string path, Action handler) => + GetHandlersFor(watcherEvent, path, true).Add(handler); - public bool Enabled + private Dictionary> GetHandlerMapFor(Event watcherEvent, bool createIfMissing = false) + { + if (_mappedHandlers.TryGetValue(watcherEvent, out var eventHandlerMap)) { - get => _watcher.EnableRaisingEvents; - set => _watcher.EnableRaisingEvents = value; + return eventHandlerMap; } - public void AddEventListener(Event watcherEvent, string path, Action handler) => - GetHandlersFor(watcherEvent, path, true).Add(handler); - - private Dictionary> GetHandlerMapFor(Event watcherEvent, bool createIfMissing = false) + if (!createIfMissing) { - if (_mappedHandlers.TryGetValue(watcherEvent, out var eventHandlerMap)) - { - return eventHandlerMap; - } + return default; + } - if (!createIfMissing) - { - return default; - } + eventHandlerMap = new Dictionary>(); + _mappedHandlers.Add(watcherEvent, eventHandlerMap); + return eventHandlerMap; + } - eventHandlerMap = new Dictionary>(); - _mappedHandlers.Add(watcherEvent, eventHandlerMap); - return eventHandlerMap; + private List GetHandlersFor(Event watcherEvent, string path, bool createIfMissing = false) + { + var eventHandlerMap = GetHandlerMapFor(watcherEvent, createIfMissing); + if (eventHandlerMap == default) + { + return default; } - private List GetHandlersFor(Event watcherEvent, string path, bool createIfMissing = false) + if (eventHandlerMap.TryGetValue(path, out var handlers)) { - var eventHandlerMap = GetHandlerMapFor(watcherEvent, createIfMissing); - if (eventHandlerMap == default) - { - return default; - } + return handlers; + } - if (eventHandlerMap.TryGetValue(path, out var handlers)) - { - return handlers; - } + if (!createIfMissing) + { + return default; + } - if (!createIfMissing) - { - return default; - } + handlers = new List(); + eventHandlerMap.Add(path, handlers); + return handlers; + } - handlers = new List(); - eventHandlerMap.Add(path, handlers); - return handlers; + public void Modify(string path, Action modificationAction) + { + if (modificationAction == default) + { + throw new ArgumentNullException(nameof(modificationAction)); } - public void Modify(string path, Action modificationAction) + _ = _ignore.TryAdd(path, true); + modificationAction(); + _ = Task.Delay(1000).ContinueWith(completedTask => { - if (modificationAction == default) - { - throw new ArgumentNullException(nameof(modificationAction)); - } + _ = _ignore.TryRemove(path, out _); + }, TaskScheduler.Current); + } - _ = _ignore.TryAdd(path, true); - modificationAction(); - _ = Task.Delay(1000).ContinueWith(completedTask => - { - _ = _ignore.TryRemove(path, out _); - }, TaskScheduler.Current); + private void HandleEvent(object sender, FileSystemEventArgs args, Event watcherEvent) + { + var relativePath = args.FullPath.Replace(_root, string.Empty); + if (relativePath.StartsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)) + { + relativePath = relativePath.Substring(1); } - private void HandleEvent(object sender, FileSystemEventArgs args, Event watcherEvent) + if (_ignore.ContainsKey(relativePath)) { - var relativePath = args.FullPath.Replace(_root, string.Empty); - if (relativePath.StartsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)) - { - relativePath = relativePath.Substring(1); - } + return; + } - if (_ignore.ContainsKey(relativePath)) - { - return; - } + var handlers = GetHandlersFor(watcherEvent, relativePath); + if (handlers == default) + { + return; + } - var handlers = GetHandlersFor(watcherEvent, relativePath); - if (handlers == default) + _ = Task.Delay(1000).ContinueWith(completedTask => + { + foreach (var handler in handlers) { - return; + handler?.Invoke(); } + }, TaskScheduler.Current); + } - _ = Task.Delay(1000).ContinueWith(completedTask => - { - foreach (var handler in handlers) - { - handler?.Invoke(); - } - }, TaskScheduler.Current); - } - - private void HandleChanged(object sender, FileSystemEventArgs args) => HandleEvent(sender, args, Event.Change); + private void HandleChanged(object sender, FileSystemEventArgs args) => HandleEvent(sender, args, Event.Change); - private void HandleCreated(object sender, FileSystemEventArgs args) => HandleEvent(sender, args, Event.Create); + private void HandleCreated(object sender, FileSystemEventArgs args) => HandleEvent(sender, args, Event.Create); - private void HandleDeleted(object sender, FileSystemEventArgs args) => HandleEvent(sender, args, Event.Delete); + private void HandleDeleted(object sender, FileSystemEventArgs args) => HandleEvent(sender, args, Event.Delete); - private void HandleRenamed(object sender, RenamedEventArgs args) => HandleEvent(sender, args, Event.Rename); - } + private void HandleRenamed(object sender, RenamedEventArgs args) => HandleEvent(sender, args, Event.Rename); } diff --git a/Intersect.Client.Framework/Content/IAsset.cs b/Intersect.Client.Framework/Content/IAsset.cs index ec2d308596..e1e8d759ea 100644 --- a/Intersect.Client.Framework/Content/IAsset.cs +++ b/Intersect.Client.Framework/Content/IAsset.cs @@ -1,7 +1,6 @@ -namespace Intersect.Client.Framework.Content +namespace Intersect.Client.Framework.Content; + +public interface IAsset { - public interface IAsset - { - string Name { get; } - } + string Name { get; } } diff --git a/Intersect.Client.Framework/Content/IContentManager.cs b/Intersect.Client.Framework/Content/IContentManager.cs index 6ef755d3b9..b26d67943d 100644 --- a/Intersect.Client.Framework/Content/IContentManager.cs +++ b/Intersect.Client.Framework/Content/IContentManager.cs @@ -1,59 +1,57 @@ using Intersect.Plugins; -namespace Intersect.Client.Framework.Content -{ +namespace Intersect.Client.Framework.Content; - public interface IContentManager - { - /// - /// Find a specified Asset from within the Content Manager. - /// - /// - /// The type of asset to try and search for. - /// The name/alias of the asset to try and search for. - /// Returns the specified if it exists, if not returns - TAsset Find(ContentTypes contentType, string assetName) where TAsset : class, IAsset; - /// - /// Load an asset from disk by the specified file. - /// - /// - /// The type of asset to load. - /// The path of the asset file to load. - /// The alias to give to the asset for future reference. - /// Returns an instance of - TAsset Load(ContentTypes contentType, string assetPath, string assetAlias) where TAsset : class, IAsset; +public interface IContentManager +{ + /// + /// Find a specified Asset from within the Content Manager. + /// + /// + /// The type of asset to try and search for. + /// The name/alias of the asset to try and search for. + /// Returns the specified if it exists, if not returns + TAsset Find(ContentTypes contentType, string assetName) where TAsset : class, IAsset; - /// - /// Load an asset embedded from within the binary. - /// - /// - /// The to load the embedded asset from. - /// The type of asset to load./ - /// The name of the file within the binary's manifest file. - /// Returns an instance of - TAsset LoadEmbedded( - IPluginContext context, - ContentTypes contentType, - string assetName - ) where TAsset : class, IAsset; + /// + /// Load an asset from disk by the specified file. + /// + /// + /// The type of asset to load. + /// The path of the asset file to load. + /// The alias to give to the asset for future reference. + /// Returns an instance of + TAsset Load(ContentTypes contentType, string assetPath, string assetAlias) where TAsset : class, IAsset; - /// - /// Load an asset embedded from within the binary. - /// - /// - /// The to load the embedded asset from. - /// The type of asset to load. - /// The name of the file within the binary's manifest file. - /// The alias to give to the asset for future reference. - /// Returns an instance of - TAsset LoadEmbedded( - IPluginContext context, - ContentTypes contentType, - string assetName, - string assetAlias - ) where TAsset : class, IAsset; + /// + /// Load an asset embedded from within the binary. + /// + /// + /// The to load the embedded asset from. + /// The type of asset to load./ + /// The name of the file within the binary's manifest file. + /// Returns an instance of + TAsset LoadEmbedded( + IPluginContext context, + ContentTypes contentType, + string assetName + ) where TAsset : class, IAsset; - } + /// + /// Load an asset embedded from within the binary. + /// + /// + /// The to load the embedded asset from. + /// The type of asset to load. + /// The name of the file within the binary's manifest file. + /// The alias to give to the asset for future reference. + /// Returns an instance of + TAsset LoadEmbedded( + IPluginContext context, + ContentTypes contentType, + string assetName, + string assetAlias + ) where TAsset : class, IAsset; } diff --git a/Intersect.Client.Framework/Content/TextureType.cs b/Intersect.Client.Framework/Content/TextureType.cs index 9b33b57486..d007cf942e 100644 --- a/Intersect.Client.Framework/Content/TextureType.cs +++ b/Intersect.Client.Framework/Content/TextureType.cs @@ -1,31 +1,30 @@ -namespace Intersect.Client.Framework.Content +namespace Intersect.Client.Framework.Content; + +public enum TextureType { - public enum TextureType - { - Tileset = 0, + Tileset = 0, - Item, + Item, - Entity, + Entity, - Spell, + Spell, - Animation, + Animation, - Face, + Face, - Image, + Image, - Fog, + Fog, - Resource, + Resource, - Paperdoll, + Paperdoll, - Gui, + Gui, - Misc, + Misc, - } } diff --git a/Intersect.Client.Framework/Core/Sounds/IMapSound.cs b/Intersect.Client.Framework/Core/Sounds/IMapSound.cs index d3bdb78194..bac8a18dce 100644 --- a/Intersect.Client.Framework/Core/Sounds/IMapSound.cs +++ b/Intersect.Client.Framework/Core/Sounds/IMapSound.cs @@ -1,7 +1,6 @@ -namespace Intersect.Client.Framework.Core.Sounds +namespace Intersect.Client.Framework.Core.Sounds; + +public interface IMapSound : ISound { - public interface IMapSound : ISound - { - void UpdatePosition(int x, int y, Guid mapId); - } + void UpdatePosition(int x, int y, Guid mapId); } \ No newline at end of file diff --git a/Intersect.Client.Framework/Core/Sounds/ISound.cs b/Intersect.Client.Framework/Core/Sounds/ISound.cs index e8a1039d2c..3771a2b8b6 100644 --- a/Intersect.Client.Framework/Core/Sounds/ISound.cs +++ b/Intersect.Client.Framework/Core/Sounds/ISound.cs @@ -1,11 +1,10 @@ -namespace Intersect.Client.Framework.Core.Sounds +namespace Intersect.Client.Framework.Core.Sounds; + +public interface ISound { - public interface ISound - { - bool Loaded { get; set; } - bool Loop { get; set; } + bool Loaded { get; set; } + bool Loop { get; set; } - void Stop(); - bool Update(); - } + void Stop(); + bool Update(); } \ No newline at end of file diff --git a/Intersect.Client.Framework/Database/GameDatabase.cs b/Intersect.Client.Framework/Database/GameDatabase.cs index 058642016e..e772fcb64f 100644 --- a/Intersect.Client.Framework/Database/GameDatabase.cs +++ b/Intersect.Client.Framework/Database/GameDatabase.cs @@ -1,178 +1,176 @@ using Intersect.Enums; -namespace Intersect.Client.Framework.Database +namespace Intersect.Client.Framework.Database; + +/// +/// User preferences database for client settings. +/// +public abstract partial class GameDatabase { - /// - /// User preferences database for client settings. - /// - public abstract partial class GameDatabase - { - public bool FullScreen { get; set; } + public bool FullScreen { get; set; } - public bool HideOthersOnWindowOpen { get; set; } + public bool HideOthersOnWindowOpen { get; set; } - public bool AutoToggleChatLog { get; set; } + public bool AutoToggleChatLog { get; set; } - public bool TargetAccountDirection { get; set; } + public bool TargetAccountDirection { get; set; } - public int MusicVolume { get; set; } + public int MusicVolume { get; set; } - public int SoundVolume { get; set; } + public int SoundVolume { get; set; } - public int TargetFps { get; set; } + public int TargetFps { get; set; } - public int TargetResolution { get; set; } + public int TargetResolution { get; set; } - public bool EnableLighting { get; set; } + public bool EnableLighting { get; set; } - public bool StickyTarget { get; set; } + public bool StickyTarget { get; set; } - public bool AutoTurnToTarget { get; set; } + public bool AutoTurnToTarget { get; set; } - public bool FriendOverheadInfo { get; set; } + public bool FriendOverheadInfo { get; set; } - public bool FriendOverheadHpBar { get; set; } + public bool FriendOverheadHpBar { get; set; } - public bool GuildMemberOverheadInfo { get; set; } + public bool GuildMemberOverheadInfo { get; set; } - public bool GuildMemberOverheadHpBar { get; set; } + public bool GuildMemberOverheadHpBar { get; set; } - public bool MyOverheadInfo { get; set; } + public bool MyOverheadInfo { get; set; } - public bool MyOverheadHpBar { get; set; } + public bool MyOverheadHpBar { get; set; } - public bool NpcOverheadInfo { get; set; } + public bool NpcOverheadInfo { get; set; } - public bool NpcOverheadHpBar { get; set; } + public bool NpcOverheadHpBar { get; set; } - public bool PartyMemberOverheadInfo { get; set; } + public bool PartyMemberOverheadInfo { get; set; } - public bool PartyMemberOverheadHpBar { get; set; } + public bool PartyMemberOverheadHpBar { get; set; } - public bool PlayerOverheadInfo { get; set; } + public bool PlayerOverheadInfo { get; set; } - public bool PlayerOverheadHpBar { get; set; } + public bool PlayerOverheadHpBar { get; set; } - public bool ShowExperienceAsPercentage { get; set; } + public bool ShowExperienceAsPercentage { get; set; } - public bool ShowHealthAsPercentage { get; set; } + public bool ShowHealthAsPercentage { get; set; } - public bool ShowManaAsPercentage { get; set; } + public bool ShowManaAsPercentage { get; set; } - public TypewriterBehavior TypewriterBehavior { get; set; } + public TypewriterBehavior TypewriterBehavior { get; set; } - public float UIScale { get; set; } = 1.0f; + public float UIScale { get; set; } = 1.0f; - public float WorldZoom { get; set; } = 1.0f; + public float WorldZoom { get; set; } = 1.0f; - public abstract void DeletePreference(string key); + public abstract void DeletePreference(string key); - public abstract bool HasPreference(string key); + public abstract bool HasPreference(string key); - //Saving password, other stuff we don't want in the games directory - public abstract void SavePreference(string key, TValue value); + //Saving password, other stuff we don't want in the games directory + public abstract void SavePreference(string key, TValue value); - public abstract string LoadPreference(string key); + public abstract string LoadPreference(string key); - public T LoadPreference(string key, T defaultValue) + public T LoadPreference(string key, T defaultValue) + { + var value = LoadPreference(key); + if (string.IsNullOrEmpty(value)) { - var value = LoadPreference(key); - if (string.IsNullOrEmpty(value)) + return defaultValue; + } + + var type = typeof(T); + if (type.IsEnum) + { + try { - return defaultValue; + var enumValue = Enum.Parse(type, value); + return (T)enumValue; } - - var type = typeof(T); - if (type.IsEnum) + catch { - try - { - var enumValue = Enum.Parse(type, value); - return (T)enumValue; - } - catch - { - return defaultValue; - } + return defaultValue; } - - return (T)Convert.ChangeType(value, typeof(T)); - } - - /// - /// Load all settings preferences when the game starts. - /// - public virtual void LoadPreferences() - { - MusicVolume = LoadPreference(nameof(MusicVolume), 10); - SoundVolume = LoadPreference(nameof(SoundVolume), 15); - TargetResolution = LoadPreference(nameof(TargetResolution), -1); - TargetFps = LoadPreference(nameof(TargetFps), 0); - FullScreen = LoadPreference(nameof(FullScreen), false); - EnableLighting = LoadPreference(nameof(EnableLighting), true); - HideOthersOnWindowOpen = LoadPreference(nameof(HideOthersOnWindowOpen), true); - AutoToggleChatLog = LoadPreference(nameof(AutoToggleChatLog), false); - TargetAccountDirection = LoadPreference(nameof(TargetAccountDirection), false); - StickyTarget = LoadPreference(nameof(StickyTarget), false); - AutoTurnToTarget = LoadPreference(nameof(AutoTurnToTarget), false); - FriendOverheadInfo = LoadPreference(nameof(FriendOverheadInfo), true); - FriendOverheadHpBar = LoadPreference(nameof(FriendOverheadHpBar), false); - GuildMemberOverheadInfo = LoadPreference(nameof(GuildMemberOverheadInfo), true); - GuildMemberOverheadHpBar = LoadPreference(nameof(GuildMemberOverheadHpBar), false); - MyOverheadInfo = LoadPreference(nameof(MyOverheadInfo), true); - MyOverheadHpBar = LoadPreference(nameof(MyOverheadHpBar), false); - NpcOverheadInfo = LoadPreference(nameof(NpcOverheadInfo), true); - NpcOverheadHpBar = LoadPreference(nameof(NpcOverheadHpBar), false); - PartyMemberOverheadInfo = LoadPreference(nameof(PartyMemberOverheadInfo), true); - PartyMemberOverheadHpBar = LoadPreference(nameof(PartyMemberOverheadHpBar), false); - PlayerOverheadInfo = LoadPreference(nameof(PlayerOverheadInfo), true); - PlayerOverheadHpBar = LoadPreference(nameof(PlayerOverheadHpBar), false); - ShowExperienceAsPercentage = LoadPreference(nameof(ShowExperienceAsPercentage), true); - ShowHealthAsPercentage = LoadPreference(nameof(ShowHealthAsPercentage), false); - ShowManaAsPercentage = LoadPreference(nameof(ShowManaAsPercentage), false); - TypewriterBehavior = LoadPreference(nameof(TypewriterBehavior), TypewriterBehavior.Word); - UIScale = LoadPreference(nameof(UIScale), 1.0f); - WorldZoom = LoadPreference(nameof(WorldZoom), 1.0f); } - /// - /// Saves all settings when applying preferences. - /// - public virtual void SavePreferences() - { - SavePreference(nameof(MusicVolume), MusicVolume); - SavePreference(nameof(SoundVolume), SoundVolume); - SavePreference(nameof(TargetResolution), TargetResolution); - SavePreference(nameof(TargetFps), TargetFps); - SavePreference(nameof(FullScreen), FullScreen); - SavePreference(nameof(EnableLighting), EnableLighting); - SavePreference(nameof(HideOthersOnWindowOpen), HideOthersOnWindowOpen); - SavePreference(nameof(AutoToggleChatLog), AutoToggleChatLog); - SavePreference(nameof(TargetAccountDirection), TargetAccountDirection); - SavePreference(nameof(StickyTarget), StickyTarget); - SavePreference(nameof(AutoTurnToTarget), AutoTurnToTarget); - SavePreference(nameof(FriendOverheadInfo), FriendOverheadInfo); - SavePreference(nameof(FriendOverheadHpBar), FriendOverheadHpBar); - SavePreference(nameof(GuildMemberOverheadInfo), GuildMemberOverheadInfo); - SavePreference(nameof(GuildMemberOverheadHpBar), GuildMemberOverheadHpBar); - SavePreference(nameof(MyOverheadInfo), MyOverheadInfo); - SavePreference(nameof(MyOverheadHpBar), MyOverheadHpBar); - SavePreference(nameof(NpcOverheadInfo), NpcOverheadInfo); - SavePreference(nameof(NpcOverheadHpBar), NpcOverheadHpBar); - SavePreference(nameof(PartyMemberOverheadInfo), PartyMemberOverheadInfo); - SavePreference(nameof(PartyMemberOverheadHpBar), PartyMemberOverheadHpBar); - SavePreference(nameof(PlayerOverheadInfo), PlayerOverheadInfo); - SavePreference(nameof(PlayerOverheadHpBar), PlayerOverheadHpBar); - SavePreference(nameof(ShowExperienceAsPercentage), ShowExperienceAsPercentage); - SavePreference(nameof(ShowHealthAsPercentage), ShowHealthAsPercentage); - SavePreference(nameof(ShowManaAsPercentage), ShowManaAsPercentage); - SavePreference(nameof(TypewriterBehavior), TypewriterBehavior); - SavePreference(nameof(UIScale), UIScale); - SavePreference(nameof(WorldZoom), WorldZoom); - } + return (T)Convert.ChangeType(value, typeof(T)); + } - public abstract bool LoadConfig(); + /// + /// Load all settings preferences when the game starts. + /// + public virtual void LoadPreferences() + { + MusicVolume = LoadPreference(nameof(MusicVolume), 10); + SoundVolume = LoadPreference(nameof(SoundVolume), 15); + TargetResolution = LoadPreference(nameof(TargetResolution), -1); + TargetFps = LoadPreference(nameof(TargetFps), 0); + FullScreen = LoadPreference(nameof(FullScreen), false); + EnableLighting = LoadPreference(nameof(EnableLighting), true); + HideOthersOnWindowOpen = LoadPreference(nameof(HideOthersOnWindowOpen), true); + AutoToggleChatLog = LoadPreference(nameof(AutoToggleChatLog), false); + TargetAccountDirection = LoadPreference(nameof(TargetAccountDirection), false); + StickyTarget = LoadPreference(nameof(StickyTarget), false); + AutoTurnToTarget = LoadPreference(nameof(AutoTurnToTarget), false); + FriendOverheadInfo = LoadPreference(nameof(FriendOverheadInfo), true); + FriendOverheadHpBar = LoadPreference(nameof(FriendOverheadHpBar), false); + GuildMemberOverheadInfo = LoadPreference(nameof(GuildMemberOverheadInfo), true); + GuildMemberOverheadHpBar = LoadPreference(nameof(GuildMemberOverheadHpBar), false); + MyOverheadInfo = LoadPreference(nameof(MyOverheadInfo), true); + MyOverheadHpBar = LoadPreference(nameof(MyOverheadHpBar), false); + NpcOverheadInfo = LoadPreference(nameof(NpcOverheadInfo), true); + NpcOverheadHpBar = LoadPreference(nameof(NpcOverheadHpBar), false); + PartyMemberOverheadInfo = LoadPreference(nameof(PartyMemberOverheadInfo), true); + PartyMemberOverheadHpBar = LoadPreference(nameof(PartyMemberOverheadHpBar), false); + PlayerOverheadInfo = LoadPreference(nameof(PlayerOverheadInfo), true); + PlayerOverheadHpBar = LoadPreference(nameof(PlayerOverheadHpBar), false); + ShowExperienceAsPercentage = LoadPreference(nameof(ShowExperienceAsPercentage), true); + ShowHealthAsPercentage = LoadPreference(nameof(ShowHealthAsPercentage), false); + ShowManaAsPercentage = LoadPreference(nameof(ShowManaAsPercentage), false); + TypewriterBehavior = LoadPreference(nameof(TypewriterBehavior), TypewriterBehavior.Word); + UIScale = LoadPreference(nameof(UIScale), 1.0f); + WorldZoom = LoadPreference(nameof(WorldZoom), 1.0f); + } + /// + /// Saves all settings when applying preferences. + /// + public virtual void SavePreferences() + { + SavePreference(nameof(MusicVolume), MusicVolume); + SavePreference(nameof(SoundVolume), SoundVolume); + SavePreference(nameof(TargetResolution), TargetResolution); + SavePreference(nameof(TargetFps), TargetFps); + SavePreference(nameof(FullScreen), FullScreen); + SavePreference(nameof(EnableLighting), EnableLighting); + SavePreference(nameof(HideOthersOnWindowOpen), HideOthersOnWindowOpen); + SavePreference(nameof(AutoToggleChatLog), AutoToggleChatLog); + SavePreference(nameof(TargetAccountDirection), TargetAccountDirection); + SavePreference(nameof(StickyTarget), StickyTarget); + SavePreference(nameof(AutoTurnToTarget), AutoTurnToTarget); + SavePreference(nameof(FriendOverheadInfo), FriendOverheadInfo); + SavePreference(nameof(FriendOverheadHpBar), FriendOverheadHpBar); + SavePreference(nameof(GuildMemberOverheadInfo), GuildMemberOverheadInfo); + SavePreference(nameof(GuildMemberOverheadHpBar), GuildMemberOverheadHpBar); + SavePreference(nameof(MyOverheadInfo), MyOverheadInfo); + SavePreference(nameof(MyOverheadHpBar), MyOverheadHpBar); + SavePreference(nameof(NpcOverheadInfo), NpcOverheadInfo); + SavePreference(nameof(NpcOverheadHpBar), NpcOverheadHpBar); + SavePreference(nameof(PartyMemberOverheadInfo), PartyMemberOverheadInfo); + SavePreference(nameof(PartyMemberOverheadHpBar), PartyMemberOverheadHpBar); + SavePreference(nameof(PlayerOverheadInfo), PlayerOverheadInfo); + SavePreference(nameof(PlayerOverheadHpBar), PlayerOverheadHpBar); + SavePreference(nameof(ShowExperienceAsPercentage), ShowExperienceAsPercentage); + SavePreference(nameof(ShowHealthAsPercentage), ShowHealthAsPercentage); + SavePreference(nameof(ShowManaAsPercentage), ShowManaAsPercentage); + SavePreference(nameof(TypewriterBehavior), TypewriterBehavior); + SavePreference(nameof(UIScale), UIScale); + SavePreference(nameof(WorldZoom), WorldZoom); } + public abstract bool LoadConfig(); + } diff --git a/Intersect.Client.Framework/Entities/IAnimation.cs b/Intersect.Client.Framework/Entities/IAnimation.cs index 89e455e2dd..b32010a604 100644 --- a/Intersect.Client.Framework/Entities/IAnimation.cs +++ b/Intersect.Client.Framework/Entities/IAnimation.cs @@ -1,19 +1,18 @@ using Intersect.GameObjects; using Intersect.Enums; -namespace Intersect.Client.Framework.Entities +namespace Intersect.Client.Framework.Entities; + +public interface IAnimation : IDisposable { - public interface IAnimation : IDisposable - { - bool AutoRotate { get; set; } - bool Hidden { get; set; } - bool InfiniteLoop { get; set; } - AnimationBase MyBase { get; set; } - Point Size { get; } + bool AutoRotate { get; set; } + bool Hidden { get; set; } + bool InfiniteLoop { get; set; } + AnimationBase MyBase { get; set; } + Point Size { get; } - void Hide(); - void SetDir(Direction dir); - void SetPosition(float worldX, float worldY, int mapx, int mapy, Guid mapId, Direction dir, int z = 0); - void Show(); - } + void Hide(); + void SetDir(Direction dir); + void SetPosition(float worldX, float worldY, int mapx, int mapy, Guid mapId, Direction dir, int z = 0); + void Show(); } diff --git a/Intersect.Client.Framework/Entities/IDash.cs b/Intersect.Client.Framework/Entities/IDash.cs index c5e1618062..2e5c9eb6d7 100644 --- a/Intersect.Client.Framework/Entities/IDash.cs +++ b/Intersect.Client.Framework/Entities/IDash.cs @@ -1,8 +1,7 @@ -namespace Intersect.Client.Framework.Entities +namespace Intersect.Client.Framework.Entities; + +public interface IDash { - public interface IDash - { - float OffsetX { get; } - float OffsetY { get; } - } + float OffsetX { get; } + float OffsetY { get; } } \ No newline at end of file diff --git a/Intersect.Client.Framework/Entities/IEntity.cs b/Intersect.Client.Framework/Entities/IEntity.cs index 45b15fac67..29ff97c8f5 100644 --- a/Intersect.Client.Framework/Entities/IEntity.cs +++ b/Intersect.Client.Framework/Entities/IEntity.cs @@ -4,53 +4,52 @@ using Intersect.Client.Framework.Maps; using Intersect.Enums; -namespace Intersect.Client.Framework.Entities +namespace Intersect.Client.Framework.Entities; + +public interface IEntity : IDisposable { - public interface IEntity : IDisposable - { - Guid Id { get; } - EntityType Type { get; } - string Name { get; } - Gender Gender { get; } - Color NameColor { get; } - Label FooterLabel { get; } - Label HeaderLabel { get; } - bool IsHidden { get; } - string Sprite { get; } - string TransformedSprite { get; } - string Face { get; } - GameTexture Texture { get; } - Color Color { get; } - FloatRect WorldPos { get; } - float OffsetX { get; } - float OffsetY { get; } - Pointf Center { get; } - Pointf Origin { get; } - bool IsMoving { get; } - bool IsStealthed { get; } - bool IsBlocking { get; } - bool IsDashing { get; } - IDash CurrentDash { get; } - bool IsCasting { get; } - bool InView { get; } - IMapInstance MapInstance { get; } - Guid MapId { get; } - Direction Dir { get; } - byte X { get; } - byte Y { get; } - byte Z { get; } - int Level { get; } - IReadOnlyList Stats { get; } - IReadOnlyList Vitals { get; } - IReadOnlyList MaxVitals { get; } - IReadOnlyList Items { get; } - IReadOnlyList EquipmentSlots { get; } - IReadOnlyList Spells { get; } - IReadOnlyList Status { get; } - NpcAggression Aggression { get; } + Guid Id { get; } + EntityType Type { get; } + string Name { get; } + Gender Gender { get; } + Color NameColor { get; } + Label FooterLabel { get; } + Label HeaderLabel { get; } + bool IsHidden { get; } + string Sprite { get; } + string TransformedSprite { get; } + string Face { get; } + GameTexture Texture { get; } + Color Color { get; } + FloatRect WorldPos { get; } + float OffsetX { get; } + float OffsetY { get; } + Pointf Center { get; } + Pointf Origin { get; } + bool IsMoving { get; } + bool IsStealthed { get; } + bool IsBlocking { get; } + bool IsDashing { get; } + IDash CurrentDash { get; } + bool IsCasting { get; } + bool InView { get; } + IMapInstance MapInstance { get; } + Guid MapId { get; } + Direction Dir { get; } + byte X { get; } + byte Y { get; } + byte Z { get; } + int Level { get; } + IReadOnlyList Stats { get; } + IReadOnlyList Vitals { get; } + IReadOnlyList MaxVitals { get; } + IReadOnlyList Items { get; } + IReadOnlyList EquipmentSlots { get; } + IReadOnlyList Spells { get; } + IReadOnlyList Status { get; } + NpcAggression Aggression { get; } - void AddChatBubble(string text); - float GetLabelLocation(LabelType type); - float GetTop(int overrideHeight = 0); - } + void AddChatBubble(string text); + float GetLabelLocation(LabelType type); + float GetTop(int overrideHeight = 0); } diff --git a/Intersect.Client.Framework/Entities/IFriendInstance.cs b/Intersect.Client.Framework/Entities/IFriendInstance.cs index 30fbd1aa8f..79ae42f81a 100644 --- a/Intersect.Client.Framework/Entities/IFriendInstance.cs +++ b/Intersect.Client.Framework/Entities/IFriendInstance.cs @@ -1,9 +1,8 @@ -namespace Intersect.Client.Framework.Entities +namespace Intersect.Client.Framework.Entities; + +public interface IFriendInstance { - public interface IFriendInstance - { - string Map { get; set; } - string Name { get; set; } - bool Online { get; set; } - } + string Map { get; set; } + string Name { get; set; } + bool Online { get; set; } } \ No newline at end of file diff --git a/Intersect.Client.Framework/Entities/IHotbarInstance.cs b/Intersect.Client.Framework/Entities/IHotbarInstance.cs index ccec35d3c1..f7b1ae003a 100644 --- a/Intersect.Client.Framework/Entities/IHotbarInstance.cs +++ b/Intersect.Client.Framework/Entities/IHotbarInstance.cs @@ -1,9 +1,8 @@ -namespace Intersect.Client.Framework.Entities +namespace Intersect.Client.Framework.Entities; + +public interface IHotbarInstance { - public interface IHotbarInstance - { - Guid BagId { get; set; } - Guid ItemOrSpellId { get; set; } - int[] PreferredStatBuffs { get; set; } - } + Guid BagId { get; set; } + Guid ItemOrSpellId { get; set; } + int[] PreferredStatBuffs { get; set; } } \ No newline at end of file diff --git a/Intersect.Client.Framework/Entities/IPartyMember.cs b/Intersect.Client.Framework/Entities/IPartyMember.cs index 6d9f993f67..64da31b420 100644 --- a/Intersect.Client.Framework/Entities/IPartyMember.cs +++ b/Intersect.Client.Framework/Entities/IPartyMember.cs @@ -1,11 +1,10 @@ -namespace Intersect.Client.Framework.Entities +namespace Intersect.Client.Framework.Entities; + +public interface IPartyMember { - public interface IPartyMember - { - Guid Id { get; set; } - int Level { get; set; } - long[] MaxVital { get; set; } - string Name { get; set; } - long[] Vital { get; set; } - } + Guid Id { get; set; } + int Level { get; set; } + long[] MaxVital { get; set; } + string Name { get; set; } + long[] Vital { get; set; } } \ No newline at end of file diff --git a/Intersect.Client.Framework/Entities/IPlayer.cs b/Intersect.Client.Framework/Entities/IPlayer.cs index a30526b271..2513778a7a 100644 --- a/Intersect.Client.Framework/Entities/IPlayer.cs +++ b/Intersect.Client.Framework/Entities/IPlayer.cs @@ -2,63 +2,62 @@ using Intersect.Enums; using Intersect.GameObjects; -namespace Intersect.Client.Framework.Entities +namespace Intersect.Client.Framework.Entities; + +public interface IPlayer : IEntity { - public interface IPlayer : IEntity - { - Guid Class { get; } - long Experience { get; } - long ExperienceToNextLevel { get; } - int StatPoints { get; } - bool IsInParty { get; } - IReadOnlyList PartyMembers { get; } - long CombatTimer { get; } - Guid TargetIndex { get; } - TargetType TargetType { get; } - IReadOnlyList Friends { get; } - IReadOnlyList HotbarSlots { get; } - IReadOnlyDictionary ItemCooldowns { get; } - IReadOnlyDictionary SpellCooldowns { get; } - IReadOnlyDictionary QuestProgress { get; } - Guid[] HiddenQuests { get; } - bool IsInGuild { get; } - string GuildName { get; } - GuildRank GuildRank { get; } - bool IsBusy { get; } + Guid Class { get; } + long Experience { get; } + long ExperienceToNextLevel { get; } + int StatPoints { get; } + bool IsInParty { get; } + IReadOnlyList PartyMembers { get; } + long CombatTimer { get; } + Guid TargetIndex { get; } + TargetType TargetType { get; } + IReadOnlyList Friends { get; } + IReadOnlyList HotbarSlots { get; } + IReadOnlyDictionary ItemCooldowns { get; } + IReadOnlyDictionary SpellCooldowns { get; } + IReadOnlyDictionary QuestProgress { get; } + Guid[] HiddenQuests { get; } + bool IsInGuild { get; } + string GuildName { get; } + GuildRank GuildRank { get; } + bool IsBusy { get; } - bool TryGetRealLocation(ref int x, ref int y, ref Guid mapId); - bool TryTarget(); - bool TryTarget(IEntity entity, bool force = false); - void AutoTarget(); - bool ClearTarget(); - void AddToHotbar(int hotbarSlot, sbyte itemType, int itemSlot); - int FindHotbarItem(IHotbarInstance hotbarInstance); - int FindHotbarSpell(IHotbarInstance hotbarInstance); - void HotbarSwap(int index, int swapIndex); - int FindItem(Guid itemId, int itemVal = 1); - void SwapItems(int item1, int item2); - long GetItemCooldown(Guid id); - long GetItemRemainingCooldown(int slot); - bool IsItemOnCooldown(int slot); - void TryDropItem(int index); - void TryUseItem(int index); - void SwapSpells(int spell1, int spell2); - long GetSpellCooldown(Guid id); - long GetSpellRemainingCooldown(int slot); - bool IsSpellOnCooldown(int slot); - void TryForgetSpell(int index); - void TryUseSpell(Guid spellId); - void TryUseSpell(int index); - bool IsEquipped(int slot); - bool IsInMyParty(Guid id); - bool IsInMyParty(IPlayer player); - bool TryAttack(); - bool TryBlock(); + bool TryGetRealLocation(ref int x, ref int y, ref Guid mapId); + bool TryTarget(); + bool TryTarget(IEntity entity, bool force = false); + void AutoTarget(); + bool ClearTarget(); + void AddToHotbar(int hotbarSlot, sbyte itemType, int itemSlot); + int FindHotbarItem(IHotbarInstance hotbarInstance); + int FindHotbarSpell(IHotbarInstance hotbarInstance); + void HotbarSwap(int index, int swapIndex); + int FindItem(Guid itemId, int itemVal = 1); + void SwapItems(int item1, int item2); + long GetItemCooldown(Guid id); + long GetItemRemainingCooldown(int slot); + bool IsItemOnCooldown(int slot); + void TryDropItem(int index); + void TryUseItem(int index); + void SwapSpells(int spell1, int spell2); + long GetSpellCooldown(Guid id); + long GetSpellRemainingCooldown(int slot); + bool IsSpellOnCooldown(int slot); + void TryForgetSpell(int index); + void TryUseSpell(Guid spellId); + void TryUseSpell(int index); + bool IsEquipped(int slot); + bool IsInMyParty(Guid id); + bool IsInMyParty(IPlayer player); + bool TryAttack(); + bool TryBlock(); - - - } + + } diff --git a/Intersect.Client.Framework/Entities/IResource.cs b/Intersect.Client.Framework/Entities/IResource.cs index ddd3b4f4aa..a789df00e7 100644 --- a/Intersect.Client.Framework/Entities/IResource.cs +++ b/Intersect.Client.Framework/Entities/IResource.cs @@ -1,12 +1,11 @@ using Intersect.GameObjects; -namespace Intersect.Client.Framework.Entities +namespace Intersect.Client.Framework.Entities; + +public interface IResource : IEntity { - public interface IResource : IEntity - { - ResourceBase BaseResource { get; } - - bool IsDepleted { get; } + ResourceBase BaseResource { get; } + + bool IsDepleted { get; } - } } \ No newline at end of file diff --git a/Intersect.Client.Framework/Entities/IStatus.cs b/Intersect.Client.Framework/Entities/IStatus.cs index 7e6d5a0dda..f5e0b6ec4f 100644 --- a/Intersect.Client.Framework/Entities/IStatus.cs +++ b/Intersect.Client.Framework/Entities/IStatus.cs @@ -1,18 +1,17 @@ using Intersect.Enums; -namespace Intersect.Client.Framework.Entities +namespace Intersect.Client.Framework.Entities; + +public interface IStatus { - public interface IStatus - { - string Data { get; set; } - long[] Shield { get; set; } - Guid SpellId { get; set; } - long TimeRecevied { get; set; } - long TimeRemaining { get; set; } - long TotalDuration { get; set; } - SpellEffect Type { get; set; } + string Data { get; set; } + long[] Shield { get; set; } + Guid SpellId { get; set; } + long TimeRecevied { get; set; } + long TimeRemaining { get; set; } + long TotalDuration { get; set; } + SpellEffect Type { get; set; } - bool IsActive { get; } - long RemainingMs { get; } - } + bool IsActive { get; } + long RemainingMs { get; } } \ No newline at end of file diff --git a/Intersect.Client.Framework/Entities/Label.cs b/Intersect.Client.Framework/Entities/Label.cs index 6cff5d37b0..cc6adf2861 100644 --- a/Intersect.Client.Framework/Entities/Label.cs +++ b/Intersect.Client.Framework/Entities/Label.cs @@ -1,21 +1,19 @@ using Newtonsoft.Json; -namespace Intersect.Client.Framework.Entities -{ +namespace Intersect.Client.Framework.Entities; - public partial class Label - { - [JsonProperty("Label")] public string Text { get; set; } +public partial class Label +{ - public Color Color { get; set; } + [JsonProperty("Label")] public string Text { get; set; } - public Label(string label, Color color) - { - Text = label; - Color = color; - } + public Color Color { get; set; } + public Label(string label, Color color) + { + Text = label; + Color = color; } } diff --git a/Intersect.Client.Framework/Entities/LabelType.cs b/Intersect.Client.Framework/Entities/LabelType.cs index a2fbe4c2ec..70b906ad79 100644 --- a/Intersect.Client.Framework/Entities/LabelType.cs +++ b/Intersect.Client.Framework/Entities/LabelType.cs @@ -1,17 +1,16 @@ -namespace Intersect.Client.Framework.Entities +namespace Intersect.Client.Framework.Entities; + +public enum LabelType { - public enum LabelType - { - Header = 0, + Header = 0, - Footer, + Footer, - Name, + Name, - ChatBubble, + ChatBubble, - Guild + Guild - } } diff --git a/Intersect.Client.Framework/Entities/SpriteAnimations.cs b/Intersect.Client.Framework/Entities/SpriteAnimations.cs index 7e5454a3de..6da9db0157 100644 --- a/Intersect.Client.Framework/Entities/SpriteAnimations.cs +++ b/Intersect.Client.Framework/Entities/SpriteAnimations.cs @@ -1,12 +1,11 @@ -namespace Intersect.Client.Framework.Entities +namespace Intersect.Client.Framework.Entities; + +public enum SpriteAnimations { - public enum SpriteAnimations - { - Normal = 0, - Idle, - Attack, - Shoot, - Cast, - Weapon, - } + Normal = 0, + Idle, + Attack, + Shoot, + Cast, + Weapon, } diff --git a/Intersect.Client.Framework/File Management/GameContentManager.cs b/Intersect.Client.Framework/File Management/GameContentManager.cs index 740ec33f24..633fe83412 100644 --- a/Intersect.Client.Framework/File Management/GameContentManager.cs +++ b/Intersect.Client.Framework/File Management/GameContentManager.cs @@ -7,607 +7,605 @@ using Intersect.Logging; using Intersect.Plugins; -namespace Intersect.Client.Framework.File_Management +namespace Intersect.Client.Framework.File_Management; + + +public abstract partial class GameContentManager : IContentManager { - public abstract partial class GameContentManager : IContentManager + + + public enum UI { + Menu, + InGame, + Shared, - public enum UI - { - Menu, + Debug, + } - InGame, + public static GameContentManager Current; - Shared, + protected Dictionary mAnimationDict = new Dictionary(); - Debug, - } + protected Dictionary mEntityDict = new Dictionary(); - public static GameContentManager Current; + protected Dictionary mFaceDict = new Dictionary(); - protected Dictionary mAnimationDict = new Dictionary(); + protected Dictionary mFogDict = new Dictionary(); - protected Dictionary mEntityDict = new Dictionary(); + protected List mFontDict = new List(); - protected Dictionary mFaceDict = new Dictionary(); + protected Dictionary mGuiDict = new Dictionary(); - protected Dictionary mFogDict = new Dictionary(); + protected Dictionary mImageDict = new Dictionary(); - protected List mFontDict = new List(); + protected Dictionary mItemDict = new Dictionary(); - protected Dictionary mGuiDict = new Dictionary(); + protected Dictionary mMiscDict = new Dictionary(); - protected Dictionary mImageDict = new Dictionary(); + protected Dictionary mMusicDict = new Dictionary(); - protected Dictionary mItemDict = new Dictionary(); + protected Dictionary mPaperdollDict = new Dictionary(); - protected Dictionary mMiscDict = new Dictionary(); + protected Dictionary mResourceDict = new Dictionary(); - protected Dictionary mMusicDict = new Dictionary(); + protected Dictionary mShaderDict = new Dictionary(); - protected Dictionary mPaperdollDict = new Dictionary(); + protected Dictionary mSoundDict = new Dictionary(); - protected Dictionary mResourceDict = new Dictionary(); + protected Dictionary, string> mUiDict = new Dictionary, string>(); - protected Dictionary mShaderDict = new Dictionary(); + /// + /// Contains all indexed files and their caches from sound pack files. + /// + public AssetPacker SoundPacks { get; set; } - protected Dictionary mSoundDict = new Dictionary(); + /// + /// Contains all indexed files and their caches from music pack files. + /// + public AssetPacker MusicPacks { get; set; } - protected Dictionary, string> mUiDict = new Dictionary, string>(); + protected Dictionary mSpellDict = new Dictionary(); - /// - /// Contains all indexed files and their caches from sound pack files. - /// - public AssetPacker SoundPacks { get; set; } + protected Dictionary mTexturePackDict = new Dictionary(); - /// - /// Contains all indexed files and their caches from music pack files. - /// - public AssetPacker MusicPacks { get; set; } + //Game Content + protected Dictionary mTilesetDict = new Dictionary(); - protected Dictionary mSpellDict = new Dictionary(); + public bool TilesetsLoaded = false; - protected Dictionary mTexturePackDict = new Dictionary(); + public ContentWatcher ContentWatcher { get; protected set; } - //Game Content - protected Dictionary mTilesetDict = new Dictionary(); + public void Init(GameContentManager manager) + { + Current = manager; + } - public bool TilesetsLoaded = false; + //Content Loading + public void LoadAll() + { + LoadTexturePacks(); + LoadEntities(); + LoadItems(); + LoadAnimations(); + LoadSpells(); + LoadFaces(); + LoadImages(); + LoadFogs(); + LoadResources(); + LoadPaperdolls(); + LoadMisc(); + LoadGui(); + LoadFonts(); + LoadShaders(); + } - public ContentWatcher ContentWatcher { get; protected set; } + public abstract void LoadTexturePacks(); - public void Init(GameContentManager manager) - { - Current = manager; - } + public abstract void LoadTilesets(string[] tilesetnames); - //Content Loading - public void LoadAll() - { - LoadTexturePacks(); - LoadEntities(); - LoadItems(); - LoadAnimations(); - LoadSpells(); - LoadFaces(); - LoadImages(); - LoadFogs(); - LoadResources(); - LoadPaperdolls(); - LoadMisc(); - LoadGui(); - LoadFonts(); - LoadShaders(); - } + public abstract void LoadItems(); - public abstract void LoadTexturePacks(); + public abstract void LoadEntities(); - public abstract void LoadTilesets(string[] tilesetnames); + public abstract void LoadSpells(); - public abstract void LoadItems(); + public abstract void LoadAnimations(); - public abstract void LoadEntities(); + public abstract void LoadFaces(); - public abstract void LoadSpells(); + public abstract void LoadImages(); - public abstract void LoadAnimations(); + public abstract void LoadFogs(); - public abstract void LoadFaces(); + public abstract void LoadResources(); - public abstract void LoadImages(); + public abstract void LoadPaperdolls(); - public abstract void LoadFogs(); + public abstract void LoadGui(); - public abstract void LoadResources(); + public abstract void LoadMisc(); - public abstract void LoadPaperdolls(); + public abstract void LoadFonts(); - public abstract void LoadGui(); + public abstract void LoadShaders(); - public abstract void LoadMisc(); + //Audio Loading + public void LoadAudio() + { + LoadSounds(); + LoadMusic(); + } - public abstract void LoadFonts(); + public abstract void LoadSounds(); - public abstract void LoadShaders(); + public abstract void LoadMusic(); - //Audio Loading - public void LoadAudio() + public static string RemoveExtension(string fileName) + { + var fileExtPos = fileName.LastIndexOf("."); + if (fileExtPos >= 0) { - LoadSounds(); - LoadMusic(); + fileName = fileName.Substring(0, fileExtPos); } - public abstract void LoadSounds(); - - public abstract void LoadMusic(); + return fileName; + } - public static string RemoveExtension(string fileName) + public string[] GetTextureNames(TextureType type) + { + switch (type) { - var fileExtPos = fileName.LastIndexOf("."); - if (fileExtPos >= 0) - { - fileName = fileName.Substring(0, fileExtPos); - } + case TextureType.Tileset: + return mTilesetDict.Keys.ToArray(); - return fileName; - } + case TextureType.Item: + return mItemDict.Keys.ToArray(); - public string[] GetTextureNames(TextureType type) - { - switch (type) - { - case TextureType.Tileset: - return mTilesetDict.Keys.ToArray(); - - case TextureType.Item: - return mItemDict.Keys.ToArray(); + case TextureType.Entity: + return mEntityDict.Keys.ToArray(); - case TextureType.Entity: - return mEntityDict.Keys.ToArray(); + case TextureType.Spell: + return mSpellDict.Keys.ToArray(); - case TextureType.Spell: - return mSpellDict.Keys.ToArray(); + case TextureType.Animation: + return mAnimationDict.Keys.ToArray(); - case TextureType.Animation: - return mAnimationDict.Keys.ToArray(); + case TextureType.Face: + return mFaceDict.Keys.ToArray(); - case TextureType.Face: - return mFaceDict.Keys.ToArray(); + case TextureType.Image: + return mImageDict.Keys.ToArray(); - case TextureType.Image: - return mImageDict.Keys.ToArray(); + case TextureType.Fog: + return mFogDict.Keys.ToArray(); - case TextureType.Fog: - return mFogDict.Keys.ToArray(); + case TextureType.Resource: + return mResourceDict.Keys.ToArray(); - case TextureType.Resource: - return mResourceDict.Keys.ToArray(); + case TextureType.Paperdoll: + return mPaperdollDict.Keys.ToArray(); - case TextureType.Paperdoll: - return mPaperdollDict.Keys.ToArray(); + case TextureType.Gui: + return mGuiDict.Keys.ToArray(); - case TextureType.Gui: - return mGuiDict.Keys.ToArray(); + case TextureType.Misc: + return mMiscDict.Keys.ToArray(); + } - case TextureType.Misc: - return mMiscDict.Keys.ToArray(); - } + return null; + } + //Content Getters + public virtual GameTexture GetTexture(TextureType type, string name) + { + if (string.IsNullOrEmpty(name)) + { return null; } - //Content Getters - public virtual GameTexture GetTexture(TextureType type, string name) + IDictionary textureDict; + switch (type) { - if (string.IsNullOrEmpty(name)) - { - return null; - } + case TextureType.Tileset: + textureDict = mTilesetDict; - IDictionary textureDict; - switch (type) - { - case TextureType.Tileset: - textureDict = mTilesetDict; + break; - break; + case TextureType.Item: + textureDict = mItemDict; - case TextureType.Item: - textureDict = mItemDict; + break; - break; + case TextureType.Entity: + textureDict = mEntityDict; - case TextureType.Entity: - textureDict = mEntityDict; + break; - break; + case TextureType.Spell: + textureDict = mSpellDict; - case TextureType.Spell: - textureDict = mSpellDict; + break; - break; + case TextureType.Animation: + textureDict = mAnimationDict; - case TextureType.Animation: - textureDict = mAnimationDict; + break; - break; + case TextureType.Face: + textureDict = mFaceDict; - case TextureType.Face: - textureDict = mFaceDict; + break; - break; + case TextureType.Image: + textureDict = mImageDict; - case TextureType.Image: - textureDict = mImageDict; + break; - break; + case TextureType.Fog: + textureDict = mFogDict; - case TextureType.Fog: - textureDict = mFogDict; + break; - break; + case TextureType.Resource: + textureDict = mResourceDict; - case TextureType.Resource: - textureDict = mResourceDict; + break; - break; + case TextureType.Paperdoll: + textureDict = mPaperdollDict; - case TextureType.Paperdoll: - textureDict = mPaperdollDict; + break; - break; + case TextureType.Gui: + textureDict = mGuiDict; - case TextureType.Gui: - textureDict = mGuiDict; + break; - break; + case TextureType.Misc: + textureDict = mMiscDict; - case TextureType.Misc: - textureDict = mMiscDict; + break; - break; + default: + return null; + } - default: - return null; - } + if (textureDict == null) + { + return null; + } - if (textureDict == null) - { - return null; - } + return textureDict.TryGetValue(name.ToLower(), out var asset) ? asset as GameTexture : default; + } - return textureDict.TryGetValue(name.ToLower(), out var asset) ? asset as GameTexture : default; + public virtual GameShader GetShader(string name) + { + if (string.IsNullOrEmpty(name)) + { + return null; } - public virtual GameShader GetShader(string name) + if (mShaderDict == null) { - if (string.IsNullOrEmpty(name)) - { - return null; - } + return null; + } - if (mShaderDict == null) - { - return null; - } + return mShaderDict.TryGetValue(name.ToLower(), out var effect) ? effect : null; + } - return mShaderDict.TryGetValue(name.ToLower(), out var effect) ? effect : null; + public virtual GameFont GetFont(string name, int size) + { + if (name == null) + { + return null; } - public virtual GameFont GetFont(string name, int size) - { - if (name == null) - { - return null; - } + return mFontDict.Where(t => t != null) + .Where(t => t.GetName().ToLower().Trim() == name.ToLower().Trim()) + .FirstOrDefault(t => t.GetSize() == size); + } - return mFontDict.Where(t => t != null) - .Where(t => t.GetName().ToLower().Trim() == name.ToLower().Trim()) - .FirstOrDefault(t => t.GetSize() == size); + public virtual GameAudioSource GetMusic(string name) + { + if (string.IsNullOrEmpty(name)) + { + return null; } - public virtual GameAudioSource GetMusic(string name) + if (mMusicDict == null) { - if (string.IsNullOrEmpty(name)) - { - return null; - } + return null; + } - if (mMusicDict == null) - { - return null; - } + return mMusicDict.TryGetValue(name.ToLower(), out var music) ? music as GameAudioSource : default; + } - return mMusicDict.TryGetValue(name.ToLower(), out var music) ? music as GameAudioSource : default; + public virtual GameAudioSource GetSound(string name) + { + if (string.IsNullOrEmpty(name)) + { + return null; } - public virtual GameAudioSource GetSound(string name) + if (mSoundDict == null) { - if (string.IsNullOrEmpty(name)) - { - return null; - } + return null; + } - if (mSoundDict == null) - { - return null; - } + return mSoundDict.TryGetValue(name.ToLower(), out var sound) ? sound as GameAudioSource : default; + } - return mSoundDict.TryGetValue(name.ToLower(), out var sound) ? sound as GameAudioSource : default; - } + public virtual bool GetLayout(UI stage, string name, string resolution, bool skipCache, Action layoutHandler) + { + var isReload = false; - public virtual bool GetLayout(UI stage, string name, string resolution, bool skipCache, Action layoutHandler) + var stageName = stage.ToString().ToLowerInvariant(); + if (stage == UI.InGame) { - var isReload = false; + stageName = "game"; + } - var stageName = stage.ToString().ToLowerInvariant(); - if (stage == UI.InGame) - { - stageName = "game"; - } + var resourcePartialDirectory = Path.Combine("gui", "layouts", stageName); - var resourcePartialDirectory = Path.Combine("gui", "layouts", stageName); + void onLayoutReady() + { + var result = GetLayout(stage, name, resolution, skipCache || isReload, out var cacheHit); + layoutHandler(result, cacheHit); + isReload = true; + } - void onLayoutReady() - { - var result = GetLayout(stage, name, resolution, skipCache || isReload, out var cacheHit); - layoutHandler(result, cacheHit); - isReload = true; - } + void addChangeListener(string targetPath) + { + ContentWatcher?.AddEventListener(ContentWatcher.Event.Change, targetPath, () => onLayoutReady()); + onLayoutReady(); + } - void addChangeListener(string targetPath) + void addCreateOrChangeListener(string targetPath, bool createIfMissing) + { + var resourcePath = Path.Combine(ClientConfiguration.ResourcesDirectory, targetPath); + if (File.Exists(resourcePath)) { - ContentWatcher?.AddEventListener(ContentWatcher.Event.Change, targetPath, () => onLayoutReady()); - onLayoutReady(); + addChangeListener(targetPath); } - - void addCreateOrChangeListener(string targetPath, bool createIfMissing) + else { - var resourcePath = Path.Combine(ClientConfiguration.ResourcesDirectory, targetPath); - if (File.Exists(resourcePath)) + if (createIfMissing) { - addChangeListener(targetPath); - } - else - { - if (createIfMissing) - { - layoutHandler?.Invoke(string.Empty, false); - } - - ContentWatcher?.AddEventListener(ContentWatcher.Event.Create, targetPath, () => addChangeListener(targetPath)); + layoutHandler?.Invoke(string.Empty, false); } - } - if (!string.IsNullOrWhiteSpace(resolution)) - { - var resolutionPath = Path.Combine(resourcePartialDirectory, $"{name}.{resolution}.json"); - addCreateOrChangeListener(resolutionPath, false); + ContentWatcher?.AddEventListener(ContentWatcher.Event.Create, targetPath, () => addChangeListener(targetPath)); } - - var genericPath = Path.Combine(resourcePartialDirectory, $"{name}.json"); - addCreateOrChangeListener(genericPath, true); - - return true; } - protected virtual string GetLayout(UI stage, string name, string resolution, bool skipCache, out bool cacheHit) + if (!string.IsNullOrWhiteSpace(resolution)) { - cacheHit = false; - var key = new KeyValuePair(stage, $"{name}.{resolution}.json"); - if (!skipCache && mUiDict.TryGetValue(key, out var rawLayout)) - { - cacheHit = true; - return rawLayout; - } + var resolutionPath = Path.Combine(resourcePartialDirectory, $"{name}.{resolution}.json"); + addCreateOrChangeListener(resolutionPath, false); + } - var stageName = stage.ToString().ToLowerInvariant(); - if (stage == UI.InGame) - { - stageName = "game"; - } + var genericPath = Path.Combine(resourcePartialDirectory, $"{name}.json"); + addCreateOrChangeListener(genericPath, true); - var resourceDirectory = Path.Combine(ClientConfiguration.ResourcesDirectory, "gui", "layouts", stageName); + return true; + } - if (!Directory.Exists(resourceDirectory)) - { - Directory.CreateDirectory(resourceDirectory); - } + protected virtual string GetLayout(UI stage, string name, string resolution, bool skipCache, out bool cacheHit) + { + cacheHit = false; + var key = new KeyValuePair(stage, $"{name}.{resolution}.json"); + if (!skipCache && mUiDict.TryGetValue(key, out var rawLayout)) + { + cacheHit = true; + return rawLayout; + } - var resolutionPath = Path.Combine(resourceDirectory, $"{name}.{resolution}.json"); - if (!string.IsNullOrWhiteSpace(resolution) && File.Exists(resolutionPath)) { - rawLayout = File.ReadAllText(resolutionPath); - mUiDict[key] = rawLayout; - return rawLayout; - } + var stageName = stage.ToString().ToLowerInvariant(); + if (stage == UI.InGame) + { + stageName = "game"; + } - var genericPath = Path.Combine(resourceDirectory, $"{name}.json"); - if (File.Exists(genericPath)) - { - rawLayout = ExceptionRepeater.Run(() => File.ReadAllText(genericPath), 5); - mUiDict[key] = rawLayout; - return rawLayout; - } + var resourceDirectory = Path.Combine(ClientConfiguration.ResourcesDirectory, "gui", "layouts", stageName); - return string.Empty; + if (!Directory.Exists(resourceDirectory)) + { + Directory.CreateDirectory(resourceDirectory); } - public virtual string GetUIJson(UI stage, string name, string resolution, out bool cacheHit) + var resolutionPath = Path.Combine(resourceDirectory, $"{name}.{resolution}.json"); + if (!string.IsNullOrWhiteSpace(resolution) && File.Exists(resolutionPath)) { + rawLayout = File.ReadAllText(resolutionPath); + mUiDict[key] = rawLayout; + return rawLayout; + } + + var genericPath = Path.Combine(resourceDirectory, $"{name}.json"); + if (File.Exists(genericPath)) { - return GetLayout(stage, name, resolution, false, out cacheHit); + rawLayout = ExceptionRepeater.Run(() => File.ReadAllText(genericPath), 5); + mUiDict[key] = rawLayout; + return rawLayout; } - public virtual void SaveUIJson(UI stage, string name, string json, string resolution) + return string.Empty; + } + + public virtual string GetUIJson(UI stage, string name, string resolution, out bool cacheHit) + { + return GetLayout(stage, name, resolution, false, out cacheHit); + } + + public virtual void SaveUIJson(UI stage, string name, string json, string resolution) + { + var stageName = stage.ToString().ToLowerInvariant(); + if (stage == UI.InGame) { - var stageName = stage.ToString().ToLowerInvariant(); - if (stage == UI.InGame) - { - stageName = "game"; - } + stageName = "game"; + } - var stagePartialPath = Path.Combine("gui", "layouts", stageName); + var stagePartialPath = Path.Combine("gui", "layouts", stageName); - string resourceName; - if (resolution != null) + string resourceName; + if (resolution != null) + { + resourceName = Path.Combine(stagePartialPath, $"{name}.{resolution}.json"); + var resourcePath = Path.Combine(ClientConfiguration.ResourcesDirectory, resourceName); + if (File.Exists(resourcePath)) { - resourceName = Path.Combine(stagePartialPath, $"{name}.{resolution}.json"); - var resourcePath = Path.Combine(ClientConfiguration.ResourcesDirectory, resourceName); - if (File.Exists(resourcePath)) + ContentWatcher?.Modify(resourceName, () => { - ContentWatcher?.Modify(resourceName, () => + try { - try - { - File.WriteAllText(resourcePath, json); - } - catch (Exception exception) - { - Log.Debug(exception); - } - }); - return; - } + File.WriteAllText(resourcePath, json); + } + catch (Exception exception) + { + Log.Debug(exception); + } + }); + return; } - - resourceName = Path.Combine(stagePartialPath, $"{name}.json"); - ContentWatcher?.Modify(resourceName, () => - { - var resourcePath = Path.Combine(ClientConfiguration.ResourcesDirectory, resourceName); - try - { - File.WriteAllText(resourcePath, json); - } - catch (Exception exception) - { - Log.Debug(exception); - } - }); } - protected Dictionary GetAssetLookup(ContentTypes contentType) + resourceName = Path.Combine(stagePartialPath, $"{name}.json"); + ContentWatcher?.Modify(resourceName, () => { - switch (contentType) + var resourcePath = Path.Combine(ClientConfiguration.ResourcesDirectory, resourceName); + try { - case ContentTypes.Animation: - return mAnimationDict; - - case ContentTypes.Entity: - return mEntityDict; + File.WriteAllText(resourcePath, json); + } + catch (Exception exception) + { + Log.Debug(exception); + } + }); + } - case ContentTypes.Face: - return mFaceDict; + protected Dictionary GetAssetLookup(ContentTypes contentType) + { + switch (contentType) + { + case ContentTypes.Animation: + return mAnimationDict; - case ContentTypes.Fog: - return mFogDict; + case ContentTypes.Entity: + return mEntityDict; - case ContentTypes.Image: - return mImageDict; + case ContentTypes.Face: + return mFaceDict; - case ContentTypes.Interface: - return mGuiDict; + case ContentTypes.Fog: + return mFogDict; - case ContentTypes.Item: - return mItemDict; + case ContentTypes.Image: + return mImageDict; - case ContentTypes.Miscellaneous: - return mMiscDict; + case ContentTypes.Interface: + return mGuiDict; - case ContentTypes.Paperdoll: - return mPaperdollDict; + case ContentTypes.Item: + return mItemDict; - case ContentTypes.Resource: - return mResourceDict; + case ContentTypes.Miscellaneous: + return mMiscDict; - case ContentTypes.Spell: - return mSpellDict; + case ContentTypes.Paperdoll: + return mPaperdollDict; - case ContentTypes.TexturePack: - return mTexturePackDict; + case ContentTypes.Resource: + return mResourceDict; - case ContentTypes.TileSet: - return mTilesetDict; + case ContentTypes.Spell: + return mSpellDict; - case ContentTypes.Font: - throw new NotImplementedException(); + case ContentTypes.TexturePack: + return mTexturePackDict; - case ContentTypes.Shader: - throw new NotImplementedException(); + case ContentTypes.TileSet: + return mTilesetDict; - case ContentTypes.Music: - return mMusicDict; + case ContentTypes.Font: + throw new NotImplementedException(); - case ContentTypes.Sound: - return mSoundDict; + case ContentTypes.Shader: + throw new NotImplementedException(); - default: - throw new ArgumentOutOfRangeException(nameof(contentType), contentType, null); - } - } + case ContentTypes.Music: + return mMusicDict; - protected abstract TAsset Load( - Dictionary lookup, - ContentTypes contentType, - string assetName, - Func createStream - ) where TAsset : class, IAsset; + case ContentTypes.Sound: + return mSoundDict; - /// - public TAsset Find(ContentTypes contentType, string assetName) where TAsset : class, IAsset - { - var assetLookup = GetAssetLookup(contentType); + default: + throw new ArgumentOutOfRangeException(nameof(contentType), contentType, null); + } + } - if (assetLookup.TryGetValue(assetName, out var asset)) - { - return asset as TAsset; - } + protected abstract TAsset Load( + Dictionary lookup, + ContentTypes contentType, + string assetName, + Func createStream + ) where TAsset : class, IAsset; - return null; - } + /// + public TAsset Find(ContentTypes contentType, string assetName) where TAsset : class, IAsset + { + var assetLookup = GetAssetLookup(contentType); - /// - public TAsset Load(ContentTypes contentType, string assetPath, string assetAlias) where TAsset : class, IAsset + if (assetLookup.TryGetValue(assetName, out var asset)) { - if (!File.Exists(assetPath)) - { - throw new FileNotFoundException($@"Asset does not exist at '{assetPath}'."); - } - - return Load(contentType, assetAlias.ToLower(), () => File.OpenRead(assetPath)); + return asset as TAsset; } - /// - public TAsset Load(ContentTypes contentType, string assetName, Func createStream) - where TAsset : class, IAsset + return null; + } + + /// + public TAsset Load(ContentTypes contentType, string assetPath, string assetAlias) where TAsset : class, IAsset + { + if (!File.Exists(assetPath)) { - var assetLookup = GetAssetLookup(contentType); + throw new FileNotFoundException($@"Asset does not exist at '{assetPath}'."); + } - if (assetLookup.TryGetValue(assetName, out var asset)) - { - return asset as TAsset; - } + return Load(contentType, assetAlias.ToLower(), () => File.OpenRead(assetPath)); + } - return Load(assetLookup, contentType, assetName, createStream); - } + /// + public TAsset Load(ContentTypes contentType, string assetName, Func createStream) + where TAsset : class, IAsset + { + var assetLookup = GetAssetLookup(contentType); - /// - public TAsset LoadEmbedded(IPluginContext context, ContentTypes contentType, string assetName) - where TAsset : class, IAsset + if (assetLookup.TryGetValue(assetName, out var asset)) { - var manifestResourceName = context.EmbeddedResources.Resolve(assetName); - return Load(contentType, assetName, () => context.EmbeddedResources.Read(manifestResourceName)); + return asset as TAsset; } - /// - public TAsset LoadEmbedded(IPluginContext context, ContentTypes contentType, string assetName, string assetAlias) - where TAsset : class, IAsset - { - var manifestResourceName = context.EmbeddedResources.Resolve(assetName); - return Load(contentType, assetName, assetAlias); - } + return Load(assetLookup, contentType, assetName, createStream); + } + /// + public TAsset LoadEmbedded(IPluginContext context, ContentTypes contentType, string assetName) + where TAsset : class, IAsset + { + var manifestResourceName = context.EmbeddedResources.Resolve(assetName); + return Load(contentType, assetName, () => context.EmbeddedResources.Read(manifestResourceName)); + } + + /// + public TAsset LoadEmbedded(IPluginContext context, ContentTypes contentType, string assetName, string assetAlias) + where TAsset : class, IAsset + { + var manifestResourceName = context.EmbeddedResources.Resolve(assetName); + return Load(contentType, assetName, assetAlias); } } diff --git a/Intersect.Client.Framework/General/GameStates.cs b/Intersect.Client.Framework/General/GameStates.cs index 142ba7d80a..a8e9815b9b 100644 --- a/Intersect.Client.Framework/General/GameStates.cs +++ b/Intersect.Client.Framework/General/GameStates.cs @@ -1,19 +1,17 @@ -namespace Intersect.Client.General -{ +namespace Intersect.Client.General; - public enum GameStates - { - Intro = 0, +public enum GameStates +{ - Menu, + Intro = 0, - Loading, + Menu, - InGame, + Loading, - Error + InGame, - } + Error } diff --git a/Intersect.Client.Framework/GenericClasses/Cursor.cs b/Intersect.Client.Framework/GenericClasses/Cursor.cs index 844741a3cd..5c4c4fab4c 100644 --- a/Intersect.Client.Framework/GenericClasses/Cursor.cs +++ b/Intersect.Client.Framework/GenericClasses/Cursor.cs @@ -1,60 +1,58 @@ -namespace Intersect.Client.Framework.GenericClasses -{ - - public partial class Cursor - { - - private int mType = 0; +namespace Intersect.Client.Framework.GenericClasses; - public Cursor() - { - } - public Cursor(Cursors.CursorTypes t) - { - mType = (int) t; - } +public partial class Cursor +{ - public static Cursor Current { get; set; } + private int mType = 0; + public Cursor() + { } - public static partial class Cursors + public Cursor(Cursors.CursorTypes t) { + mType = (int) t; + } - public enum CursorTypes - { + public static Cursor Current { get; set; } - Default = 0, //default +} - SizeAll, +public static partial class Cursors +{ - SizeNs, + public enum CursorTypes + { - SizeWe, + Default = 0, //default - SizeNwse, + SizeAll, - SizeNesw, + SizeNs, - No + SizeWe, - } + SizeNwse, - public static Cursor Default => new Cursor(CursorTypes.Default); + SizeNesw, - public static Cursor SizeNs => new Cursor(CursorTypes.SizeNs); + No - public static Cursor SizeWe => new Cursor(CursorTypes.SizeWe); + } - public static Cursor SizeAll => new Cursor(CursorTypes.SizeAll); + public static Cursor Default => new Cursor(CursorTypes.Default); - public static Cursor SizeNwse => new Cursor(CursorTypes.SizeNwse); + public static Cursor SizeNs => new Cursor(CursorTypes.SizeNs); - public static Cursor SizeNesw => new Cursor(CursorTypes.SizeNesw); + public static Cursor SizeWe => new Cursor(CursorTypes.SizeWe); - public static Cursor No => new Cursor(CursorTypes.No); + public static Cursor SizeAll => new Cursor(CursorTypes.SizeAll); - } + public static Cursor SizeNwse => new Cursor(CursorTypes.SizeNwse); + + public static Cursor SizeNesw => new Cursor(CursorTypes.SizeNesw); + + public static Cursor No => new Cursor(CursorTypes.No); } diff --git a/Intersect.Client.Framework/GenericClasses/FloatRect.cs b/Intersect.Client.Framework/GenericClasses/FloatRect.cs index 3dcc157b1a..1d86929c06 100644 --- a/Intersect.Client.Framework/GenericClasses/FloatRect.cs +++ b/Intersect.Client.Framework/GenericClasses/FloatRect.cs @@ -1,171 +1,170 @@ using System.Runtime.CompilerServices; -namespace Intersect.Client.Framework.GenericClasses -{ +namespace Intersect.Client.Framework.GenericClasses; - public partial struct FloatRect - { - private float mX; +public partial struct FloatRect +{ - private float mY; + private float mX; - private float mWidth; + private float mY; - private float mHeight; + private float mWidth; - public float X - { - get => mX; - set => mX = value; - } + private float mHeight; - public float Y - { - get => mY; - set => mY = value; - } + public float X + { + get => mX; + set => mX = value; + } - public float Width - { - get => mWidth; - set => mWidth = value; - } + public float Y + { + get => mY; + set => mY = value; + } - public float Height - { - get => mHeight; - set => mHeight = value; - } + public float Width + { + get => mWidth; + set => mWidth = value; + } + + public float Height + { + get => mHeight; + set => mHeight = value; + } - public Pointf Position + public Pointf Position + { + get => new Pointf(X, Y); + set { - get => new Pointf(X, Y); - set - { - X = value.X; - Y = value.Y; - } + X = value.X; + Y = value.Y; } + } - public Pointf Size + public Pointf Size + { + get => new Pointf(Width, Height); + set { - get => new Pointf(Width, Height); - set - { - Width = value.X; - Height = value.Y; - } + Width = value.X; + Height = value.Y; } + } - public float Left => X; - - public float Top => Y; + public float Left => X; - public float Bottom => Y + Height; + public float Top => Y; - public float Right => X + Width; + public float Bottom => Y + Height; - public static FloatRect Empty => new FloatRect(); + public float Right => X + Width; - public FloatRect(float x, float y, float w, float h) - { - mX = x; - mY = y; - mWidth = w; - mHeight = h; - } + public static FloatRect Empty => new FloatRect(); - public FloatRect(Pointf position, Pointf size) : this(position.X, position.Y, size.X, size.Y) { } + public FloatRect(float x, float y, float w, float h) + { + mX = x; + mY = y; + mWidth = w; + mHeight = h; + } - public static FloatRect Intersect(FloatRect a, FloatRect b) - { - // MS.NET returns a non-empty rectangle if the two rectangles - // touch each other - if (!a.IntersectsWithInclusive(b)) - { - return Empty; - } - - return FloatRect.FromLtrb( - Math.Max(a.Left, b.Left), Math.Max(a.Top, b.Top), Math.Min(a.Right, b.Right), - Math.Min(a.Bottom, b.Bottom) - ); - } + public FloatRect(Pointf position, Pointf size) : this(position.X, position.Y, size.X, size.Y) { } - public static FloatRect FromLtrb(float left, float top, float right, float bottom) + public static FloatRect Intersect(FloatRect a, FloatRect b) + { + // MS.NET returns a non-empty rectangle if the two rectangles + // touch each other + if (!a.IntersectsWithInclusive(b)) { - return new FloatRect(left, top, right - left, bottom - top); + return Empty; } - public bool IntersectsWith(FloatRect rect) - { - return !(Left >= rect.Right || Right <= rect.Left || Top >= rect.Bottom || Bottom <= rect.Top); - } + return FloatRect.FromLtrb( + Math.Max(a.Left, b.Left), Math.Max(a.Top, b.Top), Math.Min(a.Right, b.Right), + Math.Min(a.Bottom, b.Bottom) + ); + } - private bool IntersectsWithInclusive(FloatRect r) - { - return !(Left > r.Right || Right < r.Left || Top > r.Bottom || Bottom < r.Top); - } + public static FloatRect FromLtrb(float left, float top, float right, float bottom) + { + return new FloatRect(left, top, right - left, bottom - top); + } - public void Reset() - { - X = 0; - Y = 0; - Width = 0; - Height = 0; - } + public bool IntersectsWith(FloatRect rect) + { + return !(Left >= rect.Right || Right <= rect.Left || Top >= rect.Bottom || Bottom <= rect.Top); + } - /// - /// Contains Method - /// - /// - /// Checks if an x,y coordinate lies within this Rectangle. - /// - public bool Contains(float x, float y) - { - return x >= Left && x < Right && y >= Top && y < Bottom; - } + private bool IntersectsWithInclusive(FloatRect r) + { + return !(Left > r.Right || Right < r.Left || Top > r.Bottom || Bottom < r.Top); + } - /// - /// Contains Method - /// - /// - /// Checks if a Pofloat lies within this Rectangle. - /// - public bool Contains(Point pt) - { - return Contains(pt.X, pt.Y); - } + public void Reset() + { + X = 0; + Y = 0; + Width = 0; + Height = 0; + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static FloatRect operator *(FloatRect lhs, float rhs) - { - return new FloatRect( - lhs.X * rhs, - lhs.Y * rhs, - lhs.Width * rhs, - lhs.Height * rhs - ); - } + /// + /// Contains Method + /// + /// + /// Checks if an x,y coordinate lies within this Rectangle. + /// + public bool Contains(float x, float y) + { + return x >= Left && x < Right && y >= Top && y < Bottom; + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static FloatRect operator *(float lhs, FloatRect rhs) => rhs * lhs; + /// + /// Contains Method + /// + /// + /// Checks if a Pofloat lies within this Rectangle. + /// + public bool Contains(Point pt) + { + return Contains(pt.X, pt.Y); + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static FloatRect operator /(FloatRect lhs, float rhs) - { - return new FloatRect( - lhs.X / rhs, - lhs.Y / rhs, - lhs.Width / rhs, - lhs.Height / rhs - ); - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static FloatRect operator *(FloatRect lhs, float rhs) + { + return new FloatRect( + lhs.X * rhs, + lhs.Y * rhs, + lhs.Width * rhs, + lhs.Height * rhs + ); + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static FloatRect operator /(float lhs, FloatRect rhs) => rhs / lhs; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static FloatRect operator *(float lhs, FloatRect rhs) => rhs * lhs; - public override string ToString() => $"{Left},{Top} + {Width},{Height} -> {Right},{Bottom}"; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static FloatRect operator /(FloatRect lhs, float rhs) + { + return new FloatRect( + lhs.X / rhs, + lhs.Y / rhs, + lhs.Width / rhs, + lhs.Height / rhs + ); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static FloatRect operator /(float lhs, FloatRect rhs) => rhs / lhs; + + public override string ToString() => $"{Left},{Top} + {Width},{Height} -> {Right},{Bottom}"; } diff --git a/Intersect.Client.Framework/GenericClasses/Keys.cs b/Intersect.Client.Framework/GenericClasses/Keys.cs index 12c90a8d72..a8e67f50a3 100644 --- a/Intersect.Client.Framework/GenericClasses/Keys.cs +++ b/Intersect.Client.Framework/GenericClasses/Keys.cs @@ -1,397 +1,395 @@ -namespace Intersect.Client.Framework.GenericClasses -{ +namespace Intersect.Client.Framework.GenericClasses; - public enum Keys - { - None = 0x00000000, +public enum Keys +{ - LButton = 0x00000001, + None = 0x00000000, - RButton = 0x00000002, + LButton = 0x00000001, - Cancel = 0x00000003, + RButton = 0x00000002, - MButton = 0x00000004, + Cancel = 0x00000003, - XButton1 = 0x00000005, + MButton = 0x00000004, - XButton2 = 0x00000006, + XButton1 = 0x00000005, - Back = 0x00000008, + XButton2 = 0x00000006, - Tab = 0x00000009, + Back = 0x00000008, - LineFeed = 0x0000000A, + Tab = 0x00000009, - Clear = 0x0000000C, + LineFeed = 0x0000000A, - Return = 0x0000000D, + Clear = 0x0000000C, - Enter = 0x0000000D, + Return = 0x0000000D, - ShiftKey = 0x00000010, + Enter = 0x0000000D, - ControlKey = 0x00000011, + ShiftKey = 0x00000010, - Menu = 0x00000012, + ControlKey = 0x00000011, - Pause = 0x00000013, + Menu = 0x00000012, - CapsLock = 0x00000014, + Pause = 0x00000013, - Capital = 0x00000014, + CapsLock = 0x00000014, - KanaMode = 0x00000015, + Capital = 0x00000014, - HanguelMode = 0x00000015, + KanaMode = 0x00000015, - HangulMode = 0x00000015, + HanguelMode = 0x00000015, - JunjaMode = 0x00000017, + HangulMode = 0x00000015, - FinalMode = 0x00000018, + JunjaMode = 0x00000017, - KanjiMode = 0x00000019, + FinalMode = 0x00000018, - HanjaMode = 0x00000019, + KanjiMode = 0x00000019, - Escape = 0x0000001B, + HanjaMode = 0x00000019, - ImeConvert = 0x0000001C, + Escape = 0x0000001B, - ImeNonconvert = 0x0000001D, + ImeConvert = 0x0000001C, - ImeAceept = 0x0000001E, + ImeNonconvert = 0x0000001D, - ImeModeChange = 0x0000001F, + ImeAceept = 0x0000001E, - Space = 0x00000020, + ImeModeChange = 0x0000001F, - PageUp = 0x00000021, + Space = 0x00000020, - Prior = 0x00000021, + PageUp = 0x00000021, - PageDown = 0x00000022, + Prior = 0x00000021, - Next = 0x00000022, + PageDown = 0x00000022, - End = 0x00000023, + Next = 0x00000022, - Home = 0x00000024, + End = 0x00000023, - Left = 0x00000025, + Home = 0x00000024, - Up = 0x00000026, + Left = 0x00000025, - Right = 0x00000027, + Up = 0x00000026, - Down = 0x00000028, + Right = 0x00000027, - Select = 0x00000029, + Down = 0x00000028, - Print = 0x0000002A, + Select = 0x00000029, - Execute = 0x0000002B, + Print = 0x0000002A, - PrintScreen = 0x0000002C, + Execute = 0x0000002B, - Snapshot = 0x0000002C, + PrintScreen = 0x0000002C, - Insert = 0x0000002D, + Snapshot = 0x0000002C, - Delete = 0x0000002E, + Insert = 0x0000002D, - Help = 0x0000002F, + Delete = 0x0000002E, - D0 = 0x00000030, + Help = 0x0000002F, - D1 = 0x00000031, + D0 = 0x00000030, - D2 = 0x00000032, + D1 = 0x00000031, - D3 = 0x00000033, + D2 = 0x00000032, - D4 = 0x00000034, + D3 = 0x00000033, - D5 = 0x00000035, + D4 = 0x00000034, - D6 = 0x00000036, + D5 = 0x00000035, - D7 = 0x00000037, + D6 = 0x00000036, - D8 = 0x00000038, + D7 = 0x00000037, - D9 = 0x00000039, + D8 = 0x00000038, - A = 0x00000041, + D9 = 0x00000039, - B = 0x00000042, + A = 0x00000041, - C = 0x00000043, + B = 0x00000042, - D = 0x00000044, + C = 0x00000043, - E = 0x00000045, + D = 0x00000044, - F = 0x00000046, + E = 0x00000045, - G = 0x00000047, + F = 0x00000046, - H = 0x00000048, + G = 0x00000047, - I = 0x00000049, + H = 0x00000048, - J = 0x0000004A, + I = 0x00000049, - K = 0x0000004B, + J = 0x0000004A, - L = 0x0000004C, + K = 0x0000004B, - M = 0x0000004D, + L = 0x0000004C, - N = 0x0000004E, + M = 0x0000004D, - O = 0x0000004F, + N = 0x0000004E, - P = 0x00000050, + O = 0x0000004F, - Q = 0x00000051, + P = 0x00000050, - R = 0x00000052, + Q = 0x00000051, - S = 0x00000053, + R = 0x00000052, - T = 0x00000054, + S = 0x00000053, - U = 0x00000055, + T = 0x00000054, - V = 0x00000056, + U = 0x00000055, - W = 0x00000057, + V = 0x00000056, - X = 0x00000058, + W = 0x00000057, - Y = 0x00000059, + X = 0x00000058, - Z = 0x0000005A, + Y = 0x00000059, - LWin = 0x0000005B, + Z = 0x0000005A, - RWin = 0x0000005C, + LWin = 0x0000005B, - Apps = 0x0000005D, + RWin = 0x0000005C, - NumPad0 = 0x00000060, + Apps = 0x0000005D, - NumPad1 = 0x00000061, + NumPad0 = 0x00000060, - NumPad2 = 0x00000062, + NumPad1 = 0x00000061, - NumPad3 = 0x00000063, + NumPad2 = 0x00000062, - NumPad4 = 0x00000064, + NumPad3 = 0x00000063, - NumPad5 = 0x00000065, + NumPad4 = 0x00000064, - NumPad6 = 0x00000066, + NumPad5 = 0x00000065, - NumPad7 = 0x00000067, + NumPad6 = 0x00000066, - NumPad8 = 0x00000068, + NumPad7 = 0x00000067, - NumPad9 = 0x00000069, + NumPad8 = 0x00000068, - Multiply = 0x0000006A, + NumPad9 = 0x00000069, - Add = 0x0000006B, + Multiply = 0x0000006A, - Separator = 0x0000006C, + Add = 0x0000006B, - Subtract = 0x0000006D, + Separator = 0x0000006C, - Decimal = 0x0000006E, + Subtract = 0x0000006D, - Divide = 0x0000006F, + Decimal = 0x0000006E, - F1 = 0x00000070, + Divide = 0x0000006F, - F2 = 0x00000071, + F1 = 0x00000070, - F3 = 0x00000072, + F2 = 0x00000071, - F4 = 0x00000073, + F3 = 0x00000072, - F5 = 0x00000074, + F4 = 0x00000073, - F6 = 0x00000075, + F5 = 0x00000074, - F7 = 0x00000076, + F6 = 0x00000075, - F8 = 0x00000077, + F7 = 0x00000076, - F9 = 0x00000078, + F8 = 0x00000077, - F10 = 0x00000079, + F9 = 0x00000078, - F11 = 0x0000007A, + F10 = 0x00000079, - F12 = 0x0000007B, + F11 = 0x0000007A, - F13 = 0x0000007C, + F12 = 0x0000007B, - F14 = 0x0000007D, + F13 = 0x0000007C, - F15 = 0x0000007E, + F14 = 0x0000007D, - F16 = 0x0000007F, + F15 = 0x0000007E, - F17 = 0x00000080, + F16 = 0x0000007F, - F18 = 0x00000081, + F17 = 0x00000080, - F19 = 0x00000082, + F18 = 0x00000081, - F20 = 0x00000083, + F19 = 0x00000082, - F21 = 0x00000084, + F20 = 0x00000083, - F22 = 0x00000085, + F21 = 0x00000084, - F23 = 0x00000086, + F22 = 0x00000085, - F24 = 0x00000087, + F23 = 0x00000086, - NumLock = 0x00000090, + F24 = 0x00000087, - Scroll = 0x00000091, + NumLock = 0x00000090, - LShiftKey = 0x000000A0, + Scroll = 0x00000091, - RShiftKey = 0x000000A1, + LShiftKey = 0x000000A0, - LControlKey = 0x000000A2, + RShiftKey = 0x000000A1, - RControlKey = 0x000000A3, + LControlKey = 0x000000A2, - LMenu = 0x000000A4, + RControlKey = 0x000000A3, - RMenu = 0x000000A5, + LMenu = 0x000000A4, - BrowserBack = 0x000000A6, + RMenu = 0x000000A5, - BrowserForward = 0x000000A7, + BrowserBack = 0x000000A6, - BrowserRefresh = 0x000000A8, + BrowserForward = 0x000000A7, - BrowserStop = 0x000000A9, + BrowserRefresh = 0x000000A8, - BrowserSearch = 0x000000AA, + BrowserStop = 0x000000A9, - BrowserFavorites = 0x000000AB, + BrowserSearch = 0x000000AA, - BrowserHome = 0x000000AC, + BrowserFavorites = 0x000000AB, - VolumeMute = 0x000000AD, + BrowserHome = 0x000000AC, - VolumeDown = 0x000000AE, + VolumeMute = 0x000000AD, - VolumeUp = 0x000000AF, + VolumeDown = 0x000000AE, - MediaNextTrack = 0x000000B0, + VolumeUp = 0x000000AF, - MediaPreviousTrack = 0x000000B1, + MediaNextTrack = 0x000000B0, - MediaStop = 0x000000B2, + MediaPreviousTrack = 0x000000B1, - MediaPlayPause = 0x000000B3, + MediaStop = 0x000000B2, - LaunchMail = 0x000000B4, + MediaPlayPause = 0x000000B3, - SelectMedia = 0x000000B5, + LaunchMail = 0x000000B4, - LaunchApplication1 = 0x000000B6, + SelectMedia = 0x000000B5, - LaunchApplication2 = 0x000000B7, + LaunchApplication1 = 0x000000B6, - OemSemicolon = 0x000000BA, + LaunchApplication2 = 0x000000B7, - Oemplus = 0x000000BB, + OemSemicolon = 0x000000BA, - Oemcomma = 0x000000BC, + Oemplus = 0x000000BB, - OemMinus = 0x000000BD, + Oemcomma = 0x000000BC, - OemPeriod = 0x000000BE, + OemMinus = 0x000000BD, - OemQuestion = 0x000000BF, + OemPeriod = 0x000000BE, - Oemtilde = 0x000000C0, + OemQuestion = 0x000000BF, - OemOpenBrackets = 0x000000DB, + Oemtilde = 0x000000C0, - OemPipe = 0x000000DC, + OemOpenBrackets = 0x000000DB, - OemCloseBrackets = 0x000000DD, + OemPipe = 0x000000DC, - OemQuotes = 0x000000DE, + OemCloseBrackets = 0x000000DD, - Oem8 = 0x000000DF, + OemQuotes = 0x000000DE, - OemBackslash = 0x000000E2, + Oem8 = 0x000000DF, - ProcessKey = 0x000000E5, + OemBackslash = 0x000000E2, - Attn = 0x000000F6, + ProcessKey = 0x000000E5, - Crsel = 0x000000F7, + Attn = 0x000000F6, - Exsel = 0x000000F8, + Crsel = 0x000000F7, - EraseEof = 0x000000F9, + Exsel = 0x000000F8, - Play = 0x000000FA, + EraseEof = 0x000000F9, - Zoom = 0x000000FB, + Play = 0x000000FA, - NoName = 0x000000FC, + Zoom = 0x000000FB, - Pa1 = 0x000000FD, + NoName = 0x000000FC, - OemClear = 0x000000FE, + Pa1 = 0x000000FD, - KeyCode = 0x0000FFFF, + OemClear = 0x000000FE, - Shift = 0x00010000, + KeyCode = 0x0000FFFF, - Control = 0x00020000, + Shift = 0x00010000, - Alt = 0x00040000, + Control = 0x00020000, - Modifiers = unchecked((int) 0xFFFF0000), + Alt = 0x00040000, - ImeAccept = 0x0000001E, + Modifiers = unchecked((int) 0xFFFF0000), - Oem1 = 0x000000BA, + ImeAccept = 0x0000001E, - Oem102 = 0x000000E2, + Oem1 = 0x000000BA, - Oem2 = 0x000000BF, + Oem102 = 0x000000E2, - Oem3 = 0x000000C0, + Oem2 = 0x000000BF, - Oem4 = 0x000000DB, + Oem3 = 0x000000C0, - Oem5 = 0x000000DC, + Oem4 = 0x000000DB, - Oem6 = 0x000000DD, + Oem5 = 0x000000DC, - Oem7 = 0x000000DE, + Oem6 = 0x000000DD, - Packet = 0x000000E7, + Oem7 = 0x000000DE, - Sleep = 0x0000005F + Packet = 0x000000E7, - } + Sleep = 0x0000005F } diff --git a/Intersect.Client.Framework/GenericClasses/OpenFileDialog.cs b/Intersect.Client.Framework/GenericClasses/OpenFileDialog.cs index cfcfa0bc2e..c446a73c8f 100644 --- a/Intersect.Client.Framework/GenericClasses/OpenFileDialog.cs +++ b/Intersect.Client.Framework/GenericClasses/OpenFileDialog.cs @@ -1,34 +1,32 @@ -namespace Intersect.Client.Framework.GenericClasses -{ +namespace Intersect.Client.Framework.GenericClasses; - public enum DialogResult - { - Ok = 0, +public enum DialogResult +{ - } + Ok = 0, - public partial class OpenFileDialog - { - public string Title { get; set; } +} - public string InitialDirectory { get; set; } +public partial class OpenFileDialog +{ + public string Title { get; set; } - public string DefaultExt { get; set; } + public string InitialDirectory { get; set; } - public string Filter { get; set; } + public string DefaultExt { get; set; } - public bool CheckPathExists { get; set; } + public string Filter { get; set; } - public bool Multiselect { get; set; } + public bool CheckPathExists { get; set; } - public string FileName { get; set; } + public bool Multiselect { get; set; } - public DialogResult ShowDialog() - { - return DialogResult.Ok; - } + public string FileName { get; set; } + public DialogResult ShowDialog() + { + return DialogResult.Ok; } } diff --git a/Intersect.Client.Framework/GenericClasses/Pointf.cs b/Intersect.Client.Framework/GenericClasses/Pointf.cs index 83d094b649..666ab5e46c 100644 --- a/Intersect.Client.Framework/GenericClasses/Pointf.cs +++ b/Intersect.Client.Framework/GenericClasses/Pointf.cs @@ -1,64 +1,62 @@ -namespace Intersect.Client.Framework.GenericClasses -{ - - public partial struct Pointf - { - public static Pointf Empty => new Pointf(); +namespace Intersect.Client.Framework.GenericClasses; - public static Pointf UnitX => new Pointf(1, 0); - public static Pointf UnitY => new Pointf(0, 1); +public partial struct Pointf +{ + public static Pointf Empty => new Pointf(); - private const float TOLERANCE = 0.001f; + public static Pointf UnitX => new Pointf(1, 0); - public float X { get; set; } + public static Pointf UnitY => new Pointf(0, 1); - public float Y { get; set; } + private const float TOLERANCE = 0.001f; - public Pointf(float x, float y) - { - X = x; - Y = y; - } + public float X { get; set; } - public override bool Equals(object obj) - { - if (obj is Pointf point) - { - return point == this; - } + public float Y { get; set; } - return false; - } + public Pointf(float x, float y) + { + X = x; + Y = y; + } - public bool Equals(Pointf other) + public override bool Equals(object obj) + { + if (obj is Pointf point) { - return Math.Abs(X - other.X) < TOLERANCE && Math.Abs(Y - other.Y) < TOLERANCE; + return point == this; } - public override int GetHashCode() => X.GetHashCode() ^ Y.GetHashCode(); + return false; + } + + public bool Equals(Pointf other) + { + return Math.Abs(X - other.X) < TOLERANCE && Math.Abs(Y - other.Y) < TOLERANCE; + } - public Pointf StripX() => new Pointf(0, Y); + public override int GetHashCode() => X.GetHashCode() ^ Y.GetHashCode(); - public Pointf StripY() => new Pointf(X, 0); + public Pointf StripX() => new Pointf(0, Y); - public static bool operator !=(Pointf left, Pointf right) - { - return Math.Abs(left.X - right.X) > TOLERANCE || Math.Abs(left.Y - right.Y) > TOLERANCE; - } + public Pointf StripY() => new Pointf(X, 0); - public static bool operator ==(Pointf left, Pointf right) - { - return Math.Abs(left.X - right.X) < TOLERANCE && Math.Abs(left.Y - right.Y) < TOLERANCE; - } + public static bool operator !=(Pointf left, Pointf right) + { + return Math.Abs(left.X - right.X) > TOLERANCE || Math.Abs(left.Y - right.Y) > TOLERANCE; + } - public static Pointf operator +(Pointf left, Pointf right) => new Pointf(left.X + right.X, left.Y + right.Y); + public static bool operator ==(Pointf left, Pointf right) + { + return Math.Abs(left.X - right.X) < TOLERANCE && Math.Abs(left.Y - right.Y) < TOLERANCE; + } - public static Pointf operator -(Pointf left, Pointf right) => new Pointf(left.X - right.X, left.Y - right.Y); + public static Pointf operator +(Pointf left, Pointf right) => new Pointf(left.X + right.X, left.Y + right.Y); - public static Pointf operator *(Pointf point, float scalar) => new Pointf(point.X * scalar, point.Y * scalar); + public static Pointf operator -(Pointf left, Pointf right) => new Pointf(left.X - right.X, left.Y - right.Y); - public static Pointf operator /(Pointf point, float scalar) => new Pointf(point.X / scalar, point.Y / scalar); - } + public static Pointf operator *(Pointf point, float scalar) => new Pointf(point.X * scalar, point.Y * scalar); + public static Pointf operator /(Pointf point, float scalar) => new Pointf(point.X / scalar, point.Y / scalar); } diff --git a/Intersect.Client.Framework/GenericClasses/Rectangle.cs b/Intersect.Client.Framework/GenericClasses/Rectangle.cs index e29f8f26c9..6899777252 100644 --- a/Intersect.Client.Framework/GenericClasses/Rectangle.cs +++ b/Intersect.Client.Framework/GenericClasses/Rectangle.cs @@ -1,148 +1,146 @@ -namespace Intersect.Client.Framework.GenericClasses +namespace Intersect.Client.Framework.GenericClasses; + + +public partial struct Rectangle { - public partial struct Rectangle - { + private int mX; - private int mX; + private int mY; - private int mY; + private int mWidth; - private int mWidth; + private int mHeight; - private int mHeight; + public int X + { + get => mX; + set => mX = value; + } - public int X - { - get => mX; - set => mX = value; - } + public int Y + { + get => mY; + set => mY = value; + } - public int Y - { - get => mY; - set => mY = value; - } + public int Width + { + get => mWidth; + set => mWidth = value; + } - public int Width - { - get => mWidth; - set => mWidth = value; - } + public int Height + { + get => mHeight; + set => mHeight = value; + } - public int Height - { - get => mHeight; - set => mHeight = value; - } + public int Left => X; - public int Left => X; + public int Top => Y; - public int Top => Y; + public int Bottom => Y + Height; - public int Bottom => Y + Height; + public int Right => X + Width; - public int Right => X + Width; + public static Rectangle Empty => new Rectangle(); - public static Rectangle Empty => new Rectangle(); + public Rectangle(Point position, int width, int height) + { + mX = position.X; + mY = position.Y; + mWidth = width; + mHeight = height; + } - public Rectangle(Point position, int width, int height) - { - mX = position.X; - mY = position.Y; - mWidth = width; - mHeight = height; - } + public Rectangle(int x, int y, int w, int h) + { + mX = x; + mY = y; + mWidth = w; + mHeight = h; + } - public Rectangle(int x, int y, int w, int h) + public static Rectangle Intersect(Rectangle a, Rectangle b) + { + // MS.NET returns a non-empty rectangle if the two rectangles + // touch each other + if (!a.IntersectsWithInclusive(b)) { - mX = x; - mY = y; - mWidth = w; - mHeight = h; + return Empty; } - public static Rectangle Intersect(Rectangle a, Rectangle b) - { - // MS.NET returns a non-empty rectangle if the two rectangles - // touch each other - if (!a.IntersectsWithInclusive(b)) - { - return Empty; - } - - return Rectangle.FromLtrb( - Math.Max(a.Left, b.Left), Math.Max(a.Top, b.Top), Math.Min(a.Right, b.Right), - Math.Min(a.Bottom, b.Bottom) - ); - } + return Rectangle.FromLtrb( + Math.Max(a.Left, b.Left), Math.Max(a.Top, b.Top), Math.Min(a.Right, b.Right), + Math.Min(a.Bottom, b.Bottom) + ); + } - public static Rectangle FromLtrb(int left, int top, int right, int bottom) - { - return new Rectangle(left, top, right - left, bottom - top); - } + public static Rectangle FromLtrb(int left, int top, int right, int bottom) + { + return new Rectangle(left, top, right - left, bottom - top); + } - public bool IntersectsWith(Rectangle rect) - { - return !(Left >= rect.Right || Right <= rect.Left || Top >= rect.Bottom || Bottom <= rect.Top); - } + public bool IntersectsWith(Rectangle rect) + { + return !(Left >= rect.Right || Right <= rect.Left || Top >= rect.Bottom || Bottom <= rect.Top); + } - private bool IntersectsWithInclusive(Rectangle r) - { - return !(Left > r.Right || Right < r.Left || Top > r.Bottom || Bottom < r.Top); - } + private bool IntersectsWithInclusive(Rectangle r) + { + return !(Left > r.Right || Right < r.Left || Top > r.Bottom || Bottom < r.Top); + } - /// - /// Contains Method - /// - /// - /// Checks if an x,y coordinate lies within this Rectangle. - /// - public bool Contains(int x, int y) - { - return x >= Left && x < Right && y >= Top && y < Bottom; - } + /// + /// Contains Method + /// + /// + /// Checks if an x,y coordinate lies within this Rectangle. + /// + public bool Contains(int x, int y) + { + return x >= Left && x < Right && y >= Top && y < Bottom; + } - public void Reset() - { - X = 0; - Y = 0; - Width = 0; - Height = 0; - } + public void Reset() + { + X = 0; + Y = 0; + Width = 0; + Height = 0; + } - /// - /// Contains Method - /// - /// - /// Checks if a Point lies within this Rectangle. - /// - public bool Contains(Point pt) - { - return Contains(pt.X, pt.Y); - } + /// + /// Contains Method + /// + /// + /// Checks if a Point lies within this Rectangle. + /// + public bool Contains(Point pt) + { + return Contains(pt.X, pt.Y); + } + + public override string ToString() => $"{X},{Y},{Width},{Height}"; - public override string ToString() => $"{X},{Y},{Width},{Height}"; + public static string ToString(Rectangle rect) => rect.ToString(); - public static string ToString(Rectangle rect) => rect.ToString(); + public static Rectangle FromString(string rect) + { + if (string.IsNullOrEmpty(rect)) + { + return Rectangle.Empty; + } - public static Rectangle FromString(string rect) + var strs = rect.Split(",".ToCharArray()); + var parts = new int[strs.Length]; + for (var i = 0; i < strs.Length; i++) { - if (string.IsNullOrEmpty(rect)) - { - return Rectangle.Empty; - } - - var strs = rect.Split(",".ToCharArray()); - var parts = new int[strs.Length]; - for (var i = 0; i < strs.Length; i++) - { - parts[i] = int.Parse(strs[i]); - } - - return new Rectangle(parts[0], parts[1], parts[2], parts[3]); + parts[i] = int.Parse(strs[i]); } + return new Rectangle(parts[0], parts[1], parts[2], parts[3]); } } diff --git a/Intersect.Client.Framework/GenericClasses/SaveFileDialog.cs b/Intersect.Client.Framework/GenericClasses/SaveFileDialog.cs index 0efae054b0..a38cf2be38 100644 --- a/Intersect.Client.Framework/GenericClasses/SaveFileDialog.cs +++ b/Intersect.Client.Framework/GenericClasses/SaveFileDialog.cs @@ -1,29 +1,27 @@ -namespace Intersect.Client.Framework.GenericClasses -{ +namespace Intersect.Client.Framework.GenericClasses; - public partial class SaveFileDialog - { - public string Title { get; set; } - public string InitialDirectory { get; set; } +public partial class SaveFileDialog +{ + public string Title { get; set; } - public string DefaultExt { get; set; } + public string InitialDirectory { get; set; } - public string Filter { get; set; } + public string DefaultExt { get; set; } - public bool CheckPathExists { get; set; } + public string Filter { get; set; } - public bool Multiselect { get; set; } + public bool CheckPathExists { get; set; } - public string FileName { get; set; } + public bool Multiselect { get; set; } - public bool OverwritePrompt { get; set; } + public string FileName { get; set; } - public DialogResult ShowDialog() - { - return DialogResult.Ok; - } + public bool OverwritePrompt { get; set; } + public DialogResult ShowDialog() + { + return DialogResult.Ok; } } diff --git a/Intersect.Client.Framework/Graphics/BoundsComparison.cs b/Intersect.Client.Framework/Graphics/BoundsComparison.cs index 671ea33410..2ef639a3ac 100644 --- a/Intersect.Client.Framework/Graphics/BoundsComparison.cs +++ b/Intersect.Client.Framework/Graphics/BoundsComparison.cs @@ -1,13 +1,12 @@ -namespace Intersect.Client.Framework.Graphics +namespace Intersect.Client.Framework.Graphics; + +public enum BoundsComparison { - public enum BoundsComparison - { - Width, + Width, - Height, + Height, - Dimensions, + Dimensions, - Area, - } + Area, } diff --git a/Intersect.Client.Framework/Graphics/DrawStates.cs b/Intersect.Client.Framework/Graphics/DrawStates.cs index 0138a0aaa8..84c8fc9aa6 100644 --- a/Intersect.Client.Framework/Graphics/DrawStates.cs +++ b/Intersect.Client.Framework/Graphics/DrawStates.cs @@ -1,17 +1,16 @@ -namespace Intersect.Client.Framework.Graphics +namespace Intersect.Client.Framework.Graphics; + +public enum DrawStates { - public enum DrawStates - { - GroundLayers = 0, + GroundLayers = 0, - BelowPlayer, + BelowPlayer, - AbovePlayer, + AbovePlayer, - FringeLayers, + FringeLayers, - BeforeEntity, + BeforeEntity, - AfterEntity, - } + AfterEntity, } diff --git a/Intersect.Client.Framework/Graphics/GameBlendModes.cs b/Intersect.Client.Framework/Graphics/GameBlendModes.cs index 7483d38db3..fa58cff6a2 100644 --- a/Intersect.Client.Framework/Graphics/GameBlendModes.cs +++ b/Intersect.Client.Framework/Graphics/GameBlendModes.cs @@ -1,21 +1,19 @@ -namespace Intersect.Client.Framework.Graphics -{ +namespace Intersect.Client.Framework.Graphics; - public enum GameBlendModes - { - Add = 0, +public enum GameBlendModes +{ - Alpha, + Add = 0, - Multiply, + Alpha, - None, + Multiply, - Opaque, + None, - Cutout + Opaque, - } + Cutout } diff --git a/Intersect.Client.Framework/Graphics/GameFont.cs b/Intersect.Client.Framework/Graphics/GameFont.cs index 01ff64212b..149c1ad839 100644 --- a/Intersect.Client.Framework/Graphics/GameFont.cs +++ b/Intersect.Client.Framework/Graphics/GameFont.cs @@ -1,31 +1,30 @@ -namespace Intersect.Client.Framework.Graphics +namespace Intersect.Client.Framework.Graphics; + +public abstract partial class GameFont { - public abstract partial class GameFont - { - public string Name { get; set; } = string.Empty; + public string Name { get; set; } = string.Empty; - public int Size { get; set; } = 12; + public int Size { get; set; } = 12; - public GameFont(string fontName, int fontSize) - { - Name = fontName; - Size = fontSize; - } + public GameFont(string fontName, int fontSize) + { + Name = fontName; + Size = fontSize; + } - public string GetName() - { - return Name; - } + public string GetName() + { + return Name; + } - public int GetSize() - { - return Size; - } + public int GetSize() + { + return Size; + } - public abstract object GetFont(); + public abstract object GetFont(); - public override string ToString() => $"{Name},{Size}"; + public override string ToString() => $"{Name},{Size}"; - public static string ToString(GameFont font) => font?.ToString(); - } + public static string ToString(GameFont font) => font?.ToString(); } diff --git a/Intersect.Client.Framework/Graphics/GameRenderTexture.cs b/Intersect.Client.Framework/Graphics/GameRenderTexture.cs index 16bc1d496d..4907e12d15 100644 --- a/Intersect.Client.Framework/Graphics/GameRenderTexture.cs +++ b/Intersect.Client.Framework/Graphics/GameRenderTexture.cs @@ -1,40 +1,38 @@ -namespace Intersect.Client.Framework.Graphics -{ +namespace Intersect.Client.Framework.Graphics; - public abstract partial class GameRenderTexture : GameTexture - { - public GameRenderTexture(int width, int height) - { - } +public abstract partial class GameRenderTexture : GameTexture +{ - public static int RenderTextureCount { get; set; } = 0; + public GameRenderTexture(int width, int height) + { + } - /// - /// Called before a frame is drawn, if the renderer must re-created or anything it does it here. - /// - /// - public abstract bool Begin(); + public static int RenderTextureCount { get; set; } = 0; - /// - /// Called when the frame is done being drawn, generally used to finally display the content to the screen. - /// - public abstract void End(); + /// + /// Called before a frame is drawn, if the renderer must re-created or anything it does it here. + /// + /// + public abstract bool Begin(); - public bool SetActive(bool active) - { - return true; - } + /// + /// Called when the frame is done being drawn, generally used to finally display the content to the screen. + /// + public abstract void End(); - /// - /// Clears everything off the render target with a specified color. - /// - public abstract void Clear(Color color); + public bool SetActive(bool active) + { + return true; + } - public abstract override object GetTexture(); + /// + /// Clears everything off the render target with a specified color. + /// + public abstract void Clear(Color color); - public abstract void Dispose(); + public abstract override object GetTexture(); - } + public abstract void Dispose(); } diff --git a/Intersect.Client.Framework/Graphics/GameRenderer.cs b/Intersect.Client.Framework/Graphics/GameRenderer.cs index 7f6327624d..419b473b76 100644 --- a/Intersect.Client.Framework/Graphics/GameRenderer.cs +++ b/Intersect.Client.Framework/Graphics/GameRenderer.cs @@ -1,206 +1,204 @@ using Intersect.Client.Framework.GenericClasses; -namespace Intersect.Client.Framework.Graphics +namespace Intersect.Client.Framework.Graphics; + + +public abstract partial class GameRenderer : IGameRenderer { - public abstract partial class GameRenderer : IGameRenderer + public GameRenderer() { + ScreenshotRequests = new List(); + } - public GameRenderer() - { - ScreenshotRequests = new List(); - } - - public List ScreenshotRequests { get; } + public List ScreenshotRequests { get; } - public Resolution ActiveResolution => new Resolution(PreferredResolution, OverrideResolution); + public Resolution ActiveResolution => new Resolution(PreferredResolution, OverrideResolution); - public bool HasOverrideResolution => OverrideResolution != Resolution.Empty; + public bool HasOverrideResolution => OverrideResolution != Resolution.Empty; - public Resolution OverrideResolution { get; set; } + public Resolution OverrideResolution { get; set; } - public Resolution PreferredResolution { get; set; } + public Resolution PreferredResolution { get; set; } - protected float _scale = 1.0f; + protected float _scale = 1.0f; - public float Scale + public float Scale + { + get => _scale; + set { - get => _scale; - set + if (Math.Abs(_scale - value) < 0.001) { - if (Math.Abs(_scale - value) < 0.001) - { - return; - } - - _scale = value; - RecreateSpriteBatch(); + return; } + + _scale = value; + RecreateSpriteBatch(); } + } - public abstract void Init(); + public abstract void Init(); - /// - /// Called before a frame is drawn, if the renderer must re-created or anything it does it here. - /// - /// - public abstract bool Begin(); + /// + /// Called before a frame is drawn, if the renderer must re-created or anything it does it here. + /// + /// + public abstract bool Begin(); - public abstract bool BeginScreenshot(); + public abstract bool BeginScreenshot(); - protected abstract bool RecreateSpriteBatch(); + protected abstract bool RecreateSpriteBatch(); - /// - /// Called when the frame is done being drawn, generally used to finally display the content to the screen. - /// - public abstract void End(); + /// + /// Called when the frame is done being drawn, generally used to finally display the content to the screen. + /// + public abstract void End(); - public abstract void EndScreenshot(); + public abstract void EndScreenshot(); - /// - /// Clears everything off the render target with a specified color. - /// - public abstract void Clear(Color color); + /// + /// Clears everything off the render target with a specified color. + /// + public abstract void Clear(Color color); - public abstract void SetView(FloatRect view); + public abstract void SetView(FloatRect view); - public FloatRect CurrentView + public FloatRect CurrentView + { + get { return GetView(); } + set { SetView(value); } + } + + public abstract FloatRect GetView(); + + public abstract GameFont LoadFont(string filename); + + public abstract void DrawTexture( + GameTexture tex, + float sx, + float sy, + float sw, + float sh, + float tx, + float ty, + float tw, + float th, + Color renderColor, + GameRenderTexture renderTarget = null, + GameBlendModes blendMode = GameBlendModes.None, + GameShader shader = null, + float rotationDegrees = 0.0f, + bool isUi = false, + bool drawImmediate = false + ); + + public int Fps => GetFps(); + + public abstract int GetFps(); + + public int ScreenWidth => GetScreenWidth(); + + public abstract int GetScreenWidth(); + + public int ScreenHeight => GetScreenHeight(); + + public abstract int GetScreenHeight(); + + public string ResolutionAsString => GetResolutionString(); + + void IGameRenderer.DrawTexture( + GameTexture tex, + float sx, + float sy, + float sw, + float sh, + float tx, + float ty, + float tw, + float th, + Color renderColor, + GameRenderTexture renderTarget = null, + GameBlendModes blendMode = GameBlendModes.None, + GameShader shader = null, + float rotationDegrees = 0.0f + ) => DrawTexture(tex, sx, sy, sw, sh, tx, ty, tw, th, renderColor, renderTarget, blendMode, shader, rotationDegrees); + + public GameRenderTexture CreateWhiteTexture() => GetWhiteTexture() as GameRenderTexture; + + public abstract string GetResolutionString(); + + public abstract bool DisplayModeChanged(); + + public abstract GameRenderTexture CreateRenderTexture(int width, int height); + + public abstract GameTexture LoadTexture(string filename, string realFilename); + + public abstract GameTexture LoadTexture( + string assetName, + Func createStream + ); + + public abstract GameTexture GetWhiteTexture(); + + public abstract Pointf MeasureText(string text, GameFont gameFont, float fontScale); + + public abstract void DrawString( + string text, + GameFont gameFont, + float x, + float y, + float fontScale, + Color fontColor, + bool worldPos = true, + GameRenderTexture renderTexture = null, + Color borderColor = null + ); + + public abstract void DrawString( + string text, + GameFont gameFont, + float x, + float y, + float fontScale, + Color fontColor, + bool worldPos, + GameRenderTexture renderTexture, + FloatRect clipRect, + Color borderColor = null + ); + + //Buffers + public abstract GameTileBuffer CreateTileBuffer(); + + public abstract void DrawTileBuffer(GameTileBuffer buffer); + + public abstract void Close(); + + public List ValidVideoModes => GetValidVideoModes(); + public abstract List GetValidVideoModes(); + + public abstract GameShader LoadShader(string shaderName); + + public void RequestScreenshot(string screenshotDir = "screenshots") + { + if (!Directory.Exists(screenshotDir)) { - get { return GetView(); } - set { SetView(value); } + Directory.CreateDirectory(screenshotDir ?? ""); } - public abstract FloatRect GetView(); - - public abstract GameFont LoadFont(string filename); - - public abstract void DrawTexture( - GameTexture tex, - float sx, - float sy, - float sw, - float sh, - float tx, - float ty, - float tw, - float th, - Color renderColor, - GameRenderTexture renderTarget = null, - GameBlendModes blendMode = GameBlendModes.None, - GameShader shader = null, - float rotationDegrees = 0.0f, - bool isUi = false, - bool drawImmediate = false - ); - - public int Fps => GetFps(); - - public abstract int GetFps(); - - public int ScreenWidth => GetScreenWidth(); - - public abstract int GetScreenWidth(); - - public int ScreenHeight => GetScreenHeight(); - - public abstract int GetScreenHeight(); - - public string ResolutionAsString => GetResolutionString(); - - void IGameRenderer.DrawTexture( - GameTexture tex, - float sx, - float sy, - float sw, - float sh, - float tx, - float ty, - float tw, - float th, - Color renderColor, - GameRenderTexture renderTarget = null, - GameBlendModes blendMode = GameBlendModes.None, - GameShader shader = null, - float rotationDegrees = 0.0f - ) => DrawTexture(tex, sx, sy, sw, sh, tx, ty, tw, th, renderColor, renderTarget, blendMode, shader, rotationDegrees); - - public GameRenderTexture CreateWhiteTexture() => GetWhiteTexture() as GameRenderTexture; - - public abstract string GetResolutionString(); - - public abstract bool DisplayModeChanged(); - - public abstract GameRenderTexture CreateRenderTexture(int width, int height); - - public abstract GameTexture LoadTexture(string filename, string realFilename); - - public abstract GameTexture LoadTexture( - string assetName, - Func createStream - ); - - public abstract GameTexture GetWhiteTexture(); - - public abstract Pointf MeasureText(string text, GameFont gameFont, float fontScale); - - public abstract void DrawString( - string text, - GameFont gameFont, - float x, - float y, - float fontScale, - Color fontColor, - bool worldPos = true, - GameRenderTexture renderTexture = null, - Color borderColor = null - ); - - public abstract void DrawString( - string text, - GameFont gameFont, - float x, - float y, - float fontScale, - Color fontColor, - bool worldPos, - GameRenderTexture renderTexture, - FloatRect clipRect, - Color borderColor = null - ); - - //Buffers - public abstract GameTileBuffer CreateTileBuffer(); - - public abstract void DrawTileBuffer(GameTileBuffer buffer); - - public abstract void Close(); - - public List ValidVideoModes => GetValidVideoModes(); - public abstract List GetValidVideoModes(); - - public abstract GameShader LoadShader(string shaderName); - - public void RequestScreenshot(string screenshotDir = "screenshots") + var screenshotNumber = 0; + string screenshotFile; + do { - if (!Directory.Exists(screenshotDir)) - { - Directory.CreateDirectory(screenshotDir ?? ""); - } - - var screenshotNumber = 0; - string screenshotFile; - do - { - screenshotFile = Path.Combine( - screenshotDir ?? "", $"{DateTime.Now:yyyyMMdd-HHmmssfff}{screenshotNumber}.png" - ); + screenshotFile = Path.Combine( + screenshotDir ?? "", $"{DateTime.Now:yyyyMMdd-HHmmssfff}{screenshotNumber}.png" + ); - ++screenshotNumber; - } while (File.Exists(screenshotFile) && screenshotNumber < 4); - - ScreenshotRequests.Add(File.OpenWrite(screenshotFile)); - } + ++screenshotNumber; + } while (File.Exists(screenshotFile) && screenshotNumber < 4); + ScreenshotRequests.Add(File.OpenWrite(screenshotFile)); } } diff --git a/Intersect.Client.Framework/Graphics/GameShader.cs b/Intersect.Client.Framework/Graphics/GameShader.cs index 153be87be7..e36a6c4851 100644 --- a/Intersect.Client.Framework/Graphics/GameShader.cs +++ b/Intersect.Client.Framework/Graphics/GameShader.cs @@ -1,29 +1,27 @@ using Intersect.Client.Framework.GenericClasses; -namespace Intersect.Client.Framework.Graphics -{ +namespace Intersect.Client.Framework.Graphics; - public abstract partial class GameShader - { - public GameShader(string shaderName) - { - } +public abstract partial class GameShader +{ - public abstract void SetFloat(string key, float val); + public GameShader(string shaderName) + { + } - public abstract void SetInt(string key, int val); + public abstract void SetFloat(string key, float val); - public abstract void SetColor(string key, Color val); + public abstract void SetInt(string key, int val); - public abstract void SetVector2(string key, Pointf val); + public abstract void SetColor(string key, Color val); - public abstract bool ValuesChanged(); + public abstract void SetVector2(string key, Pointf val); - public abstract void ResetChanged(); + public abstract bool ValuesChanged(); - public abstract object GetShader(); + public abstract void ResetChanged(); - } + public abstract object GetShader(); } diff --git a/Intersect.Client.Framework/Graphics/GameTexture.cs b/Intersect.Client.Framework/Graphics/GameTexture.cs index 8903cf49fc..e55832504f 100644 --- a/Intersect.Client.Framework/Graphics/GameTexture.cs +++ b/Intersect.Client.Framework/Graphics/GameTexture.cs @@ -2,95 +2,94 @@ using Intersect.Client.Framework.GenericClasses; using Intersect.Logging; -namespace Intersect.Client.Framework.Graphics +namespace Intersect.Client.Framework.Graphics; + + +public abstract partial class GameTexture : IAsset { - public abstract partial class GameTexture : IAsset - { + public string Name => GetName() ?? throw new ArgumentNullException(nameof(GetName)); - public string Name => GetName() ?? throw new ArgumentNullException(nameof(GetName)); + public int Width => GetWidth(); - public int Width => GetWidth(); + public int Height => GetHeight(); - public int Height => GetHeight(); + public int Area => Width * Height; - public int Area => Width * Height; + public Pointf Dimensions => new Pointf(Width, Height); - public Pointf Dimensions => new Pointf(Width, Height); + public FloatRect Bounds => new FloatRect(0, 0, Width, Height); - public FloatRect Bounds => new FloatRect(0, 0, Width, Height); + public Pointf Center => Dimensions / 2; - public Pointf Center => Dimensions / 2; + public object PlatformTextureObject => GetTexture(); - public object PlatformTextureObject => GetTexture(); + public GameTexturePackFrame TexturePackFrame => GetTexturePackFrame(); - public GameTexturePackFrame TexturePackFrame => GetTexturePackFrame(); + public abstract string GetName(); - public abstract string GetName(); + public abstract int GetWidth(); - public abstract int GetWidth(); + public abstract int GetHeight(); - public abstract int GetHeight(); + public abstract object GetTexture(); - public abstract object GetTexture(); + public abstract Color GetPixel(int x1, int y1); - public abstract Color GetPixel(int x1, int y1); + public abstract GameTexturePackFrame GetTexturePackFrame(); - public abstract GameTexturePackFrame GetTexturePackFrame(); + public static string ToString(GameTexture tex) + { + return tex?.GetName() ?? ""; + } - public static string ToString(GameTexture tex) - { - return tex?.GetName() ?? ""; - } + public static GameTexture GetBoundingTexture(BoundsComparison boundsComparison, params GameTexture[] textures) + { + GameTexture boundingTexture = default; - public static GameTexture GetBoundingTexture(BoundsComparison boundsComparison, params GameTexture[] textures) + foreach (var texture in textures) { - GameTexture boundingTexture = default; - - foreach (var texture in textures) + if (texture == default) + { + continue; + } + else if (boundingTexture == default) { - if (texture == default) + boundingTexture = texture; + } + else + { + var select = false; + switch (boundsComparison) { - continue; + case BoundsComparison.Width: + select = texture.Width > boundingTexture.Width; + break; + + case BoundsComparison.Height: + select = texture.Height > boundingTexture.Height; + break; + + case BoundsComparison.Dimensions: + select = texture.Width >= boundingTexture.Width && texture.Height >= boundingTexture.Height; + break; + + case BoundsComparison.Area: + select = texture.Area > boundingTexture.Area; + break; + + default: + Log.Error(new ArgumentOutOfRangeException(nameof(boundsComparison), boundsComparison.ToString())); + break; } - else if (boundingTexture == default) + + if (select) { boundingTexture = texture; } - else - { - var select = false; - switch (boundsComparison) - { - case BoundsComparison.Width: - select = texture.Width > boundingTexture.Width; - break; - - case BoundsComparison.Height: - select = texture.Height > boundingTexture.Height; - break; - - case BoundsComparison.Dimensions: - select = texture.Width >= boundingTexture.Width && texture.Height >= boundingTexture.Height; - break; - - case BoundsComparison.Area: - select = texture.Area > boundingTexture.Area; - break; - - default: - Log.Error(new ArgumentOutOfRangeException(nameof(boundsComparison), boundsComparison.ToString())); - break; - } - - if (select) - { - boundingTexture = texture; - } - } } - - return boundingTexture; } + + return boundingTexture; } } diff --git a/Intersect.Client.Framework/Graphics/GameTexturePack.cs b/Intersect.Client.Framework/Graphics/GameTexturePack.cs index 01ac5dbd1b..8c3f07d085 100644 --- a/Intersect.Client.Framework/Graphics/GameTexturePack.cs +++ b/Intersect.Client.Framework/Graphics/GameTexturePack.cs @@ -1,80 +1,78 @@ using Intersect.Client.Framework.GenericClasses; -namespace Intersect.Client.Framework.Graphics +namespace Intersect.Client.Framework.Graphics; + + +public partial class GameTexturePacks { - public partial class GameTexturePacks - { + private static List mFrames = new List(); - private static List mFrames = new List(); + private static Dictionary> mFrameTypes = + new Dictionary>(); - private static Dictionary> mFrameTypes = - new Dictionary>(); + public static void AddFrame(GameTexturePackFrame frame) + { + mFrames.Add(frame); - public static void AddFrame(GameTexturePackFrame frame) + //find the sub folder + var sep = new char[] {'/', '\\'}; + var subFolder = frame.Filename.Split(sep)[1].ToLower(); + if (!mFrameTypes.ContainsKey(subFolder)) { - mFrames.Add(frame); - - //find the sub folder - var sep = new char[] {'/', '\\'}; - var subFolder = frame.Filename.Split(sep)[1].ToLower(); - if (!mFrameTypes.ContainsKey(subFolder)) - { - mFrameTypes.Add(subFolder, new List()); - } - - if (!mFrameTypes[subFolder].Contains(frame)) - { - mFrameTypes[subFolder].Add(frame); - } + mFrameTypes.Add(subFolder, new List()); } - public static GameTexturePackFrame[] GetFolderFrames(string folder) + if (!mFrameTypes[subFolder].Contains(frame)) { - if (mFrameTypes.ContainsKey(folder.ToLower())) - { - return mFrameTypes[folder.ToLower()].ToArray(); - } - - return null; + mFrameTypes[subFolder].Add(frame); } + } - public static GameTexturePackFrame GetFrame(string filename) + public static GameTexturePackFrame[] GetFolderFrames(string folder) + { + if (mFrameTypes.ContainsKey(folder.ToLower())) { - filename = filename.Replace("\\", "/"); - return mFrames.Where(p => p.Filename.ToLower() == filename).FirstOrDefault(); + return mFrameTypes[folder.ToLower()].ToArray(); } + return null; } - public partial class GameTexturePackFrame + public static GameTexturePackFrame GetFrame(string filename) { + filename = filename.Replace("\\", "/"); + return mFrames.Where(p => p.Filename.ToLower() == filename).FirstOrDefault(); + } - public GameTexturePackFrame( - string filename, - Rectangle rect, - bool rotated, - Rectangle sourceSpriteRect, - GameTexture packTexture - ) - { - Filename = filename.Replace('\\', '/'); - Rect = rect; - Rotated = rotated; - SourceRect = sourceSpriteRect; - PackTexture = packTexture; - } +} + +public partial class GameTexturePackFrame +{ - public string Filename { get; set; } + public GameTexturePackFrame( + string filename, + Rectangle rect, + bool rotated, + Rectangle sourceSpriteRect, + GameTexture packTexture + ) + { + Filename = filename.Replace('\\', '/'); + Rect = rect; + Rotated = rotated; + SourceRect = sourceSpriteRect; + PackTexture = packTexture; + } - public Rectangle Rect { get; set; } + public string Filename { get; set; } - public bool Rotated { get; set; } + public Rectangle Rect { get; set; } - public Rectangle SourceRect { get; set; } + public bool Rotated { get; set; } - public GameTexture PackTexture { get; set; } + public Rectangle SourceRect { get; set; } - } + public GameTexture PackTexture { get; set; } } diff --git a/Intersect.Client.Framework/Graphics/GameTileBuffer.cs b/Intersect.Client.Framework/Graphics/GameTileBuffer.cs index 8c0c8b11c6..bd64488920 100644 --- a/Intersect.Client.Framework/Graphics/GameTileBuffer.cs +++ b/Intersect.Client.Framework/Graphics/GameTileBuffer.cs @@ -1,23 +1,21 @@ -namespace Intersect.Client.Framework.Graphics -{ +namespace Intersect.Client.Framework.Graphics; - public abstract partial class GameTileBuffer - { - public static int TileBufferCount { get; set; } = 0; +public abstract partial class GameTileBuffer +{ - public abstract bool Supported { get; } + public static int TileBufferCount { get; set; } = 0; - public abstract GameTexture Texture { get; protected set; } + public abstract bool Supported { get; } - public abstract bool AddTile(GameTexture texture, float x, float y, int srcX, int srcY, int srcW, int srcH); + public abstract GameTexture Texture { get; protected set; } - public abstract bool UpdateTile(GameTexture texture, float x, float y, int srcX, int srcY, int srcW, int srcH); + public abstract bool AddTile(GameTexture texture, float x, float y, int srcX, int srcY, int srcW, int srcH); - public abstract bool SetData(); + public abstract bool UpdateTile(GameTexture texture, float x, float y, int srcX, int srcY, int srcW, int srcH); - public abstract void Dispose(); + public abstract bool SetData(); - } + public abstract void Dispose(); } diff --git a/Intersect.Client.Framework/Graphics/IGameRenderer.cs b/Intersect.Client.Framework/Graphics/IGameRenderer.cs index 469833bf9a..b9fe954dc1 100644 --- a/Intersect.Client.Framework/Graphics/IGameRenderer.cs +++ b/Intersect.Client.Framework/Graphics/IGameRenderer.cs @@ -1,140 +1,139 @@ using Intersect.Client.Framework.GenericClasses; -namespace Intersect.Client.Framework.Graphics +namespace Intersect.Client.Framework.Graphics; + +public interface IGameRenderer { - public interface IGameRenderer - { - /// - /// The current active resolution of the client. - /// - Resolution ActiveResolution { get; } - - /// - /// The current active resolution of the client as a string. - /// - string ResolutionAsString { get; } - - /// - /// The current height of the client screen. - /// - int ScreenHeight { get; } - - /// - /// The current width of the client screen. - /// - int ScreenWidth { get; } - - /// - /// The current override resolution of the client. - /// - Resolution OverrideResolution { get; set; } - - /// - /// The preferred resolution of the client. - /// - Resolution PreferredResolution { get; set; } - - /// - /// The current viewport of the client. - /// - FloatRect CurrentView { get; set; } - - /// - /// All currently standing request for screenshots of the client. - /// - List ScreenshotRequests { get; } - - /// - /// The current framerate at which the client is drawing frames. - /// - int Fps { get; } - - /// - /// All valid video modes that the client can render at. - /// - List ValidVideoModes { get; } - - /// - /// Clear the screen. - /// - /// The to clear the screen with. - void Clear(Color color); - - /// - /// Create a new empty render texture in memory. - /// - /// The width of the render texture. - /// The height of the render texture. - /// Returns a new with the configured height and width. - GameRenderTexture CreateRenderTexture(int width, int height); - - /// - /// Create a new render texture in memory that's white. - /// - /// Returns a new white . - GameRenderTexture CreateWhiteTexture(); - - /// - /// Draw a texture to the client display. - /// - /// The to render to the screen. - /// The X position to use on the texture to draw from. - /// The Y position to use on the texture to draw from. - /// The width to use on the texture to draw from. - /// The height to use on the texture to draw from. - /// The destination X position on screen. - /// The destination Y position on screen. - /// The destination width on screen. - /// The destination height on screen. - /// The to render this texture as. Use to retain original colors. - /// Overrides this method to draw to the specified instead of the screen. - /// The to use to render this texture to the screen with. - /// The to use to render this to the screen with. - /// The angle to render this texture at. - void DrawTexture(GameTexture texture, float sourceX, float sourceY, float sourceWidth, float sourceHeight, float targetX, float targetY, float targetWidth, float targetHeight, Color renderColor, GameRenderTexture renderTarget = null, GameBlendModes blendMode = GameBlendModes.None, GameShader shader = null, float rotationDegrees = 0); - - /// - /// Draw text to the client display. - /// - /// The text to render to the screen. - /// The to use to render the text. - /// The X location on the screen to render the text to. - /// The Y location on the screen to render the text to. - /// The scale of the font to render the text with. - /// The to use to render the text with. - /// Determines if this text is rendered in a world relative location. When false it will render screen relative. - /// Overrides this method to draw to the specified instead of the screen. - /// The to use to render the border of this text with. - void DrawString(string text, GameFont gameFont, float x, float y, float fontScale, Color fontColor, bool worldPos = true, GameRenderTexture renderTexture = null, Color borderColor = null); - - /// - /// Draw text to the client display. - /// - /// The text to render to the screen. - /// The to use to render the text. - /// The X location on the screen to render the text to. - /// The Y location on the screen to render the text to. - /// The scale of the font to render the text with. - /// The to use to render the text with. - /// Determines if this text is rendered in a world relative location. When false it will render screen relative. - /// Overrides this method to draw to the specified instead of the screen. - /// The to use to render the border of this text with. - /// The containing locations that this text can not be rendered outside of, cutting off anything outside of it. - void DrawString(string text, GameFont gameFont, float x, float y, float fontScale, Color fontColor, bool worldPos, GameRenderTexture renderTexture, FloatRect clipRect, Color borderColor = null); - - /// - /// Measures a string of text. - /// - /// The text to measure the size of. - /// The to use to measure the text with. - /// The scale of the font to measure the text with. - /// Returns a containing the width and height of the measured text. - Pointf MeasureText(string text, GameFont gameFont, float fontScale); - - /// - /// Send a request for the client to take a screenshot the next draw cycle. - /// - /// The directory (relative to the client directory) to store the screenshot in. - void RequestScreenshot(string screenshotDir = "screenshots"); - } + /// + /// The current active resolution of the client. + /// + Resolution ActiveResolution { get; } + + /// + /// The current active resolution of the client as a string. + /// + string ResolutionAsString { get; } + + /// + /// The current height of the client screen. + /// + int ScreenHeight { get; } + + /// + /// The current width of the client screen. + /// + int ScreenWidth { get; } + + /// + /// The current override resolution of the client. + /// + Resolution OverrideResolution { get; set; } + + /// + /// The preferred resolution of the client. + /// + Resolution PreferredResolution { get; set; } + + /// + /// The current viewport of the client. + /// + FloatRect CurrentView { get; set; } + + /// + /// All currently standing request for screenshots of the client. + /// + List ScreenshotRequests { get; } + + /// + /// The current framerate at which the client is drawing frames. + /// + int Fps { get; } + + /// + /// All valid video modes that the client can render at. + /// + List ValidVideoModes { get; } + + /// + /// Clear the screen. + /// + /// The to clear the screen with. + void Clear(Color color); + + /// + /// Create a new empty render texture in memory. + /// + /// The width of the render texture. + /// The height of the render texture. + /// Returns a new with the configured height and width. + GameRenderTexture CreateRenderTexture(int width, int height); + + /// + /// Create a new render texture in memory that's white. + /// + /// Returns a new white . + GameRenderTexture CreateWhiteTexture(); + + /// + /// Draw a texture to the client display. + /// + /// The to render to the screen. + /// The X position to use on the texture to draw from. + /// The Y position to use on the texture to draw from. + /// The width to use on the texture to draw from. + /// The height to use on the texture to draw from. + /// The destination X position on screen. + /// The destination Y position on screen. + /// The destination width on screen. + /// The destination height on screen. + /// The to render this texture as. Use to retain original colors. + /// Overrides this method to draw to the specified instead of the screen. + /// The to use to render this texture to the screen with. + /// The to use to render this to the screen with. + /// The angle to render this texture at. + void DrawTexture(GameTexture texture, float sourceX, float sourceY, float sourceWidth, float sourceHeight, float targetX, float targetY, float targetWidth, float targetHeight, Color renderColor, GameRenderTexture renderTarget = null, GameBlendModes blendMode = GameBlendModes.None, GameShader shader = null, float rotationDegrees = 0); + + /// + /// Draw text to the client display. + /// + /// The text to render to the screen. + /// The to use to render the text. + /// The X location on the screen to render the text to. + /// The Y location on the screen to render the text to. + /// The scale of the font to render the text with. + /// The to use to render the text with. + /// Determines if this text is rendered in a world relative location. When false it will render screen relative. + /// Overrides this method to draw to the specified instead of the screen. + /// The to use to render the border of this text with. + void DrawString(string text, GameFont gameFont, float x, float y, float fontScale, Color fontColor, bool worldPos = true, GameRenderTexture renderTexture = null, Color borderColor = null); + + /// + /// Draw text to the client display. + /// + /// The text to render to the screen. + /// The to use to render the text. + /// The X location on the screen to render the text to. + /// The Y location on the screen to render the text to. + /// The scale of the font to render the text with. + /// The to use to render the text with. + /// Determines if this text is rendered in a world relative location. When false it will render screen relative. + /// Overrides this method to draw to the specified instead of the screen. + /// The to use to render the border of this text with. + /// The containing locations that this text can not be rendered outside of, cutting off anything outside of it. + void DrawString(string text, GameFont gameFont, float x, float y, float fontScale, Color fontColor, bool worldPos, GameRenderTexture renderTexture, FloatRect clipRect, Color borderColor = null); + + /// + /// Measures a string of text. + /// + /// The text to measure the size of. + /// The to use to measure the text with. + /// The scale of the font to measure the text with. + /// Returns a containing the width and height of the measured text. + Pointf MeasureText(string text, GameFont gameFont, float fontScale); + + /// + /// Send a request for the client to take a screenshot the next draw cycle. + /// + /// The directory (relative to the client directory) to store the screenshot in. + void RequestScreenshot(string screenshotDir = "screenshots"); } \ No newline at end of file diff --git a/Intersect.Client.Framework/Graphics/Resolution.cs b/Intersect.Client.Framework/Graphics/Resolution.cs index fa8482a997..9faa857c76 100644 --- a/Intersect.Client.Framework/Graphics/Resolution.cs +++ b/Intersect.Client.Framework/Graphics/Resolution.cs @@ -1,98 +1,96 @@ -namespace Intersect.Client.Framework.Graphics +namespace Intersect.Client.Framework.Graphics; + + +public partial struct Resolution : IComparable { - public partial struct Resolution : IComparable - { + public static readonly Resolution Empty = default; - public static readonly Resolution Empty = default; + private static readonly char[] Separators = { 'x', ',', ' ', '/', '-', '_', '.', '~' }; - private static readonly char[] Separators = { 'x', ',', ' ', '/', '-', '_', '.', '~' }; + public readonly ushort X; - public readonly ushort X; + public readonly ushort Y; - public readonly ushort Y; + public Resolution(long x = 800, long y = 600) + { + X = (ushort)(x & 0xFFFF); + Y = (ushort)(y & 0xFFFF); + } - public Resolution(long x = 800, long y = 600) - { - X = (ushort)(x & 0xFFFF); - Y = (ushort)(y & 0xFFFF); - } + public Resolution(ulong x = 800, ulong y = 600) + { + X = (ushort)(x & 0xFFFF); + Y = (ushort)(y & 0xFFFF); + } - public Resolution(ulong x = 800, ulong y = 600) - { - X = (ushort)(x & 0xFFFF); - Y = (ushort)(y & 0xFFFF); - } + public Resolution(Resolution resolution, long overrideX = 0, long overrideY = 0) + : this( + overrideX > 0 ? overrideX : resolution.X, overrideY > 0 ? overrideY : resolution.Y + ) + { } - public Resolution(Resolution resolution, long overrideX = 0, long overrideY = 0) - : this( - overrideX > 0 ? overrideX : resolution.X, overrideY > 0 ? overrideY : resolution.Y - ) - { } + public Resolution(Resolution resolution, Resolution? overrideResolution = null) + { + var x = overrideResolution?.X ?? resolution.X; + X = x > 0 ? x : resolution.X; - public Resolution(Resolution resolution, Resolution? overrideResolution = null) - { - var x = overrideResolution?.X ?? resolution.X; - X = x > 0 ? x : resolution.X; + var y = overrideResolution?.Y ?? resolution.Y; + Y = y > 0 ? y : resolution.Y; + } - var y = overrideResolution?.Y ?? resolution.Y; - Y = y > 0 ? y : resolution.Y; - } + public int CompareTo(Resolution other) + { + var diffX = X - other.X; + return diffX != 0 ? diffX : Y - other.Y; + } - public int CompareTo(Resolution other) - { - var diffX = X - other.X; - return diffX != 0 ? diffX : Y - other.Y; - } + public override bool Equals(object obj) => obj is Resolution resolution && Equals(resolution); - public override bool Equals(object obj) => obj is Resolution resolution && Equals(resolution); + public bool Equals(Resolution other) => X == other.X && Y == other.Y; - public bool Equals(Resolution other) => X == other.X && Y == other.Y; + public override int GetHashCode() => (X << 16) & Y; - public override int GetHashCode() => (X << 16) & Y; + public override string ToString() => $"{X},{Y}"; - public override string ToString() => $"{X},{Y}"; + public static Resolution Parse(string resolution) + { + var split = resolution?.Split(Separators); + string xString = split?[0], yString = split?[1]; - public static Resolution Parse(string resolution) + if (string.IsNullOrWhiteSpace(xString)) { - var split = resolution?.Split(Separators); - string xString = split?[0], yString = split?[1]; - - if (string.IsNullOrWhiteSpace(xString)) - { - throw new ArgumentNullException(nameof(xString)); - } - - if (string.IsNullOrWhiteSpace(yString)) - { - throw new ArgumentNullException(nameof(xString)); - } - - var x = ushort.Parse(xString); - var y = ushort.Parse(yString); - return new Resolution(x, y); + throw new ArgumentNullException(nameof(xString)); } - public static bool TryParse(string resolutionString, out Resolution resolution) + if (string.IsNullOrWhiteSpace(yString)) { - try - { - resolution = Parse(resolutionString); - return true; - } - catch - { - // Ignore - resolution = default; - return false; - } + throw new ArgumentNullException(nameof(xString)); } - public static bool operator ==(Resolution left, Resolution right) => - left.X == right.X && left.Y == right.Y; + var x = ushort.Parse(xString); + var y = ushort.Parse(yString); + return new Resolution(x, y); + } - public static bool operator !=(Resolution left, Resolution right) => - left.X != right.X && left.Y != right.Y; + public static bool TryParse(string resolutionString, out Resolution resolution) + { + try + { + resolution = Parse(resolutionString); + return true; + } + catch + { + // Ignore + resolution = default; + return false; + } } + public static bool operator ==(Resolution left, Resolution right) => + left.X == right.X && left.Y == right.Y; + + public static bool operator !=(Resolution left, Resolution right) => + left.X != right.X && left.Y != right.Y; } diff --git a/Intersect.Client.Framework/Gwen/Align.cs b/Intersect.Client.Framework/Gwen/Align.cs index 7070cc5479..6448acb968 100644 --- a/Intersect.Client.Framework/Gwen/Align.cs +++ b/Intersect.Client.Framework/Gwen/Align.cs @@ -1,160 +1,158 @@ using Intersect.Client.Framework.Gwen.Control; -namespace Intersect.Client.Framework.Gwen +namespace Intersect.Client.Framework.Gwen; + + +public enum Alignments { - public enum Alignments - { + Top, - Top, + Bottom, - Bottom, + Left, - Left, + Right, - Right, + Center, - Center, + CenterH, - CenterH, + CenterV - CenterV +} - } +/// +/// Utility class for manipulating control's position according to its parent. Rarely needed, use control.Dock. +/// +public static partial class Align +{ /// - /// Utility class for manipulating control's position according to its parent. Rarely needed, use control.Dock. + /// Centers the control inside its parent. /// - public static partial class Align + /// Control to center. + public static void Center(Base control) { - - /// - /// Centers the control inside its parent. - /// - /// Control to center. - public static void Center(Base control) + var parent = control.Parent; + if (parent == null) { - var parent = control.Parent; - if (parent == null) - { - return; - } - - control.SetPosition( - parent.Padding.Left + (parent.Width - parent.Padding.Left - parent.Padding.Right - control.Width) / 2 + control.AlignmentDistance.Left, - (parent.Height - control.Height) / 2 + control.AlignmentDistance.Top - ); + return; } - /// - /// Moves the control to the left of its parent. - /// - /// - public static void AlignLeft(Base control) - { - var parent = control.Parent; - if (null == parent) - { - return; - } - - control.SetPosition(parent.Padding.Left + control.Margin.Left, control.Y); - } + control.SetPosition( + parent.Padding.Left + (parent.Width - parent.Padding.Left - parent.Padding.Right - control.Width) / 2 + control.AlignmentDistance.Left, + (parent.Height - control.Height) / 2 + control.AlignmentDistance.Top + ); + } - /// - /// Centers the control horizontally inside its parent. - /// - /// - public static void CenterHorizontally(Base control) + /// + /// Moves the control to the left of its parent. + /// + /// + public static void AlignLeft(Base control) + { + var parent = control.Parent; + if (null == parent) { - var parent = control.Parent; - if (null == parent) - { - return; - } - - control.SetPosition( - parent.Padding.Left + (parent.Width - parent.Padding.Left - parent.Padding.Right - control.Width) / 2, - control.Y - ); + return; } - /// - /// Moves the control to the right of its parent. - /// - /// - public static void AlignRight(Base control) - { - var parent = control.Parent; - if (null == parent) - { - return; - } - - control.SetPosition(parent.Width - control.Width - parent.Padding.Right - control.Margin.Right, control.Y); - } + control.SetPosition(parent.Padding.Left + control.Margin.Left, control.Y); + } - /// - /// Moves the control to the top of its parent. - /// - /// - public static void AlignTop(Base control) + /// + /// Centers the control horizontally inside its parent. + /// + /// + public static void CenterHorizontally(Base control) + { + var parent = control.Parent; + if (null == parent) { - control.SetPosition(control.X, control.Margin.Top); + return; } - /// - /// Centers the control vertically inside its parent. - /// - /// - public static void CenterVertically(Base control) - { - var parent = control.Parent; - if (null == parent) - { - return; - } + control.SetPosition( + parent.Padding.Left + (parent.Width - parent.Padding.Left - parent.Padding.Right - control.Width) / 2, + control.Y + ); + } - control.SetPosition(control.X, (parent.Height - control.Height) / 2); + /// + /// Moves the control to the right of its parent. + /// + /// + public static void AlignRight(Base control) + { + var parent = control.Parent; + if (null == parent) + { + return; } - /// - /// Moves the control to the bottom of its parent. - /// - /// - public static void AlignBottom(Base control) - { - var parent = control.Parent; - if (null == parent) - { - return; - } + control.SetPosition(parent.Width - control.Width - parent.Padding.Right - control.Margin.Right, control.Y); + } - control.SetPosition(control.X, parent.Height - control.Height - control.Margin.Bottom); - } + /// + /// Moves the control to the top of its parent. + /// + /// + public static void AlignTop(Base control) + { + control.SetPosition(control.X, control.Margin.Top); + } - /// - /// Places the control below other control (left aligned), taking margins into account. - /// - /// Control to place. - /// Anchor control. - /// Optional spacing. - public static void PlaceDownLeft(Base control, Base anchor, int spacing = 0) + /// + /// Centers the control vertically inside its parent. + /// + /// + public static void CenterVertically(Base control) + { + var parent = control.Parent; + if (null == parent) { - control.SetPosition(anchor.X, anchor.Bottom + spacing); + return; } - /// - /// Places the control to the right of other control (bottom aligned), taking margins into account. - /// - /// Control to place. - /// Anchor control. - /// Optional spacing. - public static void PlaceRightBottom(Base control, Base anchor, int spacing = 0) + control.SetPosition(control.X, (parent.Height - control.Height) / 2); + } + + /// + /// Moves the control to the bottom of its parent. + /// + /// + public static void AlignBottom(Base control) + { + var parent = control.Parent; + if (null == parent) { - control.SetPosition(anchor.Right + spacing, anchor.Y - control.Height + anchor.Height); + return; } + control.SetPosition(control.X, parent.Height - control.Height - control.Margin.Bottom); + } + + /// + /// Places the control below other control (left aligned), taking margins into account. + /// + /// Control to place. + /// Anchor control. + /// Optional spacing. + public static void PlaceDownLeft(Base control, Base anchor, int spacing = 0) + { + control.SetPosition(anchor.X, anchor.Bottom + spacing); + } + + /// + /// Places the control to the right of other control (bottom aligned), taking margins into account. + /// + /// Control to place. + /// Anchor control. + /// Optional spacing. + public static void PlaceRightBottom(Base control, Base anchor, int spacing = 0) + { + control.SetPosition(anchor.Right + spacing, anchor.Y - control.Height + anchor.Height); } } diff --git a/Intersect.Client.Framework/Gwen/Anim/Animation.cs b/Intersect.Client.Framework/Gwen/Anim/Animation.cs index 20819b0acf..500539aada 100644 --- a/Intersect.Client.Framework/Gwen/Anim/Animation.cs +++ b/Intersect.Client.Framework/Gwen/Anim/Animation.cs @@ -1,58 +1,56 @@ using Intersect.Client.Framework.Gwen.Control; -namespace Intersect.Client.Framework.Gwen.Anim +namespace Intersect.Client.Framework.Gwen.Anim; + + +public partial class Animation { - public partial class Animation - { + //private static List g_AnimationsListed = new List(); // unused + private static readonly Dictionary> Animations = new Dictionary>(); - //private static List g_AnimationsListed = new List(); // unused - private static readonly Dictionary> Animations = new Dictionary>(); + protected Base mControl; - protected Base mControl; + public virtual bool Finished => throw new InvalidOperationException("Pure virtual function call"); - public virtual bool Finished => throw new InvalidOperationException("Pure virtual function call"); + protected virtual void Think() + { + } - protected virtual void Think() + public static void Add(Base control, Animation animation) + { + animation.mControl = control; + if (!Animations.ContainsKey(control)) { + Animations[control] = new List(); } - public static void Add(Base control, Animation animation) - { - animation.mControl = control; - if (!Animations.ContainsKey(control)) - { - Animations[control] = new List(); - } - - Animations[control].Add(animation); - } + Animations[control].Add(animation); + } - public static void Cancel(Base control) + public static void Cancel(Base control) + { + if (Animations.ContainsKey(control)) { - if (Animations.ContainsKey(control)) - { - Animations[control].Clear(); - Animations.Remove(control); - } + Animations[control].Clear(); + Animations.Remove(control); } + } - internal static void GlobalThink() + internal static void GlobalThink() + { + foreach (var pair in Animations) { - foreach (var pair in Animations) + var valCopy = pair.Value.FindAll(x => true); // list copy so foreach won't break when we remove elements + foreach (var animation in valCopy) { - var valCopy = pair.Value.FindAll(x => true); // list copy so foreach won't break when we remove elements - foreach (var animation in valCopy) + animation.Think(); + if (animation.Finished) { - animation.Think(); - if (animation.Finished) - { - pair.Value.Remove(animation); - } + pair.Value.Remove(animation); } } } - } } diff --git a/Intersect.Client.Framework/Gwen/Anim/Size/Height.cs b/Intersect.Client.Framework/Gwen/Anim/Size/Height.cs index 52cd8a9875..4c4237dfb9 100644 --- a/Intersect.Client.Framework/Gwen/Anim/Size/Height.cs +++ b/Intersect.Client.Framework/Gwen/Anim/Size/Height.cs @@ -1,48 +1,46 @@ -namespace Intersect.Client.Framework.Gwen.Anim.Size +namespace Intersect.Client.Framework.Gwen.Anim.Size; + + +partial class Height : TimedAnimation { - partial class Height : TimedAnimation + private int mDelta; + + private bool mHide; + + private int mStartSize; + + public Height( + int startSize, + int endSize, + float length, + bool hide = false, + float delay = 0.0f, + float ease = 1.0f + ) : base(length, delay, ease) + { + mStartSize = startSize; + mDelta = endSize - mStartSize; + mHide = hide; + } + + protected override void OnStart() { + base.OnStart(); + mControl.Height = mStartSize; + } - private int mDelta; - - private bool mHide; - - private int mStartSize; - - public Height( - int startSize, - int endSize, - float length, - bool hide = false, - float delay = 0.0f, - float ease = 1.0f - ) : base(length, delay, ease) - { - mStartSize = startSize; - mDelta = endSize - mStartSize; - mHide = hide; - } - - protected override void OnStart() - { - base.OnStart(); - mControl.Height = mStartSize; - } - - protected override void Run(float delta) - { - base.Run(delta); - mControl.Height = (int) (mStartSize + mDelta * delta); - } - - protected override void OnFinish() - { - base.OnFinish(); - mControl.Height = mStartSize + mDelta; - mControl.IsHidden = mHide; - } + protected override void Run(float delta) + { + base.Run(delta); + mControl.Height = (int) (mStartSize + mDelta * delta); + } + protected override void OnFinish() + { + base.OnFinish(); + mControl.Height = mStartSize + mDelta; + mControl.IsHidden = mHide; } } diff --git a/Intersect.Client.Framework/Gwen/Anim/Size/Width.cs b/Intersect.Client.Framework/Gwen/Anim/Size/Width.cs index 38943414a1..636243ea67 100644 --- a/Intersect.Client.Framework/Gwen/Anim/Size/Width.cs +++ b/Intersect.Client.Framework/Gwen/Anim/Size/Width.cs @@ -1,42 +1,40 @@ -namespace Intersect.Client.Framework.Gwen.Anim.Size -{ +namespace Intersect.Client.Framework.Gwen.Anim.Size; - partial class Width : TimedAnimation - { - private int mDelta; +partial class Width : TimedAnimation +{ - private bool mHide; + private int mDelta; - private int mStartSize; + private bool mHide; - public Width(int startSize, int endSize, float length, bool hide = false, float delay = 0.0f, float ease = 1.0f) - : base(length, delay, ease) - { - mStartSize = startSize; - mDelta = endSize - mStartSize; - mHide = hide; - } + private int mStartSize; - protected override void OnStart() - { - base.OnStart(); - mControl.Width = mStartSize; - } + public Width(int startSize, int endSize, float length, bool hide = false, float delay = 0.0f, float ease = 1.0f) + : base(length, delay, ease) + { + mStartSize = startSize; + mDelta = endSize - mStartSize; + mHide = hide; + } - protected override void Run(float delta) - { - base.Run(delta); - mControl.Width = (int) Math.Round(mStartSize + mDelta * delta); - } + protected override void OnStart() + { + base.OnStart(); + mControl.Width = mStartSize; + } - protected override void OnFinish() - { - base.OnFinish(); - mControl.Width = mStartSize + mDelta; - mControl.IsHidden = mHide; - } + protected override void Run(float delta) + { + base.Run(delta); + mControl.Width = (int) Math.Round(mStartSize + mDelta * delta); + } + protected override void OnFinish() + { + base.OnFinish(); + mControl.Width = mStartSize + mDelta; + mControl.IsHidden = mHide; } } diff --git a/Intersect.Client.Framework/Gwen/Anim/TimedAnimation.cs b/Intersect.Client.Framework/Gwen/Anim/TimedAnimation.cs index 5ad13f3844..574dc21cd3 100644 --- a/Intersect.Client.Framework/Gwen/Anim/TimedAnimation.cs +++ b/Intersect.Client.Framework/Gwen/Anim/TimedAnimation.cs @@ -1,87 +1,85 @@ -namespace Intersect.Client.Framework.Gwen.Anim +namespace Intersect.Client.Framework.Gwen.Anim; + + +// Timed animation. Provides a useful base for animations. +public partial class TimedAnimation : Animation { - // Timed animation. Provides a useful base for animations. - public partial class TimedAnimation : Animation - { + private float mEase; - private float mEase; + private float mEnd; - private float mEnd; + private bool mFinished; - private bool mFinished; + private float mStart; - private float mStart; + private bool mStarted; + + public TimedAnimation(float length, float delay = 0.0f, float ease = 1.0f) + { + mStart = Platform.Neutral.GetTimeInSeconds() + delay; + mEnd = mStart + length; + mEase = ease; + mStarted = false; + mFinished = false; + } - private bool mStarted; + public override bool Finished => mFinished; - public TimedAnimation(float length, float delay = 0.0f, float ease = 1.0f) + protected override void Think() + { + //base.Think(); + + if (mFinished) { - mStart = Platform.Neutral.GetTimeInSeconds() + delay; - mEnd = mStart + length; - mEase = ease; - mStarted = false; - mFinished = false; + return; } - public override bool Finished => mFinished; - - protected override void Think() + var current = Platform.Neutral.GetTimeInSeconds(); + var secondsIn = current - mStart; + if (secondsIn < 0.0) { - //base.Think(); - - if (mFinished) - { - return; - } - - var current = Platform.Neutral.GetTimeInSeconds(); - var secondsIn = current - mStart; - if (secondsIn < 0.0) - { - return; - } - - if (!mStarted) - { - mStarted = true; - OnStart(); - } - - var delta = secondsIn / (mEnd - mStart); - if (delta < 0.0f) - { - delta = 0.0f; - } - - if (delta > 1.0f) - { - delta = 1.0f; - } - - Run((float) Math.Pow(delta, mEase)); - - if (delta == 1.0f) - { - mFinished = true; - OnFinish(); - } + return; } - // These are the magic functions you should be overriding + if (!mStarted) + { + mStarted = true; + OnStart(); + } - protected virtual void OnStart() + var delta = secondsIn / (mEnd - mStart); + if (delta < 0.0f) { + delta = 0.0f; } - protected virtual void Run(float delta) + if (delta > 1.0f) { + delta = 1.0f; } - protected virtual void OnFinish() + Run((float) Math.Pow(delta, mEase)); + + if (delta == 1.0f) { + mFinished = true; + OnFinish(); } + } + + // These are the magic functions you should be overriding + + protected virtual void OnStart() + { + } + protected virtual void Run(float delta) + { + } + + protected virtual void OnFinish() + { } } diff --git a/Intersect.Client.Framework/Gwen/Control/Base.cs b/Intersect.Client.Framework/Gwen/Control/Base.cs index dd545dc1db..5185c5818b 100644 --- a/Intersect.Client.Framework/Gwen/Control/Base.cs +++ b/Intersect.Client.Framework/Gwen/Control/Base.cs @@ -14,1270 +14,1286 @@ using Intersect.Client.Framework.Gwen.Renderer; using Intersect.Reflection; -namespace Intersect.Client.Framework.Gwen.Control -{ +namespace Intersect.Client.Framework.Gwen.Control; - /// - /// Base control class. - /// - public partial class Base : IDisposable - { - private bool _inheritParentEnablementProperties; +/// +/// Base control class. +/// +public partial class Base : IDisposable +{ + + private bool _inheritParentEnablementProperties; - internal bool InheritParentEnablementProperties + internal bool InheritParentEnablementProperties + { + get => _inheritParentEnablementProperties; + set { - get => _inheritParentEnablementProperties; - set - { - _inheritParentEnablementProperties = value; - IsDisabled = Parent?.IsDisabled ?? IsDisabled; - IsHidden = Parent?.IsHidden ?? IsHidden; - } + _inheritParentEnablementProperties = value; + IsDisabled = Parent?.IsDisabled ?? IsDisabled; + IsHidden = Parent?.IsHidden ?? IsHidden; } + } - /// - /// Delegate used for all control event handlers. - /// - /// Event source. - /// Additional arguments. May be empty (EventArgs.Empty). - public delegate void GwenEventHandler(Base sender, T arguments) where T : System.EventArgs; + /// + /// Delegate used for all control event handlers. + /// + /// Event source. + /// Additional arguments. May be empty (EventArgs.Empty). + public delegate void GwenEventHandler(Base sender, T arguments) where T : System.EventArgs; - public const int MAX_COORD = 4096; // added here from various places in code + public const int MAX_COORD = 4096; // added here from various places in code - /// - /// Accelerator map. - /// - private readonly Dictionary> mAccelerators; + /// + /// Accelerator map. + /// + private readonly Dictionary> mAccelerators; - /// - /// Real list of children. - /// - private readonly List mChildren; + /// + /// Real list of children. + /// + private readonly List mChildren; - /// - /// This is the panel's actual parent - most likely the logical - /// parent's InnerPanel (if it has one). You should rarely need this. - /// - private Base mActualParent; + /// + /// This is the panel's actual parent - most likely the logical + /// parent's InnerPanel (if it has one). You should rarely need this. + /// + private Base mActualParent; - private Padding mAlignmentDistance; + private Padding mAlignmentDistance; - private List mAlignments = new List(); + private List mAlignments = new List(); - private Point mAlignmentTransform; + private Point mAlignmentTransform; - private Rectangle mBounds; - private Rectangle mBoundsOnDisk; + private Rectangle mBounds; + private Rectangle mBoundsOnDisk; - private bool mCacheTextureDirty; + private bool mCacheTextureDirty; - private bool mCacheToTexture; + private bool mCacheToTexture; - private Color mColor; + private Color mColor; - private Cursor mCursor; + private Cursor mCursor; - private bool mDisabled; + private bool mDisabled; - private bool mDisposed; + private bool mDisposed; - private Pos mDock; + private Pos mDock; - private Package mDragAndDrop_package; + private Package mDragAndDrop_package; - private bool mDrawBackground; + private bool mDrawBackground; - private bool mDrawDebugOutlines; + private bool mDrawDebugOutlines; - private bool mHidden; + private bool mHidden; - private bool mHideToolTip; + private bool mHideToolTip; - private Rectangle mInnerBounds; + private Rectangle mInnerBounds; - /// - /// If the innerpanel exists our children will automatically become children of that - /// instead of us - allowing us to move them all around by moving that panel (useful for scrolling etc). - /// - protected Base mInnerPanel; + /// + /// If the innerpanel exists our children will automatically become children of that + /// instead of us - allowing us to move them all around by moving that panel (useful for scrolling etc). + /// + protected Base mInnerPanel; - private bool mKeyboardInputEnabled; + private bool mKeyboardInputEnabled; - private Margin mMargin; + private Margin mMargin; - private Point mMaximumSize = new Point(MAX_COORD, MAX_COORD); + private Point mMaximumSize = new Point(MAX_COORD, MAX_COORD); - private Point mMinimumSize = new Point(1, 1); + private Point mMinimumSize = new Point(1, 1); - private bool mMouseInputEnabled; + private bool mMouseInputEnabled; - private string mName; + private string mName; - private bool mNeedsLayout; + private bool mNeedsLayout; - private Padding mPadding; + private Padding mPadding; - private Base? mParent; + private Base? mParent; - private Rectangle mRenderBounds; + private Rectangle mRenderBounds; - private bool mRestrictToParent; + private bool mRestrictToParent; - private Skin.Base mSkin; + private Skin.Base mSkin; - private bool mTabable; + private bool mTabable; - private Base mToolTip; + private Base mToolTip; - private string mToolTipBackgroundFilename; + private string mToolTipBackgroundFilename; - private GameTexture mToolTipBackgroundImage; + private GameTexture mToolTipBackgroundImage; - private GameFont mToolTipFont; + private GameFont mToolTipFont; - private Color mToolTipFontColor; + private Color mToolTipFontColor; - private string mToolTipFontInfo; + private string mToolTipFontInfo; - private object mUserData; + private object mUserData; - /// - /// Initializes a new instance of the class. - /// - /// parent control - /// name of this control - public Base(Base? parent = default, string? name = default) - { - mName = name ?? string.Empty; - mChildren = new List(); - mAccelerators = new Dictionary>(); + /// + /// Initializes a new instance of the class. + /// + /// parent control + /// name of this control + public Base(Base? parent = default, string? name = default) + { + mName = name ?? string.Empty; + mChildren = new List(); + mAccelerators = new Dictionary>(); - Parent = parent; + Parent = parent; - mHidden = false; - mBounds = new Rectangle(0, 0, 10, 10); - mPadding = Padding.Zero; - mMargin = Margin.Zero; - mColor = Color.White; - mAlignmentDistance = Padding.Zero; + mHidden = false; + mBounds = new Rectangle(0, 0, 10, 10); + mPadding = Padding.Zero; + mMargin = Margin.Zero; + mColor = Color.White; + mAlignmentDistance = Padding.Zero; - RestrictToParent = false; + RestrictToParent = false; - MouseInputEnabled = true; - KeyboardInputEnabled = false; + MouseInputEnabled = true; + KeyboardInputEnabled = false; - Invalidate(); - Cursor = Cursors.Default; + Invalidate(); + Cursor = Cursors.Default; - //ToolTip = null; - IsTabable = false; - ShouldDrawBackground = true; - mDisabled = false; - mCacheTextureDirty = true; - mCacheToTexture = false; + //ToolTip = null; + IsTabable = false; + ShouldDrawBackground = true; + mDisabled = false; + mCacheTextureDirty = true; + mCacheToTexture = false; - BoundsOutlineColor = Color.Red; - MarginOutlineColor = Color.Green; - PaddingOutlineColor = Color.Blue; - } + BoundsOutlineColor = Color.Red; + MarginOutlineColor = Color.Green; + PaddingOutlineColor = Color.Blue; + } - /// - /// Font. - /// - public GameFont ToolTipFont + /// + /// Font. + /// + public GameFont ToolTipFont + { + get => mToolTipFont; + set { - get => mToolTipFont; - set - { - mToolTipFont = value; - mToolTipFontInfo = $"{value?.GetName()},{value?.GetSize()}"; - } + mToolTipFont = value; + mToolTipFontInfo = $"{value?.GetName()},{value?.GetSize()}"; } + } - public List CurAlignments => mAlignments; + public List CurAlignments => mAlignments; - /// - /// Returns true if any on click events are set. - /// - internal bool ClickEventAssigned => - Clicked != null || RightClicked != null || DoubleClicked != null || DoubleRightClicked != null; + /// + /// Returns true if any on click events are set. + /// + internal bool ClickEventAssigned => + Clicked != null || RightClicked != null || DoubleClicked != null || DoubleRightClicked != null; - /// - /// Logical list of children. If InnerPanel is not null, returns InnerPanel's children. - /// - public List Children => mInnerPanel?.Children ?? mChildren; + /// + /// Logical list of children. If InnerPanel is not null, returns InnerPanel's children. + /// + public List Children => mInnerPanel?.Children ?? mChildren; - /// - /// The logical parent. It's usually what you expect, the control you've parented it to. - /// - public Base? Parent + /// + /// The logical parent. It's usually what you expect, the control you've parented it to. + /// + public Base? Parent + { + get => mParent; + set { - get => mParent; - set + if (mParent == value) { - if (mParent == value) - { - return; - } + return; + } - if (mParent != default) - { - OnDetaching(mParent); - } + if (mParent != default) + { + OnDetaching(mParent); + } - mParent?.RemoveChild(this, false); + mParent?.RemoveChild(this, false); - mParent = value; - mActualParent = default; + mParent = value; + mActualParent = default; - mParent?.AddChild(this); - if (mParent != default) - { - OnAttaching(mParent); - } + mParent?.AddChild(this); + if (mParent != default) + { + OnAttaching(mParent); } } + } - public Base Root + public Base Root + { + get { - get + var root = this; + while (root.Parent != default) { - var root = this; - while (root.Parent != default) - { - root = root.Parent; - } - return root; + root = root.Parent; } + return root; } + } - // todo: ParentChanged event? + // todo: ParentChanged event? - /// - /// Dock position. - /// - public Pos Dock + /// + /// Dock position. + /// + public Pos Dock + { + get => mDock; + set { - get => mDock; - set + if (mDock == value) { - if (mDock == value) - { - return; - } + return; + } - mDock = value; + mDock = value; - Invalidate(); - InvalidateParent(); - } + Invalidate(); + InvalidateParent(); } + } - protected bool HasSkin => mSkin != null || (mParent?.HasSkin ?? false); + protected bool HasSkin => mSkin != null || (mParent?.HasSkin ?? false); - /// - /// Current skin. - /// - public Skin.Base Skin + /// + /// Current skin. + /// + public Skin.Base Skin + { + get { - get + if (mSkin != null) { - if (mSkin != null) - { - return mSkin; - } - - if (mParent != null) - { - return mParent.Skin; - } + return mSkin; + } - throw new InvalidOperationException("GetSkin: null"); + if (mParent != null) + { + return mParent.Skin; } + + throw new InvalidOperationException("GetSkin: null"); } + } - /// - /// Current tooltip. - /// - public Base ToolTip + /// + /// Current tooltip. + /// + public Base ToolTip + { + get => mToolTip; + set { - get => mToolTip; - set + mToolTip = value; + if (mToolTip != null) { - mToolTip = value; - if (mToolTip != null) - { - mToolTip.Parent = this; - mToolTip.IsHidden = true; - } + mToolTip.Parent = this; + mToolTip.IsHidden = true; } } + } - /// - /// Indicates whether this control is a menu component. - /// - internal virtual bool IsMenuComponent + /// + /// Indicates whether this control is a menu component. + /// + internal virtual bool IsMenuComponent + { + get { - get + if (mParent == null) { - if (mParent == null) - { - return false; - } - - return mParent.IsMenuComponent; + return false; } + + return mParent.IsMenuComponent; } + } - /// - /// Determines whether the control should be clipped to its bounds while rendering. - /// - protected virtual bool ShouldClip => true; + /// + /// Determines whether the control should be clipped to its bounds while rendering. + /// + protected virtual bool ShouldClip => true; - /// - /// Current padding - inner spacing. - /// - public Padding Padding + /// + /// Current padding - inner spacing. + /// + public Padding Padding + { + get => mPadding; + set { - get => mPadding; - set + if (mPadding == value) { - if (mPadding == value) - { - return; - } - - mPadding = value; - Invalidate(); - InvalidateParent(); + return; } + + mPadding = value; + Invalidate(); + InvalidateParent(); } + } - /// - /// Alignment Distance - Minimum distance from parent edges when processing alignments. - /// - public Padding AlignmentDistance + /// + /// Alignment Distance - Minimum distance from parent edges when processing alignments. + /// + public Padding AlignmentDistance + { + get => mAlignmentDistance; + set { - get => mAlignmentDistance; - set + if (mAlignmentDistance == value) { - if (mAlignmentDistance == value) - { - return; - } - - mAlignmentDistance = value; - Invalidate(); - InvalidateParent(); + return; } + + mAlignmentDistance = value; + Invalidate(); + InvalidateParent(); } + } - /// - /// Current padding - inner spacing. - /// - public Color RenderColor + /// + /// Current padding - inner spacing. + /// + public Color RenderColor + { + get => mColor; + set { - get => mColor; - set + if (mColor == value) { - if (mColor == value) - { - return; - } - - mColor = value; - Invalidate(); - InvalidateParent(); + return; } + + mColor = value; + Invalidate(); + InvalidateParent(); } + } - /// - /// Current margin - outer spacing. - /// - public Margin Margin + /// + /// Current margin - outer spacing. + /// + public Margin Margin + { + get => mMargin; + set { - get => mMargin; - set + if (mMargin == value) { - if (mMargin == value) - { - return; - } - - mMargin = value; - Invalidate(); - InvalidateParent(); + return; } + + mMargin = value; + Invalidate(); + InvalidateParent(); } + } - /// - /// Indicates whether the control is on top of its parent's children. - /// - public virtual bool IsOnTop + /// + /// Indicates whether the control is on top of its parent's children. + /// + public virtual bool IsOnTop - // todo: validate - => this == Parent.mChildren.First(); + // todo: validate + => this == Parent.mChildren.First(); - /// - /// User data associated with the control. - /// - public object UserData - { - get => mUserData; - set => mUserData = value; - } + /// + /// User data associated with the control. + /// + public object UserData + { + get => mUserData; + set => mUserData = value; + } - /// - /// Indicates whether the control is hovered by mouse pointer. - /// - public virtual bool IsHovered => InputHandler.HoveredControl == this; + /// + /// Indicates whether the control is hovered by mouse pointer. + /// + public virtual bool IsHovered => InputHandler.HoveredControl == this; - /// - /// Indicates whether the control has focus. - /// - public bool HasFocus => InputHandler.KeyboardFocus == this; + /// + /// Indicates whether the control has focus. + /// + public bool HasFocus => InputHandler.KeyboardFocus == this; - /// - /// Indicates whether the control is disabled. - /// - public virtual bool IsDisabled + /// + /// Indicates whether the control is disabled. + /// + public virtual bool IsDisabled + { + get => (_inheritParentEnablementProperties && Parent != default) ? Parent.IsDisabled : mDisabled; + set { - get => (_inheritParentEnablementProperties && Parent != default) ? Parent.IsDisabled : mDisabled; - set + if (value == mDisabled) { - if (value == mDisabled) - { - return; - } - - if (_inheritParentEnablementProperties) - { - mDisabled = Parent?.IsDisabled ?? value; - } - else - { - mDisabled = value; - } + return; + } - Invalidate(); + if (_inheritParentEnablementProperties) + { + mDisabled = Parent?.IsDisabled ?? value; } + else + { + mDisabled = value; + } + + Invalidate(); } + } - /// - /// Indicates whether the control is hidden. - /// - public virtual bool IsHidden + /// + /// Indicates whether the control is hidden. + /// + public virtual bool IsHidden + { + get => (_inheritParentEnablementProperties && Parent != default) ? Parent.IsHidden : mHidden; + set { - get => (_inheritParentEnablementProperties && Parent != default) ? Parent.IsHidden : mHidden; - set + if (value == mHidden) { - if (value == mHidden) - { - return; - } - - if (_inheritParentEnablementProperties) - { - mHidden = Parent?.IsHidden ?? value; - } - else - { - mHidden = value; - } + return; + } - Invalidate(); - InvalidateParent(); + if (_inheritParentEnablementProperties) + { + mHidden = Parent?.IsHidden ?? value; + } + else + { + mHidden = value; } - } - public virtual bool IsHiddenByTree => mHidden || (Parent?.IsHidden ?? false); + Invalidate(); + InvalidateParent(); + } + } - public virtual bool IsDisabledByTree => mDisabled || (Parent?.IsDisabled ?? false); + public virtual bool IsHiddenByTree => mHidden || (Parent?.IsHidden ?? false); - /// - /// Determines whether the control's position should be restricted to parent's bounds. - /// - public bool RestrictToParent - { - get => mRestrictToParent; - set => mRestrictToParent = value; - } + public virtual bool IsDisabledByTree => mDisabled || (Parent?.IsDisabled ?? false); - /// - /// Determines whether the control receives mouse input events. - /// - public bool MouseInputEnabled - { - get => mMouseInputEnabled; - set => mMouseInputEnabled = value; - } + /// + /// Determines whether the control's position should be restricted to parent's bounds. + /// + public bool RestrictToParent + { + get => mRestrictToParent; + set => mRestrictToParent = value; + } - /// - /// Determines whether the control receives keyboard input events. - /// - public bool KeyboardInputEnabled - { - get => mKeyboardInputEnabled; - set => mKeyboardInputEnabled = value; - } + /// + /// Determines whether the control receives mouse input events. + /// + public bool MouseInputEnabled + { + get => mMouseInputEnabled; + set => mMouseInputEnabled = value; + } - /// - /// Gets or sets the mouse cursor when the cursor is hovering the control. - /// - public Cursor Cursor - { - get => mCursor; - set => mCursor = value; - } + /// + /// Determines whether the control receives keyboard input events. + /// + public bool KeyboardInputEnabled + { + get => mKeyboardInputEnabled; + set => mKeyboardInputEnabled = value; + } - public int GlobalX => X + (Parent?.GlobalX ?? 0); + /// + /// Gets or sets the mouse cursor when the cursor is hovering the control. + /// + public Cursor Cursor + { + get => mCursor; + set => mCursor = value; + } - public int GlobalY => Y + (Parent?.GlobalY ?? 0); + public int GlobalX => X + (Parent?.GlobalX ?? 0); - public Point PositionGlobal => new Point(X, Y) + (Parent?.PositionGlobal ?? Point.Empty); + public int GlobalY => Y + (Parent?.GlobalY ?? 0); - public Rectangle BoundsGlobal => new Rectangle(PositionGlobal, Width, Height); + public Point PositionGlobal => new Point(X, Y) + (Parent?.PositionGlobal ?? Point.Empty); - /// - /// Indicates whether the control is tabable (can be focused by pressing Tab). - /// - public bool IsTabable - { - get => mTabable; - set => mTabable = value; - } + public Rectangle BoundsGlobal => new Rectangle(PositionGlobal, Width, Height); - /// - /// Indicates whether control's background should be drawn during rendering. - /// - public bool ShouldDrawBackground - { - get => mDrawBackground; - set => mDrawBackground = value; - } + /// + /// Indicates whether the control is tabable (can be focused by pressing Tab). + /// + public bool IsTabable + { + get => mTabable; + set => mTabable = value; + } - /// - /// Indicates whether the renderer should cache drawing to a texture to improve performance (at the cost of memory). - /// - public bool ShouldCacheToTexture - { - get => mCacheToTexture; - set => mCacheToTexture = value; - } + /// + /// Indicates whether control's background should be drawn during rendering. + /// + public bool ShouldDrawBackground + { + get => mDrawBackground; + set => mDrawBackground = value; + } - /// - /// Gets the control's internal canonical name. - /// - public string CanonicalName => mParent == null ? Name : mParent.Name + "." + Name; + /// + /// Indicates whether the renderer should cache drawing to a texture to improve performance (at the cost of memory). + /// + public bool ShouldCacheToTexture + { + get => mCacheToTexture; + set => mCacheToTexture = value; + } - /// - /// Gets or sets the control's internal name. - /// - public string Name - { - get => mName; - set => mName = value; - } + /// + /// Gets the control's internal canonical name. + /// + public string CanonicalName => mParent == null ? Name : mParent.Name + "." + Name; - /// - /// Control's size and position relative to the parent. - /// - public Rectangle Bounds => mBounds; + /// + /// Gets or sets the control's internal name. + /// + public string Name + { + get => mName; + set => mName = value; + } - /// - /// Bounds for the renderer. - /// - public Rectangle RenderBounds => mRenderBounds; + /// + /// Control's size and position relative to the parent. + /// + public Rectangle Bounds => mBounds; - /// - /// Bounds adjusted by padding. - /// - public Rectangle InnerBounds => mInnerBounds; + /// + /// Bounds for the renderer. + /// + public Rectangle RenderBounds => mRenderBounds; - /// - /// Size restriction. - /// - public Point MinimumSize - { - get => mMinimumSize; - set => mMinimumSize = value; - } + /// + /// Bounds adjusted by padding. + /// + public Rectangle InnerBounds => mInnerBounds; - /// - /// Size restriction. - /// - public Point MaximumSize - { - get => mMaximumSize; - set - { - mMaximumSize = value; - if (mInnerPanel != null) - { - mInnerPanel.MaximumSize = value; - } + /// + /// Size restriction. + /// + public Point MinimumSize + { + get => mMinimumSize; + set => mMinimumSize = value; + } + + /// + /// Size restriction. + /// + public Point MaximumSize + { + get => mMaximumSize; + set + { + mMaximumSize = value; + if (mInnerPanel != null) + { + mInnerPanel.MaximumSize = value; } } + } - /// - /// Determines whether hover should be drawn during rendering. - /// - protected bool ShouldDrawHover => InputHandler.MouseFocus == this || InputHandler.MouseFocus == null; + /// + /// Determines whether hover should be drawn during rendering. + /// + protected bool ShouldDrawHover => InputHandler.MouseFocus == this || InputHandler.MouseFocus == null; - protected virtual bool AccelOnlyFocus => false; + protected virtual bool AccelOnlyFocus => false; - protected virtual bool NeedsInputChars => false; + protected virtual bool NeedsInputChars => false; - /// - /// Indicates whether the control and its parents are visible. - /// - public bool IsVisible + /// + /// Indicates whether the control and its parents are visible. + /// + public bool IsVisible + { + get { - get + if (IsHidden) { - if (IsHidden) - { - return false; - } - - return Parent == null || Parent.IsVisible; + return false; } - set => IsHidden = !value; - } - /// - /// Leftmost coordinate of the control. - /// - public int X - { - get => mBounds.X; - set => SetPosition(value, Y); + return Parent == null || Parent.IsVisible; } + set => IsHidden = !value; + } - /// - /// Topmost coordinate of the control. - /// - public int Y - { - get => mBounds.Y; - set => SetPosition(X, value); - } + /// + /// Leftmost coordinate of the control. + /// + public int X + { + get => mBounds.X; + set => SetPosition(value, Y); + } - // todo: Bottom/Right includes margin but X/Y not? + /// + /// Topmost coordinate of the control. + /// + public int Y + { + get => mBounds.Y; + set => SetPosition(X, value); + } - public int Width - { - get => mBounds.Width; - set => SetSize(value, Height); - } + // todo: Bottom/Right includes margin but X/Y not? - public int Height - { - get => mBounds.Height; - set => SetSize(Width, value); - } + public int Width + { + get => mBounds.Width; + set => SetSize(value, Height); + } + + public int Height + { + get => mBounds.Height; + set => SetSize(Width, value); + } - public int InnerWidth => mBounds.Width - (mPadding.Left + mPadding.Right); + public int InnerWidth => mBounds.Width - (mPadding.Left + mPadding.Right); - public int InnerHeight => mBounds.Height - (mPadding.Top + mPadding.Bottom); + public int InnerHeight => mBounds.Height - (mPadding.Top + mPadding.Bottom); - public int Bottom => mBounds.Bottom + mMargin.Bottom; + public int Bottom => mBounds.Bottom + mMargin.Bottom; - public int Right => mBounds.Right + mMargin.Right; + public int Right => mBounds.Right + mMargin.Right; - /// - /// Determines whether margin, padding and bounds outlines for the control will be drawn. Applied recursively to all - /// children. - /// - public bool DrawDebugOutlines + /// + /// Determines whether margin, padding and bounds outlines for the control will be drawn. Applied recursively to all + /// children. + /// + public bool DrawDebugOutlines + { + get => mDrawDebugOutlines; + set { - get => mDrawDebugOutlines; - set + mDrawDebugOutlines = value; + foreach (var child in Children) { - mDrawDebugOutlines = value; - foreach (var child in Children) - { - child.DrawDebugOutlines = value; - } + child.DrawDebugOutlines = value; } } + } - public Color PaddingOutlineColor { get; set; } + public Color PaddingOutlineColor { get; set; } - public Color MarginOutlineColor { get; set; } + public Color MarginOutlineColor { get; set; } - public Color BoundsOutlineColor { get; set; } + public Color BoundsOutlineColor { get; set; } - /// - /// Gets the canvas (root parent) of the control. - /// - /// - public Canvas? Canvas => GetCanvas(); + /// + /// Gets the canvas (root parent) of the control. + /// + /// + public Canvas? Canvas => GetCanvas(); - public bool SkipSerialization { get; set; } = false; + public bool SkipSerialization { get; set; } = false; - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public virtual void Dispose() + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public virtual void Dispose() + { + ////debug.print("Control.Base: Disposing {0} {1:X}", this, GetHashCode()); + if (mDisposed) { - ////debug.print("Control.Base: Disposing {0} {1:X}", this, GetHashCode()); - if (mDisposed) - { - return; - } + return; + } - ICacheToTexture cache = default; + ICacheToTexture cache = default; #pragma warning disable CA1031 // Do not catch general exception types - try - { - cache = Skin.Renderer.Ctt; - } - catch - { - // If this fails it's because mSkin and mParent.Skin are null, we couldn't care less - } + try + { + cache = Skin.Renderer.Ctt; + } + catch + { + // If this fails it's because mSkin and mParent.Skin are null, we couldn't care less + } #pragma warning restore CA1031 // Do not catch general exception types - if (ShouldCacheToTexture && cache != null) - { - cache.DisposeCachedTexture(this); - } + if (ShouldCacheToTexture && cache != null) + { + cache.DisposeCachedTexture(this); + } - if (InputHandler.HoveredControl == this) - { - InputHandler.HoveredControl = null; - } + if (InputHandler.HoveredControl == this) + { + InputHandler.HoveredControl = null; + } - if (InputHandler.KeyboardFocus == this) - { - InputHandler.KeyboardFocus = null; - } + if (InputHandler.KeyboardFocus == this) + { + InputHandler.KeyboardFocus = null; + } - if (InputHandler.MouseFocus == this) - { - InputHandler.MouseFocus = null; - } + if (InputHandler.MouseFocus == this) + { + InputHandler.MouseFocus = null; + } - DragAndDrop.ControlDeleted(this); - Gwen.ToolTip.ControlDeleted(this); - Animation.Cancel(this); + DragAndDrop.ControlDeleted(this); + Gwen.ToolTip.ControlDeleted(this); + Animation.Cancel(this); - mChildren?.ForEach(child => child?.Dispose()); - mChildren?.Clear(); + mChildren?.ForEach(child => child?.Dispose()); + mChildren?.Clear(); - mInnerPanel?.Dispose(); + mInnerPanel?.Dispose(); - mDisposed = true; - GC.SuppressFinalize(this); - } + mDisposed = true; + GC.SuppressFinalize(this); + } - /// - /// Invoked before this control is drawn - /// - public event GwenEventHandler BeforeDraw; + /// + /// Invoked before this control is drawn + /// + public event GwenEventHandler BeforeDraw; - /// - /// Invoked after this control is drawn - /// - public event GwenEventHandler AfterDraw; + /// + /// Invoked after this control is drawn + /// + public event GwenEventHandler AfterDraw; - public void AddAlignment(Alignments alignment) + public void AddAlignment(Alignments alignment) + { + if (mAlignments?.Contains(alignment) ?? true) { - if (mAlignments?.Contains(alignment) ?? true) - { - return; - } - - mAlignments.Add(alignment); + return; } - public void RemoveAlignments() - { - mAlignments.Clear(); - } + mAlignments.Add(alignment); + } - public virtual string GetJsonUI(bool isRoot = false) - { - return JsonConvert.SerializeObject(GetJson(isRoot), Formatting.Indented); - } + public void RemoveAlignments() + { + mAlignments.Clear(); + } + + public virtual string GetJsonUI(bool isRoot = false) + { + return JsonConvert.SerializeObject(GetJson(isRoot), Formatting.Indented); + } - public virtual JObject GetJson(bool isRoot = default) + public virtual JObject GetJson(bool isRoot = default) + { + var alignments = new List(); + foreach (var alignment in mAlignments) { - var alignments = new List(); - foreach (var alignment in mAlignments) - { - alignments.Add(alignment.ToString()); - } + alignments.Add(alignment.ToString()); + } - isRoot |= Parent == default; + isRoot |= Parent == default; - var boundsToWrite = isRoot - ? new Rectangle(mBoundsOnDisk.X, mBoundsOnDisk.Y, mBounds.Width, mBounds.Height) - : mBounds; - var o = new JObject( - new JProperty("Bounds", Rectangle.ToString(boundsToWrite)), - new JProperty("Padding", Padding.ToString(mPadding)), - new JProperty("AlignmentEdgeDistances", Padding.ToString(mAlignmentDistance)), - new JProperty("AlignmentTransform", Point.ToString(mAlignmentTransform)), - new JProperty("Margin", Margin.ToString(mMargin)), new JProperty("RenderColor", Color.ToString(mColor)), - new JProperty("Alignments", string.Join(",", alignments.ToArray())), - new JProperty("DrawBackground", mDrawBackground), - new JProperty("MinimumSize", Point.ToString(mMinimumSize)), - new JProperty("MaximumSize", Point.ToString(mMaximumSize)), new JProperty("Disabled", mDisabled), - new JProperty("Hidden", mHidden), new JProperty("RestrictToParent", mRestrictToParent), - new JProperty("MouseInputEnabled", mMouseInputEnabled), new JProperty("HideToolTip", mHideToolTip), - new JProperty("ToolTipBackground", mToolTipBackgroundFilename), - new JProperty("ToolTipFont", mToolTipFontInfo), - new JProperty("ToolTipTextColor", Color.ToString(mToolTipFontColor)) - ); + var boundsToWrite = isRoot + ? new Rectangle(mBoundsOnDisk.X, mBoundsOnDisk.Y, mBounds.Width, mBounds.Height) + : mBounds; + var o = new JObject( + new JProperty("Bounds", Rectangle.ToString(boundsToWrite)), + new JProperty("Padding", Padding.ToString(mPadding)), + new JProperty("AlignmentEdgeDistances", Padding.ToString(mAlignmentDistance)), + new JProperty("AlignmentTransform", Point.ToString(mAlignmentTransform)), + new JProperty("Margin", Margin.ToString(mMargin)), new JProperty("RenderColor", Color.ToString(mColor)), + new JProperty("Alignments", string.Join(",", alignments.ToArray())), + new JProperty("DrawBackground", mDrawBackground), + new JProperty("MinimumSize", Point.ToString(mMinimumSize)), + new JProperty("MaximumSize", Point.ToString(mMaximumSize)), new JProperty("Disabled", mDisabled), + new JProperty("Hidden", mHidden), new JProperty("RestrictToParent", mRestrictToParent), + new JProperty("MouseInputEnabled", mMouseInputEnabled), new JProperty("HideToolTip", mHideToolTip), + new JProperty("ToolTipBackground", mToolTipBackgroundFilename), + new JProperty("ToolTipFont", mToolTipFontInfo), + new JProperty("ToolTipTextColor", Color.ToString(mToolTipFontColor)) + ); - if (HasNamedChildren()) + if (HasNamedChildren()) + { + var children = new JObject(); + foreach (var ctrl in mChildren) { - var children = new JObject(); - foreach (var ctrl in mChildren) + if (!string.IsNullOrEmpty(ctrl.Name) && children[ctrl.Name] == null) { - if (!string.IsNullOrEmpty(ctrl.Name) && children[ctrl.Name] == null) - { - children.Add(ctrl.Name, ctrl.GetJson()); - } + children.Add(ctrl.Name, ctrl.GetJson()); } - - o.Add("Children", children); } - return FixJson(o); + o.Add("Children", children); } - public virtual JObject FixJson(JObject json) - { - var children = json.Property("Children"); - if (children != null) - { - json.Remove("Children"); - json.Add(children); - } + return FixJson(o); + } - return json; + public virtual JObject FixJson(JObject json) + { + var children = json.Property("Children"); + if (children != null) + { + json.Remove("Children"); + json.Add(children); } - public void LoadJsonUi(GameContentManager.UI stage, string resolution, bool saveOutput = true) + return json; + } + + public void LoadJsonUi(GameContentManager.UI stage, string resolution, bool saveOutput = true) + { + if (string.IsNullOrWhiteSpace(Name)) { - if (string.IsNullOrWhiteSpace(Name)) - { - Log.Warn($"Attempted to load layout for nameless {GetType().FullName}"); - return; - } + Log.Warn($"Attempted to load layout for nameless {GetType().FullName}"); + return; + } - _ = GameContentManager.Current?.GetLayout(stage, Name, resolution, false, (rawLayout, cacheHit) => + _ = GameContentManager.Current?.GetLayout(stage, Name, resolution, false, (rawLayout, cacheHit) => + { + if (!string.IsNullOrWhiteSpace(rawLayout)) { - if (!string.IsNullOrWhiteSpace(rawLayout)) + try { - try - { - var obj = JsonConvert.DeserializeObject(rawLayout); + var obj = JsonConvert.DeserializeObject(rawLayout); - if (obj != null) - { - LoadJson(obj, true); - ProcessAlignments(); - } - } - catch (Exception exception) + if (obj != null) { - //Log JSON UI Loading Error - throw new Exception("Error loading json ui for " + CanonicalName, exception); + LoadJson(obj, true); + ProcessAlignments(); } } - - if (!cacheHit && saveOutput) + catch (Exception exception) { - GameContentManager.Current?.SaveUIJson(stage, Name, GetJsonUI(true), resolution); + //Log JSON UI Loading Error + throw new Exception("Error loading json ui for " + CanonicalName, exception); } - }); - } + } + + if (!cacheHit && saveOutput) + { + GameContentManager.Current?.SaveUIJson(stage, Name, GetJsonUI(true), resolution); + } + }); + } - public virtual void LoadJson(JToken obj, bool isRoot = default) + public virtual void LoadJson(JToken obj, bool isRoot = default) + { + if (obj["Alignments"] != null) { - if (obj["Alignments"] != null) + RemoveAlignments(); + var alignments = ((string) obj["Alignments"]).Split(','); + foreach (var alignment in alignments) { - RemoveAlignments(); - var alignments = ((string) obj["Alignments"]).Split(','); - foreach (var alignment in alignments) + switch (alignment.ToLower()) { - switch (alignment.ToLower()) - { - case "top": - AddAlignment(Alignments.Top); + case "top": + AddAlignment(Alignments.Top); - break; + break; - case "bottom": - AddAlignment(Alignments.Bottom); + case "bottom": + AddAlignment(Alignments.Bottom); - break; + break; - case "left": - AddAlignment(Alignments.Left); + case "left": + AddAlignment(Alignments.Left); - break; + break; - case "right": - AddAlignment(Alignments.Right); + case "right": + AddAlignment(Alignments.Right); - break; + break; - case "center": - AddAlignment(Alignments.Center); + case "center": + AddAlignment(Alignments.Center); - break; + break; - case "centerh": - AddAlignment(Alignments.CenterH); + case "centerh": + AddAlignment(Alignments.CenterH); - break; + break; - case "centerv": - AddAlignment(Alignments.CenterV); + case "centerv": + AddAlignment(Alignments.CenterV); - break; - } - } - } - - if (obj["Bounds"] != null) - { - mBoundsOnDisk = Rectangle.FromString((string)obj["Bounds"]); - isRoot = isRoot || Parent == default; - if (isRoot) - { - SetSize(mBoundsOnDisk.Width, mBoundsOnDisk.Height); - } - else - { - SetBounds(mBoundsOnDisk); + break; } } + } - if (obj["Padding"] != null) + if (obj["Bounds"] != null) + { + mBoundsOnDisk = Rectangle.FromString((string)obj["Bounds"]); + isRoot = isRoot || Parent == default; + if (isRoot) { - Padding = Padding.FromString((string) obj["Padding"]); + SetSize(mBoundsOnDisk.Width, mBoundsOnDisk.Height); } - - if (obj["AlignmentEdgeDistances"] != null) + else { - mAlignmentDistance = Padding.FromString((string) obj["AlignmentEdgeDistances"]); + SetBounds(mBoundsOnDisk); } + } - if (obj["AlignmentTransform"] != null) - { - mAlignmentTransform = Point.FromString((string) obj["AlignmentTransform"]); - } + if (obj["Padding"] != null) + { + Padding = Padding.FromString((string) obj["Padding"]); + } - if (obj["Margin"] != null) - { - Margin = Margin.FromString((string) obj["Margin"]); - } + if (obj["AlignmentEdgeDistances"] != null) + { + mAlignmentDistance = Padding.FromString((string) obj["AlignmentEdgeDistances"]); + } - if (obj["RenderColor"] != null) - { - RenderColor = Color.FromString((string) obj["RenderColor"]); - } + if (obj["AlignmentTransform"] != null) + { + mAlignmentTransform = Point.FromString((string) obj["AlignmentTransform"]); + } - if (obj["DrawBackground"] != null) - { - ShouldDrawBackground = (bool) obj["DrawBackground"]; - } + if (obj["Margin"] != null) + { + Margin = Margin.FromString((string) obj["Margin"]); + } - if (obj["MinimumSize"] != null) - { - MinimumSize = Point.FromString((string) obj["MinimumSize"]); - } + if (obj["RenderColor"] != null) + { + RenderColor = Color.FromString((string) obj["RenderColor"]); + } - if (obj["MaximumSize"] != null) - { - MaximumSize = Point.FromString((string) obj["MaximumSize"]); - } + if (obj["DrawBackground"] != null) + { + ShouldDrawBackground = (bool) obj["DrawBackground"]; + } - if (obj["Disabled"] != null) - { - IsDisabled = (bool) obj["Disabled"]; - } + if (obj["MinimumSize"] != null) + { + MinimumSize = Point.FromString((string) obj["MinimumSize"]); + } - if (obj["Hidden"] != null) - { - IsHidden = (bool) obj["Hidden"]; - } + if (obj["MaximumSize"] != null) + { + MaximumSize = Point.FromString((string) obj["MaximumSize"]); + } - if (obj["RestrictToParent"] != null) - { - RestrictToParent = (bool) obj["RestrictToParent"]; - } + if (obj["Disabled"] != null) + { + IsDisabled = (bool) obj["Disabled"]; + } - if (obj["MouseInputEnabled"] != null) - { - MouseInputEnabled = (bool) obj["MouseInputEnabled"]; - } + if (obj["Hidden"] != null) + { + IsHidden = (bool) obj["Hidden"]; + } - if (obj["HideToolTip"] != null && (bool) obj["HideToolTip"]) - { - mHideToolTip = true; - SetToolTipText(null); - } + if (obj["RestrictToParent"] != null) + { + RestrictToParent = (bool) obj["RestrictToParent"]; + } - if (obj["ToolTipBackground"] != null) - { - var fileName = (string) obj["ToolTipBackground"]; - GameTexture texture = null; - if (!string.IsNullOrWhiteSpace(fileName)) - { - texture = GameContentManager.Current?.GetTexture(Framework.Content.TextureType.Gui, fileName); - } + if (obj["MouseInputEnabled"] != null) + { + MouseInputEnabled = (bool) obj["MouseInputEnabled"]; + } - mToolTipBackgroundFilename = fileName; - mToolTipBackgroundImage = texture; - } + if (obj["HideToolTip"] != null && (bool) obj["HideToolTip"]) + { + mHideToolTip = true; + SetToolTipText(null); + } - if (obj["ToolTipFont"] != null && obj["ToolTipFont"].Type != JTokenType.Null) + if (obj["ToolTipBackground"] != null) + { + var fileName = (string) obj["ToolTipBackground"]; + GameTexture texture = null; + if (!string.IsNullOrWhiteSpace(fileName)) { - var fontArr = ((string) obj["ToolTipFont"]).Split(','); - mToolTipFontInfo = (string) obj["ToolTipFont"]; - mToolTipFont = GameContentManager.Current.GetFont(fontArr[0], int.Parse(fontArr[1])); + texture = GameContentManager.Current?.GetTexture(Framework.Content.TextureType.Gui, fileName); } - if (obj["ToolTipTextColor"] != null) - { - mToolTipFontColor = Color.FromString((string) obj["ToolTipTextColor"]); - } + mToolTipBackgroundFilename = fileName; + mToolTipBackgroundImage = texture; + } + + if (obj["ToolTipFont"] != null && obj["ToolTipFont"].Type != JTokenType.Null) + { + var fontArr = ((string) obj["ToolTipFont"]).Split(','); + mToolTipFontInfo = (string) obj["ToolTipFont"]; + mToolTipFont = GameContentManager.Current.GetFont(fontArr[0], int.Parse(fontArr[1])); + } + + if (obj["ToolTipTextColor"] != null) + { + mToolTipFontColor = Color.FromString((string) obj["ToolTipTextColor"]); + } - UpdateToolTipProperties(); - if (HasNamedChildren()) + UpdateToolTipProperties(); + if (HasNamedChildren()) + { + if (obj["Children"] != null) { - if (obj["Children"] != null) + var children = obj["Children"]; + foreach (JProperty tkn in children) { - var children = obj["Children"]; - foreach (JProperty tkn in children) + var name = tkn.Name; + foreach (var ctrl in mChildren) { - var name = tkn.Name; - foreach (var ctrl in mChildren) + if (ctrl.Name == name) { - if (ctrl.Name == name) - { - ctrl.LoadJson(tkn.First); - } + ctrl.LoadJson(tkn.First); } } } } } + } - public virtual void ProcessAlignments() - { - mAlignments?.ForEach( - alignment => + public virtual void ProcessAlignments() + { + mAlignments?.ForEach( + alignment => + { + switch (alignment) { - switch (alignment) - { - case Alignments.Top: - Align.AlignTop(this); + case Alignments.Top: + Align.AlignTop(this); - break; + break; - case Alignments.Bottom: - Align.AlignBottom(this); + case Alignments.Bottom: + Align.AlignBottom(this); - break; + break; - case Alignments.Left: - Align.AlignLeft(this); + case Alignments.Left: + Align.AlignLeft(this); - break; + break; - case Alignments.Right: - Align.AlignRight(this); + case Alignments.Right: + Align.AlignRight(this); - break; + break; - case Alignments.Center: - Align.Center(this); + case Alignments.Center: + Align.Center(this); - break; + break; - case Alignments.CenterH: - Align.CenterHorizontally(this); + case Alignments.CenterH: + Align.CenterHorizontally(this); - break; + break; - case Alignments.CenterV: - Align.CenterVertically(this); + case Alignments.CenterV: + Align.CenterVertically(this); - break; + break; - default: - throw new ArgumentOutOfRangeException(nameof(alignment), alignment, null); - } + default: + throw new ArgumentOutOfRangeException(nameof(alignment), alignment, null); } - ); + } + ); - MoveTo(X + mAlignmentTransform.X, Y + mAlignmentTransform.Y, true); - Children?.ForEach(child => child?.ProcessAlignments()); - } + MoveTo(X + mAlignmentTransform.X, Y + mAlignmentTransform.Y, true); + Children?.ForEach(child => child?.ProcessAlignments()); + } - private bool HasNamedChildren() - { - return mChildren?.Any(ctrl => !string.IsNullOrEmpty(ctrl?.Name)) ?? false; - } + private bool HasNamedChildren() + { + return mChildren?.Any(ctrl => !string.IsNullOrEmpty(ctrl?.Name)) ?? false; + } - /// - /// Invoked when mouse pointer enters the control. - /// - public event GwenEventHandler HoverEnter; + /// + /// Invoked when mouse pointer enters the control. + /// + public event GwenEventHandler HoverEnter; - /// - /// Invoked when mouse pointer leaves the control. - /// - public event GwenEventHandler HoverLeave; + /// + /// Invoked when mouse pointer leaves the control. + /// + public event GwenEventHandler HoverLeave; - /// - /// Invoked when control's bounds have been changed. - /// - public event GwenEventHandler BoundsChanged; + /// + /// Invoked when control's bounds have been changed. + /// + public event GwenEventHandler BoundsChanged; - /// - /// Invoked when the control has been left-clicked. - /// - public virtual event GwenEventHandler Clicked; + /// + /// Invoked when the control has been left-clicked. + /// + public virtual event GwenEventHandler Clicked; - /// - /// Invoked when the control has been double-left-clicked. - /// - public virtual event GwenEventHandler DoubleClicked; + /// + /// Invoked when the control has been double-left-clicked. + /// + public virtual event GwenEventHandler DoubleClicked; - /// - /// Invoked when the control has been right-clicked. - /// - public virtual event GwenEventHandler RightClicked; + /// + /// Invoked when the control has been right-clicked. + /// + public virtual event GwenEventHandler RightClicked; - /// - /// Invoked when the control has been double-right-clicked. - /// - public virtual event GwenEventHandler DoubleRightClicked; + /// + /// Invoked when the control has been double-right-clicked. + /// + public virtual event GwenEventHandler DoubleRightClicked; #if DIAGNOSTIC - ~Base() - { - Log.Debug($"IDisposable object finalized: {GetType()}"); - } + ~Base() + { + Log.Debug($"IDisposable object finalized: {GetType()}"); + } #endif - /// - /// Detaches the control from canvas and adds to the deletion queue (processed in Canvas.DoThink). - /// - public void DelayedDelete() - { - Canvas?.AddDelayedDelete(this); - } - - public override string ToString() - { - if (this is MenuItem) - { - return "[MenuItem: " + (this as MenuItem).Text + "]"; - } - - if (this is Label) - { - return "[Label: " + (this as Label).Text + "]"; - } - - if (this is ControlInternal.Text) - { - return "[Text: " + (this as ControlInternal.Text).String + "]"; - } - - return GetType().ToString(); - } - - /// - /// Gets the canvas (root parent) of the control. - /// - /// - public virtual Canvas? GetCanvas() => mParent?.GetCanvas(); + /// + /// Detaches the control from canvas and adds to the deletion queue (processed in Canvas.DoThink). + /// + public void DelayedDelete() + { + Canvas?.AddDelayedDelete(this); + } - /// - /// Enables the control. - /// - public void Enable() + public override string ToString() + { + if (this is MenuItem) { - IsDisabled = false; + return "[MenuItem: " + (this as MenuItem).Text + "]"; } - /// - /// Disables the control. - /// - public virtual void Disable() + if (this is Label) { - IsDisabled = true; + return "[Label: " + (this as Label).Text + "]"; } - /// - /// Default accelerator handler. - /// - /// Event source. - private void DefaultAcceleratorHandler(Base control, EventArgs args) + if (this is ControlInternal.Text) { - OnAccelerator(); + return "[Text: " + (this as ControlInternal.Text).String + "]"; } - /// - /// Default accelerator handler. - /// - protected virtual void OnAccelerator() - { - } + return GetType().ToString(); + } - /// - /// Hides the control. - /// - public virtual void Hide() - { - IsHidden = true; - } + /// + /// Gets the canvas (root parent) of the control. + /// + /// + public virtual Canvas? GetCanvas() => mParent?.GetCanvas(); - /// - /// Shows the control. - /// - public virtual void Show() - { - IsHidden = false; - } + /// + /// Enables the control. + /// + public void Enable() + { + IsDisabled = false; + } + + /// + /// Disables the control. + /// + public virtual void Disable() + { + IsDisabled = true; + } + + /// + /// Default accelerator handler. + /// + /// Event source. + private void DefaultAcceleratorHandler(Base control, EventArgs args) + { + OnAccelerator(); + } + + /// + /// Default accelerator handler. + /// + protected virtual void OnAccelerator() + { + } + + /// + /// Hides the control. + /// + public virtual void Hide() + { + IsHidden = true; + } + + /// + /// Shows the control. + /// + public virtual void Show() + { + IsHidden = false; + } + + public virtual void ToggleHidden() + { + IsHidden = !IsHidden; + } - public virtual void ToggleHidden() + /// + /// Creates a tooltip for the control. + /// + /// Tooltip text. + public virtual void SetToolTipText(string text) + { + if (mHideToolTip || string.IsNullOrWhiteSpace(text)) { - IsHidden = !IsHidden; + if (this.ToolTip != null && this.ToolTip.Parent != null) + { + this.ToolTip?.Parent.RemoveChild(this.ToolTip, true); + } + this.ToolTip = null; + + return; } - /// - /// Creates a tooltip for the control. - /// - /// Tooltip text. - public virtual void SetToolTipText(string text) + var tooltip = this.ToolTip != null ? (Label)this.ToolTip : new Label(this); + tooltip.Text = text; + tooltip.TextColorOverride = mToolTipFontColor ?? Skin.Colors.TooltipText; + if (mToolTipFont != null) { - if (mHideToolTip || string.IsNullOrWhiteSpace(text)) - { - if (this.ToolTip != null && this.ToolTip.Parent != null) - { - this.ToolTip?.Parent.RemoveChild(this.ToolTip, true); - } - this.ToolTip = null; + tooltip.Font = mToolTipFont; + } - return; - } + tooltip.ToolTipBackground = mToolTipBackgroundImage; + tooltip.Padding = new Padding(5, 3, 5, 3); + tooltip.SizeToContents(); + ToolTip = tooltip; + } - var tooltip = this.ToolTip != null ? (Label)this.ToolTip : new Label(this); - tooltip.Text = text; + protected virtual void UpdateToolTipProperties() + { + if (ToolTip != null && ToolTip is Label tooltip) + { tooltip.TextColorOverride = mToolTipFontColor ?? Skin.Colors.TooltipText; if (mToolTipFont != null) { @@ -1285,2063 +1301,2046 @@ public virtual void SetToolTipText(string text) } tooltip.ToolTipBackground = mToolTipBackgroundImage; - tooltip.Padding = new Padding(5, 3, 5, 3); - tooltip.SizeToContents(); - ToolTip = tooltip; } + } - protected virtual void UpdateToolTipProperties() + /// + /// Invalidates the control's children (relayout/repaint). + /// + /// Determines whether the operation should be carried recursively. + protected virtual void InvalidateChildren(bool recursive = false) + { + for (int i = 0; i < mChildren.Count; i++) { - if (ToolTip != null && ToolTip is Label tooltip) + mChildren[i]?.Invalidate(); + if (recursive) { - tooltip.TextColorOverride = mToolTipFontColor ?? Skin.Colors.TooltipText; - if (mToolTipFont != null) - { - tooltip.Font = mToolTipFont; - } - - tooltip.ToolTipBackground = mToolTipBackgroundImage; + mChildren[i]?.InvalidateChildren(true); } } - /// - /// Invalidates the control's children (relayout/repaint). - /// - /// Determines whether the operation should be carried recursively. - protected virtual void InvalidateChildren(bool recursive = false) + if (mInnerPanel != null) { - for (int i = 0; i < mChildren.Count; i++) + foreach (var child in mInnerPanel.mChildren) { - mChildren[i]?.Invalidate(); + child?.Invalidate(); if (recursive) { - mChildren[i]?.InvalidateChildren(true); - } - } - - if (mInnerPanel != null) - { - foreach (var child in mInnerPanel.mChildren) - { - child?.Invalidate(); - if (recursive) - { - child?.InvalidateChildren(true); - } + child?.InvalidateChildren(true); } } } + } - /// - /// Invalidates the control. - /// - /// - /// Causes layout, repaint, invalidates cached texture. - /// - public virtual void Invalidate() - { - mNeedsLayout = true; - mCacheTextureDirty = true; - } + /// + /// Invalidates the control. + /// + /// + /// Causes layout, repaint, invalidates cached texture. + /// + public virtual void Invalidate() + { + mNeedsLayout = true; + mCacheTextureDirty = true; + } - /// - /// Sends the control to the bottom of paren't visibility stack. - /// - public virtual void SendToBack() + /// + /// Sends the control to the bottom of paren't visibility stack. + /// + public virtual void SendToBack() + { + if (mActualParent == null) { - if (mActualParent == null) - { - return; - } - - if (mActualParent.mChildren.Count == 0) - { - return; - } - - if (mActualParent.mChildren.First() == this) - { - return; - } - - mActualParent.mChildren.Remove(this); - mActualParent.mChildren.Insert(0, this); - - InvalidateParent(); + return; } - /// - /// Brings the control to the top of paren't visibility stack. - /// - public virtual void BringToFront() + if (mActualParent.mChildren.Count == 0) { - if (mParent != null && mParent is Modal modal) - { - modal.BringToFront(); - } - - var last = mActualParent?.mChildren.LastOrDefault(); - if (last == default || last == this) - { - return; - } - - mActualParent.mChildren.Remove(this); - mActualParent.mChildren.Add(this); - InvalidateParent(); - Redraw(); + return; } - public virtual void BringNextToControl(Base child, bool behind) + if (mActualParent.mChildren.First() == this) { - if (null == mActualParent) - { - return; - } - - mActualParent.mChildren.Remove(this); - - // todo: validate - var idx = mActualParent.mChildren.IndexOf(child); - if (idx == mActualParent.mChildren.Count - 1) - { - BringToFront(); - - return; - } - - if (behind) - { - ++idx; - - if (idx == mActualParent.mChildren.Count - 1) - { - BringToFront(); + return; + } - return; - } - } + mActualParent.mChildren.Remove(this); + mActualParent.mChildren.Insert(0, this); - mActualParent.mChildren.Insert(idx, this); - InvalidateParent(); - } + InvalidateParent(); + } - /// - /// Finds the first child that matches the predicate. - /// - /// The delegate that defines the conditions of the element to search for. - /// Whether or not the search will recurse through the element tree. - /// The first element that matches the conditions defined by the specified predicate, if found; otherwise, the default value for type . - public virtual Base Find(Predicate predicate, bool recurse = false) + /// + /// Brings the control to the top of paren't visibility stack. + /// + public virtual void BringToFront() + { + if (mParent != null && mParent is Modal modal) { - var child = mChildren.Find(predicate); - if (child != null) - { - return child; - } - - return recurse - ? mChildren.Select(selectChild => selectChild?.Find(predicate, true)).FirstOrDefault() - : default; + modal.BringToFront(); } - /// - /// Finds all children that match the predicate. - /// - /// The delegate that defines the conditions of the element to search for. - /// Whether or not the search will recurse through the element tree. - /// All elements that matches the conditions defined by the specified predicate. - public virtual IEnumerable FindAll(Predicate predicate, bool recurse = false) + var last = mActualParent?.mChildren.LastOrDefault(); + if (last == default || last == this) { - var children = new List(); - - children.AddRange(mChildren.FindAll(predicate)); + return; + } - if (recurse) - { - children.AddRange(mChildren.SelectMany(selectChild => selectChild?.FindAll(predicate, true))); - } + mActualParent.mChildren.Remove(this); + mActualParent.mChildren.Add(this); + InvalidateParent(); + Redraw(); + } - return children; + public virtual void BringNextToControl(Base child, bool behind) + { + if (null == mActualParent) + { + return; } - /// - /// Finds a child by name. - /// - /// Child name. - /// Determines whether the search should be recursive. - /// Found control or null. - public virtual Base FindChildByName(string name, bool recursive = false) => - Find(child => string.Equals(child?.Name, name)); + mActualParent.mChildren.Remove(this); - /// - /// Attaches specified control as a child of this one. - /// - /// - /// If InnerPanel is not null, it will become the parent. - /// - /// Control to be added as a child. - public virtual void AddChild(Base child) + // todo: validate + var idx = mActualParent.mChildren.IndexOf(child); + if (idx == mActualParent.mChildren.Count - 1) { - if (mInnerPanel != null) - { - mInnerPanel.AddChild(child); - } - else - { - mChildren.Add(child); - child.mActualParent = this; - child.DrawDebugOutlines = DrawDebugOutlines; - } + BringToFront(); - OnChildAdded(child); + return; } - /// - /// Detaches specified control from this one. - /// - /// Child to be removed. - /// Determines whether the child should be disposed (added to delayed delete queue). - public virtual void RemoveChild(Base child, bool dispose) + if (behind) { - // If we removed our innerpanel - // remove our pointer to it - if (mInnerPanel == child) - { - mChildren.Remove(mInnerPanel); - mInnerPanel.DelayedDelete(); - mInnerPanel = null; - - return; - } + ++idx; - if (mInnerPanel != null && mInnerPanel.Children.Contains(child)) + if (idx == mActualParent.mChildren.Count - 1) { - mInnerPanel.RemoveChild(child, dispose); + BringToFront(); return; } - - mChildren.Remove(child); - OnChildRemoved(child); - - if (dispose) - { - child.DelayedDelete(); - } } - /// - /// Removes all children (and disposes them). - /// - public virtual void DeleteAllChildren() - { - // todo: probably shouldn't invalidate after each removal - while (mChildren.Count > 0) - { - RemoveChild(mChildren[0], true); - } - } + mActualParent.mChildren.Insert(idx, this); + InvalidateParent(); + } - protected virtual void OnAttached(Base parent) + /// + /// Finds the first child that matches the predicate. + /// + /// The delegate that defines the conditions of the element to search for. + /// Whether or not the search will recurse through the element tree. + /// The first element that matches the conditions defined by the specified predicate, if found; otherwise, the default value for type . + public virtual Base Find(Predicate predicate, bool recurse = false) + { + var child = mChildren.Find(predicate); + if (child != null) { + return child; } - protected virtual void OnAttaching(Base newParent) - { - } + return recurse + ? mChildren.Select(selectChild => selectChild?.Find(predicate, true)).FirstOrDefault() + : default; + } - protected virtual void OnDetached() - { - } + /// + /// Finds all children that match the predicate. + /// + /// The delegate that defines the conditions of the element to search for. + /// Whether or not the search will recurse through the element tree. + /// All elements that matches the conditions defined by the specified predicate. + public virtual IEnumerable FindAll(Predicate predicate, bool recurse = false) + { + var children = new List(); - protected virtual void OnDetaching(Base oldParent) - { - } + children.AddRange(mChildren.FindAll(predicate)); - /// - /// Handler invoked when a child is added. - /// - /// Child added. - protected virtual void OnChildAdded(Base child) + if (recurse) { - child?.OnAttached(this); - Invalidate(); + children.AddRange(mChildren.SelectMany(selectChild => selectChild?.FindAll(predicate, true))); } - /// - /// Handler invoked when a child is removed. - /// - /// Child removed. - protected virtual void OnChildRemoved(Base child) - { - child?.OnDetached(); - Invalidate(); - } + return children; + } - /// - /// Moves the control by a specific amount. - /// - /// X-axis movement. - /// Y-axis movement. - public virtual void MoveBy(int x, int y) - { - SetBounds(X + x, Y + y, Width, Height); - } + /// + /// Finds a child by name. + /// + /// Child name. + /// Determines whether the search should be recursive. + /// Found control or null. + public virtual Base FindChildByName(string name, bool recursive = false) => + Find(child => string.Equals(child?.Name, name)); - /// - /// Moves the control to a specific point. - /// - /// Target x coordinate. - /// Target y coordinate. - public virtual void MoveTo(float x, float y) + /// + /// Attaches specified control as a child of this one. + /// + /// + /// If InnerPanel is not null, it will become the parent. + /// + /// Control to be added as a child. + public virtual void AddChild(Base child) + { + if (mInnerPanel != null) { - MoveTo((int) x, (int) y); + mInnerPanel.AddChild(child); } - - /// - /// Moves the control to a specific point, clamping on paren't bounds if RestrictToParent is set. - /// - /// Target x coordinate. - /// Target y coordinate. - public virtual void MoveTo(int x, int y, bool aligning = false) + else { - if (RestrictToParent && Parent != null) - { - var parent = Parent; - if (x - Padding.Left - (aligning ? mAlignmentDistance.Left : 0) < parent.Margin.Left) - { - x = parent.Margin.Left + Padding.Left + (aligning ? mAlignmentDistance.Left : 0); - } - - if (y - Padding.Top - (aligning ? mAlignmentDistance.Top : 0) < parent.Margin.Top) - { - y = parent.Margin.Top + Padding.Top + (aligning ? mAlignmentDistance.Top : 0); - } + mChildren.Add(child); + child.mActualParent = this; + child.DrawDebugOutlines = DrawDebugOutlines; + } - if (x + Width + Padding.Right + (aligning ? mAlignmentDistance.Right : 0) > - parent.Width - parent.Margin.Right) - { - x = parent.Width - - parent.Margin.Right - - Width - - Padding.Right - - (aligning ? mAlignmentDistance.Right : 0); - } + OnChildAdded(child); + } - if (y + Height + Padding.Bottom + (aligning ? mAlignmentDistance.Bottom : 0) > - parent.Height - parent.Margin.Bottom) - { - y = parent.Height - - parent.Margin.Bottom - - Height - - Padding.Bottom - - (aligning ? mAlignmentDistance.Bottom : 0); - } - } + /// + /// Detaches specified control from this one. + /// + /// Child to be removed. + /// Determines whether the child should be disposed (added to delayed delete queue). + public virtual void RemoveChild(Base child, bool dispose) + { + // If we removed our innerpanel + // remove our pointer to it + if (mInnerPanel == child) + { + mChildren.Remove(mInnerPanel); + mInnerPanel.DelayedDelete(); + mInnerPanel = null; - SetBounds(x, y, Width, Height); + return; } - /// - /// Sets the control position based on ImagePanel - /// - public virtual void SetPosition(Base _icon) + if (mInnerPanel != null && mInnerPanel.Children.Contains(child)) { - SetPosition((int)_icon.LocalPosToCanvas(new Point(0, 0)).X, (int)_icon.LocalPosToCanvas(new Point(0, 0)).Y); - } + mInnerPanel.RemoveChild(child, dispose); - /// - /// Sets the control position. - /// - /// Target x coordinate. - /// Target y coordinate. - public virtual void SetPosition(float x, float y) - { - SetPosition((int) x, (int) y); + return; } - /// - /// Sets the control position. - /// - /// Target x coordinate. - /// Target y coordinate. - public virtual void SetPosition(int x, int y) - { - SetBounds(x, y, Width, Height); - } + mChildren.Remove(child); + OnChildRemoved(child); - /// - /// Sets the control size. - /// - /// New width. - /// New height. - /// True if bounds changed. - public virtual bool SetSize(int width, int height) + if (dispose) { - return SetBounds(X, Y, width, height); + child.DelayedDelete(); } + } - /// - /// Sets the control bounds. - /// - /// New bounds. - /// True if bounds changed. - public virtual bool SetBounds(Rectangle bounds) + /// + /// Removes all children (and disposes them). + /// + public virtual void DeleteAllChildren() + { + // todo: probably shouldn't invalidate after each removal + while (mChildren.Count > 0) { - return SetBounds(bounds.X, bounds.Y, bounds.Width, bounds.Height); + RemoveChild(mChildren[0], true); } + } - /// - /// Sets the control bounds. - /// - /// X. - /// Y. - /// Width. - /// Height. - /// - /// True if bounds changed. - /// - public virtual bool SetBounds(float x, float y, float width, float height) - { - return SetBounds((int) x, (int) y, (int) width, (int) height); - } + protected virtual void OnAttached(Base parent) + { + } - /// - /// Sets the control bounds. - /// - /// X position. - /// Y position. - /// Width. - /// Height. - /// - /// True if bounds changed. - /// - public virtual bool SetBounds(int x, int y, int width, int height) - { - if (mBounds.X == x && mBounds.Y == y && mBounds.Width == width && mBounds.Height == height) - { - return false; - } + protected virtual void OnAttaching(Base newParent) + { + } - var oldBounds = Bounds; + protected virtual void OnDetached() + { + } - mBounds.X = x; - mBounds.Y = y; + protected virtual void OnDetaching(Base oldParent) + { + } - mBounds.Width = Math.Min(MaximumSize.X, width); - mBounds.Height = Math.Min(MaximumSize.Y, height); + /// + /// Handler invoked when a child is added. + /// + /// Child added. + protected virtual void OnChildAdded(Base child) + { + child?.OnAttached(this); + Invalidate(); + } - OnBoundsChanged(oldBounds); + /// + /// Handler invoked when a child is removed. + /// + /// Child removed. + protected virtual void OnChildRemoved(Base child) + { + child?.OnDetached(); + Invalidate(); + } - if (BoundsChanged != null) - { - BoundsChanged.Invoke(this, EventArgs.Empty); - } + /// + /// Moves the control by a specific amount. + /// + /// X-axis movement. + /// Y-axis movement. + public virtual void MoveBy(int x, int y) + { + SetBounds(X + x, Y + y, Width, Height); + } - return true; - } + /// + /// Moves the control to a specific point. + /// + /// Target x coordinate. + /// Target y coordinate. + public virtual void MoveTo(float x, float y) + { + MoveTo((int) x, (int) y); + } - /// - /// Positions the control inside its parent. - /// - /// Target position. - /// X padding. - /// Y padding. - public virtual void Position(Pos pos, int xPadding = 0, int yPadding = 0) + /// + /// Moves the control to a specific point, clamping on paren't bounds if RestrictToParent is set. + /// + /// Target x coordinate. + /// Target y coordinate. + public virtual void MoveTo(int x, int y, bool aligning = false) + { + if (RestrictToParent && Parent != null) { - // Cache frequently used values. - int parentWidth = Parent.Width; - int parentHeight = Parent.Height; - Padding padding = Parent.Padding; - - // Calculate the new X and Y positions using bitwise operations. - int x = X; - int y = Y; - if ((pos & Pos.Left) != 0) - { - x = padding.Left + xPadding; - } - else if ((pos & Pos.Right) != 0) - { - x = parentWidth - Width - padding.Right - xPadding; - } - else if ((pos & Pos.CenterH) != 0) - { - x = (int)(padding.Left + xPadding + (parentWidth - Width - padding.Left - padding.Right) * 0.5f); - } - - if ((pos & Pos.Top) != 0) - { - y = padding.Top + yPadding; - } - else if ((pos & Pos.Bottom) != 0) - { - y = parentHeight - Height - padding.Bottom - yPadding; - } - else if ((pos & Pos.CenterV) != 0) + var parent = Parent; + if (x - Padding.Left - (aligning ? mAlignmentDistance.Left : 0) < parent.Margin.Left) { - y = (int)(padding.Top + yPadding + (parentHeight - Height - padding.Bottom - padding.Top) * 0.5f); + x = parent.Margin.Left + Padding.Left + (aligning ? mAlignmentDistance.Left : 0); } - // Set the new position. - SetPosition(x, y); - } - - /// - /// Handler invoked when control's bounds change. - /// - /// Old bounds. - protected virtual void OnBoundsChanged(Rectangle oldBounds) - { - //Anything that needs to update on size changes - //Iterate my children and tell them I've changed - // - if (Parent != null) + if (y - Padding.Top - (aligning ? mAlignmentDistance.Top : 0) < parent.Margin.Top) { - Parent.OnChildBoundsChanged(oldBounds, this); + y = parent.Margin.Top + Padding.Top + (aligning ? mAlignmentDistance.Top : 0); } - if (mBounds.Width != oldBounds.Width || mBounds.Height != oldBounds.Height) + if (x + Width + Padding.Right + (aligning ? mAlignmentDistance.Right : 0) > + parent.Width - parent.Margin.Right) { - Invalidate(); + x = parent.Width - + parent.Margin.Right - + Width - + Padding.Right - + (aligning ? mAlignmentDistance.Right : 0); } - Redraw(); - UpdateRenderBounds(); - } - - /// - /// Handler invoked when control's scale changes. - /// - protected virtual void OnScaleChanged() - { - for (int i = 0; i < mChildren.Count; i++) + if (y + Height + Padding.Bottom + (aligning ? mAlignmentDistance.Bottom : 0) > + parent.Height - parent.Margin.Bottom) { - mChildren[i].OnScaleChanged(); + y = parent.Height - + parent.Margin.Bottom - + Height - + Padding.Bottom - + (aligning ? mAlignmentDistance.Bottom : 0); } } - /// - /// Handler invoked when control children's bounds change. - /// - protected virtual void OnChildBoundsChanged(Rectangle oldChildBounds, Base child) - { - } - - /// - /// Renders the control using specified skin. - /// - /// Skin to use. - protected virtual void Render(Skin.Base skin) - { - } + SetBounds(x, y, Width, Height); + } - /// - /// Renders the control to a cache using specified skin. - /// - /// Skin to use. - /// Root parent. - protected virtual void DoCacheRender(Skin.Base skin, Base master) - { - var renderer = skin?.Renderer; - var cache = renderer?.Ctt; + /// + /// Sets the control position based on ImagePanel + /// + public virtual void SetPosition(Base _icon) + { + SetPosition((int)_icon.LocalPosToCanvas(new Point(0, 0)).X, (int)_icon.LocalPosToCanvas(new Point(0, 0)).Y); + } - // Return early if the cache is not available - if (cache == null) - { - return; - } + /// + /// Sets the control position. + /// + /// Target x coordinate. + /// Target y coordinate. + public virtual void SetPosition(float x, float y) + { + SetPosition((int) x, (int) y); + } - // Save current render offset and clip region - var oldRenderOffset = renderer.RenderOffset; - var oldRegion = renderer.ClipRegion; + /// + /// Sets the control position. + /// + /// Target x coordinate. + /// Target y coordinate. + public virtual void SetPosition(int x, int y) + { + SetBounds(x, y, Width, Height); + } - // Set render offset and clip region based on whether this control is the root parent - if (this != master) - { - renderer.AddRenderOffset(Bounds); - renderer.AddClipRegion(Bounds); - } - else - { - renderer.RenderOffset = Point.Empty; - renderer.ClipRegion = new Rectangle(0, 0, Width, Height); - } + /// + /// Sets the control size. + /// + /// New width. + /// New height. + /// True if bounds changed. + public virtual bool SetSize(int width, int height) + { + return SetBounds(X, Y, width, height); + } - // Render the control and its children if the cache is dirty and the clip region is visible - if (mCacheTextureDirty && renderer.ClipRegionVisible) - { - renderer.StartClip(); + /// + /// Sets the control bounds. + /// + /// New bounds. + /// True if bounds changed. + public virtual bool SetBounds(Rectangle bounds) + { + return SetBounds(bounds.X, bounds.Y, bounds.Width, bounds.Height); + } - // Setup the cache texture if necessary - if (ShouldCacheToTexture) - { - cache.SetupCacheTexture(this); - } + /// + /// Sets the control bounds. + /// + /// X. + /// Y. + /// Width. + /// Height. + /// + /// True if bounds changed. + /// + public virtual bool SetBounds(float x, float y, float width, float height) + { + return SetBounds((int) x, (int) y, (int) width, (int) height); + } - // Render the control - Render(skin); + /// + /// Sets the control bounds. + /// + /// X position. + /// Y position. + /// Width. + /// Height. + /// + /// True if bounds changed. + /// + public virtual bool SetBounds(int x, int y, int width, int height) + { + if (mBounds.X == x && mBounds.Y == y && mBounds.Width == width && mBounds.Height == height) + { + return false; + } - // Render the children (Reverse). - for (int i = 0; i < mChildren.Count; i++) - { - var child = mChildren[i]; - if (!child.IsHidden) - { - child.DoCacheRender(skin, master); - } - } + var oldBounds = Bounds; - // Finish the cache texture if necessary - if (ShouldCacheToTexture) - { - cache.FinishCacheTexture(this); - mCacheTextureDirty = false; - } - } + mBounds.X = x; + mBounds.Y = y; - // Restore the original clip region and render offset - renderer.ClipRegion = oldRegion; - renderer.StartClip(); - renderer.RenderOffset = oldRenderOffset; + mBounds.Width = Math.Min(MaximumSize.X, width); + mBounds.Height = Math.Min(MaximumSize.Y, height); - // Draw the cached control texture if necessary - if (ShouldCacheToTexture) - { - cache.DrawCachedControlTexture(this); - } - } + OnBoundsChanged(oldBounds); - /// - /// Rendering logic implementation. - /// - /// Skin to use. - internal virtual void DoRender(Skin.Base skin) + if (BoundsChanged != null) { - // If this control has a different skin, - // then so does its children. - if (mSkin != null) - { - skin = mSkin; - } + BoundsChanged.Invoke(this, EventArgs.Empty); + } - // Do think - Think(); + return true; + } - var render = skin.Renderer; + /// + /// Positions the control inside its parent. + /// + /// Target position. + /// X padding. + /// Y padding. + public virtual void Position(Pos pos, int xPadding = 0, int yPadding = 0) + { + // Cache frequently used values. + int parentWidth = Parent.Width; + int parentHeight = Parent.Height; + Padding padding = Parent.Padding; - if (render.Ctt != null && ShouldCacheToTexture) - { - DoCacheRender(skin, this); - if (DrawDebugOutlines) - { - RenderDebugOutlinesRecursive(skin); - } - } - else - { - RenderRecursive(skin, Bounds); - if (DrawDebugOutlines) - { - skin.DrawDebugOutlines(this); - } - } + // Calculate the new X and Y positions using bitwise operations. + int x = X; + int y = Y; + if ((pos & Pos.Left) != 0) + { + x = padding.Left + xPadding; } - - internal virtual void RenderDebugOutlinesRecursive(Skin.Base skin) + else if ((pos & Pos.Right) != 0) { - var oldRenderOffset = skin.Renderer.RenderOffset; - skin.Renderer.AddRenderOffset(Bounds); - foreach (var child in mChildren) - { - if (child.IsHidden) - { - continue; - } - - child.RenderDebugOutlinesRecursive(skin); - } - skin.Renderer.RenderOffset = oldRenderOffset; - - skin.DrawDebugOutlines(this); + x = parentWidth - Width - padding.Right - xPadding; } - - /// - /// Recursive rendering logic. - /// - /// Skin to use. - /// Clipping rectangle. - protected virtual void RenderRecursive(Skin.Base skin, Rectangle clipRect) + else if ((pos & Pos.CenterH) != 0) { - if (BeforeDraw != null) - { - BeforeDraw.Invoke(this, EventArgs.Empty); - } - - var render = skin.Renderer; - var oldRenderOffset = render.RenderOffset; - - render.AddRenderOffset(clipRect); - - RenderUnder(skin); - - var oldRegion = render.ClipRegion; + x = (int)(padding.Left + xPadding + (parentWidth - Width - padding.Left - padding.Right) * 0.5f); + } - if (ShouldClip) - { - render.AddClipRegion(clipRect); + if ((pos & Pos.Top) != 0) + { + y = padding.Top + yPadding; + } + else if ((pos & Pos.Bottom) != 0) + { + y = parentHeight - Height - padding.Bottom - yPadding; + } + else if ((pos & Pos.CenterV) != 0) + { + y = (int)(padding.Top + yPadding + (parentHeight - Height - padding.Bottom - padding.Top) * 0.5f); + } - if (!render.ClipRegionVisible) - { - render.RenderOffset = oldRenderOffset; - render.ClipRegion = oldRegion; + // Set the new position. + SetPosition(x, y); + } - return; - } + /// + /// Handler invoked when control's bounds change. + /// + /// Old bounds. + protected virtual void OnBoundsChanged(Rectangle oldBounds) + { + //Anything that needs to update on size changes + //Iterate my children and tell them I've changed + // + if (Parent != null) + { + Parent.OnChildBoundsChanged(oldBounds, this); + } - render.StartClip(); - } + if (mBounds.Width != oldBounds.Width || mBounds.Height != oldBounds.Height) + { + Invalidate(); + } - //Render myself first - Render(skin); + Redraw(); + UpdateRenderBounds(); + } - if (mChildren.Count > 0) - { - //Now render my kids - //For iteration prevents list size changed crash - for (int i = 0; i < mChildren.Count; i++) - { - if (mChildren[i].IsHidden) - { - continue; - } + /// + /// Handler invoked when control's scale changes. + /// + protected virtual void OnScaleChanged() + { + for (int i = 0; i < mChildren.Count; i++) + { + mChildren[i].OnScaleChanged(); + } + } - mChildren[i].DoRender(skin); + /// + /// Handler invoked when control children's bounds change. + /// + protected virtual void OnChildBoundsChanged(Rectangle oldChildBounds, Base child) + { + } - } - } + /// + /// Renders the control using specified skin. + /// + /// Skin to use. + protected virtual void Render(Skin.Base skin) + { + } - render.ClipRegion = oldRegion; - render.StartClip(); - RenderOver(skin); + /// + /// Renders the control to a cache using specified skin. + /// + /// Skin to use. + /// Root parent. + protected virtual void DoCacheRender(Skin.Base skin, Base master) + { + var renderer = skin?.Renderer; + var cache = renderer?.Ctt; - RenderFocus(skin); + // Return early if the cache is not available + if (cache == null) + { + return; + } - render.RenderOffset = oldRenderOffset; + // Save current render offset and clip region + var oldRenderOffset = renderer.RenderOffset; + var oldRegion = renderer.ClipRegion; - if (AfterDraw != null) - { - AfterDraw.Invoke(this, EventArgs.Empty); - } + // Set render offset and clip region based on whether this control is the root parent + if (this != master) + { + renderer.AddRenderOffset(Bounds); + renderer.AddClipRegion(Bounds); + } + else + { + renderer.RenderOffset = Point.Empty; + renderer.ClipRegion = new Rectangle(0, 0, Width, Height); } - /// - /// Sets the control's skin. - /// - /// New skin. - /// Deterines whether to change children skin. - public virtual void SetSkin(Skin.Base skin, bool doChildren = false) + // Render the control and its children if the cache is dirty and the clip region is visible + if (mCacheTextureDirty && renderer.ClipRegionVisible) { - if (mSkin == skin) + renderer.StartClip(); + + // Setup the cache texture if necessary + if (ShouldCacheToTexture) { - return; + cache.SetupCacheTexture(this); } - mSkin = skin; - Invalidate(); - Redraw(); - OnSkinChanged(skin); + // Render the control + Render(skin); - if (doChildren) + // Render the children (Reverse). + for (int i = 0; i < mChildren.Count; i++) { - for (int i = 0; i < mChildren.Count; i++) + var child = mChildren[i]; + if (!child.IsHidden) { - mChildren[i].SetSkin(skin, true); + child.DoCacheRender(skin, master); } } - } - - /// - /// Handler invoked when control's skin changes. - /// - /// New skin. - protected virtual void OnSkinChanged(Skin.Base newSkin) - { - } - /// - /// Handler invoked on mouse wheel event. - /// - /// Scroll delta. - protected virtual bool OnMouseWheeled(int delta) - { - if (mActualParent != null) + // Finish the cache texture if necessary + if (ShouldCacheToTexture) { - return mActualParent.OnMouseWheeled(delta); + cache.FinishCacheTexture(this); + mCacheTextureDirty = false; } - - return false; } - /// - /// Invokes mouse wheeled event (used by input system). - /// - internal bool InputMouseWheeled(int delta) - { - return OnMouseWheeled(delta); - } + // Restore the original clip region and render offset + renderer.ClipRegion = oldRegion; + renderer.StartClip(); + renderer.RenderOffset = oldRenderOffset; - /// - /// Handler invoked on mouse wheel event. - /// - /// Scroll delta. - protected virtual bool OnMouseHWheeled(int delta) + // Draw the cached control texture if necessary + if (ShouldCacheToTexture) { - if (mActualParent != null) - { - return mActualParent.OnMouseHWheeled(delta); - } - - return false; + cache.DrawCachedControlTexture(this); } + } - /// - /// Invokes mouse wheeled event (used by input system). - /// - internal bool InputMouseHWheeled(int delta) + /// + /// Rendering logic implementation. + /// + /// Skin to use. + internal virtual void DoRender(Skin.Base skin) + { + // If this control has a different skin, + // then so does its children. + if (mSkin != null) { - return OnMouseHWheeled(delta); + skin = mSkin; } - /// - /// Handler invoked on mouse moved event. - /// - /// X coordinate. - /// Y coordinate. - /// X change. - /// Y change. - protected virtual void OnMouseMoved(int x, int y, int dx, int dy) - { - } + // Do think + Think(); - /// - /// Invokes mouse moved event (used by input system). - /// - internal void InputMouseMoved(int x, int y, int dx, int dy) - { - OnMouseMoved(x, y, dx, dy); - } + var render = skin.Renderer; - /// - /// Handler invoked on mouse click (left) event. - /// - /// X coordinate. - /// Y coordinate. - /// If set to true mouse button is down. - protected virtual void OnMouseClickedLeft(int x, int y, bool down, bool automated = false) + if (render.Ctt != null && ShouldCacheToTexture) { - if (down && Clicked != null) + DoCacheRender(skin, this); + if (DrawDebugOutlines) { - Clicked(this, new ClickedEventArgs(x, y, down)); + RenderDebugOutlinesRecursive(skin); } } - - /// - /// Invokes left mouse click event (used by input system). - /// - internal void InputMouseClickedLeft(int x, int y, bool down, bool automated = false) + else { - OnMouseClickedLeft(x, y, down, automated); + RenderRecursive(skin, Bounds); + if (DrawDebugOutlines) + { + skin.DrawDebugOutlines(this); + } } + } - /// - /// Handler invoked on mouse click (right) event. - /// - /// X coordinate. - /// Y coordinate. - /// If set to true mouse button is down. - protected virtual void OnMouseClickedRight(int x, int y, bool down) + internal virtual void RenderDebugOutlinesRecursive(Skin.Base skin) + { + var oldRenderOffset = skin.Renderer.RenderOffset; + skin.Renderer.AddRenderOffset(Bounds); + foreach (var child in mChildren) { - if (down && RightClicked != null) + if (child.IsHidden) { - RightClicked(this, new ClickedEventArgs(x, y, down)); + continue; } - } - /// - /// Invokes right mouse click event (used by input system). - /// - internal void InputMouseClickedRight(int x, int y, bool down) - { - OnMouseClickedRight(x, y, down); + child.RenderDebugOutlinesRecursive(skin); } + skin.Renderer.RenderOffset = oldRenderOffset; - /// - /// Handler invoked on mouse double click (left) event. - /// - /// X coordinate. - /// Y coordinate. - protected virtual void OnMouseDoubleClickedLeft(int x, int y) - { - // [omeg] should this be called? - // [halfofastaple] Maybe. Technically, a double click is still technically a single click. However, this shouldn't be called here, and - // Should be called by the event handler. - OnMouseClickedLeft(x, y, true); - - DoubleClicked?.Invoke(this, new ClickedEventArgs(x, y, true)); - } + skin.DrawDebugOutlines(this); + } - /// - /// Invokes left double mouse click event (used by input system). - /// - internal void InputMouseDoubleClickedLeft(int x, int y) + /// + /// Recursive rendering logic. + /// + /// Skin to use. + /// Clipping rectangle. + protected virtual void RenderRecursive(Skin.Base skin, Rectangle clipRect) + { + if (BeforeDraw != null) { - OnMouseDoubleClickedLeft(x, y); + BeforeDraw.Invoke(this, EventArgs.Empty); } - /// - /// Handler invoked on mouse double click (right) event. - /// - /// X coordinate. - /// Y coordinate. - protected virtual void OnMouseDoubleClickedRight(int x, int y) - { - // [halfofastaple] See: OnMouseDoubleClicked for discussion on triggering single clicks in a double click event - OnMouseClickedRight(x, y, true); + var render = skin.Renderer; + var oldRenderOffset = render.RenderOffset; - DoubleRightClicked?.Invoke(this, new ClickedEventArgs(x, y, true)); - } + render.AddRenderOffset(clipRect); - /// - /// Invokes right double mouse click event (used by input system). - /// - internal void InputMouseDoubleClickedRight(int x, int y) - { - OnMouseDoubleClickedRight(x, y); - } + RenderUnder(skin); - /// - /// Handler invoked on mouse cursor entering control's bounds. - /// - protected virtual void OnMouseEntered() + var oldRegion = render.ClipRegion; + + if (ShouldClip) { - if (HoverEnter != null) - { - HoverEnter.Invoke(this, EventArgs.Empty); - } + render.AddClipRegion(clipRect); - if (ToolTip != null) - { - Gwen.ToolTip.Enable(this); - } - else if (Parent != null && Parent.ToolTip != null) + if (!render.ClipRegionVisible) { - Gwen.ToolTip.Enable(Parent); + render.RenderOffset = oldRenderOffset; + render.ClipRegion = oldRegion; + + return; } - Redraw(); + render.StartClip(); } - protected void PlaySound(string filename) - { - if (filename == null || this.IsDisabled) - { - return; - } + //Render myself first + Render(skin); - filename = GameContentManager.RemoveExtension(filename).ToLower(); - var sound = GameContentManager.Current.GetSound(filename); - if (sound != null) + if (mChildren.Count > 0) + { + //Now render my kids + //For iteration prevents list size changed crash + for (int i = 0; i < mChildren.Count; i++) { - var soundInstance = sound.CreateInstance(); - if (soundInstance != null) + if (mChildren[i].IsHidden) { - Canvas.PlayAndAddSound(soundInstance); + continue; } + + mChildren[i].DoRender(skin); + } } - /// - /// Invokes mouse enter event (used by input system). - /// - internal void InputMouseEntered() - { - OnMouseEntered(); - } + render.ClipRegion = oldRegion; + render.StartClip(); + RenderOver(skin); - /// - /// Handler invoked on mouse cursor leaving control's bounds. - /// - protected virtual void OnMouseLeft() - { - if (HoverLeave != null) - { - HoverLeave.Invoke(this, EventArgs.Empty); - } + RenderFocus(skin); - if (ToolTip != null) - { - Gwen.ToolTip.Disable(this); - } - else if (Parent != null && Parent.ToolTip != null) - { - Gwen.ToolTip.Disable(Parent); - } + render.RenderOffset = oldRenderOffset; - Redraw(); + if (AfterDraw != null) + { + AfterDraw.Invoke(this, EventArgs.Empty); } + } - /// - /// Invokes mouse leave event (used by input system). - /// - internal void InputMouseLeft() + /// + /// Sets the control's skin. + /// + /// New skin. + /// Deterines whether to change children skin. + public virtual void SetSkin(Skin.Base skin, bool doChildren = false) + { + if (mSkin == skin) { - OnMouseLeft(); + return; } - /// - /// Focuses the control. - /// - public virtual void Focus(bool moveMouse = false) + mSkin = skin; + Invalidate(); + Redraw(); + OnSkinChanged(skin); + + if (doChildren) { - if (InputHandler.KeyboardFocus == this) + for (int i = 0; i < mChildren.Count; i++) { - return; - } - - if (InputHandler.KeyboardFocus != null) - { - InputHandler.KeyboardFocus.OnLostKeyboardFocus(); - } - - if (moveMouse) - { - InputHandler.Focus(FocusSource.Keyboard, this); - } - else - { - InputHandler.KeyboardFocus = this; - } - - OnKeyboardFocus(); - Redraw(); - } - - /// - /// Unfocuses the control. - /// - public virtual void Blur() - { - if (InputHandler.KeyboardFocus != this) - { - return; + mChildren[i].SetSkin(skin, true); } - - InputHandler.KeyboardFocus = null; - OnLostKeyboardFocus(); - Redraw(); } + } - /// - /// Control has been clicked - invoked by input system. Windows use it to propagate activation. - /// - public virtual void Touch() - { - if (Parent != null) - { - Parent.OnChildTouched(this); - } - } + /// + /// Handler invoked when control's skin changes. + /// + /// New skin. + protected virtual void OnSkinChanged(Skin.Base newSkin) + { + } - protected virtual void OnChildTouched(Base control) + /// + /// Handler invoked on mouse wheel event. + /// + /// Scroll delta. + protected virtual bool OnMouseWheeled(int delta) + { + if (mActualParent != null) { - Touch(); + return mActualParent.OnMouseWheeled(delta); } - /// - /// Gets a child by its coordinates. - /// - /// Child X. - /// Child Y. - /// Control or null if not found. - public virtual Base GetControlAt(int x, int y) - { - // Return null if control is hidden or coordinates are outside the control's bounds. - if (IsHidden || x < 0 || y < 0 || x >= Width || y >= Height) - { - return null; - } - - // Check children in reverse order (last added first). - for (int i = mChildren.Count - 1; i >= 0; i--) - { - var child = mChildren[i]; - var found = child.GetControlAt(x - child.X, y - child.Y); - if (found != null) - { - return found; - } - } - - // Return control if it is mouse input enabled, otherwise return null. - return MouseInputEnabled ? this : null; - } + return false; + } - public virtual Base GetControlAt(Point point) => GetControlAt(point.X, point.Y); + /// + /// Invokes mouse wheeled event (used by input system). + /// + internal bool InputMouseWheeled(int delta) + { + return OnMouseWheeled(delta); + } - /// - /// Lays out the control's interior according to alignment, padding, dock etc. - /// - /// Skin to use. - protected virtual void Layout(Skin.Base skin) + /// + /// Handler invoked on mouse wheel event. + /// + /// Scroll delta. + protected virtual bool OnMouseHWheeled(int delta) + { + if (mActualParent != null) { - if (skin?.Renderer.Ctt != null && ShouldCacheToTexture) - { - skin.Renderer.Ctt.CreateControlCacheTexture(this); - } + return mActualParent.OnMouseHWheeled(delta); } - /// - /// Recursively lays out the control's interior according to alignment, margin, padding, dock etc. - /// - /// Skin to use. - protected virtual void RecurseLayout(Skin.Base skin) - { - if (mSkin != null) - { - skin = mSkin; - } - - if (IsHidden) - { - return; - } - - if (mNeedsLayout) - { - mNeedsLayout = false; - Layout(skin); - } - - var bounds = RenderBounds; - - // Adjust bounds for padding - bounds.X += mPadding.Left; - bounds.Width -= mPadding.Left + mPadding.Right; - bounds.Y += mPadding.Top; - bounds.Height -= mPadding.Top + mPadding.Bottom; - - for (int i = 0; i < mChildren.Count; i++) - { - if (mChildren[i].IsHidden) - { - continue; - } - - var dock = mChildren[i].Dock; - - if (dock.HasFlag(Pos.Fill)) - { - continue; - } - - if (dock.HasFlag(Pos.Top)) - { - var margin = mChildren[i].Margin; - - mChildren[i].SetBounds( - bounds.X + margin.Left, bounds.Y + margin.Top, bounds.Width - margin.Left - margin.Right, - mChildren[i].Height - ); - - var height = margin.Top + margin.Bottom + mChildren[i].Height; - bounds.Y += height; - bounds.Height -= height; - } - - if (dock.HasFlag(Pos.Left)) - { - var margin = mChildren[i].Margin; - - mChildren[i].SetBounds( - bounds.X + margin.Left, bounds.Y + margin.Top, mChildren[i].Width, - bounds.Height - margin.Top - margin.Bottom - ); - - var width = margin.Left + margin.Right + mChildren[i].Width; - bounds.X += width; - bounds.Width -= width; - } - - if (dock.HasFlag(Pos.Right)) - { - // TODO: THIS MARGIN CODE MIGHT NOT BE FULLY FUNCTIONAL - var margin = mChildren[i].Margin; - - mChildren[i].SetBounds( - bounds.X + bounds.Width - mChildren[i].Width - margin.Right, bounds.Y + margin.Top, mChildren[i].Width, - bounds.Height - margin.Top - margin.Bottom - ); + return false; + } - var width = margin.Left + margin.Right + mChildren[i].Width; - bounds.Width -= width; - } + /// + /// Invokes mouse wheeled event (used by input system). + /// + internal bool InputMouseHWheeled(int delta) + { + return OnMouseHWheeled(delta); + } - if (dock.HasFlag(Pos.Bottom)) - { - // TODO: THIS MARGIN CODE MIGHT NOT BE FULLY FUNCTIONAL - var margin = mChildren[i].Margin; + /// + /// Handler invoked on mouse moved event. + /// + /// X coordinate. + /// Y coordinate. + /// X change. + /// Y change. + protected virtual void OnMouseMoved(int x, int y, int dx, int dy) + { + } - mChildren[i].SetBounds( - bounds.X + margin.Left, bounds.Y + bounds.Height - mChildren[i].Height - margin.Bottom, - bounds.Width - margin.Left - margin.Right, mChildren[i].Height - ); + /// + /// Invokes mouse moved event (used by input system). + /// + internal void InputMouseMoved(int x, int y, int dx, int dy) + { + OnMouseMoved(x, y, dx, dy); + } - bounds.Height -= mChildren[i].Height + margin.Bottom + margin.Top; - } + /// + /// Handler invoked on mouse click (left) event. + /// + /// X coordinate. + /// Y coordinate. + /// If set to true mouse button is down. + protected virtual void OnMouseClickedLeft(int x, int y, bool down, bool automated = false) + { + if (down && Clicked != null) + { + Clicked(this, new ClickedEventArgs(x, y, down)); + } + } - mChildren[i].RecurseLayout(skin); - } + /// + /// Invokes left mouse click event (used by input system). + /// + internal void InputMouseClickedLeft(int x, int y, bool down, bool automated = false) + { + OnMouseClickedLeft(x, y, down, automated); + } - mInnerBounds = bounds; + /// + /// Handler invoked on mouse click (right) event. + /// + /// X coordinate. + /// Y coordinate. + /// If set to true mouse button is down. + protected virtual void OnMouseClickedRight(int x, int y, bool down) + { + if (down && RightClicked != null) + { + RightClicked(this, new ClickedEventArgs(x, y, down)); + } + } - // - // Fill uses the left over space, so do that now. - // - for (int i = 0; i < mChildren.Count; i++) - { - var dock = mChildren[i].Dock; + /// + /// Invokes right mouse click event (used by input system). + /// + internal void InputMouseClickedRight(int x, int y, bool down) + { + OnMouseClickedRight(x, y, down); + } - if (!dock.HasFlag(Pos.Fill)) - { - continue; - } + /// + /// Handler invoked on mouse double click (left) event. + /// + /// X coordinate. + /// Y coordinate. + protected virtual void OnMouseDoubleClickedLeft(int x, int y) + { + // [omeg] should this be called? + // [halfofastaple] Maybe. Technically, a double click is still technically a single click. However, this shouldn't be called here, and + // Should be called by the event handler. + OnMouseClickedLeft(x, y, true); - var margin = mChildren[i].Margin; + DoubleClicked?.Invoke(this, new ClickedEventArgs(x, y, true)); + } - mChildren[i].SetBounds( - bounds.X + margin.Left, bounds.Y + margin.Top, bounds.Width - margin.Left - margin.Right, - bounds.Height - margin.Top - margin.Bottom - ); + /// + /// Invokes left double mouse click event (used by input system). + /// + internal void InputMouseDoubleClickedLeft(int x, int y) + { + OnMouseDoubleClickedLeft(x, y); + } - mChildren[i].RecurseLayout(skin); - } + /// + /// Handler invoked on mouse double click (right) event. + /// + /// X coordinate. + /// Y coordinate. + protected virtual void OnMouseDoubleClickedRight(int x, int y) + { + // [halfofastaple] See: OnMouseDoubleClicked for discussion on triggering single clicks in a double click event + OnMouseClickedRight(x, y, true); - PostLayout(skin); + DoubleRightClicked?.Invoke(this, new ClickedEventArgs(x, y, true)); + } - var canvas = GetCanvas(); - // ReSharper disable once InvertIf - if (canvas != default) - { - if (IsTabable && !canvas._tabQueue.Contains(this)) - { - canvas._tabQueue.AddLast(this); - } + /// + /// Invokes right double mouse click event (used by input system). + /// + internal void InputMouseDoubleClickedRight(int x, int y) + { + OnMouseDoubleClickedRight(x, y); + } - if (InputHandler.KeyboardFocus == this && !canvas._tabQueue.Contains(this)) - { - canvas._tabQueue.AddLast(this); - } - } + /// + /// Handler invoked on mouse cursor entering control's bounds. + /// + protected virtual void OnMouseEntered() + { + if (HoverEnter != null) + { + HoverEnter.Invoke(this, EventArgs.Empty); } - /// - /// Checks if the given control is a child of this instance. - /// - /// Control to examine. - /// True if the control is out child. - public bool IsChild(Base child) + if (ToolTip != null) { - return mChildren.Contains(child); + Gwen.ToolTip.Enable(this); } - - /// - /// Converts local coordinates to canvas coordinates. - /// - /// Local coordinates. - /// Canvas coordinates. - public virtual Point LocalPosToCanvas(Point pnt) + else if (Parent != null && Parent.ToolTip != null) { - if (mParent == null) - { - return pnt; - } - - var x = pnt.X + X; - var y = pnt.Y + Y; + Gwen.ToolTip.Enable(Parent); + } - // If our parent has an innerpanel and we're a child of it - // add its offset onto us. - if (mParent.mInnerPanel != null && mParent.mInnerPanel.IsChild(this)) - { - x += mParent.mInnerPanel.X; - y += mParent.mInnerPanel.Y; - } + Redraw(); + } - return mParent.LocalPosToCanvas(new Point(x, y)); + protected void PlaySound(string filename) + { + if (filename == null || this.IsDisabled) + { + return; } - /// - /// Converts canvas coordinates to local coordinates. - /// - /// Canvas coordinates. - /// Local coordinates. - public virtual Point CanvasPosToLocal(Point pnt) + filename = GameContentManager.RemoveExtension(filename).ToLower(); + var sound = GameContentManager.Current.GetSound(filename); + if (sound != null) { - if (mParent == null) + var soundInstance = sound.CreateInstance(); + if (soundInstance != null) { - return pnt; + Canvas.PlayAndAddSound(soundInstance); } + } + } - var x = pnt.X - X; - var y = pnt.Y - Y; - - // If our parent has an innerpanel and we're a child of it - // add its offset onto us. - if (mParent.mInnerPanel != null && mParent.mInnerPanel.IsChild(this)) - { - x -= mParent.mInnerPanel.X; - y -= mParent.mInnerPanel.Y; - } + /// + /// Invokes mouse enter event (used by input system). + /// + internal void InputMouseEntered() + { + OnMouseEntered(); + } - return mParent.CanvasPosToLocal(new Point(x, y)); + /// + /// Handler invoked on mouse cursor leaving control's bounds. + /// + protected virtual void OnMouseLeft() + { + if (HoverLeave != null) + { + HoverLeave.Invoke(this, EventArgs.Empty); } - /// - /// Closes all menus recursively. - /// - public virtual void CloseMenus() + if (ToolTip != null) { - ////debug.print("Base.CloseMenus: {0}", this); - - // todo: not very efficient with the copying and recursive closing, maybe store currently open menus somewhere (canvas)? - var childrenCopy = mChildren.FindAll(x => true); - foreach (var child in childrenCopy) - { - child.CloseMenus(); - } + Gwen.ToolTip.Disable(this); } - - /// - /// Copies Bounds to RenderBounds. - /// - protected virtual void UpdateRenderBounds() + else if (Parent != null && Parent.ToolTip != null) { - mRenderBounds.X = 0; - mRenderBounds.Y = 0; - - mRenderBounds.Width = mBounds.Width; - mRenderBounds.Height = mBounds.Height; + Gwen.ToolTip.Disable(Parent); } - /// - /// Sets mouse cursor to current cursor. - /// - public virtual void UpdateCursor() + Redraw(); + } + + /// + /// Invokes mouse leave event (used by input system). + /// + internal void InputMouseLeft() + { + OnMouseLeft(); + } + + /// + /// Focuses the control. + /// + public virtual void Focus(bool moveMouse = false) + { + if (InputHandler.KeyboardFocus == this) { - Platform.Neutral.SetCursor(mCursor); + return; } - // giver - public virtual Package DragAndDrop_GetPackage(int x, int y) + if (InputHandler.KeyboardFocus != null) { - return mDragAndDrop_package; + InputHandler.KeyboardFocus.OnLostKeyboardFocus(); } - // giver - public virtual bool DragAndDrop_Draggable() + if (moveMouse) { - if (mDragAndDrop_package == null) - { - return false; - } - - return mDragAndDrop_package.IsDraggable; + InputHandler.Focus(FocusSource.Keyboard, this); } - - // giver - public virtual void DragAndDrop_SetPackage(bool draggable, string name = "", object userData = null) + else { - if (mDragAndDrop_package == null) - { - mDragAndDrop_package = new Package(); - mDragAndDrop_package.IsDraggable = draggable; - mDragAndDrop_package.Name = name; - mDragAndDrop_package.UserData = userData; - } + InputHandler.KeyboardFocus = this; } - // giver - public virtual bool DragAndDrop_ShouldStartDrag() + OnKeyboardFocus(); + Redraw(); + } + + /// + /// Unfocuses the control. + /// + public virtual void Blur() + { + if (InputHandler.KeyboardFocus != this) { - return true; + return; } - // giver - public virtual void DragAndDrop_StartDragging(Package package, int x, int y) + InputHandler.KeyboardFocus = null; + OnLostKeyboardFocus(); + Redraw(); + } + + /// + /// Control has been clicked - invoked by input system. Windows use it to propagate activation. + /// + public virtual void Touch() + { + if (Parent != null) { - package.HoldOffset = CanvasPosToLocal(new Point(x, y)); - package.DrawControl = this; + Parent.OnChildTouched(this); } + } - // giver - public virtual void DragAndDrop_EndDragging(bool success, int x, int y) + protected virtual void OnChildTouched(Base control) + { + Touch(); + } + + /// + /// Gets a child by its coordinates. + /// + /// Child X. + /// Child Y. + /// Control or null if not found. + public virtual Base GetControlAt(int x, int y) + { + // Return null if control is hidden or coordinates are outside the control's bounds. + if (IsHidden || x < 0 || y < 0 || x >= Width || y >= Height) { + return null; } - // receiver - public virtual bool DragAndDrop_HandleDrop(Package p, int x, int y) + // Check children in reverse order (last added first). + for (int i = mChildren.Count - 1; i >= 0; i--) { - DragAndDrop.SourceControl.Parent = this; - - return true; + var child = mChildren[i]; + var found = child.GetControlAt(x - child.X, y - child.Y); + if (found != null) + { + return found; + } } - // receiver - public virtual void DragAndDrop_HoverEnter(Package p, int x, int y) + // Return control if it is mouse input enabled, otherwise return null. + return MouseInputEnabled ? this : null; + } + + public virtual Base GetControlAt(Point point) => GetControlAt(point.X, point.Y); + + /// + /// Lays out the control's interior according to alignment, padding, dock etc. + /// + /// Skin to use. + protected virtual void Layout(Skin.Base skin) + { + if (skin?.Renderer.Ctt != null && ShouldCacheToTexture) { + skin.Renderer.Ctt.CreateControlCacheTexture(this); } + } - // receiver - public virtual void DragAndDrop_HoverLeave(Package p) + /// + /// Recursively lays out the control's interior according to alignment, margin, padding, dock etc. + /// + /// Skin to use. + protected virtual void RecurseLayout(Skin.Base skin) + { + if (mSkin != null) { + skin = mSkin; } - // receiver - public virtual void DragAndDrop_Hover(Package p, int x, int y) + if (IsHidden) { + return; } - // receiver - public virtual bool DragAndDrop_CanAcceptPackage(Package p) + if (mNeedsLayout) { - return false; + mNeedsLayout = false; + Layout(skin); } - /// - /// Resizes the control to fit its children. - /// - /// Determines whether to change control's width. - /// Determines whether to change control's height. - /// True if bounds changed. - public virtual bool SizeToChildren(bool width = true, bool height = true) - { - var size = GetChildrenSize(); - size.X += Padding.Right; - size.Y += Padding.Bottom; + var bounds = RenderBounds; - return SetSize(width ? size.X : Width, height ? size.Y : Height); - } + // Adjust bounds for padding + bounds.X += mPadding.Left; + bounds.Width -= mPadding.Left + mPadding.Right; + bounds.Y += mPadding.Top; + bounds.Height -= mPadding.Top + mPadding.Bottom; - /// - /// Returns the total width and height of all children. - /// - /// - /// Default implementation returns maximum size of children since the layout is unknown. - /// Implement this in derived compound controls to properly return their size. - /// - /// - public virtual Point GetChildrenSize() + for (int i = 0; i < mChildren.Count; i++) { - var size = Point.Empty; - - for (int i = 0; i < mChildren.Count; i++) + if (mChildren[i].IsHidden) { - if (mChildren[i].IsHidden) - { - continue; - } - - size.X = Math.Max(size.X, mChildren[i].Right); - size.Y = Math.Max(size.Y, mChildren[i].Bottom); + continue; } - return size; - } + var dock = mChildren[i].Dock; - /// - /// Handles keyboard accelerator. - /// - /// Accelerator text. - /// True if handled. - internal virtual bool HandleAccelerator(string accelerator) - { - if (InputHandler.KeyboardFocus == this || !AccelOnlyFocus) + if (dock.HasFlag(Pos.Fill)) { - if (mAccelerators.ContainsKey(accelerator)) - { - mAccelerators[accelerator].Invoke(this, EventArgs.Empty); + continue; + } - return true; - } + if (dock.HasFlag(Pos.Top)) + { + var margin = mChildren[i].Margin; + + mChildren[i].SetBounds( + bounds.X + margin.Left, bounds.Y + margin.Top, bounds.Width - margin.Left - margin.Right, + mChildren[i].Height + ); + + var height = margin.Top + margin.Bottom + mChildren[i].Height; + bounds.Y += height; + bounds.Height -= height; + } + + if (dock.HasFlag(Pos.Left)) + { + var margin = mChildren[i].Margin; + + mChildren[i].SetBounds( + bounds.X + margin.Left, bounds.Y + margin.Top, mChildren[i].Width, + bounds.Height - margin.Top - margin.Bottom + ); + + var width = margin.Left + margin.Right + mChildren[i].Width; + bounds.X += width; + bounds.Width -= width; } - return mChildren.Any(child => child.HandleAccelerator(accelerator)); + if (dock.HasFlag(Pos.Right)) + { + // TODO: THIS MARGIN CODE MIGHT NOT BE FULLY FUNCTIONAL + var margin = mChildren[i].Margin; + + mChildren[i].SetBounds( + bounds.X + bounds.Width - mChildren[i].Width - margin.Right, bounds.Y + margin.Top, mChildren[i].Width, + bounds.Height - margin.Top - margin.Bottom + ); + + var width = margin.Left + margin.Right + mChildren[i].Width; + bounds.Width -= width; + } + + if (dock.HasFlag(Pos.Bottom)) + { + // TODO: THIS MARGIN CODE MIGHT NOT BE FULLY FUNCTIONAL + var margin = mChildren[i].Margin; + + mChildren[i].SetBounds( + bounds.X + margin.Left, bounds.Y + bounds.Height - mChildren[i].Height - margin.Bottom, + bounds.Width - margin.Left - margin.Right, mChildren[i].Height + ); + + bounds.Height -= mChildren[i].Height + margin.Bottom + margin.Top; + } + + mChildren[i].RecurseLayout(skin); } - /// - /// Adds keyboard accelerator. - /// - /// Accelerator text. - /// Handler. - public void AddAccelerator(string accelerator, GwenEventHandler handler) + mInnerBounds = bounds; + + // + // Fill uses the left over space, so do that now. + // + for (int i = 0; i < mChildren.Count; i++) { - accelerator = accelerator.Trim().ToUpperInvariant(); - mAccelerators[accelerator] = handler; + var dock = mChildren[i].Dock; + + if (!dock.HasFlag(Pos.Fill)) + { + continue; + } + + var margin = mChildren[i].Margin; + + mChildren[i].SetBounds( + bounds.X + margin.Left, bounds.Y + margin.Top, bounds.Width - margin.Left - margin.Right, + bounds.Height - margin.Top - margin.Bottom + ); + + mChildren[i].RecurseLayout(skin); } - /// - /// Adds keyboard accelerator with a default handler. - /// - /// Accelerator text. - public void AddAccelerator(string accelerator) + PostLayout(skin); + + var canvas = GetCanvas(); + // ReSharper disable once InvertIf + if (canvas != default) { - mAccelerators[accelerator] = DefaultAcceleratorHandler; + if (IsTabable && !canvas._tabQueue.Contains(this)) + { + canvas._tabQueue.AddLast(this); + } + + if (InputHandler.KeyboardFocus == this && !canvas._tabQueue.Contains(this)) + { + canvas._tabQueue.AddLast(this); + } } + } - /// - /// Function invoked after layout. - /// - /// Skin to use. - protected virtual void PostLayout(Skin.Base skin) + /// + /// Checks if the given control is a child of this instance. + /// + /// Control to examine. + /// True if the control is out child. + public bool IsChild(Base child) + { + return mChildren.Contains(child); + } + + /// + /// Converts local coordinates to canvas coordinates. + /// + /// Local coordinates. + /// Canvas coordinates. + public virtual Point LocalPosToCanvas(Point pnt) + { + if (mParent == null) { + return pnt; } - /// - /// Re-renders the control, invalidates cached texture. - /// - public virtual void Redraw() + var x = pnt.X + X; + var y = pnt.Y + Y; + + // If our parent has an innerpanel and we're a child of it + // add its offset onto us. + if (mParent.mInnerPanel != null && mParent.mInnerPanel.IsChild(this)) { - UpdateColors(); - mCacheTextureDirty = true; - mParent?.Redraw(); + x += mParent.mInnerPanel.X; + y += mParent.mInnerPanel.Y; } - /// - /// Updates control colors. - /// - /// - /// Used in composite controls like lists to differentiate row colors etc. - /// - public virtual void UpdateColors() + return mParent.LocalPosToCanvas(new Point(x, y)); + } + + /// + /// Converts canvas coordinates to local coordinates. + /// + /// Canvas coordinates. + /// Local coordinates. + public virtual Point CanvasPosToLocal(Point pnt) + { + if (mParent == null) { + return pnt; } - /// - /// Invalidates control's parent. - /// - public void InvalidateParent() + var x = pnt.X - X; + var y = pnt.Y - Y; + + // If our parent has an innerpanel and we're a child of it + // add its offset onto us. + if (mParent.mInnerPanel != null && mParent.mInnerPanel.IsChild(this)) { - mParent?.Invalidate(); - mParent?.InvalidateParent(); + x -= mParent.mInnerPanel.X; + y -= mParent.mInnerPanel.Y; } - /// - /// Handler for keyboard events. - /// - /// Key pressed. - /// Indicates whether the key was pressed or released. - /// True if handled. - protected virtual bool OnKeyPressed(Key key, bool down = true) - { - var handled = false; - switch (key) - { - case Key.Tab: - handled = OnKeyTab(down); + return mParent.CanvasPosToLocal(new Point(x, y)); + } - break; + /// + /// Closes all menus recursively. + /// + public virtual void CloseMenus() + { + ////debug.print("Base.CloseMenus: {0}", this); - case Key.Space: - handled = OnKeySpace(down); + // todo: not very efficient with the copying and recursive closing, maybe store currently open menus somewhere (canvas)? + var childrenCopy = mChildren.FindAll(x => true); + foreach (var child in childrenCopy) + { + child.CloseMenus(); + } + } - break; + /// + /// Copies Bounds to RenderBounds. + /// + protected virtual void UpdateRenderBounds() + { + mRenderBounds.X = 0; + mRenderBounds.Y = 0; - case Key.Home: - handled = OnKeyHome(down); + mRenderBounds.Width = mBounds.Width; + mRenderBounds.Height = mBounds.Height; + } - break; + /// + /// Sets mouse cursor to current cursor. + /// + public virtual void UpdateCursor() + { + Platform.Neutral.SetCursor(mCursor); + } - case Key.End: - handled = OnKeyEnd(down); + // giver + public virtual Package DragAndDrop_GetPackage(int x, int y) + { + return mDragAndDrop_package; + } - break; + // giver + public virtual bool DragAndDrop_Draggable() + { + if (mDragAndDrop_package == null) + { + return false; + } - case Key.Return: - handled = OnKeyReturn(down); + return mDragAndDrop_package.IsDraggable; + } - break; + // giver + public virtual void DragAndDrop_SetPackage(bool draggable, string name = "", object userData = null) + { + if (mDragAndDrop_package == null) + { + mDragAndDrop_package = new Package(); + mDragAndDrop_package.IsDraggable = draggable; + mDragAndDrop_package.Name = name; + mDragAndDrop_package.UserData = userData; + } + } - case Key.Backspace: - handled = OnKeyBackspace(down); + // giver + public virtual bool DragAndDrop_ShouldStartDrag() + { + return true; + } - break; + // giver + public virtual void DragAndDrop_StartDragging(Package package, int x, int y) + { + package.HoldOffset = CanvasPosToLocal(new Point(x, y)); + package.DrawControl = this; + } - case Key.Delete: - handled = OnKeyDelete(down); + // giver + public virtual void DragAndDrop_EndDragging(bool success, int x, int y) + { + } - break; + // receiver + public virtual bool DragAndDrop_HandleDrop(Package p, int x, int y) + { + DragAndDrop.SourceControl.Parent = this; - case Key.Right: - handled = OnKeyRight(down); + return true; + } - break; + // receiver + public virtual void DragAndDrop_HoverEnter(Package p, int x, int y) + { + } - case Key.Left: - handled = OnKeyLeft(down); + // receiver + public virtual void DragAndDrop_HoverLeave(Package p) + { + } - break; + // receiver + public virtual void DragAndDrop_Hover(Package p, int x, int y) + { + } - case Key.Up: - handled = OnKeyUp(down); + // receiver + public virtual bool DragAndDrop_CanAcceptPackage(Package p) + { + return false; + } - break; + /// + /// Resizes the control to fit its children. + /// + /// Determines whether to change control's width. + /// Determines whether to change control's height. + /// True if bounds changed. + public virtual bool SizeToChildren(bool width = true, bool height = true) + { + var size = GetChildrenSize(); + size.X += Padding.Right; + size.Y += Padding.Bottom; - case Key.Down: - handled = OnKeyDown(down); + return SetSize(width ? size.X : Width, height ? size.Y : Height); + } - break; + /// + /// Returns the total width and height of all children. + /// + /// + /// Default implementation returns maximum size of children since the layout is unknown. + /// Implement this in derived compound controls to properly return their size. + /// + /// + public virtual Point GetChildrenSize() + { + var size = Point.Empty; - case Key.Escape: - handled = OnKeyEscape(down); + for (int i = 0; i < mChildren.Count; i++) + { + if (mChildren[i].IsHidden) + { + continue; + } - break; + size.X = Math.Max(size.X, mChildren[i].Right); + size.Y = Math.Max(size.Y, mChildren[i].Bottom); + } - case Key.Invalid: - case Key.Shift: - case Key.Control: - case Key.Alt: - case Key.Count: - default: - break; - } + return size; + } - if (handled) + /// + /// Handles keyboard accelerator. + /// + /// Accelerator text. + /// True if handled. + internal virtual bool HandleAccelerator(string accelerator) + { + if (InputHandler.KeyboardFocus == this || !AccelOnlyFocus) + { + if (mAccelerators.ContainsKey(accelerator)) { + mAccelerators[accelerator].Invoke(this, EventArgs.Empty); + return true; } + } - Parent?.OnKeyPressed(key, down); + return mChildren.Any(child => child.HandleAccelerator(accelerator)); + } - return false; + /// + /// Adds keyboard accelerator. + /// + /// Accelerator text. + /// Handler. + public void AddAccelerator(string accelerator, GwenEventHandler handler) + { + accelerator = accelerator.Trim().ToUpperInvariant(); + mAccelerators[accelerator] = handler; + } + + /// + /// Adds keyboard accelerator with a default handler. + /// + /// Accelerator text. + public void AddAccelerator(string accelerator) + { + mAccelerators[accelerator] = DefaultAcceleratorHandler; + } + + /// + /// Function invoked after layout. + /// + /// Skin to use. + protected virtual void PostLayout(Skin.Base skin) + { + } + + /// + /// Re-renders the control, invalidates cached texture. + /// + public virtual void Redraw() + { + UpdateColors(); + mCacheTextureDirty = true; + mParent?.Redraw(); + } + + /// + /// Updates control colors. + /// + /// + /// Used in composite controls like lists to differentiate row colors etc. + /// + public virtual void UpdateColors() + { + } + + /// + /// Invalidates control's parent. + /// + public void InvalidateParent() + { + mParent?.Invalidate(); + mParent?.InvalidateParent(); + } + + /// + /// Handler for keyboard events. + /// + /// Key pressed. + /// Indicates whether the key was pressed or released. + /// True if handled. + protected virtual bool OnKeyPressed(Key key, bool down = true) + { + var handled = false; + switch (key) + { + case Key.Tab: + handled = OnKeyTab(down); + + break; + + case Key.Space: + handled = OnKeySpace(down); + + break; + + case Key.Home: + handled = OnKeyHome(down); + + break; + + case Key.End: + handled = OnKeyEnd(down); + + break; + + case Key.Return: + handled = OnKeyReturn(down); + + break; + + case Key.Backspace: + handled = OnKeyBackspace(down); + + break; + + case Key.Delete: + handled = OnKeyDelete(down); + + break; + + case Key.Right: + handled = OnKeyRight(down); + + break; + + case Key.Left: + handled = OnKeyLeft(down); + + break; + + case Key.Up: + handled = OnKeyUp(down); + + break; + + case Key.Down: + handled = OnKeyDown(down); + + break; + + case Key.Escape: + handled = OnKeyEscape(down); + + break; + + case Key.Invalid: + case Key.Shift: + case Key.Control: + case Key.Alt: + case Key.Count: + default: + break; } - /// - /// Invokes key press event (used by input system). - /// - internal bool InputKeyPressed(Key key, bool down = true) + if (handled) + { + return true; + } + + Parent?.OnKeyPressed(key, down); + + return false; + } + + /// + /// Invokes key press event (used by input system). + /// + internal bool InputKeyPressed(Key key, bool down = true) + { + return OnKeyPressed(key, down); + } + + /// + /// Handler for keyboard events. + /// + /// Key pressed. + /// True if handled. + protected virtual bool OnKeyReleaseed(Key key) + { + return OnKeyPressed(key, false); + } + + /// + /// Handler for Tab keyboard event. + /// + /// Indicates whether the key was pressed or released. + /// True if handled. + protected virtual bool OnKeyTab(bool down, bool shift = false) + { + if (!down) { - return OnKeyPressed(key, down); + return true; } - /// - /// Handler for keyboard events. - /// - /// Key pressed. - /// True if handled. - protected virtual bool OnKeyReleaseed(Key key) + var canvas = GetCanvas(); + if (canvas == default) { - return OnKeyPressed(key, false); + return true; } - /// - /// Handler for Tab keyboard event. - /// - /// Indicates whether the key was pressed or released. - /// True if handled. - protected virtual bool OnKeyTab(bool down, bool shift = false) + Base? next; + lock (canvas._tabQueue) { - if (!down) + var hasValid = canvas._tabQueue.Any( + control => control is { IsDisabledByTree: false, IsHiddenByTree: false } + ); + if (!hasValid) { return true; } - var canvas = GetCanvas(); - if (canvas == default) + var currentFocus = InputHandler.KeyboardFocus; + var last = (shift ? canvas._tabQueue.First : canvas._tabQueue.Last)?.Value; + if (currentFocus != default && canvas._tabQueue.Contains(currentFocus) && currentFocus != last) { - return true; + while (canvas._tabQueue.Last?.Value != currentFocus) + { + next = canvas._tabQueue.First?.Value; + if (next == default) + { + break; + } + + canvas._tabQueue.RemoveFirst(); + canvas._tabQueue.AddLast(next); + } } - Base? next; - lock (canvas._tabQueue) + do { - var hasValid = canvas._tabQueue.Any( - control => control is { IsDisabledByTree: false, IsHiddenByTree: false } - ); - if (!hasValid) + next = (shift ? canvas._tabQueue.Last : canvas._tabQueue.First)?.Value; + if (next == default) { return true; } - var currentFocus = InputHandler.KeyboardFocus; - var last = (shift ? canvas._tabQueue.First : canvas._tabQueue.Last)?.Value; - if (currentFocus != default && canvas._tabQueue.Contains(currentFocus) && currentFocus != last) + if (shift) { - while (canvas._tabQueue.Last?.Value != currentFocus) - { - next = canvas._tabQueue.First?.Value; - if (next == default) - { - break; - } - - canvas._tabQueue.RemoveFirst(); - canvas._tabQueue.AddLast(next); - } + canvas._tabQueue.RemoveLast(); + canvas._tabQueue.AddFirst(next); } - - do + else { - next = (shift ? canvas._tabQueue.Last : canvas._tabQueue.First)?.Value; - if (next == default) - { - return true; - } - - if (shift) - { - canvas._tabQueue.RemoveLast(); - canvas._tabQueue.AddFirst(next); - } - else - { - canvas._tabQueue.RemoveFirst(); - canvas._tabQueue.AddLast(next); - } + canvas._tabQueue.RemoveFirst(); + canvas._tabQueue.AddLast(next); } - while (next.IsHiddenByTree || next.IsDisabledByTree || !next.IsTabable); - } - - if (next is { IsTabable: true, IsDisabledByTree: false, IsHiddenByTree: false }) - { - Console.WriteLine($"Focusing {next.CanonicalName} ({next.GetFullishName()})"); - next.Focus(moveMouse: next is not TextBox); } - - Redraw(); - - return true; + while (next.IsHiddenByTree || next.IsDisabledByTree || !next.IsTabable); } - /// - /// Handler for Space keyboard event. - /// - /// Indicates whether the key was pressed or released. - /// True if handled. - protected virtual bool OnKeySpace(bool down) + if (next is { IsTabable: true, IsDisabledByTree: false, IsHiddenByTree: false }) { - return false; + Console.WriteLine($"Focusing {next.CanonicalName} ({next.GetFullishName()})"); + next.Focus(moveMouse: next is not TextBox); } - /// - /// Handler for Return keyboard event. - /// - /// Indicates whether the key was pressed or released. - /// True if handled. - protected virtual bool OnKeyReturn(bool down) - { - return false; - } + Redraw(); - /// - /// Handler for Backspace keyboard event. - /// - /// Indicates whether the key was pressed or released. - /// True if handled. - protected virtual bool OnKeyBackspace(bool down) - { - return false; - } + return true; + } - /// - /// Handler for Delete keyboard event. - /// - /// Indicates whether the key was pressed or released. - /// True if handled. - protected virtual bool OnKeyDelete(bool down) - { - return false; - } + /// + /// Handler for Space keyboard event. + /// + /// Indicates whether the key was pressed or released. + /// True if handled. + protected virtual bool OnKeySpace(bool down) + { + return false; + } - /// - /// Handler for Right Arrow keyboard event. - /// - /// Indicates whether the key was pressed or released. - /// True if handled. - protected virtual bool OnKeyRight(bool down) - { - return false; - } + /// + /// Handler for Return keyboard event. + /// + /// Indicates whether the key was pressed or released. + /// True if handled. + protected virtual bool OnKeyReturn(bool down) + { + return false; + } - /// - /// Handler for Left Arrow keyboard event. - /// - /// Indicates whether the key was pressed or released. - /// True if handled. - protected virtual bool OnKeyLeft(bool down) - { - return false; - } + /// + /// Handler for Backspace keyboard event. + /// + /// Indicates whether the key was pressed or released. + /// True if handled. + protected virtual bool OnKeyBackspace(bool down) + { + return false; + } - /// - /// Handler for Home keyboard event. - /// - /// Indicates whether the key was pressed or released. - /// True if handled. - protected virtual bool OnKeyHome(bool down) - { - return false; - } + /// + /// Handler for Delete keyboard event. + /// + /// Indicates whether the key was pressed or released. + /// True if handled. + protected virtual bool OnKeyDelete(bool down) + { + return false; + } - /// - /// Handler for End keyboard event. - /// - /// Indicates whether the key was pressed or released. - /// True if handled. - protected virtual bool OnKeyEnd(bool down) - { - return false; - } + /// + /// Handler for Right Arrow keyboard event. + /// + /// Indicates whether the key was pressed or released. + /// True if handled. + protected virtual bool OnKeyRight(bool down) + { + return false; + } - /// - /// Handler for Up Arrow keyboard event. - /// - /// Indicates whether the key was pressed or released. - /// True if handled. - protected virtual bool OnKeyUp(bool down) - { - return false; - } + /// + /// Handler for Left Arrow keyboard event. + /// + /// Indicates whether the key was pressed or released. + /// True if handled. + protected virtual bool OnKeyLeft(bool down) + { + return false; + } - /// - /// Handler for Down Arrow keyboard event. - /// - /// Indicates whether the key was pressed or released. - /// True if handled. - protected virtual bool OnKeyDown(bool down) - { - return false; - } + /// + /// Handler for Home keyboard event. + /// + /// Indicates whether the key was pressed or released. + /// True if handled. + protected virtual bool OnKeyHome(bool down) + { + return false; + } - /// - /// Handler for Escape keyboard event. - /// - /// Indicates whether the key was pressed or released. - /// True if handled. - protected virtual bool OnKeyEscape(bool down) - { - return false; - } + /// + /// Handler for End keyboard event. + /// + /// Indicates whether the key was pressed or released. + /// True if handled. + protected virtual bool OnKeyEnd(bool down) + { + return false; + } - /// - /// Handler for Paste event. - /// - /// Source control. - protected virtual void OnPaste(Base from, EventArgs args) - { - } + /// + /// Handler for Up Arrow keyboard event. + /// + /// Indicates whether the key was pressed or released. + /// True if handled. + protected virtual bool OnKeyUp(bool down) + { + return false; + } - /// - /// Handler for Copy event. - /// - /// Source control. - protected virtual void OnCopy(Base from, EventArgs args) - { - } + /// + /// Handler for Down Arrow keyboard event. + /// + /// Indicates whether the key was pressed or released. + /// True if handled. + protected virtual bool OnKeyDown(bool down) + { + return false; + } - /// - /// Handler for Cut event. - /// - /// Source control. - protected virtual void OnCut(Base from, EventArgs args) - { - } + /// + /// Handler for Escape keyboard event. + /// + /// Indicates whether the key was pressed or released. + /// True if handled. + protected virtual bool OnKeyEscape(bool down) + { + return false; + } - /// - /// Handler for Select All event. - /// - /// Source control. - protected virtual void OnSelectAll(Base from, EventArgs args) - { - } + /// + /// Handler for Paste event. + /// + /// Source control. + protected virtual void OnPaste(Base from, EventArgs args) + { + } - internal void InputCopy(Base from) - { - OnCopy(from, EventArgs.Empty); - } + /// + /// Handler for Copy event. + /// + /// Source control. + protected virtual void OnCopy(Base from, EventArgs args) + { + } - internal void InputPaste(Base from) - { - OnPaste(from, EventArgs.Empty); - } + /// + /// Handler for Cut event. + /// + /// Source control. + protected virtual void OnCut(Base from, EventArgs args) + { + } - internal void InputCut(Base from) - { - OnCut(from, EventArgs.Empty); - } + /// + /// Handler for Select All event. + /// + /// Source control. + protected virtual void OnSelectAll(Base from, EventArgs args) + { + } - internal void InputSelectAll(Base from) - { - OnSelectAll(from, EventArgs.Empty); - } + internal void InputCopy(Base from) + { + OnCopy(from, EventArgs.Empty); + } - /// - /// Renders the focus overlay. - /// - /// Skin to use. - protected virtual void RenderFocus(Skin.Base skin) - { - if (InputHandler.KeyboardFocus != this) - { - return; - } + internal void InputPaste(Base from) + { + OnPaste(from, EventArgs.Empty); + } - if (!IsTabable) - { - return; - } + internal void InputCut(Base from) + { + OnCut(from, EventArgs.Empty); + } - skin.DrawKeyboardHighlight(this, RenderBounds, 3); - } + internal void InputSelectAll(Base from) + { + OnSelectAll(from, EventArgs.Empty); + } - /// - /// Renders under the actual control (shadows etc). - /// - /// Skin to use. - protected virtual void RenderUnder(Skin.Base skin) + /// + /// Renders the focus overlay. + /// + /// Skin to use. + protected virtual void RenderFocus(Skin.Base skin) + { + if (InputHandler.KeyboardFocus != this) { + return; } - /// - /// Renders over the actual control (overlays). - /// - /// Skin to use. - protected virtual void RenderOver(Skin.Base skin) + if (!IsTabable) { + return; } - /// - /// Called during rendering. - /// - public virtual void Think() - { - } + skin.DrawKeyboardHighlight(this, RenderBounds, 3); + } - /// - /// Handler for gaining keyboard focus. - /// - protected virtual void OnKeyboardFocus() - { - } + /// + /// Renders under the actual control (shadows etc). + /// + /// Skin to use. + protected virtual void RenderUnder(Skin.Base skin) + { + } - /// - /// Handler for losing keyboard focus. - /// - protected virtual void OnLostKeyboardFocus() - { - } + /// + /// Renders over the actual control (overlays). + /// + /// Skin to use. + protected virtual void RenderOver(Skin.Base skin) + { + } - /// - /// Handler for character input event. - /// - /// Character typed. - /// True if handled. - protected virtual bool OnChar(Char chr) - { - return false; - } + /// + /// Called during rendering. + /// + public virtual void Think() + { + } - internal bool InputChar(Char chr) - { - return OnChar(chr); - } + /// + /// Handler for gaining keyboard focus. + /// + protected virtual void OnKeyboardFocus() + { + } - public virtual void Anim_WidthIn(float length, float delay = 0.0f, float ease = 1.0f) - { - Animation.Add(this, new Anim.Size.Width(0, Width, length, false, delay, ease)); - Width = 0; - } + /// + /// Handler for losing keyboard focus. + /// + protected virtual void OnLostKeyboardFocus() + { + } - public virtual void Anim_HeightIn(float length, float delay, float ease) - { - Animation.Add(this, new Anim.Size.Height(0, Height, length, false, delay, ease)); - Height = 0; - } + /// + /// Handler for character input event. + /// + /// Character typed. + /// True if handled. + protected virtual bool OnChar(Char chr) + { + return false; + } - public virtual void Anim_WidthOut(float length, bool hide, float delay, float ease) - { - Animation.Add(this, new Anim.Size.Width(Width, 0, length, hide, delay, ease)); - } + internal bool InputChar(Char chr) + { + return OnChar(chr); + } - public virtual void Anim_HeightOut(float length, bool hide, float delay, float ease) - { - Animation.Add(this, new Anim.Size.Height(Height, 0, length, hide, delay, ease)); - } + public virtual void Anim_WidthIn(float length, float delay = 0.0f, float ease = 1.0f) + { + Animation.Add(this, new Anim.Size.Width(0, Width, length, false, delay, ease)); + Width = 0; + } - public void FitChildrenToSize() - { - foreach (var child in Children) - { - //push them back into view if they are outside it - child.X = Math.Min(Bounds.Width, child.X + child.Width) - child.Width; - child.Y = Math.Min(Bounds.Height, child.Y + child.Height) - child.Height; + public virtual void Anim_HeightIn(float length, float delay, float ease) + { + Animation.Add(this, new Anim.Size.Height(0, Height, length, false, delay, ease)); + Height = 0; + } - //Non-negative has priority, so do it second. - child.X = Math.Max(0, child.X); - child.Y = Math.Max(0, child.Y); - } - } + public virtual void Anim_WidthOut(float length, bool hide, float delay, float ease) + { + Animation.Add(this, new Anim.Size.Width(Width, 0, length, hide, delay, ease)); + } - protected bool SetIfChanged(ref T field, T value) + public virtual void Anim_HeightOut(float length, bool hide, float delay, float ease) + { + Animation.Add(this, new Anim.Size.Height(Height, 0, length, hide, delay, ease)); + } + + public void FitChildrenToSize() + { + foreach (var child in Children) { - if (EqualityComparer.Default.Equals(field, value)) - { - return false; - } + //push them back into view if they are outside it + child.X = Math.Min(Bounds.Width, child.X + child.Width) - child.Width; + child.Y = Math.Min(Bounds.Height, child.Y + child.Height) - child.Height; - field = value; - return true; + //Non-negative has priority, so do it second. + child.X = Math.Max(0, child.X); + child.Y = Math.Max(0, child.Y); } + } - protected bool SetIfChanged(ref T field, T value, out T oldValue) + protected bool SetIfChanged(ref T field, T value) + { + if (EqualityComparer.Default.Equals(field, value)) { - oldValue = field; - return SetIfChanged(ref field, value); + return false; } - protected bool SetAndDoIfChanged(ref T field, T value, Action action) - { - if (default == action) - { - throw new ArgumentNullException(nameof(action)); - } + field = value; + return true; + } - if (SetIfChanged(ref field, value)) - { - action(); - return true; - } + protected bool SetIfChanged(ref T field, T value, out T oldValue) + { + oldValue = field; + return SetIfChanged(ref field, value); + } - return false; + protected bool SetAndDoIfChanged(ref T field, T value, Action action) + { + if (default == action) + { + throw new ArgumentNullException(nameof(action)); } - protected bool SetAndDoIfChanged(ref T field, T value, ValueChangedHandler valueChangedHandle) + if (SetIfChanged(ref field, value)) { - if (default == valueChangedHandle) - { - throw new ArgumentNullException(nameof(valueChangedHandle)); - } + action(); + return true; + } - if (SetIfChanged(ref field, value, out var oldValue)) - { - valueChangedHandle(oldValue, field); - return true; - } + return false; + } - return false; + protected bool SetAndDoIfChanged(ref T field, T value, ValueChangedHandler valueChangedHandle) + { + if (default == valueChangedHandle) + { + throw new ArgumentNullException(nameof(valueChangedHandle)); } - } - public delegate void ValueChangedHandler(T oldValue, T newValue); + if (SetIfChanged(ref field, value, out var oldValue)) + { + valueChangedHandle(oldValue, field); + return true; + } + + return false; + } } + +public delegate void ValueChangedHandler(T oldValue, T newValue); diff --git a/Intersect.Client.Framework/Gwen/Control/Button.cs b/Intersect.Client.Framework/Gwen/Control/Button.cs index 2b78747df5..15d074016d 100644 --- a/Intersect.Client.Framework/Gwen/Control/Button.cs +++ b/Intersect.Client.Framework/Gwen/Control/Button.cs @@ -5,592 +5,590 @@ using Newtonsoft.Json.Linq; -namespace Intersect.Client.Framework.Gwen.Control +namespace Intersect.Client.Framework.Gwen.Control; + +public static class ButtonControlStateExtensions { - public static class ButtonControlStateExtensions + public static Label.ControlState ToLabelControlState(this Button.ControlState controlState) { - public static Label.ControlState ToLabelControlState(this Button.ControlState controlState) + return controlState switch { - return controlState switch - { - Button.ControlState.Normal => Label.ControlState.Normal, - Button.ControlState.Hovered => Label.ControlState.Hovered, - Button.ControlState.Clicked => Label.ControlState.Clicked, - Button.ControlState.Disabled => Label.ControlState.Disabled, - _ => throw new ArgumentOutOfRangeException(nameof(controlState), controlState, null), - }; - } + Button.ControlState.Normal => Label.ControlState.Normal, + Button.ControlState.Hovered => Label.ControlState.Hovered, + Button.ControlState.Clicked => Label.ControlState.Clicked, + Button.ControlState.Disabled => Label.ControlState.Disabled, + _ => throw new ArgumentOutOfRangeException(nameof(controlState), controlState, null), + }; } +} - /// - /// Button control. - /// - public partial class Button : Label - { +/// +/// Button control. +/// +public partial class Button : Label +{ - public enum ControlState - { + public enum ControlState + { - Normal = 0, + Normal = 0, - Hovered, + Hovered, - Clicked, + Clicked, - Disabled, + Disabled, - } + } - private bool mCenterImage; + private bool mCenterImage; - private GameTexture mClickedImage; + private GameTexture mClickedImage; - private string mClickedImageFilename; + private string mClickedImageFilename; - protected string mClickSound; + protected string mClickSound; - private bool mDepressed; + private bool mDepressed; - private GameTexture mDisabledImage; + private GameTexture mDisabledImage; - private string mDisabledImageFilename; + private string mDisabledImageFilename; - private GameTexture mHoverImage; + private GameTexture mHoverImage; - private string mHoverImageFilename; + private string mHoverImageFilename; - //Sound Effects - protected string mHoverSound; + //Sound Effects + protected string mHoverSound; - protected string mMouseDownSound; + protected string mMouseDownSound; - protected string mMouseUpSound; + protected string mMouseUpSound; - private GameTexture mNormalImage; + private GameTexture mNormalImage; - private string mNormalImageFilename; + private string mNormalImageFilename; - private bool mToggle; + private bool mToggle; - private bool mToggleStatus; + private bool mToggleStatus; - /// - /// Control constructor. - /// - /// Parent control. - public Button(Base parent, string name = default, bool disableText = false) : base(parent, name, disableText) - { - AutoSizeToContents = false; - SetSize(100, 20); - MouseInputEnabled = true; - Alignment = Pos.Center; - TextPadding = new Padding(3, 3, 3, 3); - Name = name; - } + /// + /// Control constructor. + /// + /// Parent control. + public Button(Base parent, string name = default, bool disableText = false) : base(parent, name, disableText) + { + AutoSizeToContents = false; + SetSize(100, 20); + MouseInputEnabled = true; + Alignment = Pos.Center; + TextPadding = new Padding(3, 3, 3, 3); + Name = name; + } - /// - /// Indicates whether the button is depressed. - /// - public bool IsDepressed + /// + /// Indicates whether the button is depressed. + /// + public bool IsDepressed + { + get => mDepressed; + set { - get => mDepressed; - set + if (mDepressed == value) { - if (mDepressed == value) - { - return; - } - - mDepressed = value; - Redraw(); + return; } - } - - /// - /// Indicates whether the button is toggleable. - /// - public bool IsToggle - { - get => mToggle; - set => mToggle = value; - } - /// - /// Determines the button's toggle state. - /// - public bool ToggleState - { - get => mToggleStatus; - set - { - if (!mToggle) - { - return; - } - - if (mToggleStatus == value) - { - return; - } - - mToggleStatus = value; - - if (Toggled != null) - { - Toggled.Invoke(this, EventArgs.Empty); - } - - if (mToggleStatus) - { - if (ToggledOn != null) - { - ToggledOn.Invoke(this, EventArgs.Empty); - } - } - else - { - if (ToggledOff != null) - { - ToggledOff.Invoke(this, EventArgs.Empty); - } - } - - Redraw(); - } + mDepressed = value; + Redraw(); } + } - /// - /// Invoked when the button is pressed. - /// - public event GwenEventHandler Pressed; - - /// - /// Invoked when the button is released. - /// - public event GwenEventHandler Released; - - /// - /// Invoked when the button's toggle state has changed. - /// - public event GwenEventHandler Toggled; - - /// - /// Invoked when the button's toggle state has changed to On. - /// - public event GwenEventHandler ToggledOn; - - /// - /// Invoked when the button's toggle state has changed to Off. - /// - public event GwenEventHandler ToggledOff; + /// + /// Indicates whether the button is toggleable. + /// + public bool IsToggle + { + get => mToggle; + set => mToggle = value; + } - public override JObject GetJson(bool isRoot = default) + /// + /// Determines the button's toggle state. + /// + public bool ToggleState + { + get => mToggleStatus; + set { - var obj = base.GetJson(isRoot); - if (this.GetType() != typeof(CheckBox)) + if (!mToggle) { - obj.Add("NormalImage", GetImageFilename(ControlState.Normal)); - obj.Add("HoveredImage", GetImageFilename(ControlState.Hovered)); - obj.Add("ClickedImage", GetImageFilename(ControlState.Clicked)); - obj.Add("DisabledImage", GetImageFilename(ControlState.Disabled)); + return; } - obj.Add("CenterImage", mCenterImage); - if (this.GetType() != typeof(ComboBox)) + if (mToggleStatus == value) { - obj.Add("HoverSound", mHoverSound); - obj.Add("MouseUpSound", mMouseUpSound); - obj.Add("MouseDownSound", mMouseDownSound); - obj.Add("ClickSound", mClickSound); + return; } - return base.FixJson(obj); - } + mToggleStatus = value; - public override void LoadJson(JToken obj, bool isRoot = default) - { - base.LoadJson(obj); - if (obj["NormalImage"] != null) + if (Toggled != null) { - SetImage( - GameContentManager.Current.GetTexture( - Framework.Content.TextureType.Gui, (string)obj["NormalImage"] - ), (string)obj["NormalImage"], ControlState.Normal - ); + Toggled.Invoke(this, EventArgs.Empty); } - if (obj["HoveredImage"] != null) + if (mToggleStatus) { - SetImage( - GameContentManager.Current.GetTexture( - Framework.Content.TextureType.Gui, (string)obj["HoveredImage"] - ), (string)obj["HoveredImage"], ControlState.Hovered - ); + if (ToggledOn != null) + { + ToggledOn.Invoke(this, EventArgs.Empty); + } } - - if (obj["ClickedImage"] != null) + else { - SetImage( - GameContentManager.Current.GetTexture( - Framework.Content.TextureType.Gui, (string)obj["ClickedImage"] - ), (string)obj["ClickedImage"], ControlState.Clicked - ); + if (ToggledOff != null) + { + ToggledOff.Invoke(this, EventArgs.Empty); + } } - if (obj["DisabledImage"] != null) - { - SetImage( - GameContentManager.Current.GetTexture( - Framework.Content.TextureType.Gui, (string)obj["DisabledImage"] - ), (string)obj["DisabledImage"], ControlState.Disabled - ); - } + Redraw(); + } + } - if (obj["CenterImage"] != null) - { - mCenterImage = (bool)obj["CenterImage"]; - } + /// + /// Invoked when the button is pressed. + /// + public event GwenEventHandler Pressed; - if (this.GetType() != typeof(ComboBox) && this.GetType() != typeof(CheckBox)) - { - if (obj["HoverSound"] != null) - { - mHoverSound = (string)obj["HoverSound"]; - } + /// + /// Invoked when the button is released. + /// + public event GwenEventHandler Released; - if (obj["MouseUpSound"] != null) - { - mMouseUpSound = (string)obj["MouseUpSound"]; - } + /// + /// Invoked when the button's toggle state has changed. + /// + public event GwenEventHandler Toggled; - if (obj["MouseDownSound"] != null) - { - mMouseDownSound = (string)obj["MouseDownSound"]; - } + /// + /// Invoked when the button's toggle state has changed to On. + /// + public event GwenEventHandler ToggledOn; - if (obj["ClickSound"] != null) - { - mClickSound = (string)obj["ClickSound"]; - } - } - } + /// + /// Invoked when the button's toggle state has changed to Off. + /// + public event GwenEventHandler ToggledOff; - public void PlayHoverSound() + public override JObject GetJson(bool isRoot = default) + { + var obj = base.GetJson(isRoot); + if (this.GetType() != typeof(CheckBox)) { - base.PlaySound(mHoverSound); + obj.Add("NormalImage", GetImageFilename(ControlState.Normal)); + obj.Add("HoveredImage", GetImageFilename(ControlState.Hovered)); + obj.Add("ClickedImage", GetImageFilename(ControlState.Clicked)); + obj.Add("DisabledImage", GetImageFilename(ControlState.Disabled)); } - public void PlayClickSound() + obj.Add("CenterImage", mCenterImage); + if (this.GetType() != typeof(ComboBox)) { - base.PlaySound(mClickSound); + obj.Add("HoverSound", mHoverSound); + obj.Add("MouseUpSound", mMouseUpSound); + obj.Add("MouseDownSound", mMouseDownSound); + obj.Add("ClickSound", mClickSound); } - public void ClearSounds() + return base.FixJson(obj); + } + + public override void LoadJson(JToken obj, bool isRoot = default) + { + base.LoadJson(obj); + if (obj["NormalImage"] != null) { - mMouseUpSound = ""; - mMouseDownSound = ""; - mHoverSound = ""; - mClickSound = ""; + SetImage( + GameContentManager.Current.GetTexture( + Framework.Content.TextureType.Gui, (string)obj["NormalImage"] + ), (string)obj["NormalImage"], ControlState.Normal + ); } - /// - /// Toggles the button. - /// - public virtual void Toggle() + if (obj["HoveredImage"] != null) { - ToggleState = !ToggleState; + SetImage( + GameContentManager.Current.GetTexture( + Framework.Content.TextureType.Gui, (string)obj["HoveredImage"] + ), (string)obj["HoveredImage"], ControlState.Hovered + ); } - /// - /// "Clicks" the button. - /// - public virtual void Press(Base control = null) + if (obj["ClickedImage"] != null) { - OnClicked(0, 0); + SetImage( + GameContentManager.Current.GetTexture( + Framework.Content.TextureType.Gui, (string)obj["ClickedImage"] + ), (string)obj["ClickedImage"], ControlState.Clicked + ); } - /// - /// Renders the control using specified skin. - /// - /// Skin to use. - protected override void Render(Skin.Base skin) + if (obj["DisabledImage"] != null) { - base.Render(skin); - - if (ShouldDrawBackground) - { - var drawDepressed = IsDepressed && IsHovered; - if (IsToggle) - { - drawDepressed = drawDepressed || ToggleState; - } - - var bDrawHovered = IsHovered && ShouldDrawHover; + SetImage( + GameContentManager.Current.GetTexture( + Framework.Content.TextureType.Gui, (string)obj["DisabledImage"] + ), (string)obj["DisabledImage"], ControlState.Disabled + ); + } - skin.DrawButton(this, drawDepressed, bDrawHovered, IsDisabled, HasFocus); - } + if (obj["CenterImage"] != null) + { + mCenterImage = (bool)obj["CenterImage"]; } - /// - /// Handler invoked on mouse click (left) event. - /// - /// X coordinate. - /// Y coordinate. - /// If set to true mouse button is down. - protected override void OnMouseClickedLeft(int x, int y, bool down, bool automated = false) + if (this.GetType() != typeof(ComboBox) && this.GetType() != typeof(CheckBox)) { - //base.OnMouseClickedLeft(x, y, down); - if (down) + if (obj["HoverSound"] != null) { - IsDepressed = true; - InputHandler.MouseFocus = this; - - //Play Mouse Down Sound - base.PlaySound(mMouseDownSound); - if (Pressed != null) - { - Pressed.Invoke(this, EventArgs.Empty); - } + mHoverSound = (string)obj["HoverSound"]; } - else - { - if (IsHovered && mDepressed) - { - //Play Clicked Sound - base.PlaySound(mClickSound); - OnClicked(x, y); - } - //Play Mouse Up Sound - base.PlaySound(mMouseUpSound); - IsDepressed = false; - InputHandler.MouseFocus = null; - if (Released != null) - { - Released.Invoke(this, EventArgs.Empty); - } + if (obj["MouseUpSound"] != null) + { + mMouseUpSound = (string)obj["MouseUpSound"]; } - Redraw(); - } - - /// - /// Internal OnPressed implementation. - /// - protected virtual void OnClicked(int x, int y) - { - if (IsDisabled) + if (obj["MouseDownSound"] != null) { - return; + mMouseDownSound = (string)obj["MouseDownSound"]; } - if (IsToggle) + if (obj["ClickSound"] != null) { - Toggle(); + mClickSound = (string)obj["ClickSound"]; } - - base.OnMouseClickedLeft(x, y, true); } + } - /// - /// Handler for Space keyboard event. - /// - /// Indicates whether the key was pressed or released. - /// - /// True if handled. - /// - protected override bool OnKeySpace(bool down) - { - return base.OnKeySpace(down); + public void PlayHoverSound() + { + base.PlaySound(mHoverSound); + } - //if (down) - // OnClicked(0, 0); - //return true; - } + public void PlayClickSound() + { + base.PlaySound(mClickSound); + } - /// - /// Default accelerator handler. - /// - protected override void OnAccelerator() - { - OnClicked(0, 0); - } + public void ClearSounds() + { + mMouseUpSound = ""; + mMouseDownSound = ""; + mHoverSound = ""; + mClickSound = ""; + } + + /// + /// Toggles the button. + /// + public virtual void Toggle() + { + ToggleState = !ToggleState; + } + + /// + /// "Clicks" the button. + /// + public virtual void Press(Base control = null) + { + OnClicked(0, 0); + } + + /// + /// Renders the control using specified skin. + /// + /// Skin to use. + protected override void Render(Skin.Base skin) + { + base.Render(skin); - /// - /// Lays out the control's interior according to alignment, padding, dock etc. - /// - /// Skin to use. - protected override void Layout(Skin.Base skin) + if (ShouldDrawBackground) { - base.Layout(skin); + var drawDepressed = IsDepressed && IsHovered; + if (IsToggle) + { + drawDepressed = drawDepressed || ToggleState; + } + + var bDrawHovered = IsHovered && ShouldDrawHover; + + skin.DrawButton(this, drawDepressed, bDrawHovered, IsDisabled, HasFocus); } + } - /// - /// Updates control colors. - /// - public override void UpdateColors() + /// + /// Handler invoked on mouse click (left) event. + /// + /// X coordinate. + /// Y coordinate. + /// If set to true mouse button is down. + protected override void OnMouseClickedLeft(int x, int y, bool down, bool automated = false) + { + //base.OnMouseClickedLeft(x, y, down); + if (down) { - var textColor = GetTextColor(Label.ControlState.Normal); - if (IsDisabled && GetTextColor(Label.ControlState.Disabled) != null) + IsDepressed = true; + InputHandler.MouseFocus = this; + + //Play Mouse Down Sound + base.PlaySound(mMouseDownSound); + if (Pressed != null) { - textColor = GetTextColor(Label.ControlState.Disabled); + Pressed.Invoke(this, EventArgs.Empty); } - else if (IsHovered && GetTextColor(Label.ControlState.Hovered) != null) + } + else + { + if (IsHovered && mDepressed) { - textColor = GetTextColor(Label.ControlState.Hovered); + //Play Clicked Sound + base.PlaySound(mClickSound); + OnClicked(x, y); } - if (textColor != null) + //Play Mouse Up Sound + base.PlaySound(mMouseUpSound); + IsDepressed = false; + InputHandler.MouseFocus = null; + if (Released != null) { - TextColor = textColor; - - return; + Released.Invoke(this, EventArgs.Empty); } + } - if (IsDisabled) - { - TextColor = Skin.Colors.Button.Disabled; + Redraw(); + } - return; - } + /// + /// Internal OnPressed implementation. + /// + protected virtual void OnClicked(int x, int y) + { + if (IsDisabled) + { + return; + } - if (IsDepressed || ToggleState) - { - TextColor = Skin.Colors.Button.Down; + if (IsToggle) + { + Toggle(); + } - return; - } + base.OnMouseClickedLeft(x, y, true); + } - if (IsHovered) - { - TextColor = Skin.Colors.Button.Hover; + /// + /// Handler for Space keyboard event. + /// + /// Indicates whether the key was pressed or released. + /// + /// True if handled. + /// + protected override bool OnKeySpace(bool down) + { + return base.OnKeySpace(down); - return; - } + //if (down) + // OnClicked(0, 0); + //return true; + } - TextColor = Skin.Colors.Button.Normal; - } + /// + /// Default accelerator handler. + /// + protected override void OnAccelerator() + { + OnClicked(0, 0); + } + + /// + /// Lays out the control's interior according to alignment, padding, dock etc. + /// + /// Skin to use. + protected override void Layout(Skin.Base skin) + { + base.Layout(skin); + } - /// - /// Handler invoked on mouse double click (left) event. - /// - /// X coordinate. - /// Y coordinate. - protected override void OnMouseDoubleClickedLeft(int x, int y) + /// + /// Updates control colors. + /// + public override void UpdateColors() + { + var textColor = GetTextColor(Label.ControlState.Normal); + if (IsDisabled && GetTextColor(Label.ControlState.Disabled) != null) { - base.OnMouseDoubleClickedLeft(x, y); - OnMouseClickedLeft(x, y, true); + textColor = GetTextColor(Label.ControlState.Disabled); } - - public void SetImage(string textureName, ControlState controlState) + else if (IsHovered && GetTextColor(Label.ControlState.Hovered) != null) { - var texture = GameContentManager.Current.GetTexture(TextureType.Gui, textureName); - SetImage(texture, textureName, controlState); + textColor = GetTextColor(Label.ControlState.Hovered); } - /// - /// Sets the button's image. - /// - /// Texture name. Null to remove. - public void SetImage(GameTexture texture, string fileName, ControlState state) + if (textColor != null) { - if (texture == null && !string.IsNullOrWhiteSpace(fileName)) - { - texture = GameContentManager.Current?.GetTexture(Framework.Content.TextureType.Gui, fileName); - } + TextColor = textColor; - switch (state) - { - case ControlState.Normal: - mNormalImageFilename = fileName; - mNormalImage = texture; - - break; - case ControlState.Hovered: - mHoverImageFilename = fileName; - mHoverImage = texture; - - break; - case ControlState.Clicked: - mClickedImageFilename = fileName; - mClickedImage = texture; - - break; - case ControlState.Disabled: - mDisabledImageFilename = fileName; - mDisabledImage = texture; - - break; - default: - throw new ArgumentOutOfRangeException(nameof(state), state, null); - } + return; } - public GameTexture? GetImage(ControlState state) + if (IsDisabled) { - switch (state) - { - case ControlState.Normal: - return mNormalImage; - case ControlState.Hovered: - return mHoverImage; - case ControlState.Clicked: - return mClickedImage; - case ControlState.Disabled: - return mDisabledImage; - default: - return null; - } + TextColor = Skin.Colors.Button.Disabled; + + return; } - public string GetImageFilename(ControlState state) + if (IsDepressed || ToggleState) { - switch (state) - { - case ControlState.Normal: - return mNormalImageFilename; - case ControlState.Hovered: - return mHoverImageFilename; - case ControlState.Clicked: - return mClickedImageFilename; - case ControlState.Disabled: - return mDisabledImageFilename; - default: - return null; - } + TextColor = Skin.Colors.Button.Down; + + return; } - protected override void OnMouseEntered() + if (IsHovered) { - base.OnMouseEntered(); + TextColor = Skin.Colors.Button.Hover; - //Play Mouse Entered Sound - if (ShouldDrawHover) - { - base.PlaySound(mHoverSound); - } + return; + } + + TextColor = Skin.Colors.Button.Normal; + } + + /// + /// Handler invoked on mouse double click (left) event. + /// + /// X coordinate. + /// Y coordinate. + protected override void OnMouseDoubleClickedLeft(int x, int y) + { + base.OnMouseDoubleClickedLeft(x, y); + OnMouseClickedLeft(x, y, true); + } + + public void SetImage(string textureName, ControlState controlState) + { + var texture = GameContentManager.Current.GetTexture(TextureType.Gui, textureName); + SetImage(texture, textureName, controlState); + } + + /// + /// Sets the button's image. + /// + /// Texture name. Null to remove. + public void SetImage(GameTexture texture, string fileName, ControlState state) + { + if (texture == null && !string.IsNullOrWhiteSpace(fileName)) + { + texture = GameContentManager.Current?.GetTexture(Framework.Content.TextureType.Gui, fileName); } - public void SetHoverSound(string sound) + switch (state) { - mHoverSound = sound; + case ControlState.Normal: + mNormalImageFilename = fileName; + mNormalImage = texture; + + break; + case ControlState.Hovered: + mHoverImageFilename = fileName; + mHoverImage = texture; + + break; + case ControlState.Clicked: + mClickedImageFilename = fileName; + mClickedImage = texture; + + break; + case ControlState.Disabled: + mDisabledImageFilename = fileName; + mDisabledImage = texture; + + break; + default: + throw new ArgumentOutOfRangeException(nameof(state), state, null); } + } - public void SetClickSound(string sound) + public GameTexture? GetImage(ControlState state) + { + switch (state) { - mClickSound = sound; + case ControlState.Normal: + return mNormalImage; + case ControlState.Hovered: + return mHoverImage; + case ControlState.Clicked: + return mClickedImage; + case ControlState.Disabled: + return mDisabledImage; + default: + return null; } + } - public void SetMouseDownSound(string sound) + public string GetImageFilename(ControlState state) + { + switch (state) { - mMouseDownSound = sound; + case ControlState.Normal: + return mNormalImageFilename; + case ControlState.Hovered: + return mHoverImageFilename; + case ControlState.Clicked: + return mClickedImageFilename; + case ControlState.Disabled: + return mDisabledImageFilename; + default: + return null; } + } + + protected override void OnMouseEntered() + { + base.OnMouseEntered(); - public void SetMouseUpSound(string sound) + //Play Mouse Entered Sound + if (ShouldDrawHover) { - mMouseUpSound = sound; + base.PlaySound(mHoverSound); } + } + + public void SetHoverSound(string sound) + { + mHoverSound = sound; + } + public void SetClickSound(string sound) + { + mClickSound = sound; + } + + public void SetMouseDownSound(string sound) + { + mMouseDownSound = sound; + } + + public void SetMouseUpSound(string sound) + { + mMouseUpSound = sound; } } diff --git a/Intersect.Client.Framework/Gwen/Control/Canvas.cs b/Intersect.Client.Framework/Gwen/Control/Canvas.cs index a348f3e120..f4a86dc4b2 100644 --- a/Intersect.Client.Framework/Gwen/Control/Canvas.cs +++ b/Intersect.Client.Framework/Gwen/Control/Canvas.cs @@ -4,440 +4,438 @@ using Intersect.Client.Framework.Gwen.Input; using Intersect.Client.Framework.Audio; -namespace Intersect.Client.Framework.Gwen.Control +namespace Intersect.Client.Framework.Gwen.Control; + + +/// +/// Canvas control. It should be the root parent for all other controls. +/// +public partial class Canvas : Base { + private readonly List mDisposeQueue; // dictionary for faster access? + + private Color mBackgroundColor; + + // [omeg] these are not created by us, so no disposing + internal Base? mFirstTab; + + internal Base? mNextTab; + + internal readonly LinkedList _tabQueue = new(); + + private bool mNeedsRedraw; + + private float mScale; + + private List mUISounds; + /// - /// Canvas control. It should be the root parent for all other controls. + /// Initializes a new instance of the class. /// - public partial class Canvas : Base + /// Skin to use. + public Canvas(Skin.Base skin, string name) : base(null, name) { + mUISounds = new List(); + SetBounds(0, 0, 10000, 10000); + SetSkin(skin); + Scale = 1.0f; + BackgroundColor = Color.White; + ShouldDrawBackground = false; + IsTabable = false; + + mDisposeQueue = new List(); + } - private readonly List mDisposeQueue; // dictionary for faster access? + /// + /// Scale for rendering. + /// + public float Scale + { + get => mScale; + set + { + if (mScale == value) + { + return; + } - private Color mBackgroundColor; + mScale = value; - // [omeg] these are not created by us, so no disposing - internal Base? mFirstTab; + if (Skin != null && Skin.Renderer != null) + { + Skin.Renderer.Scale = mScale; + } - internal Base? mNextTab; + OnScaleChanged(); + Redraw(); + } + } - internal readonly LinkedList _tabQueue = new(); + /// + /// Background color. + /// + public Color BackgroundColor + { + get => mBackgroundColor; + set => mBackgroundColor = value; + } - private bool mNeedsRedraw; + /// + /// In most situations you will be rendering the canvas every frame. + /// But in some situations you will only want to render when there have been changes. + /// You can do this by checking NeedsRedraw. + /// + public bool NeedsRedraw + { + get => mNeedsRedraw; + set => mNeedsRedraw = value; + } - private float mScale; + public override void Dispose() + { + ProcessDelayedDeletes(); + base.Dispose(); + } - private List mUISounds; + /// + /// Re-renders the control, invalidates cached texture. + /// + public override void Redraw() + { + NeedsRedraw = true; + base.Redraw(); + } - /// - /// Initializes a new instance of the class. - /// - /// Skin to use. - public Canvas(Skin.Base skin, string name) : base(null, name) - { - mUISounds = new List(); - SetBounds(0, 0, 10000, 10000); - SetSkin(skin); - Scale = 1.0f; - BackgroundColor = Color.White; - ShouldDrawBackground = false; - IsTabable = false; - - mDisposeQueue = new List(); - } + // Children call parent.GetCanvas() until they get to + // this top level function. + public override Canvas? GetCanvas() + { + return this; + } - /// - /// Scale for rendering. - /// - public float Scale - { - get => mScale; - set - { - if (mScale == value) - { - return; - } + /// + /// Additional initialization (which is sometimes not appropriate in the constructor) + /// + protected void Initialize() + { + } - mScale = value; + /// + /// Renders the canvas. Call in your rendering loop. + /// + public void RenderCanvas() + { + DoThink(); - if (Skin != null && Skin.Renderer != null) - { - Skin.Renderer.Scale = mScale; - } + var render = Skin.Renderer; - OnScaleChanged(); - Redraw(); - } - } + render.Begin(); - /// - /// Background color. - /// - public Color BackgroundColor - { - get => mBackgroundColor; - set => mBackgroundColor = value; - } + RecurseLayout(Skin); - /// - /// In most situations you will be rendering the canvas every frame. - /// But in some situations you will only want to render when there have been changes. - /// You can do this by checking NeedsRedraw. - /// - public bool NeedsRedraw - { - get => mNeedsRedraw; - set => mNeedsRedraw = value; - } + render.ClipRegion = Bounds; - public override void Dispose() - { - ProcessDelayedDeletes(); - base.Dispose(); - } + //render.RenderOffset = new Point(X,Y); + render.Scale = Scale; - /// - /// Re-renders the control, invalidates cached texture. - /// - public override void Redraw() + if (ShouldDrawBackground) { - NeedsRedraw = true; - base.Redraw(); + render.DrawColor = mBackgroundColor; + render.DrawFilledRect(RenderBounds); } - // Children call parent.GetCanvas() until they get to - // this top level function. - public override Canvas? GetCanvas() - { - return this; - } + DoRender(Skin); - /// - /// Additional initialization (which is sometimes not appropriate in the constructor) - /// - protected void Initialize() - { - } + DragAndDrop.RenderOverlay(this, Skin); - /// - /// Renders the canvas. Call in your rendering loop. - /// - public void RenderCanvas() - { - DoThink(); + Gwen.ToolTip.RenderToolTip(Skin); - var render = Skin.Renderer; + render.EndClip(); - render.Begin(); + render.End(); + } - RecurseLayout(Skin); + /// + /// Renders the control using specified skin. + /// + /// Skin to use. + protected override void Render(Skin.Base skin) + { + //skin.Renderer.rnd = new Random(1); + base.Render(skin); + mNeedsRedraw = false; + } - render.ClipRegion = Bounds; + /// + /// Handler invoked when control's bounds change. + /// + /// Old bounds. + protected override void OnBoundsChanged(Rectangle oldBounds) + { + base.OnBoundsChanged(oldBounds); + InvalidateChildren(true); + } - //render.RenderOffset = new Point(X,Y); - render.Scale = Scale; + public void PlayAndAddSound(GameAudioInstance sound) + { + // Track the sound - we will check to see when it's done and dispose of it in DoThink() + mUISounds.Add(sound); + // And play the sound + sound.SetVolume(100, false); + sound.Play(); + } - if (ShouldDrawBackground) + private void RemoveAndDisposeDeadSounds() + { + mUISounds.RemoveAll(item => + { + if (item.State == GameAudioInstance.AudioInstanceState.Stopped || item.State == GameAudioInstance.AudioInstanceState.Disposed) + { + item.Dispose(); + return true; + } + else { - render.DrawColor = mBackgroundColor; - render.DrawFilledRect(RenderBounds); + return false; } + }); + } - DoRender(Skin); + /// + /// Processes input and layout. Also purges delayed delete queue. + /// + private void DoThink() + { + if (IsHidden) + { + return; + } - DragAndDrop.RenderOverlay(this, Skin); + RemoveAndDisposeDeadSounds(); - Gwen.ToolTip.RenderToolTip(Skin); + Animation.GlobalThink(); - render.EndClip(); + // Reset tabbing + mNextTab = null; + mFirstTab = null; - render.End(); - } + ProcessDelayedDeletes(); - /// - /// Renders the control using specified skin. - /// - /// Skin to use. - protected override void Render(Skin.Base skin) - { - //skin.Renderer.rnd = new Random(1); - base.Render(skin); - mNeedsRedraw = false; - } + // Check has focus etc.. + RecurseLayout(Skin); - /// - /// Handler invoked when control's bounds change. - /// - /// Old bounds. - protected override void OnBoundsChanged(Rectangle oldBounds) + // If we didn't have a next tab, cycle to the start. + if (mNextTab == null) { - base.OnBoundsChanged(oldBounds); - InvalidateChildren(true); + mNextTab = mFirstTab; } - public void PlayAndAddSound(GameAudioInstance sound) + InputHandler.OnCanvasThink(this); + } + + /// + /// Adds given control to the delete queue and detaches it from canvas. Don't call from Dispose, it modifies child + /// list. + /// + /// Control to delete. + public void AddDelayedDelete(Base control) + { + if (!mDisposeQueue.Contains(control)) { - // Track the sound - we will check to see when it's done and dispose of it in DoThink() - mUISounds.Add(sound); - // And play the sound - sound.SetVolume(100, false); - sound.Play(); + mDisposeQueue.Add(control); + RemoveChild(control, false); } - - private void RemoveAndDisposeDeadSounds() +#if DEBUG + else { - mUISounds.RemoveAll(item => - { - if (item.State == GameAudioInstance.AudioInstanceState.Stopped || item.State == GameAudioInstance.AudioInstanceState.Disposed) - { - item.Dispose(); - return true; - } - else - { - return false; - } - }); + throw new InvalidOperationException("Control deleted twice"); } +#endif + } - /// - /// Processes input and layout. Also purges delayed delete queue. - /// - private void DoThink() + private void ProcessDelayedDeletes() + { + //if (m_DisposeQueue.Count > 0) + // System.Diagnostics.//debug.print("Canvas.ProcessDelayedDeletes: {0} items", m_DisposeQueue.Count); + foreach (var control in mDisposeQueue) { - if (IsHidden) - { - return; - } - - RemoveAndDisposeDeadSounds(); - - Animation.GlobalThink(); - - // Reset tabbing - mNextTab = null; - mFirstTab = null; + control.Dispose(); + } - ProcessDelayedDeletes(); + mDisposeQueue.Clear(); + } - // Check has focus etc.. - RecurseLayout(Skin); + /// + /// Handles mouse movement events. Called from Input subsystems. + /// + /// True if handled. + public bool Input_MouseMoved(int x, int y, int dx, int dy) + { + if (IsHidden) + { + return false; + } - // If we didn't have a next tab, cycle to the start. - if (mNextTab == null) - { - mNextTab = mFirstTab; - } + // Todo: Handle scaling here.. + var fScale = 1.0f / Scale; + x = (int) (x * fScale); + y = (int) (y * fScale); + dx = (int) (dx * fScale); + dy = (int) (dy * fScale); - InputHandler.OnCanvasThink(this); - } + InputHandler.OnMouseMoved(this, x, y, dx, dy); - /// - /// Adds given control to the delete queue and detaches it from canvas. Don't call from Dispose, it modifies child - /// list. - /// - /// Control to delete. - public void AddDelayedDelete(Base control) + if (InputHandler.HoveredControl == null) { - if (!mDisposeQueue.Contains(control)) - { - mDisposeQueue.Add(control); - RemoveChild(control, false); - } -#if DEBUG - else - { - throw new InvalidOperationException("Control deleted twice"); - } -#endif + return false; } - private void ProcessDelayedDeletes() + if (InputHandler.HoveredControl == this) { - //if (m_DisposeQueue.Count > 0) - // System.Diagnostics.//debug.print("Canvas.ProcessDelayedDeletes: {0} items", m_DisposeQueue.Count); - foreach (var control in mDisposeQueue) - { - control.Dispose(); - } - - mDisposeQueue.Clear(); + return false; } - /// - /// Handles mouse movement events. Called from Input subsystems. - /// - /// True if handled. - public bool Input_MouseMoved(int x, int y, int dx, int dy) + if (InputHandler.HoveredControl.GetCanvas() != this) { - if (IsHidden) - { - return false; - } + return false; + } - // Todo: Handle scaling here.. - var fScale = 1.0f / Scale; - x = (int) (x * fScale); - y = (int) (y * fScale); - dx = (int) (dx * fScale); - dy = (int) (dy * fScale); + InputHandler.HoveredControl.InputMouseMoved(x, y, dx, dy); + InputHandler.HoveredControl.UpdateCursor(); - InputHandler.OnMouseMoved(this, x, y, dx, dy); + DragAndDrop.OnMouseMoved(InputHandler.HoveredControl, x, y); - if (InputHandler.HoveredControl == null) - { - return false; - } + return true; + } - if (InputHandler.HoveredControl == this) - { - return false; - } + /// + /// Handles mouse button events. Called from Input subsystems. + /// + /// True if handled. + public bool Input_MouseButton(int button, bool down) + { + if (IsHidden) + { + return false; + } - if (InputHandler.HoveredControl.GetCanvas() != this) - { - return false; - } + return InputHandler.OnMouseClicked(this, button, down); + } - InputHandler.HoveredControl.InputMouseMoved(x, y, dx, dy); - InputHandler.HoveredControl.UpdateCursor(); + /// + /// Handles mouse button events. Called from Input subsystems. + /// + /// True if handled. + public bool Input_MouseScroll(int deltaX, int deltaY) + { + if (IsHidden) + { + return false; + } - DragAndDrop.OnMouseMoved(InputHandler.HoveredControl, x, y); + return InputHandler.OnMouseScroll(this, deltaX, deltaY); + } - return true; + /// + /// Handles keyboard events. Called from Input subsystems. + /// + /// True if handled. + public bool Input_Key(Key key, bool down, bool shift = false) + { + if (IsHidden) + { + return false; } - /// - /// Handles mouse button events. Called from Input subsystems. - /// - /// True if handled. - public bool Input_MouseButton(int button, bool down) + if (key <= Key.Invalid) { - if (IsHidden) - { - return false; - } - - return InputHandler.OnMouseClicked(this, button, down); + return false; } - /// - /// Handles mouse button events. Called from Input subsystems. - /// - /// True if handled. - public bool Input_MouseScroll(int deltaX, int deltaY) + if (key >= Key.Count) { - if (IsHidden) - { - return false; - } - - return InputHandler.OnMouseScroll(this, deltaX, deltaY); + return false; } - /// - /// Handles keyboard events. Called from Input subsystems. - /// - /// True if handled. - public bool Input_Key(Key key, bool down, bool shift = false) + if (key == Key.Tab) { - if (IsHidden) - { - return false; - } - - if (key <= Key.Invalid) - { - return false; - } - - if (key >= Key.Count) - { - return false; - } + return OnKeyTab(down, shift); + } - if (key == Key.Tab) - { - return OnKeyTab(down, shift); - } + return InputHandler.OnKeyEvent(this, key, down); + } - return InputHandler.OnKeyEvent(this, key, down); + /// + /// Handles keyboard events. Called from Input subsystems. + /// + /// True if handled. + public bool Input_Character(char chr) + { + if (IsHidden) + { + return false; } - /// - /// Handles keyboard events. Called from Input subsystems. - /// - /// True if handled. - public bool Input_Character(char chr) + if (char.IsControl(chr)) { - if (IsHidden) - { - return false; - } + return false; + } - if (char.IsControl(chr)) - { - return false; - } + //Handle Accelerators + if (InputHandler.HandleAccelerator(this, chr)) + { + return true; + } - //Handle Accelerators - if (InputHandler.HandleAccelerator(this, chr)) - { - return true; - } + //Handle characters + if (InputHandler.KeyboardFocus == null) + { + return false; + } - //Handle characters - if (InputHandler.KeyboardFocus == null) - { - return false; - } + if (InputHandler.KeyboardFocus.GetCanvas() != this) + { + return false; + } - if (InputHandler.KeyboardFocus.GetCanvas() != this) - { - return false; - } + if (!InputHandler.KeyboardFocus.IsVisible) + { + return false; + } - if (!InputHandler.KeyboardFocus.IsVisible) - { - return false; - } + //if (InputHandler.IsControlDown) return false; - //if (InputHandler.IsControlDown) return false; + return InputHandler.KeyboardFocus.InputChar(chr); + } - return InputHandler.KeyboardFocus.InputChar(chr); + /// + /// Handles the mouse wheel events. Called from Input subsystems. + /// + /// True if handled. + public bool Input_MouseWheel(int val) + { + if (IsHidden) + { + return false; } - /// - /// Handles the mouse wheel events. Called from Input subsystems. - /// - /// True if handled. - public bool Input_MouseWheel(int val) + if (InputHandler.HoveredControl == null) { - if (IsHidden) - { - return false; - } - - if (InputHandler.HoveredControl == null) - { - return false; - } - - if (InputHandler.HoveredControl == this) - { - return false; - } + return false; + } - if (InputHandler.HoveredControl.GetCanvas() != this) - { - return false; - } + if (InputHandler.HoveredControl == this) + { + return false; + } - return InputHandler.HoveredControl.InputMouseWheeled(val); + if (InputHandler.HoveredControl.GetCanvas() != this) + { + return false; } + return InputHandler.HoveredControl.InputMouseWheeled(val); } } diff --git a/Intersect.Client.Framework/Gwen/Control/CheckBox.cs b/Intersect.Client.Framework/Gwen/Control/CheckBox.cs index 8a9edcf004..4e7508e508 100644 --- a/Intersect.Client.Framework/Gwen/Control/CheckBox.cs +++ b/Intersect.Client.Framework/Gwen/Control/CheckBox.cs @@ -3,300 +3,298 @@ using Newtonsoft.Json.Linq; -namespace Intersect.Client.Framework.Gwen.Control +namespace Intersect.Client.Framework.Gwen.Control; + + +/// +/// CheckBox control. +/// +public partial class CheckBox : Button { - /// - /// CheckBox control. - /// - public partial class CheckBox : Button + public enum ControlState { - public enum ControlState - { + Normal = 0, - Normal = 0, + Disabled, - Disabled, + CheckedNormal, - CheckedNormal, + CheckedDisabled, - CheckedDisabled, + } - } + private bool mChecked; - private bool mChecked; + private GameTexture mCheckedDisabledImage; - private GameTexture mCheckedDisabledImage; + private string mCheckedDisabledImageFilename; - private string mCheckedDisabledImageFilename; + private GameTexture mCheckedNormalImage; - private GameTexture mCheckedNormalImage; + private string mCheckedNormalImageFilename; - private string mCheckedNormalImageFilename; + //Sound Effects + private string mCheckSound; - //Sound Effects - private string mCheckSound; + private GameTexture mDisabledImage; - private GameTexture mDisabledImage; + private string mDisabledImageFilename; - private string mDisabledImageFilename; + private GameTexture mNormalImage; - private GameTexture mNormalImage; + private string mNormalImageFilename; - private string mNormalImageFilename; + private string mUncheckedSound; - private string mUncheckedSound; + /// + /// Initializes a new instance of the class. + /// + /// Parent control. + public CheckBox(Base parent, string name = default, bool disableText = true) : base(parent, name, disableText) + { + SetSize(15, 15); + IsToggle = true; + } - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public CheckBox(Base parent, string name = default, bool disableText = true) : base(parent, name, disableText) + /// + /// Indicates whether the checkbox is checked. + /// + public bool IsChecked + { + get => mChecked; + set { - SetSize(15, 15); - IsToggle = true; + if (mChecked == value) + { + return; + } + + mChecked = value; + OnCheckChanged(); } + } - /// - /// Indicates whether the checkbox is checked. - /// - public bool IsChecked + /// + /// Determines whether unchecking is allowed. + /// + protected virtual bool AllowUncheck => true; + + public override JObject GetJson(bool isRoot = default) + { + var obj = base.GetJson(isRoot); + obj.Add("NormalImage", GetImageFilename(ControlState.Normal)); + obj.Add("CheckedImage", GetImageFilename(ControlState.CheckedNormal)); + obj.Add("DisabledImage", GetImageFilename(ControlState.Disabled)); + obj.Add("CheckedDisabledImage", GetImageFilename(ControlState.CheckedDisabled)); + obj.Add("CheckedSound", mCheckSound); + obj.Add("UncheckedSound", mUncheckedSound); + + return base.FixJson(obj); + } + + public override void LoadJson(JToken obj, bool isRoot = default) + { + base.LoadJson(obj); + if (obj["NormalImage"] != null) { - get => mChecked; - set - { - if (mChecked == value) - { - return; - } + SetImage( + GameContentManager.Current.GetTexture( + Framework.Content.TextureType.Gui, (string)obj["NormalImage"] + ), (string)obj["NormalImage"], ControlState.Normal + ); + } - mChecked = value; - OnCheckChanged(); - } + if (obj["CheckedImage"] != null) + { + SetImage( + GameContentManager.Current.GetTexture( + Framework.Content.TextureType.Gui, (string)obj["CheckedImage"] + ), (string)obj["CheckedImage"], ControlState.CheckedNormal + ); } - /// - /// Determines whether unchecking is allowed. - /// - protected virtual bool AllowUncheck => true; + if (obj["DisabledImage"] != null) + { + SetImage( + GameContentManager.Current.GetTexture( + Framework.Content.TextureType.Gui, (string)obj["DisabledImage"] + ), (string)obj["DisabledImage"], ControlState.Disabled + ); + } - public override JObject GetJson(bool isRoot = default) + if (obj["CheckedDisabledImage"] != null) { - var obj = base.GetJson(isRoot); - obj.Add("NormalImage", GetImageFilename(ControlState.Normal)); - obj.Add("CheckedImage", GetImageFilename(ControlState.CheckedNormal)); - obj.Add("DisabledImage", GetImageFilename(ControlState.Disabled)); - obj.Add("CheckedDisabledImage", GetImageFilename(ControlState.CheckedDisabled)); - obj.Add("CheckedSound", mCheckSound); - obj.Add("UncheckedSound", mUncheckedSound); - - return base.FixJson(obj); + SetImage( + GameContentManager.Current.GetTexture( + Framework.Content.TextureType.Gui, (string)obj["CheckedDisabledImage"] + ), (string)obj["CheckedDisabledImage"], ControlState.CheckedDisabled + ); } - public override void LoadJson(JToken obj, bool isRoot = default) + if (obj["CheckedSound"] != null) { - base.LoadJson(obj); - if (obj["NormalImage"] != null) - { - SetImage( - GameContentManager.Current.GetTexture( - Framework.Content.TextureType.Gui, (string)obj["NormalImage"] - ), (string)obj["NormalImage"], ControlState.Normal - ); - } + mCheckSound = (string)obj["CheckedSound"]; + } - if (obj["CheckedImage"] != null) - { - SetImage( - GameContentManager.Current.GetTexture( - Framework.Content.TextureType.Gui, (string)obj["CheckedImage"] - ), (string)obj["CheckedImage"], ControlState.CheckedNormal - ); - } + if (obj["UncheckedSound"] != null) + { + mUncheckedSound = (string)obj["UncheckedSound"]; + } + } - if (obj["DisabledImage"] != null) - { - SetImage( - GameContentManager.Current.GetTexture( - Framework.Content.TextureType.Gui, (string)obj["DisabledImage"] - ), (string)obj["DisabledImage"], ControlState.Disabled - ); - } + /// + /// Toggles the checkbox. + /// + public override void Toggle() + { + base.Toggle(); + IsChecked = !IsChecked; + if (IsChecked) + { + base.PlaySound(mCheckSound); + } + else + { + base.PlaySound(mUncheckedSound); + } + } - if (obj["CheckedDisabledImage"] != null) - { - SetImage( - GameContentManager.Current.GetTexture( - Framework.Content.TextureType.Gui, (string)obj["CheckedDisabledImage"] - ), (string)obj["CheckedDisabledImage"], ControlState.CheckedDisabled - ); - } + /// + /// Invoked when the checkbox has been checked. + /// + public event GwenEventHandler Checked; - if (obj["CheckedSound"] != null) - { - mCheckSound = (string)obj["CheckedSound"]; - } + /// + /// Invoked when the checkbox has been unchecked. + /// + public event GwenEventHandler UnChecked; - if (obj["UncheckedSound"] != null) - { - mUncheckedSound = (string)obj["UncheckedSound"]; - } - } + /// + /// Invoked when the checkbox state has been changed. + /// + public event GwenEventHandler CheckChanged; - /// - /// Toggles the checkbox. - /// - public override void Toggle() + /// + /// Handler for CheckChanged event. + /// + protected virtual void OnCheckChanged() + { + if (IsChecked) { - base.Toggle(); - IsChecked = !IsChecked; - if (IsChecked) - { - base.PlaySound(mCheckSound); - } - else + if (Checked != null) { - base.PlaySound(mUncheckedSound); + Checked.Invoke(this, EventArgs.Empty); } } - - /// - /// Invoked when the checkbox has been checked. - /// - public event GwenEventHandler Checked; - - /// - /// Invoked when the checkbox has been unchecked. - /// - public event GwenEventHandler UnChecked; - - /// - /// Invoked when the checkbox state has been changed. - /// - public event GwenEventHandler CheckChanged; - - /// - /// Handler for CheckChanged event. - /// - protected virtual void OnCheckChanged() + else { - if (IsChecked) - { - if (Checked != null) - { - Checked.Invoke(this, EventArgs.Empty); - } - } - else + if (UnChecked != null) { - if (UnChecked != null) - { - UnChecked.Invoke(this, EventArgs.Empty); - } - } - - if (CheckChanged != null) - { - CheckChanged.Invoke(this, EventArgs.Empty); + UnChecked.Invoke(this, EventArgs.Empty); } } - /// - /// Renders the control using specified skin. - /// - /// Skin to use. - protected override void Render(Skin.Base skin) + if (CheckChanged != null) { - //base.Render(skin); - skin.DrawCheckBox(this, mChecked, IsHovered, IsDepressed); + CheckChanged.Invoke(this, EventArgs.Empty); } + } + + /// + /// Renders the control using specified skin. + /// + /// Skin to use. + protected override void Render(Skin.Base skin) + { + //base.Render(skin); + skin.DrawCheckBox(this, mChecked, IsHovered, IsDepressed); + } + + public void SetCheckSize(int w, int h) + { + } - public void SetCheckSize(int w, int h) + /// + /// Internal OnPressed implementation. + /// + protected override void OnClicked(int x, int y) + { + if (IsDisabled) { + return; } - /// - /// Internal OnPressed implementation. - /// - protected override void OnClicked(int x, int y) + if (IsChecked && !AllowUncheck) { - if (IsDisabled) - { - return; - } - - if (IsChecked && !AllowUncheck) - { - return; - } - - base.OnClicked(x, y); + return; } - public void SetImage(GameTexture texture, string fileName, ControlState state) + base.OnClicked(x, y); + } + + public void SetImage(GameTexture texture, string fileName, ControlState state) + { + switch (state) { - switch (state) - { - case ControlState.Normal: - mNormalImageFilename = fileName; - mNormalImage = texture; - - break; - case ControlState.Disabled: - mDisabledImageFilename = fileName; - mDisabledImage = texture; - - break; - case ControlState.CheckedNormal: - mCheckedNormalImageFilename = fileName; - mCheckedNormalImage = texture; - - break; - case ControlState.CheckedDisabled: - mCheckedDisabledImageFilename = fileName; - mCheckedDisabledImage = texture; - - break; - default: - throw new ArgumentOutOfRangeException(nameof(state), state, null); - } + case ControlState.Normal: + mNormalImageFilename = fileName; + mNormalImage = texture; + + break; + case ControlState.Disabled: + mDisabledImageFilename = fileName; + mDisabledImage = texture; + + break; + case ControlState.CheckedNormal: + mCheckedNormalImageFilename = fileName; + mCheckedNormalImage = texture; + + break; + case ControlState.CheckedDisabled: + mCheckedDisabledImageFilename = fileName; + mCheckedDisabledImage = texture; + + break; + default: + throw new ArgumentOutOfRangeException(nameof(state), state, null); } + } - public GameTexture GetImage(ControlState state) + public GameTexture GetImage(ControlState state) + { + switch (state) { - switch (state) - { - case ControlState.Normal: - return mNormalImage; - case ControlState.Disabled: - return mDisabledImage; - case ControlState.CheckedNormal: - return mCheckedNormalImage; - case ControlState.CheckedDisabled: - return mCheckedDisabledImage; - default: - return null; - } + case ControlState.Normal: + return mNormalImage; + case ControlState.Disabled: + return mDisabledImage; + case ControlState.CheckedNormal: + return mCheckedNormalImage; + case ControlState.CheckedDisabled: + return mCheckedDisabledImage; + default: + return null; } + } - public string GetImageFilename(ControlState state) + public string GetImageFilename(ControlState state) + { + switch (state) { - switch (state) - { - case ControlState.Normal: - return mNormalImageFilename; - case ControlState.Disabled: - return mDisabledImageFilename; - case ControlState.CheckedNormal: - return mCheckedNormalImageFilename; - case ControlState.CheckedDisabled: - return mCheckedDisabledImageFilename; - default: - return null; - } + case ControlState.Normal: + return mNormalImageFilename; + case ControlState.Disabled: + return mDisabledImageFilename; + case ControlState.CheckedNormal: + return mCheckedNormalImageFilename; + case ControlState.CheckedDisabled: + return mCheckedDisabledImageFilename; + default: + return null; } - } } diff --git a/Intersect.Client.Framework/Gwen/Control/CollapsibleCategory.cs b/Intersect.Client.Framework/Gwen/Control/CollapsibleCategory.cs index 36c598b7ff..e4f2fc99f3 100644 --- a/Intersect.Client.Framework/Gwen/Control/CollapsibleCategory.cs +++ b/Intersect.Client.Framework/Gwen/Control/CollapsibleCategory.cs @@ -1,204 +1,202 @@ using Intersect.Client.Framework.Gwen.Control.EventArguments; using Intersect.Client.Framework.Gwen.ControlInternal; -namespace Intersect.Client.Framework.Gwen.Control +namespace Intersect.Client.Framework.Gwen.Control; + + +/// +/// CollapsibleCategory control. Used in CollapsibleList. +/// +public partial class CollapsibleCategory : Base { + private readonly Button mHeaderButton; + + private readonly CollapsibleList mList; + /// - /// CollapsibleCategory control. Used in CollapsibleList. + /// Initializes a new instance of the class. /// - public partial class CollapsibleCategory : Base + /// Parent control. + public CollapsibleCategory(CollapsibleList parent) : base(parent) { + mHeaderButton = new CategoryHeaderButton(this); + mHeaderButton.Text = "Category Title"; // [omeg] todo: i18n + mHeaderButton.Dock = Pos.Top; + mHeaderButton.Height = 20; + mHeaderButton.Toggled += OnHeaderToggle; - private readonly Button mHeaderButton; + mList = parent; - private readonly CollapsibleList mList; + Padding = new Padding(1, 0, 1, 5); + SetSize(512, 512); + } - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public CollapsibleCategory(CollapsibleList parent) : base(parent) - { - mHeaderButton = new CategoryHeaderButton(this); - mHeaderButton.Text = "Category Title"; // [omeg] todo: i18n - mHeaderButton.Dock = Pos.Top; - mHeaderButton.Height = 20; - mHeaderButton.Toggled += OnHeaderToggle; + /// + /// Header text. + /// + public string Text + { + get => mHeaderButton.Text; + set => mHeaderButton.Text = value; + } - mList = parent; + /// + /// Determines whether the category is collapsed (closed). + /// + public bool IsCollapsed + { + get => mHeaderButton.ToggleState; + set => mHeaderButton.ToggleState = value; + } - Padding = new Padding(1, 0, 1, 5); - SetSize(512, 512); - } + /// + /// Invoked when an entry has been selected. + /// + public event GwenEventHandler Selected; - /// - /// Header text. - /// - public string Text - { - get => mHeaderButton.Text; - set => mHeaderButton.Text = value; - } + /// + /// Invoked when the category collapsed state has been changed (header button has been pressed). + /// + public event GwenEventHandler Collapsed; - /// - /// Determines whether the category is collapsed (closed). - /// - public bool IsCollapsed + /// + /// Gets the selected entry. + /// + public Button GetSelectedButton() + { + foreach (var child in Children) { - get => mHeaderButton.ToggleState; - set => mHeaderButton.ToggleState = value; - } + var button = child as CategoryButton; + if (button == null) + { + continue; + } - /// - /// Invoked when an entry has been selected. - /// - public event GwenEventHandler Selected; + if (button.ToggleState) + { + return button; + } + } - /// - /// Invoked when the category collapsed state has been changed (header button has been pressed). - /// - public event GwenEventHandler Collapsed; + return null; + } - /// - /// Gets the selected entry. - /// - public Button GetSelectedButton() + /// + /// Handler for header button toggle event. + /// + /// Source control. + protected virtual void OnHeaderToggle(Base control, EventArgs args) + { + if (Collapsed != null) { - foreach (var child in Children) - { - var button = child as CategoryButton; - if (button == null) - { - continue; - } - - if (button.ToggleState) - { - return button; - } - } + Collapsed.Invoke(this, EventArgs.Empty); + } + } - return null; + /// + /// Handler for Selected event. + /// + /// Event source. + protected virtual void OnSelected(Base control, EventArgs args) + { + var child = control as CategoryButton; + if (child == null) + { + return; } - /// - /// Handler for header button toggle event. - /// - /// Source control. - protected virtual void OnHeaderToggle(Base control, EventArgs args) + if (mList != null) { - if (Collapsed != null) - { - Collapsed.Invoke(this, EventArgs.Empty); - } + mList.UnselectAll(); } + else + { + UnselectAll(); + } + + child.ToggleState = true; - /// - /// Handler for Selected event. - /// - /// Event source. - protected virtual void OnSelected(Base control, EventArgs args) + if (Selected != null) { - var child = control as CategoryButton; - if (child == null) - { - return; - } + Selected.Invoke(this, new ItemSelectedEventArgs(control)); + } + } - if (mList != null) - { - mList.UnselectAll(); - } - else - { - UnselectAll(); - } + /// + /// Adds a new entry. + /// + /// Entry name (displayed). + /// Newly created control. + public Button Add(string name) + { + var button = new CategoryButton(this); + button.Text = name; + button.Dock = Pos.Top; + button.SizeToContents(); + button.SetSize(button.Width + 4, button.Height + 4); + button.Padding = new Padding(5, 2, 2, 2); + button.Clicked += OnSelected; + + return button; + } - child.ToggleState = true; + /// + /// Renders the control using specified skin. + /// + /// Skin to use. + protected override void Render(Skin.Base skin) + { + skin.DrawCategoryInner(this, mHeaderButton.ToggleState); + base.Render(skin); + } - if (Selected != null) + /// + /// Unselects all entries. + /// + public void UnselectAll() + { + foreach (var child in Children) + { + var button = child as CategoryButton; + if (button == null) { - Selected.Invoke(this, new ItemSelectedEventArgs(control)); + continue; } - } - /// - /// Adds a new entry. - /// - /// Entry name (displayed). - /// Newly created control. - public Button Add(string name) - { - var button = new CategoryButton(this); - button.Text = name; - button.Dock = Pos.Top; - button.SizeToContents(); - button.SetSize(button.Width + 4, button.Height + 4); - button.Padding = new Padding(5, 2, 2, 2); - button.Clicked += OnSelected; - - return button; + button.ToggleState = false; } + } - /// - /// Renders the control using specified skin. - /// - /// Skin to use. - protected override void Render(Skin.Base skin) + /// + /// Function invoked after layout. + /// + /// Skin to use. + protected override void PostLayout(Skin.Base skin) + { + if (IsCollapsed) { - skin.DrawCategoryInner(this, mHeaderButton.ToggleState); - base.Render(skin); + Height = mHeaderButton.Height; } - - /// - /// Unselects all entries. - /// - public void UnselectAll() + else { - foreach (var child in Children) - { - var button = child as CategoryButton; - if (button == null) - { - continue; - } - - button.ToggleState = false; - } + SizeToChildren(false, true); } - /// - /// Function invoked after layout. - /// - /// Skin to use. - protected override void PostLayout(Skin.Base skin) + // alternate row coloring + var b = true; + foreach (var child in Children) { - if (IsCollapsed) + var button = child as CategoryButton; + if (button == null) { - Height = mHeaderButton.Height; - } - else - { - SizeToChildren(false, true); + continue; } - // alternate row coloring - var b = true; - foreach (var child in Children) - { - var button = child as CategoryButton; - if (button == null) - { - continue; - } - - button.mAlt = b; - button.UpdateColors(); - b = !b; - } + button.mAlt = b; + button.UpdateColors(); + b = !b; } - } } diff --git a/Intersect.Client.Framework/Gwen/Control/CollapsibleList.cs b/Intersect.Client.Framework/Gwen/Control/CollapsibleList.cs index dbcaa5a111..272f99ad48 100644 --- a/Intersect.Client.Framework/Gwen/Control/CollapsibleList.cs +++ b/Intersect.Client.Framework/Gwen/Control/CollapsibleList.cs @@ -1,153 +1,151 @@ using Intersect.Client.Framework.Gwen.Control.EventArguments; -namespace Intersect.Client.Framework.Gwen.Control +namespace Intersect.Client.Framework.Gwen.Control; + + +/// +/// CollapsibleList control. Groups CollapsibleCategory controls. +/// +public partial class CollapsibleList : ScrollControl { /// - /// CollapsibleList control. Groups CollapsibleCategory controls. + /// Initializes a new instance of the class. /// - public partial class CollapsibleList : ScrollControl + /// Parent control. + public CollapsibleList(Base parent) : base(parent) { + MouseInputEnabled = true; + EnableScroll(false, true); + AutoHideBars = true; + } - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public CollapsibleList(Base parent) : base(parent) - { - MouseInputEnabled = true; - EnableScroll(false, true); - AutoHideBars = true; - } - - /// - /// Invoked when an entry has been selected. - /// - public event GwenEventHandler ItemSelected; + /// + /// Invoked when an entry has been selected. + /// + public event GwenEventHandler ItemSelected; - /// - /// Invoked when a category collapsed state has been changed (header button has been pressed). - /// - public event GwenEventHandler CategoryCollapsed; + /// + /// Invoked when a category collapsed state has been changed (header button has been pressed). + /// + public event GwenEventHandler CategoryCollapsed; - // todo: iterator, make this as function? check if works + // todo: iterator, make this as function? check if works - /// - /// Selected entry. - /// - public Button GetSelectedButton() + /// + /// Selected entry. + /// + public Button GetSelectedButton() + { + foreach (var child in Children) { - foreach (var child in Children) + var cat = child as CollapsibleCategory; + if (cat == null) { - var cat = child as CollapsibleCategory; - if (cat == null) - { - continue; - } - - var button = cat.GetSelectedButton(); - - if (button != null) - { - return button; - } + continue; } - return null; - } - - /// - /// Adds a category to the list. - /// - /// Category control to add. - protected virtual void Add(CollapsibleCategory category) - { - category.Parent = this; - category.Dock = Pos.Top; - category.Margin = new Margin(1, 0, 1, 1); - category.Selected += OnCategorySelected; - category.Collapsed += OnCategoryCollapsed; + var button = cat.GetSelectedButton(); - // this relies on fact that category.m_List is set to its parent + if (button != null) + { + return button; + } } - /// - /// Adds a new category to the list. - /// - /// Name of the category. - /// Newly created control. - public virtual CollapsibleCategory Add(string categoryName) - { - var cat = new CollapsibleCategory(this); - cat.Text = categoryName; - Add(cat); + return null; + } - return cat; - } + /// + /// Adds a category to the list. + /// + /// Category control to add. + protected virtual void Add(CollapsibleCategory category) + { + category.Parent = this; + category.Dock = Pos.Top; + category.Margin = new Margin(1, 0, 1, 1); + category.Selected += OnCategorySelected; + category.Collapsed += OnCategoryCollapsed; - /// - /// Renders the control using specified skin. - /// - /// Skin to use. - protected override void Render(Skin.Base skin) - { - skin.DrawCategoryHolder(this); - base.Render(skin); - } + // this relies on fact that category.m_List is set to its parent + } - /// - /// Unselects all entries. - /// - public virtual void UnselectAll() - { - foreach (var child in Children) - { - var cat = child as CollapsibleCategory; - if (cat == null) - { - continue; - } + /// + /// Adds a new category to the list. + /// + /// Name of the category. + /// Newly created control. + public virtual CollapsibleCategory Add(string categoryName) + { + var cat = new CollapsibleCategory(this); + cat.Text = categoryName; + Add(cat); - cat.UnselectAll(); - } - } + return cat; + } - /// - /// Handler for ItemSelected event. - /// - /// Event source: . - protected virtual void OnCategorySelected(Base control, EventArgs args) + /// + /// Renders the control using specified skin. + /// + /// Skin to use. + protected override void Render(Skin.Base skin) + { + skin.DrawCategoryHolder(this); + base.Render(skin); + } + + /// + /// Unselects all entries. + /// + public virtual void UnselectAll() + { + foreach (var child in Children) { - var cat = control as CollapsibleCategory; + var cat = child as CollapsibleCategory; if (cat == null) { - return; + continue; } - if (ItemSelected != null) - { - ItemSelected.Invoke(this, new ItemSelectedEventArgs(cat)); - } + cat.UnselectAll(); } + } - /// - /// Handler for category collapsed event. - /// - /// Event source: . - protected virtual void OnCategoryCollapsed(Base control, EventArgs args) + /// + /// Handler for ItemSelected event. + /// + /// Event source: . + protected virtual void OnCategorySelected(Base control, EventArgs args) + { + var cat = control as CollapsibleCategory; + if (cat == null) { - var cat = control as CollapsibleCategory; - if (cat == null) - { - return; - } + return; + } - if (CategoryCollapsed != null) - { - CategoryCollapsed.Invoke(control, EventArgs.Empty); - } + if (ItemSelected != null) + { + ItemSelected.Invoke(this, new ItemSelectedEventArgs(cat)); + } + } + + /// + /// Handler for category collapsed event. + /// + /// Event source: . + protected virtual void OnCategoryCollapsed(Base control, EventArgs args) + { + var cat = control as CollapsibleCategory; + if (cat == null) + { + return; } + if (CategoryCollapsed != null) + { + CategoryCollapsed.Invoke(control, EventArgs.Empty); + } } } diff --git a/Intersect.Client.Framework/Gwen/Control/ColorLerpBox.cs b/Intersect.Client.Framework/Gwen/Control/ColorLerpBox.cs index 91d37d7a2d..39d281021e 100644 --- a/Intersect.Client.Framework/Gwen/Control/ColorLerpBox.cs +++ b/Intersect.Client.Framework/Gwen/Control/ColorLerpBox.cs @@ -1,204 +1,202 @@ using Intersect.Client.Framework.GenericClasses; using Intersect.Client.Framework.Gwen.Input; -namespace Intersect.Client.Framework.Gwen.Control +namespace Intersect.Client.Framework.Gwen.Control; + + +/// +/// Linear-interpolated HSV color box. +/// +public partial class ColorLerpBox : Base { + private Point mCursorPos; + + private bool mDepressed; + + private float mHue; + /// - /// Linear-interpolated HSV color box. + /// Initializes a new instance of the class. /// - public partial class ColorLerpBox : Base + /// Parent control. + public ColorLerpBox(Base parent) : base(parent) { + SetColor(Color.FromArgb(255, 255, 128, 0)); + SetSize(128, 128); + MouseInputEnabled = true; + mDepressed = false; - private Point mCursorPos; + // texture is initialized in Render() if null + } - private bool mDepressed; + /// + /// Selected color. + /// + public Color SelectedColor => GetColorAt(mCursorPos.X, mCursorPos.Y); - private float mHue; + /// + /// Invoked when the selected color has been changed. + /// + public event GwenEventHandler ColorChanged; - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public ColorLerpBox(Base parent) : base(parent) - { - SetColor(Color.FromArgb(255, 255, 128, 0)); - SetSize(128, 128); - MouseInputEnabled = true; - mDepressed = false; + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public override void Dispose() + { + base.Dispose(); + } - // texture is initialized in Render() if null - } + /// + /// Linear color interpolation. + /// + public static Color Lerp(Color toColor, Color fromColor, float amount) + { + var delta = toColor.Subtract(fromColor); + delta = delta.Multiply(amount); - /// - /// Selected color. - /// - public Color SelectedColor => GetColorAt(mCursorPos.X, mCursorPos.Y); + return fromColor.Add(delta); + } - /// - /// Invoked when the selected color has been changed. - /// - public event GwenEventHandler ColorChanged; + /// + /// Sets the selected color. + /// + /// Value to set. + /// Deetrmines whether to only set H value (not SV). + public void SetColor(Color value, bool onlyHue = true) + { + var hsv = value.ToHsv(); + mHue = hsv.H; - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public override void Dispose() + if (!onlyHue) { - base.Dispose(); + mCursorPos.X = (int) (hsv.s * Width); + mCursorPos.Y = (int) ((1 - hsv.V) * Height); } - /// - /// Linear color interpolation. - /// - public static Color Lerp(Color toColor, Color fromColor, float amount) - { - var delta = toColor.Subtract(fromColor); - delta = delta.Multiply(amount); + Invalidate(); - return fromColor.Add(delta); + if (ColorChanged != null) + { + ColorChanged.Invoke(this, EventArgs.Empty); } + } - /// - /// Sets the selected color. - /// - /// Value to set. - /// Deetrmines whether to only set H value (not SV). - public void SetColor(Color value, bool onlyHue = true) + /// + /// Handler invoked on mouse moved event. + /// + /// X coordinate. + /// Y coordinate. + /// X change. + /// Y change. + protected override void OnMouseMoved(int x, int y, int dx, int dy) + { + if (mDepressed) { - var hsv = value.ToHsv(); - mHue = hsv.H; + mCursorPos = CanvasPosToLocal(new Point(x, y)); - if (!onlyHue) + //Do we have clamp? + if (mCursorPos.X < 0) { - mCursorPos.X = (int) (hsv.s * Width); - mCursorPos.Y = (int) ((1 - hsv.V) * Height); + mCursorPos.X = 0; } - Invalidate(); - - if (ColorChanged != null) + if (mCursorPos.X > Width) { - ColorChanged.Invoke(this, EventArgs.Empty); + mCursorPos.X = Width; } - } - /// - /// Handler invoked on mouse moved event. - /// - /// X coordinate. - /// Y coordinate. - /// X change. - /// Y change. - protected override void OnMouseMoved(int x, int y, int dx, int dy) - { - if (mDepressed) + if (mCursorPos.Y < 0) { - mCursorPos = CanvasPosToLocal(new Point(x, y)); - - //Do we have clamp? - if (mCursorPos.X < 0) - { - mCursorPos.X = 0; - } - - if (mCursorPos.X > Width) - { - mCursorPos.X = Width; - } - - if (mCursorPos.Y < 0) - { - mCursorPos.Y = 0; - } - - if (mCursorPos.Y > Height) - { - mCursorPos.Y = Height; - } - - if (ColorChanged != null) - { - ColorChanged.Invoke(this, EventArgs.Empty); - } + mCursorPos.Y = 0; } - } - /// - /// Handler invoked on mouse click (left) event. - /// - /// X coordinate. - /// Y coordinate. - /// If set to true mouse button is down. - protected override void OnMouseClickedLeft(int x, int y, bool down, bool automated = false) - { - base.OnMouseClickedLeft(x, y, down); - mDepressed = down; - if (down) + if (mCursorPos.Y > Height) { - InputHandler.MouseFocus = this; + mCursorPos.Y = Height; } - else + + if (ColorChanged != null) { - InputHandler.MouseFocus = null; + ColorChanged.Invoke(this, EventArgs.Empty); } - - OnMouseMoved(x, y, 0, 0); } + } - /// - /// Gets the color from specified coordinates. - /// - /// X - /// Y - /// Color value. - private Color GetColorAt(int x, int y) + /// + /// Handler invoked on mouse click (left) event. + /// + /// X coordinate. + /// Y coordinate. + /// If set to true mouse button is down. + protected override void OnMouseClickedLeft(int x, int y, bool down, bool automated = false) + { + base.OnMouseClickedLeft(x, y, down); + mDepressed = down; + if (down) { - var xPercent = x / (float) Width; - var yPercent = 1 - y / (float) Height; - - var result = Util.HsvToColor(mHue, xPercent, yPercent); - - return result; + InputHandler.MouseFocus = this; } - - /// - /// Invalidates the control. - /// - public override void Invalidate() + else { - base.Invalidate(); + InputHandler.MouseFocus = null; } - /// - /// Renders the control using specified skin. - /// - /// Skin to use. - protected override void Render(Skin.Base skin) - { - skin.Renderer.DrawColor = Color.White; - skin.Renderer.DrawTexturedRect(skin.Renderer.GetWhiteTexture(), RenderBounds, Color.White); + OnMouseMoved(x, y, 0, 0); + } - skin.Renderer.DrawColor = Color.Black; - skin.Renderer.DrawLinedRect(RenderBounds); + /// + /// Gets the color from specified coordinates. + /// + /// X + /// Y + /// Color value. + private Color GetColorAt(int x, int y) + { + var xPercent = x / (float) Width; + var yPercent = 1 - y / (float) Height; - var selected = SelectedColor; - if ((selected.R + selected.G + selected.B) / 3 < 170) - { - skin.Renderer.DrawColor = Color.White; - } - else - { - skin.Renderer.DrawColor = Color.Black; - } + var result = Util.HsvToColor(mHue, xPercent, yPercent); + + return result; + } - var testRect = new Rectangle(mCursorPos.X - 3, mCursorPos.Y - 3, 6, 6); + /// + /// Invalidates the control. + /// + public override void Invalidate() + { + base.Invalidate(); + } + + /// + /// Renders the control using specified skin. + /// + /// Skin to use. + protected override void Render(Skin.Base skin) + { + skin.Renderer.DrawColor = Color.White; + skin.Renderer.DrawTexturedRect(skin.Renderer.GetWhiteTexture(), RenderBounds, Color.White); - skin.Renderer.DrawShavedCornerRect(testRect); + skin.Renderer.DrawColor = Color.Black; + skin.Renderer.DrawLinedRect(RenderBounds); - base.Render(skin); + var selected = SelectedColor; + if ((selected.R + selected.G + selected.B) / 3 < 170) + { + skin.Renderer.DrawColor = Color.White; } + else + { + skin.Renderer.DrawColor = Color.Black; + } + + var testRect = new Rectangle(mCursorPos.X - 3, mCursorPos.Y - 3, 6, 6); + + skin.Renderer.DrawShavedCornerRect(testRect); + base.Render(skin); } } diff --git a/Intersect.Client.Framework/Gwen/Control/ColorPicker.cs b/Intersect.Client.Framework/Gwen/Control/ColorPicker.cs index 5caa2d14d0..0a8c1e8430 100644 --- a/Intersect.Client.Framework/Gwen/Control/ColorPicker.cs +++ b/Intersect.Client.Framework/Gwen/Control/ColorPicker.cs @@ -1,342 +1,340 @@ using Intersect.Client.Framework.Gwen.ControlInternal; -namespace Intersect.Client.Framework.Gwen.Control +namespace Intersect.Client.Framework.Gwen.Control; + + +/// +/// RGBA color picker. +/// +public partial class ColorPicker : Base, IColorPicker { + private Color mColor; + + /// + /// Initializes a new instance of the class. + /// + /// Parent control. + public ColorPicker(Base parent) : base(parent) + { + MouseInputEnabled = true; + + SetSize(256, 150); + CreateControls(); + SelectedColor = Color.FromArgb(255, 50, 60, 70); + } + + /// + /// Red value of the selected color. + /// + public int R + { + get => mColor.R; + set => mColor = Color.FromArgb(mColor.A, value, mColor.G, mColor.B); + } + + /// + /// Green value of the selected color. + /// + public int G + { + get => mColor.G; + set => mColor = Color.FromArgb(mColor.A, mColor.R, value, mColor.B); + } + /// - /// RGBA color picker. + /// Blue value of the selected color. /// - public partial class ColorPicker : Base, IColorPicker + public int B { + get => mColor.B; + set => mColor = Color.FromArgb(mColor.A, mColor.R, mColor.G, value); + } - private Color mColor; + /// + /// Alpha value of the selected color. + /// + public int A + { + get => mColor.A; + set => mColor = Color.FromArgb(value, mColor.R, mColor.G, mColor.B); + } - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public ColorPicker(Base parent) : base(parent) + /// + /// Determines whether the Alpha control is visible. + /// + public bool AlphaVisible + { + get { - MouseInputEnabled = true; + var gb = FindChildByName("Alphagroupbox", true) as GroupBox; - SetSize(256, 150); - CreateControls(); - SelectedColor = Color.FromArgb(255, 50, 60, 70); + return !gb.IsHidden; } - - /// - /// Red value of the selected color. - /// - public int R + set { - get => mColor.R; - set => mColor = Color.FromArgb(mColor.A, value, mColor.G, mColor.B); + var gb = FindChildByName("Alphagroupbox", true) as GroupBox; + gb.IsHidden = !value; + Invalidate(); } + } - /// - /// Green value of the selected color. - /// - public int G + /// + /// Selected color. + /// + public Color SelectedColor + { + get => mColor; + set { - get => mColor.G; - set => mColor = Color.FromArgb(mColor.A, mColor.R, value, mColor.B); + mColor = value; + UpdateControls(); } + } + + /// + /// Invoked when the selected color has been changed. + /// + public event GwenEventHandler ColorChanged; + + private void CreateColorControl(string name, int y) + { + const int colorSize = 12; + + var colorGroup = new GroupBox(this); + colorGroup.SetPosition(10, y); + colorGroup.SetText(name); + colorGroup.SetSize(160, 35); + colorGroup.Name = name + "groupbox"; + + var disp = new ColorDisplay(colorGroup); + disp.Name = name; + disp.SetBounds(0, 10, colorSize, colorSize); + + var numeric = new TextBoxNumeric(colorGroup); + numeric.Name = name + "Box"; + numeric.SetPosition(105, 7); + numeric.SetSize(26, 16); + numeric.SelectAllOnFocus = true; + numeric.TextChanged += NumericTyped; + + var slider = new HorizontalSlider(colorGroup); + slider.SetPosition(colorSize + 5, 10); + slider.SetRange(0, 255); + slider.SetSize(80, colorSize); + slider.Name = name + "Slider"; + slider.ValueChanged += SlidersMoved; + } - /// - /// Blue value of the selected color. - /// - public int B + private void NumericTyped(Base control, EventArgs args) + { + var box = control as TextBoxNumeric; + if (null == box) { - get => mColor.B; - set => mColor = Color.FromArgb(mColor.A, mColor.R, mColor.G, value); + return; } - /// - /// Alpha value of the selected color. - /// - public int A + if (box.Text == string.Empty) { - get => mColor.A; - set => mColor = Color.FromArgb(value, mColor.R, mColor.G, mColor.B); + return; } - /// - /// Determines whether the Alpha control is visible. - /// - public bool AlphaVisible + var textValue = (int) box.Value; + if (textValue < 0) { - get - { - var gb = FindChildByName("Alphagroupbox", true) as GroupBox; - - return !gb.IsHidden; - } - set - { - var gb = FindChildByName("Alphagroupbox", true) as GroupBox; - gb.IsHidden = !value; - Invalidate(); - } + textValue = 0; } - /// - /// Selected color. - /// - public Color SelectedColor + if (textValue > 255) { - get => mColor; - set - { - mColor = value; - UpdateControls(); - } + textValue = 255; } - /// - /// Invoked when the selected color has been changed. - /// - public event GwenEventHandler ColorChanged; - - private void CreateColorControl(string name, int y) + if (box.Name.Contains("Red")) { - const int colorSize = 12; - - var colorGroup = new GroupBox(this); - colorGroup.SetPosition(10, y); - colorGroup.SetText(name); - colorGroup.SetSize(160, 35); - colorGroup.Name = name + "groupbox"; - - var disp = new ColorDisplay(colorGroup); - disp.Name = name; - disp.SetBounds(0, 10, colorSize, colorSize); - - var numeric = new TextBoxNumeric(colorGroup); - numeric.Name = name + "Box"; - numeric.SetPosition(105, 7); - numeric.SetSize(26, 16); - numeric.SelectAllOnFocus = true; - numeric.TextChanged += NumericTyped; - - var slider = new HorizontalSlider(colorGroup); - slider.SetPosition(colorSize + 5, 10); - slider.SetRange(0, 255); - slider.SetSize(80, colorSize); - slider.Name = name + "Slider"; - slider.ValueChanged += SlidersMoved; + R = textValue; } - private void NumericTyped(Base control, EventArgs args) + if (box.Name.Contains("Green")) { - var box = control as TextBoxNumeric; - if (null == box) - { - return; - } - - if (box.Text == string.Empty) - { - return; - } - - var textValue = (int) box.Value; - if (textValue < 0) - { - textValue = 0; - } - - if (textValue > 255) - { - textValue = 255; - } - - if (box.Name.Contains("Red")) - { - R = textValue; - } - - if (box.Name.Contains("Green")) - { - G = textValue; - } - - if (box.Name.Contains("Blue")) - { - B = textValue; - } - - if (box.Name.Contains("Alpha")) - { - A = textValue; - } + G = textValue; + } - UpdateControls(); + if (box.Name.Contains("Blue")) + { + B = textValue; } - private void CreateControls() + if (box.Name.Contains("Alpha")) { - const int startY = 5; - const int height = 35; + A = textValue; + } - CreateColorControl("Red", startY); - CreateColorControl("Green", startY + height); - CreateColorControl("Blue", startY + height * 2); - CreateColorControl("Alpha", startY + height * 3); + UpdateControls(); + } - var finalGroup = new GroupBox(this); - finalGroup.SetPosition(180, 40); - finalGroup.SetSize(60, 60); - finalGroup.SetText("Result"); - finalGroup.Name = "ResultGroupBox"; + private void CreateControls() + { + const int startY = 5; + const int height = 35; - var disp = new ColorDisplay(finalGroup); - disp.Name = "Result"; - disp.SetBounds(0, 10, 32, 32); + CreateColorControl("Red", startY); + CreateColorControl("Green", startY + height); + CreateColorControl("Blue", startY + height * 2); + CreateColorControl("Alpha", startY + height * 3); - //disp.DrawCheckers = true; + var finalGroup = new GroupBox(this); + finalGroup.SetPosition(180, 40); + finalGroup.SetSize(60, 60); + finalGroup.SetText("Result"); + finalGroup.Name = "ResultGroupBox"; - //UpdateControls(); - } + var disp = new ColorDisplay(finalGroup); + disp.Name = "Result"; + disp.SetBounds(0, 10, 32, 32); - private void UpdateColorControls(string name, Color col, int sliderVal) - { - var disp = FindChildByName(name, true) as ColorDisplay; - disp.Color = col; + //disp.DrawCheckers = true; + + //UpdateControls(); + } + + private void UpdateColorControls(string name, Color col, int sliderVal) + { + var disp = FindChildByName(name, true) as ColorDisplay; + disp.Color = col; - var slider = FindChildByName(name + "Slider", true) as HorizontalSlider; - slider.Value = sliderVal; + var slider = FindChildByName(name + "Slider", true) as HorizontalSlider; + slider.Value = sliderVal; - var box = FindChildByName(name + "Box", true) as TextBoxNumeric; - box.Value = sliderVal; + var box = FindChildByName(name + "Box", true) as TextBoxNumeric; + box.Value = sliderVal; + } + + private void UpdateControls() + { + //This is a little weird, but whatever for now + UpdateColorControls("Red", Color.FromArgb(255, SelectedColor.R, 0, 0), SelectedColor.R); + UpdateColorControls("Green", Color.FromArgb(255, 0, SelectedColor.G, 0), SelectedColor.G); + UpdateColorControls("Blue", Color.FromArgb(255, 0, 0, SelectedColor.B), SelectedColor.B); + UpdateColorControls("Alpha", Color.FromArgb(SelectedColor.A, 255, 255, 255), SelectedColor.A); + + var disp = FindChildByName("Result", true) as ColorDisplay; + disp.Color = SelectedColor; + + if (ColorChanged != null) + { + ColorChanged.Invoke(this, EventArgs.Empty); } + } - private void UpdateControls() + private void SlidersMoved(Base control, EventArgs args) + { + /* + HorizontalSlider* redSlider = gwen_cast( FindChildByName( "RedSlider", true ) ); + HorizontalSlider* greenSlider = gwen_cast( FindChildByName( "GreenSlider", true ) ); + HorizontalSlider* blueSlider = gwen_cast( FindChildByName( "BlueSlider", true ) ); + HorizontalSlider* alphaSlider = gwen_cast( FindChildByName( "AlphaSlider", true ) ); + */ + + var slider = control as HorizontalSlider; + if (slider != null) { - //This is a little weird, but whatever for now - UpdateColorControls("Red", Color.FromArgb(255, SelectedColor.R, 0, 0), SelectedColor.R); - UpdateColorControls("Green", Color.FromArgb(255, 0, SelectedColor.G, 0), SelectedColor.G); - UpdateColorControls("Blue", Color.FromArgb(255, 0, 0, SelectedColor.B), SelectedColor.B); - UpdateColorControls("Alpha", Color.FromArgb(SelectedColor.A, 255, 255, 255), SelectedColor.A); - - var disp = FindChildByName("Result", true) as ColorDisplay; - disp.Color = SelectedColor; - - if (ColorChanged != null) - { - ColorChanged.Invoke(this, EventArgs.Empty); - } + SetColorByName(GetColorFromName(slider.Name), (int) slider.Value); } - private void SlidersMoved(Base control, EventArgs args) + UpdateControls(); + + //SetColor( Gwen::Color( redSlider->GetValue(), greenSlider->GetValue(), blueSlider->GetValue(), alphaSlider->GetValue() ) ); + } + + /// + /// Lays out the control's interior according to alignment, padding, dock etc. + /// + /// Skin to use. + protected override void Layout(Skin.Base skin) + { + base.Layout(skin); + + SizeToChildren(false, true); + SetSize(Width, Height + 5); + + var groupBox = FindChildByName("ResultGroupBox", true) as GroupBox; + if (groupBox != null) { - /* - HorizontalSlider* redSlider = gwen_cast( FindChildByName( "RedSlider", true ) ); - HorizontalSlider* greenSlider = gwen_cast( FindChildByName( "GreenSlider", true ) ); - HorizontalSlider* blueSlider = gwen_cast( FindChildByName( "BlueSlider", true ) ); - HorizontalSlider* alphaSlider = gwen_cast( FindChildByName( "AlphaSlider", true ) ); - */ - - var slider = control as HorizontalSlider; - if (slider != null) - { - SetColorByName(GetColorFromName(slider.Name), (int) slider.Value); - } + groupBox.SetPosition(groupBox.X, Height * 0.5f - groupBox.Height * 0.5f); + } - UpdateControls(); + //UpdateControls(); // this spams events continuously every tick + } + + private int GetColorByName(string colorName) + { + if (colorName == "Red") + { + return SelectedColor.R; + } - //SetColor( Gwen::Color( redSlider->GetValue(), greenSlider->GetValue(), blueSlider->GetValue(), alphaSlider->GetValue() ) ); + if (colorName == "Green") + { + return SelectedColor.G; } - /// - /// Lays out the control's interior according to alignment, padding, dock etc. - /// - /// Skin to use. - protected override void Layout(Skin.Base skin) + if (colorName == "Blue") { - base.Layout(skin); + return SelectedColor.B; + } - SizeToChildren(false, true); - SetSize(Width, Height + 5); + if (colorName == "Alpha") + { + return SelectedColor.A; + } - var groupBox = FindChildByName("ResultGroupBox", true) as GroupBox; - if (groupBox != null) - { - groupBox.SetPosition(groupBox.X, Height * 0.5f - groupBox.Height * 0.5f); - } + return 0; + } - //UpdateControls(); // this spams events continuously every tick + private static string GetColorFromName(string name) + { + if (name.Contains("Red")) + { + return "Red"; } - private int GetColorByName(string colorName) + if (name.Contains("Green")) { - if (colorName == "Red") - { - return SelectedColor.R; - } - - if (colorName == "Green") - { - return SelectedColor.G; - } - - if (colorName == "Blue") - { - return SelectedColor.B; - } - - if (colorName == "Alpha") - { - return SelectedColor.A; - } - - return 0; + return "Green"; } - private static string GetColorFromName(string name) + if (name.Contains("Blue")) { - if (name.Contains("Red")) - { - return "Red"; - } - - if (name.Contains("Green")) - { - return "Green"; - } - - if (name.Contains("Blue")) - { - return "Blue"; - } - - if (name.Contains("Alpha")) - { - return "Alpha"; - } - - return String.Empty; + return "Blue"; } - private void SetColorByName(string colorName, int colorValue) + if (name.Contains("Alpha")) { - if (colorName == "Red") - { - R = colorValue; - } - else if (colorName == "Green") - { - G = colorValue; - } - else if (colorName == "Blue") - { - B = colorValue; - } - else if (colorName == "Alpha") - { - A = colorValue; - } + return "Alpha"; } + return String.Empty; + } + + private void SetColorByName(string colorName, int colorValue) + { + if (colorName == "Red") + { + R = colorValue; + } + else if (colorName == "Green") + { + G = colorValue; + } + else if (colorName == "Blue") + { + B = colorValue; + } + else if (colorName == "Alpha") + { + A = colorValue; + } } } diff --git a/Intersect.Client.Framework/Gwen/Control/ColorSlider.cs b/Intersect.Client.Framework/Gwen/Control/ColorSlider.cs index d4489f89f3..9be0daf3e4 100644 --- a/Intersect.Client.Framework/Gwen/Control/ColorSlider.cs +++ b/Intersect.Client.Framework/Gwen/Control/ColorSlider.cs @@ -2,151 +2,149 @@ using Intersect.Client.Framework.Graphics; using Intersect.Client.Framework.Gwen.Input; -namespace Intersect.Client.Framework.Gwen.Control +namespace Intersect.Client.Framework.Gwen.Control; + + +/// +/// HSV hue selector. +/// +public partial class ColorSlider : Base { + private bool mDepressed; + + private int mSelectedDist; + + private GameTexture mTexture; + /// - /// HSV hue selector. + /// Initializes a new instance of the class. /// - public partial class ColorSlider : Base + /// Parent control. + public ColorSlider(Base parent) : base(parent) { + SetSize(32, 128); + MouseInputEnabled = true; + mDepressed = false; + } - private bool mDepressed; + /// + /// Selected color. + /// + public Color SelectedColor + { + get => GetColorAtHeight(mSelectedDist); + set => SetColor(value); + } - private int mSelectedDist; + /// + /// Invoked when the selected color has been changed. + /// + public event GwenEventHandler ColorChanged; - private GameTexture mTexture; + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public override void Dispose() + { + base.Dispose(); + } - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public ColorSlider(Base parent) : base(parent) - { - SetSize(32, 128); - MouseInputEnabled = true; - mDepressed = false; - } + /// + /// Renders the control using specified skin. + /// + /// Skin to use. + protected override void Render(Skin.Base skin) + { + skin.Renderer.DrawColor = Color.White; + skin.Renderer.DrawTexturedRect( + skin.Renderer.GetWhiteTexture(), new Rectangle(5, 0, Width - 10, Height), Color.White + ); + + var drawHeight = mSelectedDist - 3; + + //Draw our selectors + skin.Renderer.DrawColor = Color.Black; + skin.Renderer.DrawFilledRect(new Rectangle(0, drawHeight + 2, Width, 1)); + skin.Renderer.DrawFilledRect(new Rectangle(0, drawHeight, 5, 5)); + skin.Renderer.DrawFilledRect(new Rectangle(Width - 5, drawHeight, 5, 5)); + skin.Renderer.DrawColor = Color.White; + skin.Renderer.DrawFilledRect(new Rectangle(1, drawHeight + 1, 3, 3)); + skin.Renderer.DrawFilledRect(new Rectangle(Width - 4, drawHeight + 1, 3, 3)); + + base.Render(skin); + } - /// - /// Selected color. - /// - public Color SelectedColor + /// + /// Handler invoked on mouse click (left) event. + /// + /// X coordinate. + /// Y coordinate. + /// If set to true mouse button is down. + protected override void OnMouseClickedLeft(int x, int y, bool down, bool automated = false) + { + base.OnMouseClickedLeft(x, y, down); + mDepressed = down; + if (down) { - get => GetColorAtHeight(mSelectedDist); - set => SetColor(value); + InputHandler.MouseFocus = this; } - - /// - /// Invoked when the selected color has been changed. - /// - public event GwenEventHandler ColorChanged; - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public override void Dispose() + else { - base.Dispose(); + InputHandler.MouseFocus = null; } - /// - /// Renders the control using specified skin. - /// - /// Skin to use. - protected override void Render(Skin.Base skin) - { - skin.Renderer.DrawColor = Color.White; - skin.Renderer.DrawTexturedRect( - skin.Renderer.GetWhiteTexture(), new Rectangle(5, 0, Width - 10, Height), Color.White - ); - - var drawHeight = mSelectedDist - 3; - - //Draw our selectors - skin.Renderer.DrawColor = Color.Black; - skin.Renderer.DrawFilledRect(new Rectangle(0, drawHeight + 2, Width, 1)); - skin.Renderer.DrawFilledRect(new Rectangle(0, drawHeight, 5, 5)); - skin.Renderer.DrawFilledRect(new Rectangle(Width - 5, drawHeight, 5, 5)); - skin.Renderer.DrawColor = Color.White; - skin.Renderer.DrawFilledRect(new Rectangle(1, drawHeight + 1, 3, 3)); - skin.Renderer.DrawFilledRect(new Rectangle(Width - 4, drawHeight + 1, 3, 3)); - - base.Render(skin); - } + OnMouseMoved(x, y, 0, 0); + } - /// - /// Handler invoked on mouse click (left) event. - /// - /// X coordinate. - /// Y coordinate. - /// If set to true mouse button is down. - protected override void OnMouseClickedLeft(int x, int y, bool down, bool automated = false) + /// + /// Handler invoked on mouse moved event. + /// + /// X coordinate. + /// Y coordinate. + /// X change. + /// Y change. + protected override void OnMouseMoved(int x, int y, int dx, int dy) + { + if (mDepressed) { - base.OnMouseClickedLeft(x, y, down); - mDepressed = down; - if (down) + var cursorPos = CanvasPosToLocal(new Point(x, y)); + + if (cursorPos.Y < 0) { - InputHandler.MouseFocus = this; + cursorPos.Y = 0; } - else + + if (cursorPos.Y > Height) { - InputHandler.MouseFocus = null; + cursorPos.Y = Height; } - OnMouseMoved(x, y, 0, 0); - } - - /// - /// Handler invoked on mouse moved event. - /// - /// X coordinate. - /// Y coordinate. - /// X change. - /// Y change. - protected override void OnMouseMoved(int x, int y, int dx, int dy) - { - if (mDepressed) + mSelectedDist = cursorPos.Y; + if (ColorChanged != null) { - var cursorPos = CanvasPosToLocal(new Point(x, y)); - - if (cursorPos.Y < 0) - { - cursorPos.Y = 0; - } - - if (cursorPos.Y > Height) - { - cursorPos.Y = Height; - } - - mSelectedDist = cursorPos.Y; - if (ColorChanged != null) - { - ColorChanged.Invoke(this, EventArgs.Empty); - } + ColorChanged.Invoke(this, EventArgs.Empty); } } + } - private Color GetColorAtHeight(int y) - { - var yPercent = y / (float) Height; + private Color GetColorAtHeight(int y) + { + var yPercent = y / (float) Height; - return Util.HsvToColor(yPercent * 360, 1, 1); - } + return Util.HsvToColor(yPercent * 360, 1, 1); + } - private void SetColor(Color color) - { - var hsv = color.ToHsv(); + private void SetColor(Color color) + { + var hsv = color.ToHsv(); - mSelectedDist = (int) (hsv.H / 360 * Height); + mSelectedDist = (int) (hsv.H / 360 * Height); - if (ColorChanged != null) - { - ColorChanged.Invoke(this, EventArgs.Empty); - } + if (ColorChanged != null) + { + ColorChanged.Invoke(this, EventArgs.Empty); } - } } diff --git a/Intersect.Client.Framework/Gwen/Control/ComboBox.cs b/Intersect.Client.Framework/Gwen/Control/ComboBox.cs index 5c6e47c89a..76d94e4a30 100644 --- a/Intersect.Client.Framework/Gwen/Control/ComboBox.cs +++ b/Intersect.Client.Framework/Gwen/Control/ComboBox.cs @@ -4,532 +4,530 @@ using Newtonsoft.Json.Linq; -namespace Intersect.Client.Framework.Gwen.Control -{ +namespace Intersect.Client.Framework.Gwen.Control; - /// - /// ComboBox control. - /// - public partial class ComboBox : Button - { - private readonly Base mButton; +/// +/// ComboBox control. +/// +public partial class ComboBox : Button +{ + + private readonly Base mButton; - private string mCloseMenuSound; + private string mCloseMenuSound; - private string mHoverItemSound; + private string mHoverItemSound; - private string mHoverMenuSound; + private string mHoverMenuSound; - private Menu mMenu; + private Menu mMenu; - private bool mMenuAbove; + private bool mMenuAbove; - //Sound Effects - private string mOpenMenuSound; + //Sound Effects + private string mOpenMenuSound; - private MenuItem mSelectedItem; + private MenuItem mSelectedItem; - private string mSelectItemSound; + private string mSelectItemSound; - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - /// - public ComboBox(Base parent, string name = default) : base(parent, name) + /// + /// Initializes a new instance of the class. + /// + /// Parent control. + /// + public ComboBox(Base parent, string name = default) : base(parent, name) + { + SetSize(100, 20); + mMenu = new Menu(this) { - SetSize(100, 20); - mMenu = new Menu(this) - { - IsHidden = true, - IconMarginDisabled = true, - IsTabable = false - }; + IsHidden = true, + IconMarginDisabled = true, + IsTabable = false + }; - var arrow = new DownArrow(this); - mButton = arrow; + var arrow = new DownArrow(this); + mButton = arrow; - Alignment = Pos.Left | Pos.CenterV; - Text = string.Empty; - Margin = new Margin(3, 0, 0, 0); + Alignment = Pos.Left | Pos.CenterV; + Text = string.Empty; + Margin = new Margin(3, 0, 0, 0); - IsTabable = true; - KeyboardInputEnabled = true; - } + IsTabable = true; + KeyboardInputEnabled = true; + } - /// - /// Indicates whether the combo menu is open. - /// - public bool IsOpen => mMenu != null && !mMenu.IsHidden; + /// + /// Indicates whether the combo menu is open. + /// + public bool IsOpen => mMenu != null && !mMenu.IsHidden; - /// - /// Selected item. - /// - /// Not just String property, because items also have internal names. - public MenuItem SelectedItem + /// + /// Selected item. + /// + /// Not just String property, because items also have internal names. + public MenuItem SelectedItem + { + get => mSelectedItem; + set { - get => mSelectedItem; - set + if (value == null || value.Parent != mMenu) { - if (value == null || value.Parent != mMenu) - { - return; - } - - mSelectedItem = value; - OnItemSelected(mSelectedItem, new ItemSelectedEventArgs(value, true)); + return; } + + mSelectedItem = value; + OnItemSelected(mSelectedItem, new ItemSelectedEventArgs(value, true)); } + } - internal override bool IsMenuComponent => true; + internal override bool IsMenuComponent => true; - /// - /// Invoked when the selected item has changed. - /// - public event GwenEventHandler ItemSelected; + /// + /// Invoked when the selected item has changed. + /// + public event GwenEventHandler ItemSelected; - public void SetMenuAbove() + public void SetMenuAbove() + { + mMenuAbove = true; + if (IsOpen) { - mMenuAbove = true; - if (IsOpen) - { - Open(); - } + Open(); } + } - public void SetMenuBelow() + public void SetMenuBelow() + { + mMenuAbove = false; + if (IsOpen) { - mMenuAbove = false; - if (IsOpen) - { - Open(); - } + Open(); } + } + + public override JObject GetJson(bool isRoot = default) + { + var obj = base.GetJson(isRoot); + obj.Add("MenuAbove", mMenuAbove); + obj.Add("Menu", mMenu.GetJson()); + obj.Add("DropDownButton", mButton.GetJson()); + obj.Add("OpenMenuSound", mOpenMenuSound); + obj.Add("CloseMenuSound", mCloseMenuSound); + obj.Add("HoverMenuSound", mHoverMenuSound); + obj.Add("ItemHoverSound", mHoverItemSound); + obj.Add("SelectItemSound", mSelectItemSound); + + return base.FixJson(obj); + } - public override JObject GetJson(bool isRoot = default) + public override void LoadJson(JToken obj, bool isRoot = default) + { + base.LoadJson(obj); + if (obj["MenuAbove"] != null) { - var obj = base.GetJson(isRoot); - obj.Add("MenuAbove", mMenuAbove); - obj.Add("Menu", mMenu.GetJson()); - obj.Add("DropDownButton", mButton.GetJson()); - obj.Add("OpenMenuSound", mOpenMenuSound); - obj.Add("CloseMenuSound", mCloseMenuSound); - obj.Add("HoverMenuSound", mHoverMenuSound); - obj.Add("ItemHoverSound", mHoverItemSound); - obj.Add("SelectItemSound", mSelectItemSound); - - return base.FixJson(obj); + mMenuAbove = (bool)obj["MenuAbove"]; } - public override void LoadJson(JToken obj, bool isRoot = default) + if (obj["Menu"] != null) { - base.LoadJson(obj); - if (obj["MenuAbove"] != null) - { - mMenuAbove = (bool)obj["MenuAbove"]; - } - - if (obj["Menu"] != null) - { - mMenu.LoadJson(obj["Menu"]); - } + mMenu.LoadJson(obj["Menu"]); + } - if (obj["DropDownButton"] != null) - { - mButton.LoadJson(obj["DropDownButton"]); - } + if (obj["DropDownButton"] != null) + { + mButton.LoadJson(obj["DropDownButton"]); + } - if (obj["OpenMenuSound"] != null) - { - mOpenMenuSound = (string)obj["OpenMenuSound"]; - } + if (obj["OpenMenuSound"] != null) + { + mOpenMenuSound = (string)obj["OpenMenuSound"]; + } - if (obj["CloseMenuSound"] != null) - { - mCloseMenuSound = (string)obj["CloseMenuSound"]; - } + if (obj["CloseMenuSound"] != null) + { + mCloseMenuSound = (string)obj["CloseMenuSound"]; + } - if (obj["HoverMenuSound"] != null) - { - mHoverMenuSound = (string)obj["HoverMenuSound"]; - } + if (obj["HoverMenuSound"] != null) + { + mHoverMenuSound = (string)obj["HoverMenuSound"]; + } - if (obj["ItemHoverSound"] != null) - { - mHoverItemSound = (string)obj["ItemHoverSound"]; - } + if (obj["ItemHoverSound"] != null) + { + mHoverItemSound = (string)obj["ItemHoverSound"]; + } - if (obj["SelectItemSound"] != null) - { - mSelectItemSound = (string)obj["SelectItemSound"]; - } + if (obj["SelectItemSound"] != null) + { + mSelectItemSound = (string)obj["SelectItemSound"]; + } - foreach (var child in Children) + foreach (var child in Children) + { + if (child is Menu menu) { - if (child is Menu menu) + foreach (var menuChild in menu.Children) { - foreach (var menuChild in menu.Children) + if (menuChild is MenuItem menuItem) { - if (menuChild is MenuItem menuItem) - { - menuItem.SetHoverSound(mHoverItemSound); - } + menuItem.SetHoverSound(mHoverItemSound); } } } } + } - /// - /// Adds a new item. - /// - /// Item label (displayed). - /// Item name. - /// Newly created control. - public virtual MenuItem AddItem(string label, string name = "", object userData = null) + /// + /// Adds a new item. + /// + /// Item label (displayed). + /// Item name. + /// Newly created control. + public virtual MenuItem AddItem(string label, string name = "", object userData = null) + { + var item = mMenu.AddItem(label, null, "", "", this.Font); + item.Name = name; + item.Selected += OnItemSelected; + item.UserData = userData; + item.SetTextColor(GetTextColor(Label.ControlState.Normal), Label.ControlState.Normal); + item.SetTextColor(GetTextColor(Label.ControlState.Hovered), Label.ControlState.Hovered); + item.SetTextColor(GetTextColor(Label.ControlState.Clicked), Label.ControlState.Clicked); + item.SetTextColor(GetTextColor(Label.ControlState.Disabled), Label.ControlState.Disabled); + item.SetHoverSound(mHoverItemSound); + + if (mSelectedItem == null) { - var item = mMenu.AddItem(label, null, "", "", this.Font); - item.Name = name; - item.Selected += OnItemSelected; - item.UserData = userData; - item.SetTextColor(GetTextColor(Label.ControlState.Normal), Label.ControlState.Normal); - item.SetTextColor(GetTextColor(Label.ControlState.Hovered), Label.ControlState.Hovered); - item.SetTextColor(GetTextColor(Label.ControlState.Clicked), Label.ControlState.Clicked); - item.SetTextColor(GetTextColor(Label.ControlState.Disabled), Label.ControlState.Disabled); - item.SetHoverSound(mHoverItemSound); - - if (mSelectedItem == null) - { - OnItemSelected(item, new ItemSelectedEventArgs(null, true)); - } + OnItemSelected(item, new ItemSelectedEventArgs(null, true)); + } + + return item; + } - return item; + /// + /// Renders the control using specified skin. + /// + /// Skin to use. + protected override void Render(Skin.Base skin) + { + skin.DrawComboBox(this, IsDepressed, IsOpen); + } + + public override void Disable() + { + base.Disable(); + GetCanvas().CloseMenus(); + } + + /// + /// Internal Pressed implementation. + /// + protected override void OnClicked(int x, int y) + { + if (IsOpen) + { + GetCanvas().CloseMenus(); + + return; } - /// - /// Renders the control using specified skin. - /// - /// Skin to use. - protected override void Render(Skin.Base skin) + var wasMenuHidden = mMenu.IsHidden; + + GetCanvas().CloseMenus(); + + if (wasMenuHidden) { - skin.DrawComboBox(this, IsDepressed, IsOpen); + Open(); } - public override void Disable() + base.OnClicked(x, y); + } + + /// + /// Removes all items. + /// + public virtual void DeleteAll() + { + if (mMenu != null) { - base.Disable(); - GetCanvas().CloseMenus(); + mMenu.DeleteAll(); } + } - /// - /// Internal Pressed implementation. - /// - protected override void OnClicked(int x, int y) + /// + /// Internal handler for item selected event. + /// + /// Event source. + protected virtual void OnItemSelected(Base control, ItemSelectedEventArgs args) + { + if (!IsDisabled) { - if (IsOpen) + //Convert selected to a menu item + var item = control as MenuItem; + if (null == item) { - GetCanvas().CloseMenus(); - return; } - var wasMenuHidden = mMenu.IsHidden; + mSelectedItem = item; + Text = mSelectedItem.Text; + mMenu.IsHidden = true; - GetCanvas().CloseMenus(); - - if (wasMenuHidden) + if (ItemSelected != null) { - Open(); + ItemSelected.Invoke(this, args); } - base.OnClicked(x, y); - } - - /// - /// Removes all items. - /// - public virtual void DeleteAll() - { - if (mMenu != null) + if (!args.Automated) { - mMenu.DeleteAll(); + base.PlaySound(mSelectItemSound); } + + Focus(); + Invalidate(); } + } - /// - /// Internal handler for item selected event. - /// - /// Event source. - protected virtual void OnItemSelected(Base control, ItemSelectedEventArgs args) + /// + /// Lays out the control's interior according to alignment, padding, dock etc. + /// + /// Skin to use. + protected override void Layout(Skin.Base skin) + { + mButton.Position(Pos.Right | Pos.CenterV, 4, 0); + base.Layout(skin); + } + + /// + /// Handler for losing keyboard focus. + /// + protected override void OnLostKeyboardFocus() + { + if (GetTextColor(Label.ControlState.Normal) != null) { - if (!IsDisabled) - { - //Convert selected to a menu item - var item = control as MenuItem; - if (null == item) - { - return; - } + TextColor = GetTextColor(Label.ControlState.Normal); - mSelectedItem = item; - Text = mSelectedItem.Text; - mMenu.IsHidden = true; + return; + } - if (ItemSelected != null) - { - ItemSelected.Invoke(this, args); - } + TextColor = Color.Black; + } - if (!args.Automated) - { - base.PlaySound(mSelectItemSound); - } + /// + /// Handler for gaining keyboard focus. + /// + protected override void OnKeyboardFocus() + { + //Until we add the blue highlighting again + if (GetTextColor(Label.ControlState.Normal) != null) + { + TextColor = GetTextColor(Label.ControlState.Normal); - Focus(); - Invalidate(); - } + return; } - /// - /// Lays out the control's interior according to alignment, padding, dock etc. - /// - /// Skin to use. - protected override void Layout(Skin.Base skin) - { - mButton.Position(Pos.Right | Pos.CenterV, 4, 0); - base.Layout(skin); - } + TextColor = Color.Black; + } - /// - /// Handler for losing keyboard focus. - /// - protected override void OnLostKeyboardFocus() + /// + /// Opens the combo. + /// + public virtual void Open() + { + if (!IsDisabled) { - if (GetTextColor(Label.ControlState.Normal) != null) + if (null == mMenu) { - TextColor = GetTextColor(Label.ControlState.Normal); - return; } - TextColor = Color.Black; - } + mMenu.Parent = GetCanvas(); + mMenu.IsHidden = false; + mMenu.BringToFront(); - /// - /// Handler for gaining keyboard focus. - /// - protected override void OnKeyboardFocus() - { - //Until we add the blue highlighting again - if (GetTextColor(Label.ControlState.Normal) != null) + var p = LocalPosToCanvas(Point.Empty); + if (mMenuAbove) { - TextColor = GetTextColor(Label.ControlState.Normal); - - return; + mMenu.RestrictToParent = false; + mMenu.Height = mMenu.Children.Sum(child => child != null ? child.Height : 0); + mMenu.SetBounds(new Rectangle(p.X, p.Y - mMenu.Height, Width, mMenu.Height)); + mMenu.RestrictToParent = true; } - - TextColor = Color.Black; - } - - /// - /// Opens the combo. - /// - public virtual void Open() - { - if (!IsDisabled) + else { - if (null == mMenu) - { - return; - } - - mMenu.Parent = GetCanvas(); - mMenu.IsHidden = false; - mMenu.BringToFront(); - - var p = LocalPosToCanvas(Point.Empty); - if (mMenuAbove) - { - mMenu.RestrictToParent = false; - mMenu.Height = mMenu.Children.Sum(child => child != null ? child.Height : 0); - mMenu.SetBounds(new Rectangle(p.X, p.Y - mMenu.Height, Width, mMenu.Height)); - mMenu.RestrictToParent = true; - } - else - { - mMenu.SetBounds(new Rectangle(p.X, p.Y + Height, Width, mMenu.Height)); - } - - base.PlaySound(mOpenMenuSound); + mMenu.SetBounds(new Rectangle(p.X, p.Y + Height, Width, mMenu.Height)); } + + base.PlaySound(mOpenMenuSound); } + } - /// - /// Closes the combo. - /// - public virtual void Close() + /// + /// Closes the combo. + /// + public virtual void Close() + { + if (mMenu == null) { - if (mMenu == null) - { - return; - } + return; + } - mMenu.Hide(); + mMenu.Hide(); - base.PlaySound(mCloseMenuSound); - } + base.PlaySound(mCloseMenuSound); + } - /// - /// Handler for Down Arrow keyboard event. - /// - /// Indicates whether the key was pressed or released. - /// - /// True if handled. - /// - protected override bool OnKeyDown(bool down) + /// + /// Handler for Down Arrow keyboard event. + /// + /// Indicates whether the key was pressed or released. + /// + /// True if handled. + /// + protected override bool OnKeyDown(bool down) + { + if (down) { - if (down) + var it = mMenu.Children.FindIndex(x => x == mSelectedItem); + if (it + 1 < mMenu.Children.Count) { - var it = mMenu.Children.FindIndex(x => x == mSelectedItem); - if (it + 1 < mMenu.Children.Count) - { - OnItemSelected(this, new ItemSelectedEventArgs(mMenu.Children[it + 1])); - } + OnItemSelected(this, new ItemSelectedEventArgs(mMenu.Children[it + 1])); } - - return true; } - /// - /// Handler for Up Arrow keyboard event. - /// - /// Indicates whether the key was pressed or released. - /// - /// True if handled. - /// - protected override bool OnKeyUp(bool down) + return true; + } + + /// + /// Handler for Up Arrow keyboard event. + /// + /// Indicates whether the key was pressed or released. + /// + /// True if handled. + /// + protected override bool OnKeyUp(bool down) + { + if (down) { - if (down) + var it = mMenu.Children.FindLastIndex(x => x == mSelectedItem); + if (it - 1 >= 0) { - var it = mMenu.Children.FindLastIndex(x => x == mSelectedItem); - if (it - 1 >= 0) - { - OnItemSelected(this, new ItemSelectedEventArgs(mMenu.Children[it - 1])); - } + OnItemSelected(this, new ItemSelectedEventArgs(mMenu.Children[it - 1])); } - - return true; } - /// - /// Renders the focus overlay. - /// - /// Skin to use. - protected override void RenderFocus(Skin.Base skin) - { - } + return true; + } + + /// + /// Renders the focus overlay. + /// + /// Skin to use. + protected override void RenderFocus(Skin.Base skin) + { + } - /// - /// Selects the first menu item with the given text it finds. - /// If a menu item can not be found that matches input, nothing happens. - /// - /// The label to look for, this is what is shown to the user. - public void SelectByText(string text) + /// + /// Selects the first menu item with the given text it finds. + /// If a menu item can not be found that matches input, nothing happens. + /// + /// The label to look for, this is what is shown to the user. + public void SelectByText(string text) + { + foreach (MenuItem item in mMenu.Children) { - foreach (MenuItem item in mMenu.Children) + if (item.Text == text) { - if (item.Text == text) - { - SelectedItem = item; + SelectedItem = item; - return; - } + return; } } + } - /// - /// Selects the first menu item with the given internal name it finds. - /// If a menu item can not be found that matches input, nothing happens. - /// - /// The internal name to look for. To select by what is displayed to the user, use "SelectByText". - public void SelectByName(string name) + /// + /// Selects the first menu item with the given internal name it finds. + /// If a menu item can not be found that matches input, nothing happens. + /// + /// The internal name to look for. To select by what is displayed to the user, use "SelectByText". + public void SelectByName(string name) + { + foreach (MenuItem item in mMenu.Children) { - foreach (MenuItem item in mMenu.Children) + if (item.Name == name) { - if (item.Name == name) - { - SelectedItem = item; + SelectedItem = item; - return; - } + return; } } + } - /// - /// Selects the first menu item with the given user data it finds. - /// If a menu item can not be found that matches input, nothing happens. - /// - /// - /// The UserData to look for. The equivalency check uses "param.Equals(item.UserData)". - /// If null is passed in, it will look for null/unset UserData. - /// - public void SelectByUserData(object userdata) + /// + /// Selects the first menu item with the given user data it finds. + /// If a menu item can not be found that matches input, nothing happens. + /// + /// + /// The UserData to look for. The equivalency check uses "param.Equals(item.UserData)". + /// If null is passed in, it will look for null/unset UserData. + /// + public void SelectByUserData(object userdata) + { + foreach (MenuItem item in mMenu.Children) { - foreach (MenuItem item in mMenu.Children) + if (userdata == null) { - if (userdata == null) - { - if (item.UserData == null) - { - SelectedItem = item; - - return; - } - } - else if (userdata.Equals(item.UserData)) + if (item.UserData == null) { SelectedItem = item; return; } } - } + else if (userdata.Equals(item.UserData)) + { + SelectedItem = item; - public void SetMenuBackgroundColor(Color clr) - { - mMenu.RenderColor = clr; + return; + } } + } - public void SetMenuMaxSize(int w, int h) - { - mMenu.MaximumSize = new Point(w, h); - } + public void SetMenuBackgroundColor(Color clr) + { + mMenu.RenderColor = clr; + } - public override void SetTextColor(Color clr, Label.ControlState state) - { - base.SetTextColor(clr, state); - foreach (MenuItem itm in mMenu.Children) - { - itm.SetTextColor(clr, state); - } - } + public void SetMenuMaxSize(int w, int h) + { + mMenu.MaximumSize = new Point(w, h); + } - public void SetMenu(Menu menu) + public override void SetTextColor(Color clr, Label.ControlState state) + { + base.SetTextColor(clr, state); + foreach (MenuItem itm in mMenu.Children) { - mMenu = menu; + itm.SetTextColor(clr, state); } + } - protected override void OnMouseEntered() - { - base.OnMouseEntered(); + public void SetMenu(Menu menu) + { + mMenu = menu; + } - //Play Mouse Entered Sound - if (!IsOpen && ShouldDrawHover) - { - base.PlaySound(mHoverMenuSound); - } - } + protected override void OnMouseEntered() + { + base.OnMouseEntered(); + //Play Mouse Entered Sound + if (!IsOpen && ShouldDrawHover) + { + base.PlaySound(mHoverMenuSound); + } } } diff --git a/Intersect.Client.Framework/Gwen/Control/CrossSplitter.cs b/Intersect.Client.Framework/Gwen/Control/CrossSplitter.cs index efa217482c..2e35913a39 100644 --- a/Intersect.Client.Framework/Gwen/Control/CrossSplitter.cs +++ b/Intersect.Client.Framework/Gwen/Control/CrossSplitter.cs @@ -1,317 +1,315 @@ using Intersect.Client.Framework.GenericClasses; using Intersect.Client.Framework.Gwen.ControlInternal; -namespace Intersect.Client.Framework.Gwen.Control -{ +namespace Intersect.Client.Framework.Gwen.Control; - /// - /// Splitter control. - /// - public partial class CrossSplitter : Base - { - private readonly SplitterBar mCSplitter; +/// +/// Splitter control. +/// +public partial class CrossSplitter : Base +{ - private readonly SplitterBar mHSplitter; + private readonly SplitterBar mCSplitter; - private readonly Base[] mSections; + private readonly SplitterBar mHSplitter; - private readonly SplitterBar mVSplitter; + private readonly Base[] mSections; - private int mBarSize; // pixels + private readonly SplitterBar mVSplitter; - private float mHVal; // 0-1 + private int mBarSize; // pixels - private float mVVal; // 0-1 + private float mHVal; // 0-1 - private int mZoomedSection; // 0-3 + private float mVVal; // 0-1 - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public CrossSplitter(Base parent) : base(parent) - { - mSections = new Base[4]; + private int mZoomedSection; // 0-3 - mVSplitter = new SplitterBar(this); - mVSplitter.SetPosition(0, 128); - mVSplitter.Dragged += OnVerticalMoved; - mVSplitter.Cursor = Cursors.SizeNs; + /// + /// Initializes a new instance of the class. + /// + /// Parent control. + public CrossSplitter(Base parent) : base(parent) + { + mSections = new Base[4]; - mHSplitter = new SplitterBar(this); - mHSplitter.SetPosition(128, 0); - mHSplitter.Dragged += OnHorizontalMoved; - mHSplitter.Cursor = Cursors.SizeWe; + mVSplitter = new SplitterBar(this); + mVSplitter.SetPosition(0, 128); + mVSplitter.Dragged += OnVerticalMoved; + mVSplitter.Cursor = Cursors.SizeNs; - mCSplitter = new SplitterBar(this); - mCSplitter.SetPosition(128, 128); - mCSplitter.Dragged += OnCenterMoved; - mCSplitter.Cursor = Cursors.SizeAll; + mHSplitter = new SplitterBar(this); + mHSplitter.SetPosition(128, 0); + mHSplitter.Dragged += OnHorizontalMoved; + mHSplitter.Cursor = Cursors.SizeWe; - mHVal = 0.5f; - mVVal = 0.5f; + mCSplitter = new SplitterBar(this); + mCSplitter.SetPosition(128, 128); + mCSplitter.Dragged += OnCenterMoved; + mCSplitter.Cursor = Cursors.SizeAll; - SetPanel(0, null); - SetPanel(1, null); - SetPanel(2, null); - SetPanel(3, null); + mHVal = 0.5f; + mVVal = 0.5f; - SplitterSize = 5; - SplittersVisible = false; + SetPanel(0, null); + SetPanel(1, null); + SetPanel(2, null); + SetPanel(3, null); - mZoomedSection = -1; - } + SplitterSize = 5; + SplittersVisible = false; - /// - /// Indicates whether any of the panels is zoomed. - /// - public bool IsZoomed => mZoomedSection != -1; + mZoomedSection = -1; + } - /// - /// Gets or sets a value indicating whether splitters should be visible. - /// - public bool SplittersVisible - { - get => mCSplitter.ShouldDrawBackground; - set - { - mCSplitter.ShouldDrawBackground = value; - mVSplitter.ShouldDrawBackground = value; - mHSplitter.ShouldDrawBackground = value; - } - } + /// + /// Indicates whether any of the panels is zoomed. + /// + public bool IsZoomed => mZoomedSection != -1; - /// - /// Gets or sets the size of the splitter. - /// - public int SplitterSize + /// + /// Gets or sets a value indicating whether splitters should be visible. + /// + public bool SplittersVisible + { + get => mCSplitter.ShouldDrawBackground; + set { - get => mBarSize; - set => mBarSize = value; + mCSplitter.ShouldDrawBackground = value; + mVSplitter.ShouldDrawBackground = value; + mHSplitter.ShouldDrawBackground = value; } + } - /// - /// Invoked when one of the panels has been zoomed (maximized). - /// - public event GwenEventHandler PanelZoomed; - - /// - /// Invoked when one of the panels has been unzoomed (restored). - /// - public event GwenEventHandler PanelUnZoomed; - - /// - /// Invoked when the zoomed panel has been changed. - /// - public event GwenEventHandler ZoomChanged; - - /// - /// Centers the panels so that they take even amount of space. - /// - public void CenterPanels() - { - mHVal = 0.5f; - mVVal = 0.5f; - Invalidate(); - } + /// + /// Gets or sets the size of the splitter. + /// + public int SplitterSize + { + get => mBarSize; + set => mBarSize = value; + } - private void UpdateVSplitter() - { - mVSplitter.MoveTo(mVSplitter.X, (Height - mVSplitter.Height) * mVVal); - } + /// + /// Invoked when one of the panels has been zoomed (maximized). + /// + public event GwenEventHandler PanelZoomed; - private void UpdateHSplitter() - { - mHSplitter.MoveTo((Width - mHSplitter.Width) * mHVal, mHSplitter.Y); - } + /// + /// Invoked when one of the panels has been unzoomed (restored). + /// + public event GwenEventHandler PanelUnZoomed; - private void UpdateCSplitter() - { - mCSplitter.MoveTo((Width - mCSplitter.Width) * mHVal, (Height - mCSplitter.Height) * mVVal); - } + /// + /// Invoked when the zoomed panel has been changed. + /// + public event GwenEventHandler ZoomChanged; - protected void OnCenterMoved(Base control, EventArgs args) - { - CalculateValueCenter(); - Invalidate(); - } + /// + /// Centers the panels so that they take even amount of space. + /// + public void CenterPanels() + { + mHVal = 0.5f; + mVVal = 0.5f; + Invalidate(); + } - protected void OnVerticalMoved(Base control, EventArgs args) - { - mVVal = CalculateValueVertical(); - Invalidate(); - } + private void UpdateVSplitter() + { + mVSplitter.MoveTo(mVSplitter.X, (Height - mVSplitter.Height) * mVVal); + } - protected void OnHorizontalMoved(Base control, EventArgs args) - { - mHVal = CalculateValueHorizontal(); - Invalidate(); - } + private void UpdateHSplitter() + { + mHSplitter.MoveTo((Width - mHSplitter.Width) * mHVal, mHSplitter.Y); + } - private void CalculateValueCenter() - { - mHVal = mCSplitter.X / (float) (Width - mCSplitter.Width); - mVVal = mCSplitter.Y / (float) (Height - mCSplitter.Height); - } + private void UpdateCSplitter() + { + mCSplitter.MoveTo((Width - mCSplitter.Width) * mHVal, (Height - mCSplitter.Height) * mVVal); + } - private float CalculateValueVertical() - { - return mVSplitter.Y / (float) (Height - mVSplitter.Height); - } + protected void OnCenterMoved(Base control, EventArgs args) + { + CalculateValueCenter(); + Invalidate(); + } - private float CalculateValueHorizontal() - { - return mHSplitter.X / (float) (Width - mHSplitter.Width); - } + protected void OnVerticalMoved(Base control, EventArgs args) + { + mVVal = CalculateValueVertical(); + Invalidate(); + } - /// - /// Lays out the control's interior according to alignment, padding, dock etc. - /// - /// Skin to use. - protected override void Layout(Skin.Base skin) - { - mVSplitter.SetSize(Width, mBarSize); - mHSplitter.SetSize(mBarSize, Height); - mCSplitter.SetSize(mBarSize, mBarSize); + protected void OnHorizontalMoved(Base control, EventArgs args) + { + mHVal = CalculateValueHorizontal(); + Invalidate(); + } - UpdateVSplitter(); - UpdateHSplitter(); - UpdateCSplitter(); + private void CalculateValueCenter() + { + mHVal = mCSplitter.X / (float) (Width - mCSplitter.Width); + mVVal = mCSplitter.Y / (float) (Height - mCSplitter.Height); + } - if (mZoomedSection == -1) - { - if (mSections[0] != null) - { - mSections[0].SetBounds(0, 0, mHSplitter.X, mVSplitter.Y); - } + private float CalculateValueVertical() + { + return mVSplitter.Y / (float) (Height - mVSplitter.Height); + } - if (mSections[1] != null) - { - mSections[1].SetBounds(mHSplitter.X + mBarSize, 0, Width - (mHSplitter.X + mBarSize), mVSplitter.Y); - } + private float CalculateValueHorizontal() + { + return mHSplitter.X / (float) (Width - mHSplitter.Width); + } - if (mSections[2] != null) - { - mSections[2] - .SetBounds(0, mVSplitter.Y + mBarSize, mHSplitter.X, Height - (mVSplitter.Y + mBarSize)); - } + /// + /// Lays out the control's interior according to alignment, padding, dock etc. + /// + /// Skin to use. + protected override void Layout(Skin.Base skin) + { + mVSplitter.SetSize(Width, mBarSize); + mHSplitter.SetSize(mBarSize, Height); + mCSplitter.SetSize(mBarSize, mBarSize); - if (mSections[3] != null) - { - mSections[3] - .SetBounds( - mHSplitter.X + mBarSize, mVSplitter.Y + mBarSize, Width - (mHSplitter.X + mBarSize), - Height - (mVSplitter.Y + mBarSize) - ); - } - } - else + UpdateVSplitter(); + UpdateHSplitter(); + UpdateCSplitter(); + + if (mZoomedSection == -1) + { + if (mSections[0] != null) { - //This should probably use Fill docking instead - mSections[mZoomedSection].SetBounds(0, 0, Width, Height); + mSections[0].SetBounds(0, 0, mHSplitter.X, mVSplitter.Y); } - } - /// - /// Assigns a control to the specific inner section. - /// - /// Section index (0-3). - /// Control to assign. - public void SetPanel(int index, Base panel) - { - mSections[index] = panel; + if (mSections[1] != null) + { + mSections[1].SetBounds(mHSplitter.X + mBarSize, 0, Width - (mHSplitter.X + mBarSize), mVSplitter.Y); + } - if (panel != null) + if (mSections[2] != null) { - panel.Dock = Pos.None; - panel.Parent = this; + mSections[2] + .SetBounds(0, mVSplitter.Y + mBarSize, mHSplitter.X, Height - (mVSplitter.Y + mBarSize)); } - Invalidate(); + if (mSections[3] != null) + { + mSections[3] + .SetBounds( + mHSplitter.X + mBarSize, mVSplitter.Y + mBarSize, Width - (mHSplitter.X + mBarSize), + Height - (mVSplitter.Y + mBarSize) + ); + } + } + else + { + //This should probably use Fill docking instead + mSections[mZoomedSection].SetBounds(0, 0, Width, Height); } + } - /// - /// Gets the specific inner section. - /// - /// Section index (0-3). - /// Specified section. - public Base GetPanel(int index) + /// + /// Assigns a control to the specific inner section. + /// + /// Section index (0-3). + /// Control to assign. + public void SetPanel(int index, Base panel) + { + mSections[index] = panel; + + if (panel != null) { - return mSections[index]; + panel.Dock = Pos.None; + panel.Parent = this; } - /// - /// Internal handler for the zoom changed event. - /// - protected void OnZoomChanged() + Invalidate(); + } + + /// + /// Gets the specific inner section. + /// + /// Section index (0-3). + /// Specified section. + public Base GetPanel(int index) + { + return mSections[index]; + } + + /// + /// Internal handler for the zoom changed event. + /// + protected void OnZoomChanged() + { + if (ZoomChanged != null) { - if (ZoomChanged != null) - { - ZoomChanged.Invoke(this, EventArgs.Empty); - } + ZoomChanged.Invoke(this, EventArgs.Empty); + } - if (mZoomedSection == -1) + if (mZoomedSection == -1) + { + if (PanelUnZoomed != null) { - if (PanelUnZoomed != null) - { - PanelUnZoomed.Invoke(this, EventArgs.Empty); - } + PanelUnZoomed.Invoke(this, EventArgs.Empty); } - else + } + else + { + if (PanelZoomed != null) { - if (PanelZoomed != null) - { - PanelZoomed.Invoke(this, EventArgs.Empty); - } + PanelZoomed.Invoke(this, EventArgs.Empty); } } + } - /// - /// Maximizes the specified panel so it fills the entire control. - /// - /// Panel index (0-3). - public void Zoom(int section) - { - UnZoom(); + /// + /// Maximizes the specified panel so it fills the entire control. + /// + /// Panel index (0-3). + public void Zoom(int section) + { + UnZoom(); - if (mSections[section] != null) + if (mSections[section] != null) + { + for (var i = 0; i < 4; i++) { - for (var i = 0; i < 4; i++) + if (i != section && mSections[i] != null) { - if (i != section && mSections[i] != null) - { - mSections[i].IsHidden = true; - } + mSections[i].IsHidden = true; } - - mZoomedSection = section; - - Invalidate(); } - OnZoomChanged(); + mZoomedSection = section; + + Invalidate(); } - /// - /// Restores the control so all panels are visible. - /// - public void UnZoom() - { - mZoomedSection = -1; + OnZoomChanged(); + } - for (var i = 0; i < 4; i++) + /// + /// Restores the control so all panels are visible. + /// + public void UnZoom() + { + mZoomedSection = -1; + + for (var i = 0; i < 4; i++) + { + if (mSections[i] != null) { - if (mSections[i] != null) - { - mSections[i].IsHidden = false; - } + mSections[i].IsHidden = false; } - - Invalidate(); - OnZoomChanged(); } + Invalidate(); + OnZoomChanged(); } } diff --git a/Intersect.Client.Framework/Gwen/Control/Data/ITableCellDataProvider.cs b/Intersect.Client.Framework/Gwen/Control/Data/ITableCellDataProvider.cs index 9bb0c6fe6b..e032ff76f2 100644 --- a/Intersect.Client.Framework/Gwen/Control/Data/ITableCellDataProvider.cs +++ b/Intersect.Client.Framework/Gwen/Control/Data/ITableCellDataProvider.cs @@ -1,22 +1,21 @@ -namespace Intersect.Client.Framework.Gwen.Control.Data +namespace Intersect.Client.Framework.Gwen.Control.Data; + +public partial class CellDataChangedEventArgs : EventArgs { - public partial class CellDataChangedEventArgs : EventArgs + public CellDataChangedEventArgs(object oldValue, object newValue) { - public CellDataChangedEventArgs(object oldValue, object newValue) - { - OldValue = oldValue; - NewValue = newValue; - } + OldValue = oldValue; + NewValue = newValue; + } - public object OldValue { get; } + public object OldValue { get; } - public object NewValue { get; } - } + public object NewValue { get; } +} - public delegate void TableCellDataChangedEventHandler(object sender, CellDataChangedEventArgs args); +public delegate void TableCellDataChangedEventHandler(object sender, CellDataChangedEventArgs args); - public interface ITableCellDataProvider - { - event TableCellDataChangedEventHandler DataChanged; - } +public interface ITableCellDataProvider +{ + event TableCellDataChangedEventHandler DataChanged; } diff --git a/Intersect.Client.Framework/Gwen/Control/Data/ITableDataProvider.cs b/Intersect.Client.Framework/Gwen/Control/Data/ITableDataProvider.cs index a358f6681d..c54897df77 100644 --- a/Intersect.Client.Framework/Gwen/Control/Data/ITableDataProvider.cs +++ b/Intersect.Client.Framework/Gwen/Control/Data/ITableDataProvider.cs @@ -1,20 +1,19 @@ -namespace Intersect.Client.Framework.Gwen.Control.Data +namespace Intersect.Client.Framework.Gwen.Control.Data; + +public partial class TableDataChangedEventArgs : RowDataChangedEventArgs { - public partial class TableDataChangedEventArgs : RowDataChangedEventArgs + public TableDataChangedEventArgs(int row, int column, object oldValue, object newValue) + : base(column, oldValue, newValue) { - public TableDataChangedEventArgs(int row, int column, object oldValue, object newValue) - : base(column, oldValue, newValue) - { - Row = row; - } - - public int Row { get; } + Row = row; } - public delegate void TableDataChangedEventHandler(object sender, TableDataChangedEventArgs args); + public int Row { get; } +} - public interface ITableDataProvider - { - event TableDataChangedEventHandler DataChanged; - } +public delegate void TableDataChangedEventHandler(object sender, TableDataChangedEventArgs args); + +public interface ITableDataProvider +{ + event TableDataChangedEventHandler DataChanged; } diff --git a/Intersect.Client.Framework/Gwen/Control/Data/ITableRowDataProvider.cs b/Intersect.Client.Framework/Gwen/Control/Data/ITableRowDataProvider.cs index a0a965b1dd..df83d58e69 100644 --- a/Intersect.Client.Framework/Gwen/Control/Data/ITableRowDataProvider.cs +++ b/Intersect.Client.Framework/Gwen/Control/Data/ITableRowDataProvider.cs @@ -1,20 +1,19 @@ -namespace Intersect.Client.Framework.Gwen.Control.Data +namespace Intersect.Client.Framework.Gwen.Control.Data; + +public partial class RowDataChangedEventArgs : CellDataChangedEventArgs { - public partial class RowDataChangedEventArgs : CellDataChangedEventArgs + public RowDataChangedEventArgs(int column, object oldValue, object newValue) + : base(oldValue, newValue) { - public RowDataChangedEventArgs(int column, object oldValue, object newValue) - : base(oldValue, newValue) - { - Column = column; - } - - public int Column { get; } + Column = column; } - public delegate void TableRowDataChangedEventHandler(object sender, RowDataChangedEventArgs args); + public int Column { get; } +} - public interface ITableRowDataProvider - { - event TableRowDataChangedEventHandler DataChanged; - } +public delegate void TableRowDataChangedEventHandler(object sender, RowDataChangedEventArgs args); + +public interface ITableRowDataProvider +{ + event TableRowDataChangedEventHandler DataChanged; } diff --git a/Intersect.Client.Framework/Gwen/Control/Data/ValueTableCellDataProvider`1.cs b/Intersect.Client.Framework/Gwen/Control/Data/ValueTableCellDataProvider`1.cs index 4daacff738..8fa1c71317 100644 --- a/Intersect.Client.Framework/Gwen/Control/Data/ValueTableCellDataProvider`1.cs +++ b/Intersect.Client.Framework/Gwen/Control/Data/ValueTableCellDataProvider`1.cs @@ -1,39 +1,38 @@ using Intersect.Async; -namespace Intersect.Client.Framework.Gwen.Control.Data +namespace Intersect.Client.Framework.Gwen.Control.Data; + +public partial class ValueTableCellDataProvider : ITableCellDataProvider { - public partial class ValueTableCellDataProvider : ITableCellDataProvider + public ValueTableCellDataProvider(Func provideValue, int delay = 100) { - public ValueTableCellDataProvider(Func provideValue, int delay = 100) + AsyncValueGenerator CreateValueGenerator(CancellationToken cancellationToken) { - AsyncValueGenerator CreateValueGenerator(CancellationToken cancellationToken) - { - return new AsyncValueGenerator( - () => Task.Delay(delay).ContinueWith((_) => cancellationToken.IsCancellationRequested ? default : provideValue(), TaskScheduler.Current), - value => DataChanged?.Invoke(this, new CellDataChangedEventArgs(default, value)), - cancellationToken - ); - } - - Generator = new CancellableGenerator(CreateValueGenerator); + return new AsyncValueGenerator( + () => Task.Delay(delay).ContinueWith((_) => cancellationToken.IsCancellationRequested ? default : provideValue(), TaskScheduler.Current), + value => DataChanged?.Invoke(this, new CellDataChangedEventArgs(default, value)), + cancellationToken + ); } - public ValueTableCellDataProvider(Func provideValue) - { - AsyncValueGenerator CreateValueGenerator(CancellationToken cancellationToken) - { - return new AsyncValueGenerator( - () => Task.Delay(100).ContinueWith((_) => cancellationToken.IsCancellationRequested ? default : provideValue(cancellationToken), TaskScheduler.Current), - value => DataChanged?.Invoke(this, new CellDataChangedEventArgs(default, value)), - cancellationToken - ); - } + Generator = new CancellableGenerator(CreateValueGenerator); + } - Generator = new CancellableGenerator(CreateValueGenerator); + public ValueTableCellDataProvider(Func provideValue) + { + AsyncValueGenerator CreateValueGenerator(CancellationToken cancellationToken) + { + return new AsyncValueGenerator( + () => Task.Delay(100).ContinueWith((_) => cancellationToken.IsCancellationRequested ? default : provideValue(cancellationToken), TaskScheduler.Current), + value => DataChanged?.Invoke(this, new CellDataChangedEventArgs(default, value)), + cancellationToken + ); } - public event TableCellDataChangedEventHandler DataChanged; - - public CancellableGenerator Generator { get; } + Generator = new CancellableGenerator(CreateValueGenerator); } + + public event TableCellDataChangedEventHandler DataChanged; + + public CancellableGenerator Generator { get; } } diff --git a/Intersect.Client.Framework/Gwen/Control/DockBase.cs b/Intersect.Client.Framework/Gwen/Control/DockBase.cs index 9555c6bb2e..225111ae5a 100644 --- a/Intersect.Client.Framework/Gwen/Control/DockBase.cs +++ b/Intersect.Client.Framework/Gwen/Control/DockBase.cs @@ -2,549 +2,547 @@ using Intersect.Client.Framework.Gwen.ControlInternal; using Intersect.Client.Framework.Gwen.DragDrop; -namespace Intersect.Client.Framework.Gwen.Control +namespace Intersect.Client.Framework.Gwen.Control; + + +/// +/// Base for dockable containers. +/// +public partial class DockBase : Base { + private DockBase mBottom; + + // Only CHILD dockpanels have a tabcontrol. + private DockedTabControl mDockedTabControl; + + private bool mDrawHover; + + private bool mDropFar; + + private Rectangle mHoverRect; + + private DockBase mLeft; + + private DockBase mRight; + + private Resizer mSizer; + + private DockBase mTop; + /// - /// Base for dockable containers. + /// Initializes a new instance of the class. /// - public partial class DockBase : Base + /// Parent control. + public DockBase(Base parent) : base(parent) { + Padding = Padding.One; + SetSize(200, 200); + } - private DockBase mBottom; + // todo: dock events? - // Only CHILD dockpanels have a tabcontrol. - private DockedTabControl mDockedTabControl; + /// + /// Control docked on the left side. + /// + public DockBase LeftDock => GetChildDock(Pos.Left); - private bool mDrawHover; + /// + /// Control docked on the right side. + /// + public DockBase RightDock => GetChildDock(Pos.Right); - private bool mDropFar; + /// + /// Control docked on the top side. + /// + public DockBase TopDock => GetChildDock(Pos.Top); - private Rectangle mHoverRect; + /// + /// Control docked on the bottom side. + /// + public DockBase BottomDock => GetChildDock(Pos.Bottom); - private DockBase mLeft; + public TabControl TabControl => mDockedTabControl; - private DockBase mRight; + /// + /// Indicates whether the control contains any docked children. + /// + public virtual bool IsEmpty + { + get + { + if (mDockedTabControl != null && mDockedTabControl.TabCount > 0) + { + return false; + } - private Resizer mSizer; + if (mLeft != null && !mLeft.IsEmpty) + { + return false; + } - private DockBase mTop; + if (mRight != null && !mRight.IsEmpty) + { + return false; + } - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public DockBase(Base parent) : base(parent) - { - Padding = Padding.One; - SetSize(200, 200); + if (mTop != null && !mTop.IsEmpty) + { + return false; + } + + if (mBottom != null && !mBottom.IsEmpty) + { + return false; + } + + return true; } + } - // todo: dock events? + /// + /// Handler for Space keyboard event. + /// + /// Indicates whether the key was pressed or released. + /// + /// True if handled. + /// + protected override bool OnKeySpace(bool down) + { + // No action on space (default button action is to press) + return false; + } - /// - /// Control docked on the left side. - /// - public DockBase LeftDock => GetChildDock(Pos.Left); + /// + /// Initializes an inner docked control for the specified position. + /// + /// Dock position. + protected virtual void SetupChildDock(Pos pos) + { + if (mDockedTabControl == null) + { + mDockedTabControl = new DockedTabControl(this); + mDockedTabControl.TabRemoved += OnTabRemoved; + mDockedTabControl.TabStripPosition = Pos.Bottom; + mDockedTabControl.TitleBarVisible = true; + } - /// - /// Control docked on the right side. - /// - public DockBase RightDock => GetChildDock(Pos.Right); + Dock = pos; - /// - /// Control docked on the top side. - /// - public DockBase TopDock => GetChildDock(Pos.Top); + Pos sizeDir; + if (pos == Pos.Right) + { + sizeDir = Pos.Left; + } + else if (pos == Pos.Left) + { + sizeDir = Pos.Right; + } + else if (pos == Pos.Top) + { + sizeDir = Pos.Bottom; + } + else if (pos == Pos.Bottom) + { + sizeDir = Pos.Top; + } + else + { + throw new ArgumentException("Invalid dock", "pos"); + } - /// - /// Control docked on the bottom side. - /// - public DockBase BottomDock => GetChildDock(Pos.Bottom); + if (mSizer != null) + { + mSizer.Dispose(); + } + + mSizer = new Resizer(this); + mSizer.Dock = sizeDir; + mSizer.ResizeDir = sizeDir; + mSizer.SetSize(2, 2); + } - public TabControl TabControl => mDockedTabControl; + /// + /// Renders the control using specified skin. + /// + /// Skin to use. + protected override void Render(Skin.Base skin) + { + } - /// - /// Indicates whether the control contains any docked children. - /// - public virtual bool IsEmpty + /// + /// Gets an inner docked control for the specified position. + /// + /// + /// + protected virtual DockBase GetChildDock(Pos pos) + { + // todo: verify + DockBase dock = null; + switch (pos) { - get - { - if (mDockedTabControl != null && mDockedTabControl.TabCount > 0) + case Pos.Left: + if (mLeft == null) { - return false; + mLeft = new DockBase(this); + mLeft.SetupChildDock(pos); } - if (mLeft != null && !mLeft.IsEmpty) - { - return false; - } + dock = mLeft; + + break; - if (mRight != null && !mRight.IsEmpty) + case Pos.Right: + if (mRight == null) { - return false; + mRight = new DockBase(this); + mRight.SetupChildDock(pos); } - if (mTop != null && !mTop.IsEmpty) + dock = mRight; + + break; + + case Pos.Top: + if (mTop == null) { - return false; + mTop = new DockBase(this); + mTop.SetupChildDock(pos); } - if (mBottom != null && !mBottom.IsEmpty) + dock = mTop; + + break; + + case Pos.Bottom: + if (mBottom == null) { - return false; + mBottom = new DockBase(this); + mBottom.SetupChildDock(pos); } - return true; - } - } + dock = mBottom; - /// - /// Handler for Space keyboard event. - /// - /// Indicates whether the key was pressed or released. - /// - /// True if handled. - /// - protected override bool OnKeySpace(bool down) - { - // No action on space (default button action is to press) - return false; + break; } - /// - /// Initializes an inner docked control for the specified position. - /// - /// Dock position. - protected virtual void SetupChildDock(Pos pos) + if (dock != null) { - if (mDockedTabControl == null) - { - mDockedTabControl = new DockedTabControl(this); - mDockedTabControl.TabRemoved += OnTabRemoved; - mDockedTabControl.TabStripPosition = Pos.Bottom; - mDockedTabControl.TitleBarVisible = true; - } + dock.IsHidden = false; + } - Dock = pos; + return dock; + } - Pos sizeDir; - if (pos == Pos.Right) - { - sizeDir = Pos.Left; - } - else if (pos == Pos.Left) - { - sizeDir = Pos.Right; - } - else if (pos == Pos.Top) - { - sizeDir = Pos.Bottom; - } - else if (pos == Pos.Bottom) - { - sizeDir = Pos.Top; - } - else - { - throw new ArgumentException("Invalid dock", "pos"); - } + /// + /// Calculates dock direction from dragdrop coordinates. + /// + /// X coordinate. + /// Y coordinate. + /// Dock direction. + protected virtual Pos GetDroppedTabDirection(int x, int y) + { + var w = Width; + var h = Height; + var top = y / (float) h; + var left = x / (float) w; + var right = (w - x) / (float) w; + var bottom = (h - y) / (float) h; + var minimum = Math.Min(Math.Min(Math.Min(top, left), right), bottom); - if (mSizer != null) - { - mSizer.Dispose(); - } + mDropFar = minimum < 0.2f; - mSizer = new Resizer(this); - mSizer.Dock = sizeDir; - mSizer.ResizeDir = sizeDir; - mSizer.SetSize(2, 2); + if (minimum > 0.3f) + { + return Pos.Fill; } - /// - /// Renders the control using specified skin. - /// - /// Skin to use. - protected override void Render(Skin.Base skin) + if (top == minimum && (null == mTop || mTop.IsHidden)) { + return Pos.Top; } - /// - /// Gets an inner docked control for the specified position. - /// - /// - /// - protected virtual DockBase GetChildDock(Pos pos) + if (left == minimum && (null == mLeft || mLeft.IsHidden)) { - // todo: verify - DockBase dock = null; - switch (pos) - { - case Pos.Left: - if (mLeft == null) - { - mLeft = new DockBase(this); - mLeft.SetupChildDock(pos); - } - - dock = mLeft; - - break; - - case Pos.Right: - if (mRight == null) - { - mRight = new DockBase(this); - mRight.SetupChildDock(pos); - } - - dock = mRight; - - break; + return Pos.Left; + } - case Pos.Top: - if (mTop == null) - { - mTop = new DockBase(this); - mTop.SetupChildDock(pos); - } + if (right == minimum && (null == mRight || mRight.IsHidden)) + { + return Pos.Right; + } - dock = mTop; + if (bottom == minimum && (null == mBottom || mBottom.IsHidden)) + { + return Pos.Bottom; + } - break; + return Pos.Fill; + } - case Pos.Bottom: - if (mBottom == null) - { - mBottom = new DockBase(this); - mBottom.SetupChildDock(pos); - } + public override bool DragAndDrop_CanAcceptPackage(Package p) + { + // A TAB button dropped + if (p.Name == "TabButtonMove") + { + return true; + } - dock = mBottom; + // a TAB window dropped + if (p.Name == "TabWindowMove") + { + return true; + } - break; - } + return false; + } - if (dock != null) - { - dock.IsHidden = false; - } + public override bool DragAndDrop_HandleDrop(Package p, int x, int y) + { + var pos = CanvasPosToLocal(new Point(x, y)); + var dir = GetDroppedTabDirection(pos.X, pos.Y); - return dock; + var addTo = mDockedTabControl; + if (dir == Pos.Fill && addTo == null) + { + return false; } - /// - /// Calculates dock direction from dragdrop coordinates. - /// - /// X coordinate. - /// Y coordinate. - /// Dock direction. - protected virtual Pos GetDroppedTabDirection(int x, int y) + if (dir != Pos.Fill) { - var w = Width; - var h = Height; - var top = y / (float) h; - var left = x / (float) w; - var right = (w - x) / (float) w; - var bottom = (h - y) / (float) h; - var minimum = Math.Min(Math.Min(Math.Min(top, left), right), bottom); - - mDropFar = minimum < 0.2f; - - if (minimum > 0.3f) - { - return Pos.Fill; - } + var dock = GetChildDock(dir); + addTo = dock.mDockedTabControl; - if (top == minimum && (null == mTop || mTop.IsHidden)) + if (!mDropFar) { - return Pos.Top; + dock.BringToFront(); } - - if (left == minimum && (null == mLeft || mLeft.IsHidden)) - { - return Pos.Left; - } - - if (right == minimum && (null == mRight || mRight.IsHidden)) + else { - return Pos.Right; + dock.SendToBack(); } + } - if (bottom == minimum && (null == mBottom || mBottom.IsHidden)) + if (p.Name == "TabButtonMove") + { + var tabButton = DragAndDrop.SourceControl as TabButton; + if (null == tabButton) { - return Pos.Bottom; + return false; } - return Pos.Fill; + addTo.AddPage(tabButton); } - public override bool DragAndDrop_CanAcceptPackage(Package p) + if (p.Name == "TabWindowMove") { - // A TAB button dropped - if (p.Name == "TabButtonMove") + var tabControl = DragAndDrop.SourceControl as DockedTabControl; + if (null == tabControl) { - return true; + return false; } - // a TAB window dropped - if (p.Name == "TabWindowMove") + if (tabControl == addTo) { - return true; + return false; } - return false; + tabControl.MoveTabsTo(addTo); } - public override bool DragAndDrop_HandleDrop(Package p, int x, int y) - { - var pos = CanvasPosToLocal(new Point(x, y)); - var dir = GetDroppedTabDirection(pos.X, pos.Y); + Invalidate(); - var addTo = mDockedTabControl; - if (dir == Pos.Fill && addTo == null) - { - return false; - } + return true; + } - if (dir != Pos.Fill) - { - var dock = GetChildDock(dir); - addTo = dock.mDockedTabControl; + protected virtual void OnTabRemoved(Base control, EventArgs args) + { + DoRedundancyCheck(); + DoConsolidateCheck(); + } - if (!mDropFar) - { - dock.BringToFront(); - } - else - { - dock.SendToBack(); - } - } + protected virtual void DoRedundancyCheck() + { + if (!IsEmpty) + { + return; + } - if (p.Name == "TabButtonMove") - { - var tabButton = DragAndDrop.SourceControl as TabButton; - if (null == tabButton) - { - return false; - } + var pDockParent = Parent as DockBase; + if (null == pDockParent) + { + return; + } - addTo.AddPage(tabButton); - } + pDockParent.OnRedundantChildDock(this); + } - if (p.Name == "TabWindowMove") - { - var tabControl = DragAndDrop.SourceControl as DockedTabControl; - if (null == tabControl) - { - return false; - } + protected virtual void DoConsolidateCheck() + { + if (IsEmpty) + { + return; + } - if (tabControl == addTo) - { - return false; - } + if (null == mDockedTabControl) + { + return; + } - tabControl.MoveTabsTo(addTo); - } + if (mDockedTabControl.TabCount > 0) + { + return; + } - Invalidate(); + if (mBottom != null && !mBottom.IsEmpty) + { + mBottom.mDockedTabControl.MoveTabsTo(mDockedTabControl); - return true; + return; } - protected virtual void OnTabRemoved(Base control, EventArgs args) + if (mTop != null && !mTop.IsEmpty) { - DoRedundancyCheck(); - DoConsolidateCheck(); + mTop.mDockedTabControl.MoveTabsTo(mDockedTabControl); + + return; } - protected virtual void DoRedundancyCheck() + if (mLeft != null && !mLeft.IsEmpty) { - if (!IsEmpty) - { - return; - } + mLeft.mDockedTabControl.MoveTabsTo(mDockedTabControl); - var pDockParent = Parent as DockBase; - if (null == pDockParent) - { - return; - } - - pDockParent.OnRedundantChildDock(this); + return; } - protected virtual void DoConsolidateCheck() + if (mRight != null && !mRight.IsEmpty) { - if (IsEmpty) - { - return; - } + mRight.mDockedTabControl.MoveTabsTo(mDockedTabControl); - if (null == mDockedTabControl) - { - return; - } - - if (mDockedTabControl.TabCount > 0) - { - return; - } + return; + } + } - if (mBottom != null && !mBottom.IsEmpty) - { - mBottom.mDockedTabControl.MoveTabsTo(mDockedTabControl); + protected virtual void OnRedundantChildDock(DockBase dock) + { + dock.IsHidden = true; + DoRedundancyCheck(); + DoConsolidateCheck(); + } - return; - } + public override void DragAndDrop_HoverEnter(Package p, int x, int y) + { + mDrawHover = true; + } - if (mTop != null && !mTop.IsEmpty) - { - mTop.mDockedTabControl.MoveTabsTo(mDockedTabControl); + public override void DragAndDrop_HoverLeave(Package p) + { + mDrawHover = false; + } - return; - } + public override void DragAndDrop_Hover(Package p, int x, int y) + { + var pos = CanvasPosToLocal(new Point(x, y)); + var dir = GetDroppedTabDirection(pos.X, pos.Y); - if (mLeft != null && !mLeft.IsEmpty) + if (dir == Pos.Fill) + { + if (null == mDockedTabControl) { - mLeft.mDockedTabControl.MoveTabsTo(mDockedTabControl); + mHoverRect = Rectangle.Empty; return; } - if (mRight != null && !mRight.IsEmpty) - { - mRight.mDockedTabControl.MoveTabsTo(mDockedTabControl); + mHoverRect = InnerBounds; - return; - } + return; } - protected virtual void OnRedundantChildDock(DockBase dock) + mHoverRect = RenderBounds; + + var helpBarWidth = 0; + + if (dir == Pos.Left) { - dock.IsHidden = true; - DoRedundancyCheck(); - DoConsolidateCheck(); + helpBarWidth = (int) (mHoverRect.Width * 0.25f); + mHoverRect.Width = helpBarWidth; } - public override void DragAndDrop_HoverEnter(Package p, int x, int y) + if (dir == Pos.Right) { - mDrawHover = true; + helpBarWidth = (int) (mHoverRect.Width * 0.25f); + mHoverRect.X = mHoverRect.Width - helpBarWidth; + mHoverRect.Width = helpBarWidth; } - public override void DragAndDrop_HoverLeave(Package p) + if (dir == Pos.Top) { - mDrawHover = false; + helpBarWidth = (int) (mHoverRect.Height * 0.25f); + mHoverRect.Height = helpBarWidth; } - public override void DragAndDrop_Hover(Package p, int x, int y) + if (dir == Pos.Bottom) { - var pos = CanvasPosToLocal(new Point(x, y)); - var dir = GetDroppedTabDirection(pos.X, pos.Y); - - if (dir == Pos.Fill) - { - if (null == mDockedTabControl) - { - mHoverRect = Rectangle.Empty; - - return; - } - - mHoverRect = InnerBounds; - - return; - } - - mHoverRect = RenderBounds; - - var helpBarWidth = 0; - - if (dir == Pos.Left) - { - helpBarWidth = (int) (mHoverRect.Width * 0.25f); - mHoverRect.Width = helpBarWidth; - } + helpBarWidth = (int) (mHoverRect.Height * 0.25f); + mHoverRect.Y = mHoverRect.Height - helpBarWidth; + mHoverRect.Height = helpBarWidth; + } - if (dir == Pos.Right) + if ((dir == Pos.Top || dir == Pos.Bottom) && !mDropFar) + { + if (mLeft != null && mLeft.IsVisible) { - helpBarWidth = (int) (mHoverRect.Width * 0.25f); - mHoverRect.X = mHoverRect.Width - helpBarWidth; - mHoverRect.Width = helpBarWidth; + mHoverRect.X += mLeft.Width; + mHoverRect.Width -= mLeft.Width; } - if (dir == Pos.Top) + if (mRight != null && mRight.IsVisible) { - helpBarWidth = (int) (mHoverRect.Height * 0.25f); - mHoverRect.Height = helpBarWidth; + mHoverRect.Width -= mRight.Width; } + } - if (dir == Pos.Bottom) + if ((dir == Pos.Left || dir == Pos.Right) && !mDropFar) + { + if (mTop != null && mTop.IsVisible) { - helpBarWidth = (int) (mHoverRect.Height * 0.25f); - mHoverRect.Y = mHoverRect.Height - helpBarWidth; - mHoverRect.Height = helpBarWidth; + mHoverRect.Y += mTop.Height; + mHoverRect.Height -= mTop.Height; } - if ((dir == Pos.Top || dir == Pos.Bottom) && !mDropFar) + if (mBottom != null && mBottom.IsVisible) { - if (mLeft != null && mLeft.IsVisible) - { - mHoverRect.X += mLeft.Width; - mHoverRect.Width -= mLeft.Width; - } - - if (mRight != null && mRight.IsVisible) - { - mHoverRect.Width -= mRight.Width; - } - } - - if ((dir == Pos.Left || dir == Pos.Right) && !mDropFar) - { - if (mTop != null && mTop.IsVisible) - { - mHoverRect.Y += mTop.Height; - mHoverRect.Height -= mTop.Height; - } - - if (mBottom != null && mBottom.IsVisible) - { - mHoverRect.Height -= mBottom.Height; - } + mHoverRect.Height -= mBottom.Height; } } + } - /// - /// Renders over the actual control (overlays). - /// - /// Skin to use. - protected override void RenderOver(Skin.Base skin) + /// + /// Renders over the actual control (overlays). + /// + /// Skin to use. + protected override void RenderOver(Skin.Base skin) + { + if (!mDrawHover) { - if (!mDrawHover) - { - return; - } - - var render = skin.Renderer; - render.DrawColor = Color.FromArgb(20, 255, 200, 255); - render.DrawFilledRect(RenderBounds); - - if (mHoverRect.Width == 0) - { - return; - } + return; + } - render.DrawColor = Color.FromArgb(100, 255, 200, 255); - render.DrawFilledRect(mHoverRect); + var render = skin.Renderer; + render.DrawColor = Color.FromArgb(20, 255, 200, 255); + render.DrawFilledRect(RenderBounds); - render.DrawColor = Color.FromArgb(200, 255, 200, 255); - render.DrawLinedRect(mHoverRect); + if (mHoverRect.Width == 0) + { + return; } + render.DrawColor = Color.FromArgb(100, 255, 200, 255); + render.DrawFilledRect(mHoverRect); + + render.DrawColor = Color.FromArgb(200, 255, 200, 255); + render.DrawLinedRect(mHoverRect); } } diff --git a/Intersect.Client.Framework/Gwen/Control/DockedTabControl.cs b/Intersect.Client.Framework/Gwen/Control/DockedTabControl.cs index c3925e331b..67364ec439 100644 --- a/Intersect.Client.Framework/Gwen/Control/DockedTabControl.cs +++ b/Intersect.Client.Framework/Gwen/Control/DockedTabControl.cs @@ -1,93 +1,91 @@ -namespace Intersect.Client.Framework.Gwen.Control +namespace Intersect.Client.Framework.Gwen.Control; + + +/// +/// Docked tab control. +/// +public partial class DockedTabControl : TabControl { + private readonly TabTitleBar mTitleBar; + /// - /// Docked tab control. + /// Initializes a new instance of the class. /// - public partial class DockedTabControl : TabControl + /// Parent control. + public DockedTabControl(Base parent) : base(parent) { + Dock = Pos.Fill; - private readonly TabTitleBar mTitleBar; - - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public DockedTabControl(Base parent) : base(parent) - { - Dock = Pos.Fill; + mTitleBar = new TabTitleBar(this); + mTitleBar.Dock = Pos.Top; + mTitleBar.IsHidden = true; + } - mTitleBar = new TabTitleBar(this); - mTitleBar.Dock = Pos.Top; - mTitleBar.IsHidden = true; - } + /// + /// Determines whether the title bar is visible. + /// + public bool TitleBarVisible + { + get => !mTitleBar.IsHidden; + set => mTitleBar.IsHidden = !value; + } - /// - /// Determines whether the title bar is visible. - /// - public bool TitleBarVisible - { - get => !mTitleBar.IsHidden; - set => mTitleBar.IsHidden = !value; - } + /// + /// Lays out the control's interior according to alignment, padding, dock etc. + /// + /// Skin to use. + protected override void Layout(Skin.Base skin) + { + TabStrip.IsHidden = TabCount <= 1; + UpdateTitleBar(); + base.Layout(skin); + } - /// - /// Lays out the control's interior according to alignment, padding, dock etc. - /// - /// Skin to use. - protected override void Layout(Skin.Base skin) + private void UpdateTitleBar() + { + if (CurrentButton == null) { - TabStrip.IsHidden = TabCount <= 1; - UpdateTitleBar(); - base.Layout(skin); + return; } - private void UpdateTitleBar() - { - if (CurrentButton == null) - { - return; - } - - mTitleBar.UpdateFromTab(CurrentButton); - } + mTitleBar.UpdateFromTab(CurrentButton); + } - public override void DragAndDrop_StartDragging(DragDrop.Package package, int x, int y) - { - base.DragAndDrop_StartDragging(package, x, y); + public override void DragAndDrop_StartDragging(DragDrop.Package package, int x, int y) + { + base.DragAndDrop_StartDragging(package, x, y); - IsHidden = true; + IsHidden = true; - // This hiding our parent thing is kind of lousy. - Parent.IsHidden = true; - } + // This hiding our parent thing is kind of lousy. + Parent.IsHidden = true; + } - public override void DragAndDrop_EndDragging(bool success, int x, int y) + public override void DragAndDrop_EndDragging(bool success, int x, int y) + { + IsHidden = false; + if (!success) { - IsHidden = false; - if (!success) - { - Parent.IsHidden = false; - } + Parent.IsHidden = false; } + } - public void MoveTabsTo(DockedTabControl target) + public void MoveTabsTo(DockedTabControl target) + { + var children = TabStrip.Children.ToArray(); // copy because collection will be modified + foreach (var child in children) { - var children = TabStrip.Children.ToArray(); // copy because collection will be modified - foreach (var child in children) + var button = child as TabButton; + if (button == null) { - var button = child as TabButton; - if (button == null) - { - continue; - } - - target.AddPage(button); + continue; } - Invalidate(); + target.AddPage(button); } + Invalidate(); } } diff --git a/Intersect.Client.Framework/Gwen/Control/EnumRadioButtonGroup.cs b/Intersect.Client.Framework/Gwen/Control/EnumRadioButtonGroup.cs index 0107693b04..8f21594ddd 100644 --- a/Intersect.Client.Framework/Gwen/Control/EnumRadioButtonGroup.cs +++ b/Intersect.Client.Framework/Gwen/Control/EnumRadioButtonGroup.cs @@ -1,40 +1,38 @@ -namespace Intersect.Client.Framework.Gwen.Control +namespace Intersect.Client.Framework.Gwen.Control; + + +public partial class EnumRadioButtonGroup : RadioButtonGroup where T : struct, IConvertible { - public partial class EnumRadioButtonGroup : RadioButtonGroup where T : struct, IConvertible + public EnumRadioButtonGroup(Base parent) : base(parent) { - - public EnumRadioButtonGroup(Base parent) : base(parent) + if (!typeof(T).IsEnum) { - if (!typeof(T).IsEnum) - { - throw new Exception("T must be an enumerated type!"); - } + throw new Exception("T must be an enumerated type!"); + } - this.Text = typeof(T).Name; - for (var i = 0; i < Enum.GetValues(typeof(T)).Length; i++) - { - var name = Enum.GetNames(typeof(T))[i]; - var lrb = this.AddOption(name); - lrb.UserData = Enum.GetValues(typeof(T)).GetValue(i); - } + this.Text = typeof(T).Name; + for (var i = 0; i < Enum.GetValues(typeof(T)).Length; i++) + { + var name = Enum.GetNames(typeof(T))[i]; + var lrb = this.AddOption(name); + lrb.UserData = Enum.GetValues(typeof(T)).GetValue(i); } + } - public T SelectedValue + public T SelectedValue + { + get => (T) this.Selected.UserData; + set { - get => (T) this.Selected.UserData; - set + foreach (var child in Children) { - foreach (var child in Children) + if (child is LabeledRadioButton && child.UserData.Equals(value)) { - if (child is LabeledRadioButton && child.UserData.Equals(value)) - { - (child as LabeledRadioButton).RadioButton.Press(); - } + (child as LabeledRadioButton).RadioButton.Press(); } } } - } } diff --git a/Intersect.Client.Framework/Gwen/Control/EventArguments/ClickedEventArgs.cs b/Intersect.Client.Framework/Gwen/Control/EventArguments/ClickedEventArgs.cs index ae52a0712e..a4e155fdfb 100644 --- a/Intersect.Client.Framework/Gwen/Control/EventArguments/ClickedEventArgs.cs +++ b/Intersect.Client.Framework/Gwen/Control/EventArguments/ClickedEventArgs.cs @@ -1,22 +1,20 @@ -namespace Intersect.Client.Framework.Gwen.Control.EventArguments -{ +namespace Intersect.Client.Framework.Gwen.Control.EventArguments; - public partial class ClickedEventArgs : EventArgs - { - internal ClickedEventArgs(int x, int y, bool down) - { - this.X = x; - this.Y = y; - this.MouseDown = down; - } +public partial class ClickedEventArgs : EventArgs +{ - public int X { get; private set; } + internal ClickedEventArgs(int x, int y, bool down) + { + this.X = x; + this.Y = y; + this.MouseDown = down; + } - public int Y { get; private set; } + public int X { get; private set; } - public bool MouseDown { get; private set; } + public int Y { get; private set; } - } + public bool MouseDown { get; private set; } } diff --git a/Intersect.Client.Framework/Gwen/Control/EventArguments/ItemSelectedEventArgs.cs b/Intersect.Client.Framework/Gwen/Control/EventArguments/ItemSelectedEventArgs.cs index 4a66c224fb..3cf928993b 100644 --- a/Intersect.Client.Framework/Gwen/Control/EventArguments/ItemSelectedEventArgs.cs +++ b/Intersect.Client.Framework/Gwen/Control/EventArguments/ItemSelectedEventArgs.cs @@ -1,19 +1,17 @@ -namespace Intersect.Client.Framework.Gwen.Control.EventArguments -{ +namespace Intersect.Client.Framework.Gwen.Control.EventArguments; - public partial class ItemSelectedEventArgs : EventArgs - { - internal ItemSelectedEventArgs(Base selecteditem, bool automated = false) - { - this.SelectedItem = selecteditem; - this.Automated = automated; - } +public partial class ItemSelectedEventArgs : EventArgs +{ - public Base SelectedItem { get; private set; } + internal ItemSelectedEventArgs(Base selecteditem, bool automated = false) + { + this.SelectedItem = selecteditem; + this.Automated = automated; + } - public bool Automated { get; private set; } + public Base SelectedItem { get; private set; } - } + public bool Automated { get; private set; } } diff --git a/Intersect.Client.Framework/Gwen/Control/GroupBox.cs b/Intersect.Client.Framework/Gwen/Control/GroupBox.cs index d71c49925b..524817df69 100644 --- a/Intersect.Client.Framework/Gwen/Control/GroupBox.cs +++ b/Intersect.Client.Framework/Gwen/Control/GroupBox.cs @@ -1,79 +1,77 @@ -namespace Intersect.Client.Framework.Gwen.Control +namespace Intersect.Client.Framework.Gwen.Control; + + +/// +/// Group box (container). +/// +/// Don't use autosize with docking. +public partial class GroupBox : Label { /// - /// Group box (container). + /// Initializes a new instance of the class. /// - /// Don't use autosize with docking. - public partial class GroupBox : Label + /// Parent control. + public GroupBox(Base parent) : base(parent) { + AutoSizeToContents = false; - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public GroupBox(Base parent) : base(parent) - { - AutoSizeToContents = false; - - // Set to true, because it's likely that our - // children will want mouse input, and they - // can't get it without us.. - MouseInputEnabled = true; - KeyboardInputEnabled = true; + // Set to true, because it's likely that our + // children will want mouse input, and they + // can't get it without us.. + MouseInputEnabled = true; + KeyboardInputEnabled = true; - TextPadding = new Padding(10, 0, 10, 0); - Alignment = Pos.Top | Pos.Left; - Invalidate(); + TextPadding = new Padding(10, 0, 10, 0); + Alignment = Pos.Top | Pos.Left; + Invalidate(); - mInnerPanel = new Base(this); - mInnerPanel.Dock = Pos.Fill; - mInnerPanel.Margin = new Margin(5, TextHeight + 5, 5, 5); + mInnerPanel = new Base(this); + mInnerPanel.Dock = Pos.Fill; + mInnerPanel.Margin = new Margin(5, TextHeight + 5, 5, 5); - //Margin = new Margin(5, 5, 5, 5); - } + //Margin = new Margin(5, 5, 5, 5); + } - /// - /// Lays out the control's interior according to alignment, padding, dock etc. - /// - /// Skin to use. - protected override void Layout(Skin.Base skin) + /// + /// Lays out the control's interior according to alignment, padding, dock etc. + /// + /// Skin to use. + protected override void Layout(Skin.Base skin) + { + base.Layout(skin); + if (AutoSizeToContents) { - base.Layout(skin); - if (AutoSizeToContents) - { - DoSizeToContents(); - } + DoSizeToContents(); } + } - /// - /// Renders the control using specified skin. - /// - /// Skin to use. - protected override void Render(Skin.Base skin) - { - skin.DrawGroupBox(this, TextX, TextHeight, TextWidth); - } + /// + /// Renders the control using specified skin. + /// + /// Skin to use. + protected override void Render(Skin.Base skin) + { + skin.DrawGroupBox(this, TextX, TextHeight, TextWidth); + } - /// - /// Sizes to contents. - /// - public override void SizeToContents() - { - // we inherit from Label and shouldn't use its method. - DoSizeToContents(); - } + /// + /// Sizes to contents. + /// + public override void SizeToContents() + { + // we inherit from Label and shouldn't use its method. + DoSizeToContents(); + } - protected virtual void DoSizeToContents() + protected virtual void DoSizeToContents() + { + mInnerPanel.SizeToChildren(); + SizeToChildren(); + if (Width < TextWidth + TextPadding.Right + TextPadding.Left) { - mInnerPanel.SizeToChildren(); - SizeToChildren(); - if (Width < TextWidth + TextPadding.Right + TextPadding.Left) - { - Width = TextWidth + TextPadding.Right + TextPadding.Left; - } + Width = TextWidth + TextPadding.Right + TextPadding.Left; } - } } diff --git a/Intersect.Client.Framework/Gwen/Control/HSVColorPicker.cs b/Intersect.Client.Framework/Gwen/Control/HSVColorPicker.cs index 3829485a77..33cd74eac3 100644 --- a/Intersect.Client.Framework/Gwen/Control/HSVColorPicker.cs +++ b/Intersect.Client.Framework/Gwen/Control/HSVColorPicker.cs @@ -1,235 +1,233 @@ using Intersect.Client.Framework.Gwen.ControlInternal; -namespace Intersect.Client.Framework.Gwen.Control +namespace Intersect.Client.Framework.Gwen.Control; + + +/// +/// HSV color picker with "before" and "after" color boxes. +/// +public partial class HsvColorPicker : Base, IColorPicker { + private readonly ColorDisplay mAfter; + + private readonly ColorDisplay mBefore; + + private readonly ColorSlider mColorSlider; + + private readonly ColorLerpBox mLerpBox; + /// - /// HSV color picker with "before" and "after" color boxes. + /// Initializes a new instance of the class. /// - public partial class HsvColorPicker : Base, IColorPicker + /// Parent control. + public HsvColorPicker(Base parent) : base(parent) { + MouseInputEnabled = true; + SetSize(256, 128); + + //ShouldCacheToTexture = true; + + mLerpBox = new ColorLerpBox(this); + mLerpBox.ColorChanged += ColorBoxChanged; + mLerpBox.Dock = Pos.Left; - private readonly ColorDisplay mAfter; + mColorSlider = new ColorSlider(this); + mColorSlider.SetPosition(mLerpBox.Width + 15, 5); + mColorSlider.ColorChanged += ColorSliderChanged; + mColorSlider.Dock = Pos.Left; - private readonly ColorDisplay mBefore; + mAfter = new ColorDisplay(this); + mAfter.SetSize(48, 24); + mAfter.SetPosition(mColorSlider.X + mColorSlider.Width + 15, 5); - private readonly ColorSlider mColorSlider; + mBefore = new ColorDisplay(this); + mBefore.SetSize(48, 24); + mBefore.SetPosition(mAfter.X, 28); - private readonly ColorLerpBox mLerpBox; + var x = mBefore.X; + var y = mBefore.Y + 30; - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public HsvColorPicker(Base parent) : base(parent) { - MouseInputEnabled = true; - SetSize(256, 128); + var label = new Label(this); + label.SetText("R:"); + label.SizeToContents(); + label.SetPosition(x, y); + + var numeric = new TextBoxNumeric(this); + numeric.Name = "RedBox"; + numeric.SetPosition(x + 15, y - 1); + numeric.SetSize(26, 16); + numeric.SelectAllOnFocus = true; + numeric.TextChanged += NumericTyped; + } - //ShouldCacheToTexture = true; + y += 20; - mLerpBox = new ColorLerpBox(this); - mLerpBox.ColorChanged += ColorBoxChanged; - mLerpBox.Dock = Pos.Left; + { + var label = new Label(this); + label.SetText("G:"); + label.SizeToContents(); + label.SetPosition(x, y); + + var numeric = new TextBoxNumeric(this); + numeric.Name = "GreenBox"; + numeric.SetPosition(x + 15, y - 1); + numeric.SetSize(26, 16); + numeric.SelectAllOnFocus = true; + numeric.TextChanged += NumericTyped; + } - mColorSlider = new ColorSlider(this); - mColorSlider.SetPosition(mLerpBox.Width + 15, 5); - mColorSlider.ColorChanged += ColorSliderChanged; - mColorSlider.Dock = Pos.Left; + y += 20; - mAfter = new ColorDisplay(this); - mAfter.SetSize(48, 24); - mAfter.SetPosition(mColorSlider.X + mColorSlider.Width + 15, 5); + { + var label = new Label(this); + label.SetText("B:"); + label.SizeToContents(); + label.SetPosition(x, y); + + var numeric = new TextBoxNumeric(this); + numeric.Name = "BlueBox"; + numeric.SetPosition(x + 15, y - 1); + numeric.SetSize(26, 16); + numeric.SelectAllOnFocus = true; + numeric.TextChanged += NumericTyped; + } + + SetColor(DefaultColor); + } - mBefore = new ColorDisplay(this); - mBefore.SetSize(48, 24); - mBefore.SetPosition(mAfter.X, 28); + /// + /// The "before" color. + /// + public Color DefaultColor + { + get => mBefore.Color; + set => mBefore.Color = value; + } - var x = mBefore.X; - var y = mBefore.Y + 30; - - { - var label = new Label(this); - label.SetText("R:"); - label.SizeToContents(); - label.SetPosition(x, y); - - var numeric = new TextBoxNumeric(this); - numeric.Name = "RedBox"; - numeric.SetPosition(x + 15, y - 1); - numeric.SetSize(26, 16); - numeric.SelectAllOnFocus = true; - numeric.TextChanged += NumericTyped; - } - - y += 20; - - { - var label = new Label(this); - label.SetText("G:"); - label.SizeToContents(); - label.SetPosition(x, y); - - var numeric = new TextBoxNumeric(this); - numeric.Name = "GreenBox"; - numeric.SetPosition(x + 15, y - 1); - numeric.SetSize(26, 16); - numeric.SelectAllOnFocus = true; - numeric.TextChanged += NumericTyped; - } - - y += 20; - - { - var label = new Label(this); - label.SetText("B:"); - label.SizeToContents(); - label.SetPosition(x, y); - - var numeric = new TextBoxNumeric(this); - numeric.Name = "BlueBox"; - numeric.SetPosition(x + 15, y - 1); - numeric.SetSize(26, 16); - numeric.SelectAllOnFocus = true; - numeric.TextChanged += NumericTyped; - } - - SetColor(DefaultColor); - } - - /// - /// The "before" color. - /// - public Color DefaultColor - { - get => mBefore.Color; - set => mBefore.Color = value; - } - - /// - /// Selected color. - /// - public Color SelectedColor => mLerpBox.SelectedColor; - - /// - /// Invoked when the selected color has changed. - /// - public event GwenEventHandler ColorChanged; - - private void NumericTyped(Base control, EventArgs args) - { - var box = control as TextBoxNumeric; - if (null == box) - { - return; - } - - if (box.Text == String.Empty) - { - return; - } - - var textValue = (int) box.Value; - if (textValue < 0) - { - textValue = 0; - } - - if (textValue > 255) - { - textValue = 255; - } + /// + /// Selected color. + /// + public Color SelectedColor => mLerpBox.SelectedColor; - var newColor = SelectedColor; - - if (box.Name.Contains("Red")) - { - newColor = Color.FromArgb(SelectedColor.A, textValue, SelectedColor.G, SelectedColor.B); - } - else if (box.Name.Contains("Green")) - { - newColor = Color.FromArgb(SelectedColor.A, SelectedColor.R, textValue, SelectedColor.B); - } - else if (box.Name.Contains("Blue")) - { - newColor = Color.FromArgb(SelectedColor.A, SelectedColor.R, SelectedColor.G, textValue); - } - else if (box.Name.Contains("Alpha")) - { - newColor = Color.FromArgb(textValue, SelectedColor.R, SelectedColor.G, SelectedColor.B); - } + /// + /// Invoked when the selected color has changed. + /// + public event GwenEventHandler ColorChanged; - SetColor(newColor); + private void NumericTyped(Base control, EventArgs args) + { + var box = control as TextBoxNumeric; + if (null == box) + { + return; } - private void UpdateControls(Color color) + if (box.Text == String.Empty) { - // [???] TODO: Make this code safer. - // [halfofastaple] This code SHOULD (in theory) never crash/not work as intended, but referencing children by their name is unsafe. - // Instead, a direct reference to their objects should be maintained. Worst case scenario, we grab the wrong "RedBox". - - var redBox = FindChildByName("RedBox", false) as TextBoxNumeric; - if (redBox != null) - { - redBox.SetText(color.R.ToString(), false); - } + return; + } - var greenBox = FindChildByName("GreenBox", false) as TextBoxNumeric; - if (greenBox != null) - { - greenBox.SetText(color.G.ToString(), false); - } + var textValue = (int) box.Value; + if (textValue < 0) + { + textValue = 0; + } - var blueBox = FindChildByName("BlueBox", false) as TextBoxNumeric; - if (blueBox != null) - { - blueBox.SetText(color.B.ToString(), false); - } + if (textValue > 255) + { + textValue = 255; + } - mAfter.Color = color; + var newColor = SelectedColor; - if (ColorChanged != null) - { - ColorChanged.Invoke(this, EventArgs.Empty); - } + if (box.Name.Contains("Red")) + { + newColor = Color.FromArgb(SelectedColor.A, textValue, SelectedColor.G, SelectedColor.B); + } + else if (box.Name.Contains("Green")) + { + newColor = Color.FromArgb(SelectedColor.A, SelectedColor.R, textValue, SelectedColor.B); + } + else if (box.Name.Contains("Blue")) + { + newColor = Color.FromArgb(SelectedColor.A, SelectedColor.R, SelectedColor.G, textValue); + } + else if (box.Name.Contains("Alpha")) + { + newColor = Color.FromArgb(textValue, SelectedColor.R, SelectedColor.G, SelectedColor.B); } - /// - /// Sets the selected color. - /// - /// Color to set. - /// Determines whether only the hue should be set. - /// Determines whether the "before" color should be set as well. - public void SetColor(Color color, bool onlyHue = false, bool reset = false) + SetColor(newColor); + } + + private void UpdateControls(Color color) + { + // [???] TODO: Make this code safer. + // [halfofastaple] This code SHOULD (in theory) never crash/not work as intended, but referencing children by their name is unsafe. + // Instead, a direct reference to their objects should be maintained. Worst case scenario, we grab the wrong "RedBox". + + var redBox = FindChildByName("RedBox", false) as TextBoxNumeric; + if (redBox != null) { - UpdateControls(color); + redBox.SetText(color.R.ToString(), false); + } - if (reset) - { - mBefore.Color = color; - } + var greenBox = FindChildByName("GreenBox", false) as TextBoxNumeric; + if (greenBox != null) + { + greenBox.SetText(color.G.ToString(), false); + } - mColorSlider.SelectedColor = color; - mLerpBox.SetColor(color, onlyHue); - mAfter.Color = color; + var blueBox = FindChildByName("BlueBox", false) as TextBoxNumeric; + if (blueBox != null) + { + blueBox.SetText(color.B.ToString(), false); } - private void ColorBoxChanged(Base control, EventArgs args) + mAfter.Color = color; + + if (ColorChanged != null) { - UpdateControls(SelectedColor); - Invalidate(); + ColorChanged.Invoke(this, EventArgs.Empty); } + } + + /// + /// Sets the selected color. + /// + /// Color to set. + /// Determines whether only the hue should be set. + /// Determines whether the "before" color should be set as well. + public void SetColor(Color color, bool onlyHue = false, bool reset = false) + { + UpdateControls(color); - private void ColorSliderChanged(Base control, EventArgs args) + if (reset) { - if (mLerpBox != null) - { - mLerpBox.SetColor(mColorSlider.SelectedColor, true); - } + mBefore.Color = color; + } - Invalidate(); + mColorSlider.SelectedColor = color; + mLerpBox.SetColor(color, onlyHue); + mAfter.Color = color; + } + + private void ColorBoxChanged(Base control, EventArgs args) + { + UpdateControls(SelectedColor); + Invalidate(); + } + + private void ColorSliderChanged(Base control, EventArgs args) + { + if (mLerpBox != null) + { + mLerpBox.SetColor(mColorSlider.SelectedColor, true); } + Invalidate(); } } diff --git a/Intersect.Client.Framework/Gwen/Control/HorizontalScrollBar.cs b/Intersect.Client.Framework/Gwen/Control/HorizontalScrollBar.cs index 9bda546a0d..01af80321f 100644 --- a/Intersect.Client.Framework/Gwen/Control/HorizontalScrollBar.cs +++ b/Intersect.Client.Framework/Gwen/Control/HorizontalScrollBar.cs @@ -1,212 +1,210 @@ using Intersect.Client.Framework.Gwen.Input; -namespace Intersect.Client.Framework.Gwen.Control +namespace Intersect.Client.Framework.Gwen.Control; + + +/// +/// Horizontal scrollbar. +/// +public partial class HorizontalScrollBar : ScrollBar { /// - /// Horizontal scrollbar. + /// Initializes a new instance of the class. /// - public partial class HorizontalScrollBar : ScrollBar + /// Parent control. + public HorizontalScrollBar(Base parent) : base(parent) { + mBar.IsHorizontal = true; - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public HorizontalScrollBar(Base parent) : base(parent) - { - mBar.IsHorizontal = true; - - mScrollButton[0].SetDirectionLeft(); - mScrollButton[0].Clicked += NudgeLeft; + mScrollButton[0].SetDirectionLeft(); + mScrollButton[0].Clicked += NudgeLeft; - mScrollButton[1].SetDirectionRight(); - mScrollButton[1].Clicked += NudgeRight; + mScrollButton[1].SetDirectionRight(); + mScrollButton[1].Clicked += NudgeRight; - mBar.Dragged += OnBarMoved; - } + mBar.Dragged += OnBarMoved; + } - /// - /// Bar size (in pixels). - /// - public override int BarSize - { - get => mBar.Width; - set => mBar.Width = value; - } + /// + /// Bar size (in pixels). + /// + public override int BarSize + { + get => mBar.Width; + set => mBar.Width = value; + } - /// - /// Bar position (in pixels). - /// - public override int BarPos => mBar.X - Height; + /// + /// Bar position (in pixels). + /// + public override int BarPos => mBar.X - Height; - /// - /// Indicates whether the bar is horizontal. - /// - public override bool IsHorizontal => true; + /// + /// Indicates whether the bar is horizontal. + /// + public override bool IsHorizontal => true; - /// - /// Button size (in pixels). - /// - public override int ButtonSize => Height; + /// + /// Button size (in pixels). + /// + public override int ButtonSize => Height; - public override float NudgeAmount + public override float NudgeAmount + { + get { - get + if (mDepressed) { - if (mDepressed) - { - return mViewableContentSize / mContentSize; - } - else - { - return base.NudgeAmount; - } + return mViewableContentSize / mContentSize; + } + else + { + return base.NudgeAmount; } - set => base.NudgeAmount = value; } + set => base.NudgeAmount = value; + } - /// - /// Lays out the control's interior according to alignment, padding, dock etc. - /// - /// Skin to use. - protected override void Layout(Skin.Base skin) - { - base.Layout(skin); - - mScrollButton[0].Width = Height; - mScrollButton[0].Dock = Pos.Left; - - mScrollButton[1].Width = Height; - mScrollButton[1].Dock = Pos.Right; + /// + /// Lays out the control's interior according to alignment, padding, dock etc. + /// + /// Skin to use. + protected override void Layout(Skin.Base skin) + { + base.Layout(skin); - mBar.Height = ButtonSize; - mBar.Padding = new Padding(ButtonSize, 0, ButtonSize, 0); + mScrollButton[0].Width = Height; + mScrollButton[0].Dock = Pos.Left; - var barWidth = mViewableContentSize / mContentSize * (Width - ButtonSize * 2); + mScrollButton[1].Width = Height; + mScrollButton[1].Dock = Pos.Right; - if (barWidth < ButtonSize * 0.5f) - { - barWidth = (int) (ButtonSize * 0.5f); - } + mBar.Height = ButtonSize; + mBar.Padding = new Padding(ButtonSize, 0, ButtonSize, 0); - mBar.Width = (int) barWidth; - mBar.IsHidden = Width - ButtonSize * 2 <= barWidth; + var barWidth = mViewableContentSize / mContentSize * (Width - ButtonSize * 2); - //Based on our last scroll amount, produce a position for the bar - if (!mBar.IsHeld) - { - SetScrollAmount(ScrollAmount, true); - } + if (barWidth < ButtonSize * 0.5f) + { + barWidth = (int) (ButtonSize * 0.5f); } - public void NudgeLeft(Base control, EventArgs args) + mBar.Width = (int) barWidth; + mBar.IsHidden = Width - ButtonSize * 2 <= barWidth; + + //Based on our last scroll amount, produce a position for the bar + if (!mBar.IsHeld) { - if (!IsDisabled) - { - SetScrollAmount(ScrollAmount - NudgeAmount, true); - base.PlaySound(mBar.GetMouseUpSound()); - } + SetScrollAmount(ScrollAmount, true); } + } - public void NudgeRight(Base control, EventArgs args) + public void NudgeLeft(Base control, EventArgs args) + { + if (!IsDisabled) { - if (!IsDisabled) - { - SetScrollAmount(ScrollAmount + NudgeAmount, true); - base.PlaySound(mBar.GetMouseUpSound()); - } + SetScrollAmount(ScrollAmount - NudgeAmount, true); + base.PlaySound(mBar.GetMouseUpSound()); } + } - public override void ScrollToLeft() + public void NudgeRight(Base control, EventArgs args) + { + if (!IsDisabled) { - SetScrollAmount(0, true); + SetScrollAmount(ScrollAmount + NudgeAmount, true); + base.PlaySound(mBar.GetMouseUpSound()); } + } + + public override void ScrollToLeft() + { + SetScrollAmount(0, true); + } - public override void ScrollToRight() + public override void ScrollToRight() + { + SetScrollAmount(1, true); + } + + /// + /// Handler invoked on mouse click (left) event. + /// + /// X coordinate. + /// Y coordinate. + /// If set to true mouse button is down. + protected override void OnMouseClickedLeft(int x, int y, bool down, bool automated = false) + { + base.OnMouseClickedLeft(x, y, down); + if (down) { - SetScrollAmount(1, true); + mDepressed = true; + InputHandler.MouseFocus = this; } - - /// - /// Handler invoked on mouse click (left) event. - /// - /// X coordinate. - /// Y coordinate. - /// If set to true mouse button is down. - protected override void OnMouseClickedLeft(int x, int y, bool down, bool automated = false) + else { - base.OnMouseClickedLeft(x, y, down); - if (down) + var clickPos = CanvasPosToLocal(new Point(x, y)); + if (clickPos.X < mBar.X) { - mDepressed = true; - InputHandler.MouseFocus = this; + NudgeLeft(this, EventArgs.Empty); } - else + else if (clickPos.X > mBar.X + mBar.Width) { - var clickPos = CanvasPosToLocal(new Point(x, y)); - if (clickPos.X < mBar.X) - { - NudgeLeft(this, EventArgs.Empty); - } - else if (clickPos.X > mBar.X + mBar.Width) - { - NudgeRight(this, EventArgs.Empty); - } - - mDepressed = false; - InputHandler.MouseFocus = null; + NudgeRight(this, EventArgs.Empty); } + + mDepressed = false; + InputHandler.MouseFocus = null; } + } - protected override float CalculateScrolledAmount() + protected override float CalculateScrolledAmount() + { + return (float) (mBar.X - ButtonSize) / (Width - mBar.Width - ButtonSize * 2); + } + + /// + /// Sets the scroll amount (0-1). + /// + /// Scroll amount. + /// Determines whether the control should be updated. + /// + /// True if control state changed. + /// + public override bool SetScrollAmount(float value, bool forceUpdate = false) + { + value = Util.Clamp(value, 0, 1); + + if (!base.SetScrollAmount(value, forceUpdate)) { - return (float) (mBar.X - ButtonSize) / (Width - mBar.Width - ButtonSize * 2); + return false; } - /// - /// Sets the scroll amount (0-1). - /// - /// Scroll amount. - /// Determines whether the control should be updated. - /// - /// True if control state changed. - /// - public override bool SetScrollAmount(float value, bool forceUpdate = false) + if (forceUpdate) { - value = Util.Clamp(value, 0, 1); - - if (!base.SetScrollAmount(value, forceUpdate)) - { - return false; - } + var newX = (int) (ButtonSize + value * (Width - mBar.Width - ButtonSize * 2)); + mBar.MoveTo(newX, mBar.Y); + } - if (forceUpdate) - { - var newX = (int) (ButtonSize + value * (Width - mBar.Width - ButtonSize * 2)); - mBar.MoveTo(newX, mBar.Y); - } + return true; + } - return true; + /// + /// Handler for the BarMoved event. + /// + /// Event source. + protected override void OnBarMoved(Base control, EventArgs args) + { + if (mBar.IsHeld) + { + SetScrollAmount(CalculateScrolledAmount(), false); + base.OnBarMoved(control, args); } - - /// - /// Handler for the BarMoved event. - /// - /// Event source. - protected override void OnBarMoved(Base control, EventArgs args) + else { - if (mBar.IsHeld) - { - SetScrollAmount(CalculateScrolledAmount(), false); - base.OnBarMoved(control, args); - } - else - { - InvalidateParent(); - } + InvalidateParent(); } - } } diff --git a/Intersect.Client.Framework/Gwen/Control/HorizontalSlider.cs b/Intersect.Client.Framework/Gwen/Control/HorizontalSlider.cs index 23676b778b..d863183923 100644 --- a/Intersect.Client.Framework/Gwen/Control/HorizontalSlider.cs +++ b/Intersect.Client.Framework/Gwen/Control/HorizontalSlider.cs @@ -1,64 +1,62 @@ -namespace Intersect.Client.Framework.Gwen.Control +namespace Intersect.Client.Framework.Gwen.Control; + + +/// +/// Horizontal slider. +/// +public partial class HorizontalSlider : Slider { /// - /// Horizontal slider. + /// Initializes a new instance of the class. /// - public partial class HorizontalSlider : Slider + /// Parent control. + public HorizontalSlider(Base parent, string name = "") : base(parent, name) { + mSliderBar.IsHorizontal = true; + } - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public HorizontalSlider(Base parent, string name = "") : base(parent, name) - { - mSliderBar.IsHorizontal = true; - } - - protected override float CalculateValue() - { - return (float) mSliderBar.X / (Width - mSliderBar.Width); - } - - protected override void UpdateBarFromValue() - { - mSliderBar.MoveTo((int) ((Width - mSliderBar.Width) * mValue), mSliderBar.Y); - } + protected override float CalculateValue() + { + return (float) mSliderBar.X / (Width - mSliderBar.Width); + } - /// - /// Handler invoked on mouse click (left) event. - /// - /// X coordinate. - /// Y coordinate. - /// If set to true mouse button is down. - protected override void OnMouseClickedLeft(int x, int y, bool down, bool automated = false) - { - base.OnMouseClickedLeft(x, y, down); - mSliderBar.MoveTo((int) (CanvasPosToLocal(new Point(x, y)).X - mSliderBar.Width * 0.5), mSliderBar.Y); - mSliderBar.InputMouseClickedLeft(x, y, down, true); - OnMoved(mSliderBar, EventArgs.Empty); - } + protected override void UpdateBarFromValue() + { + mSliderBar.MoveTo((int) ((Width - mSliderBar.Width) * mValue), mSliderBar.Y); + } - /// - /// Lays out the control's interior according to alignment, padding, dock etc. - /// - /// Skin to use. - protected override void Layout(Skin.Base skin) - { - //m_SliderBar.SetSize(15, Height); - UpdateBarFromValue(); - } + /// + /// Handler invoked on mouse click (left) event. + /// + /// X coordinate. + /// Y coordinate. + /// If set to true mouse button is down. + protected override void OnMouseClickedLeft(int x, int y, bool down, bool automated = false) + { + base.OnMouseClickedLeft(x, y, down); + mSliderBar.MoveTo((int) (CanvasPosToLocal(new Point(x, y)).X - mSliderBar.Width * 0.5), mSliderBar.Y); + mSliderBar.InputMouseClickedLeft(x, y, down, true); + OnMoved(mSliderBar, EventArgs.Empty); + } - /// - /// Renders the control using specified skin. - /// - /// Skin to use. - protected override void Render(Skin.Base skin) - { - skin.DrawSlider(this, true, Notches, mSnapToNotches ? mNotchCount : 0, mSliderBar.Width); - } + /// + /// Lays out the control's interior according to alignment, padding, dock etc. + /// + /// Skin to use. + protected override void Layout(Skin.Base skin) + { + //m_SliderBar.SetSize(15, Height); + UpdateBarFromValue(); + } + /// + /// Renders the control using specified skin. + /// + /// Skin to use. + protected override void Render(Skin.Base skin) + { + skin.DrawSlider(this, true, Notches, mSnapToNotches ? mNotchCount : 0, mSliderBar.Width); } } diff --git a/Intersect.Client.Framework/Gwen/Control/HorizontalSplitter.cs b/Intersect.Client.Framework/Gwen/Control/HorizontalSplitter.cs index b68ef8a465..ce1d70dcde 100644 --- a/Intersect.Client.Framework/Gwen/Control/HorizontalSplitter.cs +++ b/Intersect.Client.Framework/Gwen/Control/HorizontalSplitter.cs @@ -1,237 +1,235 @@ using Intersect.Client.Framework.GenericClasses; using Intersect.Client.Framework.Gwen.ControlInternal; -namespace Intersect.Client.Framework.Gwen.Control -{ +namespace Intersect.Client.Framework.Gwen.Control; - public partial class HorizontalSplitter : Base - { - private readonly Base[] mSections; +public partial class HorizontalSplitter : Base +{ - private readonly SplitterBar mVSplitter; + private readonly Base[] mSections; - private int mBarSize; // pixels + private readonly SplitterBar mVSplitter; - private float mVVal; // 0-1 + private int mBarSize; // pixels - private int mZoomedSection; // 0-1 + private float mVVal; // 0-1 - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public HorizontalSplitter(Base parent) : base(parent) - { - mSections = new Base[2]; + private int mZoomedSection; // 0-1 - mVSplitter = new SplitterBar(this); - mVSplitter.SetPosition(0, 128); - mVSplitter.Dragged += OnVerticalMoved; - mVSplitter.Cursor = Cursors.SizeNs; + /// + /// Initializes a new instance of the class. + /// + /// Parent control. + public HorizontalSplitter(Base parent) : base(parent) + { + mSections = new Base[2]; - mVVal = 0.5f; + mVSplitter = new SplitterBar(this); + mVSplitter.SetPosition(0, 128); + mVSplitter.Dragged += OnVerticalMoved; + mVSplitter.Cursor = Cursors.SizeNs; - SetPanel(0, null); - SetPanel(1, null); + mVVal = 0.5f; - SplitterSize = 5; - SplittersVisible = false; + SetPanel(0, null); + SetPanel(1, null); - mZoomedSection = -1; - } + SplitterSize = 5; + SplittersVisible = false; - /// - /// Indicates whether any of the panels is zoomed. - /// - public bool IsZoomed => mZoomedSection != -1; + mZoomedSection = -1; + } - /// - /// Gets or sets a value indicating whether splitters should be visible. - /// - public bool SplittersVisible - { - get => mVSplitter.ShouldDrawBackground; - set => mVSplitter.ShouldDrawBackground = value; - } + /// + /// Indicates whether any of the panels is zoomed. + /// + public bool IsZoomed => mZoomedSection != -1; - /// - /// Gets or sets the size of the splitter. - /// - public int SplitterSize - { - get => mBarSize; - set => mBarSize = value; - } + /// + /// Gets or sets a value indicating whether splitters should be visible. + /// + public bool SplittersVisible + { + get => mVSplitter.ShouldDrawBackground; + set => mVSplitter.ShouldDrawBackground = value; + } - /// - /// Invoked when one of the panels has been zoomed (maximized). - /// - public event GwenEventHandler PanelZoomed; - - /// - /// Invoked when one of the panels has been unzoomed (restored). - /// - public event GwenEventHandler PanelUnZoomed; - - /// - /// Invoked when the zoomed panel has been changed. - /// - public event GwenEventHandler ZoomChanged; - - /// - /// Centers the panels so that they take even amount of space. - /// - public void CenterPanels() - { - mVVal = 0.5f; - Invalidate(); - } + /// + /// Gets or sets the size of the splitter. + /// + public int SplitterSize + { + get => mBarSize; + set => mBarSize = value; + } - private void UpdateVSplitter() - { - mVSplitter.MoveTo(mVSplitter.X, (Height - mVSplitter.Height) * mVVal); - } + /// + /// Invoked when one of the panels has been zoomed (maximized). + /// + public event GwenEventHandler PanelZoomed; + + /// + /// Invoked when one of the panels has been unzoomed (restored). + /// + public event GwenEventHandler PanelUnZoomed; + + /// + /// Invoked when the zoomed panel has been changed. + /// + public event GwenEventHandler ZoomChanged; + + /// + /// Centers the panels so that they take even amount of space. + /// + public void CenterPanels() + { + mVVal = 0.5f; + Invalidate(); + } - protected void OnVerticalMoved(Base control, EventArgs args) - { - mVVal = CalculateValueVertical(); - Invalidate(); - } + private void UpdateVSplitter() + { + mVSplitter.MoveTo(mVSplitter.X, (Height - mVSplitter.Height) * mVVal); + } - private float CalculateValueVertical() - { - return mVSplitter.Y / (float) (Height - mVSplitter.Height); - } + protected void OnVerticalMoved(Base control, EventArgs args) + { + mVVal = CalculateValueVertical(); + Invalidate(); + } - /// - /// Lays out the control's interior according to alignment, padding, dock etc. - /// - /// Skin to use. - protected override void Layout(Skin.Base skin) - { - mVSplitter.SetSize(Width, mBarSize); + private float CalculateValueVertical() + { + return mVSplitter.Y / (float) (Height - mVSplitter.Height); + } - UpdateVSplitter(); + /// + /// Lays out the control's interior according to alignment, padding, dock etc. + /// + /// Skin to use. + protected override void Layout(Skin.Base skin) + { + mVSplitter.SetSize(Width, mBarSize); - if (mZoomedSection == -1) - { - if (mSections[0] != null) - { - mSections[0].SetBounds(0, 0, Width, mVSplitter.Y); - } + UpdateVSplitter(); - if (mSections[1] != null) - { - mSections[1].SetBounds(0, mVSplitter.Y + mBarSize, Width, Height - (mVSplitter.Y + mBarSize)); - } + if (mZoomedSection == -1) + { + if (mSections[0] != null) + { + mSections[0].SetBounds(0, 0, Width, mVSplitter.Y); } - else + + if (mSections[1] != null) { - //This should probably use Fill docking instead - mSections[mZoomedSection].SetBounds(0, 0, Width, Height); + mSections[1].SetBounds(0, mVSplitter.Y + mBarSize, Width, Height - (mVSplitter.Y + mBarSize)); } } - - /// - /// Assigns a control to the specific inner section. - /// - /// Section index (0-3). - /// Control to assign. - public void SetPanel(int index, Base panel) + else { - mSections[index] = panel; + //This should probably use Fill docking instead + mSections[mZoomedSection].SetBounds(0, 0, Width, Height); + } + } - if (panel != null) - { - panel.Dock = Pos.None; - panel.Parent = this; - } + /// + /// Assigns a control to the specific inner section. + /// + /// Section index (0-3). + /// Control to assign. + public void SetPanel(int index, Base panel) + { + mSections[index] = panel; - Invalidate(); + if (panel != null) + { + panel.Dock = Pos.None; + panel.Parent = this; } - /// - /// Gets the specific inner section. - /// - /// Section index (0-3). - /// Specified section. - public Base GetPanel(int index) + Invalidate(); + } + + /// + /// Gets the specific inner section. + /// + /// Section index (0-3). + /// Specified section. + public Base GetPanel(int index) + { + return mSections[index]; + } + + /// + /// Internal handler for the zoom changed event. + /// + protected void OnZoomChanged() + { + if (ZoomChanged != null) { - return mSections[index]; + ZoomChanged.Invoke(this, EventArgs.Empty); } - /// - /// Internal handler for the zoom changed event. - /// - protected void OnZoomChanged() + if (mZoomedSection == -1) { - if (ZoomChanged != null) - { - ZoomChanged.Invoke(this, EventArgs.Empty); - } - - if (mZoomedSection == -1) + if (PanelUnZoomed != null) { - if (PanelUnZoomed != null) - { - PanelUnZoomed.Invoke(this, EventArgs.Empty); - } + PanelUnZoomed.Invoke(this, EventArgs.Empty); } - else + } + else + { + if (PanelZoomed != null) { - if (PanelZoomed != null) - { - PanelZoomed.Invoke(this, EventArgs.Empty); - } + PanelZoomed.Invoke(this, EventArgs.Empty); } } + } - /// - /// Maximizes the specified panel so it fills the entire control. - /// - /// Panel index (0-3). - public void Zoom(int section) - { - UnZoom(); + /// + /// Maximizes the specified panel so it fills the entire control. + /// + /// Panel index (0-3). + public void Zoom(int section) + { + UnZoom(); - if (mSections[section] != null) + if (mSections[section] != null) + { + for (var i = 0; i < 2; i++) { - for (var i = 0; i < 2; i++) + if (i != section && mSections[i] != null) { - if (i != section && mSections[i] != null) - { - mSections[i].IsHidden = true; - } + mSections[i].IsHidden = true; } - - mZoomedSection = section; - - Invalidate(); } - OnZoomChanged(); + mZoomedSection = section; + + Invalidate(); } - /// - /// Restores the control so all panels are visible. - /// - public void UnZoom() - { - mZoomedSection = -1; + OnZoomChanged(); + } - for (var i = 0; i < 2; i++) + /// + /// Restores the control so all panels are visible. + /// + public void UnZoom() + { + mZoomedSection = -1; + + for (var i = 0; i < 2; i++) + { + if (mSections[i] != null) { - if (mSections[i] != null) - { - mSections[i].IsHidden = false; - } + mSections[i].IsHidden = false; } - - Invalidate(); - OnZoomChanged(); } + Invalidate(); + OnZoomChanged(); } } diff --git a/Intersect.Client.Framework/Gwen/Control/IColorPicker.cs b/Intersect.Client.Framework/Gwen/Control/IColorPicker.cs index f8a15736d1..873420778c 100644 --- a/Intersect.Client.Framework/Gwen/Control/IColorPicker.cs +++ b/Intersect.Client.Framework/Gwen/Control/IColorPicker.cs @@ -1,11 +1,9 @@ -namespace Intersect.Client.Framework.Gwen.Control -{ +namespace Intersect.Client.Framework.Gwen.Control; - public interface IColorPicker - { - Color SelectedColor { get; } +public interface IColorPicker +{ - } + Color SelectedColor { get; } } diff --git a/Intersect.Client.Framework/Gwen/Control/IColorableText.cs b/Intersect.Client.Framework/Gwen/Control/IColorableText.cs index 4b42e5db2d..abfe603e97 100644 --- a/Intersect.Client.Framework/Gwen/Control/IColorableText.cs +++ b/Intersect.Client.Framework/Gwen/Control/IColorableText.cs @@ -1,9 +1,8 @@ -namespace Intersect.Client.Framework.Gwen.Control +namespace Intersect.Client.Framework.Gwen.Control; + +public interface IColorableText { - public interface IColorableText - { - Color TextColor { get; set; } + Color TextColor { get; set; } - Color TextColorOverride { get; set; } - } + Color TextColorOverride { get; set; } } diff --git a/Intersect.Client.Framework/Gwen/Control/ILabel.cs b/Intersect.Client.Framework/Gwen/Control/ILabel.cs index d6df94a9e6..1de5bcd876 100644 --- a/Intersect.Client.Framework/Gwen/Control/ILabel.cs +++ b/Intersect.Client.Framework/Gwen/Control/ILabel.cs @@ -1,27 +1,26 @@ using Intersect.Client.Framework.Graphics; -namespace Intersect.Client.Framework.Gwen.Control +namespace Intersect.Client.Framework.Gwen.Control; + +public interface ILabel : IColorableText { - public interface ILabel : IColorableText - { - Pos Alignment { get; set; } + Pos Alignment { get; set; } - bool AutoSizeToContents { get; set; } + bool AutoSizeToContents { get; set; } - GameFont Font { get; set; } + GameFont Font { get; set; } - string FontName { get; set; } + string FontName { get; set; } - int FontSize { get; set; } + int FontSize { get; set; } - Color TextColor { get; set; } + Color TextColor { get; set; } - Color TextColorOverride { get; set; } + Color TextColorOverride { get; set; } - Padding TextPadding { get; set; } + Padding TextPadding { get; set; } - void SizeToContents(); + void SizeToContents(); - void UpdateColors(); - } + void UpdateColors(); } diff --git a/Intersect.Client.Framework/Gwen/Control/ImagePanel.cs b/Intersect.Client.Framework/Gwen/Control/ImagePanel.cs index 4941466247..71304f40af 100644 --- a/Intersect.Client.Framework/Gwen/Control/ImagePanel.cs +++ b/Intersect.Client.Framework/Gwen/Control/ImagePanel.cs @@ -5,275 +5,273 @@ using Newtonsoft.Json.Linq; -namespace Intersect.Client.Framework.Gwen.Control +namespace Intersect.Client.Framework.Gwen.Control; + + +/// +/// Image container. +/// +public partial class ImagePanel : Base { + private readonly float[] mUv; + + //Sound Effects + protected string mHoverSound; + + protected string mLeftMouseClickSound; + + private Modal mModal; + + private Base mOldParent; + + protected string mRightMouseClickSound; + + private GameTexture mTexture; + + private string mTextureFilename; + /// - /// Image container. + /// Initializes a new instance of the class. /// - public partial class ImagePanel : Base + /// Parent control. + public ImagePanel(Base parent, string name = "") : base(parent) { + mUv = new float[4]; + mTexture = null; + SetUv(0, 0, 1, 1); + MouseInputEnabled = true; + Name = name; + this.Clicked += ImagePanel_Clicked; + this.RightClicked += ImagePanel_RightClicked; + this.HoverEnter += ImagePanel_HoverEnter; + } - private readonly float[] mUv; + /// + /// Assign Existing Texture + /// + public GameTexture Texture + { + get => mTexture; + set + { + mTexture = value; + this.InvalidateParent(); + } + } - //Sound Effects - protected string mHoverSound; + public string TextureFilename + { + get => mTextureFilename; + set => mTextureFilename = value; + } - protected string mLeftMouseClickSound; + private void ImagePanel_HoverEnter(Base sender, System.EventArgs arguments) + { + PlaySound(mHoverSound); + } - private Modal mModal; + private void ImagePanel_RightClicked(Base sender, EventArguments.ClickedEventArgs arguments) + { + PlaySound(mRightMouseClickSound); + } - private Base mOldParent; + private void ImagePanel_Clicked(Base sender, EventArguments.ClickedEventArgs arguments) + { + PlaySound(mLeftMouseClickSound); + } - protected string mRightMouseClickSound; + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public override void Dispose() + { + base.Dispose(); + } - private GameTexture mTexture; + public override JObject GetJson(bool isRoot = default) + { + var obj = base.GetJson(isRoot); + obj.Add("Texture", TextureFilename); + obj.Add("HoverSound", mHoverSound); + obj.Add("LeftMouseClickSound", mLeftMouseClickSound); + obj.Add("RightMouseClickSound", mRightMouseClickSound); - private string mTextureFilename; + return base.FixJson(obj); + } - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public ImagePanel(Base parent, string name = "") : base(parent) + public override void LoadJson(JToken obj, bool isRoot = default) + { + base.LoadJson(obj); + if (obj["Texture"] != null) { - mUv = new float[4]; - mTexture = null; - SetUv(0, 0, 1, 1); - MouseInputEnabled = true; - Name = name; - this.Clicked += ImagePanel_Clicked; - this.RightClicked += ImagePanel_RightClicked; - this.HoverEnter += ImagePanel_HoverEnter; - } + Texture = GameContentManager.Current.GetTexture( + Framework.Content.TextureType.Gui, (string) obj["Texture"] + ); - /// - /// Assign Existing Texture - /// - public GameTexture Texture - { - get => mTexture; - set - { - mTexture = value; - this.InvalidateParent(); - } + TextureFilename = (string) obj["Texture"]; } - public string TextureFilename + if (obj["HoverSound"] != null) { - get => mTextureFilename; - set => mTextureFilename = value; + mHoverSound = (string) obj["HoverSound"]; } - private void ImagePanel_HoverEnter(Base sender, System.EventArgs arguments) + if (obj["LeftMouseClickSound"] != null) { - PlaySound(mHoverSound); + mLeftMouseClickSound = (string) obj["LeftMouseClickSound"]; } - private void ImagePanel_RightClicked(Base sender, EventArguments.ClickedEventArgs arguments) + if (obj["RightMouseClickSound"] != null) { - PlaySound(mRightMouseClickSound); + mRightMouseClickSound = (string) obj["RightMouseClickSound"]; } + } - private void ImagePanel_Clicked(Base sender, EventArguments.ClickedEventArgs arguments) + /// + /// Sets the texture coordinates of the image. + /// + public virtual void SetUv(float u1, float v1, float u2, float v2) + { + mUv[0] = u1; + mUv[1] = v1; + mUv[2] = u2; + mUv[3] = v2; + } + + /// + /// Sets the texture coordinates of the image. + /// + public virtual void SetTextureRect(int x, int y, int w, int h) + { + if (mTexture == null) { - PlaySound(mLeftMouseClickSound); + return; } - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public override void Dispose() + if (x < 0) { - base.Dispose(); + x = 0; } - public override JObject GetJson(bool isRoot = default) + if (y < 0) { - var obj = base.GetJson(isRoot); - obj.Add("Texture", TextureFilename); - obj.Add("HoverSound", mHoverSound); - obj.Add("LeftMouseClickSound", mLeftMouseClickSound); - obj.Add("RightMouseClickSound", mRightMouseClickSound); - - return base.FixJson(obj); + y = 0; } - public override void LoadJson(JToken obj, bool isRoot = default) + if (w <= 0) { - base.LoadJson(obj); - if (obj["Texture"] != null) - { - Texture = GameContentManager.Current.GetTexture( - Framework.Content.TextureType.Gui, (string) obj["Texture"] - ); - - TextureFilename = (string) obj["Texture"]; - } - - if (obj["HoverSound"] != null) - { - mHoverSound = (string) obj["HoverSound"]; - } - - if (obj["LeftMouseClickSound"] != null) - { - mLeftMouseClickSound = (string) obj["LeftMouseClickSound"]; - } - - if (obj["RightMouseClickSound"] != null) - { - mRightMouseClickSound = (string) obj["RightMouseClickSound"]; - } + w = mTexture.GetWidth(); } - /// - /// Sets the texture coordinates of the image. - /// - public virtual void SetUv(float u1, float v1, float u2, float v2) + if (h <= 0) { - mUv[0] = u1; - mUv[1] = v1; - mUv[2] = u2; - mUv[3] = v2; + h = mTexture.GetHeight(); } - /// - /// Sets the texture coordinates of the image. - /// - public virtual void SetTextureRect(int x, int y, int w, int h) + if (x + w > mTexture.GetWidth() || y + h > mTexture.GetHeight()) { - if (mTexture == null) - { - return; - } - - if (x < 0) - { - x = 0; - } - - if (y < 0) - { - y = 0; - } - - if (w <= 0) - { - w = mTexture.GetWidth(); - } - - if (h <= 0) - { - h = mTexture.GetHeight(); - } - - if (x + w > mTexture.GetWidth() || y + h > mTexture.GetHeight()) - { - return; - } - - mUv[0] = (float) x / (float) mTexture.GetWidth(); - mUv[1] = (float) y / (float) mTexture.GetHeight(); - mUv[2] = (float) (x + w) / (float) mTexture.GetWidth(); - mUv[3] = (float) (y + h) / (float) mTexture.GetHeight(); + return; } - public virtual Rectangle GetTextureRect() + mUv[0] = (float) x / (float) mTexture.GetWidth(); + mUv[1] = (float) y / (float) mTexture.GetHeight(); + mUv[2] = (float) (x + w) / (float) mTexture.GetWidth(); + mUv[3] = (float) (y + h) / (float) mTexture.GetHeight(); + } + + public virtual Rectangle GetTextureRect() + { + if (Texture == null) { - if (Texture == null) - { - return new Rectangle(0, 0, 0, 0); - } - - return new Rectangle( - (int) (mUv[0] * mTexture.GetWidth()), (int) (mUv[1] * mTexture.GetHeight()), - (int) ((mUv[2] - mUv[0]) * mTexture.GetWidth()), (int) ((mUv[3] - mUv[1]) * mTexture.GetWidth()) - ); + return new Rectangle(0, 0, 0, 0); } - /// - /// Renders the control using specified skin. - /// - /// Skin to use. - protected override void Render(Skin.Base skin) + return new Rectangle( + (int) (mUv[0] * mTexture.GetWidth()), (int) (mUv[1] * mTexture.GetHeight()), + (int) ((mUv[2] - mUv[0]) * mTexture.GetWidth()), (int) ((mUv[3] - mUv[1]) * mTexture.GetWidth()) + ); + } + + /// + /// Renders the control using specified skin. + /// + /// Skin to use. + protected override void Render(Skin.Base skin) + { + base.Render(skin); + skin.Renderer.DrawColor = base.RenderColor; + skin.Renderer.DrawTexturedRect(mTexture, RenderBounds, base.RenderColor, mUv[0], mUv[1], mUv[2], mUv[3]); + } + + /// + /// Sizes the control to its contents. + /// + public virtual void SizeToContents() + { + if (mTexture == null) { - base.Render(skin); - skin.Renderer.DrawColor = base.RenderColor; - skin.Renderer.DrawTexturedRect(mTexture, RenderBounds, base.RenderColor, mUv[0], mUv[1], mUv[2], mUv[3]); + return; } - /// - /// Sizes the control to its contents. - /// - public virtual void SizeToContents() - { - if (mTexture == null) - { - return; - } + SetSize((int) (mTexture.GetWidth() * (mUv[2] - mUv[0])), (int) (mTexture.GetHeight() * (mUv[3] - mUv[1]))); + } - SetSize((int) (mTexture.GetWidth() * (mUv[2] - mUv[0])), (int) (mTexture.GetHeight() * (mUv[3] - mUv[1]))); - } + /// + /// Control has been clicked - invoked by input system. Windows use it to propagate activation. + /// + public override void Touch() + { + base.Touch(); + } - /// - /// Control has been clicked - invoked by input system. Windows use it to propagate activation. - /// - public override void Touch() + /// + /// Handler for Space keyboard event. + /// + /// Indicates whether the key was pressed or released. + /// + /// True if handled. + /// + protected override bool OnKeySpace(bool down) + { + if (down) { - base.Touch(); + base.OnMouseClickedLeft(0, 0, true); } - /// - /// Handler for Space keyboard event. - /// - /// Indicates whether the key was pressed or released. - /// - /// True if handled. - /// - protected override bool OnKeySpace(bool down) - { - if (down) - { - base.OnMouseClickedLeft(0, 0, true); - } + return true; + } - return true; + /// + /// Makes the window modal: covers the whole canvas and gets all input. + /// + /// Determines whether all the background should be dimmed. + public void MakeModal(bool dim = false) + { + if (mModal != null) + { + return; } - /// - /// Makes the window modal: covers the whole canvas and gets all input. - /// - /// Determines whether all the background should be dimmed. - public void MakeModal(bool dim = false) + mModal = new Modal(GetCanvas()) { - if (mModal != null) - { - return; - } - - mModal = new Modal(GetCanvas()) - { - ShouldDrawBackground = dim - }; - - mOldParent = Parent; - Parent = mModal; - } + ShouldDrawBackground = dim + }; + + mOldParent = Parent; + Parent = mModal; + } - public void RemoveModal() + public void RemoveModal() + { + if (mModal == null) { - if (mModal == null) - { - return; - } - - Parent = mOldParent; - GetCanvas()?.RemoveChild(mModal, false); - mModal = null; + return; } + Parent = mOldParent; + GetCanvas()?.RemoveChild(mModal, false); + mModal = null; } } diff --git a/Intersect.Client.Framework/Gwen/Control/Label.cs b/Intersect.Client.Framework/Gwen/Control/Label.cs index 8f05a87a23..254e6e4449 100644 --- a/Intersect.Client.Framework/Gwen/Control/Label.cs +++ b/Intersect.Client.Framework/Gwen/Control/Label.cs @@ -5,618 +5,616 @@ using Newtonsoft.Json.Linq; -namespace Intersect.Client.Framework.Gwen.Control +namespace Intersect.Client.Framework.Gwen.Control; + + +/// +/// Static text label. +/// +public partial class Label : Base, ILabel { - /// - /// Static text label. - /// - public partial class Label : Base, ILabel + public enum ControlState { - public enum ControlState - { + Normal = 0, - Normal = 0, + Hovered, - Hovered, + Clicked, - Clicked, + Disabled, - Disabled, - - } + } - protected readonly Text mText; + protected readonly Text mText; - private string fontInfo; + private string fontInfo; - private Pos mAlign; + private Pos mAlign; - private bool mAutoSizeToContents; + private bool mAutoSizeToContents; - private string mBackgroundTemplateFilename; + private string mBackgroundTemplateFilename; - private GameTexture mBackgroundTemplateTex; + private GameTexture mBackgroundTemplateTex; - protected Color mClickedTextColor; + protected Color mClickedTextColor; - protected Color mDisabledTextColor; + protected Color mDisabledTextColor; - protected Color mHoverTextColor; + protected Color mHoverTextColor; - protected Color mNormalTextColor; + protected Color mNormalTextColor; - private Padding mTextPadding; + private Padding mTextPadding; - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public Label(Base parent, string name = default, bool disableText = false) : base(parent, name) + /// + /// Initializes a new instance of the class. + /// + /// Parent control. + public Label(Base parent, string name = default, bool disableText = false) : base(parent, name) + { + mText = new Text(this) { - mText = new Text(this) - { - IsHidden = disableText, - }; + IsHidden = disableText, + }; - //m_Text.Font = Skin.DefaultFont; + //m_Text.Font = Skin.DefaultFont; - MouseInputEnabled = false; - SetSize(100, 10); - Alignment = Pos.Left | Pos.Top; + MouseInputEnabled = false; + SetSize(100, 10); + Alignment = Pos.Left | Pos.Top; - mAutoSizeToContents = true; - } + mAutoSizeToContents = true; + } - public GameTexture ToolTipBackground { get; set; } + public GameTexture ToolTipBackground { get; set; } - /// - /// Text alignment. - /// - public Pos Alignment - { - get => mAlign; - set => SetAndDoIfChanged(ref mAlign, value, Invalidate); - } + /// + /// Text alignment. + /// + public Pos Alignment + { + get => mAlign; + set => SetAndDoIfChanged(ref mAlign, value, Invalidate); + } - /// - /// Text. - /// - public virtual string Text - { - get => mText?.String; - set => SetText(value); - } + /// + /// Text. + /// + public virtual string Text + { + get => mText?.String; + set => SetText(value); + } - /// - /// Font. - /// - public GameFont Font + /// + /// Font. + /// + public GameFont Font + { + get => mText?.Font; + set { - get => mText?.Font; - set + if (value != null) { - if (value != null) + if (mText != null) + { + mText.Font = value; + fontInfo = $"{value?.GetName()},{value?.GetSize()}"; + } + + if (mAutoSizeToContents) { - if (mText != null) - { - mText.Font = value; - fontInfo = $"{value?.GetName()},{value?.GetSize()}"; - } - - if (mAutoSizeToContents) - { - SizeToContents(); - } - - Invalidate(); + SizeToContents(); } + + Invalidate(); } } + } - /// - /// Font Name - /// - public string FontName - { - get => mText?.Font?.GetName() ?? "arial"; - set => Font = GameContentManager.Current?.GetFont(value, FontSize); - } + /// + /// Font Name + /// + public string FontName + { + get => mText?.Font?.GetName() ?? "arial"; + set => Font = GameContentManager.Current?.GetFont(value, FontSize); + } - /// - /// Font Size - /// - public int FontSize - { - get => mText?.Font?.GetSize() ?? 12; - set => Font = GameContentManager.Current?.GetFont(FontName, value); - } + /// + /// Font Size + /// + public int FontSize + { + get => mText?.Font?.GetSize() ?? 12; + set => Font = GameContentManager.Current?.GetFont(FontName, value); + } - /// - /// Text color. - /// - public Color TextColor - { - get => mText.TextColor; - set => mText.TextColor = value; - } + /// + /// Text color. + /// + public Color TextColor + { + get => mText.TextColor; + set => mText.TextColor = value; + } - /// - /// Override text color (used by tooltips). - /// - public Color TextColorOverride - { - get => mText.TextColorOverride; - set => mText.TextColorOverride = value; - } + /// + /// Override text color (used by tooltips). + /// + public Color TextColorOverride + { + get => mText.TextColorOverride; + set => mText.TextColorOverride = value; + } - /// - /// Text override - used to display different string. - /// - public string TextOverride - { - get => mText.TextOverride; - set => mText.TextOverride = value; - } + /// + /// Text override - used to display different string. + /// + public string TextOverride + { + get => mText.TextOverride; + set => mText.TextOverride = value; + } - /// - /// Width of the text (in pixels). - /// - public int TextWidth => mText.Width; + /// + /// Width of the text (in pixels). + /// + public int TextWidth => mText.Width; - /// - /// Height of the text (in pixels). - /// - public int TextHeight => mText.Height; + /// + /// Height of the text (in pixels). + /// + public int TextHeight => mText.Height; - public int TextX => mText.X; + public int TextX => mText.X; - public int TextY => mText.Y; + public int TextY => mText.Y; - /// - /// Text length (in characters). - /// - public int TextLength => mText.Length; + /// + /// Text length (in characters). + /// + public int TextLength => mText.Length; - public int TextRight => mText.Right; + public int TextRight => mText.Right; - /// - /// Determines if the control should autosize to its text. - /// - public bool AutoSizeToContents + /// + /// Determines if the control should autosize to its text. + /// + public bool AutoSizeToContents + { + get => mAutoSizeToContents; + set { - get => mAutoSizeToContents; - set - { - mAutoSizeToContents = value; - Invalidate(); - InvalidateParent(); - } + mAutoSizeToContents = value; + Invalidate(); + InvalidateParent(); } + } - /// - /// Text padding. - /// - public Padding TextPadding + /// + /// Text padding. + /// + public Padding TextPadding + { + get => mTextPadding; + set { - get => mTextPadding; - set - { - mTextPadding = value; - Invalidate(); - InvalidateParent(); - } + mTextPadding = value; + Invalidate(); + InvalidateParent(); } + } - public override JObject GetJson(bool isRoot = default) + public override JObject GetJson(bool isRoot = default) + { + var obj = base.GetJson(isRoot); + if (typeof(Label) == GetType()) { - var obj = base.GetJson(isRoot); - if (typeof(Label) == GetType()) - { - obj.Add("BackgroundTemplate", mBackgroundTemplateFilename); - } - - obj.Add("TextColor", Color.ToString(TextColor)); - obj.Add("HoveredTextColor", Color.ToString(mHoverTextColor)); - obj.Add("ClickedTextColor", Color.ToString(mClickedTextColor)); - obj.Add("DisabledTextColor", Color.ToString(mDisabledTextColor)); - obj.Add("TextAlign", mAlign.ToString()); - obj.Add("TextPadding", Padding.ToString(mTextPadding)); - obj.Add("AutoSizeToContents", mAutoSizeToContents); - obj.Add("Font", fontInfo); - obj.Add("TextScale", mText.GetScale()); - - return base.FixJson(obj); + obj.Add("BackgroundTemplate", mBackgroundTemplateFilename); } - public override void LoadJson(JToken obj, bool isRoot = default) - { - base.LoadJson(obj); - if (typeof(Label) == GetType() && obj["BackgroundTemplate"] != null) - { - SetBackgroundTemplate( - GameContentManager.Current.GetTexture( - Framework.Content.TextureType.Gui, (string)obj["BackgroundTemplate"] - ), (string)obj["BackgroundTemplate"] - ); - } - - if (obj["TextColor"] != null) - { - TextColor = Color.FromString((string)obj["TextColor"]); - } - - mNormalTextColor = TextColor; - if (obj["HoveredTextColor"] != null) - { - mHoverTextColor = Color.FromString((string)obj["HoveredTextColor"]); - } - - if (obj["ClickedTextColor"] != null) - { - mClickedTextColor = Color.FromString((string)obj["ClickedTextColor"]); - } - - mDisabledTextColor = Color.FromString((string)obj["DisabledTextColor"], new Color(255, 90, 90, 90)); - if (obj["TextAlign"] != null) - { - mAlign = (Pos)Enum.Parse(typeof(Pos), (string)obj["TextAlign"]); - } - - if (obj["TextPadding"] != null) - { - TextPadding = Padding.FromString((string)obj["TextPadding"]); - } - - if (obj["AutoSizeToContents"] != null) - { - mAutoSizeToContents = (bool)obj["AutoSizeToContents"]; - } + obj.Add("TextColor", Color.ToString(TextColor)); + obj.Add("HoveredTextColor", Color.ToString(mHoverTextColor)); + obj.Add("ClickedTextColor", Color.ToString(mClickedTextColor)); + obj.Add("DisabledTextColor", Color.ToString(mDisabledTextColor)); + obj.Add("TextAlign", mAlign.ToString()); + obj.Add("TextPadding", Padding.ToString(mTextPadding)); + obj.Add("AutoSizeToContents", mAutoSizeToContents); + obj.Add("Font", fontInfo); + obj.Add("TextScale", mText.GetScale()); - if (obj["Font"] != null && obj["Font"].Type != JTokenType.Null) - { - var fontArr = ((string)obj["Font"]).Split(','); - fontInfo = (string)obj["Font"]; - Font = GameContentManager.Current.GetFont(fontArr[0], int.Parse(fontArr[1])); - } + return base.FixJson(obj); + } - if (obj["TextScale"] != null) - { - mText.SetScale((float)obj["TextScale"]); - } + public override void LoadJson(JToken obj, bool isRoot = default) + { + base.LoadJson(obj); + if (typeof(Label) == GetType() && obj["BackgroundTemplate"] != null) + { + SetBackgroundTemplate( + GameContentManager.Current.GetTexture( + Framework.Content.TextureType.Gui, (string)obj["BackgroundTemplate"] + ), (string)obj["BackgroundTemplate"] + ); } - public GameTexture GetTemplate() + if (obj["TextColor"] != null) { - return mBackgroundTemplateTex; + TextColor = Color.FromString((string)obj["TextColor"]); } - public void SetBackgroundTemplate(GameTexture texture, string fileName) + mNormalTextColor = TextColor; + if (obj["HoveredTextColor"] != null) { - if (texture == null && !string.IsNullOrWhiteSpace(fileName)) - { - texture = GameContentManager.Current?.GetTexture(Framework.Content.TextureType.Gui, fileName); - } - - mBackgroundTemplateFilename = fileName; - mBackgroundTemplateTex = texture; + mHoverTextColor = Color.FromString((string)obj["HoveredTextColor"]); } - public virtual void MakeColorNormal() + if (obj["ClickedTextColor"] != null) { - TextColor = Skin.Colors.Label.Default; + mClickedTextColor = Color.FromString((string)obj["ClickedTextColor"]); } - public virtual void MakeColorBright() + mDisabledTextColor = Color.FromString((string)obj["DisabledTextColor"], new Color(255, 90, 90, 90)); + if (obj["TextAlign"] != null) { - TextColor = Skin.Colors.Label.Bright; + mAlign = (Pos)Enum.Parse(typeof(Pos), (string)obj["TextAlign"]); } - public virtual void MakeColorDark() + if (obj["TextPadding"] != null) { - TextColor = Skin.Colors.Label.Dark; + TextPadding = Padding.FromString((string)obj["TextPadding"]); } - public virtual void MakeColorHighlight() + if (obj["AutoSizeToContents"] != null) { - TextColor = Skin.Colors.Label.Highlight; + mAutoSizeToContents = (bool)obj["AutoSizeToContents"]; } - public override event Base.GwenEventHandler Clicked + if (obj["Font"] != null && obj["Font"].Type != JTokenType.Null) { - add - { - base.Clicked += value; - MouseInputEnabled = ClickEventAssigned; - } - remove - { - base.Clicked -= value; - MouseInputEnabled = ClickEventAssigned; - } + var fontArr = ((string)obj["Font"]).Split(','); + fontInfo = (string)obj["Font"]; + Font = GameContentManager.Current.GetFont(fontArr[0], int.Parse(fontArr[1])); } - public override event Base.GwenEventHandler DoubleClicked + if (obj["TextScale"] != null) { - add - { - base.DoubleClicked += value; - MouseInputEnabled = ClickEventAssigned; - } - remove - { - base.DoubleClicked -= value; - MouseInputEnabled = ClickEventAssigned; - } + mText.SetScale((float)obj["TextScale"]); } + } + + public GameTexture GetTemplate() + { + return mBackgroundTemplateTex; + } - public override event Base.GwenEventHandler RightClicked + public void SetBackgroundTemplate(GameTexture texture, string fileName) + { + if (texture == null && !string.IsNullOrWhiteSpace(fileName)) { - add - { - base.RightClicked += value; - MouseInputEnabled = ClickEventAssigned; - } - remove - { - base.RightClicked -= value; - MouseInputEnabled = ClickEventAssigned; - } + texture = GameContentManager.Current?.GetTexture(Framework.Content.TextureType.Gui, fileName); } - public override event Base.GwenEventHandler DoubleRightClicked + mBackgroundTemplateFilename = fileName; + mBackgroundTemplateTex = texture; + } + + public virtual void MakeColorNormal() + { + TextColor = Skin.Colors.Label.Default; + } + + public virtual void MakeColorBright() + { + TextColor = Skin.Colors.Label.Bright; + } + + public virtual void MakeColorDark() + { + TextColor = Skin.Colors.Label.Dark; + } + + public virtual void MakeColorHighlight() + { + TextColor = Skin.Colors.Label.Highlight; + } + + public override event Base.GwenEventHandler Clicked + { + add { - add - { - base.DoubleRightClicked += value; - MouseInputEnabled = ClickEventAssigned; - } - remove - { - base.DoubleRightClicked -= value; - MouseInputEnabled = ClickEventAssigned; - } + base.Clicked += value; + MouseInputEnabled = ClickEventAssigned; } - - /// - /// Returns index of the character closest to specified point (in canvas coordinates). - /// - /// - /// - /// - protected virtual Point GetClosestCharacter(int x, int y) + remove { - return new Point(mText.GetClosestCharacter(mText.CanvasPosToLocal(new Point(x, y))), 0); + base.Clicked -= value; + MouseInputEnabled = ClickEventAssigned; } + } - /// - /// Sets the position of the internal text control. - /// - /// - /// - protected void SetTextPosition(int x, int y) + public override event Base.GwenEventHandler DoubleClicked + { + add + { + base.DoubleClicked += value; + MouseInputEnabled = ClickEventAssigned; + } + remove { - mText.SetPosition(x, y); + base.DoubleClicked -= value; + MouseInputEnabled = ClickEventAssigned; } + } - /// - /// Handler for text changed event. - /// - protected virtual void OnTextChanged() + public override event Base.GwenEventHandler RightClicked + { + add + { + base.RightClicked += value; + MouseInputEnabled = ClickEventAssigned; + } + remove { + base.RightClicked -= value; + MouseInputEnabled = ClickEventAssigned; } + } - /// - /// Lays out the control's interior according to alignment, padding, dock etc. - /// - /// Skin to use. - protected override void Layout(Skin.Base skin) + public override event Base.GwenEventHandler DoubleRightClicked + { + add + { + base.DoubleRightClicked += value; + MouseInputEnabled = ClickEventAssigned; + } + remove { - base.Layout(skin); + base.DoubleRightClicked -= value; + MouseInputEnabled = ClickEventAssigned; + } + } - var align = mAlign; + /// + /// Returns index of the character closest to specified point (in canvas coordinates). + /// + /// + /// + /// + protected virtual Point GetClosestCharacter(int x, int y) + { + return new Point(mText.GetClosestCharacter(mText.CanvasPosToLocal(new Point(x, y))), 0); + } - if (mAutoSizeToContents) - { - SizeToContents(); - } + /// + /// Sets the position of the internal text control. + /// + /// + /// + protected void SetTextPosition(int x, int y) + { + mText.SetPosition(x, y); + } - var x = mTextPadding.Left + Padding.Left; - var y = mTextPadding.Top + Padding.Top; + /// + /// Handler for text changed event. + /// + protected virtual void OnTextChanged() + { + } - if (0 != (align & Pos.Right)) - { - x = Width - mText.Width - mTextPadding.Right - Padding.Right; - } + /// + /// Lays out the control's interior according to alignment, padding, dock etc. + /// + /// Skin to use. + protected override void Layout(Skin.Base skin) + { + base.Layout(skin); - if (0 != (align & Pos.CenterH)) - { - x = (int)(mTextPadding.Left + - Padding.Left + - (Width - - mText.Width - - mTextPadding.Left - - Padding.Left - - mTextPadding.Right - - Padding.Right) * - 0.5f); - } + var align = mAlign; - if (0 != (align & Pos.CenterV)) - { - y = (int)(mTextPadding.Top + - Padding.Top + - (Height - mText.Height) * 0.5f - - mTextPadding.Bottom - - Padding.Bottom); - } + if (mAutoSizeToContents) + { + SizeToContents(); + } - if (0 != (align & Pos.Bottom)) - { - y = Height - mText.Height - mTextPadding.Bottom - Padding.Bottom; - } + var x = mTextPadding.Left + Padding.Left; + var y = mTextPadding.Top + Padding.Top; - mText.SetPosition(x, y); + if (0 != (align & Pos.Right)) + { + x = Width - mText.Width - mTextPadding.Right - Padding.Right; } - /// - /// Sets the label text. - /// - /// Text to set. - /// Determines whether to invoke "text changed" event. - public virtual void SetText(string str, bool doEvents = true) + if (0 != (align & Pos.CenterH)) { - if (Text == str) - { - return; - } - - mText.String = str; - if (mAutoSizeToContents) - { - SizeToContents(); - } - - Invalidate(); - InvalidateParent(); - - if (doEvents) - { - OnTextChanged(); - } + x = (int)(mTextPadding.Left + + Padding.Left + + (Width - + mText.Width - + mTextPadding.Left - + Padding.Left - + mTextPadding.Right - + Padding.Right) * + 0.5f); } - public virtual void SetTextScale(float scale) + if (0 != (align & Pos.CenterV)) { - mText.SetScale(scale); - if (mAutoSizeToContents) - { - SizeToContents(); - } - - Invalidate(); - InvalidateParent(); + y = (int)(mTextPadding.Top + + Padding.Top + + (Height - mText.Height) * 0.5f - + mTextPadding.Bottom - + Padding.Bottom); } - public virtual void SizeToContents() + if (0 != (align & Pos.Bottom)) { - mText.SetPosition(mTextPadding.Left + Padding.Left, mTextPadding.Top + Padding.Top); - mText.SizeToContents(); + y = Height - mText.Height - mTextPadding.Bottom - Padding.Bottom; + } - SetSize( - mText.Width + Padding.Left + Padding.Right + mTextPadding.Left + mTextPadding.Right, - mText.Height + Padding.Top + Padding.Bottom + mTextPadding.Top + mTextPadding.Bottom - ); + mText.SetPosition(x, y); + } - ProcessAlignments(); - InvalidateParent(); + /// + /// Sets the label text. + /// + /// Text to set. + /// Determines whether to invoke "text changed" event. + public virtual void SetText(string str, bool doEvents = true) + { + if (Text == str) + { + return; } - /// - /// Gets the coordinates of specified character. - /// - /// Character index. - /// Character coordinates (local). - public virtual Point GetCharacterPosition(int index) + mText.String = str; + if (mAutoSizeToContents) { - var p = mText.GetCharacterPosition(index); - - return new Point(p.X + mText.X, p.Y + mText.Y); + SizeToContents(); } - /// - /// Renders the control using specified skin. - /// - /// Skin to use. - protected override void Render(Skin.Base skin) + Invalidate(); + InvalidateParent(); + + if (doEvents) { - skin.DrawLabel(this); + OnTextChanged(); } + } - /// - /// Updates control colors. - /// - public override void UpdateColors() + public virtual void SetTextScale(float scale) + { + mText.SetScale(scale); + if (mAutoSizeToContents) { - var textColor = GetTextColor(ControlState.Normal); - if (IsDisabled && GetTextColor(ControlState.Disabled) != null) - { - textColor = GetTextColor(ControlState.Disabled); - } - else if (IsHovered && GetTextColor(ControlState.Hovered) != null) - { - textColor = GetTextColor(ControlState.Hovered); - } + SizeToContents(); + } - if (textColor != null) - { - TextColor = textColor; + Invalidate(); + InvalidateParent(); + } - return; - } + public virtual void SizeToContents() + { + mText.SetPosition(mTextPadding.Left + Padding.Left, mTextPadding.Top + Padding.Top); + mText.SizeToContents(); - if (IsDisabled) - { - TextColor = Skin.Colors.Button.Disabled; + SetSize( + mText.Width + Padding.Left + Padding.Right + mTextPadding.Left + mTextPadding.Right, + mText.Height + Padding.Top + Padding.Bottom + mTextPadding.Top + mTextPadding.Bottom + ); - return; - } + ProcessAlignments(); + InvalidateParent(); + } - if (IsHovered && ClickEventAssigned) - { - TextColor = Skin.Colors.Button.Hover; + /// + /// Gets the coordinates of specified character. + /// + /// Character index. + /// Character coordinates (local). + public virtual Point GetCharacterPosition(int index) + { + var p = mText.GetCharacterPosition(index); - return; - } + return new Point(p.X + mText.X, p.Y + mText.Y); + } + + /// + /// Renders the control using specified skin. + /// + /// Skin to use. + protected override void Render(Skin.Base skin) + { + skin.DrawLabel(this); + } - TextColor = Skin.Colors.Button.Normal; + /// + /// Updates control colors. + /// + public override void UpdateColors() + { + var textColor = GetTextColor(ControlState.Normal); + if (IsDisabled && GetTextColor(ControlState.Disabled) != null) + { + textColor = GetTextColor(ControlState.Disabled); + } + else if (IsHovered && GetTextColor(ControlState.Hovered) != null) + { + textColor = GetTextColor(ControlState.Hovered); } - public virtual void SetTextColor(Color clr, ControlState state) + if (textColor != null) { - switch (state) - { - case ControlState.Normal: - mNormalTextColor = clr; + TextColor = textColor; - break; - case ControlState.Hovered: - mHoverTextColor = clr; + return; + } - break; - case ControlState.Clicked: - mClickedTextColor = clr; + if (IsDisabled) + { + TextColor = Skin.Colors.Button.Disabled; - break; - case ControlState.Disabled: - mDisabledTextColor = clr; + return; + } - break; - default: - throw new ArgumentOutOfRangeException(nameof(state), state, null); - } + if (IsHovered && ClickEventAssigned) + { + TextColor = Skin.Colors.Button.Hover; - UpdateColors(); + return; } - public virtual Color? GetTextColor(ControlState state) + TextColor = Skin.Colors.Button.Normal; + } + + public virtual void SetTextColor(Color clr, ControlState state) + { + switch (state) { - switch (state) - { - case ControlState.Normal: - return mNormalTextColor; - case ControlState.Hovered: - return mHoverTextColor; - case ControlState.Clicked: - return mClickedTextColor; - case ControlState.Disabled: - return mDisabledTextColor; - default: - return null; - } + case ControlState.Normal: + mNormalTextColor = clr; + + break; + case ControlState.Hovered: + mHoverTextColor = clr; + + break; + case ControlState.Clicked: + mClickedTextColor = clr; + + break; + case ControlState.Disabled: + mDisabledTextColor = clr; + + break; + default: + throw new ArgumentOutOfRangeException(nameof(state), state, null); } + UpdateColors(); + } + + public virtual Color? GetTextColor(ControlState state) + { + switch (state) + { + case ControlState.Normal: + return mNormalTextColor; + case ControlState.Hovered: + return mHoverTextColor; + case ControlState.Clicked: + return mClickedTextColor; + case ControlState.Disabled: + return mDisabledTextColor; + default: + return null; + } } } diff --git a/Intersect.Client.Framework/Gwen/Control/LabeledCheckBox.cs b/Intersect.Client.Framework/Gwen/Control/LabeledCheckBox.cs index 935975e505..b0538920ac 100644 --- a/Intersect.Client.Framework/Gwen/Control/LabeledCheckBox.cs +++ b/Intersect.Client.Framework/Gwen/Control/LabeledCheckBox.cs @@ -3,174 +3,172 @@ using Newtonsoft.Json.Linq; -namespace Intersect.Client.Framework.Gwen.Control +namespace Intersect.Client.Framework.Gwen.Control; + + +/// +/// CheckBox with label. +/// +public partial class LabeledCheckBox : Base { + private readonly CheckBox mCheckBox; + + private readonly Label mLabel; + /// - /// CheckBox with label. + /// Initializes a new instance of the class. /// - public partial class LabeledCheckBox : Base + /// Parent control. + public LabeledCheckBox(Base parent, string name = "") : base(parent, name) { + _ = SetSize(200, 19); - private readonly CheckBox mCheckBox; - - private readonly Label mLabel; - - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public LabeledCheckBox(Base parent, string name = "") : base(parent, name) + mCheckBox = new CheckBox(this) + { + InheritParentEnablementProperties = true, + Dock = Pos.Left, + Margin = new Margin(0, 2, 2, 2), + IsTabable = false + }; + mCheckBox.CheckChanged += OnCheckChanged; + + mLabel = new Label(this) { - _ = SetSize(200, 19); + InheritParentEnablementProperties = true, + Dock = Pos.Fill, + IsTabable = false + }; + mLabel.Clicked += delegate (Base control, ClickedEventArgs args) { mCheckBox.Press(control); }; - mCheckBox = new CheckBox(this) - { - InheritParentEnablementProperties = true, - Dock = Pos.Left, - Margin = new Margin(0, 2, 2, 2), - IsTabable = false - }; - mCheckBox.CheckChanged += OnCheckChanged; - - mLabel = new Label(this) - { - InheritParentEnablementProperties = true, - Dock = Pos.Fill, - IsTabable = false - }; - mLabel.Clicked += delegate (Base control, ClickedEventArgs args) { mCheckBox.Press(control); }; + IsTabable = false; + } - IsTabable = false; - } + /// + /// Indicates whether the control is checked. + /// + public bool IsChecked + { + get => mCheckBox.IsChecked; + set => mCheckBox.IsChecked = value; + } - /// - /// Indicates whether the control is checked. - /// - public bool IsChecked - { - get => mCheckBox.IsChecked; - set => mCheckBox.IsChecked = value; - } + /// + /// Label text. + /// + public string Text + { + get => mLabel.Text; + set => mLabel.Text = value; + } - /// - /// Label text. - /// - public string Text - { - get => mLabel.Text; - set => mLabel.Text = value; - } + /// + /// Invoked when the control has been checked. + /// + public event GwenEventHandler Checked; + + /// + /// Invoked when the control has been unchecked. + /// + public event GwenEventHandler UnChecked; - /// - /// Invoked when the control has been checked. - /// - public event GwenEventHandler Checked; + /// + /// Invoked when the control's check has been changed. + /// + public event GwenEventHandler CheckChanged; - /// - /// Invoked when the control has been unchecked. - /// - public event GwenEventHandler UnChecked; + public override JObject GetJson(bool isRoot = default) + { + var obj = base.GetJson(isRoot); + obj.Add("Label", mLabel.GetJson()); + obj.Add("Checkbox", mCheckBox.GetJson()); - /// - /// Invoked when the control's check has been changed. - /// - public event GwenEventHandler CheckChanged; + return base.FixJson(obj); + } - public override JObject GetJson(bool isRoot = default) + public override void LoadJson(JToken obj, bool isRoot = default) + { + base.LoadJson(obj); + if (obj["Label"] != null) { - var obj = base.GetJson(isRoot); - obj.Add("Label", mLabel.GetJson()); - obj.Add("Checkbox", mCheckBox.GetJson()); - - return base.FixJson(obj); + mLabel.Dock = Pos.None; + mLabel.LoadJson(obj["Label"]); } - public override void LoadJson(JToken obj, bool isRoot = default) + if (obj["Checkbox"] != null) { - base.LoadJson(obj); - if (obj["Label"] != null) - { - mLabel.Dock = Pos.None; - mLabel.LoadJson(obj["Label"]); - } - - if (obj["Checkbox"] != null) - { - mCheckBox.Dock = Pos.None; - mCheckBox.LoadJson(obj["Checkbox"]); - } + mCheckBox.Dock = Pos.None; + mCheckBox.LoadJson(obj["Checkbox"]); } + } - /// - /// Handler for CheckChanged event. - /// - protected virtual void OnCheckChanged(Base control, EventArgs args) + /// + /// Handler for CheckChanged event. + /// + protected virtual void OnCheckChanged(Base control, EventArgs args) + { + if (mCheckBox.IsChecked) { - if (mCheckBox.IsChecked) - { - if (Checked != null) - { - Checked.Invoke(this, EventArgs.Empty); - } - } - else + if (Checked != null) { - if (UnChecked != null) - { - UnChecked.Invoke(this, EventArgs.Empty); - } + Checked.Invoke(this, EventArgs.Empty); } - - if (CheckChanged != null) + } + else + { + if (UnChecked != null) { - CheckChanged.Invoke(this, EventArgs.Empty); + UnChecked.Invoke(this, EventArgs.Empty); } } - public void SetCheckSize(int w, int h) + if (CheckChanged != null) { - mCheckBox.SetSize(w, h); + CheckChanged.Invoke(this, EventArgs.Empty); } + } - public void SetImage(GameTexture texture, string fileName, CheckBox.ControlState state) - { - mCheckBox.SetImage(texture, fileName, state); - } + public void SetCheckSize(int w, int h) + { + mCheckBox.SetSize(w, h); + } - public void SetTextColor(Color clr, Label.ControlState state) - { - mLabel.SetTextColor(clr, state); - } + public void SetImage(GameTexture texture, string fileName, CheckBox.ControlState state) + { + mCheckBox.SetImage(texture, fileName, state); + } - public void SetLabelDistance(int dist) - { - mCheckBox.Margin = new Margin(0, 2, dist, 2); - } + public void SetTextColor(Color clr, Label.ControlState state) + { + mLabel.SetTextColor(clr, state); + } - public void SetFont(GameFont font) - { - mLabel.Font = font; - } + public void SetLabelDistance(int dist) + { + mCheckBox.Margin = new Margin(0, 2, dist, 2); + } - /// - /// Handler for Space keyboard event. - /// - /// Indicates whether the key was pressed or released. - /// - /// True if handled. - /// - protected override bool OnKeySpace(bool down) - { - base.OnKeySpace(down); - if (!down) - { - mCheckBox.IsChecked = !mCheckBox.IsChecked; - } + public void SetFont(GameFont font) + { + mLabel.Font = font; + } - return true; + /// + /// Handler for Space keyboard event. + /// + /// Indicates whether the key was pressed or released. + /// + /// True if handled. + /// + protected override bool OnKeySpace(bool down) + { + base.OnKeySpace(down); + if (!down) + { + mCheckBox.IsChecked = !mCheckBox.IsChecked; } + return true; } } diff --git a/Intersect.Client.Framework/Gwen/Control/LabeledHorizontalSlider.cs b/Intersect.Client.Framework/Gwen/Control/LabeledHorizontalSlider.cs index 0f9007ab18..5d1675f141 100644 --- a/Intersect.Client.Framework/Gwen/Control/LabeledHorizontalSlider.cs +++ b/Intersect.Client.Framework/Gwen/Control/LabeledHorizontalSlider.cs @@ -2,146 +2,145 @@ using Newtonsoft.Json.Linq; -namespace Intersect.Client.Framework.Gwen.Control +namespace Intersect.Client.Framework.Gwen.Control; + + +/// +/// Base slider. +/// +public partial class LabeledHorizontalSlider : Base { + private readonly Label _label; + private readonly HorizontalSlider _slider; + private readonly ImagePanel _sliderBackground; + private readonly TextBoxNumeric _sliderValue; + private double _scale = 1.0; /// - /// Base slider. + /// Initializes a new instance of the class. /// - public partial class LabeledHorizontalSlider : Base + /// Parent control. + public LabeledHorizontalSlider(Base parent, string name = "") : base(parent, name) { - private readonly Label _label; - private readonly HorizontalSlider _slider; - private readonly ImagePanel _sliderBackground; - private readonly TextBoxNumeric _sliderValue; - private double _scale = 1.0; - - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public LabeledHorizontalSlider(Base parent, string name = "") : base(parent, name) - { - SetBounds(new Rectangle(0, 0, 32, 128)); + SetBounds(new Rectangle(0, 0, 32, 128)); - _label = new Label(this, "SliderLabel"); + _label = new Label(this, "SliderLabel"); - _sliderBackground = new ImagePanel(this, "SliderBackground"); - _slider = new HorizontalSlider(_sliderBackground, "Slider"); - _sliderValue = new TextBoxNumeric(_sliderBackground, "SliderValue"); + _sliderBackground = new ImagePanel(this, "SliderBackground"); + _slider = new HorizontalSlider(_sliderBackground, "Slider"); + _sliderValue = new TextBoxNumeric(_sliderBackground, "SliderValue"); - _slider.ValueChanged += (sender, arguments) => + _slider.ValueChanged += (sender, arguments) => + { + if (sender == _sliderValue) { - if (sender == _sliderValue) - { - return; - } + return; + } - _sliderValue.Value = _slider.Value * _scale; - ValueChanged?.Invoke(sender, arguments); - }; + _sliderValue.Value = _slider.Value * _scale; + ValueChanged?.Invoke(sender, arguments); + }; - _sliderValue.TextChanged += (sender, arguments) => + _sliderValue.TextChanged += (sender, arguments) => + { + if (sender == _slider) { - if (sender == _slider) - { - return; - } + return; + } - _slider.Value = _sliderValue.Value / _scale; - ValueChanged?.Invoke(sender, arguments); - }; + _slider.Value = _sliderValue.Value / _scale; + ValueChanged?.Invoke(sender, arguments); + }; - KeyboardInputEnabled = true; - IsTabable = true; - } + KeyboardInputEnabled = true; + IsTabable = true; + } - public string Label - { - get => _label.Text; - set => _label.Text = value; - } + public string Label + { + get => _label.Text; + set => _label.Text = value; + } - /// - /// Number of notches on the slider axis. - /// - public int NotchCount - { - get => _slider.NotchCount; - set => _slider.NotchCount = value; - } + /// + /// Number of notches on the slider axis. + /// + public int NotchCount + { + get => _slider.NotchCount; + set => _slider.NotchCount = value; + } - public double[] Notches - { - get => _slider.Notches; - set => _slider.Notches = value; - } + public double[] Notches + { + get => _slider.Notches; + set => _slider.Notches = value; + } - /// - /// Determines whether the slider should snap to notches. - /// - public bool SnapToNotches - { - get => _slider.SnapToNotches; - set => _slider.SnapToNotches = value; - } + /// + /// Determines whether the slider should snap to notches. + /// + public bool SnapToNotches + { + get => _slider.SnapToNotches; + set => _slider.SnapToNotches = value; + } - /// - /// Minimum value. - /// - public double Min - { - get => _slider.Min; - set => _slider.Min = value; - } + /// + /// Minimum value. + /// + public double Min + { + get => _slider.Min; + set => _slider.Min = value; + } - /// - /// Maximum value. - /// - public double Max - { - get => _slider.Max; - set => _slider.Max = value; - } + /// + /// Maximum value. + /// + public double Max + { + get => _slider.Max; + set => _slider.Max = value; + } - public double Scale + public double Scale + { + get => _scale; + set { - get => _scale; - set - { - _scale = value; - _sliderValue.Value = _slider.Value * _scale; - } + _scale = value; + _sliderValue.Value = _slider.Value * _scale; } + } - /// - /// Current value. - /// - public double Value + /// + /// Current value. + /// + public double Value + { + get => _slider.Value; + set { - get => _slider.Value; - set - { - _slider.Value = value; - _sliderValue.Value = _slider.Value * _scale; - } + _slider.Value = value; + _sliderValue.Value = _slider.Value * _scale; } + } - /// - /// Invoked when the value has been changed. - /// - public event GwenEventHandler ValueChanged; + /// + /// Invoked when the value has been changed. + /// + public event GwenEventHandler ValueChanged; - public override JObject GetJson(bool isRoot = default) - { - var obj = base.GetJson(isRoot); + public override JObject GetJson(bool isRoot = default) + { + var obj = base.GetJson(isRoot); - return base.FixJson(obj); - } + return base.FixJson(obj); + } - public override void LoadJson(JToken obj, bool isRoot = default) - { - base.LoadJson(obj); - } + public override void LoadJson(JToken obj, bool isRoot = default) + { + base.LoadJson(obj); } } diff --git a/Intersect.Client.Framework/Gwen/Control/LabeledRadioButton.cs b/Intersect.Client.Framework/Gwen/Control/LabeledRadioButton.cs index a1b818a6d4..abb266105e 100644 --- a/Intersect.Client.Framework/Gwen/Control/LabeledRadioButton.cs +++ b/Intersect.Client.Framework/Gwen/Control/LabeledRadioButton.cs @@ -1,117 +1,115 @@ using Intersect.Client.Framework.Gwen.Control.EventArguments; using Intersect.Client.Framework.Gwen.Input; -namespace Intersect.Client.Framework.Gwen.Control +namespace Intersect.Client.Framework.Gwen.Control; + + +/// +/// RadioButton with label. +/// +public partial class LabeledRadioButton : Base { + private readonly Label mLabel; + + private readonly RadioButton mRadioButton; + /// - /// RadioButton with label. + /// Initializes a new instance of the class. /// - public partial class LabeledRadioButton : Base + /// Parent control. + public LabeledRadioButton(Base parent) : base(parent) { + MouseInputEnabled = true; + _ = SetSize(100, 20); - private readonly Label mLabel; + mRadioButton = new RadioButton(this) + { + //Dock = Pos.Left, // no docking, it causes resizing + InheritParentEnablementProperties = true, + IsTabable = false, + KeyboardInputEnabled = false, + //Margin = new Margin(0, 2, 2, 2), + }; + + mLabel = new Label(this) + { + Alignment = Pos.CenterV | Pos.Left, + InheritParentEnablementProperties = true, + IsTabable = false, + KeyboardInputEnabled = false, + }; + mLabel.Clicked += delegate (Base control, ClickedEventArgs args) { mRadioButton.Press(control); }; + } - private readonly RadioButton mRadioButton; + /// + /// Label text. + /// + public string Text + { + get => mLabel.Text; + set => mLabel.Text = value; + } - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public LabeledRadioButton(Base parent) : base(parent) - { - MouseInputEnabled = true; - _ = SetSize(100, 20); - - mRadioButton = new RadioButton(this) - { - //Dock = Pos.Left, // no docking, it causes resizing - InheritParentEnablementProperties = true, - IsTabable = false, - KeyboardInputEnabled = false, - //Margin = new Margin(0, 2, 2, 2), - }; - - mLabel = new Label(this) - { - Alignment = Pos.CenterV | Pos.Left, - InheritParentEnablementProperties = true, - IsTabable = false, - KeyboardInputEnabled = false, - }; - mLabel.Clicked += delegate (Base control, ClickedEventArgs args) { mRadioButton.Press(control); }; - } + // todo: would be nice to remove that + internal RadioButton RadioButton => mRadioButton; - /// - /// Label text. - /// - public string Text + protected override void Layout(Skin.Base skin) + { + // ugly stuff because we don't have anchoring without docking (docking resizes children) + if (mLabel.Height > mRadioButton.Height + ) // usually radio is smaller than label so it gets repositioned to avoid clipping with negative Y { - get => mLabel.Text; - set => mLabel.Text = value; + mRadioButton.Y = (mLabel.Height - mRadioButton.Height) / 2; } - // todo: would be nice to remove that - internal RadioButton RadioButton => mRadioButton; + Align.PlaceRightBottom(mLabel, mRadioButton); + SizeToChildren(); + base.Layout(skin); + } - protected override void Layout(Skin.Base skin) + /// + /// Renders the focus overlay. + /// + /// Skin to use. + protected override void RenderFocus(Skin.Base skin) + { + if (InputHandler.KeyboardFocus != this) { - // ugly stuff because we don't have anchoring without docking (docking resizes children) - if (mLabel.Height > mRadioButton.Height - ) // usually radio is smaller than label so it gets repositioned to avoid clipping with negative Y - { - mRadioButton.Y = (mLabel.Height - mRadioButton.Height) / 2; - } - - Align.PlaceRightBottom(mLabel, mRadioButton); - SizeToChildren(); - base.Layout(skin); + return; } - /// - /// Renders the focus overlay. - /// - /// Skin to use. - protected override void RenderFocus(Skin.Base skin) + if (!IsTabable) { - if (InputHandler.KeyboardFocus != this) - { - return; - } - - if (!IsTabable) - { - return; - } - - skin.DrawKeyboardHighlight(this, RenderBounds, 0); + return; } - /// - /// Handler for Space keyboard event. - /// - /// Indicates whether the key was pressed or released. - /// - /// True if handled. - /// - protected override bool OnKeySpace(bool down) - { - if (down) - { - mRadioButton.IsChecked = !mRadioButton.IsChecked; - } - - return true; - } + skin.DrawKeyboardHighlight(this, RenderBounds, 0); + } - /// - /// Selects the radio button. - /// - public virtual void Select() + /// + /// Handler for Space keyboard event. + /// + /// Indicates whether the key was pressed or released. + /// + /// True if handled. + /// + protected override bool OnKeySpace(bool down) + { + if (down) { - mRadioButton.IsChecked = true; + mRadioButton.IsChecked = !mRadioButton.IsChecked; } + return true; + } + + /// + /// Selects the radio button. + /// + public virtual void Select() + { + mRadioButton.IsChecked = true; } } diff --git a/Intersect.Client.Framework/Gwen/Control/Layout/Positioner.cs b/Intersect.Client.Framework/Gwen/Control/Layout/Positioner.cs index 2c0886b7ac..7d9d917853 100644 --- a/Intersect.Client.Framework/Gwen/Control/Layout/Positioner.cs +++ b/Intersect.Client.Framework/Gwen/Control/Layout/Positioner.cs @@ -1,61 +1,59 @@ -namespace Intersect.Client.Framework.Gwen.Control.Layout +namespace Intersect.Client.Framework.Gwen.Control.Layout; + + +/// +/// Helper control that positions its children in a specific way. +/// +public partial class Positioner : Base { + private Pos mPos; + /// - /// Helper control that positions its children in a specific way. + /// Initializes a new instance of the class. /// - public partial class Positioner : Base + /// Parent control. + public Positioner(Base parent) : base(parent) { + Pos = Pos.Left | Pos.Top; + } - private Pos mPos; - - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public Positioner(Base parent) : base(parent) - { - Pos = Pos.Left | Pos.Top; - } + /// + /// Children position. + /// + public Pos Pos + { + get => mPos; + set => mPos = value; + } - /// - /// Children position. - /// - public Pos Pos + /// + /// Function invoked after layout. + /// + /// Skin to use. + protected override void PostLayout(Skin.Base skin) + { + foreach (var child in Children) // ok? { - get => mPos; - set => mPos = value; + child.Position(mPos); } + } - /// - /// Function invoked after layout. - /// - /// Skin to use. - protected override void PostLayout(Skin.Base skin) - { - foreach (var child in Children) // ok? - { - child.Position(mPos); - } - } +} - } +/// +/// Helper class that centers all its children. +/// +public partial class Center : Positioner +{ /// - /// Helper class that centers all its children. + /// Initializes a new instance of the class. /// - public partial class Center : Positioner + /// Parent control. + public Center(Base parent) : base(parent) { - - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public Center(Base parent) : base(parent) - { - Pos = Pos.Center; - } - + Pos = Pos.Center; } } diff --git a/Intersect.Client.Framework/Gwen/Control/Layout/Splitter.cs b/Intersect.Client.Framework/Gwen/Control/Layout/Splitter.cs index 18356cd01e..e3dc3412b4 100644 --- a/Intersect.Client.Framework/Gwen/Control/Layout/Splitter.cs +++ b/Intersect.Client.Framework/Gwen/Control/Layout/Splitter.cs @@ -1,111 +1,109 @@ -namespace Intersect.Client.Framework.Gwen.Control.Layout +namespace Intersect.Client.Framework.Gwen.Control.Layout; + + +/// +/// Base splitter class. +/// +public partial class Splitter : Base { + private readonly Base[] mPanel; + + private readonly bool[] mScale; + /// - /// Base splitter class. + /// Initializes a new instance of the class. /// - public partial class Splitter : Base + /// Parent control. + public Splitter(Base parent) : base(parent) { + mPanel = new Base[2]; + mScale = new bool[2]; + mScale[0] = true; + mScale[1] = true; + } - private readonly Base[] mPanel; + /// + /// Sets the contents of a splitter panel. + /// + /// Panel index (0-1). + /// Panel contents. + /// Determines whether the content is to be scaled. + public void SetPanel(int panelIndex, Base panel, bool noScale = false) + { + if (panelIndex < 0 || panelIndex > 1) + { + throw new ArgumentException("Invalid panel index", "panelIndex"); + } - private readonly bool[] mScale; + mPanel[panelIndex] = panel; + mScale[panelIndex] = !noScale; - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public Splitter(Base parent) : base(parent) + if (null != mPanel[panelIndex]) { - mPanel = new Base[2]; - mScale = new bool[2]; - mScale[0] = true; - mScale[1] = true; + mPanel[panelIndex].Parent = this; } + } - /// - /// Sets the contents of a splitter panel. - /// - /// Panel index (0-1). - /// Panel contents. - /// Determines whether the content is to be scaled. - public void SetPanel(int panelIndex, Base panel, bool noScale = false) + /// + /// Gets the contents of a secific panel. + /// + /// Panel index (0-1). + /// + Base GetPanel(int panelIndex) + { + if (panelIndex < 0 || panelIndex > 1) { - if (panelIndex < 0 || panelIndex > 1) - { - throw new ArgumentException("Invalid panel index", "panelIndex"); - } - - mPanel[panelIndex] = panel; - mScale[panelIndex] = !noScale; - - if (null != mPanel[panelIndex]) - { - mPanel[panelIndex].Parent = this; - } + throw new ArgumentException("Invalid panel index", "panelIndex"); } - /// - /// Gets the contents of a secific panel. - /// - /// Panel index (0-1). - /// - Base GetPanel(int panelIndex) - { - if (panelIndex < 0 || panelIndex > 1) - { - throw new ArgumentException("Invalid panel index", "panelIndex"); - } + return mPanel[panelIndex]; + } - return mPanel[panelIndex]; - } + /// + /// Lays out the control's interior according to alignment, padding, dock etc. + /// + /// Skin to use. + protected override void Layout(Skin.Base skin) + { + LayoutVertical(skin); + } - /// - /// Lays out the control's interior according to alignment, padding, dock etc. - /// - /// Skin to use. - protected override void Layout(Skin.Base skin) - { - LayoutVertical(skin); - } + protected virtual void LayoutVertical(Skin.Base skin) + { + var w = Width; + var h = Height; - protected virtual void LayoutVertical(Skin.Base skin) + if (mPanel[0] != null) { - var w = Width; - var h = Height; - - if (mPanel[0] != null) + var m = mPanel[0].Margin; + if (mScale[0]) { - var m = mPanel[0].Margin; - if (mScale[0]) - { - mPanel[0].SetBounds(m.Left, m.Top, w - m.Left - m.Right, h * 0.5f - m.Top - m.Bottom); - } - else - { - mPanel[0].Position(Pos.Center, 0, (int) (h * -0.25f)); - } + mPanel[0].SetBounds(m.Left, m.Top, w - m.Left - m.Right, h * 0.5f - m.Top - m.Bottom); } - - if (mPanel[1] != null) + else { - var m = mPanel[1].Margin; - if (mScale[1]) - { - mPanel[1].SetBounds(m.Left, m.Top + h * 0.5f, w - m.Left - m.Right, h * 0.5f - m.Top - m.Bottom); - } - else - { - mPanel[1].Position(Pos.Center, 0, (int) (h * 0.25f)); - } + mPanel[0].Position(Pos.Center, 0, (int) (h * -0.25f)); } } - protected virtual void LayoutHorizontal(Skin.Base skin) + if (mPanel[1] != null) { - throw new NotImplementedException(); + var m = mPanel[1].Margin; + if (mScale[1]) + { + mPanel[1].SetBounds(m.Left, m.Top + h * 0.5f, w - m.Left - m.Right, h * 0.5f - m.Top - m.Bottom); + } + else + { + mPanel[1].Position(Pos.Center, 0, (int) (h * 0.25f)); + } } + } + protected virtual void LayoutHorizontal(Skin.Base skin) + { + throw new NotImplementedException(); } } diff --git a/Intersect.Client.Framework/Gwen/Control/Layout/Table.cs b/Intersect.Client.Framework/Gwen/Control/Layout/Table.cs index 6b3d19bad0..b29a602a07 100644 --- a/Intersect.Client.Framework/Gwen/Control/Layout/Table.cs +++ b/Intersect.Client.Framework/Gwen/Control/Layout/Table.cs @@ -6,463 +6,461 @@ using Intersect.Configuration; using Newtonsoft.Json.Linq; -namespace Intersect.Client.Framework.Gwen.Control.Layout -{ +namespace Intersect.Client.Framework.Gwen.Control.Layout; - /// - /// Base class for multi-column tables. - /// - public partial class Table : Base, IColorableText - { - private readonly List mColumnWidths; +/// +/// Base class for multi-column tables. +/// +public partial class Table : Base, IColorableText +{ - private readonly List mColumnAlignments; + private readonly List mColumnWidths; - private int mColumnCount; + private readonly List mColumnAlignments; - private int mDefaultRowHeight; + private int mColumnCount; - private ITableDataProvider mDataProvider; + private int mDefaultRowHeight; - private int mMaxWidth; // for autosizing, if nonzero - fills last cell up to this size + private ITableDataProvider mDataProvider; - // only children of this control should be TableRow. + private int mMaxWidth; // for autosizing, if nonzero - fills last cell up to this size - private bool mSizeToContents; + // only children of this control should be TableRow. - private GameFont mFont; + private bool mSizeToContents; - private Color mTextColor; + private GameFont mFont; - private Color mTextColorOverride; + private Color mTextColor; - /// - /// Initializes a new instance of the class. - /// - /// Parent control. - public Table(Base parent, string name = default) : base(parent, name) - { - mColumnCount = 1; - mColumnAlignments = new List(ColumnCount); - mColumnWidths = new List(ColumnCount); - mDefaultRowHeight = 22; - mSizeToContents = false; - mTextColor = Color.Black; - mTextColorOverride = Color.Transparent; + private Color mTextColorOverride; - for (var i = 0; i < ColumnCount; i++) - { - mColumnWidths.Add(20); - } + /// + /// Initializes a new instance of the class. + /// + /// Parent control. + public Table(Base parent, string name = default) : base(parent, name) + { + mColumnCount = 1; + mColumnAlignments = new List(ColumnCount); + mColumnWidths = new List(ColumnCount); + mDefaultRowHeight = 22; + mSizeToContents = false; + mTextColor = Color.Black; + mTextColorOverride = Color.Transparent; + + for (var i = 0; i < ColumnCount; i++) + { + mColumnWidths.Add(20); } + } - public IReadOnlyList ColumnAlignments => mColumnAlignments.ToList(); + public IReadOnlyList ColumnAlignments => mColumnAlignments.ToList(); - /// - /// Column count (default 1). - /// - public int ColumnCount - { - get => mColumnCount; - set => SetAndDoIfChanged(ref mColumnCount, value, SetColumnCount); - } + /// + /// Column count (default 1). + /// + public int ColumnCount + { + get => mColumnCount; + set => SetAndDoIfChanged(ref mColumnCount, value, SetColumnCount); + } - public ITableDataProvider DataProvider + public ITableDataProvider DataProvider + { + get => mDataProvider; + set => SetAndDoIfChanged(ref mDataProvider, value, (oldValue, newValue) => { - get => mDataProvider; - set => SetAndDoIfChanged(ref mDataProvider, value, (oldValue, newValue) => + if (oldValue != default) { - if (oldValue != default) - { - oldValue.DataChanged -= OnDataChanged; - } + oldValue.DataChanged -= OnDataChanged; + } - if (newValue != default) - { - newValue.DataChanged += OnDataChanged; - } - }); - } + if (newValue != default) + { + newValue.DataChanged += OnDataChanged; + } + }); + } - public GameFont Font + public GameFont Font + { + get => mFont; + set => SetAndDoIfChanged(ref mFont, value, () => { - get => mFont; - set => SetAndDoIfChanged(ref mFont, value, () => + foreach (TableRow child in Children.Where(child => child is TableRow)) { - foreach (TableRow child in Children.Where(child => child is TableRow)) + if (child != default) { - if (child != default) - { - child.Font = value; - } + child.Font = value; } - }); - } + } + }); + } - /// - /// Row count. - /// - public int RowCount => Children.Count; + /// + /// Row count. + /// + public int RowCount => Children.Count; - public Color TextColor + public Color TextColor + { + get => mTextColor; + set => SetAndDoIfChanged(ref mTextColor, value, () => { - get => mTextColor; - set => SetAndDoIfChanged(ref mTextColor, value, () => + foreach (IColorableText colorableText in Children) { - foreach (IColorableText colorableText in Children) - { - colorableText.TextColor = value; - } - }); - } + colorableText.TextColor = value; + } + }); + } - public Color TextColorOverride + public Color TextColorOverride + { + get => mTextColorOverride; + set => SetAndDoIfChanged(ref mTextColorOverride, value, () => { - get => mTextColorOverride; - set => SetAndDoIfChanged(ref mTextColorOverride, value, () => + foreach (IColorableText colorableText in Children) { - foreach (IColorableText colorableText in Children) - { - colorableText.TextColorOverride = value; - } - }); - } + colorableText.TextColorOverride = value; + } + }); + } - /// - /// Gets or sets default height for new table rows. - /// - public int DefaultRowHeight + /// + /// Gets or sets default height for new table rows. + /// + public int DefaultRowHeight + { + get => mDefaultRowHeight; + set => mDefaultRowHeight = value; + } + + /// + /// Returns specific row of the table. + /// + /// Row index. + /// Row at the specified index. + public TableRow this[int index] => Children[index] as TableRow; + + protected virtual void OnDataChanged(object sender, TableDataChangedEventArgs args) + { + while (Children.Count - 1 < args.Row) { - get => mDefaultRowHeight; - set => mDefaultRowHeight = value; + _ = AddRow(); } - /// - /// Returns specific row of the table. - /// - /// Row index. - /// Row at the specified index. - public TableRow this[int index] => Children[index] as TableRow; + var row = Children[args.Row] as TableRow; + row.SetCellText(args.Column, args.NewValue?.ToString()); + } - protected virtual void OnDataChanged(object sender, TableDataChangedEventArgs args) - { - while (Children.Count - 1 < args.Row) - { - _ = AddRow(); - } + public override JObject GetJson(bool isRoot = default) + { + var obj = base.GetJson(isRoot); + obj.Add("SizeToContents", mSizeToContents); + obj.Add("DefaultRowHeight", mDefaultRowHeight); + obj.Add(nameof(ColumnAlignments), new JArray(ColumnAlignments.Select(alignment => alignment.ToString() as object).ToArray())); + obj.Add(nameof(Font), Font?.ToString()); + obj.Add(nameof(TextColor), TextColor.ToString()); + obj.Add(nameof(TextColorOverride), TextColorOverride.ToString()); + + return base.FixJson(obj); + } - var row = Children[args.Row] as TableRow; - row.SetCellText(args.Column, args.NewValue?.ToString()); + public override void LoadJson(JToken obj, bool isRoot = default) + { + base.LoadJson(obj); + if (obj[nameof(SizeToContents)] != null) + { + mSizeToContents = (bool)obj[nameof(SizeToContents)]; } - public override JObject GetJson(bool isRoot = default) + if (obj[nameof(DefaultRowHeight)] != null) { - var obj = base.GetJson(isRoot); - obj.Add("SizeToContents", mSizeToContents); - obj.Add("DefaultRowHeight", mDefaultRowHeight); - obj.Add(nameof(ColumnAlignments), new JArray(ColumnAlignments.Select(alignment => alignment.ToString() as object).ToArray())); - obj.Add(nameof(Font), Font?.ToString()); - obj.Add(nameof(TextColor), TextColor.ToString()); - obj.Add(nameof(TextColorOverride), TextColorOverride.ToString()); - - return base.FixJson(obj); + mDefaultRowHeight = (int)obj[nameof(DefaultRowHeight)]; } - public override void LoadJson(JToken obj, bool isRoot = default) + if (obj[nameof(ColumnAlignments)] != null) { - base.LoadJson(obj); - if (obj[nameof(SizeToContents)] != null) - { - mSizeToContents = (bool)obj[nameof(SizeToContents)]; - } - - if (obj[nameof(DefaultRowHeight)] != null) + var jColumnAlignments = (JArray)obj[nameof(ColumnAlignments)]; + for (var columnIndex = 0; columnIndex < Math.Min(ColumnCount, jColumnAlignments.Count); columnIndex++) { - mDefaultRowHeight = (int)obj[nameof(DefaultRowHeight)]; - } - - if (obj[nameof(ColumnAlignments)] != null) - { - var jColumnAlignments = (JArray)obj[nameof(ColumnAlignments)]; - for (var columnIndex = 0; columnIndex < Math.Min(ColumnCount, jColumnAlignments.Count); columnIndex++) + while (mColumnAlignments.Count <= columnIndex) { - while (mColumnAlignments.Count <= columnIndex) - { - mColumnAlignments.Add(default); - } - - mColumnAlignments[columnIndex] = (Pos)Enum.Parse(typeof(Pos), (string)jColumnAlignments[columnIndex]); + mColumnAlignments.Add(default); } - } - if (obj[nameof(Font)] != null) - { - var fontInfo = (string)obj[nameof(Font)]; - if (!string.IsNullOrWhiteSpace(fontInfo)) - { - var parts = fontInfo.Split(','); - var name = parts[0]; - var size = int.Parse(parts[1], CultureInfo.InvariantCulture); - Font = GameContentManager.Current?.GetFont(name, size); - } - } - - if (obj[nameof(TextColor)] != null) - { - TextColor = Color.FromString((string)obj[nameof(TextColor)]); - } - - if (obj[nameof(TextColorOverride)] != null) - { - TextColorOverride = Color.FromString((string)obj[nameof(TextColorOverride)]); + mColumnAlignments[columnIndex] = (Pos)Enum.Parse(typeof(Pos), (string)jColumnAlignments[columnIndex]); } } - /// - /// Sets the number of columns. - /// - /// Number of columns. - protected virtual void SetColumnCount() + if (obj[nameof(Font)] != null) { - while (mColumnWidths.Count < ColumnCount) + var fontInfo = (string)obj[nameof(Font)]; + if (!string.IsNullOrWhiteSpace(fontInfo)) { - mColumnWidths.Add(20); + var parts = fontInfo.Split(','); + var name = parts[0]; + var size = int.Parse(parts[1], CultureInfo.InvariantCulture); + Font = GameContentManager.Current?.GetFont(name, size); } + } - foreach (var row in Children.OfType()) - { - row.ColumnCount = Math.Min(row.ColumnCount, ColumnCount); - } + if (obj[nameof(TextColor)] != null) + { + TextColor = Color.FromString((string)obj[nameof(TextColor)]); } - /// - /// Sets the column width (in pixels). - /// - /// Column index. - /// Column width. - public void SetColumnWidth(int column, int width) + if (obj[nameof(TextColorOverride)] != null) { - if (mColumnWidths[column] == width) - { - return; - } + TextColorOverride = Color.FromString((string)obj[nameof(TextColorOverride)]); + } + } - mColumnWidths[column] = width; - Invalidate(); + /// + /// Sets the number of columns. + /// + /// Number of columns. + protected virtual void SetColumnCount() + { + while (mColumnWidths.Count < ColumnCount) + { + mColumnWidths.Add(20); } - protected virtual void SynchronizeColumnAlignments() + foreach (var row in Children.OfType()) { - InvalidateChildren(false); + row.ColumnCount = Math.Min(row.ColumnCount, ColumnCount); } + } - /// - /// Gets the column width (in pixels). - /// - /// Column index. - /// Column width. - public int GetColumnWidth(int column) + /// + /// Sets the column width (in pixels). + /// + /// Column index. + /// Column width. + public void SetColumnWidth(int column, int width) + { + if (mColumnWidths[column] == width) { - return mColumnWidths[column]; + return; } - /// - /// Adds a new empty row. - /// - /// Newly created row. - public TableRow AddRow() => AddRow(ColumnCount); + mColumnWidths[column] = width; + Invalidate(); + } + + protected virtual void SynchronizeColumnAlignments() + { + InvalidateChildren(false); + } + + /// + /// Gets the column width (in pixels). + /// + /// Column index. + /// Column width. + public int GetColumnWidth(int column) + { + return mColumnWidths[column]; + } + + /// + /// Adds a new empty row. + /// + /// Newly created row. + public TableRow AddRow() => AddRow(ColumnCount); - public TableRow AddRow(int columnCount) + public TableRow AddRow(int columnCount) + { + var row = new TableRow(this) { - var row = new TableRow(this) - { - ColumnCount = columnCount, - Dock = Pos.Top, - Font = Font, - Height = mDefaultRowHeight, - }; + ColumnCount = columnCount, + Dock = Pos.Top, + Font = Font, + Height = mDefaultRowHeight, + }; - return row; - } + return row; + } - /// - /// Adds a new row. - /// - /// Row to add. - public void AddRow(TableRow row) + /// + /// Adds a new row. + /// + /// Row to add. + public void AddRow(TableRow row) + { + if (row == default) { - if (row == default) - { - throw new ArgumentNullException(nameof(row)); - } + throw new ArgumentNullException(nameof(row)); + } - row.Parent = this; + row.Parent = this; - row.ColumnCount = Math.Min(mColumnCount, row.ColumnCount); - row.Dock = Pos.Top; - row.Font = row.Font ?? Font; - row.Height = mDefaultRowHeight; + row.ColumnCount = Math.Min(mColumnCount, row.ColumnCount); + row.Dock = Pos.Top; + row.Font = row.Font ?? Font; + row.Height = mDefaultRowHeight; - row.SetColumnWidths(mColumnWidths); - } + row.SetColumnWidths(mColumnWidths); + } - /// - /// Adds a new row with specified text in first column. - /// - /// Text to add. - /// New row. - public TableRow AddRow(string text) - { - var row = AddRow(); - row.SetCellText(0, text); + /// + /// Adds a new row with specified text in first column. + /// + /// Text to add. + /// New row. + public TableRow AddRow(string text) + { + var row = AddRow(); + row.SetCellText(0, text); - return row; - } + return row; + } - public TableRow AddRow(string text, int columnCount) - { - var row = AddRow(columnCount); - row.SetCellText(0, text); + public TableRow AddRow(string text, int columnCount) + { + var row = AddRow(columnCount); + row.SetCellText(0, text); - return row; - } + return row; + } - /// - /// Removes a row by reference. - /// - /// Row to remove. - public void RemoveRow(TableRow row) - { - RemoveChild(row, true); - } + /// + /// Removes a row by reference. + /// + /// Row to remove. + public void RemoveRow(TableRow row) + { + RemoveChild(row, true); + } + + /// + /// Removes a row by index. + /// + /// Row index. + public void RemoveRow(int idx) + { + var row = Children[idx]; + RemoveRow(row as TableRow); + } - /// - /// Removes a row by index. - /// - /// Row index. - public void RemoveRow(int idx) + /// + /// Removes all rows. + /// + public void RemoveAll() + { + while (RowCount > 0) { - var row = Children[idx]; - RemoveRow(row as TableRow); + RemoveRow(0); } + DoSizeToContents(); + } - /// - /// Removes all rows. - /// - public void RemoveAll() + /// + /// Gets the index of a specified row. + /// + /// Row to search for. + /// Row index if found, -1 otherwise. + public int GetRowIndex(TableRow row) + { + return Children.IndexOf(row); + } + + /// + /// Lays out the control's interior according to alignment, padding, dock etc. + /// + /// Skin to use. + protected override void Layout(Skin.Base skin) + { + base.Layout(skin); + + if (mSizeToContents) { - while (RowCount > 0) - { - RemoveRow(0); - } DoSizeToContents(); + mSizeToContents = false; } - - /// - /// Gets the index of a specified row. - /// - /// Row to search for. - /// Row index if found, -1 otherwise. - public int GetRowIndex(TableRow row) + else { - return Children.IndexOf(row); + ComputeColumnWidths(); } - /// - /// Lays out the control's interior according to alignment, padding, dock etc. - /// - /// Skin to use. - protected override void Layout(Skin.Base skin) + var even = false; + foreach (TableRow row in Children) { - base.Layout(skin); + row.EvenRow = even; + even = ClientConfiguration.Instance.EnableZebraStripedRows && !even; - if (mSizeToContents) - { - DoSizeToContents(); - mSizeToContents = false; - } - else - { - ComputeColumnWidths(); - } - - var even = false; - foreach (TableRow row in Children) - { - row.EvenRow = even; - even = ClientConfiguration.Instance.EnableZebraStripedRows && !even; - - row.SetColumnWidths(mColumnWidths); - } + row.SetColumnWidths(mColumnWidths); } + } - protected override void PostLayout(Skin.Base skin) - { - base.PostLayout(skin); - } + protected override void PostLayout(Skin.Base skin) + { + base.PostLayout(skin); + } - /// - /// Sizes to fit contents. - /// - public void SizeToContents(int maxWidth) - { - mMaxWidth = maxWidth; - mSizeToContents = true; - Invalidate(); - } + /// + /// Sizes to fit contents. + /// + public void SizeToContents(int maxWidth) + { + mMaxWidth = maxWidth; + mSizeToContents = true; + Invalidate(); + } + + protected virtual (int width, int height) ComputeColumnWidths() + { + var height = 0; + var width = 0; - protected virtual (int width, int height) ComputeColumnWidths() + foreach (TableRow row in Children) { - var height = 0; - var width = 0; + row.SizeToContents(); // now all columns fit but only in this particular row - foreach (TableRow row in Children) + for (var i = 0; i < ColumnCount; i++) { - row.SizeToContents(); // now all columns fit but only in this particular row - - for (var i = 0; i < ColumnCount; i++) + Base cell = row.GetColumn(i); + if (null != cell && row.ColumnCount == ColumnCount) { - Base cell = row.GetColumn(i); - if (null != cell && row.ColumnCount == ColumnCount) + if (i < ColumnCount - 1 || mMaxWidth == 0) { - if (i < ColumnCount - 1 || mMaxWidth == 0) - { - mColumnWidths[i] = Math.Max( - mColumnWidths[i], cell.Width + cell.Margin.Left + cell.Margin.Right - ); - } - else - { - mColumnWidths[i] = mMaxWidth - width; // last cell - fill - } + mColumnWidths[i] = Math.Max( + mColumnWidths[i], cell.Width + cell.Margin.Left + cell.Margin.Right + ); + } + else + { + mColumnWidths[i] = mMaxWidth - width; // last cell - fill } } - - height += row.Height; } - // sum all column widths - width += mColumnWidths.Take(ColumnCount).Sum(); - - return (width, height); + height += row.Height; } - public void DoSizeToContents() - { - var (width, height) = ComputeColumnWidths(); + // sum all column widths + width += mColumnWidths.Take(ColumnCount).Sum(); - SetSize(width, height); + return (width, height); + } - //InvalidateParent(); - } + public void DoSizeToContents() + { + var (width, height) = ComputeColumnWidths(); - public override void Invalidate() - { - base.Invalidate(); - InvalidateChildren(true); - } + SetSize(width, height); + //InvalidateParent(); + } + + public override void Invalidate() + { + base.Invalidate(); + InvalidateChildren(true); } } diff --git a/Intersect.Client.Framework/Gwen/Control/Layout/TableRow.cs b/Intersect.Client.Framework/Gwen/Control/Layout/TableRow.cs index 7da1193493..1eb31c2539 100644 --- a/Intersect.Client.Framework/Gwen/Control/Layout/TableRow.cs +++ b/Intersect.Client.Framework/Gwen/Control/Layout/TableRow.cs @@ -2,517 +2,516 @@ using Intersect.Client.Framework.Gwen.Control.Data; using Intersect.Client.Framework.Gwen.Control.EventArguments; -namespace Intersect.Client.Framework.Gwen.Control.Layout -{ +namespace Intersect.Client.Framework.Gwen.Control.Layout; - /// - /// Single table row. - /// - public partial class TableRow : Base, IColorableText - { - private readonly List mDisposalActions; - private readonly List