├── ClaudiaIDE
├── Images
│ └── .gitkeep
├── Localized
│ └── .gitkeep
├── GuidList.cs
├── Properties
│ └── AssemblyInfo.cs
├── source.extension.vsixmanifest
├── ClaudiaIDE.csproj
└── Resources
│ ├── ClaudiaIdePackage.zh-CN.vsct
│ └── ClaudiaIdePackage.ja-JP.vsct
├── ClaudiaIDE16
├── Images
│ └── .gitkeep
├── Localized
│ └── .gitkeep
├── GuidList.cs
├── Properties
│ └── AssemblyInfo.cs
├── source.extension.vsixmanifest
├── ClaudiaIDE16.csproj
└── Resources
│ ├── ClaudiaIdePackage.zh-CN.vsct
│ └── ClaudiaIdePackage.ja-JP.vsct
├── Images
├── tile01.png
├── tile02.png
├── tile03.png
├── tile04.png
├── howto01.png
├── howto02.png
├── howto03.png
├── howto04.png
├── example01.png
├── workaround01.png
└── config-per-solution.png
├── .github
└── FUNDING.yml
├── Shared
├── Resources
│ ├── 400.ico
│ ├── ss.png
│ ├── vsixicon.png
│ └── ClaudiaIDEMenu.png
├── Images
│ ├── background.png
│ └── background2.png
├── Interfaces
│ ├── ISkipable.cs
│ └── IPausable.cs
├── Helpers
│ ├── AnimateImageChangeParams.cs
│ ├── ResourceExtension.cs
│ ├── DependencyObjectExtensions.cs
│ ├── PausableTimer.cs
│ ├── ImageDownloader.cs
│ ├── ImageSourceAnimator.cs
│ └── Utils.cs
├── GlobalSuppressions.cs
├── Shared.shproj
├── Settings
│ ├── JsonSerializer.cs
│ └── WeakEvent.cs
├── config.txt
├── ImageProviders
│ ├── SingleImageWebProvider.cs
│ ├── SingleImageProvider.cs
│ ├── WebApiImageProvider.cs
│ ├── SingleImageEachProvider.cs
│ └── SlideShowImageProvider.cs
├── Extensions.cs
├── Localized
│ └── LocalManager.cs
├── MenuCommands
│ ├── ToggleHiddenImage.cs
│ ├── OpenSettings.cs
│ ├── ResetSolutionSettings.cs
│ ├── AboutImage.cs
│ ├── SaveSolutionSettings.cs
│ ├── NextImage.cs
│ └── PauseSlideshow.cs
├── Shared.projitems
├── ImageProvider.cs
├── VSPackage.Designer.cs
├── ClaudiaIDEFactory.cs
└── VSPackage.resx
├── .editorconfig
├── .gitignore
├── ClaudiaIDE.sln
└── README.md
/ClaudiaIDE/Images/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ClaudiaIDE16/Images/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ClaudiaIDE/Localized/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ClaudiaIDE16/Localized/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Images/tile01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/buchizo/ClaudiaIDE/HEAD/Images/tile01.png
--------------------------------------------------------------------------------
/Images/tile02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/buchizo/ClaudiaIDE/HEAD/Images/tile02.png
--------------------------------------------------------------------------------
/Images/tile03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/buchizo/ClaudiaIDE/HEAD/Images/tile03.png
--------------------------------------------------------------------------------
/Images/tile04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/buchizo/ClaudiaIDE/HEAD/Images/tile04.png
--------------------------------------------------------------------------------
/Images/howto01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/buchizo/ClaudiaIDE/HEAD/Images/howto01.png
--------------------------------------------------------------------------------
/Images/howto02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/buchizo/ClaudiaIDE/HEAD/Images/howto02.png
--------------------------------------------------------------------------------
/Images/howto03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/buchizo/ClaudiaIDE/HEAD/Images/howto03.png
--------------------------------------------------------------------------------
/Images/howto04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/buchizo/ClaudiaIDE/HEAD/Images/howto04.png
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [buchizo]
4 |
--------------------------------------------------------------------------------
/Images/example01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/buchizo/ClaudiaIDE/HEAD/Images/example01.png
--------------------------------------------------------------------------------
/Images/workaround01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/buchizo/ClaudiaIDE/HEAD/Images/workaround01.png
--------------------------------------------------------------------------------
/Shared/Resources/400.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/buchizo/ClaudiaIDE/HEAD/Shared/Resources/400.ico
--------------------------------------------------------------------------------
/Shared/Resources/ss.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/buchizo/ClaudiaIDE/HEAD/Shared/Resources/ss.png
--------------------------------------------------------------------------------
/Shared/Images/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/buchizo/ClaudiaIDE/HEAD/Shared/Images/background.png
--------------------------------------------------------------------------------
/Shared/Images/background2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/buchizo/ClaudiaIDE/HEAD/Shared/Images/background2.png
--------------------------------------------------------------------------------
/Shared/Resources/vsixicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/buchizo/ClaudiaIDE/HEAD/Shared/Resources/vsixicon.png
--------------------------------------------------------------------------------
/Images/config-per-solution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/buchizo/ClaudiaIDE/HEAD/Images/config-per-solution.png
--------------------------------------------------------------------------------
/Shared/Resources/ClaudiaIDEMenu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/buchizo/ClaudiaIDE/HEAD/Shared/Resources/ClaudiaIDEMenu.png
--------------------------------------------------------------------------------
/Shared/Interfaces/ISkipable.cs:
--------------------------------------------------------------------------------
1 | namespace ClaudiaIDE.Interfaces
2 | {
3 | internal interface ISkipable
4 | {
5 | void Skip();
6 | }
7 | }
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*.cs]
4 | charset = utf-8
5 | end_of_line = crlf
6 | indent_style = space
7 | trim_trailing_whitespace = true
8 | csharp_new_line_before_open_brace = all
9 |
--------------------------------------------------------------------------------
/Shared/Interfaces/IPausable.cs:
--------------------------------------------------------------------------------
1 | namespace ClaudiaIDE.Interfaces
2 | {
3 | internal interface IPausable
4 | {
5 | bool IsPaused { get; }
6 | void Pause();
7 | void Resume();
8 | }
9 | }
--------------------------------------------------------------------------------
/Shared/Helpers/AnimateImageChangeParams.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace ClaudiaIDE.Helpers
4 | {
5 | internal class AnimateImageChangeParams
6 | {
7 | public double TargetOpacity { get; set; } = 0.35;
8 | public TimeSpan FadeTime { get; set; } = TimeSpan.FromSeconds(5);
9 | }
10 | }
--------------------------------------------------------------------------------
/ClaudiaIDE/GuidList.cs:
--------------------------------------------------------------------------------
1 | namespace ClaudiaIDE
2 | {
3 | public static class GuidList
4 | {
5 | public const string PackageId = "7442ac19-889b-4699-a817-e6e054877ee3";
6 | public const string GeneralOptionPageId = "ACCEFBB9-1547-4B84-BA0D-B92F937FA28C";
7 | public const string OptionPageId = "441f0a76-1771-41c2-817c-81b8b03fb0e8";
8 | public const string DarkThemeOptionPageId = "EEFB93BE-B731-4DAC-BF91-6AAD0548BCBD";
9 | public const string MenuSetId = "f0ffaf7c-8feb-40d2-b898-1acfe50e1d6b";
10 | }
11 | }
--------------------------------------------------------------------------------
/ClaudiaIDE16/GuidList.cs:
--------------------------------------------------------------------------------
1 | namespace ClaudiaIDE
2 | {
3 | public static class GuidList
4 | {
5 | public const string PackageId = "9ab800ef-0cff-4893-bf16-57d58ff53456";
6 | public const string GeneralOptionPageId = "91A270EA-27B4-4A3A-BB2D-CFBC2E882FE1";
7 | public const string OptionPageId = "595e3c9f-2648-4225-99cb-7e6ed3b5c354";
8 | public const string DarkThemeOptionPageId = "06D8DABA-0E13-4E13-9990-F0879EFC823B";
9 | public const string MenuSetId = "74c31f05-fe81-450e-912d-da9fc31105ac";
10 | }
11 | }
--------------------------------------------------------------------------------
/Shared/Helpers/ResourceExtension.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 |
4 | namespace Shared.Helpers
5 | {
6 | public static class ResourceExtension
7 | {
8 | private static ResourceManager Resources = new ResourceManager("ClaudiaIDE.Localized.ResLocalized", Assembly.GetExecutingAssembly());
9 |
10 | public static string GetResourceString(string key)
11 | {
12 | try
13 | {
14 | return Resources.GetString(key) ?? "";
15 | }
16 | catch
17 | {
18 | return "";
19 | }
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Shared/GlobalSuppressions.cs:
--------------------------------------------------------------------------------
1 | // This file is used by Code Analysis to maintain SuppressMessage
2 | // attributes that are applied to this project. Project-level
3 | // suppressions either have no target or are given a specific target
4 | // and scoped to a namespace, type, member, etc.
5 | //
6 | // To add a suppression to this file, right-click the message in the
7 | // Error List, point to "Suppress Message(s)", and click "In Project
8 | // Suppression File". You do not need to add suppressions to this
9 | // file manually.
10 |
11 | using System.Diagnostics.CodeAnalysis;
12 |
13 | [assembly: SuppressMessage("Microsoft.Design", "CA1017:MarkAssembliesWithComVisible")]
--------------------------------------------------------------------------------
/Shared/Shared.shproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 6d268f80-dd38-48bb-81e2-51805e5a4e17
5 | 14.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Shared/Settings/JsonSerializer.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using System.Linq;
3 | using System.Runtime.Serialization.Json;
4 | using System.Text;
5 |
6 | namespace ClaudiaIDE.Settings
7 | {
8 | public static class JsonSerializer where TType : class
9 | {
10 | public static string Serialize(TType instance)
11 | {
12 | var serializer = new DataContractJsonSerializer(typeof(TType));
13 | using (var stream = new MemoryStream())
14 | using (var writer = JsonReaderWriterFactory.CreateJsonWriter(stream, Encoding.UTF8, true, true))
15 | {
16 | serializer.WriteObject(writer, instance);
17 | writer.Flush();
18 | return Encoding.UTF8.GetString(stream.ToArray(), 0, stream.ToArray().Count());
19 | }
20 | }
21 |
22 | public static TType DeSerialize(string json)
23 | {
24 | using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
25 | {
26 | var serializer = new DataContractJsonSerializer(typeof(TType));
27 | return serializer.ReadObject(stream) as TType;
28 | }
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/Shared/config.txt:
--------------------------------------------------------------------------------
1 | {
2 | "BackgroundImageAbsolutePath":"Images\\background.png",
3 | "BackgroundImagesDirectoryAbsolutePath":"Images",
4 | "Extensions":".png, .jpg, .gif, .bmp",
5 | "ImageBackgroundType":0,
6 | "Opacity":0.35,
7 | "ImageStretch":0,
8 | "PositionHorizon":1,
9 | "PositionVertical":1,
10 | "UpdateImageInterval":"PT30M",
11 | "ImageFadeAnimationInterval":"PT30S",
12 | "LoopSlideshow":true,
13 | "ShuffleSlideshow":false,
14 | "MaxWidth": 0,
15 | "MaxHeight": 0,
16 | "SoftEdgeX": 0,
17 | "SoftEdgeY": 0,
18 | "BlurRadius": 0,
19 | "BlurMethod": 0,
20 | "ExpandToIDE": false,
21 | "ViewBoxPointX": 0,
22 | "ViewBoxPointY": 0,
23 | "IsLimitToMainlyEditorWindow": false,
24 | "ViewPortWidth": 1,
25 | "ViewPortHeight": 1,
26 | "ViewPortPointX": 0,
27 | "ViewPortPointY": 0,
28 | "TileMode": 0,
29 | "SingleWebUrl": "",
30 | "WebApiDownloadInterval": "PT10S",
31 | "WebApiEndpoint": "https://azure.moe/api/image",
32 | "WebApiJsonKey": "url",
33 | "WebSingleUrl": "https://azure.moe/img/topbackground.png",
34 | "IsTransparentToContentMargin": false,
35 | "IsTransparentToStickyScroll": false,
36 | "StickyScrollColor": "#00000000",
37 | "EditorBackgroundColor": ""
38 | }
39 |
--------------------------------------------------------------------------------
/ClaudiaIDE/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Reflection;
3 | using System.Resources;
4 | using System.Runtime.InteropServices;
5 |
6 | // General Information about an assembly is controlled through the following
7 | // set of attributes. Change these attribute values to modify the information
8 | // associated with an assembly.
9 | [assembly: AssemblyTitle("ClaudiaIDE")]
10 | [assembly: AssemblyDescription("")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("")]
13 | [assembly: AssemblyProduct("ClaudiaIDE")]
14 | [assembly: AssemblyCopyright("")]
15 | [assembly: AssemblyTrademark("")]
16 | [assembly: AssemblyCulture("")]
17 | [assembly: CLSCompliant(false)]
18 | [assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
19 |
20 | // Setting ComVisible to false makes the types in this assembly not visible
21 | // to COM components. If you need to access a type in this assembly from
22 | // COM, set the ComVisible attribute to true on that type.
23 | [assembly: ComVisible(false)]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
--------------------------------------------------------------------------------
/ClaudiaIDE16/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Reflection;
3 | using System.Resources;
4 | using System.Runtime.InteropServices;
5 |
6 | // General Information about an assembly is controlled through the following
7 | // set of attributes. Change these attribute values to modify the information
8 | // associated with an assembly.
9 | [assembly: AssemblyTitle("ClaudiaIDE")]
10 | [assembly: AssemblyDescription("")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("")]
13 | [assembly: AssemblyProduct("ClaudiaIDE")]
14 | [assembly: AssemblyCopyright("")]
15 | [assembly: AssemblyTrademark("")]
16 | [assembly: AssemblyCulture("")]
17 | [assembly: CLSCompliant(false)]
18 | [assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
19 |
20 | // Setting ComVisible to false makes the types in this assembly not visible
21 | // to COM components. If you need to access a type in this assembly from
22 | // COM, set the ComVisible attribute to true on that type.
23 | [assembly: ComVisible(false)]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
--------------------------------------------------------------------------------
/Shared/Helpers/DependencyObjectExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Windows;
5 | using System.Windows.Media;
6 |
7 | namespace ClaudiaIDE.Helpers
8 | {
9 | public static class DependencyObjectExtensions
10 | {
11 | public static IEnumerable Children(this DependencyObject obj)
12 | {
13 | if (obj == null)
14 | throw new ArgumentNullException("obj");
15 |
16 | var count = VisualTreeHelper.GetChildrenCount(obj);
17 | if (count == 0)
18 | yield break;
19 |
20 | for (var i = 0; i < count; i++)
21 | {
22 | var child = VisualTreeHelper.GetChild(obj, i);
23 | if (child != null)
24 | yield return child;
25 | }
26 | }
27 |
28 | public static IEnumerable Descendants(this DependencyObject obj)
29 | {
30 | if (obj == null)
31 | throw new ArgumentNullException("obj");
32 |
33 | foreach (var child in obj.Children())
34 | {
35 | yield return child;
36 | foreach (var grandChild in child.Descendants())
37 | yield return grandChild;
38 | }
39 | }
40 |
41 | public static IEnumerable Children(this DependencyObject obj)
42 | where T : DependencyObject
43 | {
44 | return obj.Children().OfType();
45 | }
46 |
47 | public static IEnumerable Descendants(this DependencyObject obj)
48 | where T : DependencyObject
49 | {
50 | return obj.Descendants().OfType();
51 | }
52 | }
53 | }
--------------------------------------------------------------------------------
/Shared/Helpers/PausableTimer.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.Timers;
3 |
4 | namespace ClaudiaIDE.Helpers
5 | {
6 | internal class PausableTimer : Timer
7 | {
8 | private readonly double _initialInterval;
9 | private readonly Stopwatch _stopwatch;
10 | private bool _resumed;
11 |
12 | public PausableTimer(double interval) : base(interval <= 0 ? 1 : interval)
13 | {
14 | _initialInterval = interval <= 0 ? 1 : interval;
15 | Elapsed += OnElapsed;
16 | IsPaused = false;
17 | _stopwatch = new Stopwatch();
18 | }
19 |
20 | public double RemainingAfterPause { get; private set; }
21 | public bool IsPaused { get; private set; }
22 |
23 | public new void Start()
24 | {
25 | ResetStopwatch();
26 | IsPaused = false;
27 | base.Start();
28 | }
29 |
30 | public void Restart()
31 | {
32 | Stop();
33 | Start();
34 | }
35 |
36 | private void OnElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
37 | {
38 | if (_resumed)
39 | {
40 | _resumed = false;
41 | Stop();
42 | Interval = _initialInterval;
43 | Start();
44 | }
45 |
46 | ResetStopwatch();
47 | }
48 |
49 | private void ResetStopwatch()
50 | {
51 | _stopwatch.Reset();
52 | _stopwatch.Start();
53 | }
54 |
55 | public void Pause()
56 | {
57 | Stop();
58 | IsPaused = true;
59 | _stopwatch.Stop();
60 | RemainingAfterPause = Interval - _stopwatch.Elapsed.TotalMilliseconds;
61 | }
62 |
63 | public void Resume()
64 | {
65 | IsPaused = false;
66 | _resumed = true;
67 | Interval = RemainingAfterPause;
68 | RemainingAfterPause = 0;
69 | Start();
70 | }
71 | }
72 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
2 | [Oo]bj/
3 |
4 | # mstest test results
5 | TestResults
6 |
7 | ## Ignore Visual Studio temporary files, build results, and
8 | ## files generated by popular Visual Studio add-ons.
9 |
10 | # User-specific files
11 | *.suo
12 | *.user
13 | *.sln.docstates
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Rr]elease/
18 | x64/
19 | *_i.c
20 | *_p.c
21 | *.ilk
22 | *.meta
23 | *.obj
24 | *.pch
25 | *.pdb
26 | *.pgc
27 | *.pgd
28 | *.rsp
29 | *.sbr
30 | *.tlb
31 | *.tli
32 | *.tlh
33 | *.tmp
34 | *.log
35 | *.vspscc
36 | *.vssscc
37 | .builds
38 |
39 | # Visual C++ cache files
40 | ipch/
41 | *.aps
42 | *.ncb
43 | *.opensdf
44 | *.sdf
45 |
46 | # Visual Studio profiler
47 | *.psess
48 | *.vsp
49 | *.vspx
50 |
51 | # Guidance Automation Toolkit
52 | *.gpState
53 |
54 | # ReSharper is a .NET coding add-in
55 | _ReSharper*
56 |
57 | # NCrunch
58 | *.ncrunch*
59 | .*crunch*.local.xml
60 |
61 | # Installshield output folder
62 | [Ee]xpress
63 |
64 | # DocProject is a documentation generator add-in
65 | DocProject/buildhelp/
66 | DocProject/Help/*.HxT
67 | DocProject/Help/*.HxC
68 | DocProject/Help/*.hhc
69 | DocProject/Help/*.hhk
70 | DocProject/Help/*.hhp
71 | DocProject/Help/Html2
72 | DocProject/Help/html
73 |
74 | # Click-Once directory
75 | publish
76 |
77 | # Publish Web Output
78 | *.Publish.xml
79 |
80 | # NuGet Packages Directory
81 | packages
82 |
83 | # Windows Azure Build Output
84 | csx
85 | *.build.csdef
86 |
87 | # Windows Store app package directory
88 | AppPackages/
89 |
90 | # Others
91 | [Oo]bj
92 | sql
93 | TestResults
94 | [Tt]est[Rr]esult*
95 | *.Cache
96 | ClientBin
97 | [Ss]tyle[Cc]op.*
98 | ~$*
99 | *.dbmdl
100 | Generated_Code #added for RIA/Silverlight projects
101 |
102 | # Backup & report files from converting an old project file to a newer
103 | # Visual Studio version. Backup files are not needed, because we have git ;-)
104 | _UpgradeReport_Files/
105 | Backup*/
106 | UpgradeLog*.XML
107 |
108 | .vs/
109 |
--------------------------------------------------------------------------------
/ClaudiaIDE16/source.extension.vsixmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ClaudiaIDE 2019
6 | This extension allows you to change the background image of the editor.
7 | https://github.com/buchizo/ClaudiaIDE
8 | https://github.com/buchizo/ClaudiaIDE/wiki/Release-notes
9 | Resources\vsixicon.png
10 | Resources\ss.png
11 | theme, Text Editor, 痛IDE拡張, Background, Claudia
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/Shared/ImageProviders/SingleImageWebProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using System.Windows.Media.Imaging;
6 | using ClaudiaIDE.Helpers;
7 | using ClaudiaIDE.Settings;
8 | using Microsoft.VisualStudio.Threading;
9 |
10 | namespace ClaudiaIDE.ImageProviders
11 | {
12 | internal class SingleImageWebProvider : ImageProvider
13 | {
14 | private string _currentUrl;
15 |
16 | public SingleImageWebProvider(Setting setting, string solutionfile = null) : base(setting, solutionfile,
17 | ImageBackgroundType.WebSingle)
18 | {
19 | }
20 |
21 | protected override void OnSettingChanged(object sender, EventArgs e)
22 | {
23 | if ((sender as Setting)?.ImageBackgroundType != ImageBackgroundType.WebSingle) return;
24 | ImageDownloader.ResetUrl();
25 | Image = null;
26 | }
27 |
28 | public override BitmapSource GetBitmap()
29 | {
30 | if (Image != null) return Image;
31 | LoadImageFromWebAsync().Forget();
32 | return null;
33 | }
34 |
35 | private async Task LoadImageFromWebAsync()
36 | {
37 | try
38 | {
39 | _currentUrl = Setting.WebSingleUrl;
40 | if (!IsStaticImage()) return;
41 | Image = await ImageDownloader.LoadImageAsync(Setting.WebSingleUrl, Setting.ImageStretch, Setting.MaxWidth, Setting.MaxHeight, Setting);
42 | if (Image != null) FireImageAvailable();
43 | }
44 | catch { }
45 | }
46 |
47 | public override bool IsStaticImage()
48 | {
49 | if (string.IsNullOrEmpty(_currentUrl)) return true;
50 | var f = new FileInfo(new Uri(_currentUrl).LocalPath);
51 | return !Setting.SupportVideoFileExtensions.Any(x => x == f.Extension.ToLower());
52 | }
53 |
54 | public override string GetCurrentImageUri()
55 | {
56 | return _currentUrl;
57 | }
58 | }
59 | }
--------------------------------------------------------------------------------
/Shared/Extensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using EnvDTE;
5 | using EnvDTE80;
6 | using Microsoft.VisualStudio.Shell;
7 |
8 | namespace ClaudiaIDE
9 | {
10 | public static class Extensions
11 | {
12 | public static void Shuffle(this IList list)
13 | {
14 | var rng = new Random();
15 | var n = list.Count;
16 | while (n > 1)
17 | {
18 | n--;
19 | var k = rng.Next(n + 1);
20 | var value = list[k];
21 | list[k] = list[n];
22 | list[n] = value;
23 | }
24 | }
25 | }
26 |
27 | public static class VisualStudioUtility
28 | {
29 | public static string GetSolutionSettingsFileFullPath(bool checkExists = true)
30 | {
31 | try
32 | {
33 | if (!TryGetSolutionPath(out string path)) return null;
34 |
35 | // CMake or other directory project (not .sln) `path` is directory
36 | var dir = File.GetAttributes(path).HasFlag(FileAttributes.Directory)
37 | ? path
38 | : Path.GetDirectoryName(path);
39 | if (string.IsNullOrWhiteSpace(dir)) return null;
40 |
41 | var configPath = Path.Combine(dir, ".claudiaideconfig");
42 | return checkExists
43 | ? File.Exists(configPath) ? configPath : null
44 | : configPath;
45 | }
46 | catch
47 | {
48 | return null;
49 | }
50 | }
51 |
52 |
53 | public static bool TryGetSolutionPath(out string path)
54 | {
55 | try
56 | {
57 | var dte = Package.GetGlobalService(typeof(DTE)) as DTE2;
58 | path = dte?.Solution?.FileName;
59 | return !string.IsNullOrWhiteSpace(path);
60 | }
61 | catch
62 | {
63 | path = null;
64 | return false;
65 | }
66 | }
67 | }
68 | }
--------------------------------------------------------------------------------
/ClaudiaIDE.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.28803.452
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClaudiaIDE", "ClaudiaIDE\ClaudiaIDE.csproj", "{FA0103C8-8CCD-4A1E-AF09-9862C9A4A04A}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{72CB9490-9766-43FD-8A16-11E9797EC02B}"
9 | ProjectSection(SolutionItems) = preProject
10 | .editorconfig = .editorconfig
11 | EndProjectSection
12 | EndProject
13 | Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Shared", "Shared\Shared.shproj", "{6D268F80-DD38-48BB-81E2-51805E5A4E17}"
14 | EndProject
15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClaudiaIDE16", "ClaudiaIDE16\ClaudiaIDE16.csproj", "{E803B36C-090C-4155-B13C-EAE30CA78AA7}"
16 | EndProject
17 | Global
18 | GlobalSection(SharedMSBuildProjectFiles) = preSolution
19 | Shared\Shared.projitems*{6d268f80-dd38-48bb-81e2-51805e5a4e17}*SharedItemsImports = 13
20 | Shared\Shared.projitems*{e803b36c-090c-4155-b13c-eae30ca78aa7}*SharedItemsImports = 4
21 | Shared\Shared.projitems*{fa0103c8-8ccd-4a1e-af09-9862c9a4a04a}*SharedItemsImports = 4
22 | EndGlobalSection
23 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
24 | Debug|Any CPU = Debug|Any CPU
25 | Release|Any CPU = Release|Any CPU
26 | EndGlobalSection
27 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
28 | {FA0103C8-8CCD-4A1E-AF09-9862C9A4A04A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | {FA0103C8-8CCD-4A1E-AF09-9862C9A4A04A}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | {FA0103C8-8CCD-4A1E-AF09-9862C9A4A04A}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {FA0103C8-8CCD-4A1E-AF09-9862C9A4A04A}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {E803B36C-090C-4155-B13C-EAE30CA78AA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {E803B36C-090C-4155-B13C-EAE30CA78AA7}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | {E803B36C-090C-4155-B13C-EAE30CA78AA7}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 | {E803B36C-090C-4155-B13C-EAE30CA78AA7}.Release|Any CPU.Build.0 = Release|Any CPU
36 | EndGlobalSection
37 | GlobalSection(SolutionProperties) = preSolution
38 | HideSolutionNode = FALSE
39 | EndGlobalSection
40 | GlobalSection(ExtensibilityGlobals) = postSolution
41 | SolutionGuid = {742C5C24-8743-44F4-8877-60779C1E23B4}
42 | EndGlobalSection
43 | EndGlobal
44 |
--------------------------------------------------------------------------------
/Shared/Localized/LocalManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Resources;
4 |
5 | namespace ClaudiaIDE.Localized
6 | {
7 | internal class LocalManager
8 | {
9 | internal static ResourceManager _rm;
10 |
11 | private static ResourceManager GetInstance()
12 | {
13 | if (_rm == null) _rm = ResLocalized.ResourceManager;
14 |
15 | return _rm;
16 | }
17 |
18 | [AttributeUsage(AttributeTargets.Assembly |
19 | AttributeTargets.Module |
20 | AttributeTargets.Class |
21 | AttributeTargets.Struct |
22 | AttributeTargets.Enum |
23 | AttributeTargets.Constructor |
24 | AttributeTargets.Method |
25 | AttributeTargets.Property |
26 | AttributeTargets.Field |
27 | AttributeTargets.Event |
28 | AttributeTargets.Interface |
29 | AttributeTargets.Parameter |
30 | AttributeTargets.Delegate |
31 | AttributeTargets.ReturnValue |
32 | AttributeTargets.GenericParameter)]
33 | internal class LocalizedDescriptionAttribute : DescriptionAttribute
34 | {
35 | internal LocalizedDescriptionAttribute(string _key) : base(Localize(_key))
36 | {
37 | }
38 |
39 | private static string Localize(string _key)
40 | {
41 | return GetInstance().GetString(_key);
42 | }
43 | }
44 |
45 | [AttributeUsage(AttributeTargets.All)]
46 | internal class LocalizedCategoryAttribute : CategoryAttribute
47 | {
48 | internal LocalizedCategoryAttribute(string _key) : base(Localize(_key))
49 | {
50 | }
51 |
52 | private static string Localize(string _key)
53 | {
54 | return GetInstance().GetString(_key);
55 | }
56 | }
57 |
58 | [AttributeUsage(AttributeTargets.Class |
59 | AttributeTargets.Method |
60 | AttributeTargets.Property |
61 | AttributeTargets.Event)]
62 | internal class LocalizedDisplayNameAttribute : DisplayNameAttribute
63 | {
64 | internal LocalizedDisplayNameAttribute(string _key) : base(Localize(_key))
65 | {
66 | }
67 |
68 | private static string Localize(string _key)
69 | {
70 | return GetInstance().GetString(_key);
71 | }
72 | }
73 | }
74 | }
--------------------------------------------------------------------------------
/Shared/MenuCommands/ToggleHiddenImage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel.Design;
3 | using ClaudiaIDE.Settings;
4 | using Microsoft.VisualStudio.Shell;
5 | using Task = System.Threading.Tasks.Task;
6 |
7 | namespace ClaudiaIDE.MenuCommands
8 | {
9 | ///
10 | /// Command handler
11 | ///
12 | internal sealed class ToggleHiddenImage
13 | {
14 | ///
15 | /// Command ID.
16 | ///
17 | public const int CommandId = 0x0140;
18 |
19 | ///
20 | /// Command menu group (command set GUID).
21 | ///
22 | public static readonly Guid CommandSet = new Guid(GuidList.MenuSetId);
23 |
24 | private readonly MenuCommand _menuItem;
25 |
26 | private ToggleHiddenImage(AsyncPackage package, OleMenuCommandService commandService)
27 | {
28 | commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));
29 | var menuCommandID = new CommandID(CommandSet, CommandId);
30 | _menuItem = new MenuCommand(Execute, menuCommandID)
31 | {
32 | Enabled = true
33 | };
34 | commandService.AddCommand(_menuItem);
35 | }
36 |
37 | ///
38 | /// Gets the instance of the command.
39 | ///
40 | public static ToggleHiddenImage Instance { get; private set; }
41 |
42 | ///
43 | /// Initializes the singleton instance of the command.
44 | ///
45 | /// Owner package, not null.
46 | public static async Task InitializeAsync(AsyncPackage package)
47 | {
48 | // Switch to the main thread - the call to AddCommand in NextImage's constructor requires
49 | // the UI thread.
50 | if (Instance != null) return;
51 | await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);
52 | var commandService =
53 | await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
54 | Instance = new ToggleHiddenImage(package, commandService);
55 | }
56 |
57 | ///
58 | /// This function is the callback used to execute the command when the menu item is clicked.
59 | /// See the constructor to see how the menu item is associated with this function using
60 | /// OleMenuCommandService service and MenuCommand class.
61 | ///
62 | /// Event sender.
63 | /// Event args.
64 | private void Execute(object sender, EventArgs e)
65 | {
66 | Setting.Instance.OnToggleVisibility();
67 | }
68 | }
69 | }
--------------------------------------------------------------------------------
/Shared/MenuCommands/OpenSettings.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel.Design;
3 | using ClaudiaIDE.Options;
4 | using Microsoft.VisualStudio.Shell;
5 | using Task = System.Threading.Tasks.Task;
6 |
7 | namespace ClaudiaIDE.MenuCommands
8 | {
9 | ///
10 | /// Command handler
11 | ///
12 | internal sealed class OpenSettings
13 | {
14 | ///
15 | /// Command ID.
16 | ///
17 | public const int CommandId = 0x0170;
18 |
19 | ///
20 | /// Command menu group (command set GUID).
21 | ///
22 | public static readonly Guid CommandSet = new Guid(GuidList.MenuSetId);
23 |
24 | private readonly MenuCommand _menuItem;
25 | private readonly AsyncPackage _package;
26 |
27 | private OpenSettings(AsyncPackage package, OleMenuCommandService commandService)
28 | {
29 | commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));
30 | var menuCommandID = new CommandID(CommandSet, CommandId);
31 | _package = package;
32 | _menuItem = new MenuCommand(Execute, menuCommandID)
33 | {
34 | Enabled = true
35 | };
36 | commandService.AddCommand(_menuItem);
37 | }
38 |
39 | ///
40 | /// Gets the instance of the command.
41 | ///
42 | public static OpenSettings Instance { get; private set; }
43 |
44 | ///
45 | /// Initializes the singleton instance of the command.
46 | ///
47 | /// Owner package, not null.
48 | public static async Task InitializeAsync(AsyncPackage package)
49 | {
50 | // Switch to the main thread - the call to AddCommand in OpenSettings's constructor requires
51 | // the UI thread.
52 | if (Instance != null) return;
53 | await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);
54 | var commandService =
55 | await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
56 | Instance = new OpenSettings(package, commandService);
57 | }
58 |
59 | ///
60 | /// This function is the callback used to execute the command when the menu item is clicked.
61 | /// See the constructor to see how the menu item is associated with this function using
62 | /// OleMenuCommandService service and MenuCommand class.
63 | ///
64 | /// Event sender.
65 | /// Event args.
66 | private void Execute(object sender, EventArgs e)
67 | {
68 | Instance._package?.ShowOptionPage(typeof(ClaudiaIdeGeneralOptionPageGrid));
69 | }
70 | }
71 | }
--------------------------------------------------------------------------------
/ClaudiaIDE/source.extension.vsixmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ClaudiaIDE
6 | This extension allows you to change the background image of the editor.
7 | https://github.com/buchizo/ClaudiaIDE
8 | https://github.com/buchizo/ClaudiaIDE/wiki/Release-notes
9 | Resources\vsixicon.png
10 | Resources\ss.png
11 | theme, Text Editor, 痛IDE拡張, Background, Claudia
12 |
13 |
14 |
17 |
18 | amd64
19 |
20 |
21 | amd64
22 |
23 |
24 | amd64
25 |
26 |
29 |
30 | arm64
31 |
32 |
33 | arm64
34 |
35 |
36 | arm64
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/Shared/Shared.projitems:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
5 | true
6 | 6d268f80-dd38-48bb-81e2-51805e5a4e17
7 |
8 |
9 | Shared
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Shared/MenuCommands/ResetSolutionSettings.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel.Design;
3 | using System.IO;
4 | using ClaudiaIDE.Settings;
5 | using Microsoft.VisualStudio.Shell;
6 | using Task = System.Threading.Tasks.Task;
7 |
8 | namespace ClaudiaIDE.MenuCommands
9 | {
10 | ///
11 | /// Command handler
12 | ///
13 | internal sealed class ResetSolutionSettings
14 | {
15 | ///
16 | /// Command ID.
17 | ///
18 | public const int CommandId = 0x0150;
19 |
20 | ///
21 | /// Command menu group (command set GUID).
22 | ///
23 | public static readonly Guid CommandSet = new Guid(GuidList.MenuSetId);
24 |
25 | private readonly OleMenuCommand _menuItem;
26 |
27 | private readonly Setting _setting;
28 |
29 | private ResetSolutionSettings(AsyncPackage package, OleMenuCommandService commandService, Setting setting)
30 | {
31 | _setting = setting;
32 | commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));
33 | var menuCommandID = new CommandID(CommandSet, CommandId);
34 | _menuItem = new OleMenuCommand(Execute, menuCommandID);
35 | _menuItem.BeforeQueryStatus += (s, e) =>
36 | {
37 | ThreadHelper.ThrowIfNotOnUIThread();
38 | _menuItem.Enabled = !string.IsNullOrWhiteSpace(VisualStudioUtility.GetSolutionSettingsFileFullPath());
39 | };
40 | commandService.AddCommand(_menuItem);
41 | }
42 |
43 | ///
44 | /// Gets the instance of the command.
45 | ///
46 | public static ResetSolutionSettings Instance { get; private set; }
47 |
48 | ///
49 | /// Initializes the singleton instance of the command.
50 | ///
51 | /// Owner package, not null.
52 | public static async Task InitializeAsync(AsyncPackage package, Setting setting)
53 | {
54 | // Switch to the main thread - the call to AddCommand in NextImage's constructor requires
55 | // the UI thread.
56 | if (Instance != null) return;
57 | await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);
58 | var commandService =
59 | await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
60 | Instance = new ResetSolutionSettings(package, commandService, setting);
61 | }
62 |
63 | ///
64 | /// Reset/remove .claudiaideconfig file from solution directory.
65 | ///
66 | ///
67 | ///
68 | private void Execute(object sender, EventArgs e)
69 | {
70 | ThreadHelper.ThrowIfNotOnUIThread();
71 | var solution = VisualStudioUtility.GetSolutionSettingsFileFullPath();
72 | if (string.IsNullOrWhiteSpace(solution)) return;
73 | try
74 | {
75 | File.Delete(solution);
76 | _setting.SolutionConfigFilePath = null;
77 | Setting.Instance.OnApplyChanged();
78 | }
79 | catch { }
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/Shared/MenuCommands/AboutImage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel.Design;
3 | using ClaudiaIDE.Forms;
4 | using ClaudiaIDE.ImageProviders;
5 | using Microsoft.VisualStudio.Shell;
6 | using Task = System.Threading.Tasks.Task;
7 |
8 | namespace ClaudiaIDE.MenuCommands
9 | {
10 | ///
11 | /// Command handler
12 | ///
13 | internal sealed class AboutImage
14 | {
15 | ///
16 | /// Command ID.
17 | ///
18 | public const int CommandId = 0x0160;
19 |
20 | ///
21 | /// Command menu group (command set GUID).
22 | ///
23 | public static readonly Guid CommandSet = new Guid(GuidList.MenuSetId);
24 |
25 | private readonly OleMenuCommand _menuItem;
26 | private readonly AsyncPackage _package;
27 |
28 | private AboutImage(AsyncPackage package, OleMenuCommandService commandService)
29 | {
30 | commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));
31 | var menuCommandID = new CommandID(CommandSet, CommandId);
32 | _package = package;
33 | _menuItem = new OleMenuCommand(Execute, menuCommandID);
34 | _menuItem.BeforeQueryStatus += (s, e) =>
35 | {
36 | ImageProvider provider = ProvidersHolder.Instance.ActiveProvider;
37 | // It is unavailable with the SingleEach image type as the provider does not track the image within each individual pane.
38 | _menuItem.Enabled = !(provider is SingleImageEachProvider);
39 | };
40 | commandService.AddCommand(_menuItem);
41 | }
42 |
43 | ///
44 | /// Gets the instance of the command.
45 | ///
46 | public static AboutImage Instance { get; private set; }
47 |
48 | ///
49 | /// Initializes the singleton instance of the command.
50 | ///
51 | /// Owner package, not null.
52 | public static async Task InitializeAsync(AsyncPackage package)
53 | {
54 | // Switch to the main thread - the call to AddCommand in AboutImage's constructor requires
55 | // the UI thread.
56 | if (Instance != null) return;
57 | await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);
58 | var commandService =
59 | await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
60 | Instance = new AboutImage(package, commandService);
61 | }
62 |
63 | ///
64 | /// This function is the callback used to execute the command when the menu item is clicked.
65 | /// See the constructor to see how the menu item is associated with this function using
66 | /// OleMenuCommandService service and MenuCommand class.
67 | ///
68 | /// Event sender.
69 | /// Event args.
70 | private void Execute(object sender, EventArgs e)
71 | {
72 | ImageProvider provider = ProvidersHolder.Instance.ActiveProvider;
73 | if (provider == null) return;
74 |
75 | using (AboutImageForm form = new AboutImageForm(provider))
76 | {
77 | form.ShowDialog();
78 | }
79 | }
80 | }
81 | }
--------------------------------------------------------------------------------
/Shared/MenuCommands/SaveSolutionSettings.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel.Design;
3 | using ClaudiaIDE.Settings;
4 | using Microsoft.VisualStudio.Shell;
5 | using Task = System.Threading.Tasks.Task;
6 |
7 | namespace ClaudiaIDE.MenuCommands
8 | {
9 | ///
10 | /// Command handler
11 | ///
12 | internal sealed class SaveSolutionSettings
13 | {
14 | ///
15 | /// Command ID.
16 | ///
17 | public const int CommandId = 0x0130;
18 |
19 | ///
20 | /// Command menu group (command set GUID).
21 | ///
22 | public static readonly Guid CommandSet = new Guid(GuidList.MenuSetId);
23 |
24 | private readonly OleMenuCommand _menuItem;
25 |
26 | private readonly Setting _setting;
27 |
28 | private SaveSolutionSettings(AsyncPackage package, OleMenuCommandService commandService, Setting setting)
29 | {
30 | _setting = setting;
31 | commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));
32 | var menuCommandID = new CommandID(CommandSet, CommandId);
33 | _menuItem = new OleMenuCommand(Execute, menuCommandID);
34 | _menuItem.BeforeQueryStatus += (s, e) =>
35 | {
36 | ThreadHelper.ThrowIfNotOnUIThread();
37 | _menuItem.Enabled = VisualStudioUtility.TryGetSolutionPath(out _);
38 | };
39 | commandService.AddCommand(_menuItem);
40 | }
41 |
42 | ///
43 | /// Gets the instance of the command.
44 | ///
45 | public static SaveSolutionSettings Instance { get; private set; }
46 |
47 | ///
48 | /// Initializes the singleton instance of the command.
49 | ///
50 | /// Owner package, not null.
51 | public static async Task InitializeAsync(AsyncPackage package, Setting setting)
52 | {
53 | // Switch to the main thread - the call to AddCommand in NextImage's constructor requires
54 | // the UI thread.
55 | if (Instance != null) return;
56 | await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);
57 | var commandService =
58 | await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
59 | Instance = new SaveSolutionSettings(package, commandService, setting);
60 | }
61 |
62 | ///
63 | /// This function is the callback used to execute the command when the menu item is clicked.
64 | /// See the constructor to see how the menu item is associated with this function using
65 | /// OleMenuCommandService service and MenuCommand class.
66 | ///
67 | /// Event sender.
68 | /// Event args.
69 | private void Execute(object sender, EventArgs e)
70 | {
71 | ThreadHelper.ThrowIfNotOnUIThread();
72 | var solution = VisualStudioUtility.GetSolutionSettingsFileFullPath(false);
73 | if (!string.IsNullOrWhiteSpace(solution))
74 | {
75 | try {
76 | _setting.Serialize(solution);
77 | }
78 | catch { }
79 | }
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/Shared/MenuCommands/NextImage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel.Design;
3 | using ClaudiaIDE.Interfaces;
4 | using Microsoft.VisualStudio.Shell;
5 | using Task = System.Threading.Tasks.Task;
6 |
7 | namespace ClaudiaIDE.MenuCommands
8 | {
9 | ///
10 | /// Command handler
11 | ///
12 | internal sealed class NextImage
13 | {
14 | ///
15 | /// Command ID.
16 | ///
17 | public const int CommandId = 0x0100;
18 |
19 | ///
20 | /// Command menu group (command set GUID).
21 | ///
22 | public static readonly Guid CommandSet = new Guid(GuidList.MenuSetId);
23 |
24 | private readonly OleMenuCommand _menuItem;
25 |
26 |
27 | private ISkipable activeSkipabe;
28 |
29 | ///
30 | /// Initializes a new instance of the class.
31 | /// Adds our command handlers for menu (commands must exist in the command table file)
32 | ///
33 | /// Owner package, not null.
34 | /// Command service to add command to, not null.
35 | private NextImage(AsyncPackage package, OleMenuCommandService commandService)
36 | {
37 | commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));
38 | var menuCommandID = new CommandID(CommandSet, CommandId);
39 | _menuItem = new OleMenuCommand(Execute, menuCommandID);
40 | _menuItem.BeforeQueryStatus += ReloadSettings;
41 | commandService.AddCommand(_menuItem);
42 | }
43 |
44 | ///
45 | /// Gets the instance of the command.
46 | ///
47 | public static NextImage Instance { get; private set; }
48 |
49 | public void ReloadSettings(object sender, EventArgs args)
50 | {
51 | if (ProvidersHolder.Instance.ActiveProvider is ISkipable skipable)
52 | activeSkipabe = skipable;
53 | else
54 | activeSkipabe = null;
55 |
56 | _menuItem.Enabled = activeSkipabe != null;
57 | }
58 |
59 | ///
60 | /// Initializes the singleton instance of the command.
61 | ///
62 | /// Owner package, not null.
63 | public static async Task InitializeAsync(AsyncPackage package)
64 | {
65 | // Switch to the main thread - the call to AddCommand in NextImage's constructor requires
66 | // the UI thread.
67 | if (Instance != null) return;
68 | await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);
69 | var commandService =
70 | await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
71 | Instance = new NextImage(package, commandService);
72 | }
73 |
74 | ///
75 | /// This function is the callback used to execute the command when the menu item is clicked.
76 | /// See the constructor to see how the menu item is associated with this function using
77 | /// OleMenuCommandService service and MenuCommand class.
78 | ///
79 | /// Event sender.
80 | /// Event args.
81 | private void Execute(object sender, EventArgs e)
82 | {
83 | ThreadHelper.ThrowIfNotOnUIThread();
84 | activeSkipabe.Skip();
85 | }
86 | }
87 | }
--------------------------------------------------------------------------------
/Shared/ImageProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Windows.Media.Imaging;
5 | using ClaudiaIDE.Settings;
6 |
7 | namespace ClaudiaIDE
8 | {
9 | public abstract class ImageProvider
10 | {
11 | protected readonly Setting Setting;
12 | protected BitmapSource Image;
13 |
14 | public ImageProvider(Setting setting, string solutionConfigFile, ImageBackgroundType providerType)
15 | {
16 | Setting = setting;
17 | Setting.OnChanged.AddEventHandler(OnSettingChanged);
18 | SolutionConfigFile = solutionConfigFile;
19 | ProviderType = providerType;
20 | }
21 |
22 | public ImageBackgroundType ProviderType { get; }
23 |
24 | public string SolutionConfigFile { get; }
25 |
26 | public bool IsActive { get; set; }
27 |
28 | public virtual BitmapSource GetBitmap()
29 | {
30 | return Image;
31 | }
32 |
33 | public abstract bool IsStaticImage();
34 | public abstract string GetCurrentImageUri();
35 |
36 | public event EventHandler NewImageAvailable;
37 |
38 | ~ImageProvider()
39 | {
40 | Setting.OnChanged.RemoveEventHandler(OnSettingChanged);
41 | }
42 |
43 | protected void FireImageAvailable()
44 | {
45 | NewImageAvailable?.Invoke(this, EventArgs.Empty);
46 | }
47 |
48 | protected abstract void OnSettingChanged(object sender, EventArgs e);
49 | }
50 |
51 | public class ProvidersHolder
52 | {
53 | private static readonly Lazy
54 | _instance = new Lazy(() => new ProvidersHolder());
55 |
56 | private ProvidersHolder()
57 | {
58 | }
59 |
60 | public static ProvidersHolder Instance => _instance.Value;
61 |
62 | public List Providers { get; private set; }
63 |
64 | public ImageProvider ActiveProvider
65 | {
66 | get
67 | {
68 | var solfile = VisualStudioUtility.GetSolutionSettingsFileFullPath();
69 | return Providers.FirstOrDefault(provider => string.IsNullOrEmpty(solfile) ? provider.IsActive : provider.SolutionConfigFile == solfile);
70 | }
71 | }
72 |
73 | public static void Initialize(Setting settings, List providers)
74 | {
75 | if (_instance.Value.Providers == null) _instance.Value.Providers = providers;
76 | var tp = _instance.Value.Providers?.FirstOrDefault(x => x.ProviderType == settings?.ImageBackgroundType);
77 | if (tp != null) tp.IsActive = true;
78 | }
79 |
80 | public ImageProvider ChangeActive(ImageBackgroundType newType, string solution)
81 | {
82 | Providers.ForEach(x => x.IsActive = false);
83 | var ret = Providers.FirstOrDefault(x => x.SolutionConfigFile == solution && x.ProviderType == newType);
84 | if (!string.IsNullOrEmpty(solution))
85 | {
86 | ret = Providers.FirstOrDefault(x => x.SolutionConfigFile == solution);
87 | if (ret == null)
88 | {
89 | ret = Providers.FirstOrDefault(x =>
90 | x.SolutionConfigFile == null && x.ProviderType == newType);
91 | }
92 | }
93 | else
94 | {
95 | ret = Providers.FirstOrDefault(x =>
96 | x.SolutionConfigFile == null && x.ProviderType == newType);
97 | }
98 | ret.IsActive = true;
99 | return ret;
100 | }
101 | }
102 | }
--------------------------------------------------------------------------------
/Shared/Helpers/ImageDownloader.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net.Http;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 | using System.Windows.Media.Imaging;
6 | using ClaudiaIDE.Settings;
7 |
8 | namespace ClaudiaIDE.Helpers
9 | {
10 | internal class ImageDownloader
11 | {
12 | private static readonly HttpClient _client = new HttpClient();
13 | private static BitmapImage _image;
14 | private static bool loading;
15 |
16 | public static async Task LoadImageAsync(string url, ImageStretch imageStretch, int maxWidth, int maxHeight, Setting setting)
17 | {
18 | if (string.IsNullOrEmpty(url)) return null;
19 | if (loading) return null;
20 |
21 | try
22 | {
23 | var cts = new CancellationTokenSource();
24 | cts.CancelAfter(setting.WebApiDownloadInterval);
25 | var request = new HttpRequestMessage(HttpMethod.Get, new Uri(url));
26 | request.Headers.Add("ContentType", "application/json; charset=utf-8");
27 | var httpres = await _client.SendAsync(request, cts.Token);
28 | if (!httpres.IsSuccessStatusCode) return null;
29 |
30 | using (var memoryStream = await httpres.Content.ReadAsStreamAsync())
31 | {
32 | _image = new BitmapImage();
33 | _image.BeginInit();
34 | _image.StreamSource = memoryStream;
35 | _image.StreamSource.Position = 0;
36 | _image.EndInit();
37 | _image.Freeze();
38 |
39 | if (imageStretch == ImageStretch.None)
40 | {
41 | if (maxHeight > 0 || maxWidth > 0)
42 | {
43 | var tmp = new BitmapImage();
44 | tmp.BeginInit();
45 | tmp.StreamSource = memoryStream;
46 | memoryStream.Position = 0;
47 | var modified = false;
48 | if (maxHeight > 0 && _image.PixelHeight > maxHeight)
49 | {
50 | if (_image.PixelHeight > _image.PixelWidth || maxWidth == 0)
51 | tmp.DecodePixelHeight = maxHeight;
52 | else
53 | tmp.DecodePixelWidth = maxWidth;
54 | modified = true;
55 | }
56 |
57 | if (maxWidth > 0 && _image.PixelWidth > maxHeight && !modified)
58 | {
59 | if (_image.PixelWidth > _image.PixelHeight || maxHeight == 0)
60 | tmp.DecodePixelWidth = maxWidth;
61 | else
62 | tmp.DecodePixelHeight = maxHeight;
63 | }
64 |
65 | tmp.EndInit();
66 | tmp.Freeze();
67 | _image = tmp;
68 | }
69 | }
70 |
71 | BitmapSource ret_bitmap = null;
72 | if ((_image.Width != _image.PixelWidth || _image.Height != _image.PixelHeight))
73 | ret_bitmap = Utils.ConvertToDpi96(_image);
74 |
75 | if (setting.SoftEdgeX > 0 || setting.SoftEdgeY > 0)
76 | ret_bitmap = Utils.SoftenEdges(ret_bitmap ?? _image, setting.SoftEdgeX, setting.SoftEdgeY);
77 |
78 | loading = false;
79 | return ret_bitmap ?? _image;
80 | }
81 | }
82 | catch
83 | {
84 | return null;
85 | }
86 | }
87 |
88 | internal static void ResetUrl()
89 | {
90 | }
91 | }
92 | }
--------------------------------------------------------------------------------
/Shared/ImageProviders/SingleImageProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Windows.Media.Imaging;
6 | using ClaudiaIDE.Helpers;
7 | using ClaudiaIDE.Settings;
8 |
9 | namespace ClaudiaIDE.ImageProviders
10 | {
11 | public class SingleImageProvider : ImageProvider
12 | {
13 | private BitmapImage _bitmap;
14 | private BitmapSource _bitmapSource;
15 |
16 | public SingleImageProvider(Setting setting, string solutionfile = null) : base(setting, solutionfile,
17 | ImageBackgroundType.Single)
18 | {
19 | LoadImage();
20 | }
21 |
22 | protected override void OnSettingChanged(object sender, EventArgs e)
23 | {
24 | if ((sender as Setting)?.ImageBackgroundType != ImageBackgroundType.Single) return;
25 | LoadImage();
26 | FireImageAvailable();
27 | }
28 |
29 |
30 | public override BitmapSource GetBitmap()
31 | {
32 | if (_bitmap == null && _bitmapSource != null) return _bitmapSource;
33 | if (_bitmap != null && _bitmapSource == null) return _bitmap;
34 | return _bitmap;
35 | }
36 |
37 | public override bool IsStaticImage()
38 | {
39 | if (string.IsNullOrEmpty(Setting.BackgroundImageAbsolutePath)) return true;
40 | var fileInfo = new FileInfo(Setting.BackgroundImageAbsolutePath);
41 | return !Setting.SupportVideoFileExtensions.Any(x => x == fileInfo.Extension.ToLower());
42 | }
43 |
44 | private void LoadImage()
45 | {
46 | try
47 | {
48 | var fileUri = new Uri(Setting.BackgroundImageAbsolutePath, UriKind.RelativeOrAbsolute);
49 | var fileInfo = new FileInfo(Setting.BackgroundImageAbsolutePath);
50 | if (Setting.SupportVideoFileExtensions.Any(x => x == fileInfo.Extension.ToLower())) return;
51 | if (fileInfo.Exists)
52 | {
53 | _bitmapSource = null;
54 | try
55 | {
56 | _bitmap = new BitmapImage();
57 | _bitmap.BeginInit();
58 | _bitmap.CacheOption = BitmapCacheOption.OnLoad;
59 | _bitmap.CreateOptions = BitmapCreateOptions.None;
60 | _bitmap.UriSource = fileUri;
61 | _bitmap.EndInit();
62 | _bitmap.Freeze();
63 | }
64 | catch
65 | {
66 | // maybe not supported exception
67 | _bitmap = new BitmapImage();
68 | _bitmap.Freeze();
69 | }
70 |
71 | if (Setting.ImageStretch == ImageStretch.None)
72 | _bitmap = Utils.EnsureMaxWidthHeight(_bitmap, Setting.MaxWidth, Setting.MaxHeight);
73 |
74 | BitmapSource ret_bitmap = null;
75 | if (Setting.ImageStretch == ImageStretch.None &&
76 | (_bitmap.Width != _bitmap.PixelWidth || _bitmap.Height != _bitmap.PixelHeight)
77 | )
78 | ret_bitmap = Utils.ConvertToDpi96(_bitmap);
79 | else
80 | ret_bitmap = _bitmap;
81 |
82 | if (Setting.SoftEdgeX > 0 || Setting.SoftEdgeY > 0)
83 | ret_bitmap = Utils.SoftenEdges(ret_bitmap ?? _bitmap, Setting.SoftEdgeX, Setting.SoftEdgeY);
84 |
85 | if (ret_bitmap != null)
86 | {
87 | _bitmapSource = ret_bitmap;
88 | _bitmap = null;
89 | }
90 | }
91 | else
92 | {
93 | _bitmap = null;
94 | _bitmapSource = null;
95 | }
96 | }
97 | catch { }
98 | }
99 |
100 | public override string GetCurrentImageUri()
101 | {
102 | return Setting.BackgroundImageAbsolutePath;
103 | }
104 | }
105 | }
--------------------------------------------------------------------------------
/Shared/ImageProviders/WebApiImageProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Linq;
4 | using System.Net.Http;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 | using System.Timers;
8 | using ClaudiaIDE.Helpers;
9 | using ClaudiaIDE.Interfaces;
10 | using ClaudiaIDE.Settings;
11 | using Microsoft.VisualStudio.Threading;
12 | using Newtonsoft.Json.Linq;
13 |
14 | namespace ClaudiaIDE.ImageProviders
15 | {
16 | internal class WebApiImageProvider : ImageProvider, IPausable, ISkipable
17 | {
18 | private static HttpClient _client = new HttpClient();
19 | private PausableTimer _timer;
20 | private string _currentUrl;
21 |
22 | public WebApiImageProvider(Setting setting, string solutionConfigFile = null) : base(setting,
23 | solutionConfigFile, ImageBackgroundType.WebApi)
24 | {
25 | OnSettingChanged(setting, null);
26 | }
27 |
28 | public bool IsPaused => _timer.IsPaused;
29 |
30 | public void Pause()
31 | {
32 | if (!IsPaused) _timer.Pause();
33 | }
34 |
35 | public void Resume()
36 | {
37 | if (IsPaused) _timer.Resume();
38 | }
39 |
40 | public void Skip()
41 | {
42 | _timer.Stop();
43 | ChangeImage();
44 | if (IsPaused)
45 | _timer.Pause();
46 | }
47 |
48 | private void ChangeImage()
49 | {
50 | ChangeImageAsync().Forget();
51 | }
52 |
53 | private async Task ChangeImageAsync()
54 | {
55 | if (Setting.ImageBackgroundType != ImageBackgroundType.WebApi) return;
56 | if (_timer.IsPaused) return;
57 |
58 | try
59 | {
60 | var cts = new CancellationTokenSource();
61 | cts.CancelAfter(Setting.WebApiDownloadInterval);
62 | var request = new HttpRequestMessage(HttpMethod.Get, new Uri(Setting.WebApiEndpoint));
63 | request.Headers.Add("ContentType", "application/json; charset=utf-8");
64 | var httpres = await _client.SendAsync(request, cts.Token);
65 | if (!httpres.IsSuccessStatusCode) return;
66 | var response = await httpres.Content.ReadAsStringAsync();
67 |
68 | var jsonObject = JObject.Parse(response);
69 | var imageUrl = jsonObject.SelectToken(Setting.WebApiJsonKey);
70 | if (imageUrl != null)
71 | {
72 | _currentUrl = imageUrl.ToString();
73 | if (!IsStaticImage())
74 | {
75 | FireImageAvailable();
76 | return;
77 | }
78 | Image = await ImageDownloader.LoadImageAsync(_currentUrl, Setting.ImageStretch, Setting.MaxWidth, Setting.MaxHeight, Setting);
79 | _timer.Restart();
80 | if (Image != null) FireImageAvailable();
81 | return;
82 | }
83 | }
84 | catch { }
85 | }
86 |
87 | protected override void OnSettingChanged(object sender, EventArgs e)
88 | {
89 | if (_timer != null)
90 | {
91 | _timer.Stop();
92 | _timer.Elapsed -= OnTimerElapsed;
93 | _timer.Dispose();
94 | }
95 |
96 | _timer = new PausableTimer(Setting.WebApiDownloadInterval.TotalMilliseconds);
97 | _timer.Elapsed += OnTimerElapsed;
98 |
99 | if ((sender as Setting)?.ImageBackgroundType != ImageBackgroundType.WebApi)
100 | {
101 | _timer.Stop();
102 | return;
103 | }
104 |
105 | ImageDownloader.ResetUrl();
106 | ChangeImage();
107 | }
108 |
109 | private void OnTimerElapsed(object sender, ElapsedEventArgs e)
110 | {
111 | ChangeImage();
112 | }
113 |
114 | public override bool IsStaticImage()
115 | {
116 | if (string.IsNullOrEmpty(_currentUrl)) return true;
117 | var f = new FileInfo(new Uri(_currentUrl).LocalPath);
118 | return !Setting.SupportVideoFileExtensions.Any(x => x == f.Extension.ToLower());
119 | }
120 |
121 | public override string GetCurrentImageUri()
122 | {
123 | return _currentUrl;
124 | }
125 | }
126 | }
--------------------------------------------------------------------------------
/Shared/Helpers/ImageSourceAnimator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows;
3 | using System.Windows.Controls;
4 | using System.Windows.Media;
5 | using System.Windows.Media.Animation;
6 |
7 | namespace ClaudiaIDE.Helpers
8 | {
9 | internal static class ImageSourceAnimator
10 | {
11 | public static void AnimateImageSourceChange(this Brush background, ImageBrush newImage,
12 | Action onChangeImage, AnimateImageChangeParams animateImageChangeParams = null)
13 | {
14 | var animationParameters = animateImageChangeParams ?? new AnimateImageChangeParams();
15 |
16 | if (background != null)
17 | {
18 | var fadeOutAnimation = new DoubleAnimation(0d, animationParameters.FadeTime) { AutoReverse = false };
19 | var fadeInAnimation =
20 | new DoubleAnimation(0d, animationParameters.TargetOpacity, animationParameters.FadeTime)
21 | { AutoReverse = false };
22 |
23 | fadeOutAnimation.Completed += (o, e) =>
24 | {
25 | newImage.Opacity = 0d;
26 | onChangeImage(newImage);
27 | background.Opacity = animationParameters.TargetOpacity;
28 | newImage.BeginAnimation(Brush.OpacityProperty, fadeInAnimation);
29 | };
30 |
31 | background.BeginAnimation(Brush.OpacityProperty, fadeOutAnimation);
32 | }
33 | else
34 | {
35 | newImage.Opacity = animateImageChangeParams.TargetOpacity;
36 | onChangeImage(newImage);
37 | }
38 | }
39 |
40 | public static void AnimateImageSourceChange(this Brush background, VisualBrush newVisual,
41 | Action onChangeVisual, AnimateImageChangeParams animateImageChangeParams = null)
42 | {
43 | var animationParameters = animateImageChangeParams ?? new AnimateImageChangeParams();
44 |
45 | if (background != null)
46 | {
47 | var fadeOutAnimation = new DoubleAnimation(0d, animationParameters.FadeTime) { AutoReverse = false };
48 | var fadeInAnimation =
49 | new DoubleAnimation(0d, animationParameters.TargetOpacity, animationParameters.FadeTime)
50 | { AutoReverse = false };
51 |
52 | fadeOutAnimation.Completed += (o, e) =>
53 | {
54 | newVisual.Opacity = 0d;
55 | onChangeVisual(newVisual);
56 | background.Opacity = animationParameters.TargetOpacity;
57 | newVisual.BeginAnimation(Brush.OpacityProperty, fadeInAnimation);
58 | };
59 |
60 | background.BeginAnimation(Brush.OpacityProperty, fadeOutAnimation);
61 | }
62 | else
63 | {
64 | newVisual.Opacity = animateImageChangeParams.TargetOpacity;
65 | onChangeVisual(newVisual);
66 | }
67 | }
68 |
69 | public static void AnimateImageSourceChange(this Image image,
70 | ImageSource newImage,
71 | Action onChangeImage,
72 | AnimateImageChangeParams animateImageChangeParams = null)
73 | {
74 | var animationParameters = animateImageChangeParams ?? new AnimateImageChangeParams();
75 |
76 | if (image != null)
77 | {
78 | var fadeOutAnimation = new DoubleAnimation(0d, animationParameters.FadeTime) { AutoReverse = false };
79 | var fadeInAnimation =
80 | new DoubleAnimation(0d, animationParameters.TargetOpacity, animationParameters.FadeTime)
81 | { AutoReverse = false };
82 |
83 | fadeOutAnimation.Completed += (o, e) =>
84 | {
85 | onChangeImage(image);
86 | image.Source = newImage;
87 | RenderOptions.SetBitmapScalingMode(image, BitmapScalingMode.Fant);
88 | image.BeginAnimation(UIElement.OpacityProperty, fadeInAnimation);
89 | };
90 | image.BeginAnimation(UIElement.OpacityProperty, fadeOutAnimation);
91 | }
92 | else
93 | {
94 | image.Opacity = animateImageChangeParams.TargetOpacity;
95 | image.Source = newImage;
96 | onChangeImage(image);
97 | }
98 | }
99 | }
100 | }
--------------------------------------------------------------------------------
/Shared/Settings/WeakEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq.Expressions;
4 | using System.Reflection;
5 |
6 | namespace ClaudiaIDE.Settings
7 | {
8 | // https://gist.github.com/wonderful-panda/3b68a9a6040d89df907b
9 |
10 | public class WeakHandler : IEquatable>
11 | where TEventArgs : EventArgs
12 | {
13 | private readonly Action