| | 1 | | using PropertyGridHelpers.Attributes; |
| | 2 | | using PropertyGridHelpers.Enums; |
| | 3 | | using System; |
| | 4 | | using System.ComponentModel; |
| | 5 | | using System.Drawing; |
| | 6 | | using System.Drawing.Design; |
| | 7 | | using System.Drawing.Drawing2D; |
| | 8 | | using System.Globalization; |
| | 9 | | using System.IO; |
| | 10 | | using System.Linq; |
| | 11 | | using System.Resources; |
| | 12 | |
|
| | 13 | | namespace PropertyGridHelpers.UIEditors |
| | 14 | | { |
| | 15 | | /// <summary> |
| | 16 | | /// Provides a <see cref="UITypeEditor"/> for editing enumeration values that have associated images. |
| | 17 | | /// </summary> |
| | 18 | | /// <remarks> |
| | 19 | | /// This editor is designed to display an enumeration in a UI with each value optionally associated with an image. |
| | 20 | | /// The editor can be customized to include additional functionality or presentation enhancements. |
| | 21 | | /// </remarks> |
| | 22 | | /// <example> |
| | 23 | | /// To use this editor, apply the <see cref="ImageTextUIEditor"/> to an enum property: |
| | 24 | | /// <code> |
| | 25 | | /// [Editor(typeof(ImageTextUIEditor), typeof(UITypeEditor))] |
| | 26 | | /// public TestEnum EnumWithImages { get; set; } |
| | 27 | | /// </code> |
| | 28 | | /// Ensure that the enum has descriptions or resources set up using the <see cref="EnumImageAttribute"/> to provide |
| | 29 | | /// </example> |
| | 30 | | /// <seealso cref="UITypeEditor" /> |
| | 31 | | public partial class ImageTextUIEditor : UITypeEditor, IDisposable |
| | 32 | | { |
| | 33 | | #region Fields ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| | 34 | |
|
| | 35 | | /// <summary> |
| | 36 | | /// The object is disposed |
| | 37 | | /// </summary> |
| | 38 | | private bool disposedValue; |
| | 39 | |
|
| | 40 | | /// <summary> |
| | 41 | | /// The enum type |
| | 42 | | /// </summary> |
| | 43 | | protected Type EnumType |
| | 44 | | { |
| 56 | 45 | | get; |
| | 46 | | } |
| | 47 | |
|
| | 48 | | /// <summary> |
| | 49 | | /// The path to the resources where the images are stored |
| | 50 | | /// </summary> |
| | 51 | | protected string ResourcePath |
| | 52 | | { |
| 116 | 53 | | get; private set; |
| | 54 | | } |
| | 55 | |
|
| | 56 | | /// <summary> |
| | 57 | | /// Gets the file extension. |
| | 58 | | /// </summary> |
| | 59 | | /// <value> |
| | 60 | | /// The file extension. |
| | 61 | | /// </value> |
| | 62 | | protected string FileExtension |
| | 63 | | { |
| 44 | 64 | | get; private set; |
| | 65 | | } |
| | 66 | |
|
| | 67 | | #endregion |
| | 68 | |
|
| | 69 | | #region Constructors ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| | 70 | |
|
| | 71 | | /// <summary> |
| | 72 | | /// Initializes a new instance of the <see cref="ImageTextUIEditor"/> class. |
| | 73 | | /// </summary> |
| | 74 | | /// <param name="type">Type of enum that is used in the process</param> |
| 32 | 75 | | public ImageTextUIEditor(Type type) |
| 24 | 76 | | { |
| 32 | 77 | | EnumType = type; |
| 32 | 78 | | ResourcePath = Support.Support.GetResourcePath(null, type, ResourceUsage.Images); |
| 32 | 79 | | } |
| | 80 | |
|
| | 81 | | /// <summary> |
| | 82 | | /// Initializes a new instance of the <see cref="ImageTextUIEditor"/> class. |
| | 83 | | /// </summary> |
| | 84 | | /// <param name="type">Type of enum that is used in the process</param> |
| | 85 | | /// <param name="ResourcePath">The path to the resources where the images are stored</param> |
| 64 | 86 | | public ImageTextUIEditor(Type type, string ResourcePath) |
| 56 | 87 | | { |
| 64 | 88 | | EnumType = type; |
| 64 | 89 | | this.ResourcePath = ResourcePath; |
| 64 | 90 | | } |
| | 91 | |
|
| | 92 | | #endregion |
| | 93 | |
|
| | 94 | | #region PaintValue Routines ^^^^^^^^^^^^^^^^^^^^^^^ |
| | 95 | |
|
| | 96 | | /// <summary> |
| | 97 | | /// return that the editor will paint the items in the drop-down |
| | 98 | | /// </summary> |
| | 99 | | /// <param name="context">The Type Descriptor Context</param> |
| | 100 | | public override bool GetPaintValueSupported(ITypeDescriptorContext context) |
| 12 | 101 | | { |
| 20 | 102 | | ResourcePath = Support.Support.GetResourcePath(context, EnumType, ResourceUsage.Images); |
| 20 | 103 | | FileExtension = Support.Support.GetFileExtension(context); |
| 20 | 104 | | return true; |
| 12 | 105 | | } |
| | 106 | |
|
| | 107 | | /// <summary> |
| | 108 | | /// Paint the value in the drop-down list |
| | 109 | | /// </summary> |
| | 110 | | /// <param name="e">Paint Value Event Arguments</param> |
| | 111 | | public override void PaintValue(PaintValueEventArgs e) |
| 52 | 112 | | { |
| | 113 | | #if NET5_0_OR_GREATER |
| 44 | 114 | | ArgumentNullException.ThrowIfNull(e); |
| | 115 | | #else |
| 16 | 116 | | if (e is null) throw new ArgumentNullException(nameof(e)); |
| | 117 | | #endif |
| 56 | 118 | | var newImage = GetImageFromResource(e.Value, EnumType, ResourcePath, FileExtension, e.Bounds); |
| 48 | 119 | | if (newImage != null) |
| 44 | 120 | | e.Graphics.DrawImage(newImage, e.Bounds); |
| 48 | 121 | | } |
| | 122 | |
|
| | 123 | | #endregion |
| | 124 | |
|
| | 125 | | #region Static Methods ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| | 126 | |
|
| | 127 | | /// <summary> |
| | 128 | | /// Gets the image from resource. |
| | 129 | | /// </summary> |
| | 130 | | /// <param name="Value">The value.</param> |
| | 131 | | /// <param name="enumType">Type of the enum.</param> |
| | 132 | | /// <param name="ResourcePath">The resource path.</param> |
| | 133 | | /// <param name="fileExtension"></param> |
| | 134 | | /// <returns></returns> |
| | 135 | | /// <exception cref="System.InvalidOperationException">Resource file '{ResourceName}.resources' not found in ass |
| | 136 | | /// $"Available resources: {string.Join(", ", resourceNames)} |
| | 137 | | /// or |
| | 138 | | /// Resource {enumImage} is not a valid image or byte array.</exception> |
| | 139 | | /// <exception cref="InvalidOperationException">Resource file not found in the assembly. |
| | 140 | | /// or |
| | 141 | | /// Resource is not a valid image or byte array.</exception> |
| | 142 | | /// <param name="bounds">The bounds of the generated image.</param> |
| | 143 | | public static Bitmap GetImageFromResource( |
| | 144 | | object Value, |
| | 145 | | Type enumType, |
| | 146 | | string ResourcePath, |
| | 147 | | string fileExtension, |
| | 148 | | Rectangle bounds) |
| 64 | 149 | | { |
| | 150 | | #if NET5_0_OR_GREATER |
| 56 | 151 | | ArgumentNullException.ThrowIfNull(Value); |
| 52 | 152 | | ArgumentNullException.ThrowIfNull(enumType); |
| | 153 | | #else |
| 16 | 154 | | if (Value is null) throw new ArgumentNullException(nameof(Value)); |
| 16 | 155 | | if (enumType is null) throw new ArgumentNullException(nameof(enumType)); |
| | 156 | | #endif |
| | 157 | | // get the EnumImageAttribute for the field |
| 64 | 158 | | var dna = EnumImageAttribute.Get((Enum)Value); |
| | 159 | |
|
| 64 | 160 | | if (dna != null) |
| 52 | 161 | | { |
| 60 | 162 | | var m = GetModuleName(Value); |
| 60 | 163 | | var ei = EnumImageAttribute.GetEnumImage((Enum)Value); |
| 60 | 164 | | Bitmap originalImage = null; |
| | 165 | | string ResourceName; |
| 60 | 166 | | switch (dna.ImageLocation) |
| | 167 | | { |
| | 168 | | case ImageLocation.Embedded: |
| 28 | 169 | | ResourceName = $"{m}{(string.IsNullOrEmpty(ResourcePath) ? "" : $".{ResourcePath}")}"; |
| 28 | 170 | | originalImage = GetImageFromEmbeddedResource(Value, ei, ResourceName, fileExtension); |
| 28 | 171 | | break; |
| | 172 | | case ImageLocation.Resource: |
| | 173 | | // Create a resource manager to access the resources |
| 44 | 174 | | ResourceName = $"{m}{(string.IsNullOrEmpty(ResourcePath) ? "" : $".{ResourcePath}")}"; |
| 44 | 175 | | originalImage = GetImageFromResourceFile(Value, ei, ResourceName, fileExtension, LicenseManager. |
| 36 | 176 | | break; |
| | 177 | | case ImageLocation.File: |
| 20 | 178 | | originalImage = GetImageFromFile(Value, ei, ResourcePath, fileExtension); |
| 12 | 179 | | break; |
| | 180 | | } |
| | 181 | |
|
| 56 | 182 | | if (originalImage == null) return null; |
| | 183 | |
|
| | 184 | | // Create a new bitmap for the scaled image |
| 48 | 185 | | var scaledImage = new Bitmap(bounds.Width, bounds.Height); |
| | 186 | |
|
| 48 | 187 | | using (var g = Graphics.FromImage(scaledImage)) |
| 40 | 188 | | { |
| 48 | 189 | | g.Clear(Color.Transparent); // Optional: set background to transparent |
| 48 | 190 | | g.InterpolationMode = InterpolationMode.HighQualityBicubic; |
| | 191 | |
|
| 48 | 192 | | var ts = GetTargetSizes(originalImage, bounds); |
| | 193 | |
|
| | 194 | | // Draw the scaled image centered in the bounds |
| 48 | 195 | | g.DrawImage(originalImage, ts.OffsetX, ts.OffsetY, ts.TargetWidth, ts.TargetHeight); |
| 48 | 196 | | } |
| | 197 | |
|
| 48 | 198 | | return scaledImage; |
| | 199 | | } |
| | 200 | |
|
| 20 | 201 | | return null; |
| 48 | 202 | | } |
| | 203 | |
|
| | 204 | | /// <summary> |
| | 205 | | /// Gets the image from embedded resource. |
| | 206 | | /// </summary> |
| | 207 | | /// <param name="Value">The value.</param> |
| | 208 | | /// <param name="ResourceItem">The resource entry to retrieve.</param> |
| | 209 | | /// <param name="ResourcePath">Name of the resource.</param> |
| | 210 | | /// <param name="fileExtension">The file extension.</param> |
| | 211 | | /// <returns></returns> |
| | 212 | | /// <exception cref="System.ArgumentNullException">Value</exception> |
| | 213 | | /// <exception cref="System.ArgumentException">'{nameof(enumImage)}' cannot be null or empty. - enumImage |
| | 214 | | /// or |
| | 215 | | /// '{nameof(ResourceName)}' cannot be null or empty. - ResourceName</exception> |
| | 216 | | public static Bitmap GetImageFromEmbeddedResource( |
| | 217 | | object Value, |
| | 218 | | string ResourceItem, |
| | 219 | | string ResourcePath, |
| | 220 | | string fileExtension) |
| 36 | 221 | | { |
| | 222 | | #if NET5_0_OR_GREATER |
| 28 | 223 | | ArgumentNullException.ThrowIfNull(Value); |
| | 224 | | #else |
| 16 | 225 | | if (Value is null) throw new ArgumentNullException(nameof(Value)); |
| | 226 | | #endif |
| 44 | 227 | | if (string.IsNullOrEmpty(ResourceItem)) throw new ArgumentException($"'{nameof(ResourceItem)}' cannot be nul |
| 40 | 228 | | if (string.IsNullOrEmpty(ResourcePath)) throw new ArgumentException($"'{nameof(ResourcePath)}' cannot be nul |
| 32 | 229 | | ResourcePath = $"{ResourcePath}.{ResourceItem}"; |
| 32 | 230 | | if (!string.IsNullOrEmpty(fileExtension)) |
| 20 | 231 | | ResourcePath = $"{ResourcePath}.{fileExtension}"; |
| | 232 | |
|
| 32 | 233 | | Bitmap newImage = null; |
| | 234 | |
|
| 32 | 235 | | using (var stream = Value.GetType().Assembly.GetManifestResourceStream(ResourcePath)) |
| | 236 | | #if NET5_0_OR_GREATER |
| 16 | 237 | | if (stream is not null) |
| | 238 | | #else |
| 16 | 239 | | if (!(stream is null)) |
| | 240 | | #endif |
| 32 | 241 | | newImage = (Bitmap)Image.FromStream(stream); |
| | 242 | |
|
| 32 | 243 | | return newImage; |
| 24 | 244 | | } |
| | 245 | |
|
| | 246 | | /// <summary> |
| | 247 | | /// Gets the image from resource file. |
| | 248 | | /// </summary> |
| | 249 | | /// <param name="Value">The value.</param> |
| | 250 | | /// <param name="ResourceItem">The resource entry to retrieve.</param> |
| | 251 | | /// <param name="ResourcePath">Name of the resource.</param> |
| | 252 | | /// <param name="fileExtension">The file extension.</param> |
| | 253 | | /// <param name="IsInDesignMode">if set to <c>true</c> is in design mode.</param> |
| | 254 | | /// <returns></returns> |
| | 255 | | /// <exception cref="System.ArgumentNullException">Value</exception> |
| | 256 | | /// <exception cref="System.ArgumentException">'{nameof(ResourceItem)}' cannot be null or empty. - ResourceItem |
| | 257 | | /// or |
| | 258 | | /// '{nameof(ResourcePath)}' cannot be null or empty. - ResourcePath</exception> |
| | 259 | | /// <exception cref="System.InvalidOperationException">Resource file '{ResourcePath}.resources' not found in ass |
| | 260 | | /// $"Available resources: {string.Join(", ", resourceNames)} |
| | 261 | | /// or |
| | 262 | | /// Error retrieving resource '{ResourceItem}{(string.IsNullOrEmpty(fileExtension) ? "" : $".{fileExtension}")}' |
| | 263 | | /// or |
| | 264 | | /// Resource '{ResourcePath}.resources.{ResourceItem}' is not a valid image or byte array.</exception> |
| | 265 | | /// <exception cref="ArgumentNullException">Value</exception> |
| | 266 | | /// <exception cref="ArgumentException">'{nameof(ResourceItem)}' cannot be null or empty. - ResourceItem |
| | 267 | | /// or |
| | 268 | | /// '{nameof(ResourcePath)}' cannot be null or empty. - ResourcePath</exception> |
| | 269 | | /// <exception cref="InvalidOperationException">Resource file '{ResourcePath}.resources' not found in assembly ' |
| | 270 | | /// $"Available resources: {string.Join(", ", resourceNames)} |
| | 271 | | /// or |
| | 272 | | /// Resource '{ResourcePath}.resources.{ResourceItem}' is not a valid image or byte array.</exception> |
| | 273 | | /// <exception cref="InvalidOperationException">Resource file '{ResourcePath}.resources' not found in assembly ' |
| | 274 | | /// $"Available resources: {string.Join(", ", resourceNames)} |
| | 275 | | /// or |
| | 276 | | /// Resource '{ResourcePath}.resources.{ResourceItem}' is not a valid image or byte array.</exception> |
| | 277 | | public static Bitmap GetImageFromResourceFile( |
| | 278 | | object Value, |
| | 279 | | string ResourceItem, |
| | 280 | | string ResourcePath, |
| | 281 | | string fileExtension, |
| | 282 | | bool IsInDesignMode) |
| 68 | 283 | | { |
| | 284 | | #if NET5_0_OR_GREATER |
| 60 | 285 | | ArgumentNullException.ThrowIfNull(Value); |
| | 286 | | #else |
| 16 | 287 | | if (Value is null) throw new ArgumentNullException(nameof(Value)); |
| | 288 | | #endif |
| 76 | 289 | | if (string.IsNullOrEmpty(ResourceItem)) throw new ArgumentException($"'{nameof(ResourceItem)}' cannot be nul |
| 72 | 290 | | if (string.IsNullOrEmpty(ResourcePath)) throw new ArgumentException($"'{nameof(ResourcePath)}' cannot be nul |
| | 291 | |
|
| | 292 | | // Check if the resource file exists in the assembly |
| 64 | 293 | | var resourceNames = Value.GetType().Assembly.GetManifestResourceNames(); |
| 168 | 294 | | if (!resourceNames.Any(r => r.EndsWith($"{ResourcePath}.resources", StringComparison.CurrentCulture))) |
| 12 | 295 | | { |
| 20 | 296 | | var m = GetModuleName(Value); |
| 20 | 297 | | throw new InvalidOperationException( |
| 20 | 298 | | $"Resource file '{ResourcePath}.resources' not found in assembly '{m}'. \n" + |
| 20 | 299 | | $"Available resources: {string.Join(", ", resourceNames)}"); |
| | 300 | | } |
| | 301 | |
|
| | 302 | | object resource; |
| | 303 | |
|
| | 304 | | // Get the resource object |
| | 305 | | try |
| 52 | 306 | | { |
| 60 | 307 | | if (IsInDesignMode) |
| 16 | 308 | | { |
| | 309 | | // If in design mode, use the ResourceManager to get the resource |
| 24 | 310 | | var rm = new ComponentResourceManager(Value.GetType()); |
| 24 | 311 | | resource = rm.GetObject($"{ResourceItem}{(string.IsNullOrEmpty(fileExtension) ? "" : $".{fileExtensi |
| 16 | 312 | | } |
| | 313 | | else |
| 44 | 314 | | { |
| | 315 | | // If in runtime, use the ResourceManager to get the resource |
| 52 | 316 | | var rm = new ResourceManager(ResourcePath, Value.GetType().Assembly); |
| 52 | 317 | | resource = rm.GetObject($"{ResourceItem}{(string.IsNullOrEmpty(fileExtension) ? "" : $".{fileExtensi |
| 36 | 318 | | } |
| 52 | 319 | | } |
| 24 | 320 | | catch (Exception ex) |
| 16 | 321 | | { |
| 24 | 322 | | throw new InvalidOperationException($"Error retrieving resource '{ResourceItem}{(string.IsNullOrEmpty(fi |
| | 323 | | } |
| | 324 | |
|
| 52 | 325 | | Bitmap newImage = null; |
| 52 | 326 | | if (resource != null) |
| 40 | 327 | | { |
| 48 | 328 | | if (resource is Bitmap bitmap) |
| | 329 | | // If the resource is a Bitmap, use it directly |
| 28 | 330 | | newImage = bitmap; |
| 36 | 331 | | else if (resource is byte[] byteArray) |
| | 332 | | // If the resource is a byte array, convert it to an image |
| 32 | 333 | | using (var ms = new MemoryStream(byteArray)) |
| 32 | 334 | | newImage = new Bitmap(ms); |
| | 335 | | else |
| 20 | 336 | | throw new InvalidOperationException($"Resource '{ResourcePath}.resources.{ResourceItem}' is not a va |
| 36 | 337 | | } |
| | 338 | |
|
| 48 | 339 | | return newImage; |
| 40 | 340 | | } |
| | 341 | |
|
| | 342 | | /// <summary> |
| | 343 | | /// Gets the image from file. |
| | 344 | | /// </summary> |
| | 345 | | /// <param name="Value">The value.</param> |
| | 346 | | /// <param name="ResourceItem">The resource entry to retrieve.</param> |
| | 347 | | /// <param name="ResourcePath">The resource path.</param> |
| | 348 | | /// <param name="fileExtension">The file extension.</param> |
| | 349 | | /// <returns></returns> |
| | 350 | | /// <exception cref="System.ArgumentNullException">Value</exception> |
| | 351 | | /// <exception cref="System.ArgumentException"> |
| | 352 | | /// '{nameof(ResourceItem)}' cannot be null or empty. - ResourceItem |
| | 353 | | /// or |
| | 354 | | /// '{nameof(ResourcePath)}' cannot be null or empty. - ResourcePath |
| | 355 | | /// </exception> |
| | 356 | | /// <exception cref="ArgumentNullException">Value</exception> |
| | 357 | | /// <exception cref="ArgumentException">'{nameof(ResourceItem)}' cannot be null or empty. - ResourceItem |
| | 358 | | /// or |
| | 359 | | /// '{nameof(ResourcePath)}' cannot be null or empty. - ResourcePath</exception> |
| | 360 | | public static Bitmap GetImageFromFile( |
| | 361 | | object Value, |
| | 362 | | string ResourceItem, |
| | 363 | | string ResourcePath, |
| | 364 | | string fileExtension) |
| 32 | 365 | | { |
| | 366 | | #if NET5_0_OR_GREATER |
| 24 | 367 | | ArgumentNullException.ThrowIfNull(Value); |
| | 368 | | #else |
| 16 | 369 | | if (Value is null) throw new ArgumentNullException(nameof(Value)); |
| | 370 | | #endif |
| 40 | 371 | | if (string.IsNullOrEmpty(ResourceItem)) throw new ArgumentException($"'{nameof(ResourceItem)}' cannot be nul |
| 36 | 372 | | if (string.IsNullOrEmpty(ResourcePath)) throw new ArgumentException($"'{nameof(ResourcePath)}' cannot be nul |
| | 373 | | string assemblyPath; |
| | 374 | | // Get the directory of the assembly containing _enumType |
| | 375 | | #pragma warning disable SYSLIB0012 // The class is obsolete |
| 28 | 376 | | var uri = new UriBuilder(Value.GetType().Assembly.CodeBase); |
| | 377 | | #pragma warning restore SYSLIB0012 // The class is obsolete |
| 28 | 378 | | assemblyPath = Path.GetDirectoryName(Uri.UnescapeDataString(uri.Path)); |
| | 379 | | // Construct the full file path |
| 28 | 380 | | if (!string.IsNullOrEmpty(ResourcePath)) |
| 28 | 381 | | assemblyPath = Path.Combine(assemblyPath, ResourcePath); |
| 28 | 382 | | if (!string.IsNullOrEmpty(fileExtension)) |
| 20 | 383 | | ResourceItem = $"{ResourceItem}.{fileExtension}"; |
| 28 | 384 | | var ResourceName = Path.Combine(assemblyPath, ResourceItem); |
| | 385 | |
|
| | 386 | | // Load the image from the file path |
| 28 | 387 | | var newImage = new Bitmap(ResourceName); |
| | 388 | |
|
| 28 | 389 | | return newImage; |
| 20 | 390 | | } |
| | 391 | |
|
| | 392 | | /// <summary> |
| | 393 | | /// Gets the name of the module. |
| | 394 | | /// </summary> |
| | 395 | | /// <param name="Value">The value.</param> |
| | 396 | | /// <returns></returns> |
| | 397 | | public static string GetModuleName(object Value) |
| 56 | 398 | | { |
| | 399 | | // Get the name of the DLL or EXE where the reference object is declared |
| 64 | 400 | | var m = Value.GetType().Module.Name; |
| | 401 | | // Remove the file extension from the name |
| | 402 | | #if NET5_0_OR_GREATER |
| 48 | 403 | | m = m[0..^4]; |
| | 404 | | #else |
| 16 | 405 | | m = m.Substring(0, m.Length - 4); |
| | 406 | | #endif |
| 64 | 407 | | return m; |
| 56 | 408 | | } |
| | 409 | |
|
| | 410 | | /// <summary> |
| | 411 | | /// Gets the target sizes. |
| | 412 | | /// </summary> |
| | 413 | | /// <param name="originalImage">The original image.</param> |
| | 414 | | /// <param name="bounds">The bounds.</param> |
| | 415 | | /// <returns></returns> |
| | 416 | | public static TargetSizes GetTargetSizes( |
| | 417 | | Bitmap originalImage, |
| | 418 | | Rectangle bounds) |
| 48 | 419 | | { |
| 56 | 420 | | var ts = new TargetSizes(); |
| 56 | 421 | | var aspectRatio = (double)originalImage.Width / originalImage.Height; |
| | 422 | |
|
| 56 | 423 | | if (bounds.Width / (double)bounds.Height > aspectRatio) |
| 12 | 424 | | { |
| 20 | 425 | | ts.TargetHeight = bounds.Height; |
| 20 | 426 | | ts.TargetWidth = (int)(ts.TargetHeight * aspectRatio); |
| 12 | 427 | | } |
| | 428 | | else |
| 44 | 429 | | { |
| 52 | 430 | | ts.TargetWidth = bounds.Width; |
| 52 | 431 | | ts.TargetHeight = (int)(ts.TargetWidth / aspectRatio); |
| 44 | 432 | | } |
| | 433 | |
|
| 56 | 434 | | ts.OffsetX = (bounds.Width - ts.TargetWidth) / 2; |
| 56 | 435 | | ts.OffsetY = (bounds.Height - ts.TargetHeight) / 2; |
| 56 | 436 | | return ts; |
| 48 | 437 | | } |
| | 438 | |
|
| | 439 | | /// <summary> |
| | 440 | | /// Target sizes for the image |
| | 441 | | /// </summary> |
| | 442 | | public struct TargetSizes |
| | 443 | | { |
| | 444 | | /// <summary> |
| | 445 | | /// The target width |
| | 446 | | /// </summary> |
| | 447 | | public int TargetWidth; |
| | 448 | | /// <summary> |
| | 449 | | /// The target height |
| | 450 | | /// </summary> |
| | 451 | | public int TargetHeight; |
| | 452 | | /// <summary> |
| | 453 | | /// The offset x |
| | 454 | | /// </summary> |
| | 455 | | public int OffsetX; |
| | 456 | | /// <summary> |
| | 457 | | /// The offset y |
| | 458 | | /// </summary> |
| | 459 | | public int OffsetY; |
| | 460 | | } |
| | 461 | |
|
| | 462 | | #endregion |
| | 463 | |
|
| | 464 | | #region Disposal routines ^^^^^^^^^^^^^^^^^^^^^^^^^ |
| | 465 | |
|
| | 466 | | /// <summary> |
| | 467 | | /// Releases unmanaged and - optionally - managed resources. |
| | 468 | | /// </summary> |
| | 469 | | /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release |
| | 470 | | protected virtual void Dispose(bool disposing) |
| 12 | 471 | | { |
| 20 | 472 | | if (!disposedValue) |
| 12 | 473 | | { |
| 20 | 474 | | if (disposing) |
| 12 | 475 | | { |
| 12 | 476 | | } |
| | 477 | |
|
| 20 | 478 | | disposedValue = true; |
| 12 | 479 | | } |
| 20 | 480 | | } |
| | 481 | |
|
| | 482 | | // // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources |
| | 483 | | // ~FlagEnumUIEditor() |
| | 484 | | // { |
| | 485 | | // // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method |
| | 486 | | // Dispose(disposing: false); |
| | 487 | | // } |
| | 488 | |
|
| | 489 | | /// <summary> |
| | 490 | | /// Releases unmanaged and - optionally - managed resources. |
| | 491 | | /// </summary> |
| | 492 | | public void Dispose() |
| 12 | 493 | | { |
| | 494 | | // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method |
| 20 | 495 | | Dispose(disposing: true); |
| 20 | 496 | | GC.SuppressFinalize(this); |
| 20 | 497 | | } |
| | 498 | |
|
| | 499 | | #endregion |
| | 500 | | } |
| | 501 | | } |